1 /// Copyright (C) 2019 The Android Open Source Project
2 // Copyright (C) 2019 Google Inc.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 #include "AndroidHardwareBuffer.h"
16
17 #include "../OpenglSystemCommon/HostConnection.h"
18
19 #include "vk_format_info.h"
20 #include "vk_util.h"
21
22 namespace goldfish_vk {
23
24 // From Intel ANV implementation.
25 /* Construct ahw usage mask from image usage bits, see
26 * 'AHardwareBuffer Usage Equivalence' in Vulkan spec.
27 */
28 uint64_t
getAndroidHardwareBufferUsageFromVkUsage(const VkImageCreateFlags vk_create,const VkImageUsageFlags vk_usage)29 getAndroidHardwareBufferUsageFromVkUsage(const VkImageCreateFlags vk_create,
30 const VkImageUsageFlags vk_usage)
31 {
32 uint64_t ahw_usage = 0;
33
34 if (vk_usage & VK_IMAGE_USAGE_SAMPLED_BIT)
35 ahw_usage |= AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
36
37 if (vk_usage & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)
38 ahw_usage |= AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
39
40 if (vk_usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)
41 ahw_usage |= AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT;
42
43 if (vk_create & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT)
44 ahw_usage |= AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP;
45
46 if (vk_create & VK_IMAGE_CREATE_PROTECTED_BIT)
47 ahw_usage |= AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT;
48
49 /* No usage bits set - set at least one GPU usage. */
50 if (ahw_usage == 0)
51 ahw_usage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
52
53 return ahw_usage;
54 }
55
getAndroidHardwareBufferPropertiesANDROID(Gralloc * grallocHelper,const HostVisibleMemoryVirtualizationInfo * hostMemVirtInfo,VkDevice,const AHardwareBuffer * buffer,VkAndroidHardwareBufferPropertiesANDROID * pProperties)56 VkResult getAndroidHardwareBufferPropertiesANDROID(
57 Gralloc* grallocHelper,
58 const HostVisibleMemoryVirtualizationInfo* hostMemVirtInfo,
59 VkDevice,
60 const AHardwareBuffer* buffer,
61 VkAndroidHardwareBufferPropertiesANDROID* pProperties) {
62
63 VkAndroidHardwareBufferFormatPropertiesANDROID* ahbFormatProps =
64 vk_find_struct<VkAndroidHardwareBufferFormatPropertiesANDROID>(pProperties);
65
66 if (ahbFormatProps) {
67 AHardwareBuffer_Desc desc;
68 AHardwareBuffer_describe(buffer, &desc);
69
70 const uint64_t gpu_usage =
71 AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE |
72 AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT |
73 AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER;
74
75 if (!(desc.usage & (gpu_usage))) {
76 return VK_ERROR_INVALID_EXTERNAL_HANDLE;
77 }
78
79 ahbFormatProps->format = vk_format_from_android(desc.format);
80 ahbFormatProps->externalFormat = desc.format;
81
82 // The formatFeatures member must include
83 // VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT and at least one of
84 // VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT or
85 // VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT, and should include
86 // VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT and
87 // VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT.
88
89 ahbFormatProps->formatFeatures =
90 VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT |
91 VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT;
92
93 // "Implementations may not always be able to determine the color model,
94 // numerical range, or chroma offsets of the image contents, so the values in
95 // VkAndroidHardwareBufferFormatPropertiesANDROID are only suggestions.
96 // Applications should treat these values as sensible defaults to use in the
97 // absence of more reliable information obtained through some other means."
98
99 ahbFormatProps->samplerYcbcrConversionComponents.r = VK_COMPONENT_SWIZZLE_IDENTITY;
100 ahbFormatProps->samplerYcbcrConversionComponents.g = VK_COMPONENT_SWIZZLE_IDENTITY;
101 ahbFormatProps->samplerYcbcrConversionComponents.b = VK_COMPONENT_SWIZZLE_IDENTITY;
102 ahbFormatProps->samplerYcbcrConversionComponents.a = VK_COMPONENT_SWIZZLE_IDENTITY;
103
104 ahbFormatProps->suggestedYcbcrModel =
105 android_format_is_yuv(desc.format) ?
106 VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601 :
107 VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY;
108 ahbFormatProps->suggestedYcbcrRange = VK_SAMPLER_YCBCR_RANGE_ITU_FULL;
109
110 ahbFormatProps->suggestedXChromaOffset = VK_CHROMA_LOCATION_MIDPOINT;
111 ahbFormatProps->suggestedYChromaOffset = VK_CHROMA_LOCATION_MIDPOINT;
112 }
113
114 const native_handle_t *handle =
115 AHardwareBuffer_getNativeHandle(buffer);
116 uint32_t colorBufferHandle =
117 grallocHelper->getHostHandle(handle);
118 if (!colorBufferHandle) {
119 return VK_ERROR_INVALID_EXTERNAL_HANDLE;
120 }
121
122 // Disallow host visible and noflags heaps for now
123 // (hard to make actual dedicated allocs)
124 uint32_t memoryTypeBits = 0;
125 for (uint32_t i = 0; i < VK_MAX_MEMORY_TYPES; ++i) {
126 if (isNoFlagsMemoryTypeIndexForGuest(hostMemVirtInfo, i)) continue;
127 if (isHostVisibleMemoryTypeIndexForGuest(hostMemVirtInfo, i)) continue;
128 memoryTypeBits |= (1 << i);
129 }
130
131 pProperties->memoryTypeBits = memoryTypeBits;
132 pProperties->allocationSize =
133 grallocHelper->getAllocatedSize(handle);
134
135 return VK_SUCCESS;
136 }
137
138 // Based on Intel ANV implementation.
getMemoryAndroidHardwareBufferANDROID(struct AHardwareBuffer ** pBuffer)139 VkResult getMemoryAndroidHardwareBufferANDROID(struct AHardwareBuffer **pBuffer) {
140
141 /* Some quotes from Vulkan spec:
142 *
143 * "If the device memory was created by importing an Android hardware
144 * buffer, vkGetMemoryAndroidHardwareBufferANDROID must return that same
145 * Android hardware buffer object."
146 *
147 * "VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID must
148 * have been included in VkExportMemoryAllocateInfo::handleTypes when
149 * memory was created."
150 */
151
152 if (!pBuffer) return VK_ERROR_OUT_OF_HOST_MEMORY;
153 if (!(*pBuffer)) return VK_ERROR_OUT_OF_HOST_MEMORY;
154
155 AHardwareBuffer_acquire(*pBuffer);
156 return VK_SUCCESS;
157 }
158
importAndroidHardwareBuffer(Gralloc * grallocHelper,const VkImportAndroidHardwareBufferInfoANDROID * info,struct AHardwareBuffer ** importOut)159 VkResult importAndroidHardwareBuffer(
160 Gralloc* grallocHelper,
161 const VkImportAndroidHardwareBufferInfoANDROID* info,
162 struct AHardwareBuffer **importOut) {
163
164 if (!info || !info->buffer) {
165 return VK_ERROR_INVALID_EXTERNAL_HANDLE;
166 }
167
168 uint32_t colorBufferHandle =
169 grallocHelper->getHostHandle(
170 AHardwareBuffer_getNativeHandle(info->buffer));
171 if (!colorBufferHandle) {
172 return VK_ERROR_INVALID_EXTERNAL_HANDLE;
173 }
174
175 auto ahb = info->buffer;
176
177 AHardwareBuffer_acquire(ahb);
178
179 if (importOut) *importOut = ahb;
180
181 return VK_SUCCESS;
182 }
183
createAndroidHardwareBuffer(bool hasDedicatedImage,bool hasDedicatedBuffer,const VkExtent3D & imageExtent,uint32_t imageLayers,VkFormat imageFormat,VkImageUsageFlags imageUsage,VkImageCreateFlags imageCreateFlags,VkDeviceSize bufferSize,VkDeviceSize allocationInfoAllocSize,struct AHardwareBuffer ** out)184 VkResult createAndroidHardwareBuffer(
185 bool hasDedicatedImage,
186 bool hasDedicatedBuffer,
187 const VkExtent3D& imageExtent,
188 uint32_t imageLayers,
189 VkFormat imageFormat,
190 VkImageUsageFlags imageUsage,
191 VkImageCreateFlags imageCreateFlags,
192 VkDeviceSize bufferSize,
193 VkDeviceSize allocationInfoAllocSize,
194 struct AHardwareBuffer **out) {
195
196 uint32_t w = 0;
197 uint32_t h = 1;
198 uint32_t layers = 1;
199 uint32_t format = 0;
200 uint64_t usage = 0;
201
202 /* If caller passed dedicated information. */
203 if (hasDedicatedImage) {
204 w = imageExtent.width;
205 h = imageExtent.height;
206 layers = imageLayers;
207 format = android_format_from_vk(imageFormat);
208 usage = getAndroidHardwareBufferUsageFromVkUsage(imageCreateFlags, imageUsage);
209 } else if (hasDedicatedBuffer) {
210 w = bufferSize;
211 format = AHARDWAREBUFFER_FORMAT_BLOB;
212 usage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN |
213 AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN |
214 AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER;
215 } else {
216 w = allocationInfoAllocSize;
217 format = AHARDWAREBUFFER_FORMAT_BLOB;
218 usage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN |
219 AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN |
220 AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER;
221 }
222
223 struct AHardwareBuffer *ahw = NULL;
224 struct AHardwareBuffer_Desc desc = {
225 .width = w,
226 .height = h,
227 .layers = layers,
228 .format = format,
229 .usage = usage,
230 };
231
232 if (AHardwareBuffer_allocate(&desc, &ahw) != 0) {
233 return VK_ERROR_OUT_OF_HOST_MEMORY;
234 }
235
236 *out = ahw;
237
238 return VK_SUCCESS;
239 }
240
241 } // namespace goldfish_vk
242