aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom/vrdisplay.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/script/dom/vrdisplay.rs')
-rw-r--r--components/script/dom/vrdisplay.rs104
1 files changed, 88 insertions, 16 deletions
diff --git a/components/script/dom/vrdisplay.rs b/components/script/dom/vrdisplay.rs
index c02d5439be8..048157a0ba7 100644
--- a/components/script/dom/vrdisplay.rs
+++ b/components/script/dom/vrdisplay.rs
@@ -4,14 +4,15 @@
use crate::dom::bindings::callback::ExceptionHandling;
use crate::dom::bindings::cell::DomRefCell;
-use crate::dom::bindings::codegen::Bindings::PerformanceBinding::PerformanceBinding::PerformanceMethods;
+use crate::dom::bindings::codegen::Bindings::PerformanceBinding::PerformanceMethods;
use crate::dom::bindings::codegen::Bindings::VRDisplayBinding;
use crate::dom::bindings::codegen::Bindings::VRDisplayBinding::VRDisplayMethods;
use crate::dom::bindings::codegen::Bindings::VRDisplayBinding::VREye;
use crate::dom::bindings::codegen::Bindings::VRLayerBinding::VRLayer;
use crate::dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextMethods;
use crate::dom::bindings::codegen::Bindings::WindowBinding::FrameRequestCallback;
-use crate::dom::bindings::codegen::Bindings::WindowBinding::WindowBinding::WindowMethods;
+use crate::dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
+use crate::dom::bindings::codegen::Bindings::XRSessionBinding::XRFrameRequestCallback;
use crate::dom::bindings::inheritance::Castable;
use crate::dom::bindings::num::Finite;
use crate::dom::bindings::refcounted::Trusted;
@@ -29,6 +30,8 @@ use crate::dom::vrframedata::VRFrameData;
use crate::dom::vrpose::VRPose;
use crate::dom::vrstageparameters::VRStageParameters;
use crate::dom::webglrenderingcontext::WebGLRenderingContext;
+use crate::dom::xrframe::XRFrame;
+use crate::dom::xrsession::XRSession;
use crate::script_runtime::CommonScriptMsg;
use crate::script_runtime::ScriptThreadEventCategory::WebVREvent;
use crate::task_source::TaskSourceName;
@@ -67,6 +70,8 @@ pub struct VRDisplay {
/// List of request animation frame callbacks
#[ignore_malloc_size_of = "closures are hard"]
raf_callback_list: DomRefCell<Vec<(u32, Option<Rc<FrameRequestCallback>>)>>,
+ #[ignore_malloc_size_of = "closures are hard"]
+ xr_raf_callback_list: DomRefCell<Vec<(u32, Option<Rc<XRFrameRequestCallback>>)>>,
// Compositor VRFrameData synchonization
frame_data_status: Cell<VRFrameDataStatus>,
#[ignore_malloc_size_of = "closures are hard"]
@@ -74,6 +79,8 @@ pub struct VRDisplay {
running_display_raf: Cell<bool>,
paused: Cell<bool>,
stopped_on_pause: Cell<bool>,
+ /// Whether or not this is XR mode, and the session
+ xr_session: MutNullableDom<XRSession>,
}
unsafe_no_jsmanaged_fields!(WebVRDisplayData);
@@ -120,6 +127,7 @@ impl VRDisplay {
layer_ctx: MutNullableDom::default(),
next_raf_id: Cell::new(1),
raf_callback_list: DomRefCell::new(vec![]),
+ xr_raf_callback_list: DomRefCell::new(vec![]),
frame_data_status: Cell::new(VRFrameDataStatus::Waiting),
frame_data_receiver: DomRefCell::new(None),
running_display_raf: Cell::new(false),
@@ -129,6 +137,7 @@ 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),
+ xr_session: MutNullableDom::default(),
}
}
@@ -624,25 +633,42 @@ impl VRDisplay {
fn handle_raf(&self, end_sender: &Sender<Result<(f64, f64), ()>>) {
self.frame_data_status.set(VRFrameDataStatus::Waiting);
- self.running_display_raf.set(true);
- let mut callbacks = mem::replace(&mut *self.raf_callback_list.borrow_mut(), vec![]);
let now = self.global().as_window().Performance().Now();
- // Call registered VRDisplay.requestAnimationFrame callbacks.
- for (_, callback) in callbacks.drain(..) {
- if let Some(callback) = callback {
- let _ = callback.Call__(Finite::wrap(*now), ExceptionHandling::Report);
+ if let Some(session) = self.xr_session.get() {
+ let mut callbacks = mem::replace(&mut *self.xr_raf_callback_list.borrow_mut(), vec![]);
+ if callbacks.is_empty() {
+ return;
}
- }
-
- self.running_display_raf.set(false);
- if self.frame_data_status.get() == VRFrameDataStatus::Waiting {
- // User didn't call getFrameData while presenting.
- // We automatically reads the pending VRFrameData to avoid overflowing the IPC-Channel buffers.
- // Show a warning as the WebVR Spec recommends.
- warn!("WebVR: You should call GetFrameData while presenting");
self.sync_frame_data();
+ let frame = XRFrame::new(&self.global(), &session, self.frame_data.borrow().clone());
+
+ for (_, callback) in callbacks.drain(..) {
+ if let Some(callback) = callback {
+ let _ = callback.Call__(Finite::wrap(*now), &frame, ExceptionHandling::Report);
+ }
+ }
+ // frame submission is automatic in XR
+ self.SubmitFrame();
+ } else {
+ self.running_display_raf.set(true);
+ let mut callbacks = mem::replace(&mut *self.raf_callback_list.borrow_mut(), vec![]);
+ // Call registered VRDisplay.requestAnimationFrame callbacks.
+ for (_, callback) in callbacks.drain(..) {
+ if let Some(callback) = callback {
+ let _ = callback.Call__(Finite::wrap(*now), ExceptionHandling::Report);
+ }
+ }
+
+ self.running_display_raf.set(false);
+ if self.frame_data_status.get() == VRFrameDataStatus::Waiting {
+ // User didn't call getFrameData while presenting.
+ // We automatically reads the pending VRFrameData to avoid overflowing the IPC-Channel buffers.
+ // Show a warning as the WebVR Spec recommends.
+ warn!("WebVR: You should call GetFrameData while presenting");
+ self.sync_frame_data();
+ }
}
match self.frame_data_status.get() {
@@ -661,6 +687,52 @@ impl VRDisplay {
}
}
+// XR stuff
+// XXXManishearth eventually we should share as much logic as possible
+impl VRDisplay {
+ pub fn xr_present(&self, session: &XRSession, ctx: &WebGLRenderingContext) {
+ let layer_bounds = WebVRLayer::default();
+ self.xr_session.set(Some(session));
+ if self.presenting.get() {
+ *self.layer.borrow_mut() = layer_bounds;
+ self.layer_ctx.set(Some(&ctx));
+ return;
+ }
+
+ // 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();
+
+ if let Ok(()) = receiver.recv().unwrap() {
+ *self.layer.borrow_mut() = layer_bounds;
+ self.layer_ctx.set(Some(&ctx));
+ self.init_present();
+ }
+ }
+
+ pub fn xr_raf(&self, callback: Rc<XRFrameRequestCallback>) -> u32 {
+ let raf_id = self.next_raf_id.get();
+ self.next_raf_id.set(raf_id + 1);
+ self.xr_raf_callback_list
+ .borrow_mut()
+ .push((raf_id, Some(callback)));
+ raf_id
+ }
+
+ pub fn xr_cancel_raf(&self, handle: i32) {
+ let mut list = self.xr_raf_callback_list.borrow_mut();
+ if let Some(pair) = list.iter_mut().find(|pair| pair.0 == handle as u32) {
+ pair.1 = None;
+ }
+ }
+}
+
// WebVR Spec: If the number of values in the leftBounds/rightBounds arrays
// is not 0 or 4 for any of the passed layers the promise is rejected
fn parse_bounds(src: &Option<Vec<Finite<f32>>>, dst: &mut [f32; 4]) -> Result<(), &'static str> {