all repos — mgba @ f44846cb9a0818af13830a34c0deee830b4451d4

mGBA Game Boy Advance Emulator

GBA Video: Changing OpenGL scaling no longer requires restart
Vicki Pfau vi@endrift.com
Sun, 19 Jan 2020 19:15:36 -0800
commit

f44846cb9a0818af13830a34c0deee830b4451d4

parent

9a0da39848a540ef3909f0051160843f093dfd83

M CHANGESCHANGES

@@ -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
M include/mgba/internal/gba/renderers/gl.hinclude/mgba/internal/gba/renderers/gl.h

@@ -196,6 +196,7 @@ int scale;

}; void GBAVideoGLRendererCreate(struct GBAVideoGLRenderer* renderer); +void GBAVideoGLRendererSetScale(struct GBAVideoGLRenderer* renderer, int scale); #endif
M src/gba/core.csrc/gba/core.c

@@ -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) {
M src/gba/renderers/gl.csrc/gba/renderers/gl.c

@@ -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
M src/platform/qt/Display.hsrc/platform/qt/Display.h

@@ -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; }
M src/platform/qt/DisplayGL.cppsrc/platform/qt/DisplayGL.cpp

@@ -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());
M src/platform/qt/DisplayGL.hsrc/platform/qt/DisplayGL.h

@@ -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(); }
M src/platform/qt/SettingsView.cppsrc/platform/qt/SettingsView.cpp

@@ -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);
M src/platform/qt/Window.cppsrc/platform/qt/Window.cpp

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