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