Composite render targets using tiles, taking the Z-buffer into account.
We can do more tile-based optimization, but this should be enough to ensure a correct rendering. This temporarily breaks subpixel AA, but it should be fixable by modifying `blur.fs.glsl`. Closes #271.
This commit is contained in:
parent
0f35d9c817
commit
f607b607b0
|
@ -242,6 +242,7 @@ dependencies = [
|
||||||
"pathfinder_gpu 0.1.0",
|
"pathfinder_gpu 0.1.0",
|
||||||
"pathfinder_metal 0.1.0",
|
"pathfinder_metal 0.1.0",
|
||||||
"pathfinder_renderer 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 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)",
|
"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_gl 0.1.0",
|
||||||
"pathfinder_gpu 0.1.0",
|
"pathfinder_gpu 0.1.0",
|
||||||
"pathfinder_renderer 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 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)",
|
"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 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)",
|
"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)",
|
"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]]
|
[[package]]
|
||||||
|
|
|
@ -36,3 +36,6 @@ path = "../../metal"
|
||||||
|
|
||||||
[dependencies.pathfinder_renderer]
|
[dependencies.pathfinder_renderer]
|
||||||
path = "../../renderer"
|
path = "../../renderer"
|
||||||
|
|
||||||
|
[dependencies.pathfinder_resources]
|
||||||
|
path = "../../resources"
|
||||||
|
|
|
@ -31,3 +31,6 @@ path = "../../gpu"
|
||||||
|
|
||||||
[dependencies.pathfinder_renderer]
|
[dependencies.pathfinder_renderer]
|
||||||
path = "../../renderer"
|
path = "../../renderer"
|
||||||
|
|
||||||
|
[dependencies.pathfinder_resources]
|
||||||
|
path = "../../resources"
|
||||||
|
|
|
@ -12,6 +12,7 @@ rayon = "1.0"
|
||||||
serde = "1.0"
|
serde = "1.0"
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
smallvec = "1.2"
|
smallvec = "1.2"
|
||||||
|
vec_map = "0.8"
|
||||||
|
|
||||||
[dependencies.log]
|
[dependencies.log]
|
||||||
version = "0.4"
|
version = "0.4"
|
||||||
|
|
|
@ -13,7 +13,8 @@
|
||||||
use crate::concurrent::executor::Executor;
|
use crate::concurrent::executor::Executor;
|
||||||
use crate::gpu::renderer::{BlendModeProgram, MASK_TILES_ACROSS};
|
use crate::gpu::renderer::{BlendModeProgram, MASK_TILES_ACROSS};
|
||||||
use crate::gpu_data::{AlphaTile, AlphaTileBatch, AlphaTileVertex, FillBatchPrimitive, MaskTile};
|
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::gpu_data::{SolidTileBatch, TileObjectPrimitive};
|
||||||
use crate::options::{PreparedBuildOptions, RenderCommandListener};
|
use crate::options::{PreparedBuildOptions, RenderCommandListener};
|
||||||
use crate::paint::{PaintInfo, PaintMetadata};
|
use crate::paint::{PaintInfo, PaintMetadata};
|
||||||
|
@ -21,7 +22,7 @@ use crate::scene::{DisplayItem, Scene};
|
||||||
use crate::tile_map::DenseTileMap;
|
use crate::tile_map::DenseTileMap;
|
||||||
use crate::tiles::{self, TILE_HEIGHT, TILE_WIDTH, Tiler, TilingPathInfo};
|
use crate::tiles::{self, TILE_HEIGHT, TILE_WIDTH, Tiler, TilingPathInfo};
|
||||||
use crate::z_buffer::ZBuffer;
|
use crate::z_buffer::ZBuffer;
|
||||||
use pathfinder_content::effects::{BlendMode, Effects};
|
use pathfinder_content::effects::BlendMode;
|
||||||
use pathfinder_content::fill::FillRule;
|
use pathfinder_content::fill::FillRule;
|
||||||
use pathfinder_content::pattern::RenderTargetId;
|
use pathfinder_content::pattern::RenderTargetId;
|
||||||
use pathfinder_geometry::line_segment::{LineSegment2F, LineSegmentU4, LineSegmentU8};
|
use pathfinder_geometry::line_segment::{LineSegment2F, LineSegmentU4, LineSegmentU8};
|
||||||
|
@ -219,55 +220,67 @@ impl<'a> SceneBuilder<'a> {
|
||||||
|
|
||||||
// Process first Z-buffer.
|
// Process first Z-buffer.
|
||||||
let first_z_buffer = remaining_layer_z_buffers.pop().unwrap();
|
let first_z_buffer = remaining_layer_z_buffers.pop().unwrap();
|
||||||
let first_solid_tiles = first_z_buffer.build_solid_tiles(&self.scene.paths,
|
let first_solid_tiles = first_z_buffer.build_solid_tiles(paint_metadata);
|
||||||
paint_metadata);
|
|
||||||
for batch in first_solid_tiles.batches {
|
for batch in first_solid_tiles.batches {
|
||||||
culled_tiles.display_list.push(CulledDisplayItem::DrawSolidTiles(batch));
|
culled_tiles.display_list.push(CulledDisplayItem::DrawSolidTiles(batch));
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut layer_z_buffers_stack = vec![first_z_buffer];
|
let mut layer_z_buffers_stack = vec![first_z_buffer];
|
||||||
|
let mut current_depth = 1;
|
||||||
|
|
||||||
for display_item in &self.scene.display_list {
|
for display_item in &self.scene.display_list {
|
||||||
// Pass all commands except `DrawPaths` through.
|
match *display_item {
|
||||||
let (start_draw_path_index, end_draw_path_index) = match *display_item {
|
|
||||||
DisplayItem::PushRenderTarget(render_target_id) => {
|
DisplayItem::PushRenderTarget(render_target_id) => {
|
||||||
culled_tiles.display_list
|
culled_tiles.display_list
|
||||||
.push(CulledDisplayItem::PushRenderTarget(render_target_id));
|
.push(CulledDisplayItem::PushRenderTarget(render_target_id));
|
||||||
|
|
||||||
let z_buffer = remaining_layer_z_buffers.pop().unwrap();
|
let z_buffer = remaining_layer_z_buffers.pop().unwrap();
|
||||||
let solid_tiles = z_buffer.build_solid_tiles(&self.scene.paths,
|
let solid_tiles = z_buffer.build_solid_tiles(paint_metadata);
|
||||||
paint_metadata);
|
|
||||||
for batch in solid_tiles.batches {
|
for batch in solid_tiles.batches {
|
||||||
culled_tiles.display_list.push(CulledDisplayItem::DrawSolidTiles(batch));
|
culled_tiles.display_list.push(CulledDisplayItem::DrawSolidTiles(batch));
|
||||||
}
|
}
|
||||||
layer_z_buffers_stack.push(z_buffer);
|
layer_z_buffers_stack.push(z_buffer);
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DisplayItem::PopRenderTarget => {
|
DisplayItem::PopRenderTarget => {
|
||||||
culled_tiles.display_list.push(CulledDisplayItem::PopRenderTarget);
|
culled_tiles.display_list.push(CulledDisplayItem::PopRenderTarget);
|
||||||
layer_z_buffers_stack.pop();
|
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),
|
|
||||||
};
|
|
||||||
|
|
||||||
|
DisplayItem::DrawRenderTarget { render_target, effects } => {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
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];
|
let built_draw_path = &built_draw_paths[draw_path_index as usize];
|
||||||
culled_tiles.push_mask_tiles(&built_draw_path.path);
|
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
|
// Create a new `DrawAlphaTiles` display item if we don't have one or if we
|
||||||
// break a batch due to blend mode or paint page. Note that every path with a blend
|
// have to break a batch due to blend mode or paint page. Note that every
|
||||||
// mode that requires a readable framebuffer needs its own batch.
|
// 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
|
// TODO(pcwalton): If we really wanted to, we could use tile maps to avoid
|
||||||
// breaks in some cases…
|
// batch breaks in some cases…
|
||||||
match culled_tiles.display_list.last() {
|
match culled_tiles.display_list.last() {
|
||||||
Some(&CulledDisplayItem::DrawAlphaTiles(AlphaTileBatch {
|
Some(&CulledDisplayItem::DrawAlphaTiles(AlphaTileBatch {
|
||||||
tiles: _,
|
tiles: _,
|
||||||
|
@ -280,18 +293,21 @@ impl<'a> SceneBuilder<'a> {
|
||||||
!BlendModeProgram::from_blend_mode(
|
!BlendModeProgram::from_blend_mode(
|
||||||
blend_mode).needs_readable_framebuffer() => {}
|
blend_mode).needs_readable_framebuffer() => {}
|
||||||
_ => {
|
_ => {
|
||||||
culled_tiles.display_list
|
let batch = AlphaTileBatch {
|
||||||
.push(CulledDisplayItem::DrawAlphaTiles(AlphaTileBatch {
|
|
||||||
tiles: vec![],
|
tiles: vec![],
|
||||||
paint_page: built_draw_path.paint_page,
|
paint_page: built_draw_path.paint_page,
|
||||||
blend_mode: built_draw_path.blend_mode,
|
blend_mode: built_draw_path.blend_mode,
|
||||||
sampling_flags: built_draw_path.sampling_flags,
|
sampling_flags: built_draw_path.sampling_flags,
|
||||||
}))
|
};
|
||||||
|
culled_tiles.display_list
|
||||||
|
.push(CulledDisplayItem::DrawAlphaTiles(batch))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch the destination alpha tiles buffer.
|
// Fetch the destination alpha tiles buffer.
|
||||||
let culled_alpha_tiles = match *culled_tiles.display_list.last_mut().unwrap() {
|
let culled_alpha_tiles = match *culled_tiles.display_list
|
||||||
|
.last_mut()
|
||||||
|
.unwrap() {
|
||||||
CulledDisplayItem::DrawAlphaTiles(AlphaTileBatch {
|
CulledDisplayItem::DrawAlphaTiles(AlphaTileBatch {
|
||||||
tiles: ref mut culled_alpha_tiles,
|
tiles: ref mut culled_alpha_tiles,
|
||||||
..
|
..
|
||||||
|
@ -302,11 +318,14 @@ impl<'a> SceneBuilder<'a> {
|
||||||
let layer_z_buffer = layer_z_buffers_stack.last().unwrap();
|
let layer_z_buffer = layer_z_buffers_stack.last().unwrap();
|
||||||
for alpha_tile in &built_draw_path.path.alpha_tiles {
|
for alpha_tile in &built_draw_path.path.alpha_tiles {
|
||||||
let alpha_tile_coords = alpha_tile.upper_left.tile_position();
|
let alpha_tile_coords = alpha_tile.upper_left.tile_position();
|
||||||
if layer_z_buffer.test(alpha_tile_coords,
|
if layer_z_buffer.test(alpha_tile_coords, current_depth) {
|
||||||
alpha_tile.upper_left.object_index as u32) {
|
|
||||||
culled_alpha_tiles.push(*alpha_tile);
|
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 effective_view_box = self.scene.effective_view_box(self.built_options);
|
||||||
let mut z_buffers = vec![ZBuffer::new(effective_view_box)];
|
let mut z_buffers = vec![ZBuffer::new(effective_view_box)];
|
||||||
let mut z_buffer_index_stack = vec![0];
|
let mut z_buffer_index_stack = vec![0];
|
||||||
|
let mut current_depth = 0;
|
||||||
|
|
||||||
// Create Z-buffers.
|
// Create Z-buffers.
|
||||||
for display_item in &self.scene.display_list {
|
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()];
|
let z_buffer = &mut z_buffers[*z_buffer_index_stack.last().unwrap()];
|
||||||
for (path_subindex, built_draw_path) in
|
for (path_subindex, built_draw_path) in
|
||||||
built_draw_paths[start_index..end_index].iter().enumerate() {
|
built_draw_paths[start_index..end_index].iter().enumerate() {
|
||||||
z_buffer.update(&built_draw_path.path.solid_tiles,
|
let solid_tiles = &built_draw_path.path.solid_tiles;
|
||||||
(path_subindex + start_index) as u32);
|
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 { .. } => {
|
DisplayItem::DrawRenderTarget { .. } => {
|
||||||
// FIXME(pcwalton): Not great that this doesn't participate in Z-buffering!
|
// 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) => {
|
CulledDisplayItem::DrawAlphaTiles(batch) => {
|
||||||
self.listener.send(RenderCommand::DrawAlphaTiles(batch))
|
self.listener.send(RenderCommand::DrawAlphaTiles(batch))
|
||||||
}
|
}
|
||||||
CulledDisplayItem::DrawRenderTarget { render_target, effects } => {
|
CulledDisplayItem::DrawRenderTargetTiles(batch) => {
|
||||||
self.listener.send(RenderCommand::DrawRenderTarget { render_target, effects })
|
self.listener.send(RenderCommand::DrawRenderTargetTiles(batch))
|
||||||
}
|
}
|
||||||
CulledDisplayItem::PushRenderTarget(render_target_id) => {
|
CulledDisplayItem::PushRenderTarget(render_target_id) => {
|
||||||
self.listener.send(RenderCommand::PushRenderTarget(render_target_id))
|
self.listener.send(RenderCommand::PushRenderTarget(render_target_id))
|
||||||
|
@ -449,7 +473,7 @@ struct CulledTiles {
|
||||||
enum CulledDisplayItem {
|
enum CulledDisplayItem {
|
||||||
DrawSolidTiles(SolidTileBatch),
|
DrawSolidTiles(SolidTileBatch),
|
||||||
DrawAlphaTiles(AlphaTileBatch),
|
DrawAlphaTiles(AlphaTileBatch),
|
||||||
DrawRenderTarget { render_target: RenderTargetId, effects: Effects },
|
DrawRenderTargetTiles(RenderTargetTileBatch),
|
||||||
PushRenderTarget(RenderTargetId),
|
PushRenderTarget(RenderTargetId),
|
||||||
PopRenderTarget,
|
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 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -12,15 +12,14 @@ use crate::gpu::debug::DebugUIPresenter;
|
||||||
use crate::gpu::options::{DestFramebuffer, RendererOptions};
|
use crate::gpu::options::{DestFramebuffer, RendererOptions};
|
||||||
use crate::gpu::shaders::{AlphaTileBlendModeProgram, AlphaTileDodgeBurnProgram};
|
use crate::gpu::shaders::{AlphaTileBlendModeProgram, AlphaTileDodgeBurnProgram};
|
||||||
use crate::gpu::shaders::{AlphaTileHSLProgram, AlphaTileOverlayProgram};
|
use crate::gpu::shaders::{AlphaTileHSLProgram, AlphaTileOverlayProgram};
|
||||||
use crate::gpu::shaders::{AlphaTileProgram, AlphaTileVertexArray, CopyTileProgram};
|
use crate::gpu::shaders::{AlphaTileProgram, AlphaTileVertexArray, BlitProgram, BlitVertexArray, CopyTileProgram};
|
||||||
use crate::gpu::shaders::{CopyTileVertexArray, FillProgram, FillVertexArray, FilterBasicProgram};
|
use crate::gpu::shaders::{CopyTileVertexArray, FillProgram, FillVertexArray};
|
||||||
use crate::gpu::shaders::{FilterBasicVertexArray,FilterBlurProgram, FilterBlurVertexArray};
|
use crate::gpu::shaders::{MAX_FILLS_PER_BATCH};
|
||||||
use crate::gpu::shaders::{FilterTextProgram, FilterTextVertexArray, MAX_FILLS_PER_BATCH};
|
|
||||||
use crate::gpu::shaders::{MaskTileProgram, MaskTileVertexArray, ReprojectionProgram};
|
use crate::gpu::shaders::{MaskTileProgram, MaskTileVertexArray, ReprojectionProgram};
|
||||||
use crate::gpu::shaders::{ReprojectionVertexArray, SolidTileProgram, SolidTileVertexArray};
|
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::{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::options::BoundingQuad;
|
||||||
use crate::tiles::{TILE_HEIGHT, TILE_WIDTH};
|
use crate::tiles::{TILE_HEIGHT, TILE_WIDTH};
|
||||||
use pathfinder_color::{self as color, ColorF};
|
use pathfinder_color::{self as color, ColorF};
|
||||||
|
@ -78,6 +77,7 @@ where
|
||||||
// Core data
|
// Core data
|
||||||
dest_framebuffer: DestFramebuffer<D>,
|
dest_framebuffer: DestFramebuffer<D>,
|
||||||
options: RendererOptions,
|
options: RendererOptions,
|
||||||
|
blit_program: BlitProgram<D>,
|
||||||
fill_program: FillProgram<D>,
|
fill_program: FillProgram<D>,
|
||||||
mask_winding_tile_program: MaskTileProgram<D>,
|
mask_winding_tile_program: MaskTileProgram<D>,
|
||||||
mask_evenodd_tile_program: MaskTileProgram<D>,
|
mask_evenodd_tile_program: MaskTileProgram<D>,
|
||||||
|
@ -90,6 +90,7 @@ where
|
||||||
alpha_tile_difference_program: AlphaTileBlendModeProgram<D>,
|
alpha_tile_difference_program: AlphaTileBlendModeProgram<D>,
|
||||||
alpha_tile_exclusion_program: AlphaTileBlendModeProgram<D>,
|
alpha_tile_exclusion_program: AlphaTileBlendModeProgram<D>,
|
||||||
alpha_tile_hsl_program: AlphaTileHSLProgram<D>,
|
alpha_tile_hsl_program: AlphaTileHSLProgram<D>,
|
||||||
|
blit_vertex_array: BlitVertexArray<D>,
|
||||||
mask_winding_tile_vertex_array: MaskTileVertexArray<D>,
|
mask_winding_tile_vertex_array: MaskTileVertexArray<D>,
|
||||||
mask_evenodd_tile_vertex_array: MaskTileVertexArray<D>,
|
mask_evenodd_tile_vertex_array: MaskTileVertexArray<D>,
|
||||||
copy_tile_vertex_array: CopyTileVertexArray<D>,
|
copy_tile_vertex_array: CopyTileVertexArray<D>,
|
||||||
|
@ -122,12 +123,13 @@ where
|
||||||
clear_paint_texture: D::Texture,
|
clear_paint_texture: D::Texture,
|
||||||
|
|
||||||
// Filter shaders
|
// Filter shaders
|
||||||
filter_basic_program: FilterBasicProgram<D>,
|
tile_filter_basic_program: TileFilterBasicProgram<D>,
|
||||||
filter_basic_vertex_array: FilterBasicVertexArray<D>,
|
tile_filter_blur_program: TileFilterBlurProgram<D>,
|
||||||
filter_blur_program: FilterBlurProgram<D>,
|
tile_filter_text_program: TileFilterTextProgram<D>,
|
||||||
filter_blur_vertex_array: FilterBlurVertexArray<D>,
|
tile_filter_basic_vertex_array: TileFilterVertexArray<D>,
|
||||||
filter_text_program: FilterTextProgram<D>,
|
tile_filter_blur_vertex_array: TileFilterVertexArray<D>,
|
||||||
filter_text_vertex_array: FilterTextVertexArray<D>,
|
tile_filter_text_vertex_array: TileFilterVertexArray<D>,
|
||||||
|
tile_filter_vertex_buffer: D::Buffer,
|
||||||
gamma_lut_texture: D::Texture,
|
gamma_lut_texture: D::Texture,
|
||||||
|
|
||||||
// Stencil shader
|
// Stencil shader
|
||||||
|
@ -163,6 +165,7 @@ where
|
||||||
dest_framebuffer: DestFramebuffer<D>,
|
dest_framebuffer: DestFramebuffer<D>,
|
||||||
options: RendererOptions)
|
options: RendererOptions)
|
||||||
-> Renderer<D> {
|
-> Renderer<D> {
|
||||||
|
let blit_program = BlitProgram::new(&device, resources);
|
||||||
let fill_program = FillProgram::new(&device, resources);
|
let fill_program = FillProgram::new(&device, resources);
|
||||||
let mask_winding_tile_program = MaskTileProgram::new(FillRule::Winding,
|
let mask_winding_tile_program = MaskTileProgram::new(FillRule::Winding,
|
||||||
&device,
|
&device,
|
||||||
|
@ -184,9 +187,9 @@ where
|
||||||
resources,
|
resources,
|
||||||
"tile_alpha_exclusion");
|
"tile_alpha_exclusion");
|
||||||
let alpha_tile_hsl_program = AlphaTileHSLProgram::new(&device, resources);
|
let alpha_tile_hsl_program = AlphaTileHSLProgram::new(&device, resources);
|
||||||
let filter_basic_program = FilterBasicProgram::new(&device, resources);
|
let tile_filter_basic_program = TileFilterBasicProgram::new(&device, resources);
|
||||||
let filter_blur_program = FilterBlurProgram::new(&device, resources);
|
let tile_filter_blur_program = TileFilterBlurProgram::new(&device, resources);
|
||||||
let filter_text_program = FilterTextProgram::new(&device, resources);
|
let tile_filter_text_program = TileFilterTextProgram::new(&device, resources);
|
||||||
let stencil_program = StencilProgram::new(&device, resources);
|
let stencil_program = StencilProgram::new(&device, resources);
|
||||||
let reprojection_program = ReprojectionProgram::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 gamma_lut_texture = device.create_texture_from_png(resources, "gamma-lut");
|
||||||
|
|
||||||
let alpha_tile_vertex_buffer = device.create_buffer();
|
let alpha_tile_vertex_buffer = device.create_buffer();
|
||||||
|
let tile_filter_vertex_buffer = device.create_buffer();
|
||||||
let quad_vertex_positions_buffer = device.create_buffer();
|
let quad_vertex_positions_buffer = device.create_buffer();
|
||||||
device.allocate_buffer(
|
device.allocate_buffer(
|
||||||
&quad_vertex_positions_buffer,
|
&quad_vertex_positions_buffer,
|
||||||
|
@ -210,6 +214,12 @@ where
|
||||||
);
|
);
|
||||||
let quads_vertex_indices_buffer = device.create_buffer();
|
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(
|
let fill_vertex_array = FillVertexArray::new(
|
||||||
&device,
|
&device,
|
||||||
&fill_program,
|
&fill_program,
|
||||||
|
@ -279,23 +289,23 @@ where
|
||||||
&solid_tile_program,
|
&solid_tile_program,
|
||||||
&quads_vertex_indices_buffer,
|
&quads_vertex_indices_buffer,
|
||||||
);
|
);
|
||||||
let filter_basic_vertex_array = FilterBasicVertexArray::new(
|
let tile_filter_basic_vertex_array = TileFilterVertexArray::new(
|
||||||
&device,
|
&device,
|
||||||
&filter_basic_program,
|
&tile_filter_basic_program.tile_filter_program,
|
||||||
&quad_vertex_positions_buffer,
|
&tile_filter_vertex_buffer,
|
||||||
&quad_vertex_indices_buffer,
|
&quads_vertex_indices_buffer,
|
||||||
);
|
);
|
||||||
let filter_blur_vertex_array = FilterBlurVertexArray::new(
|
let tile_filter_blur_vertex_array = TileFilterVertexArray::new(
|
||||||
&device,
|
&device,
|
||||||
&filter_blur_program,
|
&tile_filter_blur_program.tile_filter_program,
|
||||||
&quad_vertex_positions_buffer,
|
&tile_filter_vertex_buffer,
|
||||||
&quad_vertex_indices_buffer,
|
&quads_vertex_indices_buffer,
|
||||||
);
|
);
|
||||||
let filter_text_vertex_array = FilterTextVertexArray::new(
|
let tile_filter_text_vertex_array = TileFilterVertexArray::new(
|
||||||
&device,
|
&device,
|
||||||
&filter_text_program,
|
&tile_filter_text_program.tile_filter_program,
|
||||||
&quad_vertex_positions_buffer,
|
&tile_filter_vertex_buffer,
|
||||||
&quad_vertex_indices_buffer,
|
&quads_vertex_indices_buffer,
|
||||||
);
|
);
|
||||||
let stencil_vertex_array = StencilVertexArray::new(&device, &stencil_program);
|
let stencil_vertex_array = StencilVertexArray::new(&device, &stencil_program);
|
||||||
let reprojection_vertex_array = ReprojectionVertexArray::new(
|
let reprojection_vertex_array = ReprojectionVertexArray::new(
|
||||||
|
@ -335,6 +345,7 @@ where
|
||||||
|
|
||||||
dest_framebuffer,
|
dest_framebuffer,
|
||||||
options,
|
options,
|
||||||
|
blit_program,
|
||||||
fill_program,
|
fill_program,
|
||||||
mask_winding_tile_program,
|
mask_winding_tile_program,
|
||||||
mask_evenodd_tile_program,
|
mask_evenodd_tile_program,
|
||||||
|
@ -347,6 +358,7 @@ where
|
||||||
alpha_tile_difference_program,
|
alpha_tile_difference_program,
|
||||||
alpha_tile_exclusion_program,
|
alpha_tile_exclusion_program,
|
||||||
alpha_tile_hsl_program,
|
alpha_tile_hsl_program,
|
||||||
|
blit_vertex_array,
|
||||||
mask_winding_tile_vertex_array,
|
mask_winding_tile_vertex_array,
|
||||||
mask_evenodd_tile_vertex_array,
|
mask_evenodd_tile_vertex_array,
|
||||||
copy_tile_vertex_array,
|
copy_tile_vertex_array,
|
||||||
|
@ -374,12 +386,13 @@ where
|
||||||
render_target_stack: vec![],
|
render_target_stack: vec![],
|
||||||
clear_paint_texture,
|
clear_paint_texture,
|
||||||
|
|
||||||
filter_basic_program,
|
tile_filter_basic_program,
|
||||||
filter_basic_vertex_array,
|
tile_filter_basic_vertex_array,
|
||||||
filter_blur_program,
|
tile_filter_blur_program,
|
||||||
filter_blur_vertex_array,
|
tile_filter_blur_vertex_array,
|
||||||
filter_text_program,
|
tile_filter_text_program,
|
||||||
filter_text_vertex_array,
|
tile_filter_text_vertex_array,
|
||||||
|
tile_filter_vertex_buffer,
|
||||||
gamma_lut_texture,
|
gamma_lut_texture,
|
||||||
|
|
||||||
stencil_program,
|
stencil_program,
|
||||||
|
@ -428,8 +441,10 @@ where
|
||||||
self.push_render_target(render_target_id)
|
self.push_render_target(render_target_id)
|
||||||
}
|
}
|
||||||
RenderCommand::PopRenderTarget => self.pop_render_target(),
|
RenderCommand::PopRenderTarget => self.pop_render_target(),
|
||||||
RenderCommand::DrawRenderTarget { render_target, effects } => {
|
RenderCommand::DrawRenderTargetTiles(ref batch) => {
|
||||||
self.draw_entire_render_target(render_target, effects)
|
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) => {
|
RenderCommand::DrawSolidTiles(ref batch) => {
|
||||||
let count = batch.vertices.len() / 4;
|
let count = batch.vertices.len() / 4;
|
||||||
|
@ -630,6 +645,14 @@ where
|
||||||
self.ensure_index_buffer(alpha_tiles.len());
|
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) {
|
fn ensure_index_buffer(&mut self, mut length: usize) {
|
||||||
length = length.next_power_of_two();
|
length = length.next_power_of_two();
|
||||||
if self.quads_vertex_indices_length >= length {
|
if self.quads_vertex_indices_length >= length {
|
||||||
|
@ -1152,118 +1175,92 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME(pcwalton): This is inefficient and should eventually go away.
|
// 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 {
|
match effects.filter {
|
||||||
Filter::Composite(composite_op) => {
|
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 } => {
|
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,
|
fg_color,
|
||||||
bg_color,
|
bg_color,
|
||||||
defringing_kernel,
|
defringing_kernel,
|
||||||
gamma_correction)
|
gamma_correction)
|
||||||
}
|
}
|
||||||
Filter::Blur { direction, sigma } => {
|
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();
|
self.preserve_draw_framebuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn composite_render_target(&self,
|
fn composite_render_target(&mut self,
|
||||||
|
tile_count: u32,
|
||||||
render_target_id: RenderTargetId,
|
render_target_id: RenderTargetId,
|
||||||
composite_op: CompositeOp) {
|
composite_op: CompositeOp) {
|
||||||
let clear_color = self.clear_color_for_draw_operation();
|
self.finish_drawing_render_target_tiles(&self.tile_filter_basic_program
|
||||||
let source_framebuffer = &self.render_targets[render_target_id.0 as usize].framebuffer;
|
.tile_filter_program,
|
||||||
let source_texture = self.device.framebuffer_texture(source_framebuffer);
|
&self.tile_filter_basic_vertex_array,
|
||||||
let main_viewport = self.main_viewport();
|
tile_count,
|
||||||
|
render_target_id,
|
||||||
|
vec![],
|
||||||
|
vec![],
|
||||||
|
composite_op.to_blend_state());
|
||||||
|
|
||||||
let uniforms = vec![
|
self.preserve_draw_framebuffer();
|
||||||
(&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()
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_text_render_target(&self,
|
fn draw_text_render_target(&mut self,
|
||||||
|
tile_count: u32,
|
||||||
render_target_id: RenderTargetId,
|
render_target_id: RenderTargetId,
|
||||||
fg_color: ColorF,
|
fg_color: ColorF,
|
||||||
bg_color: ColorF,
|
bg_color: ColorF,
|
||||||
defringing_kernel: Option<DefringingKernel>,
|
defringing_kernel: Option<DefringingKernel>,
|
||||||
gamma_correction: bool) {
|
gamma_correction: bool) {
|
||||||
let clear_color = self.clear_color_for_draw_operation();
|
let textures = vec![&self.gamma_lut_texture];
|
||||||
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 mut uniforms = vec![
|
let mut uniforms = vec![
|
||||||
(&self.filter_text_program.framebuffer_size_uniform,
|
(&self.tile_filter_text_program.gamma_lut_uniform, UniformData::TextureUnit(0)),
|
||||||
UniformData::Vec2(main_viewport.size().to_f32().0)),
|
(&self.tile_filter_text_program.fg_color_uniform, UniformData::Vec4(fg_color.0)),
|
||||||
(&self.filter_text_program.source_uniform, UniformData::TextureUnit(0)),
|
(&self.tile_filter_text_program.bg_color_uniform, UniformData::Vec4(bg_color.0)),
|
||||||
(&self.filter_text_program.source_size_uniform,
|
(&self.tile_filter_text_program.gamma_correction_enabled_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,
|
|
||||||
UniformData::Int(gamma_correction as i32)),
|
UniformData::Int(gamma_correction as i32)),
|
||||||
];
|
];
|
||||||
|
|
||||||
match defringing_kernel {
|
match defringing_kernel {
|
||||||
Some(ref 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))));
|
UniformData::Vec4(F32x4::from_slice(&kernel.0))));
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
uniforms.push((&self.filter_text_program.kernel_uniform,
|
uniforms.push((&self.tile_filter_text_program.kernel_uniform,
|
||||||
UniformData::Vec4(F32x4::default())));
|
UniformData::Vec4(F32x4::default())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.device.draw_elements(6, &RenderState {
|
self.finish_drawing_render_target_tiles(&self.tile_filter_text_program.tile_filter_program,
|
||||||
target: &self.draw_render_target(),
|
&self.tile_filter_text_vertex_array,
|
||||||
program: &self.filter_text_program.program,
|
tile_count,
|
||||||
vertex_array: &self.filter_text_vertex_array.vertex_array,
|
render_target_id,
|
||||||
primitive: Primitive::Triangles,
|
uniforms,
|
||||||
textures: &[&source_texture, &self.gamma_lut_texture],
|
textures,
|
||||||
uniforms: &uniforms,
|
None);
|
||||||
viewport: main_viewport,
|
|
||||||
options: RenderOptions {
|
self.preserve_draw_framebuffer();
|
||||||
clear_ops: ClearOps { color: clear_color, ..ClearOps::default() },
|
|
||||||
..RenderOptions::default()
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_blur_render_target(&self,
|
fn draw_blur_render_target(&mut self,
|
||||||
|
tile_count: u32,
|
||||||
render_target_id: RenderTargetId,
|
render_target_id: RenderTargetId,
|
||||||
direction: BlurDirection,
|
direction: BlurDirection,
|
||||||
sigma: f32) {
|
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_framebuffer = &self.render_targets[render_target_id.0 as usize].framebuffer;
|
||||||
let source_texture = self.device.framebuffer_texture(source_framebuffer);
|
let source_texture = self.device.framebuffer_texture(source_framebuffer);
|
||||||
let source_texture_size = self.device.texture_size(source_texture);
|
let source_texture_size = self.device.texture_size(source_texture);
|
||||||
let main_viewport = self.main_viewport();
|
|
||||||
|
|
||||||
let sigma_inv = 1.0 / sigma;
|
let sigma_inv = 1.0 / sigma;
|
||||||
let gauss_coeff_x = SQRT_2_PI_INV * sigma_inv;
|
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 src_offset_scale = src_offset / source_texture_size.to_f32();
|
||||||
|
|
||||||
let uniforms = vec![
|
let uniforms = vec![
|
||||||
(&self.filter_blur_program.framebuffer_size_uniform,
|
(&self.tile_filter_blur_program.src_offset_scale_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,
|
|
||||||
UniformData::Vec2(src_offset_scale.0)),
|
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])),
|
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)),
|
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<D>,
|
||||||
|
tile_filter_vertex_array: &'a TileFilterVertexArray<D>,
|
||||||
|
tile_count: u32,
|
||||||
|
render_target_id: RenderTargetId,
|
||||||
|
mut uniforms: Vec<(&'a D::Uniform, UniformData)>,
|
||||||
|
mut textures: Vec<&'a D::Texture>,
|
||||||
|
blend_state: Option<BlendState>) {
|
||||||
|
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(),
|
target: &self.draw_render_target(),
|
||||||
program: &self.filter_blur_program.program,
|
program: &tile_filter_program.program,
|
||||||
vertex_array: &self.filter_blur_vertex_array.vertex_array,
|
vertex_array: &tile_filter_vertex_array.vertex_array,
|
||||||
primitive: Primitive::Triangles,
|
primitive: Primitive::Triangles,
|
||||||
textures: &[&source_texture],
|
textures: &textures,
|
||||||
uniforms: &uniforms,
|
uniforms: &uniforms,
|
||||||
viewport: main_viewport,
|
viewport: main_viewport,
|
||||||
options: RenderOptions {
|
options: RenderOptions {
|
||||||
clear_ops: ClearOps { color: clear_color, ..ClearOps::default() },
|
clear_ops: ClearOps { color: clear_color, ..ClearOps::default() },
|
||||||
blend: CompositeOp::SrcOver.to_blend_state(),
|
blend: blend_state,
|
||||||
..RenderOptions::default()
|
..RenderOptions::default()
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -1311,13 +1342,13 @@ where
|
||||||
|
|
||||||
let main_viewport = self.main_viewport();
|
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))];
|
let textures = [(self.device.framebuffer_texture(&self.intermediate_dest_framebuffer))];
|
||||||
|
|
||||||
self.device.draw_elements(6, &RenderState {
|
self.device.draw_elements(6, &RenderState {
|
||||||
target: &RenderTarget::Default,
|
target: &RenderTarget::Default,
|
||||||
program: &self.filter_basic_program.program,
|
program: &self.blit_program.program,
|
||||||
vertex_array: &self.filter_basic_vertex_array.vertex_array,
|
vertex_array: &self.blit_vertex_array.vertex_array,
|
||||||
primitive: Primitive::Triangles,
|
primitive: Primitive::Triangles,
|
||||||
textures: &textures[..],
|
textures: &textures[..],
|
||||||
uniforms: &uniforms[..],
|
uniforms: &uniforms[..],
|
||||||
|
|
|
@ -18,10 +18,40 @@ use pathfinder_resources::ResourceLoader;
|
||||||
const FILL_INSTANCE_SIZE: usize = 8;
|
const FILL_INSTANCE_SIZE: usize = 8;
|
||||||
const SOLID_TILE_VERTEX_SIZE: usize = 16;
|
const SOLID_TILE_VERTEX_SIZE: usize = 16;
|
||||||
const ALPHA_TILE_VERTEX_SIZE: usize = 20;
|
const ALPHA_TILE_VERTEX_SIZE: usize = 20;
|
||||||
|
const FILTER_TILE_VERTEX_SIZE: usize = 4;
|
||||||
const MASK_TILE_VERTEX_SIZE: usize = 12;
|
const MASK_TILE_VERTEX_SIZE: usize = 12;
|
||||||
|
|
||||||
pub const MAX_FILLS_PER_BATCH: usize = 0x4000;
|
pub const MAX_FILLS_PER_BATCH: usize = 0x4000;
|
||||||
|
|
||||||
|
pub struct BlitVertexArray<D> where D: Device {
|
||||||
|
pub vertex_array: D::VertexArray,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<D> BlitVertexArray<D> where D: Device {
|
||||||
|
pub fn new(device: &D,
|
||||||
|
blit_program: &BlitProgram<D>,
|
||||||
|
quad_vertex_positions_buffer: &D::Buffer,
|
||||||
|
quad_vertex_indices_buffer: &D::Buffer)
|
||||||
|
-> BlitVertexArray<D> {
|
||||||
|
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<D>
|
pub struct FillVertexArray<D>
|
||||||
where
|
where
|
||||||
D: Device,
|
D: Device,
|
||||||
|
@ -323,6 +353,19 @@ impl<D> CopyTileVertexArray<D> where D: Device {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct BlitProgram<D> where D: Device {
|
||||||
|
pub program: D::Program,
|
||||||
|
pub src_uniform: D::Uniform,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<D> BlitProgram<D> where D: Device {
|
||||||
|
pub fn new(device: &D, resources: &dyn ResourceLoader) -> BlitProgram<D> {
|
||||||
|
let program = device.create_program(resources, "blit");
|
||||||
|
let src_uniform = device.get_uniform(&program, "Src");
|
||||||
|
BlitProgram { program, src_uniform }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct FillProgram<D>
|
pub struct FillProgram<D>
|
||||||
where
|
where
|
||||||
D: Device,
|
D: Device,
|
||||||
|
@ -523,79 +566,101 @@ impl<D> AlphaTileDodgeBurnProgram<D> where D: Device {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct FilterBasicProgram<D> where D: Device {
|
pub struct TileFilterProgram<D> where D: Device {
|
||||||
pub program: D::Program,
|
pub program: D::Program,
|
||||||
pub source_uniform: D::Uniform,
|
pub transform_uniform: D::Uniform,
|
||||||
pub framebuffer_size_uniform: D::Uniform,
|
pub tile_size_uniform: D::Uniform,
|
||||||
|
pub src_uniform: D::Uniform,
|
||||||
|
pub src_size_uniform: D::Uniform,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D> FilterBasicProgram<D> where D: Device {
|
impl<D> TileFilterProgram<D> where D: Device {
|
||||||
pub fn new(device: &D, resources: &dyn ResourceLoader) -> FilterBasicProgram<D> {
|
pub fn new(device: &D,
|
||||||
|
resources: &dyn ResourceLoader,
|
||||||
|
program_name: &str,
|
||||||
|
fragment_shader_name: &str)
|
||||||
|
-> TileFilterProgram<D> {
|
||||||
let program = device.create_program_from_shader_names(resources,
|
let program = device.create_program_from_shader_names(resources,
|
||||||
"filter_basic",
|
program_name,
|
||||||
"filter",
|
"tile_filter",
|
||||||
"filter_basic");
|
fragment_shader_name);
|
||||||
let source_uniform = device.get_uniform(&program, "Source");
|
let transform_uniform = device.get_uniform(&program, "Transform");
|
||||||
let framebuffer_size_uniform = device.get_uniform(&program, "FramebufferSize");
|
let tile_size_uniform = device.get_uniform(&program, "TileSize");
|
||||||
FilterBasicProgram { program, source_uniform, framebuffer_size_uniform }
|
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<D> where D: Device {
|
pub struct TileFilterBasicProgram<D> where D: Device {
|
||||||
|
pub tile_filter_program: TileFilterProgram<D>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<D> TileFilterBasicProgram<D> where D: Device {
|
||||||
|
pub fn new(device: &D, resources: &dyn ResourceLoader) -> TileFilterBasicProgram<D> {
|
||||||
|
TileFilterBasicProgram {
|
||||||
|
tile_filter_program: TileFilterProgram::new(device, resources, "filter_basic", "blit"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct TileFilterVertexArray<D> where D: Device {
|
||||||
pub vertex_array: D::VertexArray,
|
pub vertex_array: D::VertexArray,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D> FilterBasicVertexArray<D> where D: Device {
|
impl<D> TileFilterVertexArray<D> where D: Device {
|
||||||
pub fn new(
|
pub fn new(device: &D,
|
||||||
device: &D,
|
tile_filter_program: &TileFilterProgram<D>,
|
||||||
fill_basic_program: &FilterBasicProgram<D>,
|
tile_filter_vertex_buffer: &D::Buffer,
|
||||||
quad_vertex_positions_buffer: &D::Buffer,
|
quads_vertex_indices_buffer: &D::Buffer)
|
||||||
quad_vertex_indices_buffer: &D::Buffer,
|
-> TileFilterVertexArray<D> {
|
||||||
) -> FilterBasicVertexArray<D> {
|
|
||||||
let vertex_array = device.create_vertex_array();
|
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);
|
let tile_position_attr =
|
||||||
device.configure_vertex_attr(&vertex_array, &position_attr, &VertexAttrDescriptor {
|
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,
|
size: 2,
|
||||||
class: VertexAttrClass::Int,
|
class: VertexAttrClass::Int,
|
||||||
attr_type: VertexAttrType::I16,
|
attr_type: VertexAttrType::I16,
|
||||||
stride: 4,
|
stride: FILTER_TILE_VERTEX_SIZE,
|
||||||
offset: 0,
|
offset: 0,
|
||||||
divisor: 0,
|
divisor: 0,
|
||||||
buffer_index: 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<D> where D: Device {
|
pub struct TileFilterBlurProgram<D> where D: Device {
|
||||||
pub program: D::Program,
|
pub tile_filter_program: TileFilterProgram<D>,
|
||||||
pub framebuffer_size_uniform: D::Uniform,
|
|
||||||
pub src_uniform: D::Uniform,
|
|
||||||
pub src_offset_scale_uniform: D::Uniform,
|
pub src_offset_scale_uniform: D::Uniform,
|
||||||
pub initial_gauss_coeff_uniform: D::Uniform,
|
pub initial_gauss_coeff_uniform: D::Uniform,
|
||||||
pub support_uniform: D::Uniform,
|
pub support_uniform: D::Uniform,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D> FilterBlurProgram<D> where D: Device {
|
impl<D> TileFilterBlurProgram<D> where D: Device {
|
||||||
pub fn new(device: &D, resources: &dyn ResourceLoader) -> FilterBlurProgram<D> {
|
pub fn new(device: &D, resources: &dyn ResourceLoader) -> TileFilterBlurProgram<D> {
|
||||||
let program = device.create_program_from_shader_names(resources,
|
let tile_filter_program = TileFilterProgram::new(device,
|
||||||
"filter_blur",
|
resources,
|
||||||
"filter",
|
"tile_filter_blur",
|
||||||
"filter_blur");
|
"tile_filter_blur");
|
||||||
let framebuffer_size_uniform = device.get_uniform(&program, "FramebufferSize");
|
let src_offset_scale_uniform = device.get_uniform(&tile_filter_program.program,
|
||||||
let src_uniform = device.get_uniform(&program, "Src");
|
"SrcOffsetScale");
|
||||||
let src_offset_scale_uniform = device.get_uniform(&program, "SrcOffsetScale");
|
let initial_gauss_coeff_uniform = device.get_uniform(&tile_filter_program.program,
|
||||||
let initial_gauss_coeff_uniform = device.get_uniform(&program, "InitialGaussCoeff");
|
"InitialGaussCoeff");
|
||||||
let support_uniform = device.get_uniform(&program, "Support");
|
let support_uniform = device.get_uniform(&tile_filter_program.program, "Support");
|
||||||
FilterBlurProgram {
|
TileFilterBlurProgram {
|
||||||
program,
|
tile_filter_program,
|
||||||
framebuffer_size_uniform,
|
|
||||||
src_uniform,
|
|
||||||
src_offset_scale_uniform,
|
src_offset_scale_uniform,
|
||||||
initial_gauss_coeff_uniform,
|
initial_gauss_coeff_uniform,
|
||||||
support_uniform,
|
support_uniform,
|
||||||
|
@ -603,42 +668,8 @@ impl<D> FilterBlurProgram<D> where D: Device {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct FilterBlurVertexArray<D> where D: Device {
|
pub struct TileFilterTextProgram<D> where D: Device {
|
||||||
pub vertex_array: D::VertexArray,
|
pub tile_filter_program: TileFilterProgram<D>,
|
||||||
}
|
|
||||||
|
|
||||||
impl<D> FilterBlurVertexArray<D> where D: Device {
|
|
||||||
pub fn new(
|
|
||||||
device: &D,
|
|
||||||
fill_blur_program: &FilterBlurProgram<D>,
|
|
||||||
quad_vertex_positions_buffer: &D::Buffer,
|
|
||||||
quad_vertex_indices_buffer: &D::Buffer,
|
|
||||||
) -> FilterBlurVertexArray<D> {
|
|
||||||
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<D> 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 kernel_uniform: D::Uniform,
|
pub kernel_uniform: D::Uniform,
|
||||||
pub gamma_lut_uniform: D::Uniform,
|
pub gamma_lut_uniform: D::Uniform,
|
||||||
pub gamma_correction_enabled_uniform: D::Uniform,
|
pub gamma_correction_enabled_uniform: D::Uniform,
|
||||||
|
@ -646,26 +677,20 @@ pub struct FilterTextProgram<D> where D: Device {
|
||||||
pub bg_color_uniform: D::Uniform,
|
pub bg_color_uniform: D::Uniform,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D> FilterTextProgram<D> where D: Device {
|
impl<D> TileFilterTextProgram<D> where D: Device {
|
||||||
pub fn new(device: &D, resources: &dyn ResourceLoader) -> FilterTextProgram<D> {
|
pub fn new(device: &D, resources: &dyn ResourceLoader) -> TileFilterTextProgram<D> {
|
||||||
let program = device.create_program_from_shader_names(resources,
|
let tile_filter_program = TileFilterProgram::new(device,
|
||||||
"filter_text",
|
resources,
|
||||||
"filter",
|
"tile_filter_text",
|
||||||
"filter_text");
|
"tile_filter_text");
|
||||||
let source_uniform = device.get_uniform(&program, "Source");
|
let kernel_uniform = device.get_uniform(&tile_filter_program.program, "Kernel");
|
||||||
let source_size_uniform = device.get_uniform(&program, "SourceSize");
|
let gamma_lut_uniform = device.get_uniform(&tile_filter_program.program, "GammaLUT");
|
||||||
let framebuffer_size_uniform = device.get_uniform(&program, "FramebufferSize");
|
let gamma_correction_enabled_uniform = device.get_uniform(&tile_filter_program.program,
|
||||||
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,
|
|
||||||
"GammaCorrectionEnabled");
|
"GammaCorrectionEnabled");
|
||||||
let fg_color_uniform = device.get_uniform(&program, "FGColor");
|
let fg_color_uniform = device.get_uniform(&tile_filter_program.program, "FGColor");
|
||||||
let bg_color_uniform = device.get_uniform(&program, "BGColor");
|
let bg_color_uniform = device.get_uniform(&tile_filter_program.program, "BGColor");
|
||||||
FilterTextProgram {
|
TileFilterTextProgram {
|
||||||
program,
|
tile_filter_program,
|
||||||
source_uniform,
|
|
||||||
source_size_uniform,
|
|
||||||
framebuffer_size_uniform,
|
|
||||||
kernel_uniform,
|
kernel_uniform,
|
||||||
gamma_lut_uniform,
|
gamma_lut_uniform,
|
||||||
gamma_correction_enabled_uniform,
|
gamma_correction_enabled_uniform,
|
||||||
|
@ -675,37 +700,6 @@ impl<D> FilterTextProgram<D> where D: Device {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct FilterTextVertexArray<D> where D: Device {
|
|
||||||
pub vertex_array: D::VertexArray,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<D> FilterTextVertexArray<D> where D: Device {
|
|
||||||
pub fn new(
|
|
||||||
device: &D,
|
|
||||||
fill_text_program: &FilterTextProgram<D>,
|
|
||||||
quad_vertex_positions_buffer: &D::Buffer,
|
|
||||||
quad_vertex_indices_buffer: &D::Buffer,
|
|
||||||
) -> FilterTextVertexArray<D> {
|
|
||||||
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<D>
|
pub struct StencilProgram<D>
|
||||||
where
|
where
|
||||||
D: Device,
|
D: Device,
|
||||||
|
|
|
@ -62,12 +62,12 @@ pub enum RenderCommand {
|
||||||
// Draws a batch of solid tiles to the render target on top of the stack.
|
// Draws a batch of solid tiles to the render target on top of the stack.
|
||||||
DrawSolidTiles(SolidTileBatch),
|
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
|
// FIXME(pcwalton): We should get rid of this command and transition all uses to
|
||||||
// of this command and transition all uses to `DrawAlphaTiles`/`DrawSolidTiles`. The reason it
|
// `DrawAlphaTiles`/`DrawSolidTiles`. The reason it exists is that we don't have logic to
|
||||||
// exists is that we don't have logic to create tiles for blur bounding regions yet.
|
// create tiles for blur bounding regions yet.
|
||||||
DrawRenderTarget { render_target: RenderTargetId, effects: Effects },
|
DrawRenderTargetTiles(RenderTargetTileBatch),
|
||||||
|
|
||||||
// Presents a rendered frame.
|
// Presents a rendered frame.
|
||||||
Finish { build_time: Duration },
|
Finish { build_time: Duration },
|
||||||
|
@ -108,6 +108,13 @@ pub struct SolidTileBatch {
|
||||||
pub sampling_flags: TextureSamplingFlags,
|
pub sampling_flags: TextureSamplingFlags,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct RenderTargetTileBatch {
|
||||||
|
pub tiles: Vec<RenderTargetTile>,
|
||||||
|
pub render_target: RenderTargetId,
|
||||||
|
pub effects: Effects,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
pub struct FillObjectPrimitive {
|
pub struct FillObjectPrimitive {
|
||||||
pub px: LineSegmentU4,
|
pub px: LineSegmentU4,
|
||||||
|
@ -162,6 +169,15 @@ pub struct AlphaTile {
|
||||||
pub lower_right: AlphaTileVertex,
|
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)]
|
#[derive(Clone, Copy, Debug, Default)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct MaskTileVertex {
|
pub struct MaskTileVertex {
|
||||||
|
@ -187,6 +203,13 @@ pub struct AlphaTileVertex {
|
||||||
pub pad: u8,
|
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 {
|
impl Debug for RenderCommand {
|
||||||
fn fmt(&self, formatter: &mut Formatter) -> DebugResult {
|
fn fmt(&self, formatter: &mut Formatter) -> DebugResult {
|
||||||
match *self {
|
match *self {
|
||||||
|
@ -203,9 +226,6 @@ impl Debug for RenderCommand {
|
||||||
write!(formatter, "PushRenderTarget({:?})", render_target_id)
|
write!(formatter, "PushRenderTarget({:?})", render_target_id)
|
||||||
}
|
}
|
||||||
RenderCommand::PopRenderTarget => write!(formatter, "PopRenderTarget"),
|
RenderCommand::PopRenderTarget => write!(formatter, "PopRenderTarget"),
|
||||||
RenderCommand::DrawRenderTarget { render_target, .. } => {
|
|
||||||
write!(formatter, "DrawRenderTarget({:?})", render_target)
|
|
||||||
}
|
|
||||||
RenderCommand::DrawAlphaTiles(ref batch) => {
|
RenderCommand::DrawAlphaTiles(ref batch) => {
|
||||||
write!(formatter,
|
write!(formatter,
|
||||||
"DrawAlphaTiles(x{}, {:?}, {:?}, {:?})",
|
"DrawAlphaTiles(x{}, {:?}, {:?}, {:?})",
|
||||||
|
@ -221,6 +241,12 @@ impl Debug for RenderCommand {
|
||||||
batch.paint_page,
|
batch.paint_page,
|
||||||
batch.sampling_flags)
|
batch.sampling_flags)
|
||||||
}
|
}
|
||||||
|
RenderCommand::DrawRenderTargetTiles(ref batch) => {
|
||||||
|
write!(formatter,
|
||||||
|
"DrawRenderTarget(x{}, {:?})",
|
||||||
|
batch.tiles.len(),
|
||||||
|
batch.render_target)
|
||||||
|
}
|
||||||
RenderCommand::Finish { .. } => write!(formatter, "Finish"),
|
RenderCommand::Finish { .. } => write!(formatter, "Finish"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,15 +12,16 @@
|
||||||
|
|
||||||
use crate::builder::SolidTile;
|
use crate::builder::SolidTile;
|
||||||
use crate::gpu_data::{SolidTileBatch, SolidTileVertex};
|
use crate::gpu_data::{SolidTileBatch, SolidTileVertex};
|
||||||
use crate::paint::PaintMetadata;
|
use crate::paint::{PaintId, PaintMetadata};
|
||||||
use crate::scene::DrawPath;
|
|
||||||
use crate::tile_map::DenseTileMap;
|
use crate::tile_map::DenseTileMap;
|
||||||
use crate::tiles;
|
use crate::tiles;
|
||||||
use pathfinder_geometry::rect::RectF;
|
use pathfinder_geometry::rect::RectF;
|
||||||
use pathfinder_geometry::vector::Vector2I;
|
use pathfinder_geometry::vector::Vector2I;
|
||||||
|
use vec_map::VecMap;
|
||||||
|
|
||||||
pub(crate) struct ZBuffer {
|
pub(crate) struct ZBuffer {
|
||||||
buffer: DenseTileMap<u32>,
|
buffer: DenseTileMap<u32>,
|
||||||
|
depth_to_paint_id: VecMap<PaintId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) struct SolidTiles {
|
pub(crate) struct SolidTiles {
|
||||||
|
@ -32,24 +33,25 @@ impl ZBuffer {
|
||||||
let tile_rect = tiles::round_rect_out_to_tile_bounds(view_box);
|
let tile_rect = tiles::round_rect_out_to_tile_bounds(view_box);
|
||||||
ZBuffer {
|
ZBuffer {
|
||||||
buffer: DenseTileMap::from_builder(|_| 0, tile_rect),
|
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);
|
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 {
|
for solid_tile in solid_tiles {
|
||||||
let tile_index = self.buffer.coords_to_index_unchecked(solid_tile.coords);
|
let tile_index = self.buffer.coords_to_index_unchecked(solid_tile.coords);
|
||||||
let z_dest = &mut self.buffer.data[tile_index as usize];
|
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])
|
pub(crate) fn build_solid_tiles(&self, paint_metadata: &[PaintMetadata]) -> SolidTiles {
|
||||||
-> SolidTiles {
|
|
||||||
let mut solid_tiles = SolidTiles { batches: vec![] };
|
let mut solid_tiles = SolidTiles { batches: vec![] };
|
||||||
|
|
||||||
for tile_index in 0..self.buffer.data.len() {
|
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 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 paint_metadata = &paint_metadata[paint_id.0 as usize];
|
||||||
|
|
||||||
let tile_position = tile_coords + self.buffer.rect.origin();
|
let tile_position = tile_coords + self.buffer.rect.origin();
|
||||||
let object_index = object_index as u16;
|
|
||||||
|
|
||||||
// Create a batch if necessary.
|
// Create a batch if necessary.
|
||||||
match solid_tiles.batches.last() {
|
match solid_tiles.batches.last() {
|
||||||
|
@ -83,16 +83,10 @@ impl ZBuffer {
|
||||||
|
|
||||||
let batch = solid_tiles.batches.last_mut().unwrap();
|
let batch = solid_tiles.batches.last_mut().unwrap();
|
||||||
batch.vertices.extend_from_slice(&[
|
batch.vertices.extend_from_slice(&[
|
||||||
SolidTileVertex::new(tile_position, object_index, paint_metadata),
|
SolidTileVertex::new(tile_position, paint_metadata),
|
||||||
SolidTileVertex::new(tile_position + Vector2I::new(1, 0),
|
SolidTileVertex::new(tile_position + Vector2I::new(1, 0), paint_metadata),
|
||||||
object_index,
|
SolidTileVertex::new(tile_position + Vector2I::new(0, 1), paint_metadata),
|
||||||
paint_metadata),
|
SolidTileVertex::new(tile_position + Vector2I::new(1, 1), 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),
|
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,13 +95,12 @@ impl ZBuffer {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SolidTileVertex {
|
impl SolidTileVertex {
|
||||||
fn new(tile_position: Vector2I, object_index: u16, paint_metadata: &PaintMetadata)
|
fn new(tile_position: Vector2I, paint_metadata: &PaintMetadata) -> SolidTileVertex {
|
||||||
-> SolidTileVertex {
|
|
||||||
let color_uv = paint_metadata.calculate_tex_coords(tile_position);
|
let color_uv = paint_metadata.calculate_tex_coords(tile_position);
|
||||||
SolidTileVertex {
|
SolidTileVertex {
|
||||||
tile_x: tile_position.x() as i16,
|
tile_x: tile_position.x() as i16,
|
||||||
tile_y: tile_position.y() as i16,
|
tile_y: tile_position.y() as i16,
|
||||||
object_index: object_index,
|
object_index: 0,
|
||||||
color_u: color_uv.x(),
|
color_u: color_uv.x(),
|
||||||
color_v: color_uv.y(),
|
color_v: color_uv.y(),
|
||||||
pad: 0,
|
pad: 0,
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
// Automatically generated from files in pathfinder/shaders/. Do not edit!
|
||||||
|
#include <metal_stdlib>
|
||||||
|
#include <simd/simd.h>
|
||||||
|
|
||||||
|
using namespace metal;
|
||||||
|
|
||||||
|
struct spvDescriptorSetBuffer0
|
||||||
|
{
|
||||||
|
texture2d<float> 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;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
// Automatically generated from files in pathfinder/shaders/. Do not edit!
|
||||||
|
#include <metal_stdlib>
|
||||||
|
#include <simd/simd.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
// Automatically generated from files in pathfinder/shaders/. Do not edit!
|
||||||
|
#include <metal_stdlib>
|
||||||
|
#include <simd/simd.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
// Automatically generated from files in pathfinder/shaders/. Do not edit!
|
||||||
|
#include <metal_stdlib>
|
||||||
|
#include <simd/simd.h>
|
||||||
|
|
||||||
|
using namespace metal;
|
||||||
|
|
||||||
|
struct spvDescriptorSetBuffer0
|
||||||
|
{
|
||||||
|
constant float3* uInitialGaussCoeff [[id(0)]];
|
||||||
|
texture2d<float> 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;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,130 @@
|
||||||
|
// Automatically generated from files in pathfinder/shaders/. Do not edit!
|
||||||
|
#pragma clang diagnostic ignored "-Wmissing-prototypes"
|
||||||
|
|
||||||
|
#include <metal_stdlib>
|
||||||
|
#include <simd/simd.h>
|
||||||
|
|
||||||
|
using namespace metal;
|
||||||
|
|
||||||
|
struct spvDescriptorSetBuffer0
|
||||||
|
{
|
||||||
|
texture2d<float> uGammaLUT [[id(0)]];
|
||||||
|
sampler uGammaLUTSmplr [[id(1)]];
|
||||||
|
constant float4* uKernel [[id(2)]];
|
||||||
|
texture2d<float> 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<float> 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<float> 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<float> 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<float> 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;
|
||||||
|
}
|
||||||
|
|
|
@ -3,6 +3,8 @@ TARGET_DIR?=../resources/shaders
|
||||||
EMPTY=
|
EMPTY=
|
||||||
|
|
||||||
SHADERS=\
|
SHADERS=\
|
||||||
|
blit.fs.glsl \
|
||||||
|
blit.vs.glsl \
|
||||||
debug_solid.fs.glsl \
|
debug_solid.fs.glsl \
|
||||||
debug_solid.vs.glsl \
|
debug_solid.vs.glsl \
|
||||||
debug_texture.fs.glsl \
|
debug_texture.fs.glsl \
|
||||||
|
@ -11,10 +13,6 @@ SHADERS=\
|
||||||
demo_ground.vs.glsl \
|
demo_ground.vs.glsl \
|
||||||
fill.fs.glsl \
|
fill.fs.glsl \
|
||||||
fill.vs.glsl \
|
fill.vs.glsl \
|
||||||
filter.vs.glsl \
|
|
||||||
filter_basic.fs.glsl \
|
|
||||||
filter_blur.fs.glsl \
|
|
||||||
filter_text.fs.glsl \
|
|
||||||
mask.vs.glsl \
|
mask.vs.glsl \
|
||||||
mask_evenodd.fs.glsl \
|
mask_evenodd.fs.glsl \
|
||||||
mask_winding.fs.glsl \
|
mask_winding.fs.glsl \
|
||||||
|
@ -32,14 +30,17 @@ SHADERS=\
|
||||||
tile_alpha_softlight.fs.glsl \
|
tile_alpha_softlight.fs.glsl \
|
||||||
tile_copy.fs.glsl \
|
tile_copy.fs.glsl \
|
||||||
tile_copy.vs.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.fs.glsl \
|
||||||
tile_solid.vs.glsl \
|
tile_solid.vs.glsl \
|
||||||
$(EMPTY)
|
$(EMPTY)
|
||||||
|
|
||||||
INCLUDES=\
|
INCLUDES=\
|
||||||
filter_text_convolve.inc.glsl \
|
|
||||||
filter_text_gamma_correct.inc.glsl \
|
|
||||||
tile_alpha_sample.inc.glsl \
|
tile_alpha_sample.inc.glsl \
|
||||||
|
tile_filter_text_convolve.inc.glsl \
|
||||||
|
tile_filter_text_gamma_correct.inc.glsl \
|
||||||
$(EMPTY)
|
$(EMPTY)
|
||||||
|
|
||||||
OUT=\
|
OUT=\
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#version 330
|
#version 330
|
||||||
|
|
||||||
// pathfinder/shaders/filter_basic.fs.glsl
|
// pathfinder/shaders/blit.fs.glsl
|
||||||
//
|
//
|
||||||
// Copyright © 2020 The Pathfinder Project Developers.
|
// Copyright © 2020 The Pathfinder Project Developers.
|
||||||
//
|
//
|
||||||
|
@ -10,20 +10,15 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// 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;
|
precision highp float;
|
||||||
|
|
||||||
uniform sampler2D uSource;
|
uniform sampler2D uSrc;
|
||||||
|
|
||||||
in vec2 vTexCoord;
|
in vec2 vTexCoord;
|
||||||
|
|
||||||
out vec4 oFragColor;
|
out vec4 oFragColor;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
vec4 color = texture(uSource, vTexCoord);
|
vec4 color = texture(uSrc, vTexCoord);
|
||||||
oFragColor = vec4(color.rgb * color.a, color.a);
|
oFragColor = vec4(color.rgb * color.a, color.a);
|
||||||
}
|
}
|
|
@ -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 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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);
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
#version 330
|
#version 330
|
||||||
|
|
||||||
// pathfinder/shaders/filter.vs.glsl
|
// pathfinder/shaders/tile_filter.vs.glsl
|
||||||
//
|
//
|
||||||
// Copyright © 2020 The Pathfinder Project Developers.
|
// Copyright © 2020 The Pathfinder Project Developers.
|
||||||
//
|
//
|
||||||
|
@ -12,17 +12,17 @@
|
||||||
|
|
||||||
precision highp float;
|
precision highp float;
|
||||||
|
|
||||||
in ivec2 aPosition;
|
uniform mat4 uTransform;
|
||||||
|
uniform vec2 uTileSize;
|
||||||
|
uniform vec2 uSrcSize;
|
||||||
|
|
||||||
|
in ivec2 aTilePosition;
|
||||||
|
|
||||||
out vec2 vTexCoord;
|
out vec2 vTexCoord;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
vec2 position = vec2(aPosition);
|
vec2 position = vec2(aTilePosition) * uTileSize;
|
||||||
vTexCoord = position;
|
|
||||||
|
|
||||||
#ifdef PF_ORIGIN_UPPER_LEFT
|
vTexCoord = position / uSrcSize;
|
||||||
// FIXME(pcwalton): This is wrong.
|
gl_Position = uTransform * vec4(position, 0.0, 1.0);
|
||||||
position.y = 1.0 - position.y;
|
|
||||||
#endif
|
|
||||||
gl_Position = vec4(vec2(position) * 2.0 - 1.0, 0.0, 1.0);
|
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
#version 330
|
#version 330
|
||||||
|
|
||||||
// pathfinder/shaders/filter_text.fs.glsl
|
// pathfinder/shaders/tile_filter_text.fs.glsl
|
||||||
//
|
//
|
||||||
// Copyright © 2019 The Pathfinder Project Developers.
|
// Copyright © 2019 The Pathfinder Project Developers.
|
||||||
//
|
//
|
||||||
|
@ -10,15 +10,12 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// 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
|
#extension GL_GOOGLE_include_directive : enable
|
||||||
|
|
||||||
precision highp float;
|
precision highp float;
|
||||||
|
|
||||||
uniform sampler2D uSource;
|
uniform sampler2D uSrc;
|
||||||
uniform vec2 uSourceSize;
|
uniform vec2 uSrcSize;
|
||||||
uniform vec4 uFGColor;
|
uniform vec4 uFGColor;
|
||||||
uniform vec4 uBGColor;
|
uniform vec4 uBGColor;
|
||||||
uniform int uGammaCorrectionEnabled;
|
uniform int uGammaCorrectionEnabled;
|
||||||
|
@ -27,23 +24,23 @@ in vec2 vTexCoord;
|
||||||
|
|
||||||
out vec4 oFragColor;
|
out vec4 oFragColor;
|
||||||
|
|
||||||
#include "filter_text_gamma_correct.inc.glsl"
|
#include "tile_filter_text_gamma_correct.inc.glsl"
|
||||||
#include "filter_text_convolve.inc.glsl"
|
#include "tile_filter_text_convolve.inc.glsl"
|
||||||
|
|
||||||
// Convolve horizontally in this pass.
|
// Convolve horizontally in this pass.
|
||||||
float sample1Tap(float offset) {
|
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() {
|
void main() {
|
||||||
// Apply defringing if necessary.
|
// Apply defringing if necessary.
|
||||||
vec3 alpha;
|
vec3 alpha;
|
||||||
if (uKernel.w == 0.0) {
|
if (uKernel.w == 0.0) {
|
||||||
alpha = texture(uSource, vTexCoord).rrr;
|
alpha = texture(uSrc, vTexCoord).rrr;
|
||||||
} else {
|
} else {
|
||||||
vec4 alphaLeft, alphaRight;
|
vec4 alphaLeft, alphaRight;
|
||||||
float alphaCenter;
|
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 r = convolve7Tap(alphaLeft, vec3(alphaCenter, alphaRight.xy));
|
||||||
float g = convolve7Tap(vec4(alphaLeft.yzw, alphaCenter), alphaRight.xyz);
|
float g = convolve7Tap(vec4(alphaLeft.yzw, alphaCenter), alphaRight.xyz);
|
|
@ -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 <LICENSE-APACHE or
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
Loading…
Reference in New Issue