mirror of
https://github.com/servo/servo.git
synced 2025-08-03 04:30:10 +01:00
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>
This commit is contained in:
parent
48d918dcde
commit
a358bca766
52 changed files with 1929 additions and 2195 deletions
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue