Fill in XR frame/pose/view implementations

This commit is contained in:
Manish Goregaokar 2018-12-21 15:20:51 -08:00
parent 7e043a33f1
commit 28dff81dbf
12 changed files with 152 additions and 38 deletions

View file

@ -153,7 +153,7 @@ impl NavigatorMethods for Navigator {
let displays = self.Xr().get_displays(); let displays = self.Xr().get_displays();
match displays { match displays {
Ok(displays) => promise.resolve_native(&displays), Ok(displays) => promise.resolve_native(&displays),
Err(e) => promise.reject_error(Error::Security), Err(_) => promise.reject_error(Error::Security),
} }
promise promise
} }

View file

@ -683,7 +683,8 @@ impl VRDisplay {
self.global().pipeline_id(), self.global().pipeline_id(),
self.display.borrow().display_id, self.display.borrow().display_id,
sender, sender,
)).unwrap(); ))
.unwrap();
if let Ok(()) = receiver.recv().unwrap() { if let Ok(()) = receiver.recv().unwrap() {
*self.layer.borrow_mut() = layer_bounds; *self.layer.borrow_mut() = layer_bounds;

View file

@ -71,8 +71,9 @@ impl VRFrameData {
} }
} }
/// FIXME(#22526) this should be in a better place
#[allow(unsafe_code)] #[allow(unsafe_code)]
fn create_typed_array(cx: *mut JSContext, src: &[f32], dst: &Heap<*mut JSObject>) { pub fn create_typed_array(cx: *mut JSContext, src: &[f32], dst: &Heap<*mut JSObject>) {
rooted!(in (cx) let mut array = ptr::null_mut::<JSObject>()); rooted!(in (cx) let mut array = ptr::null_mut::<JSObject>());
unsafe { unsafe {
let _ = Float32Array::create(cx, CreateWith::Slice(src), array.handle_mut()); let _ = Float32Array::create(cx, CreateWith::Slice(src), array.handle_mut());

View file

@ -5,8 +5,8 @@
// https://immersive-web.github.io/webxr/#xrframe-interface // https://immersive-web.github.io/webxr/#xrframe-interface
[SecureContext, Exposed=Window] interface XRFrame { [SecureContext, Exposed=Window] interface XRFrame {
// readonly attribute XRSession session; readonly attribute XRSession session;
// XRViewerPose? getViewerPose(optional XRReferenceSpace referenceSpace); XRViewerPose? getViewerPose(optional XRReferenceSpace referenceSpace);
// XRInputPose? getInputPose(XRInputSource inputSource, optional XRReferenceSpace referenceSpace); // XRInputPose? getInputPose(XRInputSource inputSource, optional XRReferenceSpace referenceSpace);
}; };

View file

@ -11,7 +11,7 @@ enum XREye {
[SecureContext, Exposed=Window] interface XRView { [SecureContext, Exposed=Window] interface XRView {
readonly attribute XREye eye; readonly attribute XREye eye;
// readonly attribute Float32Array projectionMatrix; readonly attribute Float32Array projectionMatrix;
// readonly attribute Float32Array viewMatrix; readonly attribute Float32Array viewMatrix;
// readonly attribute XRRigidTransform transform; // readonly attribute XRRigidTransform transform;
}; };

View file

@ -7,4 +7,6 @@
[SecureContext, Exposed=Window] interface XRViewerPose { [SecureContext, Exposed=Window] interface XRViewerPose {
// readonly attribute XRRigidTransform transform; // readonly attribute XRRigidTransform transform;
// readonly attribute FrozenArray<XRView> views; // readonly attribute FrozenArray<XRView> views;
// workaround until we have FrozenArray
sequence<XRView> views();
}; };

View file

@ -119,7 +119,7 @@ impl XR {
self.sync_display(&display); self.sync_display(&display);
} }
}, },
Err(e) => return Err(()), Err(_) => return Err(()),
} }
} else { } else {
// WebVR spec: The Promise MUST be rejected if WebVR is not enabled/supported. // WebVR spec: The Promise MUST be rejected if WebVR is not enabled/supported.
@ -127,7 +127,8 @@ impl XR {
} }
// convert from Dom to DomRoot // convert from Dom to DomRoot
Ok(self.displays Ok(self
.displays
.borrow() .borrow()
.iter() .iter()
.map(|d| DomRoot::from_ref(&**d)) .map(|d| DomRoot::from_ref(&**d))

View file

@ -3,28 +3,63 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use crate::dom::bindings::codegen::Bindings::XRFrameBinding; use crate::dom::bindings::codegen::Bindings::XRFrameBinding;
use crate::dom::bindings::reflector::{reflect_dom_object, Reflector}; use crate::dom::bindings::codegen::Bindings::XRFrameBinding::XRFrameMethods;
use crate::dom::bindings::root::DomRoot; use crate::dom::bindings::codegen::Bindings::XRViewBinding::XREye;
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector};
use crate::dom::bindings::root::{Dom, DomRoot};
use crate::dom::globalscope::GlobalScope; use crate::dom::globalscope::GlobalScope;
use crate::dom::xrreferencespace::XRReferenceSpace;
use crate::dom::xrsession::XRSession;
use crate::dom::xrview::XRView;
use crate::dom::xrviewerpose::XRViewerPose;
use dom_struct::dom_struct; use dom_struct::dom_struct;
use webvr_traits::WebVRFrameData;
#[dom_struct] #[dom_struct]
pub struct XRFrame { pub struct XRFrame {
reflector_: Reflector, reflector_: Reflector,
session: Dom<XRSession>,
#[ignore_malloc_size_of = "defined in rust-webvr"]
data: WebVRFrameData,
} }
impl XRFrame { impl XRFrame {
fn new_inherited() -> XRFrame { fn new_inherited(session: &XRSession, data: WebVRFrameData) -> XRFrame {
XRFrame { XRFrame {
reflector_: Reflector::new(), reflector_: Reflector::new(),
session: Dom::from_ref(session),
data,
} }
} }
pub fn new(global: &GlobalScope) -> DomRoot<XRFrame> { pub fn new(
global: &GlobalScope,
session: &XRSession,
data: WebVRFrameData,
) -> DomRoot<XRFrame> {
reflect_dom_object( reflect_dom_object(
Box::new(XRFrame::new_inherited()), Box::new(XRFrame::new_inherited(session, data)),
global, global,
XRFrameBinding::Wrap, XRFrameBinding::Wrap,
) )
} }
} }
impl XRFrameMethods for XRFrame {
fn Session(&self) -> DomRoot<XRSession> {
DomRoot::from_ref(&self.session)
}
fn GetViewerPose(&self, reference: Option<&XRReferenceSpace>) -> Option<DomRoot<XRViewerPose>> {
// We assume the reference space is eye level for now
// since it's the only one 3DOF devices support
if reference.is_some() {
// it's not possible to obtain a reference
// space at all yet
return None;
}
let left = XRView::new(&self.global(), &self.session, XREye::Left, &self.data);
let right = XRView::new(&self.global(), &self.session, XREye::Right, &self.data);
Some(XRViewerPose::new(&self.global(), &left, &right))
}
}

View file

@ -7,14 +7,20 @@ use crate::dom::bindings::codegen::Bindings::XRViewBinding::{XREye, XRViewMethod
use crate::dom::bindings::reflector::{reflect_dom_object, Reflector}; use crate::dom::bindings::reflector::{reflect_dom_object, Reflector};
use crate::dom::bindings::root::{Dom, DomRoot}; use crate::dom::bindings::root::{Dom, DomRoot};
use crate::dom::globalscope::GlobalScope; use crate::dom::globalscope::GlobalScope;
use crate::dom::vrframedata::create_typed_array;
use crate::dom::xrsession::XRSession; use crate::dom::xrsession::XRSession;
use dom_struct::dom_struct; use dom_struct::dom_struct;
use js::jsapi::{Heap, JSContext, JSObject};
use std::ptr::NonNull;
use webvr_traits::WebVRFrameData;
#[dom_struct] #[dom_struct]
pub struct XRView { pub struct XRView {
reflector_: Reflector, reflector_: Reflector,
session: Dom<XRSession>, session: Dom<XRSession>,
eye: XREye, eye: XREye,
proj: Heap<*mut JSObject>,
view: Heap<*mut JSObject>,
} }
impl XRView { impl XRView {
@ -22,16 +28,34 @@ impl XRView {
XRView { XRView {
reflector_: Reflector::new(), reflector_: Reflector::new(),
session: Dom::from_ref(session), session: Dom::from_ref(session),
eye eye,
proj: Heap::default(),
view: Heap::default(),
} }
} }
pub fn new(global: &GlobalScope, session: &XRSession, eye: XREye) -> DomRoot<XRView> { pub fn new(
reflect_dom_object( global: &GlobalScope,
session: &XRSession,
eye: XREye,
data: &WebVRFrameData,
) -> DomRoot<XRView> {
let ret = reflect_dom_object(
Box::new(XRView::new_inherited(session, eye)), Box::new(XRView::new_inherited(session, eye)),
global, global,
XRViewBinding::Wrap, XRViewBinding::Wrap,
) );
let (proj, view) = if eye == XREye::Left {
(&data.left_projection_matrix, &data.left_view_matrix)
} else {
(&data.right_projection_matrix, &data.right_view_matrix)
};
let cx = global.get_cx();
create_typed_array(cx, proj, &ret.proj);
create_typed_array(cx, view, &ret.view);
ret
} }
pub fn session(&self) -> &XRSession { pub fn session(&self) -> &XRSession {
@ -44,4 +68,16 @@ impl XRViewMethods for XRView {
fn Eye(&self) -> XREye { fn Eye(&self) -> XREye {
self.eye self.eye
} }
}
#[allow(unsafe_code)]
/// https://immersive-web.github.io/webxr/#dom-xrview-projectionmatrix
unsafe fn ProjectionMatrix(&self, _cx: *mut JSContext) -> NonNull<JSObject> {
NonNull::new_unchecked(self.proj.get())
}
#[allow(unsafe_code)]
/// https://immersive-web.github.io/webxr/#dom-xrview-projectionmatrix
unsafe fn ViewMatrix(&self, _cx: *mut JSContext) -> NonNull<JSObject> {
NonNull::new_unchecked(self.view.get())
}
}

View file

@ -3,28 +3,43 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use crate::dom::bindings::codegen::Bindings::XRViewerPoseBinding; use crate::dom::bindings::codegen::Bindings::XRViewerPoseBinding;
use crate::dom::bindings::codegen::Bindings::XRViewerPoseBinding::XRViewerPoseMethods;
use crate::dom::bindings::reflector::{reflect_dom_object, Reflector}; 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::globalscope::GlobalScope;
use crate::dom::xrview::XRView;
use dom_struct::dom_struct; use dom_struct::dom_struct;
#[dom_struct] #[dom_struct]
pub struct XRViewerPose { pub struct XRViewerPose {
reflector_: Reflector, reflector_: Reflector,
left: Dom<XRView>,
right: Dom<XRView>,
} }
impl XRViewerPose { impl XRViewerPose {
fn new_inherited() -> XRViewerPose { fn new_inherited(left: &XRView, right: &XRView) -> XRViewerPose {
XRViewerPose { XRViewerPose {
reflector_: Reflector::new(), reflector_: Reflector::new(),
left: Dom::from_ref(left),
right: Dom::from_ref(right),
} }
} }
pub fn new(global: &GlobalScope) -> DomRoot<XRViewerPose> { pub fn new(global: &GlobalScope, left: &XRView, right: &XRView) -> DomRoot<XRViewerPose> {
reflect_dom_object( reflect_dom_object(
Box::new(XRViewerPose::new_inherited()), Box::new(XRViewerPose::new_inherited(left, right)),
global, global,
XRViewerPoseBinding::Wrap, XRViewerPoseBinding::Wrap,
) )
} }
} }
impl XRViewerPoseMethods for XRViewerPose {
fn Views(&self) -> Vec<DomRoot<XRView>> {
vec![
DomRoot::from_ref(&self.left),
DomRoot::from_ref(&self.right),
]
}
}

View file

@ -22,12 +22,20 @@ impl XRViewport {
fn new_inherited(x: u32, y: u32, width: u32, height: u32) -> XRViewport { fn new_inherited(x: u32, y: u32, width: u32, height: u32) -> XRViewport {
XRViewport { XRViewport {
reflector_: Reflector::new(), reflector_: Reflector::new(),
x, y, width, height x,
y,
width,
height,
} }
} }
pub fn new(global: &GlobalScope, pub fn new(
x: u32, y: u32, width: u32, height: u32) -> DomRoot<XRViewport> { global: &GlobalScope,
x: u32,
y: u32,
width: u32,
height: u32,
) -> DomRoot<XRViewport> {
reflect_dom_object( reflect_dom_object(
Box::new(XRViewport::new_inherited(x, y, width, height)), Box::new(XRViewport::new_inherited(x, y, width, height)),
global, global,
@ -56,4 +64,4 @@ impl XRViewportMethods for XRViewport {
fn Height(&self) -> i32 { fn Height(&self) -> i32 {
self.height as i32 self.height as i32
} }
} }

View file

@ -4,10 +4,10 @@
use crate::dom::bindings::codegen::Bindings::XRViewBinding::{XREye, XRViewMethods}; use crate::dom::bindings::codegen::Bindings::XRViewBinding::{XREye, XRViewMethods};
use crate::dom::bindings::codegen::Bindings::XRWebGLLayerBinding; use crate::dom::bindings::codegen::Bindings::XRWebGLLayerBinding;
use crate::dom::bindings::codegen::Bindings::XRWebGLLayerBinding::XRWebGLLayerMethods;
use crate::dom::bindings::codegen::Bindings::XRWebGLLayerBinding::XRWebGLLayerInit; use crate::dom::bindings::codegen::Bindings::XRWebGLLayerBinding::XRWebGLLayerInit;
use crate::dom::bindings::codegen::Bindings::XRWebGLLayerBinding::XRWebGLLayerMethods;
use crate::dom::bindings::error::Fallible; use crate::dom::bindings::error::Fallible;
use crate::dom::bindings::reflector::{DomObject, reflect_dom_object}; use crate::dom::bindings::reflector::{reflect_dom_object, DomObject};
use crate::dom::bindings::root::{Dom, DomRoot}; use crate::dom::bindings::root::{Dom, DomRoot};
use crate::dom::globalscope::GlobalScope; use crate::dom::globalscope::GlobalScope;
use crate::dom::webglrenderingcontext::WebGLRenderingContext; use crate::dom::webglrenderingcontext::WebGLRenderingContext;
@ -32,8 +32,11 @@ pub struct XRWebGLLayer {
} }
impl XRWebGLLayer { impl XRWebGLLayer {
pub fn new_inherited(session: &XRSession, context: &WebGLRenderingContext, pub fn new_inherited(
init: &XRWebGLLayerInit) -> XRWebGLLayer { session: &XRSession,
context: &WebGLRenderingContext,
init: &XRWebGLLayerInit,
) -> XRWebGLLayer {
XRWebGLLayer { XRWebGLLayer {
xrlayer: XRLayer::new_inherited(), xrlayer: XRLayer::new_inherited(),
antialias: Cell::new(init.antialias), antialias: Cell::new(init.antialias),
@ -45,8 +48,12 @@ impl XRWebGLLayer {
} }
} }
pub fn new(global: &GlobalScope, session: &XRSession, context: &WebGLRenderingContext, pub fn new(
init: &XRWebGLLayerInit) -> DomRoot<XRWebGLLayer> { global: &GlobalScope,
session: &XRSession,
context: &WebGLRenderingContext,
init: &XRWebGLLayerInit,
) -> DomRoot<XRWebGLLayer> {
reflect_dom_object( reflect_dom_object(
Box::new(XRWebGLLayer::new_inherited(session, context, init)), Box::new(XRWebGLLayer::new_inherited(session, context, init)),
global, global,
@ -54,9 +61,12 @@ impl XRWebGLLayer {
) )
} }
pub fn Constructor(global: &Window, session: &XRSession, pub fn Constructor(
context: &WebGLRenderingContext, global: &Window,
init: &XRWebGLLayerInit) -> Fallible<DomRoot<Self>> { session: &XRSession,
context: &WebGLRenderingContext,
init: &XRWebGLLayerInit,
) -> Fallible<DomRoot<Self>> {
Ok(XRWebGLLayer::new(&global.global(), session, context, init)) Ok(XRWebGLLayer::new(&global.global(), session, context, init))
} }
} }
@ -97,7 +107,12 @@ impl XRWebGLLayerMethods for XRWebGLLayer {
// XXXManishearth this assumes the WebVR default of canvases being cut in half // 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 // which need not be generally true for all devices, and will not work in
// inline VR mode // inline VR mode
Some(XRViewport::new(&self.global(), x, 0, size.width / 2, size.height)) Some(XRViewport::new(
&self.global(),
x,
0,
size.width / 2,
size.height,
))
} }
} }