Home | History | Annotate | Download | only in main
      1 /**************************************************************************
      2  *
      3  * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
      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 
     90 #include "eglcontext.h"
     91 #include "egldisplay.h"
     92 #include "egltypedefs.h"
     93 #include "eglcurrent.h"
     94 #include "egldriver.h"
     95 #include "eglsurface.h"
     96 #include "eglconfig.h"
     97 #include "eglscreen.h"
     98 #include "eglmode.h"
     99 #include "eglimage.h"
    100 #include "eglsync.h"
    101 
    102 
    103 /**
    104  * Macros to help return an API entrypoint.
    105  *
    106  * These macros will unlock the display and record the error code.
    107  */
    108 #define RETURN_EGL_ERROR(disp, err, ret)        \
    109    do {                                         \
    110       if (disp)                                 \
    111          _eglUnlockDisplay(disp);               \
    112       /* EGL error codes are non-zero */        \
    113       if (err)                                  \
    114          _eglError(err, __FUNCTION__);          \
    115       return ret;                               \
    116    } while (0)
    117 
    118 #define RETURN_EGL_SUCCESS(disp, ret) \
    119    RETURN_EGL_ERROR(disp, EGL_SUCCESS, ret)
    120 
    121 /* record EGL_SUCCESS only when ret evaluates to true */
    122 #define RETURN_EGL_EVAL(disp, ret) \
    123    RETURN_EGL_ERROR(disp, (ret) ? EGL_SUCCESS : 0, ret)
    124 
    125 
    126 /*
    127  * A bunch of macros and checks to simplify error checking.
    128  */
    129 
    130 #define _EGL_CHECK_DISPLAY(disp, ret, drv)         \
    131    do {                                            \
    132       drv = _eglCheckDisplay(disp, __FUNCTION__);  \
    133       if (!drv)                                    \
    134          RETURN_EGL_ERROR(disp, 0, ret);           \
    135    } while (0)
    136 
    137 #define _EGL_CHECK_OBJECT(disp, type, obj, ret, drv)      \
    138    do {                                                   \
    139       drv = _eglCheck ## type(disp, obj, __FUNCTION__);   \
    140       if (!drv)                                           \
    141          RETURN_EGL_ERROR(disp, 0, ret);                  \
    142    } while (0)
    143 
    144 #define _EGL_CHECK_SURFACE(disp, surf, ret, drv) \
    145    _EGL_CHECK_OBJECT(disp, Surface, surf, ret, drv)
    146 
    147 #define _EGL_CHECK_CONTEXT(disp, context, ret, drv) \
    148    _EGL_CHECK_OBJECT(disp, Context, context, ret, drv)
    149 
    150 #define _EGL_CHECK_CONFIG(disp, conf, ret, drv) \
    151    _EGL_CHECK_OBJECT(disp, Config, conf, ret, drv)
    152 
    153 #define _EGL_CHECK_SCREEN(disp, scrn, ret, drv) \
    154    _EGL_CHECK_OBJECT(disp, Screen, scrn, ret, drv)
    155 
    156 #define _EGL_CHECK_MODE(disp, m, ret, drv) \
    157    _EGL_CHECK_OBJECT(disp, Mode, m, ret, drv)
    158 
    159 #define _EGL_CHECK_SYNC(disp, s, ret, drv) \
    160    _EGL_CHECK_OBJECT(disp, Sync, s, ret, drv)
    161 
    162 
    163 static INLINE _EGLDriver *
    164 _eglCheckDisplay(_EGLDisplay *disp, const char *msg)
    165 {
    166    if (!disp) {
    167       _eglError(EGL_BAD_DISPLAY, msg);
    168       return NULL;
    169    }
    170    if (!disp->Initialized) {
    171       _eglError(EGL_NOT_INITIALIZED, msg);
    172       return NULL;
    173    }
    174    return disp->Driver;
    175 }
    176 
    177 
    178 static INLINE _EGLDriver *
    179 _eglCheckSurface(_EGLDisplay *disp, _EGLSurface *surf, const char *msg)
    180 {
    181    _EGLDriver *drv = _eglCheckDisplay(disp, msg);
    182    if (!drv)
    183       return NULL;
    184    if (!surf) {
    185       _eglError(EGL_BAD_SURFACE, msg);
    186       return NULL;
    187    }
    188    return drv;
    189 }
    190 
    191 
    192 static INLINE _EGLDriver *
    193 _eglCheckContext(_EGLDisplay *disp, _EGLContext *context, const char *msg)
    194 {
    195    _EGLDriver *drv = _eglCheckDisplay(disp, msg);
    196    if (!drv)
    197       return NULL;
    198    if (!context) {
    199       _eglError(EGL_BAD_CONTEXT, msg);
    200       return NULL;
    201    }
    202    return drv;
    203 }
    204 
    205 
    206 static INLINE _EGLDriver *
    207 _eglCheckConfig(_EGLDisplay *disp, _EGLConfig *conf, const char *msg)
    208 {
    209    _EGLDriver *drv = _eglCheckDisplay(disp, msg);
    210    if (!drv)
    211       return NULL;
    212    if (!conf) {
    213       _eglError(EGL_BAD_CONFIG, msg);
    214       return NULL;
    215    }
    216    return drv;
    217 }
    218 
    219 
    220 static INLINE _EGLDriver *
    221 _eglCheckSync(_EGLDisplay *disp, _EGLSync *s, const char *msg)
    222 {
    223    _EGLDriver *drv = _eglCheckDisplay(disp, msg);
    224    if (!drv)
    225       return NULL;
    226    if (!s) {
    227       _eglError(EGL_BAD_PARAMETER, msg);
    228       return NULL;
    229    }
    230    return drv;
    231 }
    232 
    233 
    234 #ifdef EGL_MESA_screen_surface
    235 
    236 
    237 static INLINE _EGLDriver *
    238 _eglCheckScreen(_EGLDisplay *disp, _EGLScreen *scrn, const char *msg)
    239 {
    240    _EGLDriver *drv = _eglCheckDisplay(disp, msg);
    241    if (!drv)
    242       return NULL;
    243    if (!scrn) {
    244       _eglError(EGL_BAD_SCREEN_MESA, msg);
    245       return NULL;
    246    }
    247    return drv;
    248 }
    249 
    250 
    251 static INLINE _EGLDriver *
    252 _eglCheckMode(_EGLDisplay *disp, _EGLMode *m, const char *msg)
    253 {
    254    _EGLDriver *drv = _eglCheckDisplay(disp, msg);
    255    if (!drv)
    256       return NULL;
    257    if (!m) {
    258       _eglError(EGL_BAD_MODE_MESA, msg);
    259       return NULL;
    260    }
    261    return drv;
    262 }
    263 
    264 
    265 #endif /* EGL_MESA_screen_surface */
    266 
    267 
    268 /**
    269  * Lookup and lock a display.
    270  */
    271 static INLINE _EGLDisplay *
    272 _eglLockDisplay(EGLDisplay display)
    273 {
    274    _EGLDisplay *dpy = _eglLookupDisplay(display);
    275    if (dpy)
    276       _eglLockMutex(&dpy->Mutex);
    277    return dpy;
    278 }
    279 
    280 
    281 /**
    282  * Unlock a display.
    283  */
    284 static INLINE void
    285 _eglUnlockDisplay(_EGLDisplay *dpy)
    286 {
    287    _eglUnlockMutex(&dpy->Mutex);
    288 }
    289 
    290 
    291 /**
    292  * This is typically the first EGL function that an application calls.
    293  * It associates a private _EGLDisplay object to the native display.
    294  */
    295 EGLDisplay EGLAPIENTRY
    296 eglGetDisplay(EGLNativeDisplayType nativeDisplay)
    297 {
    298    _EGLPlatformType plat = _eglGetNativePlatform(nativeDisplay);
    299    _EGLDisplay *dpy = _eglFindDisplay(plat, (void *) nativeDisplay);
    300    return _eglGetDisplayHandle(dpy);
    301 }
    302 
    303 
    304 /**
    305  * This is typically the second EGL function that an application calls.
    306  * Here we load/initialize the actual hardware driver.
    307  */
    308 EGLBoolean EGLAPIENTRY
    309 eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
    310 {
    311    _EGLDisplay *disp = _eglLockDisplay(dpy);
    312 
    313    if (!disp)
    314       RETURN_EGL_ERROR(NULL, EGL_BAD_DISPLAY, EGL_FALSE);
    315 
    316    if (!disp->Initialized) {
    317       if (!_eglMatchDriver(disp, EGL_FALSE))
    318          RETURN_EGL_ERROR(disp, EGL_NOT_INITIALIZED, EGL_FALSE);
    319 
    320       /* limit to APIs supported by core */
    321       disp->ClientAPIs &= _EGL_API_ALL_BITS;
    322    }
    323 
    324    /* Update applications version of major and minor if not NULL */
    325    if ((major != NULL) && (minor != NULL)) {
    326       *major = disp->VersionMajor;
    327       *minor = disp->VersionMinor;
    328    }
    329 
    330    RETURN_EGL_SUCCESS(disp, EGL_TRUE);
    331 }
    332 
    333 
    334 EGLBoolean EGLAPIENTRY
    335 eglTerminate(EGLDisplay dpy)
    336 {
    337    _EGLDisplay *disp = _eglLockDisplay(dpy);
    338 
    339    if (!disp)
    340       RETURN_EGL_ERROR(NULL, EGL_BAD_DISPLAY, EGL_FALSE);
    341 
    342    if (disp->Initialized) {
    343       _EGLDriver *drv = disp->Driver;
    344 
    345       drv->API.Terminate(drv, disp);
    346       /* do not reset disp->Driver */
    347       disp->Initialized = EGL_FALSE;
    348    }
    349 
    350    RETURN_EGL_SUCCESS(disp, EGL_TRUE);
    351 }
    352 
    353 
    354 const char * EGLAPIENTRY
    355 eglQueryString(EGLDisplay dpy, EGLint name)
    356 {
    357    _EGLDisplay *disp = _eglLockDisplay(dpy);
    358    _EGLDriver *drv;
    359    const char *ret;
    360 
    361    _EGL_CHECK_DISPLAY(disp, NULL, drv);
    362    ret = drv->API.QueryString(drv, disp, name);
    363 
    364    RETURN_EGL_EVAL(disp, ret);
    365 }
    366 
    367 
    368 EGLBoolean EGLAPIENTRY
    369 eglGetConfigs(EGLDisplay dpy, EGLConfig *configs,
    370               EGLint config_size, EGLint *num_config)
    371 {
    372    _EGLDisplay *disp = _eglLockDisplay(dpy);
    373    _EGLDriver *drv;
    374    EGLBoolean ret;
    375 
    376    _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
    377    ret = drv->API.GetConfigs(drv, disp, configs, config_size, num_config);
    378 
    379    RETURN_EGL_EVAL(disp, ret);
    380 }
    381 
    382 
    383 EGLBoolean EGLAPIENTRY
    384 eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs,
    385                 EGLint config_size, EGLint *num_config)
    386 {
    387    _EGLDisplay *disp = _eglLockDisplay(dpy);
    388    _EGLDriver *drv;
    389    EGLBoolean ret;
    390 
    391    _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
    392    ret = drv->API.ChooseConfig(drv, disp, attrib_list, configs,
    393                                 config_size, num_config);
    394 
    395    RETURN_EGL_EVAL(disp, ret);
    396 }
    397 
    398 
    399 EGLBoolean EGLAPIENTRY
    400 eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
    401                    EGLint attribute, EGLint *value)
    402 {
    403    _EGLDisplay *disp = _eglLockDisplay(dpy);
    404    _EGLConfig *conf = _eglLookupConfig(config, disp);
    405    _EGLDriver *drv;
    406    EGLBoolean ret;
    407 
    408    _EGL_CHECK_CONFIG(disp, conf, EGL_FALSE, drv);
    409    ret = drv->API.GetConfigAttrib(drv, disp, conf, attribute, value);
    410 
    411    RETURN_EGL_EVAL(disp, ret);
    412 }
    413 
    414 
    415 EGLContext EGLAPIENTRY
    416 eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_list,
    417                  const EGLint *attrib_list)
    418 {
    419    _EGLDisplay *disp = _eglLockDisplay(dpy);
    420    _EGLConfig *conf = _eglLookupConfig(config, disp);
    421    _EGLContext *share = _eglLookupContext(share_list, disp);
    422    _EGLDriver *drv;
    423    _EGLContext *context;
    424    EGLContext ret;
    425 
    426    _EGL_CHECK_DISPLAY(disp, EGL_NO_CONTEXT, drv);
    427 
    428    if (!config) {
    429       /* config may be NULL if surfaceless */
    430       if (!disp->Extensions.KHR_surfaceless_context)
    431          RETURN_EGL_ERROR(disp, EGL_BAD_CONFIG, EGL_NO_CONTEXT);
    432    }
    433 
    434    if (!share && share_list != EGL_NO_CONTEXT)
    435       RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_NO_CONTEXT);
    436 
    437    context = drv->API.CreateContext(drv, disp, conf, share, attrib_list);
    438    ret = (context) ? _eglLinkContext(context) : EGL_NO_CONTEXT;
    439 
    440    RETURN_EGL_EVAL(disp, ret);
    441 }
    442 
    443 
    444 EGLBoolean EGLAPIENTRY
    445 eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
    446 {
    447    _EGLDisplay *disp = _eglLockDisplay(dpy);
    448    _EGLContext *context = _eglLookupContext(ctx, disp);
    449    _EGLDriver *drv;
    450    EGLBoolean ret;
    451 
    452    _EGL_CHECK_CONTEXT(disp, context, EGL_FALSE, drv);
    453    _eglUnlinkContext(context);
    454    ret = drv->API.DestroyContext(drv, disp, context);
    455 
    456    RETURN_EGL_EVAL(disp, ret);
    457 }
    458 
    459 
    460 EGLBoolean EGLAPIENTRY
    461 eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read,
    462                EGLContext ctx)
    463 {
    464    _EGLDisplay *disp = _eglLockDisplay(dpy);
    465    _EGLContext *context = _eglLookupContext(ctx, disp);
    466    _EGLSurface *draw_surf = _eglLookupSurface(draw, disp);
    467    _EGLSurface *read_surf = _eglLookupSurface(read, disp);
    468    _EGLDriver *drv;
    469    EGLBoolean ret;
    470 
    471    if (!disp)
    472       RETURN_EGL_ERROR(disp, EGL_BAD_DISPLAY, EGL_FALSE);
    473    drv = disp->Driver;
    474 
    475    /* display is allowed to be uninitialized under certain condition */
    476    if (!disp->Initialized) {
    477       if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE ||
    478           ctx != EGL_NO_CONTEXT)
    479          RETURN_EGL_ERROR(disp, EGL_BAD_DISPLAY, EGL_FALSE);
    480    }
    481    if (!drv)
    482       RETURN_EGL_SUCCESS(disp, EGL_TRUE);
    483 
    484    if (!context && ctx != EGL_NO_CONTEXT)
    485       RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_FALSE);
    486    if (!draw_surf || !read_surf) {
    487       /* surfaces may be NULL if surfaceless */
    488       if (!disp->Extensions.KHR_surfaceless_context)
    489          RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
    490 
    491       if ((!draw_surf && draw != EGL_NO_SURFACE) ||
    492           (!read_surf && read != EGL_NO_SURFACE))
    493          RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
    494       if (draw_surf || read_surf)
    495          RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_FALSE);
    496    }
    497 
    498    ret = drv->API.MakeCurrent(drv, disp, draw_surf, read_surf, context);
    499 
    500    RETURN_EGL_EVAL(disp, ret);
    501 }
    502 
    503 
    504 EGLBoolean EGLAPIENTRY
    505 eglQueryContext(EGLDisplay dpy, EGLContext ctx,
    506                 EGLint attribute, EGLint *value)
    507 {
    508    _EGLDisplay *disp = _eglLockDisplay(dpy);
    509    _EGLContext *context = _eglLookupContext(ctx, disp);
    510    _EGLDriver *drv;
    511    EGLBoolean ret;
    512 
    513    _EGL_CHECK_CONTEXT(disp, context, EGL_FALSE, drv);
    514    ret = drv->API.QueryContext(drv, disp, context, attribute, value);
    515 
    516    RETURN_EGL_EVAL(disp, ret);
    517 }
    518 
    519 
    520 EGLSurface EGLAPIENTRY
    521 eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config,
    522                        EGLNativeWindowType window, const EGLint *attrib_list)
    523 {
    524    _EGLDisplay *disp = _eglLockDisplay(dpy);
    525    _EGLConfig *conf = _eglLookupConfig(config, disp);
    526    _EGLDriver *drv;
    527    _EGLSurface *surf;
    528    EGLSurface ret;
    529 
    530    _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv);
    531    if (disp->Platform != _eglGetNativePlatform(disp->PlatformDisplay))
    532       RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
    533 
    534    surf = drv->API.CreateWindowSurface(drv, disp, conf, window, attrib_list);
    535    ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE;
    536 
    537    RETURN_EGL_EVAL(disp, ret);
    538 }
    539 
    540 
    541 EGLSurface EGLAPIENTRY
    542 eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config,
    543                        EGLNativePixmapType pixmap, const EGLint *attrib_list)
    544 {
    545    _EGLDisplay *disp = _eglLockDisplay(dpy);
    546    _EGLConfig *conf = _eglLookupConfig(config, disp);
    547    _EGLDriver *drv;
    548    _EGLSurface *surf;
    549    EGLSurface ret;
    550 
    551    _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv);
    552    if (disp->Platform != _eglGetNativePlatform(disp->PlatformDisplay))
    553       RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_PIXMAP, EGL_NO_SURFACE);
    554 
    555    surf = drv->API.CreatePixmapSurface(drv, disp, conf, pixmap, attrib_list);
    556    ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE;
    557 
    558    RETURN_EGL_EVAL(disp, ret);
    559 }
    560 
    561 
    562 EGLSurface EGLAPIENTRY
    563 eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config,
    564                         const EGLint *attrib_list)
    565 {
    566    _EGLDisplay *disp = _eglLockDisplay(dpy);
    567    _EGLConfig *conf = _eglLookupConfig(config, disp);
    568    _EGLDriver *drv;
    569    _EGLSurface *surf;
    570    EGLSurface ret;
    571 
    572    _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv);
    573 
    574    surf = drv->API.CreatePbufferSurface(drv, disp, conf, attrib_list);
    575    ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE;
    576 
    577    RETURN_EGL_EVAL(disp, ret);
    578 }
    579 
    580 
    581 EGLBoolean EGLAPIENTRY
    582 eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
    583 {
    584    _EGLDisplay *disp = _eglLockDisplay(dpy);
    585    _EGLSurface *surf = _eglLookupSurface(surface, disp);
    586    _EGLDriver *drv;
    587    EGLBoolean ret;
    588 
    589    _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
    590    _eglUnlinkSurface(surf);
    591    ret = drv->API.DestroySurface(drv, disp, surf);
    592 
    593    RETURN_EGL_EVAL(disp, ret);
    594 }
    595 
    596 EGLBoolean EGLAPIENTRY
    597 eglQuerySurface(EGLDisplay dpy, EGLSurface surface,
    598                 EGLint attribute, EGLint *value)
    599 {
    600    _EGLDisplay *disp = _eglLockDisplay(dpy);
    601    _EGLSurface *surf = _eglLookupSurface(surface, disp);
    602    _EGLDriver *drv;
    603    EGLBoolean ret;
    604 
    605    _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
    606    ret = drv->API.QuerySurface(drv, disp, surf, attribute, value);
    607 
    608    RETURN_EGL_EVAL(disp, ret);
    609 }
    610 
    611 EGLBoolean EGLAPIENTRY
    612 eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface,
    613                  EGLint attribute, EGLint value)
    614 {
    615    _EGLDisplay *disp = _eglLockDisplay(dpy);
    616    _EGLSurface *surf = _eglLookupSurface(surface, disp);
    617    _EGLDriver *drv;
    618    EGLBoolean ret;
    619 
    620    _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
    621    ret = drv->API.SurfaceAttrib(drv, disp, surf, attribute, value);
    622 
    623    RETURN_EGL_EVAL(disp, ret);
    624 }
    625 
    626 
    627 EGLBoolean EGLAPIENTRY
    628 eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
    629 {
    630    _EGLDisplay *disp = _eglLockDisplay(dpy);
    631    _EGLSurface *surf = _eglLookupSurface(surface, disp);
    632    _EGLDriver *drv;
    633    EGLBoolean ret;
    634 
    635    _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
    636    ret = drv->API.BindTexImage(drv, disp, surf, buffer);
    637 
    638    RETURN_EGL_EVAL(disp, ret);
    639 }
    640 
    641 
    642 EGLBoolean EGLAPIENTRY
    643 eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
    644 {
    645    _EGLDisplay *disp = _eglLockDisplay(dpy);
    646    _EGLSurface *surf = _eglLookupSurface(surface, disp);
    647    _EGLDriver *drv;
    648    EGLBoolean ret;
    649 
    650    _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
    651    ret = drv->API.ReleaseTexImage(drv, disp, surf, buffer);
    652 
    653    RETURN_EGL_EVAL(disp, ret);
    654 }
    655 
    656 
    657 EGLBoolean EGLAPIENTRY
    658 eglSwapInterval(EGLDisplay dpy, EGLint interval)
    659 {
    660    _EGLDisplay *disp = _eglLockDisplay(dpy);
    661    _EGLContext *ctx = _eglGetCurrentContext();
    662    _EGLSurface *surf;
    663    _EGLDriver *drv;
    664    EGLBoolean ret;
    665 
    666    _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
    667 
    668    if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
    669        ctx->Resource.Display != disp)
    670       RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_FALSE);
    671 
    672    surf = ctx->DrawSurface;
    673    if (_eglGetSurfaceHandle(surf) == EGL_NO_SURFACE)
    674       RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
    675 
    676    ret = drv->API.SwapInterval(drv, disp, surf, interval);
    677 
    678    RETURN_EGL_EVAL(disp, ret);
    679 }
    680 
    681 
    682 EGLBoolean EGLAPIENTRY
    683 eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
    684 {
    685    _EGLContext *ctx = _eglGetCurrentContext();
    686    _EGLDisplay *disp = _eglLockDisplay(dpy);
    687    _EGLSurface *surf = _eglLookupSurface(surface, disp);
    688    _EGLDriver *drv;
    689    EGLBoolean ret;
    690 
    691    _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
    692 
    693    /* surface must be bound to current context in EGL 1.4 */
    694    if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
    695        surf != ctx->DrawSurface)
    696       RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
    697 
    698    ret = drv->API.SwapBuffers(drv, disp, surf);
    699 
    700    RETURN_EGL_EVAL(disp, ret);
    701 }
    702 
    703 
    704 EGLBoolean EGLAPIENTRY
    705 eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)
    706 {
    707    _EGLDisplay *disp = _eglLockDisplay(dpy);
    708    _EGLSurface *surf = _eglLookupSurface(surface, disp);
    709    _EGLDriver *drv;
    710    EGLBoolean ret;
    711 
    712    _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
    713    if (disp->Platform != _eglGetNativePlatform(disp->PlatformDisplay))
    714       RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_PIXMAP, EGL_FALSE);
    715    ret = drv->API.CopyBuffers(drv, disp, surf, target);
    716 
    717    RETURN_EGL_EVAL(disp, ret);
    718 }
    719 
    720 
    721 EGLBoolean EGLAPIENTRY
    722 eglWaitClient(void)
    723 {
    724    _EGLContext *ctx = _eglGetCurrentContext();
    725    _EGLDisplay *disp;
    726    _EGLDriver *drv;
    727    EGLBoolean ret;
    728 
    729    if (!ctx)
    730       RETURN_EGL_SUCCESS(NULL, EGL_TRUE);
    731 
    732    disp = ctx->Resource.Display;
    733    _eglLockMutex(&disp->Mutex);
    734 
    735    /* let bad current context imply bad current surface */
    736    if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
    737        _eglGetSurfaceHandle(ctx->DrawSurface) == EGL_NO_SURFACE)
    738       RETURN_EGL_ERROR(disp, EGL_BAD_CURRENT_SURFACE, EGL_FALSE);
    739 
    740    /* a valid current context implies an initialized current display */
    741    assert(disp->Initialized);
    742    drv = disp->Driver;
    743    ret = drv->API.WaitClient(drv, disp, ctx);
    744 
    745    RETURN_EGL_EVAL(disp, ret);
    746 }
    747 
    748 
    749 EGLBoolean EGLAPIENTRY
    750 eglWaitGL(void)
    751 {
    752    _EGLThreadInfo *t = _eglGetCurrentThread();
    753    EGLint api_index = t->CurrentAPIIndex;
    754    EGLint es_index = _eglConvertApiToIndex(EGL_OPENGL_ES_API);
    755    EGLBoolean ret;
    756 
    757    if (api_index != es_index && _eglIsCurrentThreadDummy())
    758       RETURN_EGL_ERROR(NULL, EGL_BAD_ALLOC, EGL_FALSE);
    759 
    760    t->CurrentAPIIndex = es_index;
    761    ret = eglWaitClient();
    762    t->CurrentAPIIndex = api_index;
    763    return ret;
    764 }
    765 
    766 
    767 EGLBoolean EGLAPIENTRY
    768 eglWaitNative(EGLint engine)
    769 {
    770    _EGLContext *ctx = _eglGetCurrentContext();
    771    _EGLDisplay *disp;
    772    _EGLDriver *drv;
    773    EGLBoolean ret;
    774 
    775    if (!ctx)
    776       RETURN_EGL_SUCCESS(NULL, EGL_TRUE);
    777 
    778    disp = ctx->Resource.Display;
    779    _eglLockMutex(&disp->Mutex);
    780 
    781    /* let bad current context imply bad current surface */
    782    if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
    783        _eglGetSurfaceHandle(ctx->DrawSurface) == EGL_NO_SURFACE)
    784       RETURN_EGL_ERROR(disp, EGL_BAD_CURRENT_SURFACE, EGL_FALSE);
    785 
    786    /* a valid current context implies an initialized current display */
    787    assert(disp->Initialized);
    788    drv = disp->Driver;
    789    ret = drv->API.WaitNative(drv, disp, engine);
    790 
    791    RETURN_EGL_EVAL(disp, ret);
    792 }
    793 
    794 
    795 EGLDisplay EGLAPIENTRY
    796 eglGetCurrentDisplay(void)
    797 {
    798    _EGLContext *ctx = _eglGetCurrentContext();
    799    EGLDisplay ret;
    800 
    801    ret = (ctx) ? _eglGetDisplayHandle(ctx->Resource.Display) : EGL_NO_DISPLAY;
    802 
    803    RETURN_EGL_SUCCESS(NULL, ret);
    804 }
    805 
    806 
    807 EGLContext EGLAPIENTRY
    808 eglGetCurrentContext(void)
    809 {
    810    _EGLContext *ctx = _eglGetCurrentContext();
    811    EGLContext ret;
    812 
    813    ret = _eglGetContextHandle(ctx);
    814 
    815    RETURN_EGL_SUCCESS(NULL, ret);
    816 }
    817 
    818 
    819 EGLSurface EGLAPIENTRY
    820 eglGetCurrentSurface(EGLint readdraw)
    821 {
    822    _EGLContext *ctx = _eglGetCurrentContext();
    823    EGLint err = EGL_SUCCESS;
    824    _EGLSurface *surf;
    825    EGLSurface ret;
    826 
    827    if (!ctx)
    828       RETURN_EGL_SUCCESS(NULL, EGL_NO_SURFACE);
    829 
    830    switch (readdraw) {
    831    case EGL_DRAW:
    832       surf = ctx->DrawSurface;
    833       break;
    834    case EGL_READ:
    835       surf = ctx->ReadSurface;
    836       break;
    837    default:
    838       surf = NULL;
    839       err = EGL_BAD_PARAMETER;
    840       break;
    841    }
    842 
    843    ret = _eglGetSurfaceHandle(surf);
    844 
    845    RETURN_EGL_ERROR(NULL, err, ret);
    846 }
    847 
    848 
    849 EGLint EGLAPIENTRY
    850 eglGetError(void)
    851 {
    852    _EGLThreadInfo *t = _eglGetCurrentThread();
    853    EGLint e = t->LastError;
    854    if (!_eglIsCurrentThreadDummy())
    855       t->LastError = EGL_SUCCESS;
    856    return e;
    857 }
    858 
    859 
    860 __eglMustCastToProperFunctionPointerType EGLAPIENTRY
    861 eglGetProcAddress(const char *procname)
    862 {
    863    static const struct {
    864       const char *name;
    865       _EGLProc function;
    866    } egl_functions[] = {
    867       /* core functions should not be queryable, but, well... */
    868 #ifdef _EGL_GET_CORE_ADDRESSES
    869       /* alphabetical order */
    870       { "eglBindAPI", (_EGLProc) eglBindAPI },
    871       { "eglBindTexImage", (_EGLProc) eglBindTexImage },
    872       { "eglChooseConfig", (_EGLProc) eglChooseConfig },
    873       { "eglCopyBuffers", (_EGLProc) eglCopyBuffers },
    874       { "eglCreateContext", (_EGLProc) eglCreateContext },
    875       { "eglCreatePbufferFromClientBuffer", (_EGLProc) eglCreatePbufferFromClientBuffer },
    876       { "eglCreatePbufferSurface", (_EGLProc) eglCreatePbufferSurface },
    877       { "eglCreatePixmapSurface", (_EGLProc) eglCreatePixmapSurface },
    878       { "eglCreateWindowSurface", (_EGLProc) eglCreateWindowSurface },
    879       { "eglDestroyContext", (_EGLProc) eglDestroyContext },
    880       { "eglDestroySurface", (_EGLProc) eglDestroySurface },
    881       { "eglGetConfigAttrib", (_EGLProc) eglGetConfigAttrib },
    882       { "eglGetConfigs", (_EGLProc) eglGetConfigs },
    883       { "eglGetCurrentContext", (_EGLProc) eglGetCurrentContext },
    884       { "eglGetCurrentDisplay", (_EGLProc) eglGetCurrentDisplay },
    885       { "eglGetCurrentSurface", (_EGLProc) eglGetCurrentSurface },
    886       { "eglGetDisplay", (_EGLProc) eglGetDisplay },
    887       { "eglGetError", (_EGLProc) eglGetError },
    888       { "eglGetProcAddress", (_EGLProc) eglGetProcAddress },
    889       { "eglInitialize", (_EGLProc) eglInitialize },
    890       { "eglMakeCurrent", (_EGLProc) eglMakeCurrent },
    891       { "eglQueryAPI", (_EGLProc) eglQueryAPI },
    892       { "eglQueryContext", (_EGLProc) eglQueryContext },
    893       { "eglQueryString", (_EGLProc) eglQueryString },
    894       { "eglQuerySurface", (_EGLProc) eglQuerySurface },
    895       { "eglReleaseTexImage", (_EGLProc) eglReleaseTexImage },
    896       { "eglReleaseThread", (_EGLProc) eglReleaseThread },
    897       { "eglSurfaceAttrib", (_EGLProc) eglSurfaceAttrib },
    898       { "eglSwapBuffers", (_EGLProc) eglSwapBuffers },
    899       { "eglSwapInterval", (_EGLProc) eglSwapInterval },
    900       { "eglTerminate", (_EGLProc) eglTerminate },
    901       { "eglWaitClient", (_EGLProc) eglWaitClient },
    902       { "eglWaitGL", (_EGLProc) eglWaitGL },
    903       { "eglWaitNative", (_EGLProc) eglWaitNative },
    904 #endif /* _EGL_GET_CORE_ADDRESSES */
    905 #ifdef EGL_MESA_screen_surface
    906       { "eglChooseModeMESA", (_EGLProc) eglChooseModeMESA },
    907       { "eglGetModesMESA", (_EGLProc) eglGetModesMESA },
    908       { "eglGetModeAttribMESA", (_EGLProc) eglGetModeAttribMESA },
    909       { "eglCopyContextMESA", (_EGLProc) eglCopyContextMESA },
    910       { "eglGetScreensMESA", (_EGLProc) eglGetScreensMESA },
    911       { "eglCreateScreenSurfaceMESA", (_EGLProc) eglCreateScreenSurfaceMESA },
    912       { "eglShowScreenSurfaceMESA", (_EGLProc) eglShowScreenSurfaceMESA },
    913       { "eglScreenPositionMESA", (_EGLProc) eglScreenPositionMESA },
    914       { "eglQueryScreenMESA", (_EGLProc) eglQueryScreenMESA },
    915       { "eglQueryScreenSurfaceMESA", (_EGLProc) eglQueryScreenSurfaceMESA },
    916       { "eglQueryScreenModeMESA", (_EGLProc) eglQueryScreenModeMESA },
    917       { "eglQueryModeStringMESA", (_EGLProc) eglQueryModeStringMESA },
    918 #endif /* EGL_MESA_screen_surface */
    919 #ifdef EGL_MESA_drm_display
    920       { "eglGetDRMDisplayMESA", (_EGLProc) eglGetDRMDisplayMESA },
    921 #endif
    922       { "eglCreateImageKHR", (_EGLProc) eglCreateImageKHR },
    923       { "eglDestroyImageKHR", (_EGLProc) eglDestroyImageKHR },
    924       { "eglCreateSyncKHR", (_EGLProc) eglCreateSyncKHR },
    925       { "eglDestroySyncKHR", (_EGLProc) eglDestroySyncKHR },
    926       { "eglClientWaitSyncKHR", (_EGLProc) eglClientWaitSyncKHR },
    927       { "eglSignalSyncKHR", (_EGLProc) eglSignalSyncKHR },
    928       { "eglGetSyncAttribKHR", (_EGLProc) eglGetSyncAttribKHR },
    929 #ifdef EGL_NOK_swap_region
    930       { "eglSwapBuffersRegionNOK", (_EGLProc) eglSwapBuffersRegionNOK },
    931 #endif
    932 #ifdef EGL_MESA_drm_image
    933       { "eglCreateDRMImageMESA", (_EGLProc) eglCreateDRMImageMESA },
    934       { "eglExportDRMImageMESA", (_EGLProc) eglExportDRMImageMESA },
    935 #endif
    936 #ifdef EGL_WL_bind_wayland_display
    937       { "eglBindWaylandDisplayWL", (_EGLProc) eglBindWaylandDisplayWL },
    938       { "eglUnbindWaylandDisplayWL", (_EGLProc) eglUnbindWaylandDisplayWL },
    939       { "eglQueryWaylandBufferWL", (_EGLProc) eglQueryWaylandBufferWL },
    940 #endif
    941       { "eglPostSubBufferNV", (_EGLProc) eglPostSubBufferNV },
    942       { NULL, NULL }
    943    };
    944    EGLint i;
    945    _EGLProc ret;
    946 
    947    if (!procname)
    948       RETURN_EGL_SUCCESS(NULL, NULL);
    949 
    950    ret = NULL;
    951    if (strncmp(procname, "egl", 3) == 0) {
    952       for (i = 0; egl_functions[i].name; i++) {
    953          if (strcmp(egl_functions[i].name, procname) == 0) {
    954             ret = egl_functions[i].function;
    955             break;
    956          }
    957       }
    958    }
    959    if (!ret)
    960       ret = _eglGetDriverProc(procname);
    961 
    962    RETURN_EGL_SUCCESS(NULL, ret);
    963 }
    964 
    965 
    966 #ifdef EGL_MESA_screen_surface
    967 
    968 
    969 /*
    970  * EGL_MESA_screen extension
    971  */
    972 
    973 EGLBoolean EGLAPIENTRY
    974 eglChooseModeMESA(EGLDisplay dpy, EGLScreenMESA screen,
    975                   const EGLint *attrib_list, EGLModeMESA *modes,
    976                   EGLint modes_size, EGLint *num_modes)
    977 {
    978    _EGLDisplay *disp = _eglLockDisplay(dpy);
    979    _EGLScreen *scrn = _eglLookupScreen(screen, disp);
    980    _EGLDriver *drv;
    981    EGLBoolean ret;
    982 
    983    _EGL_CHECK_SCREEN(disp, scrn, EGL_FALSE, drv);
    984    ret = drv->API.ChooseModeMESA(drv, disp, scrn, attrib_list,
    985          modes, modes_size, num_modes);
    986 
    987    RETURN_EGL_EVAL(disp, ret);
    988 }
    989 
    990 
    991 EGLBoolean EGLAPIENTRY
    992 eglGetModesMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLModeMESA *modes,
    993                 EGLint mode_size, EGLint *num_mode)
    994 {
    995    _EGLDisplay *disp = _eglLockDisplay(dpy);
    996    _EGLScreen *scrn = _eglLookupScreen(screen, disp);
    997    _EGLDriver *drv;
    998    EGLBoolean ret;
    999 
   1000    _EGL_CHECK_SCREEN(disp, scrn, EGL_FALSE, drv);
   1001    ret = drv->API.GetModesMESA(drv, disp, scrn, modes, mode_size, num_mode);
   1002 
   1003    RETURN_EGL_EVAL(disp, ret);
   1004 }
   1005 
   1006 
   1007 EGLBoolean EGLAPIENTRY
   1008 eglGetModeAttribMESA(EGLDisplay dpy, EGLModeMESA mode,
   1009                      EGLint attribute, EGLint *value)
   1010 {
   1011    _EGLDisplay *disp = _eglLockDisplay(dpy);
   1012    _EGLMode *m = _eglLookupMode(mode, disp);
   1013    _EGLDriver *drv;
   1014    EGLBoolean ret;
   1015 
   1016    _EGL_CHECK_MODE(disp, m, EGL_FALSE, drv);
   1017    ret = drv->API.GetModeAttribMESA(drv, disp, m, attribute, value);
   1018 
   1019    RETURN_EGL_EVAL(disp, ret);
   1020 }
   1021 
   1022 
   1023 EGLBoolean EGLAPIENTRY
   1024 eglCopyContextMESA(EGLDisplay dpy, EGLContext source, EGLContext dest,
   1025                    EGLint mask)
   1026 {
   1027    _EGLDisplay *disp = _eglLockDisplay(dpy);
   1028    _EGLContext *source_context = _eglLookupContext(source, disp);
   1029    _EGLContext *dest_context = _eglLookupContext(dest, disp);
   1030    _EGLDriver *drv;
   1031    EGLBoolean ret;
   1032 
   1033    _EGL_CHECK_CONTEXT(disp, source_context, EGL_FALSE, drv);
   1034    if (!dest_context)
   1035       RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_FALSE);
   1036 
   1037    ret = drv->API.CopyContextMESA(drv, disp,
   1038          source_context, dest_context, mask);
   1039 
   1040    RETURN_EGL_EVAL(disp, ret);
   1041 }
   1042 
   1043 
   1044 EGLBoolean EGLAPIENTRY
   1045 eglGetScreensMESA(EGLDisplay dpy, EGLScreenMESA *screens,
   1046                   EGLint max_screens, EGLint *num_screens)
   1047 {
   1048    _EGLDisplay *disp = _eglLockDisplay(dpy);
   1049    _EGLDriver *drv;
   1050    EGLBoolean ret;
   1051 
   1052    _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
   1053    ret = drv->API.GetScreensMESA(drv, disp, screens, max_screens, num_screens);
   1054 
   1055    RETURN_EGL_EVAL(disp, ret);
   1056 }
   1057 
   1058 
   1059 EGLSurface EGLAPIENTRY
   1060 eglCreateScreenSurfaceMESA(EGLDisplay dpy, EGLConfig config,
   1061                            const EGLint *attrib_list)
   1062 {
   1063    _EGLDisplay *disp = _eglLockDisplay(dpy);
   1064    _EGLConfig *conf = _eglLookupConfig(config, disp);
   1065    _EGLDriver *drv;
   1066    _EGLSurface *surf;
   1067    EGLSurface ret;
   1068 
   1069    _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv);
   1070 
   1071    surf = drv->API.CreateScreenSurfaceMESA(drv, disp, conf, attrib_list);
   1072    ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE;
   1073 
   1074    RETURN_EGL_EVAL(disp, ret);
   1075 }
   1076 
   1077 
   1078 EGLBoolean EGLAPIENTRY
   1079 eglShowScreenSurfaceMESA(EGLDisplay dpy, EGLint screen,
   1080                          EGLSurface surface, EGLModeMESA mode)
   1081 {
   1082    _EGLDisplay *disp = _eglLockDisplay(dpy);
   1083    _EGLScreen *scrn = _eglLookupScreen((EGLScreenMESA) screen, disp);
   1084    _EGLSurface *surf = _eglLookupSurface(surface, disp);
   1085    _EGLMode *m = _eglLookupMode(mode, disp);
   1086    _EGLDriver *drv;
   1087    EGLBoolean ret;
   1088 
   1089    _EGL_CHECK_SCREEN(disp, scrn, EGL_FALSE, drv);
   1090    if (!surf && surface != EGL_NO_SURFACE)
   1091       RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
   1092    if (!m && mode != EGL_NO_MODE_MESA)
   1093       RETURN_EGL_ERROR(disp, EGL_BAD_MODE_MESA, EGL_FALSE);
   1094 
   1095    ret = drv->API.ShowScreenSurfaceMESA(drv, disp, scrn, surf, m);
   1096 
   1097    RETURN_EGL_EVAL(disp, ret);
   1098 }
   1099 
   1100 
   1101 EGLBoolean EGLAPIENTRY
   1102 eglScreenPositionMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLint x, EGLint y)
   1103 {
   1104    _EGLDisplay *disp = _eglLockDisplay(dpy);
   1105    _EGLScreen *scrn = _eglLookupScreen(screen, disp);
   1106    _EGLDriver *drv;
   1107    EGLBoolean ret;
   1108 
   1109    _EGL_CHECK_SCREEN(disp, scrn, EGL_FALSE, drv);
   1110    ret = drv->API.ScreenPositionMESA(drv, disp, scrn, x, y);
   1111 
   1112    RETURN_EGL_EVAL(disp, ret);
   1113 }
   1114 
   1115 
   1116 EGLBoolean EGLAPIENTRY
   1117 eglQueryScreenMESA(EGLDisplay dpy, EGLScreenMESA screen,
   1118                    EGLint attribute, EGLint *value)
   1119 {
   1120    _EGLDisplay *disp = _eglLockDisplay(dpy);
   1121    _EGLScreen *scrn = _eglLookupScreen(screen, disp);
   1122    _EGLDriver *drv;
   1123    EGLBoolean ret;
   1124 
   1125    _EGL_CHECK_SCREEN(disp, scrn, EGL_FALSE, drv);
   1126    ret = drv->API.QueryScreenMESA(drv, disp, scrn, attribute, value);
   1127 
   1128    RETURN_EGL_EVAL(disp, ret);
   1129 }
   1130 
   1131 
   1132 EGLBoolean EGLAPIENTRY
   1133 eglQueryScreenSurfaceMESA(EGLDisplay dpy, EGLScreenMESA screen,
   1134                           EGLSurface *surface)
   1135 {
   1136    _EGLDisplay *disp = _eglLockDisplay(dpy);
   1137    _EGLScreen *scrn = _eglLookupScreen((EGLScreenMESA) screen, disp);
   1138    _EGLDriver *drv;
   1139    _EGLSurface *surf;
   1140    EGLBoolean ret;
   1141 
   1142    _EGL_CHECK_SCREEN(disp, scrn, EGL_FALSE, drv);
   1143    ret = drv->API.QueryScreenSurfaceMESA(drv, disp, scrn, &surf);
   1144    if (ret && surface)
   1145       *surface = _eglGetSurfaceHandle(surf);
   1146 
   1147    RETURN_EGL_EVAL(disp, ret);
   1148 }
   1149 
   1150 
   1151 EGLBoolean EGLAPIENTRY
   1152 eglQueryScreenModeMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLModeMESA *mode)
   1153 {
   1154    _EGLDisplay *disp = _eglLockDisplay(dpy);
   1155    _EGLScreen *scrn = _eglLookupScreen((EGLScreenMESA) screen, disp);
   1156    _EGLDriver *drv;
   1157    _EGLMode *m;
   1158    EGLBoolean ret;
   1159 
   1160    _EGL_CHECK_SCREEN(disp, scrn, EGL_FALSE, drv);
   1161    ret = drv->API.QueryScreenModeMESA(drv, disp, scrn, &m);
   1162    if (ret && mode)
   1163       *mode = m->Handle;
   1164 
   1165    RETURN_EGL_EVAL(disp, ret);
   1166 }
   1167 
   1168 
   1169 const char * EGLAPIENTRY
   1170 eglQueryModeStringMESA(EGLDisplay dpy, EGLModeMESA mode)
   1171 {
   1172    _EGLDisplay *disp = _eglLockDisplay(dpy);
   1173    _EGLMode *m = _eglLookupMode(mode, disp);
   1174    _EGLDriver *drv;
   1175    const char *ret;
   1176 
   1177    _EGL_CHECK_MODE(disp, m, NULL, drv);
   1178    ret = drv->API.QueryModeStringMESA(drv, disp, m);
   1179 
   1180    RETURN_EGL_EVAL(disp, ret);
   1181 }
   1182 
   1183 
   1184 #endif /* EGL_MESA_screen_surface */
   1185 
   1186 
   1187 #ifdef EGL_MESA_drm_display
   1188 
   1189 EGLDisplay EGLAPIENTRY
   1190 eglGetDRMDisplayMESA(int fd)
   1191 {
   1192    _EGLDisplay *dpy = _eglFindDisplay(_EGL_PLATFORM_DRM, (void *) (intptr_t) fd);
   1193    return _eglGetDisplayHandle(dpy);
   1194 }
   1195 
   1196 #endif /* EGL_MESA_drm_display */
   1197 
   1198 /**
   1199  ** EGL 1.2
   1200  **/
   1201 
   1202 /**
   1203  * Specify the client API to use for subsequent calls including:
   1204  *  eglCreateContext()
   1205  *  eglGetCurrentContext()
   1206  *  eglGetCurrentDisplay()
   1207  *  eglGetCurrentSurface()
   1208  *  eglMakeCurrent(when the ctx parameter is EGL NO CONTEXT)
   1209  *  eglWaitClient()
   1210  *  eglWaitNative()
   1211  * See section 3.7 "Rendering Context" in the EGL specification for details.
   1212  */
   1213 EGLBoolean EGLAPIENTRY
   1214 eglBindAPI(EGLenum api)
   1215 {
   1216    _EGLThreadInfo *t = _eglGetCurrentThread();
   1217 
   1218    if (_eglIsCurrentThreadDummy())
   1219       RETURN_EGL_ERROR(NULL, EGL_BAD_ALLOC, EGL_FALSE);
   1220 
   1221    if (!_eglIsApiValid(api))
   1222       RETURN_EGL_ERROR(NULL, EGL_BAD_PARAMETER, EGL_FALSE);
   1223 
   1224    t->CurrentAPIIndex = _eglConvertApiToIndex(api);
   1225 
   1226    RETURN_EGL_SUCCESS(NULL, EGL_TRUE);
   1227 }
   1228 
   1229 
   1230 /**
   1231  * Return the last value set with eglBindAPI().
   1232  */
   1233 EGLenum EGLAPIENTRY
   1234 eglQueryAPI(void)
   1235 {
   1236    _EGLThreadInfo *t = _eglGetCurrentThread();
   1237    EGLenum ret;
   1238 
   1239    /* returns one of EGL_OPENGL_API, EGL_OPENGL_ES_API or EGL_OPENVG_API */
   1240    ret = _eglConvertApiFromIndex(t->CurrentAPIIndex);
   1241 
   1242    RETURN_EGL_SUCCESS(NULL, ret);
   1243 }
   1244 
   1245 
   1246 EGLSurface EGLAPIENTRY
   1247 eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype,
   1248                                  EGLClientBuffer buffer, EGLConfig config,
   1249                                  const EGLint *attrib_list)
   1250 {
   1251    _EGLDisplay *disp = _eglLockDisplay(dpy);
   1252    _EGLConfig *conf = _eglLookupConfig(config, disp);
   1253    _EGLDriver *drv;
   1254    _EGLSurface *surf;
   1255    EGLSurface ret;
   1256 
   1257    _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv);
   1258 
   1259    surf = drv->API.CreatePbufferFromClientBuffer(drv, disp, buftype, buffer,
   1260                                                  conf, attrib_list);
   1261    ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE;
   1262 
   1263    RETURN_EGL_EVAL(disp, ret);
   1264 }
   1265 
   1266 
   1267 EGLBoolean EGLAPIENTRY
   1268 eglReleaseThread(void)
   1269 {
   1270    /* unbind current contexts */
   1271    if (!_eglIsCurrentThreadDummy()) {
   1272       _EGLThreadInfo *t = _eglGetCurrentThread();
   1273       EGLint api_index = t->CurrentAPIIndex;
   1274       EGLint i;
   1275 
   1276       for (i = 0; i < _EGL_API_NUM_APIS; i++) {
   1277          _EGLContext *ctx = t->CurrentContexts[i];
   1278          if (ctx) {
   1279             _EGLDisplay *disp = ctx->Resource.Display;
   1280             _EGLDriver *drv;
   1281 
   1282             t->CurrentAPIIndex = i;
   1283 
   1284             _eglLockMutex(&disp->Mutex);
   1285             drv = disp->Driver;
   1286             (void) drv->API.MakeCurrent(drv, disp, NULL, NULL, NULL);
   1287             _eglUnlockMutex(&disp->Mutex);
   1288          }
   1289       }
   1290 
   1291       t->CurrentAPIIndex = api_index;
   1292    }
   1293 
   1294    _eglDestroyCurrentThread();
   1295 
   1296    RETURN_EGL_SUCCESS(NULL, EGL_TRUE);
   1297 }
   1298 
   1299 
   1300 EGLImageKHR EGLAPIENTRY
   1301 eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
   1302                   EGLClientBuffer buffer, const EGLint *attr_list)
   1303 {
   1304    _EGLDisplay *disp = _eglLockDisplay(dpy);
   1305    _EGLContext *context = _eglLookupContext(ctx, disp);
   1306    _EGLDriver *drv;
   1307    _EGLImage *img;
   1308    EGLImageKHR ret;
   1309 
   1310    _EGL_CHECK_DISPLAY(disp, EGL_NO_IMAGE_KHR, drv);
   1311    if (!disp->Extensions.KHR_image_base)
   1312       RETURN_EGL_EVAL(disp, EGL_NO_IMAGE_KHR);
   1313    if (!context && ctx != EGL_NO_CONTEXT)
   1314       RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
   1315 
   1316    img = drv->API.CreateImageKHR(drv,
   1317          disp, context, target, buffer, attr_list);
   1318    ret = (img) ? _eglLinkImage(img) : EGL_NO_IMAGE_KHR;
   1319 
   1320    RETURN_EGL_EVAL(disp, ret);
   1321 }
   1322 
   1323 
   1324 EGLBoolean EGLAPIENTRY
   1325 eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR image)
   1326 {
   1327    _EGLDisplay *disp = _eglLockDisplay(dpy);
   1328    _EGLImage *img = _eglLookupImage(image, disp);
   1329    _EGLDriver *drv;
   1330    EGLBoolean ret;
   1331 
   1332    _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
   1333    if (!disp->Extensions.KHR_image_base)
   1334       RETURN_EGL_EVAL(disp, EGL_FALSE);
   1335    if (!img)
   1336       RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
   1337 
   1338    _eglUnlinkImage(img);
   1339    ret = drv->API.DestroyImageKHR(drv, disp, img);
   1340 
   1341    RETURN_EGL_EVAL(disp, ret);
   1342 }
   1343 
   1344 
   1345 EGLSyncKHR EGLAPIENTRY
   1346 eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
   1347 {
   1348    _EGLDisplay *disp = _eglLockDisplay(dpy);
   1349    _EGLDriver *drv;
   1350    _EGLSync *sync;
   1351    EGLSyncKHR ret;
   1352 
   1353    _EGL_CHECK_DISPLAY(disp, EGL_NO_SYNC_KHR, drv);
   1354    if (!disp->Extensions.KHR_reusable_sync)
   1355       RETURN_EGL_EVAL(disp, EGL_NO_SYNC_KHR);
   1356 
   1357    sync = drv->API.CreateSyncKHR(drv, disp, type, attrib_list);
   1358    ret = (sync) ? _eglLinkSync(sync) : EGL_NO_SYNC_KHR;
   1359 
   1360    RETURN_EGL_EVAL(disp, ret);
   1361 }
   1362 
   1363 
   1364 EGLBoolean EGLAPIENTRY
   1365 eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
   1366 {
   1367    _EGLDisplay *disp = _eglLockDisplay(dpy);
   1368    _EGLSync *s = _eglLookupSync(sync, disp);
   1369    _EGLDriver *drv;
   1370    EGLBoolean ret;
   1371 
   1372    _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
   1373    assert(disp->Extensions.KHR_reusable_sync);
   1374 
   1375    _eglUnlinkSync(s);
   1376    ret = drv->API.DestroySyncKHR(drv, disp, s);
   1377 
   1378    RETURN_EGL_EVAL(disp, ret);
   1379 }
   1380 
   1381 
   1382 EGLint EGLAPIENTRY
   1383 eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout)
   1384 {
   1385    _EGLDisplay *disp = _eglLockDisplay(dpy);
   1386    _EGLSync *s = _eglLookupSync(sync, disp);
   1387    _EGLDriver *drv;
   1388    EGLint ret;
   1389 
   1390    _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
   1391    assert(disp->Extensions.KHR_reusable_sync);
   1392    ret = drv->API.ClientWaitSyncKHR(drv, disp, s, flags, timeout);
   1393 
   1394    RETURN_EGL_EVAL(disp, ret);
   1395 }
   1396 
   1397 
   1398 EGLBoolean EGLAPIENTRY
   1399 eglSignalSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode)
   1400 {
   1401    _EGLDisplay *disp = _eglLockDisplay(dpy);
   1402    _EGLSync *s = _eglLookupSync(sync, disp);
   1403    _EGLDriver *drv;
   1404    EGLBoolean ret;
   1405 
   1406    _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
   1407    assert(disp->Extensions.KHR_reusable_sync);
   1408    ret = drv->API.SignalSyncKHR(drv, disp, s, mode);
   1409 
   1410    RETURN_EGL_EVAL(disp, ret);
   1411 }
   1412 
   1413 
   1414 EGLBoolean EGLAPIENTRY
   1415 eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value)
   1416 {
   1417    _EGLDisplay *disp = _eglLockDisplay(dpy);
   1418    _EGLSync *s = _eglLookupSync(sync, disp);
   1419    _EGLDriver *drv;
   1420    EGLBoolean ret;
   1421 
   1422    _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
   1423    assert(disp->Extensions.KHR_reusable_sync);
   1424    ret = drv->API.GetSyncAttribKHR(drv, disp, s, attribute, value);
   1425 
   1426    RETURN_EGL_EVAL(disp, ret);
   1427 }
   1428 
   1429 
   1430 #ifdef EGL_NOK_swap_region
   1431 
   1432 EGLBoolean EGLAPIENTRY
   1433 eglSwapBuffersRegionNOK(EGLDisplay dpy, EGLSurface surface,
   1434 			EGLint numRects, const EGLint *rects)
   1435 {
   1436    _EGLContext *ctx = _eglGetCurrentContext();
   1437    _EGLDisplay *disp = _eglLockDisplay(dpy);
   1438    _EGLSurface *surf = _eglLookupSurface(surface, disp);
   1439    _EGLDriver *drv;
   1440    EGLBoolean ret;
   1441 
   1442    _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
   1443 
   1444    if (!disp->Extensions.NOK_swap_region)
   1445       RETURN_EGL_EVAL(disp, EGL_FALSE);
   1446 
   1447    /* surface must be bound to current context in EGL 1.4 */
   1448    if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
   1449        surf != ctx->DrawSurface)
   1450       RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
   1451 
   1452    ret = drv->API.SwapBuffersRegionNOK(drv, disp, surf, numRects, rects);
   1453 
   1454    RETURN_EGL_EVAL(disp, ret);
   1455 }
   1456 
   1457 #endif /* EGL_NOK_swap_region */
   1458 
   1459 
   1460 #ifdef EGL_MESA_drm_image
   1461 
   1462 EGLImageKHR EGLAPIENTRY
   1463 eglCreateDRMImageMESA(EGLDisplay dpy, const EGLint *attr_list)
   1464 {
   1465    _EGLDisplay *disp = _eglLockDisplay(dpy);
   1466    _EGLDriver *drv;
   1467    _EGLImage *img;
   1468    EGLImageKHR ret;
   1469 
   1470    _EGL_CHECK_DISPLAY(disp, EGL_NO_IMAGE_KHR, drv);
   1471    if (!disp->Extensions.MESA_drm_image)
   1472       RETURN_EGL_EVAL(disp, EGL_NO_IMAGE_KHR);
   1473 
   1474    img = drv->API.CreateDRMImageMESA(drv, disp, attr_list);
   1475    ret = (img) ? _eglLinkImage(img) : EGL_NO_IMAGE_KHR;
   1476 
   1477    RETURN_EGL_EVAL(disp, ret);
   1478 }
   1479 
   1480 EGLBoolean EGLAPIENTRY
   1481 eglExportDRMImageMESA(EGLDisplay dpy, EGLImageKHR image,
   1482 		      EGLint *name, EGLint *handle, EGLint *stride)
   1483 {
   1484    _EGLDisplay *disp = _eglLockDisplay(dpy);
   1485    _EGLImage *img = _eglLookupImage(image, disp);
   1486    _EGLDriver *drv;
   1487    EGLBoolean ret;
   1488 
   1489    _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
   1490    assert(disp->Extensions.MESA_drm_image);
   1491 
   1492    if (!img)
   1493       RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
   1494 
   1495    ret = drv->API.ExportDRMImageMESA(drv, disp, img, name, handle, stride);
   1496 
   1497    RETURN_EGL_EVAL(disp, ret);
   1498 }
   1499 
   1500 #endif
   1501 
   1502 #ifdef EGL_WL_bind_wayland_display
   1503 struct wl_display;
   1504 
   1505 EGLBoolean EGLAPIENTRY
   1506 eglBindWaylandDisplayWL(EGLDisplay dpy, struct wl_display *display)
   1507 {
   1508    _EGLDisplay *disp = _eglLockDisplay(dpy);
   1509    _EGLDriver *drv;
   1510    EGLBoolean ret;
   1511 
   1512    _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
   1513    assert(disp->Extensions.WL_bind_wayland_display);
   1514 
   1515    if (!display)
   1516       RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
   1517 
   1518    ret = drv->API.BindWaylandDisplayWL(drv, disp, display);
   1519 
   1520    RETURN_EGL_EVAL(disp, ret);
   1521 }
   1522 
   1523 EGLBoolean EGLAPIENTRY
   1524 eglUnbindWaylandDisplayWL(EGLDisplay dpy, struct wl_display *display)
   1525 {
   1526    _EGLDisplay *disp = _eglLockDisplay(dpy);
   1527    _EGLDriver *drv;
   1528    EGLBoolean ret;
   1529 
   1530    _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
   1531    assert(disp->Extensions.WL_bind_wayland_display);
   1532 
   1533    if (!display)
   1534       RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
   1535 
   1536    ret = drv->API.UnbindWaylandDisplayWL(drv, disp, display);
   1537 
   1538    RETURN_EGL_EVAL(disp, ret);
   1539 }
   1540 
   1541 EGLBoolean EGLAPIENTRY
   1542 eglQueryWaylandBufferWL(EGLDisplay dpy,struct wl_buffer *buffer,
   1543                         EGLint attribute, EGLint *value)
   1544 {
   1545    _EGLDisplay *disp = _eglLockDisplay(dpy);
   1546    _EGLDriver *drv;
   1547    EGLBoolean ret;
   1548 
   1549    _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
   1550    assert(disp->Extensions.WL_bind_wayland_display);
   1551 
   1552    if (!buffer)
   1553       RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
   1554 
   1555    ret = drv->API.QueryWaylandBufferWL(drv, disp, buffer, attribute, value);
   1556 
   1557    RETURN_EGL_EVAL(disp, ret);
   1558 }
   1559 #endif
   1560 
   1561 
   1562 EGLBoolean EGLAPIENTRY
   1563 eglPostSubBufferNV(EGLDisplay dpy, EGLSurface surface,
   1564                    EGLint x, EGLint y, EGLint width, EGLint height)
   1565 {
   1566    _EGLDisplay *disp = _eglLockDisplay(dpy);
   1567    _EGLSurface *surf = _eglLookupSurface(surface, disp);
   1568    _EGLDriver *drv;
   1569    EGLBoolean ret;
   1570 
   1571    _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
   1572 
   1573    if (!disp->Extensions.NV_post_sub_buffer)
   1574       RETURN_EGL_EVAL(disp, EGL_FALSE);
   1575 
   1576    ret = drv->API.PostSubBufferNV(drv, disp, surf, x, y, width, height);
   1577 
   1578    RETURN_EGL_EVAL(disp, ret);
   1579 }
   1580