mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-01 14:58:14 +00:00
Break the circular dependency caused by putting EmuThread in core using an interface
This commit is contained in:
1 parent
cb1b4067f7
commit
85f8715660
15 files changed
+70
-35
No files matched your search
@@ -822,6 +822,7 @@ add_library(Common STATIC
|
||||
Common/Audio/AudioBackend.h
|
||||
Common/System/Display.cpp
|
||||
Common/System/Display.h
|
||||
Common/System/Application.h
|
||||
Common/System/System.h
|
||||
Common/System/NativeApp.h
|
||||
Common/System/Request.cpp
|
||||
|
||||
@@ -536,6 +536,7 @@
|
||||
<ClInclude Include="StringUtils.h" />
|
||||
<ClInclude Include="Swap.h" />
|
||||
<ClInclude Include="SysError.h" />
|
||||
<ClInclude Include="System\Application.h" />
|
||||
<ClInclude Include="System\Display.h" />
|
||||
<ClInclude Include="System\OSD.h" />
|
||||
<ClInclude Include="System\Request.h" />
|
||||
|
||||
@@ -784,6 +784,9 @@
|
||||
<ClInclude Include="Data\Text\StringWriter.h">
|
||||
<Filter>Data\Text</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="System\Application.h">
|
||||
<Filter>System</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="ABI.cpp" />
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
class GraphicsContext;
|
||||
|
||||
class Application {
|
||||
public:
|
||||
virtual ~Application() = default;
|
||||
virtual bool InitGraphics(GraphicsContext *graphicsContext) = 0;
|
||||
virtual void ShutdownGraphics(GraphicsContext *graphicsContext) = 0;
|
||||
virtual void Frame(GraphicsContext *graphicsContext) = 0;
|
||||
};
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <string>
|
||||
|
||||
#include "Common/Common.h"
|
||||
#include "Common/System/Application.h"
|
||||
|
||||
// The Native App API.
|
||||
//
|
||||
@@ -91,7 +92,7 @@ void NativeMix(short *audio, int num_samples, int sampleRateHz, void *userdata);
|
||||
// The graphics context should still be active when calling this, as freeing
|
||||
// of graphics resources happens here.
|
||||
// Main thread.
|
||||
void NativeShutdownGraphics();
|
||||
void NativeShutdownGraphics(GraphicsContext *graphicsContext);
|
||||
void NativeShutdown();
|
||||
|
||||
void PostLoadConfig();
|
||||
@@ -112,3 +113,17 @@ bool Native_IsWindowHidden();
|
||||
bool Native_UpdateScreenScale(int width, int height, float customScale);
|
||||
|
||||
AudioBackend *System_CreateAudioBackend();
|
||||
|
||||
class NativeApplication : public Application {
|
||||
public:
|
||||
NativeApplication() {}
|
||||
bool InitGraphics(GraphicsContext *graphicsContext) override {
|
||||
return NativeInitGraphics(graphicsContext);
|
||||
}
|
||||
void ShutdownGraphics(GraphicsContext *graphicsContext) override {
|
||||
return NativeShutdownGraphics(graphicsContext);
|
||||
}
|
||||
void Frame(GraphicsContext *graphicsContext) override {
|
||||
return NativeFrame(graphicsContext);
|
||||
}
|
||||
};
|
||||
+14
-14
@@ -4,9 +4,9 @@
|
||||
#include <atomic>
|
||||
#include <thread>
|
||||
|
||||
#include "Common/System/NativeApp.h"
|
||||
#include "Common/System/System.h"
|
||||
#include "Common/System/Request.h"
|
||||
#include "Common/System/Application.h"
|
||||
#include "Common/Data/Text/I18n.h"
|
||||
#include "Common/Input/InputState.h"
|
||||
#include "Common/Data/Encoding/Utf8.h"
|
||||
@@ -40,7 +40,7 @@ bool MainThread_Ready() {
|
||||
return g_inLoop;
|
||||
}
|
||||
|
||||
static void EmuThreadFunc(GraphicsContext *graphicsContext, std::function<void()> postFrame) {
|
||||
static void EmuThreadFunc(GraphicsContext *graphicsContext, Application *application, std::function<void()> postFrame) {
|
||||
INFO_LOG(Log::G3D, "Entering emu thread");
|
||||
SetCurrentThreadName("EmuThread");
|
||||
|
||||
@@ -50,7 +50,7 @@ static void EmuThreadFunc(GraphicsContext *graphicsContext, std::function<void()
|
||||
// We just call the update/render loop here.
|
||||
g_emuThreadState = EmuThreadState::RUNNING;
|
||||
|
||||
if (!NativeInitGraphics(graphicsContext)) {
|
||||
if (!application->InitGraphics(graphicsContext)) {
|
||||
_assert_msg_(false, "NativeInitGraphics failed, might as well bail");
|
||||
// If this fails, which it normally shouldn't, let's bail.
|
||||
g_emuThreadState = EmuThreadState::QUIT_REQUESTED;
|
||||
@@ -61,7 +61,7 @@ static void EmuThreadFunc(GraphicsContext *graphicsContext, std::function<void()
|
||||
while (g_emuThreadState != EmuThreadState::QUIT_REQUESTED) {
|
||||
// We're here again, so the game quit. Restart Run() which controls the UI.
|
||||
// This way they can load a new game.
|
||||
NativeFrame(graphicsContext);
|
||||
application->Frame(graphicsContext);
|
||||
if (postFrame) {
|
||||
postFrame();
|
||||
}
|
||||
@@ -75,13 +75,13 @@ static void EmuThreadFunc(GraphicsContext *graphicsContext, std::function<void()
|
||||
|
||||
g_emuThreadState = EmuThreadState::STOPPED;
|
||||
|
||||
NativeShutdownGraphics();
|
||||
application->ShutdownGraphics(graphicsContext);
|
||||
INFO_LOG(Log::System, "Leaving emu thread");
|
||||
}
|
||||
|
||||
std::thread EmuThread_Start(GraphicsContext *graphicsContext, std::function<void()> postFrame) {
|
||||
std::thread EmuThread_Start(GraphicsContext *graphicsContext, Application *application, std::function<void()> postFrame) {
|
||||
g_emuThreadState = EmuThreadState::START_REQUESTED;
|
||||
std::thread emuThread = std::thread(&EmuThreadFunc, graphicsContext, postFrame);
|
||||
std::thread emuThread = std::thread(&EmuThreadFunc, graphicsContext, application, postFrame);
|
||||
return emuThread;
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@ void EmuThread_Join(GraphicsContext *graphicsContext, std::thread &emuThread) {
|
||||
emuThread = std::thread();
|
||||
}
|
||||
|
||||
void MainThreadFunc(GraphicsContext *graphicsContext, std::function<void()> postFrame) {
|
||||
void MainThreadFunc(GraphicsContext *graphicsContext, Application *application, std::function<void()> postFrame) {
|
||||
if (graphicsContext->NeedsRenderThread()) {
|
||||
SetCurrentThreadName("RenderThread");
|
||||
// This is now the render thread, and will spawn the emu thread below.
|
||||
@@ -114,7 +114,7 @@ void MainThreadFunc(GraphicsContext *graphicsContext, std::function<void()> post
|
||||
|
||||
g_inLoop = true;
|
||||
|
||||
std::thread emuThread = EmuThread_Start(graphicsContext, postFrame);
|
||||
std::thread emuThread = EmuThread_Start(graphicsContext, application, postFrame);
|
||||
|
||||
graphicsContext->ThreadStart();
|
||||
// This thread becomes the render thread.
|
||||
@@ -144,8 +144,8 @@ void MainThreadFunc(GraphicsContext *graphicsContext, std::function<void()> post
|
||||
std::string error_string;
|
||||
bool success = graphicsContext->InitFromRenderThread(&error_string);
|
||||
|
||||
NativeInitGraphics(graphicsContext);
|
||||
NativeResized();
|
||||
application->InitGraphics(graphicsContext);
|
||||
// NativeResized();
|
||||
|
||||
DEBUG_LOG(Log::Boot, "Done.");
|
||||
|
||||
@@ -155,18 +155,18 @@ void MainThreadFunc(GraphicsContext *graphicsContext, std::function<void()> post
|
||||
while (GetUIState() != UISTATE_EXIT) {
|
||||
// We're here again, so the game quit. Restart Run() which controls the UI.
|
||||
// This way they can load a new game.
|
||||
NativeFrame(graphicsContext);
|
||||
application->Frame(graphicsContext);
|
||||
postFrame();
|
||||
}
|
||||
Core_Stop();
|
||||
|
||||
// Process the shutdown. Without this, non-GL delays 800ms on shutdown.
|
||||
Core_StateProcessed();
|
||||
NativeFrame(graphicsContext);
|
||||
application->Frame(graphicsContext);
|
||||
|
||||
g_inLoop = false;
|
||||
|
||||
NativeShutdownGraphics();
|
||||
application->ShutdownGraphics(graphicsContext);
|
||||
|
||||
graphicsContext->ThreadEnd();
|
||||
graphicsContext->ShutdownFromRenderThread();
|
||||
|
||||
+4
-2
@@ -18,6 +18,8 @@
|
||||
#pragma once
|
||||
#include <functional>
|
||||
|
||||
#include "Common/System/Application.h"
|
||||
|
||||
// Utilities to manage Emu and Render threads.
|
||||
// TODO: Use across platforms, currently Windows-only.
|
||||
|
||||
@@ -28,9 +30,9 @@ 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.
|
||||
void MainThreadFunc(GraphicsContext *graphicsContext, std::function<void()> postFrame);
|
||||
void MainThreadFunc(GraphicsContext * graphicsContext, Application *application, 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.
|
||||
std::thread EmuThread_Start(GraphicsContext *graphicsContext, std::function<void()> postFrame);
|
||||
std::thread EmuThread_Start(GraphicsContext *graphicsContext, Application *application, std::function<void()> postFrame);
|
||||
void EmuThread_Join(GraphicsContext *graphicsContext, std::thread &emuThread);
|
||||
+1
-1
@@ -676,7 +676,7 @@ void MainUI::EmuThreadFunc() {
|
||||
}
|
||||
emuThreadState = (int)EmuThreadState::STOPPED;
|
||||
|
||||
NativeShutdownGraphics();
|
||||
NativeShutdownGraphics(graphicsContext);
|
||||
}
|
||||
|
||||
void MainUI::EmuThreadStart() {
|
||||
|
||||
+3
-2
@@ -2096,7 +2096,8 @@ int main(int argc, char *argv[]) {
|
||||
}
|
||||
EnableFZ();
|
||||
|
||||
std::thread emuThread = EmuThread_Start(graphicsContext, nullptr);
|
||||
NativeApplication application;
|
||||
std::thread emuThread = EmuThread_Start(graphicsContext, &application, nullptr);
|
||||
|
||||
graphicsContext->ThreadStart();
|
||||
|
||||
@@ -2196,7 +2197,7 @@ int main(int argc, char *argv[]) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
emuThread = EmuThread_Start(graphicsContext, nullptr);
|
||||
emuThread = EmuThread_Start(graphicsContext, &application, nullptr);
|
||||
graphicsContext->ThreadStart();
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -953,7 +953,7 @@ bool CreateGlobalPipelines() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void NativeShutdownGraphics() {
|
||||
void NativeShutdownGraphics(GraphicsContext *graphicContext) {
|
||||
INFO_LOG(Log::System, "NativeShutdownGraphics begin");
|
||||
|
||||
if (g_screenManager) {
|
||||
@@ -1032,7 +1032,7 @@ void NativeFrame(GraphicsContext *graphicsContext) {
|
||||
// This can only be accessed from Windows currently, and causes linking errors with headless etc.
|
||||
if (g_restartGraphics == 1) {
|
||||
// Used for debugging only.
|
||||
NativeShutdownGraphics();
|
||||
NativeShutdownGraphics(graphicsContext);
|
||||
g_restartGraphics++;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -101,7 +101,7 @@ PPSSPP_UWPMain::~PPSSPP_UWPMain() {
|
||||
g_InputManager.Shutdown();
|
||||
|
||||
ctx_->GetDrawContext()->HandleEvent(Draw::Event::LOST_BACKBUFFER, 0, 0, nullptr);
|
||||
NativeShutdownGraphics();
|
||||
NativeShutdownGraphics(ctx_.get());
|
||||
NativeShutdown();
|
||||
g_VFS.Clear();
|
||||
|
||||
|
||||
+2
-1
@@ -1261,13 +1261,14 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin
|
||||
System_SetWindowTitle("");
|
||||
|
||||
std::thread mainThread = std::thread([]() {
|
||||
NativeApplication application;
|
||||
std::unique_ptr<GraphicsContext> graphicsContext(CreateGraphicsContextOrExit());
|
||||
if (!graphicsContext) {
|
||||
// We're screwed. Should never get here.
|
||||
_dbg_assert_(false);
|
||||
return;
|
||||
}
|
||||
MainThreadFunc(graphicsContext.get(), []() {});
|
||||
MainThreadFunc(graphicsContext.get(), &application, []() {});
|
||||
PostMessage(MainWindow::GetHWND(), MainWindow::WM_USER_UPDATE_UI, 0, 0);
|
||||
});
|
||||
|
||||
|
||||
@@ -203,7 +203,7 @@ int utimensat(int fd, const char *path, const struct timespec times[2]) {
|
||||
}
|
||||
#endif
|
||||
|
||||
static void ProcessFrameCommands(JNIEnv *env);
|
||||
static void ProcessFrameCommands();
|
||||
|
||||
JNIEnv* getEnv() {
|
||||
JNIEnv *env;
|
||||
@@ -268,7 +268,6 @@ static void EmuThreadFunc() {
|
||||
SetCurrentThreadName("Entering EmuThread");
|
||||
|
||||
AndroidJNIThreadContext jniContext;
|
||||
JNIEnv *env = getEnv(); // TODO: Make it gettable from AndroidJNIThreadContext
|
||||
|
||||
INFO_LOG(Log::System, "Entering emu thread");
|
||||
|
||||
@@ -286,13 +285,13 @@ static void EmuThreadFunc() {
|
||||
emuThreadState = (int)EmuThreadState::RUNNING;
|
||||
while (emuThreadState != (int)EmuThreadState::QUIT_REQUESTED) {
|
||||
NativeFrame(graphicsContext);
|
||||
ProcessFrameCommands(env);
|
||||
ProcessFrameCommands();
|
||||
}
|
||||
|
||||
INFO_LOG(Log::System, "emuThreadState was set to QUIT_REQUESTED, left EmuThreadFunc loop. Setting state to STOPPED.");
|
||||
emuThreadState = (int)EmuThreadState::STOPPED;
|
||||
|
||||
NativeShutdownGraphics();
|
||||
NativeShutdownGraphics(graphicsContext);
|
||||
|
||||
INFO_LOG(Log::System, "Leaving EmuThread");
|
||||
}
|
||||
@@ -723,7 +722,7 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeApp_init
|
||||
SetCurrentThreadName("androidInit");
|
||||
|
||||
// Makes sure we get early permission grants.
|
||||
ProcessFrameCommands(env);
|
||||
ProcessFrameCommands();
|
||||
|
||||
EARLY_LOG("NativeApp.init() -- begin");
|
||||
PROFILE_INIT();
|
||||
@@ -1674,7 +1673,8 @@ extern "C" void JNICALL Java_org_ppsspp_ppsspp_NativeApp_pushCameraImageAndroid(
|
||||
}
|
||||
|
||||
// Call this under frameCommandLock.
|
||||
static void ProcessFrameCommands(JNIEnv *env) {
|
||||
static void ProcessFrameCommands() {
|
||||
JNIEnv *env = getEnv();
|
||||
std::vector<FrameCommand> frameCommands;
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(frameCommandLock);
|
||||
@@ -1789,14 +1789,14 @@ static void VulkanEmuThread(ANativeWindow *wnd) {
|
||||
|
||||
while (!exitRenderLoop) {
|
||||
NativeFrame(graphicsContext);
|
||||
ProcessFrameCommands(env);
|
||||
ProcessFrameCommands();
|
||||
}
|
||||
INFO_LOG(Log::G3D, "Leaving Vulkan main loop.");
|
||||
} else {
|
||||
INFO_LOG(Log::G3D, "Not entering main loop.");
|
||||
}
|
||||
|
||||
NativeShutdownGraphics();
|
||||
NativeShutdownGraphics(graphicsContext);
|
||||
|
||||
renderer_inited = false;
|
||||
graphicsContext->ThreadEnd();
|
||||
|
||||
@@ -134,7 +134,7 @@ void GLRenderLoop(IOSGLESContext *graphicsContext) {
|
||||
}
|
||||
|
||||
INFO_LOG(Log::System, "Emulation thread shutting down\n");
|
||||
NativeShutdownGraphics();
|
||||
NativeShutdownGraphics(graphicsContext);
|
||||
|
||||
// Also ask the main thread to stop, so it doesn't hang waiting for a new frame.
|
||||
INFO_LOG(Log::System, "Emulation thread stopping\n");
|
||||
|
||||
@@ -117,7 +117,7 @@ void IOSVulkanContext::ShutdownFromRenderThread() {
|
||||
}
|
||||
|
||||
void IOSVulkanContext::Shutdown() {
|
||||
INFO_LOG(Log::G3D, "Calling NativeShutdownGraphics");
|
||||
INFO_LOG(Log::G3D, "IOSVulkanContext::Shutdown");
|
||||
g_Vulkan->DestroyDevice();
|
||||
g_Vulkan->DestroyInstance();
|
||||
// We keep the g_Vulkan context around to avoid invalidating a ton of pointers around the app.
|
||||
@@ -243,7 +243,7 @@ void VulkanRenderLoop(IOSVulkanContext *graphicsContext, CAMetalLayer *metalLaye
|
||||
INFO_LOG(Log::G3D, "Not entering main loop.");
|
||||
}
|
||||
|
||||
NativeShutdownGraphics();
|
||||
NativeShutdownGraphics(graphicsContext);
|
||||
|
||||
graphicsContext->ThreadEnd();
|
||||
|
||||
|
||||
Reference in new issue
Block a user