Mesa (main): zink: add back kms handling

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Sat Jun 4 01:48:26 UTC 2022


Module: Mesa
Branch: main
Commit: b0fe621459c1b02b658f05ebbaba3ca68a7830de
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=b0fe621459c1b02b658f05ebbaba3ca68a7830de

Author: Mike Blumenkrantz <michael.blumenkrantz at gmail.com>
Date:   Wed Jun  1 11:31:28 2022 -0400

zink: add back kms handling

removing this broke the ability to create system compositors

rework it a bit though so that kms handles are stored and destroyed
when the bo is freed

Reviewed-by: Adam Jackson <ajax at redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/16815>

---

 src/gallium/drivers/zink/meson.build     |  2 +-
 src/gallium/drivers/zink/zink_bo.c       | 64 ++++++++++++++++++++++++++++----
 src/gallium/drivers/zink/zink_bo.h       | 14 +++++++
 src/gallium/drivers/zink/zink_resource.c | 15 +++++++-
 src/gallium/drivers/zink/zink_screen.h   |  2 -
 5 files changed, 85 insertions(+), 12 deletions(-)

diff --git a/src/gallium/drivers/zink/meson.build b/src/gallium/drivers/zink/meson.build
index 78975f90e93..4621e7f983e 100644
--- a/src/gallium/drivers/zink/meson.build
+++ b/src/gallium/drivers/zink/meson.build
@@ -92,7 +92,7 @@ libzink = static_library(
   include_directories : [inc_include, inc_src, inc_mapi, inc_mesa, inc_gallium, inc_gallium_aux, inc_vulkan_util, inc_zink_vk],
   dependencies: [
     idep_nir_headers, idep_mesautil, idep_vulkan_util_headers,
-    idep_vulkan_wsi_headers, idep_vulkan_util
+    idep_vulkan_wsi_headers, idep_vulkan_util, dep_libdrm
   ],
   c_args: zink_c_args,
 )
diff --git a/src/gallium/drivers/zink/zink_bo.c b/src/gallium/drivers/zink/zink_bo.c
index 5afa5ec413e..d4b48d1b518 100644
--- a/src/gallium/drivers/zink/zink_bo.c
+++ b/src/gallium/drivers/zink/zink_bo.c
@@ -34,6 +34,11 @@
 #include "zink_screen.h"
 #include "util/u_hash_table.h"
 
+#if !defined(__APPLE__) && !defined(_WIN32)
+#define ZINK_USE_DMABUF
+#include <xf86drm.h>
+#endif
+
 struct zink_bo;
 
 struct zink_sparse_backing_chunk {
@@ -120,9 +125,19 @@ bo_destroy(struct zink_screen *screen, struct pb_buffer *pbuf)
 {
    struct zink_bo *bo = zink_bo(pbuf);
 
-   simple_mtx_lock(&screen->pb.bo_export_table_lock);
-   _mesa_hash_table_remove_key(screen->pb.bo_export_table, bo);
-   simple_mtx_unlock(&screen->pb.bo_export_table_lock);
+#ifdef ZINK_USE_DMABUF
+   if (!bo->u.real.use_reusable_pool) {
+      simple_mtx_lock(&bo->u.real.export_lock);
+      list_for_each_entry_safe(struct bo_export, export, &bo->u.real.exports, link) {
+         struct drm_gem_close args = { .handle = export->gem_handle };
+         drmIoctl(export->drm_fd, DRM_IOCTL_GEM_CLOSE, &args);
+         list_del(&export->link);
+         free(export);
+      }
+      simple_mtx_unlock(&bo->u.real.export_lock);
+      simple_mtx_destroy(&bo->u.real.export_lock);
+   }
+#endif
 
    if (!bo->u.real.is_user_ptr && bo->u.real.cpu_ptr) {
       bo->u.real.map_count = 1;
@@ -282,6 +297,11 @@ demote:
    if (init_pb_cache) {
       bo->u.real.use_reusable_pool = true;
       pb_cache_init_entry(&screen->pb.bo_cache, bo->cache_entry, &bo->base, heap);
+   } else {
+#ifdef ZINK_USE_DMABUF
+      list_inithead(&bo->u.real.exports);
+      simple_mtx_init(&bo->u.real.export_lock, mtx_plain);
+#endif
    }
 
 
@@ -1065,6 +1085,40 @@ out:
    return ok;
 }
 
+bool
+zink_bo_get_kms_handle(struct zink_screen *screen, struct zink_bo *bo, int fd, uint32_t *handle)
+{
+#ifdef ZINK_USE_DMABUF
+   assert(bo->mem && !bo->u.real.use_reusable_pool);
+   simple_mtx_lock(&bo->u.real.export_lock);
+   list_for_each_entry(struct bo_export, export, &bo->u.real.exports, link) {
+      if (export->drm_fd == fd) {
+         simple_mtx_unlock(&bo->u.real.export_lock);
+         *handle = export->gem_handle;
+         return true;
+      }
+   }
+   struct bo_export *export = CALLOC_STRUCT(bo_export);
+   if (!export) {
+      simple_mtx_unlock(&bo->u.real.export_lock);
+      return false;
+   }
+   bool success = drmPrimeFDToHandle(screen->drm_fd, fd, handle) == 0;
+   if (success) {
+      list_addtail(&export->link, &bo->u.real.exports);
+      export->gem_handle = *handle;
+      export->drm_fd = screen->drm_fd;
+   } else {
+      mesa_loge("zink: failed drmPrimeFDToHandle %s", strerror(errno));
+      FREE(export);
+   }
+   simple_mtx_unlock(&bo->u.real.export_lock);
+   return success;
+#else
+   return false;
+#endif
+}
+
 static const struct pb_vtbl bo_slab_vtbl = {
    /* Cast to void* because one of the function parameters is a struct pointer instead of void*. */
    (void*)bo_slab_destroy
@@ -1214,8 +1268,6 @@ zink_bo_init(struct zink_screen *screen)
       min_slab_order = max_order + 1;
    }
    screen->pb.min_alloc_size = 1 << screen->pb.bo_slabs[0].min_order;
-   screen->pb.bo_export_table = util_hash_table_create_ptr_keys();
-   simple_mtx_init(&screen->pb.bo_export_table_lock, mtx_plain);
    return true;
 }
 
@@ -1227,6 +1279,4 @@ zink_bo_deinit(struct zink_screen *screen)
          pb_slabs_deinit(&screen->pb.bo_slabs[i]);
    }
    pb_cache_deinit(&screen->pb.bo_cache);
-   _mesa_hash_table_destroy(screen->pb.bo_export_table, NULL);
-   simple_mtx_destroy(&screen->pb.bo_export_table_lock);
 }
diff --git a/src/gallium/drivers/zink/zink_bo.h b/src/gallium/drivers/zink/zink_bo.h
index 82cedb170d4..19215a4bdc0 100644
--- a/src/gallium/drivers/zink/zink_bo.h
+++ b/src/gallium/drivers/zink/zink_bo.h
@@ -55,6 +55,15 @@ enum zink_alloc_flag {
    ZINK_ALLOC_NO_SUBALLOC = 1<<1,
 };
 
+struct bo_export {
+   /** File descriptor associated with a handle export. */
+   int drm_fd;
+
+   /** GEM handle in drm_fd */
+   uint32_t gem_handle;
+
+   struct list_head link;
+};
 
 struct zink_bo {
    struct pb_buffer base;
@@ -63,6 +72,8 @@ struct zink_bo {
       struct {
          void *cpu_ptr; /* for user_ptr and permanent maps */
          int map_count;
+         struct list_head exports;
+         simple_mtx_t export_lock;
 
          bool is_user_ptr;
          bool use_reusable_pool;
@@ -175,6 +186,9 @@ zink_bo_deinit(struct zink_screen *screen);
 struct pb_buffer *
 zink_bo_create(struct zink_screen *screen, uint64_t size, unsigned alignment, enum zink_heap heap, enum zink_alloc_flag flags, const void *pNext);
 
+bool
+zink_bo_get_kms_handle(struct zink_screen *screen, struct zink_bo *bo, int fd, uint32_t *handle);
+
 static inline uint64_t
 zink_bo_get_offset(const struct zink_bo *bo)
 {
diff --git a/src/gallium/drivers/zink/zink_resource.c b/src/gallium/drivers/zink/zink_resource.c
index 2645450cfe7..6decdd6fefa 100644
--- a/src/gallium/drivers/zink/zink_resource.c
+++ b/src/gallium/drivers/zink/zink_resource.c
@@ -1299,14 +1299,16 @@ zink_resource_get_param(struct pipe_screen *pscreen, struct pipe_context *pctx,
          break;
    }
 
-   case PIPE_RESOURCE_PARAM_HANDLE_TYPE_KMS:
       return false;
+   case PIPE_RESOURCE_PARAM_HANDLE_TYPE_KMS:
    case PIPE_RESOURCE_PARAM_HANDLE_TYPE_SHARED:
    case PIPE_RESOURCE_PARAM_HANDLE_TYPE_FD: {
 #ifdef ZINK_USE_DMABUF
       memset(&whandle, 0, sizeof(whandle));
       if (param == PIPE_RESOURCE_PARAM_HANDLE_TYPE_SHARED)
          whandle.type = WINSYS_HANDLE_TYPE_SHARED;
+      if (param == PIPE_RESOURCE_PARAM_HANDLE_TYPE_KMS)
+         whandle.type = WINSYS_HANDLE_TYPE_KMS;
       else if (param == PIPE_RESOURCE_PARAM_HANDLE_TYPE_FD)
          whandle.type = WINSYS_HANDLE_TYPE_FD;
 
@@ -1342,7 +1344,7 @@ zink_resource_get_handle(struct pipe_screen *pscreen,
       struct zink_resource_object *obj = res->obj;
 
 #if !defined(_WIN32)
-      if (whandle->type == WINSYS_HANDLE_TYPE_KMS) {
+      if (whandle->type == WINSYS_HANDLE_TYPE_KMS && screen->drm_fd == -1) {
          whandle->handle = -1;
       } else {
          if (!res->obj->exportable) {
@@ -1368,6 +1370,15 @@ zink_resource_get_handle(struct pipe_screen *pscreen,
             mesa_loge("ZINK: vkGetMemoryFdKHR failed");
             return false;
          }
+         if (whandle->type == WINSYS_HANDLE_TYPE_KMS) {
+            uint32_t h;
+            bool ret = zink_bo_get_kms_handle(screen, obj->bo, fd, &h);
+            close(fd);
+            if (!ret)
+               return false;
+            fd = h;
+         }
+
          whandle->handle = fd;
       }
 #else
diff --git a/src/gallium/drivers/zink/zink_screen.h b/src/gallium/drivers/zink/zink_screen.h
index 142c127f3c5..bbc98f0a981 100644
--- a/src/gallium/drivers/zink/zink_screen.h
+++ b/src/gallium/drivers/zink/zink_screen.h
@@ -128,8 +128,6 @@ struct zink_screen {
       struct pb_cache bo_cache;
       struct pb_slabs bo_slabs[NUM_SLAB_ALLOCATORS];
       unsigned min_alloc_size;
-      struct hash_table *bo_export_table;
-      simple_mtx_t bo_export_table_lock;
       uint32_t next_bo_unique_id;
    } pb;
    uint8_t heap_map[VK_MAX_MEMORY_TYPES];



More information about the mesa-commit mailing list