From b654b6007a0673be6297443dbdf1d5d39e91a670 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Wed, 10 Jul 2019 13:46:23 -0700 Subject: [PATCH] Hook input code into new webxr crate --- components/script/dom/bindings/trace.rs | 7 ++++- components/script/dom/vrdisplay.rs | 25 ++-------------- components/script/dom/xrinputsource.rs | 38 +++++++++---------------- components/script/dom/xrsession.rs | 24 +++++++++++++--- components/script/dom/xrspace.rs | 15 ++++++++-- 5 files changed, 54 insertions(+), 55 deletions(-) diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs index 889036eff06..9579ab99ad8 100644 --- a/components/script/dom/bindings/trace.rs +++ b/components/script/dom/bindings/trace.rs @@ -486,7 +486,12 @@ unsafe_no_jsmanaged_fields!(WebGLVersion); unsafe_no_jsmanaged_fields!(WebGLSLVersion); unsafe_no_jsmanaged_fields!(MediaList); unsafe_no_jsmanaged_fields!(WebVRGamepadData, WebVRGamepadState, WebVRGamepadHand); -unsafe_no_jsmanaged_fields!(webxr_api::Registry, webxr_api::Session, webxr_api::Frame); +unsafe_no_jsmanaged_fields!( + webxr_api::Registry, + webxr_api::Session, + webxr_api::Frame, + webxr_api::InputSource +); unsafe_no_jsmanaged_fields!(ScriptToConstellationChan); unsafe_no_jsmanaged_fields!(InteractiveMetrics); unsafe_no_jsmanaged_fields!(InteractiveWindow); diff --git a/components/script/dom/vrdisplay.rs b/components/script/dom/vrdisplay.rs index 9e17abb18dc..462b1651eb3 100644 --- a/components/script/dom/vrdisplay.rs +++ b/components/script/dom/vrdisplay.rs @@ -20,7 +20,7 @@ use crate::dom::bindings::inheritance::Castable; use crate::dom::bindings::num::Finite; use crate::dom::bindings::refcounted::{Trusted, TrustedPromise}; use crate::dom::bindings::reflector::{reflect_dom_object, DomObject}; -use crate::dom::bindings::root::{Dom, DomRoot, MutDom, MutNullableDom}; +use crate::dom::bindings::root::{DomRoot, MutDom, MutNullableDom}; use crate::dom::bindings::str::DOMString; use crate::dom::event::Event; use crate::dom::eventtarget::EventTarget; @@ -33,7 +33,6 @@ use crate::dom::vrframedata::VRFrameData; use crate::dom::vrpose::VRPose; use crate::dom::vrstageparameters::VRStageParameters; use crate::dom::webglrenderingcontext::WebGLRenderingContext; -use crate::dom::xrinputsource::XRInputSource; use crate::script_runtime::CommonScriptMsg; use crate::script_runtime::ScriptThreadEventCategory::WebVREvent; use crate::task_source::{TaskSource, TaskSourceName}; @@ -43,7 +42,6 @@ use dom_struct::dom_struct; use ipc_channel::ipc::IpcSender; use profile_traits::ipc; use std::cell::Cell; -use std::collections::HashMap; use std::mem; use std::ops::Deref; use std::rc::Rc; @@ -85,10 +83,6 @@ pub struct VRDisplay { running_display_raf: Cell, paused: Cell, stopped_on_pause: Cell, - /// Have inputs been initialized? (i.e, has getInputSources() been called?) - /// XR only - initialized_inputs: Cell, - input_sources: DomRefCell>>, } unsafe_no_jsmanaged_fields!(WebVRDisplayData); @@ -112,8 +106,6 @@ struct VRRAFUpdate { /// Number uniquely identifying the WebGL context /// so that we may setup/tear down VR compositors as things change context_id: usize, - /// Do we need input data? - needs_inputs: bool, } type VRRAFUpdateSender = Sender>; @@ -161,8 +153,6 @@ impl VRDisplay { // This flag is set when the Display was presenting when it received a VR Pause event. // When the VR Resume event is received and the flag is set, VR presentation automatically restarts. stopped_on_pause: Cell::new(false), - initialized_inputs: Cell::new(false), - input_sources: DomRefCell::new(HashMap::new()), } } @@ -610,7 +600,6 @@ impl VRDisplay { depth_far: self.depth_far.get(), api_sender: self.api_sender(), context_id: self.context_id(), - needs_inputs: self.initialized_inputs.get(), } } @@ -635,7 +624,6 @@ impl VRDisplay { let (raf_sender, raf_receiver) = unbounded(); let (wakeup_sender, wakeup_receiver) = unbounded(); *self.raf_wakeup_sender.borrow_mut() = Some(wakeup_sender); - let mut needs_inputs = false; // The render loop at native headset frame rate is implemented using a dedicated thread. // Every loop iteration syncs pose data with the HMD, submits the pixels to the display and waits for Vsync. @@ -676,7 +664,7 @@ impl VRDisplay { display_id, near, far, - needs_inputs, + false, sync_sender.clone(), ); api_sender.send_vr(msg).unwrap(); @@ -702,7 +690,6 @@ impl VRDisplay { if let Ok(update) = raf_receiver.recv().unwrap() { near = update.depth_near; far = update.depth_far; - needs_inputs = update.needs_inputs; if update.context_id != context_id { if let Some(ref api_sender) = update.api_sender { api_sender @@ -759,14 +746,6 @@ impl VRDisplay { match receiver.recv().unwrap() { Ok(pose) => { *self.frame_data.borrow_mut() = pose.frame.block(); - if self.initialized_inputs.get() { - let inputs = self.input_sources.borrow(); - for (id, state) in pose.gamepads { - if let Some(input) = inputs.get(&id) { - input.update_state(state); - } - } - } VRFrameDataStatus::Synced }, Err(()) => VRFrameDataStatus::Exit, diff --git a/components/script/dom/xrinputsource.rs b/components/script/dom/xrinputsource.rs index 108ca16b9fc..061f746016a 100644 --- a/components/script/dom/xrinputsource.rs +++ b/components/script/dom/xrinputsource.rs @@ -2,7 +2,6 @@ * 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::cell::DomRefCell; use crate::dom::bindings::codegen::Bindings::XRInputSourceBinding; use crate::dom::bindings::codegen::Bindings::XRInputSourceBinding::{ XRHandedness, XRInputSourceMethods, @@ -10,33 +9,27 @@ use crate::dom::bindings::codegen::Bindings::XRInputSourceBinding::{ use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector}; use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom}; use crate::dom::globalscope::GlobalScope; -use crate::dom::xrsession::{ApiPose, XRSession}; +use crate::dom::xrsession::XRSession; use crate::dom::xrspace::XRSpace; use dom_struct::dom_struct; -use webvr_traits::{WebVRGamepadData, WebVRGamepadHand, WebVRGamepadState}; +use webxr_api::{Handedness, InputId, InputSource}; #[dom_struct] pub struct XRInputSource { reflector: Reflector, session: Dom, #[ignore_malloc_size_of = "Defined in rust-webvr"] - data: WebVRGamepadData, + info: InputSource, #[ignore_malloc_size_of = "Defined in rust-webvr"] - state: DomRefCell, target_ray_space: MutNullableDom, } impl XRInputSource { - pub fn new_inherited( - session: &XRSession, - data: WebVRGamepadData, - state: WebVRGamepadState, - ) -> XRInputSource { + pub fn new_inherited(session: &XRSession, info: InputSource) -> XRInputSource { XRInputSource { reflector: Reflector::new(), session: Dom::from_ref(session), - data, - state: DomRefCell::new(state), + info, target_ray_space: Default::default(), } } @@ -44,32 +37,27 @@ impl XRInputSource { pub fn new( global: &GlobalScope, session: &XRSession, - data: WebVRGamepadData, - state: WebVRGamepadState, + info: InputSource, ) -> DomRoot { reflect_dom_object( - Box::new(XRInputSource::new_inherited(session, data, state)), + Box::new(XRInputSource::new_inherited(session, info)), global, XRInputSourceBinding::Wrap, ) } - pub fn update_state(&self, state: WebVRGamepadState) { - *self.state.borrow_mut() = state; - } - - pub fn pose(&self) -> ApiPose { - unimplemented!() + pub fn id(&self) -> InputId { + self.info.id } } impl XRInputSourceMethods for XRInputSource { /// https://immersive-web.github.io/webxr/#dom-xrinputsource-handedness fn Handedness(&self) -> XRHandedness { - match self.data.hand { - WebVRGamepadHand::Unknown => XRHandedness::None, - WebVRGamepadHand::Left => XRHandedness::Left, - WebVRGamepadHand::Right => XRHandedness::Right, + match self.info.handedness { + Handedness::None => XRHandedness::None, + Handedness::Left => XRHandedness::Left, + Handedness::Right => XRHandedness::Right, } } diff --git a/components/script/dom/xrsession.rs b/components/script/dom/xrsession.rs index 9a0dfdb3454..da54753b337 100644 --- a/components/script/dom/xrsession.rs +++ b/components/script/dom/xrsession.rs @@ -19,7 +19,7 @@ use crate::dom::bindings::inheritance::Castable; use crate::dom::bindings::num::Finite; use crate::dom::bindings::refcounted::Trusted; use crate::dom::bindings::reflector::{reflect_dom_object, DomObject}; -use crate::dom::bindings::root::{DomRoot, MutDom, MutNullableDom}; +use crate::dom::bindings::root::{Dom, DomRoot, MutDom, MutNullableDom}; use crate::dom::eventtarget::EventTarget; use crate::dom::globalscope::GlobalScope; use crate::dom::promise::Promise; @@ -58,6 +58,7 @@ pub struct XRSession { raf_callback_list: DomRefCell>)>>, #[ignore_malloc_size_of = "defined in ipc-channel"] raf_sender: DomRefCell>>, + input_sources: DomRefCell>>, } impl XRSession { @@ -76,16 +77,27 @@ impl XRSession { next_raf_id: Cell::new(0), raf_callback_list: DomRefCell::new(vec![]), raf_sender: DomRefCell::new(None), + input_sources: DomRefCell::new(vec![]), } } pub fn new(global: &GlobalScope, session: Session) -> DomRoot { let render_state = XRRenderState::new(global, 0.1, 1000.0, None); - reflect_dom_object( + let ret = reflect_dom_object( Box::new(XRSession::new_inherited(session, &render_state)), global, XRSessionBinding::Wrap, - ) + ); + { + let mut input_sources = ret.input_sources.borrow_mut(); + for info in ret.session.borrow().initial_inputs() { + // XXXManishearth we should be able to listen for updates + // to the input sources + let input = XRInputSource::new(global, &ret, *info); + input_sources.push(Dom::from_ref(&input)); + } + } + ret } pub fn with_session(&self, with: F) { @@ -268,7 +280,11 @@ impl XRSessionMethods for XRSession { /// https://immersive-web.github.io/webxr/#dom-xrsession-getinputsources fn GetInputSources(&self) -> Vec> { - unimplemented!() + self.input_sources + .borrow() + .iter() + .map(|x| DomRoot::from_ref(&**x)) + .collect() } } diff --git a/components/script/dom/xrspace.rs b/components/script/dom/xrspace.rs index ad76be52518..6fa00d1cffe 100644 --- a/components/script/dom/xrspace.rs +++ b/components/script/dom/xrspace.rs @@ -10,7 +10,7 @@ use crate::dom::eventtarget::EventTarget; use crate::dom::globalscope::GlobalScope; use crate::dom::xrinputsource::XRInputSource; use crate::dom::xrreferencespace::XRReferenceSpace; -use crate::dom::xrsession::{ApiPose, XRSession}; +use crate::dom::xrsession::{cast_transform, ApiPose, XRSession}; use dom_struct::dom_struct; use webxr_api::Frame; @@ -61,7 +61,18 @@ impl XRSpace { if let Some(reference) = self.downcast::() { reference.get_pose(base_pose) } else if let Some(source) = self.input_source.get() { - source.pose() + // XXXManishearth we should be able to request frame information + // for inputs when necessary instead of always loading it + // + // Also, the below code is quadratic, so this API may need an overhaul anyway + let id = source.id(); + // XXXManishearth once we have dynamic inputs we'll need to handle this better + let frame = base_pose + .inputs + .iter() + .find(|i| i.id == id) + .expect("no input found"); + cast_transform(frame.target_ray_origin) } else { unreachable!() }