xref: /aosp_15_r20/external/mesa3d/src/virtio/vulkan/vn_android.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
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/hwvulkan.h>
15 #include <vndk/hardware_buffer.h>
16 #include <vulkan/vk_icd.h>
17 
18 #include "util/os_file.h"
19 #include "util/u_gralloc/u_gralloc.h"
20 #include "vk_android.h"
21 
22 #include "vn_buffer.h"
23 #include "vn_device.h"
24 #include "vn_device_memory.h"
25 #include "vn_image.h"
26 #include "vn_instance.h"
27 #include "vn_physical_device.h"
28 #include "vn_queue.h"
29 
30 struct vn_android_gralloc {
31    struct u_gralloc *gralloc;
32    uint64_t front_rendering_usage;
33 };
34 
35 static struct vn_android_gralloc _vn_android_gralloc;
36 
37 static int
vn_android_gralloc_init()38 vn_android_gralloc_init()
39 {
40    assert(!_vn_android_gralloc.gralloc);
41 
42    struct u_gralloc *gralloc = u_gralloc_create(U_GRALLOC_TYPE_AUTO);
43    if (!gralloc) {
44       vn_log(NULL, "u_gralloc failed to create a gralloc module instance");
45       return -1;
46    }
47 
48    const int gralloc_type = u_gralloc_get_type(gralloc);
49    if (gralloc_type != U_GRALLOC_TYPE_CROS &&
50        gralloc_type != U_GRALLOC_TYPE_GRALLOC4) {
51       u_gralloc_destroy(&gralloc);
52       vn_log(NULL, "only CrOS and IMapper v4 grallocs are supported for "
53                    "Venus Vulkan HAL");
54       return -1;
55    }
56 
57    _vn_android_gralloc.gralloc = gralloc;
58 
59    return 0;
60 }
61 
62 static inline void
vn_android_gralloc_fini()63 vn_android_gralloc_fini()
64 {
65    u_gralloc_destroy(&_vn_android_gralloc.gralloc);
66 }
67 
68 static void
vn_android_gralloc_shared_present_usage_init_once()69 vn_android_gralloc_shared_present_usage_init_once()
70 {
71    assert(_vn_android_gralloc.gralloc);
72 
73    int ret = u_gralloc_get_front_rendering_usage(
74       _vn_android_gralloc.gralloc,
75       &_vn_android_gralloc.front_rendering_usage);
76 
77    if (ret == 0)
78       assert(_vn_android_gralloc.front_rendering_usage);
79 }
80 
81 uint64_t
vn_android_gralloc_get_shared_present_usage()82 vn_android_gralloc_get_shared_present_usage()
83 {
84    static once_flag once = ONCE_FLAG_INIT;
85    call_once(&once, vn_android_gralloc_shared_present_usage_init_once);
86    return _vn_android_gralloc.front_rendering_usage;
87 }
88 
89 struct vn_android_gralloc_buffer_properties {
90    uint32_t drm_fourcc;
91    uint32_t num_planes;
92    uint64_t modifier;
93 
94    /* plane order matches VkImageDrmFormatModifierExplicitCreateInfoEXT */
95    uint32_t offset[4];
96    uint32_t stride[4];
97 };
98 
99 static bool
vn_android_gralloc_get_buffer_properties(buffer_handle_t handle,struct vn_android_gralloc_buffer_properties * out_props)100 vn_android_gralloc_get_buffer_properties(
101    buffer_handle_t handle,
102    struct vn_android_gralloc_buffer_properties *out_props)
103 {
104    struct u_gralloc *gralloc = _vn_android_gralloc.gralloc;
105    struct u_gralloc_buffer_basic_info info;
106 
107    /*
108     * We only support (and care of) CrOS and IMapper v4 gralloc modules
109     * at this point. They don't need the pixel stride and HAL format
110     * to be provided externally to them. It allows integrating u_gralloc
111     * with minimal modifications at this point.
112     */
113    struct u_gralloc_buffer_handle ugb_handle = {
114       .handle = handle,
115       .pixel_stride = 0,
116       .hal_format = 0,
117    };
118 
119    if (u_gralloc_get_buffer_basic_info(gralloc, &ugb_handle, &info) != 0) {
120       vn_log(NULL, "u_gralloc_get_buffer_basic_info failed");
121       return false;
122    }
123 
124    if (info.modifier == DRM_FORMAT_MOD_INVALID) {
125       vn_log(NULL, "Unexpected DRM_FORMAT_MOD_INVALID");
126       return false;
127    }
128 
129    assert(info.num_planes <= 4);
130 
131    out_props->drm_fourcc = info.drm_fourcc;
132    out_props->num_planes = info.num_planes;
133    for (uint32_t i = 0; i < info.num_planes; i++) {
134       if (!info.strides[i]) {
135          out_props->num_planes = i;
136          break;
137       }
138       out_props->stride[i] = info.strides[i];
139       out_props->offset[i] = info.offsets[i];
140    }
141 
142    /* YVU420 has a chroma order of CrCb. So we must swap the planes for CrCb
143     * to align with VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM. This is to serve
144     * VkImageDrmFormatModifierExplicitCreateInfoEXT explicit plane layouts.
145     */
146    if (info.drm_fourcc == DRM_FORMAT_YVU420) {
147       out_props->stride[1] = info.strides[2];
148       out_props->offset[1] = info.offsets[2];
149       out_props->stride[2] = info.strides[1];
150       out_props->offset[2] = info.offsets[1];
151    }
152 
153    out_props->modifier = info.modifier;
154 
155    return true;
156 }
157 
158 static int
vn_android_gralloc_get_dma_buf_fd(const native_handle_t * handle)159 vn_android_gralloc_get_dma_buf_fd(const native_handle_t *handle)
160 {
161    /* There can be multiple fds wrapped inside a native_handle_t, but we
162     * expect the 1st one pointing to the dma_buf. For multi-planar format,
163     * there should only exist one undelying dma_buf. The other fd(s) could be
164     * dups to the same dma_buf or point to the shared memory used to store
165     * gralloc buffer metadata.
166     */
167    assert(handle);
168 
169    if (handle->numFds < 1) {
170       vn_log(NULL, "handle->numFds is %d, expected >= 1", handle->numFds);
171       return -1;
172    }
173 
174    if (handle->data[0] < 0) {
175       vn_log(NULL, "handle->data[0] < 0");
176       return -1;
177    }
178 
179    return handle->data[0];
180 }
181 
182 static int
183 vn_hal_open(const struct hw_module_t *mod,
184             const char *id,
185             struct hw_device_t **dev);
186 
187 static_assert(HWVULKAN_DISPATCH_MAGIC == ICD_LOADER_MAGIC, "");
188 
189 PUBLIC struct hwvulkan_module_t HAL_MODULE_INFO_SYM = {
190    .common = {
191       .tag = HARDWARE_MODULE_TAG,
192       .module_api_version = HWVULKAN_MODULE_API_VERSION_0_1,
193       .hal_api_version = HARDWARE_HAL_API_VERSION,
194       .id = HWVULKAN_HARDWARE_MODULE_ID,
195       .name = "Venus Vulkan HAL",
196       .author = "Google LLC",
197       .methods = &(hw_module_methods_t) {
198          .open = vn_hal_open,
199       },
200    },
201 };
202 
203 static int
vn_hal_close(UNUSED struct hw_device_t * dev)204 vn_hal_close(UNUSED struct hw_device_t *dev)
205 {
206    vn_android_gralloc_fini();
207    return 0;
208 }
209 
210 static hwvulkan_device_t vn_hal_dev = {
211   .common = {
212      .tag = HARDWARE_DEVICE_TAG,
213      .version = HWVULKAN_DEVICE_API_VERSION_0_1,
214      .module = &HAL_MODULE_INFO_SYM.common,
215      .close = vn_hal_close,
216   },
217  .EnumerateInstanceExtensionProperties = vn_EnumerateInstanceExtensionProperties,
218  .CreateInstance = vn_CreateInstance,
219  .GetInstanceProcAddr = vn_GetInstanceProcAddr,
220 };
221 
222 static int
vn_hal_open(const struct hw_module_t * mod,const char * id,struct hw_device_t ** dev)223 vn_hal_open(const struct hw_module_t *mod,
224             const char *id,
225             struct hw_device_t **dev)
226 {
227    int ret;
228 
229    assert(mod == &HAL_MODULE_INFO_SYM.common);
230    assert(strcmp(id, HWVULKAN_DEVICE_0) == 0);
231 
232    ret = vn_android_gralloc_init();
233    if (ret)
234       return ret;
235 
236    *dev = &vn_hal_dev.common;
237 
238    return 0;
239 }
240 
241 const VkFormat *
vn_android_format_to_view_formats(VkFormat format,uint32_t * out_count)242 vn_android_format_to_view_formats(VkFormat format, uint32_t *out_count)
243 {
244    /* For AHB image prop query and creation, venus overrides the tiling to
245     * VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT, which requires to chain
246     * VkImageFormatListCreateInfo struct in the corresponding pNext when the
247     * VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT is set. Those AHB images are assumed
248     * to be mutable no more than sRGB-ness, and the implementations can fail
249     * whenever going beyond.
250     *
251     * This helper provides the view formats that have sRGB variants for the
252     * image format that venus supports.
253     */
254    static const VkFormat view_formats_r8g8b8a8[] = {
255       VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_R8G8B8A8_SRGB
256    };
257    static const VkFormat view_formats_r8g8b8[] = { VK_FORMAT_R8G8B8_UNORM,
258                                                    VK_FORMAT_R8G8B8_SRGB };
259 
260    switch (format) {
261    case VK_FORMAT_R8G8B8A8_UNORM:
262       *out_count = ARRAY_SIZE(view_formats_r8g8b8a8);
263       return view_formats_r8g8b8a8;
264       break;
265    case VK_FORMAT_R8G8B8_UNORM:
266       *out_count = ARRAY_SIZE(view_formats_r8g8b8);
267       return view_formats_r8g8b8;
268       break;
269    default:
270       /* let the caller handle the fallback case */
271       *out_count = 0;
272       return NULL;
273    }
274 }
275 
276 VkFormat
vn_android_drm_format_to_vk_format(uint32_t format)277 vn_android_drm_format_to_vk_format(uint32_t format)
278 {
279    switch (format) {
280    case DRM_FORMAT_ABGR8888:
281    case DRM_FORMAT_XBGR8888:
282       return VK_FORMAT_R8G8B8A8_UNORM;
283    case DRM_FORMAT_BGR888:
284       return VK_FORMAT_R8G8B8_UNORM;
285    case DRM_FORMAT_RGB565:
286       return VK_FORMAT_R5G6B5_UNORM_PACK16;
287    case DRM_FORMAT_ABGR16161616F:
288       return VK_FORMAT_R16G16B16A16_SFLOAT;
289    case DRM_FORMAT_ABGR2101010:
290       return VK_FORMAT_A2B10G10R10_UNORM_PACK32;
291    case DRM_FORMAT_YVU420:
292       return VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM;
293    case DRM_FORMAT_NV12:
294       return VK_FORMAT_G8_B8R8_2PLANE_420_UNORM;
295    default:
296       return VK_FORMAT_UNDEFINED;
297    }
298 }
299 
300 static bool
vn_android_drm_format_is_yuv(uint32_t format)301 vn_android_drm_format_is_yuv(uint32_t format)
302 {
303    assert(vn_android_drm_format_to_vk_format(format) != VK_FORMAT_UNDEFINED);
304 
305    switch (format) {
306    case DRM_FORMAT_YVU420:
307    case DRM_FORMAT_NV12:
308       return true;
309    default:
310       return false;
311    }
312 }
313 
314 VkResult
vn_GetSwapchainGrallocUsage2ANDROID(VkDevice device,VkFormat format,VkImageUsageFlags imageUsage,VkSwapchainImageUsageFlagsANDROID swapchainImageUsage,uint64_t * grallocConsumerUsage,uint64_t * grallocProducerUsage)315 vn_GetSwapchainGrallocUsage2ANDROID(
316    VkDevice device,
317    VkFormat format,
318    VkImageUsageFlags imageUsage,
319    VkSwapchainImageUsageFlagsANDROID swapchainImageUsage,
320    uint64_t *grallocConsumerUsage,
321    uint64_t *grallocProducerUsage)
322 {
323    struct vn_device *dev = vn_device_from_handle(device);
324 
325    if (VN_DEBUG(WSI)) {
326       vn_log(dev->instance,
327              "format=%d, imageUsage=0x%x, swapchainImageUsage=0x%x", format,
328              imageUsage, swapchainImageUsage);
329    }
330 
331    *grallocConsumerUsage = 0;
332    *grallocProducerUsage = 0;
333    if (imageUsage & (VK_IMAGE_USAGE_TRANSFER_DST_BIT |
334                      VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT))
335       *grallocProducerUsage |= AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER;
336 
337    if (imageUsage &
338        (VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT |
339         VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT))
340       *grallocProducerUsage |= AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
341 
342    if (swapchainImageUsage & VK_SWAPCHAIN_IMAGE_USAGE_SHARED_BIT_ANDROID)
343       *grallocProducerUsage |= vn_android_gralloc_get_shared_present_usage();
344 
345    vn_tls_set_async_pipeline_create();
346 
347    return VK_SUCCESS;
348 }
349 
350 static VkResult
vn_android_get_modifier_properties(struct vn_device * dev,VkFormat format,uint64_t modifier,VkDrmFormatModifierPropertiesEXT * out_props)351 vn_android_get_modifier_properties(struct vn_device *dev,
352                                    VkFormat format,
353                                    uint64_t modifier,
354                                    VkDrmFormatModifierPropertiesEXT *out_props)
355 {
356    VkPhysicalDevice physical_device =
357       vn_physical_device_to_handle(dev->physical_device);
358    VkDrmFormatModifierPropertiesListEXT mod_prop_list = {
359       .sType = VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT,
360    };
361    VkFormatProperties2 format_prop = {
362       .sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2,
363       .pNext = &mod_prop_list,
364    };
365 
366    vn_GetPhysicalDeviceFormatProperties2(physical_device, format,
367                                          &format_prop);
368 
369    if (!mod_prop_list.drmFormatModifierCount) {
370       vn_log(dev->instance, "No compatible modifier for VkFormat(%u)",
371              format);
372       return VK_ERROR_INVALID_EXTERNAL_HANDLE;
373    }
374 
375    STACK_ARRAY(VkDrmFormatModifierPropertiesEXT, mod_props,
376                mod_prop_list.drmFormatModifierCount);
377 
378    mod_prop_list.pDrmFormatModifierProperties = mod_props;
379    vn_GetPhysicalDeviceFormatProperties2(physical_device, format,
380                                          &format_prop);
381 
382    bool modifier_found = false;
383    for (uint32_t i = 0; i < mod_prop_list.drmFormatModifierCount; i++) {
384       if (mod_props[i].drmFormatModifier == modifier) {
385          *out_props = mod_props[i];
386          modifier_found = true;
387          break;
388       }
389    }
390 
391    STACK_ARRAY_FINISH(mod_props);
392 
393    if (!modifier_found) {
394       vn_log(dev->instance,
395              "No matching modifier(%" PRIu64 ") properties for VkFormat(%u)",
396              modifier, format);
397       return VK_ERROR_INVALID_EXTERNAL_HANDLE;
398    }
399 
400    return VK_SUCCESS;
401 }
402 
403 struct vn_android_image_builder {
404    VkImageCreateInfo create;
405    VkSubresourceLayout layouts[4];
406    VkImageDrmFormatModifierExplicitCreateInfoEXT modifier;
407    VkExternalMemoryImageCreateInfo external;
408    VkImageFormatListCreateInfo list;
409 };
410 
411 static VkResult
vn_android_get_image_builder(struct vn_device * dev,const VkImageCreateInfo * create_info,const native_handle_t * handle,struct vn_android_image_builder * out_builder)412 vn_android_get_image_builder(struct vn_device *dev,
413                              const VkImageCreateInfo *create_info,
414                              const native_handle_t *handle,
415                              struct vn_android_image_builder *out_builder)
416 {
417    /* Android image builder is only used by ANB or AHB. For ANB, Android
418     * Vulkan loader will never pass the below structs. For AHB, struct
419     * vn_image_create_deferred_info will never carry below either.
420     */
421    assert(!vk_find_struct_const(
422       create_info->pNext,
423       IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT));
424    assert(!vk_find_struct_const(create_info->pNext,
425                                 EXTERNAL_MEMORY_IMAGE_CREATE_INFO));
426 
427    struct vn_android_gralloc_buffer_properties buf_props;
428    if (!vn_android_gralloc_get_buffer_properties(handle, &buf_props))
429       return VK_ERROR_INVALID_EXTERNAL_HANDLE;
430 
431    /* fill VkImageCreateInfo */
432    memset(out_builder, 0, sizeof(*out_builder));
433    out_builder->create = *create_info;
434    out_builder->create.tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT;
435 
436    /* fill VkImageDrmFormatModifierExplicitCreateInfoEXT */
437    for (uint32_t i = 0; i < buf_props.num_planes; i++) {
438       out_builder->layouts[i].offset = buf_props.offset[i];
439       out_builder->layouts[i].rowPitch = buf_props.stride[i];
440    }
441    out_builder->modifier = (VkImageDrmFormatModifierExplicitCreateInfoEXT){
442       .sType =
443          VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT,
444       .pNext = out_builder->create.pNext,
445       .drmFormatModifier = buf_props.modifier,
446       .drmFormatModifierPlaneCount = buf_props.num_planes,
447       .pPlaneLayouts = out_builder->layouts,
448    };
449    out_builder->create.pNext = &out_builder->modifier;
450 
451    /* fill VkExternalMemoryImageCreateInfo */
452    out_builder->external = (VkExternalMemoryImageCreateInfo){
453       .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO,
454       .pNext = out_builder->create.pNext,
455       .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
456    };
457    out_builder->create.pNext = &out_builder->external;
458 
459    /* fill VkImageFormatListCreateInfo if needed
460     *
461     * vn_image::deferred_info only stores VkImageFormatListCreateInfo with a
462     * non-zero viewFormatCount, and that stored struct will be respected.
463     */
464    if ((create_info->flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) &&
465        !vk_find_struct_const(create_info->pNext,
466                              IMAGE_FORMAT_LIST_CREATE_INFO)) {
467       /* 12.3. Images
468        *
469        * If tiling is VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT and flags
470        * contains VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT, then the pNext chain
471        * must include a VkImageFormatListCreateInfo structure with non-zero
472        * viewFormatCount.
473        */
474       uint32_t vcount = 0;
475       const VkFormat *vformats =
476          vn_android_format_to_view_formats(create_info->format, &vcount);
477       if (!vformats) {
478          /* image builder struct persists through the image creation call */
479          vformats = &out_builder->create.format;
480          vcount = 1;
481       }
482       out_builder->list = (VkImageFormatListCreateInfo){
483          .sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO,
484          .pNext = out_builder->create.pNext,
485          .viewFormatCount = vcount,
486          .pViewFormats = vformats,
487       };
488       out_builder->create.pNext = &out_builder->list;
489    }
490 
491    return VK_SUCCESS;
492 }
493 
494 static VkResult
vn_android_image_from_anb_internal(struct vn_device * dev,const VkImageCreateInfo * create_info,const VkNativeBufferANDROID * anb_info,const VkAllocationCallbacks * alloc,struct vn_image ** out_img)495 vn_android_image_from_anb_internal(struct vn_device *dev,
496                                    const VkImageCreateInfo *create_info,
497                                    const VkNativeBufferANDROID *anb_info,
498                                    const VkAllocationCallbacks *alloc,
499                                    struct vn_image **out_img)
500 {
501    /* If anb_info->handle points to a classic resouce created from
502     * virtio_gpu_cmd_resource_create_3d, anb_info->stride is the stride of the
503     * guest shadow storage other than the host gpu storage.
504     *
505     * We also need to pass the correct stride to vn_CreateImage, which will be
506     * done via VkImageDrmFormatModifierExplicitCreateInfoEXT and will require
507     * VK_EXT_image_drm_format_modifier support in the host driver. The struct
508     * needs host storage info which can be queried from cros gralloc.
509     */
510    struct vn_image *img = NULL;
511    VkResult result;
512 
513    assert(!(create_info->flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT));
514    assert(!vk_find_struct_const(create_info->pNext,
515                                 IMAGE_FORMAT_LIST_CREATE_INFO));
516    assert(!vk_find_struct_const(create_info->pNext,
517                                 IMAGE_STENCIL_USAGE_CREATE_INFO));
518 
519    struct vn_android_image_builder builder;
520    result = vn_android_get_image_builder(dev, create_info, anb_info->handle,
521                                          &builder);
522    if (result != VK_SUCCESS)
523       return result;
524 
525    /* encoder will strip the Android specific pNext structs */
526    if (*out_img) {
527       /* driver side img obj has been created for deferred init like ahb */
528       img = *out_img;
529       result = vn_image_init_deferred(dev, &builder.create, img);
530       if (result != VK_SUCCESS) {
531          vn_log(dev->instance, "anb: vn_image_init_deferred failed");
532          return result;
533       }
534    } else {
535       result = vn_image_create(dev, &builder.create, alloc, &img);
536       if (result != VK_SUCCESS) {
537          vn_log(dev->instance, "anb: vn_image_create failed");
538          return result;
539       }
540    }
541 
542    img->wsi.is_wsi = true;
543    img->wsi.tiling_override = builder.create.tiling;
544    img->wsi.drm_format_modifier = builder.modifier.drmFormatModifier;
545 
546    int dma_buf_fd = vn_android_gralloc_get_dma_buf_fd(anb_info->handle);
547    if (dma_buf_fd < 0) {
548       result = VK_ERROR_INVALID_EXTERNAL_HANDLE;
549       goto fail;
550    }
551 
552    uint64_t alloc_size = 0;
553    uint32_t mem_type_bits = 0;
554    result = vn_get_memory_dma_buf_properties(dev, dma_buf_fd, &alloc_size,
555                                              &mem_type_bits);
556    if (result != VK_SUCCESS)
557       goto fail;
558 
559    const VkMemoryRequirements *mem_req =
560       &img->requirements[0].memory.memoryRequirements;
561    if (alloc_size < mem_req->size) {
562       vn_log(dev->instance,
563              "anb: alloc_size(%" PRIu64 ") mem_req->size(%" PRIu64 ")",
564              alloc_size, mem_req->size);
565       result = VK_ERROR_INVALID_EXTERNAL_HANDLE;
566       goto fail;
567    }
568 
569    mem_type_bits &= mem_req->memoryTypeBits;
570    if (!mem_type_bits) {
571       vn_log(dev->instance, "anb: no compatible mem type");
572       result = VK_ERROR_INVALID_EXTERNAL_HANDLE;
573       goto fail;
574    }
575 
576    int dup_fd = os_dupfd_cloexec(dma_buf_fd);
577    if (dup_fd < 0) {
578       vn_log(dev->instance, "anb: os_dupfd_cloexec failed(%d)", errno);
579       result = (errno == EMFILE) ? VK_ERROR_TOO_MANY_OBJECTS
580                                  : VK_ERROR_OUT_OF_HOST_MEMORY;
581       goto fail;
582    }
583 
584    const VkImportMemoryFdInfoKHR import_fd_info = {
585       .sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR,
586       .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
587       .fd = dup_fd,
588    };
589    const VkMemoryAllocateInfo memory_info = {
590       .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
591       .pNext = &import_fd_info,
592       .allocationSize = mem_req->size,
593       .memoryTypeIndex = ffs(mem_type_bits) - 1,
594    };
595    VkDeviceMemory mem_handle;
596    result = vn_AllocateMemory(vn_device_to_handle(dev), &memory_info, alloc,
597                               &mem_handle);
598    if (result != VK_SUCCESS) {
599       vn_log(dev->instance, "anb: mem import failed");
600       /* only need to close the dup_fd on import failure */
601       close(dup_fd);
602       goto fail;
603    }
604 
605    /* Android WSI image owns the memory */
606    img->wsi.memory = vn_device_memory_from_handle(mem_handle);
607    img->wsi.memory_owned = true;
608    *out_img = img;
609 
610    return VK_SUCCESS;
611 
612 fail:
613    /* this handles mem free for owned import */
614    vn_DestroyImage(vn_device_to_handle(dev), vn_image_to_handle(img), alloc);
615    return result;
616 }
617 
618 VkResult
vn_android_image_from_anb(struct vn_device * dev,const VkImageCreateInfo * create_info,const VkNativeBufferANDROID * anb_info,const VkAllocationCallbacks * alloc,struct vn_image ** out_img)619 vn_android_image_from_anb(struct vn_device *dev,
620                           const VkImageCreateInfo *create_info,
621                           const VkNativeBufferANDROID *anb_info,
622                           const VkAllocationCallbacks *alloc,
623                           struct vn_image **out_img)
624 {
625    struct vn_image *img = NULL;
626    VkResult result = vn_android_image_from_anb_internal(
627       dev, create_info, anb_info, alloc, &img);
628    if (result != VK_SUCCESS)
629       return result;
630 
631    const VkBindImageMemoryInfo bind_info = {
632       .sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO,
633       .image = vn_image_to_handle(img),
634       .memory = vn_device_memory_to_handle(img->wsi.memory),
635    };
636    result = vn_BindImageMemory2(vn_device_to_handle(dev), 1, &bind_info);
637    if (result != VK_SUCCESS) {
638       vn_DestroyImage(vn_device_to_handle(dev), vn_image_to_handle(img),
639                       alloc);
640       return result;
641    }
642 
643    *out_img = img;
644    return VK_SUCCESS;
645 }
646 
647 struct vn_device_memory *
vn_android_get_wsi_memory_from_bind_info(struct vn_device * dev,const VkBindImageMemoryInfo * bind_info)648 vn_android_get_wsi_memory_from_bind_info(
649    struct vn_device *dev, const VkBindImageMemoryInfo *bind_info)
650 {
651    const VkNativeBufferANDROID *anb_info =
652       vk_find_struct_const(bind_info->pNext, NATIVE_BUFFER_ANDROID);
653    assert(anb_info && anb_info->handle);
654 
655    struct vn_image *img = vn_image_from_handle(bind_info->image);
656    VkResult result = vn_android_image_from_anb_internal(
657       dev, &img->deferred_info->create, anb_info, &dev->base.base.alloc,
658       &img);
659    if (result != VK_SUCCESS)
660       return NULL;
661 
662    assert(img->wsi.memory_owned);
663    return img->wsi.memory;
664 }
665 
666 static VkResult
vn_android_get_ahb_format_properties(struct vn_device * dev,const struct AHardwareBuffer * ahb,VkAndroidHardwareBufferFormatPropertiesANDROID * out_props)667 vn_android_get_ahb_format_properties(
668    struct vn_device *dev,
669    const struct AHardwareBuffer *ahb,
670    VkAndroidHardwareBufferFormatPropertiesANDROID *out_props)
671 {
672    AHardwareBuffer_Desc desc;
673    VkFormat format;
674    struct vn_android_gralloc_buffer_properties buf_props;
675    VkDrmFormatModifierPropertiesEXT mod_props;
676 
677    AHardwareBuffer_describe(ahb, &desc);
678    if (!(desc.usage & (AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE |
679                        AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER |
680                        AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER))) {
681       vn_log(dev->instance,
682              "AHB usage(%" PRIu64 ") must include at least one GPU bit",
683              desc.usage);
684       return VK_ERROR_INVALID_EXTERNAL_HANDLE;
685    }
686 
687    /* Handle the special AHARDWAREBUFFER_FORMAT_BLOB for VkBuffer case. */
688    if (desc.format == AHARDWAREBUFFER_FORMAT_BLOB) {
689       out_props->format = VK_FORMAT_UNDEFINED;
690       return VK_SUCCESS;
691    }
692 
693    if (!vn_android_gralloc_get_buffer_properties(
694           AHardwareBuffer_getNativeHandle(ahb), &buf_props))
695       return VK_ERROR_INVALID_EXTERNAL_HANDLE;
696 
697    /* We implement AHB extension support with EXT_image_drm_format_modifier.
698     * It requires us to have a compatible VkFormat but not DRM formats. So if
699     * the ahb is not intended for backing a VkBuffer, error out early if the
700     * format is VK_FORMAT_UNDEFINED.
701     */
702    format = vn_android_drm_format_to_vk_format(buf_props.drm_fourcc);
703    if (format == VK_FORMAT_UNDEFINED) {
704       vn_log(dev->instance, "Unknown drm_fourcc(%u) from AHB format(0x%X)",
705              buf_props.drm_fourcc, desc.format);
706       return VK_ERROR_INVALID_EXTERNAL_HANDLE;
707    }
708 
709    VkResult result = vn_android_get_modifier_properties(
710       dev, format, buf_props.modifier, &mod_props);
711    if (result != VK_SUCCESS)
712       return result;
713 
714    if (mod_props.drmFormatModifierPlaneCount != buf_props.num_planes) {
715       vn_log(dev->instance,
716              "drmFormatModifierPlaneCount(%u) != buf_props.num_planes(%u) "
717              "for DRM format modifier(%" PRIu64 ")",
718              mod_props.drmFormatModifierPlaneCount, buf_props.num_planes,
719              buf_props.modifier);
720       return VK_ERROR_INVALID_EXTERNAL_HANDLE;
721    }
722 
723    /* The spec requires that formatFeatures must include at least one of
724     * VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT or
725     * VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT.
726     */
727    const VkFormatFeatureFlags format_features =
728       mod_props.drmFormatModifierTilingFeatures |
729       VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT;
730 
731    /* 11.2.7. Android Hardware Buffer External Memory
732     *
733     * Implementations may not always be able to determine the color model,
734     * numerical range, or chroma offsets of the image contents, so the values
735     * in VkAndroidHardwareBufferFormatPropertiesANDROID are only suggestions.
736     * Applications should treat these values as sensible defaults to use in the
737     * absence of more reliable information obtained through some other means.
738     */
739    const bool is_yuv = vn_android_drm_format_is_yuv(buf_props.drm_fourcc);
740    const VkSamplerYcbcrModelConversion model =
741       is_yuv ? VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601
742              : VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY;
743 
744    /* ANGLE expects VK_FORMAT_UNDEFINED with externalFormat resolved from
745     * AHARDWAREBUFFER_FORMAT_IMPLEMENTATION_DEFINED and any supported planar
746     * AHB formats. Venus supports below explicit ones:
747     * - AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420 (DRM_FORMAT_NV12)
748     * - AHARDWAREBUFFER_FORMAT_YV12 (DRM_FORMAT_YVU420)
749     */
750    if (desc.format == AHARDWAREBUFFER_FORMAT_IMPLEMENTATION_DEFINED || is_yuv)
751       format = VK_FORMAT_UNDEFINED;
752 
753    *out_props = (VkAndroidHardwareBufferFormatPropertiesANDROID) {
754       .sType = out_props->sType,
755       .pNext = out_props->pNext,
756       .format = format,
757       .externalFormat = buf_props.drm_fourcc,
758       .formatFeatures = format_features,
759       .samplerYcbcrConversionComponents = {
760          .r = VK_COMPONENT_SWIZZLE_IDENTITY,
761          .g = VK_COMPONENT_SWIZZLE_IDENTITY,
762          .b = VK_COMPONENT_SWIZZLE_IDENTITY,
763          .a = VK_COMPONENT_SWIZZLE_IDENTITY,
764       },
765       .suggestedYcbcrModel = model,
766       /* match EGL_YUV_NARROW_RANGE_EXT used in egl platform_android */
767       .suggestedYcbcrRange = VK_SAMPLER_YCBCR_RANGE_ITU_NARROW,
768       .suggestedXChromaOffset = VK_CHROMA_LOCATION_MIDPOINT,
769       .suggestedYChromaOffset = VK_CHROMA_LOCATION_MIDPOINT,
770    };
771 
772    return VK_SUCCESS;
773 }
774 
775 VkResult
vn_GetAndroidHardwareBufferPropertiesANDROID(VkDevice device,const struct AHardwareBuffer * buffer,VkAndroidHardwareBufferPropertiesANDROID * pProperties)776 vn_GetAndroidHardwareBufferPropertiesANDROID(
777    VkDevice device,
778    const struct AHardwareBuffer *buffer,
779    VkAndroidHardwareBufferPropertiesANDROID *pProperties)
780 {
781    VN_TRACE_FUNC();
782    struct vn_device *dev = vn_device_from_handle(device);
783    VkResult result = VK_SUCCESS;
784    int dma_buf_fd = -1;
785    uint64_t alloc_size = 0;
786    uint32_t mem_type_bits = 0;
787 
788    VkAndroidHardwareBufferFormatProperties2ANDROID *format_props2 =
789       vk_find_struct(pProperties->pNext,
790                      ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_2_ANDROID);
791    VkAndroidHardwareBufferFormatPropertiesANDROID *format_props =
792       vk_find_struct(pProperties->pNext,
793                      ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID);
794    if (format_props2 || format_props) {
795       VkAndroidHardwareBufferFormatPropertiesANDROID local_props = {
796          .sType =
797             VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID,
798       };
799       if (!format_props)
800          format_props = &local_props;
801 
802       result =
803          vn_android_get_ahb_format_properties(dev, buffer, format_props);
804       if (result != VK_SUCCESS)
805          return vn_error(dev->instance, result);
806 
807       if (format_props2) {
808          format_props2->format = format_props->format;
809          format_props2->externalFormat = format_props->externalFormat;
810          format_props2->formatFeatures =
811             (VkFormatFeatureFlags2)format_props->formatFeatures;
812          format_props2->samplerYcbcrConversionComponents =
813             format_props->samplerYcbcrConversionComponents;
814          format_props2->suggestedYcbcrModel =
815             format_props->suggestedYcbcrModel;
816          format_props2->suggestedYcbcrRange =
817             format_props->suggestedYcbcrRange;
818          format_props2->suggestedXChromaOffset =
819             format_props->suggestedXChromaOffset;
820          format_props2->suggestedYChromaOffset =
821             format_props->suggestedYChromaOffset;
822       }
823    }
824 
825    dma_buf_fd = vn_android_gralloc_get_dma_buf_fd(
826       AHardwareBuffer_getNativeHandle(buffer));
827    if (dma_buf_fd < 0)
828       return vn_error(dev->instance, VK_ERROR_INVALID_EXTERNAL_HANDLE);
829 
830    result = vn_get_memory_dma_buf_properties(dev, dma_buf_fd, &alloc_size,
831                                              &mem_type_bits);
832    if (result != VK_SUCCESS)
833       return vn_error(dev->instance, result);
834 
835    pProperties->allocationSize = alloc_size;
836    pProperties->memoryTypeBits = mem_type_bits;
837 
838    return VK_SUCCESS;
839 }
840 
841 static AHardwareBuffer *
vn_android_ahb_allocate(uint32_t width,uint32_t height,uint32_t layers,uint32_t format,uint64_t usage)842 vn_android_ahb_allocate(uint32_t width,
843                         uint32_t height,
844                         uint32_t layers,
845                         uint32_t format,
846                         uint64_t usage)
847 {
848    AHardwareBuffer *ahb = NULL;
849    AHardwareBuffer_Desc desc;
850    int ret = 0;
851 
852    memset(&desc, 0, sizeof(desc));
853    desc.width = width;
854    desc.height = height;
855    desc.layers = layers;
856    desc.format = format;
857    desc.usage = usage;
858 
859    ret = AHardwareBuffer_allocate(&desc, &ahb);
860    if (ret) {
861       /* We just log the error code here for now since the platform falsely
862        * maps all gralloc allocation failures to oom.
863        */
864       vn_log(NULL, "AHB alloc(w=%u,h=%u,l=%u,f=%u,u=%" PRIu64 ") failed(%d)",
865              width, height, layers, format, usage, ret);
866       return NULL;
867    }
868 
869    return ahb;
870 }
871 
872 bool
vn_android_get_drm_format_modifier_info(const VkPhysicalDeviceImageFormatInfo2 * format_info,VkPhysicalDeviceImageDrmFormatModifierInfoEXT * out_info)873 vn_android_get_drm_format_modifier_info(
874    const VkPhysicalDeviceImageFormatInfo2 *format_info,
875    VkPhysicalDeviceImageDrmFormatModifierInfoEXT *out_info)
876 {
877    /* To properly fill VkPhysicalDeviceImageDrmFormatModifierInfoEXT, we have
878     * to allocate an ahb to retrieve the drm format modifier. For the image
879     * sharing mode, we assume VK_SHARING_MODE_EXCLUSIVE for now.
880     */
881    AHardwareBuffer *ahb = NULL;
882    uint32_t format = 0;
883    uint64_t usage = 0;
884    struct vn_android_gralloc_buffer_properties buf_props;
885 
886    assert(format_info->tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT);
887 
888    format = vk_image_format_to_ahb_format(format_info->format);
889    if (!format)
890       return false;
891 
892    usage =
893       vk_image_usage_to_ahb_usage(format_info->flags, format_info->usage);
894    ahb = vn_android_ahb_allocate(16, 16, 1, format, usage);
895    if (!ahb)
896       return false;
897 
898    if (!vn_android_gralloc_get_buffer_properties(
899           AHardwareBuffer_getNativeHandle(ahb), &buf_props)) {
900       AHardwareBuffer_release(ahb);
901       return false;
902    }
903 
904    *out_info = (VkPhysicalDeviceImageDrmFormatModifierInfoEXT){
905       .sType =
906          VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT,
907       .pNext = NULL,
908       .drmFormatModifier = buf_props.modifier,
909       .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
910       .queueFamilyIndexCount = 0,
911       .pQueueFamilyIndices = NULL,
912    };
913 
914    AHardwareBuffer_release(ahb);
915    return true;
916 }
917 
918 VkResult
vn_android_device_import_ahb(struct vn_device * dev,struct vn_device_memory * mem,const struct VkMemoryDedicatedAllocateInfo * dedicated_info)919 vn_android_device_import_ahb(
920    struct vn_device *dev,
921    struct vn_device_memory *mem,
922    const struct VkMemoryDedicatedAllocateInfo *dedicated_info)
923 {
924    const struct vk_device_memory *mem_vk = &mem->base.base;
925    const native_handle_t *handle = NULL;
926    int dma_buf_fd = -1;
927    int dup_fd = -1;
928    uint64_t alloc_size = 0;
929    uint32_t mem_type_bits = 0;
930    uint32_t mem_type_index = mem_vk->memory_type_index;
931    bool force_unmappable = false;
932    VkResult result = VK_SUCCESS;
933 
934    handle = AHardwareBuffer_getNativeHandle(mem_vk->ahardware_buffer);
935    dma_buf_fd = vn_android_gralloc_get_dma_buf_fd(handle);
936    if (dma_buf_fd < 0)
937       return VK_ERROR_INVALID_EXTERNAL_HANDLE;
938 
939    result = vn_get_memory_dma_buf_properties(dev, dma_buf_fd, &alloc_size,
940                                              &mem_type_bits);
941    if (result != VK_SUCCESS)
942       return result;
943 
944    /* If ahb is for an image, finish the deferred image creation first */
945    if (dedicated_info && dedicated_info->image != VK_NULL_HANDLE) {
946       struct vn_image *img = vn_image_from_handle(dedicated_info->image);
947       struct vn_android_image_builder builder;
948 
949       result = vn_android_get_image_builder(dev, &img->deferred_info->create,
950                                             handle, &builder);
951       if (result != VK_SUCCESS)
952          return result;
953 
954       result = vn_image_init_deferred(dev, &builder.create, img);
955       if (result != VK_SUCCESS)
956          return result;
957 
958       const VkMemoryRequirements *mem_req =
959          &img->requirements[0].memory.memoryRequirements;
960       if (alloc_size < mem_req->size) {
961          vn_log(dev->instance,
962                 "alloc_size(%" PRIu64 ") mem_req->size(%" PRIu64 ")",
963                 alloc_size, mem_req->size);
964          return VK_ERROR_INVALID_EXTERNAL_HANDLE;
965       }
966 
967       alloc_size = mem_req->size;
968 
969       /* Per spec 11.2.3. Device Memory Allocation
970        *
971        * If the parameters define an export operation and the external handle
972        * type is
973        * VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID,
974        * implementations should not strictly follow memoryTypeIndex. Instead,
975        * they should modify the allocation internally to use the required
976        * memory type for the application’s given usage. This is because for an
977        * export operation, there is currently no way for the client to know
978        * the memory type index before allocating.
979        */
980       if (!(mem_vk->import_handle_type &
981             VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID)) {
982          if ((mem_type_bits & mem_req->memoryTypeBits) == 0) {
983             vn_log(dev->instance, "memoryTypeBits: img(0x%X) fd(0x%X)",
984                    mem_req->memoryTypeBits, mem_type_bits);
985             return VK_ERROR_INVALID_EXTERNAL_HANDLE;
986          }
987 
988          mem_type_index = ffs(mem_type_bits & mem_req->memoryTypeBits) - 1;
989       }
990 
991       /* XXX Workaround before we use cross-domain backend in minigbm. The
992        * blob_mem allocated from virgl backend can have a queried guest
993        * mappable size smaller than the size returned from image memory
994        * requirement.
995        */
996       force_unmappable = true;
997    }
998 
999    if (dedicated_info && dedicated_info->buffer != VK_NULL_HANDLE) {
1000       struct vn_buffer *buf = vn_buffer_from_handle(dedicated_info->buffer);
1001       const VkMemoryRequirements *mem_req =
1002          &buf->requirements.memory.memoryRequirements;
1003       if (alloc_size < mem_req->size) {
1004          vn_log(dev->instance,
1005                 "alloc_size(%" PRIu64 ") mem_req->size(%" PRIu64 ")",
1006                 alloc_size, mem_req->size);
1007          return VK_ERROR_INVALID_EXTERNAL_HANDLE;
1008       }
1009 
1010       alloc_size = mem_req->size;
1011 
1012       assert((1 << mem_type_index) & mem_req->memoryTypeBits);
1013    }
1014 
1015    assert((1 << mem_type_index) & mem_type_bits);
1016 
1017    errno = 0;
1018    dup_fd = os_dupfd_cloexec(dma_buf_fd);
1019    if (dup_fd < 0)
1020       return (errno == EMFILE) ? VK_ERROR_TOO_MANY_OBJECTS
1021                                : VK_ERROR_OUT_OF_HOST_MEMORY;
1022 
1023    /* Spec requires AHB export info to be present, so we must strip it. In
1024     * practice, the AHB import path here only needs the main allocation info
1025     * and the dedicated_info.
1026     */
1027    VkMemoryDedicatedAllocateInfo local_dedicated_info;
1028    /* Override when dedicated_info exists and is not the tail struct. */
1029    if (dedicated_info && dedicated_info->pNext) {
1030       local_dedicated_info = *dedicated_info;
1031       local_dedicated_info.pNext = NULL;
1032       dedicated_info = &local_dedicated_info;
1033    }
1034    const VkMemoryAllocateInfo local_alloc_info = {
1035       .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
1036       .pNext = dedicated_info,
1037       .allocationSize = alloc_size,
1038       .memoryTypeIndex = mem_type_index,
1039    };
1040    result = vn_device_memory_import_dma_buf(dev, mem, &local_alloc_info,
1041                                             force_unmappable, dup_fd);
1042    if (result != VK_SUCCESS) {
1043       close(dup_fd);
1044       return result;
1045    }
1046 
1047    return VK_SUCCESS;
1048 }
1049 
1050 uint32_t
vn_android_get_ahb_buffer_memory_type_bits(struct vn_device * dev)1051 vn_android_get_ahb_buffer_memory_type_bits(struct vn_device *dev)
1052 {
1053    static const uint32_t format = AHARDWAREBUFFER_FORMAT_BLOB;
1054    /* ensure dma_buf_memory_type_bits covers host visible usage */
1055    static const uint64_t usage = AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER |
1056                                  AHARDWAREBUFFER_USAGE_CPU_READ_RARELY |
1057                                  AHARDWAREBUFFER_USAGE_CPU_WRITE_RARELY;
1058    AHardwareBuffer *ahb = vn_android_ahb_allocate(4096, 1, 1, format, usage);
1059    if (!ahb)
1060       return 0;
1061 
1062    int dma_buf_fd =
1063       vn_android_gralloc_get_dma_buf_fd(AHardwareBuffer_getNativeHandle(ahb));
1064    if (dma_buf_fd < 0) {
1065       AHardwareBuffer_release(ahb);
1066       return 0;
1067    }
1068 
1069    uint64_t alloc_size = 0;
1070    uint32_t mem_type_bits = 0;
1071    VkResult ret = vn_get_memory_dma_buf_properties(
1072       dev, dma_buf_fd, &alloc_size, &mem_type_bits);
1073    /* release ahb first as below no longer needs it */
1074    AHardwareBuffer_release(ahb);
1075 
1076    if (ret != VK_SUCCESS) {
1077       vn_log(dev->instance, "AHB buffer mem type bits query failed %d", ret);
1078       return 0;
1079    }
1080 
1081    return mem_type_bits;
1082 }
1083