• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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,const VkAllocationCallbacks * alloc,VkDrmFormatModifierPropertiesEXT * out_props)351 vn_android_get_modifier_properties(struct vn_device *dev,
352                                    VkFormat format,
353                                    uint64_t modifier,
354                                    const VkAllocationCallbacks *alloc,
355                                    VkDrmFormatModifierPropertiesEXT *out_props)
356 {
357    VkPhysicalDevice physical_device =
358       vn_physical_device_to_handle(dev->physical_device);
359    VkDrmFormatModifierPropertiesListEXT mod_prop_list = {
360       .sType = VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT,
361       .pNext = NULL,
362       .drmFormatModifierCount = 0,
363       .pDrmFormatModifierProperties = NULL,
364    };
365    VkFormatProperties2 format_prop = {
366       .sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2,
367       .pNext = &mod_prop_list,
368    };
369    VkDrmFormatModifierPropertiesEXT *mod_props = NULL;
370    bool modifier_found = false;
371 
372    vn_GetPhysicalDeviceFormatProperties2(physical_device, format,
373                                          &format_prop);
374 
375    if (!mod_prop_list.drmFormatModifierCount) {
376       vn_log(dev->instance, "No compatible modifier for VkFormat(%u)",
377              format);
378       return VK_ERROR_INVALID_EXTERNAL_HANDLE;
379    }
380 
381    mod_props = vk_zalloc(
382       alloc, sizeof(*mod_props) * mod_prop_list.drmFormatModifierCount,
383       VN_DEFAULT_ALIGN, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
384    if (!mod_props)
385       return VK_ERROR_OUT_OF_HOST_MEMORY;
386 
387    mod_prop_list.pDrmFormatModifierProperties = mod_props;
388    vn_GetPhysicalDeviceFormatProperties2(physical_device, format,
389                                          &format_prop);
390 
391    for (uint32_t i = 0; i < mod_prop_list.drmFormatModifierCount; i++) {
392       if (mod_props[i].drmFormatModifier == modifier) {
393          *out_props = mod_props[i];
394          modifier_found = true;
395          break;
396       }
397    }
398 
399    vk_free(alloc, mod_props);
400 
401    if (!modifier_found) {
402       vn_log(dev->instance,
403              "No matching modifier(%" PRIu64 ") properties for VkFormat(%u)",
404              modifier, format);
405       return VK_ERROR_INVALID_EXTERNAL_HANDLE;
406    }
407 
408    return VK_SUCCESS;
409 }
410 
411 struct vn_android_image_builder {
412    VkImageCreateInfo create;
413    VkSubresourceLayout layouts[4];
414    VkImageDrmFormatModifierExplicitCreateInfoEXT modifier;
415    VkExternalMemoryImageCreateInfo external;
416    VkImageFormatListCreateInfo list;
417 };
418 
419 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)420 vn_android_get_image_builder(struct vn_device *dev,
421                              const VkImageCreateInfo *create_info,
422                              const native_handle_t *handle,
423                              struct vn_android_image_builder *out_builder)
424 {
425    /* Android image builder is only used by ANB or AHB. For ANB, Android
426     * Vulkan loader will never pass the below structs. For AHB, struct
427     * vn_image_create_deferred_info will never carry below either.
428     */
429    assert(!vk_find_struct_const(
430       create_info->pNext,
431       IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT));
432    assert(!vk_find_struct_const(create_info->pNext,
433                                 EXTERNAL_MEMORY_IMAGE_CREATE_INFO));
434 
435    struct vn_android_gralloc_buffer_properties buf_props;
436    if (!vn_android_gralloc_get_buffer_properties(handle, &buf_props))
437       return VK_ERROR_INVALID_EXTERNAL_HANDLE;
438 
439    /* fill VkImageCreateInfo */
440    memset(out_builder, 0, sizeof(*out_builder));
441    out_builder->create = *create_info;
442    out_builder->create.tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT;
443 
444    /* fill VkImageDrmFormatModifierExplicitCreateInfoEXT */
445    for (uint32_t i = 0; i < buf_props.num_planes; i++) {
446       out_builder->layouts[i].offset = buf_props.offset[i];
447       out_builder->layouts[i].rowPitch = buf_props.stride[i];
448    }
449    out_builder->modifier = (VkImageDrmFormatModifierExplicitCreateInfoEXT){
450       .sType =
451          VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT,
452       .pNext = out_builder->create.pNext,
453       .drmFormatModifier = buf_props.modifier,
454       .drmFormatModifierPlaneCount = buf_props.num_planes,
455       .pPlaneLayouts = out_builder->layouts,
456    };
457    out_builder->create.pNext = &out_builder->modifier;
458 
459    /* fill VkExternalMemoryImageCreateInfo */
460    out_builder->external = (VkExternalMemoryImageCreateInfo){
461       .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO,
462       .pNext = out_builder->create.pNext,
463       .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
464    };
465    out_builder->create.pNext = &out_builder->external;
466 
467    /* fill VkImageFormatListCreateInfo if needed
468     *
469     * vn_image::deferred_info only stores VkImageFormatListCreateInfo with a
470     * non-zero viewFormatCount, and that stored struct will be respected.
471     */
472    if ((create_info->flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) &&
473        !vk_find_struct_const(create_info->pNext,
474                              IMAGE_FORMAT_LIST_CREATE_INFO)) {
475       /* 12.3. Images
476        *
477        * If tiling is VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT and flags
478        * contains VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT, then the pNext chain
479        * must include a VkImageFormatListCreateInfo structure with non-zero
480        * viewFormatCount.
481        */
482       uint32_t vcount = 0;
483       const VkFormat *vformats =
484          vn_android_format_to_view_formats(create_info->format, &vcount);
485       if (!vformats) {
486          /* image builder struct persists through the image creation call */
487          vformats = &out_builder->create.format;
488          vcount = 1;
489       }
490       out_builder->list = (VkImageFormatListCreateInfo){
491          .sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO,
492          .pNext = out_builder->create.pNext,
493          .viewFormatCount = vcount,
494          .pViewFormats = vformats,
495       };
496       out_builder->create.pNext = &out_builder->list;
497    }
498 
499    return VK_SUCCESS;
500 }
501 
502 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)503 vn_android_image_from_anb(struct vn_device *dev,
504                           const VkImageCreateInfo *create_info,
505                           const VkNativeBufferANDROID *anb_info,
506                           const VkAllocationCallbacks *alloc,
507                           struct vn_image **out_img)
508 {
509    /* If anb_info->handle points to a classic resouce created from
510     * virtio_gpu_cmd_resource_create_3d, anb_info->stride is the stride of the
511     * guest shadow storage other than the host gpu storage.
512     *
513     * We also need to pass the correct stride to vn_CreateImage, which will be
514     * done via VkImageDrmFormatModifierExplicitCreateInfoEXT and will require
515     * VK_EXT_image_drm_format_modifier support in the host driver. The struct
516     * needs host storage info which can be queried from cros gralloc.
517     */
518    VkResult result = VK_SUCCESS;
519    VkDevice device = vn_device_to_handle(dev);
520    VkDeviceMemory memory = VK_NULL_HANDLE;
521    VkImage image = VK_NULL_HANDLE;
522    struct vn_image *img = NULL;
523    uint64_t alloc_size = 0;
524    uint32_t mem_type_bits = 0;
525    int dma_buf_fd = -1;
526    int dup_fd = -1;
527    VkImageCreateInfo local_create_info;
528    struct vn_android_image_builder builder;
529 
530    dma_buf_fd = vn_android_gralloc_get_dma_buf_fd(anb_info->handle);
531    if (dma_buf_fd < 0) {
532       result = VK_ERROR_INVALID_EXTERNAL_HANDLE;
533       goto fail;
534    }
535 
536    assert(!(create_info->flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT));
537    assert(!vk_find_struct_const(create_info->pNext,
538                                 IMAGE_FORMAT_LIST_CREATE_INFO));
539    assert(!vk_find_struct_const(create_info->pNext,
540                                 IMAGE_STENCIL_USAGE_CREATE_INFO));
541 
542    /* strip VkNativeBufferANDROID and VkSwapchainImageCreateInfoANDROID */
543    local_create_info = *create_info;
544    local_create_info.pNext = NULL;
545    result = vn_android_get_image_builder(dev, &local_create_info,
546                                          anb_info->handle, &builder);
547    if (result != VK_SUCCESS)
548       goto fail;
549 
550    /* encoder will strip the Android specific pNext structs */
551    result = vn_image_create(dev, &builder.create, alloc, &img);
552    if (result != VK_SUCCESS) {
553       if (VN_DEBUG(WSI))
554          vn_log(dev->instance, "vn_image_create failed");
555       goto fail;
556    }
557 
558    image = vn_image_to_handle(img);
559 
560    const VkMemoryRequirements *mem_req =
561       &img->requirements[0].memory.memoryRequirements;
562    if (!mem_req->memoryTypeBits) {
563       if (VN_DEBUG(WSI))
564          vn_log(dev->instance, "mem_req->memoryTypeBits cannot be zero");
565       result = VK_ERROR_INVALID_EXTERNAL_HANDLE;
566       goto fail;
567    }
568 
569    result = vn_get_memory_dma_buf_properties(dev, dma_buf_fd, &alloc_size,
570                                              &mem_type_bits);
571    if (result != VK_SUCCESS)
572       goto fail;
573 
574    if (VN_DEBUG(WSI)) {
575       vn_log(dev->instance,
576              "size = img(%" PRIu64 ") fd(%" PRIu64 "), "
577              "memoryTypeBits = img(0x%X) & fd(0x%X)",
578              mem_req->size, alloc_size, mem_req->memoryTypeBits,
579              mem_type_bits);
580    }
581 
582    if (alloc_size < mem_req->size) {
583       if (VN_DEBUG(WSI)) {
584          vn_log(dev->instance,
585                 "alloc_size(%" PRIu64 ") mem_req->size(%" PRIu64 ")",
586                 alloc_size, mem_req->size);
587       }
588       result = VK_ERROR_INVALID_EXTERNAL_HANDLE;
589       goto fail;
590    }
591 
592    mem_type_bits &= mem_req->memoryTypeBits;
593    if (!mem_type_bits) {
594       result = VK_ERROR_INVALID_EXTERNAL_HANDLE;
595       goto fail;
596    }
597 
598    dup_fd = os_dupfd_cloexec(dma_buf_fd);
599    if (dup_fd < 0) {
600       result = (errno == EMFILE) ? VK_ERROR_TOO_MANY_OBJECTS
601                                  : VK_ERROR_OUT_OF_HOST_MEMORY;
602       goto fail;
603    }
604 
605    const VkImportMemoryFdInfoKHR import_fd_info = {
606       .sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR,
607       .pNext = NULL,
608       .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
609       .fd = dup_fd,
610    };
611    const VkMemoryAllocateInfo memory_info = {
612       .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
613       .pNext = &import_fd_info,
614       .allocationSize = mem_req->size,
615       .memoryTypeIndex = ffs(mem_type_bits) - 1,
616    };
617    result = vn_AllocateMemory(device, &memory_info, alloc, &memory);
618    if (result != VK_SUCCESS) {
619       /* only need to close the dup_fd on import failure */
620       close(dup_fd);
621       goto fail;
622    }
623 
624    const VkBindImageMemoryInfo bind_info = {
625       .sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO,
626       .pNext = NULL,
627       .image = image,
628       .memory = memory,
629       .memoryOffset = 0,
630    };
631    result = vn_BindImageMemory2(device, 1, &bind_info);
632    if (result != VK_SUCCESS)
633       goto fail;
634 
635    img->wsi.is_wsi = true;
636    img->wsi.tiling_override = builder.create.tiling;
637    img->wsi.drm_format_modifier = builder.modifier.drmFormatModifier;
638    /* Android WSI image owns the memory */
639    img->wsi.memory = vn_device_memory_from_handle(memory);
640    img->wsi.memory_owned = true;
641    *out_img = img;
642 
643    return VK_SUCCESS;
644 
645 fail:
646    if (image != VK_NULL_HANDLE)
647       vn_DestroyImage(device, image, alloc);
648    if (memory != VK_NULL_HANDLE)
649       vn_FreeMemory(device, memory, alloc);
650    return vn_error(dev->instance, result);
651 }
652 
653 static VkResult
vn_android_get_ahb_format_properties(struct vn_device * dev,const struct AHardwareBuffer * ahb,VkAndroidHardwareBufferFormatPropertiesANDROID * out_props)654 vn_android_get_ahb_format_properties(
655    struct vn_device *dev,
656    const struct AHardwareBuffer *ahb,
657    VkAndroidHardwareBufferFormatPropertiesANDROID *out_props)
658 {
659    AHardwareBuffer_Desc desc;
660    VkFormat format;
661    struct vn_android_gralloc_buffer_properties buf_props;
662    VkDrmFormatModifierPropertiesEXT mod_props;
663 
664    AHardwareBuffer_describe(ahb, &desc);
665    if (!(desc.usage & (AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE |
666                        AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER |
667                        AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER))) {
668       vn_log(dev->instance,
669              "AHB usage(%" PRIu64 ") must include at least one GPU bit",
670              desc.usage);
671       return VK_ERROR_INVALID_EXTERNAL_HANDLE;
672    }
673 
674    /* Handle the special AHARDWAREBUFFER_FORMAT_BLOB for VkBuffer case. */
675    if (desc.format == AHARDWAREBUFFER_FORMAT_BLOB) {
676       out_props->format = VK_FORMAT_UNDEFINED;
677       return VK_SUCCESS;
678    }
679 
680    if (!vn_android_gralloc_get_buffer_properties(
681           AHardwareBuffer_getNativeHandle(ahb), &buf_props))
682       return VK_ERROR_INVALID_EXTERNAL_HANDLE;
683 
684    /* We implement AHB extension support with EXT_image_drm_format_modifier.
685     * It requires us to have a compatible VkFormat but not DRM formats. So if
686     * the ahb is not intended for backing a VkBuffer, error out early if the
687     * format is VK_FORMAT_UNDEFINED.
688     */
689    format = vn_android_drm_format_to_vk_format(buf_props.drm_fourcc);
690    if (format == VK_FORMAT_UNDEFINED) {
691       vn_log(dev->instance, "Unknown drm_fourcc(%u) from AHB format(0x%X)",
692              buf_props.drm_fourcc, desc.format);
693       return VK_ERROR_INVALID_EXTERNAL_HANDLE;
694    }
695 
696    VkResult result = vn_android_get_modifier_properties(
697       dev, format, buf_props.modifier, &dev->base.base.alloc, &mod_props);
698    if (result != VK_SUCCESS)
699       return result;
700 
701    if (mod_props.drmFormatModifierPlaneCount != buf_props.num_planes) {
702       vn_log(dev->instance,
703              "drmFormatModifierPlaneCount(%u) != buf_props.num_planes(%u) "
704              "for DRM format modifier(%" PRIu64 ")",
705              mod_props.drmFormatModifierPlaneCount, buf_props.num_planes,
706              buf_props.modifier);
707       return VK_ERROR_INVALID_EXTERNAL_HANDLE;
708    }
709 
710    /* The spec requires that formatFeatures must include at least one of
711     * VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT or
712     * VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT.
713     */
714    const VkFormatFeatureFlags format_features =
715       mod_props.drmFormatModifierTilingFeatures |
716       VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT;
717 
718    /* 11.2.7. Android Hardware Buffer External Memory
719     *
720     * Implementations may not always be able to determine the color model,
721     * numerical range, or chroma offsets of the image contents, so the values
722     * in VkAndroidHardwareBufferFormatPropertiesANDROID are only suggestions.
723     * Applications should treat these values as sensible defaults to use in the
724     * absence of more reliable information obtained through some other means.
725     */
726    const bool is_yuv = vn_android_drm_format_is_yuv(buf_props.drm_fourcc);
727    const VkSamplerYcbcrModelConversion model =
728       is_yuv ? VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601
729              : VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY;
730 
731    /* ANGLE expects VK_FORMAT_UNDEFINED with externalFormat resolved from
732     * AHARDWAREBUFFER_FORMAT_IMPLEMENTATION_DEFINED and any supported planar
733     * AHB formats. Venus supports below explicit ones:
734     * - AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420 (DRM_FORMAT_NV12)
735     * - AHARDWAREBUFFER_FORMAT_YV12 (DRM_FORMAT_YVU420)
736     */
737    if (desc.format == AHARDWAREBUFFER_FORMAT_IMPLEMENTATION_DEFINED || is_yuv)
738       format = VK_FORMAT_UNDEFINED;
739 
740    *out_props = (VkAndroidHardwareBufferFormatPropertiesANDROID) {
741       .sType = out_props->sType,
742       .pNext = out_props->pNext,
743       .format = format,
744       .externalFormat = buf_props.drm_fourcc,
745       .formatFeatures = format_features,
746       .samplerYcbcrConversionComponents = {
747          .r = VK_COMPONENT_SWIZZLE_IDENTITY,
748          .g = VK_COMPONENT_SWIZZLE_IDENTITY,
749          .b = VK_COMPONENT_SWIZZLE_IDENTITY,
750          .a = VK_COMPONENT_SWIZZLE_IDENTITY,
751       },
752       .suggestedYcbcrModel = model,
753       /* match EGL_YUV_NARROW_RANGE_EXT used in egl platform_android */
754       .suggestedYcbcrRange = VK_SAMPLER_YCBCR_RANGE_ITU_NARROW,
755       .suggestedXChromaOffset = VK_CHROMA_LOCATION_MIDPOINT,
756       .suggestedYChromaOffset = VK_CHROMA_LOCATION_MIDPOINT,
757    };
758 
759    return VK_SUCCESS;
760 }
761 
762 VkResult
vn_GetAndroidHardwareBufferPropertiesANDROID(VkDevice device,const struct AHardwareBuffer * buffer,VkAndroidHardwareBufferPropertiesANDROID * pProperties)763 vn_GetAndroidHardwareBufferPropertiesANDROID(
764    VkDevice device,
765    const struct AHardwareBuffer *buffer,
766    VkAndroidHardwareBufferPropertiesANDROID *pProperties)
767 {
768    VN_TRACE_FUNC();
769    struct vn_device *dev = vn_device_from_handle(device);
770    VkResult result = VK_SUCCESS;
771    int dma_buf_fd = -1;
772    uint64_t alloc_size = 0;
773    uint32_t mem_type_bits = 0;
774 
775    VkAndroidHardwareBufferFormatProperties2ANDROID *format_props2 =
776       vk_find_struct(pProperties->pNext,
777                      ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_2_ANDROID);
778    VkAndroidHardwareBufferFormatPropertiesANDROID *format_props =
779       vk_find_struct(pProperties->pNext,
780                      ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID);
781    if (format_props2 || format_props) {
782       VkAndroidHardwareBufferFormatPropertiesANDROID local_props = {
783          .sType =
784             VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID,
785       };
786       if (!format_props)
787          format_props = &local_props;
788 
789       result =
790          vn_android_get_ahb_format_properties(dev, buffer, format_props);
791       if (result != VK_SUCCESS)
792          return vn_error(dev->instance, result);
793 
794       if (format_props2) {
795          format_props2->format = format_props->format;
796          format_props2->externalFormat = format_props->externalFormat;
797          format_props2->formatFeatures =
798             (VkFormatFeatureFlags2)format_props->formatFeatures;
799          format_props2->samplerYcbcrConversionComponents =
800             format_props->samplerYcbcrConversionComponents;
801          format_props2->suggestedYcbcrModel =
802             format_props->suggestedYcbcrModel;
803          format_props2->suggestedYcbcrRange =
804             format_props->suggestedYcbcrRange;
805          format_props2->suggestedXChromaOffset =
806             format_props->suggestedXChromaOffset;
807          format_props2->suggestedYChromaOffset =
808             format_props->suggestedYChromaOffset;
809       }
810    }
811 
812    dma_buf_fd = vn_android_gralloc_get_dma_buf_fd(
813       AHardwareBuffer_getNativeHandle(buffer));
814    if (dma_buf_fd < 0)
815       return vn_error(dev->instance, VK_ERROR_INVALID_EXTERNAL_HANDLE);
816 
817    result = vn_get_memory_dma_buf_properties(dev, dma_buf_fd, &alloc_size,
818                                              &mem_type_bits);
819    if (result != VK_SUCCESS)
820       return vn_error(dev->instance, result);
821 
822    pProperties->allocationSize = alloc_size;
823    pProperties->memoryTypeBits = mem_type_bits;
824 
825    return VK_SUCCESS;
826 }
827 
828 static AHardwareBuffer *
vn_android_ahb_allocate(uint32_t width,uint32_t height,uint32_t layers,uint32_t format,uint64_t usage)829 vn_android_ahb_allocate(uint32_t width,
830                         uint32_t height,
831                         uint32_t layers,
832                         uint32_t format,
833                         uint64_t usage)
834 {
835    AHardwareBuffer *ahb = NULL;
836    AHardwareBuffer_Desc desc;
837    int ret = 0;
838 
839    memset(&desc, 0, sizeof(desc));
840    desc.width = width;
841    desc.height = height;
842    desc.layers = layers;
843    desc.format = format;
844    desc.usage = usage;
845 
846    ret = AHardwareBuffer_allocate(&desc, &ahb);
847    if (ret) {
848       /* We just log the error code here for now since the platform falsely
849        * maps all gralloc allocation failures to oom.
850        */
851       vn_log(NULL, "AHB alloc(w=%u,h=%u,l=%u,f=%u,u=%" PRIu64 ") failed(%d)",
852              width, height, layers, format, usage, ret);
853       return NULL;
854    }
855 
856    return ahb;
857 }
858 
859 bool
vn_android_get_drm_format_modifier_info(const VkPhysicalDeviceImageFormatInfo2 * format_info,VkPhysicalDeviceImageDrmFormatModifierInfoEXT * out_info)860 vn_android_get_drm_format_modifier_info(
861    const VkPhysicalDeviceImageFormatInfo2 *format_info,
862    VkPhysicalDeviceImageDrmFormatModifierInfoEXT *out_info)
863 {
864    /* To properly fill VkPhysicalDeviceImageDrmFormatModifierInfoEXT, we have
865     * to allocate an ahb to retrieve the drm format modifier. For the image
866     * sharing mode, we assume VK_SHARING_MODE_EXCLUSIVE for now.
867     */
868    AHardwareBuffer *ahb = NULL;
869    uint32_t format = 0;
870    uint64_t usage = 0;
871    struct vn_android_gralloc_buffer_properties buf_props;
872 
873    assert(format_info->tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT);
874 
875    format = vk_image_format_to_ahb_format(format_info->format);
876    if (!format)
877       return false;
878 
879    usage =
880       vk_image_usage_to_ahb_usage(format_info->flags, format_info->usage);
881    ahb = vn_android_ahb_allocate(16, 16, 1, format, usage);
882    if (!ahb)
883       return false;
884 
885    if (!vn_android_gralloc_get_buffer_properties(
886           AHardwareBuffer_getNativeHandle(ahb), &buf_props)) {
887       AHardwareBuffer_release(ahb);
888       return false;
889    }
890 
891    *out_info = (VkPhysicalDeviceImageDrmFormatModifierInfoEXT){
892       .sType =
893          VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT,
894       .pNext = NULL,
895       .drmFormatModifier = buf_props.modifier,
896       .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
897       .queueFamilyIndexCount = 0,
898       .pQueueFamilyIndices = NULL,
899    };
900 
901    AHardwareBuffer_release(ahb);
902    return true;
903 }
904 
905 VkResult
vn_android_device_import_ahb(struct vn_device * dev,struct vn_device_memory * mem,const struct VkMemoryDedicatedAllocateInfo * dedicated_info)906 vn_android_device_import_ahb(
907    struct vn_device *dev,
908    struct vn_device_memory *mem,
909    const struct VkMemoryDedicatedAllocateInfo *dedicated_info)
910 {
911    const struct vk_device_memory *mem_vk = &mem->base.base;
912    const native_handle_t *handle = NULL;
913    int dma_buf_fd = -1;
914    int dup_fd = -1;
915    uint64_t alloc_size = 0;
916    uint32_t mem_type_bits = 0;
917    uint32_t mem_type_index = mem_vk->memory_type_index;
918    bool force_unmappable = false;
919    VkResult result = VK_SUCCESS;
920 
921    handle = AHardwareBuffer_getNativeHandle(mem_vk->ahardware_buffer);
922    dma_buf_fd = vn_android_gralloc_get_dma_buf_fd(handle);
923    if (dma_buf_fd < 0)
924       return VK_ERROR_INVALID_EXTERNAL_HANDLE;
925 
926    result = vn_get_memory_dma_buf_properties(dev, dma_buf_fd, &alloc_size,
927                                              &mem_type_bits);
928    if (result != VK_SUCCESS)
929       return result;
930 
931    /* If ahb is for an image, finish the deferred image creation first */
932    if (dedicated_info && dedicated_info->image != VK_NULL_HANDLE) {
933       struct vn_image *img = vn_image_from_handle(dedicated_info->image);
934       struct vn_android_image_builder builder;
935 
936       result = vn_android_get_image_builder(dev, &img->deferred_info->create,
937                                             handle, &builder);
938       if (result != VK_SUCCESS)
939          return result;
940 
941       result = vn_image_init_deferred(dev, &builder.create, img);
942       if (result != VK_SUCCESS)
943          return result;
944 
945       const VkMemoryRequirements *mem_req =
946          &img->requirements[0].memory.memoryRequirements;
947       if (alloc_size < mem_req->size) {
948          vn_log(dev->instance,
949                 "alloc_size(%" PRIu64 ") mem_req->size(%" PRIu64 ")",
950                 alloc_size, mem_req->size);
951          return VK_ERROR_INVALID_EXTERNAL_HANDLE;
952       }
953 
954       alloc_size = mem_req->size;
955 
956       /* Per spec 11.2.3. Device Memory Allocation
957        *
958        * If the parameters define an export operation and the external handle
959        * type is
960        * VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID,
961        * implementations should not strictly follow memoryTypeIndex. Instead,
962        * they should modify the allocation internally to use the required
963        * memory type for the application’s given usage. This is because for an
964        * export operation, there is currently no way for the client to know
965        * the memory type index before allocating.
966        */
967       if (!(mem_vk->import_handle_type &
968             VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID)) {
969          if ((mem_type_bits & mem_req->memoryTypeBits) == 0) {
970             vn_log(dev->instance, "memoryTypeBits: img(0x%X) fd(0x%X)",
971                    mem_req->memoryTypeBits, mem_type_bits);
972             return VK_ERROR_INVALID_EXTERNAL_HANDLE;
973          }
974 
975          mem_type_index = ffs(mem_type_bits & mem_req->memoryTypeBits) - 1;
976       }
977 
978       /* XXX Workaround before we use cross-domain backend in minigbm. The
979        * blob_mem allocated from virgl backend can have a queried guest
980        * mappable size smaller than the size returned from image memory
981        * requirement.
982        */
983       force_unmappable = true;
984    }
985 
986    if (dedicated_info && dedicated_info->buffer != VK_NULL_HANDLE) {
987       struct vn_buffer *buf = vn_buffer_from_handle(dedicated_info->buffer);
988       const VkMemoryRequirements *mem_req =
989          &buf->requirements.memory.memoryRequirements;
990       if (alloc_size < mem_req->size) {
991          vn_log(dev->instance,
992                 "alloc_size(%" PRIu64 ") mem_req->size(%" PRIu64 ")",
993                 alloc_size, mem_req->size);
994          return VK_ERROR_INVALID_EXTERNAL_HANDLE;
995       }
996 
997       alloc_size = mem_req->size;
998 
999       assert((1 << mem_type_index) & mem_req->memoryTypeBits);
1000    }
1001 
1002    assert((1 << mem_type_index) & mem_type_bits);
1003 
1004    errno = 0;
1005    dup_fd = os_dupfd_cloexec(dma_buf_fd);
1006    if (dup_fd < 0)
1007       return (errno == EMFILE) ? VK_ERROR_TOO_MANY_OBJECTS
1008                                : VK_ERROR_OUT_OF_HOST_MEMORY;
1009 
1010    /* Spec requires AHB export info to be present, so we must strip it. In
1011     * practice, the AHB import path here only needs the main allocation info
1012     * and the dedicated_info.
1013     */
1014    VkMemoryDedicatedAllocateInfo local_dedicated_info;
1015    /* Override when dedicated_info exists and is not the tail struct. */
1016    if (dedicated_info && dedicated_info->pNext) {
1017       local_dedicated_info = *dedicated_info;
1018       local_dedicated_info.pNext = NULL;
1019       dedicated_info = &local_dedicated_info;
1020    }
1021    const VkMemoryAllocateInfo local_alloc_info = {
1022       .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
1023       .pNext = dedicated_info,
1024       .allocationSize = alloc_size,
1025       .memoryTypeIndex = mem_type_index,
1026    };
1027    result = vn_device_memory_import_dma_buf(dev, mem, &local_alloc_info,
1028                                             force_unmappable, dup_fd);
1029    if (result != VK_SUCCESS) {
1030       close(dup_fd);
1031       return result;
1032    }
1033 
1034    return VK_SUCCESS;
1035 }
1036 
1037 uint32_t
vn_android_get_ahb_buffer_memory_type_bits(struct vn_device * dev)1038 vn_android_get_ahb_buffer_memory_type_bits(struct vn_device *dev)
1039 {
1040    static const uint32_t format = AHARDWAREBUFFER_FORMAT_BLOB;
1041    /* ensure dma_buf_memory_type_bits covers host visible usage */
1042    static const uint64_t usage = AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER |
1043                                  AHARDWAREBUFFER_USAGE_CPU_READ_RARELY |
1044                                  AHARDWAREBUFFER_USAGE_CPU_WRITE_RARELY;
1045    AHardwareBuffer *ahb = vn_android_ahb_allocate(4096, 1, 1, format, usage);
1046    if (!ahb)
1047       return 0;
1048 
1049    int dma_buf_fd =
1050       vn_android_gralloc_get_dma_buf_fd(AHardwareBuffer_getNativeHandle(ahb));
1051    if (dma_buf_fd < 0) {
1052       AHardwareBuffer_release(ahb);
1053       return 0;
1054    }
1055 
1056    uint64_t alloc_size = 0;
1057    uint32_t mem_type_bits = 0;
1058    VkResult ret = vn_get_memory_dma_buf_properties(
1059       dev, dma_buf_fd, &alloc_size, &mem_type_bits);
1060    /* release ahb first as below no longer needs it */
1061    AHardwareBuffer_release(ahb);
1062 
1063    if (ret != VK_SUCCESS) {
1064       vn_log(dev->instance, "AHB buffer mem type bits query failed %d", ret);
1065       return 0;
1066    }
1067 
1068    return mem_type_bits;
1069 }
1070