Hook input code into new webxr crate

This commit is contained in:
Manish Goregaokar 2019-07-10 13:46:23 -07:00
parent 0d5d1a3dc4
commit b654b6007a
5 changed files with 54 additions and 55 deletions

View file

@ -486,7 +486,12 @@ unsafe_no_jsmanaged_fields!(WebGLVersion);
unsafe_no_jsmanaged_fields!(WebGLSLVersion); unsafe_no_jsmanaged_fields!(WebGLSLVersion);
unsafe_no_jsmanaged_fields!(MediaList); unsafe_no_jsmanaged_fields!(MediaList);
unsafe_no_jsmanaged_fields!(WebVRGamepadData, WebVRGamepadState, WebVRGamepadHand); 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!(ScriptToConstellationChan);
unsafe_no_jsmanaged_fields!(InteractiveMetrics); unsafe_no_jsmanaged_fields!(InteractiveMetrics);
unsafe_no_jsmanaged_fields!(InteractiveWindow); unsafe_no_jsmanaged_fields!(InteractiveWindow);

View file

@ -20,7 +20,7 @@ use crate::dom::bindings::inheritance::Castable;
use crate::dom::bindings::num::Finite; use crate::dom::bindings::num::Finite;
use crate::dom::bindings::refcounted::{Trusted, TrustedPromise}; use crate::dom::bindings::refcounted::{Trusted, TrustedPromise};
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject}; 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::bindings::str::DOMString;
use crate::dom::event::Event; use crate::dom::event::Event;
use crate::dom::eventtarget::EventTarget; use crate::dom::eventtarget::EventTarget;
@ -33,7 +33,6 @@ use crate::dom::vrframedata::VRFrameData;
use crate::dom::vrpose::VRPose; use crate::dom::vrpose::VRPose;
use crate::dom::vrstageparameters::VRStageParameters; use crate::dom::vrstageparameters::VRStageParameters;
use crate::dom::webglrenderingcontext::WebGLRenderingContext; use crate::dom::webglrenderingcontext::WebGLRenderingContext;
use crate::dom::xrinputsource::XRInputSource;
use crate::script_runtime::CommonScriptMsg; use crate::script_runtime::CommonScriptMsg;
use crate::script_runtime::ScriptThreadEventCategory::WebVREvent; use crate::script_runtime::ScriptThreadEventCategory::WebVREvent;
use crate::task_source::{TaskSource, TaskSourceName}; use crate::task_source::{TaskSource, TaskSourceName};
@ -43,7 +42,6 @@ use dom_struct::dom_struct;
use ipc_channel::ipc::IpcSender; use ipc_channel::ipc::IpcSender;
use profile_traits::ipc; use profile_traits::ipc;
use std::cell::Cell; use std::cell::Cell;
use std::collections::HashMap;
use std::mem; use std::mem;
use std::ops::Deref; use std::ops::Deref;
use std::rc::Rc; use std::rc::Rc;
@ -85,10 +83,6 @@ pub struct VRDisplay {
running_display_raf: Cell<bool>, running_display_raf: Cell<bool>,
paused: Cell<bool>, paused: Cell<bool>,
stopped_on_pause: Cell<bool>, stopped_on_pause: Cell<bool>,
/// Have inputs been initialized? (i.e, has getInputSources() been called?)
/// XR only
initialized_inputs: Cell<bool>,
input_sources: DomRefCell<HashMap<u32, Dom<XRInputSource>>>,
} }
unsafe_no_jsmanaged_fields!(WebVRDisplayData); unsafe_no_jsmanaged_fields!(WebVRDisplayData);
@ -112,8 +106,6 @@ struct VRRAFUpdate {
/// Number uniquely identifying the WebGL context /// Number uniquely identifying the WebGL context
/// so that we may setup/tear down VR compositors as things change /// so that we may setup/tear down VR compositors as things change
context_id: usize, context_id: usize,
/// Do we need input data?
needs_inputs: bool,
} }
type VRRAFUpdateSender = Sender<Result<VRRAFUpdate, ()>>; type VRRAFUpdateSender = Sender<Result<VRRAFUpdate, ()>>;
@ -161,8 +153,6 @@ impl VRDisplay {
// This flag is set when the Display was presenting when it received a VR Pause event. // 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. // When the VR Resume event is received and the flag is set, VR presentation automatically restarts.
stopped_on_pause: Cell::new(false), 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(), depth_far: self.depth_far.get(),
api_sender: self.api_sender(), api_sender: self.api_sender(),
context_id: self.context_id(), context_id: self.context_id(),
needs_inputs: self.initialized_inputs.get(),
} }
} }
@ -635,7 +624,6 @@ impl VRDisplay {
let (raf_sender, raf_receiver) = unbounded(); let (raf_sender, raf_receiver) = unbounded();
let (wakeup_sender, wakeup_receiver) = unbounded(); let (wakeup_sender, wakeup_receiver) = unbounded();
*self.raf_wakeup_sender.borrow_mut() = Some(wakeup_sender); *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. // 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. // 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, display_id,
near, near,
far, far,
needs_inputs, false,
sync_sender.clone(), sync_sender.clone(),
); );
api_sender.send_vr(msg).unwrap(); api_sender.send_vr(msg).unwrap();
@ -702,7 +690,6 @@ impl VRDisplay {
if let Ok(update) = raf_receiver.recv().unwrap() { if let Ok(update) = raf_receiver.recv().unwrap() {
near = update.depth_near; near = update.depth_near;
far = update.depth_far; far = update.depth_far;
needs_inputs = update.needs_inputs;
if update.context_id != context_id { if update.context_id != context_id {
if let Some(ref api_sender) = update.api_sender { if let Some(ref api_sender) = update.api_sender {
api_sender api_sender
@ -759,14 +746,6 @@ impl VRDisplay {
match receiver.recv().unwrap() { match receiver.recv().unwrap() {
Ok(pose) => { Ok(pose) => {
*self.frame_data.borrow_mut() = pose.frame.block(); *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 VRFrameDataStatus::Synced
}, },
Err(()) => VRFrameDataStatus::Exit, Err(()) => VRFrameDataStatus::Exit,

View file

@ -2,7 +2,6 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * 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;
use crate::dom::bindings::codegen::Bindings::XRInputSourceBinding::{ use crate::dom::bindings::codegen::Bindings::XRInputSourceBinding::{
XRHandedness, XRInputSourceMethods, 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::reflector::{reflect_dom_object, DomObject, Reflector};
use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom}; use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom};
use crate::dom::globalscope::GlobalScope; use crate::dom::globalscope::GlobalScope;
use crate::dom::xrsession::{ApiPose, XRSession}; use crate::dom::xrsession::XRSession;
use crate::dom::xrspace::XRSpace; use crate::dom::xrspace::XRSpace;
use dom_struct::dom_struct; use dom_struct::dom_struct;
use webvr_traits::{WebVRGamepadData, WebVRGamepadHand, WebVRGamepadState}; use webxr_api::{Handedness, InputId, InputSource};
#[dom_struct] #[dom_struct]
pub struct XRInputSource { pub struct XRInputSource {
reflector: Reflector, reflector: Reflector,
session: Dom<XRSession>, session: Dom<XRSession>,
#[ignore_malloc_size_of = "Defined in rust-webvr"] #[ignore_malloc_size_of = "Defined in rust-webvr"]
data: WebVRGamepadData, info: InputSource,
#[ignore_malloc_size_of = "Defined in rust-webvr"] #[ignore_malloc_size_of = "Defined in rust-webvr"]
state: DomRefCell<WebVRGamepadState>,
target_ray_space: MutNullableDom<XRSpace>, target_ray_space: MutNullableDom<XRSpace>,
} }
impl XRInputSource { impl XRInputSource {
pub fn new_inherited( pub fn new_inherited(session: &XRSession, info: InputSource) -> XRInputSource {
session: &XRSession,
data: WebVRGamepadData,
state: WebVRGamepadState,
) -> XRInputSource {
XRInputSource { XRInputSource {
reflector: Reflector::new(), reflector: Reflector::new(),
session: Dom::from_ref(session), session: Dom::from_ref(session),
data, info,
state: DomRefCell::new(state),
target_ray_space: Default::default(), target_ray_space: Default::default(),
} }
} }
@ -44,32 +37,27 @@ impl XRInputSource {
pub fn new( pub fn new(
global: &GlobalScope, global: &GlobalScope,
session: &XRSession, session: &XRSession,
data: WebVRGamepadData, info: InputSource,
state: WebVRGamepadState,
) -> DomRoot<XRInputSource> { ) -> DomRoot<XRInputSource> {
reflect_dom_object( reflect_dom_object(
Box::new(XRInputSource::new_inherited(session, data, state)), Box::new(XRInputSource::new_inherited(session, info)),
global, global,
XRInputSourceBinding::Wrap, XRInputSourceBinding::Wrap,
) )
} }
pub fn update_state(&self, state: WebVRGamepadState) { pub fn id(&self) -> InputId {
*self.state.borrow_mut() = state; self.info.id
}
pub fn pose(&self) -> ApiPose {
unimplemented!()
} }
} }
impl XRInputSourceMethods for XRInputSource { impl XRInputSourceMethods for XRInputSource {
/// https://immersive-web.github.io/webxr/#dom-xrinputsource-handedness /// https://immersive-web.github.io/webxr/#dom-xrinputsource-handedness
fn Handedness(&self) -> XRHandedness { fn Handedness(&self) -> XRHandedness {
match self.data.hand { match self.info.handedness {
WebVRGamepadHand::Unknown => XRHandedness::None, Handedness::None => XRHandedness::None,
WebVRGamepadHand::Left => XRHandedness::Left, Handedness::Left => XRHandedness::Left,
WebVRGamepadHand::Right => XRHandedness::Right, Handedness::Right => XRHandedness::Right,
} }
} }

View file

@ -19,7 +19,7 @@ use crate::dom::bindings::inheritance::Castable;
use crate::dom::bindings::num::Finite; use crate::dom::bindings::num::Finite;
use crate::dom::bindings::refcounted::Trusted; use crate::dom::bindings::refcounted::Trusted;
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject}; 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::eventtarget::EventTarget;
use crate::dom::globalscope::GlobalScope; use crate::dom::globalscope::GlobalScope;
use crate::dom::promise::Promise; use crate::dom::promise::Promise;
@ -58,6 +58,7 @@ pub struct XRSession {
raf_callback_list: DomRefCell<Vec<(i32, Option<Rc<XRFrameRequestCallback>>)>>, raf_callback_list: DomRefCell<Vec<(i32, Option<Rc<XRFrameRequestCallback>>)>>,
#[ignore_malloc_size_of = "defined in ipc-channel"] #[ignore_malloc_size_of = "defined in ipc-channel"]
raf_sender: DomRefCell<Option<IpcSender<(f64, Frame)>>>, raf_sender: DomRefCell<Option<IpcSender<(f64, Frame)>>>,
input_sources: DomRefCell<Vec<Dom<XRInputSource>>>,
} }
impl XRSession { impl XRSession {
@ -76,16 +77,27 @@ impl XRSession {
next_raf_id: Cell::new(0), next_raf_id: Cell::new(0),
raf_callback_list: DomRefCell::new(vec![]), raf_callback_list: DomRefCell::new(vec![]),
raf_sender: DomRefCell::new(None), raf_sender: DomRefCell::new(None),
input_sources: DomRefCell::new(vec![]),
} }
} }
pub fn new(global: &GlobalScope, session: Session) -> DomRoot<XRSession> { pub fn new(global: &GlobalScope, session: Session) -> DomRoot<XRSession> {
let render_state = XRRenderState::new(global, 0.1, 1000.0, None); 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)), Box::new(XRSession::new_inherited(session, &render_state)),
global, global,
XRSessionBinding::Wrap, 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<F: FnOnce(&Session)>(&self, with: F) { pub fn with_session<F: FnOnce(&Session)>(&self, with: F) {
@ -268,7 +280,11 @@ impl XRSessionMethods for XRSession {
/// https://immersive-web.github.io/webxr/#dom-xrsession-getinputsources /// https://immersive-web.github.io/webxr/#dom-xrsession-getinputsources
fn GetInputSources(&self) -> Vec<DomRoot<XRInputSource>> { fn GetInputSources(&self) -> Vec<DomRoot<XRInputSource>> {
unimplemented!() self.input_sources
.borrow()
.iter()
.map(|x| DomRoot::from_ref(&**x))
.collect()
} }
} }

View file

@ -10,7 +10,7 @@ use crate::dom::eventtarget::EventTarget;
use crate::dom::globalscope::GlobalScope; use crate::dom::globalscope::GlobalScope;
use crate::dom::xrinputsource::XRInputSource; use crate::dom::xrinputsource::XRInputSource;
use crate::dom::xrreferencespace::XRReferenceSpace; 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 dom_struct::dom_struct;
use webxr_api::Frame; use webxr_api::Frame;
@ -61,7 +61,18 @@ impl XRSpace {
if let Some(reference) = self.downcast::<XRReferenceSpace>() { if let Some(reference) = self.downcast::<XRReferenceSpace>() {
reference.get_pose(base_pose) reference.get_pose(base_pose)
} else if let Some(source) = self.input_source.get() { } 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 { } else {
unreachable!() unreachable!()
} }