turnip: add functions to import/export prime fd
authorChia-I Wu <olvaffe@gmail.com>
Thu, 31 Jan 2019 23:03:03 +0000 (15:03 -0800)
committerChia-I Wu <olvaffe@gmail.com>
Mon, 11 Mar 2019 17:02:13 +0000 (10:02 -0700)
Add tu_bo_init_dmabuf, tu_bo_export_dmabuf, tu_gem_import_dmabuf,
and tu_gem_export_dmabuf.

src/freedreno/vulkan/tu_device.c
src/freedreno/vulkan/tu_drm.c
src/freedreno/vulkan/tu_private.h

index 072da76a602b08b70fcb24c3cf0d0e9934aaeeef..c728f397d5da9b649f4f5aafa79a808717b3bd97 100644 (file)
@@ -73,6 +73,25 @@ tu_get_device_uuid(void *uuid)
    memset(uuid, 0, VK_UUID_SIZE);
 }
 
+static VkResult
+tu_bo_init(struct tu_device *dev,
+           struct tu_bo *bo,
+           uint32_t gem_handle,
+           uint64_t size)
+{
+   uint64_t iova = tu_gem_info_iova(dev, gem_handle);
+   if (!iova)
+      return VK_ERROR_OUT_OF_DEVICE_MEMORY;
+
+   *bo = (struct tu_bo) {
+      .gem_handle = gem_handle,
+      .size = size,
+      .iova = iova,
+   };
+
+   return VK_SUCCESS;
+}
+
 VkResult
 tu_bo_init_new(struct tu_device *dev, struct tu_bo *bo, uint64_t size)
 {
@@ -81,24 +100,40 @@ tu_bo_init_new(struct tu_device *dev, struct tu_bo *bo, uint64_t size)
     */
    uint32_t gem_handle = tu_gem_new(dev, size, MSM_BO_WC);
    if (!gem_handle)
-      goto fail_new;
+      return vk_error(dev->instance, VK_ERROR_OUT_OF_DEVICE_MEMORY);
 
-   uint64_t iova = tu_gem_info_iova(dev, gem_handle);
-   if (!iova)
-      goto fail_info;
+   VkResult result = tu_bo_init(dev, bo, gem_handle, size);
+   if (result != VK_SUCCESS) {
+      tu_gem_close(dev, gem_handle);
+      return vk_error(dev->instance, result);
+   }
 
-   *bo = (struct tu_bo) {
-      .gem_handle = gem_handle,
-      .size = size,
-      .iova = iova,
-   };
+   return VK_SUCCESS;
+}
+
+VkResult
+tu_bo_init_dmabuf(struct tu_device *dev,
+                  struct tu_bo *bo,
+                  uint64_t size,
+                  int fd)
+{
+   uint32_t gem_handle = tu_gem_import_dmabuf(dev, fd, size);
+   if (!gem_handle)
+      return vk_error(dev->instance, VK_ERROR_INVALID_EXTERNAL_HANDLE);
+
+   VkResult result = tu_bo_init(dev, bo, gem_handle, size);
+   if (result != VK_SUCCESS) {
+      tu_gem_close(dev, gem_handle);
+      return vk_error(dev->instance, result);
+   }
 
    return VK_SUCCESS;
+}
 
-fail_info:
-   tu_gem_close(dev, bo->gem_handle);
-fail_new:
-   return vk_error(dev->instance, VK_ERROR_OUT_OF_DEVICE_MEMORY);
+int
+tu_bo_export_dmabuf(struct tu_device *dev, struct tu_bo *bo)
+{
+   return tu_gem_export_dmabuf(dev, bo->gem_handle);
 }
 
 VkResult
@@ -109,7 +144,7 @@ tu_bo_map(struct tu_device *dev, struct tu_bo *bo)
 
    uint64_t offset = tu_gem_info_offset(dev, bo->gem_handle);
    if (!offset)
-          return vk_error(dev->instance, VK_ERROR_OUT_OF_DEVICE_MEMORY);
+      return vk_error(dev->instance, VK_ERROR_OUT_OF_DEVICE_MEMORY);
 
    /* TODO: Should we use the wrapper os_mmap() like Freedreno does? */
    void *map = mmap(0, bo->size, PROT_READ | PROT_WRITE, MAP_SHARED,
index c103561ef1a2c35a75b61e6859718f9d17010cf4..6904b011e710395e0df33681e771277d244eea69 100644 (file)
@@ -25,6 +25,7 @@
 #include "tu_private.h"
 
 #include <errno.h>
+#include <fcntl.h>
 #include <stdint.h>
 #include <sys/ioctl.h>
 #include <xf86drm.h>
@@ -123,6 +124,34 @@ tu_gem_new(const struct tu_device *dev, uint64_t size, uint32_t flags)
    return req.handle;
 }
 
+uint32_t
+tu_gem_import_dmabuf(const struct tu_device *dev, int prime_fd, uint64_t size)
+{
+   /* lseek() to get the real size */
+   off_t real_size = lseek(prime_fd, 0, SEEK_END);
+   lseek(prime_fd, 0, SEEK_SET);
+   if (real_size < 0 || (uint64_t) real_size < size)
+      return 0;
+
+   uint32_t gem_handle;
+   int ret = drmPrimeFDToHandle(dev->physical_device->local_fd, prime_fd,
+                                &gem_handle);
+   if (ret)
+      return 0;
+
+   return gem_handle;
+}
+
+int
+tu_gem_export_dmabuf(const struct tu_device *dev, uint32_t gem_handle)
+{
+   int prime_fd;
+   int ret = drmPrimeHandleToFD(dev->physical_device->local_fd, gem_handle,
+                                DRM_CLOEXEC, &prime_fd);
+
+   return ret == 0 ? prime_fd : -1;
+}
+
 void
 tu_gem_close(const struct tu_device *dev, uint32_t gem_handle)
 {
index 51b52848daf319012afd3d89d65d71c0362b9b29..62f7cf280042d7ec0fae3239332f3e3ad5b1acc6 100644 (file)
@@ -442,6 +442,13 @@ struct tu_bo
 
 VkResult
 tu_bo_init_new(struct tu_device *dev, struct tu_bo *bo, uint64_t size);
+VkResult
+tu_bo_init_dmabuf(struct tu_device *dev,
+                  struct tu_bo *bo,
+                  uint64_t size,
+                  int fd);
+int
+tu_bo_export_dmabuf(struct tu_device *dev, struct tu_bo *bo);
 void
 tu_bo_finish(struct tu_device *dev, struct tu_bo *bo);
 VkResult
@@ -1315,6 +1322,12 @@ tu_drm_submitqueue_close(const struct tu_device *dev, uint32_t queue_id);
 
 uint32_t
 tu_gem_new(const struct tu_device *dev, uint64_t size, uint32_t flags);
+uint32_t
+tu_gem_import_dmabuf(const struct tu_device *dev,
+                     int prime_fd,
+                     uint64_t size);
+int
+tu_gem_export_dmabuf(const struct tu_device *dev, uint32_t gem_handle);
 void
 tu_gem_close(const struct tu_device *dev, uint32_t gem_handle);
 uint64_t