diff --git a/components/script/dom/mod.rs b/components/script/dom/mod.rs index 3ecb76bba66..253dc2b54bb 100644 --- a/components/script/dom/mod.rs +++ b/components/script/dom/mod.rs @@ -527,4 +527,5 @@ pub mod xrspace; pub mod xrstationaryreferencespace; pub mod xrview; pub mod xrviewerpose; +pub mod xrviewport; pub mod xrwebgllayer; diff --git a/components/script/dom/webglrenderingcontext.rs b/components/script/dom/webglrenderingcontext.rs index c7896b42436..376da84486d 100644 --- a/components/script/dom/webglrenderingcontext.rs +++ b/components/script/dom/webglrenderingcontext.rs @@ -157,6 +157,7 @@ pub struct WebGLRenderingContext { current_scissor: Cell<(i32, i32, u32, u32)>, #[ignore_malloc_size_of = "Because it's small"] current_clear_color: Cell<(f32, f32, f32, f32)>, + size: Cell>, extension_manager: WebGLExtensions, capabilities: Capabilities, default_vao: DomOnceCell, @@ -211,6 +212,7 @@ impl WebGLRenderingContext { current_program: MutNullableDom::new(None), current_vertex_attrib_0: Cell::new((0f32, 0f32, 0f32, 1f32)), current_scissor: Cell::new((0, 0, size.width, size.height)), + size: Cell::new(size), current_clear_color: Cell::new((0.0, 0.0, 0.0, 0.0)), extension_manager: WebGLExtensions::new(webgl_version), capabilities: Default::default(), @@ -266,6 +268,7 @@ impl WebGLRenderingContext { pub fn recreate(&self, size: Size2D) { let (sender, receiver) = webgl_channel().unwrap(); self.webgl_sender.send_resize(size, sender).unwrap(); + self.size.set(size); if let Err(msg) = receiver.recv().unwrap() { error!("Error resizing WebGLContext: {}", msg); @@ -340,6 +343,10 @@ impl WebGLRenderingContext { } } + pub fn size(&self) -> Size2D { + self.size.get() + } + // Helper function for validating framebuffer completeness in // calls touching the framebuffer. From the GLES 2.0.25 spec, // page 119: diff --git a/components/script/dom/webidls/XRSession.webidl b/components/script/dom/webidls/XRSession.webidl index b0785764a18..546a7dcab2f 100644 --- a/components/script/dom/webidls/XRSession.webidl +++ b/components/script/dom/webidls/XRSession.webidl @@ -10,6 +10,8 @@ enum XREnvironmentBlendMode { "alpha-blend", }; +callback XRFrameRequestCallback = void (DOMHighResTimeStamp time, XRFrame frame); + [SecureContext, Exposed=Window] interface XRSession : EventTarget { // // Attributes readonly attribute XRSessionMode mode; diff --git a/components/script/dom/webidls/XRView.webidl b/components/script/dom/webidls/XRView.webidl index 17c804009de..9d0c894f8a3 100644 --- a/components/script/dom/webidls/XRView.webidl +++ b/components/script/dom/webidls/XRView.webidl @@ -10,7 +10,7 @@ enum XREye { }; [SecureContext, Exposed=Window] interface XRView { - // readonly attribute XREye eye; + readonly attribute XREye eye; // readonly attribute Float32Array projectionMatrix; // readonly attribute Float32Array viewMatrix; // readonly attribute XRRigidTransform transform; diff --git a/components/script/dom/webidls/XRViewport.webidl b/components/script/dom/webidls/XRViewport.webidl new file mode 100644 index 00000000000..fb68099fa86 --- /dev/null +++ b/components/script/dom/webidls/XRViewport.webidl @@ -0,0 +1,12 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * 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/. */ + +// https://immersive-web.github.io/webxr/#xrviewport-interface + +[SecureContext, Exposed=Window] interface XRViewport { + readonly attribute long x; + readonly attribute long y; + readonly attribute long width; + readonly attribute long height; +}; \ No newline at end of file diff --git a/components/script/dom/webidls/XRWebGLLayer.webidl b/components/script/dom/webidls/XRWebGLLayer.webidl index 8f66ac625d9..9f208ddc5f9 100644 --- a/components/script/dom/webidls/XRWebGLLayer.webidl +++ b/components/script/dom/webidls/XRWebGLLayer.webidl @@ -34,7 +34,7 @@ interface XRWebGLLayer : XRLayer { // readonly attribute unsigned long framebufferHeight; // // Methods - // XRViewport? getViewport(XRView view); + XRViewport? getViewport(XRView view); // void requestViewportScaling(double viewportScaleFactor); // // Static Methods diff --git a/components/script/dom/xrview.rs b/components/script/dom/xrview.rs index c8f420b016c..f9d538cb946 100644 --- a/components/script/dom/xrview.rs +++ b/components/script/dom/xrview.rs @@ -3,28 +3,45 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ use crate::dom::bindings::codegen::Bindings::XRViewBinding; +use crate::dom::bindings::codegen::Bindings::XRViewBinding::{XREye, XRViewMethods}; use crate::dom::bindings::reflector::{reflect_dom_object, Reflector}; -use crate::dom::bindings::root::DomRoot; +use crate::dom::bindings::root::{Dom, DomRoot}; use crate::dom::globalscope::GlobalScope; +use crate::dom::xrsession::XRSession; use dom_struct::dom_struct; #[dom_struct] pub struct XRView { reflector_: Reflector, + session: Dom, + eye: XREye, } impl XRView { - fn new_inherited() -> XRView { + fn new_inherited(session: &XRSession, eye: XREye) -> XRView { XRView { reflector_: Reflector::new(), + session: Dom::from_ref(session), + eye } } - pub fn new(global: &GlobalScope) -> DomRoot { + pub fn new(global: &GlobalScope, session: &XRSession, eye: XREye) -> DomRoot { reflect_dom_object( - Box::new(XRView::new_inherited()), + Box::new(XRView::new_inherited(session, eye)), global, XRViewBinding::Wrap, ) } + + pub fn session(&self) -> &XRSession { + &self.session + } } + +impl XRViewMethods for XRView { + /// https://immersive-web.github.io/webxr/#dom-xrview-eye + fn Eye(&self) -> XREye { + self.eye + } +} \ No newline at end of file diff --git a/components/script/dom/xrviewport.rs b/components/script/dom/xrviewport.rs new file mode 100644 index 00000000000..a49aaf3bf2f --- /dev/null +++ b/components/script/dom/xrviewport.rs @@ -0,0 +1,59 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * 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 crate::dom::bindings::codegen::Bindings::XRViewportBinding; +use crate::dom::bindings::codegen::Bindings::XRViewportBinding::XRViewportMethods; +use crate::dom::bindings::reflector::{reflect_dom_object, Reflector}; +use crate::dom::bindings::root::DomRoot; +use crate::dom::globalscope::GlobalScope; +use dom_struct::dom_struct; + +#[dom_struct] +pub struct XRViewport { + reflector_: Reflector, + x: u32, + y: u32, + width: u32, + height: u32, +} + +impl XRViewport { + fn new_inherited(x: u32, y: u32, width: u32, height: u32) -> XRViewport { + XRViewport { + reflector_: Reflector::new(), + x, y, width, height + } + } + + pub fn new(global: &GlobalScope, + x: u32, y: u32, width: u32, height: u32) -> DomRoot { + reflect_dom_object( + Box::new(XRViewport::new_inherited(x, y, width, height)), + global, + XRViewportBinding::Wrap, + ) + } +} + +impl XRViewportMethods for XRViewport { + /// https://immersive-web.github.io/webxr/#dom-xrviewport-x + fn X(&self) -> i32 { + self.x as i32 + } + + /// https://immersive-web.github.io/webxr/#dom-xrviewport-y + fn Y(&self) -> i32 { + self.y as i32 + } + + /// https://immersive-web.github.io/webxr/#dom-xrviewport-width + fn Width(&self) -> i32 { + self.height as i32 + } + + /// https://immersive-web.github.io/webxr/#dom-xrviewport-height + fn Height(&self) -> i32 { + self.height as i32 + } +} \ No newline at end of file diff --git a/components/script/dom/xrwebgllayer.rs b/components/script/dom/xrwebgllayer.rs index a34e6913d9e..3aef06642ce 100644 --- a/components/script/dom/xrwebgllayer.rs +++ b/components/script/dom/xrwebgllayer.rs @@ -2,6 +2,7 @@ * 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 crate::dom::bindings::codegen::Bindings::XRViewBinding::{XREye, XRViewMethods}; use crate::dom::bindings::codegen::Bindings::XRWebGLLayerBinding; use crate::dom::bindings::codegen::Bindings::XRWebGLLayerBinding::XRWebGLLayerMethods; use crate::dom::bindings::codegen::Bindings::XRWebGLLayerBinding::XRWebGLLayerInit; @@ -13,6 +14,8 @@ use crate::dom::webglrenderingcontext::WebGLRenderingContext; use crate::dom::window::Window; use crate::dom::xrlayer::XRLayer; use crate::dom::xrsession::XRSession; +use crate::dom::xrview::XRView; +use crate::dom::xrviewport::XRViewport; use dom_struct::dom_struct; use std::cell::Cell; @@ -78,5 +81,23 @@ impl XRWebGLLayerMethods for XRWebGLLayer { fn Context(&self) -> DomRoot { DomRoot::from_ref(&self.context) } + + fn GetViewport(&self, view: &XRView) -> Option> { + if self.session != view.session() { + return None; + } + + let size = self.context.size(); + + let x = if view.Eye() == XREye::Left { + 0 + } else { + size.width / 2 + }; + // XXXManishearth this assumes the WebVR default of canvases being cut in half + // which need not be generally true for all devices, and will not work in + // inline VR mode + Some(XRViewport::new(&self.global(), x, 0, size.width / 2, size.height)) + } }