From 08938499a0bfbc0b2c52fd1f7d29c57fceab6c76 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Sun, 30 Oct 2016 17:19:04 -0700 Subject: [PATCH 1/9] webgl: Add an interface for getting the size of renderbuffers. We need this for framebuffer status checking. --- components/script/dom/webglrenderbuffer.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/components/script/dom/webglrenderbuffer.rs b/components/script/dom/webglrenderbuffer.rs index 9e3c516cfbd..186b2aedf5a 100644 --- a/components/script/dom/webglrenderbuffer.rs +++ b/components/script/dom/webglrenderbuffer.rs @@ -20,6 +20,7 @@ pub struct WebGLRenderbuffer { id: WebGLRenderbufferId, ever_bound: Cell, is_deleted: Cell, + size: Cell>, internal_format: Cell>, #[ignore_heap_size_of = "Defined in ipc-channel"] renderer: IpcSender, @@ -36,6 +37,7 @@ impl WebGLRenderbuffer { is_deleted: Cell::new(false), renderer: renderer, internal_format: Cell::new(None), + size: Cell::new(None), } } @@ -64,6 +66,10 @@ impl WebGLRenderbuffer { self.id } + pub fn size(&self) -> Option<(i32, i32)> { + self.size.get() + } + pub fn bind(&self, target: u32) { self.ever_bound.set(true); let msg = CanvasMsg::WebGL(WebGLCommand::BindRenderbuffer(target, Some(self.id))); @@ -106,6 +112,8 @@ impl WebGLRenderbuffer { internal_format, width, height)); self.renderer.send(msg).unwrap(); + self.size.set(Some((width, height))); + Ok(()) } } From 59634cf78e002eaae971524c21ef0f3462f11dac Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Sun, 30 Oct 2016 18:41:04 -0700 Subject: [PATCH 2/9] webgl: Track the level with texture attachments. We need this to be able to get the size of the attached texture for completeness validation. Signed-off-by: Eric Anholt --- components/script/dom/webglframebuffer.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/components/script/dom/webglframebuffer.rs b/components/script/dom/webglframebuffer.rs index 8e22f17d079..029c794616c 100644 --- a/components/script/dom/webglframebuffer.rs +++ b/components/script/dom/webglframebuffer.rs @@ -21,7 +21,7 @@ use webrender_traits::{WebGLCommand, WebGLFramebufferBindingRequest, WebGLFrameb #[derive(JSTraceable, Clone, HeapSizeOf)] enum WebGLFramebufferAttachment { Renderbuffer(JS), - Texture(JS), + Texture { texture: JS, level: i32 }, } impl HeapGCValue for WebGLFramebufferAttachment {} @@ -190,7 +190,10 @@ impl WebGLFramebuffer { // Note, from the GLES 2.0.25 spec, page 113: // "If texture is zero, then textarget and level are ignored." Some(texture) => { - *binding.borrow_mut() = Some(WebGLFramebufferAttachment::Texture(JS::from_ref(texture))); + *binding.borrow_mut() = Some(WebGLFramebufferAttachment::Texture { + texture: JS::from_ref(texture), + level: level } + ); // From the GLES 2.0.25 spec, page 113: // @@ -282,7 +285,7 @@ impl WebGLFramebuffer { for attachment in &attachments { let matched = { match *attachment.borrow() { - Some(WebGLFramebufferAttachment::Texture(ref att_texture)) + Some(WebGLFramebufferAttachment::Texture { texture: ref att_texture, .. }) if texture.id() == att_texture.id() => true, _ => false, } From bf5a3db745151f79aaa6cd45d4a1ebd4648bcb62 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Sat, 5 Nov 2016 10:30:40 -0700 Subject: [PATCH 3/9] webgl: Don't update texture attachment state if we throw an error. If we're going to return from this function without updating the underlying GL state because of a WebGLError, we shouldn't have updated our shadow of the GL state. --- components/script/dom/webglframebuffer.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/components/script/dom/webglframebuffer.rs b/components/script/dom/webglframebuffer.rs index 029c794616c..44f9586adb1 100644 --- a/components/script/dom/webglframebuffer.rs +++ b/components/script/dom/webglframebuffer.rs @@ -190,11 +190,6 @@ impl WebGLFramebuffer { // Note, from the GLES 2.0.25 spec, page 113: // "If texture is zero, then textarget and level are ignored." Some(texture) => { - *binding.borrow_mut() = Some(WebGLFramebufferAttachment::Texture { - texture: JS::from_ref(texture), - level: level } - ); - // From the GLES 2.0.25 spec, page 113: // // "level specifies the mipmap level of the texture image @@ -234,6 +229,11 @@ impl WebGLFramebuffer { _ => return Err(WebGLError::InvalidOperation), } + *binding.borrow_mut() = Some(WebGLFramebufferAttachment::Texture { + texture: JS::from_ref(texture), + level: level } + ); + Some(texture.id()) } From 8e681dddc18c7aaaa7df5f7974274a62430c99f5 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 1 Nov 2016 21:28:25 -0700 Subject: [PATCH 4/9] webgl: Don't forget to update FBO status after detaching a texture. We had this in the renderbuffer detach process, but missed it in this one. --- components/script/dom/webglframebuffer.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/components/script/dom/webglframebuffer.rs b/components/script/dom/webglframebuffer.rs index 44f9586adb1..2571586ab11 100644 --- a/components/script/dom/webglframebuffer.rs +++ b/components/script/dom/webglframebuffer.rs @@ -293,6 +293,7 @@ impl WebGLFramebuffer { if matched { *attachment.borrow_mut() = None; + self.update_status(); } } } From d77373654a4d168092fb51d1810236d4bf0b3b52 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 1 Nov 2016 21:45:29 -0700 Subject: [PATCH 5/9] webgl: Update FBO status when textures or RBs are reallocated. FBO status is supposed to depend on the size of the attachments all matching, so we need to re-check when it changes. We don't ensure matching yet, but this will prevent regressions when we do. --- components/script/dom/webglframebuffer.rs | 40 ++++++++++++++++--- .../script/dom/webglrenderingcontext.rs | 13 +++++- 2 files changed, 45 insertions(+), 8 deletions(-) diff --git a/components/script/dom/webglframebuffer.rs b/components/script/dom/webglframebuffer.rs index 2571586ab11..e271f1c7034 100644 --- a/components/script/dom/webglframebuffer.rs +++ b/components/script/dom/webglframebuffer.rs @@ -254,7 +254,9 @@ impl WebGLFramebuffer { Ok(()) } - pub fn detach_renderbuffer(&self, rb: &WebGLRenderbuffer) { + fn with_matching_renderbuffers(&self, rb: &WebGLRenderbuffer, mut closure: F) + where F: FnMut(&DOMRefCell>) + { let attachments = [&self.color, &self.depth, &self.stencil, @@ -270,13 +272,14 @@ impl WebGLFramebuffer { }; if matched { - *attachment.borrow_mut() = None; - self.update_status(); + closure(attachment); } } } - pub fn detach_texture(&self, texture: &WebGLTexture) { + fn with_matching_textures(&self, texture: &WebGLTexture, mut closure: F) + where F: FnMut(&DOMRefCell>) + { let attachments = [&self.color, &self.depth, &self.stencil, @@ -292,12 +295,37 @@ impl WebGLFramebuffer { }; if matched { - *attachment.borrow_mut() = None; - self.update_status(); + closure(attachment); } } } + pub fn detach_renderbuffer(&self, rb: &WebGLRenderbuffer) { + self.with_matching_renderbuffers(rb, |att| { + *att.borrow_mut() = None; + self.update_status(); + }); + } + + pub fn detach_texture(&self, texture: &WebGLTexture) { + self.with_matching_textures(texture, |att| { + *att.borrow_mut() = None; + self.update_status(); + }); + } + + pub fn invalidate_renderbuffer(&self, rb: &WebGLRenderbuffer) { + self.with_matching_renderbuffers(rb, |_att| { + self.update_status(); + }); + } + + pub fn invalidate_texture(&self, texture: &WebGLTexture) { + self.with_matching_textures(texture, |_att| { + self.update_status(); + }); + } + pub fn target(&self) -> Option { self.target.get() } diff --git a/components/script/dom/webglrenderingcontext.rs b/components/script/dom/webglrenderingcontext.rs index b67f524825f..24bbb1a9dbb 100644 --- a/components/script/dom/webglrenderingcontext.rs +++ b/components/script/dom/webglrenderingcontext.rs @@ -465,7 +465,11 @@ impl WebGLRenderingContext { self.ipc_renderer .send(CanvasMsg::WebGL(msg)) - .unwrap() + .unwrap(); + + if let Some(fb) = self.bound_framebuffer.get() { + fb.invalidate_texture(&*texture); + } } fn tex_sub_image_2d(&self, @@ -2621,7 +2625,12 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { } match self.bound_renderbuffer.get() { - Some(rb) => handle_potential_webgl_error!(self, rb.storage(internal_format, width, height)), + Some(rb) => { + handle_potential_webgl_error!(self, rb.storage(internal_format, width, height)); + if let Some(fb) = self.bound_framebuffer.get() { + fb.invalidate_renderbuffer(&*rb); + } + } None => self.webgl_error(InvalidOperation), }; From 3277c5281cf7d4345d8c0eb11a8f451a5796eb3e Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Sun, 30 Oct 2016 19:02:35 -0700 Subject: [PATCH 6/9] webgl: Validate that framebuffer attachment sizes match. This is required by the WebGL spec, and we need to figure out the FB size like this for validating ReadPixels. --- components/script/dom/webglframebuffer.rs | 39 ++++++++++++++++++++--- components/script/dom/webgltexture.rs | 2 +- 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/components/script/dom/webglframebuffer.rs b/components/script/dom/webglframebuffer.rs index e271f1c7034..8586b09d5bf 100644 --- a/components/script/dom/webglframebuffer.rs +++ b/components/script/dom/webglframebuffer.rs @@ -111,10 +111,15 @@ impl WebGLFramebuffer { } fn update_status(&self) { - let has_c = self.color.borrow().is_some(); - let has_z = self.depth.borrow().is_some(); - let has_s = self.stencil.borrow().is_some(); - let has_zs = self.depthstencil.borrow().is_some(); + let c = self.color.borrow(); + let z = self.depth.borrow(); + let s = self.stencil.borrow(); + let zs = self.depthstencil.borrow(); + let has_c = c.is_some(); + let has_z = z.is_some(); + let has_s = s.is_some(); + let has_zs = zs.is_some(); + let attachments = [&*c, &*z, &*s, &*zs]; // From the WebGL spec, 6.6 ("Framebuffer Object Attachments"): // @@ -135,6 +140,32 @@ impl WebGLFramebuffer { return; } + let mut fb_size = None; + for attachment in &attachments { + // Get the size of this attachment. + let size = match **attachment { + Some(WebGLFramebufferAttachment::Renderbuffer(ref att_rb)) => { + att_rb.size() + } + Some(WebGLFramebufferAttachment::Texture { texture: ref att_tex, level } ) => { + let info = att_tex.image_info_at_face(0, level as u32); + Some((info.width() as i32, info.height() as i32)) + } + None => None, + }; + + // Make sure that, if we've found any other attachment, + // that the size matches. + if size.is_some() { + if fb_size.is_some() && size != fb_size { + self.status.set(constants::FRAMEBUFFER_INCOMPLETE_DIMENSIONS); + return; + } else { + fb_size = size; + } + } + } + if has_c || has_z || has_zs || has_s { self.status.set(constants::FRAMEBUFFER_COMPLETE); } else { diff --git a/components/script/dom/webgltexture.rs b/components/script/dom/webgltexture.rs index 31fdaafcffd..3ba8eefca85 100644 --- a/components/script/dom/webgltexture.rs +++ b/components/script/dom/webgltexture.rs @@ -332,7 +332,7 @@ impl WebGLTexture { self.image_info_at_face(face_index, level) } - fn image_info_at_face(&self, face: u8, level: u32) -> ImageInfo { + pub fn image_info_at_face(&self, face: u8, level: u32) -> ImageInfo { let pos = (level * self.face_count.get() as u32) + face as u32; self.image_info_array.borrow()[pos as usize] } From 9a10666941ea4bbec03205609d1b578a749251c6 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Sat, 13 Aug 2016 23:46:25 -0700 Subject: [PATCH 7/9] webgl: Throw an error on readPixels(width < 0 || height < 0) Otherwise gleam will try to allocate a negative size area for the result, and we'll panic with oom. --- components/script/dom/webglrenderingcontext.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/components/script/dom/webglrenderingcontext.rs b/components/script/dom/webglrenderingcontext.rs index 24bbb1a9dbb..781b95c60bf 100644 --- a/components/script/dom/webglrenderingcontext.rs +++ b/components/script/dom/webglrenderingcontext.rs @@ -1777,6 +1777,10 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { _ => return Ok(self.webgl_error(InvalidOperation)), } + if width < 0 || height < 0 { + return Ok(self.webgl_error(InvalidValue)); + } + let (sender, receiver) = ipc::channel().unwrap(); self.ipc_renderer .send(CanvasMsg::WebGL(WebGLCommand::ReadPixels(x, y, width, height, format, pixel_type, sender))) From 5e5eb18b0b48f008768487dd9dc0fd1c8b1adf18 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Sun, 14 Aug 2016 00:14:54 -0700 Subject: [PATCH 8/9] webgl: Fix out-of-bounds readpixels handling. This fixes the crash in read-pixels-pack-alignment (which was trying to read out of bounds). Fixes #13901 --- components/script/dom/webglframebuffer.rs | 7 ++ .../script/dom/webglrenderingcontext.rs | 111 +++++++++++++++++- .../misc/object-deletion-behaviour.html.ini | 3 - .../more/functions/readPixelsBadArgs.html.ini | 8 -- .../read-pixels-pack-alignment.html.ini | 14 ++- 5 files changed, 122 insertions(+), 21 deletions(-) delete mode 100644 tests/wpt/metadata/webgl/conformance-1.0.3/conformance/more/functions/readPixelsBadArgs.html.ini diff --git a/components/script/dom/webglframebuffer.rs b/components/script/dom/webglframebuffer.rs index 8586b09d5bf..ef40fecac19 100644 --- a/components/script/dom/webglframebuffer.rs +++ b/components/script/dom/webglframebuffer.rs @@ -33,6 +33,7 @@ pub struct WebGLFramebuffer { /// target can only be gl::FRAMEBUFFER at the moment target: Cell>, is_deleted: Cell, + size: Cell>, status: Cell, #[ignore_heap_size_of = "Defined in ipc-channel"] renderer: IpcSender, @@ -55,6 +56,7 @@ impl WebGLFramebuffer { target: Cell::new(None), is_deleted: Cell::new(false), renderer: renderer, + size: Cell::new(None), status: Cell::new(constants::FRAMEBUFFER_UNSUPPORTED), color: DOMRefCell::new(None), depth: DOMRefCell::new(None), @@ -110,6 +112,10 @@ impl WebGLFramebuffer { self.is_deleted.get() } + pub fn size(&self) -> Option<(i32, i32)> { + self.size.get() + } + fn update_status(&self) { let c = self.color.borrow(); let z = self.depth.borrow(); @@ -165,6 +171,7 @@ impl WebGLFramebuffer { } } } + self.size.set(fb_size); if has_c || has_z || has_zs || has_s { self.status.set(constants::FRAMEBUFFER_COMPLETE); diff --git a/components/script/dom/webglrenderingcontext.rs b/components/script/dom/webglrenderingcontext.rs index 781b95c60bf..c5af5f4c39d 100644 --- a/components/script/dom/webglrenderingcontext.rs +++ b/components/script/dom/webglrenderingcontext.rs @@ -283,6 +283,16 @@ impl WebGLRenderingContext { .unwrap(); } + fn get_current_framebuffer_size(&self) -> Option<(i32, i32)> { + match self.bound_framebuffer.get() { + Some(fb) => return fb.size(), + + // The window system framebuffer is bound + None => return Some((self.DrawingBufferWidth(), + self.DrawingBufferHeight())), + } + } + fn validate_stencil_actions(&self, action: u32) -> bool { match action { 0 | constants::KEEP | constants::REPLACE | constants::INCR | constants::DECR | @@ -649,6 +659,26 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { return object_binding_to_js_or_null!(cx, &self.bound_texture_2d), constants::TEXTURE_BINDING_CUBE_MAP => return object_binding_to_js_or_null!(cx, &self.bound_texture_cube_map), + + // In readPixels we currently support RGBA/UBYTE only. If + // we wanted to support other formats, we could ask the + // driver, but we would need to check for + // 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_complete() { + return NullValue(); + } else { + return Int32Value(constants::RGBA as i32); + } + } + constants::IMPLEMENTATION_COLOR_READ_TYPE => { + if !self.validate_framebuffer_complete() { + return NullValue(); + } else { + return Int32Value(constants::UNSIGNED_BYTE as i32); + } + } _ => {} } @@ -1777,10 +1807,80 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { _ => return Ok(self.webgl_error(InvalidOperation)), } + // From the WebGL specification, 5.14.12 Reading back pixels + // + // "Only two combinations of format and type are + // accepted. The first is format RGBA and type + // UNSIGNED_BYTE. The second is an implementation-chosen + // format. The values of format and type for this format + // may be determined by calling getParameter with the + // symbolic constants IMPLEMENTATION_COLOR_READ_FORMAT + // and IMPLEMENTATION_COLOR_READ_TYPE, respectively. The + // implementation-chosen format may vary depending on the + // format of the currently bound rendering + // surface. Unsupported combinations of format and type + // will generate an INVALID_OPERATION error." + // + // To avoid having to support general format packing math, we + // always report RGBA/UNSIGNED_BYTE as our only supported + // format. + if format != constants::RGBA || pixel_type != constants::UNSIGNED_BYTE { + return Ok(self.webgl_error(InvalidOperation)); + } + let cpp = 4; + + // "If pixels is non-null, but is not large enough to + // retrieve all of the pixels in the specified rectangle + // taking into account pixel store modes, an + // INVALID_OPERATION error is generated." + let stride = match width.checked_mul(cpp) { + Some(stride) => stride, + _ => return Ok(self.webgl_error(InvalidOperation)), + }; + + match height.checked_mul(stride) { + Some(size) if size <= data.len() as i32 => {} + _ => return Ok(self.webgl_error(InvalidOperation)), + } + + // "For any pixel lying outside the frame buffer, the + // corresponding destination buffer range remains + // untouched; see Reading Pixels Outside the + // Framebuffer." + let mut x = x; + let mut y = y; + let mut width = width; + let mut height = height; + let mut dst_offset = 0; + + if x < 0 { + dst_offset += cpp * -x; + width += x; + x = 0; + } + + if y < 0 { + dst_offset += stride * -y; + height += y; + y = 0; + } + if width < 0 || height < 0 { return Ok(self.webgl_error(InvalidValue)); } + match self.get_current_framebuffer_size() { + Some((fb_width, fb_height)) => { + if x + width > fb_width { + width = fb_width - x; + } + if y + height > fb_height { + height = fb_height - y; + } + } + _ => return Ok(self.webgl_error(InvalidOperation)), + }; + let (sender, receiver) = ipc::channel().unwrap(); self.ipc_renderer .send(CanvasMsg::WebGL(WebGLCommand::ReadPixels(x, y, width, height, format, pixel_type, sender))) @@ -1788,12 +1888,11 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { let result = receiver.recv().unwrap(); - if result.len() > data.len() { - return Ok(self.webgl_error(InvalidOperation)); - } - - for i in 0..result.len() { - data[i] = result[i] + for i in 0..height { + for j in 0..(width * cpp) { + data[(dst_offset + i * stride + j) as usize] = + result[(i * width * cpp + j) as usize]; + } } Ok(()) diff --git a/tests/wpt/metadata/webgl/conformance-1.0.3/conformance/misc/object-deletion-behaviour.html.ini b/tests/wpt/metadata/webgl/conformance-1.0.3/conformance/misc/object-deletion-behaviour.html.ini index 8e2be3e1863..8cb6c72e03d 100644 --- a/tests/wpt/metadata/webgl/conformance-1.0.3/conformance/misc/object-deletion-behaviour.html.ini +++ b/tests/wpt/metadata/webgl/conformance-1.0.3/conformance/misc/object-deletion-behaviour.html.ini @@ -174,9 +174,6 @@ [WebGL test #171: gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE) threw exception TypeError: gl.getFramebufferAttachmentParameter is not a function] expected: FAIL - [WebGL test #187: gl.checkFramebufferStatus(gl.FRAMEBUFFER) should not be 36053.] - expected: FAIL - [WebGL test #196: gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) should be [object WebGLTexture\]. Threw exception TypeError: gl.getFramebufferAttachmentParameter is not a function] expected: FAIL diff --git a/tests/wpt/metadata/webgl/conformance-1.0.3/conformance/more/functions/readPixelsBadArgs.html.ini b/tests/wpt/metadata/webgl/conformance-1.0.3/conformance/more/functions/readPixelsBadArgs.html.ini deleted file mode 100644 index e85893ee2a5..00000000000 --- a/tests/wpt/metadata/webgl/conformance-1.0.3/conformance/more/functions/readPixelsBadArgs.html.ini +++ /dev/null @@ -1,8 +0,0 @@ -[readPixelsBadArgs.html] - type: testharness - expected: - if os == "linux": CRASH - if os == "mac": TIMEOUT - [WebGL test #0: testReadPixels] - expected: FAIL - diff --git a/tests/wpt/metadata/webgl/conformance-1.0.3/conformance/reading/read-pixels-pack-alignment.html.ini b/tests/wpt/metadata/webgl/conformance-1.0.3/conformance/reading/read-pixels-pack-alignment.html.ini index 3704c6c4f1b..d5b3c59a27d 100644 --- a/tests/wpt/metadata/webgl/conformance-1.0.3/conformance/reading/read-pixels-pack-alignment.html.ini +++ b/tests/wpt/metadata/webgl/conformance-1.0.3/conformance/reading/read-pixels-pack-alignment.html.ini @@ -1,8 +1,14 @@ [read-pixels-pack-alignment.html] type: testharness - expected: - if os == "linux": CRASH - if os == "mac": TIMEOUT - [WebGL test #3: successfullyParsed should be true (of type boolean). Was undefined (of type undefined).] + [WebGL test #17: pixel should be 255,102,0,255. Was 0,0,0,0.] + expected: FAIL + + [WebGL test #33: pixel should be 255,102,0,255. Was 0,0,0,0.] + expected: FAIL + + [WebGL test #53: pixel should be 255,102,0,255. Was 0,0,0,0.] + expected: FAIL + + [WebGL test #61: pixel should be 255,102,0,255. Was 0,0,0,0.] expected: FAIL From eaec5de1849beb6f7b3e464851044c9429a23537 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 1 Nov 2016 21:27:21 -0700 Subject: [PATCH 9/9] webgl: Only update FBO status once in framebufferTexture2D(). We update it below after we send the actual FramebufferTexture2D command to the GL. --- components/script/dom/webglframebuffer.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/components/script/dom/webglframebuffer.rs b/components/script/dom/webglframebuffer.rs index ef40fecac19..25026dac22d 100644 --- a/components/script/dom/webglframebuffer.rs +++ b/components/script/dom/webglframebuffer.rs @@ -277,7 +277,6 @@ impl WebGLFramebuffer { _ => { *binding.borrow_mut() = None; - self.update_status(); None } };