Update WebXR Layer IDL, and matching changes to the Rust code.

This commit is contained in:
Alan Jeffrey 2020-07-31 18:44:57 -05:00
parent 092dcaf2e6
commit bf7f4eae31
13 changed files with 235 additions and 325 deletions

View file

@ -5,7 +5,6 @@
// https://www.khronos.org/registry/webgl/specs/latest/1.0/webgl.idl
use crate::dom::bindings::cell::DomRefCell;
use crate::dom::bindings::codegen::Bindings::WebGL2RenderingContextBinding::WebGL2RenderingContextConstants as constants;
use crate::dom::bindings::codegen::Bindings::XRWebGLLayerBinding::XRWebGLRenderingContext;
use crate::dom::bindings::inheritance::Castable;
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject};
use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom};
@ -141,13 +140,9 @@ impl WebGLFramebuffer {
// https://github.com/servo/servo/issues/24498
pub fn maybe_new_webxr(
session: &XRSession,
context: &XRWebGLRenderingContext,
context: &WebGLRenderingContext,
size: Size2D<i32, Viewport>,
) -> Option<DomRoot<Self>> {
let context = match context {
XRWebGLRenderingContext::WebGLRenderingContext(ref ctx) => DomRoot::from_ref(&**ctx),
XRWebGLRenderingContext::WebGL2RenderingContext(ref ctx) => ctx.base_context(),
};
let framebuffer = Self::maybe_new(&*context)?;
framebuffer.size.set(Some((size.width, size.height)));
framebuffer.status.set(constants::FRAMEBUFFER_COMPLETE);

View file

@ -2,59 +2,74 @@
* 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/layers/#xrlayertype
[SecureContext, Exposed=Window, Pref="dom.webxr.layers.enabled"]
interface XRLayer {
// attribute boolean blendTextureSourceAlpha;
// attribute boolean chromaticAberrationCorrection;
// https://immersive-web.github.io/webxr/#xrlayer
[SecureContext, Exposed=Window, Pref="dom.webxr.enabled"]
interface XRLayer : EventTarget {};
void destroy();
};
//
// TODO: Implement the layer types
//
// [SecureContext, Exposed=Window, Pref="dom.webxr.enabled"]
// interface XRProjectionLayer : XRLayer {
// [SecureContext, Exposed=Window, Pref="dom.webxr.layers.enabled"]
// interface XRCompositionLayer : XRLayer {
// readonly attribute XRLayerLayout layout;
//
// attribute boolean blendTextureSourceAlpha;
// attribute boolean? chromaticAberrationCorrection;
// attribute float? fixedFoveation;
//
// readonly attribute boolean needsRedraw;
//
// void destroy();
// };
//
// [SecureContext, Exposed=Window, Pref="dom.webxr.layers.enabled"]
// interface XRProjectionLayer : XRCompositionLayer {
// readonly attribute boolean ignoreDepthValues;
// };
//
// [SecureContext, Exposed=Window, Pref="dom.webxr.layers.enabled"]
// interface XRQuadLayer : XRLayer {
// readonly attribute XRLayerLayout layout;
// interface XRQuadLayer : XRCompositionLayer {
// attribute XRSpace space;
// attribute XRRigidTransform transform;
//
// attribute float width;
// attribute float height;
//
// // Events
// attribute EventHandler onredraw;
// };
//
// [SecureContext, Exposed=Window, Pref="dom.webxr.layers.enabled"]
// interface XRCylinderLayer : XRLayer {
// readonly attribute XRLayerLayout layout;
// attribute XRReferenceSpace referenceSpace;
//
// interface XRCylinderLayer : XRCompositionLayer {
// attribute XRSpace space;
// attribute XRRigidTransform transform;
//
// attribute float radius;
// attribute float centralAngle;
// attribute float aspectRatio;
//
// // Events
// attribute EventHandler onredraw;
// };
//
// [SecureContext, Exposed=Window, Pref="dom.webxr.layers.enabled"]
// interface XREquirectLayer : XRLayer {
// readonly attribute XRLayerLayout layout;
// attribute XRReferenceSpace referenceSpace;
//
// interface XREquirectLayer : XRCompositionLayer {
// attribute XRSpace space;
// attribute XRRigidTransform transform;
//
// attribute float radius;
// attribute float scaleX;
// attribute float scaleY;
// attribute float biasX;
// attribute float biasY;
// attribute float centralHorizontalAngle;
// attribute float upperVerticalAngle;
// attribute float lowerVerticalAngle;
//
// // Events
// attribute EventHandler onredraw;
// };
//
// [SecureContext, Exposed=Window, Pref="dom.webxr.layers.enabled"]
// interface XRCubeLayer : XRLayer {
// readonly attribute XRLayerLayout layout;
// attribute XRReferenceSpace referenceSpace;
// interface XRCubeLayer : XRCompositionLayer {
// attribute XRSpace space;
// attribute DOMPointReadOnly orientation;
//
// attribute DOMPoint orientation;
// // Events
// attribute EventHandler onredraw;
// };

View file

@ -0,0 +1,15 @@
/* 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/layers/#xrlayerevent-interface
// [SecureContext, Exposed=Window]
// interface XRLayerEvent : Event {
// constructor(DOMString type, XRLayerEventInit eventInitDict);
// [SameObject] readonly attribute XRLayer layer;
// };
dictionary XRLayerEventInit : EventInit {
required XRLayer layer;
};

View file

@ -13,6 +13,7 @@ interface XRMediaBinding {
};
dictionary XRMediaLayerInit {
required XRSpace space;
XRLayerLayout layout = "mono";
boolean invertStereo = false;
};

View file

@ -2,16 +2,14 @@
* 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/. */
typedef (XRWebGLLayer or XRLayer) XRGenericLayer;
// https://immersive-web.github.io/webxr/#xrrenderstate-interface
dictionary XRRenderStateInit {
double depthNear;
double depthFar;
double inlineVerticalFieldOfView;
XRWebGLLayer baseLayer;
sequence<XRGenericLayer> layers;
XRWebGLLayer? baseLayer;
sequence<XRLayer>? layers;
};
[SecureContext, Exposed=Window, Pref="dom.webxr.enabled"] interface XRRenderState {
@ -19,4 +17,8 @@ dictionary XRRenderStateInit {
readonly attribute double depthFar;
readonly attribute double? inlineVerticalFieldOfView;
readonly attribute XRWebGLLayer? baseLayer;
// https://immersive-web.github.io/layers/#xrrenderstatechanges
// workaround until we have FrozenArray
readonly attribute /* FrozenArray<XRLayer> */ any layers;
};

View file

@ -5,5 +5,5 @@
// https://immersive-web.github.io/layers/#xrsubimagetype
[SecureContext, Exposed=Window, Pref="dom.webxr.layers.enabled"]
interface XRSubImage {
readonly attribute XRViewport viewport;
[SameObject] readonly attribute XRViewport viewport;
};

View file

@ -9,14 +9,18 @@ interface XRWebGLBinding {
// readonly attribute double nativeProjectionScaleFactor;
// XRProjectionLayer createProjectionLayer(GLenum textureTarget, optional XRProjectionLayerInit init = {});
// XRQuadLayer createQuadLayer(GLenum textureTarget, XRLayerInit init);
// XRCylinderLayer createCylinderLayer(GLenum textureTarget, XRLayerInit init);
// XREquirectLayer createEquirectLayer(GLenum textureTarget, XRLayerInit init);
// XRCubeLayer createCubeLayer(XRLayerInit init);
// XRProjectionLayer createProjectionLayer(XRTextureType textureType,
// optional XRProjectionLayerInit init);
// XRQuadLayer createQuadLayer(XRTextureType textureType,
// optional XRQuadLayerInit init);
// XRCylinderLayer createCylinderLayer(XRTextureType textureType,
// optional XRCylinderLayerInit init);
// XREquirectLayer createEquirectLayer(XRTextureType textureType,
// optional XREquirectLayerInit init);
// XRCubeLayer createCubeLayer(optional XRCubeLayerInit init);
XRWebGLSubImage? getSubImage(XRLayer layer, XRFrame frame); // for mono layers
XRWebGLSubImage? getViewSubImage(XRLayer layer, XRView view); // for stereo layers
// XRWebGLSubImage getSubImage(XRCompositionLayer layer, XRFrame frame, optional XREye eye = "none");
// XRWebGLSubImage getViewSubImage(XRProjectionLayer layer, XRView view);
};
dictionary XRProjectionLayerInit {
@ -26,19 +30,54 @@ dictionary XRProjectionLayerInit {
double scaleFactor = 1.0;
};
dictionary XRQuadLayerInit : XRLayerInit {
XRRigidTransform? transform;
float width = 1.0;
float height = 1.0;
boolean isStatic = false;
};
dictionary XRCylinderLayerInit : XRLayerInit {
XRRigidTransform? transform;
float radius = 2.0;
float centralAngle = 0.78539;
float aspectRatio = 2.0;
boolean isStatic = false;
};
dictionary XREquirectLayerInit : XRLayerInit {
XRRigidTransform? transform;
float radius = 0;
float centralHorizontalAngle = 6.28318;
float upperVerticalAngle = 1.570795;
float lowerVerticalAngle = -1.570795;
boolean isStatic = false;
};
dictionary XRCubeLayerInit : XRLayerInit {
DOMPointReadOnly? orientation;
boolean isStatic = false;
};
dictionary XRLayerInit {
required unsigned long pixelWidth;
required unsigned long pixelHeight;
required XRSpace space;
required unsigned long viewPixelWidth;
required unsigned long viewPixelHeight;
XRLayerLayout layout = "mono";
boolean depth = false; // This is a change from typical WebGL initialization, but feels appropriate.
boolean depth = false;
boolean stencil = false;
boolean alpha = true;
};
enum XRTextureType {
"texture",
"texture-array"
};
enum XRLayerLayout {
"default",
"mono",
"stereo",
"stereo-left-right",
"stereo-top-bottom"
};

View file

@ -17,19 +17,19 @@ dictionary XRWebGLLayerInit {
};
[SecureContext, Exposed=Window, Pref="dom.webxr.enabled"]
interface XRWebGLLayer {
interface XRWebGLLayer: XRLayer {
[Throws] constructor(XRSession session,
XRWebGLRenderingContext context,
optional XRWebGLLayerInit layerInit = {});
// // Attributes
// Attributes
readonly attribute boolean antialias;
readonly attribute boolean ignoreDepthValues;
readonly attribute WebGLFramebuffer? framebuffer;
[SameObject] readonly attribute WebGLFramebuffer? framebuffer;
readonly attribute unsigned long framebufferWidth;
readonly attribute unsigned long framebufferHeight;
// // Methods
// Methods
XRViewport? getViewport(XRView view);
// // Static Methods

View file

@ -2,30 +2,26 @@
* 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::XRLayerBinding::XRLayerBinding::XRLayerMethods;
use crate::dom::bindings::reflector::Reflector;
use crate::dom::bindings::inheritance::Castable;
use crate::dom::bindings::root::Dom;
use crate::dom::eventtarget::EventTarget;
use crate::dom::webglrenderingcontext::WebGLRenderingContext;
use crate::dom::xrframe::XRFrame;
use crate::dom::xrsession::XRSession;
use crate::dom::xrwebgllayer::XRWebGLLayer;
use canvas_traits::webgl::WebGLContextId;
use dom_struct::dom_struct;
use webxr_api::LayerId;
#[dom_struct]
pub struct XRLayer {
reflector: Reflector,
event_target: EventTarget,
session: Dom<XRSession>,
context: Dom<WebGLRenderingContext>,
#[ignore_malloc_size_of = "Layers don't heap-allocate"]
layer_id: LayerId,
}
impl XRLayerMethods for XRLayer {
/// https://immersive-web.github.io/layers/#dom-xrlayer-destroy
fn Destroy(&self) {
// TODO: Implement this
}
/// If none, the session is inline (the composition disabled flag is true)
/// and this is a XRWebGLLayer.
#[ignore_malloc_size_of = "Layer ids don't heap-allocate"]
layer_id: Option<LayerId>,
}
impl XRLayer {
@ -33,17 +29,17 @@ impl XRLayer {
pub fn new_inherited(
session: &XRSession,
context: &WebGLRenderingContext,
layer_id: LayerId,
layer_id: Option<LayerId>,
) -> XRLayer {
XRLayer {
reflector: Reflector::new(),
event_target: EventTarget::new_inherited(),
session: Dom::from_ref(session),
context: Dom::from_ref(context),
layer_id,
}
}
pub(crate) fn layer_id(&self) -> LayerId {
pub(crate) fn layer_id(&self) -> Option<LayerId> {
self.layer_id
}
@ -51,13 +47,29 @@ impl XRLayer {
self.context.context_id()
}
pub fn begin_frame(&self, _frame: &XRFrame) -> Option<()> {
// TODO: Implement this
None
pub(crate) fn context(&self) -> &WebGLRenderingContext {
&self.context
}
pub fn end_frame(&self, _frame: &XRFrame) -> Option<()> {
// TODO: Implement this
None
pub(crate) fn session(&self) -> &XRSession {
&self.session
}
pub fn begin_frame(&self, frame: &XRFrame) -> Option<()> {
// TODO: Implement this for other layer types
if let Some(this) = self.downcast::<XRWebGLLayer>() {
this.begin_frame(frame)
} else {
unimplemented!()
}
}
pub fn end_frame(&self, frame: &XRFrame) -> Option<()> {
// TODO: Implement this for other layer types
if let Some(this) = self.downcast::<XRWebGLLayer>() {
this.end_frame(frame)
} else {
unimplemented!()
}
}
}

View file

@ -4,17 +4,18 @@
use crate::dom::bindings::cell::DomRefCell;
use crate::dom::bindings::codegen::Bindings::XRRenderStateBinding::XRRenderStateMethods;
use crate::dom::bindings::codegen::UnionTypes::XRWebGLLayerOrXRLayer as RootedXRWebGLLayerOrXRLayer;
use crate::dom::bindings::num::Finite;
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector};
use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom};
use crate::dom::bindings::root::Dom;
use crate::dom::bindings::root::{DomRoot, MutNullableDom};
use crate::dom::bindings::utils::to_frozen_array;
use crate::dom::globalscope::GlobalScope;
use crate::dom::xrlayer::XRLayer;
use crate::dom::xrwebgllayer::XRWebGLLayer;
use canvas_traits::webgl::WebGLContextId;
use crate::script_runtime::JSContext;
use dom_struct::dom_struct;
use js::jsval::JSVal;
use std::cell::Cell;
use webxr_api::LayerId;
use webxr_api::SubImages;
#[dom_struct]
@ -24,51 +25,7 @@ pub struct XRRenderState {
depth_far: Cell<f64>,
inline_vertical_fov: Cell<Option<f64>>,
base_layer: MutNullableDom<XRWebGLLayer>,
layers: DomRefCell<Vec<XRWebGLLayerOrXRLayer>>,
}
#[unrooted_must_root_lint::must_root]
#[derive(Clone, JSTraceable, MallocSizeOf)]
pub enum XRWebGLLayerOrXRLayer {
XRWebGLLayer(Dom<XRWebGLLayer>),
XRLayer(Dom<XRLayer>),
}
impl XRWebGLLayerOrXRLayer {
#[allow(unrooted_must_root)]
fn from_ref(layer: &RootedXRWebGLLayerOrXRLayer) -> XRWebGLLayerOrXRLayer {
match layer {
RootedXRWebGLLayerOrXRLayer::XRWebGLLayer(ref layer) => {
XRWebGLLayerOrXRLayer::XRWebGLLayer(Dom::from_ref(layer))
},
RootedXRWebGLLayerOrXRLayer::XRLayer(ref layer) => {
XRWebGLLayerOrXRLayer::XRLayer(Dom::from_ref(layer))
},
}
}
pub(crate) fn layer_id(&self) -> Option<LayerId> {
match self {
XRWebGLLayerOrXRLayer::XRWebGLLayer(ref layer) => layer.layer_id(),
XRWebGLLayerOrXRLayer::XRLayer(ref layer) => Some(layer.layer_id()),
}
}
}
impl RootedXRWebGLLayerOrXRLayer {
pub(crate) fn layer_id(&self) -> Option<LayerId> {
match self {
RootedXRWebGLLayerOrXRLayer::XRWebGLLayer(ref layer) => layer.layer_id(),
RootedXRWebGLLayerOrXRLayer::XRLayer(ref layer) => Some(layer.layer_id()),
}
}
pub(crate) fn context_id(&self) -> WebGLContextId {
match self {
RootedXRWebGLLayerOrXRLayer::XRWebGLLayer(ref layer) => layer.context_id(),
RootedXRWebGLLayerOrXRLayer::XRLayer(ref layer) => layer.context_id(),
}
}
layers: DomRefCell<Vec<Dom<XRLayer>>>,
}
impl XRRenderState {
@ -77,7 +34,7 @@ impl XRRenderState {
depth_far: f64,
inline_vertical_fov: Option<f64>,
layer: Option<&XRWebGLLayer>,
layers: &[XRWebGLLayerOrXRLayer],
layers: Vec<&XRLayer>,
) -> XRRenderState {
debug_assert!(layer.is_none() || layers.is_empty());
XRRenderState {
@ -86,7 +43,12 @@ impl XRRenderState {
depth_far: Cell::new(depth_far),
inline_vertical_fov: Cell::new(inline_vertical_fov),
base_layer: MutNullableDom::new(layer),
layers: DomRefCell::new(layers.iter().cloned().collect()),
layers: DomRefCell::new(
layers
.into_iter()
.map(|layer| Dom::from_ref(layer))
.collect(),
),
}
}
@ -96,7 +58,7 @@ impl XRRenderState {
depth_far: f64,
inline_vertical_fov: Option<f64>,
layer: Option<&XRWebGLLayer>,
layers: &[XRWebGLLayerOrXRLayer],
layers: Vec<&XRLayer>,
) -> DomRoot<XRRenderState> {
reflect_dom_object(
Box::new(XRRenderState::new_inherited(
@ -111,14 +73,13 @@ impl XRRenderState {
}
pub fn clone_object(&self) -> DomRoot<Self> {
let layers = self.layers.borrow();
XRRenderState::new(
&self.global(),
self.depth_near.get(),
self.depth_far.get(),
self.inline_vertical_fov.get(),
self.base_layer.get().as_ref().map(|x| &**x),
&layers,
self.layers.borrow().iter().map(|x| &**x).collect(),
)
}
@ -135,12 +96,15 @@ impl XRRenderState {
pub fn set_base_layer(&self, layer: Option<&XRWebGLLayer>) {
self.base_layer.set(layer)
}
pub fn set_layers(&self, layers: &[RootedXRWebGLLayerOrXRLayer]) {
*self.layers.borrow_mut() = layers.iter().map(XRWebGLLayerOrXRLayer::from_ref).collect();
pub fn set_layers(&self, layers: Vec<&XRLayer>) {
*self.layers.borrow_mut() = layers
.into_iter()
.map(|layer| Dom::from_ref(layer))
.collect();
}
pub fn with_layers<F, R>(&self, f: F) -> R
where
F: FnOnce(&[XRWebGLLayerOrXRLayer]) -> R,
F: FnOnce(&[Dom<XRLayer>]) -> R,
{
let layers = self.layers.borrow();
f(&*layers)
@ -187,4 +151,12 @@ impl XRRenderStateMethods for XRRenderState {
fn GetBaseLayer(&self) -> Option<DomRoot<XRWebGLLayer>> {
self.base_layer.get()
}
/// https://immersive-web.github.io/layers/#dom-xrrenderstate-layers
fn Layers(&self, cx: JSContext) -> JSVal {
// TODO: cache this array?
let layers = self.layers.borrow();
let layers: Vec<&XRLayer> = layers.iter().map(|x| &**x).collect();
to_frozen_array(&layers[..], cx)
}
}

View file

@ -16,7 +16,6 @@ use crate::dom::bindings::codegen::Bindings::XRSessionBinding::XRFrameRequestCal
use crate::dom::bindings::codegen::Bindings::XRSessionBinding::XRSessionMethods;
use crate::dom::bindings::codegen::Bindings::XRSessionBinding::XRVisibilityState;
use crate::dom::bindings::codegen::Bindings::XRSystemBinding::XRSessionMode;
use crate::dom::bindings::codegen::Bindings::XRWebGLLayerBinding::XRWebGLRenderingContext;
use crate::dom::bindings::error::{Error, ErrorResult};
use crate::dom::bindings::inheritance::Castable;
use crate::dom::bindings::refcounted::Trusted;
@ -33,7 +32,6 @@ use crate::dom::xrinputsourcearray::XRInputSourceArray;
use crate::dom::xrinputsourceevent::XRInputSourceEvent;
use crate::dom::xrreferencespace::XRReferenceSpace;
use crate::dom::xrrenderstate::XRRenderState;
use crate::dom::xrrenderstate::XRWebGLLayerOrXRLayer;
use crate::dom::xrsessionevent::XRSessionEvent;
use crate::dom::xrspace::XRSpace;
use crate::realms::InRealm;
@ -133,7 +131,7 @@ impl XRSession {
} else {
None
};
let render_state = XRRenderState::new(global, 0.1, 1000.0, ivfov, None, &[]);
let render_state = XRRenderState::new(global, 0.1, 1000.0, ivfov, None, Vec::new());
let input_sources = XRInputSourceArray::new(global);
let ret = reflect_dom_object(
Box::new(XRSession::new_inherited(
@ -495,12 +493,7 @@ impl XRSession {
pub fn dirty_layers(&self) {
if let Some(layer) = self.RenderState().GetBaseLayer() {
match layer.context() {
XRWebGLRenderingContext::WebGLRenderingContext(c) => c.mark_as_dirty(),
XRWebGLRenderingContext::WebGL2RenderingContext(c) => {
c.base_context().mark_as_dirty()
},
}
layer.context().mark_as_dirty();
}
}
@ -511,14 +504,7 @@ impl XRSession {
}
self.active_render_state.get().with_layers(|layers| {
for layer in layers {
match layer {
XRWebGLLayerOrXRLayer::XRWebGLLayer(layer) => {
layer.begin_frame(frame);
},
XRWebGLLayerOrXRLayer::XRLayer(layer) => {
layer.begin_frame(frame);
},
}
layer.begin_frame(frame);
}
});
}
@ -530,14 +516,7 @@ impl XRSession {
}
self.active_render_state.get().with_layers(|layers| {
for layer in layers {
match layer {
XRWebGLLayerOrXRLayer::XRWebGLLayer(layer) => {
layer.end_frame(frame);
},
XRWebGLLayerOrXRLayer::XRLayer(layer) => {
layer.end_frame(frame);
},
}
layer.end_frame(frame);
}
});
}
@ -612,7 +591,7 @@ impl XRSessionMethods for XRSession {
return Err(Error::InvalidState);
}
// Step 3:
if let Some(ref layer) = init.baseLayer {
if let Some(Some(ref layer)) = init.baseLayer {
if Dom::from_ref(layer.session()) != Dom::from_ref(self) {
return Err(Error::InvalidState);
}
@ -623,22 +602,8 @@ impl XRSessionMethods for XRSession {
return Err(Error::InvalidState);
}
// TODO: add spec link for this step once XR layers has settled down
// https://immersive-web.github.io/layers/
if init.baseLayer.is_some() && init.layers.is_some() {
return Err(Error::InvalidState);
}
// TODO: add spec link for this step once XR layers has settled down
// https://immersive-web.github.io/layers/
if init
.layers
.as_ref()
.map(|layers| layers.is_empty())
.unwrap_or(false)
{
return Err(Error::InvalidState);
}
// TODO: Add the checks in
// https://immersive-web.github.io/layers/#updaterenderstatechanges
let pending = self
.pending_render_state
@ -673,9 +638,10 @@ impl XRSessionMethods for XRSession {
pending.set_inline_vertical_fov(fov);
}
if let Some(ref layer) = init.baseLayer {
pending.set_base_layer(Some(&layer));
pending.set_layers(&[]);
let layers = std::iter::once(layer)
pending.set_base_layer(layer.as_deref());
pending.set_layers(Vec::new());
let layers = layer
.iter()
.filter_map(|layer| {
let context_id = WebXRContextId::from(layer.context_id());
let layer_id = layer.layer_id()?;
@ -691,11 +657,11 @@ impl XRSessionMethods for XRSession {
.update_clip_planes(*pending.DepthNear() as f32, *pending.DepthFar() as f32);
}
// TODO: add spec link for this step once XR layers has settled down
// https://immersive-web.github.io/layers/
// https://immersive-web.github.io/layers/#updaterenderstatechanges
if let Some(ref layers) = init.layers {
let layers = layers.as_deref().unwrap_or_default();
pending.set_base_layer(None);
pending.set_layers(layers);
pending.set_layers(layers.iter().map(|x| &**x).collect());
let layers = layers
.iter()
.filter_map(|layer| {

View file

@ -2,105 +2,36 @@
* 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::XRWebGLBindingBinding::XRWebGLBindingBinding::XRWebGLBindingMethods;
use crate::dom::bindings::codegen::UnionTypes::WebGLRenderingContextOrWebGL2RenderingContext as RootedWebGLRenderingContextOrWebGL2RenderingContext;
use crate::dom::bindings::codegen::UnionTypes::WebGLRenderingContextOrWebGL2RenderingContext;
use crate::dom::bindings::reflector::reflect_dom_object;
use crate::dom::bindings::reflector::Reflector;
use crate::dom::bindings::root::Dom;
use crate::dom::bindings::root::DomRoot;
use crate::dom::webgl2renderingcontext::WebGL2RenderingContext;
use crate::dom::webglrenderingcontext::WebGLRenderingContext;
use crate::dom::window::Window;
use crate::dom::xrframe::XRFrame;
use crate::dom::xrlayer::XRLayer;
use crate::dom::xrsession::XRSession;
use crate::dom::xrview::XRView;
use crate::dom::xrwebglsubimage::XRWebGLSubImage;
use canvas_traits::webgl::WebGLContextId;
use dom_struct::dom_struct;
#[dom_struct]
pub struct XRWebGLBinding {
reflector: Reflector,
session: Dom<XRSession>,
context: WebGLRenderingContextOrWebGL2RenderingContext,
}
// TODO: Should this live somewhere else?
#[unrooted_must_root_lint::must_root]
#[derive(Clone, JSTraceable, MallocSizeOf)]
pub enum WebGLRenderingContextOrWebGL2RenderingContext {
WebGLRenderingContext(Dom<WebGLRenderingContext>),
WebGL2RenderingContext(Dom<WebGL2RenderingContext>),
}
impl WebGLRenderingContextOrWebGL2RenderingContext {
#[allow(unrooted_must_root)]
fn from_ref(
context: &RootedWebGLRenderingContextOrWebGL2RenderingContext,
) -> WebGLRenderingContextOrWebGL2RenderingContext {
match context {
RootedWebGLRenderingContextOrWebGL2RenderingContext::WebGLRenderingContext(
ref context,
) => WebGLRenderingContextOrWebGL2RenderingContext::WebGLRenderingContext(
Dom::from_ref(context),
),
RootedWebGLRenderingContextOrWebGL2RenderingContext::WebGL2RenderingContext(
ref context,
) => WebGLRenderingContextOrWebGL2RenderingContext::WebGL2RenderingContext(
Dom::from_ref(context),
),
}
}
}
impl RootedWebGLRenderingContextOrWebGL2RenderingContext {
pub(crate) fn context_id(&self) -> WebGLContextId {
match self {
RootedWebGLRenderingContextOrWebGL2RenderingContext::WebGLRenderingContext(
ref context,
) => context.context_id(),
RootedWebGLRenderingContextOrWebGL2RenderingContext::WebGL2RenderingContext(
ref context,
) => context.base_context().context_id(),
}
}
}
impl XRWebGLBindingMethods for XRWebGLBinding {
/// https://immersive-web.github.io/layers/#dom-xrwebglbinding-getsubimage
fn GetSubImage(&self, _layer: &XRLayer, _frame: &XRFrame) -> Option<DomRoot<XRWebGLSubImage>> {
// TODO: Implement this
None
}
/// https://immersive-web.github.io/layers/#dom-xrwebglbinding-getviewsubimage
fn GetViewSubImage(
&self,
_layer: &XRLayer,
_view: &XRView,
) -> Option<DomRoot<XRWebGLSubImage>> {
// TODO: Implement this
None
}
context: Dom<WebGLRenderingContext>,
}
impl XRWebGLBinding {
pub fn new_inherited(
session: &XRSession,
context: &WebGLRenderingContextOrWebGL2RenderingContext,
) -> XRWebGLBinding {
pub fn new_inherited(session: &XRSession, context: &WebGLRenderingContext) -> XRWebGLBinding {
XRWebGLBinding {
reflector: Reflector::new(),
session: Dom::from_ref(session),
context: context.clone(),
context: Dom::from_ref(context),
}
}
pub fn new(
global: &Window,
session: &XRSession,
context: &WebGLRenderingContextOrWebGL2RenderingContext,
context: &WebGLRenderingContext,
) -> DomRoot<XRWebGLBinding> {
reflect_dom_object(
Box::new(XRWebGLBinding::new_inherited(session, context)),
@ -112,12 +43,14 @@ impl XRWebGLBinding {
pub fn Constructor(
global: &Window,
session: &XRSession,
context: RootedWebGLRenderingContextOrWebGL2RenderingContext,
context: WebGLRenderingContextOrWebGL2RenderingContext,
) -> DomRoot<XRWebGLBinding> {
XRWebGLBinding::new(
global,
session,
&WebGLRenderingContextOrWebGL2RenderingContext::from_ref(&context),
)
let context = match context {
WebGLRenderingContextOrWebGL2RenderingContext::WebGLRenderingContext(ctx) => ctx,
WebGLRenderingContextOrWebGL2RenderingContext::WebGL2RenderingContext(ctx) => {
ctx.base_context()
},
};
XRWebGLBinding::new(global, session, &context)
}
}

View file

@ -2,30 +2,29 @@
* 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::inheritance::Castable;
use crate::dom::bindings::codegen::Bindings::WebGL2RenderingContextBinding::WebGL2RenderingContextConstants as constants;
use crate::dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextMethods;
use crate::dom::bindings::codegen::Bindings::WebGL2RenderingContextBinding::WebGL2RenderingContextBinding::WebGL2RenderingContextMethods;
use crate::dom::bindings::codegen::Bindings::XRWebGLLayerBinding::XRWebGLLayerInit;
use crate::dom::bindings::codegen::Bindings::XRWebGLLayerBinding::XRWebGLLayerMethods;
use crate::dom::bindings::codegen::Bindings::XRWebGLLayerBinding::XRWebGLRenderingContext;
use crate::dom::bindings::error::Error;
use crate::dom::bindings::error::Fallible;
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector};
use crate::dom::bindings::inheritance::Castable;
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject};
use crate::dom::bindings::root::{Dom, DomRoot};
use crate::dom::globalscope::GlobalScope;
use crate::dom::webglframebuffer::WebGLFramebuffer;
use crate::dom::webglobject::WebGLObject;
use crate::dom::webgltexture::WebGLTexture;
use crate::dom::webglrenderingcontext::WebGLRenderingContext;
use crate::dom::webgl2renderingcontext::WebGL2RenderingContext;
use crate::dom::webgltexture::WebGLTexture;
use crate::dom::window::Window;
use crate::dom::xrframe::XRFrame;
use crate::dom::xrlayer::XRLayer;
use crate::dom::xrsession::XRSession;
use crate::dom::xrview::XRView;
use crate::dom::xrviewport::XRViewport;
use canvas_traits::webgl::WebGLContextId;
use canvas_traits::webgl::WebGLCommand;
use canvas_traits::webgl::WebGLContextId;
use canvas_traits::webgl::WebGLTextureId;
use dom_struct::dom_struct;
use euclid::{Rect, Size2D};
@ -35,22 +34,6 @@ use webxr_api::LayerId;
use webxr_api::LayerInit;
use webxr_api::Viewport;
#[derive(JSTraceable, MallocSizeOf)]
#[unrooted_must_root_lint::must_root]
pub enum RenderingContext {
WebGL1(Dom<WebGLRenderingContext>),
WebGL2(Dom<WebGL2RenderingContext>),
}
impl RenderingContext {
fn context_id(&self) -> WebGLContextId {
match self {
RenderingContext::WebGL1(ref ctx) => ctx.context_id(),
RenderingContext::WebGL2(ref ctx) => ctx.base_context().context_id(),
}
}
}
impl<'a> From<&'a XRWebGLLayerInit> for LayerInit {
fn from(init: &'a XRWebGLLayerInit) -> LayerInit {
LayerInit::WebGLLayer {
@ -66,46 +49,31 @@ impl<'a> From<&'a XRWebGLLayerInit> for LayerInit {
#[dom_struct]
pub struct XRWebGLLayer {
reflector_: Reflector,
xr_layer: XRLayer,
antialias: bool,
depth: bool,
stencil: bool,
alpha: bool,
ignore_depth_values: bool,
context: RenderingContext,
session: Dom<XRSession>,
/// If none, this is an inline session (the composition disabled flag is true)
framebuffer: Option<Dom<WebGLFramebuffer>>,
/// If none, this is an inline session (the composition disabled flag is true)
#[ignore_malloc_size_of = "Layer ids don't heap-allocate"]
layer_id: Option<LayerId>,
}
impl XRWebGLLayer {
pub fn new_inherited(
session: &XRSession,
context: XRWebGLRenderingContext,
context: &WebGLRenderingContext,
init: &XRWebGLLayerInit,
framebuffer: Option<&WebGLFramebuffer>,
layer_id: Option<LayerId>,
) -> XRWebGLLayer {
XRWebGLLayer {
reflector_: Reflector::new(),
xr_layer: XRLayer::new_inherited(session, context, layer_id),
antialias: init.antialias,
depth: init.depth,
stencil: init.stencil,
alpha: init.alpha,
ignore_depth_values: init.ignoreDepthValues,
layer_id,
context: match context {
XRWebGLRenderingContext::WebGLRenderingContext(ctx) => {
RenderingContext::WebGL1(Dom::from_ref(&*ctx))
},
XRWebGLRenderingContext::WebGL2RenderingContext(ctx) => {
RenderingContext::WebGL2(Dom::from_ref(&*ctx))
},
},
session: Dom::from_ref(session),
framebuffer: framebuffer.map(Dom::from_ref),
}
}
@ -113,7 +81,7 @@ impl XRWebGLLayer {
pub fn new(
global: &GlobalScope,
session: &XRSession,
context: XRWebGLRenderingContext,
context: &WebGLRenderingContext,
init: &XRWebGLLayerInit,
framebuffer: Option<&WebGLFramebuffer>,
layer_id: Option<LayerId>,
@ -138,6 +106,11 @@ impl XRWebGLLayer {
context: XRWebGLRenderingContext,
init: &XRWebGLLayerInit,
) -> Fallible<DomRoot<Self>> {
let context = match context {
XRWebGLRenderingContext::WebGLRenderingContext(ctx) => ctx,
XRWebGLRenderingContext::WebGL2RenderingContext(ctx) => ctx.base_context(),
};
// Step 2
if session.is_ended() {
return Err(Error::InvalidState);
@ -169,16 +142,13 @@ impl XRWebGLLayer {
};
// Ensure that we finish setting up this layer before continuing.
match context {
XRWebGLRenderingContext::WebGLRenderingContext(ref ctx) => ctx.Finish(),
XRWebGLRenderingContext::WebGL2RenderingContext(ref ctx) => ctx.Finish(),
}
context.Finish();
// Step 10. "Return layer."
Ok(XRWebGLLayer::new(
&global.global(),
session,
context,
&context,
init,
framebuffer.as_deref(),
layer_id,
@ -186,15 +156,15 @@ impl XRWebGLLayer {
}
pub fn layer_id(&self) -> Option<LayerId> {
self.layer_id
self.xr_layer.layer_id()
}
pub fn context_id(&self) -> WebGLContextId {
self.context.context_id()
self.xr_layer.context_id()
}
pub fn session(&self) -> &XRSession {
&self.session
&self.xr_layer.session()
}
pub fn size(&self) -> Size2D<u32, Viewport> {
@ -205,10 +175,7 @@ impl XRWebGLLayer {
size.1.try_into().unwrap_or(0),
)
} else {
let size = match self.context {
RenderingContext::WebGL1(ref ctx) => ctx.Canvas().get_size(),
RenderingContext::WebGL2(ref ctx) => ctx.base_context().Canvas().get_size(),
};
let size = self.context().Canvas().get_size();
Size2D::from_untyped(size)
}
}
@ -225,7 +192,7 @@ impl XRWebGLLayer {
debug!("XRWebGLLayer begin frame");
let framebuffer = self.framebuffer.as_ref()?;
let context = framebuffer.upcast::<WebGLObject>().context();
let sub_images = frame.get_sub_images(self.layer_id?)?;
let sub_images = frame.get_sub_images(self.layer_id()?)?;
// TODO: Cache this texture
let color_texture_id =
WebGLTextureId::maybe_new(sub_images.sub_image.as_ref()?.color_texture)?;
@ -306,15 +273,8 @@ impl XRWebGLLayer {
Some(())
}
pub(crate) fn context(&self) -> XRWebGLRenderingContext {
match self.context {
RenderingContext::WebGL1(ref ctx) => {
XRWebGLRenderingContext::WebGLRenderingContext(DomRoot::from_ref(&**ctx))
},
RenderingContext::WebGL2(ref ctx) => {
XRWebGLRenderingContext::WebGL2RenderingContext(DomRoot::from_ref(&**ctx))
},
}
pub(crate) fn context(&self) -> &WebGLRenderingContext {
self.xr_layer.context()
}
}
@ -346,13 +306,13 @@ impl XRWebGLLayerMethods for XRWebGLLayer {
/// https://immersive-web.github.io/webxr/#dom-xrwebgllayer-getviewport
fn GetViewport(&self, view: &XRView) -> Option<DomRoot<XRViewport>> {
if self.session != view.session() {
if self.session() != view.session() {
return None;
}
let index = view.viewport_index();
let viewport = self.session.with_session(|s| {
let viewport = self.session().with_session(|s| {
// Inline sssions
if s.viewports().is_empty() {
Rect::from_size(self.size().to_i32())