Skip to content

Commit bb4f2b0

Browse files
committed
Add a set_background method
1 parent 39ec863 commit bb4f2b0

12 files changed

Lines changed: 237 additions & 41 deletions

File tree

sparse_strips/vello_common/src/coarse.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,13 @@ impl<const MODE: u8> Wide<MODE> {
423423
self.batch_count = 0;
424424
}
425425

426+
/// Return the background of the wide tile composited on top of the provided background.
427+
pub fn tile_bg(&self, x: u16, y: u16, background: PremulColor) -> PremulColor {
428+
let bg = self.get(x, y).bg;
429+
430+
bg.composite(background)
431+
}
432+
426433
/// Return the number of horizontal tiles.
427434
pub fn width_tiles(&self) -> u16 {
428435
self.width.div_ceil(WideTile::WIDTH)

sparse_strips/vello_common/src/paint.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,25 @@ impl PremulColor {
236236
pub fn is_opaque(&self) -> bool {
237237
self.premul_f32.components[3] == 1.0
238238
}
239+
240+
/// Return whether the color is fully transparent.
241+
pub fn is_transparent(&self) -> bool {
242+
self.premul_f32.components[3] == 0.0
243+
}
244+
245+
/// Composite this color over the given background using source-over.
246+
pub fn composite(self, background: Self) -> Self {
247+
let src = self.premul_f32.components;
248+
let bg = background.premul_f32.components;
249+
let inv_src_alpha = 1.0 - src[3];
250+
251+
Self::from_premul_color(peniko::color::PremulColor::new([
252+
src[0] + bg[0] * inv_src_alpha,
253+
src[1] + bg[1] * inv_src_alpha,
254+
src[2] + bg[2] * inv_src_alpha,
255+
src[3] + bg[3] * inv_src_alpha,
256+
]))
257+
}
239258
}
240259

241260
/// How tint color is applied to an image.

sparse_strips/vello_cpu/src/dispatch/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use vello_common::coarse::Wide;
1313
use vello_common::encode::EncodedPaint;
1414
use vello_common::filter_effects::Filter;
1515
use vello_common::mask::Mask;
16-
use vello_common::paint::{ImageResolver, Paint};
16+
use vello_common::paint::{ImageResolver, Paint, PremulColor};
1717

1818
pub(crate) trait Dispatcher: Debug + Send + Sync {
1919
fn wide(&self) -> &Wide;
@@ -76,6 +76,7 @@ pub(crate) trait Dispatcher: Debug + Send + Sync {
7676
render_mode: RenderMode,
7777
width: u16,
7878
height: u16,
79+
background: PremulColor,
7980
encoded_paints: &[EncodedPaint],
8081
image_resolver: &dyn ImageResolver,
8182
);

sparse_strips/vello_cpu/src/dispatch/multi_threaded.rs

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ use vello_common::fearless_simd::{Level, Simd, dispatch};
2828
use vello_common::filter_effects::Filter;
2929
use vello_common::geometry::RectU16;
3030
use vello_common::mask::Mask;
31-
use vello_common::paint::{ImageResolver, Paint};
31+
use vello_common::paint::{ImageResolver, Paint, PremulColor};
3232
use vello_common::render_graph::RenderGraph;
3333
use vello_common::strip::Strip;
3434
use vello_common::strip_generator::StripGenerator;
@@ -166,11 +166,12 @@ impl MultiThreadedDispatcher {
166166
buffer: &mut [u8],
167167
width: u16,
168168
height: u16,
169+
background: PremulColor,
169170
encoded_paints: &[EncodedPaint],
170171
image_resolver: &dyn ImageResolver,
171172
) {
172173
use crate::fine::F32Kernel;
173-
dispatch!(self.level, simd => self.rasterize_with::<_, F32Kernel>(simd, buffer, width, height, encoded_paints, image_resolver));
174+
dispatch!(self.level, simd => self.rasterize_with::<_, F32Kernel>(simd, buffer, width, height, background, encoded_paints, image_resolver));
174175
}
175176

176177
#[cfg(feature = "u8_pipeline")]
@@ -179,11 +180,12 @@ impl MultiThreadedDispatcher {
179180
buffer: &mut [u8],
180181
width: u16,
181182
height: u16,
183+
background: PremulColor,
182184
encoded_paints: &[EncodedPaint],
183185
image_resolver: &dyn ImageResolver,
184186
) {
185187
use crate::fine::U8Kernel;
186-
dispatch!(self.level, simd => self.rasterize_with::<_, U8Kernel>(simd, buffer, width, height, encoded_paints, image_resolver));
188+
dispatch!(self.level, simd => self.rasterize_with::<_, U8Kernel>(simd, buffer, width, height, background, encoded_paints, image_resolver));
187189
}
188190

189191
fn init(&mut self) {
@@ -364,6 +366,7 @@ impl MultiThreadedDispatcher {
364366
buffer: &mut [u8],
365367
width: u16,
366368
height: u16,
369+
background: PremulColor,
367370
encoded_paints: &[EncodedPaint],
368371
image_resolver: &dyn ImageResolver,
369372
) {
@@ -384,7 +387,7 @@ impl MultiThreadedDispatcher {
384387
let wtile = wide.get(x, y);
385388
fine.set_coords(x, y);
386389

387-
fine.clear(wtile.bg);
390+
fine.clear(wide.tile_bg(x, y, background));
388391
for cmd in &wtile.cmds {
389392
let thread_idx = match cmd {
390393
Cmd::AlphaFill(a) => Some(wide.attrs.fill[a.attrs_idx as usize].thread_idx),
@@ -586,6 +589,7 @@ impl Dispatcher for MultiThreadedDispatcher {
586589
render_mode: RenderMode,
587590
width: u16,
588591
height: u16,
592+
background: PremulColor,
589593
encoded_paints: &[EncodedPaint],
590594
image_resolver: &dyn ImageResolver,
591595
) {
@@ -595,23 +599,51 @@ impl Dispatcher for MultiThreadedDispatcher {
595599
#[cfg(all(feature = "u8_pipeline", not(feature = "f32_pipeline")))]
596600
{
597601
let _ = render_mode;
598-
self.rasterize_u8(buffer, width, height, encoded_paints, image_resolver);
602+
self.rasterize_u8(
603+
buffer,
604+
width,
605+
height,
606+
background,
607+
encoded_paints,
608+
image_resolver,
609+
);
599610
}
600611
// Only f32 pipeline enabled
601612
#[cfg(all(feature = "f32_pipeline", not(feature = "u8_pipeline")))]
602613
{
603614
let _ = render_mode;
604-
self.rasterize_f32(buffer, width, height, encoded_paints, image_resolver);
615+
self.rasterize_f32(
616+
buffer,
617+
width,
618+
height,
619+
background,
620+
encoded_paints,
621+
image_resolver,
622+
);
605623
}
606624

607625
// Both pipelines enabled
608626
#[cfg(all(feature = "f32_pipeline", feature = "u8_pipeline"))]
609627
match render_mode {
610628
RenderMode::OptimizeSpeed => {
611-
self.rasterize_u8(buffer, width, height, encoded_paints, image_resolver);
629+
self.rasterize_u8(
630+
buffer,
631+
width,
632+
height,
633+
background,
634+
encoded_paints,
635+
image_resolver,
636+
);
612637
}
613638
RenderMode::OptimizeQuality => {
614-
self.rasterize_f32(buffer, width, height, encoded_paints, image_resolver);
639+
self.rasterize_f32(
640+
buffer,
641+
width,
642+
height,
643+
background,
644+
encoded_paints,
645+
image_resolver,
646+
);
615647
}
616648
}
617649
}

sparse_strips/vello_cpu/src/dispatch/single_threaded.rs

Lines changed: 44 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -92,12 +92,13 @@ impl SingleThreadedDispatcher {
9292
buffer: &mut [u8],
9393
width: u16,
9494
height: u16,
95+
background: PremulColor,
9596
encoded_paints: &[EncodedPaint],
9697
image_resolver: &dyn ImageResolver,
9798
) {
9899
use crate::fine::F32Kernel;
99100
use vello_common::fearless_simd::dispatch;
100-
dispatch!(self.level, simd => self.rasterize_with::<_, F32Kernel>(simd, buffer, width, height, encoded_paints, image_resolver));
101+
dispatch!(self.level, simd => self.rasterize_with::<_, F32Kernel>(simd, buffer, width, height, background, encoded_paints, image_resolver));
101102
}
102103

103104
/// Rasterizes the scene using u8 precision (fast).
@@ -110,12 +111,13 @@ impl SingleThreadedDispatcher {
110111
buffer: &mut [u8],
111112
width: u16,
112113
height: u16,
114+
background: PremulColor,
113115
encoded_paints: &[EncodedPaint],
114116
image_resolver: &dyn ImageResolver,
115117
) {
116118
use crate::fine::U8Kernel;
117119
use vello_common::fearless_simd::dispatch;
118-
dispatch!(self.level, simd => self.rasterize_with::<_, U8Kernel>(simd, buffer, width, height, encoded_paints, image_resolver));
120+
dispatch!(self.level, simd => self.rasterize_with::<_, U8Kernel>(simd, buffer, width, height, background, encoded_paints, image_resolver));
119121
}
120122

121123
/// Core rasterization dispatcher that chooses between simple and filter-aware paths.
@@ -132,6 +134,7 @@ impl SingleThreadedDispatcher {
132134
buffer: &mut [u8],
133135
width: u16,
134136
height: u16,
137+
background: PremulColor,
135138
encoded_paints: &[EncodedPaint],
136139
image_resolver: &dyn ImageResolver,
137140
) {
@@ -144,6 +147,7 @@ impl SingleThreadedDispatcher {
144147
buffer,
145148
width,
146149
height,
150+
background,
147151
encoded_paints,
148152
image_resolver,
149153
&mut layer_manager,
@@ -155,6 +159,7 @@ impl SingleThreadedDispatcher {
155159
buffer,
156160
width,
157161
height,
162+
background,
158163
encoded_paints,
159164
image_resolver,
160165
);
@@ -177,6 +182,7 @@ impl SingleThreadedDispatcher {
177182
buffer: &mut [u8],
178183
width: u16,
179184
height: u16,
185+
background: PremulColor,
180186
encoded_paints: &[EncodedPaint],
181187
image_resolver: &dyn ImageResolver,
182188
layer_manager: &mut LayerManager,
@@ -246,8 +252,7 @@ impl SingleThreadedDispatcher {
246252
// Final composition directly to output buffer.
247253
let mut regions = Regions::new(width, height, buffer);
248254
regions.update_regions(|region| {
249-
// Use the background color from the wide tile.
250-
let bg = self.wide.get(region.x, region.y).bg;
255+
let bg = self.wide.tile_bg(region.x, region.y, background);
251256
self.process_layer_tile(
252257
&mut fine,
253258
region.x,
@@ -395,6 +400,7 @@ impl SingleThreadedDispatcher {
395400
buffer: &mut [u8],
396401
width: u16,
397402
height: u16,
403+
background: PremulColor,
398404
encoded_paints: &[EncodedPaint],
399405
image_resolver: &dyn ImageResolver,
400406
) {
@@ -409,7 +415,7 @@ impl SingleThreadedDispatcher {
409415
fine.set_coords(x, y);
410416

411417
// Clear to background and process all commands in order.
412-
fine.clear(wtile.bg);
418+
fine.clear(self.wide.tile_bg(x, y, background));
413419
for cmd in &wtile.cmds {
414420
fine.run_cmd(
415421
cmd,
@@ -703,33 +709,62 @@ impl Dispatcher for SingleThreadedDispatcher {
703709
render_mode: RenderMode,
704710
width: u16,
705711
height: u16,
712+
background: PremulColor,
706713
encoded_paints: &[EncodedPaint],
707714
image_resolver: &dyn ImageResolver,
708715
) {
709716
// If only the u8 pipeline is enabled, then use it
710717
#[cfg(all(feature = "u8_pipeline", not(feature = "f32_pipeline")))]
711718
{
712719
let _ = render_mode;
713-
self.rasterize_u8(buffer, width, height, encoded_paints, image_resolver);
720+
self.rasterize_u8(
721+
buffer,
722+
width,
723+
height,
724+
background,
725+
encoded_paints,
726+
image_resolver,
727+
);
714728
}
715729

716730
// If only the f32 pipeline is enabled, then use it
717731
#[cfg(all(feature = "f32_pipeline", not(feature = "u8_pipeline")))]
718732
{
719733
let _ = render_mode;
720-
self.rasterize_f32(buffer, width, height, encoded_paints, image_resolver);
734+
self.rasterize_f32(
735+
buffer,
736+
width,
737+
height,
738+
background,
739+
encoded_paints,
740+
image_resolver,
741+
);
721742
}
722743

723744
// If both pipelines are enabled, select precision based on render mode parameter.
724745
#[cfg(all(feature = "u8_pipeline", feature = "f32_pipeline"))]
725746
match render_mode {
726747
RenderMode::OptimizeSpeed => {
727748
// Use u8 precision for faster rendering.
728-
self.rasterize_u8(buffer, width, height, encoded_paints, image_resolver);
749+
self.rasterize_u8(
750+
buffer,
751+
width,
752+
height,
753+
background,
754+
encoded_paints,
755+
image_resolver,
756+
);
729757
}
730758
RenderMode::OptimizeQuality => {
731759
// Use f32 precision for higher quality.
732-
self.rasterize_f32(buffer, width, height, encoded_paints, image_resolver);
760+
self.rasterize_f32(
761+
buffer,
762+
width,
763+
height,
764+
background,
765+
encoded_paints,
766+
image_resolver,
767+
);
733768
}
734769
}
735770

0 commit comments

Comments
 (0)