diff --git a/Cargo.lock b/Cargo.lock index 48a9dfeb..113552ce 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -242,6 +242,7 @@ dependencies = [ "pathfinder_gpu 0.1.0", "pathfinder_metal 0.1.0", "pathfinder_renderer 0.1.0", + "pathfinder_resources 0.1.0", "sdl2 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)", "sdl2-sys 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -293,6 +294,7 @@ dependencies = [ "pathfinder_gl 0.1.0", "pathfinder_gpu 0.1.0", "pathfinder_renderer 0.1.0", + "pathfinder_resources 0.1.0", "sdl2 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)", "sdl2-sys 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1819,6 +1821,7 @@ dependencies = [ "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] diff --git a/examples/canvas_metal_minimal/Cargo.toml b/examples/canvas_metal_minimal/Cargo.toml index b1c862fa..79fd2fb5 100644 --- a/examples/canvas_metal_minimal/Cargo.toml +++ b/examples/canvas_metal_minimal/Cargo.toml @@ -36,3 +36,6 @@ path = "../../metal" [dependencies.pathfinder_renderer] path = "../../renderer" + +[dependencies.pathfinder_resources] +path = "../../resources" diff --git a/examples/canvas_nanovg/Cargo.toml b/examples/canvas_nanovg/Cargo.toml index 0a76cc63..f954c5e7 100644 --- a/examples/canvas_nanovg/Cargo.toml +++ b/examples/canvas_nanovg/Cargo.toml @@ -31,3 +31,6 @@ path = "../../gpu" [dependencies.pathfinder_renderer] path = "../../renderer" + +[dependencies.pathfinder_resources] +path = "../../resources" diff --git a/renderer/Cargo.toml b/renderer/Cargo.toml index 8b1037dc..a228ed2b 100644 --- a/renderer/Cargo.toml +++ b/renderer/Cargo.toml @@ -12,6 +12,7 @@ rayon = "1.0" serde = "1.0" serde_json = "1.0" smallvec = "1.2" +vec_map = "0.8" [dependencies.log] version = "0.4" diff --git a/renderer/src/builder.rs b/renderer/src/builder.rs index 16482de7..8e60398d 100644 --- a/renderer/src/builder.rs +++ b/renderer/src/builder.rs @@ -13,7 +13,8 @@ use crate::concurrent::executor::Executor; use crate::gpu::renderer::{BlendModeProgram, MASK_TILES_ACROSS}; use crate::gpu_data::{AlphaTile, AlphaTileBatch, AlphaTileVertex, FillBatchPrimitive, MaskTile}; -use crate::gpu_data::{MaskTileVertex, PaintPageId, RenderCommand}; +use crate::gpu_data::{MaskTileVertex, PaintPageId, RenderCommand, RenderTargetTile}; +use crate::gpu_data::{RenderTargetTileBatch, RenderTargetTileVertex}; use crate::gpu_data::{SolidTileBatch, TileObjectPrimitive}; use crate::options::{PreparedBuildOptions, RenderCommandListener}; use crate::paint::{PaintInfo, PaintMetadata}; @@ -21,7 +22,7 @@ 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 pathfinder_content::effects::{BlendMode, Effects}; +use pathfinder_content::effects::BlendMode; use pathfinder_content::fill::FillRule; use pathfinder_content::pattern::RenderTargetId; use pathfinder_geometry::line_segment::{LineSegment2F, LineSegmentU4, LineSegmentU8}; @@ -219,92 +220,110 @@ impl<'a> SceneBuilder<'a> { // Process first Z-buffer. let first_z_buffer = remaining_layer_z_buffers.pop().unwrap(); - let first_solid_tiles = first_z_buffer.build_solid_tiles(&self.scene.paths, - paint_metadata); + let first_solid_tiles = first_z_buffer.build_solid_tiles(paint_metadata); for batch in first_solid_tiles.batches { culled_tiles.display_list.push(CulledDisplayItem::DrawSolidTiles(batch)); } let mut layer_z_buffers_stack = vec![first_z_buffer]; + let mut current_depth = 1; for display_item in &self.scene.display_list { - // Pass all commands except `DrawPaths` through. - let (start_draw_path_index, end_draw_path_index) = match *display_item { + match *display_item { DisplayItem::PushRenderTarget(render_target_id) => { culled_tiles.display_list .push(CulledDisplayItem::PushRenderTarget(render_target_id)); let z_buffer = remaining_layer_z_buffers.pop().unwrap(); - let solid_tiles = z_buffer.build_solid_tiles(&self.scene.paths, - paint_metadata); + let solid_tiles = z_buffer.build_solid_tiles(paint_metadata); for batch in solid_tiles.batches { culled_tiles.display_list.push(CulledDisplayItem::DrawSolidTiles(batch)); } layer_z_buffers_stack.push(z_buffer); - continue; } + DisplayItem::PopRenderTarget => { culled_tiles.display_list.push(CulledDisplayItem::PopRenderTarget); layer_z_buffers_stack.pop(); - continue; } + DisplayItem::DrawRenderTarget { render_target, effects } => { - culled_tiles.display_list.push(CulledDisplayItem::DrawRenderTarget { - render_target, - effects, - }); - continue; - } - DisplayItem::DrawPaths { start_index, end_index } => (start_index, end_index), - }; - - for draw_path_index in start_draw_path_index..end_draw_path_index { - let built_draw_path = &built_draw_paths[draw_path_index as usize]; - culled_tiles.push_mask_tiles(&built_draw_path.path); - - // Create a new `DrawAlphaTiles` display item if we don't have one or if we have to - // break a batch due to blend mode or paint page. Note that every path with a blend - // mode that requires a readable framebuffer needs its own batch. - // - // TODO(pcwalton): If we really wanted to, we could use tile maps to avoid batch - // breaks in some cases… - match culled_tiles.display_list.last() { - Some(&CulledDisplayItem::DrawAlphaTiles(AlphaTileBatch { - tiles: _, - paint_page, - blend_mode, - sampling_flags - })) if paint_page == built_draw_path.paint_page && - blend_mode == built_draw_path.blend_mode && - sampling_flags == built_draw_path.sampling_flags && - !BlendModeProgram::from_blend_mode( - blend_mode).needs_readable_framebuffer() => {} - _ => { - culled_tiles.display_list - .push(CulledDisplayItem::DrawAlphaTiles(AlphaTileBatch { - tiles: vec![], - paint_page: built_draw_path.paint_page, - blend_mode: built_draw_path.blend_mode, - sampling_flags: built_draw_path.sampling_flags, - })) + let effective_view_box = self.scene.effective_view_box(self.built_options); + let tile_rect = tiles::round_rect_out_to_tile_bounds(effective_view_box); + let layer_z_buffer = layer_z_buffers_stack.last().unwrap(); + let mut tiles = vec![]; + for tile_y in tile_rect.min_y()..tile_rect.max_y() { + for tile_x in tile_rect.min_x()..tile_rect.max_x() { + let tile_coords = Vector2I::new(tile_x, tile_y); + if layer_z_buffer.test(tile_coords, current_depth) { + tiles.push(RenderTargetTile::new(tile_coords)); + } + } } + let batch = RenderTargetTileBatch { tiles, render_target, effects }; + culled_tiles.display_list + .push(CulledDisplayItem::DrawRenderTargetTiles(batch)); + current_depth += 1; } - // Fetch the destination alpha tiles buffer. - let culled_alpha_tiles = match *culled_tiles.display_list.last_mut().unwrap() { - CulledDisplayItem::DrawAlphaTiles(AlphaTileBatch { - tiles: ref mut culled_alpha_tiles, - .. - }) => culled_alpha_tiles, - _ => unreachable!(), - }; + DisplayItem::DrawPaths { + start_index: start_draw_path_index, + end_index: end_draw_path_index, + } => { + for draw_path_index in start_draw_path_index..end_draw_path_index { + let built_draw_path = &built_draw_paths[draw_path_index as usize]; + culled_tiles.push_mask_tiles(&built_draw_path.path); - let layer_z_buffer = layer_z_buffers_stack.last().unwrap(); - for alpha_tile in &built_draw_path.path.alpha_tiles { - let alpha_tile_coords = alpha_tile.upper_left.tile_position(); - if layer_z_buffer.test(alpha_tile_coords, - alpha_tile.upper_left.object_index as u32) { - culled_alpha_tiles.push(*alpha_tile); + // Create a new `DrawAlphaTiles` display item if we don't have one or if we + // have to break a batch due to blend mode or paint page. Note that every + // path with a blend mode that requires a readable framebuffer needs its + // own batch. + // + // TODO(pcwalton): If we really wanted to, we could use tile maps to avoid + // batch breaks in some cases… + match culled_tiles.display_list.last() { + Some(&CulledDisplayItem::DrawAlphaTiles(AlphaTileBatch { + tiles: _, + paint_page, + blend_mode, + sampling_flags + })) if paint_page == built_draw_path.paint_page && + blend_mode == built_draw_path.blend_mode && + sampling_flags == built_draw_path.sampling_flags && + !BlendModeProgram::from_blend_mode( + blend_mode).needs_readable_framebuffer() => {} + _ => { + let batch = AlphaTileBatch { + tiles: vec![], + paint_page: built_draw_path.paint_page, + blend_mode: built_draw_path.blend_mode, + sampling_flags: built_draw_path.sampling_flags, + }; + culled_tiles.display_list + .push(CulledDisplayItem::DrawAlphaTiles(batch)) + } + } + + // Fetch the destination alpha tiles buffer. + let culled_alpha_tiles = match *culled_tiles.display_list + .last_mut() + .unwrap() { + CulledDisplayItem::DrawAlphaTiles(AlphaTileBatch { + tiles: ref mut culled_alpha_tiles, + .. + }) => culled_alpha_tiles, + _ => unreachable!(), + }; + + let layer_z_buffer = layer_z_buffers_stack.last().unwrap(); + for alpha_tile in &built_draw_path.path.alpha_tiles { + let alpha_tile_coords = alpha_tile.upper_left.tile_position(); + if layer_z_buffer.test(alpha_tile_coords, current_depth) { + culled_alpha_tiles.push(*alpha_tile); + } + } + + current_depth += 1; } } } @@ -317,6 +336,7 @@ impl<'a> SceneBuilder<'a> { let effective_view_box = self.scene.effective_view_box(self.built_options); let mut z_buffers = vec![ZBuffer::new(effective_view_box)]; let mut z_buffer_index_stack = vec![0]; + let mut current_depth = 0; // Create Z-buffers. for display_item in &self.scene.display_list { @@ -333,12 +353,16 @@ impl<'a> SceneBuilder<'a> { let z_buffer = &mut z_buffers[*z_buffer_index_stack.last().unwrap()]; for (path_subindex, built_draw_path) in built_draw_paths[start_index..end_index].iter().enumerate() { - z_buffer.update(&built_draw_path.path.solid_tiles, - (path_subindex + start_index) as u32); + 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); + current_depth += 1; } } DisplayItem::DrawRenderTarget { .. } => { // FIXME(pcwalton): Not great that this doesn't participate in Z-buffering! + current_depth += 1; } } } @@ -369,8 +393,8 @@ impl<'a> SceneBuilder<'a> { CulledDisplayItem::DrawAlphaTiles(batch) => { self.listener.send(RenderCommand::DrawAlphaTiles(batch)) } - CulledDisplayItem::DrawRenderTarget { render_target, effects } => { - self.listener.send(RenderCommand::DrawRenderTarget { render_target, effects }) + CulledDisplayItem::DrawRenderTargetTiles(batch) => { + self.listener.send(RenderCommand::DrawRenderTargetTiles(batch)) } CulledDisplayItem::PushRenderTarget(render_target_id) => { self.listener.send(RenderCommand::PushRenderTarget(render_target_id)) @@ -449,7 +473,7 @@ struct CulledTiles { enum CulledDisplayItem { DrawSolidTiles(SolidTileBatch), DrawAlphaTiles(AlphaTileBatch), - DrawRenderTarget { render_target: RenderTargetId, effects: Effects }, + DrawRenderTargetTiles(RenderTargetTileBatch), PushRenderTarget(RenderTargetId), PopRenderTarget, } @@ -774,3 +798,20 @@ impl CulledTiles { } } } + +impl RenderTargetTile { + fn new(tile_coords: Vector2I) -> RenderTargetTile { + RenderTargetTile { + upper_left: RenderTargetTileVertex::new(tile_coords), + upper_right: RenderTargetTileVertex::new(tile_coords + Vector2I::new(1, 0)), + lower_left: RenderTargetTileVertex::new(tile_coords + Vector2I::new(0, 1)), + lower_right: RenderTargetTileVertex::new(tile_coords + Vector2I::splat(1)), + } + } +} + +impl RenderTargetTileVertex { + fn new(tile_coords: Vector2I) -> RenderTargetTileVertex { + RenderTargetTileVertex { tile_x: tile_coords.x() as i16, tile_y: tile_coords.y() as i16 } + } +} diff --git a/renderer/src/gpu/renderer.rs b/renderer/src/gpu/renderer.rs index ea1198ca..62941149 100644 --- a/renderer/src/gpu/renderer.rs +++ b/renderer/src/gpu/renderer.rs @@ -12,15 +12,14 @@ use crate::gpu::debug::DebugUIPresenter; use crate::gpu::options::{DestFramebuffer, RendererOptions}; use crate::gpu::shaders::{AlphaTileBlendModeProgram, AlphaTileDodgeBurnProgram}; use crate::gpu::shaders::{AlphaTileHSLProgram, AlphaTileOverlayProgram}; -use crate::gpu::shaders::{AlphaTileProgram, AlphaTileVertexArray, CopyTileProgram}; -use crate::gpu::shaders::{CopyTileVertexArray, FillProgram, FillVertexArray, FilterBasicProgram}; -use crate::gpu::shaders::{FilterBasicVertexArray,FilterBlurProgram, FilterBlurVertexArray}; -use crate::gpu::shaders::{FilterTextProgram, FilterTextVertexArray, MAX_FILLS_PER_BATCH}; +use crate::gpu::shaders::{AlphaTileProgram, AlphaTileVertexArray, BlitProgram, BlitVertexArray, CopyTileProgram}; +use crate::gpu::shaders::{CopyTileVertexArray, FillProgram, FillVertexArray}; +use crate::gpu::shaders::{MAX_FILLS_PER_BATCH}; use crate::gpu::shaders::{MaskTileProgram, MaskTileVertexArray, ReprojectionProgram}; use crate::gpu::shaders::{ReprojectionVertexArray, SolidTileProgram, SolidTileVertexArray}; -use crate::gpu::shaders::{StencilProgram, StencilVertexArray}; +use crate::gpu::shaders::{StencilProgram, StencilVertexArray, TileFilterBasicProgram, TileFilterBlurProgram, TileFilterProgram, TileFilterTextProgram, TileFilterVertexArray}; use crate::gpu_data::{AlphaTile, FillBatchPrimitive, MaskTile, PaintData, PaintPageContents}; -use crate::gpu_data::{PaintPageId, RenderCommand, SolidTileVertex}; +use crate::gpu_data::{PaintPageId, RenderCommand, RenderTargetTile, SolidTileVertex}; use crate::options::BoundingQuad; use crate::tiles::{TILE_HEIGHT, TILE_WIDTH}; use pathfinder_color::{self as color, ColorF}; @@ -78,6 +77,7 @@ where // Core data dest_framebuffer: DestFramebuffer, options: RendererOptions, + blit_program: BlitProgram, fill_program: FillProgram, mask_winding_tile_program: MaskTileProgram, mask_evenodd_tile_program: MaskTileProgram, @@ -90,6 +90,7 @@ where alpha_tile_difference_program: AlphaTileBlendModeProgram, alpha_tile_exclusion_program: AlphaTileBlendModeProgram, alpha_tile_hsl_program: AlphaTileHSLProgram, + blit_vertex_array: BlitVertexArray, mask_winding_tile_vertex_array: MaskTileVertexArray, mask_evenodd_tile_vertex_array: MaskTileVertexArray, copy_tile_vertex_array: CopyTileVertexArray, @@ -122,12 +123,13 @@ where clear_paint_texture: D::Texture, // Filter shaders - filter_basic_program: FilterBasicProgram, - filter_basic_vertex_array: FilterBasicVertexArray, - filter_blur_program: FilterBlurProgram, - filter_blur_vertex_array: FilterBlurVertexArray, - filter_text_program: FilterTextProgram, - filter_text_vertex_array: FilterTextVertexArray, + tile_filter_basic_program: TileFilterBasicProgram, + tile_filter_blur_program: TileFilterBlurProgram, + tile_filter_text_program: TileFilterTextProgram, + tile_filter_basic_vertex_array: TileFilterVertexArray, + tile_filter_blur_vertex_array: TileFilterVertexArray, + tile_filter_text_vertex_array: TileFilterVertexArray, + tile_filter_vertex_buffer: D::Buffer, gamma_lut_texture: D::Texture, // Stencil shader @@ -163,6 +165,7 @@ where dest_framebuffer: DestFramebuffer, options: RendererOptions) -> Renderer { + let blit_program = BlitProgram::new(&device, resources); let fill_program = FillProgram::new(&device, resources); let mask_winding_tile_program = MaskTileProgram::new(FillRule::Winding, &device, @@ -184,9 +187,9 @@ where resources, "tile_alpha_exclusion"); let alpha_tile_hsl_program = AlphaTileHSLProgram::new(&device, resources); - let filter_basic_program = FilterBasicProgram::new(&device, resources); - let filter_blur_program = FilterBlurProgram::new(&device, resources); - let filter_text_program = FilterTextProgram::new(&device, resources); + let tile_filter_basic_program = TileFilterBasicProgram::new(&device, resources); + let tile_filter_blur_program = TileFilterBlurProgram::new(&device, resources); + let tile_filter_text_program = TileFilterTextProgram::new(&device, resources); let stencil_program = StencilProgram::new(&device, resources); let reprojection_program = ReprojectionProgram::new(&device, resources); @@ -194,6 +197,7 @@ where let gamma_lut_texture = device.create_texture_from_png(resources, "gamma-lut"); let alpha_tile_vertex_buffer = device.create_buffer(); + let tile_filter_vertex_buffer = device.create_buffer(); let quad_vertex_positions_buffer = device.create_buffer(); device.allocate_buffer( &quad_vertex_positions_buffer, @@ -210,6 +214,12 @@ where ); let quads_vertex_indices_buffer = device.create_buffer(); + let blit_vertex_array = BlitVertexArray::new( + &device, + &blit_program, + &quad_vertex_positions_buffer, + &quad_vertex_indices_buffer, + ); let fill_vertex_array = FillVertexArray::new( &device, &fill_program, @@ -279,23 +289,23 @@ where &solid_tile_program, &quads_vertex_indices_buffer, ); - let filter_basic_vertex_array = FilterBasicVertexArray::new( + let tile_filter_basic_vertex_array = TileFilterVertexArray::new( &device, - &filter_basic_program, - &quad_vertex_positions_buffer, - &quad_vertex_indices_buffer, + &tile_filter_basic_program.tile_filter_program, + &tile_filter_vertex_buffer, + &quads_vertex_indices_buffer, ); - let filter_blur_vertex_array = FilterBlurVertexArray::new( + let tile_filter_blur_vertex_array = TileFilterVertexArray::new( &device, - &filter_blur_program, - &quad_vertex_positions_buffer, - &quad_vertex_indices_buffer, + &tile_filter_blur_program.tile_filter_program, + &tile_filter_vertex_buffer, + &quads_vertex_indices_buffer, ); - let filter_text_vertex_array = FilterTextVertexArray::new( + let tile_filter_text_vertex_array = TileFilterVertexArray::new( &device, - &filter_text_program, - &quad_vertex_positions_buffer, - &quad_vertex_indices_buffer, + &tile_filter_text_program.tile_filter_program, + &tile_filter_vertex_buffer, + &quads_vertex_indices_buffer, ); let stencil_vertex_array = StencilVertexArray::new(&device, &stencil_program); let reprojection_vertex_array = ReprojectionVertexArray::new( @@ -335,6 +345,7 @@ where dest_framebuffer, options, + blit_program, fill_program, mask_winding_tile_program, mask_evenodd_tile_program, @@ -347,6 +358,7 @@ where alpha_tile_difference_program, alpha_tile_exclusion_program, alpha_tile_hsl_program, + blit_vertex_array, mask_winding_tile_vertex_array, mask_evenodd_tile_vertex_array, copy_tile_vertex_array, @@ -374,12 +386,13 @@ where render_target_stack: vec![], clear_paint_texture, - filter_basic_program, - filter_basic_vertex_array, - filter_blur_program, - filter_blur_vertex_array, - filter_text_program, - filter_text_vertex_array, + tile_filter_basic_program, + tile_filter_basic_vertex_array, + tile_filter_blur_program, + tile_filter_blur_vertex_array, + tile_filter_text_program, + tile_filter_text_vertex_array, + tile_filter_vertex_buffer, gamma_lut_texture, stencil_program, @@ -428,8 +441,10 @@ where self.push_render_target(render_target_id) } RenderCommand::PopRenderTarget => self.pop_render_target(), - RenderCommand::DrawRenderTarget { render_target, effects } => { - self.draw_entire_render_target(render_target, effects) + RenderCommand::DrawRenderTargetTiles(ref batch) => { + let count = batch.tiles.len(); + self.upload_render_target_tiles(&batch.tiles); + self.draw_render_target_tiles(count as u32, batch.render_target, batch.effects) } RenderCommand::DrawSolidTiles(ref batch) => { let count = batch.vertices.len() / 4; @@ -630,6 +645,14 @@ where self.ensure_index_buffer(alpha_tiles.len()); } + fn upload_render_target_tiles(&mut self, render_target_tiles: &[RenderTargetTile]) { + self.device.allocate_buffer(&self.tile_filter_vertex_buffer, + BufferData::Memory(&render_target_tiles), + BufferTarget::Vertex, + BufferUploadMode::Dynamic); + self.ensure_index_buffer(render_target_tiles.len()); + } + fn ensure_index_buffer(&mut self, mut length: usize) { length = length.next_power_of_two(); if self.quads_vertex_indices_length >= length { @@ -1152,118 +1175,92 @@ where } // FIXME(pcwalton): This is inefficient and should eventually go away. - fn draw_entire_render_target(&mut self, render_target_id: RenderTargetId, effects: Effects) { + fn draw_render_target_tiles(&mut self, + count: u32, + render_target_id: RenderTargetId, + effects: Effects) { match effects.filter { Filter::Composite(composite_op) => { - self.composite_render_target(render_target_id, composite_op) + self.composite_render_target(count, render_target_id, composite_op) } Filter::Text { fg_color, bg_color, defringing_kernel, gamma_correction } => { - self.draw_text_render_target(render_target_id, + self.draw_text_render_target(count, + render_target_id, fg_color, bg_color, defringing_kernel, gamma_correction) } Filter::Blur { direction, sigma } => { - self.draw_blur_render_target(render_target_id, direction, sigma) + self.draw_blur_render_target(count, render_target_id, direction, sigma) } } self.preserve_draw_framebuffer(); } - fn composite_render_target(&self, + fn composite_render_target(&mut self, + tile_count: u32, render_target_id: RenderTargetId, composite_op: CompositeOp) { - let clear_color = self.clear_color_for_draw_operation(); - let source_framebuffer = &self.render_targets[render_target_id.0 as usize].framebuffer; - let source_texture = self.device.framebuffer_texture(source_framebuffer); - let main_viewport = self.main_viewport(); + self.finish_drawing_render_target_tiles(&self.tile_filter_basic_program + .tile_filter_program, + &self.tile_filter_basic_vertex_array, + tile_count, + render_target_id, + vec![], + vec![], + composite_op.to_blend_state()); - let uniforms = vec![ - (&self.filter_basic_program.framebuffer_size_uniform, - UniformData::Vec2(main_viewport.size().to_f32().0)), - (&self.filter_basic_program.source_uniform, UniformData::TextureUnit(0)), - ]; - - let blend_state = composite_op.to_blend_state(); - - self.device.draw_elements(6, &RenderState { - target: &self.draw_render_target(), - program: &self.filter_basic_program.program, - vertex_array: &self.filter_basic_vertex_array.vertex_array, - primitive: Primitive::Triangles, - textures: &[&source_texture], - uniforms: &uniforms, - viewport: main_viewport, - options: RenderOptions { - clear_ops: ClearOps { color: clear_color, ..ClearOps::default() }, - blend: blend_state, - ..RenderOptions::default() - }, - }); + self.preserve_draw_framebuffer(); } - fn draw_text_render_target(&self, + fn draw_text_render_target(&mut self, + tile_count: u32, render_target_id: RenderTargetId, fg_color: ColorF, bg_color: ColorF, defringing_kernel: Option, gamma_correction: bool) { - let clear_color = self.clear_color_for_draw_operation(); - let source_framebuffer = &self.render_targets[render_target_id.0 as usize].framebuffer; - let source_texture = self.device.framebuffer_texture(source_framebuffer); - let source_texture_size = self.device.texture_size(source_texture); - let main_viewport = self.main_viewport(); - + let textures = vec![&self.gamma_lut_texture]; let mut uniforms = vec![ - (&self.filter_text_program.framebuffer_size_uniform, - UniformData::Vec2(main_viewport.size().to_f32().0)), - (&self.filter_text_program.source_uniform, UniformData::TextureUnit(0)), - (&self.filter_text_program.source_size_uniform, - UniformData::Vec2(source_texture_size.0.to_f32x2())), - (&self.filter_text_program.gamma_lut_uniform, UniformData::TextureUnit(1)), - (&self.filter_text_program.fg_color_uniform, UniformData::Vec4(fg_color.0)), - (&self.filter_text_program.bg_color_uniform, UniformData::Vec4(bg_color.0)), - (&self.filter_text_program.gamma_correction_enabled_uniform, + (&self.tile_filter_text_program.gamma_lut_uniform, UniformData::TextureUnit(0)), + (&self.tile_filter_text_program.fg_color_uniform, UniformData::Vec4(fg_color.0)), + (&self.tile_filter_text_program.bg_color_uniform, UniformData::Vec4(bg_color.0)), + (&self.tile_filter_text_program.gamma_correction_enabled_uniform, UniformData::Int(gamma_correction as i32)), ]; match defringing_kernel { Some(ref kernel) => { - uniforms.push((&self.filter_text_program.kernel_uniform, + uniforms.push((&self.tile_filter_text_program.kernel_uniform, UniformData::Vec4(F32x4::from_slice(&kernel.0)))); } None => { - uniforms.push((&self.filter_text_program.kernel_uniform, + uniforms.push((&self.tile_filter_text_program.kernel_uniform, UniformData::Vec4(F32x4::default()))); } } - self.device.draw_elements(6, &RenderState { - target: &self.draw_render_target(), - program: &self.filter_text_program.program, - vertex_array: &self.filter_text_vertex_array.vertex_array, - primitive: Primitive::Triangles, - textures: &[&source_texture, &self.gamma_lut_texture], - uniforms: &uniforms, - viewport: main_viewport, - options: RenderOptions { - clear_ops: ClearOps { color: clear_color, ..ClearOps::default() }, - ..RenderOptions::default() - }, - }); + self.finish_drawing_render_target_tiles(&self.tile_filter_text_program.tile_filter_program, + &self.tile_filter_text_vertex_array, + tile_count, + render_target_id, + uniforms, + textures, + None); + + self.preserve_draw_framebuffer(); } - fn draw_blur_render_target(&self, + fn draw_blur_render_target(&mut self, + tile_count: u32, render_target_id: RenderTargetId, direction: BlurDirection, sigma: f32) { - let clear_color = self.clear_color_for_draw_operation(); let source_framebuffer = &self.render_targets[render_target_id.0 as usize].framebuffer; let source_texture = self.device.framebuffer_texture(source_framebuffer); let source_texture_size = self.device.texture_size(source_texture); - let main_viewport = self.main_viewport(); let sigma_inv = 1.0 / sigma; let gauss_coeff_x = SQRT_2_PI_INV * sigma_inv; @@ -1277,28 +1274,62 @@ where let src_offset_scale = src_offset / source_texture_size.to_f32(); let uniforms = vec![ - (&self.filter_blur_program.framebuffer_size_uniform, - UniformData::Vec2(main_viewport.size().to_f32().0)), - (&self.filter_blur_program.src_uniform, UniformData::TextureUnit(0)), - (&self.filter_blur_program.src_offset_scale_uniform, + (&self.tile_filter_blur_program.src_offset_scale_uniform, UniformData::Vec2(src_offset_scale.0)), - (&self.filter_blur_program.initial_gauss_coeff_uniform, + (&self.tile_filter_blur_program.initial_gauss_coeff_uniform, UniformData::Vec3([gauss_coeff_x, gauss_coeff_y, gauss_coeff_z])), - (&self.filter_blur_program.support_uniform, + (&self.tile_filter_blur_program.support_uniform, UniformData::Int(f32::ceil(1.5 * sigma) as i32 * 2)), ]; - self.device.draw_elements(6, &RenderState { + self.finish_drawing_render_target_tiles(&self.tile_filter_blur_program.tile_filter_program, + &self.tile_filter_blur_vertex_array, + tile_count, + render_target_id, + uniforms, + vec![], + CompositeOp::SrcOver.to_blend_state()); + + self.preserve_draw_framebuffer(); + } + + fn finish_drawing_render_target_tiles<'a>( + &'a self, + tile_filter_program: &'a TileFilterProgram, + tile_filter_vertex_array: &'a TileFilterVertexArray, + tile_count: u32, + render_target_id: RenderTargetId, + mut uniforms: Vec<(&'a D::Uniform, UniformData)>, + mut textures: Vec<&'a D::Texture>, + blend_state: Option) { + let clear_color = self.clear_color_for_draw_operation(); + let main_viewport = self.main_viewport(); + let src_framebuffer = &self.render_targets[render_target_id.0 as usize].framebuffer; + let src_texture = self.device.framebuffer_texture(src_framebuffer); + let src_texture_size = self.device.texture_size(src_texture); + + uniforms.extend_from_slice(&[ + (&tile_filter_program.src_uniform, UniformData::TextureUnit(textures.len() as u32)), + (&tile_filter_program.src_size_uniform, + UniformData::Vec2(src_texture_size.0.to_f32x2())), + (&tile_filter_program.transform_uniform, + UniformData::Mat4(self.tile_transform().to_columns())), + (&tile_filter_program.tile_size_uniform, + UniformData::Vec2(F32x2::new(TILE_WIDTH as f32, TILE_HEIGHT as f32))), + ]); + textures.push(src_texture); + + self.device.draw_elements(6 * tile_count, &RenderState { target: &self.draw_render_target(), - program: &self.filter_blur_program.program, - vertex_array: &self.filter_blur_vertex_array.vertex_array, + program: &tile_filter_program.program, + vertex_array: &tile_filter_vertex_array.vertex_array, primitive: Primitive::Triangles, - textures: &[&source_texture], + textures: &textures, uniforms: &uniforms, viewport: main_viewport, options: RenderOptions { clear_ops: ClearOps { color: clear_color, ..ClearOps::default() }, - blend: CompositeOp::SrcOver.to_blend_state(), + blend: blend_state, ..RenderOptions::default() }, }); @@ -1311,13 +1342,13 @@ where let main_viewport = self.main_viewport(); - let uniforms = [(&self.filter_basic_program.source_uniform, UniformData::TextureUnit(0))]; + let uniforms = [(&self.blit_program.src_uniform, UniformData::TextureUnit(0))]; let textures = [(self.device.framebuffer_texture(&self.intermediate_dest_framebuffer))]; self.device.draw_elements(6, &RenderState { target: &RenderTarget::Default, - program: &self.filter_basic_program.program, - vertex_array: &self.filter_basic_vertex_array.vertex_array, + program: &self.blit_program.program, + vertex_array: &self.blit_vertex_array.vertex_array, primitive: Primitive::Triangles, textures: &textures[..], uniforms: &uniforms[..], diff --git a/renderer/src/gpu/shaders.rs b/renderer/src/gpu/shaders.rs index c3a10698..6eac750b 100644 --- a/renderer/src/gpu/shaders.rs +++ b/renderer/src/gpu/shaders.rs @@ -18,10 +18,40 @@ use pathfinder_resources::ResourceLoader; const FILL_INSTANCE_SIZE: usize = 8; const SOLID_TILE_VERTEX_SIZE: usize = 16; const ALPHA_TILE_VERTEX_SIZE: usize = 20; +const FILTER_TILE_VERTEX_SIZE: usize = 4; const MASK_TILE_VERTEX_SIZE: usize = 12; pub const MAX_FILLS_PER_BATCH: usize = 0x4000; +pub struct BlitVertexArray where D: Device { + pub vertex_array: D::VertexArray, +} + +impl BlitVertexArray where D: Device { + pub fn new(device: &D, + blit_program: &BlitProgram, + quad_vertex_positions_buffer: &D::Buffer, + quad_vertex_indices_buffer: &D::Buffer) + -> BlitVertexArray { + let vertex_array = device.create_vertex_array(); + let position_attr = device.get_vertex_attr(&blit_program.program, "Position").unwrap(); + + device.bind_buffer(&vertex_array, quad_vertex_positions_buffer, BufferTarget::Vertex); + device.configure_vertex_attr(&vertex_array, &position_attr, &VertexAttrDescriptor { + size: 2, + class: VertexAttrClass::Int, + attr_type: VertexAttrType::I16, + stride: 4, + offset: 0, + divisor: 0, + buffer_index: 0, + }); + device.bind_buffer(&vertex_array, quad_vertex_indices_buffer, BufferTarget::Index); + + BlitVertexArray { vertex_array } + } +} + pub struct FillVertexArray where D: Device, @@ -323,6 +353,19 @@ impl CopyTileVertexArray where D: Device { } } +pub struct BlitProgram where D: Device { + pub program: D::Program, + pub src_uniform: D::Uniform, +} + +impl BlitProgram where D: Device { + pub fn new(device: &D, resources: &dyn ResourceLoader) -> BlitProgram { + let program = device.create_program(resources, "blit"); + let src_uniform = device.get_uniform(&program, "Src"); + BlitProgram { program, src_uniform } + } +} + pub struct FillProgram where D: Device, @@ -523,79 +566,101 @@ impl AlphaTileDodgeBurnProgram where D: Device { } } -pub struct FilterBasicProgram where D: Device { +pub struct TileFilterProgram where D: Device { pub program: D::Program, - pub source_uniform: D::Uniform, - pub framebuffer_size_uniform: D::Uniform, + pub transform_uniform: D::Uniform, + pub tile_size_uniform: D::Uniform, + pub src_uniform: D::Uniform, + pub src_size_uniform: D::Uniform, } -impl FilterBasicProgram where D: Device { - pub fn new(device: &D, resources: &dyn ResourceLoader) -> FilterBasicProgram { +impl TileFilterProgram where D: Device { + pub fn new(device: &D, + resources: &dyn ResourceLoader, + program_name: &str, + fragment_shader_name: &str) + -> TileFilterProgram { let program = device.create_program_from_shader_names(resources, - "filter_basic", - "filter", - "filter_basic"); - let source_uniform = device.get_uniform(&program, "Source"); - let framebuffer_size_uniform = device.get_uniform(&program, "FramebufferSize"); - FilterBasicProgram { program, source_uniform, framebuffer_size_uniform } + program_name, + "tile_filter", + fragment_shader_name); + let transform_uniform = device.get_uniform(&program, "Transform"); + let tile_size_uniform = device.get_uniform(&program, "TileSize"); + let src_uniform = device.get_uniform(&program, "Src"); + let src_size_uniform = device.get_uniform(&program, "SrcSize"); + TileFilterProgram { + program, + transform_uniform, + tile_size_uniform, + src_uniform, + src_size_uniform, + } } } -pub struct FilterBasicVertexArray where D: Device { +pub struct TileFilterBasicProgram where D: Device { + pub tile_filter_program: TileFilterProgram, +} + +impl TileFilterBasicProgram where D: Device { + pub fn new(device: &D, resources: &dyn ResourceLoader) -> TileFilterBasicProgram { + TileFilterBasicProgram { + tile_filter_program: TileFilterProgram::new(device, resources, "filter_basic", "blit"), + } + } +} + +pub struct TileFilterVertexArray where D: Device { pub vertex_array: D::VertexArray, } -impl FilterBasicVertexArray where D: Device { - pub fn new( - device: &D, - fill_basic_program: &FilterBasicProgram, - quad_vertex_positions_buffer: &D::Buffer, - quad_vertex_indices_buffer: &D::Buffer, - ) -> FilterBasicVertexArray { +impl TileFilterVertexArray where D: Device { + pub fn new(device: &D, + tile_filter_program: &TileFilterProgram, + tile_filter_vertex_buffer: &D::Buffer, + quads_vertex_indices_buffer: &D::Buffer) + -> TileFilterVertexArray { let vertex_array = device.create_vertex_array(); - let position_attr = device.get_vertex_attr(&fill_basic_program.program, "Position") - .unwrap(); - device.bind_buffer(&vertex_array, quad_vertex_positions_buffer, BufferTarget::Vertex); - device.configure_vertex_attr(&vertex_array, &position_attr, &VertexAttrDescriptor { + let tile_position_attr = + device.get_vertex_attr(&tile_filter_program.program, "TilePosition").unwrap(); + + device.bind_buffer(&vertex_array, tile_filter_vertex_buffer, BufferTarget::Vertex); + device.configure_vertex_attr(&vertex_array, &tile_position_attr, &VertexAttrDescriptor { size: 2, class: VertexAttrClass::Int, attr_type: VertexAttrType::I16, - stride: 4, + stride: FILTER_TILE_VERTEX_SIZE, offset: 0, divisor: 0, buffer_index: 0, }); - device.bind_buffer(&vertex_array, quad_vertex_indices_buffer, BufferTarget::Index); + device.bind_buffer(&vertex_array, quads_vertex_indices_buffer, BufferTarget::Index); - FilterBasicVertexArray { vertex_array } + TileFilterVertexArray { vertex_array } } } -pub struct FilterBlurProgram where D: Device { - pub program: D::Program, - pub framebuffer_size_uniform: D::Uniform, - pub src_uniform: D::Uniform, +pub struct TileFilterBlurProgram where D: Device { + pub tile_filter_program: TileFilterProgram, pub src_offset_scale_uniform: D::Uniform, pub initial_gauss_coeff_uniform: D::Uniform, pub support_uniform: D::Uniform, } -impl FilterBlurProgram where D: Device { - pub fn new(device: &D, resources: &dyn ResourceLoader) -> FilterBlurProgram { - let program = device.create_program_from_shader_names(resources, - "filter_blur", - "filter", - "filter_blur"); - let framebuffer_size_uniform = device.get_uniform(&program, "FramebufferSize"); - let src_uniform = device.get_uniform(&program, "Src"); - let src_offset_scale_uniform = device.get_uniform(&program, "SrcOffsetScale"); - let initial_gauss_coeff_uniform = device.get_uniform(&program, "InitialGaussCoeff"); - let support_uniform = device.get_uniform(&program, "Support"); - FilterBlurProgram { - program, - framebuffer_size_uniform, - src_uniform, +impl TileFilterBlurProgram where D: Device { + pub fn new(device: &D, resources: &dyn ResourceLoader) -> TileFilterBlurProgram { + let tile_filter_program = TileFilterProgram::new(device, + resources, + "tile_filter_blur", + "tile_filter_blur"); + let src_offset_scale_uniform = device.get_uniform(&tile_filter_program.program, + "SrcOffsetScale"); + let initial_gauss_coeff_uniform = device.get_uniform(&tile_filter_program.program, + "InitialGaussCoeff"); + let support_uniform = device.get_uniform(&tile_filter_program.program, "Support"); + TileFilterBlurProgram { + tile_filter_program, src_offset_scale_uniform, initial_gauss_coeff_uniform, support_uniform, @@ -603,42 +668,8 @@ impl FilterBlurProgram where D: Device { } } -pub struct FilterBlurVertexArray where D: Device { - pub vertex_array: D::VertexArray, -} - -impl FilterBlurVertexArray where D: Device { - pub fn new( - device: &D, - fill_blur_program: &FilterBlurProgram, - quad_vertex_positions_buffer: &D::Buffer, - quad_vertex_indices_buffer: &D::Buffer, - ) -> FilterBlurVertexArray { - let vertex_array = device.create_vertex_array(); - let position_attr = device.get_vertex_attr(&fill_blur_program.program, "Position") - .unwrap(); - - device.bind_buffer(&vertex_array, quad_vertex_positions_buffer, BufferTarget::Vertex); - device.configure_vertex_attr(&vertex_array, &position_attr, &VertexAttrDescriptor { - size: 2, - class: VertexAttrClass::Int, - attr_type: VertexAttrType::I16, - stride: 4, - offset: 0, - divisor: 0, - buffer_index: 0, - }); - device.bind_buffer(&vertex_array, quad_vertex_indices_buffer, BufferTarget::Index); - - FilterBlurVertexArray { vertex_array } - } -} - -pub struct FilterTextProgram where D: Device { - pub program: D::Program, - pub source_uniform: D::Uniform, - pub source_size_uniform: D::Uniform, - pub framebuffer_size_uniform: D::Uniform, +pub struct TileFilterTextProgram where D: Device { + pub tile_filter_program: TileFilterProgram, pub kernel_uniform: D::Uniform, pub gamma_lut_uniform: D::Uniform, pub gamma_correction_enabled_uniform: D::Uniform, @@ -646,26 +677,20 @@ pub struct FilterTextProgram where D: Device { pub bg_color_uniform: D::Uniform, } -impl FilterTextProgram where D: Device { - pub fn new(device: &D, resources: &dyn ResourceLoader) -> FilterTextProgram { - let program = device.create_program_from_shader_names(resources, - "filter_text", - "filter", - "filter_text"); - let source_uniform = device.get_uniform(&program, "Source"); - let source_size_uniform = device.get_uniform(&program, "SourceSize"); - let framebuffer_size_uniform = device.get_uniform(&program, "FramebufferSize"); - let kernel_uniform = device.get_uniform(&program, "Kernel"); - let gamma_lut_uniform = device.get_uniform(&program, "GammaLUT"); - let gamma_correction_enabled_uniform = device.get_uniform(&program, +impl TileFilterTextProgram where D: Device { + pub fn new(device: &D, resources: &dyn ResourceLoader) -> TileFilterTextProgram { + let tile_filter_program = TileFilterProgram::new(device, + resources, + "tile_filter_text", + "tile_filter_text"); + let kernel_uniform = device.get_uniform(&tile_filter_program.program, "Kernel"); + let gamma_lut_uniform = device.get_uniform(&tile_filter_program.program, "GammaLUT"); + let gamma_correction_enabled_uniform = device.get_uniform(&tile_filter_program.program, "GammaCorrectionEnabled"); - let fg_color_uniform = device.get_uniform(&program, "FGColor"); - let bg_color_uniform = device.get_uniform(&program, "BGColor"); - FilterTextProgram { - program, - source_uniform, - source_size_uniform, - framebuffer_size_uniform, + let fg_color_uniform = device.get_uniform(&tile_filter_program.program, "FGColor"); + let bg_color_uniform = device.get_uniform(&tile_filter_program.program, "BGColor"); + TileFilterTextProgram { + tile_filter_program, kernel_uniform, gamma_lut_uniform, gamma_correction_enabled_uniform, @@ -675,37 +700,6 @@ impl FilterTextProgram where D: Device { } } -pub struct FilterTextVertexArray where D: Device { - pub vertex_array: D::VertexArray, -} - -impl FilterTextVertexArray where D: Device { - pub fn new( - device: &D, - fill_text_program: &FilterTextProgram, - quad_vertex_positions_buffer: &D::Buffer, - quad_vertex_indices_buffer: &D::Buffer, - ) -> FilterTextVertexArray { - let vertex_array = device.create_vertex_array(); - let position_attr = device.get_vertex_attr(&fill_text_program.program, "Position") - .unwrap(); - - device.bind_buffer(&vertex_array, quad_vertex_positions_buffer, BufferTarget::Vertex); - device.configure_vertex_attr(&vertex_array, &position_attr, &VertexAttrDescriptor { - size: 2, - class: VertexAttrClass::Int, - attr_type: VertexAttrType::I16, - stride: 4, - offset: 0, - divisor: 0, - buffer_index: 0, - }); - device.bind_buffer(&vertex_array, quad_vertex_indices_buffer, BufferTarget::Index); - - FilterTextVertexArray { vertex_array } - } -} - pub struct StencilProgram where D: Device, diff --git a/renderer/src/gpu_data.rs b/renderer/src/gpu_data.rs index 61770453..7b08bcad 100644 --- a/renderer/src/gpu_data.rs +++ b/renderer/src/gpu_data.rs @@ -62,12 +62,12 @@ pub enum RenderCommand { // Draws a batch of solid tiles to the render target on top of the stack. DrawSolidTiles(SolidTileBatch), - // Draws an entire render target to the render target on top of the stack. + // Draws a batch of render target tiles to the render target on top of the stack. // - // FIXME(pcwalton): This draws the entire render target, so it's inefficient. We should get rid - // of this command and transition all uses to `DrawAlphaTiles`/`DrawSolidTiles`. The reason it - // exists is that we don't have logic to create tiles for blur bounding regions yet. - DrawRenderTarget { render_target: RenderTargetId, effects: Effects }, + // FIXME(pcwalton): We should get rid of this command and transition all uses to + // `DrawAlphaTiles`/`DrawSolidTiles`. The reason it exists is that we don't have logic to + // create tiles for blur bounding regions yet. + DrawRenderTargetTiles(RenderTargetTileBatch), // Presents a rendered frame. Finish { build_time: Duration }, @@ -108,6 +108,13 @@ pub struct SolidTileBatch { pub sampling_flags: TextureSamplingFlags, } +#[derive(Clone, Debug)] +pub struct RenderTargetTileBatch { + pub tiles: Vec, + pub render_target: RenderTargetId, + pub effects: Effects, +} + #[derive(Clone, Copy, Debug)] pub struct FillObjectPrimitive { pub px: LineSegmentU4, @@ -162,6 +169,15 @@ pub struct AlphaTile { pub lower_right: AlphaTileVertex, } +#[derive(Clone, Copy, Debug, Default)] +#[repr(C)] +pub struct RenderTargetTile { + pub upper_left: RenderTargetTileVertex, + pub upper_right: RenderTargetTileVertex, + pub lower_left: RenderTargetTileVertex, + pub lower_right: RenderTargetTileVertex, +} + #[derive(Clone, Copy, Debug, Default)] #[repr(C)] pub struct MaskTileVertex { @@ -187,6 +203,13 @@ pub struct AlphaTileVertex { pub pad: u8, } +#[derive(Clone, Copy, Debug, Default)] +#[repr(C)] +pub struct RenderTargetTileVertex { + pub tile_x: i16, + pub tile_y: i16, +} + impl Debug for RenderCommand { fn fmt(&self, formatter: &mut Formatter) -> DebugResult { match *self { @@ -203,9 +226,6 @@ impl Debug for RenderCommand { write!(formatter, "PushRenderTarget({:?})", render_target_id) } RenderCommand::PopRenderTarget => write!(formatter, "PopRenderTarget"), - RenderCommand::DrawRenderTarget { render_target, .. } => { - write!(formatter, "DrawRenderTarget({:?})", render_target) - } RenderCommand::DrawAlphaTiles(ref batch) => { write!(formatter, "DrawAlphaTiles(x{}, {:?}, {:?}, {:?})", @@ -221,6 +241,12 @@ impl Debug for RenderCommand { batch.paint_page, batch.sampling_flags) } + RenderCommand::DrawRenderTargetTiles(ref batch) => { + write!(formatter, + "DrawRenderTarget(x{}, {:?})", + batch.tiles.len(), + batch.render_target) + } RenderCommand::Finish { .. } => write!(formatter, "Finish"), } } diff --git a/renderer/src/z_buffer.rs b/renderer/src/z_buffer.rs index 3eeef34c..c893158a 100644 --- a/renderer/src/z_buffer.rs +++ b/renderer/src/z_buffer.rs @@ -12,15 +12,16 @@ use crate::builder::SolidTile; use crate::gpu_data::{SolidTileBatch, SolidTileVertex}; -use crate::paint::PaintMetadata; -use crate::scene::DrawPath; +use crate::paint::{PaintId, PaintMetadata}; use crate::tile_map::DenseTileMap; use crate::tiles; use pathfinder_geometry::rect::RectF; use pathfinder_geometry::vector::Vector2I; +use vec_map::VecMap; pub(crate) struct ZBuffer { buffer: DenseTileMap, + depth_to_paint_id: VecMap, } pub(crate) struct SolidTiles { @@ -32,24 +33,25 @@ impl 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(), } } - pub(crate) fn test(&self, coords: Vector2I, object_index: u32) -> bool { + 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] < object_index + 1 + self.buffer.data[tile_index as usize] < depth } - pub(crate) fn update(&mut self, solid_tiles: &[SolidTile], object_index: u32) { + 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); 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, object_index + 1); + *z_dest = u32::max(*z_dest, depth); } } - pub(crate) fn build_solid_tiles(&self, paths: &[DrawPath], paint_metadata: &[PaintMetadata]) - -> SolidTiles { + 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() { @@ -59,13 +61,11 @@ impl ZBuffer { } let tile_coords = self.buffer.index_to_coords(tile_index); - let object_index = (depth - 1) as u32; - let paint_id = paths[object_index as usize].paint(); + let paint_id = self.depth_to_paint_id[depth as usize]; let paint_metadata = &paint_metadata[paint_id.0 as usize]; let tile_position = tile_coords + self.buffer.rect.origin(); - let object_index = object_index as u16; // Create a batch if necessary. match solid_tiles.batches.last() { @@ -83,16 +83,10 @@ impl ZBuffer { let batch = solid_tiles.batches.last_mut().unwrap(); batch.vertices.extend_from_slice(&[ - SolidTileVertex::new(tile_position, object_index, paint_metadata), - SolidTileVertex::new(tile_position + Vector2I::new(1, 0), - object_index, - paint_metadata), - SolidTileVertex::new(tile_position + Vector2I::new(0, 1), - object_index, - paint_metadata), - SolidTileVertex::new(tile_position + Vector2I::new(1, 1), - object_index, - paint_metadata), + 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), ]); } @@ -101,13 +95,12 @@ impl ZBuffer { } impl SolidTileVertex { - fn new(tile_position: Vector2I, object_index: u16, paint_metadata: &PaintMetadata) - -> SolidTileVertex { + fn new(tile_position: Vector2I, paint_metadata: &PaintMetadata) -> SolidTileVertex { let color_uv = paint_metadata.calculate_tex_coords(tile_position); SolidTileVertex { tile_x: tile_position.x() as i16, tile_y: tile_position.y() as i16, - object_index: object_index, + object_index: 0, color_u: color_uv.x(), color_v: color_uv.y(), pad: 0, diff --git a/resources/shaders/gl3/blit.fs.glsl b/resources/shaders/gl3/blit.fs.glsl new file mode 100644 index 00000000..0efcd294 --- /dev/null +++ b/resources/shaders/gl3/blit.fs.glsl @@ -0,0 +1,27 @@ +#version {{version}} +// Automatically generated from files in pathfinder/shaders/. Do not edit! + + + + + + + + + + + + +precision highp float; + +uniform sampler2D uSrc; + +in vec2 vTexCoord; + +out vec4 oFragColor; + +void main(){ + vec4 color = texture(uSrc, vTexCoord); + oFragColor = vec4(color . rgb * color . a, color . a); +} + diff --git a/resources/shaders/gl3/blit.vs.glsl b/resources/shaders/gl3/blit.vs.glsl new file mode 100644 index 00000000..6203f17a --- /dev/null +++ b/resources/shaders/gl3/blit.vs.glsl @@ -0,0 +1,25 @@ +#version {{version}} +// Automatically generated from files in pathfinder/shaders/. Do not edit! + + + + + + + + + + + + +precision highp float; + +in vec2 aPosition; + +out vec2 vTexCoord; + +void main(){ + vTexCoord = aPosition; + gl_Position = vec4(mix(aPosition, vec2(- 1.0), vec2(1.0)), 0.0, 1.0); +} + diff --git a/resources/shaders/gl3/tile_filter.vs.glsl b/resources/shaders/gl3/tile_filter.vs.glsl new file mode 100644 index 00000000..d3bf9f7c --- /dev/null +++ b/resources/shaders/gl3/tile_filter.vs.glsl @@ -0,0 +1,31 @@ +#version {{version}} +// Automatically generated from files in pathfinder/shaders/. Do not edit! + + + + + + + + + + + + +precision highp float; + +uniform mat4 uTransform; +uniform vec2 uTileSize; +uniform vec2 uSrcSize; + +in ivec2 aTilePosition; + +out vec2 vTexCoord; + +void main(){ + vec2 position = vec2(aTilePosition)* uTileSize; + + vTexCoord = position / uSrcSize; + gl_Position = uTransform * vec4(position, 0.0, 1.0); +} + diff --git a/resources/shaders/gl3/tile_filter_blur.fs.glsl b/resources/shaders/gl3/tile_filter_blur.fs.glsl new file mode 100644 index 00000000..dca9e4d1 --- /dev/null +++ b/resources/shaders/gl3/tile_filter_blur.fs.glsl @@ -0,0 +1,69 @@ +#version {{version}} +// Automatically generated from files in pathfinder/shaders/. Do not edit! + + + + + + + + + + + + + + + + + + + + +#extension GL_GOOGLE_include_directive : enable + +precision highp float; + +uniform sampler2D uSrc; +uniform vec2 uSrcOffsetScale; +uniform vec3 uInitialGaussCoeff; +uniform int uSupport; + +in vec2 vTexCoord; + +out vec4 oFragColor; + +void main(){ + + vec3 gaussCoeff = uInitialGaussCoeff; + float gaussSum = gaussCoeff . x; + vec4 color = texture(uSrc, vTexCoord)* gaussCoeff . x; + gaussCoeff . xy *= gaussCoeff . yz; + + + + + + + + + + for(int i = 1;i <= uSupport;i += 2){ + float gaussPartialSum = gaussCoeff . x; + gaussCoeff . xy *= gaussCoeff . yz; + gaussPartialSum += gaussCoeff . x; + + vec2 srcOffset = uSrcOffsetScale *(float(i)+ gaussCoeff . x / gaussPartialSum); + color +=(texture(uSrc, vTexCoord - srcOffset)+ texture(uSrc, vTexCoord + srcOffset))* + gaussPartialSum; + + gaussSum += 2.0 * gaussPartialSum; + gaussCoeff . xy *= gaussCoeff . yz; + } + + + color /= gaussSum; + color . rgb *= color . a; + oFragColor = color; +} + diff --git a/resources/shaders/gl3/tile_filter_text.fs.glsl b/resources/shaders/gl3/tile_filter_text.fs.glsl new file mode 100644 index 00000000..88a60f25 --- /dev/null +++ b/resources/shaders/gl3/tile_filter_text.fs.glsl @@ -0,0 +1,124 @@ +#version {{version}} +// Automatically generated from files in pathfinder/shaders/. Do not edit! + + + + + + + + + + + + +#extension GL_GOOGLE_include_directive : enable + +precision highp float; + +uniform sampler2D uSrc; +uniform vec2 uSrcSize; +uniform vec4 uFGColor; +uniform vec4 uBGColor; +uniform int uGammaCorrectionEnabled; + +in vec2 vTexCoord; + +out vec4 oFragColor; + + + + + + + + + + + + + + +uniform sampler2D uGammaLUT; + +float gammaCorrectChannel(float bgColor, float fgColor){ + return texture(uGammaLUT, vec2(fgColor, 1.0 - bgColor)). r; +} + + +vec3 gammaCorrect(vec3 bgColor, vec3 fgColor){ + return vec3(gammaCorrectChannel(bgColor . r, fgColor . r), + gammaCorrectChannel(bgColor . g, fgColor . g), + gammaCorrectChannel(bgColor . b, fgColor . b)); +} + + + + + + + + + + + + + +uniform vec4 uKernel; + + + +float sample1Tap(float offset); + + +void sample9Tap(out vec4 outAlphaLeft, + out float outAlphaCenter, + out vec4 outAlphaRight, + float onePixel){ + outAlphaLeft = vec4(uKernel . x > 0.0 ? sample1Tap(- 4.0 * onePixel): 0.0, + sample1Tap(- 3.0 * onePixel), + sample1Tap(- 2.0 * onePixel), + sample1Tap(- 1.0 * onePixel)); + outAlphaCenter = sample1Tap(0.0); + outAlphaRight = vec4(sample1Tap(1.0 * onePixel), + sample1Tap(2.0 * onePixel), + sample1Tap(3.0 * onePixel), + uKernel . x > 0.0 ? sample1Tap(4.0 * onePixel): 0.0); +} + + +float convolve7Tap(vec4 alpha0, vec3 alpha1){ + return dot(alpha0, uKernel)+ dot(alpha1, uKernel . zyx); +} + + + +float sample1Tap(float offset){ + return texture(uSrc, vec2(vTexCoord . x + offset, vTexCoord . y)). r; +} + +void main(){ + + vec3 alpha; + if(uKernel . w == 0.0){ + alpha = texture(uSrc, vTexCoord). rrr; + } else { + vec4 alphaLeft, alphaRight; + float alphaCenter; + sample9Tap(alphaLeft, alphaCenter, alphaRight, 1.0 / uSrcSize . x); + + float r = convolve7Tap(alphaLeft, vec3(alphaCenter, alphaRight . xy)); + float g = convolve7Tap(vec4(alphaLeft . yzw, alphaCenter), alphaRight . xyz); + float b = convolve7Tap(vec4(alphaLeft . zw, alphaCenter, alphaRight . x), alphaRight . yzw); + + alpha = vec3(r, g, b); + } + + + if(uGammaCorrectionEnabled != 0) + alpha = gammaCorrect(uBGColor . rgb, alpha); + + + oFragColor = vec4(mix(uBGColor . rgb, uFGColor . rgb, alpha), 1.0); +} + diff --git a/resources/shaders/metal/blit.fs.metal b/resources/shaders/metal/blit.fs.metal new file mode 100644 index 00000000..5f3d2748 --- /dev/null +++ b/resources/shaders/metal/blit.fs.metal @@ -0,0 +1,30 @@ +// Automatically generated from files in pathfinder/shaders/. Do not edit! +#include +#include + +using namespace metal; + +struct spvDescriptorSetBuffer0 +{ + texture2d uSrc [[id(0)]]; + sampler uSrcSmplr [[id(1)]]; +}; + +struct main0_out +{ + float4 oFragColor [[color(0)]]; +}; + +struct main0_in +{ + float2 vTexCoord [[user(locn0)]]; +}; + +fragment main0_out main0(main0_in in [[stage_in]], constant spvDescriptorSetBuffer0& spvDescriptorSet0 [[buffer(0)]]) +{ + main0_out out = {}; + float4 color = spvDescriptorSet0.uSrc.sample(spvDescriptorSet0.uSrcSmplr, in.vTexCoord); + out.oFragColor = float4(color.xyz * color.w, color.w); + return out; +} + diff --git a/resources/shaders/metal/blit.vs.metal b/resources/shaders/metal/blit.vs.metal new file mode 100644 index 00000000..38e49044 --- /dev/null +++ b/resources/shaders/metal/blit.vs.metal @@ -0,0 +1,25 @@ +// Automatically generated from files in pathfinder/shaders/. Do not edit! +#include +#include + +using namespace metal; + +struct main0_out +{ + float2 vTexCoord [[user(locn0)]]; + float4 gl_Position [[position]]; +}; + +struct main0_in +{ + float2 aPosition [[attribute(0)]]; +}; + +vertex main0_out main0(main0_in in [[stage_in]]) +{ + main0_out out = {}; + out.vTexCoord = in.aPosition; + out.gl_Position = float4(mix(in.aPosition, float2(-1.0), float2(1.0)), 0.0, 1.0); + return out; +} + diff --git a/resources/shaders/metal/tile_filter.vs.metal b/resources/shaders/metal/tile_filter.vs.metal new file mode 100644 index 00000000..ba6d6f3b --- /dev/null +++ b/resources/shaders/metal/tile_filter.vs.metal @@ -0,0 +1,33 @@ +// Automatically generated from files in pathfinder/shaders/. Do not edit! +#include +#include + +using namespace metal; + +struct spvDescriptorSetBuffer0 +{ + constant float2* uTileSize [[id(0)]]; + constant float2* uSrcSize [[id(1)]]; + constant float4x4* uTransform [[id(2)]]; +}; + +struct main0_out +{ + float2 vTexCoord [[user(locn0)]]; + float4 gl_Position [[position]]; +}; + +struct main0_in +{ + int2 aTilePosition [[attribute(0)]]; +}; + +vertex main0_out main0(main0_in in [[stage_in]], constant spvDescriptorSetBuffer0& spvDescriptorSet0 [[buffer(0)]]) +{ + main0_out out = {}; + float2 position = float2(in.aTilePosition) * (*spvDescriptorSet0.uTileSize); + out.vTexCoord = position / (*spvDescriptorSet0.uSrcSize); + out.gl_Position = (*spvDescriptorSet0.uTransform) * float4(position, 0.0, 1.0); + return out; +} + diff --git a/resources/shaders/metal/tile_filter_blur.fs.metal b/resources/shaders/metal/tile_filter_blur.fs.metal new file mode 100644 index 00000000..b70ef414 --- /dev/null +++ b/resources/shaders/metal/tile_filter_blur.fs.metal @@ -0,0 +1,52 @@ +// Automatically generated from files in pathfinder/shaders/. Do not edit! +#include +#include + +using namespace metal; + +struct spvDescriptorSetBuffer0 +{ + constant float3* uInitialGaussCoeff [[id(0)]]; + texture2d uSrc [[id(1)]]; + sampler uSrcSmplr [[id(2)]]; + constant int* uSupport [[id(3)]]; + constant float2* uSrcOffsetScale [[id(4)]]; +}; + +struct main0_out +{ + float4 oFragColor [[color(0)]]; +}; + +struct main0_in +{ + float2 vTexCoord [[user(locn0)]]; +}; + +fragment main0_out main0(main0_in in [[stage_in]], constant spvDescriptorSetBuffer0& spvDescriptorSet0 [[buffer(0)]]) +{ + main0_out out = {}; + float3 gaussCoeff = (*spvDescriptorSet0.uInitialGaussCoeff); + float gaussSum = gaussCoeff.x; + float4 color = spvDescriptorSet0.uSrc.sample(spvDescriptorSet0.uSrcSmplr, in.vTexCoord) * gaussCoeff.x; + float2 _39 = gaussCoeff.xy * gaussCoeff.yz; + gaussCoeff = float3(_39.x, _39.y, gaussCoeff.z); + for (int i = 1; i <= (*spvDescriptorSet0.uSupport); i += 2) + { + float gaussPartialSum = gaussCoeff.x; + float2 _64 = gaussCoeff.xy * gaussCoeff.yz; + gaussCoeff = float3(_64.x, _64.y, gaussCoeff.z); + gaussPartialSum += gaussCoeff.x; + float2 srcOffset = (*spvDescriptorSet0.uSrcOffsetScale) * (float(i) + (gaussCoeff.x / gaussPartialSum)); + color += ((spvDescriptorSet0.uSrc.sample(spvDescriptorSet0.uSrcSmplr, (in.vTexCoord - srcOffset)) + spvDescriptorSet0.uSrc.sample(spvDescriptorSet0.uSrcSmplr, (in.vTexCoord + srcOffset))) * gaussPartialSum); + gaussSum += (2.0 * gaussPartialSum); + float2 _108 = gaussCoeff.xy * gaussCoeff.yz; + gaussCoeff = float3(_108.x, _108.y, gaussCoeff.z); + } + color /= float4(gaussSum); + float3 _123 = color.xyz * color.w; + color = float4(_123.x, _123.y, _123.z, color.w); + out.oFragColor = color; + return out; +} + diff --git a/resources/shaders/metal/tile_filter_text.fs.metal b/resources/shaders/metal/tile_filter_text.fs.metal new file mode 100644 index 00000000..4f56dce1 --- /dev/null +++ b/resources/shaders/metal/tile_filter_text.fs.metal @@ -0,0 +1,130 @@ +// Automatically generated from files in pathfinder/shaders/. Do not edit! +#pragma clang diagnostic ignored "-Wmissing-prototypes" + +#include +#include + +using namespace metal; + +struct spvDescriptorSetBuffer0 +{ + texture2d uGammaLUT [[id(0)]]; + sampler uGammaLUTSmplr [[id(1)]]; + constant float4* uKernel [[id(2)]]; + texture2d uSrc [[id(3)]]; + sampler uSrcSmplr [[id(4)]]; + constant float2* uSrcSize [[id(5)]]; + constant int* uGammaCorrectionEnabled [[id(6)]]; + constant float4* uBGColor [[id(7)]]; + constant float4* uFGColor [[id(8)]]; +}; + +struct main0_out +{ + float4 oFragColor [[color(0)]]; +}; + +struct main0_in +{ + float2 vTexCoord [[user(locn0)]]; +}; + +float sample1Tap(thread const float& offset, thread texture2d uSrc, thread const sampler uSrcSmplr, thread float2& vTexCoord) +{ + return uSrc.sample(uSrcSmplr, float2(vTexCoord.x + offset, vTexCoord.y)).x; +} + +void sample9Tap(thread float4& outAlphaLeft, thread float& outAlphaCenter, thread float4& outAlphaRight, thread const float& onePixel, thread float4 uKernel, thread texture2d uSrc, thread const sampler uSrcSmplr, thread float2& vTexCoord) +{ + float _89; + if (uKernel.x > 0.0) + { + float param = (-4.0) * onePixel; + _89 = sample1Tap(param, uSrc, uSrcSmplr, vTexCoord); + } + else + { + _89 = 0.0; + } + float param_1 = (-3.0) * onePixel; + float param_2 = (-2.0) * onePixel; + float param_3 = (-1.0) * onePixel; + outAlphaLeft = float4(_89, sample1Tap(param_1, uSrc, uSrcSmplr, vTexCoord), sample1Tap(param_2, uSrc, uSrcSmplr, vTexCoord), sample1Tap(param_3, uSrc, uSrcSmplr, vTexCoord)); + float param_4 = 0.0; + outAlphaCenter = sample1Tap(param_4, uSrc, uSrcSmplr, vTexCoord); + float param_5 = 1.0 * onePixel; + float param_6 = 2.0 * onePixel; + float param_7 = 3.0 * onePixel; + float _134; + if (uKernel.x > 0.0) + { + float param_8 = 4.0 * onePixel; + _134 = sample1Tap(param_8, uSrc, uSrcSmplr, vTexCoord); + } + else + { + _134 = 0.0; + } + outAlphaRight = float4(sample1Tap(param_5, uSrc, uSrcSmplr, vTexCoord), sample1Tap(param_6, uSrc, uSrcSmplr, vTexCoord), sample1Tap(param_7, uSrc, uSrcSmplr, vTexCoord), _134); +} + +float convolve7Tap(thread const float4& alpha0, thread const float3& alpha1, thread float4 uKernel) +{ + return dot(alpha0, uKernel) + dot(alpha1, uKernel.zyx); +} + +float gammaCorrectChannel(thread const float& bgColor, thread const float& fgColor, thread texture2d uGammaLUT, thread const sampler uGammaLUTSmplr) +{ + return uGammaLUT.sample(uGammaLUTSmplr, float2(fgColor, 1.0 - bgColor)).x; +} + +float3 gammaCorrect(thread const float3& bgColor, thread const float3& fgColor, thread texture2d uGammaLUT, thread const sampler uGammaLUTSmplr) +{ + float param = bgColor.x; + float param_1 = fgColor.x; + float param_2 = bgColor.y; + float param_3 = fgColor.y; + float param_4 = bgColor.z; + float param_5 = fgColor.z; + return float3(gammaCorrectChannel(param, param_1, uGammaLUT, uGammaLUTSmplr), gammaCorrectChannel(param_2, param_3, uGammaLUT, uGammaLUTSmplr), gammaCorrectChannel(param_4, param_5, uGammaLUT, uGammaLUTSmplr)); +} + +fragment main0_out main0(main0_in in [[stage_in]], constant spvDescriptorSetBuffer0& spvDescriptorSet0 [[buffer(0)]]) +{ + main0_out out = {}; + float3 alpha; + if ((*spvDescriptorSet0.uKernel).w == 0.0) + { + alpha = spvDescriptorSet0.uSrc.sample(spvDescriptorSet0.uSrcSmplr, in.vTexCoord).xxx; + } + else + { + float param_3 = 1.0 / (*spvDescriptorSet0.uSrcSize).x; + float4 param; + float param_1; + float4 param_2; + sample9Tap(param, param_1, param_2, param_3, (*spvDescriptorSet0.uKernel), spvDescriptorSet0.uSrc, spvDescriptorSet0.uSrcSmplr, in.vTexCoord); + float4 alphaLeft = param; + float alphaCenter = param_1; + float4 alphaRight = param_2; + float4 param_4 = alphaLeft; + float3 param_5 = float3(alphaCenter, alphaRight.xy); + float r = convolve7Tap(param_4, param_5, (*spvDescriptorSet0.uKernel)); + float4 param_6 = float4(alphaLeft.yzw, alphaCenter); + float3 param_7 = alphaRight.xyz; + float g = convolve7Tap(param_6, param_7, (*spvDescriptorSet0.uKernel)); + float4 param_8 = float4(alphaLeft.zw, alphaCenter, alphaRight.x); + float3 param_9 = alphaRight.yzw; + float b = convolve7Tap(param_8, param_9, (*spvDescriptorSet0.uKernel)); + alpha = float3(r, g, b); + } + if ((*spvDescriptorSet0.uGammaCorrectionEnabled) != 0) + { + float3 param_10 = (*spvDescriptorSet0.uBGColor).xyz; + float3 param_11 = alpha; + alpha = gammaCorrect(param_10, param_11, spvDescriptorSet0.uGammaLUT, spvDescriptorSet0.uGammaLUTSmplr); + } + out.oFragColor = float4(mix((*spvDescriptorSet0.uBGColor).xyz, (*spvDescriptorSet0.uFGColor).xyz, alpha), 1.0); + return out; +} + diff --git a/shaders/Makefile b/shaders/Makefile index 7e672f04..f0b08a38 100644 --- a/shaders/Makefile +++ b/shaders/Makefile @@ -3,6 +3,8 @@ TARGET_DIR?=../resources/shaders EMPTY= SHADERS=\ + blit.fs.glsl \ + blit.vs.glsl \ debug_solid.fs.glsl \ debug_solid.vs.glsl \ debug_texture.fs.glsl \ @@ -11,10 +13,6 @@ SHADERS=\ demo_ground.vs.glsl \ fill.fs.glsl \ fill.vs.glsl \ - filter.vs.glsl \ - filter_basic.fs.glsl \ - filter_blur.fs.glsl \ - filter_text.fs.glsl \ mask.vs.glsl \ mask_evenodd.fs.glsl \ mask_winding.fs.glsl \ @@ -32,14 +30,17 @@ SHADERS=\ tile_alpha_softlight.fs.glsl \ tile_copy.fs.glsl \ tile_copy.vs.glsl \ + tile_filter.vs.glsl \ + tile_filter_blur.fs.glsl \ + tile_filter_text.fs.glsl \ tile_solid.fs.glsl \ tile_solid.vs.glsl \ $(EMPTY) INCLUDES=\ - filter_text_convolve.inc.glsl \ - filter_text_gamma_correct.inc.glsl \ tile_alpha_sample.inc.glsl \ + tile_filter_text_convolve.inc.glsl \ + tile_filter_text_gamma_correct.inc.glsl \ $(EMPTY) OUT=\ diff --git a/shaders/filter_basic.fs.glsl b/shaders/blit.fs.glsl similarity index 65% rename from shaders/filter_basic.fs.glsl rename to shaders/blit.fs.glsl index 28faf163..41cf366c 100644 --- a/shaders/filter_basic.fs.glsl +++ b/shaders/blit.fs.glsl @@ -1,6 +1,6 @@ #version 330 -// pathfinder/shaders/filter_basic.fs.glsl +// pathfinder/shaders/blit.fs.glsl // // Copyright © 2020 The Pathfinder Project Developers. // @@ -10,20 +10,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// TODO(pcwalton): This could be significantly optimized by operating on a -// sparse per-tile basis. - -#extension GL_GOOGLE_include_directive : enable - precision highp float; -uniform sampler2D uSource; +uniform sampler2D uSrc; in vec2 vTexCoord; out vec4 oFragColor; void main() { - vec4 color = texture(uSource, vTexCoord); + vec4 color = texture(uSrc, vTexCoord); oFragColor = vec4(color.rgb * color.a, color.a); } diff --git a/shaders/blit.vs.glsl b/shaders/blit.vs.glsl new file mode 100644 index 00000000..81f4e4e1 --- /dev/null +++ b/shaders/blit.vs.glsl @@ -0,0 +1,22 @@ +#version 330 + +// pathfinder/shaders/blit.vs.glsl +// +// Copyright © 2020 The Pathfinder Project Developers. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +precision highp float; + +in vec2 aPosition; + +out vec2 vTexCoord; + +void main() { + vTexCoord = aPosition; + gl_Position = vec4(mix(aPosition, vec2(-1.0), vec2(1.0)), 0.0, 1.0); +} diff --git a/shaders/filter.vs.glsl b/shaders/tile_filter.vs.glsl similarity index 60% rename from shaders/filter.vs.glsl rename to shaders/tile_filter.vs.glsl index 0d6d47cb..aaeee99a 100644 --- a/shaders/filter.vs.glsl +++ b/shaders/tile_filter.vs.glsl @@ -1,6 +1,6 @@ #version 330 -// pathfinder/shaders/filter.vs.glsl +// pathfinder/shaders/tile_filter.vs.glsl // // Copyright © 2020 The Pathfinder Project Developers. // @@ -12,17 +12,17 @@ precision highp float; -in ivec2 aPosition; +uniform mat4 uTransform; +uniform vec2 uTileSize; +uniform vec2 uSrcSize; + +in ivec2 aTilePosition; out vec2 vTexCoord; void main() { - vec2 position = vec2(aPosition); - vTexCoord = position; + vec2 position = vec2(aTilePosition) * uTileSize; -#ifdef PF_ORIGIN_UPPER_LEFT - // FIXME(pcwalton): This is wrong. - position.y = 1.0 - position.y; -#endif - gl_Position = vec4(vec2(position) * 2.0 - 1.0, 0.0, 1.0); + vTexCoord = position / uSrcSize; + gl_Position = uTransform * vec4(position, 0.0, 1.0); } diff --git a/shaders/filter_blur.fs.glsl b/shaders/tile_filter_blur.fs.glsl similarity index 100% rename from shaders/filter_blur.fs.glsl rename to shaders/tile_filter_blur.fs.glsl diff --git a/shaders/filter_text.fs.glsl b/shaders/tile_filter_text.fs.glsl similarity index 73% rename from shaders/filter_text.fs.glsl rename to shaders/tile_filter_text.fs.glsl index d714ad2d..abf5991c 100644 --- a/shaders/filter_text.fs.glsl +++ b/shaders/tile_filter_text.fs.glsl @@ -1,6 +1,6 @@ #version 330 -// pathfinder/shaders/filter_text.fs.glsl +// pathfinder/shaders/tile_filter_text.fs.glsl // // Copyright © 2019 The Pathfinder Project Developers. // @@ -10,15 +10,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// TODO(pcwalton): This could be significantly optimized by operating on a -// sparse per-tile basis. - #extension GL_GOOGLE_include_directive : enable precision highp float; -uniform sampler2D uSource; -uniform vec2 uSourceSize; +uniform sampler2D uSrc; +uniform vec2 uSrcSize; uniform vec4 uFGColor; uniform vec4 uBGColor; uniform int uGammaCorrectionEnabled; @@ -27,23 +24,23 @@ in vec2 vTexCoord; out vec4 oFragColor; -#include "filter_text_gamma_correct.inc.glsl" -#include "filter_text_convolve.inc.glsl" +#include "tile_filter_text_gamma_correct.inc.glsl" +#include "tile_filter_text_convolve.inc.glsl" // Convolve horizontally in this pass. float sample1Tap(float offset) { - return texture(uSource, vec2(vTexCoord.x + offset, vTexCoord.y)).r; + return texture(uSrc, vec2(vTexCoord.x + offset, vTexCoord.y)).r; } void main() { // Apply defringing if necessary. vec3 alpha; if (uKernel.w == 0.0) { - alpha = texture(uSource, vTexCoord).rrr; + alpha = texture(uSrc, vTexCoord).rrr; } else { vec4 alphaLeft, alphaRight; float alphaCenter; - sample9Tap(alphaLeft, alphaCenter, alphaRight, 1.0 / uSourceSize.x); + sample9Tap(alphaLeft, alphaCenter, alphaRight, 1.0 / uSrcSize.x); float r = convolve7Tap(alphaLeft, vec3(alphaCenter, alphaRight.xy)); float g = convolve7Tap(vec4(alphaLeft.yzw, alphaCenter), alphaRight.xyz); diff --git a/shaders/filter_text_convolve.inc.glsl b/shaders/tile_filter_text_convolve.inc.glsl similarity index 92% rename from shaders/filter_text_convolve.inc.glsl rename to shaders/tile_filter_text_convolve.inc.glsl index cbeded95..bbfe1d45 100644 --- a/shaders/filter_text_convolve.inc.glsl +++ b/shaders/tile_filter_text_convolve.inc.glsl @@ -1,6 +1,6 @@ -// pathfinder/shaders/filter_text_convolve.inc.glsl +// pathfinder/shaders/tile_filter_text_convolve.inc.glsl // -// Copyright © 2019 The Pathfinder Project Developers. +// Copyright © 2020 The Pathfinder Project Developers. // // Licensed under the Apache License, Version 2.0 or the MIT license diff --git a/shaders/filter_text_gamma_correct.inc.glsl b/shaders/tile_filter_text_gamma_correct.inc.glsl similarity index 100% rename from shaders/filter_text_gamma_correct.inc.glsl rename to shaders/tile_filter_text_gamma_correct.inc.glsl