From c370260a8f15e9be2f43a7d237f438592a09cccd Mon Sep 17 00:00:00 2001 From: Faith Ekstrand Date: Mon, 17 Jul 2023 17:37:24 -0500 Subject: [PATCH] nouveau/winsys: Add dma-buf import support This requires a lock and a buffer cache on the nouveau_ws_device. Part-of: --- src/nouveau/winsys/meson.build | 1 + src/nouveau/winsys/nouveau_bo.c | 79 +++++++++++++++++++++++++---- src/nouveau/winsys/nouveau_bo.h | 2 + src/nouveau/winsys/nouveau_device.c | 6 +++ src/nouveau/winsys/nouveau_device.h | 5 ++ 5 files changed, 84 insertions(+), 9 deletions(-) diff --git a/src/nouveau/winsys/meson.build b/src/nouveau/winsys/meson.build index 80d6fbad436..738ef306998 100644 --- a/src/nouveau/winsys/meson.build +++ b/src/nouveau/winsys/meson.build @@ -18,6 +18,7 @@ libnouveau_ws = static_library( dependencies : [ dep_libdrm, dep_libdrm_nouveau, + dep_valgrind, idep_nvidia_headers, ], gnu_symbol_visibility : 'hidden', diff --git a/src/nouveau/winsys/nouveau_bo.c b/src/nouveau/winsys/nouveau_bo.c index 3684a5d9a43..569ecd0f2e4 100644 --- a/src/nouveau/winsys/nouveau_bo.c +++ b/src/nouveau/winsys/nouveau_bo.c @@ -1,5 +1,7 @@ #include "nouveau_bo.h" +#include + #include #include @@ -67,19 +69,71 @@ nouveau_ws_bo_new_tiled(struct nouveau_ws_device *dev, req.info.size = size; req.align = align; + simple_mtx_lock(&dev->bos_lock); + int ret = drmCommandWriteRead(dev->fd, DRM_NOUVEAU_GEM_NEW, &req, sizeof(req)); - if (ret) { + if (ret == 0) { + bo->size = req.info.size; + bo->offset = req.info.offset; + bo->handle = req.info.handle; + bo->map_handle = req.info.map_handle; + bo->dev = dev; + bo->flags = flags; + bo->refcnt = 1; + + _mesa_hash_table_insert(dev->bos, (void *)(uintptr_t)bo->handle, bo); + } else { FREE(bo); - return NULL; + bo = NULL; } - bo->size = req.info.size; - bo->offset = req.info.offset; - bo->handle = req.info.handle; - bo->map_handle = req.info.map_handle; - bo->dev = dev; - bo->flags = flags; - bo->refcnt = 1; + simple_mtx_unlock(&dev->bos_lock); + + return bo; +} + +struct nouveau_ws_bo * +nouveau_ws_bo_from_dma_buf(struct nouveau_ws_device *dev, int fd) +{ + struct nouveau_ws_bo *bo = NULL; + + simple_mtx_lock(&dev->bos_lock); + + uint32_t handle; + int ret = drmPrimeFDToHandle(dev->fd, fd, &handle); + if (ret == 0) { + struct hash_entry *entry = + _mesa_hash_table_search(dev->bos, (void *)(uintptr_t)handle); + if (entry != NULL) { + bo = entry->data; + } else { + struct drm_nouveau_gem_info info = { + .handle = handle + }; + ret = drmCommandWriteRead(dev->fd, DRM_NOUVEAU_GEM_INFO, + &info, sizeof(info)); + if (ret == 0) { + enum nouveau_ws_bo_flags flags = 0; + if (info.domain & NOUVEAU_GEM_DOMAIN_GART) + flags |= NOUVEAU_WS_BO_GART; + if (info.map_handle) + flags |= NOUVEAU_WS_BO_MAP; + + bo = CALLOC_STRUCT(nouveau_ws_bo); + bo->size = info.size; + bo->offset = info.offset; + bo->handle = info.handle; + bo->map_handle = info.map_handle; + bo->dev = dev; + bo->flags = flags; + bo->refcnt = 1; + + _mesa_hash_table_insert(dev->bos, (void *)(uintptr_t)handle, bo); + } + } + } + + simple_mtx_unlock(&dev->bos_lock); return bo; } @@ -90,8 +144,15 @@ nouveau_ws_bo_destroy(struct nouveau_ws_bo *bo) if (--bo->refcnt) return; + struct nouveau_ws_device *dev = bo->dev; + + simple_mtx_lock(&dev->bos_lock); + + _mesa_hash_table_remove_key(dev->bos, (void *)(uintptr_t)bo->handle); drmCloseBufferHandle(bo->dev->fd, bo->handle); FREE(bo); + + simple_mtx_unlock(&dev->bos_lock); } void * diff --git a/src/nouveau/winsys/nouveau_bo.h b/src/nouveau/winsys/nouveau_bo.h index bb355f31839..63fdb909ccc 100644 --- a/src/nouveau/winsys/nouveau_bo.h +++ b/src/nouveau/winsys/nouveau_bo.h @@ -54,6 +54,8 @@ struct nouveau_ws_bo *nouveau_ws_bo_new_tiled(struct nouveau_ws_device *, uint8_t pte_kind, uint16_t tile_mode, enum nouveau_ws_bo_flags); +struct nouveau_ws_bo *nouveau_ws_bo_from_dma_buf(struct nouveau_ws_device *, + int fd); void nouveau_ws_bo_destroy(struct nouveau_ws_bo *); void *nouveau_ws_bo_map(struct nouveau_ws_bo *, enum nouveau_ws_bo_map_flags); bool nouveau_ws_bo_wait(struct nouveau_ws_bo *, enum nouveau_ws_bo_map_flags flags); diff --git a/src/nouveau/winsys/nouveau_device.c b/src/nouveau/winsys/nouveau_device.c index dfade7ef6a5..1c246bae45c 100644 --- a/src/nouveau/winsys/nouveau_device.c +++ b/src/nouveau/winsys/nouveau_device.c @@ -7,6 +7,7 @@ #include #include #include +#include #include "nouveau_context.h" @@ -266,6 +267,9 @@ nouveau_ws_device_new(drmDevicePtr drm_device) nouveau_ws_context_destroy(tmp_ctx); + simple_mtx_init(&device->bos_lock, mtx_plain); + device->bos = _mesa_pointer_hash_table_create(NULL); + return device; out_err: @@ -282,6 +286,8 @@ nouveau_ws_device_destroy(struct nouveau_ws_device *device) if (!device) return; + _mesa_hash_table_destroy(device->bos, NULL); + simple_mtx_destroy(&device->bos_lock); close(device->fd); FREE(device->chipset_name); FREE(device->device_name); diff --git a/src/nouveau/winsys/nouveau_device.h b/src/nouveau/winsys/nouveau_device.h index 6744c9296ab..b07da5d9a06 100644 --- a/src/nouveau/winsys/nouveau_device.h +++ b/src/nouveau/winsys/nouveau_device.h @@ -3,10 +3,12 @@ #include "nouveau_private.h" #include "nv_device_info.h" +#include "util/simple_mtx.h" #include struct _drmDevice; +struct hash_table; #ifdef __cplusplus extern "C" { @@ -52,6 +54,9 @@ struct nouveau_ws_device { uint16_t mp_count; enum nvk_debug debug_flags; + + simple_mtx_t bos_lock; + struct hash_table *bos; }; struct nouveau_ws_device *nouveau_ws_device_new(struct _drmDevice *drm_device);