From 2beb2bb1260042c83d572326745a15ecf59238ac Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Tue, 3 Mar 2020 14:26:38 -0800 Subject: [PATCH] Apply path transforms to paints --- renderer/src/builder.rs | 46 ++++++++++++++++++++-------------------- renderer/src/paint.rs | 8 +++++-- renderer/src/scene.rs | 4 +++- renderer/src/tiles.rs | 35 ++++++++++++++++++------------ renderer/src/z_buffer.rs | 41 ++++++++++++++++++++++++----------- resources/MANIFEST | 9 ++++---- 6 files changed, 87 insertions(+), 56 deletions(-) diff --git a/renderer/src/builder.rs b/renderer/src/builder.rs index 12c5c151..6aeda844 100644 --- a/renderer/src/builder.rs +++ b/renderer/src/builder.rs @@ -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, } } diff --git a/renderer/src/paint.rs b/renderer/src/paint.rs index 76e0556e..b0ef9b18 100644 --- a/renderer/src/paint.rs +++ b/renderer/src/paint.rs @@ -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 } } diff --git a/renderer/src/scene.rs b/renderer/src/scene.rs index 64b2e242..21fa35f4 100644 --- a/renderer/src/scene.rs +++ b/renderer/src/scene.rs @@ -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); diff --git a/renderer/src/tiles.rs b/renderer/src/tiles.rs index 44423dab..4fdf48af 100644 --- a/renderer/src/tiles.rs +++ b/renderer/src/tiles.rs @@ -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); } } diff --git a/renderer/src/z_buffer.rs b/renderer/src/z_buffer.rs index c893158a..669813e4 100644 --- a/renderer/src/z_buffer.rs +++ b/renderer/src/z_buffer.rs @@ -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, - depth_to_paint_id: VecMap, + depth_metadata: VecMap, } pub(crate) struct SolidTiles { pub(crate) batches: Vec, } +#[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, diff --git a/resources/MANIFEST b/resources/MANIFEST index 1b246bba..bb285b02 100644 --- a/resources/MANIFEST +++ b/resources/MANIFEST @@ -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