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