diff --git a/components/script/dom/webidls/XRSession.webidl b/components/script/dom/webidls/XRSession.webidl index 39e689a8dc29..59ccecb521ae 100644 --- a/components/script/dom/webidls/XRSession.webidl +++ b/components/script/dom/webidls/XRSession.webidl @@ -29,7 +29,7 @@ interface XRSession : EventTarget { // FrozenArray getInputSources(); sequence getInputSources(); - Promise updateRenderState(optional XRRenderStateInit state); + void updateRenderState(optional XRRenderStateInit state); long requestAnimationFrame(XRFrameRequestCallback callback); void cancelAnimationFrame(long handle); diff --git a/components/script/dom/xrrenderstate.rs b/components/script/dom/xrrenderstate.rs index cc0739396e24..04ce6d1810ad 100644 --- a/components/script/dom/xrrenderstate.rs +++ b/components/script/dom/xrrenderstate.rs @@ -4,8 +4,7 @@ use crate::dom::bindings::codegen::Bindings::XRRenderStateBinding::{self, XRRenderStateMethods}; use crate::dom::bindings::num::Finite; -use crate::dom::bindings::reflector::reflect_dom_object; -use crate::dom::bindings::reflector::Reflector; +use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector}; use crate::dom::bindings::root::{DomRoot, MutNullableDom}; use crate::dom::globalscope::GlobalScope; use crate::dom::xrlayer::XRLayer; @@ -47,6 +46,25 @@ impl XRRenderState { XRRenderStateBinding::Wrap, ) } + + pub fn copy(&self) -> DomRoot { + XRRenderState::new( + &self.global(), + self.depth_near.get(), + self.depth_far.get(), + self.layer.get().as_ref().map(|x| &**x), + ) + } + + pub fn set_depth_near(&self, depth: f64) { + self.depth_near.set(depth) + } + pub fn set_depth_far(&self, depth: f64) { + self.depth_far.set(depth) + } + pub fn set_layer(&self, layer: Option<&XRLayer>) { + self.layer.set(layer) + } } impl XRRenderStateMethods for XRRenderState { diff --git a/components/script/dom/xrsession.rs b/components/script/dom/xrsession.rs index ea32bdfc1f6e..06a93060db22 100644 --- a/components/script/dom/xrsession.rs +++ b/components/script/dom/xrsession.rs @@ -12,7 +12,7 @@ use crate::dom::bindings::codegen::Bindings::XRSessionBinding::XRFrameRequestCal use crate::dom::bindings::codegen::Bindings::XRSessionBinding::XRSessionMethods; use crate::dom::bindings::error::Error; use crate::dom::bindings::reflector::{reflect_dom_object, DomObject}; -use crate::dom::bindings::root::{DomRoot, MutNullableDom}; +use crate::dom::bindings::root::{DomRoot, MutDom, MutNullableDom}; use crate::dom::eventtarget::EventTarget; use crate::dom::globalscope::GlobalScope; use crate::dom::promise::Promise; @@ -23,6 +23,7 @@ use crate::dom::xrrenderstate::XRRenderState; use crate::dom::xrspace::XRSpace; use dom_struct::dom_struct; use euclid::Vector3D; +use std::cell::Cell; use std::rc::Rc; use webxr_api::Session; @@ -34,10 +35,13 @@ pub struct XRSession { viewer_space: MutNullableDom, #[ignore_malloc_size_of = "defined in webxr"] session: Session, + frame_requested: Cell, + pending_render_state: MutNullableDom, + active_render_state: MutDom, } impl XRSession { - fn new_inherited(session: Session) -> XRSession { + fn new_inherited(session: Session, render_state: &XRRenderState) -> XRSession { XRSession { eventtarget: EventTarget::new_inherited(), base_layer: Default::default(), @@ -45,12 +49,16 @@ impl XRSession { blend_mode: XREnvironmentBlendMode::Opaque, viewer_space: Default::default(), session, + frame_requested: Cell::new(false), + pending_render_state: MutNullableDom::new(None), + active_render_state: MutDom::new(render_state), } } pub fn new(global: &GlobalScope, session: Session) -> DomRoot { + let render_state = XRRenderState::new(global, 0.1, 1000.0, None); reflect_dom_object( - Box::new(XRSession::new_inherited(session)), + Box::new(XRSession::new_inherited(session, &render_state)), global, XRSessionBinding::Wrap, ) @@ -77,12 +85,31 @@ impl XRSessionMethods for XRSession { // https://immersive-web.github.io/webxr/#dom-xrsession-renderstate fn RenderState(&self) -> DomRoot { - unimplemented!() + self.active_render_state.get() } - /// https://immersive-web.github.io/webxr/#dom-xrsession-requestanimationframe - fn UpdateRenderState(&self, init: &XRRenderStateInit, comp: InCompartment) -> Rc { - unimplemented!() + /// https://immersive-web.github.io/webxr/#dom-xrsession-updaterenderstate + fn UpdateRenderState(&self, init: &XRRenderStateInit, _: InCompartment) { + // XXXManishearth various checks: + // If session’s ended value is true, throw an InvalidStateError and abort these steps + // If newState’s baseLayer's was created with an XRSession other than session, + // throw an InvalidStateError and abort these steps + // If newState’s inlineVerticalFieldOfView is set and session is an + // immersive session, throw an InvalidStateError and abort these steps. + + let pending = self + .pending_render_state + .or_init(|| self.active_render_state.get().copy()); + if let Some(near) = init.depthNear { + pending.set_depth_near(*near); + } + if let Some(far) = init.depthFar { + pending.set_depth_far(*far); + } + if let Some(ref layer) = init.baseLayer { + pending.set_layer(Some(&layer)) + } + // XXXManishearth handle inlineVerticalFieldOfView } /// https://immersive-web.github.io/webxr/#dom-xrsession-requestanimationframe