From c10a3e71607d4a85d2eb5a54adfa3a1918fa27ca Mon Sep 17 00:00:00 2001 From: wheremyfoodat <44909372+wheremyfoodat@users.noreply.github.com> Date: Sun, 1 Oct 2023 16:28:14 +0300 Subject: [PATCH] Make emulator output size properly configurable --- include/PICA/gpu.hpp | 3 +++ include/emulator.hpp | 2 ++ include/panda_qt/screen.hpp | 4 ++++ include/renderer.hpp | 10 ++++++++++ src/core/renderer_gl/renderer_gl.cpp | 2 +- src/emulator.cpp | 12 ++++++------ src/panda_qt/main_window.cpp | 1 + src/panda_qt/screen.cpp | 3 +++ 8 files changed, 30 insertions(+), 7 deletions(-) diff --git a/include/PICA/gpu.hpp b/include/PICA/gpu.hpp index f35b1254..d8f5ab19 100644 --- a/include/PICA/gpu.hpp +++ b/include/PICA/gpu.hpp @@ -113,6 +113,9 @@ class GPU { u32 readInternalReg(u32 index); void writeInternalReg(u32 index, u32 value, u32 mask); + // Used for setting the size of the window we'll be outputting graphics to + void setOutputSize(u32 width, u32 height) { renderer->setOutputSize(width, height); } + // TODO: Emulate the transfer engine & its registers // Then this can be emulated by just writing the appropriate values there void clearBuffer(u32 startAddress, u32 endAddress, u32 value, u32 control) { renderer->clearBuffer(startAddress, endAddress, value, control); } diff --git a/include/emulator.hpp b/include/emulator.hpp index 91fa02a0..4a5fab75 100644 --- a/include/emulator.hpp +++ b/include/emulator.hpp @@ -120,5 +120,7 @@ class Emulator { void initGraphicsContext() { gpu.initGraphicsContext(window); } #endif + void setOutputSize(u32 width, u32 height) { gpu.setOutputSize(width, height); } + EmulatorConfig& getConfig() { return config; } }; diff --git a/include/panda_qt/screen.hpp b/include/panda_qt/screen.hpp index 8f04c0e9..dcff3e90 100644 --- a/include/panda_qt/screen.hpp +++ b/include/panda_qt/screen.hpp @@ -13,6 +13,10 @@ class ScreenWidget : public QWidget { ScreenWidget(QWidget* parent = nullptr); GL::Context* getGLContext() { return glContext.get(); } + // Dimensions of our output surface + u32 surfaceWidth = 0; + u32 surfaceHeight = 0; + private: std::unique_ptr glContext = nullptr; bool createGLContext(); diff --git a/include/renderer.hpp b/include/renderer.hpp index 1f3d63d3..10890e56 100644 --- a/include/renderer.hpp +++ b/include/renderer.hpp @@ -40,6 +40,11 @@ class Renderer { u32 depthBufferLoc; PICA::DepthFmt depthBufferFormat; + // Width and height of the window we're outputting to, needed for properly scaling the final image + // We initialize it to the 3DS resolution by default and the frontend can notify us if it changes via the setOutputSize function + u32 outputWindowWidth = 400; + u32 outputWindowHeight = 240 * 2; + public: Renderer(GPU& gpu, const std::array& internalRegs, const std::array& externalRegs); virtual ~Renderer(); @@ -78,4 +83,9 @@ class Renderer { void setColourBufferLoc(u32 loc) { colourBufferLoc = loc; } void setDepthBufferLoc(u32 loc) { depthBufferLoc = loc; } + + void setOutputSize(u32 width, u32 height) { + outputWindowWidth = width; + outputWindowHeight = height; + } }; diff --git a/src/core/renderer_gl/renderer_gl.cpp b/src/core/renderer_gl/renderer_gl.cpp index 14989c13..107b8806 100644 --- a/src/core/renderer_gl/renderer_gl.cpp +++ b/src/core/renderer_gl/renderer_gl.cpp @@ -524,7 +524,7 @@ void RendererGL::display() { glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); screenFramebuffer.bind(OpenGL::ReadFramebuffer); - glBlitFramebuffer(0, 0, 400, 480, 0, 0, 400, 480, GL_COLOR_BUFFER_BIT, GL_LINEAR); + glBlitFramebuffer(0, 0, 400, 480, 0, 0, outputWindowWidth, outputWindowHeight, GL_COLOR_BUFFER_BIT, GL_LINEAR); } void RendererGL::clearBuffer(u32 startAddress, u32 endAddress, u32 value, u32 control) { diff --git a/src/emulator.cpp b/src/emulator.cpp index 387239fa..5d87fccd 100644 --- a/src/emulator.cpp +++ b/src/emulator.cpp @@ -28,12 +28,6 @@ Emulator::Emulator() Helpers::warn("Failed to initialize SDL2 GameController: %s", SDL_GetError()); } - // We need OpenGL for software rendering or for OpenGL if it's enabled - bool needOpenGL = config.rendererType == RendererType::Software; -#ifdef PANDA3DS_ENABLE_OPENGL - needOpenGL = needOpenGL || (config.rendererType == RendererType::OpenGL); -#endif - #ifdef PANDA3DS_ENABLE_DISCORD_RPC if (config.discordRpcEnabled) { discordRpc.init(); @@ -41,6 +35,12 @@ Emulator::Emulator() } #endif + // We need OpenGL for software rendering or for OpenGL if it's enabled + bool needOpenGL = config.rendererType == RendererType::Software; +#ifdef PANDA3DS_ENABLE_OPENGL + needOpenGL = needOpenGL || (config.rendererType == RendererType::OpenGL); +#endif + // Only create SDL Window for SDL frontend #ifdef PANDA3DS_FRONTEND_SDL if (needOpenGL) { diff --git a/src/panda_qt/main_window.cpp b/src/panda_qt/main_window.cpp index 0a201c55..a5ba0129 100644 --- a/src/panda_qt/main_window.cpp +++ b/src/panda_qt/main_window.cpp @@ -27,6 +27,7 @@ MainWindow::MainWindow(QApplication* app, QWidget* parent) : QMainWindow(parent) connect(themeSelect, &QComboBox::currentIndexChanged, this, [&](int index) { setTheme(static_cast(index)); }); emu = new Emulator(); + emu->setOutputSize(screen.surfaceWidth, screen.surfaceHeight); // The emulator graphics context for the thread should be initialized in the emulator thread due to how GL contexts work emuThread = std::thread([&]() { diff --git a/src/panda_qt/screen.cpp b/src/panda_qt/screen.cpp index d01682a8..354a7f42 100644 --- a/src/panda_qt/screen.cpp +++ b/src/panda_qt/screen.cpp @@ -105,6 +105,9 @@ std::optional ScreenWidget::getWindowInfo() { wi.surface_height = static_cast(scaledWindowHeight()); wi.surface_scale = static_cast(devicePixelRatioFromScreen()); + surfaceWidth = wi.surface_width; + surfaceHeight = wi.surface_height; + return wi; } #endif \ No newline at end of file