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 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:

View File

@ -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

View File

@ -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);

View File

@ -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<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");
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<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) {
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() {

View File

@ -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());

View File

@ -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<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() {
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<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_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)
{

View File

@ -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 <typename T, typename... A> std::function<void()> openTView(A... arg);
template <typename T, typename... A> std::function<void()> openControllerTView(A... arg);