1/*
2 * Copyright 2021 Google LLC
3 * SPDX-License-Identifier: MIT
4 *
5 * based in part on anv and radv which are:
6 * Copyright © 2015 Intel Corporation
7 * Copyright © 2016 Red Hat
8 * Copyright © 2016 Bas Nieuwenhuizen
9 */
10
11#include "vn_android.h"
12
13#include <dlfcn.h>
14#include <hardware/gralloc.h>
15#include <hardware/hwvulkan.h>
16#include <vndk/hardware_buffer.h>
17#include <vulkan/vk_icd.h>
18
19#include "drm-uapi/drm_fourcc.h"
20#include "util/libsync.h"
21#include "util/os_file.h"
22
23#include "vn_buffer.h"
24#include "vn_device.h"
25#include "vn_device_memory.h"
26#include "vn_image.h"
27#include "vn_instance.h"
28#include "vn_physical_device.h"
29#include "vn_queue.h"
30
31static int
32vn_hal_open(const struct hw_module_t *mod,
33            const char *id,
34            struct hw_device_t **dev);
35
36static void UNUSED
37static_asserts(void)
38{
39   STATIC_ASSERT(HWVULKAN_DISPATCH_MAGIC == ICD_LOADER_MAGIC);
40}
41
42PUBLIC struct hwvulkan_module_t HAL_MODULE_INFO_SYM = {
43   .common = {
44      .tag = HARDWARE_MODULE_TAG,
45      .module_api_version = HWVULKAN_MODULE_API_VERSION_0_1,
46      .hal_api_version = HARDWARE_HAL_API_VERSION,
47      .id = HWVULKAN_HARDWARE_MODULE_ID,
48      .name = "Venus Vulkan HAL",
49      .author = "Google LLC",
50      .methods = &(hw_module_methods_t) {
51         .open = vn_hal_open,
52      },
53   },
54};
55
56static const gralloc_module_t *gralloc = NULL;
57
58static int
59vn_hal_close(UNUSED struct hw_device_t *dev)
60{
61   dlclose(gralloc->common.dso);
62   return 0;
63}
64
65static hwvulkan_device_t vn_hal_dev = {
66  .common = {
67     .tag = HARDWARE_DEVICE_TAG,
68     .version = HWVULKAN_DEVICE_API_VERSION_0_1,
69     .module = &HAL_MODULE_INFO_SYM.common,
70     .close = vn_hal_close,
71  },
72 .EnumerateInstanceExtensionProperties = vn_EnumerateInstanceExtensionProperties,
73 .CreateInstance = vn_CreateInstance,
74 .GetInstanceProcAddr = vn_GetInstanceProcAddr,
75};
76
77static int
78vn_hal_open(const struct hw_module_t *mod,
79            const char *id,
80            struct hw_device_t **dev)
81{
82   static const char CROS_GRALLOC_MODULE_NAME[] = "CrOS Gralloc";
83
84   assert(mod == &HAL_MODULE_INFO_SYM.common);
85   assert(strcmp(id, HWVULKAN_DEVICE_0) == 0);
86
87   /* get gralloc module for gralloc buffer info query */
88   int ret = hw_get_module(GRALLOC_HARDWARE_MODULE_ID,
89                           (const hw_module_t **)&gralloc);
90   if (ret) {
91      if (VN_DEBUG(WSI))
92         vn_log(NULL, "failed to open gralloc module(ret=%d)", ret);
93      return ret;
94   }
95
96   if (VN_DEBUG(WSI))
97      vn_log(NULL, "opened gralloc module name: %s", gralloc->common.name);
98
99   if (strcmp(gralloc->common.name, CROS_GRALLOC_MODULE_NAME) != 0 ||
100       !gralloc->perform) {
101      dlclose(gralloc->common.dso);
102      return -1;
103   }
104
105   *dev = &vn_hal_dev.common;
106
107   return 0;
108}
109
110static uint32_t
111vn_android_ahb_format_from_vk_format(VkFormat format)
112{
113   switch (format) {
114   case VK_FORMAT_R8G8B8A8_UNORM:
115      return AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
116   case VK_FORMAT_R8G8B8_UNORM:
117      return AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM;
118   case VK_FORMAT_R5G6B5_UNORM_PACK16:
119      return AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM;
120   case VK_FORMAT_R16G16B16A16_SFLOAT:
121      return AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT;
122   case VK_FORMAT_A2B10G10R10_UNORM_PACK32:
123      return AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM;
124   case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
125      return AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420;
126   default:
127      return 0;
128   }
129}
130
131VkFormat
132vn_android_drm_format_to_vk_format(uint32_t format)
133{
134   switch (format) {
135   case DRM_FORMAT_ABGR8888:
136   case DRM_FORMAT_XBGR8888:
137      return VK_FORMAT_R8G8B8A8_UNORM;
138   case DRM_FORMAT_BGR888:
139      return VK_FORMAT_R8G8B8_UNORM;
140   case DRM_FORMAT_RGB565:
141      return VK_FORMAT_R5G6B5_UNORM_PACK16;
142   case DRM_FORMAT_ABGR16161616F:
143      return VK_FORMAT_R16G16B16A16_SFLOAT;
144   case DRM_FORMAT_ABGR2101010:
145      return VK_FORMAT_A2B10G10R10_UNORM_PACK32;
146   case DRM_FORMAT_YVU420:
147   case DRM_FORMAT_NV12:
148      return VK_FORMAT_G8_B8R8_2PLANE_420_UNORM;
149   default:
150      return VK_FORMAT_UNDEFINED;
151   }
152}
153
154static bool
155vn_android_drm_format_is_yuv(uint32_t format)
156{
157   assert(vn_android_drm_format_to_vk_format(format) != VK_FORMAT_UNDEFINED);
158
159   switch (format) {
160   case DRM_FORMAT_YVU420:
161   case DRM_FORMAT_NV12:
162      return true;
163   default:
164      return false;
165   }
166}
167
168uint64_t
169vn_android_get_ahb_usage(const VkImageUsageFlags usage,
170                         const VkImageCreateFlags flags)
171{
172   uint64_t ahb_usage = 0;
173   if (usage &
174       (VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT))
175      ahb_usage |= AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
176
177   if (usage & (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
178                VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT))
179      ahb_usage |= AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER;
180
181   if (flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT)
182      ahb_usage |= AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP;
183
184   if (flags & VK_IMAGE_CREATE_PROTECTED_BIT)
185      ahb_usage |= AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT;
186
187   /* must include at least one GPU usage flag */
188   if (ahb_usage == 0)
189      ahb_usage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
190
191   return ahb_usage;
192}
193
194VkResult
195vn_GetSwapchainGrallocUsage2ANDROID(
196   VkDevice device,
197   VkFormat format,
198   VkImageUsageFlags imageUsage,
199   VkSwapchainImageUsageFlagsANDROID swapchainImageUsage,
200   uint64_t *grallocConsumerUsage,
201   uint64_t *grallocProducerUsage)
202{
203   struct vn_device *dev = vn_device_from_handle(device);
204   *grallocConsumerUsage = 0;
205   *grallocProducerUsage = 0;
206
207   if (swapchainImageUsage & VK_SWAPCHAIN_IMAGE_USAGE_SHARED_BIT_ANDROID)
208      return vn_error(dev->instance, VK_ERROR_INITIALIZATION_FAILED);
209
210   if (VN_DEBUG(WSI))
211      vn_log(dev->instance, "format=%d, imageUsage=0x%x", format, imageUsage);
212
213   if (imageUsage & (VK_IMAGE_USAGE_TRANSFER_DST_BIT |
214                     VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT))
215      *grallocProducerUsage |= AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER;
216
217   if (imageUsage &
218       (VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT |
219        VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT))
220      *grallocConsumerUsage |= AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
221
222   return VK_SUCCESS;
223}
224
225struct cros_gralloc0_buffer_info {
226   uint32_t drm_fourcc;
227   int num_fds; /* ignored */
228   int fds[4];  /* ignored */
229   uint64_t modifier;
230   uint32_t offset[4];
231   uint32_t stride[4];
232};
233
234struct vn_android_gralloc_buffer_properties {
235   uint32_t drm_fourcc;
236   uint64_t modifier;
237   uint32_t offset[4];
238   uint32_t stride[4];
239};
240
241static VkResult
242vn_android_get_dma_buf_from_native_handle(const native_handle_t *handle,
243                                          int *out_dma_buf)
244{
245   /* There can be multiple fds wrapped inside a native_handle_t, but we
246    * expect only the 1st one points to the dma_buf. For multi-planar format,
247    * there should only exist one dma_buf as well. The other fd(s) may point
248    * to shared memory used to store buffer metadata or other vendor specific
249    * bits.
250    */
251   if (handle->numFds < 1) {
252      vn_log(NULL, "handle->numFds is %d, expected >= 1", handle->numFds);
253      return VK_ERROR_INVALID_EXTERNAL_HANDLE;
254   }
255
256   if (handle->data[0] < 0) {
257      vn_log(NULL, "handle->data[0] < 0");
258      return VK_ERROR_INVALID_EXTERNAL_HANDLE;
259   }
260
261   *out_dma_buf = handle->data[0];
262   return VK_SUCCESS;
263}
264
265static bool
266vn_android_get_gralloc_buffer_properties(
267   buffer_handle_t handle,
268   struct vn_android_gralloc_buffer_properties *out_props)
269{
270   static const int32_t CROS_GRALLOC_DRM_GET_BUFFER_INFO = 4;
271   struct cros_gralloc0_buffer_info info;
272   if (gralloc->perform(gralloc, CROS_GRALLOC_DRM_GET_BUFFER_INFO, handle,
273                        &info) != 0) {
274      vn_log(NULL, "CROS_GRALLOC_DRM_GET_BUFFER_INFO failed");
275      return false;
276   }
277
278   if (info.modifier == DRM_FORMAT_MOD_INVALID) {
279      vn_log(NULL, "Unexpected DRM_FORMAT_MOD_INVALID");
280      return false;
281   }
282
283   out_props->drm_fourcc = info.drm_fourcc;
284   for (uint32_t i = 0; i < 4; i++) {
285      out_props->stride[i] = info.stride[i];
286      out_props->offset[i] = info.offset[i];
287   }
288   out_props->modifier = info.modifier;
289
290   return true;
291}
292
293static VkResult
294vn_android_get_modifier_properties(struct vn_device *dev,
295                                   VkFormat format,
296                                   uint64_t modifier,
297                                   const VkAllocationCallbacks *alloc,
298                                   VkDrmFormatModifierPropertiesEXT *out_props)
299{
300   VkPhysicalDevice physical_device =
301      vn_physical_device_to_handle(dev->physical_device);
302   VkDrmFormatModifierPropertiesListEXT mod_prop_list = {
303      .sType = VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT,
304      .pNext = NULL,
305      .drmFormatModifierCount = 0,
306      .pDrmFormatModifierProperties = NULL,
307   };
308   VkFormatProperties2 format_prop = {
309      .sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2,
310      .pNext = &mod_prop_list,
311   };
312   VkDrmFormatModifierPropertiesEXT *mod_props = NULL;
313   bool modifier_found = false;
314
315   vn_GetPhysicalDeviceFormatProperties2(physical_device, format,
316                                         &format_prop);
317
318   if (!mod_prop_list.drmFormatModifierCount) {
319      vn_log(dev->instance, "No compatible modifier for VkFormat(%u)",
320             format);
321      return VK_ERROR_INVALID_EXTERNAL_HANDLE;
322   }
323
324   mod_props = vk_zalloc(
325      alloc, sizeof(*mod_props) * mod_prop_list.drmFormatModifierCount,
326      VN_DEFAULT_ALIGN, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
327   if (!mod_props)
328      return VK_ERROR_OUT_OF_HOST_MEMORY;
329
330   mod_prop_list.pDrmFormatModifierProperties = mod_props;
331   vn_GetPhysicalDeviceFormatProperties2(physical_device, format,
332                                         &format_prop);
333
334   for (uint32_t i = 0; i < mod_prop_list.drmFormatModifierCount; i++) {
335      if (mod_props[i].drmFormatModifier == modifier) {
336         *out_props = mod_props[i];
337         modifier_found = true;
338         break;
339      }
340   }
341
342   vk_free(alloc, mod_props);
343
344   if (!modifier_found) {
345      vn_log(dev->instance,
346             "No matching modifier(%" PRIu64 ") properties for VkFormat(%u)",
347             modifier, format);
348      return VK_ERROR_INVALID_EXTERNAL_HANDLE;
349   }
350
351   return VK_SUCCESS;
352}
353
354struct vn_android_image_builder {
355   VkImageCreateInfo create;
356   VkSubresourceLayout layouts[4];
357   VkImageDrmFormatModifierExplicitCreateInfoEXT modifier;
358   VkExternalMemoryImageCreateInfo external;
359};
360
361static VkResult
362vn_android_get_image_builder(struct vn_device *dev,
363                             const VkImageCreateInfo *create_info,
364                             const native_handle_t *handle,
365                             const VkAllocationCallbacks *alloc,
366                             struct vn_android_image_builder *out_builder)
367{
368   VkResult result = VK_SUCCESS;
369   struct vn_android_gralloc_buffer_properties buf_props;
370   VkDrmFormatModifierPropertiesEXT mod_props;
371
372   if (!vn_android_get_gralloc_buffer_properties(handle, &buf_props))
373      return VK_ERROR_INVALID_EXTERNAL_HANDLE;
374
375   result = vn_android_get_modifier_properties(
376      dev, create_info->format, buf_props.modifier, alloc, &mod_props);
377   if (result != VK_SUCCESS)
378      return result;
379
380   memset(out_builder->layouts, 0, sizeof(out_builder->layouts));
381   for (uint32_t i = 0; i < mod_props.drmFormatModifierPlaneCount; i++) {
382      out_builder->layouts[i].offset = buf_props.offset[i];
383      out_builder->layouts[i].rowPitch = buf_props.stride[i];
384   }
385   out_builder->modifier = (VkImageDrmFormatModifierExplicitCreateInfoEXT){
386      .sType =
387         VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT,
388      .pNext = create_info->pNext,
389      .drmFormatModifier = buf_props.modifier,
390      .drmFormatModifierPlaneCount = mod_props.drmFormatModifierPlaneCount,
391      .pPlaneLayouts = out_builder->layouts,
392   };
393   out_builder->external = (VkExternalMemoryImageCreateInfo){
394      .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO,
395      .pNext = &out_builder->modifier,
396      .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
397   };
398   out_builder->create = *create_info;
399   out_builder->create.pNext = &out_builder->external;
400   out_builder->create.tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT;
401
402   return VK_SUCCESS;
403}
404
405VkResult
406vn_android_image_from_anb(struct vn_device *dev,
407                          const VkImageCreateInfo *create_info,
408                          const VkNativeBufferANDROID *anb_info,
409                          const VkAllocationCallbacks *alloc,
410                          struct vn_image **out_img)
411{
412   /* If anb_info->handle points to a classic resouce created from
413    * virtio_gpu_cmd_resource_create_3d, anb_info->stride is the stride of the
414    * guest shadow storage other than the host gpu storage.
415    *
416    * We also need to pass the correct stride to vn_CreateImage, which will be
417    * done via VkImageDrmFormatModifierExplicitCreateInfoEXT and will require
418    * VK_EXT_image_drm_format_modifier support in the host driver. The struct
419    * needs host storage info which can be queried from cros gralloc.
420    */
421   VkResult result = VK_SUCCESS;
422   VkDevice device = vn_device_to_handle(dev);
423   VkDeviceMemory memory = VK_NULL_HANDLE;
424   VkImage image = VK_NULL_HANDLE;
425   struct vn_image *img = NULL;
426   uint64_t alloc_size = 0;
427   uint32_t mem_type_bits = 0;
428   int dma_buf_fd = -1;
429   int dup_fd = -1;
430   struct vn_android_image_builder builder;
431
432   result = vn_android_get_dma_buf_from_native_handle(anb_info->handle,
433                                                      &dma_buf_fd);
434   if (result != VK_SUCCESS)
435      goto fail;
436
437   result = vn_android_get_image_builder(dev, create_info, anb_info->handle,
438                                         alloc, &builder);
439   if (result != VK_SUCCESS)
440      goto fail;
441
442   /* encoder will strip the Android specific pNext structs */
443   result = vn_image_create(dev, &builder.create, alloc, &img);
444   if (result != VK_SUCCESS) {
445      if (VN_DEBUG(WSI))
446         vn_log(dev->instance, "vn_image_create failed");
447      goto fail;
448   }
449
450   image = vn_image_to_handle(img);
451   VkMemoryRequirements mem_req;
452   vn_GetImageMemoryRequirements(device, image, &mem_req);
453   if (!mem_req.memoryTypeBits) {
454      if (VN_DEBUG(WSI))
455         vn_log(dev->instance, "mem_req.memoryTypeBits cannot be zero");
456      result = VK_ERROR_INVALID_EXTERNAL_HANDLE;
457      goto fail;
458   }
459
460   result = vn_get_memory_dma_buf_properties(dev, dma_buf_fd, &alloc_size,
461                                             &mem_type_bits);
462   if (result != VK_SUCCESS)
463      goto fail;
464
465   if (VN_DEBUG(WSI)) {
466      vn_log(dev->instance,
467             "size = img(%" PRIu64 ") fd(%" PRIu64 "), "
468             "memoryTypeBits = img(0x%X) & fd(0x%X)",
469             mem_req.size, alloc_size, mem_req.memoryTypeBits, mem_type_bits);
470   }
471
472   if (alloc_size < mem_req.size) {
473      if (VN_DEBUG(WSI)) {
474         vn_log(dev->instance,
475                "alloc_size(%" PRIu64 ") mem_req.size(%" PRIu64 ")",
476                alloc_size, mem_req.size);
477      }
478      result = VK_ERROR_INVALID_EXTERNAL_HANDLE;
479      goto fail;
480   }
481
482   mem_type_bits &= mem_req.memoryTypeBits;
483   if (!mem_type_bits) {
484      result = VK_ERROR_INVALID_EXTERNAL_HANDLE;
485      goto fail;
486   }
487
488   dup_fd = os_dupfd_cloexec(dma_buf_fd);
489   if (dup_fd < 0) {
490      result = (errno == EMFILE) ? VK_ERROR_TOO_MANY_OBJECTS
491                                 : VK_ERROR_OUT_OF_HOST_MEMORY;
492      goto fail;
493   }
494
495   const VkImportMemoryFdInfoKHR import_fd_info = {
496      .sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR,
497      .pNext = NULL,
498      .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
499      .fd = dup_fd,
500   };
501   const VkMemoryAllocateInfo memory_info = {
502      .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
503      .pNext = &import_fd_info,
504      .allocationSize = mem_req.size,
505      .memoryTypeIndex = ffs(mem_type_bits) - 1,
506   };
507   result = vn_AllocateMemory(device, &memory_info, alloc, &memory);
508   if (result != VK_SUCCESS) {
509      /* only need to close the dup_fd on import failure */
510      close(dup_fd);
511      goto fail;
512   }
513
514   result = vn_BindImageMemory(device, image, memory, 0);
515   if (result != VK_SUCCESS)
516      goto fail;
517
518   img->is_wsi = true;
519   /* Android WSI image owns the memory */
520   img->private_memory = memory;
521   *out_img = img;
522
523   return VK_SUCCESS;
524
525fail:
526   if (image != VK_NULL_HANDLE)
527      vn_DestroyImage(device, image, alloc);
528   if (memory != VK_NULL_HANDLE)
529      vn_FreeMemory(device, memory, alloc);
530   return vn_error(dev->instance, result);
531}
532
533VkResult
534vn_AcquireImageANDROID(VkDevice device,
535                       UNUSED VkImage image,
536                       int nativeFenceFd,
537                       VkSemaphore semaphore,
538                       VkFence fence)
539{
540   struct vn_device *dev = vn_device_from_handle(device);
541   VkResult result = VK_SUCCESS;
542
543   if (dev->instance->experimental.globalFencing == VK_FALSE) {
544      /* Fallback when VkVenusExperimentalFeatures100000MESA::globalFencing is
545       * VK_FALSE, out semaphore and fence are filled with already signaled
546       * payloads, and the native fence fd is waited inside until signaled.
547       */
548      if (nativeFenceFd >= 0) {
549         int ret = sync_wait(nativeFenceFd, -1);
550         /* Android loader expects the ICD to always close the fd */
551         close(nativeFenceFd);
552         if (ret)
553            return vn_error(dev->instance, VK_ERROR_SURFACE_LOST_KHR);
554      }
555
556      if (semaphore != VK_NULL_HANDLE)
557         vn_semaphore_signal_wsi(dev, vn_semaphore_from_handle(semaphore));
558
559      if (fence != VK_NULL_HANDLE)
560         vn_fence_signal_wsi(dev, vn_fence_from_handle(fence));
561
562      return VK_SUCCESS;
563   }
564
565   int semaphore_fd = -1;
566   int fence_fd = -1;
567   if (nativeFenceFd >= 0) {
568      if (semaphore != VK_NULL_HANDLE && fence != VK_NULL_HANDLE) {
569         semaphore_fd = nativeFenceFd;
570         fence_fd = os_dupfd_cloexec(nativeFenceFd);
571         if (fence_fd < 0) {
572            result = (errno == EMFILE) ? VK_ERROR_TOO_MANY_OBJECTS
573                                       : VK_ERROR_OUT_OF_HOST_MEMORY;
574            close(nativeFenceFd);
575            return vn_error(dev->instance, result);
576         }
577      } else if (semaphore != VK_NULL_HANDLE) {
578         semaphore_fd = nativeFenceFd;
579      } else if (fence != VK_NULL_HANDLE) {
580         fence_fd = nativeFenceFd;
581      } else {
582         close(nativeFenceFd);
583      }
584   }
585
586   if (semaphore != VK_NULL_HANDLE) {
587      const VkImportSemaphoreFdInfoKHR info = {
588         .sType = VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR,
589         .pNext = NULL,
590         .semaphore = semaphore,
591         .flags = VK_SEMAPHORE_IMPORT_TEMPORARY_BIT,
592         .handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT,
593         .fd = semaphore_fd,
594      };
595      result = vn_ImportSemaphoreFdKHR(device, &info);
596      if (result == VK_SUCCESS)
597         semaphore_fd = -1;
598   }
599
600   if (result == VK_SUCCESS && fence != VK_NULL_HANDLE) {
601      const VkImportFenceFdInfoKHR info = {
602         .sType = VK_STRUCTURE_TYPE_IMPORT_FENCE_FD_INFO_KHR,
603         .pNext = NULL,
604         .fence = fence,
605         .flags = VK_FENCE_IMPORT_TEMPORARY_BIT,
606         .handleType = VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT,
607         .fd = fence_fd,
608      };
609      result = vn_ImportFenceFdKHR(device, &info);
610      if (result == VK_SUCCESS)
611         fence_fd = -1;
612   }
613
614   if (semaphore_fd >= 0)
615      close(semaphore_fd);
616   if (fence_fd >= 0)
617      close(fence_fd);
618
619   return vn_result(dev->instance, result);
620}
621
622VkResult
623vn_QueueSignalReleaseImageANDROID(VkQueue queue,
624                                  uint32_t waitSemaphoreCount,
625                                  const VkSemaphore *pWaitSemaphores,
626                                  VkImage image,
627                                  int *pNativeFenceFd)
628{
629   struct vn_queue *que = vn_queue_from_handle(queue);
630   struct vn_device *dev = que->device;
631   const VkAllocationCallbacks *alloc = &dev->base.base.alloc;
632   VkDevice device = vn_device_to_handle(dev);
633   VkPipelineStageFlags local_stage_masks[8];
634   VkPipelineStageFlags *stage_masks = local_stage_masks;
635   VkResult result = VK_SUCCESS;
636   int fd = -1;
637
638   if (waitSemaphoreCount == 0) {
639      *pNativeFenceFd = -1;
640      return VK_SUCCESS;
641   }
642
643   if (waitSemaphoreCount > ARRAY_SIZE(local_stage_masks)) {
644      stage_masks =
645         vk_alloc(alloc, sizeof(*stage_masks) * waitSemaphoreCount,
646                  VN_DEFAULT_ALIGN, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
647      if (!stage_masks)
648         return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
649   }
650
651   for (uint32_t i = 0; i < waitSemaphoreCount; i++)
652      stage_masks[i] = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
653
654   const VkSubmitInfo submit_info = {
655      .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
656      .pNext = NULL,
657      .waitSemaphoreCount = waitSemaphoreCount,
658      .pWaitSemaphores = pWaitSemaphores,
659      .pWaitDstStageMask = stage_masks,
660      .commandBufferCount = 0,
661      .pCommandBuffers = NULL,
662      .signalSemaphoreCount = 0,
663      .pSignalSemaphores = NULL,
664   };
665   /* XXX When globalFencing is supported, our implementation is not able to
666    * reset the fence during vn_GetFenceFdKHR currently. Thus to ensure proper
667    * host driver behavior, we pass VK_NULL_HANDLE here.
668    */
669   result = vn_QueueSubmit(
670      queue, 1, &submit_info,
671      dev->instance->experimental.globalFencing == VK_TRUE ? VK_NULL_HANDLE
672                                                           : que->wait_fence);
673
674   if (stage_masks != local_stage_masks)
675      vk_free(alloc, stage_masks);
676
677   if (result != VK_SUCCESS)
678      return vn_error(dev->instance, result);
679
680   if (dev->instance->experimental.globalFencing == VK_TRUE) {
681      const VkFenceGetFdInfoKHR fd_info = {
682         .sType = VK_STRUCTURE_TYPE_FENCE_GET_FD_INFO_KHR,
683         .pNext = NULL,
684         .fence = que->wait_fence,
685         .handleType = VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT,
686      };
687      result = vn_GetFenceFdKHR(device, &fd_info, &fd);
688   } else {
689      result =
690         vn_WaitForFences(device, 1, &que->wait_fence, VK_TRUE, UINT64_MAX);
691      if (result != VK_SUCCESS)
692         return vn_error(dev->instance, result);
693
694      result = vn_ResetFences(device, 1, &que->wait_fence);
695   }
696
697   if (result != VK_SUCCESS)
698      return vn_error(dev->instance, result);
699
700   *pNativeFenceFd = fd;
701
702   return VK_SUCCESS;
703}
704
705static VkResult
706vn_android_get_ahb_format_properties(
707   struct vn_device *dev,
708   const struct AHardwareBuffer *ahb,
709   VkAndroidHardwareBufferFormatPropertiesANDROID *out_props)
710{
711   AHardwareBuffer_Desc desc;
712   VkFormat format;
713   struct vn_android_gralloc_buffer_properties buf_props;
714   VkDrmFormatModifierPropertiesEXT mod_props;
715
716   AHardwareBuffer_describe(ahb, &desc);
717   if (!(desc.usage & (AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE |
718                       AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER |
719                       AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER))) {
720      vn_log(dev->instance,
721             "AHB usage(%" PRIu64 ") must include at least one GPU bit",
722             desc.usage);
723      return VK_ERROR_INVALID_EXTERNAL_HANDLE;
724   }
725
726   /* Handle the special AHARDWAREBUFFER_FORMAT_BLOB for VkBuffer case. */
727   if (desc.format == AHARDWAREBUFFER_FORMAT_BLOB) {
728      out_props->format = VK_FORMAT_UNDEFINED;
729      return VK_SUCCESS;
730   }
731
732   if (!vn_android_get_gralloc_buffer_properties(
733          AHardwareBuffer_getNativeHandle(ahb), &buf_props))
734      return VK_ERROR_INVALID_EXTERNAL_HANDLE;
735
736   /* We implement AHB extension support with EXT_image_drm_format_modifier.
737    * It requires us to have a compatible VkFormat but not DRM formats. So if
738    * the ahb is not intended for backing a VkBuffer, error out early if the
739    * format is VK_FORMAT_UNDEFINED.
740    */
741   format = vn_android_drm_format_to_vk_format(buf_props.drm_fourcc);
742   if (format == VK_FORMAT_UNDEFINED) {
743      vn_log(dev->instance, "Unknown drm_fourcc(%u) from AHB format(0x%X)",
744             buf_props.drm_fourcc, desc.format);
745      return VK_ERROR_INVALID_EXTERNAL_HANDLE;
746   }
747
748   VkResult result = vn_android_get_modifier_properties(
749      dev, format, buf_props.modifier, &dev->base.base.alloc, &mod_props);
750   if (result != VK_SUCCESS)
751      return result;
752
753   /* The spec requires that formatFeatures must include at least one of
754    * VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT or
755    * VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT.
756    */
757   const VkFormatFeatureFlags format_features =
758      mod_props.drmFormatModifierTilingFeatures |
759      VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT;
760
761   /* 11.2.7. Android Hardware Buffer External Memory
762    *
763    * Implementations may not always be able to determine the color model,
764    * numerical range, or chroma offsets of the image contents, so the values
765    * in VkAndroidHardwareBufferFormatPropertiesANDROID are only suggestions.
766    * Applications should treat these values as sensible defaults to use in the
767    * absence of more reliable information obtained through some other means.
768    */
769   const VkSamplerYcbcrModelConversion model =
770      vn_android_drm_format_is_yuv(buf_props.drm_fourcc)
771         ? VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601
772         : VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY;
773   *out_props = (VkAndroidHardwareBufferFormatPropertiesANDROID) {
774      .sType = out_props->sType,
775      .pNext = out_props->pNext,
776      .format = format,
777      .externalFormat = buf_props.drm_fourcc,
778      .formatFeatures = format_features,
779      .samplerYcbcrConversionComponents = {
780         .r = VK_COMPONENT_SWIZZLE_IDENTITY,
781         .g = VK_COMPONENT_SWIZZLE_IDENTITY,
782         .b = VK_COMPONENT_SWIZZLE_IDENTITY,
783         .a = VK_COMPONENT_SWIZZLE_IDENTITY,
784      },
785      .suggestedYcbcrModel = model,
786      .suggestedYcbcrRange = VK_SAMPLER_YCBCR_RANGE_ITU_FULL,
787      .suggestedXChromaOffset = VK_CHROMA_LOCATION_MIDPOINT,
788      .suggestedYChromaOffset = VK_CHROMA_LOCATION_MIDPOINT,
789   };
790
791   return VK_SUCCESS;
792}
793
794VkResult
795vn_GetAndroidHardwareBufferPropertiesANDROID(
796   VkDevice device,
797   const struct AHardwareBuffer *buffer,
798   VkAndroidHardwareBufferPropertiesANDROID *pProperties)
799{
800   struct vn_device *dev = vn_device_from_handle(device);
801   VkResult result = VK_SUCCESS;
802   int dma_buf_fd = -1;
803   uint64_t alloc_size = 0;
804   uint32_t mem_type_bits = 0;
805
806   VkAndroidHardwareBufferFormatPropertiesANDROID *format_props =
807      vk_find_struct(pProperties->pNext,
808                     ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID);
809   if (format_props) {
810      result =
811         vn_android_get_ahb_format_properties(dev, buffer, format_props);
812      if (result != VK_SUCCESS)
813         return vn_error(dev->instance, result);
814   }
815
816   const native_handle_t *handle = AHardwareBuffer_getNativeHandle(buffer);
817   result = vn_android_get_dma_buf_from_native_handle(handle, &dma_buf_fd);
818   if (result != VK_SUCCESS)
819      return vn_error(dev->instance, result);
820
821   result = vn_get_memory_dma_buf_properties(dev, dma_buf_fd, &alloc_size,
822                                             &mem_type_bits);
823   if (result != VK_SUCCESS)
824      return vn_error(dev->instance, result);
825
826   pProperties->allocationSize = alloc_size;
827   pProperties->memoryTypeBits = mem_type_bits;
828
829   return VK_SUCCESS;
830}
831
832static AHardwareBuffer *
833vn_android_ahb_allocate(uint32_t width,
834                        uint32_t height,
835                        uint32_t layers,
836                        uint32_t format,
837                        uint64_t usage)
838{
839   AHardwareBuffer *ahb = NULL;
840   AHardwareBuffer_Desc desc;
841   int ret = 0;
842
843   memset(&desc, 0, sizeof(desc));
844   desc.width = width;
845   desc.height = height;
846   desc.layers = layers;
847   desc.format = format;
848   desc.usage = usage;
849
850   ret = AHardwareBuffer_allocate(&desc, &ahb);
851   if (ret) {
852      /* We just log the error code here for now since the platform falsely
853       * maps all gralloc allocation failures to oom.
854       */
855      vn_log(NULL, "AHB alloc(w=%u,h=%u,l=%u,f=%u,u=%" PRIu64 ") failed(%d)",
856             width, height, layers, format, usage, ret);
857      return NULL;
858   }
859
860   return ahb;
861}
862
863bool
864vn_android_get_drm_format_modifier_info(
865   const VkPhysicalDeviceImageFormatInfo2 *format_info,
866   VkPhysicalDeviceImageDrmFormatModifierInfoEXT *out_info)
867{
868   /* To properly fill VkPhysicalDeviceImageDrmFormatModifierInfoEXT, we have
869    * to allocate an ahb to retrieve the drm format modifier. For the image
870    * sharing mode, we assume VK_SHARING_MODE_EXCLUSIVE for now.
871    */
872   AHardwareBuffer *ahb = NULL;
873   uint32_t format = 0;
874   uint64_t usage = 0;
875   struct vn_android_gralloc_buffer_properties buf_props;
876
877   assert(format_info->tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT);
878
879   format = vn_android_ahb_format_from_vk_format(format_info->format);
880   if (!format)
881      return false;
882
883   usage = vn_android_get_ahb_usage(format_info->usage, format_info->flags);
884   ahb = vn_android_ahb_allocate(16, 16, 1, format, usage);
885   if (!ahb)
886      return false;
887
888   if (!vn_android_get_gralloc_buffer_properties(
889          AHardwareBuffer_getNativeHandle(ahb), &buf_props)) {
890      AHardwareBuffer_release(ahb);
891      return false;
892   }
893
894   *out_info = (VkPhysicalDeviceImageDrmFormatModifierInfoEXT){
895      .sType =
896         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT,
897      .pNext = NULL,
898      .drmFormatModifier = buf_props.modifier,
899      .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
900      .queueFamilyIndexCount = 0,
901      .pQueueFamilyIndices = NULL,
902   };
903
904   AHardwareBuffer_release(ahb);
905   return true;
906}
907
908VkResult
909vn_android_image_from_ahb(struct vn_device *dev,
910                          const VkImageCreateInfo *create_info,
911                          const VkAllocationCallbacks *alloc,
912                          struct vn_image **out_img)
913{
914   const VkExternalFormatANDROID *ext_info =
915      vk_find_struct_const(create_info->pNext, EXTERNAL_FORMAT_ANDROID);
916
917   VkImageCreateInfo local_info;
918   if (ext_info && ext_info->externalFormat) {
919      assert(create_info->format == VK_FORMAT_UNDEFINED);
920      assert(create_info->imageType == VK_IMAGE_TYPE_2D);
921      assert(create_info->usage == VK_IMAGE_USAGE_SAMPLED_BIT);
922      assert(create_info->tiling == VK_IMAGE_TILING_OPTIMAL);
923
924      local_info = *create_info;
925      local_info.format =
926         vn_android_drm_format_to_vk_format(ext_info->externalFormat);
927      create_info = &local_info;
928   }
929
930   return vn_image_create_deferred(dev, create_info, alloc, out_img);
931}
932
933VkResult
934vn_android_device_import_ahb(struct vn_device *dev,
935                             struct vn_device_memory *mem,
936                             const VkMemoryAllocateInfo *alloc_info,
937                             const VkAllocationCallbacks *alloc,
938                             struct AHardwareBuffer *ahb)
939{
940   VkDevice device = vn_device_to_handle(dev);
941   const VkMemoryDedicatedAllocateInfo *dedicated_info =
942      vk_find_struct_const(alloc_info->pNext, MEMORY_DEDICATED_ALLOCATE_INFO);
943   const native_handle_t *handle = NULL;
944   int dma_buf_fd = -1;
945   int dup_fd = -1;
946   uint64_t alloc_size = 0;
947   uint32_t mem_type_bits = 0;
948   bool force_unmappable = false;
949   VkResult result = VK_SUCCESS;
950
951   handle = AHardwareBuffer_getNativeHandle(ahb);
952   result = vn_android_get_dma_buf_from_native_handle(handle, &dma_buf_fd);
953   if (result != VK_SUCCESS)
954      return result;
955
956   result = vn_get_memory_dma_buf_properties(dev, dma_buf_fd, &alloc_size,
957                                             &mem_type_bits);
958   if (result != VK_SUCCESS)
959      return result;
960
961   if (((1 << alloc_info->memoryTypeIndex) & mem_type_bits) == 0) {
962      vn_log(dev->instance, "memoryTypeIndex(%u) mem_type_bits(0x%X)",
963             alloc_info->memoryTypeIndex, mem_type_bits);
964      return VK_ERROR_INVALID_EXTERNAL_HANDLE;
965   }
966
967   /* If ahb is for an image, finish the deferred image creation first */
968   if (dedicated_info && dedicated_info->image != VK_NULL_HANDLE) {
969      struct vn_image *img = vn_image_from_handle(dedicated_info->image);
970      struct vn_android_image_builder builder;
971
972      result = vn_android_get_image_builder(dev, &img->deferred_info->create,
973                                            handle, alloc, &builder);
974      if (result != VK_SUCCESS)
975         return result;
976
977      result = vn_image_init_deferred(dev, &builder.create, img);
978      if (result != VK_SUCCESS)
979         return result;
980
981      VkMemoryRequirements mem_req;
982      vn_GetImageMemoryRequirements(device, dedicated_info->image, &mem_req);
983      if (alloc_size < mem_req.size) {
984         vn_log(dev->instance,
985                "alloc_size(%" PRIu64 ") mem_req.size(%" PRIu64 ")",
986                alloc_size, mem_req.size);
987         return VK_ERROR_INVALID_EXTERNAL_HANDLE;
988      }
989
990      alloc_size = mem_req.size;
991
992      /* XXX Workaround before we use cross-domain backend in minigbm. The
993       * blob_mem allocated from virgl backend can have a queried guest mappable
994       * size smaller than the size returned from image memory requirement.
995       */
996      force_unmappable = true;
997   }
998
999   if (dedicated_info && dedicated_info->buffer != VK_NULL_HANDLE) {
1000      VkMemoryRequirements mem_req;
1001      vn_GetBufferMemoryRequirements(device, dedicated_info->buffer,
1002                                     &mem_req);
1003      if (alloc_size < mem_req.size) {
1004         vn_log(dev->instance,
1005                "alloc_size(%" PRIu64 ") mem_req.size(%" PRIu64 ")",
1006                alloc_size, mem_req.size);
1007         return VK_ERROR_INVALID_EXTERNAL_HANDLE;
1008      }
1009
1010      alloc_size = mem_req.size;
1011   }
1012
1013   errno = 0;
1014   dup_fd = os_dupfd_cloexec(dma_buf_fd);
1015   if (dup_fd < 0)
1016      return (errno == EMFILE) ? VK_ERROR_TOO_MANY_OBJECTS
1017                               : VK_ERROR_OUT_OF_HOST_MEMORY;
1018
1019   /* Spec requires AHB export info to be present, so we must strip it. In
1020    * practice, the AHB import path here only needs the main allocation info
1021    * and the dedicated_info.
1022    */
1023   VkMemoryDedicatedAllocateInfo local_dedicated_info;
1024   /* Override when dedicated_info exists and is not the tail struct. */
1025   if (dedicated_info && dedicated_info->pNext) {
1026      local_dedicated_info = *dedicated_info;
1027      local_dedicated_info.pNext = NULL;
1028      dedicated_info = &local_dedicated_info;
1029   }
1030   const VkMemoryAllocateInfo local_alloc_info = {
1031      .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
1032      .pNext = dedicated_info,
1033      .allocationSize = alloc_size,
1034      .memoryTypeIndex = alloc_info->memoryTypeIndex,
1035   };
1036   result = vn_device_memory_import_dma_buf(dev, mem, &local_alloc_info,
1037                                            force_unmappable, dup_fd);
1038   if (result != VK_SUCCESS) {
1039      close(dup_fd);
1040      return result;
1041   }
1042
1043   AHardwareBuffer_acquire(ahb);
1044   mem->ahb = ahb;
1045
1046   return VK_SUCCESS;
1047}
1048
1049VkResult
1050vn_android_device_allocate_ahb(struct vn_device *dev,
1051                               struct vn_device_memory *mem,
1052                               const VkMemoryAllocateInfo *alloc_info,
1053                               const VkAllocationCallbacks *alloc)
1054{
1055   const VkMemoryDedicatedAllocateInfo *dedicated_info =
1056      vk_find_struct_const(alloc_info->pNext, MEMORY_DEDICATED_ALLOCATE_INFO);
1057   uint32_t width = 0;
1058   uint32_t height = 1;
1059   uint32_t layers = 1;
1060   uint32_t format = 0;
1061   uint64_t usage = 0;
1062   struct AHardwareBuffer *ahb = NULL;
1063
1064   if (dedicated_info && dedicated_info->image != VK_NULL_HANDLE) {
1065      const VkImageCreateInfo *image_info =
1066         &vn_image_from_handle(dedicated_info->image)->deferred_info->create;
1067      assert(image_info);
1068      width = image_info->extent.width;
1069      height = image_info->extent.height;
1070      layers = image_info->arrayLayers;
1071      format = vn_android_ahb_format_from_vk_format(image_info->format);
1072      usage = vn_android_get_ahb_usage(image_info->usage, image_info->flags);
1073   } else {
1074      const VkPhysicalDeviceMemoryProperties *mem_props =
1075         &dev->physical_device->memory_properties.memoryProperties;
1076
1077      assert(alloc_info->memoryTypeIndex < mem_props->memoryTypeCount);
1078
1079      width = alloc_info->allocationSize;
1080      format = AHARDWAREBUFFER_FORMAT_BLOB;
1081      usage = AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER;
1082      if (mem_props->memoryTypes[alloc_info->memoryTypeIndex].propertyFlags &
1083          VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) {
1084         usage |= AHARDWAREBUFFER_USAGE_CPU_READ_RARELY |
1085                  AHARDWAREBUFFER_USAGE_CPU_WRITE_RARELY;
1086      }
1087   }
1088
1089   ahb = vn_android_ahb_allocate(width, height, layers, format, usage);
1090   if (!ahb)
1091      return VK_ERROR_OUT_OF_HOST_MEMORY;
1092
1093   VkResult result =
1094      vn_android_device_import_ahb(dev, mem, alloc_info, alloc, ahb);
1095
1096   /* ahb alloc has already acquired a ref and import will acquire another,
1097    * must release one here to avoid leak.
1098    */
1099   AHardwareBuffer_release(ahb);
1100
1101   return result;
1102}
1103
1104void
1105vn_android_release_ahb(struct AHardwareBuffer *ahb)
1106{
1107   AHardwareBuffer_release(ahb);
1108}
1109
1110VkResult
1111vn_GetMemoryAndroidHardwareBufferANDROID(
1112   VkDevice device,
1113   const VkMemoryGetAndroidHardwareBufferInfoANDROID *pInfo,
1114   struct AHardwareBuffer **pBuffer)
1115{
1116   struct vn_device_memory *mem = vn_device_memory_from_handle(pInfo->memory);
1117
1118   AHardwareBuffer_acquire(mem->ahb);
1119   *pBuffer = mem->ahb;
1120
1121   return VK_SUCCESS;
1122}
1123
1124struct vn_android_buffer_create_info {
1125   VkBufferCreateInfo create;
1126   VkExternalMemoryBufferCreateInfo external;
1127   VkBufferOpaqueCaptureAddressCreateInfo address;
1128};
1129
1130static const VkBufferCreateInfo *
1131vn_android_fix_buffer_create_info(
1132   const VkBufferCreateInfo *create_info,
1133   struct vn_android_buffer_create_info *local_info)
1134{
1135   local_info->create = *create_info;
1136   VkBaseOutStructure *dst = (void *)&local_info->create;
1137
1138   vk_foreach_struct_const(src, create_info->pNext) {
1139      void *pnext = NULL;
1140      switch (src->sType) {
1141      case VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO:
1142         memcpy(&local_info->external, src, sizeof(local_info->external));
1143         local_info->external.handleTypes =
1144            VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
1145         pnext = &local_info->external;
1146         break;
1147      case VK_STRUCTURE_TYPE_BUFFER_OPAQUE_CAPTURE_ADDRESS_CREATE_INFO:
1148         memcpy(&local_info->address, src, sizeof(local_info->address));
1149         pnext = &local_info->address;
1150         break;
1151      default:
1152         break;
1153      }
1154
1155      if (pnext) {
1156         dst->pNext = pnext;
1157         dst = pnext;
1158      }
1159   }
1160
1161   dst->pNext = NULL;
1162
1163   return &local_info->create;
1164}
1165
1166VkResult
1167vn_android_init_ahb_buffer_memory_type_bits(struct vn_device *dev)
1168{
1169   const uint32_t format = AHARDWAREBUFFER_FORMAT_BLOB;
1170   /* ensure dma_buf_memory_type_bits covers host visible usage */
1171   const uint64_t usage = AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER |
1172                          AHARDWAREBUFFER_USAGE_CPU_READ_RARELY |
1173                          AHARDWAREBUFFER_USAGE_CPU_WRITE_RARELY;
1174   AHardwareBuffer *ahb = NULL;
1175   int dma_buf_fd = -1;
1176   uint64_t alloc_size = 0;
1177   uint32_t mem_type_bits = 0;
1178   VkResult result;
1179
1180   ahb = vn_android_ahb_allocate(4096, 1, 1, format, usage);
1181   if (!ahb)
1182      return VK_ERROR_OUT_OF_HOST_MEMORY;
1183
1184   result = vn_android_get_dma_buf_from_native_handle(
1185      AHardwareBuffer_getNativeHandle(ahb), &dma_buf_fd);
1186   if (result != VK_SUCCESS) {
1187      AHardwareBuffer_release(ahb);
1188      return result;
1189   }
1190
1191   result = vn_get_memory_dma_buf_properties(dev, dma_buf_fd, &alloc_size,
1192                                             &mem_type_bits);
1193
1194   AHardwareBuffer_release(ahb);
1195
1196   if (result != VK_SUCCESS)
1197      return result;
1198
1199   dev->ahb_buffer_memory_type_bits = mem_type_bits;
1200
1201   return VK_SUCCESS;
1202}
1203
1204VkResult
1205vn_android_buffer_from_ahb(struct vn_device *dev,
1206                           const VkBufferCreateInfo *create_info,
1207                           const VkAllocationCallbacks *alloc,
1208                           struct vn_buffer **out_buf)
1209{
1210   struct vn_android_buffer_create_info local_info;
1211   VkResult result;
1212
1213   create_info = vn_android_fix_buffer_create_info(create_info, &local_info);
1214   result = vn_buffer_create(dev, create_info, alloc, out_buf);
1215   if (result != VK_SUCCESS)
1216      return result;
1217
1218   /* AHB backed buffer layers on top of dma_buf, so here we must comine the
1219    * queried type bits from both buffer memory requirement and dma_buf fd
1220    * properties.
1221    */
1222   (*out_buf)->memory_requirements.memoryRequirements.memoryTypeBits &=
1223      dev->ahb_buffer_memory_type_bits;
1224
1225   assert((*out_buf)->memory_requirements.memoryRequirements.memoryTypeBits);
1226
1227   return VK_SUCCESS;
1228}
1229