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