From ea93bae302cc9eabe2bb65cbf22bac0e81cbfc0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tam=C3=A1s=20B=C3=A1lint=20Misius?= Date: Thu, 23 Jan 2025 23:59:55 +0100 Subject: [PATCH] Make emscripten work with draw limits --- src/PowderToyFontEditor.cpp | 6 +++- src/PowderToySDL.cpp | 9 ++---- src/PowderToySDL.h | 6 ++-- src/PowderToySDLCommon.cpp | 12 ++++---- src/PowderToySDLEmscripten.cpp | 52 +++++++++++++++++++++------------- src/gui/interface/Engine.cpp | 2 +- 6 files changed, 50 insertions(+), 37 deletions(-) diff --git a/src/PowderToyFontEditor.cpp b/src/PowderToyFontEditor.cpp index a491be9b5..c134d2023 100644 --- a/src/PowderToyFontEditor.cpp +++ b/src/PowderToyFontEditor.cpp @@ -82,7 +82,11 @@ int main(int argc, char * argv[]) while (engine.Running()) { - EngineProcess(); + auto delay = EngineProcess(); + if (delay.has_value()) + { + SDL_Delay(std::max(*delay, UINT64_C(1))); + } } Platform::Exit(0); return 0; diff --git a/src/PowderToySDL.cpp b/src/PowderToySDL.cpp index 0f5856756..946bddc5e 100644 --- a/src/PowderToySDL.cpp +++ b/src/PowderToySDL.cpp @@ -319,7 +319,7 @@ void SDLSetScreen() SDL_SetWindowSize(sdl_window, size.X, size.Y); LoadWindowPosition(); } - UpdateFpsLimit(); + ApplyFpsLimit(); if (newFrameOpsNorm.fullscreen) { SDL_RaiseWindow(sdl_window); @@ -450,7 +450,7 @@ static void EventProcess(const SDL_Event &event) } } -void EngineProcess() +std::optional EngineProcess() { auto &engine = ui::Engine::Ref(); auto correctedFrameTime = tickSchedule.GetFrameTime(); @@ -509,8 +509,5 @@ void EngineProcess() delay = tickSchedule.Arm(fpsLimitExplicit->value) / UINT64_C(1'000'000); } } - if (delay.has_value()) - { - SDL_Delay(std::max(*delay, UINT64_C(1))); - } + return delay; } diff --git a/src/PowderToySDL.h b/src/PowderToySDL.h index 43e3f69e0..5f3a7779b 100644 --- a/src/PowderToySDL.h +++ b/src/PowderToySDL.h @@ -6,6 +6,7 @@ #include #include #include +#include extern int desktopWidth; extern int desktopHeight; @@ -25,7 +26,7 @@ extern bool calculatedInitialMouse; extern bool hasMouseMoved; void MainLoop(); -void EngineProcess(); +std::optional EngineProcess(); void StartTextInput(); void StopTextInput(); void SetTextInputRect(int x, int y, int w, int h); @@ -37,9 +38,8 @@ void blit(pixel *vid); void SDLOpen(); void SDLClose(); void SDLSetScreen(); -void SetFpsLimit(FpsLimit newFpsLimit); void LoadWindowPosition(); void SaveWindowPosition(); void LargeScreenDialog(); void TickClient(); -void UpdateFpsLimit(); +void ApplyFpsLimit(); diff --git a/src/PowderToySDLCommon.cpp b/src/PowderToySDLCommon.cpp index c1d27fa46..b6c573ada 100644 --- a/src/PowderToySDLCommon.cpp +++ b/src/PowderToySDLCommon.cpp @@ -5,14 +5,14 @@ void MainLoop() { while (ui::Engine::Ref().Running()) { - EngineProcess(); + auto delay = EngineProcess(); + if (delay.has_value()) + { + SDL_Delay(std::max(*delay, UINT64_C(1))); + } } } -void SetFpsLimit(FpsLimit newFpsLimit) -{ -} - -void UpdateFpsLimit() +void ApplyFpsLimit() { } diff --git a/src/PowderToySDLEmscripten.cpp b/src/PowderToySDLEmscripten.cpp index 4b52c0692..408ea99ef 100644 --- a/src/PowderToySDLEmscripten.cpp +++ b/src/PowderToySDLEmscripten.cpp @@ -14,7 +14,7 @@ static void MainLoopBody() Platform::MaybeTriggerSyncFs(); } -void SetFpsLimit(FpsLimit newFpsLimit) +void ApplyFpsLimit() { static bool mainLoopSet = false; if (!mainLoopSet) @@ -22,31 +22,43 @@ void SetFpsLimit(FpsLimit newFpsLimit) emscripten_set_main_loop(MainLoopBody, 0, 0); mainLoopSet = true; } - // if (std::get_if(&newFpsLimit)) // TODO: DrawLimitVsync - // { - // emscripten_set_main_loop_timing(EM_TIMING_RAF, 1); - // std::cerr << "implicit fps limit via vsync" << std::endl; - // } - // else - // { - auto delay = 0; - if (auto *fpsLimitExplicit = std::get_if(&newFpsLimit)) + // this generally attempts to replicate the behaviour of EngineProcess + std::optional drawLimit; + auto &engine = ui::Engine::Ref(); + auto fpsLimit = engine.GetFpsLimit(); + if (auto *fpsLimitExplicit = std::get_if(&fpsLimit)) + { + drawLimit = fpsLimitExplicit->value; + } + else if (std::holds_alternative(fpsLimit)) + { + auto effectiveDrawLimit = engine.GetEffectiveDrawCap(); + if (effectiveDrawLimit) { - delay = int(1000.f / fpsLimitExplicit->value); + drawLimit = float(*effectiveDrawLimit); } - emscripten_set_main_loop_timing(EM_TIMING_SETTIMEOUT, delay); - std::cerr << "explicit fps limit: " << delay << "ms delays" << std::endl; - // } -} - -void UpdateFpsLimit() -{ - SetFpsLimit(ui::Engine::Ref().GetFpsLimit()); + // else // TODO: DrawLimitVsync + // { + // if (std::holds_alternative(engine.GetDrawingFrequencyLimit())) + // { + // emscripten_set_main_loop_timing(EM_TIMING_RAF, 1); + // std::cerr << "implicit fps limit via vsync" << std::endl; + // return; + // } + // } + } + int delay = 0; // no cap + if (drawLimit.has_value()) + { + delay = int(1000.f / *drawLimit); + } + emscripten_set_main_loop_timing(EM_TIMING_SETTIMEOUT, delay); + std::cerr << "explicit fps limit: " << delay << "ms delays" << std::endl; } // Is actually only called once at startup, the real main loop body is MainLoopBody. void MainLoop() { - UpdateFpsLimit(); + ApplyFpsLimit(); MainLoopBody(); } diff --git a/src/gui/interface/Engine.cpp b/src/gui/interface/Engine.cpp index 160858d1b..89b390a19 100644 --- a/src/gui/interface/Engine.cpp +++ b/src/gui/interface/Engine.cpp @@ -39,7 +39,7 @@ Engine::~Engine() void Engine::ApplyFpsLimit() { - ::SetFpsLimit(GetFpsLimit()); + ::ApplyFpsLimit(); } void Engine::Begin()