Qt: Make renderer able to be changed while running

This commit is contained in:
Vicki Pfau 2020-01-30 21:26:58 -08:00
parent 74af414b96
commit b922cecc61
7 changed files with 92 additions and 47 deletions

View File

@ -22,6 +22,8 @@ Other fixes:
- Qt: Fix crash unloading shaders - Qt: Fix crash unloading shaders
- Qt: Fix toggled actions on gamepads (fixes mgba.io/i/1650) - Qt: Fix toggled actions on gamepads (fixes mgba.io/i/1650)
- Qt: Fix extraneous dialog (fixes mgba.io/i/1654) - Qt: Fix extraneous dialog (fixes mgba.io/i/1654)
Misc:
- Qt: Renderer can be changed while a game is running
0.8.0: (2020-01-21) 0.8.0: (2020-01-21)
Features: Features:

View File

@ -347,8 +347,9 @@ static void _GBACoreReloadConfigOption(struct mCore* core, const char* option, c
} }
return; return;
} }
#if defined(BUILD_GLES2) || defined(BUILD_GLES3)
struct GBACore* gbacore = (struct GBACore*) core; struct GBACore* gbacore = (struct GBACore*) core;
#if defined(BUILD_GLES2) || defined(BUILD_GLES3)
if (strcmp("videoScale", option) == 0) { if (strcmp("videoScale", option) == 0) {
if (config != &core->config) { if (config != &core->config) {
mCoreConfigCopyValue(&core->config, config, "videoScale"); mCoreConfigCopyValue(&core->config, config, "videoScale");
@ -361,6 +362,31 @@ static void _GBACoreReloadConfigOption(struct mCore* core, const char* option, c
return; return;
} }
#endif #endif
if (strcmp("hwaccelVideo", option) == 0) {
struct GBAVideoRenderer* renderer = NULL;
if (gbacore->renderer.outputBuffer) {
renderer = &gbacore->renderer.d;
}
int fakeBool;
#if defined(BUILD_GLES2) || defined(BUILD_GLES3)
if (gbacore->glRenderer.outputTex != (unsigned) -1 && mCoreConfigGetIntValue(&core->config, "hwaccelVideo", &fakeBool) && fakeBool) {
mCoreConfigGetIntValue(&core->config, "videoScale", &gbacore->glRenderer.scale);
renderer = &gbacore->glRenderer.d;
} else {
gbacore->glRenderer.scale = 1;
}
#endif
#ifndef MINIMAL_CORE
if (renderer && core->videoLogger) {
gbacore->proxyRenderer.logger = core->videoLogger;
GBAVideoProxyRendererCreate(&gbacore->proxyRenderer, renderer);
renderer = &gbacore->proxyRenderer.d;
}
#endif
if (renderer) {
GBAVideoAssociateRenderer(&gba->video, renderer);
}
}
} }
static void _GBACoreDesiredVideoDimensions(struct mCore* core, unsigned* width, unsigned* height) { static void _GBACoreDesiredVideoDimensions(struct mCore* core, unsigned* width, unsigned* height) {
@ -529,8 +555,10 @@ static void _GBACoreReset(struct mCore* core) {
int fakeBool; int fakeBool;
#if defined(BUILD_GLES2) || defined(BUILD_GLES3) #if defined(BUILD_GLES2) || defined(BUILD_GLES3)
if (gbacore->glRenderer.outputTex != (unsigned) -1 && mCoreConfigGetIntValue(&core->config, "hwaccelVideo", &fakeBool) && fakeBool) { if (gbacore->glRenderer.outputTex != (unsigned) -1 && mCoreConfigGetIntValue(&core->config, "hwaccelVideo", &fakeBool) && fakeBool) {
renderer = &gbacore->glRenderer.d;
mCoreConfigGetIntValue(&core->config, "videoScale", &gbacore->glRenderer.scale); mCoreConfigGetIntValue(&core->config, "videoScale", &gbacore->glRenderer.scale);
renderer = &gbacore->glRenderer.d;
} else {
gbacore->glRenderer.scale = 1;
} }
#endif #endif
#ifndef DISABLE_THREADING #ifndef DISABLE_THREADING

View File

@ -143,8 +143,8 @@ void GBAVideoProxyRendererDeinit(struct GBAVideoRenderer* renderer) {
if (!proxyRenderer->logger->block) { if (!proxyRenderer->logger->block) {
proxyRenderer->backend->deinit(proxyRenderer->backend); proxyRenderer->backend->deinit(proxyRenderer->backend);
} else { } else {
proxyRenderer->logger->postEvent(proxyRenderer->logger, LOGGER_EVENT_DEINIT);
mVideoLoggerRendererFlush(proxyRenderer->logger); mVideoLoggerRendererFlush(proxyRenderer->logger);
proxyRenderer->logger->postEvent(proxyRenderer->logger, LOGGER_EVENT_DEINIT);
} }
mVideoLoggerRendererDeinit(proxyRenderer->logger); mVideoLoggerRendererDeinit(proxyRenderer->logger);

View File

@ -81,9 +81,7 @@ CoreController::CoreController(mCore* core, QObject* parent)
controller->m_resetActions.clear(); controller->m_resetActions.clear();
if (!controller->m_hwaccel) { context->core->setVideoBuffer(context->core, reinterpret_cast<color_t*>(controller->m_activeBuffer.data()), controller->screenDimensions().width());
context->core->setVideoBuffer(context->core, reinterpret_cast<color_t*>(controller->m_activeBuffer.data()), controller->screenDimensions().width());
}
QMetaObject::invokeMethod(controller, "didReset"); QMetaObject::invokeMethod(controller, "didReset");
controller->finishFrame(); controller->finishFrame();
@ -358,14 +356,12 @@ void CoreController::setLogger(LogController* logger) {
} }
void CoreController::start() { void CoreController::start() {
if (!m_hwaccel) { QSize size(256, 224);
QSize size(256, 224); m_activeBuffer.resize(size.width() * size.height() * sizeof(color_t));
m_activeBuffer.resize(size.width() * size.height() * sizeof(color_t)); m_activeBuffer.fill(0xFF);
m_activeBuffer.fill(0xFF); m_completeBuffer = m_activeBuffer;
m_completeBuffer = m_activeBuffer;
m_threadContext.core->setVideoBuffer(m_threadContext.core, reinterpret_cast<color_t*>(m_activeBuffer.data()), size.width()); m_threadContext.core->setVideoBuffer(m_threadContext.core, reinterpret_cast<color_t*>(m_activeBuffer.data()), size.width());
}
if (!m_patched) { if (!m_patched) {
mCoreAutoloadPatch(m_threadContext.core); mCoreAutoloadPatch(m_threadContext.core);
@ -860,11 +856,23 @@ void CoreController::endVideoLog(bool closeVf) {
void CoreController::setFramebufferHandle(int fb) { void CoreController::setFramebufferHandle(int fb) {
Interrupter interrupter(this); Interrupter interrupter(this);
if (fb < 0) { if (fb < 0) {
if (!m_hwaccel) {
return;
}
mCoreConfigSetIntValue(&m_threadContext.core->config, "hwaccelVideo", 0);
m_threadContext.core->setVideoGLTex(m_threadContext.core, -1);
m_hwaccel = false; m_hwaccel = false;
} else { } else {
mCoreConfigSetIntValue(&m_threadContext.core->config, "hwaccelVideo", 1);
m_threadContext.core->setVideoGLTex(m_threadContext.core, fb); m_threadContext.core->setVideoGLTex(m_threadContext.core, fb);
if (m_hwaccel) {
return;
}
m_hwaccel = true; m_hwaccel = true;
} }
if (hasStarted()) {
m_threadContext.core->reloadConfigOption(m_threadContext.core, "hwaccelVideo", NULL);
}
} }
void CoreController::updateKeys() { void CoreController::updateKeys() {

View File

@ -493,12 +493,13 @@ void SettingsView::updateConfig() {
} }
int videoScale = m_controller->getOption("videoScale", 1).toInt(); int videoScale = m_controller->getOption("videoScale", 1).toInt();
saveSetting("videoScale", m_ui.videoScale);
int hwaccelVideo = m_controller->getOption("hwaccelVideo").toInt(); int hwaccelVideo = m_controller->getOption("hwaccelVideo").toInt();
saveSetting("hwaccelVideo", m_ui.hwaccelVideo->currentIndex());
if (hwaccelVideo != m_ui.hwaccelVideo->currentIndex()) { if (hwaccelVideo != m_ui.hwaccelVideo->currentIndex()) {
emit videoRendererChanged(); emit videoRendererChanged();
} }
saveSetting("videoScale", m_ui.videoScale);
saveSetting("hwaccelVideo", m_ui.hwaccelVideo->currentIndex());
m_logModel.save(m_controller); m_logModel.save(m_controller);
m_logModel.logger()->setLogFile(m_ui.logFile->text()); m_logModel.logger()->setLogFile(m_ui.logFile->text());

View File

@ -461,7 +461,7 @@ void Window::openSettingsWindow() {
connect(settingsWindow, &SettingsView::audioDriverChanged, this, &Window::reloadAudioDriver); connect(settingsWindow, &SettingsView::audioDriverChanged, this, &Window::reloadAudioDriver);
connect(settingsWindow, &SettingsView::cameraDriverChanged, this, &Window::mustRestart); connect(settingsWindow, &SettingsView::cameraDriverChanged, this, &Window::mustRestart);
connect(settingsWindow, &SettingsView::cameraChanged, &m_inputController, &InputController::setCamera); connect(settingsWindow, &SettingsView::cameraChanged, &m_inputController, &InputController::setCamera);
connect(settingsWindow, &SettingsView::videoRendererChanged, this, &Window::mustRestart); connect(settingsWindow, &SettingsView::videoRendererChanged, this, &Window::changeRenderer);
connect(settingsWindow, &SettingsView::languageChanged, this, &Window::mustRestart); connect(settingsWindow, &SettingsView::languageChanged, this, &Window::mustRestart);
connect(settingsWindow, &SettingsView::pathsChanged, this, &Window::reloadConfig); connect(settingsWindow, &SettingsView::pathsChanged, this, &Window::reloadConfig);
#ifdef USE_SQLITE3 #ifdef USE_SQLITE3
@ -883,10 +883,6 @@ void Window::unimplementedBiosCall(int call) {
void Window::reloadDisplayDriver() { void Window::reloadDisplayDriver() {
if (m_controller) { if (m_controller) {
if (m_controller->hardwareAccelerated()) {
mustRestart();
return;
}
m_display->stopDrawing(); m_display->stopDrawing();
detachWidget(m_display.get()); detachWidget(m_display.get());
} }
@ -924,14 +920,7 @@ void Window::reloadDisplayDriver() {
#endif #endif
if (m_controller) { if (m_controller) {
connect(m_controller.get(), &CoreController::stateLoaded, m_display.get(), &Display::resizeContext); attachDisplay();
connect(m_controller.get(), &CoreController::stateLoaded, m_display.get(), &Display::forceDraw);
connect(m_controller.get(), &CoreController::rewound, m_display.get(), &Display::forceDraw);
connect(m_controller.get(), &CoreController::paused, m_display.get(), &Display::pauseDrawing);
connect(m_controller.get(), &CoreController::unpaused, m_display.get(), &Display::unpauseDrawing);
connect(m_controller.get(), &CoreController::frameAvailable, m_display.get(), &Display::framePosted);
connect(m_controller.get(), &CoreController::statusPosted, m_display.get(), &Display::showMessage);
connect(m_controller.get(), &CoreController::didReset, m_display.get(), &Display::resizeContext);
attachWidget(m_display.get()); attachWidget(m_display.get());
m_display->startDrawing(m_controller); m_display->startDrawing(m_controller);
@ -962,6 +951,27 @@ void Window::reloadAudioDriver() {
connect(m_controller.get(), &CoreController::fastForwardChanged, m_audioProcessor.get(), &AudioProcessor::inputParametersChanged); connect(m_controller.get(), &CoreController::fastForwardChanged, m_audioProcessor.get(), &AudioProcessor::inputParametersChanged);
} }
void Window::changeRenderer() {
if (!m_controller) {
return;
}
if (m_config->getOption("hwaccelVideo").toInt() && m_display->supportsShaders() && m_controller->supportsFeature(CoreController::Feature::OPENGL)) {
std::shared_ptr<VideoProxy> proxy = m_display->videoProxy();
if (!proxy) {
proxy = std::make_shared<VideoProxy>();
}
m_display->setVideoProxy(proxy);
proxy->attach(m_controller.get());
int fb = m_display->framebufferHandle();
if (fb >= 0) {
m_controller->setFramebufferHandle(fb);
}
} else {
m_controller->setFramebufferHandle(-1);
}
}
void Window::tryMakePortable() { void Window::tryMakePortable() {
QMessageBox* confirm = new QMessageBox(QMessageBox::Question, tr("Really make portable?"), QMessageBox* confirm = new QMessageBox(QMessageBox::Question, tr("Really make portable?"),
tr("This will make the emulator load its configuration from the same directory as the executable. Do you want to continue?"), tr("This will make the emulator load its configuration from the same directory as the executable. Do you want to continue?"),
@ -1810,17 +1820,6 @@ void Window::setController(CoreController* controller, const QString& fname) {
reloadDisplayDriver(); reloadDisplayDriver();
} }
if (m_config->getOption("hwaccelVideo").toInt() && m_display->supportsShaders() && controller->supportsFeature(CoreController::Feature::OPENGL)) {
std::shared_ptr<VideoProxy> proxy = std::make_shared<VideoProxy>();
m_display->setVideoProxy(proxy);
proxy->attach(controller);
int fb = m_display->framebufferHandle();
if (fb >= 0) {
controller->setFramebufferHandle(fb);
}
}
m_controller = std::shared_ptr<CoreController>(controller); m_controller = std::shared_ptr<CoreController>(controller);
m_inputController.recalibrateAxes(); m_inputController.recalibrateAxes();
m_controller->setInputController(&m_inputController); m_controller->setInputController(&m_inputController);
@ -1860,14 +1859,7 @@ void Window::setController(CoreController* controller, const QString& fname) {
emit paused(false); emit paused(false);
}); });
connect(m_controller.get(), &CoreController::stateLoaded, m_display.get(), &Display::resizeContext); attachDisplay();
connect(m_controller.get(), &CoreController::stateLoaded, m_display.get(), &Display::forceDraw);
connect(m_controller.get(), &CoreController::rewound, m_display.get(), &Display::forceDraw);
connect(m_controller.get(), &CoreController::paused, m_display.get(), &Display::pauseDrawing);
connect(m_controller.get(), &CoreController::unpaused, m_display.get(), &Display::unpauseDrawing);
connect(m_controller.get(), &CoreController::frameAvailable, m_display.get(), &Display::framePosted);
connect(m_controller.get(), &CoreController::statusPosted, m_display.get(), &Display::showMessage);
connect(m_controller.get(), &CoreController::didReset, m_display.get(), &Display::resizeContext);
connect(m_controller.get(), &CoreController::unpaused, &m_inputController, &InputController::suspendScreensaver); connect(m_controller.get(), &CoreController::unpaused, &m_inputController, &InputController::suspendScreensaver);
connect(m_controller.get(), &CoreController::frameAvailable, this, &Window::recordFrame); connect(m_controller.get(), &CoreController::frameAvailable, this, &Window::recordFrame);
@ -1924,6 +1916,18 @@ void Window::setController(CoreController* controller, const QString& fname) {
} }
} }
void Window::attachDisplay() {
connect(m_controller.get(), &CoreController::stateLoaded, m_display.get(), &Display::resizeContext);
connect(m_controller.get(), &CoreController::stateLoaded, m_display.get(), &Display::forceDraw);
connect(m_controller.get(), &CoreController::rewound, m_display.get(), &Display::forceDraw);
connect(m_controller.get(), &CoreController::paused, m_display.get(), &Display::pauseDrawing);
connect(m_controller.get(), &CoreController::unpaused, m_display.get(), &Display::unpauseDrawing);
connect(m_controller.get(), &CoreController::frameAvailable, m_display.get(), &Display::framePosted);
connect(m_controller.get(), &CoreController::statusPosted, m_display.get(), &Display::showMessage);
connect(m_controller.get(), &CoreController::didReset, m_display.get(), &Display::resizeContext);
changeRenderer();
}
WindowBackground::WindowBackground(QWidget* parent) WindowBackground::WindowBackground(QWidget* parent)
: QWidget(parent) : QWidget(parent)
{ {

View File

@ -130,6 +130,7 @@ private slots:
void reloadAudioDriver(); void reloadAudioDriver();
void reloadDisplayDriver(); void reloadDisplayDriver();
void changeRenderer();
void tryMakePortable(); void tryMakePortable();
void mustRestart(); void mustRestart();
@ -155,6 +156,7 @@ private:
void updateMRU(); void updateMRU();
void openView(QWidget* widget); void openView(QWidget* widget);
void attachDisplay();
template <typename T, typename... A> std::function<void()> openTView(A... arg); template <typename T, typename... A> std::function<void()> openTView(A... arg);
template <typename T, typename... A> std::function<void()> openControllerTView(A... arg); template <typename T, typename... A> std::function<void()> openControllerTView(A... arg);