GBA Video: Changing OpenGL scaling no longer requires restart

This commit is contained in:
Vicki Pfau 2020-01-19 19:15:36 -08:00
parent 9a0da39848
commit f44846cb9a
9 changed files with 75 additions and 19 deletions

View File

@ -121,6 +121,7 @@ Misc:
- 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

View File

@ -196,6 +196,7 @@ struct GBAVideoGLRenderer {
};
void GBAVideoGLRendererCreate(struct GBAVideoGLRenderer* renderer);
void GBAVideoGLRendererSetScale(struct GBAVideoGLRenderer* renderer, int scale);
#endif

View File

@ -347,6 +347,20 @@ 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 (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) {

View File

@ -755,19 +755,7 @@ static void _initFramebufferTexture(GLuint tex, GLenum format, GLenum attachment
_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 @@ void GBAVideoGLRendererInit(struct GBAVideoRenderer* renderer) {
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 @@ void GBAVideoGLRendererInit(struct GBAVideoRenderer* renderer) {
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];
@ -1851,4 +1858,17 @@ void GBAVideoGLRendererDrawWindow(struct GBAVideoGLRenderer* renderer, int y) {
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

View File

@ -51,6 +51,7 @@ public:
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; }

View File

@ -218,7 +218,6 @@ void DisplayGL::clearShaders() {
QMetaObject::invokeMethod(m_painter, "clearShaders");
}
void DisplayGL::resizeContext() {
if (m_drawThread) {
m_isDrawing = false;
@ -227,6 +226,15 @@ void DisplayGL::resizeContext() {
}
}
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);
}
}
void DisplayGL::resizeEvent(QResizeEvent* event) {
Display::resizeEvent(event);
resizePainter();
@ -348,6 +356,9 @@ void PainterGL::resizeContext() {
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());
}

View File

@ -62,6 +62,7 @@ public slots:
void setShaders(struct VDir*) override;
void clearShaders() override;
void resizeContext() override;
void setVideoScale(int scale) override;
protected:
virtual void paintEvent(QPaintEvent*) override { forceDraw(); }

View File

@ -494,7 +494,7 @@ void SettingsView::updateConfig() {
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);

View File

@ -1617,6 +1617,13 @@ void Window::setupMenu(QMenuBar* menubar) {
}
}, 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) {