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.
This commit is contained in:
Chia-I Wu 2019-01-31 15:03:03 -08:00
parent d5239bc59c
commit de89436216
3 changed files with 92 additions and 15 deletions

View File

@ -73,19 +73,15 @@ tu_get_device_uuid(void *uuid)
memset(uuid, 0, VK_UUID_SIZE);
}
VkResult
tu_bo_init_new(struct tu_device *dev, struct tu_bo *bo, uint64_t size)
static VkResult
tu_bo_init(struct tu_device *dev,
struct tu_bo *bo,
uint32_t gem_handle,
uint64_t size)
{
/* TODO: Choose better flags. As of 2018-11-12, freedreno/drm/msm_bo.c
* always sets `flags = MSM_BO_WC`, and we copy that behavior here.
*/
uint32_t gem_handle = tu_gem_new(dev, size, MSM_BO_WC);
if (!gem_handle)
goto fail_new;
uint64_t iova = tu_gem_info_iova(dev, gem_handle);
if (!iova)
goto fail_info;
return VK_ERROR_OUT_OF_DEVICE_MEMORY;
*bo = (struct tu_bo) {
.gem_handle = gem_handle,
@ -94,11 +90,50 @@ tu_bo_init_new(struct tu_device *dev, struct tu_bo *bo, uint64_t size)
};
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);
VkResult
tu_bo_init_new(struct tu_device *dev, struct tu_bo *bo, uint64_t size)
{
/* TODO: Choose better flags. As of 2018-11-12, freedreno/drm/msm_bo.c
* always sets `flags = MSM_BO_WC`, and we copy that behavior here.
*/
uint32_t gem_handle = tu_gem_new(dev, size, MSM_BO_WC);
if (!gem_handle)
return vk_error(dev->instance, VK_ERROR_OUT_OF_DEVICE_MEMORY);
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;
}
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;
}
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,

View 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)
{

View 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