Home | History | Annotate | Line # | Download | only in vulkan
      1 /*
      2  * Copyright 2019 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_image.h"
     12 
     13 #include "venus-protocol/vn_protocol_driver_image.h"
     14 #include "venus-protocol/vn_protocol_driver_image_view.h"
     15 #include "venus-protocol/vn_protocol_driver_sampler.h"
     16 #include "venus-protocol/vn_protocol_driver_sampler_ycbcr_conversion.h"
     17 
     18 #include "vn_android.h"
     19 #include "vn_device.h"
     20 #include "vn_device_memory.h"
     21 #include "vn_wsi.h"
     22 
     23 static void
     24 vn_image_init_memory_requirements(struct vn_image *img,
     25                                   struct vn_device *dev,
     26                                   const VkImageCreateInfo *create_info)
     27 {
     28    uint32_t plane_count = 1;
     29    if (create_info->flags & VK_IMAGE_CREATE_DISJOINT_BIT) {
     30       /* TODO VkDrmFormatModifierPropertiesEXT::drmFormatModifierPlaneCount */
     31       assert(create_info->tiling != VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT);
     32 
     33       switch (create_info->format) {
     34       case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
     35       case VK_FORMAT_G8_B8R8_2PLANE_422_UNORM:
     36       case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:
     37       case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16:
     38       case VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16:
     39       case VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16:
     40       case VK_FORMAT_G16_B16R16_2PLANE_420_UNORM:
     41       case VK_FORMAT_G16_B16R16_2PLANE_422_UNORM:
     42          plane_count = 2;
     43          break;
     44       case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
     45       case VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM:
     46       case VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM:
     47       case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16:
     48       case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16:
     49       case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16:
     50       case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16:
     51       case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16:
     52       case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16:
     53       case VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM:
     54       case VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM:
     55       case VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM:
     56          plane_count = 3;
     57          break;
     58       default:
     59          plane_count = 1;
     60          break;
     61       }
     62    }
     63    assert(plane_count <= ARRAY_SIZE(img->memory_requirements));
     64 
     65    /* TODO add a per-device cache for the requirements */
     66    for (uint32_t i = 0; i < plane_count; i++) {
     67       img->memory_requirements[i].sType =
     68          VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2;
     69       img->memory_requirements[i].pNext = &img->dedicated_requirements[i];
     70       img->dedicated_requirements[i].sType =
     71          VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS;
     72       img->dedicated_requirements[i].pNext = NULL;
     73    }
     74 
     75    VkDevice dev_handle = vn_device_to_handle(dev);
     76    VkImage img_handle = vn_image_to_handle(img);
     77    if (plane_count == 1) {
     78       vn_call_vkGetImageMemoryRequirements2(
     79          dev->instance, dev_handle,
     80          &(VkImageMemoryRequirementsInfo2){
     81             .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2,
     82             .image = img_handle,
     83          },
     84          &img->memory_requirements[0]);
     85 
     86       /* AHB backed image requires dedicated allocation */
     87       if (img->deferred_info) {
     88          img->dedicated_requirements[0].prefersDedicatedAllocation = VK_TRUE;
     89          img->dedicated_requirements[0].requiresDedicatedAllocation = VK_TRUE;
     90       }
     91    } else {
     92       for (uint32_t i = 0; i < plane_count; i++) {
     93          vn_call_vkGetImageMemoryRequirements2(
     94             dev->instance, dev_handle,
     95             &(VkImageMemoryRequirementsInfo2){
     96                .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2,
     97                .pNext =
     98                   &(VkImagePlaneMemoryRequirementsInfo){
     99                      .sType =
    100                         VK_STRUCTURE_TYPE_IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO,
    101                      .planeAspect = VK_IMAGE_ASPECT_PLANE_0_BIT << i,
    102                   },
    103                .image = img_handle,
    104             },
    105             &img->memory_requirements[i]);
    106       }
    107    }
    108 }
    109 
    110 static VkResult
    111 vn_image_store_deferred_create_info(
    112    const VkImageCreateInfo *create_info,
    113    const VkAllocationCallbacks *alloc,
    114    struct vn_image_create_deferred_info **out_info)
    115 {
    116    struct vn_image_create_deferred_info *info = NULL;
    117    VkBaseOutStructure *dst = NULL;
    118 
    119    info = vk_zalloc(alloc, sizeof(*info), VN_DEFAULT_ALIGN,
    120                     VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
    121    if (!info)
    122       return VK_ERROR_OUT_OF_HOST_MEMORY;
    123 
    124    info->create = *create_info;
    125    dst = (void *)&info->create;
    126 
    127    vk_foreach_struct_const(src, create_info->pNext) {
    128       void *pnext = NULL;
    129       switch (src->sType) {
    130       case VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO:
    131          memcpy(&info->list, src, sizeof(info->list));
    132          pnext = &info->list;
    133          break;
    134       case VK_STRUCTURE_TYPE_IMAGE_STENCIL_USAGE_CREATE_INFO:
    135          memcpy(&info->stencil, src, sizeof(info->stencil));
    136          pnext = &info->stencil;
    137          break;
    138       default:
    139          break;
    140       }
    141 
    142       if (pnext) {
    143          dst->pNext = pnext;
    144          dst = pnext;
    145       }
    146    }
    147    dst->pNext = NULL;
    148 
    149    *out_info = info;
    150 
    151    return VK_SUCCESS;
    152 }
    153 
    154 static VkResult
    155 vn_image_init(struct vn_device *dev,
    156               const VkImageCreateInfo *create_info,
    157               struct vn_image *img)
    158 {
    159    VkDevice device = vn_device_to_handle(dev);
    160    VkImage image = vn_image_to_handle(img);
    161    VkResult result = VK_SUCCESS;
    162 
    163    img->sharing_mode = create_info->sharingMode;
    164 
    165    /* TODO async */
    166    result =
    167       vn_call_vkCreateImage(dev->instance, device, create_info, NULL, &image);
    168    if (result != VK_SUCCESS)
    169       return result;
    170 
    171    vn_image_init_memory_requirements(img, dev, create_info);
    172 
    173    return VK_SUCCESS;
    174 }
    175 
    176 VkResult
    177 vn_image_create(struct vn_device *dev,
    178                 const VkImageCreateInfo *create_info,
    179                 const VkAllocationCallbacks *alloc,
    180                 struct vn_image **out_img)
    181 {
    182    struct vn_image *img = NULL;
    183    VkResult result = VK_SUCCESS;
    184 
    185    img = vk_zalloc(alloc, sizeof(*img), VN_DEFAULT_ALIGN,
    186                    VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
    187    if (!img)
    188       return VK_ERROR_OUT_OF_HOST_MEMORY;
    189 
    190    vn_object_base_init(&img->base, VK_OBJECT_TYPE_IMAGE, &dev->base);
    191 
    192    result = vn_image_init(dev, create_info, img);
    193    if (result != VK_SUCCESS) {
    194       vn_object_base_fini(&img->base);
    195       vk_free(alloc, img);
    196       return result;
    197    }
    198 
    199    *out_img = img;
    200 
    201    return VK_SUCCESS;
    202 }
    203 
    204 VkResult
    205 vn_image_init_deferred(struct vn_device *dev,
    206                        const VkImageCreateInfo *create_info,
    207                        struct vn_image *img)
    208 {
    209    VkResult result = vn_image_init(dev, create_info, img);
    210    img->deferred_info->initialized = result == VK_SUCCESS;
    211    return result;
    212 }
    213 
    214 VkResult
    215 vn_image_create_deferred(struct vn_device *dev,
    216                          const VkImageCreateInfo *create_info,
    217                          const VkAllocationCallbacks *alloc,
    218                          struct vn_image **out_img)
    219 {
    220    struct vn_image *img = NULL;
    221    VkResult result = VK_SUCCESS;
    222 
    223    img = vk_zalloc(alloc, sizeof(*img), VN_DEFAULT_ALIGN,
    224                    VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
    225    if (!img)
    226       return VK_ERROR_OUT_OF_HOST_MEMORY;
    227 
    228    vn_object_base_init(&img->base, VK_OBJECT_TYPE_IMAGE, &dev->base);
    229 
    230    result = vn_image_store_deferred_create_info(create_info, alloc,
    231                                                 &img->deferred_info);
    232    if (result != VK_SUCCESS) {
    233       vn_object_base_fini(&img->base);
    234       vk_free(alloc, img);
    235       return result;
    236    }
    237 
    238    *out_img = img;
    239 
    240    return VK_SUCCESS;
    241 }
    242 
    243 /* image commands */
    244 
    245 VkResult
    246 vn_CreateImage(VkDevice device,
    247                const VkImageCreateInfo *pCreateInfo,
    248                const VkAllocationCallbacks *pAllocator,
    249                VkImage *pImage)
    250 {
    251    struct vn_device *dev = vn_device_from_handle(device);
    252    const VkAllocationCallbacks *alloc =
    253       pAllocator ? pAllocator : &dev->base.base.alloc;
    254    struct vn_image *img;
    255    VkResult result;
    256 
    257    const struct wsi_image_create_info *wsi_info =
    258       vn_wsi_find_wsi_image_create_info(pCreateInfo);
    259    const VkNativeBufferANDROID *anb_info =
    260       vn_android_find_native_buffer(pCreateInfo);
    261    const VkExternalMemoryImageCreateInfo *external_info =
    262       vk_find_struct_const(pCreateInfo->pNext,
    263                            EXTERNAL_MEMORY_IMAGE_CREATE_INFO);
    264    const bool ahb_info =
    265       external_info &&
    266       external_info->handleTypes ==
    267          VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID;
    268 
    269    if (wsi_info) {
    270       result = vn_wsi_create_image(dev, pCreateInfo, wsi_info, alloc, &img);
    271    } else if (anb_info) {
    272       result =
    273          vn_android_image_from_anb(dev, pCreateInfo, anb_info, alloc, &img);
    274    } else if (ahb_info) {
    275       result = vn_android_image_from_ahb(dev, pCreateInfo, alloc, &img);
    276    } else {
    277       result = vn_image_create(dev, pCreateInfo, alloc, &img);
    278    }
    279 
    280    if (result != VK_SUCCESS)
    281       return vn_error(dev->instance, result);
    282 
    283    *pImage = vn_image_to_handle(img);
    284    return VK_SUCCESS;
    285 }
    286 
    287 void
    288 vn_DestroyImage(VkDevice device,
    289                 VkImage image,
    290                 const VkAllocationCallbacks *pAllocator)
    291 {
    292    struct vn_device *dev = vn_device_from_handle(device);
    293    struct vn_image *img = vn_image_from_handle(image);
    294    const VkAllocationCallbacks *alloc =
    295       pAllocator ? pAllocator : &dev->base.base.alloc;
    296 
    297    if (!img)
    298       return;
    299 
    300    if (img->private_memory != VK_NULL_HANDLE)
    301       vn_FreeMemory(device, img->private_memory, pAllocator);
    302 
    303    /* must not ask renderer to destroy uninitialized deferred image */
    304    if (!img->deferred_info || img->deferred_info->initialized)
    305       vn_async_vkDestroyImage(dev->instance, device, image, NULL);
    306 
    307    if (img->deferred_info)
    308       vk_free(alloc, img->deferred_info);
    309 
    310    vn_object_base_fini(&img->base);
    311    vk_free(alloc, img);
    312 }
    313 
    314 void
    315 vn_GetImageMemoryRequirements(VkDevice device,
    316                               VkImage image,
    317                               VkMemoryRequirements *pMemoryRequirements)
    318 {
    319    const struct vn_image *img = vn_image_from_handle(image);
    320 
    321    *pMemoryRequirements = img->memory_requirements[0].memoryRequirements;
    322 }
    323 
    324 void
    325 vn_GetImageSparseMemoryRequirements(
    326    VkDevice device,
    327    VkImage image,
    328    uint32_t *pSparseMemoryRequirementCount,
    329    VkSparseImageMemoryRequirements *pSparseMemoryRequirements)
    330 {
    331    struct vn_device *dev = vn_device_from_handle(device);
    332 
    333    /* TODO per-device cache */
    334    vn_call_vkGetImageSparseMemoryRequirements(dev->instance, device, image,
    335                                               pSparseMemoryRequirementCount,
    336                                               pSparseMemoryRequirements);
    337 }
    338 
    339 void
    340 vn_GetImageMemoryRequirements2(VkDevice device,
    341                                const VkImageMemoryRequirementsInfo2 *pInfo,
    342                                VkMemoryRequirements2 *pMemoryRequirements)
    343 {
    344    const struct vn_image *img = vn_image_from_handle(pInfo->image);
    345    union {
    346       VkBaseOutStructure *pnext;
    347       VkMemoryRequirements2 *two;
    348       VkMemoryDedicatedRequirements *dedicated;
    349    } u = { .two = pMemoryRequirements };
    350 
    351    uint32_t plane = 0;
    352    const VkImagePlaneMemoryRequirementsInfo *plane_info =
    353       vk_find_struct_const(pInfo->pNext,
    354                            IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO);
    355    if (plane_info) {
    356       switch (plane_info->planeAspect) {
    357       case VK_IMAGE_ASPECT_PLANE_1_BIT:
    358          plane = 1;
    359          break;
    360       case VK_IMAGE_ASPECT_PLANE_2_BIT:
    361          plane = 2;
    362          break;
    363       default:
    364          plane = 0;
    365          break;
    366       }
    367    }
    368 
    369    while (u.pnext) {
    370       switch (u.pnext->sType) {
    371       case VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2:
    372          u.two->memoryRequirements =
    373             img->memory_requirements[plane].memoryRequirements;
    374          break;
    375       case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS:
    376          u.dedicated->prefersDedicatedAllocation =
    377             img->dedicated_requirements[plane].prefersDedicatedAllocation;
    378          u.dedicated->requiresDedicatedAllocation =
    379             img->dedicated_requirements[plane].requiresDedicatedAllocation;
    380          break;
    381       default:
    382          break;
    383       }
    384       u.pnext = u.pnext->pNext;
    385    }
    386 }
    387 
    388 void
    389 vn_GetImageSparseMemoryRequirements2(
    390    VkDevice device,
    391    const VkImageSparseMemoryRequirementsInfo2 *pInfo,
    392    uint32_t *pSparseMemoryRequirementCount,
    393    VkSparseImageMemoryRequirements2 *pSparseMemoryRequirements)
    394 {
    395    struct vn_device *dev = vn_device_from_handle(device);
    396 
    397    /* TODO per-device cache */
    398    vn_call_vkGetImageSparseMemoryRequirements2(dev->instance, device, pInfo,
    399                                                pSparseMemoryRequirementCount,
    400                                                pSparseMemoryRequirements);
    401 }
    402 
    403 VkResult
    404 vn_BindImageMemory(VkDevice device,
    405                    VkImage image,
    406                    VkDeviceMemory memory,
    407                    VkDeviceSize memoryOffset)
    408 {
    409    struct vn_device *dev = vn_device_from_handle(device);
    410    struct vn_device_memory *mem = vn_device_memory_from_handle(memory);
    411 
    412    if (mem->base_memory) {
    413       memory = vn_device_memory_to_handle(mem->base_memory);
    414       memoryOffset += mem->base_offset;
    415    }
    416 
    417    vn_async_vkBindImageMemory(dev->instance, device, image, memory,
    418                               memoryOffset);
    419 
    420    return VK_SUCCESS;
    421 }
    422 
    423 VkResult
    424 vn_BindImageMemory2(VkDevice device,
    425                     uint32_t bindInfoCount,
    426                     const VkBindImageMemoryInfo *pBindInfos)
    427 {
    428    struct vn_device *dev = vn_device_from_handle(device);
    429    const VkAllocationCallbacks *alloc = &dev->base.base.alloc;
    430 
    431    VkBindImageMemoryInfo *local_infos = NULL;
    432    for (uint32_t i = 0; i < bindInfoCount; i++) {
    433       const VkBindImageMemoryInfo *info = &pBindInfos[i];
    434       struct vn_device_memory *mem =
    435          vn_device_memory_from_handle(info->memory);
    436       /* TODO handle VkBindImageMemorySwapchainInfoKHR */
    437       if (!mem || !mem->base_memory)
    438          continue;
    439 
    440       if (!local_infos) {
    441          const size_t size = sizeof(*local_infos) * bindInfoCount;
    442          local_infos = vk_alloc(alloc, size, VN_DEFAULT_ALIGN,
    443                                 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
    444          if (!local_infos)
    445             return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
    446 
    447          memcpy(local_infos, pBindInfos, size);
    448       }
    449 
    450       local_infos[i].memory = vn_device_memory_to_handle(mem->base_memory);
    451       local_infos[i].memoryOffset += mem->base_offset;
    452    }
    453    if (local_infos)
    454       pBindInfos = local_infos;
    455 
    456    vn_async_vkBindImageMemory2(dev->instance, device, bindInfoCount,
    457                                pBindInfos);
    458 
    459    vk_free(alloc, local_infos);
    460 
    461    return VK_SUCCESS;
    462 }
    463 
    464 VkResult
    465 vn_GetImageDrmFormatModifierPropertiesEXT(
    466    VkDevice device,
    467    VkImage image,
    468    VkImageDrmFormatModifierPropertiesEXT *pProperties)
    469 {
    470    struct vn_device *dev = vn_device_from_handle(device);
    471 
    472    /* TODO local cache */
    473    return vn_call_vkGetImageDrmFormatModifierPropertiesEXT(
    474       dev->instance, device, image, pProperties);
    475 }
    476 
    477 void
    478 vn_GetImageSubresourceLayout(VkDevice device,
    479                              VkImage image,
    480                              const VkImageSubresource *pSubresource,
    481                              VkSubresourceLayout *pLayout)
    482 {
    483    struct vn_device *dev = vn_device_from_handle(device);
    484 
    485    /* TODO local cache */
    486    vn_call_vkGetImageSubresourceLayout(dev->instance, device, image,
    487                                        pSubresource, pLayout);
    488 }
    489 
    490 /* image view commands */
    491 
    492 VkResult
    493 vn_CreateImageView(VkDevice device,
    494                    const VkImageViewCreateInfo *pCreateInfo,
    495                    const VkAllocationCallbacks *pAllocator,
    496                    VkImageView *pView)
    497 {
    498    struct vn_device *dev = vn_device_from_handle(device);
    499    const VkAllocationCallbacks *alloc =
    500       pAllocator ? pAllocator : &dev->base.base.alloc;
    501 
    502    struct vn_image_view *view =
    503       vk_zalloc(alloc, sizeof(*view), VN_DEFAULT_ALIGN,
    504                 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
    505    if (!view)
    506       return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
    507 
    508    vn_object_base_init(&view->base, VK_OBJECT_TYPE_IMAGE_VIEW, &dev->base);
    509    view->image = vn_image_from_handle(pCreateInfo->image);
    510 
    511    VkImageView view_handle = vn_image_view_to_handle(view);
    512    vn_async_vkCreateImageView(dev->instance, device, pCreateInfo, NULL,
    513                               &view_handle);
    514 
    515    *pView = view_handle;
    516 
    517    return VK_SUCCESS;
    518 }
    519 
    520 void
    521 vn_DestroyImageView(VkDevice device,
    522                     VkImageView imageView,
    523                     const VkAllocationCallbacks *pAllocator)
    524 {
    525    struct vn_device *dev = vn_device_from_handle(device);
    526    struct vn_image_view *view = vn_image_view_from_handle(imageView);
    527    const VkAllocationCallbacks *alloc =
    528       pAllocator ? pAllocator : &dev->base.base.alloc;
    529 
    530    if (!view)
    531       return;
    532 
    533    vn_async_vkDestroyImageView(dev->instance, device, imageView, NULL);
    534 
    535    vn_object_base_fini(&view->base);
    536    vk_free(alloc, view);
    537 }
    538 
    539 /* sampler commands */
    540 
    541 VkResult
    542 vn_CreateSampler(VkDevice device,
    543                  const VkSamplerCreateInfo *pCreateInfo,
    544                  const VkAllocationCallbacks *pAllocator,
    545                  VkSampler *pSampler)
    546 {
    547    struct vn_device *dev = vn_device_from_handle(device);
    548    const VkAllocationCallbacks *alloc =
    549       pAllocator ? pAllocator : &dev->base.base.alloc;
    550 
    551    struct vn_sampler *sampler =
    552       vk_zalloc(alloc, sizeof(*sampler), VN_DEFAULT_ALIGN,
    553                 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
    554    if (!sampler)
    555       return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
    556 
    557    vn_object_base_init(&sampler->base, VK_OBJECT_TYPE_SAMPLER, &dev->base);
    558 
    559    VkSampler sampler_handle = vn_sampler_to_handle(sampler);
    560    vn_async_vkCreateSampler(dev->instance, device, pCreateInfo, NULL,
    561                             &sampler_handle);
    562 
    563    *pSampler = sampler_handle;
    564 
    565    return VK_SUCCESS;
    566 }
    567 
    568 void
    569 vn_DestroySampler(VkDevice device,
    570                   VkSampler _sampler,
    571                   const VkAllocationCallbacks *pAllocator)
    572 {
    573    struct vn_device *dev = vn_device_from_handle(device);
    574    struct vn_sampler *sampler = vn_sampler_from_handle(_sampler);
    575    const VkAllocationCallbacks *alloc =
    576       pAllocator ? pAllocator : &dev->base.base.alloc;
    577 
    578    if (!sampler)
    579       return;
    580 
    581    vn_async_vkDestroySampler(dev->instance, device, _sampler, NULL);
    582 
    583    vn_object_base_fini(&sampler->base);
    584    vk_free(alloc, sampler);
    585 }
    586 
    587 /* sampler YCbCr conversion commands */
    588 
    589 VkResult
    590 vn_CreateSamplerYcbcrConversion(
    591    VkDevice device,
    592    const VkSamplerYcbcrConversionCreateInfo *pCreateInfo,
    593    const VkAllocationCallbacks *pAllocator,
    594    VkSamplerYcbcrConversion *pYcbcrConversion)
    595 {
    596    struct vn_device *dev = vn_device_from_handle(device);
    597    const VkAllocationCallbacks *alloc =
    598       pAllocator ? pAllocator : &dev->base.base.alloc;
    599    const VkExternalFormatANDROID *ext_info =
    600       vk_find_struct_const(pCreateInfo->pNext, EXTERNAL_FORMAT_ANDROID);
    601 
    602    VkSamplerYcbcrConversionCreateInfo local_info;
    603    if (ext_info && ext_info->externalFormat) {
    604       assert(pCreateInfo->format == VK_FORMAT_UNDEFINED);
    605 
    606       local_info = *pCreateInfo;
    607       local_info.format =
    608          vn_android_drm_format_to_vk_format(ext_info->externalFormat);
    609       local_info.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
    610       local_info.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
    611       local_info.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
    612       local_info.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
    613       pCreateInfo = &local_info;
    614 
    615       assert(pCreateInfo->format != VK_FORMAT_UNDEFINED);
    616    }
    617 
    618    struct vn_sampler_ycbcr_conversion *conv =
    619       vk_zalloc(alloc, sizeof(*conv), VN_DEFAULT_ALIGN,
    620                 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
    621    if (!conv)
    622       return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
    623 
    624    vn_object_base_init(&conv->base, VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION,
    625                        &dev->base);
    626 
    627    VkSamplerYcbcrConversion conv_handle =
    628       vn_sampler_ycbcr_conversion_to_handle(conv);
    629    vn_async_vkCreateSamplerYcbcrConversion(dev->instance, device, pCreateInfo,
    630                                            NULL, &conv_handle);
    631 
    632    *pYcbcrConversion = conv_handle;
    633 
    634    return VK_SUCCESS;
    635 }
    636 
    637 void
    638 vn_DestroySamplerYcbcrConversion(VkDevice device,
    639                                  VkSamplerYcbcrConversion ycbcrConversion,
    640                                  const VkAllocationCallbacks *pAllocator)
    641 {
    642    struct vn_device *dev = vn_device_from_handle(device);
    643    struct vn_sampler_ycbcr_conversion *conv =
    644       vn_sampler_ycbcr_conversion_from_handle(ycbcrConversion);
    645    const VkAllocationCallbacks *alloc =
    646       pAllocator ? pAllocator : &dev->base.base.alloc;
    647 
    648    if (!conv)
    649       return;
    650 
    651    vn_async_vkDestroySamplerYcbcrConversion(dev->instance, device,
    652                                             ycbcrConversion, NULL);
    653 
    654    vn_object_base_fini(&conv->base);
    655    vk_free(alloc, conv);
    656 }
    657