tu_android.c revision 7ec681f3
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 43static int 44tu_hal_open(const struct hw_module_t *mod, 45 const char *id, 46 struct hw_device_t **dev); 47static int 48tu_hal_close(struct hw_device_t *dev); 49 50static void UNUSED 51static_asserts(void) 52{ 53 STATIC_ASSERT(HWVULKAN_DISPATCH_MAGIC == ICD_LOADER_MAGIC); 54} 55 56PUBLIC 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. */ 73static inline bool 74unmask32(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 81static int 82tu_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 111static int 112tu_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 */ 119static VkResult 120tu_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 177static 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 183struct 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 192static VkResult 193tu_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 214VkResult 215tu_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 */ 264VkResult 265tu_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 316fail_create_image: 317 tu_DestroyImage(device_h, image_h, alloc); 318 319 return result; 320} 321 322static VkResult 323format_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 370static VkResult 371setup_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 411VKAPI_ATTR VkResult VKAPI_CALL 412tu_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 429VKAPI_ATTR VkResult VKAPI_CALL 430tu_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 475VKAPI_ATTR VkResult VKAPI_CALL 476tu_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