diff --git a/src/gallium/frontends/lavapipe/lvp_android.c b/src/gallium/frontends/lavapipe/lvp_android.c index cc5cbb655de..cf0d3702289 100644 --- a/src/gallium/frontends/lavapipe/lvp_android.c +++ b/src/gallium/frontends/lavapipe/lvp_android.c @@ -30,6 +30,8 @@ #include #include +#include +#include #include "util/libsync.h" #include "util/os_file.h" @@ -37,6 +39,7 @@ #include "vk_fence.h" #include "vk_semaphore.h" +#include "vk_android.h" static int lvp_hal_open(const struct hw_module_t *mod, @@ -175,3 +178,45 @@ lvp_QueueSignalReleaseImageANDROID(VkQueue _queue, return VK_SUCCESS; } + +VkResult +lvp_import_ahb_memory(struct lvp_device *device, struct lvp_device_memory *mem, + const VkImportAndroidHardwareBufferInfoANDROID *info) +{ + const native_handle_t *handle = AHardwareBuffer_getNativeHandle(info->buffer); + int dma_buf = (handle && handle->numFds) ? handle->data[0] : -1; + if (dma_buf < 0) + return VK_ERROR_INVALID_EXTERNAL_HANDLE; + + uint64_t size; + int result = device->pscreen->import_memory_fd(device->pscreen, dma_buf, (struct pipe_memory_allocation**)&mem->pmem, &size, true); + if (!result) + return VK_ERROR_INVALID_EXTERNAL_HANDLE; + + AHardwareBuffer_acquire(info->buffer); + mem->android_hardware_buffer = info->buffer; + mem->size = size; + mem->memory_type = LVP_DEVICE_MEMORY_TYPE_DMA_BUF; + + return VK_SUCCESS; +} + +VkResult +lvp_create_ahb_memory(struct lvp_device *device, struct lvp_device_memory *mem, + const VkMemoryAllocateInfo *pAllocateInfo) +{ + mem->android_hardware_buffer = vk_alloc_ahardware_buffer(pAllocateInfo); + if (mem->android_hardware_buffer == NULL) + return VK_ERROR_OUT_OF_HOST_MEMORY; + + const struct VkImportAndroidHardwareBufferInfoANDROID import_info = { + .buffer = mem->android_hardware_buffer, + }; + + VkResult result = lvp_import_ahb_memory(device, mem, &import_info); + + /* Release a reference to avoid leak for AHB allocation. */ + AHardwareBuffer_release(mem->android_hardware_buffer); + + return result; +} diff --git a/src/gallium/frontends/lavapipe/lvp_device.c b/src/gallium/frontends/lavapipe/lvp_device.c index 844ffb644c2..122378473ec 100644 --- a/src/gallium/frontends/lavapipe/lvp_device.c +++ b/src/gallium/frontends/lavapipe/lvp_device.c @@ -1270,6 +1270,8 @@ lvp_physical_device_init(struct lvp_physical_device *device, device->vk.supported_extensions.KHR_external_semaphore_fd = true; device->vk.supported_extensions.KHR_external_fence_fd = true; } + if (supported_dmabuf_bits & DRM_PRIME_CAP_IMPORT) + device->vk.supported_extensions.ANDROID_external_memory_android_hardware_buffer = true; #endif /* SNORM blending on llvmpipe fails CTS - disable by default */ @@ -1860,6 +1862,9 @@ VKAPI_ATTR VkResult VKAPI_CALL lvp_AllocateMemory( struct lvp_device_memory *mem; ASSERTED const VkExportMemoryAllocateInfo *export_info = NULL; ASSERTED const VkImportMemoryFdInfoKHR *import_info = NULL; +#if DETECT_OS_ANDROID + ASSERTED const VkImportAndroidHardwareBufferInfoANDROID *ahb_import_info = NULL; +#endif const VkImportMemoryHostPointerInfoEXT *host_ptr_info = NULL; VkResult error = VK_ERROR_OUT_OF_DEVICE_MEMORY; assert(pAllocateInfo->sType == VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO); @@ -1890,6 +1895,12 @@ VKAPI_ATTR VkResult VKAPI_CALL lvp_AllocateMemory( priority = get_mem_priority(prio->priority); break; } +#if DETECT_OS_ANDROID + case VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID: { + ahb_import_info = (VkImportAndroidHardwareBufferInfoANDROID*)ext; + break; + } +#endif default: break; } @@ -1912,6 +1923,11 @@ VKAPI_ATTR VkResult VKAPI_CALL lvp_AllocateMemory( mem->memory_type = LVP_DEVICE_MEMORY_TYPE_DEFAULT; mem->backed_fd = -1; mem->size = pAllocateInfo->allocationSize; + +#if DETECT_OS_ANDROID + mem->android_hardware_buffer = NULL; +#endif + if (host_ptr_info) { mem->mem_alloc = (struct llvmpipe_memory_allocation) { .cpu_addr = host_ptr_info->pHostPointer, @@ -1920,6 +1936,18 @@ VKAPI_ATTR VkResult VKAPI_CALL lvp_AllocateMemory( mem->map = host_ptr_info->pHostPointer; mem->memory_type = LVP_DEVICE_MEMORY_TYPE_USER_PTR; } +#if DETECT_OS_ANDROID + else if(ahb_import_info) { + error = lvp_import_ahb_memory(device, mem, ahb_import_info); + if (error != VK_SUCCESS) + goto fail; + } else if(export_info && + (export_info->handleTypes & VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID)) { + error = lvp_create_ahb_memory(device, mem, pAllocateInfo); + if (error != VK_SUCCESS) + goto fail; + } +#endif #ifdef PIPE_MEMORY_FD else if(import_info && import_info->handleType) { bool dmabuf = import_info->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT; diff --git a/src/gallium/frontends/lavapipe/lvp_private.h b/src/gallium/frontends/lavapipe/lvp_private.h index 1d0fc14feeb..806611a15a0 100644 --- a/src/gallium/frontends/lavapipe/lvp_private.h +++ b/src/gallium/frontends/lavapipe/lvp_private.h @@ -49,6 +49,10 @@ #include "drm-uapi/drm_fourcc.h" #endif +#if DETECT_OS_ANDROID +#include +#endif + /* Pre-declarations needed for WSI entrypoints */ struct wl_surface; struct wl_display; @@ -239,6 +243,12 @@ struct lvp_device_memory { void * map; enum lvp_device_memory_type memory_type; int backed_fd; +#ifdef PIPE_MEMORY_FD + struct llvmpipe_memory_allocation *alloc; +#endif +#if DETECT_OS_ANDROID + struct AHardwareBuffer *android_hardware_buffer; +#endif }; struct lvp_pipe_sync { @@ -778,6 +788,15 @@ lvp_nir_lower_sparse_residency(struct nir_shader *shader); enum vk_cmd_type lvp_nv_dgc_token_to_cmd_type(const VkIndirectCommandsLayoutTokenNV *token); +#if DETECT_OS_ANDROID +VkResult +lvp_import_ahb_memory(struct lvp_device *device, struct lvp_device_memory *mem, + const VkImportAndroidHardwareBufferInfoANDROID *info); +VkResult +lvp_create_ahb_memory(struct lvp_device *device, struct lvp_device_memory *mem, + const VkMemoryAllocateInfo *pAllocateInfo); +#endif + #ifdef __cplusplus } #endif