1 /*
2 * Copyright © 2024, 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 DEALINGS
21 * IN THE SOFTWARE.
22 */
23
24 #include <lvp_private.h>
25 #include <hardware/gralloc.h>
26
27 #if ANDROID_API_LEVEL >= 26
28 #include <hardware/gralloc1.h>
29 #endif
30
31 #include <hardware/hardware.h>
32 #include <hardware/hwvulkan.h>
33 #include <vulkan/vk_android_native_buffer.h>
34 #include <vulkan/vk_icd.h>
35
36 #include "util/libsync.h"
37 #include "util/os_file.h"
38 #include "util/libsync.h"
39
40 #include "vk_fence.h"
41 #include "vk_semaphore.h"
42 #include "vk_android.h"
43
44 static int
45 lvp_hal_open(const struct hw_module_t *mod,
46 const char *id,
47 struct hw_device_t **dev);
48 static int
49 lvp_hal_close(struct hw_device_t *dev);
50
51 static_assert(HWVULKAN_DISPATCH_MAGIC == ICD_LOADER_MAGIC, "");
52
53 struct hw_module_methods_t HAL_MODULE_METHODS = {
54 .open = lvp_hal_open,
55 };
56
57 PUBLIC struct hwvulkan_module_t HAL_MODULE_INFO_SYM = {
58 .common =
59 {
60 .tag = HARDWARE_MODULE_TAG,
61 .module_api_version = HWVULKAN_MODULE_API_VERSION_0_1,
62 .hal_api_version = HARDWARE_MAKE_API_VERSION(1, 0),
63 .id = HWVULKAN_HARDWARE_MODULE_ID,
64 .name = "Lavapipe Vulkan HAL",
65 .author = "Mesa3D",
66 .methods = &HAL_MODULE_METHODS,
67 },
68 };
69
70 static int
lvp_hal_open(const struct hw_module_t * mod,const char * id,struct hw_device_t ** dev)71 lvp_hal_open(const struct hw_module_t *mod,
72 const char *id,
73 struct hw_device_t **dev)
74 {
75 assert(mod == &HAL_MODULE_INFO_SYM.common);
76 assert(strcmp(id, HWVULKAN_DEVICE_0) == 0);
77
78 hwvulkan_device_t *hal_dev = (hwvulkan_device_t *) malloc(sizeof(*hal_dev));
79 if (!hal_dev)
80 return -1;
81
82 *hal_dev = (hwvulkan_device_t){
83 .common =
84 {
85 .tag = HARDWARE_DEVICE_TAG,
86 .version = HWVULKAN_DEVICE_API_VERSION_0_1,
87 .module = &HAL_MODULE_INFO_SYM.common,
88 .close = lvp_hal_close,
89 },
90 .EnumerateInstanceExtensionProperties =
91 lvp_EnumerateInstanceExtensionProperties,
92 .CreateInstance = lvp_CreateInstance,
93 .GetInstanceProcAddr = lvp_GetInstanceProcAddr,
94 };
95
96 *dev = &hal_dev->common;
97 return 0;
98 }
99
100 static int
lvp_hal_close(struct hw_device_t * dev)101 lvp_hal_close(struct hw_device_t *dev)
102 {
103 /* hwvulkan.h claims that hw_device_t::close() is never called. */
104 return -1;
105 }
106
107 VKAPI_ATTR VkResult VKAPI_CALL
lvp_GetSwapchainGrallocUsageANDROID(VkDevice device_h,VkFormat format,VkImageUsageFlags imageUsage,int * grallocUsage)108 lvp_GetSwapchainGrallocUsageANDROID(VkDevice device_h,
109 VkFormat format,
110 VkImageUsageFlags imageUsage,
111 int *grallocUsage)
112 {
113 *grallocUsage = GRALLOC_USAGE_SW_WRITE_OFTEN | GRALLOC_USAGE_SW_READ_OFTEN;
114
115 return VK_SUCCESS;
116 }
117
118 #if ANDROID_API_LEVEL >= 26
119 VKAPI_ATTR VkResult VKAPI_CALL
lvp_GetSwapchainGrallocUsage2ANDROID(VkDevice device_h,VkFormat format,VkImageUsageFlags imageUsage,VkSwapchainImageUsageFlagsANDROID swapchainImageUsage,uint64_t * grallocConsumerUsage,uint64_t * grallocProducerUsage)120 lvp_GetSwapchainGrallocUsage2ANDROID(VkDevice device_h,
121 VkFormat format,
122 VkImageUsageFlags imageUsage,
123 VkSwapchainImageUsageFlagsANDROID swapchainImageUsage,
124 uint64_t *grallocConsumerUsage,
125 uint64_t *grallocProducerUsage)
126 {
127 *grallocConsumerUsage = 0;
128 *grallocProducerUsage = GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN | GRALLOC1_PRODUCER_USAGE_CPU_READ_OFTEN;
129
130 return VK_SUCCESS;
131 }
132 #endif
133
134 VKAPI_ATTR VkResult VKAPI_CALL
lvp_AcquireImageANDROID(VkDevice _device,VkImage image,int nativeFenceFd,VkSemaphore semaphore,VkFence fence)135 lvp_AcquireImageANDROID(VkDevice _device,
136 VkImage image,
137 int nativeFenceFd,
138 VkSemaphore semaphore,
139 VkFence fence)
140 {
141 VK_FROM_HANDLE(vk_device, vk_device, _device);
142 VkResult result = VK_SUCCESS;
143
144 if(nativeFenceFd >= 0)
145 {
146 sync_wait(nativeFenceFd, -1);
147 close(nativeFenceFd);
148 }
149
150 if(fence != VK_NULL_HANDLE)
151 {
152 VK_FROM_HANDLE(vk_fence, vk_fence, fence);
153 result = vk_sync_signal(vk_device, &vk_fence->permanent, 0);
154 }
155
156 if(result == VK_SUCCESS && semaphore != VK_NULL_HANDLE)
157 {
158 VK_FROM_HANDLE(vk_semaphore, vk_semaphore, semaphore);
159 result = vk_sync_signal(vk_device, &vk_semaphore->permanent, 0);
160 }
161
162 return result;
163 }
164
165 VKAPI_ATTR VkResult VKAPI_CALL
lvp_QueueSignalReleaseImageANDROID(VkQueue _queue,uint32_t waitSemaphoreCount,const VkSemaphore * pWaitSemaphores,VkImage image,int * pNativeFenceFd)166 lvp_QueueSignalReleaseImageANDROID(VkQueue _queue,
167 uint32_t waitSemaphoreCount,
168 const VkSemaphore *pWaitSemaphores,
169 VkImage image,
170 int *pNativeFenceFd)
171 {
172 VK_FROM_HANDLE(vk_queue, queue, _queue);
173 struct vk_device *device = queue->base.device;
174
175 device->dispatch_table.QueueWaitIdle(_queue);
176
177 *pNativeFenceFd = -1;
178
179 return VK_SUCCESS;
180 }
181
182 VkResult
lvp_import_ahb_memory(struct lvp_device * device,struct lvp_device_memory * mem,const VkImportAndroidHardwareBufferInfoANDROID * info)183 lvp_import_ahb_memory(struct lvp_device *device, struct lvp_device_memory *mem,
184 const VkImportAndroidHardwareBufferInfoANDROID *info)
185 {
186 const native_handle_t *handle = AHardwareBuffer_getNativeHandle(info->buffer);
187 int dma_buf = (handle && handle->numFds) ? handle->data[0] : -1;
188 if (dma_buf < 0)
189 return VK_ERROR_INVALID_EXTERNAL_HANDLE;
190
191 uint64_t size;
192 int result = device->pscreen->import_memory_fd(device->pscreen, dma_buf, (struct pipe_memory_allocation**)&mem->pmem, &size, true);
193 if (!result)
194 return VK_ERROR_INVALID_EXTERNAL_HANDLE;
195
196 AHardwareBuffer_acquire(info->buffer);
197 mem->android_hardware_buffer = info->buffer;
198 mem->size = size;
199 mem->memory_type = LVP_DEVICE_MEMORY_TYPE_DMA_BUF;
200
201 return VK_SUCCESS;
202 }
203
204 VkResult
lvp_create_ahb_memory(struct lvp_device * device,struct lvp_device_memory * mem,const VkMemoryAllocateInfo * pAllocateInfo)205 lvp_create_ahb_memory(struct lvp_device *device, struct lvp_device_memory *mem,
206 const VkMemoryAllocateInfo *pAllocateInfo)
207 {
208 mem->android_hardware_buffer = vk_alloc_ahardware_buffer(pAllocateInfo);
209 if (mem->android_hardware_buffer == NULL)
210 return VK_ERROR_OUT_OF_HOST_MEMORY;
211
212 const struct VkImportAndroidHardwareBufferInfoANDROID import_info = {
213 .buffer = mem->android_hardware_buffer,
214 };
215
216 VkResult result = lvp_import_ahb_memory(device, mem, &import_info);
217
218 /* Release a reference to avoid leak for AHB allocation. */
219 AHardwareBuffer_release(mem->android_hardware_buffer);
220
221 return result;
222 }
223