1 /*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 #include <GLcommon/ShareGroup.h>
17 #include <GLcommon/ObjectNameSpace.h>
18 #include <GLcommon/GLEScontext.h>
19
20 #include "aemu/base/synchronization/Lock.h"
21 #include "aemu/base/containers/Lookup.h"
22 #include "GLcommon/FramebufferData.h"
23
24 #include "host-common/logging.h"
25
26 #include <array>
27 #include <utility>
28
toIndex(NamedObjectType type)29 static constexpr int toIndex(NamedObjectType type) {
30 return static_cast<int>(type);
31 }
32
33 struct ShareGroup::ObjectDataAutoLock {
ObjectDataAutoLockShareGroup::ObjectDataAutoLock34 ObjectDataAutoLock(ShareGroup* self) : self(self) {
35 self->lockObjectData();
36 }
~ObjectDataAutoLockShareGroup::ObjectDataAutoLock37 ~ObjectDataAutoLock() {
38 self->unlockObjectData();
39 }
40
41 ShareGroup* self;
42 };
43
ShareGroup(GlobalNameSpace * globalNameSpace,uint64_t sharedGroupID,android::base::Stream * stream,const ObjectData::loadObject_t & loadObject)44 ShareGroup::ShareGroup(GlobalNameSpace *globalNameSpace,
45 uint64_t sharedGroupID,
46 android::base::Stream* stream,
47 const ObjectData::loadObject_t& loadObject) :
48 m_sharedGroupID(sharedGroupID) {
49 ObjectDataAutoLock lock(this);
50 for (int i = 0; i < toIndex(NamedObjectType::NUM_OBJECT_TYPES);
51 i++) {
52 m_nameSpace[i] = new NameSpace(static_cast<NamedObjectType>(i),
53 globalNameSpace, stream, loadObject);
54 }
55 if (stream) {
56 m_needLoadRestore = true;
57 int i = 0;
58 (void)i;
59 for (auto ns : m_nameSpace) {
60 GL_LOG("ShareGroup::%s: %p: start restore namespace for type %d\n", __func__, this, i);
61 ns->postLoad(
62 [this](NamedObjectType p_type, ObjectLocalName p_localName) {
63 return this->getObjectDataPtrNoLock(p_type, p_localName);
64 });
65 GL_LOG("ShareGroup::%s: %p: finish restore namespace for type %d\n", __func__, this, i);
66 ++i;
67 }
68 }
69 }
70
preSave(GlobalNameSpace * globalNameSpace)71 void ShareGroup::preSave(GlobalNameSpace *globalNameSpace) {
72 ObjectDataAutoLock lock(this);
73 if (m_saveStage == PreSaved) return;
74 assert(m_saveStage == Empty);
75 m_saveStage = PreSaved;
76 m_nameSpace[(int)NamedObjectType::TEXTURE]->preSave(globalNameSpace);
77 }
78
onSave(android::base::Stream * stream)79 void ShareGroup::onSave(android::base::Stream* stream) {
80 // we do not save m_nameSpace
81 ObjectDataAutoLock lock(this);
82 if (m_saveStage == Saved) return;
83 assert(m_saveStage == PreSaved);
84 m_saveStage = Saved;
85 int i = 0;
86 (void)i;
87 for (auto ns : m_nameSpace) {
88 GL_LOG("ShareGroup::%s: %p: start saving type %d\n", __func__, this, i);
89 ns->onSave(stream);
90 GL_LOG("ShareGroup::%s: %p: finish saving type %d\n", __func__, this, i);
91 ++i;
92 }
93 }
94
postSave(android::base::Stream * stream)95 void ShareGroup::postSave(android::base::Stream* stream) {
96 (void)stream;
97 m_saveStage = Empty;
98 // We need to mark the textures dirty, for those that has been bound to
99 // a potential render target.
100 NameSpace* renderbufferNs = m_nameSpace[(int)NamedObjectType::RENDERBUFFER];
101 for (ObjectDataMap::const_iterator it = renderbufferNs->objDataMapBegin();
102 it != renderbufferNs->objDataMapEnd();
103 it ++) {
104 RenderbufferData* rbData = (RenderbufferData*)it->second.get();
105 rbData->makeTextureDirty();
106 }
107 }
108
postLoadRestore()109 void ShareGroup::postLoadRestore() {
110 android::base::AutoLock lock(m_restoreLock);
111 if (m_needLoadRestore) {
112 int i = 0;
113 (void)i;
114 for (auto ns : m_nameSpace) {
115 GL_LOG("ShareGroup::%s: %p: start post load restore namespace for type %d\n", __func__, this, i);
116 ns->postLoadRestore([this](NamedObjectType p_type,
117 ObjectLocalName p_localName) {
118 return getGlobalName(p_type, p_localName);
119 });
120 GL_LOG("ShareGroup::%s: %p: end post load restore namespace for type %d\n", __func__, this, i);
121 ++i;
122 }
123 m_needLoadRestore = false;
124 }
125 }
126
needRestore()127 bool ShareGroup::needRestore() {
128 return m_needLoadRestore;
129 }
130
lockObjectData()131 void ShareGroup::lockObjectData() {
132 while (m_objectsDataLock.test_and_set(std::memory_order_acquire)) {
133 ;
134 }
135 }
136
unlockObjectData()137 void ShareGroup::unlockObjectData() {
138 m_objectsDataLock.clear(std::memory_order_release);
139 }
140
~ShareGroup()141 ShareGroup::~ShareGroup()
142 {
143 {
144 android::base::AutoLock lock(m_namespaceLock);
145 ObjectDataAutoLock objDataLock(this);
146 for (auto n : m_nameSpace) {
147 delete n;
148 }
149 }
150 }
151
152 ObjectLocalName
genName(GenNameInfo genNameInfo,ObjectLocalName p_localName,bool genLocal)153 ShareGroup::genName(GenNameInfo genNameInfo,
154 ObjectLocalName p_localName,
155 bool genLocal)
156 {
157 assert(genNameInfo.m_type != NamedObjectType::FRAMEBUFFER);
158 if (toIndex(genNameInfo.m_type) >=
159 toIndex(NamedObjectType::NUM_OBJECT_TYPES)) {
160 return 0;
161 }
162
163 android::base::AutoLock lock(m_namespaceLock);
164 ObjectLocalName localName =
165 m_nameSpace[toIndex(genNameInfo.m_type)]->genName(
166 genNameInfo,
167 p_localName, genLocal);
168 return localName;
169 }
170
genName(NamedObjectType namedObjectType,ObjectLocalName p_localName,bool genLocal)171 ObjectLocalName ShareGroup::genName(NamedObjectType namedObjectType,
172 ObjectLocalName p_localName,
173 bool genLocal) {
174 return genName(GenNameInfo(namedObjectType), p_localName, genLocal);
175 }
176
genName(ShaderProgramType shaderProgramType,ObjectLocalName p_localName,bool genLocal,GLuint existingGlobal)177 ObjectLocalName ShareGroup::genName(ShaderProgramType shaderProgramType,
178 ObjectLocalName p_localName,
179 bool genLocal,
180 GLuint existingGlobal) {
181 return genName(GenNameInfo(shaderProgramType, existingGlobal), p_localName, genLocal);
182 }
183
184 unsigned int
getGlobalName(NamedObjectType p_type,ObjectLocalName p_localName)185 ShareGroup::getGlobalName(NamedObjectType p_type,
186 ObjectLocalName p_localName)
187 {
188 assert(p_type != NamedObjectType::FRAMEBUFFER);
189 if (toIndex(p_type) >= toIndex(NamedObjectType::NUM_OBJECT_TYPES)) {
190 return 0;
191 }
192 android::base::AutoLock lock(m_namespaceLock);
193 return m_nameSpace[toIndex(p_type)]->getGlobalName(p_localName);
194 }
195
196 ObjectLocalName
getLocalName(NamedObjectType p_type,unsigned int p_globalName)197 ShareGroup::getLocalName(NamedObjectType p_type,
198 unsigned int p_globalName)
199 {
200 assert(p_type != NamedObjectType::FRAMEBUFFER);
201 if (toIndex(p_type) >= toIndex(NamedObjectType::NUM_OBJECT_TYPES)) {
202 return 0;
203 }
204
205 android::base::AutoLock lock(m_namespaceLock);
206 return m_nameSpace[toIndex(p_type)]->getLocalName(p_globalName);
207 }
208
getNamedObject(NamedObjectType p_type,ObjectLocalName p_localName)209 NamedObjectPtr ShareGroup::getNamedObject(NamedObjectType p_type,
210 ObjectLocalName p_localName) {
211 assert(p_type != NamedObjectType::FRAMEBUFFER);
212 if (toIndex(p_type) >= toIndex(NamedObjectType::NUM_OBJECT_TYPES)) {
213 return 0;
214 }
215
216 android::base::AutoLock lock(m_namespaceLock);
217 return m_nameSpace[toIndex(p_type)]->getNamedObject(p_localName);
218 }
219
220 void
deleteName(NamedObjectType p_type,ObjectLocalName p_localName)221 ShareGroup::deleteName(NamedObjectType p_type, ObjectLocalName p_localName)
222 {
223 assert(p_type != NamedObjectType::FRAMEBUFFER);
224 if (toIndex(p_type) >= toIndex(NamedObjectType::NUM_OBJECT_TYPES)) {
225 return;
226 }
227
228 android::base::AutoLock lock(m_namespaceLock);
229 ObjectDataAutoLock objDataLock(this);
230 m_nameSpace[toIndex(p_type)]->deleteName(p_localName);
231 }
232
233 bool
isObject(NamedObjectType p_type,ObjectLocalName p_localName)234 ShareGroup::isObject(NamedObjectType p_type, ObjectLocalName p_localName)
235 {
236 assert(p_type != NamedObjectType::FRAMEBUFFER);
237 if (toIndex(p_type) >= toIndex(NamedObjectType::NUM_OBJECT_TYPES)) {
238 return 0;
239 }
240
241 android::base::AutoLock lock(m_namespaceLock);
242 return m_nameSpace[toIndex(p_type)]->isObject(p_localName);
243 }
244
245 void
replaceGlobalObject(NamedObjectType p_type,ObjectLocalName p_localName,NamedObjectPtr p_globalObject)246 ShareGroup::replaceGlobalObject(NamedObjectType p_type,
247 ObjectLocalName p_localName,
248 NamedObjectPtr p_globalObject)
249 {
250 assert(p_type != NamedObjectType::FRAMEBUFFER);
251 if (toIndex(p_type) >= toIndex(NamedObjectType::NUM_OBJECT_TYPES)) {
252 return;
253 }
254
255 android::base::AutoLock lock(m_namespaceLock);
256 m_nameSpace[toIndex(p_type)]->replaceGlobalObject(p_localName,
257 p_globalObject);
258 }
259
260 void
setGlobalObject(NamedObjectType p_type,ObjectLocalName p_localName,NamedObjectPtr p_globalObject)261 ShareGroup::setGlobalObject(NamedObjectType p_type,
262 ObjectLocalName p_localName,
263 NamedObjectPtr p_globalObject)
264 {
265 assert(p_type != NamedObjectType::FRAMEBUFFER);
266 if (toIndex(p_type) >= toIndex(NamedObjectType::NUM_OBJECT_TYPES)) {
267 return;
268 }
269
270 android::base::AutoLock lock(m_namespaceLock);
271 m_nameSpace[toIndex(p_type)]->setGlobalObject(p_localName,
272 p_globalObject);
273 }
274
275 void
setObjectData(NamedObjectType p_type,ObjectLocalName p_localName,ObjectDataPtr data)276 ShareGroup::setObjectData(NamedObjectType p_type,
277 ObjectLocalName p_localName,
278 ObjectDataPtr data) {
279 ObjectDataAutoLock lock(this);
280 setObjectDataLocked(p_type, p_localName, std::move(data));
281 }
282
283 void
setObjectDataLocked(NamedObjectType p_type,ObjectLocalName p_localName,ObjectDataPtr && data)284 ShareGroup::setObjectDataLocked(NamedObjectType p_type,
285 ObjectLocalName p_localName,
286 ObjectDataPtr&& data)
287 {
288 assert(p_type != NamedObjectType::FRAMEBUFFER);
289 if (toIndex(p_type) >= toIndex(NamedObjectType::NUM_OBJECT_TYPES)) {
290 return;
291 }
292 m_nameSpace[toIndex(p_type)]->setObjectData(p_localName, data);
293 }
294
getObjectDataPtrNoLock(NamedObjectType p_type,ObjectLocalName p_localName)295 const ObjectDataPtr& ShareGroup::getObjectDataPtrNoLock(
296 NamedObjectType p_type, ObjectLocalName p_localName) {
297 assert(p_type != NamedObjectType::FRAMEBUFFER);
298 return m_nameSpace[toIndex(p_type)]->getObjectDataPtr(p_localName);
299 }
300
getObjectData(NamedObjectType p_type,ObjectLocalName p_localName)301 ObjectData* ShareGroup::getObjectData(NamedObjectType p_type,
302 ObjectLocalName p_localName) {
303 if (toIndex(p_type) >=
304 toIndex(NamedObjectType::NUM_OBJECT_TYPES))
305 return nullptr;
306
307 ObjectDataAutoLock lock(this);
308 return getObjectDataPtrNoLock(p_type, p_localName).get();
309 }
310
getObjectDataPtr(NamedObjectType p_type,ObjectLocalName p_localName)311 ObjectDataPtr ShareGroup::getObjectDataPtr(NamedObjectType p_type,
312 ObjectLocalName p_localName)
313 {
314 if (toIndex(p_type) >=
315 toIndex(NamedObjectType::NUM_OBJECT_TYPES))
316 return {};
317
318 ObjectDataAutoLock lock(this);
319 return getObjectDataPtrNoLock(p_type, p_localName);
320 }
321
322 #define CC_LIKELY( exp ) (__builtin_expect( !!(exp), true ))
323 #define CC_UNLIKELY( exp ) (__builtin_expect( !!(exp), false ))
324
ensureObjectOnBind(NamedObjectType p_type,ObjectLocalName p_localName)325 unsigned int ShareGroup::ensureObjectOnBind(NamedObjectType p_type, ObjectLocalName p_localName) {
326 android::base::AutoLock lock(m_namespaceLock);
327 ObjectDataAutoLock objDataLock(this);
328
329 auto ns = m_nameSpace[toIndex(p_type)];
330
331 bool isObj;
332 unsigned int globalName = ns->getGlobalName(p_localName, &isObj);
333
334 if (CC_LIKELY(isObj)) {
335 bool everBound = ns->everBound(p_localName);
336 if (CC_LIKELY(everBound)) return globalName;
337
338 auto ptr = ns->getObjectDataPtr(p_localName);
339
340 if (ptr) {
341 switch (p_type) {
342 case NamedObjectType::VERTEXBUFFER: {
343 auto vbo = ((GLESbuffer*)(ptr.get()));
344 vbo->setBinded();
345 break;
346 }
347 // TODO: Add other object types here
348 default:
349 fprintf(stderr, "%s: Warning: Unhandled object type 0x%x\n",
350 __func__, (uint32_t)p_type);
351 break;
352 }
353 }
354
355 ns->setBoundAtLeastOnce(p_localName);
356 return globalName;
357 }
358
359 // No such object, generate one and bind it
360 bool genLocal = false;
361 auto gi = GenNameInfo(p_type);
362 ns->genName( gi, p_localName, genLocal);
363
364 switch (p_type) {
365 case NamedObjectType::VERTEXBUFFER: {
366 auto vbo = new GLESbuffer;
367 vbo->setBinded();
368 ns->setObjectData(p_localName, ObjectDataPtr(vbo));
369 break;
370 }
371 // TODO: Add other object types here
372 default:
373 fprintf(stderr, "%s: Warning: Unhandled object type 0x%x\n",
374 __func__, (uint32_t)p_type);
375 break;
376 }
377
378 ns->setBoundAtLeastOnce(p_localName);
379 return (uint32_t)(ns->getGlobalName(p_localName));
380 }
381
ObjectNameManager(GlobalNameSpace * globalNameSpace)382 ObjectNameManager::ObjectNameManager(GlobalNameSpace *globalNameSpace) :
383 m_globalNameSpace(globalNameSpace) {}
384
385 ShareGroupPtr
createShareGroup(void * p_groupName,uint64_t sharedGroupID,android::base::Stream * stream,const ObjectData::loadObject_t & loadObject)386 ObjectNameManager::createShareGroup(void *p_groupName, uint64_t sharedGroupID,
387 android::base::Stream* stream, const ObjectData::loadObject_t& loadObject)
388 {
389 android::base::AutoLock lock(m_lock);
390
391 ShareGroupPtr& shareGroupReturn = m_groups[p_groupName];
392 if (!shareGroupReturn) {
393 if (!sharedGroupID) {
394 while (m_nextSharedGroupID == 0 ||
395 android::base::contains(m_usedSharedGroupIDs,
396 m_nextSharedGroupID)) {
397 m_nextSharedGroupID ++;
398 }
399 sharedGroupID = m_nextSharedGroupID;
400 m_usedSharedGroupIDs.insert(sharedGroupID);
401 ++m_nextSharedGroupID;
402 } else {
403 assert(!m_usedSharedGroupIDs.count(sharedGroupID));
404 m_usedSharedGroupIDs.insert(sharedGroupID);
405 }
406 shareGroupReturn.reset(new ShareGroup(m_globalNameSpace, sharedGroupID,
407 stream, loadObject));
408 } else {
409 assert(sharedGroupID == 0
410 || sharedGroupID == shareGroupReturn->getId());
411 }
412
413 return shareGroupReturn;
414 }
415
416 ShareGroupPtr
getShareGroup(void * p_groupName)417 ObjectNameManager::getShareGroup(void *p_groupName)
418 {
419 android::base::AutoLock lock(m_lock);
420
421 ShareGroupPtr shareGroupReturn;
422
423 ShareGroupsMap::iterator s( m_groups.find(p_groupName) );
424 if (s != m_groups.end()) {
425 shareGroupReturn = (*s).second;
426 }
427
428 return shareGroupReturn;
429 }
430
431 ShareGroupPtr
attachShareGroup(void * p_groupName,void * p_existingGroupName)432 ObjectNameManager::attachShareGroup(void *p_groupName,
433 void *p_existingGroupName)
434 {
435 android::base::AutoLock lock(m_lock);
436
437 ShareGroupsMap::iterator s( m_groups.find(p_existingGroupName) );
438 if (s == m_groups.end()) {
439 // ShareGroup is not found !!!
440 return ShareGroupPtr();
441 }
442
443 ShareGroupPtr shareGroupReturn((*s).second);
444 if (m_groups.find(p_groupName) == m_groups.end()) {
445 m_groups.emplace(p_groupName, shareGroupReturn);
446 m_usedSharedGroupIDs.insert(shareGroupReturn->getId());
447 }
448 return shareGroupReturn;
449 }
450
attachOrCreateShareGroup(void * p_groupName,uint64_t p_existingGroupID,android::base::Stream * stream,const ObjectData::loadObject_t & loadObject)451 ShareGroupPtr ObjectNameManager::attachOrCreateShareGroup(void *p_groupName,
452 uint64_t p_existingGroupID, android::base::Stream* stream,
453 const ObjectData::loadObject_t& loadObject) {
454 assert(m_groups.find(p_groupName) == m_groups.end());
455 ShareGroupsMap::iterator ite = p_existingGroupID ? m_groups.begin()
456 : m_groups.end();
457 while (ite != m_groups.end() && ite->second->getId() != p_existingGroupID) {
458 ++ite;
459 }
460 if (ite == m_groups.end()) {
461 return createShareGroup(p_groupName, p_existingGroupID, stream,
462 loadObject);
463 } else {
464 return attachShareGroup(p_groupName, ite->first);
465 }
466 }
467
468 void
deleteShareGroup(void * p_groupName)469 ObjectNameManager::deleteShareGroup(void *p_groupName)
470 {
471 android::base::AutoLock lock(m_lock);
472 auto sharedGroup = m_groups.find(p_groupName);
473 if (sharedGroup == m_groups.end()) return;
474 m_usedSharedGroupIDs.erase(sharedGroup->second->getId());
475 m_groups.erase(sharedGroup);
476 }
477
getGlobalContext()478 void *ObjectNameManager::getGlobalContext()
479 {
480 android::base::AutoLock lock(m_lock);
481 return m_groups.empty() ? nullptr : m_groups.begin()->first;
482 }
483
preSave()484 void ObjectNameManager::preSave() {
485 for (auto& shareGroup : m_groups) {
486 shareGroup.second->preSave(m_globalNameSpace);
487 }
488 }
489