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#ifdef ANDROID
25#include <libsync.h>
26#include <hardware/gralloc.h>
27#include <hardware/hardware.h>
28#include <hardware/hwvulkan.h>
29#include <vulkan/vk_android_native_buffer.h>
30#include <vulkan/vk_icd.h>
31
32#if ANDROID_API_LEVEL >= 26
33#include <hardware/gralloc1.h>
34#endif
35#endif
36
37#include "util/os_file.h"
38
39#include "radv_private.h"
40#include "vk_util.h"
41
42#ifdef ANDROID
43
44static int radv_hal_open(const struct hw_module_t *mod, const char *id, struct hw_device_t **dev);
45static int radv_hal_close(struct hw_device_t *dev);
46
47static void UNUSED
48static_asserts(void)
49{
50   STATIC_ASSERT(HWVULKAN_DISPATCH_MAGIC == ICD_LOADER_MAGIC);
51}
52
53PUBLIC struct hwvulkan_module_t HAL_MODULE_INFO_SYM = {
54   .common =
55      {
56         .tag = HARDWARE_MODULE_TAG,
57         .module_api_version = HWVULKAN_MODULE_API_VERSION_0_1,
58         .hal_api_version = HARDWARE_MAKE_API_VERSION(1, 0),
59         .id = HWVULKAN_HARDWARE_MODULE_ID,
60         .name = "AMD Vulkan HAL",
61         .author = "Google",
62         .methods =
63            &(hw_module_methods_t){
64               .open = radv_hal_open,
65            },
66      },
67};
68
69/* If any bits in test_mask are set, then unset them and return true. */
70static inline bool
71unmask32(uint32_t *inout_mask, uint32_t test_mask)
72{
73   uint32_t orig_mask = *inout_mask;
74   *inout_mask &= ~test_mask;
75   return *inout_mask != orig_mask;
76}
77
78static int
79radv_hal_open(const struct hw_module_t *mod, const char *id, struct hw_device_t **dev)
80{
81   assert(mod == &HAL_MODULE_INFO_SYM.common);
82   assert(strcmp(id, HWVULKAN_DEVICE_0) == 0);
83
84   hwvulkan_device_t *hal_dev = malloc(sizeof(*hal_dev));
85   if (!hal_dev)
86      return -1;
87
88   *hal_dev = (hwvulkan_device_t){
89      .common =
90         {
91            .tag = HARDWARE_DEVICE_TAG,
92            .version = HWVULKAN_DEVICE_API_VERSION_0_1,
93            .module = &HAL_MODULE_INFO_SYM.common,
94            .close = radv_hal_close,
95         },
96      .EnumerateInstanceExtensionProperties = radv_EnumerateInstanceExtensionProperties,
97      .CreateInstance = radv_CreateInstance,
98      .GetInstanceProcAddr = radv_GetInstanceProcAddr,
99   };
100
101   *dev = &hal_dev->common;
102   return 0;
103}
104
105static int
106radv_hal_close(struct hw_device_t *dev)
107{
108   /* hwvulkan.h claims that hw_device_t::close() is never called. */
109   return -1;
110}
111
112VkResult
113radv_image_from_gralloc(VkDevice device_h, const VkImageCreateInfo *base_info,
114                        const VkNativeBufferANDROID *gralloc_info,
115                        const VkAllocationCallbacks *alloc, VkImage *out_image_h)
116
117{
118   RADV_FROM_HANDLE(radv_device, device, device_h);
119   VkImage image_h = VK_NULL_HANDLE;
120   struct radv_image *image = NULL;
121   VkResult result;
122
123   if (gralloc_info->handle->numFds != 1) {
124      return vk_errorf(device, VK_ERROR_INVALID_EXTERNAL_HANDLE,
125                       "VkNativeBufferANDROID::handle::numFds is %d, "
126                       "expected 1",
127                       gralloc_info->handle->numFds);
128   }
129
130   /* Do not close the gralloc handle's dma_buf. The lifetime of the dma_buf
131    * must exceed that of the gralloc handle, and we do not own the gralloc
132    * handle.
133    */
134   int dma_buf = gralloc_info->handle->data[0];
135
136   VkDeviceMemory memory_h;
137
138   const VkImportMemoryFdInfoKHR import_info = {
139      .sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR,
140      .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT,
141      .fd = os_dupfd_cloexec(dma_buf),
142   };
143
144   /* Find the first VRAM memory type, or GART for PRIME images. */
145   int memory_type_index = -1;
146   for (int i = 0; i < device->physical_device->memory_properties.memoryTypeCount; ++i) {
147      bool is_local = !!(device->physical_device->memory_properties.memoryTypes[i].propertyFlags &
148                         VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
149      if (is_local) {
150         memory_type_index = i;
151         break;
152      }
153   }
154
155   /* fallback */
156   if (memory_type_index == -1)
157      memory_type_index = 0;
158
159   result = radv_AllocateMemory(device_h,
160                                &(VkMemoryAllocateInfo){
161                                   .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
162                                   .pNext = &import_info,
163                                   /* Max buffer size, unused for imports */
164                                   .allocationSize = 0x7FFFFFFF,
165                                   .memoryTypeIndex = memory_type_index,
166                                },
167                                alloc, &memory_h);
168   if (result != VK_SUCCESS)
169      return result;
170
171   struct radeon_bo_metadata md;
172   device->ws->buffer_get_metadata(device->ws, radv_device_memory_from_handle(memory_h)->bo, &md);
173
174   VkImageCreateInfo updated_base_info = *base_info;
175
176   VkExternalMemoryImageCreateInfo external_memory_info = {
177      .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO,
178      .pNext = updated_base_info.pNext,
179      .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
180   };
181
182   updated_base_info.pNext = &external_memory_info;
183
184   result = radv_image_create(device_h,
185                              &(struct radv_image_create_info){
186                                 .vk_info = &updated_base_info,
187                                 .no_metadata_planes = true,
188                                 .bo_metadata = &md,
189                              },
190                              alloc, &image_h);
191
192   if (result != VK_SUCCESS)
193      goto fail_create_image;
194
195   image = radv_image_from_handle(image_h);
196
197   radv_image_override_offset_stride(device, image, 0, gralloc_info->stride);
198
199   VkBindImageMemoryInfo bind_info = {
200      .sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO,
201      .image = image_h,
202      .memory = memory_h,
203      .memoryOffset = 0
204   };
205   radv_BindImageMemory2(device_h, 1, &bind_info);
206
207   image->owned_memory = memory_h;
208   /* Don't clobber the out-parameter until success is certain. */
209   *out_image_h = image_h;
210
211   return VK_SUCCESS;
212
213fail_create_image:
214   radv_FreeMemory(device_h, memory_h, alloc);
215   return result;
216}
217
218VkResult
219radv_GetSwapchainGrallocUsageANDROID(VkDevice device_h, VkFormat format,
220                                     VkImageUsageFlags imageUsage, int *grallocUsage)
221{
222   RADV_FROM_HANDLE(radv_device, device, device_h);
223   struct radv_physical_device *phys_dev = device->physical_device;
224   VkPhysicalDevice phys_dev_h = radv_physical_device_to_handle(phys_dev);
225   VkResult result;
226
227   *grallocUsage = 0;
228
229   /* WARNING: Android Nougat's libvulkan.so hardcodes the VkImageUsageFlags
230    * returned to applications via VkSurfaceCapabilitiesKHR::supportedUsageFlags.
231    * The relevant code in libvulkan/swapchain.cpp contains this fun comment:
232    *
233    *     TODO(jessehall): I think these are right, but haven't thought hard
234    *     about it. Do we need to query the driver for support of any of
235    *     these?
236    *
237    * Any disagreement between this function and the hardcoded
238    * VkSurfaceCapabilitiesKHR:supportedUsageFlags causes tests
239    * dEQP-VK.wsi.android.swapchain.*.image_usage to fail.
240    */
241
242   const VkPhysicalDeviceImageFormatInfo2 image_format_info = {
243      .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
244      .format = format,
245      .type = VK_IMAGE_TYPE_2D,
246      .tiling = VK_IMAGE_TILING_OPTIMAL,
247      .usage = imageUsage,
248   };
249
250   VkImageFormatProperties2 image_format_props = {
251      .sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
252   };
253
254   /* Check that requested format and usage are supported. */
255   result = radv_GetPhysicalDeviceImageFormatProperties2(phys_dev_h, &image_format_info,
256                                                         &image_format_props);
257   if (result != VK_SUCCESS) {
258      return vk_errorf(device, result,
259                       "radv_GetPhysicalDeviceImageFormatProperties2 failed "
260                       "inside %s",
261                       __func__);
262   }
263
264   if (unmask32(&imageUsage, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT))
265      *grallocUsage |= GRALLOC_USAGE_HW_RENDER;
266
267   if (unmask32(&imageUsage, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT |
268                                VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT))
269      *grallocUsage |= GRALLOC_USAGE_HW_TEXTURE;
270
271   /* All VkImageUsageFlags not explicitly checked here are unsupported for
272    * gralloc swapchains.
273    */
274   if (imageUsage != 0) {
275      return vk_errorf(device, VK_ERROR_FORMAT_NOT_SUPPORTED,
276                       "unsupported VkImageUsageFlags(0x%x) for gralloc "
277                       "swapchain",
278                       imageUsage);
279   }
280
281   /*
282    * FINISHME: Advertise all display-supported formats. Mostly
283    * DRM_FORMAT_ARGB2101010 and DRM_FORMAT_ABGR2101010, but need to check
284    * what we need for 30-bit colors.
285    */
286   if (format == VK_FORMAT_B8G8R8A8_UNORM || format == VK_FORMAT_B5G6R5_UNORM_PACK16) {
287      *grallocUsage |=
288         GRALLOC_USAGE_HW_FB | GRALLOC_USAGE_HW_COMPOSER | GRALLOC_USAGE_EXTERNAL_DISP;
289   }
290
291   if (*grallocUsage == 0)
292      return VK_ERROR_FORMAT_NOT_SUPPORTED;
293
294   return VK_SUCCESS;
295}
296
297VkResult
298radv_GetSwapchainGrallocUsage2ANDROID(VkDevice device_h, VkFormat format,
299                                      VkImageUsageFlags imageUsage,
300                                      VkSwapchainImageUsageFlagsANDROID swapchainImageUsage,
301                                      uint64_t *grallocConsumerUsage,
302                                      uint64_t *grallocProducerUsage)
303{
304   /* Before level 26 (Android 8.0/Oreo) the loader uses
305    * vkGetSwapchainGrallocUsageANDROID. */
306#if ANDROID_API_LEVEL >= 26
307   RADV_FROM_HANDLE(radv_device, device, device_h);
308   struct radv_physical_device *phys_dev = device->physical_device;
309   VkPhysicalDevice phys_dev_h = radv_physical_device_to_handle(phys_dev);
310   VkResult result;
311
312   *grallocConsumerUsage = 0;
313   *grallocProducerUsage = 0;
314
315   if (swapchainImageUsage & VK_SWAPCHAIN_IMAGE_USAGE_SHARED_BIT_ANDROID)
316      return vk_errorf(device, VK_ERROR_FORMAT_NOT_SUPPORTED,
317                       "The Vulkan loader tried to query shared presentable image support");
318
319   const VkPhysicalDeviceImageFormatInfo2 image_format_info = {
320      .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
321      .format = format,
322      .type = VK_IMAGE_TYPE_2D,
323      .tiling = VK_IMAGE_TILING_OPTIMAL,
324      .usage = imageUsage,
325   };
326
327   VkImageFormatProperties2 image_format_props = {
328      .sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
329   };
330
331   /* Check that requested format and usage are supported. */
332   result = radv_GetPhysicalDeviceImageFormatProperties2(phys_dev_h, &image_format_info,
333                                                         &image_format_props);
334   if (result != VK_SUCCESS) {
335      return vk_errorf(device, result,
336                       "radv_GetPhysicalDeviceImageFormatProperties2 failed "
337                       "inside %s",
338                       __func__);
339   }
340
341   if (unmask32(&imageUsage,
342                VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)) {
343      *grallocProducerUsage |= GRALLOC1_PRODUCER_USAGE_GPU_RENDER_TARGET;
344      *grallocConsumerUsage |= GRALLOC1_CONSUMER_USAGE_CLIENT_TARGET;
345   }
346
347   if (unmask32(&imageUsage, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT |
348                                VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)) {
349      *grallocConsumerUsage |= GRALLOC1_CONSUMER_USAGE_GPU_TEXTURE;
350   }
351
352   if (imageUsage != 0) {
353      return vk_errorf(device, VK_ERROR_FORMAT_NOT_SUPPORTED,
354                       "unsupported VkImageUsageFlags(0x%x) for gralloc "
355                       "swapchain",
356                       imageUsage);
357   }
358
359   /*
360    * FINISHME: Advertise all display-supported formats. Mostly
361    * DRM_FORMAT_ARGB2101010 and DRM_FORMAT_ABGR2101010, but need to check
362    * what we need for 30-bit colors.
363    */
364   if (format == VK_FORMAT_B8G8R8A8_UNORM || format == VK_FORMAT_B5G6R5_UNORM_PACK16) {
365      *grallocProducerUsage |= GRALLOC1_PRODUCER_USAGE_GPU_RENDER_TARGET;
366      *grallocConsumerUsage |= GRALLOC1_CONSUMER_USAGE_HWCOMPOSER;
367   }
368
369   if (!*grallocProducerUsage && !*grallocConsumerUsage)
370      return VK_ERROR_FORMAT_NOT_SUPPORTED;
371
372   return VK_SUCCESS;
373#else
374   *grallocConsumerUsage = 0;
375   *grallocProducerUsage = 0;
376   return VK_ERROR_FORMAT_NOT_SUPPORTED;
377#endif
378}
379
380VkResult
381radv_AcquireImageANDROID(VkDevice device_h, VkImage image_h, int nativeFenceFd, VkSemaphore semaphore,
382                         VkFence fence)
383{
384   RADV_FROM_HANDLE(radv_device, device, device_h);
385   VkResult result = VK_SUCCESS;
386
387   /* From https://source.android.com/devices/graphics/implement-vulkan :
388    *
389    *    "The driver takes ownership of the fence file descriptor and closes
390    *    the fence file descriptor when no longer needed. The driver must do
391    *    so even if neither a semaphore or fence object is provided, or even
392    *    if vkAcquireImageANDROID fails and returns an error."
393    *
394    * The Vulkan spec for VkImportFence/SemaphoreFdKHR(), however, requires
395    * the file descriptor to be left alone on failure.
396    */
397   int semaphore_fd = -1, fence_fd = -1;
398   if (nativeFenceFd >= 0) {
399      if (semaphore != VK_NULL_HANDLE && fence != VK_NULL_HANDLE) {
400         /* We have both so we have to import the sync file twice. One of
401          * them needs to be a dup.
402          */
403         semaphore_fd = nativeFenceFd;
404         fence_fd = dup(nativeFenceFd);
405         if (fence_fd < 0) {
406            VkResult err = (errno == EMFILE) ? VK_ERROR_TOO_MANY_OBJECTS :
407                                               VK_ERROR_OUT_OF_HOST_MEMORY;
408            close(nativeFenceFd);
409            return vk_error(device, err);
410         }
411      } else if (semaphore != VK_NULL_HANDLE) {
412         semaphore_fd = nativeFenceFd;
413      } else if (fence != VK_NULL_HANDLE) {
414         fence_fd = nativeFenceFd;
415      } else {
416         /* Nothing to import into so we have to close the file */
417         close(nativeFenceFd);
418      }
419   }
420
421   if (semaphore != VK_NULL_HANDLE) {
422      const VkImportSemaphoreFdInfoKHR info = {
423         .sType = VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR,
424         .semaphore = semaphore,
425         .flags = VK_SEMAPHORE_IMPORT_TEMPORARY_BIT,
426         .handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT,
427         .fd = semaphore_fd,
428      };
429      result = radv_ImportSemaphoreFdKHR(device_h, &info);
430      if (result == VK_SUCCESS)
431         semaphore_fd = -1; /* RADV took ownership */
432   }
433
434   if (result == VK_SUCCESS && fence != VK_NULL_HANDLE) {
435      const VkImportFenceFdInfoKHR info = {
436         .sType = VK_STRUCTURE_TYPE_IMPORT_FENCE_FD_INFO_KHR,
437         .fence = fence,
438         .flags = VK_FENCE_IMPORT_TEMPORARY_BIT,
439         .handleType = VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT,
440         .fd = fence_fd,
441      };
442      result = radv_ImportFenceFdKHR(device_h, &info);
443      if (result == VK_SUCCESS)
444         fence_fd = -1; /* RADV took ownership */
445   }
446
447   if (semaphore_fd >= 0)
448      close(semaphore_fd);
449   if (fence_fd >= 0)
450      close(fence_fd);
451
452   return result;
453}
454
455VkResult
456radv_QueueSignalReleaseImageANDROID(VkQueue _queue, uint32_t waitSemaphoreCount,
457                                    const VkSemaphore *pWaitSemaphores, VkImage image,
458                                    int *pNativeFenceFd)
459{
460   RADV_FROM_HANDLE(radv_queue, queue, _queue);
461   VkResult result = VK_SUCCESS;
462
463   if (waitSemaphoreCount == 0) {
464      if (pNativeFenceFd)
465         *pNativeFenceFd = -1;
466      return VK_SUCCESS;
467   }
468
469   int fd = -1;
470
471   for (uint32_t i = 0; i < waitSemaphoreCount; ++i) {
472      int tmp_fd;
473      result =
474         radv_GetSemaphoreFdKHR(radv_device_to_handle(queue->device),
475                                &(VkSemaphoreGetFdInfoKHR){
476                                   .sType = VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR,
477                                   .handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT,
478                                   .semaphore = pWaitSemaphores[i],
479                                },
480                                &tmp_fd);
481      if (result != VK_SUCCESS) {
482         if (fd >= 0)
483            close(fd);
484         return result;
485      }
486
487      if (fd < 0)
488         fd = tmp_fd;
489      else if (tmp_fd >= 0) {
490         sync_accumulate("radv", &fd, tmp_fd);
491         close(tmp_fd);
492      }
493   }
494
495   if (pNativeFenceFd) {
496      *pNativeFenceFd = fd;
497   } else if (fd >= 0) {
498      close(fd);
499      /* We still need to do the exports, to reset the semaphores, but
500       * otherwise we don't wait on them. */
501   }
502   return VK_SUCCESS;
503}
504#endif
505
506#if RADV_SUPPORT_ANDROID_HARDWARE_BUFFER
507
508enum {
509   /* Usage bit equal to GRALLOC_USAGE_HW_CAMERA_MASK */
510   BUFFER_USAGE_CAMERA_MASK = 0x00060000U,
511};
512
513static inline VkFormat
514vk_format_from_android(unsigned android_format, unsigned android_usage)
515{
516   switch (android_format) {
517   case AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM:
518   case AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM:
519      return VK_FORMAT_R8G8B8A8_UNORM;
520   case AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM:
521      return VK_FORMAT_R8G8B8_UNORM;
522   case AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM:
523      return VK_FORMAT_R5G6B5_UNORM_PACK16;
524   case AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT:
525      return VK_FORMAT_R16G16B16A16_SFLOAT;
526   case AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM:
527      return VK_FORMAT_A2B10G10R10_UNORM_PACK32;
528   case AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420:
529      return VK_FORMAT_G8_B8R8_2PLANE_420_UNORM;
530   case AHARDWAREBUFFER_FORMAT_IMPLEMENTATION_DEFINED:
531      if (android_usage & BUFFER_USAGE_CAMERA_MASK)
532         return VK_FORMAT_G8_B8R8_2PLANE_420_UNORM;
533      else
534         return VK_FORMAT_R8G8B8_UNORM;
535   case AHARDWAREBUFFER_FORMAT_BLOB:
536   default:
537      return VK_FORMAT_UNDEFINED;
538   }
539}
540
541static inline unsigned
542android_format_from_vk(unsigned vk_format)
543{
544   switch (vk_format) {
545   case VK_FORMAT_R8G8B8A8_UNORM:
546      return AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
547   case VK_FORMAT_R8G8B8_UNORM:
548      return AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM;
549   case VK_FORMAT_R5G6B5_UNORM_PACK16:
550      return AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM;
551   case VK_FORMAT_R16G16B16A16_SFLOAT:
552      return AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT;
553   case VK_FORMAT_A2B10G10R10_UNORM_PACK32:
554      return AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM;
555   case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
556      return AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420;
557   default:
558      return AHARDWAREBUFFER_FORMAT_BLOB;
559   }
560}
561
562uint64_t
563radv_ahb_usage_from_vk_usage(const VkImageCreateFlags vk_create, const VkImageUsageFlags vk_usage)
564{
565   uint64_t ahb_usage = 0;
566   if (vk_usage & VK_IMAGE_USAGE_SAMPLED_BIT)
567      ahb_usage |= AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
568
569   if (vk_usage & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)
570      ahb_usage |= AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
571
572   if (vk_usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)
573      ahb_usage |= AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT;
574
575   if (vk_create & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT)
576      ahb_usage |= AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP;
577
578   if (vk_create & VK_IMAGE_CREATE_PROTECTED_BIT)
579      ahb_usage |= AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT;
580
581   /* No usage bits set - set at least one GPU usage. */
582   if (ahb_usage == 0)
583      ahb_usage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
584   return ahb_usage;
585}
586
587static VkResult
588get_ahb_buffer_format_properties(VkDevice device_h, const struct AHardwareBuffer *buffer,
589                                 VkAndroidHardwareBufferFormatPropertiesANDROID *pProperties)
590{
591   RADV_FROM_HANDLE(radv_device, device, device_h);
592
593   /* Get a description of buffer contents . */
594   AHardwareBuffer_Desc desc;
595   AHardwareBuffer_describe(buffer, &desc);
596
597   /* Verify description. */
598   const uint64_t gpu_usage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE |
599                              AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT |
600                              AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER;
601
602   /* "Buffer must be a valid Android hardware buffer object with at least
603    * one of the AHARDWAREBUFFER_USAGE_GPU_* usage flags."
604    */
605   if (!(desc.usage & (gpu_usage)))
606      return VK_ERROR_INVALID_EXTERNAL_HANDLE;
607
608   /* Fill properties fields based on description. */
609   VkAndroidHardwareBufferFormatPropertiesANDROID *p = pProperties;
610
611   p->format = vk_format_from_android(desc.format, desc.usage);
612   p->externalFormat = (uint64_t)(uintptr_t)p->format;
613
614   VkFormatProperties2 format_properties = {
615      .sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2
616   };
617
618   radv_GetPhysicalDeviceFormatProperties2(radv_physical_device_to_handle(device->physical_device),
619                                               p->format, &format_properties);
620
621   if (desc.usage & AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER)
622      p->formatFeatures = format_properties.formatProperties.linearTilingFeatures;
623   else
624      p->formatFeatures = format_properties.formatProperties.optimalTilingFeatures;
625
626   /* "Images can be created with an external format even if the Android hardware
627    *  buffer has a format which has an equivalent Vulkan format to enable
628    *  consistent handling of images from sources that might use either category
629    *  of format. However, all images created with an external format are subject
630    *  to the valid usage requirements associated with external formats, even if
631    *  the Android hardware buffer’s format has a Vulkan equivalent."
632    *
633    * "The formatFeatures member *must* include
634    *  VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT and at least one of
635    *  VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT or
636    *  VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT"
637    */
638   assert(p->formatFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT);
639
640   p->formatFeatures |= VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT;
641
642   /* "Implementations may not always be able to determine the color model,
643    *  numerical range, or chroma offsets of the image contents, so the values
644    *  in VkAndroidHardwareBufferFormatPropertiesANDROID are only suggestions.
645    *  Applications should treat these values as sensible defaults to use in
646    *  the absence of more reliable information obtained through some other
647    *  means."
648    */
649   p->samplerYcbcrConversionComponents.r = VK_COMPONENT_SWIZZLE_IDENTITY;
650   p->samplerYcbcrConversionComponents.g = VK_COMPONENT_SWIZZLE_IDENTITY;
651   p->samplerYcbcrConversionComponents.b = VK_COMPONENT_SWIZZLE_IDENTITY;
652   p->samplerYcbcrConversionComponents.a = VK_COMPONENT_SWIZZLE_IDENTITY;
653
654   p->suggestedYcbcrModel = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601;
655   p->suggestedYcbcrRange = VK_SAMPLER_YCBCR_RANGE_ITU_FULL;
656
657   p->suggestedXChromaOffset = VK_CHROMA_LOCATION_MIDPOINT;
658   p->suggestedYChromaOffset = VK_CHROMA_LOCATION_MIDPOINT;
659
660   return VK_SUCCESS;
661}
662
663static VkResult
664get_ahb_buffer_format_properties2(VkDevice device_h, const struct AHardwareBuffer *buffer,
665                                  VkAndroidHardwareBufferFormatProperties2ANDROID *pProperties)
666{
667   RADV_FROM_HANDLE(radv_device, device, device_h);
668
669   /* Get a description of buffer contents . */
670   AHardwareBuffer_Desc desc;
671   AHardwareBuffer_describe(buffer, &desc);
672
673   /* Verify description. */
674   const uint64_t gpu_usage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE |
675                              AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT |
676                              AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER;
677
678   /* "Buffer must be a valid Android hardware buffer object with at least
679    * one of the AHARDWAREBUFFER_USAGE_GPU_* usage flags."
680    */
681   if (!(desc.usage & (gpu_usage)))
682      return VK_ERROR_INVALID_EXTERNAL_HANDLE;
683
684   /* Fill properties fields based on description. */
685   VkAndroidHardwareBufferFormatProperties2ANDROID *p = pProperties;
686
687   p->format = vk_format_from_android(desc.format, desc.usage);
688   p->externalFormat = (uint64_t)(uintptr_t)p->format;
689
690   VkFormatProperties2 format_properties = {
691      .sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2
692   };
693
694   radv_GetPhysicalDeviceFormatProperties2(radv_physical_device_to_handle(device->physical_device),
695                                               p->format, &format_properties);
696
697   if (desc.usage & AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER)
698      p->formatFeatures = format_properties.formatProperties.linearTilingFeatures;
699   else
700      p->formatFeatures = format_properties.formatProperties.optimalTilingFeatures;
701
702   /* "Images can be created with an external format even if the Android hardware
703    *  buffer has a format which has an equivalent Vulkan format to enable
704    *  consistent handling of images from sources that might use either category
705    *  of format. However, all images created with an external format are subject
706    *  to the valid usage requirements associated with external formats, even if
707    *  the Android hardware buffer’s format has a Vulkan equivalent."
708    *
709    * "The formatFeatures member *must* include
710    *  VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT_KHR and at least one of
711    *  VK_FORMAT_FEATURE_2_MIDPOINT_CHROMA_SAMPLES_BIT_KHR or
712    *  VK_FORMAT_FEATURE_2_COSITED_CHROMA_SAMPLES_BIT_KHR"
713    */
714   assert(p->formatFeatures & VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT_KHR);
715
716   p->formatFeatures |= VK_FORMAT_FEATURE_2_MIDPOINT_CHROMA_SAMPLES_BIT_KHR;
717
718   /* "Implementations may not always be able to determine the color model,
719    *  numerical range, or chroma offsets of the image contents, so the values
720    *  in VkAndroidHardwareBufferFormatPropertiesANDROID are only suggestions.
721    *  Applications should treat these values as sensible defaults to use in
722    *  the absence of more reliable information obtained through some other
723    *  means."
724    */
725   p->samplerYcbcrConversionComponents.r = VK_COMPONENT_SWIZZLE_IDENTITY;
726   p->samplerYcbcrConversionComponents.g = VK_COMPONENT_SWIZZLE_IDENTITY;
727   p->samplerYcbcrConversionComponents.b = VK_COMPONENT_SWIZZLE_IDENTITY;
728   p->samplerYcbcrConversionComponents.a = VK_COMPONENT_SWIZZLE_IDENTITY;
729
730   p->suggestedYcbcrModel = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601;
731   p->suggestedYcbcrRange = VK_SAMPLER_YCBCR_RANGE_ITU_FULL;
732
733   p->suggestedXChromaOffset = VK_CHROMA_LOCATION_MIDPOINT;
734   p->suggestedYChromaOffset = VK_CHROMA_LOCATION_MIDPOINT;
735
736   return VK_SUCCESS;
737}
738
739VkResult
740radv_GetAndroidHardwareBufferPropertiesANDROID(VkDevice device_h,
741                                               const struct AHardwareBuffer *buffer,
742                                               VkAndroidHardwareBufferPropertiesANDROID *pProperties)
743{
744   RADV_FROM_HANDLE(radv_device, dev, device_h);
745   struct radv_physical_device *pdevice = dev->physical_device;
746
747   VkAndroidHardwareBufferFormatPropertiesANDROID *format_prop =
748      vk_find_struct(pProperties->pNext, ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID);
749
750   /* Fill format properties of an Android hardware buffer. */
751   if (format_prop)
752      get_ahb_buffer_format_properties(device_h, buffer, format_prop);
753
754   VkAndroidHardwareBufferFormatProperties2ANDROID *format_prop2 =
755      vk_find_struct(pProperties->pNext, ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_2_ANDROID);
756   if (format_prop2)
757      get_ahb_buffer_format_properties2(device_h, buffer, format_prop2);
758
759   /* NOTE - We support buffers with only one handle but do not error on
760    * multiple handle case. Reason is that we want to support YUV formats
761    * where we have many logical planes but they all point to the same
762    * buffer, like is the case with VK_FORMAT_G8_B8R8_2PLANE_420_UNORM.
763    */
764   const native_handle_t *handle = AHardwareBuffer_getNativeHandle(buffer);
765   int dma_buf = (handle && handle->numFds) ? handle->data[0] : -1;
766   if (dma_buf < 0)
767      return VK_ERROR_INVALID_EXTERNAL_HANDLE;
768
769   /* All memory types. */
770   uint32_t memory_types = (1u << pdevice->memory_properties.memoryTypeCount) - 1;
771
772   pProperties->allocationSize = lseek(dma_buf, 0, SEEK_END);
773   pProperties->memoryTypeBits = memory_types;
774
775   return VK_SUCCESS;
776}
777
778VkResult
779radv_GetMemoryAndroidHardwareBufferANDROID(VkDevice device_h,
780                                           const VkMemoryGetAndroidHardwareBufferInfoANDROID *pInfo,
781                                           struct AHardwareBuffer **pBuffer)
782{
783   RADV_FROM_HANDLE(radv_device_memory, mem, pInfo->memory);
784
785   /* This should always be set due to the export handle types being set on
786    * allocation. */
787   assert(mem->android_hardware_buffer);
788
789   /* Some quotes from Vulkan spec:
790    *
791    * "If the device memory was created by importing an Android hardware
792    * buffer, vkGetMemoryAndroidHardwareBufferANDROID must return that same
793    * Android hardware buffer object."
794    *
795    * "VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID must
796    * have been included in VkExportMemoryAllocateInfo::handleTypes when
797    * memory was created."
798    */
799   *pBuffer = mem->android_hardware_buffer;
800   /* Increase refcount. */
801   AHardwareBuffer_acquire(mem->android_hardware_buffer);
802   return VK_SUCCESS;
803}
804
805#endif
806
807VkFormat
808radv_select_android_external_format(const void *next, VkFormat default_format)
809{
810#if RADV_SUPPORT_ANDROID_HARDWARE_BUFFER
811   const VkExternalFormatANDROID *android_format =
812      vk_find_struct_const(next, EXTERNAL_FORMAT_ANDROID);
813
814   if (android_format && android_format->externalFormat) {
815      return (VkFormat)android_format->externalFormat;
816   }
817#endif
818
819   return default_format;
820}
821
822VkResult
823radv_import_ahb_memory(struct radv_device *device, struct radv_device_memory *mem,
824                       unsigned priority, const VkImportAndroidHardwareBufferInfoANDROID *info)
825{
826#if RADV_SUPPORT_ANDROID_HARDWARE_BUFFER
827   /* Import from AHardwareBuffer to radv_device_memory. */
828   const native_handle_t *handle = AHardwareBuffer_getNativeHandle(info->buffer);
829
830   /* NOTE - We support buffers with only one handle but do not error on
831    * multiple handle case. Reason is that we want to support YUV formats
832    * where we have many logical planes but they all point to the same
833    * buffer, like is the case with VK_FORMAT_G8_B8R8_2PLANE_420_UNORM.
834    */
835   int dma_buf = (handle && handle->numFds) ? handle->data[0] : -1;
836   if (dma_buf < 0)
837      return VK_ERROR_INVALID_EXTERNAL_HANDLE;
838
839   uint64_t alloc_size = 0;
840   VkResult result =
841      device->ws->buffer_from_fd(device->ws, dma_buf, priority, &mem->bo, &alloc_size);
842   if (result != VK_SUCCESS)
843      return result;
844
845   if (mem->image) {
846      struct radeon_bo_metadata metadata;
847      device->ws->buffer_get_metadata(device->ws, mem->bo, &metadata);
848
849      struct radv_image_create_info create_info = {.no_metadata_planes = true,
850                                                   .bo_metadata = &metadata};
851
852      VkResult result = radv_image_create_layout(device, create_info, NULL, mem->image);
853      if (result != VK_SUCCESS) {
854         device->ws->buffer_destroy(device->ws, mem->bo);
855         mem->bo = NULL;
856         return result;
857      }
858
859      if (alloc_size < mem->image->size) {
860         device->ws->buffer_destroy(device->ws, mem->bo);
861         mem->bo = NULL;
862         return VK_ERROR_INVALID_EXTERNAL_HANDLE;
863      }
864   } else if (mem->buffer) {
865      if (alloc_size < mem->buffer->size) {
866         device->ws->buffer_destroy(device->ws, mem->bo);
867         mem->bo = NULL;
868         return VK_ERROR_INVALID_EXTERNAL_HANDLE;
869      }
870   }
871
872   /* "If the vkAllocateMemory command succeeds, the implementation must
873    * acquire a reference to the imported hardware buffer, which it must
874    * release when the device memory object is freed. If the command fails,
875    * the implementation must not retain a reference."
876    */
877   AHardwareBuffer_acquire(info->buffer);
878   mem->android_hardware_buffer = info->buffer;
879
880   return VK_SUCCESS;
881#else /* RADV_SUPPORT_ANDROID_HARDWARE_BUFFER */
882   return VK_ERROR_EXTENSION_NOT_PRESENT;
883#endif
884}
885
886VkResult
887radv_create_ahb_memory(struct radv_device *device, struct radv_device_memory *mem,
888                       unsigned priority, const VkMemoryAllocateInfo *pAllocateInfo)
889{
890#if RADV_SUPPORT_ANDROID_HARDWARE_BUFFER
891   const VkMemoryDedicatedAllocateInfo *dedicated_info =
892      vk_find_struct_const(pAllocateInfo->pNext, MEMORY_DEDICATED_ALLOCATE_INFO);
893
894   uint32_t w = 0;
895   uint32_t h = 1;
896   uint32_t layers = 1;
897   uint32_t format = 0;
898   uint64_t usage = 0;
899
900   /* If caller passed dedicated information. */
901   if (dedicated_info && dedicated_info->image) {
902      RADV_FROM_HANDLE(radv_image, image, dedicated_info->image);
903      w = image->info.width;
904      h = image->info.height;
905      layers = image->info.array_size;
906      format = android_format_from_vk(image->vk_format);
907      usage = radv_ahb_usage_from_vk_usage(image->flags, image->usage);
908   } else if (dedicated_info && dedicated_info->buffer) {
909      RADV_FROM_HANDLE(radv_buffer, buffer, dedicated_info->buffer);
910      w = buffer->size;
911      format = AHARDWAREBUFFER_FORMAT_BLOB;
912      usage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN | AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN;
913   } else {
914      w = pAllocateInfo->allocationSize;
915      format = AHARDWAREBUFFER_FORMAT_BLOB;
916      usage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN | AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN;
917   }
918
919   struct AHardwareBuffer *android_hardware_buffer = NULL;
920   struct AHardwareBuffer_Desc desc = {
921      .width = w,
922      .height = h,
923      .layers = layers,
924      .format = format,
925      .usage = usage,
926   };
927
928   if (AHardwareBuffer_allocate(&desc, &android_hardware_buffer) != 0)
929      return VK_ERROR_OUT_OF_HOST_MEMORY;
930
931   mem->android_hardware_buffer = android_hardware_buffer;
932
933   const struct VkImportAndroidHardwareBufferInfoANDROID import_info = {
934      .buffer = mem->android_hardware_buffer,
935   };
936
937   VkResult result = radv_import_ahb_memory(device, mem, priority, &import_info);
938
939   /* Release a reference to avoid leak for AHB allocation. */
940   AHardwareBuffer_release(mem->android_hardware_buffer);
941
942   return result;
943#else /* RADV_SUPPORT_ANDROID_HARDWARE_BUFFER */
944   return VK_ERROR_EXTENSION_NOT_PRESENT;
945#endif
946}
947
948bool
949radv_android_gralloc_supports_format(VkFormat format, VkImageUsageFlagBits usage)
950{
951#if RADV_SUPPORT_ANDROID_HARDWARE_BUFFER
952   /* Ideally we check Gralloc for what it supports and then merge that with the radv
953      format support, but there is no easy gralloc query besides just creating an image.
954      That seems a bit on the expensive side, so just hardcode for now. */
955   /* TODO: Add multi-plane formats after confirming everything works between radeonsi
956      and radv. */
957   switch (format) {
958   case VK_FORMAT_R8G8B8A8_UNORM:
959   case VK_FORMAT_R5G6B5_UNORM_PACK16:
960      return true;
961   case VK_FORMAT_R8_UNORM:
962   case VK_FORMAT_R8G8_UNORM:
963      return !(usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
964   default:
965      return false;
966   }
967#else
968   (void)format;
969   (void)usage;
970   return false;
971#endif
972}
973