Clip entire tiles appropriately.

This doesn't composite masks together, so it's currently incomplete.
This commit is contained in:
Patrick Walton 2020-02-15 18:01:23 -08:00
parent a8019a1a1a
commit 0d3bbbd506
3 changed files with 70 additions and 26 deletions

View File

@ -42,7 +42,6 @@ pub(crate) struct SceneBuilder<'a> {
pub(crate) struct ObjectBuilder {
pub built_path: BuiltPath,
pub fills: Vec<FillBatchPrimitive>,
pub tiles: DenseTileMap<TileObjectPrimitive>,
pub bounds: RectF,
}
@ -50,6 +49,7 @@ pub(crate) struct ObjectBuilder {
pub(crate) struct BuiltPath {
pub mask_tiles: Vec<MaskTile>,
pub alpha_tiles: Vec<AlphaTile>,
pub tiles: DenseTileMap<TileObjectPrimitive>,
}
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<u32> {
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<MaskTile>,
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<AlphaTile>,
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(),

View File

@ -42,6 +42,11 @@ impl<T> DenseTileMap<T> {
}
}
#[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<usize> {
if self.rect.contains_point(coords) {

View File

@ -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;
}