1use crate::RenderMode;
5use crate::dispatch::Dispatcher;
6use crate::fine::{F32Kernel, Fine, FineKernel, U8Kernel};
7use crate::kurbo::{Affine, BezPath, Stroke};
8use crate::peniko::{BlendMode, Fill};
9use crate::region::Regions;
10use alloc::vec::Vec;
11use vello_common::coarse::{MODE_CPU, Wide};
12use vello_common::encode::EncodedPaint;
13use vello_common::fearless_simd::{Level, Simd, simd_dispatch};
14use vello_common::mask::Mask;
15use vello_common::paint::Paint;
16use vello_common::strip_generator::StripGenerator;
17
18#[derive(Debug)]
19pub(crate) struct SingleThreadedDispatcher {
20 wide: Wide,
21 strip_generator: StripGenerator,
22 level: Level,
23}
24
25impl SingleThreadedDispatcher {
26 pub(crate) fn new(width: u16, height: u16, level: Level) -> Self {
27 let wide = Wide::<MODE_CPU>::new(width, height);
28 let strip_generator = StripGenerator::new(width, height, level);
29
30 Self {
31 wide,
32 strip_generator,
33 level,
34 }
35 }
36
37 fn rasterize_f32(
38 &self,
39 buffer: &mut [u8],
40 width: u16,
41 height: u16,
42 encoded_paints: &[EncodedPaint],
43 ) {
44 rasterize_with_f32_dispatch(self.level, self, buffer, width, height, encoded_paints);
45 }
46
47 fn rasterize_u8(
48 &self,
49 buffer: &mut [u8],
50 width: u16,
51 height: u16,
52 encoded_paints: &[EncodedPaint],
53 ) {
54 rasterize_with_u8_dispatch(self.level, self, buffer, width, height, encoded_paints);
55 }
56
57 fn rasterize_with<S: Simd, F: FineKernel<S>>(
58 &self,
59 simd: S,
60 buffer: &mut [u8],
61 width: u16,
62 height: u16,
63 encoded_paints: &[EncodedPaint],
64 ) {
65 let mut buffer = Regions::new(width, height, buffer);
66 let mut fine = Fine::<S, F>::new(simd);
67
68 buffer.update_regions(|region| {
69 let x = region.x;
70 let y = region.y;
71
72 let wtile = self.wide.get(x, y);
73 fine.set_coords(x, y);
74
75 fine.clear(wtile.bg);
76 for cmd in &wtile.cmds {
77 fine.run_cmd(cmd, self.strip_generator.alpha_buf(), encoded_paints);
78 }
79
80 fine.pack(region);
81 });
82 }
83}
84
85impl Dispatcher for SingleThreadedDispatcher {
86 fn wide(&self) -> &Wide {
87 &self.wide
88 }
89
90 fn wide_mut(&mut self) -> &mut Wide {
91 &mut self.wide
92 }
93
94 fn fill_path(
95 &mut self,
96 path: &BezPath,
97 fill_rule: Fill,
98 transform: Affine,
99 paint: Paint,
100 anti_alias: bool,
101 ) {
102 let wide = &mut self.wide;
103
104 let func = |strips| wide.generate(strips, fill_rule, paint, 0);
105 self.strip_generator
106 .generate_filled_path(path, fill_rule, transform, anti_alias, func);
107 }
108
109 fn stroke_path(
110 &mut self,
111 path: &BezPath,
112 stroke: &Stroke,
113 transform: Affine,
114 paint: Paint,
115 anti_alias: bool,
116 ) {
117 let wide = &mut self.wide;
118
119 let func = |strips| wide.generate(strips, Fill::NonZero, paint, 0);
120 self.strip_generator
121 .generate_stroked_path(path, stroke, transform, anti_alias, func);
122 }
123
124 fn alpha_buf(&self) -> &[u8] {
125 self.strip_generator.alpha_buf()
126 }
127
128 fn extend_alpha_buf(&mut self, alphas: &[u8]) {
129 self.strip_generator.extend_alpha_buf(alphas);
130 }
131
132 fn replace_alpha_buf(&mut self, alphas: Vec<u8>) -> Vec<u8> {
133 self.strip_generator.replace_alpha_buf(alphas)
134 }
135
136 fn set_alpha_buf(&mut self, alphas: Vec<u8>) {
137 self.strip_generator.set_alpha_buf(alphas);
138 }
139
140 fn push_layer(
141 &mut self,
142 clip_path: Option<&BezPath>,
143 fill_rule: Fill,
144 clip_transform: Affine,
145 blend_mode: BlendMode,
146 opacity: f32,
147 anti_alias: bool,
148 mask: Option<Mask>,
149 ) {
150 let clip = if let Some(c) = clip_path {
151 let mut strip_buf = &[][..];
154
155 self.strip_generator.generate_filled_path(
156 c,
157 fill_rule,
158 clip_transform,
159 anti_alias,
160 |strips| strip_buf = strips,
161 );
162
163 Some((strip_buf, fill_rule))
164 } else {
165 None
166 };
167
168 self.wide.push_layer(clip, blend_mode, mask, opacity, 0);
169 }
170
171 fn pop_layer(&mut self) {
172 self.wide.pop_layer();
173 }
174
175 fn reset(&mut self) {
176 self.wide.reset();
177 self.strip_generator.reset();
178 }
179
180 fn flush(&mut self) {}
181
182 fn rasterize(
183 &self,
184 buffer: &mut [u8],
185 render_mode: RenderMode,
186 width: u16,
187 height: u16,
188 encoded_paints: &[EncodedPaint],
189 ) {
190 match render_mode {
191 RenderMode::OptimizeSpeed => self.rasterize_u8(buffer, width, height, encoded_paints),
192 RenderMode::OptimizeQuality => {
193 self.rasterize_f32(buffer, width, height, encoded_paints);
194 }
195 }
196 }
197}
198
199simd_dispatch!(
200 pub rasterize_with_f32_dispatch(
201 level,
202 self_: &SingleThreadedDispatcher,
203 buffer: &mut [u8],
204 width: u16,
205 height: u16,
206 encoded_paints: &[EncodedPaint]
207 ) = rasterize_with_f32
208);
209
210simd_dispatch!(
211 pub rasterize_with_u8_dispatch(
212 level,
213 self_: &SingleThreadedDispatcher,
214 buffer: &mut [u8],
215 width: u16,
216 height: u16,
217 encoded_paints: &[EncodedPaint]
218 ) = rasterize_with_u8
219);
220
221fn rasterize_with_f32<S: Simd>(
222 simd: S,
223 self_: &SingleThreadedDispatcher,
224 buffer: &mut [u8],
225 width: u16,
226 height: u16,
227 encoded_paints: &[EncodedPaint],
228) {
229 self_.rasterize_with::<S, F32Kernel>(simd, buffer, width, height, encoded_paints);
230}
231
232fn rasterize_with_u8<S: Simd>(
233 simd: S,
234 self_: &SingleThreadedDispatcher,
235 buffer: &mut [u8],
236 width: u16,
237 height: u16,
238 encoded_paints: &[EncodedPaint],
239) {
240 self_.rasterize_with::<S, U8Kernel>(simd, buffer, width, height, encoded_paints);
241}