diff --git a/Common/GPU/GraphicsContext.h b/Common/GPU/GraphicsContext.h index a4b2667a41..ca05a20a17 100644 --- a/Common/GPU/GraphicsContext.h +++ b/Common/GPU/GraphicsContext.h @@ -54,6 +54,10 @@ public: // Called from the emu thread, so be ready for that. virtual void NotifyEmuThreadExit() {} + // The API context that queued-up commands were recorded against is gone (or isn't current on the + // thread about to drain them), so they must not be executed for real. Only meaningful on Android GL. + virtual void NotifyContextLost() {} + // Useful for checks that need to be performed every frame. // Should strive to get rid of these. virtual void Poll() {} diff --git a/Common/GPU/OpenGL/GLRenderManager.h b/Common/GPU/OpenGL/GLRenderManager.h index edfe69b373..9c9f13f70a 100644 --- a/Common/GPU/OpenGL/GLRenderManager.h +++ b/Common/GPU/OpenGL/GLRenderManager.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -930,7 +931,8 @@ private: bool syncDone_ = false; GLDeleter deleter_; - bool skipGLCalls_ = false; + // Set from either thread, read on the render thread. + std::atomic skipGLCalls_{false}; int curFrame_ = 0; diff --git a/Common/GPU/OpenGL/OpenGLGraphicsContext.h b/Common/GPU/OpenGL/OpenGLGraphicsContext.h index 88ba27f5f3..082ac4a819 100644 --- a/Common/GPU/OpenGL/OpenGLGraphicsContext.h +++ b/Common/GPU/OpenGL/OpenGLGraphicsContext.h @@ -33,6 +33,12 @@ public: renderManager_->ThreadEnd(); } + void NotifyContextLost() override { + if (renderManager_) { + renderManager_->SetSkipGLCalls(); + } + } + // Call from emu thread void NotifyEmuThreadExit() override { renderManager_->SetSkipGLCalls(); diff --git a/android/jni/app-android.cpp b/android/jni/app-android.cpp index 50cb99e2b2..65522d3bd6 100644 --- a/android/jni/app-android.cpp +++ b/android/jni/app-android.cpp @@ -899,6 +899,8 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeApp_shutdown(JNIEnv *, jclass) { if (renderer_inited && graphicsContext && graphicsContext->NeedsSeparateEmuThread()) { // Only used in Java EGL path. + // The join drains the render queue right here, on a thread without a GL context. + graphicsContext->NotifyContextLost(); INFO_LOG(Log::System, "Joining emuthread."); EmuThread_Join(graphicsContext, g_emuThread); @@ -967,6 +969,9 @@ extern "C" jboolean Java_org_ppsspp_ppsspp_NativeRenderer_displayInit(JNIEnv * e // but the only mechanism for handling lost devices seems to be that onSurfaceCreated is called again, // which ends up calling displayInit. INFO_LOG(Log::G3D, "NativeApp.displayInit(): Second time, joining the emuthread and starting it up again."); + // We only get here with a fresh EGL context. What's left in the render queue refers to objects + // from the old one, so it mustn't be run against this one when the join drains it. + graphicsContext->NotifyContextLost(); EmuThread_Join(graphicsContext, g_emuThread); graphicsContext->ShutdownSurface();