From 807c15a824316b8c4e3d543ed236697e67f5eab4 Mon Sep 17 00:00:00 2001 From: wheremyfoodat <44909372+wheremyfoodat@users.noreply.github.com> Date: Sat, 26 Jul 2025 03:42:59 +0300 Subject: [PATCH] Clean up graphics context code --- include/PICA/gpu.hpp | 1 - include/emulator.hpp | 7 +--- include/panda_qt/main_window.hpp | 2 +- include/panda_qt/screen.hpp | 6 +-- include/renderer.hpp | 5 --- include/renderer_gl/renderer_gl.hpp | 4 -- include/renderer_mtl/renderer_mtl.hpp | 4 -- include/renderer_null/renderer_null.hpp | 4 -- include/renderer_sw/renderer_sw.hpp | 4 -- src/core/renderer_mtl/renderer_mtl.cpp | 2 - src/panda_qt/main_window.cpp | 51 +++++++++++++++---------- src/panda_qt/screen.cpp | 8 ++-- 12 files changed, 41 insertions(+), 57 deletions(-) diff --git a/include/PICA/gpu.hpp b/include/PICA/gpu.hpp index 4a3580b0..3a9e38c0 100644 --- a/include/PICA/gpu.hpp +++ b/include/PICA/gpu.hpp @@ -110,7 +110,6 @@ class GPU { void deinitGraphicsContext() { renderer->deinitGraphicsContext(); } void initGraphicsContext(void* window) { renderer->initGraphicsContext(window); } - void initGraphicsContext(GL::Context* context) { renderer->initGraphicsContext(context); } void fireDMA(u32 dest, u32 source, u32 size); void reset(); diff --git a/include/emulator.hpp b/include/emulator.hpp index be770d91..366f86f2 100644 --- a/include/emulator.hpp +++ b/include/emulator.hpp @@ -106,11 +106,8 @@ class Emulator { bool loadELF(const std::filesystem::path& path); bool loadELF(std::ifstream& file); -#ifdef PANDA3DS_FRONTEND_QT - // For passing the GL context from Qt to the renderer - void initGraphicsContext(GL::Context* glContext) { gpu.initGraphicsContext(glContext); } - void initGraphicsContext(void* window) { gpu.initGraphicsContext(window); } -#endif + // For passing the SDL Window, GL context, etc from the frontend to the renderer + void initGraphicsContext(void* context) { gpu.initGraphicsContext(context); } RomFS::DumpingResult dumpRomFS(const std::filesystem::path& path); void setOutputSize(u32 width, u32 height) { gpu.setOutputSize(width, height); } diff --git a/include/panda_qt/main_window.hpp b/include/panda_qt/main_window.hpp index 7bdf6b96..0dc9a1bd 100644 --- a/include/panda_qt/main_window.hpp +++ b/include/panda_qt/main_window.hpp @@ -136,7 +136,7 @@ class MainWindow : public QMainWindow { void loadKeybindings(); void saveKeybindings(); - // Tracks whether we are using an OpenGL-backed renderer or a Vulkan-backed renderer + // Tracks what graphics API is backing our renderer bool usingGL = false; bool usingVk = false; bool usingMtl = false; diff --git a/include/panda_qt/screen.hpp b/include/panda_qt/screen.hpp index a461fb5d..2a3d999d 100644 --- a/include/panda_qt/screen.hpp +++ b/include/panda_qt/screen.hpp @@ -9,14 +9,14 @@ // OpenGL widget for drawing the 3DS screen class ScreenWidget : public QWidget { - enum class API { OpenGL, Metal, Vulkan }; - Q_OBJECT public: using ResizeCallback = std::function; - ScreenWidget(ResizeCallback resizeCallback, QWidget* parent = nullptr); + enum class API { OpenGL, Metal, Vulkan }; + + ScreenWidget(API api, ResizeCallback resizeCallback, QWidget* parent = nullptr); void resizeEvent(QResizeEvent* event) override; // Called by the emulator thread for resizing the actual GL surface, since the emulator thread owns the GL context void resizeSurface(u32 width, u32 height); diff --git a/include/renderer.hpp b/include/renderer.hpp index 2803e821..e4d07885 100644 --- a/include/renderer.hpp +++ b/include/renderer.hpp @@ -101,11 +101,6 @@ class Renderer { // Returns whether this draw is eligible for using hardware-accelerated shaders or if shaders should run on the CPU virtual bool prepareForDraw(ShaderUnit& shaderUnit, PICA::DrawAcceleration* accel) { return false; } - // Functions for initializing the graphics context for the Qt frontend, where we don't have the convenience of SDL_Window -#ifdef PANDA3DS_FRONTEND_QT - virtual void initGraphicsContext(GL::Context* context) { Helpers::panic("Tried to initialize incompatible renderer with GL context"); } -#endif - void setFBSize(u32 width, u32 height) { fbSize[0] = width; fbSize[1] = height; diff --git a/include/renderer_gl/renderer_gl.hpp b/include/renderer_gl/renderer_gl.hpp index ac7fc2fa..cbbb15e3 100644 --- a/include/renderer_gl/renderer_gl.hpp +++ b/include/renderer_gl/renderer_gl.hpp @@ -211,10 +211,6 @@ class RendererGL final : public Renderer { void resetStateManager() { gl.reset(); } void initUbershader(OpenGL::Program& program); -#ifdef PANDA3DS_FRONTEND_QT - virtual void initGraphicsContext([[maybe_unused]] GL::Context* context) override { initGraphicsContextInternal(); } -#endif - // Take a screenshot of the screen and store it in a file void screenshot(const std::string& name) override; }; \ No newline at end of file diff --git a/include/renderer_mtl/renderer_mtl.hpp b/include/renderer_mtl/renderer_mtl.hpp index 3d197aa6..edfd4244 100644 --- a/include/renderer_mtl/renderer_mtl.hpp +++ b/include/renderer_mtl/renderer_mtl.hpp @@ -37,10 +37,6 @@ class RendererMTL final : public Renderer { void screenshot(const std::string& name) override; void deinitGraphicsContext() override; -#ifdef PANDA3DS_FRONTEND_QT - virtual void initGraphicsContext([[maybe_unused]] GL::Context* context) override {} -#endif - virtual void setMTKLayer(void* layer) override; private: diff --git a/include/renderer_null/renderer_null.hpp b/include/renderer_null/renderer_null.hpp index 56fb3652..e6b831d7 100644 --- a/include/renderer_null/renderer_null.hpp +++ b/include/renderer_null/renderer_null.hpp @@ -20,8 +20,4 @@ class RendererNull final : public Renderer { // Tell the GPU core that we'll handle vertex fetch & shader execution in the renderer in order to speed up execution. // Of course, we don't do this and geometry is never actually processed, since this is the null renderer. virtual bool prepareForDraw(ShaderUnit& shaderUnit, PICA::DrawAcceleration* accel) override { return true; }; - -#ifdef PANDA3DS_FRONTEND_QT - virtual void initGraphicsContext([[maybe_unused]] GL::Context* context) override {} -#endif }; diff --git a/include/renderer_sw/renderer_sw.hpp b/include/renderer_sw/renderer_sw.hpp index b520eb6d..1e79cf11 100644 --- a/include/renderer_sw/renderer_sw.hpp +++ b/include/renderer_sw/renderer_sw.hpp @@ -16,8 +16,4 @@ class RendererSw final : public Renderer { void drawVertices(PICA::PrimType primType, std::span vertices) override; void screenshot(const std::string& name) override; void deinitGraphicsContext() override; - -#ifdef PANDA3DS_FRONTEND_QT - virtual void initGraphicsContext([[maybe_unused]] GL::Context* context) override {} -#endif }; diff --git a/src/core/renderer_mtl/renderer_mtl.cpp b/src/core/renderer_mtl/renderer_mtl.cpp index 12f35aa2..8f924d43 100644 --- a/src/core/renderer_mtl/renderer_mtl.cpp +++ b/src/core/renderer_mtl/renderer_mtl.cpp @@ -57,8 +57,6 @@ void RendererMTL::reset() { colorRenderTargetCache.reset(); } -void RendererMTL::setMTKLayer(void* layer) { - metalLayer = (CA::MetalLayer*)layer; void RendererMTL::setMTKLayer(void* layer) { metalLayer = (CA::MetalLayer*)layer; } void RendererMTL::display() { diff --git a/src/panda_qt/main_window.cpp b/src/panda_qt/main_window.cpp index 00f0040e..e3ca79a1 100644 --- a/src/panda_qt/main_window.cpp +++ b/src/panda_qt/main_window.cpp @@ -25,8 +25,19 @@ MainWindow::MainWindow(QApplication* app, QWidget* parent) : QMainWindow(parent) resize(800, 240 * 4); show(); + const RendererType rendererType = emu->getConfig().rendererType; + usingGL = (rendererType == RendererType::OpenGL || rendererType == RendererType::Software || rendererType == RendererType::Null); + usingVk = (rendererType == RendererType::Vulkan); + usingMtl = (rendererType == RendererType::Metal); + + ScreenWidget::API api = ScreenWidget::API::OpenGL; + if (usingVk) + api = ScreenWidget::API::Vulkan; + else if (usingMtl) + api = ScreenWidget::API::Metal; + // We pass a callback to the screen widget that will be triggered every time we resize the screen - screen = new ScreenWidget([this](u32 width, u32 height) { handleScreenResize(width, height); }, this); + screen = new ScreenWidget(api, [this](u32 width, u32 height) { handleScreenResize(width, height); }, this); setCentralWidget(screen); appRunning = true; @@ -149,29 +160,29 @@ MainWindow::MainWindow(QApplication* app, QWidget* parent) : QMainWindow(parent) // The emulator graphics context for the thread should be initialized in the emulator thread due to how GL contexts work emuThread = std::thread([this]() { - const RendererType rendererType = emu->getConfig().rendererType; - usingGL = (rendererType == RendererType::OpenGL || rendererType == RendererType::Software || rendererType == RendererType::Null); - usingVk = (rendererType == RendererType::Vulkan); - usingMtl = (rendererType == RendererType::Metal); + switch (screen->api) { + case ScreenWidget::API::OpenGL: { + // Make GL context current for this thread, enable VSync + GL::Context* glContext = screen->getGLContext(); + glContext->MakeCurrent(); + glContext->SetSwapInterval(emu->getConfig().vsyncEnabled ? 1 : 0); - if (usingGL) { - // Make GL context current for this thread, enable VSync - GL::Context* glContext = screen->getGLContext(); - glContext->MakeCurrent(); - glContext->SetSwapInterval(emu->getConfig().vsyncEnabled ? 1 : 0); + if (glContext->IsGLES()) { + emu->getRenderer()->setupGLES(); + } - if (glContext->IsGLES()) { - emu->getRenderer()->setupGLES(); + emu->initGraphicsContext(glContext); + break; } - emu->initGraphicsContext(glContext); - } else if (usingVk) { - Helpers::panic("Vulkan on Qt is currently WIP, try the SDL frontend instead!"); - } else if (usingMtl) { - emu->initGraphicsContext((void*)nullptr); - emu->getRenderer()->setMTKLayer(screen->getMTKLayer()); - } else { - Helpers::panic("Unsupported graphics backend for Qt frontend!"); + case ScreenWidget::API::Metal: { + emu->initGraphicsContext(nullptr); + emu->getRenderer()->setMTKLayer(screen->getMTKLayer()); + break; + } + + case ScreenWidget::API::Vulkan: Helpers::panic("Vulkan on Qt is currently WIP, try the SDL frontend instead!"); break; + default: Helpers::panic("Unsupported graphics backend for Qt frontend!"); break; } // We have to initialize controllers on the same thread they'll be polled in diff --git a/src/panda_qt/screen.cpp b/src/panda_qt/screen.cpp index 9f125f88..dfbf7882 100644 --- a/src/panda_qt/screen.cpp +++ b/src/panda_qt/screen.cpp @@ -18,10 +18,8 @@ // and https://github.com/melonDS-emu/melonDS/blob/master/src/frontend/qt_sdl/main.cpp #ifdef PANDA3DS_ENABLE_OPENGL -ScreenWidget::ScreenWidget(ResizeCallback resizeCallback, QWidget* parent) : QWidget(parent), resizeCallback(resizeCallback) { +ScreenWidget::ScreenWidget(API api, ResizeCallback resizeCallback, QWidget* parent) : api(api), QWidget(parent), resizeCallback(resizeCallback) { // Create a native window for use with our graphics API of choice - resize(800, 240 * 4); - setAutoFillBackground(false); setAttribute(Qt::WA_NativeWindow, true); setAttribute(Qt::WA_NoSystemBackground, true); @@ -29,7 +27,6 @@ ScreenWidget::ScreenWidget(ResizeCallback resizeCallback, QWidget* parent) : QWi setAttribute(Qt::WA_KeyCompression, false); setFocusPolicy(Qt::StrongFocus); setMouseTracking(true); - show(); if (api == API::OpenGL) { if (!createGLContext()) { @@ -42,6 +39,9 @@ ScreenWidget::ScreenWidget(ResizeCallback resizeCallback, QWidget* parent) : QWi } else { Helpers::panic("Unspported api for Qt screen widget"); } + + resize(800, 240 * 4); + show(); } void ScreenWidget::resizeEvent(QResizeEvent* event) {