diff --git a/components/script/dom/webidls/XRView.webidl b/components/script/dom/webidls/XRView.webidl index 2b4bf5f5f0a..ac58caa8144 100644 --- a/components/script/dom/webidls/XRView.webidl +++ b/components/script/dom/webidls/XRView.webidl @@ -14,7 +14,10 @@ enum XREye { interface XRView { readonly attribute XREye eye; readonly attribute Float32Array projectionMatrix; - readonly attribute XRRigidTransform transform; + [SameObject] readonly attribute XRRigidTransform transform; + readonly attribute double? recommendedViewportScale; + + undefined requestViewportScale(double? scale); // AR Module readonly attribute boolean isFirstPersonObserver; diff --git a/components/script/dom/xrview.rs b/components/script/dom/xrview.rs index f26bf0f126d..047318a62ea 100644 --- a/components/script/dom/xrview.rs +++ b/components/script/dom/xrview.rs @@ -2,6 +2,8 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +use std::cell::Cell; + use dom_struct::dom_struct; use euclid::RigidTransform3D; use js::typedarray::{Float32, Float32Array}; @@ -9,6 +11,7 @@ use webxr_api::{ApiSpace, View}; use super::bindings::buffer_source::HeapBufferSource; use crate::dom::bindings::codegen::Bindings::XRViewBinding::{XREye, XRViewMethods}; +use crate::dom::bindings::num::Finite; use crate::dom::bindings::reflector::{reflect_dom_object, Reflector}; use crate::dom::bindings::root::{Dom, DomRoot}; use crate::dom::globalscope::GlobalScope; @@ -28,6 +31,7 @@ pub struct XRView { #[no_trace] view: View, transform: Dom, + requested_viewport_scale: Cell, } impl XRView { @@ -46,6 +50,7 @@ impl XRView { proj: HeapBufferSource::default(), view, transform: Dom::from_ref(transform), + requested_viewport_scale: Cell::new(1.0), } } @@ -107,6 +112,22 @@ impl XRViewMethods for XRView { DomRoot::from_ref(&self.transform) } + /// + fn GetRecommendedViewportScale(&self) -> Option> { + // Just return 1.0 since we currently will always use full-sized viewports + Finite::new(1.0) + } + + /// + fn RequestViewportScale(&self, scale: Option>) { + if let Some(scale) = scale { + if *scale > 0.0 { + let clamped_scale = scale.clamp(0.0, 1.0); + self.requested_viewport_scale.set(clamped_scale); + } + } + } + /// fn IsFirstPersonObserver(&self) -> bool { // Servo is not currently supported anywhere that supports this, so return false diff --git a/components/script/dom/xrwebgllayer.rs b/components/script/dom/xrwebgllayer.rs index e99b0376b1d..933e8537f1d 100644 --- a/components/script/dom/xrwebgllayer.rs +++ b/components/script/dom/xrwebgllayer.rs @@ -316,7 +316,7 @@ impl XRWebGLLayerMethods for XRWebGLLayer { let index = view.viewport_index(); let viewport = self.session().with_session(|s| { - // Inline sssions + // Inline sessions if s.viewports().is_empty() { Rect::from_size(self.size().to_i32()) } else { @@ -324,6 +324,11 @@ impl XRWebGLLayerMethods for XRWebGLLayer { } }); + // NOTE: According to spec, viewport sizes should be recalculated here if the + // requested viewport scale has changed. However, existing browser implementations + // don't seem to do this for stereoscopic immersive sessions. + // Revisit if Servo gets support for handheld AR/VR via ARCore/ARKit + Some(XRViewport::new(&self.global(), viewport)) } } diff --git a/tests/wpt/meta-legacy-layout/webxr/idlharness.https.window.js.ini b/tests/wpt/meta-legacy-layout/webxr/idlharness.https.window.js.ini index dcf09636ea1..0919bc970d6 100644 --- a/tests/wpt/meta-legacy-layout/webxr/idlharness.https.window.js.ini +++ b/tests/wpt/meta-legacy-layout/webxr/idlharness.https.window.js.ini @@ -317,12 +317,6 @@ [XRSession interface: calling cancelAnimationFrame(unsigned long) on xrSession with too few arguments must throw TypeError] expected: FAIL - [XRView interface: attribute recommendedViewportScale] - expected: FAIL - - [XRView interface: operation requestViewportScale(double?)] - expected: FAIL - [XRPose interface: attribute linearVelocity] expected: FAIL diff --git a/tests/wpt/meta-legacy-layout/webxr/xr_viewport_scale.https.html.ini b/tests/wpt/meta-legacy-layout/webxr/xr_viewport_scale.https.html.ini index 5be9a58789a..7cc38eed275 100644 --- a/tests/wpt/meta-legacy-layout/webxr/xr_viewport_scale.https.html.ini +++ b/tests/wpt/meta-legacy-layout/webxr/xr_viewport_scale.https.html.ini @@ -1,85 +1,24 @@ [xr_viewport_scale.https.html] - expected: ERROR - [requestViewportScale valid viewport for inline session - webgl] - expected: TIMEOUT - - [recommendedViewportScale for immersive-vr session - webgl2] - expected: NOTRUN - [requestViewportScale applied next frame for immersive-vr session - webgl] - expected: NOTRUN - - [requestViewportScale valid viewport w/ very small scale for inline session - webgl] - expected: NOTRUN + expected: PRECONDITION_FAILED [requestViewportScale same frame for inline session - webgl] - expected: NOTRUN + expected: PRECONDITION_FAILED [requestViewportScale same frame for immersive-vr session - webgl] - expected: NOTRUN - - [requestViewportScale valid viewport w/ null scale for immersive-vr session - webgl] - expected: NOTRUN - - [requestViewportScale valid viewport w/ undefined scale for inline session - webgl] - expected: NOTRUN + expected: PRECONDITION_FAILED [requestViewportScale applied next frame for immersive-vr session - webgl2] - expected: NOTRUN - - [requestViewportScale valid viewport for immersive-vr session - webgl] - expected: NOTRUN - - [requestViewportScale valid viewport w/ very small scale for immersive-vr session - webgl2] - expected: NOTRUN + expected: PRECONDITION_FAILED [requestViewportScale applied next frame for inline session - webgl] - expected: NOTRUN - - [recommendedViewportScale for inline session - webgl2] - expected: NOTRUN - - [requestViewportScale valid viewport w/ very small scale for inline session - webgl2] - expected: NOTRUN + expected: PRECONDITION_FAILED [requestViewportScale same frame for immersive-vr session - webgl2] - expected: NOTRUN - - [requestViewportScale valid viewport w/ null scale for inline session - webgl2] - expected: NOTRUN - - [recommendedViewportScale for inline session - webgl] - expected: NOTRUN - - [requestViewportScale valid viewport for immersive-vr session - webgl2] - expected: NOTRUN - - [requestViewportScale valid viewport w/ undefined scale for immersive-vr session - webgl2] - expected: NOTRUN - - [requestViewportScale valid viewport w/ undefined scale for immersive-vr session - webgl] - expected: NOTRUN + expected: PRECONDITION_FAILED [requestViewportScale same frame for inline session - webgl2] - expected: NOTRUN + expected: PRECONDITION_FAILED [requestViewportScale applied next frame for inline session - webgl2] - expected: NOTRUN - - [recommendedViewportScale for immersive-vr session - webgl] - expected: NOTRUN - - [requestViewportScale valid viewport for inline session - webgl2] - expected: NOTRUN - - [requestViewportScale valid viewport w/ null scale for inline session - webgl] - expected: NOTRUN - - [requestViewportScale valid viewport w/ null scale for immersive-vr session - webgl2] - expected: NOTRUN - - [requestViewportScale valid viewport w/ very small scale for immersive-vr session - webgl] - expected: NOTRUN - - [requestViewportScale valid viewport w/ undefined scale for inline session - webgl2] - expected: NOTRUN + expected: PRECONDITION_FAILED diff --git a/tests/wpt/meta/webxr/idlharness.https.window.js.ini b/tests/wpt/meta/webxr/idlharness.https.window.js.ini index 9b9b62d8b21..c991fec154b 100644 --- a/tests/wpt/meta/webxr/idlharness.https.window.js.ini +++ b/tests/wpt/meta/webxr/idlharness.https.window.js.ini @@ -260,12 +260,6 @@ [XRSession interface: calling cancelAnimationFrame(unsigned long) on xrSession with too few arguments must throw TypeError] expected: FAIL - [XRView interface: attribute recommendedViewportScale] - expected: FAIL - - [XRView interface: operation requestViewportScale(double?)] - expected: FAIL - [XRPose interface: attribute linearVelocity] expected: FAIL diff --git a/tests/wpt/meta/webxr/xr_viewport_scale.https.html.ini b/tests/wpt/meta/webxr/xr_viewport_scale.https.html.ini index 42e68b4cbee..7cc38eed275 100644 --- a/tests/wpt/meta/webxr/xr_viewport_scale.https.html.ini +++ b/tests/wpt/meta/webxr/xr_viewport_scale.https.html.ini @@ -1,127 +1,24 @@ [xr_viewport_scale.https.html] - expected: ERROR - [requestViewportScale valid viewport for inline session] - expected: TIMEOUT - - [requestViewportScale valid viewport w/ null scale for inline session] - expected: NOTRUN - - [recommendedViewportScale for immersive-vr session] - expected: NOTRUN - - [requestViewportScale applied next frame for inline session] - expected: NOTRUN - - [requestViewportScale valid viewport w/ very small scale for inline session] - expected: NOTRUN - - [requestViewportScale valid viewport w/ undefined scale for immersive-vr session] - expected: NOTRUN - - [requestViewportScale valid viewport for immersive-vr session] - expected: NOTRUN - - [requestViewportScale same frame for inline session] - expected: NOTRUN - - [recommendedViewportScale for inline session] - expected: NOTRUN - - [requestViewportScale same frame for immersive-vr session] - expected: NOTRUN - - [requestViewportScale valid viewport w/ very small scale for immersive-vr session] - expected: NOTRUN - - [requestViewportScale valid viewport w/ null scale for immersive-vr session] - expected: NOTRUN - - [requestViewportScale valid viewport w/ undefined scale for inline session] - expected: NOTRUN - - [requestViewportScale applied next frame for immersive-vr session] - expected: NOTRUN - - [requestViewportScale valid viewport for inline session - webgl] - expected: TIMEOUT - - [recommendedViewportScale for immersive-vr session - webgl2] - expected: NOTRUN - [requestViewportScale applied next frame for immersive-vr session - webgl] - expected: NOTRUN - - [requestViewportScale valid viewport w/ very small scale for inline session - webgl] - expected: NOTRUN + expected: PRECONDITION_FAILED [requestViewportScale same frame for inline session - webgl] - expected: NOTRUN + expected: PRECONDITION_FAILED [requestViewportScale same frame for immersive-vr session - webgl] - expected: NOTRUN - - [requestViewportScale valid viewport w/ null scale for immersive-vr session - webgl] - expected: NOTRUN - - [requestViewportScale valid viewport w/ undefined scale for inline session - webgl] - expected: NOTRUN + expected: PRECONDITION_FAILED [requestViewportScale applied next frame for immersive-vr session - webgl2] - expected: NOTRUN - - [requestViewportScale valid viewport for immersive-vr session - webgl] - expected: NOTRUN - - [requestViewportScale valid viewport w/ very small scale for immersive-vr session - webgl2] - expected: NOTRUN + expected: PRECONDITION_FAILED [requestViewportScale applied next frame for inline session - webgl] - expected: NOTRUN - - [recommendedViewportScale for inline session - webgl2] - expected: NOTRUN - - [requestViewportScale valid viewport w/ very small scale for inline session - webgl2] - expected: NOTRUN + expected: PRECONDITION_FAILED [requestViewportScale same frame for immersive-vr session - webgl2] - expected: NOTRUN - - [requestViewportScale valid viewport w/ null scale for inline session - webgl2] - expected: NOTRUN - - [recommendedViewportScale for inline session - webgl] - expected: NOTRUN - - [requestViewportScale valid viewport for immersive-vr session - webgl2] - expected: NOTRUN - - [requestViewportScale valid viewport w/ undefined scale for immersive-vr session - webgl2] - expected: NOTRUN - - [requestViewportScale valid viewport w/ undefined scale for immersive-vr session - webgl] - expected: NOTRUN + expected: PRECONDITION_FAILED [requestViewportScale same frame for inline session - webgl2] - expected: NOTRUN + expected: PRECONDITION_FAILED [requestViewportScale applied next frame for inline session - webgl2] - expected: NOTRUN - - [recommendedViewportScale for immersive-vr session - webgl] - expected: NOTRUN - - [requestViewportScale valid viewport for inline session - webgl2] - expected: NOTRUN - - [requestViewportScale valid viewport w/ null scale for inline session - webgl] - expected: NOTRUN - - [requestViewportScale valid viewport w/ null scale for immersive-vr session - webgl2] - expected: NOTRUN - - [requestViewportScale valid viewport w/ very small scale for immersive-vr session - webgl] - expected: NOTRUN - - [requestViewportScale valid viewport w/ undefined scale for inline session - webgl2] - expected: NOTRUN + expected: PRECONDITION_FAILED