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 #if !defined(HOST_BUILD)
18 #if defined(__ANDROID__) || defined(__linux__)
19 #include <drm_fourcc.h>
20 #define DRM_FORMAT_YVU420_ANDROID fourcc_code('9', '9', '9', '7')
21 #endif
22 #endif
23
24 #include "../OpenglSystemCommon/HostConnection.h"
25
26 #include "vk_format_info.h"
27 #include "vk_util.h"
28 #include <assert.h>
29
30 namespace gfxstream {
31 namespace vk {
32
33 // From Intel ANV implementation.
34 /* Construct ahw usage mask from image usage bits, see
35 * 'AHardwareBuffer Usage Equivalence' in Vulkan spec.
36 */
37 uint64_t
getAndroidHardwareBufferUsageFromVkUsage(const VkImageCreateFlags vk_create,const VkImageUsageFlags vk_usage)38 getAndroidHardwareBufferUsageFromVkUsage(const VkImageCreateFlags vk_create,
39 const VkImageUsageFlags vk_usage)
40 {
41 uint64_t ahw_usage = 0;
42
43 if (vk_usage & VK_IMAGE_USAGE_SAMPLED_BIT)
44 ahw_usage |= AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
45
46 if (vk_usage & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)
47 ahw_usage |= AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
48
49 if (vk_usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)
50 ahw_usage |= AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT;
51
52 if (vk_create & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT)
53 ahw_usage |= AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP;
54
55 if (vk_create & VK_IMAGE_CREATE_PROTECTED_BIT)
56 ahw_usage |= AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT;
57
58 /* No usage bits set - set at least one GPU usage. */
59 if (ahw_usage == 0)
60 ahw_usage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
61
62 return ahw_usage;
63 }
64
updateMemoryTypeBits(uint32_t * memoryTypeBits,uint32_t colorBufferMemoryIndex)65 void updateMemoryTypeBits(uint32_t* memoryTypeBits, uint32_t colorBufferMemoryIndex) {
66 *memoryTypeBits = 1u << colorBufferMemoryIndex;
67 }
68
getAndroidHardwareBufferPropertiesANDROID(Gralloc * grallocHelper,const AHardwareBuffer * buffer,VkAndroidHardwareBufferPropertiesANDROID * pProperties)69 VkResult getAndroidHardwareBufferPropertiesANDROID(
70 Gralloc* grallocHelper,
71 const AHardwareBuffer* buffer,
72 VkAndroidHardwareBufferPropertiesANDROID* pProperties) {
73
74 const native_handle_t *handle =
75 AHardwareBuffer_getNativeHandle(buffer);
76
77 VkAndroidHardwareBufferFormatPropertiesANDROID* ahbFormatProps =
78 vk_find_struct<VkAndroidHardwareBufferFormatPropertiesANDROID>(pProperties);
79
80 if (ahbFormatProps) {
81 AHardwareBuffer_Desc desc;
82 AHardwareBuffer_describe(buffer, &desc);
83
84 const uint64_t gpu_usage =
85 AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE |
86 AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT |
87 AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER;
88
89 if (!(desc.usage & (gpu_usage))) {
90 return VK_ERROR_INVALID_EXTERNAL_HANDLE;
91 }
92 switch(desc.format) {
93 case AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM:
94 ahbFormatProps->format = VK_FORMAT_R8G8B8A8_UNORM;
95 break;
96 case AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM:
97 ahbFormatProps->format = VK_FORMAT_R8G8B8A8_UNORM;
98 break;
99 case AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM:
100 ahbFormatProps->format = VK_FORMAT_R8G8B8_UNORM;
101 break;
102 case AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM:
103 ahbFormatProps->format = VK_FORMAT_R5G6B5_UNORM_PACK16;
104 break;
105 case AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT:
106 ahbFormatProps->format = VK_FORMAT_R16G16B16A16_SFLOAT;
107 break;
108 case AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM:
109 ahbFormatProps->format = VK_FORMAT_A2B10G10R10_UNORM_PACK32;
110 break;
111 case AHARDWAREBUFFER_FORMAT_D16_UNORM:
112 ahbFormatProps->format = VK_FORMAT_D16_UNORM;
113 break;
114 case AHARDWAREBUFFER_FORMAT_D24_UNORM:
115 ahbFormatProps->format = VK_FORMAT_X8_D24_UNORM_PACK32;
116 break;
117 case AHARDWAREBUFFER_FORMAT_D24_UNORM_S8_UINT:
118 ahbFormatProps->format = VK_FORMAT_D24_UNORM_S8_UINT;
119 break;
120 case AHARDWAREBUFFER_FORMAT_D32_FLOAT:
121 ahbFormatProps->format = VK_FORMAT_D32_SFLOAT;
122 break;
123 case AHARDWAREBUFFER_FORMAT_D32_FLOAT_S8_UINT:
124 ahbFormatProps->format = VK_FORMAT_D32_SFLOAT_S8_UINT;
125 break;
126 case AHARDWAREBUFFER_FORMAT_S8_UINT:
127 ahbFormatProps->format = VK_FORMAT_S8_UINT;
128 break;
129 default:
130 ahbFormatProps->format = VK_FORMAT_UNDEFINED;
131 }
132 ahbFormatProps->externalFormat = desc.format;
133
134 // The formatFeatures member must include
135 // VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT and at least one of
136 // VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT or
137 // VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT, and should include
138 // VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT and
139 // VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT.
140
141 // org.skia.skqp.SkQPRunner#UnitTest_VulkanHardwareBuffer* requires the following:
142 // VK_FORMAT_FEATURE_TRANSFER_SRC_BIT
143 // VK_FORMAT_FEATURE_TRANSFER_DST_BIT
144 // VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT
145 ahbFormatProps->formatFeatures =
146 VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT |
147 VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT |
148 VK_FORMAT_FEATURE_TRANSFER_SRC_BIT |
149 VK_FORMAT_FEATURE_TRANSFER_DST_BIT |
150 VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT;
151
152 // "Implementations may not always be able to determine the color model,
153 // numerical range, or chroma offsets of the image contents, so the values in
154 // VkAndroidHardwareBufferFormatPropertiesANDROID are only suggestions.
155 // Applications should treat these values as sensible defaults to use in the
156 // absence of more reliable information obtained through some other means."
157
158 ahbFormatProps->samplerYcbcrConversionComponents.r = VK_COMPONENT_SWIZZLE_IDENTITY;
159 ahbFormatProps->samplerYcbcrConversionComponents.g = VK_COMPONENT_SWIZZLE_IDENTITY;
160 ahbFormatProps->samplerYcbcrConversionComponents.b = VK_COMPONENT_SWIZZLE_IDENTITY;
161 ahbFormatProps->samplerYcbcrConversionComponents.a = VK_COMPONENT_SWIZZLE_IDENTITY;
162
163 #if !defined(HOST_BUILD)
164 #if defined(__ANDROID__) || defined(__linux__)
165 if (android_format_is_yuv(desc.format)) {
166 uint32_t drmFormat = grallocHelper->getFormatDrmFourcc(handle);
167 if (drmFormat) {
168 // The host renderer is not aware of the plane ordering for YUV formats used
169 // in the guest and simply knows that the format "layout" is one of:
170 //
171 // * VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16
172 // * VK_FORMAT_G8_B8R8_2PLANE_420_UNORM
173 // * VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM
174 //
175 // With this, the guest needs to adjust the component swizzle based on plane
176 // ordering to ensure that the channels are interpreted correctly.
177 //
178 // From the Vulkan spec's "Sampler Y'CBCR Conversion" section:
179 //
180 // * Y comes from the G-channel (after swizzle)
181 // * U (CB) comes from the B-channel (after swizzle)
182 // * V (CR) comes from the R-channel (after swizzle)
183 //
184 // See https://www.khronos.org/registry/vulkan/specs/1.3-extensions/html/vkspec.html#textures-sampler-YCbCr-conversion
185 //
186 // To match the above, the guest needs to swizzle such that:
187 //
188 // * Y ends up in the G-channel
189 // * U (CB) ends up in the B-channel
190 // * V (CB) ends up in the R-channel
191 switch (drmFormat) {
192 case DRM_FORMAT_NV12:
193 // NV12 is a Y-plane followed by a interleaved UV-plane and is
194 // VK_FORMAT_G8_B8R8_2PLANE_420_UNORM on the host.
195 case DRM_FORMAT_P010:
196 // P010 is a Y-plane followed by a interleaved UV-plane and is
197 // VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16 on the host.
198 break;
199
200 case DRM_FORMAT_NV21:
201 // NV21 is a Y-plane followed by a interleaved VU-plane and is
202 // VK_FORMAT_G8_B8R8_2PLANE_420_UNORM on the host.
203 case DRM_FORMAT_YVU420:
204 // YV12 is a Y-plane, then a V-plane, and then a U-plane and is
205 // VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM on the host.
206 case DRM_FORMAT_YVU420_ANDROID:
207 // DRM_FORMAT_YVU420_ANDROID is the same as DRM_FORMAT_YVU420 with
208 // Android's extra alignement requirements.
209 ahbFormatProps->samplerYcbcrConversionComponents.r = VK_COMPONENT_SWIZZLE_B;
210 ahbFormatProps->samplerYcbcrConversionComponents.b = VK_COMPONENT_SWIZZLE_R;
211 break;
212
213 default:
214 ALOGE("%s: Unhandled YUV drm format:%" PRIu32, __FUNCTION__, drmFormat);
215 break;
216 }
217 }
218 }
219 #endif
220 #endif
221
222 ahbFormatProps->suggestedYcbcrModel =
223 android_format_is_yuv(desc.format) ?
224 VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601 :
225 VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY;
226 ahbFormatProps->suggestedYcbcrRange = VK_SAMPLER_YCBCR_RANGE_ITU_FULL;
227
228 ahbFormatProps->suggestedXChromaOffset = VK_CHROMA_LOCATION_MIDPOINT;
229 ahbFormatProps->suggestedYChromaOffset = VK_CHROMA_LOCATION_MIDPOINT;
230 }
231
232 uint32_t colorBufferHandle =
233 grallocHelper->getHostHandle(handle);
234 if (!colorBufferHandle) {
235 return VK_ERROR_INVALID_EXTERNAL_HANDLE;
236 }
237
238 pProperties->allocationSize =
239 grallocHelper->getAllocatedSize(handle);
240
241 return VK_SUCCESS;
242 }
243
244 // Based on Intel ANV implementation.
getMemoryAndroidHardwareBufferANDROID(struct AHardwareBuffer ** pBuffer)245 VkResult getMemoryAndroidHardwareBufferANDROID(struct AHardwareBuffer **pBuffer) {
246
247 /* Some quotes from Vulkan spec:
248 *
249 * "If the device memory was created by importing an Android hardware
250 * buffer, vkGetMemoryAndroidHardwareBufferANDROID must return that same
251 * Android hardware buffer object."
252 *
253 * "VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID must
254 * have been included in VkExportMemoryAllocateInfo::handleTypes when
255 * memory was created."
256 */
257
258 if (!pBuffer) return VK_ERROR_OUT_OF_HOST_MEMORY;
259 if (!(*pBuffer)) return VK_ERROR_OUT_OF_HOST_MEMORY;
260
261 AHardwareBuffer_acquire(*pBuffer);
262 return VK_SUCCESS;
263 }
264
importAndroidHardwareBuffer(Gralloc * grallocHelper,const VkImportAndroidHardwareBufferInfoANDROID * info,struct AHardwareBuffer ** importOut)265 VkResult importAndroidHardwareBuffer(
266 Gralloc* grallocHelper,
267 const VkImportAndroidHardwareBufferInfoANDROID* info,
268 struct AHardwareBuffer **importOut) {
269
270 if (!info || !info->buffer) {
271 return VK_ERROR_INVALID_EXTERNAL_HANDLE;
272 }
273
274 uint32_t colorBufferHandle =
275 grallocHelper->getHostHandle(
276 AHardwareBuffer_getNativeHandle(info->buffer));
277 if (!colorBufferHandle) {
278 return VK_ERROR_INVALID_EXTERNAL_HANDLE;
279 }
280
281 auto ahb = info->buffer;
282
283 AHardwareBuffer_acquire(ahb);
284
285 if (importOut) *importOut = ahb;
286
287 return VK_SUCCESS;
288 }
289
createAndroidHardwareBuffer(bool hasDedicatedImage,bool hasDedicatedBuffer,const VkExtent3D & imageExtent,uint32_t imageLayers,VkFormat imageFormat,VkImageUsageFlags imageUsage,VkImageCreateFlags imageCreateFlags,VkDeviceSize bufferSize,VkDeviceSize allocationInfoAllocSize,struct AHardwareBuffer ** out)290 VkResult createAndroidHardwareBuffer(
291 bool hasDedicatedImage,
292 bool hasDedicatedBuffer,
293 const VkExtent3D& imageExtent,
294 uint32_t imageLayers,
295 VkFormat imageFormat,
296 VkImageUsageFlags imageUsage,
297 VkImageCreateFlags imageCreateFlags,
298 VkDeviceSize bufferSize,
299 VkDeviceSize allocationInfoAllocSize,
300 struct AHardwareBuffer **out) {
301
302 uint32_t w = 0;
303 uint32_t h = 1;
304 uint32_t layers = 1;
305 uint32_t format = 0;
306 uint64_t usage = 0;
307
308 /* If caller passed dedicated information. */
309 if (hasDedicatedImage) {
310 w = imageExtent.width;
311 h = imageExtent.height;
312 layers = imageLayers;
313 format = android_format_from_vk(imageFormat);
314 usage = getAndroidHardwareBufferUsageFromVkUsage(imageCreateFlags, imageUsage);
315 } else if (hasDedicatedBuffer) {
316 w = bufferSize;
317 format = AHARDWAREBUFFER_FORMAT_BLOB;
318 usage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN |
319 AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN |
320 AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER;
321 } else {
322 w = allocationInfoAllocSize;
323 format = AHARDWAREBUFFER_FORMAT_BLOB;
324 usage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN |
325 AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN |
326 AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER;
327 }
328
329 struct AHardwareBuffer *ahw = NULL;
330 struct AHardwareBuffer_Desc desc = {
331 .width = w,
332 .height = h,
333 .layers = layers,
334 .format = format,
335 .usage = usage,
336 };
337
338 if (AHardwareBuffer_allocate(&desc, &ahw) != 0) {
339 return VK_ERROR_OUT_OF_HOST_MEMORY;
340 }
341
342 *out = ahw;
343
344 return VK_SUCCESS;
345 }
346
347 } // namespace vk
348 } // namespace gfxstream
349