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
24 changes: 13 additions & 11 deletions src/mask.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ use tiny_skia_path::{IntRect, IntSize, Path, Scalar, Transform};
use crate::geom::IntSizeExt;
use crate::painter::DrawTiler;
use crate::pipeline::RasterPipelineBlitter;
use crate::pixmap::SubPixmapMut;
use crate::scan;
use crate::{FillRule, PixmapRef};

Expand Down Expand Up @@ -157,21 +156,19 @@ impl Mask {
})
}

pub(crate) fn as_subpixmap(&mut self) -> SubPixmapMut<'_> {
SubPixmapMut {
size: self.size,
pub(crate) fn as_submask_mut(&mut self) -> SubMaskMut<'_> {
SubMaskMut {
real_width: self.size.width() as usize,
data: &mut self.data,
}
}

pub(crate) fn subpixmap(&mut self, rect: IntRect) -> Option<SubPixmapMut<'_>> {
pub(crate) fn submask_mut(&mut self, rect: IntRect) -> Option<SubMaskMut<'_>> {
let rect = self.size.to_int_rect(0, 0).intersect(&rect)?;
let row_bytes = self.width() as usize;
let offset = rect.top() as usize * row_bytes + rect.left() as usize;

Some(SubPixmapMut {
size: rect.size(),
Some(SubMaskMut {
real_width: self.size.width() as usize,
data: &mut self.data[offset..],
})
Expand Down Expand Up @@ -294,12 +291,12 @@ impl Mask {
};

let clip_rect = tile.size().to_screen_int_rect(0, 0);
let mut subpix = match self.subpixmap(tile.to_int_rect()) {
let mut submask = match self.submask_mut(tile.to_int_rect()) {
Some(v) => v,
None => continue, // technically unreachable
};

let mut blitter = match RasterPipelineBlitter::new_mask(&mut subpix) {
let mut blitter = match RasterPipelineBlitter::new_mask(&mut submask) {
Some(v) => v,
None => continue, // nothing to do, all good
};
Expand All @@ -321,8 +318,8 @@ impl Mask {
}
} else {
let clip_rect = self.size().to_screen_int_rect(0, 0);
let mut subpix = self.as_subpixmap();
let mut blitter = match RasterPipelineBlitter::new_mask(&mut subpix) {
let mut submask = self.as_submask_mut();
let mut blitter = match RasterPipelineBlitter::new_mask(&mut submask) {
Some(v) => v,
None => return, // nothing to do, all good
};
Expand Down Expand Up @@ -402,3 +399,8 @@ impl<'a> SubMaskRef<'a> {
}
}
}

pub(crate) struct SubMaskMut<'a> {
pub(crate) data: &'a mut [u8],
pub(crate) real_width: usize,
}
4 changes: 2 additions & 2 deletions src/painter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use tiny_skia_path::{PathStroker, Scalar, SCALAR_MAX};

use crate::geom::ScreenIntRect;
use crate::mask::SubMaskRef;
use crate::pipeline::{RasterPipelineBlitter, RasterPipelineBuilder};
use crate::pipeline::{GenericPixmapMut, RasterPipelineBlitter, RasterPipelineBuilder};
use crate::pixmap::SubPixmapMut;
use crate::scan;

Expand Down Expand Up @@ -536,7 +536,7 @@ impl PixmapMut<'_> {
pipeline::AAMaskCtx::default(),
mask.as_submask().mask_ctx(),
pixmap_src,
&mut self.as_subpixmap(),
GenericPixmapMut::from_pixmap(&mut self.as_subpixmap()),
);
}
}
Expand Down
76 changes: 45 additions & 31 deletions src/pipeline/blitter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,33 @@ use crate::alpha_runs::AlphaRun;
use crate::blitter::{Blitter, Mask};
use crate::color::AlphaU8;
use crate::geom::ScreenIntRect;
use crate::mask::SubMaskRef;
use crate::mask::{SubMaskMut, SubMaskRef};
use crate::math::LENGTH_U32_ONE;
use crate::pipeline::{self, RasterPipeline, RasterPipelineBuilder};
use crate::pipeline::{self, GenericPixmapMut, RasterPipeline, RasterPipelineBuilder};
use crate::pixmap::SubPixmapMut;

enum PipelineDest<'a, 'b: 'a> {
Mask(&'a mut SubMaskMut<'b>),
Pixmap(&'a mut SubPixmapMut<'b>),
}

impl<'a: 'c, 'b: 'a, 'c> PipelineDest<'a, 'b> {
fn to_generic_pixmap(&'c mut self) -> GenericPixmapMut<'c> {
match self {
PipelineDest::Mask(mask) => GenericPixmapMut::from_mask(mask),
PipelineDest::Pixmap(pixmap) => GenericPixmapMut::from_pixmap(pixmap),
}
}
}

pub struct RasterPipelineBlitter<'a, 'b: 'a> {
mask: Option<SubMaskRef<'a>>,
pixmap_src: PixmapRef<'a>,
pixmap: &'a mut SubPixmapMut<'b>,
pixmap_dst: PipelineDest<'a, 'b>,
memset2d_color: Option<PremultipliedColorU8>,
blit_anti_h_rp: RasterPipeline,
blit_rect_rp: RasterPipeline,
blit_mask_rp: RasterPipeline,
is_mask: bool,
}

impl<'a, 'b: 'a> RasterPipelineBlitter<'a, 'b> {
Expand Down Expand Up @@ -202,16 +215,15 @@ impl<'a, 'b: 'a> RasterPipelineBlitter<'a, 'b> {
Some(RasterPipelineBlitter {
mask,
pixmap_src,
pixmap,
pixmap_dst: PipelineDest::Pixmap(pixmap),
memset2d_color,
blit_anti_h_rp,
blit_rect_rp,
blit_mask_rp,
is_mask: false,
})
}

pub fn new_mask(pixmap: &'a mut SubPixmapMut<'b>) -> Option<Self> {
pub fn new_mask(mask: &'a mut SubMaskMut<'b>) -> Option<Self> {
let color = Color::WHITE.premultiply();

let memset2d_color = Some(color.to_color_u8());
Expand Down Expand Up @@ -244,12 +256,11 @@ impl<'a, 'b: 'a> RasterPipelineBlitter<'a, 'b> {
Some(RasterPipelineBlitter {
mask: None,
pixmap_src: PixmapRef::from_bytes(&[0, 0, 0, 0], 1, 1).unwrap(),
pixmap,
pixmap_dst: PipelineDest::Mask(mask),
memset2d_color,
blit_anti_h_rp,
blit_rect_rp,
blit_mask_rp,
is_mask: true,
})
}
}
Expand Down Expand Up @@ -283,7 +294,7 @@ impl Blitter for RasterPipelineBlitter<'_, '_> {
pipeline::AAMaskCtx::default(),
mask_ctx,
self.pixmap_src,
self.pixmap,
self.pixmap_dst.to_generic_pixmap(),
);
}
}
Expand Down Expand Up @@ -333,25 +344,23 @@ impl Blitter for RasterPipelineBlitter<'_, '_> {

fn blit_rect(&mut self, rect: &ScreenIntRect) {
if let Some(c) = self.memset2d_color {
if self.is_mask {
for y in 0..rect.height() {
let start = self
.pixmap
.offset(rect.x() as usize, (rect.y() + y) as usize);
let end = start + rect.width() as usize;
self.pixmap.data[start..end]
.iter_mut()
.for_each(|p| *p = c.alpha());
match &mut self.pixmap_dst {
PipelineDest::Mask(mask) => {
for y in 0..rect.height() {
let start = mask.real_width * ((rect.y() + y) as usize) + rect.x() as usize;
let end = start + rect.width() as usize;
mask.data[start..end].fill(c.alpha());
}
}
} else {
for y in 0..rect.height() {
let start = self
.pixmap
.offset(rect.x() as usize, (rect.y() + y) as usize);
let end = start + rect.width() as usize;
self.pixmap.pixels_mut()[start..end]
.iter_mut()
.for_each(|p| *p = c);
PipelineDest::Pixmap(pixmap) => {
for y in 0..rect.height() {
let start =
4 * pixmap.real_width * (rect.y() + y) as usize + 4 * rect.x() as usize;
let row_pixels = bytemuck::cast_slice_mut::<_, PremultipliedColorU8>(
&mut pixmap.data[start..start + 4 * rect.width() as usize],
);
row_pixels.fill(c);
}
}
}

Expand All @@ -365,7 +374,7 @@ impl Blitter for RasterPipelineBlitter<'_, '_> {
pipeline::AAMaskCtx::default(),
mask_ctx,
self.pixmap_src,
self.pixmap,
self.pixmap_dst.to_generic_pixmap(),
);
}

Expand All @@ -378,7 +387,12 @@ impl Blitter for RasterPipelineBlitter<'_, '_> {

let mask_ctx = self.mask.map(|c| c.mask_ctx()).unwrap_or_default();

self.blit_mask_rp
.run(clip, aa_mask_ctx, mask_ctx, self.pixmap_src, self.pixmap);
self.blit_mask_rp.run(
clip,
aa_mask_ctx,
mask_ctx,
self.pixmap_src,
self.pixmap_dst.to_generic_pixmap(),
);
}
}
6 changes: 3 additions & 3 deletions src/pipeline/highp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ and we're using a manual implementation.
use crate::{PremultipliedColorU8, SpreadMode, PixmapRef};

use crate::geom::ScreenIntRect;
use crate::pixmap::SubPixmapMut;
use crate::pipeline::GenericPixmapMut;
use crate::wide::{f32x8, i32x8, u32x8};

pub const STAGE_WIDTH: usize = 8;
Expand All @@ -29,7 +29,7 @@ pub struct Pipeline<'a, 'b: 'a> {
index: usize,
functions: &'a [StageFn],
pixmap_src: PixmapRef<'a>,
pixmap_dst: &'a mut SubPixmapMut<'b>,
pixmap_dst: GenericPixmapMut<'b>,
ctx: &'a mut super::Context, // TODO: remove mut
mask_ctx: super::MaskCtx<'a>,
aa_mask_ctx: super::AAMaskCtx,
Expand Down Expand Up @@ -151,7 +151,7 @@ pub fn start(
mask_ctx: super::MaskCtx,
ctx: &mut super::Context,
pixmap_src: PixmapRef,
pixmap_dst: &mut SubPixmapMut,
pixmap_dst: GenericPixmapMut,
) {
let mut p = Pipeline {
index: 0,
Expand Down
6 changes: 3 additions & 3 deletions src/pipeline/lowp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ On ARM AArch64 the story is different and explicit SIMD make our code up to 2-3x

use crate::PremultipliedColorU8;

use crate::pixmap::SubPixmapMut;
use crate::pipeline::GenericPixmapMut;
use crate::wide::{f32x8, u16x16, f32x16};
use crate::geom::ScreenIntRect;

Expand All @@ -41,7 +41,7 @@ pub type StageFn = fn(p: &mut Pipeline);
pub struct Pipeline<'a, 'b: 'a> {
index: usize,
functions: &'a [StageFn],
pixmap: &'a mut SubPixmapMut<'b>,
pixmap: GenericPixmapMut<'b>,
mask_ctx: super::MaskCtx<'a>,
aa_mask_ctx: super::AAMaskCtx,
ctx: &'a mut super::Context,
Expand Down Expand Up @@ -169,7 +169,7 @@ pub fn start(
aa_mask_ctx: super::AAMaskCtx,
mask_ctx: super::MaskCtx,
ctx: &mut super::Context,
pixmap: &mut SubPixmapMut,
pixmap: GenericPixmapMut,
) {
let mut p = Pipeline {
index: 0,
Expand Down
49 changes: 37 additions & 12 deletions src/pipeline/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ use arrayvec::ArrayVec;

use tiny_skia_path::NormalizedF32;

use crate::mask::SubMaskMut;
use crate::{Color, PremultipliedColor, PremultipliedColorU8, SpreadMode};
use crate::{PixmapRef, Transform};

Expand Down Expand Up @@ -169,7 +170,27 @@ impl PixmapRef<'_> {
}
}

impl SubPixmapMut<'_> {
/// The target of a pipeline, can be either from a PixmapMut or a MaskMut. The pixel format
/// is left implicit.
pub(crate) struct GenericPixmapMut<'a> {
pub(crate) data: &'a mut [u8],
pub(crate) real_width: usize,
}

impl<'b> GenericPixmapMut<'b> {
pub(crate) fn from_pixmap<'a: 'b>(pixmap: &'b mut SubPixmapMut<'a>) -> Self {
Self {
data: pixmap.data,
real_width: pixmap.real_width,
}
}
pub(crate) fn from_mask<'a: 'b>(mask: &'b mut SubMaskMut<'a>) -> Self {
Self {
data: mask.data,
real_width: mask.real_width,
}
}

#[inline(always)]
pub(crate) fn offset(&self, dx: usize, dy: usize) -> usize {
self.real_width * dy + dx
Expand All @@ -178,13 +199,7 @@ impl SubPixmapMut<'_> {
#[inline(always)]
pub(crate) fn slice_at_xy(&mut self, dx: usize, dy: usize) -> &mut [PremultipliedColorU8] {
let offset = self.offset(dx, dy);
&mut self.pixels_mut()[offset..]
}

#[inline(always)]
pub(crate) fn slice_mask_at_xy(&mut self, dx: usize, dy: usize) -> &mut [u8] {
let offset = self.offset(dx, dy);
&mut self.data[offset..]
&mut bytemuck::cast_slice_mut(self.data)[offset..]
}

#[inline(always)]
Expand All @@ -194,7 +209,9 @@ impl SubPixmapMut<'_> {
dy: usize,
) -> &mut [PremultipliedColorU8; highp::STAGE_WIDTH] {
let offset = self.offset(dx, dy);
self.pixels_mut()[offset..].first_chunk_mut().unwrap()
bytemuck::cast_slice_mut(self.data)[offset..]
.first_chunk_mut()
.unwrap()
}

#[inline(always)]
Expand All @@ -204,7 +221,15 @@ impl SubPixmapMut<'_> {
dy: usize,
) -> &mut [PremultipliedColorU8; lowp::STAGE_WIDTH] {
let offset = self.offset(dx, dy);
self.pixels_mut()[offset..].first_chunk_mut().unwrap()
bytemuck::cast_slice_mut(self.data)[offset..]
.first_chunk_mut()
.unwrap()
}

#[inline(always)]
pub(crate) fn slice_mask_at_xy(&mut self, dx: usize, dy: usize) -> &mut [u8] {
let offset = self.offset(dx, dy);
&mut self.data[offset..]
}

#[inline(always)]
Expand Down Expand Up @@ -508,7 +533,7 @@ impl RasterPipeline {
aa_mask_ctx: AAMaskCtx,
mask_ctx: MaskCtx,
pixmap_src: PixmapRef,
pixmap_dst: &mut SubPixmapMut,
pixmap_dst: GenericPixmapMut,
) {
match self.kind {
RasterPipelineKind::High {
Expand Down Expand Up @@ -578,7 +603,7 @@ mod blend_tests {
let mut p = p.compile();
let rect = pixmap.size().to_screen_int_rect(0, 0);
p.run(&rect, AAMaskCtx::default(), MaskCtx::default(), pixmap_src,
&mut pixmap.as_mut().as_subpixmap());
GenericPixmapMut::from_pixmap(&mut pixmap.as_mut().as_subpixmap()));

assert_eq!(
pixmap.as_ref().pixel(0, 0).unwrap(),
Expand Down
7 changes: 0 additions & 7 deletions src/pixmap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -580,13 +580,6 @@ pub struct SubPixmapMut<'a> {
pub real_width: usize,
}

impl SubPixmapMut<'_> {
/// Returns a mutable slice of pixels.
pub fn pixels_mut(&mut self) -> &mut [PremultipliedColorU8] {
bytemuck::cast_slice_mut(self.data)
}
}

/// Returns minimum bytes per row as usize.
///
/// Pixmap's maximum value for row bytes must fit in 31 bits.
Expand Down
Loading