• 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 
17 #include "GLcommon/ObjectNameSpace.h"
18 
19 #include "base/Lock.h"
20 #include "base/Lookup.h"
21 #include "base/PathUtils.h"
22 #include "base/StreamSerializing.h"
23 #include "snapshot/TextureLoader.h"
24 #include "snapshot/TextureSaver.h"
25 #include "host-common/crash_reporter.h"
26 #include "GLcommon/GLEScontext.h"
27 #include "GLcommon/TranslatorIfaces.h"
28 
29 #include <assert.h>
30 
31 #define GL_LOG(...)
32 
33 using android::snapshot::ITextureSaver;
34 using android::snapshot::ITextureLoader;
35 using android::snapshot::ITextureSaverPtr;
36 using android::snapshot::ITextureLoaderPtr;
37 using android::snapshot::ITextureLoaderWPtr;
38 
NameSpace(NamedObjectType p_type,GlobalNameSpace * globalNameSpace,android::base::Stream * stream,const ObjectData::loadObject_t & loadObject)39 NameSpace::NameSpace(NamedObjectType p_type, GlobalNameSpace *globalNameSpace,
40         android::base::Stream* stream, const ObjectData::loadObject_t& loadObject) :
41     m_type(p_type),
42     m_globalNameSpace(globalNameSpace) {
43     if (!stream) return;
44     // When loading from a snapshot, we restores translator states here, but
45     // host GPU states are not touched until postLoadRestore is called.
46     // GlobalNames are not yet generated.
47     size_t objSize = stream->getBe32();
48     for (size_t obj = 0; obj < objSize; obj++) {
49         ObjectLocalName localName = stream->getBe64();
50         ObjectDataPtr data = loadObject((NamedObjectType)m_type,
51                 localName, stream);
52         if (m_type == NamedObjectType::TEXTURE) {
53             // Texture data are managed differently
54             // They are loaded by GlobalNameSpace before loading
55             // share groups
56             TextureData* texData = (TextureData*)data.get();
57             if (!texData->getGlobalName()) {
58                 GL_LOG("NameSpace::%s: %p: texture data %p is 0 texture\n",
59                        __func__, this, texData);
60                 continue;
61             }
62 
63             SaveableTexturePtr saveableTexture =
64                     globalNameSpace->getSaveableTextureFromLoad(
65                             texData->getGlobalName());
66             texData->setSaveableTexture(std::move(saveableTexture));
67             texData->setGlobalName(0);
68         }
69         setObjectData(localName, std::move(data));
70     }
71 }
72 
~NameSpace()73 NameSpace::~NameSpace() {
74 }
75 
postLoad(const ObjectData::getObjDataPtr_t & getObjDataPtr)76 void NameSpace::postLoad(const ObjectData::getObjDataPtr_t& getObjDataPtr) {
77     for (const auto& objData : m_objectDataMap) {
78         GL_LOG("NameSpace::%s: %p: try to load object %llu\n", __func__, this, objData.first);
79         if (!objData.second) {
80             // bug: 130631787
81             // emugl::emugl_crash_reporter(
82             //         "Fatal: null object data ptr on restore\n");
83             continue;
84         }
85         objData.second->postLoad(getObjDataPtr);
86     }
87 }
88 
touchTextures()89 void NameSpace::touchTextures() {
90     assert(m_type == NamedObjectType::TEXTURE);
91     for (const auto& obj : m_objectDataMap) {
92         TextureData* texData = (TextureData*)obj.second.get();
93         if (!texData->needRestore()) {
94             GL_LOG("NameSpace::%s: %p: texture data %p does not need restore\n",
95                     __func__, this, texData);
96             continue;
97         }
98         const SaveableTexturePtr& saveableTexture = texData->getSaveableTexture();
99         if (!saveableTexture.get()) {
100             GL_LOG("NameSpace::%s: %p: warning: no saveableTexture for texture data %p\n",
101                     __func__, this, texData);
102             continue;
103         }
104 
105         NamedObjectPtr texNamedObj = saveableTexture->getGlobalObject();
106         if (!texNamedObj) {
107             GL_LOG("NameSpace::%s: %p: fatal: global object null for texture data %p\n",
108                     __func__, this, texData);
109             emugl_crash_reporter(
110                     "fatal: null global texture object in "
111                     "NameSpace::touchTextures");
112         }
113         setGlobalObject(obj.first, texNamedObj);
114         texData->setGlobalName(texNamedObj->getGlobalName());
115         texData->restore(0, nullptr);
116     }
117 }
118 
postLoadRestore(const ObjectData::getGlobalName_t & getGlobalName)119 void NameSpace::postLoadRestore(const ObjectData::getGlobalName_t& getGlobalName) {
120     // Texture data are special, they got the global name from SaveableTexture
121     // This is because texture data can be shared across multiple share groups
122     if (m_type == NamedObjectType::TEXTURE) {
123         touchTextures();
124         return;
125     }
126     // 2 passes are needed for SHADER_OR_PROGRAM type, because (1) they
127     // live in the same namespace (2) shaders must be created before
128     // programs.
129     int numPasses = m_type == NamedObjectType::SHADER_OR_PROGRAM
130             ? 2 : 1;
131     for (int pass = 0; pass < numPasses; pass ++) {
132         for (const auto& obj : m_objectDataMap) {
133             assert(m_type == ObjectDataType2NamedObjectType(
134                     obj.second->getDataType()));
135             // get global names
136             if ((obj.second->getDataType() == PROGRAM_DATA && pass == 0)
137                     || (obj.second->getDataType() == SHADER_DATA &&
138                             pass == 1)) {
139                 continue;
140             }
141             genName(obj.second->getGenNameInfo(), obj.first, false);
142             obj.second->restore(obj.first, getGlobalName);
143         }
144     }
145 }
146 
preSave(GlobalNameSpace * globalNameSpace)147 void NameSpace::preSave(GlobalNameSpace *globalNameSpace) {
148     if (m_type != NamedObjectType::TEXTURE) {
149         return;
150     }
151     // In case we loaded textures from a previous snapshot and have not yet
152     // restore them to GPU, we do the restoration here.
153     // TODO: skip restoration and write saveableTexture directly to the new
154     // snapshot
155     touchTextures();
156     for (const auto& obj : m_objectDataMap) {
157         globalNameSpace->preSaveAddTex((TextureData*)obj.second.get());
158     }
159 }
160 
onSave(android::base::Stream * stream)161 void NameSpace::onSave(android::base::Stream* stream) {
162     stream->putBe32(m_objectDataMap.size());
163     for (const auto& obj : m_objectDataMap) {
164         stream->putBe64(obj.first);
165         obj.second->onSave(stream, getGlobalName(obj.first));
166     }
167 }
168 
169 static ObjectDataPtr* nullObjectData = new ObjectDataPtr;
170 static NamedObjectPtr* nullNamedObject = new NamedObjectPtr;
171 
172 ObjectLocalName
genName(GenNameInfo genNameInfo,ObjectLocalName p_localName,bool genLocal)173 NameSpace::genName(GenNameInfo genNameInfo, ObjectLocalName p_localName, bool genLocal)
174 {
175     assert(m_type == genNameInfo.m_type);
176     ObjectLocalName localName = p_localName;
177     if (genLocal) {
178         do {
179             localName = ++m_nextName;
180         } while(localName == 0 ||
181                 nullptr != m_localToGlobalMap.getExceptZero_const(localName));
182     }
183 
184     auto newObjPtr = NamedObjectPtr( new NamedObject(genNameInfo, m_globalNameSpace));
185     m_localToGlobalMap.add(localName, newObjPtr);
186 
187     unsigned int globalName = newObjPtr->getGlobalName();
188     m_globalToLocalMap.add(globalName, localName);
189     return localName;
190 }
191 
192 
193 unsigned int
getGlobalName(ObjectLocalName p_localName,bool * found)194 NameSpace::getGlobalName(ObjectLocalName p_localName, bool* found)
195 {
196     auto objPtrPtr = m_localToGlobalMap.getExceptZero_const(p_localName);
197 
198     if (!objPtrPtr) {
199         if (found) *found = false;
200         return 0;
201     }
202 
203     if (found) *found = true;
204     auto res =  (*objPtrPtr)->getGlobalName();
205     return res;
206 }
207 
208 ObjectLocalName
getLocalName(unsigned int p_globalName)209 NameSpace::getLocalName(unsigned int p_globalName)
210 {
211     auto localPtr = m_globalToLocalMap.get_const(p_globalName);
212     if (!localPtr) return 0;
213     return *localPtr;
214 }
215 
getNamedObject(ObjectLocalName p_localName)216 NamedObjectPtr NameSpace::getNamedObject(ObjectLocalName p_localName) {
217     auto objPtrPtr = m_localToGlobalMap.get_const(p_localName);
218     if (!objPtrPtr || !(*objPtrPtr)) return nullptr;
219     return *objPtrPtr;
220 }
221 
222 void
deleteName(ObjectLocalName p_localName)223 NameSpace::deleteName(ObjectLocalName p_localName)
224 {
225     auto objPtrPtr = m_localToGlobalMap.getExceptZero(p_localName);
226     if (objPtrPtr) {
227         m_globalToLocalMap.remove((*objPtrPtr)->getGlobalName());
228         *objPtrPtr = *nullNamedObject;
229         m_localToGlobalMap.remove(p_localName);
230     }
231 
232     m_objectDataMap.erase(p_localName);
233     m_boundMap.remove(p_localName);
234 }
235 
236 bool
isObject(ObjectLocalName p_localName)237 NameSpace::isObject(ObjectLocalName p_localName)
238 {
239     auto objPtrPtr = m_localToGlobalMap.getExceptZero_const(p_localName);
240     return nullptr != objPtrPtr;
241 }
242 
243 void
setGlobalObject(ObjectLocalName p_localName,NamedObjectPtr p_namedObject)244 NameSpace::setGlobalObject(ObjectLocalName p_localName,
245                                NamedObjectPtr p_namedObject) {
246 
247     auto objPtrPtr = m_localToGlobalMap.getExceptZero(p_localName);
248     if (objPtrPtr) {
249         m_globalToLocalMap.remove((*objPtrPtr)->getGlobalName());
250         *objPtrPtr = p_namedObject;
251     } else {
252         m_localToGlobalMap.add(p_localName, p_namedObject);
253     }
254 
255     m_globalToLocalMap.add(p_namedObject->getGlobalName(), p_localName);
256 }
257 
258 void
replaceGlobalObject(ObjectLocalName p_localName,NamedObjectPtr p_namedObject)259 NameSpace::replaceGlobalObject(ObjectLocalName p_localName,
260                                NamedObjectPtr p_namedObject)
261 {
262     auto objPtrPtr = m_localToGlobalMap.getExceptZero(p_localName);
263     if (objPtrPtr) {
264         m_globalToLocalMap.remove((*objPtrPtr)->getGlobalName());
265         *objPtrPtr = p_namedObject;
266         m_globalToLocalMap.add(p_namedObject->getGlobalName(), p_localName);
267     }
268 }
269 
270 // sets that the local name has been bound at least once, to save time later
setBoundAtLeastOnce(ObjectLocalName p_localName)271 void NameSpace::setBoundAtLeastOnce(ObjectLocalName p_localName) {
272     m_boundMap.add(p_localName, true);
273 }
274 
275 // sets that the local name has been bound at least once, to save time later
everBound(ObjectLocalName p_localName) const276 bool NameSpace::everBound(ObjectLocalName p_localName) const {
277     const bool* boundPtr = m_boundMap.get_const(p_localName);
278     if (!boundPtr) return false;
279     return *boundPtr;
280 }
281 
objDataMapBegin() const282 ObjectDataMap::const_iterator NameSpace::objDataMapBegin() const {
283     return m_objectDataMap.begin();
284 }
285 
objDataMapEnd() const286 ObjectDataMap::const_iterator NameSpace::objDataMapEnd() const {
287     return m_objectDataMap.end();
288 }
289 
getObjectDataPtr(ObjectLocalName p_localName)290 const ObjectDataPtr& NameSpace::getObjectDataPtr(
291         ObjectLocalName p_localName) {
292     const auto it = m_objectDataMap.find(p_localName);
293     if (it != m_objectDataMap.end()) {
294         return it->second;
295     }
296     return *nullObjectData;
297 }
298 
setObjectData(ObjectLocalName p_localName,ObjectDataPtr data)299 void NameSpace::setObjectData(ObjectLocalName p_localName,
300         ObjectDataPtr data) {
301     m_objectDataMap[p_localName] = std::move(data);
302 }
303 
preSaveAddEglImage(EglImage * eglImage)304 void GlobalNameSpace::preSaveAddEglImage(EglImage* eglImage) {
305     if (!eglImage->globalTexObj) {
306         GL_LOG("GlobalNameSpace::%s: %p: egl image %p with null texture object\n",
307                __func__, this, eglImage);
308         emugl_crash_reporter(
309                 "Fatal: egl image with null texture object\n");
310     }
311     unsigned int globalName = eglImage->globalTexObj->getGlobalName();
312     android::base::AutoLock lock(m_lock);
313 
314     if (!globalName) {
315         GL_LOG("GlobalNameSpace::%s: %p: egl image %p has 0 texture object\n",
316                __func__, this, eglImage);
317         return;
318     }
319 
320     const auto& saveableTexIt = m_textureMap.find(globalName);
321     if (saveableTexIt == m_textureMap.end()) {
322         assert(eglImage->saveableTexture);
323         m_textureMap.emplace(globalName, eglImage->saveableTexture);
324     } else {
325         assert(m_textureMap[globalName] == eglImage->saveableTexture);
326     }
327 }
328 
preSaveAddTex(TextureData * texture)329 void GlobalNameSpace::preSaveAddTex(TextureData* texture) {
330     android::base::AutoLock lock(m_lock);
331     const auto& saveableTexIt = m_textureMap.find(texture->getGlobalName());
332 
333     if (!texture->getGlobalName()) {
334         GL_LOG("GlobalNameSpace::%s: %p: texture data %p is 0 texture\n",
335                __func__, this, texture);
336         return;
337     }
338 
339     if (saveableTexIt == m_textureMap.end()) {
340         assert(texture->getSaveableTexture());
341         m_textureMap.emplace(texture->getGlobalName(),
342                              texture->getSaveableTexture());
343     } else {
344         assert(m_textureMap[texture->getGlobalName()] ==
345                texture->getSaveableTexture());
346     }
347 }
348 
onSave(android::base::Stream * stream,const ITextureSaverPtr & textureSaver,SaveableTexture::saver_t saver)349 void GlobalNameSpace::onSave(android::base::Stream* stream,
350                              const ITextureSaverPtr& textureSaver,
351                              SaveableTexture::saver_t saver) {
352 #if SNAPSHOT_PROFILE > 1
353     int cleanTexs = 0;
354     int dirtyTexs = 0;
355 #endif // SNAPSHOT_PROFILE > 1
356     saveCollection(
357             stream, m_textureMap,
358             [saver, &textureSaver
359 #if SNAPSHOT_PROFILE > 1
360             , &cleanTexs, &dirtyTexs
361 #endif // SNAPSHOT_PROFILE > 1
362                 ](
363                     android::base::Stream* stream,
364                     const std::pair<const unsigned int, SaveableTexturePtr>&
365                             tex) {
366                 stream->putBe32(tex.first);
367 #if SNAPSHOT_PROFILE > 1
368                 if (tex.second.get() && tex.second->isDirty()) {
369                     dirtyTexs ++;
370                 } else {
371                     cleanTexs ++;
372                 }
373 #endif // SNAPSHOT_PROFILE > 1
374                 textureSaver->saveTexture(
375                         tex.first,
376                         [saver, &tex](android::base::Stream* stream,
377                                       ITextureSaver::Buffer* buffer) {
378                             if (!tex.second.get()) return;
379                             saver(tex.second.get(), stream, buffer);
380                         });
381             });
382     clearTextureMap();
383 #if SNAPSHOT_PROFILE > 1
384     printf("Dirty texture saved %d, clean texture saved %d\n",
385             dirtyTexs, cleanTexs);
386 #endif // SNAPSHOT_PROFILE > 1
387 }
388 
onLoad(android::base::Stream * stream,const ITextureLoaderWPtr & textureLoaderWPtr,SaveableTexture::creator_t creator)389 void GlobalNameSpace::onLoad(android::base::Stream* stream,
390                              const ITextureLoaderWPtr& textureLoaderWPtr,
391                              SaveableTexture::creator_t creator) {
392     const ITextureLoaderPtr textureLoader = textureLoaderWPtr.lock();
393     assert(m_textureMap.size() == 0);
394     if (!textureLoader->start()) {
395         fprintf(stderr,
396                 "Error: texture file unsupported version or corrupted.\n");
397         emugl_crash_reporter(
398                 "Error: texture file unsupported version or corrupted.\n");
399         return;
400     }
401     loadCollection(
402             stream, &m_textureMap,
403             [this, creator, textureLoaderWPtr](android::base::Stream* stream) {
404                 unsigned int globalName = stream->getBe32();
405                 // A lot of function wrapping happens here.
406                 // When touched, saveableTexture triggers
407                 // textureLoader->loadTexture, which sets up the file position
408                 // and the mutex, and triggers saveableTexture->loadFromStream
409                 // for the real loading.
410                 SaveableTexture* saveableTexture = creator(
411                         this, [globalName, textureLoaderWPtr](
412                                       SaveableTexture* saveableTexture) {
413                             auto textureLoader = textureLoaderWPtr.lock();
414                             if (!textureLoader) return;
415                             textureLoader->loadTexture(
416                                     globalName,
417                                     [saveableTexture](
418                                             android::base::Stream* stream) {
419                                         saveableTexture->loadFromStream(stream);
420                                     });
421                         });
422                 return std::make_pair(globalName,
423                                       SaveableTexturePtr(saveableTexture));
424             });
425 
426     m_backgroundLoader =
427         std::make_shared<GLBackgroundLoader>(
428             textureLoaderWPtr, *m_eglIface, *m_glesIface, m_textureMap);
429     textureLoader->acquireLoaderThread(m_backgroundLoader);
430 }
431 
clearTextureMap()432 void GlobalNameSpace::clearTextureMap() {
433     decltype(m_textureMap)().swap(m_textureMap);
434 }
435 
postLoad(android::base::Stream * stream)436 void GlobalNameSpace::postLoad(android::base::Stream* stream) {
437     m_backgroundLoader->start();
438     m_backgroundLoader.reset(); // leave it to TextureLoader
439 }
440 
getSaveableTextureFromLoad(unsigned int oldGlobalName)441 const SaveableTexturePtr& GlobalNameSpace::getSaveableTextureFromLoad(
442         unsigned int oldGlobalName) {
443     assert(m_textureMap.count(oldGlobalName));
444     return m_textureMap[oldGlobalName];
445 }
446