mirror of
https://github.com/servo/servo.git
synced 2025-06-19 14:48:59 +01:00
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 -->
This commit is contained in:
commit
44cbe969e2
3 changed files with 81 additions and 58 deletions
|
@ -15,7 +15,7 @@ use crate::dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
|
||||||
use crate::dom::bindings::codegen::Bindings::XRSessionBinding::XRFrameRequestCallback;
|
use crate::dom::bindings::codegen::Bindings::XRSessionBinding::XRFrameRequestCallback;
|
||||||
use crate::dom::bindings::inheritance::Castable;
|
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, TrustedPromise};
|
||||||
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::{DomRoot, MutDom, MutNullableDom};
|
||||||
use crate::dom::bindings::str::DOMString;
|
use crate::dom::bindings::str::DOMString;
|
||||||
|
@ -34,7 +34,7 @@ use crate::dom::xrframe::XRFrame;
|
||||||
use crate::dom::xrsession::XRSession;
|
use crate::dom::xrsession::XRSession;
|
||||||
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::TaskSourceName;
|
use crate::task_source::{TaskSource, TaskSourceName};
|
||||||
use canvas_traits::webgl::{webgl_channel, WebGLReceiver, WebVRCommand};
|
use canvas_traits::webgl::{webgl_channel, WebGLReceiver, WebVRCommand};
|
||||||
use crossbeam_channel::{unbounded, Sender};
|
use crossbeam_channel::{unbounded, Sender};
|
||||||
use dom_struct::dom_struct;
|
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.
|
self.request_present(layer_bounds, Some(&layer_ctx), Some(promise.clone()), |p| {
|
||||||
if self.presenting.get() {
|
p.resolve_native(&())
|
||||||
*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);
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
promise
|
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) {
|
pub fn handle_webvr_event(&self, event: &WebVRDisplayEvent) {
|
||||||
match *event {
|
match *event {
|
||||||
WebVRDisplayEvent::Connect(ref display) => {
|
WebVRDisplayEvent::Connect(ref display) => {
|
||||||
|
@ -688,30 +720,19 @@ impl VRDisplay {
|
||||||
// XR stuff
|
// XR stuff
|
||||||
// XXXManishearth eventually we should share as much logic as possible
|
// XXXManishearth eventually we should share as much logic as possible
|
||||||
impl VRDisplay {
|
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();
|
let layer_bounds = WebVRLayer::default();
|
||||||
self.xr_session.set(Some(session));
|
self.xr_session.set(Some(session));
|
||||||
if self.presenting.get() {
|
let session = Trusted::new(session);
|
||||||
*self.layer.borrow_mut() = layer_bounds;
|
self.request_present(layer_bounds, ctx, promise, move |p| {
|
||||||
self.layer_ctx.set(Some(&ctx));
|
let session = session.root();
|
||||||
return;
|
p.resolve_native(&session);
|
||||||
}
|
});
|
||||||
|
|
||||||
// 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 {
|
pub fn xr_raf(&self, callback: Rc<XRFrameRequestCallback>) -> u32 {
|
||||||
|
|
|
@ -95,10 +95,7 @@ impl XRMethods for XR {
|
||||||
}
|
}
|
||||||
|
|
||||||
let session = XRSession::new(&self.global(), &displays[0]);
|
let session = XRSession::new(&self.global(), &displays[0]);
|
||||||
promise.resolve_native(&session);
|
session.xr_present(promise.clone());
|
||||||
// whether or not we should initiate presentation is unclear
|
|
||||||
// https://github.com/immersive-web/webxr/issues/453
|
|
||||||
|
|
||||||
promise
|
promise
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ use crate::dom::bindings::reflector::reflect_dom_object;
|
||||||
use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom};
|
use crate::dom::bindings::root::{Dom, DomRoot, 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::vrdisplay::VRDisplay;
|
use crate::dom::vrdisplay::VRDisplay;
|
||||||
use crate::dom::xrlayer::XRLayer;
|
use crate::dom::xrlayer::XRLayer;
|
||||||
use crate::dom::xrwebgllayer::XRWebGLLayer;
|
use crate::dom::xrwebgllayer::XRWebGLLayer;
|
||||||
|
@ -43,6 +44,10 @@ impl XRSession {
|
||||||
XRSessionBinding::Wrap,
|
XRSessionBinding::Wrap,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn xr_present(&self, p: Rc<Promise>) {
|
||||||
|
self.display.xr_present(self, None, Some(p));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl XRSessionMethods for XRSession {
|
impl XRSessionMethods for XRSession {
|
||||||
|
@ -76,7 +81,7 @@ impl XRSessionMethods for XRSession {
|
||||||
self.base_layer.set(layer);
|
self.base_layer.set(layer);
|
||||||
if let Some(layer) = layer {
|
if let Some(layer) = layer {
|
||||||
let layer = layer.downcast::<XRWebGLLayer>().unwrap();
|
let layer = layer.downcast::<XRWebGLLayer>().unwrap();
|
||||||
self.display.xr_present(&self, &layer.Context());
|
self.display.xr_present(&self, Some(&layer.Context()), None);
|
||||||
} else {
|
} else {
|
||||||
// steps unknown
|
// steps unknown
|
||||||
// https://github.com/immersive-web/webxr/issues/453
|
// https://github.com/immersive-web/webxr/issues/453
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue