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 
InitializeFromGpuMemoryBufferHandle(VulkanDeviceQueue * device_queue,gfx::GpuMemoryBufferHandle gmb_handle,const gfx::Size & size,VkFormat format,VkImageUsageFlags usage,VkImageCreateFlags flags,VkImageTiling image_tiling)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