Просмотр исходного кода

Merge pull request #75 from xsacha/qt5

Fix threading for Qt5.
bunnei 12 лет назад
Родитель
Сommit
613b0a8df8
4 измененных файлов с 41 добавлено и 18 удалено
  1. 34 14
      src/citra_qt/bootmanager.cpp
  2. 7 0
      src/citra_qt/bootmanager.hxx
  3. 0 3
      src/citra_qt/main.cpp
  4. 0 1
      src/video_core/video_core.cpp

+ 34 - 14
src/citra_qt/bootmanager.cpp

@@ -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);
     */
     */
-}
+}
+

+ 7 - 0
src/citra_qt/bootmanager.hxx

@@ -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;
 
 

+ 0 - 3
src/citra_qt/main.cpp

@@ -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();
     }
     }
 }
 }
 
 

+ 0 - 1
src/video_core/video_core.cpp

@@ -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();