use crate::builder::Occluder;
use crate::gpu_data::{Tile, TileBatch};
use crate::paint::{PaintId, PaintMetadata};
use crate::tile_map::DenseTileMap;
use crate::tiles;
use pathfinder_content::effects::{BlendMode, Filter};
use pathfinder_geometry::rect::RectF;
use pathfinder_geometry::vector::Vector2I;
use vec_map::VecMap;
pub(crate) struct ZBuffer {
buffer: DenseTileMap<u32>,
depth_metadata: VecMap<DepthMetadata>,
}
pub(crate) struct SolidTiles {
pub(crate) batches: Vec<TileBatch>,
}
#[derive(Clone, Copy)]
pub(crate) struct DepthMetadata {
pub(crate) paint_id: PaintId,
}
impl ZBuffer {
pub(crate) fn new(view_box: RectF) -> ZBuffer {
let tile_rect = tiles::round_rect_out_to_tile_bounds(view_box);
ZBuffer {
buffer: DenseTileMap::from_builder(|_| 0, tile_rect),
depth_metadata: VecMap::new(),
}
}
pub(crate) fn test(&self, coords: Vector2I, depth: u32) -> bool {
let tile_index = self.buffer.coords_to_index_unchecked(coords);
self.buffer.data[tile_index as usize] < depth
}
pub(crate) fn update(&mut self,
solid_tiles: &[Occluder],
depth: u32,
metadata: DepthMetadata) {
self.depth_metadata.insert(depth as usize, metadata);
for solid_tile in solid_tiles {
let tile_index = self.buffer.coords_to_index_unchecked(solid_tile.coords);
let z_dest = &mut self.buffer.data[tile_index as usize];
*z_dest = u32::max(*z_dest, depth);
}
}
pub(crate) fn build_solid_tiles(&self, paint_metadata: &[PaintMetadata]) -> SolidTiles {
let mut solid_tiles = SolidTiles { batches: vec![] };
for tile_index in 0..self.buffer.data.len() {
let depth = self.buffer.data[tile_index];
if depth == 0 {
continue;
}
let tile_coords = self.buffer.index_to_coords(tile_index);
let depth_metadata = self.depth_metadata[depth as usize];
let paint_id = depth_metadata.paint_id;
let paint_metadata = &paint_metadata[paint_id.0 as usize];
let tile_position = tile_coords + self.buffer.rect.origin();
let paint_tile_batch_texture = paint_metadata.tile_batch_texture();
match solid_tiles.batches.last() {
Some(TileBatch { color_texture: tile_batch_texture, .. }) if
*tile_batch_texture == paint_tile_batch_texture => {}
_ => {
solid_tiles.batches.push(TileBatch {
color_texture: paint_tile_batch_texture,
tiles: vec![],
filter: Filter::None,
blend_mode: BlendMode::default(),
mask_0_fill_rule: None,
mask_1_fill_rule: None,
tile_page: !0,
});
}
}
let batch = solid_tiles.batches.last_mut().unwrap();
batch.tiles.push(Tile::new_solid_from_paint_id(tile_position, paint_id));
}
solid_tiles
}
}
impl Tile {
pub(crate) fn new_solid_from_paint_id(tile_origin: Vector2I, paint_id: PaintId) -> Tile {
Tile {
tile_x: tile_origin.x() as i16,
tile_y: tile_origin.y() as i16,
mask_0_backdrop: 0,
mask_1_backdrop: 0,
mask_0_u: 0,
mask_0_v: 0,
mask_1_u: 0,
mask_1_v: 0,
color: paint_id.0,
}
}
}