aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/freedreno/vulkan/tu_device.c63
-rw-r--r--src/freedreno/vulkan/tu_drm.c29
-rw-r--r--src/freedreno/vulkan/tu_private.h13
3 files changed, 91 insertions, 14 deletions
diff --git a/src/freedreno/vulkan/tu_device.c b/src/freedreno/vulkan/tu_device.c
index 072da76a602..c728f397d5d 100644
--- a/src/freedreno/vulkan/tu_device.c
+++ b/src/freedreno/vulkan/tu_device.c
@@ -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,
diff --git a/src/freedreno/vulkan/tu_drm.c b/src/freedreno/vulkan/tu_drm.c
index c103561ef1a..6904b011e71 100644
--- a/src/freedreno/vulkan/tu_drm.c
+++ b/src/freedreno/vulkan/tu_drm.c
@@ -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)
{
diff --git a/src/freedreno/vulkan/tu_private.h b/src/freedreno/vulkan/tu_private.h
index 51b52848daf..62f7cf28004 100644
--- a/src/freedreno/vulkan/tu_private.h
+++ b/src/freedreno/vulkan/tu_private.h
@@ -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