Subversion Repositories Kolibri OS

Rev

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.  
  720.    switch (disp->Platform) {
  721. #ifdef HAVE_X11_PLATFORM
  722.    case _EGL_PLATFORM_X11:
  723.       if (dri2_dpy->own_device) {
  724.          xcb_disconnect(dri2_dpy->conn);
  725.       }
  726.       break;
  727. #endif
  728. #ifdef HAVE_DRM_PLATFORM
  729.    case _EGL_PLATFORM_DRM:
  730.       if (dri2_dpy->own_device) {
  731.          gbm_device_destroy(&dri2_dpy->gbm_dri->base.base);
  732.       }
  733.       break;
  734. #endif
  735. #ifdef HAVE_WAYLAND_PLATFORM
  736.    case _EGL_PLATFORM_WAYLAND:
  737.       if (dri2_dpy->wl_drm)
  738.           wl_drm_destroy(dri2_dpy->wl_drm);
  739.       if (dri2_dpy->wl_shm)
  740.           wl_shm_destroy(dri2_dpy->wl_shm);
  741.       wl_registry_destroy(dri2_dpy->wl_registry);
  742.       wl_event_queue_destroy(dri2_dpy->wl_queue);
  743.       if (dri2_dpy->own_device) {
  744.          wl_display_disconnect(dri2_dpy->wl_dpy);
  745.       }
  746.       break;
  747. #endif
  748.    default:
  749.       break;
  750.    }
  751.  
  752.    /* The drm platform does not create the screen/driver_configs but reuses
  753.     * the ones from the gbm device. As such the gbm itself is responsible
  754.     * for the cleanup.
  755.     */
  756.    if (disp->Platform != _EGL_PLATFORM_DRM) {
  757.       for (i = 0; dri2_dpy->driver_configs[i]; i++)
  758.          free((__DRIconfig *) dri2_dpy->driver_configs[i]);
  759.       free(dri2_dpy->driver_configs);
  760.    }
  761.    free(dri2_dpy);
  762.    disp->DriverData = NULL;
  763.  
  764.    return EGL_TRUE;
  765. }
  766.  
  767. /**
  768.  * Set the error code after a call to
  769.  * dri2_egl_display::dri2::createContextAttribs.
  770.  */
  771. static void
  772. dri2_create_context_attribs_error(int dri_error)
  773. {
  774.    EGLint egl_error;
  775.  
  776.    switch (dri_error) {
  777.    case __DRI_CTX_ERROR_SUCCESS:
  778.       return;
  779.  
  780.    case __DRI_CTX_ERROR_NO_MEMORY:
  781.       egl_error = EGL_BAD_ALLOC;
  782.       break;
  783.  
  784.   /* From the EGL_KHR_create_context spec, section "Errors":
  785.    *
  786.    *   * If <config> does not support a client API context compatible
  787.    *     with the requested API major and minor version, [...] context flags,
  788.    *     and context reset notification behavior (for client API types where
  789.    *     these attributes are supported), then an EGL_BAD_MATCH error is
  790.    *     generated.
  791.    *
  792.    *   * If an OpenGL ES context is requested and the values for
  793.    *     attributes EGL_CONTEXT_MAJOR_VERSION_KHR and
  794.    *     EGL_CONTEXT_MINOR_VERSION_KHR specify an OpenGL ES version that
  795.    *     is not defined, than an EGL_BAD_MATCH error is generated.
  796.    *
  797.    *   * If an OpenGL context is requested, the requested version is
  798.    *     greater than 3.2, and the value for attribute
  799.    *     EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR has no bits set; has any
  800.    *     bits set other than EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR and
  801.    *     EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR; has more than
  802.    *     one of these bits set; or if the implementation does not support
  803.    *     the requested profile, then an EGL_BAD_MATCH error is generated.
  804.    */
  805.    case __DRI_CTX_ERROR_BAD_API:
  806.    case __DRI_CTX_ERROR_BAD_VERSION:
  807.    case __DRI_CTX_ERROR_BAD_FLAG:
  808.       egl_error = EGL_BAD_MATCH;
  809.       break;
  810.  
  811.   /* From the EGL_KHR_create_context spec, section "Errors":
  812.    *
  813.    *   * If an attribute name or attribute value in <attrib_list> is not
  814.    *     recognized (including unrecognized bits in bitmask attributes),
  815.    *     then an EGL_BAD_ATTRIBUTE error is generated."
  816.    */
  817.    case __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE:
  818.    case __DRI_CTX_ERROR_UNKNOWN_FLAG:
  819.       egl_error = EGL_BAD_ATTRIBUTE;
  820.       break;
  821.  
  822.    default:
  823.       assert(0);
  824.       egl_error = EGL_BAD_MATCH;
  825.       break;
  826.    }
  827.  
  828.    _eglError(egl_error, "dri2_create_context");
  829. }
  830.  
  831. /**
  832.  * Called via eglCreateContext(), drv->API.CreateContext().
  833.  */
  834. static _EGLContext *
  835. dri2_create_context(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf,
  836.                     _EGLContext *share_list, const EGLint *attrib_list)
  837. {
  838.    struct dri2_egl_context *dri2_ctx;
  839.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  840.    struct dri2_egl_context *dri2_ctx_shared = dri2_egl_context(share_list);
  841.    __DRIcontext *shared =
  842.       dri2_ctx_shared ? dri2_ctx_shared->dri_context : NULL;
  843.    struct dri2_egl_config *dri2_config = dri2_egl_config(conf);
  844.    const __DRIconfig *dri_config;
  845.    int api;
  846.  
  847.    (void) drv;
  848.  
  849.    dri2_ctx = malloc(sizeof *dri2_ctx);
  850.    if (!dri2_ctx) {
  851.       _eglError(EGL_BAD_ALLOC, "eglCreateContext");
  852.       return NULL;
  853.    }
  854.  
  855.    if (!_eglInitContext(&dri2_ctx->base, disp, conf, attrib_list))
  856.       goto cleanup;
  857.  
  858.    switch (dri2_ctx->base.ClientAPI) {
  859.    case EGL_OPENGL_ES_API:
  860.       switch (dri2_ctx->base.ClientMajorVersion) {
  861.       case 1:
  862.          api = __DRI_API_GLES;
  863.          break;
  864.       case 2:
  865.          api = __DRI_API_GLES2;
  866.          break;
  867.       case 3:
  868.          api = __DRI_API_GLES3;
  869.          break;
  870.       default:
  871.          _eglError(EGL_BAD_PARAMETER, "eglCreateContext");
  872.          free(dri2_ctx);
  873.          return NULL;
  874.       }
  875.       break;
  876.    case EGL_OPENGL_API:
  877.       if ((dri2_ctx->base.ClientMajorVersion >= 4
  878.            || (dri2_ctx->base.ClientMajorVersion == 3
  879.                && dri2_ctx->base.ClientMinorVersion >= 2))
  880.           && dri2_ctx->base.Profile == EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR)
  881.          api = __DRI_API_OPENGL_CORE;
  882.       else
  883.          api = __DRI_API_OPENGL;
  884.       break;
  885.    default:
  886.       _eglError(EGL_BAD_PARAMETER, "eglCreateContext");
  887.       free(dri2_ctx);
  888.       return NULL;
  889.    }
  890.  
  891.    if (conf != NULL) {
  892.       /* The config chosen here isn't necessarily
  893.        * used for surfaces later.
  894.        * A pixmap surface will use the single config.
  895.        * This opportunity depends on disabling the
  896.        * doubleBufferMode check in
  897.        * src/mesa/main/context.c:check_compatible()
  898.        */
  899.       if (dri2_config->dri_double_config)
  900.          dri_config = dri2_config->dri_double_config;
  901.       else
  902.          dri_config = dri2_config->dri_single_config;
  903.  
  904.       /* EGL_WINDOW_BIT is set only when there is a dri_double_config.  This
  905.        * makes sure the back buffer will always be used.
  906.        */
  907.       if (conf->SurfaceType & EGL_WINDOW_BIT)
  908.          dri2_ctx->base.WindowRenderBuffer = EGL_BACK_BUFFER;
  909.    }
  910.    else
  911.       dri_config = NULL;
  912.  
  913.    if (dri2_dpy->dri2) {
  914.       if (dri2_dpy->dri2->base.version >= 3) {
  915.          unsigned error;
  916.          unsigned num_attribs = 0;
  917.          uint32_t ctx_attribs[8];
  918.  
  919.          ctx_attribs[num_attribs++] = __DRI_CTX_ATTRIB_MAJOR_VERSION;
  920.          ctx_attribs[num_attribs++] = dri2_ctx->base.ClientMajorVersion;
  921.          ctx_attribs[num_attribs++] = __DRI_CTX_ATTRIB_MINOR_VERSION;
  922.          ctx_attribs[num_attribs++] = dri2_ctx->base.ClientMinorVersion;
  923.  
  924.          if (dri2_ctx->base.Flags != 0) {
  925.             /* If the implementation doesn't support the __DRI2_ROBUSTNESS
  926.              * extension, don't even try to send it the robust-access flag.
  927.              * It may explode.  Instead, generate the required EGL error here.
  928.              */
  929.             if ((dri2_ctx->base.Flags & EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR) != 0
  930.                 && !dri2_dpy->robustness) {
  931.                _eglError(EGL_BAD_MATCH, "eglCreateContext");
  932.                goto cleanup;
  933.             }
  934.  
  935.             ctx_attribs[num_attribs++] = __DRI_CTX_ATTRIB_FLAGS;
  936.             ctx_attribs[num_attribs++] = dri2_ctx->base.Flags;
  937.          }
  938.  
  939.          if (dri2_ctx->base.ResetNotificationStrategy != EGL_NO_RESET_NOTIFICATION_KHR) {
  940.             /* If the implementation doesn't support the __DRI2_ROBUSTNESS
  941.              * extension, don't even try to send it a reset strategy.  It may
  942.              * explode.  Instead, generate the required EGL error here.
  943.              */
  944.             if (!dri2_dpy->robustness) {
  945.                _eglError(EGL_BAD_CONFIG, "eglCreateContext");
  946.                goto cleanup;
  947.             }
  948.  
  949.             ctx_attribs[num_attribs++] = __DRI_CTX_ATTRIB_RESET_STRATEGY;
  950.             ctx_attribs[num_attribs++] = __DRI_CTX_RESET_LOSE_CONTEXT;
  951.          }
  952.  
  953.          assert(num_attribs <= ARRAY_SIZE(ctx_attribs));
  954.  
  955.          dri2_ctx->dri_context =
  956.             dri2_dpy->dri2->createContextAttribs(dri2_dpy->dri_screen,
  957.                                                  api,
  958.                                                  dri_config,
  959.                                                  shared,
  960.                                                  num_attribs / 2,
  961.                                                  ctx_attribs,
  962.                                                  & error,
  963.                                                  dri2_ctx);
  964.          dri2_create_context_attribs_error(error);
  965.       } else {
  966.          dri2_ctx->dri_context =
  967.             dri2_dpy->dri2->createNewContextForAPI(dri2_dpy->dri_screen,
  968.                                                    api,
  969.                                                    dri_config,
  970.                                                    shared,
  971.                                                    dri2_ctx);
  972.       }
  973.    } else {
  974.       assert(dri2_dpy->swrast);
  975.       dri2_ctx->dri_context =
  976.          dri2_dpy->swrast->createNewContextForAPI(dri2_dpy->dri_screen,
  977.                                                   api,
  978.                                                   dri_config,
  979.                                                   shared,
  980.                                                   dri2_ctx);
  981.    }
  982.  
  983.    if (!dri2_ctx->dri_context)
  984.       goto cleanup;
  985.  
  986.    return &dri2_ctx->base;
  987.  
  988.  cleanup:
  989.    free(dri2_ctx);
  990.    return NULL;
  991. }
  992.  
  993. /**
  994.  * Called via eglDestroyContext(), drv->API.DestroyContext().
  995.  */
  996. static EGLBoolean
  997. dri2_destroy_context(_EGLDriver *drv, _EGLDisplay *disp, _EGLContext *ctx)
  998. {
  999.    struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
  1000.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  1001.  
  1002.    if (_eglPutContext(ctx)) {
  1003.       dri2_dpy->core->destroyContext(dri2_ctx->dri_context);
  1004.       free(dri2_ctx);
  1005.    }
  1006.  
  1007.    return EGL_TRUE;
  1008. }
  1009.  
  1010. /**
  1011.  * Called via eglMakeCurrent(), drv->API.MakeCurrent().
  1012.  */
  1013. static EGLBoolean
  1014. dri2_make_current(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *dsurf,
  1015.                   _EGLSurface *rsurf, _EGLContext *ctx)
  1016. {
  1017.    struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv);
  1018.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  1019.    struct dri2_egl_surface *dri2_dsurf = dri2_egl_surface(dsurf);
  1020.    struct dri2_egl_surface *dri2_rsurf = dri2_egl_surface(rsurf);
  1021.    struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
  1022.    _EGLContext *old_ctx;
  1023.    _EGLSurface *old_dsurf, *old_rsurf;
  1024.    __DRIdrawable *ddraw, *rdraw;
  1025.    __DRIcontext *cctx;
  1026.  
  1027.    /* make new bindings */
  1028.    if (!_eglBindContext(ctx, dsurf, rsurf, &old_ctx, &old_dsurf, &old_rsurf))
  1029.       return EGL_FALSE;
  1030.  
  1031.    /* flush before context switch */
  1032.    if (old_ctx && dri2_drv->glFlush)
  1033.       dri2_drv->glFlush();
  1034.  
  1035.    ddraw = (dri2_dsurf) ? dri2_dsurf->dri_drawable : NULL;
  1036.    rdraw = (dri2_rsurf) ? dri2_rsurf->dri_drawable : NULL;
  1037.    cctx = (dri2_ctx) ? dri2_ctx->dri_context : NULL;
  1038.  
  1039.    if (old_ctx) {
  1040.       __DRIcontext *old_cctx = dri2_egl_context(old_ctx)->dri_context;
  1041.       dri2_dpy->core->unbindContext(old_cctx);
  1042.    }
  1043.  
  1044.    if ((cctx == NULL && ddraw == NULL && rdraw == NULL) ||
  1045.        dri2_dpy->core->bindContext(cctx, ddraw, rdraw)) {
  1046.       if (old_dsurf)
  1047.          drv->API.DestroySurface(drv, disp, old_dsurf);
  1048.       if (old_rsurf)
  1049.          drv->API.DestroySurface(drv, disp, old_rsurf);
  1050.       if (old_ctx)
  1051.          drv->API.DestroyContext(drv, disp, old_ctx);
  1052.  
  1053.       return EGL_TRUE;
  1054.    } else {
  1055.       /* undo the previous _eglBindContext */
  1056.       _eglBindContext(old_ctx, old_dsurf, old_rsurf, &ctx, &dsurf, &rsurf);
  1057.       assert(&dri2_ctx->base == ctx &&
  1058.              &dri2_dsurf->base == dsurf &&
  1059.              &dri2_rsurf->base == rsurf);
  1060.  
  1061.       _eglPutSurface(dsurf);
  1062.       _eglPutSurface(rsurf);
  1063.       _eglPutContext(ctx);
  1064.  
  1065.       _eglPutSurface(old_dsurf);
  1066.       _eglPutSurface(old_rsurf);
  1067.       _eglPutContext(old_ctx);
  1068.  
  1069.       return EGL_FALSE;
  1070.    }
  1071. }
  1072.  
  1073. /*
  1074.  * Called from eglGetProcAddress() via drv->API.GetProcAddress().
  1075.  */
  1076. static _EGLProc
  1077. dri2_get_proc_address(_EGLDriver *drv, const char *procname)
  1078. {
  1079.    struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv);
  1080.  
  1081.    return dri2_drv->get_proc_address(procname);
  1082. }
  1083.  
  1084. static _EGLSurface*
  1085. dri2_create_window_surface(_EGLDriver *drv, _EGLDisplay *dpy,
  1086.                            _EGLConfig *conf, void *native_window,
  1087.                            const EGLint *attrib_list)
  1088. {
  1089.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
  1090.    return dri2_dpy->vtbl->create_window_surface(drv, dpy, conf, native_window,
  1091.                                                 attrib_list);
  1092. }
  1093.  
  1094. static _EGLSurface*
  1095. dri2_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *dpy,
  1096.                            _EGLConfig *conf, void *native_pixmap,
  1097.                            const EGLint *attrib_list)
  1098. {
  1099.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
  1100.    return dri2_dpy->vtbl->create_pixmap_surface(drv, dpy, conf, native_pixmap,
  1101.                                                 attrib_list);
  1102. }
  1103.  
  1104. static _EGLSurface*
  1105. dri2_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *dpy,
  1106.                            _EGLConfig *conf, const EGLint *attrib_list)
  1107. {
  1108.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
  1109.    return dri2_dpy->vtbl->create_pbuffer_surface(drv, dpy, conf, attrib_list);
  1110. }
  1111.  
  1112. static EGLBoolean
  1113. dri2_destroy_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf)
  1114. {
  1115.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
  1116.    return dri2_dpy->vtbl->destroy_surface(drv, dpy, surf);
  1117. }
  1118.  
  1119. static EGLBoolean
  1120. dri2_swap_interval(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
  1121.                    EGLint interval)
  1122. {
  1123.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
  1124.    return dri2_dpy->vtbl->swap_interval(drv, dpy, surf, interval);
  1125. }
  1126.  
  1127. /**
  1128.  * Asks the client API to flush any rendering to the drawable so that we can
  1129.  * do our swapbuffers.
  1130.  */
  1131. void
  1132. dri2_flush_drawable_for_swapbuffers(_EGLDisplay *disp, _EGLSurface *draw)
  1133. {
  1134.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  1135.    struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
  1136.  
  1137.    if (dri2_dpy->flush) {
  1138.       if (dri2_dpy->flush->base.version >= 4) {
  1139.          /* We know there's a current context because:
  1140.           *
  1141.           *     "If surface is not bound to the calling thread’s current
  1142.           *      context, an EGL_BAD_SURFACE error is generated."
  1143.          */
  1144.          _EGLContext *ctx = _eglGetCurrentContext();
  1145.          struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
  1146.  
  1147.          /* From the EGL 1.4 spec (page 52):
  1148.           *
  1149.           *     "The contents of ancillary buffers are always undefined
  1150.           *      after calling eglSwapBuffers."
  1151.           */
  1152.          dri2_dpy->flush->flush_with_flags(dri2_ctx->dri_context,
  1153.                                            dri2_surf->dri_drawable,
  1154.                                            __DRI2_FLUSH_DRAWABLE |
  1155.                                            __DRI2_FLUSH_INVALIDATE_ANCILLARY,
  1156.                                            __DRI2_THROTTLE_SWAPBUFFER);
  1157.       } else {
  1158.          dri2_dpy->flush->flush(dri2_surf->dri_drawable);
  1159.       }
  1160.    }
  1161. }
  1162.  
  1163. static EGLBoolean
  1164. dri2_swap_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf)
  1165. {
  1166.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
  1167.    return dri2_dpy->vtbl->swap_buffers(drv, dpy, surf);
  1168. }
  1169.  
  1170. static EGLBoolean
  1171. dri2_swap_buffers_with_damage(_EGLDriver *drv, _EGLDisplay *dpy,
  1172.                               _EGLSurface *surf,
  1173.                               const EGLint *rects, EGLint n_rects)
  1174. {
  1175.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
  1176.    return dri2_dpy->vtbl->swap_buffers_with_damage(drv, dpy, surf,
  1177.                                                    rects, n_rects);
  1178. }
  1179.  
  1180. static EGLBoolean
  1181. dri2_swap_buffers_region(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
  1182.                          EGLint numRects, const EGLint *rects)
  1183. {
  1184.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
  1185.    return dri2_dpy->vtbl->swap_buffers_region(drv, dpy, surf, numRects, rects);
  1186. }
  1187.  
  1188. static EGLBoolean
  1189. dri2_post_sub_buffer(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
  1190.                      EGLint x, EGLint y, EGLint width, EGLint height)
  1191. {
  1192.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
  1193.    return dri2_dpy->vtbl->post_sub_buffer(drv, dpy, surf, x, y, width, height);
  1194. }
  1195.  
  1196. static EGLBoolean
  1197. dri2_copy_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
  1198.                   void *native_pixmap_target)
  1199. {
  1200.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
  1201.    return dri2_dpy->vtbl->copy_buffers(drv, dpy, surf, native_pixmap_target);
  1202. }
  1203.  
  1204. static EGLint
  1205. dri2_query_buffer_age(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf)
  1206. {
  1207.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
  1208.    return dri2_dpy->vtbl->query_buffer_age(drv, dpy, surf);
  1209. }
  1210.  
  1211. static EGLBoolean
  1212. dri2_wait_client(_EGLDriver *drv, _EGLDisplay *disp, _EGLContext *ctx)
  1213. {
  1214.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  1215.    struct dri2_egl_surface *dri2_surf = dri2_egl_surface(ctx->DrawSurface);
  1216.  
  1217.    (void) drv;
  1218.  
  1219.    /* FIXME: If EGL allows frontbuffer rendering for window surfaces,
  1220.     * we need to copy fake to real here.*/
  1221.  
  1222.    if (dri2_dpy->flush != NULL)
  1223.       dri2_dpy->flush->flush(dri2_surf->dri_drawable);
  1224.  
  1225.    return EGL_TRUE;
  1226. }
  1227.  
  1228. static EGLBoolean
  1229. dri2_wait_native(_EGLDriver *drv, _EGLDisplay *disp, EGLint engine)
  1230. {
  1231.    (void) drv;
  1232.    (void) disp;
  1233.  
  1234.    if (engine != EGL_CORE_NATIVE_ENGINE)
  1235.       return _eglError(EGL_BAD_PARAMETER, "eglWaitNative");
  1236.    /* glXWaitX(); */
  1237.  
  1238.    return EGL_TRUE;
  1239. }
  1240.  
  1241. static EGLBoolean
  1242. dri2_bind_tex_image(_EGLDriver *drv,
  1243.                     _EGLDisplay *disp, _EGLSurface *surf, EGLint buffer)
  1244. {
  1245.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  1246.    struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
  1247.    struct dri2_egl_context *dri2_ctx;
  1248.    _EGLContext *ctx;
  1249.    GLint format, target;
  1250.  
  1251.    ctx = _eglGetCurrentContext();
  1252.    dri2_ctx = dri2_egl_context(ctx);
  1253.  
  1254.    if (!_eglBindTexImage(drv, disp, surf, buffer))
  1255.       return EGL_FALSE;
  1256.  
  1257.    switch (dri2_surf->base.TextureFormat) {
  1258.    case EGL_TEXTURE_RGB:
  1259.       format = __DRI_TEXTURE_FORMAT_RGB;
  1260.       break;
  1261.    case EGL_TEXTURE_RGBA:
  1262.       format = __DRI_TEXTURE_FORMAT_RGBA;
  1263.       break;
  1264.    default:
  1265.       assert(0);
  1266.    }
  1267.  
  1268.    switch (dri2_surf->base.TextureTarget) {
  1269.    case EGL_TEXTURE_2D:
  1270.       target = GL_TEXTURE_2D;
  1271.       break;
  1272.    default:
  1273.       assert(0);
  1274.    }
  1275.  
  1276.    (*dri2_dpy->tex_buffer->setTexBuffer2)(dri2_ctx->dri_context,
  1277.                                           target, format,
  1278.                                           dri2_surf->dri_drawable);
  1279.  
  1280.    return EGL_TRUE;
  1281. }
  1282.  
  1283. static EGLBoolean
  1284. dri2_release_tex_image(_EGLDriver *drv,
  1285.                        _EGLDisplay *disp, _EGLSurface *surf, EGLint buffer)
  1286. {
  1287.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  1288.    struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
  1289.    struct dri2_egl_context *dri2_ctx;
  1290.    _EGLContext *ctx;
  1291.    GLint  target;
  1292.  
  1293.    ctx = _eglGetCurrentContext();
  1294.    dri2_ctx = dri2_egl_context(ctx);
  1295.  
  1296.    if (!_eglReleaseTexImage(drv, disp, surf, buffer))
  1297.       return EGL_FALSE;
  1298.  
  1299.    switch (dri2_surf->base.TextureTarget) {
  1300.    case EGL_TEXTURE_2D:
  1301.       target = GL_TEXTURE_2D;
  1302.       break;
  1303.    default:
  1304.       assert(0);
  1305.    }
  1306.  
  1307.    if (dri2_dpy->tex_buffer->base.version >= 3 &&
  1308.        dri2_dpy->tex_buffer->releaseTexBuffer != NULL) {
  1309.       (*dri2_dpy->tex_buffer->releaseTexBuffer)(dri2_ctx->dri_context,
  1310.                                                 target,
  1311.                                                 dri2_surf->dri_drawable);
  1312.    }
  1313.  
  1314.    return EGL_TRUE;
  1315. }
  1316.  
  1317. static _EGLImage*
  1318. dri2_create_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx,
  1319.                   EGLenum target, EGLClientBuffer buffer,
  1320.                   const EGLint *attr_list)
  1321. {
  1322.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
  1323.    return dri2_dpy->vtbl->create_image(drv, dpy, ctx, target, buffer,
  1324.                                        attr_list);
  1325. }
  1326.  
  1327. static _EGLImage *
  1328. dri2_create_image_from_dri(_EGLDisplay *disp, __DRIimage *dri_image)
  1329. {
  1330.    struct dri2_egl_image *dri2_img;
  1331.  
  1332.    if (dri_image == NULL) {
  1333.       _eglError(EGL_BAD_ALLOC, "dri2_create_image");
  1334.       return NULL;
  1335.    }
  1336.  
  1337.    dri2_img = malloc(sizeof *dri2_img);
  1338.    if (!dri2_img) {
  1339.       _eglError(EGL_BAD_ALLOC, "dri2_create_image");
  1340.       return NULL;
  1341.    }
  1342.  
  1343.    if (!_eglInitImage(&dri2_img->base, disp)) {
  1344.       free(dri2_img);
  1345.       return NULL;
  1346.    }
  1347.  
  1348.    dri2_img->dri_image = dri_image;
  1349.  
  1350.    return &dri2_img->base;
  1351. }
  1352.  
  1353. static _EGLImage *
  1354. dri2_create_image_khr_renderbuffer(_EGLDisplay *disp, _EGLContext *ctx,
  1355.                                    EGLClientBuffer buffer,
  1356.                                    const EGLint *attr_list)
  1357. {
  1358.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  1359.    struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
  1360.    GLuint renderbuffer = (GLuint) (uintptr_t) buffer;
  1361.    __DRIimage *dri_image;
  1362.  
  1363.    if (renderbuffer == 0) {
  1364.       _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
  1365.       return EGL_NO_IMAGE_KHR;
  1366.    }
  1367.  
  1368.    dri_image =
  1369.       dri2_dpy->image->createImageFromRenderbuffer(dri2_ctx->dri_context,
  1370.                                                    renderbuffer, NULL);
  1371.  
  1372.    return dri2_create_image_from_dri(disp, dri_image);
  1373. }
  1374.  
  1375. #ifdef HAVE_LIBDRM
  1376. static _EGLImage *
  1377. dri2_create_image_mesa_drm_buffer(_EGLDisplay *disp, _EGLContext *ctx,
  1378.                                   EGLClientBuffer buffer, const EGLint *attr_list)
  1379. {
  1380.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  1381.    EGLint format, name, pitch, err;
  1382.    _EGLImageAttribs attrs;
  1383.    __DRIimage *dri_image;
  1384.  
  1385.    name = (EGLint) (uintptr_t) buffer;
  1386.  
  1387.    err = _eglParseImageAttribList(&attrs, disp, attr_list);
  1388.    if (err != EGL_SUCCESS)
  1389.       return NULL;
  1390.  
  1391.    if (attrs.Width <= 0 || attrs.Height <= 0 ||
  1392.        attrs.DRMBufferStrideMESA <= 0) {
  1393.       _eglError(EGL_BAD_PARAMETER,
  1394.                 "bad width, height or stride");
  1395.       return NULL;
  1396.    }
  1397.  
  1398.    switch (attrs.DRMBufferFormatMESA) {
  1399.    case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA:
  1400.       format = __DRI_IMAGE_FORMAT_ARGB8888;
  1401.       pitch = attrs.DRMBufferStrideMESA;
  1402.       break;
  1403.    default:
  1404.       _eglError(EGL_BAD_PARAMETER,
  1405.                 "dri2_create_image_khr: unsupported pixmap depth");
  1406.       return NULL;
  1407.    }
  1408.  
  1409.    dri_image =
  1410.       dri2_dpy->image->createImageFromName(dri2_dpy->dri_screen,
  1411.                                            attrs.Width,
  1412.                                            attrs.Height,
  1413.                                            format,
  1414.                                            name,
  1415.                                            pitch,
  1416.                                            NULL);
  1417.  
  1418.    return dri2_create_image_from_dri(disp, dri_image);
  1419. }
  1420. #endif
  1421.  
  1422. #ifdef HAVE_WAYLAND_PLATFORM
  1423.  
  1424. /* This structure describes how a wl_buffer maps to one or more
  1425.  * __DRIimages.  A wl_drm_buffer stores the wl_drm format code and the
  1426.  * offsets and strides of the planes in the buffer.  This table maps a
  1427.  * wl_drm format code to a description of the planes in the buffer
  1428.  * that lets us create a __DRIimage for each of the planes. */
  1429.  
  1430. static const struct wl_drm_components_descriptor {
  1431.    uint32_t dri_components;
  1432.    EGLint components;
  1433.    int nplanes;
  1434. } wl_drm_components[] = {
  1435.    { __DRI_IMAGE_COMPONENTS_RGB, EGL_TEXTURE_RGB, 1 },
  1436.    { __DRI_IMAGE_COMPONENTS_RGBA, EGL_TEXTURE_RGBA, 1 },
  1437.    { __DRI_IMAGE_COMPONENTS_Y_U_V, EGL_TEXTURE_Y_U_V_WL, 3 },
  1438.    { __DRI_IMAGE_COMPONENTS_Y_UV, EGL_TEXTURE_Y_UV_WL, 2 },
  1439.    { __DRI_IMAGE_COMPONENTS_Y_XUXV, EGL_TEXTURE_Y_XUXV_WL, 2 },
  1440. };
  1441.  
  1442. static _EGLImage *
  1443. dri2_create_image_wayland_wl_buffer(_EGLDisplay *disp, _EGLContext *ctx,
  1444.                                     EGLClientBuffer _buffer,
  1445.                                     const EGLint *attr_list)
  1446. {
  1447.    struct wl_drm_buffer *buffer;
  1448.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  1449.    const struct wl_drm_components_descriptor *f;
  1450.    __DRIimage *dri_image;
  1451.    _EGLImageAttribs attrs;
  1452.    EGLint err;
  1453.    int32_t plane;
  1454.  
  1455.    buffer = wayland_drm_buffer_get(dri2_dpy->wl_server_drm,
  1456.                                    (struct wl_resource *) _buffer);
  1457.    if (!buffer)
  1458.        return NULL;
  1459.  
  1460.    err = _eglParseImageAttribList(&attrs, disp, attr_list);
  1461.    plane = attrs.PlaneWL;
  1462.    if (err != EGL_SUCCESS) {
  1463.       _eglError(EGL_BAD_PARAMETER, "dri2_create_image_wayland_wl_buffer");
  1464.       return NULL;
  1465.    }
  1466.  
  1467.    f = buffer->driver_format;
  1468.    if (plane < 0 || plane >= f->nplanes) {
  1469.       _eglError(EGL_BAD_PARAMETER,
  1470.                 "dri2_create_image_wayland_wl_buffer (plane out of bounds)");
  1471.       return NULL;
  1472.    }
  1473.  
  1474.    dri_image = dri2_dpy->image->fromPlanar(buffer->driver_buffer, plane, NULL);
  1475.  
  1476.    if (dri_image == NULL) {
  1477.       _eglError(EGL_BAD_PARAMETER, "dri2_create_image_wayland_wl_buffer");
  1478.       return NULL;
  1479.    }
  1480.  
  1481.    return dri2_create_image_from_dri(disp, dri_image);
  1482. }
  1483. #endif
  1484.  
  1485. static EGLBoolean
  1486. dri2_get_sync_values_chromium(_EGLDisplay *dpy, _EGLSurface *surf,
  1487.                               EGLuint64KHR *ust, EGLuint64KHR *msc,
  1488.                               EGLuint64KHR *sbc)
  1489. {
  1490.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
  1491.    return dri2_dpy->vtbl->get_sync_values(dpy, surf, ust, msc, sbc);
  1492. }
  1493.  
  1494. /**
  1495.  * Set the error code after a call to
  1496.  * dri2_egl_image::dri_image::createImageFromTexture.
  1497.  */
  1498. static void
  1499. dri2_create_image_khr_texture_error(int dri_error)
  1500. {
  1501.    EGLint egl_error;
  1502.  
  1503.    switch (dri_error) {
  1504.    case __DRI_IMAGE_ERROR_SUCCESS:
  1505.       return;
  1506.  
  1507.    case __DRI_IMAGE_ERROR_BAD_ALLOC:
  1508.       egl_error = EGL_BAD_ALLOC;
  1509.       break;
  1510.  
  1511.    case __DRI_IMAGE_ERROR_BAD_MATCH:
  1512.       egl_error = EGL_BAD_MATCH;
  1513.       break;
  1514.  
  1515.    case __DRI_IMAGE_ERROR_BAD_PARAMETER:
  1516.       egl_error = EGL_BAD_PARAMETER;
  1517.       break;
  1518.  
  1519.    default:
  1520.       assert(0);
  1521.       egl_error = EGL_BAD_MATCH;
  1522.       break;
  1523.    }
  1524.  
  1525.    _eglError(egl_error, "dri2_create_image_khr_texture");
  1526. }
  1527.  
  1528. static _EGLImage *
  1529. dri2_create_image_khr_texture(_EGLDisplay *disp, _EGLContext *ctx,
  1530.                                    EGLenum target,
  1531.                                    EGLClientBuffer buffer,
  1532.                                    const EGLint *attr_list)
  1533. {
  1534.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  1535.    struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
  1536.    struct dri2_egl_image *dri2_img;
  1537.    GLuint texture = (GLuint) (uintptr_t) buffer;
  1538.    _EGLImageAttribs attrs;
  1539.    GLuint depth;
  1540.    GLenum gl_target;
  1541.    unsigned error;
  1542.  
  1543.    if (texture == 0) {
  1544.       _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
  1545.       return EGL_NO_IMAGE_KHR;
  1546.    }
  1547.  
  1548.    if (_eglParseImageAttribList(&attrs, disp, attr_list) != EGL_SUCCESS)
  1549.       return EGL_NO_IMAGE_KHR;
  1550.  
  1551.    switch (target) {
  1552.    case EGL_GL_TEXTURE_2D_KHR:
  1553.       depth = 0;
  1554.       gl_target = GL_TEXTURE_2D;
  1555.       break;
  1556.    case EGL_GL_TEXTURE_3D_KHR:
  1557.       depth = attrs.GLTextureZOffset;
  1558.       gl_target = GL_TEXTURE_3D;
  1559.       break;
  1560.    case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:
  1561.    case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:
  1562.    case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:
  1563.    case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:
  1564.    case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:
  1565.    case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:
  1566.       depth = target - EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR;
  1567.       gl_target = GL_TEXTURE_CUBE_MAP;
  1568.       break;
  1569.    default:
  1570.       _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
  1571.       return EGL_NO_IMAGE_KHR;
  1572.    }
  1573.  
  1574.    dri2_img = malloc(sizeof *dri2_img);
  1575.    if (!dri2_img) {
  1576.       _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr");
  1577.       return EGL_NO_IMAGE_KHR;
  1578.    }
  1579.  
  1580.    if (!_eglInitImage(&dri2_img->base, disp)) {
  1581.       _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr");
  1582.       free(dri2_img);
  1583.       return EGL_NO_IMAGE_KHR;
  1584.    }
  1585.  
  1586.    dri2_img->dri_image =
  1587.       dri2_dpy->image->createImageFromTexture(dri2_ctx->dri_context,
  1588.                                               gl_target,
  1589.                                               texture,
  1590.                                               depth,
  1591.                                               attrs.GLTextureLevel,
  1592.                                               &error,
  1593.                                               dri2_img);
  1594.    dri2_create_image_khr_texture_error(error);
  1595.  
  1596.    if (!dri2_img->dri_image) {
  1597.       free(dri2_img);
  1598.       return EGL_NO_IMAGE_KHR;
  1599.    }
  1600.    return &dri2_img->base;
  1601. }
  1602.  
  1603. static struct wl_buffer*
  1604. dri2_create_wayland_buffer_from_image(_EGLDriver *drv, _EGLDisplay *dpy,
  1605.                                       _EGLImage *img)
  1606. {
  1607.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
  1608.    return dri2_dpy->vtbl->create_wayland_buffer_from_image(drv, dpy, img);
  1609. }
  1610.  
  1611. #ifdef HAVE_LIBDRM
  1612. static EGLBoolean
  1613. dri2_check_dma_buf_attribs(const _EGLImageAttribs *attrs)
  1614. {
  1615.    unsigned i;
  1616.  
  1617.    /**
  1618.      * The spec says:
  1619.      *
  1620.      * "Required attributes and their values are as follows:
  1621.      *
  1622.      *  * EGL_WIDTH & EGL_HEIGHT: The logical dimensions of the buffer in pixels
  1623.      *
  1624.      *  * EGL_LINUX_DRM_FOURCC_EXT: The pixel format of the buffer, as specified
  1625.      *    by drm_fourcc.h and used as the pixel_format parameter of the
  1626.      *    drm_mode_fb_cmd2 ioctl."
  1627.      *
  1628.      * and
  1629.      *
  1630.      * "* If <target> is EGL_LINUX_DMA_BUF_EXT, and the list of attributes is
  1631.      *    incomplete, EGL_BAD_PARAMETER is generated."
  1632.      */
  1633.    if (attrs->Width <= 0 || attrs->Height <= 0 ||
  1634.        !attrs->DMABufFourCC.IsPresent) {
  1635.       _eglError(EGL_BAD_PARAMETER, "attribute(s) missing");
  1636.       return EGL_FALSE;
  1637.    }
  1638.  
  1639.    /**
  1640.     * Also:
  1641.     *
  1642.     * "If <target> is EGL_LINUX_DMA_BUF_EXT and one or more of the values
  1643.     *  specified for a plane's pitch or offset isn't supported by EGL,
  1644.     *  EGL_BAD_ACCESS is generated."
  1645.     */
  1646.    for (i = 0; i < ARRAY_SIZE(attrs->DMABufPlanePitches); ++i) {
  1647.       if (attrs->DMABufPlanePitches[i].IsPresent &&
  1648.           attrs->DMABufPlanePitches[i].Value <= 0) {
  1649.          _eglError(EGL_BAD_ACCESS, "invalid pitch");
  1650.          return EGL_FALSE;
  1651.       }
  1652.    }
  1653.  
  1654.    return EGL_TRUE;
  1655. }
  1656.  
  1657. /* Returns the total number of file descriptors. Zero indicates an error. */
  1658. static unsigned
  1659. dri2_check_dma_buf_format(const _EGLImageAttribs *attrs)
  1660. {
  1661.    unsigned i, plane_n;
  1662.  
  1663.    switch (attrs->DMABufFourCC.Value) {
  1664.    case DRM_FORMAT_RGB332:
  1665.    case DRM_FORMAT_BGR233:
  1666.    case DRM_FORMAT_XRGB4444:
  1667.    case DRM_FORMAT_XBGR4444:
  1668.    case DRM_FORMAT_RGBX4444:
  1669.    case DRM_FORMAT_BGRX4444:
  1670.    case DRM_FORMAT_ARGB4444:
  1671.    case DRM_FORMAT_ABGR4444:
  1672.    case DRM_FORMAT_RGBA4444:
  1673.    case DRM_FORMAT_BGRA4444:
  1674.    case DRM_FORMAT_XRGB1555:
  1675.    case DRM_FORMAT_XBGR1555:
  1676.    case DRM_FORMAT_RGBX5551:
  1677.    case DRM_FORMAT_BGRX5551:
  1678.    case DRM_FORMAT_ARGB1555:
  1679.    case DRM_FORMAT_ABGR1555:
  1680.    case DRM_FORMAT_RGBA5551:
  1681.    case DRM_FORMAT_BGRA5551:
  1682.    case DRM_FORMAT_RGB565:
  1683.    case DRM_FORMAT_BGR565:
  1684.    case DRM_FORMAT_RGB888:
  1685.    case DRM_FORMAT_BGR888:
  1686.    case DRM_FORMAT_XRGB8888:
  1687.    case DRM_FORMAT_XBGR8888:
  1688.    case DRM_FORMAT_RGBX8888:
  1689.    case DRM_FORMAT_BGRX8888:
  1690.    case DRM_FORMAT_ARGB8888:
  1691.    case DRM_FORMAT_ABGR8888:
  1692.    case DRM_FORMAT_RGBA8888:
  1693.    case DRM_FORMAT_BGRA8888:
  1694.    case DRM_FORMAT_XRGB2101010:
  1695.    case DRM_FORMAT_XBGR2101010:
  1696.    case DRM_FORMAT_RGBX1010102:
  1697.    case DRM_FORMAT_BGRX1010102:
  1698.    case DRM_FORMAT_ARGB2101010:
  1699.    case DRM_FORMAT_ABGR2101010:
  1700.    case DRM_FORMAT_RGBA1010102:
  1701.    case DRM_FORMAT_BGRA1010102:
  1702.    case DRM_FORMAT_YUYV:
  1703.    case DRM_FORMAT_YVYU:
  1704.    case DRM_FORMAT_UYVY:
  1705.    case DRM_FORMAT_VYUY:
  1706.       plane_n = 1;
  1707.       break;
  1708.    case DRM_FORMAT_NV12:
  1709.    case DRM_FORMAT_NV21:
  1710.    case DRM_FORMAT_NV16:
  1711.    case DRM_FORMAT_NV61:
  1712.       plane_n = 2;
  1713.       break;
  1714.    case DRM_FORMAT_YUV410:
  1715.    case DRM_FORMAT_YVU410:
  1716.    case DRM_FORMAT_YUV411:
  1717.    case DRM_FORMAT_YVU411:
  1718.    case DRM_FORMAT_YUV420:
  1719.    case DRM_FORMAT_YVU420:
  1720.    case DRM_FORMAT_YUV422:
  1721.    case DRM_FORMAT_YVU422:
  1722.    case DRM_FORMAT_YUV444:
  1723.    case DRM_FORMAT_YVU444:
  1724.       plane_n = 3;
  1725.       break;
  1726.    default:
  1727.       _eglError(EGL_BAD_ATTRIBUTE, "invalid format");
  1728.       return 0;
  1729.    }
  1730.  
  1731.    /**
  1732.      * The spec says:
  1733.      *
  1734.      * "* If <target> is EGL_LINUX_DMA_BUF_EXT, and the list of attributes is
  1735.      *    incomplete, EGL_BAD_PARAMETER is generated."
  1736.      */
  1737.    for (i = 0; i < plane_n; ++i) {
  1738.       if (!attrs->DMABufPlaneFds[i].IsPresent ||
  1739.           !attrs->DMABufPlaneOffsets[i].IsPresent ||
  1740.           !attrs->DMABufPlanePitches[i].IsPresent) {
  1741.          _eglError(EGL_BAD_PARAMETER, "plane attribute(s) missing");
  1742.          return 0;
  1743.       }
  1744.    }
  1745.  
  1746.    /**
  1747.     * The spec also says:
  1748.     *
  1749.     * "If <target> is EGL_LINUX_DMA_BUF_EXT, and the EGL_LINUX_DRM_FOURCC_EXT
  1750.     *  attribute indicates a single-plane format, EGL_BAD_ATTRIBUTE is
  1751.     *  generated if any of the EGL_DMA_BUF_PLANE1_* or EGL_DMA_BUF_PLANE2_*
  1752.     *  attributes are specified."
  1753.     */
  1754.    for (i = plane_n; i < 3; ++i) {
  1755.       if (attrs->DMABufPlaneFds[i].IsPresent ||
  1756.           attrs->DMABufPlaneOffsets[i].IsPresent ||
  1757.           attrs->DMABufPlanePitches[i].IsPresent) {
  1758.          _eglError(EGL_BAD_ATTRIBUTE, "too many plane attributes");
  1759.          return 0;
  1760.       }
  1761.    }
  1762.  
  1763.    return plane_n;
  1764. }
  1765.  
  1766. /**
  1767.  * The spec says:
  1768.  *
  1769.  * "If eglCreateImageKHR is successful for a EGL_LINUX_DMA_BUF_EXT target, the
  1770.  *  EGL will take a reference to the dma_buf(s) which it will release at any
  1771.  *  time while the EGLDisplay is initialized. It is the responsibility of the
  1772.  *  application to close the dma_buf file descriptors."
  1773.  *
  1774.  * Therefore we must never close or otherwise modify the file descriptors.
  1775.  */
  1776. static _EGLImage *
  1777. dri2_create_image_dma_buf(_EGLDisplay *disp, _EGLContext *ctx,
  1778.                           EGLClientBuffer buffer, const EGLint *attr_list)
  1779. {
  1780.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  1781.    _EGLImage *res;
  1782.    EGLint err;
  1783.    _EGLImageAttribs attrs;
  1784.    __DRIimage *dri_image;
  1785.    unsigned num_fds;
  1786.    unsigned i;
  1787.    int fds[3];
  1788.    int pitches[3];
  1789.    int offsets[3];
  1790.    unsigned error;
  1791.  
  1792.    /**
  1793.     * The spec says:
  1794.     *
  1795.     * ""* If <target> is EGL_LINUX_DMA_BUF_EXT and <buffer> is not NULL, the
  1796.     *     error EGL_BAD_PARAMETER is generated."
  1797.     */
  1798.    if (buffer != NULL) {
  1799.       _eglError(EGL_BAD_PARAMETER, "buffer not NULL");
  1800.       return NULL;
  1801.    }
  1802.  
  1803.    err = _eglParseImageAttribList(&attrs, disp, attr_list);
  1804.    if (err != EGL_SUCCESS) {
  1805.       _eglError(err, "bad attribute");
  1806.       return NULL;
  1807.    }
  1808.  
  1809.    if (!dri2_check_dma_buf_attribs(&attrs))
  1810.       return NULL;
  1811.  
  1812.    num_fds = dri2_check_dma_buf_format(&attrs);
  1813.    if (!num_fds)
  1814.       return NULL;
  1815.  
  1816.    for (i = 0; i < num_fds; ++i) {
  1817.       fds[i] = attrs.DMABufPlaneFds[i].Value;
  1818.       pitches[i] = attrs.DMABufPlanePitches[i].Value;
  1819.       offsets[i] = attrs.DMABufPlaneOffsets[i].Value;
  1820.    }
  1821.  
  1822.    dri_image =
  1823.       dri2_dpy->image->createImageFromDmaBufs(dri2_dpy->dri_screen,
  1824.          attrs.Width, attrs.Height, attrs.DMABufFourCC.Value,
  1825.          fds, num_fds, pitches, offsets,
  1826.          attrs.DMABufYuvColorSpaceHint.Value,
  1827.          attrs.DMABufSampleRangeHint.Value,
  1828.          attrs.DMABufChromaHorizontalSiting.Value,
  1829.          attrs.DMABufChromaVerticalSiting.Value,
  1830.          &error,
  1831.          NULL);
  1832.    dri2_create_image_khr_texture_error(error);
  1833.  
  1834.    if (!dri_image)
  1835.       return EGL_NO_IMAGE_KHR;
  1836.  
  1837.    res = dri2_create_image_from_dri(disp, dri_image);
  1838.  
  1839.    return res;
  1840. }
  1841. #endif
  1842.  
  1843. _EGLImage *
  1844. dri2_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
  1845.                       _EGLContext *ctx, EGLenum target,
  1846.                       EGLClientBuffer buffer, const EGLint *attr_list)
  1847. {
  1848.    (void) drv;
  1849.  
  1850.    switch (target) {
  1851.    case EGL_GL_TEXTURE_2D_KHR:
  1852.    case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:
  1853.    case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:
  1854.    case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:
  1855.    case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:
  1856.    case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:
  1857.    case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:
  1858.       return dri2_create_image_khr_texture(disp, ctx, target, buffer, attr_list);
  1859.    case EGL_GL_RENDERBUFFER_KHR:
  1860.       return dri2_create_image_khr_renderbuffer(disp, ctx, buffer, attr_list);
  1861. #ifdef HAVE_LIBDRM
  1862.    case EGL_DRM_BUFFER_MESA:
  1863.       return dri2_create_image_mesa_drm_buffer(disp, ctx, buffer, attr_list);
  1864. #endif
  1865. #ifdef HAVE_WAYLAND_PLATFORM
  1866.    case EGL_WAYLAND_BUFFER_WL:
  1867.       return dri2_create_image_wayland_wl_buffer(disp, ctx, buffer, attr_list);
  1868. #endif
  1869. #ifdef HAVE_LIBDRM
  1870.    case EGL_LINUX_DMA_BUF_EXT:
  1871.       return dri2_create_image_dma_buf(disp, ctx, buffer, attr_list);
  1872. #endif
  1873.    default:
  1874.       _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
  1875.       return EGL_NO_IMAGE_KHR;
  1876.    }
  1877. }
  1878.  
  1879. static EGLBoolean
  1880. dri2_destroy_image_khr(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *image)
  1881. {
  1882.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  1883.    struct dri2_egl_image *dri2_img = dri2_egl_image(image);
  1884.  
  1885.    (void) drv;
  1886.  
  1887.    dri2_dpy->image->destroyImage(dri2_img->dri_image);
  1888.    free(dri2_img);
  1889.  
  1890.    return EGL_TRUE;
  1891. }
  1892.  
  1893. #ifdef HAVE_LIBDRM
  1894. static _EGLImage *
  1895. dri2_create_drm_image_mesa(_EGLDriver *drv, _EGLDisplay *disp,
  1896.                            const EGLint *attr_list)
  1897. {
  1898.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  1899.    struct dri2_egl_image *dri2_img;
  1900.    _EGLImageAttribs attrs;
  1901.    unsigned int dri_use, valid_mask;
  1902.    int format;
  1903.    EGLint err = EGL_SUCCESS;
  1904.  
  1905.    (void) drv;
  1906.  
  1907.    dri2_img = malloc(sizeof *dri2_img);
  1908.    if (!dri2_img) {
  1909.       _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr");
  1910.       return EGL_NO_IMAGE_KHR;
  1911.    }
  1912.  
  1913.    if (!attr_list) {
  1914.       err = EGL_BAD_PARAMETER;
  1915.       goto cleanup_img;
  1916.    }
  1917.  
  1918.    if (!_eglInitImage(&dri2_img->base, disp)) {
  1919.       err = EGL_BAD_PARAMETER;
  1920.       goto cleanup_img;
  1921.    }
  1922.  
  1923.    err = _eglParseImageAttribList(&attrs, disp, attr_list);
  1924.    if (err != EGL_SUCCESS)
  1925.       goto cleanup_img;
  1926.  
  1927.    if (attrs.Width <= 0 || attrs.Height <= 0) {
  1928.       _eglLog(_EGL_WARNING, "bad width or height (%dx%d)",
  1929.             attrs.Width, attrs.Height);
  1930.       goto cleanup_img;
  1931.    }
  1932.  
  1933.    switch (attrs.DRMBufferFormatMESA) {
  1934.    case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA:
  1935.       format = __DRI_IMAGE_FORMAT_ARGB8888;
  1936.       break;
  1937.    default:
  1938.       _eglLog(_EGL_WARNING, "bad image format value 0x%04x",
  1939.             attrs.DRMBufferFormatMESA);
  1940.       goto cleanup_img;
  1941.    }
  1942.  
  1943.    valid_mask =
  1944.       EGL_DRM_BUFFER_USE_SCANOUT_MESA |
  1945.       EGL_DRM_BUFFER_USE_SHARE_MESA |
  1946.       EGL_DRM_BUFFER_USE_CURSOR_MESA;
  1947.    if (attrs.DRMBufferUseMESA & ~valid_mask) {
  1948.       _eglLog(_EGL_WARNING, "bad image use bit 0x%04x",
  1949.             attrs.DRMBufferUseMESA & ~valid_mask);
  1950.       goto cleanup_img;
  1951.    }
  1952.  
  1953.    dri_use = 0;
  1954.    if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_SHARE_MESA)
  1955.       dri_use |= __DRI_IMAGE_USE_SHARE;
  1956.    if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_SCANOUT_MESA)
  1957.       dri_use |= __DRI_IMAGE_USE_SCANOUT;
  1958.    if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_CURSOR_MESA)
  1959.       dri_use |= __DRI_IMAGE_USE_CURSOR;
  1960.  
  1961.    dri2_img->dri_image =
  1962.       dri2_dpy->image->createImage(dri2_dpy->dri_screen,
  1963.                                    attrs.Width, attrs.Height,
  1964.                                    format, dri_use, dri2_img);
  1965.    if (dri2_img->dri_image == NULL) {
  1966.       err = EGL_BAD_ALLOC;
  1967.       goto cleanup_img;
  1968.    }
  1969.  
  1970.    return &dri2_img->base;
  1971.  
  1972.  cleanup_img:
  1973.    free(dri2_img);
  1974.    _eglError(err, "dri2_create_drm_image_mesa");
  1975.  
  1976.    return EGL_NO_IMAGE_KHR;
  1977. }
  1978.  
  1979. static EGLBoolean
  1980. dri2_export_drm_image_mesa(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *img,
  1981.                           EGLint *name, EGLint *handle, EGLint *stride)
  1982. {
  1983.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  1984.    struct dri2_egl_image *dri2_img = dri2_egl_image(img);
  1985.  
  1986.    (void) drv;
  1987.  
  1988.    if (name && !dri2_dpy->image->queryImage(dri2_img->dri_image,
  1989.                                             __DRI_IMAGE_ATTRIB_NAME, name)) {
  1990.       _eglError(EGL_BAD_ALLOC, "dri2_export_drm_image_mesa");
  1991.       return EGL_FALSE;
  1992.    }
  1993.  
  1994.    if (handle)
  1995.       dri2_dpy->image->queryImage(dri2_img->dri_image,
  1996.                                   __DRI_IMAGE_ATTRIB_HANDLE, handle);
  1997.  
  1998.    if (stride)
  1999.       dri2_dpy->image->queryImage(dri2_img->dri_image,
  2000.                                   __DRI_IMAGE_ATTRIB_STRIDE, stride);
  2001.  
  2002.    return EGL_TRUE;
  2003. }
  2004.  
  2005. static EGLBoolean
  2006. dri2_export_dma_buf_image_query_mesa(_EGLDriver *drv, _EGLDisplay *disp,
  2007.                                      _EGLImage *img,
  2008.                                      EGLint *fourcc, EGLint *nplanes,
  2009.                                      EGLuint64KHR *modifiers)
  2010. {
  2011.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  2012.    struct dri2_egl_image *dri2_img = dri2_egl_image(img);
  2013.  
  2014.    (void) drv;
  2015.  
  2016.  
  2017.    if (nplanes)
  2018.       dri2_dpy->image->queryImage(dri2_img->dri_image,
  2019.                                   __DRI_IMAGE_ATTRIB_NUM_PLANES, nplanes);
  2020.    if (fourcc)
  2021.       dri2_dpy->image->queryImage(dri2_img->dri_image,
  2022.                                   __DRI_IMAGE_ATTRIB_FOURCC, fourcc);
  2023.  
  2024.    if (modifiers)
  2025.       *modifiers = 0;
  2026.  
  2027.    return EGL_TRUE;
  2028. }
  2029.  
  2030. static EGLBoolean
  2031. dri2_export_dma_buf_image_mesa(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *img,
  2032.                                int *fds, EGLint *strides, EGLint *offsets)
  2033. {
  2034.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  2035.    struct dri2_egl_image *dri2_img = dri2_egl_image(img);
  2036.  
  2037.    (void) drv;
  2038.  
  2039.    /* rework later to provide multiple fds/strides/offsets */
  2040.    if (fds)
  2041.       dri2_dpy->image->queryImage(dri2_img->dri_image,
  2042.                                   __DRI_IMAGE_ATTRIB_FD, fds);
  2043.  
  2044.    if (strides)
  2045.       dri2_dpy->image->queryImage(dri2_img->dri_image,
  2046.                                   __DRI_IMAGE_ATTRIB_STRIDE, strides);
  2047.  
  2048.    if (offsets)
  2049.       offsets[0] = 0;
  2050.  
  2051.    return EGL_TRUE;
  2052. }
  2053. #endif
  2054.  
  2055. #ifdef HAVE_WAYLAND_PLATFORM
  2056.  
  2057. static void
  2058. dri2_wl_reference_buffer(void *user_data, uint32_t name, int fd,
  2059.                          struct wl_drm_buffer *buffer)
  2060. {
  2061.    _EGLDisplay *disp = user_data;
  2062.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  2063.    __DRIimage *img;
  2064.    int i, dri_components = 0;
  2065.  
  2066.    if (fd == -1)
  2067.       img = dri2_dpy->image->createImageFromNames(dri2_dpy->dri_screen,
  2068.                                                   buffer->width,
  2069.                                                   buffer->height,
  2070.                                                   buffer->format,
  2071.                                                   (int*)&name, 1,
  2072.                                                   buffer->stride,
  2073.                                                   buffer->offset,
  2074.                                                   NULL);
  2075.    else
  2076.       img = dri2_dpy->image->createImageFromFds(dri2_dpy->dri_screen,
  2077.                                                 buffer->width,
  2078.                                                 buffer->height,
  2079.                                                 buffer->format,
  2080.                                                 &fd, 1,
  2081.                                                 buffer->stride,
  2082.                                                 buffer->offset,
  2083.                                                 NULL);
  2084.  
  2085.    if (img == NULL)
  2086.       return;
  2087.  
  2088.    dri2_dpy->image->queryImage(img, __DRI_IMAGE_ATTRIB_COMPONENTS, &dri_components);
  2089.  
  2090.    buffer->driver_format = NULL;
  2091.    for (i = 0; i < ARRAY_SIZE(wl_drm_components); i++)
  2092.       if (wl_drm_components[i].dri_components == dri_components)
  2093.          buffer->driver_format = &wl_drm_components[i];
  2094.  
  2095.    if (buffer->driver_format == NULL)
  2096.       dri2_dpy->image->destroyImage(img);
  2097.    else
  2098.       buffer->driver_buffer = img;
  2099. }
  2100.  
  2101. static void
  2102. dri2_wl_release_buffer(void *user_data, struct wl_drm_buffer *buffer)
  2103. {
  2104.    _EGLDisplay *disp = user_data;
  2105.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  2106.  
  2107.    dri2_dpy->image->destroyImage(buffer->driver_buffer);
  2108. }
  2109.  
  2110. static struct wayland_drm_callbacks wl_drm_callbacks = {
  2111.         .authenticate = NULL,
  2112.         .reference_buffer = dri2_wl_reference_buffer,
  2113.         .release_buffer = dri2_wl_release_buffer
  2114. };
  2115.  
  2116. static EGLBoolean
  2117. dri2_bind_wayland_display_wl(_EGLDriver *drv, _EGLDisplay *disp,
  2118.                              struct wl_display *wl_dpy)
  2119. {
  2120.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  2121.    int flags = 0;
  2122.    uint64_t cap;
  2123.  
  2124.    (void) drv;
  2125.  
  2126.    if (dri2_dpy->wl_server_drm)
  2127.            return EGL_FALSE;
  2128.  
  2129.    wl_drm_callbacks.authenticate =
  2130.       (int(*)(void *, uint32_t)) dri2_dpy->vtbl->authenticate;
  2131.  
  2132. #ifdef HAVE_LIBDRM
  2133.    if (drmGetCap(dri2_dpy->fd, DRM_CAP_PRIME, &cap) == 0 &&
  2134.        cap == (DRM_PRIME_CAP_IMPORT | DRM_PRIME_CAP_EXPORT) &&
  2135.        dri2_dpy->image->base.version >= 7 &&
  2136.        dri2_dpy->image->createImageFromFds != NULL)
  2137.       flags |= WAYLAND_DRM_PRIME;
  2138. #endif
  2139.  
  2140.    dri2_dpy->wl_server_drm =
  2141.            wayland_drm_init(wl_dpy, dri2_dpy->device_name,
  2142.                             &wl_drm_callbacks, disp, flags);
  2143.  
  2144.    if (!dri2_dpy->wl_server_drm)
  2145.            return EGL_FALSE;
  2146.  
  2147. #ifdef HAVE_DRM_PLATFORM
  2148.    /* We have to share the wl_drm instance with gbm, so gbm can convert
  2149.     * wl_buffers to gbm bos. */
  2150.    if (dri2_dpy->gbm_dri)
  2151.       dri2_dpy->gbm_dri->wl_drm = dri2_dpy->wl_server_drm;
  2152. #endif
  2153.  
  2154.    return EGL_TRUE;
  2155. }
  2156.  
  2157. static EGLBoolean
  2158. dri2_unbind_wayland_display_wl(_EGLDriver *drv, _EGLDisplay *disp,
  2159.                                struct wl_display *wl_dpy)
  2160. {
  2161.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  2162.  
  2163.    (void) drv;
  2164.  
  2165.    if (!dri2_dpy->wl_server_drm)
  2166.            return EGL_FALSE;
  2167.  
  2168.    wayland_drm_uninit(dri2_dpy->wl_server_drm);
  2169.    dri2_dpy->wl_server_drm = NULL;
  2170.  
  2171.    return EGL_TRUE;
  2172. }
  2173.  
  2174. static EGLBoolean
  2175. dri2_query_wayland_buffer_wl(_EGLDriver *drv, _EGLDisplay *disp,
  2176.                              struct wl_resource *buffer_resource,
  2177.                              EGLint attribute, EGLint *value)
  2178. {
  2179.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  2180.    struct wl_drm_buffer *buffer;
  2181.    const struct wl_drm_components_descriptor *format;
  2182.  
  2183.    buffer = wayland_drm_buffer_get(dri2_dpy->wl_server_drm, buffer_resource);
  2184.    if (!buffer)
  2185.       return EGL_FALSE;
  2186.  
  2187.    format = buffer->driver_format;
  2188.    switch (attribute) {
  2189.    case EGL_TEXTURE_FORMAT:
  2190.       *value = format->components;
  2191.       return EGL_TRUE;
  2192.    case EGL_WIDTH:
  2193.       *value = buffer->width;
  2194.       return EGL_TRUE;
  2195.    case EGL_HEIGHT:
  2196.       *value = buffer->height;
  2197.       return EGL_TRUE;
  2198.    }
  2199.  
  2200.    return EGL_FALSE;
  2201. }
  2202. #endif
  2203.  
  2204. static void
  2205. dri2_egl_ref_sync(struct dri2_egl_sync *sync)
  2206. {
  2207.    p_atomic_inc(&sync->refcount);
  2208. }
  2209.  
  2210. static void
  2211. dri2_egl_unref_sync(struct dri2_egl_display *dri2_dpy,
  2212.                     struct dri2_egl_sync *dri2_sync)
  2213. {
  2214.    if (p_atomic_dec_zero(&dri2_sync->refcount)) {
  2215.       dri2_dpy->fence->destroy_fence(dri2_dpy->dri_screen, dri2_sync->fence);
  2216.       free(dri2_sync);
  2217.    }
  2218. }
  2219.  
  2220. static _EGLSync *
  2221. dri2_create_sync(_EGLDriver *drv, _EGLDisplay *dpy,
  2222.                  EGLenum type, const EGLint *attrib_list,
  2223.                  const EGLAttribKHR *attrib_list64)
  2224. {
  2225.    _EGLContext *ctx = _eglGetCurrentContext();
  2226.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
  2227.    struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
  2228.    struct dri2_egl_sync *dri2_sync;
  2229.  
  2230.    dri2_sync = calloc(1, sizeof(struct dri2_egl_sync));
  2231.    if (!dri2_sync) {
  2232.       _eglError(EGL_BAD_ALLOC, "eglCreateSyncKHR");
  2233.       return NULL;
  2234.    }
  2235.  
  2236.    if (!_eglInitSync(&dri2_sync->base, dpy, type, attrib_list,
  2237.                      attrib_list64)) {
  2238.       free(dri2_sync);
  2239.       return NULL;
  2240.    }
  2241.  
  2242.    switch (type) {
  2243.    case EGL_SYNC_FENCE_KHR:
  2244.       dri2_sync->fence = dri2_dpy->fence->create_fence(dri2_ctx->dri_context);
  2245.       if (!dri2_sync->fence) {
  2246.          /* Why did it fail? DRI doesn't return an error code, so we emit
  2247.           * a generic EGL error that doesn't communicate user error.
  2248.           */
  2249.          _eglError(EGL_BAD_ALLOC, "eglCreateSyncKHR");
  2250.          free(dri2_sync);
  2251.          return NULL;
  2252.       }
  2253.       break;
  2254.  
  2255.    case EGL_SYNC_CL_EVENT_KHR:
  2256.       dri2_sync->fence = dri2_dpy->fence->get_fence_from_cl_event(
  2257.                                  dri2_dpy->dri_screen,
  2258.                                  dri2_sync->base.CLEvent);
  2259.       /* this can only happen if the cl_event passed in is invalid. */
  2260.       if (!dri2_sync->fence) {
  2261.          _eglError(EGL_BAD_ATTRIBUTE, "eglCreateSyncKHR");
  2262.          free(dri2_sync);
  2263.          return NULL;
  2264.       }
  2265.  
  2266.       /* the initial status must be "signaled" if the cl_event is signaled */
  2267.       if (dri2_dpy->fence->client_wait_sync(dri2_ctx->dri_context,
  2268.                                             dri2_sync->fence, 0, 0))
  2269.          dri2_sync->base.SyncStatus = EGL_SIGNALED_KHR;
  2270.       break;
  2271.    }
  2272.  
  2273.    p_atomic_set(&dri2_sync->refcount, 1);
  2274.    return &dri2_sync->base;
  2275. }
  2276.  
  2277. static EGLBoolean
  2278. dri2_destroy_sync(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync)
  2279. {
  2280.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
  2281.    struct dri2_egl_sync *dri2_sync = dri2_egl_sync(sync);
  2282.  
  2283.    dri2_egl_unref_sync(dri2_dpy, dri2_sync);
  2284.    return EGL_TRUE;
  2285. }
  2286.  
  2287. static EGLint
  2288. dri2_client_wait_sync(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync,
  2289.                       EGLint flags, EGLTimeKHR timeout)
  2290. {
  2291.    _EGLContext *ctx = _eglGetCurrentContext();
  2292.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
  2293.    struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
  2294.    struct dri2_egl_sync *dri2_sync = dri2_egl_sync(sync);
  2295.    unsigned wait_flags = 0;
  2296.    EGLint ret = EGL_CONDITION_SATISFIED_KHR;
  2297.  
  2298.    if (flags & EGL_SYNC_FLUSH_COMMANDS_BIT_KHR)
  2299.       wait_flags |= __DRI2_FENCE_FLAG_FLUSH_COMMANDS;
  2300.  
  2301.    /* the sync object should take a reference while waiting */
  2302.    dri2_egl_ref_sync(dri2_sync);
  2303.  
  2304.    if (dri2_dpy->fence->client_wait_sync(dri2_ctx->dri_context,
  2305.                                          dri2_sync->fence, wait_flags,
  2306.                                          timeout))
  2307.       dri2_sync->base.SyncStatus = EGL_SIGNALED_KHR;
  2308.    else
  2309.       ret = EGL_TIMEOUT_EXPIRED_KHR;
  2310.  
  2311.    dri2_egl_unref_sync(dri2_dpy, dri2_sync);
  2312.    return ret;
  2313. }
  2314.  
  2315. static EGLint
  2316. dri2_server_wait_sync(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync)
  2317. {
  2318.    _EGLContext *ctx = _eglGetCurrentContext();
  2319.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
  2320.    struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
  2321.    struct dri2_egl_sync *dri2_sync = dri2_egl_sync(sync);
  2322.  
  2323.    dri2_dpy->fence->server_wait_sync(dri2_ctx->dri_context,
  2324.                                      dri2_sync->fence, 0);
  2325.    return EGL_TRUE;
  2326. }
  2327.  
  2328. static void
  2329. dri2_unload(_EGLDriver *drv)
  2330. {
  2331.    struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv);
  2332.  
  2333. //   if (dri2_drv->handle)
  2334. //      dlclose(dri2_drv->handle);
  2335.    free(dri2_drv);
  2336. }
  2337.  
  2338. static EGLBoolean
  2339. dri2_load(_EGLDriver *drv)
  2340. {
  2341.    struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv);
  2342.    const char *libname = "libGL.dll";
  2343.  
  2344.    lib_handle handle;
  2345.  
  2346.    handle = load_library(libname);
  2347.    if (handle) {
  2348.       dri2_drv->get_proc_address = (_EGLProc (*)(const char *))
  2349.          get_proc_address(handle, "_glapi_get_proc_address");
  2350.       if (!dri2_drv->get_proc_address) {
  2351.          /* no need to keep a reference */
  2352.          handle = 0;
  2353.       }
  2354.    }
  2355.  
  2356.    /* if glapi is not available, loading DRI drivers will fail */
  2357.    if (!dri2_drv->get_proc_address) {
  2358.       _eglLog(_EGL_WARNING, "DRI2: failed to find _glapi_get_proc_address");
  2359.       return EGL_FALSE;
  2360.    }
  2361.  
  2362.    dri2_drv->glFlush = (void (*)(void))
  2363.       dri2_drv->get_proc_address("glFlush");
  2364.  
  2365.    dri2_drv->handle = handle;
  2366.  
  2367.    return EGL_TRUE;
  2368. }
  2369.  
  2370. /**
  2371.  * This is the main entrypoint into the driver, called by libEGL.
  2372.  * Create a new _EGLDriver object and init its dispatch table.
  2373.  */
  2374. _EGLDriver *
  2375. _eglBuiltInDriverDRI2(const char *args)
  2376. {
  2377.    struct dri2_egl_driver *dri2_drv;
  2378.  
  2379.    (void) args;
  2380.  
  2381.    dri2_drv = calloc(1, sizeof *dri2_drv);
  2382.    if (!dri2_drv)
  2383.       return NULL;
  2384.  
  2385.    if (!dri2_load(&dri2_drv->base)) {
  2386.       free(dri2_drv);
  2387.       return NULL;
  2388.    }
  2389.  
  2390.    _eglInitDriverFallbacks(&dri2_drv->base);
  2391.    dri2_drv->base.API.Initialize = dri2_initialize;
  2392.    dri2_drv->base.API.Terminate = dri2_terminate;
  2393.    dri2_drv->base.API.CreateContext = dri2_create_context;
  2394.    dri2_drv->base.API.DestroyContext = dri2_destroy_context;
  2395.    dri2_drv->base.API.MakeCurrent = dri2_make_current;
  2396.    dri2_drv->base.API.CreateWindowSurface = dri2_create_window_surface;
  2397.    dri2_drv->base.API.CreatePixmapSurface = dri2_create_pixmap_surface;
  2398.    dri2_drv->base.API.CreatePbufferSurface = dri2_create_pbuffer_surface;
  2399.    dri2_drv->base.API.DestroySurface = dri2_destroy_surface;
  2400.    dri2_drv->base.API.GetProcAddress = dri2_get_proc_address;
  2401.    dri2_drv->base.API.WaitClient = dri2_wait_client;
  2402.    dri2_drv->base.API.WaitNative = dri2_wait_native;
  2403.    dri2_drv->base.API.BindTexImage = dri2_bind_tex_image;
  2404.    dri2_drv->base.API.ReleaseTexImage = dri2_release_tex_image;
  2405.    dri2_drv->base.API.SwapInterval = dri2_swap_interval;
  2406.    dri2_drv->base.API.SwapBuffers = dri2_swap_buffers;
  2407.    dri2_drv->base.API.SwapBuffersWithDamageEXT = dri2_swap_buffers_with_damage;
  2408.    dri2_drv->base.API.SwapBuffersRegionNOK = dri2_swap_buffers_region;
  2409.    dri2_drv->base.API.PostSubBufferNV = dri2_post_sub_buffer;
  2410.    dri2_drv->base.API.CopyBuffers = dri2_copy_buffers,
  2411.    dri2_drv->base.API.QueryBufferAge = dri2_query_buffer_age;
  2412.    dri2_drv->base.API.CreateImageKHR = dri2_create_image;
  2413.    dri2_drv->base.API.DestroyImageKHR = dri2_destroy_image_khr;
  2414.    dri2_drv->base.API.CreateWaylandBufferFromImageWL = dri2_create_wayland_buffer_from_image;
  2415. #ifdef HAVE_LIBDRM
  2416.    dri2_drv->base.API.CreateDRMImageMESA = dri2_create_drm_image_mesa;
  2417.    dri2_drv->base.API.ExportDRMImageMESA = dri2_export_drm_image_mesa;
  2418.    dri2_drv->base.API.ExportDMABUFImageQueryMESA = dri2_export_dma_buf_image_query_mesa;
  2419.    dri2_drv->base.API.ExportDMABUFImageMESA = dri2_export_dma_buf_image_mesa;
  2420. #endif
  2421. #ifdef HAVE_WAYLAND_PLATFORM
  2422.    dri2_drv->base.API.BindWaylandDisplayWL = dri2_bind_wayland_display_wl;
  2423.    dri2_drv->base.API.UnbindWaylandDisplayWL = dri2_unbind_wayland_display_wl;
  2424.    dri2_drv->base.API.QueryWaylandBufferWL = dri2_query_wayland_buffer_wl;
  2425. #endif
  2426.    dri2_drv->base.API.GetSyncValuesCHROMIUM = dri2_get_sync_values_chromium;
  2427.    dri2_drv->base.API.CreateSyncKHR = dri2_create_sync;
  2428.    dri2_drv->base.API.ClientWaitSyncKHR = dri2_client_wait_sync;
  2429.    dri2_drv->base.API.WaitSyncKHR = dri2_server_wait_sync;
  2430.    dri2_drv->base.API.DestroySyncKHR = dri2_destroy_sync;
  2431.  
  2432.    dri2_drv->base.Name = "DRI2";
  2433.    dri2_drv->base.Unload = dri2_unload;
  2434.  
  2435.    return &dri2_drv->base;
  2436. }
  2437.