GBA Video: Changing OpenGL scaling no longer requires restart
@@ -121,6 +121,7 @@ - GB Memory: Support manual SRAM editing (fixes mgba.io/i/1580)
- GBA: Trim non-movie ROMs to 32 MiB if applicable - GBA Audio: Redo channel 4 batching for GBA only - GBA I/O: Stop logging several harmless invalid register reads + - GBA Video: Changing OpenGL scaling no longer requires restart - Debugger: Separate aliases from main commands - Debugger: Print break-/watchpoint ID when breaking in CLI - Debugger: Minor interface cleanup
@@ -196,6 +196,7 @@ int scale;
}; void GBAVideoGLRendererCreate(struct GBAVideoGLRenderer* renderer); +void GBAVideoGLRendererSetScale(struct GBAVideoGLRenderer* renderer, int scale); #endif
@@ -347,6 +347,20 @@ gba->allowOpposingDirections = fakeBool;
} return; } +#if defined(BUILD_GLES2) || defined(BUILD_GLES3) + struct GBACore* gbacore = (struct GBACore*) core; + if (strcmp("videoScale", option) == 0) { + if (config != &core->config) { + mCoreConfigCopyValue(&core->config, config, "videoScale"); + } + if (gbacore->glRenderer.outputTex != (unsigned) -1 && mCoreConfigGetIntValue(&core->config, "hwaccelVideo", &fakeBool) && fakeBool) { + int scale; + mCoreConfigGetIntValue(config, "videoScale", &scale); + GBAVideoGLRendererSetScale(&gbacore->glRenderer, scale); + } + return; + } +#endif } static void _GBACoreDesiredVideoDimensions(struct mCore* core, unsigned* width, unsigned* height) {
@@ -755,19 +755,7 @@ static void _initFramebufferTexture(GLuint tex, GLenum format, GLenum attachment, int scale) {
_initFramebufferTextureEx(tex, format, format, GL_UNSIGNED_BYTE, attachment, scale); } -void GBAVideoGLRendererInit(struct GBAVideoRenderer* renderer) { - struct GBAVideoGLRenderer* glRenderer = (struct GBAVideoGLRenderer*) renderer; - glRenderer->temporaryBuffer = NULL; - - glGenFramebuffers(GBA_GL_FBO_MAX, glRenderer->fbo); - glGenTextures(GBA_GL_TEX_MAX, glRenderer->layers); - - glGenTextures(1, &glRenderer->vramTex); - glBindTexture(GL_TEXTURE_2D, glRenderer->vramTex); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA4, 256, 192, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, 0); - +static void _initFramebuffers(struct GBAVideoGLRenderer* glRenderer) { glBindFramebuffer(GL_FRAMEBUFFER, glRenderer->fbo[GBA_GL_FBO_OBJ]); _initFramebufferTexture(glRenderer->layers[GBA_GL_TEX_OBJ_COLOR], GL_RGBA, GL_COLOR_ATTACHMENT0, glRenderer->scale); _initFramebufferTextureEx(glRenderer->layers[GBA_GL_TEX_OBJ_FLAGS], GL_RGBA8I, GL_RGBA_INTEGER, GL_BYTE, GL_COLOR_ATTACHMENT1, glRenderer->scale);@@ -784,7 +772,28 @@
glBindFramebuffer(GL_FRAMEBUFFER, glRenderer->fbo[GBA_GL_FBO_OUTPUT]); _initFramebufferTexture(glRenderer->outputTex, GL_RGB, GL_COLOR_ATTACHMENT0, glRenderer->scale); + int i; + for (i = 0; i < 4; ++i) { + struct GBAVideoGLBackground* bg = &glRenderer->bg[i]; + glBindFramebuffer(GL_FRAMEBUFFER, bg->fbo); + _initFramebufferTexture(bg->tex, GL_RGBA, GL_COLOR_ATTACHMENT0, glRenderer->scale); + _initFramebufferTextureEx(bg->flags, GL_RGBA8I, GL_RGBA_INTEGER, GL_BYTE, GL_COLOR_ATTACHMENT1, glRenderer->scale); + } glBindFramebuffer(GL_FRAMEBUFFER, 0); +} + +void GBAVideoGLRendererInit(struct GBAVideoRenderer* renderer) { + struct GBAVideoGLRenderer* glRenderer = (struct GBAVideoGLRenderer*) renderer; + glRenderer->temporaryBuffer = NULL; + + glGenFramebuffers(GBA_GL_FBO_MAX, glRenderer->fbo); + glGenTextures(GBA_GL_TEX_MAX, glRenderer->layers); + + glGenTextures(1, &glRenderer->vramTex); + glBindTexture(GL_TEXTURE_2D, glRenderer->vramTex); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA4, 256, 192, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, 0); glGenBuffers(1, &glRenderer->vbo); glBindBuffer(GL_ARRAY_BUFFER, glRenderer->vbo);@@ -817,11 +826,9 @@ bg->affine.sy = 0;
glGenFramebuffers(1, &bg->fbo); glGenTextures(1, &bg->tex); glGenTextures(1, &bg->flags); - glBindFramebuffer(GL_FRAMEBUFFER, bg->fbo); - _initFramebufferTexture(bg->tex, GL_RGBA, GL_COLOR_ATTACHMENT0, glRenderer->scale); - _initFramebufferTextureEx(bg->flags, GL_RGBA8I, GL_RGBA_INTEGER, GL_BYTE, GL_COLOR_ATTACHMENT1, glRenderer->scale); } - glBindFramebuffer(GL_FRAMEBUFFER, 0); + + _initFramebuffers(glRenderer); char log[2048]; const GLchar* shaderBuffer[4];@@ -1849,6 +1856,19 @@ glUniform4iv(uniforms[GBA_GL_WIN_WIN0], GBA_VIDEO_VERTICAL_PIXELS, renderer->winNHistory[0]);
glUniform4iv(uniforms[GBA_GL_WIN_WIN1], GBA_VIDEO_VERTICAL_PIXELS, renderer->winNHistory[1]); glDrawBuffers(1, (GLenum[]) { GL_COLOR_ATTACHMENT0 }); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); +} + +void GBAVideoGLRendererSetScale(struct GBAVideoGLRenderer* renderer, int scale) { + if (scale == renderer->scale) { + return; + } + if (renderer->temporaryBuffer) { + mappedMemoryFree(renderer->temporaryBuffer, GBA_VIDEO_HORIZONTAL_PIXELS * GBA_VIDEO_VERTICAL_PIXELS * renderer->scale * renderer->scale * BYTES_PER_PIXEL); + renderer->temporaryBuffer = NULL; + } + renderer->scale = scale; + _initFramebuffers(renderer); + renderer->paletteDirty = true; } #endif
@@ -51,6 +51,7 @@ virtual bool isDrawing() const = 0;
virtual bool supportsShaders() const = 0; virtual VideoShader* shaders() = 0; virtual int framebufferHandle() { return -1; } + virtual void setVideoScale(int scale) {} virtual void setVideoProxy(std::shared_ptr<VideoProxy> proxy) { m_videoProxy = proxy; } std::shared_ptr<VideoProxy> videoProxy() { return m_videoProxy; }
@@ -218,11 +218,19 @@ void DisplayGL::clearShaders() {
QMetaObject::invokeMethod(m_painter, "clearShaders"); } - void DisplayGL::resizeContext() { if (m_drawThread) { m_isDrawing = false; CoreController::Interrupter interrupter(m_context); + QMetaObject::invokeMethod(m_painter, "resizeContext", Qt::BlockingQueuedConnection); + } +} + +void DisplayGL::setVideoScale(int scale) { + if (m_drawThread) { + m_isDrawing = false; + CoreController::Interrupter interrupter(m_context); + mCoreConfigSetIntValue(&m_context->thread()->core->config, "videoScale", scale); QMetaObject::invokeMethod(m_painter, "resizeContext", Qt::BlockingQueuedConnection); } }@@ -347,6 +355,9 @@ void PainterGL::resizeContext() {
if (!m_context) { return; } + + mCore* core = m_context->thread()->core; + core->reloadConfigOption(core, "videoScale", NULL); QSize size = m_context->screenDimensions(); m_backend->setDimensions(m_backend, size.width(), size.height());
@@ -62,6 +62,7 @@ void framePosted() override;
void setShaders(struct VDir*) override; void clearShaders() override; void resizeContext() override; + void setVideoScale(int scale) override; protected: virtual void paintEvent(QPaintEvent*) override { forceDraw(); }
@@ -494,7 +494,7 @@ }
int videoScale = m_controller->getOption("videoScale", 1).toInt(); int hwaccelVideo = m_controller->getOption("hwaccelVideo").toInt(); - if (videoScale != m_ui.videoScale->value() || hwaccelVideo != m_ui.hwaccelVideo->currentIndex()) { + if (hwaccelVideo != m_ui.hwaccelVideo->currentIndex()) { emit videoRendererChanged(); } saveSetting("videoScale", m_ui.videoScale);
@@ -1617,6 +1617,13 @@ m_display->showOSDMessages(value.toBool());
} }, this); + ConfigOption* videoScale = m_config->addOption("videoScale"); + videoScale->connect([this](const QVariant& value) { + if (m_display) { + m_display->setVideoScale(value.toInt()); + } + }, this); + m_actions.addHiddenAction(tr("Exit fullscreen"), "exitFullScreen", this, &Window::exitFullScreen, "frame", QKeySequence("Esc")); m_actions.addHeldAction(tr("GameShark Button (held)"), "holdGSButton", [this](bool held) {