Home | History | Annotate | Download | only in main
      1 /**************************************************************************
      2  *
      3  * Copyright 2008 VMware, Inc.
      4  * Copyright 2009-2010 Chia-I Wu <olvaffe (at) gmail.com>
      5  * Copyright 2010-2011 LunarG, Inc.
      6  * All Rights Reserved.
      7  *
      8  * Permission is hereby granted, free of charge, to any person obtaining a
      9  * copy of this software and associated documentation files (the
     10  * "Software"), to deal in the Software without restriction, including
     11  * without limitation the rights to use, copy, modify, merge, publish,
     12  * distribute, sub license, and/or sell copies of the Software, and to
     13  * permit persons to whom the Software is furnished to do so, subject to
     14  * the following conditions:
     15  *
     16  * The above copyright notice and this permission notice (including the
     17  * next paragraph) shall be included in all copies or substantial portions
     18  * of the Software.
     19  *
     20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     21  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     22  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     23  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     24  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     25  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     26  * DEALINGS IN THE SOFTWARE.
     27  *
     28  **************************************************************************/
     29 
     30 
     31 /**
     32  * Public EGL API entrypoints
     33  *
     34  * Generally, we use the EGLDisplay parameter as a key to lookup the
     35  * appropriate device driver handle, then jump though the driver's
     36  * dispatch table to handle the function.
     37  *
     38  * That allows us the option of supporting multiple, simultaneous,
     39  * heterogeneous hardware devices in the future.
     40  *
     41  * The EGLDisplay, EGLConfig, EGLContext and EGLSurface types are
     42  * opaque handles. Internal objects are linked to a display to
     43  * create the handles.
     44  *
     45  * For each public API entry point, the opaque handles are looked up
     46  * before being dispatched to the drivers.  When it fails to look up
     47  * a handle, one of
     48  *
     49  * EGL_BAD_DISPLAY
     50  * EGL_BAD_CONFIG
     51  * EGL_BAD_CONTEXT
     52  * EGL_BAD_SURFACE
     53  * EGL_BAD_SCREEN_MESA
     54  * EGL_BAD_MODE_MESA
     55  *
     56  * is generated and the driver function is not called. An
     57  * uninitialized EGLDisplay has no driver associated with it. When
     58  * such display is detected,
     59  *
     60  * EGL_NOT_INITIALIZED
     61  *
     62  * is generated.
     63  *
     64  * Some of the entry points use current display, context, or surface
     65  * implicitly.  For such entry points, the implicit objects are also
     66  * checked before calling the driver function.  Other than the
     67  * errors listed above,
     68  *
     69  * EGL_BAD_CURRENT_SURFACE
     70  *
     71  * may also be generated.
     72  *
     73  * Notes on naming conventions:
     74  *
     75  * eglFooBar    - public EGL function
     76  * EGL_FOO_BAR  - public EGL token
     77  * EGLDatatype  - public EGL datatype
     78  *
     79  * _eglFooBar   - private EGL function
     80  * _EGLDatatype - private EGL datatype, typedef'd struct
     81  * _egl_struct  - private EGL struct, non-typedef'd
     82  *
     83  */
     84 
     85 
     86 #include <stdio.h>
     87 #include <stdlib.h>
     88 #include <string.h>
     89 #include "c99_compat.h"
     90 #include "c11/threads.h"
     91 #include "GL/mesa_glinterop.h"
     92 #include "eglcompiler.h"
     93 
     94 #include "eglglobals.h"
     95 #include "eglcontext.h"
     96 #include "egldisplay.h"
     97 #include "egltypedefs.h"
     98 #include "eglcurrent.h"
     99 #include "egldriver.h"
    100 #include "eglsurface.h"
    101 #include "eglconfig.h"
    102 #include "eglimage.h"
    103 #include "eglsync.h"
    104 
    105 
    106 /**
    107  * Macros to help return an API entrypoint.
    108  *
    109  * These macros will unlock the display and record the error code.
    110  */
    111 #define RETURN_EGL_ERROR(disp, err, ret)        \
    112    do {                                         \
    113       if (disp)                                 \
    114          _eglUnlockDisplay(disp);               \
    115       /* EGL error codes are non-zero */        \
    116       if (err)                                  \
    117          _eglError(err, __func__);              \
    118       return ret;                               \
    119    } while (0)
    120 
    121 #define RETURN_EGL_SUCCESS(disp, ret) \
    122    RETURN_EGL_ERROR(disp, EGL_SUCCESS, ret)
    123 
    124 /* record EGL_SUCCESS only when ret evaluates to true */
    125 #define RETURN_EGL_EVAL(disp, ret) \
    126    RETURN_EGL_ERROR(disp, (ret) ? EGL_SUCCESS : 0, ret)
    127 
    128 
    129 /*
    130  * A bunch of macros and checks to simplify error checking.
    131  */
    132 
    133 #define _EGL_CHECK_DISPLAY(disp, ret, drv)         \
    134    do {                                            \
    135       drv = _eglCheckDisplay(disp, __func__);      \
    136       if (!drv)                                    \
    137          RETURN_EGL_ERROR(disp, 0, ret);           \
    138    } while (0)
    139 
    140 #define _EGL_CHECK_OBJECT(disp, type, obj, ret, drv)      \
    141    do {                                                   \
    142       drv = _eglCheck ## type(disp, obj, __func__);       \
    143       if (!drv)                                           \
    144          RETURN_EGL_ERROR(disp, 0, ret);                  \
    145    } while (0)
    146 
    147 #define _EGL_CHECK_SURFACE(disp, surf, ret, drv) \
    148    _EGL_CHECK_OBJECT(disp, Surface, surf, ret, drv)
    149 
    150 #define _EGL_CHECK_CONTEXT(disp, context, ret, drv) \
    151    _EGL_CHECK_OBJECT(disp, Context, context, ret, drv)
    152 
    153 #define _EGL_CHECK_CONFIG(disp, conf, ret, drv) \
    154    _EGL_CHECK_OBJECT(disp, Config, conf, ret, drv)
    155 
    156 #define _EGL_CHECK_SYNC(disp, s, ret, drv) \
    157    _EGL_CHECK_OBJECT(disp, Sync, s, ret, drv)
    158 
    159 
    160 static inline _EGLDriver *
    161 _eglCheckDisplay(_EGLDisplay *disp, const char *msg)
    162 {
    163    if (!disp) {
    164       _eglError(EGL_BAD_DISPLAY, msg);
    165       return NULL;
    166    }
    167    if (!disp->Initialized) {
    168       _eglError(EGL_NOT_INITIALIZED, msg);
    169       return NULL;
    170    }
    171    return disp->Driver;
    172 }
    173 
    174 
    175 static inline _EGLDriver *
    176 _eglCheckSurface(_EGLDisplay *disp, _EGLSurface *surf, const char *msg)
    177 {
    178    _EGLDriver *drv = _eglCheckDisplay(disp, msg);
    179    if (!drv)
    180       return NULL;
    181    if (!surf) {
    182       _eglError(EGL_BAD_SURFACE, msg);
    183       return NULL;
    184    }
    185    return drv;
    186 }
    187 
    188 
    189 static inline _EGLDriver *
    190 _eglCheckContext(_EGLDisplay *disp, _EGLContext *context, const char *msg)
    191 {
    192    _EGLDriver *drv = _eglCheckDisplay(disp, msg);
    193    if (!drv)
    194       return NULL;
    195    if (!context) {
    196       _eglError(EGL_BAD_CONTEXT, msg);
    197       return NULL;
    198    }
    199    return drv;
    200 }
    201 
    202 
    203 static inline _EGLDriver *
    204 _eglCheckConfig(_EGLDisplay *disp, _EGLConfig *conf, const char *msg)
    205 {
    206    _EGLDriver *drv = _eglCheckDisplay(disp, msg);
    207    if (!drv)
    208       return NULL;
    209    if (!conf) {
    210       _eglError(EGL_BAD_CONFIG, msg);
    211       return NULL;
    212    }
    213    return drv;
    214 }
    215 
    216 
    217 static inline _EGLDriver *
    218 _eglCheckSync(_EGLDisplay *disp, _EGLSync *s, const char *msg)
    219 {
    220    _EGLDriver *drv = _eglCheckDisplay(disp, msg);
    221    if (!drv)
    222       return NULL;
    223    if (!s) {
    224       _eglError(EGL_BAD_PARAMETER, msg);
    225       return NULL;
    226    }
    227    return drv;
    228 }
    229 
    230 
    231 /**
    232  * Lookup and lock a display.
    233  */
    234 static inline _EGLDisplay *
    235 _eglLockDisplay(EGLDisplay display)
    236 {
    237    _EGLDisplay *dpy = _eglLookupDisplay(display);
    238    if (dpy)
    239       mtx_lock(&dpy->Mutex);
    240    return dpy;
    241 }
    242 
    243 
    244 /**
    245  * Unlock a display.
    246  */
    247 static inline void
    248 _eglUnlockDisplay(_EGLDisplay *dpy)
    249 {
    250    mtx_unlock(&dpy->Mutex);
    251 }
    252 
    253 static EGLBoolean
    254 _eglSetFuncName(const char *funcName, _EGLDisplay *disp, EGLenum objectType, _EGLResource *object)
    255 {
    256    _EGLThreadInfo *thr = _eglGetCurrentThread();
    257    if (!_eglIsCurrentThreadDummy()) {
    258       thr->CurrentFuncName = funcName;
    259       thr->CurrentObjectLabel = NULL;
    260 
    261       if (objectType == EGL_OBJECT_THREAD_KHR)
    262          thr->CurrentObjectLabel = thr->Label;
    263       else if (objectType == EGL_OBJECT_DISPLAY_KHR && disp)
    264          thr->CurrentObjectLabel = disp->Label;
    265       else if (object)
    266          thr->CurrentObjectLabel = object->Label;
    267 
    268       return EGL_TRUE;
    269    }
    270 
    271    _eglDebugReportFull(EGL_BAD_ALLOC, funcName, funcName,
    272 		       EGL_DEBUG_MSG_CRITICAL_KHR, NULL, NULL);
    273    return EGL_FALSE;
    274 }
    275 
    276 #define _EGL_FUNC_START(disp, objectType, object, ret) \
    277    do { \
    278       if (!_eglSetFuncName(__func__, disp, objectType, (_EGLResource *) object)) { \
    279          if (disp)                                 \
    280             _eglUnlockDisplay(disp);               \
    281          return ret; \
    282       } \
    283    } while(0)
    284 
    285 /**
    286  * Convert an attribute list from EGLint[] to EGLAttrib[].
    287  *
    288  * Return an EGL error code. The output parameter out_attrib_list is modified
    289  * only on success.
    290  */
    291 static EGLint
    292 _eglConvertIntsToAttribs(const EGLint *int_list, EGLAttrib **out_attrib_list)
    293 {
    294    size_t len = 0;
    295    EGLAttrib *attrib_list;
    296 
    297    if (int_list) {
    298       while (int_list[2*len] != EGL_NONE)
    299          ++len;
    300    }
    301 
    302    if (len == 0) {
    303       *out_attrib_list = NULL;
    304       return EGL_SUCCESS;
    305    }
    306 
    307    if (2*len + 1 > SIZE_MAX / sizeof(EGLAttrib))
    308       return EGL_BAD_ALLOC;
    309 
    310    attrib_list = malloc((2*len + 1) * sizeof(EGLAttrib));
    311    if (!attrib_list)
    312       return EGL_BAD_ALLOC;
    313 
    314    for (size_t i = 0; i < len; ++i) {
    315       attrib_list[2*i + 0] = int_list[2*i + 0];
    316       attrib_list[2*i + 1] = int_list[2*i + 1];
    317    }
    318 
    319    attrib_list[2*len] = EGL_NONE;
    320 
    321    *out_attrib_list = attrib_list;
    322    return EGL_SUCCESS;
    323 }
    324 
    325 
    326 static EGLint *
    327 _eglConvertAttribsToInt(const EGLAttrib *attr_list)
    328 {
    329    EGLint *int_attribs = NULL;
    330 
    331    /* Convert attributes from EGLAttrib[] to EGLint[] */
    332    if (attr_list) {
    333       int i, size = 0;
    334 
    335       while (attr_list[size] != EGL_NONE)
    336          size += 2;
    337 
    338       size += 1; /* add space for EGL_NONE */
    339 
    340       int_attribs = calloc(size, sizeof(int_attribs[0]));
    341       if (!int_attribs)
    342          return NULL;
    343 
    344       for (i = 0; i < size; i++)
    345          int_attribs[i] = attr_list[i];
    346    }
    347    return int_attribs;
    348 }
    349 
    350 
    351 /**
    352  * This is typically the first EGL function that an application calls.
    353  * It associates a private _EGLDisplay object to the native display.
    354  */
    355 EGLDisplay EGLAPIENTRY
    356 eglGetDisplay(EGLNativeDisplayType nativeDisplay)
    357 {
    358    _EGLPlatformType plat;
    359    _EGLDisplay *dpy;
    360    void *native_display_ptr;
    361 
    362    _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_NO_DISPLAY);
    363 
    364    STATIC_ASSERT(sizeof(void*) == sizeof(nativeDisplay));
    365    native_display_ptr = (void*) nativeDisplay;
    366 
    367    plat = _eglGetNativePlatform(native_display_ptr);
    368    dpy = _eglFindDisplay(plat, native_display_ptr);
    369    return _eglGetDisplayHandle(dpy);
    370 }
    371 
    372 static EGLDisplay
    373 _eglGetPlatformDisplayCommon(EGLenum platform, void *native_display,
    374 			     const EGLint *attrib_list)
    375 {
    376    _EGLDisplay *dpy;
    377 
    378    switch (platform) {
    379 #ifdef HAVE_X11_PLATFORM
    380    case EGL_PLATFORM_X11_EXT:
    381       dpy = _eglGetX11Display((Display*) native_display, attrib_list);
    382       break;
    383 #endif
    384 #ifdef HAVE_DRM_PLATFORM
    385    case EGL_PLATFORM_GBM_MESA:
    386       dpy = _eglGetGbmDisplay((struct gbm_device*) native_display,
    387                               attrib_list);
    388       break;
    389 #endif
    390 #ifdef HAVE_WAYLAND_PLATFORM
    391    case EGL_PLATFORM_WAYLAND_EXT:
    392       dpy = _eglGetWaylandDisplay((struct wl_display*) native_display,
    393                                   attrib_list);
    394       break;
    395 #endif
    396 #ifdef HAVE_SURFACELESS_PLATFORM
    397    case EGL_PLATFORM_SURFACELESS_MESA:
    398       dpy = _eglGetSurfacelessDisplay(native_display, attrib_list);
    399       break;
    400 #endif
    401    default:
    402       RETURN_EGL_ERROR(NULL, EGL_BAD_PARAMETER, NULL);
    403    }
    404 
    405    return _eglGetDisplayHandle(dpy);
    406 }
    407 
    408 static EGLDisplay EGLAPIENTRY
    409 eglGetPlatformDisplayEXT(EGLenum platform, void *native_display,
    410                          const EGLint *attrib_list)
    411 {
    412    _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_NO_DISPLAY);
    413    return _eglGetPlatformDisplayCommon(platform, native_display, attrib_list);
    414 }
    415 
    416 EGLDisplay EGLAPIENTRY
    417 eglGetPlatformDisplay(EGLenum platform, void *native_display,
    418                       const EGLAttrib *attrib_list)
    419 {
    420    EGLDisplay display;
    421    EGLint *int_attribs;
    422 
    423    _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_NO_DISPLAY);
    424 
    425    int_attribs = _eglConvertAttribsToInt(attrib_list);
    426    if (attrib_list && !int_attribs)
    427       RETURN_EGL_ERROR(NULL, EGL_BAD_ALLOC, NULL);
    428 
    429    display = _eglGetPlatformDisplayCommon(platform, native_display, int_attribs);
    430    free(int_attribs);
    431    return display;
    432 }
    433 
    434 /**
    435  * Copy the extension into the string and update the string pointer.
    436  */
    437 static EGLint
    438 _eglAppendExtension(char **str, const char *ext)
    439 {
    440    char *s = *str;
    441    size_t len = strlen(ext);
    442 
    443    if (s) {
    444       memcpy(s, ext, len);
    445       s[len++] = ' ';
    446       s[len] = '\0';
    447 
    448       *str += len;
    449    }
    450    else {
    451       len++;
    452    }
    453 
    454    return (EGLint) len;
    455 }
    456 
    457 /**
    458  * Examine the individual extension enable/disable flags and recompute
    459  * the driver's Extensions string.
    460  */
    461 static void
    462 _eglCreateExtensionsString(_EGLDisplay *dpy)
    463 {
    464 #define _EGL_CHECK_EXTENSION(ext)                                          \
    465    do {                                                                    \
    466       if (dpy->Extensions.ext) {                                           \
    467          _eglAppendExtension(&exts, "EGL_" #ext);                          \
    468          assert(exts <= dpy->ExtensionsString + _EGL_MAX_EXTENSIONS_LEN);  \
    469       }                                                                    \
    470    } while (0)
    471 
    472    char *exts = dpy->ExtensionsString;
    473 
    474    /* Please keep these sorted alphabetically. */
    475    _EGL_CHECK_EXTENSION(ANDROID_framebuffer_target);
    476    _EGL_CHECK_EXTENSION(ANDROID_image_native_buffer);
    477    _EGL_CHECK_EXTENSION(ANDROID_native_fence_sync);
    478    _EGL_CHECK_EXTENSION(ANDROID_recordable);
    479 
    480    _EGL_CHECK_EXTENSION(CHROMIUM_sync_control);
    481 
    482    _EGL_CHECK_EXTENSION(EXT_buffer_age);
    483    _EGL_CHECK_EXTENSION(EXT_create_context_robustness);
    484    _EGL_CHECK_EXTENSION(EXT_image_dma_buf_import);
    485    _EGL_CHECK_EXTENSION(EXT_swap_buffers_with_damage);
    486 
    487    _EGL_CHECK_EXTENSION(KHR_cl_event2);
    488    _EGL_CHECK_EXTENSION(KHR_config_attribs);
    489    _EGL_CHECK_EXTENSION(KHR_create_context);
    490    _EGL_CHECK_EXTENSION(KHR_fence_sync);
    491    _EGL_CHECK_EXTENSION(KHR_get_all_proc_addresses);
    492    _EGL_CHECK_EXTENSION(KHR_gl_colorspace);
    493    _EGL_CHECK_EXTENSION(KHR_gl_renderbuffer_image);
    494    _EGL_CHECK_EXTENSION(KHR_gl_texture_2D_image);
    495    _EGL_CHECK_EXTENSION(KHR_gl_texture_3D_image);
    496    _EGL_CHECK_EXTENSION(KHR_gl_texture_cubemap_image);
    497    if (dpy->Extensions.KHR_image_base && dpy->Extensions.KHR_image_pixmap)
    498       _eglAppendExtension(&exts, "EGL_KHR_image");
    499    _EGL_CHECK_EXTENSION(KHR_image_base);
    500    _EGL_CHECK_EXTENSION(KHR_image_pixmap);
    501    _EGL_CHECK_EXTENSION(KHR_no_config_context);
    502    _EGL_CHECK_EXTENSION(KHR_reusable_sync);
    503    _EGL_CHECK_EXTENSION(KHR_surfaceless_context);
    504    if (dpy->Extensions.EXT_swap_buffers_with_damage)
    505       _eglAppendExtension(&exts, "EGL_KHR_swap_buffers_with_damage");
    506    _EGL_CHECK_EXTENSION(KHR_wait_sync);
    507 
    508    if (dpy->Extensions.KHR_no_config_context)
    509       _eglAppendExtension(&exts, "EGL_MESA_configless_context");
    510    _EGL_CHECK_EXTENSION(MESA_drm_image);
    511    _EGL_CHECK_EXTENSION(MESA_image_dma_buf_export);
    512 
    513    _EGL_CHECK_EXTENSION(NOK_swap_region);
    514    _EGL_CHECK_EXTENSION(NOK_texture_from_pixmap);
    515 
    516    _EGL_CHECK_EXTENSION(NV_post_sub_buffer);
    517 
    518    _EGL_CHECK_EXTENSION(WL_bind_wayland_display);
    519    _EGL_CHECK_EXTENSION(WL_create_wayland_buffer_from_image);
    520 
    521 #undef _EGL_CHECK_EXTENSION
    522 }
    523 
    524 static void
    525 _eglCreateAPIsString(_EGLDisplay *dpy)
    526 {
    527    if (dpy->ClientAPIs & EGL_OPENGL_BIT)
    528       strcat(dpy->ClientAPIsString, "OpenGL ");
    529 
    530    if (dpy->ClientAPIs & EGL_OPENGL_ES_BIT ||
    531        dpy->ClientAPIs & EGL_OPENGL_ES2_BIT ||
    532        dpy->ClientAPIs & EGL_OPENGL_ES3_BIT_KHR) {
    533       strcat(dpy->ClientAPIsString, "OpenGL_ES ");
    534    }
    535 
    536    if (dpy->ClientAPIs & EGL_OPENVG_BIT)
    537       strcat(dpy->ClientAPIsString, "OpenVG ");
    538 
    539    assert(strlen(dpy->ClientAPIsString) < sizeof(dpy->ClientAPIsString));
    540 }
    541 
    542 static void
    543 _eglComputeVersion(_EGLDisplay *disp)
    544 {
    545    disp->Version = 14;
    546 
    547    if (disp->Extensions.KHR_fence_sync &&
    548        disp->Extensions.KHR_cl_event2 &&
    549        disp->Extensions.KHR_wait_sync &&
    550        disp->Extensions.KHR_image_base &&
    551        disp->Extensions.KHR_gl_texture_2D_image &&
    552        disp->Extensions.KHR_gl_texture_3D_image &&
    553        disp->Extensions.KHR_gl_texture_cubemap_image &&
    554        disp->Extensions.KHR_gl_renderbuffer_image &&
    555        disp->Extensions.KHR_create_context &&
    556        disp->Extensions.EXT_create_context_robustness &&
    557        disp->Extensions.KHR_get_all_proc_addresses &&
    558        disp->Extensions.KHR_gl_colorspace &&
    559        disp->Extensions.KHR_surfaceless_context)
    560       disp->Version = 15;
    561 }
    562 
    563 /**
    564  * This is typically the second EGL function that an application calls.
    565  * Here we load/initialize the actual hardware driver.
    566  */
    567 EGLBoolean EGLAPIENTRY
    568 eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
    569 {
    570    _EGLDisplay *disp = _eglLockDisplay(dpy);
    571 
    572    _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
    573 
    574    if (!disp)
    575       RETURN_EGL_ERROR(NULL, EGL_BAD_DISPLAY, EGL_FALSE);
    576 
    577    if (!disp->Initialized) {
    578       if (!_eglMatchDriver(disp, EGL_FALSE))
    579          RETURN_EGL_ERROR(disp, EGL_NOT_INITIALIZED, EGL_FALSE);
    580 
    581       /* limit to APIs supported by core */
    582       disp->ClientAPIs &= _EGL_API_ALL_BITS;
    583 
    584       /* EGL_KHR_get_all_proc_addresses is a corner-case extension. The spec
    585        * classifies it as an EGL display extension, though conceptually it's an
    586        * EGL client extension.
    587        *
    588        * From the EGL_KHR_get_all_proc_addresses spec:
    589        *
    590        *    The EGL implementation must expose the name
    591        *    EGL_KHR_client_get_all_proc_addresses if and only if it exposes
    592        *    EGL_KHR_get_all_proc_addresses and supports
    593        *    EGL_EXT_client_extensions.
    594        *
    595        * Mesa unconditionally exposes both client extensions mentioned above,
    596        * so the spec requires that each EGLDisplay unconditionally expose
    597        * EGL_KHR_get_all_proc_addresses also.
    598        */
    599       disp->Extensions.KHR_get_all_proc_addresses = EGL_TRUE;
    600 
    601       /* Extensions is used to provide EGL 1.3 functionality for 1.2 aware
    602        * programs. It is driver agnostic and handled in the main EGL code.
    603        */
    604       disp->Extensions.KHR_config_attribs = EGL_TRUE;
    605 
    606       _eglComputeVersion(disp);
    607       _eglCreateExtensionsString(disp);
    608       _eglCreateAPIsString(disp);
    609       snprintf(disp->VersionString, sizeof(disp->VersionString),
    610               "%d.%d (%s)", disp->Version / 10, disp->Version % 10,
    611               disp->Driver->Name);
    612    }
    613 
    614    /* Update applications version of major and minor if not NULL */
    615    if ((major != NULL) && (minor != NULL)) {
    616       *major = disp->Version / 10;
    617       *minor = disp->Version % 10;
    618    }
    619 
    620    RETURN_EGL_SUCCESS(disp, EGL_TRUE);
    621 }
    622 
    623 
    624 EGLBoolean EGLAPIENTRY
    625 eglTerminate(EGLDisplay dpy)
    626 {
    627    _EGLDisplay *disp = _eglLockDisplay(dpy);
    628 
    629    _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
    630 
    631    if (!disp)
    632       RETURN_EGL_ERROR(NULL, EGL_BAD_DISPLAY, EGL_FALSE);
    633 
    634    if (disp->Initialized) {
    635       _EGLDriver *drv = disp->Driver;
    636 
    637       drv->API.Terminate(drv, disp);
    638       /* do not reset disp->Driver */
    639       disp->ClientAPIsString[0] = 0;
    640       disp->Initialized = EGL_FALSE;
    641    }
    642 
    643    RETURN_EGL_SUCCESS(disp, EGL_TRUE);
    644 }
    645 
    646 
    647 const char * EGLAPIENTRY
    648 eglQueryString(EGLDisplay dpy, EGLint name)
    649 {
    650    _EGLDisplay *disp;
    651    _EGLDriver *drv;
    652 
    653    if (dpy == EGL_NO_DISPLAY && name == EGL_EXTENSIONS) {
    654       RETURN_EGL_SUCCESS(NULL, _eglGlobal.ClientExtensionString);
    655    }
    656 
    657    disp = _eglLockDisplay(dpy);
    658    _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, NULL);
    659    _EGL_CHECK_DISPLAY(disp, NULL, drv);
    660 
    661    switch (name) {
    662    case EGL_VENDOR:
    663       RETURN_EGL_SUCCESS(disp, _EGL_VENDOR_STRING);
    664    case EGL_VERSION:
    665       RETURN_EGL_SUCCESS(disp, disp->VersionString);
    666    case EGL_EXTENSIONS:
    667       RETURN_EGL_SUCCESS(disp, disp->ExtensionsString);
    668    case EGL_CLIENT_APIS:
    669       RETURN_EGL_SUCCESS(disp, disp->ClientAPIsString);
    670    default:
    671       RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, NULL);
    672    }
    673 }
    674 
    675 
    676 EGLBoolean EGLAPIENTRY
    677 eglGetConfigs(EGLDisplay dpy, EGLConfig *configs,
    678               EGLint config_size, EGLint *num_config)
    679 {
    680    _EGLDisplay *disp = _eglLockDisplay(dpy);
    681    _EGLDriver *drv;
    682    EGLBoolean ret;
    683 
    684    _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
    685 
    686    _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
    687    ret = drv->API.GetConfigs(drv, disp, configs, config_size, num_config);
    688 
    689    RETURN_EGL_EVAL(disp, ret);
    690 }
    691 
    692 
    693 EGLBoolean EGLAPIENTRY
    694 eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs,
    695                 EGLint config_size, EGLint *num_config)
    696 {
    697    _EGLDisplay *disp = _eglLockDisplay(dpy);
    698    _EGLDriver *drv;
    699    EGLBoolean ret;
    700 
    701    _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
    702 
    703    _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
    704    ret = drv->API.ChooseConfig(drv, disp, attrib_list, configs,
    705                                 config_size, num_config);
    706 
    707    RETURN_EGL_EVAL(disp, ret);
    708 }
    709 
    710 
    711 EGLBoolean EGLAPIENTRY
    712 eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
    713                    EGLint attribute, EGLint *value)
    714 {
    715    _EGLDisplay *disp = _eglLockDisplay(dpy);
    716    _EGLConfig *conf = _eglLookupConfig(config, disp);
    717    _EGLDriver *drv;
    718    EGLBoolean ret;
    719 
    720    _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
    721 
    722    _EGL_CHECK_CONFIG(disp, conf, EGL_FALSE, drv);
    723    ret = drv->API.GetConfigAttrib(drv, disp, conf, attribute, value);
    724 
    725    RETURN_EGL_EVAL(disp, ret);
    726 }
    727 
    728 
    729 EGLContext EGLAPIENTRY
    730 eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_list,
    731                  const EGLint *attrib_list)
    732 {
    733    _EGLDisplay *disp = _eglLockDisplay(dpy);
    734    _EGLConfig *conf = _eglLookupConfig(config, disp);
    735    _EGLContext *share = _eglLookupContext(share_list, disp);
    736    _EGLDriver *drv;
    737    _EGLContext *context;
    738    EGLContext ret;
    739 
    740    _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_CONTEXT);
    741 
    742    _EGL_CHECK_DISPLAY(disp, EGL_NO_CONTEXT, drv);
    743 
    744    if (config != EGL_NO_CONFIG_KHR)
    745       _EGL_CHECK_CONFIG(disp, conf, EGL_NO_CONTEXT, drv);
    746    else if (!disp->Extensions.KHR_no_config_context)
    747       RETURN_EGL_ERROR(disp, EGL_BAD_CONFIG, EGL_NO_CONTEXT);
    748 
    749    if (!share && share_list != EGL_NO_CONTEXT)
    750       RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_NO_CONTEXT);
    751 
    752    context = drv->API.CreateContext(drv, disp, conf, share, attrib_list);
    753    ret = (context) ? _eglLinkContext(context) : EGL_NO_CONTEXT;
    754 
    755    RETURN_EGL_EVAL(disp, ret);
    756 }
    757 
    758 
    759 EGLBoolean EGLAPIENTRY
    760 eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
    761 {
    762    _EGLDisplay *disp = _eglLockDisplay(dpy);
    763    _EGLContext *context = _eglLookupContext(ctx, disp);
    764    _EGLDriver *drv;
    765    EGLBoolean ret;
    766 
    767    _EGL_FUNC_START(disp, EGL_OBJECT_CONTEXT_KHR, context, EGL_FALSE);
    768 
    769    _EGL_CHECK_CONTEXT(disp, context, EGL_FALSE, drv);
    770    _eglUnlinkContext(context);
    771    ret = drv->API.DestroyContext(drv, disp, context);
    772 
    773    RETURN_EGL_EVAL(disp, ret);
    774 }
    775 
    776 
    777 EGLBoolean EGLAPIENTRY
    778 eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read,
    779                EGLContext ctx)
    780 {
    781    _EGLDisplay *disp = _eglLockDisplay(dpy);
    782    _EGLContext *context = _eglLookupContext(ctx, disp);
    783    _EGLSurface *draw_surf = _eglLookupSurface(draw, disp);
    784    _EGLSurface *read_surf = _eglLookupSurface(read, disp);
    785    _EGLDriver *drv;
    786    EGLBoolean ret;
    787 
    788    _EGL_FUNC_START(disp, EGL_OBJECT_CONTEXT_KHR, context, EGL_FALSE);
    789 
    790    if (!disp)
    791       RETURN_EGL_ERROR(disp, EGL_BAD_DISPLAY, EGL_FALSE);
    792    drv = disp->Driver;
    793 
    794    /* display is allowed to be uninitialized under certain condition */
    795    if (!disp->Initialized) {
    796       if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE ||
    797           ctx != EGL_NO_CONTEXT)
    798          RETURN_EGL_ERROR(disp, EGL_BAD_DISPLAY, EGL_FALSE);
    799    }
    800    if (!drv)
    801       RETURN_EGL_SUCCESS(disp, EGL_TRUE);
    802 
    803    if (!context && ctx != EGL_NO_CONTEXT)
    804       RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_FALSE);
    805    if (!draw_surf || !read_surf) {
    806       /* From the EGL 1.4 (20130211) spec:
    807        *
    808        *    To release the current context without assigning a new one, set ctx
    809        *    to EGL_NO_CONTEXT and set draw and read to EGL_NO_SURFACE.
    810        */
    811       if (!disp->Extensions.KHR_surfaceless_context && ctx != EGL_NO_CONTEXT)
    812          RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
    813 
    814       if ((!draw_surf && draw != EGL_NO_SURFACE) ||
    815           (!read_surf && read != EGL_NO_SURFACE))
    816          RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
    817       if (draw_surf || read_surf)
    818          RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_FALSE);
    819    }
    820 
    821    ret = drv->API.MakeCurrent(drv, disp, draw_surf, read_surf, context);
    822 
    823    RETURN_EGL_EVAL(disp, ret);
    824 }
    825 
    826 
    827 EGLBoolean EGLAPIENTRY
    828 eglQueryContext(EGLDisplay dpy, EGLContext ctx,
    829                 EGLint attribute, EGLint *value)
    830 {
    831    _EGLDisplay *disp = _eglLockDisplay(dpy);
    832    _EGLContext *context = _eglLookupContext(ctx, disp);
    833    _EGLDriver *drv;
    834    EGLBoolean ret;
    835 
    836    _EGL_FUNC_START(disp, EGL_OBJECT_CONTEXT_KHR, context, EGL_FALSE);
    837 
    838    _EGL_CHECK_CONTEXT(disp, context, EGL_FALSE, drv);
    839    ret = drv->API.QueryContext(drv, disp, context, attribute, value);
    840 
    841    RETURN_EGL_EVAL(disp, ret);
    842 }
    843 
    844 
    845 static EGLSurface
    846 _eglCreateWindowSurfaceCommon(_EGLDisplay *disp, EGLConfig config,
    847                               void *native_window, const EGLint *attrib_list)
    848 {
    849    _EGLConfig *conf = _eglLookupConfig(config, disp);
    850    _EGLDriver *drv;
    851    _EGLSurface *surf;
    852    EGLSurface ret;
    853 
    854 
    855    if (native_window == NULL)
    856       RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
    857 
    858 #ifdef HAVE_SURFACELESS_PLATFORM
    859    if (disp && disp->Platform == _EGL_PLATFORM_SURFACELESS) {
    860       /* From the EGL_MESA_platform_surfaceless spec (v1):
    861        *
    862        *    eglCreatePlatformWindowSurface fails when called with a <display>
    863        *    that belongs to the surfaceless platform. It returns
    864        *    EGL_NO_SURFACE and generates EGL_BAD_NATIVE_WINDOW. The
    865        *    justification for this unconditional failure is that the
    866        *    surfaceless platform has no native windows, and therefore the
    867        *    <native_window> parameter is always invalid.
    868        *
    869        * This check must occur before checking the EGLConfig, which emits
    870        * EGL_BAD_CONFIG.
    871        */
    872       RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
    873    }
    874 #endif
    875 
    876    _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv);
    877 
    878    if ((conf->SurfaceType & EGL_WINDOW_BIT) == 0)
    879       RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_NO_SURFACE);
    880 
    881    surf = drv->API.CreateWindowSurface(drv, disp, conf, native_window,
    882                                        attrib_list);
    883    ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE;
    884 
    885    RETURN_EGL_EVAL(disp, ret);
    886 }
    887 
    888 
    889 EGLSurface EGLAPIENTRY
    890 eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config,
    891                        EGLNativeWindowType window, const EGLint *attrib_list)
    892 {
    893    _EGLDisplay *disp = _eglLockDisplay(dpy);
    894 
    895    _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE);
    896    STATIC_ASSERT(sizeof(void*) == sizeof(window));
    897    return _eglCreateWindowSurfaceCommon(disp, config, (void*) window,
    898                                         attrib_list);
    899 }
    900 
    901 static void *
    902 _fixupNativeWindow(_EGLDisplay *disp, void *native_window)
    903 {
    904 #ifdef HAVE_X11_PLATFORM
    905    if (disp->Platform == _EGL_PLATFORM_X11 && native_window != NULL) {
    906       /* The `native_window` parameter for the X11 platform differs between
    907        * eglCreateWindowSurface() and eglCreatePlatformPixmapSurfaceEXT(). In
    908        * eglCreateWindowSurface(), the type of `native_window` is an Xlib
    909        * `Window`. In eglCreatePlatformWindowSurfaceEXT(), the type is
    910        * `Window*`.  Convert `Window*` to `Window` because that's what
    911        * dri2_x11_create_window_surface() expects.
    912        */
    913       return (void *)(* (Window*) native_window);
    914    }
    915 #endif
    916    return native_window;
    917 }
    918 
    919 static EGLSurface EGLAPIENTRY
    920 eglCreatePlatformWindowSurfaceEXT(EGLDisplay dpy, EGLConfig config,
    921                                   void *native_window,
    922                                   const EGLint *attrib_list)
    923 {
    924    _EGLDisplay *disp = _eglLockDisplay(dpy);
    925 
    926    native_window = _fixupNativeWindow(disp, native_window);
    927 
    928    _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE);
    929    return _eglCreateWindowSurfaceCommon(disp, config, native_window,
    930                                         attrib_list);
    931 }
    932 
    933 
    934 EGLSurface EGLAPIENTRY
    935 eglCreatePlatformWindowSurface(EGLDisplay dpy, EGLConfig config,
    936                                void *native_window,
    937                                const EGLAttrib *attrib_list)
    938 {
    939    _EGLDisplay *disp = _eglLockDisplay(dpy);
    940    EGLSurface surface;
    941    EGLint *int_attribs;
    942 
    943    _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE);
    944 
    945    int_attribs = _eglConvertAttribsToInt(attrib_list);
    946    if (attrib_list && !int_attribs)
    947       RETURN_EGL_ERROR(disp, EGL_BAD_ALLOC, EGL_NO_SURFACE);
    948 
    949    native_window = _fixupNativeWindow(disp, native_window);
    950    surface = _eglCreateWindowSurfaceCommon(disp, config, native_window,
    951                                            int_attribs);
    952    free(int_attribs);
    953    return surface;
    954 }
    955 
    956 static void *
    957 _fixupNativePixmap(_EGLDisplay *disp, void *native_pixmap)
    958 {
    959 #ifdef HAVE_X11_PLATFORM
    960       /* The `native_pixmap` parameter for the X11 platform differs between
    961        * eglCreatePixmapSurface() and eglCreatePlatformPixmapSurfaceEXT(). In
    962        * eglCreatePixmapSurface(), the type of `native_pixmap` is an Xlib
    963        * `Pixmap`. In eglCreatePlatformPixmapSurfaceEXT(), the type is
    964        * `Pixmap*`.  Convert `Pixmap*` to `Pixmap` because that's what
    965        * dri2_x11_create_pixmap_surface() expects.
    966        */
    967    if (disp->Platform == _EGL_PLATFORM_X11 && native_pixmap != NULL)
    968       return (void *)(* (Pixmap*) native_pixmap);
    969 #endif
    970    return native_pixmap;
    971 }
    972 
    973 static EGLSurface
    974 _eglCreatePixmapSurfaceCommon(_EGLDisplay *disp, EGLConfig config,
    975                               void *native_pixmap, const EGLint *attrib_list)
    976 {
    977    _EGLConfig *conf = _eglLookupConfig(config, disp);
    978    _EGLDriver *drv;
    979    _EGLSurface *surf;
    980    EGLSurface ret;
    981 
    982 #if HAVE_SURFACELESS_PLATFORM
    983    if (disp && disp->Platform == _EGL_PLATFORM_SURFACELESS) {
    984       /* From the EGL_MESA_platform_surfaceless spec (v1):
    985        *
    986        *   [Like eglCreatePlatformWindowSurface,] eglCreatePlatformPixmapSurface
    987        *   also fails when called with a <display> that belongs to the
    988        *   surfaceless platform.  It returns EGL_NO_SURFACE and generates
    989        *   EGL_BAD_NATIVE_PIXMAP.
    990        *
    991        * This check must occur before checking the EGLConfig, which emits
    992        * EGL_BAD_CONFIG.
    993        */
    994       RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_PIXMAP, EGL_NO_SURFACE);
    995    }
    996 #endif
    997 
    998    _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv);
    999 
   1000    if ((conf->SurfaceType & EGL_PIXMAP_BIT) == 0)
   1001       RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_NO_SURFACE);
   1002 
   1003    surf = drv->API.CreatePixmapSurface(drv, disp, conf, native_pixmap,
   1004                                        attrib_list);
   1005    ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE;
   1006 
   1007    RETURN_EGL_EVAL(disp, ret);
   1008 }
   1009 
   1010 
   1011 EGLSurface EGLAPIENTRY
   1012 eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config,
   1013                        EGLNativePixmapType pixmap, const EGLint *attrib_list)
   1014 {
   1015    _EGLDisplay *disp = _eglLockDisplay(dpy);
   1016 
   1017    _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE);
   1018    STATIC_ASSERT(sizeof(void*) == sizeof(pixmap));
   1019    return _eglCreatePixmapSurfaceCommon(disp, config, (void*) pixmap,
   1020                                          attrib_list);
   1021 }
   1022 
   1023 static EGLSurface EGLAPIENTRY
   1024 eglCreatePlatformPixmapSurfaceEXT(EGLDisplay dpy, EGLConfig config,
   1025                                    void *native_pixmap,
   1026                                    const EGLint *attrib_list)
   1027 {
   1028    _EGLDisplay *disp = _eglLockDisplay(dpy);
   1029 
   1030    _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE);
   1031    native_pixmap = _fixupNativePixmap(disp, native_pixmap);
   1032    return _eglCreatePixmapSurfaceCommon(disp, config, native_pixmap,
   1033                                         attrib_list);
   1034 }
   1035 
   1036 
   1037 EGLSurface EGLAPIENTRY
   1038 eglCreatePlatformPixmapSurface(EGLDisplay dpy, EGLConfig config,
   1039                                void *native_pixmap,
   1040                                const EGLAttrib *attrib_list)
   1041 {
   1042    _EGLDisplay *disp = _eglLockDisplay(dpy);
   1043    EGLSurface surface;
   1044    EGLint *int_attribs;
   1045 
   1046    _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE);
   1047 
   1048    int_attribs = _eglConvertAttribsToInt(attrib_list);
   1049    if (attrib_list && !int_attribs)
   1050       RETURN_EGL_ERROR(disp, EGL_BAD_ALLOC, EGL_NO_SURFACE);
   1051 
   1052    native_pixmap = _fixupNativePixmap(disp, native_pixmap);
   1053    surface = _eglCreatePixmapSurfaceCommon(disp, config, native_pixmap,
   1054                                            int_attribs);
   1055    free(int_attribs);
   1056    return surface;
   1057 }
   1058 
   1059 
   1060 EGLSurface EGLAPIENTRY
   1061 eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config,
   1062                         const EGLint *attrib_list)
   1063 {
   1064    _EGLDisplay *disp = _eglLockDisplay(dpy);
   1065    _EGLConfig *conf = _eglLookupConfig(config, disp);
   1066    _EGLDriver *drv;
   1067    _EGLSurface *surf;
   1068    EGLSurface ret;
   1069 
   1070    _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE);
   1071    _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv);
   1072 
   1073    if ((conf->SurfaceType & EGL_PBUFFER_BIT) == 0)
   1074       RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_NO_SURFACE);
   1075 
   1076    surf = drv->API.CreatePbufferSurface(drv, disp, conf, attrib_list);
   1077    ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE;
   1078 
   1079    RETURN_EGL_EVAL(disp, ret);
   1080 }
   1081 
   1082 
   1083 EGLBoolean EGLAPIENTRY
   1084 eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
   1085 {
   1086    _EGLDisplay *disp = _eglLockDisplay(dpy);
   1087    _EGLSurface *surf = _eglLookupSurface(surface, disp);
   1088    _EGLDriver *drv;
   1089    EGLBoolean ret;
   1090 
   1091    _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
   1092    _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
   1093    _eglUnlinkSurface(surf);
   1094    ret = drv->API.DestroySurface(drv, disp, surf);
   1095 
   1096    RETURN_EGL_EVAL(disp, ret);
   1097 }
   1098 
   1099 EGLBoolean EGLAPIENTRY
   1100 eglQuerySurface(EGLDisplay dpy, EGLSurface surface,
   1101                 EGLint attribute, EGLint *value)
   1102 {
   1103    _EGLDisplay *disp = _eglLockDisplay(dpy);
   1104    _EGLSurface *surf = _eglLookupSurface(surface, disp);
   1105    _EGLDriver *drv;
   1106    EGLBoolean ret;
   1107 
   1108    _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
   1109    _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
   1110    ret = drv->API.QuerySurface(drv, disp, surf, attribute, value);
   1111 
   1112    RETURN_EGL_EVAL(disp, ret);
   1113 }
   1114 
   1115 EGLBoolean EGLAPIENTRY
   1116 eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface,
   1117                  EGLint attribute, EGLint value)
   1118 {
   1119    _EGLDisplay *disp = _eglLockDisplay(dpy);
   1120    _EGLSurface *surf = _eglLookupSurface(surface, disp);
   1121    _EGLDriver *drv;
   1122    EGLBoolean ret;
   1123 
   1124    _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
   1125    _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
   1126    ret = drv->API.SurfaceAttrib(drv, disp, surf, attribute, value);
   1127 
   1128    RETURN_EGL_EVAL(disp, ret);
   1129 }
   1130 
   1131 
   1132 EGLBoolean EGLAPIENTRY
   1133 eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
   1134 {
   1135    _EGLDisplay *disp = _eglLockDisplay(dpy);
   1136    _EGLSurface *surf = _eglLookupSurface(surface, disp);
   1137    _EGLDriver *drv;
   1138    EGLBoolean ret;
   1139 
   1140    _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
   1141    _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
   1142    ret = drv->API.BindTexImage(drv, disp, surf, buffer);
   1143 
   1144    RETURN_EGL_EVAL(disp, ret);
   1145 }
   1146 
   1147 
   1148 EGLBoolean EGLAPIENTRY
   1149 eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
   1150 {
   1151    _EGLDisplay *disp = _eglLockDisplay(dpy);
   1152    _EGLSurface *surf = _eglLookupSurface(surface, disp);
   1153    _EGLDriver *drv;
   1154    EGLBoolean ret;
   1155 
   1156    _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
   1157    _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
   1158    ret = drv->API.ReleaseTexImage(drv, disp, surf, buffer);
   1159 
   1160    RETURN_EGL_EVAL(disp, ret);
   1161 }
   1162 
   1163 
   1164 EGLBoolean EGLAPIENTRY
   1165 eglSwapInterval(EGLDisplay dpy, EGLint interval)
   1166 {
   1167    _EGLDisplay *disp = _eglLockDisplay(dpy);
   1168    _EGLContext *ctx = _eglGetCurrentContext();
   1169    _EGLSurface *surf = ctx ? ctx->DrawSurface : NULL;
   1170    _EGLDriver *drv;
   1171    EGLBoolean ret;
   1172 
   1173    _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
   1174    _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
   1175 
   1176    if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
   1177        ctx->Resource.Display != disp)
   1178       RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_FALSE);
   1179 
   1180    if (_eglGetSurfaceHandle(surf) == EGL_NO_SURFACE)
   1181       RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
   1182 
   1183    ret = drv->API.SwapInterval(drv, disp, surf, interval);
   1184 
   1185    RETURN_EGL_EVAL(disp, ret);
   1186 }
   1187 
   1188 
   1189 EGLBoolean EGLAPIENTRY
   1190 eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
   1191 {
   1192    _EGLContext *ctx = _eglGetCurrentContext();
   1193    _EGLDisplay *disp = _eglLockDisplay(dpy);
   1194    _EGLSurface *surf = _eglLookupSurface(surface, disp);
   1195    _EGLDriver *drv;
   1196    EGLBoolean ret;
   1197 
   1198    _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
   1199    _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
   1200 
   1201    /* surface must be bound to current context in EGL 1.4 */
   1202    #ifndef _EGL_BUILT_IN_DRIVER_HAIKU
   1203    if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
   1204        surf != ctx->DrawSurface)
   1205       RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
   1206    #endif
   1207 
   1208    ret = drv->API.SwapBuffers(drv, disp, surf);
   1209 
   1210    RETURN_EGL_EVAL(disp, ret);
   1211 }
   1212 
   1213 
   1214 static EGLBoolean
   1215 _eglSwapBuffersWithDamageCommon(_EGLDisplay *disp, _EGLSurface *surf,
   1216                                 EGLint *rects, EGLint n_rects)
   1217 {
   1218    _EGLContext *ctx = _eglGetCurrentContext();
   1219    _EGLDriver *drv;
   1220    EGLBoolean ret;
   1221 
   1222    _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
   1223 
   1224    /* surface must be bound to current context in EGL 1.4 */
   1225    if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
   1226        surf != ctx->DrawSurface)
   1227       RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
   1228 
   1229    if ((n_rects > 0 && rects == NULL) || n_rects < 0)
   1230       RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
   1231 
   1232    ret = drv->API.SwapBuffersWithDamageEXT(drv, disp, surf, rects, n_rects);
   1233 
   1234    RETURN_EGL_EVAL(disp, ret);
   1235 }
   1236 
   1237 static EGLBoolean EGLAPIENTRY
   1238 eglSwapBuffersWithDamageEXT(EGLDisplay dpy, EGLSurface surface,
   1239                             EGLint *rects, EGLint n_rects)
   1240 {
   1241    _EGLDisplay *disp = _eglLockDisplay(dpy);
   1242    _EGLSurface *surf = _eglLookupSurface(surface, disp);
   1243    _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
   1244    return _eglSwapBuffersWithDamageCommon(disp, surf, rects, n_rects);
   1245 }
   1246 
   1247 static EGLBoolean EGLAPIENTRY
   1248 eglSwapBuffersWithDamageKHR(EGLDisplay dpy, EGLSurface surface,
   1249                             EGLint *rects, EGLint n_rects)
   1250 {
   1251    _EGLDisplay *disp = _eglLockDisplay(dpy);
   1252    _EGLSurface *surf = _eglLookupSurface(surface, disp);
   1253    _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
   1254    return _eglSwapBuffersWithDamageCommon(disp, surf, rects, n_rects);
   1255 }
   1256 
   1257 EGLBoolean EGLAPIENTRY
   1258 eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)
   1259 {
   1260    _EGLDisplay *disp = _eglLockDisplay(dpy);
   1261    _EGLSurface *surf = _eglLookupSurface(surface, disp);
   1262    _EGLDriver *drv;
   1263    EGLBoolean ret;
   1264    void *native_pixmap_ptr;
   1265 
   1266    _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
   1267    STATIC_ASSERT(sizeof(void*) == sizeof(target));
   1268    native_pixmap_ptr = (void*) target;
   1269 
   1270    _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
   1271    if (disp->Platform != _eglGetNativePlatform(disp->PlatformDisplay))
   1272       RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_PIXMAP, EGL_FALSE);
   1273    ret = drv->API.CopyBuffers(drv, disp, surf, native_pixmap_ptr);
   1274 
   1275    RETURN_EGL_EVAL(disp, ret);
   1276 }
   1277 
   1278 
   1279 static EGLBoolean
   1280 _eglWaitClientCommon(void)
   1281 {
   1282    _EGLContext *ctx = _eglGetCurrentContext();
   1283    _EGLDisplay *disp;
   1284    _EGLDriver *drv;
   1285    EGLBoolean ret;
   1286 
   1287    if (!ctx)
   1288       RETURN_EGL_SUCCESS(NULL, EGL_TRUE);
   1289 
   1290    disp = ctx->Resource.Display;
   1291    mtx_lock(&disp->Mutex);
   1292 
   1293    /* let bad current context imply bad current surface */
   1294    if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
   1295        _eglGetSurfaceHandle(ctx->DrawSurface) == EGL_NO_SURFACE)
   1296       RETURN_EGL_ERROR(disp, EGL_BAD_CURRENT_SURFACE, EGL_FALSE);
   1297 
   1298    /* a valid current context implies an initialized current display */
   1299    assert(disp->Initialized);
   1300    drv = disp->Driver;
   1301    ret = drv->API.WaitClient(drv, disp, ctx);
   1302 
   1303    RETURN_EGL_EVAL(disp, ret);
   1304 }
   1305 
   1306 EGLBoolean EGLAPIENTRY
   1307 eglWaitClient(void)
   1308 {
   1309    _EGL_FUNC_START(NULL, EGL_OBJECT_CONTEXT_KHR, _eglGetCurrentContext(), EGL_FALSE);
   1310    return _eglWaitClientCommon();
   1311 }
   1312 
   1313 EGLBoolean EGLAPIENTRY
   1314 eglWaitGL(void)
   1315 {
   1316    /* Since we only support OpenGL and GLES, eglWaitGL is equivalent to eglWaitClient. */
   1317    _EGL_FUNC_START(NULL, EGL_OBJECT_CONTEXT_KHR, _eglGetCurrentContext(), EGL_FALSE);
   1318    return _eglWaitClientCommon();
   1319 }
   1320 
   1321 
   1322 EGLBoolean EGLAPIENTRY
   1323 eglWaitNative(EGLint engine)
   1324 {
   1325    _EGLContext *ctx = _eglGetCurrentContext();
   1326    _EGLDisplay *disp;
   1327    _EGLDriver *drv;
   1328    EGLBoolean ret;
   1329 
   1330    if (!ctx)
   1331       RETURN_EGL_SUCCESS(NULL, EGL_TRUE);
   1332 
   1333    _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_FALSE);
   1334 
   1335    disp = ctx->Resource.Display;
   1336    mtx_lock(&disp->Mutex);
   1337 
   1338    /* let bad current context imply bad current surface */
   1339    if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
   1340        _eglGetSurfaceHandle(ctx->DrawSurface) == EGL_NO_SURFACE)
   1341       RETURN_EGL_ERROR(disp, EGL_BAD_CURRENT_SURFACE, EGL_FALSE);
   1342 
   1343    /* a valid current context implies an initialized current display */
   1344    assert(disp->Initialized);
   1345    drv = disp->Driver;
   1346    ret = drv->API.WaitNative(drv, disp, engine);
   1347 
   1348    RETURN_EGL_EVAL(disp, ret);
   1349 }
   1350 
   1351 
   1352 EGLDisplay EGLAPIENTRY
   1353 eglGetCurrentDisplay(void)
   1354 {
   1355    _EGLContext *ctx = _eglGetCurrentContext();
   1356    EGLDisplay ret;
   1357 
   1358    ret = (ctx) ? _eglGetDisplayHandle(ctx->Resource.Display) : EGL_NO_DISPLAY;
   1359 
   1360    RETURN_EGL_SUCCESS(NULL, ret);
   1361 }
   1362 
   1363 
   1364 EGLContext EGLAPIENTRY
   1365 eglGetCurrentContext(void)
   1366 {
   1367    _EGLContext *ctx = _eglGetCurrentContext();
   1368    EGLContext ret;
   1369 
   1370    ret = _eglGetContextHandle(ctx);
   1371 
   1372    RETURN_EGL_SUCCESS(NULL, ret);
   1373 }
   1374 
   1375 
   1376 EGLSurface EGLAPIENTRY
   1377 eglGetCurrentSurface(EGLint readdraw)
   1378 {
   1379    _EGLContext *ctx = _eglGetCurrentContext();
   1380    EGLint err = EGL_SUCCESS;
   1381    _EGLSurface *surf;
   1382    EGLSurface ret;
   1383 
   1384    _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_NO_SURFACE);
   1385 
   1386    if (!ctx)
   1387       RETURN_EGL_SUCCESS(NULL, EGL_NO_SURFACE);
   1388 
   1389    switch (readdraw) {
   1390    case EGL_DRAW:
   1391       surf = ctx->DrawSurface;
   1392       break;
   1393    case EGL_READ:
   1394       surf = ctx->ReadSurface;
   1395       break;
   1396    default:
   1397       surf = NULL;
   1398       err = EGL_BAD_PARAMETER;
   1399       break;
   1400    }
   1401 
   1402    ret = _eglGetSurfaceHandle(surf);
   1403 
   1404    RETURN_EGL_ERROR(NULL, err, ret);
   1405 }
   1406 
   1407 
   1408 EGLint EGLAPIENTRY
   1409 eglGetError(void)
   1410 {
   1411    _EGLThreadInfo *t = _eglGetCurrentThread();
   1412    EGLint e = t->LastError;
   1413    if (!_eglIsCurrentThreadDummy())
   1414       t->LastError = EGL_SUCCESS;
   1415    return e;
   1416 }
   1417 
   1418 
   1419 /**
   1420  ** EGL 1.2
   1421  **/
   1422 
   1423 /**
   1424  * Specify the client API to use for subsequent calls including:
   1425  *  eglCreateContext()
   1426  *  eglGetCurrentContext()
   1427  *  eglGetCurrentDisplay()
   1428  *  eglGetCurrentSurface()
   1429  *  eglMakeCurrent(when the ctx parameter is EGL NO CONTEXT)
   1430  *  eglWaitClient()
   1431  *  eglWaitNative()
   1432  * See section 3.7 "Rendering Context" in the EGL specification for details.
   1433  */
   1434 EGLBoolean EGLAPIENTRY
   1435 eglBindAPI(EGLenum api)
   1436 {
   1437    _EGLThreadInfo *t;
   1438 
   1439    _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_FALSE);
   1440 
   1441    t = _eglGetCurrentThread();
   1442    if (_eglIsCurrentThreadDummy())
   1443       RETURN_EGL_ERROR(NULL, EGL_BAD_ALLOC, EGL_FALSE);
   1444 
   1445    if (!_eglIsApiValid(api))
   1446       RETURN_EGL_ERROR(NULL, EGL_BAD_PARAMETER, EGL_FALSE);
   1447 
   1448    t->CurrentAPI = api;
   1449 
   1450    RETURN_EGL_SUCCESS(NULL, EGL_TRUE);
   1451 }
   1452 
   1453 
   1454 /**
   1455  * Return the last value set with eglBindAPI().
   1456  */
   1457 EGLenum EGLAPIENTRY
   1458 eglQueryAPI(void)
   1459 {
   1460    _EGLThreadInfo *t = _eglGetCurrentThread();
   1461    EGLenum ret;
   1462 
   1463    /* returns one of EGL_OPENGL_API, EGL_OPENGL_ES_API or EGL_OPENVG_API */
   1464    ret = t->CurrentAPI;
   1465 
   1466    RETURN_EGL_SUCCESS(NULL, ret);
   1467 }
   1468 
   1469 
   1470 EGLSurface EGLAPIENTRY
   1471 eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype,
   1472                                  EGLClientBuffer buffer, EGLConfig config,
   1473                                  const EGLint *attrib_list)
   1474 {
   1475    _EGLDisplay *disp = _eglLockDisplay(dpy);
   1476    _EGLConfig *conf = _eglLookupConfig(config, disp);
   1477    _EGLDriver *drv;
   1478    _EGLSurface *surf;
   1479    EGLSurface ret;
   1480 
   1481    _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE);
   1482 
   1483    _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv);
   1484 
   1485    surf = drv->API.CreatePbufferFromClientBuffer(drv, disp, buftype, buffer,
   1486                                                  conf, attrib_list);
   1487    ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE;
   1488 
   1489    RETURN_EGL_EVAL(disp, ret);
   1490 }
   1491 
   1492 
   1493 EGLBoolean EGLAPIENTRY
   1494 eglReleaseThread(void)
   1495 {
   1496    /* unbind current contexts */
   1497    if (!_eglIsCurrentThreadDummy()) {
   1498       _EGLThreadInfo *t = _eglGetCurrentThread();
   1499       _EGLContext *ctx = t->CurrentContext;
   1500 
   1501       _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_FALSE);
   1502 
   1503       if (ctx) {
   1504          _EGLDisplay *disp = ctx->Resource.Display;
   1505          _EGLDriver *drv;
   1506 
   1507          mtx_lock(&disp->Mutex);
   1508          drv = disp->Driver;
   1509          (void) drv->API.MakeCurrent(drv, disp, NULL, NULL, NULL);
   1510          mtx_unlock(&disp->Mutex);
   1511       }
   1512    }
   1513 
   1514    _eglDestroyCurrentThread();
   1515 
   1516    RETURN_EGL_SUCCESS(NULL, EGL_TRUE);
   1517 }
   1518 
   1519 
   1520 static EGLImage
   1521 _eglCreateImageCommon(_EGLDisplay *disp, EGLContext ctx, EGLenum target,
   1522                   EGLClientBuffer buffer, const EGLint *attr_list)
   1523 {
   1524    _EGLContext *context = _eglLookupContext(ctx, disp);
   1525    _EGLDriver *drv;
   1526    _EGLImage *img;
   1527    EGLImage ret;
   1528 
   1529    _EGL_CHECK_DISPLAY(disp, EGL_NO_IMAGE_KHR, drv);
   1530    if (!disp->Extensions.KHR_image_base)
   1531       RETURN_EGL_EVAL(disp, EGL_NO_IMAGE_KHR);
   1532    if (!context && ctx != EGL_NO_CONTEXT)
   1533       RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
   1534    /* "If <target> is EGL_LINUX_DMA_BUF_EXT, <dpy> must be a valid display,
   1535     *  <ctx> must be EGL_NO_CONTEXT..."
   1536     */
   1537    if (ctx != EGL_NO_CONTEXT && target == EGL_LINUX_DMA_BUF_EXT)
   1538       RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
   1539 
   1540    img = drv->API.CreateImageKHR(drv,
   1541          disp, context, target, buffer, attr_list);
   1542    ret = (img) ? _eglLinkImage(img) : EGL_NO_IMAGE_KHR;
   1543 
   1544    RETURN_EGL_EVAL(disp, ret);
   1545 }
   1546 
   1547 static EGLImage EGLAPIENTRY
   1548 eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
   1549                   EGLClientBuffer buffer, const EGLint *attr_list)
   1550 {
   1551    _EGLDisplay *disp = _eglLockDisplay(dpy);
   1552    _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_IMAGE_KHR);
   1553    return _eglCreateImageCommon(disp, ctx, target, buffer, attr_list);
   1554 }
   1555 
   1556 
   1557 EGLImage EGLAPIENTRY
   1558 eglCreateImage(EGLDisplay dpy, EGLContext ctx, EGLenum target,
   1559                EGLClientBuffer buffer, const EGLAttrib *attr_list)
   1560 {
   1561    _EGLDisplay *disp = _eglLockDisplay(dpy);
   1562    EGLImage image;
   1563    EGLint *int_attribs;
   1564 
   1565    _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_IMAGE_KHR);
   1566 
   1567    int_attribs = _eglConvertAttribsToInt(attr_list);
   1568    if (attr_list && !int_attribs)
   1569       RETURN_EGL_ERROR(disp, EGL_BAD_ALLOC, EGL_NO_IMAGE);
   1570 
   1571    image = _eglCreateImageCommon(disp, ctx, target, buffer, int_attribs);
   1572    free(int_attribs);
   1573    return image;
   1574 }
   1575 
   1576 
   1577 EGLBoolean EGLAPIENTRY
   1578 eglDestroyImage(EGLDisplay dpy, EGLImage image)
   1579 {
   1580    _EGLDisplay *disp = _eglLockDisplay(dpy);
   1581    _EGLImage *img = _eglLookupImage(image, disp);
   1582    _EGLDriver *drv;
   1583    EGLBoolean ret;
   1584 
   1585    _EGL_FUNC_START(disp, EGL_OBJECT_IMAGE_KHR, img, EGL_FALSE);
   1586 
   1587    _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
   1588    if (!disp->Extensions.KHR_image_base)
   1589       RETURN_EGL_EVAL(disp, EGL_FALSE);
   1590    if (!img)
   1591       RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
   1592 
   1593    _eglUnlinkImage(img);
   1594    ret = drv->API.DestroyImageKHR(drv, disp, img);
   1595 
   1596    RETURN_EGL_EVAL(disp, ret);
   1597 }
   1598 
   1599 
   1600 static EGLSync
   1601 _eglCreateSync(_EGLDisplay *disp, EGLenum type, const EGLAttrib *attrib_list,
   1602                EGLBoolean orig_is_EGLAttrib,
   1603                EGLenum invalid_type_error)
   1604 {
   1605    _EGLContext *ctx = _eglGetCurrentContext();
   1606    _EGLDriver *drv;
   1607    _EGLSync *sync;
   1608    EGLSync ret;
   1609 
   1610    _EGL_CHECK_DISPLAY(disp, EGL_NO_SYNC_KHR, drv);
   1611 
   1612    if (!disp->Extensions.KHR_cl_event2 && orig_is_EGLAttrib) {
   1613       /* There exist two EGLAttrib variants of eglCreateSync*:
   1614        * eglCreateSync64KHR which requires EGL_KHR_cl_event2, and eglCreateSync
   1615        * which requires EGL 1.5. Here we use the presence of EGL_KHR_cl_event2
   1616        * support as a proxy for EGL 1.5 support, even though that's not
   1617        * entirely correct (though _eglComputeVersion does the same).
   1618        *
   1619        * The EGL spec provides no guidance on how to handle unsupported
   1620        * functions. EGL_BAD_MATCH seems reasonable.
   1621        */
   1622       RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_NO_SYNC_KHR);
   1623    }
   1624 
   1625    /* If type is EGL_SYNC_FENCE and no context is current for the bound API
   1626     * (i.e., eglGetCurrentContext returns EGL_NO_CONTEXT ), an EGL_BAD_MATCH
   1627     * error is generated.
   1628     */
   1629    if (!ctx &&
   1630        (type == EGL_SYNC_FENCE_KHR || type == EGL_SYNC_NATIVE_FENCE_ANDROID))
   1631       RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_NO_SYNC_KHR);
   1632 
   1633    /* return an error if the client API doesn't support GL_OES_EGL_sync */
   1634    if (ctx && (ctx->Resource.Display != disp ||
   1635        ctx->ClientAPI != EGL_OPENGL_ES_API))
   1636       RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_NO_SYNC_KHR);
   1637 
   1638    switch (type) {
   1639    case EGL_SYNC_FENCE_KHR:
   1640       if (!disp->Extensions.KHR_fence_sync)
   1641          RETURN_EGL_ERROR(disp, invalid_type_error, EGL_NO_SYNC_KHR);
   1642       break;
   1643    case EGL_SYNC_REUSABLE_KHR:
   1644       if (!disp->Extensions.KHR_reusable_sync)
   1645          RETURN_EGL_ERROR(disp, invalid_type_error, EGL_NO_SYNC_KHR);
   1646       break;
   1647    case EGL_SYNC_CL_EVENT_KHR:
   1648       if (!disp->Extensions.KHR_cl_event2)
   1649          RETURN_EGL_ERROR(disp, invalid_type_error, EGL_NO_SYNC_KHR);
   1650       break;
   1651    case EGL_SYNC_NATIVE_FENCE_ANDROID:
   1652       if (!disp->Extensions.ANDROID_native_fence_sync)
   1653          RETURN_EGL_ERROR(disp, invalid_type_error, EGL_NO_SYNC_KHR);
   1654       break;
   1655    default:
   1656       RETURN_EGL_ERROR(disp, invalid_type_error, EGL_NO_SYNC_KHR);
   1657    }
   1658 
   1659    sync = drv->API.CreateSyncKHR(drv, disp, type, attrib_list);
   1660    ret = (sync) ? _eglLinkSync(sync) : EGL_NO_SYNC_KHR;
   1661 
   1662    RETURN_EGL_EVAL(disp, ret);
   1663 }
   1664 
   1665 
   1666 static EGLSync EGLAPIENTRY
   1667 eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *int_list)
   1668 {
   1669    _EGLDisplay *disp = _eglLockDisplay(dpy);
   1670    _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
   1671 
   1672    EGLSync sync;
   1673    EGLAttrib *attrib_list;
   1674    EGLint err;
   1675 
   1676    if (sizeof(int_list[0]) == sizeof(attrib_list[0])) {
   1677       attrib_list = (EGLAttrib *) int_list;
   1678    } else {
   1679       err = _eglConvertIntsToAttribs(int_list, &attrib_list);
   1680       if (err != EGL_SUCCESS)
   1681          RETURN_EGL_ERROR(disp, err, EGL_NO_SYNC);
   1682    }
   1683 
   1684    sync = _eglCreateSync(disp, type, attrib_list, EGL_FALSE,
   1685                          EGL_BAD_ATTRIBUTE);
   1686 
   1687    if (sizeof(int_list[0]) != sizeof(attrib_list[0]))
   1688       free(attrib_list);
   1689 
   1690    /* Don't double-unlock the display. _eglCreateSync already unlocked it. */
   1691    return sync;
   1692 }
   1693 
   1694 
   1695 static EGLSync EGLAPIENTRY
   1696 eglCreateSync64KHR(EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list)
   1697 {
   1698    _EGLDisplay *disp = _eglLockDisplay(dpy);
   1699    _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
   1700    return _eglCreateSync(disp, type, attrib_list, EGL_TRUE,
   1701                          EGL_BAD_ATTRIBUTE);
   1702 }
   1703 
   1704 
   1705 EGLSync EGLAPIENTRY
   1706 eglCreateSync(EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list)
   1707 {
   1708    _EGLDisplay *disp = _eglLockDisplay(dpy);
   1709    _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
   1710    return _eglCreateSync(disp, type, attrib_list, EGL_TRUE,
   1711                          EGL_BAD_PARAMETER);
   1712 }
   1713 
   1714 
   1715 EGLBoolean EGLAPIENTRY
   1716 eglDestroySync(EGLDisplay dpy, EGLSync sync)
   1717 {
   1718    _EGLDisplay *disp = _eglLockDisplay(dpy);
   1719    _EGLSync *s = _eglLookupSync(sync, disp);
   1720    _EGLDriver *drv;
   1721    EGLBoolean ret;
   1722 
   1723    _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
   1724 
   1725    _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
   1726    assert(disp->Extensions.KHR_reusable_sync ||
   1727           disp->Extensions.KHR_fence_sync ||
   1728           disp->Extensions.ANDROID_native_fence_sync);
   1729 
   1730    _eglUnlinkSync(s);
   1731    ret = drv->API.DestroySyncKHR(drv, disp, s);
   1732 
   1733    RETURN_EGL_EVAL(disp, ret);
   1734 }
   1735 
   1736 
   1737 EGLint EGLAPIENTRY
   1738 eglClientWaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout)
   1739 {
   1740    _EGLDisplay *disp = _eglLockDisplay(dpy);
   1741    _EGLSync *s = _eglLookupSync(sync, disp);
   1742    _EGLDriver *drv;
   1743    EGLint ret;
   1744 
   1745    _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
   1746 
   1747    _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
   1748    assert(disp->Extensions.KHR_reusable_sync ||
   1749           disp->Extensions.KHR_fence_sync ||
   1750           disp->Extensions.ANDROID_native_fence_sync);
   1751 
   1752    if (s->SyncStatus == EGL_SIGNALED_KHR)
   1753       RETURN_EGL_EVAL(disp, EGL_CONDITION_SATISFIED_KHR);
   1754 
   1755    /* if sync type is EGL_SYNC_REUSABLE_KHR, dpy should be
   1756     * unlocked here to allow other threads also to be able to
   1757     * go into waiting state.
   1758     */
   1759 
   1760    if (s->Type == EGL_SYNC_REUSABLE_KHR)
   1761       _eglUnlockDisplay(dpy);
   1762 
   1763    ret = drv->API.ClientWaitSyncKHR(drv, disp, s, flags, timeout);
   1764 
   1765    /*
   1766     * 'disp' is already unlocked for reusable sync type,
   1767     * so passing 'NULL' to bypass unlocking display.
   1768     */
   1769    if (s->Type == EGL_SYNC_REUSABLE_KHR)
   1770       RETURN_EGL_EVAL(NULL, ret);
   1771    else
   1772       RETURN_EGL_EVAL(disp, ret);
   1773 }
   1774 
   1775 
   1776 static EGLint
   1777 _eglWaitSyncCommon(_EGLDisplay *disp, _EGLSync *s, EGLint flags)
   1778 {
   1779    _EGLContext *ctx = _eglGetCurrentContext();
   1780    _EGLDriver *drv;
   1781    EGLint ret;
   1782 
   1783    _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
   1784    assert(disp->Extensions.KHR_wait_sync);
   1785 
   1786    /* return an error if the client API doesn't support GL_OES_EGL_sync */
   1787    if (ctx == EGL_NO_CONTEXT || ctx->ClientAPI != EGL_OPENGL_ES_API)
   1788       RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_FALSE);
   1789 
   1790    /* the API doesn't allow any flags yet */
   1791    if (flags != 0)
   1792       RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
   1793 
   1794    ret = drv->API.WaitSyncKHR(drv, disp, s);
   1795 
   1796    RETURN_EGL_EVAL(disp, ret);
   1797 }
   1798 
   1799 static EGLint EGLAPIENTRY
   1800 eglWaitSyncKHR(EGLDisplay dpy, EGLSync sync, EGLint flags)
   1801 {
   1802    _EGLDisplay *disp = _eglLockDisplay(dpy);
   1803    _EGLSync *s = _eglLookupSync(sync, disp);
   1804    _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
   1805    return _eglWaitSyncCommon(disp, s, flags);
   1806 }
   1807 
   1808 
   1809 EGLBoolean EGLAPIENTRY
   1810 eglWaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags)
   1811 {
   1812    /* The KHR version returns EGLint, while the core version returns
   1813     * EGLBoolean. In both cases, the return values can only be EGL_FALSE and
   1814     * EGL_TRUE.
   1815     */
   1816    _EGLDisplay *disp = _eglLockDisplay(dpy);
   1817    _EGLSync *s = _eglLookupSync(sync, disp);
   1818    _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
   1819    return _eglWaitSyncCommon(disp, s, flags);
   1820 }
   1821 
   1822 
   1823 static EGLBoolean EGLAPIENTRY
   1824 eglSignalSyncKHR(EGLDisplay dpy, EGLSync sync, EGLenum mode)
   1825 {
   1826    _EGLDisplay *disp = _eglLockDisplay(dpy);
   1827    _EGLSync *s = _eglLookupSync(sync, disp);
   1828    _EGLDriver *drv;
   1829    EGLBoolean ret;
   1830 
   1831    _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
   1832 
   1833    _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
   1834    assert(disp->Extensions.KHR_reusable_sync);
   1835    ret = drv->API.SignalSyncKHR(drv, disp, s, mode);
   1836 
   1837    RETURN_EGL_EVAL(disp, ret);
   1838 }
   1839 
   1840 
   1841 static EGLBoolean
   1842 _eglGetSyncAttribCommon(_EGLDisplay *disp, _EGLSync *s, EGLint attribute, EGLAttrib *value)
   1843 {
   1844    _EGLDriver *drv;
   1845    EGLBoolean ret;
   1846 
   1847    _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
   1848    assert(disp->Extensions.KHR_reusable_sync ||
   1849           disp->Extensions.KHR_fence_sync ||
   1850           disp->Extensions.ANDROID_native_fence_sync);
   1851    ret = drv->API.GetSyncAttrib(drv, disp, s, attribute, value);
   1852 
   1853    RETURN_EGL_EVAL(disp, ret);
   1854 }
   1855 
   1856 EGLBoolean EGLAPIENTRY
   1857 eglGetSyncAttrib(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib *value)
   1858 {
   1859    _EGLDisplay *disp = _eglLockDisplay(dpy);
   1860    _EGLSync *s = _eglLookupSync(sync, disp);
   1861    _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
   1862    return _eglGetSyncAttribCommon(disp, s, attribute, value);
   1863 }
   1864 
   1865 
   1866 static EGLBoolean EGLAPIENTRY
   1867 eglGetSyncAttribKHR(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLint *value)
   1868 {
   1869    _EGLDisplay *disp = _eglLockDisplay(dpy);
   1870    _EGLSync *s = _eglLookupSync(sync, disp);
   1871    EGLAttrib attrib;
   1872    EGLBoolean result;
   1873 
   1874    _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
   1875 
   1876    if (!value)
   1877       RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
   1878 
   1879    attrib = *value;
   1880    result = _eglGetSyncAttribCommon(disp, s, attribute, &attrib);
   1881 
   1882    /* The EGL_KHR_fence_sync spec says this about eglGetSyncAttribKHR:
   1883     *
   1884     *    If any error occurs, <*value> is not modified.
   1885     */
   1886    if (result == EGL_FALSE)
   1887       return result;
   1888 
   1889    *value = attrib;
   1890    return result;
   1891 }
   1892 
   1893 static EGLint EGLAPIENTRY
   1894 eglDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSync sync)
   1895 {
   1896    _EGLDisplay *disp = _eglLockDisplay(dpy);
   1897    _EGLSync *s = _eglLookupSync(sync, disp);
   1898    _EGLDriver *drv;
   1899    EGLBoolean ret;
   1900 
   1901    _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
   1902 
   1903    /* the spec doesn't seem to specify what happens if the fence
   1904     * type is not EGL_SYNC_NATIVE_FENCE_ANDROID, but this seems
   1905     * sensible:
   1906     */
   1907    if (!(s && (s->Type == EGL_SYNC_NATIVE_FENCE_ANDROID)))
   1908       RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_NO_NATIVE_FENCE_FD_ANDROID);
   1909 
   1910    _EGL_CHECK_SYNC(disp, s, EGL_NO_NATIVE_FENCE_FD_ANDROID, drv);
   1911    assert(disp->Extensions.ANDROID_native_fence_sync);
   1912    ret = drv->API.DupNativeFenceFDANDROID(drv, disp, s);
   1913 
   1914    RETURN_EGL_EVAL(disp, ret);
   1915 }
   1916 
   1917 static EGLBoolean EGLAPIENTRY
   1918 eglSwapBuffersRegionNOK(EGLDisplay dpy, EGLSurface surface,
   1919 			EGLint numRects, const EGLint *rects)
   1920 {
   1921    _EGLContext *ctx = _eglGetCurrentContext();
   1922    _EGLDisplay *disp = _eglLockDisplay(dpy);
   1923    _EGLSurface *surf = _eglLookupSurface(surface, disp);
   1924    _EGLDriver *drv;
   1925    EGLBoolean ret;
   1926 
   1927    _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
   1928 
   1929    _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
   1930 
   1931    if (!disp->Extensions.NOK_swap_region)
   1932       RETURN_EGL_EVAL(disp, EGL_FALSE);
   1933 
   1934    /* surface must be bound to current context in EGL 1.4 */
   1935    if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
   1936        surf != ctx->DrawSurface)
   1937       RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
   1938 
   1939    ret = drv->API.SwapBuffersRegionNOK(drv, disp, surf, numRects, rects);
   1940 
   1941    RETURN_EGL_EVAL(disp, ret);
   1942 }
   1943 
   1944 
   1945 static EGLImage EGLAPIENTRY
   1946 eglCreateDRMImageMESA(EGLDisplay dpy, const EGLint *attr_list)
   1947 {
   1948    _EGLDisplay *disp = _eglLockDisplay(dpy);
   1949    _EGLDriver *drv;
   1950    _EGLImage *img;
   1951    EGLImage ret;
   1952 
   1953    _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
   1954 
   1955    _EGL_CHECK_DISPLAY(disp, EGL_NO_IMAGE_KHR, drv);
   1956    if (!disp->Extensions.MESA_drm_image)
   1957       RETURN_EGL_EVAL(disp, EGL_NO_IMAGE_KHR);
   1958 
   1959    img = drv->API.CreateDRMImageMESA(drv, disp, attr_list);
   1960    ret = (img) ? _eglLinkImage(img) : EGL_NO_IMAGE_KHR;
   1961 
   1962    RETURN_EGL_EVAL(disp, ret);
   1963 }
   1964 
   1965 static EGLBoolean EGLAPIENTRY
   1966 eglExportDRMImageMESA(EGLDisplay dpy, EGLImage image,
   1967 		      EGLint *name, EGLint *handle, EGLint *stride)
   1968 {
   1969    _EGLDisplay *disp = _eglLockDisplay(dpy);
   1970    _EGLImage *img = _eglLookupImage(image, disp);
   1971    _EGLDriver *drv;
   1972    EGLBoolean ret;
   1973 
   1974    _EGL_FUNC_START(disp, EGL_OBJECT_IMAGE_KHR, img, EGL_FALSE);
   1975 
   1976    _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
   1977    assert(disp->Extensions.MESA_drm_image);
   1978 
   1979    if (!img)
   1980       RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
   1981 
   1982    ret = drv->API.ExportDRMImageMESA(drv, disp, img, name, handle, stride);
   1983 
   1984    RETURN_EGL_EVAL(disp, ret);
   1985 }
   1986 
   1987 
   1988 struct wl_display;
   1989 
   1990 static EGLBoolean EGLAPIENTRY
   1991 eglBindWaylandDisplayWL(EGLDisplay dpy, struct wl_display *display)
   1992 {
   1993    _EGLDisplay *disp = _eglLockDisplay(dpy);
   1994    _EGLDriver *drv;
   1995    EGLBoolean ret;
   1996 
   1997    _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
   1998 
   1999    _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
   2000    assert(disp->Extensions.WL_bind_wayland_display);
   2001 
   2002    if (!display)
   2003       RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
   2004 
   2005    ret = drv->API.BindWaylandDisplayWL(drv, disp, display);
   2006 
   2007    RETURN_EGL_EVAL(disp, ret);
   2008 }
   2009 
   2010 static EGLBoolean EGLAPIENTRY
   2011 eglUnbindWaylandDisplayWL(EGLDisplay dpy, struct wl_display *display)
   2012 {
   2013    _EGLDisplay *disp = _eglLockDisplay(dpy);
   2014    _EGLDriver *drv;
   2015    EGLBoolean ret;
   2016 
   2017    _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
   2018 
   2019    _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
   2020    assert(disp->Extensions.WL_bind_wayland_display);
   2021 
   2022    if (!display)
   2023       RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
   2024 
   2025    ret = drv->API.UnbindWaylandDisplayWL(drv, disp, display);
   2026 
   2027    RETURN_EGL_EVAL(disp, ret);
   2028 }
   2029 
   2030 static EGLBoolean EGLAPIENTRY
   2031 eglQueryWaylandBufferWL(EGLDisplay dpy, struct wl_resource *buffer,
   2032                         EGLint attribute, EGLint *value)
   2033 {
   2034    _EGLDisplay *disp = _eglLockDisplay(dpy);
   2035    _EGLDriver *drv;
   2036    EGLBoolean ret;
   2037 
   2038    _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
   2039 
   2040    _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
   2041    assert(disp->Extensions.WL_bind_wayland_display);
   2042 
   2043    if (!buffer)
   2044       RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
   2045 
   2046    ret = drv->API.QueryWaylandBufferWL(drv, disp, buffer, attribute, value);
   2047 
   2048    RETURN_EGL_EVAL(disp, ret);
   2049 }
   2050 
   2051 
   2052 static struct wl_buffer * EGLAPIENTRY
   2053 eglCreateWaylandBufferFromImageWL(EGLDisplay dpy, EGLImage image)
   2054 {
   2055    _EGLDisplay *disp = _eglLockDisplay(dpy);
   2056    _EGLImage *img;
   2057    _EGLDriver *drv;
   2058    struct wl_buffer *ret;
   2059 
   2060    _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
   2061 
   2062    _EGL_CHECK_DISPLAY(disp, NULL, drv);
   2063    assert(disp->Extensions.WL_create_wayland_buffer_from_image);
   2064 
   2065    img = _eglLookupImage(image, disp);
   2066 
   2067    if (!img)
   2068       RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, NULL);
   2069 
   2070    ret = drv->API.CreateWaylandBufferFromImageWL(drv, disp, img);
   2071 
   2072    RETURN_EGL_EVAL(disp, ret);
   2073 }
   2074 
   2075 static EGLBoolean EGLAPIENTRY
   2076 eglPostSubBufferNV(EGLDisplay dpy, EGLSurface surface,
   2077                    EGLint x, EGLint y, EGLint width, EGLint height)
   2078 {
   2079    _EGLDisplay *disp = _eglLockDisplay(dpy);
   2080    _EGLSurface *surf = _eglLookupSurface(surface, disp);
   2081    _EGLDriver *drv;
   2082    EGLBoolean ret;
   2083 
   2084    _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
   2085 
   2086    _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
   2087 
   2088    if (!disp->Extensions.NV_post_sub_buffer)
   2089       RETURN_EGL_EVAL(disp, EGL_FALSE);
   2090 
   2091    ret = drv->API.PostSubBufferNV(drv, disp, surf, x, y, width, height);
   2092 
   2093    RETURN_EGL_EVAL(disp, ret);
   2094 }
   2095 
   2096 static EGLBoolean EGLAPIENTRY
   2097 eglGetSyncValuesCHROMIUM(EGLDisplay display, EGLSurface surface,
   2098                          EGLuint64KHR *ust, EGLuint64KHR *msc,
   2099                          EGLuint64KHR *sbc)
   2100 {
   2101    _EGLDisplay *disp = _eglLockDisplay(display);
   2102    _EGLSurface *surf = _eglLookupSurface(surface, disp);
   2103    _EGLDriver *drv;
   2104    EGLBoolean ret;
   2105 
   2106    _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
   2107 
   2108    _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
   2109    if (!disp->Extensions.CHROMIUM_sync_control)
   2110       RETURN_EGL_EVAL(disp, EGL_FALSE);
   2111 
   2112    if (!ust || !msc || !sbc)
   2113       RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
   2114 
   2115    ret = drv->API.GetSyncValuesCHROMIUM(disp, surf, ust, msc, sbc);
   2116 
   2117    RETURN_EGL_EVAL(disp, ret);
   2118 }
   2119 
   2120 static EGLBoolean EGLAPIENTRY
   2121 eglExportDMABUFImageQueryMESA(EGLDisplay dpy, EGLImage image,
   2122                               EGLint *fourcc, EGLint *nplanes,
   2123                               EGLuint64KHR *modifiers)
   2124 {
   2125    _EGLDisplay *disp = _eglLockDisplay(dpy);
   2126    _EGLImage *img = _eglLookupImage(image, disp);
   2127    _EGLDriver *drv;
   2128    EGLBoolean ret;
   2129 
   2130    _EGL_FUNC_START(disp, EGL_OBJECT_IMAGE_KHR, img, EGL_FALSE);
   2131 
   2132    _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
   2133    assert(disp->Extensions.MESA_image_dma_buf_export);
   2134 
   2135    if (!img)
   2136       RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
   2137 
   2138    ret = drv->API.ExportDMABUFImageQueryMESA(drv, disp, img, fourcc, nplanes,
   2139                                              modifiers);
   2140 
   2141    RETURN_EGL_EVAL(disp, ret);
   2142 }
   2143 
   2144 static EGLBoolean EGLAPIENTRY
   2145 eglExportDMABUFImageMESA(EGLDisplay dpy, EGLImage image,
   2146                          int *fds, EGLint *strides, EGLint *offsets)
   2147 {
   2148    _EGLDisplay *disp = _eglLockDisplay(dpy);
   2149    _EGLImage *img = _eglLookupImage(image, disp);
   2150    _EGLDriver *drv;
   2151    EGLBoolean ret;
   2152 
   2153    _EGL_FUNC_START(disp, EGL_OBJECT_IMAGE_KHR, img, EGL_FALSE);
   2154 
   2155    _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
   2156    assert(disp->Extensions.MESA_image_dma_buf_export);
   2157 
   2158    if (!img)
   2159       RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
   2160 
   2161    ret = drv->API.ExportDMABUFImageMESA(drv, disp, img, fds, strides, offsets);
   2162 
   2163    RETURN_EGL_EVAL(disp, ret);
   2164 }
   2165 
   2166 static EGLint EGLAPIENTRY
   2167 eglLabelObjectKHR(EGLDisplay dpy, EGLenum objectType, EGLObjectKHR object,
   2168 		  EGLLabelKHR label)
   2169 {
   2170    _EGLDisplay *disp = NULL;
   2171    _EGLResourceType type;
   2172 
   2173    _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_BAD_ALLOC);
   2174 
   2175    if (objectType == EGL_OBJECT_THREAD_KHR) {
   2176       _EGLThreadInfo *t = _eglGetCurrentThread();
   2177 
   2178       if (!_eglIsCurrentThreadDummy()) {
   2179          t->Label = label;
   2180          return EGL_SUCCESS;
   2181       }
   2182 
   2183       RETURN_EGL_ERROR(NULL, EGL_BAD_ALLOC, EGL_BAD_ALLOC);
   2184    }
   2185 
   2186    disp = _eglLockDisplay(dpy);
   2187    if (disp == NULL)
   2188       RETURN_EGL_ERROR(disp, EGL_BAD_DISPLAY, EGL_BAD_DISPLAY);
   2189 
   2190    if (objectType == EGL_OBJECT_DISPLAY_KHR) {
   2191       if (dpy != (EGLDisplay) object)
   2192          RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_BAD_PARAMETER);
   2193 
   2194       disp->Label = label;
   2195       RETURN_EGL_EVAL(disp, EGL_SUCCESS);
   2196    }
   2197 
   2198    switch (objectType) {
   2199       case EGL_OBJECT_CONTEXT_KHR:
   2200          type = _EGL_RESOURCE_CONTEXT;
   2201          break;
   2202       case EGL_OBJECT_SURFACE_KHR:
   2203          type = _EGL_RESOURCE_SURFACE;
   2204          break;
   2205       case EGL_OBJECT_IMAGE_KHR:
   2206          type = _EGL_RESOURCE_IMAGE;
   2207          break;
   2208       case EGL_OBJECT_SYNC_KHR:
   2209          type = _EGL_RESOURCE_SYNC;
   2210          break;
   2211       case EGL_OBJECT_STREAM_KHR:
   2212       default:
   2213          RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_BAD_PARAMETER);
   2214    }
   2215 
   2216    if (_eglCheckResource(object, type, disp)) {
   2217       _EGLResource *res = (_EGLResource *) object;
   2218 
   2219       res->Label = label;
   2220       RETURN_EGL_EVAL(disp, EGL_SUCCESS);
   2221    }
   2222 
   2223    RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_BAD_PARAMETER);
   2224 }
   2225 
   2226 static EGLBoolean
   2227 _validDebugMessageLevel(EGLAttrib level)
   2228 {
   2229    return (level >= EGL_DEBUG_MSG_CRITICAL_KHR &&
   2230            level <= EGL_DEBUG_MSG_INFO_KHR);
   2231 }
   2232 
   2233 static EGLint EGLAPIENTRY
   2234 eglDebugMessageControlKHR(EGLDEBUGPROCKHR callback,
   2235 			  const EGLAttrib *attrib_list)
   2236 {
   2237    unsigned int newEnabled;
   2238 
   2239    _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_BAD_ALLOC);
   2240 
   2241    mtx_lock(_eglGlobal.Mutex);
   2242 
   2243    newEnabled = _eglGlobal.debugTypesEnabled;
   2244    if (attrib_list != NULL) {
   2245       int i;
   2246 
   2247       for (i = 0; attrib_list[i] != EGL_NONE; i += 2) {
   2248          if (_validDebugMessageLevel(attrib_list[i])) {
   2249             if (attrib_list[i + 1])
   2250                newEnabled |= DebugBitFromType(attrib_list[i]);
   2251             else
   2252                newEnabled &= ~DebugBitFromType(attrib_list[i]);
   2253             continue;
   2254          }
   2255 
   2256          // On error, set the last error code, call the current
   2257          // debug callback, and return the error code.
   2258          mtx_unlock(_eglGlobal.Mutex);
   2259          _eglReportError(EGL_BAD_ATTRIBUTE, NULL,
   2260                "Invalid attribute 0x%04lx", (unsigned long) attrib_list[i]);
   2261          return EGL_BAD_ATTRIBUTE;
   2262       }
   2263    }
   2264 
   2265    if (callback != NULL) {
   2266       _eglGlobal.debugCallback = callback;
   2267       _eglGlobal.debugTypesEnabled = newEnabled;
   2268    } else {
   2269       _eglGlobal.debugCallback = NULL;
   2270       _eglGlobal.debugTypesEnabled = _EGL_DEBUG_BIT_CRITICAL | _EGL_DEBUG_BIT_ERROR;
   2271    }
   2272 
   2273    mtx_unlock(_eglGlobal.Mutex);
   2274    return EGL_SUCCESS;
   2275 }
   2276 
   2277 static EGLBoolean EGLAPIENTRY
   2278 eglQueryDebugKHR(EGLint attribute, EGLAttrib *value)
   2279 {
   2280    _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_BAD_ALLOC);
   2281 
   2282    mtx_lock(_eglGlobal.Mutex);
   2283 
   2284    do {
   2285       if (_validDebugMessageLevel(attribute)) {
   2286          if (_eglGlobal.debugTypesEnabled & DebugBitFromType(attribute))
   2287             *value = EGL_TRUE;
   2288          else
   2289             *value = EGL_FALSE;
   2290          break;
   2291       }
   2292 
   2293       if (attribute == EGL_DEBUG_CALLBACK_KHR) {
   2294          *value = (EGLAttrib) _eglGlobal.debugCallback;
   2295          break;
   2296       }
   2297 
   2298       mtx_unlock(_eglGlobal.Mutex);
   2299       _eglReportError(EGL_BAD_ATTRIBUTE, NULL,
   2300               "Invalid attribute 0x%04lx", (unsigned long) attribute);
   2301       return EGL_FALSE;
   2302    } while (0);
   2303 
   2304    mtx_unlock(_eglGlobal.Mutex);
   2305    return EGL_TRUE;
   2306 }
   2307 
   2308 __eglMustCastToProperFunctionPointerType EGLAPIENTRY
   2309 eglGetProcAddress(const char *procname)
   2310 {
   2311    static const struct {
   2312       const char *name;
   2313       _EGLProc function;
   2314    } egl_functions[] = {
   2315       /* core functions queryable in the presence of
   2316        * EGL_KHR_get_all_proc_addresses or EGL 1.5
   2317        */
   2318       /* alphabetical order */
   2319       { "eglBindAPI", (_EGLProc) eglBindAPI },
   2320       { "eglBindTexImage", (_EGLProc) eglBindTexImage },
   2321       { "eglChooseConfig", (_EGLProc) eglChooseConfig },
   2322       { "eglCopyBuffers", (_EGLProc) eglCopyBuffers },
   2323       { "eglCreateContext", (_EGLProc) eglCreateContext },
   2324       { "eglCreatePbufferFromClientBuffer", (_EGLProc) eglCreatePbufferFromClientBuffer },
   2325       { "eglCreatePbufferSurface", (_EGLProc) eglCreatePbufferSurface },
   2326       { "eglCreatePixmapSurface", (_EGLProc) eglCreatePixmapSurface },
   2327       { "eglCreateWindowSurface", (_EGLProc) eglCreateWindowSurface },
   2328       { "eglDestroyContext", (_EGLProc) eglDestroyContext },
   2329       { "eglDestroySurface", (_EGLProc) eglDestroySurface },
   2330       { "eglGetConfigAttrib", (_EGLProc) eglGetConfigAttrib },
   2331       { "eglGetConfigs", (_EGLProc) eglGetConfigs },
   2332       { "eglGetCurrentContext", (_EGLProc) eglGetCurrentContext },
   2333       { "eglGetCurrentDisplay", (_EGLProc) eglGetCurrentDisplay },
   2334       { "eglGetCurrentSurface", (_EGLProc) eglGetCurrentSurface },
   2335       { "eglGetDisplay", (_EGLProc) eglGetDisplay },
   2336       { "eglGetError", (_EGLProc) eglGetError },
   2337       { "eglGetProcAddress", (_EGLProc) eglGetProcAddress },
   2338       { "eglInitialize", (_EGLProc) eglInitialize },
   2339       { "eglMakeCurrent", (_EGLProc) eglMakeCurrent },
   2340       { "eglQueryAPI", (_EGLProc) eglQueryAPI },
   2341       { "eglQueryContext", (_EGLProc) eglQueryContext },
   2342       { "eglQueryString", (_EGLProc) eglQueryString },
   2343       { "eglQuerySurface", (_EGLProc) eglQuerySurface },
   2344       { "eglReleaseTexImage", (_EGLProc) eglReleaseTexImage },
   2345       { "eglReleaseThread", (_EGLProc) eglReleaseThread },
   2346       { "eglSurfaceAttrib", (_EGLProc) eglSurfaceAttrib },
   2347       { "eglSwapBuffers", (_EGLProc) eglSwapBuffers },
   2348       { "eglSwapInterval", (_EGLProc) eglSwapInterval },
   2349       { "eglTerminate", (_EGLProc) eglTerminate },
   2350       { "eglWaitClient", (_EGLProc) eglWaitClient },
   2351       { "eglWaitGL", (_EGLProc) eglWaitGL },
   2352       { "eglWaitNative", (_EGLProc) eglWaitNative },
   2353       { "eglCreateSync", (_EGLProc) eglCreateSync },
   2354       { "eglDestroySync", (_EGLProc) eglDestroySync },
   2355       { "eglClientWaitSync", (_EGLProc) eglClientWaitSync },
   2356       { "eglGetSyncAttrib", (_EGLProc) eglGetSyncAttrib },
   2357       { "eglWaitSync", (_EGLProc) eglWaitSync },
   2358       { "eglCreateImage", (_EGLProc) eglCreateImage },
   2359       { "eglDestroyImage", (_EGLProc) eglDestroyImage },
   2360       { "eglGetPlatformDisplay", (_EGLProc) eglGetPlatformDisplay },
   2361       { "eglCreatePlatformWindowSurface", (_EGLProc) eglCreatePlatformWindowSurface },
   2362       { "eglCreatePlatformPixmapSurface", (_EGLProc) eglCreatePlatformPixmapSurface },
   2363       { "eglCreateImageKHR", (_EGLProc) eglCreateImageKHR },
   2364       { "eglDestroyImageKHR", (_EGLProc) eglDestroyImage },
   2365       { "eglCreateSyncKHR", (_EGLProc) eglCreateSyncKHR },
   2366       { "eglCreateSync64KHR", (_EGLProc) eglCreateSync64KHR },
   2367       { "eglDestroySyncKHR", (_EGLProc) eglDestroySync },
   2368       { "eglClientWaitSyncKHR", (_EGLProc) eglClientWaitSync },
   2369       { "eglWaitSyncKHR", (_EGLProc) eglWaitSyncKHR },
   2370       { "eglSignalSyncKHR", (_EGLProc) eglSignalSyncKHR },
   2371       { "eglGetSyncAttribKHR", (_EGLProc) eglGetSyncAttribKHR },
   2372       { "eglSwapBuffersRegionNOK", (_EGLProc) eglSwapBuffersRegionNOK },
   2373       { "eglCreateDRMImageMESA", (_EGLProc) eglCreateDRMImageMESA },
   2374       { "eglExportDRMImageMESA", (_EGLProc) eglExportDRMImageMESA },
   2375       { "eglBindWaylandDisplayWL", (_EGLProc) eglBindWaylandDisplayWL },
   2376       { "eglUnbindWaylandDisplayWL", (_EGLProc) eglUnbindWaylandDisplayWL },
   2377       { "eglQueryWaylandBufferWL", (_EGLProc) eglQueryWaylandBufferWL },
   2378       { "eglCreateWaylandBufferFromImageWL", (_EGLProc) eglCreateWaylandBufferFromImageWL },
   2379       { "eglPostSubBufferNV", (_EGLProc) eglPostSubBufferNV },
   2380       { "eglSwapBuffersWithDamageEXT", (_EGLProc) eglSwapBuffersWithDamageEXT },
   2381       { "eglSwapBuffersWithDamageKHR", (_EGLProc) eglSwapBuffersWithDamageKHR },
   2382       { "eglGetPlatformDisplayEXT", (_EGLProc) eglGetPlatformDisplayEXT },
   2383       { "eglCreatePlatformWindowSurfaceEXT", (_EGLProc) eglCreatePlatformWindowSurfaceEXT },
   2384       { "eglCreatePlatformPixmapSurfaceEXT", (_EGLProc) eglCreatePlatformPixmapSurfaceEXT },
   2385       { "eglGetSyncValuesCHROMIUM", (_EGLProc) eglGetSyncValuesCHROMIUM },
   2386       { "eglExportDMABUFImageQueryMESA", (_EGLProc) eglExportDMABUFImageQueryMESA },
   2387       { "eglExportDMABUFImageMESA", (_EGLProc) eglExportDMABUFImageMESA },
   2388       { "eglLabelObjectKHR", (_EGLProc) eglLabelObjectKHR },
   2389       { "eglDebugMessageControlKHR", (_EGLProc) eglDebugMessageControlKHR },
   2390       { "eglQueryDebugKHR", (_EGLProc) eglQueryDebugKHR },
   2391       { "eglDupNativeFenceFDANDROID", (_EGLProc) eglDupNativeFenceFDANDROID },
   2392       { NULL, NULL }
   2393    };
   2394    EGLint i;
   2395    _EGLProc ret;
   2396 
   2397    if (!procname)
   2398       RETURN_EGL_SUCCESS(NULL, NULL);
   2399 
   2400    _EGL_FUNC_START(NULL, EGL_NONE, NULL, NULL);
   2401 
   2402    ret = NULL;
   2403    if (strncmp(procname, "egl", 3) == 0) {
   2404       for (i = 0; egl_functions[i].name; i++) {
   2405          if (strcmp(egl_functions[i].name, procname) == 0) {
   2406             ret = egl_functions[i].function;
   2407             break;
   2408          }
   2409       }
   2410    }
   2411    if (!ret)
   2412       ret = _eglGetDriverProc(procname);
   2413 
   2414    RETURN_EGL_SUCCESS(NULL, ret);
   2415 }
   2416 
   2417 static int
   2418 _eglLockDisplayInterop(EGLDisplay dpy, EGLContext context,
   2419                        _EGLDisplay **disp, _EGLDriver **drv,
   2420                        _EGLContext **ctx)
   2421 {
   2422 
   2423    *disp = _eglLockDisplay(dpy);
   2424    if (!*disp || !(*disp)->Initialized || !(*disp)->Driver) {
   2425       if (*disp)
   2426          _eglUnlockDisplay(*disp);
   2427       return MESA_GLINTEROP_INVALID_DISPLAY;
   2428    }
   2429 
   2430    *drv = (*disp)->Driver;
   2431 
   2432    *ctx = _eglLookupContext(context, *disp);
   2433    if (!*ctx ||
   2434        ((*ctx)->ClientAPI != EGL_OPENGL_API &&
   2435         (*ctx)->ClientAPI != EGL_OPENGL_ES_API)) {
   2436       _eglUnlockDisplay(*disp);
   2437       return MESA_GLINTEROP_INVALID_CONTEXT;
   2438    }
   2439 
   2440    return MESA_GLINTEROP_SUCCESS;
   2441 }
   2442 
   2443 PUBLIC int
   2444 MesaGLInteropEGLQueryDeviceInfo(EGLDisplay dpy, EGLContext context,
   2445                                 struct mesa_glinterop_device_info *out)
   2446 {
   2447    _EGLDisplay *disp;
   2448    _EGLDriver *drv;
   2449    _EGLContext *ctx;
   2450    int ret;
   2451 
   2452    ret = _eglLockDisplayInterop(dpy, context, &disp, &drv, &ctx);
   2453    if (ret != MESA_GLINTEROP_SUCCESS)
   2454       return ret;
   2455 
   2456    if (drv->API.GLInteropQueryDeviceInfo)
   2457       ret = drv->API.GLInteropQueryDeviceInfo(disp, ctx, out);
   2458    else
   2459       ret = MESA_GLINTEROP_UNSUPPORTED;
   2460 
   2461    _eglUnlockDisplay(disp);
   2462    return ret;
   2463 }
   2464 
   2465 PUBLIC int
   2466 MesaGLInteropEGLExportObject(EGLDisplay dpy, EGLContext context,
   2467                              struct mesa_glinterop_export_in *in,
   2468                              struct mesa_glinterop_export_out *out)
   2469 {
   2470    _EGLDisplay *disp;
   2471    _EGLDriver *drv;
   2472    _EGLContext *ctx;
   2473    int ret;
   2474 
   2475    ret = _eglLockDisplayInterop(dpy, context, &disp, &drv, &ctx);
   2476    if (ret != MESA_GLINTEROP_SUCCESS)
   2477       return ret;
   2478 
   2479    if (drv->API.GLInteropExportObject)
   2480       ret = drv->API.GLInteropExportObject(disp, ctx, in, out);
   2481    else
   2482       ret = MESA_GLINTEROP_UNSUPPORTED;
   2483 
   2484    _eglUnlockDisplay(disp);
   2485    return ret;
   2486 }
   2487