nouveau/winsys: Add dma-buf import support

This requires a lock and a buffer cache on the nouveau_ws_device.

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24326>
This commit is contained in:
Faith Ekstrand 2023-07-17 17:37:24 -05:00 committed by Marge Bot
parent 10ffe8e709
commit c370260a8f
5 changed files with 84 additions and 9 deletions

View file

@ -18,6 +18,7 @@ libnouveau_ws = static_library(
dependencies : [ dependencies : [
dep_libdrm, dep_libdrm,
dep_libdrm_nouveau, dep_libdrm_nouveau,
dep_valgrind,
idep_nvidia_headers, idep_nvidia_headers,
], ],
gnu_symbol_visibility : 'hidden', gnu_symbol_visibility : 'hidden',

View file

@ -1,5 +1,7 @@
#include "nouveau_bo.h" #include "nouveau_bo.h"
#include <util/hash_table.h>
#include <nouveau_drm.h> #include <nouveau_drm.h>
#include <xf86drm.h> #include <xf86drm.h>
@ -67,12 +69,10 @@ nouveau_ws_bo_new_tiled(struct nouveau_ws_device *dev,
req.info.size = size; req.info.size = size;
req.align = align; req.align = align;
int ret = drmCommandWriteRead(dev->fd, DRM_NOUVEAU_GEM_NEW, &req, sizeof(req)); simple_mtx_lock(&dev->bos_lock);
if (ret) {
FREE(bo);
return NULL;
}
int ret = drmCommandWriteRead(dev->fd, DRM_NOUVEAU_GEM_NEW, &req, sizeof(req));
if (ret == 0) {
bo->size = req.info.size; bo->size = req.info.size;
bo->offset = req.info.offset; bo->offset = req.info.offset;
bo->handle = req.info.handle; bo->handle = req.info.handle;
@ -81,6 +81,60 @@ nouveau_ws_bo_new_tiled(struct nouveau_ws_device *dev,
bo->flags = flags; bo->flags = flags;
bo->refcnt = 1; bo->refcnt = 1;
_mesa_hash_table_insert(dev->bos, (void *)(uintptr_t)bo->handle, bo);
} else {
FREE(bo);
bo = NULL;
}
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; return bo;
} }
@ -90,8 +144,15 @@ nouveau_ws_bo_destroy(struct nouveau_ws_bo *bo)
if (--bo->refcnt) if (--bo->refcnt)
return; 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); drmCloseBufferHandle(bo->dev->fd, bo->handle);
FREE(bo); FREE(bo);
simple_mtx_unlock(&dev->bos_lock);
} }
void * void *

View file

@ -54,6 +54,8 @@ struct nouveau_ws_bo *nouveau_ws_bo_new_tiled(struct nouveau_ws_device *,
uint8_t pte_kind, uint8_t pte_kind,
uint16_t tile_mode, uint16_t tile_mode,
enum nouveau_ws_bo_flags); 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_destroy(struct nouveau_ws_bo *);
void *nouveau_ws_bo_map(struct nouveau_ws_bo *, enum nouveau_ws_bo_map_flags); 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); bool nouveau_ws_bo_wait(struct nouveau_ws_bo *, enum nouveau_ws_bo_map_flags flags);

View file

@ -7,6 +7,7 @@
#include <nouveau/nvif/ioctl.h> #include <nouveau/nvif/ioctl.h>
#include <nvif/cl0080.h> #include <nvif/cl0080.h>
#include <nvif/class.h> #include <nvif/class.h>
#include <util/hash_table.h>
#include "nouveau_context.h" #include "nouveau_context.h"
@ -266,6 +267,9 @@ nouveau_ws_device_new(drmDevicePtr drm_device)
nouveau_ws_context_destroy(tmp_ctx); nouveau_ws_context_destroy(tmp_ctx);
simple_mtx_init(&device->bos_lock, mtx_plain);
device->bos = _mesa_pointer_hash_table_create(NULL);
return device; return device;
out_err: out_err:
@ -282,6 +286,8 @@ nouveau_ws_device_destroy(struct nouveau_ws_device *device)
if (!device) if (!device)
return; return;
_mesa_hash_table_destroy(device->bos, NULL);
simple_mtx_destroy(&device->bos_lock);
close(device->fd); close(device->fd);
FREE(device->chipset_name); FREE(device->chipset_name);
FREE(device->device_name); FREE(device->device_name);

View file

@ -3,10 +3,12 @@
#include "nouveau_private.h" #include "nouveau_private.h"
#include "nv_device_info.h" #include "nv_device_info.h"
#include "util/simple_mtx.h"
#include <stddef.h> #include <stddef.h>
struct _drmDevice; struct _drmDevice;
struct hash_table;
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -52,6 +54,9 @@ struct nouveau_ws_device {
uint16_t mp_count; uint16_t mp_count;
enum nvk_debug debug_flags; 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); struct nouveau_ws_device *nouveau_ws_device_new(struct _drmDevice *drm_device);