Apply path transforms to paints

This commit is contained in:
Patrick Walton 2020-03-03 14:26:38 -08:00
parent 12574101e5
commit 2beb2bb126
6 changed files with 87 additions and 56 deletions

View File

@ -20,15 +20,15 @@ use crate::options::{PreparedBuildOptions, RenderCommandListener};
use crate::paint::{PaintInfo, PaintMetadata};
use crate::scene::{DisplayItem, Scene};
use crate::tile_map::DenseTileMap;
use crate::tiles::{self, TILE_HEIGHT, TILE_WIDTH, Tiler, TilingPathInfo};
use crate::z_buffer::ZBuffer;
use crate::tiles::{self, DrawTilingPathInfo, TILE_HEIGHT, TILE_WIDTH, Tiler, TilingPathInfo};
use crate::z_buffer::{DepthMetadata, ZBuffer};
use pathfinder_content::effects::BlendMode;
use pathfinder_content::fill::FillRule;
use pathfinder_content::pattern::RenderTargetId;
use pathfinder_geometry::line_segment::{LineSegment2F, LineSegmentU4, LineSegmentU8};
use pathfinder_geometry::vector::{Vector2F, Vector2I};
use pathfinder_geometry::rect::{RectF, RectI};
use pathfinder_geometry::util;
use pathfinder_geometry::vector::{Vector2F, Vector2I};
use pathfinder_gpu::TextureSamplingFlags;
use pathfinder_simd::default::{F32x4, I32x4};
use std::sync::atomic::{AtomicUsize, Ordering};
@ -170,8 +170,7 @@ impl<'a> SceneBuilder<'a> {
built_clip_paths: &[BuiltPath],
) -> BuiltDrawPath {
let path_object = &scene.paths[path_index];
let mut outline = scene.apply_render_options(path_object.outline(), built_options);
outline.transform(&path_object.transform());
let outline = scene.apply_render_options(path_object.outline(), built_options);
let paint_id = path_object.paint();
let paint_metadata = &paint_metadata[paint_id.0 as usize];
@ -183,12 +182,13 @@ impl<'a> SceneBuilder<'a> {
path_object.fill_rule(),
view_box,
path_index as u16,
TilingPathInfo::Draw {
TilingPathInfo::Draw(DrawTilingPathInfo {
paint_metadata,
blend_mode: path_object.blend_mode(),
opacity: path_object.opacity(),
built_clip_path,
});
transform_inv: path_object.transform().inverse(),
}));
tiler.generate_tiles();
@ -357,8 +357,12 @@ impl<'a> SceneBuilder<'a> {
built_draw_paths[start_index..end_index].iter().enumerate() {
let solid_tiles = &built_draw_path.path.solid_tiles;
let path_index = (path_subindex + start_index) as u32;
let paint = self.scene.paths[path_index as usize].paint();
z_buffer.update(solid_tiles, current_depth, paint);
let path = &self.scene.paths[path_index as usize];
let metadata = DepthMetadata {
paint_id: path.paint(),
transform: path.transform(),
};
z_buffer.update(solid_tiles, current_depth, metadata);
current_depth += 1;
}
}
@ -701,33 +705,28 @@ impl ObjectBuilder {
mask_tile_index: u16,
tile_coords: Vector2I,
object_index: u16,
opacity: u8,
paint_metadata: &PaintMetadata) {
draw_tiling_path_info: &DrawTilingPathInfo) {
alpha_tiles.push(AlphaTile {
upper_left: AlphaTileVertex::new(tile_coords,
mask_tile_index,
Vector2I::default(),
object_index,
opacity,
paint_metadata),
draw_tiling_path_info),
upper_right: AlphaTileVertex::new(tile_coords,
mask_tile_index,
Vector2I::new(1, 0),
object_index,
opacity,
paint_metadata),
draw_tiling_path_info),
lower_left: AlphaTileVertex::new(tile_coords,
mask_tile_index,
Vector2I::new(0, 1),
object_index,
opacity,
paint_metadata),
draw_tiling_path_info),
lower_right: AlphaTileVertex::new(tile_coords,
mask_tile_index,
Vector2I::splat(1),
object_index,
opacity,
paint_metadata),
draw_tiling_path_info),
});
}
}
@ -759,11 +758,12 @@ impl AlphaTileVertex {
tile_index: u16,
tile_offset: Vector2I,
object_index: u16,
opacity: u8,
paint_metadata: &PaintMetadata)
draw_tiling_path_info: &DrawTilingPathInfo)
-> AlphaTileVertex {
let tile_position = tile_origin + tile_offset;
let color_uv = paint_metadata.calculate_tex_coords(tile_position);
let transform_inv = draw_tiling_path_info.transform_inv;
let color_uv = draw_tiling_path_info.paint_metadata.calculate_tex_coords(tile_position,
transform_inv);
let mask_uv = calculate_mask_uv(tile_index, tile_offset);
AlphaTileVertex {
tile_x: tile_position.x() as i16,
@ -773,7 +773,7 @@ impl AlphaTileVertex {
mask_u: mask_uv.x() as u16,
mask_v: mask_uv.y() as u16,
object_index,
opacity,
opacity: draw_tiling_path_info.opacity,
pad: 0,
}
}

View File

@ -525,9 +525,13 @@ impl Palette {
impl PaintMetadata {
// TODO(pcwalton): Apply clamp/repeat to tile rect.
pub(crate) fn calculate_tex_coords(&self, tile_position: Vector2I) -> Vector2F {
pub(crate) fn calculate_tex_coords(&self,
tile_position: Vector2I,
path_transform_inv: Transform2F)
-> Vector2F {
let tile_size = Vector2I::new(TILE_WIDTH as i32, TILE_HEIGHT as i32);
let tex_coords = self.tex_transform * tile_position.scale_xy(tile_size).to_f32();
let position = tile_position.scale_xy(tile_size).to_f32();
let tex_coords = self.tex_transform * path_transform_inv * position;
tex_coords
}
}

View File

@ -46,7 +46,9 @@ impl Scene {
}
}
pub fn push_path(&mut self, path: DrawPath) {
pub fn push_path(&mut self, mut path: DrawPath) {
path.outline.transform(&path.transform());
self.bounds = self.bounds.union_rect(path.outline.bounds());
self.paths.push(path);

View File

@ -18,6 +18,7 @@ use pathfinder_content::segment::Segment;
use pathfinder_content::sorted_vector::SortedVector;
use pathfinder_geometry::line_segment::LineSegment2F;
use pathfinder_geometry::rect::{RectF, RectI};
use pathfinder_geometry::transform2d::Transform2F;
use pathfinder_geometry::vector::{Vector2F, Vector2I};
use std::cmp::Ordering;
use std::mem;
@ -43,12 +44,19 @@ pub(crate) struct Tiler<'a> {
#[derive(Clone, Copy)]
pub(crate) enum TilingPathInfo<'a> {
Clip,
Draw {
paint_metadata: &'a PaintMetadata,
blend_mode: BlendMode,
opacity: u8,
built_clip_path: Option<&'a BuiltPath>,
},
Draw(DrawTilingPathInfo<'a>),
}
#[derive(Clone, Copy)]
pub(crate) struct DrawTilingPathInfo<'a> {
pub(crate) paint_metadata: &'a PaintMetadata,
pub(crate) blend_mode: BlendMode,
pub(crate) opacity: u8,
// The inverse of the path transform.
//
// We calculate texture transforms with this.
pub(crate) transform_inv: Transform2F,
pub(crate) built_clip_path: Option<&'a BuiltPath>,
}
impl<'a> Tiler<'a> {
@ -128,11 +136,9 @@ impl<'a> Tiler<'a> {
}
fn pack_and_cull_draw_path(&mut self) {
let (paint_metadata, blend_mode, opacity, built_clip_path) = match self.path_info {
let draw_tiling_path_info = match self.path_info {
TilingPathInfo::Clip => unreachable!(),
TilingPathInfo::Draw { paint_metadata, blend_mode, opacity, built_clip_path } => {
(paint_metadata, blend_mode, opacity, built_clip_path)
}
TilingPathInfo::Draw(draw_tiling_path_info) => draw_tiling_path_info,
};
for (draw_tile_index, draw_tile) in self.object_builder
@ -145,7 +151,7 @@ impl<'a> Tiler<'a> {
.local_tile_index_to_coords(draw_tile_index as u32);
// Figure out what clip tile we need, if any.
let clip_tile = match built_clip_path {
let clip_tile = match draw_tiling_path_info.built_clip_path {
None => None,
Some(built_clip_path) => {
match built_clip_path.tiles.get(tile_coords) {
@ -182,7 +188,9 @@ impl<'a> Tiler<'a> {
// Next, if this is a solid tile that completely occludes the background, record
// that fact and stop here.
if paint_metadata.is_opaque && blend_mode.occludes_backdrop() && opacity == !0 {
if draw_tiling_path_info.paint_metadata.is_opaque &&
draw_tiling_path_info.blend_mode.occludes_backdrop() &&
draw_tiling_path_info.opacity == !0 {
self.object_builder.built_path.solid_tiles.push(SolidTile::new(tile_coords));
continue;
}
@ -210,8 +218,7 @@ impl<'a> Tiler<'a> {
mask_tile_index,
tile_coords,
self.object_index,
opacity,
paint_metadata);
&draw_tiling_path_info);
}
}

View File

@ -16,24 +16,30 @@ use crate::paint::{PaintId, PaintMetadata};
use crate::tile_map::DenseTileMap;
use crate::tiles;
use pathfinder_geometry::rect::RectF;
use pathfinder_geometry::transform2d::Transform2F;
use pathfinder_geometry::vector::Vector2I;
use vec_map::VecMap;
pub(crate) struct ZBuffer {
buffer: DenseTileMap<u32>,
depth_to_paint_id: VecMap<PaintId>,
depth_metadata: VecMap<DepthMetadata>,
}
pub(crate) struct SolidTiles {
pub(crate) batches: Vec<SolidTileBatch>,
}
#[derive(Clone, Copy)]
pub(crate) struct DepthMetadata {
pub(crate) paint_id: PaintId,
pub(crate) transform: Transform2F,
}
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_to_paint_id: VecMap::new(),
depth_metadata: VecMap::new(),
}
}
@ -42,8 +48,11 @@ impl ZBuffer {
self.buffer.data[tile_index as usize] < depth
}
pub(crate) fn update(&mut self, solid_tiles: &[SolidTile], depth: u32, paint_id: PaintId) {
self.depth_to_paint_id.insert(depth as usize, paint_id);
pub(crate) fn update(&mut self,
solid_tiles: &[SolidTile],
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];
@ -62,8 +71,9 @@ impl ZBuffer {
let tile_coords = self.buffer.index_to_coords(tile_index);
let paint_id = self.depth_to_paint_id[depth as usize];
let paint_metadata = &paint_metadata[paint_id.0 as usize];
let depth_metadata = self.depth_metadata[depth as usize];
let paint_metadata = &paint_metadata[depth_metadata.paint_id.0 as usize];
let transform = depth_metadata.transform;
let tile_position = tile_coords + self.buffer.rect.origin();
@ -83,10 +93,16 @@ impl ZBuffer {
let batch = solid_tiles.batches.last_mut().unwrap();
batch.vertices.extend_from_slice(&[
SolidTileVertex::new(tile_position, paint_metadata),
SolidTileVertex::new(tile_position + Vector2I::new(1, 0), paint_metadata),
SolidTileVertex::new(tile_position + Vector2I::new(0, 1), paint_metadata),
SolidTileVertex::new(tile_position + Vector2I::new(1, 1), paint_metadata),
SolidTileVertex::new(tile_position, transform, paint_metadata),
SolidTileVertex::new(tile_position + Vector2I::new(1, 0),
transform,
paint_metadata),
SolidTileVertex::new(tile_position + Vector2I::new(0, 1),
transform,
paint_metadata),
SolidTileVertex::new(tile_position + Vector2I::new(1, 1),
transform,
paint_metadata),
]);
}
@ -95,8 +111,9 @@ impl ZBuffer {
}
impl SolidTileVertex {
fn new(tile_position: Vector2I, paint_metadata: &PaintMetadata) -> SolidTileVertex {
let color_uv = paint_metadata.calculate_tex_coords(tile_position);
fn new(tile_position: Vector2I, transform: Transform2F, paint_metadata: &PaintMetadata)
-> SolidTileVertex {
let color_uv = paint_metadata.calculate_tex_coords(tile_position, transform);
SolidTileVertex {
tile_x: tile_position.x() as i16,
tile_y: tile_position.y() as i16,

View File

@ -3,6 +3,8 @@
# When you add a new resource, make sure to add it to this file.
debug-fonts/regular.json
shaders/gl3/blit.fs.glsl
shaders/gl3/blit.vs.glsl
shaders/gl3/debug_solid.fs.glsl
shaders/gl3/debug_solid.vs.glsl
shaders/gl3/debug_texture.fs.glsl
@ -11,10 +13,6 @@ shaders/gl3/demo_ground.fs.glsl
shaders/gl3/demo_ground.vs.glsl
shaders/gl3/fill.fs.glsl
shaders/gl3/fill.vs.glsl
shaders/gl3/filter.vs.glsl
shaders/gl3/filter_basic.fs.glsl
shaders/gl3/filter_blur.fs.glsl
shaders/gl3/filter_text.fs.glsl
shaders/gl3/mask.vs.glsl
shaders/gl3/mask_evenodd.fs.glsl
shaders/gl3/mask_winding.fs.glsl
@ -37,6 +35,9 @@ shaders/gl3/tile_alpha_overlay.fs.glsl
shaders/gl3/tile_alpha_softlight.fs.glsl
shaders/gl3/tile_copy.fs.glsl
shaders/gl3/tile_copy.vs.glsl
shaders/gl3/tile_filter.vs.glsl
shaders/gl3/tile_filter_blur.fs.glsl
shaders/gl3/tile_filter_text.fs.glsl
shaders/gl3/tile_solid.fs.glsl
shaders/gl3/tile_solid.vs.glsl
shaders/gl3/tile_solid_monochrome.vs.glsl