mirror of
https://github.com/servo/servo.git
synced 2025-08-03 20:50:07 +01:00
Auto merge of #22528 - Manishearth:webxr, r=jdm,MortimerGoro
Preliminary WebXR support This implements just enough WebXR to display to 3DOF devices in immersive mode only. Couple missing things: - [ ] Handling reference spaces (even if just supporting eye-level spaces) - [x] Spec links - [ ] We enter immersive mode when baseLayer is set, but it seems like we're supposed to do this when requestSession is called (https://github.com/immersive-web/webxr/issues/453) - [ ] VR/XR should block less (https://github.com/servo/servo/issues/22505) - [x] More pref-gating - [x] `views` is a method instead of an attribute because we don't support FrozenArray <s>Once I add spec links and pref gating</s> this can be landed as-is for further experimentation. r? @jdm @MortimerGoro <!-- 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/22528) <!-- Reviewable:end -->
This commit is contained in:
commit
c4a6dcfe4b
33 changed files with 1092 additions and 71 deletions
|
@ -479,7 +479,6 @@ pub mod validation;
|
||||||
pub mod validitystate;
|
pub mod validitystate;
|
||||||
pub mod values;
|
pub mod values;
|
||||||
pub mod virtualmethods;
|
pub mod virtualmethods;
|
||||||
pub mod vr;
|
|
||||||
pub mod vrdisplay;
|
pub mod vrdisplay;
|
||||||
pub mod vrdisplaycapabilities;
|
pub mod vrdisplaycapabilities;
|
||||||
pub mod vrdisplayevent;
|
pub mod vrdisplayevent;
|
||||||
|
@ -518,3 +517,15 @@ pub mod xmldocument;
|
||||||
pub mod xmlhttprequest;
|
pub mod xmlhttprequest;
|
||||||
pub mod xmlhttprequesteventtarget;
|
pub mod xmlhttprequesteventtarget;
|
||||||
pub mod xmlhttprequestupload;
|
pub mod xmlhttprequestupload;
|
||||||
|
pub mod xr;
|
||||||
|
pub mod xrframe;
|
||||||
|
pub mod xrlayer;
|
||||||
|
pub mod xrreferencespace;
|
||||||
|
pub mod xrrigidtransform;
|
||||||
|
pub mod xrsession;
|
||||||
|
pub mod xrspace;
|
||||||
|
pub mod xrstationaryreferencespace;
|
||||||
|
pub mod xrview;
|
||||||
|
pub mod xrviewerpose;
|
||||||
|
pub mod xrviewport;
|
||||||
|
pub mod xrwebgllayer;
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
use crate::dom::bindings::codegen::Bindings::NavigatorBinding;
|
use crate::dom::bindings::codegen::Bindings::NavigatorBinding;
|
||||||
use crate::dom::bindings::codegen::Bindings::NavigatorBinding::NavigatorMethods;
|
use crate::dom::bindings::codegen::Bindings::NavigatorBinding::NavigatorMethods;
|
||||||
use crate::dom::bindings::codegen::Bindings::VRBinding::VRBinding::VRMethods;
|
use crate::dom::bindings::error::Error;
|
||||||
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector};
|
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector};
|
||||||
use crate::dom::bindings::root::{DomRoot, MutNullableDom};
|
use crate::dom::bindings::root::{DomRoot, MutNullableDom};
|
||||||
use crate::dom::bindings::str::DOMString;
|
use crate::dom::bindings::str::DOMString;
|
||||||
|
@ -16,8 +16,8 @@ use crate::dom::permissions::Permissions;
|
||||||
use crate::dom::pluginarray::PluginArray;
|
use crate::dom::pluginarray::PluginArray;
|
||||||
use crate::dom::promise::Promise;
|
use crate::dom::promise::Promise;
|
||||||
use crate::dom::serviceworkercontainer::ServiceWorkerContainer;
|
use crate::dom::serviceworkercontainer::ServiceWorkerContainer;
|
||||||
use crate::dom::vr::VR;
|
|
||||||
use crate::dom::window::Window;
|
use crate::dom::window::Window;
|
||||||
|
use crate::dom::xr::XR;
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ pub struct Navigator {
|
||||||
plugins: MutNullableDom<PluginArray>,
|
plugins: MutNullableDom<PluginArray>,
|
||||||
mime_types: MutNullableDom<MimeTypeArray>,
|
mime_types: MutNullableDom<MimeTypeArray>,
|
||||||
service_worker: MutNullableDom<ServiceWorkerContainer>,
|
service_worker: MutNullableDom<ServiceWorkerContainer>,
|
||||||
vr: MutNullableDom<VR>,
|
xr: MutNullableDom<XR>,
|
||||||
gamepads: MutNullableDom<GamepadList>,
|
gamepads: MutNullableDom<GamepadList>,
|
||||||
permissions: MutNullableDom<Permissions>,
|
permissions: MutNullableDom<Permissions>,
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,7 @@ impl Navigator {
|
||||||
plugins: Default::default(),
|
plugins: Default::default(),
|
||||||
mime_types: Default::default(),
|
mime_types: Default::default(),
|
||||||
service_worker: Default::default(),
|
service_worker: Default::default(),
|
||||||
vr: Default::default(),
|
xr: Default::default(),
|
||||||
gamepads: Default::default(),
|
gamepads: Default::default(),
|
||||||
permissions: Default::default(),
|
permissions: Default::default(),
|
||||||
}
|
}
|
||||||
|
@ -135,7 +135,7 @@ impl NavigatorMethods for Navigator {
|
||||||
.gamepads
|
.gamepads
|
||||||
.or_init(|| GamepadList::new(&self.global(), &[]));
|
.or_init(|| GamepadList::new(&self.global(), &[]));
|
||||||
|
|
||||||
let vr_gamepads = self.Vr().get_gamepads();
|
let vr_gamepads = self.Xr().get_gamepads();
|
||||||
root.add_if_not_exists(&vr_gamepads);
|
root.add_if_not_exists(&vr_gamepads);
|
||||||
// TODO: Add not VR related gamepads
|
// TODO: Add not VR related gamepads
|
||||||
root
|
root
|
||||||
|
@ -149,12 +149,17 @@ impl NavigatorMethods for Navigator {
|
||||||
// https://w3c.github.io/webvr/spec/1.1/#navigator-getvrdisplays-attribute
|
// https://w3c.github.io/webvr/spec/1.1/#navigator-getvrdisplays-attribute
|
||||||
#[allow(unrooted_must_root)]
|
#[allow(unrooted_must_root)]
|
||||||
fn GetVRDisplays(&self) -> Rc<Promise> {
|
fn GetVRDisplays(&self) -> Rc<Promise> {
|
||||||
self.Vr().GetDisplays()
|
let promise = Promise::new(&self.global());
|
||||||
|
let displays = self.Xr().get_displays();
|
||||||
|
match displays {
|
||||||
|
Ok(displays) => promise.resolve_native(&displays),
|
||||||
|
Err(_) => promise.reject_error(Error::Security),
|
||||||
}
|
}
|
||||||
|
promise
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Navigator {
|
/// https://immersive-web.github.io/webxr/#dom-navigator-xr
|
||||||
pub fn Vr(&self) -> DomRoot<VR> {
|
fn Xr(&self) -> DomRoot<XR> {
|
||||||
self.vr.or_init(|| VR::new(&self.global()))
|
self.xr.or_init(|| XR::new(&self.global()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,14 +4,15 @@
|
||||||
|
|
||||||
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::PerformanceBinding::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;
|
||||||
use crate::dom::bindings::codegen::Bindings::VRDisplayBinding::VREye;
|
use crate::dom::bindings::codegen::Bindings::VRDisplayBinding::VREye;
|
||||||
use crate::dom::bindings::codegen::Bindings::VRLayerBinding::VRLayer;
|
use crate::dom::bindings::codegen::Bindings::VRLayerBinding::VRLayer;
|
||||||
use crate::dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextMethods;
|
use crate::dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextMethods;
|
||||||
use crate::dom::bindings::codegen::Bindings::WindowBinding::FrameRequestCallback;
|
use crate::dom::bindings::codegen::Bindings::WindowBinding::FrameRequestCallback;
|
||||||
use crate::dom::bindings::codegen::Bindings::WindowBinding::WindowBinding::WindowMethods;
|
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::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;
|
||||||
|
@ -29,6 +30,8 @@ use crate::dom::vrframedata::VRFrameData;
|
||||||
use crate::dom::vrpose::VRPose;
|
use crate::dom::vrpose::VRPose;
|
||||||
use crate::dom::vrstageparameters::VRStageParameters;
|
use crate::dom::vrstageparameters::VRStageParameters;
|
||||||
use crate::dom::webglrenderingcontext::WebGLRenderingContext;
|
use crate::dom::webglrenderingcontext::WebGLRenderingContext;
|
||||||
|
use crate::dom::xrframe::XRFrame;
|
||||||
|
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::TaskSourceName;
|
||||||
|
@ -67,6 +70,8 @@ pub struct VRDisplay {
|
||||||
/// List of request animation frame callbacks
|
/// List of request animation frame callbacks
|
||||||
#[ignore_malloc_size_of = "closures are hard"]
|
#[ignore_malloc_size_of = "closures are hard"]
|
||||||
raf_callback_list: DomRefCell<Vec<(u32, Option<Rc<FrameRequestCallback>>)>>,
|
raf_callback_list: DomRefCell<Vec<(u32, Option<Rc<FrameRequestCallback>>)>>,
|
||||||
|
#[ignore_malloc_size_of = "closures are hard"]
|
||||||
|
xr_raf_callback_list: DomRefCell<Vec<(u32, Option<Rc<XRFrameRequestCallback>>)>>,
|
||||||
// Compositor VRFrameData synchonization
|
// Compositor VRFrameData synchonization
|
||||||
frame_data_status: Cell<VRFrameDataStatus>,
|
frame_data_status: Cell<VRFrameDataStatus>,
|
||||||
#[ignore_malloc_size_of = "closures are hard"]
|
#[ignore_malloc_size_of = "closures are hard"]
|
||||||
|
@ -74,6 +79,8 @@ pub struct VRDisplay {
|
||||||
running_display_raf: Cell<bool>,
|
running_display_raf: Cell<bool>,
|
||||||
paused: Cell<bool>,
|
paused: Cell<bool>,
|
||||||
stopped_on_pause: Cell<bool>,
|
stopped_on_pause: Cell<bool>,
|
||||||
|
/// Whether or not this is XR mode, and the session
|
||||||
|
xr_session: MutNullableDom<XRSession>,
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe_no_jsmanaged_fields!(WebVRDisplayData);
|
unsafe_no_jsmanaged_fields!(WebVRDisplayData);
|
||||||
|
@ -120,6 +127,7 @@ impl VRDisplay {
|
||||||
layer_ctx: MutNullableDom::default(),
|
layer_ctx: MutNullableDom::default(),
|
||||||
next_raf_id: Cell::new(1),
|
next_raf_id: Cell::new(1),
|
||||||
raf_callback_list: DomRefCell::new(vec![]),
|
raf_callback_list: DomRefCell::new(vec![]),
|
||||||
|
xr_raf_callback_list: DomRefCell::new(vec![]),
|
||||||
frame_data_status: Cell::new(VRFrameDataStatus::Waiting),
|
frame_data_status: Cell::new(VRFrameDataStatus::Waiting),
|
||||||
frame_data_receiver: DomRefCell::new(None),
|
frame_data_receiver: DomRefCell::new(None),
|
||||||
running_display_raf: Cell::new(false),
|
running_display_raf: Cell::new(false),
|
||||||
|
@ -129,6 +137,7 @@ impl VRDisplay {
|
||||||
// This flag is set when the Display was presenting when it received a VR Pause event.
|
// This flag is set when the Display was presenting when it received a VR Pause event.
|
||||||
// When the VR Resume event is received and the flag is set, VR presentation automatically restarts.
|
// When the VR Resume event is received and the flag is set, VR presentation automatically restarts.
|
||||||
stopped_on_pause: Cell::new(false),
|
stopped_on_pause: Cell::new(false),
|
||||||
|
xr_session: MutNullableDom::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -624,11 +633,27 @@ impl VRDisplay {
|
||||||
|
|
||||||
fn handle_raf(&self, end_sender: &Sender<Result<(f64, f64), ()>>) {
|
fn handle_raf(&self, end_sender: &Sender<Result<(f64, f64), ()>>) {
|
||||||
self.frame_data_status.set(VRFrameDataStatus::Waiting);
|
self.frame_data_status.set(VRFrameDataStatus::Waiting);
|
||||||
self.running_display_raf.set(true);
|
|
||||||
|
|
||||||
let mut callbacks = mem::replace(&mut *self.raf_callback_list.borrow_mut(), vec![]);
|
|
||||||
let now = self.global().as_window().Performance().Now();
|
let now = self.global().as_window().Performance().Now();
|
||||||
|
|
||||||
|
if let Some(session) = self.xr_session.get() {
|
||||||
|
let mut callbacks = mem::replace(&mut *self.xr_raf_callback_list.borrow_mut(), vec![]);
|
||||||
|
if callbacks.is_empty() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
self.sync_frame_data();
|
||||||
|
let frame = XRFrame::new(&self.global(), &session, self.frame_data.borrow().clone());
|
||||||
|
|
||||||
|
for (_, callback) in callbacks.drain(..) {
|
||||||
|
if let Some(callback) = callback {
|
||||||
|
let _ = callback.Call__(Finite::wrap(*now), &frame, ExceptionHandling::Report);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// frame submission is automatic in XR
|
||||||
|
self.SubmitFrame();
|
||||||
|
} else {
|
||||||
|
self.running_display_raf.set(true);
|
||||||
|
let mut callbacks = mem::replace(&mut *self.raf_callback_list.borrow_mut(), vec![]);
|
||||||
// Call registered VRDisplay.requestAnimationFrame callbacks.
|
// Call registered VRDisplay.requestAnimationFrame callbacks.
|
||||||
for (_, callback) in callbacks.drain(..) {
|
for (_, callback) in callbacks.drain(..) {
|
||||||
if let Some(callback) = callback {
|
if let Some(callback) = callback {
|
||||||
|
@ -644,6 +669,7 @@ impl VRDisplay {
|
||||||
warn!("WebVR: You should call GetFrameData while presenting");
|
warn!("WebVR: You should call GetFrameData while presenting");
|
||||||
self.sync_frame_data();
|
self.sync_frame_data();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
match self.frame_data_status.get() {
|
match self.frame_data_status.get() {
|
||||||
VRFrameDataStatus::Synced => {
|
VRFrameDataStatus::Synced => {
|
||||||
|
@ -661,6 +687,52 @@ 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) {
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn xr_raf(&self, callback: Rc<XRFrameRequestCallback>) -> u32 {
|
||||||
|
let raf_id = self.next_raf_id.get();
|
||||||
|
self.next_raf_id.set(raf_id + 1);
|
||||||
|
self.xr_raf_callback_list
|
||||||
|
.borrow_mut()
|
||||||
|
.push((raf_id, Some(callback)));
|
||||||
|
raf_id
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn xr_cancel_raf(&self, handle: i32) {
|
||||||
|
let mut list = self.xr_raf_callback_list.borrow_mut();
|
||||||
|
if let Some(pair) = list.iter_mut().find(|pair| pair.0 == handle as u32) {
|
||||||
|
pair.1 = None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// WebVR Spec: If the number of values in the leftBounds/rightBounds arrays
|
// WebVR Spec: If the number of values in the leftBounds/rightBounds arrays
|
||||||
// is not 0 or 4 for any of the passed layers the promise is rejected
|
// is not 0 or 4 for any of the passed layers the promise is rejected
|
||||||
fn parse_bounds(src: &Option<Vec<Finite<f32>>>, dst: &mut [f32; 4]) -> Result<(), &'static str> {
|
fn parse_bounds(src: &Option<Vec<Finite<f32>>>, dst: &mut [f32; 4]) -> Result<(), &'static str> {
|
||||||
|
|
|
@ -71,8 +71,9 @@ impl VRFrameData {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// FIXME(#22526) this should be in a better place
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
fn create_typed_array(cx: *mut JSContext, src: &[f32], dst: &Heap<*mut JSObject>) {
|
pub fn create_typed_array(cx: *mut JSContext, src: &[f32], dst: &Heap<*mut JSObject>) {
|
||||||
rooted!(in (cx) let mut array = ptr::null_mut::<JSObject>());
|
rooted!(in (cx) let mut array = ptr::null_mut::<JSObject>());
|
||||||
unsafe {
|
unsafe {
|
||||||
let _ = Float32Array::create(cx, CreateWith::Slice(src), array.handle_mut());
|
let _ = Float32Array::create(cx, CreateWith::Slice(src), array.handle_mut());
|
||||||
|
|
|
@ -157,6 +157,7 @@ pub struct WebGLRenderingContext {
|
||||||
current_scissor: Cell<(i32, i32, u32, u32)>,
|
current_scissor: Cell<(i32, i32, u32, u32)>,
|
||||||
#[ignore_malloc_size_of = "Because it's small"]
|
#[ignore_malloc_size_of = "Because it's small"]
|
||||||
current_clear_color: Cell<(f32, f32, f32, f32)>,
|
current_clear_color: Cell<(f32, f32, f32, f32)>,
|
||||||
|
size: Cell<Size2D<u32>>,
|
||||||
extension_manager: WebGLExtensions,
|
extension_manager: WebGLExtensions,
|
||||||
capabilities: Capabilities,
|
capabilities: Capabilities,
|
||||||
default_vao: DomOnceCell<WebGLVertexArrayObjectOES>,
|
default_vao: DomOnceCell<WebGLVertexArrayObjectOES>,
|
||||||
|
@ -211,6 +212,9 @@ impl WebGLRenderingContext {
|
||||||
current_program: MutNullableDom::new(None),
|
current_program: MutNullableDom::new(None),
|
||||||
current_vertex_attrib_0: Cell::new((0f32, 0f32, 0f32, 1f32)),
|
current_vertex_attrib_0: Cell::new((0f32, 0f32, 0f32, 1f32)),
|
||||||
current_scissor: Cell::new((0, 0, size.width, size.height)),
|
current_scissor: Cell::new((0, 0, size.width, size.height)),
|
||||||
|
// FIXME(#21718) The backend is allowed to choose a size smaller than
|
||||||
|
// what was requested
|
||||||
|
size: Cell::new(size),
|
||||||
current_clear_color: Cell::new((0.0, 0.0, 0.0, 0.0)),
|
current_clear_color: Cell::new((0.0, 0.0, 0.0, 0.0)),
|
||||||
extension_manager: WebGLExtensions::new(webgl_version),
|
extension_manager: WebGLExtensions::new(webgl_version),
|
||||||
capabilities: Default::default(),
|
capabilities: Default::default(),
|
||||||
|
@ -266,6 +270,9 @@ impl WebGLRenderingContext {
|
||||||
pub fn recreate(&self, size: Size2D<u32>) {
|
pub fn recreate(&self, size: Size2D<u32>) {
|
||||||
let (sender, receiver) = webgl_channel().unwrap();
|
let (sender, receiver) = webgl_channel().unwrap();
|
||||||
self.webgl_sender.send_resize(size, sender).unwrap();
|
self.webgl_sender.send_resize(size, sender).unwrap();
|
||||||
|
// FIXME(#21718) The backend is allowed to choose a size smaller than
|
||||||
|
// what was requested
|
||||||
|
self.size.set(size);
|
||||||
|
|
||||||
if let Err(msg) = receiver.recv().unwrap() {
|
if let Err(msg) = receiver.recv().unwrap() {
|
||||||
error!("Error resizing WebGLContext: {}", msg);
|
error!("Error resizing WebGLContext: {}", msg);
|
||||||
|
@ -340,6 +347,10 @@ impl WebGLRenderingContext {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn size(&self) -> Size2D<u32> {
|
||||||
|
self.size.get()
|
||||||
|
}
|
||||||
|
|
||||||
// Helper function for validating framebuffer completeness in
|
// Helper function for validating framebuffer completeness in
|
||||||
// calls touching the framebuffer. From the GLES 2.0.25 spec,
|
// calls touching the framebuffer. From the GLES 2.0.25 spec,
|
||||||
// page 119:
|
// page 119:
|
||||||
|
|
|
@ -1,11 +0,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/. */
|
|
||||||
|
|
||||||
// https://w3c.github.io/webvr/#interface-navigator
|
|
||||||
[NoInterfaceObject]
|
|
||||||
interface VR {
|
|
||||||
[Pref="dom.webvr.enabled"]
|
|
||||||
Promise<sequence<VRDisplay>> getDisplays();
|
|
||||||
//readonly attribute FrozenArray<VRDisplay> activeVRDisplays;
|
|
||||||
};
|
|
30
components/script/dom/webidls/XR.webidl
Normal file
30
components/script/dom/webidls/XR.webidl
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
/* 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://immersive-web.github.io/webxr/#xr-interface
|
||||||
|
[SecureContext, Exposed=Window, Pref="dom.webxr.enabled"]
|
||||||
|
interface XR: EventTarget {
|
||||||
|
// Methods
|
||||||
|
Promise<void> supportsSessionMode(XRSessionMode mode);
|
||||||
|
Promise<XRSession> requestSession(optional XRSessionCreationOptions parameters);
|
||||||
|
|
||||||
|
// Events
|
||||||
|
// attribute EventHandler ondevicechange;
|
||||||
|
};
|
||||||
|
|
||||||
|
[SecureContext]
|
||||||
|
partial interface Navigator {
|
||||||
|
[SameObject, Pref="dom.webxr.enabled"] readonly attribute XR xr;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum XRSessionMode {
|
||||||
|
"inline",
|
||||||
|
"immersive-vr",
|
||||||
|
"immersive-ar"
|
||||||
|
};
|
||||||
|
|
||||||
|
dictionary XRSessionCreationOptions {
|
||||||
|
XRSessionMode mode = "inline";
|
||||||
|
// XRPresentationContext outputContext;
|
||||||
|
};
|
13
components/script/dom/webidls/XRFrame.webidl
Normal file
13
components/script/dom/webidls/XRFrame.webidl
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
/* 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://immersive-web.github.io/webxr/#xrframe-interface
|
||||||
|
|
||||||
|
[SecureContext, Exposed=Window, Pref="dom.webxr.enabled"]
|
||||||
|
interface XRFrame {
|
||||||
|
readonly attribute XRSession session;
|
||||||
|
|
||||||
|
XRViewerPose? getViewerPose(optional XRReferenceSpace referenceSpace);
|
||||||
|
// XRInputPose? getInputPose(XRInputSource inputSource, optional XRReferenceSpace referenceSpace);
|
||||||
|
};
|
8
components/script/dom/webidls/XRLayer.webidl
Normal file
8
components/script/dom/webidls/XRLayer.webidl
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
/* 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://immersive-web.github.io/webxr/#xrlayer-interface
|
||||||
|
|
||||||
|
[SecureContext, Exposed=Window, Pref="dom.webxr.enabled"]
|
||||||
|
interface XRLayer {};
|
21
components/script/dom/webidls/XRReferenceSpace.webidl
Normal file
21
components/script/dom/webidls/XRReferenceSpace.webidl
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
/* 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://immersive-web.github.io/webxr/#xrreferencespace-interface
|
||||||
|
|
||||||
|
enum XRReferenceSpaceType {
|
||||||
|
"stationary",
|
||||||
|
"bounded",
|
||||||
|
"unbounded"
|
||||||
|
};
|
||||||
|
|
||||||
|
dictionary XRReferenceSpaceOptions {
|
||||||
|
required XRReferenceSpaceType type;
|
||||||
|
};
|
||||||
|
|
||||||
|
[SecureContext, Exposed=Window, Pref="dom.webxr.enabled"]
|
||||||
|
interface XRReferenceSpace : XRSpace {
|
||||||
|
// attribute XRRigidTransform originOffset;
|
||||||
|
// attribute EventHandler onreset;
|
||||||
|
};
|
13
components/script/dom/webidls/XRRigidTransform.webidl
Normal file
13
components/script/dom/webidls/XRRigidTransform.webidl
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
/* 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://immersive-web.github.io/webxr/#xrrigidtransform-interface
|
||||||
|
|
||||||
|
[SecureContext, Exposed=Window, Pref="dom.webxr.enabled"]
|
||||||
|
// [Constructor(optional DOMPointInit position, optional DOMPointInit orientation)]
|
||||||
|
interface XRRigidTransform {
|
||||||
|
// readonly attribute DOMPointReadOnly position;
|
||||||
|
// readonly attribute DOMPointReadOnly orientation;
|
||||||
|
// readonly attribute Float32Array matrix;
|
||||||
|
};
|
45
components/script/dom/webidls/XRSession.webidl
Normal file
45
components/script/dom/webidls/XRSession.webidl
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
/* 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://immersive-web.github.io/webxr/#xrsession-interface
|
||||||
|
|
||||||
|
enum XREnvironmentBlendMode {
|
||||||
|
"opaque",
|
||||||
|
"additive",
|
||||||
|
"alpha-blend",
|
||||||
|
};
|
||||||
|
|
||||||
|
callback XRFrameRequestCallback = void (DOMHighResTimeStamp time, XRFrame frame);
|
||||||
|
|
||||||
|
[SecureContext, Exposed=Window, Pref="dom.webxr.enabled"]
|
||||||
|
interface XRSession : EventTarget {
|
||||||
|
// // Attributes
|
||||||
|
readonly attribute XRSessionMode mode;
|
||||||
|
// readonly attribute XRPresentationContext outputContext;
|
||||||
|
// readonly attribute XREnvironmentBlendMode environmentBlendMode;
|
||||||
|
|
||||||
|
attribute double depthNear;
|
||||||
|
attribute double depthFar;
|
||||||
|
attribute XRLayer? baseLayer;
|
||||||
|
|
||||||
|
// // Methods
|
||||||
|
// Promise<XRReferenceSpace> requestReferenceSpace(XRReferenceSpaceType type,
|
||||||
|
// optional XRReferenceSpaceOptions options);
|
||||||
|
|
||||||
|
// FrozenArray<XRInputSource> getInputSources();
|
||||||
|
|
||||||
|
long requestAnimationFrame(XRFrameRequestCallback callback);
|
||||||
|
void cancelAnimationFrame(long handle);
|
||||||
|
|
||||||
|
// Promise<void> end();
|
||||||
|
|
||||||
|
// // Events
|
||||||
|
// attribute EventHandler onblur;
|
||||||
|
// attribute EventHandler onfocus;
|
||||||
|
// attribute EventHandler onend;
|
||||||
|
// attribute EventHandler onselect;
|
||||||
|
// attribute EventHandler oninputsourceschange;
|
||||||
|
// attribute EventHandler onselectstart;
|
||||||
|
// attribute EventHandler onselectend;
|
||||||
|
};
|
10
components/script/dom/webidls/XRSpace.webidl
Normal file
10
components/script/dom/webidls/XRSpace.webidl
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
/* 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://immersive-web.github.io/webxr/#xrspace-interface
|
||||||
|
|
||||||
|
[SecureContext, Exposed=Window, Pref="dom.webxr.enabled"]
|
||||||
|
interface XRSpace : EventTarget {
|
||||||
|
// XRRigidTransform? getTransformTo(XRSpace other);
|
||||||
|
};
|
|
@ -0,0 +1,20 @@
|
||||||
|
/* 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://immersive-web.github.io/webxr/#xrstationaryreferencespace-interface
|
||||||
|
|
||||||
|
enum XRStationaryReferenceSpaceSubtype {
|
||||||
|
"eye-level",
|
||||||
|
"floor-level",
|
||||||
|
"position-disabled"
|
||||||
|
};
|
||||||
|
|
||||||
|
dictionary XRStationaryReferenceSpaceOptions : XRReferenceSpaceOptions {
|
||||||
|
required XRStationaryReferenceSpaceSubtype subtype;
|
||||||
|
};
|
||||||
|
|
||||||
|
[SecureContext, Exposed=Window, Pref="dom.webxr.enabled"]
|
||||||
|
interface XRStationaryReferenceSpace: XRReferenceSpace {
|
||||||
|
// readonly attribute XRStationaryReferenceSpaceSubtype subtype;
|
||||||
|
};
|
18
components/script/dom/webidls/XRView.webidl
Normal file
18
components/script/dom/webidls/XRView.webidl
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
/* 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://immersive-web.github.io/webxr/#xrview-interface
|
||||||
|
|
||||||
|
enum XREye {
|
||||||
|
"left",
|
||||||
|
"right"
|
||||||
|
};
|
||||||
|
|
||||||
|
[SecureContext, Exposed=Window, Pref="dom.webxr.enabled"]
|
||||||
|
interface XRView {
|
||||||
|
readonly attribute XREye eye;
|
||||||
|
readonly attribute Float32Array projectionMatrix;
|
||||||
|
readonly attribute Float32Array viewMatrix;
|
||||||
|
// readonly attribute XRRigidTransform transform;
|
||||||
|
};
|
14
components/script/dom/webidls/XRViewerPose.webidl
Normal file
14
components/script/dom/webidls/XRViewerPose.webidl
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
/* 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://immersive-web.github.io/webxr/#xrviewerpose-interface
|
||||||
|
|
||||||
|
[SecureContext, Exposed=Window, Pref="dom.webxr.enabled"]
|
||||||
|
interface XRViewerPose {
|
||||||
|
// readonly attribute XRRigidTransform transform;
|
||||||
|
// readonly attribute FrozenArray<XRView> views;
|
||||||
|
// workaround until we have FrozenArray
|
||||||
|
// see https://github.com/servo/servo/issues/10427#issuecomment-449593626
|
||||||
|
readonly attribute any views;
|
||||||
|
};
|
13
components/script/dom/webidls/XRViewport.webidl
Normal file
13
components/script/dom/webidls/XRViewport.webidl
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
/* 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://immersive-web.github.io/webxr/#xrviewport-interface
|
||||||
|
|
||||||
|
[SecureContext, Exposed=Window, Pref="dom.webxr.enabled"]
|
||||||
|
interface XRViewport {
|
||||||
|
readonly attribute long x;
|
||||||
|
readonly attribute long y;
|
||||||
|
readonly attribute long width;
|
||||||
|
readonly attribute long height;
|
||||||
|
};
|
43
components/script/dom/webidls/XRWebGLLayer.webidl
Normal file
43
components/script/dom/webidls/XRWebGLLayer.webidl
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
/* 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://immersive-web.github.io/webxr/#xrwebgllayer-interface
|
||||||
|
|
||||||
|
// typedef (WebGLRenderingContext or
|
||||||
|
// WebGL2RenderingContext) XRWebGLRenderingContext;
|
||||||
|
|
||||||
|
typedef WebGLRenderingContext XRWebGLRenderingContext;
|
||||||
|
|
||||||
|
dictionary XRWebGLLayerInit {
|
||||||
|
boolean antialias = true;
|
||||||
|
boolean depth = true;
|
||||||
|
boolean stencil = false;
|
||||||
|
boolean alpha = true;
|
||||||
|
// double framebufferScaleFactor = 1.0;
|
||||||
|
};
|
||||||
|
|
||||||
|
[SecureContext, Exposed=Window, Constructor(XRSession session,
|
||||||
|
XRWebGLRenderingContext context,
|
||||||
|
optional XRWebGLLayerInit layerInit),
|
||||||
|
Pref="dom.webxr.enabled"]
|
||||||
|
interface XRWebGLLayer : XRLayer {
|
||||||
|
// // Attributes
|
||||||
|
readonly attribute XRWebGLRenderingContext context;
|
||||||
|
|
||||||
|
readonly attribute boolean antialias;
|
||||||
|
readonly attribute boolean depth;
|
||||||
|
readonly attribute boolean stencil;
|
||||||
|
readonly attribute boolean alpha;
|
||||||
|
|
||||||
|
// readonly attribute WebGLFramebuffer framebuffer;
|
||||||
|
// readonly attribute unsigned long framebufferWidth;
|
||||||
|
// readonly attribute unsigned long framebufferHeight;
|
||||||
|
|
||||||
|
// // Methods
|
||||||
|
XRViewport? getViewport(XRView view);
|
||||||
|
// void requestViewportScaling(double viewportScaleFactor);
|
||||||
|
|
||||||
|
// // Static Methods
|
||||||
|
// static double getNativeFramebufferScaleFactor(XRSession session);
|
||||||
|
};
|
|
@ -3,12 +3,13 @@
|
||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use crate::dom::bindings::cell::DomRefCell;
|
use crate::dom::bindings::cell::DomRefCell;
|
||||||
use crate::dom::bindings::codegen::Bindings::VRBinding;
|
|
||||||
use crate::dom::bindings::codegen::Bindings::VRBinding::VRMethods;
|
|
||||||
use crate::dom::bindings::codegen::Bindings::VRDisplayBinding::VRDisplayMethods;
|
use crate::dom::bindings::codegen::Bindings::VRDisplayBinding::VRDisplayMethods;
|
||||||
|
use crate::dom::bindings::codegen::Bindings::XRBinding;
|
||||||
|
use crate::dom::bindings::codegen::Bindings::XRBinding::XRSessionCreationOptions;
|
||||||
|
use crate::dom::bindings::codegen::Bindings::XRBinding::{XRMethods, XRSessionMode};
|
||||||
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, Reflector};
|
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject};
|
||||||
use crate::dom::bindings::root::{Dom, DomRoot};
|
use crate::dom::bindings::root::{Dom, DomRoot};
|
||||||
use crate::dom::event::Event;
|
use crate::dom::event::Event;
|
||||||
use crate::dom::eventtarget::EventTarget;
|
use crate::dom::eventtarget::EventTarget;
|
||||||
|
@ -18,6 +19,7 @@ use crate::dom::globalscope::GlobalScope;
|
||||||
use crate::dom::promise::Promise;
|
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 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;
|
||||||
|
@ -26,44 +28,91 @@ use webvr_traits::{WebVRDisplayData, WebVRDisplayEvent, WebVREvent, WebVRMsg};
|
||||||
use webvr_traits::{WebVRGamepadData, WebVRGamepadEvent, WebVRGamepadState};
|
use webvr_traits::{WebVRGamepadData, WebVRGamepadEvent, WebVRGamepadState};
|
||||||
|
|
||||||
#[dom_struct]
|
#[dom_struct]
|
||||||
pub struct VR {
|
pub struct XR {
|
||||||
reflector_: Reflector,
|
eventtarget: EventTarget,
|
||||||
displays: DomRefCell<Vec<Dom<VRDisplay>>>,
|
displays: DomRefCell<Vec<Dom<VRDisplay>>>,
|
||||||
gamepads: DomRefCell<Vec<Dom<Gamepad>>>,
|
gamepads: DomRefCell<Vec<Dom<Gamepad>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VR {
|
impl XR {
|
||||||
fn new_inherited() -> VR {
|
fn new_inherited() -> XR {
|
||||||
VR {
|
XR {
|
||||||
reflector_: Reflector::new(),
|
eventtarget: EventTarget::new_inherited(),
|
||||||
displays: DomRefCell::new(Vec::new()),
|
displays: DomRefCell::new(Vec::new()),
|
||||||
gamepads: DomRefCell::new(Vec::new()),
|
gamepads: DomRefCell::new(Vec::new()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new(global: &GlobalScope) -> DomRoot<VR> {
|
pub fn new(global: &GlobalScope) -> DomRoot<XR> {
|
||||||
let root = reflect_dom_object(Box::new(VR::new_inherited()), global, VRBinding::Wrap);
|
let root = reflect_dom_object(Box::new(XR::new_inherited()), global, XRBinding::Wrap);
|
||||||
root.register();
|
root.register();
|
||||||
root
|
root
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for VR {
|
impl Drop for XR {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
self.unregister();
|
self.unregister();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VRMethods for VR {
|
impl XRMethods for XR {
|
||||||
#[allow(unrooted_must_root)]
|
#[allow(unrooted_must_root)]
|
||||||
// https://w3c.github.io/webvr/#interface-navigator
|
/// https://immersive-web.github.io/webxr/#dom-xr-supportssessionmode
|
||||||
fn GetDisplays(&self) -> Rc<Promise> {
|
fn SupportsSessionMode(&self, mode: XRSessionMode) -> Rc<Promise> {
|
||||||
|
// XXXManishearth this should select an XR device first
|
||||||
let promise = Promise::new(&self.global());
|
let promise = Promise::new(&self.global());
|
||||||
|
if mode == XRSessionMode::Immersive_vr {
|
||||||
|
promise.resolve_native(&());
|
||||||
|
} else {
|
||||||
|
// XXXManishearth support other modes
|
||||||
|
promise.reject_error(Error::NotSupported);
|
||||||
|
}
|
||||||
|
|
||||||
|
promise
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(unrooted_must_root)]
|
||||||
|
/// https://immersive-web.github.io/webxr/#dom-xr-requestsession
|
||||||
|
fn RequestSession(&self, options: &XRSessionCreationOptions) -> Rc<Promise> {
|
||||||
|
let promise = Promise::new(&self.global());
|
||||||
|
if options.mode != XRSessionMode::Immersive_vr {
|
||||||
|
promise.reject_error(Error::NotSupported);
|
||||||
|
return promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
let displays = self.get_displays();
|
||||||
|
|
||||||
|
let displays = match displays {
|
||||||
|
Ok(d) => d,
|
||||||
|
Err(_) => {
|
||||||
|
promise.reject_native(&());
|
||||||
|
return promise;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
// XXXManishearth filter for displays which can_present
|
||||||
|
if displays.is_empty() {
|
||||||
|
promise.reject_error(Error::Security);
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
promise
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl XR {
|
||||||
|
pub fn get_displays(&self) -> Result<Vec<DomRoot<VRDisplay>>, ()> {
|
||||||
if let Some(webvr_thread) = self.webvr_thread() {
|
if let Some(webvr_thread) = self.webvr_thread() {
|
||||||
let (sender, receiver) =
|
let (sender, receiver) =
|
||||||
ipc::channel(self.global().time_profiler_chan().clone()).unwrap();
|
ipc::channel(self.global().time_profiler_chan().clone()).unwrap();
|
||||||
webvr_thread.send(WebVRMsg::GetDisplays(sender)).unwrap();
|
webvr_thread.send(WebVRMsg::GetDisplays(sender)).unwrap();
|
||||||
|
|
||||||
|
// FIXME(#22505) we should not block here and instead produce a promise
|
||||||
match receiver.recv().unwrap() {
|
match receiver.recv().unwrap() {
|
||||||
Ok(displays) => {
|
Ok(displays) => {
|
||||||
// Sync displays
|
// Sync displays
|
||||||
|
@ -71,31 +120,22 @@ impl VRMethods for VR {
|
||||||
self.sync_display(&display);
|
self.sync_display(&display);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Err(e) => {
|
Err(_) => return Err(()),
|
||||||
promise.reject_native(&e);
|
|
||||||
return promise;
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// WebVR spec: The Promise MUST be rejected if WebVR is not enabled/supported.
|
// WebVR spec: The Promise MUST be rejected if WebVR is not enabled/supported.
|
||||||
promise.reject_error(Error::Security);
|
return Err(());
|
||||||
return promise;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// convert from Dom to DomRoot
|
// convert from Dom to DomRoot
|
||||||
let displays: Vec<DomRoot<VRDisplay>> = self
|
Ok(self
|
||||||
.displays
|
.displays
|
||||||
.borrow()
|
.borrow()
|
||||||
.iter()
|
.iter()
|
||||||
.map(|d| DomRoot::from_ref(&**d))
|
.map(|d| DomRoot::from_ref(&**d))
|
||||||
.collect();
|
.collect())
|
||||||
promise.resolve_native(&displays);
|
|
||||||
|
|
||||||
promise
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VR {
|
|
||||||
fn webvr_thread(&self) -> Option<IpcSender<WebVRMsg>> {
|
fn webvr_thread(&self) -> Option<IpcSender<WebVRMsg>> {
|
||||||
self.global().as_window().webvr_thread()
|
self.global().as_window().webvr_thread()
|
||||||
}
|
}
|
||||||
|
@ -209,7 +249,7 @@ impl VR {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gamepad
|
// Gamepad
|
||||||
impl VR {
|
impl XR {
|
||||||
fn find_gamepad(&self, gamepad_id: u32) -> Option<DomRoot<Gamepad>> {
|
fn find_gamepad(&self, gamepad_id: u32) -> Option<DomRoot<Gamepad>> {
|
||||||
self.gamepads
|
self.gamepads
|
||||||
.borrow()
|
.borrow()
|
67
components/script/dom/xrframe.rs
Normal file
67
components/script/dom/xrframe.rs
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
/* 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::XRFrameBinding;
|
||||||
|
use crate::dom::bindings::codegen::Bindings::XRFrameBinding::XRFrameMethods;
|
||||||
|
use crate::dom::bindings::codegen::Bindings::XRViewBinding::XREye;
|
||||||
|
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector};
|
||||||
|
use crate::dom::bindings::root::{Dom, DomRoot};
|
||||||
|
use crate::dom::globalscope::GlobalScope;
|
||||||
|
use crate::dom::xrreferencespace::XRReferenceSpace;
|
||||||
|
use crate::dom::xrsession::XRSession;
|
||||||
|
use crate::dom::xrview::XRView;
|
||||||
|
use crate::dom::xrviewerpose::XRViewerPose;
|
||||||
|
use dom_struct::dom_struct;
|
||||||
|
use webvr_traits::WebVRFrameData;
|
||||||
|
|
||||||
|
#[dom_struct]
|
||||||
|
pub struct XRFrame {
|
||||||
|
reflector_: Reflector,
|
||||||
|
session: Dom<XRSession>,
|
||||||
|
#[ignore_malloc_size_of = "defined in rust-webvr"]
|
||||||
|
data: WebVRFrameData,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl XRFrame {
|
||||||
|
fn new_inherited(session: &XRSession, data: WebVRFrameData) -> XRFrame {
|
||||||
|
XRFrame {
|
||||||
|
reflector_: Reflector::new(),
|
||||||
|
session: Dom::from_ref(session),
|
||||||
|
data,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new(
|
||||||
|
global: &GlobalScope,
|
||||||
|
session: &XRSession,
|
||||||
|
data: WebVRFrameData,
|
||||||
|
) -> DomRoot<XRFrame> {
|
||||||
|
reflect_dom_object(
|
||||||
|
Box::new(XRFrame::new_inherited(session, data)),
|
||||||
|
global,
|
||||||
|
XRFrameBinding::Wrap,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl XRFrameMethods for XRFrame {
|
||||||
|
/// https://immersive-web.github.io/webxr/#dom-xrframe-session
|
||||||
|
fn Session(&self) -> DomRoot<XRSession> {
|
||||||
|
DomRoot::from_ref(&self.session)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// https://immersive-web.github.io/webxr/#dom-xrframe-getviewerpose
|
||||||
|
fn GetViewerPose(&self, reference: Option<&XRReferenceSpace>) -> Option<DomRoot<XRViewerPose>> {
|
||||||
|
// We assume the reference space is eye level for now
|
||||||
|
// since it's the only one 3DOF devices support
|
||||||
|
if reference.is_some() {
|
||||||
|
// it's not possible to obtain a reference
|
||||||
|
// space at all yet
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let left = XRView::new(&self.global(), &self.session, XREye::Left, &self.data);
|
||||||
|
let right = XRView::new(&self.global(), &self.session, XREye::Right, &self.data);
|
||||||
|
Some(XRViewerPose::new(&self.global(), &left, &right))
|
||||||
|
}
|
||||||
|
}
|
19
components/script/dom/xrlayer.rs
Normal file
19
components/script/dom/xrlayer.rs
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
/* 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::reflector::Reflector;
|
||||||
|
use dom_struct::dom_struct;
|
||||||
|
|
||||||
|
#[dom_struct]
|
||||||
|
pub struct XRLayer {
|
||||||
|
reflector_: Reflector,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl XRLayer {
|
||||||
|
pub fn new_inherited() -> XRLayer {
|
||||||
|
XRLayer {
|
||||||
|
reflector_: Reflector::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
32
components/script/dom/xrreferencespace.rs
Normal file
32
components/script/dom/xrreferencespace.rs
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
/* 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::XRReferenceSpaceBinding;
|
||||||
|
use crate::dom::bindings::reflector::reflect_dom_object;
|
||||||
|
use crate::dom::bindings::root::DomRoot;
|
||||||
|
use crate::dom::globalscope::GlobalScope;
|
||||||
|
use crate::dom::xrspace::XRSpace;
|
||||||
|
use dom_struct::dom_struct;
|
||||||
|
|
||||||
|
#[dom_struct]
|
||||||
|
pub struct XRReferenceSpace {
|
||||||
|
xrspace: XRSpace,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl XRReferenceSpace {
|
||||||
|
pub fn new_inherited() -> XRReferenceSpace {
|
||||||
|
XRReferenceSpace {
|
||||||
|
xrspace: XRSpace::new_inherited(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
|
pub fn new(global: &GlobalScope) -> DomRoot<XRReferenceSpace> {
|
||||||
|
reflect_dom_object(
|
||||||
|
Box::new(XRReferenceSpace::new_inherited()),
|
||||||
|
global,
|
||||||
|
XRReferenceSpaceBinding::Wrap,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
31
components/script/dom/xrrigidtransform.rs
Normal file
31
components/script/dom/xrrigidtransform.rs
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
/* 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::XRRigidTransformBinding;
|
||||||
|
use crate::dom::bindings::reflector::{reflect_dom_object, Reflector};
|
||||||
|
use crate::dom::bindings::root::DomRoot;
|
||||||
|
use crate::dom::globalscope::GlobalScope;
|
||||||
|
use dom_struct::dom_struct;
|
||||||
|
|
||||||
|
#[dom_struct]
|
||||||
|
pub struct XRRigidTransform {
|
||||||
|
reflector_: Reflector,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl XRRigidTransform {
|
||||||
|
fn new_inherited() -> XRRigidTransform {
|
||||||
|
XRRigidTransform {
|
||||||
|
reflector_: Reflector::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
|
pub fn new(global: &GlobalScope) -> DomRoot<XRRigidTransform> {
|
||||||
|
reflect_dom_object(
|
||||||
|
Box::new(XRRigidTransform::new_inherited()),
|
||||||
|
global,
|
||||||
|
XRRigidTransformBinding::Wrap,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
100
components/script/dom/xrsession.rs
Normal file
100
components/script/dom/xrsession.rs
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
/* 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::VRDisplayBinding::VRDisplayMethods;
|
||||||
|
use crate::dom::bindings::codegen::Bindings::XRBinding::XRSessionMode;
|
||||||
|
use crate::dom::bindings::codegen::Bindings::XRSessionBinding;
|
||||||
|
use crate::dom::bindings::codegen::Bindings::XRSessionBinding::XRFrameRequestCallback;
|
||||||
|
use crate::dom::bindings::codegen::Bindings::XRSessionBinding::XRSessionMethods;
|
||||||
|
use crate::dom::bindings::codegen::Bindings::XRWebGLLayerBinding::XRWebGLLayerMethods;
|
||||||
|
use crate::dom::bindings::inheritance::Castable;
|
||||||
|
use crate::dom::bindings::num::Finite;
|
||||||
|
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::vrdisplay::VRDisplay;
|
||||||
|
use crate::dom::xrlayer::XRLayer;
|
||||||
|
use crate::dom::xrwebgllayer::XRWebGLLayer;
|
||||||
|
use dom_struct::dom_struct;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
#[dom_struct]
|
||||||
|
pub struct XRSession {
|
||||||
|
eventtarget: EventTarget,
|
||||||
|
display: Dom<VRDisplay>,
|
||||||
|
base_layer: MutNullableDom<XRLayer>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl XRSession {
|
||||||
|
fn new_inherited(display: &VRDisplay) -> XRSession {
|
||||||
|
XRSession {
|
||||||
|
eventtarget: EventTarget::new_inherited(),
|
||||||
|
display: Dom::from_ref(display),
|
||||||
|
base_layer: Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new(global: &GlobalScope, display: &VRDisplay) -> DomRoot<XRSession> {
|
||||||
|
reflect_dom_object(
|
||||||
|
Box::new(XRSession::new_inherited(display)),
|
||||||
|
global,
|
||||||
|
XRSessionBinding::Wrap,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl XRSessionMethods for XRSession {
|
||||||
|
/// https://immersive-web.github.io/webxr/#dom-xrsession-depthnear
|
||||||
|
fn DepthNear(&self) -> Finite<f64> {
|
||||||
|
self.display.DepthNear()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// https://immersive-web.github.io/webxr/#dom-xrsession-depthfar
|
||||||
|
fn DepthFar(&self) -> Finite<f64> {
|
||||||
|
self.display.DepthFar()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// https://immersive-web.github.io/webxr/#dom-xrsession-depthnear
|
||||||
|
fn SetDepthNear(&self, d: Finite<f64>) {
|
||||||
|
self.display.SetDepthNear(d)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// https://immersive-web.github.io/webxr/#dom-xrsession-depthfar
|
||||||
|
fn SetDepthFar(&self, d: Finite<f64>) {
|
||||||
|
self.display.SetDepthFar(d)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// https://immersive-web.github.io/webxr/#dom-xrsession-mode
|
||||||
|
fn Mode(&self) -> XRSessionMode {
|
||||||
|
XRSessionMode::Immersive_vr
|
||||||
|
}
|
||||||
|
|
||||||
|
/// https://immersive-web.github.io/webxr/#dom-xrsession-baselayer
|
||||||
|
fn SetBaseLayer(&self, layer: Option<&XRLayer>) {
|
||||||
|
self.base_layer.set(layer);
|
||||||
|
if let Some(layer) = layer {
|
||||||
|
let layer = layer.downcast::<XRWebGLLayer>().unwrap();
|
||||||
|
self.display.xr_present(&self, &layer.Context());
|
||||||
|
} else {
|
||||||
|
// steps unknown
|
||||||
|
// https://github.com/immersive-web/webxr/issues/453
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// https://immersive-web.github.io/webxr/#dom-xrsession-baselayer
|
||||||
|
fn GetBaseLayer(&self) -> Option<DomRoot<XRLayer>> {
|
||||||
|
self.base_layer.get()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// https://immersive-web.github.io/webxr/#dom-xrsession-requestanimationframe
|
||||||
|
fn RequestAnimationFrame(&self, callback: Rc<XRFrameRequestCallback>) -> i32 {
|
||||||
|
self.display.xr_raf(callback) as i32
|
||||||
|
}
|
||||||
|
|
||||||
|
/// https://immersive-web.github.io/webxr/#dom-xrsession-cancelanimationframe
|
||||||
|
fn CancelAnimationFrame(&self, frame: i32) {
|
||||||
|
self.display.xr_cancel_raf(frame)
|
||||||
|
}
|
||||||
|
}
|
32
components/script/dom/xrspace.rs
Normal file
32
components/script/dom/xrspace.rs
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
/* 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::XRSpaceBinding;
|
||||||
|
use crate::dom::bindings::reflector::reflect_dom_object;
|
||||||
|
use crate::dom::bindings::root::DomRoot;
|
||||||
|
use crate::dom::eventtarget::EventTarget;
|
||||||
|
use crate::dom::globalscope::GlobalScope;
|
||||||
|
use dom_struct::dom_struct;
|
||||||
|
|
||||||
|
#[dom_struct]
|
||||||
|
pub struct XRSpace {
|
||||||
|
eventtarget: EventTarget,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl XRSpace {
|
||||||
|
pub fn new_inherited() -> XRSpace {
|
||||||
|
XRSpace {
|
||||||
|
eventtarget: EventTarget::new_inherited(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
|
pub fn new(global: &GlobalScope) -> DomRoot<XRSpace> {
|
||||||
|
reflect_dom_object(
|
||||||
|
Box::new(XRSpace::new_inherited()),
|
||||||
|
global,
|
||||||
|
XRSpaceBinding::Wrap,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
32
components/script/dom/xrstationaryreferencespace.rs
Normal file
32
components/script/dom/xrstationaryreferencespace.rs
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
/* 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::XRStationaryReferenceSpaceBinding;
|
||||||
|
use crate::dom::bindings::reflector::reflect_dom_object;
|
||||||
|
use crate::dom::bindings::root::DomRoot;
|
||||||
|
use crate::dom::globalscope::GlobalScope;
|
||||||
|
use crate::dom::xrreferencespace::XRReferenceSpace;
|
||||||
|
use dom_struct::dom_struct;
|
||||||
|
|
||||||
|
#[dom_struct]
|
||||||
|
pub struct XRStationaryReferenceSpace {
|
||||||
|
xrreferencespace: XRReferenceSpace,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
|
impl XRStationaryReferenceSpace {
|
||||||
|
pub fn new_inherited() -> XRStationaryReferenceSpace {
|
||||||
|
XRStationaryReferenceSpace {
|
||||||
|
xrreferencespace: XRReferenceSpace::new_inherited(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new(global: &GlobalScope) -> DomRoot<XRStationaryReferenceSpace> {
|
||||||
|
reflect_dom_object(
|
||||||
|
Box::new(XRStationaryReferenceSpace::new_inherited()),
|
||||||
|
global,
|
||||||
|
XRStationaryReferenceSpaceBinding::Wrap,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
83
components/script/dom/xrview.rs
Normal file
83
components/script/dom/xrview.rs
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
/* 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::XRViewBinding;
|
||||||
|
use crate::dom::bindings::codegen::Bindings::XRViewBinding::{XREye, XRViewMethods};
|
||||||
|
use crate::dom::bindings::reflector::{reflect_dom_object, Reflector};
|
||||||
|
use crate::dom::bindings::root::{Dom, DomRoot};
|
||||||
|
use crate::dom::globalscope::GlobalScope;
|
||||||
|
use crate::dom::vrframedata::create_typed_array;
|
||||||
|
use crate::dom::xrsession::XRSession;
|
||||||
|
use dom_struct::dom_struct;
|
||||||
|
use js::jsapi::{Heap, JSContext, JSObject};
|
||||||
|
use std::ptr::NonNull;
|
||||||
|
use webvr_traits::WebVRFrameData;
|
||||||
|
|
||||||
|
#[dom_struct]
|
||||||
|
pub struct XRView {
|
||||||
|
reflector_: Reflector,
|
||||||
|
session: Dom<XRSession>,
|
||||||
|
eye: XREye,
|
||||||
|
proj: Heap<*mut JSObject>,
|
||||||
|
view: Heap<*mut JSObject>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl XRView {
|
||||||
|
fn new_inherited(session: &XRSession, eye: XREye) -> XRView {
|
||||||
|
XRView {
|
||||||
|
reflector_: Reflector::new(),
|
||||||
|
session: Dom::from_ref(session),
|
||||||
|
eye,
|
||||||
|
proj: Heap::default(),
|
||||||
|
view: Heap::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new(
|
||||||
|
global: &GlobalScope,
|
||||||
|
session: &XRSession,
|
||||||
|
eye: XREye,
|
||||||
|
data: &WebVRFrameData,
|
||||||
|
) -> DomRoot<XRView> {
|
||||||
|
let ret = reflect_dom_object(
|
||||||
|
Box::new(XRView::new_inherited(session, eye)),
|
||||||
|
global,
|
||||||
|
XRViewBinding::Wrap,
|
||||||
|
);
|
||||||
|
|
||||||
|
let (proj, view) = if eye == XREye::Left {
|
||||||
|
(&data.left_projection_matrix, &data.left_view_matrix)
|
||||||
|
} else {
|
||||||
|
(&data.right_projection_matrix, &data.right_view_matrix)
|
||||||
|
};
|
||||||
|
|
||||||
|
let cx = global.get_cx();
|
||||||
|
create_typed_array(cx, proj, &ret.proj);
|
||||||
|
create_typed_array(cx, view, &ret.view);
|
||||||
|
ret
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn session(&self) -> &XRSession {
|
||||||
|
&self.session
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl XRViewMethods for XRView {
|
||||||
|
/// https://immersive-web.github.io/webxr/#dom-xrview-eye
|
||||||
|
fn Eye(&self) -> XREye {
|
||||||
|
self.eye
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(unsafe_code)]
|
||||||
|
/// https://immersive-web.github.io/webxr/#dom-xrview-projectionmatrix
|
||||||
|
unsafe fn ProjectionMatrix(&self, _cx: *mut JSContext) -> NonNull<JSObject> {
|
||||||
|
NonNull::new(self.proj.get()).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(unsafe_code)]
|
||||||
|
/// https://immersive-web.github.io/webxr/#dom-xrview-projectionmatrix
|
||||||
|
unsafe fn ViewMatrix(&self, _cx: *mut JSContext) -> NonNull<JSObject> {
|
||||||
|
NonNull::new(self.view.get()).unwrap()
|
||||||
|
}
|
||||||
|
}
|
56
components/script/dom/xrviewerpose.rs
Normal file
56
components/script/dom/xrviewerpose.rs
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
/* 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::XRViewerPoseBinding;
|
||||||
|
use crate::dom::bindings::codegen::Bindings::XRViewerPoseBinding::XRViewerPoseMethods;
|
||||||
|
use crate::dom::bindings::reflector::{reflect_dom_object, Reflector};
|
||||||
|
use crate::dom::bindings::root::DomRoot;
|
||||||
|
use crate::dom::globalscope::GlobalScope;
|
||||||
|
use crate::dom::xrview::XRView;
|
||||||
|
use dom_struct::dom_struct;
|
||||||
|
use js::conversions::ToJSValConvertible;
|
||||||
|
use js::jsapi::{Heap, JSContext};
|
||||||
|
use js::jsval::{JSVal, UndefinedValue};
|
||||||
|
|
||||||
|
#[dom_struct]
|
||||||
|
pub struct XRViewerPose {
|
||||||
|
reflector_: Reflector,
|
||||||
|
views: Heap<JSVal>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl XRViewerPose {
|
||||||
|
fn new_inherited() -> XRViewerPose {
|
||||||
|
XRViewerPose {
|
||||||
|
reflector_: Reflector::new(),
|
||||||
|
views: Heap::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(unsafe_code)]
|
||||||
|
pub fn new(global: &GlobalScope, left: &XRView, right: &XRView) -> DomRoot<XRViewerPose> {
|
||||||
|
let pose = reflect_dom_object(
|
||||||
|
Box::new(XRViewerPose::new_inherited()),
|
||||||
|
global,
|
||||||
|
XRViewerPoseBinding::Wrap,
|
||||||
|
);
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let cx = global.get_cx();
|
||||||
|
rooted!(in(cx) let mut jsval = UndefinedValue());
|
||||||
|
let vec = vec![DomRoot::from_ref(left), DomRoot::from_ref(right)];
|
||||||
|
vec.to_jsval(cx, jsval.handle_mut());
|
||||||
|
pose.views.set(jsval.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
pose
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl XRViewerPoseMethods for XRViewerPose {
|
||||||
|
/// https://immersive-web.github.io/webxr/#dom-xrviewerpose-views
|
||||||
|
#[allow(unsafe_code)]
|
||||||
|
unsafe fn Views(&self, _cx: *mut JSContext) -> JSVal {
|
||||||
|
self.views.get()
|
||||||
|
}
|
||||||
|
}
|
67
components/script/dom/xrviewport.rs
Normal file
67
components/script/dom/xrviewport.rs
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
/* 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::XRViewportBinding;
|
||||||
|
use crate::dom::bindings::codegen::Bindings::XRViewportBinding::XRViewportMethods;
|
||||||
|
use crate::dom::bindings::reflector::{reflect_dom_object, Reflector};
|
||||||
|
use crate::dom::bindings::root::DomRoot;
|
||||||
|
use crate::dom::globalscope::GlobalScope;
|
||||||
|
use dom_struct::dom_struct;
|
||||||
|
|
||||||
|
#[dom_struct]
|
||||||
|
pub struct XRViewport {
|
||||||
|
reflector_: Reflector,
|
||||||
|
x: u32,
|
||||||
|
y: u32,
|
||||||
|
width: u32,
|
||||||
|
height: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl XRViewport {
|
||||||
|
fn new_inherited(x: u32, y: u32, width: u32, height: u32) -> XRViewport {
|
||||||
|
XRViewport {
|
||||||
|
reflector_: Reflector::new(),
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new(
|
||||||
|
global: &GlobalScope,
|
||||||
|
x: u32,
|
||||||
|
y: u32,
|
||||||
|
width: u32,
|
||||||
|
height: u32,
|
||||||
|
) -> DomRoot<XRViewport> {
|
||||||
|
reflect_dom_object(
|
||||||
|
Box::new(XRViewport::new_inherited(x, y, width, height)),
|
||||||
|
global,
|
||||||
|
XRViewportBinding::Wrap,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl XRViewportMethods for XRViewport {
|
||||||
|
/// https://immersive-web.github.io/webxr/#dom-xrviewport-x
|
||||||
|
fn X(&self) -> i32 {
|
||||||
|
self.x as i32
|
||||||
|
}
|
||||||
|
|
||||||
|
/// https://immersive-web.github.io/webxr/#dom-xrviewport-y
|
||||||
|
fn Y(&self) -> i32 {
|
||||||
|
self.y as i32
|
||||||
|
}
|
||||||
|
|
||||||
|
/// https://immersive-web.github.io/webxr/#dom-xrviewport-width
|
||||||
|
fn Width(&self) -> i32 {
|
||||||
|
self.height as i32
|
||||||
|
}
|
||||||
|
|
||||||
|
/// https://immersive-web.github.io/webxr/#dom-xrviewport-height
|
||||||
|
fn Height(&self) -> i32 {
|
||||||
|
self.height as i32
|
||||||
|
}
|
||||||
|
}
|
122
components/script/dom/xrwebgllayer.rs
Normal file
122
components/script/dom/xrwebgllayer.rs
Normal file
|
@ -0,0 +1,122 @@
|
||||||
|
/* 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::XRViewBinding::{XREye, XRViewMethods};
|
||||||
|
use crate::dom::bindings::codegen::Bindings::XRWebGLLayerBinding;
|
||||||
|
use crate::dom::bindings::codegen::Bindings::XRWebGLLayerBinding::XRWebGLLayerInit;
|
||||||
|
use crate::dom::bindings::codegen::Bindings::XRWebGLLayerBinding::XRWebGLLayerMethods;
|
||||||
|
use crate::dom::bindings::error::Fallible;
|
||||||
|
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject};
|
||||||
|
use crate::dom::bindings::root::{Dom, DomRoot};
|
||||||
|
use crate::dom::globalscope::GlobalScope;
|
||||||
|
use crate::dom::webglrenderingcontext::WebGLRenderingContext;
|
||||||
|
use crate::dom::window::Window;
|
||||||
|
use crate::dom::xrlayer::XRLayer;
|
||||||
|
use crate::dom::xrsession::XRSession;
|
||||||
|
use crate::dom::xrview::XRView;
|
||||||
|
use crate::dom::xrviewport::XRViewport;
|
||||||
|
use dom_struct::dom_struct;
|
||||||
|
|
||||||
|
#[dom_struct]
|
||||||
|
pub struct XRWebGLLayer {
|
||||||
|
xrlayer: XRLayer,
|
||||||
|
antialias: bool,
|
||||||
|
depth: bool,
|
||||||
|
stencil: bool,
|
||||||
|
alpha: bool,
|
||||||
|
context: Dom<WebGLRenderingContext>,
|
||||||
|
session: Dom<XRSession>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl XRWebGLLayer {
|
||||||
|
pub fn new_inherited(
|
||||||
|
session: &XRSession,
|
||||||
|
context: &WebGLRenderingContext,
|
||||||
|
init: &XRWebGLLayerInit,
|
||||||
|
) -> XRWebGLLayer {
|
||||||
|
XRWebGLLayer {
|
||||||
|
xrlayer: XRLayer::new_inherited(),
|
||||||
|
antialias: init.antialias,
|
||||||
|
depth: init.depth,
|
||||||
|
stencil: init.stencil,
|
||||||
|
alpha: init.alpha,
|
||||||
|
context: Dom::from_ref(context),
|
||||||
|
session: Dom::from_ref(session),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new(
|
||||||
|
global: &GlobalScope,
|
||||||
|
session: &XRSession,
|
||||||
|
context: &WebGLRenderingContext,
|
||||||
|
init: &XRWebGLLayerInit,
|
||||||
|
) -> DomRoot<XRWebGLLayer> {
|
||||||
|
reflect_dom_object(
|
||||||
|
Box::new(XRWebGLLayer::new_inherited(session, context, init)),
|
||||||
|
global,
|
||||||
|
XRWebGLLayerBinding::Wrap,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn Constructor(
|
||||||
|
global: &Window,
|
||||||
|
session: &XRSession,
|
||||||
|
context: &WebGLRenderingContext,
|
||||||
|
init: &XRWebGLLayerInit,
|
||||||
|
) -> Fallible<DomRoot<Self>> {
|
||||||
|
Ok(XRWebGLLayer::new(&global.global(), session, context, init))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl XRWebGLLayerMethods for XRWebGLLayer {
|
||||||
|
/// https://immersive-web.github.io/webxr/#dom-xrwebgllayer-depth
|
||||||
|
fn Depth(&self) -> bool {
|
||||||
|
self.depth
|
||||||
|
}
|
||||||
|
|
||||||
|
/// https://immersive-web.github.io/webxr/#dom-xrwebgllayer-stencil
|
||||||
|
fn Stencil(&self) -> bool {
|
||||||
|
self.stencil
|
||||||
|
}
|
||||||
|
|
||||||
|
/// https://immersive-web.github.io/webxr/#dom-xrwebgllayer-antialias
|
||||||
|
fn Antialias(&self) -> bool {
|
||||||
|
self.antialias
|
||||||
|
}
|
||||||
|
|
||||||
|
/// https://immersive-web.github.io/webxr/#dom-xrwebgllayer-alpha
|
||||||
|
fn Alpha(&self) -> bool {
|
||||||
|
self.alpha
|
||||||
|
}
|
||||||
|
|
||||||
|
/// https://immersive-web.github.io/webxr/#dom-xrwebgllayer-context
|
||||||
|
fn Context(&self) -> DomRoot<WebGLRenderingContext> {
|
||||||
|
DomRoot::from_ref(&self.context)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// https://immersive-web.github.io/webxr/#dom-xrwebgllayer-getviewport
|
||||||
|
fn GetViewport(&self, view: &XRView) -> Option<DomRoot<XRViewport>> {
|
||||||
|
if self.session != view.session() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let size = self.context.size();
|
||||||
|
|
||||||
|
let x = if view.Eye() == XREye::Left {
|
||||||
|
0
|
||||||
|
} else {
|
||||||
|
size.width / 2
|
||||||
|
};
|
||||||
|
// XXXManishearth this assumes the WebVR default of canvases being cut in half
|
||||||
|
// which need not be generally true for all devices, and will not work in
|
||||||
|
// inline VR mode
|
||||||
|
Some(XRViewport::new(
|
||||||
|
&self.global(),
|
||||||
|
x,
|
||||||
|
0,
|
||||||
|
size.width / 2,
|
||||||
|
size.height,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
|
@ -24,6 +24,7 @@ use crate::dom::bindings::codegen::Bindings::DocumentBinding::{
|
||||||
DocumentMethods, DocumentReadyState,
|
DocumentMethods, DocumentReadyState,
|
||||||
};
|
};
|
||||||
use crate::dom::bindings::codegen::Bindings::EventBinding::EventInit;
|
use crate::dom::bindings::codegen::Bindings::EventBinding::EventInit;
|
||||||
|
use crate::dom::bindings::codegen::Bindings::NavigatorBinding::NavigatorMethods;
|
||||||
use crate::dom::bindings::codegen::Bindings::TransitionEventBinding::TransitionEventInit;
|
use crate::dom::bindings::codegen::Bindings::TransitionEventBinding::TransitionEventInit;
|
||||||
use crate::dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
|
use crate::dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
|
||||||
use crate::dom::bindings::conversions::{
|
use crate::dom::bindings::conversions::{
|
||||||
|
@ -3320,8 +3321,8 @@ impl ScriptThread {
|
||||||
fn handle_webvr_events(&self, pipeline_id: PipelineId, events: Vec<WebVREvent>) {
|
fn handle_webvr_events(&self, pipeline_id: PipelineId, events: Vec<WebVREvent>) {
|
||||||
let window = self.documents.borrow().find_window(pipeline_id);
|
let window = self.documents.borrow().find_window(pipeline_id);
|
||||||
if let Some(window) = window {
|
if let Some(window) = window {
|
||||||
let vr = window.Navigator().Vr();
|
let xr = window.Navigator().Xr();
|
||||||
vr.handle_webvr_events(events);
|
xr.handle_webvr_events(events);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -95,6 +95,7 @@ WEBIDL_STANDARDS = [
|
||||||
"//svgwg.org/svg2-draft",
|
"//svgwg.org/svg2-draft",
|
||||||
"//wicg.github.io",
|
"//wicg.github.io",
|
||||||
"//webaudio.github.io",
|
"//webaudio.github.io",
|
||||||
|
"//immersive-web.github.io/",
|
||||||
# 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."
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
"windows": {},
|
"windows": {},
|
||||||
"vr": {
|
"vr": {
|
||||||
"_comment": "settings specific to VR builds",
|
"_comment": "settings specific to VR builds",
|
||||||
"dom.webvr.enabled": true
|
"dom.webvr.enabled": true,
|
||||||
|
"dom.webxr.enabled": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue