Home | History | Annotate | Download | only in dri2
      1 /*
      2  * Copyright  2010 Intel Corporation
      3  *
      4  * Permission is hereby granted, free of charge, to any person obtaining a
      5  * copy of this software and associated documentation files (the "Software"),
      6  * to deal in the Software without restriction, including without limitation
      7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      8  * and/or sell copies of the Software, and to permit persons to whom the
      9  * Software is furnished to do so, subject to the following conditions:
     10  *
     11  * The above copyright notice and this permission notice (including the next
     12  * paragraph) shall be included in all copies or substantial portions of the
     13  * Software.
     14  *
     15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
     18  * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
     19  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
     20  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     22  * DEALINGS IN THE SOFTWARE.
     23  *
     24  * Authors:
     25  *    Kristian Hgsberg <krh (at) bitplanet.net>
     26  */
     27 
     28 #include <stdlib.h>
     29 #include <string.h>
     30 #include <stdio.h>
     31 #include <limits.h>
     32 #include <dlfcn.h>
     33 #include <fcntl.h>
     34 #include <errno.h>
     35 #include <unistd.h>
     36 #include <xf86drm.h>
     37 #include <GL/gl.h>
     38 #include <GL/internal/dri_interface.h>
     39 #include <sys/types.h>
     40 #include <sys/stat.h>
     41 
     42 #include "egl_dri2.h"
     43 
     44 const __DRIuseInvalidateExtension use_invalidate = {
     45    { __DRI_USE_INVALIDATE, 1 }
     46 };
     47 
     48 EGLint dri2_to_egl_attribute_map[] = {
     49    0,
     50    EGL_BUFFER_SIZE,		/* __DRI_ATTRIB_BUFFER_SIZE */
     51    EGL_LEVEL,			/* __DRI_ATTRIB_LEVEL */
     52    EGL_RED_SIZE,		/* __DRI_ATTRIB_RED_SIZE */
     53    EGL_GREEN_SIZE,		/* __DRI_ATTRIB_GREEN_SIZE */
     54    EGL_BLUE_SIZE,		/* __DRI_ATTRIB_BLUE_SIZE */
     55    EGL_LUMINANCE_SIZE,		/* __DRI_ATTRIB_LUMINANCE_SIZE */
     56    EGL_ALPHA_SIZE,		/* __DRI_ATTRIB_ALPHA_SIZE */
     57    0,				/* __DRI_ATTRIB_ALPHA_MASK_SIZE */
     58    EGL_DEPTH_SIZE,		/* __DRI_ATTRIB_DEPTH_SIZE */
     59    EGL_STENCIL_SIZE,		/* __DRI_ATTRIB_STENCIL_SIZE */
     60    0,				/* __DRI_ATTRIB_ACCUM_RED_SIZE */
     61    0,				/* __DRI_ATTRIB_ACCUM_GREEN_SIZE */
     62    0,				/* __DRI_ATTRIB_ACCUM_BLUE_SIZE */
     63    0,				/* __DRI_ATTRIB_ACCUM_ALPHA_SIZE */
     64    EGL_SAMPLE_BUFFERS,		/* __DRI_ATTRIB_SAMPLE_BUFFERS */
     65    EGL_SAMPLES,			/* __DRI_ATTRIB_SAMPLES */
     66    0,				/* __DRI_ATTRIB_RENDER_TYPE, */
     67    0,				/* __DRI_ATTRIB_CONFIG_CAVEAT */
     68    0,				/* __DRI_ATTRIB_CONFORMANT */
     69    0,				/* __DRI_ATTRIB_DOUBLE_BUFFER */
     70    0,				/* __DRI_ATTRIB_STEREO */
     71    0,				/* __DRI_ATTRIB_AUX_BUFFERS */
     72    0,				/* __DRI_ATTRIB_TRANSPARENT_TYPE */
     73    0,				/* __DRI_ATTRIB_TRANSPARENT_INDEX_VALUE */
     74    0,				/* __DRI_ATTRIB_TRANSPARENT_RED_VALUE */
     75    0,				/* __DRI_ATTRIB_TRANSPARENT_GREEN_VALUE */
     76    0,				/* __DRI_ATTRIB_TRANSPARENT_BLUE_VALUE */
     77    0,				/* __DRI_ATTRIB_TRANSPARENT_ALPHA_VALUE */
     78    0,				/* __DRI_ATTRIB_FLOAT_MODE */
     79    0,				/* __DRI_ATTRIB_RED_MASK */
     80    0,				/* __DRI_ATTRIB_GREEN_MASK */
     81    0,				/* __DRI_ATTRIB_BLUE_MASK */
     82    0,				/* __DRI_ATTRIB_ALPHA_MASK */
     83    EGL_MAX_PBUFFER_WIDTH,	/* __DRI_ATTRIB_MAX_PBUFFER_WIDTH */
     84    EGL_MAX_PBUFFER_HEIGHT,	/* __DRI_ATTRIB_MAX_PBUFFER_HEIGHT */
     85    EGL_MAX_PBUFFER_PIXELS,	/* __DRI_ATTRIB_MAX_PBUFFER_PIXELS */
     86    0,				/* __DRI_ATTRIB_OPTIMAL_PBUFFER_WIDTH */
     87    0,				/* __DRI_ATTRIB_OPTIMAL_PBUFFER_HEIGHT */
     88    0,				/* __DRI_ATTRIB_VISUAL_SELECT_GROUP */
     89    0,				/* __DRI_ATTRIB_SWAP_METHOD */
     90    EGL_MAX_SWAP_INTERVAL,	/* __DRI_ATTRIB_MAX_SWAP_INTERVAL */
     91    EGL_MIN_SWAP_INTERVAL,	/* __DRI_ATTRIB_MIN_SWAP_INTERVAL */
     92    0,				/* __DRI_ATTRIB_BIND_TO_TEXTURE_RGB */
     93    0,				/* __DRI_ATTRIB_BIND_TO_TEXTURE_RGBA */
     94    0,				/* __DRI_ATTRIB_BIND_TO_MIPMAP_TEXTURE */
     95    0,				/* __DRI_ATTRIB_BIND_TO_TEXTURE_TARGETS */
     96    EGL_Y_INVERTED_NOK,		/* __DRI_ATTRIB_YINVERTED */
     97    0,				/* __DRI_ATTRIB_FRAMEBUFFER_SRGB_CAPABLE */
     98 };
     99 
    100 static EGLBoolean
    101 dri2_match_config(const _EGLConfig *conf, const _EGLConfig *criteria)
    102 {
    103    if (_eglCompareConfigs(conf, criteria, NULL, EGL_FALSE) != 0)
    104       return EGL_FALSE;
    105 
    106    if (!_eglMatchConfig(conf, criteria))
    107       return EGL_FALSE;
    108 
    109    return EGL_TRUE;
    110 }
    111 
    112 struct dri2_egl_config *
    113 dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id,
    114 		int depth, EGLint surface_type, const EGLint *attr_list,
    115 		const unsigned int *rgba_masks)
    116 {
    117    struct dri2_egl_config *conf;
    118    struct dri2_egl_display *dri2_dpy;
    119    _EGLConfig base;
    120    unsigned int attrib, value, double_buffer;
    121    EGLint key, bind_to_texture_rgb, bind_to_texture_rgba;
    122    unsigned int dri_masks[4] = { 0, 0, 0, 0 };
    123    _EGLConfig *matching_config;
    124    EGLint num_configs = 0;
    125    EGLint config_id;
    126    int i;
    127 
    128    dri2_dpy = disp->DriverData;
    129    _eglInitConfig(&base, disp, id);
    130 
    131    i = 0;
    132    double_buffer = 0;
    133    bind_to_texture_rgb = 0;
    134    bind_to_texture_rgba = 0;
    135 
    136    while (dri2_dpy->core->indexConfigAttrib(dri_config, i++, &attrib, &value)) {
    137       switch (attrib) {
    138       case __DRI_ATTRIB_RENDER_TYPE:
    139 	 if (value & __DRI_ATTRIB_RGBA_BIT)
    140 	    value = EGL_RGB_BUFFER;
    141 	 else if (value & __DRI_ATTRIB_LUMINANCE_BIT)
    142 	    value = EGL_LUMINANCE_BUFFER;
    143 	 else
    144 	    /* not valid */;
    145 	 _eglSetConfigKey(&base, EGL_COLOR_BUFFER_TYPE, value);
    146 	 break;
    147 
    148       case __DRI_ATTRIB_CONFIG_CAVEAT:
    149          if (value & __DRI_ATTRIB_NON_CONFORMANT_CONFIG)
    150             value = EGL_NON_CONFORMANT_CONFIG;
    151          else if (value & __DRI_ATTRIB_SLOW_BIT)
    152             value = EGL_SLOW_CONFIG;
    153 	 else
    154 	    value = EGL_NONE;
    155 	 _eglSetConfigKey(&base, EGL_CONFIG_CAVEAT, value);
    156          break;
    157 
    158       case __DRI_ATTRIB_BIND_TO_TEXTURE_RGB:
    159 	 bind_to_texture_rgb = value;
    160 	 break;
    161 
    162       case __DRI_ATTRIB_BIND_TO_TEXTURE_RGBA:
    163 	 bind_to_texture_rgba = value;
    164 	 break;
    165 
    166       case __DRI_ATTRIB_DOUBLE_BUFFER:
    167 	 double_buffer = value;
    168 	 break;
    169 
    170       case __DRI_ATTRIB_RED_MASK:
    171          dri_masks[0] = value;
    172          break;
    173 
    174       case __DRI_ATTRIB_GREEN_MASK:
    175          dri_masks[1] = value;
    176          break;
    177 
    178       case __DRI_ATTRIB_BLUE_MASK:
    179          dri_masks[2] = value;
    180          break;
    181 
    182       case __DRI_ATTRIB_ALPHA_MASK:
    183          dri_masks[3] = value;
    184          break;
    185 
    186       default:
    187 	 key = dri2_to_egl_attribute_map[attrib];
    188 	 if (key != 0)
    189 	    _eglSetConfigKey(&base, key, value);
    190 	 break;
    191       }
    192    }
    193 
    194    if (attr_list)
    195       for (i = 0; attr_list[i] != EGL_NONE; i += 2)
    196          _eglSetConfigKey(&base, attr_list[i], attr_list[i+1]);
    197 
    198    if (depth > 0 && depth != base.BufferSize)
    199       return NULL;
    200 
    201    if (rgba_masks && memcmp(rgba_masks, dri_masks, sizeof(dri_masks)))
    202       return NULL;
    203 
    204    base.NativeRenderable = EGL_TRUE;
    205 
    206    base.SurfaceType = surface_type;
    207    if (surface_type & (EGL_PBUFFER_BIT |
    208        (disp->Extensions.NOK_texture_from_pixmap ? EGL_PIXMAP_BIT : 0))) {
    209       base.BindToTextureRGB = bind_to_texture_rgb;
    210       if (base.AlphaSize > 0)
    211          base.BindToTextureRGBA = bind_to_texture_rgba;
    212    }
    213 
    214    base.RenderableType = disp->ClientAPIs;
    215    base.Conformant = disp->ClientAPIs;
    216 
    217    if (!_eglValidateConfig(&base, EGL_FALSE)) {
    218       _eglLog(_EGL_DEBUG, "DRI2: failed to validate config %d", id);
    219       return NULL;
    220    }
    221 
    222    config_id = base.ConfigID;
    223    base.ConfigID    = EGL_DONT_CARE;
    224    base.SurfaceType = EGL_DONT_CARE;
    225    num_configs = _eglFilterArray(disp->Configs, (void **) &matching_config, 1,
    226                                  (_EGLArrayForEach) dri2_match_config, &base);
    227 
    228    if (num_configs == 1) {
    229       conf = (struct dri2_egl_config *) matching_config;
    230 
    231       if (double_buffer && !conf->dri_double_config)
    232          conf->dri_double_config = dri_config;
    233       else if (!double_buffer && !conf->dri_single_config)
    234          conf->dri_single_config = dri_config;
    235       else
    236          /* a similar config type is already added (unlikely) => discard */
    237          return NULL;
    238    }
    239    else if (num_configs == 0) {
    240       conf = malloc(sizeof *conf);
    241       if (conf == NULL)
    242          return NULL;
    243 
    244       memcpy(&conf->base, &base, sizeof base);
    245       if (double_buffer) {
    246          conf->dri_double_config = dri_config;
    247          conf->dri_single_config = NULL;
    248       } else {
    249          conf->dri_single_config = dri_config;
    250          conf->dri_double_config = NULL;
    251       }
    252       conf->base.SurfaceType = 0;
    253       conf->base.ConfigID = config_id;
    254 
    255       _eglLinkConfig(&conf->base);
    256    }
    257    else {
    258       assert(0);
    259       return NULL;
    260    }
    261 
    262    if (double_buffer) {
    263       surface_type &= ~EGL_PIXMAP_BIT;
    264 
    265       if (dri2_dpy->swap_available) {
    266          conf->base.MinSwapInterval = 0;
    267          conf->base.MaxSwapInterval = 1000; /* XXX arbitrary value */
    268       }
    269    }
    270 
    271    conf->base.SurfaceType |= surface_type;
    272 
    273    return conf;
    274 }
    275 
    276 __DRIimage *
    277 dri2_lookup_egl_image(__DRIscreen *screen, void *image, void *data)
    278 {
    279    _EGLDisplay *disp = data;
    280    struct dri2_egl_image *dri2_img;
    281    _EGLImage *img;
    282 
    283    (void) screen;
    284 
    285    img = _eglLookupImage(image, disp);
    286    if (img == NULL) {
    287       _eglError(EGL_BAD_PARAMETER, "dri2_lookup_egl_image");
    288       return NULL;
    289    }
    290 
    291    dri2_img = dri2_egl_image(image);
    292 
    293    return dri2_img->dri_image;
    294 }
    295 
    296 const __DRIimageLookupExtension image_lookup_extension = {
    297    { __DRI_IMAGE_LOOKUP, 1 },
    298    dri2_lookup_egl_image
    299 };
    300 
    301 static const char dri_driver_path[] = DEFAULT_DRIVER_DIR;
    302 
    303 struct dri2_extension_match {
    304    const char *name;
    305    int version;
    306    int offset;
    307 };
    308 
    309 static struct dri2_extension_match dri2_driver_extensions[] = {
    310    { __DRI_CORE, 1, offsetof(struct dri2_egl_display, core) },
    311    { __DRI_DRI2, 2, offsetof(struct dri2_egl_display, dri2) },
    312    { NULL, 0, 0 }
    313 };
    314 
    315 static struct dri2_extension_match dri2_core_extensions[] = {
    316    { __DRI2_FLUSH, 1, offsetof(struct dri2_egl_display, flush) },
    317    { __DRI_TEX_BUFFER, 2, offsetof(struct dri2_egl_display, tex_buffer) },
    318    { __DRI_IMAGE, 1, offsetof(struct dri2_egl_display, image) },
    319    { NULL, 0, 0 }
    320 };
    321 
    322 static struct dri2_extension_match swrast_driver_extensions[] = {
    323    { __DRI_CORE, 1, offsetof(struct dri2_egl_display, core) },
    324    { __DRI_SWRAST, 2, offsetof(struct dri2_egl_display, swrast) },
    325    { NULL, 0, 0 }
    326 };
    327 
    328 static struct dri2_extension_match swrast_core_extensions[] = {
    329    { __DRI_TEX_BUFFER, 2, offsetof(struct dri2_egl_display, tex_buffer) },
    330    { NULL, 0, 0 }
    331 };
    332 
    333 static EGLBoolean
    334 dri2_bind_extensions(struct dri2_egl_display *dri2_dpy,
    335 		     struct dri2_extension_match *matches,
    336 		     const __DRIextension **extensions)
    337 {
    338    int i, j, ret = EGL_TRUE;
    339    void *field;
    340 
    341    for (i = 0; extensions[i]; i++) {
    342       _eglLog(_EGL_DEBUG, "DRI2: found extension `%s'", extensions[i]->name);
    343       for (j = 0; matches[j].name; j++) {
    344 	 if (strcmp(extensions[i]->name, matches[j].name) == 0 &&
    345 	     extensions[i]->version >= matches[j].version) {
    346 	    field = ((char *) dri2_dpy + matches[j].offset);
    347 	    *(const __DRIextension **) field = extensions[i];
    348 	    _eglLog(_EGL_INFO, "DRI2: found extension %s version %d",
    349 		    extensions[i]->name, extensions[i]->version);
    350 	 }
    351       }
    352    }
    353 
    354    for (j = 0; matches[j].name; j++) {
    355       field = ((char *) dri2_dpy + matches[j].offset);
    356       if (*(const __DRIextension **) field == NULL) {
    357 	 _eglLog(_EGL_FATAL, "DRI2: did not find extension %s version %d",
    358 		 matches[j].name, matches[j].version);
    359 	 ret = EGL_FALSE;
    360       }
    361    }
    362 
    363    return ret;
    364 }
    365 
    366 static const __DRIextension **
    367 dri2_open_driver(_EGLDisplay *disp)
    368 {
    369    struct dri2_egl_display *dri2_dpy = disp->DriverData;
    370    const __DRIextension **extensions;
    371    char path[PATH_MAX], *search_paths, *p, *next, *end;
    372 
    373    search_paths = NULL;
    374    if (geteuid() == getuid()) {
    375       /* don't allow setuid apps to use LIBGL_DRIVERS_PATH */
    376       search_paths = getenv("LIBGL_DRIVERS_PATH");
    377    }
    378    if (search_paths == NULL)
    379       search_paths = DEFAULT_DRIVER_DIR;
    380 
    381    dri2_dpy->driver = NULL;
    382    end = search_paths + strlen(search_paths);
    383    for (p = search_paths; p < end && dri2_dpy->driver == NULL; p = next + 1) {
    384       int len;
    385       next = strchr(p, ':');
    386       if (next == NULL)
    387          next = end;
    388 
    389       len = next - p;
    390 #if GLX_USE_TLS
    391       snprintf(path, sizeof path,
    392 	       "%.*s/tls/%s_dri.so", len, p, dri2_dpy->driver_name);
    393       dri2_dpy->driver = dlopen(path, RTLD_NOW | RTLD_GLOBAL);
    394 #endif
    395       if (dri2_dpy->driver == NULL) {
    396 	 snprintf(path, sizeof path,
    397 		  "%.*s/%s_dri.so", len, p, dri2_dpy->driver_name);
    398 	 dri2_dpy->driver = dlopen(path, RTLD_NOW | RTLD_GLOBAL);
    399 	 if (dri2_dpy->driver == NULL)
    400 	    _eglLog(_EGL_DEBUG, "failed to open %s: %s\n", path, dlerror());
    401       }
    402    }
    403 
    404    if (dri2_dpy->driver == NULL) {
    405       _eglLog(_EGL_WARNING,
    406 	      "DRI2: failed to open %s (search paths %s)",
    407 	      dri2_dpy->driver_name, search_paths);
    408       return NULL;
    409    }
    410 
    411    _eglLog(_EGL_DEBUG, "DRI2: dlopen(%s)", path);
    412    extensions = dlsym(dri2_dpy->driver, __DRI_DRIVER_EXTENSIONS);
    413    if (extensions == NULL) {
    414       _eglLog(_EGL_WARNING,
    415 	      "DRI2: driver exports no extensions (%s)", dlerror());
    416       dlclose(dri2_dpy->driver);
    417    }
    418 
    419    return extensions;
    420 }
    421 
    422 EGLBoolean
    423 dri2_load_driver(_EGLDisplay *disp)
    424 {
    425    struct dri2_egl_display *dri2_dpy = disp->DriverData;
    426    const __DRIextension **extensions;
    427 
    428    extensions = dri2_open_driver(disp);
    429    if (!extensions)
    430       return EGL_FALSE;
    431 
    432    if (!dri2_bind_extensions(dri2_dpy, dri2_driver_extensions, extensions)) {
    433       dlclose(dri2_dpy->driver);
    434       return EGL_FALSE;
    435    }
    436 
    437    return EGL_TRUE;
    438 }
    439 
    440 EGLBoolean
    441 dri2_load_driver_swrast(_EGLDisplay *disp)
    442 {
    443    struct dri2_egl_display *dri2_dpy = disp->DriverData;
    444    const __DRIextension **extensions;
    445 
    446    dri2_dpy->driver_name = "swrast";
    447    extensions = dri2_open_driver(disp);
    448 
    449    if (!extensions)
    450       return EGL_FALSE;
    451 
    452    if (!dri2_bind_extensions(dri2_dpy, swrast_driver_extensions, extensions)) {
    453       dlclose(dri2_dpy->driver);
    454       return EGL_FALSE;
    455    }
    456 
    457    return EGL_TRUE;
    458 }
    459 
    460 void
    461 dri2_setup_screen(_EGLDisplay *disp)
    462 {
    463    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
    464    unsigned int api_mask;
    465 
    466    if (dri2_dpy->dri2) {
    467       api_mask = dri2_dpy->dri2->getAPIMask(dri2_dpy->dri_screen);
    468    } else {
    469       assert(dri2_dpy->swrast);
    470       api_mask = 1 << __DRI_API_OPENGL | 1 << __DRI_API_GLES | 1 << __DRI_API_GLES2;
    471    }
    472 
    473    disp->ClientAPIs = 0;
    474    if (api_mask & (1 <<__DRI_API_OPENGL))
    475       disp->ClientAPIs |= EGL_OPENGL_BIT;
    476    if (api_mask & (1 <<__DRI_API_GLES))
    477       disp->ClientAPIs |= EGL_OPENGL_ES_BIT;
    478    if (api_mask & (1 << __DRI_API_GLES2))
    479       disp->ClientAPIs |= EGL_OPENGL_ES2_BIT;
    480 
    481    assert(dri2_dpy->dri2 || dri2_dpy->swrast);
    482    disp->Extensions.KHR_surfaceless_context = EGL_TRUE;
    483 
    484    if (dri2_dpy->dri2 && dri2_dpy->dri2->base.version >= 3) {
    485       disp->Extensions.KHR_create_context = EGL_TRUE;
    486 
    487       if (dri2_dpy->robustness)
    488          disp->Extensions.EXT_create_context_robustness = EGL_TRUE;
    489    }
    490 
    491    if (dri2_dpy->image) {
    492       disp->Extensions.MESA_drm_image = EGL_TRUE;
    493       disp->Extensions.KHR_image_base = EGL_TRUE;
    494       disp->Extensions.KHR_gl_renderbuffer_image = EGL_TRUE;
    495    }
    496 }
    497 
    498 EGLBoolean
    499 dri2_create_screen(_EGLDisplay *disp)
    500 {
    501    const __DRIextension **extensions;
    502    struct dri2_egl_display *dri2_dpy;
    503 
    504    dri2_dpy = disp->DriverData;
    505 
    506    if (dri2_dpy->dri2) {
    507       dri2_dpy->dri_screen =
    508          dri2_dpy->dri2->createNewScreen(0, dri2_dpy->fd, dri2_dpy->extensions,
    509 				         &dri2_dpy->driver_configs, disp);
    510    } else {
    511       assert(dri2_dpy->swrast);
    512       dri2_dpy->dri_screen =
    513          dri2_dpy->swrast->createNewScreen(0, dri2_dpy->extensions,
    514                                            &dri2_dpy->driver_configs, disp);
    515    }
    516 
    517    if (dri2_dpy->dri_screen == NULL) {
    518       _eglLog(_EGL_WARNING, "DRI2: failed to create dri screen");
    519       return EGL_FALSE;
    520    }
    521 
    522    dri2_dpy->own_dri_screen = 1;
    523 
    524    extensions = dri2_dpy->core->getExtensions(dri2_dpy->dri_screen);
    525 
    526    if (dri2_dpy->dri2) {
    527       unsigned i;
    528 
    529       if (!dri2_bind_extensions(dri2_dpy, dri2_core_extensions, extensions))
    530          goto cleanup_dri_screen;
    531 
    532       for (i = 0; extensions[i]; i++) {
    533 	 if (strcmp(extensions[i]->name, __DRI2_ROBUSTNESS) == 0) {
    534             dri2_dpy->robustness = (__DRIrobustnessExtension *) extensions[i];
    535 	 }
    536       }
    537    } else {
    538       assert(dri2_dpy->swrast);
    539       if (!dri2_bind_extensions(dri2_dpy, swrast_core_extensions, extensions))
    540          goto cleanup_dri_screen;
    541    }
    542 
    543    dri2_setup_screen(disp);
    544 
    545    return EGL_TRUE;
    546 
    547  cleanup_dri_screen:
    548    dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen);
    549 
    550    return EGL_FALSE;
    551 }
    552 
    553 /**
    554  * Called via eglInitialize(), GLX_drv->API.Initialize().
    555  */
    556 static EGLBoolean
    557 dri2_initialize(_EGLDriver *drv, _EGLDisplay *disp)
    558 {
    559    /* not until swrast_dri is supported */
    560    if (disp->Options.UseFallback)
    561       return EGL_FALSE;
    562 
    563    switch (disp->Platform) {
    564 #ifdef HAVE_X11_PLATFORM
    565    case _EGL_PLATFORM_X11:
    566       if (disp->Options.TestOnly)
    567          return EGL_TRUE;
    568       return dri2_initialize_x11(drv, disp);
    569 #endif
    570 
    571 #ifdef HAVE_LIBUDEV
    572 #ifdef HAVE_DRM_PLATFORM
    573    case _EGL_PLATFORM_DRM:
    574       if (disp->Options.TestOnly)
    575          return EGL_TRUE;
    576       return dri2_initialize_drm(drv, disp);
    577 #endif
    578 #ifdef HAVE_WAYLAND_PLATFORM
    579    case _EGL_PLATFORM_WAYLAND:
    580       if (disp->Options.TestOnly)
    581          return EGL_TRUE;
    582       return dri2_initialize_wayland(drv, disp);
    583 #endif
    584 #endif
    585 #ifdef HAVE_ANDROID_PLATFORM
    586    case _EGL_PLATFORM_ANDROID:
    587       if (disp->Options.TestOnly)
    588          return EGL_TRUE;
    589       return dri2_initialize_android(drv, disp);
    590 #endif
    591 
    592    default:
    593       return EGL_FALSE;
    594    }
    595 }
    596 
    597 /**
    598  * Called via eglTerminate(), drv->API.Terminate().
    599  */
    600 static EGLBoolean
    601 dri2_terminate(_EGLDriver *drv, _EGLDisplay *disp)
    602 {
    603    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
    604 
    605    _eglReleaseDisplayResources(drv, disp);
    606    _eglCleanupDisplay(disp);
    607 
    608    if (dri2_dpy->own_dri_screen)
    609       dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen);
    610    if (dri2_dpy->fd)
    611       close(dri2_dpy->fd);
    612    if (dri2_dpy->driver)
    613       dlclose(dri2_dpy->driver);
    614    if (dri2_dpy->device_name)
    615       free(dri2_dpy->device_name);
    616 
    617    if (disp->PlatformDisplay == NULL) {
    618       switch (disp->Platform) {
    619 #ifdef HAVE_X11_PLATFORM
    620       case _EGL_PLATFORM_X11:
    621          xcb_disconnect(dri2_dpy->conn);
    622          break;
    623 #endif
    624 #ifdef HAVE_DRM_PLATFORM
    625       case _EGL_PLATFORM_DRM:
    626          if (dri2_dpy->own_device) {
    627             gbm_device_destroy(&dri2_dpy->gbm_dri->base.base);
    628          }
    629          break;
    630 #endif
    631       default:
    632          break;
    633       }
    634    }
    635 
    636    free(dri2_dpy);
    637    disp->DriverData = NULL;
    638 
    639    return EGL_TRUE;
    640 }
    641 
    642 /**
    643  * Set the error code after a call to
    644  * dri2_egl_display::dri2::createContextAttribs.
    645  */
    646 static void
    647 dri2_create_context_attribs_error(int dri_error)
    648 {
    649    EGLint egl_error;
    650 
    651    switch (dri_error) {
    652    case __DRI_CTX_ERROR_SUCCESS:
    653       return;
    654 
    655    case __DRI_CTX_ERROR_NO_MEMORY:
    656       egl_error = EGL_BAD_ALLOC;
    657       break;
    658 
    659   /* From the EGL_KHR_create_context spec, section "Errors":
    660    *
    661    *   * If <config> does not support a client API context compatible
    662    *     with the requested API major and minor version, [...] context flags,
    663    *     and context reset notification behavior (for client API types where
    664    *     these attributes are supported), then an EGL_BAD_MATCH error is
    665    *     generated.
    666    *
    667    *   * If an OpenGL ES context is requested and the values for
    668    *     attributes EGL_CONTEXT_MAJOR_VERSION_KHR and
    669    *     EGL_CONTEXT_MINOR_VERSION_KHR specify an OpenGL ES version that
    670    *     is not defined, than an EGL_BAD_MATCH error is generated.
    671    *
    672    *   * If an OpenGL context is requested, the requested version is
    673    *     greater than 3.2, and the value for attribute
    674    *     EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR has no bits set; has any
    675    *     bits set other than EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR and
    676    *     EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR; has more than
    677    *     one of these bits set; or if the implementation does not support
    678    *     the requested profile, then an EGL_BAD_MATCH error is generated.
    679    */
    680    case __DRI_CTX_ERROR_BAD_API:
    681    case __DRI_CTX_ERROR_BAD_VERSION:
    682    case __DRI_CTX_ERROR_BAD_FLAG:
    683       egl_error = EGL_BAD_MATCH;
    684       break;
    685 
    686   /* From the EGL_KHR_create_context spec, section "Errors":
    687    *
    688    *   * If an attribute name or attribute value in <attrib_list> is not
    689    *     recognized (including unrecognized bits in bitmask attributes),
    690    *     then an EGL_BAD_ATTRIBUTE error is generated."
    691    */
    692    case __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE:
    693    case __DRI_CTX_ERROR_UNKNOWN_FLAG:
    694       egl_error = EGL_BAD_ATTRIBUTE;
    695       break;
    696 
    697    default:
    698       assert(0);
    699       egl_error = EGL_BAD_MATCH;
    700       break;
    701    }
    702 
    703    _eglError(egl_error, "dri2_create_context");
    704 }
    705 
    706 /**
    707  * Called via eglCreateContext(), drv->API.CreateContext().
    708  */
    709 static _EGLContext *
    710 dri2_create_context(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf,
    711 		    _EGLContext *share_list, const EGLint *attrib_list)
    712 {
    713    struct dri2_egl_context *dri2_ctx;
    714    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
    715    struct dri2_egl_context *dri2_ctx_shared = dri2_egl_context(share_list);
    716    __DRIcontext *shared =
    717       dri2_ctx_shared ? dri2_ctx_shared->dri_context : NULL;
    718    struct dri2_egl_config *dri2_config = dri2_egl_config(conf);
    719    const __DRIconfig *dri_config;
    720    int api;
    721 
    722    (void) drv;
    723 
    724    dri2_ctx = malloc(sizeof *dri2_ctx);
    725    if (!dri2_ctx) {
    726       _eglError(EGL_BAD_ALLOC, "eglCreateContext");
    727       return NULL;
    728    }
    729 
    730    if (!_eglInitContext(&dri2_ctx->base, disp, conf, attrib_list))
    731       goto cleanup;
    732 
    733    switch (dri2_ctx->base.ClientAPI) {
    734    case EGL_OPENGL_ES_API:
    735       switch (dri2_ctx->base.ClientMajorVersion) {
    736       case 1:
    737          api = __DRI_API_GLES;
    738          break;
    739       case 2:
    740       case 3:
    741          api = __DRI_API_GLES2;
    742          break;
    743       default:
    744 	 _eglError(EGL_BAD_PARAMETER, "eglCreateContext");
    745 	 return NULL;
    746       }
    747       break;
    748    case EGL_OPENGL_API:
    749       if ((dri2_ctx->base.ClientMajorVersion >= 4
    750            || (dri2_ctx->base.ClientMajorVersion == 3
    751                && dri2_ctx->base.ClientMinorVersion >= 2))
    752           && dri2_ctx->base.Profile == EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR)
    753          api = __DRI_API_OPENGL_CORE;
    754       else
    755          api = __DRI_API_OPENGL;
    756       break;
    757    default:
    758       _eglError(EGL_BAD_PARAMETER, "eglCreateContext");
    759       return NULL;
    760    }
    761 
    762    if (conf != NULL) {
    763       /* The config chosen here isn't necessarily
    764        * used for surfaces later.
    765        * A pixmap surface will use the single config.
    766        * This opportunity depends on disabling the
    767        * doubleBufferMode check in
    768        * src/mesa/main/context.c:check_compatible()
    769        */
    770       if (dri2_config->dri_double_config)
    771          dri_config = dri2_config->dri_double_config;
    772       else
    773          dri_config = dri2_config->dri_single_config;
    774 
    775       /* EGL_WINDOW_BIT is set only when there is a dri_double_config.  This
    776        * makes sure the back buffer will always be used.
    777        */
    778       if (conf->SurfaceType & EGL_WINDOW_BIT)
    779          dri2_ctx->base.WindowRenderBuffer = EGL_BACK_BUFFER;
    780    }
    781    else
    782       dri_config = NULL;
    783 
    784    if (dri2_dpy->dri2) {
    785       if (dri2_dpy->dri2->base.version >= 3) {
    786          unsigned error;
    787          unsigned num_attribs = 0;
    788          uint32_t ctx_attribs[8];
    789 
    790          ctx_attribs[num_attribs++] = __DRI_CTX_ATTRIB_MAJOR_VERSION;
    791          ctx_attribs[num_attribs++] = dri2_ctx->base.ClientMajorVersion;
    792          ctx_attribs[num_attribs++] = __DRI_CTX_ATTRIB_MINOR_VERSION;
    793          ctx_attribs[num_attribs++] = dri2_ctx->base.ClientMinorVersion;
    794 
    795          if (dri2_ctx->base.Flags != 0) {
    796             /* If the implementation doesn't support the __DRI2_ROBUSTNESS
    797              * extension, don't even try to send it the robust-access flag.
    798              * It may explode.  Instead, generate the required EGL error here.
    799              */
    800             if ((dri2_ctx->base.Flags & EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR) != 0
    801                 && !dri2_dpy->robustness) {
    802                _eglError(EGL_BAD_MATCH, "eglCreateContext");
    803                goto cleanup;
    804             }
    805 
    806             ctx_attribs[num_attribs++] = __DRI_CTX_ATTRIB_FLAGS;
    807             ctx_attribs[num_attribs++] = dri2_ctx->base.Flags;
    808          }
    809 
    810          if (dri2_ctx->base.ResetNotificationStrategy != EGL_NO_RESET_NOTIFICATION_KHR) {
    811             /* If the implementation doesn't support the __DRI2_ROBUSTNESS
    812              * extension, don't even try to send it a reset strategy.  It may
    813              * explode.  Instead, generate the required EGL error here.
    814              */
    815             if (!dri2_dpy->robustness) {
    816                _eglError(EGL_BAD_CONFIG, "eglCreateContext");
    817                goto cleanup;
    818             }
    819 
    820             ctx_attribs[num_attribs++] = __DRI_CTX_ATTRIB_RESET_STRATEGY;
    821             ctx_attribs[num_attribs++] = __DRI_CTX_RESET_LOSE_CONTEXT;
    822          }
    823 
    824          assert(num_attribs <= ARRAY_SIZE(ctx_attribs));
    825 
    826 	 dri2_ctx->dri_context =
    827 	    dri2_dpy->dri2->createContextAttribs(dri2_dpy->dri_screen,
    828                                                  api,
    829                                                  dri_config,
    830                                                  shared,
    831                                                  num_attribs / 2,
    832                                                  ctx_attribs,
    833                                                  & error,
    834                                                  dri2_ctx);
    835 	 dri2_create_context_attribs_error(error);
    836       } else {
    837 	 dri2_ctx->dri_context =
    838 	    dri2_dpy->dri2->createNewContextForAPI(dri2_dpy->dri_screen,
    839 						   api,
    840 						   dri_config,
    841                                                    shared,
    842 						   dri2_ctx);
    843       }
    844    } else {
    845       assert(dri2_dpy->swrast);
    846       dri2_ctx->dri_context =
    847          dri2_dpy->swrast->createNewContextForAPI(dri2_dpy->dri_screen,
    848                                                   api,
    849                                                   dri_config,
    850                                                   shared,
    851                                                   dri2_ctx);
    852    }
    853 
    854    if (!dri2_ctx->dri_context)
    855       goto cleanup;
    856 
    857    return &dri2_ctx->base;
    858 
    859  cleanup:
    860    free(dri2_ctx);
    861    return NULL;
    862 }
    863 
    864 /**
    865  * Called via eglDestroyContext(), drv->API.DestroyContext().
    866  */
    867 static EGLBoolean
    868 dri2_destroy_context(_EGLDriver *drv, _EGLDisplay *disp, _EGLContext *ctx)
    869 {
    870    struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
    871    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
    872 
    873    if (_eglPutContext(ctx)) {
    874       dri2_dpy->core->destroyContext(dri2_ctx->dri_context);
    875       free(dri2_ctx);
    876    }
    877 
    878    return EGL_TRUE;
    879 }
    880 
    881 /**
    882  * Called via eglMakeCurrent(), drv->API.MakeCurrent().
    883  */
    884 static EGLBoolean
    885 dri2_make_current(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *dsurf,
    886 		  _EGLSurface *rsurf, _EGLContext *ctx)
    887 {
    888    struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv);
    889    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
    890    struct dri2_egl_surface *dri2_dsurf = dri2_egl_surface(dsurf);
    891    struct dri2_egl_surface *dri2_rsurf = dri2_egl_surface(rsurf);
    892    struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
    893    _EGLContext *old_ctx;
    894    _EGLSurface *old_dsurf, *old_rsurf;
    895    __DRIdrawable *ddraw, *rdraw;
    896    __DRIcontext *cctx;
    897 
    898    /* make new bindings */
    899    if (!_eglBindContext(ctx, dsurf, rsurf, &old_ctx, &old_dsurf, &old_rsurf))
    900       return EGL_FALSE;
    901 
    902    /* flush before context switch */
    903    if (old_ctx && dri2_drv->glFlush)
    904       dri2_drv->glFlush();
    905 
    906    ddraw = (dri2_dsurf) ? dri2_dsurf->dri_drawable : NULL;
    907    rdraw = (dri2_rsurf) ? dri2_rsurf->dri_drawable : NULL;
    908    cctx = (dri2_ctx) ? dri2_ctx->dri_context : NULL;
    909 
    910    if (old_ctx) {
    911       __DRIcontext *old_cctx = dri2_egl_context(old_ctx)->dri_context;
    912       dri2_dpy->core->unbindContext(old_cctx);
    913    }
    914 
    915    if ((cctx == NULL && ddraw == NULL && rdraw == NULL) ||
    916        dri2_dpy->core->bindContext(cctx, ddraw, rdraw)) {
    917       if (old_dsurf)
    918          drv->API.DestroySurface(drv, disp, old_dsurf);
    919       if (old_rsurf)
    920          drv->API.DestroySurface(drv, disp, old_rsurf);
    921       if (old_ctx)
    922          drv->API.DestroyContext(drv, disp, old_ctx);
    923 
    924       return EGL_TRUE;
    925    } else {
    926       /* undo the previous _eglBindContext */
    927       _eglBindContext(old_ctx, old_dsurf, old_rsurf, &ctx, &dsurf, &rsurf);
    928       assert(&dri2_ctx->base == ctx &&
    929              &dri2_dsurf->base == dsurf &&
    930              &dri2_rsurf->base == rsurf);
    931 
    932       _eglPutSurface(dsurf);
    933       _eglPutSurface(rsurf);
    934       _eglPutContext(ctx);
    935 
    936       _eglPutSurface(old_dsurf);
    937       _eglPutSurface(old_rsurf);
    938       _eglPutContext(old_ctx);
    939 
    940       return EGL_FALSE;
    941    }
    942 }
    943 
    944 /*
    945  * Called from eglGetProcAddress() via drv->API.GetProcAddress().
    946  */
    947 static _EGLProc
    948 dri2_get_proc_address(_EGLDriver *drv, const char *procname)
    949 {
    950    struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv);
    951 
    952    return dri2_drv->get_proc_address(procname);
    953 }
    954 
    955 static EGLBoolean
    956 dri2_wait_client(_EGLDriver *drv, _EGLDisplay *disp, _EGLContext *ctx)
    957 {
    958    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
    959    struct dri2_egl_surface *dri2_surf = dri2_egl_surface(ctx->DrawSurface);
    960 
    961    (void) drv;
    962 
    963    /* FIXME: If EGL allows frontbuffer rendering for window surfaces,
    964     * we need to copy fake to real here.*/
    965 
    966    (*dri2_dpy->flush->flush)(dri2_surf->dri_drawable);
    967 
    968    return EGL_TRUE;
    969 }
    970 
    971 static EGLBoolean
    972 dri2_wait_native(_EGLDriver *drv, _EGLDisplay *disp, EGLint engine)
    973 {
    974    (void) drv;
    975    (void) disp;
    976 
    977    if (engine != EGL_CORE_NATIVE_ENGINE)
    978       return _eglError(EGL_BAD_PARAMETER, "eglWaitNative");
    979    /* glXWaitX(); */
    980 
    981    return EGL_TRUE;
    982 }
    983 
    984 static EGLBoolean
    985 dri2_bind_tex_image(_EGLDriver *drv,
    986 		    _EGLDisplay *disp, _EGLSurface *surf, EGLint buffer)
    987 {
    988    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
    989    struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
    990    struct dri2_egl_context *dri2_ctx;
    991    _EGLContext *ctx;
    992    GLint format, target;
    993 
    994    ctx = _eglGetCurrentContext();
    995    dri2_ctx = dri2_egl_context(ctx);
    996 
    997    if (!_eglBindTexImage(drv, disp, surf, buffer))
    998       return EGL_FALSE;
    999 
   1000    switch (dri2_surf->base.TextureFormat) {
   1001    case EGL_TEXTURE_RGB:
   1002       format = __DRI_TEXTURE_FORMAT_RGB;
   1003       break;
   1004    case EGL_TEXTURE_RGBA:
   1005       format = __DRI_TEXTURE_FORMAT_RGBA;
   1006       break;
   1007    default:
   1008       assert(0);
   1009    }
   1010 
   1011    switch (dri2_surf->base.TextureTarget) {
   1012    case EGL_TEXTURE_2D:
   1013       target = GL_TEXTURE_2D;
   1014       break;
   1015    default:
   1016       assert(0);
   1017    }
   1018 
   1019    (*dri2_dpy->tex_buffer->setTexBuffer2)(dri2_ctx->dri_context,
   1020 					  target, format,
   1021 					  dri2_surf->dri_drawable);
   1022 
   1023    return EGL_TRUE;
   1024 }
   1025 
   1026 static EGLBoolean
   1027 dri2_release_tex_image(_EGLDriver *drv,
   1028 		       _EGLDisplay *disp, _EGLSurface *surf, EGLint buffer)
   1029 {
   1030 #if __DRI_TEX_BUFFER_VERSION >= 3
   1031    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
   1032    struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
   1033    struct dri2_egl_context *dri2_ctx;
   1034    _EGLContext *ctx;
   1035    GLint  target;
   1036 
   1037    ctx = _eglGetCurrentContext();
   1038    dri2_ctx = dri2_egl_context(ctx);
   1039 
   1040    if (!_eglReleaseTexImage(drv, disp, surf, buffer))
   1041       return EGL_FALSE;
   1042 
   1043    switch (dri2_surf->base.TextureTarget) {
   1044    case EGL_TEXTURE_2D:
   1045       target = GL_TEXTURE_2D;
   1046       break;
   1047    default:
   1048       assert(0);
   1049    }
   1050    if (dri2_dpy->tex_buffer->releaseTexBuffer!=NULL)
   1051     (*dri2_dpy->tex_buffer->releaseTexBuffer)(dri2_ctx->dri_context,
   1052                                              target,
   1053                                              dri2_surf->dri_drawable);
   1054 #endif
   1055 
   1056    return EGL_TRUE;
   1057 }
   1058 
   1059 static _EGLImage *
   1060 dri2_create_image(_EGLDisplay *disp, __DRIimage *dri_image)
   1061 {
   1062    struct dri2_egl_image *dri2_img;
   1063 
   1064    if (dri_image == NULL) {
   1065       _eglError(EGL_BAD_ALLOC, "dri2_create_image");
   1066       return NULL;
   1067    }
   1068 
   1069    dri2_img = malloc(sizeof *dri2_img);
   1070    if (!dri2_img) {
   1071       _eglError(EGL_BAD_ALLOC, "dri2_create_image");
   1072       return NULL;
   1073    }
   1074 
   1075    if (!_eglInitImage(&dri2_img->base, disp)) {
   1076       free(dri2_img);
   1077       return NULL;
   1078    }
   1079 
   1080    dri2_img->dri_image = dri_image;
   1081 
   1082    return &dri2_img->base;
   1083 }
   1084 
   1085 static _EGLImage *
   1086 dri2_create_image_khr_renderbuffer(_EGLDisplay *disp, _EGLContext *ctx,
   1087 				   EGLClientBuffer buffer,
   1088 				   const EGLint *attr_list)
   1089 {
   1090    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
   1091    struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
   1092    GLuint renderbuffer = (GLuint) (uintptr_t) buffer;
   1093    __DRIimage *dri_image;
   1094 
   1095    if (renderbuffer == 0) {
   1096       _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
   1097       return EGL_NO_IMAGE_KHR;
   1098    }
   1099 
   1100    dri_image =
   1101       dri2_dpy->image->createImageFromRenderbuffer(dri2_ctx->dri_context,
   1102                                                    renderbuffer, NULL);
   1103 
   1104    return dri2_create_image(disp, dri_image);
   1105 }
   1106 
   1107 static _EGLImage *
   1108 dri2_create_image_mesa_drm_buffer(_EGLDisplay *disp, _EGLContext *ctx,
   1109 				  EGLClientBuffer buffer, const EGLint *attr_list)
   1110 {
   1111    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
   1112    EGLint format, name, pitch, err;
   1113    _EGLImageAttribs attrs;
   1114    __DRIimage *dri_image;
   1115 
   1116    name = (EGLint) (uintptr_t) buffer;
   1117 
   1118    err = _eglParseImageAttribList(&attrs, disp, attr_list);
   1119    if (err != EGL_SUCCESS)
   1120       return NULL;
   1121 
   1122    if (attrs.Width <= 0 || attrs.Height <= 0 ||
   1123        attrs.DRMBufferStrideMESA <= 0) {
   1124       _eglError(EGL_BAD_PARAMETER,
   1125 		"bad width, height or stride");
   1126       return NULL;
   1127    }
   1128 
   1129    switch (attrs.DRMBufferFormatMESA) {
   1130    case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA:
   1131       format = __DRI_IMAGE_FORMAT_ARGB8888;
   1132       pitch = attrs.DRMBufferStrideMESA;
   1133       break;
   1134    default:
   1135       _eglError(EGL_BAD_PARAMETER,
   1136 		"dri2_create_image_khr: unsupported pixmap depth");
   1137       return NULL;
   1138    }
   1139 
   1140    dri_image =
   1141       dri2_dpy->image->createImageFromName(dri2_dpy->dri_screen,
   1142 					   attrs.Width,
   1143 					   attrs.Height,
   1144 					   format,
   1145 					   name,
   1146 					   pitch,
   1147 					   NULL);
   1148 
   1149    return dri2_create_image(disp, dri_image);
   1150 }
   1151 
   1152 #ifdef HAVE_WAYLAND_PLATFORM
   1153 
   1154 /* This structure describes how a wl_buffer maps to one or more
   1155  * __DRIimages.  A wl_drm_buffer stores the wl_drm format code and the
   1156  * offsets and strides of the planes in the buffer.  This table maps a
   1157  * wl_drm format code to a description of the planes in the buffer
   1158  * that lets us create a __DRIimage for each of the planes. */
   1159 
   1160 static const struct wl_drm_components_descriptor {
   1161    uint32_t dri_components;
   1162    EGLint components;
   1163    int nplanes;
   1164 } wl_drm_components[] = {
   1165    { __DRI_IMAGE_COMPONENTS_RGB, EGL_TEXTURE_RGB, 1 },
   1166    { __DRI_IMAGE_COMPONENTS_RGBA, EGL_TEXTURE_RGBA, 1 },
   1167    { __DRI_IMAGE_COMPONENTS_Y_U_V, EGL_TEXTURE_Y_U_V_WL, 3 },
   1168    { __DRI_IMAGE_COMPONENTS_Y_UV, EGL_TEXTURE_Y_UV_WL, 2 },
   1169    { __DRI_IMAGE_COMPONENTS_Y_XUXV, EGL_TEXTURE_Y_XUXV_WL, 2 },
   1170 };
   1171 
   1172 static _EGLImage *
   1173 dri2_create_image_wayland_wl_buffer(_EGLDisplay *disp, _EGLContext *ctx,
   1174 				    EGLClientBuffer _buffer,
   1175 				    const EGLint *attr_list)
   1176 {
   1177    struct wl_drm_buffer *buffer = (struct wl_drm_buffer *) _buffer;
   1178    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
   1179    const struct wl_drm_components_descriptor *f;
   1180    __DRIimage *dri_image;
   1181    _EGLImageAttribs attrs;
   1182    EGLint err;
   1183    int32_t plane;
   1184 
   1185    if (!wayland_buffer_is_drm(&buffer->buffer))
   1186        return NULL;
   1187 
   1188    err = _eglParseImageAttribList(&attrs, disp, attr_list);
   1189    plane = attrs.PlaneWL;
   1190    if (err != EGL_SUCCESS) {
   1191       _eglError(EGL_BAD_PARAMETER, "dri2_create_image_wayland_wl_buffer");
   1192       return NULL;
   1193    }
   1194 
   1195    f = buffer->driver_format;
   1196    if (plane < 0 || plane >= f->nplanes) {
   1197       _eglError(EGL_BAD_PARAMETER,
   1198                 "dri2_create_image_wayland_wl_buffer (plane out of bounds)");
   1199       return NULL;
   1200    }
   1201 
   1202    dri_image = dri2_dpy->image->fromPlanar(buffer->driver_buffer, plane, NULL);
   1203 
   1204    if (dri_image == NULL) {
   1205       _eglError(EGL_BAD_PARAMETER, "dri2_create_image_wayland_wl_buffer");
   1206       return NULL;
   1207    }
   1208 
   1209    return dri2_create_image(disp, dri_image);
   1210 }
   1211 #endif
   1212 
   1213 _EGLImage *
   1214 dri2_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
   1215 		      _EGLContext *ctx, EGLenum target,
   1216 		      EGLClientBuffer buffer, const EGLint *attr_list)
   1217 {
   1218    (void) drv;
   1219 
   1220    switch (target) {
   1221    case EGL_GL_RENDERBUFFER_KHR:
   1222       return dri2_create_image_khr_renderbuffer(disp, ctx, buffer, attr_list);
   1223    case EGL_DRM_BUFFER_MESA:
   1224       return dri2_create_image_mesa_drm_buffer(disp, ctx, buffer, attr_list);
   1225 #ifdef HAVE_WAYLAND_PLATFORM
   1226    case EGL_WAYLAND_BUFFER_WL:
   1227       return dri2_create_image_wayland_wl_buffer(disp, ctx, buffer, attr_list);
   1228 #endif
   1229    default:
   1230       _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
   1231       return EGL_NO_IMAGE_KHR;
   1232    }
   1233 }
   1234 
   1235 static EGLBoolean
   1236 dri2_destroy_image_khr(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *image)
   1237 {
   1238    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
   1239    struct dri2_egl_image *dri2_img = dri2_egl_image(image);
   1240 
   1241    (void) drv;
   1242 
   1243    dri2_dpy->image->destroyImage(dri2_img->dri_image);
   1244    free(dri2_img);
   1245 
   1246    return EGL_TRUE;
   1247 }
   1248 
   1249 static _EGLImage *
   1250 dri2_create_drm_image_mesa(_EGLDriver *drv, _EGLDisplay *disp,
   1251 			   const EGLint *attr_list)
   1252 {
   1253    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
   1254    struct dri2_egl_image *dri2_img;
   1255    _EGLImageAttribs attrs;
   1256    unsigned int dri_use, valid_mask;
   1257    int format;
   1258    EGLint err = EGL_SUCCESS;
   1259 
   1260    (void) drv;
   1261 
   1262    dri2_img = malloc(sizeof *dri2_img);
   1263    if (!dri2_img) {
   1264       _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr");
   1265       return EGL_NO_IMAGE_KHR;
   1266    }
   1267 
   1268    if (!attr_list) {
   1269       err = EGL_BAD_PARAMETER;
   1270       goto cleanup_img;
   1271    }
   1272 
   1273    if (!_eglInitImage(&dri2_img->base, disp)) {
   1274       err = EGL_BAD_PARAMETER;
   1275       goto cleanup_img;
   1276    }
   1277 
   1278    err = _eglParseImageAttribList(&attrs, disp, attr_list);
   1279    if (err != EGL_SUCCESS)
   1280       goto cleanup_img;
   1281 
   1282    if (attrs.Width <= 0 || attrs.Height <= 0) {
   1283       _eglLog(_EGL_WARNING, "bad width or height (%dx%d)",
   1284             attrs.Width, attrs.Height);
   1285       goto cleanup_img;
   1286    }
   1287 
   1288    switch (attrs.DRMBufferFormatMESA) {
   1289    case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA:
   1290       format = __DRI_IMAGE_FORMAT_ARGB8888;
   1291       break;
   1292    default:
   1293       _eglLog(_EGL_WARNING, "bad image format value 0x%04x",
   1294             attrs.DRMBufferFormatMESA);
   1295       goto cleanup_img;
   1296    }
   1297 
   1298    valid_mask =
   1299       EGL_DRM_BUFFER_USE_SCANOUT_MESA |
   1300       EGL_DRM_BUFFER_USE_SHARE_MESA |
   1301       EGL_DRM_BUFFER_USE_CURSOR_MESA;
   1302    if (attrs.DRMBufferUseMESA & ~valid_mask) {
   1303       _eglLog(_EGL_WARNING, "bad image use bit 0x%04x",
   1304             attrs.DRMBufferUseMESA & ~valid_mask);
   1305       goto cleanup_img;
   1306    }
   1307 
   1308    dri_use = 0;
   1309    if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_SHARE_MESA)
   1310       dri_use |= __DRI_IMAGE_USE_SHARE;
   1311    if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_SCANOUT_MESA)
   1312       dri_use |= __DRI_IMAGE_USE_SCANOUT;
   1313    if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_CURSOR_MESA)
   1314       dri_use |= __DRI_IMAGE_USE_CURSOR;
   1315 
   1316    dri2_img->dri_image =
   1317       dri2_dpy->image->createImage(dri2_dpy->dri_screen,
   1318 				   attrs.Width, attrs.Height,
   1319                                    format, dri_use, dri2_img);
   1320    if (dri2_img->dri_image == NULL) {
   1321       err = EGL_BAD_ALLOC;
   1322       goto cleanup_img;
   1323    }
   1324 
   1325    return &dri2_img->base;
   1326 
   1327  cleanup_img:
   1328    free(dri2_img);
   1329    _eglError(err, "dri2_create_drm_image_mesa");
   1330 
   1331    return EGL_NO_IMAGE_KHR;
   1332 }
   1333 
   1334 static EGLBoolean
   1335 dri2_export_drm_image_mesa(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *img,
   1336 			  EGLint *name, EGLint *handle, EGLint *stride)
   1337 {
   1338    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
   1339    struct dri2_egl_image *dri2_img = dri2_egl_image(img);
   1340 
   1341    (void) drv;
   1342 
   1343    if (name && !dri2_dpy->image->queryImage(dri2_img->dri_image,
   1344 					    __DRI_IMAGE_ATTRIB_NAME, name)) {
   1345       _eglError(EGL_BAD_ALLOC, "dri2_export_drm_image_mesa");
   1346       return EGL_FALSE;
   1347    }
   1348 
   1349    if (handle)
   1350       dri2_dpy->image->queryImage(dri2_img->dri_image,
   1351 				  __DRI_IMAGE_ATTRIB_HANDLE, handle);
   1352 
   1353    if (stride)
   1354       dri2_dpy->image->queryImage(dri2_img->dri_image,
   1355 				  __DRI_IMAGE_ATTRIB_STRIDE, stride);
   1356 
   1357    return EGL_TRUE;
   1358 }
   1359 
   1360 #ifdef HAVE_WAYLAND_PLATFORM
   1361 
   1362 static void
   1363 dri2_wl_reference_buffer(void *user_data, uint32_t name,
   1364                          struct wl_drm_buffer *buffer)
   1365 {
   1366    _EGLDisplay *disp = user_data;
   1367    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
   1368    __DRIimage *img;
   1369    int i, dri_components = 0;
   1370 
   1371    img = dri2_dpy->image->createImageFromNames(dri2_dpy->dri_screen,
   1372                                                buffer->buffer.width,
   1373                                                buffer->buffer.height,
   1374                                                buffer->format, (int*)&name, 1,
   1375                                                buffer->stride,
   1376                                                buffer->offset,
   1377                                                NULL);
   1378 
   1379    if (img == NULL)
   1380       return;
   1381 
   1382    dri2_dpy->image->queryImage(img, __DRI_IMAGE_ATTRIB_COMPONENTS, &dri_components);
   1383 
   1384    buffer->driver_format = NULL;
   1385    for (i = 0; i < ARRAY_SIZE(wl_drm_components); i++)
   1386       if (wl_drm_components[i].dri_components == dri_components)
   1387          buffer->driver_format = &wl_drm_components[i];
   1388 
   1389    if (buffer->driver_format == NULL)
   1390       dri2_dpy->image->destroyImage(img);
   1391    else
   1392       buffer->driver_buffer = img;
   1393 }
   1394 
   1395 static void
   1396 dri2_wl_release_buffer(void *user_data, struct wl_drm_buffer *buffer)
   1397 {
   1398    _EGLDisplay *disp = user_data;
   1399    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
   1400 
   1401    dri2_dpy->image->destroyImage(buffer->driver_buffer);
   1402 }
   1403 
   1404 static struct wayland_drm_callbacks wl_drm_callbacks = {
   1405 	.authenticate = NULL,
   1406 	.reference_buffer = dri2_wl_reference_buffer,
   1407 	.release_buffer = dri2_wl_release_buffer
   1408 };
   1409 
   1410 static EGLBoolean
   1411 dri2_bind_wayland_display_wl(_EGLDriver *drv, _EGLDisplay *disp,
   1412 			     struct wl_display *wl_dpy)
   1413 {
   1414    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
   1415 
   1416    (void) drv;
   1417 
   1418    if (dri2_dpy->wl_server_drm)
   1419 	   return EGL_FALSE;
   1420 
   1421    wl_drm_callbacks.authenticate =
   1422       (int(*)(void *, uint32_t)) dri2_dpy->authenticate;
   1423 
   1424    dri2_dpy->wl_server_drm =
   1425 	   wayland_drm_init(wl_dpy, dri2_dpy->device_name,
   1426                             &wl_drm_callbacks, disp);
   1427 
   1428    if (!dri2_dpy->wl_server_drm)
   1429 	   return EGL_FALSE;
   1430 
   1431    return EGL_TRUE;
   1432 }
   1433 
   1434 static EGLBoolean
   1435 dri2_unbind_wayland_display_wl(_EGLDriver *drv, _EGLDisplay *disp,
   1436 			       struct wl_display *wl_dpy)
   1437 {
   1438    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
   1439 
   1440    (void) drv;
   1441 
   1442    if (!dri2_dpy->wl_server_drm)
   1443 	   return EGL_FALSE;
   1444 
   1445    wayland_drm_uninit(dri2_dpy->wl_server_drm);
   1446    dri2_dpy->wl_server_drm = NULL;
   1447 
   1448    return EGL_TRUE;
   1449 }
   1450 
   1451 static EGLBoolean
   1452 dri2_query_wayland_buffer_wl(_EGLDriver *drv, _EGLDisplay *disp,
   1453                              struct wl_buffer *_buffer,
   1454                              EGLint attribute, EGLint *value)
   1455 {
   1456    struct wl_drm_buffer *buffer = (struct wl_drm_buffer *) _buffer;
   1457    const struct wl_drm_components_descriptor *format;
   1458 
   1459    if (!wayland_buffer_is_drm(&buffer->buffer))
   1460       return EGL_FALSE;
   1461 
   1462    format = buffer->driver_format;
   1463    switch (attribute) {
   1464    case EGL_TEXTURE_FORMAT:
   1465       *value = format->components;
   1466       return EGL_TRUE;
   1467    case EGL_WIDTH:
   1468       *value = buffer->buffer.width;
   1469       break;
   1470    case EGL_HEIGHT:
   1471       *value = buffer->buffer.height;
   1472       break;
   1473    }
   1474 
   1475    return EGL_FALSE;
   1476 }
   1477 #endif
   1478 
   1479 static void
   1480 dri2_unload(_EGLDriver *drv)
   1481 {
   1482    struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv);
   1483 
   1484    if (dri2_drv->handle)
   1485       dlclose(dri2_drv->handle);
   1486    free(dri2_drv);
   1487 }
   1488 
   1489 static EGLBoolean
   1490 dri2_load(_EGLDriver *drv)
   1491 {
   1492    struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv);
   1493 #ifdef HAVE_SHARED_GLAPI
   1494 #ifdef HAVE_ANDROID_PLATFORM
   1495    const char *libname = "libglapi.so";
   1496 #else
   1497    const char *libname = "libglapi.so.0";
   1498 #endif
   1499 #else
   1500    /*
   1501     * Both libGL.so and libglapi.so are glapi providers.  There is no way to
   1502     * tell which one to load.
   1503     */
   1504    const char *libname = NULL;
   1505 #endif
   1506    void *handle;
   1507 
   1508    /* RTLD_GLOBAL to make sure glapi symbols are visible to DRI drivers */
   1509    handle = dlopen(libname, RTLD_LAZY | RTLD_GLOBAL);
   1510    if (handle) {
   1511       dri2_drv->get_proc_address = (_EGLProc (*)(const char *))
   1512          dlsym(handle, "_glapi_get_proc_address");
   1513       if (!dri2_drv->get_proc_address || !libname) {
   1514          /* no need to keep a reference */
   1515          dlclose(handle);
   1516          handle = NULL;
   1517       }
   1518    }
   1519 
   1520    /* if glapi is not available, loading DRI drivers will fail */
   1521    if (!dri2_drv->get_proc_address) {
   1522       _eglLog(_EGL_WARNING, "DRI2: failed to find _glapi_get_proc_address");
   1523       return EGL_FALSE;
   1524    }
   1525 
   1526    dri2_drv->glFlush = (void (*)(void))
   1527       dri2_drv->get_proc_address("glFlush");
   1528 
   1529    dri2_drv->handle = handle;
   1530 
   1531    return EGL_TRUE;
   1532 }
   1533 
   1534 /**
   1535  * This is the main entrypoint into the driver, called by libEGL.
   1536  * Create a new _EGLDriver object and init its dispatch table.
   1537  */
   1538 _EGLDriver *
   1539 _eglBuiltInDriverDRI2(const char *args)
   1540 {
   1541    struct dri2_egl_driver *dri2_drv;
   1542 
   1543    (void) args;
   1544 
   1545    dri2_drv = malloc(sizeof *dri2_drv);
   1546    if (!dri2_drv)
   1547       return NULL;
   1548 
   1549    memset(dri2_drv, 0, sizeof *dri2_drv);
   1550 
   1551    if (!dri2_load(&dri2_drv->base)) {
   1552       free(dri2_drv);
   1553       return NULL;
   1554    }
   1555 
   1556    _eglInitDriverFallbacks(&dri2_drv->base);
   1557    dri2_drv->base.API.Initialize = dri2_initialize;
   1558    dri2_drv->base.API.Terminate = dri2_terminate;
   1559    dri2_drv->base.API.CreateContext = dri2_create_context;
   1560    dri2_drv->base.API.DestroyContext = dri2_destroy_context;
   1561    dri2_drv->base.API.MakeCurrent = dri2_make_current;
   1562    dri2_drv->base.API.GetProcAddress = dri2_get_proc_address;
   1563    dri2_drv->base.API.WaitClient = dri2_wait_client;
   1564    dri2_drv->base.API.WaitNative = dri2_wait_native;
   1565    dri2_drv->base.API.BindTexImage = dri2_bind_tex_image;
   1566    dri2_drv->base.API.ReleaseTexImage = dri2_release_tex_image;
   1567    dri2_drv->base.API.CreateImageKHR = dri2_create_image_khr;
   1568    dri2_drv->base.API.DestroyImageKHR = dri2_destroy_image_khr;
   1569    dri2_drv->base.API.CreateDRMImageMESA = dri2_create_drm_image_mesa;
   1570    dri2_drv->base.API.ExportDRMImageMESA = dri2_export_drm_image_mesa;
   1571 #ifdef HAVE_WAYLAND_PLATFORM
   1572    dri2_drv->base.API.BindWaylandDisplayWL = dri2_bind_wayland_display_wl;
   1573    dri2_drv->base.API.UnbindWaylandDisplayWL = dri2_unbind_wayland_display_wl;
   1574    dri2_drv->base.API.QueryWaylandBufferWL = dri2_query_wayland_buffer_wl;
   1575 #endif
   1576 
   1577    dri2_drv->base.Name = "DRI2";
   1578    dri2_drv->base.Unload = dri2_unload;
   1579 
   1580    return &dri2_drv->base;
   1581 }
   1582