diff options
Diffstat (limited to 'components/script/dom')
-rw-r--r-- | components/script/dom/bindings/trace.rs | 4 | ||||
-rw-r--r-- | components/script/dom/webglframebuffer.rs | 25 | ||||
-rw-r--r-- | components/script/dom/webglrenderbuffer.rs | 17 | ||||
-rw-r--r-- | components/script/dom/webglrenderingcontext.rs | 62 | ||||
-rw-r--r-- | components/script/dom/webgltexture.rs | 19 | ||||
-rw-r--r-- | components/script/dom/xrwebgllayer.rs | 8 |
6 files changed, 124 insertions, 11 deletions
diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs index 91b4c119999..3e7486ed8ca 100644 --- a/components/script/dom/bindings/trace.rs +++ b/components/script/dom/bindings/trace.rs @@ -45,8 +45,8 @@ use canvas_traits::canvas::{ CanvasGradientStop, CanvasId, LinearGradientStyle, RadialGradientStyle, }; use canvas_traits::canvas::{CompositionOrBlending, LineCapStyle, LineJoinStyle, RepetitionStyle}; -use canvas_traits::webgl::GLLimits; use canvas_traits::webgl::{ActiveAttribInfo, ActiveUniformInfo, GlType, TexDataType, TexFormat}; +use canvas_traits::webgl::{GLFormats, GLLimits}; use canvas_traits::webgl::{WebGLBufferId, WebGLChan, WebGLContextShareMode, WebGLError}; use canvas_traits::webgl::{WebGLFramebufferId, WebGLMsgSender, WebGLPipeline, WebGLProgramId}; use canvas_traits::webgl::{WebGLReceiver, WebGLRenderbufferId, WebGLSLVersion, WebGLSender}; @@ -437,7 +437,7 @@ unsafe_no_jsmanaged_fields!(StorageType); unsafe_no_jsmanaged_fields!(CanvasGradientStop, LinearGradientStyle, RadialGradientStyle); unsafe_no_jsmanaged_fields!(LineCapStyle, LineJoinStyle, CompositionOrBlending); unsafe_no_jsmanaged_fields!(RepetitionStyle); -unsafe_no_jsmanaged_fields!(WebGLError, GLLimits, GlType); +unsafe_no_jsmanaged_fields!(WebGLError, GLFormats, GLLimits, GlType); unsafe_no_jsmanaged_fields!(TimeProfilerChan); unsafe_no_jsmanaged_fields!(MemProfilerChan); unsafe_no_jsmanaged_fields!(PseudoElement); diff --git a/components/script/dom/webglframebuffer.rs b/components/script/dom/webglframebuffer.rs index 114ede38b01..3a31e99be33 100644 --- a/components/script/dom/webglframebuffer.rs +++ b/components/script/dom/webglframebuffer.rs @@ -59,6 +59,15 @@ impl WebGLFramebufferAttachment { }, } } + + fn detach(&self) { + match self { + WebGLFramebufferAttachment::Renderbuffer(rb) => rb.detach_from_framebuffer(), + WebGLFramebufferAttachment::Texture { ref texture, .. } => { + texture.detach_from_framebuffer() + }, + } + } } #[derive(Clone, JSTraceable, MallocSizeOf)] @@ -161,7 +170,7 @@ impl WebGLFramebuffer { self.size.get() } - fn update_status(&self) { + pub fn update_status(&self) { let c = self.color.borrow(); let z = self.depth.borrow(); let s = self.stencil.borrow(); @@ -177,6 +186,7 @@ impl WebGLFramebuffer { constants::RGB5_A1, constants::RGB565, constants::RGBA, + constants::RGB, ][..], &[constants::DEPTH_COMPONENT16][..], &[constants::STENCIL_INDEX8][..], @@ -310,6 +320,7 @@ impl WebGLFramebuffer { } *binding.borrow_mut() = Some(WebGLFramebufferAttachment::Renderbuffer(Dom::from_ref(rb))); + rb.attach_to_framebuffer(self); Some(rb.id()) }, @@ -339,6 +350,9 @@ impl WebGLFramebuffer { binding: &DomRefCell<Option<WebGLFramebufferAttachment>>, attachment: u32, ) { + if let Some(att) = &*binding.borrow() { + att.detach(); + } *binding.borrow_mut() = None; if INTERESTING_ATTACHMENT_POINTS.contains(&attachment) { self.reattach_depth_stencil(); @@ -363,6 +377,7 @@ impl WebGLFramebuffer { let context = self.upcast::<WebGLObject>().context(); match *attachment { WebGLFramebufferAttachment::Renderbuffer(ref rb) => { + rb.attach_to_framebuffer(self); context.send_command(WebGLCommand::FramebufferRenderbuffer( constants::FRAMEBUFFER, attachment_point, @@ -371,6 +386,7 @@ impl WebGLFramebuffer { )); }, WebGLFramebufferAttachment::Texture { ref texture, level } => { + texture.attach_to_framebuffer(self); context.send_command(WebGLCommand::FramebufferTexture2D( constants::FRAMEBUFFER, attachment_point, @@ -463,6 +479,7 @@ impl WebGLFramebuffer { texture: Dom::from_ref(texture), level: level, }); + texture.attach_to_framebuffer(self); Some(texture.id()) }, @@ -550,6 +567,9 @@ impl WebGLFramebuffer { let mut depth_or_stencil_updated = false; self.with_matching_renderbuffers(rb, |att, name| { depth_or_stencil_updated |= INTERESTING_ATTACHMENT_POINTS.contains(&name); + if let Some(att) = &*att.borrow() { + att.detach(); + } *att.borrow_mut() = None; self.update_status(); }); @@ -563,6 +583,9 @@ impl WebGLFramebuffer { let mut depth_or_stencil_updated = false; self.with_matching_textures(texture, |att, name| { depth_or_stencil_updated |= INTERESTING_ATTACHMENT_POINTS.contains(&name); + if let Some(att) = &*att.borrow() { + att.detach(); + } *att.borrow_mut() = None; self.update_status(); }); diff --git a/components/script/dom/webglrenderbuffer.rs b/components/script/dom/webglrenderbuffer.rs index f210b579e88..07afdbccb44 100644 --- a/components/script/dom/webglrenderbuffer.rs +++ b/components/script/dom/webglrenderbuffer.rs @@ -10,7 +10,8 @@ use crate::dom::bindings::codegen::Bindings::WebGLRenderbufferBinding; 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::DomRoot; +use crate::dom::bindings::root::{DomRoot, MutNullableDom}; +use crate::dom::webglframebuffer::WebGLFramebuffer; use crate::dom::webglobject::WebGLObject; use crate::dom::webglrenderingcontext::WebGLRenderingContext; use canvas_traits::webgl::{ @@ -28,6 +29,7 @@ pub struct WebGLRenderbuffer { size: Cell<Option<(i32, i32)>>, internal_format: Cell<Option<u32>>, is_initialized: Cell<bool>, + attached_framebuffer: MutNullableDom<WebGLFramebuffer>, } impl WebGLRenderbuffer { @@ -40,6 +42,7 @@ impl WebGLRenderbuffer { internal_format: Cell::new(None), size: Cell::new(None), is_initialized: Cell::new(false), + attached_framebuffer: Default::default(), } } @@ -186,6 +189,10 @@ impl WebGLRenderbuffer { self.internal_format.set(Some(internal_format)); self.is_initialized.set(false); + if let Some(fb) = self.attached_framebuffer.get() { + fb.update_status(); + } + self.upcast::<WebGLObject>() .context() .send_command(WebGLCommand::RenderbufferStorage( @@ -199,6 +206,14 @@ impl WebGLRenderbuffer { Ok(()) } + + pub fn attach_to_framebuffer(&self, fb: &WebGLFramebuffer) { + self.attached_framebuffer.set(Some(fb)); + } + + pub fn detach_from_framebuffer(&self) { + self.attached_framebuffer.set(None); + } } impl Drop for WebGLRenderbuffer { diff --git a/components/script/dom/webglrenderingcontext.rs b/components/script/dom/webglrenderingcontext.rs index e50d70cb916..33aaaf603d4 100644 --- a/components/script/dom/webglrenderingcontext.rs +++ b/components/script/dom/webglrenderingcontext.rs @@ -53,8 +53,8 @@ use crate::script_runtime::JSContext as SafeJSContext; use backtrace::Backtrace; use canvas_traits::webgl::WebGLError::*; use canvas_traits::webgl::{ - webgl_channel, AlphaTreatment, DOMToTextureCommand, GLContextAttributes, GLLimits, GlType, - Parameter, TexDataType, TexFormat, TexParameter, WebGLChan, WebGLCommand, + webgl_channel, AlphaTreatment, DOMToTextureCommand, GLContextAttributes, GLFormats, GLLimits, + GlType, Parameter, TexDataType, TexFormat, TexParameter, WebGLChan, WebGLCommand, WebGLCommandBacktrace, WebGLContextId, WebGLContextShareMode, WebGLError, WebGLFramebufferBindingRequest, WebGLMsg, WebGLMsgSender, WebGLProgramId, WebGLResult, WebGLSLVersion, WebGLSendResult, WebGLSender, WebGLVersion, WebVRCommand, YAxisTreatment, @@ -170,6 +170,7 @@ pub struct WebGLRenderingContext { current_vao: MutNullableDom<WebGLVertexArrayObjectOES>, textures: Textures, api_type: GlType, + framebuffer_format: GLFormats, } impl WebGLRenderingContext { @@ -229,6 +230,7 @@ impl WebGLRenderingContext { current_vao: Default::default(), textures: Textures::new(max_combined_texture_image_units), api_type: ctx_data.api_type, + framebuffer_format: ctx_data.framebuffer_format, } }) } @@ -1109,6 +1111,10 @@ impl WebGLRenderingContext { pub fn extension_manager(&self) -> &WebGLExtensions { &self.extension_manager } + + pub fn formats(&self) -> &GLFormats { + &self.framebuffer_format + } } #[cfg(not(feature = "webgl_backtrace"))] @@ -1241,9 +1247,17 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { // GL_OES_read_format support (assuming an underlying GLES // driver. Desktop is happy to format convert for us). constants::IMPLEMENTATION_COLOR_READ_FORMAT => { + if self.validate_framebuffer().is_err() { + self.webgl_error(InvalidOperation); + return NullValue(); + } return Int32Value(constants::RGBA as i32); }, constants::IMPLEMENTATION_COLOR_READ_TYPE => { + if self.validate_framebuffer().is_err() { + self.webgl_error(InvalidOperation); + return NullValue(); + } return Int32Value(constants::UNSIGNED_BYTE as i32); }, constants::COMPRESSED_TEXTURE_FORMATS => unsafe { @@ -1920,6 +1934,47 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { Err(_) => return, }; + let framebuffer_format = match self.bound_framebuffer.get() { + Some(fb) => match fb.attachment(constants::COLOR_ATTACHMENT0) { + Some(WebGLFramebufferAttachmentRoot::Renderbuffer(rb)) => { + TexFormat::from_gl_constant(rb.internal_format()) + }, + Some(WebGLFramebufferAttachmentRoot::Texture(texture)) => { + texture.image_info_for_target(&target, 0).internal_format() + }, + None => None, + }, + None => { + let attrs = self.GetContextAttributes().unwrap(); + Some(if attrs.alpha { + TexFormat::RGBA + } else { + TexFormat::RGB + }) + }, + }; + + let framebuffer_format = match framebuffer_format { + Some(f) => f, + None => { + self.webgl_error(InvalidOperation); + return; + }, + }; + + match (framebuffer_format, internal_format) { + (a, b) if a == b => (), + (TexFormat::RGBA, TexFormat::RGB) => (), + (TexFormat::RGBA, TexFormat::Alpha) => (), + (TexFormat::RGBA, TexFormat::Luminance) => (), + (TexFormat::RGBA, TexFormat::LuminanceAlpha) => (), + (TexFormat::RGB, TexFormat::Luminance) => (), + _ => { + self.webgl_error(InvalidOperation); + return; + }, + } + // NB: TexImage2D depth is always equal to 1 handle_potential_webgl_error!( self, @@ -2819,6 +2874,8 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { pixel_type: u32, mut pixels: CustomAutoRooterGuard<Option<ArrayBufferView>>, ) { + handle_potential_webgl_error!(self, self.validate_framebuffer(), return); + let pixels = handle_potential_webgl_error!(self, pixels.as_mut().ok_or(InvalidValue), return); @@ -2834,7 +2891,6 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { return self.webgl_error(InvalidOperation); } - handle_potential_webgl_error!(self, self.validate_framebuffer(), return); let (fb_width, fb_height) = handle_potential_webgl_error!( self, self.get_current_framebuffer_size().ok_or(InvalidOperation), diff --git a/components/script/dom/webgltexture.rs b/components/script/dom/webgltexture.rs index a7e548dcdef..e4a18b519a3 100644 --- a/components/script/dom/webgltexture.rs +++ b/components/script/dom/webgltexture.rs @@ -10,8 +10,9 @@ use crate::dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGL use crate::dom::bindings::codegen::Bindings::WebGLTextureBinding; use crate::dom::bindings::inheritance::Castable; use crate::dom::bindings::reflector::{reflect_dom_object, DomObject}; -use crate::dom::bindings::root::DomRoot; +use crate::dom::bindings::root::{DomRoot, MutNullableDom}; use crate::dom::webgl_validations::types::TexImageTarget; +use crate::dom::webglframebuffer::WebGLFramebuffer; use crate::dom::webglobject::WebGLObject; use crate::dom::webglrenderingcontext::WebGLRenderingContext; use canvas_traits::webgl::{webgl_channel, TexDataType, TexFormat, WebGLResult, WebGLTextureId}; @@ -48,6 +49,8 @@ pub struct WebGLTexture { mag_filter: Cell<u32>, /// True if this texture is used for the DOMToTexture feature. attached_to_dom: Cell<bool>, + /// Framebuffer that this texture is attached to. + attached_framebuffer: MutNullableDom<WebGLFramebuffer>, } impl WebGLTexture { @@ -63,6 +66,7 @@ impl WebGLTexture { mag_filter: Cell::new(constants::LINEAR), image_info_array: DomRefCell::new([ImageInfo::new(); MAX_LEVEL_COUNT * MAX_FACE_COUNT]), attached_to_dom: Cell::new(false), + attached_framebuffer: Default::default(), } } @@ -138,6 +142,11 @@ impl WebGLTexture { let face_index = self.face_index_for_target(&target); self.set_image_infos_at_level_and_face(level, face_index, image_info); + + if let Some(fb) = self.attached_framebuffer.get() { + fb.update_status(); + } + Ok(()) } @@ -405,6 +414,14 @@ impl WebGLTexture { pub fn set_attached_to_dom(&self) { self.attached_to_dom.set(true); } + + pub fn attach_to_framebuffer(&self, fb: &WebGLFramebuffer) { + self.attached_framebuffer.set(Some(fb)); + } + + pub fn detach_from_framebuffer(&self) { + self.attached_framebuffer.set(None); + } } impl Drop for WebGLTexture { diff --git a/components/script/dom/xrwebgllayer.rs b/components/script/dom/xrwebgllayer.rs index a1e912252e9..dabff8fc947 100644 --- a/components/script/dom/xrwebgllayer.rs +++ b/components/script/dom/xrwebgllayer.rs @@ -110,16 +110,18 @@ impl XRWebGLLayer { let mut pixels = CustomAutoRooter::new(None); let mut clear_bits = constants::COLOR_BUFFER_BIT; + let formats = context.formats(); + context.BindTexture(constants::TEXTURE_2D, Some(&texture)); let sc = context.TexImage2D( constants::TEXTURE_2D, 0, - constants::RGBA, + formats.texture_format, resolution.width, resolution.height, 0, - constants::RGBA, - constants::UNSIGNED_BYTE, + formats.texture_format, + formats.texture_type, pixels.root(*cx), ); |