mirror of https://github.com/mgba-emu/mgba.git
Qt: Make renderer able to be changed while running
This commit is contained in:
parent
74af414b96
commit
b922cecc61
2
CHANGES
2
CHANGES
|
@ -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:
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue