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