From 86fd919699f94d4e306b388c9714f46a3063dd83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tam=C3=A1s=20B=C3=A1lint=20Misius?= Date: Sat, 21 Dec 2024 10:14:05 +0100 Subject: [PATCH] Add draw limit variant that mirrors the display's refresh rate --- src/FpsLimit.h | 12 ++++++++++++ src/PowderToySDL.cpp | 24 ++++++++++++++++++++---- src/gui/interface/Engine.cpp | 2 +- src/gui/interface/Engine.h | 18 +++++++++++++++--- src/lua/LuaMisc.cpp | 28 +++++++++++++++++++++++++--- 5 files changed, 73 insertions(+), 11 deletions(-) diff --git a/src/FpsLimit.h b/src/FpsLimit.h index 5d8a69335..88f4e6fd8 100644 --- a/src/FpsLimit.h +++ b/src/FpsLimit.h @@ -12,3 +12,15 @@ struct FpsLimitExplicit float value; }; using FpsLimit = std::variant; + +struct DrawLimitDisplay +{ +}; +struct DrawLimitNone +{ +}; +struct DrawLimitExplicit +{ + int value; +}; +using DrawLimit = std::variant; diff --git a/src/PowderToySDL.cpp b/src/PowderToySDL.cpp index c34d88e0b..26277f369 100644 --- a/src/PowderToySDL.cpp +++ b/src/PowderToySDL.cpp @@ -156,6 +156,7 @@ void SDLOpen() SDLSetScreen(); int displayIndex = SDL_GetWindowDisplayIndex(sdl_window); + std::optional refreshRate; if (displayIndex >= 0) { SDL_Rect rect; @@ -164,7 +165,13 @@ void SDLOpen() desktopWidth = rect.w; desktopHeight = rect.h; } + SDL_DisplayMode displayMode; + if (!SDL_GetCurrentDisplayMode(displayIndex, &displayMode) && displayMode.refresh_rate) + { + refreshRate = displayMode.refresh_rate; + } } + ui::Engine::Ref().SetRefreshRate(refreshRate); StopTextInput(); } @@ -460,15 +467,24 @@ void EngineProcess() engine.Tick(); { - int drawcap = ui::Engine::Ref().GetDrawingFrequencyLimit(); + auto drawLimit = ui::Engine::Ref().GetDrawingFrequencyLimit(); auto nowNs = uint64_t(SDL_GetTicks()) * UINT64_C(1'000'000); - if (!drawcap || drawSchedule.HasElapsed(nowNs)) + std::optional effectiveDrawLimit; + if (auto *drawLimitExplicit = std::get_if(&drawLimit)) + { + effectiveDrawLimit = drawLimitExplicit->value; + } + if (std::get_if(&drawLimit)) + { + effectiveDrawLimit = engine.GetRefreshRate(); + } + if (!effectiveDrawLimit || drawSchedule.HasElapsed(nowNs)) { engine.Draw(); drawSchedule.SetNow(nowNs); - if (drawcap) + if (effectiveDrawLimit) { - drawSchedule.Arm(float(drawcap)); + drawSchedule.Arm(float(*effectiveDrawLimit)); } SDLSetScreen(); blit(engine.g->Data()); diff --git a/src/gui/interface/Engine.cpp b/src/gui/interface/Engine.cpp index 5b8635ad3..a73448e43 100644 --- a/src/gui/interface/Engine.cpp +++ b/src/gui/interface/Engine.cpp @@ -11,7 +11,7 @@ using namespace ui; Engine::Engine(): - drawingFrequencyLimit(0), + drawingFrequencyLimit(DrawLimitDisplay{}), FrameIndex(0), state_(nullptr), windowTargetPosition(0, 0), diff --git a/src/gui/interface/Engine.h b/src/gui/interface/Engine.h index 9d6fa1ce8..65ea041f4 100644 --- a/src/gui/interface/Engine.h +++ b/src/gui/interface/Engine.h @@ -1,5 +1,6 @@ #pragma once #include +#include #include #include "common/String.h" #include "common/ExplicitSingleton.h" @@ -47,8 +48,8 @@ namespace ui void Exit(); void ConfirmExit(); - void SetDrawingFrequencyLimit(int limit) {drawingFrequencyLimit = limit;} - inline int GetDrawingFrequencyLimit() {return drawingFrequencyLimit;} + void SetDrawingFrequencyLimit(DrawLimit limit) {drawingFrequencyLimit = limit;} + inline DrawLimit GetDrawingFrequencyLimit() {return drawingFrequencyLimit;} void SetFastQuit(bool fastquit) { FastQuit = fastquit; } inline bool GetFastQuit() {return FastQuit; } void SetGlobalQuit(bool newGlobalQuit) { GlobalQuit = newGlobalQuit; } @@ -78,7 +79,7 @@ namespace ui return fpsLimit; } - int drawingFrequencyLimit; + DrawLimit drawingFrequencyLimit; Graphics * g; bool GraveExitsConsole; @@ -99,6 +100,7 @@ namespace ui Window* state_; Point windowTargetPosition; bool ignoreEvents = false; + std::optional refreshRate; // saved appearances of windows that are in the backround and // thus are not currently being redrawn @@ -141,5 +143,15 @@ namespace ui bool GetForceIntegerScaling() const { return windowFrameOps.forceIntegerScaling; } bool GetResizable () const { return windowFrameOps.resizable; } bool GetBlurryScaling () const { return windowFrameOps.blurryScaling; } + + std::optional GetRefreshRate() const + { + return refreshRate; + } + + void SetRefreshRate(std::optional newRefreshRate) + { + refreshRate = newRefreshRate; + } }; } diff --git a/src/lua/LuaMisc.cpp b/src/lua/LuaMisc.cpp index deb34b20d..654745a46 100644 --- a/src/lua/LuaMisc.cpp +++ b/src/lua/LuaMisc.cpp @@ -239,13 +239,35 @@ static int drawCap(lua_State *L) int acount = lua_gettop(L); if (acount == 0) { - lua_pushinteger(L, ui::Engine::Ref().GetDrawingFrequencyLimit()); + auto drawLimit = ui::Engine::Ref().GetDrawingFrequencyLimit(); + if (std::holds_alternative(drawLimit)) + { + lua_pushliteral(L, "display"); + } + else if (std::holds_alternative(drawLimit)) + { + lua_pushinteger(L, 0); + } + else + { + lua_pushinteger(L, std::get(drawLimit).value); + } return 1; } - int drawcap = luaL_checkint(L, 1); + if (lua_isstring(L, 1) && byteStringEqualsLiteral(tpt_lua_toByteString(L, 1), "display")) + { + ui::Engine::Ref().SetDrawingFrequencyLimit(DrawLimitDisplay{}); + return 0; + } + int drawcap = luaL_checkinteger(L, 1); if(drawcap < 0) return luaL_error(L, "draw cap too small"); - ui::Engine::Ref().SetDrawingFrequencyLimit(drawcap); + if (drawcap == 0) + { + ui::Engine::Ref().SetDrawingFrequencyLimit(DrawLimitNone{}); + return 0; + } + ui::Engine::Ref().SetDrawingFrequencyLimit(DrawLimitExplicit{ drawcap }); return 0; }