diff options
author | bors-servo <lbergstrom+bors@mozilla.com> | 2019-01-08 20:42:37 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-01-08 20:42:37 -0500 |
commit | 44cbe969e24e65fc8f82f77bac6374ceb4aa0e71 (patch) | |
tree | 35209a562f09750d891cadfded8dc03d8f9271a7 /components/script | |
parent | d3763452b59837d72bd23eb03eac0926d1ff6145 (diff) | |
parent | e2522d36ffa053b10296bbd1c16d60e502f1f452 (diff) | |
download | servo-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.rs | 127 | ||||
-rw-r--r-- | components/script/dom/xr.rs | 5 | ||||
-rw-r--r-- | components/script/dom/xrsession.rs | 7 |
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 |