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