Subversion Repositories Kolibri OS

Rev

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

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