/* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include "aemu/base/containers/SmallVector.h" #include "aemu/base/files/Stream.h" #include "snapshot/LazySnapshotObj.h" #include "GLcommon/NamedObject.h" #include "GLcommon/TextureData.h" #include "GLcommon/TranslatorIfaces.h" #include #include #include #include class GLDispatch; class GlobalNameSpace; class TextureData; // TextureGlobal is an auxiliary class when save and load a texture / EglImage. // We need it only for texture because texture is the only GL object that can be // shared globally (i.e. across guest processes) by wrapping it up in EglImage. // Lifespan: // When saving a snapshot, TextureGlobal should be populated in the pre-save // stage, save data in save stage and get destroyed right after that. // When loading from a snapshot, TextureGlobal will be populated and restoring // hardware texture before restoring any EglImage or GLES texture handles. // EglImages and GLES textures get their global handles from TextureGlobal when // EglImages and GLES textures are being loaded. Then TextureGlobal will be // destroyed. class SaveableTexture : public android::snapshot::LazySnapshotObj { public: using Buffer = android::base::SmallVector; using saver_t = void (*)(SaveableTexture*, android::base::Stream*, Buffer* buffer); // loader_t is supposed to setup a stream and trigger loadFromStream. typedef std::function loader_t; using creator_t = SaveableTexture* (*)(GlobalNameSpace*, loader_t&&); using restorer_t = void (*)(SaveableTexture*); SaveableTexture() = delete; SaveableTexture(SaveableTexture&&) = delete; SaveableTexture(GlobalNameSpace* globalNameSpace, loader_t&& loader); SaveableTexture& operator=(SaveableTexture&&) = delete; SaveableTexture(const TextureData& texture); // preSave and postSave should be called exactly once before and after // all texture saves. // The bound context cannot be changed from preSave to onSave to postSave static void preSave(); static void postSave(); // precondition: a context must be properly bound void onSave(android::base::Stream* stream); // getGlobalObject() will touch and load data onto GPU if it is not yet // restored const NamedObjectPtr& getGlobalObject(); // precondition: a context must be properly bound void fillEglImage(EglImage* eglImage); void loadFromStream(android::base::Stream* stream); void makeDirty(); bool isDirty() const; void setTarget(GLenum target); void setMipmapLevelAtLeast(unsigned int level); unsigned int getGlobalName(); // precondition: (1) a context must be properly bound // (2) m_fileReader is set up void restore(); private: unsigned int m_target = GL_TEXTURE_2D; unsigned int m_width = 0; unsigned int m_height = 0; unsigned int m_depth = 0; // For texture 3D unsigned int m_format = GL_RGBA; unsigned int m_internalFormat = GL_RGBA; unsigned int m_type = GL_UNSIGNED_BYTE; unsigned int m_border = 0; unsigned int m_texStorageLevels = 0; unsigned int m_maxMipmapLevel = 0; // Attributes used when saving a snapshot unsigned int m_globalName = 0; // Attributes used when loaded from a snapshot NamedObjectPtr m_globalTexObj = nullptr; struct LevelImageData { unsigned int m_width = 0; unsigned int m_height = 0; unsigned int m_depth = 0; android::base::SmallFixedVector m_data; }; std::unique_ptr m_levelData[6] = {}; std::unordered_map m_texParam; loader_t m_loader; GlobalNameSpace* m_globalNamespace = nullptr; bool m_isDirty = true; std::atomic m_loadedFromStream { false }; }; typedef std::shared_ptr SaveableTexturePtr;