Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 23 additions & 9 deletions sparse_strips/vello_cpu/src/fine/common/image.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
use crate::fine::macros::{f32x16_painter, u8x16_painter};
use crate::fine::{PosExt, Splat4thExt, u8_to_f32};
use crate::kurbo::Point;
use crate::peniko::ImageQuality;
use vello_common::encode::EncodedImage;
use vello_common::fearless_simd::{Bytes, Simd, SimdBase, SimdFloat, f32x4, f32x16, u8x16, u32x4};
use vello_common::pixmap::Pixmap;
Expand Down Expand Up @@ -145,13 +144,21 @@ impl<S: Simd> Iterator for NNImagePainter<'_, S> {
u8x16_painter!(NNImagePainter<'_, S>);

/// A painter for images with bilinear or bicubic filtering.
///
/// The painter is generic over sampler quality using the const-generic `QUALITY` parameter.
///
/// - Set `QUALITY` to `1` for bilinear sampling; or
/// - set `QUALITY` to `2` for bicubic sampling.
///
/// These values for `QUALITY` are the same numeric values as defined by
/// [`crate::peniko::ImageQuality`].
#[derive(Debug)]
pub(crate) struct FilteredImagePainter<'a, S: Simd> {
pub(crate) struct FilteredImagePainter<'a, S: Simd, const QUALITY: u8> {
data: ImagePainterData<'a, S>,
simd: S,
}

impl<'a, S: Simd> FilteredImagePainter<'a, S> {
impl<'a, S: Simd, const QUALITY: u8> FilteredImagePainter<'a, S, QUALITY> {
pub(crate) fn new(
simd: S,
image: &'a EncodedImage,
Expand All @@ -165,7 +172,7 @@ impl<'a, S: Simd> FilteredImagePainter<'a, S> {
}
}

impl<S: Simd> Iterator for FilteredImagePainter<'_, S> {
impl<S: Simd, const QUALITY: u8> Iterator for FilteredImagePainter<'_, S, QUALITY> {
type Item = f32x16<S>;

fn next(&mut self) -> Option<Self::Item> {
Expand Down Expand Up @@ -233,9 +240,9 @@ impl<S: Simd> Iterator for FilteredImagePainter<'_, S> {
};
}

match self.data.image.sampler.quality {
ImageQuality::Low => unreachable!(),
ImageQuality::Medium => {
match QUALITY {
// medium quality: bilinear
1 => {
// <https://github.com/google/skia/blob/220738774f7a0ce4a6c7bd17519a336e5e5dea5b/src/opts/SkRasterPipeline_opts.h#L5039-L5078>
let cx = [1.0 - x_fract, x_fract];
let cy = [1.0 - y_fract, y_fract];
Expand Down Expand Up @@ -265,7 +272,8 @@ impl<S: Simd> Iterator for FilteredImagePainter<'_, S> {

interpolated_color *= f32x16::splat(self.simd, 1.0 / 255.0);
}
ImageQuality::High => {
// high quality: bicubic
2 => {
// Compare to <https://github.com/google/skia/blob/84ff153b0093fc83f6c77cd10b025c06a12c5604/src/opts/SkRasterPipeline_opts.h#L5030-L5075>.
let cx = weights(self.simd, x_fract);
let cy = weights(self.simd, y_fract);
Expand Down Expand Up @@ -317,6 +325,9 @@ impl<S: Simd> Iterator for FilteredImagePainter<'_, S> {
.max(f32x16::splat(self.simd, 0.0))
.min(alphas);
}
_ => panic!(
"Unknown value for `FilteredImagePainter`'s const-generic `QUALITY` parameter. Expected `1` for bilinear or `2` for bicubic, got: `{QUALITY}`."
),
}

self.data.cur_pos += self.data.image.x_advance;
Expand All @@ -325,7 +336,10 @@ impl<S: Simd> Iterator for FilteredImagePainter<'_, S> {
}
}

f32x16_painter!(FilteredImagePainter<'_, S>);
// Bilinear
f32x16_painter!(FilteredImagePainter<'_, S, 1>);
// Bicubic
f32x16_painter!(FilteredImagePainter<'_, S, 2>);

/// Common data used by different image painters
#[derive(Debug)]
Expand Down
4 changes: 2 additions & 2 deletions sparse_strips/vello_cpu/src/fine/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ pub trait FineKernel<S: Simd>: Send + Sync + 'static {
) -> impl Painter + 'a {
simd.vectorize(
#[inline(always)]
|| FilteredImagePainter::new(simd, image, pixmap, start_x, start_y),
|| FilteredImagePainter::<S, 1>::new(simd, image, pixmap, start_x, start_y),
)
}

Expand All @@ -351,7 +351,7 @@ pub trait FineKernel<S: Simd>: Send + Sync + 'static {
) -> impl Painter + 'a {
simd.vectorize(
#[inline(always)]
|| FilteredImagePainter::new(simd, image, pixmap, start_x, start_y),
|| FilteredImagePainter::<S, 2>::new(simd, image, pixmap, start_x, start_y),
)
}

Expand Down