summaryrefslogtreecommitdiffstats
path: root/modules/openxr/extensions
diff options
context:
space:
mode:
Diffstat (limited to 'modules/openxr/extensions')
-rw-r--r--modules/openxr/extensions/openxr_composition_layer_extension.cpp322
-rw-r--r--modules/openxr/extensions/openxr_composition_layer_extension.h116
-rw-r--r--modules/openxr/extensions/openxr_extension_wrapper.h5
-rw-r--r--modules/openxr/extensions/openxr_extension_wrapper_extension.cpp34
-rw-r--r--modules/openxr/extensions/openxr_extension_wrapper_extension.h12
-rw-r--r--modules/openxr/extensions/openxr_fb_display_refresh_rate_extension.cpp18
-rw-r--r--modules/openxr/extensions/openxr_fb_display_refresh_rate_extension.h1
-rw-r--r--modules/openxr/extensions/platform/openxr_vulkan_extension.cpp4
8 files changed, 512 insertions, 0 deletions
diff --git a/modules/openxr/extensions/openxr_composition_layer_extension.cpp b/modules/openxr/extensions/openxr_composition_layer_extension.cpp
new file mode 100644
index 0000000000..1fba8e5f8b
--- /dev/null
+++ b/modules/openxr/extensions/openxr_composition_layer_extension.cpp
@@ -0,0 +1,322 @@
+/**************************************************************************/
+/* openxr_composition_layer_extension.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* 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_composition_layer_extension.h"
+
+#include "servers/rendering/rendering_server_globals.h"
+
+////////////////////////////////////////////////////////////////////////////
+// OpenXRCompositionLayerExtension
+
+OpenXRCompositionLayerExtension *OpenXRCompositionLayerExtension::singleton = nullptr;
+
+OpenXRCompositionLayerExtension *OpenXRCompositionLayerExtension::get_singleton() {
+ return singleton;
+}
+
+OpenXRCompositionLayerExtension::OpenXRCompositionLayerExtension() {
+ singleton = this;
+}
+
+OpenXRCompositionLayerExtension::~OpenXRCompositionLayerExtension() {
+ singleton = nullptr;
+}
+
+HashMap<String, bool *> OpenXRCompositionLayerExtension::get_requested_extensions() {
+ HashMap<String, bool *> request_extensions;
+
+ request_extensions[XR_KHR_COMPOSITION_LAYER_CYLINDER_EXTENSION_NAME] = &cylinder_ext_available;
+ request_extensions[XR_KHR_COMPOSITION_LAYER_EQUIRECT2_EXTENSION_NAME] = &equirect_ext_available;
+
+ return request_extensions;
+}
+
+void OpenXRCompositionLayerExtension::on_session_created(const XrSession p_instance) {
+ OpenXRAPI::get_singleton()->register_composition_layer_provider(this);
+}
+
+void OpenXRCompositionLayerExtension::on_session_destroyed() {
+ OpenXRAPI::get_singleton()->unregister_composition_layer_provider(this);
+}
+
+void OpenXRCompositionLayerExtension::on_pre_render() {
+ for (OpenXRViewportCompositionLayerProvider *composition_layer : composition_layers) {
+ composition_layer->on_pre_render();
+ }
+}
+
+int OpenXRCompositionLayerExtension::get_composition_layer_count() {
+ return composition_layers.size();
+}
+
+XrCompositionLayerBaseHeader *OpenXRCompositionLayerExtension::get_composition_layer(int p_index) {
+ ERR_FAIL_INDEX_V(p_index, composition_layers.size(), nullptr);
+ return composition_layers[p_index]->get_composition_layer();
+}
+
+int OpenXRCompositionLayerExtension::get_composition_layer_order(int p_index) {
+ ERR_FAIL_INDEX_V(p_index, composition_layers.size(), 1);
+ return composition_layers[p_index]->get_sort_order();
+}
+
+void OpenXRCompositionLayerExtension::register_viewport_composition_layer_provider(OpenXRViewportCompositionLayerProvider *p_composition_layer) {
+ composition_layers.push_back(p_composition_layer);
+}
+
+void OpenXRCompositionLayerExtension::unregister_viewport_composition_layer_provider(OpenXRViewportCompositionLayerProvider *p_composition_layer) {
+ composition_layers.erase(p_composition_layer);
+}
+
+bool OpenXRCompositionLayerExtension::is_available(XrStructureType p_which) {
+ switch (p_which) {
+ case XR_TYPE_COMPOSITION_LAYER_QUAD: {
+ // Doesn't require an extension.
+ return true;
+ } break;
+ case XR_TYPE_COMPOSITION_LAYER_CYLINDER_KHR: {
+ return cylinder_ext_available;
+ } break;
+ case XR_TYPE_COMPOSITION_LAYER_EQUIRECT2_KHR: {
+ return equirect_ext_available;
+ } break;
+ default: {
+ ERR_PRINT(vformat("Unsupported composition layer type: %s", p_which));
+ return false;
+ }
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////
+// OpenXRViewportCompositionLayerProvider
+
+OpenXRViewportCompositionLayerProvider::OpenXRViewportCompositionLayerProvider(XrCompositionLayerBaseHeader *p_composition_layer) {
+ composition_layer = p_composition_layer;
+ openxr_api = OpenXRAPI::get_singleton();
+ composition_layer_extension = OpenXRCompositionLayerExtension::get_singleton();
+}
+
+OpenXRViewportCompositionLayerProvider::~OpenXRViewportCompositionLayerProvider() {
+ for (OpenXRExtensionWrapper *extension : OpenXRAPI::get_registered_extension_wrappers()) {
+ extension->on_viewport_composition_layer_destroyed(composition_layer);
+ }
+
+ // This will reset the viewport and free the swapchain too.
+ set_viewport(RID(), Size2i());
+}
+
+void OpenXRViewportCompositionLayerProvider::set_alpha_blend(bool p_alpha_blend) {
+ if (alpha_blend != p_alpha_blend) {
+ alpha_blend = p_alpha_blend;
+ if (alpha_blend) {
+ composition_layer->layerFlags |= XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BIT;
+ } else {
+ composition_layer->layerFlags &= ~XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BIT;
+ }
+ }
+}
+
+void OpenXRViewportCompositionLayerProvider::set_viewport(RID p_viewport, Size2i p_size) {
+ RenderingServer *rs = RenderingServer::get_singleton();
+ ERR_FAIL_NULL(rs);
+
+ if (viewport != p_viewport) {
+ if (viewport.is_valid()) {
+ RID rt = rs->viewport_get_render_target(viewport);
+ RSG::texture_storage->render_target_set_override(rt, RID(), RID(), RID());
+ }
+
+ viewport = p_viewport;
+
+ if (viewport.is_valid()) {
+ viewport_size = p_size;
+ } else {
+ free_swapchain();
+ viewport_size = Size2i();
+ }
+ }
+}
+
+void OpenXRViewportCompositionLayerProvider::set_extension_property_values(const Dictionary &p_extension_property_values) {
+ extension_property_values = p_extension_property_values;
+ extension_property_values_changed = true;
+}
+
+void OpenXRViewportCompositionLayerProvider::on_pre_render() {
+ RenderingServer *rs = RenderingServer::get_singleton();
+ ERR_FAIL_NULL(rs);
+
+ if (viewport.is_valid() && openxr_api && openxr_api->is_running()) {
+ RS::ViewportUpdateMode update_mode = rs->viewport_get_update_mode(viewport);
+ if (update_mode == RS::VIEWPORT_UPDATE_ONCE || update_mode == RS::VIEWPORT_UPDATE_ALWAYS) {
+ // Update our XR swapchain
+ if (update_and_acquire_swapchain(update_mode == RS::VIEWPORT_UPDATE_ONCE)) {
+ // Render to our XR swapchain image.
+ RID rt = rs->viewport_get_render_target(viewport);
+ RSG::texture_storage->render_target_set_override(rt, get_current_swapchain_texture(), RID(), RID());
+ }
+ }
+ }
+}
+
+XrCompositionLayerBaseHeader *OpenXRViewportCompositionLayerProvider::get_composition_layer() {
+ if (openxr_api == nullptr || composition_layer_extension == nullptr) {
+ // OpenXR not initialised or we're in the editor?
+ return nullptr;
+ }
+
+ if (!composition_layer_extension->is_available(composition_layer->type)) {
+ // Selected type is not supported, ignore our layer.
+ return nullptr;
+ }
+
+ if (swapchain_info.get_swapchain() == XR_NULL_HANDLE) {
+ // Don't have a swapchain to display? Ignore our layer.
+ return nullptr;
+ }
+
+ if (swapchain_info.is_image_acquired()) {
+ swapchain_info.release();
+ }
+
+ // Update the layer struct for the swapchain.
+ switch (composition_layer->type) {
+ case XR_TYPE_COMPOSITION_LAYER_QUAD: {
+ XrCompositionLayerQuad *quad_layer = (XrCompositionLayerQuad *)composition_layer;
+ quad_layer->subImage.swapchain = swapchain_info.get_swapchain();
+ quad_layer->subImage.imageArrayIndex = 0;
+ quad_layer->subImage.imageRect.offset.x = 0;
+ quad_layer->subImage.imageRect.offset.y = 0;
+ quad_layer->subImage.imageRect.extent.width = swapchain_size.width;
+ quad_layer->subImage.imageRect.extent.height = swapchain_size.height;
+ } break;
+
+ case XR_TYPE_COMPOSITION_LAYER_CYLINDER_KHR: {
+ XrCompositionLayerCylinderKHR *cylinder_layer = (XrCompositionLayerCylinderKHR *)composition_layer;
+ cylinder_layer->subImage.swapchain = swapchain_info.get_swapchain();
+ cylinder_layer->subImage.imageArrayIndex = 0;
+ cylinder_layer->subImage.imageRect.offset.x = 0;
+ cylinder_layer->subImage.imageRect.offset.y = 0;
+ cylinder_layer->subImage.imageRect.extent.width = swapchain_size.width;
+ cylinder_layer->subImage.imageRect.extent.height = swapchain_size.height;
+ } break;
+
+ case XR_TYPE_COMPOSITION_LAYER_EQUIRECT2_KHR: {
+ XrCompositionLayerEquirect2KHR *equirect_layer = (XrCompositionLayerEquirect2KHR *)composition_layer;
+ equirect_layer->subImage.swapchain = swapchain_info.get_swapchain();
+ equirect_layer->subImage.imageArrayIndex = 0;
+ equirect_layer->subImage.imageRect.offset.x = 0;
+ equirect_layer->subImage.imageRect.offset.y = 0;
+ equirect_layer->subImage.imageRect.extent.width = swapchain_size.width;
+ equirect_layer->subImage.imageRect.extent.height = swapchain_size.height;
+ } break;
+
+ default: {
+ return nullptr;
+ } break;
+ }
+
+ if (extension_property_values_changed) {
+ extension_property_values_changed = false;
+
+ void *next_pointer = nullptr;
+ for (OpenXRExtensionWrapper *extension : OpenXRAPI::get_registered_extension_wrappers()) {
+ void *np = extension->set_viewport_composition_layer_and_get_next_pointer(composition_layer, extension_property_values, next_pointer);
+ if (np) {
+ next_pointer = np;
+ }
+ }
+ composition_layer->next = next_pointer;
+ }
+
+ return composition_layer;
+}
+
+bool OpenXRViewportCompositionLayerProvider::update_and_acquire_swapchain(bool p_static_image) {
+ if (openxr_api == nullptr || composition_layer_extension == nullptr) {
+ // OpenXR not initialised or we're in the editor?
+ return false;
+ }
+ if (!composition_layer_extension->is_available(composition_layer->type)) {
+ // Selected type is not supported?
+ return false;
+ }
+
+ // See if our current swapchain is outdated.
+ if (swapchain_info.get_swapchain() != XR_NULL_HANDLE) {
+ // If this swap chain, or the previous one, were static, then we can't reuse it.
+ if (swapchain_size == viewport_size && !p_static_image && !static_image) {
+ // We're all good! Just acquire it.
+ // We can ignore should_render here, return will be false.
+ XrBool32 should_render = true;
+ return swapchain_info.acquire(should_render);
+ }
+
+ swapchain_info.queue_free();
+ }
+
+ // Create our new swap chain
+ int64_t swapchain_format = openxr_api->get_color_swapchain_format();
+ const uint32_t sample_count = 3;
+ const uint32_t array_size = 1;
+ XrSwapchainCreateFlags create_flags = 0;
+ if (p_static_image) {
+ create_flags |= XR_SWAPCHAIN_CREATE_STATIC_IMAGE_BIT;
+ }
+ if (!swapchain_info.create(create_flags, XR_SWAPCHAIN_USAGE_SAMPLED_BIT | XR_SWAPCHAIN_USAGE_COLOR_ATTACHMENT_BIT | XR_SWAPCHAIN_USAGE_MUTABLE_FORMAT_BIT, swapchain_format, viewport_size.width, viewport_size.height, sample_count, array_size)) {
+ swapchain_size = Size2i();
+ return false;
+ }
+
+ // Acquire our image so we can start rendering into it,
+ // we can ignore should_render here, ret will be false.
+ XrBool32 should_render = true;
+ bool ret = swapchain_info.acquire(should_render);
+
+ swapchain_size = viewport_size;
+ static_image = p_static_image;
+ return ret;
+}
+
+void OpenXRViewportCompositionLayerProvider::free_swapchain() {
+ if (swapchain_info.get_swapchain() != XR_NULL_HANDLE) {
+ swapchain_info.queue_free();
+ }
+
+ swapchain_size = Size2i();
+ static_image = false;
+}
+
+RID OpenXRViewportCompositionLayerProvider::get_current_swapchain_texture() {
+ if (openxr_api == nullptr) {
+ return RID();
+ }
+
+ return swapchain_info.get_image();
+}
diff --git a/modules/openxr/extensions/openxr_composition_layer_extension.h b/modules/openxr/extensions/openxr_composition_layer_extension.h
new file mode 100644
index 0000000000..4fefc416e6
--- /dev/null
+++ b/modules/openxr/extensions/openxr_composition_layer_extension.h
@@ -0,0 +1,116 @@
+/**************************************************************************/
+/* openxr_composition_layer_extension.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* 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_COMPOSITION_LAYER_EXTENSION_H
+#define OPENXR_COMPOSITION_LAYER_EXTENSION_H
+
+#include "openxr_composition_layer_provider.h"
+#include "openxr_extension_wrapper.h"
+
+#include "../openxr_api.h"
+
+class OpenXRViewportCompositionLayerProvider;
+
+// This extension provides access to composition layers for displaying 2D content through the XR compositor.
+
+// OpenXRCompositionLayerExtension enables the extensions related to this functionality
+class OpenXRCompositionLayerExtension : public OpenXRExtensionWrapper, public OpenXRCompositionLayerProvider {
+public:
+ static OpenXRCompositionLayerExtension *get_singleton();
+
+ OpenXRCompositionLayerExtension();
+ virtual ~OpenXRCompositionLayerExtension() override;
+
+ virtual HashMap<String, bool *> get_requested_extensions() override;
+ virtual void on_session_created(const XrSession p_instance) override;
+ virtual void on_session_destroyed() override;
+ virtual void on_pre_render() override;
+
+ virtual int get_composition_layer_count() override;
+ virtual XrCompositionLayerBaseHeader *get_composition_layer(int p_index) override;
+ virtual int get_composition_layer_order(int p_index) override;
+
+ void register_viewport_composition_layer_provider(OpenXRViewportCompositionLayerProvider *p_composition_layer);
+ void unregister_viewport_composition_layer_provider(OpenXRViewportCompositionLayerProvider *p_composition_layer);
+
+ bool is_available(XrStructureType p_which);
+
+private:
+ static OpenXRCompositionLayerExtension *singleton;
+
+ Vector<OpenXRViewportCompositionLayerProvider *> composition_layers;
+
+ bool cylinder_ext_available = false;
+ bool equirect_ext_available = false;
+};
+
+class OpenXRViewportCompositionLayerProvider {
+ XrCompositionLayerBaseHeader *composition_layer = nullptr;
+ int sort_order = 1;
+ bool alpha_blend = false;
+ Dictionary extension_property_values;
+ bool extension_property_values_changed = true;
+
+ RID viewport;
+ Size2i viewport_size;
+
+ OpenXRAPI::OpenXRSwapChainInfo swapchain_info;
+ Size2i swapchain_size;
+ bool static_image = false;
+
+ OpenXRAPI *openxr_api = nullptr;
+ OpenXRCompositionLayerExtension *composition_layer_extension = nullptr;
+
+ bool update_and_acquire_swapchain(bool p_static_image);
+ void free_swapchain();
+ RID get_current_swapchain_texture();
+
+public:
+ XrStructureType get_openxr_type() { return composition_layer->type; }
+
+ void set_sort_order(int p_sort_order) { sort_order = p_sort_order; }
+ int get_sort_order() const { return sort_order; }
+
+ void set_alpha_blend(bool p_alpha_blend);
+ bool get_alpha_blend() const { return alpha_blend; }
+
+ void set_viewport(RID p_viewport, Size2i p_size);
+ RID get_viewport() const { return viewport; }
+
+ void set_extension_property_values(const Dictionary &p_property_values);
+
+ void on_pre_render();
+ XrCompositionLayerBaseHeader *get_composition_layer();
+
+ OpenXRViewportCompositionLayerProvider(XrCompositionLayerBaseHeader *p_composition_layer);
+ ~OpenXRViewportCompositionLayerProvider();
+};
+
+#endif // OPENXR_COMPOSITION_LAYER_EXTENSION_H
diff --git a/modules/openxr/extensions/openxr_extension_wrapper.h b/modules/openxr/extensions/openxr_extension_wrapper.h
index ad326472ab..ce03df0b30 100644
--- a/modules/openxr/extensions/openxr_extension_wrapper.h
+++ b/modules/openxr/extensions/openxr_extension_wrapper.h
@@ -96,6 +96,11 @@ public:
virtual void on_state_loss_pending() {} // `on_state_loss_pending` is called when the OpenXR session state is changed to loss pending.
virtual void on_state_exiting() {} // `on_state_exiting` is called when the OpenXR session state is changed to exiting.
+ virtual void *set_viewport_composition_layer_and_get_next_pointer(const XrCompositionLayerBaseHeader *p_layer, Dictionary p_property_values, void *p_next_pointer) { return p_next_pointer; } // Add additional data structures to composition layers created via OpenXRCompositionLayer.
+ virtual void on_viewport_composition_layer_destroyed(const XrCompositionLayerBaseHeader *p_layer) {} // `on_viewport_composition_layer_destroyed` is called when a composition layer created via OpenXRCompositionLayer is destroyed.
+ virtual void get_viewport_composition_layer_extension_properties(List<PropertyInfo> *p_property_list) {} // Get additional property definitions for OpenXRCompositionLayer.
+ virtual Dictionary get_viewport_composition_layer_extension_property_defaults() { return Dictionary(); } // Get the default values for the additional property definitions for OpenXRCompositionLayer.
+
// `on_event_polled` is called when there is an OpenXR event to process.
// Should return true if the event was handled, false otherwise.
virtual bool on_event_polled(const XrEventDataBuffer &event) {
diff --git a/modules/openxr/extensions/openxr_extension_wrapper_extension.cpp b/modules/openxr/extensions/openxr_extension_wrapper_extension.cpp
index 60a934e3a8..3b31e1b1f6 100644
--- a/modules/openxr/extensions/openxr_extension_wrapper_extension.cpp
+++ b/modules/openxr/extensions/openxr_extension_wrapper_extension.cpp
@@ -60,6 +60,10 @@ void OpenXRExtensionWrapperExtension::_bind_methods() {
GDVIRTUAL_BIND(_on_state_loss_pending);
GDVIRTUAL_BIND(_on_state_exiting);
GDVIRTUAL_BIND(_on_event_polled, "event");
+ GDVIRTUAL_BIND(_set_viewport_composition_layer_and_get_next_pointer, "layer", "property_values", "next_pointer");
+ GDVIRTUAL_BIND(_get_viewport_composition_layer_extension_properties);
+ GDVIRTUAL_BIND(_get_viewport_composition_layer_extension_property_defaults);
+ GDVIRTUAL_BIND(_on_viewport_composition_layer_destroyed, "layer");
ClassDB::bind_method(D_METHOD("get_openxr_api"), &OpenXRExtensionWrapperExtension::get_openxr_api);
ClassDB::bind_method(D_METHOD("register_extension_wrapper"), &OpenXRExtensionWrapperExtension::register_extension_wrapper);
@@ -240,6 +244,36 @@ bool OpenXRExtensionWrapperExtension::on_event_polled(const XrEventDataBuffer &p
return false;
}
+void *OpenXRExtensionWrapperExtension::set_viewport_composition_layer_and_get_next_pointer(const XrCompositionLayerBaseHeader *p_layer, Dictionary p_property_values, void *p_next_pointer) {
+ uint64_t pointer = 0;
+
+ if (GDVIRTUAL_CALL(_set_viewport_composition_layer_and_get_next_pointer, GDExtensionConstPtr<void>(p_layer), p_property_values, GDExtensionPtr<void>(p_next_pointer), pointer)) {
+ return reinterpret_cast<void *>(pointer);
+ }
+
+ return p_next_pointer;
+}
+
+void OpenXRExtensionWrapperExtension::on_viewport_composition_layer_destroyed(const XrCompositionLayerBaseHeader *p_layer) {
+ GDVIRTUAL_CALL(_on_viewport_composition_layer_destroyed, GDExtensionConstPtr<void>(p_layer));
+}
+
+void OpenXRExtensionWrapperExtension::get_viewport_composition_layer_extension_properties(List<PropertyInfo> *p_property_list) {
+ TypedArray<Dictionary> properties;
+
+ if (GDVIRTUAL_CALL(_get_viewport_composition_layer_extension_properties, properties)) {
+ for (int i = 0; i < properties.size(); i++) {
+ p_property_list->push_back(PropertyInfo::from_dict(properties[i]));
+ }
+ }
+}
+
+Dictionary OpenXRExtensionWrapperExtension::get_viewport_composition_layer_extension_property_defaults() {
+ Dictionary property_defaults;
+ GDVIRTUAL_CALL(_get_viewport_composition_layer_extension_property_defaults, property_defaults);
+ return property_defaults;
+}
+
Ref<OpenXRAPIExtension> OpenXRExtensionWrapperExtension::get_openxr_api() {
return openxr_api;
}
diff --git a/modules/openxr/extensions/openxr_extension_wrapper_extension.h b/modules/openxr/extensions/openxr_extension_wrapper_extension.h
index d3b78bf617..71d2a57ff8 100644
--- a/modules/openxr/extensions/openxr_extension_wrapper_extension.h
+++ b/modules/openxr/extensions/openxr_extension_wrapper_extension.h
@@ -38,6 +38,7 @@
#include "core/os/os.h"
#include "core/os/thread_safe.h"
#include "core/variant/native_ptr.h"
+#include "core/variant/typed_array.h"
class OpenXRExtensionWrapperExtension : public Object, public OpenXRExtensionWrapper, public OpenXRCompositionLayerProvider {
GDCLASS(OpenXRExtensionWrapperExtension, Object);
@@ -59,6 +60,7 @@ public:
virtual void *set_session_create_and_get_next_pointer(void *p_next_pointer) override;
virtual void *set_swapchain_create_info_and_get_next_pointer(void *p_next_pointer) override;
virtual void *set_hand_joint_locations_and_get_next_pointer(int p_hand_index, void *p_next_pointer) override;
+
virtual int get_composition_layer_count() override;
virtual XrCompositionLayerBaseHeader *get_composition_layer(int p_index) override;
virtual int get_composition_layer_order(int p_index) override;
@@ -117,6 +119,16 @@ public:
GDVIRTUAL1R(bool, _on_event_polled, GDExtensionConstPtr<void>);
+ virtual void *set_viewport_composition_layer_and_get_next_pointer(const XrCompositionLayerBaseHeader *p_layer, Dictionary p_property_values, void *p_next_pointer) override;
+ virtual void on_viewport_composition_layer_destroyed(const XrCompositionLayerBaseHeader *p_layer) override;
+ virtual void get_viewport_composition_layer_extension_properties(List<PropertyInfo> *p_property_list) override;
+ virtual Dictionary get_viewport_composition_layer_extension_property_defaults() override;
+
+ GDVIRTUAL3R(uint64_t, _set_viewport_composition_layer_and_get_next_pointer, GDExtensionConstPtr<void>, Dictionary, GDExtensionPtr<void>);
+ GDVIRTUAL1(_on_viewport_composition_layer_destroyed, GDExtensionConstPtr<void>);
+ GDVIRTUAL0R(TypedArray<Dictionary>, _get_viewport_composition_layer_extension_properties);
+ GDVIRTUAL0R(Dictionary, _get_viewport_composition_layer_extension_property_defaults);
+
Ref<OpenXRAPIExtension> get_openxr_api();
void register_extension_wrapper();
diff --git a/modules/openxr/extensions/openxr_fb_display_refresh_rate_extension.cpp b/modules/openxr/extensions/openxr_fb_display_refresh_rate_extension.cpp
index 0ef7070531..402389144a 100644
--- a/modules/openxr/extensions/openxr_fb_display_refresh_rate_extension.cpp
+++ b/modules/openxr/extensions/openxr_fb_display_refresh_rate_extension.cpp
@@ -29,6 +29,7 @@
/**************************************************************************/
#include "openxr_fb_display_refresh_rate_extension.h"
+#include "../openxr_interface.h"
OpenXRDisplayRefreshRateExtension *OpenXRDisplayRefreshRateExtension::singleton = nullptr;
@@ -64,6 +65,23 @@ void OpenXRDisplayRefreshRateExtension::on_instance_destroyed() {
display_refresh_rate_ext = false;
}
+bool OpenXRDisplayRefreshRateExtension::on_event_polled(const XrEventDataBuffer &event) {
+ switch (event.type) {
+ case XR_TYPE_EVENT_DATA_DISPLAY_REFRESH_RATE_CHANGED_FB: {
+ const XrEventDataDisplayRefreshRateChangedFB *event_fb = (XrEventDataDisplayRefreshRateChangedFB *)&event;
+
+ OpenXRInterface *xr_interface = OpenXRAPI::get_singleton()->get_xr_interface();
+ if (xr_interface) {
+ xr_interface->on_refresh_rate_changes(event_fb->toDisplayRefreshRate);
+ }
+
+ return true;
+ } break;
+ default:
+ return false;
+ }
+}
+
float OpenXRDisplayRefreshRateExtension::get_refresh_rate() const {
float refresh_rate = 0.0;
diff --git a/modules/openxr/extensions/openxr_fb_display_refresh_rate_extension.h b/modules/openxr/extensions/openxr_fb_display_refresh_rate_extension.h
index d8015fe600..1048d245a4 100644
--- a/modules/openxr/extensions/openxr_fb_display_refresh_rate_extension.h
+++ b/modules/openxr/extensions/openxr_fb_display_refresh_rate_extension.h
@@ -51,6 +51,7 @@ public:
virtual void on_instance_created(const XrInstance p_instance) override;
virtual void on_instance_destroyed() override;
+ virtual bool on_event_polled(const XrEventDataBuffer &event) override;
float get_refresh_rate() const;
void set_refresh_rate(float p_refresh_rate);
diff --git a/modules/openxr/extensions/platform/openxr_vulkan_extension.cpp b/modules/openxr/extensions/platform/openxr_vulkan_extension.cpp
index f5e7fc192c..da613f8435 100644
--- a/modules/openxr/extensions/platform/openxr_vulkan_extension.cpp
+++ b/modules/openxr/extensions/platform/openxr_vulkan_extension.cpp
@@ -229,6 +229,10 @@ void OpenXRVulkanExtension::get_usable_swapchain_formats(Vector<int64_t> &p_usab
}
void OpenXRVulkanExtension::get_usable_depth_formats(Vector<int64_t> &p_usable_swap_chains) {
+ // Note, it is very likely we do NOT support any of depth formats where we can combine our stencil support (e.g. _S8_UINT).
+ // Right now this isn't a problem but once stencil support becomes an issue, we need to check for this in the rendering engine
+ // and create a separate buffer for the stencil.
+
p_usable_swap_chains.push_back(VK_FORMAT_D24_UNORM_S8_UINT);
p_usable_swap_chains.push_back(VK_FORMAT_D32_SFLOAT_S8_UINT);
p_usable_swap_chains.push_back(VK_FORMAT_D32_SFLOAT);