aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom/webglframebuffer.rs
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2019-10-15 12:57:00 -0500
committerAlan Jeffrey <ajeffrey@mozilla.com>2019-11-01 08:47:11 -0500
commita358bca7667a2da42024aca4ef619dad6d812862 (patch)
treeacf2cc228afdf6875931d546cc08ec29dfb05362 /components/script/dom/webglframebuffer.rs
parent48d918dcdead5fcf38dbda1dfc0d0ca8284108c2 (diff)
downloadservo-a358bca7667a2da42024aca4ef619dad6d812862.tar.gz
servo-a358bca7667a2da42024aca4ef619dad6d812862.zip
Use surfman for managing GL surfaces
Co-authored-by: Alan Jeffrey <ajeffrey@mozilla.com> Co-authored-by: Zakor Gyula <gyula.zakor@h-lab.eu> Co-authored-by: Josh Matthews <josh@joshmatthews.net>
Diffstat (limited to 'components/script/dom/webglframebuffer.rs')
-rw-r--r--components/script/dom/webglframebuffer.rs129
1 files changed, 108 insertions, 21 deletions
diff --git a/components/script/dom/webglframebuffer.rs b/components/script/dom/webglframebuffer.rs
index 3a31e99be33..0ab85f14e2f 100644
--- a/components/script/dom/webglframebuffer.rs
+++ b/components/script/dom/webglframebuffer.rs
@@ -8,15 +8,20 @@ use crate::dom::bindings::codegen::Bindings::WebGLFramebufferBinding;
use crate::dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextConstants as constants;
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::bindings::root::{Dom, DomRoot, MutNullableDom};
use crate::dom::webglobject::WebGLObject;
use crate::dom::webglrenderbuffer::WebGLRenderbuffer;
use crate::dom::webglrenderingcontext::WebGLRenderingContext;
use crate::dom::webgltexture::WebGLTexture;
+use crate::dom::xrsession::XRSession;
use canvas_traits::webgl::{webgl_channel, WebGLError, WebGLResult};
-use canvas_traits::webgl::{WebGLCommand, WebGLFramebufferBindingRequest, WebGLFramebufferId};
+use canvas_traits::webgl::{WebGLCommand, WebGLFramebufferBindingRequest};
+use canvas_traits::webgl::{WebGLFramebufferId, WebGLOpaqueFramebufferId};
use dom_struct::dom_struct;
+use euclid::Size2D;
use std::cell::Cell;
+use webxr_api::SwapChainId as WebXRSwapChainId;
+use webxr_api::Viewport;
pub enum CompleteForRendering {
Complete,
@@ -92,6 +97,9 @@ pub struct WebGLFramebuffer {
stencil: DomRefCell<Option<WebGLFramebufferAttachment>>,
depthstencil: DomRefCell<Option<WebGLFramebufferAttachment>>,
is_initialized: Cell<bool>,
+ // Framebuffers for XR keep a reference to the XR session.
+ // https://github.com/immersive-web/webxr/issues/856
+ xr_session: MutNullableDom<XRSession>,
}
impl WebGLFramebuffer {
@@ -108,16 +116,37 @@ impl WebGLFramebuffer {
stencil: DomRefCell::new(None),
depthstencil: DomRefCell::new(None),
is_initialized: Cell::new(false),
+ xr_session: Default::default(),
}
}
pub fn maybe_new(context: &WebGLRenderingContext) -> Option<DomRoot<Self>> {
let (sender, receiver) = webgl_channel().unwrap();
context.send_command(WebGLCommand::CreateFramebuffer(sender));
- receiver
- .recv()
- .unwrap()
- .map(|id| WebGLFramebuffer::new(context, id))
+ let id = receiver.recv().unwrap()?;
+ let framebuffer = WebGLFramebuffer::new(context, WebGLFramebufferId::Transparent(id));
+ Some(framebuffer)
+ }
+
+ // TODO: depth, stencil and alpha
+ // https://github.com/servo/servo/issues/24498
+ pub fn maybe_new_webxr(
+ session: &XRSession,
+ context: &WebGLRenderingContext,
+ size: Size2D<i32, Viewport>,
+ ) -> Option<(WebXRSwapChainId, DomRoot<Self>)> {
+ let (sender, receiver) = webgl_channel().unwrap();
+ let _ = context
+ .webgl_sender()
+ .send_create_webxr_swap_chain(size.to_untyped(), sender);
+ let swap_chain_id = receiver.recv().unwrap()?;
+ let framebuffer_id =
+ WebGLFramebufferId::Opaque(WebGLOpaqueFramebufferId::WebXR(swap_chain_id));
+ let framebuffer = WebGLFramebuffer::new(context, framebuffer_id);
+ framebuffer.size.set(Some((size.width, size.height)));
+ framebuffer.status.set(constants::FRAMEBUFFER_COMPLETE);
+ framebuffer.xr_session.set(Some(session));
+ Some((swap_chain_id, framebuffer))
}
pub fn new(context: &WebGLRenderingContext, id: WebGLFramebufferId) -> DomRoot<Self> {
@@ -134,11 +163,25 @@ impl WebGLFramebuffer {
self.id
}
+ fn is_in_xr_session(&self) -> bool {
+ self.xr_session.get().is_some()
+ }
+
+ pub fn validate_transparent(&self) -> WebGLResult<()> {
+ if self.is_in_xr_session() {
+ Err(WebGLError::InvalidOperation)
+ } else {
+ Ok(())
+ }
+ }
+
pub fn bind(&self, target: u32) {
- // Update the framebuffer status on binding. It may have
- // changed if its attachments were resized or deleted while
- // we've been unbound.
- self.update_status();
+ if !self.is_in_xr_session() {
+ // Update the framebuffer status on binding. It may have
+ // changed if its attachments were resized or deleted while
+ // we've been unbound.
+ self.update_status();
+ }
self.target.set(Some(target));
self.upcast::<WebGLObject>()
@@ -267,7 +310,17 @@ impl WebGLFramebuffer {
}
pub fn check_status(&self) -> u32 {
- return self.status.get();
+ // For opaque framebuffers, check to see if the XR session is currently processing an rAF
+ // https://immersive-web.github.io/webxr/#opaque-framebuffer
+ if let Some(xr_session) = self.xr_session.get() {
+ if xr_session.is_outside_raf() {
+ constants::FRAMEBUFFER_UNSUPPORTED
+ } else {
+ constants::FRAMEBUFFER_COMPLETE
+ }
+ } else {
+ self.status.get()
+ }
}
pub fn check_status_for_rendering(&self) -> CompleteForRendering {
@@ -276,6 +329,12 @@ impl WebGLFramebuffer {
return CompleteForRendering::Incomplete;
}
+ // XR framebuffers are complete inside an rAF
+ // https://github.com/immersive-web/webxr/issues/854
+ if self.xr_session.get().is_some() {
+ return CompleteForRendering::Complete;
+ }
+
if self.color.borrow().is_none() {
return CompleteForRendering::MissingColorAttachment;
}
@@ -309,6 +368,10 @@ impl WebGLFramebuffer {
}
pub fn renderbuffer(&self, attachment: u32, rb: Option<&WebGLRenderbuffer>) -> WebGLResult<()> {
+ // Opaque framebuffers cannot have their attachments changed
+ // https://immersive-web.github.io/webxr/#opaque-framebuffer
+ self.validate_transparent()?;
+
let binding = self
.attachment_binding(attachment)
.ok_or(WebGLError::InvalidEnum)?;
@@ -337,7 +400,7 @@ impl WebGLFramebuffer {
));
if rb.is_none() {
- self.detach_binding(binding, attachment);
+ self.detach_binding(binding, attachment)?;
}
self.update_status();
@@ -349,14 +412,19 @@ impl WebGLFramebuffer {
&self,
binding: &DomRefCell<Option<WebGLFramebufferAttachment>>,
attachment: u32,
- ) {
+ ) -> WebGLResult<()> {
+ // Opaque framebuffers cannot have their attachments changed
+ // https://immersive-web.github.io/webxr/#opaque-framebuffer
+ self.validate_transparent()?;
+
if let Some(att) = &*binding.borrow() {
att.detach();
}
*binding.borrow_mut() = None;
if INTERESTING_ATTACHMENT_POINTS.contains(&attachment) {
- self.reattach_depth_stencil();
+ self.reattach_depth_stencil()?;
}
+ Ok(())
}
fn attachment_binding(
@@ -372,7 +440,11 @@ impl WebGLFramebuffer {
}
}
- fn reattach_depth_stencil(&self) {
+ fn reattach_depth_stencil(&self) -> WebGLResult<()> {
+ // Opaque framebuffers cannot have their attachments changed
+ // https://immersive-web.github.io/webxr/#opaque-framebuffer
+ self.validate_transparent()?;
+
let reattach = |attachment: &WebGLFramebufferAttachment, attachment_point| {
let context = self.upcast::<WebGLObject>().context();
match *attachment {
@@ -411,6 +483,7 @@ impl WebGLFramebuffer {
if let Some(ref depth_stencil) = *self.depthstencil.borrow() {
reattach(depth_stencil, constants::DEPTH_STENCIL_ATTACHMENT);
}
+ Ok(())
}
pub fn attachment(&self, attachment: u32) -> Option<WebGLFramebufferAttachmentRoot> {
@@ -428,6 +501,10 @@ impl WebGLFramebuffer {
texture: Option<&WebGLTexture>,
level: i32,
) -> WebGLResult<()> {
+ // Opaque framebuffers cannot have their attachments changed
+ // https://immersive-web.github.io/webxr/#opaque-framebuffer
+ self.validate_transparent()?;
+
let binding = self
.attachment_binding(attachment)
.ok_or(WebGLError::InvalidEnum)?;
@@ -498,7 +575,7 @@ impl WebGLFramebuffer {
));
if texture.is_none() {
- self.detach_binding(binding, attachment);
+ self.detach_binding(binding, attachment)?;
}
self.update_status();
@@ -563,7 +640,11 @@ impl WebGLFramebuffer {
}
}
- pub fn detach_renderbuffer(&self, rb: &WebGLRenderbuffer) {
+ pub fn detach_renderbuffer(&self, rb: &WebGLRenderbuffer) -> WebGLResult<()> {
+ // Opaque framebuffers cannot have their attachments changed
+ // https://immersive-web.github.io/webxr/#opaque-framebuffer
+ self.validate_transparent()?;
+
let mut depth_or_stencil_updated = false;
self.with_matching_renderbuffers(rb, |att, name| {
depth_or_stencil_updated |= INTERESTING_ATTACHMENT_POINTS.contains(&name);
@@ -575,11 +656,16 @@ impl WebGLFramebuffer {
});
if depth_or_stencil_updated {
- self.reattach_depth_stencil();
+ self.reattach_depth_stencil()?;
}
+ Ok(())
}
- pub fn detach_texture(&self, texture: &WebGLTexture) {
+ pub fn detach_texture(&self, texture: &WebGLTexture) -> WebGLResult<()> {
+ // Opaque framebuffers cannot have their attachments changed
+ // https://immersive-web.github.io/webxr/#opaque-framebuffer
+ self.validate_transparent()?;
+
let mut depth_or_stencil_updated = false;
self.with_matching_textures(texture, |att, name| {
depth_or_stencil_updated |= INTERESTING_ATTACHMENT_POINTS.contains(&name);
@@ -591,8 +677,9 @@ impl WebGLFramebuffer {
});
if depth_or_stencil_updated {
- self.reattach_depth_stencil();
+ self.reattach_depth_stencil()?;
}
+ Ok(())
}
pub fn invalidate_renderbuffer(&self, rb: &WebGLRenderbuffer) {
@@ -615,7 +702,7 @@ impl WebGLFramebuffer {
impl Drop for WebGLFramebuffer {
fn drop(&mut self) {
- self.delete(true);
+ let _ = self.delete(true);
}
}