Add draw_manager::get_frame_length() to get the length of one frame

This will usually be determined by the monitor's refresh rate,
but also is rounded down to provide some leeway. It also limits
according to the draw_delay preference.

The loading screen now uses this to limit event calls.
This commit is contained in:
Tommy 2022-07-29 16:34:28 +12:00
parent c0990fd258
commit 09f80573a1
3 changed files with 18 additions and 4 deletions

View file

@ -18,6 +18,7 @@
#include "exceptions.hpp"
#include "log.hpp"
#include "gui/core/top_level_drawable.hpp"
#include "preferences/general.hpp"
#include "sdl/rect.hpp"
#include "video.hpp"
@ -161,7 +162,7 @@ void sparkle()
last_sparkle_ = SDL_GetTicks();
}
static void wait_for_vsync()
int get_frame_length()
{
int rr = video::current_refresh_rate();
if (rr <= 0) {
@ -170,7 +171,13 @@ static void wait_for_vsync()
}
// allow 1ms for general processing
int vsync_delay = (1000 / rr) - 1;
int time_to_wait = last_sparkle_ + vsync_delay - SDL_GetTicks();
// if there's a preferred limit, limit to that
return std::clamp(vsync_delay, preferences::draw_delay(), 1000);
}
static void wait_for_vsync()
{
int time_to_wait = last_sparkle_ + get_frame_length() - SDL_GetTicks();
if (time_to_wait > 0) {
// delay a maximum of 1 second in case something crazy happens
SDL_Delay(std::min(time_to_wait, 1000));

View file

@ -105,6 +105,13 @@ void invalidate_all();
*/
void sparkle();
/**
* Returns the length of one display frame, in milliseconds.
*
* This will usually be determined by the active monitor's refresh rate.
*/
int get_frame_length();
/** Register a top-level drawable.
*
* Registered drawables will be drawn in the order of registration,

View file

@ -139,9 +139,9 @@ void loading_screen::spin()
// Restrict actual update rate.
int elapsed = SDL_GetTicks() - last_spin_;
if (elapsed > 10 || elapsed < 0) {
events::pump_and_draw();
if (elapsed > draw_manager::get_frame_length() || elapsed < 0) {
last_spin_ = SDL_GetTicks();
events::pump_and_draw();
}
}