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