• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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