OSDN Git Service

am 2daeb124: am edcfe7c5: Merge "libui: Apply GRALLOC_USAGE_ALLOC_MASK during alloc"
[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 <utils/KeyedVector.h>
37 #include <utils/SortedVector.h>
38 #include <utils/String8.h>
39 #include <utils/Trace.h>
40
41 #include "../egl_impl.h"
42 #include "../glestrace.h"
43 #include "../hooks.h"
44
45 #include "egl_display.h"
46 #include "egl_object.h"
47 #include "egl_tls.h"
48 #include "egldefs.h"
49
50 using namespace android;
51
52 // This extension has not been ratified yet, so can't be shipped.
53 // Implementation is incomplete and untested.
54 #define ENABLE_EGL_KHR_GL_COLORSPACE 0
55
56 // ----------------------------------------------------------------------------
57
58 namespace android {
59
60 struct extention_map_t {
61     const char* name;
62     __eglMustCastToProperFunctionPointerType address;
63 };
64
65 /*
66  * This is the list of EGL extensions exposed to applications.
67  *
68  * Some of them (gBuiltinExtensionString) are implemented entirely in this EGL
69  * wrapper and are always available.
70  *
71  * The rest (gExtensionString) depend on support in the EGL driver, and are
72  * only available if the driver supports them. However, some of these must be
73  * supported because they are used by the Android system itself; these are
74  * listd as mandatory below and are required by the CDD. The system *assumes*
75  * the mandatory extensions are present and may not function properly if some
76  * are missing.
77  *
78  * NOTE: Both strings MUST have a single space as the last character.
79  */
80 extern char const * const gBuiltinExtensionString =
81         "EGL_KHR_get_all_proc_addresses "
82         "EGL_ANDROID_presentation_time "
83         "EGL_KHR_swap_buffers_with_damage "
84         ;
85 extern char const * const gExtensionString  =
86         "EGL_KHR_image "                        // mandatory
87         "EGL_KHR_image_base "                   // mandatory
88         "EGL_KHR_image_pixmap "
89         "EGL_KHR_lock_surface "
90 #if (ENABLE_EGL_KHR_GL_COLORSPACE != 0)
91         "EGL_KHR_gl_colorspace "
92 #endif
93         "EGL_KHR_gl_texture_2D_image "
94         "EGL_KHR_gl_texture_cubemap_image "
95         "EGL_KHR_gl_renderbuffer_image "
96         "EGL_KHR_reusable_sync "
97         "EGL_KHR_fence_sync "
98         "EGL_KHR_create_context "
99         "EGL_EXT_create_context_robustness "
100         "EGL_NV_system_time "
101         "EGL_ANDROID_image_native_buffer "      // mandatory
102         "EGL_KHR_wait_sync "                    // strongly recommended
103         "EGL_ANDROID_recordable "               // mandatory
104         "EGL_KHR_partial_update "               // strongly recommended
105         "EGL_EXT_buffer_age "                   // strongly recommended with partial_update
106         "EGL_KHR_create_context_no_error "
107         ;
108
109 // extensions not exposed to applications but used by the ANDROID system
110 //      "EGL_ANDROID_blob_cache "               // strongly recommended
111 //      "EGL_IMG_hibernate_process "            // optional
112 //      "EGL_ANDROID_native_fence_sync "        // strongly recommended
113 //      "EGL_ANDROID_framebuffer_target "       // mandatory for HWC 1.1
114 //      "EGL_ANDROID_image_crop "               // optional
115
116 /*
117  * EGL Extensions entry-points exposed to 3rd party applications
118  * (keep in sync with gExtensionString above)
119  *
120  */
121 static const extention_map_t sExtensionMap[] = {
122     // EGL_KHR_lock_surface
123     { "eglLockSurfaceKHR",
124             (__eglMustCastToProperFunctionPointerType)&eglLockSurfaceKHR },
125     { "eglUnlockSurfaceKHR",
126             (__eglMustCastToProperFunctionPointerType)&eglUnlockSurfaceKHR },
127
128     // EGL_KHR_image, EGL_KHR_image_base
129     { "eglCreateImageKHR",
130             (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR },
131     { "eglDestroyImageKHR",
132             (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR },
133
134     // EGL_KHR_reusable_sync, EGL_KHR_fence_sync
135     { "eglCreateSyncKHR",
136             (__eglMustCastToProperFunctionPointerType)&eglCreateSyncKHR },
137     { "eglDestroySyncKHR",
138             (__eglMustCastToProperFunctionPointerType)&eglDestroySyncKHR },
139     { "eglClientWaitSyncKHR",
140             (__eglMustCastToProperFunctionPointerType)&eglClientWaitSyncKHR },
141     { "eglSignalSyncKHR",
142             (__eglMustCastToProperFunctionPointerType)&eglSignalSyncKHR },
143     { "eglGetSyncAttribKHR",
144             (__eglMustCastToProperFunctionPointerType)&eglGetSyncAttribKHR },
145
146     // EGL_NV_system_time
147     { "eglGetSystemTimeFrequencyNV",
148             (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeFrequencyNV },
149     { "eglGetSystemTimeNV",
150             (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeNV },
151
152     // EGL_KHR_wait_sync
153     { "eglWaitSyncKHR",
154             (__eglMustCastToProperFunctionPointerType)&eglWaitSyncKHR },
155
156     // EGL_ANDROID_presentation_time
157     { "eglPresentationTimeANDROID",
158             (__eglMustCastToProperFunctionPointerType)&eglPresentationTimeANDROID },
159
160     // EGL_KHR_swap_buffers_with_damage
161     { "eglSwapBuffersWithDamageKHR",
162             (__eglMustCastToProperFunctionPointerType)&eglSwapBuffersWithDamageKHR },
163
164     // EGL_KHR_partial_update
165     { "eglSetDamageRegionKHR",
166             (__eglMustCastToProperFunctionPointerType)&eglSetDamageRegionKHR },
167 };
168
169 /*
170  * These extensions entry-points should not be exposed to applications.
171  * They're used internally by the Android EGL layer.
172  */
173 #define FILTER_EXTENSIONS(procname) \
174         (!strcmp((procname), "eglSetBlobCacheFuncsANDROID") ||    \
175          !strcmp((procname), "eglHibernateProcessIMG")      ||    \
176          !strcmp((procname), "eglAwakenProcessIMG")         ||    \
177          !strcmp((procname), "eglDupNativeFenceFDANDROID"))
178
179
180
181 // accesses protected by sExtensionMapMutex
182 static DefaultKeyedVector<String8, __eglMustCastToProperFunctionPointerType> sGLExtentionMap;
183 static int sGLExtentionSlot = 0;
184 static pthread_mutex_t sExtensionMapMutex = PTHREAD_MUTEX_INITIALIZER;
185
186 static void(*findProcAddress(const char* name,
187         const extention_map_t* map, size_t n))() {
188     for (uint32_t i=0 ; i<n ; i++) {
189         if (!strcmp(name, map[i].name)) {
190             return map[i].address;
191         }
192     }
193     return NULL;
194 }
195
196 // ----------------------------------------------------------------------------
197
198 extern void setGLHooksThreadSpecific(gl_hooks_t const *value);
199 extern EGLBoolean egl_init_drivers();
200 extern const __eglMustCastToProperFunctionPointerType gExtensionForwarders[MAX_NUMBER_OF_GL_EXTENSIONS];
201 extern int getEGLDebugLevel();
202 extern void setEGLDebugLevel(int level);
203 extern gl_hooks_t gHooksTrace;
204
205 } // namespace android;
206
207
208 // ----------------------------------------------------------------------------
209
210 static inline void clearError() { egl_tls_t::clearError(); }
211 static inline EGLContext getContext() { return egl_tls_t::getContext(); }
212
213 // ----------------------------------------------------------------------------
214
215 EGLDisplay eglGetDisplay(EGLNativeDisplayType display)
216 {
217     clearError();
218
219     uintptr_t index = reinterpret_cast<uintptr_t>(display);
220     if (index >= NUM_DISPLAYS) {
221         return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
222     }
223
224     if (egl_init_drivers() == EGL_FALSE) {
225         return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
226     }
227
228     EGLDisplay dpy = egl_display_t::getFromNativeDisplay(display);
229     return dpy;
230 }
231
232 // ----------------------------------------------------------------------------
233 // Initialization
234 // ----------------------------------------------------------------------------
235
236 EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
237 {
238     clearError();
239
240     egl_display_ptr dp = get_display(dpy);
241     if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
242
243     EGLBoolean res = dp->initialize(major, minor);
244
245     return res;
246 }
247
248 EGLBoolean eglTerminate(EGLDisplay dpy)
249 {
250     // NOTE: don't unload the drivers b/c some APIs can be called
251     // after eglTerminate() has been called. eglTerminate() only
252     // terminates an EGLDisplay, not a EGL itself.
253
254     clearError();
255
256     egl_display_ptr dp = get_display(dpy);
257     if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
258
259     EGLBoolean res = dp->terminate();
260
261     return res;
262 }
263
264 // ----------------------------------------------------------------------------
265 // configuration
266 // ----------------------------------------------------------------------------
267
268 EGLBoolean eglGetConfigs(   EGLDisplay dpy,
269                             EGLConfig *configs,
270                             EGLint config_size, EGLint *num_config)
271 {
272     clearError();
273
274     const egl_display_ptr dp = validate_display(dpy);
275     if (!dp) return EGL_FALSE;
276
277     if (num_config==0) {
278         return setError(EGL_BAD_PARAMETER, EGL_FALSE);
279     }
280
281     EGLBoolean res = EGL_FALSE;
282     *num_config = 0;
283
284     egl_connection_t* const cnx = &gEGLImpl;
285     if (cnx->dso) {
286         res = cnx->egl.eglGetConfigs(
287                 dp->disp.dpy, configs, config_size, num_config);
288     }
289
290     return res;
291 }
292
293 EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list,
294                             EGLConfig *configs, EGLint config_size,
295                             EGLint *num_config)
296 {
297     clearError();
298
299     const egl_display_ptr dp = validate_display(dpy);
300     if (!dp) return EGL_FALSE;
301
302     if (num_config==0) {
303         return setError(EGL_BAD_PARAMETER, EGL_FALSE);
304     }
305
306     EGLBoolean res = EGL_FALSE;
307     *num_config = 0;
308
309     egl_connection_t* const cnx = &gEGLImpl;
310     if (cnx->dso) {
311         if (attrib_list) {
312             char value[PROPERTY_VALUE_MAX];
313             property_get("debug.egl.force_msaa", value, "false");
314
315             if (!strcmp(value, "true")) {
316                 size_t attribCount = 0;
317                 EGLint attrib = attrib_list[0];
318
319                 // Only enable MSAA if the context is OpenGL ES 2.0 and
320                 // if no caveat is requested
321                 const EGLint *attribRendererable = NULL;
322                 const EGLint *attribCaveat = NULL;
323
324                 // Count the number of attributes and look for
325                 // EGL_RENDERABLE_TYPE and EGL_CONFIG_CAVEAT
326                 while (attrib != EGL_NONE) {
327                     attrib = attrib_list[attribCount];
328                     switch (attrib) {
329                         case EGL_RENDERABLE_TYPE:
330                             attribRendererable = &attrib_list[attribCount];
331                             break;
332                         case EGL_CONFIG_CAVEAT:
333                             attribCaveat = &attrib_list[attribCount];
334                             break;
335                     }
336                     attribCount++;
337                 }
338
339                 if (attribRendererable && attribRendererable[1] == EGL_OPENGL_ES2_BIT &&
340                         (!attribCaveat || attribCaveat[1] != EGL_NONE)) {
341
342                     // Insert 2 extra attributes to force-enable MSAA 4x
343                     EGLint aaAttribs[attribCount + 4];
344                     aaAttribs[0] = EGL_SAMPLE_BUFFERS;
345                     aaAttribs[1] = 1;
346                     aaAttribs[2] = EGL_SAMPLES;
347                     aaAttribs[3] = 4;
348
349                     memcpy(&aaAttribs[4], attrib_list, attribCount * sizeof(EGLint));
350
351                     EGLint numConfigAA;
352                     EGLBoolean resAA = cnx->egl.eglChooseConfig(
353                             dp->disp.dpy, aaAttribs, configs, config_size, &numConfigAA);
354
355                     if (resAA == EGL_TRUE && numConfigAA > 0) {
356                         ALOGD("Enabling MSAA 4x");
357                         *num_config = numConfigAA;
358                         return resAA;
359                     }
360                 }
361             }
362         }
363
364         res = cnx->egl.eglChooseConfig(
365                 dp->disp.dpy, attrib_list, configs, config_size, num_config);
366     }
367     return res;
368 }
369
370 EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
371         EGLint attribute, EGLint *value)
372 {
373     clearError();
374
375     egl_connection_t* cnx = NULL;
376     const egl_display_ptr dp = validate_display_connection(dpy, cnx);
377     if (!dp) return EGL_FALSE;
378
379     return cnx->egl.eglGetConfigAttrib(
380             dp->disp.dpy, config, attribute, value);
381 }
382
383 // ----------------------------------------------------------------------------
384 // surfaces
385 // ----------------------------------------------------------------------------
386
387 // The EGL_KHR_gl_colorspace spec hasn't been ratified yet, so these haven't
388 // been added to the Khronos egl.h.
389 #define EGL_GL_COLORSPACE_KHR           EGL_VG_COLORSPACE
390 #define EGL_GL_COLORSPACE_SRGB_KHR      EGL_VG_COLORSPACE_sRGB
391 #define EGL_GL_COLORSPACE_LINEAR_KHR    EGL_VG_COLORSPACE_LINEAR
392
393 // Turn linear formats into corresponding sRGB formats when colorspace is
394 // EGL_GL_COLORSPACE_SRGB_KHR, or turn sRGB formats into corresponding linear
395 // formats when colorspace is EGL_GL_COLORSPACE_LINEAR_KHR. In any cases where
396 // the modification isn't possible, the original dataSpace is returned.
397 static android_dataspace modifyBufferDataspace( android_dataspace dataSpace,
398                                                 EGLint colorspace) {
399     if (colorspace == EGL_GL_COLORSPACE_LINEAR_KHR) {
400         return HAL_DATASPACE_SRGB_LINEAR;
401     } else if (colorspace == EGL_GL_COLORSPACE_SRGB_KHR) {
402         return HAL_DATASPACE_SRGB;
403     }
404     return dataSpace;
405 }
406
407 EGLSurface eglCreateWindowSurface(  EGLDisplay dpy, EGLConfig config,
408                                     NativeWindowType window,
409                                     const EGLint *attrib_list)
410 {
411     clearError();
412
413     egl_connection_t* cnx = NULL;
414     egl_display_ptr dp = validate_display_connection(dpy, cnx);
415     if (dp) {
416         EGLDisplay iDpy = dp->disp.dpy;
417
418         int result = native_window_api_connect(window, NATIVE_WINDOW_API_EGL);
419         if (result != OK) {
420             ALOGE("eglCreateWindowSurface: native_window_api_connect (win=%p) "
421                     "failed (%#x) (already connected to another API?)",
422                     window, result);
423             return setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
424         }
425
426         // Set the native window's buffers format to match what this config requests.
427         // Whether to use sRGB gamma is not part of the EGLconfig, but is part
428         // of our native format. So if sRGB gamma is requested, we have to
429         // modify the EGLconfig's format before setting the native window's
430         // format.
431
432         // by default, just pick RGBA_8888
433         EGLint format = HAL_PIXEL_FORMAT_RGBA_8888;
434         android_dataspace dataSpace = HAL_DATASPACE_UNKNOWN;
435
436         EGLint a = 0;
437         cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_ALPHA_SIZE, &a);
438         if (a > 0) {
439             // alpha-channel requested, there's really only one suitable format
440             format = HAL_PIXEL_FORMAT_RGBA_8888;
441         } else {
442             EGLint r, g, b;
443             r = g = b = 0;
444             cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_RED_SIZE,   &r);
445             cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_GREEN_SIZE, &g);
446             cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_BLUE_SIZE,  &b);
447             EGLint colorDepth = r + g + b;
448             if (colorDepth <= 16) {
449                 format = HAL_PIXEL_FORMAT_RGB_565;
450             } else {
451                 format = HAL_PIXEL_FORMAT_RGBX_8888;
452             }
453         }
454
455         // now select a corresponding sRGB format if needed
456         if (attrib_list && dp->haveExtension("EGL_KHR_gl_colorspace")) {
457             for (const EGLint* attr = attrib_list; *attr != EGL_NONE; attr += 2) {
458                 if (*attr == EGL_GL_COLORSPACE_KHR) {
459                     if (ENABLE_EGL_KHR_GL_COLORSPACE) {
460                         dataSpace = modifyBufferDataspace(dataSpace, *(attr+1));
461                     } else {
462                         // Normally we'd pass through unhandled attributes to
463                         // the driver. But in case the driver implements this
464                         // extension but we're disabling it, we want to prevent
465                         // it getting through -- support will be broken without
466                         // our help.
467                         ALOGE("sRGB window surfaces not supported");
468                         return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
469                     }
470                 }
471             }
472         }
473
474         if (format != 0) {
475             int err = native_window_set_buffers_format(window, format);
476             if (err != 0) {
477                 ALOGE("error setting native window pixel format: %s (%d)",
478                         strerror(-err), err);
479                 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
480                 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
481             }
482         }
483
484         if (dataSpace != 0) {
485             int err = native_window_set_buffers_data_space(window, dataSpace);
486             if (err != 0) {
487                 ALOGE("error setting native window pixel dataSpace: %s (%d)",
488                         strerror(-err), err);
489                 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
490                 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
491             }
492         }
493
494         // the EGL spec requires that a new EGLSurface default to swap interval
495         // 1, so explicitly set that on the window here.
496         ANativeWindow* anw = reinterpret_cast<ANativeWindow*>(window);
497         anw->setSwapInterval(anw, 1);
498
499         EGLSurface surface = cnx->egl.eglCreateWindowSurface(
500                 iDpy, config, window, attrib_list);
501         if (surface != EGL_NO_SURFACE) {
502             egl_surface_t* s = new egl_surface_t(dp.get(), config, window,
503                     surface, cnx);
504             return s;
505         }
506
507         // EGLSurface creation failed
508         native_window_set_buffers_format(window, 0);
509         native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
510     }
511     return EGL_NO_SURFACE;
512 }
513
514 EGLSurface eglCreatePixmapSurface(  EGLDisplay dpy, EGLConfig config,
515                                     NativePixmapType pixmap,
516                                     const EGLint *attrib_list)
517 {
518     clearError();
519
520     egl_connection_t* cnx = NULL;
521     egl_display_ptr dp = validate_display_connection(dpy, cnx);
522     if (dp) {
523         EGLSurface surface = cnx->egl.eglCreatePixmapSurface(
524                 dp->disp.dpy, config, pixmap, attrib_list);
525         if (surface != EGL_NO_SURFACE) {
526             egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL,
527                     surface, cnx);
528             return s;
529         }
530     }
531     return EGL_NO_SURFACE;
532 }
533
534 EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config,
535                                     const EGLint *attrib_list)
536 {
537     clearError();
538
539     egl_connection_t* cnx = NULL;
540     egl_display_ptr dp = validate_display_connection(dpy, cnx);
541     if (dp) {
542         EGLSurface surface = cnx->egl.eglCreatePbufferSurface(
543                 dp->disp.dpy, config, attrib_list);
544         if (surface != EGL_NO_SURFACE) {
545             egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL,
546                     surface, cnx);
547             return s;
548         }
549     }
550     return EGL_NO_SURFACE;
551 }
552
553 EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
554 {
555     clearError();
556
557     const egl_display_ptr dp = validate_display(dpy);
558     if (!dp) return EGL_FALSE;
559
560     SurfaceRef _s(dp.get(), surface);
561     if (!_s.get())
562         return setError(EGL_BAD_SURFACE, EGL_FALSE);
563
564     egl_surface_t * const s = get_surface(surface);
565     EGLBoolean result = s->cnx->egl.eglDestroySurface(dp->disp.dpy, s->surface);
566     if (result == EGL_TRUE) {
567         _s.terminate();
568     }
569     return result;
570 }
571
572 EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface,
573                             EGLint attribute, EGLint *value)
574 {
575     clearError();
576
577     const egl_display_ptr dp = validate_display(dpy);
578     if (!dp) return EGL_FALSE;
579
580     SurfaceRef _s(dp.get(), surface);
581     if (!_s.get())
582         return setError(EGL_BAD_SURFACE, EGL_FALSE);
583
584     egl_surface_t const * const s = get_surface(surface);
585     return s->cnx->egl.eglQuerySurface(
586             dp->disp.dpy, s->surface, attribute, value);
587 }
588
589 void EGLAPI eglBeginFrame(EGLDisplay dpy, EGLSurface surface) {
590     ATRACE_CALL();
591     clearError();
592
593     const egl_display_ptr dp = validate_display(dpy);
594     if (!dp) {
595         return;
596     }
597
598     SurfaceRef _s(dp.get(), surface);
599     if (!_s.get()) {
600         setError(EGL_BAD_SURFACE, EGL_FALSE);
601         return;
602     }
603 }
604
605 // ----------------------------------------------------------------------------
606 // Contexts
607 // ----------------------------------------------------------------------------
608
609 EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config,
610                             EGLContext share_list, const EGLint *attrib_list)
611 {
612     clearError();
613
614     egl_connection_t* cnx = NULL;
615     const egl_display_ptr dp = validate_display_connection(dpy, cnx);
616     if (dp) {
617         if (share_list != EGL_NO_CONTEXT) {
618             if (!ContextRef(dp.get(), share_list).get()) {
619                 return setError(EGL_BAD_CONTEXT, EGL_NO_CONTEXT);
620             }
621             egl_context_t* const c = get_context(share_list);
622             share_list = c->context;
623         }
624         EGLContext context = cnx->egl.eglCreateContext(
625                 dp->disp.dpy, config, share_list, attrib_list);
626         if (context != EGL_NO_CONTEXT) {
627             // figure out if it's a GLESv1 or GLESv2
628             int version = 0;
629             if (attrib_list) {
630                 while (*attrib_list != EGL_NONE) {
631                     GLint attr = *attrib_list++;
632                     GLint value = *attrib_list++;
633                     if (attr == EGL_CONTEXT_CLIENT_VERSION) {
634                         if (value == 1) {
635                             version = egl_connection_t::GLESv1_INDEX;
636                         } else if (value == 2 || value == 3) {
637                             version = egl_connection_t::GLESv2_INDEX;
638                         }
639                     }
640                 };
641             }
642             egl_context_t* c = new egl_context_t(dpy, context, config, cnx,
643                     version);
644 #if EGL_TRACE
645             if (getEGLDebugLevel() > 0)
646                 GLTrace_eglCreateContext(version, c);
647 #endif
648             return c;
649         }
650     }
651     return EGL_NO_CONTEXT;
652 }
653
654 EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
655 {
656     clearError();
657
658     const egl_display_ptr dp = validate_display(dpy);
659     if (!dp)
660         return EGL_FALSE;
661
662     ContextRef _c(dp.get(), ctx);
663     if (!_c.get())
664         return setError(EGL_BAD_CONTEXT, EGL_FALSE);
665
666     egl_context_t * const c = get_context(ctx);
667     EGLBoolean result = c->cnx->egl.eglDestroyContext(dp->disp.dpy, c->context);
668     if (result == EGL_TRUE) {
669         _c.terminate();
670     }
671     return result;
672 }
673
674 EGLBoolean eglMakeCurrent(  EGLDisplay dpy, EGLSurface draw,
675                             EGLSurface read, EGLContext ctx)
676 {
677     clearError();
678
679     egl_display_ptr dp = validate_display(dpy);
680     if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
681
682     // If ctx is not EGL_NO_CONTEXT, read is not EGL_NO_SURFACE, or draw is not
683     // EGL_NO_SURFACE, then an EGL_NOT_INITIALIZED error is generated if dpy is
684     // a valid but uninitialized display.
685     if ( (ctx != EGL_NO_CONTEXT) || (read != EGL_NO_SURFACE) ||
686          (draw != EGL_NO_SURFACE) ) {
687         if (!dp->isReady()) return setError(EGL_NOT_INITIALIZED, EGL_FALSE);
688     }
689
690     // get a reference to the object passed in
691     ContextRef _c(dp.get(), ctx);
692     SurfaceRef _d(dp.get(), draw);
693     SurfaceRef _r(dp.get(), read);
694
695     // validate the context (if not EGL_NO_CONTEXT)
696     if ((ctx != EGL_NO_CONTEXT) && !_c.get()) {
697         // EGL_NO_CONTEXT is valid
698         return setError(EGL_BAD_CONTEXT, EGL_FALSE);
699     }
700
701     // these are the underlying implementation's object
702     EGLContext impl_ctx  = EGL_NO_CONTEXT;
703     EGLSurface impl_draw = EGL_NO_SURFACE;
704     EGLSurface impl_read = EGL_NO_SURFACE;
705
706     // these are our objects structs passed in
707     egl_context_t       * c = NULL;
708     egl_surface_t const * d = NULL;
709     egl_surface_t const * r = NULL;
710
711     // these are the current objects structs
712     egl_context_t * cur_c = get_context(getContext());
713
714     if (ctx != EGL_NO_CONTEXT) {
715         c = get_context(ctx);
716         impl_ctx = c->context;
717     } else {
718         // no context given, use the implementation of the current context
719         if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) {
720             // calling eglMakeCurrent( ..., !=0, !=0, EGL_NO_CONTEXT);
721             return setError(EGL_BAD_MATCH, EGL_FALSE);
722         }
723         if (cur_c == NULL) {
724             // no current context
725             // not an error, there is just no current context.
726             return EGL_TRUE;
727         }
728     }
729
730     // retrieve the underlying implementation's draw EGLSurface
731     if (draw != EGL_NO_SURFACE) {
732         if (!_d.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
733         d = get_surface(draw);
734         impl_draw = d->surface;
735     }
736
737     // retrieve the underlying implementation's read EGLSurface
738     if (read != EGL_NO_SURFACE) {
739         if (!_r.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
740         r = get_surface(read);
741         impl_read = r->surface;
742     }
743
744
745     EGLBoolean result = dp->makeCurrent(c, cur_c,
746             draw, read, ctx,
747             impl_draw, impl_read, impl_ctx);
748
749     if (result == EGL_TRUE) {
750         if (c) {
751             setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
752             egl_tls_t::setContext(ctx);
753 #if EGL_TRACE
754             if (getEGLDebugLevel() > 0)
755                 GLTrace_eglMakeCurrent(c->version, c->cnx->hooks[c->version], ctx);
756 #endif
757             _c.acquire();
758             _r.acquire();
759             _d.acquire();
760         } else {
761             setGLHooksThreadSpecific(&gHooksNoContext);
762             egl_tls_t::setContext(EGL_NO_CONTEXT);
763         }
764     } else {
765         // this will ALOGE the error
766         egl_connection_t* const cnx = &gEGLImpl;
767         result = setError(cnx->egl.eglGetError(), EGL_FALSE);
768     }
769     return result;
770 }
771
772
773 EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx,
774                             EGLint attribute, EGLint *value)
775 {
776     clearError();
777
778     const egl_display_ptr dp = validate_display(dpy);
779     if (!dp) return EGL_FALSE;
780
781     ContextRef _c(dp.get(), ctx);
782     if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
783
784     egl_context_t * const c = get_context(ctx);
785     return c->cnx->egl.eglQueryContext(
786             dp->disp.dpy, c->context, attribute, value);
787
788 }
789
790 EGLContext eglGetCurrentContext(void)
791 {
792     // could be called before eglInitialize(), but we wouldn't have a context
793     // then, and this function would correctly return EGL_NO_CONTEXT.
794
795     clearError();
796
797     EGLContext ctx = getContext();
798     return ctx;
799 }
800
801 EGLSurface eglGetCurrentSurface(EGLint readdraw)
802 {
803     // could be called before eglInitialize(), but we wouldn't have a context
804     // then, and this function would correctly return EGL_NO_SURFACE.
805
806     clearError();
807
808     EGLContext ctx = getContext();
809     if (ctx) {
810         egl_context_t const * const c = get_context(ctx);
811         if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
812         switch (readdraw) {
813             case EGL_READ: return c->read;
814             case EGL_DRAW: return c->draw;
815             default: return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
816         }
817     }
818     return EGL_NO_SURFACE;
819 }
820
821 EGLDisplay eglGetCurrentDisplay(void)
822 {
823     // could be called before eglInitialize(), but we wouldn't have a context
824     // then, and this function would correctly return EGL_NO_DISPLAY.
825
826     clearError();
827
828     EGLContext ctx = getContext();
829     if (ctx) {
830         egl_context_t const * const c = get_context(ctx);
831         if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
832         return c->dpy;
833     }
834     return EGL_NO_DISPLAY;
835 }
836
837 EGLBoolean eglWaitGL(void)
838 {
839     clearError();
840
841     egl_connection_t* const cnx = &gEGLImpl;
842     if (!cnx->dso)
843         return setError(EGL_BAD_CONTEXT, EGL_FALSE);
844
845     return cnx->egl.eglWaitGL();
846 }
847
848 EGLBoolean eglWaitNative(EGLint engine)
849 {
850     clearError();
851
852     egl_connection_t* const cnx = &gEGLImpl;
853     if (!cnx->dso)
854         return setError(EGL_BAD_CONTEXT, EGL_FALSE);
855
856     return cnx->egl.eglWaitNative(engine);
857 }
858
859 EGLint eglGetError(void)
860 {
861     EGLint err = EGL_SUCCESS;
862     egl_connection_t* const cnx = &gEGLImpl;
863     if (cnx->dso) {
864         err = cnx->egl.eglGetError();
865     }
866     if (err == EGL_SUCCESS) {
867         err = egl_tls_t::getError();
868     }
869     return err;
870 }
871
872 static __eglMustCastToProperFunctionPointerType findBuiltinWrapper(
873         const char* procname) {
874     const egl_connection_t* cnx = &gEGLImpl;
875     void* proc = NULL;
876
877     proc = dlsym(cnx->libEgl, procname);
878     if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
879
880     proc = dlsym(cnx->libGles2, procname);
881     if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
882
883     proc = dlsym(cnx->libGles1, procname);
884     if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
885
886     return NULL;
887 }
888
889 __eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
890 {
891     // eglGetProcAddress() could be the very first function called
892     // in which case we must make sure we've initialized ourselves, this
893     // happens the first time egl_get_display() is called.
894
895     clearError();
896
897     if (egl_init_drivers() == EGL_FALSE) {
898         setError(EGL_BAD_PARAMETER, NULL);
899         return  NULL;
900     }
901
902     if (FILTER_EXTENSIONS(procname)) {
903         return NULL;
904     }
905
906     __eglMustCastToProperFunctionPointerType addr;
907     addr = findProcAddress(procname, sExtensionMap, NELEM(sExtensionMap));
908     if (addr) return addr;
909
910     addr = findBuiltinWrapper(procname);
911     if (addr) return addr;
912
913     // this protects accesses to sGLExtentionMap and sGLExtentionSlot
914     pthread_mutex_lock(&sExtensionMapMutex);
915
916         /*
917          * Since eglGetProcAddress() is not associated to anything, it needs
918          * to return a function pointer that "works" regardless of what
919          * the current context is.
920          *
921          * For this reason, we return a "forwarder", a small stub that takes
922          * care of calling the function associated with the context
923          * currently bound.
924          *
925          * We first look for extensions we've already resolved, if we're seeing
926          * this extension for the first time, we go through all our
927          * implementations and call eglGetProcAddress() and record the
928          * result in the appropriate implementation hooks and return the
929          * address of the forwarder corresponding to that hook set.
930          *
931          */
932
933         const String8 name(procname);
934         addr = sGLExtentionMap.valueFor(name);
935         const int slot = sGLExtentionSlot;
936
937         ALOGE_IF(slot >= MAX_NUMBER_OF_GL_EXTENSIONS,
938                 "no more slots for eglGetProcAddress(\"%s\")",
939                 procname);
940
941 #if EGL_TRACE
942         gl_hooks_t *debugHooks = GLTrace_getGLHooks();
943 #endif
944
945         if (!addr && (slot < MAX_NUMBER_OF_GL_EXTENSIONS)) {
946             bool found = false;
947
948             egl_connection_t* const cnx = &gEGLImpl;
949             if (cnx->dso && cnx->egl.eglGetProcAddress) {
950                 // Extensions are independent of the bound context
951                 addr =
952                 cnx->hooks[egl_connection_t::GLESv1_INDEX]->ext.extensions[slot] =
953                 cnx->hooks[egl_connection_t::GLESv2_INDEX]->ext.extensions[slot] =
954 #if EGL_TRACE
955                 debugHooks->ext.extensions[slot] =
956                 gHooksTrace.ext.extensions[slot] =
957 #endif
958                         cnx->egl.eglGetProcAddress(procname);
959                 if (addr) found = true;
960             }
961
962             if (found) {
963                 addr = gExtensionForwarders[slot];
964                 sGLExtentionMap.add(name, addr);
965                 sGLExtentionSlot++;
966             }
967         }
968
969     pthread_mutex_unlock(&sExtensionMapMutex);
970     return addr;
971 }
972
973 class FrameCompletionThread : public Thread {
974 public:
975
976     static void queueSync(EGLSyncKHR sync) {
977         static sp<FrameCompletionThread> thread(new FrameCompletionThread);
978         static bool running = false;
979         if (!running) {
980             thread->run("GPUFrameCompletion");
981             running = true;
982         }
983         {
984             Mutex::Autolock lock(thread->mMutex);
985             ScopedTrace st(ATRACE_TAG, String8::format("kicked off frame %d",
986                     thread->mFramesQueued).string());
987             thread->mQueue.push_back(sync);
988             thread->mCondition.signal();
989             thread->mFramesQueued++;
990             ATRACE_INT("GPU Frames Outstanding", thread->mQueue.size());
991         }
992     }
993
994 private:
995     FrameCompletionThread() : mFramesQueued(0), mFramesCompleted(0) {}
996
997     virtual bool threadLoop() {
998         EGLSyncKHR sync;
999         uint32_t frameNum;
1000         {
1001             Mutex::Autolock lock(mMutex);
1002             while (mQueue.isEmpty()) {
1003                 mCondition.wait(mMutex);
1004             }
1005             sync = mQueue[0];
1006             frameNum = mFramesCompleted;
1007         }
1008         EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
1009         {
1010             ScopedTrace st(ATRACE_TAG, String8::format("waiting for frame %d",
1011                     frameNum).string());
1012             EGLint result = eglClientWaitSyncKHR(dpy, sync, 0, EGL_FOREVER_KHR);
1013             if (result == EGL_FALSE) {
1014                 ALOGE("FrameCompletion: error waiting for fence: %#x", eglGetError());
1015             } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
1016                 ALOGE("FrameCompletion: timeout waiting for fence");
1017             }
1018             eglDestroySyncKHR(dpy, sync);
1019         }
1020         {
1021             Mutex::Autolock lock(mMutex);
1022             mQueue.removeAt(0);
1023             mFramesCompleted++;
1024             ATRACE_INT("GPU Frames Outstanding", mQueue.size());
1025         }
1026         return true;
1027     }
1028
1029     uint32_t mFramesQueued;
1030     uint32_t mFramesCompleted;
1031     Vector<EGLSyncKHR> mQueue;
1032     Condition mCondition;
1033     Mutex mMutex;
1034 };
1035
1036 EGLBoolean eglSwapBuffersWithDamageKHR(EGLDisplay dpy, EGLSurface draw,
1037         EGLint *rects, EGLint n_rects)
1038 {
1039     ATRACE_CALL();
1040     clearError();
1041
1042     const egl_display_ptr dp = validate_display(dpy);
1043     if (!dp) return EGL_FALSE;
1044
1045     SurfaceRef _s(dp.get(), draw);
1046     if (!_s.get())
1047         return setError(EGL_BAD_SURFACE, EGL_FALSE);
1048
1049 #if EGL_TRACE
1050     gl_hooks_t const *trace_hooks = getGLTraceThreadSpecific();
1051     if (getEGLDebugLevel() > 0) {
1052         if (trace_hooks == NULL) {
1053             if (GLTrace_start() < 0) {
1054                 ALOGE("Disabling Tracer for OpenGL ES");
1055                 setEGLDebugLevel(0);
1056             } else {
1057                 // switch over to the trace version of hooks
1058                 EGLContext ctx = egl_tls_t::getContext();
1059                 egl_context_t * const c = get_context(ctx);
1060                 if (c) {
1061                     setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
1062                     GLTrace_eglMakeCurrent(c->version, c->cnx->hooks[c->version], ctx);
1063                 }
1064             }
1065         }
1066
1067         GLTrace_eglSwapBuffers(dpy, draw);
1068     } else if (trace_hooks != NULL) {
1069         // tracing is now disabled, so switch back to the non trace version
1070         EGLContext ctx = egl_tls_t::getContext();
1071         egl_context_t * const c = get_context(ctx);
1072         if (c) setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
1073         GLTrace_stop();
1074     }
1075 #endif
1076
1077     egl_surface_t const * const s = get_surface(draw);
1078
1079     if (CC_UNLIKELY(dp->traceGpuCompletion)) {
1080         EGLSyncKHR sync = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, NULL);
1081         if (sync != EGL_NO_SYNC_KHR) {
1082             FrameCompletionThread::queueSync(sync);
1083         }
1084     }
1085
1086     if (CC_UNLIKELY(dp->finishOnSwap)) {
1087         uint32_t pixel;
1088         egl_context_t * const c = get_context( egl_tls_t::getContext() );
1089         if (c) {
1090             // glReadPixels() ensures that the frame is complete
1091             s->cnx->hooks[c->version]->gl.glReadPixels(0,0,1,1,
1092                     GL_RGBA,GL_UNSIGNED_BYTE,&pixel);
1093         }
1094     }
1095
1096     if (n_rects == 0) {
1097         return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface);
1098     }
1099
1100     Vector<android_native_rect_t> androidRects;
1101     for (int r = 0; r < n_rects; ++r) {
1102         int offset = r * 4;
1103         int x = rects[offset];
1104         int y = rects[offset + 1];
1105         int width = rects[offset + 2];
1106         int height = rects[offset + 3];
1107         android_native_rect_t androidRect;
1108         androidRect.left = x;
1109         androidRect.top = y + height;
1110         androidRect.right = x + width;
1111         androidRect.bottom = y;
1112         androidRects.push_back(androidRect);
1113     }
1114     native_window_set_surface_damage(s->win.get(), androidRects.array(),
1115             androidRects.size());
1116
1117     if (s->cnx->egl.eglSwapBuffersWithDamageKHR) {
1118         return s->cnx->egl.eglSwapBuffersWithDamageKHR(dp->disp.dpy, s->surface,
1119                 rects, n_rects);
1120     } else {
1121         return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface);
1122     }
1123 }
1124
1125 EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
1126 {
1127     return eglSwapBuffersWithDamageKHR(dpy, surface, NULL, 0);
1128 }
1129
1130 EGLBoolean eglCopyBuffers(  EGLDisplay dpy, EGLSurface surface,
1131                             NativePixmapType target)
1132 {
1133     clearError();
1134
1135     const egl_display_ptr dp = validate_display(dpy);
1136     if (!dp) return EGL_FALSE;
1137
1138     SurfaceRef _s(dp.get(), surface);
1139     if (!_s.get())
1140         return setError(EGL_BAD_SURFACE, EGL_FALSE);
1141
1142     egl_surface_t const * const s = get_surface(surface);
1143     return s->cnx->egl.eglCopyBuffers(dp->disp.dpy, s->surface, target);
1144 }
1145
1146 const char* eglQueryString(EGLDisplay dpy, EGLint name)
1147 {
1148     clearError();
1149
1150     const egl_display_ptr dp = validate_display(dpy);
1151     if (!dp) return (const char *) NULL;
1152
1153     switch (name) {
1154         case EGL_VENDOR:
1155             return dp->getVendorString();
1156         case EGL_VERSION:
1157             return dp->getVersionString();
1158         case EGL_EXTENSIONS:
1159             return dp->getExtensionString();
1160         case EGL_CLIENT_APIS:
1161             return dp->getClientApiString();
1162     }
1163     return setError(EGL_BAD_PARAMETER, (const char *)0);
1164 }
1165
1166 EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name)
1167 {
1168     clearError();
1169
1170     const egl_display_ptr dp = validate_display(dpy);
1171     if (!dp) return (const char *) NULL;
1172
1173     switch (name) {
1174         case EGL_VENDOR:
1175             return dp->disp.queryString.vendor;
1176         case EGL_VERSION:
1177             return dp->disp.queryString.version;
1178         case EGL_EXTENSIONS:
1179             return dp->disp.queryString.extensions;
1180         case EGL_CLIENT_APIS:
1181             return dp->disp.queryString.clientApi;
1182     }
1183     return setError(EGL_BAD_PARAMETER, (const char *)0);
1184 }
1185
1186 // ----------------------------------------------------------------------------
1187 // EGL 1.1
1188 // ----------------------------------------------------------------------------
1189
1190 EGLBoolean eglSurfaceAttrib(
1191         EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
1192 {
1193     clearError();
1194
1195     const egl_display_ptr dp = validate_display(dpy);
1196     if (!dp) return EGL_FALSE;
1197
1198     SurfaceRef _s(dp.get(), surface);
1199     if (!_s.get())
1200         return setError(EGL_BAD_SURFACE, EGL_FALSE);
1201
1202     egl_surface_t const * const s = get_surface(surface);
1203     if (s->cnx->egl.eglSurfaceAttrib) {
1204         return s->cnx->egl.eglSurfaceAttrib(
1205                 dp->disp.dpy, s->surface, attribute, value);
1206     }
1207     return setError(EGL_BAD_SURFACE, EGL_FALSE);
1208 }
1209
1210 EGLBoolean eglBindTexImage(
1211         EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1212 {
1213     clearError();
1214
1215     const egl_display_ptr dp = validate_display(dpy);
1216     if (!dp) return EGL_FALSE;
1217
1218     SurfaceRef _s(dp.get(), surface);
1219     if (!_s.get())
1220         return setError(EGL_BAD_SURFACE, EGL_FALSE);
1221
1222     egl_surface_t const * const s = get_surface(surface);
1223     if (s->cnx->egl.eglBindTexImage) {
1224         return s->cnx->egl.eglBindTexImage(
1225                 dp->disp.dpy, s->surface, buffer);
1226     }
1227     return setError(EGL_BAD_SURFACE, EGL_FALSE);
1228 }
1229
1230 EGLBoolean eglReleaseTexImage(
1231         EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1232 {
1233     clearError();
1234
1235     const egl_display_ptr dp = validate_display(dpy);
1236     if (!dp) return EGL_FALSE;
1237
1238     SurfaceRef _s(dp.get(), surface);
1239     if (!_s.get())
1240         return setError(EGL_BAD_SURFACE, EGL_FALSE);
1241
1242     egl_surface_t const * const s = get_surface(surface);
1243     if (s->cnx->egl.eglReleaseTexImage) {
1244         return s->cnx->egl.eglReleaseTexImage(
1245                 dp->disp.dpy, s->surface, buffer);
1246     }
1247     return setError(EGL_BAD_SURFACE, EGL_FALSE);
1248 }
1249
1250 EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
1251 {
1252     clearError();
1253
1254     const egl_display_ptr dp = validate_display(dpy);
1255     if (!dp) return EGL_FALSE;
1256
1257     EGLBoolean res = EGL_TRUE;
1258     egl_connection_t* const cnx = &gEGLImpl;
1259     if (cnx->dso && cnx->egl.eglSwapInterval) {
1260         res = cnx->egl.eglSwapInterval(dp->disp.dpy, interval);
1261     }
1262
1263     return res;
1264 }
1265
1266
1267 // ----------------------------------------------------------------------------
1268 // EGL 1.2
1269 // ----------------------------------------------------------------------------
1270
1271 EGLBoolean eglWaitClient(void)
1272 {
1273     clearError();
1274
1275     egl_connection_t* const cnx = &gEGLImpl;
1276     if (!cnx->dso)
1277         return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1278
1279     EGLBoolean res;
1280     if (cnx->egl.eglWaitClient) {
1281         res = cnx->egl.eglWaitClient();
1282     } else {
1283         res = cnx->egl.eglWaitGL();
1284     }
1285     return res;
1286 }
1287
1288 EGLBoolean eglBindAPI(EGLenum api)
1289 {
1290     clearError();
1291
1292     if (egl_init_drivers() == EGL_FALSE) {
1293         return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1294     }
1295
1296     // bind this API on all EGLs
1297     EGLBoolean res = EGL_TRUE;
1298     egl_connection_t* const cnx = &gEGLImpl;
1299     if (cnx->dso && cnx->egl.eglBindAPI) {
1300         res = cnx->egl.eglBindAPI(api);
1301     }
1302     return res;
1303 }
1304
1305 EGLenum eglQueryAPI(void)
1306 {
1307     clearError();
1308
1309     if (egl_init_drivers() == EGL_FALSE) {
1310         return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1311     }
1312
1313     egl_connection_t* const cnx = &gEGLImpl;
1314     if (cnx->dso && cnx->egl.eglQueryAPI) {
1315         return cnx->egl.eglQueryAPI();
1316     }
1317
1318     // or, it can only be OpenGL ES
1319     return EGL_OPENGL_ES_API;
1320 }
1321
1322 EGLBoolean eglReleaseThread(void)
1323 {
1324     clearError();
1325
1326 #if EGL_TRACE
1327     if (getEGLDebugLevel() > 0)
1328         GLTrace_eglReleaseThread();
1329 #endif
1330
1331     // If there is context bound to the thread, release it
1332     egl_display_t::loseCurrent(get_context(getContext()));
1333
1334     egl_connection_t* const cnx = &gEGLImpl;
1335     if (cnx->dso && cnx->egl.eglReleaseThread) {
1336         cnx->egl.eglReleaseThread();
1337     }
1338     egl_tls_t::clearTLS();
1339     return EGL_TRUE;
1340 }
1341
1342 EGLSurface eglCreatePbufferFromClientBuffer(
1343           EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
1344           EGLConfig config, const EGLint *attrib_list)
1345 {
1346     clearError();
1347
1348     egl_connection_t* cnx = NULL;
1349     const egl_display_ptr dp = validate_display_connection(dpy, cnx);
1350     if (!dp) return EGL_FALSE;
1351     if (cnx->egl.eglCreatePbufferFromClientBuffer) {
1352         return cnx->egl.eglCreatePbufferFromClientBuffer(
1353                 dp->disp.dpy, buftype, buffer, config, attrib_list);
1354     }
1355     return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE);
1356 }
1357
1358 // ----------------------------------------------------------------------------
1359 // EGL_EGLEXT_VERSION 3
1360 // ----------------------------------------------------------------------------
1361
1362 EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface,
1363         const EGLint *attrib_list)
1364 {
1365     clearError();
1366
1367     const egl_display_ptr dp = validate_display(dpy);
1368     if (!dp) return EGL_FALSE;
1369
1370     SurfaceRef _s(dp.get(), surface);
1371     if (!_s.get())
1372         return setError(EGL_BAD_SURFACE, EGL_FALSE);
1373
1374     egl_surface_t const * const s = get_surface(surface);
1375     if (s->cnx->egl.eglLockSurfaceKHR) {
1376         return s->cnx->egl.eglLockSurfaceKHR(
1377                 dp->disp.dpy, s->surface, attrib_list);
1378     }
1379     return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1380 }
1381
1382 EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface)
1383 {
1384     clearError();
1385
1386     const egl_display_ptr dp = validate_display(dpy);
1387     if (!dp) return EGL_FALSE;
1388
1389     SurfaceRef _s(dp.get(), surface);
1390     if (!_s.get())
1391         return setError(EGL_BAD_SURFACE, EGL_FALSE);
1392
1393     egl_surface_t const * const s = get_surface(surface);
1394     if (s->cnx->egl.eglUnlockSurfaceKHR) {
1395         return s->cnx->egl.eglUnlockSurfaceKHR(dp->disp.dpy, s->surface);
1396     }
1397     return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1398 }
1399
1400 EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
1401         EGLClientBuffer buffer, const EGLint *attrib_list)
1402 {
1403     clearError();
1404
1405     const egl_display_ptr dp = validate_display(dpy);
1406     if (!dp) return EGL_NO_IMAGE_KHR;
1407
1408     ContextRef _c(dp.get(), ctx);
1409     egl_context_t * const c = _c.get();
1410
1411     EGLImageKHR result = EGL_NO_IMAGE_KHR;
1412     egl_connection_t* const cnx = &gEGLImpl;
1413     if (cnx->dso && cnx->egl.eglCreateImageKHR) {
1414         result = cnx->egl.eglCreateImageKHR(
1415                 dp->disp.dpy,
1416                 c ? c->context : EGL_NO_CONTEXT,
1417                 target, buffer, attrib_list);
1418     }
1419     return result;
1420 }
1421
1422 EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
1423 {
1424     clearError();
1425
1426     const egl_display_ptr dp = validate_display(dpy);
1427     if (!dp) return EGL_FALSE;
1428
1429     EGLBoolean result = EGL_FALSE;
1430     egl_connection_t* const cnx = &gEGLImpl;
1431     if (cnx->dso && cnx->egl.eglDestroyImageKHR) {
1432         result = cnx->egl.eglDestroyImageKHR(dp->disp.dpy, img);
1433     }
1434     return result;
1435 }
1436
1437 // ----------------------------------------------------------------------------
1438 // EGL_EGLEXT_VERSION 5
1439 // ----------------------------------------------------------------------------
1440
1441
1442 EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
1443 {
1444     clearError();
1445
1446     const egl_display_ptr dp = validate_display(dpy);
1447     if (!dp) return EGL_NO_SYNC_KHR;
1448
1449     EGLSyncKHR result = EGL_NO_SYNC_KHR;
1450     egl_connection_t* const cnx = &gEGLImpl;
1451     if (cnx->dso && cnx->egl.eglCreateSyncKHR) {
1452         result = cnx->egl.eglCreateSyncKHR(dp->disp.dpy, type, attrib_list);
1453     }
1454     return result;
1455 }
1456
1457 EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
1458 {
1459     clearError();
1460
1461     const egl_display_ptr dp = validate_display(dpy);
1462     if (!dp) return EGL_FALSE;
1463
1464     EGLBoolean result = EGL_FALSE;
1465     egl_connection_t* const cnx = &gEGLImpl;
1466     if (cnx->dso && cnx->egl.eglDestroySyncKHR) {
1467         result = cnx->egl.eglDestroySyncKHR(dp->disp.dpy, sync);
1468     }
1469     return result;
1470 }
1471
1472 EGLBoolean eglSignalSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode) {
1473     clearError();
1474
1475     const egl_display_ptr dp = validate_display(dpy);
1476     if (!dp) return EGL_FALSE;
1477
1478     EGLBoolean result = EGL_FALSE;
1479     egl_connection_t* const cnx = &gEGLImpl;
1480     if (cnx->dso && cnx->egl.eglSignalSyncKHR) {
1481         result = cnx->egl.eglSignalSyncKHR(
1482                 dp->disp.dpy, sync, mode);
1483     }
1484     return result;
1485 }
1486
1487 EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync,
1488         EGLint flags, EGLTimeKHR timeout)
1489 {
1490     clearError();
1491
1492     const egl_display_ptr dp = validate_display(dpy);
1493     if (!dp) return EGL_FALSE;
1494
1495     EGLBoolean result = EGL_FALSE;
1496     egl_connection_t* const cnx = &gEGLImpl;
1497     if (cnx->dso && cnx->egl.eglClientWaitSyncKHR) {
1498         result = cnx->egl.eglClientWaitSyncKHR(
1499                 dp->disp.dpy, sync, flags, timeout);
1500     }
1501     return result;
1502 }
1503
1504 EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync,
1505         EGLint attribute, EGLint *value)
1506 {
1507     clearError();
1508
1509     const egl_display_ptr dp = validate_display(dpy);
1510     if (!dp) return EGL_FALSE;
1511
1512     EGLBoolean result = EGL_FALSE;
1513     egl_connection_t* const cnx = &gEGLImpl;
1514     if (cnx->dso && cnx->egl.eglGetSyncAttribKHR) {
1515         result = cnx->egl.eglGetSyncAttribKHR(
1516                 dp->disp.dpy, sync, attribute, value);
1517     }
1518     return result;
1519 }
1520
1521 // ----------------------------------------------------------------------------
1522 // EGL_EGLEXT_VERSION 15
1523 // ----------------------------------------------------------------------------
1524
1525 EGLint eglWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags) {
1526     clearError();
1527     const egl_display_ptr dp = validate_display(dpy);
1528     if (!dp) return EGL_FALSE;
1529     EGLint result = EGL_FALSE;
1530     egl_connection_t* const cnx = &gEGLImpl;
1531     if (cnx->dso && cnx->egl.eglWaitSyncKHR) {
1532         result = cnx->egl.eglWaitSyncKHR(dp->disp.dpy, sync, flags);
1533     }
1534     return result;
1535 }
1536
1537 // ----------------------------------------------------------------------------
1538 // ANDROID extensions
1539 // ----------------------------------------------------------------------------
1540
1541 EGLint eglDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSyncKHR sync)
1542 {
1543     clearError();
1544
1545     const egl_display_ptr dp = validate_display(dpy);
1546     if (!dp) return EGL_NO_NATIVE_FENCE_FD_ANDROID;
1547
1548     EGLint result = EGL_NO_NATIVE_FENCE_FD_ANDROID;
1549     egl_connection_t* const cnx = &gEGLImpl;
1550     if (cnx->dso && cnx->egl.eglDupNativeFenceFDANDROID) {
1551         result = cnx->egl.eglDupNativeFenceFDANDROID(dp->disp.dpy, sync);
1552     }
1553     return result;
1554 }
1555
1556 EGLBoolean eglPresentationTimeANDROID(EGLDisplay dpy, EGLSurface surface,
1557         EGLnsecsANDROID time)
1558 {
1559     clearError();
1560
1561     const egl_display_ptr dp = validate_display(dpy);
1562     if (!dp) {
1563         return EGL_FALSE;
1564     }
1565
1566     SurfaceRef _s(dp.get(), surface);
1567     if (!_s.get()) {
1568         setError(EGL_BAD_SURFACE, EGL_FALSE);
1569         return EGL_FALSE;
1570     }
1571
1572     egl_surface_t const * const s = get_surface(surface);
1573     native_window_set_buffers_timestamp(s->win.get(), time);
1574
1575     return EGL_TRUE;
1576 }
1577
1578 // ----------------------------------------------------------------------------
1579 // NVIDIA extensions
1580 // ----------------------------------------------------------------------------
1581 EGLuint64NV eglGetSystemTimeFrequencyNV()
1582 {
1583     clearError();
1584
1585     if (egl_init_drivers() == EGL_FALSE) {
1586         return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1587     }
1588
1589     EGLuint64NV ret = 0;
1590     egl_connection_t* const cnx = &gEGLImpl;
1591
1592     if (cnx->dso && cnx->egl.eglGetSystemTimeFrequencyNV) {
1593         return cnx->egl.eglGetSystemTimeFrequencyNV();
1594     }
1595
1596     return setErrorQuiet(EGL_BAD_DISPLAY, 0);
1597 }
1598
1599 EGLuint64NV eglGetSystemTimeNV()
1600 {
1601     clearError();
1602
1603     if (egl_init_drivers() == EGL_FALSE) {
1604         return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1605     }
1606
1607     EGLuint64NV ret = 0;
1608     egl_connection_t* const cnx = &gEGLImpl;
1609
1610     if (cnx->dso && cnx->egl.eglGetSystemTimeNV) {
1611         return cnx->egl.eglGetSystemTimeNV();
1612     }
1613
1614     return setErrorQuiet(EGL_BAD_DISPLAY, 0);
1615 }
1616
1617 // ----------------------------------------------------------------------------
1618 // Partial update extension
1619 // ----------------------------------------------------------------------------
1620 EGLBoolean eglSetDamageRegionKHR(EGLDisplay dpy, EGLSurface surface,
1621         EGLint *rects, EGLint n_rects)
1622 {
1623     clearError();
1624
1625     const egl_display_ptr dp = validate_display(dpy);
1626     if (!dp) {
1627         setError(EGL_BAD_DISPLAY, EGL_FALSE);
1628         return EGL_FALSE;
1629     }
1630
1631     SurfaceRef _s(dp.get(), surface);
1632     if (!_s.get()) {
1633         setError(EGL_BAD_SURFACE, EGL_FALSE);
1634         return EGL_FALSE;
1635     }
1636
1637     egl_surface_t const * const s = get_surface(surface);
1638     if (s->cnx->egl.eglSetDamageRegionKHR) {
1639         return s->cnx->egl.eglSetDamageRegionKHR(dp->disp.dpy, s->surface,
1640                 rects, n_rects);
1641     }
1642
1643     return EGL_FALSE;
1644 }