diff options
author | RĂ©mi Verschelde <rverschelde@gmail.com> | 2020-06-30 22:13:58 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-06-30 22:13:58 +0200 |
commit | 5187d25eb207539d1b6eacc9ea2e9a9ec9a7d87a (patch) | |
tree | 2b96683e999d5a042d425180c09de2d29c564aa3 /core | |
parent | 8ea75abde62817ff695cc9a113306e16b01d3c45 (diff) | |
parent | 1b6e3458b24836c362ac245ddeec627207dd2981 (diff) |
Merge pull request #39994 from Faless/iteration/os_delay
Move frame delaying functions from Main to OS.
Diffstat (limited to 'core')
-rw-r--r-- | core/os/os.cpp | 36 | ||||
-rw-r--r-- | core/os/os.h | 3 |
2 files changed, 39 insertions, 0 deletions
diff --git a/core/os/os.cpp b/core/os/os.cpp index c842be333c..231069fcfb 100644 --- a/core/os/os.cpp +++ b/core/os/os.cpp @@ -41,6 +41,7 @@ #include <stdarg.h> OS *OS::singleton = nullptr; +uint64_t OS::target_ticks = 0; OS *OS::get_singleton() { return singleton; @@ -468,6 +469,41 @@ void OS::close_midi_inputs() { } } +void OS::add_frame_delay(bool p_can_draw) { + const uint32_t frame_delay = Engine::get_singleton()->get_frame_delay(); + if (frame_delay) { + // Add fixed frame delay to decrease CPU/GPU usage. This doesn't take + // the actual frame time into account. + // Due to the high fluctuation of the actual sleep duration, it's not recommended + // to use this as a FPS limiter. + delay_usec(frame_delay * 1000); + } + + // Add a dynamic frame delay to decrease CPU/GPU usage. This takes the + // previous frame time into account for a smoother result. + uint64_t dynamic_delay = 0; + if (is_in_low_processor_usage_mode() || !p_can_draw) { + dynamic_delay = get_low_processor_usage_mode_sleep_usec(); + } + const int target_fps = Engine::get_singleton()->get_target_fps(); + if (target_fps > 0 && !Engine::get_singleton()->is_editor_hint()) { + // Override the low processor usage mode sleep delay if the target FPS is lower. + dynamic_delay = MAX(dynamic_delay, (uint64_t)(1000000 / target_fps)); + } + + if (dynamic_delay > 0) { + target_ticks += dynamic_delay; + uint64_t current_ticks = get_ticks_usec(); + + if (current_ticks < target_ticks) { + delay_usec(target_ticks - current_ticks); + } + + current_ticks = get_ticks_usec(); + target_ticks = MIN(MAX(target_ticks, current_ticks - dynamic_delay), current_ticks + dynamic_delay); + } +} + OS::OS() { void *volatile stack_bottom; diff --git a/core/os/os.h b/core/os/os.h index 04e10518dc..f21c0d4df7 100644 --- a/core/os/os.h +++ b/core/os/os.h @@ -43,6 +43,7 @@ class OS { static OS *singleton; + static uint64_t target_ticks; String _execpath; List<String> _cmdline; bool _keep_screen_on = true; // set default value to true, because this had been true before godot 2.0. @@ -212,6 +213,8 @@ public: virtual double get_unix_time() const; virtual void delay_usec(uint32_t p_usec) const = 0; + virtual void add_frame_delay(bool p_can_draw); + virtual uint64_t get_ticks_usec() const = 0; uint32_t get_ticks_msec() const; uint64_t get_splash_tick_msec() const; |