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 // 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     uintptr_t index = reinterpret_cast<uintptr_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         int result = native_window_api_connect(window, NATIVE_WINDOW_API_EGL);
    412         if (result != OK) {
    413             ALOGE("eglCreateWindowSurface: native_window_api_connect (win=%p) "
    414                     "failed (%#x) (already connected to another API?)",
    415                     window, result);
    416             return setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
    417         }
    418 
    419         // Set the native window's buffers format to match what this config requests.
    420         // Whether to use sRGB gamma is not part of the EGLconfig, but is part
    421         // of our native format. So if sRGB gamma is requested, we have to
    422         // modify the EGLconfig's format before setting the native window's
    423         // format.
    424 #if WORKAROUND_BUG_10194508
    425 #warning "WORKAROUND_10194508 enabled"
    426         EGLint format;
    427         if (!cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_NATIVE_VISUAL_ID,
    428                 &format)) {
    429             ALOGE("eglGetConfigAttrib(EGL_NATIVE_VISUAL_ID) failed: %#x",
    430                     eglGetError());
    431             format = 0;
    432         }
    433         if (attrib_list) {
    434             for (const EGLint* attr = attrib_list; *attr != EGL_NONE;
    435                     attr += 2) {
    436                 if (*attr == EGL_GL_COLORSPACE_KHR &&
    437                         dp->haveExtension("EGL_KHR_gl_colorspace")) {
    438                     if (ENABLE_EGL_KHR_GL_COLORSPACE) {
    439                         format = modifyFormatColorspace(format, *(attr+1));
    440                     } else {
    441                         // Normally we'd pass through unhandled attributes to
    442                         // the driver. But in case the driver implements this
    443                         // extension but we're disabling it, we want to prevent
    444                         // it getting through -- support will be broken without
    445                         // our help.
    446                         ALOGE("sRGB window surfaces not supported");
    447                         return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
    448                     }
    449                 }
    450             }
    451         }
    452 #else
    453         // by default, just pick RGBA_8888
    454         EGLint format = HAL_PIXEL_FORMAT_RGBA_8888;
    455 
    456         EGLint a = 0;
    457         cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_ALPHA_SIZE, &a);
    458         if (a > 0) {
    459             // alpha-channel requested, there's really only one suitable format
    460             format = HAL_PIXEL_FORMAT_RGBA_8888;
    461         } else {
    462             EGLint r, g, b;
    463             r = g = b = 0;
    464             cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_RED_SIZE,   &r);
    465             cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_GREEN_SIZE, &g);
    466             cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_BLUE_SIZE,  &b);
    467             EGLint colorDepth = r + g + b;
    468             if (colorDepth <= 16) {
    469                 format = HAL_PIXEL_FORMAT_RGB_565;
    470             } else {
    471                 format = HAL_PIXEL_FORMAT_RGBX_8888;
    472             }
    473         }
    474 
    475         // now select a corresponding sRGB format if needed
    476         if (attrib_list && dp->haveExtension("EGL_KHR_gl_colorspace")) {
    477             for (const EGLint* attr = attrib_list; *attr != EGL_NONE; attr += 2) {
    478                 if (*attr == EGL_GL_COLORSPACE_KHR) {
    479                     if (ENABLE_EGL_KHR_GL_COLORSPACE) {
    480                         format = modifyFormatColorspace(format, *(attr+1));
    481                     } else {
    482                         // Normally we'd pass through unhandled attributes to
    483                         // the driver. But in case the driver implements this
    484                         // extension but we're disabling it, we want to prevent
    485                         // it getting through -- support will be broken without
    486                         // our help.
    487                         ALOGE("sRGB window surfaces not supported");
    488                         return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
    489                     }
    490                 }
    491             }
    492         }
    493 #endif
    494         if (format != 0) {
    495             int err = native_window_set_buffers_format(window, format);
    496             if (err != 0) {
    497                 ALOGE("error setting native window pixel format: %s (%d)",
    498                         strerror(-err), err);
    499                 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
    500                 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
    501             }
    502         }
    503 
    504         // the EGL spec requires that a new EGLSurface default to swap interval
    505         // 1, so explicitly set that on the window here.
    506         ANativeWindow* anw = reinterpret_cast<ANativeWindow*>(window);
    507         anw->setSwapInterval(anw, 1);
    508 
    509         EGLSurface surface = cnx->egl.eglCreateWindowSurface(
    510                 iDpy, config, window, attrib_list);
    511         if (surface != EGL_NO_SURFACE) {
    512             egl_surface_t* s = new egl_surface_t(dp.get(), config, window,
    513                     surface, cnx);
    514             return s;
    515         }
    516 
    517         // EGLSurface creation failed
    518         native_window_set_buffers_format(window, 0);
    519         native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
    520     }
    521     return EGL_NO_SURFACE;
    522 }
    523 
    524 EGLSurface eglCreatePixmapSurface(  EGLDisplay dpy, EGLConfig config,
    525                                     NativePixmapType pixmap,
    526                                     const EGLint *attrib_list)
    527 {
    528     clearError();
    529 
    530     egl_connection_t* cnx = NULL;
    531     egl_display_ptr dp = validate_display_connection(dpy, cnx);
    532     if (dp) {
    533         EGLSurface surface = cnx->egl.eglCreatePixmapSurface(
    534                 dp->disp.dpy, config, pixmap, attrib_list);
    535         if (surface != EGL_NO_SURFACE) {
    536             egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL,
    537                     surface, cnx);
    538             return s;
    539         }
    540     }
    541     return EGL_NO_SURFACE;
    542 }
    543 
    544 EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config,
    545                                     const EGLint *attrib_list)
    546 {
    547     clearError();
    548 
    549     egl_connection_t* cnx = NULL;
    550     egl_display_ptr dp = validate_display_connection(dpy, cnx);
    551     if (dp) {
    552         EGLSurface surface = cnx->egl.eglCreatePbufferSurface(
    553                 dp->disp.dpy, config, attrib_list);
    554         if (surface != EGL_NO_SURFACE) {
    555             egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL,
    556                     surface, cnx);
    557             return s;
    558         }
    559     }
    560     return EGL_NO_SURFACE;
    561 }
    562 
    563 EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
    564 {
    565     clearError();
    566 
    567     const egl_display_ptr dp = validate_display(dpy);
    568     if (!dp) return EGL_FALSE;
    569 
    570     SurfaceRef _s(dp.get(), surface);
    571     if (!_s.get())
    572         return setError(EGL_BAD_SURFACE, EGL_FALSE);
    573 
    574     egl_surface_t * const s = get_surface(surface);
    575     EGLBoolean result = s->cnx->egl.eglDestroySurface(dp->disp.dpy, s->surface);
    576     if (result == EGL_TRUE) {
    577         _s.terminate();
    578     }
    579     return result;
    580 }
    581 
    582 EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface,
    583                             EGLint attribute, EGLint *value)
    584 {
    585     clearError();
    586 
    587     const egl_display_ptr dp = validate_display(dpy);
    588     if (!dp) return EGL_FALSE;
    589 
    590     SurfaceRef _s(dp.get(), surface);
    591     if (!_s.get())
    592         return setError(EGL_BAD_SURFACE, EGL_FALSE);
    593 
    594     egl_surface_t const * const s = get_surface(surface);
    595     return s->cnx->egl.eglQuerySurface(
    596             dp->disp.dpy, s->surface, attribute, value);
    597 }
    598 
    599 void EGLAPI eglBeginFrame(EGLDisplay dpy, EGLSurface surface) {
    600     ATRACE_CALL();
    601     clearError();
    602 
    603     const egl_display_ptr dp = validate_display(dpy);
    604     if (!dp) {
    605         return;
    606     }
    607 
    608     SurfaceRef _s(dp.get(), surface);
    609     if (!_s.get()) {
    610         setError(EGL_BAD_SURFACE, EGL_FALSE);
    611         return;
    612     }
    613 }
    614 
    615 // ----------------------------------------------------------------------------
    616 // Contexts
    617 // ----------------------------------------------------------------------------
    618 
    619 EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config,
    620                             EGLContext share_list, const EGLint *attrib_list)
    621 {
    622     clearError();
    623 
    624     egl_connection_t* cnx = NULL;
    625     const egl_display_ptr dp = validate_display_connection(dpy, cnx);
    626     if (dp) {
    627         if (share_list != EGL_NO_CONTEXT) {
    628             if (!ContextRef(dp.get(), share_list).get()) {
    629                 return setError(EGL_BAD_CONTEXT, EGL_NO_CONTEXT);
    630             }
    631             egl_context_t* const c = get_context(share_list);
    632             share_list = c->context;
    633         }
    634         EGLContext context = cnx->egl.eglCreateContext(
    635                 dp->disp.dpy, config, share_list, attrib_list);
    636         if (context != EGL_NO_CONTEXT) {
    637             // figure out if it's a GLESv1 or GLESv2
    638             int version = 0;
    639             if (attrib_list) {
    640                 while (*attrib_list != EGL_NONE) {
    641                     GLint attr = *attrib_list++;
    642                     GLint value = *attrib_list++;
    643                     if (attr == EGL_CONTEXT_CLIENT_VERSION) {
    644                         if (value == 1) {
    645                             version = egl_connection_t::GLESv1_INDEX;
    646                         } else if (value == 2 || value == 3) {
    647                             version = egl_connection_t::GLESv2_INDEX;
    648                         }
    649                     }
    650                 };
    651             }
    652             egl_context_t* c = new egl_context_t(dpy, context, config, cnx,
    653                     version);
    654 #if EGL_TRACE
    655             if (getEGLDebugLevel() > 0)
    656                 GLTrace_eglCreateContext(version, c);
    657 #endif
    658             return c;
    659         }
    660     }
    661     return EGL_NO_CONTEXT;
    662 }
    663 
    664 EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
    665 {
    666     clearError();
    667 
    668     const egl_display_ptr dp = validate_display(dpy);
    669     if (!dp)
    670         return EGL_FALSE;
    671 
    672     ContextRef _c(dp.get(), ctx);
    673     if (!_c.get())
    674         return setError(EGL_BAD_CONTEXT, EGL_FALSE);
    675 
    676     egl_context_t * const c = get_context(ctx);
    677     EGLBoolean result = c->cnx->egl.eglDestroyContext(dp->disp.dpy, c->context);
    678     if (result == EGL_TRUE) {
    679         _c.terminate();
    680     }
    681     return result;
    682 }
    683 
    684 EGLBoolean eglMakeCurrent(  EGLDisplay dpy, EGLSurface draw,
    685                             EGLSurface read, EGLContext ctx)
    686 {
    687     clearError();
    688 
    689     egl_display_ptr dp = validate_display(dpy);
    690     if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
    691 
    692     // If ctx is not EGL_NO_CONTEXT, read is not EGL_NO_SURFACE, or draw is not
    693     // EGL_NO_SURFACE, then an EGL_NOT_INITIALIZED error is generated if dpy is
    694     // a valid but uninitialized display.
    695     if ( (ctx != EGL_NO_CONTEXT) || (read != EGL_NO_SURFACE) ||
    696          (draw != EGL_NO_SURFACE) ) {
    697         if (!dp->isReady()) return setError(EGL_NOT_INITIALIZED, EGL_FALSE);
    698     }
    699 
    700     // get a reference to the object passed in
    701     ContextRef _c(dp.get(), ctx);
    702     SurfaceRef _d(dp.get(), draw);
    703     SurfaceRef _r(dp.get(), read);
    704 
    705     // validate the context (if not EGL_NO_CONTEXT)
    706     if ((ctx != EGL_NO_CONTEXT) && !_c.get()) {
    707         // EGL_NO_CONTEXT is valid
    708         return setError(EGL_BAD_CONTEXT, EGL_FALSE);
    709     }
    710 
    711     // these are the underlying implementation's object
    712     EGLContext impl_ctx  = EGL_NO_CONTEXT;
    713     EGLSurface impl_draw = EGL_NO_SURFACE;
    714     EGLSurface impl_read = EGL_NO_SURFACE;
    715 
    716     // these are our objects structs passed in
    717     egl_context_t       * c = NULL;
    718     egl_surface_t const * d = NULL;
    719     egl_surface_t const * r = NULL;
    720 
    721     // these are the current objects structs
    722     egl_context_t * cur_c = get_context(getContext());
    723 
    724     if (ctx != EGL_NO_CONTEXT) {
    725         c = get_context(ctx);
    726         impl_ctx = c->context;
    727     } else {
    728         // no context given, use the implementation of the current context
    729         if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) {
    730             // calling eglMakeCurrent( ..., !=0, !=0, EGL_NO_CONTEXT);
    731             return setError(EGL_BAD_MATCH, EGL_FALSE);
    732         }
    733         if (cur_c == NULL) {
    734             // no current context
    735             // not an error, there is just no current context.
    736             return EGL_TRUE;
    737         }
    738     }
    739 
    740     // retrieve the underlying implementation's draw EGLSurface
    741     if (draw != EGL_NO_SURFACE) {
    742         if (!_d.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
    743         d = get_surface(draw);
    744         impl_draw = d->surface;
    745     }
    746 
    747     // retrieve the underlying implementation's read EGLSurface
    748     if (read != EGL_NO_SURFACE) {
    749         if (!_r.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
    750         r = get_surface(read);
    751         impl_read = r->surface;
    752     }
    753 
    754 
    755     EGLBoolean result = dp->makeCurrent(c, cur_c,
    756             draw, read, ctx,
    757             impl_draw, impl_read, impl_ctx);
    758 
    759     if (result == EGL_TRUE) {
    760         if (c) {
    761             setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
    762             egl_tls_t::setContext(ctx);
    763 #if EGL_TRACE
    764             if (getEGLDebugLevel() > 0)
    765                 GLTrace_eglMakeCurrent(c->version, c->cnx->hooks[c->version], ctx);
    766 #endif
    767             _c.acquire();
    768             _r.acquire();
    769             _d.acquire();
    770         } else {
    771             setGLHooksThreadSpecific(&gHooksNoContext);
    772             egl_tls_t::setContext(EGL_NO_CONTEXT);
    773         }
    774     } else {
    775         // this will ALOGE the error
    776         egl_connection_t* const cnx = &gEGLImpl;
    777         result = setError(cnx->egl.eglGetError(), EGL_FALSE);
    778     }
    779     return result;
    780 }
    781 
    782 
    783 EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx,
    784                             EGLint attribute, EGLint *value)
    785 {
    786     clearError();
    787 
    788     const egl_display_ptr dp = validate_display(dpy);
    789     if (!dp) return EGL_FALSE;
    790 
    791     ContextRef _c(dp.get(), ctx);
    792     if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
    793 
    794     egl_context_t * const c = get_context(ctx);
    795     return c->cnx->egl.eglQueryContext(
    796             dp->disp.dpy, c->context, attribute, value);
    797 
    798 }
    799 
    800 EGLContext eglGetCurrentContext(void)
    801 {
    802     // could be called before eglInitialize(), but we wouldn't have a context
    803     // then, and this function would correctly return EGL_NO_CONTEXT.
    804 
    805     clearError();
    806 
    807     EGLContext ctx = getContext();
    808     return ctx;
    809 }
    810 
    811 EGLSurface eglGetCurrentSurface(EGLint readdraw)
    812 {
    813     // could be called before eglInitialize(), but we wouldn't have a context
    814     // then, and this function would correctly return EGL_NO_SURFACE.
    815 
    816     clearError();
    817 
    818     EGLContext ctx = getContext();
    819     if (ctx) {
    820         egl_context_t const * const c = get_context(ctx);
    821         if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
    822         switch (readdraw) {
    823             case EGL_READ: return c->read;
    824             case EGL_DRAW: return c->draw;
    825             default: return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
    826         }
    827     }
    828     return EGL_NO_SURFACE;
    829 }
    830 
    831 EGLDisplay eglGetCurrentDisplay(void)
    832 {
    833     // could be called before eglInitialize(), but we wouldn't have a context
    834     // then, and this function would correctly return EGL_NO_DISPLAY.
    835 
    836     clearError();
    837 
    838     EGLContext ctx = getContext();
    839     if (ctx) {
    840         egl_context_t const * const c = get_context(ctx);
    841         if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
    842         return c->dpy;
    843     }
    844     return EGL_NO_DISPLAY;
    845 }
    846 
    847 EGLBoolean eglWaitGL(void)
    848 {
    849     clearError();
    850 
    851     egl_connection_t* const cnx = &gEGLImpl;
    852     if (!cnx->dso)
    853         return setError(EGL_BAD_CONTEXT, EGL_FALSE);
    854 
    855     return cnx->egl.eglWaitGL();
    856 }
    857 
    858 EGLBoolean eglWaitNative(EGLint engine)
    859 {
    860     clearError();
    861 
    862     egl_connection_t* const cnx = &gEGLImpl;
    863     if (!cnx->dso)
    864         return setError(EGL_BAD_CONTEXT, EGL_FALSE);
    865 
    866     return cnx->egl.eglWaitNative(engine);
    867 }
    868 
    869 EGLint eglGetError(void)
    870 {
    871     EGLint err = EGL_SUCCESS;
    872     egl_connection_t* const cnx = &gEGLImpl;
    873     if (cnx->dso) {
    874         err = cnx->egl.eglGetError();
    875     }
    876     if (err == EGL_SUCCESS) {
    877         err = egl_tls_t::getError();
    878     }
    879     return err;
    880 }
    881 
    882 static __eglMustCastToProperFunctionPointerType findBuiltinWrapper(
    883         const char* procname) {
    884     const egl_connection_t* cnx = &gEGLImpl;
    885     void* proc = NULL;
    886 
    887     proc = dlsym(cnx->libEgl, procname);
    888     if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
    889 
    890     proc = dlsym(cnx->libGles2, procname);
    891     if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
    892 
    893     proc = dlsym(cnx->libGles1, procname);
    894     if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
    895 
    896     return NULL;
    897 }
    898 
    899 __eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
    900 {
    901     // eglGetProcAddress() could be the very first function called
    902     // in which case we must make sure we've initialized ourselves, this
    903     // happens the first time egl_get_display() is called.
    904 
    905     clearError();
    906 
    907     if (egl_init_drivers() == EGL_FALSE) {
    908         setError(EGL_BAD_PARAMETER, NULL);
    909         return  NULL;
    910     }
    911 
    912     if (FILTER_EXTENSIONS(procname)) {
    913         return NULL;
    914     }
    915 
    916     __eglMustCastToProperFunctionPointerType addr;
    917     addr = findProcAddress(procname, sExtensionMap, NELEM(sExtensionMap));
    918     if (addr) return addr;
    919 
    920     addr = findBuiltinWrapper(procname);
    921     if (addr) return addr;
    922 
    923     // this protects accesses to sGLExtentionMap and sGLExtentionSlot
    924     pthread_mutex_lock(&sExtensionMapMutex);
    925 
    926         /*
    927          * Since eglGetProcAddress() is not associated to anything, it needs
    928          * to return a function pointer that "works" regardless of what
    929          * the current context is.
    930          *
    931          * For this reason, we return a "forwarder", a small stub that takes
    932          * care of calling the function associated with the context
    933          * currently bound.
    934          *
    935          * We first look for extensions we've already resolved, if we're seeing
    936          * this extension for the first time, we go through all our
    937          * implementations and call eglGetProcAddress() and record the
    938          * result in the appropriate implementation hooks and return the
    939          * address of the forwarder corresponding to that hook set.
    940          *
    941          */
    942 
    943         const String8 name(procname);
    944         addr = sGLExtentionMap.valueFor(name);
    945         const int slot = sGLExtentionSlot;
    946 
    947         ALOGE_IF(slot >= MAX_NUMBER_OF_GL_EXTENSIONS,
    948                 "no more slots for eglGetProcAddress(\"%s\")",
    949                 procname);
    950 
    951 #if EGL_TRACE
    952         gl_hooks_t *debugHooks = GLTrace_getGLHooks();
    953 #endif
    954 
    955         if (!addr && (slot < MAX_NUMBER_OF_GL_EXTENSIONS)) {
    956             bool found = false;
    957 
    958             egl_connection_t* const cnx = &gEGLImpl;
    959             if (cnx->dso && cnx->egl.eglGetProcAddress) {
    960                 // Extensions are independent of the bound context
    961                 addr =
    962                 cnx->hooks[egl_connection_t::GLESv1_INDEX]->ext.extensions[slot] =
    963                 cnx->hooks[egl_connection_t::GLESv2_INDEX]->ext.extensions[slot] =
    964 #if EGL_TRACE
    965                 debugHooks->ext.extensions[slot] =
    966                 gHooksTrace.ext.extensions[slot] =
    967 #endif
    968                         cnx->egl.eglGetProcAddress(procname);
    969                 if (addr) found = true;
    970             }
    971 
    972             if (found) {
    973                 addr = gExtensionForwarders[slot];
    974                 sGLExtentionMap.add(name, addr);
    975                 sGLExtentionSlot++;
    976             }
    977         }
    978 
    979     pthread_mutex_unlock(&sExtensionMapMutex);
    980     return addr;
    981 }
    982 
    983 class FrameCompletionThread : public Thread {
    984 public:
    985 
    986     static void queueSync(EGLSyncKHR sync) {
    987         static sp<FrameCompletionThread> thread(new FrameCompletionThread);
    988         static bool running = false;
    989         if (!running) {
    990             thread->run("GPUFrameCompletion");
    991             running = true;
    992         }
    993         {
    994             Mutex::Autolock lock(thread->mMutex);
    995             ScopedTrace st(ATRACE_TAG, String8::format("kicked off frame %d",
    996                     thread->mFramesQueued).string());
    997             thread->mQueue.push_back(sync);
    998             thread->mCondition.signal();
    999             thread->mFramesQueued++;
   1000             ATRACE_INT("GPU Frames Outstanding", thread->mQueue.size());
   1001         }
   1002     }
   1003 
   1004 private:
   1005     FrameCompletionThread() : mFramesQueued(0), mFramesCompleted(0) {}
   1006 
   1007     virtual bool threadLoop() {
   1008         EGLSyncKHR sync;
   1009         uint32_t frameNum;
   1010         {
   1011             Mutex::Autolock lock(mMutex);
   1012             while (mQueue.isEmpty()) {
   1013                 mCondition.wait(mMutex);
   1014             }
   1015             sync = mQueue[0];
   1016             frameNum = mFramesCompleted;
   1017         }
   1018         EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
   1019         {
   1020             ScopedTrace st(ATRACE_TAG, String8::format("waiting for frame %d",
   1021                     frameNum).string());
   1022             EGLint result = eglClientWaitSyncKHR(dpy, sync, 0, EGL_FOREVER_KHR);
   1023             if (result == EGL_FALSE) {
   1024                 ALOGE("FrameCompletion: error waiting for fence: %#x", eglGetError());
   1025             } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
   1026                 ALOGE("FrameCompletion: timeout waiting for fence");
   1027             }
   1028             eglDestroySyncKHR(dpy, sync);
   1029         }
   1030         {
   1031             Mutex::Autolock lock(mMutex);
   1032             mQueue.removeAt(0);
   1033             mFramesCompleted++;
   1034             ATRACE_INT("GPU Frames Outstanding", mQueue.size());
   1035         }
   1036         return true;
   1037     }
   1038 
   1039     uint32_t mFramesQueued;
   1040     uint32_t mFramesCompleted;
   1041     Vector<EGLSyncKHR> mQueue;
   1042     Condition mCondition;
   1043     Mutex mMutex;
   1044 };
   1045 
   1046 EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw)
   1047 {
   1048     ATRACE_CALL();
   1049     clearError();
   1050 
   1051     const egl_display_ptr dp = validate_display(dpy);
   1052     if (!dp) return EGL_FALSE;
   1053 
   1054     SurfaceRef _s(dp.get(), draw);
   1055     if (!_s.get())
   1056         return setError(EGL_BAD_SURFACE, EGL_FALSE);
   1057 
   1058 #if EGL_TRACE
   1059     gl_hooks_t const *trace_hooks = getGLTraceThreadSpecific();
   1060     if (getEGLDebugLevel() > 0) {
   1061         if (trace_hooks == NULL) {
   1062             if (GLTrace_start() < 0) {
   1063                 ALOGE("Disabling Tracer for OpenGL ES");
   1064                 setEGLDebugLevel(0);
   1065             } else {
   1066                 // switch over to the trace version of hooks
   1067                 EGLContext ctx = egl_tls_t::getContext();
   1068                 egl_context_t * const c = get_context(ctx);
   1069                 if (c) {
   1070                     setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
   1071                     GLTrace_eglMakeCurrent(c->version, c->cnx->hooks[c->version], ctx);
   1072                 }
   1073             }
   1074         }
   1075 
   1076         GLTrace_eglSwapBuffers(dpy, draw);
   1077     } else if (trace_hooks != NULL) {
   1078         // tracing is now disabled, so switch back to the non trace version
   1079         EGLContext ctx = egl_tls_t::getContext();
   1080         egl_context_t * const c = get_context(ctx);
   1081         if (c) setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
   1082         GLTrace_stop();
   1083     }
   1084 #endif
   1085 
   1086     egl_surface_t const * const s = get_surface(draw);
   1087 
   1088     if (CC_UNLIKELY(dp->traceGpuCompletion)) {
   1089         EGLSyncKHR sync = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, NULL);
   1090         if (sync != EGL_NO_SYNC_KHR) {
   1091             FrameCompletionThread::queueSync(sync);
   1092         }
   1093     }
   1094 
   1095     if (CC_UNLIKELY(dp->finishOnSwap)) {
   1096         uint32_t pixel;
   1097         egl_context_t * const c = get_context( egl_tls_t::getContext() );
   1098         if (c) {
   1099             // glReadPixels() ensures that the frame is complete
   1100             s->cnx->hooks[c->version]->gl.glReadPixels(0,0,1,1,
   1101                     GL_RGBA,GL_UNSIGNED_BYTE,&pixel);
   1102         }
   1103     }
   1104 
   1105     return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface);
   1106 }
   1107 
   1108 EGLBoolean eglCopyBuffers(  EGLDisplay dpy, EGLSurface surface,
   1109                             NativePixmapType target)
   1110 {
   1111     clearError();
   1112 
   1113     const egl_display_ptr dp = validate_display(dpy);
   1114     if (!dp) return EGL_FALSE;
   1115 
   1116     SurfaceRef _s(dp.get(), surface);
   1117     if (!_s.get())
   1118         return setError(EGL_BAD_SURFACE, EGL_FALSE);
   1119 
   1120     egl_surface_t const * const s = get_surface(surface);
   1121     return s->cnx->egl.eglCopyBuffers(dp->disp.dpy, s->surface, target);
   1122 }
   1123 
   1124 const char* eglQueryString(EGLDisplay dpy, EGLint name)
   1125 {
   1126     clearError();
   1127 
   1128     const egl_display_ptr dp = validate_display(dpy);
   1129     if (!dp) return (const char *) NULL;
   1130 
   1131     switch (name) {
   1132         case EGL_VENDOR:
   1133             return dp->getVendorString();
   1134         case EGL_VERSION:
   1135             return dp->getVersionString();
   1136         case EGL_EXTENSIONS:
   1137             return dp->getExtensionString();
   1138         case EGL_CLIENT_APIS:
   1139             return dp->getClientApiString();
   1140     }
   1141     return setError(EGL_BAD_PARAMETER, (const char *)0);
   1142 }
   1143 
   1144 EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name)
   1145 {
   1146     clearError();
   1147 
   1148     const egl_display_ptr dp = validate_display(dpy);
   1149     if (!dp) return (const char *) NULL;
   1150 
   1151     switch (name) {
   1152         case EGL_VENDOR:
   1153             return dp->disp.queryString.vendor;
   1154         case EGL_VERSION:
   1155             return dp->disp.queryString.version;
   1156         case EGL_EXTENSIONS:
   1157             return dp->disp.queryString.extensions;
   1158         case EGL_CLIENT_APIS:
   1159             return dp->disp.queryString.clientApi;
   1160     }
   1161     return setError(EGL_BAD_PARAMETER, (const char *)0);
   1162 }
   1163 
   1164 // ----------------------------------------------------------------------------
   1165 // EGL 1.1
   1166 // ----------------------------------------------------------------------------
   1167 
   1168 EGLBoolean eglSurfaceAttrib(
   1169         EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
   1170 {
   1171     clearError();
   1172 
   1173     const egl_display_ptr dp = validate_display(dpy);
   1174     if (!dp) return EGL_FALSE;
   1175 
   1176     SurfaceRef _s(dp.get(), surface);
   1177     if (!_s.get())
   1178         return setError(EGL_BAD_SURFACE, EGL_FALSE);
   1179 
   1180     egl_surface_t const * const s = get_surface(surface);
   1181     if (s->cnx->egl.eglSurfaceAttrib) {
   1182         return s->cnx->egl.eglSurfaceAttrib(
   1183                 dp->disp.dpy, s->surface, attribute, value);
   1184     }
   1185     return setError(EGL_BAD_SURFACE, EGL_FALSE);
   1186 }
   1187 
   1188 EGLBoolean eglBindTexImage(
   1189         EGLDisplay dpy, EGLSurface surface, EGLint buffer)
   1190 {
   1191     clearError();
   1192 
   1193     const egl_display_ptr dp = validate_display(dpy);
   1194     if (!dp) return EGL_FALSE;
   1195 
   1196     SurfaceRef _s(dp.get(), surface);
   1197     if (!_s.get())
   1198         return setError(EGL_BAD_SURFACE, EGL_FALSE);
   1199 
   1200     egl_surface_t const * const s = get_surface(surface);
   1201     if (s->cnx->egl.eglBindTexImage) {
   1202         return s->cnx->egl.eglBindTexImage(
   1203                 dp->disp.dpy, s->surface, buffer);
   1204     }
   1205     return setError(EGL_BAD_SURFACE, EGL_FALSE);
   1206 }
   1207 
   1208 EGLBoolean eglReleaseTexImage(
   1209         EGLDisplay dpy, EGLSurface surface, EGLint buffer)
   1210 {
   1211     clearError();
   1212 
   1213     const egl_display_ptr dp = validate_display(dpy);
   1214     if (!dp) return EGL_FALSE;
   1215 
   1216     SurfaceRef _s(dp.get(), surface);
   1217     if (!_s.get())
   1218         return setError(EGL_BAD_SURFACE, EGL_FALSE);
   1219 
   1220     egl_surface_t const * const s = get_surface(surface);
   1221     if (s->cnx->egl.eglReleaseTexImage) {
   1222         return s->cnx->egl.eglReleaseTexImage(
   1223                 dp->disp.dpy, s->surface, buffer);
   1224     }
   1225     return setError(EGL_BAD_SURFACE, EGL_FALSE);
   1226 }
   1227 
   1228 EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
   1229 {
   1230     clearError();
   1231 
   1232     const egl_display_ptr dp = validate_display(dpy);
   1233     if (!dp) return EGL_FALSE;
   1234 
   1235     EGLBoolean res = EGL_TRUE;
   1236     egl_connection_t* const cnx = &gEGLImpl;
   1237     if (cnx->dso && cnx->egl.eglSwapInterval) {
   1238         res = cnx->egl.eglSwapInterval(dp->disp.dpy, interval);
   1239     }
   1240 
   1241     return res;
   1242 }
   1243 
   1244 
   1245 // ----------------------------------------------------------------------------
   1246 // EGL 1.2
   1247 // ----------------------------------------------------------------------------
   1248 
   1249 EGLBoolean eglWaitClient(void)
   1250 {
   1251     clearError();
   1252 
   1253     egl_connection_t* const cnx = &gEGLImpl;
   1254     if (!cnx->dso)
   1255         return setError(EGL_BAD_CONTEXT, EGL_FALSE);
   1256 
   1257     EGLBoolean res;
   1258     if (cnx->egl.eglWaitClient) {
   1259         res = cnx->egl.eglWaitClient();
   1260     } else {
   1261         res = cnx->egl.eglWaitGL();
   1262     }
   1263     return res;
   1264 }
   1265 
   1266 EGLBoolean eglBindAPI(EGLenum api)
   1267 {
   1268     clearError();
   1269 
   1270     if (egl_init_drivers() == EGL_FALSE) {
   1271         return setError(EGL_BAD_PARAMETER, EGL_FALSE);
   1272     }
   1273 
   1274     // bind this API on all EGLs
   1275     EGLBoolean res = EGL_TRUE;
   1276     egl_connection_t* const cnx = &gEGLImpl;
   1277     if (cnx->dso && cnx->egl.eglBindAPI) {
   1278         res = cnx->egl.eglBindAPI(api);
   1279     }
   1280     return res;
   1281 }
   1282 
   1283 EGLenum eglQueryAPI(void)
   1284 {
   1285     clearError();
   1286 
   1287     if (egl_init_drivers() == EGL_FALSE) {
   1288         return setError(EGL_BAD_PARAMETER, EGL_FALSE);
   1289     }
   1290 
   1291     egl_connection_t* const cnx = &gEGLImpl;
   1292     if (cnx->dso && cnx->egl.eglQueryAPI) {
   1293         return cnx->egl.eglQueryAPI();
   1294     }
   1295 
   1296     // or, it can only be OpenGL ES
   1297     return EGL_OPENGL_ES_API;
   1298 }
   1299 
   1300 EGLBoolean eglReleaseThread(void)
   1301 {
   1302     clearError();
   1303 
   1304 #if EGL_TRACE
   1305     if (getEGLDebugLevel() > 0)
   1306         GLTrace_eglReleaseThread();
   1307 #endif
   1308 
   1309     // If there is context bound to the thread, release it
   1310     egl_display_t::loseCurrent(get_context(getContext()));
   1311 
   1312     egl_connection_t* const cnx = &gEGLImpl;
   1313     if (cnx->dso && cnx->egl.eglReleaseThread) {
   1314         cnx->egl.eglReleaseThread();
   1315     }
   1316     egl_tls_t::clearTLS();
   1317     return EGL_TRUE;
   1318 }
   1319 
   1320 EGLSurface eglCreatePbufferFromClientBuffer(
   1321           EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
   1322           EGLConfig config, const EGLint *attrib_list)
   1323 {
   1324     clearError();
   1325 
   1326     egl_connection_t* cnx = NULL;
   1327     const egl_display_ptr dp = validate_display_connection(dpy, cnx);
   1328     if (!dp) return EGL_FALSE;
   1329     if (cnx->egl.eglCreatePbufferFromClientBuffer) {
   1330         return cnx->egl.eglCreatePbufferFromClientBuffer(
   1331                 dp->disp.dpy, buftype, buffer, config, attrib_list);
   1332     }
   1333     return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE);
   1334 }
   1335 
   1336 // ----------------------------------------------------------------------------
   1337 // EGL_EGLEXT_VERSION 3
   1338 // ----------------------------------------------------------------------------
   1339 
   1340 EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface,
   1341         const EGLint *attrib_list)
   1342 {
   1343     clearError();
   1344 
   1345     const egl_display_ptr dp = validate_display(dpy);
   1346     if (!dp) return EGL_FALSE;
   1347 
   1348     SurfaceRef _s(dp.get(), surface);
   1349     if (!_s.get())
   1350         return setError(EGL_BAD_SURFACE, EGL_FALSE);
   1351 
   1352     egl_surface_t const * const s = get_surface(surface);
   1353     if (s->cnx->egl.eglLockSurfaceKHR) {
   1354         return s->cnx->egl.eglLockSurfaceKHR(
   1355                 dp->disp.dpy, s->surface, attrib_list);
   1356     }
   1357     return setError(EGL_BAD_DISPLAY, EGL_FALSE);
   1358 }
   1359 
   1360 EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface)
   1361 {
   1362     clearError();
   1363 
   1364     const egl_display_ptr dp = validate_display(dpy);
   1365     if (!dp) return EGL_FALSE;
   1366 
   1367     SurfaceRef _s(dp.get(), surface);
   1368     if (!_s.get())
   1369         return setError(EGL_BAD_SURFACE, EGL_FALSE);
   1370 
   1371     egl_surface_t const * const s = get_surface(surface);
   1372     if (s->cnx->egl.eglUnlockSurfaceKHR) {
   1373         return s->cnx->egl.eglUnlockSurfaceKHR(dp->disp.dpy, s->surface);
   1374     }
   1375     return setError(EGL_BAD_DISPLAY, EGL_FALSE);
   1376 }
   1377 
   1378 EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
   1379         EGLClientBuffer buffer, const EGLint *attrib_list)
   1380 {
   1381     clearError();
   1382 
   1383     const egl_display_ptr dp = validate_display(dpy);
   1384     if (!dp) return EGL_NO_IMAGE_KHR;
   1385 
   1386     ContextRef _c(dp.get(), ctx);
   1387     egl_context_t * const c = _c.get();
   1388 
   1389     EGLImageKHR result = EGL_NO_IMAGE_KHR;
   1390     egl_connection_t* const cnx = &gEGLImpl;
   1391     if (cnx->dso && cnx->egl.eglCreateImageKHR) {
   1392         result = cnx->egl.eglCreateImageKHR(
   1393                 dp->disp.dpy,
   1394                 c ? c->context : EGL_NO_CONTEXT,
   1395                 target, buffer, attrib_list);
   1396     }
   1397     return result;
   1398 }
   1399 
   1400 EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
   1401 {
   1402     clearError();
   1403 
   1404     const egl_display_ptr dp = validate_display(dpy);
   1405     if (!dp) return EGL_FALSE;
   1406 
   1407     EGLBoolean result = EGL_FALSE;
   1408     egl_connection_t* const cnx = &gEGLImpl;
   1409     if (cnx->dso && cnx->egl.eglDestroyImageKHR) {
   1410         result = cnx->egl.eglDestroyImageKHR(dp->disp.dpy, img);
   1411     }
   1412     return result;
   1413 }
   1414 
   1415 // ----------------------------------------------------------------------------
   1416 // EGL_EGLEXT_VERSION 5
   1417 // ----------------------------------------------------------------------------
   1418 
   1419 
   1420 EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
   1421 {
   1422     clearError();
   1423 
   1424     const egl_display_ptr dp = validate_display(dpy);
   1425     if (!dp) return EGL_NO_SYNC_KHR;
   1426 
   1427     EGLSyncKHR result = EGL_NO_SYNC_KHR;
   1428     egl_connection_t* const cnx = &gEGLImpl;
   1429     if (cnx->dso && cnx->egl.eglCreateSyncKHR) {
   1430         result = cnx->egl.eglCreateSyncKHR(dp->disp.dpy, type, attrib_list);
   1431     }
   1432     return result;
   1433 }
   1434 
   1435 EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
   1436 {
   1437     clearError();
   1438 
   1439     const egl_display_ptr dp = validate_display(dpy);
   1440     if (!dp) return EGL_FALSE;
   1441 
   1442     EGLBoolean result = EGL_FALSE;
   1443     egl_connection_t* const cnx = &gEGLImpl;
   1444     if (cnx->dso && cnx->egl.eglDestroySyncKHR) {
   1445         result = cnx->egl.eglDestroySyncKHR(dp->disp.dpy, sync);
   1446     }
   1447     return result;
   1448 }
   1449 
   1450 EGLBoolean eglSignalSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode) {
   1451     clearError();
   1452 
   1453     const egl_display_ptr dp = validate_display(dpy);
   1454     if (!dp) return EGL_FALSE;
   1455 
   1456     EGLBoolean result = EGL_FALSE;
   1457     egl_connection_t* const cnx = &gEGLImpl;
   1458     if (cnx->dso && cnx->egl.eglSignalSyncKHR) {
   1459         result = cnx->egl.eglSignalSyncKHR(
   1460                 dp->disp.dpy, sync, mode);
   1461     }
   1462     return result;
   1463 }
   1464 
   1465 EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync,
   1466         EGLint flags, EGLTimeKHR timeout)
   1467 {
   1468     clearError();
   1469 
   1470     const egl_display_ptr dp = validate_display(dpy);
   1471     if (!dp) return EGL_FALSE;
   1472 
   1473     EGLBoolean result = EGL_FALSE;
   1474     egl_connection_t* const cnx = &gEGLImpl;
   1475     if (cnx->dso && cnx->egl.eglClientWaitSyncKHR) {
   1476         result = cnx->egl.eglClientWaitSyncKHR(
   1477                 dp->disp.dpy, sync, flags, timeout);
   1478     }
   1479     return result;
   1480 }
   1481 
   1482 EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync,
   1483         EGLint attribute, EGLint *value)
   1484 {
   1485     clearError();
   1486 
   1487     const egl_display_ptr dp = validate_display(dpy);
   1488     if (!dp) return EGL_FALSE;
   1489 
   1490     EGLBoolean result = EGL_FALSE;
   1491     egl_connection_t* const cnx = &gEGLImpl;
   1492     if (cnx->dso && cnx->egl.eglGetSyncAttribKHR) {
   1493         result = cnx->egl.eglGetSyncAttribKHR(
   1494                 dp->disp.dpy, sync, attribute, value);
   1495     }
   1496     return result;
   1497 }
   1498 
   1499 // ----------------------------------------------------------------------------
   1500 // EGL_EGLEXT_VERSION 15
   1501 // ----------------------------------------------------------------------------
   1502 
   1503 EGLint eglWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags) {
   1504     clearError();
   1505     const egl_display_ptr dp = validate_display(dpy);
   1506     if (!dp) return EGL_FALSE;
   1507     EGLint result = EGL_FALSE;
   1508     egl_connection_t* const cnx = &gEGLImpl;
   1509     if (cnx->dso && cnx->egl.eglWaitSyncKHR) {
   1510         result = cnx->egl.eglWaitSyncKHR(dp->disp.dpy, sync, flags);
   1511     }
   1512     return result;
   1513 }
   1514 
   1515 // ----------------------------------------------------------------------------
   1516 // ANDROID extensions
   1517 // ----------------------------------------------------------------------------
   1518 
   1519 EGLint eglDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSyncKHR sync)
   1520 {
   1521     clearError();
   1522 
   1523     const egl_display_ptr dp = validate_display(dpy);
   1524     if (!dp) return EGL_NO_NATIVE_FENCE_FD_ANDROID;
   1525 
   1526     EGLint result = EGL_NO_NATIVE_FENCE_FD_ANDROID;
   1527     egl_connection_t* const cnx = &gEGLImpl;
   1528     if (cnx->dso && cnx->egl.eglDupNativeFenceFDANDROID) {
   1529         result = cnx->egl.eglDupNativeFenceFDANDROID(dp->disp.dpy, sync);
   1530     }
   1531     return result;
   1532 }
   1533 
   1534 EGLBoolean eglPresentationTimeANDROID(EGLDisplay dpy, EGLSurface surface,
   1535         EGLnsecsANDROID time)
   1536 {
   1537     clearError();
   1538 
   1539     const egl_display_ptr dp = validate_display(dpy);
   1540     if (!dp) {
   1541         return EGL_FALSE;
   1542     }
   1543 
   1544     SurfaceRef _s(dp.get(), surface);
   1545     if (!_s.get()) {
   1546         setError(EGL_BAD_SURFACE, EGL_FALSE);
   1547         return EGL_FALSE;
   1548     }
   1549 
   1550     egl_surface_t const * const s = get_surface(surface);
   1551     native_window_set_buffers_timestamp(s->win.get(), time);
   1552 
   1553     return EGL_TRUE;
   1554 }
   1555 
   1556 // ----------------------------------------------------------------------------
   1557 // NVIDIA extensions
   1558 // ----------------------------------------------------------------------------
   1559 EGLuint64NV eglGetSystemTimeFrequencyNV()
   1560 {
   1561     clearError();
   1562 
   1563     if (egl_init_drivers() == EGL_FALSE) {
   1564         return setError(EGL_BAD_PARAMETER, EGL_FALSE);
   1565     }
   1566 
   1567     EGLuint64NV ret = 0;
   1568     egl_connection_t* const cnx = &gEGLImpl;
   1569 
   1570     if (cnx->dso && cnx->egl.eglGetSystemTimeFrequencyNV) {
   1571         return cnx->egl.eglGetSystemTimeFrequencyNV();
   1572     }
   1573 
   1574     return setErrorQuiet(EGL_BAD_DISPLAY, 0);
   1575 }
   1576 
   1577 EGLuint64NV eglGetSystemTimeNV()
   1578 {
   1579     clearError();
   1580 
   1581     if (egl_init_drivers() == EGL_FALSE) {
   1582         return setError(EGL_BAD_PARAMETER, EGL_FALSE);
   1583     }
   1584 
   1585     EGLuint64NV ret = 0;
   1586     egl_connection_t* const cnx = &gEGLImpl;
   1587 
   1588     if (cnx->dso && cnx->egl.eglGetSystemTimeNV) {
   1589         return cnx->egl.eglGetSystemTimeNV();
   1590     }
   1591 
   1592     return setErrorQuiet(EGL_BAD_DISPLAY, 0);
   1593 }
   1594