diff options
author | Patrick Walton <pcwalton@mimiga.net> | 2019-10-15 12:57:00 -0500 |
---|---|---|
committer | Alan Jeffrey <ajeffrey@mozilla.com> | 2019-11-01 08:47:11 -0500 |
commit | a358bca7667a2da42024aca4ef619dad6d812862 (patch) | |
tree | acf2cc228afdf6875931d546cc08ec29dfb05362 /components/script/dom/webglframebuffer.rs | |
parent | 48d918dcdead5fcf38dbda1dfc0d0ca8284108c2 (diff) | |
download | servo-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.rs | 129 |
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); } } |