From 232cfb3c551ceec97f9de8e3839b9953f67c0419 Mon Sep 17 00:00:00 2001 From: Nicolai Hähnle Date: Thu, 30 Nov 2017 19:10:28 +0100 Subject: Proof of concept: amdgpu backend based on dri_interface --- Makefile | 2 +- amdgpu.c | 376 +++------------------------------------------------------------ dri.c | 319 +++++++++++++++++++++++++++++++++++++++++++++++++++++ dri.h | 44 ++++++++ 4 files changed, 381 insertions(+), 360 deletions(-) create mode 100644 dri.c create mode 100644 dri.h diff --git a/Makefile b/Makefile index 9050e20..a58f63b 100644 --- a/Makefile +++ b/Makefile @@ -13,7 +13,7 @@ CFLAGS += -std=c99 -Wall -Wsign-compare -Wpointer-arith -Wcast-qual \ -Wcast-align -D_GNU_SOURCE=1 -D_FILE_OFFSET_BITS=64 ifdef DRV_AMDGPU - CFLAGS += $(shell $(PKG_CONFIG) --cflags libdrm_amdgpu) + CFLAGS += $(shell $(PKG_CONFIG) --cflags libdrm_amdgpu) -DDRV_AMDGPU LDLIBS += -ldrm_amdgpu -ldl endif ifdef DRV_EXYNOS diff --git a/amdgpu.c b/amdgpu.c index 35a900d..dfcad22 100644 --- a/amdgpu.c +++ b/amdgpu.c @@ -17,56 +17,11 @@ #include "drv_priv.h" #include "helpers.h" #include "util.h" -#include "ac_surface.h" -#include "ac_gpu_info.h" +#include "dri.h" // clang-format off #define DRI_PATH "/usr/lib64/dri/radeonsi_dri.so" -typedef void* (*addr_create)(const struct radeon_info*, - const struct amdgpu_gpu_info*, - uint64_t*); - -typedef int (*addr_destroy)(void*); - -typedef int (*compute_surface)(void*, - const struct radeon_info*, - const struct ac_surf_config*, - enum radeon_surf_mode, - struct radeon_surf*); - -typedef bool (*query_gpu_info)(int, amdgpu_device_handle, - struct radeon_info*, struct amdgpu_gpu_info*); - -typedef int (*read_write_tiled)(void*, struct ac_surf_config*, - struct radeon_surf*, void*, - uint8_t*, int); - -struct dri_functors { - void *handle; - addr_create fptr_create; - addr_destroy fptr_destroy; - compute_surface fptr_compute_surface; - query_gpu_info fptr_query_gpu_info; - read_write_tiled fptr_read_write_tiled; -}; - -struct drv_priv_ptr { - struct dri_functors *dri_handle; - void *addrlib_handle; - enum radeon_surf_mode surf_mode; - struct radeon_info info; - struct ac_surf_config surf_config; - struct radeon_surf *surf_info; - uint64_t base_align; -}; - -struct bo_priv_ptr { - void *untiled_buf_ptr; - uint32_t ref_count; - int prot; -}; - // clang-format on const static uint32_t render_target_formats[] = { DRM_FORMAT_ABGR8888, DRM_FORMAT_ARGB8888, DRM_FORMAT_RGB565, DRM_FORMAT_XBGR8888, @@ -75,142 +30,15 @@ const static uint32_t render_target_formats[] = { DRM_FORMAT_ABGR8888, DRM_FORMA const static uint32_t texture_source_formats[] = { DRM_FORMAT_GR88, DRM_FORMAT_R8, DRM_FORMAT_NV21, DRM_FORMAT_NV12 }; -static int amdgpu_set_metadata(int fd, uint32_t handle, struct amdgpu_bo_metadata *info) -{ - struct drm_amdgpu_gem_metadata args = { 0 }; - - if (!info) - return -EINVAL; - - args.handle = handle; - args.op = AMDGPU_GEM_METADATA_OP_SET_METADATA; - args.data.flags = info->flags; - args.data.tiling_info = info->tiling_info; - - if (info->size_metadata > sizeof(args.data.data)) - return -EINVAL; - - if (info->size_metadata) { - args.data.data_size_bytes = info->size_metadata; - memcpy(args.data.data, info->umd_metadata, info->size_metadata); - } - - return drmCommandWriteRead(fd, DRM_AMDGPU_GEM_METADATA, &args, sizeof(args)); -} - -static int amdgpu_addrlib_compute(struct drv_priv_ptr *drv_priv, uint32_t width, uint32_t height, - uint32_t format, uint64_t use_flags, uint32_t *tiling_flags) -{ - struct radeon_surf *surf_info = drv_priv->surf_info; - memset(surf_info, 0, sizeof(struct radeon_surf)); - struct ac_surf_config surf_config; - - drv_priv->surf_mode = RADEON_SURF_MODE_2D; - - surf_config.info.width = width; - surf_config.info.height = height; - surf_config.info.depth = 1; - surf_config.info.samples = 1; - surf_config.info.levels = 1; - surf_config.info.array_size = 1; - surf_config.is_3d = 0; - surf_config.is_cube = 0; - - surf_info->bpe = drv_stride_from_format(format, 1, 0); - - if (use_flags & - (BO_USE_CURSOR | BO_USE_LINEAR | BO_USE_SW_READ_OFTEN | BO_USE_SW_WRITE_OFTEN)) { - drv_priv->surf_mode = RADEON_SURF_MODE_LINEAR_ALIGNED; - } else if (width <= 16 || height <= 16) { - drv_priv->surf_mode = RADEON_SURF_MODE_1D; - } - - if (use_flags & BO_USE_SCANOUT) - surf_info->flags |= RADEON_SURF_SCANOUT; - - drv_priv->dri_handle->fptr_compute_surface(drv_priv->addrlib_handle, &drv_priv->info, - &surf_config, drv_priv->surf_mode, surf_info); - drv_priv->surf_mode = surf_info->u.legacy.level[0].mode; - - drv_priv->surf_config = surf_config; - *tiling_flags |= AMDGPU_TILING_SET(ARRAY_MODE, 1 << (drv_priv->surf_mode - 1)); - *tiling_flags |= AMDGPU_TILING_SET(MICRO_TILE_MODE, surf_info->micro_tile_mode); - - *tiling_flags |= AMDGPU_TILING_SET(BANK_WIDTH, drv_log_base2(surf_info->u.legacy.bankw)); - *tiling_flags |= AMDGPU_TILING_SET(BANK_HEIGHT, drv_log_base2(surf_info->u.legacy.bankh)); - *tiling_flags |= AMDGPU_TILING_SET(TILE_SPLIT, drv_log_base2(surf_info->u.legacy.tile_split >> 6)); - *tiling_flags |= AMDGPU_TILING_SET(MACRO_TILE_ASPECT, drv_log_base2(surf_info->u.legacy.mtilea)); - *tiling_flags |= AMDGPU_TILING_SET(PIPE_CONFIG, surf_info->u.legacy.pipe_config); - *tiling_flags |= AMDGPU_TILING_SET(NUM_BANKS, drv_log_base2(surf_info->u.legacy.num_banks >> 1)); - - return 0; -} - -static void *amdgpu_addrlib_init(int fd, struct dri_functors* dri_handle, struct radeon_info* info, uint64_t *base_align) -{ - int ret; - struct amdgpu_gpu_info gpu_info = { 0 }; - amdgpu_device_handle dev; - uint32_t drm_major, drm_minor; - void *addr_handle = NULL; - - ret = amdgpu_device_initialize(fd, &drm_major, &drm_minor, &dev); - if (ret) { - return NULL; - } - if (!dri_handle->fptr_query_gpu_info(fd, dev, info, &gpu_info)) { - return NULL; - } - - amdgpu_device_deinitialize(dev); - addr_handle = dri_handle->fptr_create(info, &gpu_info, base_align); - return addr_handle; -} - static int amdgpu_init(struct driver *drv) { - void *addrlib; - struct format_metadata metadata; - uint64_t use_flags = BO_USE_RENDER_MASK; - struct drv_priv_ptr* drv_priv = (struct drv_priv_ptr*) malloc (sizeof(struct drv_priv_ptr)); - drv_priv->surf_info = (struct radeon_surf*) malloc (sizeof(struct radeon_surf)); - drv_priv->dri_handle = (struct dri_functors*) malloc (sizeof(struct dri_functors)); - drv_priv->dri_handle->handle = dlopen(DRI_PATH, RTLD_NOW | RTLD_GLOBAL | RTLD_NODELETE); - if (!drv_priv->dri_handle->handle) - return -1; - - drv_priv->dri_handle->fptr_create = - (addr_create)dlsym(drv_priv->dri_handle->handle, "amdgpu_addr_create"); - if (!drv_priv->dri_handle->fptr_create) - return -1; - - drv_priv->dri_handle->fptr_destroy = - (addr_destroy)dlsym(drv_priv->dri_handle->handle, "amdgpu_addr_destroy"); - if (!drv_priv->dri_handle->fptr_destroy) - return -1; + drv->priv = malloc(sizeof(struct dri_driver_priv)); - drv_priv->dri_handle->fptr_compute_surface = - (compute_surface)dlsym(drv_priv->dri_handle->handle, "ac_compute_surface"); - if (!drv_priv->dri_handle->fptr_compute_surface) + if (dri_init(drv, DRI_PATH, "radeonsi") < 0) return -1; - drv_priv->dri_handle->fptr_query_gpu_info = - (query_gpu_info)dlsym(drv_priv->dri_handle->handle, "ac_query_gpu_info"); - if (!drv_priv->dri_handle->fptr_query_gpu_info) - return -1; - - drv_priv->dri_handle->fptr_read_write_tiled = - (read_write_tiled)dlsym(drv_priv->dri_handle->handle, "ac_read_write_tiled_data"); - if (!drv_priv->dri_handle->fptr_read_write_tiled) { - return -1; - } - - addrlib = amdgpu_addrlib_init(drv_get_fd(drv), drv_priv->dri_handle, &drv_priv->info, &drv_priv->base_align); - if (!addrlib) - return -1; - - drv_priv->addrlib_handle = addrlib; - drv->priv = drv_priv; + struct format_metadata metadata; + uint64_t use_flags = BO_USE_RENDER_MASK; drv_add_combinations(drv, texture_source_formats, ARRAY_SIZE(texture_source_formats), &LINEAR_METADATA, BO_USE_TEXTURE_MASK); @@ -228,7 +56,7 @@ static int amdgpu_init(struct driver *drv) drv_modify_combination(drv, DRM_FORMAT_NV21, &LINEAR_METADATA, BO_USE_SCANOUT); drv_modify_combination(drv, DRM_FORMAT_NV12, &LINEAR_METADATA, BO_USE_SCANOUT); - metadata.tiling = RADEON_MICRO_MODE_DISPLAY << 16 | RADEON_SURF_MODE_LINEAR_ALIGNED; + metadata.tiling = 0xf00f; /* TODO */ metadata.priority = 2; metadata.modifier = DRM_FORMAT_MOD_LINEAR; @@ -239,7 +67,7 @@ static int amdgpu_init(struct driver *drv) drv_modify_combination(drv, DRM_FORMAT_XRGB8888, &metadata, BO_USE_CURSOR | BO_USE_SCANOUT); drv_modify_combination(drv, DRM_FORMAT_XBGR8888, &metadata, BO_USE_SCANOUT); - metadata.tiling = RADEON_MICRO_MODE_THIN << 16 | RADEON_SURF_MODE_LINEAR_ALIGNED; + metadata.tiling = 0xf00f; /* TODO */ metadata.priority = 3; metadata.modifier = DRM_FORMAT_MOD_LINEAR; @@ -250,7 +78,7 @@ static int amdgpu_init(struct driver *drv) use_flags &= ~BO_USE_SW_READ_OFTEN; use_flags &= ~BO_USE_LINEAR; - metadata.tiling = RADEON_MICRO_MODE_DISPLAY << 16 | RADEON_SURF_MODE_2D; + metadata.tiling = 0xf00f; /* TODO */ metadata.priority = 4; drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats), @@ -260,7 +88,7 @@ static int amdgpu_init(struct driver *drv) drv_modify_combination(drv, DRM_FORMAT_XRGB8888, &metadata, BO_USE_SCANOUT); drv_modify_combination(drv, DRM_FORMAT_XBGR8888, &metadata, BO_USE_SCANOUT); - metadata.tiling = RADEON_MICRO_MODE_THIN << 16 | RADEON_SURF_MODE_2D; + metadata.tiling = 0xf00f; /* TODO */ metadata.priority = 5; drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats), @@ -271,182 +99,12 @@ static int amdgpu_init(struct driver *drv) static void amdgpu_close(struct driver *drv) { - struct drv_priv_ptr* drv_priv = (struct drv_priv_ptr*)drv->priv; - drv_priv->dri_handle->fptr_destroy(drv_priv->addrlib_handle); - drv_priv->addrlib_handle = NULL; - free(drv_priv->surf_info); - drv_priv->surf_info = NULL; - dlclose(drv_priv->dri_handle->handle); - free(drv_priv->dri_handle); - drv_priv->dri_handle = NULL; - drv->priv = NULL; -} - -static int amdgpu_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format, - uint64_t use_flags) -{ - struct drv_priv_ptr *drv_priv = (struct drv_priv_ptr*)bo->drv->priv; - struct bo_priv_ptr *bo_priv = (struct bo_priv_ptr*)bo->priv; - union drm_amdgpu_gem_create gem_create; - struct amdgpu_bo_metadata metadata = { 0 }; - uint32_t tiling_flags = 0; - size_t plane; - int ret; - struct driver* tmp_drv = bo->drv; - - if (bo->priv == NULL) { - bo_priv = (struct bo_priv_ptr*) malloc (sizeof(struct bo_priv_ptr)); - bo_priv->ref_count = 0; - bo_priv->untiled_buf_ptr = NULL; - bo->priv = bo_priv; - } else { - bo_priv = (struct bo_priv_ptr*)bo->priv; - } - - if (format == DRM_FORMAT_NV12 || format == DRM_FORMAT_NV21) { - drv_bo_from_format(bo, ALIGN(width, 64), height, format); - } else { - if (amdgpu_addrlib_compute(drv_priv, width, height, format, use_flags, - &tiling_flags) < 0) { - return -EINVAL; - } - bo->tiling = tiling_flags; - /* RGB has 1 plane only */ - bo->offsets[0] = drv_priv->surf_info->u.legacy.level[0].offset; - bo->total_size = bo->sizes[0] = drv_priv->surf_info->surf_size; - - bo->strides[0] = drv_stride_from_format(format, - drv_priv->surf_info->u.legacy.level[0].nblk_x,0); - } + dri_close(drv); - //FIXME:drv pointer gets changed after amdgpu_addrlib_compute call - //store it in temp pointer - bo->drv = tmp_drv; - - memset(&gem_create, 0, sizeof(gem_create)); - - gem_create.in.bo_size = bo->total_size; - gem_create.in.alignment = drv_priv->surf_info->surf_alignment; - - /* Set the placement. */ - gem_create.in.domains = AMDGPU_GEM_DOMAIN_VRAM; - gem_create.in.domain_flags = AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED; - /* Allocate the buffer with the preferred heap. */ - - ret = drmCommandWriteRead(drv_get_fd(bo->drv), DRM_AMDGPU_GEM_CREATE, &gem_create, - sizeof(gem_create)); - - if (ret < 0) { - fprintf(stderr, "drmCommandWriteRead failed with %d\n", ret); - return ret; - } - - metadata.tiling_info = tiling_flags; - - for (plane = 0; plane < bo->num_planes; plane++) - bo->handles[plane].u32 = gem_create.out.handle; - - ret = amdgpu_set_metadata(drv_get_fd(bo->drv), bo->handles[0].u32, &metadata); - - return ret; -} - -static int amdgpu_gbm_bo_import(struct bo *bo, struct drv_import_fd_data *data) -{ - struct drv_priv_ptr *drv_priv = (struct drv_priv_ptr*)bo->drv->priv; - struct bo_priv_ptr *bo_priv = NULL; - uint32_t width = data->width; - uint32_t height = data->height; - uint32_t format = data->format; - uint32_t usage = data->use_flags; - uint32_t tiling_flags = 0; - - if (bo->priv == NULL) { - bo_priv = (struct bo_priv_ptr*) malloc (sizeof(struct bo_priv_ptr)); - bo_priv->ref_count = 0; - bo->priv = bo_priv; - } else { - bo_priv = (struct bo_priv_ptr*)bo->priv; - } - - if (format == DRM_FORMAT_NV12 || format == DRM_FORMAT_NV21) { - drv_bo_from_format(bo, ALIGN(width, 64), height, format); - } else { - if (amdgpu_addrlib_compute(drv_priv, width, height, format, usage, - &tiling_flags) < 0) { - return -EINVAL; - } - } - return drv_prime_bo_import(bo, data); -} - -static void *amdgpu_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint32_t map_flags) -{ - int ret; - union drm_amdgpu_gem_mmap gem_map; - void *addr = NULL; - int prot = drv_get_prot(map_flags); - struct bo_priv_ptr *bo_priv = (struct bo_priv_ptr*)bo->priv; - struct drv_priv_ptr *drv_priv = (struct drv_priv_ptr*)bo->drv->priv; - - memset(&gem_map, 0, sizeof(gem_map)); - gem_map.in.handle = bo->handles[plane].u32; - - ret = drmIoctl(bo->drv->fd, DRM_IOCTL_AMDGPU_GEM_MMAP, &gem_map); - if (ret) { - fprintf(stderr, "drv: DRM_IOCTL_AMDGPU_GEM_MMAP failed\n"); - return MAP_FAILED; - } - - vma->length = bo->total_size; - addr = mmap(0, bo->total_size, prot, MAP_SHARED, bo->drv->fd, gem_map.out.addr_ptr); - if (drv_priv->surf_mode >= RADEON_SURF_MODE_2D) { - if (bo_priv->ref_count == 0) { - uint32_t buf_size = drv_priv->surf_info->u.legacy.level[0].nblk_x * - drv_priv->surf_config.info.height * - (drv_priv->surf_info->bpe); - bo_priv->untiled_buf_ptr = malloc(buf_size); - if (bo_priv->untiled_buf_ptr == NULL) { - munmap(addr, vma->length); - return NULL; - } - } - bo_priv->prot = prot; - bo_priv->ref_count++; - drv_priv->dri_handle->fptr_read_write_tiled(drv_priv->addrlib_handle, - &drv_priv->surf_config, - drv_priv->surf_info, addr, - (uint8_t*)bo_priv->untiled_buf_ptr, - 0); - return bo_priv->untiled_buf_ptr; - } - bo_priv->ref_count++; - return addr; + free(drv->priv); + drv->priv = NULL; } -static int amdgpu_bo_unmap(struct bo *bo, struct vma *vma) -{ - struct bo_priv_ptr *bo_priv = (struct bo_priv_ptr *)bo->priv; - struct drv_priv_ptr *drv_priv = (struct drv_priv_ptr *)bo->drv->priv; - bo_priv->ref_count--; - if (drv_priv->surf_mode >= RADEON_SURF_MODE_2D) { - if (bo_priv->untiled_buf_ptr != NULL) { - if (bo_priv->prot & PROT_WRITE) - drv_priv->dri_handle->fptr_read_write_tiled(drv_priv->addrlib_handle, - &drv_priv->surf_config, - drv_priv->surf_info, - vma->addr, - (uint8_t*)bo_priv->untiled_buf_ptr, - 1); - if (bo_priv->ref_count == 0) { - free(bo_priv->untiled_buf_ptr); - bo_priv->untiled_buf_ptr = NULL; - } - } - } - return munmap(vma->addr, vma->length); -} - static uint32_t amdgpu_resolve_format(uint32_t format, uint64_t use_flags) { switch (format) { @@ -467,11 +125,11 @@ const struct backend backend_amdgpu = { .name = "amdgpu", .init = amdgpu_init, .close = amdgpu_close, - .bo_create = amdgpu_bo_create, - .bo_destroy = drv_gem_bo_destroy, - .bo_import = amdgpu_gbm_bo_import, - .bo_map = amdgpu_bo_map, - .bo_unmap = amdgpu_bo_unmap, + .bo_create = dri_bo_create, + .bo_destroy = dri_bo_destroy, + .bo_import = dri_bo_import, + .bo_map = dri_bo_map, + .bo_unmap = dri_bo_unmap, .resolve_format = amdgpu_resolve_format, }; diff --git a/dri.c b/dri.c new file mode 100644 index 0000000..48bab92 --- /dev/null +++ b/dri.c @@ -0,0 +1,319 @@ +/* + * Copyright 2017 Advanced Micro Devices. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* This file implements a minigbm driver based on loading a driver .so + * that uses the DRI interface as implemented in Mesa. + * + * TODO: + * - this is currently setup as a kind of library / base class which allows + * specialization by the caller; can we get rid of that? + * - lots of TODOs throughout the code, e.g. incomplete format support + */ + +#include "dri.h" + +#include +#include +#include +#include + +#include +#include + +#include "drv_priv.h" +#include "gbm.h" +#include "helpers.h" +#include "util.h" + +// clang-format off + +struct dri_bo_priv { + __DRIimage *image; +}; + +static bool lookup_extension(const __DRIextension * const *extensions, + const char *name, int min_version, + const __DRIextension **dst) +{ + while (*extensions) { + if ((*extensions)->name && + !strcmp((*extensions)->name, name) && + (*extensions)->version >= min_version) { + *dst = *extensions; + return true; + } + } + + return false; +} + +static const struct { + uint32_t gbm_format; + int dri_image_format; +} gbm_to_dri_image_formats[] = { + { GBM_FORMAT_R8, __DRI_IMAGE_FORMAT_R8 }, + { GBM_FORMAT_GR88, __DRI_IMAGE_FORMAT_GR88 }, + { GBM_FORMAT_RGB565, __DRI_IMAGE_FORMAT_RGB565 }, + { GBM_FORMAT_XRGB8888, __DRI_IMAGE_FORMAT_XRGB8888 }, + { GBM_FORMAT_ARGB8888, __DRI_IMAGE_FORMAT_ARGB8888 }, + { GBM_FORMAT_XBGR8888, __DRI_IMAGE_FORMAT_XBGR8888 }, + { GBM_FORMAT_ABGR8888, __DRI_IMAGE_FORMAT_ABGR8888 }, + { GBM_FORMAT_XRGB2101010, __DRI_IMAGE_FORMAT_XRGB2101010 }, + { GBM_FORMAT_ARGB2101010, __DRI_IMAGE_FORMAT_ARGB2101010 }, +}; + +static int +gbm_format_to_dri_format(uint32_t gbm_format) +{ + for (unsigned i = 0; i < ARRAY_SIZE(gbm_to_dri_image_formats); i++) { + if (gbm_to_dri_image_formats[i].gbm_format == gbm_format) + return gbm_to_dri_image_formats[i].dri_image_format; + } + + return 0; +} + +/** + * The caller is responsible for setting drv->priv to a structure that derives + * from dri_driver_priv. + * + * TODO: + * - should this handle the drv_{add,modify}_combination calls? + */ +int dri_init(struct driver *drv, const char *dri_so_path, const char *driver_suffix) +{ + struct dri_driver_priv *dri = (struct dri_driver_priv *)drv->priv; + if (!dri) + return -1; + + dri->driver_handle = dlopen(dri_so_path, RTLD_NOW | RTLD_GLOBAL); + if (!dri->driver_handle) + return -1; + + const __DRIextension **(*get_extensions)(); + char fname[128]; + + snprintf(fname, sizeof(fname), __DRI_DRIVER_GET_EXTENSIONS "_%s", driver_suffix); + + get_extensions = dlsym(dri->driver_handle, fname); + if (!get_extensions) + goto fail; + + dri->extensions = get_extensions(); + if (!dri->extensions) + goto fail; + + if (!lookup_extension(dri->extensions, __DRI_CORE, 2, + (const __DRIextension **)&dri->core_extension)) + goto fail; + + /* Version 4 for createNewScreen2 */ + if (!lookup_extension(dri->extensions, __DRI_DRI2, 4, + (const __DRIextension **)&dri->dri2_extension)) + goto fail; + + /* Version 13 for __DRI_IMAGE_ATTRIB_OFFSET */ + if (!lookup_extension(dri->extensions, __DRI_IMAGE, 12, + (const __DRIextension **)&dri->image_extension)) + goto fail; + + static const __DRIextension * empty_extensions[] = { NULL }; + + dri->device = dri->dri2_extension->createNewScreen2( + 0, /* screen -- unused X-ism */ + drv_get_fd(drv), + empty_extensions, /* loader (i.e., our) extensions */ + dri->extensions, + &dri->configs, + NULL); /* loader private */ + if (!dri->device) + goto fail; + + return 0; + +fail: + dlclose(dri->driver_handle); + dri->driver_handle = NULL; + return -1; +} + +/** + * The caller is responsible for freeing drv->priv. + */ +void dri_close(struct driver *drv) +{ + struct dri_driver_priv *dri = (struct dri_driver_priv *)drv->priv; + + if (dri->context) + dri->core_extension->destroyContext(dri->context); + + dri->core_extension->destroyScreen(dri->device); + dlclose(dri->driver_handle); +} + +int dri_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format, + uint64_t use_flags) +{ + struct dri_driver_priv *dri = (struct dri_driver_priv *)bo->drv->priv; + struct dri_bo_priv *bo_dri; + + assert(!bo->priv); + + bo_dri = (struct dri_bo_priv *)calloc(1, sizeof(*bo_dri)); + if (!bo_dri) + return -1; + + int dri_format = gbm_format_to_dri_format(format); + unsigned dri_use = 0; + + if (use_flags & GBM_BO_USE_SCANOUT) + dri_use |= __DRI_IMAGE_USE_SCANOUT; + if (use_flags & GBM_BO_USE_CURSOR) + dri_use |= __DRI_IMAGE_USE_CURSOR; + if (use_flags & GBM_BO_USE_LINEAR) + dri_use |= __DRI_IMAGE_USE_LINEAR; + + /* Gallium drivers requires shared in order to get the handle/stride */ + dri_use |= __DRI_IMAGE_USE_SHARE; + + bo_dri->image = dri->image_extension->createImage( + dri->device, + width, height, dri_format, dri_use, + NULL); /* loaderPrivate */ + if (!bo_dri->image) + goto fail; + + assert(bo->num_planes == 1); /* TODO: implement */ + + if (!dri->image_extension->queryImage( + bo_dri->image, + __DRI_IMAGE_ATTRIB_HANDLE, + &bo->handles[0].s32)) + goto fail_free; + if (!dri->image_extension->queryImage( + bo_dri->image, + __DRI_IMAGE_ATTRIB_STRIDE, + (int *)&bo->strides[0])) + goto fail_free; + if (!dri->image_extension->queryImage( + bo_dri->image, + __DRI_IMAGE_ATTRIB_OFFSET, + (int *)&bo->offsets[0])) + goto fail_free; + + bo->sizes[0] = 42; /* TODO */ + bo->total_size = bo->sizes[0]; + + bo->priv = bo_dri; + return 0; + +fail_free: + dri->image_extension->destroyImage(bo_dri->image); +fail: + free(bo_dri); + return -1; +} + +int dri_bo_import(struct bo *bo, struct drv_import_fd_data *data) +{ + struct dri_driver_priv *dri = (struct dri_driver_priv *)bo->drv->priv; + struct dri_bo_priv *bo_dri; + + assert(!bo->priv); + + bo_dri = (struct dri_bo_priv *)calloc(1, sizeof(*bo_dri)); + if (!bo_dri) + return -1; + + bo_dri->image = dri->image_extension->createImageFromFds( + dri->device, + data->width, data->height, data->format, + data->fds, bo->num_planes, + (int*)data->strides, (int*)data->offsets, + NULL); /* loaderPrivate */ + if (!bo_dri->image) + goto fail; + + assert(bo->num_planes == 1); /* TODO: implement */ + + if (!dri->image_extension->queryImage( + bo_dri->image, + __DRI_IMAGE_ATTRIB_HANDLE, + &bo->handles[0].s32)) + goto fail_free; + + bo->priv = bo_dri; + return 0; + +fail_free: + dri->image_extension->destroyImage(bo_dri->image); +fail: + free(bo_dri); + return -1; +} + +int dri_bo_destroy(struct bo *bo) +{ + struct dri_driver_priv *dri = (struct dri_driver_priv *)bo->drv->priv; + struct dri_bo_priv *bo_dri = (struct dri_bo_priv *)bo->priv; + + dri->image_extension->destroyImage(bo_dri->image); + free(bo_dri); + + return 0; +} + +/** + * Map an image plane. + * + * This relies on the underlying driver to do a decompressing and/or de-tiling + * blit if necessary, + * + * This function itself is not thread-safe; we rely on the fact that the caller + * locks a per-driver mutex. + */ +void *dri_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint32_t map_flags) +{ + struct dri_driver_priv *dri = (struct dri_driver_priv *)bo->drv->priv; + struct dri_bo_priv *bo_dri = (struct dri_bo_priv *)bo->priv; + + if (!dri->context) { + dri->context = dri->dri2_extension->createNewContext( + dri->device, + NULL, /* config */ + NULL, /* shared */ + NULL); /* loaderPrivate */ + if (!dri->context) + return MAP_FAILED; + } + + assert(plane == 0); /* TODO */ + + void *addr; + int stride; + + addr = dri->image_extension->mapImage( + dri->context, bo_dri->image, + 0, 0, bo->width, bo->height, /* rectangle to map */ + map_flags, /* GBM flags and DRI flags are the same */ + &stride, &vma->priv); + if (!addr) + return MAP_FAILED; + + assert((uint32_t)stride == bo->strides[plane]); + + return addr; +} + +int dri_bo_unmap(struct bo *bo, struct vma *vma) +{ + struct dri_driver_priv *dri = (struct dri_driver_priv *)bo->drv->priv; + struct dri_bo_priv *bo_dri = (struct dri_bo_priv *)bo->priv; + + dri->image_extension->unmapImage(dri->context, bo_dri->image, vma->priv); + + return 0; +} diff --git a/dri.h b/dri.h new file mode 100644 index 0000000..ffdd2e8 --- /dev/null +++ b/dri.h @@ -0,0 +1,44 @@ +/* + * Copyright 2017 Advanced Micro Devices. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef MINIGBM_DRI_H +#define MINIGBM_DRI_H + +// clang-format off + +/* for GLboolean */ +#include "GL/gl.h" + +#include "GL/internal/dri_interface.h" + +struct bo; +struct driver; +struct vma; + +struct drv_import_fd_data; + +struct dri_driver_priv { + void *driver_handle; + __DRIscreen *device; + __DRIcontext *context; /* used for map/unmap operations */ + const __DRIextension **extensions; + const __DRIcoreExtension *core_extension; + const __DRIdri2Extension *dri2_extension; + const __DRIimageExtension *image_extension; + const __DRIconfig **configs; +}; + + +int dri_init(struct driver *drv, const char *dri_so_path, const char *driver_suffix); +void dri_close(struct driver *drv); +int dri_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format, + uint64_t use_flags); +int dri_bo_import(struct bo *bo, struct drv_import_fd_data *data); +int dri_bo_destroy(struct bo *bo); +void *dri_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint32_t map_flags); +int dri_bo_unmap(struct bo *bo, struct vma *vma); + +#endif -- cgit v1.2.3