• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "v3dv_private.h"
25 #include <hardware/gralloc.h>
26 
27 #if ANDROID_API_LEVEL >= 26
28 #include <hardware/gralloc1.h>
29 #endif
30 
31 #include "drm-uapi/drm_fourcc.h"
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 "util/libsync.h"
39 #include "util/log.h"
40 #include "util/os_file.h"
41 
42 static int
43 v3dv_hal_open(const struct hw_module_t *mod,
44               const char *id,
45               struct hw_device_t **dev);
46 static int
47 v3dv_hal_close(struct hw_device_t *dev);
48 
49 static void UNUSED
static_asserts(void)50 static_asserts(void)
51 {
52    STATIC_ASSERT(HWVULKAN_DISPATCH_MAGIC == ICD_LOADER_MAGIC);
53 }
54 
55 PUBLIC struct hwvulkan_module_t HAL_MODULE_INFO_SYM = {
56    .common =
57      {
58        .tag = HARDWARE_MODULE_TAG,
59        .module_api_version = HWVULKAN_MODULE_API_VERSION_0_1,
60        .hal_api_version = HARDWARE_MAKE_API_VERSION(1, 0),
61        .id = HWVULKAN_HARDWARE_MODULE_ID,
62        .name = "Broadcom Vulkan HAL",
63        .author = "Mesa3D",
64        .methods =
65          &(hw_module_methods_t) {
66            .open = v3dv_hal_open,
67          },
68      },
69 };
70 
71 /* If any bits in test_mask are set, then unset them and return true. */
72 static inline bool
unmask32(uint32_t * inout_mask,uint32_t test_mask)73 unmask32(uint32_t *inout_mask, uint32_t test_mask)
74 {
75    uint32_t orig_mask = *inout_mask;
76    *inout_mask &= ~test_mask;
77    return *inout_mask != orig_mask;
78 }
79 
80 static int
v3dv_hal_open(const struct hw_module_t * mod,const char * id,struct hw_device_t ** dev)81 v3dv_hal_open(const struct hw_module_t *mod,
82               const char *id,
83               struct hw_device_t **dev)
84 {
85    assert(mod == &HAL_MODULE_INFO_SYM.common);
86    assert(strcmp(id, HWVULKAN_DEVICE_0) == 0);
87 
88    hwvulkan_device_t *hal_dev = malloc(sizeof(*hal_dev));
89    if (!hal_dev)
90       return -1;
91 
92    *hal_dev = (hwvulkan_device_t){
93       .common =
94         {
95           .tag = HARDWARE_DEVICE_TAG,
96           .version = HWVULKAN_DEVICE_API_VERSION_0_1,
97           .module = &HAL_MODULE_INFO_SYM.common,
98           .close = v3dv_hal_close,
99         },
100      .EnumerateInstanceExtensionProperties =
101         v3dv_EnumerateInstanceExtensionProperties,
102      .CreateInstance = v3dv_CreateInstance,
103      .GetInstanceProcAddr = v3dv_GetInstanceProcAddr,
104    };
105 
106    mesa_logi("v3dv: Warning: Android Vulkan implementation is experimental");
107 
108    *dev = &hal_dev->common;
109    return 0;
110 }
111 
112 static int
v3dv_hal_close(struct hw_device_t * dev)113 v3dv_hal_close(struct hw_device_t *dev)
114 {
115    /* hwvulkan.h claims that hw_device_t::close() is never called. */
116    return -1;
117 }
118 
119 static int
get_format_bpp(int native)120 get_format_bpp(int native)
121 {
122    int bpp;
123 
124    switch (native) {
125    case HAL_PIXEL_FORMAT_RGBA_FP16:
126       bpp = 8;
127       break;
128    case HAL_PIXEL_FORMAT_RGBA_8888:
129    case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
130    case HAL_PIXEL_FORMAT_RGBX_8888:
131    case HAL_PIXEL_FORMAT_BGRA_8888:
132    case HAL_PIXEL_FORMAT_RGBA_1010102:
133       bpp = 4;
134       break;
135    case HAL_PIXEL_FORMAT_RGB_565:
136       bpp = 2;
137       break;
138    default:
139       bpp = 0;
140       break;
141    }
142 
143    return bpp;
144 }
145 
146 /* get buffer info from VkNativeBufferANDROID */
147 static VkResult
v3dv_gralloc_info_other(struct v3dv_device * device,const VkNativeBufferANDROID * native_buffer,int * out_stride,uint64_t * out_modifier)148 v3dv_gralloc_info_other(struct v3dv_device *device,
149                         const VkNativeBufferANDROID *native_buffer,
150                         int *out_stride,
151                         uint64_t *out_modifier)
152 {
153    *out_stride = native_buffer->stride /*in pixels*/ *
154                  get_format_bpp(native_buffer->format);
155    *out_modifier = 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 
163 struct cros_gralloc0_buffer_info
164 {
165    uint32_t drm_fourcc;
166    int num_fds;
167    int fds[4];
168    uint64_t modifier;
169    int offset[4];
170    int stride[4];
171 };
172 
173 static VkResult
v3dv_gralloc_info_cros(struct v3dv_device * device,const VkNativeBufferANDROID * native_buffer,int * out_stride,uint64_t * out_modifier)174 v3dv_gralloc_info_cros(struct v3dv_device *device,
175                        const VkNativeBufferANDROID *native_buffer,
176                        int *out_stride,
177                        uint64_t *out_modifier)
178 {
179    const gralloc_module_t *gralloc = device->gralloc;
180    struct cros_gralloc0_buffer_info info;
181    int ret;
182 
183    ret = gralloc->perform(gralloc, CROS_GRALLOC_DRM_GET_BUFFER_INFO,
184                           native_buffer->handle, &info);
185    if (ret)
186       return VK_ERROR_INVALID_EXTERNAL_HANDLE;
187 
188    *out_stride = info.stride[0];
189    *out_modifier = info.modifier;
190 
191    return VK_SUCCESS;
192 }
193 
194 VkResult
v3dv_gralloc_info(struct v3dv_device * device,const VkNativeBufferANDROID * native_buffer,int * out_dmabuf,int * out_stride,int * out_size,uint64_t * out_modifier)195 v3dv_gralloc_info(struct v3dv_device *device,
196                   const VkNativeBufferANDROID *native_buffer,
197                   int *out_dmabuf,
198                   int *out_stride,
199                   int *out_size,
200                   uint64_t *out_modifier)
201 {
202    if (device->gralloc_type == V3DV_GRALLOC_UNKNOWN) {
203       /* get gralloc module for gralloc buffer info query */
204       int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID,
205                               (const hw_module_t **) &device->gralloc);
206 
207       device->gralloc_type = V3DV_GRALLOC_OTHER;
208 
209       if (err == 0) {
210          const gralloc_module_t *gralloc = device->gralloc;
211          mesa_logi("opened gralloc module name: %s", gralloc->common.name);
212 
213          if (strcmp(gralloc->common.name, cros_gralloc_module_name) == 0 &&
214              gralloc->perform) {
215             device->gralloc_type = V3DV_GRALLOC_CROS;
216          }
217       }
218    }
219 
220    *out_dmabuf = native_buffer->handle->data[0];
221    *out_size = lseek(*out_dmabuf, 0, SEEK_END);
222 
223    if (device->gralloc_type == V3DV_GRALLOC_CROS) {
224       return v3dv_gralloc_info_cros(device, native_buffer, out_stride,
225                                     out_modifier);
226    } else {
227       return v3dv_gralloc_info_other(device, native_buffer, out_stride,
228                                      out_modifier);
229    }
230 }
231 
232 VkResult
v3dv_import_native_buffer_fd(VkDevice device_h,int native_buffer_fd,const VkAllocationCallbacks * alloc,VkImage image_h)233 v3dv_import_native_buffer_fd(VkDevice device_h,
234                              int native_buffer_fd,
235                              const VkAllocationCallbacks *alloc,
236                              VkImage image_h)
237 {
238    struct v3dv_image *image = NULL;
239    VkResult result;
240 
241    image = v3dv_image_from_handle(image_h);
242 
243    VkDeviceMemory memory_h;
244 
245    const VkMemoryDedicatedAllocateInfo ded_alloc = {
246       .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
247       .pNext = NULL,
248       .buffer = VK_NULL_HANDLE,
249       .image = image_h
250    };
251 
252    const VkImportMemoryFdInfoKHR import_info = {
253       .sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR,
254       .pNext = &ded_alloc,
255       .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT,
256       .fd = os_dupfd_cloexec(native_buffer_fd),
257    };
258 
259    result =
260       v3dv_AllocateMemory(device_h,
261                           &(VkMemoryAllocateInfo) {
262                              .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
263                              .pNext = &import_info,
264                              .allocationSize = image->size,
265                              .memoryTypeIndex = 0,
266                           },
267                           alloc, &memory_h);
268 
269    if (result != VK_SUCCESS)
270       goto fail_create_image;
271 
272    VkBindImageMemoryInfo bind_info = {
273       .sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO,
274       .image = image_h,
275       .memory = memory_h,
276       .memoryOffset = 0,
277    };
278    v3dv_BindImageMemory2(device_h, 1, &bind_info);
279 
280    image->is_native_buffer_memory = true;
281 
282    return VK_SUCCESS;
283 
284 fail_create_image:
285    close(import_info.fd);
286 
287    return result;
288 }
289 
290 static VkResult
format_supported_with_usage(VkDevice device_h,VkFormat format,VkImageUsageFlags imageUsage)291 format_supported_with_usage(VkDevice device_h,
292                             VkFormat format,
293                             VkImageUsageFlags imageUsage)
294 {
295    V3DV_FROM_HANDLE(v3dv_device, device, device_h);
296    struct v3dv_physical_device *phys_dev = &device->instance->physicalDevice;
297    VkPhysicalDevice phys_dev_h = v3dv_physical_device_to_handle(phys_dev);
298    VkResult result;
299 
300    const VkPhysicalDeviceImageFormatInfo2 image_format_info = {
301       .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
302       .format = format,
303       .type = VK_IMAGE_TYPE_2D,
304       .tiling = VK_IMAGE_TILING_OPTIMAL,
305       .usage = imageUsage,
306    };
307 
308    VkImageFormatProperties2 image_format_props = {
309       .sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
310    };
311 
312    /* Check that requested format and usage are supported. */
313    result = v3dv_GetPhysicalDeviceImageFormatProperties2(
314       phys_dev_h, &image_format_info, &image_format_props);
315    if (result != VK_SUCCESS) {
316       return vk_errorf(device, result,
317                        "v3dv_GetPhysicalDeviceImageFormatProperties2 failed "
318                        "inside %s",
319                        __func__);
320    }
321 
322    return VK_SUCCESS;
323 }
324 
325 static VkResult
setup_gralloc0_usage(struct v3dv_device * device,VkFormat format,VkImageUsageFlags imageUsage,int * grallocUsage)326 setup_gralloc0_usage(struct v3dv_device *device,
327                      VkFormat format,
328                      VkImageUsageFlags imageUsage,
329                      int *grallocUsage)
330 {
331    if (unmask32(&imageUsage, VK_IMAGE_USAGE_TRANSFER_DST_BIT |
332                              VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT))
333       *grallocUsage |= GRALLOC_USAGE_HW_RENDER;
334 
335    if (unmask32(&imageUsage, VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
336                              VK_IMAGE_USAGE_SAMPLED_BIT |
337                              VK_IMAGE_USAGE_STORAGE_BIT |
338                              VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT))
339       *grallocUsage |= GRALLOC_USAGE_HW_TEXTURE;
340 
341    /* All VkImageUsageFlags not explicitly checked here are unsupported for
342     * gralloc swapchains.
343     */
344    if (imageUsage != 0) {
345       return vk_errorf(device, VK_ERROR_FORMAT_NOT_SUPPORTED,
346                        "unsupported VkImageUsageFlags(0x%x) for gralloc "
347                        "swapchain",
348                        imageUsage);
349    }
350 
351    /* Swapchain assumes direct displaying, therefore enable COMPOSER flag,
352     * In case format is not supported by display controller, gralloc will
353     * drop this flag and still allocate the buffer in VRAM
354     */
355    *grallocUsage |= GRALLOC_USAGE_HW_COMPOSER;
356 
357    if (*grallocUsage == 0)
358       return VK_ERROR_FORMAT_NOT_SUPPORTED;
359 
360    return VK_SUCCESS;
361 }
362 
363 VKAPI_ATTR VkResult VKAPI_CALL
v3dv_GetSwapchainGrallocUsageANDROID(VkDevice device_h,VkFormat format,VkImageUsageFlags imageUsage,int * grallocUsage)364 v3dv_GetSwapchainGrallocUsageANDROID(VkDevice device_h,
365                                      VkFormat format,
366                                      VkImageUsageFlags imageUsage,
367                                      int *grallocUsage)
368 {
369    V3DV_FROM_HANDLE(v3dv_device, device, device_h);
370    VkResult result;
371 
372    result = format_supported_with_usage(device_h, format, imageUsage);
373    if (result != VK_SUCCESS)
374       return result;
375 
376    *grallocUsage = 0;
377    return setup_gralloc0_usage(device, format, imageUsage, grallocUsage);
378 }
379 
380 #if ANDROID_API_LEVEL >= 26
381 VKAPI_ATTR VkResult VKAPI_CALL
v3dv_GetSwapchainGrallocUsage2ANDROID(VkDevice device_h,VkFormat format,VkImageUsageFlags imageUsage,VkSwapchainImageUsageFlagsANDROID swapchainImageUsage,uint64_t * grallocConsumerUsage,uint64_t * grallocProducerUsage)382 v3dv_GetSwapchainGrallocUsage2ANDROID(
383    VkDevice device_h,
384    VkFormat format,
385    VkImageUsageFlags imageUsage,
386    VkSwapchainImageUsageFlagsANDROID swapchainImageUsage,
387    uint64_t *grallocConsumerUsage,
388    uint64_t *grallocProducerUsage)
389 {
390    V3DV_FROM_HANDLE(v3dv_device, device, device_h);
391    VkResult result;
392 
393    *grallocConsumerUsage = 0;
394    *grallocProducerUsage = 0;
395    mesa_logd("%s: format=%d, usage=0x%x", __func__, format, imageUsage);
396 
397    result = format_supported_with_usage(device_h, format, imageUsage);
398    if (result != VK_SUCCESS)
399       return result;
400 
401    int32_t grallocUsage = 0;
402    result = setup_gralloc0_usage(device, format, imageUsage, &grallocUsage);
403    if (result != VK_SUCCESS)
404       return result;
405 
406    /* Setup gralloc1 usage flags from gralloc0 flags. */
407 
408    if (grallocUsage & GRALLOC_USAGE_HW_RENDER) {
409       *grallocProducerUsage |= GRALLOC1_PRODUCER_USAGE_GPU_RENDER_TARGET;
410    }
411 
412    if (grallocUsage & GRALLOC_USAGE_HW_TEXTURE) {
413       *grallocConsumerUsage |= GRALLOC1_CONSUMER_USAGE_GPU_TEXTURE;
414    }
415 
416    if (grallocUsage & GRALLOC_USAGE_HW_COMPOSER) {
417       /* GPU composing case */
418       *grallocConsumerUsage |= GRALLOC1_CONSUMER_USAGE_GPU_TEXTURE;
419       /* Hardware composing case */
420       *grallocConsumerUsage |= GRALLOC1_CONSUMER_USAGE_HWCOMPOSER;
421    }
422 
423    return VK_SUCCESS;
424 }
425 #endif
426