Refactor into separate functions

This commit is contained in:
Patrick Walton 2018-12-21 13:46:28 -08:00
parent 8887b55469
commit 3b92ed0798
1 changed files with 190 additions and 169 deletions

View File

@ -939,6 +939,10 @@ struct Tiler<'o, 'p> {
point_queue: SortedVector<QueuedEndpoint>, point_queue: SortedVector<QueuedEndpoint>,
active_edges: SortedVector<ActiveEdge>, active_edges: SortedVector<ActiveEdge>,
strip_fills: Vec<FillPrimitive>,
strip_tiles: Vec<MaskTilePrimitive>,
used_strip_tiles: FixedBitSet,
old_active_edges: Vec<ActiveEdge>,
} }
impl<'o, 'p> Tiler<'o, 'p> { impl<'o, 'p> Tiler<'o, 'p> {
@ -956,6 +960,10 @@ impl<'o, 'p> Tiler<'o, 'p> {
point_queue: SortedVector::new(), point_queue: SortedVector::new(),
active_edges: SortedVector::new(), active_edges: SortedVector::new(),
strip_fills: vec![],
strip_tiles: vec![],
used_strip_tiles: FixedBitSet::with_capacity(1),
old_active_edges: vec![],
} }
} }
@ -989,11 +997,10 @@ impl<'o, 'p> Tiler<'o, 'p> {
}; };
let mut tile_index_y = (f32::floor(view_box_origin_y / TILE_HEIGHT) * TILE_HEIGHT) as i16; let mut tile_index_y = (f32::floor(view_box_origin_y / TILE_HEIGHT) * TILE_HEIGHT) as i16;
let mut strip_fills = vec![]; self.strip_tiles.clear();
let mut strip_tiles = Vec::with_capacity(tiles_across); self.strip_tiles.reserve(tiles_across);
let mut used_strip_tiles = FixedBitSet::with_capacity(tiles_across); self.used_strip_tiles.grow(tiles_across);
self.old_active_edges.clear();
let mut old_active_edges = vec![];
// Generate strips. // Generate strips.
while strip_origin.y < bounds.max_y() { while strip_origin.y < bounds.max_y() {
@ -1003,29 +1010,66 @@ impl<'o, 'p> Tiler<'o, 'p> {
Size2D::new(strip_right_extent - strip_origin.x, Size2D::new(strip_right_extent - strip_origin.x,
strip_extent.y - strip_origin.y)); strip_extent.y - strip_origin.y));
// Generate strip.
self.generate_strip(&strip_bounds, tile_index_y, tiles_across);
strip_origin.y = strip_extent.y;
tile_index_y += 1;
}
}
#[inline(never)]
fn generate_strip(&mut self,
strip_bounds: &Rect<f32>,
tile_index_y: i16,
tiles_across: usize) {
// We can skip a bunch of steps if we're above the viewport. // We can skip a bunch of steps if we're above the viewport.
let above_view_box = tile_index_y < 0; let above_view_box = tile_index_y < 0;
// Reset strip info. // Reset strip info.
strip_fills.clear(); self.strip_fills.clear();
strip_tiles.clear(); self.strip_tiles.clear();
used_strip_tiles.clear(); self.used_strip_tiles.clear();
// Allocate tiles. // Allocate tiles.
for tile_index_x in 0..tiles_across { for tile_index_x in 0..tiles_across {
strip_tiles.push(MaskTilePrimitive::new(tile_index_x as i16, self.strip_tiles
tile_index_y, .push(MaskTilePrimitive::new(tile_index_x as i16, tile_index_y, self.fill_color));
self.fill_color));
} }
// Process old active edges. // Process old active edges.
self.process_old_active_edges(strip_bounds, tile_index_y);
// Add new active edges.
loop {
match self.point_queue.peek() {
Some(queued_endpoint) if queued_endpoint.y < strip_bounds.max_y() => {}
Some(_) | None => break,
}
self.add_new_active_edge(strip_bounds, tile_index_y);
}
// Finalize tiles.
if !above_view_box {
// NB: This order must not be changed!
self.flush_fills();
self.flush_tiles(tile_index_y);
}
}
#[inline(never)]
fn process_old_active_edges(&mut self, strip_bounds: &Rect<f32>, tile_index_y: i16) {
// We can skip a bunch of steps if we're above the viewport.
let above_view_box = tile_index_y < 0;
let (mut tile_index_x, mut current_left) = (0, strip_bounds.origin.x); let (mut tile_index_x, mut current_left) = (0, strip_bounds.origin.x);
let mut winding = 0; let mut winding = 0;
mem::swap(&mut old_active_edges, &mut self.active_edges.array); mem::swap(&mut self.old_active_edges, &mut self.active_edges.array);
for mut active_edge in old_active_edges.drain(..) { for mut active_edge in self.old_active_edges.drain(..) {
// Move over to the correct tile, filling in as we go. // Move over to the correct tile, filling in as we go.
let mut tile_left = strip_bounds.origin.x + (tile_index_x as f32) * TILE_WIDTH; let mut tile_left = strip_bounds.origin.x + (tile_index_x as f32) * TILE_WIDTH;
while tile_index_x < strip_tiles.len() { while tile_index_x < self.strip_tiles.len() {
let tile_right = tile_left + TILE_WIDTH; let tile_right = tile_left + TILE_WIDTH;
let segment_left = active_edge.segment.min_x(); let segment_left = active_edge.segment.min_x();
@ -1033,7 +1077,7 @@ impl<'o, 'p> Tiler<'o, 'p> {
break break
} }
strip_tiles[tile_index_x].backdrop = winding as f32; self.strip_tiles[tile_index_x].backdrop = winding as f32;
current_left = tile_right; current_left = tile_right;
tile_left = tile_right; tile_left = tile_right;
tile_index_x += 1; tile_index_x += 1;
@ -1042,15 +1086,15 @@ impl<'o, 'p> Tiler<'o, 'p> {
// Do subtile fill. // Do subtile fill.
let min_x = active_edge.segment.min_x(); let min_x = active_edge.segment.min_x();
let edge_winding = active_edge.segment.winding(); let edge_winding = active_edge.segment.winding();
if current_left < min_x && tile_index_x < strip_tiles.len() { if current_left < min_x && tile_index_x < self.strip_tiles.len() {
let left = Point2D::new(current_left - tile_left, 0.0); let left = Point2D::new(current_left - tile_left, 0.0);
let right = Point2D::new(current_left - min_x, 0.0); let right = Point2D::new(current_left - min_x, 0.0);
strip_fills.push(FillPrimitive { self.strip_fills.push(FillPrimitive {
from: if edge_winding < 0 { left } else { right }, from: if edge_winding < 0 { left } else { right },
to: if edge_winding < 0 { right } else { left }, to: if edge_winding < 0 { right } else { left },
tile_index: tile_index_x as u32, tile_index: tile_index_x as u32,
}); });
used_strip_tiles.insert(tile_index_x); self.used_strip_tiles.insert(tile_index_x);
current_left = right.x; current_left = right.x;
} }
@ -1058,41 +1102,22 @@ impl<'o, 'p> Tiler<'o, 'p> {
winding += edge_winding; winding += edge_winding;
// Process the edge. // Process the edge.
let fills = if above_view_box { None } else { Some(&mut strip_fills) }; let fills = if above_view_box { None } else { Some(&mut self.strip_fills) };
process_active_edge(&mut active_edge.segment, process_active_edge(&mut active_edge.segment,
&strip_bounds, &strip_bounds,
fills, fills,
&mut used_strip_tiles); &mut self.used_strip_tiles);
if !active_edge.segment.is_none() { if !active_edge.segment.is_none() {
self.active_edges.push(active_edge); self.active_edges.push(active_edge);
} }
} }
}
/* #[inline(never)]
// Sort point queue. fn add_new_active_edge(&mut self, strip_bounds: &Rect<f32>, tile_index_y: i16) {
self.point_queue.sort_unstable_by(|this, other| { // We can skip a bunch of steps if we're above the viewport.
match other.y.partial_cmp(&this.y) { let above_view_box = tile_index_y < 0;
Some(Ordering::Equal) | None => {
match other.point_index.contour_index.cmp(&this.point_index
.contour_index) {
Ordering::Equal => {
other.point_index.point_index.cmp(&this.point_index.point_index)
}
ordering => ordering,
}
}
Some(ordering) => ordering,
}
});
*/
// Add new active edges.
loop {
match self.point_queue.peek() {
Some(queued_endpoint) if queued_endpoint.y < strip_extent.y => {}
Some(_) | None => break,
}
let outline = &self.outline; let outline = &self.outline;
let point_index = self.point_queue.pop().unwrap().point_index; let point_index = self.point_queue.pop().unwrap().point_index;
@ -1102,13 +1127,13 @@ impl<'o, 'p> Tiler<'o, 'p> {
let prev_endpoint_index = contour.prev_endpoint_index_of(point_index.point_index); let prev_endpoint_index = contour.prev_endpoint_index_of(point_index.point_index);
let next_endpoint_index = contour.next_endpoint_index_of(point_index.point_index); let next_endpoint_index = contour.next_endpoint_index_of(point_index.point_index);
if contour.point_is_logically_above(point_index.point_index, prev_endpoint_index) { if contour.point_is_logically_above(point_index.point_index, prev_endpoint_index) {
let fills = if above_view_box { None } else { Some(&mut strip_fills) }; let fills = if above_view_box { None } else { Some(&mut self.strip_fills) };
process_active_segment(contour, process_active_segment(contour,
prev_endpoint_index, prev_endpoint_index,
&mut self.active_edges, &mut self.active_edges,
&strip_bounds, &strip_bounds,
fills, fills,
&mut used_strip_tiles); &mut self.used_strip_tiles);
self.point_queue.push(QueuedEndpoint { self.point_queue.push(QueuedEndpoint {
point_index: PointIndex { point_index: PointIndex {
@ -1120,13 +1145,13 @@ impl<'o, 'p> Tiler<'o, 'p> {
} }
if contour.point_is_logically_above(point_index.point_index, next_endpoint_index) { if contour.point_is_logically_above(point_index.point_index, next_endpoint_index) {
let fills = if above_view_box { None } else { Some(&mut strip_fills) }; let fills = if above_view_box { None } else { Some(&mut self.strip_fills) };
process_active_segment(contour, process_active_segment(contour,
point_index.point_index, point_index.point_index,
&mut self.active_edges, &mut self.active_edges,
&strip_bounds, &strip_bounds,
fills, fills,
&mut used_strip_tiles); &mut self.used_strip_tiles);
self.point_queue.push(QueuedEndpoint { self.point_queue.push(QueuedEndpoint {
point_index: PointIndex { point_index: PointIndex {
@ -1138,12 +1163,12 @@ impl<'o, 'p> Tiler<'o, 'p> {
} }
} }
// Finalize tiles. #[inline(never)]
if !above_view_box { fn flush_tiles(&mut self, tile_index_y: i16) {
// Flush tiles. // Flush tiles.
let first_tile_index = self.built_scene.mask_tiles.len() as u32; let first_tile_index = self.built_scene.mask_tiles.len() as u32;
for (tile_index_x, tile) in strip_tiles.iter().enumerate() { for (tile_index_x, tile) in self.strip_tiles.iter().enumerate() {
if used_strip_tiles.contains(tile_index_x) { if self.used_strip_tiles.contains(tile_index_x) {
self.built_scene.mask_tiles.push(*tile); self.built_scene.mask_tiles.push(*tile);
} else if tile.backdrop != 0.0 { } else if tile.backdrop != 0.0 {
let primitive = let primitive =
@ -1151,13 +1176,14 @@ impl<'o, 'p> Tiler<'o, 'p> {
self.built_scene.solid_tiles.push(primitive); self.built_scene.solid_tiles.push(primitive);
} }
} }
}
// Flush fills. #[inline(never)]
// fn flush_fills(&mut self) {
// TODO(pcwalton): Don't use a temporary vector to hold these. let first_tile_index = self.built_scene.mask_tiles.len() as u32;
for fill in &strip_fills { for fill in &self.strip_fills {
let real_tile_index = first_tile_index + let real_tile_index = first_tile_index +
used_strip_tiles.count_ones(0..(fill.tile_index as usize)) as u32; self.used_strip_tiles.count_ones(0..(fill.tile_index as usize)) as u32;
self.built_scene.fills.push(FillPrimitive { self.built_scene.fills.push(FillPrimitive {
from: fill.from, from: fill.from,
to: fill.to, to: fill.to,
@ -1166,11 +1192,6 @@ impl<'o, 'p> Tiler<'o, 'p> {
} }
} }
strip_origin.y = strip_extent.y;
tile_index_y += 1;
}
}
#[inline(never)] #[inline(never)]
fn init_point_queue(&mut self) { fn init_point_queue(&mut self) {
// Find MIN points. // Find MIN points.