diff options
-rw-r--r-- | Cargo.lock | 4 | ||||
-rw-r--r-- | components/canvas/Cargo.toml | 2 | ||||
-rw-r--r-- | components/canvas/webgl_thread.rs | 28 | ||||
-rw-r--r-- | components/canvas_traits/webgl.rs | 10 | ||||
-rw-r--r-- | components/script/dom/webgl2renderingcontext.rs | 86 | ||||
-rw-r--r-- | components/script/dom/webglrenderingcontext.rs | 103 | ||||
-rw-r--r-- | components/script/dom/webidls/WebGL2RenderingContext.webidl | 6 | ||||
-rw-r--r-- | tests/wpt/webgl/meta/conformance2/transform_feedback/simultaneous_binding.html.ini | 64 |
8 files changed, 254 insertions, 49 deletions
diff --git a/Cargo.lock b/Cargo.lock index 03e2674e91c..bafaad3cabb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5345,9 +5345,9 @@ dependencies = [ [[package]] name = "sparkle" -version = "0.1.24" +version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7cd7f292661a533c2a7e239af495ba63891b5723c3a6d48712b2e3823466174" +checksum = "7184285ed8ddbf106cda8fef17f584207fc64a03125e3694c324b19b708825fa" dependencies = [ "gl_generator 0.13.1", ] diff --git a/components/canvas/Cargo.toml b/components/canvas/Cargo.toml index 7285776ddec..f0374c3df90 100644 --- a/components/canvas/Cargo.toml +++ b/components/canvas/Cargo.toml @@ -35,7 +35,7 @@ pixels = { path = "../pixels" } raqote = { version = "0.8", features = ["text"] } servo_arc = { path = "../servo_arc" } servo_config = { path = "../config" } -sparkle = "0.1.24" +sparkle = "0.1.25" style = { path = "../style" } # NOTE: the sm-angle feature only enables ANGLE on Windows, not other platforms! surfman = { version = "0.2", features = ["sm-angle", "sm-angle-default"] } diff --git a/components/canvas/webgl_thread.rs b/components/canvas/webgl_thread.rs index 0d8bc69cb77..62f979e65e0 100644 --- a/components/canvas/webgl_thread.rs +++ b/components/canvas/webgl_thread.rs @@ -919,7 +919,7 @@ impl WebGLThread { 0, gl::RGBA, gl::UNSIGNED_BYTE, - None, + gl::TexImageSource::Pixels(None), ); self.dom_outputs.insert( pipeline_id, @@ -1595,7 +1595,31 @@ impl WebGLImpl { 0, format.as_gl_constant(), effective_data_type, - Some(&pixels), + gl::TexImageSource::Pixels(Some(&pixels)), + ); + }, + WebGLCommand::TexImage2DPBO { + target, + level, + internal_format, + size, + format, + effective_data_type, + unpacking_alignment, + offset, + } => { + gl.pixel_store_i(gl::UNPACK_ALIGNMENT, unpacking_alignment as i32); + + gl.tex_image_2d( + target, + level as i32, + internal_format.as_gl_constant() as i32, + size.width as i32, + size.height as i32, + 0, + format.as_gl_constant(), + effective_data_type, + gl::TexImageSource::BufferOffset(offset), ); }, WebGLCommand::TexSubImage2D { diff --git a/components/canvas_traits/webgl.rs b/components/canvas_traits/webgl.rs index c95fe603a35..2b4b9dda482 100644 --- a/components/canvas_traits/webgl.rs +++ b/components/canvas_traits/webgl.rs @@ -398,6 +398,16 @@ pub enum WebGLCommand { pixel_format: Option<PixelFormat>, data: TruncatedDebug<IpcSharedMemory>, }, + TexImage2DPBO { + target: u32, + level: u32, + internal_format: TexFormat, + size: Size2D<u32>, + format: TexFormat, + effective_data_type: u32, + unpacking_alignment: u32, + offset: i64, + }, TexSubImage2D { target: u32, level: u32, diff --git a/components/script/dom/webgl2renderingcontext.rs b/components/script/dom/webgl2renderingcontext.rs index 0ca44ab3d7c..4af734253af 100644 --- a/components/script/dom/webgl2renderingcontext.rs +++ b/components/script/dom/webgl2renderingcontext.rs @@ -29,7 +29,8 @@ use crate::dom::webglprogram::WebGLProgram; use crate::dom::webglquery::WebGLQuery; use crate::dom::webglrenderbuffer::WebGLRenderbuffer; use crate::dom::webglrenderingcontext::{ - uniform_get, uniform_typed, Operation, TexPixels, VertexAttrib, WebGLRenderingContext, + uniform_get, uniform_typed, Operation, TexPixels, TexSource, VertexAttrib, + WebGLRenderingContext, }; use crate::dom::webglsampler::{WebGLSampler, WebGLSamplerValue}; use crate::dom::webglshader::WebGLShader; @@ -2926,6 +2927,79 @@ impl WebGL2RenderingContextMethods for WebGL2RenderingContext { border: i32, format: u32, type_: u32, + pbo_offset: i64, + ) -> Fallible<()> { + let pixel_unpack_buffer = match self.bound_pixel_unpack_buffer.get() { + Some(pixel_unpack_buffer) => pixel_unpack_buffer, + None => return Ok(self.base.webgl_error(InvalidOperation)), + }; + + if let Some(tf_buffer) = self.bound_transform_feedback_buffer.get() { + if pixel_unpack_buffer == tf_buffer { + return Ok(self.base.webgl_error(InvalidOperation)); + } + } + + if pbo_offset < 0 || pbo_offset as usize > pixel_unpack_buffer.capacity() { + return Ok(self.base.webgl_error(InvalidValue)); + } + + let unpacking_alignment = self.base.texture_unpacking_alignment(); + + let validator = TexImage2DValidator::new( + &self.base, + target, + level, + internalformat as u32, + width, + height, + border, + format, + type_, + ); + + let TexImage2DValidatorResult { + texture, + target, + width, + height, + level, + border, + internal_format, + format, + data_type, + } = match validator.validate() { + Ok(result) => result, + Err(_) => return Ok(()), + }; + + self.base.tex_image_2d( + &texture, + target, + data_type, + internal_format, + format, + level, + border, + unpacking_alignment, + Size2D::new(width, height), + TexSource::BufferOffset(pbo_offset), + ); + + Ok(()) + } + + /// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.6 + fn TexImage2D___( + &self, + target: u32, + level: i32, + internalformat: i32, + width: i32, + height: i32, + border: i32, + format: u32, + type_: u32, source: ImageDataOrHTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement, ) -> Fallible<()> { if self.bound_pixel_unpack_buffer.get().is_some() { @@ -2975,7 +3049,8 @@ impl WebGL2RenderingContextMethods for WebGL2RenderingContext { level, border, unpacking_alignment, - pixels, + pixels.size(), + TexSource::Pixels(pixels), ); Ok(()) @@ -2983,7 +3058,7 @@ impl WebGL2RenderingContextMethods for WebGL2RenderingContext { /// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.6 #[allow(unsafe_code)] - fn TexImage2D___( + fn TexImage2D____( &self, target: u32, level: i32, @@ -3060,6 +3135,8 @@ impl WebGL2RenderingContextMethods for WebGL2RenderingContext { return Ok(self.base.webgl_error(InvalidOperation)); } + let size = Size2D::new(width, height); + self.base.tex_image_2d( &texture, target, @@ -3069,7 +3146,8 @@ impl WebGL2RenderingContextMethods for WebGL2RenderingContext { level, border, unpacking_alignment, - TexPixels::from_array(buff, Size2D::new(width, height)), + size, + TexSource::Pixels(TexPixels::from_array(buff, size)), ); Ok(()) diff --git a/components/script/dom/webglrenderingcontext.rs b/components/script/dom/webglrenderingcontext.rs index 4c1adbc58d3..a3f78e64c91 100644 --- a/components/script/dom/webglrenderingcontext.rs +++ b/components/script/dom/webglrenderingcontext.rs @@ -613,12 +613,13 @@ impl WebGLRenderingContext { level, 0, 1, - TexPixels::new( + size, + TexSource::Pixels(TexPixels::new( IpcSharedMemory::from_bytes(&pixels), size, PixelFormat::RGBA8, true, - ), + )), ); false @@ -756,15 +757,16 @@ impl WebGLRenderingContext { level: u32, _border: u32, unpacking_alignment: u32, - pixels: TexPixels, + size: Size2D<u32>, + source: TexSource, ) { // TexImage2D depth is always equal to 1. handle_potential_webgl_error!( self, texture.initialize( target, - pixels.size.width, - pixels.size.height, + size.width, + size.height, 1, format, level, @@ -775,12 +777,6 @@ impl WebGLRenderingContext { let settings = self.texture_unpacking_settings.get(); let dest_premultiplied = settings.contains(TextureUnpacking::PREMULTIPLY_ALPHA); - let alpha_treatment = match (pixels.premultiplied, dest_premultiplied) { - (true, false) => Some(AlphaTreatment::Unmultiply), - (false, true) => Some(AlphaTreatment::Premultiply), - _ => None, - }; - let y_axis_treatment = if settings.contains(TextureUnpacking::FLIP_Y_AXIS) { YAxisTreatment::Flipped } else { @@ -795,21 +791,43 @@ impl WebGLRenderingContext { .extension_manager .effective_type(data_type.as_gl_constant()); - // TODO(emilio): convert colorspace if requested. - self.send_command(WebGLCommand::TexImage2D { - target: target.as_gl_constant(), - level, - internal_format, - size: pixels.size, - format, - data_type, - effective_data_type, - unpacking_alignment, - alpha_treatment, - y_axis_treatment, - pixel_format: pixels.pixel_format, - data: pixels.data.into(), - }); + match source { + TexSource::Pixels(pixels) => { + let alpha_treatment = match (pixels.premultiplied, dest_premultiplied) { + (true, false) => Some(AlphaTreatment::Unmultiply), + (false, true) => Some(AlphaTreatment::Premultiply), + _ => None, + }; + + // TODO(emilio): convert colorspace if requested. + self.send_command(WebGLCommand::TexImage2D { + target: target.as_gl_constant(), + level, + internal_format, + size, + format, + data_type, + effective_data_type, + unpacking_alignment, + alpha_treatment, + y_axis_treatment, + pixel_format: pixels.pixel_format, + data: pixels.data.into(), + }); + }, + TexSource::BufferOffset(offset) => { + self.send_command(WebGLCommand::TexImage2DPBO { + target: target.as_gl_constant(), + level, + internal_format, + size, + format, + effective_data_type, + unpacking_alignment, + offset, + }); + }, + } if let Some(fb) = self.bound_draw_framebuffer.get() { fb.invalidate_texture(&*texture); @@ -839,9 +857,9 @@ impl WebGLRenderingContext { // - x offset plus the width is greater than the texture width // - y offset plus the height is greater than the texture height if xoffset < 0 || - (xoffset as u32 + pixels.size.width) > image_info.width() || + (xoffset as u32 + pixels.size().width) > image_info.width() || yoffset < 0 || - (yoffset as u32 + pixels.size.height) > image_info.height() + (yoffset as u32 + pixels.size().height) > image_info.height() { return self.webgl_error(InvalidValue); } @@ -884,7 +902,7 @@ impl WebGLRenderingContext { level, xoffset, yoffset, - size: pixels.size, + size: pixels.size(), format, data_type, effective_data_type, @@ -4319,6 +4337,8 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { return Ok(()); } + let size = Size2D::new(width, height); + self.tex_image_2d( &texture, target, @@ -4328,7 +4348,8 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { level, border, unpacking_alignment, - TexPixels::from_array(buff, Size2D::new(width, height)), + size, + TexSource::Pixels(TexPixels::from_array(buff, size)), ); Ok(()) @@ -4358,8 +4379,8 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { target, level, internal_format as u32, - pixels.size.width as i32, - pixels.size.height as i32, + pixels.size().width as i32, + pixels.size().height as i32, 0, format, data_type, @@ -4391,7 +4412,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { target, level, internal_format, - pixels.size, + pixels.size(), data_type, ) { // FIXME(nox): What is the spec for this? No error is emitted ever @@ -4408,7 +4429,8 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { level, border, 1, - pixels, + pixels.size(), + TexSource::Pixels(pixels), ); Ok(()) } @@ -4568,8 +4590,8 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { target, level, format, - pixels.size.width as i32, - pixels.size.height as i32, + pixels.size().width as i32, + pixels.size().height as i32, 0, format, data_type, @@ -4910,6 +4932,15 @@ impl TexPixels { premultiplied: false, } } + + pub fn size(&self) -> Size2D<u32> { + self.size + } +} + +pub enum TexSource { + Pixels(TexPixels), + BufferOffset(i64), } #[derive(JSTraceable)] diff --git a/components/script/dom/webidls/WebGL2RenderingContext.webidl b/components/script/dom/webidls/WebGL2RenderingContext.webidl index 7595fd951cf..632f1ce5cc6 100644 --- a/components/script/dom/webidls/WebGL2RenderingContext.webidl +++ b/components/script/dom/webidls/WebGL2RenderingContext.webidl @@ -505,9 +505,9 @@ interface mixin WebGL2RenderingContextOverloads GLenum format, GLenum type, TexImageSource source); // May throw DOMException // WebGL2 entrypoints: - //[Throws] - //void texImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, - // GLint border, GLenum format, GLenum type, GLintptr pboOffset); + [Throws] + void texImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, + GLint border, GLenum format, GLenum type, GLintptr pboOffset); [Throws] void texImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, diff --git a/tests/wpt/webgl/meta/conformance2/transform_feedback/simultaneous_binding.html.ini b/tests/wpt/webgl/meta/conformance2/transform_feedback/simultaneous_binding.html.ini index 9eaefa95b43..b4cdc0030c9 100644 --- a/tests/wpt/webgl/meta/conformance2/transform_feedback/simultaneous_binding.html.ini +++ b/tests/wpt/webgl/meta/conformance2/transform_feedback/simultaneous_binding.html.ini @@ -1,5 +1,4 @@ [simultaneous_binding.html] - expected: ERROR [WebGL test #12: getError expected: INVALID_OPERATION. Was NO_ERROR : drawArrays: buffer used as vertex attrib and tf simultaneously] expected: FAIL @@ -75,3 +74,66 @@ [WebGL test #17: getError expected: INVALID_OPERATION. Was NO_ERROR : drawElements: buffer used as uniform buffer and tf simultaneously] expected: FAIL + [WebGL test #110: getError expected: NO_ERROR. Was INVALID_OPERATION : PIXEL_UNPACK_BUFFER is not bound for transform feedback] + expected: FAIL + + [WebGL test #101: getError expected: INVALID_OPERATION. Was NO_ERROR : bufferSubData with double bound buffer] + expected: FAIL + + [WebGL test #85: getError expected: INVALID_OPERATION. Was NO_ERROR : PIXEL_PACK_BUFFER is bound for transform feedback] + expected: FAIL + + [WebGL test #118: getError expected: INVALID_OPERATION. Was NO_ERROR : copyBufferSubData with double bound buffer] + expected: FAIL + + [WebGL test #104: getError expected: INVALID_OPERATION. Was NO_ERROR : copyBufferSubData with double bound buffer] + expected: FAIL + + [WebGL test #114: getError expected: INVALID_OPERATION. Was NO_ERROR : bufferData with double bound buffer] + expected: FAIL + + [WebGL test #103: getError expected: INVALID_OPERATION. Was NO_ERROR : copyBufferSubData with double bound buffer] + expected: FAIL + + [WebGL test #116: getError expected: INVALID_OPERATION. Was NO_ERROR : getBufferSubData with double bound buffer] + expected: FAIL + + [WebGL test #88: getError expected: INVALID_OPERATION. Was NO_ERROR : getBufferSubData with double bound buffer] + expected: FAIL + + [WebGL test #113: getError expected: INVALID_OPERATION. Was NO_ERROR : PIXEL_PACK_BUFFER is bound for transform feedback] + expected: FAIL + + [WebGL test #83: getError expected: INVALID_OPERATION. Was NO_ERROR : PIXEL_UNPACK_BUFFER is bound for transform feedback] + expected: FAIL + + [WebGL test #117: getError expected: INVALID_OPERATION. Was NO_ERROR : copyBufferSubData with double bound buffer] + expected: FAIL + + [WebGL test #100: getError expected: INVALID_OPERATION. Was NO_ERROR : bufferData with double bound buffer] + expected: FAIL + + [WebGL test #89: getError expected: INVALID_OPERATION. Was NO_ERROR : copyBufferSubData with double bound buffer] + expected: FAIL + + [WebGL test #102: getError expected: INVALID_OPERATION. Was NO_ERROR : getBufferSubData with double bound buffer] + expected: FAIL + + [WebGL test #111: getError expected: INVALID_OPERATION. Was NO_ERROR : PIXEL_UNPACK_BUFFER is bound for transform feedback] + expected: FAIL + + [WebGL test #87: getError expected: INVALID_OPERATION. Was NO_ERROR : bufferSubData with double bound buffer] + expected: FAIL + + [WebGL test #99: getError expected: INVALID_OPERATION. Was NO_ERROR : PIXEL_PACK_BUFFER is bound for transform feedback] + expected: FAIL + + [WebGL test #86: getError expected: INVALID_OPERATION. Was NO_ERROR : bufferData with double bound buffer] + expected: FAIL + + [WebGL test #90: getError expected: INVALID_OPERATION. Was NO_ERROR : copyBufferSubData with double bound buffer] + expected: FAIL + + [WebGL test #115: getError expected: INVALID_OPERATION. Was NO_ERROR : bufferSubData with double bound buffer] + expected: FAIL + |