• 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,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 bool prefer_dedicated =
585       img->requirements[0].dedicated.prefersDedicatedAllocation == VK_TRUE;
586    const VkMemoryDedicatedAllocateInfo dedicated_info = {
587       .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
588       .image = vn_image_to_handle(img),
589    };
590    const VkImportMemoryFdInfoKHR import_fd_info = {
591       .sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR,
592       .pNext = prefer_dedicated ? &dedicated_info : NULL,
593       .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
594       .fd = dup_fd,
595    };
596    const VkMemoryAllocateInfo memory_info = {
597       .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
598       .pNext = &import_fd_info,
599       .allocationSize = mem_req->size,
600       .memoryTypeIndex = ffs(mem_type_bits) - 1,
601    };
602    VkDeviceMemory mem_handle;
603    result = vn_AllocateMemory(vn_device_to_handle(dev), &memory_info, alloc,
604                               &mem_handle);
605    if (result != VK_SUCCESS) {
606       vn_log(dev->instance, "anb: mem import failed");
607       /* only need to close the dup_fd on import failure */
608       close(dup_fd);
609       goto fail;
610    }
611 
612    /* Android WSI image owns the memory */
613    img->wsi.memory = vn_device_memory_from_handle(mem_handle);
614    img->wsi.memory_owned = true;
615    *out_img = img;
616 
617    return VK_SUCCESS;
618 
619 fail:
620    /* this handles mem free for owned import */
621    vn_DestroyImage(vn_device_to_handle(dev), vn_image_to_handle(img), alloc);
622    return result;
623 }
624 
625 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)626 vn_android_image_from_anb(struct vn_device *dev,
627                           const VkImageCreateInfo *create_info,
628                           const VkNativeBufferANDROID *anb_info,
629                           const VkAllocationCallbacks *alloc,
630                           struct vn_image **out_img)
631 {
632    struct vn_image *img = NULL;
633    VkResult result = vn_android_image_from_anb_internal(
634       dev, create_info, anb_info, alloc, &img);
635    if (result != VK_SUCCESS)
636       return result;
637 
638    const VkBindImageMemoryInfo bind_info = {
639       .sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO,
640       .image = vn_image_to_handle(img),
641       .memory = vn_device_memory_to_handle(img->wsi.memory),
642    };
643    result = vn_BindImageMemory2(vn_device_to_handle(dev), 1, &bind_info);
644    if (result != VK_SUCCESS) {
645       vn_DestroyImage(vn_device_to_handle(dev), vn_image_to_handle(img),
646                       alloc);
647       return result;
648    }
649 
650    *out_img = img;
651    return VK_SUCCESS;
652 }
653 
654 struct vn_device_memory *
vn_android_get_wsi_memory_from_bind_info(struct vn_device * dev,const VkBindImageMemoryInfo * bind_info)655 vn_android_get_wsi_memory_from_bind_info(
656    struct vn_device *dev, const VkBindImageMemoryInfo *bind_info)
657 {
658    const VkNativeBufferANDROID *anb_info =
659       vk_find_struct_const(bind_info->pNext, NATIVE_BUFFER_ANDROID);
660    assert(anb_info && anb_info->handle);
661 
662    struct vn_image *img = vn_image_from_handle(bind_info->image);
663    VkResult result = vn_android_image_from_anb_internal(
664       dev, &img->deferred_info->create, anb_info, &dev->base.base.alloc,
665       &img);
666    if (result != VK_SUCCESS)
667       return NULL;
668 
669    assert(img->wsi.memory_owned);
670    return img->wsi.memory;
671 }
672 
673 static VkResult
vn_android_get_ahb_format_properties(struct vn_device * dev,const struct AHardwareBuffer * ahb,VkAndroidHardwareBufferFormatPropertiesANDROID * out_props)674 vn_android_get_ahb_format_properties(
675    struct vn_device *dev,
676    const struct AHardwareBuffer *ahb,
677    VkAndroidHardwareBufferFormatPropertiesANDROID *out_props)
678 {
679    AHardwareBuffer_Desc desc;
680    VkFormat format;
681    struct vn_android_gralloc_buffer_properties buf_props;
682    VkDrmFormatModifierPropertiesEXT mod_props;
683 
684    AHardwareBuffer_describe(ahb, &desc);
685    if (!(desc.usage & (AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE |
686                        AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER |
687                        AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER))) {
688       vn_log(dev->instance,
689              "AHB usage(%" PRIu64 ") must include at least one GPU bit",
690              desc.usage);
691       return VK_ERROR_INVALID_EXTERNAL_HANDLE;
692    }
693 
694    /* Handle the special AHARDWAREBUFFER_FORMAT_BLOB for VkBuffer case. */
695    if (desc.format == AHARDWAREBUFFER_FORMAT_BLOB) {
696       out_props->format = VK_FORMAT_UNDEFINED;
697       return VK_SUCCESS;
698    }
699 
700    if (!vn_android_gralloc_get_buffer_properties(
701           AHardwareBuffer_getNativeHandle(ahb), &buf_props))
702       return VK_ERROR_INVALID_EXTERNAL_HANDLE;
703 
704    /* We implement AHB extension support with EXT_image_drm_format_modifier.
705     * It requires us to have a compatible VkFormat but not DRM formats. So if
706     * the ahb is not intended for backing a VkBuffer, error out early if the
707     * format is VK_FORMAT_UNDEFINED.
708     */
709    format = vn_android_drm_format_to_vk_format(buf_props.drm_fourcc);
710    if (format == VK_FORMAT_UNDEFINED) {
711       vn_log(dev->instance, "Unknown drm_fourcc(%u) from AHB format(0x%X)",
712              buf_props.drm_fourcc, desc.format);
713       return VK_ERROR_INVALID_EXTERNAL_HANDLE;
714    }
715 
716    VkResult result = vn_android_get_modifier_properties(
717       dev, format, buf_props.modifier, &mod_props);
718    if (result != VK_SUCCESS)
719       return result;
720 
721    if (mod_props.drmFormatModifierPlaneCount != buf_props.num_planes) {
722       vn_log(dev->instance,
723              "drmFormatModifierPlaneCount(%u) != buf_props.num_planes(%u) "
724              "for DRM format modifier(%" PRIu64 ")",
725              mod_props.drmFormatModifierPlaneCount, buf_props.num_planes,
726              buf_props.modifier);
727       return VK_ERROR_INVALID_EXTERNAL_HANDLE;
728    }
729 
730    /* The spec requires that formatFeatures must include at least one of
731     * VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT or
732     * VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT.
733     */
734    const VkFormatFeatureFlags format_features =
735       mod_props.drmFormatModifierTilingFeatures |
736       VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT;
737 
738    /* 11.2.7. Android Hardware Buffer External Memory
739     *
740     * Implementations may not always be able to determine the color model,
741     * numerical range, or chroma offsets of the image contents, so the values
742     * in VkAndroidHardwareBufferFormatPropertiesANDROID are only suggestions.
743     * Applications should treat these values as sensible defaults to use in the
744     * absence of more reliable information obtained through some other means.
745     */
746    const bool is_yuv = vn_android_drm_format_is_yuv(buf_props.drm_fourcc);
747    const VkSamplerYcbcrModelConversion model =
748       is_yuv ? VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601
749              : VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY;
750 
751    /* ANGLE expects VK_FORMAT_UNDEFINED with externalFormat resolved from
752     * AHARDWAREBUFFER_FORMAT_IMPLEMENTATION_DEFINED and any supported planar
753     * AHB formats. Venus supports below explicit ones:
754     * - AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420 (DRM_FORMAT_NV12)
755     * - AHARDWAREBUFFER_FORMAT_YV12 (DRM_FORMAT_YVU420)
756     */
757    if (desc.format == AHARDWAREBUFFER_FORMAT_IMPLEMENTATION_DEFINED || is_yuv)
758       format = VK_FORMAT_UNDEFINED;
759 
760    *out_props = (VkAndroidHardwareBufferFormatPropertiesANDROID) {
761       .sType = out_props->sType,
762       .pNext = out_props->pNext,
763       .format = format,
764       .externalFormat = buf_props.drm_fourcc,
765       .formatFeatures = format_features,
766       .samplerYcbcrConversionComponents = {
767          .r = VK_COMPONENT_SWIZZLE_IDENTITY,
768          .g = VK_COMPONENT_SWIZZLE_IDENTITY,
769          .b = VK_COMPONENT_SWIZZLE_IDENTITY,
770          .a = VK_COMPONENT_SWIZZLE_IDENTITY,
771       },
772       .suggestedYcbcrModel = model,
773       /* match EGL_YUV_NARROW_RANGE_EXT used in egl platform_android */
774       .suggestedYcbcrRange = VK_SAMPLER_YCBCR_RANGE_ITU_NARROW,
775       .suggestedXChromaOffset = VK_CHROMA_LOCATION_MIDPOINT,
776       .suggestedYChromaOffset = VK_CHROMA_LOCATION_MIDPOINT,
777    };
778 
779    return VK_SUCCESS;
780 }
781 
782 VkResult
vn_GetAndroidHardwareBufferPropertiesANDROID(VkDevice device,const struct AHardwareBuffer * buffer,VkAndroidHardwareBufferPropertiesANDROID * pProperties)783 vn_GetAndroidHardwareBufferPropertiesANDROID(
784    VkDevice device,
785    const struct AHardwareBuffer *buffer,
786    VkAndroidHardwareBufferPropertiesANDROID *pProperties)
787 {
788    VN_TRACE_FUNC();
789    struct vn_device *dev = vn_device_from_handle(device);
790    VkResult result = VK_SUCCESS;
791    int dma_buf_fd = -1;
792    uint64_t alloc_size = 0;
793    uint32_t mem_type_bits = 0;
794 
795    VkAndroidHardwareBufferFormatProperties2ANDROID *format_props2 =
796       vk_find_struct(pProperties->pNext,
797                      ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_2_ANDROID);
798    VkAndroidHardwareBufferFormatPropertiesANDROID *format_props =
799       vk_find_struct(pProperties->pNext,
800                      ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID);
801    if (format_props2 || format_props) {
802       VkAndroidHardwareBufferFormatPropertiesANDROID local_props = {
803          .sType =
804             VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID,
805       };
806       if (!format_props)
807          format_props = &local_props;
808 
809       result =
810          vn_android_get_ahb_format_properties(dev, buffer, format_props);
811       if (result != VK_SUCCESS)
812          return vn_error(dev->instance, result);
813 
814       if (format_props2) {
815          format_props2->format = format_props->format;
816          format_props2->externalFormat = format_props->externalFormat;
817          format_props2->formatFeatures =
818             (VkFormatFeatureFlags2)format_props->formatFeatures;
819          format_props2->samplerYcbcrConversionComponents =
820             format_props->samplerYcbcrConversionComponents;
821          format_props2->suggestedYcbcrModel =
822             format_props->suggestedYcbcrModel;
823          format_props2->suggestedYcbcrRange =
824             format_props->suggestedYcbcrRange;
825          format_props2->suggestedXChromaOffset =
826             format_props->suggestedXChromaOffset;
827          format_props2->suggestedYChromaOffset =
828             format_props->suggestedYChromaOffset;
829       }
830    }
831 
832    dma_buf_fd = vn_android_gralloc_get_dma_buf_fd(
833       AHardwareBuffer_getNativeHandle(buffer));
834    if (dma_buf_fd < 0)
835       return vn_error(dev->instance, VK_ERROR_INVALID_EXTERNAL_HANDLE);
836 
837    result = vn_get_memory_dma_buf_properties(dev, dma_buf_fd, &alloc_size,
838                                              &mem_type_bits);
839    if (result != VK_SUCCESS)
840       return vn_error(dev->instance, result);
841 
842    pProperties->allocationSize = alloc_size;
843    pProperties->memoryTypeBits = mem_type_bits;
844 
845    return VK_SUCCESS;
846 }
847 
848 static AHardwareBuffer *
vn_android_ahb_allocate(uint32_t width,uint32_t height,uint32_t layers,uint32_t format,uint64_t usage)849 vn_android_ahb_allocate(uint32_t width,
850                         uint32_t height,
851                         uint32_t layers,
852                         uint32_t format,
853                         uint64_t usage)
854 {
855    AHardwareBuffer *ahb = NULL;
856    AHardwareBuffer_Desc desc;
857    int ret = 0;
858 
859    memset(&desc, 0, sizeof(desc));
860    desc.width = width;
861    desc.height = height;
862    desc.layers = layers;
863    desc.format = format;
864    desc.usage = usage;
865 
866    ret = AHardwareBuffer_allocate(&desc, &ahb);
867    if (ret) {
868       /* We just log the error code here for now since the platform falsely
869        * maps all gralloc allocation failures to oom.
870        */
871       vn_log(NULL, "AHB alloc(w=%u,h=%u,l=%u,f=%u,u=%" PRIu64 ") failed(%d)",
872              width, height, layers, format, usage, ret);
873       return NULL;
874    }
875 
876    return ahb;
877 }
878 
879 bool
vn_android_get_drm_format_modifier_info(const VkPhysicalDeviceImageFormatInfo2 * format_info,VkPhysicalDeviceImageDrmFormatModifierInfoEXT * out_info)880 vn_android_get_drm_format_modifier_info(
881    const VkPhysicalDeviceImageFormatInfo2 *format_info,
882    VkPhysicalDeviceImageDrmFormatModifierInfoEXT *out_info)
883 {
884    /* To properly fill VkPhysicalDeviceImageDrmFormatModifierInfoEXT, we have
885     * to allocate an ahb to retrieve the drm format modifier. For the image
886     * sharing mode, we assume VK_SHARING_MODE_EXCLUSIVE for now.
887     */
888    AHardwareBuffer *ahb = NULL;
889    uint32_t format = 0;
890    uint64_t usage = 0;
891    struct vn_android_gralloc_buffer_properties buf_props;
892 
893    assert(format_info->tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT);
894 
895    format = vk_image_format_to_ahb_format(format_info->format);
896    if (!format)
897       return false;
898 
899    usage =
900       vk_image_usage_to_ahb_usage(format_info->flags, format_info->usage);
901    ahb = vn_android_ahb_allocate(16, 16, 1, format, usage);
902    if (!ahb)
903       return false;
904 
905    if (!vn_android_gralloc_get_buffer_properties(
906           AHardwareBuffer_getNativeHandle(ahb), &buf_props)) {
907       AHardwareBuffer_release(ahb);
908       return false;
909    }
910 
911    *out_info = (VkPhysicalDeviceImageDrmFormatModifierInfoEXT){
912       .sType =
913          VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT,
914       .pNext = NULL,
915       .drmFormatModifier = buf_props.modifier,
916       .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
917       .queueFamilyIndexCount = 0,
918       .pQueueFamilyIndices = NULL,
919    };
920 
921    AHardwareBuffer_release(ahb);
922    return true;
923 }
924 
925 VkResult
vn_android_device_import_ahb(struct vn_device * dev,struct vn_device_memory * mem,const struct VkMemoryDedicatedAllocateInfo * dedicated_info)926 vn_android_device_import_ahb(
927    struct vn_device *dev,
928    struct vn_device_memory *mem,
929    const struct VkMemoryDedicatedAllocateInfo *dedicated_info)
930 {
931    const struct vk_device_memory *mem_vk = &mem->base.base;
932    const native_handle_t *handle = NULL;
933    int dma_buf_fd = -1;
934    int dup_fd = -1;
935    uint64_t alloc_size = 0;
936    uint32_t mem_type_bits = 0;
937    uint32_t mem_type_index = mem_vk->memory_type_index;
938    bool force_unmappable = false;
939    VkResult result = VK_SUCCESS;
940 
941    handle = AHardwareBuffer_getNativeHandle(mem_vk->ahardware_buffer);
942    dma_buf_fd = vn_android_gralloc_get_dma_buf_fd(handle);
943    if (dma_buf_fd < 0)
944       return VK_ERROR_INVALID_EXTERNAL_HANDLE;
945 
946    result = vn_get_memory_dma_buf_properties(dev, dma_buf_fd, &alloc_size,
947                                              &mem_type_bits);
948    if (result != VK_SUCCESS)
949       return result;
950 
951    /* If ahb is for an image, finish the deferred image creation first */
952    if (dedicated_info && dedicated_info->image != VK_NULL_HANDLE) {
953       struct vn_image *img = vn_image_from_handle(dedicated_info->image);
954       struct vn_android_image_builder builder;
955 
956       result = vn_android_get_image_builder(dev, &img->deferred_info->create,
957                                             handle, &builder);
958       if (result != VK_SUCCESS)
959          return result;
960 
961       result = vn_image_init_deferred(dev, &builder.create, img);
962       if (result != VK_SUCCESS)
963          return result;
964 
965       const VkMemoryRequirements *mem_req =
966          &img->requirements[0].memory.memoryRequirements;
967       if (alloc_size < mem_req->size) {
968          vn_log(dev->instance,
969                 "alloc_size(%" PRIu64 ") mem_req->size(%" PRIu64 ")",
970                 alloc_size, mem_req->size);
971          return VK_ERROR_INVALID_EXTERNAL_HANDLE;
972       }
973 
974       alloc_size = mem_req->size;
975 
976       /* Per spec 11.2.3. Device Memory Allocation
977        *
978        * If the parameters define an export operation and the external handle
979        * type is
980        * VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID,
981        * implementations should not strictly follow memoryTypeIndex. Instead,
982        * they should modify the allocation internally to use the required
983        * memory type for the application’s given usage. This is because for an
984        * export operation, there is currently no way for the client to know
985        * the memory type index before allocating.
986        */
987       if (!(mem_vk->import_handle_type &
988             VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID)) {
989          if ((mem_type_bits & mem_req->memoryTypeBits) == 0) {
990             vn_log(dev->instance, "memoryTypeBits: img(0x%X) fd(0x%X)",
991                    mem_req->memoryTypeBits, mem_type_bits);
992             return VK_ERROR_INVALID_EXTERNAL_HANDLE;
993          }
994 
995          mem_type_index = ffs(mem_type_bits & mem_req->memoryTypeBits) - 1;
996       }
997 
998       /* XXX Workaround before we use cross-domain backend in minigbm. The
999        * blob_mem allocated from virgl backend can have a queried guest
1000        * mappable size smaller than the size returned from image memory
1001        * requirement.
1002        */
1003       force_unmappable = true;
1004    }
1005 
1006    if (dedicated_info && dedicated_info->buffer != VK_NULL_HANDLE) {
1007       struct vn_buffer *buf = vn_buffer_from_handle(dedicated_info->buffer);
1008       const VkMemoryRequirements *mem_req =
1009          &buf->requirements.memory.memoryRequirements;
1010       if (alloc_size < mem_req->size) {
1011          vn_log(dev->instance,
1012                 "alloc_size(%" PRIu64 ") mem_req->size(%" PRIu64 ")",
1013                 alloc_size, mem_req->size);
1014          return VK_ERROR_INVALID_EXTERNAL_HANDLE;
1015       }
1016 
1017       alloc_size = mem_req->size;
1018 
1019       assert((1 << mem_type_index) & mem_req->memoryTypeBits);
1020    }
1021 
1022    assert((1 << mem_type_index) & mem_type_bits);
1023 
1024    errno = 0;
1025    dup_fd = os_dupfd_cloexec(dma_buf_fd);
1026    if (dup_fd < 0)
1027       return (errno == EMFILE) ? VK_ERROR_TOO_MANY_OBJECTS
1028                                : VK_ERROR_OUT_OF_HOST_MEMORY;
1029 
1030    /* Spec requires AHB export info to be present, so we must strip it. In
1031     * practice, the AHB import path here only needs the main allocation info
1032     * and the dedicated_info.
1033     */
1034    VkMemoryDedicatedAllocateInfo local_dedicated_info;
1035    /* Override when dedicated_info exists and is not the tail struct. */
1036    if (dedicated_info && dedicated_info->pNext) {
1037       local_dedicated_info = *dedicated_info;
1038       local_dedicated_info.pNext = NULL;
1039       dedicated_info = &local_dedicated_info;
1040    }
1041    const VkMemoryAllocateInfo local_alloc_info = {
1042       .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
1043       .pNext = dedicated_info,
1044       .allocationSize = alloc_size,
1045       .memoryTypeIndex = mem_type_index,
1046    };
1047    result = vn_device_memory_import_dma_buf(dev, mem, &local_alloc_info,
1048                                             force_unmappable, dup_fd);
1049    if (result != VK_SUCCESS) {
1050       close(dup_fd);
1051       return result;
1052    }
1053 
1054    return VK_SUCCESS;
1055 }
1056 
1057 uint32_t
vn_android_get_ahb_buffer_memory_type_bits(struct vn_device * dev)1058 vn_android_get_ahb_buffer_memory_type_bits(struct vn_device *dev)
1059 {
1060    static const uint32_t format = AHARDWAREBUFFER_FORMAT_BLOB;
1061    /* ensure dma_buf_memory_type_bits covers host visible usage */
1062    static const uint64_t usage = AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER |
1063                                  AHARDWAREBUFFER_USAGE_CPU_READ_RARELY |
1064                                  AHARDWAREBUFFER_USAGE_CPU_WRITE_RARELY;
1065    AHardwareBuffer *ahb = vn_android_ahb_allocate(4096, 1, 1, format, usage);
1066    if (!ahb)
1067       return 0;
1068 
1069    int dma_buf_fd =
1070       vn_android_gralloc_get_dma_buf_fd(AHardwareBuffer_getNativeHandle(ahb));
1071    if (dma_buf_fd < 0) {
1072       AHardwareBuffer_release(ahb);
1073       return 0;
1074    }
1075 
1076    uint64_t alloc_size = 0;
1077    uint32_t mem_type_bits = 0;
1078    VkResult ret = vn_get_memory_dma_buf_properties(
1079       dev, dma_buf_fd, &alloc_size, &mem_type_bits);
1080    /* release ahb first as below no longer needs it */
1081    AHardwareBuffer_release(ahb);
1082 
1083    if (ret != VK_SUCCESS) {
1084       vn_log(dev->instance, "AHB buffer mem type bits query failed %d", ret);
1085       return 0;
1086    }
1087 
1088    return mem_type_bits;
1089 }
1090