aboutsummaryrefslogtreecommitdiffstats
path: root/components/script
diff options
context:
space:
mode:
authorbors-servo <lbergstrom+bors@mozilla.com>2019-01-08 20:42:37 -0500
committerGitHub <noreply@github.com>2019-01-08 20:42:37 -0500
commit44cbe969e24e65fc8f82f77bac6374ceb4aa0e71 (patch)
tree35209a562f09750d891cadfded8dc03d8f9271a7 /components/script
parentd3763452b59837d72bd23eb03eac0926d1ff6145 (diff)
parente2522d36ffa053b10296bbd1c16d60e502f1f452 (diff)
downloadservo-44cbe969e24e65fc8f82f77bac6374ceb4aa0e71.tar.gz
servo-44cbe969e24e65fc8f82f77bac6374ceb4aa0e71.zip
Auto merge of #22649 - Manishearth:xr-promises, r=jdm
Make XR/VR presenting code async Previously we only pretended to be async, we returned promises that were already resolved because we synchronously blocked on the channel. This: - Moves XR presentation to session creation (where it belongs, see https://github.com/immersive-web/webxr/issues/453) - Factors out common presentation code in a way that supports asynchronously resolving promises - Uses this for `VRDisplay::RequestPresent()` and `XR::RequestSession()` r? @jdm <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/22649) <!-- Reviewable:end -->
Diffstat (limited to 'components/script')
-rw-r--r--components/script/dom/vrdisplay.rs127
-rw-r--r--components/script/dom/xr.rs5
-rw-r--r--components/script/dom/xrsession.rs7
3 files changed, 81 insertions, 58 deletions
diff --git a/components/script/dom/vrdisplay.rs b/components/script/dom/vrdisplay.rs
index 896bd0d4f81..6c4bea1568c 100644
--- a/components/script/dom/vrdisplay.rs
+++ b/components/script/dom/vrdisplay.rs
@@ -15,7 +15,7 @@ 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;
+use crate::dom::bindings::refcounted::{Trusted, TrustedPromise};
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject};
use crate::dom::bindings::root::{DomRoot, MutDom, MutNullableDom};
use crate::dom::bindings::str::DOMString;
@@ -34,7 +34,7 @@ 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;
+use crate::task_source::{TaskSource, TaskSourceName};
use canvas_traits::webgl::{webgl_channel, WebGLReceiver, WebVRCommand};
use crossbeam_channel::{unbounded, Sender};
use dom_struct::dom_struct;
@@ -347,35 +347,9 @@ impl VRDisplayMethods for VRDisplay {
},
};
- // WebVR spec: Repeat calls while already presenting will update the VRLayers being displayed.
- if self.presenting.get() {
- *self.layer.borrow_mut() = layer_bounds;
- self.layer_ctx.set(Some(&layer_ctx));
- promise.resolve_native(&());
- return promise;
- }
-
- // 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();
- match receiver.recv().unwrap() {
- Ok(()) => {
- *self.layer.borrow_mut() = layer_bounds;
- self.layer_ctx.set(Some(&layer_ctx));
- self.init_present();
- promise.resolve_native(&());
- },
- Err(e) => {
- promise.reject_native(&e);
- },
- }
-
+ self.request_present(layer_bounds, Some(&layer_ctx), Some(promise.clone()), |p| {
+ p.resolve_native(&())
+ });
promise
}
@@ -464,6 +438,64 @@ impl VRDisplay {
}
}
+ pub fn request_present<F>(
+ &self,
+ layer_bounds: WebVRLayer,
+ ctx: Option<&WebGLRenderingContext>,
+ promise: Option<Rc<Promise>>,
+ resolve: F,
+ ) where
+ F: FnOnce(Rc<Promise>) + Send + 'static,
+ {
+ // WebVR spec: Repeat calls while already presenting will update the VRLayers being displayed.
+ if self.presenting.get() {
+ *self.layer.borrow_mut() = layer_bounds;
+ self.layer_ctx.set(ctx);
+ promise.map(resolve);
+ 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();
+ let promise = promise.map(TrustedPromise::new);
+ let this = Trusted::new(self);
+ let ctx = ctx.map(|c| Trusted::new(c));
+ let global = self.global();
+ let window = global.as_window();
+ let (task_source, canceller) = window
+ .task_manager()
+ .dom_manipulation_task_source_with_canceller();
+ thread::spawn(move || {
+ let recv = receiver.recv().unwrap();
+ let _ = task_source.queue_with_canceller(
+ task!(vr_presenting: move || {
+ let this = this.root();
+ let promise = promise.map(|p| p.root());
+ let ctx = ctx.map(|c| c.root());
+ match recv {
+ Ok(()) => {
+ *this.layer.borrow_mut() = layer_bounds;
+ this.layer_ctx.set(ctx.as_ref().map(|c| &**c));
+ this.init_present();
+ promise.map(resolve);
+ },
+ Err(e) => {
+ promise.map(|p| p.reject_native(&e));
+ },
+ }
+ }),
+ &canceller,
+ );
+ });
+ }
+
pub fn handle_webvr_event(&self, event: &WebVRDisplayEvent) {
match *event {
WebVRDisplayEvent::Connect(ref display) => {
@@ -688,30 +720,19 @@ 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) {
+ pub fn xr_present(
+ &self,
+ session: &XRSession,
+ ctx: Option<&WebGLRenderingContext>,
+ promise: Option<Rc<Promise>>,
+ ) {
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();
- }
+ let session = Trusted::new(session);
+ self.request_present(layer_bounds, ctx, promise, move |p| {
+ let session = session.root();
+ p.resolve_native(&session);
+ });
}
pub fn xr_raf(&self, callback: Rc<XRFrameRequestCallback>) -> u32 {
diff --git a/components/script/dom/xr.rs b/components/script/dom/xr.rs
index dae63a4baca..3e18ee0d279 100644
--- a/components/script/dom/xr.rs
+++ b/components/script/dom/xr.rs
@@ -95,10 +95,7 @@ impl XRMethods for XR {
}
let session = XRSession::new(&self.global(), &displays[0]);
- promise.resolve_native(&session);
- // whether or not we should initiate presentation is unclear
- // https://github.com/immersive-web/webxr/issues/453
-
+ session.xr_present(promise.clone());
promise
}
}
diff --git a/components/script/dom/xrsession.rs b/components/script/dom/xrsession.rs
index 449d4acf8fc..93837255f37 100644
--- a/components/script/dom/xrsession.rs
+++ b/components/script/dom/xrsession.rs
@@ -14,6 +14,7 @@ use crate::dom::bindings::reflector::reflect_dom_object;
use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom};
use crate::dom::eventtarget::EventTarget;
use crate::dom::globalscope::GlobalScope;
+use crate::dom::promise::Promise;
use crate::dom::vrdisplay::VRDisplay;
use crate::dom::xrlayer::XRLayer;
use crate::dom::xrwebgllayer::XRWebGLLayer;
@@ -43,6 +44,10 @@ impl XRSession {
XRSessionBinding::Wrap,
)
}
+
+ pub fn xr_present(&self, p: Rc<Promise>) {
+ self.display.xr_present(self, None, Some(p));
+ }
}
impl XRSessionMethods for XRSession {
@@ -76,7 +81,7 @@ impl XRSessionMethods for XRSession {
self.base_layer.set(layer);
if let Some(layer) = layer {
let layer = layer.downcast::<XRWebGLLayer>().unwrap();
- self.display.xr_present(&self, &layer.Context());
+ self.display.xr_present(&self, Some(&layer.Context()), None);
} else {
// steps unknown
// https://github.com/immersive-web/webxr/issues/453