1 /*
2 * Copyright 2018 Google LLC
3 * SPDX-License-Identifier: MIT
4 */
5 #include "Resources.h"
6
7 #include <stdlib.h>
8
9 #include "util/log.h"
10 #include "util/detect_os.h"
11
12 #define GOLDFISH_VK_OBJECT_DEBUG 0
13
14 #if GOLDFISH_VK_OBJECT_DEBUG
15 #define D(fmt, ...) ALOGD("%s: " fmt, __func__, ##__VA_ARGS__);
16 #else
17 #ifndef D
18 #define D(fmt, ...)
19 #endif
20 #endif
21
22 extern "C" {
23
24 #if DETECT_OS_ANDROID || DETECT_OS_FUCHSIA
25 #define SET_HWVULKAN_DISPATCH_MAGIC res->dispatch.magic = HWVULKAN_DISPATCH_MAGIC;
26 #elif DETECT_OS_LINUX
27 #define SET_HWVULKAN_DISPATCH_MAGIC res->loaderData.loaderMagic = ICD_LOADER_MAGIC;
28 #else
29 #define SET_HWVULKAN_DISPATCH_MAGIC
30 #endif
31
32 #define GOLDFISH_VK_NEW_DISPATCHABLE_FROM_HOST_IMPL(type) \
33 type new_from_host_##type(type underlying) { \
34 struct goldfish_##type* res = \
35 static_cast<goldfish_##type*>(malloc(sizeof(goldfish_##type))); \
36 if (!res) { \
37 mesa_loge("FATAL: Failed to alloc " #type " handle"); \
38 abort(); \
39 } \
40 SET_HWVULKAN_DISPATCH_MAGIC \
41 res->underlying = (uint64_t)underlying; \
42 res->lastUsedEncoder = nullptr; \
43 res->sequenceNumber = 0; \
44 res->privateEncoder = 0; \
45 res->privateStream = 0; \
46 res->flags = 0; \
47 res->poolObjects = 0; \
48 res->subObjects = 0; \
49 res->superObjects = 0; \
50 res->userPtr = 0; \
51 return reinterpret_cast<type>(res); \
52 }
53
54 #define GOLDFISH_VK_NEW_TRIVIAL_NON_DISPATCHABLE_FROM_HOST_IMPL(type) \
55 type new_from_host_##type(type underlying) { \
56 struct goldfish_##type* res = \
57 static_cast<goldfish_##type*>(malloc(sizeof(goldfish_##type))); \
58 res->underlying = (uint64_t)underlying; \
59 res->poolObjects = 0; \
60 res->subObjects = 0; \
61 res->superObjects = 0; \
62 res->userPtr = 0; \
63 return reinterpret_cast<type>(res); \
64 }
65
66 #define GOLDFISH_VK_AS_GOLDFISH_IMPL(type) \
67 struct goldfish_##type* as_goldfish_##type(type toCast) { \
68 return reinterpret_cast<goldfish_##type*>(toCast); \
69 }
70
71 #define GOLDFISH_VK_GET_HOST_IMPL(type) \
72 type get_host_##type(type toUnwrap) { \
73 if (!toUnwrap) return VK_NULL_HANDLE; \
74 auto as_goldfish = as_goldfish_##type(toUnwrap); \
75 return (type)(as_goldfish->underlying); \
76 }
77
78 #define GOLDFISH_VK_DELETE_GOLDFISH_IMPL(type) \
79 void delete_goldfish_##type(type toDelete) { \
80 D("guest %p", toDelete); \
81 free(as_goldfish_##type(toDelete)); \
82 }
83
84 #define GOLDFISH_VK_IDENTITY_IMPL(type) \
85 type vk_handle_identity_##type(type handle) { return handle; }
86
87 #define GOLDFISH_VK_NEW_DISPATCHABLE_FROM_HOST_U64_IMPL(type) \
88 type new_from_host_u64_##type(uint64_t underlying) { \
89 struct goldfish_##type* res = \
90 static_cast<goldfish_##type*>(malloc(sizeof(goldfish_##type))); \
91 if (!res) { \
92 mesa_loge("FATAL: Failed to alloc " #type " handle"); \
93 abort(); \
94 } \
95 SET_HWVULKAN_DISPATCH_MAGIC \
96 res->underlying = underlying; \
97 res->lastUsedEncoder = nullptr; \
98 res->sequenceNumber = 0; \
99 res->privateEncoder = 0; \
100 res->privateStream = 0; \
101 res->flags = 0; \
102 res->poolObjects = 0; \
103 res->subObjects = 0; \
104 res->superObjects = 0; \
105 res->userPtr = 0; \
106 return reinterpret_cast<type>(res); \
107 }
108
109 #define GOLDFISH_VK_NEW_TRIVIAL_NON_DISPATCHABLE_FROM_HOST_U64_IMPL(type) \
110 type new_from_host_u64_##type(uint64_t underlying) { \
111 struct goldfish_##type* res = \
112 static_cast<goldfish_##type*>(malloc(sizeof(goldfish_##type))); \
113 res->underlying = underlying; \
114 D("guest %p: host u64: 0x%llx", res, (unsigned long long)res->underlying); \
115 res->poolObjects = 0; \
116 res->subObjects = 0; \
117 res->superObjects = 0; \
118 res->userPtr = 0; \
119 return reinterpret_cast<type>(res); \
120 }
121
122 #define GOLDFISH_VK_GET_HOST_U64_IMPL(type) \
123 uint64_t get_host_u64_##type(type toUnwrap) { \
124 if (!toUnwrap) return 0; \
125 auto as_goldfish = as_goldfish_##type(toUnwrap); \
126 D("guest %p: host u64: 0x%llx", toUnwrap, (unsigned long long)as_goldfish->underlying); \
127 return as_goldfish->underlying; \
128 }
129
130 GOLDFISH_VK_LIST_DISPATCHABLE_HANDLE_TYPES(GOLDFISH_VK_NEW_DISPATCHABLE_FROM_HOST_IMPL)
GOLDFISH_VK_LIST_DISPATCHABLE_HANDLE_TYPES(GOLDFISH_VK_AS_GOLDFISH_IMPL)131 GOLDFISH_VK_LIST_DISPATCHABLE_HANDLE_TYPES(GOLDFISH_VK_AS_GOLDFISH_IMPL)
132 GOLDFISH_VK_LIST_DISPATCHABLE_HANDLE_TYPES(GOLDFISH_VK_GET_HOST_IMPL)
133 GOLDFISH_VK_LIST_DISPATCHABLE_HANDLE_TYPES(GOLDFISH_VK_DELETE_GOLDFISH_IMPL)
134 GOLDFISH_VK_LIST_DISPATCHABLE_HANDLE_TYPES(GOLDFISH_VK_IDENTITY_IMPL)
135 GOLDFISH_VK_LIST_DISPATCHABLE_HANDLE_TYPES(GOLDFISH_VK_NEW_DISPATCHABLE_FROM_HOST_U64_IMPL)
136 GOLDFISH_VK_LIST_DISPATCHABLE_HANDLE_TYPES(GOLDFISH_VK_GET_HOST_U64_IMPL)
137
138 GOLDFISH_VK_LIST_NON_DISPATCHABLE_HANDLE_TYPES(GOLDFISH_VK_AS_GOLDFISH_IMPL)
139 GOLDFISH_VK_LIST_NON_DISPATCHABLE_HANDLE_TYPES(GOLDFISH_VK_GET_HOST_IMPL)
140 GOLDFISH_VK_LIST_NON_DISPATCHABLE_HANDLE_TYPES(GOLDFISH_VK_IDENTITY_IMPL)
141 GOLDFISH_VK_LIST_NON_DISPATCHABLE_HANDLE_TYPES(GOLDFISH_VK_GET_HOST_U64_IMPL)
142 GOLDFISH_VK_LIST_AUTODEFINED_STRUCT_NON_DISPATCHABLE_HANDLE_TYPES(
143 GOLDFISH_VK_NEW_TRIVIAL_NON_DISPATCHABLE_FROM_HOST_IMPL)
144 GOLDFISH_VK_LIST_AUTODEFINED_STRUCT_NON_DISPATCHABLE_HANDLE_TYPES(
145 GOLDFISH_VK_NEW_TRIVIAL_NON_DISPATCHABLE_FROM_HOST_U64_IMPL)
146 GOLDFISH_VK_LIST_NON_DISPATCHABLE_HANDLE_TYPES(GOLDFISH_VK_DELETE_GOLDFISH_IMPL)
147
148 VkDescriptorPool new_from_host_VkDescriptorPool(VkDescriptorPool underlying) {
149 struct goldfish_VkDescriptorPool* res =
150 static_cast<goldfish_VkDescriptorPool*>(malloc(sizeof(goldfish_VkDescriptorPool)));
151 res->underlying = (uint64_t)underlying;
152 res->allocInfo = nullptr;
153 return reinterpret_cast<VkDescriptorPool>(res);
154 }
155
new_from_host_u64_VkDescriptorPool(uint64_t underlying)156 VkDescriptorPool new_from_host_u64_VkDescriptorPool(uint64_t underlying) {
157 return new_from_host_VkDescriptorPool((VkDescriptorPool)underlying);
158 }
159
new_from_host_VkDescriptorSet(VkDescriptorSet underlying)160 VkDescriptorSet new_from_host_VkDescriptorSet(VkDescriptorSet underlying) {
161 struct goldfish_VkDescriptorSet* res =
162 static_cast<goldfish_VkDescriptorSet*>(malloc(sizeof(goldfish_VkDescriptorSet)));
163 res->underlying = (uint64_t)underlying;
164 res->reified = nullptr;
165 return reinterpret_cast<VkDescriptorSet>(res);
166 }
167
new_from_host_u64_VkDescriptorSet(uint64_t underlying)168 VkDescriptorSet new_from_host_u64_VkDescriptorSet(uint64_t underlying) {
169 return new_from_host_VkDescriptorSet((VkDescriptorSet)underlying);
170 }
171
new_from_host_VkDescriptorSetLayout(VkDescriptorSetLayout underlying)172 VkDescriptorSetLayout new_from_host_VkDescriptorSetLayout(VkDescriptorSetLayout underlying) {
173 struct goldfish_VkDescriptorSetLayout* res = static_cast<goldfish_VkDescriptorSetLayout*>(
174 malloc(sizeof(goldfish_VkDescriptorSetLayout)));
175 res->underlying = (uint64_t)underlying;
176 res->layoutInfo = nullptr;
177 return reinterpret_cast<VkDescriptorSetLayout>(res);
178 }
179
new_from_host_u64_VkDescriptorSetLayout(uint64_t underlying)180 VkDescriptorSetLayout new_from_host_u64_VkDescriptorSetLayout(uint64_t underlying) {
181 return new_from_host_VkDescriptorSetLayout((VkDescriptorSetLayout)underlying);
182 }
183
184 } // extern "C"
185
186 namespace gfxstream {
187 namespace vk {
188
appendObject(struct goldfish_vk_object_list ** begin,void * val)189 void appendObject(struct goldfish_vk_object_list** begin, void* val) {
190 D("for %p", val);
191 struct goldfish_vk_object_list* o = new goldfish_vk_object_list;
192 o->next = nullptr;
193 o->obj = val;
194 D("new ptr: %p", o);
195 if (!*begin) {
196 D("first");
197 *begin = o;
198 return;
199 }
200
201 struct goldfish_vk_object_list* q = *begin;
202 struct goldfish_vk_object_list* p = q;
203
204 while (q) {
205 p = q;
206 q = q->next;
207 }
208
209 D("set next of %p to %p", p, o);
210 p->next = o;
211 }
212
eraseObject(struct goldfish_vk_object_list ** begin,void * val)213 void eraseObject(struct goldfish_vk_object_list** begin, void* val) {
214 D("for val %p", val);
215 if (!*begin) {
216 D("val %p notfound", val);
217 return;
218 }
219
220 struct goldfish_vk_object_list* q = *begin;
221 struct goldfish_vk_object_list* p = q;
222
223 while (q) {
224 struct goldfish_vk_object_list* n = q->next;
225 if (val == q->obj) {
226 D("val %p found, delete", val);
227 delete q;
228 if (*begin == q) {
229 D("val %p set begin to %p:", val, n);
230 *begin = n;
231 } else {
232 D("val %p set pnext to %p:", val, n);
233 p->next = n;
234 }
235 return;
236 }
237 p = q;
238 q = n;
239 }
240
241 D("val %p notfound after looping", val);
242 }
243
eraseObjects(struct goldfish_vk_object_list ** begin)244 void eraseObjects(struct goldfish_vk_object_list** begin) {
245 struct goldfish_vk_object_list* q = *begin;
246 struct goldfish_vk_object_list* p = q;
247
248 while (q) {
249 p = q;
250 q = q->next;
251 delete p;
252 }
253
254 *begin = nullptr;
255 }
256
forAllObjects(struct goldfish_vk_object_list * begin,std::function<void (void *)> func)257 void forAllObjects(struct goldfish_vk_object_list* begin, std::function<void(void*)> func) {
258 struct goldfish_vk_object_list* q = begin;
259 struct goldfish_vk_object_list* p = q;
260
261 D("call");
262 while (q) {
263 D("iter");
264 p = q;
265 q = q->next;
266 func(p->obj);
267 }
268 }
269
270 } // namespace vk
271 } // namespace gfxstream
272