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
- GBA Video: Prevent tiles < 512 from being used in modes 3 - 5
- Qt: Fix passing command line options
- Qt: Fix crashes on Windows by using using QMetaObject to do cross-thread calls
Misc:
- Qt: Handle saving input settings better
- Debugger: Free watchpoints in addition to breakpoints

View File

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

View File

@ -114,25 +114,25 @@ GameController::GameController(QObject* parent)
vf->truncate(vf, 0);
}
}
controller->gameStarted(context);
QMetaObject::invokeMethod(controller, "gameStarted", Q_ARG(GBAThread*, context));
};
m_threadContext.cleanCallback = [](GBAThread* context) {
GameController* controller = static_cast<GameController*>(context->userData);
controller->gameStopped(context);
QMetaObject::invokeMethod(controller, "gameStopped", Q_ARG(GBAThread*, context));
};
m_threadContext.frameCallback = [](GBAThread* context) {
GameController* controller = static_cast<GameController*>(context->userData);
if (GBASyncDrawingFrame(&controller->m_threadContext.sync)) {
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 {
controller->frameAvailable(nullptr);
QMetaObject::invokeMethod(controller, "frameAvailable", Q_ARG(const uint32_t*, nullptr));
}
if (controller->m_pauseAfterFrame.testAndSetAcquire(true, false)) {
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);
int immediate = va_arg(argc, int);
va_end(argc);
controller->unimplementedBiosCall(immediate);
QMetaObject::invokeMethod(controller, "unimplementedBiosCall", Q_ARG(int, immediate));
} else if (level == GBA_LOG_STATUS) {
// Slot 0 is reserved for suspend points
if (strncmp(savestateMessage, format, strlen(savestateMessage)) == 0) {
@ -189,9 +189,9 @@ GameController::GameController(QObject* parent)
}
QString message(QString().vsprintf(format, args));
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]() {