Merge pull request #75 from xsacha/qt5

Fix threading for Qt5.
This commit is contained in:
bunnei 2014-08-24 22:25:35 -04:00
commit 613b0a8df8
4 changed files with 41 additions and 18 deletions

View file

@ -1,5 +1,6 @@
#include <QHBoxLayout> #include <QHBoxLayout>
#include <QKeyEvent> #include <QKeyEvent>
#include <QApplication>
#include "common/common.h" #include "common/common.h"
#include "bootmanager.hxx" #include "bootmanager.hxx"
@ -19,7 +20,8 @@
EmuThread::EmuThread(GRenderWindow* render_window) : EmuThread::EmuThread(GRenderWindow* render_window) :
exec_cpu_step(false), cpu_running(false), exec_cpu_step(false), cpu_running(false),
render_window(render_window), filename("") render_window(render_window), filename(""),
stop_run(false)
{ {
} }
@ -30,7 +32,8 @@ void EmuThread::SetFilename(std::string filename)
void EmuThread::run() void EmuThread::run()
{ {
while (true) stop_run = false;
while (!stop_run)
{ {
for (int tight_loop = 0; tight_loop < 10000; ++tight_loop) for (int tight_loop = 0; tight_loop < 10000; ++tight_loop)
{ {
@ -40,11 +43,14 @@ void EmuThread::run()
exec_cpu_step = false; exec_cpu_step = false;
Core::SingleStep(); Core::SingleStep();
if (!cpu_running) if (!cpu_running) {
emit CPUStepped(); emit CPUStepped();
yieldCurrentThread();
}
} }
} }
} }
render_window->moveContext();
Core::Stop(); Core::Stop();
} }
@ -56,17 +62,21 @@ void EmuThread::Stop()
INFO_LOG(MASTER_LOG, "EmuThread::Stop called while emu thread wasn't running, returning..."); INFO_LOG(MASTER_LOG, "EmuThread::Stop called while emu thread wasn't running, returning...");
return; return;
} }
stop_run = true;
//core::g_state = core::SYS_DIE; //core::g_state = core::SYS_DIE;
wait(1000); wait(500);
if (isRunning()) if (isRunning())
{ {
WARN_LOG(MASTER_LOG, "EmuThread still running, terminating..."); WARN_LOG(MASTER_LOG, "EmuThread still running, terminating...");
terminate(); quit();
wait(1000); wait(1000);
if (isRunning()) if (isRunning())
{
WARN_LOG(MASTER_LOG, "EmuThread STILL running, something is wrong here..."); WARN_LOG(MASTER_LOG, "EmuThread STILL running, something is wrong here...");
terminate();
}
} }
INFO_LOG(MASTER_LOG, "EmuThread stopped"); INFO_LOG(MASTER_LOG, "EmuThread stopped");
} }
@ -77,17 +87,13 @@ void EmuThread::Stop()
class GGLWidgetInternal : public QGLWidget class GGLWidgetInternal : public QGLWidget
{ {
public: public:
GGLWidgetInternal(QGLFormat fmt, GRenderWindow* parent) : QGLWidget(parent) GGLWidgetInternal(QGLFormat fmt, GRenderWindow* parent) : QGLWidget(fmt, parent)
{ {
doneCurrent();
parent_ = parent; parent_ = parent;
} }
void paintEvent(QPaintEvent* ev) void paintEvent(QPaintEvent* ev)
{ {
// Apparently, Windows doesn't display anything if we don't call this here.
// TODO: Breaks linux though because we aren't calling doneCurrent() ... -.-
// makeCurrent();
} }
void resizeEvent(QResizeEvent* ev) { void resizeEvent(QResizeEvent* ev) {
parent_->SetClientAreaWidth(size().width()); parent_->SetClientAreaWidth(size().width());
@ -118,24 +124,37 @@ GRenderWindow::GRenderWindow(QWidget* parent) : QWidget(parent), emu_thread(this
layout->addWidget(child); layout->addWidget(child);
layout->setMargin(0); layout->setMargin(0);
setLayout(layout); setLayout(layout);
QObject::connect(&emu_thread, SIGNAL(started()), this, SLOT(moveContext()));
BackupGeometry(); BackupGeometry();
} }
void GRenderWindow::moveContext()
{
DoneCurrent();
// We need to move GL context to the swapping thread in Qt5
#if QT_VERSION > QT_VERSION_CHECK(5, 0, 0)
// If the thread started running, move the GL Context to the new thread. Otherwise, move it back.
child->context()->moveToThread((QThread::currentThread() == qApp->thread()) ? &emu_thread : qApp->thread());
#endif
}
GRenderWindow::~GRenderWindow() GRenderWindow::~GRenderWindow()
{ {
emu_thread.Stop(); if (emu_thread.isRunning())
emu_thread.Stop();
} }
void GRenderWindow::SwapBuffers() void GRenderWindow::SwapBuffers()
{ {
child->makeCurrent(); // TODO: Not necessary? // MakeCurrent is already called in renderer_opengl
child->swapBuffers(); child->swapBuffers();
} }
void GRenderWindow::closeEvent(QCloseEvent* event) void GRenderWindow::closeEvent(QCloseEvent* event)
{ {
emu_thread.Stop(); if (emu_thread.isRunning())
emu_thread.Stop();
QWidget::closeEvent(event); QWidget::closeEvent(event);
} }
@ -212,4 +231,5 @@ void GRenderWindow::keyReleaseEvent(QKeyEvent* event)
if (!key_processed) if (!key_processed)
QWidget::keyPressEvent(event); QWidget::keyPressEvent(event);
*/ */
} }

View file

@ -1,5 +1,6 @@
#include <QThread> #include <QThread>
#include <QGLWidget> #include <QGLWidget>
#include <atomic>
#include "common/common.h" #include "common/common.h"
#include "common/emu_window.h" #include "common/emu_window.h"
@ -66,6 +67,7 @@ private:
bool exec_cpu_step; bool exec_cpu_step;
bool cpu_running; bool cpu_running;
std::atomic<bool> stop_run;
GRenderWindow* render_window; GRenderWindow* render_window;
@ -81,6 +83,8 @@ signals:
class GRenderWindow : public QWidget, public EmuWindow class GRenderWindow : public QWidget, public EmuWindow
{ {
Q_OBJECT
public: public:
GRenderWindow(QWidget* parent = NULL); GRenderWindow(QWidget* parent = NULL);
~GRenderWindow(); ~GRenderWindow();
@ -103,6 +107,9 @@ public:
void keyPressEvent(QKeyEvent* event); void keyPressEvent(QKeyEvent* event);
void keyReleaseEvent(QKeyEvent* event); void keyReleaseEvent(QKeyEvent* event);
public slots:
void moveContext();
private: private:
QGLWidget* child; QGLWidget* child;

View file

@ -142,7 +142,6 @@ void GMainWindow::BootGame(std::string filename)
registersWidget->OnCPUStepped(); registersWidget->OnCPUStepped();
callstackWidget->OnCPUStepped(); callstackWidget->OnCPUStepped();
render_window->DoneCurrent(); // make sure EmuThread can access GL context
render_window->GetEmuThread().SetFilename(filename); render_window->GetEmuThread().SetFilename(filename);
render_window->GetEmuThread().start(); render_window->GetEmuThread().start();
@ -204,7 +203,6 @@ void GMainWindow::ToggleWindowMode()
ui.horizontalLayout->removeWidget(render_window); ui.horizontalLayout->removeWidget(render_window);
render_window->setParent(NULL); render_window->setParent(NULL);
render_window->setVisible(true); render_window->setVisible(true);
render_window->DoneCurrent();
render_window->RestoreGeometry(); render_window->RestoreGeometry();
} }
else if (!enable && render_window->parent() == NULL) else if (!enable && render_window->parent() == NULL)
@ -212,7 +210,6 @@ void GMainWindow::ToggleWindowMode()
render_window->BackupGeometry(); render_window->BackupGeometry();
ui.horizontalLayout->addWidget(render_window); ui.horizontalLayout->addWidget(render_window);
render_window->setVisible(true); render_window->setVisible(true);
render_window->DoneCurrent();
} }
} }

View file

@ -36,7 +36,6 @@ void Init(EmuWindow* emu_window) {
glewExperimental = GL_TRUE; glewExperimental = GL_TRUE;
g_emu_window = emu_window; g_emu_window = emu_window;
g_emu_window->MakeCurrent();
g_renderer = new RendererOpenGL(); g_renderer = new RendererOpenGL();
g_renderer->SetWindow(g_emu_window); g_renderer->SetWindow(g_emu_window);
g_renderer->Init(); g_renderer->Init();