Qt: Fix crashes on Windows by using using QMetaObject to do cross-thread calls

This commit is contained in:
Jeffrey Pfau 2015-08-09 23:25:03 -07:00
parent 709f4f7a83
commit 9352f75e6f
3 changed files with 11 additions and 8 deletions

View File

@ -69,6 +69,7 @@ Bugfixes:
- Qt: Fix analog buttons not getting unmapped - Qt: Fix analog buttons not getting unmapped
- GBA Video: Prevent tiles < 512 from being used in modes 3 - 5 - GBA Video: Prevent tiles < 512 from being used in modes 3 - 5
- Qt: Fix passing command line options - Qt: Fix passing command line options
- Qt: Fix crashes on Windows by using using QMetaObject to do cross-thread calls
Misc: Misc:
- Qt: Handle saving input settings better - Qt: Handle saving input settings better
- Debugger: Free watchpoints in addition to breakpoints - Debugger: Free watchpoints in addition to breakpoints

View File

@ -15,6 +15,7 @@
#include <QIcon> #include <QIcon>
extern "C" { extern "C" {
#include "gba/supervisor/thread.h"
#include "platform/commandline.h" #include "platform/commandline.h"
#include "util/socket.h" #include "util/socket.h"
} }
@ -37,6 +38,7 @@ GBAApp::GBAApp(int& argc, char* argv[])
SocketSubsystemInit(); SocketSubsystemInit();
qRegisterMetaType<const uint32_t*>("const uint32_t*"); qRegisterMetaType<const uint32_t*>("const uint32_t*");
qRegisterMetaType<GBAThread*>("GBAThread*");
QApplication::setApplicationName(projectName); QApplication::setApplicationName(projectName);
QApplication::setApplicationVersion(projectVersion); QApplication::setApplicationVersion(projectVersion);

View File

@ -114,25 +114,25 @@ GameController::GameController(QObject* parent)
vf->truncate(vf, 0); vf->truncate(vf, 0);
} }
} }
controller->gameStarted(context); QMetaObject::invokeMethod(controller, "gameStarted", Q_ARG(GBAThread*, context));
}; };
m_threadContext.cleanCallback = [](GBAThread* context) { m_threadContext.cleanCallback = [](GBAThread* context) {
GameController* controller = static_cast<GameController*>(context->userData); GameController* controller = static_cast<GameController*>(context->userData);
controller->gameStopped(context); QMetaObject::invokeMethod(controller, "gameStopped", Q_ARG(GBAThread*, context));
}; };
m_threadContext.frameCallback = [](GBAThread* context) { m_threadContext.frameCallback = [](GBAThread* context) {
GameController* controller = static_cast<GameController*>(context->userData); GameController* controller = static_cast<GameController*>(context->userData);
if (GBASyncDrawingFrame(&controller->m_threadContext.sync)) { if (GBASyncDrawingFrame(&controller->m_threadContext.sync)) {
memcpy(controller->m_frontBuffer, controller->m_drawContext, 256 * VIDEO_HORIZONTAL_PIXELS * BYTES_PER_PIXEL); memcpy(controller->m_frontBuffer, controller->m_drawContext, 256 * VIDEO_HORIZONTAL_PIXELS * BYTES_PER_PIXEL);
controller->frameAvailable(controller->m_frontBuffer); QMetaObject::invokeMethod(controller, "frameAvailable", Q_ARG(const uint32_t*, controller->m_frontBuffer));
} else { } else {
controller->frameAvailable(nullptr); QMetaObject::invokeMethod(controller, "frameAvailable", Q_ARG(const uint32_t*, nullptr));
} }
if (controller->m_pauseAfterFrame.testAndSetAcquire(true, false)) { if (controller->m_pauseAfterFrame.testAndSetAcquire(true, false)) {
GBAThreadPauseFromThread(context); GBAThreadPauseFromThread(context);
controller->gamePaused(&controller->m_threadContext); QMetaObject::invokeMethod(controller, "gamePaused", Q_ARG(GBAThread*, context));
} }
}; };
@ -161,7 +161,7 @@ GameController::GameController(QObject* parent)
va_copy(argc, args); va_copy(argc, args);
int immediate = va_arg(argc, int); int immediate = va_arg(argc, int);
va_end(argc); va_end(argc);
controller->unimplementedBiosCall(immediate); QMetaObject::invokeMethod(controller, "unimplementedBiosCall", Q_ARG(int, immediate));
} else if (level == GBA_LOG_STATUS) { } else if (level == GBA_LOG_STATUS) {
// Slot 0 is reserved for suspend points // Slot 0 is reserved for suspend points
if (strncmp(savestateMessage, format, strlen(savestateMessage)) == 0) { if (strncmp(savestateMessage, format, strlen(savestateMessage)) == 0) {
@ -189,9 +189,9 @@ GameController::GameController(QObject* parent)
} }
QString message(QString().vsprintf(format, args)); QString message(QString().vsprintf(format, args));
if (level == GBA_LOG_STATUS) { if (level == GBA_LOG_STATUS) {
controller->statusPosted(message); QMetaObject::invokeMethod(controller, "statusPosted", Q_ARG(const QString&, message));
} }
controller->postLog(level, message); QMetaObject::invokeMethod(controller, "postLog", Q_ARG(int, level), Q_ARG(const QString&, message));
}; };
connect(&m_rewindTimer, &QTimer::timeout, [this]() { connect(&m_rewindTimer, &QTimer::timeout, [this]() {