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