diff --git a/renderer/src/builder.rs b/renderer/src/builder.rs index 4c6e1110..2f49f212 100644 --- a/renderer/src/builder.rs +++ b/renderer/src/builder.rs @@ -42,7 +42,6 @@ pub(crate) struct SceneBuilder<'a> { pub(crate) struct ObjectBuilder { pub built_path: BuiltPath, pub fills: Vec, - pub tiles: DenseTileMap, pub bounds: RectF, } @@ -50,6 +49,7 @@ pub(crate) struct ObjectBuilder { pub(crate) struct BuiltPath { pub mask_tiles: Vec, pub alpha_tiles: Vec, + pub tiles: DenseTileMap, } impl<'a> SceneBuilder<'a> { @@ -226,16 +226,15 @@ impl ObjectBuilder { let tile_rect = tiles::round_rect_out_to_tile_bounds(bounds); let tiles = DenseTileMap::new(tile_rect); ObjectBuilder { - built_path: BuiltPath { mask_tiles: vec![], alpha_tiles: vec![] }, + built_path: BuiltPath { mask_tiles: vec![], alpha_tiles: vec![], tiles }, bounds, fills: vec![], - tiles, } } #[inline] pub(crate) fn tile_rect(&self) -> RectI { - self.tiles.rect + self.built_path.tiles.rect } fn add_fill( @@ -295,8 +294,8 @@ impl ObjectBuilder { scene_builder: &SceneBuilder, tile_coords: Vector2I, ) -> u16 { - let local_tile_index = self.tiles.coords_to_index_unchecked(tile_coords); - let alpha_tile_index = self.tiles.data[local_tile_index].alpha_tile_index; + let local_tile_index = self.built_path.tiles.coords_to_index_unchecked(tile_coords); + let alpha_tile_index = self.built_path.tiles.data[local_tile_index].alpha_tile_index; if alpha_tile_index != !0 { return alpha_tile_index; } @@ -304,7 +303,7 @@ impl ObjectBuilder { let alpha_tile_index = scene_builder .next_alpha_tile_index .fetch_add(1, Ordering::Relaxed) as u16; - self.tiles.data[local_tile_index].alpha_tile_index = alpha_tile_index; + self.built_path.tiles.data[local_tile_index].alpha_tile_index = alpha_tile_index; alpha_tile_index } @@ -400,18 +399,18 @@ impl ObjectBuilder { #[inline] pub(crate) fn tile_coords_to_local_index(&self, coords: Vector2I) -> Option { - self.tiles.coords_to_index(coords).map(|index| index as u32) + self.built_path.tiles.coords_to_index(coords).map(|index| index as u32) } #[inline] pub(crate) fn local_tile_index_to_coords(&self, tile_index: u32) -> Vector2I { - self.tiles.index_to_coords(tile_index as usize) + self.built_path.tiles.index_to_coords(tile_index as usize) } -} -impl BuiltPath { - pub(crate) fn push_mask_tile(&mut self, tile: &TileObjectPrimitive, object_index: u16) { - self.mask_tiles.push(MaskTile { + pub(crate) fn push_mask_tile(mask_tiles: &mut Vec, + tile: &TileObjectPrimitive, + object_index: u16) { + mask_tiles.push(MaskTile { upper_left: MaskTileVertex::new(tile.alpha_tile_index as u16, Vector2I::default(), object_index, @@ -431,12 +430,12 @@ impl BuiltPath { }); } - pub(crate) fn push_alpha_tile(&mut self, + pub(crate) fn push_alpha_tile(alpha_tiles: &mut Vec, tile: &TileObjectPrimitive, tile_coords: Vector2I, object_index: u16, paint_metadata: &PaintMetadata) { - self.alpha_tiles.push(AlphaTile { + alpha_tiles.push(AlphaTile { upper_left: AlphaTileVertex::new(tile_coords, tile.alpha_tile_index as u16, Vector2I::default(), diff --git a/renderer/src/tile_map.rs b/renderer/src/tile_map.rs index d0ca65ca..0c946944 100644 --- a/renderer/src/tile_map.rs +++ b/renderer/src/tile_map.rs @@ -42,6 +42,11 @@ impl DenseTileMap { } } + #[inline] + pub fn get(&self, coords: Vector2I) -> Option<&T> { + self.coords_to_index(coords).and_then(|index| self.data.get(index)) + } + #[inline] pub fn coords_to_index(&self, coords: Vector2I) -> Option { if self.rect.contains_point(coords) { diff --git a/renderer/src/tiles.rs b/renderer/src/tiles.rs index 75522607..3f06ad95 100644 --- a/renderer/src/tiles.rs +++ b/renderer/src/tiles.rs @@ -114,7 +114,7 @@ impl<'a> Tiler<'a> { fn pack_and_cull(&mut self) { match self.path_info { - TilingPathInfo::Clip => unimplemented!(), + TilingPathInfo::Clip => self.pack_and_cull_clip_path(), TilingPathInfo::Draw { .. } => self.pack_and_cull_draw_path(), } } @@ -127,12 +127,43 @@ impl<'a> Tiler<'a> { } }; - for (tile_index, tile) in self.object_builder.tiles.data.iter().enumerate() { - let tile_coords = self.object_builder.local_tile_index_to_coords(tile_index as u32); + for (draw_tile_index, draw_tile) in self.object_builder + .built_path + .tiles + .data + .iter() + .enumerate() { + let tile_coords = self.object_builder + .local_tile_index_to_coords(draw_tile_index as u32); - if tile.is_solid() { + // Figure out what clip tile we need, if any. + let clip_tile = match built_clip_path { + None => None, + Some(built_clip_path) => { + match built_clip_path.tiles.get(tile_coords) { + None => { + // This tile is outside of the bounds of the clip path entirely. We can + // cull it. + continue; + } + Some(clip_tile) if clip_tile.is_solid() => { + if clip_tile.backdrop != 0 { + // The clip tile is fully opaque, so this tile isn't clipped at + // all. + None + } else { + // This tile is completely clipped out. Cull it. + continue; + } + } + Some(clip_tile) => Some(clip_tile), + } + } + }; + + if clip_tile.is_none() && draw_tile.is_solid() { // Blank tiles are always skipped. - if tile.backdrop == 0 { + if draw_tile.backdrop == 0 { continue; } @@ -143,14 +174,23 @@ impl<'a> Tiler<'a> { } } - self.object_builder.built_path.push_mask_tile(tile, self.object_index); - self.object_builder.built_path.push_alpha_tile(tile, - tile_coords, - self.object_index, - paint_metadata); + ObjectBuilder::push_mask_tile(&mut self.object_builder.built_path.mask_tiles, + draw_tile, + self.object_index); + ObjectBuilder::push_alpha_tile(&mut self.object_builder.built_path.alpha_tiles, + draw_tile, + tile_coords, + self.object_index, + paint_metadata); + + // TODO(pcwalton): Add the clip tile if necessary. } } + fn pack_and_cull_clip_path(&mut self) { + // TODO(pcwalton) + } + fn process_old_active_edges(&mut self, tile_y: i32) { let mut current_tile_x = self.object_builder.tile_rect().min_x(); let mut current_subtile_x = 0.0; @@ -225,7 +265,7 @@ impl<'a> Tiler<'a> { if let Some(tile_index) = self.object_builder .tile_coords_to_local_index(current_tile_coords) { // FIXME(pcwalton): Handle winding overflow. - self.object_builder.tiles.data[tile_index as usize].backdrop = + self.object_builder.built_path.tiles.data[tile_index as usize].backdrop = current_winding as i8; }