diff --git a/data/language/en-GB.txt b/data/language/en-GB.txt index 535ebc28ac..986d837057 100644 --- a/data/language/en-GB.txt +++ b/data/language/en-GB.txt @@ -4471,6 +4471,8 @@ STR_6161 :Gridlines display toggle STR_6162 :Spinning Wild Mouse STR_6163 :Mouse shaped cars speed through tight corners and short drops, gently spinning around to disorientate the riders STR_6164 :{WHITE}{CROSS} +STR_6165 :Use vertical sync +STR_6166 :{SMALLFONT}{BLACK}Synchronises each frame displayed to the monitor's refresh rate, preventing screen tearing. ############# # Scenarios # diff --git a/src/openrct2-ui/drawing/engines/HardwareDisplayDrawingEngine.cpp b/src/openrct2-ui/drawing/engines/HardwareDisplayDrawingEngine.cpp index 69a393f0fe..1182a2d303 100644 --- a/src/openrct2-ui/drawing/engines/HardwareDisplayDrawingEngine.cpp +++ b/src/openrct2-ui/drawing/engines/HardwareDisplayDrawingEngine.cpp @@ -53,6 +53,7 @@ private: uint32 _pixelAfterOverlay = 0; bool _overlayActive = false; bool _pausedBeforeOverlay = false; + bool _useVsync = true; std::vector _dirtyVisualsTime; @@ -76,7 +77,18 @@ public: void Initialise() override { - _sdlRenderer = SDL_CreateRenderer(_window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); + _sdlRenderer = SDL_CreateRenderer(_window, -1, SDL_RENDERER_ACCELERATED | (_useVsync ? SDL_RENDERER_PRESENTVSYNC : 0)); + } + + void SetVSync(bool vsync) override + { + if (_useVsync != vsync) + { + _useVsync = vsync; + SDL_DestroyRenderer(_sdlRenderer); + Initialise(); + Resize(_uiContext->GetWidth(), _uiContext->GetHeight()); + } } void Resize(uint32 width, uint32 height) override diff --git a/src/openrct2-ui/drawing/engines/opengl/OpenGLDrawingEngine.cpp b/src/openrct2-ui/drawing/engines/opengl/OpenGLDrawingEngine.cpp index 4c48482c27..524c6d3c07 100644 --- a/src/openrct2-ui/drawing/engines/opengl/OpenGLDrawingEngine.cpp +++ b/src/openrct2-ui/drawing/engines/opengl/OpenGLDrawingEngine.cpp @@ -225,9 +225,9 @@ public: _drawingContext->ResetPalette(); } - void SetUncappedFrameRate(bool uncapped) override + void SetVSync(bool vsync) override { - SDL_GL_SetSwapInterval(uncapped ? 0 : 1); + SDL_GL_SetSwapInterval(vsync); } void Invalidate(sint32 left, sint32 top, sint32 right, sint32 bottom) override diff --git a/src/openrct2-ui/windows/Options.cpp b/src/openrct2-ui/windows/Options.cpp index 5363ab7d0f..67ce038afe 100644 --- a/src/openrct2-ui/windows/Options.cpp +++ b/src/openrct2-ui/windows/Options.cpp @@ -92,6 +92,7 @@ enum WINDOW_OPTIONS_WIDGET_IDX { WIDX_STEAM_OVERLAY_PAUSE, WIDX_UNCAP_FPS_CHECKBOX, WIDX_SHOW_FPS_CHECKBOX, + WIDX_USE_VSYNC_CHECKBOX, WIDX_MINIMIZE_FOCUS_LOSS, // Rendering @@ -206,7 +207,7 @@ enum WINDOW_OPTIONS_WIDGET_IDX { static rct_widget window_options_display_widgets[] = { MAIN_OPTIONS_WIDGETS, - { WWT_GROUPBOX, 1, 5, 304, 53, 192, STR_HARDWARE_GROUP, STR_NONE }, // Hardware group + { WWT_GROUPBOX, 1, 5, 304, 53, 207, STR_HARDWARE_GROUP, STR_NONE }, // Hardware group { WWT_DROPDOWN, 1, 155, 299, 68, 79, STR_ARG_12_STRINGID, STR_NONE }, // Fullscreen { WWT_DROPDOWN_BUTTON, 1, 288, 298, 69, 78, STR_DROPDOWN_GLYPH, STR_FULLSCREEN_MODE_TIP }, @@ -226,9 +227,10 @@ static rct_widget window_options_display_widgets[] = { { WWT_CHECKBOX, 1, 25, 290, 144, 155, STR_STEAM_OVERLAY_PAUSE, STR_STEAM_OVERLAY_PAUSE_TIP }, // Pause on steam overlay - { WWT_CHECKBOX, 1, 11, 290, 161, 172, STR_UNCAP_FPS, STR_UNCAP_FPS_TIP }, // Uncap fps - { WWT_CHECKBOX, 1, 155, 299, 161, 172, STR_SHOW_FPS, STR_SHOW_FPS_TIP }, // Show fps - { WWT_CHECKBOX, 1, 11, 290, 176, 187, STR_MINIMISE_FULLSCREEN_ON_FOCUS_LOSS, STR_MINIMISE_FULLSCREEN_ON_FOCUS_LOSS_TIP }, // Minimise fullscreen focus loss + { WWT_CHECKBOX, 1, 11, 153, 161, 172, STR_UNCAP_FPS, STR_UNCAP_FPS_TIP }, // Uncap fps + { WWT_CHECKBOX, 1, 155, 290, 161, 172, STR_SHOW_FPS, STR_SHOW_FPS_TIP }, // Show fps + { WWT_CHECKBOX, 1, 11 , 290, 176, 187, STR_USE_VSYNC, STR_USE_VSYNC_TIP }, // Use vsync + { WWT_CHECKBOX, 1, 11, 290, 191, 202, STR_MINIMISE_FULLSCREEN_ON_FOCUS_LOSS, STR_MINIMISE_FULLSCREEN_ON_FOCUS_LOSS_TIP }, // Minimise fullscreen focus loss { WIDGETS_END }, @@ -457,6 +459,7 @@ static uint64 window_options_page_enabled_widgets[] = { (1 << WIDX_DRAWING_ENGINE) | (1 << WIDX_DRAWING_ENGINE_DROPDOWN) | (1 << WIDX_UNCAP_FPS_CHECKBOX) | + (1 << WIDX_USE_VSYNC_CHECKBOX) | (1 << WIDX_SHOW_FPS_CHECKBOX) | (1 << WIDX_MINIMIZE_FOCUS_LOSS) | (1 << WIDX_STEAM_OVERLAY_PAUSE) | @@ -606,7 +609,13 @@ static void window_options_mouseup(rct_window *w, rct_widgetindex widgetIndex) switch (widgetIndex) { case WIDX_UNCAP_FPS_CHECKBOX: gConfigGeneral.uncap_fps ^= 1; - drawing_engine_set_fps_uncapped(gConfigGeneral.uncap_fps); + drawing_engine_set_vsync(gConfigGeneral.use_vsync); + config_save_default(); + window_invalidate(w); + break; + case WIDX_USE_VSYNC_CHECKBOX: + gConfigGeneral.use_vsync ^= 1; + drawing_engine_set_vsync(gConfigGeneral.use_vsync); config_save_default(); window_invalidate(w); break; @@ -1473,7 +1482,18 @@ static void window_options_invalidate(rct_window *w) w->disabled_widgets &= ~(1 << WIDX_SCALE_QUALITY_DROPDOWN); } + // Disable changing VSync for Software engine, as we can't control its use of VSync + if (gConfigGeneral.drawing_engine == DRAWING_ENGINE_SOFTWARE) + { + w->disabled_widgets |= (1 << WIDX_USE_VSYNC_CHECKBOX); + } + else + { + w->disabled_widgets &= ~(1 << WIDX_USE_VSYNC_CHECKBOX); + } + widget_set_checkbox_value(w, WIDX_UNCAP_FPS_CHECKBOX, gConfigGeneral.uncap_fps); + widget_set_checkbox_value(w, WIDX_USE_VSYNC_CHECKBOX, gConfigGeneral.use_vsync); widget_set_checkbox_value(w, WIDX_SHOW_FPS_CHECKBOX, gConfigGeneral.show_fps); widget_set_checkbox_value(w, WIDX_MINIMIZE_FOCUS_LOSS, gConfigGeneral.minimize_fullscreen_focus_loss); widget_set_checkbox_value(w, WIDX_STEAM_OVERLAY_PAUSE, gConfigGeneral.steam_overlay_pause); diff --git a/src/openrct2/config/Config.cpp b/src/openrct2/config/Config.cpp index 17fccd57bf..1a267c3cb3 100644 --- a/src/openrct2/config/Config.cpp +++ b/src/openrct2/config/Config.cpp @@ -168,6 +168,7 @@ namespace Config model->default_display = reader->GetSint32("default_display", 0); model->drawing_engine = reader->GetEnum("drawing_engine", DRAWING_ENGINE_SOFTWARE, Enum_DrawingEngine); model->uncap_fps = reader->GetBoolean("uncap_fps", false); + model->use_vsync = reader->GetBoolean("use_vsync", true); // Default config setting is false until ghost trains are implemented #4540 model->test_unfinished_tracks = reader->GetBoolean("test_unfinished_tracks", false); @@ -242,6 +243,7 @@ namespace Config writer->WriteSint32("default_display", model->default_display); writer->WriteEnum("drawing_engine", model->drawing_engine, Enum_DrawingEngine); writer->WriteBoolean("uncap_fps", model->uncap_fps); + writer->WriteBoolean("use_vsync", model->use_vsync); writer->WriteBoolean("test_unfinished_tracks", model->test_unfinished_tracks); writer->WriteBoolean("no_test_crashes", model->no_test_crashes); writer->WriteEnum("date_format", model->date_format, Enum_DateFormat); diff --git a/src/openrct2/config/Config.h b/src/openrct2/config/Config.h index 64f14b5e9f..23ed4adeaf 100644 --- a/src/openrct2/config/Config.h +++ b/src/openrct2/config/Config.h @@ -35,6 +35,7 @@ typedef struct GeneralConfiguration sint32 drawing_engine; sint32 scale_quality; bool uncap_fps; + bool use_vsync; bool show_fps; bool minimize_fullscreen_focus_loss; diff --git a/src/openrct2/drawing/IDrawingEngine.h b/src/openrct2/drawing/IDrawingEngine.h index 645a3d4cd6..026813bb6c 100644 --- a/src/openrct2/drawing/IDrawingEngine.h +++ b/src/openrct2/drawing/IDrawingEngine.h @@ -54,7 +54,7 @@ namespace OpenRCT2 { namespace Drawing virtual void Resize(uint32 width, uint32 height) abstract; virtual void SetPalette(const rct_palette_entry * colours) abstract; - virtual void SetUncappedFrameRate(bool uncapped) abstract; + virtual void SetVSync(bool vsync) abstract; virtual void Invalidate(sint32 left, sint32 top, sint32 right, sint32 bottom) abstract; virtual void BeginDraw() abstract; diff --git a/src/openrct2/drawing/NewDrawing.cpp b/src/openrct2/drawing/NewDrawing.cpp index fe63938268..336d94f450 100644 --- a/src/openrct2/drawing/NewDrawing.cpp +++ b/src/openrct2/drawing/NewDrawing.cpp @@ -105,7 +105,7 @@ extern "C" try { drawingEngine->Initialise(); - drawingEngine->SetUncappedFrameRate(gConfigGeneral.uncap_fps == 1); + drawingEngine->SetVSync(gConfigGeneral.use_vsync); _drawingEngine = drawingEngine; } catch (const Exception &ex) @@ -202,11 +202,11 @@ extern "C" } } - void drawing_engine_set_fps_uncapped(bool uncapped) + void drawing_engine_set_vsync(bool vsync) { if (_drawingEngine != nullptr) { - _drawingEngine->SetUncappedFrameRate(uncapped); + _drawingEngine->SetVSync(vsync); } } diff --git a/src/openrct2/drawing/NewDrawing.h b/src/openrct2/drawing/NewDrawing.h index 74ceae57cb..c9003c098a 100644 --- a/src/openrct2/drawing/NewDrawing.h +++ b/src/openrct2/drawing/NewDrawing.h @@ -38,7 +38,7 @@ void drawing_engine_dispose(); rct_drawpixelinfo * drawing_engine_get_dpi(); bool drawing_engine_has_dirty_optimisations(); void drawing_engine_invalidate_image(uint32 image); -void drawing_engine_set_fps_uncapped(bool uncapped); +void drawing_engine_set_vsync(bool vsync); #ifdef __cplusplus } diff --git a/src/openrct2/drawing/X8DrawingEngine.cpp b/src/openrct2/drawing/X8DrawingEngine.cpp index ae084cb68e..6a4e1e45c2 100644 --- a/src/openrct2/drawing/X8DrawingEngine.cpp +++ b/src/openrct2/drawing/X8DrawingEngine.cpp @@ -163,7 +163,7 @@ void X8DrawingEngine::SetPalette(const rct_palette_entry * palette) { } -void X8DrawingEngine::SetUncappedFrameRate(bool uncapped) +void X8DrawingEngine::SetVSync(bool vsync) { // Not applicable for this engine } diff --git a/src/openrct2/drawing/X8DrawingEngine.h b/src/openrct2/drawing/X8DrawingEngine.h index 6f4242f60e..57f7e8bf39 100644 --- a/src/openrct2/drawing/X8DrawingEngine.h +++ b/src/openrct2/drawing/X8DrawingEngine.h @@ -99,7 +99,7 @@ namespace OpenRCT2 void Initialise() override; void Resize(uint32 width, uint32 height) override; void SetPalette(const rct_palette_entry * palette) override; - void SetUncappedFrameRate(bool uncapped) override; + void SetVSync(bool vsync) override; void Invalidate(sint32 left, sint32 top, sint32 right, sint32 bottom) override; void BeginDraw() override; void EndDraw() override; diff --git a/src/openrct2/localisation/string_ids.h b/src/openrct2/localisation/string_ids.h index 6c93d39266..a29122eb3f 100644 --- a/src/openrct2/localisation/string_ids.h +++ b/src/openrct2/localisation/string_ids.h @@ -3810,6 +3810,9 @@ enum { STR_CLOSE_X_WHITE = 6164, + STR_USE_VSYNC = 6165, + STR_USE_VSYNC_TIP = 6166, + // Have to include resource strings (from scenarios and objects) for the time being now that language is partially working STR_COUNT = 32768 };