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