Mesa (master): radv/android: Add android hardware buffer import/export.

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Thu Oct 10 17:03:31 UTC 2019


Module: Mesa
Branch: master
Commit: 83a012b60316c80ab8f4f882338cc797b9bd04ec
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=83a012b60316c80ab8f4f882338cc797b9bd04ec

Author: Bas Nieuwenhuizen <basni at chromium.org>
Date:   Wed Jul 10 14:45:01 2019 +0200

radv/android: Add android hardware buffer import/export.

Support does not include images yet.

Reviewed-by: Samuel Pitoiset <samuel.pitoiset at gmail.com>

---

 src/amd/vulkan/radv_android.c | 126 ++++++++++++++++++++++++++++++++++++++++++
 src/amd/vulkan/radv_device.c  |  26 ++++++---
 src/amd/vulkan/radv_private.h |  11 ++++
 3 files changed, 156 insertions(+), 7 deletions(-)

diff --git a/src/amd/vulkan/radv_android.c b/src/amd/vulkan/radv_android.c
index 7833e6d8922..f2fbeab459d 100644
--- a/src/amd/vulkan/radv_android.c
+++ b/src/amd/vulkan/radv_android.c
@@ -415,6 +415,27 @@ vk_format_from_android(unsigned android_format, unsigned android_usage)
 	}
 }
 
+static inline unsigned
+android_format_from_vk(unsigned vk_format)
+{
+   switch (vk_format) {
+   case VK_FORMAT_R8G8B8A8_UNORM:
+      return AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
+   case VK_FORMAT_R8G8B8_UNORM:
+      return AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM;
+   case VK_FORMAT_R5G6B5_UNORM_PACK16:
+      return AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM;
+   case VK_FORMAT_R16G16B16A16_SFLOAT:
+      return AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT;
+   case VK_FORMAT_A2B10G10R10_UNORM_PACK32:
+      return AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM;
+   case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
+      return AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420;
+   default:
+      return AHARDWAREBUFFER_FORMAT_BLOB;
+   }
+}
+
 uint64_t
 radv_ahb_usage_from_vk_usage(const VkImageCreateFlags vk_create,
                              const VkImageUsageFlags vk_usage)
@@ -599,3 +620,108 @@ radv_select_android_external_format(const void *next, VkFormat default_format)
 
 	return default_format;
 }
+
+
+VkResult
+radv_import_ahb_memory(struct radv_device *device,
+                       struct radv_device_memory *mem,
+                       unsigned priority,
+                       const VkImportAndroidHardwareBufferInfoANDROID *info)
+{
+#if RADV_SUPPORT_ANDROID_HARDWARE_BUFFER
+	/* Import from AHardwareBuffer to radv_device_memory. */
+	const native_handle_t *handle =
+		AHardwareBuffer_getNativeHandle(info->buffer);
+
+	/* NOTE - We support buffers with only one handle but do not error on
+	 * multiple handle case. Reason is that we want to support YUV formats
+	 * where we have many logical planes but they all point to the same
+	 * buffer, like is the case with VK_FORMAT_G8_B8R8_2PLANE_420_UNORM.
+	 */
+	int dma_buf = (handle && handle->numFds) ? handle->data[0] : -1;
+	if (dma_buf < 0)
+		return VK_ERROR_INVALID_EXTERNAL_HANDLE;
+
+	mem->bo = device->ws->buffer_from_fd(device->ws, dma_buf,
+	                                     priority);
+	if (!mem->bo)
+		return VK_ERROR_OUT_OF_HOST_MEMORY;
+
+	/* "If the vkAllocateMemory command succeeds, the implementation must
+	 * acquire a reference to the imported hardware buffer, which it must
+	 * release when the device memory object is freed. If the command fails,
+	 * the implementation must not retain a reference."
+	 */
+	AHardwareBuffer_acquire(info->buffer);
+	mem->android_hardware_buffer = info->buffer;
+
+	return VK_SUCCESS;
+#else /* RADV_SUPPORT_ANDROID_HARDWARE_BUFFER */
+	return VK_ERROR_EXTENSION_NOT_PRESENT;
+#endif
+}
+
+VkResult
+radv_create_ahb_memory(struct radv_device *device,
+                       struct radv_device_memory *mem,
+                       unsigned priority,
+                       const VkMemoryAllocateInfo *pAllocateInfo)
+{
+#if RADV_SUPPORT_ANDROID_HARDWARE_BUFFER
+	const VkMemoryDedicatedAllocateInfo *dedicated_info =
+		vk_find_struct_const(pAllocateInfo->pNext,
+		                     MEMORY_DEDICATED_ALLOCATE_INFO);
+
+	uint32_t w = 0;
+	uint32_t h = 1;
+	uint32_t layers = 1;
+	uint32_t format = 0;
+	uint64_t usage = 0;
+
+	/* If caller passed dedicated information. */
+	if (dedicated_info && dedicated_info->image) {
+		RADV_FROM_HANDLE(radv_image, image, dedicated_info->image);
+		w = image->info.width;
+		h = image->info.height;
+		layers = image->info.array_size;
+		format = android_format_from_vk(image->vk_format);
+		usage = radv_ahb_usage_from_vk_usage(image->flags, image->usage);
+	} else if (dedicated_info && dedicated_info->buffer) {
+		RADV_FROM_HANDLE(radv_buffer, buffer, dedicated_info->buffer);
+		w = buffer->size;
+		format = AHARDWAREBUFFER_FORMAT_BLOB;
+		usage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN |
+		        AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN;
+	} else {
+		w = pAllocateInfo->allocationSize;
+		format = AHARDWAREBUFFER_FORMAT_BLOB;
+		usage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN |
+		        AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN;
+	}
+
+	struct AHardwareBuffer *android_hardware_buffer = NULL;
+	struct AHardwareBuffer_Desc desc = {
+		.width = w,
+		.height = h,
+		.layers = layers,
+		.format = format,
+		.usage = usage,
+	};
+
+	if (AHardwareBuffer_allocate(&desc, &android_hardware_buffer) != 0)
+		return VK_ERROR_OUT_OF_HOST_MEMORY;
+
+	mem->android_hardware_buffer = android_hardware_buffer;
+
+	const struct VkImportAndroidHardwareBufferInfoANDROID import_info = {
+		.buffer = mem->android_hardware_buffer,
+	};
+
+	VkResult result = radv_import_ahb_memory(device, mem, priority, &import_info);
+	if (result != VK_SUCCESS)
+		AHardwareBuffer_release(mem->android_hardware_buffer);
+	return result;
+#else /* RADV_SUPPORT_ANDROID_HARDWARE_BUFFER */
+	return VK_ERROR_EXTENSION_NOT_PRESENT;
+#endif
+}
diff --git a/src/amd/vulkan/radv_device.c b/src/amd/vulkan/radv_device.c
index b953f63e216..b44b5cc6a9d 100644
--- a/src/amd/vulkan/radv_device.c
+++ b/src/amd/vulkan/radv_device.c
@@ -3454,24 +3454,28 @@ static VkResult radv_alloc_memory(struct radv_device *device,
 
 	assert(pAllocateInfo->sType == VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO);
 
-	if (pAllocateInfo->allocationSize == 0) {
-		/* Apparently, this is allowed */
-		*pMem = VK_NULL_HANDLE;
-		return VK_SUCCESS;
-	}
-
 	const VkImportMemoryFdInfoKHR *import_info =
 		vk_find_struct_const(pAllocateInfo->pNext, IMPORT_MEMORY_FD_INFO_KHR);
 	const VkMemoryDedicatedAllocateInfo *dedicate_info =
 		vk_find_struct_const(pAllocateInfo->pNext, MEMORY_DEDICATED_ALLOCATE_INFO);
 	const VkExportMemoryAllocateInfo *export_info =
 		vk_find_struct_const(pAllocateInfo->pNext, EXPORT_MEMORY_ALLOCATE_INFO);
+	const struct VkImportAndroidHardwareBufferInfoANDROID *ahb_import_info =
+		vk_find_struct_const(pAllocateInfo->pNext,
+		                     IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID);
 	const VkImportMemoryHostPointerInfoEXT *host_ptr_info =
 		vk_find_struct_const(pAllocateInfo->pNext, IMPORT_MEMORY_HOST_POINTER_INFO_EXT);
 
 	const struct wsi_memory_allocate_info *wsi_info =
 		vk_find_struct_const(pAllocateInfo->pNext, WSI_MEMORY_ALLOCATE_INFO_MESA);
 
+	if (pAllocateInfo->allocationSize == 0 && !ahb_import_info &&
+	    !(export_info && (export_info->handleTypes & VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID))) {
+		/* Apparently, this is allowed */
+		*pMem = VK_NULL_HANDLE;
+		return VK_SUCCESS;
+	}
+
 	mem = vk_zalloc2(&device->alloc, pAllocator, sizeof(*mem), 8,
 			  VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
 	if (mem == NULL)
@@ -3505,7 +3509,15 @@ static VkResult radv_alloc_memory(struct radv_device *device,
 	mem->android_hardware_buffer = NULL;
 #endif
 
-	if (import_info) {
+	if (ahb_import_info) {
+		result = radv_import_ahb_memory(device, mem, priority, ahb_import_info);
+		if (result != VK_SUCCESS)
+			goto fail;
+	} else if(export_info && (export_info->handleTypes & VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID)) {
+		result = radv_create_ahb_memory(device, mem, priority, pAllocateInfo);
+		if (result != VK_SUCCESS)
+			goto fail;
+	} else if (import_info) {
 		assert(import_info->handleType ==
 		       VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT ||
 		       import_info->handleType ==
diff --git a/src/amd/vulkan/radv_private.h b/src/amd/vulkan/radv_private.h
index f0a5fc19604..51b7d7953ef 100644
--- a/src/amd/vulkan/radv_private.h
+++ b/src/amd/vulkan/radv_private.h
@@ -76,6 +76,7 @@ typedef uint32_t xcb_window_t;
 
 #include <vulkan/vulkan.h>
 #include <vulkan/vulkan_intel.h>
+#include <vulkan/vulkan_android.h>
 #include <vulkan/vk_icd.h>
 #include <vulkan/vk_android_native_buffer.h>
 
@@ -1927,6 +1928,16 @@ radv_image_from_gralloc(VkDevice device_h,
 uint64_t
 radv_ahb_usage_from_vk_usage(const VkImageCreateFlags vk_create,
                              const VkImageUsageFlags vk_usage);
+VkResult
+radv_import_ahb_memory(struct radv_device *device,
+                       struct radv_device_memory *mem,
+                       unsigned priority,
+                       const VkImportAndroidHardwareBufferInfoANDROID *info);
+VkResult
+radv_create_ahb_memory(struct radv_device *device,
+                       struct radv_device_memory *mem,
+                       unsigned priority,
+                       const VkMemoryAllocateInfo *pAllocateInfo);
 
 VkFormat
 radv_select_android_external_format(const void *next, VkFormat default_format);




More information about the mesa-commit mailing list