diff options
author | Rémi Verschelde <rverschelde@gmail.com> | 2022-10-17 17:32:01 +0200 |
---|---|---|
committer | Rémi Verschelde <rverschelde@gmail.com> | 2022-10-17 17:32:01 +0200 |
commit | 667bc202b55b8d00a4d84affb212adb2101a5c30 (patch) | |
tree | 180be4f8c199e4c4d7773bf7ed81d8dbef5db7ed /modules/openxr | |
parent | 3c4b110ae014972c4c2e7a6c9704cd1b6c79f6ef (diff) | |
parent | e14717bb2e1687093d4ac6f9bc06ea79ae0bd2fb (diff) |
Merge pull request #67179 from BastiaanOlij/openxr_add_refresh_rate_extension
Adding support for the OpenXR Display Refresh Rate extension
Diffstat (limited to 'modules/openxr')
-rw-r--r-- | modules/openxr/SCsub | 1 | ||||
-rw-r--r-- | modules/openxr/doc_classes/OpenXRInterface.xml | 13 | ||||
-rw-r--r-- | modules/openxr/extensions/openxr_fb_display_refresh_rate_extension.cpp | 123 | ||||
-rw-r--r-- | modules/openxr/extensions/openxr_fb_display_refresh_rate_extension.h | 70 | ||||
-rw-r--r-- | modules/openxr/openxr_api.cpp | 27 | ||||
-rw-r--r-- | modules/openxr/openxr_api.h | 5 | ||||
-rw-r--r-- | modules/openxr/openxr_interface.cpp | 37 | ||||
-rw-r--r-- | modules/openxr/openxr_interface.h | 4 |
8 files changed, 280 insertions, 0 deletions
diff --git a/modules/openxr/SCsub b/modules/openxr/SCsub index 5ac167ad98..b5978ab134 100644 --- a/modules/openxr/SCsub +++ b/modules/openxr/SCsub @@ -96,6 +96,7 @@ env_openxr.add_source_files(module_obj, "extensions/openxr_composition_layer_dep env_openxr.add_source_files(module_obj, "extensions/openxr_htc_vive_tracker_extension.cpp") env_openxr.add_source_files(module_obj, "extensions/openxr_hand_tracking_extension.cpp") env_openxr.add_source_files(module_obj, "extensions/openxr_fb_passthrough_extension_wrapper.cpp") +env_openxr.add_source_files(module_obj, "extensions/openxr_fb_display_refresh_rate_extension.cpp") env.modules_sources += module_obj diff --git a/modules/openxr/doc_classes/OpenXRInterface.xml b/modules/openxr/doc_classes/OpenXRInterface.xml index 25bf496de9..f089fd066e 100644 --- a/modules/openxr/doc_classes/OpenXRInterface.xml +++ b/modules/openxr/doc_classes/OpenXRInterface.xml @@ -10,6 +10,19 @@ <tutorials> <link title="Setting up XR">$DOCS_URL/tutorials/xr/setting_up_xr.html</link> </tutorials> + <methods> + <method name="get_available_display_refresh_rates" qualifiers="const"> + <return type="Array" /> + <description> + Returns display refresh rates supported by the current HMD. Only returned if this feature is supported by the OpenXR runtime and after the interface has been initialized. + </description> + </method> + </methods> + <members> + <member name="display_refresh_rate" type="float" setter="set_display_refresh_rate" getter="get_display_refresh_rate" default="0.0"> + The display refresh rate for the current HMD. Only functional if this feature is supported by the OpenXR runtime and after the interface has been initialized. + </member> + </members> <signals> <signal name="pose_recentered"> <description> diff --git a/modules/openxr/extensions/openxr_fb_display_refresh_rate_extension.cpp b/modules/openxr/extensions/openxr_fb_display_refresh_rate_extension.cpp new file mode 100644 index 0000000000..c0bbaea5b4 --- /dev/null +++ b/modules/openxr/extensions/openxr_fb_display_refresh_rate_extension.cpp @@ -0,0 +1,123 @@ +/*************************************************************************/ +/* openxr_fb_display_refresh_rate_extension.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "openxr_fb_display_refresh_rate_extension.h" + +OpenXRDisplayRefreshRateExtension *OpenXRDisplayRefreshRateExtension::singleton = nullptr; + +OpenXRDisplayRefreshRateExtension *OpenXRDisplayRefreshRateExtension::get_singleton() { + return singleton; +} + +OpenXRDisplayRefreshRateExtension::OpenXRDisplayRefreshRateExtension(OpenXRAPI *p_openxr_api) : + OpenXRExtensionWrapper(p_openxr_api) { + singleton = this; + + // Extensions we use for our hand tracking. + request_extensions[XR_FB_DISPLAY_REFRESH_RATE_EXTENSION_NAME] = &display_refresh_rate_ext; +} + +OpenXRDisplayRefreshRateExtension::~OpenXRDisplayRefreshRateExtension() { + display_refresh_rate_ext = false; +} + +void OpenXRDisplayRefreshRateExtension::on_instance_created(const XrInstance p_instance) { + if (display_refresh_rate_ext) { + EXT_INIT_XR_FUNC(xrEnumerateDisplayRefreshRatesFB); + EXT_INIT_XR_FUNC(xrGetDisplayRefreshRateFB); + EXT_INIT_XR_FUNC(xrRequestDisplayRefreshRateFB); + } +} + +void OpenXRDisplayRefreshRateExtension::on_instance_destroyed() { + display_refresh_rate_ext = false; +} + +float OpenXRDisplayRefreshRateExtension::get_refresh_rate() const { + float refresh_rate = 0.0; + + if (display_refresh_rate_ext) { + float rate; + XrResult result = xrGetDisplayRefreshRateFB(openxr_api->get_session(), &rate); + if (XR_FAILED(result)) { + print_line("OpenXR: Failed to obtain refresh rate [", openxr_api->get_error_string(result), "]"); + } else { + refresh_rate = rate; + } + } + + return refresh_rate; +} + +void OpenXRDisplayRefreshRateExtension::set_refresh_rate(float p_refresh_rate) { + if (display_refresh_rate_ext) { + XrResult result = xrRequestDisplayRefreshRateFB(openxr_api->get_session(), p_refresh_rate); + if (XR_FAILED(result)) { + print_line("OpenXR: Failed to set refresh rate [", openxr_api->get_error_string(result), "]"); + } + } +} + +Array OpenXRDisplayRefreshRateExtension::get_available_refresh_rates() const { + Array arr; + XrResult result; + + if (display_refresh_rate_ext) { + uint32_t display_refresh_rate_count = 0; + result = xrEnumerateDisplayRefreshRatesFB(openxr_api->get_session(), 0, &display_refresh_rate_count, nullptr); + if (XR_FAILED(result)) { + print_line("OpenXR: Failed to obtain refresh rates count [", openxr_api->get_error_string(result), "]"); + } + + if (display_refresh_rate_count > 0) { + float *display_refresh_rates = (float *)memalloc(sizeof(float) * display_refresh_rate_count); + if (display_refresh_rates == nullptr) { + print_line("OpenXR: Failed to obtain refresh rates memory buffer [", openxr_api->get_error_string(result), "]"); + return arr; + } + + result = xrEnumerateDisplayRefreshRatesFB(openxr_api->get_session(), display_refresh_rate_count, &display_refresh_rate_count, display_refresh_rates); + if (XR_FAILED(result)) { + print_line("OpenXR: Failed to obtain refresh rates count [", openxr_api->get_error_string(result), "]"); + memfree(display_refresh_rates); + return arr; + } + + for (uint32_t i = 0; i < display_refresh_rate_count; i++) { + float refresh_rate = display_refresh_rates[i]; + arr.push_back(Variant(refresh_rate)); + } + + memfree(display_refresh_rates); + } + } + + return arr; +} diff --git a/modules/openxr/extensions/openxr_fb_display_refresh_rate_extension.h b/modules/openxr/extensions/openxr_fb_display_refresh_rate_extension.h new file mode 100644 index 0000000000..dcd52fe4d1 --- /dev/null +++ b/modules/openxr/extensions/openxr_fb_display_refresh_rate_extension.h @@ -0,0 +1,70 @@ +/*************************************************************************/ +/* openxr_fb_display_refresh_rate_extension.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef OPENXR_FB_DISPLAY_REFRESH_RATE_EXTENSION_H +#define OPENXR_FB_DISPLAY_REFRESH_RATE_EXTENSION_H + +// This extension gives us access to the possible display refresh rates +// supported by the HMD. +// While this is an FB extension it has been adopted by most runtimes and +// will likely become core in the near future. + +#include "../openxr_api.h" +#include "../util.h" + +#include "openxr_extension_wrapper.h" + +class OpenXRDisplayRefreshRateExtension : public OpenXRExtensionWrapper { +public: + static OpenXRDisplayRefreshRateExtension *get_singleton(); + + OpenXRDisplayRefreshRateExtension(OpenXRAPI *p_openxr_api); + virtual ~OpenXRDisplayRefreshRateExtension() override; + + virtual void on_instance_created(const XrInstance p_instance) override; + virtual void on_instance_destroyed() override; + + float get_refresh_rate() const; + void set_refresh_rate(float p_refresh_rate); + + Array get_available_refresh_rates() const; + +private: + static OpenXRDisplayRefreshRateExtension *singleton; + + bool display_refresh_rate_ext = false; + + // OpenXR API call wrappers + EXT_PROTO_XRRESULT_FUNC4(xrEnumerateDisplayRefreshRatesFB, (XrSession), session, (uint32_t), displayRefreshRateCapacityInput, (uint32_t *), displayRefreshRateCountOutput, (float *), displayRefreshRates); + EXT_PROTO_XRRESULT_FUNC2(xrGetDisplayRefreshRateFB, (XrSession), session, (float *), display_refresh_rate); + EXT_PROTO_XRRESULT_FUNC2(xrRequestDisplayRefreshRateFB, (XrSession), session, (float), display_refresh_rate); +}; + +#endif // OPENXR_FB_DISPLAY_REFRESH_RATE_EXTENSION_H diff --git a/modules/openxr/openxr_api.cpp b/modules/openxr/openxr_api.cpp index 8a67462613..498e947a9d 100644 --- a/modules/openxr/openxr_api.cpp +++ b/modules/openxr/openxr_api.cpp @@ -50,6 +50,7 @@ #endif #include "extensions/openxr_composition_layer_depth_extension.h" +#include "extensions/openxr_fb_display_refresh_rate_extension.h" #include "extensions/openxr_fb_passthrough_extension_wrapper.h" #include "extensions/openxr_hand_tracking_extension.h" #include "extensions/openxr_htc_vive_tracker_extension.h" @@ -1748,6 +1749,31 @@ void OpenXRAPI::end_frame() { } } +float OpenXRAPI::get_display_refresh_rate() const { + OpenXRDisplayRefreshRateExtension *drrext = OpenXRDisplayRefreshRateExtension::get_singleton(); + if (drrext) { + return drrext->get_refresh_rate(); + } + + return 0.0; +} + +void OpenXRAPI::set_display_refresh_rate(float p_refresh_rate) { + OpenXRDisplayRefreshRateExtension *drrext = OpenXRDisplayRefreshRateExtension::get_singleton(); + if (drrext != nullptr) { + drrext->set_refresh_rate(p_refresh_rate); + } +} + +Array OpenXRAPI::get_available_display_refresh_rates() const { + OpenXRDisplayRefreshRateExtension *drrext = OpenXRDisplayRefreshRateExtension::get_singleton(); + if (drrext != nullptr) { + return drrext->get_available_refresh_rates(); + } + + return Array(); +} + OpenXRAPI::OpenXRAPI() { // OpenXRAPI is only constructed if OpenXR is enabled. singleton = this; @@ -1817,6 +1843,7 @@ OpenXRAPI::OpenXRAPI() { register_extension_wrapper(memnew(OpenXRHTCViveTrackerExtension(this))); register_extension_wrapper(memnew(OpenXRHandTrackingExtension(this))); register_extension_wrapper(memnew(OpenXRFbPassthroughExtensionWrapper(this))); + register_extension_wrapper(memnew(OpenXRDisplayRefreshRateExtension(this))); } OpenXRAPI::~OpenXRAPI() { diff --git a/modules/openxr/openxr_api.h b/modules/openxr/openxr_api.h index bd69432dcb..e6781cc112 100644 --- a/modules/openxr/openxr_api.h +++ b/modules/openxr/openxr_api.h @@ -336,6 +336,11 @@ public: void post_draw_viewport(RID p_render_target); void end_frame(); + // Display refresh rate + float get_display_refresh_rate() const; + void set_display_refresh_rate(float p_refresh_rate); + Array get_available_display_refresh_rates() const; + // action map String get_default_action_map_resource_name(); diff --git a/modules/openxr/openxr_interface.cpp b/modules/openxr/openxr_interface.cpp index 68414ae84e..e4c4e3edec 100644 --- a/modules/openxr/openxr_interface.cpp +++ b/modules/openxr/openxr_interface.cpp @@ -41,6 +41,13 @@ void OpenXRInterface::_bind_methods() { ADD_SIGNAL(MethodInfo("session_focussed")); ADD_SIGNAL(MethodInfo("session_visible")); ADD_SIGNAL(MethodInfo("pose_recentered")); + + // Display refresh rate + ClassDB::bind_method(D_METHOD("get_display_refresh_rate"), &OpenXRInterface::get_display_refresh_rate); + ClassDB::bind_method(D_METHOD("set_display_refresh_rate", "refresh_rate"), &OpenXRInterface::set_display_refresh_rate); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "display_refresh_rate"), "set_display_refresh_rate", "get_display_refresh_rate"); + + ClassDB::bind_method(D_METHOD("get_available_display_refresh_rates"), &OpenXRInterface::get_available_display_refresh_rates); } StringName OpenXRInterface::get_name() const { @@ -571,6 +578,36 @@ bool OpenXRInterface::set_play_area_mode(XRInterface::PlayAreaMode p_mode) { return false; } +float OpenXRInterface::get_display_refresh_rate() const { + if (openxr_api == nullptr) { + return 0.0; + } else if (!openxr_api->is_initialized()) { + return 0.0; + } else { + return openxr_api->get_display_refresh_rate(); + } +} + +void OpenXRInterface::set_display_refresh_rate(float p_refresh_rate) { + if (openxr_api == nullptr) { + return; + } else if (!openxr_api->is_initialized()) { + return; + } else { + openxr_api->set_display_refresh_rate(p_refresh_rate); + } +} + +Array OpenXRInterface::get_available_display_refresh_rates() const { + if (openxr_api == nullptr) { + return Array(); + } else if (!openxr_api->is_initialized()) { + return Array(); + } else { + return openxr_api->get_available_display_refresh_rates(); + } +} + Size2 OpenXRInterface::get_render_target_size() { if (openxr_api == nullptr) { return Size2(); diff --git a/modules/openxr/openxr_interface.h b/modules/openxr/openxr_interface.h index 72935b039c..720426f19c 100644 --- a/modules/openxr/openxr_interface.h +++ b/modules/openxr/openxr_interface.h @@ -120,6 +120,10 @@ public: virtual XRInterface::PlayAreaMode get_play_area_mode() const override; virtual bool set_play_area_mode(XRInterface::PlayAreaMode p_mode) override; + float get_display_refresh_rate() const; + void set_display_refresh_rate(float p_refresh_rate); + Array get_available_display_refresh_rates() const; + virtual Size2 get_render_target_size() override; virtual uint32_t get_view_count() override; virtual Transform3D get_camera_transform() override; |