• 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         (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