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