Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright © 2011 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.  *    Benjamin Franzke <benjaminfranzke@googlemail.com>
  26.  */
  27.  
  28. #include <stdio.h>
  29. #include <stdlib.h>
  30. #include <stddef.h>
  31. #include <stdint.h>
  32. #include <string.h>
  33. #include <errno.h>
  34. #include <limits.h>
  35.  
  36. #include <sys/types.h>
  37. #include <unistd.h>
  38. #include <dlfcn.h>
  39. #include <xf86drm.h>
  40.  
  41. #include <GL/gl.h> /* dri_interface needs GL types */
  42. #include <GL/internal/dri_interface.h>
  43.  
  44. #include "gbm_driint.h"
  45.  
  46. #include "gbmint.h"
  47. #include "loader.h"
  48.  
  49. /* For importing wl_buffer */
  50. #if HAVE_WAYLAND_PLATFORM
  51. #include "../../../egl/wayland/wayland-drm/wayland-drm.h"
  52. #endif
  53.  
  54. static __DRIimage *
  55. dri_lookup_egl_image(__DRIscreen *screen, void *image, void *data)
  56. {
  57.    struct gbm_dri_device *dri = data;
  58.  
  59.    if (dri->lookup_image == NULL)
  60.       return NULL;
  61.  
  62.    return dri->lookup_image(screen, image, dri->lookup_user_data);
  63. }
  64.  
  65. static __DRIbuffer *
  66. dri_get_buffers(__DRIdrawable * driDrawable,
  67.                  int *width, int *height,
  68.                  unsigned int *attachments, int count,
  69.                  int *out_count, void *data)
  70. {
  71.    struct gbm_dri_surface *surf = data;
  72.    struct gbm_dri_device *dri = gbm_dri_device(surf->base.gbm);
  73.  
  74.    if (dri->get_buffers == NULL)
  75.       return NULL;
  76.  
  77.    return dri->get_buffers(driDrawable, width, height, attachments,
  78.                            count, out_count, surf->dri_private);
  79. }
  80.  
  81. static void
  82. dri_flush_front_buffer(__DRIdrawable * driDrawable, void *data)
  83. {
  84.    struct gbm_dri_surface *surf = data;
  85.    struct gbm_dri_device *dri = gbm_dri_device(surf->base.gbm);
  86.  
  87.    if (dri->flush_front_buffer != NULL)
  88.       dri->flush_front_buffer(driDrawable, surf->dri_private);
  89. }
  90.  
  91. static __DRIbuffer *
  92. dri_get_buffers_with_format(__DRIdrawable * driDrawable,
  93.                             int *width, int *height,
  94.                             unsigned int *attachments, int count,
  95.                             int *out_count, void *data)
  96. {
  97.    struct gbm_dri_surface *surf = data;
  98.    struct gbm_dri_device *dri = gbm_dri_device(surf->base.gbm);
  99.  
  100.    if (dri->get_buffers_with_format == NULL)
  101.       return NULL;
  102.  
  103.    return
  104.       dri->get_buffers_with_format(driDrawable, width, height, attachments,
  105.                                    count, out_count, surf->dri_private);
  106. }
  107.  
  108. static int
  109. image_get_buffers(__DRIdrawable *driDrawable,
  110.                   unsigned int format,
  111.                   uint32_t *stamp,
  112.                   void *loaderPrivate,
  113.                   uint32_t buffer_mask,
  114.                   struct __DRIimageList *buffers)
  115. {
  116.    struct gbm_dri_surface *surf = loaderPrivate;
  117.    struct gbm_dri_device *dri = gbm_dri_device(surf->base.gbm);
  118.  
  119.    if (dri->image_get_buffers == NULL)
  120.       return 0;
  121.  
  122.    return dri->image_get_buffers(driDrawable, format, stamp,
  123.                                  surf->dri_private, buffer_mask, buffers);
  124. }
  125.  
  126. static void
  127. swrast_get_drawable_info(__DRIdrawable *driDrawable,
  128.                          int           *x,
  129.                          int           *y,
  130.                          int           *width,
  131.                          int           *height,
  132.                          void          *loaderPrivate)
  133. {
  134.    struct gbm_dri_surface *surf = loaderPrivate;
  135.  
  136.    *x = 0;
  137.    *y = 0;
  138.    *width = surf->base.width;
  139.    *height = surf->base.height;
  140. }
  141.  
  142. static void
  143. swrast_put_image2(__DRIdrawable *driDrawable,
  144.                   int            op,
  145.                   int            x,
  146.                   int            y,
  147.                   int            width,
  148.                   int            height,
  149.                   int            stride,
  150.                   char          *data,
  151.                   void          *loaderPrivate)
  152. {
  153.    struct gbm_dri_surface *surf = loaderPrivate;
  154.    struct gbm_dri_device *dri = gbm_dri_device(surf->base.gbm);
  155.  
  156.    dri->swrast_put_image2(driDrawable,
  157.                           op, x, y,
  158.                           width, height, stride,
  159.                           data, surf->dri_private);
  160. }
  161.  
  162. static void
  163. swrast_put_image(__DRIdrawable *driDrawable,
  164.                  int            op,
  165.                  int            x,
  166.                  int            y,
  167.                  int            width,
  168.                  int            height,
  169.                  char          *data,
  170.                  void          *loaderPrivate)
  171. {
  172.    return swrast_put_image2(driDrawable, op, x, y, width, height,
  173.                             width * 4, data, loaderPrivate);
  174. }
  175.  
  176. static void
  177. swrast_get_image(__DRIdrawable *driDrawable,
  178.                  int            x,
  179.                  int            y,
  180.                  int            width,
  181.                  int            height,
  182.                  char          *data,
  183.                  void          *loaderPrivate)
  184. {
  185.    struct gbm_dri_surface *surf = loaderPrivate;
  186.    struct gbm_dri_device *dri = gbm_dri_device(surf->base.gbm);
  187.  
  188.    dri->swrast_get_image(driDrawable,
  189.                          x, y,
  190.                          width, height,
  191.                          data, surf->dri_private);
  192. }
  193.  
  194. static const __DRIuseInvalidateExtension use_invalidate = {
  195.    .base = { __DRI_USE_INVALIDATE, 1 }
  196. };
  197.  
  198. static const __DRIimageLookupExtension image_lookup_extension = {
  199.    .base = { __DRI_IMAGE_LOOKUP, 1 },
  200.  
  201.    .lookupEGLImage          = dri_lookup_egl_image
  202. };
  203.  
  204. static const __DRIdri2LoaderExtension dri2_loader_extension = {
  205.    .base = { __DRI_DRI2_LOADER, 3 },
  206.  
  207.    .getBuffers              = dri_get_buffers,
  208.    .flushFrontBuffer        = dri_flush_front_buffer,
  209.    .getBuffersWithFormat    = dri_get_buffers_with_format,
  210. };
  211.  
  212. static const __DRIimageLoaderExtension image_loader_extension = {
  213.    .base = { __DRI_IMAGE_LOADER, 1 },
  214.  
  215.    .getBuffers          = image_get_buffers,
  216.    .flushFrontBuffer    = dri_flush_front_buffer,
  217. };
  218.  
  219. static const __DRIswrastLoaderExtension swrast_loader_extension = {
  220.    .base = { __DRI_SWRAST_LOADER, 2 },
  221.  
  222.    .getDrawableInfo = swrast_get_drawable_info,
  223.    .putImage        = swrast_put_image,
  224.    .getImage        = swrast_get_image,
  225.    .putImage2       = swrast_put_image2
  226. };
  227.  
  228. static const __DRIextension *gbm_dri_screen_extensions[] = {
  229.    &image_lookup_extension.base,
  230.    &use_invalidate.base,
  231.    &dri2_loader_extension.base,
  232.    &image_loader_extension.base,
  233.    &swrast_loader_extension.base,
  234.    NULL,
  235. };
  236.  
  237. struct dri_extension_match {
  238.    const char *name;
  239.    int version;
  240.    int offset;
  241. };
  242.  
  243. static struct dri_extension_match dri_core_extensions[] = {
  244.    { __DRI2_FLUSH, 1, offsetof(struct gbm_dri_device, flush) },
  245.    { __DRI_IMAGE, 1, offsetof(struct gbm_dri_device, image) },
  246.    { NULL, 0, 0 }
  247. };
  248.  
  249. static struct dri_extension_match gbm_dri_device_extensions[] = {
  250.    { __DRI_CORE, 1, offsetof(struct gbm_dri_device, core) },
  251.    { __DRI_DRI2, 1, offsetof(struct gbm_dri_device, dri2) },
  252.    { NULL, 0, 0 }
  253. };
  254.  
  255. static struct dri_extension_match gbm_swrast_device_extensions[] = {
  256.    { __DRI_CORE, 1, offsetof(struct gbm_dri_device, core), },
  257.    { __DRI_SWRAST, 1, offsetof(struct gbm_dri_device, swrast) },
  258.    { NULL, 0, 0 }
  259. };
  260.  
  261. static int
  262. dri_bind_extensions(struct gbm_dri_device *dri,
  263.                     struct dri_extension_match *matches,
  264.                     const __DRIextension **extensions)
  265. {
  266.    int i, j, ret = 0;
  267.    void *field;
  268.  
  269.    for (i = 0; extensions[i]; i++) {
  270.       for (j = 0; matches[j].name; j++) {
  271.          if (strcmp(extensions[i]->name, matches[j].name) == 0 &&
  272.              extensions[i]->version >= matches[j].version) {
  273.             field = ((char *) dri + matches[j].offset);
  274.             *(const __DRIextension **) field = extensions[i];
  275.          }
  276.       }
  277.    }
  278.  
  279.    for (j = 0; matches[j].name; j++) {
  280.       field = ((char *) dri + matches[j].offset);
  281.       if (*(const __DRIextension **) field == NULL) {
  282.          ret = -1;
  283.       }
  284.    }
  285.  
  286.    return ret;
  287. }
  288.  
  289. static const __DRIextension **
  290. dri_open_driver(struct gbm_dri_device *dri)
  291. {
  292.    const __DRIextension **extensions = NULL;
  293.    char path[PATH_MAX], *search_paths, *p, *next, *end;
  294.    char *get_extensions_name;
  295.  
  296.    search_paths = NULL;
  297.    /* don't allow setuid apps to use LIBGL_DRIVERS_PATH or GBM_DRIVERS_PATH */
  298.    if (geteuid() == getuid()) {
  299.       /* Read GBM_DRIVERS_PATH first for compatibility, but LIBGL_DRIVERS_PATH
  300.        * is recommended over GBM_DRIVERS_PATH.
  301.        */
  302.       search_paths = getenv("GBM_DRIVERS_PATH");
  303.  
  304.       /* Read LIBGL_DRIVERS_PATH if GBM_DRIVERS_PATH was not set.
  305.        * LIBGL_DRIVERS_PATH is recommended over GBM_DRIVERS_PATH.
  306.        */
  307.       if (search_paths == NULL) {
  308.          search_paths = getenv("LIBGL_DRIVERS_PATH");
  309.       }
  310.    }
  311.    if (search_paths == NULL)
  312.       search_paths = DEFAULT_DRIVER_DIR;
  313.  
  314.    dri->driver = NULL;
  315.    end = search_paths + strlen(search_paths);
  316.    for (p = search_paths; p < end && dri->driver == NULL; p = next + 1) {
  317.       int len;
  318.       next = strchr(p, ':');
  319.       if (next == NULL)
  320.          next = end;
  321.  
  322.       len = next - p;
  323. #if GLX_USE_TLS
  324.       snprintf(path, sizeof path,
  325.                "%.*s/tls/%s_dri.so", len, p, dri->base.driver_name);
  326.       dri->driver = dlopen(path, RTLD_NOW | RTLD_GLOBAL);
  327. #endif
  328.       if (dri->driver == NULL) {
  329.          snprintf(path, sizeof path,
  330.                   "%.*s/%s_dri.so", len, p, dri->base.driver_name);
  331.          dri->driver = dlopen(path, RTLD_NOW | RTLD_GLOBAL);
  332.       }
  333.       /* not need continue to loop all paths once the driver is found */
  334.       if (dri->driver != NULL)
  335.          break;
  336.    }
  337.  
  338.    if (dri->driver == NULL) {
  339.       fprintf(stderr, "gbm: failed to open any driver (search paths %s)\n",
  340.               search_paths);
  341.       fprintf(stderr, "gbm: Last dlopen error: %s\n", dlerror());
  342.       return NULL;
  343.    }
  344.  
  345.    if (asprintf(&get_extensions_name, "%s_%s",
  346.                 __DRI_DRIVER_GET_EXTENSIONS, dri->base.driver_name) != -1) {
  347.       const __DRIextension **(*get_extensions)(void);
  348.  
  349.       get_extensions = dlsym(dri->driver, get_extensions_name);
  350.       free(get_extensions_name);
  351.  
  352.       if (get_extensions)
  353.          extensions = get_extensions();
  354.    }
  355.  
  356.    if (!extensions)
  357.       extensions = dlsym(dri->driver, __DRI_DRIVER_EXTENSIONS);
  358.    if (extensions == NULL) {
  359.       fprintf(stderr, "gbm: driver exports no extensions (%s)", dlerror());
  360.       dlclose(dri->driver);
  361.    }
  362.  
  363.    return extensions;
  364. }
  365.  
  366. static int
  367. dri_load_driver(struct gbm_dri_device *dri)
  368. {
  369.    const __DRIextension **extensions;
  370.  
  371.    extensions = dri_open_driver(dri);
  372.    if (!extensions)
  373.       return -1;
  374.  
  375.    if (dri_bind_extensions(dri, gbm_dri_device_extensions, extensions) < 0) {
  376.       dlclose(dri->driver);
  377.       fprintf(stderr, "failed to bind extensions\n");
  378.       return -1;
  379.    }
  380.  
  381.    dri->driver_extensions = extensions;
  382.  
  383.    return 0;
  384. }
  385.  
  386. static int
  387. dri_load_driver_swrast(struct gbm_dri_device *dri)
  388. {
  389.    const __DRIextension **extensions;
  390.  
  391.    extensions = dri_open_driver(dri);
  392.    if (!extensions)
  393.       return -1;
  394.  
  395.    if (dri_bind_extensions(dri, gbm_swrast_device_extensions, extensions) < 0) {
  396.       dlclose(dri->driver);
  397.       fprintf(stderr, "failed to bind extensions\n");
  398.       return -1;
  399.    }
  400.  
  401.    dri->driver_extensions = extensions;
  402.  
  403.    return 0;
  404. }
  405.  
  406. static int
  407. dri_screen_create_dri2(struct gbm_dri_device *dri, char *driver_name)
  408. {
  409.    const __DRIextension **extensions;
  410.    int ret = 0;
  411.  
  412.    dri->base.driver_name = driver_name;
  413.    if (dri->base.driver_name == NULL)
  414.       return -1;
  415.  
  416.    ret = dri_load_driver(dri);
  417.    if (ret) {
  418.       fprintf(stderr, "failed to load driver: %s\n", dri->base.driver_name);
  419.       return ret;
  420.    };
  421.  
  422.    dri->extensions = gbm_dri_screen_extensions;
  423.  
  424.    if (dri->dri2 == NULL)
  425.       return -1;
  426.  
  427.    if (dri->dri2->base.version >= 4) {
  428.       dri->screen = dri->dri2->createNewScreen2(0, dri->base.base.fd,
  429.                                                 dri->extensions,
  430.                                                 dri->driver_extensions,
  431.                                                 &dri->driver_configs, dri);
  432.    } else {
  433.       dri->screen = dri->dri2->createNewScreen(0, dri->base.base.fd,
  434.                                                dri->extensions,
  435.                                                &dri->driver_configs, dri);
  436.    }
  437.    if (dri->screen == NULL)
  438.       return -1;
  439.  
  440.    extensions = dri->core->getExtensions(dri->screen);
  441.    if (dri_bind_extensions(dri, dri_core_extensions, extensions) < 0) {
  442.       ret = -1;
  443.       goto free_screen;
  444.    }
  445.  
  446.    dri->lookup_image = NULL;
  447.    dri->lookup_user_data = NULL;
  448.  
  449.    return 0;
  450.  
  451. free_screen:
  452.    dri->core->destroyScreen(dri->screen);
  453.  
  454.    return ret;
  455. }
  456.  
  457. static int
  458. dri_screen_create_swrast(struct gbm_dri_device *dri)
  459. {
  460.    int ret;
  461.  
  462.    dri->base.driver_name = strdup("swrast");
  463.    if (dri->base.driver_name == NULL)
  464.       return -1;
  465.  
  466.    ret = dri_load_driver_swrast(dri);
  467.    if (ret) {
  468.       fprintf(stderr, "failed to load swrast driver\n");
  469.       return ret;
  470.    }
  471.  
  472.    dri->extensions = gbm_dri_screen_extensions;
  473.  
  474.    if (dri->swrast == NULL)
  475.       return -1;
  476.  
  477.    if (dri->swrast->base.version >= 4) {
  478.       dri->screen = dri->swrast->createNewScreen2(0, dri->extensions,
  479.                                                   dri->driver_extensions,
  480.                                                   &dri->driver_configs, dri);
  481.    } else {
  482.       dri->screen = dri->swrast->createNewScreen(0, dri->extensions,
  483.                                                  &dri->driver_configs, dri);
  484.    }
  485.    if (dri->screen == NULL)
  486.       return -1;
  487.  
  488.    dri->lookup_image = NULL;
  489.    dri->lookup_user_data = NULL;
  490.  
  491.    return 0;
  492. }
  493.  
  494. static int
  495. dri_screen_create(struct gbm_dri_device *dri)
  496. {
  497.    char *driver_name;
  498.  
  499.    driver_name = loader_get_driver_for_fd(dri->base.base.fd, 0);
  500.    if (!driver_name)
  501.       return -1;
  502.  
  503.    return dri_screen_create_dri2(dri, driver_name);
  504. }
  505.  
  506. static int
  507. dri_screen_create_sw(struct gbm_dri_device *dri)
  508. {
  509.    char *driver_name;
  510.    int ret;
  511.  
  512.    driver_name = strdup("kms_swrast");
  513.    if (!driver_name)
  514.       return -errno;
  515.  
  516.    ret = dri_screen_create_dri2(dri, driver_name);
  517.    if (ret == 0)
  518.       return ret;
  519.  
  520.    return dri_screen_create_swrast(dri);
  521. }
  522.  
  523. static int
  524. gbm_dri_is_format_supported(struct gbm_device *gbm,
  525.                             uint32_t format,
  526.                             uint32_t usage)
  527. {
  528.    switch (format) {
  529.    case GBM_BO_FORMAT_XRGB8888:
  530.    case GBM_FORMAT_XRGB8888:
  531.       break;
  532.    case GBM_BO_FORMAT_ARGB8888:
  533.    case GBM_FORMAT_ARGB8888:
  534.       if (usage & GBM_BO_USE_SCANOUT)
  535.          return 0;
  536.       break;
  537.    default:
  538.       return 0;
  539.    }
  540.  
  541.    if (usage & GBM_BO_USE_CURSOR &&
  542.        usage & GBM_BO_USE_RENDERING)
  543.       return 0;
  544.  
  545.    return 1;
  546. }
  547.  
  548. static int
  549. gbm_dri_bo_write(struct gbm_bo *_bo, const void *buf, size_t count)
  550. {
  551.    struct gbm_dri_bo *bo = gbm_dri_bo(_bo);
  552.  
  553.    if (bo->image != NULL) {
  554.       errno = EINVAL;
  555.       return -1;
  556.    }
  557.  
  558.    memcpy(bo->map, buf, count);
  559.  
  560.    return 0;
  561. }
  562.  
  563. static int
  564. gbm_dri_bo_get_fd(struct gbm_bo *_bo)
  565. {
  566.    struct gbm_dri_device *dri = gbm_dri_device(_bo->gbm);
  567.    struct gbm_dri_bo *bo = gbm_dri_bo(_bo);
  568.    int fd;
  569.  
  570.    if (bo->image == NULL)
  571.       return -1;
  572.  
  573.    dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_FD, &fd);
  574.  
  575.    return fd;
  576. }
  577.  
  578. static void
  579. gbm_dri_bo_destroy(struct gbm_bo *_bo)
  580. {
  581.    struct gbm_dri_device *dri = gbm_dri_device(_bo->gbm);
  582.    struct gbm_dri_bo *bo = gbm_dri_bo(_bo);
  583.    struct drm_mode_destroy_dumb arg;
  584.  
  585.    if (bo->image != NULL) {
  586.       dri->image->destroyImage(bo->image);
  587.    } else {
  588.       gbm_dri_bo_unmap(bo);
  589.       memset(&arg, 0, sizeof(arg));
  590.       arg.handle = bo->handle;
  591.       drmIoctl(dri->base.base.fd, DRM_IOCTL_MODE_DESTROY_DUMB, &arg);
  592.    }
  593.  
  594.    free(bo);
  595. }
  596.  
  597. static uint32_t
  598. gbm_dri_to_gbm_format(uint32_t dri_format)
  599. {
  600.    uint32_t ret = 0;
  601.  
  602.    switch (dri_format) {
  603.    case __DRI_IMAGE_FORMAT_RGB565:
  604.       ret = GBM_FORMAT_RGB565;
  605.       break;
  606.    case __DRI_IMAGE_FORMAT_XRGB8888:
  607.       ret = GBM_FORMAT_XRGB8888;
  608.       break;
  609.    case __DRI_IMAGE_FORMAT_ARGB8888:
  610.       ret = GBM_FORMAT_ARGB8888;
  611.       break;
  612.    case __DRI_IMAGE_FORMAT_ABGR8888:
  613.       ret = GBM_FORMAT_ABGR8888;
  614.       break;
  615.    default:
  616.       ret = 0;
  617.       break;
  618.    }
  619.  
  620.    return ret;
  621. }
  622.  
  623. static struct gbm_bo *
  624. gbm_dri_bo_import(struct gbm_device *gbm,
  625.                   uint32_t type, void *buffer, uint32_t usage)
  626. {
  627.    struct gbm_dri_device *dri = gbm_dri_device(gbm);
  628.    struct gbm_dri_bo *bo;
  629.    __DRIimage *image;
  630.    unsigned dri_use = 0;
  631.    int gbm_format;
  632.  
  633.    /* Required for query image WIDTH & HEIGHT */
  634.    if (dri->image == NULL || dri->image->base.version < 4) {
  635.       errno = ENOSYS;
  636.       return NULL;
  637.    }
  638.  
  639.    switch (type) {
  640. #if HAVE_WAYLAND_PLATFORM
  641.    case GBM_BO_IMPORT_WL_BUFFER:
  642.    {
  643.       struct wl_drm_buffer *wb;
  644.  
  645.       if (!dri->wl_drm) {
  646.          errno = EINVAL;
  647.          return NULL;
  648.       }
  649.  
  650.       wb = wayland_drm_buffer_get(dri->wl_drm, (struct wl_resource *) buffer);
  651.       if (!wb) {
  652.          errno = EINVAL;
  653.          return NULL;
  654.       }
  655.  
  656.       image = dri->image->dupImage(wb->driver_buffer, NULL);
  657.  
  658.       switch (wb->format) {
  659.       case WL_DRM_FORMAT_XRGB8888:
  660.          gbm_format = GBM_FORMAT_XRGB8888;
  661.          break;
  662.       case WL_DRM_FORMAT_ARGB8888:
  663.          gbm_format = GBM_FORMAT_ARGB8888;
  664.          break;
  665.       case WL_DRM_FORMAT_RGB565:
  666.          gbm_format = GBM_FORMAT_RGB565;
  667.          break;
  668.       case WL_DRM_FORMAT_YUYV:
  669.          gbm_format = GBM_FORMAT_YUYV;
  670.          break;
  671.       default:
  672.          return NULL;
  673.       }
  674.       break;
  675.    }
  676. #endif
  677.  
  678.    case GBM_BO_IMPORT_EGL_IMAGE:
  679.    {
  680.       int dri_format;
  681.       if (dri->lookup_image == NULL) {
  682.          errno = EINVAL;
  683.          return NULL;
  684.       }
  685.  
  686.       image = dri->lookup_image(dri->screen, buffer, dri->lookup_user_data);
  687.       image = dri->image->dupImage(image, NULL);
  688.       dri->image->queryImage(image, __DRI_IMAGE_ATTRIB_FORMAT, &dri_format);
  689.       gbm_format = gbm_dri_to_gbm_format(dri_format);
  690.       if (gbm_format == 0) {
  691.          errno = EINVAL;
  692.          return NULL;
  693.       }
  694.       break;
  695.    }
  696.  
  697.    case GBM_BO_IMPORT_FD:
  698.    {
  699.       struct gbm_import_fd_data *fd_data = buffer;
  700.       int stride = fd_data->stride, offset = 0;
  701.  
  702.       image = dri->image->createImageFromFds(dri->screen,
  703.                                              fd_data->width,
  704.                                              fd_data->height,
  705.                                              fd_data->format,
  706.                                              &fd_data->fd, 1,
  707.                                              &stride, &offset,
  708.                                              NULL);
  709.       gbm_format = fd_data->format;
  710.       break;
  711.    }
  712.  
  713.    default:
  714.       errno = ENOSYS;
  715.       return NULL;
  716.    }
  717.  
  718.  
  719.    bo = calloc(1, sizeof *bo);
  720.    if (bo == NULL)
  721.       return NULL;
  722.  
  723.    bo->image = image;
  724.  
  725.    if (usage & GBM_BO_USE_SCANOUT)
  726.       dri_use |= __DRI_IMAGE_USE_SCANOUT;
  727.    if (usage & GBM_BO_USE_CURSOR)
  728.       dri_use |= __DRI_IMAGE_USE_CURSOR;
  729.    if (dri->image->base.version >= 2 &&
  730.        !dri->image->validateUsage(bo->image, dri_use)) {
  731.       errno = EINVAL;
  732.       free(bo);
  733.       return NULL;
  734.    }
  735.  
  736.    bo->base.base.gbm = gbm;
  737.    bo->base.base.format = gbm_format;
  738.  
  739.    dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_WIDTH,
  740.                           (int*)&bo->base.base.width);
  741.    dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_HEIGHT,
  742.                           (int*)&bo->base.base.height);
  743.    dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_STRIDE,
  744.                           (int*)&bo->base.base.stride);
  745.    dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_HANDLE,
  746.                           &bo->base.base.handle.s32);
  747.  
  748.    return &bo->base.base;
  749. }
  750.  
  751. static struct gbm_bo *
  752. create_dumb(struct gbm_device *gbm,
  753.                   uint32_t width, uint32_t height,
  754.                   uint32_t format, uint32_t usage)
  755. {
  756.    struct gbm_dri_device *dri = gbm_dri_device(gbm);
  757.    struct drm_mode_create_dumb create_arg;
  758.    struct gbm_dri_bo *bo;
  759.    struct drm_mode_destroy_dumb destroy_arg;
  760.    int ret;
  761.    int is_cursor, is_scanout;
  762.  
  763.    is_cursor = (usage & GBM_BO_USE_CURSOR) != 0 &&
  764.       format == GBM_FORMAT_ARGB8888;
  765.    is_scanout = (usage & GBM_BO_USE_SCANOUT) != 0 &&
  766.       format == GBM_FORMAT_XRGB8888;
  767.    if (!is_cursor && !is_scanout) {
  768.       errno = EINVAL;
  769.       return NULL;
  770.    }
  771.  
  772.    bo = calloc(1, sizeof *bo);
  773.    if (bo == NULL)
  774.       return NULL;
  775.  
  776.    memset(&create_arg, 0, sizeof(create_arg));
  777.    create_arg.bpp = 32;
  778.    create_arg.width = width;
  779.    create_arg.height = height;
  780.  
  781.    ret = drmIoctl(dri->base.base.fd, DRM_IOCTL_MODE_CREATE_DUMB, &create_arg);
  782.    if (ret)
  783.       goto free_bo;
  784.  
  785.    bo->base.base.gbm = gbm;
  786.    bo->base.base.width = width;
  787.    bo->base.base.height = height;
  788.    bo->base.base.stride = create_arg.pitch;
  789.    bo->base.base.format = format;
  790.    bo->base.base.handle.u32 = create_arg.handle;
  791.    bo->handle = create_arg.handle;
  792.    bo->size = create_arg.size;
  793.  
  794.    if (gbm_dri_bo_map(bo) == NULL)
  795.       goto destroy_dumb;
  796.  
  797.    return &bo->base.base;
  798.  
  799. destroy_dumb:
  800.    memset(&destroy_arg, 0, sizeof destroy_arg);
  801.    destroy_arg.handle = create_arg.handle;
  802.    drmIoctl(dri->base.base.fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_arg);
  803. free_bo:
  804.    free(bo);
  805.  
  806.    return NULL;
  807. }
  808.  
  809. static struct gbm_bo *
  810. gbm_dri_bo_create(struct gbm_device *gbm,
  811.                   uint32_t width, uint32_t height,
  812.                   uint32_t format, uint32_t usage)
  813. {
  814.    struct gbm_dri_device *dri = gbm_dri_device(gbm);
  815.    struct gbm_dri_bo *bo;
  816.    int dri_format;
  817.    unsigned dri_use = 0;
  818.  
  819.    if (usage & GBM_BO_USE_WRITE || dri->image == NULL)
  820.       return create_dumb(gbm, width, height, format, usage);
  821.  
  822.    bo = calloc(1, sizeof *bo);
  823.    if (bo == NULL)
  824.       return NULL;
  825.  
  826.    bo->base.base.gbm = gbm;
  827.    bo->base.base.width = width;
  828.    bo->base.base.height = height;
  829.    bo->base.base.format = format;
  830.  
  831.    switch (format) {
  832.    case GBM_FORMAT_RGB565:
  833.       dri_format =__DRI_IMAGE_FORMAT_RGB565;
  834.       break;
  835.    case GBM_FORMAT_XRGB8888:
  836.    case GBM_BO_FORMAT_XRGB8888:
  837.       dri_format = __DRI_IMAGE_FORMAT_XRGB8888;
  838.       break;
  839.    case GBM_FORMAT_ARGB8888:
  840.    case GBM_BO_FORMAT_ARGB8888:
  841.       dri_format = __DRI_IMAGE_FORMAT_ARGB8888;
  842.       break;
  843.    case GBM_FORMAT_ABGR8888:
  844.       dri_format = __DRI_IMAGE_FORMAT_ABGR8888;
  845.       break;
  846.    case GBM_FORMAT_ARGB2101010:
  847.       dri_format = __DRI_IMAGE_FORMAT_ARGB2101010;
  848.       break;
  849.    case GBM_FORMAT_XRGB2101010:
  850.       dri_format = __DRI_IMAGE_FORMAT_XRGB2101010;
  851.       break;
  852.    default:
  853.       errno = EINVAL;
  854.       goto failed;
  855.    }
  856.  
  857.    if (usage & GBM_BO_USE_SCANOUT)
  858.       dri_use |= __DRI_IMAGE_USE_SCANOUT;
  859.    if (usage & GBM_BO_USE_CURSOR)
  860.       dri_use |= __DRI_IMAGE_USE_CURSOR;
  861.    if (usage & GBM_BO_USE_LINEAR)
  862.       dri_use |= __DRI_IMAGE_USE_LINEAR;
  863.  
  864.    /* Gallium drivers requires shared in order to get the handle/stride */
  865.    dri_use |= __DRI_IMAGE_USE_SHARE;
  866.  
  867.    bo->image =
  868.       dri->image->createImage(dri->screen,
  869.                               width, height,
  870.                               dri_format, dri_use,
  871.                               bo);
  872.    if (bo->image == NULL)
  873.       goto failed;
  874.  
  875.    dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_HANDLE,
  876.                           &bo->base.base.handle.s32);
  877.    dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_STRIDE,
  878.                           (int *) &bo->base.base.stride);
  879.  
  880.    return &bo->base.base;
  881.  
  882. failed:
  883.    free(bo);
  884.    return NULL;
  885. }
  886.  
  887. static struct gbm_surface *
  888. gbm_dri_surface_create(struct gbm_device *gbm,
  889.                        uint32_t width, uint32_t height,
  890.                        uint32_t format, uint32_t flags)
  891. {
  892.    struct gbm_dri_surface *surf;
  893.  
  894.    surf = calloc(1, sizeof *surf);
  895.    if (surf == NULL)
  896.       return NULL;
  897.  
  898.    surf->base.gbm = gbm;
  899.    surf->base.width = width;
  900.    surf->base.height = height;
  901.    surf->base.format = format;
  902.    surf->base.flags = flags;
  903.  
  904.    return &surf->base;
  905. }
  906.  
  907. static void
  908. gbm_dri_surface_destroy(struct gbm_surface *_surf)
  909. {
  910.    struct gbm_dri_surface *surf = gbm_dri_surface(_surf);
  911.  
  912.    free(surf);
  913. }
  914.  
  915. static void
  916. dri_destroy(struct gbm_device *gbm)
  917. {
  918.    struct gbm_dri_device *dri = gbm_dri_device(gbm);
  919.    unsigned i;
  920.  
  921.    dri->core->destroyScreen(dri->screen);
  922.    for (i = 0; dri->driver_configs[i]; i++)
  923.       free((__DRIconfig *) dri->driver_configs[i]);
  924.    free(dri->driver_configs);
  925.    dlclose(dri->driver);
  926.    free(dri->base.driver_name);
  927.  
  928.    free(dri);
  929. }
  930.  
  931. static struct gbm_device *
  932. dri_device_create(int fd)
  933. {
  934.    struct gbm_dri_device *dri;
  935.    int ret, force_sw;
  936.  
  937.    dri = calloc(1, sizeof *dri);
  938.    if (!dri)
  939.       return NULL;
  940.  
  941.    dri->base.base.fd = fd;
  942.    dri->base.base.bo_create = gbm_dri_bo_create;
  943.    dri->base.base.bo_import = gbm_dri_bo_import;
  944.    dri->base.base.is_format_supported = gbm_dri_is_format_supported;
  945.    dri->base.base.bo_write = gbm_dri_bo_write;
  946.    dri->base.base.bo_get_fd = gbm_dri_bo_get_fd;
  947.    dri->base.base.bo_destroy = gbm_dri_bo_destroy;
  948.    dri->base.base.destroy = dri_destroy;
  949.    dri->base.base.surface_create = gbm_dri_surface_create;
  950.    dri->base.base.surface_destroy = gbm_dri_surface_destroy;
  951.  
  952.    dri->base.type = GBM_DRM_DRIVER_TYPE_DRI;
  953.    dri->base.base.name = "drm";
  954.  
  955.    force_sw = getenv("GBM_ALWAYS_SOFTWARE") != NULL;
  956.    if (!force_sw) {
  957.       ret = dri_screen_create(dri);
  958.       if (ret)
  959.          ret = dri_screen_create_sw(dri);
  960.    } else {
  961.       ret = dri_screen_create_sw(dri);
  962.    }
  963.  
  964.    if (ret)
  965.       goto err_dri;
  966.  
  967.    return &dri->base.base;
  968.  
  969. err_dri:
  970.    free(dri);
  971.  
  972.    return NULL;
  973. }
  974.  
  975. struct gbm_backend gbm_dri_backend = {
  976.    .backend_name = "dri",
  977.    .create_device = dri_device_create,
  978. };
  979.