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