diff options
Diffstat (limited to 'components')
-rw-r--r-- | components/canvas/Cargo.toml | 1 | ||||
-rw-r--r-- | components/canvas/canvas_paint_thread.rs | 3 | ||||
-rw-r--r-- | components/canvas/lib.rs | 1 | ||||
-rw-r--r-- | components/canvas/webgl_thread.rs | 4 | ||||
-rw-r--r-- | components/canvas_traits/canvas.rs | 35 | ||||
-rw-r--r-- | components/net/Cargo.toml | 1 | ||||
-rw-r--r-- | components/net/image_cache.rs | 27 | ||||
-rw-r--r-- | components/net/lib.rs | 1 | ||||
-rw-r--r-- | components/net_traits/Cargo.toml | 1 | ||||
-rw-r--r-- | components/net_traits/image/base.rs | 21 | ||||
-rw-r--r-- | components/net_traits/lib.rs | 1 | ||||
-rw-r--r-- | components/pixels/Cargo.toml | 10 | ||||
-rw-r--r-- | components/pixels/lib.rs | 40 | ||||
-rw-r--r-- | components/script/Cargo.toml | 1 | ||||
-rw-r--r-- | components/script/dom/canvasrenderingcontext2d.rs | 5 | ||||
-rw-r--r-- | components/script/dom/webglrenderingcontext.rs | 20 | ||||
-rw-r--r-- | components/script/lib.rs | 1 |
17 files changed, 77 insertions, 96 deletions
diff --git a/components/canvas/Cargo.toml b/components/canvas/Cargo.toml index 4006947acf6..de2073a1e28 100644 --- a/components/canvas/Cargo.toml +++ b/components/canvas/Cargo.toml @@ -24,6 +24,7 @@ ipc-channel = "0.11" log = "0.4" num-traits = "0.2" offscreen_gl_context = {version = "0.21", features = ["serde", "osmesa"]} +pixels = {path = "../pixels"} serde_bytes = "0.10" servo_config = {path = "../config"} webrender = {git = "https://github.com/servo/webrender"} diff --git a/components/canvas/canvas_paint_thread.rs b/components/canvas/canvas_paint_thread.rs index 90d338e9a4e..91164a47cf0 100644 --- a/components/canvas/canvas_paint_thread.rs +++ b/components/canvas/canvas_paint_thread.rs @@ -7,6 +7,7 @@ use canvas_data::*; use canvas_traits::canvas::*; use euclid::Size2D; use ipc_channel::ipc::{self, IpcSender}; +use pixels; use std::borrow::ToOwned; use std::collections::HashMap; use std::thread; @@ -141,7 +142,7 @@ impl<'a> CanvasPaintThread <'a> { let data = match imagedata { None => vec![0; image_size.width as usize * image_size.height as usize * 4], Some(mut data) => { - byte_swap(&mut data); + pixels::byte_swap_colors_inplace(&mut data); data.into() }, }; diff --git a/components/canvas/lib.rs b/components/canvas/lib.rs index 8da9544de6e..554f598403c 100644 --- a/components/canvas/lib.rs +++ b/components/canvas/lib.rs @@ -15,6 +15,7 @@ extern crate ipc_channel; #[macro_use] extern crate log; extern crate num_traits; extern crate offscreen_gl_context; +extern crate pixels; extern crate serde_bytes; extern crate servo_config; extern crate webrender; diff --git a/components/canvas/webgl_thread.rs b/components/canvas/webgl_thread.rs index 413566e7817..cd8dbde18d2 100644 --- a/components/canvas/webgl_thread.rs +++ b/components/canvas/webgl_thread.rs @@ -2,13 +2,13 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use canvas_traits::canvas::byte_swap; use canvas_traits::webgl::*; use euclid::Size2D; use fnv::FnvHashMap; use gleam::gl; use ipc_channel::ipc::IpcBytesSender; use offscreen_gl_context::{GLContext, GLContextAttributes, GLLimits, NativeGLContextMethods}; +use pixels; use std::thread; use super::gl_context::{GLContextFactory, GLContextWrapper}; use webrender; @@ -562,7 +562,7 @@ impl<VR: WebVRRenderHandler + 'static> WebGLThread<VR> { let src_slice = &orig_pixels[src_start .. src_start + stride]; (&mut pixels[dst_start .. dst_start + stride]).clone_from_slice(&src_slice[..stride]); } - byte_swap(&mut pixels); + pixels::byte_swap_colors_inplace(&mut pixels); pixels } diff --git a/components/canvas_traits/canvas.rs b/components/canvas_traits/canvas.rs index 1fcf1a89a4a..6c7022c62a8 100644 --- a/components/canvas_traits/canvas.rs +++ b/components/canvas_traits/canvas.rs @@ -382,38 +382,3 @@ impl FromStr for CompositionOrBlending { Err(()) } } - -// TODO(pcwalton): Speed up with SIMD, or better yet, find some way to not do this. -pub fn byte_swap(data: &mut [u8]) { - let length = data.len(); - // FIXME(rust #27741): Range::step_by is not stable yet as of this writing. - let mut i = 0; - while i < length { - let r = data[i + 2]; - data[i + 2] = data[i + 0]; - data[i + 0] = r; - i += 4; - } -} - -pub fn multiply_u8_pixel(a: u8, b: u8) -> u8 { - return (a as u32 * b as u32 / 255) as u8; -} - -pub fn byte_swap_and_premultiply(data: &mut [u8]) { - let length = data.len(); - - let mut i = 0; - while i < length { - let r = data[i + 2]; - let g = data[i + 1]; - let b = data[i + 0]; - let a = data[i + 3]; - - data[i + 0] = multiply_u8_pixel(r, a); - data[i + 1] = multiply_u8_pixel(g, a); - data[i + 2] = multiply_u8_pixel(b, a); - - i += 4; - } -} diff --git a/components/net/Cargo.toml b/components/net/Cargo.toml index aca08703bae..4c0b2aa4e9b 100644 --- a/components/net/Cargo.toml +++ b/components/net/Cargo.toml @@ -34,6 +34,7 @@ mime_guess = "1.8.0" msg = {path = "../msg"} net_traits = {path = "../net_traits"} openssl = "0.9" +pixels = {path = "../pixels"} profile_traits = {path = "../profile_traits"} serde = "1.0" serde_json = "1.0" diff --git a/components/net/image_cache.rs b/components/net/image_cache.rs index 40ef8041ef7..ba0d679b0e3 100644 --- a/components/net/image_cache.rs +++ b/components/net/image_cache.rs @@ -9,6 +9,7 @@ use net_traits::image::base::{Image, ImageMetadata, PixelFormat, load_from_memor use net_traits::image_cache::{CanRequestImages, ImageCache, ImageResponder}; use net_traits::image_cache::{ImageOrMetadataAvailable, ImageResponse, ImageState}; use net_traits::image_cache::{PendingImageId, UsePlaceholder}; +use pixels; use servo_url::ServoUrl; use std::collections::HashMap; use std::collections::hash_map::Entry::{Occupied, Vacant}; @@ -52,7 +53,7 @@ fn set_webrender_image_key(webrender_api: &webrender_api::RenderApi, image: &mut let is_opaque = match image.format { PixelFormat::BGRA8 => { bytes.extend_from_slice(&*image.bytes); - premultiply(bytes.as_mut_slice()) + pixels::premultiply_inplace(bytes.as_mut_slice()) } PixelFormat::RGB8 => { for bgr in image.bytes.chunks(3) { @@ -86,30 +87,6 @@ fn set_webrender_image_key(webrender_api: &webrender_api::RenderApi, image: &mut image.id = Some(image_key); } -// Returns true if the image was found to be -// completely opaque. -fn premultiply(data: &mut [u8]) -> bool { - let mut is_opaque = true; - let length = data.len(); - - let mut i = 0; - while i < length { - let b = data[i + 0] as u32; - let g = data[i + 1] as u32; - let r = data[i + 2] as u32; - let a = data[i + 3] as u32; - - data[i + 0] = (b * a / 255) as u8; - data[i + 1] = (g * a / 255) as u8; - data[i + 2] = (r * a / 255) as u8; - - i += 4; - is_opaque = is_opaque && a == 255; - } - - is_opaque -} - // ====================================================================== // Aux structs and enums. // ====================================================================== diff --git a/components/net/lib.rs b/components/net/lib.rs index ab5c3bc74a2..285a755a9e9 100644 --- a/components/net/lib.rs +++ b/components/net/lib.rs @@ -27,6 +27,7 @@ extern crate mime_guess; extern crate msg; extern crate net_traits; extern crate openssl; +extern crate pixels; #[macro_use] extern crate profile_traits; #[macro_use] extern crate serde; diff --git a/components/net_traits/Cargo.toml b/components/net_traits/Cargo.toml index 9ae5042be69..641d77d8d0c 100644 --- a/components/net_traits/Cargo.toml +++ b/components/net_traits/Cargo.toml @@ -24,6 +24,7 @@ malloc_size_of = { path = "../malloc_size_of" } malloc_size_of_derive = { path = "../malloc_size_of_derive" } msg = {path = "../msg"} num-traits = "0.2" +pixels = {path = "../pixels"} serde = "1.0" servo_arc = {path = "../servo_arc"} servo_config = {path = "../config"} diff --git a/components/net_traits/image/base.rs b/components/net_traits/image/base.rs index 35b52e559fe..40d79b9ea74 100644 --- a/components/net_traits/image/base.rs +++ b/components/net_traits/image/base.rs @@ -4,6 +4,7 @@ use ipc_channel::ipc::IpcSharedMemory; use piston_image::{self, DynamicImage, ImageFormat}; +use pixels; use std::fmt; use webrender_api; @@ -46,24 +47,6 @@ pub struct ImageMetadata { // FIXME: Images must not be copied every frame. Instead we should atomically // reference count them. -// TODO(pcwalton): Speed up with SIMD, or better yet, find some way to not do this. -fn byte_swap_colors_inplace(data: &mut [u8]) { - let length = data.len(); - - let mut i = 0; - while i < length { - let r = data[i + 2]; - let g = data[i + 1]; - let b = data[i + 0]; - - data[i + 0] = r; - data[i + 1] = g; - data[i + 2] = b; - - i += 4; - } -} - pub fn load_from_memory(buffer: &[u8]) -> Option<Image> { if buffer.is_empty() { return None; @@ -82,7 +65,7 @@ pub fn load_from_memory(buffer: &[u8]) -> Option<Image> { DynamicImage::ImageRgba8(rgba) => rgba, image => image.to_rgba(), }; - byte_swap_colors_inplace(&mut *rgba); + pixels::byte_swap_colors_inplace(&mut *rgba); Some(Image { width: rgba.width(), height: rgba.height(), diff --git a/components/net_traits/lib.rs b/components/net_traits/lib.rs index 87dcf034caa..7066a3f1f28 100644 --- a/components/net_traits/lib.rs +++ b/components/net_traits/lib.rs @@ -17,6 +17,7 @@ extern crate ipc_channel; #[macro_use] extern crate malloc_size_of_derive; extern crate msg; extern crate num_traits; +extern crate pixels; #[macro_use] extern crate serde; extern crate servo_arc; extern crate servo_url; diff --git a/components/pixels/Cargo.toml b/components/pixels/Cargo.toml new file mode 100644 index 00000000000..49dcc3833cf --- /dev/null +++ b/components/pixels/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "pixels" +version = "0.0.1" +authors = ["The Servo Project Developers"] +license = "MPL-2.0" +publish = false + +[lib] +name = "pixels" +path = "lib.rs" diff --git a/components/pixels/lib.rs b/components/pixels/lib.rs new file mode 100644 index 00000000000..d91b14cb650 --- /dev/null +++ b/components/pixels/lib.rs @@ -0,0 +1,40 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// TODO(pcwalton): Speed up with SIMD, or better yet, find some way to not do this. +pub fn byte_swap_colors_inplace(pixels: &mut [u8]) { + assert!(pixels.len() % 4 == 0); + for rgba in pixels.chunks_mut(4) { + let b = rgba[0]; + rgba[0] = rgba[2]; + rgba[2] = b; + } +} + +pub fn byte_swap_and_premultiply_inplace(pixels: &mut [u8]) { + assert!(pixels.len() % 4 == 0); + for rgba in pixels.chunks_mut(4) { + let b = rgba[0]; + rgba[0] = multiply_u8_color(rgba[2], rgba[3]); + rgba[1] = multiply_u8_color(rgba[1], rgba[3]); + rgba[2] = multiply_u8_color(b, rgba[3]); + } +} + +/// Returns true if the pixels were found to be completely opaque. +pub fn premultiply_inplace(pixels: &mut [u8]) -> bool { + assert!(pixels.len() % 4 == 0); + let mut is_opaque = true; + for rgba in pixels.chunks_mut(4) { + rgba[0] = multiply_u8_color(rgba[0], rgba[3]); + rgba[1] = multiply_u8_color(rgba[1], rgba[3]); + rgba[2] = multiply_u8_color(rgba[2], rgba[3]); + is_opaque = is_opaque && rgba[3] == 255; + } + is_opaque +} + +pub fn multiply_u8_color(a: u8, b: u8) -> u8 { + return (a as u32 * b as u32 / 255) as u8; +} diff --git a/components/script/Cargo.toml b/components/script/Cargo.toml index ca859bb472a..078218d624b 100644 --- a/components/script/Cargo.toml +++ b/components/script/Cargo.toml @@ -75,6 +75,7 @@ num-traits = "0.2" offscreen_gl_context = {version = "0.21", features = ["serde"]} parking_lot = "0.6" phf = "0.7.18" +pixels = {path = "../pixels"} profile_traits = {path = "../profile_traits"} ref_filter_map = "1.0.1" ref_slice = "1.0" diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 9adbaa3a734..15b6eb9560f 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -5,7 +5,7 @@ use canvas_traits::canvas::{Canvas2dMsg, CanvasMsg, CanvasId}; use canvas_traits::canvas::{CompositionOrBlending, FillOrStrokeStyle, FillRule}; use canvas_traits::canvas::{LineCapStyle, LineJoinStyle, LinearGradientStyle}; -use canvas_traits::canvas::{RadialGradientStyle, RepetitionStyle, byte_swap_and_premultiply}; +use canvas_traits::canvas::{RadialGradientStyle, RepetitionStyle}; use cssparser::{Parser, ParserInput, RGBA}; use cssparser::Color as CSSColor; use dom::bindings::cell::DomRefCell; @@ -41,6 +41,7 @@ use net_traits::image_cache::ImageResponse; use net_traits::image_cache::ImageState; use net_traits::image_cache::UsePlaceholder; use num_traits::ToPrimitive; +use pixels; use profile_traits::ipc as profiled_ipc; use script_traits::ScriptMsg; use servo_url::ServoUrl; @@ -410,7 +411,7 @@ impl CanvasRenderingContext2D { Some((mut data, size)) => { // Pixels come from cache in BGRA order and drawImage expects RGBA so we // have to swap the color values - byte_swap_and_premultiply(&mut data); + pixels::byte_swap_and_premultiply_inplace(&mut data); let size = Size2D::new(size.width as f64, size.height as f64); (data, size) }, diff --git a/components/script/dom/webglrenderingcontext.rs b/components/script/dom/webglrenderingcontext.rs index 7972201b9ce..a2862831f73 100644 --- a/components/script/dom/webglrenderingcontext.rs +++ b/components/script/dom/webglrenderingcontext.rs @@ -5,7 +5,6 @@ #[cfg(feature = "webgl_backtrace")] use backtrace::Backtrace; use byteorder::{ByteOrder, NativeEndian, WriteBytesExt}; -use canvas_traits::canvas::{byte_swap, multiply_u8_pixel}; use canvas_traits::webgl::{DOMToTextureCommand, Parameter, WebGLCommandBacktrace}; use canvas_traits::webgl::{TexParameter, WebGLCommand, WebGLContextShareMode, WebGLError}; use canvas_traits::webgl::{WebGLFramebufferBindingRequest, WebGLMsg, WebGLMsgSender}; @@ -65,6 +64,7 @@ use js::typedarray::{TypedArray, TypedArrayElementCreator}; use net_traits::image::base::PixelFormat; use net_traits::image_cache::ImageResponse; use offscreen_gl_context::{GLContextAttributes, GLLimits}; +use pixels; use script_layout_interface::HTMLCanvasDataSource; use serde::{Deserialize, Serialize}; use servo_config::prefs::PREFS; @@ -550,7 +550,7 @@ impl WebGLRenderingContext { _ => unimplemented!(), }; - byte_swap(&mut data); + pixels::byte_swap_colors_inplace(&mut data); (data, size, false) }, @@ -563,7 +563,7 @@ impl WebGLRenderingContext { } if let Some((mut data, size)) = canvas.fetch_all_data() { // Pixels got from Canvas have already alpha premultiplied - byte_swap(&mut data); + pixels::byte_swap_colors_inplace(&mut data); (data, size, true) } else { return Ok(None); @@ -679,15 +679,11 @@ impl WebGLRenderingContext { match (format, data_type) { (TexFormat::RGBA, TexDataType::UnsignedByte) => { - for rgba in pixels.chunks_mut(4) { - rgba[0] = multiply_u8_pixel(rgba[0], rgba[3]); - rgba[1] = multiply_u8_pixel(rgba[1], rgba[3]); - rgba[2] = multiply_u8_pixel(rgba[2], rgba[3]); - } + pixels::premultiply_inplace(pixels); }, (TexFormat::LuminanceAlpha, TexDataType::UnsignedByte) => { for la in pixels.chunks_mut(2) { - la[0] = multiply_u8_pixel(la[0], la[1]); + la[0] = pixels::multiply_u8_color(la[0], la[1]); } }, (TexFormat::RGBA, TexDataType::UnsignedShort5551) => { @@ -707,9 +703,9 @@ impl WebGLRenderingContext { let a = extend_to_8_bits(pix & 0x0f); NativeEndian::write_u16( rgba, - ((multiply_u8_pixel(r, a) & 0xf0) as u16) << 8 | - ((multiply_u8_pixel(g, a) & 0xf0) as u16) << 4 | - ((multiply_u8_pixel(b, a) & 0xf0) as u16) | + ((pixels::multiply_u8_color(r, a) & 0xf0) as u16) << 8 | + ((pixels::multiply_u8_color(g, a) & 0xf0) as u16) << 4 | + ((pixels::multiply_u8_color(b, a) & 0xf0) as u16) | ((a & 0x0f) as u16), ); } diff --git a/components/script/lib.rs b/components/script/lib.rs index 097f69d7808..a2ece5ce32c 100644 --- a/components/script/lib.rs +++ b/components/script/lib.rs @@ -78,6 +78,7 @@ extern crate num_traits; extern crate offscreen_gl_context; extern crate parking_lot; extern crate phf; +extern crate pixels; #[macro_use] extern crate profile_traits; extern crate ref_filter_map; |