diff --git a/components/script/dom/webglrenderingcontext.rs b/components/script/dom/webglrenderingcontext.rs index c038c0abf8f..e467aba951c 100644 --- a/components/script/dom/webglrenderingcontext.rs +++ b/components/script/dom/webglrenderingcontext.rs @@ -135,6 +135,7 @@ pub struct WebGLRenderingContext { #[ignore_heap_size_of = "Defined in webrender_traits"] last_error: Cell>, texture_unpacking_settings: Cell, + texture_unpacking_alignment: Cell, bound_framebuffer: MutNullableJS, bound_renderbuffer: MutNullableJS, bound_texture_2d: MutNullableJS, @@ -170,6 +171,7 @@ impl WebGLRenderingContext { canvas: JS::from_ref(canvas), last_error: Cell::new(None), texture_unpacking_settings: Cell::new(CONVERT_COLORSPACE), + texture_unpacking_alignment: Cell::new(4), bound_framebuffer: MutNullableJS::new(None), bound_texture_2d: MutNullableJS::new(None), bound_texture_cube_map: MutNullableJS::new(None), @@ -496,6 +498,7 @@ impl WebGLRenderingContext { height: u32, format: TexFormat, data_type: TexDataType, + unpacking_alignment: u32, data: *mut JSObject) -> Result { let element_size = data_type.element_size(); @@ -527,8 +530,17 @@ impl WebGLRenderingContext { } // NOTE: width and height are positive or zero due to validate() - let expected_byte_length = width * height * element_size * components / components_per_element; - return Ok(expected_byte_length); + if height == 0 { + return Ok(0); + } else { + // We need to be careful here to not count unpack + // alignment at the end of the image, otherwise (for + // example) passing a single byte for uploading a 1x1 + // GL_ALPHA/GL_UNSIGNED_BYTE texture would throw an error. + let cpp = element_size * components / components_per_element; + let stride = (width * cpp + unpacking_alignment - 1) & !(unpacking_alignment - 1); + return Ok(stride * (height - 1) + width * cpp); + } } /// Flips the pixels in the Vec on the Y axis if @@ -538,7 +550,8 @@ impl WebGLRenderingContext { internal_format: TexFormat, data_type: TexDataType, width: usize, - height: usize) -> Vec { + height: usize, + unpacking_alignment: usize) -> Vec { if !self.texture_unpacking_settings.get().contains(FLIP_Y_AXIS) { return pixels; } @@ -546,16 +559,16 @@ impl WebGLRenderingContext { let cpp = (data_type.element_size() * internal_format.components() / data_type.components_per_element()) as usize; - let stride = width * cpp; - - // This should have already been validated. - assert!(stride * height <= pixels.len()); + let stride = (width * cpp + unpacking_alignment - 1) & !(unpacking_alignment - 1); let mut flipped = Vec::::with_capacity(pixels.len()); for y in 0..height { let flipped_y = height - 1 - y; - flipped.extend_from_slice(&pixels[(flipped_y * stride)..((flipped_y + 1) * stride)]); + let start = flipped_y * stride; + + flipped.extend_from_slice(&pixels[start..(start + width * cpp)]); + flipped.extend(vec![0u8; stride - width * cpp]); } flipped @@ -636,12 +649,13 @@ impl WebGLRenderingContext { width: u32, height: u32, _border: u32, + unpacking_alignment: u32, pixels: Vec) { // NB: pixels should NOT be premultipied // FINISHME: Consider doing premultiply and flip in a single mutable Vec. let pixels = self.premultiply_pixels(internal_format, data_type, pixels); let pixels = self.flip_teximage_y(pixels, internal_format, data_type, - width as usize, height as usize); + width as usize, height as usize, unpacking_alignment as usize); // TexImage2D depth is always equal to 1 handle_potential_webgl_error!(self, texture.initialize(target, @@ -651,6 +665,15 @@ impl WebGLRenderingContext { level, Some(data_type))); + // Set the unpack alignment. For textures coming from arrays, + // this will be the current value of the context's + // GL_UNPACK_ALIGNMENT, while for textures from images or + // canvas (produced by rgba8_image_to_tex_image_data()), it + // will be 1. + self.ipc_renderer + .send(CanvasMsg::WebGL(WebGLCommand::PixelStorei(constants::UNPACK_ALIGNMENT, unpacking_alignment as i32))) + .unwrap(); + // TODO(emilio): convert colorspace if requested let msg = WebGLCommand::TexImage2D(target.as_gl_constant(), level as i32, internal_format.as_gl_constant() as i32, @@ -677,6 +700,7 @@ impl WebGLRenderingContext { height: u32, format: TexFormat, data_type: TexDataType, + unpacking_alignment: u32, pixels: Vec) { // NB: pixels should NOT be premultipied // We have already validated level let image_info = texture.image_info_for_target(&target, level); @@ -700,7 +724,16 @@ impl WebGLRenderingContext { let pixels = self.premultiply_pixels(format, data_type, pixels); let pixels = self.flip_teximage_y(pixels, format, data_type, - width as usize, height as usize); + width as usize, height as usize, unpacking_alignment as usize); + + // Set the unpack alignment. For textures coming from arrays, + // this will be the current value of the context's + // GL_UNPACK_ALIGNMENT, while for textures from images or + // canvas (produced by rgba8_image_to_tex_image_data()), it + // will be 1. + self.ipc_renderer + .send(CanvasMsg::WebGL(WebGLCommand::PixelStorei(constants::UNPACK_ALIGNMENT, unpacking_alignment as i32))) + .unwrap(); // TODO(emilio): convert colorspace if requested let msg = WebGLCommand::TexSubImage2D(target.as_gl_constant(), @@ -2017,13 +2050,11 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { 1 | 2 | 4 | 8 => (), _ => return self.webgl_error(InvalidValue), } + self.texture_unpacking_alignment.set(param_value as u32); + return; }, _ => return self.webgl_error(InvalidEnum), } - - self.ipc_renderer - .send(CanvasMsg::WebGL(WebGLCommand::PixelStorei(param_name, param_value))) - .unwrap() } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.3 @@ -2752,10 +2783,12 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { Err(_) => return Ok(()), // NB: The validator sets the correct error for us. }; + let unpacking_alignment = self.texture_unpacking_alignment.get(); + let expected_byte_length = match { self.validate_tex_image_2d_data(width, height, - format, data_type, - data_ptr) } { + format, data_type, + unpacking_alignment, data_ptr) } { Ok(byte_length) => byte_length, Err(()) => return Ok(()), }; @@ -2778,7 +2811,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { } self.tex_image_2d(texture, target, data_type, format, - level, width, height, border, buff); + level, width, height, border, unpacking_alignment, buff); Ok(()) } @@ -2819,7 +2852,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { let pixels = self.rgba8_image_to_tex_image_data(format, data_type, pixels); self.tex_image_2d(texture, target, data_type, format, - level, width, height, border, pixels); + level, width, height, border, 1, pixels); Ok(()) } @@ -2860,10 +2893,12 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { Err(_) => return Ok(()), // NB: The validator sets the correct error for us. }; + let unpacking_alignment = self.texture_unpacking_alignment.get(); + let expected_byte_length = match { self.validate_tex_image_2d_data(width, height, - format, data_type, - data_ptr) } { + format, data_type, + unpacking_alignment, data_ptr) } { Ok(byte_length) => byte_length, Err(()) => return Ok(()), }; @@ -2886,7 +2921,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { } self.tex_sub_image_2d(texture, target, level, xoffset, yoffset, - width, height, format, data_type, buff); + width, height, format, data_type, unpacking_alignment, buff); Ok(()) } @@ -2925,7 +2960,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { let pixels = self.rgba8_image_to_tex_image_data(format, data_type, pixels); self.tex_sub_image_2d(texture, target, level, xoffset, yoffset, - width, height, format, data_type, pixels); + width, height, format, data_type, 1, pixels); Ok(()) } diff --git a/tests/wpt/metadata/webgl/conformance-1.0.3/conformance/textures/tex-image-and-sub-image-2d-with-array-buffer-view.html.ini b/tests/wpt/metadata/webgl/conformance-1.0.3/conformance/textures/tex-image-and-sub-image-2d-with-array-buffer-view.html.ini deleted file mode 100644 index 1c76e0ed842..00000000000 --- a/tests/wpt/metadata/webgl/conformance-1.0.3/conformance/textures/tex-image-and-sub-image-2d-with-array-buffer-view.html.ini +++ /dev/null @@ -1,122 +0,0 @@ -[tex-image-and-sub-image-2d-with-array-buffer-view.html] - type: testharness - [WebGL test #288: at (6, 0) expected: 0,255,0,255 was 0,0,0,255] - expected: FAIL - - [WebGL test #289: at (0, 9) expected: 255,0,0,255 was 0,0,0,255] - expected: FAIL - - [WebGL test #313: at (0, 9) expected: 255,0,0,255 was 0,0,0,255] - expected: FAIL - - [WebGL test #336: at (6, 0) expected: 0,255,0,255 was 0,0,0,255] - expected: FAIL - - [WebGL test #337: at (0, 9) expected: 255,0,0,255 was 0,0,0,255] - expected: FAIL - - [WebGL test #361: at (0, 9) expected: 255,0,0,255 was 0,0,0,255] - expected: FAIL - - [WebGL test #576: at (6, 0) expected: 0,255,0,255 was 0,0,0,255] - expected: FAIL - - [WebGL test #577: at (0, 9) expected: 255,0,0,255 was 0,0,0,255] - expected: FAIL - - [WebGL test #601: at (0, 9) expected: 255,0,0,255 was 0,0,0,255] - expected: FAIL - - [WebGL test #624: at (6, 0) expected: 0,255,0,255 was 0,0,0,255] - expected: FAIL - - [WebGL test #625: at (0, 9) expected: 255,0,0,255 was 0,0,0,255] - expected: FAIL - - [WebGL test #649: at (0, 9) expected: 255,0,0,255 was 0,0,0,255] - expected: FAIL - - [WebGL test #672: at (6, 0) expected: 0,255,0,255 was 0,0,0,255] - expected: FAIL - - [WebGL test #673: at (13, 8) expected: 255,0,0,255 was 0,0,0,255] - expected: FAIL - - [WebGL test #697: at (13, 8) expected: 255,0,0,255 was 0,0,0,255] - expected: FAIL - - [WebGL test #720: at (6, 0) expected: 0,255,0,255 was 0,0,0,255] - expected: FAIL - - [WebGL test #721: at (13, 8) expected: 255,0,0,255 was 0,0,0,255] - expected: FAIL - - [WebGL test #745: at (13, 8) expected: 255,0,0,255 was 0,0,0,255] - expected: FAIL - - [WebGL test #960: at (6, 0) expected: 0,255,0,255 was 0,0,0,255] - expected: FAIL - - [WebGL test #961: at (0, 9) expected: 255,0,0,255 was 0,0,0,255] - expected: FAIL - - [WebGL test #985: at (0, 9) expected: 255,0,0,255 was 0,0,0,255] - expected: FAIL - - [WebGL test #1008: at (6, 0) expected: 0,255,0,255 was 0,0,0,255] - expected: FAIL - - [WebGL test #1009: at (0, 9) expected: 255,0,0,255 was 0,0,0,255] - expected: FAIL - - [WebGL test #1033: at (0, 9) expected: 255,0,0,255 was 0,0,0,255] - expected: FAIL - - [WebGL test #1056: at (6, 0) expected: 0,255,0,255 was 0,0,0,255] - expected: FAIL - - [WebGL test #1057: at (13, 8) expected: 255,0,0,255 was 0,0,0,255] - expected: FAIL - - [WebGL test #1081: at (13, 8) expected: 255,0,0,255 was 0,0,0,255] - expected: FAIL - - [WebGL test #1104: at (6, 0) expected: 0,255,0,255 was 0,0,0,255] - expected: FAIL - - [WebGL test #1105: at (13, 8) expected: 255,0,0,255 was 0,0,0,255] - expected: FAIL - - [WebGL test #1129: at (13, 8) expected: 255,0,0,255 was 0,0,0,255] - expected: FAIL - - [WebGL test #312: at (0, 5) expected: 0,0,0,255 was 255,0,0,255] - expected: FAIL - - [WebGL test #360: at (0, 5) expected: 0,0,0,255 was 255,0,0,255] - expected: FAIL - - [WebGL test #600: at (0, 5) expected: 0,0,0,255 was 255,0,0,255] - expected: FAIL - - [WebGL test #648: at (0, 5) expected: 0,0,0,255 was 255,0,0,255] - expected: FAIL - - [WebGL test #696: at (0, 3) expected: 0,0,0,255 was 255,0,0,255] - expected: FAIL - - [WebGL test #744: at (0, 3) expected: 0,0,0,255 was 255,0,0,255] - expected: FAIL - - [WebGL test #984: at (0, 5) expected: 0,0,0,255 was 255,0,0,255] - expected: FAIL - - [WebGL test #1032: at (0, 5) expected: 0,0,0,255 was 255,0,0,255] - expected: FAIL - - [WebGL test #1080: at (0, 3) expected: 0,0,0,255 was 255,0,0,255] - expected: FAIL - - [WebGL test #1128: at (0, 3) expected: 0,0,0,255 was 255,0,0,255] - expected: FAIL - diff --git a/tests/wpt/metadata/webgl/conformance-1.0.3/conformance/textures/tex-image-and-sub-image-2d-with-canvas-rgb565.html.ini b/tests/wpt/metadata/webgl/conformance-1.0.3/conformance/textures/tex-image-and-sub-image-2d-with-canvas-rgb565.html.ini deleted file mode 100644 index d15e7824add..00000000000 --- a/tests/wpt/metadata/webgl/conformance-1.0.3/conformance/textures/tex-image-and-sub-image-2d-with-canvas-rgb565.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[tex-image-and-sub-image-2d-with-canvas-rgb565.html] - type: testharness - [WebGL test #0: at (0, 16) expected: 255,0,0 was 123,227,0] - expected: FAIL - diff --git a/tests/wpt/metadata/webgl/conformance-1.0.3/conformance/textures/tex-image-and-sub-image-2d-with-canvas-rgba4444.html.ini b/tests/wpt/metadata/webgl/conformance-1.0.3/conformance/textures/tex-image-and-sub-image-2d-with-canvas-rgba4444.html.ini deleted file mode 100644 index 26ae69061d1..00000000000 --- a/tests/wpt/metadata/webgl/conformance-1.0.3/conformance/textures/tex-image-and-sub-image-2d-with-canvas-rgba4444.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[tex-image-and-sub-image-2d-with-canvas-rgba4444.html] - type: testharness - [WebGL test #0: at (0, 16) expected: 255,0,0 was 119,255,0] - expected: FAIL - diff --git a/tests/wpt/metadata/webgl/conformance-1.0.3/conformance/textures/tex-image-and-sub-image-2d-with-canvas-rgba5551.html.ini b/tests/wpt/metadata/webgl/conformance-1.0.3/conformance/textures/tex-image-and-sub-image-2d-with-canvas-rgba5551.html.ini deleted file mode 100644 index 33841bcd7fe..00000000000 --- a/tests/wpt/metadata/webgl/conformance-1.0.3/conformance/textures/tex-image-and-sub-image-2d-with-canvas-rgba5551.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[tex-image-and-sub-image-2d-with-canvas-rgba5551.html] - type: testharness - [WebGL test #0: at (0, 16) expected: 255,0,0 was 123,231,0] - expected: FAIL - diff --git a/tests/wpt/metadata/webgl/conformance-1.0.3/conformance/textures/texture-size-cube-maps.html.ini b/tests/wpt/metadata/webgl/conformance-1.0.3/conformance/textures/texture-size-cube-maps.html.ini index a30cc53d41c..75fa9423abe 100644 --- a/tests/wpt/metadata/webgl/conformance-1.0.3/conformance/textures/texture-size-cube-maps.html.ini +++ b/tests/wpt/metadata/webgl/conformance-1.0.3/conformance/textures/texture-size-cube-maps.html.ini @@ -36,39 +36,3 @@ [WebGL test #35: at (0, 1) expected: 255,255,0,255 was 0,255,0,255] expected: FAIL - [WebGL test #44: at (0, 1) expected: 255,0,0,255 was 255,0,255,255] - expected: FAIL - - [WebGL test #45: at (0, 0) expected: 255,0,0,255 was 0,255,255,255] - expected: FAIL - - [WebGL test #47: at (0, 0) expected: 0,255,0,255 was 255,0,255,255] - expected: FAIL - - [WebGL test #50: at (0, 1) expected: 0,255,0,255 was 0,255,255,255] - expected: FAIL - - [WebGL test #51: at (0, 0) expected: 255,0,255,255 was 0,0,255,255] - expected: FAIL - - [WebGL test #54: at (0, 1) expected: 0,255,255,255 was 0,0,255,255] - expected: FAIL - - [WebGL test #62: at (0, 1) expected: 0,255,0,255 was 255,0,0,255] - expected: FAIL - - [WebGL test #63: at (0, 0) expected: 0,255,0,255 was 255,0,255,255] - expected: FAIL - - [WebGL test #65: at (0, 0) expected: 0,0,255,255 was 255,0,0,255] - expected: FAIL - - [WebGL test #68: at (0, 1) expected: 0,0,255,255 was 255,0,255,255] - expected: FAIL - - [WebGL test #69: at (0, 0) expected: 255,0,0,255 was 255,255,0,255] - expected: FAIL - - [WebGL test #72: at (0, 1) expected: 255,0,255,255 was 255,255,0,255] - expected: FAIL -