start actually implementing multi-window feature, still rough around the edges

fix crash when closing main window if sub windows are involved

fix OpenGL context handling, still need to fix when changing display type
This commit is contained in:
Arisotura 2024-10-27 01:14:29 +02:00
parent f375099613
commit 881a740cab
8 changed files with 49 additions and 33 deletions

View File

@ -199,6 +199,10 @@ void EmuInstance::createWindow()
numWindows++; numWindows++;
emuThread->attachWindow(win); emuThread->attachWindow(win);
// if creating a secondary window, we may need to initialize its OpenGL context here
if (win->hasOpenGL() && (win != topWindow))
emuThread->initContext(id);
} }
void EmuInstance::deleteWindow(int id, bool close) void EmuInstance::deleteWindow(int id, bool close)
@ -208,12 +212,8 @@ void EmuInstance::deleteWindow(int id, bool close)
MainWindow* win = windowList[id]; MainWindow* win = windowList[id];
if (!win) return; if (!win) return;
if (win->hasOpenGL() && win == mainWindow) if (win->hasOpenGL())
{ emuThread->deinitContext(id);
// we intentionally don't unpause here
emuThread->emuPause();
emuThread->deinitContext();
}
emuThread->detachWindow(win); emuThread->detachWindow(win);
@ -226,9 +226,10 @@ void EmuInstance::deleteWindow(int id, bool close)
if (close) if (close)
win->close(); win->close();
if ((!mainWindow) && (!deleting)) if (numWindows == 0)
{ {
// if we closed this instance's main window, delete the instance // if we closed the last window, delete the instance
// if the main window is closed, Qt will take care of closing any secondary windows
deleteEmuInstance(instanceID); deleteEmuInstance(instanceID);
} }
} }
@ -292,24 +293,18 @@ bool EmuInstance::usesOpenGL()
(globalCfg.GetInt("3D.Renderer") != renderer3D_Software); (globalCfg.GetInt("3D.Renderer") != renderer3D_Software);
} }
void EmuInstance::initOpenGL() void EmuInstance::initOpenGL(int win)
{ {
for (int i = 0; i < kMaxWindows; i++) if (windowList[win])
{ windowList[win]->initOpenGL();
if (windowList[i])
windowList[i]->initOpenGL();
}
setVSyncGL(true); setVSyncGL(true);
} }
void EmuInstance::deinitOpenGL() void EmuInstance::deinitOpenGL(int win)
{ {
for (int i = 0; i < kMaxWindows; i++) if (windowList[win])
{ windowList[win]->deinitOpenGL();
if (windowList[i])
windowList[i]->deinitOpenGL();
}
} }
void EmuInstance::setVSyncGL(bool vsync) void EmuInstance::setVSyncGL(bool vsync)

View File

@ -103,8 +103,8 @@ public:
void emuStop(melonDS::Platform::StopReason reason); void emuStop(melonDS::Platform::StopReason reason);
bool usesOpenGL(); bool usesOpenGL();
void initOpenGL(); void initOpenGL(int win);
void deinitOpenGL(); void deinitOpenGL(int win);
void setVSyncGL(bool vsync); void setVSyncGL(bool vsync);
void makeCurrentGL(); void makeCurrentGL();
void drawScreenGL(); void drawScreenGL();

View File

@ -115,7 +115,7 @@ void EmuThread::run()
if (emuInstance->usesOpenGL()) if (emuInstance->usesOpenGL())
{ {
emuInstance->initOpenGL(); emuInstance->initOpenGL(0);
useOpenGL = true; useOpenGL = true;
videoRenderer = globalCfg.GetInt("3D.Renderer"); videoRenderer = globalCfg.GetInt("3D.Renderer");
@ -547,12 +547,12 @@ void EmuThread::handleMessages()
break; break;
case msg_InitGL: case msg_InitGL:
emuInstance->initOpenGL(); emuInstance->initOpenGL(msg.param.value<int>());
useOpenGL = true; useOpenGL = true;
break; break;
case msg_DeInitGL: case msg_DeInitGL:
emuInstance->deinitOpenGL(); emuInstance->deinitOpenGL(msg.param.value<int>());
useOpenGL = false; useOpenGL = false;
break; break;
@ -650,15 +650,15 @@ void EmuThread::changeWindowTitle(char* title)
emit windowTitleChange(QString(title)); emit windowTitleChange(QString(title));
} }
void EmuThread::initContext() void EmuThread::initContext(int win)
{ {
sendMessage(msg_InitGL); sendMessage({.type = msg_InitGL, .param = win});
waitMessage(); waitMessage();
} }
void EmuThread::deinitContext() void EmuThread::deinitContext(int win)
{ {
sendMessage(msg_DeInitGL); sendMessage({.type = msg_DeInitGL, .param = win});
waitMessage(); waitMessage();
} }

View File

@ -127,8 +127,8 @@ public:
bool emuIsRunning(); bool emuIsRunning();
bool emuIsActive(); bool emuIsActive();
void initContext(); void initContext(int win);
void deinitContext(); void deinitContext(int win);
void updateVideoSettings() { videoSettingsDirty = true; } void updateVideoSettings() { videoSettingsDirty = true; }
void updateVideoRenderer() { videoSettingsDirty = true; lastVideoRenderer = -1; } void updateVideoRenderer() { videoSettingsDirty = true; lastVideoRenderer = -1; }

View File

@ -736,6 +736,8 @@ ScreenPanelGL::ScreenPanelGL(QWidget* parent) : ScreenPanel(parent)
setAttribute(Qt::WA_KeyCompression, false); setAttribute(Qt::WA_KeyCompression, false);
setFocusPolicy(Qt::StrongFocus); setFocusPolicy(Qt::StrongFocus);
setMinimumSize(screenGetMinSize()); setMinimumSize(screenGetMinSize());
glInited = false;
} }
ScreenPanelGL::~ScreenPanelGL() ScreenPanelGL::~ScreenPanelGL()
@ -781,6 +783,7 @@ void ScreenPanelGL::setSwapInterval(int intv)
void ScreenPanelGL::initOpenGL() void ScreenPanelGL::initOpenGL()
{ {
if (!glContext) return; if (!glContext) return;
if (glInited) return;
glContext->MakeCurrent(); glContext->MakeCurrent();
@ -877,11 +880,13 @@ void ScreenPanelGL::initOpenGL()
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (void*)(0)); glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (void*)(0));
transferLayout(); transferLayout();
glInited = true;
} }
void ScreenPanelGL::deinitOpenGL() void ScreenPanelGL::deinitOpenGL()
{ {
if (!glContext) return; if (!glContext) return;
if (!glInited) return;
glDeleteTextures(1, &screenTexture); glDeleteTextures(1, &screenTexture);
@ -906,6 +911,7 @@ void ScreenPanelGL::deinitOpenGL()
glContext->DoneCurrent(); glContext->DoneCurrent();
lastScreenWidth = lastScreenHeight = -1; lastScreenWidth = lastScreenHeight = -1;
glInited = false;
} }
void ScreenPanelGL::makeCurrentGL() void ScreenPanelGL::makeCurrentGL()

View File

@ -197,6 +197,7 @@ private:
void setupScreenLayout() override; void setupScreenLayout() override;
std::unique_ptr<GL::Context> glContext; std::unique_ptr<GL::Context> glContext;
bool glInited;
GLuint screenVertexBuffer, screenVertexArray; GLuint screenVertexBuffer, screenVertexArray;
GLuint screenTexture; GLuint screenTexture;

View File

@ -588,6 +588,13 @@ MainWindow::MainWindow(int id, EmuInstance* inst, QWidget* parent) :
} }
} }
menu->addSeparator();
actNewWindow = menu->addAction("Open new window");
connect(actNewWindow, &QAction::triggered, this, &MainWindow::onOpenNewWindow);
menu->addSeparator();
actScreenFiltering = menu->addAction("Screen filtering"); actScreenFiltering = menu->addAction("Screen filtering");
actScreenFiltering->setCheckable(true); actScreenFiltering->setCheckable(true);
connect(actScreenFiltering, &QAction::triggered, this, &MainWindow::onChangeScreenFiltering); connect(actScreenFiltering, &QAction::triggered, this, &MainWindow::onChangeScreenFiltering);
@ -1950,6 +1957,11 @@ void MainWindow::onChangeIntegerScaling(bool checked)
emit screenLayoutChange(); emit screenLayoutChange();
} }
void MainWindow::onOpenNewWindow()
{
emuInstance->createWindow();
}
void MainWindow::onChangeScreenFiltering(bool checked) void MainWindow::onChangeScreenFiltering(bool checked)
{ {
windowCfg.SetBool("ScreenFilter", checked); windowCfg.SetBool("ScreenFilter", checked);
@ -2077,7 +2089,7 @@ void MainWindow::onUpdateVideoSettings(bool glchange)
if (glchange) if (glchange)
{ {
emuThread->emuPause(); emuThread->emuPause();
if (hasOGL) emuThread->deinitContext(); if (hasOGL) emuThread->deinitContext(windowID);
delete panel; delete panel;
createScreenPanel(); createScreenPanel();
@ -2088,7 +2100,7 @@ void MainWindow::onUpdateVideoSettings(bool glchange)
if (glchange) if (glchange)
{ {
if (hasOGL) emuThread->initContext(); if (hasOGL) emuThread->initContext(windowID);
emuThread->emuUnpause(); emuThread->emuUnpause();
} }
} }

View File

@ -208,6 +208,7 @@ private slots:
void onChangeScreenSizing(QAction* act); void onChangeScreenSizing(QAction* act);
void onChangeScreenAspect(QAction* act); void onChangeScreenAspect(QAction* act);
void onChangeIntegerScaling(bool checked); void onChangeIntegerScaling(bool checked);
void onOpenNewWindow();
void onChangeScreenFiltering(bool checked); void onChangeScreenFiltering(bool checked);
void onChangeShowOSD(bool checked); void onChangeShowOSD(bool checked);
void onChangeLimitFramerate(bool checked); void onChangeLimitFramerate(bool checked);
@ -325,6 +326,7 @@ public:
QAction** actScreenAspectTop; QAction** actScreenAspectTop;
QActionGroup* grpScreenAspectBot; QActionGroup* grpScreenAspectBot;
QAction** actScreenAspectBot; QAction** actScreenAspectBot;
QAction* actNewWindow;
QAction* actScreenFiltering; QAction* actScreenFiltering;
QAction* actShowOSD; QAction* actShowOSD;
QAction* actLimitFramerate; QAction* actLimitFramerate;