diff --git a/components/canvas_traits/webgl.rs b/components/canvas_traits/webgl.rs index 000bf0ba119..7abf39a8c83 100644 --- a/components/canvas_traits/webgl.rs +++ b/components/canvas_traits/webgl.rs @@ -773,9 +773,53 @@ pub enum TexSource { FromArray, } +pub fn prepare_pixels( + internal_format: TexFormat, + data_type: TexDataType, + size: Size2D, + unpacking_alignment: u32, + alpha_treatment: Option, + y_axis_treatment: YAxisTreatment, + tex_source: TexSource, + mut pixels: Vec, +) -> Vec { + match alpha_treatment { + Some(AlphaTreatment::Premultiply) => { + if tex_source == TexSource::FromHtmlElement { + premultiply_inplace(TexFormat::RGBA, TexDataType::UnsignedByte, &mut pixels); + } else { + premultiply_inplace(internal_format, data_type, &mut pixels); + } + }, + Some(AlphaTreatment::Unmultiply) => { + assert_eq!(tex_source, TexSource::FromHtmlElement); + unmultiply_inplace(&mut pixels); + }, + None => {}, + } + + if tex_source == TexSource::FromHtmlElement { + pixels = rgba8_image_to_tex_image_data(internal_format, data_type, pixels); + } + + if y_axis_treatment == YAxisTreatment::Flipped { + // FINISHME: Consider doing premultiply and flip in a single mutable Vec. + pixels = flip_pixels_y( + internal_format, + data_type, + size.width as usize, + size.height as usize, + unpacking_alignment as usize, + pixels, + ); + } + + pixels +} + /// Translates an image in rgba8 (red in the first byte) format to /// the format that was requested of TexImage. -pub fn rgba8_image_to_tex_image_data( +fn rgba8_image_to_tex_image_data( format: TexFormat, data_type: TexDataType, mut pixels: Vec, @@ -978,7 +1022,7 @@ pub fn rgba8_image_to_tex_image_data( } } -pub fn premultiply_inplace(format: TexFormat, data_type: TexDataType, pixels: &mut [u8]) { +fn premultiply_inplace(format: TexFormat, data_type: TexDataType, pixels: &mut [u8]) { match (format, data_type) { (TexFormat::RGBA, TexDataType::UnsignedByte) => { pixels::rgba8_premultiply_inplace(pixels); @@ -1017,7 +1061,7 @@ pub fn premultiply_inplace(format: TexFormat, data_type: TexDataType, pixels: &m } } -pub fn unmultiply_inplace(pixels: &mut [u8]) { +fn unmultiply_inplace(pixels: &mut [u8]) { for rgba in pixels.chunks_mut(4) { let a = (rgba[3] as f32) / 255.0; rgba[0] = (rgba[0] as f32 / a) as u8; @@ -1027,7 +1071,7 @@ pub fn unmultiply_inplace(pixels: &mut [u8]) { } /// Flips the pixels in the Vec on the Y axis. -pub fn flip_pixels_y( +fn flip_pixels_y( internal_format: TexFormat, data_type: TexDataType, width: usize, diff --git a/components/script/dom/webglrenderingcontext.rs b/components/script/dom/webglrenderingcontext.rs index bbd9a12538b..1435c9133c9 100644 --- a/components/script/dom/webglrenderingcontext.rs +++ b/components/script/dom/webglrenderingcontext.rs @@ -638,55 +638,6 @@ impl WebGLRenderingContext { } } - fn prepare_pixels( - &self, - internal_format: TexFormat, - data_type: TexDataType, - size: Size2D, - unpacking_alignment: u32, - alpha_treatment: Option, - y_axis_treatment: YAxisTreatment, - tex_source: TexSource, - mut pixels: Vec, - ) -> Vec { - match alpha_treatment { - Some(AlphaTreatment::Premultiply) => { - if tex_source == TexSource::FromHtmlElement { - webgl::premultiply_inplace( - TexFormat::RGBA, - TexDataType::UnsignedByte, - &mut pixels, - ); - } else { - webgl::premultiply_inplace(internal_format, data_type, &mut pixels); - } - }, - Some(AlphaTreatment::Unmultiply) => { - assert_eq!(tex_source, TexSource::FromHtmlElement); - webgl::unmultiply_inplace(&mut pixels); - }, - None => {}, - } - - if tex_source == TexSource::FromHtmlElement { - pixels = webgl::rgba8_image_to_tex_image_data(internal_format, data_type, pixels); - } - - if y_axis_treatment == YAxisTreatment::Flipped { - // FINISHME: Consider doing premultiply and flip in a single mutable Vec. - pixels = webgl::flip_pixels_y( - internal_format, - data_type, - size.width as usize, - size.height as usize, - unpacking_alignment as usize, - pixels, - ); - } - - pixels - } - fn tex_image_2d( &self, texture: &WebGLTexture, @@ -699,6 +650,20 @@ impl WebGLRenderingContext { tex_source: TexSource, pixels: TexPixels, ) { + // TexImage2D depth is always equal to 1. + handle_potential_webgl_error!( + self, + texture.initialize( + target, + pixels.size.width, + pixels.size.height, + 1, + internal_format, + level, + Some(data_type) + ) + ); + let settings = self.texture_unpacking_settings.get(); let dest_premultiplied = settings.contains(TextureUnpacking::PREMULTIPLY_ALPHA); @@ -714,7 +679,7 @@ impl WebGLRenderingContext { YAxisTreatment::AsIs }; - let buff = self.prepare_pixels( + let buff = webgl::prepare_pixels( internal_format, data_type, pixels.size, @@ -725,20 +690,6 @@ impl WebGLRenderingContext { pixels.data, ); - // TexImage2D depth is always equal to 1 - handle_potential_webgl_error!( - self, - texture.initialize( - target, - pixels.size.width, - pixels.size.height, - 1, - internal_format, - level, - Some(data_type) - ) - ); - let format = internal_format.as_gl_constant(); let data_type = data_type.as_gl_constant(); let internal_format = self @@ -777,34 +728,6 @@ impl WebGLRenderingContext { tex_source: TexSource, pixels: TexPixels, ) { - let settings = self.texture_unpacking_settings.get(); - - let alpha_treatment = match ( - pixels.premultiplied, - settings.contains(TextureUnpacking::PREMULTIPLY_ALPHA), - ) { - (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 { - YAxisTreatment::AsIs - }; - - let buff = self.prepare_pixels( - format, - data_type, - pixels.size, - unpacking_alignment, - alpha_treatment, - y_axis_treatment, - tex_source, - pixels.data, - ); - // We have already validated level let image_info = texture.image_info_for_target(&target, level); @@ -827,6 +750,32 @@ impl WebGLRenderingContext { return self.webgl_error(InvalidOperation); } + 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 { + YAxisTreatment::AsIs + }; + + let buff = webgl::prepare_pixels( + format, + data_type, + pixels.size, + unpacking_alignment, + alpha_treatment, + y_axis_treatment, + tex_source, + pixels.data, + ); + // TODO(emilio): convert colorspace if requested let (sender, receiver) = ipc::bytes_channel().unwrap(); self.send_command(WebGLCommand::TexSubImage2D {