Skip to content

Commit

Permalink
Allow OpenXR extensions to add properties to the OpenXRCompositionLay…
Browse files Browse the repository at this point in the history
…er node
  • Loading branch information
dsnopek committed Apr 5, 2024
1 parent f6a78f8 commit fddf6dc
Show file tree
Hide file tree
Showing 8 changed files with 161 additions and 6 deletions.
31 changes: 31 additions & 0 deletions modules/openxr/doc_classes/OpenXRExtensionWrapperExtension.xml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,18 @@
Returns a [PackedStringArray] of positional tracker names that are used within the extension wrapper.
</description>
</method>
<method name="_get_viewport_composition_layer_extension_properties" qualifiers="virtual">
<return type="Dictionary[]" />
<description>
Gets an array of [Dictionary]s that represent properties, just like [method Object._get_property_list], that will be added to [OpenXRCompositionLayer] nodes.
</description>
</method>
<method name="_get_viewport_composition_layer_extension_property_defaults" qualifiers="virtual">
<return type="Dictionary" />
<description>
Gets a [Dictionary] containing the default values for the properties returned by [method _get_viewport_composition_layer_extension_properties].
</description>
</method>
<method name="_on_before_instance_created" qualifiers="virtual">
<return type="void" />
<description>
Expand Down Expand Up @@ -152,6 +164,14 @@
Called when the OpenXR session state is changed to visible. This means OpenXR is now ready to receive frames.
</description>
</method>
<method name="_on_viewport_composition_layer_destroyed" qualifiers="virtual">
<return type="void" />
<param index="0" name="layer" type="const void*" />
<description>
Called when a composition layer created via [OpenXRCompositionLayer] is destroyed.
[param layer] is a pointer to an [code]XrCompositionLayerBaseHeader[/code] struct.
</description>
</method>
<method name="_set_hand_joint_locations_and_get_next_pointer" qualifiers="virtual">
<return type="int" />
<param index="0" name="hand_index" type="int" />
Expand Down Expand Up @@ -188,6 +208,17 @@
Adds additional data structures when interogating OpenXR system abilities.
</description>
</method>
<method name="_set_viewport_composition_layer_and_get_next_pointer" qualifiers="virtual">
<return type="int" />
<param index="0" name="layer" type="const void*" />
<param index="1" name="property_values" type="Dictionary" />
<param index="2" name="next_pointer" type="void*" />
<description>
Adds additional data structures to composition layers created by [OpenXRCompositionLayer].
[param property_values] contains the values of the properties returned by [method _get_viewport_composition_layer_extension_properties].
[param layer] is a pointer to an [code]XrCompositionLayerBaseHeader[/code] struct.
</description>
</method>
<method name="get_openxr_api">
<return type="OpenXRAPIExtension" />
<description>
Expand Down
26 changes: 24 additions & 2 deletions modules/openxr/extensions/openxr_composition_layer_extension.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,11 +86,11 @@ int OpenXRCompositionLayerExtension::get_composition_layer_order(int p_index) {
return composition_layers[p_index]->get_sort_order();
}

void OpenXRCompositionLayerExtension::register_composition_layer_provider(OpenXRViewportCompositionLayerProvider *p_composition_layer) {
void OpenXRCompositionLayerExtension::register_viewport_composition_layer_provider(OpenXRViewportCompositionLayerProvider *p_composition_layer) {
composition_layers.push_back(p_composition_layer);
}

void OpenXRCompositionLayerExtension::unregister_composition_layer_provider(OpenXRViewportCompositionLayerProvider *p_composition_layer) {
void OpenXRCompositionLayerExtension::unregister_viewport_composition_layer_provider(OpenXRViewportCompositionLayerProvider *p_composition_layer) {
composition_layers.erase(p_composition_layer);
}

Expand Down Expand Up @@ -123,6 +123,10 @@ OpenXRViewportCompositionLayerProvider::OpenXRViewportCompositionLayerProvider(X
}

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());
}
Expand Down Expand Up @@ -159,6 +163,11 @@ void OpenXRViewportCompositionLayerProvider::set_viewport(RID p_viewport, 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);
Expand Down Expand Up @@ -233,6 +242,19 @@ XrCompositionLayerBaseHeader *OpenXRViewportCompositionLayerProvider::get_compos
} 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;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ class OpenXRCompositionLayerExtension : public OpenXRExtensionWrapper, public Op
virtual XrCompositionLayerBaseHeader *get_composition_layer(int p_index) override;
virtual int get_composition_layer_order(int p_index) override;

void register_composition_layer_provider(OpenXRViewportCompositionLayerProvider *p_composition_layer);
void unregister_composition_layer_provider(OpenXRViewportCompositionLayerProvider *p_composition_layer);
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);

Expand All @@ -75,6 +75,8 @@ 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;
Expand Down Expand Up @@ -102,6 +104,8 @@ class OpenXRViewportCompositionLayerProvider {
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();

Expand Down
5 changes: 5 additions & 0 deletions modules/openxr/extensions/openxr_extension_wrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,11 @@ class OpenXRExtensionWrapper {
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) {
Expand Down
34 changes: 34 additions & 0 deletions modules/openxr/extensions/openxr_extension_wrapper_extension.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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, "layer");
GDVIRTUAL_BIND(_get_viewport_composition_layer_extension_property_defaults, "layer");
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);
Expand Down Expand Up @@ -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;
}
Expand Down
12 changes: 12 additions & 0 deletions modules/openxr/extensions/openxr_extension_wrapper_extension.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -59,6 +60,7 @@ class OpenXRExtensionWrapperExtension : public Object, public OpenXRExtensionWra
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;
Expand Down Expand Up @@ -117,6 +119,16 @@ class OpenXRExtensionWrapperExtension : public Object, public OpenXRExtensionWra

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();
Expand Down
46 changes: 44 additions & 2 deletions modules/openxr/scene/openxr_composition_layer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,14 @@ void OpenXRCompositionLayer::_reset_fallback_material() {

void OpenXRCompositionLayer::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_POSTINITIALIZE: {
if (openxr_layer_provider) {
for (OpenXRExtensionWrapper *extension : OpenXRAPI::get_registered_extension_wrappers()) {
extension_property_values.merge(extension->get_viewport_composition_layer_extension_property_defaults());
}
openxr_layer_provider->set_extension_property_values(extension_property_values);
}
} break;
case NOTIFICATION_INTERNAL_PROCESS: {
if (fallback) {
if (should_update_fallback_mesh) {
Expand All @@ -260,7 +268,7 @@ void OpenXRCompositionLayer::_notification(int p_what) {
} break;
case NOTIFICATION_ENTER_TREE: {
if (composition_layer_extension) {
composition_layer_extension->register_composition_layer_provider(openxr_layer_provider);
composition_layer_extension->register_viewport_composition_layer_provider(openxr_layer_provider);
}

if (!fallback && layer_viewport && openxr_api && openxr_api->is_running() && is_visible()) {
Expand All @@ -269,7 +277,7 @@ void OpenXRCompositionLayer::_notification(int p_what) {
} break;
case NOTIFICATION_EXIT_TREE: {
if (composition_layer_extension) {
composition_layer_extension->unregister_composition_layer_provider(openxr_layer_provider);
composition_layer_extension->unregister_viewport_composition_layer_provider(openxr_layer_provider);
}

// When a node is removed in the editor, we need to clear the layer viewport, because otherwise
Expand All @@ -285,6 +293,40 @@ void OpenXRCompositionLayer::_notification(int p_what) {
}
}

void OpenXRCompositionLayer::_get_property_list(List<PropertyInfo> *p_property_list) const {
List<PropertyInfo> extension_properties;
for (OpenXRExtensionWrapper *extension : OpenXRAPI::get_registered_extension_wrappers()) {
extension->get_viewport_composition_layer_extension_properties(&extension_properties);
}

for (const PropertyInfo &pinfo : extension_properties) {
StringName prop_name = pinfo.name;
if (!String(prop_name).contains("/")) {
WARN_PRINT_ONCE(vformat("Discarding OpenXRCompositionLayer property name '%s' from extension because it doesn't contain a '/'."));
continue;
}
p_property_list->push_back(pinfo);
}
}

bool OpenXRCompositionLayer::_get(const StringName &p_property, Variant &r_value) const {
if (extension_property_values.has(p_property)) {
r_value = extension_property_values[p_property];
}

return true;
}

bool OpenXRCompositionLayer::_set(const StringName &p_property, const Variant &p_value) {
extension_property_values[p_property] = p_value;

if (openxr_layer_provider) {
openxr_layer_provider->set_extension_property_values(extension_property_values);
}

return true;
}

PackedStringArray OpenXRCompositionLayer::get_configuration_warnings() const {
PackedStringArray warnings = Node3D::get_configuration_warnings();

Expand Down
5 changes: 5 additions & 0 deletions modules/openxr/scene/openxr_composition_layer.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ class OpenXRCompositionLayer : public Node3D {
MeshInstance3D *fallback = nullptr;
bool should_update_fallback_mesh = false;

Dictionary extension_property_values;

void _create_fallback_node();
void _reset_fallback_material();

Expand All @@ -60,6 +62,9 @@ class OpenXRCompositionLayer : public Node3D {
static void _bind_methods();

void _notification(int p_what);
void _get_property_list(List<PropertyInfo> *p_property_list) const;
bool _get(const StringName &p_property, Variant &r_value) const;
bool _set(const StringName &p_property, const Variant &p_value);

virtual void _on_openxr_session_begun();
virtual void _on_openxr_session_stopping();
Expand Down

0 comments on commit fddf6dc

Please sign in to comment.