Support WebGL2 contexts in XRWebGLLayer.

This commit is contained in:
Josh Matthews 2020-04-08 12:49:16 -04:00
parent 2128bf1e05
commit c002a29582
3 changed files with 54 additions and 17 deletions

View file

@ -5,6 +5,7 @@
// https://www.khronos.org/registry/webgl/specs/latest/1.0/webgl.idl // https://www.khronos.org/registry/webgl/specs/latest/1.0/webgl.idl
use crate::dom::bindings::cell::DomRefCell; use crate::dom::bindings::cell::DomRefCell;
use crate::dom::bindings::codegen::Bindings::WebGL2RenderingContextBinding::WebGL2RenderingContextConstants as constants; 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::inheritance::Castable;
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject}; use crate::dom::bindings::reflector::{reflect_dom_object, DomObject};
use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom}; use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom};
@ -141,10 +142,14 @@ impl WebGLFramebuffer {
// https://github.com/servo/servo/issues/24498 // https://github.com/servo/servo/issues/24498
pub fn maybe_new_webxr( pub fn maybe_new_webxr(
session: &XRSession, session: &XRSession,
context: &WebGLRenderingContext, context: &XRWebGLRenderingContext,
size: Size2D<i32, Viewport>, size: Size2D<i32, Viewport>,
) -> Option<(WebXRSwapChainId, DomRoot<Self>)> { ) -> Option<(WebXRSwapChainId, DomRoot<Self>)> {
let (sender, receiver) = webgl_channel().unwrap(); let (sender, receiver) = webgl_channel().unwrap();
let context = match context {
XRWebGLRenderingContext::WebGLRenderingContext(ref ctx) => DomRoot::from_ref(&**ctx),
XRWebGLRenderingContext::WebGL2RenderingContext(ref ctx) => ctx.base_context(),
};
let _ = context.webgl_sender().send_create_webxr_swap_chain( let _ = context.webgl_sender().send_create_webxr_swap_chain(
size.to_untyped(), size.to_untyped(),
sender, sender,
@ -153,7 +158,7 @@ impl WebGLFramebuffer {
let swap_chain_id = receiver.recv().unwrap()?; let swap_chain_id = receiver.recv().unwrap()?;
let framebuffer_id = let framebuffer_id =
WebGLFramebufferId::Opaque(WebGLOpaqueFramebufferId::WebXR(swap_chain_id)); WebGLFramebufferId::Opaque(WebGLOpaqueFramebufferId::WebXR(swap_chain_id));
let framebuffer = WebGLFramebuffer::new(context, framebuffer_id); let framebuffer = WebGLFramebuffer::new(&*context, framebuffer_id);
framebuffer.size.set(Some((size.width, size.height))); framebuffer.size.set(Some((size.width, size.height)));
framebuffer.status.set(constants::FRAMEBUFFER_COMPLETE); framebuffer.status.set(constants::FRAMEBUFFER_COMPLETE);
framebuffer.xr_session.set(Some(session)); framebuffer.xr_session.set(Some(session));

View file

@ -4,10 +4,8 @@
// https://immersive-web.github.io/webxr/#xrwebgllayer-interface // https://immersive-web.github.io/webxr/#xrwebgllayer-interface
// typedef (WebGLRenderingContext or typedef (WebGLRenderingContext or
// WebGL2RenderingContext) XRWebGLRenderingContext; WebGL2RenderingContext) XRWebGLRenderingContext;
typedef WebGLRenderingContext XRWebGLRenderingContext;
dictionary XRWebGLLayerInit { dictionary XRWebGLLayerInit {
boolean antialias = true; boolean antialias = true;

View file

@ -3,9 +3,11 @@
* 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::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextMethods; use crate::dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextMethods;
use crate::dom::bindings::codegen::Bindings::WebGL2RenderingContextBinding::WebGL2RenderingContextBinding::WebGL2RenderingContextMethods;
use crate::dom::bindings::codegen::Bindings::XRViewBinding::{XREye, XRViewMethods}; use crate::dom::bindings::codegen::Bindings::XRViewBinding::{XREye, XRViewMethods};
use crate::dom::bindings::codegen::Bindings::XRWebGLLayerBinding::XRWebGLLayerInit; use crate::dom::bindings::codegen::Bindings::XRWebGLLayerBinding::XRWebGLLayerInit;
use crate::dom::bindings::codegen::Bindings::XRWebGLLayerBinding::XRWebGLLayerMethods; 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::Error;
use crate::dom::bindings::error::Fallible; use crate::dom::bindings::error::Fallible;
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector}; use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector};
@ -13,6 +15,7 @@ use crate::dom::bindings::root::{Dom, DomRoot};
use crate::dom::globalscope::GlobalScope; use crate::dom::globalscope::GlobalScope;
use crate::dom::webglframebuffer::WebGLFramebuffer; use crate::dom::webglframebuffer::WebGLFramebuffer;
use crate::dom::webglrenderingcontext::WebGLRenderingContext; use crate::dom::webglrenderingcontext::WebGLRenderingContext;
use crate::dom::webgl2renderingcontext::WebGL2RenderingContext;
use crate::dom::window::Window; use crate::dom::window::Window;
use crate::dom::xrsession::XRSession; use crate::dom::xrsession::XRSession;
use crate::dom::xrview::XRView; use crate::dom::xrview::XRView;
@ -24,6 +27,13 @@ use std::convert::TryInto;
use webxr_api::SwapChainId as WebXRSwapChainId; use webxr_api::SwapChainId as WebXRSwapChainId;
use webxr_api::{Viewport, Views}; use webxr_api::{Viewport, Views};
#[derive(JSTraceable, MallocSizeOf)]
#[unrooted_must_root_lint::must_root]
pub enum RenderingContext {
WebGL1(Dom<WebGLRenderingContext>),
WebGL2(Dom<WebGL2RenderingContext>),
}
#[dom_struct] #[dom_struct]
pub struct XRWebGLLayer { pub struct XRWebGLLayer {
reflector_: Reflector, reflector_: Reflector,
@ -33,7 +43,7 @@ pub struct XRWebGLLayer {
alpha: bool, alpha: bool,
#[ignore_malloc_size_of = "ids don't malloc"] #[ignore_malloc_size_of = "ids don't malloc"]
swap_chain_id: Option<WebXRSwapChainId>, swap_chain_id: Option<WebXRSwapChainId>,
context: Dom<WebGLRenderingContext>, context: RenderingContext,
session: Dom<XRSession>, session: Dom<XRSession>,
/// If none, this is an inline session (the composition disabled flag is true) /// If none, this is an inline session (the composition disabled flag is true)
framebuffer: Option<Dom<WebGLFramebuffer>>, framebuffer: Option<Dom<WebGLFramebuffer>>,
@ -43,7 +53,7 @@ impl XRWebGLLayer {
pub fn new_inherited( pub fn new_inherited(
swap_chain_id: Option<WebXRSwapChainId>, swap_chain_id: Option<WebXRSwapChainId>,
session: &XRSession, session: &XRSession,
context: &WebGLRenderingContext, context: XRWebGLRenderingContext,
init: &XRWebGLLayerInit, init: &XRWebGLLayerInit,
framebuffer: Option<&WebGLFramebuffer>, framebuffer: Option<&WebGLFramebuffer>,
) -> XRWebGLLayer { ) -> XRWebGLLayer {
@ -54,7 +64,14 @@ impl XRWebGLLayer {
stencil: init.stencil, stencil: init.stencil,
alpha: init.alpha, alpha: init.alpha,
swap_chain_id, swap_chain_id,
context: Dom::from_ref(context), 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), session: Dom::from_ref(session),
framebuffer: framebuffer.map(Dom::from_ref), framebuffer: framebuffer.map(Dom::from_ref),
} }
@ -64,7 +81,7 @@ impl XRWebGLLayer {
global: &GlobalScope, global: &GlobalScope,
swap_chain_id: Option<WebXRSwapChainId>, swap_chain_id: Option<WebXRSwapChainId>,
session: &XRSession, session: &XRSession,
context: &WebGLRenderingContext, context: XRWebGLRenderingContext,
init: &XRWebGLLayerInit, init: &XRWebGLLayerInit,
framebuffer: Option<&WebGLFramebuffer>, framebuffer: Option<&WebGLFramebuffer>,
) -> DomRoot<XRWebGLLayer> { ) -> DomRoot<XRWebGLLayer> {
@ -85,7 +102,7 @@ impl XRWebGLLayer {
pub fn Constructor( pub fn Constructor(
global: &Window, global: &Window,
session: &XRSession, session: &XRSession,
context: &WebGLRenderingContext, context: XRWebGLRenderingContext,
init: &XRWebGLLayerInit, init: &XRWebGLLayerInit,
) -> Fallible<DomRoot<Self>> { ) -> Fallible<DomRoot<Self>> {
let framebuffer; let framebuffer;
@ -99,7 +116,7 @@ impl XRWebGLLayer {
// Step 9.2. "Initialize layers framebuffer to a new opaque framebuffer created with context." // Step 9.2. "Initialize layers framebuffer to a new opaque framebuffer created with context."
let (swap_chain_id, framebuffer) = if session.is_immersive() { let (swap_chain_id, framebuffer) = if session.is_immersive() {
let size = session.with_session(|session| session.recommended_framebuffer_resolution()); let size = session.with_session(|session| session.recommended_framebuffer_resolution());
let (swap_chain_id, fb) = WebGLFramebuffer::maybe_new_webxr(session, context, size) let (swap_chain_id, fb) = WebGLFramebuffer::maybe_new_webxr(session, &context, size)
.ok_or(Error::Operation)?; .ok_or(Error::Operation)?;
framebuffer = fb; framebuffer = fb;
(Some(swap_chain_id), Some(&*framebuffer)) (Some(swap_chain_id), Some(&*framebuffer))
@ -114,7 +131,10 @@ impl XRWebGLLayer {
// throw an OperationError and abort these steps." // throw an OperationError and abort these steps."
// Ensure that we finish setting up this layer before continuing. // Ensure that we finish setting up this layer before continuing.
context.Finish(); match context {
XRWebGLRenderingContext::WebGLRenderingContext(ref ctx) => ctx.Finish(),
XRWebGLRenderingContext::WebGL2RenderingContext(ref ctx) => ctx.Finish(),
}
// Step 10. "Return layer." // Step 10. "Return layer."
Ok(XRWebGLLayer::new( Ok(XRWebGLLayer::new(
@ -143,7 +163,10 @@ impl XRWebGLLayer {
.expect("swap_buffers must not be called for inline sessions") .expect("swap_buffers must not be called for inline sessions")
.id() .id()
{ {
self.context.swap_buffers(Some(id)); match self.context {
RenderingContext::WebGL1(ref ctx) => ctx.swap_buffers(Some(id)),
RenderingContext::WebGL2(ref ctx) => ctx.base_context().swap_buffers(Some(id)),
}
} }
} }
@ -155,7 +178,11 @@ impl XRWebGLLayer {
size.1.try_into().unwrap_or(0), size.1.try_into().unwrap_or(0),
) )
} else { } else {
Size2D::from_untyped(self.context.Canvas().get_size()) let size = match self.context {
RenderingContext::WebGL1(ref ctx) => ctx.Canvas().get_size(),
RenderingContext::WebGL2(ref ctx) => ctx.base_context().Canvas().get_size(),
};
Size2D::from_untyped(size)
} }
} }
} }
@ -182,8 +209,15 @@ impl XRWebGLLayerMethods for XRWebGLLayer {
} }
/// https://immersive-web.github.io/webxr/#dom-xrwebgllayer-context /// https://immersive-web.github.io/webxr/#dom-xrwebgllayer-context
fn Context(&self) -> DomRoot<WebGLRenderingContext> { fn Context(&self) -> XRWebGLRenderingContext {
DomRoot::from_ref(&self.context) match self.context {
RenderingContext::WebGL1(ref ctx) => {
XRWebGLRenderingContext::WebGLRenderingContext(DomRoot::from_ref(&**ctx))
},
RenderingContext::WebGL2(ref ctx) => {
XRWebGLRenderingContext::WebGL2RenderingContext(DomRoot::from_ref(&**ctx))
},
}
} }
/// https://immersive-web.github.io/webxr/#dom-xrwebgllayer-framebuffer /// https://immersive-web.github.io/webxr/#dom-xrwebgllayer-framebuffer