Skip to content

Commit

Permalink
Implement OpenXR FB swapchain update extensions
Browse files Browse the repository at this point in the history
  • Loading branch information
devloglogan committed Jan 29, 2025
1 parent b15b24b commit 1268829
Show file tree
Hide file tree
Showing 7 changed files with 753 additions and 0 deletions.
99 changes: 99 additions & 0 deletions modules/openxr/doc_classes/OpenXRCompositionLayer.xml
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,109 @@
The sort order for this composition layer. Higher numbers will be shown in front of lower numbers.
[b]Note:[/b] This will have no effect if a fallback mesh is being used.
</member>
<member name="swapchain_state_alpha_swizzle" type="int" setter="set_alpha_swizzle" getter="get_alpha_swizzle" enum="OpenXRCompositionLayer.Swizzle" default="3">
The swizzle value for the alpha channel of the swapchain state.
[b]Note:[/b] This property only has an effect on devices that support the OpenXR XR_FB_swapchain_update_state OpenGLES/Vulkan extensions.
</member>
<member name="swapchain_state_blue_swizzle" type="int" setter="set_blue_swizzle" getter="get_blue_swizzle" enum="OpenXRCompositionLayer.Swizzle" default="2">
The swizzle value for the blue channel of the swapchain state.
[b]Note:[/b] This property only has an effect on devices that support the OpenXR XR_FB_swapchain_update_state OpenGLES/Vulkan extensions.
</member>
<member name="swapchain_state_border_color" type="Color" setter="set_border_color" getter="get_border_color" default="Color(0, 0, 0, 0)">
The border color of the swapchain state that is used when the wrap mode clamps to the border.
[b]Note:[/b] This property only has an effect on devices that support the OpenXR XR_FB_swapchain_update_state OpenGLES/Vulkan extensions.
</member>
<member name="swapchain_state_green_swizzle" type="int" setter="set_green_swizzle" getter="get_green_swizzle" enum="OpenXRCompositionLayer.Swizzle" default="1">
The swizzle value for the green channel of the swapchain state.
[b]Note:[/b] This property only has an effect on devices that support the OpenXR XR_FB_swapchain_update_state OpenGLES/Vulkan extensions.
</member>
<member name="swapchain_state_horizontal_wrap" type="int" setter="set_horizontal_wrap" getter="get_horizontal_wrap" enum="OpenXRCompositionLayer.Wrap" default="0">
The horizontal wrap mode of the swapchain state.
[b]Note:[/b] This property only has an effect on devices that support the OpenXR XR_FB_swapchain_update_state OpenGLES/Vulkan extensions.
</member>
<member name="swapchain_state_mag_filter" type="int" setter="set_mag_filter" getter="get_mag_filter" enum="OpenXRCompositionLayer.Filter" default="1">
The magnification filter of the swapchain state.
[b]Note:[/b] This property only has an effect on devices that support the OpenXR XR_FB_swapchain_update_state OpenGLES/Vulkan extensions.
</member>
<member name="swapchain_state_max_anisotropy" type="float" setter="set_max_anisotropy" getter="get_max_anisotropy" default="1.0">
The max anisotropy of the swapchain state.
[b]Note:[/b] This property only has an effect on devices that support the OpenXR XR_FB_swapchain_update_state OpenGLES/Vulkan extensions.
</member>
<member name="swapchain_state_min_filter" type="int" setter="set_min_filter" getter="get_min_filter" enum="OpenXRCompositionLayer.Filter" default="1">
The minification filter of the swapchain state.
[b]Note:[/b] This property only has an effect on devices that support the OpenXR XR_FB_swapchain_update_state OpenGLES/Vulkan extensions.
</member>
<member name="swapchain_state_mipmap_mode" type="int" setter="set_mipmap_mode" getter="get_mipmap_mode" enum="OpenXRCompositionLayer.MipmapMode" default="2">
The mipmap mode of the swapchain state.
[b]Note:[/b] This property only has an effect on devices that support the OpenXR XR_FB_swapchain_update_state OpenGLES/Vulkan extensions.
</member>
<member name="swapchain_state_red_swizzle" type="int" setter="set_red_swizzle" getter="get_red_swizzle" enum="OpenXRCompositionLayer.Swizzle" default="0">
The swizzle value for the red channel of the swapchain state.
[b]Note:[/b] This property only has an effect on devices that support the OpenXR XR_FB_swapchain_update_state OpenGLES/Vulkan extensions.
</member>
<member name="swapchain_state_vertical_wrap" type="int" setter="set_vertical_wrap" getter="get_vertical_wrap" enum="OpenXRCompositionLayer.Wrap" default="0">
The vertical wrap mode of the swapchain state.
[b]Note:[/b] This property only has an effect on devices that support the OpenXR XR_FB_swapchain_update_state OpenGLES/Vulkan extensions.
</member>
<member name="use_android_surface" type="bool" setter="set_use_android_surface" getter="get_use_android_surface" default="false">
If enabled, an Android surface will be created (with the dimensions from [member android_surface_size]) which will provide the 2D content for the composition layer, rather than using [member layer_viewport].
See [method get_android_surface] for information about how to get the surface so that your application can draw to it.
[b]Note:[/b] This will only work in Android builds.
</member>
</members>
<constants>
<constant name="FILTER_NEAREST" value="0" enum="Filter">
Perform nearest-neighbor filtering when sampling the texture.
</constant>
<constant name="FILTER_LINEAR" value="1" enum="Filter">
Perform linear filtering when sampling the texture.
</constant>
<constant name="FILTER_CUBIC" value="2" enum="Filter">
Perform cubic filtering when sampling the texture.
</constant>
<constant name="MIPMAP_MODE_DISABLED" value="0" enum="MipmapMode">
Disable mipmapping.
[b]Note:[/b] Mipmapping can only be disabled in the compatibility renderer.
</constant>
<constant name="MIPMAP_MODE_NEAREST" value="1" enum="MipmapMode">
Use the mipmap of the nearest resolution.
</constant>
<constant name="MIPMAP_MODE_LINEAR" value="2" enum="MipmapMode">
Use linear interpolation of the two mipmaps of the nearest resolution.
</constant>
<constant name="WRAP_CLAMP_TO_BORDER" value="0" enum="Wrap">
Clamp the texture to its specified border color.
</constant>
<constant name="WRAP_CLAMP_TO_EDGE" value="1" enum="Wrap">
Clamp the texture to its edge color.
</constant>
<constant name="WRAP_REPEAT" value="2" enum="Wrap">
Repeat the texture infinitely.
</constant>
<constant name="WRAP_MIRRORED_REPEAT" value="3" enum="Wrap">
Repeat the texture infinitely, mirroring it on each repeat.
</constant>
<constant name="WRAP_MIRROR_CLAMP_TO_EDGE" value="4" enum="Wrap">
Mirror the texture once and then clamp the texture to its edge color.
[b]Note:[/b] This wrap mode is not available in the compatibility renderer.
</constant>
<constant name="SWIZZLE_RED" value="0" enum="Swizzle">
Maps a color channel to the value of the red channel.
</constant>
<constant name="SWIZZLE_GREEN" value="1" enum="Swizzle">
Maps a color channel to the value of the green channel.
</constant>
<constant name="SWIZZLE_BLUE" value="2" enum="Swizzle">
Maps a color channel to the value of the blue channel.
</constant>
<constant name="SWIZZLE_ALPHA" value="3" enum="Swizzle">
Maps a color channel to the value of the alpha channel.
</constant>
<constant name="SWIZZLE_ZERO" value="4" enum="Swizzle">
Maps a color channel to the value of zero.
</constant>
<constant name="SWIZZLE_ONE" value="5" enum="Swizzle">
Maps a color channel to the value of one.
</constant>
</constants>
</class>
48 changes: 48 additions & 0 deletions modules/openxr/extensions/openxr_composition_layer_extension.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include <openxr/openxr_platform.h>
#endif

#include "openxr_fb_update_swapchain_extension.h"
#include "platform/android/api/java_class_wrapper.h"
#include "servers/rendering/rendering_server_globals.h"

Expand Down Expand Up @@ -175,6 +176,7 @@ OpenXRViewportCompositionLayerProvider::OpenXRViewportCompositionLayerProvider(X
composition_layer = p_composition_layer;
openxr_api = OpenXRAPI::get_singleton();
composition_layer_extension = OpenXRCompositionLayerExtension::get_singleton();
swapchain_state = memnew(SwapchainState);
}

OpenXRViewportCompositionLayerProvider::~OpenXRViewportCompositionLayerProvider() {
Expand All @@ -188,6 +190,8 @@ OpenXRViewportCompositionLayerProvider::~OpenXRViewportCompositionLayerProvider(
// This will reset the viewport and free the swapchain too.
set_viewport(RID(), Size2i());
}

memdelete(swapchain_state);
}

void OpenXRViewportCompositionLayerProvider::set_alpha_blend(bool p_alpha_blend) {
Expand Down Expand Up @@ -227,6 +231,13 @@ void OpenXRViewportCompositionLayerProvider::set_viewport(RID p_viewport, Size2i
void OpenXRViewportCompositionLayerProvider::set_use_android_surface(bool p_use_android_surface, Size2i p_size) {
#ifdef ANDROID_ENABLED
if (p_use_android_surface == use_android_surface) {
if (use_android_surface && swapchain_size != p_size) {
OpenXRFBUpdateSwapchainExtension *fb_update_swapchain_ext = OpenXRFBUpdateSwapchainExtension::get_singleton();
if (fb_update_swapchain_ext && fb_update_swapchain_ext->is_android_ext_enabled()) {
swapchain_size = p_size;
fb_update_swapchain_ext->update_swapchain_surface_size(android_surface.swapchain, swapchain_size);
}
}
return;
}

Expand Down Expand Up @@ -280,6 +291,8 @@ void OpenXRViewportCompositionLayerProvider::create_android_surface() {
jobject surface;
composition_layer_extension->create_android_surface_swapchain(&info, &android_surface.swapchain, &surface);

swapchain_state->dirty = true;

if (surface) {
android_surface.surface.instantiate(JavaClassWrapper::get_singleton()->wrap("android.view.Surface"), surface);
}
Expand Down Expand Up @@ -327,6 +340,11 @@ void OpenXRViewportCompositionLayerProvider::on_pre_render() {
}
}
}

if (swapchain_state->dirty) {
update_swapchain_state();
swapchain_state->dirty = false;
}
}

XrCompositionLayerBaseHeader *OpenXRViewportCompositionLayerProvider::get_composition_layer() {
Expand Down Expand Up @@ -393,6 +411,34 @@ XrCompositionLayerBaseHeader *OpenXRViewportCompositionLayerProvider::get_compos
return composition_layer;
}

void OpenXRViewportCompositionLayerProvider::update_swapchain_state() {
OpenXRFBUpdateSwapchainExtension *fb_update_swapchain_ext = OpenXRFBUpdateSwapchainExtension::get_singleton();
if (!fb_update_swapchain_ext) {
return;
}

#ifdef ANDROID_ENABLED
if (use_android_surface) {
if (android_surface.swapchain == XR_NULL_HANDLE) {
return;
}

fb_update_swapchain_ext->update_swapchain_state(android_surface.swapchain, swapchain_state);
} else
#endif
{
if (subviewport.swapchain_info.get_swapchain() == XR_NULL_HANDLE) {
return;
}

fb_update_swapchain_ext->update_swapchain_state(subviewport.swapchain_info.get_swapchain(), swapchain_state);
}
}

SwapchainState *OpenXRViewportCompositionLayerProvider::get_swapchain_state() {
return swapchain_state;
}

void OpenXRViewportCompositionLayerProvider::update_swapchain_sub_image(XrSwapchainSubImage &r_subimage) {
#ifdef ANDROID_ENABLED
if (use_android_surface) {
Expand Down Expand Up @@ -451,6 +497,8 @@ bool OpenXRViewportCompositionLayerProvider::update_and_acquire_swapchain(bool p
return false;
}

swapchain_state->dirty = true;

// Acquire our image so we can start rendering into it,
// we can ignore should_render here, ret will be false.
bool should_render = true;
Expand Down
57 changes: 57 additions & 0 deletions modules/openxr/extensions/openxr_composition_layer_extension.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,44 @@ class OpenXRCompositionLayerExtension : public OpenXRExtensionWrapper, public Op
#endif
};

struct SwapchainState;

class OpenXRViewportCompositionLayerProvider {
public:
// Must be identical to Filter enum definition in OpenXRCompositionLayer.
enum Filter {
FILTER_NEAREST,
FILTER_LINEAR,
FILTER_CUBIC,
};

// Must be identical to MipmapMode enum definition in OpenXRCompositionLayer.
enum MipmapMode {
MIPMAP_MODE_DISABLED,
MIPMAP_MODE_NEAREST,
MIPMAP_MODE_LINEAR,
};

// Must be identical to Wrap enum definition in OpenXRCompositionLayer.
enum Wrap {
WRAP_CLAMP_TO_BORDER,
WRAP_CLAMP_TO_EDGE,
WRAP_REPEAT,
WRAP_MIRRORED_REPEAT,
WRAP_MIRROR_CLAMP_TO_EDGE,
};

// Must be identical to Swizzle enum definition in OpenXRCompositionLayer.
enum Swizzle {
SWIZZLE_RED,
SWIZZLE_GREEN,
SWIZZLE_BLUE,
SWIZZLE_ALPHA,
SWIZZLE_ZERO,
SWIZZLE_ONE,
};

private:
XrCompositionLayerBaseHeader *composition_layer = nullptr;
int sort_order = 1;
bool alpha_blend = false;
Expand Down Expand Up @@ -130,6 +167,8 @@ class OpenXRViewportCompositionLayerProvider {
void update_swapchain_sub_image(XrSwapchainSubImage &r_swapchain_sub_image);
void free_swapchain();

SwapchainState *swapchain_state;

#ifdef ANDROID_ENABLED
void create_android_surface();
#endif
Expand All @@ -156,8 +195,26 @@ class OpenXRViewportCompositionLayerProvider {
void on_pre_render();
XrCompositionLayerBaseHeader *get_composition_layer();

void update_swapchain_state();
SwapchainState *get_swapchain_state();

OpenXRViewportCompositionLayerProvider(XrCompositionLayerBaseHeader *p_composition_layer);
~OpenXRViewportCompositionLayerProvider();
};

struct SwapchainState {
OpenXRViewportCompositionLayerProvider::Filter min_filter = OpenXRViewportCompositionLayerProvider::Filter::FILTER_LINEAR;
OpenXRViewportCompositionLayerProvider::Filter mag_filter = OpenXRViewportCompositionLayerProvider::Filter::FILTER_LINEAR;
OpenXRViewportCompositionLayerProvider::MipmapMode mipmap_mode = OpenXRViewportCompositionLayerProvider::MipmapMode::MIPMAP_MODE_LINEAR;
OpenXRViewportCompositionLayerProvider::Wrap horizontal_wrap = OpenXRViewportCompositionLayerProvider::Wrap::WRAP_CLAMP_TO_BORDER;
OpenXRViewportCompositionLayerProvider::Wrap vertical_wrap = OpenXRViewportCompositionLayerProvider::Wrap::WRAP_CLAMP_TO_BORDER;
OpenXRViewportCompositionLayerProvider::Swizzle red_swizzle = OpenXRViewportCompositionLayerProvider::Swizzle::SWIZZLE_RED;
OpenXRViewportCompositionLayerProvider::Swizzle green_swizzle = OpenXRViewportCompositionLayerProvider::Swizzle::SWIZZLE_GREEN;
OpenXRViewportCompositionLayerProvider::Swizzle blue_swizzle = OpenXRViewportCompositionLayerProvider::Swizzle::SWIZZLE_BLUE;
OpenXRViewportCompositionLayerProvider::Swizzle alpha_swizzle = OpenXRViewportCompositionLayerProvider::Swizzle::SWIZZLE_ALPHA;
float max_anisotropy = 1.0;
Color border_color = { 0.0, 0.0, 0.0, 0.0 };
bool dirty = false;
};

#endif // OPENXR_COMPOSITION_LAYER_EXTENSION_H
Loading

0 comments on commit 1268829

Please sign in to comment.