mirror of
https://github.com/godotengine/godot.git
synced 2025-12-07 22:00:10 +00:00
Use system timer/wait functions for frame delay when screen reader is active.
This commit is contained in:
parent
1b37dacc18
commit
98f377d9d0
9 changed files with 70 additions and 13 deletions
|
|
@ -658,7 +658,25 @@ void OS::close_midi_inputs() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OS::add_frame_delay(bool p_can_draw) {
|
uint64_t OS::get_frame_delay(bool p_can_draw) const {
|
||||||
|
const uint32_t frame_delay = Engine::get_singleton()->get_frame_delay();
|
||||||
|
|
||||||
|
// 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 max_fps = Engine::get_singleton()->get_max_fps();
|
||||||
|
if (max_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 / max_fps));
|
||||||
|
}
|
||||||
|
|
||||||
|
return frame_delay + dynamic_delay;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OS::add_frame_delay(bool p_can_draw, bool p_wake_for_events) {
|
||||||
const uint32_t frame_delay = Engine::get_singleton()->get_frame_delay();
|
const uint32_t frame_delay = Engine::get_singleton()->get_frame_delay();
|
||||||
if (frame_delay) {
|
if (frame_delay) {
|
||||||
// Add fixed frame delay to decrease CPU/GPU usage. This doesn't take
|
// Add fixed frame delay to decrease CPU/GPU usage. This doesn't take
|
||||||
|
|
|
||||||
|
|
@ -247,7 +247,8 @@ public:
|
||||||
virtual double get_unix_time() const;
|
virtual double get_unix_time() const;
|
||||||
|
|
||||||
virtual void delay_usec(uint32_t p_usec) const = 0;
|
virtual void delay_usec(uint32_t p_usec) const = 0;
|
||||||
virtual void add_frame_delay(bool p_can_draw);
|
virtual void add_frame_delay(bool p_can_draw, bool p_wake_for_events);
|
||||||
|
virtual uint64_t get_frame_delay(bool p_can_draw) const;
|
||||||
|
|
||||||
virtual uint64_t get_ticks_usec() const = 0;
|
virtual uint64_t get_ticks_usec() const = 0;
|
||||||
uint64_t get_ticks_msec() const;
|
uint64_t get_ticks_msec() const;
|
||||||
|
|
|
||||||
|
|
@ -4855,11 +4855,9 @@ bool Main::iteration() {
|
||||||
}
|
}
|
||||||
|
|
||||||
SceneTree *scene_tree = SceneTree::get_singleton();
|
SceneTree *scene_tree = SceneTree::get_singleton();
|
||||||
bool skip_delay = scene_tree && scene_tree->is_accessibility_enabled();
|
bool wake_for_events = scene_tree && scene_tree->is_accessibility_enabled();
|
||||||
|
|
||||||
if (!skip_delay) {
|
OS::get_singleton()->add_frame_delay(DisplayServer::get_singleton()->window_can_draw(), wake_for_events);
|
||||||
OS::get_singleton()->add_frame_delay(DisplayServer::get_singleton()->window_can_draw());
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef TOOLS_ENABLED
|
#ifdef TOOLS_ENABLED
|
||||||
if (auto_build_solutions) {
|
if (auto_build_solutions) {
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,7 @@ protected:
|
||||||
|
|
||||||
JoypadApple *joypad_apple = nullptr;
|
JoypadApple *joypad_apple = nullptr;
|
||||||
MainLoop *main_loop = nullptr;
|
MainLoop *main_loop = nullptr;
|
||||||
|
CFRunLoopTimerRef wait_timer = nil;
|
||||||
|
|
||||||
virtual void initialize_core() override;
|
virtual void initialize_core() override;
|
||||||
virtual void initialize() override;
|
virtual void initialize() override;
|
||||||
|
|
@ -75,6 +76,8 @@ protected:
|
||||||
virtual void delete_main_loop() override;
|
virtual void delete_main_loop() override;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
virtual void add_frame_delay(bool p_can_draw, bool p_wake_for_events) override;
|
||||||
|
|
||||||
virtual void set_cmdline_platform_args(const List<String> &p_args);
|
virtual void set_cmdline_platform_args(const List<String> &p_args);
|
||||||
virtual List<String> get_cmdline_platform_args() const override;
|
virtual List<String> get_cmdline_platform_args() const override;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,28 @@
|
||||||
#include <os/log.h>
|
#include <os/log.h>
|
||||||
#include <sys/sysctl.h>
|
#include <sys/sysctl.h>
|
||||||
|
|
||||||
|
void OS_MacOS::add_frame_delay(bool p_can_draw, bool p_wake_for_events) {
|
||||||
|
if (p_wake_for_events) {
|
||||||
|
uint64_t delay = get_frame_delay(p_can_draw);
|
||||||
|
if (delay == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (wait_timer) {
|
||||||
|
CFRunLoopTimerInvalidate(wait_timer);
|
||||||
|
CFRelease(wait_timer);
|
||||||
|
}
|
||||||
|
wait_timer = CFRunLoopTimerCreateWithHandler(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent() + (double(delay) / 1000000.0), 0, 0, 0,
|
||||||
|
^(CFRunLoopTimerRef timer) {
|
||||||
|
CFRunLoopTimerInvalidate(wait_timer);
|
||||||
|
CFRelease(wait_timer);
|
||||||
|
wait_timer = nil;
|
||||||
|
});
|
||||||
|
CFRunLoopAddTimer(CFRunLoopGetCurrent(), wait_timer, kCFRunLoopCommonModes);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
OS_Unix::add_frame_delay(p_can_draw, p_wake_for_events);
|
||||||
|
}
|
||||||
|
|
||||||
void OS_MacOS::initialize() {
|
void OS_MacOS::initialize() {
|
||||||
crash_handler.initialize();
|
crash_handler.initialize();
|
||||||
|
|
||||||
|
|
@ -995,8 +1017,9 @@ void OS_MacOS_NSApp::start_main() {
|
||||||
ERR_PRINT("NSException: " + String::utf8([exception reason].UTF8String));
|
ERR_PRINT("NSException: " + String::utf8([exception reason].UTF8String));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (wait_timer == nil) {
|
||||||
CFRunLoopWakeUp(CFRunLoopGetCurrent()); // Prevent main loop from sleeping.
|
CFRunLoopWakeUp(CFRunLoopGetCurrent()); // Prevent main loop from sleeping.
|
||||||
|
}
|
||||||
});
|
});
|
||||||
CFRunLoopAddObserver(CFRunLoopGetCurrent(), pre_wait_observer, kCFRunLoopCommonModes);
|
CFRunLoopAddObserver(CFRunLoopGetCurrent(), pre_wait_observer, kCFRunLoopCommonModes);
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -180,9 +180,9 @@ String OS_Web::get_name() const {
|
||||||
return "Web";
|
return "Web";
|
||||||
}
|
}
|
||||||
|
|
||||||
void OS_Web::add_frame_delay(bool p_can_draw) {
|
void OS_Web::add_frame_delay(bool p_can_draw, bool p_wake_for_events) {
|
||||||
#ifndef PROXY_TO_PTHREAD_ENABLED
|
#ifndef PROXY_TO_PTHREAD_ENABLED
|
||||||
OS::add_frame_delay(p_can_draw);
|
OS::add_frame_delay(p_can_draw, p_wake_for_events);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -99,7 +99,7 @@ public:
|
||||||
|
|
||||||
// Override default OS implementation which would block the main thread with delay_usec.
|
// Override default OS implementation which would block the main thread with delay_usec.
|
||||||
// Implemented in web_main.cpp loop callback instead.
|
// Implemented in web_main.cpp loop callback instead.
|
||||||
void add_frame_delay(bool p_can_draw) override;
|
void add_frame_delay(bool p_can_draw, bool p_wake_for_events) override;
|
||||||
|
|
||||||
void vibrate_handheld(int p_duration_ms, float p_amplitude) override;
|
void vibrate_handheld(int p_duration_ms, float p_amplitude) override;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2494,7 +2494,21 @@ String OS_Windows::get_system_ca_certificates() {
|
||||||
return certs;
|
return certs;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OS_Windows::add_frame_delay(bool p_can_draw) {
|
void OS_Windows::add_frame_delay(bool p_can_draw, bool p_wake_for_events) {
|
||||||
|
if (p_wake_for_events) {
|
||||||
|
uint64_t delay = get_frame_delay(p_can_draw);
|
||||||
|
if (delay == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DisplayServer *ds = DisplayServer::get_singleton();
|
||||||
|
DisplayServerWindows *ds_win = Object::cast_to<DisplayServerWindows>(ds);
|
||||||
|
if (ds_win) {
|
||||||
|
MsgWaitForMultipleObjects(0, nullptr, false, Math::floor(double(delay) / 1000.0), QS_ALLINPUT);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const uint32_t frame_delay = Engine::get_singleton()->get_frame_delay();
|
const uint32_t frame_delay = Engine::get_singleton()->get_frame_delay();
|
||||||
if (frame_delay) {
|
if (frame_delay) {
|
||||||
// Add fixed frame delay to decrease CPU/GPU usage. This doesn't take
|
// Add fixed frame delay to decrease CPU/GPU usage. This doesn't take
|
||||||
|
|
|
||||||
|
|
@ -193,7 +193,7 @@ public:
|
||||||
|
|
||||||
virtual Error set_cwd(const String &p_cwd) override;
|
virtual Error set_cwd(const String &p_cwd) override;
|
||||||
|
|
||||||
virtual void add_frame_delay(bool p_can_draw) override;
|
virtual void add_frame_delay(bool p_can_draw, bool p_wake_for_events) override;
|
||||||
virtual void delay_usec(uint32_t p_usec) const override;
|
virtual void delay_usec(uint32_t p_usec) const override;
|
||||||
virtual uint64_t get_ticks_usec() const override;
|
virtual uint64_t get_ticks_usec() const override;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue