nouveau/ws: add bo API
authorKarol Herbst <kherbst@redhat.com>
Fri, 20 May 2022 13:26:47 +0000 (15:26 +0200)
committerMarge Bot <emma+marge@anholt.net>
Fri, 4 Aug 2023 21:31:53 +0000 (21:31 +0000)
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24326>

src/nouveau/winsys/meson.build
src/nouveau/winsys/nouveau_bo.c [new file with mode: 0644]
src/nouveau/winsys/nouveau_bo.h [new file with mode: 0644]
src/nouveau/winsys/nouveau_device.c
src/nouveau/winsys/nouveau_device.h

index 6204205..7ce1762 100644 (file)
@@ -1,6 +1,8 @@
 libnouveau_ws = static_library(
   'nouveau_ws',
   [
+    'nouveau_bo.h',
+    'nouveau_bo.c',
     'nouveau_device.h',
     'nouveau_device.c',
     'nouveau_private.h',
diff --git a/src/nouveau/winsys/nouveau_bo.c b/src/nouveau/winsys/nouveau_bo.c
new file mode 100644 (file)
index 0000000..3387700
--- /dev/null
@@ -0,0 +1,70 @@
+#include "nouveau_bo.h"
+
+#include <nouveau/nouveau.h>
+#include <nouveau_drm.h>
+#include <xf86drm.h>
+
+#include <stddef.h>
+#include <sys/mman.h>
+
+struct nouveau_ws_bo *
+nouveau_ws_bo_new(struct nouveau_ws_device *dev, uint64_t size, uint64_t align, enum nouveau_ws_bo_flags flags)
+{
+   struct nouveau_ws_device_priv *pdev = nouveau_ws_device(dev);
+   struct nouveau_ws_bo *bo = CALLOC_STRUCT(nouveau_ws_bo);
+   struct drm_nouveau_gem_new req = {};
+
+   /* if the caller doesn't care, use the GPU page size */
+   if (align == 0)
+      align = 0x1000;
+
+   req.info.domain = NOUVEAU_GEM_TILE_NONCONTIG;
+   if (flags & NOUVEAU_WS_BO_GART)
+      req.info.domain |= NOUVEAU_GEM_DOMAIN_GART;
+   else
+      req.info.domain |= pdev->local_mem_domain;
+
+   if (flags & NOUVEAU_WS_BO_MAP)
+      req.info.domain |= NOUVEAU_GEM_DOMAIN_MAPPABLE;
+
+   req.info.size = size;
+   req.align = align;
+
+   int ret = drmCommandWriteRead(pdev->fd, DRM_NOUVEAU_GEM_NEW, &req, sizeof(req));
+   if (ret) {
+      FREE(bo);
+      return NULL;
+   }
+
+   bo->size = req.info.size;
+   bo->offset = req.info.offset;
+   bo->handle = req.info.handle;
+   bo->map_handle = req.info.map_handle;
+   bo->fd = pdev->fd;
+
+   return bo;
+}
+
+void
+nouveau_ws_bo_destroy(struct nouveau_ws_bo *bo)
+{
+   drmCloseBufferHandle(bo->fd, bo->handle);
+   FREE(bo);
+}
+
+void *
+nouveau_ws_bo_map(struct nouveau_ws_bo *bo, enum nouveau_ws_bo_map_flags flags)
+{
+   size_t prot = 0;
+
+   if (flags & NOUVEAU_WS_BO_RD)
+      prot |= PROT_READ;
+   if (flags & NOUVEAU_WS_BO_WR)
+      prot |= PROT_WRITE;
+
+   void *res = mmap64(NULL, bo->size, prot, MAP_SHARED, bo->fd, bo->map_handle);
+   if (res == MAP_FAILED)
+      return NULL;
+
+   return res;
+}
diff --git a/src/nouveau/winsys/nouveau_bo.h b/src/nouveau/winsys/nouveau_bo.h
new file mode 100644 (file)
index 0000000..e858d3b
--- /dev/null
@@ -0,0 +1,33 @@
+#ifndef NOUVEAU_BO
+#define NOUVEAU_BO 1
+
+#include "nouveau_private.h"
+
+#include "nouveau_device.h"
+
+enum nouveau_ws_bo_flags {
+   /* vram or gart depending on GPU */
+   NOUVEAU_WS_BO_LOCAL = 0 << 0,
+   NOUVEAU_WS_BO_GART  = 1 << 0,
+   NOUVEAU_WS_BO_MAP   = 1 << 1,
+};
+
+enum nouveau_ws_bo_map_flags {
+   NOUVEAU_WS_BO_RD   = 1 << 0,
+   NOUVEAU_WS_BO_WR   = 1 << 1,
+   NOUVEAU_WS_BO_RDWR = NOUVEAU_WS_BO_RD | NOUVEAU_WS_BO_WR,
+};
+
+struct nouveau_ws_bo {
+   uint64_t size;
+   uint64_t offset;
+   uint64_t map_handle;
+   int fd;
+   uint32_t handle;
+};
+
+struct nouveau_ws_bo *nouveau_ws_bo_new(struct nouveau_ws_device *, uint64_t size, uint64_t align, enum nouveau_ws_bo_flags);
+void nouveau_ws_bo_destroy(struct nouveau_ws_bo *);
+void *nouveau_ws_bo_map(struct nouveau_ws_bo *, enum nouveau_ws_bo_map_flags);
+
+#endif
index 1d150de..6f4d621 100644 (file)
@@ -103,6 +103,11 @@ nouveau_ws_device_new(int fd)
    device->dev = dev;
    device->fd = dup_fd;
 
+   if (dev->vram_size == 0)
+      device->local_mem_domain = NOUVEAU_GEM_DOMAIN_GART;
+   else
+      device->local_mem_domain = NOUVEAU_GEM_DOMAIN_VRAM;
+
    return &device->base;
 
 out_dev:
index 602e06b..cb78a20 100644 (file)
@@ -22,6 +22,7 @@ struct nouveau_ws_device_priv {
    struct nouveau_drm *drm;
    struct nouveau_device *dev;
    int fd;
+   uint32_t local_mem_domain;
 };
 
 static struct nouveau_ws_device_priv *