• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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