mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
Merge some byte swap/premultiply functions in their own crate
This commit is contained in:
parent
a2e3dd4e86
commit
784fbb2bc1
18 changed files with 85 additions and 96 deletions
8
Cargo.lock
generated
8
Cargo.lock
generated
|
@ -338,6 +338,7 @@ dependencies = [
|
|||
"log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"offscreen_gl_context 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pixels 0.0.1",
|
||||
"serde_bytes 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"servo_config 0.0.1",
|
||||
"webrender 0.57.2 (git+https://github.com/servo/webrender)",
|
||||
|
@ -2308,6 +2309,7 @@ dependencies = [
|
|||
"msg 0.0.1",
|
||||
"net_traits 0.0.1",
|
||||
"openssl 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pixels 0.0.1",
|
||||
"profile_traits 0.0.1",
|
||||
"serde 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -2351,6 +2353,7 @@ dependencies = [
|
|||
"malloc_size_of_derive 0.0.1",
|
||||
"msg 0.0.1",
|
||||
"num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pixels 0.0.1",
|
||||
"serde 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"servo_arc 0.1.1",
|
||||
"servo_config 0.0.1",
|
||||
|
@ -2657,6 +2660,10 @@ dependencies = [
|
|||
"unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pixels"
|
||||
version = "0.0.1"
|
||||
|
||||
[[package]]
|
||||
name = "pkg-config"
|
||||
version = "0.3.14"
|
||||
|
@ -3028,6 +3035,7 @@ dependencies = [
|
|||
"phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pixels 0.0.1",
|
||||
"profile_traits 0.0.1",
|
||||
"ref_filter_map 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ref_slice 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
|
|
@ -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"}
|
||||
|
|
|
@ -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()
|
||||
},
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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.
|
||||
// ======================================================================
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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"}
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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;
|
||||
|
|
10
components/pixels/Cargo.toml
Normal file
10
components/pixels/Cargo.toml
Normal file
|
@ -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"
|
40
components/pixels/lib.rs
Normal file
40
components/pixels/lib.rs
Normal file
|
@ -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;
|
||||
}
|
|
@ -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"
|
||||
|
|
|
@ -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)
|
||||
},
|
||||
|
|
|
@ -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),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue