mirror of
https://github.com/servo/servo.git
synced 2025-07-14 19:03:40 +01:00
Auto merge of #22911 - Manishearth:xr-spec-fixes, r=jdm
Some XR spec fixes Tie in some concepts that were previously left out of the implementation. <!-- 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/22911) <!-- Reviewable:end -->
This commit is contained in:
commit
cc8a9fa928
4 changed files with 69 additions and 10 deletions
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
use crate::dom::bindings::callback::ExceptionHandling;
|
use crate::dom::bindings::callback::ExceptionHandling;
|
||||||
use crate::dom::bindings::cell::DomRefCell;
|
use crate::dom::bindings::cell::DomRefCell;
|
||||||
|
use crate::dom::bindings::codegen::Bindings::NavigatorBinding::NavigatorMethods;
|
||||||
use crate::dom::bindings::codegen::Bindings::PerformanceBinding::PerformanceMethods;
|
use crate::dom::bindings::codegen::Bindings::PerformanceBinding::PerformanceMethods;
|
||||||
use crate::dom::bindings::codegen::Bindings::VRDisplayBinding;
|
use crate::dom::bindings::codegen::Bindings::VRDisplayBinding;
|
||||||
use crate::dom::bindings::codegen::Bindings::VRDisplayBinding::VRDisplayMethods;
|
use crate::dom::bindings::codegen::Bindings::VRDisplayBinding::VRDisplayMethods;
|
||||||
|
@ -13,6 +14,7 @@ use crate::dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGL
|
||||||
use crate::dom::bindings::codegen::Bindings::WindowBinding::FrameRequestCallback;
|
use crate::dom::bindings::codegen::Bindings::WindowBinding::FrameRequestCallback;
|
||||||
use crate::dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
|
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::error::Error;
|
||||||
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, TrustedPromise};
|
use crate::dom::bindings::refcounted::{Trusted, TrustedPromise};
|
||||||
|
@ -347,6 +349,24 @@ 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
let xr = self.global().as_window().Navigator().Xr();
|
||||||
|
|
||||||
|
if xr.pending_or_active_session() {
|
||||||
|
// WebVR spec doesn't mandate anything here, however
|
||||||
|
// the WebXR spec expects there to be only one immersive XR session at a time,
|
||||||
|
// and WebVR is deprecated
|
||||||
|
promise.reject_error(Error::InvalidState);
|
||||||
|
return promise;
|
||||||
|
}
|
||||||
|
|
||||||
self.request_present(layer_bounds, Some(&layer_ctx), Some(promise.clone()), |p| {
|
self.request_present(layer_bounds, Some(&layer_ctx), Some(promise.clone()), |p| {
|
||||||
p.resolve_native(&())
|
p.resolve_native(&())
|
||||||
});
|
});
|
||||||
|
@ -447,14 +467,6 @@ impl VRDisplay {
|
||||||
) where
|
) where
|
||||||
F: FnOnce(Rc<Promise>) + Send + 'static,
|
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
|
// Request Present
|
||||||
let (sender, receiver) = ipc::channel(self.global().time_profiler_chan().clone()).unwrap();
|
let (sender, receiver) = ipc::channel(self.global().time_profiler_chan().clone()).unwrap();
|
||||||
self.webvr_thread()
|
self.webvr_thread()
|
||||||
|
@ -557,6 +569,8 @@ impl VRDisplay {
|
||||||
|
|
||||||
fn init_present(&self) {
|
fn init_present(&self) {
|
||||||
self.presenting.set(true);
|
self.presenting.set(true);
|
||||||
|
let xr = self.global().as_window().Navigator().Xr();
|
||||||
|
xr.set_active_immersive_session(&self);
|
||||||
let (sync_sender, sync_receiver) = webgl_channel().unwrap();
|
let (sync_sender, sync_receiver) = webgl_channel().unwrap();
|
||||||
*self.frame_data_receiver.borrow_mut() = Some(sync_receiver);
|
*self.frame_data_receiver.borrow_mut() = Some(sync_receiver);
|
||||||
|
|
||||||
|
@ -623,6 +637,8 @@ impl VRDisplay {
|
||||||
|
|
||||||
fn stop_present(&self) {
|
fn stop_present(&self) {
|
||||||
self.presenting.set(false);
|
self.presenting.set(false);
|
||||||
|
let xr = self.global().as_window().Navigator().Xr();
|
||||||
|
xr.deactivate_session();
|
||||||
*self.frame_data_receiver.borrow_mut() = None;
|
*self.frame_data_receiver.borrow_mut() = None;
|
||||||
|
|
||||||
let api_sender = self.layer_ctx.get().unwrap().webgl_sender();
|
let api_sender = self.layer_ctx.get().unwrap().webgl_sender();
|
||||||
|
|
|
@ -17,7 +17,7 @@ interface XRSession : EventTarget {
|
||||||
// // Attributes
|
// // Attributes
|
||||||
readonly attribute XRSessionMode mode;
|
readonly attribute XRSessionMode mode;
|
||||||
// readonly attribute XRPresentationContext outputContext;
|
// readonly attribute XRPresentationContext outputContext;
|
||||||
// readonly attribute XREnvironmentBlendMode environmentBlendMode;
|
readonly attribute XREnvironmentBlendMode environmentBlendMode;
|
||||||
|
|
||||||
attribute double depthNear;
|
attribute double depthNear;
|
||||||
attribute double depthFar;
|
attribute double depthFar;
|
||||||
|
|
|
@ -10,7 +10,7 @@ use crate::dom::bindings::codegen::Bindings::XRBinding::{XRMethods, XRSessionMod
|
||||||
use crate::dom::bindings::error::Error;
|
use crate::dom::bindings::error::Error;
|
||||||
use crate::dom::bindings::inheritance::Castable;
|
use crate::dom::bindings::inheritance::Castable;
|
||||||
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject};
|
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject};
|
||||||
use crate::dom::bindings::root::{Dom, DomRoot};
|
use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom};
|
||||||
use crate::dom::event::Event;
|
use crate::dom::event::Event;
|
||||||
use crate::dom::eventtarget::EventTarget;
|
use crate::dom::eventtarget::EventTarget;
|
||||||
use crate::dom::gamepad::Gamepad;
|
use crate::dom::gamepad::Gamepad;
|
||||||
|
@ -23,6 +23,7 @@ use crate::dom::xrsession::XRSession;
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
use ipc_channel::ipc::IpcSender;
|
use ipc_channel::ipc::IpcSender;
|
||||||
use profile_traits::ipc;
|
use profile_traits::ipc;
|
||||||
|
use std::cell::Cell;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use webvr_traits::{WebVRDisplayData, WebVRDisplayEvent, WebVREvent, WebVRMsg};
|
use webvr_traits::{WebVRDisplayData, WebVRDisplayEvent, WebVREvent, WebVRMsg};
|
||||||
use webvr_traits::{WebVRGamepadData, WebVRGamepadEvent, WebVRGamepadState};
|
use webvr_traits::{WebVRGamepadData, WebVRGamepadEvent, WebVRGamepadState};
|
||||||
|
@ -32,6 +33,8 @@ pub struct XR {
|
||||||
eventtarget: EventTarget,
|
eventtarget: EventTarget,
|
||||||
displays: DomRefCell<Vec<Dom<VRDisplay>>>,
|
displays: DomRefCell<Vec<Dom<VRDisplay>>>,
|
||||||
gamepads: DomRefCell<Vec<Dom<Gamepad>>>,
|
gamepads: DomRefCell<Vec<Dom<Gamepad>>>,
|
||||||
|
pending_immersive_session: Cell<bool>,
|
||||||
|
active_immersive_session: MutNullableDom<VRDisplay>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl XR {
|
impl XR {
|
||||||
|
@ -40,6 +43,8 @@ impl XR {
|
||||||
eventtarget: EventTarget::new_inherited(),
|
eventtarget: EventTarget::new_inherited(),
|
||||||
displays: DomRefCell::new(Vec::new()),
|
displays: DomRefCell::new(Vec::new()),
|
||||||
gamepads: DomRefCell::new(Vec::new()),
|
gamepads: DomRefCell::new(Vec::new()),
|
||||||
|
pending_immersive_session: Cell::new(false),
|
||||||
|
active_immersive_session: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,6 +53,26 @@ impl XR {
|
||||||
root.register();
|
root.register();
|
||||||
root
|
root
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn pending_or_active_session(&self) -> bool {
|
||||||
|
self.pending_immersive_session.get() || self.active_immersive_session.get().is_some()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_pending(&self) {
|
||||||
|
self.pending_immersive_session.set(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_active_immersive_session(&self, session: &VRDisplay) {
|
||||||
|
// XXXManishearth when we support non-immersive (inline) sessions we should
|
||||||
|
// ensure they never reach these codepaths
|
||||||
|
self.pending_immersive_session.set(false);
|
||||||
|
self.active_immersive_session.set(Some(session))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deactivate_session(&self) {
|
||||||
|
self.pending_immersive_session.set(false);
|
||||||
|
self.active_immersive_session.set(None)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for XR {
|
impl Drop for XR {
|
||||||
|
@ -79,6 +104,13 @@ impl XRMethods for XR {
|
||||||
return promise;
|
return promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if self.pending_or_active_session() {
|
||||||
|
promise.reject_error(Error::InvalidState);
|
||||||
|
return promise;
|
||||||
|
}
|
||||||
|
// we set pending immersive session to true further down
|
||||||
|
// to handle rejections in a cleaner way
|
||||||
|
|
||||||
let displays = self.get_displays();
|
let displays = self.get_displays();
|
||||||
|
|
||||||
let displays = match displays {
|
let displays = match displays {
|
||||||
|
@ -94,6 +126,8 @@ impl XRMethods for XR {
|
||||||
promise.reject_error(Error::Security);
|
promise.reject_error(Error::Security);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.set_pending();
|
||||||
|
|
||||||
let session = XRSession::new(&self.global(), &displays[0]);
|
let session = XRSession::new(&self.global(), &displays[0]);
|
||||||
session.xr_present(promise.clone());
|
session.xr_present(promise.clone());
|
||||||
promise
|
promise
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
use crate::dom::bindings::codegen::Bindings::VRDisplayBinding::VRDisplayMethods;
|
use crate::dom::bindings::codegen::Bindings::VRDisplayBinding::VRDisplayMethods;
|
||||||
use crate::dom::bindings::codegen::Bindings::XRBinding::XRSessionMode;
|
use crate::dom::bindings::codegen::Bindings::XRBinding::XRSessionMode;
|
||||||
use crate::dom::bindings::codegen::Bindings::XRSessionBinding;
|
use crate::dom::bindings::codegen::Bindings::XRSessionBinding;
|
||||||
|
use crate::dom::bindings::codegen::Bindings::XRSessionBinding::XREnvironmentBlendMode;
|
||||||
use crate::dom::bindings::codegen::Bindings::XRSessionBinding::XRFrameRequestCallback;
|
use crate::dom::bindings::codegen::Bindings::XRSessionBinding::XRFrameRequestCallback;
|
||||||
use crate::dom::bindings::codegen::Bindings::XRSessionBinding::XRSessionMethods;
|
use crate::dom::bindings::codegen::Bindings::XRSessionBinding::XRSessionMethods;
|
||||||
use crate::dom::bindings::codegen::Bindings::XRWebGLLayerBinding::XRWebGLLayerMethods;
|
use crate::dom::bindings::codegen::Bindings::XRWebGLLayerBinding::XRWebGLLayerMethods;
|
||||||
|
@ -26,6 +27,7 @@ pub struct XRSession {
|
||||||
eventtarget: EventTarget,
|
eventtarget: EventTarget,
|
||||||
display: Dom<VRDisplay>,
|
display: Dom<VRDisplay>,
|
||||||
base_layer: MutNullableDom<XRLayer>,
|
base_layer: MutNullableDom<XRLayer>,
|
||||||
|
blend_mode: XREnvironmentBlendMode,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl XRSession {
|
impl XRSession {
|
||||||
|
@ -34,6 +36,8 @@ impl XRSession {
|
||||||
eventtarget: EventTarget::new_inherited(),
|
eventtarget: EventTarget::new_inherited(),
|
||||||
display: Dom::from_ref(display),
|
display: Dom::from_ref(display),
|
||||||
base_layer: Default::default(),
|
base_layer: Default::default(),
|
||||||
|
// we don't yet support any AR devices
|
||||||
|
blend_mode: XREnvironmentBlendMode::Opaque,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,4 +106,9 @@ impl XRSessionMethods for XRSession {
|
||||||
fn CancelAnimationFrame(&self, frame: i32) {
|
fn CancelAnimationFrame(&self, frame: i32) {
|
||||||
self.display.xr_cancel_raf(frame)
|
self.display.xr_cancel_raf(frame)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// https://immersive-web.github.io/webxr/#dom-xrsession-environmentblendmode
|
||||||
|
fn EnvironmentBlendMode(&self) -> XREnvironmentBlendMode {
|
||||||
|
self.blend_mode
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue