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