summaryrefslogtreecommitdiff
path: root/src/citra_qt/bootmanager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/citra_qt/bootmanager.cpp')
-rw-r--r--src/citra_qt/bootmanager.cpp103
1 files changed, 24 insertions, 79 deletions
diff --git a/src/citra_qt/bootmanager.cpp b/src/citra_qt/bootmanager.cpp
index b81bd6167..a7f949411 100644
--- a/src/citra_qt/bootmanager.cpp
+++ b/src/citra_qt/bootmanager.cpp
@@ -10,6 +10,7 @@
10 10
11#include "common/common.h" 11#include "common/common.h"
12#include "bootmanager.h" 12#include "bootmanager.h"
13#include "main.h"
13 14
14#include "core/core.h" 15#include "core/core.h"
15#include "core/settings.h" 16#include "core/settings.h"
@@ -27,43 +28,33 @@
27#define COPYRIGHT "Copyright (C) 2013-2014 Citra Team" 28#define COPYRIGHT "Copyright (C) 2013-2014 Citra Team"
28 29
29EmuThread::EmuThread(GRenderWindow* render_window) : 30EmuThread::EmuThread(GRenderWindow* render_window) :
30 filename(""), exec_cpu_step(false), cpu_running(false), 31 exec_step(false), running(false), stop_run(false), render_window(render_window) {
31 stop_run(false), render_window(render_window)
32{
33}
34 32
35void EmuThread::SetFilename(std::string filename) 33 connect(this, SIGNAL(started()), render_window, SLOT(moveContext()));
36{
37 this->filename = filename;
38} 34}
39 35
40void EmuThread::run() 36void EmuThread::run() {
41{
42 stop_run = false; 37 stop_run = false;
43 38
44 // holds whether the cpu was running during the last iteration, 39 // holds whether the cpu was running during the last iteration,
45 // so that the DebugModeLeft signal can be emitted before the 40 // so that the DebugModeLeft signal can be emitted before the
46 // next execution step 41 // next execution step
47 bool was_active = false; 42 bool was_active = false;
48 while (!stop_run) 43 while (!stop_run) {
49 { 44 if (running) {
50 if (cpu_running)
51 {
52 if (!was_active) 45 if (!was_active)
53 emit DebugModeLeft(); 46 emit DebugModeLeft();
54 47
55 Core::RunLoop(); 48 Core::RunLoop();
56 49
57 was_active = cpu_running || exec_cpu_step; 50 was_active = running || exec_step;
58 if (!was_active) 51 if (!was_active && !stop_run)
59 emit DebugModeEntered(); 52 emit DebugModeEntered();
60 } 53 } else if (exec_step) {
61 else if (exec_cpu_step)
62 {
63 if (!was_active) 54 if (!was_active)
64 emit DebugModeLeft(); 55 emit DebugModeLeft();
65 56
66 exec_cpu_step = false; 57 exec_step = false;
67 Core::SingleStep(); 58 Core::SingleStep();
68 emit DebugModeEntered(); 59 emit DebugModeEntered();
69 yieldCurrentThread(); 60 yieldCurrentThread();
@@ -71,47 +62,10 @@ void EmuThread::run()
71 was_active = false; 62 was_active = false;
72 } 63 }
73 } 64 }
74 render_window->moveContext();
75
76 Core::Stop();
77}
78
79void EmuThread::Stop()
80{
81 if (!isRunning())
82 {
83 LOG_WARNING(Frontend, "EmuThread::Stop called while emu thread wasn't running, returning...");
84 return;
85 }
86 stop_run = true;
87 65
88 // Release emu threads from any breakpoints, so that this doesn't hang forever. 66 render_window->moveContext();
89 Pica::g_debug_context->ClearBreakpoints();
90
91 //core::g_state = core::SYS_DIE;
92
93 // TODO: Waiting here is just a bad workaround for retarded shutdown logic.
94 wait(1000);
95 if (isRunning())
96 {
97 LOG_WARNING(Frontend, "EmuThread still running, terminating...");
98 quit();
99
100 // TODO: Waiting 50 seconds can be necessary if the logging subsystem has a lot of spam
101 // queued... This should be fixed.
102 wait(50000);
103 if (isRunning())
104 {
105 LOG_CRITICAL(Frontend, "EmuThread STILL running, something is wrong here...");
106 terminate();
107 }
108 }
109 LOG_INFO(Frontend, "EmuThread stopped");
110
111 System::Shutdown();
112} 67}
113 68
114
115// This class overrides paintEvent and resizeEvent to prevent the GUI thread from stealing GL context. 69// This class overrides paintEvent and resizeEvent to prevent the GUI thread from stealing GL context.
116// The corresponding functionality is handled in EmuThread instead 70// The corresponding functionality is handled in EmuThread instead
117class GGLWidgetInternal : public QGLWidget 71class GGLWidgetInternal : public QGLWidget
@@ -133,13 +87,9 @@ private:
133 GRenderWindow* parent; 87 GRenderWindow* parent;
134}; 88};
135 89
136EmuThread& GRenderWindow::GetEmuThread() 90GRenderWindow::GRenderWindow(QWidget* parent, EmuThread* emu_thread) :
137{ 91 QWidget(parent), emu_thread(emu_thread), keyboard_id(0) {
138 return emu_thread;
139}
140 92
141GRenderWindow::GRenderWindow(QWidget* parent) : QWidget(parent), emu_thread(this), keyboard_id(0)
142{
143 std::string window_title = Common::StringFromFormat("Citra | %s-%s", Common::g_scm_branch, Common::g_scm_desc); 93 std::string window_title = Common::StringFromFormat("Citra | %s-%s", Common::g_scm_branch, Common::g_scm_desc);
144 setWindowTitle(QString::fromStdString(window_title)); 94 setWindowTitle(QString::fromStdString(window_title));
145 95
@@ -160,7 +110,6 @@ GRenderWindow::GRenderWindow(QWidget* parent) : QWidget(parent), emu_thread(this
160 layout->addWidget(child); 110 layout->addWidget(child);
161 layout->setMargin(0); 111 layout->setMargin(0);
162 setLayout(layout); 112 setLayout(layout);
163 connect(&emu_thread, SIGNAL(started()), this, SLOT(moveContext()));
164 113
165 OnMinimalClientAreaChangeRequest(GetActiveConfig().min_client_area_size); 114 OnMinimalClientAreaChangeRequest(GetActiveConfig().min_client_area_size);
166 115
@@ -180,29 +129,17 @@ void GRenderWindow::moveContext()
180 // We need to move GL context to the swapping thread in Qt5 129 // We need to move GL context to the swapping thread in Qt5
181#if QT_VERSION > QT_VERSION_CHECK(5, 0, 0) 130#if QT_VERSION > QT_VERSION_CHECK(5, 0, 0)
182 // If the thread started running, move the GL Context to the new thread. Otherwise, move it back. 131 // If the thread started running, move the GL Context to the new thread. Otherwise, move it back.
183 child->context()->moveToThread((QThread::currentThread() == qApp->thread()) ? &emu_thread : qApp->thread()); 132 auto thread = (QThread::currentThread() == qApp->thread() && emu_thread != nullptr) ? emu_thread : qApp->thread();
133 child->context()->moveToThread(thread);
184#endif 134#endif
185} 135}
186 136
187GRenderWindow::~GRenderWindow()
188{
189 if (emu_thread.isRunning())
190 emu_thread.Stop();
191}
192
193void GRenderWindow::SwapBuffers() 137void GRenderWindow::SwapBuffers()
194{ 138{
195 // MakeCurrent is already called in renderer_opengl 139 // MakeCurrent is already called in renderer_opengl
196 child->swapBuffers(); 140 child->swapBuffers();
197} 141}
198 142
199void GRenderWindow::closeEvent(QCloseEvent* event)
200{
201 if (emu_thread.isRunning())
202 emu_thread.Stop();
203 QWidget::closeEvent(event);
204}
205
206void GRenderWindow::MakeCurrent() 143void GRenderWindow::MakeCurrent()
207{ 144{
208 child->makeCurrent(); 145 child->makeCurrent();
@@ -288,7 +225,7 @@ void GRenderWindow::mousePressEvent(QMouseEvent *event)
288void GRenderWindow::mouseMoveEvent(QMouseEvent *event) 225void GRenderWindow::mouseMoveEvent(QMouseEvent *event)
289{ 226{
290 auto pos = event->pos(); 227 auto pos = event->pos();
291 this->TouchMoved(static_cast<unsigned>(pos.x()), static_cast<unsigned>(pos.y())); 228 this->TouchMoved(static_cast<unsigned>(std::max(pos.x(), 0)), static_cast<unsigned>(std::max(pos.y(), 0)));
292} 229}
293 230
294void GRenderWindow::mouseReleaseEvent(QMouseEvent *event) 231void GRenderWindow::mouseReleaseEvent(QMouseEvent *event)
@@ -335,3 +272,11 @@ void GRenderWindow::OnClientAreaResized(unsigned width, unsigned height)
335void GRenderWindow::OnMinimalClientAreaChangeRequest(const std::pair<unsigned,unsigned>& minimal_size) { 272void GRenderWindow::OnMinimalClientAreaChangeRequest(const std::pair<unsigned,unsigned>& minimal_size) {
336 setMinimumSize(minimal_size.first, minimal_size.second); 273 setMinimumSize(minimal_size.first, minimal_size.second);
337} 274}
275
276void GRenderWindow::OnEmulationStarting(EmuThread* emu_thread) {
277 this->emu_thread = emu_thread;
278}
279
280void GRenderWindow::OnEmulationStopping() {
281 emu_thread = nullptr;
282}