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 void UNUSED
static_asserts(void)33 static_asserts(void)
34 {
35    STATIC_ASSERT(HWVULKAN_DISPATCH_MAGIC == ICD_LOADER_MAGIC);
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 =
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. */
55 static inline bool
unmask32(uint32_t *inout_mask, uint32_t test_mask)56 unmask32(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 
63 static int
tu_hal_open(const struct hw_module_t *mod, const char *id, struct hw_device_t **dev)64 tu_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 
93 static int
tu_hal_close(struct hw_device_t *dev)94 tu_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 */
101 static VkResult
tu_gralloc_info_other(struct tu_device *device, const VkNativeBufferANDROID *gralloc_info, int *dma_buf, uint64_t *modifier)102 tu_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 
159 static 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 
165 struct 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 
174 static VkResult
tu_gralloc_info_cros(struct tu_device *device, const VkNativeBufferANDROID *gralloc_info, int *dma_buf, uint64_t *modifier)175 tu_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 
196 VkResult
tu_gralloc_info(struct tu_device *device, const VkNativeBufferANDROID *gralloc_info, int *dma_buf, uint64_t *modifier)197 tu_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  */
246 VkResult
tu_import_memory_from_gralloc_handle(VkDevice device_h, int dma_buf, const VkAllocationCallbacks *alloc, VkImage image_h)247 tu_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 
298 fail_create_image:
299    tu_DestroyImage(device_h, image_h, alloc);
300 
301    return result;
302 }
303 
304 static VkResult
format_supported_with_usage(VkDevice device_h, VkFormat format, VkImageUsageFlags imageUsage)305 format_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 
352 static VkResult
setup_gralloc0_usage(struct tu_device *device, VkFormat format, VkImageUsageFlags imageUsage, int *grallocUsage)353 setup_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 
393 VKAPI_ATTR VkResult VKAPI_CALL
tu_GetSwapchainGrallocUsageANDROID(VkDevice device_h, VkFormat format, VkImageUsageFlags imageUsage, int *grallocUsage)394 tu_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
411 VKAPI_ATTR VkResult VKAPI_CALL
tu_GetSwapchainGrallocUsage2ANDROID(VkDevice device_h, VkFormat format, VkImageUsageFlags imageUsage, VkSwapchainImageUsageFlagsANDROID swapchainImageUsage, uint64_t *grallocConsumerUsage, uint64_t *grallocProducerUsage)412 tu_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