mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
webxr: Update XRSession to latest spec (#33059)
* Add missing XRSession members, initial implementations Signed-off-by: Daniel Adams <msub2official@gmail.com> * Implement supportedFramerates getter Signed-off-by: Daniel Adams <msub2official@gmail.com> * Implement framerate changes, add spec links Signed-off-by: Daniel Adams <msub2official@gmail.com> * Update WPT expectations Signed-off-by: Daniel Adams <msub2official@gmail.com> * ./mach fmt Signed-off-by: Daniel Adams <msub2official@gmail.com> * Add missing spec link Signed-off-by: Daniel Adams <msub2official@gmail.com> --------- Signed-off-by: Daniel Adams <msub2official@gmail.com>
This commit is contained in:
parent
f0045a7686
commit
20273b062a
7 changed files with 132 additions and 62 deletions
|
@ -117,7 +117,7 @@ DOMInterfaces = {
|
|||
},
|
||||
|
||||
'XRSession': {
|
||||
'inRealms': ['UpdateRenderState', 'RequestReferenceSpace'],
|
||||
'inRealms': ['UpdateRenderState', 'RequestReferenceSpace', 'UpdateTargetFrameRate'],
|
||||
},
|
||||
|
||||
'Bluetooth': {
|
||||
|
|
|
@ -27,11 +27,16 @@ callback XRFrameRequestCallback = undefined (DOMHighResTimeStamp time, XRFrame f
|
|||
interface XRSession : EventTarget {
|
||||
// Attributes
|
||||
readonly attribute XRVisibilityState visibilityState;
|
||||
readonly attribute float? frameRate;
|
||||
readonly attribute Float32Array? supportedFrameRates;
|
||||
[SameObject] readonly attribute XRRenderState renderState;
|
||||
[SameObject] readonly attribute XRInputSourceArray inputSources;
|
||||
readonly attribute /*FrozenArray<DOMString>*/ any enabledFeatures;
|
||||
readonly attribute boolean isSystemKeyboardSupported;
|
||||
|
||||
// Methods
|
||||
[Throws] undefined updateRenderState(optional XRRenderStateInit state = {});
|
||||
Promise<undefined> updateTargetFrameRate(float rate);
|
||||
Promise<XRReferenceSpace> requestReferenceSpace(XRReferenceSpaceType type);
|
||||
|
||||
long requestAnimationFrame(XRFrameRequestCallback callback);
|
||||
|
@ -49,6 +54,7 @@ interface XRSession : EventTarget {
|
|||
attribute EventHandler onsqueezestart;
|
||||
attribute EventHandler onsqueezeend;
|
||||
attribute EventHandler onvisibilitychange;
|
||||
attribute EventHandler onframeratechange;
|
||||
|
||||
// AR Module
|
||||
// Attributes
|
||||
|
|
|
@ -5,15 +5,19 @@
|
|||
use std::cell::Cell;
|
||||
use std::collections::HashMap;
|
||||
use std::f64::consts::{FRAC_PI_2, PI};
|
||||
use std::mem;
|
||||
use std::rc::Rc;
|
||||
use std::{mem, ptr};
|
||||
|
||||
use dom_struct::dom_struct;
|
||||
use euclid::{RigidTransform3D, Transform3D, Vector3D};
|
||||
use ipc_channel::ipc::IpcReceiver;
|
||||
use ipc_channel::router::ROUTER;
|
||||
use js::jsapi::JSObject;
|
||||
use js::jsval::JSVal;
|
||||
use js::typedarray::Float32Array;
|
||||
use metrics::ToMs;
|
||||
use profile_traits::ipc;
|
||||
use servo_atoms::Atom;
|
||||
use webxr_api::{
|
||||
self, util, ApiSpace, ContextId as WebXRContextId, Display, EntityTypes, EnvironmentBlendMode,
|
||||
Event as XREvent, Frame, FrameUpdateEvent, HitTestId, HitTestSource, InputFrame, InputId, Ray,
|
||||
|
@ -21,6 +25,7 @@ use webxr_api::{
|
|||
};
|
||||
|
||||
use super::bindings::trace::HashMapTracedValues;
|
||||
use crate::dom::bindings::buffer_source::create_buffer_source;
|
||||
use crate::dom::bindings::callback::ExceptionHandling;
|
||||
use crate::dom::bindings::cell::DomRefCell;
|
||||
use crate::dom::bindings::codegen::Bindings::NavigatorBinding::Navigator_Binding::NavigatorMethods;
|
||||
|
@ -39,9 +44,11 @@ use crate::dom::bindings::codegen::Bindings::XRSessionBinding::{
|
|||
use crate::dom::bindings::codegen::Bindings::XRSystemBinding::XRSessionMode;
|
||||
use crate::dom::bindings::error::{Error, ErrorResult};
|
||||
use crate::dom::bindings::inheritance::Castable;
|
||||
use crate::dom::bindings::num::Finite;
|
||||
use crate::dom::bindings::refcounted::Trusted;
|
||||
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject};
|
||||
use crate::dom::bindings::root::{Dom, DomRoot, MutDom, MutNullableDom};
|
||||
use crate::dom::bindings::utils::to_frozen_array;
|
||||
use crate::dom::event::Event;
|
||||
use crate::dom::eventtarget::EventTarget;
|
||||
use crate::dom::globalscope::GlobalScope;
|
||||
|
@ -56,6 +63,7 @@ use crate::dom::xrrenderstate::XRRenderState;
|
|||
use crate::dom::xrsessionevent::XRSessionEvent;
|
||||
use crate::dom::xrspace::XRSpace;
|
||||
use crate::realms::InRealm;
|
||||
use crate::script_runtime::JSContext;
|
||||
use crate::task_source::TaskSource;
|
||||
|
||||
#[dom_struct]
|
||||
|
@ -97,6 +105,9 @@ pub struct XRSession {
|
|||
#[ignore_malloc_size_of = "defined in webxr"]
|
||||
#[no_trace]
|
||||
input_frames: DomRefCell<HashMap<InputId, InputFrame>>,
|
||||
framerate: Cell<f32>,
|
||||
#[ignore_malloc_size_of = "promises are hard"]
|
||||
update_framerate_promise: DomRefCell<Option<Rc<Promise>>>,
|
||||
}
|
||||
|
||||
impl XRSession {
|
||||
|
@ -128,6 +139,8 @@ impl XRSession {
|
|||
pending_hit_test_promises: DomRefCell::new(HashMapTracedValues::new()),
|
||||
outside_raf: Cell::new(true),
|
||||
input_frames: DomRefCell::new(HashMap::new()),
|
||||
framerate: Cell::new(0.0),
|
||||
update_framerate_promise: DomRefCell::new(None),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -543,6 +556,24 @@ impl XRSession {
|
|||
_ => self.session.borrow_mut().apply_event(event),
|
||||
}
|
||||
}
|
||||
|
||||
/// <https://www.w3.org/TR/webxr/#apply-the-nominal-frame-rate>
|
||||
fn apply_nominal_framerate(&self, rate: f32) {
|
||||
if self.framerate.get() == rate || self.ended.get() {
|
||||
return;
|
||||
}
|
||||
|
||||
self.framerate.set(rate);
|
||||
|
||||
let event = XRSessionEvent::new(
|
||||
&self.global(),
|
||||
Atom::from("frameratechange"),
|
||||
false,
|
||||
false,
|
||||
self,
|
||||
);
|
||||
event.upcast::<Event>().fire(self.upcast());
|
||||
}
|
||||
}
|
||||
|
||||
impl XRSessionMethods for XRSession {
|
||||
|
@ -581,6 +612,9 @@ impl XRSessionMethods for XRSession {
|
|||
SetOninputsourceschange
|
||||
);
|
||||
|
||||
// https://www.w3.org/TR/webxr/#dom-xrsession-onframeratechange
|
||||
event_handler!(frameratechange, GetOnframeratechange, SetOnframeratechange);
|
||||
|
||||
// https://immersive-web.github.io/webxr/#dom-xrsession-renderstate
|
||||
fn RenderState(&self) -> DomRoot<XRRenderState> {
|
||||
self.active_render_state.get()
|
||||
|
@ -881,6 +915,96 @@ impl XRSessionMethods for XRSession {
|
|||
// this should always be world space
|
||||
XRInteractionMode::World_space
|
||||
}
|
||||
|
||||
/// <https://www.w3.org/TR/webxr/#dom-xrsession-framerate>
|
||||
fn GetFrameRate(&self) -> Option<Finite<f32>> {
|
||||
let session = self.session.borrow();
|
||||
if self.mode == XRSessionMode::Inline || session.supported_frame_rates().is_empty() {
|
||||
None
|
||||
} else {
|
||||
Finite::new(self.framerate.get())
|
||||
}
|
||||
}
|
||||
|
||||
/// <https://www.w3.org/TR/webxr/#dom-xrsession-supportedframerates>
|
||||
fn GetSupportedFrameRates(&self, cx: JSContext) -> Option<Float32Array> {
|
||||
let session = self.session.borrow();
|
||||
if self.mode == XRSessionMode::Inline || session.supported_frame_rates().is_empty() {
|
||||
None
|
||||
} else {
|
||||
let framerates = session.supported_frame_rates();
|
||||
rooted!(in (*cx) let mut array = ptr::null_mut::<JSObject>());
|
||||
Some(
|
||||
create_buffer_source(cx, framerates, array.handle_mut())
|
||||
.expect("Failed to construct supported frame rates array"),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// <https://www.w3.org/TR/webxr/#dom-xrsession-enabledfeatures>
|
||||
fn EnabledFeatures(&self, cx: JSContext) -> JSVal {
|
||||
let session = self.session.borrow();
|
||||
let features = session.granted_features();
|
||||
to_frozen_array(features, cx)
|
||||
}
|
||||
|
||||
/// <https://www.w3.org/TR/webxr/#dom-xrsession-issystemkeyboardsupported>
|
||||
fn IsSystemKeyboardSupported(&self) -> bool {
|
||||
// Support for this only exists on Meta headsets (no desktop support)
|
||||
// so this will always be false until that changes
|
||||
false
|
||||
}
|
||||
|
||||
/// <https://www.w3.org/TR/webxr/#dom-xrsession-updatetargetframerate>
|
||||
fn UpdateTargetFrameRate(&self, rate: Finite<f32>, comp: InRealm) -> Rc<Promise> {
|
||||
let mut session = self.session.borrow_mut();
|
||||
let supported_frame_rates = session.supported_frame_rates();
|
||||
let promise = Promise::new_in_current_realm(comp);
|
||||
|
||||
if self.mode == XRSessionMode::Inline ||
|
||||
supported_frame_rates.is_empty() ||
|
||||
self.ended.get()
|
||||
{
|
||||
promise.reject_error(Error::InvalidState);
|
||||
return promise;
|
||||
}
|
||||
|
||||
if !supported_frame_rates.contains(&*rate) {
|
||||
promise.reject_error(Error::Type("Provided framerate not supported".into()));
|
||||
return promise;
|
||||
}
|
||||
|
||||
*self.update_framerate_promise.borrow_mut() = Some(promise.clone());
|
||||
|
||||
let this = Trusted::new(self);
|
||||
let global = self.global();
|
||||
let window = global.as_window();
|
||||
let (task_source, canceller) = window
|
||||
.task_manager()
|
||||
.dom_manipulation_task_source_with_canceller();
|
||||
let (sender, receiver) = ipc::channel(global.time_profiler_chan().clone()).unwrap();
|
||||
|
||||
ROUTER.add_route(
|
||||
receiver.to_opaque(),
|
||||
Box::new(move |message| {
|
||||
let this = this.clone();
|
||||
let _ = task_source.queue_with_canceller(
|
||||
task!(update_session_framerate: move || {
|
||||
let session = this.root();
|
||||
session.apply_nominal_framerate(message.to().unwrap());
|
||||
if let Some(promise) = session.update_framerate_promise.borrow_mut().take() {
|
||||
promise.resolve_native(&());
|
||||
};
|
||||
}),
|
||||
&canceller,
|
||||
);
|
||||
}),
|
||||
);
|
||||
|
||||
session.update_frame_rate(*rate, sender);
|
||||
|
||||
promise
|
||||
}
|
||||
}
|
||||
|
||||
// The pose of an object in native-space. Should never be exposed.
|
||||
|
|
|
@ -1,16 +1,4 @@
|
|||
[depth_sensing_preferences.https.html]
|
||||
[depthSensing - Required - Fully populated grants session]
|
||||
expected: FAIL
|
||||
|
||||
[depthSensing - Required - Empty usage grants session]
|
||||
expected: FAIL
|
||||
|
||||
[depthSensing - Required - Empty format grants session]
|
||||
expected: FAIL
|
||||
|
||||
[depthSensing - Required - Empty usage and format grants session]
|
||||
expected: FAIL
|
||||
|
||||
[depthSensing - Required - Missing usage rejects session]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -335,18 +335,6 @@
|
|||
[XRWebGLLayer interface: xrWebGLLayer must inherit property "fixedFoveation" with the proper type]
|
||||
expected: FAIL
|
||||
|
||||
[XRSession interface: attribute frameRate]
|
||||
expected: FAIL
|
||||
|
||||
[XRSession interface: attribute supportedFrameRates]
|
||||
expected: FAIL
|
||||
|
||||
[XRSession interface: operation updateTargetFrameRate(float)]
|
||||
expected: FAIL
|
||||
|
||||
[XRSession interface: attribute onframeratechange]
|
||||
expected: FAIL
|
||||
|
||||
[XRSession interface: xrSession must inherit property "frameRate" with the proper type]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -365,15 +353,9 @@
|
|||
[XRFrame interface: attribute predictedDisplayTime]
|
||||
expected: FAIL
|
||||
|
||||
[XRSession interface: attribute enabledFeatures]
|
||||
expected: FAIL
|
||||
|
||||
[XRSession interface: xrSession must inherit property "enabledFeatures" with the proper type]
|
||||
expected: FAIL
|
||||
|
||||
[XRSession interface: attribute isSystemKeyboardSupported]
|
||||
expected: FAIL
|
||||
|
||||
[XRSession interface: xrSession must inherit property "isSystemKeyboardSupported" with the proper type]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -1,16 +1,4 @@
|
|||
[depth_sensing_preferences.https.html]
|
||||
[depthSensing - Required - Fully populated grants session]
|
||||
expected: FAIL
|
||||
|
||||
[depthSensing - Required - Empty usage grants session]
|
||||
expected: FAIL
|
||||
|
||||
[depthSensing - Required - Empty format grants session]
|
||||
expected: FAIL
|
||||
|
||||
[depthSensing - Required - Empty usage and format grants session]
|
||||
expected: FAIL
|
||||
|
||||
[depthSensing - Required - Missing usage rejects session]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -278,18 +278,6 @@
|
|||
[XRWebGLLayer interface: xrWebGLLayer must inherit property "fixedFoveation" with the proper type]
|
||||
expected: FAIL
|
||||
|
||||
[XRSession interface: attribute frameRate]
|
||||
expected: FAIL
|
||||
|
||||
[XRSession interface: attribute supportedFrameRates]
|
||||
expected: FAIL
|
||||
|
||||
[XRSession interface: operation updateTargetFrameRate(float)]
|
||||
expected: FAIL
|
||||
|
||||
[XRSession interface: attribute onframeratechange]
|
||||
expected: FAIL
|
||||
|
||||
[XRSession interface: xrSession must inherit property "frameRate" with the proper type]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -308,15 +296,9 @@
|
|||
[XRFrame interface: attribute predictedDisplayTime]
|
||||
expected: FAIL
|
||||
|
||||
[XRSession interface: attribute enabledFeatures]
|
||||
expected: FAIL
|
||||
|
||||
[XRSession interface: xrSession must inherit property "enabledFeatures" with the proper type]
|
||||
expected: FAIL
|
||||
|
||||
[XRSession interface: attribute isSystemKeyboardSupported]
|
||||
expected: FAIL
|
||||
|
||||
[XRSession interface: xrSession must inherit property "isSystemKeyboardSupported" with the proper type]
|
||||
expected: FAIL
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue