mirror of
https://github.com/hrydgard/ppsspp.git
synced 2024-11-23 13:30:02 +00:00
Android: Add both a lost and restore phase.
Lost = delete, restore = create. Let's stick to never overlapping. May help #8912.
This commit is contained in:
parent
29f5763d32
commit
92d930887f
@ -534,6 +534,10 @@ void GPU_DX9::DeviceLost() {
|
||||
framebufferManager_.DeviceLost();
|
||||
}
|
||||
|
||||
void GPU_DX9::DeviceRestore() {
|
||||
// Nothing needed.
|
||||
}
|
||||
|
||||
void GPU_DX9::InitClear() {
|
||||
ScheduleEvent(GPU_EVENT_INIT_CLEAR);
|
||||
}
|
||||
|
@ -56,6 +56,7 @@ public:
|
||||
bool PerformStencilUpload(u32 dest, int size) override;
|
||||
void ClearCacheNextFrame() override;
|
||||
void DeviceLost() override; // Only happens on Android. Drop all textures and shaders.
|
||||
void DeviceRestore() override;
|
||||
|
||||
void DumpNextFrame() override;
|
||||
void DoState(PointerWrap &p) override;
|
||||
|
@ -207,14 +207,18 @@ void DrawEngineGLES::DestroyDeviceObjects() {
|
||||
}
|
||||
}
|
||||
|
||||
void DrawEngineGLES::GLRestore() {
|
||||
ILOG("TransformDrawEngine::GLRestore()");
|
||||
void DrawEngineGLES::GLLost() {
|
||||
ILOG("TransformDrawEngine::GLLost()");
|
||||
// The objects have already been deleted.
|
||||
bufferNameCache_.clear();
|
||||
bufferNameInfo_.clear();
|
||||
freeSizedBuffers_.clear();
|
||||
bufferNameCacheSize_ = 0;
|
||||
ClearTrackedVertexArrays();
|
||||
}
|
||||
|
||||
void DrawEngineGLES::GLRestore() {
|
||||
ILOG("TransformDrawEngine::GLRestore()");
|
||||
InitDeviceObjects();
|
||||
}
|
||||
|
||||
|
@ -129,6 +129,7 @@ public:
|
||||
void RestoreVAO();
|
||||
void InitDeviceObjects();
|
||||
void DestroyDeviceObjects();
|
||||
void GLLost() override;
|
||||
void GLRestore() override;
|
||||
void Resized();
|
||||
|
||||
|
@ -651,6 +651,10 @@ void GPU_GLES::DeviceLost() {
|
||||
fragmentTestCache_.Clear(false);
|
||||
depalShaderCache_.Clear();
|
||||
framebufferManager_.DeviceLost();
|
||||
}
|
||||
|
||||
void GPU_GLES::DeviceRestore() {
|
||||
ILOG("GPU_GLES: DeviceRestore");
|
||||
|
||||
UpdateVsyncInterval(true);
|
||||
}
|
||||
|
@ -60,6 +60,7 @@ public:
|
||||
bool PerformStencilUpload(u32 dest, int size) override;
|
||||
void ClearCacheNextFrame() override;
|
||||
void DeviceLost() override; // Only happens on Android. Drop all textures and shaders.
|
||||
void DeviceRestore() override;
|
||||
|
||||
void DumpNextFrame() override;
|
||||
void DoState(PointerWrap &p) override;
|
||||
|
@ -268,6 +268,7 @@ public:
|
||||
virtual void EnableInterrupts(bool enable) = 0;
|
||||
|
||||
virtual void DeviceLost() = 0;
|
||||
virtual void DeviceRestore() = 0;
|
||||
virtual void ReapplyGfxState() = 0;
|
||||
virtual void SyncThread(bool force = false) = 0;
|
||||
virtual void SyncBeginFrame() = 0;
|
||||
|
@ -43,6 +43,7 @@ public:
|
||||
void ClearCacheNextFrame() override {}
|
||||
|
||||
void DeviceLost() override {}
|
||||
void DeviceRestore() override {}
|
||||
void DumpNextFrame() override {}
|
||||
|
||||
void Resized() override {}
|
||||
|
@ -78,6 +78,10 @@ void SoftGPU::DeviceLost() {
|
||||
// Handled by thin3d.
|
||||
}
|
||||
|
||||
void SoftGPU::DeviceRestore() {
|
||||
// Handled by thin3d.
|
||||
}
|
||||
|
||||
SoftGPU::~SoftGPU() {
|
||||
vformat->Release();
|
||||
vformat = nullptr;
|
||||
|
@ -69,6 +69,7 @@ public:
|
||||
void ClearCacheNextFrame() override {}
|
||||
|
||||
void DeviceLost() override;
|
||||
void DeviceRestore() override;
|
||||
void DumpNextFrame() override {}
|
||||
|
||||
void Resized() override {}
|
||||
|
@ -1947,6 +1947,10 @@ void GPU_Vulkan::DeviceLost() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
void GPU_Vulkan::DeviceRestore() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
void GPU_Vulkan::GetStats(char *buffer, size_t bufsize) {
|
||||
const DrawEngineVulkanStats &drawStats = drawEngine_.GetStats();
|
||||
float vertexAverageCycles = gpuStats.numVertsSubmitted > 0 ? (float)gpuStats.vertexGPUCycles / (float)gpuStats.numVertsSubmitted : 0.0f;
|
||||
|
@ -62,6 +62,7 @@ public:
|
||||
bool PerformStencilUpload(u32 dest, int size) override;
|
||||
void ClearCacheNextFrame() override;
|
||||
void DeviceLost() override; // Only happens on Android. Drop all textures and shaders.
|
||||
void DeviceRestore() override;
|
||||
|
||||
void DumpNextFrame() override;
|
||||
void DoState(PointerWrap &p) override;
|
||||
|
@ -1097,6 +1097,12 @@ void EmuScreen::deviceLost() {
|
||||
ILOG("EmuScreen::deviceLost()");
|
||||
if (gpu)
|
||||
gpu->DeviceLost();
|
||||
}
|
||||
|
||||
void EmuScreen::deviceRestore() {
|
||||
ILOG("EmuScreen::deviceRestore()");
|
||||
if (gpu)
|
||||
gpu->DeviceRestore();
|
||||
|
||||
RecreateViews();
|
||||
}
|
||||
|
@ -38,6 +38,7 @@ public:
|
||||
void update(InputState &input) override;
|
||||
void render() override;
|
||||
void deviceLost() override;
|
||||
void deviceRestore() override;
|
||||
void dialogFinished(const Screen *dialog, DialogResult result) override;
|
||||
void sendMessage(const char *msg, const char *value) override;
|
||||
|
||||
|
@ -808,11 +808,16 @@ void NativeUpdate(InputState &input) {
|
||||
screenManager->update(input);
|
||||
}
|
||||
|
||||
void NativeDeviceRestore() {
|
||||
void NativeDeviceLost() {
|
||||
if (g_gameInfoCache)
|
||||
g_gameInfoCache->Clear();
|
||||
screenManager->deviceLost();
|
||||
gl_lost();
|
||||
}
|
||||
|
||||
void NativeDeviceRestore() {
|
||||
NativeDeviceLost();
|
||||
screenManager->deviceRestore();
|
||||
if (GetGPUBackend() == GPUBackend::OPENGL) {
|
||||
gl_restore();
|
||||
}
|
||||
|
@ -697,6 +697,7 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeRenderer_displayRender(JNIEnv *env,
|
||||
extern "C" void Java_org_ppsspp_ppsspp_NativeRenderer_displayShutdown(JNIEnv *env, jobject obj) {
|
||||
ILOG("NativeApp.displayShutdown()");
|
||||
if (renderer_inited) {
|
||||
NativeDeviceLost();
|
||||
NativeShutdownGraphics();
|
||||
renderer_inited = false;
|
||||
NativeMessageReceived("recreateviews", "");
|
||||
|
@ -57,6 +57,24 @@ void gl_restore() {
|
||||
inRestore = false;
|
||||
}
|
||||
|
||||
void gl_lost() {
|
||||
inLost = true;
|
||||
if (!holders) {
|
||||
WLOG("GL resource holder not initialized, cannot process restore request");
|
||||
inLost = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: We should really do this when we get the context back, not during gl_lost...
|
||||
ILOG("gl_lost() clearing %i items:", (int)holders->size());
|
||||
for (size_t i = 0; i < holders->size(); i++) {
|
||||
ILOG("gl_lost(%i / %i, %p, %08x)", (int)(i + 1), (int)holders->size(), (*holders)[i], *((uint32_t *)((*holders)[i])));
|
||||
(*holders)[i]->GLLost();
|
||||
}
|
||||
ILOG("gl_lost() completed on %i items:", (int)holders->size());
|
||||
inLost = false;
|
||||
}
|
||||
|
||||
void gl_lost_manager_init() {
|
||||
if (holders) {
|
||||
FLOG("Double GL lost manager init");
|
||||
|
@ -7,6 +7,7 @@ class GfxResourceHolder {
|
||||
public:
|
||||
virtual ~GfxResourceHolder() {}
|
||||
virtual void GLRestore() = 0;
|
||||
virtual void GLLost() = 0;
|
||||
};
|
||||
|
||||
void gl_lost_manager_init();
|
||||
@ -15,5 +16,8 @@ void gl_lost_manager_shutdown();
|
||||
void register_gl_resource_holder(GfxResourceHolder *holder);
|
||||
void unregister_gl_resource_holder(GfxResourceHolder *holder);
|
||||
|
||||
// Notifies all objects it's time to forget / delete things.
|
||||
void gl_lost();
|
||||
|
||||
// Notifies all objects that it's time to be restored.
|
||||
void gl_restore();
|
||||
|
@ -220,7 +220,7 @@ bool glsl_recompile(GLSLProgram *program, std::string *error_message) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void GLSLProgram::GLRestore() {
|
||||
void GLSLProgram::GLLost() {
|
||||
// Quoth http://developer.android.com/reference/android/opengl/GLSurfaceView.Renderer.html;
|
||||
// "Note that when the EGL context is lost, all OpenGL resources associated with that context will be automatically deleted.
|
||||
// You do not need to call the corresponding "glDelete" methods such as glDeleteTextures to manually delete these lost resources."
|
||||
@ -228,9 +228,12 @@ void GLSLProgram::GLRestore() {
|
||||
// glDeleteShader(this->vsh_);
|
||||
// glDeleteShader(this->fsh_);
|
||||
// glDeleteProgram(this->program_);
|
||||
this->program_ = 0;
|
||||
this->vsh_ = 0;
|
||||
this->fsh_ = 0;
|
||||
program_ = 0;
|
||||
vsh_ = 0;
|
||||
fsh_ = 0;
|
||||
}
|
||||
|
||||
void GLSLProgram::GLRestore() {
|
||||
ILOG("Restoring GLSL program %s/%s",
|
||||
strlen(this->vshader_filename) > 0 ? this->vshader_filename : "(mem)",
|
||||
strlen(this->fshader_filename) > 0 ? this->fshader_filename : "(mem)");
|
||||
|
@ -43,6 +43,7 @@ struct GLSLProgram : public GfxResourceHolder {
|
||||
GLuint fsh_;
|
||||
GLuint program_;
|
||||
|
||||
void GLLost() override;
|
||||
void GLRestore() override;
|
||||
};
|
||||
|
||||
|
@ -207,8 +207,12 @@ public:
|
||||
glBindBuffer(target_, buffer_);
|
||||
}
|
||||
|
||||
void GLLost() override {
|
||||
buffer_ = 0;
|
||||
}
|
||||
|
||||
void GLRestore() override {
|
||||
ILOG("Recreating vertex buffer after glLost");
|
||||
ILOG("Recreating vertex buffer after gl_restore");
|
||||
knownSize_ = 0; // Will cause a new glBufferData call. Should genBuffers again though?
|
||||
glGenBuffers(1, &buffer_);
|
||||
}
|
||||
@ -235,6 +239,10 @@ public:
|
||||
}
|
||||
const std::string &GetSource() const { return source_; }
|
||||
|
||||
void Unset() {
|
||||
shader_ = 0;
|
||||
}
|
||||
|
||||
~Thin3DGLShader() {
|
||||
glDeleteShader(shader_);
|
||||
}
|
||||
@ -257,7 +265,7 @@ bool Thin3DGLShader::Compile(const char *source) {
|
||||
source = temp.c_str();
|
||||
}
|
||||
|
||||
glShaderSource(shader_, 1, &source, 0);
|
||||
glShaderSource(shader_, 1, &source, nullptr);
|
||||
glCompileShader(shader_);
|
||||
GLint success = 0;
|
||||
glGetShaderiv(shader_, GL_COMPILE_STATUS, &success);
|
||||
@ -283,6 +291,7 @@ public:
|
||||
void Unapply();
|
||||
void Compile();
|
||||
void GLRestore() override;
|
||||
void GLLost() override;
|
||||
bool RequiresBuffer() override {
|
||||
return id_ != 0;
|
||||
}
|
||||
@ -323,6 +332,12 @@ public:
|
||||
void SetVector(const char *name, float *value, int n) override;
|
||||
void SetMatrix4x4(const char *name, const float value[16]) override;
|
||||
|
||||
void GLLost() override {
|
||||
program_ = 0;
|
||||
vshader->Unset();
|
||||
fshader->Unset();
|
||||
}
|
||||
|
||||
void GLRestore() override {
|
||||
vshader->Compile(vshader->GetSource().c_str());
|
||||
fshader->Compile(fshader->GetSource().c_str());
|
||||
@ -550,15 +565,19 @@ public:
|
||||
glBindTexture(target_, tex_);
|
||||
}
|
||||
|
||||
void GLRestore() override {
|
||||
void GLLost() override {
|
||||
// We can assume that the texture is gone.
|
||||
tex_ = 0;
|
||||
generatedMips_ = false;
|
||||
}
|
||||
|
||||
void GLRestore() override {
|
||||
if (!filename_.empty()) {
|
||||
if (LoadFromFile(filename_.c_str())) {
|
||||
ILOG("Reloaded lost texture %s", filename_.c_str());
|
||||
} else {
|
||||
ELOG("Failed to reload lost texture %s", filename_.c_str());
|
||||
tex_ = 0;
|
||||
}
|
||||
} else {
|
||||
WLOG("Texture %p cannot be restored - has no filename", this);
|
||||
@ -663,6 +682,10 @@ void Thin3DGLVertexFormat::Compile() {
|
||||
lastBase_ = -1;
|
||||
}
|
||||
|
||||
void Thin3DGLVertexFormat::GLLost() {
|
||||
id_ = 0;
|
||||
}
|
||||
|
||||
void Thin3DGLVertexFormat::GLRestore() {
|
||||
Compile();
|
||||
}
|
||||
|
@ -147,6 +147,14 @@ void ScreenManager::deviceLost() {
|
||||
// TODO: Change this when it becomes necessary.
|
||||
}
|
||||
|
||||
void ScreenManager::deviceRestore() {
|
||||
for (size_t i = 0; i < stack_.size(); i++) {
|
||||
stack_[i].screen->deviceRestore();
|
||||
}
|
||||
// Dialogs too? Nah, they should only use the standard UI texture anyway.
|
||||
// TODO: Change this when it becomes necessary.
|
||||
}
|
||||
|
||||
Screen *ScreenManager::topScreen() const {
|
||||
if (!stack_.empty())
|
||||
return stack_.back().screen;
|
||||
|
@ -50,6 +50,7 @@ public:
|
||||
virtual void render() {}
|
||||
virtual void postRender() {}
|
||||
virtual void deviceLost() {}
|
||||
virtual void deviceRestore() {}
|
||||
virtual void resized() {}
|
||||
virtual void dialogFinished(const Screen *dialog, DialogResult result) {}
|
||||
virtual bool touch(const TouchInput &touch) { return false; }
|
||||
@ -103,6 +104,7 @@ public:
|
||||
void render();
|
||||
void resized();
|
||||
void deviceLost();
|
||||
void deviceRestore();
|
||||
void shutdown();
|
||||
|
||||
// Push a dialog box in front. Currently 1-level only.
|
||||
|
Loading…
Reference in New Issue
Block a user