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