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