From b922cecc61b6b1f1d191a9cc1bba0f1dac10520b Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 30 Jan 2020 21:26:58 -0800 Subject: [PATCH] Qt: Make renderer able to be changed while running --- CHANGES | 2 + src/gba/core.c | 32 +++++++++++++- src/gba/extra/proxy.c | 2 +- src/platform/qt/CoreController.cpp | 28 +++++++----- src/platform/qt/SettingsView.cpp | 5 ++- src/platform/qt/Window.cpp | 68 ++++++++++++++++-------------- src/platform/qt/Window.h | 2 + 7 files changed, 92 insertions(+), 47 deletions(-) diff --git a/CHANGES b/CHANGES index 6181f1273..90442963d 100644 --- a/CHANGES +++ b/CHANGES @@ -22,6 +22,8 @@ Other fixes: - Qt: Fix crash unloading shaders - Qt: Fix toggled actions on gamepads (fixes mgba.io/i/1650) - 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) Features: diff --git a/src/gba/core.c b/src/gba/core.c index 3c1ba6dd2..4ecf003b8 100644 --- a/src/gba/core.c +++ b/src/gba/core.c @@ -347,8 +347,9 @@ static void _GBACoreReloadConfigOption(struct mCore* core, const char* option, c } return; } -#if defined(BUILD_GLES2) || defined(BUILD_GLES3) + struct GBACore* gbacore = (struct GBACore*) core; +#if defined(BUILD_GLES2) || defined(BUILD_GLES3) if (strcmp("videoScale", option) == 0) { if (config != &core->config) { mCoreConfigCopyValue(&core->config, config, "videoScale"); @@ -361,6 +362,31 @@ static void _GBACoreReloadConfigOption(struct mCore* core, const char* option, c return; } #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) { @@ -529,8 +555,10 @@ static void _GBACoreReset(struct mCore* core) { int fakeBool; #if defined(BUILD_GLES2) || defined(BUILD_GLES3) if (gbacore->glRenderer.outputTex != (unsigned) -1 && mCoreConfigGetIntValue(&core->config, "hwaccelVideo", &fakeBool) && fakeBool) { - renderer = &gbacore->glRenderer.d; mCoreConfigGetIntValue(&core->config, "videoScale", &gbacore->glRenderer.scale); + renderer = &gbacore->glRenderer.d; + } else { + gbacore->glRenderer.scale = 1; } #endif #ifndef DISABLE_THREADING diff --git a/src/gba/extra/proxy.c b/src/gba/extra/proxy.c index 196329036..54f2e96ab 100644 --- a/src/gba/extra/proxy.c +++ b/src/gba/extra/proxy.c @@ -143,8 +143,8 @@ void GBAVideoProxyRendererDeinit(struct GBAVideoRenderer* renderer) { if (!proxyRenderer->logger->block) { proxyRenderer->backend->deinit(proxyRenderer->backend); } else { - proxyRenderer->logger->postEvent(proxyRenderer->logger, LOGGER_EVENT_DEINIT); mVideoLoggerRendererFlush(proxyRenderer->logger); + proxyRenderer->logger->postEvent(proxyRenderer->logger, LOGGER_EVENT_DEINIT); } mVideoLoggerRendererDeinit(proxyRenderer->logger); diff --git a/src/platform/qt/CoreController.cpp b/src/platform/qt/CoreController.cpp index 3f1886de5..dc8e4f93f 100644 --- a/src/platform/qt/CoreController.cpp +++ b/src/platform/qt/CoreController.cpp @@ -81,9 +81,7 @@ CoreController::CoreController(mCore* core, QObject* parent) controller->m_resetActions.clear(); - if (!controller->m_hwaccel) { - context->core->setVideoBuffer(context->core, reinterpret_cast(controller->m_activeBuffer.data()), controller->screenDimensions().width()); - } + context->core->setVideoBuffer(context->core, reinterpret_cast(controller->m_activeBuffer.data()), controller->screenDimensions().width()); QMetaObject::invokeMethod(controller, "didReset"); controller->finishFrame(); @@ -358,14 +356,12 @@ void CoreController::setLogger(LogController* logger) { } void CoreController::start() { - if (!m_hwaccel) { - QSize size(256, 224); - m_activeBuffer.resize(size.width() * size.height() * sizeof(color_t)); - m_activeBuffer.fill(0xFF); - m_completeBuffer = m_activeBuffer; + QSize size(256, 224); + m_activeBuffer.resize(size.width() * size.height() * sizeof(color_t)); + m_activeBuffer.fill(0xFF); + m_completeBuffer = m_activeBuffer; - m_threadContext.core->setVideoBuffer(m_threadContext.core, reinterpret_cast(m_activeBuffer.data()), size.width()); - } + m_threadContext.core->setVideoBuffer(m_threadContext.core, reinterpret_cast(m_activeBuffer.data()), size.width()); if (!m_patched) { mCoreAutoloadPatch(m_threadContext.core); @@ -860,11 +856,23 @@ void CoreController::endVideoLog(bool closeVf) { void CoreController::setFramebufferHandle(int fb) { Interrupter interrupter(this); 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; } else { + mCoreConfigSetIntValue(&m_threadContext.core->config, "hwaccelVideo", 1); m_threadContext.core->setVideoGLTex(m_threadContext.core, fb); + if (m_hwaccel) { + return; + } m_hwaccel = true; } + if (hasStarted()) { + m_threadContext.core->reloadConfigOption(m_threadContext.core, "hwaccelVideo", NULL); + } } void CoreController::updateKeys() { diff --git a/src/platform/qt/SettingsView.cpp b/src/platform/qt/SettingsView.cpp index cd751c797..510528a12 100644 --- a/src/platform/qt/SettingsView.cpp +++ b/src/platform/qt/SettingsView.cpp @@ -493,12 +493,13 @@ void SettingsView::updateConfig() { } int videoScale = m_controller->getOption("videoScale", 1).toInt(); + saveSetting("videoScale", m_ui.videoScale); + int hwaccelVideo = m_controller->getOption("hwaccelVideo").toInt(); + saveSetting("hwaccelVideo", m_ui.hwaccelVideo->currentIndex()); if (hwaccelVideo != m_ui.hwaccelVideo->currentIndex()) { emit videoRendererChanged(); } - saveSetting("videoScale", m_ui.videoScale); - saveSetting("hwaccelVideo", m_ui.hwaccelVideo->currentIndex()); m_logModel.save(m_controller); m_logModel.logger()->setLogFile(m_ui.logFile->text()); diff --git a/src/platform/qt/Window.cpp b/src/platform/qt/Window.cpp index 677ebad24..719da1f33 100644 --- a/src/platform/qt/Window.cpp +++ b/src/platform/qt/Window.cpp @@ -461,7 +461,7 @@ void Window::openSettingsWindow() { connect(settingsWindow, &SettingsView::audioDriverChanged, this, &Window::reloadAudioDriver); connect(settingsWindow, &SettingsView::cameraDriverChanged, this, &Window::mustRestart); 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::pathsChanged, this, &Window::reloadConfig); #ifdef USE_SQLITE3 @@ -883,10 +883,6 @@ void Window::unimplementedBiosCall(int call) { void Window::reloadDisplayDriver() { if (m_controller) { - if (m_controller->hardwareAccelerated()) { - mustRestart(); - return; - } m_display->stopDrawing(); detachWidget(m_display.get()); } @@ -924,14 +920,7 @@ void Window::reloadDisplayDriver() { #endif if (m_controller) { - 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); + attachDisplay(); attachWidget(m_display.get()); m_display->startDrawing(m_controller); @@ -962,6 +951,27 @@ void Window::reloadAudioDriver() { 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 proxy = m_display->videoProxy(); + if (!proxy) { + proxy = std::make_shared(); + } + 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() { 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?"), @@ -1810,17 +1820,6 @@ void Window::setController(CoreController* controller, const QString& fname) { reloadDisplayDriver(); } - if (m_config->getOption("hwaccelVideo").toInt() && m_display->supportsShaders() && controller->supportsFeature(CoreController::Feature::OPENGL)) { - std::shared_ptr proxy = std::make_shared(); - m_display->setVideoProxy(proxy); - proxy->attach(controller); - - int fb = m_display->framebufferHandle(); - if (fb >= 0) { - controller->setFramebufferHandle(fb); - } - } - m_controller = std::shared_ptr(controller); m_inputController.recalibrateAxes(); m_controller->setInputController(&m_inputController); @@ -1860,14 +1859,7 @@ void Window::setController(CoreController* controller, const QString& fname) { emit paused(false); }); - 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); + attachDisplay(); connect(m_controller.get(), &CoreController::unpaused, &m_inputController, &InputController::suspendScreensaver); 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) : QWidget(parent) { diff --git a/src/platform/qt/Window.h b/src/platform/qt/Window.h index b38873c9e..7716bf077 100644 --- a/src/platform/qt/Window.h +++ b/src/platform/qt/Window.h @@ -130,6 +130,7 @@ private slots: void reloadAudioDriver(); void reloadDisplayDriver(); + void changeRenderer(); void tryMakePortable(); void mustRestart(); @@ -155,6 +156,7 @@ private: void updateMRU(); void openView(QWidget* widget); + void attachDisplay(); template std::function openTView(A... arg); template std::function openControllerTView(A... arg);