librsvg source for verification 2026-05-22
This commit is contained in:
58
rsvg/benches/box_blur.rs
Normal file
58
rsvg/benches/box_blur.rs
Normal file
@@ -0,0 +1,58 @@
|
||||
use criterion::{BenchmarkId, Criterion, criterion_group, criterion_main};
|
||||
|
||||
use rsvg::bench_only::{
|
||||
AlphaOnly, Horizontal, IRect, NotAlphaOnly, SharedImageSurface, SurfaceType, Vertical,
|
||||
};
|
||||
|
||||
const SURFACE_SIDE: i32 = 512;
|
||||
const BOUNDS: IRect = IRect {
|
||||
x0: 64,
|
||||
y0: 64,
|
||||
x1: 64 + 64,
|
||||
y1: 64 + 64,
|
||||
};
|
||||
|
||||
fn bench_box_blur(c: &mut Criterion) {
|
||||
let mut group = c.benchmark_group("box_blur 9");
|
||||
|
||||
for input in [(false, false), (false, true), (true, false), (true, true)].iter() {
|
||||
group.bench_with_input(
|
||||
BenchmarkId::from_parameter(format!("{:?}", input)),
|
||||
&input,
|
||||
|b, &(vertical, alpha_only)| {
|
||||
let surface_type = if *alpha_only {
|
||||
SurfaceType::AlphaOnly
|
||||
} else {
|
||||
SurfaceType::SRgb
|
||||
};
|
||||
let input_surface =
|
||||
SharedImageSurface::empty(SURFACE_SIDE, SURFACE_SIDE, surface_type).unwrap();
|
||||
|
||||
let mut output_surface =
|
||||
cairo::ImageSurface::create(cairo::Format::ARgb32, SURFACE_SIDE, SURFACE_SIDE)
|
||||
.unwrap();
|
||||
const KERNEL_SIZE: usize = 9;
|
||||
|
||||
let f = match (vertical, alpha_only) {
|
||||
(true, true) => SharedImageSurface::box_blur_loop::<Vertical, AlphaOnly>,
|
||||
(true, false) => SharedImageSurface::box_blur_loop::<Vertical, NotAlphaOnly>,
|
||||
(false, true) => SharedImageSurface::box_blur_loop::<Horizontal, AlphaOnly>,
|
||||
(false, false) => SharedImageSurface::box_blur_loop::<Horizontal, NotAlphaOnly>,
|
||||
};
|
||||
|
||||
b.iter(|| {
|
||||
f(
|
||||
&input_surface,
|
||||
&mut output_surface,
|
||||
BOUNDS,
|
||||
KERNEL_SIZE,
|
||||
KERNEL_SIZE / 2,
|
||||
)
|
||||
})
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
criterion_group!(benches, bench_box_blur);
|
||||
criterion_main!(benches);
|
||||
44
rsvg/benches/composite.rs
Normal file
44
rsvg/benches/composite.rs
Normal file
@@ -0,0 +1,44 @@
|
||||
use criterion::{Criterion, criterion_group, criterion_main};
|
||||
use std::hint::black_box;
|
||||
|
||||
use rsvg::bench_only::{
|
||||
ExclusiveImageSurface, IRect, SharedImageSurface, SurfaceType, composite_arithmetic,
|
||||
};
|
||||
|
||||
const SURFACE_SIDE: i32 = 512;
|
||||
const BOUNDS: IRect = IRect {
|
||||
x0: 64,
|
||||
y0: 64,
|
||||
x1: 64 + 64,
|
||||
y1: 64 + 64,
|
||||
};
|
||||
|
||||
fn bench_composite(c: &mut Criterion) {
|
||||
c.bench_function("composite arithmetic", |b| {
|
||||
let input_surface =
|
||||
SharedImageSurface::empty(SURFACE_SIDE, SURFACE_SIDE, SurfaceType::SRgb).unwrap();
|
||||
let input_2_surface =
|
||||
SharedImageSurface::empty(SURFACE_SIDE, SURFACE_SIDE, SurfaceType::SRgb).unwrap();
|
||||
|
||||
let mut output_surface =
|
||||
ExclusiveImageSurface::new(SURFACE_SIDE, SURFACE_SIDE, SurfaceType::SRgb).unwrap();
|
||||
|
||||
let bounds = black_box(BOUNDS);
|
||||
|
||||
b.iter(|| {
|
||||
composite_arithmetic(
|
||||
&input_surface,
|
||||
&input_2_surface,
|
||||
&mut output_surface,
|
||||
bounds,
|
||||
0.5,
|
||||
0.5,
|
||||
0.5,
|
||||
0.5,
|
||||
);
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
criterion_group!(benches, bench_composite);
|
||||
criterion_main!(benches);
|
||||
258
rsvg/benches/lighting.rs
Normal file
258
rsvg/benches/lighting.rs
Normal file
@@ -0,0 +1,258 @@
|
||||
use criterion::{Criterion, criterion_group, criterion_main};
|
||||
use nalgebra::{Matrix3, Vector2};
|
||||
|
||||
use rsvg::bench_only::Normal;
|
||||
|
||||
use rsvg::bench_only::{EdgeMode, IRect, PixelRectangle, Pixels, SharedImageSurface, SurfaceType};
|
||||
|
||||
/// Computes and returns the normal vector for the light filters.
|
||||
fn normal(surface: &SharedImageSurface, bounds: IRect, x: u32, y: u32) -> Normal {
|
||||
assert!(x as i32 >= bounds.x0);
|
||||
assert!(y as i32 >= bounds.y0);
|
||||
assert!((x as i32) < bounds.x1);
|
||||
assert!((y as i32) < bounds.y1);
|
||||
|
||||
// Get the correct sobel kernel and factor for the pixel position.
|
||||
// Performance note: it's possible to replace the matrices with normal arrays.
|
||||
#[rustfmt::skip]
|
||||
let (factor_x, kx, factor_y, ky) = match (x as i32, y as i32) {
|
||||
(x, y) if (x, y) == (bounds.x0, bounds.y0) => (
|
||||
2. / 3.,
|
||||
Matrix3::new(
|
||||
0, 0, 0,
|
||||
0, -2, 2,
|
||||
0, -1, 1,
|
||||
),
|
||||
2. / 3.,
|
||||
Matrix3::new(
|
||||
0, 0, 0,
|
||||
0, -2, -1,
|
||||
0, 2, 1,
|
||||
),
|
||||
),
|
||||
(x, y) if (x + 1, y) == (bounds.x1, bounds.y0) => (
|
||||
2. / 3.,
|
||||
Matrix3::new(
|
||||
0, 0, 0,
|
||||
-2, 2, 0,
|
||||
-1, 1, 0,
|
||||
),
|
||||
2. / 3.,
|
||||
Matrix3::new(
|
||||
0, 0, 0,
|
||||
-1, -2, 0,
|
||||
1, 2, 0,
|
||||
),
|
||||
),
|
||||
(x, y) if (x, y + 1) == (bounds.x0, bounds.y1) => (
|
||||
2. / 3.,
|
||||
Matrix3::new(
|
||||
0, -1, 1,
|
||||
0, -2, 2,
|
||||
0, 0, 0,
|
||||
),
|
||||
2. / 3.,
|
||||
Matrix3::new(
|
||||
0, -2, -1,
|
||||
0, 2, 1,
|
||||
0, 0, 0,
|
||||
),
|
||||
),
|
||||
(x, y) if (x + 1, y + 1) == (bounds.x1, bounds.y1) => (
|
||||
2. / 3.,
|
||||
Matrix3::new(
|
||||
-1, 1, 0,
|
||||
-2, 2, 0,
|
||||
0, 0, 0,
|
||||
),
|
||||
2. / 3.,
|
||||
Matrix3::new(
|
||||
-1, -2, 0,
|
||||
1, 2, 0,
|
||||
0, 0, 0,
|
||||
),
|
||||
),
|
||||
(_, y) if y == bounds.y0 => (
|
||||
1. / 3.,
|
||||
Matrix3::new(
|
||||
0, 0, 0,
|
||||
-2, 0, 2,
|
||||
-1, 0, 1,
|
||||
),
|
||||
1. / 2.,
|
||||
Matrix3::new(
|
||||
0, 0, 0,
|
||||
-1, -2, -1,
|
||||
1, 2, 1,
|
||||
),
|
||||
),
|
||||
(x, _) if x == bounds.x0 => (
|
||||
1. / 2.,
|
||||
Matrix3::new(
|
||||
0, -1, 1,
|
||||
0, -2, 2,
|
||||
0, -1, 1,
|
||||
),
|
||||
1. / 3.,
|
||||
Matrix3::new(
|
||||
0, -2, -1,
|
||||
0, 0, 0,
|
||||
0, 2, 1,
|
||||
),
|
||||
),
|
||||
(x, _) if x + 1 == bounds.x1 => (
|
||||
1. / 2.,
|
||||
Matrix3::new(
|
||||
-1, 1, 0,
|
||||
-2, 2, 0,
|
||||
-1, 1, 0,
|
||||
),
|
||||
1. / 3.,
|
||||
Matrix3::new(
|
||||
-1, -2, 0,
|
||||
0, 0, 0,
|
||||
1, 2, 0,
|
||||
),
|
||||
),
|
||||
(_, y) if y + 1 == bounds.y1 => (
|
||||
1. / 3.,
|
||||
Matrix3::new(
|
||||
-1, 0, 1,
|
||||
-2, 0, 2,
|
||||
0, 0, 0,
|
||||
),
|
||||
1. / 2.,
|
||||
Matrix3::new(
|
||||
-1, -2, -1,
|
||||
1, 2, 1,
|
||||
0, 0, 0,
|
||||
),
|
||||
),
|
||||
_ => (
|
||||
1. / 4.,
|
||||
Matrix3::new(
|
||||
-1, 0, 1,
|
||||
-2, 0, 2,
|
||||
-1, 0, 1,
|
||||
),
|
||||
1. / 4.,
|
||||
Matrix3::new(
|
||||
-1, -2, -1,
|
||||
0, 0, 0,
|
||||
1, 2, 1,
|
||||
),
|
||||
),
|
||||
};
|
||||
|
||||
let kernel_bounds = IRect::new(x as i32 - 1, y as i32 - 1, x as i32 + 2, y as i32 + 2);
|
||||
|
||||
let mut nx = 0;
|
||||
let mut ny = 0;
|
||||
for (x, y, pixel) in PixelRectangle::within(surface, bounds, kernel_bounds, EdgeMode::None) {
|
||||
let kernel_x = (x - kernel_bounds.x0) as usize;
|
||||
let kernel_y = (y - kernel_bounds.y0) as usize;
|
||||
|
||||
nx += i16::from(pixel.a) * kx[(kernel_y, kernel_x)];
|
||||
ny += i16::from(pixel.a) * ky[(kernel_y, kernel_x)];
|
||||
}
|
||||
|
||||
// Negative nx and ny to account for the different coordinate system.
|
||||
Normal {
|
||||
factor: Vector2::new(factor_x, factor_y),
|
||||
normal: Vector2::new(-nx, -ny),
|
||||
}
|
||||
}
|
||||
|
||||
const SURFACE_SIDE: i32 = 512;
|
||||
const BOUNDS: IRect = IRect {
|
||||
x0: 64,
|
||||
y0: 64,
|
||||
x1: 64 + 64,
|
||||
y1: 64 + 64,
|
||||
};
|
||||
|
||||
fn bench_normal(c: &mut Criterion) {
|
||||
c.bench_function("normal", |b| {
|
||||
let surface =
|
||||
SharedImageSurface::empty(SURFACE_SIDE, SURFACE_SIDE, SurfaceType::SRgb).unwrap();
|
||||
|
||||
b.iter(|| {
|
||||
let mut z = 0;
|
||||
for (x, y, _pixel) in Pixels::within(&surface, BOUNDS) {
|
||||
let n = normal(&surface, BOUNDS, x, y);
|
||||
z += n.normal.x;
|
||||
}
|
||||
z
|
||||
})
|
||||
});
|
||||
|
||||
c.bench_function("normal unrolled", |b| {
|
||||
let surface =
|
||||
SharedImageSurface::empty(SURFACE_SIDE, SURFACE_SIDE, SurfaceType::SRgb).unwrap();
|
||||
|
||||
b.iter(|| {
|
||||
let mut z = 0;
|
||||
|
||||
// Top left.
|
||||
{
|
||||
let n = Normal::top_left(&surface, BOUNDS);
|
||||
z += n.normal.x;
|
||||
}
|
||||
|
||||
// Top right.
|
||||
{
|
||||
let n = Normal::top_right(&surface, BOUNDS);
|
||||
z += n.normal.x;
|
||||
}
|
||||
|
||||
// Bottom left.
|
||||
{
|
||||
let n = Normal::bottom_left(&surface, BOUNDS);
|
||||
z += n.normal.x;
|
||||
}
|
||||
|
||||
// Bottom right.
|
||||
{
|
||||
let n = Normal::bottom_right(&surface, BOUNDS);
|
||||
z += n.normal.x;
|
||||
}
|
||||
|
||||
// Top row.
|
||||
for x in BOUNDS.x0 as u32 + 1..BOUNDS.x1 as u32 - 1 {
|
||||
let n = Normal::top_row(&surface, BOUNDS, x);
|
||||
z += n.normal.x;
|
||||
}
|
||||
|
||||
// Bottom row.
|
||||
for x in BOUNDS.x0 as u32 + 1..BOUNDS.x1 as u32 - 1 {
|
||||
let n = Normal::bottom_row(&surface, BOUNDS, x);
|
||||
z += n.normal.x;
|
||||
}
|
||||
|
||||
// Left column.
|
||||
for y in BOUNDS.y0 as u32 + 1..BOUNDS.y1 as u32 - 1 {
|
||||
let n = Normal::left_column(&surface, BOUNDS, y);
|
||||
z += n.normal.x;
|
||||
}
|
||||
|
||||
// Right column.
|
||||
for y in BOUNDS.y0 as u32 + 1..BOUNDS.y1 as u32 - 1 {
|
||||
let n = Normal::right_column(&surface, BOUNDS, y);
|
||||
z += n.normal.x;
|
||||
}
|
||||
|
||||
// Interior pixels.
|
||||
for y in BOUNDS.y0 as u32 + 1..BOUNDS.y1 as u32 - 1 {
|
||||
for x in BOUNDS.x0 as u32 + 1..BOUNDS.x1 as u32 - 1 {
|
||||
let n = Normal::interior(&surface, BOUNDS, x, y);
|
||||
z += n.normal.x;
|
||||
}
|
||||
}
|
||||
|
||||
z
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
criterion_group!(benches, bench_normal);
|
||||
criterion_main!(benches);
|
||||
74
rsvg/benches/path_parser.rs
Normal file
74
rsvg/benches/path_parser.rs
Normal file
@@ -0,0 +1,74 @@
|
||||
use criterion::{Criterion, criterion_group, criterion_main};
|
||||
use std::hint::black_box;
|
||||
|
||||
use rsvg::bench_only::Lexer;
|
||||
use rsvg::bench_only::PathBuilder;
|
||||
|
||||
static INPUT: &str = "M10 20 C 30,40 50 60-70,80,90 100,110 120,130,140";
|
||||
|
||||
static BYTES: &[u8; 49] = b"M10 20 C 30,40 50 60-70,80,90 100,110 120,130,140";
|
||||
|
||||
static SLICE_EDGES: [(usize, usize); 14] = [
|
||||
(1, 3),
|
||||
(4, 6),
|
||||
(9, 11),
|
||||
(12, 14),
|
||||
(15, 17),
|
||||
(18, 20),
|
||||
(20, 23),
|
||||
(24, 26),
|
||||
(27, 29),
|
||||
(30, 33),
|
||||
(34, 37),
|
||||
(38, 41),
|
||||
(42, 45),
|
||||
(46, 49),
|
||||
];
|
||||
|
||||
fn lex_path(input: &str) {
|
||||
let lexer = Lexer::new(black_box(input));
|
||||
|
||||
for (_pos, _token) in lexer {
|
||||
// no-op
|
||||
}
|
||||
}
|
||||
|
||||
fn path_parser(c: &mut Criterion) {
|
||||
c.bench_function("parse path into builder", |b| {
|
||||
let input = black_box(INPUT);
|
||||
|
||||
b.iter(|| {
|
||||
let mut builder = PathBuilder::default();
|
||||
let _ = builder.parse(input);
|
||||
});
|
||||
});
|
||||
|
||||
c.bench_function("lex str", |b| {
|
||||
let input = black_box(INPUT);
|
||||
|
||||
b.iter(|| {
|
||||
lex_path(input);
|
||||
});
|
||||
});
|
||||
|
||||
// look at how much time *just* the parse::<i32> part of the lexer should be taking...
|
||||
c.bench_function("std i32 parse (bytes)", |b| {
|
||||
let input = black_box(BYTES);
|
||||
let slice_boundaries = black_box(SLICE_EDGES);
|
||||
|
||||
b.iter(|| {
|
||||
for (a, b) in slice_boundaries.iter() {
|
||||
let a: usize = *a;
|
||||
let b: usize = *b;
|
||||
unsafe {
|
||||
let _ = std::str::from_utf8_unchecked(&input[a..b])
|
||||
.parse::<i32>()
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
criterion_group!(benches, path_parser);
|
||||
criterion_main!(benches);
|
||||
96
rsvg/benches/pixel_iterators.rs
Normal file
96
rsvg/benches/pixel_iterators.rs
Normal file
@@ -0,0 +1,96 @@
|
||||
use criterion::{Criterion, criterion_group, criterion_main};
|
||||
use std::hint::black_box;
|
||||
|
||||
use rsvg::bench_only::{ExclusiveImageSurface, IRect, Pixels, SharedImageSurface, SurfaceType};
|
||||
|
||||
const SURFACE_SIDE: i32 = 512;
|
||||
const BOUNDS: IRect = IRect {
|
||||
x0: 64,
|
||||
y0: 32,
|
||||
x1: 448,
|
||||
y1: 480,
|
||||
};
|
||||
|
||||
fn bench_pixel_iterators(c: &mut Criterion) {
|
||||
c.bench_function("pixel_iterators straightforward", |b| {
|
||||
let mut surface =
|
||||
ExclusiveImageSurface::new(SURFACE_SIDE, SURFACE_SIDE, SurfaceType::SRgb).unwrap();
|
||||
let stride = surface.stride() as i32;
|
||||
let data = surface.data();
|
||||
|
||||
let bounds = black_box(BOUNDS);
|
||||
|
||||
b.iter(|| {
|
||||
let mut r = 0usize;
|
||||
let mut g = 0usize;
|
||||
let mut b = 0usize;
|
||||
let mut a = 0usize;
|
||||
|
||||
for y in bounds.y_range() {
|
||||
for x in bounds.x_range() {
|
||||
let base = (y * stride + x * 4) as usize;
|
||||
|
||||
r += data[base] as usize;
|
||||
g += data[base + 1] as usize;
|
||||
b += data[base + 2] as usize;
|
||||
a += data[base + 3] as usize;
|
||||
}
|
||||
}
|
||||
|
||||
(r, g, b, a)
|
||||
})
|
||||
});
|
||||
|
||||
c.bench_function("pixel_iterators get_pixel", |b| {
|
||||
let surface =
|
||||
SharedImageSurface::empty(SURFACE_SIDE, SURFACE_SIDE, SurfaceType::SRgb).unwrap();
|
||||
|
||||
let bounds = black_box(BOUNDS);
|
||||
|
||||
b.iter(|| {
|
||||
let mut r = 0usize;
|
||||
let mut g = 0usize;
|
||||
let mut b = 0usize;
|
||||
let mut a = 0usize;
|
||||
|
||||
for y in bounds.y_range() {
|
||||
for x in bounds.x_range() {
|
||||
let pixel = surface.get_pixel(x as u32, y as u32);
|
||||
|
||||
r += pixel.r as usize;
|
||||
g += pixel.g as usize;
|
||||
b += pixel.b as usize;
|
||||
a += pixel.a as usize;
|
||||
}
|
||||
}
|
||||
|
||||
(r, g, b, a)
|
||||
})
|
||||
});
|
||||
|
||||
c.bench_function("pixel_iterators pixels", |b| {
|
||||
let surface =
|
||||
SharedImageSurface::empty(SURFACE_SIDE, SURFACE_SIDE, SurfaceType::SRgb).unwrap();
|
||||
|
||||
let bounds = black_box(BOUNDS);
|
||||
|
||||
b.iter(|| {
|
||||
let mut r = 0usize;
|
||||
let mut g = 0usize;
|
||||
let mut b = 0usize;
|
||||
let mut a = 0usize;
|
||||
|
||||
for (_x, _y, pixel) in Pixels::within(&surface, bounds) {
|
||||
r += pixel.r as usize;
|
||||
g += pixel.g as usize;
|
||||
b += pixel.b as usize;
|
||||
a += pixel.a as usize;
|
||||
}
|
||||
|
||||
(r, g, b, a)
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
criterion_group!(benches, bench_pixel_iterators);
|
||||
criterion_main!(benches);
|
||||
57
rsvg/benches/pixel_ops.rs
Normal file
57
rsvg/benches/pixel_ops.rs
Normal file
@@ -0,0 +1,57 @@
|
||||
use criterion::{Criterion, criterion_group, criterion_main};
|
||||
use std::hint::black_box;
|
||||
|
||||
use rsvg::bench_only::{Pixel, PixelOps};
|
||||
|
||||
const OTHER: Pixel = Pixel {
|
||||
r: 0x10,
|
||||
g: 0x20,
|
||||
b: 0x30,
|
||||
a: 0x40,
|
||||
};
|
||||
const N: usize = 1024;
|
||||
|
||||
fn make_pixels(n: usize) -> Vec<Pixel> {
|
||||
(0..n)
|
||||
.map(|i| Pixel {
|
||||
r: (i / 2) as u8,
|
||||
g: (i / 3) as u8,
|
||||
b: (i / 4) as u8,
|
||||
a: i as u8,
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn bench_op<F>(pixels: &[Pixel], op: F)
|
||||
where
|
||||
F: Fn(&Pixel) -> Pixel,
|
||||
{
|
||||
let result: Vec<Pixel> = pixels.iter().map(op).collect();
|
||||
black_box(result);
|
||||
}
|
||||
|
||||
fn bench_pixel_ops(c: &mut Criterion) {
|
||||
c.bench_function("pixel_diff", |b| {
|
||||
let pixels = black_box(make_pixels(N));
|
||||
let other = black_box(OTHER);
|
||||
b.iter(|| bench_op(&pixels, |pixel| pixel.diff(&other)))
|
||||
});
|
||||
|
||||
c.bench_function("pixel_to_luminance_mask", |b| {
|
||||
let pixels = black_box(make_pixels(N));
|
||||
b.iter(|| bench_op(&pixels, |pixel| pixel.to_luminance_mask()))
|
||||
});
|
||||
|
||||
c.bench_function("pixel_premultiply", |b| {
|
||||
let pixels = black_box(make_pixels(N));
|
||||
b.iter(|| bench_op(&pixels, |pixel| pixel.premultiply()))
|
||||
});
|
||||
|
||||
c.bench_function("pixel_unpremultiply", |b| {
|
||||
let pixels = black_box(make_pixels(N));
|
||||
b.iter(|| bench_op(&pixels, |pixel| pixel.unpremultiply()))
|
||||
});
|
||||
}
|
||||
|
||||
criterion_group!(benches, bench_pixel_ops);
|
||||
criterion_main!(benches);
|
||||
50
rsvg/benches/srgb.rs
Normal file
50
rsvg/benches/srgb.rs
Normal file
@@ -0,0 +1,50 @@
|
||||
use criterion::{Criterion, criterion_group, criterion_main};
|
||||
use std::hint::black_box;
|
||||
|
||||
use rsvg::bench_only::{
|
||||
ExclusiveImageSurface, IRect, ImageSurfaceDataExt, Pixel, SurfaceType, linearize,
|
||||
map_unpremultiplied_components_loop,
|
||||
};
|
||||
|
||||
const SURFACE_SIDE: i32 = 512;
|
||||
const BOUNDS: IRect = IRect {
|
||||
x0: 64,
|
||||
y0: 32,
|
||||
x1: 448,
|
||||
y1: 480,
|
||||
};
|
||||
|
||||
fn bench_srgb_linearization(c: &mut Criterion) {
|
||||
c.bench_function("srgb map_unpremultiplied_components", |b| {
|
||||
let mut surface =
|
||||
ExclusiveImageSurface::new(SURFACE_SIDE, SURFACE_SIDE, SurfaceType::LinearRgb).unwrap();
|
||||
|
||||
// Fill the surface with non-zero alpha (otherwise linearization is a no-op).
|
||||
surface.modify(&mut |data, stride| {
|
||||
for y in BOUNDS.y_range() {
|
||||
for x in BOUNDS.x_range() {
|
||||
let pixel = Pixel {
|
||||
r: 0,
|
||||
g: 0,
|
||||
b: 0,
|
||||
a: 127,
|
||||
};
|
||||
|
||||
data.set_pixel(stride, pixel, x as u32, y as u32);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let surface = surface.share().unwrap();
|
||||
let mut output_surface =
|
||||
ExclusiveImageSurface::new(SURFACE_SIDE, SURFACE_SIDE, SurfaceType::SRgb).unwrap();
|
||||
let bounds = black_box(BOUNDS);
|
||||
|
||||
b.iter(|| {
|
||||
map_unpremultiplied_components_loop(&surface, &mut output_surface, bounds, linearize);
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
criterion_group!(benches, bench_srgb_linearization);
|
||||
criterion_main!(benches);
|
||||
Reference in New Issue
Block a user