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