From 15de6e6b988f8fcf3a925af8065cf9eec05e81f0 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 31 Dec 2015 16:59:40 +0100 Subject: [PATCH] GraphicsContext: Abstract away things like swapbuffers etc before adding even more backends. Needed to prevent clutter all over the codebase. Does not go all the way yet, goal would be a common render loop between platforms but not there yet. --- Common/Common.vcxproj | 1 + Common/Common.vcxproj.filters | 1 + Common/GraphicsContext.h | 35 +++++++++++++++++++++++ Core/Core.cpp | 31 ++++++-------------- Core/Core.h | 4 ++- Core/CoreParameter.h | 4 +++ Core/Host.h | 3 +- Core/System.cpp | 3 +- Core/System.h | 1 + GPU/GLES/GLES_GPU.cpp | 9 +++--- GPU/GLES/GLES_GPU.h | 5 +++- GPU/GPU.cpp | 4 +-- GPU/GPU.h | 3 +- UI/HostTypes.h | 2 +- UI/NativeApp.cpp | 29 ++++++------------- Windows/EmuThread.cpp | 10 +++++-- Windows/GPU/D3D9Context.cpp | 17 +++++++---- Windows/GPU/D3D9Context.h | 17 +++++++---- Windows/GPU/WindowsGLContext.cpp | 27 ++++++++++++------ Windows/GPU/WindowsGLContext.h | 26 +++++++++++------ Windows/GPU/WindowsGraphicsContext.h | 10 +++++++ Windows/MainWindow.cpp | 12 ++++---- Windows/PPSSPP.vcxproj | 1 + Windows/PPSSPP.vcxproj.filters | 3 ++ Windows/WindowsHost.cpp | 42 ++++++++++++++++------------ Windows/WindowsHost.h | 11 ++++++-- Windows/main.cpp | 2 +- ext/native/base/NativeApp.h | 6 ++-- ext/native/base/PCMain.cpp | 6 ++-- headless/Headless.cpp | 9 +++--- headless/StubHost.h | 5 ++-- headless/WindowsHeadlessHost.cpp | 5 ++-- headless/WindowsHeadlessHost.h | 2 +- headless/WindowsHeadlessHostDx9.cpp | 21 +++++--------- headless/WindowsHeadlessHostDx9.h | 2 +- ios/ViewController.mm | 2 +- lang | 2 +- unittest/JitHarness.cpp | 2 +- 38 files changed, 230 insertions(+), 145 deletions(-) create mode 100644 Common/GraphicsContext.h create mode 100644 Windows/GPU/WindowsGraphicsContext.h diff --git a/Common/Common.vcxproj b/Common/Common.vcxproj index d93b8d8667..e281462434 100644 --- a/Common/Common.vcxproj +++ b/Common/Common.vcxproj @@ -222,6 +222,7 @@ true true + diff --git a/Common/Common.vcxproj.filters b/Common/Common.vcxproj.filters index 5b2bb42345..ffdd697516 100644 --- a/Common/Common.vcxproj.filters +++ b/Common/Common.vcxproj.filters @@ -57,6 +57,7 @@ GL + diff --git a/Common/GraphicsContext.h b/Common/GraphicsContext.h new file mode 100644 index 0000000000..ded4d4ccd3 --- /dev/null +++ b/Common/GraphicsContext.h @@ -0,0 +1,35 @@ +#pragma once + +#include + +#include "thin3d/thin3d.h" + +// Init is done differently on each platform, and done close to the creation, so it's +// expected to be implemented by subclasses. +class GraphicsContext { +public: + virtual ~GraphicsContext() {} + + virtual void Shutdown() = 0; + virtual void SwapInterval(int interval) = 0; + virtual void SwapBuffers() = 0; + + // Used during window resize. Must be called from the window thread, + // not the rendering thread or CPU thread. + virtual void Pause() {} + virtual void Resume() {} + + virtual void Resize() = 0; + + virtual Thin3DContext *CreateThin3DContext() = 0; +}; + +class DummyGraphicsContext : public GraphicsContext { +public: + void Shutdown() override {} + void SwapInterval(int interval) override {} + void SwapBuffers() override {} + void Resize() override {} + + Thin3DContext *CreateThin3DContext() override { return nullptr; } +}; \ No newline at end of file diff --git a/Core/Core.cpp b/Core/Core.cpp index f27c7dfdf7..2287406e07 100644 --- a/Core/Core.cpp +++ b/Core/Core.cpp @@ -54,6 +54,7 @@ static std::set shutdownFuncs; static bool windowHidden = false; static double lastActivity = 0.0; static double lastKeepAwake = 0.0; +static GraphicsContext *graphicsContext; #ifdef _WIN32 InputState input_state; @@ -163,26 +164,12 @@ void UpdateRunLoop() { } if (GetUIState() != UISTATE_EXIT) { - NativeRender(); + NativeRender(graphicsContext); } } -#if defined(USING_WIN_UI) - -void GPU_SwapBuffers() { - switch (g_Config.iGPUBackend) { - case GPU_BACKEND_OPENGL: - GL_SwapBuffers(); - break; - case GPU_BACKEND_DIRECT3D9: - D3D9_SwapBuffers(); - break; - } -} - -#endif - -void Core_RunLoop() { +void Core_RunLoop(GraphicsContext *ctx) { + graphicsContext = ctx; while ((GetUIState() != UISTATE_INGAME || !PSP_IsInited()) && GetUIState() != UISTATE_EXIT) { time_update(); #if defined(USING_WIN_UI) @@ -196,7 +183,7 @@ void Core_RunLoop() { if (sleepTime > 0) Sleep(sleepTime); if (!windowHidden) { - GPU_SwapBuffers(); + ctx->SwapBuffers(); } #else UpdateRunLoop(); @@ -208,7 +195,7 @@ void Core_RunLoop() { UpdateRunLoop(); #if defined(USING_WIN_UI) if (!windowHidden && !Core_IsStepping()) { - GPU_SwapBuffers(); + ctx->SwapBuffers(); // Keep the system awake for longer than normal for cutscenes and the like. const double now = time_now_d(); @@ -246,7 +233,7 @@ static inline void CoreStateProcessed() { } // Some platforms, like Android, do not call this function but handle things on their own. -void Core_Run() +void Core_Run(GraphicsContext *ctx) { #if defined(_DEBUG) host->UpdateDisassembly(); @@ -261,7 +248,7 @@ reswitch: if (GetUIState() == UISTATE_EXIT) { return; } - Core_RunLoop(); + Core_RunLoop(ctx); #if defined(USING_QT_UI) && !defined(MOBILE_DEVICE) return; #else @@ -273,7 +260,7 @@ reswitch: { case CORE_RUNNING: // enter a fast runloop - Core_RunLoop(); + Core_RunLoop(ctx); break; // We should never get here on Android. diff --git a/Core/Core.h b/Core/Core.h index 839a63dacf..afda12b26a 100644 --- a/Core/Core.h +++ b/Core/Core.h @@ -20,9 +20,11 @@ #include "Core/System.h" #include "Core/CoreParameter.h" +class GraphicsContext; + // called from emu thread void UpdateRunLoop(); -void Core_Run(); +void Core_Run(GraphicsContext *ctx); void Core_Stop(); void Core_ErrorPause(); // called from gui diff --git a/Core/CoreParameter.h b/Core/CoreParameter.h index d99d0ea94a..0b60f84189 100644 --- a/Core/CoreParameter.h +++ b/Core/CoreParameter.h @@ -35,11 +35,15 @@ enum GPUCore { class FileLoader; +class GraphicsContext; + // PSP_CoreParameter() struct CoreParameter { CoreParameter() : collectEmuLog(0), unthrottle(false), fpsLimit(0), updateRecent(true), freezeNext(false), frozen(false), mountIsoLoader(nullptr) {} + CPUCore cpuCore; GPUCore gpuCore; + GraphicsContext *graphicsContext; // TODO: Find a better place. bool enableSound; // there aren't multiple sound cores. std::string fileToStart; diff --git a/Core/Host.h b/Core/Host.h index bd0993da68..6395769ff1 100644 --- a/Core/Host.h +++ b/Core/Host.h @@ -21,6 +21,7 @@ #include "Common/CommonTypes.h" struct InputState; +class GraphicsContext; // TODO: Whittle this down. Collecting a bunch of random stuff like this isn't good design :P class Host { @@ -33,7 +34,7 @@ public: virtual void SetDebugMode(bool mode) { } - virtual bool InitGraphics(std::string *error_string) = 0; + virtual bool InitGraphics(std::string *error_string, GraphicsContext **ctx) = 0; virtual void ShutdownGraphics() = 0; virtual void InitSound() = 0; diff --git a/Core/System.cpp b/Core/System.cpp index e548e8e75a..a228b9308e 100644 --- a/Core/System.cpp +++ b/Core/System.cpp @@ -360,6 +360,7 @@ void System_Wake() { static bool pspIsInited = false; static bool pspIsIniting = false; static bool pspIsQuiting = false; +// Ugly! bool PSP_InitStart(const CoreParameter &coreParam, std::string *error_string) { if (pspIsIniting || pspIsQuiting) { @@ -407,7 +408,7 @@ bool PSP_InitUpdate(std::string *error_string) { bool success = coreParameter.fileToStart != ""; *error_string = coreParameter.errorString; if (success) { - success = GPU_Init(); + success = GPU_Init(coreParameter.graphicsContext); if (!success) { PSP_Shutdown(); *error_string = "Unable to initialize rendering engine."; diff --git a/Core/System.h b/Core/System.h index 806b85bf95..b32a14b26a 100644 --- a/Core/System.h +++ b/Core/System.h @@ -47,6 +47,7 @@ enum PSPDirectories { DIRECTORY_CACHE, }; +class GraphicsContext; void UpdateUIState(GlobalUIState newState); GlobalUIState GetUIState(); diff --git a/GPU/GLES/GLES_GPU.cpp b/GPU/GLES/GLES_GPU.cpp index 9c434c7f21..152d14a6be 100644 --- a/GPU/GLES/GLES_GPU.cpp +++ b/GPU/GLES/GLES_GPU.cpp @@ -19,6 +19,7 @@ #include "profiler/profiler.h" #include "Common/ChunkFile.h" +#include "Common/GraphicsContext.h" #include "Core/Config.h" #include "Core/Debugger/Breakpoints.h" @@ -394,8 +395,8 @@ static const CommandTableEntry commandTable[] = { GLES_GPU::CommandInfo GLES_GPU::cmdInfo_[256]; -GLES_GPU::GLES_GPU() -: resized_(false) { +GLES_GPU::GLES_GPU(GraphicsContext *ctx) +: resized_(false), gfxCtx_(ctx) { UpdateVsyncInterval(true); CheckGPUFeatures(); @@ -466,7 +467,7 @@ GLES_GPU::~GLES_GPU() { shaderManager_ = nullptr; #ifdef _WIN32 - GL_SwapInterval(0); + gfxCtx_->SwapInterval(0); #endif } @@ -674,7 +675,7 @@ inline void GLES_GPU::UpdateVsyncInterval(bool force) { // // See http://developer.download.nvidia.com/opengl/specs/WGL_EXT_swap_control_tear.txt // glstate.SetVSyncInterval(-desiredVSyncInterval); //} else { - GL_SwapInterval(desiredVSyncInterval); + gfxCtx_->SwapInterval(desiredVSyncInterval); //} lastVsync_ = desiredVSyncInterval; } diff --git a/GPU/GLES/GLES_GPU.h b/GPU/GLES/GLES_GPU.h index 2df770bad6..5c858a9523 100644 --- a/GPU/GLES/GLES_GPU.h +++ b/GPU/GLES/GLES_GPU.h @@ -30,10 +30,11 @@ class ShaderManager; class LinkedShader; +class GraphicsContext; class GLES_GPU : public GPUCommon { public: - GLES_GPU(); + GLES_GPU(GraphicsContext *gfxCtx); ~GLES_GPU(); // This gets called on startup and when we get back from settings. @@ -192,4 +193,6 @@ private: std::string reportingPrimaryInfo_; std::string reportingFullInfo_; + + GraphicsContext *gfxCtx_; }; diff --git a/GPU/GPU.cpp b/GPU/GPU.cpp index f4f4a54f6e..f9a3d0ea6f 100644 --- a/GPU/GPU.cpp +++ b/GPU/GPU.cpp @@ -38,13 +38,13 @@ static void SetGPU(T *obj) { gpuDebug = obj; } -bool GPU_Init() { +bool GPU_Init(GraphicsContext *ctx) { switch (PSP_CoreParameter().gpuCore) { case GPU_NULL: SetGPU(new NullGPU()); break; case GPU_GLES: - SetGPU(new GLES_GPU()); + SetGPU(new GLES_GPU(ctx)); break; case GPU_SOFTWARE: SetGPU(new SoftGPU()); diff --git a/GPU/GPU.h b/GPU/GPU.h index b98c30e67b..0849ab8cbc 100644 --- a/GPU/GPU.h +++ b/GPU/GPU.h @@ -22,6 +22,7 @@ class GPUInterface; class GPUDebugInterface; +class GraphicsContext; enum SkipDrawReasonFlags { SKIPDRAW_SKIPFRAME = 1, @@ -103,6 +104,6 @@ extern GPUStatistics gpuStats; extern GPUInterface *gpu; extern GPUDebugInterface *gpuDebug; -bool GPU_Init(); +bool GPU_Init(GraphicsContext *ctx); void GPU_Shutdown(); void GPU_Reinitialize(); diff --git a/UI/HostTypes.h b/UI/HostTypes.h index f27a95aeec..e679f594a5 100644 --- a/UI/HostTypes.h +++ b/UI/HostTypes.h @@ -37,7 +37,7 @@ public: void SetDebugMode(bool mode) override { } - bool InitGraphics(std::string *error_message) override { return true; } + bool InitGraphics(std::string *error_message, GraphicsContext **ctx) override { return true; } void ShutdownGraphics() override {} void InitSound() override; diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index ae073621e0..5c9d9fb4e7 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -506,20 +506,8 @@ void NativeInit(int argc, const char *argv[], } } -void NativeInitGraphics() { -#ifndef _WIN32 - // Force backend to GL - g_Config.iGPUBackend = GPU_BACKEND_OPENGL; -#endif - - if (g_Config.iGPUBackend == GPU_BACKEND_OPENGL) { - thin3d = T3DCreateGLContext(); - CheckGLExtensions(); - } else { -#ifdef _WIN32 - thin3d = D3D9_CreateThin3DContext(); -#endif - } +void NativeInitGraphics(GraphicsContext *graphicsContext) { + thin3d = graphicsContext->CreateThin3DContext(); ui_draw2d.SetAtlas(&ui_atlas); ui_draw2d_front.SetAtlas(&ui_atlas); @@ -692,7 +680,7 @@ void DrawDownloadsOverlay(UIContext &dc) { dc.Flush(); } -void NativeRender() { +void NativeRender(GraphicsContext *graphicsContext) { g_GameManager.Update(); float xres = dp_xres; @@ -725,17 +713,16 @@ void NativeRender() { if (resized) { resized = false; - if (g_Config.iGPUBackend == GPU_BACKEND_DIRECT3D9) { -#ifdef _WIN32 - D3D9_Resize(0); -#endif - } else if (g_Config.iGPUBackend == GPU_BACKEND_OPENGL) { + + graphicsContext->Resize(); + // TODO: Move this to new GraphicsContext objects for each backend. #ifndef _WIN32 + if (g_Config.iGPUBackend == GPU_BACKEND_OPENGL) { PSP_CoreParameter().pixelWidth = pixel_xres; PSP_CoreParameter().pixelHeight = pixel_yres; NativeMessageReceived("gpu resized", ""); -#endif } +#endif } } diff --git a/Windows/EmuThread.cpp b/Windows/EmuThread.cpp index 2ad173e793..40f32028b2 100644 --- a/Windows/EmuThread.cpp +++ b/Windows/EmuThread.cpp @@ -117,8 +117,10 @@ unsigned int WINAPI TheThread(void *) host->UpdateUI(); + GraphicsContext *graphicsContext; + std::string error_string; - if (!host->InitGraphics(&error_string)) { + if (!host->InitGraphics(&error_string, &graphicsContext)) { I18NCategory *err = GetI18NCategory("Error"); Reporting::ReportMessage("Graphics init error: %s", error_string.c_str()); @@ -154,7 +156,9 @@ unsigned int WINAPI TheThread(void *) ExitProcess(1); } - NativeInitGraphics(); + PSP_CoreParameter().graphicsContext = graphicsContext; + + NativeInitGraphics(graphicsContext); NativeResized(); INFO_LOG(BOOT, "Done."); @@ -179,7 +183,7 @@ unsigned int WINAPI TheThread(void *) if (!Core_IsActive()) UpdateUIState(UISTATE_MENU); - Core_Run(); + Core_Run(graphicsContext); } shutdown: diff --git a/Windows/GPU/D3D9Context.cpp b/Windows/GPU/D3D9Context.cpp index 957a6b479f..78c8ac7bad 100644 --- a/Windows/GPU/D3D9Context.cpp +++ b/Windows/GPU/D3D9Context.cpp @@ -16,6 +16,7 @@ #include "thin3d/thin3d.h" #include "thin3d/d3dx9_loader.h" +// TODO: Move these into the context class. static bool has9Ex = false; static LPDIRECT3D9 d3d; static LPDIRECT3D9EX d3dEx; @@ -28,7 +29,8 @@ static HWND hWnd; // Holds Our Window Handle static D3DPRESENT_PARAMETERS pp; static HMODULE hD3D9; -void D3D9_SwapBuffers() { + +void D3D9Context::SwapBuffers() { if (has9Ex) { deviceEx->EndScene(); deviceEx->PresentEx(NULL, NULL, NULL, NULL, 0); @@ -40,7 +42,7 @@ void D3D9_SwapBuffers() { } } -Thin3DContext *D3D9_CreateThin3DContext() { +Thin3DContext *D3D9Context::CreateThin3DContext() { return T3DCreateDX9Context(d3d, d3dEx, adapterId, device, deviceEx); } @@ -61,7 +63,12 @@ static void GetRes(int &xres, int &yres) { yres = rc.bottom - rc.top; } -bool D3D9_Init(HWND wnd, bool windowed, std::string *error_message) { +void D3D9Context::SwapInterval(int interval) { + // Dummy +} + +bool D3D9Context::Init(HINSTANCE hInst, HWND wnd, std::string *error_message) { + bool windowed = true; hWnd = wnd; DIRECT3DCREATE9EX g_pfnCreate9ex; @@ -195,7 +202,7 @@ bool D3D9_Init(HWND wnd, bool windowed, std::string *error_message) { return true; } -void D3D9_Resize(HWND window) { +void D3D9Context::Resize() { // This should only be called from the emu thread. int xres, yres; @@ -218,7 +225,7 @@ void D3D9_Resize(HWND window) { } } -void D3D9_Shutdown() { +void D3D9Context::Shutdown() { DX9::DestroyShaders(); DX9::fbo_shutdown(); device->EndScene(); diff --git a/Windows/GPU/D3D9Context.h b/Windows/GPU/D3D9Context.h index 470aac96a4..876fb5850e 100644 --- a/Windows/GPU/D3D9Context.h +++ b/Windows/GPU/D3D9Context.h @@ -3,12 +3,19 @@ #pragma once #include "Common/CommonWindows.h" +#include "Windows/GPU/WindowsGraphicsContext.h" class Thin3DContext; -bool D3D9_Init(HWND window, bool windowed, std::string *error_message); -void D3D9_Shutdown(); -void D3D9_Resize(HWND window); -void D3D9_SwapBuffers(); +class D3D9Context : public WindowsGraphicsContext { +public: + bool Init(HINSTANCE hInst, HWND window, std::string *error_message) override; + void Shutdown() override; + void SwapInterval(int interval) override; + void SwapBuffers() override; + + void Resize() override; + + Thin3DContext *CreateThin3DContext() override; +}; -Thin3DContext *D3D9_CreateThin3DContext(); \ No newline at end of file diff --git a/Windows/GPU/WindowsGLContext.cpp b/Windows/GPU/WindowsGLContext.cpp index 21b6a19a17..953173d6d7 100644 --- a/Windows/GPU/WindowsGLContext.cpp +++ b/Windows/GPU/WindowsGLContext.cpp @@ -41,8 +41,8 @@ static HANDLE resumeEvent; static int xres, yres; -void GL_SwapBuffers() { - SwapBuffers(hDC); +void WindowsGLContext::SwapBuffers() { + ::SwapBuffers(hDC); // Used during fullscreen switching to prevent rendering. if (pauseRequested) { @@ -60,7 +60,7 @@ void GL_SwapBuffers() { // glFinish(); } -void GL_Pause() { +void WindowsGLContext::Pause() { if (!hRC) { return; } @@ -73,7 +73,7 @@ void GL_Pause() { // OK, we now know the rendering thread is paused. } -void GL_Resume() { +void WindowsGLContext::Resume() { if (!hRC) { return; } @@ -153,7 +153,7 @@ void DebugCallbackARB(GLenum source, GLenum type, GLuint id, GLenum severity, } } -bool GL_Init(HWND window, std::string *error_message) { +bool WindowsGLContext::Init(HINSTANCE hInst, HWND window, std::string *error_message) { *error_message = "ok"; hWnd = window; GLuint PixelFormat; @@ -320,7 +320,7 @@ bool GL_Init(HWND window, std::string *error_message) { hRC = m_hrc; - GL_SwapInterval(0); + SwapInterval(0); if (g_Config.bGfxDebugOutput) { if (wglewIsSupported("GL_KHR_debug") == 1) { @@ -361,13 +361,13 @@ bool GL_Init(HWND window, std::string *error_message) { return true; // Success } -void GL_SwapInterval(int interval) { +void WindowsGLContext::SwapInterval(int interval) { // glew loads wglSwapIntervalEXT if available if (wglSwapIntervalEXT) wglSwapIntervalEXT(interval); } -void GL_Shutdown() { +void WindowsGLContext::Shutdown() { CloseHandle(pauseEvent); CloseHandle(resumeEvent); if (hRC) { @@ -392,3 +392,14 @@ void GL_Shutdown() { } hWnd = NULL; } + +void WindowsGLContext::Resize() { +} + +Thin3DContext *WindowsGLContext::CreateThin3DContext() { + Thin3DContext *ctx = T3DCreateGLContext(); + if (ctx) { + CheckGLExtensions(); + } + return ctx; +} diff --git a/Windows/GPU/WindowsGLContext.h b/Windows/GPU/WindowsGLContext.h index 583186aa93..0581b87cfa 100644 --- a/Windows/GPU/WindowsGLContext.h +++ b/Windows/GPU/WindowsGLContext.h @@ -1,13 +1,23 @@ #pragma once #include "Common/CommonWindows.h" +#include "Windows/GPU/WindowsGraphicsContext.h" -bool GL_Init(HWND window, std::string *error_message); -void GL_Shutdown(); -void GL_SwapInterval(int interval); -void GL_SwapBuffers(); +class Thin3DContext; -// Used during window resize. Must be called from the window thread, -// not the rendering thread or CPU thread. -void GL_Pause(); -void GL_Resume(); \ No newline at end of file +class WindowsGLContext : public WindowsGraphicsContext { +public: + bool Init(HINSTANCE hInst, HWND window, std::string *error_message) override; + void Shutdown() override; + void SwapInterval(int interval) override; + void SwapBuffers() override; + + // Used during window resize. Must be called from the window thread, + // not the rendering thread or CPU thread. + void Pause() override; + void Resume() override; + + void Resize() override; + + Thin3DContext *CreateThin3DContext() override; +}; diff --git a/Windows/GPU/WindowsGraphicsContext.h b/Windows/GPU/WindowsGraphicsContext.h new file mode 100644 index 0000000000..db022e9b5d --- /dev/null +++ b/Windows/GPU/WindowsGraphicsContext.h @@ -0,0 +1,10 @@ +#pragma once + +#include "Common/GraphicsContext.h" +#include "Common/CommonWindows.h" + +class WindowsGraphicsContext : public GraphicsContext { +public: + virtual bool Init(HINSTANCE hInst, HWND window, std::string *error_message) = 0; +}; + diff --git a/Windows/MainWindow.cpp b/Windows/MainWindow.cpp index 1c5e12b5f0..d6b54d78b2 100644 --- a/Windows/MainWindow.cpp +++ b/Windows/MainWindow.cpp @@ -288,12 +288,10 @@ namespace MainWindow } void ToggleFullscreen(HWND hWnd, bool goingFullscreen) { + GraphicsContext *graphicsContext = PSP_CoreParameter().graphicsContext; // Make sure no rendering is happening during the switch. - - bool isOpenGL = g_Config.iGPUBackend == GPU_BACKEND_OPENGL; - - if (isOpenGL) { - GL_Pause(); + if (graphicsContext) { + graphicsContext->Pause(); } int oldWindowState = g_WindowState; @@ -355,8 +353,8 @@ namespace MainWindow WindowsRawInput::NotifyMenu(); - if (isOpenGL) { - GL_Resume(); + if (graphicsContext) { + graphicsContext->Resume(); } } diff --git a/Windows/PPSSPP.vcxproj b/Windows/PPSSPP.vcxproj index 4f1ff2e4a7..05cade844d 100644 --- a/Windows/PPSSPP.vcxproj +++ b/Windows/PPSSPP.vcxproj @@ -368,6 +368,7 @@ + diff --git a/Windows/PPSSPP.vcxproj.filters b/Windows/PPSSPP.vcxproj.filters index 9bdd231c22..4bf680c53f 100644 --- a/Windows/PPSSPP.vcxproj.filters +++ b/Windows/PPSSPP.vcxproj.filters @@ -275,6 +275,9 @@ Windows\System + + Windows\System + diff --git a/Windows/WindowsHost.cpp b/Windows/WindowsHost.cpp index c0b2770c33..ad9107db8d 100644 --- a/Windows/WindowsHost.cpp +++ b/Windows/WindowsHost.cpp @@ -63,15 +63,13 @@ static const int numCPUs = 1; float mouseDeltaX = 0; float mouseDeltaY = 0; -static BOOL PostDialogMessage(Dialog *dialog, UINT message, WPARAM wParam = 0, LPARAM lParam = 0) -{ +static BOOL PostDialogMessage(Dialog *dialog, UINT message, WPARAM wParam = 0, LPARAM lParam = 0) { return PostMessage(dialog->GetDlgHandle(), message, wParam, lParam); } -WindowsHost::WindowsHost(HWND mainWindow, HWND displayWindow) +WindowsHost::WindowsHost(HINSTANCE hInstance, HWND mainWindow, HWND displayWindow) + : gfx_(nullptr), hInstance_(hInstance), mainWindow_(mainWindow), displayWindow_(displayWindow) { - mainWindow_ = mainWindow; - displayWindow_ = displayWindow; mouseDeltaX = 0; mouseDeltaY = 0; @@ -97,33 +95,41 @@ void WindowsHost::SetConsolePosition() { void WindowsHost::UpdateConsolePosition() { RECT rc; HWND console = GetConsoleWindow(); - if (console != NULL && GetWindowRect(console, &rc) && !IsIconic(console)) - { + if (console != NULL && GetWindowRect(console, &rc) && !IsIconic(console)) { g_Config.iConsoleWindowX = rc.left; g_Config.iConsoleWindowY = rc.top; } } -bool WindowsHost::InitGraphics(std::string *error_message) { +bool WindowsHost::InitGraphics(std::string *error_message, GraphicsContext **ctx) { + WindowsGraphicsContext *graphicsContext = nullptr; switch (g_Config.iGPUBackend) { case GPU_BACKEND_OPENGL: - return GL_Init(displayWindow_, error_message); + graphicsContext = new WindowsGLContext(); + break; case GPU_BACKEND_DIRECT3D9: - return D3D9_Init(displayWindow_, true, error_message); + graphicsContext = new D3D9Context(); + break; default: return false; } + + if (graphicsContext->Init(hInstance_, displayWindow_, error_message)) { + *ctx = graphicsContext; + gfx_ = graphicsContext; + return true; + } else { + delete graphicsContext; + *ctx = nullptr; + gfx_ = nullptr; + return false; + } } void WindowsHost::ShutdownGraphics() { - switch (g_Config.iGPUBackend) { - case GPU_BACKEND_OPENGL: - GL_Shutdown(); - break; - case GPU_BACKEND_DIRECT3D9: - D3D9_Shutdown(); - break; - } + gfx_->Shutdown(); + delete gfx_; + gfx_ = nullptr; PostMessage(mainWindow_, WM_CLOSE, 0, 0); } diff --git a/Windows/WindowsHost.h b/Windows/WindowsHost.h index fa861aa68a..ed00d060f0 100644 --- a/Windows/WindowsHost.h +++ b/Windows/WindowsHost.h @@ -24,9 +24,11 @@ extern float mouseDeltaX; extern float mouseDeltaY; +class GraphicsContext; + class WindowsHost : public Host { public: - WindowsHost(HWND mainWindow, HWND displayWindow); + WindowsHost(HINSTANCE hInstance, HWND mainWindow, HWND displayWindow); ~WindowsHost() { UpdateConsolePosition(); @@ -37,7 +39,8 @@ public: void UpdateUI() override; void SetDebugMode(bool mode) override; - bool InitGraphics(std::string *error_message) override; + // If returns false, will return a null context + bool InitGraphics(std::string *error_message, GraphicsContext **ctx) override; void PollControllers(InputState &input_state) override; void ShutdownGraphics() override; @@ -65,12 +68,16 @@ public: std::shared_ptr keyboard; + GraphicsContext *GetGraphicsContext() { return gfx_; } + private: void SetConsolePosition(); void UpdateConsolePosition(); + HINSTANCE hInstance_; HWND displayWindow_; HWND mainWindow_; + GraphicsContext *gfx_; std::list> input; }; diff --git a/Windows/main.cpp b/Windows/main.cpp index 52c37476e6..6cbe20f783 100644 --- a/Windows/main.cpp +++ b/Windows/main.cpp @@ -529,7 +529,7 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin DialogManager::AddDlg(vfpudlg = new CVFPUDlg(_hInstance, hwndMain, currentDebugMIPS)); - host = new WindowsHost(hwndMain, hwndDisplay); + host = new WindowsHost(_hInstance, hwndMain, hwndDisplay); host->SetWindowTitle(0); MainWindow::CreateDebugWindows(); diff --git a/ext/native/base/NativeApp.h b/ext/native/base/NativeApp.h index c927ba5659..daa5a8cbba 100644 --- a/ext/native/base/NativeApp.h +++ b/ext/native/base/NativeApp.h @@ -14,6 +14,8 @@ struct TouchInput; struct KeyInput; struct AxisInput; +class GraphicsContext; + enum SystemPermission { SYSTEM_PERMISSION_STORAGE, }; @@ -48,7 +50,7 @@ void NativeInit(int argc, const char *argv[], const char *savegame_directory, co // Runs after NativeInit() at some point. May (and probably should) call OpenGL. // Should not initialize anything screen-size-dependent - do that in NativeResized. -void NativeInitGraphics(); +void NativeInitGraphics(GraphicsContext *graphicsContext); // Signals that you need to destroy and recreate all buffered OpenGL resources, // like textures, vbo etc. @@ -73,7 +75,7 @@ bool NativeAxis(const AxisInput &axis); // Called when it's time to render. If the device can keep up, this // will also be called sixty times per second. Main thread. -void NativeRender(); +void NativeRender(GraphicsContext *graphicsContext); // This should render num_samples 44khz stereo samples. // Try not to make too many assumptions on the granularity diff --git a/ext/native/base/PCMain.cpp b/ext/native/base/PCMain.cpp index e3f79b92f2..f64b0a0c71 100644 --- a/ext/native/base/PCMain.cpp +++ b/ext/native/base/PCMain.cpp @@ -41,15 +41,13 @@ SDLJoystick *joystick = NULL; #include "util/text/utf8.h" #include "math/math_util.h" -#ifdef PPSSPP -// Bad: PPSSPP includes from native #include "Core/System.h" #include "Core/Core.h" #include "Core/Config.h" +#include "Common/GraphicsContext.h" GlobalUIState lastUIState = UISTATE_MENU; GlobalUIState GetUIState(); -#endif static SDL_Window* g_Screen = NULL; static bool g_ToggleFullScreenNextFrame = false; @@ -622,6 +620,8 @@ int main(int argc, char *argv[]) { printf("Virtual pixels: %i x %i\n", dp_xres, dp_yres); NativeInitGraphics(); + GraphicsContext *gfx = new DummyGraphicsContext(); + NativeResized(); SDL_AudioSpec fmt, ret_fmt; diff --git a/headless/Headless.cpp b/headless/Headless.cpp index b3c0114ce9..8406f5109c 100644 --- a/headless/Headless.cpp +++ b/headless/Headless.cpp @@ -72,7 +72,7 @@ void D3D9_SwapBuffers() { } void GL_SwapBuffers() { } void GL_SwapInterval(int) { } void NativeUpdate(InputState &input_state) { } -void NativeRender() { } +void NativeRender(GraphicsContext *graphicsContext) { } void NativeResized() { } void NativeMessageReceived(const char *message, const char *value) {} @@ -299,15 +299,16 @@ int main(int argc, const char* argv[]) host = headlessHost; std::string error_string; - bool glWorking = host->InitGraphics(&error_string); + + GraphicsContext *graphicsContext; + bool glWorking = host->InitGraphics(&error_string, &graphicsContext); LogManager::Init(); LogManager *logman = LogManager::GetInstance(); PrintfLogger *printfLogger = new PrintfLogger(); - for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; i++) - { + for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; i++) { LogTypes::LOG_TYPE type = (LogTypes::LOG_TYPE)i; logman->SetEnable(type, fullLog); logman->SetLogLevel(type, LogTypes::LDEBUG); diff --git a/headless/StubHost.h b/headless/StubHost.h index 3e19dd83ab..d12ca57099 100644 --- a/headless/StubHost.h +++ b/headless/StubHost.h @@ -21,8 +21,7 @@ #include "Core/Debugger/SymbolMap.h" // TODO: Get rid of this junk -class HeadlessHost : public Host -{ +class HeadlessHost : public Host { public: void UpdateUI() override {} @@ -31,7 +30,7 @@ public: void SetDebugMode(bool mode) { } - bool InitGraphics(std::string *error_message) override {return false;} + bool InitGraphics(std::string *error_message, GraphicsContext **ctx) override {return false;} void ShutdownGraphics() override {} void InitSound() override {} diff --git a/headless/WindowsHeadlessHost.cpp b/headless/WindowsHeadlessHost.cpp index 7185ae1a0e..7b07b0201a 100644 --- a/headless/WindowsHeadlessHost.cpp +++ b/headless/WindowsHeadlessHost.cpp @@ -140,7 +140,7 @@ void WindowsHeadlessHost::SetComparisonScreenshot(const std::string &filename) comparisonScreenshot = filename; } -bool WindowsHeadlessHost::InitGraphics(std::string *error_message) +bool WindowsHeadlessHost::InitGraphics(std::string *error_message, GraphicsContext **graphicsContext) { hWnd = CreateHiddenWindow(); @@ -169,13 +169,14 @@ bool WindowsHeadlessHost::InitGraphics(std::string *error_message) ENFORCE(hRC = wglCreateContext(hDC), "Unable to create GL context."); ENFORCE(wglMakeCurrent(hDC, hRC), "Unable to activate GL context."); - GL_SwapInterval(0); + // GL_SwapInterval(0); glewInit(); CheckGLExtensions(); LoadNativeAssets(); + *graphicsContext = new DummyGraphicsContext(); return ResizeGL(); } diff --git a/headless/WindowsHeadlessHost.h b/headless/WindowsHeadlessHost.h index e5c70f2690..7e968fb9fb 100644 --- a/headless/WindowsHeadlessHost.h +++ b/headless/WindowsHeadlessHost.h @@ -28,7 +28,7 @@ class WindowsHeadlessHost : public HeadlessHost { public: - virtual bool InitGraphics(std::string *error_message) override; + virtual bool InitGraphics(std::string *error_message, GraphicsContext **ctx) override; virtual void ShutdownGraphics() override; virtual void SwapBuffers() override; diff --git a/headless/WindowsHeadlessHostDx9.cpp b/headless/WindowsHeadlessHostDx9.cpp index 4fbb57021f..b110d69a7a 100644 --- a/headless/WindowsHeadlessHostDx9.cpp +++ b/headless/WindowsHeadlessHostDx9.cpp @@ -33,8 +33,7 @@ const bool WINDOW_VISIBLE = false; const int WINDOW_WIDTH = 480; const int WINDOW_HEIGHT = 272; -HWND DxCreateWindow() -{ +HWND DxCreateWindow() { static WNDCLASSEX wndClass = { sizeof(WNDCLASSEX), CS_HREDRAW | CS_VREDRAW | CS_OWNDC, @@ -58,13 +57,12 @@ HWND DxCreateWindow() return CreateWindowEx(0, _T("PPSSPPHeadless"), _T("PPSSPPHeadless"), style, CW_USEDEFAULT, CW_USEDEFAULT, wr.right - wr.left, wr.bottom - wr.top, NULL, NULL, NULL, NULL); } -bool WindowsHeadlessHostDx9::InitGraphics(std::string *error_message) -{ +bool WindowsHeadlessHostDx9::InitGraphics(std::string *error_message, GraphicsContext **graphicsContext) { + *graphicsContext = nullptr; LoadD3DX9Dynamic(); hWnd = DxCreateWindow(); - if (WINDOW_VISIBLE) - { + if (WINDOW_VISIBLE) { ShowWindow(hWnd, TRUE); SetFocus(hWnd); } @@ -72,15 +70,13 @@ bool WindowsHeadlessHostDx9::InitGraphics(std::string *error_message) DX9::DirectxInit(hWnd); LoadNativeAssets(); - DX9::pD3Ddevice->BeginScene(); return true; } -void WindowsHeadlessHostDx9::ShutdownGraphics() -{ +void WindowsHeadlessHostDx9::ShutdownGraphics() { DX9::DestroyShaders(); DX9::fbo_shutdown(); DX9::pD3Ddevice->EndScene(); @@ -89,14 +85,11 @@ void WindowsHeadlessHostDx9::ShutdownGraphics() hWnd = NULL; } -bool WindowsHeadlessHostDx9::ResizeGL() -{ - +bool WindowsHeadlessHostDx9::ResizeGL() { return true; } -void WindowsHeadlessHostDx9::SwapBuffers() -{ +void WindowsHeadlessHostDx9::SwapBuffers() { MSG msg; PeekMessage(&msg, NULL, 0, 0, PM_REMOVE); TranslateMessage(&msg); diff --git a/headless/WindowsHeadlessHostDx9.h b/headless/WindowsHeadlessHostDx9.h index ea41e64db6..29966ec756 100644 --- a/headless/WindowsHeadlessHostDx9.h +++ b/headless/WindowsHeadlessHostDx9.h @@ -29,7 +29,7 @@ class WindowsHeadlessHostDx9 : public WindowsHeadlessHost { public: - bool InitGraphics(std::string *error_message) override; + bool InitGraphics(std::string *error_message, GraphicsContext **graphicsContext) override; void ShutdownGraphics() override; void SwapBuffers() override; diff --git a/ios/ViewController.mm b/ios/ViewController.mm index ac2131394f..4f76d92af4 100644 --- a/ios/ViewController.mm +++ b/ios/ViewController.mm @@ -247,7 +247,7 @@ ViewController* sharedViewController; EndInputState(&input_state); } - NativeRender(); + NativeRender(NULL); time_update(); } diff --git a/lang b/lang index 9900b0978a..84fd93497b 160000 --- a/lang +++ b/lang @@ -1 +1 @@ -Subproject commit 9900b0978a3e51dfe8d58cd86c6a58d3a0135580 +Subproject commit 84fd93497b9718a89ac04edfe9636b0f90943505 diff --git a/unittest/JitHarness.cpp b/unittest/JitHarness.cpp index 1a1e1f9804..e8c2da2e15 100644 --- a/unittest/JitHarness.cpp +++ b/unittest/JitHarness.cpp @@ -36,7 +36,7 @@ struct InputState; void D3D9_SwapBuffers() { } void GL_SwapBuffers() { } void NativeUpdate(InputState &input_state) { } -void NativeRender() { } +void NativeRender(GraphicsContext *graphicsContext) { } void NativeResized() { } void System_SendMessage(const char *command, const char *parameter) {}