start work on multiple window support

This commit is contained in:
Arisotura 2024-02-20 12:30:19 +01:00
parent a8429af131
commit 5c93ab4271
10 changed files with 165 additions and 33 deletions

BIN
melon.ttf Normal file

Binary file not shown.

View File

@ -66,7 +66,7 @@ using namespace melonDS;
// TEMP // TEMP
extern bool RunningSomething; extern bool RunningSomething;
extern MainWindow* mainWindow; //extern MainWindow* mainWindow;
extern int autoScreenSizing; extern int autoScreenSizing;
extern int videoRenderer; extern int videoRenderer;
extern bool videoSettingsDirty; extern bool videoSettingsDirty;
@ -79,7 +79,7 @@ EmuThread::EmuThread(QObject* parent) : QThread(parent)
EmuPauseStack = EmuPauseStackRunning; EmuPauseStack = EmuPauseStackRunning;
RunningSomething = false; RunningSomething = false;
connect(this, SIGNAL(windowUpdate()), mainWindow->panel, SLOT(repaint())); /*connect(this, SIGNAL(windowUpdate()), mainWindow->panel, SLOT(repaint()));
connect(this, SIGNAL(windowTitleChange(QString)), mainWindow, SLOT(onTitleUpdate(QString))); connect(this, SIGNAL(windowTitleChange(QString)), mainWindow, SLOT(onTitleUpdate(QString)));
connect(this, SIGNAL(windowEmuStart()), mainWindow, SLOT(onEmuStart())); connect(this, SIGNAL(windowEmuStart()), mainWindow, SLOT(onEmuStart()));
connect(this, SIGNAL(windowEmuStop()), mainWindow, SLOT(onEmuStop())); connect(this, SIGNAL(windowEmuStop()), mainWindow, SLOT(onEmuStop()));
@ -90,7 +90,45 @@ EmuThread::EmuThread(QObject* parent) : QThread(parent)
connect(this, SIGNAL(screenLayoutChange()), mainWindow->panel, SLOT(onScreenLayoutChanged())); connect(this, SIGNAL(screenLayoutChange()), mainWindow->panel, SLOT(onScreenLayoutChanged()));
connect(this, SIGNAL(windowFullscreenToggle()), mainWindow, SLOT(onFullscreenToggled())); connect(this, SIGNAL(windowFullscreenToggle()), mainWindow, SLOT(onFullscreenToggled()));
connect(this, SIGNAL(swapScreensToggle()), mainWindow->actScreenSwap, SLOT(trigger())); connect(this, SIGNAL(swapScreensToggle()), mainWindow->actScreenSwap, SLOT(trigger()));
connect(this, SIGNAL(screenEmphasisToggle()), mainWindow, SLOT(onScreenEmphasisToggled())); connect(this, SIGNAL(screenEmphasisToggle()), mainWindow, SLOT(onScreenEmphasisToggled()));*/
}
void EmuThread::attachWindow(MainWindow* window)
{
windowList.push_back(window);
mainWindow = windowList.front();
connect(this, SIGNAL(windowUpdate()), window->panel, SLOT(repaint()));
connect(this, SIGNAL(windowTitleChange(QString)), window, SLOT(onTitleUpdate(QString)));
connect(this, SIGNAL(windowEmuStart()), window, SLOT(onEmuStart()));
connect(this, SIGNAL(windowEmuStop()), window, SLOT(onEmuStop()));
connect(this, SIGNAL(windowEmuPause()), window->actPause, SLOT(trigger()));
connect(this, SIGNAL(windowEmuReset()), window->actReset, SLOT(trigger()));
connect(this, SIGNAL(windowEmuFrameStep()), window->actFrameStep, SLOT(trigger()));
connect(this, SIGNAL(windowLimitFPSChange()), window->actLimitFramerate, SLOT(trigger()));
connect(this, SIGNAL(screenLayoutChange()), window->panel, SLOT(onScreenLayoutChanged()));
connect(this, SIGNAL(windowFullscreenToggle()), window, SLOT(onFullscreenToggled()));
connect(this, SIGNAL(swapScreensToggle()), window->actScreenSwap, SLOT(trigger()));
connect(this, SIGNAL(screenEmphasisToggle()), window, SLOT(onScreenEmphasisToggled()));
}
void EmuThread::detachWindow(MainWindow* window)
{
disconnect(this, SIGNAL(windowUpdate()), window->panel, SLOT(repaint()));
disconnect(this, SIGNAL(windowTitleChange(QString)), window, SLOT(onTitleUpdate(QString)));
disconnect(this, SIGNAL(windowEmuStart()), window, SLOT(onEmuStart()));
disconnect(this, SIGNAL(windowEmuStop()), window, SLOT(onEmuStop()));
disconnect(this, SIGNAL(windowEmuPause()), window->actPause, SLOT(trigger()));
disconnect(this, SIGNAL(windowEmuReset()), window->actReset, SLOT(trigger()));
disconnect(this, SIGNAL(windowEmuFrameStep()), window->actFrameStep, SLOT(trigger()));
disconnect(this, SIGNAL(windowLimitFPSChange()), window->actLimitFramerate, SLOT(trigger()));
disconnect(this, SIGNAL(screenLayoutChange()), window->panel, SLOT(onScreenLayoutChanged()));
disconnect(this, SIGNAL(windowFullscreenToggle()), window, SLOT(onFullscreenToggled()));
disconnect(this, SIGNAL(swapScreensToggle()), window->actScreenSwap, SLOT(trigger()));
disconnect(this, SIGNAL(screenEmphasisToggle()), window, SLOT(onScreenEmphasisToggled()));
windowList.remove(window);
mainWindow = windowList.front();
} }
std::unique_ptr<NDS> EmuThread::CreateConsole( std::unique_ptr<NDS> EmuThread::CreateConsole(
@ -314,17 +352,25 @@ void EmuThread::run()
videoSettingsDirty = false; videoSettingsDirty = false;
if (mainWindow->hasOGL) if (mainWindow->hasOpenGL())
{ {
screenGL = static_cast<ScreenPanelGL*>(mainWindow->panel); //screenGL = static_cast<ScreenPanelGL*>(mainWindow->panel);
screenGL->initOpenGL(); //screenGL->initOpenGL();
//mainWindow->initOpenGL();
for (auto window : windowList)
window->initOpenGL();
useOpenGL = true;
videoRenderer = Config::_3DRenderer; videoRenderer = Config::_3DRenderer;
} }
else else
{ {
screenGL = nullptr; //screenGL = nullptr;
useOpenGL = false;
videoRenderer = 0; videoRenderer = 0;
} }
//screenGL = nullptr;
//videoRenderer = 0;
if (videoRenderer == 0) if (videoRenderer == 0)
{ // If we're using the software renderer... { // If we're using the software renderer...
@ -332,6 +378,8 @@ void EmuThread::run()
} }
else else
{ {
mainWindow->makeCurrentGL();
auto glrenderer = melonDS::GLRenderer::New(); auto glrenderer = melonDS::GLRenderer::New();
glrenderer->SetRenderSettings(Config::GL_BetterPolygons, Config::GL_ScaleFactor); glrenderer->SetRenderSettings(Config::GL_BetterPolygons, Config::GL_ScaleFactor);
NDS->GPU.SetRenderer3D(std::move(glrenderer)); NDS->GPU.SetRenderer3D(std::move(glrenderer));
@ -384,7 +432,7 @@ void EmuThread::run()
int level = NDS->GBACartSlot.SetInput(GBACart::Input_SolarSensorDown, true); int level = NDS->GBACartSlot.SetInput(GBACart::Input_SolarSensorDown, true);
if (level != -1) if (level != -1)
{ {
mainWindow->osdAddMessage(0, "Solar sensor level: %d", level); //mainWindow->osdAddMessage(0, "Solar sensor level: %d", level);
} }
} }
if (Input::HotkeyPressed(HK_SolarSensorIncrease)) if (Input::HotkeyPressed(HK_SolarSensorIncrease))
@ -392,7 +440,7 @@ void EmuThread::run()
int level = NDS->GBACartSlot.SetInput(GBACart::Input_SolarSensorUp, true); int level = NDS->GBACartSlot.SetInput(GBACart::Input_SolarSensorUp, true);
if (level != -1) if (level != -1)
{ {
mainWindow->osdAddMessage(0, "Solar sensor level: %d", level); //mainWindow->osdAddMessage(0, "Solar sensor level: %d", level);
} }
} }
@ -433,15 +481,20 @@ void EmuThread::run()
dsi.I2C.GetBPTWL()->ProcessVolumeSwitchInput(currentTime); dsi.I2C.GetBPTWL()->ProcessVolumeSwitchInput(currentTime);
} }
if (useOpenGL)
mainWindow->makeCurrentGL();
// update render settings if needed // update render settings if needed
// HACK: // HACK:
// once the fast forward hotkey is released, we need to update vsync // once the fast forward hotkey is released, we need to update vsync
// to the old setting again // to the old setting again
if (videoSettingsDirty || Input::HotkeyReleased(HK_FastForward)) if (videoSettingsDirty || Input::HotkeyReleased(HK_FastForward))
{ {
if (screenGL) if (useOpenGL)
{ {
screenGL->setSwapInterval(Config::ScreenVSync ? Config::ScreenVSyncInterval : 0); for (auto window : windowList)
window->setGLSwapInterval(Config::ScreenVSync ? Config::ScreenVSyncInterval : 0);
videoRenderer = Config::_3DRenderer; videoRenderer = Config::_3DRenderer;
} }
#ifdef OGLRENDERER_ENABLED #ifdef OGLRENDERER_ENABLED
@ -451,7 +504,7 @@ void EmuThread::run()
videoRenderer = 0; videoRenderer = 0;
} }
videoRenderer = screenGL ? Config::_3DRenderer : 0; videoRenderer = useOpenGL ? Config::_3DRenderer : 0;
videoSettingsDirty = false; videoSettingsDirty = false;
@ -474,7 +527,7 @@ void EmuThread::run()
{ {
bool lid = !NDS->IsLidClosed(); bool lid = !NDS->IsLidClosed();
NDS->SetLidClosed(lid); NDS->SetLidClosed(lid);
mainWindow->osdAddMessage(0, lid ? "Lid closed" : "Lid opened"); //mainWindow->osdAddMessage(0, lid ? "Lid closed" : "Lid opened");
} }
// microphone input // microphone input
@ -523,7 +576,7 @@ void EmuThread::run()
if (ROMManager::FirmwareSave) if (ROMManager::FirmwareSave)
ROMManager::FirmwareSave->CheckFlush(); ROMManager::FirmwareSave->CheckFlush();
if (!screenGL) if (!useOpenGL)
{ {
FrontBufferLock.lock(); FrontBufferLock.lock();
FrontBuffer = NDS->GPU.FrontBuffer; FrontBuffer = NDS->GPU.FrontBuffer;
@ -532,7 +585,9 @@ void EmuThread::run()
else else
{ {
FrontBuffer = NDS->GPU.FrontBuffer; FrontBuffer = NDS->GPU.FrontBuffer;
screenGL->drawScreenGL(); //screenGL->drawScreenGL();
for (auto window : windowList)
window->drawScreenGL();
} }
#ifdef MELONCAP #ifdef MELONCAP
@ -542,7 +597,7 @@ void EmuThread::run()
if (EmuRunning == emuStatus_Exit) break; if (EmuRunning == emuStatus_Exit) break;
winUpdateCount++; winUpdateCount++;
if (winUpdateCount >= winUpdateFreq && !screenGL) if (winUpdateCount >= winUpdateFreq && !useOpenGL)
{ {
emit windowUpdate(); emit windowUpdate();
winUpdateCount = 0; winUpdateCount = 0;
@ -550,9 +605,11 @@ void EmuThread::run()
bool fastforward = Input::HotkeyDown(HK_FastForward); bool fastforward = Input::HotkeyDown(HK_FastForward);
if (fastforward && screenGL && Config::ScreenVSync) if (fastforward && useOpenGL && Config::ScreenVSync)
{ {
screenGL->setSwapInterval(0); //screenGL->setSwapInterval(0);
for (auto window : windowList)
window->setGLSwapInterval(0);
} }
if (Config::DSiVolumeSync && NDS->ConsoleType == 1) if (Config::DSiVolumeSync && NDS->ConsoleType == 1)
@ -641,20 +698,31 @@ void EmuThread::run()
SDL_Delay(75); SDL_Delay(75);
if (screenGL) if (useOpenGL)
screenGL->drawScreenGL(); {
for (auto window : windowList)
window->drawScreenGL();
}
ContextRequestKind contextRequest = ContextRequest; ContextRequestKind contextRequest = ContextRequest;
if (contextRequest == contextRequest_InitGL) if (contextRequest == contextRequest_InitGL)
{ {
screenGL = static_cast<ScreenPanelGL*>(mainWindow->panel); //screenGL = static_cast<ScreenPanelGL*>(mainWindow->panel);
screenGL->initOpenGL(); //screenGL->initOpenGL();
for (auto window : windowList)
window->initOpenGL();
useOpenGL = true;
ContextRequest = contextRequest_None; ContextRequest = contextRequest_None;
} }
else if (contextRequest == contextRequest_DeInitGL) else if (contextRequest == contextRequest_DeInitGL)
{ {
screenGL->deinitOpenGL(); //screenGL->deinitOpenGL();
screenGL = nullptr; //screenGL = nullptr;
for (auto window : windowList)
window->deinitOpenGL();
useOpenGL = false;
ContextRequest = contextRequest_None; ContextRequest = contextRequest_None;
} }
} }

View File

@ -25,6 +25,7 @@
#include <atomic> #include <atomic>
#include <variant> #include <variant>
#include <optional> #include <optional>
#include <list>
#include "NDSCart.h" #include "NDSCart.h"
#include "GBACart.h" #include "GBACart.h"
@ -37,6 +38,7 @@ namespace melonDS
class NDS; class NDS;
} }
class MainWindow;
class ScreenPanelGL; class ScreenPanelGL;
class EmuThread : public QThread class EmuThread : public QThread
@ -47,6 +49,9 @@ class EmuThread : public QThread
public: public:
explicit EmuThread(QObject* parent = nullptr); explicit EmuThread(QObject* parent = nullptr);
void attachWindow(MainWindow* window);
void detachWindow(MainWindow* window);
void changeWindowTitle(char* title); void changeWindowTitle(char* title);
// to be called from the UI thread // to be called from the UI thread
@ -123,10 +128,13 @@ private:
}; };
std::atomic<ContextRequestKind> ContextRequest = contextRequest_None; std::atomic<ContextRequestKind> ContextRequest = contextRequest_None;
ScreenPanelGL* screenGL; //ScreenPanelGL* screenGL;
MainWindow* mainWindow;
std::list<MainWindow*> windowList;
int autoScreenSizing; int autoScreenSizing;
bool useOpenGL;
int videoRenderer; int videoRenderer;
bool videoSettingsDirty; bool videoSettingsDirty;
}; };

View File

@ -681,9 +681,23 @@ ScreenPanelGL::ScreenPanelGL(QWidget* parent) : ScreenPanel(parent)
ScreenPanelGL::~ScreenPanelGL() ScreenPanelGL::~ScreenPanelGL()
{} {}
GL::Context* hax = nullptr;
bool ScreenPanelGL::createContext() bool ScreenPanelGL::createContext()
{ {
std::optional<WindowInfo> windowInfo = getWindowInfo(); std::optional<WindowInfo> windowInfo = getWindowInfo();
if (hax)
{
if (windowInfo.has_value())
{
glContext = hax->CreateSharedContext(*getWindowInfo());
glContext->DoneCurrent();
}
return glContext != nullptr;
}
std::array<GL::Context::Version, 2> versionsToTry = { std::array<GL::Context::Version, 2> versionsToTry = {
GL::Context::Version{GL::Context::Profile::Core, 4, 3}, GL::Context::Version{GL::Context::Profile::Core, 4, 3},
GL::Context::Version{GL::Context::Profile::Core, 3, 2}}; GL::Context::Version{GL::Context::Profile::Core, 3, 2}};
@ -691,6 +705,7 @@ bool ScreenPanelGL::createContext()
{ {
glContext = GL::Context::Create(*getWindowInfo(), versionsToTry); glContext = GL::Context::Create(*getWindowInfo(), versionsToTry);
glContext->DoneCurrent(); glContext->DoneCurrent();
hax = glContext.get();
} }
return glContext != nullptr; return glContext != nullptr;
@ -838,6 +853,13 @@ void ScreenPanelGL::deinitOpenGL()
lastScreenWidth = lastScreenHeight = -1; lastScreenWidth = lastScreenHeight = -1;
} }
void ScreenPanelGL::makeCurrentGL()
{
if (!glContext) return;
glContext->MakeCurrent();
}
void ScreenPanelGL::osdRenderItem(OSDItem* item) void ScreenPanelGL::osdRenderItem(OSDItem* item)
{ {
ScreenPanel::osdRenderItem(item); ScreenPanel::osdRenderItem(item);
@ -871,6 +893,8 @@ void ScreenPanelGL::drawScreenGL()
if (!glContext) return; if (!glContext) return;
if (!emuThread->NDS) return; if (!emuThread->NDS) return;
glContext->MakeCurrent();
int w = windowInfo.surface_width; int w = windowInfo.surface_width;
int h = windowInfo.surface_height; int h = windowInfo.surface_height;
float factor = windowInfo.surface_scale; float factor = windowInfo.surface_scale;

View File

@ -152,6 +152,7 @@ public:
void initOpenGL(); void initOpenGL();
void deinitOpenGL(); void deinitOpenGL();
void makeCurrentGL();
void drawScreenGL(); void drawScreenGL();
GL::Context* getContext() { return glContext.get(); } GL::Context* getContext() { return glContext.get(); }

View File

@ -196,8 +196,11 @@ static void signalHandler(int)
} }
#endif #endif
int test = 0;
MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent) MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent)
{ {
test_num = test++;
#ifndef _WIN32 #ifndef _WIN32
if (socketpair(AF_UNIX, SOCK_STREAM, 0, signalFd)) if (socketpair(AF_UNIX, SOCK_STREAM, 0, signalFd))
{ {
@ -719,7 +722,8 @@ void MainWindow::createScreenPanel()
panel = panelGL; panel = panelGL;
panelGL->createContext(); bool res = panelGL->createContext();
printf("WIN %d CONTEXT: %d\n", test_num, res);
} }
if (!hasOGL) if (!hasOGL)
@ -745,8 +749,8 @@ GL::Context* MainWindow::getOGLContext()
return glpanel->getContext(); return glpanel->getContext();
} }
/*void MainWindow::initOpenGL() void MainWindow::initOpenGL()
{ {printf("WINDOW %d INIT OPENGL %d\n", test_num, hasOGL);
if (!hasOGL) return; if (!hasOGL) return;
ScreenPanelGL* glpanel = static_cast<ScreenPanelGL*>(panel); ScreenPanelGL* glpanel = static_cast<ScreenPanelGL*>(panel);
@ -761,13 +765,29 @@ void MainWindow::deinitOpenGL()
return glpanel->deinitOpenGL(); return glpanel->deinitOpenGL();
} }
void MainWindow::setGLSwapInterval(int intv)
{
if (!hasOGL) return;
ScreenPanelGL* glpanel = static_cast<ScreenPanelGL*>(panel);
return glpanel->setSwapInterval(intv);
}
void MainWindow::makeCurrentGL()
{
if (!hasOGL) return;
ScreenPanelGL* glpanel = static_cast<ScreenPanelGL*>(panel);
return glpanel->makeCurrentGL();
}
void MainWindow::drawScreenGL() void MainWindow::drawScreenGL()
{ {
if (!hasOGL) return; if (!hasOGL) return;
ScreenPanelGL* glpanel = static_cast<ScreenPanelGL*>(panel); ScreenPanelGL* glpanel = static_cast<ScreenPanelGL*>(panel);
return glpanel->drawScreenGL(); return glpanel->drawScreenGL();
}*/ }
void MainWindow::resizeEvent(QResizeEvent* event) void MainWindow::resizeEvent(QResizeEvent* event)
{ {
@ -1951,7 +1971,7 @@ void MainWindow::onChangeAudioSync(bool checked)
void MainWindow::onTitleUpdate(QString title) void MainWindow::onTitleUpdate(QString title)
{ {
setWindowTitle(title); setWindowTitle(test_num ? "SECOND WINDOW" : title);
} }
void ToggleFullscreen(MainWindow* mainWindow) void ToggleFullscreen(MainWindow* mainWindow)

View File

@ -103,11 +103,13 @@ public:
explicit MainWindow(QWidget* parent = nullptr); explicit MainWindow(QWidget* parent = nullptr);
~MainWindow(); ~MainWindow();
bool hasOGL; bool hasOpenGL() { return hasOGL; }
GL::Context* getOGLContext(); GL::Context* getOGLContext();
/*void initOpenGL(); void initOpenGL();
void deinitOpenGL(); void deinitOpenGL();
void drawScreenGL();*/ void setGLSwapInterval(int intv);
void makeCurrentGL();
void drawScreenGL();
bool preloadROMs(QStringList file, QStringList gbafile, bool boot); bool preloadROMs(QStringList file, QStringList gbafile, bool boot);
QStringList splitArchivePath(const QString& filename, bool useMemberSyntax); QStringList splitArchivePath(const QString& filename, bool useMemberSyntax);
@ -223,11 +225,15 @@ private:
void createScreenPanel(); void createScreenPanel();
bool hasOGL;
bool pausedManually = false; bool pausedManually = false;
int oldW, oldH; int oldW, oldH;
bool oldMax; bool oldMax;
int test_num;
public: public:
ScreenPanel* panel; ScreenPanel* panel;

View File

@ -380,7 +380,11 @@ int main(int argc, char** argv)
if (options->fullscreen) if (options->fullscreen)
ToggleFullscreen(mainWindow); ToggleFullscreen(mainWindow);
MainWindow* poop = new MainWindow();
emuThread = new EmuThread(); emuThread = new EmuThread();
emuThread->attachWindow(mainWindow);
emuThread->attachWindow(poop);
emuThread->start(); emuThread->start();
emuThread->emuPause(); emuThread->emuPause();

1
test.ttf Normal file
View File

@ -0,0 +1 @@
https://www.youtube.com/watch?v=Hdp38xLa55c