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