소스 검색

Move frame delaying functions from Main to OS.

Will allow specific platforms to override it and avoid blocking on the
main/GUI thread.
Fabio Alessandrelli 5 년 전
부모
커밋
1b6e3458b2
4개의 변경된 파일40개의 추가작업 그리고 34개의 파일을 삭제
  1. 36 0
      core/os/os.cpp
  2. 3 0
      core/os/os.h
  3. 1 33
      main/main.cpp
  4. 0 1
      main/main.h

+ 36 - 0
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;
 

+ 3 - 0
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;

+ 1 - 33
main/main.cpp

@@ -2115,7 +2115,6 @@ bool Main::start() {
  */
 
 uint64_t Main::last_ticks = 0;
-uint64_t Main::target_ticks = 0;
 uint32_t Main::frames = 0;
 uint32_t Main::frame = 0;
 bool Main::force_redraw_requested = false;
@@ -2266,38 +2265,7 @@ bool Main::iteration() {
 		return exit;
 	}
 
-	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.
-		OS::get_singleton()->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 (OS::get_singleton()->is_in_low_processor_usage_mode() || !DisplayServer::get_singleton()->window_can_draw()) {
-		dynamic_delay = OS::get_singleton()->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 = OS::get_singleton()->get_ticks_usec();
-
-		if (current_ticks < target_ticks) {
-			OS::get_singleton()->delay_usec(target_ticks - current_ticks);
-		}
-
-		current_ticks = OS::get_singleton()->get_ticks_usec();
-		target_ticks = MIN(MAX(target_ticks, current_ticks - dynamic_delay), current_ticks + dynamic_delay);
-	}
+	OS::get_singleton()->add_frame_delay(DisplayServer::get_singleton()->window_can_draw());
 
 #ifdef TOOLS_ENABLED
 	if (auto_build_solutions) {

+ 0 - 1
main/main.h

@@ -38,7 +38,6 @@
 class Main {
 	static void print_help(const char *p_binary);
 	static uint64_t last_ticks;
-	static uint64_t target_ticks;
 	static uint32_t frames;
 	static uint32_t frame;
 	static bool force_redraw_requested;