1 /*
2 * Copyright © 2017, Google Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 */
23
24 #include "radv_private.h"
25
26 #if DETECT_OS_ANDROID
27 #include <libsync.h>
28 #include <hardware/gralloc.h>
29 #include <hardware/hardware.h>
30 #include <hardware/hwvulkan.h>
31 #include <vulkan/vk_android_native_buffer.h>
32 #include <vulkan/vk_icd.h>
33
34 #if ANDROID_API_LEVEL >= 26
35 #include <hardware/gralloc1.h>
36 #endif
37 #endif /* DETECT_OS_ANDROID */
38
39 #include "util/os_file.h"
40
41 #include "vk_android.h"
42 #include "vk_util.h"
43
44 #if DETECT_OS_ANDROID
45
46 static int radv_hal_open(const struct hw_module_t *mod, const char *id, struct hw_device_t **dev);
47 static int radv_hal_close(struct hw_device_t *dev);
48
49 static_assert(HWVULKAN_DISPATCH_MAGIC == ICD_LOADER_MAGIC, "");
50
51 PUBLIC struct hwvulkan_module_t HAL_MODULE_INFO_SYM = {
52 .common =
53 {
54 .tag = HARDWARE_MODULE_TAG,
55 .module_api_version = HWVULKAN_MODULE_API_VERSION_0_1,
56 .hal_api_version = HARDWARE_MAKE_API_VERSION(1, 0),
57 .id = HWVULKAN_HARDWARE_MODULE_ID,
58 .name = "AMD Vulkan HAL",
59 .author = "Google",
60 .methods =
61 &(hw_module_methods_t){
62 .open = radv_hal_open,
63 },
64 },
65 };
66
67 /* If any bits in test_mask are set, then unset them and return true. */
68 static inline bool
unmask32(uint32_t * inout_mask,uint32_t test_mask)69 unmask32(uint32_t *inout_mask, uint32_t test_mask)
70 {
71 uint32_t orig_mask = *inout_mask;
72 *inout_mask &= ~test_mask;
73 return *inout_mask != orig_mask;
74 }
75
76 static int
radv_hal_open(const struct hw_module_t * mod,const char * id,struct hw_device_t ** dev)77 radv_hal_open(const struct hw_module_t *mod, const char *id, struct hw_device_t **dev)
78 {
79 assert(mod == &HAL_MODULE_INFO_SYM.common);
80 assert(strcmp(id, HWVULKAN_DEVICE_0) == 0);
81
82 hwvulkan_device_t *hal_dev = malloc(sizeof(*hal_dev));
83 if (!hal_dev)
84 return -1;
85
86 *hal_dev = (hwvulkan_device_t){
87 .common =
88 {
89 .tag = HARDWARE_DEVICE_TAG,
90 .version = HWVULKAN_DEVICE_API_VERSION_0_1,
91 .module = &HAL_MODULE_INFO_SYM.common,
92 .close = radv_hal_close,
93 },
94 .EnumerateInstanceExtensionProperties = radv_EnumerateInstanceExtensionProperties,
95 .CreateInstance = radv_CreateInstance,
96 .GetInstanceProcAddr = radv_GetInstanceProcAddr,
97 };
98
99 *dev = &hal_dev->common;
100 return 0;
101 }
102
103 static int
radv_hal_close(struct hw_device_t * dev)104 radv_hal_close(struct hw_device_t *dev)
105 {
106 /* hwvulkan.h claims that hw_device_t::close() is never called. */
107 return -1;
108 }
109
110 VkResult
radv_image_from_gralloc(VkDevice device_h,const VkImageCreateInfo * base_info,const VkNativeBufferANDROID * gralloc_info,const VkAllocationCallbacks * alloc,VkImage * out_image_h)111 radv_image_from_gralloc(VkDevice device_h, const VkImageCreateInfo *base_info,
112 const VkNativeBufferANDROID *gralloc_info, const VkAllocationCallbacks *alloc,
113 VkImage *out_image_h)
114
115 {
116 RADV_FROM_HANDLE(radv_device, device, device_h);
117 VkImage image_h = VK_NULL_HANDLE;
118 struct radv_image *image = NULL;
119 VkResult result;
120
121 if (gralloc_info->handle->numFds != 1) {
122 return vk_errorf(device, VK_ERROR_INVALID_EXTERNAL_HANDLE,
123 "VkNativeBufferANDROID::handle::numFds is %d, "
124 "expected 1",
125 gralloc_info->handle->numFds);
126 }
127
128 /* Do not close the gralloc handle's dma_buf. The lifetime of the dma_buf
129 * must exceed that of the gralloc handle, and we do not own the gralloc
130 * handle.
131 */
132 int dma_buf = gralloc_info->handle->data[0];
133
134 VkDeviceMemory memory_h;
135
136 const VkImportMemoryFdInfoKHR import_info = {
137 .sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR,
138 .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT,
139 .fd = os_dupfd_cloexec(dma_buf),
140 };
141
142 /* Find the first VRAM memory type, or GART for PRIME images. */
143 int memory_type_index = -1;
144 for (int i = 0; i < device->physical_device->memory_properties.memoryTypeCount; ++i) {
145 bool is_local = !!(device->physical_device->memory_properties.memoryTypes[i].propertyFlags &
146 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
147 bool is_32bit = !!(device->physical_device->memory_types_32bit & (1u << i));
148 if (is_local && !is_32bit) {
149 memory_type_index = i;
150 break;
151 }
152 }
153
154 /* fallback */
155 if (memory_type_index == -1)
156 memory_type_index = 0;
157
158 result = radv_AllocateMemory(device_h,
159 &(VkMemoryAllocateInfo){
160 .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
161 .pNext = &import_info,
162 /* Max buffer size, unused for imports */
163 .allocationSize = 0x7FFFFFFF,
164 .memoryTypeIndex = memory_type_index,
165 },
166 alloc, &memory_h);
167 if (result != VK_SUCCESS)
168 return result;
169
170 struct radeon_bo_metadata md;
171 device->ws->buffer_get_metadata(device->ws, radv_device_memory_from_handle(memory_h)->bo, &md);
172
173 VkImageCreateInfo updated_base_info = *base_info;
174
175 VkExternalMemoryImageCreateInfo external_memory_info = {
176 .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO,
177 .pNext = updated_base_info.pNext,
178 .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
179 };
180
181 updated_base_info.pNext = &external_memory_info;
182
183 result = radv_image_create(device_h,
184 &(struct radv_image_create_info){
185 .vk_info = &updated_base_info,
186 .no_metadata_planes = true,
187 .bo_metadata = &md,
188 },
189 alloc, &image_h, false);
190
191 if (result != VK_SUCCESS)
192 goto fail_create_image;
193
194 image = radv_image_from_handle(image_h);
195
196 radv_image_override_offset_stride(device, image, 0, gralloc_info->stride);
197
198 VkBindImageMemoryInfo bind_info = {.sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO,
199 .image = image_h,
200 .memory = memory_h,
201 .memoryOffset = 0};
202 radv_BindImageMemory2(device_h, 1, &bind_info);
203
204 image->owned_memory = memory_h;
205 /* Don't clobber the out-parameter until success is certain. */
206 *out_image_h = image_h;
207
208 return VK_SUCCESS;
209
210 fail_create_image:
211 radv_FreeMemory(device_h, memory_h, alloc);
212 return result;
213 }
214
215 VkResult
radv_GetSwapchainGrallocUsageANDROID(VkDevice device_h,VkFormat format,VkImageUsageFlags imageUsage,int * grallocUsage)216 radv_GetSwapchainGrallocUsageANDROID(VkDevice device_h, VkFormat format, VkImageUsageFlags imageUsage,
217 int *grallocUsage)
218 {
219 RADV_FROM_HANDLE(radv_device, device, device_h);
220 struct radv_physical_device *phys_dev = device->physical_device;
221 VkPhysicalDevice phys_dev_h = radv_physical_device_to_handle(phys_dev);
222 VkResult result;
223
224 *grallocUsage = 0;
225
226 /* WARNING: Android Nougat's libvulkan.so hardcodes the VkImageUsageFlags
227 * returned to applications via VkSurfaceCapabilitiesKHR::supportedUsageFlags.
228 * The relevant code in libvulkan/swapchain.cpp contains this fun comment:
229 *
230 * TODO(jessehall): I think these are right, but haven't thought hard
231 * about it. Do we need to query the driver for support of any of
232 * these?
233 *
234 * Any disagreement between this function and the hardcoded
235 * VkSurfaceCapabilitiesKHR:supportedUsageFlags causes tests
236 * dEQP-VK.wsi.android.swapchain.*.image_usage to fail.
237 */
238
239 const VkPhysicalDeviceImageFormatInfo2 image_format_info = {
240 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
241 .format = format,
242 .type = VK_IMAGE_TYPE_2D,
243 .tiling = VK_IMAGE_TILING_OPTIMAL,
244 .usage = imageUsage,
245 };
246
247 VkImageFormatProperties2 image_format_props = {
248 .sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
249 };
250
251 /* Check that requested format and usage are supported. */
252 result = radv_GetPhysicalDeviceImageFormatProperties2(phys_dev_h, &image_format_info, &image_format_props);
253 if (result != VK_SUCCESS) {
254 return vk_errorf(device, result,
255 "radv_GetPhysicalDeviceImageFormatProperties2 failed "
256 "inside %s",
257 __func__);
258 }
259
260 if (unmask32(&imageUsage, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT))
261 *grallocUsage |= GRALLOC_USAGE_HW_RENDER;
262
263 if (unmask32(&imageUsage, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT |
264 VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT))
265 *grallocUsage |= GRALLOC_USAGE_HW_TEXTURE;
266
267 /* All VkImageUsageFlags not explicitly checked here are unsupported for
268 * gralloc swapchains.
269 */
270 if (imageUsage != 0) {
271 return vk_errorf(device, VK_ERROR_FORMAT_NOT_SUPPORTED,
272 "unsupported VkImageUsageFlags(0x%x) for gralloc "
273 "swapchain",
274 imageUsage);
275 }
276
277 /*
278 * FINISHME: Advertise all display-supported formats. Mostly
279 * DRM_FORMAT_ARGB2101010 and DRM_FORMAT_ABGR2101010, but need to check
280 * what we need for 30-bit colors.
281 */
282 if (format == VK_FORMAT_B8G8R8A8_UNORM || format == VK_FORMAT_B5G6R5_UNORM_PACK16) {
283 *grallocUsage |= GRALLOC_USAGE_HW_FB | GRALLOC_USAGE_HW_COMPOSER | GRALLOC_USAGE_EXTERNAL_DISP;
284 }
285
286 if (*grallocUsage == 0)
287 return VK_ERROR_FORMAT_NOT_SUPPORTED;
288
289 return VK_SUCCESS;
290 }
291
292 VkResult
radv_GetSwapchainGrallocUsage2ANDROID(VkDevice device_h,VkFormat format,VkImageUsageFlags imageUsage,VkSwapchainImageUsageFlagsANDROID swapchainImageUsage,uint64_t * grallocConsumerUsage,uint64_t * grallocProducerUsage)293 radv_GetSwapchainGrallocUsage2ANDROID(VkDevice device_h, VkFormat format, VkImageUsageFlags imageUsage,
294 VkSwapchainImageUsageFlagsANDROID swapchainImageUsage,
295 uint64_t *grallocConsumerUsage, uint64_t *grallocProducerUsage)
296 {
297 /* Before level 26 (Android 8.0/Oreo) the loader uses
298 * vkGetSwapchainGrallocUsageANDROID. */
299 #if ANDROID_API_LEVEL >= 26
300 RADV_FROM_HANDLE(radv_device, device, device_h);
301 struct radv_physical_device *phys_dev = device->physical_device;
302 VkPhysicalDevice phys_dev_h = radv_physical_device_to_handle(phys_dev);
303 VkResult result;
304
305 *grallocConsumerUsage = 0;
306 *grallocProducerUsage = 0;
307
308 if (swapchainImageUsage & VK_SWAPCHAIN_IMAGE_USAGE_SHARED_BIT_ANDROID)
309 return vk_errorf(device, VK_ERROR_FORMAT_NOT_SUPPORTED,
310 "The Vulkan loader tried to query shared presentable image support");
311
312 const VkPhysicalDeviceImageFormatInfo2 image_format_info = {
313 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
314 .format = format,
315 .type = VK_IMAGE_TYPE_2D,
316 .tiling = VK_IMAGE_TILING_OPTIMAL,
317 .usage = imageUsage,
318 };
319
320 VkImageFormatProperties2 image_format_props = {
321 .sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
322 };
323
324 /* Check that requested format and usage are supported. */
325 result = radv_GetPhysicalDeviceImageFormatProperties2(phys_dev_h, &image_format_info, &image_format_props);
326 if (result != VK_SUCCESS) {
327 return vk_errorf(device, result,
328 "radv_GetPhysicalDeviceImageFormatProperties2 failed "
329 "inside %s",
330 __func__);
331 }
332
333 if (unmask32(&imageUsage, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)) {
334 *grallocProducerUsage |= GRALLOC1_PRODUCER_USAGE_GPU_RENDER_TARGET;
335 *grallocConsumerUsage |= GRALLOC1_CONSUMER_USAGE_CLIENT_TARGET;
336 }
337
338 if (unmask32(&imageUsage, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT |
339 VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)) {
340 *grallocConsumerUsage |= GRALLOC1_CONSUMER_USAGE_GPU_TEXTURE;
341 }
342
343 if (imageUsage != 0) {
344 return vk_errorf(device, VK_ERROR_FORMAT_NOT_SUPPORTED,
345 "unsupported VkImageUsageFlags(0x%x) for gralloc "
346 "swapchain",
347 imageUsage);
348 }
349
350 /*
351 * FINISHME: Advertise all display-supported formats. Mostly
352 * DRM_FORMAT_ARGB2101010 and DRM_FORMAT_ABGR2101010, but need to check
353 * what we need for 30-bit colors.
354 */
355 if (format == VK_FORMAT_B8G8R8A8_UNORM || format == VK_FORMAT_B5G6R5_UNORM_PACK16) {
356 *grallocProducerUsage |= GRALLOC1_PRODUCER_USAGE_GPU_RENDER_TARGET;
357 *grallocConsumerUsage |= GRALLOC1_CONSUMER_USAGE_HWCOMPOSER;
358 }
359
360 if (!*grallocProducerUsage && !*grallocConsumerUsage)
361 return VK_ERROR_FORMAT_NOT_SUPPORTED;
362
363 return VK_SUCCESS;
364 #else
365 *grallocConsumerUsage = 0;
366 *grallocProducerUsage = 0;
367 return VK_ERROR_FORMAT_NOT_SUPPORTED;
368 #endif
369 }
370 #endif /* DETECT_OS_ANDROID */
371
372 #if RADV_SUPPORT_ANDROID_HARDWARE_BUFFER
373
374 enum {
375 /* Usage bit equal to GRALLOC_USAGE_HW_CAMERA_MASK */
376 BUFFER_USAGE_CAMERA_MASK = 0x00060000U,
377 };
378
379 static inline VkFormat
vk_format_from_android(unsigned android_format,unsigned android_usage)380 vk_format_from_android(unsigned android_format, unsigned android_usage)
381 {
382 switch (android_format) {
383 case AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420:
384 return VK_FORMAT_G8_B8R8_2PLANE_420_UNORM;
385 case AHARDWAREBUFFER_FORMAT_IMPLEMENTATION_DEFINED:
386 if (android_usage & BUFFER_USAGE_CAMERA_MASK)
387 return VK_FORMAT_G8_B8R8_2PLANE_420_UNORM;
388 else
389 return VK_FORMAT_R8G8B8_UNORM;
390 default:
391 return vk_ahb_format_to_image_format(android_format);
392 }
393 }
394
395 unsigned
radv_ahb_format_for_vk_format(VkFormat vk_format)396 radv_ahb_format_for_vk_format(VkFormat vk_format)
397 {
398 switch (vk_format) {
399 case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
400 return AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420;
401 default:
402 return vk_image_format_to_ahb_format(vk_format);
403 }
404 }
405
406 static VkResult
get_ahb_buffer_format_properties(VkDevice device_h,const struct AHardwareBuffer * buffer,VkAndroidHardwareBufferFormatPropertiesANDROID * pProperties)407 get_ahb_buffer_format_properties(VkDevice device_h, const struct AHardwareBuffer *buffer,
408 VkAndroidHardwareBufferFormatPropertiesANDROID *pProperties)
409 {
410 RADV_FROM_HANDLE(radv_device, device, device_h);
411
412 /* Get a description of buffer contents . */
413 AHardwareBuffer_Desc desc;
414 AHardwareBuffer_describe(buffer, &desc);
415
416 /* Verify description. */
417 const uint64_t gpu_usage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE | AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT |
418 AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER;
419
420 /* "Buffer must be a valid Android hardware buffer object with at least
421 * one of the AHARDWAREBUFFER_USAGE_GPU_* usage flags."
422 */
423 if (!(desc.usage & (gpu_usage)))
424 return VK_ERROR_INVALID_EXTERNAL_HANDLE;
425
426 /* Fill properties fields based on description. */
427 VkAndroidHardwareBufferFormatPropertiesANDROID *p = pProperties;
428
429 p->format = vk_format_from_android(desc.format, desc.usage);
430 p->externalFormat = (uint64_t)(uintptr_t)p->format;
431
432 VkFormatProperties2 format_properties = {.sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2};
433
434 radv_GetPhysicalDeviceFormatProperties2(radv_physical_device_to_handle(device->physical_device), p->format,
435 &format_properties);
436
437 if (desc.usage & AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER)
438 p->formatFeatures = format_properties.formatProperties.linearTilingFeatures;
439 else
440 p->formatFeatures = format_properties.formatProperties.optimalTilingFeatures;
441
442 /* "Images can be created with an external format even if the Android hardware
443 * buffer has a format which has an equivalent Vulkan format to enable
444 * consistent handling of images from sources that might use either category
445 * of format. However, all images created with an external format are subject
446 * to the valid usage requirements associated with external formats, even if
447 * the Android hardware buffer’s format has a Vulkan equivalent."
448 *
449 * "The formatFeatures member *must* include
450 * VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT and at least one of
451 * VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT or
452 * VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT"
453 */
454 assert(p->formatFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT);
455
456 p->formatFeatures |= VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT;
457
458 /* "Implementations may not always be able to determine the color model,
459 * numerical range, or chroma offsets of the image contents, so the values
460 * in VkAndroidHardwareBufferFormatPropertiesANDROID are only suggestions.
461 * Applications should treat these values as sensible defaults to use in
462 * the absence of more reliable information obtained through some other
463 * means."
464 */
465 p->samplerYcbcrConversionComponents.r = VK_COMPONENT_SWIZZLE_IDENTITY;
466 p->samplerYcbcrConversionComponents.g = VK_COMPONENT_SWIZZLE_IDENTITY;
467 p->samplerYcbcrConversionComponents.b = VK_COMPONENT_SWIZZLE_IDENTITY;
468 p->samplerYcbcrConversionComponents.a = VK_COMPONENT_SWIZZLE_IDENTITY;
469
470 p->suggestedYcbcrModel = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601;
471 p->suggestedYcbcrRange = VK_SAMPLER_YCBCR_RANGE_ITU_FULL;
472
473 p->suggestedXChromaOffset = VK_CHROMA_LOCATION_MIDPOINT;
474 p->suggestedYChromaOffset = VK_CHROMA_LOCATION_MIDPOINT;
475
476 return VK_SUCCESS;
477 }
478
479 static VkResult
get_ahb_buffer_format_properties2(VkDevice device_h,const struct AHardwareBuffer * buffer,VkAndroidHardwareBufferFormatProperties2ANDROID * pProperties)480 get_ahb_buffer_format_properties2(VkDevice device_h, const struct AHardwareBuffer *buffer,
481 VkAndroidHardwareBufferFormatProperties2ANDROID *pProperties)
482 {
483 RADV_FROM_HANDLE(radv_device, device, device_h);
484
485 /* Get a description of buffer contents . */
486 AHardwareBuffer_Desc desc;
487 AHardwareBuffer_describe(buffer, &desc);
488
489 /* Verify description. */
490 const uint64_t gpu_usage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE | AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT |
491 AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER;
492
493 /* "Buffer must be a valid Android hardware buffer object with at least
494 * one of the AHARDWAREBUFFER_USAGE_GPU_* usage flags."
495 */
496 if (!(desc.usage & (gpu_usage)))
497 return VK_ERROR_INVALID_EXTERNAL_HANDLE;
498
499 /* Fill properties fields based on description. */
500 VkAndroidHardwareBufferFormatProperties2ANDROID *p = pProperties;
501
502 p->format = vk_format_from_android(desc.format, desc.usage);
503 p->externalFormat = (uint64_t)(uintptr_t)p->format;
504
505 VkFormatProperties2 format_properties = {.sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2};
506
507 radv_GetPhysicalDeviceFormatProperties2(radv_physical_device_to_handle(device->physical_device), p->format,
508 &format_properties);
509
510 if (desc.usage & AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER)
511 p->formatFeatures = format_properties.formatProperties.linearTilingFeatures;
512 else
513 p->formatFeatures = format_properties.formatProperties.optimalTilingFeatures;
514
515 /* "Images can be created with an external format even if the Android hardware
516 * buffer has a format which has an equivalent Vulkan format to enable
517 * consistent handling of images from sources that might use either category
518 * of format. However, all images created with an external format are subject
519 * to the valid usage requirements associated with external formats, even if
520 * the Android hardware buffer’s format has a Vulkan equivalent."
521 *
522 * "The formatFeatures member *must* include
523 * VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT and at least one of
524 * VK_FORMAT_FEATURE_2_MIDPOINT_CHROMA_SAMPLES_BIT or
525 * VK_FORMAT_FEATURE_2_COSITED_CHROMA_SAMPLES_BIT"
526 */
527 assert(p->formatFeatures & VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT);
528
529 p->formatFeatures |= VK_FORMAT_FEATURE_2_MIDPOINT_CHROMA_SAMPLES_BIT;
530
531 /* "Implementations may not always be able to determine the color model,
532 * numerical range, or chroma offsets of the image contents, so the values
533 * in VkAndroidHardwareBufferFormatPropertiesANDROID are only suggestions.
534 * Applications should treat these values as sensible defaults to use in
535 * the absence of more reliable information obtained through some other
536 * means."
537 */
538 p->samplerYcbcrConversionComponents.r = VK_COMPONENT_SWIZZLE_IDENTITY;
539 p->samplerYcbcrConversionComponents.g = VK_COMPONENT_SWIZZLE_IDENTITY;
540 p->samplerYcbcrConversionComponents.b = VK_COMPONENT_SWIZZLE_IDENTITY;
541 p->samplerYcbcrConversionComponents.a = VK_COMPONENT_SWIZZLE_IDENTITY;
542
543 p->suggestedYcbcrModel = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601;
544 p->suggestedYcbcrRange = VK_SAMPLER_YCBCR_RANGE_ITU_FULL;
545
546 p->suggestedXChromaOffset = VK_CHROMA_LOCATION_MIDPOINT;
547 p->suggestedYChromaOffset = VK_CHROMA_LOCATION_MIDPOINT;
548
549 return VK_SUCCESS;
550 }
551
552 VkResult
radv_GetAndroidHardwareBufferPropertiesANDROID(VkDevice device_h,const struct AHardwareBuffer * buffer,VkAndroidHardwareBufferPropertiesANDROID * pProperties)553 radv_GetAndroidHardwareBufferPropertiesANDROID(VkDevice device_h, const struct AHardwareBuffer *buffer,
554 VkAndroidHardwareBufferPropertiesANDROID *pProperties)
555 {
556 RADV_FROM_HANDLE(radv_device, dev, device_h);
557 struct radv_physical_device *pdevice = dev->physical_device;
558
559 VkAndroidHardwareBufferFormatPropertiesANDROID *format_prop =
560 vk_find_struct(pProperties->pNext, ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID);
561
562 /* Fill format properties of an Android hardware buffer. */
563 if (format_prop)
564 get_ahb_buffer_format_properties(device_h, buffer, format_prop);
565
566 VkAndroidHardwareBufferFormatProperties2ANDROID *format_prop2 =
567 vk_find_struct(pProperties->pNext, ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_2_ANDROID);
568 if (format_prop2)
569 get_ahb_buffer_format_properties2(device_h, buffer, format_prop2);
570
571 /* NOTE - We support buffers with only one handle but do not error on
572 * multiple handle case. Reason is that we want to support YUV formats
573 * where we have many logical planes but they all point to the same
574 * buffer, like is the case with VK_FORMAT_G8_B8R8_2PLANE_420_UNORM.
575 */
576 const native_handle_t *handle = AHardwareBuffer_getNativeHandle(buffer);
577 int dma_buf = (handle && handle->numFds) ? handle->data[0] : -1;
578 if (dma_buf < 0)
579 return VK_ERROR_INVALID_EXTERNAL_HANDLE;
580
581 /* All memory types. */
582 uint32_t memory_types = (1u << pdevice->memory_properties.memoryTypeCount) - 1;
583
584 pProperties->allocationSize = lseek(dma_buf, 0, SEEK_END);
585 pProperties->memoryTypeBits = memory_types & ~pdevice->memory_types_32bit;
586
587 return VK_SUCCESS;
588 }
589
590 VkResult
radv_GetMemoryAndroidHardwareBufferANDROID(VkDevice device_h,const VkMemoryGetAndroidHardwareBufferInfoANDROID * pInfo,struct AHardwareBuffer ** pBuffer)591 radv_GetMemoryAndroidHardwareBufferANDROID(VkDevice device_h, const VkMemoryGetAndroidHardwareBufferInfoANDROID *pInfo,
592 struct AHardwareBuffer **pBuffer)
593 {
594 RADV_FROM_HANDLE(radv_device_memory, mem, pInfo->memory);
595
596 /* This should always be set due to the export handle types being set on
597 * allocation. */
598 assert(mem->android_hardware_buffer);
599
600 /* Some quotes from Vulkan spec:
601 *
602 * "If the device memory was created by importing an Android hardware
603 * buffer, vkGetMemoryAndroidHardwareBufferANDROID must return that same
604 * Android hardware buffer object."
605 *
606 * "VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID must
607 * have been included in VkExportMemoryAllocateInfo::handleTypes when
608 * memory was created."
609 */
610 *pBuffer = mem->android_hardware_buffer;
611 /* Increase refcount. */
612 AHardwareBuffer_acquire(mem->android_hardware_buffer);
613 return VK_SUCCESS;
614 }
615
616 #endif
617
618 VkFormat
radv_select_android_external_format(const void * next,VkFormat default_format)619 radv_select_android_external_format(const void *next, VkFormat default_format)
620 {
621 #if RADV_SUPPORT_ANDROID_HARDWARE_BUFFER
622 const VkExternalFormatANDROID *android_format = vk_find_struct_const(next, EXTERNAL_FORMAT_ANDROID);
623
624 if (android_format && android_format->externalFormat) {
625 return (VkFormat)android_format->externalFormat;
626 }
627 #endif
628
629 return default_format;
630 }
631
632 VkResult
radv_import_ahb_memory(struct radv_device * device,struct radv_device_memory * mem,unsigned priority,const VkImportAndroidHardwareBufferInfoANDROID * info)633 radv_import_ahb_memory(struct radv_device *device, struct radv_device_memory *mem, unsigned priority,
634 const VkImportAndroidHardwareBufferInfoANDROID *info)
635 {
636 #if RADV_SUPPORT_ANDROID_HARDWARE_BUFFER
637 /* Import from AHardwareBuffer to radv_device_memory. */
638 const native_handle_t *handle = AHardwareBuffer_getNativeHandle(info->buffer);
639
640 /* NOTE - We support buffers with only one handle but do not error on
641 * multiple handle case. Reason is that we want to support YUV formats
642 * where we have many logical planes but they all point to the same
643 * buffer, like is the case with VK_FORMAT_G8_B8R8_2PLANE_420_UNORM.
644 */
645 int dma_buf = (handle && handle->numFds) ? handle->data[0] : -1;
646 if (dma_buf < 0)
647 return VK_ERROR_INVALID_EXTERNAL_HANDLE;
648
649 uint64_t alloc_size = 0;
650 VkResult result = device->ws->buffer_from_fd(device->ws, dma_buf, priority, &mem->bo, &alloc_size);
651 if (result != VK_SUCCESS)
652 return result;
653
654 if (mem->image) {
655 struct radeon_bo_metadata metadata;
656 device->ws->buffer_get_metadata(device->ws, mem->bo, &metadata);
657
658 struct radv_image_create_info create_info = {.no_metadata_planes = true, .bo_metadata = &metadata};
659
660 result = radv_image_create_layout(device, create_info, NULL, NULL, mem->image);
661 if (result != VK_SUCCESS) {
662 device->ws->buffer_destroy(device->ws, mem->bo);
663 mem->bo = NULL;
664 return result;
665 }
666
667 if (alloc_size < mem->image->size) {
668 device->ws->buffer_destroy(device->ws, mem->bo);
669 mem->bo = NULL;
670 return VK_ERROR_INVALID_EXTERNAL_HANDLE;
671 }
672 } else if (mem->buffer) {
673 if (alloc_size < mem->buffer->vk.size) {
674 device->ws->buffer_destroy(device->ws, mem->bo);
675 mem->bo = NULL;
676 return VK_ERROR_INVALID_EXTERNAL_HANDLE;
677 }
678 }
679
680 /* "If the vkAllocateMemory command succeeds, the implementation must
681 * acquire a reference to the imported hardware buffer, which it must
682 * release when the device memory object is freed. If the command fails,
683 * the implementation must not retain a reference."
684 */
685 AHardwareBuffer_acquire(info->buffer);
686 mem->android_hardware_buffer = info->buffer;
687
688 return VK_SUCCESS;
689 #else /* RADV_SUPPORT_ANDROID_HARDWARE_BUFFER */
690 return VK_ERROR_EXTENSION_NOT_PRESENT;
691 #endif
692 }
693
694 VkResult
radv_create_ahb_memory(struct radv_device * device,struct radv_device_memory * mem,unsigned priority,const VkMemoryAllocateInfo * pAllocateInfo)695 radv_create_ahb_memory(struct radv_device *device, struct radv_device_memory *mem, unsigned priority,
696 const VkMemoryAllocateInfo *pAllocateInfo)
697 {
698 #if RADV_SUPPORT_ANDROID_HARDWARE_BUFFER
699 mem->android_hardware_buffer = vk_alloc_ahardware_buffer(pAllocateInfo);
700 if (mem->android_hardware_buffer == NULL)
701 return VK_ERROR_OUT_OF_HOST_MEMORY;
702
703 const struct VkImportAndroidHardwareBufferInfoANDROID import_info = {
704 .buffer = mem->android_hardware_buffer,
705 };
706
707 VkResult result = radv_import_ahb_memory(device, mem, priority, &import_info);
708
709 /* Release a reference to avoid leak for AHB allocation. */
710 AHardwareBuffer_release(mem->android_hardware_buffer);
711
712 return result;
713 #else /* RADV_SUPPORT_ANDROID_HARDWARE_BUFFER */
714 return VK_ERROR_EXTENSION_NOT_PRESENT;
715 #endif
716 }
717
718 bool
radv_android_gralloc_supports_format(VkFormat format,VkImageUsageFlagBits usage)719 radv_android_gralloc_supports_format(VkFormat format, VkImageUsageFlagBits usage)
720 {
721 #if RADV_SUPPORT_ANDROID_HARDWARE_BUFFER
722 /* Ideally we check AHardwareBuffer_isSupported. But that test-allocates on most platforms and
723 * seems a bit on the expensive side. Return true as long as it is a format we understand.
724 */
725 (void)usage;
726 return radv_ahb_format_for_vk_format(format);
727 #else
728 (void)format;
729 (void)usage;
730 return false;
731 #endif
732 }
733