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