/* * Copyright © 2011 Intel Corporation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * * Authors: * Benjamin Franzke <benjaminfranzke@googlemail.com> */ #include "util/u_memory.h" #include "util/u_inlines.h" #include "state_tracker/drm_driver.h" #include <unistd.h> #include <sys/types.h> #include "gbm_gallium_drmint.h" /* For importing wl_buffer */ #if HAVE_WAYLAND_PLATFORM #include "../../../egl/wayland/wayland-drm/wayland-drm.h" #endif static INLINE enum pipe_format gbm_format_to_gallium(enum gbm_bo_format format) { switch (format) { case GBM_BO_FORMAT_XRGB8888: return PIPE_FORMAT_B8G8R8X8_UNORM; case GBM_BO_FORMAT_ARGB8888: return PIPE_FORMAT_B8G8R8A8_UNORM; default: return PIPE_FORMAT_NONE; } return PIPE_FORMAT_NONE; } static INLINE uint gbm_usage_to_gallium(uint usage) { uint resource_usage = 0; if (usage & GBM_BO_USE_SCANOUT) resource_usage |= PIPE_BIND_SCANOUT; if (usage & GBM_BO_USE_RENDERING) resource_usage |= PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; if (usage & GBM_BO_USE_CURSOR_64X64) resource_usage |= PIPE_BIND_CURSOR; return resource_usage; } static int gbm_gallium_drm_is_format_supported(struct gbm_device *gbm, enum gbm_bo_format format, uint32_t usage) { struct gbm_gallium_drm_device *gdrm = gbm_gallium_drm_device(gbm); enum pipe_format pf; pf = gbm_format_to_gallium(format); if (pf == PIPE_FORMAT_NONE) return 0; if (!gdrm->screen->is_format_supported(gdrm->screen, PIPE_TEXTURE_2D, pf, 0, gbm_usage_to_gallium(usage))) return 0; if (usage & GBM_BO_USE_SCANOUT && format != GBM_BO_FORMAT_XRGB8888) return 0; return 1; } static void gbm_gallium_drm_bo_destroy(struct gbm_bo *_bo) { struct gbm_gallium_drm_bo *bo = gbm_gallium_drm_bo(_bo); pipe_resource_reference(&bo->resource, NULL); free(bo); } static struct gbm_bo * gbm_gallium_drm_bo_import(struct gbm_device *gbm, uint32_t type, void *buffer, uint32_t usage) { struct gbm_gallium_drm_device *gdrm = gbm_gallium_drm_device(gbm); struct gbm_gallium_drm_bo *bo; struct winsys_handle whandle; struct pipe_resource *resource; switch (type) { #if HAVE_WAYLAND_PLATFORM case GBM_BO_IMPORT_WL_BUFFER: { struct wl_drm_buffer *wb = (struct wl_drm_buffer *) buffer; resource = wb->driver_buffer; break; } #endif case GBM_BO_IMPORT_EGL_IMAGE: if (!gdrm->lookup_egl_image) return NULL; resource = gdrm->lookup_egl_image(gdrm->lookup_egl_image_data, buffer); if (resource == NULL) return NULL; break; default: return NULL; } bo = CALLOC_STRUCT(gbm_gallium_drm_bo); if (bo == NULL) return NULL; bo->base.base.gbm = gbm; bo->base.base.width = resource->width0; bo->base.base.height = resource->height0; switch (resource->format) { case PIPE_FORMAT_B8G8R8X8_UNORM: bo->base.base.format = GBM_BO_FORMAT_XRGB8888; break; case PIPE_FORMAT_B8G8R8A8_UNORM: bo->base.base.format = GBM_BO_FORMAT_ARGB8888; break; default: FREE(bo); return NULL; } pipe_resource_reference(&bo->resource, resource); memset(&whandle, 0, sizeof(whandle)); whandle.type = DRM_API_HANDLE_TYPE_KMS; gdrm->screen->resource_get_handle(gdrm->screen, bo->resource, &whandle); bo->base.base.handle.u32 = whandle.handle; bo->base.base.stride = whandle.stride; return &bo->base.base; } static struct gbm_bo * gbm_gallium_drm_bo_create(struct gbm_device *gbm, uint32_t width, uint32_t height, enum gbm_bo_format format, uint32_t usage) { struct gbm_gallium_drm_device *gdrm = gbm_gallium_drm_device(gbm); struct gbm_gallium_drm_bo *bo; struct pipe_resource templ; struct winsys_handle whandle; enum pipe_format pf; bo = CALLOC_STRUCT(gbm_gallium_drm_bo); if (bo == NULL) return NULL; bo->base.base.gbm = gbm; bo->base.base.width = width; bo->base.base.height = height; bo->base.base.format = format; pf = gbm_format_to_gallium(format); if (pf == PIPE_FORMAT_NONE) return NULL; memset(&templ, 0, sizeof(templ)); templ.bind = gbm_usage_to_gallium(usage); templ.format = pf; templ.target = PIPE_TEXTURE_2D; templ.last_level = 0; templ.width0 = width; templ.height0 = height; templ.depth0 = 1; templ.array_size = 1; bo->resource = gdrm->screen->resource_create(gdrm->screen, &templ); if (bo->resource == NULL) { FREE(bo); return NULL; } memset(&whandle, 0, sizeof(whandle)); whandle.type = DRM_API_HANDLE_TYPE_KMS; gdrm->screen->resource_get_handle(gdrm->screen, bo->resource, &whandle); bo->base.base.handle.u32 = whandle.handle; bo->base.base.stride = whandle.stride; return &bo->base.base; } static void gbm_gallium_drm_destroy(struct gbm_device *gbm) { struct gbm_gallium_drm_device *gdrm = gbm_gallium_drm_device(gbm); gallium_screen_destroy(gdrm); FREE(gdrm); } struct gbm_device * gbm_gallium_drm_device_create(int fd) { struct gbm_gallium_drm_device *gdrm; int ret; gdrm = calloc(1, sizeof *gdrm); gdrm->base.base.fd = fd; gdrm->base.base.bo_create = gbm_gallium_drm_bo_create; gdrm->base.base.bo_import = gbm_gallium_drm_bo_import; gdrm->base.base.bo_destroy = gbm_gallium_drm_bo_destroy; gdrm->base.base.is_format_supported = gbm_gallium_drm_is_format_supported; gdrm->base.base.destroy = gbm_gallium_drm_destroy; gdrm->base.type = GBM_DRM_DRIVER_TYPE_GALLIUM; gdrm->base.base.name = "drm"; ret = gallium_screen_create(gdrm); if (ret) { free(gdrm); return NULL; } return &gdrm->base.base; }