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