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