1use crate::fine::COLOR_COMPONENTS;
7use alloc::vec::Vec;
8use vello_common::coarse::WideTile;
9use vello_common::pixmap::Pixmap;
10use vello_common::tile::Tile;
11
12#[derive(Debug)]
13pub struct Regions<'a> {
14 regions: Vec<Region<'a>>,
15}
16
17impl<'a> Regions<'a> {
18 pub fn new(width: u16, height: u16, mut buffer: &'a mut [u8]) -> Self {
19 let buf_width = usize::from(width);
20 let buf_height = usize::from(height);
21
22 let row_advance = buf_width * COLOR_COMPONENTS;
23
24 let height_regions = buf_height.div_ceil(usize::from(Tile::HEIGHT));
25 let width_regions = buf_width.div_ceil(usize::from(WideTile::WIDTH));
26
27 let mut regions = Vec::with_capacity(height_regions * width_regions);
28
29 let mut next_lines: [&'a mut [u8]; Tile::HEIGHT as usize] =
30 [&mut [], &mut [], &mut [], &mut []];
31
32 for y in 0..height_regions {
33 let base_y = y * usize::from(Tile::HEIGHT);
34 let region_height = usize::from(Tile::HEIGHT).min(buf_height - base_y);
35
36 for line in next_lines.iter_mut().take(region_height) {
37 let (head, tail) = buffer.split_at_mut(row_advance);
38 *line = head;
39 buffer = tail;
40 }
41
42 for x in 0..width_regions {
43 let mut areas: [&mut [u8]; Tile::HEIGHT as usize] =
44 [&mut [], &mut [], &mut [], &mut []];
45
46 let region_width =
48 (usize::from(WideTile::WIDTH) * COLOR_COMPONENTS).min(next_lines[0].len());
49
50 for h in 0..region_height {
51 let next = core::mem::take(&mut next_lines[h]);
52 let (head, tail) = next.split_at_mut(region_width);
53 areas[h] = head;
54 next_lines[h] = tail;
55 }
56
57 regions.push(Region::new(
58 areas,
59 u16::try_from(x).unwrap(),
60 u16::try_from(y).unwrap(),
61 region_width as u16 / COLOR_COMPONENTS as u16,
62 region_height as u16,
63 ));
64 }
65 }
66
67 Self { regions }
68 }
69
70 #[cfg(feature = "multithreading")]
73 pub fn update_regions_par(&mut self, func: impl Fn(&mut Region<'_>) + Send + Sync) {
74 use rayon::iter::ParallelIterator;
75 use rayon::prelude::IntoParallelRefMutIterator;
76
77 self.regions.par_iter_mut().for_each(func);
78 }
79
80 pub fn update_regions(&mut self, func: impl FnMut(&mut Region<'_>)) {
82 self.regions.iter_mut().for_each(func);
83 }
84}
85
86#[derive(Default, Debug)]
92pub struct Region<'a> {
93 pub(crate) x: u16,
95 pub(crate) y: u16,
97 pub width: u16,
98 pub height: u16,
99 areas: [&'a mut [u8]; Tile::HEIGHT as usize],
100}
101
102impl<'a> Region<'a> {
103 pub(crate) fn new(
104 areas: [&'a mut [u8]; Tile::HEIGHT as usize],
105 x: u16,
106 y: u16,
107 width: u16,
108 height: u16,
109 ) -> Self {
110 Self {
111 areas,
112 x,
113 y,
114 width,
115 height,
116 }
117 }
118
119 pub(crate) fn from_pixmap_tile(
132 pixmap: &'a mut Pixmap,
133 tile_x: u16,
134 tile_y: u16,
135 ) -> Option<Self> {
136 let pixmap_width = pixmap.width();
137 let pixmap_height = pixmap.height();
138
139 let base_x = tile_x * WideTile::WIDTH;
141 let base_y = tile_y * Tile::HEIGHT;
142
143 if base_x >= pixmap_width || base_y >= pixmap_height {
145 return None;
146 }
147
148 let region_width = WideTile::WIDTH.min(pixmap_width - base_x);
150 let region_height = Tile::HEIGHT.min(pixmap_height - base_y);
151
152 let buffer = pixmap.data_as_u8_slice_mut();
154
155 let row_stride = pixmap_width as usize * COLOR_COMPONENTS;
157 let start_offset = (base_y as usize * row_stride) + (base_x as usize * COLOR_COMPONENTS);
158 let region_width_bytes = region_width as usize * COLOR_COMPONENTS;
159
160 let tile_buffer = &mut buffer[start_offset..];
162
163 let mut areas: [&mut [u8]; Tile::HEIGHT as usize] = [&mut [], &mut [], &mut [], &mut []];
165
166 let mut remaining = tile_buffer;
168 for (i, area) in areas.iter_mut().take(region_height as usize).enumerate() {
169 if i > 0 {
170 let skip = row_stride - region_width_bytes;
172 remaining = &mut remaining[skip..];
173 }
174
175 let (row, rest) = remaining.split_at_mut(region_width_bytes.min(remaining.len()));
176 *area = row;
177 remaining = rest;
178 }
179
180 Some(Self::new(
181 areas,
182 tile_x,
183 tile_y,
184 region_width,
185 region_height,
186 ))
187 }
188
189 pub(crate) fn row_mut(&mut self, y: u16) -> &mut [u8] {
190 self.areas[usize::from(y)]
191 }
192
193 pub fn areas(&mut self) -> &mut [&'a mut [u8]; Tile::HEIGHT as usize] {
194 &mut self.areas
195 }
196}