1 /*
2 * Copyright 2019 Google LLC
3 * SPDX-License-Identifier: MIT
4 */
5 #include "AndroidHardwareBuffer.h"
6 #include "util/detect_os.h"
7
8 #if DETECT_OS_ANDROID || DETECT_OS_LINUX
9 #include <drm_fourcc.h>
10 #define DRM_FORMAT_YVU420_ANDROID fourcc_code('9', '9', '9', '7')
11 #define DRM_FORMAT_D16_UNORM fourcc_code('9', '9', '9', '6')
12 #define DRM_FORMAT_D24_UNORM fourcc_code('9', '9', '9', '5')
13 #define DRM_FORMAT_D24_UNORM_S8_UINT fourcc_code('9', '9', '9', '4')
14 #define DRM_FORMAT_D32_FLOAT fourcc_code('9', '9', '9', '3')
15 #define DRM_FORMAT_D32_FLOAT_S8_UINT fourcc_code('9', '9', '9', '2')
16 #define DRM_FORMAT_S8_UINT fourcc_code('9', '9', '9', '1')
17 #endif
18
19 #if defined(ANDROID)
20
21 #include <assert.h>
22
23 #include "gfxstream/guest/GfxStreamGralloc.h"
24 #include "vk_format_info.h"
25 #include "vk_util.h"
26 #include "util/log.h"
27
28 namespace gfxstream {
29 namespace vk {
30
31 // From Intel ANV implementation.
32 /* Construct ahw usage mask from image usage bits, see
33 * 'AHardwareBuffer Usage Equivalence' in Vulkan spec.
34 */
getAndroidHardwareBufferUsageFromVkUsage(const VkImageCreateFlags vk_create,const VkImageUsageFlags vk_usage)35 uint64_t getAndroidHardwareBufferUsageFromVkUsage(const VkImageCreateFlags vk_create,
36 const VkImageUsageFlags vk_usage) {
37 uint64_t ahw_usage = 0;
38
39 if (vk_usage & VK_IMAGE_USAGE_SAMPLED_BIT) {
40 ahw_usage |= AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
41 }
42 if (vk_usage & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT) {
43 ahw_usage |= AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
44 }
45 if (vk_usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) {
46 ahw_usage |= AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT;
47 }
48 if (vk_usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
49 ahw_usage |= AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT;
50 }
51 if (vk_create & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT) {
52 ahw_usage |= AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP;
53 }
54 if (vk_create & VK_IMAGE_CREATE_PROTECTED_BIT) {
55 ahw_usage |= AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT;
56 }
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
63 return ahw_usage;
64 }
65
getAndroidHardwareBufferPropertiesANDROID(gfxstream::Gralloc * grallocHelper,const AHardwareBuffer * buffer,VkAndroidHardwareBufferPropertiesANDROID * pProperties)66 VkResult getAndroidHardwareBufferPropertiesANDROID(
67 gfxstream::Gralloc* grallocHelper, const AHardwareBuffer* buffer,
68 VkAndroidHardwareBufferPropertiesANDROID* pProperties) {
69 VkAndroidHardwareBufferFormatPropertiesANDROID* ahbFormatProps =
70 vk_find_struct(pProperties, ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID);
71
72 const auto format = grallocHelper->getFormat(buffer);
73 if (ahbFormatProps) {
74 switch (format) {
75 case AHARDWAREBUFFER_FORMAT_R8_UNORM:
76 ahbFormatProps->format = VK_FORMAT_R8_UNORM;
77 ahbFormatProps->externalFormat = DRM_FORMAT_R8;
78 break;
79 case AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM:
80 ahbFormatProps->format = VK_FORMAT_R8G8B8A8_UNORM;
81 ahbFormatProps->externalFormat = DRM_FORMAT_ABGR8888;
82 break;
83 case AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM:
84 ahbFormatProps->format = VK_FORMAT_R8G8B8A8_UNORM;
85 ahbFormatProps->externalFormat = DRM_FORMAT_XBGR8888;
86 break;
87 case AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM:
88 ahbFormatProps->format = VK_FORMAT_R8G8B8_UNORM;
89 ahbFormatProps->externalFormat = DRM_FORMAT_BGR888;
90 break;
91 case AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM:
92 ahbFormatProps->format = VK_FORMAT_R5G6B5_UNORM_PACK16;
93 ahbFormatProps->externalFormat = DRM_FORMAT_RGB565;
94 break;
95 case AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT:
96 ahbFormatProps->format = VK_FORMAT_R16G16B16A16_SFLOAT;
97 ahbFormatProps->externalFormat = DRM_FORMAT_ABGR16161616F;
98 break;
99 case AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM:
100 ahbFormatProps->format = VK_FORMAT_A2B10G10R10_UNORM_PACK32;
101 ahbFormatProps->externalFormat = DRM_FORMAT_ABGR2101010;
102 break;
103 case AHARDWAREBUFFER_FORMAT_D16_UNORM:
104 ahbFormatProps->format = VK_FORMAT_D16_UNORM;
105 ahbFormatProps->externalFormat = DRM_FORMAT_D16_UNORM;
106 break;
107 case AHARDWAREBUFFER_FORMAT_D24_UNORM:
108 ahbFormatProps->format = VK_FORMAT_X8_D24_UNORM_PACK32;
109 ahbFormatProps->externalFormat = DRM_FORMAT_D24_UNORM;
110 break;
111 case AHARDWAREBUFFER_FORMAT_D24_UNORM_S8_UINT:
112 ahbFormatProps->format = VK_FORMAT_D24_UNORM_S8_UINT;
113 ahbFormatProps->externalFormat = DRM_FORMAT_D24_UNORM_S8_UINT;
114 break;
115 case AHARDWAREBUFFER_FORMAT_D32_FLOAT:
116 ahbFormatProps->format = VK_FORMAT_D32_SFLOAT;
117 ahbFormatProps->externalFormat = DRM_FORMAT_D32_FLOAT;
118 break;
119 case AHARDWAREBUFFER_FORMAT_D32_FLOAT_S8_UINT:
120 ahbFormatProps->format = VK_FORMAT_D32_SFLOAT_S8_UINT;
121 ahbFormatProps->externalFormat = DRM_FORMAT_D32_FLOAT_S8_UINT;
122 break;
123 case AHARDWAREBUFFER_FORMAT_S8_UINT:
124 ahbFormatProps->format = VK_FORMAT_S8_UINT;
125 ahbFormatProps->externalFormat = DRM_FORMAT_S8_UINT;
126 break;
127 default:
128 ahbFormatProps->format = VK_FORMAT_UNDEFINED;
129 ahbFormatProps->externalFormat = DRM_FORMAT_INVALID;
130 }
131
132 // The formatFeatures member must include
133 // VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT and at least one of
134 // VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT or
135 // VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT, and should include
136 // VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT and
137 // VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT.
138
139 // org.skia.skqp.SkQPRunner#UnitTest_VulkanHardwareBuffer* requires the following:
140 // VK_FORMAT_FEATURE_TRANSFER_SRC_BIT
141 // VK_FORMAT_FEATURE_TRANSFER_DST_BIT
142 // VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT
143 ahbFormatProps->formatFeatures =
144 VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT |
145 VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT |
146 VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT;
147
148 // "Implementations may not always be able to determine the color model,
149 // numerical range, or chroma offsets of the image contents, so the values in
150 // VkAndroidHardwareBufferFormatPropertiesANDROID are only suggestions.
151 // Applications should treat these values as sensible defaults to use in the
152 // absence of more reliable information obtained through some other means."
153
154 ahbFormatProps->samplerYcbcrConversionComponents.r = VK_COMPONENT_SWIZZLE_IDENTITY;
155 ahbFormatProps->samplerYcbcrConversionComponents.g = VK_COMPONENT_SWIZZLE_IDENTITY;
156 ahbFormatProps->samplerYcbcrConversionComponents.b = VK_COMPONENT_SWIZZLE_IDENTITY;
157 ahbFormatProps->samplerYcbcrConversionComponents.a = VK_COMPONENT_SWIZZLE_IDENTITY;
158
159 ahbFormatProps->suggestedYcbcrModel = VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY;
160 ahbFormatProps->suggestedYcbcrRange = VK_SAMPLER_YCBCR_RANGE_ITU_NARROW;
161 ahbFormatProps->suggestedXChromaOffset = VK_CHROMA_LOCATION_MIDPOINT;
162 ahbFormatProps->suggestedYChromaOffset = VK_CHROMA_LOCATION_MIDPOINT;
163
164 #if DETECT_OS_ANDROID || DETECT_OS_LINUX
165 if (android_format_is_yuv(format)) {
166 uint32_t drmFormat = grallocHelper->getFormatDrmFourcc(buffer);
167 ahbFormatProps->externalFormat = static_cast<uint64_t>(drmFormat);
168 if (drmFormat) {
169 // The host renderer is not aware of the plane ordering for YUV formats used
170 // in the guest and simply knows that the format "layout" is one of:
171 //
172 // * VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16
173 // * VK_FORMAT_G8_B8R8_2PLANE_420_UNORM
174 // * VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM
175 //
176 // With this, the guest needs to adjust the component swizzle based on plane
177 // ordering to ensure that the channels are interpreted correctly.
178 //
179 // From the Vulkan spec's "Sampler Y'CBCR Conversion" section:
180 //
181 // * Y comes from the G-channel (after swizzle)
182 // * U (CB) comes from the B-channel (after swizzle)
183 // * V (CR) comes from the R-channel (after swizzle)
184 //
185 // See
186 // https://www.khronos.org/registry/vulkan/specs/1.3-extensions/html/vkspec.html#textures-sampler-YCbCr-conversion
187 //
188 // To match the above, the guest needs to swizzle such that:
189 //
190 // * Y ends up in the G-channel
191 // * U (CB) ends up in the B-channel
192 // * V (CB) ends up in the R-channel
193 switch (drmFormat) {
194 case DRM_FORMAT_NV12:
195 // NV12 is a Y-plane followed by a interleaved UV-plane and is
196 // VK_FORMAT_G8_B8R8_2PLANE_420_UNORM on the host.
197 break;
198 case DRM_FORMAT_P010:
199 // P010 is a Y-plane followed by a interleaved UV-plane and is
200 // VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16 on the host.
201 break;
202 case DRM_FORMAT_YUV420:
203 // YUV420 is a Y-plane, then a U-plane, and then a V-plane and is
204 // VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM on the host.
205 break;
206 case DRM_FORMAT_NV21:
207 // NV21 is a Y-plane followed by a interleaved VU-plane and is
208 // VK_FORMAT_G8_B8R8_2PLANE_420_UNORM on the host.
209 case DRM_FORMAT_YVU420:
210 // YVU420 is a Y-plane, then a V-plane, and then a U-plane and is
211 // VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM on the host.
212 case DRM_FORMAT_YVU420_ANDROID:
213 // DRM_FORMAT_YVU420_ANDROID is the same as DRM_FORMAT_YVU420 with
214 // Android's extra alignement requirements.
215 ahbFormatProps->samplerYcbcrConversionComponents.r = VK_COMPONENT_SWIZZLE_B;
216 ahbFormatProps->samplerYcbcrConversionComponents.b = VK_COMPONENT_SWIZZLE_R;
217 break;
218
219 default:
220 mesa_loge("Unhandled YUV drm format:%u", drmFormat);
221 break;
222 }
223 }
224
225 int32_t dataspace = grallocHelper->getDataspace(buffer);
226
227 // Some of the dataspace enums are not composites built from the bitwise-or of the model,
228 // transfer, and range. Replace those enums with their corresponding composite enums:
229 switch (dataspace) {
230 case GFXSTREAM_AHB_DATASPACE_UNKNOWN: {
231 dataspace = GFXSTREAM_AHB_DATASPACE_V0_JFIF;
232 break;
233 }
234 case GFXSTREAM_AHB_DATASPACE_BT601_525: {
235 dataspace = GFXSTREAM_AHB_DATASPACE_V0_BT601_525;
236 break;
237 }
238 case GFXSTREAM_AHB_DATASPACE_BT601_625: {
239 dataspace = GFXSTREAM_AHB_DATASPACE_V0_BT601_625;
240 break;
241 }
242 case GFXSTREAM_AHB_DATASPACE_BT709: {
243 dataspace = GFXSTREAM_AHB_DATASPACE_V0_BT709;
244 break;
245 }
246 case GFXSTREAM_AHB_DATASPACE_JFIF: {
247 dataspace = GFXSTREAM_AHB_DATASPACE_V0_JFIF;
248 break;
249 }
250 case GFXSTREAM_AHB_DATASPACE_SRGB: {
251 dataspace = GFXSTREAM_AHB_DATASPACE_V0_SRGB;
252 break;
253 }
254 case GFXSTREAM_AHB_DATASPACE_SRGB_LINEAR: {
255 dataspace = GFXSTREAM_AHB_DATASPACE_V0_SRGB_LINEAR;
256 break;
257 }
258 }
259
260 const int32_t model = dataspace & GFXSTREAM_AHB_DATASPACE_STANDARD_MASK;
261 switch (model) {
262 case GFXSTREAM_AHB_DATASPACE_STANDARD_BT601_525:
263 case GFXSTREAM_AHB_DATASPACE_STANDARD_BT601_525_UNADJUSTED:
264 case GFXSTREAM_AHB_DATASPACE_STANDARD_BT601_625:
265 case GFXSTREAM_AHB_DATASPACE_STANDARD_BT601_625_UNADJUSTED: {
266 ahbFormatProps->suggestedYcbcrModel = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601;
267 break;
268 }
269 case GFXSTREAM_AHB_DATASPACE_STANDARD_BT709: {
270 ahbFormatProps->suggestedYcbcrModel = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709;
271 break;
272 }
273 case GFXSTREAM_AHB_DATASPACE_STANDARD_BT2020:
274 case GFXSTREAM_AHB_DATASPACE_STANDARD_BT2020_CONSTANT_LUMINANCE: {
275 ahbFormatProps->suggestedYcbcrModel = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020;
276 break;
277 }
278 default: {
279 mesa_logw("Unhandled AHB dataspace model: %d. Assuming YCBCR_601", model);
280 ahbFormatProps->suggestedYcbcrModel = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601;
281 break;
282 }
283 }
284
285 const int32_t range = dataspace & GFXSTREAM_AHB_DATASPACE_RANGE_MASK;
286 switch (range) {
287 case GFXSTREAM_AHB_DATASPACE_RANGE_FULL: {
288 ahbFormatProps->suggestedYcbcrRange = VK_SAMPLER_YCBCR_RANGE_ITU_FULL;
289 break;
290 }
291 case GFXSTREAM_AHB_DATASPACE_RANGE_LIMITED: {
292 ahbFormatProps->suggestedYcbcrRange = VK_SAMPLER_YCBCR_RANGE_ITU_NARROW;
293 break;
294 }
295 default: {
296 mesa_logw("Unhandled AHB dataspace range: %d. Assuming full.", range);
297 ahbFormatProps->suggestedYcbcrRange = VK_SAMPLER_YCBCR_RANGE_ITU_FULL;
298 break;
299 }
300 }
301 }
302 #endif
303
304 }
305
306 uint32_t colorBufferHandle = grallocHelper->getHostHandle(buffer);
307 if (!colorBufferHandle) {
308 return VK_ERROR_INVALID_EXTERNAL_HANDLE;
309 }
310
311 pProperties->allocationSize = grallocHelper->getAllocatedSize(buffer);
312
313 return VK_SUCCESS;
314 }
315
316 // Based on Intel ANV implementation.
getMemoryAndroidHardwareBufferANDROID(gfxstream::Gralloc * gralloc,struct AHardwareBuffer ** pBuffer)317 VkResult getMemoryAndroidHardwareBufferANDROID(gfxstream::Gralloc* gralloc,
318 struct AHardwareBuffer** pBuffer) {
319 /* Some quotes from Vulkan spec:
320 *
321 * "If the device memory was created by importing an Android hardware
322 * buffer, vkGetMemoryAndroidHardwareBufferANDROID must return that same
323 * Android hardware buffer object."
324 *
325 * "VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID must
326 * have been included in VkExportMemoryAllocateInfo::handleTypes when
327 * memory was created."
328 */
329
330 if (!pBuffer) return VK_ERROR_OUT_OF_HOST_MEMORY;
331 if (!(*pBuffer)) return VK_ERROR_OUT_OF_HOST_MEMORY;
332
333 gralloc->acquire(*pBuffer);
334 return VK_SUCCESS;
335 }
336
importAndroidHardwareBuffer(gfxstream::Gralloc * grallocHelper,const VkImportAndroidHardwareBufferInfoANDROID * info,struct AHardwareBuffer ** importOut)337 VkResult importAndroidHardwareBuffer(gfxstream::Gralloc* grallocHelper,
338 const VkImportAndroidHardwareBufferInfoANDROID* info,
339 struct AHardwareBuffer** importOut) {
340 if (!info || !info->buffer) {
341 return VK_ERROR_INVALID_EXTERNAL_HANDLE;
342 }
343
344 auto ahb = info->buffer;
345
346 uint32_t colorBufferHandle = grallocHelper->getHostHandle(ahb);
347 if (!colorBufferHandle) {
348 return VK_ERROR_INVALID_EXTERNAL_HANDLE;
349 }
350
351 grallocHelper->acquire(ahb);
352
353 if (importOut) *importOut = ahb;
354
355 return VK_SUCCESS;
356 }
357
createAndroidHardwareBuffer(gfxstream::Gralloc * gralloc,bool hasDedicatedImage,bool hasDedicatedBuffer,const VkExtent3D & imageExtent,uint32_t imageLayers,VkFormat imageFormat,VkImageUsageFlags imageUsage,VkImageCreateFlags imageCreateFlags,VkDeviceSize bufferSize,VkDeviceSize allocationInfoAllocSize,struct AHardwareBuffer ** out)358 VkResult createAndroidHardwareBuffer(gfxstream::Gralloc* gralloc, bool hasDedicatedImage,
359 bool hasDedicatedBuffer, const VkExtent3D& imageExtent,
360 uint32_t imageLayers, VkFormat imageFormat,
361 VkImageUsageFlags imageUsage,
362 VkImageCreateFlags imageCreateFlags, VkDeviceSize bufferSize,
363 VkDeviceSize allocationInfoAllocSize,
364 struct AHardwareBuffer** out) {
365 uint32_t w = 0;
366 uint32_t h = 1;
367 uint32_t layers = 1;
368 uint32_t format = 0;
369 uint64_t usage = 0;
370
371 /* If caller passed dedicated information. */
372 if (hasDedicatedImage) {
373 w = imageExtent.width;
374 h = imageExtent.height;
375 layers = imageLayers;
376 format = android_format_from_vk(imageFormat);
377 usage = getAndroidHardwareBufferUsageFromVkUsage(imageCreateFlags, imageUsage);
378 } else if (hasDedicatedBuffer) {
379 w = bufferSize;
380 format = AHARDWAREBUFFER_FORMAT_BLOB;
381 usage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN | AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN |
382 AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER;
383 } else {
384 w = allocationInfoAllocSize;
385 format = AHARDWAREBUFFER_FORMAT_BLOB;
386 usage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN | AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN |
387 AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER;
388 }
389
390 struct AHardwareBuffer* ahb = NULL;
391
392 if (gralloc->allocate(w, h, format, usage, &ahb) != 0) {
393 return VK_ERROR_OUT_OF_HOST_MEMORY;
394 }
395
396 *out = ahb;
397
398 return VK_SUCCESS;
399 }
400
401 } // namespace vk
402 } // namespace gfxstream
403
404 #endif // ANDROID
405