// // Copyright 2020 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // // vk_android_utils.cpp: Vulkan utilities for using the Android platform #include "libANGLE/renderer/vulkan/android/vk_android_utils.h" #include "common/android_util.h" #include "libANGLE/renderer/vulkan/ContextVk.h" #include "libANGLE/renderer/vulkan/vk_renderer.h" #include "libANGLE/renderer/vulkan/vk_utils.h" #if defined(ANGLE_PLATFORM_ANDROID) # include "libANGLE/Display.h" # include "libANGLE/renderer/vulkan/android/AHBFunctions.h" # include "libANGLE/renderer/vulkan/android/DisplayVkAndroid.h" #endif namespace rx { namespace vk { namespace { #if defined(ANGLE_PLATFORM_ANDROID) DisplayVkAndroid *GetDisplayVkAndroid(Renderer *renderer) { DisplayVk *displayVk = static_cast(renderer->getGlobalOps()); return static_cast(displayVk); } #endif } // anonymous namespace angle::Result GetClientBufferMemoryRequirements(ErrorContext *context, const AHardwareBuffer *hardwareBuffer, VkMemoryRequirements &memRequirements) { #if defined(ANGLE_PLATFORM_ANDROID) const AHBFunctions &ahbFunctions = GetDisplayVkAndroid(context->getRenderer())->getAHBFunctions(); ASSERT(ahbFunctions.valid()); AHardwareBuffer_Desc aHardwareBufferDescription = {}; ahbFunctions.describe(hardwareBuffer, &aHardwareBufferDescription); if (aHardwareBufferDescription.format != AHARDWAREBUFFER_FORMAT_BLOB) { ERR() << "Trying to import non-BLOB AHB as client buffer."; return angle::Result::Stop; } // Get Android Buffer Properties VkAndroidHardwareBufferPropertiesANDROID bufferProperties = {}; bufferProperties.sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID; bufferProperties.pNext = nullptr; VkDevice device = context->getRenderer()->getDevice(); ANGLE_VK_TRY(context, vkGetAndroidHardwareBufferPropertiesANDROID(device, hardwareBuffer, &bufferProperties)); memRequirements.size = bufferProperties.allocationSize; memRequirements.alignment = 0; memRequirements.memoryTypeBits = bufferProperties.memoryTypeBits; return angle::Result::Continue; #else ANGLE_VK_UNREACHABLE(context); return angle::Result::Stop; #endif } angle::Result InitAndroidExternalMemory(ErrorContext *context, EGLClientBuffer clientBuffer, VkMemoryPropertyFlags memoryProperties, Buffer *buffer, VkMemoryPropertyFlags *memoryPropertyFlagsOut, uint32_t *memoryTypeIndexOut, DeviceMemory *deviceMemoryOut, VkDeviceSize *sizeOut) { #if defined(ANGLE_PLATFORM_ANDROID) const AHBFunctions &functions = GetDisplayVkAndroid(context->getRenderer())->getAHBFunctions(); ASSERT(functions.valid()); struct AHardwareBuffer *hardwareBuffer = angle::android::ClientBufferToAHardwareBuffer(clientBuffer); VkMemoryRequirements externalMemoryRequirements = {}; ANGLE_TRY( GetClientBufferMemoryRequirements(context, hardwareBuffer, externalMemoryRequirements)); // Import Vulkan DeviceMemory from Android Hardware Buffer. VkImportAndroidHardwareBufferInfoANDROID importHardwareBufferInfo = {}; importHardwareBufferInfo.sType = VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID; importHardwareBufferInfo.buffer = hardwareBuffer; // Configure dedicated memory allocation for the external buffer and append it to the AHB info. VkMemoryDedicatedAllocateInfo dedicatedAllocateInfo = {}; dedicatedAllocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO; dedicatedAllocateInfo.buffer = buffer->getHandle(); importHardwareBufferInfo.pNext = &dedicatedAllocateInfo; ANGLE_VK_TRY(context, AllocateBufferMemoryWithRequirements( context, MemoryAllocationType::BufferExternal, memoryProperties, externalMemoryRequirements, &importHardwareBufferInfo, buffer, memoryPropertyFlagsOut, memoryTypeIndexOut, deviceMemoryOut)); *sizeOut = externalMemoryRequirements.size; functions.acquire(hardwareBuffer); return angle::Result::Continue; #else ANGLE_VK_UNREACHABLE(context); return angle::Result::Stop; #endif } void ReleaseAndroidExternalMemory(Renderer *renderer, EGLClientBuffer clientBuffer) { #if defined(ANGLE_PLATFORM_ANDROID) const AHBFunctions &functions = GetDisplayVkAndroid(renderer)->getAHBFunctions(); ASSERT(functions.valid()); struct AHardwareBuffer *hardwareBuffer = angle::android::ClientBufferToAHardwareBuffer(clientBuffer); functions.release(hardwareBuffer); #endif } } // namespace vk } // namespace rx