OSDN Git Service

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