OSDN Git Service

Merge "Fix clang static anaylzer warnings." am: a97d58a21b am: 747d847ff1
[android-x86/frameworks-native.git] / opengl / libs / EGL / eglApi.cpp
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 <ctype.h>
20 #include <dlfcn.h>
21 #include <stdlib.h>
22 #include <string.h>
23
24 #include <hardware/gralloc1.h>
25
26 #include <EGL/egl.h>
27 #include <EGL/eglext.h>
28
29 #include <android/hardware_buffer.h>
30 #include <private/android/AHardwareBufferHelpers.h>
31
32 #include <cutils/compiler.h>
33 #include <cutils/properties.h>
34 #include <log/log.h>
35
36 #include <condition_variable>
37 #include <deque>
38 #include <mutex>
39 #include <unordered_map>
40 #include <string>
41 #include <thread>
42
43 #include "../egl_impl.h"
44
45 #include "egl_display.h"
46 #include "egl_object.h"
47 #include "egl_tls.h"
48 #include "egl_trace.h"
49
50 using namespace android;
51
52 // ----------------------------------------------------------------------------
53
54 namespace android {
55
56 using nsecs_t = int64_t;
57
58 struct extention_map_t {
59     const char* name;
60     __eglMustCastToProperFunctionPointerType address;
61 };
62
63 /*
64  * This is the list of EGL extensions exposed to applications.
65  *
66  * Some of them (gBuiltinExtensionString) are implemented entirely in this EGL
67  * wrapper and are always available.
68  *
69  * The rest (gExtensionString) depend on support in the EGL driver, and are
70  * only available if the driver supports them. However, some of these must be
71  * supported because they are used by the Android system itself; these are
72  * listed as mandatory below and are required by the CDD. The system *assumes*
73  * the mandatory extensions are present and may not function properly if some
74  * are missing.
75  *
76  * NOTE: Both strings MUST have a single space as the last character.
77  */
78
79 extern char const * const gBuiltinExtensionString;
80 extern char const * const gExtensionString;
81
82 // clang-format off
83 char const * const gBuiltinExtensionString =
84         "EGL_KHR_get_all_proc_addresses "
85         "EGL_ANDROID_presentation_time "
86         "EGL_KHR_swap_buffers_with_damage "
87         "EGL_ANDROID_get_native_client_buffer "
88         "EGL_ANDROID_front_buffer_auto_refresh "
89         "EGL_ANDROID_get_frame_timestamps "
90         "EGL_EXT_gl_colorspace_scrgb_linear "
91         "EGL_EXT_gl_colorspace_display_p3_linear "
92         "EGL_EXT_gl_colorspace_display_p3 "
93         ;
94
95 char const * const gExtensionString  =
96         "EGL_KHR_image "                        // mandatory
97         "EGL_KHR_image_base "                   // mandatory
98         "EGL_KHR_image_pixmap "
99         "EGL_KHR_lock_surface "
100         "EGL_KHR_gl_colorspace "
101         "EGL_KHR_gl_texture_2D_image "
102         "EGL_KHR_gl_texture_3D_image "
103         "EGL_KHR_gl_texture_cubemap_image "
104         "EGL_KHR_gl_renderbuffer_image "
105         "EGL_KHR_reusable_sync "
106         "EGL_KHR_fence_sync "
107         "EGL_KHR_create_context "
108         "EGL_KHR_config_attribs "
109         "EGL_KHR_surfaceless_context "
110         "EGL_KHR_stream "
111         "EGL_KHR_stream_fifo "
112         "EGL_KHR_stream_producer_eglsurface "
113         "EGL_KHR_stream_consumer_gltexture "
114         "EGL_KHR_stream_cross_process_fd "
115         "EGL_EXT_create_context_robustness "
116         "EGL_NV_system_time "
117         "EGL_ANDROID_image_native_buffer "      // mandatory
118         "EGL_KHR_wait_sync "                    // strongly recommended
119         "EGL_ANDROID_recordable "               // mandatory
120         "EGL_KHR_partial_update "               // strongly recommended
121         "EGL_EXT_pixel_format_float "
122         "EGL_EXT_buffer_age "                   // strongly recommended with partial_update
123         "EGL_KHR_create_context_no_error "
124         "EGL_KHR_mutable_render_buffer "
125         "EGL_EXT_yuv_surface "
126         "EGL_EXT_protected_content "
127         "EGL_IMG_context_priority "
128         "EGL_KHR_no_config_context "
129         ;
130 // clang-format on
131
132 // extensions not exposed to applications but used by the ANDROID system
133 //      "EGL_ANDROID_blob_cache "               // strongly recommended
134 //      "EGL_IMG_hibernate_process "            // optional
135 //      "EGL_ANDROID_native_fence_sync "        // strongly recommended
136 //      "EGL_ANDROID_framebuffer_target "       // mandatory for HWC 1.1
137 //      "EGL_ANDROID_image_crop "               // optional
138
139 /*
140  * EGL Extensions entry-points exposed to 3rd party applications
141  * (keep in sync with gExtensionString above)
142  *
143  */
144 static const extention_map_t sExtensionMap[] = {
145     // EGL_KHR_lock_surface
146     { "eglLockSurfaceKHR",
147             (__eglMustCastToProperFunctionPointerType)&eglLockSurfaceKHR },
148     { "eglUnlockSurfaceKHR",
149             (__eglMustCastToProperFunctionPointerType)&eglUnlockSurfaceKHR },
150
151     // EGL_KHR_image, EGL_KHR_image_base
152     { "eglCreateImageKHR",
153             (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR },
154     { "eglDestroyImageKHR",
155             (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR },
156
157     // EGL_KHR_reusable_sync, EGL_KHR_fence_sync
158     { "eglCreateSyncKHR",
159             (__eglMustCastToProperFunctionPointerType)&eglCreateSyncKHR },
160     { "eglDestroySyncKHR",
161             (__eglMustCastToProperFunctionPointerType)&eglDestroySyncKHR },
162     { "eglClientWaitSyncKHR",
163             (__eglMustCastToProperFunctionPointerType)&eglClientWaitSyncKHR },
164     { "eglSignalSyncKHR",
165             (__eglMustCastToProperFunctionPointerType)&eglSignalSyncKHR },
166     { "eglGetSyncAttribKHR",
167             (__eglMustCastToProperFunctionPointerType)&eglGetSyncAttribKHR },
168
169     // EGL_NV_system_time
170     { "eglGetSystemTimeFrequencyNV",
171             (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeFrequencyNV },
172     { "eglGetSystemTimeNV",
173             (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeNV },
174
175     // EGL_KHR_wait_sync
176     { "eglWaitSyncKHR",
177             (__eglMustCastToProperFunctionPointerType)&eglWaitSyncKHR },
178
179     // EGL_ANDROID_presentation_time
180     { "eglPresentationTimeANDROID",
181             (__eglMustCastToProperFunctionPointerType)&eglPresentationTimeANDROID },
182
183     // EGL_KHR_swap_buffers_with_damage
184     { "eglSwapBuffersWithDamageKHR",
185             (__eglMustCastToProperFunctionPointerType)&eglSwapBuffersWithDamageKHR },
186
187     // EGL_ANDROID_get_native_client_buffer
188     { "eglGetNativeClientBufferANDROID",
189             (__eglMustCastToProperFunctionPointerType)&eglGetNativeClientBufferANDROID },
190
191     // EGL_KHR_partial_update
192     { "eglSetDamageRegionKHR",
193             (__eglMustCastToProperFunctionPointerType)&eglSetDamageRegionKHR },
194
195     { "eglCreateStreamKHR",
196             (__eglMustCastToProperFunctionPointerType)&eglCreateStreamKHR },
197     { "eglDestroyStreamKHR",
198             (__eglMustCastToProperFunctionPointerType)&eglDestroyStreamKHR },
199     { "eglStreamAttribKHR",
200             (__eglMustCastToProperFunctionPointerType)&eglStreamAttribKHR },
201     { "eglQueryStreamKHR",
202             (__eglMustCastToProperFunctionPointerType)&eglQueryStreamKHR },
203     { "eglQueryStreamu64KHR",
204             (__eglMustCastToProperFunctionPointerType)&eglQueryStreamu64KHR },
205     { "eglQueryStreamTimeKHR",
206             (__eglMustCastToProperFunctionPointerType)&eglQueryStreamTimeKHR },
207     { "eglCreateStreamProducerSurfaceKHR",
208             (__eglMustCastToProperFunctionPointerType)&eglCreateStreamProducerSurfaceKHR },
209     { "eglStreamConsumerGLTextureExternalKHR",
210             (__eglMustCastToProperFunctionPointerType)&eglStreamConsumerGLTextureExternalKHR },
211     { "eglStreamConsumerAcquireKHR",
212             (__eglMustCastToProperFunctionPointerType)&eglStreamConsumerAcquireKHR },
213     { "eglStreamConsumerReleaseKHR",
214             (__eglMustCastToProperFunctionPointerType)&eglStreamConsumerReleaseKHR },
215     { "eglGetStreamFileDescriptorKHR",
216             (__eglMustCastToProperFunctionPointerType)&eglGetStreamFileDescriptorKHR },
217     { "eglCreateStreamFromFileDescriptorKHR",
218             (__eglMustCastToProperFunctionPointerType)&eglCreateStreamFromFileDescriptorKHR },
219
220     // EGL_ANDROID_get_frame_timestamps
221     { "eglGetNextFrameIdANDROID",
222             (__eglMustCastToProperFunctionPointerType)&eglGetNextFrameIdANDROID },
223     { "eglGetCompositorTimingANDROID",
224             (__eglMustCastToProperFunctionPointerType)&eglGetCompositorTimingANDROID },
225     { "eglGetCompositorTimingSupportedANDROID",
226             (__eglMustCastToProperFunctionPointerType)&eglGetCompositorTimingSupportedANDROID },
227     { "eglGetFrameTimestampsANDROID",
228             (__eglMustCastToProperFunctionPointerType)&eglGetFrameTimestampsANDROID },
229     { "eglGetFrameTimestampSupportedANDROID",
230             (__eglMustCastToProperFunctionPointerType)&eglGetFrameTimestampSupportedANDROID },
231
232     // EGL_ANDROID_native_fence_sync
233     { "eglDupNativeFenceFDANDROID",
234             (__eglMustCastToProperFunctionPointerType)&eglDupNativeFenceFDANDROID },
235 };
236
237 /*
238  * These extensions entry-points should not be exposed to applications.
239  * They're used internally by the Android EGL layer.
240  */
241 #define FILTER_EXTENSIONS(procname) \
242         (!strcmp((procname), "eglSetBlobCacheFuncsANDROID") ||    \
243          !strcmp((procname), "eglHibernateProcessIMG")      ||    \
244          !strcmp((procname), "eglAwakenProcessIMG"))
245
246
247
248 // accesses protected by sExtensionMapMutex
249 static std::unordered_map<std::string, __eglMustCastToProperFunctionPointerType> sGLExtentionMap;
250
251 static int sGLExtentionSlot = 0;
252 static pthread_mutex_t sExtensionMapMutex = PTHREAD_MUTEX_INITIALIZER;
253
254 static void(*findProcAddress(const char* name,
255         const extention_map_t* map, size_t n))() {
256     for (uint32_t i=0 ; i<n ; i++) {
257         if (!strcmp(name, map[i].name)) {
258             return map[i].address;
259         }
260     }
261     return NULL;
262 }
263
264 // ----------------------------------------------------------------------------
265
266 extern void setGLHooksThreadSpecific(gl_hooks_t const *value);
267 extern EGLBoolean egl_init_drivers();
268 extern const __eglMustCastToProperFunctionPointerType gExtensionForwarders[MAX_NUMBER_OF_GL_EXTENSIONS];
269 extern gl_hooks_t gHooksTrace;
270
271 } // namespace android;
272
273
274 // ----------------------------------------------------------------------------
275
276 static inline void clearError() { egl_tls_t::clearError(); }
277 static inline EGLContext getContext() { return egl_tls_t::getContext(); }
278
279 // ----------------------------------------------------------------------------
280
281 EGLDisplay eglGetDisplay(EGLNativeDisplayType display)
282 {
283     ATRACE_CALL();
284     clearError();
285
286     uintptr_t index = reinterpret_cast<uintptr_t>(display);
287     if (index >= NUM_DISPLAYS) {
288         return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
289     }
290
291     if (egl_init_drivers() == EGL_FALSE) {
292         return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
293     }
294
295     EGLDisplay dpy = egl_display_t::getFromNativeDisplay(display);
296     return dpy;
297 }
298
299 // ----------------------------------------------------------------------------
300 // Initialization
301 // ----------------------------------------------------------------------------
302
303 EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
304 {
305     clearError();
306
307     egl_display_ptr dp = get_display(dpy);
308     if (!dp) return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
309
310     EGLBoolean res = dp->initialize(major, minor);
311
312     return res;
313 }
314
315 EGLBoolean eglTerminate(EGLDisplay dpy)
316 {
317     // NOTE: don't unload the drivers b/c some APIs can be called
318     // after eglTerminate() has been called. eglTerminate() only
319     // terminates an EGLDisplay, not a EGL itself.
320
321     clearError();
322
323     egl_display_ptr dp = get_display(dpy);
324     if (!dp) return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
325
326     EGLBoolean res = dp->terminate();
327
328     return res;
329 }
330
331 // ----------------------------------------------------------------------------
332 // configuration
333 // ----------------------------------------------------------------------------
334
335 EGLBoolean eglGetConfigs(   EGLDisplay dpy,
336                             EGLConfig *configs,
337                             EGLint config_size, EGLint *num_config)
338 {
339     clearError();
340
341     const egl_display_ptr dp = validate_display(dpy);
342     if (!dp) return EGL_FALSE;
343
344     if (num_config==0) {
345         return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE);
346     }
347
348     EGLBoolean res = EGL_FALSE;
349     *num_config = 0;
350
351     egl_connection_t* const cnx = &gEGLImpl;
352     if (cnx->dso) {
353         res = cnx->egl.eglGetConfigs(
354                 dp->disp.dpy, configs, config_size, num_config);
355     }
356
357     return res;
358 }
359
360 EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list,
361                             EGLConfig *configs, EGLint config_size,
362                             EGLint *num_config)
363 {
364     clearError();
365
366     const egl_display_ptr dp = validate_display(dpy);
367     if (!dp) return EGL_FALSE;
368
369     if (num_config==0) {
370         return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE);
371     }
372
373     EGLBoolean res = EGL_FALSE;
374     *num_config = 0;
375
376     egl_connection_t* const cnx = &gEGLImpl;
377     if (cnx->dso) {
378         if (attrib_list) {
379             char value[PROPERTY_VALUE_MAX];
380             property_get("debug.egl.force_msaa", value, "false");
381
382             if (!strcmp(value, "true")) {
383                 size_t attribCount = 0;
384                 EGLint attrib = attrib_list[0];
385
386                 // Only enable MSAA if the context is OpenGL ES 2.0 and
387                 // if no caveat is requested
388                 const EGLint *attribRendererable = NULL;
389                 const EGLint *attribCaveat = NULL;
390
391                 // Count the number of attributes and look for
392                 // EGL_RENDERABLE_TYPE and EGL_CONFIG_CAVEAT
393                 while (attrib != EGL_NONE) {
394                     attrib = attrib_list[attribCount];
395                     switch (attrib) {
396                         case EGL_RENDERABLE_TYPE:
397                             attribRendererable = &attrib_list[attribCount];
398                             break;
399                         case EGL_CONFIG_CAVEAT:
400                             attribCaveat = &attrib_list[attribCount];
401                             break;
402                         default:
403                             break;
404                     }
405                     attribCount++;
406                 }
407
408                 if (attribRendererable && attribRendererable[1] == EGL_OPENGL_ES2_BIT &&
409                         (!attribCaveat || attribCaveat[1] != EGL_NONE)) {
410
411                     // Insert 2 extra attributes to force-enable MSAA 4x
412                     EGLint aaAttribs[attribCount + 4];
413                     aaAttribs[0] = EGL_SAMPLE_BUFFERS;
414                     aaAttribs[1] = 1;
415                     aaAttribs[2] = EGL_SAMPLES;
416                     aaAttribs[3] = 4;
417
418                     memcpy(&aaAttribs[4], attrib_list, attribCount * sizeof(EGLint));
419
420                     EGLint numConfigAA;
421                     EGLBoolean resAA = cnx->egl.eglChooseConfig(
422                             dp->disp.dpy, aaAttribs, configs, config_size, &numConfigAA);
423
424                     if (resAA == EGL_TRUE && numConfigAA > 0) {
425                         ALOGD("Enabling MSAA 4x");
426                         *num_config = numConfigAA;
427                         return resAA;
428                     }
429                 }
430             }
431         }
432
433         res = cnx->egl.eglChooseConfig(
434                 dp->disp.dpy, attrib_list, configs, config_size, num_config);
435     }
436     return res;
437 }
438
439 EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
440         EGLint attribute, EGLint *value)
441 {
442     clearError();
443
444     egl_connection_t* cnx = NULL;
445     const egl_display_ptr dp = validate_display_connection(dpy, cnx);
446     if (!dp) return EGL_FALSE;
447
448     return cnx->egl.eglGetConfigAttrib(
449             dp->disp.dpy, config, attribute, value);
450 }
451
452 // ----------------------------------------------------------------------------
453 // surfaces
454 // ----------------------------------------------------------------------------
455
456 // Turn linear formats into corresponding sRGB formats when colorspace is
457 // EGL_GL_COLORSPACE_SRGB_KHR, or turn sRGB formats into corresponding linear
458 // formats when colorspace is EGL_GL_COLORSPACE_LINEAR_KHR. In any cases where
459 // the modification isn't possible, the original dataSpace is returned.
460 static android_dataspace modifyBufferDataspace(android_dataspace dataSpace,
461                                                EGLint colorspace) {
462     if (colorspace == EGL_GL_COLORSPACE_LINEAR_KHR) {
463         return HAL_DATASPACE_SRGB_LINEAR;
464     } else if (colorspace == EGL_GL_COLORSPACE_SRGB_KHR) {
465         return HAL_DATASPACE_SRGB;
466     } else if (colorspace == EGL_GL_COLORSPACE_DISPLAY_P3_EXT) {
467         return HAL_DATASPACE_DISPLAY_P3;
468     } else if (colorspace == EGL_GL_COLORSPACE_DISPLAY_P3_LINEAR_EXT) {
469         return HAL_DATASPACE_DISPLAY_P3_LINEAR;
470     } else if (colorspace == EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT) {
471         return HAL_DATASPACE_V0_SCRGB_LINEAR;
472     }
473     return dataSpace;
474 }
475
476 // Return true if we stripped any EGL_GL_COLORSPACE_KHR attributes.
477 static EGLBoolean stripColorSpaceAttribute(egl_display_ptr dp, const EGLint* attrib_list,
478                                            EGLint format,
479                                            std::vector<EGLint>& stripped_attrib_list) {
480     std::vector<EGLint> allowedColorSpaces;
481     switch (format) {
482         case HAL_PIXEL_FORMAT_RGBA_8888:
483         case HAL_PIXEL_FORMAT_RGB_565:
484             // driver okay with linear & sRGB for 8888, but can't handle
485             // Display-P3 or other spaces.
486             allowedColorSpaces.push_back(EGL_GL_COLORSPACE_SRGB_KHR);
487             allowedColorSpaces.push_back(EGL_GL_COLORSPACE_LINEAR_KHR);
488             break;
489
490         case HAL_PIXEL_FORMAT_RGBA_FP16:
491         case HAL_PIXEL_FORMAT_RGBA_1010102:
492         default:
493             // driver does not want to see colorspace attributes for 1010102 or fp16.
494             // Future: if driver supports XXXX extension, we can pass down that colorspace
495             break;
496     }
497
498     bool stripped = false;
499     if (attrib_list && dp->haveExtension("EGL_KHR_gl_colorspace")) {
500         for (const EGLint* attr = attrib_list; attr[0] != EGL_NONE; attr += 2) {
501             if (attr[0] == EGL_GL_COLORSPACE_KHR) {
502                 EGLint colorSpace = attr[1];
503                 bool found = false;
504                 // Verify that color space is allowed
505                 for (auto it : allowedColorSpaces) {
506                     if (colorSpace == it) {
507                         found = true;
508                     }
509                 }
510                 if (!found) {
511                     stripped = true;
512                 } else {
513                     stripped_attrib_list.push_back(attr[0]);
514                     stripped_attrib_list.push_back(attr[1]);
515                 }
516             } else {
517                 stripped_attrib_list.push_back(attr[0]);
518                 stripped_attrib_list.push_back(attr[1]);
519             }
520         }
521     }
522     if (stripped) {
523         stripped_attrib_list.push_back(EGL_NONE);
524         stripped_attrib_list.push_back(EGL_NONE);
525     }
526     return stripped;
527 }
528
529 static EGLBoolean getColorSpaceAttribute(egl_display_ptr dp, const EGLint* attrib_list,
530                                          EGLint& colorSpace, android_dataspace& dataSpace) {
531     colorSpace = EGL_GL_COLORSPACE_LINEAR_KHR;
532     dataSpace = HAL_DATASPACE_UNKNOWN;
533     if (attrib_list && dp->haveExtension("EGL_KHR_gl_colorspace")) {
534         for (const EGLint* attr = attrib_list; *attr != EGL_NONE; attr += 2) {
535             if (*attr == EGL_GL_COLORSPACE_KHR) {
536                 colorSpace = attr[1];
537                 bool found = false;
538                 // Verify that color space is allowed
539                 if (colorSpace == EGL_GL_COLORSPACE_SRGB_KHR ||
540                     colorSpace == EGL_GL_COLORSPACE_LINEAR_KHR) {
541                     found = true;
542                 } else if (colorSpace == EGL_EXT_gl_colorspace_bt2020_linear &&
543                            dp->haveExtension("EGL_EXT_gl_colorspace_bt2020_linear")) {
544                     found = true;
545                 } else if (colorSpace == EGL_EXT_gl_colorspace_bt2020_pq &&
546                            dp->haveExtension("EGL_EXT_gl_colorspace_bt2020_pq")) {
547                     found = true;
548                 } else if (colorSpace == EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT &&
549                            dp->haveExtension("EGL_EXT_gl_colorspace_scrgb_linear")) {
550                     found = true;
551                 } else if (colorSpace == EGL_GL_COLORSPACE_DISPLAY_P3_LINEAR_EXT &&
552                            dp->haveExtension("EGL_EXT_gl_colorspace_display_p3_linear")) {
553                     found = true;
554                 } else if (colorSpace == EGL_GL_COLORSPACE_DISPLAY_P3_EXT &&
555                            dp->haveExtension("EGL_EXT_gl_colorspace_display_p3")) {
556                     found = true;
557                 }
558                 if (!found) {
559                     return false;
560                 }
561                 // Only change the dataSpace from default if the application
562                 // has explicitly set the color space with a EGL_GL_COLORSPACE_KHR attribute.
563                 dataSpace = modifyBufferDataspace(dataSpace, colorSpace);
564             }
565         }
566     }
567     return true;
568 }
569
570 void getNativePixelFormat(EGLDisplay dpy, egl_connection_t* cnx, EGLConfig config, EGLint& format) {
571     // Set the native window's buffers format to match what this config requests.
572     // Whether to use sRGB gamma is not part of the EGLconfig, but is part
573     // of our native format. So if sRGB gamma is requested, we have to
574     // modify the EGLconfig's format before setting the native window's
575     // format.
576
577     EGLint componentType = EGL_COLOR_COMPONENT_TYPE_FIXED_EXT;
578     cnx->egl.eglGetConfigAttrib(dpy, config, EGL_COLOR_COMPONENT_TYPE_EXT, &componentType);
579
580     EGLint a = 0;
581     EGLint r, g, b;
582     r = g = b = 0;
583     cnx->egl.eglGetConfigAttrib(dpy, config, EGL_RED_SIZE, &r);
584     cnx->egl.eglGetConfigAttrib(dpy, config, EGL_GREEN_SIZE, &g);
585     cnx->egl.eglGetConfigAttrib(dpy, config, EGL_BLUE_SIZE, &b);
586     cnx->egl.eglGetConfigAttrib(dpy, config, EGL_ALPHA_SIZE, &a);
587     EGLint colorDepth = r + g + b;
588
589     // Today, the driver only understands sRGB and linear on 888X
590     // formats. Strip other colorspaces from the attribute list and
591     // only use them to set the dataspace via
592     // native_window_set_buffers_dataspace
593     // if pixel format is RGBX 8888
594     //    TBD: Can test for future extensions that indicate that driver
595     //    handles requested color space and we can let it through.
596     //    allow SRGB and LINEAR. All others need to be stripped.
597     // else if 565, 4444
598     //    TBD: Can we assume these are supported if 8888 is?
599     // else if FP16 or 1010102
600     //    strip colorspace from attribs.
601     // endif
602     if (a == 0) {
603         if (colorDepth <= 16) {
604             format = HAL_PIXEL_FORMAT_RGB_565;
605         } else {
606             if (componentType == EGL_COLOR_COMPONENT_TYPE_FIXED_EXT) {
607                 if (colorDepth > 24) {
608                     format = HAL_PIXEL_FORMAT_RGBA_1010102;
609                 } else {
610                     format = HAL_PIXEL_FORMAT_RGBX_8888;
611                 }
612             } else {
613                 format = HAL_PIXEL_FORMAT_RGBA_FP16;
614             }
615         }
616     } else {
617         if (componentType == EGL_COLOR_COMPONENT_TYPE_FIXED_EXT) {
618             if (colorDepth > 24) {
619                 format = HAL_PIXEL_FORMAT_RGBA_1010102;
620             } else {
621                 format = HAL_PIXEL_FORMAT_RGBA_8888;
622             }
623         } else {
624             format = HAL_PIXEL_FORMAT_RGBA_FP16;
625         }
626     }
627 }
628
629 EGLSurface eglCreateWindowSurface(  EGLDisplay dpy, EGLConfig config,
630                                     NativeWindowType window,
631                                     const EGLint *attrib_list)
632 {
633     clearError();
634
635     egl_connection_t* cnx = NULL;
636     egl_display_ptr dp = validate_display_connection(dpy, cnx);
637     if (dp) {
638         EGLDisplay iDpy = dp->disp.dpy;
639
640         if (!window) {
641             return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
642         }
643
644         int value = 0;
645         window->query(window, NATIVE_WINDOW_IS_VALID, &value);
646         if (!value) {
647             return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
648         }
649
650         int result = native_window_api_connect(window, NATIVE_WINDOW_API_EGL);
651         if (result < 0) {
652             ALOGE("eglCreateWindowSurface: native_window_api_connect (win=%p) "
653                     "failed (%#x) (already connected to another API?)",
654                     window, result);
655             return setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
656         }
657
658         EGLint format;
659         getNativePixelFormat(iDpy, cnx, config, format);
660
661         // now select correct colorspace and dataspace based on user's attribute list
662         EGLint colorSpace;
663         android_dataspace dataSpace;
664         if (!getColorSpaceAttribute(dp, attrib_list, colorSpace, dataSpace)) {
665             ALOGE("error invalid colorspace: %d", colorSpace);
666             return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
667         }
668
669         std::vector<EGLint> strippedAttribList;
670         if (stripColorSpaceAttribute(dp, attrib_list, format, strippedAttribList)) {
671             // Had to modify the attribute list due to use of color space.
672             // Use modified list from here on.
673             attrib_list = strippedAttribList.data();
674         }
675
676         if (format != 0) {
677             int err = native_window_set_buffers_format(window, format);
678             if (err != 0) {
679                 ALOGE("error setting native window pixel format: %s (%d)",
680                         strerror(-err), err);
681                 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
682                 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
683             }
684         }
685
686         if (dataSpace != 0) {
687             int err = native_window_set_buffers_data_space(window, dataSpace);
688             if (err != 0) {
689                 ALOGE("error setting native window pixel dataSpace: %s (%d)",
690                         strerror(-err), err);
691                 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
692                 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
693             }
694         }
695
696         // the EGL spec requires that a new EGLSurface default to swap interval
697         // 1, so explicitly set that on the window here.
698         ANativeWindow* anw = reinterpret_cast<ANativeWindow*>(window);
699         anw->setSwapInterval(anw, 1);
700
701         EGLSurface surface = cnx->egl.eglCreateWindowSurface(
702                 iDpy, config, window, attrib_list);
703         if (surface != EGL_NO_SURFACE) {
704             egl_surface_t* s =
705                     new egl_surface_t(dp.get(), config, window, surface, colorSpace, cnx);
706             return s;
707         }
708
709         // EGLSurface creation failed
710         native_window_set_buffers_format(window, 0);
711         native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
712     }
713     return EGL_NO_SURFACE;
714 }
715
716 EGLSurface eglCreatePixmapSurface(  EGLDisplay dpy, EGLConfig config,
717                                     NativePixmapType pixmap,
718                                     const EGLint *attrib_list)
719 {
720     clearError();
721
722     egl_connection_t* cnx = NULL;
723     egl_display_ptr dp = validate_display_connection(dpy, cnx);
724     EGLint colorSpace;
725     android_dataspace dataSpace;
726     if (dp) {
727         // now select a corresponding sRGB format if needed
728         if (!getColorSpaceAttribute(dp, attrib_list, colorSpace, dataSpace)) {
729             ALOGE("error invalid colorspace: %d", colorSpace);
730             return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
731         }
732
733         EGLSurface surface = cnx->egl.eglCreatePixmapSurface(
734                 dp->disp.dpy, config, pixmap, attrib_list);
735         if (surface != EGL_NO_SURFACE) {
736             egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL, surface, colorSpace, cnx);
737             return s;
738         }
739     }
740     return EGL_NO_SURFACE;
741 }
742
743 EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config,
744                                     const EGLint *attrib_list)
745 {
746     clearError();
747
748     egl_connection_t* cnx = NULL;
749     egl_display_ptr dp = validate_display_connection(dpy, cnx);
750     if (dp) {
751         EGLDisplay iDpy = dp->disp.dpy;
752         EGLint format;
753         getNativePixelFormat(iDpy, cnx, config, format);
754
755         // now select correct colorspace and dataspace based on user's attribute list
756         EGLint colorSpace;
757         android_dataspace dataSpace;
758         if (!getColorSpaceAttribute(dp, attrib_list, colorSpace, dataSpace)) {
759             ALOGE("error invalid colorspace: %d", colorSpace);
760             return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
761         }
762
763         // Pbuffers are not displayed so we don't need to store the
764         // colorspace. We do need to filter out color spaces the
765         // driver doesn't know how to process.
766         std::vector<EGLint> strippedAttribList;
767         if (stripColorSpaceAttribute(dp, attrib_list, format, strippedAttribList)) {
768             // Had to modify the attribute list due to use of color space.
769             // Use modified list from here on.
770             attrib_list = strippedAttribList.data();
771         }
772
773         EGLSurface surface = cnx->egl.eglCreatePbufferSurface(
774                 dp->disp.dpy, config, attrib_list);
775         if (surface != EGL_NO_SURFACE) {
776             egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL, surface, colorSpace, cnx);
777             return s;
778         }
779     }
780     return EGL_NO_SURFACE;
781 }
782
783 EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
784 {
785     clearError();
786
787     const egl_display_ptr dp = validate_display(dpy);
788     if (!dp) return EGL_FALSE;
789
790     SurfaceRef _s(dp.get(), surface);
791     if (!_s.get())
792         return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
793
794     egl_surface_t * const s = get_surface(surface);
795     EGLBoolean result = s->cnx->egl.eglDestroySurface(dp->disp.dpy, s->surface);
796     if (result == EGL_TRUE) {
797         _s.terminate();
798     }
799     return result;
800 }
801
802 EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface,
803                             EGLint attribute, EGLint *value)
804 {
805     clearError();
806
807     const egl_display_ptr dp = validate_display(dpy);
808     if (!dp) return EGL_FALSE;
809
810     SurfaceRef _s(dp.get(), surface);
811     if (!_s.get())
812         return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
813
814     egl_surface_t const * const s = get_surface(surface);
815     if (attribute == EGL_GL_COLORSPACE_KHR) {
816         *value = s->getColorSpace();
817         return EGL_TRUE;
818     }
819     return s->cnx->egl.eglQuerySurface(
820             dp->disp.dpy, s->surface, attribute, value);
821 }
822
823 void EGLAPI eglBeginFrame(EGLDisplay dpy, EGLSurface surface) {
824     ATRACE_CALL();
825     clearError();
826
827     const egl_display_ptr dp = validate_display(dpy);
828     if (!dp) {
829         return;
830     }
831
832     SurfaceRef _s(dp.get(), surface);
833     if (!_s.get()) {
834         setError(EGL_BAD_SURFACE, EGL_FALSE);
835     }
836 }
837
838 // ----------------------------------------------------------------------------
839 // Contexts
840 // ----------------------------------------------------------------------------
841
842 EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config,
843                             EGLContext share_list, const EGLint *attrib_list)
844 {
845     clearError();
846
847     egl_connection_t* cnx = NULL;
848     const egl_display_ptr dp = validate_display_connection(dpy, cnx);
849     if (dp) {
850         if (share_list != EGL_NO_CONTEXT) {
851             if (!ContextRef(dp.get(), share_list).get()) {
852                 return setError(EGL_BAD_CONTEXT, EGL_NO_CONTEXT);
853             }
854             egl_context_t* const c = get_context(share_list);
855             share_list = c->context;
856         }
857         EGLContext context = cnx->egl.eglCreateContext(
858                 dp->disp.dpy, config, share_list, attrib_list);
859         if (context != EGL_NO_CONTEXT) {
860             // figure out if it's a GLESv1 or GLESv2
861             int version = 0;
862             if (attrib_list) {
863                 while (*attrib_list != EGL_NONE) {
864                     GLint attr = *attrib_list++;
865                     GLint value = *attrib_list++;
866                     if (attr == EGL_CONTEXT_CLIENT_VERSION) {
867                         if (value == 1) {
868                             version = egl_connection_t::GLESv1_INDEX;
869                         } else if (value == 2 || value == 3) {
870                             version = egl_connection_t::GLESv2_INDEX;
871                         }
872                     }
873                 };
874             }
875             egl_context_t* c = new egl_context_t(dpy, context, config, cnx,
876                     version);
877             return c;
878         }
879     }
880     return EGL_NO_CONTEXT;
881 }
882
883 EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
884 {
885     clearError();
886
887     const egl_display_ptr dp = validate_display(dpy);
888     if (!dp)
889         return EGL_FALSE;
890
891     ContextRef _c(dp.get(), ctx);
892     if (!_c.get())
893         return setError(EGL_BAD_CONTEXT, (EGLBoolean)EGL_FALSE);
894
895     egl_context_t * const c = get_context(ctx);
896     EGLBoolean result = c->cnx->egl.eglDestroyContext(dp->disp.dpy, c->context);
897     if (result == EGL_TRUE) {
898         _c.terminate();
899     }
900     return result;
901 }
902
903 EGLBoolean eglMakeCurrent(  EGLDisplay dpy, EGLSurface draw,
904                             EGLSurface read, EGLContext ctx)
905 {
906     clearError();
907
908     egl_display_ptr dp = validate_display(dpy);
909     if (!dp) return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
910
911     // If ctx is not EGL_NO_CONTEXT, read is not EGL_NO_SURFACE, or draw is not
912     // EGL_NO_SURFACE, then an EGL_NOT_INITIALIZED error is generated if dpy is
913     // a valid but uninitialized display.
914     if ( (ctx != EGL_NO_CONTEXT) || (read != EGL_NO_SURFACE) ||
915          (draw != EGL_NO_SURFACE) ) {
916         if (!dp->isReady()) return setError(EGL_NOT_INITIALIZED, (EGLBoolean)EGL_FALSE);
917     }
918
919     // get a reference to the object passed in
920     ContextRef _c(dp.get(), ctx);
921     SurfaceRef _d(dp.get(), draw);
922     SurfaceRef _r(dp.get(), read);
923
924     // validate the context (if not EGL_NO_CONTEXT)
925     if ((ctx != EGL_NO_CONTEXT) && !_c.get()) {
926         // EGL_NO_CONTEXT is valid
927         return setError(EGL_BAD_CONTEXT, (EGLBoolean)EGL_FALSE);
928     }
929
930     // these are the underlying implementation's object
931     EGLContext impl_ctx  = EGL_NO_CONTEXT;
932     EGLSurface impl_draw = EGL_NO_SURFACE;
933     EGLSurface impl_read = EGL_NO_SURFACE;
934
935     // these are our objects structs passed in
936     egl_context_t       * c = NULL;
937     egl_surface_t const * d = NULL;
938     egl_surface_t const * r = NULL;
939
940     // these are the current objects structs
941     egl_context_t * cur_c = get_context(getContext());
942
943     if (ctx != EGL_NO_CONTEXT) {
944         c = get_context(ctx);
945         impl_ctx = c->context;
946     } else {
947         // no context given, use the implementation of the current context
948         if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) {
949             // calling eglMakeCurrent( ..., !=0, !=0, EGL_NO_CONTEXT);
950             return setError(EGL_BAD_MATCH, (EGLBoolean)EGL_FALSE);
951         }
952         if (cur_c == NULL) {
953             // no current context
954             // not an error, there is just no current context.
955             return EGL_TRUE;
956         }
957     }
958
959     // retrieve the underlying implementation's draw EGLSurface
960     if (draw != EGL_NO_SURFACE) {
961         if (!_d.get()) return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
962         d = get_surface(draw);
963         impl_draw = d->surface;
964     }
965
966     // retrieve the underlying implementation's read EGLSurface
967     if (read != EGL_NO_SURFACE) {
968         if (!_r.get()) return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
969         r = get_surface(read);
970         impl_read = r->surface;
971     }
972
973
974     EGLBoolean result = dp->makeCurrent(c, cur_c,
975             draw, read, ctx,
976             impl_draw, impl_read, impl_ctx);
977
978     if (result == EGL_TRUE) {
979         if (c) {
980             setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
981             egl_tls_t::setContext(ctx);
982             _c.acquire();
983             _r.acquire();
984             _d.acquire();
985         } else {
986             setGLHooksThreadSpecific(&gHooksNoContext);
987             egl_tls_t::setContext(EGL_NO_CONTEXT);
988         }
989     } else {
990
991         if (cur_c != NULL) {
992             // Force return to current context for drivers that cannot handle errors
993             EGLBoolean restore_result = EGL_FALSE;
994             // get a reference to the old current objects
995             ContextRef _c2(dp.get(), cur_c);
996             SurfaceRef _d2(dp.get(), cur_c->draw);
997             SurfaceRef _r2(dp.get(), cur_c->read);
998
999             c = cur_c;
1000             impl_ctx = c->context;
1001             impl_draw = EGL_NO_SURFACE;
1002             if (cur_c->draw != EGL_NO_SURFACE) {
1003                 d = get_surface(cur_c->draw);
1004                 impl_draw = d->surface;
1005             }
1006             impl_read = EGL_NO_SURFACE;
1007             if (cur_c->read != EGL_NO_SURFACE) {
1008                 r = get_surface(cur_c->read);
1009                 impl_read = r->surface;
1010             }
1011             restore_result = dp->makeCurrent(c, cur_c,
1012                     cur_c->draw, cur_c->read, cur_c->context,
1013                     impl_draw, impl_read, impl_ctx);
1014             if (restore_result == EGL_TRUE) {
1015                 _c2.acquire();
1016                 _r2.acquire();
1017                 _d2.acquire();
1018             } else {
1019                 ALOGE("Could not restore original EGL context");
1020             }
1021         }
1022         // this will ALOGE the error
1023         egl_connection_t* const cnx = &gEGLImpl;
1024         result = setError(cnx->egl.eglGetError(), (EGLBoolean)EGL_FALSE);
1025     }
1026     return result;
1027 }
1028
1029
1030 EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx,
1031                             EGLint attribute, EGLint *value)
1032 {
1033     clearError();
1034
1035     const egl_display_ptr dp = validate_display(dpy);
1036     if (!dp) return EGL_FALSE;
1037
1038     ContextRef _c(dp.get(), ctx);
1039     if (!_c.get()) return setError(EGL_BAD_CONTEXT, (EGLBoolean)EGL_FALSE);
1040
1041     egl_context_t * const c = get_context(ctx);
1042     return c->cnx->egl.eglQueryContext(
1043             dp->disp.dpy, c->context, attribute, value);
1044
1045 }
1046
1047 EGLContext eglGetCurrentContext(void)
1048 {
1049     // could be called before eglInitialize(), but we wouldn't have a context
1050     // then, and this function would correctly return EGL_NO_CONTEXT.
1051
1052     clearError();
1053
1054     EGLContext ctx = getContext();
1055     return ctx;
1056 }
1057
1058 EGLSurface eglGetCurrentSurface(EGLint readdraw)
1059 {
1060     // could be called before eglInitialize(), but we wouldn't have a context
1061     // then, and this function would correctly return EGL_NO_SURFACE.
1062
1063     clearError();
1064
1065     EGLContext ctx = getContext();
1066     if (ctx) {
1067         egl_context_t const * const c = get_context(ctx);
1068         if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
1069         switch (readdraw) {
1070             case EGL_READ: return c->read;
1071             case EGL_DRAW: return c->draw;
1072             default: return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
1073         }
1074     }
1075     return EGL_NO_SURFACE;
1076 }
1077
1078 EGLDisplay eglGetCurrentDisplay(void)
1079 {
1080     // could be called before eglInitialize(), but we wouldn't have a context
1081     // then, and this function would correctly return EGL_NO_DISPLAY.
1082
1083     clearError();
1084
1085     EGLContext ctx = getContext();
1086     if (ctx) {
1087         egl_context_t const * const c = get_context(ctx);
1088         if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
1089         return c->dpy;
1090     }
1091     return EGL_NO_DISPLAY;
1092 }
1093
1094 EGLBoolean eglWaitGL(void)
1095 {
1096     clearError();
1097
1098     egl_connection_t* const cnx = &gEGLImpl;
1099     if (!cnx->dso)
1100         return setError(EGL_BAD_CONTEXT, (EGLBoolean)EGL_FALSE);
1101
1102     return cnx->egl.eglWaitGL();
1103 }
1104
1105 EGLBoolean eglWaitNative(EGLint engine)
1106 {
1107     clearError();
1108
1109     egl_connection_t* const cnx = &gEGLImpl;
1110     if (!cnx->dso)
1111         return setError(EGL_BAD_CONTEXT, (EGLBoolean)EGL_FALSE);
1112
1113     return cnx->egl.eglWaitNative(engine);
1114 }
1115
1116 EGLint eglGetError(void)
1117 {
1118     EGLint err = EGL_SUCCESS;
1119     egl_connection_t* const cnx = &gEGLImpl;
1120     if (cnx->dso) {
1121         err = cnx->egl.eglGetError();
1122     }
1123     if (err == EGL_SUCCESS) {
1124         err = egl_tls_t::getError();
1125     }
1126     return err;
1127 }
1128
1129 static __eglMustCastToProperFunctionPointerType findBuiltinWrapper(
1130         const char* procname) {
1131     const egl_connection_t* cnx = &gEGLImpl;
1132     void* proc = NULL;
1133
1134     proc = dlsym(cnx->libEgl, procname);
1135     if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
1136
1137     proc = dlsym(cnx->libGles2, procname);
1138     if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
1139
1140     proc = dlsym(cnx->libGles1, procname);
1141     if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
1142
1143     return NULL;
1144 }
1145
1146 __eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
1147 {
1148     // eglGetProcAddress() could be the very first function called
1149     // in which case we must make sure we've initialized ourselves, this
1150     // happens the first time egl_get_display() is called.
1151
1152     clearError();
1153
1154     if (egl_init_drivers() == EGL_FALSE) {
1155         setError(EGL_BAD_PARAMETER, NULL);
1156         return  NULL;
1157     }
1158
1159     if (FILTER_EXTENSIONS(procname)) {
1160         return NULL;
1161     }
1162
1163     __eglMustCastToProperFunctionPointerType addr;
1164     addr = findProcAddress(procname, sExtensionMap, NELEM(sExtensionMap));
1165     if (addr) return addr;
1166
1167     addr = findBuiltinWrapper(procname);
1168     if (addr) return addr;
1169
1170     // this protects accesses to sGLExtentionMap and sGLExtentionSlot
1171     pthread_mutex_lock(&sExtensionMapMutex);
1172
1173         /*
1174          * Since eglGetProcAddress() is not associated to anything, it needs
1175          * to return a function pointer that "works" regardless of what
1176          * the current context is.
1177          *
1178          * For this reason, we return a "forwarder", a small stub that takes
1179          * care of calling the function associated with the context
1180          * currently bound.
1181          *
1182          * We first look for extensions we've already resolved, if we're seeing
1183          * this extension for the first time, we go through all our
1184          * implementations and call eglGetProcAddress() and record the
1185          * result in the appropriate implementation hooks and return the
1186          * address of the forwarder corresponding to that hook set.
1187          *
1188          */
1189
1190         const std::string name(procname);
1191
1192     auto& extentionMap = sGLExtentionMap;
1193     auto pos = extentionMap.find(name);
1194         addr = (pos != extentionMap.end()) ? pos->second : nullptr;
1195         const int slot = sGLExtentionSlot;
1196
1197         ALOGE_IF(slot >= MAX_NUMBER_OF_GL_EXTENSIONS,
1198                 "no more slots for eglGetProcAddress(\"%s\")",
1199                 procname);
1200
1201         if (!addr && (slot < MAX_NUMBER_OF_GL_EXTENSIONS)) {
1202             bool found = false;
1203
1204             egl_connection_t* const cnx = &gEGLImpl;
1205             if (cnx->dso && cnx->egl.eglGetProcAddress) {
1206                 // Extensions are independent of the bound context
1207                 addr =
1208                 cnx->hooks[egl_connection_t::GLESv1_INDEX]->ext.extensions[slot] =
1209                 cnx->hooks[egl_connection_t::GLESv2_INDEX]->ext.extensions[slot] =
1210                         cnx->egl.eglGetProcAddress(procname);
1211                 if (addr) found = true;
1212             }
1213
1214             if (found) {
1215                 addr = gExtensionForwarders[slot];
1216                 extentionMap[name] = addr;
1217                 sGLExtentionSlot++;
1218             }
1219         }
1220
1221     pthread_mutex_unlock(&sExtensionMapMutex);
1222     return addr;
1223 }
1224
1225 class FrameCompletionThread {
1226 public:
1227
1228     static void queueSync(EGLSyncKHR sync) {
1229         static FrameCompletionThread thread;
1230
1231         char name[64];
1232
1233         std::lock_guard<std::mutex> lock(thread.mMutex);
1234         snprintf(name, sizeof(name), "kicked off frame %u", (unsigned int)thread.mFramesQueued);
1235         ATRACE_NAME(name);
1236
1237         thread.mQueue.push_back(sync);
1238         thread.mCondition.notify_one();
1239         thread.mFramesQueued++;
1240         ATRACE_INT("GPU Frames Outstanding", int32_t(thread.mQueue.size()));
1241     }
1242
1243 private:
1244
1245     FrameCompletionThread() : mFramesQueued(0), mFramesCompleted(0) {
1246         std::thread thread(&FrameCompletionThread::loop, this);
1247         thread.detach();
1248     }
1249
1250 #pragma clang diagnostic push
1251 #pragma clang diagnostic ignored "-Wmissing-noreturn"
1252     void loop() {
1253         while (true) {
1254             threadLoop();
1255         }
1256     }
1257 #pragma clang diagnostic pop
1258
1259     void threadLoop() {
1260         EGLSyncKHR sync;
1261         uint32_t frameNum;
1262         {
1263             std::unique_lock<std::mutex> lock(mMutex);
1264             while (mQueue.empty()) {
1265                 mCondition.wait(lock);
1266             }
1267             sync = mQueue[0];
1268             frameNum = mFramesCompleted;
1269         }
1270         EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
1271         {
1272             char name[64];
1273             snprintf(name, sizeof(name), "waiting for frame %u", (unsigned int)frameNum);
1274             ATRACE_NAME(name);
1275
1276             EGLint result = eglClientWaitSyncKHR(dpy, sync, 0, EGL_FOREVER_KHR);
1277             if (result == EGL_FALSE) {
1278                 ALOGE("FrameCompletion: error waiting for fence: %#x", eglGetError());
1279             } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
1280                 ALOGE("FrameCompletion: timeout waiting for fence");
1281             }
1282             eglDestroySyncKHR(dpy, sync);
1283         }
1284         {
1285             std::lock_guard<std::mutex> lock(mMutex);
1286             mQueue.pop_front();
1287             mFramesCompleted++;
1288             ATRACE_INT("GPU Frames Outstanding", int32_t(mQueue.size()));
1289         }
1290     }
1291
1292     uint32_t mFramesQueued;
1293     uint32_t mFramesCompleted;
1294     std::deque<EGLSyncKHR> mQueue;
1295     std::condition_variable mCondition;
1296     std::mutex mMutex;
1297 };
1298
1299 EGLBoolean eglSwapBuffersWithDamageKHR(EGLDisplay dpy, EGLSurface draw,
1300         EGLint *rects, EGLint n_rects)
1301 {
1302     ATRACE_CALL();
1303     clearError();
1304
1305     const egl_display_ptr dp = validate_display(dpy);
1306     if (!dp) return EGL_FALSE;
1307
1308     SurfaceRef _s(dp.get(), draw);
1309     if (!_s.get())
1310         return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
1311
1312     egl_surface_t const * const s = get_surface(draw);
1313
1314     if (CC_UNLIKELY(dp->traceGpuCompletion)) {
1315         EGLSyncKHR sync = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, NULL);
1316         if (sync != EGL_NO_SYNC_KHR) {
1317             FrameCompletionThread::queueSync(sync);
1318         }
1319     }
1320
1321     if (CC_UNLIKELY(dp->finishOnSwap)) {
1322         uint32_t pixel;
1323         egl_context_t * const c = get_context( egl_tls_t::getContext() );
1324         if (c) {
1325             // glReadPixels() ensures that the frame is complete
1326             s->cnx->hooks[c->version]->gl.glReadPixels(0,0,1,1,
1327                     GL_RGBA,GL_UNSIGNED_BYTE,&pixel);
1328         }
1329     }
1330
1331     if (n_rects == 0) {
1332         return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface);
1333     }
1334
1335     std::vector<android_native_rect_t> androidRects((size_t)n_rects);
1336     for (int r = 0; r < n_rects; ++r) {
1337         int offset = r * 4;
1338         int x = rects[offset];
1339         int y = rects[offset + 1];
1340         int width = rects[offset + 2];
1341         int height = rects[offset + 3];
1342         android_native_rect_t androidRect;
1343         androidRect.left = x;
1344         androidRect.top = y + height;
1345         androidRect.right = x + width;
1346         androidRect.bottom = y;
1347         androidRects.push_back(androidRect);
1348     }
1349     native_window_set_surface_damage(s->getNativeWindow(), androidRects.data(), androidRects.size());
1350
1351     if (s->cnx->egl.eglSwapBuffersWithDamageKHR) {
1352         return s->cnx->egl.eglSwapBuffersWithDamageKHR(dp->disp.dpy, s->surface,
1353                 rects, n_rects);
1354     } else {
1355         return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface);
1356     }
1357 }
1358
1359 EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
1360 {
1361     return eglSwapBuffersWithDamageKHR(dpy, surface, NULL, 0);
1362 }
1363
1364 EGLBoolean eglCopyBuffers(  EGLDisplay dpy, EGLSurface surface,
1365                             NativePixmapType target)
1366 {
1367     clearError();
1368
1369     const egl_display_ptr dp = validate_display(dpy);
1370     if (!dp) return EGL_FALSE;
1371
1372     SurfaceRef _s(dp.get(), surface);
1373     if (!_s.get())
1374         return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
1375
1376     egl_surface_t const * const s = get_surface(surface);
1377     return s->cnx->egl.eglCopyBuffers(dp->disp.dpy, s->surface, target);
1378 }
1379
1380 const char* eglQueryString(EGLDisplay dpy, EGLint name)
1381 {
1382     clearError();
1383
1384     // Generate an error quietly when client extensions (as defined by
1385     // EGL_EXT_client_extensions) are queried.  We do not want to rely on
1386     // validate_display to generate the error as validate_display would log
1387     // the error, which can be misleading.
1388     //
1389     // If we want to support EGL_EXT_client_extensions later, we can return
1390     // the client extension string here instead.
1391     if (dpy == EGL_NO_DISPLAY && name == EGL_EXTENSIONS)
1392         return setErrorQuiet(EGL_BAD_DISPLAY, (const char*)0);
1393
1394     const egl_display_ptr dp = validate_display(dpy);
1395     if (!dp) return (const char *) NULL;
1396
1397     switch (name) {
1398         case EGL_VENDOR:
1399             return dp->getVendorString();
1400         case EGL_VERSION:
1401             return dp->getVersionString();
1402         case EGL_EXTENSIONS:
1403             return dp->getExtensionString();
1404         case EGL_CLIENT_APIS:
1405             return dp->getClientApiString();
1406         default:
1407             break;
1408     }
1409     return setError(EGL_BAD_PARAMETER, (const char *)0);
1410 }
1411
1412 EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name)
1413 {
1414     clearError();
1415
1416     const egl_display_ptr dp = validate_display(dpy);
1417     if (!dp) return (const char *) NULL;
1418
1419     switch (name) {
1420         case EGL_VENDOR:
1421             return dp->disp.queryString.vendor;
1422         case EGL_VERSION:
1423             return dp->disp.queryString.version;
1424         case EGL_EXTENSIONS:
1425             return dp->disp.queryString.extensions;
1426         case EGL_CLIENT_APIS:
1427             return dp->disp.queryString.clientApi;
1428         default:
1429             break;
1430     }
1431     return setError(EGL_BAD_PARAMETER, (const char *)0);
1432 }
1433
1434 // ----------------------------------------------------------------------------
1435 // EGL 1.1
1436 // ----------------------------------------------------------------------------
1437
1438 EGLBoolean eglSurfaceAttrib(
1439         EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
1440 {
1441     clearError();
1442
1443     const egl_display_ptr dp = validate_display(dpy);
1444     if (!dp) return EGL_FALSE;
1445
1446     SurfaceRef _s(dp.get(), surface);
1447     if (!_s.get())
1448         return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
1449
1450     egl_surface_t * const s = get_surface(surface);
1451
1452     if (attribute == EGL_FRONT_BUFFER_AUTO_REFRESH_ANDROID) {
1453         if (!s->getNativeWindow()) {
1454             setError(EGL_BAD_SURFACE, EGL_FALSE);
1455         }
1456         int err = native_window_set_auto_refresh(s->getNativeWindow(), value != 0);
1457         return (err == 0) ? EGL_TRUE : setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
1458     }
1459
1460     if (attribute == EGL_TIMESTAMPS_ANDROID) {
1461         if (!s->getNativeWindow()) {
1462             return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
1463         }
1464         int err = native_window_enable_frame_timestamps(s->getNativeWindow(), value != 0);
1465         return (err == 0) ? EGL_TRUE : setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
1466     }
1467
1468     if (s->cnx->egl.eglSurfaceAttrib) {
1469         return s->cnx->egl.eglSurfaceAttrib(
1470                 dp->disp.dpy, s->surface, attribute, value);
1471     }
1472     return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
1473 }
1474
1475 EGLBoolean eglBindTexImage(
1476         EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1477 {
1478     clearError();
1479
1480     const egl_display_ptr dp = validate_display(dpy);
1481     if (!dp) return EGL_FALSE;
1482
1483     SurfaceRef _s(dp.get(), surface);
1484     if (!_s.get())
1485         return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
1486
1487     egl_surface_t const * const s = get_surface(surface);
1488     if (s->cnx->egl.eglBindTexImage) {
1489         return s->cnx->egl.eglBindTexImage(
1490                 dp->disp.dpy, s->surface, buffer);
1491     }
1492     return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
1493 }
1494
1495 EGLBoolean eglReleaseTexImage(
1496         EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1497 {
1498     clearError();
1499
1500     const egl_display_ptr dp = validate_display(dpy);
1501     if (!dp) return EGL_FALSE;
1502
1503     SurfaceRef _s(dp.get(), surface);
1504     if (!_s.get())
1505         return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
1506
1507     egl_surface_t const * const s = get_surface(surface);
1508     if (s->cnx->egl.eglReleaseTexImage) {
1509         return s->cnx->egl.eglReleaseTexImage(
1510                 dp->disp.dpy, s->surface, buffer);
1511     }
1512     return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
1513 }
1514
1515 EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
1516 {
1517     clearError();
1518
1519     const egl_display_ptr dp = validate_display(dpy);
1520     if (!dp) return EGL_FALSE;
1521
1522     EGLBoolean res = EGL_TRUE;
1523     egl_connection_t* const cnx = &gEGLImpl;
1524     if (cnx->dso && cnx->egl.eglSwapInterval) {
1525         res = cnx->egl.eglSwapInterval(dp->disp.dpy, interval);
1526     }
1527
1528     return res;
1529 }
1530
1531
1532 // ----------------------------------------------------------------------------
1533 // EGL 1.2
1534 // ----------------------------------------------------------------------------
1535
1536 EGLBoolean eglWaitClient(void)
1537 {
1538     clearError();
1539
1540     egl_connection_t* const cnx = &gEGLImpl;
1541     if (!cnx->dso)
1542         return setError(EGL_BAD_CONTEXT, (EGLBoolean)EGL_FALSE);
1543
1544     EGLBoolean res;
1545     if (cnx->egl.eglWaitClient) {
1546         res = cnx->egl.eglWaitClient();
1547     } else {
1548         res = cnx->egl.eglWaitGL();
1549     }
1550     return res;
1551 }
1552
1553 EGLBoolean eglBindAPI(EGLenum api)
1554 {
1555     clearError();
1556
1557     if (egl_init_drivers() == EGL_FALSE) {
1558         return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE);
1559     }
1560
1561     // bind this API on all EGLs
1562     EGLBoolean res = EGL_TRUE;
1563     egl_connection_t* const cnx = &gEGLImpl;
1564     if (cnx->dso && cnx->egl.eglBindAPI) {
1565         res = cnx->egl.eglBindAPI(api);
1566     }
1567     return res;
1568 }
1569
1570 EGLenum eglQueryAPI(void)
1571 {
1572     clearError();
1573
1574     if (egl_init_drivers() == EGL_FALSE) {
1575         return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE);
1576     }
1577
1578     egl_connection_t* const cnx = &gEGLImpl;
1579     if (cnx->dso && cnx->egl.eglQueryAPI) {
1580         return cnx->egl.eglQueryAPI();
1581     }
1582
1583     // or, it can only be OpenGL ES
1584     return EGL_OPENGL_ES_API;
1585 }
1586
1587 EGLBoolean eglReleaseThread(void)
1588 {
1589     clearError();
1590
1591     egl_connection_t* const cnx = &gEGLImpl;
1592     if (cnx->dso && cnx->egl.eglReleaseThread) {
1593         cnx->egl.eglReleaseThread();
1594     }
1595
1596     // If there is context bound to the thread, release it
1597     egl_display_t::loseCurrent(get_context(getContext()));
1598
1599     egl_tls_t::clearTLS();
1600     return EGL_TRUE;
1601 }
1602
1603 EGLSurface eglCreatePbufferFromClientBuffer(
1604           EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
1605           EGLConfig config, const EGLint *attrib_list)
1606 {
1607     clearError();
1608
1609     egl_connection_t* cnx = NULL;
1610     const egl_display_ptr dp = validate_display_connection(dpy, cnx);
1611     if (!dp) return EGL_FALSE;
1612     if (cnx->egl.eglCreatePbufferFromClientBuffer) {
1613         return cnx->egl.eglCreatePbufferFromClientBuffer(
1614                 dp->disp.dpy, buftype, buffer, config, attrib_list);
1615     }
1616     return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE);
1617 }
1618
1619 // ----------------------------------------------------------------------------
1620 // EGL_EGLEXT_VERSION 3
1621 // ----------------------------------------------------------------------------
1622
1623 EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface,
1624         const EGLint *attrib_list)
1625 {
1626     clearError();
1627
1628     const egl_display_ptr dp = validate_display(dpy);
1629     if (!dp) return EGL_FALSE;
1630
1631     SurfaceRef _s(dp.get(), surface);
1632     if (!_s.get())
1633         return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
1634
1635     egl_surface_t const * const s = get_surface(surface);
1636     if (s->cnx->egl.eglLockSurfaceKHR) {
1637         return s->cnx->egl.eglLockSurfaceKHR(
1638                 dp->disp.dpy, s->surface, attrib_list);
1639     }
1640     return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
1641 }
1642
1643 EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface)
1644 {
1645     clearError();
1646
1647     const egl_display_ptr dp = validate_display(dpy);
1648     if (!dp) return EGL_FALSE;
1649
1650     SurfaceRef _s(dp.get(), surface);
1651     if (!_s.get())
1652         return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
1653
1654     egl_surface_t const * const s = get_surface(surface);
1655     if (s->cnx->egl.eglUnlockSurfaceKHR) {
1656         return s->cnx->egl.eglUnlockSurfaceKHR(dp->disp.dpy, s->surface);
1657     }
1658     return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
1659 }
1660
1661 EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
1662         EGLClientBuffer buffer, const EGLint *attrib_list)
1663 {
1664     clearError();
1665
1666     const egl_display_ptr dp = validate_display(dpy);
1667     if (!dp) return EGL_NO_IMAGE_KHR;
1668
1669     ContextRef _c(dp.get(), ctx);
1670     egl_context_t * const c = _c.get();
1671
1672     EGLImageKHR result = EGL_NO_IMAGE_KHR;
1673     egl_connection_t* const cnx = &gEGLImpl;
1674     if (cnx->dso && cnx->egl.eglCreateImageKHR) {
1675         result = cnx->egl.eglCreateImageKHR(
1676                 dp->disp.dpy,
1677                 c ? c->context : EGL_NO_CONTEXT,
1678                 target, buffer, attrib_list);
1679     }
1680     return result;
1681 }
1682
1683 EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
1684 {
1685     clearError();
1686
1687     const egl_display_ptr dp = validate_display(dpy);
1688     if (!dp) return EGL_FALSE;
1689
1690     EGLBoolean result = EGL_FALSE;
1691     egl_connection_t* const cnx = &gEGLImpl;
1692     if (cnx->dso && cnx->egl.eglDestroyImageKHR) {
1693         result = cnx->egl.eglDestroyImageKHR(dp->disp.dpy, img);
1694     }
1695     return result;
1696 }
1697
1698 // ----------------------------------------------------------------------------
1699 // EGL_EGLEXT_VERSION 5
1700 // ----------------------------------------------------------------------------
1701
1702
1703 EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
1704 {
1705     clearError();
1706
1707     const egl_display_ptr dp = validate_display(dpy);
1708     if (!dp) return EGL_NO_SYNC_KHR;
1709
1710     EGLSyncKHR result = EGL_NO_SYNC_KHR;
1711     egl_connection_t* const cnx = &gEGLImpl;
1712     if (cnx->dso && cnx->egl.eglCreateSyncKHR) {
1713         result = cnx->egl.eglCreateSyncKHR(dp->disp.dpy, type, attrib_list);
1714     }
1715     return result;
1716 }
1717
1718 EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
1719 {
1720     clearError();
1721
1722     const egl_display_ptr dp = validate_display(dpy);
1723     if (!dp) return EGL_FALSE;
1724
1725     EGLBoolean result = EGL_FALSE;
1726     egl_connection_t* const cnx = &gEGLImpl;
1727     if (cnx->dso && cnx->egl.eglDestroySyncKHR) {
1728         result = cnx->egl.eglDestroySyncKHR(dp->disp.dpy, sync);
1729     }
1730     return result;
1731 }
1732
1733 EGLBoolean eglSignalSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode) {
1734     clearError();
1735
1736     const egl_display_ptr dp = validate_display(dpy);
1737     if (!dp) return EGL_FALSE;
1738
1739     EGLBoolean result = EGL_FALSE;
1740     egl_connection_t* const cnx = &gEGLImpl;
1741     if (cnx->dso && cnx->egl.eglSignalSyncKHR) {
1742         result = cnx->egl.eglSignalSyncKHR(
1743                 dp->disp.dpy, sync, mode);
1744     }
1745     return result;
1746 }
1747
1748 EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync,
1749         EGLint flags, EGLTimeKHR timeout)
1750 {
1751     clearError();
1752
1753     const egl_display_ptr dp = validate_display(dpy);
1754     if (!dp) return EGL_FALSE;
1755
1756     EGLint result = EGL_FALSE;
1757     egl_connection_t* const cnx = &gEGLImpl;
1758     if (cnx->dso && cnx->egl.eglClientWaitSyncKHR) {
1759         result = cnx->egl.eglClientWaitSyncKHR(
1760                 dp->disp.dpy, sync, flags, timeout);
1761     }
1762     return result;
1763 }
1764
1765 EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync,
1766         EGLint attribute, EGLint *value)
1767 {
1768     clearError();
1769
1770     const egl_display_ptr dp = validate_display(dpy);
1771     if (!dp) return EGL_FALSE;
1772
1773     EGLBoolean result = EGL_FALSE;
1774     egl_connection_t* const cnx = &gEGLImpl;
1775     if (cnx->dso && cnx->egl.eglGetSyncAttribKHR) {
1776         result = cnx->egl.eglGetSyncAttribKHR(
1777                 dp->disp.dpy, sync, attribute, value);
1778     }
1779     return result;
1780 }
1781
1782 EGLStreamKHR eglCreateStreamKHR(EGLDisplay dpy, const EGLint *attrib_list)
1783 {
1784     clearError();
1785
1786     const egl_display_ptr dp = validate_display(dpy);
1787     if (!dp) return EGL_NO_STREAM_KHR;
1788
1789     EGLStreamKHR result = EGL_NO_STREAM_KHR;
1790     egl_connection_t* const cnx = &gEGLImpl;
1791     if (cnx->dso && cnx->egl.eglCreateStreamKHR) {
1792         result = cnx->egl.eglCreateStreamKHR(
1793                 dp->disp.dpy, attrib_list);
1794     }
1795     return result;
1796 }
1797
1798 EGLBoolean eglDestroyStreamKHR(EGLDisplay dpy, EGLStreamKHR stream)
1799 {
1800     clearError();
1801
1802     const egl_display_ptr dp = validate_display(dpy);
1803     if (!dp) return EGL_FALSE;
1804
1805     EGLBoolean result = EGL_FALSE;
1806     egl_connection_t* const cnx = &gEGLImpl;
1807     if (cnx->dso && cnx->egl.eglDestroyStreamKHR) {
1808         result = cnx->egl.eglDestroyStreamKHR(
1809                 dp->disp.dpy, stream);
1810     }
1811     return result;
1812 }
1813
1814 EGLBoolean eglStreamAttribKHR(EGLDisplay dpy, EGLStreamKHR stream,
1815         EGLenum attribute, EGLint value)
1816 {
1817     clearError();
1818
1819     const egl_display_ptr dp = validate_display(dpy);
1820     if (!dp) return EGL_FALSE;
1821
1822     EGLBoolean result = EGL_FALSE;
1823     egl_connection_t* const cnx = &gEGLImpl;
1824     if (cnx->dso && cnx->egl.eglStreamAttribKHR) {
1825         result = cnx->egl.eglStreamAttribKHR(
1826                 dp->disp.dpy, stream, attribute, value);
1827     }
1828     return result;
1829 }
1830
1831 EGLBoolean eglQueryStreamKHR(EGLDisplay dpy, EGLStreamKHR stream,
1832         EGLenum attribute, EGLint *value)
1833 {
1834     clearError();
1835
1836     const egl_display_ptr dp = validate_display(dpy);
1837     if (!dp) return EGL_FALSE;
1838
1839     EGLBoolean result = EGL_FALSE;
1840     egl_connection_t* const cnx = &gEGLImpl;
1841     if (cnx->dso && cnx->egl.eglQueryStreamKHR) {
1842         result = cnx->egl.eglQueryStreamKHR(
1843                 dp->disp.dpy, stream, attribute, value);
1844     }
1845     return result;
1846 }
1847
1848 EGLBoolean eglQueryStreamu64KHR(EGLDisplay dpy, EGLStreamKHR stream,
1849         EGLenum attribute, EGLuint64KHR *value)
1850 {
1851     clearError();
1852
1853     const egl_display_ptr dp = validate_display(dpy);
1854     if (!dp) return EGL_FALSE;
1855
1856     EGLBoolean result = EGL_FALSE;
1857     egl_connection_t* const cnx = &gEGLImpl;
1858     if (cnx->dso && cnx->egl.eglQueryStreamu64KHR) {
1859         result = cnx->egl.eglQueryStreamu64KHR(
1860                 dp->disp.dpy, stream, attribute, value);
1861     }
1862     return result;
1863 }
1864
1865 EGLBoolean eglQueryStreamTimeKHR(EGLDisplay dpy, EGLStreamKHR stream,
1866         EGLenum attribute, EGLTimeKHR *value)
1867 {
1868     clearError();
1869
1870     const egl_display_ptr dp = validate_display(dpy);
1871     if (!dp) return EGL_FALSE;
1872
1873     EGLBoolean result = EGL_FALSE;
1874     egl_connection_t* const cnx = &gEGLImpl;
1875     if (cnx->dso && cnx->egl.eglQueryStreamTimeKHR) {
1876         result = cnx->egl.eglQueryStreamTimeKHR(
1877                 dp->disp.dpy, stream, attribute, value);
1878     }
1879     return result;
1880 }
1881
1882 EGLSurface eglCreateStreamProducerSurfaceKHR(EGLDisplay dpy, EGLConfig config,
1883         EGLStreamKHR stream, const EGLint *attrib_list)
1884 {
1885     clearError();
1886
1887     egl_display_ptr dp = validate_display(dpy);
1888     if (!dp) return EGL_NO_SURFACE;
1889
1890     EGLint colorSpace = EGL_GL_COLORSPACE_LINEAR_KHR;
1891     android_dataspace dataSpace = HAL_DATASPACE_UNKNOWN;
1892     // TODO: Probably need to update EGL_KHR_stream_producer_eglsurface to
1893     // indicate support for EGL_GL_COLORSPACE_KHR.
1894     // now select a corresponding sRGB format if needed
1895     if (!getColorSpaceAttribute(dp, attrib_list, colorSpace, dataSpace)) {
1896         ALOGE("error invalid colorspace: %d", colorSpace);
1897         return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
1898     }
1899
1900     egl_connection_t* const cnx = &gEGLImpl;
1901     if (cnx->dso && cnx->egl.eglCreateStreamProducerSurfaceKHR) {
1902         EGLSurface surface = cnx->egl.eglCreateStreamProducerSurfaceKHR(
1903                 dp->disp.dpy, config, stream, attrib_list);
1904         if (surface != EGL_NO_SURFACE) {
1905             egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL, surface, colorSpace, cnx);
1906             return s;
1907         }
1908     }
1909     return EGL_NO_SURFACE;
1910 }
1911
1912 EGLBoolean eglStreamConsumerGLTextureExternalKHR(EGLDisplay dpy,
1913         EGLStreamKHR stream)
1914 {
1915     clearError();
1916
1917     const egl_display_ptr dp = validate_display(dpy);
1918     if (!dp) return EGL_FALSE;
1919
1920     EGLBoolean result = EGL_FALSE;
1921     egl_connection_t* const cnx = &gEGLImpl;
1922     if (cnx->dso && cnx->egl.eglStreamConsumerGLTextureExternalKHR) {
1923         result = cnx->egl.eglStreamConsumerGLTextureExternalKHR(
1924                 dp->disp.dpy, stream);
1925     }
1926     return result;
1927 }
1928
1929 EGLBoolean eglStreamConsumerAcquireKHR(EGLDisplay dpy,
1930         EGLStreamKHR stream)
1931 {
1932     clearError();
1933
1934     const egl_display_ptr dp = validate_display(dpy);
1935     if (!dp) return EGL_FALSE;
1936
1937     EGLBoolean result = EGL_FALSE;
1938     egl_connection_t* const cnx = &gEGLImpl;
1939     if (cnx->dso && cnx->egl.eglStreamConsumerAcquireKHR) {
1940         result = cnx->egl.eglStreamConsumerAcquireKHR(
1941                 dp->disp.dpy, stream);
1942     }
1943     return result;
1944 }
1945
1946 EGLBoolean eglStreamConsumerReleaseKHR(EGLDisplay dpy,
1947         EGLStreamKHR stream)
1948 {
1949     clearError();
1950
1951     const egl_display_ptr dp = validate_display(dpy);
1952     if (!dp) return EGL_FALSE;
1953
1954     EGLBoolean result = EGL_FALSE;
1955     egl_connection_t* const cnx = &gEGLImpl;
1956     if (cnx->dso && cnx->egl.eglStreamConsumerReleaseKHR) {
1957         result = cnx->egl.eglStreamConsumerReleaseKHR(
1958                 dp->disp.dpy, stream);
1959     }
1960     return result;
1961 }
1962
1963 EGLNativeFileDescriptorKHR eglGetStreamFileDescriptorKHR(
1964         EGLDisplay dpy, EGLStreamKHR stream)
1965 {
1966     clearError();
1967
1968     const egl_display_ptr dp = validate_display(dpy);
1969     if (!dp) return EGL_NO_FILE_DESCRIPTOR_KHR;
1970
1971     EGLNativeFileDescriptorKHR result = EGL_NO_FILE_DESCRIPTOR_KHR;
1972     egl_connection_t* const cnx = &gEGLImpl;
1973     if (cnx->dso && cnx->egl.eglGetStreamFileDescriptorKHR) {
1974         result = cnx->egl.eglGetStreamFileDescriptorKHR(
1975                 dp->disp.dpy, stream);
1976     }
1977     return result;
1978 }
1979
1980 EGLStreamKHR eglCreateStreamFromFileDescriptorKHR(
1981         EGLDisplay dpy, EGLNativeFileDescriptorKHR file_descriptor)
1982 {
1983     clearError();
1984
1985     const egl_display_ptr dp = validate_display(dpy);
1986     if (!dp) return EGL_NO_STREAM_KHR;
1987
1988     EGLStreamKHR result = EGL_NO_STREAM_KHR;
1989     egl_connection_t* const cnx = &gEGLImpl;
1990     if (cnx->dso && cnx->egl.eglCreateStreamFromFileDescriptorKHR) {
1991         result = cnx->egl.eglCreateStreamFromFileDescriptorKHR(
1992                 dp->disp.dpy, file_descriptor);
1993     }
1994     return result;
1995 }
1996
1997 // ----------------------------------------------------------------------------
1998 // EGL_EGLEXT_VERSION 15
1999 // ----------------------------------------------------------------------------
2000
2001 EGLint eglWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags) {
2002     clearError();
2003     const egl_display_ptr dp = validate_display(dpy);
2004     if (!dp) return EGL_FALSE;
2005     EGLint result = EGL_FALSE;
2006     egl_connection_t* const cnx = &gEGLImpl;
2007     if (cnx->dso && cnx->egl.eglWaitSyncKHR) {
2008         result = cnx->egl.eglWaitSyncKHR(dp->disp.dpy, sync, flags);
2009     }
2010     return result;
2011 }
2012
2013 // ----------------------------------------------------------------------------
2014 // ANDROID extensions
2015 // ----------------------------------------------------------------------------
2016
2017 EGLint eglDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSyncKHR sync)
2018 {
2019     clearError();
2020
2021     const egl_display_ptr dp = validate_display(dpy);
2022     if (!dp) return EGL_NO_NATIVE_FENCE_FD_ANDROID;
2023
2024     EGLint result = EGL_NO_NATIVE_FENCE_FD_ANDROID;
2025     egl_connection_t* const cnx = &gEGLImpl;
2026     if (cnx->dso && cnx->egl.eglDupNativeFenceFDANDROID) {
2027         result = cnx->egl.eglDupNativeFenceFDANDROID(dp->disp.dpy, sync);
2028     }
2029     return result;
2030 }
2031
2032 EGLBoolean eglPresentationTimeANDROID(EGLDisplay dpy, EGLSurface surface,
2033         EGLnsecsANDROID time)
2034 {
2035     clearError();
2036
2037     const egl_display_ptr dp = validate_display(dpy);
2038     if (!dp) {
2039         return EGL_FALSE;
2040     }
2041
2042     SurfaceRef _s(dp.get(), surface);
2043     if (!_s.get()) {
2044         setError(EGL_BAD_SURFACE, EGL_FALSE);
2045         return EGL_FALSE;
2046     }
2047
2048     egl_surface_t const * const s = get_surface(surface);
2049     native_window_set_buffers_timestamp(s->getNativeWindow(), time);
2050
2051     return EGL_TRUE;
2052 }
2053
2054 EGLClientBuffer eglGetNativeClientBufferANDROID(const AHardwareBuffer *buffer) {
2055     clearError();
2056     // AHardwareBuffer_to_ANativeWindowBuffer is a platform-only symbol and thus
2057     // this function cannot be implemented when this libEGL is built for
2058     // vendors.
2059 #ifndef __ANDROID_VNDK__
2060     if (!buffer) return setError(EGL_BAD_PARAMETER, (EGLClientBuffer)0);
2061     return const_cast<ANativeWindowBuffer *>(AHardwareBuffer_to_ANativeWindowBuffer(buffer));
2062 #else
2063     return setError(EGL_BAD_PARAMETER, (EGLClientBuffer)0);
2064 #endif
2065 }
2066
2067 // ----------------------------------------------------------------------------
2068 // NVIDIA extensions
2069 // ----------------------------------------------------------------------------
2070 EGLuint64NV eglGetSystemTimeFrequencyNV()
2071 {
2072     clearError();
2073
2074     if (egl_init_drivers() == EGL_FALSE) {
2075         return setError(EGL_BAD_PARAMETER, (EGLuint64NV)EGL_FALSE);
2076     }
2077
2078     EGLuint64NV ret = 0;
2079     egl_connection_t* const cnx = &gEGLImpl;
2080
2081     if (cnx->dso && cnx->egl.eglGetSystemTimeFrequencyNV) {
2082         return cnx->egl.eglGetSystemTimeFrequencyNV();
2083     }
2084
2085     return setErrorQuiet(EGL_BAD_DISPLAY, (EGLuint64NV)0);
2086 }
2087
2088 EGLuint64NV eglGetSystemTimeNV()
2089 {
2090     clearError();
2091
2092     if (egl_init_drivers() == EGL_FALSE) {
2093         return setError(EGL_BAD_PARAMETER, (EGLuint64NV)EGL_FALSE);
2094     }
2095
2096     EGLuint64NV ret = 0;
2097     egl_connection_t* const cnx = &gEGLImpl;
2098
2099     if (cnx->dso && cnx->egl.eglGetSystemTimeNV) {
2100         return cnx->egl.eglGetSystemTimeNV();
2101     }
2102
2103     return setErrorQuiet(EGL_BAD_DISPLAY, (EGLuint64NV)0);
2104 }
2105
2106 // ----------------------------------------------------------------------------
2107 // Partial update extension
2108 // ----------------------------------------------------------------------------
2109 EGLBoolean eglSetDamageRegionKHR(EGLDisplay dpy, EGLSurface surface,
2110         EGLint *rects, EGLint n_rects)
2111 {
2112     clearError();
2113
2114     const egl_display_ptr dp = validate_display(dpy);
2115     if (!dp) {
2116         setError(EGL_BAD_DISPLAY, EGL_FALSE);
2117         return EGL_FALSE;
2118     }
2119
2120     SurfaceRef _s(dp.get(), surface);
2121     if (!_s.get()) {
2122         setError(EGL_BAD_SURFACE, EGL_FALSE);
2123         return EGL_FALSE;
2124     }
2125
2126     egl_surface_t const * const s = get_surface(surface);
2127     if (s->cnx->egl.eglSetDamageRegionKHR) {
2128         return s->cnx->egl.eglSetDamageRegionKHR(dp->disp.dpy, s->surface,
2129                 rects, n_rects);
2130     }
2131
2132     return EGL_FALSE;
2133 }
2134
2135 EGLBoolean eglGetNextFrameIdANDROID(EGLDisplay dpy, EGLSurface surface,
2136             EGLuint64KHR *frameId) {
2137     clearError();
2138
2139     const egl_display_ptr dp = validate_display(dpy);
2140     if (!dp) {
2141         return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
2142     }
2143
2144     SurfaceRef _s(dp.get(), surface);
2145     if (!_s.get()) {
2146         return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
2147     }
2148
2149     egl_surface_t const * const s = get_surface(surface);
2150
2151     if (!s->getNativeWindow()) {
2152         return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
2153     }
2154
2155     uint64_t nextFrameId = 0;
2156     int ret = native_window_get_next_frame_id(s->getNativeWindow(), &nextFrameId);
2157
2158     if (ret != 0) {
2159         // This should not happen. Return an error that is not in the spec
2160         // so it's obvious something is very wrong.
2161         ALOGE("eglGetNextFrameId: Unexpected error.");
2162         return setError(EGL_NOT_INITIALIZED, (EGLBoolean)EGL_FALSE);
2163     }
2164
2165     *frameId = nextFrameId;
2166     return EGL_TRUE;
2167 }
2168
2169 EGLBoolean eglGetCompositorTimingANDROID(EGLDisplay dpy, EGLSurface surface,
2170         EGLint numTimestamps, const EGLint *names, EGLnsecsANDROID *values)
2171 {
2172     clearError();
2173
2174     const egl_display_ptr dp = validate_display(dpy);
2175     if (!dp) {
2176         return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
2177     }
2178
2179     SurfaceRef _s(dp.get(), surface);
2180     if (!_s.get()) {
2181         return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
2182     }
2183
2184     egl_surface_t const * const s = get_surface(surface);
2185
2186     if (!s->getNativeWindow()) {
2187         return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
2188     }
2189
2190     nsecs_t* compositeDeadline = nullptr;
2191     nsecs_t* compositeInterval = nullptr;
2192     nsecs_t* compositeToPresentLatency = nullptr;
2193
2194     for (int i = 0; i < numTimestamps; i++) {
2195         switch (names[i]) {
2196             case EGL_COMPOSITE_DEADLINE_ANDROID:
2197                 compositeDeadline = &values[i];
2198                 break;
2199             case EGL_COMPOSITE_INTERVAL_ANDROID:
2200                 compositeInterval = &values[i];
2201                 break;
2202             case EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID:
2203                 compositeToPresentLatency = &values[i];
2204                 break;
2205             default:
2206                 return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE);
2207         }
2208     }
2209
2210     int ret = native_window_get_compositor_timing(s->getNativeWindow(),
2211             compositeDeadline, compositeInterval, compositeToPresentLatency);
2212
2213     switch (ret) {
2214       case 0:
2215         return EGL_TRUE;
2216       case -ENOSYS:
2217         return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
2218       default:
2219         // This should not happen. Return an error that is not in the spec
2220         // so it's obvious something is very wrong.
2221         ALOGE("eglGetCompositorTiming: Unexpected error.");
2222         return setError(EGL_NOT_INITIALIZED, (EGLBoolean)EGL_FALSE);
2223     }
2224 }
2225
2226 EGLBoolean eglGetCompositorTimingSupportedANDROID(
2227         EGLDisplay dpy, EGLSurface surface, EGLint name)
2228 {
2229     clearError();
2230
2231     const egl_display_ptr dp = validate_display(dpy);
2232     if (!dp) {
2233         return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
2234     }
2235
2236     SurfaceRef _s(dp.get(), surface);
2237     if (!_s.get()) {
2238         return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
2239     }
2240
2241     egl_surface_t const * const s = get_surface(surface);
2242
2243     ANativeWindow* window = s->getNativeWindow();
2244     if (!window) {
2245         return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
2246     }
2247
2248     switch (name) {
2249         case EGL_COMPOSITE_DEADLINE_ANDROID:
2250         case EGL_COMPOSITE_INTERVAL_ANDROID:
2251         case EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID:
2252             return EGL_TRUE;
2253         default:
2254             return EGL_FALSE;
2255     }
2256 }
2257
2258 EGLBoolean eglGetFrameTimestampsANDROID(EGLDisplay dpy, EGLSurface surface,
2259         EGLuint64KHR frameId, EGLint numTimestamps, const EGLint *timestamps,
2260         EGLnsecsANDROID *values)
2261 {
2262     clearError();
2263
2264     const egl_display_ptr dp = validate_display(dpy);
2265     if (!dp) {
2266         return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
2267     }
2268
2269     SurfaceRef _s(dp.get(), surface);
2270     if (!_s.get()) {
2271         return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
2272     }
2273
2274     egl_surface_t const * const s = get_surface(surface);
2275
2276     if (!s->getNativeWindow()) {
2277         return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
2278     }
2279
2280     nsecs_t* requestedPresentTime = nullptr;
2281     nsecs_t* acquireTime = nullptr;
2282     nsecs_t* latchTime = nullptr;
2283     nsecs_t* firstRefreshStartTime = nullptr;
2284     nsecs_t* gpuCompositionDoneTime = nullptr;
2285     nsecs_t* lastRefreshStartTime = nullptr;
2286     nsecs_t* displayPresentTime = nullptr;
2287     nsecs_t* dequeueReadyTime = nullptr;
2288     nsecs_t* releaseTime = nullptr;
2289
2290     for (int i = 0; i < numTimestamps; i++) {
2291         switch (timestamps[i]) {
2292             case EGL_REQUESTED_PRESENT_TIME_ANDROID:
2293                 requestedPresentTime = &values[i];
2294                 break;
2295             case EGL_RENDERING_COMPLETE_TIME_ANDROID:
2296                 acquireTime = &values[i];
2297                 break;
2298             case EGL_COMPOSITION_LATCH_TIME_ANDROID:
2299                 latchTime = &values[i];
2300                 break;
2301             case EGL_FIRST_COMPOSITION_START_TIME_ANDROID:
2302                 firstRefreshStartTime = &values[i];
2303                 break;
2304             case EGL_LAST_COMPOSITION_START_TIME_ANDROID:
2305                 lastRefreshStartTime = &values[i];
2306                 break;
2307             case EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID:
2308                 gpuCompositionDoneTime = &values[i];
2309                 break;
2310             case EGL_DISPLAY_PRESENT_TIME_ANDROID:
2311                 displayPresentTime = &values[i];
2312                 break;
2313             case EGL_DEQUEUE_READY_TIME_ANDROID:
2314                 dequeueReadyTime = &values[i];
2315                 break;
2316             case EGL_READS_DONE_TIME_ANDROID:
2317                 releaseTime = &values[i];
2318                 break;
2319             default:
2320                 return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE);
2321         }
2322     }
2323
2324     int ret = native_window_get_frame_timestamps(s->getNativeWindow(), frameId,
2325             requestedPresentTime, acquireTime, latchTime, firstRefreshStartTime,
2326             lastRefreshStartTime, gpuCompositionDoneTime, displayPresentTime,
2327             dequeueReadyTime, releaseTime);
2328
2329     switch (ret) {
2330         case 0:
2331             return EGL_TRUE;
2332         case -ENOENT:
2333             return setError(EGL_BAD_ACCESS, (EGLBoolean)EGL_FALSE);
2334         case -ENOSYS:
2335             return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
2336         case -EINVAL:
2337             return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE);
2338         default:
2339             // This should not happen. Return an error that is not in the spec
2340             // so it's obvious something is very wrong.
2341             ALOGE("eglGetFrameTimestamps: Unexpected error.");
2342             return setError(EGL_NOT_INITIALIZED, (EGLBoolean)EGL_FALSE);
2343     }
2344 }
2345
2346 EGLBoolean eglGetFrameTimestampSupportedANDROID(
2347         EGLDisplay dpy, EGLSurface surface, EGLint timestamp)
2348 {
2349     clearError();
2350
2351     const egl_display_ptr dp = validate_display(dpy);
2352     if (!dp) {
2353         return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
2354     }
2355
2356     SurfaceRef _s(dp.get(), surface);
2357     if (!_s.get()) {
2358         return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
2359     }
2360
2361     egl_surface_t const * const s = get_surface(surface);
2362
2363     ANativeWindow* window = s->getNativeWindow();
2364     if (!window) {
2365         return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
2366     }
2367
2368     switch (timestamp) {
2369         case EGL_COMPOSITE_DEADLINE_ANDROID:
2370         case EGL_COMPOSITE_INTERVAL_ANDROID:
2371         case EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID:
2372         case EGL_REQUESTED_PRESENT_TIME_ANDROID:
2373         case EGL_RENDERING_COMPLETE_TIME_ANDROID:
2374         case EGL_COMPOSITION_LATCH_TIME_ANDROID:
2375         case EGL_FIRST_COMPOSITION_START_TIME_ANDROID:
2376         case EGL_LAST_COMPOSITION_START_TIME_ANDROID:
2377         case EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID:
2378         case EGL_DEQUEUE_READY_TIME_ANDROID:
2379         case EGL_READS_DONE_TIME_ANDROID:
2380             return EGL_TRUE;
2381         case EGL_DISPLAY_PRESENT_TIME_ANDROID: {
2382             int value = 0;
2383             window->query(window,
2384                     NATIVE_WINDOW_FRAME_TIMESTAMPS_SUPPORTS_PRESENT, &value);
2385             return value == 0 ? EGL_FALSE : EGL_TRUE;
2386         }
2387         default:
2388             return EGL_FALSE;
2389     }
2390 }