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