Home | History | Annotate | Download | only in gbm
      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 "util/u_memory.h"
     29 #include "util/u_inlines.h"
     30 
     31 #include "state_tracker/drm_driver.h"
     32 
     33 #include <unistd.h>
     34 #include <sys/types.h>
     35 
     36 #include "gbm_gallium_drmint.h"
     37 
     38 /* For importing wl_buffer */
     39 #if HAVE_WAYLAND_PLATFORM
     40 #include "../../../egl/wayland/wayland-drm/wayland-drm.h"
     41 #endif
     42 
     43 static INLINE enum pipe_format
     44 gbm_format_to_gallium(enum gbm_bo_format format)
     45 {
     46    switch (format) {
     47    case GBM_BO_FORMAT_XRGB8888:
     48       return PIPE_FORMAT_B8G8R8X8_UNORM;
     49    case GBM_BO_FORMAT_ARGB8888:
     50       return PIPE_FORMAT_B8G8R8A8_UNORM;
     51    default:
     52       return PIPE_FORMAT_NONE;
     53    }
     54 
     55    return PIPE_FORMAT_NONE;
     56 }
     57 
     58 static INLINE uint
     59 gbm_usage_to_gallium(uint usage)
     60 {
     61    uint resource_usage = 0;
     62 
     63    if (usage & GBM_BO_USE_SCANOUT)
     64       resource_usage |= PIPE_BIND_SCANOUT;
     65 
     66    if (usage & GBM_BO_USE_RENDERING)
     67       resource_usage |= PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
     68 
     69    if (usage & GBM_BO_USE_CURSOR_64X64)
     70       resource_usage |= PIPE_BIND_CURSOR;
     71 
     72    return resource_usage;
     73 }
     74 
     75 static int
     76 gbm_gallium_drm_is_format_supported(struct gbm_device *gbm,
     77                                     enum gbm_bo_format format,
     78                                     uint32_t usage)
     79 {
     80    struct gbm_gallium_drm_device *gdrm = gbm_gallium_drm_device(gbm);
     81    enum pipe_format pf;
     82 
     83    pf = gbm_format_to_gallium(format);
     84    if (pf == PIPE_FORMAT_NONE)
     85       return 0;
     86 
     87    if (!gdrm->screen->is_format_supported(gdrm->screen, PIPE_TEXTURE_2D, pf, 0,
     88                                           gbm_usage_to_gallium(usage)))
     89       return 0;
     90 
     91    if (usage & GBM_BO_USE_SCANOUT && format != GBM_BO_FORMAT_XRGB8888)
     92       return 0;
     93 
     94    return 1;
     95 }
     96 
     97 static void
     98 gbm_gallium_drm_bo_destroy(struct gbm_bo *_bo)
     99 {
    100    struct gbm_gallium_drm_bo *bo = gbm_gallium_drm_bo(_bo);
    101 
    102    pipe_resource_reference(&bo->resource, NULL);
    103    free(bo);
    104 }
    105 
    106 static struct gbm_bo *
    107 gbm_gallium_drm_bo_import(struct gbm_device *gbm,
    108                           uint32_t type, void *buffer, uint32_t usage)
    109 {
    110    struct gbm_gallium_drm_device *gdrm = gbm_gallium_drm_device(gbm);
    111    struct gbm_gallium_drm_bo *bo;
    112    struct winsys_handle whandle;
    113    struct pipe_resource *resource;
    114 
    115    switch (type) {
    116 #if HAVE_WAYLAND_PLATFORM
    117    case GBM_BO_IMPORT_WL_BUFFER:
    118    {
    119       struct wl_drm_buffer *wb = (struct wl_drm_buffer *) buffer;
    120 
    121       resource = wb->driver_buffer;
    122       break;
    123    }
    124 #endif
    125 
    126    case GBM_BO_IMPORT_EGL_IMAGE:
    127       if (!gdrm->lookup_egl_image)
    128          return NULL;
    129 
    130       resource = gdrm->lookup_egl_image(gdrm->lookup_egl_image_data, buffer);
    131       if (resource == NULL)
    132          return NULL;
    133       break;
    134 
    135    default:
    136       return NULL;
    137    }
    138 
    139    bo = CALLOC_STRUCT(gbm_gallium_drm_bo);
    140    if (bo == NULL)
    141       return NULL;
    142 
    143    bo->base.base.gbm = gbm;
    144    bo->base.base.width = resource->width0;
    145    bo->base.base.height = resource->height0;
    146 
    147    switch (resource->format) {
    148    case PIPE_FORMAT_B8G8R8X8_UNORM:
    149       bo->base.base.format = GBM_BO_FORMAT_XRGB8888;
    150       break;
    151    case PIPE_FORMAT_B8G8R8A8_UNORM:
    152       bo->base.base.format = GBM_BO_FORMAT_ARGB8888;
    153       break;
    154    default:
    155       FREE(bo);
    156       return NULL;
    157    }
    158 
    159    pipe_resource_reference(&bo->resource, resource);
    160 
    161    memset(&whandle, 0, sizeof(whandle));
    162    whandle.type = DRM_API_HANDLE_TYPE_KMS;
    163    gdrm->screen->resource_get_handle(gdrm->screen, bo->resource, &whandle);
    164 
    165    bo->base.base.handle.u32 = whandle.handle;
    166    bo->base.base.stride      = whandle.stride;
    167 
    168    return &bo->base.base;
    169 }
    170 
    171 static struct gbm_bo *
    172 gbm_gallium_drm_bo_create(struct gbm_device *gbm,
    173                           uint32_t width, uint32_t height,
    174                           enum gbm_bo_format format, uint32_t usage)
    175 {
    176    struct gbm_gallium_drm_device *gdrm = gbm_gallium_drm_device(gbm);
    177    struct gbm_gallium_drm_bo *bo;
    178    struct pipe_resource templ;
    179    struct winsys_handle whandle;
    180    enum pipe_format pf;
    181 
    182    bo = CALLOC_STRUCT(gbm_gallium_drm_bo);
    183    if (bo == NULL)
    184       return NULL;
    185 
    186    bo->base.base.gbm = gbm;
    187    bo->base.base.width = width;
    188    bo->base.base.height = height;
    189    bo->base.base.format = format;
    190 
    191    pf = gbm_format_to_gallium(format);
    192    if (pf == PIPE_FORMAT_NONE)
    193       return NULL;
    194 
    195    memset(&templ, 0, sizeof(templ));
    196    templ.bind = gbm_usage_to_gallium(usage);
    197    templ.format = pf;
    198    templ.target = PIPE_TEXTURE_2D;
    199    templ.last_level = 0;
    200    templ.width0 = width;
    201    templ.height0 = height;
    202    templ.depth0 = 1;
    203    templ.array_size = 1;
    204 
    205    bo->resource = gdrm->screen->resource_create(gdrm->screen, &templ);
    206    if (bo->resource == NULL) {
    207       FREE(bo);
    208       return NULL;
    209    }
    210 
    211    memset(&whandle, 0, sizeof(whandle));
    212    whandle.type = DRM_API_HANDLE_TYPE_KMS;
    213    gdrm->screen->resource_get_handle(gdrm->screen, bo->resource, &whandle);
    214 
    215    bo->base.base.handle.u32 = whandle.handle;
    216    bo->base.base.stride      = whandle.stride;
    217 
    218    return &bo->base.base;
    219 }
    220 
    221 static void
    222 gbm_gallium_drm_destroy(struct gbm_device *gbm)
    223 {
    224    struct gbm_gallium_drm_device *gdrm = gbm_gallium_drm_device(gbm);
    225 
    226    gallium_screen_destroy(gdrm);
    227    FREE(gdrm);
    228 }
    229 
    230 struct gbm_device *
    231 gbm_gallium_drm_device_create(int fd)
    232 {
    233    struct gbm_gallium_drm_device *gdrm;
    234    int ret;
    235 
    236    gdrm = calloc(1, sizeof *gdrm);
    237 
    238    gdrm->base.base.fd = fd;
    239    gdrm->base.base.bo_create = gbm_gallium_drm_bo_create;
    240    gdrm->base.base.bo_import = gbm_gallium_drm_bo_import;
    241    gdrm->base.base.bo_destroy = gbm_gallium_drm_bo_destroy;
    242    gdrm->base.base.is_format_supported = gbm_gallium_drm_is_format_supported;
    243    gdrm->base.base.destroy = gbm_gallium_drm_destroy;
    244 
    245    gdrm->base.type = GBM_DRM_DRIVER_TYPE_GALLIUM;
    246    gdrm->base.base.name = "drm";
    247 
    248    ret = gallium_screen_create(gdrm);
    249    if (ret) {
    250       free(gdrm);
    251       return NULL;
    252    }
    253 
    254    return &gdrm->base.base;
    255 }
    256