From 0f450f3e396c1a9f4e710211532ccfba4b1ac21c Mon Sep 17 00:00:00 2001 From: Ethan Lee Date: Thu, 2 Jul 2020 00:19:40 -0400 Subject: [PATCH] Move the VSync work to Screen. The problem we're running into is entirely contained in the Screen - we need to either decouple graphics context init from Screen::init or we need to take out the screenbuffer interaction from loadstats (which I'm more in favor of since we can just pull the config values and pass them to Screen::init later). --- desktop_version/src/Game.cpp | 4 +-- desktop_version/src/Graphics.cpp | 41 ---------------------------- desktop_version/src/Graphics.h | 3 -- desktop_version/src/Input.cpp | 4 +-- desktop_version/src/Render.cpp | 2 +- desktop_version/src/Screen.cpp | 47 ++++++++++++++++++++++++++++++++ desktop_version/src/Screen.h | 2 ++ desktop_version/src/main.cpp | 2 +- 8 files changed, 55 insertions(+), 50 deletions(-) diff --git a/desktop_version/src/Game.cpp b/desktop_version/src/Game.cpp index c2074420..2f4097d7 100644 --- a/desktop_version/src/Game.cpp +++ b/desktop_version/src/Game.cpp @@ -4848,7 +4848,7 @@ void Game::loadstats() if (pKey == "vsync") { - graphics.vsync = atoi(pText); + graphics.screenbuffer->vsync = atoi(pText); } if (pKey == "notextoutline") @@ -5118,7 +5118,7 @@ void Game::savestats() dataNode->LinkEndChild(msg); msg = doc.NewElement("vsync"); - msg->LinkEndChild(doc.NewText(help.String((int) graphics.vsync).c_str())); + msg->LinkEndChild(doc.NewText(help.String((int) graphics.screenbuffer->vsync).c_str())); dataNode->LinkEndChild(msg); for (size_t i = 0; i < controllerButton_flip.size(); i += 1) diff --git a/desktop_version/src/Graphics.cpp b/desktop_version/src/Graphics.cpp index 95da6806..c81d437c 100644 --- a/desktop_version/src/Graphics.cpp +++ b/desktop_version/src/Graphics.cpp @@ -139,8 +139,6 @@ void Graphics::init() col_tb = 0; kludgeswnlinewidth = false; - - vsync = false; } int Graphics::font_idx(uint32_t ch) { @@ -3273,42 +3271,3 @@ Uint32 Graphics::crewcolourreal(int t) } return col_crewcyan; } - -void Graphics::processVsync() -{ - SDL_SetHintWithPriority(SDL_HINT_RENDER_VSYNC, vsync ? "1" : "0", SDL_HINT_OVERRIDE); - - if (screenbuffer == NULL) - { - return; - } - - // FIXME: Sigh... work around SDL2 bug where the VSync hint is only - // listened to at renderer creation - - // Ugh, have to re-create m_screenTexture as well, otherwise the screen - // will be black... - if (screenbuffer->m_screenTexture != NULL) - { - SDL_DestroyTexture(screenbuffer->m_screenTexture); - } - - if (screenbuffer->m_renderer != NULL) - { - SDL_DestroyRenderer(screenbuffer->m_renderer); - } - screenbuffer->m_renderer = SDL_CreateRenderer(screenbuffer->m_window, -1, 0); - - // FIXME: This is duplicated from Screen::init()! - screenbuffer->m_screenTexture = SDL_CreateTexture( - screenbuffer->m_renderer, - SDL_PIXELFORMAT_ARGB8888, - SDL_TEXTUREACCESS_STREAMING, - 320, - 240 - ); - - // Ugh, have to make sure to re-apply graphics options after doing the - // above, otherwise letterbox/integer won't be applied... - screenbuffer->ResizeScreen(-1, -1); -} diff --git a/desktop_version/src/Graphics.h b/desktop_version/src/Graphics.h index bf42d562..477523f3 100644 --- a/desktop_version/src/Graphics.h +++ b/desktop_version/src/Graphics.h @@ -326,9 +326,6 @@ public: bool kludgeswnlinewidth; Uint32 crewcolourreal(int t); - - bool vsync; - void processVsync(); }; extern Graphics graphics; diff --git a/desktop_version/src/Input.cpp b/desktop_version/src/Input.cpp index e352e6e0..4183247d 100644 --- a/desktop_version/src/Input.cpp +++ b/desktop_version/src/Input.cpp @@ -369,8 +369,8 @@ void menuactionpress() case 6: //toggle vsync music.playef(11); - graphics.vsync = !graphics.vsync; - graphics.processVsync(); + graphics.screenbuffer->vsync = !graphics.screenbuffer->vsync; + graphics.screenbuffer->resetRendererWorkaround(); game.savestats(); break; default: diff --git a/desktop_version/src/Render.cpp b/desktop_version/src/Render.cpp index 90ed9200..4adfcb2a 100644 --- a/desktop_version/src/Render.cpp +++ b/desktop_version/src/Render.cpp @@ -231,7 +231,7 @@ void menurender() graphics.bigprint(-1, 30, "Toggle VSync", tr, tg, tb, true); graphics.Print(-1, 65, "Turn VSync on or off.", tr, tg, tb, true); - if (!graphics.vsync) + if (!graphics.screenbuffer->vsync) { graphics.Print(-1, 95, "Current mode: VSYNC OFF", tr/2, tg/2, tb/2, true); } diff --git a/desktop_version/src/Screen.cpp b/desktop_version/src/Screen.cpp index e8292511..b1c7de8c 100644 --- a/desktop_version/src/Screen.cpp +++ b/desktop_version/src/Screen.cpp @@ -26,6 +26,7 @@ void Screen::init() isWindowed = true; stretchMode = 0; isFiltered = false; + vsync = false; filterSubrect.x = 1; filterSubrect.y = 1; filterSubrect.w = 318; @@ -287,3 +288,49 @@ void Screen::toggleLinearFilter() 240 ); } + +void Screen::resetRendererWorkaround() +{ + SDL_SetHintWithPriority( + SDL_HINT_RENDER_VSYNC, + vsync ? "1" : "0", + SDL_HINT_OVERRIDE + ); + + /* FIXME: This exists because SDL_HINT_RENDER_VSYNC is not dynamic! + * As a result, our only workaround is to tear down the renderer + * and recreate everything so that it can process the variable. + * -flibit + */ + + if (m_renderer == NULL) + { + /* We haven't made it to init yet, don't worry about it */ + return; + } + + SDL_RendererInfo renderInfo; + SDL_GetRendererInfo(m_renderer, &renderInfo); + bool curVsync = (renderInfo.flags & SDL_RENDERER_PRESENTVSYNC) != 0; + if (vsync == curVsync) + { + return; + } + + SDL_DestroyTexture(m_screenTexture); + SDL_DestroyRenderer(m_renderer); + + m_renderer = SDL_CreateRenderer(m_window, -1, 0); + m_screenTexture = SDL_CreateTexture( + m_renderer, + SDL_PIXELFORMAT_ARGB8888, + SDL_TEXTUREACCESS_STREAMING, + 320, + 240 + ); + + /* Ugh, have to make sure to re-apply graphics options after doing the + * above, otherwise letterbox/integer won't be applied... + */ + ResizeScreen(-1, -1); +} diff --git a/desktop_version/src/Screen.h b/desktop_version/src/Screen.h index ea77a6c4..e29237fd 100644 --- a/desktop_version/src/Screen.h +++ b/desktop_version/src/Screen.h @@ -20,11 +20,13 @@ public: void toggleFullScreen(); void toggleStretchMode(); void toggleLinearFilter(); + void resetRendererWorkaround(); bool isWindowed; bool isFiltered; bool badSignalEffect; int stretchMode; + bool vsync; SDL_Window *m_window; SDL_Renderer *m_renderer; diff --git a/desktop_version/src/main.cpp b/desktop_version/src/main.cpp index 291c6b90..55ea9955 100644 --- a/desktop_version/src/main.cpp +++ b/desktop_version/src/main.cpp @@ -252,7 +252,7 @@ int main(int argc, char *argv[]) // renderer created by Screen::init(), which is a bit wasteful! // This is annoying to fix because we'd have to call gameScreen.init() after // game.loadstats(), but game.loadstats() assumes gameScreen.init() is already called! - graphics.processVsync(); + gameScreen.resetRendererWorkaround(); if (game.skipfakeload) game.gamestate = TITLEMODE;