소스 검색

Always render when XR is enabled, even if no OS windows can draw

David Snopek 1 년 전
부모
커밋
7a5a8597eb
5개의 변경된 파일49개의 추가작업 그리고 1개의 파일을 삭제
  1. 21 0
      doc/classes/DisplayServer.xml
  2. 1 1
      main/main.cpp
  3. 6 0
      modules/openxr/openxr_interface.cpp
  4. 15 0
      servers/display_server.cpp
  5. 6 0
      servers/display_server.h

+ 21 - 0
doc/classes/DisplayServer.xml

@@ -879,6 +879,12 @@
 				Registers callables to emit when the menu is respectively about to show or closed. Callback methods should have zero arguments.
 				Registers callables to emit when the menu is respectively about to show or closed. Callback methods should have zero arguments.
 			</description>
 			</description>
 		</method>
 		</method>
+		<method name="has_additional_outputs" qualifiers="const">
+			<return type="bool" />
+			<description>
+				Returns [code]true[/code] if any additional outputs have been registered via [method register_additional_output].
+			</description>
+		</method>
 		<method name="has_feature" qualifiers="const">
 		<method name="has_feature" qualifiers="const">
 			<return type="bool" />
 			<return type="bool" />
 			<param index="0" name="feature" type="int" enum="DisplayServer.Feature" />
 			<param index="0" name="feature" type="int" enum="DisplayServer.Feature" />
@@ -1022,6 +1028,14 @@
 				Perform window manager processing, including input flushing. See also [method force_process_and_drop_events], [method Input.flush_buffered_events] and [member Input.use_accumulated_input].
 				Perform window manager processing, including input flushing. See also [method force_process_and_drop_events], [method Input.flush_buffered_events] and [member Input.use_accumulated_input].
 			</description>
 			</description>
 		</method>
 		</method>
+		<method name="register_additional_output">
+			<return type="void" />
+			<param index="0" name="object" type="Object" />
+			<description>
+				Registers an [Object] which represents an additional output that will be rendered too, beyond normal windows. The [Object] is only used as an identifier, which can be later passed to [method unregister_additional_output].
+				This can be used to prevent Godot from skipping rendering when no normal windows are visible.
+			</description>
+		</method>
 		<method name="screen_get_dpi" qualifiers="const">
 		<method name="screen_get_dpi" qualifiers="const">
 			<return type="int" />
 			<return type="int" />
 			<param index="0" name="screen" type="int" default="-1" />
 			<param index="0" name="screen" type="int" default="-1" />
@@ -1352,6 +1366,13 @@
 				[b]Note:[/b] [member ProjectSettings.audio/general/text_to_speech] should be [code]true[/code] to use text-to-speech.
 				[b]Note:[/b] [member ProjectSettings.audio/general/text_to_speech] should be [code]true[/code] to use text-to-speech.
 			</description>
 			</description>
 		</method>
 		</method>
+		<method name="unregister_additional_output">
+			<return type="void" />
+			<param index="0" name="object" type="Object" />
+			<description>
+				Unregisters an [Object] representing an additional output, that was registered via [method register_additional_output].
+			</description>
+		</method>
 		<method name="virtual_keyboard_get_height" qualifiers="const">
 		<method name="virtual_keyboard_get_height" qualifiers="const">
 			<return type="int" />
 			<return type="int" />
 			<description>
 			<description>

+ 1 - 1
main/main.cpp

@@ -4108,7 +4108,7 @@ bool Main::iteration() {
 
 
 	RenderingServer::get_singleton()->sync(); //sync if still drawing from previous frames.
 	RenderingServer::get_singleton()->sync(); //sync if still drawing from previous frames.
 
 
-	if (DisplayServer::get_singleton()->can_any_window_draw() &&
+	if ((DisplayServer::get_singleton()->can_any_window_draw() || DisplayServer::get_singleton()->has_additional_outputs()) &&
 			RenderingServer::get_singleton()->is_render_loop_enabled()) {
 			RenderingServer::get_singleton()->is_render_loop_enabled()) {
 		if ((!force_redraw_requested) && OS::get_singleton()->is_in_low_processor_usage_mode()) {
 		if ((!force_redraw_requested) && OS::get_singleton()->is_in_low_processor_usage_mode()) {
 			if (RenderingServer::get_singleton()->has_changed()) {
 			if (RenderingServer::get_singleton()->has_changed()) {

+ 6 - 0
modules/openxr/openxr_interface.cpp

@@ -651,6 +651,10 @@ bool OpenXRInterface::initialize() {
 	// make this our primary interface
 	// make this our primary interface
 	xr_server->set_primary_interface(this);
 	xr_server->set_primary_interface(this);
 
 
+	// Register an additional output with the display server, so rendering won't
+	// be skipped if no windows are visible.
+	DisplayServer::get_singleton()->register_additional_output(this);
+
 	initialized = true;
 	initialized = true;
 
 
 	return initialized;
 	return initialized;
@@ -674,6 +678,8 @@ void OpenXRInterface::uninitialize() {
 		}
 		}
 	}
 	}
 
 
+	DisplayServer::get_singleton()->unregister_additional_output(this);
+
 	initialized = false;
 	initialized = false;
 }
 }
 
 

+ 15 - 0
servers/display_server.cpp

@@ -759,6 +759,17 @@ DisplayServer::WindowID DisplayServer::get_focused_window() const {
 void DisplayServer::set_context(Context p_context) {
 void DisplayServer::set_context(Context p_context) {
 }
 }
 
 
+void DisplayServer::register_additional_output(Object *p_object) {
+	ObjectID id = p_object->get_instance_id();
+	if (!additional_outputs.has(id)) {
+		additional_outputs.push_back(id);
+	}
+}
+
+void DisplayServer::unregister_additional_output(Object *p_object) {
+	additional_outputs.erase(p_object->get_instance_id());
+}
+
 void DisplayServer::_bind_methods() {
 void DisplayServer::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("has_feature", "feature"), &DisplayServer::has_feature);
 	ClassDB::bind_method(D_METHOD("has_feature", "feature"), &DisplayServer::has_feature);
 	ClassDB::bind_method(D_METHOD("get_name"), &DisplayServer::get_name);
 	ClassDB::bind_method(D_METHOD("get_name"), &DisplayServer::get_name);
@@ -997,6 +1008,10 @@ void DisplayServer::_bind_methods() {
 
 
 	ClassDB::bind_method(D_METHOD("is_window_transparency_available"), &DisplayServer::is_window_transparency_available);
 	ClassDB::bind_method(D_METHOD("is_window_transparency_available"), &DisplayServer::is_window_transparency_available);
 
 
+	ClassDB::bind_method(D_METHOD("register_additional_output", "object"), &DisplayServer::register_additional_output);
+	ClassDB::bind_method(D_METHOD("unregister_additional_output", "object"), &DisplayServer::unregister_additional_output);
+	ClassDB::bind_method(D_METHOD("has_additional_outputs"), &DisplayServer::has_additional_outputs);
+
 #ifndef DISABLE_DEPRECATED
 #ifndef DISABLE_DEPRECATED
 	BIND_ENUM_CONSTANT(FEATURE_GLOBAL_MENU);
 	BIND_ENUM_CONSTANT(FEATURE_GLOBAL_MENU);
 #endif
 #endif

+ 6 - 0
servers/display_server.h

@@ -53,6 +53,8 @@ class DisplayServer : public Object {
 	RID _get_rid_from_name(NativeMenu *p_nmenu, const String &p_menu_root) const;
 	RID _get_rid_from_name(NativeMenu *p_nmenu, const String &p_menu_root) const;
 #endif
 #endif
 
 
+	LocalVector<ObjectID> additional_outputs;
+
 public:
 public:
 	_FORCE_INLINE_ static DisplayServer *get_singleton() {
 	_FORCE_INLINE_ static DisplayServer *get_singleton() {
 		return singleton;
 		return singleton;
@@ -582,6 +584,10 @@ public:
 
 
 	virtual bool is_window_transparency_available() const { return false; }
 	virtual bool is_window_transparency_available() const { return false; }
 
 
+	void register_additional_output(Object *p_output);
+	void unregister_additional_output(Object *p_output);
+	bool has_additional_outputs() const { return additional_outputs.size() > 0; }
+
 	static void register_create_function(const char *p_name, CreateFunction p_function, GetRenderingDriversFunction p_get_drivers);
 	static void register_create_function(const char *p_name, CreateFunction p_function, GetRenderingDriversFunction p_get_drivers);
 	static int get_create_function_count();
 	static int get_create_function_count();
 	static const char *get_create_function_name(int p_index);
 	static const char *get_create_function_name(int p_index);