Peng Huang | 84fba7cb | 2020-03-27 16:56:43 | [diff] [blame] | 1 | // Copyright 2020 The Chromium Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #include "gpu/vulkan/vulkan_image.h" |
| 6 | |
| 7 | #include "base/android/android_hardware_buffer_compat.h" |
| 8 | #include "gpu/vulkan/vulkan_device_queue.h" |
| 9 | #include "gpu/vulkan/vulkan_function_pointers.h" |
| 10 | |
| 11 | namespace gpu { |
| 12 | |
| 13 | bool VulkanImage::InitializeFromGpuMemoryBufferHandle( |
| 14 | VulkanDeviceQueue* device_queue, |
| 15 | gfx::GpuMemoryBufferHandle gmb_handle, |
| 16 | const gfx::Size& size, |
| 17 | VkFormat format, |
| 18 | VkImageUsageFlags usage, |
| 19 | VkImageCreateFlags flags, |
| 20 | VkImageTiling image_tiling) { |
| 21 | if (gmb_handle.type != gfx::GpuMemoryBufferType::ANDROID_HARDWARE_BUFFER) { |
| 22 | DLOG(ERROR) << "gmb_handle.type is not supported. type:" << gmb_handle.type; |
| 23 | return false; |
| 24 | } |
| 25 | DCHECK(gmb_handle.android_hardware_buffer.is_valid()); |
| 26 | auto& ahb_handle = gmb_handle.android_hardware_buffer; |
| 27 | |
| 28 | // To obtain format properties of an Android hardware buffer, include an |
| 29 | // instance of VkAndroidHardwareBufferFormatPropertiesANDROID in the pNext |
| 30 | // chain of the VkAndroidHardwareBufferPropertiesANDROID instance passed to |
| 31 | // vkGetAndroidHardwareBufferPropertiesANDROID. |
| 32 | VkAndroidHardwareBufferFormatPropertiesANDROID ahb_format_props = { |
| 33 | VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID, |
| 34 | }; |
| 35 | VkAndroidHardwareBufferPropertiesANDROID ahb_props = { |
| 36 | .sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID, |
| 37 | .pNext = &ahb_format_props, |
| 38 | }; |
| 39 | |
| 40 | VkDevice vk_device = device_queue->GetVulkanDevice(); |
| 41 | VkResult result = vkGetAndroidHardwareBufferPropertiesANDROID( |
| 42 | vk_device, ahb_handle.get(), &ahb_props); |
| 43 | if (result != VK_SUCCESS) { |
| 44 | LOG(ERROR) |
| 45 | << "GetAhbProps: vkGetAndroidHardwareBufferPropertiesANDROID failed : " |
| 46 | << result; |
| 47 | return false; |
| 48 | } |
| 49 | |
| 50 | // To create an image with an external format, include an instance of |
| 51 | // VkExternalFormatANDROID in the pNext chain of VkImageCreateInfo. |
| 52 | VkExternalFormatANDROID external_format = { |
| 53 | .sType = VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID, |
| 54 | // If externalFormat is zero, the effect is as if the |
| 55 | // VkExternalFormatANDROID structure was not present. Otherwise, the image |
| 56 | // will have the specified external format. |
| 57 | .externalFormat = 0, |
| 58 | }; |
| 59 | |
| 60 | // If image has an external format, format must be VK_FORMAT_UNDEFINED. |
| 61 | if (ahb_format_props.format == VK_FORMAT_UNDEFINED) { |
| 62 | // externalFormat must be 0 or a value returned in the externalFormat member |
| 63 | // of VkAndroidHardwareBufferFormatPropertiesANDROID by an earlier call to |
| 64 | // vkGetAndroidHardwareBufferPropertiesANDROID. |
| 65 | external_format.externalFormat = ahb_format_props.externalFormat; |
| 66 | } |
| 67 | |
| 68 | // To define a set of external memory handle types that may be used as backing |
| 69 | // store for an image, add a VkExternalMemoryImageCreateInfo structure to the |
| 70 | // pNext chain of the VkImageCreateInfo structure. |
| 71 | VkExternalMemoryImageCreateInfo external_memory_image_info = { |
| 72 | .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO, |
| 73 | .pNext = &external_format, |
| 74 | .handleTypes = |
| 75 | VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID, |
| 76 | }; |
| 77 | |
| 78 | // Get the AHB description. |
| 79 | AHardwareBuffer_Desc ahb_desc = {}; |
| 80 | base::AndroidHardwareBufferCompat::GetInstance().Describe(ahb_handle.get(), |
| 81 | &ahb_desc); |
| 82 | |
| 83 | // Intended usage of the image. |
| 84 | VkImageUsageFlags usage_flags = 0; |
| 85 | // Get Vulkan Image usage flag equivalence of AHB usage. |
| 86 | if (ahb_desc.usage & AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE) { |
| 87 | usage_flags = usage_flags | VK_IMAGE_USAGE_SAMPLED_BIT | |
| 88 | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; |
| 89 | } |
| 90 | if (ahb_desc.usage & AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT) { |
| 91 | usage_flags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; |
| 92 | } |
| 93 | |
| 94 | // TODO(vikassoni) : AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP is supported from API |
| 95 | // level 28 which is not part of current android_ndk version in chromium. Add |
| 96 | // equivalent VK usage later. |
| 97 | if (!usage_flags) { |
| 98 | LOG(ERROR) << "No valid usage flags found"; |
| 99 | return false; |
| 100 | } |
| 101 | |
| 102 | VkImageCreateFlags create_flags = 0; |
| 103 | if (ahb_desc.usage & AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT) { |
| 104 | create_flags = VK_IMAGE_CREATE_PROTECTED_BIT; |
| 105 | } |
| 106 | |
| 107 | // To import memory created outside of the current Vulkan instance from an |
| 108 | // Android hardware buffer, add a VkImportAndroidHardwareBufferInfoANDROID |
| 109 | // structure to the pNext chain of the VkMemoryAllocateInfo structure. |
| 110 | VkImportAndroidHardwareBufferInfoANDROID ahb_import_info = { |
| 111 | .sType = VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID, |
| 112 | .buffer = ahb_handle.get(), |
| 113 | }; |
| 114 | |
| 115 | VkMemoryRequirements requirements = { |
| 116 | .size = ahb_props.allocationSize, |
| 117 | .memoryTypeBits = ahb_props.memoryTypeBits, |
| 118 | }; |
| 119 | if (!Initialize(device_queue, size, ahb_format_props.format, usage_flags, |
| 120 | create_flags, VK_IMAGE_TILING_OPTIMAL, |
| 121 | &external_memory_image_info, &ahb_import_info, |
| 122 | &requirements)) { |
| 123 | return false; |
| 124 | } |
| 125 | |
| 126 | // VkImage is imported from external. |
| 127 | queue_family_index_ = VK_QUEUE_FAMILY_EXTERNAL; |
| 128 | |
| 129 | if (ahb_format_props.format == VK_FORMAT_UNDEFINED) { |
| 130 | ycbcr_info_.emplace(VK_FORMAT_UNDEFINED, ahb_format_props.externalFormat, |
| 131 | ahb_format_props.suggestedYcbcrModel, |
| 132 | ahb_format_props.suggestedYcbcrRange, |
| 133 | ahb_format_props.suggestedXChromaOffset, |
| 134 | ahb_format_props.suggestedYChromaOffset, |
| 135 | ahb_format_props.formatFeatures); |
| 136 | } |
| 137 | |
| 138 | return true; |
| 139 | } |
| 140 | |
| 141 | } // namespace gpu |