OSDN Git Service

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