Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

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