mirror of
https://github.com/servo/servo.git
synced 2025-08-06 14:10:11 +01:00
Added framebuffer and related attributes to XRWebGLLayer
This commit is contained in:
parent
dc1da02aa4
commit
aa0a72df0f
10 changed files with 158 additions and 46 deletions
|
@ -6,10 +6,15 @@ use crate::dom::bindings::codegen::Bindings::XRViewBinding::{XREye, XRViewMethod
|
|||
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::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextBinding::WebGLRenderingContextMethods;
|
||||
use crate::dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextConstants as constants;
|
||||
use crate::dom::bindings::error::Error;
|
||||
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::webgl_validations::types::TexImageTarget;
|
||||
use crate::dom::webglframebuffer::WebGLFramebuffer;
|
||||
use crate::dom::webglrenderingcontext::WebGLRenderingContext;
|
||||
use crate::dom::window::Window;
|
||||
use crate::dom::xrlayer::XRLayer;
|
||||
|
@ -17,6 +22,9 @@ use crate::dom::xrsession::XRSession;
|
|||
use crate::dom::xrview::XRView;
|
||||
use crate::dom::xrviewport::XRViewport;
|
||||
use dom_struct::dom_struct;
|
||||
use js::rust::CustomAutoRooter;
|
||||
use std::convert::TryInto;
|
||||
use webxr_api::Views;
|
||||
|
||||
#[dom_struct]
|
||||
pub struct XRWebGLLayer {
|
||||
|
@ -27,6 +35,7 @@ pub struct XRWebGLLayer {
|
|||
alpha: bool,
|
||||
context: Dom<WebGLRenderingContext>,
|
||||
session: Dom<XRSession>,
|
||||
framebuffer: Dom<WebGLFramebuffer>,
|
||||
}
|
||||
|
||||
impl XRWebGLLayer {
|
||||
|
@ -34,6 +43,7 @@ impl XRWebGLLayer {
|
|||
session: &XRSession,
|
||||
context: &WebGLRenderingContext,
|
||||
init: &XRWebGLLayerInit,
|
||||
framebuffer: &WebGLFramebuffer,
|
||||
) -> XRWebGLLayer {
|
||||
XRWebGLLayer {
|
||||
xrlayer: XRLayer::new_inherited(),
|
||||
|
@ -43,6 +53,7 @@ impl XRWebGLLayer {
|
|||
alpha: init.alpha,
|
||||
context: Dom::from_ref(context),
|
||||
session: Dom::from_ref(session),
|
||||
framebuffer: Dom::from_ref(framebuffer),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -51,21 +62,82 @@ impl XRWebGLLayer {
|
|||
session: &XRSession,
|
||||
context: &WebGLRenderingContext,
|
||||
init: &XRWebGLLayerInit,
|
||||
framebuffer: &WebGLFramebuffer,
|
||||
) -> DomRoot<XRWebGLLayer> {
|
||||
reflect_dom_object(
|
||||
Box::new(XRWebGLLayer::new_inherited(session, context, init)),
|
||||
Box::new(XRWebGLLayer::new_inherited(
|
||||
session,
|
||||
context,
|
||||
init,
|
||||
framebuffer,
|
||||
)),
|
||||
global,
|
||||
XRWebGLLayerBinding::Wrap,
|
||||
)
|
||||
}
|
||||
|
||||
/// https://immersive-web.github.io/webxr/#dom-xrwebgllayer-xrwebgllayer
|
||||
pub fn Constructor(
|
||||
global: &Window,
|
||||
session: &XRSession,
|
||||
context: &WebGLRenderingContext,
|
||||
init: &XRWebGLLayerInit,
|
||||
) -> Fallible<DomRoot<Self>> {
|
||||
Ok(XRWebGLLayer::new(&global.global(), session, context, init))
|
||||
let cx = global.get_cx();
|
||||
let old_fbo = context.bound_framebuffer();
|
||||
let old_texture = context
|
||||
.textures()
|
||||
.active_texture_for_image_target(TexImageTarget::Texture2D);
|
||||
|
||||
// Step 8.2. "Initialize layer’s framebuffer to a new opaque framebuffer created with context."
|
||||
let framebuffer = context.CreateFramebuffer().ok_or(Error::Operation)?;
|
||||
|
||||
// Step 8.3. "Allocate and initialize resources compatible with session’s XR device,
|
||||
// including GPU accessible memory buffers, as required to support the compositing of layer."
|
||||
|
||||
// Create a new texture with size given by the session's recommended resolution
|
||||
let texture = context.CreateTexture().ok_or(Error::Operation)?;
|
||||
let resolution = session.with_session(|s| s.recommended_framebuffer_resolution());
|
||||
let mut pixels = CustomAutoRooter::new(None);
|
||||
context.BindTexture(constants::TEXTURE_2D, Some(&texture));
|
||||
let sc = context.TexImage2D(
|
||||
constants::TEXTURE_2D,
|
||||
0,
|
||||
constants::RGBA,
|
||||
resolution.width,
|
||||
resolution.height,
|
||||
0,
|
||||
constants::RGBA,
|
||||
constants::UNSIGNED_BYTE,
|
||||
pixels.root(cx),
|
||||
);
|
||||
|
||||
// Bind the new texture to the framebuffer
|
||||
context.BindFramebuffer(constants::FRAMEBUFFER, Some(&framebuffer));
|
||||
context.FramebufferTexture2D(
|
||||
constants::FRAMEBUFFER,
|
||||
constants::COLOR_ATTACHMENT0,
|
||||
constants::TEXTURE_2D,
|
||||
Some(&texture),
|
||||
0,
|
||||
);
|
||||
|
||||
// Restore the WebGL state while complaining about global mutable state
|
||||
context.BindTexture(constants::TEXTURE_2D, old_texture.as_ref().map(|t| &**t));
|
||||
context.BindFramebuffer(constants::FRAMEBUFFER, old_fbo.as_ref().map(|f| &**f));
|
||||
|
||||
// Step 8.4: "If layer’s resources were unable to be created for any reason,
|
||||
// throw an OperationError and abort these steps."
|
||||
sc.or(Err(Error::Operation))?;
|
||||
|
||||
// Step 9. "Return layer."
|
||||
Ok(XRWebGLLayer::new(
|
||||
&global.global(),
|
||||
session,
|
||||
context,
|
||||
init,
|
||||
&framebuffer,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -95,28 +167,48 @@ impl XRWebGLLayerMethods for XRWebGLLayer {
|
|||
DomRoot::from_ref(&self.context)
|
||||
}
|
||||
|
||||
/// https://immersive-web.github.io/webxr/#dom-xrwebgllayer-framebuffer
|
||||
fn Framebuffer(&self) -> DomRoot<WebGLFramebuffer> {
|
||||
DomRoot::from_ref(&self.framebuffer)
|
||||
}
|
||||
|
||||
/// https://immersive-web.github.io/webxr/#dom-xrwebgllayer-framebufferwidth
|
||||
fn FramebufferWidth(&self) -> u32 {
|
||||
self.framebuffer
|
||||
.size()
|
||||
.unwrap_or((0, 0))
|
||||
.0
|
||||
.try_into()
|
||||
.unwrap_or(0)
|
||||
}
|
||||
|
||||
/// https://immersive-web.github.io/webxr/#dom-xrwebgllayer-framebufferheight
|
||||
fn FramebufferHeight(&self) -> u32 {
|
||||
self.framebuffer
|
||||
.size()
|
||||
.unwrap_or((0, 0))
|
||||
.1
|
||||
.try_into()
|
||||
.unwrap_or(0)
|
||||
}
|
||||
|
||||
/// 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 views = self.session.with_session(|s| s.views().clone());
|
||||
|
||||
let x = if view.Eye() == XREye::Left {
|
||||
0
|
||||
} else {
|
||||
size.width / 2
|
||||
let viewport = match (view.Eye(), views) {
|
||||
(XREye::None, Views::Mono(view)) => view.viewport,
|
||||
(XREye::Left, Views::Stereo(view, _)) => view.viewport,
|
||||
(XREye::Right, Views::Stereo(_, view)) => view.viewport,
|
||||
// The spec doesn't really say what to do in this case
|
||||
// https://github.com/immersive-web/webxr/issues/769
|
||||
_ => return None,
|
||||
};
|
||||
// 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,
|
||||
))
|
||||
|
||||
Some(XRViewport::new(&self.global(), viewport))
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue