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