mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-09-05 00:56:02 +00:00
Clean up graphics context code
This commit is contained in:
parent
864472ebb2
commit
807c15a824
12 changed files with 41 additions and 57 deletions
|
@ -110,7 +110,6 @@ class GPU {
|
||||||
void deinitGraphicsContext() { renderer->deinitGraphicsContext(); }
|
void deinitGraphicsContext() { renderer->deinitGraphicsContext(); }
|
||||||
|
|
||||||
void initGraphicsContext(void* window) { renderer->initGraphicsContext(window); }
|
void initGraphicsContext(void* window) { renderer->initGraphicsContext(window); }
|
||||||
void initGraphicsContext(GL::Context* context) { renderer->initGraphicsContext(context); }
|
|
||||||
|
|
||||||
void fireDMA(u32 dest, u32 source, u32 size);
|
void fireDMA(u32 dest, u32 source, u32 size);
|
||||||
void reset();
|
void reset();
|
||||||
|
|
|
@ -106,11 +106,8 @@ class Emulator {
|
||||||
bool loadELF(const std::filesystem::path& path);
|
bool loadELF(const std::filesystem::path& path);
|
||||||
bool loadELF(std::ifstream& file);
|
bool loadELF(std::ifstream& file);
|
||||||
|
|
||||||
#ifdef PANDA3DS_FRONTEND_QT
|
// For passing the SDL Window, GL context, etc from the frontend to the renderer
|
||||||
// For passing the GL context from Qt to the renderer
|
void initGraphicsContext(void* context) { gpu.initGraphicsContext(context); }
|
||||||
void initGraphicsContext(GL::Context* glContext) { gpu.initGraphicsContext(glContext); }
|
|
||||||
void initGraphicsContext(void* window) { gpu.initGraphicsContext(window); }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
RomFS::DumpingResult dumpRomFS(const std::filesystem::path& path);
|
RomFS::DumpingResult dumpRomFS(const std::filesystem::path& path);
|
||||||
void setOutputSize(u32 width, u32 height) { gpu.setOutputSize(width, height); }
|
void setOutputSize(u32 width, u32 height) { gpu.setOutputSize(width, height); }
|
||||||
|
|
|
@ -136,7 +136,7 @@ class MainWindow : public QMainWindow {
|
||||||
void loadKeybindings();
|
void loadKeybindings();
|
||||||
void saveKeybindings();
|
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 usingGL = false;
|
||||||
bool usingVk = false;
|
bool usingVk = false;
|
||||||
bool usingMtl = false;
|
bool usingMtl = false;
|
||||||
|
|
|
@ -9,14 +9,14 @@
|
||||||
|
|
||||||
// OpenGL widget for drawing the 3DS screen
|
// OpenGL widget for drawing the 3DS screen
|
||||||
class ScreenWidget : public QWidget {
|
class ScreenWidget : public QWidget {
|
||||||
enum class API { OpenGL, Metal, Vulkan };
|
|
||||||
|
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using ResizeCallback = std::function<void(u32, u32)>;
|
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;
|
void resizeEvent(QResizeEvent* event) override;
|
||||||
// Called by the emulator thread for resizing the actual GL surface, since the emulator thread owns the GL context
|
// 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);
|
void resizeSurface(u32 width, u32 height);
|
||||||
|
|
|
@ -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
|
// 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; }
|
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) {
|
void setFBSize(u32 width, u32 height) {
|
||||||
fbSize[0] = width;
|
fbSize[0] = width;
|
||||||
fbSize[1] = height;
|
fbSize[1] = height;
|
||||||
|
|
|
@ -211,10 +211,6 @@ class RendererGL final : public Renderer {
|
||||||
void resetStateManager() { gl.reset(); }
|
void resetStateManager() { gl.reset(); }
|
||||||
void initUbershader(OpenGL::Program& program);
|
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
|
// Take a screenshot of the screen and store it in a file
|
||||||
void screenshot(const std::string& name) override;
|
void screenshot(const std::string& name) override;
|
||||||
};
|
};
|
|
@ -37,10 +37,6 @@ class RendererMTL final : public Renderer {
|
||||||
void screenshot(const std::string& name) override;
|
void screenshot(const std::string& name) override;
|
||||||
void deinitGraphicsContext() override;
|
void deinitGraphicsContext() override;
|
||||||
|
|
||||||
#ifdef PANDA3DS_FRONTEND_QT
|
|
||||||
virtual void initGraphicsContext([[maybe_unused]] GL::Context* context) override {}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
virtual void setMTKLayer(void* layer) override;
|
virtual void setMTKLayer(void* layer) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -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.
|
// 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.
|
// 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; };
|
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
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -16,8 +16,4 @@ class RendererSw final : public Renderer {
|
||||||
void drawVertices(PICA::PrimType primType, std::span<const PICA::Vertex> vertices) override;
|
void drawVertices(PICA::PrimType primType, std::span<const PICA::Vertex> vertices) override;
|
||||||
void screenshot(const std::string& name) override;
|
void screenshot(const std::string& name) override;
|
||||||
void deinitGraphicsContext() override;
|
void deinitGraphicsContext() override;
|
||||||
|
|
||||||
#ifdef PANDA3DS_FRONTEND_QT
|
|
||||||
virtual void initGraphicsContext([[maybe_unused]] GL::Context* context) override {}
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -57,8 +57,6 @@ void RendererMTL::reset() {
|
||||||
colorRenderTargetCache.reset();
|
colorRenderTargetCache.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RendererMTL::setMTKLayer(void* layer) {
|
|
||||||
metalLayer = (CA::MetalLayer*)layer;
|
|
||||||
void RendererMTL::setMTKLayer(void* layer) { metalLayer = (CA::MetalLayer*)layer; }
|
void RendererMTL::setMTKLayer(void* layer) { metalLayer = (CA::MetalLayer*)layer; }
|
||||||
|
|
||||||
void RendererMTL::display() {
|
void RendererMTL::display() {
|
||||||
|
|
|
@ -25,8 +25,19 @@ MainWindow::MainWindow(QApplication* app, QWidget* parent) : QMainWindow(parent)
|
||||||
resize(800, 240 * 4);
|
resize(800, 240 * 4);
|
||||||
show();
|
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
|
// 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);
|
setCentralWidget(screen);
|
||||||
|
|
||||||
appRunning = true;
|
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
|
// The emulator graphics context for the thread should be initialized in the emulator thread due to how GL contexts work
|
||||||
emuThread = std::thread([this]() {
|
emuThread = std::thread([this]() {
|
||||||
const RendererType rendererType = emu->getConfig().rendererType;
|
switch (screen->api) {
|
||||||
usingGL = (rendererType == RendererType::OpenGL || rendererType == RendererType::Software || rendererType == RendererType::Null);
|
case ScreenWidget::API::OpenGL: {
|
||||||
usingVk = (rendererType == RendererType::Vulkan);
|
// Make GL context current for this thread, enable VSync
|
||||||
usingMtl = (rendererType == RendererType::Metal);
|
GL::Context* glContext = screen->getGLContext();
|
||||||
|
glContext->MakeCurrent();
|
||||||
|
glContext->SetSwapInterval(emu->getConfig().vsyncEnabled ? 1 : 0);
|
||||||
|
|
||||||
if (usingGL) {
|
if (glContext->IsGLES()) {
|
||||||
// Make GL context current for this thread, enable VSync
|
emu->getRenderer()->setupGLES();
|
||||||
GL::Context* glContext = screen->getGLContext();
|
}
|
||||||
glContext->MakeCurrent();
|
|
||||||
glContext->SetSwapInterval(emu->getConfig().vsyncEnabled ? 1 : 0);
|
|
||||||
|
|
||||||
if (glContext->IsGLES()) {
|
emu->initGraphicsContext(glContext);
|
||||||
emu->getRenderer()->setupGLES();
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
emu->initGraphicsContext(glContext);
|
case ScreenWidget::API::Metal: {
|
||||||
} else if (usingVk) {
|
emu->initGraphicsContext(nullptr);
|
||||||
Helpers::panic("Vulkan on Qt is currently WIP, try the SDL frontend instead!");
|
emu->getRenderer()->setMTKLayer(screen->getMTKLayer());
|
||||||
} else if (usingMtl) {
|
break;
|
||||||
emu->initGraphicsContext((void*)nullptr);
|
}
|
||||||
emu->getRenderer()->setMTKLayer(screen->getMTKLayer());
|
|
||||||
} else {
|
case ScreenWidget::API::Vulkan: Helpers::panic("Vulkan on Qt is currently WIP, try the SDL frontend instead!"); break;
|
||||||
Helpers::panic("Unsupported graphics backend for Qt frontend!");
|
default: Helpers::panic("Unsupported graphics backend for Qt frontend!"); break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We have to initialize controllers on the same thread they'll be polled in
|
// We have to initialize controllers on the same thread they'll be polled in
|
||||||
|
|
|
@ -18,10 +18,8 @@
|
||||||
// and https://github.com/melonDS-emu/melonDS/blob/master/src/frontend/qt_sdl/main.cpp
|
// and https://github.com/melonDS-emu/melonDS/blob/master/src/frontend/qt_sdl/main.cpp
|
||||||
|
|
||||||
#ifdef PANDA3DS_ENABLE_OPENGL
|
#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
|
// Create a native window for use with our graphics API of choice
|
||||||
resize(800, 240 * 4);
|
|
||||||
|
|
||||||
setAutoFillBackground(false);
|
setAutoFillBackground(false);
|
||||||
setAttribute(Qt::WA_NativeWindow, true);
|
setAttribute(Qt::WA_NativeWindow, true);
|
||||||
setAttribute(Qt::WA_NoSystemBackground, true);
|
setAttribute(Qt::WA_NoSystemBackground, true);
|
||||||
|
@ -29,7 +27,6 @@ ScreenWidget::ScreenWidget(ResizeCallback resizeCallback, QWidget* parent) : QWi
|
||||||
setAttribute(Qt::WA_KeyCompression, false);
|
setAttribute(Qt::WA_KeyCompression, false);
|
||||||
setFocusPolicy(Qt::StrongFocus);
|
setFocusPolicy(Qt::StrongFocus);
|
||||||
setMouseTracking(true);
|
setMouseTracking(true);
|
||||||
show();
|
|
||||||
|
|
||||||
if (api == API::OpenGL) {
|
if (api == API::OpenGL) {
|
||||||
if (!createGLContext()) {
|
if (!createGLContext()) {
|
||||||
|
@ -42,6 +39,9 @@ ScreenWidget::ScreenWidget(ResizeCallback resizeCallback, QWidget* parent) : QWi
|
||||||
} else {
|
} else {
|
||||||
Helpers::panic("Unspported api for Qt screen widget");
|
Helpers::panic("Unspported api for Qt screen widget");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resize(800, 240 * 4);
|
||||||
|
show();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScreenWidget::resizeEvent(QResizeEvent* event) {
|
void ScreenWidget::resizeEvent(QResizeEvent* event) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue