From 7a5a8597eb81b20b14d3ab1f8b2d6dace49a2603 Mon Sep 17 00:00:00 2001 From: David Snopek Date: Mon, 15 Jul 2024 16:58:21 -0500 Subject: [PATCH] Always render when XR is enabled, even if no OS windows can draw --- doc/classes/DisplayServer.xml | 21 +++++++++++++++++++++ main/main.cpp | 2 +- modules/openxr/openxr_interface.cpp | 6 ++++++ servers/display_server.cpp | 15 +++++++++++++++ servers/display_server.h | 6 ++++++ 5 files changed, 49 insertions(+), 1 deletion(-) diff --git a/doc/classes/DisplayServer.xml b/doc/classes/DisplayServer.xml index ff1c390b3c0a..1a611bdbe7a7 100644 --- a/doc/classes/DisplayServer.xml +++ b/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. + + + + Returns [code]true[/code] if any additional outputs have been registered via [method register_additional_output]. + + @@ -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]. + + + + + 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. + + @@ -1352,6 +1366,13 @@ [b]Note:[/b] [member ProjectSettings.audio/general/text_to_speech] should be [code]true[/code] to use text-to-speech. + + + + + Unregisters an [Object] representing an additional output, that was registered via [method register_additional_output]. + + diff --git a/main/main.cpp b/main/main.cpp index 060b3fe2f608..a83338763054 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -4108,7 +4108,7 @@ bool Main::iteration() { 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()) { if ((!force_redraw_requested) && OS::get_singleton()->is_in_low_processor_usage_mode()) { if (RenderingServer::get_singleton()->has_changed()) { diff --git a/modules/openxr/openxr_interface.cpp b/modules/openxr/openxr_interface.cpp index fbbc61a91ce2..cce9c0936127 100644 --- a/modules/openxr/openxr_interface.cpp +++ b/modules/openxr/openxr_interface.cpp @@ -651,6 +651,10 @@ bool OpenXRInterface::initialize() { // make this our primary interface 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; return initialized; @@ -674,6 +678,8 @@ void OpenXRInterface::uninitialize() { } } + DisplayServer::get_singleton()->unregister_additional_output(this); + initialized = false; } diff --git a/servers/display_server.cpp b/servers/display_server.cpp index b6e0d58af744..d362a4073af7 100644 --- a/servers/display_server.cpp +++ b/servers/display_server.cpp @@ -759,6 +759,17 @@ DisplayServer::WindowID DisplayServer::get_focused_window() const { 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() { ClassDB::bind_method(D_METHOD("has_feature", "feature"), &DisplayServer::has_feature); 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("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 BIND_ENUM_CONSTANT(FEATURE_GLOBAL_MENU); #endif diff --git a/servers/display_server.h b/servers/display_server.h index 5d82b6c13c92..8c7e92fdc36c 100644 --- a/servers/display_server.h +++ b/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; #endif + LocalVector additional_outputs; + public: _FORCE_INLINE_ static DisplayServer *get_singleton() { return singleton; @@ -582,6 +584,10 @@ class DisplayServer : public Object { 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 int get_create_function_count(); static const char *get_create_function_name(int p_index);