summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRémi Verschelde <rverschelde@gmail.com>2024-03-14 22:35:08 +0100
committerRémi Verschelde <rverschelde@gmail.com>2024-03-14 22:35:08 +0100
commit36b33d9b7263ddd61502e6ca92e1ac2b3f665f46 (patch)
tree41c0ef5aa0011d4d84a24e9ea89a3d3171f49768
parent3d3de019bb7f7f8b4d4cd14e1aee84a95426cb75 (diff)
parent308a6a4734f38f79ac505e41e6f61c51df111748 (diff)
downloadredot-engine-36b33d9b7263ddd61502e6ca92e1ac2b3f665f46.tar.gz
Merge pull request #89460 from dsnopek/openxr-composition-layers-multiple
OpenXR: Allow GDExtensions to provide multiple, ordered composition layers
-rw-r--r--modules/openxr/doc_classes/OpenXRExtensionWrapperExtension.xml19
-rw-r--r--modules/openxr/extensions/openxr_composition_layer_depth_extension.cpp11
-rw-r--r--modules/openxr/extensions/openxr_composition_layer_depth_extension.h4
-rw-r--r--modules/openxr/extensions/openxr_composition_layer_provider.h4
-rw-r--r--modules/openxr/extensions/openxr_extension_wrapper_extension.cpp20
-rw-r--r--modules/openxr/extensions/openxr_extension_wrapper_extension.h8
-rw-r--r--modules/openxr/openxr_api.cpp32
-rw-r--r--modules/openxr/openxr_api.h9
8 files changed, 91 insertions, 16 deletions
diff --git a/modules/openxr/doc_classes/OpenXRExtensionWrapperExtension.xml b/modules/openxr/doc_classes/OpenXRExtensionWrapperExtension.xml
index 20ce1c42bf..9d6b197ee1 100644
--- a/modules/openxr/doc_classes/OpenXRExtensionWrapperExtension.xml
+++ b/modules/openxr/doc_classes/OpenXRExtensionWrapperExtension.xml
@@ -11,8 +11,25 @@
<methods>
<method name="_get_composition_layer" qualifiers="virtual">
<return type="int" />
+ <param index="0" name="index" type="int" />
<description>
- Returns a pointer to an [code]XrCompositionLayerBaseHeader[/code] struct to provide a composition layer. This will only be called if the extension previously registered itself with [method OpenXRAPIExtension.register_composition_layer_provider].
+ Returns a pointer to an [code]XrCompositionLayerBaseHeader[/code] struct to provide the given composition layer.
+ This will only be called if the extension previously registered itself with [method OpenXRAPIExtension.register_composition_layer_provider].
+ </description>
+ </method>
+ <method name="_get_composition_layer_count" qualifiers="virtual">
+ <return type="int" />
+ <description>
+ Returns the number of composition layers this extension wrapper provides via [method _get_composition_layer].
+ This will only be called if the extension previously registered itself with [method OpenXRAPIExtension.register_composition_layer_provider].
+ </description>
+ </method>
+ <method name="_get_composition_layer_order" qualifiers="virtual">
+ <return type="int" />
+ <param index="0" name="index" type="int" />
+ <description>
+ Returns an integer that will be used to sort the given composition layer provided via [method _get_composition_layer]. Lower numbers will move the layer to the front of the list, and higher numbers to the end. The default projection layer has an order of [code]0[/code], so layers provided by this method should probably be above or below (but not exactly) [code]0[/code].
+ This will only be called if the extension previously registered itself with [method OpenXRAPIExtension.register_composition_layer_provider].
</description>
</method>
<method name="_get_requested_extensions" qualifiers="virtual">
diff --git a/modules/openxr/extensions/openxr_composition_layer_depth_extension.cpp b/modules/openxr/extensions/openxr_composition_layer_depth_extension.cpp
index 7a16da144e..b3c94d44f0 100644
--- a/modules/openxr/extensions/openxr_composition_layer_depth_extension.cpp
+++ b/modules/openxr/extensions/openxr_composition_layer_depth_extension.cpp
@@ -56,8 +56,15 @@ bool OpenXRCompositionLayerDepthExtension::is_available() {
return available;
}
-XrCompositionLayerBaseHeader *OpenXRCompositionLayerDepthExtension::get_composition_layer() {
- // Seems this is all done in our base layer... Just in case this changes...
+int OpenXRCompositionLayerDepthExtension::get_composition_layer_count() {
+ return 0;
+}
+XrCompositionLayerBaseHeader *OpenXRCompositionLayerDepthExtension::get_composition_layer(int p_index) {
+ // Seems this is all done in our base layer... Just in case this changes...
return nullptr;
}
+
+int OpenXRCompositionLayerDepthExtension::get_composition_layer_order(int p_index) {
+ return 0;
+}
diff --git a/modules/openxr/extensions/openxr_composition_layer_depth_extension.h b/modules/openxr/extensions/openxr_composition_layer_depth_extension.h
index 50bbef4db4..1fda8844af 100644
--- a/modules/openxr/extensions/openxr_composition_layer_depth_extension.h
+++ b/modules/openxr/extensions/openxr_composition_layer_depth_extension.h
@@ -43,7 +43,9 @@ public:
virtual HashMap<String, bool *> get_requested_extensions() override;
bool is_available();
- virtual XrCompositionLayerBaseHeader *get_composition_layer() 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;
private:
static OpenXRCompositionLayerDepthExtension *singleton;
diff --git a/modules/openxr/extensions/openxr_composition_layer_provider.h b/modules/openxr/extensions/openxr_composition_layer_provider.h
index d77ae06174..44f90a0e0e 100644
--- a/modules/openxr/extensions/openxr_composition_layer_provider.h
+++ b/modules/openxr/extensions/openxr_composition_layer_provider.h
@@ -38,7 +38,9 @@
// Interface for OpenXR extensions that provide a composition layer.
class OpenXRCompositionLayerProvider {
public:
- virtual XrCompositionLayerBaseHeader *get_composition_layer() = 0;
+ virtual int get_composition_layer_count() = 0;
+ virtual XrCompositionLayerBaseHeader *get_composition_layer(int p_index) = 0;
+ virtual int get_composition_layer_order(int p_index) = 0;
virtual ~OpenXRCompositionLayerProvider() {}
};
diff --git a/modules/openxr/extensions/openxr_extension_wrapper_extension.cpp b/modules/openxr/extensions/openxr_extension_wrapper_extension.cpp
index a9b62819b7..60a934e3a8 100644
--- a/modules/openxr/extensions/openxr_extension_wrapper_extension.cpp
+++ b/modules/openxr/extensions/openxr_extension_wrapper_extension.cpp
@@ -39,7 +39,9 @@ void OpenXRExtensionWrapperExtension::_bind_methods() {
GDVIRTUAL_BIND(_set_session_create_and_get_next_pointer, "next_pointer");
GDVIRTUAL_BIND(_set_swapchain_create_info_and_get_next_pointer, "next_pointer");
GDVIRTUAL_BIND(_set_hand_joint_locations_and_get_next_pointer, "hand_index", "next_pointer");
- GDVIRTUAL_BIND(_get_composition_layer);
+ GDVIRTUAL_BIND(_get_composition_layer_count);
+ GDVIRTUAL_BIND(_get_composition_layer, "index");
+ GDVIRTUAL_BIND(_get_composition_layer_order, "index");
GDVIRTUAL_BIND(_get_suggested_tracker_names);
GDVIRTUAL_BIND(_on_register_metadata);
GDVIRTUAL_BIND(_on_before_instance_created);
@@ -140,16 +142,28 @@ PackedStringArray OpenXRExtensionWrapperExtension::get_suggested_tracker_names()
return PackedStringArray();
}
-XrCompositionLayerBaseHeader *OpenXRExtensionWrapperExtension::get_composition_layer() {
+int OpenXRExtensionWrapperExtension::get_composition_layer_count() {
+ int count = 0;
+ GDVIRTUAL_CALL(_get_composition_layer_count, count);
+ return count;
+}
+
+XrCompositionLayerBaseHeader *OpenXRExtensionWrapperExtension::get_composition_layer(int p_index) {
uint64_t pointer;
- if (GDVIRTUAL_CALL(_get_composition_layer, pointer)) {
+ if (GDVIRTUAL_CALL(_get_composition_layer, p_index, pointer)) {
return reinterpret_cast<XrCompositionLayerBaseHeader *>(pointer);
}
return nullptr;
}
+int OpenXRExtensionWrapperExtension::get_composition_layer_order(int p_index) {
+ int order = 0;
+ GDVIRTUAL_CALL(_get_composition_layer_order, p_index, order);
+ return order;
+}
+
void OpenXRExtensionWrapperExtension::on_register_metadata() {
GDVIRTUAL_CALL(_on_register_metadata);
}
diff --git a/modules/openxr/extensions/openxr_extension_wrapper_extension.h b/modules/openxr/extensions/openxr_extension_wrapper_extension.h
index edcbc0139b..d3b78bf617 100644
--- a/modules/openxr/extensions/openxr_extension_wrapper_extension.h
+++ b/modules/openxr/extensions/openxr_extension_wrapper_extension.h
@@ -59,7 +59,9 @@ 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 XrCompositionLayerBaseHeader *get_composition_layer() 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;
//TODO workaround as GDExtensionPtr<void> return type results in build error in godot-cpp
GDVIRTUAL1R(uint64_t, _set_system_properties_and_get_next_pointer, GDExtensionPtr<void>);
@@ -67,7 +69,9 @@ public:
GDVIRTUAL1R(uint64_t, _set_session_create_and_get_next_pointer, GDExtensionPtr<void>);
GDVIRTUAL1R(uint64_t, _set_swapchain_create_info_and_get_next_pointer, GDExtensionPtr<void>);
GDVIRTUAL2R(uint64_t, _set_hand_joint_locations_and_get_next_pointer, int, GDExtensionPtr<void>);
- GDVIRTUAL0R(uint64_t, _get_composition_layer);
+ GDVIRTUAL0R(int, _get_composition_layer_count);
+ GDVIRTUAL1R(uint64_t, _get_composition_layer, int);
+ GDVIRTUAL1R(int, _get_composition_layer_order, int);
virtual PackedStringArray get_suggested_tracker_names() override;
diff --git a/modules/openxr/openxr_api.cpp b/modules/openxr/openxr_api.cpp
index e978c012b5..8dd017c213 100644
--- a/modules/openxr/openxr_api.cpp
+++ b/modules/openxr/openxr_api.cpp
@@ -2080,18 +2080,29 @@ void OpenXRAPI::end_frame() {
projection_views[eye].pose = views[eye].pose;
}
- Vector<const XrCompositionLayerBaseHeader *> layers_list;
+ Vector<OrderedCompositionLayer> ordered_layers_list;
+ bool projection_layer_is_first = true;
// Add composition layers from providers
for (OpenXRCompositionLayerProvider *provider : composition_layer_providers) {
- XrCompositionLayerBaseHeader *layer = provider->get_composition_layer();
- if (layer) {
- layers_list.push_back(layer);
+ for (int i = 0; i < provider->get_composition_layer_count(); i++) {
+ OrderedCompositionLayer layer = {
+ provider->get_composition_layer(i),
+ provider->get_composition_layer_order(i),
+ };
+ if (layer.composition_layer) {
+ ordered_layers_list.push_back(layer);
+ if (layer.sort_order == 0) {
+ WARN_PRINT_ONCE_ED("Composition layer returned sort order 0, it may be overwritten by projection layer.");
+ } else if (layer.sort_order < 0) {
+ projection_layer_is_first = false;
+ }
+ }
}
}
XrCompositionLayerFlags layer_flags = XR_COMPOSITION_LAYER_CORRECT_CHROMATIC_ABERRATION_BIT;
- if (layers_list.size() > 0 || environment_blend_mode != XR_ENVIRONMENT_BLEND_MODE_OPAQUE) {
+ if (!projection_layer_is_first || environment_blend_mode != XR_ENVIRONMENT_BLEND_MODE_OPAQUE) {
layer_flags |= XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BIT;
}
@@ -2103,7 +2114,16 @@ void OpenXRAPI::end_frame() {
view_count, // viewCount
projection_views, // views
};
- layers_list.push_back((const XrCompositionLayerBaseHeader *)&projection_layer);
+ ordered_layers_list.push_back({ (const XrCompositionLayerBaseHeader *)&projection_layer, 0 });
+
+ // Sort our layers.
+ ordered_layers_list.sort_custom<OrderedCompositionLayer>();
+
+ // Now make a list we can pass on to OpenXR.
+ Vector<const XrCompositionLayerBaseHeader *> layers_list;
+ for (OrderedCompositionLayer &ordered_layer : ordered_layers_list) {
+ layers_list.push_back(ordered_layer.composition_layer);
+ }
XrFrameEndInfo frame_end_info = {
XR_TYPE_FRAME_END_INFO, // type
diff --git a/modules/openxr/openxr_api.h b/modules/openxr/openxr_api.h
index e1a04a0796..7ec622364b 100644
--- a/modules/openxr/openxr_api.h
+++ b/modules/openxr/openxr_api.h
@@ -287,6 +287,15 @@ private:
RID get_interaction_profile_rid(XrPath p_path);
XrPath get_interaction_profile_path(RID p_interaction_profile);
+ struct OrderedCompositionLayer {
+ const XrCompositionLayerBaseHeader *composition_layer;
+ int sort_order;
+
+ _FORCE_INLINE_ bool operator()(const OrderedCompositionLayer &a, const OrderedCompositionLayer &b) const {
+ return a.sort_order < b.sort_order || (a.sort_order == b.sort_order && uint64_t(a.composition_layer) < uint64_t(b.composition_layer));
+ }
+ };
+
// state changes
bool poll_events();
bool on_state_idle();