mirror of
https://github.com/melonDS-emu/melonDS.git
synced 2025-07-25 23:29:55 -06:00
fix issues with multi-window and OpenGL on Windows
This commit is contained in:
9
src/frontend/qt_sdl/EmuInstance.cpp
Normal file → Executable file
9
src/frontend/qt_sdl/EmuInstance.cpp
Normal file → Executable file
@ -408,6 +408,15 @@ void EmuInstance::makeCurrentGL()
|
||||
mainWindow->makeCurrentGL();
|
||||
}
|
||||
|
||||
void EmuInstance::releaseGL()
|
||||
{
|
||||
for (int i = 0; i < kMaxWindows; i++)
|
||||
{
|
||||
if (windowList[i])
|
||||
windowList[i]->releaseGL();
|
||||
}
|
||||
}
|
||||
|
||||
void EmuInstance::drawScreenGL()
|
||||
{
|
||||
for (int i = 0; i < kMaxWindows; i++)
|
||||
|
1
src/frontend/qt_sdl/EmuInstance.h
Normal file → Executable file
1
src/frontend/qt_sdl/EmuInstance.h
Normal file → Executable file
@ -120,6 +120,7 @@ public:
|
||||
void deinitOpenGL(int win);
|
||||
void setVSyncGL(bool vsync);
|
||||
void makeCurrentGL();
|
||||
void releaseGL();
|
||||
void drawScreenGL();
|
||||
|
||||
// return: empty string = setup OK, non-empty = error message
|
||||
|
27
src/frontend/qt_sdl/EmuThread.cpp
Normal file → Executable file
27
src/frontend/qt_sdl/EmuThread.cpp
Normal file → Executable file
@ -485,6 +485,8 @@ void EmuThread::waitAllMessages()
|
||||
|
||||
void EmuThread::handleMessages()
|
||||
{
|
||||
bool glborrow = false;
|
||||
|
||||
msgMutex.lock();
|
||||
while (!msgQueue.empty())
|
||||
{
|
||||
@ -576,6 +578,11 @@ void EmuThread::handleMessages()
|
||||
useOpenGL = false;
|
||||
break;
|
||||
|
||||
case msg_BorrowGL:
|
||||
emuInstance->releaseGL();
|
||||
glborrow = true;
|
||||
break;
|
||||
|
||||
case msg_BootROM:
|
||||
msgResult = 0;
|
||||
if (!emuInstance->loadROM(msg.param.value<QStringList>(), true, msgError))
|
||||
@ -667,6 +674,13 @@ void EmuThread::handleMessages()
|
||||
msgSemaphore.release();
|
||||
}
|
||||
msgMutex.unlock();
|
||||
|
||||
if (glborrow)
|
||||
{
|
||||
glBorrowMutex.lock();
|
||||
glBorrowCond.wait(&glBorrowMutex);
|
||||
glBorrowMutex.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
void EmuThread::changeWindowTitle(char* title)
|
||||
@ -686,6 +700,19 @@ void EmuThread::deinitContext(int win)
|
||||
waitMessage();
|
||||
}
|
||||
|
||||
void EmuThread::borrowGL()
|
||||
{
|
||||
sendMessage(msg_BorrowGL);
|
||||
waitMessage();
|
||||
}
|
||||
|
||||
void EmuThread::returnGL()
|
||||
{
|
||||
glBorrowMutex.lock();
|
||||
glBorrowCond.wakeAll();
|
||||
glBorrowMutex.unlock();
|
||||
}
|
||||
|
||||
void EmuThread::emuRun()
|
||||
{
|
||||
sendMessage(msg_EmuRun);
|
||||
|
7
src/frontend/qt_sdl/EmuThread.h
Normal file → Executable file
7
src/frontend/qt_sdl/EmuThread.h
Normal file → Executable file
@ -22,6 +22,7 @@
|
||||
#include <QThread>
|
||||
#include <QMutex>
|
||||
#include <QSemaphore>
|
||||
#include <QWaitCondition>
|
||||
#include <QQueue>
|
||||
#include <QVariant>
|
||||
|
||||
@ -66,6 +67,7 @@ public:
|
||||
|
||||
msg_InitGL,
|
||||
msg_DeInitGL,
|
||||
msg_BorrowGL,
|
||||
|
||||
msg_BootROM,
|
||||
msg_BootFirmware,
|
||||
@ -130,12 +132,17 @@ public:
|
||||
|
||||
void initContext(int win);
|
||||
void deinitContext(int win);
|
||||
void borrowGL();
|
||||
void returnGL();
|
||||
void updateVideoSettings() { videoSettingsDirty = true; }
|
||||
void updateVideoRenderer() { videoSettingsDirty = true; lastVideoRenderer = -1; }
|
||||
|
||||
int frontBuffer = 0;
|
||||
QMutex frontBufferLock;
|
||||
|
||||
QWaitCondition glBorrowCond;
|
||||
QMutex glBorrowMutex;
|
||||
|
||||
signals:
|
||||
void windowUpdate();
|
||||
void windowTitleChange(QString title);
|
||||
|
7
src/frontend/qt_sdl/Screen.cpp
Normal file → Executable file
7
src/frontend/qt_sdl/Screen.cpp
Normal file → Executable file
@ -1055,6 +1055,13 @@ void ScreenPanelGL::makeCurrentGL()
|
||||
glContext->MakeCurrent();
|
||||
}
|
||||
|
||||
void ScreenPanelGL::releaseGL()
|
||||
{
|
||||
if (!glContext) return;
|
||||
|
||||
glContext->DoneCurrent();
|
||||
}
|
||||
|
||||
void ScreenPanelGL::osdRenderItem(OSDItem* item)
|
||||
{
|
||||
ScreenPanel::osdRenderItem(item);
|
||||
|
1
src/frontend/qt_sdl/Screen.h
Normal file → Executable file
1
src/frontend/qt_sdl/Screen.h
Normal file → Executable file
@ -189,6 +189,7 @@ public:
|
||||
void initOpenGL();
|
||||
void deinitOpenGL();
|
||||
void makeCurrentGL();
|
||||
void releaseGL();
|
||||
void drawScreenGL();
|
||||
|
||||
GL::Context* getContext() { return glContext.get(); }
|
||||
|
68
src/frontend/qt_sdl/Window.cpp
Normal file → Executable file
68
src/frontend/qt_sdl/Window.cpp
Normal file → Executable file
@ -864,7 +864,10 @@ void MainWindow::createScreenPanel()
|
||||
ScreenPanelGL* panelGL = new ScreenPanelGL(this);
|
||||
panelGL->show();
|
||||
|
||||
panel = panelGL;
|
||||
// make sure no GL context is in use by the emu thread
|
||||
// otherwise we may fail to create a shared context
|
||||
if (windowID != 0)
|
||||
emuThread->borrowGL();
|
||||
|
||||
// Check that creating the context hasn't failed
|
||||
if (panelGL->createContext() == false)
|
||||
@ -874,7 +877,15 @@ void MainWindow::createScreenPanel()
|
||||
|
||||
globalCfg.SetBool("Screen.UseGL", false);
|
||||
globalCfg.SetInt("3D.Renderer", renderer3D_Software);
|
||||
|
||||
delete panelGL;
|
||||
panelGL = nullptr;
|
||||
}
|
||||
|
||||
if (windowID != 0)
|
||||
emuThread->returnGL();
|
||||
|
||||
panel = panelGL;
|
||||
}
|
||||
|
||||
if (!hasOGL)
|
||||
@ -924,6 +935,7 @@ void MainWindow::setGLSwapInterval(int intv)
|
||||
if (!hasOGL) return;
|
||||
|
||||
ScreenPanelGL* glpanel = static_cast<ScreenPanelGL*>(panel);
|
||||
if (!glpanel) return;
|
||||
return glpanel->setSwapInterval(intv);
|
||||
}
|
||||
|
||||
@ -932,14 +944,25 @@ void MainWindow::makeCurrentGL()
|
||||
if (!hasOGL) return;
|
||||
|
||||
ScreenPanelGL* glpanel = static_cast<ScreenPanelGL*>(panel);
|
||||
if (!glpanel) return;
|
||||
return glpanel->makeCurrentGL();
|
||||
}
|
||||
|
||||
void MainWindow::releaseGL()
|
||||
{
|
||||
if (!hasOGL) return;
|
||||
|
||||
ScreenPanelGL* glpanel = static_cast<ScreenPanelGL*>(panel);
|
||||
if (!glpanel) return;
|
||||
return glpanel->releaseGL();
|
||||
}
|
||||
|
||||
void MainWindow::drawScreenGL()
|
||||
{
|
||||
if (!hasOGL) return;
|
||||
|
||||
ScreenPanelGL* glpanel = static_cast<ScreenPanelGL*>(panel);
|
||||
if (!glpanel) return;
|
||||
return glpanel->drawScreenGL();
|
||||
}
|
||||
|
||||
@ -2263,42 +2286,49 @@ void MainWindow::onUpdateVideoSettings(bool glchange)
|
||||
if (parentwin)
|
||||
return parentwin->onUpdateVideoSettings(glchange);
|
||||
|
||||
auto childwins = findChildren<MainWindow *>(nullptr, Qt::FindDirectChildrenOnly);
|
||||
|
||||
bool hadOGL = hasOGL;
|
||||
if (glchange)
|
||||
{
|
||||
emuThread->emuPause();
|
||||
if (hadOGL) emuThread->deinitContext(windowID);
|
||||
if (hadOGL)
|
||||
{
|
||||
emuThread->deinitContext(windowID);
|
||||
for (auto child: childwins)
|
||||
{
|
||||
auto thread = child->getEmuInstance()->getEmuThread();
|
||||
thread->deinitContext(child->windowID);
|
||||
}
|
||||
}
|
||||
|
||||
createScreenPanel();
|
||||
for (auto child: childwins)
|
||||
{
|
||||
child->createScreenPanel();
|
||||
}
|
||||
}
|
||||
|
||||
emuThread->updateVideoSettings();
|
||||
|
||||
if (glchange)
|
||||
{
|
||||
if (hasOGL) emuThread->initContext(windowID);
|
||||
}
|
||||
|
||||
// update any child windows we have
|
||||
auto childwins = findChildren<MainWindow *>(nullptr, Qt::FindDirectChildrenOnly);
|
||||
for (auto child: childwins)
|
||||
{
|
||||
// child windows may belong to a different instance
|
||||
// in that case we need to signal their thread appropriately
|
||||
auto thread = child->getEmuInstance()->getEmuThread();
|
||||
|
||||
if (glchange)
|
||||
{
|
||||
if (hadOGL) thread->deinitContext(child->windowID);
|
||||
child->createScreenPanel();
|
||||
}
|
||||
|
||||
if (child->getWindowID() == 0)
|
||||
thread->updateVideoSettings();
|
||||
}
|
||||
|
||||
if (glchange)
|
||||
if (glchange)
|
||||
{
|
||||
if (hasOGL)
|
||||
{
|
||||
if (hasOGL) thread->initContext(child->windowID);
|
||||
emuThread->initContext(windowID);
|
||||
for (auto child: childwins)
|
||||
{
|
||||
auto thread = child->getEmuInstance()->getEmuThread();
|
||||
thread->initContext(child->windowID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
1
src/frontend/qt_sdl/Window.h
Normal file → Executable file
1
src/frontend/qt_sdl/Window.h
Normal file → Executable file
@ -124,6 +124,7 @@ public:
|
||||
void deinitOpenGL();
|
||||
void setGLSwapInterval(int intv);
|
||||
void makeCurrentGL();
|
||||
void releaseGL();
|
||||
void drawScreenGL();
|
||||
|
||||
bool preloadROMs(QStringList file, QStringList gbafile, bool boot);
|
||||
|
Reference in New Issue
Block a user