OSDN Git Service

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