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)
{
*/
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
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,
#include "tu_private.h"
#include <errno.h>
+#include <fcntl.h>
#include <stdint.h>
#include <sys/ioctl.h>
#include <xf86drm.h>
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)
{
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
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