mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +01:00
Auto merge of #23485 - Manishearth:xrtest, r=asajeffrey
Basic XR Testing support This adds support for the XRTest and FakeXRDeviceController APIs from https://github.com/immersive-web/webxr-test-api, and plugs them into the `mock` backend of rust-webvr. Tested with [a modified webxr test page](https://github.com/immersive-web/webxr-test-api) r? @jdm @asajeffrey <!-- 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/23485) <!-- Reviewable:end -->
This commit is contained in:
commit
7c8a4ecead
18 changed files with 306 additions and 13 deletions
16
Cargo.lock
generated
16
Cargo.lock
generated
|
@ -3590,7 +3590,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rust-webvr"
|
name = "rust-webvr"
|
||||||
version = "0.11.1"
|
version = "0.11.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bindgen 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bindgen 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -3603,12 +3603,12 @@ dependencies = [
|
||||||
"libloading 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libloading 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"ovr-mobile-sys 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ovr-mobile-sys 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rust-webvr-api 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rust-webvr-api 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rust-webvr-api"
|
name = "rust-webvr-api"
|
||||||
version = "0.11.0"
|
version = "0.11.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"android_injected_glue 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"android_injected_glue 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -3948,7 +3948,7 @@ dependencies = [
|
||||||
"mozangle 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"mozangle 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"osmesa-src 0.1.0 (git+https://github.com/servo/osmesa-src)",
|
"osmesa-src 0.1.0 (git+https://github.com/servo/osmesa-src)",
|
||||||
"osmesa-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"osmesa-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rust-webvr 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rust-webvr 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"sig 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"sig 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"tinyfiledialogs 3.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"tinyfiledialogs 3.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -5267,7 +5267,7 @@ dependencies = [
|
||||||
"ipc-channel 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ipc-channel 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"msg 0.0.1",
|
"msg 0.0.1",
|
||||||
"rust-webvr 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rust-webvr 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"script_traits 0.0.1",
|
"script_traits 0.0.1",
|
||||||
"servo_config 0.0.1",
|
"servo_config 0.0.1",
|
||||||
"webvr_traits 0.0.1",
|
"webvr_traits 0.0.1",
|
||||||
|
@ -5279,7 +5279,7 @@ version = "0.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ipc-channel 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ipc-channel 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"msg 0.0.1",
|
"msg 0.0.1",
|
||||||
"rust-webvr-api 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rust-webvr-api 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -5782,8 +5782,8 @@ dependencies = [
|
||||||
"checksum regex-syntax 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "dcfd8681eebe297b81d98498869d4aae052137651ad7b96822f09ceb690d0a96"
|
"checksum regex-syntax 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "dcfd8681eebe297b81d98498869d4aae052137651ad7b96822f09ceb690d0a96"
|
||||||
"checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5"
|
"checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5"
|
||||||
"checksum ron 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "da06feaa07f69125ab9ddc769b11de29090122170b402547f64b86fe16ebc399"
|
"checksum ron 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "da06feaa07f69125ab9ddc769b11de29090122170b402547f64b86fe16ebc399"
|
||||||
"checksum rust-webvr 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c5b30e882ddadf407de2229bf6bf0f1adde250b6dee10357ba4f8c4a51c0ab15"
|
"checksum rust-webvr 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7a171c39fdd52c5b461f2384a04e2d75555c7ed657c057c45ea9d69d68b5f9fb"
|
||||||
"checksum rust-webvr-api 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b5208a3b3f0b02abf17e66c0fe1e0cd3a4f5172c9bf6d1a3e1ac6338a3d218d3"
|
"checksum rust-webvr-api 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c5611b60f8a26ad5af2b8d6ac072f9e1b396305e8eb19efd5a6df84c588b1429"
|
||||||
"checksum rustc-demangle 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3058a43ada2c2d0b92b3ae38007a2d0fa5e9db971be260e0171408a4ff471c95"
|
"checksum rustc-demangle 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3058a43ada2c2d0b92b3ae38007a2d0fa5e9db971be260e0171408a4ff471c95"
|
||||||
"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
|
"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
|
||||||
"checksum rusttype 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b8eb11f5b0a98c8eca2fb1483f42646d8c340e83e46ab416f8a063a0fd0eeb20"
|
"checksum rusttype 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b8eb11f5b0a98c8eca2fb1483f42646d8c340e83e46ab416f8a063a0fd0eeb20"
|
||||||
|
|
|
@ -294,6 +294,8 @@ mod gen {
|
||||||
webxr: {
|
webxr: {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
enabled: bool,
|
enabled: bool,
|
||||||
|
#[serde(default)]
|
||||||
|
test: bool,
|
||||||
},
|
},
|
||||||
worklet: {
|
worklet: {
|
||||||
blockingsleep: {
|
blockingsleep: {
|
||||||
|
|
104
components/script/dom/fakexrdevicecontroller.rs
Normal file
104
components/script/dom/fakexrdevicecontroller.rs
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
use crate::dom::bindings::codegen::Bindings::FakeXRDeviceControllerBinding::{
|
||||||
|
self, FakeXRDeviceControllerMethods, FakeXRRigidTransform, FakeXRViewInit,
|
||||||
|
};
|
||||||
|
use crate::dom::bindings::codegen::Bindings::XRViewBinding::XREye;
|
||||||
|
use crate::dom::bindings::error::{Error, Fallible};
|
||||||
|
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector};
|
||||||
|
use crate::dom::bindings::root::DomRoot;
|
||||||
|
use crate::dom::globalscope::GlobalScope;
|
||||||
|
use dom_struct::dom_struct;
|
||||||
|
use webvr_traits::{MockVRControlMsg, WebVREyeParameters, WebVRMsg};
|
||||||
|
|
||||||
|
#[dom_struct]
|
||||||
|
pub struct FakeXRDeviceController {
|
||||||
|
reflector: Reflector,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FakeXRDeviceController {
|
||||||
|
pub fn new_inherited() -> FakeXRDeviceController {
|
||||||
|
FakeXRDeviceController {
|
||||||
|
reflector: Reflector::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new(global: &GlobalScope) -> DomRoot<FakeXRDeviceController> {
|
||||||
|
reflect_dom_object(
|
||||||
|
Box::new(FakeXRDeviceController::new_inherited()),
|
||||||
|
global,
|
||||||
|
FakeXRDeviceControllerBinding::Wrap,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn send_msg(&self, msg: MockVRControlMsg) {
|
||||||
|
self.global()
|
||||||
|
.as_window()
|
||||||
|
.webvr_thread()
|
||||||
|
.unwrap()
|
||||||
|
.send(WebVRMsg::MessageMockDisplay(msg))
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FakeXRDeviceControllerMethods for FakeXRDeviceController {
|
||||||
|
/// https://github.com/immersive-web/webxr-test-api/blob/master/explainer.md
|
||||||
|
fn SetViews(&self, views: Vec<FakeXRViewInit>) -> Fallible<()> {
|
||||||
|
if views.len() != 2 {
|
||||||
|
return Err(Error::NotSupported);
|
||||||
|
}
|
||||||
|
|
||||||
|
let (left, right) = match (views[0].eye, views[1].eye) {
|
||||||
|
(XREye::Left, XREye::Right) => (&views[0], &views[1]),
|
||||||
|
(XREye::Right, XREye::Left) => (&views[1], &views[0]),
|
||||||
|
_ => return Err(Error::NotSupported),
|
||||||
|
};
|
||||||
|
|
||||||
|
if left.projectionMatrix.len() != 16 ||
|
||||||
|
right.projectionMatrix.len() != 16 ||
|
||||||
|
left.viewOffset.position.len() != 4 ||
|
||||||
|
right.viewOffset.position.len() != 4
|
||||||
|
{
|
||||||
|
return Err(Error::Type("Incorrectly sized array".into()));
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut proj_l = [0.; 16];
|
||||||
|
let mut proj_r = [0.; 16];
|
||||||
|
let v: Vec<_> = left.projectionMatrix.iter().map(|x| **x).collect();
|
||||||
|
proj_l.copy_from_slice(&v);
|
||||||
|
let v: Vec<_> = right.projectionMatrix.iter().map(|x| **x).collect();
|
||||||
|
proj_r.copy_from_slice(&v);
|
||||||
|
|
||||||
|
let mut params_l = WebVREyeParameters::default();
|
||||||
|
let mut params_r = WebVREyeParameters::default();
|
||||||
|
let v: Vec<_> = left.viewOffset.position.iter().map(|x| **x).collect();
|
||||||
|
params_l.offset.copy_from_slice(&v);
|
||||||
|
let v: Vec<_> = right.viewOffset.position.iter().map(|x| **x).collect();
|
||||||
|
params_r.offset.copy_from_slice(&v);
|
||||||
|
|
||||||
|
self.send_msg(MockVRControlMsg::SetProjectionMatrices(proj_l, proj_r));
|
||||||
|
self.send_msg(MockVRControlMsg::SetEyeParameters(params_l, params_r));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// https://github.com/immersive-web/webxr-test-api/blob/master/explainer.md
|
||||||
|
fn SetViewerOrigin(&self, origin: &FakeXRRigidTransform) -> Fallible<()> {
|
||||||
|
if origin.position.len() != 4 || origin.orientation.len() != 4 {
|
||||||
|
return Err(Error::Type("Incorrectly sized array".into()));
|
||||||
|
}
|
||||||
|
let mut position = [0.; 3];
|
||||||
|
let mut orientation = [0.; 4];
|
||||||
|
let v: Vec<_> = origin.position.iter().map(|x| **x).collect();
|
||||||
|
position.copy_from_slice(&v[0..3]);
|
||||||
|
let v: Vec<_> = origin.orientation.iter().map(|x| **x).collect();
|
||||||
|
orientation.copy_from_slice(&v);
|
||||||
|
self.send_msg(MockVRControlMsg::SetViewerPose(position, orientation));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
|
@ -301,6 +301,7 @@ pub mod eventsource;
|
||||||
pub mod eventtarget;
|
pub mod eventtarget;
|
||||||
pub mod extendableevent;
|
pub mod extendableevent;
|
||||||
pub mod extendablemessageevent;
|
pub mod extendablemessageevent;
|
||||||
|
pub mod fakexrdevicecontroller;
|
||||||
pub mod file;
|
pub mod file;
|
||||||
pub mod filelist;
|
pub mod filelist;
|
||||||
pub mod filereader;
|
pub mod filereader;
|
||||||
|
@ -551,6 +552,7 @@ pub mod xrrigidtransform;
|
||||||
pub mod xrsession;
|
pub mod xrsession;
|
||||||
pub mod xrspace;
|
pub mod xrspace;
|
||||||
pub mod xrstationaryreferencespace;
|
pub mod xrstationaryreferencespace;
|
||||||
|
pub mod xrtest;
|
||||||
pub mod xrview;
|
pub mod xrview;
|
||||||
pub mod xrviewerpose;
|
pub mod xrviewerpose;
|
||||||
pub mod xrviewport;
|
pub mod xrviewport;
|
||||||
|
|
49
components/script/dom/webidls/FakeXRDeviceController.webidl
Normal file
49
components/script/dom/webidls/FakeXRDeviceController.webidl
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
// https://github.com/immersive-web/webxr-test-api/
|
||||||
|
|
||||||
|
[Exposed=Window, Pref="dom.webxr.test"]
|
||||||
|
interface FakeXRDeviceController {
|
||||||
|
// Creates and attaches a XRFrameOfReference of the type specified to the device.
|
||||||
|
// void setFrameOfReference(XRFrameOfReferenceType, FakeXRFrameOfReferenceInit);
|
||||||
|
|
||||||
|
// // Sets the values to be used for subsequent
|
||||||
|
// // requestAnimationFrame() callbacks.
|
||||||
|
[Throws] void setViews(sequence<FakeXRViewInit> views);
|
||||||
|
|
||||||
|
[Throws] void setViewerOrigin(FakeXRRigidTransform origin);
|
||||||
|
|
||||||
|
// Simulates the user activating the reset pose on a device.
|
||||||
|
// void simulateResetPose();
|
||||||
|
|
||||||
|
// Simulates the platform ending the sessions.
|
||||||
|
// void simulateForcedEndSessions();
|
||||||
|
|
||||||
|
// Simulates devices focusing and blurring sessions.
|
||||||
|
// void simulateBlurSession(XRSession);
|
||||||
|
// void simulateFocusSession(XRSession);
|
||||||
|
|
||||||
|
// void setBoundsGeometry(Array<FakeXRBoundsPoint> boundsCoodinates)l
|
||||||
|
|
||||||
|
// Promise<FakeXRInputSourceController>
|
||||||
|
// simulateInputSourceConnection(FakeXRInputSourceInit);
|
||||||
|
};
|
||||||
|
|
||||||
|
dictionary FakeXRViewInit {
|
||||||
|
required XREye eye;
|
||||||
|
// https://immersive-web.github.io/webxr/#view-projection-matrix
|
||||||
|
required sequence<float> projectionMatrix;
|
||||||
|
// https://immersive-web.github.io/webxr/#view-offset
|
||||||
|
required FakeXRRigidTransform viewOffset;
|
||||||
|
};
|
||||||
|
|
||||||
|
dictionary FakeXRBoundsPoint {
|
||||||
|
double x; double z;
|
||||||
|
};
|
||||||
|
|
||||||
|
dictionary FakeXRRigidTransform {
|
||||||
|
required sequence<float> position;
|
||||||
|
required sequence<float> orientation;
|
||||||
|
};
|
|
@ -28,3 +28,8 @@ dictionary XRSessionCreationOptions {
|
||||||
XRSessionMode mode = "inline";
|
XRSessionMode mode = "inline";
|
||||||
// XRPresentationContext outputContext;
|
// XRPresentationContext outputContext;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
partial interface XR {
|
||||||
|
// https://github.com/immersive-web/webxr-test-api/
|
||||||
|
[SameObject, Pref="dom.webxr.test"] readonly attribute XRTest test;
|
||||||
|
};
|
||||||
|
|
25
components/script/dom/webidls/XRTest.webidl
Normal file
25
components/script/dom/webidls/XRTest.webidl
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
// https://github.com/immersive-web/webxr-test-api/
|
||||||
|
|
||||||
|
[Exposed=Window, Pref="dom.webxr.test"]
|
||||||
|
interface XRTest {
|
||||||
|
// Simulates connecting a device to the system.
|
||||||
|
// Used to instantiate a fake device for use in tests.
|
||||||
|
Promise<FakeXRDeviceController> simulateDeviceConnection(FakeXRDeviceInit init);
|
||||||
|
|
||||||
|
// // Simulates a device being disconnected from the system.
|
||||||
|
// Promise<void> simulateDeviceDisconnection(XRDevice);
|
||||||
|
|
||||||
|
// // Simulates a user activation (aka user gesture) for the current scope.
|
||||||
|
// // The activation is only guaranteed to be valid in the provided function and only applies to WebXR
|
||||||
|
// // Device API methods.
|
||||||
|
// void simulateUserActivation(Function);
|
||||||
|
};
|
||||||
|
|
||||||
|
dictionary FakeXRDeviceInit {
|
||||||
|
// TODO: Subject to change to match spec changes.
|
||||||
|
required boolean supportsImmersive;
|
||||||
|
};
|
|
@ -21,6 +21,7 @@ use crate::dom::promise::Promise;
|
||||||
use crate::dom::vrdisplay::VRDisplay;
|
use crate::dom::vrdisplay::VRDisplay;
|
||||||
use crate::dom::vrdisplayevent::VRDisplayEvent;
|
use crate::dom::vrdisplayevent::VRDisplayEvent;
|
||||||
use crate::dom::xrsession::XRSession;
|
use crate::dom::xrsession::XRSession;
|
||||||
|
use crate::dom::xrtest::XRTest;
|
||||||
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;
|
||||||
|
@ -36,6 +37,7 @@ pub struct XR {
|
||||||
gamepads: DomRefCell<Vec<Dom<Gamepad>>>,
|
gamepads: DomRefCell<Vec<Dom<Gamepad>>>,
|
||||||
pending_immersive_session: Cell<bool>,
|
pending_immersive_session: Cell<bool>,
|
||||||
active_immersive_session: MutNullableDom<VRDisplay>,
|
active_immersive_session: MutNullableDom<VRDisplay>,
|
||||||
|
test: MutNullableDom<XRTest>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl XR {
|
impl XR {
|
||||||
|
@ -46,6 +48,7 @@ impl XR {
|
||||||
gamepads: DomRefCell::new(Vec::new()),
|
gamepads: DomRefCell::new(Vec::new()),
|
||||||
pending_immersive_session: Cell::new(false),
|
pending_immersive_session: Cell::new(false),
|
||||||
active_immersive_session: Default::default(),
|
active_immersive_session: Default::default(),
|
||||||
|
test: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,6 +144,11 @@ impl XRMethods for XR {
|
||||||
session.xr_present(promise.clone());
|
session.xr_present(promise.clone());
|
||||||
promise
|
promise
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://github.com/immersive-web/webxr-test-api/blob/master/explainer.md
|
||||||
|
fn Test(&self) -> DomRoot<XRTest> {
|
||||||
|
self.test.or_init(|| XRTest::new(&self.global()))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl XR {
|
impl XR {
|
||||||
|
|
|
@ -99,7 +99,8 @@ impl XRSpace {
|
||||||
orient[1] as f64,
|
orient[1] as f64,
|
||||||
orient[2] as f64,
|
orient[2] as f64,
|
||||||
orient[3] as f64,
|
orient[3] as f64,
|
||||||
);
|
)
|
||||||
|
.normalize();
|
||||||
RigidTransform3D::new(rotation, translation)
|
RigidTransform3D::new(rotation, translation)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
66
components/script/dom/xrtest.rs
Normal file
66
components/script/dom/xrtest.rs
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
use crate::dom::bindings::codegen::Bindings::XRTestBinding::{
|
||||||
|
self, FakeXRDeviceInit, XRTestMethods,
|
||||||
|
};
|
||||||
|
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector};
|
||||||
|
use crate::dom::bindings::root::DomRoot;
|
||||||
|
use crate::dom::fakexrdevicecontroller::FakeXRDeviceController;
|
||||||
|
use crate::dom::globalscope::GlobalScope;
|
||||||
|
use crate::dom::promise::Promise;
|
||||||
|
use dom_struct::dom_struct;
|
||||||
|
use std::cell::Cell;
|
||||||
|
use std::rc::Rc;
|
||||||
|
use webvr_traits::WebVRMsg;
|
||||||
|
|
||||||
|
#[dom_struct]
|
||||||
|
pub struct XRTest {
|
||||||
|
reflector: Reflector,
|
||||||
|
session_started: Cell<bool>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl XRTest {
|
||||||
|
pub fn new_inherited() -> XRTest {
|
||||||
|
XRTest {
|
||||||
|
reflector: Reflector::new(),
|
||||||
|
session_started: Cell::new(false),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new(global: &GlobalScope) -> DomRoot<XRTest> {
|
||||||
|
reflect_dom_object(
|
||||||
|
Box::new(XRTest::new_inherited()),
|
||||||
|
global,
|
||||||
|
XRTestBinding::Wrap,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl XRTestMethods for XRTest {
|
||||||
|
/// https://github.com/immersive-web/webxr-test-api/blob/master/explainer.md
|
||||||
|
fn SimulateDeviceConnection(&self, init: &FakeXRDeviceInit) -> Rc<Promise> {
|
||||||
|
let p = Promise::new(&self.global());
|
||||||
|
|
||||||
|
if !init.supportsImmersive || self.session_started.get() {
|
||||||
|
p.reject_native(&());
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.session_started.set(true);
|
||||||
|
self.global()
|
||||||
|
.as_window()
|
||||||
|
.webvr_thread()
|
||||||
|
.unwrap()
|
||||||
|
.send(WebVRMsg::CreateMockDisplay)
|
||||||
|
.unwrap();
|
||||||
|
p.resolve_native(&FakeXRDeviceController::new(&self.global()));
|
||||||
|
|
||||||
|
p
|
||||||
|
}
|
||||||
|
}
|
|
@ -285,7 +285,7 @@ where
|
||||||
script::init();
|
script::init();
|
||||||
|
|
||||||
let mut webvr_heartbeats = Vec::new();
|
let mut webvr_heartbeats = Vec::new();
|
||||||
let webvr_services = if pref!(dom.webvr.enabled) {
|
let webvr_services = if pref!(dom.webvr.enabled) || pref!(dom.webxr.enabled) {
|
||||||
let mut services = VRServiceManager::new();
|
let mut services = VRServiceManager::new();
|
||||||
services.register_defaults();
|
services.register_defaults();
|
||||||
embedder.register_vr_services(&mut services, &mut webvr_heartbeats);
|
embedder.register_vr_services(&mut services, &mut webvr_heartbeats);
|
||||||
|
|
|
@ -19,10 +19,10 @@ canvas_traits = {path = "../canvas_traits"}
|
||||||
crossbeam-channel = "0.3"
|
crossbeam-channel = "0.3"
|
||||||
euclid = "0.19"
|
euclid = "0.19"
|
||||||
gleam = "0.6"
|
gleam = "0.6"
|
||||||
ipc-channel = "0.11"
|
ipc-channel = "0.11.2"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
msg = {path = "../msg"}
|
msg = {path = "../msg"}
|
||||||
rust-webvr = {version = "0.11", features = ["openvr", "vrexternal"]}
|
rust-webvr = {version = "0.11.3", features = ["mock", "openvr", "vrexternal"]}
|
||||||
script_traits = {path = "../script_traits"}
|
script_traits = {path = "../script_traits"}
|
||||||
servo_config = {path = "../config"}
|
servo_config = {path = "../config"}
|
||||||
webvr_traits = {path = "../webvr_traits" }
|
webvr_traits = {path = "../webvr_traits" }
|
||||||
|
|
|
@ -14,6 +14,7 @@ use script_traits::ConstellationMsg;
|
||||||
use servo_config::pref;
|
use servo_config::pref;
|
||||||
use std::collections::hash_map::Entry;
|
use std::collections::hash_map::Entry;
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
|
use std::sync::mpsc;
|
||||||
use std::{thread, time};
|
use std::{thread, time};
|
||||||
use webvr_traits::webvr::*;
|
use webvr_traits::webvr::*;
|
||||||
use webvr_traits::{WebVRMsg, WebVRPoseInformation, WebVRResult};
|
use webvr_traits::{WebVRMsg, WebVRPoseInformation, WebVRResult};
|
||||||
|
@ -46,6 +47,7 @@ pub struct WebVRThread {
|
||||||
vr_compositor_chan: WebVRCompositorSender,
|
vr_compositor_chan: WebVRCompositorSender,
|
||||||
polling_events: bool,
|
polling_events: bool,
|
||||||
presenting: HashMap<u32, PipelineId>,
|
presenting: HashMap<u32, PipelineId>,
|
||||||
|
mock: Option<mpsc::Sender<MockVRControlMsg>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WebVRThread {
|
impl WebVRThread {
|
||||||
|
@ -65,6 +67,7 @@ impl WebVRThread {
|
||||||
vr_compositor_chan: vr_compositor_chan,
|
vr_compositor_chan: vr_compositor_chan,
|
||||||
polling_events: false,
|
polling_events: false,
|
||||||
presenting: HashMap::new(),
|
presenting: HashMap::new(),
|
||||||
|
mock: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,6 +134,13 @@ impl WebVRThread {
|
||||||
WebVRMsg::GetGamepadsForDisplay(display_id, sender) => {
|
WebVRMsg::GetGamepadsForDisplay(display_id, sender) => {
|
||||||
self.handle_get_gamepads_for_display(display_id, sender);
|
self.handle_get_gamepads_for_display(display_id, sender);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
WebVRMsg::CreateMockDisplay => {
|
||||||
|
self.handle_create_mock();
|
||||||
|
},
|
||||||
|
WebVRMsg::MessageMockDisplay(msg) => {
|
||||||
|
self.handle_message_mock_display(msg);
|
||||||
|
},
|
||||||
WebVRMsg::Exit => break,
|
WebVRMsg::Exit => break,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -302,6 +312,22 @@ impl WebVRThread {
|
||||||
sender.send(Ok(data)).unwrap();
|
sender.send(Ok(data)).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn handle_create_mock(&mut self) {
|
||||||
|
if self.mock.is_some() {
|
||||||
|
warn!("Mock display already created");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
self.mock = Some(self.service.register_mock_with_remote());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_message_mock_display(&mut self, msg: MockVRControlMsg) {
|
||||||
|
self.mock
|
||||||
|
.as_ref()
|
||||||
|
.expect("Mock Display not yet set up")
|
||||||
|
.send(msg)
|
||||||
|
.expect("Could not send message to mock display");
|
||||||
|
}
|
||||||
|
|
||||||
fn poll_events(&mut self, sender: IpcSender<bool>) {
|
fn poll_events(&mut self, sender: IpcSender<bool>) {
|
||||||
loop {
|
loop {
|
||||||
let events = self.service.poll_events();
|
let events = self.service.poll_events();
|
||||||
|
|
|
@ -13,5 +13,5 @@ path = "lib.rs"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
ipc-channel = "0.11"
|
ipc-channel = "0.11"
|
||||||
msg = {path = "../msg"}
|
msg = {path = "../msg"}
|
||||||
rust-webvr-api = {version = "0.11", features = ["ipc"]}
|
rust-webvr-api = {version = "0.11.1", features = ["ipc"]}
|
||||||
serde = "1.0"
|
serde = "1.0"
|
||||||
|
|
|
@ -11,6 +11,7 @@ mod webvr_traits;
|
||||||
|
|
||||||
pub use crate::webvr_traits::{WebVRMsg, WebVRResult};
|
pub use crate::webvr_traits::{WebVRMsg, WebVRResult};
|
||||||
pub use rust_webvr_api as webvr;
|
pub use rust_webvr_api as webvr;
|
||||||
|
pub use rust_webvr_api::MockVRControlMsg;
|
||||||
pub use rust_webvr_api::VRDisplayCapabilities as WebVRDisplayCapabilities;
|
pub use rust_webvr_api::VRDisplayCapabilities as WebVRDisplayCapabilities;
|
||||||
pub use rust_webvr_api::VRDisplayData as WebVRDisplayData;
|
pub use rust_webvr_api::VRDisplayData as WebVRDisplayData;
|
||||||
pub use rust_webvr_api::VRDisplayEvent as WebVRDisplayEvent;
|
pub use rust_webvr_api::VRDisplayEvent as WebVRDisplayEvent;
|
||||||
|
|
|
@ -26,6 +26,8 @@ pub enum WebVRMsg {
|
||||||
RequestPresent(PipelineId, u32, IpcSender<WebVRResult<()>>),
|
RequestPresent(PipelineId, u32, IpcSender<WebVRResult<()>>),
|
||||||
ExitPresent(PipelineId, u32, Option<IpcSender<WebVRResult<()>>>),
|
ExitPresent(PipelineId, u32, Option<IpcSender<WebVRResult<()>>>),
|
||||||
CreateCompositor(u32),
|
CreateCompositor(u32),
|
||||||
|
CreateMockDisplay,
|
||||||
|
MessageMockDisplay(MockVRControlMsg),
|
||||||
GetGamepads(
|
GetGamepads(
|
||||||
Vec<u32>,
|
Vec<u32>,
|
||||||
IpcSender<WebVRResult<Vec<(Option<VRGamepadData>, VRGamepadState)>>>,
|
IpcSender<WebVRResult<Vec<(Option<VRGamepadData>, VRGamepadState)>>>,
|
||||||
|
|
|
@ -98,6 +98,7 @@ WEBIDL_STANDARDS = [
|
||||||
"//wicg.github.io",
|
"//wicg.github.io",
|
||||||
"//webaudio.github.io",
|
"//webaudio.github.io",
|
||||||
"//immersive-web.github.io/",
|
"//immersive-web.github.io/",
|
||||||
|
"//github.com/immersive-web/webxr-test-api/",
|
||||||
# Not a URL
|
# Not a URL
|
||||||
"// This interface is entirely internal to Servo, and should not be" +
|
"// This interface is entirely internal to Servo, and should not be" +
|
||||||
" accessible to\n// web pages."
|
" accessible to\n// web pages."
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
"dom.webvr.event_polling_interval": 500,
|
"dom.webvr.event_polling_interval": 500,
|
||||||
"dom.webvr.test": false,
|
"dom.webvr.test": false,
|
||||||
"dom.webxr.enabled": false,
|
"dom.webxr.enabled": false,
|
||||||
|
"dom.webxr.test": false,
|
||||||
"dom.worklet.timeout_ms": 10,
|
"dom.worklet.timeout_ms": 10,
|
||||||
"gfx.subpixel-text-antialiasing.enabled": true,
|
"gfx.subpixel-text-antialiasing.enabled": true,
|
||||||
"js.asmjs.enabled": true,
|
"js.asmjs.enabled": true,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue