Browse Source

Merge pull request #108644 from bnjmntmm/secure-android-surface

Use of `XrSwapchainCreateFlags` for `OpenXRCompositionLayer`
Thaddeus Crews 2 months ago
parent
commit
788745e5b8

+ 4 - 0
modules/openxr/doc_classes/OpenXRCompositionLayer.xml

@@ -49,6 +49,10 @@
 		<member name="layer_viewport" type="SubViewport" setter="set_layer_viewport" getter="get_layer_viewport">
 			The [SubViewport] to render on the composition layer.
 		</member>
+		<member name="protected_content" type="bool" setter="set_protected_content" getter="is_protected_content" default="false">
+			If enabled, the OpenXR swapchain will be created with the [code]XR_SWAPCHAIN_CREATE_PROTECTED_CONTENT_BIT[/code] flag, which will protect its contents from CPU access.
+			When used with an Android Surface, this may allow DRM content to be presented, and will only take effect when the Surface is first created; later changes to this property will have no effect.
+		</member>
 		<member name="sort_order" type="int" setter="set_sort_order" getter="get_sort_order" default="1">
 			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.

+ 13 - 2
modules/openxr/extensions/openxr_composition_layer_extension.cpp

@@ -269,12 +269,19 @@ void OpenXRViewportCompositionLayerProvider::create_android_surface() {
 		}
 	}
 
+	// Check to see if content should be protected.
+	XrSwapchainCreateFlags create_flags = 0;
+
+	if (protected_content) {
+		create_flags = XR_SWAPCHAIN_CREATE_PROTECTED_CONTENT_BIT;
+	}
+
 	// The XR_FB_android_surface_swapchain_create extension mandates that format, sampleCount,
 	// faceCount, arraySize, and mipCount must be zero.
 	XrSwapchainCreateInfo info = {
 		XR_TYPE_SWAPCHAIN_CREATE_INFO, // type
 		next_pointer, // next
-		0, // createFlags
+		create_flags, // createFlags
 		XR_SWAPCHAIN_USAGE_SAMPLED_BIT | XR_SWAPCHAIN_USAGE_COLOR_ATTACHMENT_BIT | XR_SWAPCHAIN_USAGE_MUTABLE_FORMAT_BIT, // usageFlags
 		0, // format
 		0, // sampleCount
@@ -471,7 +478,7 @@ bool OpenXRViewportCompositionLayerProvider::update_and_acquire_swapchain(bool p
 	// See if our current swapchain is outdated.
 	if (subviewport.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 == subviewport.viewport_size && !p_static_image && !subviewport.static_image) {
+		if (swapchain_size == subviewport.viewport_size && !p_static_image && !subviewport.static_image && protected_content == subviewport.swapchain_protected_content) {
 			// We're all good! Just acquire it.
 			// We can ignore should_render here, return will be false.
 			bool should_render = true;
@@ -489,6 +496,9 @@ bool OpenXRViewportCompositionLayerProvider::update_and_acquire_swapchain(bool p
 	if (p_static_image) {
 		create_flags |= XR_SWAPCHAIN_CREATE_STATIC_IMAGE_BIT;
 	}
+	if (protected_content) {
+		create_flags |= XR_SWAPCHAIN_CREATE_PROTECTED_CONTENT_BIT;
+	}
 	if (!subviewport.swapchain_info.create(create_flags, XR_SWAPCHAIN_USAGE_SAMPLED_BIT | XR_SWAPCHAIN_USAGE_COLOR_ATTACHMENT_BIT | XR_SWAPCHAIN_USAGE_MUTABLE_FORMAT_BIT, swapchain_format, subviewport.viewport_size.width, subviewport.viewport_size.height, sample_count, array_size)) {
 		swapchain_size = Size2i();
 		return false;
@@ -503,6 +513,7 @@ bool OpenXRViewportCompositionLayerProvider::update_and_acquire_swapchain(bool p
 
 	swapchain_size = subviewport.viewport_size;
 	subviewport.static_image = p_static_image;
+	subviewport.swapchain_protected_content = protected_content;
 	return ret;
 }
 

+ 5 - 0
modules/openxr/extensions/openxr_composition_layer_extension.h

@@ -161,6 +161,7 @@ private:
 		Size2i viewport_size;
 		OpenXRAPI::OpenXRSwapChainInfo swapchain_info;
 		bool static_image = false;
+		bool swapchain_protected_content = false;
 	} subviewport;
 
 #ifdef ANDROID_ENABLED
@@ -171,6 +172,7 @@ private:
 #endif
 
 	bool use_android_surface = false;
+	bool protected_content = false;
 	Size2i swapchain_size;
 
 	OpenXRAPI *openxr_api = nullptr;
@@ -204,6 +206,9 @@ public:
 	void set_use_android_surface(bool p_enable, Size2i p_size);
 	bool get_use_android_surface() const { return use_android_surface; }
 
+	void set_protected_content(bool p_protected_content) { protected_content = p_protected_content; }
+	bool is_protected_content() const { return protected_content; }
+
 	Ref<JavaObject> get_android_surface();
 
 	void set_extension_property_values(const Dictionary &p_property_values);

+ 12 - 0
modules/openxr/scene/openxr_composition_layer.cpp

@@ -113,6 +113,9 @@ void OpenXRCompositionLayer::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("get_android_surface"), &OpenXRCompositionLayer::get_android_surface);
 	ClassDB::bind_method(D_METHOD("is_natively_supported"), &OpenXRCompositionLayer::is_natively_supported);
 
+	ClassDB::bind_method(D_METHOD("is_protected_content"), &OpenXRCompositionLayer::is_protected_content);
+	ClassDB::bind_method(D_METHOD("set_protected_content", "protected_content"), &OpenXRCompositionLayer::set_protected_content);
+
 	ClassDB::bind_method(D_METHOD("set_min_filter", "mode"), &OpenXRCompositionLayer::set_min_filter);
 	ClassDB::bind_method(D_METHOD("get_min_filter"), &OpenXRCompositionLayer::get_min_filter);
 
@@ -150,6 +153,7 @@ void OpenXRCompositionLayer::_bind_methods() {
 
 	ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "layer_viewport", PROPERTY_HINT_NODE_TYPE, "SubViewport"), "set_layer_viewport", "get_layer_viewport");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_android_surface", PROPERTY_HINT_NONE, ""), "set_use_android_surface", "get_use_android_surface");
+	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "protected_content", PROPERTY_HINT_NONE, ""), "set_protected_content", "is_protected_content");
 	ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "android_surface_size", PROPERTY_HINT_NONE, ""), "set_android_surface_size", "get_android_surface_size");
 	ADD_PROPERTY(PropertyInfo(Variant::INT, "sort_order", PROPERTY_HINT_NONE, ""), "set_sort_order", "get_sort_order");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "alpha_blend", PROPERTY_HINT_NONE, ""), "set_alpha_blend", "get_alpha_blend");
@@ -419,6 +423,14 @@ bool OpenXRCompositionLayer::is_natively_supported() const {
 	return false;
 }
 
+void OpenXRCompositionLayer::set_protected_content(bool p_protected_content) {
+	openxr_layer_provider->set_protected_content(p_protected_content);
+}
+
+bool OpenXRCompositionLayer::is_protected_content() const {
+	return openxr_layer_provider->is_protected_content();
+}
+
 void OpenXRCompositionLayer::set_min_filter(Filter p_mode) {
 	if (swapchain_state->min_filter == (OpenXRViewportCompositionLayerProvider::Filter)p_mode) {
 		return;

+ 3 - 0
modules/openxr/scene/openxr_composition_layer.h

@@ -155,6 +155,9 @@ public:
 	Ref<JavaObject> get_android_surface();
 	bool is_natively_supported() const;
 
+	void set_protected_content(bool p_protected_content);
+	bool is_protected_content() const;
+
 	void set_min_filter(Filter p_mode);
 	Filter get_min_filter() const;