Home | History | Annotate | Download | only in dri2
      1 /*
      2  * Copyright  2010 Intel Corporation
      3  *
      4  * Permission is hereby granted, free of charge, to any person obtaining a
      5  * copy of this software and associated documentation files (the "Software"),
      6  * to deal in the Software without restriction, including without limitation
      7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      8  * and/or sell copies of the Software, and to permit persons to whom the
      9  * Software is furnished to do so, subject to the following conditions:
     10  *
     11  * The above copyright notice and this permission notice (including the next
     12  * paragraph) shall be included in all copies or substantial portions of the
     13  * Software.
     14  *
     15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
     18  * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
     19  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
     20  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     22  * DEALINGS IN THE SOFTWARE.
     23  *
     24  * Authors:
     25  *    Kristian Hgsberg <krh (at) bitplanet.net>
     26  */
     27 
     28 #include <stdbool.h>
     29 #include <stdint.h>
     30 #include <stdbool.h>
     31 #include <stdlib.h>
     32 #include <string.h>
     33 #include <stdio.h>
     34 #include <limits.h>
     35 #include <dlfcn.h>
     36 #include <fcntl.h>
     37 #include <errno.h>
     38 #include <unistd.h>
     39 #include <c11/threads.h>
     40 #include <time.h>
     41 #ifdef HAVE_LIBDRM
     42 #include <xf86drm.h>
     43 #include <drm_fourcc.h>
     44 #endif
     45 #include <GL/gl.h>
     46 #include <GL/internal/dri_interface.h>
     47 #include <sys/types.h>
     48 #include <sys/stat.h>
     49 
     50 #ifdef HAVE_WAYLAND_PLATFORM
     51 #include "wayland-drm.h"
     52 #include "wayland-drm-client-protocol.h"
     53 #include "linux-dmabuf-unstable-v1-client-protocol.h"
     54 #endif
     55 
     56 #ifdef HAVE_X11_PLATFORM
     57 #include "X11/Xlibint.h"
     58 #endif
     59 
     60 #include "egl_dri2.h"
     61 #include "GL/mesa_glinterop.h"
     62 #include "loader/loader.h"
     63 #include "util/u_atomic.h"
     64 #include "util/u_vector.h"
     65 #include "mapi/glapi/glapi.h"
     66 
     67 /* The kernel header drm_fourcc.h defines the DRM formats below.  We duplicate
     68  * some of the definitions here so that building Mesa won't bleeding-edge
     69  * kernel headers.
     70  */
     71 #ifndef DRM_FORMAT_R8
     72 #define DRM_FORMAT_R8            fourcc_code('R', '8', ' ', ' ') /* [7:0] R */
     73 #endif
     74 
     75 #ifndef DRM_FORMAT_RG88
     76 #define DRM_FORMAT_RG88          fourcc_code('R', 'G', '8', '8') /* [15:0] R:G 8:8 little endian */
     77 #endif
     78 
     79 #ifndef DRM_FORMAT_GR88
     80 #define DRM_FORMAT_GR88          fourcc_code('G', 'R', '8', '8') /* [15:0] G:R 8:8 little endian */
     81 #endif
     82 
     83 #ifndef DRM_FORMAT_R16
     84 #define DRM_FORMAT_R16           fourcc_code('R', '1', '6', ' ') /* [15:0] R 16 little endian */
     85 #endif
     86 
     87 #ifndef DRM_FORMAT_GR1616
     88 #define DRM_FORMAT_GR1616        fourcc_code('G', 'R', '3', '2') /* [31:0] R:G 16:16 little endian */
     89 #endif
     90 
     91 #ifndef DRM_FORMAT_MOD_INVALID
     92 #define DRM_FORMAT_MOD_INVALID ((1ULL<<56) - 1)
     93 #endif
     94 
     95 #define NUM_ATTRIBS 12
     96 
     97 static void
     98 dri_set_background_context(void *loaderPrivate)
     99 {
    100    _EGLContext *ctx = _eglGetCurrentContext();
    101    _EGLThreadInfo *t = _eglGetCurrentThread();
    102 
    103    _eglBindContextToThread(ctx, t);
    104 }
    105 
    106 static void
    107 dri2_gl_flush()
    108 {
    109    static void (*glFlush)(void);
    110    static mtx_t glFlushMutex = _MTX_INITIALIZER_NP;
    111 
    112    mtx_lock(&glFlushMutex);
    113    if (!glFlush)
    114       glFlush = _glapi_get_proc_address("glFlush");
    115    mtx_unlock(&glFlushMutex);
    116 
    117    /* if glFlush is not available things are horribly broken */
    118    if (!glFlush) {
    119       _eglLog(_EGL_WARNING, "DRI2: failed to find glFlush entry point");
    120       return;
    121    }
    122 
    123    glFlush();
    124 }
    125 
    126 static GLboolean
    127 dri_is_thread_safe(void *loaderPrivate)
    128 {
    129    struct dri2_egl_surface *dri2_surf = loaderPrivate;
    130    _EGLDisplay *display =  dri2_surf->base.Resource.Display;
    131 
    132 #ifdef HAVE_X11_PLATFORM
    133    Display *xdpy = (Display*)display->PlatformDisplay;
    134 
    135    /* Check Xlib is running in thread safe mode when running on EGL/X11-xlib
    136     * platform
    137     *
    138     * 'lock_fns' is the XLockDisplay function pointer of the X11 display 'dpy'.
    139     * It wll be NULL if XInitThreads wasn't called.
    140     */
    141    if (display->Platform == _EGL_PLATFORM_X11 && xdpy && !xdpy->lock_fns)
    142       return false;
    143 #endif
    144 
    145 #ifdef HAVE_WAYLAND_PLATFORM
    146    if (display->Platform == _EGL_PLATFORM_WAYLAND)
    147       return true;
    148 #endif
    149 
    150    return true;
    151 }
    152 
    153 const __DRIbackgroundCallableExtension background_callable_extension = {
    154    .base = { __DRI_BACKGROUND_CALLABLE, 2 },
    155 
    156    .setBackgroundContext = dri_set_background_context,
    157    .isThreadSafe         = dri_is_thread_safe,
    158 };
    159 
    160 const __DRIuseInvalidateExtension use_invalidate = {
    161    .base = { __DRI_USE_INVALIDATE, 1 }
    162 };
    163 
    164 static const EGLint dri2_to_egl_attribute_map[__DRI_ATTRIB_MAX] = {
    165    [__DRI_ATTRIB_BUFFER_SIZE ]          = EGL_BUFFER_SIZE,
    166    [__DRI_ATTRIB_LEVEL]                 = EGL_LEVEL,
    167    [__DRI_ATTRIB_RED_SIZE]              = EGL_RED_SIZE,
    168    [__DRI_ATTRIB_GREEN_SIZE]            = EGL_GREEN_SIZE,
    169    [__DRI_ATTRIB_BLUE_SIZE]             = EGL_BLUE_SIZE,
    170    [__DRI_ATTRIB_LUMINANCE_SIZE]        = EGL_LUMINANCE_SIZE,
    171    [__DRI_ATTRIB_ALPHA_SIZE]            = EGL_ALPHA_SIZE,
    172    [__DRI_ATTRIB_DEPTH_SIZE]            = EGL_DEPTH_SIZE,
    173    [__DRI_ATTRIB_STENCIL_SIZE]          = EGL_STENCIL_SIZE,
    174    [__DRI_ATTRIB_SAMPLE_BUFFERS]        = EGL_SAMPLE_BUFFERS,
    175    [__DRI_ATTRIB_SAMPLES]               = EGL_SAMPLES,
    176    [__DRI_ATTRIB_MAX_PBUFFER_WIDTH]     = EGL_MAX_PBUFFER_WIDTH,
    177    [__DRI_ATTRIB_MAX_PBUFFER_HEIGHT]    = EGL_MAX_PBUFFER_HEIGHT,
    178    [__DRI_ATTRIB_MAX_PBUFFER_PIXELS]    = EGL_MAX_PBUFFER_PIXELS,
    179    [__DRI_ATTRIB_MAX_SWAP_INTERVAL]     = EGL_MAX_SWAP_INTERVAL,
    180    [__DRI_ATTRIB_MIN_SWAP_INTERVAL]     = EGL_MIN_SWAP_INTERVAL,
    181    [__DRI_ATTRIB_YINVERTED]             = EGL_Y_INVERTED_NOK,
    182 };
    183 
    184 const __DRIconfig *
    185 dri2_get_dri_config(struct dri2_egl_config *conf, EGLint surface_type,
    186                     EGLenum colorspace)
    187 {
    188    const bool double_buffer = surface_type == EGL_WINDOW_BIT;
    189    const bool srgb = colorspace == EGL_GL_COLORSPACE_SRGB_KHR;
    190 
    191    return conf->dri_config[double_buffer][srgb];
    192 }
    193 
    194 static EGLBoolean
    195 dri2_match_config(const _EGLConfig *conf, const _EGLConfig *criteria)
    196 {
    197    if (_eglCompareConfigs(conf, criteria, NULL, EGL_FALSE) != 0)
    198       return EGL_FALSE;
    199 
    200    if (!_eglMatchConfig(conf, criteria))
    201       return EGL_FALSE;
    202 
    203    return EGL_TRUE;
    204 }
    205 
    206 struct dri2_egl_config *
    207 dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id,
    208                 EGLint surface_type, const EGLint *attr_list,
    209                 const unsigned int *rgba_masks)
    210 {
    211    struct dri2_egl_config *conf;
    212    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
    213    _EGLConfig base;
    214    unsigned int attrib, value, double_buffer;
    215    bool srgb = false;
    216    EGLint key, bind_to_texture_rgb, bind_to_texture_rgba;
    217    unsigned int dri_masks[4] = { 0, 0, 0, 0 };
    218    _EGLConfig *matching_config;
    219    EGLint num_configs = 0;
    220    EGLint config_id;
    221 
    222    _eglInitConfig(&base, disp, id);
    223 
    224    double_buffer = 0;
    225    bind_to_texture_rgb = 0;
    226    bind_to_texture_rgba = 0;
    227 
    228    for (int i = 0; dri2_dpy->core->indexConfigAttrib(dri_config, i, &attrib,
    229                                                      &value); ++i) {
    230       switch (attrib) {
    231       case __DRI_ATTRIB_RENDER_TYPE:
    232          if (value & __DRI_ATTRIB_RGBA_BIT)
    233             value = EGL_RGB_BUFFER;
    234          else if (value & __DRI_ATTRIB_LUMINANCE_BIT)
    235             value = EGL_LUMINANCE_BUFFER;
    236          else
    237             return NULL;
    238          _eglSetConfigKey(&base, EGL_COLOR_BUFFER_TYPE, value);
    239          break;
    240 
    241       case __DRI_ATTRIB_CONFIG_CAVEAT:
    242          if (value & __DRI_ATTRIB_NON_CONFORMANT_CONFIG)
    243             value = EGL_NON_CONFORMANT_CONFIG;
    244          else if (value & __DRI_ATTRIB_SLOW_BIT)
    245             value = EGL_SLOW_CONFIG;
    246          else
    247             value = EGL_NONE;
    248          _eglSetConfigKey(&base, EGL_CONFIG_CAVEAT, value);
    249          break;
    250 
    251       case __DRI_ATTRIB_BIND_TO_TEXTURE_RGB:
    252          bind_to_texture_rgb = value;
    253          break;
    254 
    255       case __DRI_ATTRIB_BIND_TO_TEXTURE_RGBA:
    256          bind_to_texture_rgba = value;
    257          break;
    258 
    259       case __DRI_ATTRIB_DOUBLE_BUFFER:
    260          double_buffer = value;
    261          break;
    262 
    263       case __DRI_ATTRIB_RED_MASK:
    264          dri_masks[0] = value;
    265          break;
    266 
    267       case __DRI_ATTRIB_GREEN_MASK:
    268          dri_masks[1] = value;
    269          break;
    270 
    271       case __DRI_ATTRIB_BLUE_MASK:
    272          dri_masks[2] = value;
    273          break;
    274 
    275       case __DRI_ATTRIB_ALPHA_MASK:
    276          dri_masks[3] = value;
    277          break;
    278 
    279       case __DRI_ATTRIB_ACCUM_RED_SIZE:
    280       case __DRI_ATTRIB_ACCUM_GREEN_SIZE:
    281       case __DRI_ATTRIB_ACCUM_BLUE_SIZE:
    282       case __DRI_ATTRIB_ACCUM_ALPHA_SIZE:
    283          /* Don't expose visuals with the accumulation buffer. */
    284          if (value > 0)
    285             return NULL;
    286          break;
    287 
    288       case __DRI_ATTRIB_FRAMEBUFFER_SRGB_CAPABLE:
    289          srgb = value != 0;
    290          if (!disp->Extensions.KHR_gl_colorspace && srgb)
    291             return NULL;
    292          break;
    293 
    294       case __DRI_ATTRIB_MAX_PBUFFER_WIDTH:
    295          _eglSetConfigKey(&base, EGL_MAX_PBUFFER_WIDTH,
    296                           _EGL_MAX_PBUFFER_WIDTH);
    297          break;
    298       case __DRI_ATTRIB_MAX_PBUFFER_HEIGHT:
    299          _eglSetConfigKey(&base, EGL_MAX_PBUFFER_HEIGHT,
    300                           _EGL_MAX_PBUFFER_HEIGHT);
    301          break;
    302 
    303       default:
    304          key = dri2_to_egl_attribute_map[attrib];
    305          if (key != 0)
    306             _eglSetConfigKey(&base, key, value);
    307          break;
    308       }
    309    }
    310 
    311    if (attr_list)
    312       for (int i = 0; attr_list[i] != EGL_NONE; i += 2)
    313          _eglSetConfigKey(&base, attr_list[i], attr_list[i+1]);
    314 
    315    if (rgba_masks && memcmp(rgba_masks, dri_masks, sizeof(dri_masks)))
    316       return NULL;
    317 
    318    base.NativeRenderable = EGL_TRUE;
    319 
    320    base.SurfaceType = surface_type;
    321    if (surface_type & (EGL_PBUFFER_BIT |
    322        (disp->Extensions.NOK_texture_from_pixmap ? EGL_PIXMAP_BIT : 0))) {
    323       base.BindToTextureRGB = bind_to_texture_rgb;
    324       if (base.AlphaSize > 0)
    325          base.BindToTextureRGBA = bind_to_texture_rgba;
    326    }
    327 
    328    base.RenderableType = disp->ClientAPIs;
    329    base.Conformant = disp->ClientAPIs;
    330 
    331    base.MinSwapInterval = dri2_dpy->min_swap_interval;
    332    base.MaxSwapInterval = dri2_dpy->max_swap_interval;
    333 
    334    if (!_eglValidateConfig(&base, EGL_FALSE)) {
    335       _eglLog(_EGL_DEBUG, "DRI2: failed to validate config %d", id);
    336       return NULL;
    337    }
    338 
    339    config_id = base.ConfigID;
    340    base.ConfigID    = EGL_DONT_CARE;
    341    base.SurfaceType = EGL_DONT_CARE;
    342    num_configs = _eglFilterArray(disp->Configs, (void **) &matching_config, 1,
    343                                  (_EGLArrayForEach) dri2_match_config, &base);
    344 
    345    if (num_configs == 1) {
    346       conf = (struct dri2_egl_config *) matching_config;
    347 
    348       if (!conf->dri_config[double_buffer][srgb])
    349          conf->dri_config[double_buffer][srgb] = dri_config;
    350       else
    351          /* a similar config type is already added (unlikely) => discard */
    352          return NULL;
    353    }
    354    else if (num_configs == 0) {
    355       conf = calloc(1, sizeof *conf);
    356       if (conf == NULL)
    357          return NULL;
    358 
    359       conf->dri_config[double_buffer][srgb] = dri_config;
    360 
    361       memcpy(&conf->base, &base, sizeof base);
    362       conf->base.SurfaceType = 0;
    363       conf->base.ConfigID = config_id;
    364 
    365       _eglLinkConfig(&conf->base);
    366    }
    367    else {
    368       assert(0);
    369       return NULL;
    370    }
    371 
    372    if (double_buffer) {
    373       surface_type &= ~EGL_PIXMAP_BIT;
    374    }
    375 
    376    /* No support for pbuffer + MSAA for now.
    377     *
    378     * XXX TODO: pbuffer + MSAA does not work and causes crashes.
    379     * See QT bugreport: https://bugreports.qt.io/browse/QTBUG-47509
    380     */
    381    if (base.Samples) {
    382       surface_type &= ~EGL_PBUFFER_BIT;
    383    }
    384 
    385    conf->base.SurfaceType |= surface_type;
    386 
    387    return conf;
    388 }
    389 
    390 __DRIimage *
    391 dri2_lookup_egl_image(__DRIscreen *screen, void *image, void *data)
    392 {
    393    _EGLDisplay *disp = data;
    394    struct dri2_egl_image *dri2_img;
    395    _EGLImage *img;
    396 
    397    (void) screen;
    398 
    399    img = _eglLookupImage(image, disp);
    400    if (img == NULL) {
    401       _eglError(EGL_BAD_PARAMETER, "dri2_lookup_egl_image");
    402       return NULL;
    403    }
    404 
    405    dri2_img = dri2_egl_image(image);
    406 
    407    return dri2_img->dri_image;
    408 }
    409 
    410 const __DRIimageLookupExtension image_lookup_extension = {
    411    .base = { __DRI_IMAGE_LOOKUP, 1 },
    412 
    413    .lookupEGLImage       = dri2_lookup_egl_image
    414 };
    415 
    416 struct dri2_extension_match {
    417    const char *name;
    418    int version;
    419    int offset;
    420 };
    421 
    422 static const struct dri2_extension_match dri3_driver_extensions[] = {
    423    { __DRI_CORE, 1, offsetof(struct dri2_egl_display, core) },
    424    { __DRI_IMAGE_DRIVER, 1, offsetof(struct dri2_egl_display, image_driver) },
    425    { NULL, 0, 0 }
    426 };
    427 
    428 static const struct dri2_extension_match dri2_driver_extensions[] = {
    429    { __DRI_CORE, 1, offsetof(struct dri2_egl_display, core) },
    430    { __DRI_DRI2, 2, offsetof(struct dri2_egl_display, dri2) },
    431    { NULL, 0, 0 }
    432 };
    433 
    434 static const struct dri2_extension_match dri2_core_extensions[] = {
    435    { __DRI2_FLUSH, 1, offsetof(struct dri2_egl_display, flush) },
    436    { __DRI_TEX_BUFFER, 2, offsetof(struct dri2_egl_display, tex_buffer) },
    437    { __DRI_IMAGE, 1, offsetof(struct dri2_egl_display, image) },
    438    { NULL, 0, 0 }
    439 };
    440 
    441 static const struct dri2_extension_match swrast_driver_extensions[] = {
    442    { __DRI_CORE, 1, offsetof(struct dri2_egl_display, core) },
    443    { __DRI_SWRAST, 2, offsetof(struct dri2_egl_display, swrast) },
    444    { NULL, 0, 0 }
    445 };
    446 
    447 static const struct dri2_extension_match swrast_core_extensions[] = {
    448    { __DRI_TEX_BUFFER, 2, offsetof(struct dri2_egl_display, tex_buffer) },
    449    { NULL, 0, 0 }
    450 };
    451 
    452 static const struct dri2_extension_match optional_core_extensions[] = {
    453    { __DRI2_ROBUSTNESS, 1, offsetof(struct dri2_egl_display, robustness) },
    454    { __DRI2_NO_ERROR, 1, offsetof(struct dri2_egl_display, no_error) },
    455    { __DRI2_CONFIG_QUERY, 1, offsetof(struct dri2_egl_display, config) },
    456    { __DRI2_FENCE, 1, offsetof(struct dri2_egl_display, fence) },
    457    { __DRI2_RENDERER_QUERY, 1, offsetof(struct dri2_egl_display, rendererQuery) },
    458    { __DRI2_INTEROP, 1, offsetof(struct dri2_egl_display, interop) },
    459    { __DRI_IMAGE, 1, offsetof(struct dri2_egl_display, image) },
    460    { __DRI2_FLUSH_CONTROL, 1, offsetof(struct dri2_egl_display, flush_control) },
    461    { NULL, 0, 0 }
    462 };
    463 
    464 static EGLBoolean
    465 dri2_bind_extensions(struct dri2_egl_display *dri2_dpy,
    466                      const struct dri2_extension_match *matches,
    467                      const __DRIextension **extensions,
    468                      bool optional)
    469 {
    470    int ret = EGL_TRUE;
    471    void *field;
    472 
    473    for (int i = 0; extensions[i]; i++) {
    474       _eglLog(_EGL_DEBUG, "found extension `%s'", extensions[i]->name);
    475       for (int j = 0; matches[j].name; j++) {
    476          if (strcmp(extensions[i]->name, matches[j].name) == 0 &&
    477              extensions[i]->version >= matches[j].version) {
    478             field = ((char *) dri2_dpy + matches[j].offset);
    479             *(const __DRIextension **) field = extensions[i];
    480             _eglLog(_EGL_INFO, "found extension %s version %d",
    481                     extensions[i]->name, extensions[i]->version);
    482             break;
    483          }
    484       }
    485    }
    486 
    487    for (int j = 0; matches[j].name; j++) {
    488       field = ((char *) dri2_dpy + matches[j].offset);
    489       if (*(const __DRIextension **) field == NULL) {
    490          if (optional) {
    491             _eglLog(_EGL_DEBUG, "did not find optional extension %s version %d",
    492                     matches[j].name, matches[j].version);
    493          } else {
    494             _eglLog(_EGL_WARNING, "did not find extension %s version %d",
    495                     matches[j].name, matches[j].version);
    496             ret = EGL_FALSE;
    497          }
    498       }
    499    }
    500 
    501    return ret;
    502 }
    503 
    504 static const __DRIextension **
    505 dri2_open_driver(_EGLDisplay *disp)
    506 {
    507    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
    508    const __DRIextension **extensions = NULL;
    509    char path[PATH_MAX], *search_paths, *next, *end;
    510    char *get_extensions_name;
    511    const __DRIextension **(*get_extensions)(void);
    512 
    513    search_paths = NULL;
    514    if (geteuid() == getuid()) {
    515       /* don't allow setuid apps to use LIBGL_DRIVERS_PATH */
    516       search_paths = getenv("LIBGL_DRIVERS_PATH");
    517    }
    518    if (search_paths == NULL)
    519       search_paths = DEFAULT_DRIVER_DIR;
    520 
    521    dri2_dpy->driver = NULL;
    522    end = search_paths + strlen(search_paths);
    523    for (char *p = search_paths; p < end; p = next + 1) {
    524       int len;
    525       next = strchr(p, ':');
    526       if (next == NULL)
    527          next = end;
    528 
    529       len = next - p;
    530 #if GLX_USE_TLS
    531       snprintf(path, sizeof path,
    532                "%.*s/tls/%s_dri.so", len, p, dri2_dpy->driver_name);
    533       dri2_dpy->driver = dlopen(path, RTLD_NOW | RTLD_GLOBAL);
    534 #endif
    535       if (dri2_dpy->driver == NULL) {
    536          snprintf(path, sizeof path,
    537                   "%.*s/%s_dri.so", len, p, dri2_dpy->driver_name);
    538          dri2_dpy->driver = dlopen(path, RTLD_NOW | RTLD_GLOBAL);
    539          if (dri2_dpy->driver == NULL)
    540             _eglLog(_EGL_DEBUG, "failed to open %s: %s\n", path, dlerror());
    541       }
    542       /* not need continue to loop all paths once the driver is found */
    543       if (dri2_dpy->driver != NULL)
    544          break;
    545    }
    546 
    547    if (dri2_dpy->driver == NULL) {
    548       _eglLog(_EGL_WARNING,
    549               "DRI2: failed to open %s (search paths %s)",
    550               dri2_dpy->driver_name, search_paths);
    551       return NULL;
    552    }
    553 
    554    _eglLog(_EGL_DEBUG, "DRI2: dlopen(%s)", path);
    555 
    556    get_extensions_name = loader_get_extensions_name(dri2_dpy->driver_name);
    557    if (get_extensions_name) {
    558       get_extensions = dlsym(dri2_dpy->driver, get_extensions_name);
    559       if (get_extensions) {
    560          extensions = get_extensions();
    561       } else {
    562          _eglLog(_EGL_DEBUG, "driver does not expose %s(): %s\n",
    563                  get_extensions_name, dlerror());
    564       }
    565       free(get_extensions_name);
    566    }
    567 
    568    if (!extensions)
    569       extensions = dlsym(dri2_dpy->driver, __DRI_DRIVER_EXTENSIONS);
    570    if (extensions == NULL) {
    571       _eglLog(_EGL_WARNING,
    572               "DRI2: driver exports no extensions (%s)", dlerror());
    573       dlclose(dri2_dpy->driver);
    574    }
    575 
    576    return extensions;
    577 }
    578 
    579 EGLBoolean
    580 dri2_load_driver_dri3(_EGLDisplay *disp)
    581 {
    582    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
    583    const __DRIextension **extensions;
    584 
    585    extensions = dri2_open_driver(disp);
    586    if (!extensions)
    587       return EGL_FALSE;
    588 
    589    if (!dri2_bind_extensions(dri2_dpy, dri3_driver_extensions, extensions, false)) {
    590       dlclose(dri2_dpy->driver);
    591       return EGL_FALSE;
    592    }
    593    dri2_dpy->driver_extensions = extensions;
    594 
    595    return EGL_TRUE;
    596 }
    597 
    598 EGLBoolean
    599 dri2_load_driver(_EGLDisplay *disp)
    600 {
    601    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
    602    const __DRIextension **extensions;
    603 
    604    extensions = dri2_open_driver(disp);
    605    if (!extensions)
    606       return EGL_FALSE;
    607 
    608    if (!dri2_bind_extensions(dri2_dpy, dri2_driver_extensions, extensions, false)) {
    609       dlclose(dri2_dpy->driver);
    610       return EGL_FALSE;
    611    }
    612    dri2_dpy->driver_extensions = extensions;
    613 
    614    return EGL_TRUE;
    615 }
    616 
    617 EGLBoolean
    618 dri2_load_driver_swrast(_EGLDisplay *disp)
    619 {
    620    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
    621    const __DRIextension **extensions;
    622 
    623    extensions = dri2_open_driver(disp);
    624    if (!extensions)
    625       return EGL_FALSE;
    626 
    627    if (!dri2_bind_extensions(dri2_dpy, swrast_driver_extensions, extensions, false)) {
    628       dlclose(dri2_dpy->driver);
    629       return EGL_FALSE;
    630    }
    631    dri2_dpy->driver_extensions = extensions;
    632 
    633    return EGL_TRUE;
    634 }
    635 
    636 static unsigned
    637 dri2_renderer_query_integer(struct dri2_egl_display *dri2_dpy, int param)
    638 {
    639    const __DRI2rendererQueryExtension *rendererQuery = dri2_dpy->rendererQuery;
    640    unsigned int value = 0;
    641 
    642    if (!rendererQuery ||
    643        rendererQuery->queryInteger(dri2_dpy->dri_screen, param, &value) == -1)
    644       return 0;
    645 
    646    return value;
    647 }
    648 
    649 void
    650 dri2_setup_screen(_EGLDisplay *disp)
    651 {
    652    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
    653    unsigned int api_mask;
    654 
    655    /*
    656     * EGL 1.5 specification defines the default value to 1. Moreover,
    657     * eglSwapInterval() is required to clamp requested value to the supported
    658     * range. Since the default value is implicitly assumed to be supported,
    659     * use it as both minimum and maximum for the platforms that do not allow
    660     * changing the interval. Platforms, which allow it (e.g. x11, wayland)
    661     * override these values already.
    662     */
    663    dri2_dpy->min_swap_interval = 1;
    664    dri2_dpy->max_swap_interval = 1;
    665    dri2_dpy->default_swap_interval = 1;
    666 
    667    if (dri2_dpy->image_driver) {
    668       api_mask = dri2_dpy->image_driver->getAPIMask(dri2_dpy->dri_screen);
    669    } else if (dri2_dpy->dri2) {
    670       api_mask = dri2_dpy->dri2->getAPIMask(dri2_dpy->dri_screen);
    671    } else {
    672       assert(dri2_dpy->swrast);
    673       api_mask = 1 << __DRI_API_OPENGL |
    674                  1 << __DRI_API_GLES |
    675                  1 << __DRI_API_GLES2 |
    676                  1 << __DRI_API_GLES3;
    677    }
    678 
    679    disp->ClientAPIs = 0;
    680    if ((api_mask & (1 <<__DRI_API_OPENGL)) && _eglIsApiValid(EGL_OPENGL_API))
    681       disp->ClientAPIs |= EGL_OPENGL_BIT;
    682    if ((api_mask & (1 << __DRI_API_GLES)) && _eglIsApiValid(EGL_OPENGL_ES_API))
    683       disp->ClientAPIs |= EGL_OPENGL_ES_BIT;
    684    if ((api_mask & (1 << __DRI_API_GLES2)) && _eglIsApiValid(EGL_OPENGL_ES_API))
    685       disp->ClientAPIs |= EGL_OPENGL_ES2_BIT;
    686    if ((api_mask & (1 << __DRI_API_GLES3)) && _eglIsApiValid(EGL_OPENGL_ES_API))
    687       disp->ClientAPIs |= EGL_OPENGL_ES3_BIT_KHR;
    688 
    689    assert(dri2_dpy->image_driver || dri2_dpy->dri2 || dri2_dpy->swrast);
    690    disp->Extensions.KHR_no_config_context = EGL_TRUE;
    691    disp->Extensions.KHR_surfaceless_context = EGL_TRUE;
    692 
    693    /* Report back to EGL the bitmask of priorities supported */
    694    disp->Extensions.IMG_context_priority =
    695       dri2_renderer_query_integer(dri2_dpy,
    696                                   __DRI2_RENDERER_HAS_CONTEXT_PRIORITY);
    697 
    698    disp->Extensions.EXT_pixel_format_float = EGL_TRUE;
    699 
    700    if (dri2_renderer_query_integer(dri2_dpy,
    701                                    __DRI2_RENDERER_HAS_FRAMEBUFFER_SRGB))
    702       disp->Extensions.KHR_gl_colorspace = EGL_TRUE;
    703 
    704    if (dri2_dpy->image_driver ||
    705        (dri2_dpy->dri2 && dri2_dpy->dri2->base.version >= 3) ||
    706        (dri2_dpy->swrast && dri2_dpy->swrast->base.version >= 3)) {
    707       disp->Extensions.KHR_create_context = EGL_TRUE;
    708 
    709       if (dri2_dpy->robustness)
    710          disp->Extensions.EXT_create_context_robustness = EGL_TRUE;
    711    }
    712 
    713    if (dri2_dpy->no_error)
    714       disp->Extensions.KHR_create_context_no_error = EGL_TRUE;
    715 
    716    if (dri2_dpy->fence) {
    717       disp->Extensions.KHR_fence_sync = EGL_TRUE;
    718       disp->Extensions.KHR_wait_sync = EGL_TRUE;
    719       if (dri2_dpy->fence->get_fence_from_cl_event)
    720          disp->Extensions.KHR_cl_event2 = EGL_TRUE;
    721       if (dri2_dpy->fence->base.version >= 2 &&
    722           dri2_dpy->fence->get_capabilities) {
    723          unsigned capabilities =
    724             dri2_dpy->fence->get_capabilities(dri2_dpy->dri_screen);
    725          disp->Extensions.ANDROID_native_fence_sync =
    726             (capabilities & __DRI_FENCE_CAP_NATIVE_FD) != 0;
    727       }
    728    }
    729 
    730    disp->Extensions.KHR_reusable_sync = EGL_TRUE;
    731 
    732    if (dri2_dpy->image) {
    733       if (dri2_dpy->image->base.version >= 10 &&
    734           dri2_dpy->image->getCapabilities != NULL) {
    735          int capabilities;
    736 
    737          capabilities = dri2_dpy->image->getCapabilities(dri2_dpy->dri_screen);
    738          disp->Extensions.MESA_drm_image = (capabilities & __DRI_IMAGE_CAP_GLOBAL_NAMES) != 0;
    739 
    740          if (dri2_dpy->image->base.version >= 11)
    741             disp->Extensions.MESA_image_dma_buf_export = EGL_TRUE;
    742       } else {
    743          disp->Extensions.MESA_drm_image = EGL_TRUE;
    744          if (dri2_dpy->image->base.version >= 11)
    745             disp->Extensions.MESA_image_dma_buf_export = EGL_TRUE;
    746       }
    747 
    748       disp->Extensions.KHR_image_base = EGL_TRUE;
    749       disp->Extensions.KHR_gl_renderbuffer_image = EGL_TRUE;
    750       if (dri2_dpy->image->base.version >= 5 &&
    751           dri2_dpy->image->createImageFromTexture) {
    752          disp->Extensions.KHR_gl_texture_2D_image = EGL_TRUE;
    753          disp->Extensions.KHR_gl_texture_cubemap_image = EGL_TRUE;
    754 
    755          if (dri2_renderer_query_integer(dri2_dpy,
    756                                          __DRI2_RENDERER_HAS_TEXTURE_3D))
    757              disp->Extensions.KHR_gl_texture_3D_image = EGL_TRUE;
    758       }
    759 #ifdef HAVE_LIBDRM
    760       if (dri2_dpy->image->base.version >= 8 &&
    761           dri2_dpy->image->createImageFromDmaBufs) {
    762          disp->Extensions.EXT_image_dma_buf_import = EGL_TRUE;
    763       }
    764       if (dri2_dpy->image->base.version >= 15 &&
    765           dri2_dpy->image->createImageFromDmaBufs2 &&
    766           dri2_dpy->image->queryDmaBufFormats &&
    767           dri2_dpy->image->queryDmaBufModifiers) {
    768          disp->Extensions.EXT_image_dma_buf_import_modifiers = EGL_TRUE;
    769       }
    770 #endif
    771    }
    772 
    773    if (dri2_dpy->flush_control)
    774       disp->Extensions.KHR_context_flush_control = EGL_TRUE;
    775 }
    776 
    777 void
    778 dri2_setup_swap_interval(_EGLDisplay *disp, int max_swap_interval)
    779 {
    780    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
    781    GLint vblank_mode = DRI_CONF_VBLANK_DEF_INTERVAL_1;
    782 
    783    /* Allow driconf to override applications.*/
    784    if (dri2_dpy->config)
    785       dri2_dpy->config->configQueryi(dri2_dpy->dri_screen,
    786                                      "vblank_mode", &vblank_mode);
    787    switch (vblank_mode) {
    788    case DRI_CONF_VBLANK_NEVER:
    789       dri2_dpy->min_swap_interval = 0;
    790       dri2_dpy->max_swap_interval = 0;
    791       dri2_dpy->default_swap_interval = 0;
    792       break;
    793    case DRI_CONF_VBLANK_ALWAYS_SYNC:
    794       dri2_dpy->min_swap_interval = 1;
    795       dri2_dpy->max_swap_interval = max_swap_interval;
    796       dri2_dpy->default_swap_interval = 1;
    797       break;
    798    case DRI_CONF_VBLANK_DEF_INTERVAL_0:
    799       dri2_dpy->min_swap_interval = 0;
    800       dri2_dpy->max_swap_interval = max_swap_interval;
    801       dri2_dpy->default_swap_interval = 0;
    802       break;
    803    default:
    804    case DRI_CONF_VBLANK_DEF_INTERVAL_1:
    805       dri2_dpy->min_swap_interval = 0;
    806       dri2_dpy->max_swap_interval = max_swap_interval;
    807       dri2_dpy->default_swap_interval = 1;
    808       break;
    809    }
    810 }
    811 
    812 /* All platforms but DRM call this function to create the screen and populate
    813  * the driver_configs. DRM inherits that information from its display - GBM.
    814  */
    815 EGLBoolean
    816 dri2_create_screen(_EGLDisplay *disp)
    817 {
    818    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
    819 
    820    if (dri2_dpy->image_driver) {
    821       dri2_dpy->dri_screen =
    822          dri2_dpy->image_driver->createNewScreen2(0, dri2_dpy->fd,
    823                                                   dri2_dpy->loader_extensions,
    824                                                   dri2_dpy->driver_extensions,
    825                                                   &dri2_dpy->driver_configs,
    826                                                   disp);
    827    } else if (dri2_dpy->dri2) {
    828       if (dri2_dpy->dri2->base.version >= 4) {
    829          dri2_dpy->dri_screen =
    830             dri2_dpy->dri2->createNewScreen2(0, dri2_dpy->fd,
    831                                              dri2_dpy->loader_extensions,
    832                                              dri2_dpy->driver_extensions,
    833                                              &dri2_dpy->driver_configs, disp);
    834       } else {
    835          dri2_dpy->dri_screen =
    836             dri2_dpy->dri2->createNewScreen(0, dri2_dpy->fd,
    837                                             dri2_dpy->loader_extensions,
    838                                             &dri2_dpy->driver_configs, disp);
    839       }
    840    } else {
    841       assert(dri2_dpy->swrast);
    842       if (dri2_dpy->swrast->base.version >= 4) {
    843          dri2_dpy->dri_screen =
    844             dri2_dpy->swrast->createNewScreen2(0, dri2_dpy->loader_extensions,
    845                                                dri2_dpy->driver_extensions,
    846                                                &dri2_dpy->driver_configs, disp);
    847       } else {
    848          dri2_dpy->dri_screen =
    849             dri2_dpy->swrast->createNewScreen(0, dri2_dpy->loader_extensions,
    850                                               &dri2_dpy->driver_configs, disp);
    851       }
    852    }
    853 
    854    if (dri2_dpy->dri_screen == NULL) {
    855       _eglLog(_EGL_WARNING, "DRI2: failed to create dri screen");
    856       return EGL_FALSE;
    857    }
    858 
    859    dri2_dpy->own_dri_screen = true;
    860    return EGL_TRUE;
    861 }
    862 
    863 EGLBoolean
    864 dri2_setup_extensions(_EGLDisplay *disp)
    865 {
    866    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
    867    const struct dri2_extension_match *mandatory_core_extensions;
    868    const __DRIextension **extensions;
    869 
    870    extensions = dri2_dpy->core->getExtensions(dri2_dpy->dri_screen);
    871 
    872    if (dri2_dpy->image_driver || dri2_dpy->dri2)
    873       mandatory_core_extensions = dri2_core_extensions;
    874    else
    875       mandatory_core_extensions = swrast_core_extensions;
    876 
    877    if (!dri2_bind_extensions(dri2_dpy, mandatory_core_extensions, extensions, false))
    878       return EGL_FALSE;
    879 
    880    dri2_bind_extensions(dri2_dpy, optional_core_extensions, extensions, true);
    881    return EGL_TRUE;
    882 }
    883 
    884 /**
    885  * Called via eglInitialize(), GLX_drv->API.Initialize().
    886  *
    887  * This must be guaranteed to be called exactly once, even if eglInitialize is
    888  * called many times (without a eglTerminate in between).
    889  */
    890 static EGLBoolean
    891 dri2_initialize(_EGLDriver *drv, _EGLDisplay *disp)
    892 {
    893    EGLBoolean ret = EGL_FALSE;
    894    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
    895 
    896    /* In the case where the application calls eglMakeCurrent(context1),
    897     * eglTerminate, then eglInitialize again (without a call to eglReleaseThread
    898     * or eglMakeCurrent(NULL) before that), dri2_dpy structure is still
    899     * initialized, as we need it to be able to free context1 correctly.
    900     *
    901     * It would probably be safest to forcibly release the display with
    902     * dri2_display_release, to make sure the display is reinitialized correctly.
    903     * However, the EGL spec states that we need to keep a reference to the
    904     * current context (so we cannot call dri2_make_current(NULL)), and therefore
    905     * we would leak context1 as we would be missing the old display connection
    906     * to free it up correctly.
    907     */
    908    if (dri2_dpy) {
    909       dri2_dpy->ref_count++;
    910       return EGL_TRUE;
    911    }
    912 
    913    switch (disp->Platform) {
    914    case _EGL_PLATFORM_SURFACELESS:
    915       ret = dri2_initialize_surfaceless(drv, disp);
    916       break;
    917    case _EGL_PLATFORM_X11:
    918       ret = dri2_initialize_x11(drv, disp);
    919       break;
    920    case _EGL_PLATFORM_DRM:
    921       ret = dri2_initialize_drm(drv, disp);
    922       break;
    923    case _EGL_PLATFORM_WAYLAND:
    924       ret = dri2_initialize_wayland(drv, disp);
    925       break;
    926    case _EGL_PLATFORM_ANDROID:
    927       ret = dri2_initialize_android(drv, disp);
    928       break;
    929    default:
    930       unreachable("Callers ensure we cannot get here.");
    931       return EGL_FALSE;
    932    }
    933 
    934    if (!ret)
    935       return EGL_FALSE;
    936 
    937    dri2_dpy = dri2_egl_display(disp);
    938    dri2_dpy->ref_count++;
    939 
    940    return EGL_TRUE;
    941 }
    942 
    943 /**
    944  * Decrement display reference count, and free up display if necessary.
    945  */
    946 static void
    947 dri2_display_release(_EGLDisplay *disp)
    948 {
    949    struct dri2_egl_display *dri2_dpy;
    950 
    951    if (!disp)
    952       return;
    953 
    954    dri2_dpy = dri2_egl_display(disp);
    955 
    956    assert(dri2_dpy->ref_count > 0);
    957    dri2_dpy->ref_count--;
    958 
    959    if (dri2_dpy->ref_count > 0)
    960       return;
    961 
    962    _eglCleanupDisplay(disp);
    963    dri2_display_destroy(disp);
    964 }
    965 
    966 void
    967 dri2_display_destroy(_EGLDisplay *disp)
    968 {
    969    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
    970 
    971    if (dri2_dpy->own_dri_screen) {
    972       if (dri2_dpy->vtbl && dri2_dpy->vtbl->close_screen_notify)
    973          dri2_dpy->vtbl->close_screen_notify(disp);
    974       dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen);
    975    }
    976    if (dri2_dpy->fd >= 0)
    977       close(dri2_dpy->fd);
    978    if (dri2_dpy->driver)
    979       dlclose(dri2_dpy->driver);
    980    free(dri2_dpy->driver_name);
    981 
    982 #ifdef HAVE_WAYLAND_PLATFORM
    983    free(dri2_dpy->device_name);
    984 #endif
    985 
    986    switch (disp->Platform) {
    987    case _EGL_PLATFORM_X11:
    988       dri2_teardown_x11(dri2_dpy);
    989       break;
    990    case _EGL_PLATFORM_DRM:
    991       dri2_teardown_drm(dri2_dpy);
    992       break;
    993    case _EGL_PLATFORM_WAYLAND:
    994       dri2_teardown_wayland(dri2_dpy);
    995       break;
    996    default:
    997       /* TODO: add teardown for other platforms */
    998       break;
    999    }
   1000 
   1001    /* The drm platform does not create the screen/driver_configs but reuses
   1002     * the ones from the gbm device. As such the gbm itself is responsible
   1003     * for the cleanup.
   1004     */
   1005    if (disp->Platform != _EGL_PLATFORM_DRM && dri2_dpy->driver_configs) {
   1006       for (unsigned i = 0; dri2_dpy->driver_configs[i]; i++)
   1007          free((__DRIconfig *) dri2_dpy->driver_configs[i]);
   1008       free(dri2_dpy->driver_configs);
   1009    }
   1010    free(dri2_dpy);
   1011    disp->DriverData = NULL;
   1012 }
   1013 
   1014 __DRIbuffer *
   1015 dri2_egl_surface_alloc_local_buffer(struct dri2_egl_surface *dri2_surf,
   1016                                     unsigned int att, unsigned int format)
   1017 {
   1018    struct dri2_egl_display *dri2_dpy =
   1019       dri2_egl_display(dri2_surf->base.Resource.Display);
   1020 
   1021    if (att >= ARRAY_SIZE(dri2_surf->local_buffers))
   1022       return NULL;
   1023 
   1024    if (!dri2_surf->local_buffers[att]) {
   1025       dri2_surf->local_buffers[att] =
   1026          dri2_dpy->dri2->allocateBuffer(dri2_dpy->dri_screen, att, format,
   1027                                         dri2_surf->base.Width, dri2_surf->base.Height);
   1028    }
   1029 
   1030    return dri2_surf->local_buffers[att];
   1031 }
   1032 
   1033 void
   1034 dri2_egl_surface_free_local_buffers(struct dri2_egl_surface *dri2_surf)
   1035 {
   1036    struct dri2_egl_display *dri2_dpy =
   1037       dri2_egl_display(dri2_surf->base.Resource.Display);
   1038 
   1039    for (int i = 0; i < ARRAY_SIZE(dri2_surf->local_buffers); i++) {
   1040       if (dri2_surf->local_buffers[i]) {
   1041          dri2_dpy->dri2->releaseBuffer(dri2_dpy->dri_screen,
   1042                                        dri2_surf->local_buffers[i]);
   1043          dri2_surf->local_buffers[i] = NULL;
   1044       }
   1045    }
   1046 }
   1047 
   1048 /**
   1049  * Called via eglTerminate(), drv->API.Terminate().
   1050  *
   1051  * This must be guaranteed to be called exactly once, even if eglTerminate is
   1052  * called many times (without a eglInitialize in between).
   1053  */
   1054 static EGLBoolean
   1055 dri2_terminate(_EGLDriver *drv, _EGLDisplay *disp)
   1056 {
   1057    /* Release all non-current Context/Surfaces. */
   1058    _eglReleaseDisplayResources(drv, disp);
   1059 
   1060    dri2_display_release(disp);
   1061 
   1062    return EGL_TRUE;
   1063 }
   1064 
   1065 /**
   1066  * Set the error code after a call to
   1067  * dri2_egl_display::dri2::createContextAttribs.
   1068  */
   1069 static void
   1070 dri2_create_context_attribs_error(int dri_error)
   1071 {
   1072    EGLint egl_error;
   1073 
   1074    switch (dri_error) {
   1075    case __DRI_CTX_ERROR_SUCCESS:
   1076       return;
   1077 
   1078    case __DRI_CTX_ERROR_NO_MEMORY:
   1079       egl_error = EGL_BAD_ALLOC;
   1080       break;
   1081 
   1082   /* From the EGL_KHR_create_context spec, section "Errors":
   1083    *
   1084    *   * If <config> does not support a client API context compatible
   1085    *     with the requested API major and minor version, [...] context flags,
   1086    *     and context reset notification behavior (for client API types where
   1087    *     these attributes are supported), then an EGL_BAD_MATCH error is
   1088    *     generated.
   1089    *
   1090    *   * If an OpenGL ES context is requested and the values for
   1091    *     attributes EGL_CONTEXT_MAJOR_VERSION_KHR and
   1092    *     EGL_CONTEXT_MINOR_VERSION_KHR specify an OpenGL ES version that
   1093    *     is not defined, than an EGL_BAD_MATCH error is generated.
   1094    *
   1095    *   * If an OpenGL context is requested, the requested version is
   1096    *     greater than 3.2, and the value for attribute
   1097    *     EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR has no bits set; has any
   1098    *     bits set other than EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR and
   1099    *     EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR; has more than
   1100    *     one of these bits set; or if the implementation does not support
   1101    *     the requested profile, then an EGL_BAD_MATCH error is generated.
   1102    */
   1103    case __DRI_CTX_ERROR_BAD_API:
   1104    case __DRI_CTX_ERROR_BAD_VERSION:
   1105    case __DRI_CTX_ERROR_BAD_FLAG:
   1106       egl_error = EGL_BAD_MATCH;
   1107       break;
   1108 
   1109   /* From the EGL_KHR_create_context spec, section "Errors":
   1110    *
   1111    *   * If an attribute name or attribute value in <attrib_list> is not
   1112    *     recognized (including unrecognized bits in bitmask attributes),
   1113    *     then an EGL_BAD_ATTRIBUTE error is generated."
   1114    */
   1115    case __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE:
   1116    case __DRI_CTX_ERROR_UNKNOWN_FLAG:
   1117       egl_error = EGL_BAD_ATTRIBUTE;
   1118       break;
   1119 
   1120    default:
   1121       assert(0);
   1122       egl_error = EGL_BAD_MATCH;
   1123       break;
   1124    }
   1125 
   1126    _eglError(egl_error, "dri2_create_context");
   1127 }
   1128 
   1129 static bool
   1130 dri2_fill_context_attribs(struct dri2_egl_context *dri2_ctx,
   1131                           struct dri2_egl_display *dri2_dpy,
   1132                           uint32_t *ctx_attribs,
   1133                           unsigned *num_attribs)
   1134 {
   1135    int pos = 0;
   1136 
   1137    assert(*num_attribs >= NUM_ATTRIBS);
   1138 
   1139    ctx_attribs[pos++] = __DRI_CTX_ATTRIB_MAJOR_VERSION;
   1140    ctx_attribs[pos++] = dri2_ctx->base.ClientMajorVersion;
   1141    ctx_attribs[pos++] = __DRI_CTX_ATTRIB_MINOR_VERSION;
   1142    ctx_attribs[pos++] = dri2_ctx->base.ClientMinorVersion;
   1143 
   1144    if (dri2_ctx->base.Flags != 0 || dri2_ctx->base.NoError) {
   1145       /* If the implementation doesn't support the __DRI2_ROBUSTNESS
   1146        * extension, don't even try to send it the robust-access flag.
   1147        * It may explode.  Instead, generate the required EGL error here.
   1148        */
   1149       if ((dri2_ctx->base.Flags & EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR) != 0
   1150             && !dri2_dpy->robustness) {
   1151          _eglError(EGL_BAD_MATCH, "eglCreateContext");
   1152          return false;
   1153       }
   1154 
   1155       ctx_attribs[pos++] = __DRI_CTX_ATTRIB_FLAGS;
   1156       ctx_attribs[pos++] = dri2_ctx->base.Flags |
   1157          (dri2_ctx->base.NoError ? __DRI_CTX_FLAG_NO_ERROR : 0);
   1158    }
   1159 
   1160    if (dri2_ctx->base.ResetNotificationStrategy != EGL_NO_RESET_NOTIFICATION_KHR) {
   1161       /* If the implementation doesn't support the __DRI2_ROBUSTNESS
   1162        * extension, don't even try to send it a reset strategy.  It may
   1163        * explode.  Instead, generate the required EGL error here.
   1164        */
   1165       if (!dri2_dpy->robustness) {
   1166          _eglError(EGL_BAD_CONFIG, "eglCreateContext");
   1167          return false;
   1168       }
   1169 
   1170       ctx_attribs[pos++] = __DRI_CTX_ATTRIB_RESET_STRATEGY;
   1171       ctx_attribs[pos++] = __DRI_CTX_RESET_LOSE_CONTEXT;
   1172    }
   1173 
   1174    if (dri2_ctx->base.ContextPriority != EGL_CONTEXT_PRIORITY_MEDIUM_IMG) {
   1175       unsigned val;
   1176 
   1177       switch (dri2_ctx->base.ContextPriority) {
   1178       case EGL_CONTEXT_PRIORITY_HIGH_IMG:
   1179          val = __DRI_CTX_PRIORITY_HIGH;
   1180          break;
   1181       case EGL_CONTEXT_PRIORITY_MEDIUM_IMG:
   1182          val = __DRI_CTX_PRIORITY_MEDIUM;
   1183          break;
   1184       case EGL_CONTEXT_PRIORITY_LOW_IMG:
   1185          val = __DRI_CTX_PRIORITY_LOW;
   1186          break;
   1187       default:
   1188          _eglError(EGL_BAD_CONFIG, "eglCreateContext");
   1189          return false;
   1190       }
   1191 
   1192       ctx_attribs[pos++] = __DRI_CTX_ATTRIB_PRIORITY;
   1193       ctx_attribs[pos++] = val;
   1194    }
   1195 
   1196    if (dri2_ctx->base.ReleaseBehavior == EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR) {
   1197       ctx_attribs[pos++] = __DRI_CTX_ATTRIB_RELEASE_BEHAVIOR;
   1198       ctx_attribs[pos++] = __DRI_CTX_RELEASE_BEHAVIOR_NONE;
   1199    }
   1200 
   1201    *num_attribs = pos;
   1202 
   1203    return true;
   1204 }
   1205 
   1206 /**
   1207  * Called via eglCreateContext(), drv->API.CreateContext().
   1208  */
   1209 static _EGLContext *
   1210 dri2_create_context(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf,
   1211                     _EGLContext *share_list, const EGLint *attrib_list)
   1212 {
   1213    struct dri2_egl_context *dri2_ctx;
   1214    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
   1215    struct dri2_egl_context *dri2_ctx_shared = dri2_egl_context(share_list);
   1216    __DRIcontext *shared =
   1217       dri2_ctx_shared ? dri2_ctx_shared->dri_context : NULL;
   1218    struct dri2_egl_config *dri2_config = dri2_egl_config(conf);
   1219    const __DRIconfig *dri_config;
   1220    int api;
   1221    unsigned error;
   1222    unsigned num_attribs = NUM_ATTRIBS;
   1223    uint32_t ctx_attribs[NUM_ATTRIBS];
   1224 
   1225    (void) drv;
   1226 
   1227    dri2_ctx = malloc(sizeof *dri2_ctx);
   1228    if (!dri2_ctx) {
   1229       _eglError(EGL_BAD_ALLOC, "eglCreateContext");
   1230       return NULL;
   1231    }
   1232 
   1233    if (!_eglInitContext(&dri2_ctx->base, disp, conf, attrib_list))
   1234       goto cleanup;
   1235 
   1236    /* The EGL_EXT_create_context_robustness spec says:
   1237     *
   1238     *    "Add to the eglCreateContext context creation errors: [...]
   1239     *
   1240     *     * If the reset notification behavior of <share_context> and the
   1241     *       newly created context are different then an EGL_BAD_MATCH error is
   1242     *       generated."
   1243     */
   1244    if (share_list && share_list->ResetNotificationStrategy !=
   1245                      dri2_ctx->base.ResetNotificationStrategy) {
   1246       _eglError(EGL_BAD_MATCH, "eglCreateContext");
   1247       goto cleanup;
   1248    }
   1249 
   1250    /* The EGL_KHR_create_context_no_error spec says:
   1251     *
   1252     *    "BAD_MATCH is generated if the value of EGL_CONTEXT_OPENGL_NO_ERROR_KHR
   1253     *    used to create <share_context> does not match the value of
   1254     *    EGL_CONTEXT_OPENGL_NO_ERROR_KHR for the context being created."
   1255     */
   1256    if (share_list && share_list->NoError != dri2_ctx->base.NoError) {
   1257       _eglError(EGL_BAD_MATCH, "eglCreateContext");
   1258       goto cleanup;
   1259    }
   1260 
   1261    switch (dri2_ctx->base.ClientAPI) {
   1262    case EGL_OPENGL_ES_API:
   1263       switch (dri2_ctx->base.ClientMajorVersion) {
   1264       case 1:
   1265          api = __DRI_API_GLES;
   1266          break;
   1267       case 2:
   1268          api = __DRI_API_GLES2;
   1269          break;
   1270       case 3:
   1271          api = __DRI_API_GLES3;
   1272          break;
   1273       default:
   1274          _eglError(EGL_BAD_PARAMETER, "eglCreateContext");
   1275          free(dri2_ctx);
   1276          return NULL;
   1277       }
   1278       break;
   1279    case EGL_OPENGL_API:
   1280       if ((dri2_ctx->base.ClientMajorVersion >= 4
   1281            || (dri2_ctx->base.ClientMajorVersion == 3
   1282                && dri2_ctx->base.ClientMinorVersion >= 2))
   1283           && dri2_ctx->base.Profile == EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR)
   1284          api = __DRI_API_OPENGL_CORE;
   1285       else
   1286          api = __DRI_API_OPENGL;
   1287       break;
   1288    default:
   1289       _eglError(EGL_BAD_PARAMETER, "eglCreateContext");
   1290       free(dri2_ctx);
   1291       return NULL;
   1292    }
   1293 
   1294    if (conf != NULL) {
   1295       /* The config chosen here isn't necessarily
   1296        * used for surfaces later.
   1297        * A pixmap surface will use the single config.
   1298        * This opportunity depends on disabling the
   1299        * doubleBufferMode check in
   1300        * src/mesa/main/context.c:check_compatible()
   1301        */
   1302       if (dri2_config->dri_config[1][0])
   1303          dri_config = dri2_config->dri_config[1][0];
   1304       else
   1305          dri_config = dri2_config->dri_config[0][0];
   1306 
   1307       /* EGL_WINDOW_BIT is set only when there is a double-buffered dri_config.
   1308        * This makes sure the back buffer will always be used.
   1309        */
   1310       if (conf->SurfaceType & EGL_WINDOW_BIT)
   1311          dri2_ctx->base.WindowRenderBuffer = EGL_BACK_BUFFER;
   1312    }
   1313    else
   1314       dri_config = NULL;
   1315 
   1316    if (!dri2_fill_context_attribs(dri2_ctx, dri2_dpy, ctx_attribs,
   1317                                   &num_attribs))
   1318       goto cleanup;
   1319 
   1320    if (dri2_dpy->image_driver) {
   1321       dri2_ctx->dri_context =
   1322          dri2_dpy->image_driver->createContextAttribs(dri2_dpy->dri_screen,
   1323                                                       api,
   1324                                                       dri_config,
   1325                                                       shared,
   1326                                                       num_attribs / 2,
   1327                                                       ctx_attribs,
   1328                                                       & error,
   1329                                                       dri2_ctx);
   1330       dri2_create_context_attribs_error(error);
   1331    } else if (dri2_dpy->dri2) {
   1332       if (dri2_dpy->dri2->base.version >= 3) {
   1333          dri2_ctx->dri_context =
   1334             dri2_dpy->dri2->createContextAttribs(dri2_dpy->dri_screen,
   1335                                                  api,
   1336                                                  dri_config,
   1337                                                  shared,
   1338                                                  num_attribs / 2,
   1339                                                  ctx_attribs,
   1340                                                  & error,
   1341                                                  dri2_ctx);
   1342          dri2_create_context_attribs_error(error);
   1343       } else {
   1344          dri2_ctx->dri_context =
   1345             dri2_dpy->dri2->createNewContextForAPI(dri2_dpy->dri_screen,
   1346                                                    api,
   1347                                                    dri_config,
   1348                                                    shared,
   1349                                                    dri2_ctx);
   1350       }
   1351    } else {
   1352       assert(dri2_dpy->swrast);
   1353       if (dri2_dpy->swrast->base.version >= 3) {
   1354          dri2_ctx->dri_context =
   1355             dri2_dpy->swrast->createContextAttribs(dri2_dpy->dri_screen,
   1356                                                    api,
   1357                                                    dri_config,
   1358                                                    shared,
   1359                                                    num_attribs / 2,
   1360                                                    ctx_attribs,
   1361                                                    & error,
   1362                                                    dri2_ctx);
   1363          dri2_create_context_attribs_error(error);
   1364       } else {
   1365          dri2_ctx->dri_context =
   1366             dri2_dpy->swrast->createNewContextForAPI(dri2_dpy->dri_screen,
   1367                                                      api,
   1368                                                      dri_config,
   1369                                                      shared,
   1370                                                      dri2_ctx);
   1371       }
   1372    }
   1373 
   1374    if (!dri2_ctx->dri_context)
   1375       goto cleanup;
   1376 
   1377    return &dri2_ctx->base;
   1378 
   1379  cleanup:
   1380    free(dri2_ctx);
   1381    return NULL;
   1382 }
   1383 
   1384 /**
   1385  * Called via eglDestroyContext(), drv->API.DestroyContext().
   1386  */
   1387 static EGLBoolean
   1388 dri2_destroy_context(_EGLDriver *drv, _EGLDisplay *disp, _EGLContext *ctx)
   1389 {
   1390    struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
   1391    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
   1392 
   1393    if (_eglPutContext(ctx)) {
   1394       dri2_dpy->core->destroyContext(dri2_ctx->dri_context);
   1395       free(dri2_ctx);
   1396    }
   1397 
   1398    return EGL_TRUE;
   1399 }
   1400 
   1401 EGLBoolean
   1402 dri2_init_surface(_EGLSurface *surf, _EGLDisplay *dpy, EGLint type,
   1403         _EGLConfig *conf, const EGLint *attrib_list, EGLBoolean enable_out_fence)
   1404 {
   1405    struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
   1406    struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
   1407 
   1408    dri2_surf->out_fence_fd = -1;
   1409    dri2_surf->enable_out_fence = false;
   1410    if (dri2_dpy->fence && dri2_dpy->fence->base.version >= 2 &&
   1411        dri2_dpy->fence->get_capabilities &&
   1412        (dri2_dpy->fence->get_capabilities(dri2_dpy->dri_screen) &
   1413         __DRI_FENCE_CAP_NATIVE_FD)) {
   1414       dri2_surf->enable_out_fence = enable_out_fence;
   1415    }
   1416 
   1417    return _eglInitSurface(surf, dpy, type, conf, attrib_list);
   1418 }
   1419 
   1420 static void
   1421 dri2_surface_set_out_fence_fd( _EGLSurface *surf, int fence_fd)
   1422 {
   1423    struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
   1424 
   1425    if (dri2_surf->out_fence_fd >= 0)
   1426       close(dri2_surf->out_fence_fd);
   1427 
   1428    dri2_surf->out_fence_fd = fence_fd;
   1429 }
   1430 
   1431 void
   1432 dri2_fini_surface(_EGLSurface *surf)
   1433 {
   1434    struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
   1435 
   1436    dri2_surface_set_out_fence_fd(surf, -1);
   1437    dri2_surf->enable_out_fence = false;
   1438 }
   1439 
   1440 static EGLBoolean
   1441 dri2_destroy_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf)
   1442 {
   1443    struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
   1444 
   1445    if (!_eglPutSurface(surf))
   1446       return EGL_TRUE;
   1447 
   1448    return dri2_dpy->vtbl->destroy_surface(drv, dpy, surf);
   1449 }
   1450 
   1451 static void
   1452 dri2_surf_update_fence_fd(_EGLContext *ctx,
   1453                           _EGLDisplay *dpy, _EGLSurface *surf)
   1454 {
   1455    __DRIcontext *dri_ctx = dri2_egl_context(ctx)->dri_context;
   1456    struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
   1457    struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
   1458    int fence_fd = -1;
   1459    void *fence;
   1460 
   1461    if (!dri2_surf->enable_out_fence)
   1462       return;
   1463 
   1464    fence = dri2_dpy->fence->create_fence_fd(dri_ctx, -1);
   1465    if (fence) {
   1466       fence_fd = dri2_dpy->fence->get_fence_fd(dri2_dpy->dri_screen,
   1467                                                fence);
   1468       dri2_dpy->fence->destroy_fence(dri2_dpy->dri_screen, fence);
   1469    }
   1470    dri2_surface_set_out_fence_fd(surf, fence_fd);
   1471 }
   1472 
   1473 /**
   1474  * Called via eglMakeCurrent(), drv->API.MakeCurrent().
   1475  */
   1476 static EGLBoolean
   1477 dri2_make_current(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *dsurf,
   1478                   _EGLSurface *rsurf, _EGLContext *ctx)
   1479 {
   1480    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
   1481    struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
   1482    _EGLContext *old_ctx;
   1483    _EGLSurface *old_dsurf, *old_rsurf;
   1484    _EGLSurface *tmp_dsurf, *tmp_rsurf;
   1485    __DRIdrawable *ddraw, *rdraw;
   1486    __DRIcontext *cctx;
   1487    EGLBoolean unbind;
   1488 
   1489    if (!dri2_dpy)
   1490       return _eglError(EGL_NOT_INITIALIZED, "eglMakeCurrent");
   1491 
   1492    /* make new bindings */
   1493    if (!_eglBindContext(ctx, dsurf, rsurf, &old_ctx, &old_dsurf, &old_rsurf)) {
   1494       /* _eglBindContext already sets the EGL error (in _eglCheckMakeCurrent) */
   1495       return EGL_FALSE;
   1496    }
   1497 
   1498    /* flush before context switch */
   1499    if (old_ctx)
   1500       dri2_gl_flush();
   1501 
   1502    ddraw = (dsurf) ? dri2_dpy->vtbl->get_dri_drawable(dsurf) : NULL;
   1503    rdraw = (rsurf) ? dri2_dpy->vtbl->get_dri_drawable(rsurf) : NULL;
   1504    cctx = (dri2_ctx) ? dri2_ctx->dri_context : NULL;
   1505 
   1506    if (old_ctx) {
   1507       __DRIcontext *old_cctx = dri2_egl_context(old_ctx)->dri_context;
   1508 
   1509       if (old_dsurf)
   1510          dri2_surf_update_fence_fd(old_ctx, disp, old_dsurf);
   1511       dri2_dpy->core->unbindContext(old_cctx);
   1512    }
   1513 
   1514    unbind = (cctx == NULL && ddraw == NULL && rdraw == NULL);
   1515 
   1516    if (unbind || dri2_dpy->core->bindContext(cctx, ddraw, rdraw)) {
   1517       dri2_destroy_surface(drv, disp, old_dsurf);
   1518       dri2_destroy_surface(drv, disp, old_rsurf);
   1519 
   1520       if (!unbind)
   1521          dri2_dpy->ref_count++;
   1522       if (old_ctx) {
   1523          EGLDisplay old_disp = _eglGetDisplayHandle(old_ctx->Resource.Display);
   1524          dri2_destroy_context(drv, disp, old_ctx);
   1525          dri2_display_release(old_disp);
   1526       }
   1527 
   1528       return EGL_TRUE;
   1529    } else {
   1530       /* undo the previous _eglBindContext */
   1531       _eglBindContext(old_ctx, old_dsurf, old_rsurf, &ctx, &tmp_dsurf, &tmp_rsurf);
   1532       assert(&dri2_ctx->base == ctx &&
   1533              tmp_dsurf == dsurf &&
   1534              tmp_rsurf == rsurf);
   1535 
   1536       _eglPutSurface(dsurf);
   1537       _eglPutSurface(rsurf);
   1538       _eglPutContext(ctx);
   1539 
   1540       _eglPutSurface(old_dsurf);
   1541       _eglPutSurface(old_rsurf);
   1542       _eglPutContext(old_ctx);
   1543 
   1544       /* dri2_dpy->core->bindContext failed. We cannot tell for sure why, but
   1545        * setting the error to EGL_BAD_MATCH is surely better than leaving it
   1546        * as EGL_SUCCESS.
   1547        */
   1548       return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
   1549    }
   1550 }
   1551 
   1552 __DRIdrawable *
   1553 dri2_surface_get_dri_drawable(_EGLSurface *surf)
   1554 {
   1555    struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
   1556 
   1557    return dri2_surf->dri_drawable;
   1558 }
   1559 
   1560 /*
   1561  * Called from eglGetProcAddress() via drv->API.GetProcAddress().
   1562  */
   1563 static _EGLProc
   1564 dri2_get_proc_address(_EGLDriver *drv, const char *procname)
   1565 {
   1566    return _glapi_get_proc_address(procname);
   1567 }
   1568 
   1569 static _EGLSurface*
   1570 dri2_create_window_surface(_EGLDriver *drv, _EGLDisplay *dpy,
   1571                            _EGLConfig *conf, void *native_window,
   1572                            const EGLint *attrib_list)
   1573 {
   1574    struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
   1575    return dri2_dpy->vtbl->create_window_surface(drv, dpy, conf, native_window,
   1576                                                 attrib_list);
   1577 }
   1578 
   1579 static _EGLSurface*
   1580 dri2_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *dpy,
   1581                            _EGLConfig *conf, void *native_pixmap,
   1582                            const EGLint *attrib_list)
   1583 {
   1584    struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
   1585    return dri2_dpy->vtbl->create_pixmap_surface(drv, dpy, conf, native_pixmap,
   1586                                                 attrib_list);
   1587 }
   1588 
   1589 static _EGLSurface*
   1590 dri2_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *dpy,
   1591                            _EGLConfig *conf, const EGLint *attrib_list)
   1592 {
   1593    struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
   1594    return dri2_dpy->vtbl->create_pbuffer_surface(drv, dpy, conf, attrib_list);
   1595 }
   1596 
   1597 static EGLBoolean
   1598 dri2_swap_interval(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
   1599                    EGLint interval)
   1600 {
   1601    struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
   1602    if (!dri2_dpy->vtbl->swap_interval)
   1603       return EGL_TRUE;
   1604    return dri2_dpy->vtbl->swap_interval(drv, dpy, surf, interval);
   1605 }
   1606 
   1607 /**
   1608  * Asks the client API to flush any rendering to the drawable so that we can
   1609  * do our swapbuffers.
   1610  */
   1611 void
   1612 dri2_flush_drawable_for_swapbuffers(_EGLDisplay *disp, _EGLSurface *draw)
   1613 {
   1614    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
   1615    __DRIdrawable *dri_drawable = dri2_dpy->vtbl->get_dri_drawable(draw);
   1616 
   1617    if (dri2_dpy->flush) {
   1618       if (dri2_dpy->flush->base.version >= 4) {
   1619          /* We know there's a current context because:
   1620           *
   1621           *     "If surface is not bound to the calling threads current
   1622           *      context, an EGL_BAD_SURFACE error is generated."
   1623          */
   1624          _EGLContext *ctx = _eglGetCurrentContext();
   1625          struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
   1626 
   1627          /* From the EGL 1.4 spec (page 52):
   1628           *
   1629           *     "The contents of ancillary buffers are always undefined
   1630           *      after calling eglSwapBuffers."
   1631           */
   1632          dri2_dpy->flush->flush_with_flags(dri2_ctx->dri_context,
   1633                                            dri_drawable,
   1634                                            __DRI2_FLUSH_DRAWABLE |
   1635                                            __DRI2_FLUSH_INVALIDATE_ANCILLARY,
   1636                                            __DRI2_THROTTLE_SWAPBUFFER);
   1637       } else {
   1638          dri2_dpy->flush->flush(dri_drawable);
   1639       }
   1640    }
   1641 }
   1642 
   1643 static EGLBoolean
   1644 dri2_swap_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf)
   1645 {
   1646    struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
   1647    _EGLContext *ctx = _eglGetCurrentContext();
   1648 
   1649    if (ctx && surf)
   1650       dri2_surf_update_fence_fd(ctx, dpy, surf);
   1651    return dri2_dpy->vtbl->swap_buffers(drv, dpy, surf);
   1652 }
   1653 
   1654 static EGLBoolean
   1655 dri2_swap_buffers_with_damage(_EGLDriver *drv, _EGLDisplay *dpy,
   1656                               _EGLSurface *surf,
   1657                               const EGLint *rects, EGLint n_rects)
   1658 {
   1659    struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
   1660    _EGLContext *ctx = _eglGetCurrentContext();
   1661 
   1662    if (ctx && surf)
   1663       dri2_surf_update_fence_fd(ctx, dpy, surf);
   1664    return dri2_dpy->vtbl->swap_buffers_with_damage(drv, dpy, surf,
   1665                                                    rects, n_rects);
   1666 }
   1667 
   1668 static EGLBoolean
   1669 dri2_swap_buffers_region(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
   1670                          EGLint numRects, const EGLint *rects)
   1671 {
   1672    struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
   1673    return dri2_dpy->vtbl->swap_buffers_region(drv, dpy, surf, numRects, rects);
   1674 }
   1675 
   1676 static EGLBoolean
   1677 dri2_set_damage_region(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
   1678                        EGLint *rects, EGLint n_rects)
   1679 {
   1680    struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
   1681    return dri2_dpy->vtbl->set_damage_region(drv, dpy, surf, rects, n_rects);
   1682 }
   1683 
   1684 static EGLBoolean
   1685 dri2_post_sub_buffer(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
   1686                      EGLint x, EGLint y, EGLint width, EGLint height)
   1687 {
   1688    struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
   1689    return dri2_dpy->vtbl->post_sub_buffer(drv, dpy, surf, x, y, width, height);
   1690 }
   1691 
   1692 static EGLBoolean
   1693 dri2_copy_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
   1694                   void *native_pixmap_target)
   1695 {
   1696    struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
   1697    return dri2_dpy->vtbl->copy_buffers(drv, dpy, surf, native_pixmap_target);
   1698 }
   1699 
   1700 static EGLint
   1701 dri2_query_buffer_age(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf)
   1702 {
   1703    struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
   1704    return dri2_dpy->vtbl->query_buffer_age(drv, dpy, surf);
   1705 }
   1706 
   1707 static EGLBoolean
   1708 dri2_wait_client(_EGLDriver *drv, _EGLDisplay *disp, _EGLContext *ctx)
   1709 {
   1710    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
   1711    _EGLSurface *surf = ctx->DrawSurface;
   1712    __DRIdrawable *dri_drawable = dri2_dpy->vtbl->get_dri_drawable(surf);
   1713 
   1714    (void) drv;
   1715 
   1716    /* FIXME: If EGL allows frontbuffer rendering for window surfaces,
   1717     * we need to copy fake to real here.*/
   1718 
   1719    if (dri2_dpy->flush != NULL)
   1720       dri2_dpy->flush->flush(dri_drawable);
   1721 
   1722    return EGL_TRUE;
   1723 }
   1724 
   1725 static EGLBoolean
   1726 dri2_wait_native(_EGLDriver *drv, _EGLDisplay *disp, EGLint engine)
   1727 {
   1728    (void) drv;
   1729    (void) disp;
   1730 
   1731    if (engine != EGL_CORE_NATIVE_ENGINE)
   1732       return _eglError(EGL_BAD_PARAMETER, "eglWaitNative");
   1733    /* glXWaitX(); */
   1734 
   1735    return EGL_TRUE;
   1736 }
   1737 
   1738 static EGLBoolean
   1739 dri2_bind_tex_image(_EGLDriver *drv,
   1740                     _EGLDisplay *disp, _EGLSurface *surf, EGLint buffer)
   1741 {
   1742    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
   1743    struct dri2_egl_context *dri2_ctx;
   1744    _EGLContext *ctx;
   1745    GLint format, target;
   1746    __DRIdrawable *dri_drawable = dri2_dpy->vtbl->get_dri_drawable(surf);
   1747 
   1748    ctx = _eglGetCurrentContext();
   1749    dri2_ctx = dri2_egl_context(ctx);
   1750 
   1751    if (!_eglBindTexImage(drv, disp, surf, buffer))
   1752       return EGL_FALSE;
   1753 
   1754    switch (surf->TextureFormat) {
   1755    case EGL_TEXTURE_RGB:
   1756       format = __DRI_TEXTURE_FORMAT_RGB;
   1757       break;
   1758    case EGL_TEXTURE_RGBA:
   1759       format = __DRI_TEXTURE_FORMAT_RGBA;
   1760       break;
   1761    default:
   1762       assert(!"Unexpected texture format in dri2_bind_tex_image()");
   1763       format = __DRI_TEXTURE_FORMAT_RGBA;
   1764    }
   1765 
   1766    switch (surf->TextureTarget) {
   1767    case EGL_TEXTURE_2D:
   1768       target = GL_TEXTURE_2D;
   1769       break;
   1770    default:
   1771       target = GL_TEXTURE_2D;
   1772       assert(!"Unexpected texture target in dri2_bind_tex_image()");
   1773    }
   1774 
   1775    dri2_dpy->tex_buffer->setTexBuffer2(dri2_ctx->dri_context,
   1776                                        target, format,
   1777                                        dri_drawable);
   1778 
   1779    return EGL_TRUE;
   1780 }
   1781 
   1782 static EGLBoolean
   1783 dri2_release_tex_image(_EGLDriver *drv,
   1784                        _EGLDisplay *disp, _EGLSurface *surf, EGLint buffer)
   1785 {
   1786    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
   1787    struct dri2_egl_context *dri2_ctx;
   1788    _EGLContext *ctx;
   1789    GLint  target;
   1790    __DRIdrawable *dri_drawable = dri2_dpy->vtbl->get_dri_drawable(surf);
   1791 
   1792    ctx = _eglGetCurrentContext();
   1793    dri2_ctx = dri2_egl_context(ctx);
   1794 
   1795    if (!_eglReleaseTexImage(drv, disp, surf, buffer))
   1796       return EGL_FALSE;
   1797 
   1798    switch (surf->TextureTarget) {
   1799    case EGL_TEXTURE_2D:
   1800       target = GL_TEXTURE_2D;
   1801       break;
   1802    default:
   1803       assert(0);
   1804    }
   1805 
   1806    if (dri2_dpy->tex_buffer->base.version >= 3 &&
   1807        dri2_dpy->tex_buffer->releaseTexBuffer != NULL) {
   1808       dri2_dpy->tex_buffer->releaseTexBuffer(dri2_ctx->dri_context,
   1809                                              target, dri_drawable);
   1810    }
   1811 
   1812    return EGL_TRUE;
   1813 }
   1814 
   1815 static _EGLImage*
   1816 dri2_create_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx,
   1817                   EGLenum target, EGLClientBuffer buffer,
   1818                   const EGLint *attr_list)
   1819 {
   1820    struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
   1821    return dri2_dpy->vtbl->create_image(drv, dpy, ctx, target, buffer,
   1822                                        attr_list);
   1823 }
   1824 
   1825 static _EGLImage *
   1826 dri2_create_image_from_dri(_EGLDisplay *disp, __DRIimage *dri_image)
   1827 {
   1828    struct dri2_egl_image *dri2_img;
   1829 
   1830    if (dri_image == NULL) {
   1831       _eglError(EGL_BAD_ALLOC, "dri2_create_image");
   1832       return NULL;
   1833    }
   1834 
   1835    dri2_img = malloc(sizeof *dri2_img);
   1836    if (!dri2_img) {
   1837       _eglError(EGL_BAD_ALLOC, "dri2_create_image");
   1838       return NULL;
   1839    }
   1840 
   1841    _eglInitImage(&dri2_img->base, disp);
   1842 
   1843    dri2_img->dri_image = dri_image;
   1844 
   1845    return &dri2_img->base;
   1846 }
   1847 
   1848 /**
   1849  * Translate a DRI Image extension error code into an EGL error code.
   1850  */
   1851 static EGLint
   1852 egl_error_from_dri_image_error(int dri_error)
   1853 {
   1854    switch (dri_error) {
   1855    case __DRI_IMAGE_ERROR_SUCCESS:
   1856       return EGL_SUCCESS;
   1857    case __DRI_IMAGE_ERROR_BAD_ALLOC:
   1858       return EGL_BAD_ALLOC;
   1859    case __DRI_IMAGE_ERROR_BAD_MATCH:
   1860       return EGL_BAD_MATCH;
   1861    case __DRI_IMAGE_ERROR_BAD_PARAMETER:
   1862       return EGL_BAD_PARAMETER;
   1863    case __DRI_IMAGE_ERROR_BAD_ACCESS:
   1864       return EGL_BAD_ACCESS;
   1865    default:
   1866       assert(0);
   1867       return EGL_BAD_ALLOC;
   1868    }
   1869 }
   1870 
   1871 static _EGLImage *
   1872 dri2_create_image_khr_renderbuffer(_EGLDisplay *disp, _EGLContext *ctx,
   1873                                    EGLClientBuffer buffer,
   1874                                    const EGLint *attr_list)
   1875 {
   1876    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
   1877    struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
   1878    GLuint renderbuffer = (GLuint) (uintptr_t) buffer;
   1879    __DRIimage *dri_image;
   1880 
   1881    if (renderbuffer == 0) {
   1882       _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
   1883       return EGL_NO_IMAGE_KHR;
   1884    }
   1885 
   1886    if (!disp->Extensions.KHR_gl_renderbuffer_image) {
   1887       _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
   1888       return EGL_NO_IMAGE_KHR;
   1889    }
   1890 
   1891    if (dri2_dpy->image->base.version >= 17 &&
   1892        dri2_dpy->image->createImageFromRenderbuffer2) {
   1893       unsigned error = ~0;
   1894 
   1895       dri_image = dri2_dpy->image->createImageFromRenderbuffer2(
   1896                dri2_ctx->dri_context, renderbuffer, NULL, &error);
   1897 
   1898       assert(!!dri_image == (error == __DRI_IMAGE_ERROR_SUCCESS));
   1899 
   1900       if (!dri_image) {
   1901          _eglError(egl_error_from_dri_image_error(error), "dri2_create_image_khr");
   1902          return EGL_NO_IMAGE_KHR;
   1903       }
   1904    } else {
   1905       dri_image = dri2_dpy->image->createImageFromRenderbuffer(
   1906                dri2_ctx->dri_context, renderbuffer, NULL);
   1907       if (!dri_image) {
   1908          _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr");
   1909          return EGL_NO_IMAGE_KHR;
   1910       }
   1911    }
   1912 
   1913    return dri2_create_image_from_dri(disp, dri_image);
   1914 }
   1915 
   1916 #ifdef HAVE_WAYLAND_PLATFORM
   1917 
   1918 /* This structure describes how a wl_buffer maps to one or more
   1919  * __DRIimages.  A wl_drm_buffer stores the wl_drm format code and the
   1920  * offsets and strides of the planes in the buffer.  This table maps a
   1921  * wl_drm format code to a description of the planes in the buffer
   1922  * that lets us create a __DRIimage for each of the planes. */
   1923 
   1924 static const struct wl_drm_components_descriptor {
   1925    uint32_t dri_components;
   1926    EGLint components;
   1927    int nplanes;
   1928 } wl_drm_components[] = {
   1929    { __DRI_IMAGE_COMPONENTS_RGB, EGL_TEXTURE_RGB, 1 },
   1930    { __DRI_IMAGE_COMPONENTS_RGBA, EGL_TEXTURE_RGBA, 1 },
   1931    { __DRI_IMAGE_COMPONENTS_Y_U_V, EGL_TEXTURE_Y_U_V_WL, 3 },
   1932    { __DRI_IMAGE_COMPONENTS_Y_UV, EGL_TEXTURE_Y_UV_WL, 2 },
   1933    { __DRI_IMAGE_COMPONENTS_Y_XUXV, EGL_TEXTURE_Y_XUXV_WL, 2 },
   1934 };
   1935 
   1936 static _EGLImage *
   1937 dri2_create_image_wayland_wl_buffer(_EGLDisplay *disp, _EGLContext *ctx,
   1938                                     EGLClientBuffer _buffer,
   1939                                     const EGLint *attr_list)
   1940 {
   1941    struct wl_drm_buffer *buffer;
   1942    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
   1943    const struct wl_drm_components_descriptor *f;
   1944    __DRIimage *dri_image;
   1945    _EGLImageAttribs attrs;
   1946    int32_t plane;
   1947 
   1948    buffer = wayland_drm_buffer_get(dri2_dpy->wl_server_drm,
   1949                                    (struct wl_resource *) _buffer);
   1950    if (!buffer)
   1951        return NULL;
   1952 
   1953    if (!_eglParseImageAttribList(&attrs, disp, attr_list))
   1954       return NULL;
   1955 
   1956    plane = attrs.PlaneWL;
   1957    f = buffer->driver_format;
   1958    if (plane < 0 || plane >= f->nplanes) {
   1959       _eglError(EGL_BAD_PARAMETER,
   1960                 "dri2_create_image_wayland_wl_buffer (plane out of bounds)");
   1961       return NULL;
   1962    }
   1963 
   1964    dri_image = dri2_dpy->image->fromPlanar(buffer->driver_buffer, plane, NULL);
   1965 
   1966    if (dri_image == NULL) {
   1967       _eglError(EGL_BAD_PARAMETER, "dri2_create_image_wayland_wl_buffer");
   1968       return NULL;
   1969    }
   1970 
   1971    return dri2_create_image_from_dri(disp, dri_image);
   1972 }
   1973 #endif
   1974 
   1975 static EGLBoolean
   1976 dri2_get_sync_values_chromium(_EGLDisplay *dpy, _EGLSurface *surf,
   1977                               EGLuint64KHR *ust, EGLuint64KHR *msc,
   1978                               EGLuint64KHR *sbc)
   1979 {
   1980    struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
   1981    return dri2_dpy->vtbl->get_sync_values(dpy, surf, ust, msc, sbc);
   1982 }
   1983 
   1984 /**
   1985  * Set the error code after a call to
   1986  * dri2_egl_image::dri_image::createImageFromTexture.
   1987  */
   1988 static void
   1989 dri2_create_image_khr_texture_error(int dri_error)
   1990 {
   1991    EGLint egl_error = egl_error_from_dri_image_error(dri_error);
   1992 
   1993    if (egl_error != EGL_SUCCESS)
   1994       _eglError(egl_error, "dri2_create_image_khr_texture");
   1995 }
   1996 
   1997 static _EGLImage *
   1998 dri2_create_image_khr_texture(_EGLDisplay *disp, _EGLContext *ctx,
   1999                                    EGLenum target,
   2000                                    EGLClientBuffer buffer,
   2001                                    const EGLint *attr_list)
   2002 {
   2003    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
   2004    struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
   2005    struct dri2_egl_image *dri2_img;
   2006    GLuint texture = (GLuint) (uintptr_t) buffer;
   2007    _EGLImageAttribs attrs;
   2008    GLuint depth;
   2009    GLenum gl_target;
   2010    unsigned error;
   2011 
   2012    if (texture == 0) {
   2013       _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
   2014       return EGL_NO_IMAGE_KHR;
   2015    }
   2016 
   2017    if (!_eglParseImageAttribList(&attrs, disp, attr_list))
   2018       return EGL_NO_IMAGE_KHR;
   2019 
   2020    switch (target) {
   2021    case EGL_GL_TEXTURE_2D_KHR:
   2022       if (!disp->Extensions.KHR_gl_texture_2D_image) {
   2023          _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
   2024          return EGL_NO_IMAGE_KHR;
   2025       }
   2026       depth = 0;
   2027       gl_target = GL_TEXTURE_2D;
   2028       break;
   2029    case EGL_GL_TEXTURE_3D_KHR:
   2030       if (!disp->Extensions.KHR_gl_texture_3D_image) {
   2031          _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
   2032          return EGL_NO_IMAGE_KHR;
   2033       }
   2034 
   2035       depth = attrs.GLTextureZOffset;
   2036       gl_target = GL_TEXTURE_3D;
   2037       break;
   2038    case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:
   2039    case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:
   2040    case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:
   2041    case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:
   2042    case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:
   2043    case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:
   2044       if (!disp->Extensions.KHR_gl_texture_cubemap_image) {
   2045          _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
   2046          return EGL_NO_IMAGE_KHR;
   2047       }
   2048 
   2049       depth = target - EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR;
   2050       gl_target = GL_TEXTURE_CUBE_MAP;
   2051       break;
   2052    default:
   2053       unreachable("Unexpected target in dri2_create_image_khr_texture()");
   2054       return EGL_NO_IMAGE_KHR;
   2055    }
   2056 
   2057    dri2_img = malloc(sizeof *dri2_img);
   2058    if (!dri2_img) {
   2059       _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr");
   2060       return EGL_NO_IMAGE_KHR;
   2061    }
   2062 
   2063    _eglInitImage(&dri2_img->base, disp);
   2064 
   2065    dri2_img->dri_image =
   2066       dri2_dpy->image->createImageFromTexture(dri2_ctx->dri_context,
   2067                                               gl_target,
   2068                                               texture,
   2069                                               depth,
   2070                                               attrs.GLTextureLevel,
   2071                                               &error,
   2072                                               dri2_img);
   2073    dri2_create_image_khr_texture_error(error);
   2074 
   2075    if (!dri2_img->dri_image) {
   2076       free(dri2_img);
   2077       return EGL_NO_IMAGE_KHR;
   2078    }
   2079    return &dri2_img->base;
   2080 }
   2081 
   2082 static EGLBoolean
   2083 dri2_query_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
   2084                    EGLint attribute, EGLint *value)
   2085 {
   2086    struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
   2087    if (!dri2_dpy->vtbl->query_surface)
   2088       return _eglQuerySurface(drv, dpy, surf, attribute, value);
   2089    return dri2_dpy->vtbl->query_surface(drv, dpy, surf, attribute, value);
   2090 }
   2091 
   2092 static struct wl_buffer*
   2093 dri2_create_wayland_buffer_from_image(_EGLDriver *drv, _EGLDisplay *dpy,
   2094                                       _EGLImage *img)
   2095 {
   2096    struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
   2097    return dri2_dpy->vtbl->create_wayland_buffer_from_image(drv, dpy, img);
   2098 }
   2099 
   2100 #ifdef HAVE_LIBDRM
   2101 static _EGLImage *
   2102 dri2_create_image_mesa_drm_buffer(_EGLDisplay *disp, _EGLContext *ctx,
   2103                                   EGLClientBuffer buffer, const EGLint *attr_list)
   2104 {
   2105    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
   2106    EGLint format, name, pitch;
   2107    _EGLImageAttribs attrs;
   2108    __DRIimage *dri_image;
   2109 
   2110    name = (EGLint) (uintptr_t) buffer;
   2111 
   2112    if (!_eglParseImageAttribList(&attrs, disp, attr_list))
   2113       return NULL;
   2114 
   2115    if (attrs.Width <= 0 || attrs.Height <= 0 ||
   2116        attrs.DRMBufferStrideMESA <= 0) {
   2117       _eglError(EGL_BAD_PARAMETER,
   2118                 "bad width, height or stride");
   2119       return NULL;
   2120    }
   2121 
   2122    switch (attrs.DRMBufferFormatMESA) {
   2123    case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA:
   2124       format = __DRI_IMAGE_FORMAT_ARGB8888;
   2125       pitch = attrs.DRMBufferStrideMESA;
   2126       break;
   2127    default:
   2128       _eglError(EGL_BAD_PARAMETER,
   2129                 "dri2_create_image_khr: unsupported pixmap depth");
   2130       return NULL;
   2131    }
   2132 
   2133    dri_image =
   2134       dri2_dpy->image->createImageFromName(dri2_dpy->dri_screen,
   2135                                            attrs.Width,
   2136                                            attrs.Height,
   2137                                            format,
   2138                                            name,
   2139                                            pitch,
   2140                                            NULL);
   2141 
   2142    return dri2_create_image_from_dri(disp, dri_image);
   2143 }
   2144 
   2145 static EGLBoolean
   2146 dri2_check_dma_buf_attribs(const _EGLImageAttribs *attrs)
   2147 {
   2148    /**
   2149      * The spec says:
   2150      *
   2151      * "Required attributes and their values are as follows:
   2152      *
   2153      *  * EGL_WIDTH & EGL_HEIGHT: The logical dimensions of the buffer in pixels
   2154      *
   2155      *  * EGL_LINUX_DRM_FOURCC_EXT: The pixel format of the buffer, as specified
   2156      *    by drm_fourcc.h and used as the pixel_format parameter of the
   2157      *    drm_mode_fb_cmd2 ioctl."
   2158      *
   2159      * and
   2160      *
   2161      * "* If <target> is EGL_LINUX_DMA_BUF_EXT, and the list of attributes is
   2162      *    incomplete, EGL_BAD_PARAMETER is generated."
   2163      */
   2164    if (attrs->Width <= 0 || attrs->Height <= 0 ||
   2165        !attrs->DMABufFourCC.IsPresent)
   2166       return _eglError(EGL_BAD_PARAMETER, "attribute(s) missing");
   2167 
   2168    /**
   2169     * Also:
   2170     *
   2171     * "If <target> is EGL_LINUX_DMA_BUF_EXT and one or more of the values
   2172     *  specified for a plane's pitch or offset isn't supported by EGL,
   2173     *  EGL_BAD_ACCESS is generated."
   2174     */
   2175    for (unsigned i = 0; i < ARRAY_SIZE(attrs->DMABufPlanePitches); ++i) {
   2176       if (attrs->DMABufPlanePitches[i].IsPresent &&
   2177           attrs->DMABufPlanePitches[i].Value <= 0)
   2178          return _eglError(EGL_BAD_ACCESS, "invalid pitch");
   2179    }
   2180 
   2181    /**
   2182     * If <target> is EGL_LINUX_DMA_BUF_EXT, both or neither of the following
   2183     * attribute values may be given.
   2184     *
   2185     * This is referring to EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT and
   2186     * EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT, and the same for other planes.
   2187     */
   2188    for (unsigned i = 0; i < DMA_BUF_MAX_PLANES; ++i) {
   2189       if (attrs->DMABufPlaneModifiersLo[i].IsPresent !=
   2190           attrs->DMABufPlaneModifiersHi[i].IsPresent)
   2191          return _eglError(EGL_BAD_PARAMETER, "modifier attribute lo or hi missing");
   2192    }
   2193 
   2194    /* Although the EGL_EXT_image_dma_buf_import_modifiers spec doesn't
   2195     * mandate it, we only accept the same modifier across all planes. */
   2196    for (unsigned i = 1; i < DMA_BUF_MAX_PLANES; ++i) {
   2197       if (attrs->DMABufPlaneFds[i].IsPresent) {
   2198          if ((attrs->DMABufPlaneModifiersLo[0].IsPresent !=
   2199                attrs->DMABufPlaneModifiersLo[i].IsPresent) ||
   2200              (attrs->DMABufPlaneModifiersLo[0].Value !=
   2201                attrs->DMABufPlaneModifiersLo[i].Value) ||
   2202              (attrs->DMABufPlaneModifiersHi[0].Value !=
   2203                attrs->DMABufPlaneModifiersHi[i].Value))
   2204             return _eglError(EGL_BAD_PARAMETER, "modifier attributes not equal");
   2205       }
   2206    }
   2207 
   2208    return EGL_TRUE;
   2209 }
   2210 
   2211 /* Returns the total number of file descriptors. Zero indicates an error. */
   2212 static unsigned
   2213 dri2_check_dma_buf_format(const _EGLImageAttribs *attrs)
   2214 {
   2215    unsigned plane_n;
   2216 
   2217    switch (attrs->DMABufFourCC.Value) {
   2218    case DRM_FORMAT_R8:
   2219    case DRM_FORMAT_RG88:
   2220    case DRM_FORMAT_GR88:
   2221    case DRM_FORMAT_R16:
   2222    case DRM_FORMAT_GR1616:
   2223    case DRM_FORMAT_RGB332:
   2224    case DRM_FORMAT_BGR233:
   2225    case DRM_FORMAT_XRGB4444:
   2226    case DRM_FORMAT_XBGR4444:
   2227    case DRM_FORMAT_RGBX4444:
   2228    case DRM_FORMAT_BGRX4444:
   2229    case DRM_FORMAT_ARGB4444:
   2230    case DRM_FORMAT_ABGR4444:
   2231    case DRM_FORMAT_RGBA4444:
   2232    case DRM_FORMAT_BGRA4444:
   2233    case DRM_FORMAT_XRGB1555:
   2234    case DRM_FORMAT_XBGR1555:
   2235    case DRM_FORMAT_RGBX5551:
   2236    case DRM_FORMAT_BGRX5551:
   2237    case DRM_FORMAT_ARGB1555:
   2238    case DRM_FORMAT_ABGR1555:
   2239    case DRM_FORMAT_RGBA5551:
   2240    case DRM_FORMAT_BGRA5551:
   2241    case DRM_FORMAT_RGB565:
   2242    case DRM_FORMAT_BGR565:
   2243    case DRM_FORMAT_RGB888:
   2244    case DRM_FORMAT_BGR888:
   2245    case DRM_FORMAT_XRGB8888:
   2246    case DRM_FORMAT_XBGR8888:
   2247    case DRM_FORMAT_RGBX8888:
   2248    case DRM_FORMAT_BGRX8888:
   2249    case DRM_FORMAT_ARGB8888:
   2250    case DRM_FORMAT_ABGR8888:
   2251    case DRM_FORMAT_RGBA8888:
   2252    case DRM_FORMAT_BGRA8888:
   2253    case DRM_FORMAT_XRGB2101010:
   2254    case DRM_FORMAT_XBGR2101010:
   2255    case DRM_FORMAT_RGBX1010102:
   2256    case DRM_FORMAT_BGRX1010102:
   2257    case DRM_FORMAT_ARGB2101010:
   2258    case DRM_FORMAT_ABGR2101010:
   2259    case DRM_FORMAT_RGBA1010102:
   2260    case DRM_FORMAT_BGRA1010102:
   2261    case DRM_FORMAT_YUYV:
   2262    case DRM_FORMAT_YVYU:
   2263    case DRM_FORMAT_UYVY:
   2264    case DRM_FORMAT_VYUY:
   2265       plane_n = 1;
   2266       break;
   2267    case DRM_FORMAT_NV12:
   2268    case DRM_FORMAT_NV21:
   2269    case DRM_FORMAT_NV16:
   2270    case DRM_FORMAT_NV61:
   2271       plane_n = 2;
   2272       break;
   2273    case DRM_FORMAT_YUV410:
   2274    case DRM_FORMAT_YVU410:
   2275    case DRM_FORMAT_YUV411:
   2276    case DRM_FORMAT_YVU411:
   2277    case DRM_FORMAT_YUV420:
   2278    case DRM_FORMAT_YVU420:
   2279    case DRM_FORMAT_YUV422:
   2280    case DRM_FORMAT_YVU422:
   2281    case DRM_FORMAT_YUV444:
   2282    case DRM_FORMAT_YVU444:
   2283       plane_n = 3;
   2284       break;
   2285    default:
   2286       _eglError(EGL_BAD_ATTRIBUTE, "invalid format");
   2287       return 0;
   2288    }
   2289 
   2290    for (unsigned i = plane_n; i < DMA_BUF_MAX_PLANES; i++) {
   2291       /**
   2292        * The modifiers extension spec says:
   2293        *
   2294        * "Modifiers may modify any attribute of a buffer import, including
   2295        *  but not limited to adding extra planes to a format which
   2296        *  otherwise does not have those planes. As an example, a modifier
   2297        *  may add a plane for an external compression buffer to a
   2298        *  single-plane format. The exact meaning and effect of any
   2299        *  modifier is canonically defined by drm_fourcc.h, not as part of
   2300        *  this extension."
   2301        */
   2302       if (attrs->DMABufPlaneModifiersLo[i].IsPresent &&
   2303           attrs->DMABufPlaneModifiersHi[i].IsPresent) {
   2304          plane_n = i + 1;
   2305       }
   2306    }
   2307 
   2308    /**
   2309      * The spec says:
   2310      *
   2311      * "* If <target> is EGL_LINUX_DMA_BUF_EXT, and the list of attributes is
   2312      *    incomplete, EGL_BAD_PARAMETER is generated."
   2313      */
   2314    for (unsigned i = 0; i < plane_n; ++i) {
   2315       if (!attrs->DMABufPlaneFds[i].IsPresent ||
   2316           !attrs->DMABufPlaneOffsets[i].IsPresent ||
   2317           !attrs->DMABufPlanePitches[i].IsPresent) {
   2318          _eglError(EGL_BAD_PARAMETER, "plane attribute(s) missing");
   2319          return 0;
   2320       }
   2321    }
   2322 
   2323    /**
   2324     * The spec also says:
   2325     *
   2326     * "If <target> is EGL_LINUX_DMA_BUF_EXT, and the EGL_LINUX_DRM_FOURCC_EXT
   2327     *  attribute indicates a single-plane format, EGL_BAD_ATTRIBUTE is
   2328     *  generated if any of the EGL_DMA_BUF_PLANE1_* or EGL_DMA_BUF_PLANE2_*
   2329     *  or EGL_DMA_BUF_PLANE3_* attributes are specified."
   2330     */
   2331    for (unsigned i = plane_n; i < DMA_BUF_MAX_PLANES; ++i) {
   2332       if (attrs->DMABufPlaneFds[i].IsPresent ||
   2333           attrs->DMABufPlaneOffsets[i].IsPresent ||
   2334           attrs->DMABufPlanePitches[i].IsPresent) {
   2335          _eglError(EGL_BAD_ATTRIBUTE, "too many plane attributes");
   2336          return 0;
   2337       }
   2338    }
   2339 
   2340    return plane_n;
   2341 }
   2342 
   2343 static EGLBoolean
   2344 dri2_query_dma_buf_formats(_EGLDriver *drv, _EGLDisplay *disp,
   2345                             EGLint max, EGLint *formats, EGLint *count)
   2346 {
   2347    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
   2348    if (max < 0 || (max > 0 && formats == NULL))
   2349       return _eglError(EGL_BAD_PARAMETER, "invalid value for max count of formats");
   2350 
   2351    if (dri2_dpy->image->base.version < 15 ||
   2352        dri2_dpy->image->queryDmaBufFormats == NULL)
   2353       return EGL_FALSE;
   2354 
   2355    if (!dri2_dpy->image->queryDmaBufFormats(dri2_dpy->dri_screen, max,
   2356                                             formats, count))
   2357       return EGL_FALSE;
   2358 
   2359    return EGL_TRUE;
   2360 }
   2361 
   2362 static EGLBoolean
   2363 dri2_query_dma_buf_modifiers(_EGLDriver *drv, _EGLDisplay *disp, EGLint format,
   2364                              EGLint max, EGLuint64KHR *modifiers,
   2365                              EGLBoolean *external_only, EGLint *count)
   2366 {
   2367    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
   2368 
   2369    if (max < 0)
   2370       return _eglError(EGL_BAD_PARAMETER, "invalid value for max count of formats");
   2371 
   2372    if (max > 0 && modifiers == NULL)
   2373       return _eglError(EGL_BAD_PARAMETER, "invalid modifiers array");
   2374 
   2375    if (dri2_dpy->image->base.version < 15 ||
   2376        dri2_dpy->image->queryDmaBufModifiers == NULL)
   2377       return EGL_FALSE;
   2378 
   2379    if (dri2_dpy->image->queryDmaBufModifiers(dri2_dpy->dri_screen, format,
   2380                                              max, modifiers,
   2381                                              (unsigned int *) external_only,
   2382                                              count) == false)
   2383       return _eglError(EGL_BAD_PARAMETER, "invalid format");
   2384 
   2385    return EGL_TRUE;
   2386 }
   2387 
   2388 /**
   2389  * The spec says:
   2390  *
   2391  * "If eglCreateImageKHR is successful for a EGL_LINUX_DMA_BUF_EXT target, the
   2392  *  EGL will take a reference to the dma_buf(s) which it will release at any
   2393  *  time while the EGLDisplay is initialized. It is the responsibility of the
   2394  *  application to close the dma_buf file descriptors."
   2395  *
   2396  * Therefore we must never close or otherwise modify the file descriptors.
   2397  */
   2398 _EGLImage *
   2399 dri2_create_image_dma_buf(_EGLDisplay *disp, _EGLContext *ctx,
   2400                           EGLClientBuffer buffer, const EGLint *attr_list)
   2401 {
   2402    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
   2403    _EGLImage *res;
   2404    _EGLImageAttribs attrs;
   2405    __DRIimage *dri_image;
   2406    unsigned num_fds;
   2407    int fds[DMA_BUF_MAX_PLANES];
   2408    int pitches[DMA_BUF_MAX_PLANES];
   2409    int offsets[DMA_BUF_MAX_PLANES];
   2410    uint64_t modifier;
   2411    bool has_modifier = false;
   2412    unsigned error;
   2413 
   2414    /**
   2415     * The spec says:
   2416     *
   2417     * ""* If <target> is EGL_LINUX_DMA_BUF_EXT and <buffer> is not NULL, the
   2418     *     error EGL_BAD_PARAMETER is generated."
   2419     */
   2420    if (buffer != NULL) {
   2421       _eglError(EGL_BAD_PARAMETER, "buffer not NULL");
   2422       return NULL;
   2423    }
   2424 
   2425    if (!_eglParseImageAttribList(&attrs, disp, attr_list))
   2426       return NULL;
   2427 
   2428    if (!dri2_check_dma_buf_attribs(&attrs))
   2429       return NULL;
   2430 
   2431    num_fds = dri2_check_dma_buf_format(&attrs);
   2432    if (!num_fds)
   2433       return NULL;
   2434 
   2435    for (unsigned i = 0; i < num_fds; ++i) {
   2436       fds[i] = attrs.DMABufPlaneFds[i].Value;
   2437       pitches[i] = attrs.DMABufPlanePitches[i].Value;
   2438       offsets[i] = attrs.DMABufPlaneOffsets[i].Value;
   2439    }
   2440 
   2441    /* dri2_check_dma_buf_attribs ensures that the modifier, if available,
   2442     * will be present in attrs.DMABufPlaneModifiersLo[0] and
   2443     * attrs.DMABufPlaneModifiersHi[0] */
   2444    if (attrs.DMABufPlaneModifiersLo[0].IsPresent) {
   2445       modifier = (uint64_t) attrs.DMABufPlaneModifiersHi[0].Value << 32;
   2446       modifier |= (uint64_t) (attrs.DMABufPlaneModifiersLo[0].Value & 0xffffffff);
   2447       has_modifier = true;
   2448    }
   2449 
   2450    if (has_modifier) {
   2451       if (dri2_dpy->image->base.version < 15 ||
   2452           dri2_dpy->image->createImageFromDmaBufs2 == NULL) {
   2453          _eglError(EGL_BAD_MATCH, "unsupported dma_buf format modifier");
   2454          return EGL_NO_IMAGE_KHR;
   2455       }
   2456       dri_image =
   2457          dri2_dpy->image->createImageFromDmaBufs2(dri2_dpy->dri_screen,
   2458             attrs.Width, attrs.Height, attrs.DMABufFourCC.Value,
   2459             modifier, fds, num_fds, pitches, offsets,
   2460             attrs.DMABufYuvColorSpaceHint.Value,
   2461             attrs.DMABufSampleRangeHint.Value,
   2462             attrs.DMABufChromaHorizontalSiting.Value,
   2463             attrs.DMABufChromaVerticalSiting.Value,
   2464             &error,
   2465             NULL);
   2466    }
   2467    else {
   2468       dri_image =
   2469          dri2_dpy->image->createImageFromDmaBufs(dri2_dpy->dri_screen,
   2470             attrs.Width, attrs.Height, attrs.DMABufFourCC.Value,
   2471             fds, num_fds, pitches, offsets,
   2472             attrs.DMABufYuvColorSpaceHint.Value,
   2473             attrs.DMABufSampleRangeHint.Value,
   2474             attrs.DMABufChromaHorizontalSiting.Value,
   2475             attrs.DMABufChromaVerticalSiting.Value,
   2476             &error,
   2477             NULL);
   2478    }
   2479    dri2_create_image_khr_texture_error(error);
   2480 
   2481    if (!dri_image)
   2482       return EGL_NO_IMAGE_KHR;
   2483 
   2484    res = dri2_create_image_from_dri(disp, dri_image);
   2485 
   2486    return res;
   2487 }
   2488 static _EGLImage *
   2489 dri2_create_drm_image_mesa(_EGLDriver *drv, _EGLDisplay *disp,
   2490                            const EGLint *attr_list)
   2491 {
   2492    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
   2493    struct dri2_egl_image *dri2_img;
   2494    _EGLImageAttribs attrs;
   2495    unsigned int dri_use, valid_mask;
   2496    int format;
   2497 
   2498    (void) drv;
   2499 
   2500    if (!attr_list) {
   2501       _eglError(EGL_BAD_PARAMETER, __func__);
   2502       return EGL_NO_IMAGE_KHR;
   2503    }
   2504 
   2505    if (!_eglParseImageAttribList(&attrs, disp, attr_list))
   2506       return EGL_NO_IMAGE_KHR;
   2507 
   2508    if (attrs.Width <= 0 || attrs.Height <= 0) {
   2509       _eglError(EGL_BAD_PARAMETER, __func__);
   2510       return EGL_NO_IMAGE_KHR;
   2511    }
   2512 
   2513    switch (attrs.DRMBufferFormatMESA) {
   2514    case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA:
   2515       format = __DRI_IMAGE_FORMAT_ARGB8888;
   2516       break;
   2517    default:
   2518       _eglError(EGL_BAD_PARAMETER, __func__);
   2519       return EGL_NO_IMAGE_KHR;
   2520    }
   2521 
   2522    valid_mask =
   2523       EGL_DRM_BUFFER_USE_SCANOUT_MESA |
   2524       EGL_DRM_BUFFER_USE_SHARE_MESA |
   2525       EGL_DRM_BUFFER_USE_CURSOR_MESA;
   2526    if (attrs.DRMBufferUseMESA & ~valid_mask) {
   2527       _eglError(EGL_BAD_PARAMETER, __func__);
   2528       return EGL_NO_IMAGE_KHR;
   2529    }
   2530 
   2531    dri_use = 0;
   2532    if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_SHARE_MESA)
   2533       dri_use |= __DRI_IMAGE_USE_SHARE;
   2534    if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_SCANOUT_MESA)
   2535       dri_use |= __DRI_IMAGE_USE_SCANOUT;
   2536    if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_CURSOR_MESA)
   2537       dri_use |= __DRI_IMAGE_USE_CURSOR;
   2538 
   2539    dri2_img = malloc(sizeof *dri2_img);
   2540    if (!dri2_img) {
   2541       _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr");
   2542       return EGL_NO_IMAGE_KHR;
   2543    }
   2544 
   2545    _eglInitImage(&dri2_img->base, disp);
   2546 
   2547    dri2_img->dri_image =
   2548       dri2_dpy->image->createImage(dri2_dpy->dri_screen,
   2549                                    attrs.Width, attrs.Height,
   2550                                    format, dri_use, dri2_img);
   2551    if (dri2_img->dri_image == NULL) {
   2552       free(dri2_img);
   2553        _eglError(EGL_BAD_ALLOC, "dri2_create_drm_image_mesa");
   2554       return EGL_NO_IMAGE_KHR;
   2555    }
   2556 
   2557    return &dri2_img->base;
   2558 }
   2559 
   2560 static EGLBoolean
   2561 dri2_export_drm_image_mesa(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *img,
   2562                           EGLint *name, EGLint *handle, EGLint *stride)
   2563 {
   2564    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
   2565    struct dri2_egl_image *dri2_img = dri2_egl_image(img);
   2566 
   2567    (void) drv;
   2568 
   2569    if (name && !dri2_dpy->image->queryImage(dri2_img->dri_image,
   2570                                             __DRI_IMAGE_ATTRIB_NAME, name))
   2571       return _eglError(EGL_BAD_ALLOC, "dri2_export_drm_image_mesa");
   2572 
   2573    if (handle)
   2574       dri2_dpy->image->queryImage(dri2_img->dri_image,
   2575                                   __DRI_IMAGE_ATTRIB_HANDLE, handle);
   2576 
   2577    if (stride)
   2578       dri2_dpy->image->queryImage(dri2_img->dri_image,
   2579                                   __DRI_IMAGE_ATTRIB_STRIDE, stride);
   2580 
   2581    return EGL_TRUE;
   2582 }
   2583 
   2584 static EGLBoolean
   2585 dri2_export_dma_buf_image_query_mesa(_EGLDriver *drv, _EGLDisplay *disp,
   2586                                      _EGLImage *img,
   2587                                      EGLint *fourcc, EGLint *nplanes,
   2588                                      EGLuint64KHR *modifiers)
   2589 {
   2590    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
   2591    struct dri2_egl_image *dri2_img = dri2_egl_image(img);
   2592 
   2593    (void) drv;
   2594 
   2595 
   2596    if (nplanes)
   2597       dri2_dpy->image->queryImage(dri2_img->dri_image,
   2598                                   __DRI_IMAGE_ATTRIB_NUM_PLANES, nplanes);
   2599    if (fourcc)
   2600       dri2_dpy->image->queryImage(dri2_img->dri_image,
   2601                                   __DRI_IMAGE_ATTRIB_FOURCC, fourcc);
   2602 
   2603    if (modifiers)
   2604       *modifiers = 0;
   2605 
   2606    return EGL_TRUE;
   2607 }
   2608 
   2609 static EGLBoolean
   2610 dri2_export_dma_buf_image_mesa(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *img,
   2611                                int *fds, EGLint *strides, EGLint *offsets)
   2612 {
   2613    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
   2614    struct dri2_egl_image *dri2_img = dri2_egl_image(img);
   2615 
   2616    (void) drv;
   2617 
   2618    /* rework later to provide multiple fds/strides/offsets */
   2619    if (fds)
   2620       dri2_dpy->image->queryImage(dri2_img->dri_image,
   2621                                   __DRI_IMAGE_ATTRIB_FD, fds);
   2622 
   2623    if (strides)
   2624       dri2_dpy->image->queryImage(dri2_img->dri_image,
   2625                                   __DRI_IMAGE_ATTRIB_STRIDE, strides);
   2626 
   2627    if (offsets) {
   2628       int img_offset;
   2629       bool ret = dri2_dpy->image->queryImage(dri2_img->dri_image,
   2630                      __DRI_IMAGE_ATTRIB_OFFSET, &img_offset);
   2631       if (ret)
   2632          offsets[0] = img_offset;
   2633       else
   2634          offsets[0] = 0;
   2635    }
   2636 
   2637    return EGL_TRUE;
   2638 }
   2639 
   2640 #endif
   2641 
   2642 _EGLImage *
   2643 dri2_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
   2644                       _EGLContext *ctx, EGLenum target,
   2645                       EGLClientBuffer buffer, const EGLint *attr_list)
   2646 {
   2647    (void) drv;
   2648 
   2649    switch (target) {
   2650    case EGL_GL_TEXTURE_2D_KHR:
   2651    case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:
   2652    case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:
   2653    case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:
   2654    case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:
   2655    case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:
   2656    case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:
   2657    case EGL_GL_TEXTURE_3D_KHR:
   2658       return dri2_create_image_khr_texture(disp, ctx, target, buffer, attr_list);
   2659    case EGL_GL_RENDERBUFFER_KHR:
   2660       return dri2_create_image_khr_renderbuffer(disp, ctx, buffer, attr_list);
   2661 #ifdef HAVE_LIBDRM
   2662    case EGL_DRM_BUFFER_MESA:
   2663       return dri2_create_image_mesa_drm_buffer(disp, ctx, buffer, attr_list);
   2664    case EGL_LINUX_DMA_BUF_EXT:
   2665       return dri2_create_image_dma_buf(disp, ctx, buffer, attr_list);
   2666 #endif
   2667 #ifdef HAVE_WAYLAND_PLATFORM
   2668    case EGL_WAYLAND_BUFFER_WL:
   2669       return dri2_create_image_wayland_wl_buffer(disp, ctx, buffer, attr_list);
   2670 #endif
   2671    default:
   2672       _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
   2673       return EGL_NO_IMAGE_KHR;
   2674    }
   2675 }
   2676 
   2677 static EGLBoolean
   2678 dri2_destroy_image_khr(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *image)
   2679 {
   2680    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
   2681    struct dri2_egl_image *dri2_img = dri2_egl_image(image);
   2682 
   2683    (void) drv;
   2684 
   2685    dri2_dpy->image->destroyImage(dri2_img->dri_image);
   2686    free(dri2_img);
   2687 
   2688    return EGL_TRUE;
   2689 }
   2690 
   2691 #ifdef HAVE_WAYLAND_PLATFORM
   2692 
   2693 static void
   2694 dri2_wl_reference_buffer(void *user_data, uint32_t name, int fd,
   2695                          struct wl_drm_buffer *buffer)
   2696 {
   2697    _EGLDisplay *disp = user_data;
   2698    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
   2699    __DRIimage *img;
   2700    int dri_components = 0;
   2701 
   2702    if (fd == -1)
   2703       img = dri2_dpy->image->createImageFromNames(dri2_dpy->dri_screen,
   2704                                                   buffer->width,
   2705                                                   buffer->height,
   2706                                                   buffer->format,
   2707                                                   (int*)&name, 1,
   2708                                                   buffer->stride,
   2709                                                   buffer->offset,
   2710                                                   NULL);
   2711    else
   2712       img = dri2_dpy->image->createImageFromFds(dri2_dpy->dri_screen,
   2713                                                 buffer->width,
   2714                                                 buffer->height,
   2715                                                 buffer->format,
   2716                                                 &fd, 1,
   2717                                                 buffer->stride,
   2718                                                 buffer->offset,
   2719                                                 NULL);
   2720 
   2721    if (img == NULL)
   2722       return;
   2723 
   2724    dri2_dpy->image->queryImage(img, __DRI_IMAGE_ATTRIB_COMPONENTS, &dri_components);
   2725 
   2726    buffer->driver_format = NULL;
   2727    for (int i = 0; i < ARRAY_SIZE(wl_drm_components); i++)
   2728       if (wl_drm_components[i].dri_components == dri_components)
   2729          buffer->driver_format = &wl_drm_components[i];
   2730 
   2731    if (buffer->driver_format == NULL)
   2732       dri2_dpy->image->destroyImage(img);
   2733    else
   2734       buffer->driver_buffer = img;
   2735 }
   2736 
   2737 static void
   2738 dri2_wl_release_buffer(void *user_data, struct wl_drm_buffer *buffer)
   2739 {
   2740    _EGLDisplay *disp = user_data;
   2741    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
   2742 
   2743    dri2_dpy->image->destroyImage(buffer->driver_buffer);
   2744 }
   2745 
   2746 static EGLBoolean
   2747 dri2_bind_wayland_display_wl(_EGLDriver *drv, _EGLDisplay *disp,
   2748                              struct wl_display *wl_dpy)
   2749 {
   2750    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
   2751    const struct wayland_drm_callbacks wl_drm_callbacks = {
   2752       .authenticate = (int(*)(void *, uint32_t)) dri2_dpy->vtbl->authenticate,
   2753       .reference_buffer = dri2_wl_reference_buffer,
   2754       .release_buffer = dri2_wl_release_buffer
   2755    };
   2756    int flags = 0;
   2757    uint64_t cap;
   2758 
   2759    (void) drv;
   2760 
   2761    if (dri2_dpy->wl_server_drm)
   2762            return EGL_FALSE;
   2763 
   2764    if (drmGetCap(dri2_dpy->fd, DRM_CAP_PRIME, &cap) == 0 &&
   2765        cap == (DRM_PRIME_CAP_IMPORT | DRM_PRIME_CAP_EXPORT) &&
   2766        dri2_dpy->image->base.version >= 7 &&
   2767        dri2_dpy->image->createImageFromFds != NULL)
   2768       flags |= WAYLAND_DRM_PRIME;
   2769 
   2770    dri2_dpy->wl_server_drm =
   2771            wayland_drm_init(wl_dpy, dri2_dpy->device_name,
   2772                             &wl_drm_callbacks, disp, flags);
   2773 
   2774    if (!dri2_dpy->wl_server_drm)
   2775            return EGL_FALSE;
   2776 
   2777 #ifdef HAVE_DRM_PLATFORM
   2778    /* We have to share the wl_drm instance with gbm, so gbm can convert
   2779     * wl_buffers to gbm bos. */
   2780    if (dri2_dpy->gbm_dri)
   2781       dri2_dpy->gbm_dri->wl_drm = dri2_dpy->wl_server_drm;
   2782 #endif
   2783 
   2784    return EGL_TRUE;
   2785 }
   2786 
   2787 static EGLBoolean
   2788 dri2_unbind_wayland_display_wl(_EGLDriver *drv, _EGLDisplay *disp,
   2789                                struct wl_display *wl_dpy)
   2790 {
   2791    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
   2792 
   2793    (void) drv;
   2794 
   2795    if (!dri2_dpy->wl_server_drm)
   2796            return EGL_FALSE;
   2797 
   2798    wayland_drm_uninit(dri2_dpy->wl_server_drm);
   2799    dri2_dpy->wl_server_drm = NULL;
   2800 
   2801    return EGL_TRUE;
   2802 }
   2803 
   2804 static EGLBoolean
   2805 dri2_query_wayland_buffer_wl(_EGLDriver *drv, _EGLDisplay *disp,
   2806                              struct wl_resource *buffer_resource,
   2807                              EGLint attribute, EGLint *value)
   2808 {
   2809    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
   2810    struct wl_drm_buffer *buffer;
   2811    const struct wl_drm_components_descriptor *format;
   2812 
   2813    buffer = wayland_drm_buffer_get(dri2_dpy->wl_server_drm, buffer_resource);
   2814    if (!buffer)
   2815       return EGL_FALSE;
   2816 
   2817    format = buffer->driver_format;
   2818    switch (attribute) {
   2819    case EGL_TEXTURE_FORMAT:
   2820       *value = format->components;
   2821       return EGL_TRUE;
   2822    case EGL_WIDTH:
   2823       *value = buffer->width;
   2824       return EGL_TRUE;
   2825    case EGL_HEIGHT:
   2826       *value = buffer->height;
   2827       return EGL_TRUE;
   2828    }
   2829 
   2830    return EGL_FALSE;
   2831 }
   2832 #endif
   2833 
   2834 static void
   2835 dri2_egl_ref_sync(struct dri2_egl_sync *sync)
   2836 {
   2837    p_atomic_inc(&sync->refcount);
   2838 }
   2839 
   2840 static void
   2841 dri2_egl_unref_sync(struct dri2_egl_display *dri2_dpy,
   2842                     struct dri2_egl_sync *dri2_sync)
   2843 {
   2844    if (p_atomic_dec_zero(&dri2_sync->refcount)) {
   2845       switch (dri2_sync->base.Type) {
   2846       case EGL_SYNC_REUSABLE_KHR:
   2847          cnd_destroy(&dri2_sync->cond);
   2848          break;
   2849       case EGL_SYNC_NATIVE_FENCE_ANDROID:
   2850          if (dri2_sync->base.SyncFd != EGL_NO_NATIVE_FENCE_FD_ANDROID)
   2851             close(dri2_sync->base.SyncFd);
   2852          break;
   2853       default:
   2854          break;
   2855       }
   2856 
   2857       if (dri2_sync->fence)
   2858          dri2_dpy->fence->destroy_fence(dri2_dpy->dri_screen, dri2_sync->fence);
   2859 
   2860       free(dri2_sync);
   2861    }
   2862 }
   2863 
   2864 static _EGLSync *
   2865 dri2_create_sync(_EGLDriver *drv, _EGLDisplay *dpy,
   2866                  EGLenum type, const EGLAttrib *attrib_list)
   2867 {
   2868    _EGLContext *ctx = _eglGetCurrentContext();
   2869    struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
   2870    struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
   2871    struct dri2_egl_sync *dri2_sync;
   2872    EGLint ret;
   2873    pthread_condattr_t attr;
   2874 
   2875    dri2_sync = calloc(1, sizeof(struct dri2_egl_sync));
   2876    if (!dri2_sync) {
   2877       _eglError(EGL_BAD_ALLOC, "eglCreateSyncKHR");
   2878       return NULL;
   2879    }
   2880 
   2881    if (!_eglInitSync(&dri2_sync->base, dpy, type, attrib_list)) {
   2882       free(dri2_sync);
   2883       return NULL;
   2884    }
   2885 
   2886    switch (type) {
   2887    case EGL_SYNC_FENCE_KHR:
   2888       dri2_sync->fence = dri2_dpy->fence->create_fence(dri2_ctx->dri_context);
   2889       if (!dri2_sync->fence) {
   2890          /* Why did it fail? DRI doesn't return an error code, so we emit
   2891           * a generic EGL error that doesn't communicate user error.
   2892           */
   2893          _eglError(EGL_BAD_ALLOC, "eglCreateSyncKHR");
   2894          free(dri2_sync);
   2895          return NULL;
   2896       }
   2897       break;
   2898 
   2899    case EGL_SYNC_CL_EVENT_KHR:
   2900       dri2_sync->fence = dri2_dpy->fence->get_fence_from_cl_event(
   2901                                  dri2_dpy->dri_screen,
   2902                                  dri2_sync->base.CLEvent);
   2903       /* this can only happen if the cl_event passed in is invalid. */
   2904       if (!dri2_sync->fence) {
   2905          _eglError(EGL_BAD_ATTRIBUTE, "eglCreateSyncKHR");
   2906          free(dri2_sync);
   2907          return NULL;
   2908       }
   2909 
   2910       /* the initial status must be "signaled" if the cl_event is signaled */
   2911       if (dri2_dpy->fence->client_wait_sync(dri2_ctx->dri_context,
   2912                                             dri2_sync->fence, 0, 0))
   2913          dri2_sync->base.SyncStatus = EGL_SIGNALED_KHR;
   2914       break;
   2915 
   2916    case EGL_SYNC_REUSABLE_KHR:
   2917       /* intialize attr */
   2918       ret = pthread_condattr_init(&attr);
   2919 
   2920       if (ret) {
   2921          _eglError(EGL_BAD_ACCESS, "eglCreateSyncKHR");
   2922          free(dri2_sync);
   2923          return NULL;
   2924       }
   2925 
   2926       /* change clock attribute to CLOCK_MONOTONIC */
   2927       ret = pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
   2928 
   2929       if (ret) {
   2930          _eglError(EGL_BAD_ACCESS, "eglCreateSyncKHR");
   2931          free(dri2_sync);
   2932          return NULL;
   2933       }
   2934 
   2935       ret = pthread_cond_init(&dri2_sync->cond, &attr);
   2936 
   2937       if (ret) {
   2938          _eglError(EGL_BAD_ACCESS, "eglCreateSyncKHR");
   2939          free(dri2_sync);
   2940          return NULL;
   2941       }
   2942 
   2943       /* initial status of reusable sync must be "unsignaled" */
   2944       dri2_sync->base.SyncStatus = EGL_UNSIGNALED_KHR;
   2945       break;
   2946 
   2947    case EGL_SYNC_NATIVE_FENCE_ANDROID:
   2948       if (dri2_dpy->fence->create_fence_fd) {
   2949          dri2_sync->fence = dri2_dpy->fence->create_fence_fd(
   2950                                     dri2_ctx->dri_context,
   2951                                     dri2_sync->base.SyncFd);
   2952       }
   2953       if (!dri2_sync->fence) {
   2954          _eglError(EGL_BAD_ATTRIBUTE, "eglCreateSyncKHR");
   2955          free(dri2_sync);
   2956          return NULL;
   2957       }
   2958       break;
   2959    }
   2960 
   2961    p_atomic_set(&dri2_sync->refcount, 1);
   2962    return &dri2_sync->base;
   2963 }
   2964 
   2965 static EGLBoolean
   2966 dri2_destroy_sync(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync)
   2967 {
   2968    struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
   2969    struct dri2_egl_sync *dri2_sync = dri2_egl_sync(sync);
   2970    EGLint ret = EGL_TRUE;
   2971    EGLint err;
   2972 
   2973    /* if type of sync is EGL_SYNC_REUSABLE_KHR and it is not signaled yet,
   2974     * then unlock all threads possibly blocked by the reusable sync before
   2975     * destroying it.
   2976     */
   2977    if (dri2_sync->base.Type == EGL_SYNC_REUSABLE_KHR &&
   2978        dri2_sync->base.SyncStatus == EGL_UNSIGNALED_KHR) {
   2979       dri2_sync->base.SyncStatus = EGL_SIGNALED_KHR;
   2980       /* unblock all threads currently blocked by sync */
   2981       err = cnd_broadcast(&dri2_sync->cond);
   2982 
   2983       if (err) {
   2984          _eglError(EGL_BAD_ACCESS, "eglDestroySyncKHR");
   2985          ret = EGL_FALSE;
   2986       }
   2987    }
   2988 
   2989    dri2_egl_unref_sync(dri2_dpy, dri2_sync);
   2990 
   2991    return ret;
   2992 }
   2993 
   2994 static EGLint
   2995 dri2_dup_native_fence_fd(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync)
   2996 {
   2997    struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
   2998    struct dri2_egl_sync *dri2_sync = dri2_egl_sync(sync);
   2999 
   3000    assert(sync->Type == EGL_SYNC_NATIVE_FENCE_ANDROID);
   3001 
   3002    if (sync->SyncFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
   3003       /* try to retrieve the actual native fence fd.. if rendering is
   3004        * not flushed this will just return -1, aka NO_NATIVE_FENCE_FD:
   3005        */
   3006       sync->SyncFd = dri2_dpy->fence->get_fence_fd(dri2_dpy->dri_screen,
   3007                                                    dri2_sync->fence);
   3008    }
   3009 
   3010    if (sync->SyncFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
   3011       /* if native fence fd still not created, return an error: */
   3012       _eglError(EGL_BAD_PARAMETER, "eglDupNativeFenceFDANDROID");
   3013       return EGL_NO_NATIVE_FENCE_FD_ANDROID;
   3014    }
   3015 
   3016    return dup(sync->SyncFd);
   3017 }
   3018 
   3019 static EGLint
   3020 dri2_client_wait_sync(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync,
   3021                       EGLint flags, EGLTime timeout)
   3022 {
   3023    _EGLContext *ctx = _eglGetCurrentContext();
   3024    struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
   3025    struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
   3026    struct dri2_egl_sync *dri2_sync = dri2_egl_sync(sync);
   3027    unsigned wait_flags = 0;
   3028 
   3029    EGLint ret = EGL_CONDITION_SATISFIED_KHR;
   3030 
   3031    /* The EGL_KHR_fence_sync spec states:
   3032     *
   3033     *    "If no context is current for the bound API,
   3034     *     the EGL_SYNC_FLUSH_COMMANDS_BIT_KHR bit is ignored.
   3035     */
   3036    if (dri2_ctx && flags & EGL_SYNC_FLUSH_COMMANDS_BIT_KHR)
   3037       wait_flags |= __DRI2_FENCE_FLAG_FLUSH_COMMANDS;
   3038 
   3039    /* the sync object should take a reference while waiting */
   3040    dri2_egl_ref_sync(dri2_sync);
   3041 
   3042    switch (sync->Type) {
   3043    case EGL_SYNC_FENCE_KHR:
   3044    case EGL_SYNC_NATIVE_FENCE_ANDROID:
   3045    case EGL_SYNC_CL_EVENT_KHR:
   3046       if (dri2_dpy->fence->client_wait_sync(dri2_ctx ? dri2_ctx->dri_context : NULL,
   3047                                          dri2_sync->fence, wait_flags,
   3048                                          timeout))
   3049          dri2_sync->base.SyncStatus = EGL_SIGNALED_KHR;
   3050       else
   3051          ret = EGL_TIMEOUT_EXPIRED_KHR;
   3052       break;
   3053 
   3054    case EGL_SYNC_REUSABLE_KHR:
   3055       if (dri2_ctx && dri2_sync->base.SyncStatus == EGL_UNSIGNALED_KHR &&
   3056           (flags & EGL_SYNC_FLUSH_COMMANDS_BIT_KHR)) {
   3057          /* flush context if EGL_SYNC_FLUSH_COMMANDS_BIT_KHR is set */
   3058          dri2_gl_flush();
   3059       }
   3060 
   3061       /* if timeout is EGL_FOREVER_KHR, it should wait without any timeout.*/
   3062       if (timeout == EGL_FOREVER_KHR) {
   3063          mtx_lock(&dri2_sync->mutex);
   3064          cnd_wait(&dri2_sync->cond, &dri2_sync->mutex);
   3065          mtx_unlock(&dri2_sync->mutex);
   3066       } else {
   3067          /* if reusable sync has not been yet signaled */
   3068          if (dri2_sync->base.SyncStatus != EGL_SIGNALED_KHR) {
   3069             /* timespecs for cnd_timedwait */
   3070             struct timespec current;
   3071             struct timespec expire;
   3072 
   3073             /* We override the clock to monotonic when creating the condition
   3074              * variable. */
   3075             clock_gettime(CLOCK_MONOTONIC, &current);
   3076 
   3077             /* calculating when to expire */
   3078             expire.tv_nsec = timeout % 1000000000L;
   3079             expire.tv_sec = timeout / 1000000000L;
   3080 
   3081             expire.tv_nsec += current.tv_nsec;
   3082             expire.tv_sec += current.tv_sec;
   3083 
   3084             /* expire.nsec now is a number between 0 and 1999999998 */
   3085             if (expire.tv_nsec > 999999999L) {
   3086                expire.tv_sec++;
   3087                expire.tv_nsec -= 1000000000L;
   3088             }
   3089 
   3090             mtx_lock(&dri2_sync->mutex);
   3091             ret = cnd_timedwait(&dri2_sync->cond, &dri2_sync->mutex, &expire);
   3092             mtx_unlock(&dri2_sync->mutex);
   3093 
   3094             if (ret == thrd_busy) {
   3095                if (dri2_sync->base.SyncStatus == EGL_UNSIGNALED_KHR) {
   3096                   ret = EGL_TIMEOUT_EXPIRED_KHR;
   3097                } else {
   3098                   _eglError(EGL_BAD_ACCESS, "eglClientWaitSyncKHR");
   3099                   ret = EGL_FALSE;
   3100                }
   3101             }
   3102          }
   3103       }
   3104       break;
   3105   }
   3106   dri2_egl_unref_sync(dri2_dpy, dri2_sync);
   3107 
   3108   return ret;
   3109 }
   3110 
   3111 static EGLBoolean
   3112 dri2_signal_sync(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync,
   3113                       EGLenum mode)
   3114 {
   3115    struct dri2_egl_sync *dri2_sync = dri2_egl_sync(sync);
   3116    EGLint ret;
   3117 
   3118    if (sync->Type != EGL_SYNC_REUSABLE_KHR)
   3119       return _eglError(EGL_BAD_MATCH, "eglSignalSyncKHR");
   3120 
   3121    if (mode != EGL_SIGNALED_KHR && mode != EGL_UNSIGNALED_KHR)
   3122       return _eglError(EGL_BAD_ATTRIBUTE, "eglSignalSyncKHR");
   3123 
   3124    dri2_sync->base.SyncStatus = mode;
   3125 
   3126    if (mode == EGL_SIGNALED_KHR) {
   3127       ret = cnd_broadcast(&dri2_sync->cond);
   3128 
   3129       /* fail to broadcast */
   3130       if (ret)
   3131          return _eglError(EGL_BAD_ACCESS, "eglSignalSyncKHR");
   3132    }
   3133 
   3134    return EGL_TRUE;
   3135 }
   3136 
   3137 static EGLint
   3138 dri2_server_wait_sync(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync)
   3139 {
   3140    _EGLContext *ctx = _eglGetCurrentContext();
   3141    struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
   3142    struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
   3143    struct dri2_egl_sync *dri2_sync = dri2_egl_sync(sync);
   3144 
   3145    dri2_dpy->fence->server_wait_sync(dri2_ctx->dri_context,
   3146                                      dri2_sync->fence, 0);
   3147    return EGL_TRUE;
   3148 }
   3149 
   3150 static int
   3151 dri2_interop_query_device_info(_EGLDisplay *dpy, _EGLContext *ctx,
   3152                                struct mesa_glinterop_device_info *out)
   3153 {
   3154    struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
   3155    struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
   3156 
   3157    if (!dri2_dpy->interop)
   3158       return MESA_GLINTEROP_UNSUPPORTED;
   3159 
   3160    return dri2_dpy->interop->query_device_info(dri2_ctx->dri_context, out);
   3161 }
   3162 
   3163 static int
   3164 dri2_interop_export_object(_EGLDisplay *dpy, _EGLContext *ctx,
   3165                            struct mesa_glinterop_export_in *in,
   3166                            struct mesa_glinterop_export_out *out)
   3167 {
   3168    struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
   3169    struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
   3170 
   3171    if (!dri2_dpy->interop)
   3172       return MESA_GLINTEROP_UNSUPPORTED;
   3173 
   3174    return dri2_dpy->interop->export_object(dri2_ctx->dri_context, in, out);
   3175 }
   3176 
   3177 /**
   3178  * This is the main entrypoint into the driver, called by libEGL.
   3179  * Create a new _EGLDriver object and init its dispatch table.
   3180  */
   3181 _EGLDriver *
   3182 _eglBuiltInDriver(void)
   3183 {
   3184    _EGLDriver *dri2_drv = calloc(1, sizeof *dri2_drv);
   3185    if (!dri2_drv)
   3186       return NULL;
   3187 
   3188    _eglInitDriverFallbacks(dri2_drv);
   3189    dri2_drv->API.Initialize = dri2_initialize;
   3190    dri2_drv->API.Terminate = dri2_terminate;
   3191    dri2_drv->API.CreateContext = dri2_create_context;
   3192    dri2_drv->API.DestroyContext = dri2_destroy_context;
   3193    dri2_drv->API.MakeCurrent = dri2_make_current;
   3194    dri2_drv->API.CreateWindowSurface = dri2_create_window_surface;
   3195    dri2_drv->API.CreatePixmapSurface = dri2_create_pixmap_surface;
   3196    dri2_drv->API.CreatePbufferSurface = dri2_create_pbuffer_surface;
   3197    dri2_drv->API.DestroySurface = dri2_destroy_surface;
   3198    dri2_drv->API.GetProcAddress = dri2_get_proc_address;
   3199    dri2_drv->API.WaitClient = dri2_wait_client;
   3200    dri2_drv->API.WaitNative = dri2_wait_native;
   3201    dri2_drv->API.BindTexImage = dri2_bind_tex_image;
   3202    dri2_drv->API.ReleaseTexImage = dri2_release_tex_image;
   3203    dri2_drv->API.SwapInterval = dri2_swap_interval;
   3204    dri2_drv->API.SwapBuffers = dri2_swap_buffers;
   3205    dri2_drv->API.SwapBuffersWithDamageEXT = dri2_swap_buffers_with_damage;
   3206    dri2_drv->API.SwapBuffersRegionNOK = dri2_swap_buffers_region;
   3207    dri2_drv->API.SetDamageRegion = dri2_set_damage_region;
   3208    dri2_drv->API.PostSubBufferNV = dri2_post_sub_buffer;
   3209    dri2_drv->API.CopyBuffers = dri2_copy_buffers,
   3210    dri2_drv->API.QueryBufferAge = dri2_query_buffer_age;
   3211    dri2_drv->API.CreateImageKHR = dri2_create_image;
   3212    dri2_drv->API.DestroyImageKHR = dri2_destroy_image_khr;
   3213    dri2_drv->API.CreateWaylandBufferFromImageWL = dri2_create_wayland_buffer_from_image;
   3214    dri2_drv->API.QuerySurface = dri2_query_surface;
   3215 #ifdef HAVE_LIBDRM
   3216    dri2_drv->API.CreateDRMImageMESA = dri2_create_drm_image_mesa;
   3217    dri2_drv->API.ExportDRMImageMESA = dri2_export_drm_image_mesa;
   3218    dri2_drv->API.ExportDMABUFImageQueryMESA = dri2_export_dma_buf_image_query_mesa;
   3219    dri2_drv->API.ExportDMABUFImageMESA = dri2_export_dma_buf_image_mesa;
   3220    dri2_drv->API.QueryDmaBufFormatsEXT = dri2_query_dma_buf_formats;
   3221    dri2_drv->API.QueryDmaBufModifiersEXT = dri2_query_dma_buf_modifiers;
   3222 #endif
   3223 #ifdef HAVE_WAYLAND_PLATFORM
   3224    dri2_drv->API.BindWaylandDisplayWL = dri2_bind_wayland_display_wl;
   3225    dri2_drv->API.UnbindWaylandDisplayWL = dri2_unbind_wayland_display_wl;
   3226    dri2_drv->API.QueryWaylandBufferWL = dri2_query_wayland_buffer_wl;
   3227 #endif
   3228    dri2_drv->API.GetSyncValuesCHROMIUM = dri2_get_sync_values_chromium;
   3229    dri2_drv->API.CreateSyncKHR = dri2_create_sync;
   3230    dri2_drv->API.ClientWaitSyncKHR = dri2_client_wait_sync;
   3231    dri2_drv->API.SignalSyncKHR = dri2_signal_sync;
   3232    dri2_drv->API.WaitSyncKHR = dri2_server_wait_sync;
   3233    dri2_drv->API.DestroySyncKHR = dri2_destroy_sync;
   3234    dri2_drv->API.GLInteropQueryDeviceInfo = dri2_interop_query_device_info;
   3235    dri2_drv->API.GLInteropExportObject = dri2_interop_export_object;
   3236    dri2_drv->API.DupNativeFenceFDANDROID = dri2_dup_native_fence_fd;
   3237 
   3238    dri2_drv->Name = "DRI2";
   3239 
   3240    return dri2_drv;
   3241 }
   3242