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