diff options
Diffstat (limited to 'components/script/dom/vrdisplay.rs')
-rw-r--r-- | components/script/dom/vrdisplay.rs | 226 |
1 files changed, 136 insertions, 90 deletions
diff --git a/components/script/dom/vrdisplay.rs b/components/script/dom/vrdisplay.rs index d44d9d0fa22..9efd763989e 100644 --- a/components/script/dom/vrdisplay.rs +++ b/components/script/dom/vrdisplay.rs @@ -84,7 +84,7 @@ unsafe_no_jsmanaged_fields!(WebVRLayer); enum VRFrameDataStatus { Waiting, Synced, - Exit + Exit, } unsafe_no_jsmanaged_fields!(VRFrameDataStatus); @@ -93,7 +93,7 @@ impl VRDisplay { fn new_inherited(global: &GlobalScope, display: WebVRDisplayData) -> VRDisplay { let stage = match display.stage_parameters { Some(ref params) => Some(VRStageParameters::new(params.clone(), &global)), - None => None + None => None, }; VRDisplay { @@ -102,9 +102,18 @@ impl VRDisplay { depth_near: Cell::new(0.01), depth_far: Cell::new(10000.0), presenting: Cell::new(false), - left_eye_params: MutDom::new(&*VREyeParameters::new(display.left_eye_parameters.clone(), &global)), - right_eye_params: MutDom::new(&*VREyeParameters::new(display.right_eye_parameters.clone(), &global)), - capabilities: MutDom::new(&*VRDisplayCapabilities::new(display.capabilities.clone(), &global)), + left_eye_params: MutDom::new(&*VREyeParameters::new( + display.left_eye_parameters.clone(), + &global, + )), + right_eye_params: MutDom::new(&*VREyeParameters::new( + display.right_eye_parameters.clone(), + &global, + )), + capabilities: MutDom::new(&*VRDisplayCapabilities::new( + display.capabilities.clone(), + &global, + )), stage_params: MutNullableDom::new(stage.as_ref().map(|v| v.deref())), frame_data: DomRefCell::new(Default::default()), layer: DomRefCell::new(Default::default()), @@ -119,14 +128,16 @@ impl VRDisplay { paused: Cell::new(false), // 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) + stopped_on_pause: Cell::new(false), } } pub fn new(global: &GlobalScope, display: WebVRDisplayData) -> DomRoot<VRDisplay> { - reflect_dom_object(Box::new(VRDisplay::new_inherited(&global, display)), - global, - VRDisplayBinding::Wrap) + reflect_dom_object( + Box::new(VRDisplay::new_inherited(&global, display)), + global, + VRDisplayBinding::Wrap, + ) } } @@ -163,7 +174,7 @@ impl VRDisplayMethods for VRDisplay { fn GetEyeParameters(&self, eye: VREye) -> DomRoot<VREyeParameters> { match eye { VREye::Left => DomRoot::from_ref(&*self.left_eye_params.get()), - VREye::Right => DomRoot::from_ref(&*self.right_eye_params.get()) + VREye::Right => DomRoot::from_ref(&*self.right_eye_params.get()), } } @@ -189,17 +200,20 @@ impl VRDisplayMethods for VRDisplay { if self.frame_data_status.get() == VRFrameDataStatus::Waiting { self.sync_frame_data(); } - frameData.update(& self.frame_data.borrow()); + frameData.update(&self.frame_data.borrow()); return true; } // If not presenting we fetch inmediante VRFrameData let (sender, receiver) = ipc::channel(self.global().time_profiler_chan().clone()).unwrap(); - self.webvr_thread().send(WebVRMsg::GetFrameData(self.global().pipeline_id(), - self.DisplayId(), - self.depth_near.get(), - self.depth_far.get(), - sender)).unwrap(); + self.webvr_thread() + .send(WebVRMsg::GetFrameData( + self.global().pipeline_id(), + self.DisplayId(), + self.depth_near.get(), + self.depth_far.get(), + sender, + )).unwrap(); return match receiver.recv().unwrap() { Ok(data) => { frameData.update(&data); @@ -208,7 +222,7 @@ impl VRDisplayMethods for VRDisplay { Err(e) => { error!("WebVR::GetFrameData: {:?}", e); false - } + }, }; } @@ -220,9 +234,12 @@ impl VRDisplayMethods for VRDisplay { // https://w3c.github.io/webvr/#dom-vrdisplay-resetpose fn ResetPose(&self) { let (sender, receiver) = ipc::channel(self.global().time_profiler_chan().clone()).unwrap(); - self.webvr_thread().send(WebVRMsg::ResetPose(self.global().pipeline_id(), - self.DisplayId(), - sender)).unwrap(); + self.webvr_thread() + .send(WebVRMsg::ResetPose( + self.global().pipeline_id(), + self.DisplayId(), + sender, + )).unwrap(); if let Ok(data) = receiver.recv().unwrap() { // Some VRDisplay data might change after calling ResetPose() *self.display.borrow_mut() = data; @@ -254,7 +271,9 @@ impl VRDisplayMethods for VRDisplay { if self.presenting.get() { let raf_id = self.next_raf_id.get(); self.next_raf_id.set(raf_id + 1); - self.raf_callback_list.borrow_mut().push((raf_id, Some(callback))); + self.raf_callback_list + .borrow_mut() + .push((raf_id, Some(callback))); raf_id } else { // WebVR spec: When a VRDisplay is not presenting it should @@ -315,7 +334,7 @@ impl VRDisplayMethods for VRDisplay { let msg = msg.to_string(); promise.reject_native(&msg); return promise; - } + }, }; // WebVR spec: Repeat calls while already presenting will update the VRLayers being displayed. @@ -328,10 +347,12 @@ impl VRDisplayMethods for VRDisplay { // Request Present let (sender, receiver) = ipc::channel(self.global().time_profiler_chan().clone()).unwrap(); - self.webvr_thread().send(WebVRMsg::RequestPresent(self.global().pipeline_id(), - self.display.borrow().display_id, - sender)) - .unwrap(); + self.webvr_thread() + .send(WebVRMsg::RequestPresent( + self.global().pipeline_id(), + self.display.borrow().display_id, + sender, + )).unwrap(); match receiver.recv().unwrap() { Ok(()) => { *self.layer.borrow_mut() = layer_bounds; @@ -341,7 +362,7 @@ impl VRDisplayMethods for VRDisplay { }, Err(e) => { promise.reject_native(&e); - } + }, } promise @@ -361,10 +382,12 @@ impl VRDisplayMethods for VRDisplay { // Exit present let (sender, receiver) = ipc::channel(self.global().time_profiler_chan().clone()).unwrap(); - self.webvr_thread().send(WebVRMsg::ExitPresent(self.global().pipeline_id(), - self.display.borrow().display_id, - Some(sender))) - .unwrap(); + self.webvr_thread() + .send(WebVRMsg::ExitPresent( + self.global().pipeline_id(), + self.display.borrow().display_id, + Some(sender), + )).unwrap(); match receiver.recv().unwrap() { Ok(()) => { self.stop_present(); @@ -372,7 +395,7 @@ impl VRDisplayMethods for VRDisplay { }, Err(e) => { promise.reject_native(&e); - } + }, } promise @@ -410,7 +433,10 @@ impl VRDisplayMethods for VRDisplay { impl VRDisplay { fn webvr_thread(&self) -> IpcSender<WebVRMsg> { - self.global().as_window().webvr_thread().expect("Shouldn't arrive here with WebVR disabled") + self.global() + .as_window() + .webvr_thread() + .expect("Shouldn't arrive here with WebVR disabled") } pub fn update_display(&self, display: &WebVRDisplayData) { @@ -461,7 +487,6 @@ impl VRDisplay { self.stop_present(); self.stopped_on_pause.set(true); } - }, WebVRDisplayEvent::Resume(_) => { self.paused.set(false); @@ -475,14 +500,16 @@ impl VRDisplay { if self.presenting.get() { self.stop_present(); } - } + }, }; } fn notify_event(&self, event: &WebVRDisplayEvent) { let root = DomRoot::from_ref(&*self); let event = VRDisplayEvent::new_from_webvr(&self.global(), &root, &event); - event.upcast::<Event>().fire(self.global().upcast::<EventTarget>()); + event + .upcast::<Event>() + .fire(self.global().upcast::<EventTarget>()); } fn init_present(&self) { @@ -504,44 +531,49 @@ impl VRDisplay { // in the Webrender thread are executed in parallel. This allows to get some JavaScript code executed ahead. // while the render thread is syncing the VRFrameData to be used for the current frame. // This thread runs until the user calls ExitPresent, the tab is closed or some unexpected error happened. - thread::Builder::new().name("WebVR_RAF".into()).spawn(move || { - let (raf_sender, raf_receiver) = channel(); - let mut near = near_init; - let mut far = far_init; - - // Initialize compositor - api_sender.send_vr(WebVRCommand::Create(display_id)).unwrap(); - loop { - // Run RAF callbacks on JavaScript thread - let this = address.clone(); - let sender = raf_sender.clone(); - let task = Box::new(task!(handle_vrdisplay_raf: move || { + thread::Builder::new() + .name("WebVR_RAF".into()) + .spawn(move || { + let (raf_sender, raf_receiver) = channel(); + let mut near = near_init; + let mut far = far_init; + + // Initialize compositor + api_sender + .send_vr(WebVRCommand::Create(display_id)) + .unwrap(); + loop { + // Run RAF callbacks on JavaScript thread + let this = address.clone(); + let sender = raf_sender.clone(); + let task = Box::new(task!(handle_vrdisplay_raf: move || { this.root().handle_raf(&sender); })); - // NOTE: WebVR spec doesn't specify what task source we should use. Is - // dom-manipulation a good choice long term? - js_sender.send(CommonScriptMsg::Task( - WebVREvent, - task, - Some(pipeline_id), - TaskSourceName::DOMManipulation, - )).unwrap(); - - // Run Sync Poses in parallell on Render thread - let msg = WebVRCommand::SyncPoses(display_id, near, far, sync_sender.clone()); - api_sender.send_vr(msg).unwrap(); - - // Wait until both SyncPoses & RAF ends - if let Ok(depth) = raf_receiver.recv().unwrap() { - near = depth.0; - far = depth.1; - } else { - // Stop thread - // ExitPresent called or some error happened - return; + // NOTE: WebVR spec doesn't specify what task source we should use. Is + // dom-manipulation a good choice long term? + js_sender + .send(CommonScriptMsg::Task( + WebVREvent, + task, + Some(pipeline_id), + TaskSourceName::DOMManipulation, + )).unwrap(); + + // Run Sync Poses in parallell on Render thread + let msg = WebVRCommand::SyncPoses(display_id, near, far, sync_sender.clone()); + api_sender.send_vr(msg).unwrap(); + + // Wait until both SyncPoses & RAF ends + if let Ok(depth) = raf_receiver.recv().unwrap() { + near = depth.0; + far = depth.1; + } else { + // Stop thread + // ExitPresent called or some error happened + return; + } } - } - }).expect("Thread spawning failed"); + }).expect("Thread spawning failed"); } fn stop_present(&self) { @@ -550,16 +582,20 @@ impl VRDisplay { let api_sender = self.layer_ctx.get().unwrap().webgl_sender(); let display_id = self.display.borrow().display_id; - api_sender.send_vr(WebVRCommand::Release(display_id)).unwrap(); + api_sender + .send_vr(WebVRCommand::Release(display_id)) + .unwrap(); } // Only called when the JSContext is destroyed while presenting. // In this case we don't want to wait for WebVR Thread response. fn force_stop_present(&self) { - self.webvr_thread().send(WebVRMsg::ExitPresent(self.global().pipeline_id(), - self.display.borrow().display_id, - None)) - .unwrap(); + self.webvr_thread() + .send(WebVRMsg::ExitPresent( + self.global().pipeline_id(), + self.display.borrow().display_id, + None, + )).unwrap(); self.stop_present(); } @@ -570,9 +606,7 @@ impl VRDisplay { *self.frame_data.borrow_mut() = WebVRFrameData::from_bytes(&bytes[..]); VRFrameDataStatus::Synced }, - Err(()) => { - VRFrameDataStatus::Exit - } + Err(()) => VRFrameDataStatus::Exit, } } else { VRFrameDataStatus::Exit @@ -607,13 +641,15 @@ impl VRDisplay { match self.frame_data_status.get() { VRFrameDataStatus::Synced => { // Sync succeeded. Notify RAF thread. - end_sender.send(Ok((self.depth_near.get(), self.depth_far.get()))).unwrap(); + end_sender + .send(Ok((self.depth_near.get(), self.depth_far.get()))) + .unwrap(); }, VRFrameDataStatus::Exit | VRFrameDataStatus::Waiting => { // ExitPresent called or some error ocurred. // Notify VRDisplay RAF thread to stop. end_sender.send(Err(())).unwrap(); - } + }, } } } @@ -624,22 +660,30 @@ fn parse_bounds(src: &Option<Vec<Finite<f32>>>, dst: &mut [f32; 4]) -> Result<() match *src { Some(ref values) => { if values.len() == 0 { - return Ok(()) + return Ok(()); } if values.len() != 4 { - return Err("The number of values in the leftBounds/rightBounds arrays must be 0 or 4") + return Err( + "The number of values in the leftBounds/rightBounds arrays must be 0 or 4", + ); } for i in 0..4 { dst[i] = *values[i].deref(); } Ok(()) }, - None => Ok(()) + None => Ok(()), } } -fn validate_layer(layer: &VRLayer) -> Result<(WebVRLayer, DomRoot<WebGLRenderingContext>), &'static str> { - let ctx = layer.source.as_ref().map(|ref s| s.get_base_webgl_context()).unwrap_or(None); +fn validate_layer( + layer: &VRLayer, +) -> Result<(WebVRLayer, DomRoot<WebGLRenderingContext>), &'static str> { + let ctx = layer + .source + .as_ref() + .map(|ref s| s.get_base_webgl_context()) + .unwrap_or(None); if let Some(ctx) = ctx { let mut data = WebVRLayer::default(); parse_bounds(&layer.leftBounds, &mut data.left_bounds)?; @@ -651,8 +695,10 @@ fn validate_layer(layer: &VRLayer) -> Result<(WebVRLayer, DomRoot<WebGLRendering } fn bounds_to_vec(src: &[f32; 4]) -> Vec<Finite<f32>> { - vec![Finite::wrap(src[0]), - Finite::wrap(src[1]), - Finite::wrap(src[2]), - Finite::wrap(src[3])] + vec![ + Finite::wrap(src[0]), + Finite::wrap(src[1]), + Finite::wrap(src[2]), + Finite::wrap(src[3]), + ] } |