Clean up graphics context code

This commit is contained in:
wheremyfoodat 2025-07-26 03:42:59 +03:00
commit 807c15a824
12 changed files with 41 additions and 57 deletions

View file

@ -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();

View file

@ -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); }

View file

@ -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;

View file

@ -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<void(u32, u32)>;
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);

View file

@ -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;

View file

@ -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;
};

View file

@ -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:

View file

@ -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
};

View file

@ -16,8 +16,4 @@ class RendererSw final : public Renderer {
void drawVertices(PICA::PrimType primType, std::span<const PICA::Vertex> 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
};

View file

@ -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() {

View file

@ -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

View file

@ -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) {