1 /*
2 ** Copyright 2007, The Android Open Source Project
3 **
4 ** Licensed under the Apache License, Version 2.0 (the "License");
5 ** you may not use this file except in compliance with the License.
6 ** You may obtain a copy of the License at
7 **
8 ** http://www.apache.org/licenses/LICENSE-2.0
9 **
10 ** Unless required by applicable law or agreed to in writing, software
11 ** distributed under the License is distributed on an "AS IS" BASIS,
12 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 ** See the License for the specific language governing permissions and
14 ** limitations under the License.
15 */
16
17 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
18
19 #include "egl_platform_entries.h"
20
21 #include <aidl/android/hardware/graphics/common/PixelFormat.h>
22 #include <android-base/properties.h>
23 #include <android-base/strings.h>
24 #include <android/hardware_buffer.h>
25 #include <ctype.h>
26 #include <cutils/compiler.h>
27 #include <dlfcn.h>
28 #include <graphicsenv/GraphicsEnv.h>
29 #include <log/log.h>
30 #include <private/android/AHardwareBufferHelpers.h>
31 #include <stdlib.h>
32 #include <string.h>
33
34 #include <condition_variable>
35 #include <deque>
36 #include <mutex>
37 #include <string>
38 #include <thread>
39 #include <unordered_map>
40
41 #include "../egl_impl.h"
42 #include "EGL/egl.h"
43 #include "EGL/eglext.h"
44 #include "EGL/eglext_angle.h"
45 #include "egl_display.h"
46 #include "egl_layers.h"
47 #include "egl_object.h"
48 #include "egl_tls.h"
49 #include "egl_trace.h"
50
51 using namespace android;
52 using PixelFormat = aidl::android::hardware::graphics::common::PixelFormat;
53
54 // ----------------------------------------------------------------------------
55
56 namespace android {
57
58 using nsecs_t = int64_t;
59
60 struct extension_map_t {
61 const char* name;
62 __eglMustCastToProperFunctionPointerType address;
63 };
64
65 /*
66 * This is the list of EGL extensions exposed to applications.
67 *
68 * Some of them (gBuiltinExtensionString) are implemented entirely in this EGL
69 * wrapper and are always available.
70 *
71 * The rest (gExtensionString) depend on support in the EGL driver, and are
72 * only available if the driver supports them. However, some of these must be
73 * supported because they are used by the Android system itself; these are
74 * listed as mandatory below and are required by the CDD. The system *assumes*
75 * the mandatory extensions are present and may not function properly if some
76 * are missing.
77 *
78 * NOTE: Both strings MUST have a single space as the last character.
79 */
80
81 extern const char* const gBuiltinExtensionString;
82 extern const char* const gExtensionString;
83
84 // clang-format off
85 // Extensions implemented by the EGL wrapper.
86 const char* const gBuiltinExtensionString =
87 "EGL_ANDROID_front_buffer_auto_refresh "
88 // b/269060366 Conditionally enabled during display initialization:
89 //"EGL_ANDROID_get_frame_timestamps "
90 "EGL_ANDROID_get_native_client_buffer "
91 "EGL_ANDROID_presentation_time "
92 "EGL_EXT_surface_CTA861_3_metadata "
93 "EGL_EXT_surface_SMPTE2086_metadata "
94 "EGL_KHR_get_all_proc_addresses "
95 "EGL_KHR_swap_buffers_with_damage "
96 ;
97
98 // Allowed list of extensions exposed to applications if implemented in the vendor driver.
99 const char* const gExtensionString =
100 "EGL_ANDROID_image_native_buffer " // mandatory
101 "EGL_ANDROID_native_fence_sync " // strongly recommended
102 "EGL_ANDROID_recordable " // mandatory
103 "EGL_EXT_buffer_age " // strongly recommended with partial_update
104 "EGL_EXT_create_context_robustness "
105 "EGL_EXT_image_gl_colorspace "
106 "EGL_EXT_pixel_format_float "
107 "EGL_EXT_protected_content "
108 "EGL_EXT_yuv_surface "
109 "EGL_IMG_context_priority "
110 "EGL_KHR_config_attribs "
111 "EGL_KHR_create_context "
112 "EGL_KHR_create_context_no_error "
113 "EGL_KHR_fence_sync "
114 "EGL_KHR_gl_colorspace "
115 "EGL_KHR_gl_renderbuffer_image "
116 "EGL_KHR_gl_texture_2D_image "
117 "EGL_KHR_gl_texture_3D_image "
118 "EGL_KHR_gl_texture_cubemap_image "
119 "EGL_KHR_image " // mandatory
120 "EGL_KHR_image_base " // mandatory
121 "EGL_KHR_image_pixmap "
122 "EGL_KHR_lock_surface "
123 "EGL_KHR_mutable_render_buffer "
124 "EGL_KHR_no_config_context "
125 "EGL_KHR_partial_update " // strongly recommended
126 "EGL_KHR_reusable_sync "
127 "EGL_KHR_stream "
128 "EGL_KHR_stream_consumer_gltexture "
129 "EGL_KHR_stream_cross_process_fd "
130 "EGL_KHR_stream_fifo "
131 "EGL_KHR_stream_producer_eglsurface "
132 "EGL_KHR_surfaceless_context "
133 "EGL_KHR_wait_sync " // strongly recommended
134 "EGL_NV_context_priority_realtime "
135 "EGL_NV_system_time "
136 ;
137
138 const char* const gClientExtensionString =
139 "EGL_ANDROID_GLES_layers "
140 "EGL_ANGLE_platform_angle "
141 "EGL_EXT_client_extensions "
142 "EGL_KHR_platform_android "
143 ;
144
145 // extensions not exposed to applications but used by the ANDROID system
146 // "EGL_ANDROID_blob_cache " // strongly recommended
147 // "EGL_ANDROID_framebuffer_target " // mandatory for HWC 1.1
148
149 /*
150 * EGL Extensions entry-points exposed to 3rd party applications
151 * (keep in sync with gExtensionString above)
152 *
153 */
154 static const extension_map_t sExtensionMap[] = {
155 // EGL_KHR_lock_surface
156 { "eglLockSurfaceKHR", (__eglMustCastToProperFunctionPointerType)&eglLockSurfaceKHR },
157 { "eglUnlockSurfaceKHR", (__eglMustCastToProperFunctionPointerType)&eglUnlockSurfaceKHR },
158
159 // EGL_KHR_image, EGL_KHR_image_base
160 { "eglCreateImageKHR", (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR },
161 { "eglDestroyImageKHR", (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR },
162
163 // EGL_KHR_reusable_sync, EGL_KHR_fence_sync
164 { "eglCreateSyncKHR", (__eglMustCastToProperFunctionPointerType)&eglCreateSyncKHR },
165 { "eglDestroySyncKHR", (__eglMustCastToProperFunctionPointerType)&eglDestroySyncKHR },
166 { "eglClientWaitSyncKHR", (__eglMustCastToProperFunctionPointerType)&eglClientWaitSyncKHR },
167 { "eglSignalSyncKHR", (__eglMustCastToProperFunctionPointerType)&eglSignalSyncKHR },
168 { "eglGetSyncAttribKHR", (__eglMustCastToProperFunctionPointerType)&eglGetSyncAttribKHR },
169
170 // EGL_NV_system_time
171 { "eglGetSystemTimeFrequencyNV", (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeFrequencyNV },
172 { "eglGetSystemTimeNV", (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeNV },
173
174 // EGL_KHR_wait_sync
175 { "eglWaitSyncKHR", (__eglMustCastToProperFunctionPointerType)&eglWaitSyncKHR },
176
177 // EGL_ANDROID_presentation_time
178 { "eglPresentationTimeANDROID", (__eglMustCastToProperFunctionPointerType)&eglPresentationTimeANDROID },
179
180 // EGL_KHR_swap_buffers_with_damage
181 { "eglSwapBuffersWithDamageKHR", (__eglMustCastToProperFunctionPointerType)&eglSwapBuffersWithDamageKHR },
182
183 // EGL_ANDROID_get_native_client_buffer
184 { "eglGetNativeClientBufferANDROID", (__eglMustCastToProperFunctionPointerType)&eglGetNativeClientBufferANDROID },
185
186 // EGL_KHR_partial_update
187 { "eglSetDamageRegionKHR", (__eglMustCastToProperFunctionPointerType)&eglSetDamageRegionKHR },
188
189 { "eglCreateStreamKHR", (__eglMustCastToProperFunctionPointerType)&eglCreateStreamKHR },
190 { "eglDestroyStreamKHR", (__eglMustCastToProperFunctionPointerType)&eglDestroyStreamKHR },
191 { "eglStreamAttribKHR", (__eglMustCastToProperFunctionPointerType)&eglStreamAttribKHR },
192 { "eglQueryStreamKHR", (__eglMustCastToProperFunctionPointerType)&eglQueryStreamKHR },
193 { "eglQueryStreamu64KHR", (__eglMustCastToProperFunctionPointerType)&eglQueryStreamu64KHR },
194 { "eglQueryStreamTimeKHR", (__eglMustCastToProperFunctionPointerType)&eglQueryStreamTimeKHR },
195 { "eglCreateStreamProducerSurfaceKHR", (__eglMustCastToProperFunctionPointerType)&eglCreateStreamProducerSurfaceKHR },
196 { "eglStreamConsumerGLTextureExternalKHR", (__eglMustCastToProperFunctionPointerType)&eglStreamConsumerGLTextureExternalKHR },
197 { "eglStreamConsumerAcquireKHR", (__eglMustCastToProperFunctionPointerType)&eglStreamConsumerAcquireKHR },
198 { "eglStreamConsumerReleaseKHR", (__eglMustCastToProperFunctionPointerType)&eglStreamConsumerReleaseKHR },
199 { "eglGetStreamFileDescriptorKHR", (__eglMustCastToProperFunctionPointerType)&eglGetStreamFileDescriptorKHR },
200 { "eglCreateStreamFromFileDescriptorKHR", (__eglMustCastToProperFunctionPointerType)&eglCreateStreamFromFileDescriptorKHR },
201
202 // EGL_ANDROID_get_frame_timestamps
203 { "eglGetNextFrameIdANDROID", (__eglMustCastToProperFunctionPointerType)&eglGetNextFrameIdANDROID },
204 { "eglGetCompositorTimingANDROID", (__eglMustCastToProperFunctionPointerType)&eglGetCompositorTimingANDROID },
205 { "eglGetCompositorTimingSupportedANDROID", (__eglMustCastToProperFunctionPointerType)&eglGetCompositorTimingSupportedANDROID },
206 { "eglGetFrameTimestampsANDROID", (__eglMustCastToProperFunctionPointerType)&eglGetFrameTimestampsANDROID },
207 { "eglGetFrameTimestampSupportedANDROID", (__eglMustCastToProperFunctionPointerType)&eglGetFrameTimestampSupportedANDROID },
208
209 // EGL_ANDROID_native_fence_sync
210 { "eglDupNativeFenceFDANDROID", (__eglMustCastToProperFunctionPointerType)&eglDupNativeFenceFDANDROID },
211 };
212 // clang-format on
213
214 /*
215 * These extensions entry-points should not be exposed to applications.
216 * They're used internally by the Android EGL layer.
217 */
218 #define FILTER_EXTENSIONS(procname) (!strcmp((procname), "eglSetBlobCacheFuncsANDROID"))
219
220 // accesses protected by sExtensionMapMutex
221 static std::unordered_map<std::string, __eglMustCastToProperFunctionPointerType> sGLExtensionMap;
222 static std::unordered_map<std::string, int> sGLExtensionSlotMap;
223
224 static int sGLExtensionSlot = 0;
225 static pthread_mutex_t sExtensionMapMutex = PTHREAD_MUTEX_INITIALIZER;
226
findProcAddress(const char * name,const extension_map_t * map,size_t n)227 static void (*findProcAddress(const char* name, const extension_map_t* map, size_t n))() {
228 for (uint32_t i = 0; i < n; i++) {
229 if (!strcmp(name, map[i].name)) {
230 return map[i].address;
231 }
232 }
233 return nullptr;
234 }
235
236 // ----------------------------------------------------------------------------
237
238 extern void setGLHooksThreadSpecific(gl_hooks_t const* value);
239 extern EGLBoolean egl_init_drivers();
240 extern const __eglMustCastToProperFunctionPointerType
241 gExtensionForwarders[MAX_NUMBER_OF_GL_EXTENSIONS];
242 extern gl_hooks_t gHooksTrace;
243
244 // ----------------------------------------------------------------------------
245
getContext()246 static inline EGLContext getContext() {
247 return egl_tls_t::getContext();
248 }
249
250 // ----------------------------------------------------------------------------
251
eglGetPlatformDisplayTmpl(EGLenum platform,EGLNativeDisplayType display,const EGLAttrib * attrib_list)252 static EGLDisplay eglGetPlatformDisplayTmpl(EGLenum platform, EGLNativeDisplayType display,
253 const EGLAttrib* attrib_list) {
254 if (platform != EGL_PLATFORM_ANDROID_KHR) {
255 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
256 }
257
258 uintptr_t index = reinterpret_cast<uintptr_t>(display);
259 if (index >= NUM_DISPLAYS) {
260 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
261 }
262
263 EGLDisplay dpy = egl_display_t::getFromNativeDisplay(display, attrib_list);
264 return dpy;
265 }
266
eglGetDisplayImpl(EGLNativeDisplayType display)267 EGLDisplay eglGetDisplayImpl(EGLNativeDisplayType display) {
268 return eglGetPlatformDisplayTmpl(EGL_PLATFORM_ANDROID_KHR, display, nullptr);
269 }
270
eglGetPlatformDisplayImpl(EGLenum platform,void * native_display,const EGLAttrib * attrib_list)271 EGLDisplay eglGetPlatformDisplayImpl(EGLenum platform, void* native_display,
272 const EGLAttrib* attrib_list) {
273 return eglGetPlatformDisplayTmpl(platform, static_cast<EGLNativeDisplayType>(native_display),
274 attrib_list);
275 }
276
277 // ----------------------------------------------------------------------------
278 // Initialization
279 // ----------------------------------------------------------------------------
280
eglInitializeImpl(EGLDisplay dpy,EGLint * major,EGLint * minor)281 EGLBoolean eglInitializeImpl(EGLDisplay dpy, EGLint* major, EGLint* minor) {
282 egl_display_t* dp = get_display(dpy);
283 if (!dp) return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
284
285 EGLBoolean res = dp->initialize(major, minor);
286
287 return res;
288 }
289
eglTerminateImpl(EGLDisplay dpy)290 EGLBoolean eglTerminateImpl(EGLDisplay dpy) {
291 // NOTE: don't unload the drivers b/c some APIs can be called
292 // after eglTerminate() has been called. eglTerminate() only
293 // terminates an EGLDisplay, not a EGL itself.
294
295 egl_display_t* dp = get_display(dpy);
296 if (!dp) return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
297
298 EGLBoolean res = dp->terminate();
299
300 return res;
301 }
302
303 // ----------------------------------------------------------------------------
304 // configuration
305 // ----------------------------------------------------------------------------
306
eglGetConfigsImpl(EGLDisplay dpy,EGLConfig * configs,EGLint config_size,EGLint * num_config)307 EGLBoolean eglGetConfigsImpl(EGLDisplay dpy, EGLConfig* configs, EGLint config_size,
308 EGLint* num_config) {
309 const egl_display_t* dp = validate_display(dpy);
310 if (!dp) return EGL_FALSE;
311
312 if (num_config == nullptr) {
313 return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE);
314 }
315
316 EGLBoolean res = EGL_FALSE;
317 *num_config = 0;
318
319 egl_connection_t* const cnx = &gEGLImpl;
320 if (cnx->dso) {
321 res = cnx->egl.eglGetConfigs(dp->disp.dpy, configs, config_size, num_config);
322 }
323
324 return res;
325 }
326
eglChooseConfigImpl(EGLDisplay dpy,const EGLint * attrib_list,EGLConfig * configs,EGLint config_size,EGLint * num_config)327 EGLBoolean eglChooseConfigImpl(EGLDisplay dpy, const EGLint* attrib_list, EGLConfig* configs,
328 EGLint config_size, EGLint* num_config) {
329 const egl_display_t* dp = validate_display(dpy);
330 if (!dp) return EGL_FALSE;
331
332 if (num_config == nullptr) {
333 return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE);
334 }
335
336 *num_config = 0;
337
338 egl_connection_t* const cnx = &gEGLImpl;
339 if (!cnx->dso) return EGL_FALSE;
340
341 if (!attrib_list || !base::GetBoolProperty("debug.egl.force_msaa", false))
342 return cnx->egl.eglChooseConfig(dp->disp.dpy, attrib_list, configs, config_size,
343 num_config);
344
345 // Force 4x MSAA
346 size_t attribCount = 0;
347 EGLint attrib = attrib_list[0];
348
349 // Only enable MSAA if the context is OpenGL ES 2.0 and
350 // if no caveat is requested
351 const EGLint* attribRendererable = nullptr;
352 const EGLint* attribCaveat = nullptr;
353
354 // Count the number of attributes and look for
355 // EGL_RENDERABLE_TYPE and EGL_CONFIG_CAVEAT
356 while (attrib != EGL_NONE) {
357 attrib = attrib_list[attribCount];
358 switch (attrib) {
359 case EGL_RENDERABLE_TYPE:
360 attribRendererable = &attrib_list[attribCount];
361 break;
362 case EGL_CONFIG_CAVEAT:
363 attribCaveat = &attrib_list[attribCount];
364 break;
365 default:
366 break;
367 }
368 attribCount++;
369 }
370
371 if (attribRendererable && attribRendererable[1] == EGL_OPENGL_ES2_BIT &&
372 (!attribCaveat || attribCaveat[1] != EGL_NONE)) {
373 // Insert 2 extra attributes to force-enable MSAA 4x
374 EGLint aaAttribs[attribCount + 4];
375 aaAttribs[0] = EGL_SAMPLE_BUFFERS;
376 aaAttribs[1] = 1;
377 aaAttribs[2] = EGL_SAMPLES;
378 aaAttribs[3] = 4;
379
380 memcpy(&aaAttribs[4], attrib_list, attribCount * sizeof(EGLint));
381
382 EGLint numConfigAA;
383 EGLBoolean resAA = cnx->egl.eglChooseConfig(dp->disp.dpy, aaAttribs, configs, config_size,
384 &numConfigAA);
385
386 if (resAA == EGL_TRUE && numConfigAA > 0) {
387 ALOGD("Enabling MSAA 4x");
388 *num_config = numConfigAA;
389 return resAA;
390 }
391 }
392
393 return cnx->egl.eglChooseConfig(dp->disp.dpy, attrib_list, configs, config_size, num_config);
394 }
395
eglGetConfigAttribImpl(EGLDisplay dpy,EGLConfig config,EGLint attribute,EGLint * value)396 EGLBoolean eglGetConfigAttribImpl(EGLDisplay dpy, EGLConfig config, EGLint attribute,
397 EGLint* value) {
398 egl_connection_t* cnx = nullptr;
399 const egl_display_t* dp = validate_display_connection(dpy, &cnx);
400 if (!dp) return EGL_FALSE;
401
402 return cnx->egl.eglGetConfigAttrib(dp->disp.dpy, config, attribute, value);
403 }
404
405 // ----------------------------------------------------------------------------
406 // surfaces
407 // ----------------------------------------------------------------------------
408
409 // Translates EGL color spaces to Android data spaces.
dataSpaceFromEGLColorSpace(EGLint colorspace,PixelFormat pixelFormat)410 static android_dataspace dataSpaceFromEGLColorSpace(EGLint colorspace, PixelFormat pixelFormat) {
411 if (colorspace == EGL_GL_COLORSPACE_LINEAR_KHR) {
412 return HAL_DATASPACE_UNKNOWN;
413 } else if (colorspace == EGL_GL_COLORSPACE_SRGB_KHR) {
414 return HAL_DATASPACE_V0_SRGB;
415 } else if (colorspace == EGL_GL_COLORSPACE_DISPLAY_P3_EXT) {
416 return HAL_DATASPACE_DISPLAY_P3;
417 } else if (colorspace == EGL_GL_COLORSPACE_DISPLAY_P3_LINEAR_EXT) {
418 return HAL_DATASPACE_DISPLAY_P3_LINEAR;
419 } else if (colorspace == EGL_GL_COLORSPACE_DISPLAY_P3_PASSTHROUGH_EXT) {
420 return HAL_DATASPACE_DISPLAY_P3;
421 } else if (colorspace == EGL_GL_COLORSPACE_SCRGB_EXT) {
422 return HAL_DATASPACE_V0_SCRGB;
423 } else if (colorspace == EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT) {
424 return HAL_DATASPACE_V0_SCRGB_LINEAR;
425 } else if (colorspace == EGL_GL_COLORSPACE_BT2020_HLG_EXT) {
426 return static_cast<android_dataspace>(HAL_DATASPACE_BT2020_HLG);
427 } else if (colorspace == EGL_GL_COLORSPACE_BT2020_LINEAR_EXT) {
428 if (pixelFormat == PixelFormat::RGBA_FP16) {
429 return static_cast<android_dataspace>(HAL_DATASPACE_STANDARD_BT2020 |
430 HAL_DATASPACE_TRANSFER_LINEAR |
431 HAL_DATASPACE_RANGE_EXTENDED);
432 } else {
433 return HAL_DATASPACE_BT2020_LINEAR;
434 }
435 } else if (colorspace == EGL_GL_COLORSPACE_BT2020_PQ_EXT) {
436 return HAL_DATASPACE_BT2020_PQ;
437 }
438
439 return HAL_DATASPACE_UNKNOWN;
440 }
441
442 // Get the colorspace value that should be reported from queries. When the colorspace
443 // is unknown (no attribute passed), default to reporting LINEAR.
getReportedColorSpace(EGLint colorspace)444 static EGLint getReportedColorSpace(EGLint colorspace) {
445 return colorspace == EGL_UNKNOWN ? EGL_GL_COLORSPACE_LINEAR_KHR : colorspace;
446 }
447
448 // Returns a list of color spaces understood by the vendor EGL driver.
getDriverColorSpaces(egl_display_t * dp)449 static std::vector<EGLint> getDriverColorSpaces(egl_display_t* dp) {
450 std::vector<EGLint> colorSpaces;
451
452 // sRGB and linear are always supported when color space support is present.
453 colorSpaces.push_back(EGL_GL_COLORSPACE_SRGB_KHR);
454 colorSpaces.push_back(EGL_GL_COLORSPACE_LINEAR_KHR);
455
456 if (findExtension(dp->disp.queryString.extensions, "EGL_EXT_gl_colorspace_display_p3")) {
457 colorSpaces.push_back(EGL_GL_COLORSPACE_DISPLAY_P3_EXT);
458 }
459 if (findExtension(dp->disp.queryString.extensions, "EGL_EXT_gl_colorspace_scrgb")) {
460 colorSpaces.push_back(EGL_GL_COLORSPACE_SCRGB_EXT);
461 }
462 if (findExtension(dp->disp.queryString.extensions, "EGL_EXT_gl_colorspace_scrgb_linear")) {
463 colorSpaces.push_back(EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT);
464 }
465 if (findExtension(dp->disp.queryString.extensions, "EGL_EXT_gl_colorspace_bt2020_hlg")) {
466 colorSpaces.push_back(EGL_GL_COLORSPACE_BT2020_HLG_EXT);
467 }
468 if (findExtension(dp->disp.queryString.extensions, "EGL_EXT_gl_colorspace_bt2020_linear")) {
469 colorSpaces.push_back(EGL_GL_COLORSPACE_BT2020_LINEAR_EXT);
470 }
471 if (findExtension(dp->disp.queryString.extensions, "EGL_EXT_gl_colorspace_bt2020_pq")) {
472 colorSpaces.push_back(EGL_GL_COLORSPACE_BT2020_PQ_EXT);
473 }
474 if (findExtension(dp->disp.queryString.extensions, "EGL_EXT_gl_colorspace_display_p3_linear")) {
475 colorSpaces.push_back(EGL_GL_COLORSPACE_DISPLAY_P3_LINEAR_EXT);
476 }
477 if (findExtension(dp->disp.queryString.extensions,
478 "EGL_EXT_gl_colorspace_display_p3_passthrough")) {
479 colorSpaces.push_back(EGL_GL_COLORSPACE_DISPLAY_P3_PASSTHROUGH_EXT);
480 }
481 return colorSpaces;
482 }
483
484 // Cleans up color space related parameters that the driver does not understand.
485 // If there is no color space attribute in attrib_list, colorSpace is left
486 // unmodified.
487 template <typename AttrType>
processAttributes(egl_display_t * dp,ANativeWindow * window,const AttrType * attrib_list,EGLint * colorSpace,std::vector<AttrType> * strippedAttribList)488 static EGLBoolean processAttributes(egl_display_t* dp, ANativeWindow* window,
489 const AttrType* attrib_list, EGLint* colorSpace,
490 std::vector<AttrType>* strippedAttribList) {
491 for (const AttrType* attr = attrib_list; attr && attr[0] != EGL_NONE; attr += 2) {
492 bool copyAttribute = true;
493 if (attr[0] == EGL_GL_COLORSPACE_KHR) {
494 switch (attr[1]) {
495 case EGL_GL_COLORSPACE_LINEAR_KHR:
496 case EGL_GL_COLORSPACE_SRGB_KHR:
497 case EGL_GL_COLORSPACE_DISPLAY_P3_EXT:
498 case EGL_GL_COLORSPACE_DISPLAY_P3_PASSTHROUGH_EXT:
499 case EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT:
500 case EGL_GL_COLORSPACE_SCRGB_EXT:
501 case EGL_GL_COLORSPACE_BT2020_HLG_EXT:
502 case EGL_GL_COLORSPACE_BT2020_LINEAR_EXT:
503 case EGL_GL_COLORSPACE_BT2020_PQ_EXT:
504 case EGL_GL_COLORSPACE_DISPLAY_P3_LINEAR_EXT:
505 // Fail immediately if the driver doesn't have color space support at all.
506 if (!dp->hasColorSpaceSupport) return setError(EGL_BAD_ATTRIBUTE, EGL_FALSE);
507 break;
508 default:
509 // BAD_ATTRIBUTE if attr is not any of the EGL_GL_COLORSPACE_*
510 return setError(EGL_BAD_ATTRIBUTE, EGL_FALSE);
511 }
512 *colorSpace = static_cast<EGLint>(attr[1]);
513
514 // Strip the attribute if the driver doesn't understand it.
515 copyAttribute = false;
516 std::vector<EGLint> driverColorSpaces = getDriverColorSpaces(dp);
517 for (auto driverColorSpace : driverColorSpaces) {
518 if (static_cast<EGLint>(attr[1]) == driverColorSpace) {
519 copyAttribute = true;
520 break;
521 }
522 }
523
524 // If the driver doesn't understand it, we should map sRGB-encoded P3 to
525 // sRGB rather than just dropping the colorspace on the floor.
526 // For this format, the driver is expected to apply the sRGB
527 // transfer function during framebuffer operations.
528 if (!copyAttribute && attr[1] == EGL_GL_COLORSPACE_DISPLAY_P3_EXT) {
529 strippedAttribList->push_back(attr[0]);
530 strippedAttribList->push_back(EGL_GL_COLORSPACE_SRGB_KHR);
531 }
532 }
533 if (copyAttribute) {
534 strippedAttribList->push_back(attr[0]);
535 strippedAttribList->push_back(attr[1]);
536 }
537 }
538 // Terminate the attribute list.
539 strippedAttribList->push_back(EGL_NONE);
540
541 // If the passed color space has wide color gamut, check whether the target native window
542 // supports wide color.
543 const bool colorSpaceIsNarrow = *colorSpace == EGL_GL_COLORSPACE_SRGB_KHR ||
544 *colorSpace == EGL_GL_COLORSPACE_LINEAR_KHR || *colorSpace == EGL_UNKNOWN;
545 if (window && !colorSpaceIsNarrow) {
546 bool windowSupportsWideColor = true;
547 // Ordinarily we'd put a call to native_window_get_wide_color_support
548 // at the beginning of the function so that we'll have the
549 // result when needed elsewhere in the function.
550 // However, because eglCreateWindowSurface is called by SurfaceFlinger and
551 // SurfaceFlinger is required to answer the call below we would
552 // end up in a deadlock situation. By moving the call to only happen
553 // if the application has specifically asked for wide-color we avoid
554 // the deadlock with SurfaceFlinger since it will not ask for a
555 // wide-color surface.
556 int err = native_window_get_wide_color_support(window, &windowSupportsWideColor);
557
558 if (err) {
559 ALOGE("processAttributes: invalid window (win=%p) "
560 "failed (%#x) (already connected to another API?)",
561 window, err);
562 return setError(EGL_BAD_NATIVE_WINDOW, EGL_FALSE);
563 }
564 if (!windowSupportsWideColor) {
565 // Application has asked for a wide-color colorspace but
566 // wide-color support isn't available on the display the window is on.
567 return setError(EGL_BAD_MATCH, EGL_FALSE);
568 }
569 }
570 return true;
571 }
572
573 // Note: This only works for existing GLenum's that are all 32bits.
574 // If you have 64bit attributes (e.g. pointers) you shouldn't be calling this.
convertAttribs(const EGLAttrib * attribList,std::vector<EGLint> & newList)575 void convertAttribs(const EGLAttrib* attribList, std::vector<EGLint>& newList) {
576 for (const EGLAttrib* attr = attribList; attr && attr[0] != EGL_NONE; attr += 2) {
577 newList.push_back(static_cast<EGLint>(attr[0]));
578 newList.push_back(static_cast<EGLint>(attr[1]));
579 }
580 newList.push_back(EGL_NONE);
581 }
582
583 // Gets the native pixel format corrsponding to the passed EGLConfig.
getNativePixelFormat(EGLDisplay dpy,egl_connection_t * cnx,EGLConfig config,PixelFormat * format)584 void getNativePixelFormat(EGLDisplay dpy, egl_connection_t* cnx, EGLConfig config,
585 PixelFormat* format) {
586 // Set the native window's buffers format to match what this config requests.
587 // Whether to use sRGB gamma is not part of the EGLconfig, but is part
588 // of our native format. So if sRGB gamma is requested, we have to
589 // modify the EGLconfig's format before setting the native window's
590 // format.
591
592 EGLint componentType = EGL_COLOR_COMPONENT_TYPE_FIXED_EXT;
593 cnx->egl.eglGetConfigAttrib(dpy, config, EGL_COLOR_COMPONENT_TYPE_EXT, &componentType);
594
595 EGLint a = 0;
596 EGLint r, g, b;
597 r = g = b = 0;
598 cnx->egl.eglGetConfigAttrib(dpy, config, EGL_RED_SIZE, &r);
599 cnx->egl.eglGetConfigAttrib(dpy, config, EGL_GREEN_SIZE, &g);
600 cnx->egl.eglGetConfigAttrib(dpy, config, EGL_BLUE_SIZE, &b);
601 cnx->egl.eglGetConfigAttrib(dpy, config, EGL_ALPHA_SIZE, &a);
602 EGLint colorDepth = r + g + b;
603
604 // Today, the driver only understands sRGB and linear on 888X
605 // formats. Strip other colorspaces from the attribute list and
606 // only use them to set the dataspace via
607 // native_window_set_buffers_dataspace
608 // if pixel format is RGBX 8888
609 // TBD: Can test for future extensions that indicate that driver
610 // handles requested color space and we can let it through.
611 // allow SRGB and LINEAR. All others need to be stripped.
612 // else if 565, 4444
613 // TBD: Can we assume these are supported if 8888 is?
614 // else if FP16 or 1010102
615 // strip colorspace from attribs.
616 // endif
617 if (a == 0) {
618 if (8 == r && 0 == g && 0 == b) {
619 *format = PixelFormat::R_8;
620 } else if (colorDepth <= 16) {
621 *format = PixelFormat::RGB_565;
622 } else {
623 if (componentType == EGL_COLOR_COMPONENT_TYPE_FIXED_EXT) {
624 if (colorDepth > 24) {
625 *format = PixelFormat::RGBA_1010102;
626 } else {
627 *format = PixelFormat::RGBX_8888;
628 }
629 } else {
630 *format = PixelFormat::RGBA_FP16;
631 }
632 }
633 } else {
634 if (componentType == EGL_COLOR_COMPONENT_TYPE_FIXED_EXT) {
635 if (colorDepth > 24) {
636 *format = PixelFormat::RGBA_1010102;
637 } else {
638 *format = PixelFormat::RGBA_8888;
639 }
640 } else {
641 *format = PixelFormat::RGBA_FP16;
642 }
643 }
644 }
645
sendSurfaceMetadata(egl_surface_t * s)646 EGLBoolean sendSurfaceMetadata(egl_surface_t* s) {
647 android_smpte2086_metadata smpteMetadata;
648 if (s->getSmpte2086Metadata(smpteMetadata)) {
649 int err =
650 native_window_set_buffers_smpte2086_metadata(s->getNativeWindow(), &smpteMetadata);
651 s->resetSmpte2086Metadata();
652 if (err != 0) {
653 ALOGE("error setting native window smpte2086 metadata: %s (%d)", strerror(-err), err);
654 return EGL_FALSE;
655 }
656 }
657 android_cta861_3_metadata cta8613Metadata;
658 if (s->getCta8613Metadata(cta8613Metadata)) {
659 int err =
660 native_window_set_buffers_cta861_3_metadata(s->getNativeWindow(), &cta8613Metadata);
661 s->resetCta8613Metadata();
662 if (err != 0) {
663 ALOGE("error setting native window CTS 861.3 metadata: %s (%d)", strerror(-err), err);
664 return EGL_FALSE;
665 }
666 }
667 return EGL_TRUE;
668 }
669
670 template <typename AttrType, typename CreateFuncType>
eglCreateWindowSurfaceTmpl(egl_display_t * dp,egl_connection_t * cnx,EGLConfig config,ANativeWindow * window,const AttrType * attrib_list,CreateFuncType createWindowSurfaceFunc)671 EGLSurface eglCreateWindowSurfaceTmpl(egl_display_t* dp, egl_connection_t* cnx, EGLConfig config,
672 ANativeWindow* window, const AttrType* attrib_list,
673 CreateFuncType createWindowSurfaceFunc) {
674 const AttrType* origAttribList = attrib_list;
675
676 if (!window) {
677 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
678 }
679
680 int value = 0;
681 window->query(window, NATIVE_WINDOW_IS_VALID, &value);
682 if (!value) {
683 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
684 }
685
686 // NOTE: When using Vulkan backend, the Vulkan runtime makes all the
687 // native_window_* calls, so don't do them here.
688 if (!cnx->angleLoaded) {
689 int result = native_window_api_connect(window, NATIVE_WINDOW_API_EGL);
690 if (result < 0) {
691 ALOGE("eglCreateWindowSurface: native_window_api_connect (win=%p) "
692 "failed (%#x) (already connected to another API?)",
693 window, result);
694 return setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
695 }
696 }
697
698 EGLDisplay iDpy = dp->disp.dpy;
699 PixelFormat format;
700 getNativePixelFormat(iDpy, cnx, config, &format);
701
702 // now select correct colorspace and dataspace based on user's attribute list
703 EGLint colorSpace = EGL_UNKNOWN;
704 std::vector<AttrType> strippedAttribList;
705 if (!processAttributes<AttrType>(dp, window, attrib_list, &colorSpace, &strippedAttribList)) {
706 ALOGE("error invalid colorspace: %d", colorSpace);
707 if (!cnx->angleLoaded) {
708 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
709 }
710 return EGL_NO_SURFACE;
711 }
712 attrib_list = strippedAttribList.data();
713
714 if (!cnx->angleLoaded) {
715 int err = native_window_set_buffers_format(window, static_cast<int>(format));
716 if (err != 0) {
717 ALOGE("error setting native window pixel format: %s (%d)", strerror(-err), err);
718 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
719 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
720 }
721
722 android_dataspace dataSpace = dataSpaceFromEGLColorSpace(colorSpace, format);
723 // Set dataSpace even if it could be HAL_DATASPACE_UNKNOWN.
724 // HAL_DATASPACE_UNKNOWN is the default value, but it may have changed
725 // at this point.
726 err = native_window_set_buffers_data_space(window, dataSpace);
727 if (err != 0) {
728 ALOGE("error setting native window pixel dataSpace: %s (%d)", strerror(-err), err);
729 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
730 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
731 }
732 }
733
734 // the EGL spec requires that a new EGLSurface default to swap interval
735 // 1, so explicitly set that on the window here.
736 window->setSwapInterval(window, 1);
737
738 EGLSurface surface = createWindowSurfaceFunc(iDpy, config, window, attrib_list);
739 if (surface != EGL_NO_SURFACE) {
740 egl_surface_t* s = new egl_surface_t(dp, config, window, surface,
741 getReportedColorSpace(colorSpace), cnx);
742 return s;
743 }
744
745 // EGLSurface creation failed
746 if (!cnx->angleLoaded) {
747 native_window_set_buffers_format(window, 0);
748 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
749 }
750 return EGL_NO_SURFACE;
751 }
752
753 typedef EGLSurface(EGLAPIENTRYP PFNEGLCREATEWINDOWSURFACEPROC)(EGLDisplay dpy, EGLConfig config,
754 NativeWindowType window,
755 const EGLint* attrib_list);
756 typedef EGLSurface(EGLAPIENTRYP PFNEGLCREATEPLATFORMWINDOWSURFACEPROC)(
757 EGLDisplay dpy, EGLConfig config, void* native_window, const EGLAttrib* attrib_list);
758
eglCreateWindowSurfaceImpl(EGLDisplay dpy,EGLConfig config,NativeWindowType window,const EGLint * attrib_list)759 EGLSurface eglCreateWindowSurfaceImpl(EGLDisplay dpy, EGLConfig config, NativeWindowType window,
760 const EGLint* attrib_list) {
761 egl_connection_t* cnx = nullptr;
762 egl_display_t* dp = validate_display_connection(dpy, &cnx);
763 if (dp) {
764 return eglCreateWindowSurfaceTmpl<
765 EGLint, PFNEGLCREATEWINDOWSURFACEPROC>(dp, cnx, config, window, attrib_list,
766 cnx->egl.eglCreateWindowSurface);
767 }
768 return EGL_NO_SURFACE;
769 }
770
eglCreatePlatformWindowSurfaceImpl(EGLDisplay dpy,EGLConfig config,void * native_window,const EGLAttrib * attrib_list)771 EGLSurface eglCreatePlatformWindowSurfaceImpl(EGLDisplay dpy, EGLConfig config, void* native_window,
772 const EGLAttrib* attrib_list) {
773 egl_connection_t* cnx = nullptr;
774 egl_display_t* dp = validate_display_connection(dpy, &cnx);
775 if (dp) {
776 if (cnx->driverVersion >= EGL_MAKE_VERSION(1, 5, 0)) {
777 if (cnx->egl.eglCreatePlatformWindowSurface) {
778 return eglCreateWindowSurfaceTmpl<EGLAttrib, PFNEGLCREATEPLATFORMWINDOWSURFACEPROC>(
779 dp, cnx, config, static_cast<ANativeWindow*>(native_window), attrib_list,
780 cnx->egl.eglCreatePlatformWindowSurface);
781 }
782 // driver doesn't support native function, return EGL_BAD_DISPLAY
783 ALOGE("Driver indicates EGL 1.5 support, but does not have "
784 "eglCreatePlatformWindowSurface");
785 return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE);
786 }
787
788 std::vector<EGLint> convertedAttribs;
789 convertAttribs(attrib_list, convertedAttribs);
790 if (cnx->egl.eglCreatePlatformWindowSurfaceEXT) {
791 return eglCreateWindowSurfaceTmpl<EGLint, PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC>(
792 dp, cnx, config, static_cast<ANativeWindow*>(native_window),
793 convertedAttribs.data(), cnx->egl.eglCreatePlatformWindowSurfaceEXT);
794 } else {
795 return eglCreateWindowSurfaceTmpl<
796 EGLint, PFNEGLCREATEWINDOWSURFACEPROC>(dp, cnx, config,
797 static_cast<ANativeWindow*>(
798 native_window),
799 convertedAttribs.data(),
800 cnx->egl.eglCreateWindowSurface);
801 }
802 }
803 return EGL_NO_SURFACE;
804 }
805
eglCreatePlatformPixmapSurfaceImpl(EGLDisplay dpy,EGLConfig,void *,const EGLAttrib *)806 EGLSurface eglCreatePlatformPixmapSurfaceImpl(EGLDisplay dpy, EGLConfig /*config*/,
807 void* /*native_pixmap*/,
808 const EGLAttrib* /*attrib_list*/) {
809 // Per EGL_KHR_platform_android:
810 // It is not valid to call eglCreatePlatformPixmapSurface with a <dpy> that
811 // belongs to the Android platform. Any such call fails and generates
812 // an EGL_BAD_PARAMETER error.
813
814 egl_connection_t* cnx = nullptr;
815 const egl_display_t* dp = validate_display_connection(dpy, &cnx);
816 if (dp) {
817 return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
818 }
819 return EGL_NO_SURFACE;
820 }
821
eglCreatePixmapSurfaceImpl(EGLDisplay dpy,EGLConfig,NativePixmapType,const EGLint *)822 EGLSurface eglCreatePixmapSurfaceImpl(EGLDisplay dpy, EGLConfig /*config*/,
823 NativePixmapType /*pixmap*/, const EGLint* /*attrib_list*/) {
824 egl_connection_t* cnx = nullptr;
825 const egl_display_t* dp = validate_display_connection(dpy, &cnx);
826 if (dp) {
827 return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
828 }
829 return EGL_NO_SURFACE;
830 }
831
eglCreatePbufferSurfaceImpl(EGLDisplay dpy,EGLConfig config,const EGLint * attrib_list)832 EGLSurface eglCreatePbufferSurfaceImpl(EGLDisplay dpy, EGLConfig config,
833 const EGLint* attrib_list) {
834 egl_connection_t* cnx = nullptr;
835 egl_display_t* dp = validate_display_connection(dpy, &cnx);
836 if (!dp) return EGL_NO_SURFACE;
837
838 EGLDisplay iDpy = dp->disp.dpy;
839 PixelFormat format;
840 getNativePixelFormat(iDpy, cnx, config, &format);
841
842 // Select correct colorspace based on user's attribute list
843 EGLint colorSpace = EGL_UNKNOWN;
844 std::vector<EGLint> strippedAttribList;
845 if (!processAttributes(dp, nullptr, attrib_list, &colorSpace, &strippedAttribList)) {
846 ALOGE("error invalid colorspace: %d", colorSpace);
847 return EGL_NO_SURFACE;
848 }
849 attrib_list = strippedAttribList.data();
850
851 EGLSurface surface = cnx->egl.eglCreatePbufferSurface(iDpy, config, attrib_list);
852 if (surface == EGL_NO_SURFACE) return surface;
853
854 return new egl_surface_t(dp, config, nullptr, surface, getReportedColorSpace(colorSpace), cnx);
855 }
856
eglDestroySurfaceImpl(EGLDisplay dpy,EGLSurface surface)857 EGLBoolean eglDestroySurfaceImpl(EGLDisplay dpy, EGLSurface surface) {
858 const egl_display_t* dp = validate_display(dpy);
859 if (!dp) return EGL_FALSE;
860
861 SurfaceRef _s(dp, surface);
862 if (!_s.get()) return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
863
864 egl_surface_t* const s = get_surface(surface);
865 EGLBoolean result = s->cnx->egl.eglDestroySurface(dp->disp.dpy, s->surface);
866 if (result == EGL_TRUE) {
867 _s.terminate();
868 }
869 return result;
870 }
871
eglQuerySurfaceImpl(EGLDisplay dpy,EGLSurface surface,EGLint attribute,EGLint * value)872 EGLBoolean eglQuerySurfaceImpl(EGLDisplay dpy, EGLSurface surface, EGLint attribute,
873 EGLint* value) {
874 const egl_display_t* dp = validate_display(dpy);
875 if (!dp) return EGL_FALSE;
876
877 SurfaceRef _s(dp, surface);
878 if (!_s.get()) return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
879
880 egl_surface_t const* const s = get_surface(surface);
881 if (s->getColorSpaceAttribute(attribute, value)) {
882 return EGL_TRUE;
883 } else if (s->getSmpte2086Attribute(attribute, value)) {
884 return EGL_TRUE;
885 } else if (s->getCta8613Attribute(attribute, value)) {
886 return EGL_TRUE;
887 }
888 return s->cnx->egl.eglQuerySurface(dp->disp.dpy, s->surface, attribute, value);
889 }
890
eglBeginFrameImpl(EGLDisplay dpy,EGLSurface surface)891 void EGLAPI eglBeginFrameImpl(EGLDisplay dpy, EGLSurface surface) {
892 const egl_display_t* dp = validate_display(dpy);
893 if (!dp) {
894 return;
895 }
896
897 SurfaceRef _s(dp, surface);
898 if (!_s.get()) {
899 setError(EGL_BAD_SURFACE, EGL_FALSE);
900 }
901 }
902
903 // ----------------------------------------------------------------------------
904 // Contexts
905 // ----------------------------------------------------------------------------
906
eglCreateContextImpl(EGLDisplay dpy,EGLConfig config,EGLContext share_list,const EGLint * attrib_list)907 EGLContext eglCreateContextImpl(EGLDisplay dpy, EGLConfig config, EGLContext share_list,
908 const EGLint* attrib_list) {
909 egl_connection_t* cnx = nullptr;
910 const egl_display_t* dp = validate_display_connection(dpy, &cnx);
911 if (dp) {
912 if (share_list != EGL_NO_CONTEXT) {
913 if (!ContextRef(dp, share_list).get()) {
914 return setError(EGL_BAD_CONTEXT, EGL_NO_CONTEXT);
915 }
916 egl_context_t* const c = get_context(share_list);
917 share_list = c->context;
918 }
919
920 bool skip_telemetry = false;
921
922 auto findAttribute = [](const EGLint* attrib_ptr, GLint attribute, GLint* value) {
923 while (attrib_ptr && *attrib_ptr != EGL_NONE) {
924 GLint attr = *attrib_ptr++;
925 GLint val = *attrib_ptr++;
926 if (attr == attribute) {
927 if (value) {
928 *value = val;
929 }
930 return true;
931 }
932 }
933 return false;
934 };
935
936 std::vector<EGLint> replacement_attrib_list;
937 GLint telemetry_value;
938 if (findAttribute(attrib_list, EGL_TELEMETRY_HINT_ANDROID, &telemetry_value)) {
939 skip_telemetry = (telemetry_value == android::GpuStatsInfo::SKIP_TELEMETRY);
940
941 // We need to remove EGL_TELEMETRY_HINT_ANDROID or the underlying drivers will
942 // complain about an unexpected attribute
943 const EGLint* attrib_ptr = attrib_list;
944 while (attrib_ptr && *attrib_ptr != EGL_NONE) {
945 GLint attr = *attrib_ptr++;
946 GLint val = *attrib_ptr++;
947 if (attr != EGL_TELEMETRY_HINT_ANDROID) {
948 replacement_attrib_list.push_back(attr);
949 replacement_attrib_list.push_back(val);
950 }
951 }
952 replacement_attrib_list.push_back(EGL_NONE);
953 attrib_list = replacement_attrib_list.data();
954 }
955 // b/111083885 - If we are presenting EGL 1.4 interface to apps
956 // error out on robust access attributes that are invalid
957 // in EGL 1.4 as the driver may be fine with them but dEQP expects
958 // tests to fail according to spec.
959 if (attrib_list && (cnx->driverVersion < EGL_MAKE_VERSION(1, 5, 0))) {
960 if (findAttribute(attrib_list, EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR,
961 nullptr)) {
962 // We are GL ES context with EGL 1.4, this is an invalid attribute
963 return setError(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
964 }
965 }
966 EGLContext context =
967 cnx->egl.eglCreateContext(dp->disp.dpy, config, share_list, attrib_list);
968 if (context != EGL_NO_CONTEXT) {
969 // figure out if it's a GLESv1 or GLESv2
970 int version = egl_connection_t::GLESv1_INDEX;
971 GLint version_value;
972 if (findAttribute(attrib_list, EGL_CONTEXT_CLIENT_VERSION, &version_value)) {
973 if (version_value == 2 || version_value == 3) {
974 version = egl_connection_t::GLESv2_INDEX;
975 }
976 }
977 if (version == egl_connection_t::GLESv1_INDEX) {
978 android::GraphicsEnv::getInstance().setTargetStats(
979 android::GpuStatsInfo::Stats::GLES_1_IN_USE);
980 }
981 if (!skip_telemetry) {
982 android::GraphicsEnv::getInstance().setTargetStats(
983 android::GpuStatsInfo::Stats::CREATED_GLES_CONTEXT);
984 }
985 egl_context_t* c = new egl_context_t(dpy, context, config, cnx, version);
986 return c;
987 }
988 }
989 return EGL_NO_CONTEXT;
990 }
991
eglDestroyContextImpl(EGLDisplay dpy,EGLContext ctx)992 EGLBoolean eglDestroyContextImpl(EGLDisplay dpy, EGLContext ctx) {
993 const egl_display_t* dp = validate_display(dpy);
994 if (!dp) return EGL_FALSE;
995
996 ContextRef _c(dp, ctx);
997 if (!_c.get()) return setError(EGL_BAD_CONTEXT, (EGLBoolean)EGL_FALSE);
998
999 egl_context_t* const c = get_context(ctx);
1000 EGLBoolean result = c->cnx->egl.eglDestroyContext(dp->disp.dpy, c->context);
1001 if (result == EGL_TRUE) {
1002 _c.terminate();
1003 }
1004 return result;
1005 }
1006
eglMakeCurrentImpl(EGLDisplay dpy,EGLSurface draw,EGLSurface read,EGLContext ctx)1007 EGLBoolean eglMakeCurrentImpl(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx) {
1008 egl_display_t* dp = validate_display(dpy);
1009 if (!dp) return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
1010
1011 // If ctx is not EGL_NO_CONTEXT, read is not EGL_NO_SURFACE, or draw is not
1012 // EGL_NO_SURFACE, then an EGL_NOT_INITIALIZED error is generated if dpy is
1013 // a valid but uninitialized display.
1014 if ((ctx != EGL_NO_CONTEXT) || (read != EGL_NO_SURFACE) || (draw != EGL_NO_SURFACE)) {
1015 if (!dp->isReady()) return setError(EGL_NOT_INITIALIZED, (EGLBoolean)EGL_FALSE);
1016 }
1017
1018 // get a reference to the object passed in
1019 ContextRef _c(dp, ctx);
1020 SurfaceRef _d(dp, draw);
1021 SurfaceRef _r(dp, read);
1022
1023 // validate the context (if not EGL_NO_CONTEXT)
1024 if ((ctx != EGL_NO_CONTEXT) && !_c.get()) {
1025 // EGL_NO_CONTEXT is valid
1026 return setError(EGL_BAD_CONTEXT, (EGLBoolean)EGL_FALSE);
1027 }
1028
1029 // these are the underlying implementation's object
1030 EGLContext impl_ctx = EGL_NO_CONTEXT;
1031 EGLSurface impl_draw = EGL_NO_SURFACE;
1032 EGLSurface impl_read = EGL_NO_SURFACE;
1033
1034 // these are our objects structs passed in
1035 egl_context_t* c = nullptr;
1036 egl_surface_t const* d = nullptr;
1037 egl_surface_t const* r = nullptr;
1038
1039 // these are the current objects structs
1040 egl_context_t* cur_c = get_context(getContext());
1041
1042 if (ctx != EGL_NO_CONTEXT) {
1043 c = get_context(ctx);
1044 impl_ctx = c->context;
1045 } else {
1046 // no context given, use the implementation of the current context
1047 if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) {
1048 // calling eglMakeCurrent( ..., !=0, !=0, EGL_NO_CONTEXT);
1049 return setError(EGL_BAD_MATCH, (EGLBoolean)EGL_FALSE);
1050 }
1051 if (cur_c == nullptr) {
1052 // no current context
1053 // not an error, there is just no current context.
1054 return EGL_TRUE;
1055 }
1056 }
1057
1058 // retrieve the underlying implementation's draw EGLSurface
1059 if (draw != EGL_NO_SURFACE) {
1060 if (!_d.get()) return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
1061 d = get_surface(draw);
1062 impl_draw = d->surface;
1063 }
1064
1065 // retrieve the underlying implementation's read EGLSurface
1066 if (read != EGL_NO_SURFACE) {
1067 if (!_r.get()) return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
1068 r = get_surface(read);
1069 impl_read = r->surface;
1070 }
1071
1072 EGLBoolean result = dp->makeCurrent(c, cur_c, draw, read, ctx, impl_draw, impl_read, impl_ctx);
1073
1074 if (result == EGL_TRUE) {
1075 if (c) {
1076 setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
1077 egl_tls_t::setContext(ctx);
1078 _c.acquire();
1079 _r.acquire();
1080 _d.acquire();
1081 } else {
1082 setGLHooksThreadSpecific(&gHooksNoContext);
1083 egl_tls_t::setContext(EGL_NO_CONTEXT);
1084 }
1085 } else {
1086 // this will ALOGE the error
1087 egl_connection_t* const cnx = &gEGLImpl;
1088 result = setError(cnx->egl.eglGetError(), (EGLBoolean)EGL_FALSE);
1089 }
1090 return result;
1091 }
1092
eglQueryContextImpl(EGLDisplay dpy,EGLContext ctx,EGLint attribute,EGLint * value)1093 EGLBoolean eglQueryContextImpl(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint* value) {
1094 const egl_display_t* dp = validate_display(dpy);
1095 if (!dp) return EGL_FALSE;
1096
1097 ContextRef _c(dp, ctx);
1098 if (!_c.get()) return setError(EGL_BAD_CONTEXT, (EGLBoolean)EGL_FALSE);
1099
1100 egl_context_t* const c = get_context(ctx);
1101 return c->cnx->egl.eglQueryContext(dp->disp.dpy, c->context, attribute, value);
1102 }
1103
eglGetCurrentContextImpl(void)1104 EGLContext eglGetCurrentContextImpl(void) {
1105 // could be called before eglInitialize(), but we wouldn't have a context
1106 // then, and this function would correctly return EGL_NO_CONTEXT.
1107 EGLContext ctx = getContext();
1108 return ctx;
1109 }
1110
eglGetCurrentSurfaceImpl(EGLint readdraw)1111 EGLSurface eglGetCurrentSurfaceImpl(EGLint readdraw) {
1112 // could be called before eglInitialize(), but we wouldn't have a context
1113 // then, and this function would correctly return EGL_NO_SURFACE.
1114
1115 EGLContext ctx = getContext();
1116 if (ctx) {
1117 egl_context_t const* const c = get_context(ctx);
1118 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
1119 switch (readdraw) {
1120 case EGL_READ:
1121 return c->read;
1122 case EGL_DRAW:
1123 return c->draw;
1124 default:
1125 return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
1126 }
1127 }
1128 return EGL_NO_SURFACE;
1129 }
1130
eglGetCurrentDisplayImpl(void)1131 EGLDisplay eglGetCurrentDisplayImpl(void) {
1132 // could be called before eglInitialize(), but we wouldn't have a context
1133 // then, and this function would correctly return EGL_NO_DISPLAY.
1134
1135 EGLContext ctx = getContext();
1136 if (ctx) {
1137 egl_context_t const* const c = get_context(ctx);
1138 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
1139 return c->dpy;
1140 }
1141 return EGL_NO_DISPLAY;
1142 }
1143
eglWaitGLImpl(void)1144 EGLBoolean eglWaitGLImpl(void) {
1145 egl_connection_t* const cnx = &gEGLImpl;
1146 if (!cnx->dso) return setError(EGL_BAD_CONTEXT, (EGLBoolean)EGL_FALSE);
1147
1148 return cnx->egl.eglWaitGL();
1149 }
1150
eglWaitNativeImpl(EGLint engine)1151 EGLBoolean eglWaitNativeImpl(EGLint engine) {
1152 egl_connection_t* const cnx = &gEGLImpl;
1153 if (!cnx->dso) return setError(EGL_BAD_CONTEXT, (EGLBoolean)EGL_FALSE);
1154
1155 return cnx->egl.eglWaitNative(engine);
1156 }
1157
eglGetErrorImpl(void)1158 EGLint eglGetErrorImpl(void) {
1159 EGLint err = EGL_SUCCESS;
1160 egl_connection_t* const cnx = &gEGLImpl;
1161 if (cnx->dso) {
1162 err = cnx->egl.eglGetError();
1163 }
1164 if (err == EGL_SUCCESS) {
1165 err = egl_tls_t::getError();
1166 }
1167 return err;
1168 }
1169
findBuiltinWrapper(const char * procname)1170 static __eglMustCastToProperFunctionPointerType findBuiltinWrapper(const char* procname) {
1171 const egl_connection_t* cnx = &gEGLImpl;
1172 void* proc = nullptr;
1173
1174 proc = dlsym(cnx->libEgl, procname);
1175 if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
1176
1177 proc = dlsym(cnx->libGles2, procname);
1178 if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
1179
1180 proc = dlsym(cnx->libGles1, procname);
1181 if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
1182
1183 return nullptr;
1184 }
1185
eglGetProcAddressImpl(const char * procname)1186 __eglMustCastToProperFunctionPointerType eglGetProcAddressImpl(const char* procname) {
1187 if (FILTER_EXTENSIONS(procname)) {
1188 return nullptr;
1189 }
1190
1191 __eglMustCastToProperFunctionPointerType addr;
1192 addr = findProcAddress(procname, sExtensionMap, NELEM(sExtensionMap));
1193 if (addr) return addr;
1194
1195 addr = findBuiltinWrapper(procname);
1196 if (addr) return addr;
1197
1198 // this protects accesses to sGLExtensionMap, sGLExtensionSlot, and sGLExtensionSlotMap
1199 pthread_mutex_lock(&sExtensionMapMutex);
1200
1201 /*
1202 * Since eglGetProcAddress() is not associated to anything, it needs
1203 * to return a function pointer that "works" regardless of what
1204 * the current context is.
1205 *
1206 * For this reason, we return a "forwarder", a small stub that takes
1207 * care of calling the function associated with the context
1208 * currently bound.
1209 *
1210 * We first look for extensions we've already resolved, if we're seeing
1211 * this extension for the first time, we go through all our
1212 * implementations and call eglGetProcAddress() and record the
1213 * result in the appropriate implementation hooks and return the
1214 * address of the forwarder corresponding to that hook set.
1215 *
1216 */
1217
1218 const std::string name(procname);
1219 auto& extensionMap = sGLExtensionMap;
1220 auto& extensionSlotMap = sGLExtensionSlotMap;
1221 egl_connection_t* const cnx = &gEGLImpl;
1222 LayerLoader& layer_loader(LayerLoader::getInstance());
1223
1224 // See if we've already looked up this extension
1225 auto pos = extensionMap.find(name);
1226 addr = (pos != extensionMap.end()) ? pos->second : nullptr;
1227
1228 if (!addr) {
1229 // This is the first time we've looked this function up
1230 // Ensure we have room to track it
1231 const int slot = sGLExtensionSlot;
1232 if (slot < MAX_NUMBER_OF_GL_EXTENSIONS) {
1233 if (cnx->dso && cnx->egl.eglGetProcAddress) {
1234 // Extensions are independent of the bound context
1235 addr = cnx->egl.eglGetProcAddress(procname);
1236 if (addr) {
1237 // purposefully track the bottom of the stack in extensionMap
1238 extensionMap[name] = addr;
1239
1240 // Apply layers
1241 addr = layer_loader.ApplyLayers(procname, addr);
1242
1243 // Track the top most entry point return the extension forwarder
1244 cnx->hooks[egl_connection_t::GLESv1_INDEX]->ext.extensions[slot] =
1245 cnx->hooks[egl_connection_t::GLESv2_INDEX]->ext.extensions[slot] = addr;
1246 addr = gExtensionForwarders[slot];
1247
1248 // Remember the slot for this extension
1249 extensionSlotMap[name] = slot;
1250
1251 // Increment the global extension index
1252 sGLExtensionSlot++;
1253 }
1254 }
1255 } else {
1256 // The extension forwarder has a fixed number of slots
1257 ALOGE("no more slots for eglGetProcAddress(\"%s\")", procname);
1258 }
1259
1260 } else {
1261 // We tracked an address, so we've seen this func before
1262 // Look up the slot for this extension
1263 auto slot_pos = extensionSlotMap.find(name);
1264 int ext_slot = (slot_pos != extensionSlotMap.end()) ? slot_pos->second : -1;
1265 if (ext_slot < 0) {
1266 // Something has gone wrong, this should not happen
1267 ALOGE("No extension slot found for %s", procname);
1268 return nullptr;
1269 }
1270
1271 // We tracked the bottom of the stack, so re-apply layers since
1272 // more layers might have been enabled
1273 addr = layer_loader.ApplyLayers(procname, addr);
1274
1275 // Track the top most entry point and return the extension forwarder
1276 cnx->hooks[egl_connection_t::GLESv1_INDEX]->ext.extensions[ext_slot] =
1277 cnx->hooks[egl_connection_t::GLESv2_INDEX]->ext.extensions[ext_slot] = addr;
1278 addr = gExtensionForwarders[ext_slot];
1279 }
1280
1281 pthread_mutex_unlock(&sExtensionMapMutex);
1282 return addr;
1283 }
1284
1285 class FrameCompletionThread {
1286 public:
queueSync(EGLSyncKHR sync)1287 static void queueSync(EGLSyncKHR sync) {
1288 static FrameCompletionThread thread;
1289
1290 char name[64];
1291
1292 std::lock_guard<std::mutex> lock(thread.mMutex);
1293 snprintf(name, sizeof(name), "kicked off frame %u", (unsigned int)thread.mFramesQueued);
1294 ATRACE_NAME(name);
1295
1296 thread.mQueue.push_back(sync);
1297 thread.mCondition.notify_one();
1298 thread.mFramesQueued++;
1299 ATRACE_INT("GPU Frames Outstanding", int32_t(thread.mQueue.size()));
1300 }
1301
1302 private:
FrameCompletionThread()1303 FrameCompletionThread() : mFramesQueued(0), mFramesCompleted(0) {
1304 std::thread thread(&FrameCompletionThread::loop, this);
1305 thread.detach();
1306 }
1307
1308 #pragma clang diagnostic push
1309 #pragma clang diagnostic ignored "-Wmissing-noreturn"
loop()1310 void loop() {
1311 while (true) {
1312 threadLoop();
1313 }
1314 }
1315 #pragma clang diagnostic pop
1316
threadLoop()1317 void threadLoop() {
1318 EGLSyncKHR sync;
1319 uint32_t frameNum;
1320 {
1321 std::unique_lock<std::mutex> lock(mMutex);
1322 while (mQueue.empty()) {
1323 mCondition.wait(lock);
1324 }
1325 sync = mQueue[0];
1326 frameNum = mFramesCompleted;
1327 }
1328 EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
1329 {
1330 char name[64];
1331 snprintf(name, sizeof(name), "waiting for frame %u", (unsigned int)frameNum);
1332 ATRACE_NAME(name);
1333
1334 EGLint result = eglClientWaitSyncKHR(dpy, sync, 0, EGL_FOREVER_KHR);
1335 if (result == EGL_FALSE) {
1336 ALOGE("FrameCompletion: error waiting for fence: %#x", eglGetError());
1337 } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
1338 ALOGE("FrameCompletion: timeout waiting for fence");
1339 }
1340 eglDestroySyncKHR(dpy, sync);
1341 }
1342 {
1343 std::lock_guard<std::mutex> lock(mMutex);
1344 mQueue.pop_front();
1345 mFramesCompleted++;
1346 ATRACE_INT("GPU Frames Outstanding", int32_t(mQueue.size()));
1347 }
1348 }
1349
1350 uint32_t mFramesQueued;
1351 uint32_t mFramesCompleted;
1352 std::deque<EGLSyncKHR> mQueue;
1353 std::condition_variable mCondition;
1354 std::mutex mMutex;
1355 };
1356
eglSwapBuffersWithDamageKHRImpl(EGLDisplay dpy,EGLSurface draw,const EGLint * rects,EGLint n_rects)1357 EGLBoolean eglSwapBuffersWithDamageKHRImpl(EGLDisplay dpy, EGLSurface draw, const EGLint* rects,
1358 EGLint n_rects) {
1359 const egl_display_t* dp = validate_display(dpy);
1360 if (!dp) return EGL_FALSE;
1361
1362 SurfaceRef _s(dp, draw);
1363 if (!_s.get()) return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
1364
1365 if (n_rects < 0 || (n_rects > 0 && rects == NULL))
1366 return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE);
1367
1368 egl_surface_t* const s = get_surface(draw);
1369
1370 if (CC_UNLIKELY(dp->traceGpuCompletion)) {
1371 EGLSyncKHR sync = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, nullptr);
1372 if (sync != EGL_NO_SYNC_KHR) {
1373 FrameCompletionThread::queueSync(sync);
1374 }
1375 }
1376
1377 if (CC_UNLIKELY(dp->finishOnSwap)) {
1378 uint32_t pixel;
1379 egl_context_t* const c = get_context(egl_tls_t::getContext());
1380 if (c) {
1381 // glReadPixels() ensures that the frame is complete
1382 s->cnx->hooks[c->version]->gl.glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE,
1383 &pixel);
1384 }
1385 }
1386
1387 if (!s->cnx->angleLoaded) {
1388 if (!sendSurfaceMetadata(s)) {
1389 native_window_api_disconnect(s->getNativeWindow(), NATIVE_WINDOW_API_EGL);
1390 return setError(EGL_BAD_NATIVE_WINDOW, (EGLBoolean)EGL_FALSE);
1391 }
1392 }
1393
1394 if (n_rects == 0) {
1395 return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface);
1396 }
1397
1398 std::vector<android_native_rect_t> androidRects((size_t)n_rects);
1399 for (int r = 0; r < n_rects; ++r) {
1400 int offset = r * 4;
1401 int x = rects[offset];
1402 int y = rects[offset + 1];
1403 int width = rects[offset + 2];
1404 int height = rects[offset + 3];
1405 android_native_rect_t androidRect;
1406 androidRect.left = x;
1407 androidRect.top = y + height;
1408 androidRect.right = x + width;
1409 androidRect.bottom = y;
1410 androidRects.push_back(androidRect);
1411 }
1412 if (!s->cnx->angleLoaded) {
1413 native_window_set_surface_damage(s->getNativeWindow(), androidRects.data(),
1414 androidRects.size());
1415 }
1416
1417 if (s->cnx->egl.eglSwapBuffersWithDamageKHR) {
1418 return s->cnx->egl.eglSwapBuffersWithDamageKHR(dp->disp.dpy, s->surface, rects, n_rects);
1419 }
1420
1421 return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface);
1422 }
1423
eglSwapBuffersImpl(EGLDisplay dpy,EGLSurface surface)1424 EGLBoolean eglSwapBuffersImpl(EGLDisplay dpy, EGLSurface surface) {
1425 return eglSwapBuffersWithDamageKHRImpl(dpy, surface, nullptr, 0);
1426 }
1427
eglCopyBuffersImpl(EGLDisplay dpy,EGLSurface surface,NativePixmapType target)1428 EGLBoolean eglCopyBuffersImpl(EGLDisplay dpy, EGLSurface surface, NativePixmapType target) {
1429 const egl_display_t* dp = validate_display(dpy);
1430 if (!dp) return EGL_FALSE;
1431
1432 SurfaceRef _s(dp, surface);
1433 if (!_s.get()) return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
1434
1435 egl_surface_t const* const s = get_surface(surface);
1436 return s->cnx->egl.eglCopyBuffers(dp->disp.dpy, s->surface, target);
1437 }
1438
eglQueryStringImpl(EGLDisplay dpy,EGLint name)1439 const char* eglQueryStringImpl(EGLDisplay dpy, EGLint name) {
1440 if (dpy == EGL_NO_DISPLAY && name == EGL_EXTENSIONS) {
1441 // Return list of client extensions
1442 return gClientExtensionString;
1443 }
1444
1445 const egl_display_t* dp = validate_display(dpy);
1446 if (!dp) return (const char*)nullptr;
1447
1448 switch (name) {
1449 case EGL_VENDOR:
1450 return dp->getVendorString();
1451 case EGL_VERSION:
1452 return dp->getVersionString();
1453 case EGL_EXTENSIONS:
1454 return dp->getExtensionString();
1455 case EGL_CLIENT_APIS:
1456 return dp->getClientApiString();
1457 default:
1458 break;
1459 }
1460 return setError(EGL_BAD_PARAMETER, (const char*)nullptr);
1461 }
1462
eglQueryStringImplementationANDROIDImpl(EGLDisplay dpy,EGLint name)1463 EGLAPI const char* eglQueryStringImplementationANDROIDImpl(EGLDisplay dpy, EGLint name) {
1464 const egl_display_t* dp = validate_display(dpy);
1465 if (!dp) return (const char*)nullptr;
1466
1467 switch (name) {
1468 case EGL_VENDOR:
1469 return dp->disp.queryString.vendor;
1470 case EGL_VERSION:
1471 return dp->disp.queryString.version;
1472 case EGL_EXTENSIONS:
1473 return dp->disp.queryString.extensions;
1474 case EGL_CLIENT_APIS:
1475 return dp->disp.queryString.clientApi;
1476 default:
1477 break;
1478 }
1479 return setError(EGL_BAD_PARAMETER, (const char*)nullptr);
1480 }
1481
1482 // ----------------------------------------------------------------------------
1483 // EGL 1.1
1484 // ----------------------------------------------------------------------------
1485
eglSurfaceAttribImpl(EGLDisplay dpy,EGLSurface surface,EGLint attribute,EGLint value)1486 EGLBoolean eglSurfaceAttribImpl(EGLDisplay dpy, EGLSurface surface, EGLint attribute,
1487 EGLint value) {
1488 const egl_display_t* dp = validate_display(dpy);
1489 if (!dp) return EGL_FALSE;
1490
1491 SurfaceRef _s(dp, surface);
1492 if (!_s.get()) return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
1493
1494 egl_surface_t* const s = get_surface(surface);
1495
1496 if (attribute == EGL_FRONT_BUFFER_AUTO_REFRESH_ANDROID) {
1497 if (!s->getNativeWindow()) {
1498 setError(EGL_BAD_SURFACE, EGL_FALSE);
1499 }
1500 int err = native_window_set_auto_refresh(s->getNativeWindow(), value != 0);
1501 if (err != 0) {
1502 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
1503 } else if (!s->cnx->angleLoaded) {
1504 return EGL_TRUE;
1505 } // else if ANGLE, fall through to the call to the driver (i.e. ANGLE) below
1506 }
1507
1508 if (attribute == EGL_TIMESTAMPS_ANDROID) {
1509 if (!s->getNativeWindow()) {
1510 // According to the spec, "if surface is not a window surface this has no
1511 // effect."
1512 return EGL_TRUE;
1513 }
1514 int err = native_window_enable_frame_timestamps(s->getNativeWindow(), value != 0);
1515 if (err != 0) {
1516 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
1517 } else if (!s->cnx->angleLoaded) {
1518 return EGL_TRUE;
1519 } // else if ANGLE, fall through to the call to the driver (i.e. ANGLE) below
1520 }
1521
1522 if (s->setSmpte2086Attribute(attribute, value)) {
1523 return EGL_TRUE;
1524 } else if (s->setCta8613Attribute(attribute, value)) {
1525 return EGL_TRUE;
1526 } else if (s->cnx->egl.eglSurfaceAttrib) {
1527 return s->cnx->egl.eglSurfaceAttrib(dp->disp.dpy, s->surface, attribute, value);
1528 }
1529 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
1530 }
1531
eglBindTexImageImpl(EGLDisplay dpy,EGLSurface surface,EGLint buffer)1532 EGLBoolean eglBindTexImageImpl(EGLDisplay dpy, EGLSurface surface, EGLint buffer) {
1533 const egl_display_t* dp = validate_display(dpy);
1534 if (!dp) return EGL_FALSE;
1535
1536 SurfaceRef _s(dp, surface);
1537 if (!_s.get()) return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
1538
1539 egl_surface_t const* const s = get_surface(surface);
1540 if (s->cnx->egl.eglBindTexImage) {
1541 return s->cnx->egl.eglBindTexImage(dp->disp.dpy, s->surface, buffer);
1542 }
1543 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
1544 }
1545
eglReleaseTexImageImpl(EGLDisplay dpy,EGLSurface surface,EGLint buffer)1546 EGLBoolean eglReleaseTexImageImpl(EGLDisplay dpy, EGLSurface surface, EGLint buffer) {
1547 const egl_display_t* dp = validate_display(dpy);
1548 if (!dp) return EGL_FALSE;
1549
1550 SurfaceRef _s(dp, surface);
1551 if (!_s.get()) return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
1552
1553 egl_surface_t const* const s = get_surface(surface);
1554 if (s->cnx->egl.eglReleaseTexImage) {
1555 return s->cnx->egl.eglReleaseTexImage(dp->disp.dpy, s->surface, buffer);
1556 }
1557 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
1558 }
1559
eglSwapIntervalImpl(EGLDisplay dpy,EGLint interval)1560 EGLBoolean eglSwapIntervalImpl(EGLDisplay dpy, EGLint interval) {
1561 const egl_display_t* dp = validate_display(dpy);
1562 if (!dp) return EGL_FALSE;
1563
1564 EGLBoolean res = EGL_TRUE;
1565 egl_connection_t* const cnx = &gEGLImpl;
1566 if (cnx->dso && cnx->egl.eglSwapInterval) {
1567 res = cnx->egl.eglSwapInterval(dp->disp.dpy, interval);
1568 }
1569
1570 return res;
1571 }
1572
1573 // ----------------------------------------------------------------------------
1574 // EGL 1.2
1575 // ----------------------------------------------------------------------------
1576
eglWaitClientImpl(void)1577 EGLBoolean eglWaitClientImpl(void) {
1578 egl_connection_t* const cnx = &gEGLImpl;
1579 if (!cnx->dso) return setError(EGL_BAD_CONTEXT, (EGLBoolean)EGL_FALSE);
1580
1581 EGLBoolean res;
1582 if (cnx->egl.eglWaitClient) {
1583 res = cnx->egl.eglWaitClient();
1584 } else {
1585 res = cnx->egl.eglWaitGL();
1586 }
1587 return res;
1588 }
1589
eglBindAPIImpl(EGLenum api)1590 EGLBoolean eglBindAPIImpl(EGLenum api) {
1591 // bind this API on all EGLs
1592 EGLBoolean res = EGL_TRUE;
1593 egl_connection_t* const cnx = &gEGLImpl;
1594 if (cnx->dso && cnx->egl.eglBindAPI) {
1595 res = cnx->egl.eglBindAPI(api);
1596 }
1597 return res;
1598 }
1599
eglQueryAPIImpl(void)1600 EGLenum eglQueryAPIImpl(void) {
1601 egl_connection_t* const cnx = &gEGLImpl;
1602 if (cnx->dso && cnx->egl.eglQueryAPI) {
1603 return cnx->egl.eglQueryAPI();
1604 }
1605
1606 // or, it can only be OpenGL ES
1607 return EGL_OPENGL_ES_API;
1608 }
1609
eglReleaseThreadImpl(void)1610 EGLBoolean eglReleaseThreadImpl(void) {
1611 egl_connection_t* const cnx = &gEGLImpl;
1612 if (cnx->dso && cnx->egl.eglReleaseThread) {
1613 cnx->egl.eglReleaseThread();
1614 }
1615
1616 // If there is context bound to the thread, release it
1617 egl_display_t::loseCurrent(get_context(getContext()));
1618
1619 egl_tls_t::clearTLS();
1620 return EGL_TRUE;
1621 }
1622
eglCreatePbufferFromClientBufferImpl(EGLDisplay dpy,EGLenum buftype,EGLClientBuffer buffer,EGLConfig config,const EGLint * attrib_list)1623 EGLSurface eglCreatePbufferFromClientBufferImpl(EGLDisplay dpy, EGLenum buftype,
1624 EGLClientBuffer buffer, EGLConfig config,
1625 const EGLint* attrib_list) {
1626 egl_connection_t* cnx = nullptr;
1627 const egl_display_t* dp = validate_display_connection(dpy, &cnx);
1628 if (!dp) return EGL_FALSE;
1629 if (cnx->egl.eglCreatePbufferFromClientBuffer) {
1630 return cnx->egl.eglCreatePbufferFromClientBuffer(dp->disp.dpy, buftype, buffer, config,
1631 attrib_list);
1632 }
1633 return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE);
1634 }
1635
1636 // ----------------------------------------------------------------------------
1637 // EGL_EGLEXT_VERSION 3
1638 // ----------------------------------------------------------------------------
1639
eglLockSurfaceKHRImpl(EGLDisplay dpy,EGLSurface surface,const EGLint * attrib_list)1640 EGLBoolean eglLockSurfaceKHRImpl(EGLDisplay dpy, EGLSurface surface, const EGLint* attrib_list) {
1641 const egl_display_t* dp = validate_display(dpy);
1642 if (!dp) return EGL_FALSE;
1643
1644 SurfaceRef _s(dp, surface);
1645 if (!_s.get()) return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
1646
1647 egl_surface_t const* const s = get_surface(surface);
1648 if (s->cnx->egl.eglLockSurfaceKHR) {
1649 return s->cnx->egl.eglLockSurfaceKHR(dp->disp.dpy, s->surface, attrib_list);
1650 }
1651 return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
1652 }
1653
eglUnlockSurfaceKHRImpl(EGLDisplay dpy,EGLSurface surface)1654 EGLBoolean eglUnlockSurfaceKHRImpl(EGLDisplay dpy, EGLSurface surface) {
1655 const egl_display_t* dp = validate_display(dpy);
1656 if (!dp) return EGL_FALSE;
1657
1658 SurfaceRef _s(dp, surface);
1659 if (!_s.get()) return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
1660
1661 egl_surface_t const* const s = get_surface(surface);
1662 if (s->cnx->egl.eglUnlockSurfaceKHR) {
1663 return s->cnx->egl.eglUnlockSurfaceKHR(dp->disp.dpy, s->surface);
1664 }
1665 return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
1666 }
1667
1668 // Note: EGLImageKHR and EGLImage are the same thing so no need
1669 // to templatize that.
1670 template <typename AttrType, typename FuncType>
eglCreateImageTmpl(EGLDisplay dpy,EGLContext ctx,EGLenum target,EGLClientBuffer buffer,const AttrType * attrib_list,FuncType eglCreateImageFunc)1671 EGLImageKHR eglCreateImageTmpl(EGLDisplay dpy, EGLContext ctx, EGLenum target,
1672 EGLClientBuffer buffer, const AttrType* attrib_list,
1673 FuncType eglCreateImageFunc) {
1674 const egl_display_t* dp = validate_display(dpy);
1675 if (!dp) return EGL_NO_IMAGE_KHR;
1676
1677 ContextRef _c(dp, ctx);
1678 egl_context_t* const c = _c.get();
1679
1680 EGLImageKHR result = EGL_NO_IMAGE_KHR;
1681 egl_connection_t* const cnx = &gEGLImpl;
1682 if (cnx->dso && eglCreateImageFunc) {
1683 result = eglCreateImageFunc(dp->disp.dpy, c ? c->context : EGL_NO_CONTEXT, target, buffer,
1684 attrib_list);
1685 }
1686 return result;
1687 }
1688
1689 typedef EGLImage(EGLAPIENTRYP PFNEGLCREATEIMAGE)(EGLDisplay dpy, EGLContext ctx, EGLenum target,
1690 EGLClientBuffer buffer,
1691 const EGLAttrib* attrib_list);
1692
eglCreateImageKHRImpl(EGLDisplay dpy,EGLContext ctx,EGLenum target,EGLClientBuffer buffer,const EGLint * attrib_list)1693 EGLImageKHR eglCreateImageKHRImpl(EGLDisplay dpy, EGLContext ctx, EGLenum target,
1694 EGLClientBuffer buffer, const EGLint* attrib_list) {
1695 return eglCreateImageTmpl<EGLint, PFNEGLCREATEIMAGEKHRPROC>(dpy, ctx, target, buffer,
1696 attrib_list,
1697 gEGLImpl.egl.eglCreateImageKHR);
1698 }
1699
eglCreateImageImpl(EGLDisplay dpy,EGLContext ctx,EGLenum target,EGLClientBuffer buffer,const EGLAttrib * attrib_list)1700 EGLImage eglCreateImageImpl(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer,
1701 const EGLAttrib* attrib_list) {
1702 egl_connection_t* const cnx = &gEGLImpl;
1703 if (cnx->driverVersion >= EGL_MAKE_VERSION(1, 5, 0)) {
1704 if (cnx->egl.eglCreateImage) {
1705 return eglCreateImageTmpl<EGLAttrib, PFNEGLCREATEIMAGE>(dpy, ctx, target, buffer,
1706 attrib_list,
1707 cnx->egl.eglCreateImage);
1708 }
1709 // driver doesn't support native function, return EGL_BAD_DISPLAY
1710 ALOGE("Driver indicates EGL 1.5 support, but does not have eglCreateImage");
1711 return setError(EGL_BAD_DISPLAY, EGL_NO_IMAGE);
1712 }
1713
1714 std::vector<EGLint> convertedAttribs;
1715 convertAttribs(attrib_list, convertedAttribs);
1716 return eglCreateImageTmpl<EGLint, PFNEGLCREATEIMAGEKHRPROC>(dpy, ctx, target, buffer,
1717 convertedAttribs.data(),
1718 gEGLImpl.egl.eglCreateImageKHR);
1719 }
1720
eglDestroyImageTmpl(EGLDisplay dpy,EGLImageKHR img,PFNEGLDESTROYIMAGEKHRPROC destroyImageFunc)1721 EGLBoolean eglDestroyImageTmpl(EGLDisplay dpy, EGLImageKHR img,
1722 PFNEGLDESTROYIMAGEKHRPROC destroyImageFunc) {
1723 const egl_display_t* dp = validate_display(dpy);
1724 if (!dp) return EGL_FALSE;
1725
1726 EGLBoolean result = EGL_FALSE;
1727 egl_connection_t* const cnx = &gEGLImpl;
1728 if (cnx->dso && destroyImageFunc) {
1729 result = destroyImageFunc(dp->disp.dpy, img);
1730 }
1731 return result;
1732 }
1733
eglDestroyImageKHRImpl(EGLDisplay dpy,EGLImageKHR img)1734 EGLBoolean eglDestroyImageKHRImpl(EGLDisplay dpy, EGLImageKHR img) {
1735 return eglDestroyImageTmpl(dpy, img, gEGLImpl.egl.eglDestroyImageKHR);
1736 }
1737
eglDestroyImageImpl(EGLDisplay dpy,EGLImageKHR img)1738 EGLBoolean eglDestroyImageImpl(EGLDisplay dpy, EGLImageKHR img) {
1739 egl_connection_t* const cnx = &gEGLImpl;
1740 if (cnx->driverVersion >= EGL_MAKE_VERSION(1, 5, 0)) {
1741 if (cnx->egl.eglDestroyImage) {
1742 return eglDestroyImageTmpl(dpy, img, gEGLImpl.egl.eglDestroyImage);
1743 }
1744 // driver doesn't support native function, return EGL_BAD_DISPLAY
1745 ALOGE("Driver indicates EGL 1.5 support, but does not have eglDestroyImage");
1746 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1747 }
1748
1749 return eglDestroyImageTmpl(dpy, img, gEGLImpl.egl.eglDestroyImageKHR);
1750 }
1751
1752 // ----------------------------------------------------------------------------
1753 // EGL_EGLEXT_VERSION 5
1754 // ----------------------------------------------------------------------------
1755
1756 // NOTE: EGLSyncKHR and EGLSync are identical, no need to templatize
1757 template <typename AttrType, typename FuncType>
eglCreateSyncTmpl(EGLDisplay dpy,EGLenum type,const AttrType * attrib_list,FuncType eglCreateSyncFunc)1758 EGLSyncKHR eglCreateSyncTmpl(EGLDisplay dpy, EGLenum type, const AttrType* attrib_list,
1759 FuncType eglCreateSyncFunc) {
1760 const egl_display_t* dp = validate_display(dpy);
1761 if (!dp) return EGL_NO_SYNC_KHR;
1762
1763 egl_connection_t* const cnx = &gEGLImpl;
1764 EGLSyncKHR result = EGL_NO_SYNC_KHR;
1765 if (cnx->dso && eglCreateSyncFunc) {
1766 result = eglCreateSyncFunc(dp->disp.dpy, type, attrib_list);
1767 }
1768 return result;
1769 }
1770
1771 typedef EGLSurface(EGLAPIENTRYP PFNEGLCREATESYNC)(EGLDisplay dpy, EGLenum type,
1772 const EGLAttrib* attrib_list);
1773
eglCreateSyncKHRImpl(EGLDisplay dpy,EGLenum type,const EGLint * attrib_list)1774 EGLSyncKHR eglCreateSyncKHRImpl(EGLDisplay dpy, EGLenum type, const EGLint* attrib_list) {
1775 return eglCreateSyncTmpl<EGLint, PFNEGLCREATESYNCKHRPROC>(dpy, type, attrib_list,
1776 gEGLImpl.egl.eglCreateSyncKHR);
1777 }
1778
eglCreateSyncImpl(EGLDisplay dpy,EGLenum type,const EGLAttrib * attrib_list)1779 EGLSync eglCreateSyncImpl(EGLDisplay dpy, EGLenum type, const EGLAttrib* attrib_list) {
1780 egl_connection_t* const cnx = &gEGLImpl;
1781 if (cnx->driverVersion >= EGL_MAKE_VERSION(1, 5, 0)) {
1782 if (cnx->egl.eglCreateSync) {
1783 return eglCreateSyncTmpl<EGLAttrib, PFNEGLCREATESYNC>(dpy, type, attrib_list,
1784 cnx->egl.eglCreateSync);
1785 }
1786 // driver doesn't support native function, return EGL_BAD_DISPLAY
1787 ALOGE("Driver indicates EGL 1.5 support, but does not have eglCreateSync");
1788 return setError(EGL_BAD_DISPLAY, EGL_NO_SYNC);
1789 }
1790
1791 std::vector<EGLint> convertedAttribs;
1792 convertAttribs(attrib_list, convertedAttribs);
1793 return eglCreateSyncTmpl<EGLint, PFNEGLCREATESYNCKHRPROC>(dpy, type, convertedAttribs.data(),
1794 cnx->egl.eglCreateSyncKHR);
1795 }
1796
eglDestroySyncTmpl(EGLDisplay dpy,EGLSyncKHR sync,PFNEGLDESTROYSYNCKHRPROC eglDestroySyncFunc)1797 EGLBoolean eglDestroySyncTmpl(EGLDisplay dpy, EGLSyncKHR sync,
1798 PFNEGLDESTROYSYNCKHRPROC eglDestroySyncFunc) {
1799 const egl_display_t* dp = validate_display(dpy);
1800 if (!dp) return EGL_FALSE;
1801
1802 EGLBoolean result = EGL_FALSE;
1803 egl_connection_t* const cnx = &gEGLImpl;
1804 if (cnx->dso && eglDestroySyncFunc) {
1805 result = eglDestroySyncFunc(dp->disp.dpy, sync);
1806 }
1807 return result;
1808 }
1809
eglDestroySyncKHRImpl(EGLDisplay dpy,EGLSyncKHR sync)1810 EGLBoolean eglDestroySyncKHRImpl(EGLDisplay dpy, EGLSyncKHR sync) {
1811 return eglDestroySyncTmpl(dpy, sync, gEGLImpl.egl.eglDestroySyncKHR);
1812 }
1813
eglDestroySyncImpl(EGLDisplay dpy,EGLSyncKHR sync)1814 EGLBoolean eglDestroySyncImpl(EGLDisplay dpy, EGLSyncKHR sync) {
1815 egl_connection_t* const cnx = &gEGLImpl;
1816 if (cnx->driverVersion >= EGL_MAKE_VERSION(1, 5, 0)) {
1817 if (cnx->egl.eglDestroySync) {
1818 return eglDestroySyncTmpl(dpy, sync, cnx->egl.eglDestroySync);
1819 }
1820 ALOGE("Driver indicates EGL 1.5 support, but does not have eglDestroySync");
1821 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1822 }
1823
1824 return eglDestroySyncTmpl(dpy, sync, cnx->egl.eglDestroySyncKHR);
1825 }
1826
eglSignalSyncKHRImpl(EGLDisplay dpy,EGLSyncKHR sync,EGLenum mode)1827 EGLBoolean eglSignalSyncKHRImpl(EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode) {
1828 const egl_display_t* dp = validate_display(dpy);
1829 if (!dp) return EGL_FALSE;
1830
1831 EGLBoolean result = EGL_FALSE;
1832 egl_connection_t* const cnx = &gEGLImpl;
1833 if (cnx->dso && gEGLImpl.egl.eglSignalSyncKHR) {
1834 result = gEGLImpl.egl.eglSignalSyncKHR(dp->disp.dpy, sync, mode);
1835 }
1836 return result;
1837 }
1838
eglClientWaitSyncTmpl(EGLDisplay dpy,EGLSyncKHR sync,EGLint flags,EGLTimeKHR timeout,PFNEGLCLIENTWAITSYNCKHRPROC eglClientWaitSyncFunc)1839 EGLint eglClientWaitSyncTmpl(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout,
1840 PFNEGLCLIENTWAITSYNCKHRPROC eglClientWaitSyncFunc) {
1841 const egl_display_t* dp = validate_display(dpy);
1842 if (!dp) return EGL_FALSE;
1843
1844 EGLint result = EGL_FALSE;
1845 egl_connection_t* const cnx = &gEGLImpl;
1846 if (cnx->dso && eglClientWaitSyncFunc) {
1847 result = eglClientWaitSyncFunc(dp->disp.dpy, sync, flags, timeout);
1848 }
1849 return result;
1850 }
1851
eglClientWaitSyncKHRImpl(EGLDisplay dpy,EGLSyncKHR sync,EGLint flags,EGLTimeKHR timeout)1852 EGLint eglClientWaitSyncKHRImpl(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout) {
1853 egl_connection_t* const cnx = &gEGLImpl;
1854 return eglClientWaitSyncTmpl(dpy, sync, flags, timeout, cnx->egl.eglClientWaitSyncKHR);
1855 }
1856
eglClientWaitSyncImpl(EGLDisplay dpy,EGLSync sync,EGLint flags,EGLTimeKHR timeout)1857 EGLint eglClientWaitSyncImpl(EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTimeKHR timeout) {
1858 egl_connection_t* const cnx = &gEGLImpl;
1859 if (cnx->driverVersion >= EGL_MAKE_VERSION(1, 5, 0)) {
1860 if (cnx->egl.eglClientWaitSync) {
1861 return eglClientWaitSyncTmpl(dpy, sync, flags, timeout, cnx->egl.eglClientWaitSync);
1862 }
1863 ALOGE("Driver indicates EGL 1.5 support, but does not have eglClientWaitSync");
1864 return setError(EGL_BAD_DISPLAY, (EGLint)EGL_FALSE);
1865 }
1866
1867 return eglClientWaitSyncTmpl(dpy, sync, flags, timeout, cnx->egl.eglClientWaitSyncKHR);
1868 }
1869
1870 template <typename AttrType, typename FuncType>
eglGetSyncAttribTmpl(EGLDisplay dpy,EGLSyncKHR sync,EGLint attribute,AttrType * value,FuncType eglGetSyncAttribFunc)1871 EGLBoolean eglGetSyncAttribTmpl(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, AttrType* value,
1872 FuncType eglGetSyncAttribFunc) {
1873 const egl_display_t* dp = validate_display(dpy);
1874 if (!dp) return EGL_FALSE;
1875
1876 EGLBoolean result = EGL_FALSE;
1877 egl_connection_t* const cnx = &gEGLImpl;
1878 if (cnx->dso && eglGetSyncAttribFunc) {
1879 result = eglGetSyncAttribFunc(dp->disp.dpy, sync, attribute, value);
1880 }
1881 return result;
1882 }
1883
1884 typedef EGLBoolean(EGLAPIENTRYP PFNEGLGETSYNCATTRIB)(EGLDisplay dpy, EGLSync sync, EGLint attribute,
1885 EGLAttrib* value);
1886
eglGetSyncAttribImpl(EGLDisplay dpy,EGLSync sync,EGLint attribute,EGLAttrib * value)1887 EGLBoolean eglGetSyncAttribImpl(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib* value) {
1888 egl_connection_t* const cnx = &gEGLImpl;
1889 if (cnx->driverVersion >= EGL_MAKE_VERSION(1, 5, 0)) {
1890 if (cnx->egl.eglGetSyncAttrib) {
1891 return eglGetSyncAttribTmpl<EGLAttrib, PFNEGLGETSYNCATTRIB>(dpy, sync, attribute, value,
1892 cnx->egl.eglGetSyncAttrib);
1893 }
1894 ALOGE("Driver indicates EGL 1.5 support, but does not have eglGetSyncAttrib");
1895 return setError(EGL_BAD_DISPLAY, (EGLint)EGL_FALSE);
1896 }
1897
1898 // Fallback to KHR, ask for EGLint attribute and cast back to EGLAttrib
1899 EGLint attribValue;
1900 EGLBoolean ret =
1901 eglGetSyncAttribTmpl<EGLint, PFNEGLGETSYNCATTRIBKHRPROC>(dpy, sync, attribute,
1902 &attribValue,
1903 gEGLImpl.egl
1904 .eglGetSyncAttribKHR);
1905 if (ret) {
1906 *value = static_cast<EGLAttrib>(attribValue);
1907 }
1908 return ret;
1909 }
1910
eglGetSyncAttribKHRImpl(EGLDisplay dpy,EGLSyncKHR sync,EGLint attribute,EGLint * value)1911 EGLBoolean eglGetSyncAttribKHRImpl(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute,
1912 EGLint* value) {
1913 return eglGetSyncAttribTmpl<EGLint, PFNEGLGETSYNCATTRIBKHRPROC>(dpy, sync, attribute, value,
1914 gEGLImpl.egl
1915 .eglGetSyncAttribKHR);
1916 }
1917
eglCreateStreamKHRImpl(EGLDisplay dpy,const EGLint * attrib_list)1918 EGLStreamKHR eglCreateStreamKHRImpl(EGLDisplay dpy, const EGLint* attrib_list) {
1919 const egl_display_t* dp = validate_display(dpy);
1920 if (!dp) return EGL_NO_STREAM_KHR;
1921
1922 EGLStreamKHR result = EGL_NO_STREAM_KHR;
1923 egl_connection_t* const cnx = &gEGLImpl;
1924 if (cnx->dso && cnx->egl.eglCreateStreamKHR) {
1925 result = cnx->egl.eglCreateStreamKHR(dp->disp.dpy, attrib_list);
1926 }
1927 return result;
1928 }
1929
eglDestroyStreamKHRImpl(EGLDisplay dpy,EGLStreamKHR stream)1930 EGLBoolean eglDestroyStreamKHRImpl(EGLDisplay dpy, EGLStreamKHR stream) {
1931 const egl_display_t* dp = validate_display(dpy);
1932 if (!dp) return EGL_FALSE;
1933
1934 EGLBoolean result = EGL_FALSE;
1935 egl_connection_t* const cnx = &gEGLImpl;
1936 if (cnx->dso && cnx->egl.eglDestroyStreamKHR) {
1937 result = cnx->egl.eglDestroyStreamKHR(dp->disp.dpy, stream);
1938 }
1939 return result;
1940 }
1941
eglStreamAttribKHRImpl(EGLDisplay dpy,EGLStreamKHR stream,EGLenum attribute,EGLint value)1942 EGLBoolean eglStreamAttribKHRImpl(EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute,
1943 EGLint value) {
1944 const egl_display_t* dp = validate_display(dpy);
1945 if (!dp) return EGL_FALSE;
1946
1947 EGLBoolean result = EGL_FALSE;
1948 egl_connection_t* const cnx = &gEGLImpl;
1949 if (cnx->dso && cnx->egl.eglStreamAttribKHR) {
1950 result = cnx->egl.eglStreamAttribKHR(dp->disp.dpy, stream, attribute, value);
1951 }
1952 return result;
1953 }
1954
eglQueryStreamKHRImpl(EGLDisplay dpy,EGLStreamKHR stream,EGLenum attribute,EGLint * value)1955 EGLBoolean eglQueryStreamKHRImpl(EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute,
1956 EGLint* value) {
1957 const egl_display_t* dp = validate_display(dpy);
1958 if (!dp) return EGL_FALSE;
1959
1960 EGLBoolean result = EGL_FALSE;
1961 egl_connection_t* const cnx = &gEGLImpl;
1962 if (cnx->dso && cnx->egl.eglQueryStreamKHR) {
1963 result = cnx->egl.eglQueryStreamKHR(dp->disp.dpy, stream, attribute, value);
1964 }
1965 return result;
1966 }
1967
eglQueryStreamu64KHRImpl(EGLDisplay dpy,EGLStreamKHR stream,EGLenum attribute,EGLuint64KHR * value)1968 EGLBoolean eglQueryStreamu64KHRImpl(EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute,
1969 EGLuint64KHR* value) {
1970 const egl_display_t* dp = validate_display(dpy);
1971 if (!dp) return EGL_FALSE;
1972
1973 EGLBoolean result = EGL_FALSE;
1974 egl_connection_t* const cnx = &gEGLImpl;
1975 if (cnx->dso && cnx->egl.eglQueryStreamu64KHR) {
1976 result = cnx->egl.eglQueryStreamu64KHR(dp->disp.dpy, stream, attribute, value);
1977 }
1978 return result;
1979 }
1980
eglQueryStreamTimeKHRImpl(EGLDisplay dpy,EGLStreamKHR stream,EGLenum attribute,EGLTimeKHR * value)1981 EGLBoolean eglQueryStreamTimeKHRImpl(EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute,
1982 EGLTimeKHR* value) {
1983 const egl_display_t* dp = validate_display(dpy);
1984 if (!dp) return EGL_FALSE;
1985
1986 EGLBoolean result = EGL_FALSE;
1987 egl_connection_t* const cnx = &gEGLImpl;
1988 if (cnx->dso && cnx->egl.eglQueryStreamTimeKHR) {
1989 result = cnx->egl.eglQueryStreamTimeKHR(dp->disp.dpy, stream, attribute, value);
1990 }
1991 return result;
1992 }
1993
eglCreateStreamProducerSurfaceKHRImpl(EGLDisplay dpy,EGLConfig config,EGLStreamKHR stream,const EGLint * attrib_list)1994 EGLSurface eglCreateStreamProducerSurfaceKHRImpl(EGLDisplay dpy, EGLConfig config,
1995 EGLStreamKHR stream, const EGLint* attrib_list) {
1996 egl_display_t* dp = validate_display(dpy);
1997 if (!dp) return EGL_NO_SURFACE;
1998
1999 egl_connection_t* const cnx = &gEGLImpl;
2000 if (cnx->dso && cnx->egl.eglCreateStreamProducerSurfaceKHR) {
2001 EGLSurface surface = cnx->egl.eglCreateStreamProducerSurfaceKHR(dp->disp.dpy, config,
2002 stream, attrib_list);
2003 if (surface != EGL_NO_SURFACE) {
2004 egl_surface_t* s = new egl_surface_t(dp, config, nullptr, surface,
2005 EGL_GL_COLORSPACE_LINEAR_KHR, cnx);
2006 return s;
2007 }
2008 }
2009 return EGL_NO_SURFACE;
2010 }
2011
eglStreamConsumerGLTextureExternalKHRImpl(EGLDisplay dpy,EGLStreamKHR stream)2012 EGLBoolean eglStreamConsumerGLTextureExternalKHRImpl(EGLDisplay dpy, EGLStreamKHR stream) {
2013 const egl_display_t* dp = validate_display(dpy);
2014 if (!dp) return EGL_FALSE;
2015
2016 EGLBoolean result = EGL_FALSE;
2017 egl_connection_t* const cnx = &gEGLImpl;
2018 if (cnx->dso && cnx->egl.eglStreamConsumerGLTextureExternalKHR) {
2019 result = cnx->egl.eglStreamConsumerGLTextureExternalKHR(dp->disp.dpy, stream);
2020 }
2021 return result;
2022 }
2023
eglStreamConsumerAcquireKHRImpl(EGLDisplay dpy,EGLStreamKHR stream)2024 EGLBoolean eglStreamConsumerAcquireKHRImpl(EGLDisplay dpy, EGLStreamKHR stream) {
2025 const egl_display_t* dp = validate_display(dpy);
2026 if (!dp) return EGL_FALSE;
2027
2028 EGLBoolean result = EGL_FALSE;
2029 egl_connection_t* const cnx = &gEGLImpl;
2030 if (cnx->dso && cnx->egl.eglStreamConsumerAcquireKHR) {
2031 result = cnx->egl.eglStreamConsumerAcquireKHR(dp->disp.dpy, stream);
2032 }
2033 return result;
2034 }
2035
eglStreamConsumerReleaseKHRImpl(EGLDisplay dpy,EGLStreamKHR stream)2036 EGLBoolean eglStreamConsumerReleaseKHRImpl(EGLDisplay dpy, EGLStreamKHR stream) {
2037 const egl_display_t* dp = validate_display(dpy);
2038 if (!dp) return EGL_FALSE;
2039
2040 EGLBoolean result = EGL_FALSE;
2041 egl_connection_t* const cnx = &gEGLImpl;
2042 if (cnx->dso && cnx->egl.eglStreamConsumerReleaseKHR) {
2043 result = cnx->egl.eglStreamConsumerReleaseKHR(dp->disp.dpy, stream);
2044 }
2045 return result;
2046 }
2047
eglGetStreamFileDescriptorKHRImpl(EGLDisplay dpy,EGLStreamKHR stream)2048 EGLNativeFileDescriptorKHR eglGetStreamFileDescriptorKHRImpl(EGLDisplay dpy, EGLStreamKHR stream) {
2049 const egl_display_t* dp = validate_display(dpy);
2050 if (!dp) return EGL_NO_FILE_DESCRIPTOR_KHR;
2051
2052 EGLNativeFileDescriptorKHR result = EGL_NO_FILE_DESCRIPTOR_KHR;
2053 egl_connection_t* const cnx = &gEGLImpl;
2054 if (cnx->dso && cnx->egl.eglGetStreamFileDescriptorKHR) {
2055 result = cnx->egl.eglGetStreamFileDescriptorKHR(dpy, stream);
2056 }
2057 return result;
2058 }
2059
eglCreateStreamFromFileDescriptorKHRImpl(EGLDisplay dpy,EGLNativeFileDescriptorKHR file_descriptor)2060 EGLStreamKHR eglCreateStreamFromFileDescriptorKHRImpl(EGLDisplay dpy,
2061 EGLNativeFileDescriptorKHR file_descriptor) {
2062 const egl_display_t* dp = validate_display(dpy);
2063 if (!dp) return EGL_NO_STREAM_KHR;
2064
2065 EGLStreamKHR result = EGL_NO_STREAM_KHR;
2066 egl_connection_t* const cnx = &gEGLImpl;
2067 if (cnx->dso && cnx->egl.eglCreateStreamFromFileDescriptorKHR) {
2068 result = cnx->egl.eglCreateStreamFromFileDescriptorKHR(dp->disp.dpy, file_descriptor);
2069 }
2070 return result;
2071 }
2072
2073 // ----------------------------------------------------------------------------
2074 // EGL_EGLEXT_VERSION 15
2075 // ----------------------------------------------------------------------------
2076
2077 // Need to template function type because return type is different
2078 template <typename ReturnType, typename FuncType>
eglWaitSyncTmpl(EGLDisplay dpy,EGLSyncKHR sync,EGLint flags,FuncType eglWaitSyncFunc)2079 ReturnType eglWaitSyncTmpl(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags,
2080 FuncType eglWaitSyncFunc) {
2081 const egl_display_t* dp = validate_display(dpy);
2082 if (!dp) return EGL_FALSE;
2083 ReturnType result = EGL_FALSE;
2084 egl_connection_t* const cnx = &gEGLImpl;
2085 if (cnx->dso && eglWaitSyncFunc) {
2086 result = eglWaitSyncFunc(dp->disp.dpy, sync, flags);
2087 }
2088 return result;
2089 }
2090
2091 typedef EGLBoolean(EGLAPIENTRYP PFNEGLWAITSYNC)(EGLDisplay dpy, EGLSync sync, EGLint flags);
2092
eglWaitSyncKHRImpl(EGLDisplay dpy,EGLSyncKHR sync,EGLint flags)2093 EGLint eglWaitSyncKHRImpl(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags) {
2094 egl_connection_t* const cnx = &gEGLImpl;
2095 return eglWaitSyncTmpl<EGLint, PFNEGLWAITSYNCKHRPROC>(dpy, sync, flags,
2096 cnx->egl.eglWaitSyncKHR);
2097 }
2098
eglWaitSyncImpl(EGLDisplay dpy,EGLSync sync,EGLint flags)2099 EGLBoolean eglWaitSyncImpl(EGLDisplay dpy, EGLSync sync, EGLint flags) {
2100 egl_connection_t* const cnx = &gEGLImpl;
2101 if (cnx->driverVersion >= EGL_MAKE_VERSION(1, 5, 0)) {
2102 if (cnx->egl.eglWaitSync) {
2103 return eglWaitSyncTmpl<EGLBoolean, PFNEGLWAITSYNC>(dpy, sync, flags,
2104 cnx->egl.eglWaitSync);
2105 }
2106 return setError(EGL_BAD_DISPLAY, (EGLint)EGL_FALSE);
2107 }
2108
2109 return static_cast<EGLBoolean>(
2110 eglWaitSyncTmpl<EGLint, PFNEGLWAITSYNCKHRPROC>(dpy, sync, flags,
2111 cnx->egl.eglWaitSyncKHR));
2112 }
2113
2114 // ----------------------------------------------------------------------------
2115 // ANDROID extensions
2116 // ----------------------------------------------------------------------------
2117
eglDupNativeFenceFDANDROIDImpl(EGLDisplay dpy,EGLSyncKHR sync)2118 EGLint eglDupNativeFenceFDANDROIDImpl(EGLDisplay dpy, EGLSyncKHR sync) {
2119 const egl_display_t* dp = validate_display(dpy);
2120 if (!dp) return EGL_NO_NATIVE_FENCE_FD_ANDROID;
2121
2122 EGLint result = EGL_NO_NATIVE_FENCE_FD_ANDROID;
2123 egl_connection_t* const cnx = &gEGLImpl;
2124 if (cnx->dso && cnx->egl.eglDupNativeFenceFDANDROID) {
2125 result = cnx->egl.eglDupNativeFenceFDANDROID(dp->disp.dpy, sync);
2126 }
2127 return result;
2128 }
2129
eglPresentationTimeANDROIDImpl(EGLDisplay dpy,EGLSurface surface,EGLnsecsANDROID time)2130 EGLBoolean eglPresentationTimeANDROIDImpl(EGLDisplay dpy, EGLSurface surface,
2131 EGLnsecsANDROID time) {
2132 const egl_display_t* dp = validate_display(dpy);
2133 if (!dp) {
2134 return EGL_FALSE;
2135 }
2136
2137 SurfaceRef _s(dp, surface);
2138 if (!_s.get()) {
2139 setError(EGL_BAD_SURFACE, EGL_FALSE);
2140 return EGL_FALSE;
2141 }
2142
2143 egl_surface_t const* const s = get_surface(surface);
2144 if (!s->getNativeWindow()) {
2145 setError(EGL_BAD_SURFACE, EGL_FALSE);
2146 return EGL_FALSE;
2147 }
2148 native_window_set_buffers_timestamp(s->getNativeWindow(), time);
2149
2150 return EGL_TRUE;
2151 }
2152
eglGetNativeClientBufferANDROIDImpl(const AHardwareBuffer * buffer)2153 EGLClientBuffer eglGetNativeClientBufferANDROIDImpl(const AHardwareBuffer* buffer) {
2154 if (!buffer) return setError(EGL_BAD_PARAMETER, (EGLClientBuffer) nullptr);
2155 return const_cast<ANativeWindowBuffer*>(AHardwareBuffer_to_ANativeWindowBuffer(buffer));
2156 }
2157
2158 // ----------------------------------------------------------------------------
2159 // NVIDIA extensions
2160 // ----------------------------------------------------------------------------
eglGetSystemTimeFrequencyNVImpl()2161 EGLuint64NV eglGetSystemTimeFrequencyNVImpl() {
2162 EGLuint64NV ret = 0;
2163 egl_connection_t* const cnx = &gEGLImpl;
2164
2165 if (cnx->dso && cnx->egl.eglGetSystemTimeFrequencyNV) {
2166 return cnx->egl.eglGetSystemTimeFrequencyNV();
2167 }
2168
2169 return setErrorQuiet(EGL_BAD_DISPLAY, (EGLuint64NV)0);
2170 }
2171
eglGetSystemTimeNVImpl()2172 EGLuint64NV eglGetSystemTimeNVImpl() {
2173 EGLuint64NV ret = 0;
2174 egl_connection_t* const cnx = &gEGLImpl;
2175
2176 if (cnx->dso && cnx->egl.eglGetSystemTimeNV) {
2177 return cnx->egl.eglGetSystemTimeNV();
2178 }
2179
2180 return setErrorQuiet(EGL_BAD_DISPLAY, (EGLuint64NV)0);
2181 }
2182
2183 // ----------------------------------------------------------------------------
2184 // Partial update extension
2185 // ----------------------------------------------------------------------------
eglSetDamageRegionKHRImpl(EGLDisplay dpy,EGLSurface surface,EGLint * rects,EGLint n_rects)2186 EGLBoolean eglSetDamageRegionKHRImpl(EGLDisplay dpy, EGLSurface surface, EGLint* rects,
2187 EGLint n_rects) {
2188 const egl_display_t* dp = validate_display(dpy);
2189 if (!dp) {
2190 setError(EGL_BAD_DISPLAY, EGL_FALSE);
2191 return EGL_FALSE;
2192 }
2193
2194 SurfaceRef _s(dp, surface);
2195 if (!_s.get()) {
2196 setError(EGL_BAD_SURFACE, EGL_FALSE);
2197 return EGL_FALSE;
2198 }
2199
2200 egl_surface_t const* const s = get_surface(surface);
2201 if (s->cnx->egl.eglSetDamageRegionKHR) {
2202 return s->cnx->egl.eglSetDamageRegionKHR(dp->disp.dpy, s->surface, rects, n_rects);
2203 }
2204
2205 return EGL_FALSE;
2206 }
2207
eglGetNextFrameIdANDROIDImpl(EGLDisplay dpy,EGLSurface surface,EGLuint64KHR * frameId)2208 EGLBoolean eglGetNextFrameIdANDROIDImpl(EGLDisplay dpy, EGLSurface surface, EGLuint64KHR* frameId) {
2209 const egl_display_t* dp = validate_display(dpy);
2210 if (!dp) {
2211 return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
2212 }
2213
2214 if (!dp->haveExtension("EGL_ANDROID_get_frame_timestamps")) {
2215 return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
2216 }
2217
2218 SurfaceRef _s(dp, surface);
2219 if (!_s.get()) {
2220 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
2221 }
2222
2223 egl_surface_t const* const s = get_surface(surface);
2224
2225 if (!s->getNativeWindow()) {
2226 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
2227 }
2228
2229 uint64_t nextFrameId = 0;
2230 int ret = native_window_get_next_frame_id(s->getNativeWindow(), &nextFrameId);
2231
2232 if (ret != 0) {
2233 // This should not happen. Return an error that is not in the spec
2234 // so it's obvious something is very wrong.
2235 ALOGE("eglGetNextFrameId: Unexpected error.");
2236 return setError(EGL_NOT_INITIALIZED, (EGLBoolean)EGL_FALSE);
2237 }
2238
2239 *frameId = nextFrameId;
2240 return EGL_TRUE;
2241 }
2242
eglGetCompositorTimingANDROIDImpl(EGLDisplay dpy,EGLSurface surface,EGLint numTimestamps,const EGLint * names,EGLnsecsANDROID * values)2243 EGLBoolean eglGetCompositorTimingANDROIDImpl(EGLDisplay dpy, EGLSurface surface,
2244 EGLint numTimestamps, const EGLint* names,
2245 EGLnsecsANDROID* values) {
2246 const egl_display_t* dp = validate_display(dpy);
2247 if (!dp) {
2248 return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
2249 }
2250
2251 if (!dp->haveExtension("EGL_ANDROID_get_frame_timestamps")) {
2252 return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
2253 }
2254
2255 SurfaceRef _s(dp, surface);
2256 if (!_s.get()) {
2257 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
2258 }
2259
2260 egl_surface_t const* const s = get_surface(surface);
2261
2262 if (!s->getNativeWindow()) {
2263 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
2264 }
2265
2266 nsecs_t* compositeDeadline = nullptr;
2267 nsecs_t* compositeInterval = nullptr;
2268 nsecs_t* compositeToPresentLatency = nullptr;
2269
2270 for (int i = 0; i < numTimestamps; i++) {
2271 switch (names[i]) {
2272 case EGL_COMPOSITE_DEADLINE_ANDROID:
2273 compositeDeadline = &values[i];
2274 break;
2275 case EGL_COMPOSITE_INTERVAL_ANDROID:
2276 compositeInterval = &values[i];
2277 break;
2278 case EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID:
2279 compositeToPresentLatency = &values[i];
2280 break;
2281 default:
2282 return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE);
2283 }
2284 }
2285
2286 int ret = native_window_get_compositor_timing(s->getNativeWindow(), compositeDeadline,
2287 compositeInterval, compositeToPresentLatency);
2288
2289 switch (ret) {
2290 case 0:
2291 return EGL_TRUE;
2292 case -ENOSYS:
2293 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
2294 default:
2295 // This should not happen. Return an error that is not in the spec
2296 // so it's obvious something is very wrong.
2297 ALOGE("eglGetCompositorTiming: Unexpected error.");
2298 return setError(EGL_NOT_INITIALIZED, (EGLBoolean)EGL_FALSE);
2299 }
2300 }
2301
eglGetCompositorTimingSupportedANDROIDImpl(EGLDisplay dpy,EGLSurface surface,EGLint name)2302 EGLBoolean eglGetCompositorTimingSupportedANDROIDImpl(EGLDisplay dpy, EGLSurface surface,
2303 EGLint name) {
2304 const egl_display_t* dp = validate_display(dpy);
2305 if (!dp) {
2306 return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
2307 }
2308
2309 if (!dp->haveExtension("EGL_ANDROID_get_frame_timestamps")) {
2310 return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
2311 }
2312
2313 SurfaceRef _s(dp, surface);
2314 if (!_s.get()) {
2315 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
2316 }
2317
2318 egl_surface_t const* const s = get_surface(surface);
2319
2320 ANativeWindow* window = s->getNativeWindow();
2321 if (!window) {
2322 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
2323 }
2324
2325 switch (name) {
2326 case EGL_COMPOSITE_DEADLINE_ANDROID:
2327 case EGL_COMPOSITE_INTERVAL_ANDROID:
2328 case EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID:
2329 return EGL_TRUE;
2330 default:
2331 return EGL_FALSE;
2332 }
2333 }
2334
eglGetFrameTimestampsANDROIDImpl(EGLDisplay dpy,EGLSurface surface,EGLuint64KHR frameId,EGLint numTimestamps,const EGLint * timestamps,EGLnsecsANDROID * values)2335 EGLBoolean eglGetFrameTimestampsANDROIDImpl(EGLDisplay dpy, EGLSurface surface,
2336 EGLuint64KHR frameId, EGLint numTimestamps,
2337 const EGLint* timestamps, EGLnsecsANDROID* values) {
2338 const egl_display_t* dp = validate_display(dpy);
2339 if (!dp) {
2340 return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
2341 }
2342
2343 if (!dp->haveExtension("EGL_ANDROID_get_frame_timestamps")) {
2344 return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
2345 }
2346
2347 SurfaceRef _s(dp, surface);
2348 if (!_s.get()) {
2349 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
2350 }
2351
2352 egl_surface_t const* const s = get_surface(surface);
2353
2354 if (!s->getNativeWindow()) {
2355 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
2356 }
2357
2358 nsecs_t* requestedPresentTime = nullptr;
2359 nsecs_t* acquireTime = nullptr;
2360 nsecs_t* latchTime = nullptr;
2361 nsecs_t* firstRefreshStartTime = nullptr;
2362 nsecs_t* gpuCompositionDoneTime = nullptr;
2363 nsecs_t* lastRefreshStartTime = nullptr;
2364 nsecs_t* displayPresentTime = nullptr;
2365 nsecs_t* dequeueReadyTime = nullptr;
2366 nsecs_t* releaseTime = nullptr;
2367
2368 for (int i = 0; i < numTimestamps; i++) {
2369 switch (timestamps[i]) {
2370 case EGL_REQUESTED_PRESENT_TIME_ANDROID:
2371 requestedPresentTime = &values[i];
2372 break;
2373 case EGL_RENDERING_COMPLETE_TIME_ANDROID:
2374 acquireTime = &values[i];
2375 break;
2376 case EGL_COMPOSITION_LATCH_TIME_ANDROID:
2377 latchTime = &values[i];
2378 break;
2379 case EGL_FIRST_COMPOSITION_START_TIME_ANDROID:
2380 firstRefreshStartTime = &values[i];
2381 break;
2382 case EGL_LAST_COMPOSITION_START_TIME_ANDROID:
2383 lastRefreshStartTime = &values[i];
2384 break;
2385 case EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID:
2386 gpuCompositionDoneTime = &values[i];
2387 break;
2388 case EGL_DISPLAY_PRESENT_TIME_ANDROID:
2389 displayPresentTime = &values[i];
2390 break;
2391 case EGL_DEQUEUE_READY_TIME_ANDROID:
2392 dequeueReadyTime = &values[i];
2393 break;
2394 case EGL_READS_DONE_TIME_ANDROID:
2395 releaseTime = &values[i];
2396 break;
2397 default:
2398 return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE);
2399 }
2400 }
2401
2402 int ret =
2403 native_window_get_frame_timestamps(s->getNativeWindow(), frameId, requestedPresentTime,
2404 acquireTime, latchTime, firstRefreshStartTime,
2405 lastRefreshStartTime, gpuCompositionDoneTime,
2406 displayPresentTime, dequeueReadyTime, releaseTime);
2407
2408 switch (ret) {
2409 case 0:
2410 return EGL_TRUE;
2411 case -ENOENT:
2412 return setErrorQuiet(EGL_BAD_ACCESS, (EGLBoolean)EGL_FALSE);
2413 case -ENOSYS:
2414 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
2415 case -EINVAL:
2416 return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE);
2417 default:
2418 // This should not happen. Return an error that is not in the spec
2419 // so it's obvious something is very wrong.
2420 ALOGE("eglGetFrameTimestamps: Unexpected error.");
2421 return setError(EGL_NOT_INITIALIZED, (EGLBoolean)EGL_FALSE);
2422 }
2423 }
2424
eglGetFrameTimestampSupportedANDROIDImpl(EGLDisplay dpy,EGLSurface surface,EGLint timestamp)2425 EGLBoolean eglGetFrameTimestampSupportedANDROIDImpl(EGLDisplay dpy, EGLSurface surface,
2426 EGLint timestamp) {
2427 const egl_display_t* dp = validate_display(dpy);
2428 if (!dp) {
2429 return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
2430 }
2431
2432 if (!dp->haveExtension("EGL_ANDROID_get_frame_timestamps")) {
2433 return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
2434 }
2435
2436 SurfaceRef _s(dp, surface);
2437 if (!_s.get()) {
2438 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
2439 }
2440
2441 egl_surface_t const* const s = get_surface(surface);
2442
2443 ANativeWindow* window = s->getNativeWindow();
2444 if (!window) {
2445 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
2446 }
2447
2448 switch (timestamp) {
2449 case EGL_COMPOSITE_DEADLINE_ANDROID:
2450 case EGL_COMPOSITE_INTERVAL_ANDROID:
2451 case EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID:
2452 case EGL_REQUESTED_PRESENT_TIME_ANDROID:
2453 case EGL_RENDERING_COMPLETE_TIME_ANDROID:
2454 case EGL_COMPOSITION_LATCH_TIME_ANDROID:
2455 case EGL_FIRST_COMPOSITION_START_TIME_ANDROID:
2456 case EGL_LAST_COMPOSITION_START_TIME_ANDROID:
2457 case EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID:
2458 case EGL_DEQUEUE_READY_TIME_ANDROID:
2459 case EGL_READS_DONE_TIME_ANDROID:
2460 return EGL_TRUE;
2461 case EGL_DISPLAY_PRESENT_TIME_ANDROID: {
2462 int value = 0;
2463 window->query(window, NATIVE_WINDOW_FRAME_TIMESTAMPS_SUPPORTS_PRESENT, &value);
2464 return value == 0 ? EGL_FALSE : EGL_TRUE;
2465 }
2466 default:
2467 return EGL_FALSE;
2468 }
2469 }
2470
glGetStringImpl(GLenum name)2471 const GLubyte* glGetStringImpl(GLenum name) {
2472 const GLubyte* ret = egl_get_string_for_current_context(name);
2473 if (ret == NULL) {
2474 gl_hooks_t::gl_t const* const _c = &getGlThreadSpecific()->gl;
2475 if (_c) ret = _c->glGetString(name);
2476 }
2477 return ret;
2478 }
2479
glGetStringiImpl(GLenum name,GLuint index)2480 const GLubyte* glGetStringiImpl(GLenum name, GLuint index) {
2481 const GLubyte* ret = egl_get_string_for_current_context(name, index);
2482 if (ret == NULL) {
2483 gl_hooks_t::gl_t const* const _c = &getGlThreadSpecific()->gl;
2484 if (_c) ret = _c->glGetStringi(name, index);
2485 }
2486 return ret;
2487 }
2488
glGetBooleanvImpl(GLenum pname,GLboolean * data)2489 void glGetBooleanvImpl(GLenum pname, GLboolean* data) {
2490 if (pname == GL_NUM_EXTENSIONS) {
2491 int num_exts = egl_get_num_extensions_for_current_context();
2492 if (num_exts >= 0) {
2493 *data = num_exts > 0 ? GL_TRUE : GL_FALSE;
2494 return;
2495 }
2496 }
2497
2498 gl_hooks_t::gl_t const* const _c = &getGlThreadSpecific()->gl;
2499 if (_c) _c->glGetBooleanv(pname, data);
2500 }
2501
glGetFloatvImpl(GLenum pname,GLfloat * data)2502 void glGetFloatvImpl(GLenum pname, GLfloat* data) {
2503 if (pname == GL_NUM_EXTENSIONS) {
2504 int num_exts = egl_get_num_extensions_for_current_context();
2505 if (num_exts >= 0) {
2506 *data = (GLfloat)num_exts;
2507 return;
2508 }
2509 }
2510
2511 gl_hooks_t::gl_t const* const _c = &getGlThreadSpecific()->gl;
2512 if (_c) _c->glGetFloatv(pname, data);
2513 }
2514
glGetIntegervImpl(GLenum pname,GLint * data)2515 void glGetIntegervImpl(GLenum pname, GLint* data) {
2516 if (pname == GL_NUM_EXTENSIONS) {
2517 int num_exts = egl_get_num_extensions_for_current_context();
2518 if (num_exts >= 0) {
2519 *data = (GLint)num_exts;
2520 return;
2521 }
2522 }
2523
2524 gl_hooks_t::gl_t const* const _c = &getGlThreadSpecific()->gl;
2525 if (_c) _c->glGetIntegerv(pname, data);
2526 }
2527
glGetInteger64vImpl(GLenum pname,GLint64 * data)2528 void glGetInteger64vImpl(GLenum pname, GLint64* data) {
2529 if (pname == GL_NUM_EXTENSIONS) {
2530 int num_exts = egl_get_num_extensions_for_current_context();
2531 if (num_exts >= 0) {
2532 *data = (GLint64)num_exts;
2533 return;
2534 }
2535 }
2536
2537 gl_hooks_t::gl_t const* const _c = &getGlThreadSpecific()->gl;
2538 if (_c) _c->glGetInteger64v(pname, data);
2539 }
2540
2541 struct implementation_map_t {
2542 const char* name;
2543 EGLFuncPointer address;
2544 };
2545
2546 // clang-format off
2547 static const implementation_map_t sPlatformImplMap[] = {
2548 { "eglGetDisplay", (EGLFuncPointer)&eglGetDisplayImpl },
2549 { "eglGetPlatformDisplay", (EGLFuncPointer)&eglGetPlatformDisplayImpl },
2550 { "eglInitialize", (EGLFuncPointer)&eglInitializeImpl },
2551 { "eglTerminate", (EGLFuncPointer)&eglTerminateImpl },
2552 { "eglGetConfigs", (EGLFuncPointer)&eglGetConfigsImpl },
2553 { "eglChooseConfig", (EGLFuncPointer)&eglChooseConfigImpl },
2554 { "eglGetConfigAttrib", (EGLFuncPointer)&eglGetConfigAttribImpl },
2555 { "eglCreateWindowSurface", (EGLFuncPointer)&eglCreateWindowSurfaceImpl },
2556 { "eglCreatePixmapSurface", (EGLFuncPointer)&eglCreatePixmapSurfaceImpl },
2557 { "eglCreatePlatformWindowSurface", (EGLFuncPointer)&eglCreatePlatformWindowSurfaceImpl },
2558 { "eglCreatePlatformPixmapSurface", (EGLFuncPointer)&eglCreatePlatformPixmapSurfaceImpl },
2559 { "eglCreatePbufferSurface", (EGLFuncPointer)&eglCreatePbufferSurfaceImpl },
2560 { "eglDestroySurface", (EGLFuncPointer)&eglDestroySurfaceImpl },
2561 { "eglQuerySurface", (EGLFuncPointer)&eglQuerySurfaceImpl },
2562 { "eglBeginFrame", (EGLFuncPointer)&eglBeginFrameImpl },
2563 { "eglCreateContext", (EGLFuncPointer)&eglCreateContextImpl },
2564 { "eglDestroyContext", (EGLFuncPointer)&eglDestroyContextImpl },
2565 { "eglMakeCurrent", (EGLFuncPointer)&eglMakeCurrentImpl },
2566 { "eglQueryContext", (EGLFuncPointer)&eglQueryContextImpl },
2567 { "eglGetCurrentContext", (EGLFuncPointer)&eglGetCurrentContextImpl },
2568 { "eglGetCurrentSurface", (EGLFuncPointer)&eglGetCurrentSurfaceImpl },
2569 { "eglGetCurrentDisplay", (EGLFuncPointer)&eglGetCurrentDisplayImpl },
2570 { "eglWaitGL", (EGLFuncPointer)&eglWaitGLImpl },
2571 { "eglWaitNative", (EGLFuncPointer)&eglWaitNativeImpl },
2572 { "eglGetError", (EGLFuncPointer)&eglGetErrorImpl },
2573 { "eglSwapBuffersWithDamageKHR", (EGLFuncPointer)&eglSwapBuffersWithDamageKHRImpl },
2574 { "eglGetProcAddress", (EGLFuncPointer)&eglGetProcAddressImpl },
2575 { "eglSwapBuffers", (EGLFuncPointer)&eglSwapBuffersImpl },
2576 { "eglCopyBuffers", (EGLFuncPointer)&eglCopyBuffersImpl },
2577 { "eglQueryString", (EGLFuncPointer)&eglQueryStringImpl },
2578 { "eglQueryStringImplementationANDROID", (EGLFuncPointer)&eglQueryStringImplementationANDROIDImpl },
2579 { "eglSurfaceAttrib", (EGLFuncPointer)&eglSurfaceAttribImpl },
2580 { "eglBindTexImage", (EGLFuncPointer)&eglBindTexImageImpl },
2581 { "eglReleaseTexImage", (EGLFuncPointer)&eglReleaseTexImageImpl },
2582 { "eglSwapInterval", (EGLFuncPointer)&eglSwapIntervalImpl },
2583 { "eglWaitClient", (EGLFuncPointer)&eglWaitClientImpl },
2584 { "eglBindAPI", (EGLFuncPointer)&eglBindAPIImpl },
2585 { "eglQueryAPI", (EGLFuncPointer)&eglQueryAPIImpl },
2586 { "eglReleaseThread", (EGLFuncPointer)&eglReleaseThreadImpl },
2587 { "eglCreatePbufferFromClientBuffer", (EGLFuncPointer)&eglCreatePbufferFromClientBufferImpl },
2588 { "eglLockSurfaceKHR", (EGLFuncPointer)&eglLockSurfaceKHRImpl },
2589 { "eglUnlockSurfaceKHR", (EGLFuncPointer)&eglUnlockSurfaceKHRImpl },
2590 { "eglCreateImageKHR", (EGLFuncPointer)&eglCreateImageKHRImpl },
2591 { "eglDestroyImageKHR", (EGLFuncPointer)&eglDestroyImageKHRImpl },
2592 { "eglCreateImage", (EGLFuncPointer)&eglCreateImageImpl },
2593 { "eglDestroyImage", (EGLFuncPointer)&eglDestroyImageImpl },
2594 { "eglCreateSync", (EGLFuncPointer)&eglCreateSyncImpl },
2595 { "eglDestroySync", (EGLFuncPointer)&eglDestroySyncImpl },
2596 { "eglClientWaitSync", (EGLFuncPointer)&eglClientWaitSyncImpl },
2597 { "eglGetSyncAttrib", (EGLFuncPointer)&eglGetSyncAttribImpl },
2598 { "eglCreateSyncKHR", (EGLFuncPointer)&eglCreateSyncKHRImpl },
2599 { "eglDestroySyncKHR", (EGLFuncPointer)&eglDestroySyncKHRImpl },
2600 { "eglSignalSyncKHR", (EGLFuncPointer)&eglSignalSyncKHRImpl },
2601 { "eglClientWaitSyncKHR", (EGLFuncPointer)&eglClientWaitSyncKHRImpl },
2602 { "eglGetSyncAttribKHR", (EGLFuncPointer)&eglGetSyncAttribKHRImpl },
2603 { "eglCreateStreamKHR", (EGLFuncPointer)&eglCreateStreamKHRImpl },
2604 { "eglDestroyStreamKHR", (EGLFuncPointer)&eglDestroyStreamKHRImpl },
2605 { "eglStreamAttribKHR", (EGLFuncPointer)&eglStreamAttribKHRImpl },
2606 { "eglQueryStreamKHR", (EGLFuncPointer)&eglQueryStreamKHRImpl },
2607 { "eglQueryStreamu64KHR", (EGLFuncPointer)&eglQueryStreamu64KHRImpl },
2608 { "eglQueryStreamTimeKHR", (EGLFuncPointer)&eglQueryStreamTimeKHRImpl },
2609 { "eglCreateStreamProducerSurfaceKHR", (EGLFuncPointer)&eglCreateStreamProducerSurfaceKHRImpl },
2610 { "eglStreamConsumerGLTextureExternalKHR", (EGLFuncPointer)&eglStreamConsumerGLTextureExternalKHRImpl },
2611 { "eglStreamConsumerAcquireKHR", (EGLFuncPointer)&eglStreamConsumerAcquireKHRImpl },
2612 { "eglStreamConsumerReleaseKHR", (EGLFuncPointer)&eglStreamConsumerReleaseKHRImpl },
2613 { "eglGetStreamFileDescriptorKHR", (EGLFuncPointer)&eglGetStreamFileDescriptorKHRImpl },
2614 { "eglCreateStreamFromFileDescriptorKHR", (EGLFuncPointer)&eglCreateStreamFromFileDescriptorKHRImpl },
2615 { "eglWaitSync", (EGLFuncPointer)&eglWaitSyncImpl },
2616 { "eglWaitSyncKHR", (EGLFuncPointer)&eglWaitSyncKHRImpl },
2617 { "eglDupNativeFenceFDANDROID", (EGLFuncPointer)&eglDupNativeFenceFDANDROIDImpl },
2618 { "eglPresentationTimeANDROID", (EGLFuncPointer)&eglPresentationTimeANDROIDImpl },
2619 { "eglGetNativeClientBufferANDROID", (EGLFuncPointer)&eglGetNativeClientBufferANDROIDImpl },
2620 { "eglGetSystemTimeFrequencyNV", (EGLFuncPointer)&eglGetSystemTimeFrequencyNVImpl },
2621 { "eglGetSystemTimeNV", (EGLFuncPointer)&eglGetSystemTimeNVImpl },
2622 { "eglSetDamageRegionKHR", (EGLFuncPointer)&eglSetDamageRegionKHRImpl },
2623 { "eglGetNextFrameIdANDROID", (EGLFuncPointer)&eglGetNextFrameIdANDROIDImpl },
2624 { "eglGetCompositorTimingANDROID", (EGLFuncPointer)&eglGetCompositorTimingANDROIDImpl },
2625 { "eglGetCompositorTimingSupportedANDROID", (EGLFuncPointer)&eglGetCompositorTimingSupportedANDROIDImpl },
2626 { "eglGetFrameTimestampsANDROID", (EGLFuncPointer)&eglGetFrameTimestampsANDROIDImpl },
2627 { "eglGetFrameTimestampSupportedANDROID", (EGLFuncPointer)&eglGetFrameTimestampSupportedANDROIDImpl },
2628 { "glGetString", (EGLFuncPointer)&glGetStringImpl },
2629 { "glGetStringi", (EGLFuncPointer)&glGetStringiImpl },
2630 { "glGetBooleanv", (EGLFuncPointer)&glGetBooleanvImpl },
2631 { "glGetFloatv", (EGLFuncPointer)&glGetFloatvImpl },
2632 { "glGetIntegerv", (EGLFuncPointer)&glGetIntegervImpl },
2633 { "glGetInteger64v", (EGLFuncPointer)&glGetInteger64vImpl },
2634 };
2635 // clang-format on
2636
FindPlatformImplAddr(const char * name)2637 EGLFuncPointer FindPlatformImplAddr(const char* name) {
2638 static const bool DEBUG = false;
2639
2640 if (name == nullptr) {
2641 ALOGV("FindPlatformImplAddr called with null name");
2642 return nullptr;
2643 }
2644
2645 for (int i = 0; i < NELEM(sPlatformImplMap); i++) {
2646 if (sPlatformImplMap[i].name == nullptr) {
2647 ALOGV("FindPlatformImplAddr found nullptr for sPlatformImplMap[%i].name (%s)", i, name);
2648 return nullptr;
2649 }
2650 if (!strcmp(name, sPlatformImplMap[i].name)) {
2651 ALOGV("FindPlatformImplAddr found %llu for sPlatformImplMap[%i].address (%s)",
2652 (unsigned long long)sPlatformImplMap[i].address, i, name);
2653 return sPlatformImplMap[i].address;
2654 }
2655 }
2656
2657 ALOGV("FindPlatformImplAddr did not find an entry for %s", name);
2658 return nullptr;
2659 }
2660 } // namespace android
2661