diff options
Diffstat (limited to 'components/script')
-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 |
3 files changed, 152 insertions, 43 deletions
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, |