• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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