From: Chia-I Wu Date: Thu, 31 Jan 2019 23:03:03 +0000 (-0800) Subject: turnip: add functions to import/export prime fd X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=de89436216e178b616aa3969e3d68b24b60602fd;p=mesa.git turnip: add functions to import/export prime fd Add tu_bo_init_dmabuf, tu_bo_export_dmabuf, tu_gem_import_dmabuf, and tu_gem_export_dmabuf. --- 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 +#include #include #include #include @@ -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