blob: 4cd6e231b28140450d8e22ae39110ba4d5008296 [file] [edit]
// Copyright 2026 the Vello Authors
// SPDX-License-Identifier: Apache-2.0 OR MIT
use criterion::{BatchSize, Criterion, black_box};
use vello_common::peniko::ImageAlphaType;
use vello_common::pixmap::{PixelMetadata, Pixmap};
const WIDTH: u16 = 1920;
const HEIGHT: u16 = 1080;
const OPAQUE_BLUE: [u8; 4] = [0, 0, 255, 255];
const TRANSLUCENT_BLUE: [u8; 4] = [0, 0, 255, 128];
pub fn pixmap(c: &mut Criterion) {
let pixel_count = usize::from(WIDTH) * usize::from(HEIGHT);
let opaque_input = ("opaque", OPAQUE_BLUE.repeat(pixel_count));
let mut unpremultiply_inputs = vec![("translucent", TRANSLUCENT_BLUE.repeat(pixel_count))];
if crate::EXTENDED {
unpremultiply_inputs.push(("interleaved", interleaved_pixels(pixel_count)));
unpremultiply_inputs.push(("mixed_lanes", mixed_lane_pixels(pixel_count)));
}
let mut group = c.benchmark_group("pixmap/premultiply");
for (name, rgba) in std::iter::once(&opaque_input).chain(&unpremultiply_inputs) {
group.bench_function(*name, |b| {
b.iter_batched(
|| rgba.clone(),
|rgba| {
black_box(Pixmap::from_parts(
rgba,
WIDTH,
HEIGHT,
PixelMetadata::new(ImageAlphaType::Alpha, true),
));
},
BatchSize::LargeInput,
);
});
}
group.finish();
let pixmaps = unpremultiply_inputs
.into_iter()
.map(|(name, rgba)| {
(
name,
Pixmap::from_parts(
rgba,
WIDTH,
HEIGHT,
PixelMetadata::new(ImageAlphaType::Alpha, true),
),
)
})
.collect::<Vec<_>>();
let mut group = c.benchmark_group("pixmap/unpremultiply");
for (name, pixmap) in &pixmaps {
group.bench_function(*name, |b| {
b.iter_batched(
|| pixmap.clone(),
|pixmap| black_box(pixmap.take_rgba8(ImageAlphaType::Alpha)),
BatchSize::LargeInput,
);
});
}
group.finish();
let opaque_pixmap = Pixmap::from_parts(
OPAQUE_BLUE.repeat(pixel_count),
WIDTH,
HEIGHT,
PixelMetadata::new(ImageAlphaType::AlphaPremultiplied, false),
);
let mut group = c.benchmark_group("pixmap/rgba_to_rgb");
group.bench_function("opaque", |b| {
b.iter_batched(
|| opaque_pixmap.clone(),
|pixmap| black_box(pixmap.try_take_rgb8(ImageAlphaType::Alpha)),
BatchSize::LargeInput,
);
});
group.finish();
}
fn interleaved_pixels(pixel_count: usize) -> Vec<u8> {
let mut rgba = Vec::with_capacity(pixel_count * 4);
for index in 0..pixel_count {
let pixel = if (index / 16).is_multiple_of(2) {
TRANSLUCENT_BLUE
} else {
OPAQUE_BLUE
};
rgba.extend_from_slice(&pixel);
}
rgba
}
fn mixed_lane_pixels(pixel_count: usize) -> Vec<u8> {
let mut rgba = Vec::with_capacity(pixel_count * 4);
for index in 0..pixel_count {
let pixel = if (index / 8).is_multiple_of(2) {
TRANSLUCENT_BLUE
} else {
OPAQUE_BLUE
};
rgba.extend_from_slice(&pixel);
}
rgba
}