OSDN Git Service

DO NOT MERGE Remove window obscurement information.
[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 <dlfcn.h>
20 #include <ctype.h>
21 #include <stdlib.h>
22 #include <string.h>
23
24 #include <hardware/gralloc.h>
25 #include <system/window.h>
26
27 #include <EGL/egl.h>
28 #include <EGL/eglext.h>
29
30 #include <cutils/log.h>
31 #include <cutils/atomic.h>
32 #include <cutils/compiler.h>
33 #include <cutils/properties.h>
34 #include <cutils/memory.h>
35
36 #include <ui/GraphicBuffer.h>
37
38 #include <utils/KeyedVector.h>
39 #include <utils/SortedVector.h>
40 #include <utils/String8.h>
41 #include <utils/Trace.h>
42
43 #include "../egl_impl.h"
44 #include "../hooks.h"
45
46 #include "egl_display.h"
47 #include "egl_object.h"
48 #include "egl_tls.h"
49 #include "egldefs.h"
50
51 using namespace android;
52
53 // This extension has not been ratified yet, so can't be shipped.
54 // Implementation is incomplete and untested.
55 #define ENABLE_EGL_KHR_GL_COLORSPACE 0
56
57 #define ENABLE_EGL_ANDROID_GET_FRAME_TIMESTAMPS 0
58
59 // ----------------------------------------------------------------------------
60
61 namespace android {
62
63 struct extention_map_t {
64     const char* name;
65     __eglMustCastToProperFunctionPointerType address;
66 };
67
68 /*
69  * This is the list of EGL extensions exposed to applications.
70  *
71  * Some of them (gBuiltinExtensionString) are implemented entirely in this EGL
72  * wrapper and are always available.
73  *
74  * The rest (gExtensionString) depend on support in the EGL driver, and are
75  * only available if the driver supports them. However, some of these must be
76  * supported because they are used by the Android system itself; these are
77  * listed as mandatory below and are required by the CDD. The system *assumes*
78  * the mandatory extensions are present and may not function properly if some
79  * are missing.
80  *
81  * NOTE: Both strings MUST have a single space as the last character.
82  */
83 extern 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_create_native_client_buffer "
88         "EGL_ANDROID_front_buffer_auto_refresh "
89 #if ENABLE_EGL_ANDROID_GET_FRAME_TIMESTAMPS
90         "EGL_ANDROID_get_frame_timestamps "
91 #endif
92         ;
93 extern char const * const gExtensionString  =
94         "EGL_KHR_image "                        // mandatory
95         "EGL_KHR_image_base "                   // mandatory
96         "EGL_KHR_image_pixmap "
97         "EGL_KHR_lock_surface "
98 #if (ENABLE_EGL_KHR_GL_COLORSPACE != 0)
99         "EGL_KHR_gl_colorspace "
100 #endif
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_buffer_age "                   // strongly recommended with partial_update
122         "EGL_KHR_create_context_no_error "
123         "EGL_KHR_mutable_render_buffer "
124         "EGL_EXT_yuv_surface "
125         "EGL_EXT_protected_content "
126         ;
127
128 // extensions not exposed to applications but used by the ANDROID system
129 //      "EGL_ANDROID_blob_cache "               // strongly recommended
130 //      "EGL_IMG_hibernate_process "            // optional
131 //      "EGL_ANDROID_native_fence_sync "        // strongly recommended
132 //      "EGL_ANDROID_framebuffer_target "       // mandatory for HWC 1.1
133 //      "EGL_ANDROID_image_crop "               // optional
134
135 /*
136  * EGL Extensions entry-points exposed to 3rd party applications
137  * (keep in sync with gExtensionString above)
138  *
139  */
140 static const extention_map_t sExtensionMap[] = {
141     // EGL_KHR_lock_surface
142     { "eglLockSurfaceKHR",
143             (__eglMustCastToProperFunctionPointerType)&eglLockSurfaceKHR },
144     { "eglUnlockSurfaceKHR",
145             (__eglMustCastToProperFunctionPointerType)&eglUnlockSurfaceKHR },
146
147     // EGL_KHR_image, EGL_KHR_image_base
148     { "eglCreateImageKHR",
149             (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR },
150     { "eglDestroyImageKHR",
151             (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR },
152
153     // EGL_KHR_reusable_sync, EGL_KHR_fence_sync
154     { "eglCreateSyncKHR",
155             (__eglMustCastToProperFunctionPointerType)&eglCreateSyncKHR },
156     { "eglDestroySyncKHR",
157             (__eglMustCastToProperFunctionPointerType)&eglDestroySyncKHR },
158     { "eglClientWaitSyncKHR",
159             (__eglMustCastToProperFunctionPointerType)&eglClientWaitSyncKHR },
160     { "eglSignalSyncKHR",
161             (__eglMustCastToProperFunctionPointerType)&eglSignalSyncKHR },
162     { "eglGetSyncAttribKHR",
163             (__eglMustCastToProperFunctionPointerType)&eglGetSyncAttribKHR },
164
165     // EGL_NV_system_time
166     { "eglGetSystemTimeFrequencyNV",
167             (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeFrequencyNV },
168     { "eglGetSystemTimeNV",
169             (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeNV },
170
171     // EGL_KHR_wait_sync
172     { "eglWaitSyncKHR",
173             (__eglMustCastToProperFunctionPointerType)&eglWaitSyncKHR },
174
175     // EGL_ANDROID_presentation_time
176     { "eglPresentationTimeANDROID",
177             (__eglMustCastToProperFunctionPointerType)&eglPresentationTimeANDROID },
178
179     // EGL_KHR_swap_buffers_with_damage
180     { "eglSwapBuffersWithDamageKHR",
181             (__eglMustCastToProperFunctionPointerType)&eglSwapBuffersWithDamageKHR },
182
183     // EGL_ANDROID_native_client_buffer
184     { "eglCreateNativeClientBufferANDROID",
185             (__eglMustCastToProperFunctionPointerType)&eglCreateNativeClientBufferANDROID },
186
187     // EGL_KHR_partial_update
188     { "eglSetDamageRegionKHR",
189             (__eglMustCastToProperFunctionPointerType)&eglSetDamageRegionKHR },
190
191     { "eglCreateStreamKHR",
192             (__eglMustCastToProperFunctionPointerType)&eglCreateStreamKHR },
193     { "eglDestroyStreamKHR",
194             (__eglMustCastToProperFunctionPointerType)&eglDestroyStreamKHR },
195     { "eglStreamAttribKHR",
196             (__eglMustCastToProperFunctionPointerType)&eglStreamAttribKHR },
197     { "eglQueryStreamKHR",
198             (__eglMustCastToProperFunctionPointerType)&eglQueryStreamKHR },
199     { "eglQueryStreamu64KHR",
200             (__eglMustCastToProperFunctionPointerType)&eglQueryStreamu64KHR },
201     { "eglQueryStreamTimeKHR",
202             (__eglMustCastToProperFunctionPointerType)&eglQueryStreamTimeKHR },
203     { "eglCreateStreamProducerSurfaceKHR",
204             (__eglMustCastToProperFunctionPointerType)&eglCreateStreamProducerSurfaceKHR },
205     { "eglStreamConsumerGLTextureExternalKHR",
206             (__eglMustCastToProperFunctionPointerType)&eglStreamConsumerGLTextureExternalKHR },
207     { "eglStreamConsumerAcquireKHR",
208             (__eglMustCastToProperFunctionPointerType)&eglStreamConsumerAcquireKHR },
209     { "eglStreamConsumerReleaseKHR",
210             (__eglMustCastToProperFunctionPointerType)&eglStreamConsumerReleaseKHR },
211     { "eglGetStreamFileDescriptorKHR",
212             (__eglMustCastToProperFunctionPointerType)&eglGetStreamFileDescriptorKHR },
213     { "eglCreateStreamFromFileDescriptorKHR",
214             (__eglMustCastToProperFunctionPointerType)&eglCreateStreamFromFileDescriptorKHR },
215
216     // EGL_ANDROID_get_frame_timestamps
217     { "eglGetFrameTimestampsANDROID",
218             (__eglMustCastToProperFunctionPointerType)&eglGetFrameTimestampsANDROID },
219     { "eglQueryTimestampSupportedANDROID",
220             (__eglMustCastToProperFunctionPointerType)&eglQueryTimestampSupportedANDROID },
221 };
222
223 /*
224  * These extensions entry-points should not be exposed to applications.
225  * They're used internally by the Android EGL layer.
226  */
227 #define FILTER_EXTENSIONS(procname) \
228         (!strcmp((procname), "eglSetBlobCacheFuncsANDROID") ||    \
229          !strcmp((procname), "eglHibernateProcessIMG")      ||    \
230          !strcmp((procname), "eglAwakenProcessIMG")         ||    \
231          !strcmp((procname), "eglDupNativeFenceFDANDROID"))
232
233
234
235 // accesses protected by sExtensionMapMutex
236 static DefaultKeyedVector<String8, __eglMustCastToProperFunctionPointerType> sGLExtentionMap;
237 static int sGLExtentionSlot = 0;
238 static pthread_mutex_t sExtensionMapMutex = PTHREAD_MUTEX_INITIALIZER;
239
240 static void(*findProcAddress(const char* name,
241         const extention_map_t* map, size_t n))() {
242     for (uint32_t i=0 ; i<n ; i++) {
243         if (!strcmp(name, map[i].name)) {
244             return map[i].address;
245         }
246     }
247     return NULL;
248 }
249
250 // ----------------------------------------------------------------------------
251
252 extern void setGLHooksThreadSpecific(gl_hooks_t const *value);
253 extern EGLBoolean egl_init_drivers();
254 extern const __eglMustCastToProperFunctionPointerType gExtensionForwarders[MAX_NUMBER_OF_GL_EXTENSIONS];
255 extern gl_hooks_t gHooksTrace;
256
257 } // namespace android;
258
259
260 // ----------------------------------------------------------------------------
261
262 static inline void clearError() { egl_tls_t::clearError(); }
263 static inline EGLContext getContext() { return egl_tls_t::getContext(); }
264
265 // ----------------------------------------------------------------------------
266
267 EGLDisplay eglGetDisplay(EGLNativeDisplayType display)
268 {
269     clearError();
270
271     uintptr_t index = reinterpret_cast<uintptr_t>(display);
272     if (index >= NUM_DISPLAYS) {
273         return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
274     }
275
276     if (egl_init_drivers() == EGL_FALSE) {
277         return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
278     }
279
280     EGLDisplay dpy = egl_display_t::getFromNativeDisplay(display);
281     return dpy;
282 }
283
284 // ----------------------------------------------------------------------------
285 // Initialization
286 // ----------------------------------------------------------------------------
287
288 EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
289 {
290     clearError();
291
292     egl_display_ptr dp = get_display(dpy);
293     if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
294
295     EGLBoolean res = dp->initialize(major, minor);
296
297     return res;
298 }
299
300 EGLBoolean eglTerminate(EGLDisplay dpy)
301 {
302     // NOTE: don't unload the drivers b/c some APIs can be called
303     // after eglTerminate() has been called. eglTerminate() only
304     // terminates an EGLDisplay, not a EGL itself.
305
306     clearError();
307
308     egl_display_ptr dp = get_display(dpy);
309     if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
310
311     EGLBoolean res = dp->terminate();
312
313     return res;
314 }
315
316 // ----------------------------------------------------------------------------
317 // configuration
318 // ----------------------------------------------------------------------------
319
320 EGLBoolean eglGetConfigs(   EGLDisplay dpy,
321                             EGLConfig *configs,
322                             EGLint config_size, EGLint *num_config)
323 {
324     clearError();
325
326     const egl_display_ptr dp = validate_display(dpy);
327     if (!dp) return EGL_FALSE;
328
329     if (num_config==0) {
330         return setError(EGL_BAD_PARAMETER, EGL_FALSE);
331     }
332
333     EGLBoolean res = EGL_FALSE;
334     *num_config = 0;
335
336     egl_connection_t* const cnx = &gEGLImpl;
337     if (cnx->dso) {
338         res = cnx->egl.eglGetConfigs(
339                 dp->disp.dpy, configs, config_size, num_config);
340     }
341
342     return res;
343 }
344
345 EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list,
346                             EGLConfig *configs, EGLint config_size,
347                             EGLint *num_config)
348 {
349     clearError();
350
351     const egl_display_ptr dp = validate_display(dpy);
352     if (!dp) return EGL_FALSE;
353
354     if (num_config==0) {
355         return setError(EGL_BAD_PARAMETER, EGL_FALSE);
356     }
357
358     EGLBoolean res = EGL_FALSE;
359     *num_config = 0;
360
361     egl_connection_t* const cnx = &gEGLImpl;
362     if (cnx->dso) {
363         if (attrib_list) {
364             char value[PROPERTY_VALUE_MAX];
365             property_get("debug.egl.force_msaa", value, "false");
366
367             if (!strcmp(value, "true")) {
368                 size_t attribCount = 0;
369                 EGLint attrib = attrib_list[0];
370
371                 // Only enable MSAA if the context is OpenGL ES 2.0 and
372                 // if no caveat is requested
373                 const EGLint *attribRendererable = NULL;
374                 const EGLint *attribCaveat = NULL;
375
376                 // Count the number of attributes and look for
377                 // EGL_RENDERABLE_TYPE and EGL_CONFIG_CAVEAT
378                 while (attrib != EGL_NONE) {
379                     attrib = attrib_list[attribCount];
380                     switch (attrib) {
381                         case EGL_RENDERABLE_TYPE:
382                             attribRendererable = &attrib_list[attribCount];
383                             break;
384                         case EGL_CONFIG_CAVEAT:
385                             attribCaveat = &attrib_list[attribCount];
386                             break;
387                     }
388                     attribCount++;
389                 }
390
391                 if (attribRendererable && attribRendererable[1] == EGL_OPENGL_ES2_BIT &&
392                         (!attribCaveat || attribCaveat[1] != EGL_NONE)) {
393
394                     // Insert 2 extra attributes to force-enable MSAA 4x
395                     EGLint aaAttribs[attribCount + 4];
396                     aaAttribs[0] = EGL_SAMPLE_BUFFERS;
397                     aaAttribs[1] = 1;
398                     aaAttribs[2] = EGL_SAMPLES;
399                     aaAttribs[3] = 4;
400
401                     memcpy(&aaAttribs[4], attrib_list, attribCount * sizeof(EGLint));
402
403                     EGLint numConfigAA;
404                     EGLBoolean resAA = cnx->egl.eglChooseConfig(
405                             dp->disp.dpy, aaAttribs, configs, config_size, &numConfigAA);
406
407                     if (resAA == EGL_TRUE && numConfigAA > 0) {
408                         ALOGD("Enabling MSAA 4x");
409                         *num_config = numConfigAA;
410                         return resAA;
411                     }
412                 }
413             }
414         }
415
416         res = cnx->egl.eglChooseConfig(
417                 dp->disp.dpy, attrib_list, configs, config_size, num_config);
418     }
419     return res;
420 }
421
422 EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
423         EGLint attribute, EGLint *value)
424 {
425     clearError();
426
427     egl_connection_t* cnx = NULL;
428     const egl_display_ptr dp = validate_display_connection(dpy, cnx);
429     if (!dp) return EGL_FALSE;
430
431     return cnx->egl.eglGetConfigAttrib(
432             dp->disp.dpy, config, attribute, value);
433 }
434
435 // ----------------------------------------------------------------------------
436 // surfaces
437 // ----------------------------------------------------------------------------
438
439 // The EGL_KHR_gl_colorspace spec hasn't been ratified yet, so these haven't
440 // been added to the Khronos egl.h.
441 #define EGL_GL_COLORSPACE_KHR           EGL_VG_COLORSPACE
442 #define EGL_GL_COLORSPACE_SRGB_KHR      EGL_VG_COLORSPACE_sRGB
443 #define EGL_GL_COLORSPACE_LINEAR_KHR    EGL_VG_COLORSPACE_LINEAR
444
445 // Turn linear formats into corresponding sRGB formats when colorspace is
446 // EGL_GL_COLORSPACE_SRGB_KHR, or turn sRGB formats into corresponding linear
447 // formats when colorspace is EGL_GL_COLORSPACE_LINEAR_KHR. In any cases where
448 // the modification isn't possible, the original dataSpace is returned.
449 static android_dataspace modifyBufferDataspace( android_dataspace dataSpace,
450                                                 EGLint colorspace) {
451     if (colorspace == EGL_GL_COLORSPACE_LINEAR_KHR) {
452         return HAL_DATASPACE_SRGB_LINEAR;
453     } else if (colorspace == EGL_GL_COLORSPACE_SRGB_KHR) {
454         return HAL_DATASPACE_SRGB;
455     }
456     return dataSpace;
457 }
458
459 EGLSurface eglCreateWindowSurface(  EGLDisplay dpy, EGLConfig config,
460                                     NativeWindowType window,
461                                     const EGLint *attrib_list)
462 {
463     clearError();
464
465     egl_connection_t* cnx = NULL;
466     egl_display_ptr dp = validate_display_connection(dpy, cnx);
467     if (dp) {
468         EGLDisplay iDpy = dp->disp.dpy;
469
470         int result = native_window_api_connect(window, NATIVE_WINDOW_API_EGL);
471         if (result != OK) {
472             ALOGE("eglCreateWindowSurface: native_window_api_connect (win=%p) "
473                     "failed (%#x) (already connected to another API?)",
474                     window, result);
475             return setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
476         }
477
478         // Set the native window's buffers format to match what this config requests.
479         // Whether to use sRGB gamma is not part of the EGLconfig, but is part
480         // of our native format. So if sRGB gamma is requested, we have to
481         // modify the EGLconfig's format before setting the native window's
482         // format.
483
484         // by default, just pick RGBA_8888
485         EGLint format = HAL_PIXEL_FORMAT_RGBA_8888;
486         android_dataspace dataSpace = HAL_DATASPACE_UNKNOWN;
487
488         EGLint a = 0;
489         cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_ALPHA_SIZE, &a);
490         if (a > 0) {
491             // alpha-channel requested, there's really only one suitable format
492             format = HAL_PIXEL_FORMAT_RGBA_8888;
493         } else {
494             EGLint r, g, b;
495             r = g = b = 0;
496             cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_RED_SIZE,   &r);
497             cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_GREEN_SIZE, &g);
498             cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_BLUE_SIZE,  &b);
499             EGLint colorDepth = r + g + b;
500             if (colorDepth <= 16) {
501                 format = HAL_PIXEL_FORMAT_RGB_565;
502             } else {
503                 format = HAL_PIXEL_FORMAT_RGBX_8888;
504             }
505         }
506
507         // now select a corresponding sRGB format if needed
508         if (attrib_list && dp->haveExtension("EGL_KHR_gl_colorspace")) {
509             for (const EGLint* attr = attrib_list; *attr != EGL_NONE; attr += 2) {
510                 if (*attr == EGL_GL_COLORSPACE_KHR) {
511                     if (ENABLE_EGL_KHR_GL_COLORSPACE) {
512                         dataSpace = modifyBufferDataspace(dataSpace, *(attr+1));
513                     } else {
514                         // Normally we'd pass through unhandled attributes to
515                         // the driver. But in case the driver implements this
516                         // extension but we're disabling it, we want to prevent
517                         // it getting through -- support will be broken without
518                         // our help.
519                         ALOGE("sRGB window surfaces not supported");
520                         return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
521                     }
522                 }
523             }
524         }
525
526         if (format != 0) {
527             int err = native_window_set_buffers_format(window, format);
528             if (err != 0) {
529                 ALOGE("error setting native window pixel format: %s (%d)",
530                         strerror(-err), err);
531                 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
532                 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
533             }
534         }
535
536         if (dataSpace != 0) {
537             int err = native_window_set_buffers_data_space(window, dataSpace);
538             if (err != 0) {
539                 ALOGE("error setting native window pixel dataSpace: %s (%d)",
540                         strerror(-err), err);
541                 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
542                 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
543             }
544         }
545
546         // the EGL spec requires that a new EGLSurface default to swap interval
547         // 1, so explicitly set that on the window here.
548         ANativeWindow* anw = reinterpret_cast<ANativeWindow*>(window);
549         anw->setSwapInterval(anw, 1);
550
551         EGLSurface surface = cnx->egl.eglCreateWindowSurface(
552                 iDpy, config, window, attrib_list);
553         if (surface != EGL_NO_SURFACE) {
554             egl_surface_t* s = new egl_surface_t(dp.get(), config, window,
555                     surface, cnx);
556             return s;
557         }
558
559         // EGLSurface creation failed
560         native_window_set_buffers_format(window, 0);
561         native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
562     }
563     return EGL_NO_SURFACE;
564 }
565
566 EGLSurface eglCreatePixmapSurface(  EGLDisplay dpy, EGLConfig config,
567                                     NativePixmapType pixmap,
568                                     const EGLint *attrib_list)
569 {
570     clearError();
571
572     egl_connection_t* cnx = NULL;
573     egl_display_ptr dp = validate_display_connection(dpy, cnx);
574     if (dp) {
575         EGLSurface surface = cnx->egl.eglCreatePixmapSurface(
576                 dp->disp.dpy, config, pixmap, attrib_list);
577         if (surface != EGL_NO_SURFACE) {
578             egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL,
579                     surface, cnx);
580             return s;
581         }
582     }
583     return EGL_NO_SURFACE;
584 }
585
586 EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config,
587                                     const EGLint *attrib_list)
588 {
589     clearError();
590
591     egl_connection_t* cnx = NULL;
592     egl_display_ptr dp = validate_display_connection(dpy, cnx);
593     if (dp) {
594         EGLSurface surface = cnx->egl.eglCreatePbufferSurface(
595                 dp->disp.dpy, config, attrib_list);
596         if (surface != EGL_NO_SURFACE) {
597             egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL,
598                     surface, cnx);
599             return s;
600         }
601     }
602     return EGL_NO_SURFACE;
603 }
604
605 EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
606 {
607     clearError();
608
609     const egl_display_ptr dp = validate_display(dpy);
610     if (!dp) return EGL_FALSE;
611
612     SurfaceRef _s(dp.get(), surface);
613     if (!_s.get())
614         return setError(EGL_BAD_SURFACE, EGL_FALSE);
615
616     egl_surface_t * const s = get_surface(surface);
617     EGLBoolean result = s->cnx->egl.eglDestroySurface(dp->disp.dpy, s->surface);
618     if (result == EGL_TRUE) {
619         _s.terminate();
620     }
621     return result;
622 }
623
624 EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface,
625                             EGLint attribute, EGLint *value)
626 {
627     clearError();
628
629     const egl_display_ptr dp = validate_display(dpy);
630     if (!dp) return EGL_FALSE;
631
632     SurfaceRef _s(dp.get(), surface);
633     if (!_s.get())
634         return setError(EGL_BAD_SURFACE, EGL_FALSE);
635
636     egl_surface_t const * const s = get_surface(surface);
637     return s->cnx->egl.eglQuerySurface(
638             dp->disp.dpy, s->surface, attribute, value);
639 }
640
641 void EGLAPI eglBeginFrame(EGLDisplay dpy, EGLSurface surface) {
642     ATRACE_CALL();
643     clearError();
644
645     const egl_display_ptr dp = validate_display(dpy);
646     if (!dp) {
647         return;
648     }
649
650     SurfaceRef _s(dp.get(), surface);
651     if (!_s.get()) {
652         setError(EGL_BAD_SURFACE, EGL_FALSE);
653         return;
654     }
655 }
656
657 // ----------------------------------------------------------------------------
658 // Contexts
659 // ----------------------------------------------------------------------------
660
661 EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config,
662                             EGLContext share_list, const EGLint *attrib_list)
663 {
664     clearError();
665
666     egl_connection_t* cnx = NULL;
667     const egl_display_ptr dp = validate_display_connection(dpy, cnx);
668     if (dp) {
669         if (share_list != EGL_NO_CONTEXT) {
670             if (!ContextRef(dp.get(), share_list).get()) {
671                 return setError(EGL_BAD_CONTEXT, EGL_NO_CONTEXT);
672             }
673             egl_context_t* const c = get_context(share_list);
674             share_list = c->context;
675         }
676         EGLContext context = cnx->egl.eglCreateContext(
677                 dp->disp.dpy, config, share_list, attrib_list);
678         if (context != EGL_NO_CONTEXT) {
679             // figure out if it's a GLESv1 or GLESv2
680             int version = 0;
681             if (attrib_list) {
682                 while (*attrib_list != EGL_NONE) {
683                     GLint attr = *attrib_list++;
684                     GLint value = *attrib_list++;
685                     if (attr == EGL_CONTEXT_CLIENT_VERSION) {
686                         if (value == 1) {
687                             version = egl_connection_t::GLESv1_INDEX;
688                         } else if (value == 2 || value == 3) {
689                             version = egl_connection_t::GLESv2_INDEX;
690                         }
691                     }
692                 };
693             }
694             egl_context_t* c = new egl_context_t(dpy, context, config, cnx,
695                     version);
696             return c;
697         }
698     }
699     return EGL_NO_CONTEXT;
700 }
701
702 EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
703 {
704     clearError();
705
706     const egl_display_ptr dp = validate_display(dpy);
707     if (!dp)
708         return EGL_FALSE;
709
710     ContextRef _c(dp.get(), ctx);
711     if (!_c.get())
712         return setError(EGL_BAD_CONTEXT, EGL_FALSE);
713
714     egl_context_t * const c = get_context(ctx);
715     EGLBoolean result = c->cnx->egl.eglDestroyContext(dp->disp.dpy, c->context);
716     if (result == EGL_TRUE) {
717         _c.terminate();
718     }
719     return result;
720 }
721
722 EGLBoolean eglMakeCurrent(  EGLDisplay dpy, EGLSurface draw,
723                             EGLSurface read, EGLContext ctx)
724 {
725     clearError();
726
727     egl_display_ptr dp = validate_display(dpy);
728     if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
729
730     // If ctx is not EGL_NO_CONTEXT, read is not EGL_NO_SURFACE, or draw is not
731     // EGL_NO_SURFACE, then an EGL_NOT_INITIALIZED error is generated if dpy is
732     // a valid but uninitialized display.
733     if ( (ctx != EGL_NO_CONTEXT) || (read != EGL_NO_SURFACE) ||
734          (draw != EGL_NO_SURFACE) ) {
735         if (!dp->isReady()) return setError(EGL_NOT_INITIALIZED, EGL_FALSE);
736     }
737
738     // get a reference to the object passed in
739     ContextRef _c(dp.get(), ctx);
740     SurfaceRef _d(dp.get(), draw);
741     SurfaceRef _r(dp.get(), read);
742
743     // validate the context (if not EGL_NO_CONTEXT)
744     if ((ctx != EGL_NO_CONTEXT) && !_c.get()) {
745         // EGL_NO_CONTEXT is valid
746         return setError(EGL_BAD_CONTEXT, EGL_FALSE);
747     }
748
749     // these are the underlying implementation's object
750     EGLContext impl_ctx  = EGL_NO_CONTEXT;
751     EGLSurface impl_draw = EGL_NO_SURFACE;
752     EGLSurface impl_read = EGL_NO_SURFACE;
753
754     // these are our objects structs passed in
755     egl_context_t       * c = NULL;
756     egl_surface_t const * d = NULL;
757     egl_surface_t const * r = NULL;
758
759     // these are the current objects structs
760     egl_context_t * cur_c = get_context(getContext());
761
762     if (ctx != EGL_NO_CONTEXT) {
763         c = get_context(ctx);
764         impl_ctx = c->context;
765     } else {
766         // no context given, use the implementation of the current context
767         if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) {
768             // calling eglMakeCurrent( ..., !=0, !=0, EGL_NO_CONTEXT);
769             return setError(EGL_BAD_MATCH, EGL_FALSE);
770         }
771         if (cur_c == NULL) {
772             // no current context
773             // not an error, there is just no current context.
774             return EGL_TRUE;
775         }
776     }
777
778     // retrieve the underlying implementation's draw EGLSurface
779     if (draw != EGL_NO_SURFACE) {
780         if (!_d.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
781         d = get_surface(draw);
782         impl_draw = d->surface;
783     }
784
785     // retrieve the underlying implementation's read EGLSurface
786     if (read != EGL_NO_SURFACE) {
787         if (!_r.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
788         r = get_surface(read);
789         impl_read = r->surface;
790     }
791
792
793     EGLBoolean result = dp->makeCurrent(c, cur_c,
794             draw, read, ctx,
795             impl_draw, impl_read, impl_ctx);
796
797     if (result == EGL_TRUE) {
798         if (c) {
799             setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
800             egl_tls_t::setContext(ctx);
801             _c.acquire();
802             _r.acquire();
803             _d.acquire();
804         } else {
805             setGLHooksThreadSpecific(&gHooksNoContext);
806             egl_tls_t::setContext(EGL_NO_CONTEXT);
807         }
808     } else {
809         // this will ALOGE the error
810         egl_connection_t* const cnx = &gEGLImpl;
811         result = setError(cnx->egl.eglGetError(), EGL_FALSE);
812     }
813     return result;
814 }
815
816
817 EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx,
818                             EGLint attribute, EGLint *value)
819 {
820     clearError();
821
822     const egl_display_ptr dp = validate_display(dpy);
823     if (!dp) return EGL_FALSE;
824
825     ContextRef _c(dp.get(), ctx);
826     if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
827
828     egl_context_t * const c = get_context(ctx);
829     return c->cnx->egl.eglQueryContext(
830             dp->disp.dpy, c->context, attribute, value);
831
832 }
833
834 EGLContext eglGetCurrentContext(void)
835 {
836     // could be called before eglInitialize(), but we wouldn't have a context
837     // then, and this function would correctly return EGL_NO_CONTEXT.
838
839     clearError();
840
841     EGLContext ctx = getContext();
842     return ctx;
843 }
844
845 EGLSurface eglGetCurrentSurface(EGLint readdraw)
846 {
847     // could be called before eglInitialize(), but we wouldn't have a context
848     // then, and this function would correctly return EGL_NO_SURFACE.
849
850     clearError();
851
852     EGLContext ctx = getContext();
853     if (ctx) {
854         egl_context_t const * const c = get_context(ctx);
855         if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
856         switch (readdraw) {
857             case EGL_READ: return c->read;
858             case EGL_DRAW: return c->draw;
859             default: return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
860         }
861     }
862     return EGL_NO_SURFACE;
863 }
864
865 EGLDisplay eglGetCurrentDisplay(void)
866 {
867     // could be called before eglInitialize(), but we wouldn't have a context
868     // then, and this function would correctly return EGL_NO_DISPLAY.
869
870     clearError();
871
872     EGLContext ctx = getContext();
873     if (ctx) {
874         egl_context_t const * const c = get_context(ctx);
875         if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
876         return c->dpy;
877     }
878     return EGL_NO_DISPLAY;
879 }
880
881 EGLBoolean eglWaitGL(void)
882 {
883     clearError();
884
885     egl_connection_t* const cnx = &gEGLImpl;
886     if (!cnx->dso)
887         return setError(EGL_BAD_CONTEXT, EGL_FALSE);
888
889     return cnx->egl.eglWaitGL();
890 }
891
892 EGLBoolean eglWaitNative(EGLint engine)
893 {
894     clearError();
895
896     egl_connection_t* const cnx = &gEGLImpl;
897     if (!cnx->dso)
898         return setError(EGL_BAD_CONTEXT, EGL_FALSE);
899
900     return cnx->egl.eglWaitNative(engine);
901 }
902
903 EGLint eglGetError(void)
904 {
905     EGLint err = EGL_SUCCESS;
906     egl_connection_t* const cnx = &gEGLImpl;
907     if (cnx->dso) {
908         err = cnx->egl.eglGetError();
909     }
910     if (err == EGL_SUCCESS) {
911         err = egl_tls_t::getError();
912     }
913     return err;
914 }
915
916 static __eglMustCastToProperFunctionPointerType findBuiltinWrapper(
917         const char* procname) {
918     const egl_connection_t* cnx = &gEGLImpl;
919     void* proc = NULL;
920
921     proc = dlsym(cnx->libEgl, procname);
922     if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
923
924     proc = dlsym(cnx->libGles2, procname);
925     if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
926
927     proc = dlsym(cnx->libGles1, procname);
928     if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
929
930     return NULL;
931 }
932
933 __eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
934 {
935     // eglGetProcAddress() could be the very first function called
936     // in which case we must make sure we've initialized ourselves, this
937     // happens the first time egl_get_display() is called.
938
939     clearError();
940
941     if (egl_init_drivers() == EGL_FALSE) {
942         setError(EGL_BAD_PARAMETER, NULL);
943         return  NULL;
944     }
945
946     if (FILTER_EXTENSIONS(procname)) {
947         return NULL;
948     }
949
950     __eglMustCastToProperFunctionPointerType addr;
951     addr = findProcAddress(procname, sExtensionMap, NELEM(sExtensionMap));
952     if (addr) return addr;
953
954     addr = findBuiltinWrapper(procname);
955     if (addr) return addr;
956
957     // this protects accesses to sGLExtentionMap and sGLExtentionSlot
958     pthread_mutex_lock(&sExtensionMapMutex);
959
960         /*
961          * Since eglGetProcAddress() is not associated to anything, it needs
962          * to return a function pointer that "works" regardless of what
963          * the current context is.
964          *
965          * For this reason, we return a "forwarder", a small stub that takes
966          * care of calling the function associated with the context
967          * currently bound.
968          *
969          * We first look for extensions we've already resolved, if we're seeing
970          * this extension for the first time, we go through all our
971          * implementations and call eglGetProcAddress() and record the
972          * result in the appropriate implementation hooks and return the
973          * address of the forwarder corresponding to that hook set.
974          *
975          */
976
977         const String8 name(procname);
978         addr = sGLExtentionMap.valueFor(name);
979         const int slot = sGLExtentionSlot;
980
981         ALOGE_IF(slot >= MAX_NUMBER_OF_GL_EXTENSIONS,
982                 "no more slots for eglGetProcAddress(\"%s\")",
983                 procname);
984
985         if (!addr && (slot < MAX_NUMBER_OF_GL_EXTENSIONS)) {
986             bool found = false;
987
988             egl_connection_t* const cnx = &gEGLImpl;
989             if (cnx->dso && cnx->egl.eglGetProcAddress) {
990                 // Extensions are independent of the bound context
991                 addr =
992                 cnx->hooks[egl_connection_t::GLESv1_INDEX]->ext.extensions[slot] =
993                 cnx->hooks[egl_connection_t::GLESv2_INDEX]->ext.extensions[slot] =
994                         cnx->egl.eglGetProcAddress(procname);
995                 if (addr) found = true;
996             }
997
998             if (found) {
999                 addr = gExtensionForwarders[slot];
1000                 sGLExtentionMap.add(name, addr);
1001                 sGLExtentionSlot++;
1002             }
1003         }
1004
1005     pthread_mutex_unlock(&sExtensionMapMutex);
1006     return addr;
1007 }
1008
1009 class FrameCompletionThread : public Thread {
1010 public:
1011
1012     static void queueSync(EGLSyncKHR sync) {
1013         static sp<FrameCompletionThread> thread(new FrameCompletionThread);
1014         static bool running = false;
1015         if (!running) {
1016             thread->run("GPUFrameCompletion");
1017             running = true;
1018         }
1019         {
1020             Mutex::Autolock lock(thread->mMutex);
1021             ScopedTrace st(ATRACE_TAG, String8::format("kicked off frame %d",
1022                     thread->mFramesQueued).string());
1023             thread->mQueue.push_back(sync);
1024             thread->mCondition.signal();
1025             thread->mFramesQueued++;
1026             ATRACE_INT("GPU Frames Outstanding", thread->mQueue.size());
1027         }
1028     }
1029
1030 private:
1031     FrameCompletionThread() : mFramesQueued(0), mFramesCompleted(0) {}
1032
1033     virtual bool threadLoop() {
1034         EGLSyncKHR sync;
1035         uint32_t frameNum;
1036         {
1037             Mutex::Autolock lock(mMutex);
1038             while (mQueue.isEmpty()) {
1039                 mCondition.wait(mMutex);
1040             }
1041             sync = mQueue[0];
1042             frameNum = mFramesCompleted;
1043         }
1044         EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
1045         {
1046             ScopedTrace st(ATRACE_TAG, String8::format("waiting for frame %d",
1047                     frameNum).string());
1048             EGLint result = eglClientWaitSyncKHR(dpy, sync, 0, EGL_FOREVER_KHR);
1049             if (result == EGL_FALSE) {
1050                 ALOGE("FrameCompletion: error waiting for fence: %#x", eglGetError());
1051             } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
1052                 ALOGE("FrameCompletion: timeout waiting for fence");
1053             }
1054             eglDestroySyncKHR(dpy, sync);
1055         }
1056         {
1057             Mutex::Autolock lock(mMutex);
1058             mQueue.removeAt(0);
1059             mFramesCompleted++;
1060             ATRACE_INT("GPU Frames Outstanding", mQueue.size());
1061         }
1062         return true;
1063     }
1064
1065     uint32_t mFramesQueued;
1066     uint32_t mFramesCompleted;
1067     Vector<EGLSyncKHR> mQueue;
1068     Condition mCondition;
1069     Mutex mMutex;
1070 };
1071
1072 EGLBoolean eglSwapBuffersWithDamageKHR(EGLDisplay dpy, EGLSurface draw,
1073         EGLint *rects, EGLint n_rects)
1074 {
1075     ATRACE_CALL();
1076     clearError();
1077
1078     const egl_display_ptr dp = validate_display(dpy);
1079     if (!dp) return EGL_FALSE;
1080
1081     SurfaceRef _s(dp.get(), draw);
1082     if (!_s.get())
1083         return setError(EGL_BAD_SURFACE, EGL_FALSE);
1084
1085     egl_surface_t const * const s = get_surface(draw);
1086
1087     if (CC_UNLIKELY(dp->traceGpuCompletion)) {
1088         EGLSyncKHR sync = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, NULL);
1089         if (sync != EGL_NO_SYNC_KHR) {
1090             FrameCompletionThread::queueSync(sync);
1091         }
1092     }
1093
1094     if (CC_UNLIKELY(dp->finishOnSwap)) {
1095         uint32_t pixel;
1096         egl_context_t * const c = get_context( egl_tls_t::getContext() );
1097         if (c) {
1098             // glReadPixels() ensures that the frame is complete
1099             s->cnx->hooks[c->version]->gl.glReadPixels(0,0,1,1,
1100                     GL_RGBA,GL_UNSIGNED_BYTE,&pixel);
1101         }
1102     }
1103
1104     if (n_rects == 0) {
1105         return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface);
1106     }
1107
1108     Vector<android_native_rect_t> androidRects;
1109     for (int r = 0; r < n_rects; ++r) {
1110         int offset = r * 4;
1111         int x = rects[offset];
1112         int y = rects[offset + 1];
1113         int width = rects[offset + 2];
1114         int height = rects[offset + 3];
1115         android_native_rect_t androidRect;
1116         androidRect.left = x;
1117         androidRect.top = y + height;
1118         androidRect.right = x + width;
1119         androidRect.bottom = y;
1120         androidRects.push_back(androidRect);
1121     }
1122     native_window_set_surface_damage(s->win.get(), androidRects.array(),
1123             androidRects.size());
1124
1125     if (s->cnx->egl.eglSwapBuffersWithDamageKHR) {
1126         return s->cnx->egl.eglSwapBuffersWithDamageKHR(dp->disp.dpy, s->surface,
1127                 rects, n_rects);
1128     } else {
1129         return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface);
1130     }
1131 }
1132
1133 EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
1134 {
1135     return eglSwapBuffersWithDamageKHR(dpy, surface, NULL, 0);
1136 }
1137
1138 EGLBoolean eglCopyBuffers(  EGLDisplay dpy, EGLSurface surface,
1139                             NativePixmapType target)
1140 {
1141     clearError();
1142
1143     const egl_display_ptr dp = validate_display(dpy);
1144     if (!dp) return EGL_FALSE;
1145
1146     SurfaceRef _s(dp.get(), surface);
1147     if (!_s.get())
1148         return setError(EGL_BAD_SURFACE, EGL_FALSE);
1149
1150     egl_surface_t const * const s = get_surface(surface);
1151     return s->cnx->egl.eglCopyBuffers(dp->disp.dpy, s->surface, target);
1152 }
1153
1154 const char* eglQueryString(EGLDisplay dpy, EGLint name)
1155 {
1156     clearError();
1157
1158     const egl_display_ptr dp = validate_display(dpy);
1159     if (!dp) return (const char *) NULL;
1160
1161     switch (name) {
1162         case EGL_VENDOR:
1163             return dp->getVendorString();
1164         case EGL_VERSION:
1165             return dp->getVersionString();
1166         case EGL_EXTENSIONS:
1167             return dp->getExtensionString();
1168         case EGL_CLIENT_APIS:
1169             return dp->getClientApiString();
1170     }
1171     return setError(EGL_BAD_PARAMETER, (const char *)0);
1172 }
1173
1174 EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name)
1175 {
1176     clearError();
1177
1178     const egl_display_ptr dp = validate_display(dpy);
1179     if (!dp) return (const char *) NULL;
1180
1181     switch (name) {
1182         case EGL_VENDOR:
1183             return dp->disp.queryString.vendor;
1184         case EGL_VERSION:
1185             return dp->disp.queryString.version;
1186         case EGL_EXTENSIONS:
1187             return dp->disp.queryString.extensions;
1188         case EGL_CLIENT_APIS:
1189             return dp->disp.queryString.clientApi;
1190     }
1191     return setError(EGL_BAD_PARAMETER, (const char *)0);
1192 }
1193
1194 // ----------------------------------------------------------------------------
1195 // EGL 1.1
1196 // ----------------------------------------------------------------------------
1197
1198 EGLBoolean eglSurfaceAttrib(
1199         EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
1200 {
1201     clearError();
1202
1203     const egl_display_ptr dp = validate_display(dpy);
1204     if (!dp) return EGL_FALSE;
1205
1206     SurfaceRef _s(dp.get(), surface);
1207     if (!_s.get())
1208         return setError(EGL_BAD_SURFACE, EGL_FALSE);
1209
1210     egl_surface_t * const s = get_surface(surface);
1211
1212     if (attribute == EGL_FRONT_BUFFER_AUTO_REFRESH_ANDROID) {
1213         int err = native_window_set_auto_refresh(s->win.get(),
1214             value ? true : false);
1215         return (err == NO_ERROR) ? EGL_TRUE :
1216             setError(EGL_BAD_SURFACE, EGL_FALSE);
1217     }
1218
1219 #if ENABLE_EGL_ANDROID_GET_FRAME_TIMESTAMPS
1220     if (attribute == EGL_TIMESTAMPS_ANDROID) {
1221         s->enableTimestamps = value;
1222         return EGL_TRUE;
1223     }
1224 #endif
1225
1226     if (s->cnx->egl.eglSurfaceAttrib) {
1227         return s->cnx->egl.eglSurfaceAttrib(
1228                 dp->disp.dpy, s->surface, attribute, value);
1229     }
1230     return setError(EGL_BAD_SURFACE, EGL_FALSE);
1231 }
1232
1233 EGLBoolean eglBindTexImage(
1234         EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1235 {
1236     clearError();
1237
1238     const egl_display_ptr dp = validate_display(dpy);
1239     if (!dp) return EGL_FALSE;
1240
1241     SurfaceRef _s(dp.get(), surface);
1242     if (!_s.get())
1243         return setError(EGL_BAD_SURFACE, EGL_FALSE);
1244
1245     egl_surface_t const * const s = get_surface(surface);
1246     if (s->cnx->egl.eglBindTexImage) {
1247         return s->cnx->egl.eglBindTexImage(
1248                 dp->disp.dpy, s->surface, buffer);
1249     }
1250     return setError(EGL_BAD_SURFACE, EGL_FALSE);
1251 }
1252
1253 EGLBoolean eglReleaseTexImage(
1254         EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1255 {
1256     clearError();
1257
1258     const egl_display_ptr dp = validate_display(dpy);
1259     if (!dp) return EGL_FALSE;
1260
1261     SurfaceRef _s(dp.get(), surface);
1262     if (!_s.get())
1263         return setError(EGL_BAD_SURFACE, EGL_FALSE);
1264
1265     egl_surface_t const * const s = get_surface(surface);
1266     if (s->cnx->egl.eglReleaseTexImage) {
1267         return s->cnx->egl.eglReleaseTexImage(
1268                 dp->disp.dpy, s->surface, buffer);
1269     }
1270     return setError(EGL_BAD_SURFACE, EGL_FALSE);
1271 }
1272
1273 EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
1274 {
1275     clearError();
1276
1277     const egl_display_ptr dp = validate_display(dpy);
1278     if (!dp) return EGL_FALSE;
1279
1280     EGLBoolean res = EGL_TRUE;
1281     egl_connection_t* const cnx = &gEGLImpl;
1282     if (cnx->dso && cnx->egl.eglSwapInterval) {
1283         res = cnx->egl.eglSwapInterval(dp->disp.dpy, interval);
1284     }
1285
1286     return res;
1287 }
1288
1289
1290 // ----------------------------------------------------------------------------
1291 // EGL 1.2
1292 // ----------------------------------------------------------------------------
1293
1294 EGLBoolean eglWaitClient(void)
1295 {
1296     clearError();
1297
1298     egl_connection_t* const cnx = &gEGLImpl;
1299     if (!cnx->dso)
1300         return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1301
1302     EGLBoolean res;
1303     if (cnx->egl.eglWaitClient) {
1304         res = cnx->egl.eglWaitClient();
1305     } else {
1306         res = cnx->egl.eglWaitGL();
1307     }
1308     return res;
1309 }
1310
1311 EGLBoolean eglBindAPI(EGLenum api)
1312 {
1313     clearError();
1314
1315     if (egl_init_drivers() == EGL_FALSE) {
1316         return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1317     }
1318
1319     // bind this API on all EGLs
1320     EGLBoolean res = EGL_TRUE;
1321     egl_connection_t* const cnx = &gEGLImpl;
1322     if (cnx->dso && cnx->egl.eglBindAPI) {
1323         res = cnx->egl.eglBindAPI(api);
1324     }
1325     return res;
1326 }
1327
1328 EGLenum eglQueryAPI(void)
1329 {
1330     clearError();
1331
1332     if (egl_init_drivers() == EGL_FALSE) {
1333         return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1334     }
1335
1336     egl_connection_t* const cnx = &gEGLImpl;
1337     if (cnx->dso && cnx->egl.eglQueryAPI) {
1338         return cnx->egl.eglQueryAPI();
1339     }
1340
1341     // or, it can only be OpenGL ES
1342     return EGL_OPENGL_ES_API;
1343 }
1344
1345 EGLBoolean eglReleaseThread(void)
1346 {
1347     clearError();
1348
1349     // If there is context bound to the thread, release it
1350     egl_display_t::loseCurrent(get_context(getContext()));
1351
1352     egl_connection_t* const cnx = &gEGLImpl;
1353     if (cnx->dso && cnx->egl.eglReleaseThread) {
1354         cnx->egl.eglReleaseThread();
1355     }
1356     egl_tls_t::clearTLS();
1357     return EGL_TRUE;
1358 }
1359
1360 EGLSurface eglCreatePbufferFromClientBuffer(
1361           EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
1362           EGLConfig config, const EGLint *attrib_list)
1363 {
1364     clearError();
1365
1366     egl_connection_t* cnx = NULL;
1367     const egl_display_ptr dp = validate_display_connection(dpy, cnx);
1368     if (!dp) return EGL_FALSE;
1369     if (cnx->egl.eglCreatePbufferFromClientBuffer) {
1370         return cnx->egl.eglCreatePbufferFromClientBuffer(
1371                 dp->disp.dpy, buftype, buffer, config, attrib_list);
1372     }
1373     return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE);
1374 }
1375
1376 // ----------------------------------------------------------------------------
1377 // EGL_EGLEXT_VERSION 3
1378 // ----------------------------------------------------------------------------
1379
1380 EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface,
1381         const EGLint *attrib_list)
1382 {
1383     clearError();
1384
1385     const egl_display_ptr dp = validate_display(dpy);
1386     if (!dp) return EGL_FALSE;
1387
1388     SurfaceRef _s(dp.get(), surface);
1389     if (!_s.get())
1390         return setError(EGL_BAD_SURFACE, EGL_FALSE);
1391
1392     egl_surface_t const * const s = get_surface(surface);
1393     if (s->cnx->egl.eglLockSurfaceKHR) {
1394         return s->cnx->egl.eglLockSurfaceKHR(
1395                 dp->disp.dpy, s->surface, attrib_list);
1396     }
1397     return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1398 }
1399
1400 EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface)
1401 {
1402     clearError();
1403
1404     const egl_display_ptr dp = validate_display(dpy);
1405     if (!dp) return EGL_FALSE;
1406
1407     SurfaceRef _s(dp.get(), surface);
1408     if (!_s.get())
1409         return setError(EGL_BAD_SURFACE, EGL_FALSE);
1410
1411     egl_surface_t const * const s = get_surface(surface);
1412     if (s->cnx->egl.eglUnlockSurfaceKHR) {
1413         return s->cnx->egl.eglUnlockSurfaceKHR(dp->disp.dpy, s->surface);
1414     }
1415     return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1416 }
1417
1418 EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
1419         EGLClientBuffer buffer, const EGLint *attrib_list)
1420 {
1421     clearError();
1422
1423     const egl_display_ptr dp = validate_display(dpy);
1424     if (!dp) return EGL_NO_IMAGE_KHR;
1425
1426     ContextRef _c(dp.get(), ctx);
1427     egl_context_t * const c = _c.get();
1428
1429     EGLImageKHR result = EGL_NO_IMAGE_KHR;
1430     egl_connection_t* const cnx = &gEGLImpl;
1431     if (cnx->dso && cnx->egl.eglCreateImageKHR) {
1432         result = cnx->egl.eglCreateImageKHR(
1433                 dp->disp.dpy,
1434                 c ? c->context : EGL_NO_CONTEXT,
1435                 target, buffer, attrib_list);
1436     }
1437     return result;
1438 }
1439
1440 EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
1441 {
1442     clearError();
1443
1444     const egl_display_ptr dp = validate_display(dpy);
1445     if (!dp) return EGL_FALSE;
1446
1447     EGLBoolean result = EGL_FALSE;
1448     egl_connection_t* const cnx = &gEGLImpl;
1449     if (cnx->dso && cnx->egl.eglDestroyImageKHR) {
1450         result = cnx->egl.eglDestroyImageKHR(dp->disp.dpy, img);
1451     }
1452     return result;
1453 }
1454
1455 // ----------------------------------------------------------------------------
1456 // EGL_EGLEXT_VERSION 5
1457 // ----------------------------------------------------------------------------
1458
1459
1460 EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
1461 {
1462     clearError();
1463
1464     const egl_display_ptr dp = validate_display(dpy);
1465     if (!dp) return EGL_NO_SYNC_KHR;
1466
1467     EGLSyncKHR result = EGL_NO_SYNC_KHR;
1468     egl_connection_t* const cnx = &gEGLImpl;
1469     if (cnx->dso && cnx->egl.eglCreateSyncKHR) {
1470         result = cnx->egl.eglCreateSyncKHR(dp->disp.dpy, type, attrib_list);
1471     }
1472     return result;
1473 }
1474
1475 EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
1476 {
1477     clearError();
1478
1479     const egl_display_ptr dp = validate_display(dpy);
1480     if (!dp) return EGL_FALSE;
1481
1482     EGLBoolean result = EGL_FALSE;
1483     egl_connection_t* const cnx = &gEGLImpl;
1484     if (cnx->dso && cnx->egl.eglDestroySyncKHR) {
1485         result = cnx->egl.eglDestroySyncKHR(dp->disp.dpy, sync);
1486     }
1487     return result;
1488 }
1489
1490 EGLBoolean eglSignalSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode) {
1491     clearError();
1492
1493     const egl_display_ptr dp = validate_display(dpy);
1494     if (!dp) return EGL_FALSE;
1495
1496     EGLBoolean result = EGL_FALSE;
1497     egl_connection_t* const cnx = &gEGLImpl;
1498     if (cnx->dso && cnx->egl.eglSignalSyncKHR) {
1499         result = cnx->egl.eglSignalSyncKHR(
1500                 dp->disp.dpy, sync, mode);
1501     }
1502     return result;
1503 }
1504
1505 EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync,
1506         EGLint flags, EGLTimeKHR timeout)
1507 {
1508     clearError();
1509
1510     const egl_display_ptr dp = validate_display(dpy);
1511     if (!dp) return EGL_FALSE;
1512
1513     EGLBoolean result = EGL_FALSE;
1514     egl_connection_t* const cnx = &gEGLImpl;
1515     if (cnx->dso && cnx->egl.eglClientWaitSyncKHR) {
1516         result = cnx->egl.eglClientWaitSyncKHR(
1517                 dp->disp.dpy, sync, flags, timeout);
1518     }
1519     return result;
1520 }
1521
1522 EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync,
1523         EGLint attribute, EGLint *value)
1524 {
1525     clearError();
1526
1527     const egl_display_ptr dp = validate_display(dpy);
1528     if (!dp) return EGL_FALSE;
1529
1530     EGLBoolean result = EGL_FALSE;
1531     egl_connection_t* const cnx = &gEGLImpl;
1532     if (cnx->dso && cnx->egl.eglGetSyncAttribKHR) {
1533         result = cnx->egl.eglGetSyncAttribKHR(
1534                 dp->disp.dpy, sync, attribute, value);
1535     }
1536     return result;
1537 }
1538
1539 EGLStreamKHR eglCreateStreamKHR(EGLDisplay dpy, const EGLint *attrib_list)
1540 {
1541     clearError();
1542
1543     const egl_display_ptr dp = validate_display(dpy);
1544     if (!dp) return EGL_NO_STREAM_KHR;
1545
1546     EGLStreamKHR result = EGL_NO_STREAM_KHR;
1547     egl_connection_t* const cnx = &gEGLImpl;
1548     if (cnx->dso && cnx->egl.eglCreateStreamKHR) {
1549         result = cnx->egl.eglCreateStreamKHR(
1550                 dp->disp.dpy, attrib_list);
1551     }
1552     return result;
1553 }
1554
1555 EGLBoolean eglDestroyStreamKHR(EGLDisplay dpy, EGLStreamKHR stream)
1556 {
1557     clearError();
1558
1559     const egl_display_ptr dp = validate_display(dpy);
1560     if (!dp) return EGL_FALSE;
1561
1562     EGLBoolean result = EGL_FALSE;
1563     egl_connection_t* const cnx = &gEGLImpl;
1564     if (cnx->dso && cnx->egl.eglDestroyStreamKHR) {
1565         result = cnx->egl.eglDestroyStreamKHR(
1566                 dp->disp.dpy, stream);
1567     }
1568     return result;
1569 }
1570
1571 EGLBoolean eglStreamAttribKHR(EGLDisplay dpy, EGLStreamKHR stream,
1572         EGLenum attribute, EGLint value)
1573 {
1574     clearError();
1575
1576     const egl_display_ptr dp = validate_display(dpy);
1577     if (!dp) return EGL_FALSE;
1578
1579     EGLBoolean result = EGL_FALSE;
1580     egl_connection_t* const cnx = &gEGLImpl;
1581     if (cnx->dso && cnx->egl.eglStreamAttribKHR) {
1582         result = cnx->egl.eglStreamAttribKHR(
1583                 dp->disp.dpy, stream, attribute, value);
1584     }
1585     return result;
1586 }
1587
1588 EGLBoolean eglQueryStreamKHR(EGLDisplay dpy, EGLStreamKHR stream,
1589         EGLenum attribute, EGLint *value)
1590 {
1591     clearError();
1592
1593     const egl_display_ptr dp = validate_display(dpy);
1594     if (!dp) return EGL_FALSE;
1595
1596     EGLBoolean result = EGL_FALSE;
1597     egl_connection_t* const cnx = &gEGLImpl;
1598     if (cnx->dso && cnx->egl.eglQueryStreamKHR) {
1599         result = cnx->egl.eglQueryStreamKHR(
1600                 dp->disp.dpy, stream, attribute, value);
1601     }
1602     return result;
1603 }
1604
1605 EGLBoolean eglQueryStreamu64KHR(EGLDisplay dpy, EGLStreamKHR stream,
1606         EGLenum attribute, EGLuint64KHR *value)
1607 {
1608     clearError();
1609
1610     const egl_display_ptr dp = validate_display(dpy);
1611     if (!dp) return EGL_FALSE;
1612
1613     EGLBoolean result = EGL_FALSE;
1614     egl_connection_t* const cnx = &gEGLImpl;
1615     if (cnx->dso && cnx->egl.eglQueryStreamu64KHR) {
1616         result = cnx->egl.eglQueryStreamu64KHR(
1617                 dp->disp.dpy, stream, attribute, value);
1618     }
1619     return result;
1620 }
1621
1622 EGLBoolean eglQueryStreamTimeKHR(EGLDisplay dpy, EGLStreamKHR stream,
1623         EGLenum attribute, EGLTimeKHR *value)
1624 {
1625     clearError();
1626
1627     const egl_display_ptr dp = validate_display(dpy);
1628     if (!dp) return EGL_FALSE;
1629
1630     EGLBoolean result = EGL_FALSE;
1631     egl_connection_t* const cnx = &gEGLImpl;
1632     if (cnx->dso && cnx->egl.eglQueryStreamTimeKHR) {
1633         result = cnx->egl.eglQueryStreamTimeKHR(
1634                 dp->disp.dpy, stream, attribute, value);
1635     }
1636     return result;
1637 }
1638
1639 EGLSurface eglCreateStreamProducerSurfaceKHR(EGLDisplay dpy, EGLConfig config,
1640         EGLStreamKHR stream, const EGLint *attrib_list)
1641 {
1642     clearError();
1643
1644     egl_display_ptr dp = validate_display(dpy);
1645     if (!dp) return EGL_NO_SURFACE;
1646
1647     egl_connection_t* const cnx = &gEGLImpl;
1648     if (cnx->dso && cnx->egl.eglCreateStreamProducerSurfaceKHR) {
1649         EGLSurface surface = cnx->egl.eglCreateStreamProducerSurfaceKHR(
1650                 dp->disp.dpy, config, stream, attrib_list);
1651         if (surface != EGL_NO_SURFACE) {
1652             egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL,
1653                     surface, cnx);
1654             return s;
1655         }
1656     }
1657     return EGL_NO_SURFACE;
1658 }
1659
1660 EGLBoolean eglStreamConsumerGLTextureExternalKHR(EGLDisplay dpy,
1661         EGLStreamKHR stream)
1662 {
1663     clearError();
1664
1665     const egl_display_ptr dp = validate_display(dpy);
1666     if (!dp) return EGL_FALSE;
1667
1668     EGLBoolean result = EGL_FALSE;
1669     egl_connection_t* const cnx = &gEGLImpl;
1670     if (cnx->dso && cnx->egl.eglStreamConsumerGLTextureExternalKHR) {
1671         result = cnx->egl.eglStreamConsumerGLTextureExternalKHR(
1672                 dp->disp.dpy, stream);
1673     }
1674     return result;
1675 }
1676
1677 EGLBoolean eglStreamConsumerAcquireKHR(EGLDisplay dpy,
1678         EGLStreamKHR stream)
1679 {
1680     clearError();
1681
1682     const egl_display_ptr dp = validate_display(dpy);
1683     if (!dp) return EGL_FALSE;
1684
1685     EGLBoolean result = EGL_FALSE;
1686     egl_connection_t* const cnx = &gEGLImpl;
1687     if (cnx->dso && cnx->egl.eglStreamConsumerAcquireKHR) {
1688         result = cnx->egl.eglStreamConsumerAcquireKHR(
1689                 dp->disp.dpy, stream);
1690     }
1691     return result;
1692 }
1693
1694 EGLBoolean eglStreamConsumerReleaseKHR(EGLDisplay dpy,
1695         EGLStreamKHR stream)
1696 {
1697     clearError();
1698
1699     const egl_display_ptr dp = validate_display(dpy);
1700     if (!dp) return EGL_FALSE;
1701
1702     EGLBoolean result = EGL_FALSE;
1703     egl_connection_t* const cnx = &gEGLImpl;
1704     if (cnx->dso && cnx->egl.eglStreamConsumerReleaseKHR) {
1705         result = cnx->egl.eglStreamConsumerReleaseKHR(
1706                 dp->disp.dpy, stream);
1707     }
1708     return result;
1709 }
1710
1711 EGLNativeFileDescriptorKHR eglGetStreamFileDescriptorKHR(
1712         EGLDisplay dpy, EGLStreamKHR stream)
1713 {
1714     clearError();
1715
1716     const egl_display_ptr dp = validate_display(dpy);
1717     if (!dp) return EGL_NO_FILE_DESCRIPTOR_KHR;
1718
1719     EGLNativeFileDescriptorKHR result = EGL_NO_FILE_DESCRIPTOR_KHR;
1720     egl_connection_t* const cnx = &gEGLImpl;
1721     if (cnx->dso && cnx->egl.eglGetStreamFileDescriptorKHR) {
1722         result = cnx->egl.eglGetStreamFileDescriptorKHR(
1723                 dp->disp.dpy, stream);
1724     }
1725     return result;
1726 }
1727
1728 EGLStreamKHR eglCreateStreamFromFileDescriptorKHR(
1729         EGLDisplay dpy, EGLNativeFileDescriptorKHR file_descriptor)
1730 {
1731     clearError();
1732
1733     const egl_display_ptr dp = validate_display(dpy);
1734     if (!dp) return EGL_NO_STREAM_KHR;
1735
1736     EGLStreamKHR result = EGL_NO_STREAM_KHR;
1737     egl_connection_t* const cnx = &gEGLImpl;
1738     if (cnx->dso && cnx->egl.eglCreateStreamFromFileDescriptorKHR) {
1739         result = cnx->egl.eglCreateStreamFromFileDescriptorKHR(
1740                 dp->disp.dpy, file_descriptor);
1741     }
1742     return result;
1743 }
1744
1745 // ----------------------------------------------------------------------------
1746 // EGL_EGLEXT_VERSION 15
1747 // ----------------------------------------------------------------------------
1748
1749 EGLint eglWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags) {
1750     clearError();
1751     const egl_display_ptr dp = validate_display(dpy);
1752     if (!dp) return EGL_FALSE;
1753     EGLint result = EGL_FALSE;
1754     egl_connection_t* const cnx = &gEGLImpl;
1755     if (cnx->dso && cnx->egl.eglWaitSyncKHR) {
1756         result = cnx->egl.eglWaitSyncKHR(dp->disp.dpy, sync, flags);
1757     }
1758     return result;
1759 }
1760
1761 // ----------------------------------------------------------------------------
1762 // ANDROID extensions
1763 // ----------------------------------------------------------------------------
1764
1765 EGLint eglDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSyncKHR sync)
1766 {
1767     clearError();
1768
1769     const egl_display_ptr dp = validate_display(dpy);
1770     if (!dp) return EGL_NO_NATIVE_FENCE_FD_ANDROID;
1771
1772     EGLint result = EGL_NO_NATIVE_FENCE_FD_ANDROID;
1773     egl_connection_t* const cnx = &gEGLImpl;
1774     if (cnx->dso && cnx->egl.eglDupNativeFenceFDANDROID) {
1775         result = cnx->egl.eglDupNativeFenceFDANDROID(dp->disp.dpy, sync);
1776     }
1777     return result;
1778 }
1779
1780 EGLBoolean eglPresentationTimeANDROID(EGLDisplay dpy, EGLSurface surface,
1781         EGLnsecsANDROID time)
1782 {
1783     clearError();
1784
1785     const egl_display_ptr dp = validate_display(dpy);
1786     if (!dp) {
1787         return EGL_FALSE;
1788     }
1789
1790     SurfaceRef _s(dp.get(), surface);
1791     if (!_s.get()) {
1792         setError(EGL_BAD_SURFACE, EGL_FALSE);
1793         return EGL_FALSE;
1794     }
1795
1796     egl_surface_t const * const s = get_surface(surface);
1797     native_window_set_buffers_timestamp(s->win.get(), time);
1798
1799     return EGL_TRUE;
1800 }
1801
1802 EGLClientBuffer eglCreateNativeClientBufferANDROID(const EGLint *attrib_list)
1803 {
1804     clearError();
1805
1806     int usage = 0;
1807     uint32_t width = 0;
1808     uint32_t height = 0;
1809     uint32_t format = 0;
1810     uint32_t red_size = 0;
1811     uint32_t green_size = 0;
1812     uint32_t blue_size = 0;
1813     uint32_t alpha_size = 0;
1814
1815 #define GET_NONNEGATIVE_VALUE(case_name, target) \
1816     case case_name: \
1817         if (value >= 0) { \
1818             target = value; \
1819         } else { \
1820             return setError(EGL_BAD_PARAMETER, (EGLClientBuffer)0); \
1821         } \
1822         break
1823
1824     if (attrib_list) {
1825         while (*attrib_list != EGL_NONE) {
1826             GLint attr = *attrib_list++;
1827             GLint value = *attrib_list++;
1828             switch (attr) {
1829                 GET_NONNEGATIVE_VALUE(EGL_WIDTH, width);
1830                 GET_NONNEGATIVE_VALUE(EGL_HEIGHT, height);
1831                 GET_NONNEGATIVE_VALUE(EGL_RED_SIZE, red_size);
1832                 GET_NONNEGATIVE_VALUE(EGL_GREEN_SIZE, green_size);
1833                 GET_NONNEGATIVE_VALUE(EGL_BLUE_SIZE, blue_size);
1834                 GET_NONNEGATIVE_VALUE(EGL_ALPHA_SIZE, alpha_size);
1835                 case EGL_NATIVE_BUFFER_USAGE_ANDROID:
1836                     if (value & EGL_NATIVE_BUFFER_USAGE_PROTECTED_BIT_ANDROID) {
1837                         usage |= GRALLOC_USAGE_PROTECTED;
1838                     }
1839                     if (value & EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_BIT_ANDROID) {
1840                         usage |= GRALLOC_USAGE_HW_RENDER;
1841                     }
1842                     if (value & EGL_NATIVE_BUFFER_USAGE_TEXTURE_BIT_ANDROID) {
1843                         usage |= GRALLOC_USAGE_HW_TEXTURE;
1844                     }
1845                     // The buffer must be used for either a texture or a
1846                     // renderbuffer.
1847                     if ((value & EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_BIT_ANDROID) &&
1848                         (value & EGL_NATIVE_BUFFER_USAGE_TEXTURE_BIT_ANDROID)) {
1849                         return setError(EGL_BAD_PARAMETER, (EGLClientBuffer)0);
1850                     }
1851                     break;
1852                 default:
1853                     return setError(EGL_BAD_PARAMETER, (EGLClientBuffer)0);
1854             }
1855         }
1856     }
1857 #undef GET_NONNEGATIVE_VALUE
1858
1859     // Validate format.
1860     if (red_size == 8 && green_size == 8 && blue_size == 8) {
1861         if (alpha_size == 8) {
1862             format = HAL_PIXEL_FORMAT_RGBA_8888;
1863         } else {
1864             format = HAL_PIXEL_FORMAT_RGB_888;
1865         }
1866     } else if (red_size == 5 && green_size == 6 && blue_size == 5 &&
1867                alpha_size == 0) {
1868         format = HAL_PIXEL_FORMAT_RGB_565;
1869     } else {
1870         ALOGE("Invalid native pixel format { r=%d, g=%d, b=%d, a=%d }",
1871                 red_size, green_size, blue_size, alpha_size);
1872         return setError(EGL_BAD_PARAMETER, (EGLClientBuffer)0);
1873     }
1874
1875     GraphicBuffer* gBuffer = new GraphicBuffer(width, height, format, usage,
1876             std::string("[eglCreateNativeClientBufferANDROID pid ") +
1877             std::to_string(getpid()) + ']');
1878     const status_t err = gBuffer->initCheck();
1879     if (err != NO_ERROR) {
1880         ALOGE("Unable to create native buffer { w=%d, h=%d, f=%d, u=%#x }: %#x",
1881                 width, height, format, usage, err);
1882         // Destroy the buffer.
1883         sp<GraphicBuffer> holder(gBuffer);
1884         return setError(EGL_BAD_ALLOC, (EGLClientBuffer)0);
1885     }
1886     ALOGD("Created new native buffer %p { w=%d, h=%d, f=%d, u=%#x }",
1887             gBuffer, width, height, format, usage);
1888     return static_cast<EGLClientBuffer>(gBuffer->getNativeBuffer());
1889 }
1890
1891 // ----------------------------------------------------------------------------
1892 // NVIDIA extensions
1893 // ----------------------------------------------------------------------------
1894 EGLuint64NV eglGetSystemTimeFrequencyNV()
1895 {
1896     clearError();
1897
1898     if (egl_init_drivers() == EGL_FALSE) {
1899         return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1900     }
1901
1902     EGLuint64NV ret = 0;
1903     egl_connection_t* const cnx = &gEGLImpl;
1904
1905     if (cnx->dso && cnx->egl.eglGetSystemTimeFrequencyNV) {
1906         return cnx->egl.eglGetSystemTimeFrequencyNV();
1907     }
1908
1909     return setErrorQuiet(EGL_BAD_DISPLAY, 0);
1910 }
1911
1912 EGLuint64NV eglGetSystemTimeNV()
1913 {
1914     clearError();
1915
1916     if (egl_init_drivers() == EGL_FALSE) {
1917         return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1918     }
1919
1920     EGLuint64NV ret = 0;
1921     egl_connection_t* const cnx = &gEGLImpl;
1922
1923     if (cnx->dso && cnx->egl.eglGetSystemTimeNV) {
1924         return cnx->egl.eglGetSystemTimeNV();
1925     }
1926
1927     return setErrorQuiet(EGL_BAD_DISPLAY, 0);
1928 }
1929
1930 // ----------------------------------------------------------------------------
1931 // Partial update extension
1932 // ----------------------------------------------------------------------------
1933 EGLBoolean eglSetDamageRegionKHR(EGLDisplay dpy, EGLSurface surface,
1934         EGLint *rects, EGLint n_rects)
1935 {
1936     clearError();
1937
1938     const egl_display_ptr dp = validate_display(dpy);
1939     if (!dp) {
1940         setError(EGL_BAD_DISPLAY, EGL_FALSE);
1941         return EGL_FALSE;
1942     }
1943
1944     SurfaceRef _s(dp.get(), surface);
1945     if (!_s.get()) {
1946         setError(EGL_BAD_SURFACE, EGL_FALSE);
1947         return EGL_FALSE;
1948     }
1949
1950     egl_surface_t const * const s = get_surface(surface);
1951     if (s->cnx->egl.eglSetDamageRegionKHR) {
1952         return s->cnx->egl.eglSetDamageRegionKHR(dp->disp.dpy, s->surface,
1953                 rects, n_rects);
1954     }
1955
1956     return EGL_FALSE;
1957 }
1958
1959 EGLBoolean eglGetFrameTimestampsANDROID(EGLDisplay dpy, EGLSurface surface,
1960         EGLint framesAgo, EGLint numTimestamps, const EGLint *timestamps,
1961         EGLnsecsANDROID *values)
1962 {
1963     clearError();
1964
1965     const egl_display_ptr dp = validate_display(dpy);
1966     if (!dp) {
1967         setError(EGL_BAD_DISPLAY, EGL_FALSE);
1968         return EGL_FALSE;
1969     }
1970
1971     SurfaceRef _s(dp.get(), surface);
1972     if (!_s.get()) {
1973         setError(EGL_BAD_SURFACE, EGL_FALSE);
1974         return EGL_FALSE;
1975     }
1976
1977     egl_surface_t const * const s = get_surface(surface);
1978
1979     if (!s->enableTimestamps) {
1980         setError(EGL_BAD_SURFACE, EGL_FALSE);
1981         return EGL_FALSE;
1982     }
1983
1984     nsecs_t* postedTime = nullptr;
1985     nsecs_t* acquireTime = nullptr;
1986     nsecs_t* refreshStartTime = nullptr;
1987     nsecs_t* GLCompositionDoneTime = nullptr;
1988     nsecs_t* displayRetireTime = nullptr;
1989     nsecs_t* releaseTime = nullptr;
1990
1991     for (int i = 0; i < numTimestamps; i++) {
1992         switch (timestamps[i]) {
1993             case EGL_QUEUE_TIME_ANDROID:
1994                 postedTime = &values[i];
1995                 break;
1996             case EGL_RENDERING_COMPLETE_TIME_ANDROID:
1997                 acquireTime = &values[i];
1998                 break;
1999             case EGL_COMPOSITION_START_TIME_ANDROID:
2000                 refreshStartTime = &values[i];
2001                 break;
2002             case EGL_COMPOSITION_FINISHED_TIME_ANDROID:
2003                 GLCompositionDoneTime = &values[i];
2004                 break;
2005             case EGL_DISPLAY_RETIRE_TIME_ANDROID:
2006                 displayRetireTime = &values[i];
2007                 break;
2008             case EGL_READS_DONE_TIME_ANDROID:
2009                 releaseTime = &values[i];
2010                 break;
2011             default:
2012                 setError(EGL_BAD_PARAMETER, EGL_FALSE);
2013                 return EGL_FALSE;
2014         }
2015     }
2016
2017     status_t ret = native_window_get_frame_timestamps(s->win.get(), framesAgo,
2018             postedTime, acquireTime, refreshStartTime, GLCompositionDoneTime,
2019             displayRetireTime, releaseTime);
2020
2021     if (ret != NO_ERROR) {
2022         setError(EGL_BAD_ACCESS, EGL_FALSE);
2023         return EGL_FALSE;
2024     }
2025
2026     return EGL_TRUE;
2027 }
2028
2029 EGLBoolean eglQueryTimestampSupportedANDROID(EGLDisplay dpy, EGLSurface surface,
2030         EGLint timestamp)
2031 {
2032     clearError();
2033
2034     const egl_display_ptr dp = validate_display(dpy);
2035     if (!dp) {
2036         setError(EGL_BAD_DISPLAY, EGL_FALSE);
2037         return EGL_FALSE;
2038     }
2039
2040     SurfaceRef _s(dp.get(), surface);
2041     if (!_s.get()) {
2042         setError(EGL_BAD_SURFACE, EGL_FALSE);
2043         return EGL_FALSE;
2044     }
2045
2046     switch (timestamp) {
2047 #if ENABLE_EGL_ANDROID_GET_FRAME_TIMESTAMPS
2048         case EGL_QUEUE_TIME_ANDROID:
2049         case EGL_RENDERING_COMPLETE_TIME_ANDROID:
2050         case EGL_COMPOSITION_START_TIME_ANDROID:
2051         case EGL_COMPOSITION_FINISHED_TIME_ANDROID:
2052         case EGL_DISPLAY_RETIRE_TIME_ANDROID:
2053         case EGL_READS_DONE_TIME_ANDROID:
2054             return EGL_TRUE;
2055 #endif
2056         default:
2057             return EGL_FALSE;
2058     }
2059 }