Subversion Repositories Kolibri OS

Rev

Rev 6114 | Blame | Compare with Previous | 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. #include <wayland-kos32.h>
  45.  
  46. #include "eglmode.h"
  47. #include "eglscreen.h"
  48.  
  49. #include "egl_dri2.h"
  50.  
  51. typedef unsigned int lib_handle;
  52.  
  53. lib_handle load_library(const char *name);
  54. void *get_proc_address(lib_handle lib, char *proc_name);
  55.  
  56. const __DRIuseInvalidateExtension use_invalidate = {
  57.    { __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.                 int depth, 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.       default:
  199.          key = dri2_to_egl_attribute_map[attrib];
  200.          if (key != 0)
  201.             _eglSetConfigKey(&base, key, value);
  202.          break;
  203.       }
  204.    }
  205.  
  206.    if (attr_list)
  207.       for (i = 0; attr_list[i] != EGL_NONE; i += 2)
  208.          _eglSetConfigKey(&base, attr_list[i], attr_list[i+1]);
  209.  
  210.    /* Allow a 24-bit RGB visual to match a 32-bit RGBA EGLConfig.  Otherwise
  211.     * it will only match a 32-bit RGBA visual.  On a composited window manager
  212.     * on X11, this will make all of the EGLConfigs with destination alpha get
  213.     * blended by the compositor.  This is probably not what the application
  214.     * wants... especially on drivers that only have 32-bit RGBA EGLConfigs!
  215.     */
  216.    if (depth > 0 && depth != base.BufferSize
  217.        && !(depth == 24 && base.BufferSize == 32))
  218.       return NULL;
  219.  
  220.    if (rgba_masks && memcmp(rgba_masks, dri_masks, sizeof(dri_masks)))
  221.       return NULL;
  222.  
  223.    base.NativeRenderable = EGL_TRUE;
  224.  
  225.    base.SurfaceType = surface_type;
  226.    if (surface_type & (EGL_PBUFFER_BIT |
  227.        (disp->Extensions.NOK_texture_from_pixmap ? EGL_PIXMAP_BIT : 0))) {
  228.       base.BindToTextureRGB = bind_to_texture_rgb;
  229.       if (base.AlphaSize > 0)
  230.          base.BindToTextureRGBA = bind_to_texture_rgba;
  231.    }
  232.  
  233.    base.RenderableType = disp->ClientAPIs;
  234.    base.Conformant = disp->ClientAPIs;
  235.  
  236.    base.MinSwapInterval = dri2_dpy->min_swap_interval;
  237.    base.MaxSwapInterval = dri2_dpy->max_swap_interval;
  238.  
  239.    if (!_eglValidateConfig(&base, EGL_FALSE)) {
  240.       _eglLog(_EGL_DEBUG, "DRI2: failed to validate config %d", id);
  241.       return NULL;
  242.    }
  243.  
  244.    config_id = base.ConfigID;
  245.    base.ConfigID    = EGL_DONT_CARE;
  246.    base.SurfaceType = EGL_DONT_CARE;
  247.    num_configs = _eglFilterArray(disp->Configs, (void **) &matching_config, 1,
  248.                                  (_EGLArrayForEach) dri2_match_config, &base);
  249.  
  250.    if (num_configs == 1) {
  251.       conf = (struct dri2_egl_config *) matching_config;
  252.  
  253.       if (double_buffer && !conf->dri_double_config)
  254.          conf->dri_double_config = dri_config;
  255.       else if (!double_buffer && !conf->dri_single_config)
  256.          conf->dri_single_config = dri_config;
  257.       else
  258.          /* a similar config type is already added (unlikely) => discard */
  259.          return NULL;
  260.    }
  261.    else if (num_configs == 0) {
  262.       conf = malloc(sizeof *conf);
  263.       if (conf == NULL)
  264.          return NULL;
  265.  
  266.       memcpy(&conf->base, &base, sizeof base);
  267.       if (double_buffer) {
  268.          conf->dri_double_config = dri_config;
  269.          conf->dri_single_config = NULL;
  270.       } else {
  271.          conf->dri_single_config = dri_config;
  272.          conf->dri_double_config = NULL;
  273.       }
  274.       conf->base.SurfaceType = 0;
  275.       conf->base.ConfigID = config_id;
  276.  
  277.       _eglLinkConfig(&conf->base);
  278.    }
  279.    else {
  280.       assert(0);
  281.       return NULL;
  282.    }
  283.  
  284.    if (double_buffer) {
  285.       surface_type &= ~EGL_PIXMAP_BIT;
  286.    }
  287.  
  288.    conf->base.SurfaceType |= surface_type;
  289.  
  290.    return conf;
  291. }
  292.  
  293. __DRIimage *
  294. dri2_lookup_egl_image(__DRIscreen *screen, void *image, void *data)
  295. {
  296.    _EGLDisplay *disp = data;
  297.    struct dri2_egl_image *dri2_img;
  298.    _EGLImage *img;
  299.  
  300.    (void) screen;
  301.  
  302.    img = _eglLookupImage(image, disp);
  303.    if (img == NULL) {
  304.       _eglError(EGL_BAD_PARAMETER, "dri2_lookup_egl_image");
  305.       return NULL;
  306.    }
  307.  
  308.    dri2_img = dri2_egl_image(image);
  309.  
  310.    return dri2_img->dri_image;
  311. }
  312.  
  313. const __DRIimageLookupExtension image_lookup_extension = {
  314.    { __DRI_IMAGE_LOOKUP, 1 },
  315.    dri2_lookup_egl_image
  316. };
  317.  
  318. static const char dri_driver_path[] = "";//DEFAULT_DRIVER_DIR;
  319.  
  320. struct dri2_extension_match {
  321.    const char *name;
  322.    int version;
  323.    int offset;
  324. };
  325.  
  326. static struct dri2_extension_match dri2_driver_extensions[] = {
  327.    { __DRI_CORE, 1, offsetof(struct dri2_egl_display, core) },
  328.    { __DRI_DRI2, 2, offsetof(struct dri2_egl_display, dri2) },
  329.    { NULL, 0, 0 }
  330. };
  331.  
  332. static struct dri2_extension_match dri2_core_extensions[] = {
  333.    { __DRI2_FLUSH, 1, offsetof(struct dri2_egl_display, flush) },
  334.    { __DRI_TEX_BUFFER, 2, offsetof(struct dri2_egl_display, tex_buffer) },
  335.    { __DRI_IMAGE, 1, offsetof(struct dri2_egl_display, image) },
  336.    { NULL, 0, 0 }
  337. };
  338.  
  339. static struct dri2_extension_match swrast_driver_extensions[] = {
  340.    { __DRI_CORE, 1, offsetof(struct dri2_egl_display, core) },
  341.    { __DRI_SWRAST, 2, offsetof(struct dri2_egl_display, swrast) },
  342.    { NULL, 0, 0 }
  343. };
  344.  
  345. static struct dri2_extension_match swrast_core_extensions[] = {
  346.    { __DRI_TEX_BUFFER, 2, offsetof(struct dri2_egl_display, tex_buffer) },
  347.    { NULL, 0, 0 }
  348. };
  349.  
  350. static EGLBoolean
  351. dri2_bind_extensions(struct dri2_egl_display *dri2_dpy,
  352.                      struct dri2_extension_match *matches,
  353.                      const __DRIextension **extensions)
  354. {
  355.    int i, j, ret = EGL_TRUE;
  356.    void *field;
  357.  
  358.    for (i = 0; extensions[i]; i++) {
  359.       _eglLog(_EGL_DEBUG, "DRI2: found extension `%s'", extensions[i]->name);
  360.       for (j = 0; matches[j].name; j++) {
  361.          if (strcmp(extensions[i]->name, matches[j].name) == 0 &&
  362.              extensions[i]->version >= matches[j].version) {
  363.             field = ((char *) dri2_dpy + matches[j].offset);
  364.             *(const __DRIextension **) field = extensions[i];
  365.             _eglLog(_EGL_INFO, "DRI2: found extension %s version %d",
  366.                     extensions[i]->name, extensions[i]->version);
  367.          }
  368.       }
  369.    }
  370.  
  371.    for (j = 0; matches[j].name; j++) {
  372.       field = ((char *) dri2_dpy + matches[j].offset);
  373.       if (*(const __DRIextension **) field == NULL) {
  374.          _eglLog(_EGL_FATAL, "DRI2: did not find extension %s version %d",
  375.                  matches[j].name, matches[j].version);
  376.          ret = EGL_FALSE;
  377.       }
  378.    }
  379.  
  380.    return ret;
  381. }
  382.  
  383. #if 0
  384.  
  385. static const __DRIextension **
  386. dri2_open_driver(_EGLDisplay *disp)
  387. {
  388.    struct dri2_egl_display *dri2_dpy = disp->DriverData;
  389.    const __DRIextension **extensions;
  390.    char path[PATH_MAX], *search_paths, *p, *next, *end;
  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.    }
  422.  
  423.    if (dri2_dpy->driver == NULL) {
  424.       _eglLog(_EGL_WARNING,
  425.               "DRI2: failed to open %s (search paths %s)",
  426.               dri2_dpy->driver_name, search_paths);
  427.       return NULL;
  428.    }
  429.  
  430.    _eglLog(_EGL_DEBUG, "DRI2: dlopen(%s)", path);
  431.    extensions = dlsym(dri2_dpy->driver, __DRI_DRIVER_EXTENSIONS);
  432.    if (extensions == NULL) {
  433.       _eglLog(_EGL_WARNING,
  434.               "DRI2: driver exports no extensions (%s)", dlerror());
  435.       dlclose(dri2_dpy->driver);
  436.    }
  437.  
  438.    return extensions;
  439. }
  440.  
  441. EGLBoolean
  442. dri2_load_driver(_EGLDisplay *disp)
  443. {
  444.    struct dri2_egl_display *dri2_dpy = disp->DriverData;
  445.    const __DRIextension **extensions;
  446.  
  447.    extensions = dri2_open_driver(disp);
  448.    if (!extensions)
  449.       return EGL_FALSE;
  450.  
  451.    if (!dri2_bind_extensions(dri2_dpy, dri2_driver_extensions, extensions)) {
  452.       dlclose(dri2_dpy->driver);
  453.       return EGL_FALSE;
  454.    }
  455.  
  456.    return EGL_TRUE;
  457. }
  458.  
  459. EGLBoolean
  460. dri2_load_driver_swrast(_EGLDisplay *disp)
  461. {
  462.    struct dri2_egl_display *dri2_dpy = disp->DriverData;
  463.    const __DRIextension **extensions;
  464.  
  465.    dri2_dpy->driver_name = "swrast";
  466.    extensions = dri2_open_driver(disp);
  467.  
  468.    if (!extensions)
  469.       return EGL_FALSE;
  470.  
  471.    if (!dri2_bind_extensions(dri2_dpy, swrast_driver_extensions, extensions)) {
  472.       dlclose(dri2_dpy->driver);
  473.       return EGL_FALSE;
  474.    }
  475.  
  476.    return EGL_TRUE;
  477. }
  478. #endif
  479.  
  480. void
  481. dri2_setup_screen(_EGLDisplay *disp)
  482. {
  483.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  484.    unsigned int api_mask;
  485.  
  486.    if (dri2_dpy->dri2) {
  487.       api_mask = dri2_dpy->dri2->getAPIMask(dri2_dpy->dri_screen);
  488.    } else {
  489.       assert(dri2_dpy->swrast);
  490.       api_mask = 1 << __DRI_API_OPENGL |
  491.                  1 << __DRI_API_GLES |
  492.                  1 << __DRI_API_GLES2 |
  493.                  1 << __DRI_API_GLES3;
  494.    }
  495.  
  496.    disp->ClientAPIs = 0;
  497.    if (api_mask & (1 <<__DRI_API_OPENGL))
  498.       disp->ClientAPIs |= EGL_OPENGL_BIT;
  499.    if (api_mask & (1 <<__DRI_API_GLES))
  500.       disp->ClientAPIs |= EGL_OPENGL_ES_BIT;
  501.    if (api_mask & (1 << __DRI_API_GLES2))
  502.       disp->ClientAPIs |= EGL_OPENGL_ES2_BIT;
  503.    if (api_mask & (1 << __DRI_API_GLES3))
  504.       disp->ClientAPIs |= EGL_OPENGL_ES3_BIT_KHR;
  505.  
  506.    assert(dri2_dpy->dri2 || dri2_dpy->swrast);
  507.    disp->Extensions.KHR_surfaceless_context = EGL_TRUE;
  508.  
  509.    disp->Extensions.MESA_screen_surface = EGL_TRUE;
  510.  
  511.    if (dri2_dpy->dri2 && dri2_dpy->dri2->base.version >= 3) {
  512.       disp->Extensions.KHR_create_context = EGL_TRUE;
  513.  
  514.       if (dri2_dpy->robustness)
  515.          disp->Extensions.EXT_create_context_robustness = EGL_TRUE;
  516.    }
  517.  
  518.    if (dri2_dpy->image) {
  519.       disp->Extensions.MESA_drm_image = EGL_TRUE;
  520.       disp->Extensions.KHR_image_base = EGL_TRUE;
  521.       disp->Extensions.KHR_gl_renderbuffer_image = EGL_TRUE;
  522.       if (dri2_dpy->image->base.version >= 5 &&
  523.           dri2_dpy->image->createImageFromTexture) {
  524.          disp->Extensions.KHR_gl_texture_2D_image = EGL_TRUE;
  525.          disp->Extensions.KHR_gl_texture_cubemap_image = EGL_TRUE;
  526.       }
  527.    }
  528.     {
  529.         _EGLMode *mode;
  530.         _EGLScreen *screen = malloc(sizeof(*screen));
  531.  
  532.         _eglInitScreen(screen, disp, 3);
  533.         mode = &screen->Modes[0];
  534.         mode->Width = 800;
  535.         mode->Height = 600;
  536.         mode->RefreshRate = 60;
  537.         mode->Optimal = EGL_FALSE;
  538.         mode->Interlaced = EGL_FALSE;
  539.         mode->Name = "800 x 600 60Hz";
  540.  
  541.  
  542.         mode = &screen->Modes[1];
  543.         mode->Width = 1024;
  544.         mode->Height = 768;
  545.         mode->RefreshRate = 60;
  546.         mode->Optimal = EGL_FALSE;
  547.         mode->Interlaced = EGL_FALSE;
  548.         mode->Name = "1024 x 768 60Hz";
  549.  
  550.         mode = &screen->Modes[2];
  551.         mode->Width = 1280;
  552.         mode->Height = 1024;
  553.         mode->RefreshRate = 60;
  554.         mode->Optimal = EGL_FALSE;
  555.         mode->Interlaced = EGL_FALSE;
  556.         mode->Name = "1280 x 1024 60Hz";
  557.  
  558.         _eglLinkScreen(screen);
  559.     }
  560. }
  561.  
  562. EGLBoolean
  563. dri2_create_screen(_EGLDisplay *disp)
  564. {
  565.    const __DRIextension **extensions;
  566.    struct dri2_egl_display *dri2_dpy;
  567.  
  568.    dri2_dpy = disp->DriverData;
  569.  
  570.    if (dri2_dpy->dri2) {
  571.       dri2_dpy->dri_screen =
  572.          dri2_dpy->dri2->createNewScreen(0, dri2_dpy->fd, dri2_dpy->extensions,
  573.                                          &dri2_dpy->driver_configs, disp);
  574.    } else {
  575.       assert(dri2_dpy->swrast);
  576.       dri2_dpy->dri_screen =
  577.          dri2_dpy->swrast->createNewScreen(0, dri2_dpy->extensions,
  578.                                            &dri2_dpy->driver_configs, disp);
  579.    }
  580.  
  581.    if (dri2_dpy->dri_screen == NULL) {
  582.       _eglLog(_EGL_WARNING, "DRI2: failed to create dri screen");
  583.       return EGL_FALSE;
  584.    }
  585.  
  586.    dri2_dpy->own_dri_screen = 1;
  587.  
  588.    extensions = dri2_dpy->core->getExtensions(dri2_dpy->dri_screen);
  589.  
  590.    if (dri2_dpy->dri2) {
  591.       unsigned i;
  592.  
  593.       if (!dri2_bind_extensions(dri2_dpy, dri2_core_extensions, extensions))
  594.          goto cleanup_dri_screen;
  595.  
  596.       for (i = 0; extensions[i]; i++) {
  597.          if (strcmp(extensions[i]->name, __DRI2_ROBUSTNESS) == 0) {
  598.             dri2_dpy->robustness = (__DRIrobustnessExtension *) extensions[i];
  599.          }
  600.          if (strcmp(extensions[i]->name, __DRI2_CONFIG_QUERY) == 0) {
  601.             dri2_dpy->config = (__DRI2configQueryExtension *) extensions[i];
  602.          }
  603.       }
  604.    } else {
  605.       assert(dri2_dpy->swrast);
  606.       if (!dri2_bind_extensions(dri2_dpy, swrast_core_extensions, extensions))
  607.          goto cleanup_dri_screen;
  608.    }
  609.  
  610.    dri2_setup_screen(disp);
  611.  
  612.    return EGL_TRUE;
  613.  
  614.  cleanup_dri_screen:
  615.    dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen);
  616.  
  617.    return EGL_FALSE;
  618. }
  619.  
  620. /**
  621.  * Called via eglInitialize(), GLX_drv->API.Initialize().
  622.  */
  623. static EGLBoolean
  624. dri2_initialize(_EGLDriver *drv, _EGLDisplay *disp)
  625. {
  626.    /* not until swrast_dri is supported */
  627.    if (disp->Options.UseFallback)
  628.       return EGL_FALSE;
  629.  
  630.    return dri2_initialize_drm(drv, disp);
  631.  
  632. #if 0
  633.    switch (disp->Platform) {
  634. #ifdef HAVE_X11_PLATFORM
  635.    case _EGL_PLATFORM_X11:
  636.       if (disp->Options.TestOnly)
  637.          return EGL_TRUE;
  638.       return dri2_initialize_x11(drv, disp);
  639. #endif
  640.  
  641. #ifdef HAVE_LIBUDEV
  642. #ifdef HAVE_DRM_PLATFORM
  643.    case _EGL_PLATFORM_DRM:
  644.       if (disp->Options.TestOnly)
  645.          return EGL_TRUE;
  646.       return dri2_initialize_drm(drv, disp);
  647. #endif
  648. #ifdef HAVE_WAYLAND_PLATFORM
  649.    case _EGL_PLATFORM_WAYLAND:
  650.       if (disp->Options.TestOnly)
  651.          return EGL_TRUE;
  652.       return dri2_initialize_wayland(drv, disp);
  653. #endif
  654. #endif
  655. #ifdef HAVE_ANDROID_PLATFORM
  656.    case _EGL_PLATFORM_ANDROID:
  657.       if (disp->Options.TestOnly)
  658.          return EGL_TRUE;
  659.       return dri2_initialize_android(drv, disp);
  660. #endif
  661.  
  662.    default:
  663.       return EGL_FALSE;
  664.    }
  665. #endif
  666. }
  667.  
  668. /**
  669.  * Called via eglTerminate(), drv->API.Terminate().
  670.  */
  671. static EGLBoolean
  672. dri2_terminate(_EGLDriver *drv, _EGLDisplay *disp)
  673. {
  674.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  675.  
  676.    _eglReleaseDisplayResources(drv, disp);
  677.    _eglCleanupDisplay(disp);
  678.  
  679.    if (dri2_dpy->own_dri_screen)
  680.       dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen);
  681. //   if (dri2_dpy->fd)
  682. //      close(dri2_dpy->fd);
  683. //   if (dri2_dpy->driver)
  684. //      dlclose(dri2_dpy->driver);
  685.    free(dri2_dpy->device_name);
  686.  
  687.    if (disp->PlatformDisplay == NULL) {
  688.       switch (disp->Platform) {
  689. #ifdef HAVE_X11_PLATFORM
  690.       case _EGL_PLATFORM_X11:
  691.          xcb_disconnect(dri2_dpy->conn);
  692.          break;
  693. #endif
  694. #ifdef HAVE_DRM_PLATFORM
  695.       case _EGL_PLATFORM_DRM:
  696.          if (dri2_dpy->own_device) {
  697.             gbm_device_destroy(&dri2_dpy->gbm_dri->base.base);
  698.          }
  699.          break;
  700. #endif
  701.       default:
  702.          break;
  703.       }
  704.    }
  705.  
  706.    free(dri2_dpy);
  707.    disp->DriverData = NULL;
  708.  
  709.    return EGL_TRUE;
  710. }
  711.  
  712. /**
  713.  * Set the error code after a call to
  714.  * dri2_egl_display::dri2::createContextAttribs.
  715.  */
  716. static void
  717. dri2_create_context_attribs_error(int dri_error)
  718. {
  719.    EGLint egl_error;
  720.  
  721.    switch (dri_error) {
  722.    case __DRI_CTX_ERROR_SUCCESS:
  723.       return;
  724.  
  725.    case __DRI_CTX_ERROR_NO_MEMORY:
  726.       egl_error = EGL_BAD_ALLOC;
  727.       break;
  728.  
  729.   /* From the EGL_KHR_create_context spec, section "Errors":
  730.    *
  731.    *   * If <config> does not support a client API context compatible
  732.    *     with the requested API major and minor version, [...] context flags,
  733.    *     and context reset notification behavior (for client API types where
  734.    *     these attributes are supported), then an EGL_BAD_MATCH error is
  735.    *     generated.
  736.    *
  737.    *   * If an OpenGL ES context is requested and the values for
  738.    *     attributes EGL_CONTEXT_MAJOR_VERSION_KHR and
  739.    *     EGL_CONTEXT_MINOR_VERSION_KHR specify an OpenGL ES version that
  740.    *     is not defined, than an EGL_BAD_MATCH error is generated.
  741.    *
  742.    *   * If an OpenGL context is requested, the requested version is
  743.    *     greater than 3.2, and the value for attribute
  744.    *     EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR has no bits set; has any
  745.    *     bits set other than EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR and
  746.    *     EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR; has more than
  747.    *     one of these bits set; or if the implementation does not support
  748.    *     the requested profile, then an EGL_BAD_MATCH error is generated.
  749.    */
  750.    case __DRI_CTX_ERROR_BAD_API:
  751.    case __DRI_CTX_ERROR_BAD_VERSION:
  752.    case __DRI_CTX_ERROR_BAD_FLAG:
  753.       egl_error = EGL_BAD_MATCH;
  754.       break;
  755.  
  756.   /* From the EGL_KHR_create_context spec, section "Errors":
  757.    *
  758.    *   * If an attribute name or attribute value in <attrib_list> is not
  759.    *     recognized (including unrecognized bits in bitmask attributes),
  760.    *     then an EGL_BAD_ATTRIBUTE error is generated."
  761.    */
  762.    case __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE:
  763.    case __DRI_CTX_ERROR_UNKNOWN_FLAG:
  764.       egl_error = EGL_BAD_ATTRIBUTE;
  765.       break;
  766.  
  767.    default:
  768.       assert(0);
  769.       egl_error = EGL_BAD_MATCH;
  770.       break;
  771.    }
  772.  
  773.    _eglError(egl_error, "dri2_create_context");
  774. }
  775.  
  776. /**
  777.  * Called via eglCreateContext(), drv->API.CreateContext().
  778.  */
  779. static _EGLContext *
  780. dri2_create_context(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf,
  781.                     _EGLContext *share_list, const EGLint *attrib_list)
  782. {
  783.    struct dri2_egl_context *dri2_ctx;
  784.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  785.    struct dri2_egl_context *dri2_ctx_shared = dri2_egl_context(share_list);
  786.    __DRIcontext *shared =
  787.       dri2_ctx_shared ? dri2_ctx_shared->dri_context : NULL;
  788.    struct dri2_egl_config *dri2_config = dri2_egl_config(conf);
  789.    const __DRIconfig *dri_config;
  790.    int api;
  791.  
  792.    (void) drv;
  793.  
  794.    dri2_ctx = malloc(sizeof *dri2_ctx);
  795.    if (!dri2_ctx) {
  796.       _eglError(EGL_BAD_ALLOC, "eglCreateContext");
  797.       return NULL;
  798.    }
  799.  
  800.    if (!_eglInitContext(&dri2_ctx->base, disp, conf, attrib_list))
  801.       goto cleanup;
  802.  
  803.    switch (dri2_ctx->base.ClientAPI) {
  804.    case EGL_OPENGL_ES_API:
  805.       switch (dri2_ctx->base.ClientMajorVersion) {
  806.       case 1:
  807.          api = __DRI_API_GLES;
  808.          break;
  809.       case 2:
  810.          api = __DRI_API_GLES2;
  811.          break;
  812.       case 3:
  813.          api = __DRI_API_GLES3;
  814.          break;
  815.       default:
  816.          _eglError(EGL_BAD_PARAMETER, "eglCreateContext");
  817.          return NULL;
  818.       }
  819.       break;
  820.    case EGL_OPENGL_API:
  821.       if ((dri2_ctx->base.ClientMajorVersion >= 4
  822.            || (dri2_ctx->base.ClientMajorVersion == 3
  823.                && dri2_ctx->base.ClientMinorVersion >= 2))
  824.           && dri2_ctx->base.Profile == EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR)
  825.          api = __DRI_API_OPENGL_CORE;
  826.       else
  827.          api = __DRI_API_OPENGL;
  828.       break;
  829.    default:
  830.       _eglError(EGL_BAD_PARAMETER, "eglCreateContext");
  831.       free(dri2_ctx);
  832.       return NULL;
  833.    }
  834.  
  835.    if (conf != NULL) {
  836.       /* The config chosen here isn't necessarily
  837.        * used for surfaces later.
  838.        * A pixmap surface will use the single config.
  839.        * This opportunity depends on disabling the
  840.        * doubleBufferMode check in
  841.        * src/mesa/main/context.c:check_compatible()
  842.        */
  843.       if (dri2_config->dri_double_config)
  844.          dri_config = dri2_config->dri_double_config;
  845.       else
  846.          dri_config = dri2_config->dri_single_config;
  847.  
  848.       /* EGL_WINDOW_BIT is set only when there is a dri_double_config.  This
  849.        * makes sure the back buffer will always be used.
  850.        */
  851.       if (conf->SurfaceType & EGL_WINDOW_BIT)
  852.          dri2_ctx->base.WindowRenderBuffer = EGL_BACK_BUFFER;
  853.    }
  854.    else
  855.       dri_config = NULL;
  856.  
  857.    if (dri2_dpy->dri2) {
  858.       if (dri2_dpy->dri2->base.version >= 3) {
  859.          unsigned error;
  860.          unsigned num_attribs = 0;
  861.          uint32_t ctx_attribs[8];
  862.  
  863.          ctx_attribs[num_attribs++] = __DRI_CTX_ATTRIB_MAJOR_VERSION;
  864.          ctx_attribs[num_attribs++] = dri2_ctx->base.ClientMajorVersion;
  865.          ctx_attribs[num_attribs++] = __DRI_CTX_ATTRIB_MINOR_VERSION;
  866.          ctx_attribs[num_attribs++] = dri2_ctx->base.ClientMinorVersion;
  867.  
  868.          if (dri2_ctx->base.Flags != 0) {
  869.             /* If the implementation doesn't support the __DRI2_ROBUSTNESS
  870.              * extension, don't even try to send it the robust-access flag.
  871.              * It may explode.  Instead, generate the required EGL error here.
  872.              */
  873.             if ((dri2_ctx->base.Flags & EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR) != 0
  874.                 && !dri2_dpy->robustness) {
  875.                _eglError(EGL_BAD_MATCH, "eglCreateContext");
  876.                goto cleanup;
  877.             }
  878.  
  879.             ctx_attribs[num_attribs++] = __DRI_CTX_ATTRIB_FLAGS;
  880.             ctx_attribs[num_attribs++] = dri2_ctx->base.Flags;
  881.          }
  882.  
  883.          if (dri2_ctx->base.ResetNotificationStrategy != EGL_NO_RESET_NOTIFICATION_KHR) {
  884.             /* If the implementation doesn't support the __DRI2_ROBUSTNESS
  885.              * extension, don't even try to send it a reset strategy.  It may
  886.              * explode.  Instead, generate the required EGL error here.
  887.              */
  888.             if (!dri2_dpy->robustness) {
  889.                _eglError(EGL_BAD_CONFIG, "eglCreateContext");
  890.                goto cleanup;
  891.             }
  892.  
  893.             ctx_attribs[num_attribs++] = __DRI_CTX_ATTRIB_RESET_STRATEGY;
  894.             ctx_attribs[num_attribs++] = __DRI_CTX_RESET_LOSE_CONTEXT;
  895.          }
  896.  
  897.          assert(num_attribs <= ARRAY_SIZE(ctx_attribs));
  898.  
  899.          dri2_ctx->dri_context =
  900.             dri2_dpy->dri2->createContextAttribs(dri2_dpy->dri_screen,
  901.                                                  api,
  902.                                                  dri_config,
  903.                                                  shared,
  904.                                                  num_attribs / 2,
  905.                                                  ctx_attribs,
  906.                                                  & error,
  907.                                                  dri2_ctx);
  908.          dri2_create_context_attribs_error(error);
  909.       } else {
  910.          dri2_ctx->dri_context =
  911.             dri2_dpy->dri2->createNewContextForAPI(dri2_dpy->dri_screen,
  912.                                                    api,
  913.                                                    dri_config,
  914.                                                    shared,
  915.                                                    dri2_ctx);
  916.       }
  917.    } else {
  918.       assert(dri2_dpy->swrast);
  919.       dri2_ctx->dri_context =
  920.          dri2_dpy->swrast->createNewContextForAPI(dri2_dpy->dri_screen,
  921.                                                   api,
  922.                                                   dri_config,
  923.                                                   shared,
  924.                                                   dri2_ctx);
  925.    }
  926.  
  927.    if (!dri2_ctx->dri_context)
  928.       goto cleanup;
  929.  
  930.    return &dri2_ctx->base;
  931.  
  932.  cleanup:
  933.    free(dri2_ctx);
  934.    return NULL;
  935. }
  936.  
  937. /**
  938.  * Called via eglDestroyContext(), drv->API.DestroyContext().
  939.  */
  940. static EGLBoolean
  941. dri2_destroy_context(_EGLDriver *drv, _EGLDisplay *disp, _EGLContext *ctx)
  942. {
  943.    struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
  944.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  945.  
  946.    if (_eglPutContext(ctx)) {
  947.       dri2_dpy->core->destroyContext(dri2_ctx->dri_context);
  948.       free(dri2_ctx);
  949.    }
  950.  
  951.    return EGL_TRUE;
  952. }
  953.  
  954. /**
  955.  * Called via eglMakeCurrent(), drv->API.MakeCurrent().
  956.  */
  957. static EGLBoolean
  958. dri2_make_current(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *dsurf,
  959.                   _EGLSurface *rsurf, _EGLContext *ctx)
  960. {
  961.    struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv);
  962.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  963.    struct dri2_egl_surface *dri2_dsurf = dri2_egl_surface(dsurf);
  964.    struct dri2_egl_surface *dri2_rsurf = dri2_egl_surface(rsurf);
  965.    struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
  966.    _EGLContext *old_ctx;
  967.    _EGLSurface *old_dsurf, *old_rsurf;
  968.    __DRIdrawable *ddraw, *rdraw;
  969.    __DRIcontext *cctx;
  970.  
  971.    /* make new bindings */
  972.    if (!_eglBindContext(ctx, dsurf, rsurf, &old_ctx, &old_dsurf, &old_rsurf))
  973.       return EGL_FALSE;
  974.  
  975.    /* flush before context switch */
  976.    if (old_ctx && dri2_drv->glFlush)
  977.       dri2_drv->glFlush();
  978.  
  979.    ddraw = (dri2_dsurf) ? dri2_dsurf->dri_drawable : NULL;
  980.    rdraw = (dri2_rsurf) ? dri2_rsurf->dri_drawable : NULL;
  981.    cctx = (dri2_ctx) ? dri2_ctx->dri_context : NULL;
  982.  
  983.    if (old_ctx) {
  984.       __DRIcontext *old_cctx = dri2_egl_context(old_ctx)->dri_context;
  985.       dri2_dpy->core->unbindContext(old_cctx);
  986.    }
  987.  
  988.    if ((cctx == NULL && ddraw == NULL && rdraw == NULL) ||
  989.        dri2_dpy->core->bindContext(cctx, ddraw, rdraw)) {
  990.       if (old_dsurf)
  991.          drv->API.DestroySurface(drv, disp, old_dsurf);
  992.       if (old_rsurf)
  993.          drv->API.DestroySurface(drv, disp, old_rsurf);
  994.       if (old_ctx)
  995.          drv->API.DestroyContext(drv, disp, old_ctx);
  996.  
  997.       return EGL_TRUE;
  998.    } else {
  999.       /* undo the previous _eglBindContext */
  1000.       _eglBindContext(old_ctx, old_dsurf, old_rsurf, &ctx, &dsurf, &rsurf);
  1001.       assert(&dri2_ctx->base == ctx &&
  1002.              &dri2_dsurf->base == dsurf &&
  1003.              &dri2_rsurf->base == rsurf);
  1004.  
  1005.       _eglPutSurface(dsurf);
  1006.       _eglPutSurface(rsurf);
  1007.       _eglPutContext(ctx);
  1008.  
  1009.       _eglPutSurface(old_dsurf);
  1010.       _eglPutSurface(old_rsurf);
  1011.       _eglPutContext(old_ctx);
  1012.  
  1013.       return EGL_FALSE;
  1014.    }
  1015. }
  1016.  
  1017. /*
  1018.  * Called from eglGetProcAddress() via drv->API.GetProcAddress().
  1019.  */
  1020. static _EGLProc
  1021. dri2_get_proc_address(_EGLDriver *drv, const char *procname)
  1022. {
  1023.    struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv);
  1024.  
  1025.    return dri2_drv->get_proc_address(procname);
  1026. }
  1027.  
  1028. static EGLBoolean
  1029. dri2_wait_client(_EGLDriver *drv, _EGLDisplay *disp, _EGLContext *ctx)
  1030. {
  1031.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  1032.    struct dri2_egl_surface *dri2_surf = dri2_egl_surface(ctx->DrawSurface);
  1033.  
  1034.    (void) drv;
  1035.  
  1036.    /* FIXME: If EGL allows frontbuffer rendering for window surfaces,
  1037.     * we need to copy fake to real here.*/
  1038.  
  1039.    if (dri2_dpy->flush != NULL)
  1040.       dri2_dpy->flush->flush(dri2_surf->dri_drawable);
  1041.  
  1042.    return EGL_TRUE;
  1043. }
  1044.  
  1045. static EGLBoolean
  1046. dri2_wait_native(_EGLDriver *drv, _EGLDisplay *disp, EGLint engine)
  1047. {
  1048.    (void) drv;
  1049.    (void) disp;
  1050.  
  1051.    if (engine != EGL_CORE_NATIVE_ENGINE)
  1052.       return _eglError(EGL_BAD_PARAMETER, "eglWaitNative");
  1053.    /* glXWaitX(); */
  1054.  
  1055.    return EGL_TRUE;
  1056. }
  1057.  
  1058. static EGLBoolean
  1059. dri2_bind_tex_image(_EGLDriver *drv,
  1060.                     _EGLDisplay *disp, _EGLSurface *surf, EGLint buffer)
  1061. {
  1062.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  1063.    struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
  1064.    struct dri2_egl_context *dri2_ctx;
  1065.    _EGLContext *ctx;
  1066.    GLint format, target;
  1067.  
  1068.    ctx = _eglGetCurrentContext();
  1069.    dri2_ctx = dri2_egl_context(ctx);
  1070.  
  1071.    if (!_eglBindTexImage(drv, disp, surf, buffer))
  1072.       return EGL_FALSE;
  1073.  
  1074.    switch (dri2_surf->base.TextureFormat) {
  1075.    case EGL_TEXTURE_RGB:
  1076.       format = __DRI_TEXTURE_FORMAT_RGB;
  1077.       break;
  1078.    case EGL_TEXTURE_RGBA:
  1079.       format = __DRI_TEXTURE_FORMAT_RGBA;
  1080.       break;
  1081.    default:
  1082.       assert(0);
  1083.    }
  1084.  
  1085.    switch (dri2_surf->base.TextureTarget) {
  1086.    case EGL_TEXTURE_2D:
  1087.       target = GL_TEXTURE_2D;
  1088.       break;
  1089.    default:
  1090.       assert(0);
  1091.    }
  1092.  
  1093.    (*dri2_dpy->tex_buffer->setTexBuffer2)(dri2_ctx->dri_context,
  1094.                                           target, format,
  1095.                                           dri2_surf->dri_drawable);
  1096.  
  1097.    return EGL_TRUE;
  1098. }
  1099.  
  1100. static EGLBoolean
  1101. dri2_release_tex_image(_EGLDriver *drv,
  1102.                        _EGLDisplay *disp, _EGLSurface *surf, EGLint buffer)
  1103. {
  1104. #if __DRI_TEX_BUFFER_VERSION >= 3
  1105.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  1106.    struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
  1107.    struct dri2_egl_context *dri2_ctx;
  1108.    _EGLContext *ctx;
  1109.    GLint  target;
  1110.  
  1111.    ctx = _eglGetCurrentContext();
  1112.    dri2_ctx = dri2_egl_context(ctx);
  1113.  
  1114.    if (!_eglReleaseTexImage(drv, disp, surf, buffer))
  1115.       return EGL_FALSE;
  1116.  
  1117.    switch (dri2_surf->base.TextureTarget) {
  1118.    case EGL_TEXTURE_2D:
  1119.       target = GL_TEXTURE_2D;
  1120.       break;
  1121.    default:
  1122.       assert(0);
  1123.    }
  1124.    if (dri2_dpy->tex_buffer->releaseTexBuffer!=NULL)
  1125.     (*dri2_dpy->tex_buffer->releaseTexBuffer)(dri2_ctx->dri_context,
  1126.                                              target,
  1127.                                              dri2_surf->dri_drawable);
  1128. #endif
  1129.  
  1130.    return EGL_TRUE;
  1131. }
  1132.  
  1133. static _EGLImage *
  1134. dri2_create_image(_EGLDisplay *disp, __DRIimage *dri_image)
  1135. {
  1136.    struct dri2_egl_image *dri2_img;
  1137.  
  1138.    if (dri_image == NULL) {
  1139.       _eglError(EGL_BAD_ALLOC, "dri2_create_image");
  1140.       return NULL;
  1141.    }
  1142.  
  1143.    dri2_img = malloc(sizeof *dri2_img);
  1144.    if (!dri2_img) {
  1145.       _eglError(EGL_BAD_ALLOC, "dri2_create_image");
  1146.       return NULL;
  1147.    }
  1148.  
  1149.    if (!_eglInitImage(&dri2_img->base, disp)) {
  1150.       free(dri2_img);
  1151.       return NULL;
  1152.    }
  1153.  
  1154.    dri2_img->dri_image = dri_image;
  1155.  
  1156.    return &dri2_img->base;
  1157. }
  1158.  
  1159. static _EGLImage *
  1160. dri2_create_image_khr_renderbuffer(_EGLDisplay *disp, _EGLContext *ctx,
  1161.                                    EGLClientBuffer buffer,
  1162.                                    const EGLint *attr_list)
  1163. {
  1164.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  1165.    struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
  1166.    GLuint renderbuffer = (GLuint) (uintptr_t) buffer;
  1167.    __DRIimage *dri_image;
  1168.  
  1169.    if (renderbuffer == 0) {
  1170.       _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
  1171.       return EGL_NO_IMAGE_KHR;
  1172.    }
  1173.  
  1174.    dri_image =
  1175.       dri2_dpy->image->createImageFromRenderbuffer(dri2_ctx->dri_context,
  1176.                                                    renderbuffer, NULL);
  1177.  
  1178.    return dri2_create_image(disp, dri_image);
  1179. }
  1180.  
  1181. static _EGLImage *
  1182. dri2_create_image_mesa_drm_buffer(_EGLDisplay *disp, _EGLContext *ctx,
  1183.                                   EGLClientBuffer buffer, const EGLint *attr_list)
  1184. {
  1185.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  1186.    EGLint format, name, pitch, err;
  1187.    _EGLImageAttribs attrs;
  1188.    __DRIimage *dri_image;
  1189.  
  1190.    name = (EGLint) (uintptr_t) buffer;
  1191.  
  1192.    err = _eglParseImageAttribList(&attrs, disp, attr_list);
  1193.    if (err != EGL_SUCCESS)
  1194.       return NULL;
  1195.  
  1196.    if (attrs.Width <= 0 || attrs.Height <= 0 ||
  1197.        attrs.DRMBufferStrideMESA <= 0) {
  1198.       _eglError(EGL_BAD_PARAMETER,
  1199.                 "bad width, height or stride");
  1200.       return NULL;
  1201.    }
  1202.  
  1203.    switch (attrs.DRMBufferFormatMESA) {
  1204.    case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA:
  1205.       format = __DRI_IMAGE_FORMAT_ARGB8888;
  1206.       pitch = attrs.DRMBufferStrideMESA;
  1207.       break;
  1208.    case EGL_DRM_BUFFER_FORMAT_R8_MESA:
  1209.       format = __DRI_IMAGE_FORMAT_R8;
  1210.       pitch = attrs.DRMBufferStrideMESA;
  1211.       break;
  1212.  
  1213.    default:
  1214.       _eglError(EGL_BAD_PARAMETER,
  1215.                 "dri2_create_image_khr: unsupported pixmap depth");
  1216.       return NULL;
  1217.    }
  1218.  
  1219.    dri_image =
  1220.       dri2_dpy->image->createImageFromName(dri2_dpy->dri_screen,
  1221.                                            attrs.Width,
  1222.                                            attrs.Height,
  1223.                                            format,
  1224.                                            name,
  1225.                                            pitch,
  1226.                                            NULL);
  1227.  
  1228.    return dri2_create_image(disp, dri_image);
  1229. }
  1230.  
  1231. /* This structure describes how a wl_buffer maps to one or more
  1232.  * __DRIimages.  A wl_drm_buffer stores the wl_drm format code and the
  1233.  * offsets and strides of the planes in the buffer.  This table maps a
  1234.  * wl_drm format code to a description of the planes in the buffer
  1235.  * that lets us create a __DRIimage for each of the planes. */
  1236.  
  1237. static const struct wl_drm_components_descriptor {
  1238.    uint32_t dri_components;
  1239.    EGLint components;
  1240.    int nplanes;
  1241. } wl_drm_components[] = {
  1242.    { __DRI_IMAGE_COMPONENTS_RGB, EGL_TEXTURE_RGB, 1 },
  1243.    { __DRI_IMAGE_COMPONENTS_RGBA, EGL_TEXTURE_RGBA, 1 },
  1244.    { __DRI_IMAGE_COMPONENTS_Y_U_V, EGL_TEXTURE_Y_U_V_WL, 3 },
  1245.    { __DRI_IMAGE_COMPONENTS_Y_UV, EGL_TEXTURE_Y_UV_WL, 2 },
  1246.    { __DRI_IMAGE_COMPONENTS_Y_XUXV, EGL_TEXTURE_Y_XUXV_WL, 2 },
  1247. };
  1248.  
  1249. static _EGLImage *
  1250. dri2_create_image_wayland_wl_buffer(_EGLDisplay *disp, _EGLContext *ctx,
  1251.                                     EGLClientBuffer _buffer,
  1252.                                     const EGLint *attr_list)
  1253. {
  1254.    struct egl_planar_buffer *buffer = (struct egl_planar_buffer *) _buffer;
  1255.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  1256.    const struct wl_drm_components_descriptor *f;
  1257.    __DRIimage *dri_image;
  1258.    _EGLImageAttribs attrs;
  1259.    EGLint err;
  1260.    int32_t plane;
  1261.  
  1262.  
  1263.    err = _eglParseImageAttribList(&attrs, disp, attr_list);
  1264.    plane = attrs.PlaneWL;
  1265.    if (err != EGL_SUCCESS) {
  1266.       _eglError(EGL_BAD_PARAMETER, "dri2_create_image_wayland_wl_buffer");
  1267.       return NULL;
  1268.    }
  1269.  
  1270.    f = buffer->driver_format;
  1271.    if (plane < 0 || plane >= f->nplanes) {
  1272.       _eglError(EGL_BAD_PARAMETER,
  1273.                 "dri2_create_image_wayland_wl_buffer (plane out of bounds)");
  1274.       return NULL;
  1275.    }
  1276.  
  1277.    dri_image = dri2_dpy->image->fromPlanar(buffer->driver_buffer, plane, NULL);
  1278.  
  1279.    if (dri_image == NULL) {
  1280.       _eglError(EGL_BAD_PARAMETER, "dri2_create_image_wayland_wl_buffer");
  1281.       return NULL;
  1282.    }
  1283.  
  1284.    return dri2_create_image(disp, dri_image);
  1285. }
  1286.  
  1287. /**
  1288.  * Set the error code after a call to
  1289.  * dri2_egl_image::dri_image::createImageFromTexture.
  1290.  */
  1291. static void
  1292. dri2_create_image_khr_texture_error(int dri_error)
  1293. {
  1294.    EGLint egl_error;
  1295.  
  1296.    switch (dri_error) {
  1297.    case __DRI_IMAGE_ERROR_SUCCESS:
  1298.       return;
  1299.  
  1300.    case __DRI_IMAGE_ERROR_BAD_ALLOC:
  1301.       egl_error = EGL_BAD_ALLOC;
  1302.       break;
  1303.  
  1304.    case __DRI_IMAGE_ERROR_BAD_MATCH:
  1305.       egl_error = EGL_BAD_MATCH;
  1306.       break;
  1307.  
  1308.    case __DRI_IMAGE_ERROR_BAD_PARAMETER:
  1309.       egl_error = EGL_BAD_PARAMETER;
  1310.       break;
  1311.  
  1312.    default:
  1313.       assert(0);
  1314.       egl_error = EGL_BAD_MATCH;
  1315.       break;
  1316.    }
  1317.  
  1318.    _eglError(egl_error, "dri2_create_image_khr_texture");
  1319. }
  1320.  
  1321. static _EGLImage *
  1322. dri2_create_image_khr_texture(_EGLDisplay *disp, _EGLContext *ctx,
  1323.                                    EGLenum target,
  1324.                                    EGLClientBuffer buffer,
  1325.                                    const EGLint *attr_list)
  1326. {
  1327.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  1328.    struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
  1329.    struct dri2_egl_image *dri2_img;
  1330.    GLuint texture = (GLuint) (uintptr_t) buffer;
  1331.    _EGLImageAttribs attrs;
  1332.    GLuint depth;
  1333.    GLenum gl_target;
  1334.    unsigned error;
  1335.  
  1336.    if (texture == 0) {
  1337.       _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
  1338.       return EGL_NO_IMAGE_KHR;
  1339.    }
  1340.  
  1341.    if (_eglParseImageAttribList(&attrs, disp, attr_list) != EGL_SUCCESS)
  1342.       return EGL_NO_IMAGE_KHR;
  1343.  
  1344.    switch (target) {
  1345.    case EGL_GL_TEXTURE_2D_KHR:
  1346.       depth = 0;
  1347.       gl_target = GL_TEXTURE_2D;
  1348.       break;
  1349.    case EGL_GL_TEXTURE_3D_KHR:
  1350.       depth = attrs.GLTextureZOffset;
  1351.       gl_target = GL_TEXTURE_3D;
  1352.       break;
  1353.    case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:
  1354.    case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:
  1355.    case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:
  1356.    case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:
  1357.    case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:
  1358.    case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:
  1359.       depth = target - EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR;
  1360.       gl_target = GL_TEXTURE_CUBE_MAP;
  1361.       break;
  1362.    default:
  1363.       _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
  1364.       return EGL_NO_IMAGE_KHR;
  1365.    }
  1366.  
  1367.    dri2_img = malloc(sizeof *dri2_img);
  1368.    if (!dri2_img) {
  1369.       _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr");
  1370.       return EGL_NO_IMAGE_KHR;
  1371.    }
  1372.  
  1373.    if (!_eglInitImage(&dri2_img->base, disp)) {
  1374.       _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr");
  1375.       free(dri2_img);
  1376.       return EGL_NO_IMAGE_KHR;
  1377.    }
  1378.  
  1379.    dri2_img->dri_image =
  1380.       dri2_dpy->image->createImageFromTexture(dri2_ctx->dri_context,
  1381.                                               gl_target,
  1382.                                               texture,
  1383.                                               depth,
  1384.                                               attrs.GLTextureLevel,
  1385.                                               &error,
  1386.                                               dri2_img);
  1387.    dri2_create_image_khr_texture_error(error);
  1388.  
  1389.    if (!dri2_img->dri_image) {
  1390.       free(dri2_img);
  1391.       return EGL_NO_IMAGE_KHR;
  1392.    }
  1393.    return &dri2_img->base;
  1394. }
  1395.  
  1396. _EGLImage *
  1397. dri2_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
  1398.                       _EGLContext *ctx, EGLenum target,
  1399.                       EGLClientBuffer buffer, const EGLint *attr_list)
  1400. {
  1401.    (void) drv;
  1402.  
  1403.    switch (target) {
  1404.    case EGL_GL_TEXTURE_2D_KHR:
  1405.    case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:
  1406.    case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:
  1407.    case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:
  1408.    case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:
  1409.    case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:
  1410.    case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:
  1411.       return dri2_create_image_khr_texture(disp, ctx, target, buffer, attr_list);
  1412.    case EGL_GL_RENDERBUFFER_KHR:
  1413.       return dri2_create_image_khr_renderbuffer(disp, ctx, buffer, attr_list);
  1414.    case EGL_DRM_BUFFER_MESA:
  1415.       return dri2_create_image_mesa_drm_buffer(disp, ctx, buffer, attr_list);
  1416.    case EGL_WAYLAND_BUFFER_WL:
  1417.       return dri2_create_image_wayland_wl_buffer(disp, ctx, buffer, attr_list);
  1418.    default:
  1419.       _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
  1420.       return EGL_NO_IMAGE_KHR;
  1421.    }
  1422. }
  1423.  
  1424. static EGLBoolean
  1425. dri2_destroy_image_khr(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *image)
  1426. {
  1427.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  1428.    struct dri2_egl_image *dri2_img = dri2_egl_image(image);
  1429.  
  1430.    (void) drv;
  1431.  
  1432.    dri2_dpy->image->destroyImage(dri2_img->dri_image);
  1433.    free(dri2_img);
  1434.  
  1435.    return EGL_TRUE;
  1436. }
  1437.  
  1438. static _EGLImage *
  1439. dri2_create_drm_image_mesa(_EGLDriver *drv, _EGLDisplay *disp,
  1440.                            const EGLint *attr_list)
  1441. {
  1442.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  1443.    struct dri2_egl_image *dri2_img;
  1444.    _EGLImageAttribs attrs;
  1445.    unsigned int dri_use, valid_mask;
  1446.    int format;
  1447.    EGLint err = EGL_SUCCESS;
  1448.  
  1449.    (void) drv;
  1450.  
  1451.    dri2_img = malloc(sizeof *dri2_img);
  1452.    if (!dri2_img) {
  1453.       _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr");
  1454.       return EGL_NO_IMAGE_KHR;
  1455.    }
  1456.  
  1457.    if (!attr_list) {
  1458.       err = EGL_BAD_PARAMETER;
  1459.       goto cleanup_img;
  1460.    }
  1461.  
  1462.    if (!_eglInitImage(&dri2_img->base, disp)) {
  1463.       err = EGL_BAD_PARAMETER;
  1464.       goto cleanup_img;
  1465.    }
  1466.  
  1467.    err = _eglParseImageAttribList(&attrs, disp, attr_list);
  1468.    if (err != EGL_SUCCESS)
  1469.       goto cleanup_img;
  1470.  
  1471.    if (attrs.Width <= 0 || attrs.Height <= 0) {
  1472.       _eglLog(_EGL_WARNING, "bad width or height (%dx%d)",
  1473.             attrs.Width, attrs.Height);
  1474.       goto cleanup_img;
  1475.    }
  1476.  
  1477.    switch (attrs.DRMBufferFormatMESA) {
  1478.    case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA:
  1479.       format = __DRI_IMAGE_FORMAT_ARGB8888;
  1480.       break;
  1481.    default:
  1482.       _eglLog(_EGL_WARNING, "bad image format value 0x%04x",
  1483.             attrs.DRMBufferFormatMESA);
  1484.       goto cleanup_img;
  1485.    }
  1486.  
  1487.    valid_mask =
  1488.       EGL_DRM_BUFFER_USE_SCANOUT_MESA |
  1489.       EGL_DRM_BUFFER_USE_SHARE_MESA |
  1490.       EGL_DRM_BUFFER_USE_CURSOR_MESA;
  1491.    if (attrs.DRMBufferUseMESA & ~valid_mask) {
  1492.       _eglLog(_EGL_WARNING, "bad image use bit 0x%04x",
  1493.             attrs.DRMBufferUseMESA & ~valid_mask);
  1494.       goto cleanup_img;
  1495.    }
  1496.  
  1497.    dri_use = 0;
  1498.    if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_SHARE_MESA)
  1499.       dri_use |= __DRI_IMAGE_USE_SHARE;
  1500.    if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_SCANOUT_MESA)
  1501.       dri_use |= __DRI_IMAGE_USE_SCANOUT;
  1502.    if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_CURSOR_MESA)
  1503.       dri_use |= __DRI_IMAGE_USE_CURSOR;
  1504.  
  1505.    dri2_img->dri_image =
  1506.       dri2_dpy->image->createImage(dri2_dpy->dri_screen,
  1507.                                    attrs.Width, attrs.Height,
  1508.                                    format, dri_use, dri2_img);
  1509.    if (dri2_img->dri_image == NULL) {
  1510.       err = EGL_BAD_ALLOC;
  1511.       goto cleanup_img;
  1512.    }
  1513.  
  1514.    return &dri2_img->base;
  1515.  
  1516.  cleanup_img:
  1517.    free(dri2_img);
  1518.    _eglError(err, "dri2_create_drm_image_mesa");
  1519.  
  1520.    return EGL_NO_IMAGE_KHR;
  1521. }
  1522.  
  1523. static EGLBoolean
  1524. dri2_export_drm_image_mesa(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *img,
  1525.                           EGLint *name, EGLint *handle, EGLint *stride)
  1526. {
  1527.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  1528.    struct dri2_egl_image *dri2_img = dri2_egl_image(img);
  1529.  
  1530.    (void) drv;
  1531.  
  1532.    if (name && !dri2_dpy->image->queryImage(dri2_img->dri_image,
  1533.                                             __DRI_IMAGE_ATTRIB_NAME, name)) {
  1534.       _eglError(EGL_BAD_ALLOC, "dri2_export_drm_image_mesa");
  1535.       return EGL_FALSE;
  1536.    }
  1537.  
  1538.    if (handle)
  1539.       dri2_dpy->image->queryImage(dri2_img->dri_image,
  1540.                                   __DRI_IMAGE_ATTRIB_HANDLE, handle);
  1541.  
  1542.    if (stride)
  1543.       dri2_dpy->image->queryImage(dri2_img->dri_image,
  1544.                                   __DRI_IMAGE_ATTRIB_STRIDE, stride);
  1545.  
  1546.    return EGL_TRUE;
  1547. }
  1548.  
  1549. #ifdef HAVE_WAYLAND_PLATFORM
  1550.  
  1551. static void
  1552. dri2_wl_reference_buffer(void *user_data, uint32_t name, int fd,
  1553.                          struct wl_drm_buffer *buffer)
  1554. {
  1555.    _EGLDisplay *disp = user_data;
  1556.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  1557.    __DRIimage *img;
  1558.    int i, dri_components = 0;
  1559.  
  1560.    if (fd == -1)
  1561.       img = dri2_dpy->image->createImageFromNames(dri2_dpy->dri_screen,
  1562.                                                   buffer->buffer.width,
  1563.                                                   buffer->buffer.height,
  1564.                                                   buffer->format,
  1565.                                                   (int*)&name, 1,
  1566.                                                   buffer->stride,
  1567.                                                   buffer->offset,
  1568.                                                   NULL);
  1569.    else
  1570.       img = dri2_dpy->image->createImageFromFds(dri2_dpy->dri_screen,
  1571.                                                 buffer->buffer.width,
  1572.                                                 buffer->buffer.height,
  1573.                                                 buffer->format,
  1574.                                                 &fd, 1,
  1575.                                                 buffer->stride,
  1576.                                                 buffer->offset,
  1577.                                                 NULL);
  1578.  
  1579.    if (img == NULL)
  1580.       return;
  1581.  
  1582.    dri2_dpy->image->queryImage(img, __DRI_IMAGE_ATTRIB_COMPONENTS, &dri_components);
  1583.  
  1584.    buffer->driver_format = NULL;
  1585.    for (i = 0; i < ARRAY_SIZE(wl_drm_components); i++)
  1586.       if (wl_drm_components[i].dri_components == dri_components)
  1587.          buffer->driver_format = &wl_drm_components[i];
  1588.  
  1589.    if (buffer->driver_format == NULL)
  1590.       dri2_dpy->image->destroyImage(img);
  1591.    else
  1592.       buffer->driver_buffer = img;
  1593. }
  1594.  
  1595. static void
  1596. dri2_wl_release_buffer(void *user_data, struct wl_drm_buffer *buffer)
  1597. {
  1598.    _EGLDisplay *disp = user_data;
  1599.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  1600.  
  1601.    dri2_dpy->image->destroyImage(buffer->driver_buffer);
  1602. }
  1603.  
  1604. static struct wayland_drm_callbacks wl_drm_callbacks = {
  1605.         .authenticate = NULL,
  1606.         .reference_buffer = dri2_wl_reference_buffer,
  1607.         .release_buffer = dri2_wl_release_buffer
  1608. };
  1609.  
  1610. static EGLBoolean
  1611. dri2_bind_wayland_display_wl(_EGLDriver *drv, _EGLDisplay *disp,
  1612.                              struct wl_display *wl_dpy)
  1613. {
  1614.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  1615.    int ret, flags = 0;
  1616.    uint64_t cap;
  1617.  
  1618.    (void) drv;
  1619.  
  1620.    if (dri2_dpy->wl_server_drm)
  1621.            return EGL_FALSE;
  1622.  
  1623.    wl_drm_callbacks.authenticate =
  1624.       (int(*)(void *, uint32_t)) dri2_dpy->authenticate;
  1625.  
  1626.    ret = drmGetCap(dri2_dpy->fd, DRM_CAP_PRIME, &cap);
  1627.    if (ret == 0 && cap == (DRM_PRIME_CAP_IMPORT | DRM_PRIME_CAP_EXPORT) &&
  1628.        dri2_dpy->image->base.version >= 7 &&
  1629.        dri2_dpy->image->createImageFromFds != NULL)
  1630.       flags |= WAYLAND_DRM_PRIME;
  1631.  
  1632.    dri2_dpy->wl_server_drm =
  1633.            wayland_drm_init(wl_dpy, dri2_dpy->device_name,
  1634.                             &wl_drm_callbacks, disp, flags);
  1635.  
  1636.    if (!dri2_dpy->wl_server_drm)
  1637.            return EGL_FALSE;
  1638.  
  1639.    return EGL_TRUE;
  1640. }
  1641.  
  1642. static EGLBoolean
  1643. dri2_unbind_wayland_display_wl(_EGLDriver *drv, _EGLDisplay *disp,
  1644.                                struct wl_display *wl_dpy)
  1645. {
  1646.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  1647.  
  1648.    (void) drv;
  1649.  
  1650.    if (!dri2_dpy->wl_server_drm)
  1651.            return EGL_FALSE;
  1652.  
  1653.    wayland_drm_uninit(dri2_dpy->wl_server_drm);
  1654.    dri2_dpy->wl_server_drm = NULL;
  1655.  
  1656.    return EGL_TRUE;
  1657. }
  1658.  
  1659. static EGLBoolean
  1660. dri2_query_wayland_buffer_wl(_EGLDriver *drv, _EGLDisplay *disp,
  1661.                              struct wl_buffer *_buffer,
  1662.                              EGLint attribute, EGLint *value)
  1663. {
  1664.    struct wl_drm_buffer *buffer = (struct wl_drm_buffer *) _buffer;
  1665.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  1666.    const struct wl_drm_components_descriptor *format;
  1667.  
  1668.    if (!wayland_buffer_is_drm(dri2_dpy->wl_server_drm, &buffer->buffer))
  1669.       return EGL_FALSE;
  1670.  
  1671.    format = buffer->driver_format;
  1672.    switch (attribute) {
  1673.    case EGL_TEXTURE_FORMAT:
  1674.       *value = format->components;
  1675.       return EGL_TRUE;
  1676.    case EGL_WIDTH:
  1677.       *value = buffer->buffer.width;
  1678.       return EGL_TRUE;
  1679.    case EGL_HEIGHT:
  1680.       *value = buffer->buffer.height;
  1681.       return EGL_TRUE;
  1682.    }
  1683.  
  1684.    return EGL_FALSE;
  1685. }
  1686. #endif
  1687.  
  1688. static void
  1689. dri2_reference_planar_buffer(struct dri2_egl_display *dri2_dpy, uint32_t name,
  1690.                          struct egl_planar_buffer *buffer)
  1691. {
  1692.     __DRIimage *img;
  1693.     int i, dri_components = 0;
  1694.  
  1695.     img = dri2_dpy->image->createImageFromNames(dri2_dpy->dri_screen,
  1696.                                                 buffer->width,
  1697.                                                 buffer->height,
  1698.                                                 buffer->format,
  1699.                                                 (int*)&name, 1,
  1700.                                                 buffer->stride,
  1701.                                                 buffer->offset,
  1702.                                                 NULL);
  1703.  
  1704.    if (img == NULL)
  1705.       return;
  1706.  
  1707.    dri2_dpy->image->queryImage(img, __DRI_IMAGE_ATTRIB_COMPONENTS, &dri_components);
  1708.  
  1709.    buffer->driver_format = NULL;
  1710.    for (i = 0; i < ARRAY_SIZE(wl_drm_components); i++)
  1711.       if (wl_drm_components[i].dri_components == dri_components)
  1712.          buffer->driver_format = &wl_drm_components[i];
  1713.  
  1714.    if (buffer->driver_format == NULL)
  1715.       dri2_dpy->image->destroyImage(img);
  1716.    else
  1717.       buffer->driver_buffer = img;
  1718. }
  1719.  
  1720. _EGLImage *
  1721. dri2_create_planar_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx,
  1722.                          EGLClientBuffer clbuffer, const EGLint *attrib_list)
  1723. {
  1724.     struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
  1725.     _EGLImageAttribs attrs;
  1726.     struct egl_planar_buffer *buffer;
  1727.  
  1728.     EGLint name, err;
  1729.  
  1730.     name = (EGLint) (uintptr_t) clbuffer;
  1731.  
  1732.     err = _eglParseImageAttribList(&attrs, dpy, attrib_list);
  1733.     if (err != EGL_SUCCESS)
  1734.         return NULL;
  1735.  
  1736.     if (attrs.Width <= 0 || attrs.Height <= 0 )
  1737.     {
  1738.         _eglError(EGL_BAD_PARAMETER,
  1739.             "bad width, height or stride");
  1740.         return NULL;
  1741.     }
  1742.  
  1743.     switch (attrs.DRMBufferFormatMESA)
  1744.     {
  1745.         case WL_DRM_FORMAT_YUV410:
  1746.         case WL_DRM_FORMAT_YUV411:
  1747.         case WL_DRM_FORMAT_YUV420:
  1748.         case WL_DRM_FORMAT_YUV422:
  1749.         case WL_DRM_FORMAT_YUV444:
  1750.         case WL_DRM_FORMAT_NV12:
  1751.         case WL_DRM_FORMAT_NV16:
  1752.             break;
  1753.         default:
  1754.             _eglError(EGL_BAD_PARAMETER, "invalid format");
  1755.            return NULL;
  1756.     }
  1757.  
  1758.     buffer = calloc(1, sizeof *buffer);
  1759.     if (buffer == NULL) {
  1760.         _eglError(EGL_BAD_ALLOC, "planar buffer");
  1761.         return NULL;
  1762.     }
  1763.  
  1764.     buffer->width     = attrs.Width;
  1765.     buffer->height    = attrs.Height;
  1766.     buffer->format    = attrs.DRMBufferFormatMESA;
  1767.     buffer->offset[0] = attrs.Plane0_offset;
  1768.     buffer->stride[0] = attrs.Plane0_pitch;
  1769.     buffer->offset[1] = attrs.Plane1_offset;
  1770.     buffer->stride[1] = attrs.Plane1_pitch;
  1771.     buffer->offset[2] = attrs.Plane2_offset;
  1772.     buffer->stride[2] = attrs.Plane2_pitch;
  1773.  
  1774.     dri2_reference_planar_buffer(dri2_dpy, name, buffer);
  1775.     if (buffer->driver_buffer == NULL)
  1776.     {
  1777.         _eglError(EGL_BAD_PARAMETER,"invalid name\n");
  1778.         free(buffer);
  1779.         return NULL;
  1780.     };
  1781.  
  1782.     return (_EGLImage*)buffer;
  1783. }
  1784.  
  1785.  
  1786. static void
  1787. dri2_unload(_EGLDriver *drv)
  1788. {
  1789.    struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv);
  1790.  
  1791. //   if (dri2_drv->handle)
  1792. //      dlclose(dri2_drv->handle);
  1793.    free(dri2_drv);
  1794. }
  1795.  
  1796. static EGLBoolean
  1797. dri2_load(_EGLDriver *drv)
  1798. {
  1799.    struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv);
  1800.    const char *libname = "libGL.dll";
  1801.  
  1802.    lib_handle handle;
  1803.  
  1804.    handle = load_library(libname);
  1805.    if (handle) {
  1806.       dri2_drv->get_proc_address = (_EGLProc (*)(const char *))
  1807.          get_proc_address(handle, "_glapi_get_proc_address");
  1808.       if (!dri2_drv->get_proc_address) {
  1809.          /* no need to keep a reference */
  1810.          handle = 0;
  1811.       }
  1812.    }
  1813.  
  1814.    /* if glapi is not available, loading DRI drivers will fail */
  1815.    if (!dri2_drv->get_proc_address) {
  1816.       _eglLog(_EGL_WARNING, "DRI2: failed to find _glapi_get_proc_address");
  1817.       return EGL_FALSE;
  1818.    }
  1819.  
  1820.    dri2_drv->glFlush = (void (*)(void))
  1821.       dri2_drv->get_proc_address("glFlush");
  1822.  
  1823.    dri2_drv->handle = (void*)handle;
  1824.  
  1825.    return EGL_TRUE;
  1826. }
  1827.  
  1828. /**
  1829.  * This is the main entrypoint into the driver, called by libEGL.
  1830.  * Create a new _EGLDriver object and init its dispatch table.
  1831.  */
  1832. _EGLDriver *
  1833. _eglBuiltInDriverDRI2(const char *args)
  1834. {
  1835.    struct dri2_egl_driver *dri2_drv;
  1836.  
  1837.    (void) args;
  1838.  
  1839.    dri2_drv = calloc(1, sizeof *dri2_drv);
  1840.    if (!dri2_drv)
  1841.       return NULL;
  1842.  
  1843.    if (!dri2_load(&dri2_drv->base)) {
  1844.       free(dri2_drv);
  1845.       return NULL;
  1846.    }
  1847.  
  1848.    _eglInitDriverFallbacks(&dri2_drv->base);
  1849.    dri2_drv->base.API.Initialize = dri2_initialize;
  1850.    dri2_drv->base.API.Terminate = dri2_terminate;
  1851.    dri2_drv->base.API.CreateContext = dri2_create_context;
  1852.    dri2_drv->base.API.DestroyContext = dri2_destroy_context;
  1853.    dri2_drv->base.API.MakeCurrent = dri2_make_current;
  1854.    dri2_drv->base.API.GetProcAddress = dri2_get_proc_address;
  1855.    dri2_drv->base.API.WaitClient = dri2_wait_client;
  1856.    dri2_drv->base.API.WaitNative = dri2_wait_native;
  1857.    dri2_drv->base.API.BindTexImage = dri2_bind_tex_image;
  1858.    dri2_drv->base.API.ReleaseTexImage = dri2_release_tex_image;
  1859.    dri2_drv->base.API.CreateImageKHR = dri2_create_image_khr;
  1860.    dri2_drv->base.API.DestroyImageKHR = dri2_destroy_image_khr;
  1861.    dri2_drv->base.API.CreatePlanarImage = dri2_create_planar_image;
  1862.    dri2_drv->base.API.DestroyPlanarImage = NULL;
  1863.    dri2_drv->base.API.CreateDRMImageMESA = dri2_create_drm_image_mesa;
  1864.    dri2_drv->base.API.ExportDRMImageMESA = dri2_export_drm_image_mesa;
  1865. #ifdef HAVE_WAYLAND_PLATFORM
  1866.    dri2_drv->base.API.BindWaylandDisplayWL = dri2_bind_wayland_display_wl;
  1867.    dri2_drv->base.API.UnbindWaylandDisplayWL = dri2_unbind_wayland_display_wl;
  1868.    dri2_drv->base.API.QueryWaylandBufferWL = dri2_query_wayland_buffer_wl;
  1869. #endif
  1870.  
  1871.    dri2_drv->base.Name = "DRI2";
  1872.    dri2_drv->base.Unload = dri2_unload;
  1873.  
  1874.    return &dri2_drv->base;
  1875. }
  1876.