From 5a595cd3af15b99d266d3fd5cba41da33f1888ac Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 5 Oct 2020 14:54:52 -0700 Subject: [PATCH] turnip: Detect Qualcomm gralloc and its UBWC flag on gralloc surfaces. And document where to find information on qcom gralloc's private handle layout. I chose not to #include the gralloc_priv because it seems that there's not much we need yet, and I'm hoping we can avoid the build-time dependency on the specific platform. Part-of: --- src/freedreno/vulkan/tu_android.c | 70 +++++++++++++++++++++++++++++++-------- 1 file changed, 57 insertions(+), 13 deletions(-) diff --git a/src/freedreno/vulkan/tu_android.c b/src/freedreno/vulkan/tu_android.c index 7203757..e04a2bb 100644 --- a/src/freedreno/vulkan/tu_android.c +++ b/src/freedreno/vulkan/tu_android.c @@ -109,6 +109,12 @@ tu_hal_close(struct hw_device_t *dev) return -1; } +/** + * Creates the VkImage using the gralloc handle in *gralloc_info. + * + * We support two different grallocs here, gbm_gralloc, and the qcom gralloc + * used on Android phones. + */ VkResult tu_image_from_gralloc(VkDevice device_h, const VkImageCreateInfo *base_info, @@ -121,24 +127,62 @@ tu_image_from_gralloc(VkDevice device_h, VkImage image_h = VK_NULL_HANDLE; struct tu_image *image = NULL; VkResult result; - - result = tu_image_create(device_h, base_info, alloc, &image_h, - DRM_FORMAT_MOD_LINEAR, NULL); - if (result != VK_SUCCESS) - return result; - - if (gralloc_info->handle->numFds != 1) { + bool ubwc = false; + + const uint32_t *handle_fds = (uint32_t *)gralloc_info->handle->data; + const uint32_t *handle_data = &handle_fds[gralloc_info->handle->numFds]; + int dma_buf; + + if (gralloc_info->handle->numFds == 1) { + /* gbm_gralloc. TODO: modifiers support */ + dma_buf = handle_fds[0]; + } else if (gralloc_info->handle->numFds == 2) { + /* Qualcomm gralloc, find it at: + * + * https://android.googlesource.com/platform/hardware/qcom/display/. + * + * The gralloc_info->handle is a pointer to a struct private_handle_t + * from your platform's gralloc. On msm8996 (a5xx) and newer grallocs + * that's libgralloc1/gr_priv_handle.h, while previously it was + * libgralloc/gralloc_priv.h. + */ + + if (gralloc_info->handle->numInts < 2) { + return vk_errorf(device->instance, VK_ERROR_INVALID_EXTERNAL_HANDLE, + "VkNativeBufferANDROID::handle::numInts is %d, " + "expected at least 2 for qcom gralloc", + gralloc_info->handle->numFds); + } + + uint32_t gmsm = ('g' << 24) | ('m' << 16) | ('s' << 8) | 'm'; + if (handle_data[0] != gmsm) { + return vk_errorf(device->instance, VK_ERROR_INVALID_EXTERNAL_HANDLE, + "private_handle_t::magic is %x, expected %x", + handle_data[0], gmsm); + } + + /* This UBWC flag was introduced in a5xx. */ + ubwc = handle_data[1] & 0x08000000; + + /* QCOM gralloc has two fds passed in: the actual GPU buffer, and a buffer + * of CPU-side metadata. I haven't found any need for the metadata buffer + * yet. See qdMetaData.h for what's in the metadata fd. + */ + dma_buf = handle_fds[0]; + } else { return vk_errorf(device->instance, VK_ERROR_INVALID_EXTERNAL_HANDLE, "VkNativeBufferANDROID::handle::numFds is %d, " - "expected 1", + "expected 1 (gbm_gralloc) or 2 (qcom gralloc)", gralloc_info->handle->numFds); } - /* Do not close the gralloc handle's dma_buf. The lifetime of the dma_buf - * must exceed that of the gralloc handle, and we do not own the gralloc - * handle. - */ - int dma_buf = gralloc_info->handle->data[0]; + result = tu_image_create(device_h, base_info, alloc, &image_h, + ubwc ? + DRM_FORMAT_MOD_QCOM_COMPRESSED : + DRM_FORMAT_MOD_LINEAR, + NULL); + if (result != VK_SUCCESS) + return result; image = tu_image_from_handle(image_h); -- 2.7.4