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