Path: blob/21.2-virgl/src/freedreno/vulkan/tu_android.c
4565 views
/*1* Copyright © 2017, Google Inc.2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* the rights to use, copy, modify, merge, publish, distribute, sublicense,7* and/or sell copies of the Software, and to permit persons to whom the8* Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice (including the next11* paragraph) shall be included in all copies or substantial portions of the12* Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL17* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER18* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING19* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER20* DEALINGS IN THE SOFTWARE.21*/2223#include "tu_private.h"2425#include <hardware/gralloc.h>2627#if ANDROID_API_LEVEL >= 2628#include <hardware/gralloc1.h>29#endif3031#include <hardware/hardware.h>32#include <hardware/hwvulkan.h>3334#include <vulkan/vk_android_native_buffer.h>35#include <vulkan/vk_icd.h>3637#include "drm-uapi/drm_fourcc.h"3839#include "util/libsync.h"40#include "util/os_file.h"4142static int43tu_hal_open(const struct hw_module_t *mod,44const char *id,45struct hw_device_t **dev);46static int47tu_hal_close(struct hw_device_t *dev);4849static void UNUSED50static_asserts(void)51{52STATIC_ASSERT(HWVULKAN_DISPATCH_MAGIC == ICD_LOADER_MAGIC);53}5455PUBLIC struct hwvulkan_module_t HAL_MODULE_INFO_SYM = {56.common =57{58.tag = HARDWARE_MODULE_TAG,59.module_api_version = HWVULKAN_MODULE_API_VERSION_0_1,60.hal_api_version = HARDWARE_MAKE_API_VERSION(1, 0),61.id = HWVULKAN_HARDWARE_MODULE_ID,62.name = "Turnip Vulkan HAL",63.author = "Google",64.methods =65&(hw_module_methods_t){66.open = tu_hal_open,67},68},69};7071/* If any bits in test_mask are set, then unset them and return true. */72static inline bool73unmask32(uint32_t *inout_mask, uint32_t test_mask)74{75uint32_t orig_mask = *inout_mask;76*inout_mask &= ~test_mask;77return *inout_mask != orig_mask;78}7980static int81tu_hal_open(const struct hw_module_t *mod,82const char *id,83struct hw_device_t **dev)84{85assert(mod == &HAL_MODULE_INFO_SYM.common);86assert(strcmp(id, HWVULKAN_DEVICE_0) == 0);8788hwvulkan_device_t *hal_dev = malloc(sizeof(*hal_dev));89if (!hal_dev)90return -1;9192*hal_dev = (hwvulkan_device_t){93.common =94{95.tag = HARDWARE_DEVICE_TAG,96.version = HWVULKAN_DEVICE_API_VERSION_0_1,97.module = &HAL_MODULE_INFO_SYM.common,98.close = tu_hal_close,99},100.EnumerateInstanceExtensionProperties =101tu_EnumerateInstanceExtensionProperties,102.CreateInstance = tu_CreateInstance,103.GetInstanceProcAddr = tu_GetInstanceProcAddr,104};105106*dev = &hal_dev->common;107return 0;108}109110static int111tu_hal_close(struct hw_device_t *dev)112{113/* hwvulkan.h claims that hw_device_t::close() is never called. */114return -1;115}116117/* get dma-buf and modifier from gralloc info */118static VkResult119tu_gralloc_info_other(struct tu_device *device,120const VkNativeBufferANDROID *gralloc_info,121int *dma_buf,122uint64_t *modifier)123124{125const uint32_t *handle_fds = (uint32_t *)gralloc_info->handle->data;126const uint32_t *handle_data = &handle_fds[gralloc_info->handle->numFds];127bool ubwc = false;128129if (gralloc_info->handle->numFds == 1) {130/* gbm_gralloc. TODO: modifiers support */131*dma_buf = handle_fds[0];132} else if (gralloc_info->handle->numFds == 2) {133/* Qualcomm gralloc, find it at:134*135* https://android.googlesource.com/platform/hardware/qcom/display/.136*137* The gralloc_info->handle is a pointer to a struct private_handle_t138* from your platform's gralloc. On msm8996 (a5xx) and newer grallocs139* that's libgralloc1/gr_priv_handle.h, while previously it was140* libgralloc/gralloc_priv.h.141*/142143if (gralloc_info->handle->numInts < 2) {144return vk_errorf(device->instance, VK_ERROR_INVALID_EXTERNAL_HANDLE,145"VkNativeBufferANDROID::handle::numInts is %d, "146"expected at least 2 for qcom gralloc",147gralloc_info->handle->numFds);148}149150uint32_t gmsm = ('g' << 24) | ('m' << 16) | ('s' << 8) | 'm';151if (handle_data[0] != gmsm) {152return vk_errorf(device->instance, VK_ERROR_INVALID_EXTERNAL_HANDLE,153"private_handle_t::magic is %x, expected %x",154handle_data[0], gmsm);155}156157/* This UBWC flag was introduced in a5xx. */158ubwc = handle_data[1] & 0x08000000;159160/* QCOM gralloc has two fds passed in: the actual GPU buffer, and a buffer161* of CPU-side metadata. I haven't found any need for the metadata buffer162* yet. See qdMetaData.h for what's in the metadata fd.163*/164*dma_buf = handle_fds[0];165} else {166return vk_errorf(device->instance, VK_ERROR_INVALID_EXTERNAL_HANDLE,167"VkNativeBufferANDROID::handle::numFds is %d, "168"expected 1 (gbm_gralloc) or 2 (qcom gralloc)",169gralloc_info->handle->numFds);170}171172*modifier = ubwc ? DRM_FORMAT_MOD_QCOM_COMPRESSED : DRM_FORMAT_MOD_LINEAR;173return VK_SUCCESS;174}175176static const char cros_gralloc_module_name[] = "CrOS Gralloc";177178#define CROS_GRALLOC_DRM_GET_BUFFER_INFO 4179#define CROS_GRALLOC_DRM_GET_USAGE 5180#define CROS_GRALLOC_DRM_GET_USAGE_FRONT_RENDERING_BIT 0x1181182struct cros_gralloc0_buffer_info {183uint32_t drm_fourcc;184int num_fds;185int fds[4];186uint64_t modifier;187int offset[4];188int stride[4];189};190191static VkResult192tu_gralloc_info_cros(struct tu_device *device,193const VkNativeBufferANDROID *gralloc_info,194int *dma_buf,195uint64_t *modifier)196197{198const gralloc_module_t *gralloc = device->gralloc;199struct cros_gralloc0_buffer_info info;200int ret;201202ret = gralloc->perform(gralloc, CROS_GRALLOC_DRM_GET_BUFFER_INFO,203gralloc_info->handle, &info);204if (ret)205return VK_ERROR_INVALID_EXTERNAL_HANDLE;206207*dma_buf = info.fds[0];208*modifier = info.modifier;209210return VK_SUCCESS;211}212213VkResult214tu_gralloc_info(struct tu_device *device,215const VkNativeBufferANDROID *gralloc_info,216int *dma_buf,217uint64_t *modifier)218219{220if (!device->gralloc) {221/* get gralloc module for gralloc buffer info query */222int ret = hw_get_module(GRALLOC_HARDWARE_MODULE_ID,223(const hw_module_t **)&device->gralloc);224225if (ret) {226/* This is *slightly* awkward, but if we are asked to import227* a gralloc handle, and there is no gralloc, it is some sort228* of invalid handle.229*/230return vk_startup_errorf(device->instance,231VK_ERROR_INVALID_EXTERNAL_HANDLE,232"Could not open gralloc\n");233}234235const gralloc_module_t *gralloc = device->gralloc;236237mesa_logi("opened gralloc module name: %s", gralloc->common.name);238239/* TODO not sure qcom gralloc module name, but we should check240* for it here and move the special gmsm handling out of241* tu_gralloc_info_other()242*/243if (!strcmp(gralloc->common.name, cros_gralloc_module_name) && gralloc->perform) {244device->gralloc_type = TU_GRALLOC_CROS;245} else {246device->gralloc_type = TU_GRALLOC_OTHER;247}248}249250if (device->gralloc_type == TU_GRALLOC_CROS) {251return tu_gralloc_info_cros(device, gralloc_info, dma_buf, modifier);252} else {253return tu_gralloc_info_other(device, gralloc_info, dma_buf, modifier);254}255}256257/**258* Creates the VkImage using the gralloc handle in *gralloc_info.259*260* We support two different grallocs here, gbm_gralloc, and the qcom gralloc261* used on Android phones.262*/263VkResult264tu_import_memory_from_gralloc_handle(VkDevice device_h,265int dma_buf,266const VkAllocationCallbacks *alloc,267VkImage image_h)268269{270struct tu_image *image = NULL;271VkResult result;272273image = tu_image_from_handle(image_h);274275VkDeviceMemory memory_h;276277const VkMemoryDedicatedAllocateInfo ded_alloc = {278.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,279.pNext = NULL,280.buffer = VK_NULL_HANDLE,281.image = image_h282};283284const VkImportMemoryFdInfoKHR import_info = {285.sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR,286.pNext = &ded_alloc,287.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT,288.fd = os_dupfd_cloexec(dma_buf),289};290291result =292tu_AllocateMemory(device_h,293&(VkMemoryAllocateInfo) {294.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,295.pNext = &import_info,296.allocationSize = image->total_size,297.memoryTypeIndex = 0,298},299alloc, &memory_h);300if (result != VK_SUCCESS)301goto fail_create_image;302303VkBindImageMemoryInfo bind_info = {304.sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO,305.image = image_h,306.memory = memory_h,307.memoryOffset = 0,308};309tu_BindImageMemory2(device_h, 1, &bind_info);310311image->owned_memory = memory_h;312313return VK_SUCCESS;314315fail_create_image:316tu_DestroyImage(device_h, image_h, alloc);317318return result;319}320321static VkResult322format_supported_with_usage(VkDevice device_h, VkFormat format,323VkImageUsageFlags imageUsage)324{325TU_FROM_HANDLE(tu_device, device, device_h);326struct tu_physical_device *phys_dev = device->physical_device;327VkPhysicalDevice phys_dev_h = tu_physical_device_to_handle(phys_dev);328VkResult result;329330/* WARNING: Android Nougat's libvulkan.so hardcodes the VkImageUsageFlags331* returned to applications via332* VkSurfaceCapabilitiesKHR::supportedUsageFlags.333* The relevant code in libvulkan/swapchain.cpp contains this fun comment:334*335* TODO(jessehall): I think these are right, but haven't thought hard336* about it. Do we need to query the driver for support of any of337* these?338*339* Any disagreement between this function and the hardcoded340* VkSurfaceCapabilitiesKHR:supportedUsageFlags causes tests341* dEQP-VK.wsi.android.swapchain.*.image_usage to fail.342*/343344const VkPhysicalDeviceImageFormatInfo2 image_format_info = {345.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,346.format = format,347.type = VK_IMAGE_TYPE_2D,348.tiling = VK_IMAGE_TILING_OPTIMAL,349.usage = imageUsage,350};351352VkImageFormatProperties2 image_format_props = {353.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,354};355356/* Check that requested format and usage are supported. */357result = tu_GetPhysicalDeviceImageFormatProperties2(358phys_dev_h, &image_format_info, &image_format_props);359if (result != VK_SUCCESS) {360return vk_errorf(device->instance, result,361"tu_GetPhysicalDeviceImageFormatProperties2 failed "362"inside %s",363__func__);364}365366return VK_SUCCESS;367}368369static VkResult370setup_gralloc0_usage(struct tu_device *device, VkFormat format,371VkImageUsageFlags imageUsage, int *grallocUsage)372{373if (unmask32(&imageUsage, VK_IMAGE_USAGE_TRANSFER_DST_BIT |374VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT))375*grallocUsage |= GRALLOC_USAGE_HW_RENDER;376377if (unmask32(&imageUsage, VK_IMAGE_USAGE_TRANSFER_SRC_BIT |378VK_IMAGE_USAGE_SAMPLED_BIT |379VK_IMAGE_USAGE_STORAGE_BIT |380VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT))381*grallocUsage |= GRALLOC_USAGE_HW_TEXTURE;382383/* All VkImageUsageFlags not explicitly checked here are unsupported for384* gralloc swapchains.385*/386if (imageUsage != 0) {387return vk_errorf(device->instance, VK_ERROR_FORMAT_NOT_SUPPORTED,388"unsupported VkImageUsageFlags(0x%x) for gralloc "389"swapchain",390imageUsage);391}392393/*394* FINISHME: Advertise all display-supported formats. Mostly395* DRM_FORMAT_ARGB2101010 and DRM_FORMAT_ABGR2101010, but need to check396* what we need for 30-bit colors.397*/398if (format == VK_FORMAT_B8G8R8A8_UNORM ||399format == VK_FORMAT_B5G6R5_UNORM_PACK16) {400*grallocUsage |= GRALLOC_USAGE_HW_FB | GRALLOC_USAGE_HW_COMPOSER |401GRALLOC_USAGE_EXTERNAL_DISP;402}403404if (*grallocUsage == 0)405return VK_ERROR_FORMAT_NOT_SUPPORTED;406407return VK_SUCCESS;408}409410VKAPI_ATTR VkResult VKAPI_CALL411tu_GetSwapchainGrallocUsageANDROID(VkDevice device_h,412VkFormat format,413VkImageUsageFlags imageUsage,414int *grallocUsage)415{416TU_FROM_HANDLE(tu_device, device, device_h);417VkResult result;418419result = format_supported_with_usage(device_h, format, imageUsage);420if (result != VK_SUCCESS)421return result;422423*grallocUsage = 0;424return setup_gralloc0_usage(device, format, imageUsage, grallocUsage);425}426427#if ANDROID_API_LEVEL >= 26428VKAPI_ATTR VkResult VKAPI_CALL429tu_GetSwapchainGrallocUsage2ANDROID(VkDevice device_h,430VkFormat format,431VkImageUsageFlags imageUsage,432VkSwapchainImageUsageFlagsANDROID swapchainImageUsage,433uint64_t *grallocConsumerUsage,434uint64_t *grallocProducerUsage)435{436TU_FROM_HANDLE(tu_device, device, device_h);437VkResult result;438439*grallocConsumerUsage = 0;440*grallocProducerUsage = 0;441mesa_logd("%s: format=%d, usage=0x%x", __func__, format, imageUsage);442443result = format_supported_with_usage(device_h, format, imageUsage);444if (result != VK_SUCCESS)445return result;446447int32_t grallocUsage = 0;448result = setup_gralloc0_usage(device, format, imageUsage, &grallocUsage);449if (result != VK_SUCCESS)450return result;451452/* Setup gralloc1 usage flags from gralloc0 flags. */453454if (grallocUsage & GRALLOC_USAGE_HW_RENDER) {455*grallocProducerUsage |= GRALLOC1_PRODUCER_USAGE_GPU_RENDER_TARGET;456*grallocConsumerUsage |= GRALLOC1_CONSUMER_USAGE_CLIENT_TARGET;457}458459if (grallocUsage & GRALLOC_USAGE_HW_TEXTURE) {460*grallocConsumerUsage |= GRALLOC1_CONSUMER_USAGE_GPU_TEXTURE;461}462463if (grallocUsage & (GRALLOC_USAGE_HW_FB |464GRALLOC_USAGE_HW_COMPOSER |465GRALLOC_USAGE_EXTERNAL_DISP)) {466*grallocProducerUsage |= GRALLOC1_PRODUCER_USAGE_GPU_RENDER_TARGET;467*grallocConsumerUsage |= GRALLOC1_CONSUMER_USAGE_HWCOMPOSER;468}469470return VK_SUCCESS;471}472#endif473474VKAPI_ATTR VkResult VKAPI_CALL475tu_AcquireImageANDROID(VkDevice device,476VkImage image_h,477int nativeFenceFd,478VkSemaphore semaphore,479VkFence fence)480{481VkResult semaphore_result = VK_SUCCESS, fence_result = VK_SUCCESS;482483if (semaphore != VK_NULL_HANDLE) {484int semaphore_fd =485nativeFenceFd >= 0 ? os_dupfd_cloexec(nativeFenceFd) : nativeFenceFd;486semaphore_result = tu_ImportSemaphoreFdKHR(487device, &(VkImportSemaphoreFdInfoKHR) {488.sType = VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR,489.flags = VK_SEMAPHORE_IMPORT_TEMPORARY_BIT,490.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT,491.fd = semaphore_fd,492.semaphore = semaphore,493});494}495496if (fence != VK_NULL_HANDLE) {497int fence_fd = nativeFenceFd >= 0 ? os_dupfd_cloexec(nativeFenceFd) : nativeFenceFd;498fence_result = tu_ImportFenceFdKHR(499device, &(VkImportFenceFdInfoKHR) {500.sType = VK_STRUCTURE_TYPE_IMPORT_FENCE_FD_INFO_KHR,501.flags = VK_FENCE_IMPORT_TEMPORARY_BIT,502.fd = fence_fd,503.fence = fence,504});505}506507close(nativeFenceFd);508509if (semaphore_result != VK_SUCCESS)510return semaphore_result;511return fence_result;512}513514515