Home | History | Annotate | Line # | Download | only in vulkan
      1 /*
      2  * Copyright  2017, Google Inc.
      3  *
      4  * Permission is hereby granted, free of charge, to any person obtaining a
      5  * copy of this software and associated documentation files (the "Software"),
      6  * to deal in the Software without restriction, including without limitation
      7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      8  * and/or sell copies of the Software, and to permit persons to whom the
      9  * Software is furnished to do so, subject to the following conditions:
     10  *
     11  * The above copyright notice and this permission notice (including the next
     12  * paragraph) shall be included in all copies or substantial portions of the
     13  * Software.
     14  *
     15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     21  * DEALINGS IN THE SOFTWARE.
     22  */
     23 
     24 #include "tu_private.h"
     25 
     26 #include <hardware/gralloc.h>
     27 
     28 #if ANDROID_API_LEVEL >= 26
     29 #include <hardware/gralloc1.h>
     30 #endif
     31 
     32 #include <hardware/hardware.h>
     33 #include <hardware/hwvulkan.h>
     34 
     35 #include <vulkan/vk_android_native_buffer.h>
     36 #include <vulkan/vk_icd.h>
     37 
     38 #include "drm-uapi/drm_fourcc.h"
     39 
     40 #include "util/libsync.h"
     41 #include "util/os_file.h"
     42 
     43 static int
     44 tu_hal_open(const struct hw_module_t *mod,
     45             const char *id,
     46             struct hw_device_t **dev);
     47 static int
     48 tu_hal_close(struct hw_device_t *dev);
     49 
     50 static void UNUSED
     51 static_asserts(void)
     52 {
     53    STATIC_ASSERT(HWVULKAN_DISPATCH_MAGIC == ICD_LOADER_MAGIC);
     54 }
     55 
     56 PUBLIC struct hwvulkan_module_t HAL_MODULE_INFO_SYM = {
     57    .common =
     58      {
     59        .tag = HARDWARE_MODULE_TAG,
     60        .module_api_version = HWVULKAN_MODULE_API_VERSION_0_1,
     61        .hal_api_version = HARDWARE_MAKE_API_VERSION(1, 0),
     62        .id = HWVULKAN_HARDWARE_MODULE_ID,
     63        .name = "Turnip Vulkan HAL",
     64        .author = "Google",
     65        .methods =
     66          &(hw_module_methods_t){
     67            .open = tu_hal_open,
     68          },
     69      },
     70 };
     71 
     72 /* If any bits in test_mask are set, then unset them and return true. */
     73 static inline bool
     74 unmask32(uint32_t *inout_mask, uint32_t test_mask)
     75 {
     76    uint32_t orig_mask = *inout_mask;
     77    *inout_mask &= ~test_mask;
     78    return *inout_mask != orig_mask;
     79 }
     80 
     81 static int
     82 tu_hal_open(const struct hw_module_t *mod,
     83             const char *id,
     84             struct hw_device_t **dev)
     85 {
     86    assert(mod == &HAL_MODULE_INFO_SYM.common);
     87    assert(strcmp(id, HWVULKAN_DEVICE_0) == 0);
     88 
     89    hwvulkan_device_t *hal_dev = malloc(sizeof(*hal_dev));
     90    if (!hal_dev)
     91       return -1;
     92 
     93    *hal_dev = (hwvulkan_device_t){
     94       .common =
     95         {
     96           .tag = HARDWARE_DEVICE_TAG,
     97           .version = HWVULKAN_DEVICE_API_VERSION_0_1,
     98           .module = &HAL_MODULE_INFO_SYM.common,
     99           .close = tu_hal_close,
    100         },
    101       .EnumerateInstanceExtensionProperties =
    102         tu_EnumerateInstanceExtensionProperties,
    103       .CreateInstance = tu_CreateInstance,
    104       .GetInstanceProcAddr = tu_GetInstanceProcAddr,
    105    };
    106 
    107    *dev = &hal_dev->common;
    108    return 0;
    109 }
    110 
    111 static int
    112 tu_hal_close(struct hw_device_t *dev)
    113 {
    114    /* hwvulkan.h claims that hw_device_t::close() is never called. */
    115    return -1;
    116 }
    117 
    118 /* get dma-buf and modifier from gralloc info */
    119 static VkResult
    120 tu_gralloc_info_other(struct tu_device *device,
    121                       const VkNativeBufferANDROID *gralloc_info,
    122                       int *dma_buf,
    123                       uint64_t *modifier)
    124 
    125 {
    126    const uint32_t *handle_fds = (uint32_t *)gralloc_info->handle->data;
    127    const uint32_t *handle_data = &handle_fds[gralloc_info->handle->numFds];
    128    bool ubwc = false;
    129 
    130    if (gralloc_info->handle->numFds == 1) {
    131       /* gbm_gralloc.  TODO: modifiers support */
    132       *dma_buf = handle_fds[0];
    133    } else if (gralloc_info->handle->numFds == 2) {
    134       /* Qualcomm gralloc, find it at:
    135        *
    136        * https://android.googlesource.com/platform/hardware/qcom/display/.
    137        *
    138        * The gralloc_info->handle is a pointer to a struct private_handle_t
    139        * from your platform's gralloc.  On msm8996 (a5xx) and newer grallocs
    140        * that's libgralloc1/gr_priv_handle.h, while previously it was
    141        * libgralloc/gralloc_priv.h.
    142        */
    143 
    144       if (gralloc_info->handle->numInts < 2) {
    145          return vk_errorf(device, VK_ERROR_INVALID_EXTERNAL_HANDLE,
    146                           "VkNativeBufferANDROID::handle::numInts is %d, "
    147                           "expected at least 2 for qcom gralloc",
    148                           gralloc_info->handle->numFds);
    149       }
    150 
    151       uint32_t gmsm = ('g' << 24) | ('m' << 16) | ('s' << 8) | 'm';
    152       if (handle_data[0] != gmsm) {
    153          return vk_errorf(device, VK_ERROR_INVALID_EXTERNAL_HANDLE,
    154                           "private_handle_t::magic is %x, expected %x",
    155                           handle_data[0], gmsm);
    156       }
    157 
    158       /* This UBWC flag was introduced in a5xx. */
    159       ubwc = handle_data[1] & 0x08000000;
    160 
    161       /* QCOM gralloc has two fds passed in: the actual GPU buffer, and a buffer
    162        * of CPU-side metadata.  I haven't found any need for the metadata buffer
    163        * yet.  See qdMetaData.h for what's in the metadata fd.
    164        */
    165       *dma_buf = handle_fds[0];
    166    } else {
    167       return vk_errorf(device, VK_ERROR_INVALID_EXTERNAL_HANDLE,
    168                        "VkNativeBufferANDROID::handle::numFds is %d, "
    169                        "expected 1 (gbm_gralloc) or 2 (qcom gralloc)",
    170                        gralloc_info->handle->numFds);
    171    }
    172 
    173    *modifier = ubwc ? DRM_FORMAT_MOD_QCOM_COMPRESSED : DRM_FORMAT_MOD_LINEAR;
    174    return VK_SUCCESS;
    175 }
    176 
    177 static const char cros_gralloc_module_name[] = "CrOS Gralloc";
    178 
    179 #define CROS_GRALLOC_DRM_GET_BUFFER_INFO 4
    180 #define CROS_GRALLOC_DRM_GET_USAGE 5
    181 #define CROS_GRALLOC_DRM_GET_USAGE_FRONT_RENDERING_BIT 0x1
    182 
    183 struct cros_gralloc0_buffer_info {
    184    uint32_t drm_fourcc;
    185    int num_fds;
    186    int fds[4];
    187    uint64_t modifier;
    188    int offset[4];
    189    int stride[4];
    190 };
    191 
    192 static VkResult
    193 tu_gralloc_info_cros(struct tu_device *device,
    194                      const VkNativeBufferANDROID *gralloc_info,
    195                      int *dma_buf,
    196                      uint64_t *modifier)
    197 
    198 {
    199    const gralloc_module_t *gralloc = device->gralloc;
    200    struct cros_gralloc0_buffer_info info;
    201    int ret;
    202 
    203    ret = gralloc->perform(gralloc, CROS_GRALLOC_DRM_GET_BUFFER_INFO,
    204                           gralloc_info->handle, &info);
    205    if (ret)
    206       return VK_ERROR_INVALID_EXTERNAL_HANDLE;
    207 
    208    *dma_buf = info.fds[0];
    209    *modifier = info.modifier;
    210 
    211    return VK_SUCCESS;
    212 }
    213 
    214 VkResult
    215 tu_gralloc_info(struct tu_device *device,
    216                 const VkNativeBufferANDROID *gralloc_info,
    217                 int *dma_buf,
    218                 uint64_t *modifier)
    219 
    220 {
    221    if (!device->gralloc) {
    222       /* get gralloc module for gralloc buffer info query */
    223       int ret = hw_get_module(GRALLOC_HARDWARE_MODULE_ID,
    224                               (const hw_module_t **)&device->gralloc);
    225 
    226       if (ret) {
    227          /* This is *slightly* awkward, but if we are asked to import
    228           * a gralloc handle, and there is no gralloc, it is some sort
    229           * of invalid handle.
    230           */
    231          return vk_startup_errorf(device->instance,
    232                                   VK_ERROR_INVALID_EXTERNAL_HANDLE,
    233                                   "Could not open gralloc\n");
    234       }
    235 
    236       const gralloc_module_t *gralloc = device->gralloc;
    237 
    238       mesa_logi("opened gralloc module name: %s", gralloc->common.name);
    239 
    240       /* TODO not sure qcom gralloc module name, but we should check
    241        * for it here and move the special gmsm handling out of
    242        * tu_gralloc_info_other()
    243        */
    244       if (!strcmp(gralloc->common.name, cros_gralloc_module_name) && gralloc->perform) {
    245          device->gralloc_type = TU_GRALLOC_CROS;
    246       } else {
    247          device->gralloc_type = TU_GRALLOC_OTHER;
    248       }
    249    }
    250 
    251    if (device->gralloc_type == TU_GRALLOC_CROS) {
    252       return tu_gralloc_info_cros(device, gralloc_info, dma_buf, modifier);
    253    } else {
    254       return tu_gralloc_info_other(device, gralloc_info, dma_buf, modifier);
    255    }
    256 }
    257 
    258 /**
    259  * Creates the VkImage using the gralloc handle in *gralloc_info.
    260  *
    261  * We support two different grallocs here, gbm_gralloc, and the qcom gralloc
    262  * used on Android phones.
    263  */
    264 VkResult
    265 tu_import_memory_from_gralloc_handle(VkDevice device_h,
    266                                      int dma_buf,
    267                                      const VkAllocationCallbacks *alloc,
    268                                      VkImage image_h)
    269 
    270 {
    271    struct tu_image *image = NULL;
    272    VkResult result;
    273 
    274    image = tu_image_from_handle(image_h);
    275 
    276    VkDeviceMemory memory_h;
    277 
    278    const VkMemoryDedicatedAllocateInfo ded_alloc = {
    279       .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
    280       .pNext = NULL,
    281       .buffer = VK_NULL_HANDLE,
    282       .image = image_h
    283    };
    284 
    285    const VkImportMemoryFdInfoKHR import_info = {
    286       .sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR,
    287       .pNext = &ded_alloc,
    288       .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT,
    289       .fd = os_dupfd_cloexec(dma_buf),
    290    };
    291 
    292    result =
    293       tu_AllocateMemory(device_h,
    294                         &(VkMemoryAllocateInfo) {
    295                            .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
    296                            .pNext = &import_info,
    297                            .allocationSize = image->total_size,
    298                            .memoryTypeIndex = 0,
    299                         },
    300                         alloc, &memory_h);
    301    if (result != VK_SUCCESS)
    302       goto fail_create_image;
    303 
    304    VkBindImageMemoryInfo bind_info = {
    305       .sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO,
    306       .image = image_h,
    307       .memory = memory_h,
    308       .memoryOffset = 0,
    309    };
    310    tu_BindImageMemory2(device_h, 1, &bind_info);
    311 
    312    image->owned_memory = memory_h;
    313 
    314    return VK_SUCCESS;
    315 
    316 fail_create_image:
    317    tu_DestroyImage(device_h, image_h, alloc);
    318 
    319    return result;
    320 }
    321 
    322 static VkResult
    323 format_supported_with_usage(VkDevice device_h, VkFormat format,
    324                             VkImageUsageFlags imageUsage)
    325 {
    326    TU_FROM_HANDLE(tu_device, device, device_h);
    327    struct tu_physical_device *phys_dev = device->physical_device;
    328    VkPhysicalDevice phys_dev_h = tu_physical_device_to_handle(phys_dev);
    329    VkResult result;
    330 
    331    /* WARNING: Android Nougat's libvulkan.so hardcodes the VkImageUsageFlags
    332     * returned to applications via
    333     * VkSurfaceCapabilitiesKHR::supportedUsageFlags.
    334     * The relevant code in libvulkan/swapchain.cpp contains this fun comment:
    335     *
    336     *     TODO(jessehall): I think these are right, but haven't thought hard
    337     *     about it. Do we need to query the driver for support of any of
    338     *     these?
    339     *
    340     * Any disagreement between this function and the hardcoded
    341     * VkSurfaceCapabilitiesKHR:supportedUsageFlags causes tests
    342     * dEQP-VK.wsi.android.swapchain.*.image_usage to fail.
    343     */
    344 
    345    const VkPhysicalDeviceImageFormatInfo2 image_format_info = {
    346       .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
    347       .format = format,
    348       .type = VK_IMAGE_TYPE_2D,
    349       .tiling = VK_IMAGE_TILING_OPTIMAL,
    350       .usage = imageUsage,
    351    };
    352 
    353    VkImageFormatProperties2 image_format_props = {
    354       .sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
    355    };
    356 
    357    /* Check that requested format and usage are supported. */
    358    result = tu_GetPhysicalDeviceImageFormatProperties2(
    359       phys_dev_h, &image_format_info, &image_format_props);
    360    if (result != VK_SUCCESS) {
    361       return vk_errorf(device, result,
    362                        "tu_GetPhysicalDeviceImageFormatProperties2 failed "
    363                        "inside %s",
    364                        __func__);
    365    }
    366 
    367    return VK_SUCCESS;
    368 }
    369 
    370 static VkResult
    371 setup_gralloc0_usage(struct tu_device *device, VkFormat format,
    372                      VkImageUsageFlags imageUsage, int *grallocUsage)
    373 {
    374    if (unmask32(&imageUsage, VK_IMAGE_USAGE_TRANSFER_DST_BIT |
    375                                 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT))
    376       *grallocUsage |= GRALLOC_USAGE_HW_RENDER;
    377 
    378    if (unmask32(&imageUsage, VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
    379                                 VK_IMAGE_USAGE_SAMPLED_BIT |
    380                                 VK_IMAGE_USAGE_STORAGE_BIT |
    381                                 VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT))
    382       *grallocUsage |= GRALLOC_USAGE_HW_TEXTURE;
    383 
    384    /* All VkImageUsageFlags not explicitly checked here are unsupported for
    385     * gralloc swapchains.
    386     */
    387    if (imageUsage != 0) {
    388       return vk_errorf(device, VK_ERROR_FORMAT_NOT_SUPPORTED,
    389                        "unsupported VkImageUsageFlags(0x%x) for gralloc "
    390                        "swapchain",
    391                        imageUsage);
    392    }
    393 
    394    /*
    395     * FINISHME: Advertise all display-supported formats. Mostly
    396     * DRM_FORMAT_ARGB2101010 and DRM_FORMAT_ABGR2101010, but need to check
    397     * what we need for 30-bit colors.
    398     */
    399    if (format == VK_FORMAT_B8G8R8A8_UNORM ||
    400        format == VK_FORMAT_B5G6R5_UNORM_PACK16) {
    401       *grallocUsage |= GRALLOC_USAGE_HW_FB | GRALLOC_USAGE_HW_COMPOSER |
    402                        GRALLOC_USAGE_EXTERNAL_DISP;
    403    }
    404 
    405    if (*grallocUsage == 0)
    406       return VK_ERROR_FORMAT_NOT_SUPPORTED;
    407 
    408    return VK_SUCCESS;
    409 }
    410 
    411 VKAPI_ATTR VkResult VKAPI_CALL
    412 tu_GetSwapchainGrallocUsageANDROID(VkDevice device_h,
    413                                    VkFormat format,
    414                                    VkImageUsageFlags imageUsage,
    415                                    int *grallocUsage)
    416 {
    417    TU_FROM_HANDLE(tu_device, device, device_h);
    418    VkResult result;
    419 
    420    result = format_supported_with_usage(device_h, format, imageUsage);
    421    if (result != VK_SUCCESS)
    422       return result;
    423 
    424    *grallocUsage = 0;
    425    return setup_gralloc0_usage(device, format, imageUsage, grallocUsage);
    426 }
    427 
    428 #if ANDROID_API_LEVEL >= 26
    429 VKAPI_ATTR VkResult VKAPI_CALL
    430 tu_GetSwapchainGrallocUsage2ANDROID(VkDevice device_h,
    431                                     VkFormat format,
    432                                     VkImageUsageFlags imageUsage,
    433                                     VkSwapchainImageUsageFlagsANDROID swapchainImageUsage,
    434                                     uint64_t *grallocConsumerUsage,
    435                                     uint64_t *grallocProducerUsage)
    436 {
    437    TU_FROM_HANDLE(tu_device, device, device_h);
    438    VkResult result;
    439 
    440    *grallocConsumerUsage = 0;
    441    *grallocProducerUsage = 0;
    442    mesa_logd("%s: format=%d, usage=0x%x", __func__, format, imageUsage);
    443 
    444    result = format_supported_with_usage(device_h, format, imageUsage);
    445    if (result != VK_SUCCESS)
    446       return result;
    447 
    448    int32_t grallocUsage = 0;
    449    result = setup_gralloc0_usage(device, format, imageUsage, &grallocUsage);
    450    if (result != VK_SUCCESS)
    451       return result;
    452 
    453    /* Setup gralloc1 usage flags from gralloc0 flags. */
    454 
    455    if (grallocUsage & GRALLOC_USAGE_HW_RENDER) {
    456       *grallocProducerUsage |= GRALLOC1_PRODUCER_USAGE_GPU_RENDER_TARGET;
    457       *grallocConsumerUsage |= GRALLOC1_CONSUMER_USAGE_CLIENT_TARGET;
    458    }
    459 
    460    if (grallocUsage & GRALLOC_USAGE_HW_TEXTURE) {
    461       *grallocConsumerUsage |= GRALLOC1_CONSUMER_USAGE_GPU_TEXTURE;
    462    }
    463 
    464    if (grallocUsage & (GRALLOC_USAGE_HW_FB |
    465                        GRALLOC_USAGE_HW_COMPOSER |
    466                        GRALLOC_USAGE_EXTERNAL_DISP)) {
    467       *grallocProducerUsage |= GRALLOC1_PRODUCER_USAGE_GPU_RENDER_TARGET;
    468       *grallocConsumerUsage |= GRALLOC1_CONSUMER_USAGE_HWCOMPOSER;
    469    }
    470 
    471    return VK_SUCCESS;
    472 }
    473 #endif
    474 
    475 VKAPI_ATTR VkResult VKAPI_CALL
    476 tu_AcquireImageANDROID(VkDevice device,
    477                        VkImage image_h,
    478                        int nativeFenceFd,
    479                        VkSemaphore semaphore,
    480                        VkFence fence)
    481 {
    482    VkResult semaphore_result = VK_SUCCESS, fence_result = VK_SUCCESS;
    483 
    484    if (semaphore != VK_NULL_HANDLE) {
    485       int semaphore_fd =
    486          nativeFenceFd >= 0 ? os_dupfd_cloexec(nativeFenceFd) : nativeFenceFd;
    487       semaphore_result = tu_ImportSemaphoreFdKHR(
    488          device, &(VkImportSemaphoreFdInfoKHR) {
    489                     .sType = VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR,
    490                     .flags = VK_SEMAPHORE_IMPORT_TEMPORARY_BIT,
    491                     .handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT,
    492                     .fd = semaphore_fd,
    493                     .semaphore = semaphore,
    494                  });
    495    }
    496 
    497    if (fence != VK_NULL_HANDLE) {
    498       int fence_fd = nativeFenceFd >= 0 ? os_dupfd_cloexec(nativeFenceFd) : nativeFenceFd;
    499       fence_result = tu_ImportFenceFdKHR(
    500          device, &(VkImportFenceFdInfoKHR) {
    501                     .sType = VK_STRUCTURE_TYPE_IMPORT_FENCE_FD_INFO_KHR,
    502                     .flags = VK_FENCE_IMPORT_TEMPORARY_BIT,
    503                     .fd = fence_fd,
    504                     .fence = fence,
    505                  });
    506    }
    507 
    508    close(nativeFenceFd);
    509 
    510    if (semaphore_result != VK_SUCCESS)
    511       return semaphore_result;
    512    return fence_result;
    513 }
    514