mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-11-12 00:59:41 +01:00
Use the common EmuThread in the Android backend
This commit is contained in:
1 parent
2e837e88b4
commit
ea3a2a2e84
6 files changed
+15
-95
No files matched your search
@@ -71,6 +71,8 @@ static void EmuThreadFunc(GraphicsContext *graphicsContext, Application *applica
|
||||
// This normally calls NativeShutdownGraphics()
|
||||
application->ShutdownGraphics(graphicsContext);
|
||||
|
||||
delete application;
|
||||
|
||||
INFO_LOG(Log::System, "Leaving separate emu thread");
|
||||
}
|
||||
|
||||
|
||||
@@ -30,9 +30,11 @@ class GraphicsContext;
|
||||
// Doesn't take ownership of the graphicsContext, you have to delete it.
|
||||
// This should be used by platforms that launch a separate thread and doesn't
|
||||
// need to run a polling loop in it.
|
||||
// NOTE: Does take ownership over Application (which is just a wrapper for NativeInitGraphics/NativeShutdownGraphics/NativeFrame).
|
||||
bool MainThreadFunc(GraphicsContext * graphicsContext, Application *application, WindowSystem windowSystem, void *windowData1, void *windowData2, std::function<void()> postFrame);
|
||||
|
||||
// If you're not using MainThreadFunc, you can at least use these to manage a spinning EmuThread (that calls NativeFrame),
|
||||
// whether your graphics context requires multithreading or not.
|
||||
// NOTE: Does take ownership over Application (which is just a wrapper for NativeInitGraphics/NativeShutdownGraphics/NativeFrame).
|
||||
std::thread EmuThread_Start(GraphicsContext *graphicsContext, Application *application, std::function<void()> postFrame);
|
||||
void EmuThread_Join(GraphicsContext *graphicsContext, std::thread &emuThread);
|
||||
+1
-3
@@ -2104,10 +2104,8 @@ int main(int argc, char *argv[]) {
|
||||
}
|
||||
EnableFZ();
|
||||
|
||||
NativeApplication application;
|
||||
|
||||
// We use the emuthread both for OpenGL and Vulkan, but in OpenGL mode we also render from the main thread.
|
||||
std::thread emuThread = EmuThread_Start(graphicsContext, &application, nullptr);
|
||||
std::thread emuThread = EmuThread_Start(graphicsContext, new NativeApplication(), nullptr);
|
||||
|
||||
graphicsContext->ThreadStart();
|
||||
|
||||
|
||||
@@ -8,17 +8,11 @@
|
||||
|
||||
AndroidJavaEGLGraphicsContext::AndroidJavaEGLGraphicsContext() {
|
||||
SetGPUBackend(GPUBackend::OPENGL);
|
||||
}
|
||||
|
||||
bool AndroidJavaEGLGraphicsContext::InitAPI(void *wnd, std::string *deviceName, std::string *errorMessage) {
|
||||
// OpenGL handles rotated rendering in the driver.
|
||||
g_display.rotation = DisplayRotation::ROTATE_0;
|
||||
g_display.rot_matrix.setIdentity();
|
||||
return true;
|
||||
}
|
||||
|
||||
void AndroidJavaEGLGraphicsContext::ShutdownAPI() {}
|
||||
|
||||
bool AndroidJavaEGLGraphicsContext::InitSurface(WindowSystem winsys, void *data1, void *data2, std::string *errorMessage) {
|
||||
INFO_LOG(Log::G3D, "AndroidJavaEGLGraphicsContext::InitFromRenderThread");
|
||||
if (!CheckGLExtensions()) {
|
||||
|
||||
@@ -11,9 +11,6 @@ public:
|
||||
|
||||
bool NeedsSeparateEmuThread() const override { return true; }
|
||||
|
||||
bool InitAPI(void *wnd, std::string *deviceName, std::string *errorMessage) override;
|
||||
void ShutdownAPI() override;
|
||||
|
||||
bool InitSurface(WindowSystem winsys, void *data1, void *data2, std::string *error_message) override;
|
||||
void ShutdownSurface() override;
|
||||
|
||||
|
||||
+10
-83
@@ -100,6 +100,7 @@ struct JNIEnv {};
|
||||
#include "Core/Loaders.h"
|
||||
#include "Core/KeyMap.h"
|
||||
#include "Core/System.h"
|
||||
#include "Core/EmuThread.h"
|
||||
#include "Core/HLE/sceUsbCam.h"
|
||||
#include "Core/HLE/sceUsbGps.h"
|
||||
#include "Common/CPUDetect.h"
|
||||
@@ -116,8 +117,7 @@ enum class EmuThreadState {
|
||||
};
|
||||
|
||||
// OpenGL emu thread
|
||||
static std::thread emuThread;
|
||||
static std::atomic<int> emuThreadState((int)EmuThreadState::DISABLED);
|
||||
static std::thread g_emuThread;
|
||||
|
||||
AndroidAudioState *g_audioState;
|
||||
|
||||
@@ -262,59 +262,6 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *pjvm, void *reserved) {
|
||||
return JNI_VERSION_1_6;
|
||||
}
|
||||
|
||||
// Only used in OpenGL mode.
|
||||
static void EmuThreadFunc() {
|
||||
SetCurrentThreadName("Entering EmuThread");
|
||||
|
||||
AndroidJNIThreadContext jniContext;
|
||||
|
||||
INFO_LOG(Log::System, "Entering emu thread");
|
||||
|
||||
_assert_(graphicsContext);
|
||||
if (!NativeInitGraphics(graphicsContext)) {
|
||||
_assert_msg_(false, "NativeInitGraphics failed, might as well bail");
|
||||
emuThreadState = (int)EmuThreadState::QUIT_REQUESTED;
|
||||
return;
|
||||
}
|
||||
|
||||
INFO_LOG(Log::System, "Graphics initialized. Entering loop.");
|
||||
|
||||
// There's no real requirement that NativeInit happen on this thread.
|
||||
// We just call the update/render loop here.
|
||||
emuThreadState = (int)EmuThreadState::RUNNING;
|
||||
while (emuThreadState != (int)EmuThreadState::QUIT_REQUESTED) {
|
||||
NativeFrame(graphicsContext);
|
||||
ProcessFrameCommands();
|
||||
}
|
||||
|
||||
INFO_LOG(Log::System, "emuThreadState was set to QUIT_REQUESTED, left EmuThreadFunc loop. Setting state to STOPPED.");
|
||||
emuThreadState = (int)EmuThreadState::STOPPED;
|
||||
|
||||
NativeShutdownGraphics(graphicsContext);
|
||||
|
||||
INFO_LOG(Log::System, "Leaving EmuThread");
|
||||
}
|
||||
|
||||
static void EmuThreadStart() {
|
||||
INFO_LOG(Log::System, "EmuThreadStart");
|
||||
emuThreadState = (int)EmuThreadState::START_REQUESTED;
|
||||
emuThread = std::thread(&EmuThreadFunc);
|
||||
}
|
||||
|
||||
// Call EmuThreadStop first, then keep running the GPU (or eat commands)
|
||||
// as long as emuThreadState isn't STOPPED and/or there are still things queued up.
|
||||
// Only after that, call EmuThreadJoin.
|
||||
static void EmuThreadStop(const char *caller) {
|
||||
INFO_LOG(Log::System, "EmuThreadStop - stopping (%s)...", caller);
|
||||
emuThreadState = (int)EmuThreadState::QUIT_REQUESTED;
|
||||
}
|
||||
|
||||
static void EmuThreadJoin() {
|
||||
emuThread.join();
|
||||
emuThread = std::thread();
|
||||
INFO_LOG(Log::System, "EmuThreadJoin - joined");
|
||||
}
|
||||
|
||||
static void PushCommand(std::string_view cmd, std::string_view param) {
|
||||
std::lock_guard<std::mutex> guard(frameCommandLock);
|
||||
g_frameCommands.emplace_back(std::string(cmd), std::string(param));
|
||||
@@ -956,23 +903,7 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeApp_shutdown(JNIEnv *, jclass) {
|
||||
|
||||
if (renderer_inited && graphicsContext && graphicsContext->NeedsSeparateEmuThread()) {
|
||||
// Only used in Java EGL path.
|
||||
EmuThreadStop("shutdown");
|
||||
// NOTE: We know that the GLSurfaceView render thread is stopped here, since we now
|
||||
// correctly call GLSurfaceView.onPause/onResume. However, there may still be queued frames.
|
||||
// We can't join until we've cleared the queue by calling ThreadFrame.
|
||||
|
||||
// Now we know that more frames won't be coming in.
|
||||
|
||||
INFO_LOG(Log::System, "BeginShutdown");
|
||||
|
||||
// Now, it could be that we had some frames queued up. Get through them.
|
||||
// We're on the render thread, so this is synchronous.
|
||||
graphicsContext->ThreadFrameUntilCondition([]() -> bool {
|
||||
return emuThreadState == (int)EmuThreadState::STOPPED;
|
||||
});
|
||||
graphicsContext->ThreadEnd();
|
||||
|
||||
EmuThreadJoin();
|
||||
EmuThread_Join(graphicsContext, g_emuThread);
|
||||
|
||||
INFO_LOG(Log::System, "ThreadEnd called.");
|
||||
graphicsContext->ShutdownSurface();
|
||||
@@ -1023,7 +954,9 @@ extern "C" jboolean Java_org_ppsspp_ppsspp_NativeRenderer_displayInit(JNIEnv * e
|
||||
return false;
|
||||
}
|
||||
// This is where we start the emuthread now - after InitFromRenderThread. This eliminates a race condition.
|
||||
EmuThreadStart();
|
||||
g_emuThread = EmuThread_Start(graphicsContext, new NativeApplication(), []() {
|
||||
ProcessFrameCommands();
|
||||
});
|
||||
|
||||
graphicsContext->GetDrawContext()->SetErrorCallback([](const char *shortDesc, const char *details, void *userdata) {
|
||||
g_OSD.Show(OSDType::MESSAGE_ERROR, details, 5.0);
|
||||
@@ -1037,15 +970,7 @@ extern "C" jboolean Java_org_ppsspp_ppsspp_NativeRenderer_displayInit(JNIEnv * e
|
||||
// which ends up calling displayInit.
|
||||
|
||||
INFO_LOG(Log::G3D, "NativeApp.displayInit() restoring");
|
||||
EmuThreadStop("displayInit");
|
||||
// Skipping GL calls here because the old context is lost.
|
||||
INFO_LOG(Log::G3D, "Looping until emu thread done...");
|
||||
// TODO: Why can't we just join the EmuThread first?
|
||||
graphicsContext->ThreadFrameUntilCondition([]() -> bool {
|
||||
return emuThreadState == (int)EmuThreadState::STOPPED;
|
||||
});
|
||||
INFO_LOG(Log::G3D, "Joining emu thread");
|
||||
EmuThreadJoin();
|
||||
EmuThread_Join(graphicsContext, g_emuThread);
|
||||
|
||||
graphicsContext->ThreadEnd();
|
||||
graphicsContext->ShutdownSurface();
|
||||
@@ -1061,7 +986,9 @@ extern "C" jboolean Java_org_ppsspp_ppsspp_NativeRenderer_displayInit(JNIEnv * e
|
||||
g_OSD.Show(OSDType::MESSAGE_ERROR, details, 5.0);
|
||||
}, nullptr);
|
||||
|
||||
EmuThreadStart();
|
||||
g_emuThread = EmuThread_Start(graphicsContext, new NativeApplication(), []() {
|
||||
ProcessFrameCommands();
|
||||
});
|
||||
|
||||
graphicsContext->ThreadStart();
|
||||
|
||||
|
||||
Reference in new issue
Block a user