blob: c57d385a3617719e2a7234cacf92eb78c439e1c6 [file] [log] [blame]
/*
* 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 <GLES2/gl2ext.h>
#include <atomic>
#include <functional>
#include <memory>
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<SaveableTexture> {
public:
using Buffer = android::base::SmallVector<unsigned char>;
using saver_t = void (*)(SaveableTexture*,
android::base::Stream*,
Buffer* buffer);
// loader_t is supposed to setup a stream and trigger loadFromStream.
typedef std::function<void(SaveableTexture*)> 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<unsigned char, 16> m_data;
};
std::unique_ptr<LevelImageData[]> m_levelData[6] = {};
std::unordered_map<GLenum, GLint> m_texParam;
loader_t m_loader;
GlobalNameSpace* m_globalNamespace = nullptr;
bool m_isDirty = true;
std::atomic<bool> m_loadedFromStream { false };
};
typedef std::shared_ptr<SaveableTexture> SaveableTexturePtr;