Add a separate mask blit step, in preparation for supporting clips.
We can elide this in the future if there are no clips, but it isn't a huge performance regression right now, so let's just unconditionally do it.
This commit is contained in:
parent
6a73a63336
commit
0883f54e2d
|
@ -11,7 +11,7 @@
|
|||
//! Packs data onto the GPU.
|
||||
|
||||
use crate::concurrent::executor::Executor;
|
||||
use crate::gpu_data::{AlphaTile, FillBatchPrimitive, RenderCommand, TileObjectPrimitive};
|
||||
use crate::gpu_data::{AlphaTile, FillBatchPrimitive, MaskTile, RenderCommand, TileObjectPrimitive};
|
||||
use crate::options::{PreparedBuildOptions, RenderCommandListener};
|
||||
use crate::paint::{PaintInfo, PaintMetadata};
|
||||
use crate::scene::Scene;
|
||||
|
@ -106,9 +106,11 @@ impl<'a> SceneBuilder<'a> {
|
|||
}
|
||||
|
||||
fn cull_tiles(&self, built_objects: Vec<BuiltObject>) -> CulledTiles {
|
||||
let mut culled_tiles = CulledTiles { alpha_tiles: vec![] };
|
||||
let mut culled_tiles = CulledTiles { mask_tiles: vec![], alpha_tiles: vec![] };
|
||||
|
||||
for built_object in built_objects {
|
||||
culled_tiles.mask_tiles.extend_from_slice(&built_object.mask_tiles);
|
||||
|
||||
for alpha_tile in built_object.alpha_tiles {
|
||||
let alpha_tile_coords = alpha_tile.upper_left.tile_position();
|
||||
if self.z_buffer.test(alpha_tile_coords,
|
||||
|
@ -126,6 +128,9 @@ impl<'a> SceneBuilder<'a> {
|
|||
let solid_tiles = self.z_buffer.build_solid_tiles(&self.scene.paths,
|
||||
paint_metadata,
|
||||
0..path_count);
|
||||
if !culled_tiles.mask_tiles.is_empty() {
|
||||
self.listener.send(RenderCommand::RenderMaskTiles(culled_tiles.mask_tiles));
|
||||
}
|
||||
if !solid_tiles.is_empty() {
|
||||
self.listener.send(RenderCommand::DrawSolidTiles(solid_tiles));
|
||||
}
|
||||
|
@ -143,6 +148,11 @@ impl<'a> SceneBuilder<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
struct CulledTiles {
|
||||
mask_tiles: Vec<MaskTile>,
|
||||
alpha_tiles: Vec<AlphaTile>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default)]
|
||||
pub struct TileStats {
|
||||
pub solid_tile_count: u32,
|
||||
|
@ -156,7 +166,7 @@ impl ObjectBuilder {
|
|||
let tile_rect = tiles::round_rect_out_to_tile_bounds(bounds);
|
||||
let tiles = DenseTileMap::new(tile_rect);
|
||||
ObjectBuilder {
|
||||
built_object: BuiltObject { alpha_tiles: vec![] },
|
||||
built_object: BuiltObject { mask_tiles: vec![], alpha_tiles: vec![] },
|
||||
bounds,
|
||||
fills: vec![],
|
||||
tiles,
|
||||
|
@ -341,6 +351,7 @@ impl ObjectBuilder {
|
|||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct BuiltObject {
|
||||
pub mask_tiles: Vec<MaskTile>,
|
||||
pub alpha_tiles: Vec<AlphaTile>,
|
||||
}
|
||||
|
||||
|
@ -351,7 +362,3 @@ pub(crate) struct ObjectBuilder {
|
|||
pub tiles: DenseTileMap<TileObjectPrimitive>,
|
||||
pub bounds: RectF,
|
||||
}
|
||||
|
||||
struct CulledTiles {
|
||||
alpha_tiles: Vec<AlphaTile>,
|
||||
}
|
||||
|
|
|
@ -11,10 +11,12 @@
|
|||
use crate::gpu::debug::DebugUIPresenter;
|
||||
use crate::gpu::options::{DestFramebuffer, RendererOptions};
|
||||
use crate::gpu::shaders::{FillProgram, AlphaTileProgram, AlphaTileVertexArray, FillVertexArray};
|
||||
use crate::gpu::shaders::{MAX_FILLS_PER_BATCH, PostprocessProgram, PostprocessVertexArray};
|
||||
use crate::gpu::shaders::{ReprojectionProgram, ReprojectionVertexArray, SolidTileProgram};
|
||||
use crate::gpu::shaders::{SolidTileVertexArray, StencilProgram, StencilVertexArray};
|
||||
use crate::gpu_data::{AlphaTile, FillBatchPrimitive, PaintData, RenderCommand, SolidTileVertex};
|
||||
use crate::gpu::shaders::{MAX_FILLS_PER_BATCH, MaskWindingTileProgram, MaskWindingTileVertexArray};
|
||||
use crate::gpu::shaders::{PostprocessProgram, PostprocessVertexArray, ReprojectionProgram};
|
||||
use crate::gpu::shaders::{ReprojectionVertexArray, SolidTileProgram, SolidTileVertexArray};
|
||||
use crate::gpu::shaders::{StencilProgram, StencilVertexArray};
|
||||
use crate::gpu_data::{AlphaTile, FillBatchPrimitive, MaskTile, PaintData};
|
||||
use crate::gpu_data::{RenderCommand, SolidTileVertex};
|
||||
use crate::post::DefringingKernel;
|
||||
use crate::tiles::{TILE_HEIGHT, TILE_WIDTH};
|
||||
use pathfinder_color::{self as color, ColorF, ColorU};
|
||||
|
@ -55,8 +57,10 @@ where
|
|||
dest_framebuffer: DestFramebuffer<D>,
|
||||
options: RendererOptions,
|
||||
fill_program: FillProgram<D>,
|
||||
mask_winding_tile_program: MaskWindingTileProgram<D>,
|
||||
solid_tile_program: SolidTileProgram<D>,
|
||||
alpha_tile_program: AlphaTileProgram<D>,
|
||||
mask_winding_tile_vertex_array: MaskWindingTileVertexArray<D>,
|
||||
solid_tile_vertex_array: SolidTileVertexArray<D>,
|
||||
alpha_tile_vertex_array: AlphaTileVertexArray<D>,
|
||||
area_lut_texture: D::Texture,
|
||||
|
@ -65,6 +69,7 @@ where
|
|||
quads_vertex_indices_buffer: D::Buffer,
|
||||
quads_vertex_indices_length: usize,
|
||||
fill_vertex_array: FillVertexArray<D>,
|
||||
fill_framebuffer: D::Framebuffer,
|
||||
mask_framebuffer: D::Framebuffer,
|
||||
paint_texture: Option<D::Texture>,
|
||||
|
||||
|
@ -108,10 +113,9 @@ where
|
|||
options: RendererOptions)
|
||||
-> Renderer<D> {
|
||||
let fill_program = FillProgram::new(&device, resources);
|
||||
|
||||
let mask_winding_tile_program = MaskWindingTileProgram::new(&device, resources);
|
||||
let solid_tile_program = SolidTileProgram::new(&device, resources);
|
||||
let alpha_tile_program = AlphaTileProgram::new(&device, resources);
|
||||
|
||||
let postprocess_program = PostprocessProgram::new(&device, resources);
|
||||
let stencil_program = StencilProgram::new(&device, resources);
|
||||
let reprojection_program = ReprojectionProgram::new(&device, resources);
|
||||
|
@ -141,6 +145,11 @@ where
|
|||
&quad_vertex_positions_buffer,
|
||||
&quad_vertex_indices_buffer,
|
||||
);
|
||||
let mask_winding_tile_vertex_array = MaskWindingTileVertexArray::new(
|
||||
&device,
|
||||
&mask_winding_tile_program,
|
||||
&quads_vertex_indices_buffer,
|
||||
);
|
||||
let alpha_tile_vertex_array = AlphaTileVertexArray::new(
|
||||
&device,
|
||||
&alpha_tile_program,
|
||||
|
@ -165,10 +174,16 @@ where
|
|||
&quad_vertex_indices_buffer,
|
||||
);
|
||||
|
||||
let fill_framebuffer_size =
|
||||
Vector2I::new(MASK_FRAMEBUFFER_WIDTH, MASK_FRAMEBUFFER_HEIGHT);
|
||||
let fill_framebuffer_texture =
|
||||
device.create_texture(TextureFormat::R16F, fill_framebuffer_size);
|
||||
let fill_framebuffer = device.create_framebuffer(fill_framebuffer_texture);
|
||||
|
||||
let mask_framebuffer_size =
|
||||
Vector2I::new(MASK_FRAMEBUFFER_WIDTH, MASK_FRAMEBUFFER_HEIGHT);
|
||||
let mask_framebuffer_texture =
|
||||
device.create_texture(TextureFormat::R16F, mask_framebuffer_size);
|
||||
device.create_texture(TextureFormat::R8, mask_framebuffer_size);
|
||||
let mask_framebuffer = device.create_framebuffer(mask_framebuffer_texture);
|
||||
|
||||
let window_size = dest_framebuffer.window_size(&device);
|
||||
|
@ -180,8 +195,10 @@ where
|
|||
dest_framebuffer,
|
||||
options,
|
||||
fill_program,
|
||||
mask_winding_tile_program,
|
||||
solid_tile_program,
|
||||
alpha_tile_program,
|
||||
mask_winding_tile_vertex_array,
|
||||
solid_tile_vertex_array,
|
||||
alpha_tile_vertex_array,
|
||||
area_lut_texture,
|
||||
|
@ -190,6 +207,7 @@ where
|
|||
quads_vertex_indices_buffer,
|
||||
quads_vertex_indices_length: 0,
|
||||
fill_vertex_array,
|
||||
fill_framebuffer,
|
||||
mask_framebuffer,
|
||||
paint_texture: None,
|
||||
|
||||
|
@ -239,6 +257,11 @@ where
|
|||
self.draw_buffered_fills();
|
||||
self.begin_composite_timer_query();
|
||||
}
|
||||
RenderCommand::RenderMaskTiles(ref mask_tiles) => {
|
||||
let count = mask_tiles.len();
|
||||
self.upload_mask_tiles(mask_tiles);
|
||||
self.draw_mask_tiles(count as u32);
|
||||
}
|
||||
RenderCommand::DrawSolidTiles(ref solid_tile_vertices) => {
|
||||
let count = solid_tile_vertices.len() / 4;
|
||||
self.stats.solid_tile_count += count;
|
||||
|
@ -374,6 +397,16 @@ where
|
|||
TextureDataRef::U8(texels));
|
||||
}
|
||||
|
||||
fn upload_mask_tiles(&mut self, mask_tiles: &[MaskTile]) {
|
||||
self.device.allocate_buffer(
|
||||
&self.mask_winding_tile_vertex_array.vertex_buffer,
|
||||
BufferData::Memory(&mask_tiles),
|
||||
BufferTarget::Vertex,
|
||||
BufferUploadMode::Dynamic,
|
||||
);
|
||||
self.ensure_index_buffer(mask_tiles.len());
|
||||
}
|
||||
|
||||
fn upload_solid_tiles(&mut self, solid_tile_vertices: &[SolidTileVertex]) {
|
||||
self.device.allocate_buffer(
|
||||
&self.solid_tile_vertex_array.vertex_buffer,
|
||||
|
@ -450,7 +483,7 @@ where
|
|||
|
||||
let mut clear_color = None;
|
||||
if !self.framebuffer_flags.contains(
|
||||
FramebufferFlags::MUST_PRESERVE_MASK_FRAMEBUFFER_CONTENTS) {
|
||||
FramebufferFlags::MUST_PRESERVE_FILL_FRAMEBUFFER_CONTENTS) {
|
||||
clear_color = Some(ColorF::default());
|
||||
};
|
||||
|
||||
|
@ -459,7 +492,7 @@ where
|
|||
|
||||
debug_assert!(self.buffered_fills.len() <= u32::MAX as usize);
|
||||
self.device.draw_elements_instanced(6, self.buffered_fills.len() as u32, &RenderState {
|
||||
target: &RenderTarget::Framebuffer(&self.mask_framebuffer),
|
||||
target: &RenderTarget::Framebuffer(&self.fill_framebuffer),
|
||||
program: &self.fill_program.program,
|
||||
vertex_array: &self.fill_vertex_array.vertex_array,
|
||||
primitive: Primitive::Triangles,
|
||||
|
@ -486,7 +519,7 @@ where
|
|||
self.device.end_timer_query(&timer_query);
|
||||
self.current_timers.stage_0.push(timer_query);
|
||||
|
||||
self.framebuffer_flags.insert(FramebufferFlags::MUST_PRESERVE_MASK_FRAMEBUFFER_CONTENTS);
|
||||
self.framebuffer_flags.insert(FramebufferFlags::MUST_PRESERVE_FILL_FRAMEBUFFER_CONTENTS);
|
||||
self.buffered_fills.clear();
|
||||
}
|
||||
|
||||
|
@ -496,6 +529,38 @@ where
|
|||
Transform4F::from_scale(scale).translate(Vector4F::new(-1.0, 1.0, 0.0, 1.0))
|
||||
}
|
||||
|
||||
fn draw_mask_tiles(&mut self, tile_count: u32) {
|
||||
let clear_color =
|
||||
if self.framebuffer_flags
|
||||
.contains(FramebufferFlags::MUST_PRESERVE_MASK_FRAMEBUFFER_CONTENTS) {
|
||||
None
|
||||
} else {
|
||||
Some(ColorF::new(1.0, 1.0, 1.0, 1.0))
|
||||
};
|
||||
|
||||
let textures = vec![self.device.framebuffer_texture(&self.fill_framebuffer)];
|
||||
let uniforms = vec![
|
||||
(&self.mask_winding_tile_program.mask_texture_uniform, UniformData::TextureUnit(0)),
|
||||
];
|
||||
|
||||
self.device.draw_elements(tile_count * 6, &RenderState {
|
||||
target: &RenderTarget::Framebuffer(&self.mask_framebuffer),
|
||||
program: &self.mask_winding_tile_program.program,
|
||||
vertex_array: &self.mask_winding_tile_vertex_array.vertex_array,
|
||||
primitive: Primitive::Triangles,
|
||||
textures: &textures,
|
||||
uniforms: &uniforms,
|
||||
viewport: self.mask_viewport(),
|
||||
options: RenderOptions {
|
||||
// TODO(pcwalton): MIN blending for masks.
|
||||
clear_ops: ClearOps { color: clear_color, ..ClearOps::default() },
|
||||
..RenderOptions::default()
|
||||
},
|
||||
});
|
||||
|
||||
self.framebuffer_flags.insert(FramebufferFlags::MUST_PRESERVE_MASK_FRAMEBUFFER_CONTENTS);
|
||||
}
|
||||
|
||||
fn draw_alpha_tiles(&mut self, tile_count: u32) {
|
||||
let clear_color = self.clear_color_for_draw_operation();
|
||||
|
||||
|
@ -937,8 +1002,9 @@ impl Add<RenderTime> for RenderTime {
|
|||
|
||||
bitflags! {
|
||||
struct FramebufferFlags: u8 {
|
||||
const MUST_PRESERVE_MASK_FRAMEBUFFER_CONTENTS = 0x01;
|
||||
const MUST_PRESERVE_POSTPROCESS_FRAMEBUFFER_CONTENTS = 0x02;
|
||||
const MUST_PRESERVE_DEST_FRAMEBUFFER_CONTENTS = 0x04;
|
||||
const MUST_PRESERVE_FILL_FRAMEBUFFER_CONTENTS = 0x01;
|
||||
const MUST_PRESERVE_MASK_FRAMEBUFFER_CONTENTS = 0x02;
|
||||
const MUST_PRESERVE_POSTPROCESS_FRAMEBUFFER_CONTENTS = 0x04;
|
||||
const MUST_PRESERVE_DEST_FRAMEBUFFER_CONTENTS = 0x08;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,13 +9,15 @@
|
|||
// except according to those terms.
|
||||
|
||||
use crate::gpu_data::FillBatchPrimitive;
|
||||
use pathfinder_gpu::{BufferData, BufferTarget, BufferUploadMode, Device, VertexAttrClass, VertexAttrDescriptor, VertexAttrType};
|
||||
use pathfinder_gpu::{BufferData, BufferTarget, BufferUploadMode, Device, VertexAttrClass};
|
||||
use pathfinder_gpu::{VertexAttrDescriptor, VertexAttrType};
|
||||
use pathfinder_gpu::resources::ResourceLoader;
|
||||
|
||||
// TODO(pcwalton): Replace with `mem::size_of` calls?
|
||||
const FILL_INSTANCE_SIZE: usize = 8;
|
||||
const SOLID_TILE_VERTEX_SIZE: usize = 12;
|
||||
const MASK_TILE_VERTEX_SIZE: usize = 16;
|
||||
const ALPHA_TILE_VERTEX_SIZE: usize = 16;
|
||||
const MASK_TILE_VERTEX_SIZE: usize = 12;
|
||||
|
||||
pub const MAX_FILLS_PER_BATCH: usize = 0x4000;
|
||||
|
||||
|
@ -118,39 +120,30 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
pub struct AlphaTileVertexArray<D>
|
||||
where
|
||||
D: Device,
|
||||
{
|
||||
pub struct MaskWindingTileVertexArray<D> where D: Device {
|
||||
pub vertex_array: D::VertexArray,
|
||||
pub vertex_buffer: D::Buffer,
|
||||
}
|
||||
|
||||
impl<D> AlphaTileVertexArray<D>
|
||||
where
|
||||
D: Device,
|
||||
{
|
||||
pub fn new(
|
||||
device: &D,
|
||||
alpha_tile_program: &AlphaTileProgram<D>,
|
||||
quads_vertex_indices_buffer: &D::Buffer,
|
||||
) -> AlphaTileVertexArray<D> {
|
||||
impl<D> MaskWindingTileVertexArray<D> where D: Device {
|
||||
pub fn new(device: &D,
|
||||
mask_winding_tile_program: &MaskWindingTileProgram<D>,
|
||||
quads_vertex_indices_buffer: &D::Buffer)
|
||||
-> MaskWindingTileVertexArray<D> {
|
||||
let (vertex_array, vertex_buffer) = (device.create_vertex_array(), device.create_buffer());
|
||||
|
||||
let tile_position_attr =
|
||||
device.get_vertex_attr(&alpha_tile_program.program, "TilePosition").unwrap();
|
||||
let color_tex_coord_attr = device.get_vertex_attr(&alpha_tile_program.program,
|
||||
"ColorTexCoord").unwrap();
|
||||
let mask_tex_coord_attr = device.get_vertex_attr(&alpha_tile_program.program,
|
||||
let position_attr = device.get_vertex_attr(&mask_winding_tile_program.program, "Position")
|
||||
.unwrap();
|
||||
let mask_tex_coord_attr = device.get_vertex_attr(&mask_winding_tile_program.program,
|
||||
"MaskTexCoord").unwrap();
|
||||
let backdrop_attr = device.get_vertex_attr(&alpha_tile_program.program, "Backdrop")
|
||||
let backdrop_attr = device.get_vertex_attr(&mask_winding_tile_program.program, "Backdrop")
|
||||
.unwrap();
|
||||
|
||||
device.bind_buffer(&vertex_array, &vertex_buffer, BufferTarget::Vertex);
|
||||
device.configure_vertex_attr(&vertex_array, &tile_position_attr, &VertexAttrDescriptor {
|
||||
device.configure_vertex_attr(&vertex_array, &position_attr, &VertexAttrDescriptor {
|
||||
size: 2,
|
||||
class: VertexAttrClass::Int,
|
||||
attr_type: VertexAttrType::I16,
|
||||
class: VertexAttrClass::FloatNorm,
|
||||
attr_type: VertexAttrType::U16,
|
||||
stride: MASK_TILE_VERTEX_SIZE,
|
||||
offset: 0,
|
||||
divisor: 0,
|
||||
|
@ -165,21 +158,66 @@ where
|
|||
divisor: 0,
|
||||
buffer_index: 0,
|
||||
});
|
||||
device.configure_vertex_attr(&vertex_array, &color_tex_coord_attr, &VertexAttrDescriptor {
|
||||
size: 2,
|
||||
class: VertexAttrClass::FloatNorm,
|
||||
attr_type: VertexAttrType::U16,
|
||||
stride: MASK_TILE_VERTEX_SIZE,
|
||||
offset: 8,
|
||||
divisor: 0,
|
||||
buffer_index: 0,
|
||||
});
|
||||
device.configure_vertex_attr(&vertex_array, &backdrop_attr, &VertexAttrDescriptor {
|
||||
size: 1,
|
||||
class: VertexAttrClass::Int,
|
||||
attr_type: VertexAttrType::I16,
|
||||
stride: MASK_TILE_VERTEX_SIZE,
|
||||
offset: 12,
|
||||
offset: 8,
|
||||
divisor: 0,
|
||||
buffer_index: 0,
|
||||
});
|
||||
device.bind_buffer(&vertex_array, quads_vertex_indices_buffer, BufferTarget::Index);
|
||||
|
||||
MaskWindingTileVertexArray { vertex_array, vertex_buffer }
|
||||
}
|
||||
}
|
||||
|
||||
pub struct AlphaTileVertexArray<D> where D: Device {
|
||||
pub vertex_array: D::VertexArray,
|
||||
pub vertex_buffer: D::Buffer,
|
||||
}
|
||||
|
||||
impl<D> AlphaTileVertexArray<D> where D: Device {
|
||||
pub fn new(
|
||||
device: &D,
|
||||
alpha_tile_program: &AlphaTileProgram<D>,
|
||||
quads_vertex_indices_buffer: &D::Buffer,
|
||||
) -> AlphaTileVertexArray<D> {
|
||||
let (vertex_array, vertex_buffer) = (device.create_vertex_array(), device.create_buffer());
|
||||
|
||||
let tile_position_attr =
|
||||
device.get_vertex_attr(&alpha_tile_program.program, "TilePosition").unwrap();
|
||||
let color_tex_coord_attr = device.get_vertex_attr(&alpha_tile_program.program,
|
||||
"ColorTexCoord").unwrap();
|
||||
let mask_tex_coord_attr = device.get_vertex_attr(&alpha_tile_program.program,
|
||||
"MaskTexCoord").unwrap();
|
||||
|
||||
device.bind_buffer(&vertex_array, &vertex_buffer, BufferTarget::Vertex);
|
||||
device.configure_vertex_attr(&vertex_array, &tile_position_attr, &VertexAttrDescriptor {
|
||||
size: 2,
|
||||
class: VertexAttrClass::Int,
|
||||
attr_type: VertexAttrType::I16,
|
||||
stride: ALPHA_TILE_VERTEX_SIZE,
|
||||
offset: 0,
|
||||
divisor: 0,
|
||||
buffer_index: 0,
|
||||
});
|
||||
device.configure_vertex_attr(&vertex_array, &mask_tex_coord_attr, &VertexAttrDescriptor {
|
||||
size: 2,
|
||||
class: VertexAttrClass::FloatNorm,
|
||||
attr_type: VertexAttrType::U16,
|
||||
stride: ALPHA_TILE_VERTEX_SIZE,
|
||||
offset: 4,
|
||||
divisor: 0,
|
||||
buffer_index: 0,
|
||||
});
|
||||
device.configure_vertex_attr(&vertex_array, &color_tex_coord_attr, &VertexAttrDescriptor {
|
||||
size: 2,
|
||||
class: VertexAttrClass::FloatNorm,
|
||||
attr_type: VertexAttrType::U16,
|
||||
stride: ALPHA_TILE_VERTEX_SIZE,
|
||||
offset: 8,
|
||||
divisor: 0,
|
||||
buffer_index: 0,
|
||||
});
|
||||
|
@ -270,6 +308,19 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
pub struct MaskWindingTileProgram<D> where D: Device {
|
||||
pub program: D::Program,
|
||||
pub mask_texture_uniform: D::Uniform,
|
||||
}
|
||||
|
||||
impl<D> MaskWindingTileProgram<D> where D: Device {
|
||||
pub fn new(device: &D, resources: &dyn ResourceLoader) -> MaskWindingTileProgram<D> {
|
||||
let program = device.create_program(resources, "mask_winding");
|
||||
let mask_texture_uniform = device.get_uniform(&program, "MaskTexture");
|
||||
MaskWindingTileProgram { program, mask_texture_uniform }
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SolidTileProgram<D> where D: Device {
|
||||
pub program: D::Program,
|
||||
pub transform_uniform: D::Uniform,
|
||||
|
|
|
@ -22,6 +22,7 @@ pub enum RenderCommand {
|
|||
AddPaintData(PaintData),
|
||||
AddFills(Vec<FillBatchPrimitive>),
|
||||
FlushFills,
|
||||
RenderMaskTiles(Vec<MaskTile>),
|
||||
DrawAlphaTiles(Vec<AlphaTile>),
|
||||
DrawSolidTiles(Vec<SolidTileVertex>),
|
||||
Finish { build_time: Duration },
|
||||
|
@ -69,6 +70,15 @@ pub struct SolidTileVertex {
|
|||
pub pad: u16,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default)]
|
||||
#[repr(C)]
|
||||
pub struct MaskTile {
|
||||
pub upper_left: MaskTileVertex,
|
||||
pub upper_right: MaskTileVertex,
|
||||
pub lower_left: MaskTileVertex,
|
||||
pub lower_right: MaskTileVertex,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default)]
|
||||
#[repr(C)]
|
||||
pub struct AlphaTile {
|
||||
|
@ -78,6 +88,17 @@ pub struct AlphaTile {
|
|||
pub lower_right: AlphaTileVertex,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default)]
|
||||
#[repr(C)]
|
||||
pub struct MaskTileVertex {
|
||||
pub tile_x: u16,
|
||||
pub tile_y: u16,
|
||||
pub mask_u: u16,
|
||||
pub mask_v: u16,
|
||||
pub backdrop: i16,
|
||||
pub object_index: u16,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default)]
|
||||
#[repr(C)]
|
||||
pub struct AlphaTileVertex {
|
||||
|
@ -87,8 +108,8 @@ pub struct AlphaTileVertex {
|
|||
pub mask_v: u16,
|
||||
pub color_u: u16,
|
||||
pub color_v: u16,
|
||||
pub backdrop: i16,
|
||||
pub object_index: u16,
|
||||
pub pad: u16,
|
||||
}
|
||||
|
||||
impl Debug for RenderCommand {
|
||||
|
@ -100,6 +121,9 @@ impl Debug for RenderCommand {
|
|||
}
|
||||
RenderCommand::AddFills(ref fills) => write!(formatter, "AddFills(x{})", fills.len()),
|
||||
RenderCommand::FlushFills => write!(formatter, "FlushFills"),
|
||||
RenderCommand::RenderMaskTiles(ref tiles) => {
|
||||
write!(formatter, "RenderMaskTiles(x{})", tiles.len())
|
||||
}
|
||||
RenderCommand::DrawAlphaTiles(ref tiles) => {
|
||||
write!(formatter, "DrawAlphaTiles(x{})", tiles.len())
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
use crate::builder::{ObjectBuilder, SceneBuilder};
|
||||
use crate::gpu::renderer::MASK_TILES_ACROSS;
|
||||
use crate::gpu_data::{AlphaTile, AlphaTileVertex, TileObjectPrimitive};
|
||||
use crate::gpu_data::{AlphaTile, AlphaTileVertex, MaskTile, MaskTileVertex, TileObjectPrimitive};
|
||||
use crate::paint::PaintMetadata;
|
||||
use pathfinder_content::outline::{Contour, Outline, PointIndex};
|
||||
use pathfinder_content::segment::Segment;
|
||||
|
@ -124,30 +124,45 @@ impl<'a> Tiler<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
self.object_builder.built_object.mask_tiles.push(MaskTile {
|
||||
upper_left: MaskTileVertex::new(tile.alpha_tile_index as u16,
|
||||
Vector2I::default(),
|
||||
self.object_index,
|
||||
tile.backdrop as i16),
|
||||
upper_right: MaskTileVertex::new(tile.alpha_tile_index as u16,
|
||||
Vector2I::new(1, 0),
|
||||
self.object_index,
|
||||
tile.backdrop as i16),
|
||||
lower_left: MaskTileVertex::new(tile.alpha_tile_index as u16,
|
||||
Vector2I::new(0, 1),
|
||||
self.object_index,
|
||||
tile.backdrop as i16),
|
||||
lower_right: MaskTileVertex::new(tile.alpha_tile_index as u16,
|
||||
Vector2I::splat(1),
|
||||
self.object_index,
|
||||
tile.backdrop as i16),
|
||||
});
|
||||
|
||||
self.object_builder.built_object.alpha_tiles.push(AlphaTile {
|
||||
upper_left: AlphaTileVertex::new(tile_coords,
|
||||
tile.alpha_tile_index as u16,
|
||||
Vector2I::default(),
|
||||
self.object_index,
|
||||
tile.backdrop as i16,
|
||||
&self.paint_metadata),
|
||||
upper_right: AlphaTileVertex::new(tile_coords,
|
||||
tile.alpha_tile_index as u16,
|
||||
Vector2I::new(1, 0),
|
||||
self.object_index,
|
||||
tile.backdrop as i16,
|
||||
&self.paint_metadata),
|
||||
lower_left: AlphaTileVertex::new(tile_coords,
|
||||
tile.alpha_tile_index as u16,
|
||||
Vector2I::new(0, 1),
|
||||
self.object_index,
|
||||
tile.backdrop as i16,
|
||||
&self.paint_metadata),
|
||||
lower_right: AlphaTileVertex::new(tile_coords,
|
||||
tile.alpha_tile_index as u16,
|
||||
Vector2I::splat(1),
|
||||
self.object_index,
|
||||
tile.backdrop as i16,
|
||||
&self.paint_metadata),
|
||||
});
|
||||
}
|
||||
|
@ -540,18 +555,33 @@ impl PartialOrd<ActiveEdge> for ActiveEdge {
|
|||
}
|
||||
}
|
||||
|
||||
impl MaskTileVertex {
|
||||
#[inline]
|
||||
fn new(tile_index: u16, tile_offset: Vector2I, object_index: u16, backdrop: i16)
|
||||
-> MaskTileVertex {
|
||||
let mask_uv = calculate_mask_uv(tile_index, tile_offset);
|
||||
MaskTileVertex {
|
||||
tile_x: mask_uv.x() as u16,
|
||||
tile_y: mask_uv.y() as u16,
|
||||
mask_u: mask_uv.x() as u16,
|
||||
mask_v: mask_uv.y() as u16,
|
||||
backdrop,
|
||||
object_index,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AlphaTileVertex {
|
||||
#[inline]
|
||||
fn new(tile_origin: Vector2I,
|
||||
tile_index: u16,
|
||||
tile_offset: Vector2I,
|
||||
object_index: u16,
|
||||
backdrop: i16,
|
||||
paint_metadata: &PaintMetadata)
|
||||
-> AlphaTileVertex {
|
||||
let tile_position = tile_origin + tile_offset;
|
||||
let color_uv = paint_metadata.calculate_tex_coords(tile_position).scale(65535.0).to_i32();
|
||||
let mask_uv = calculate_mask_uv(tile_index as u16, tile_offset);
|
||||
let mask_uv = calculate_mask_uv(tile_index, tile_offset);
|
||||
|
||||
AlphaTileVertex {
|
||||
tile_x: tile_position.x() as i16,
|
||||
|
@ -561,7 +591,7 @@ impl AlphaTileVertex {
|
|||
mask_u: mask_uv.x() as u16,
|
||||
mask_v: mask_uv.y() as u16,
|
||||
object_index,
|
||||
backdrop,
|
||||
pad: 0,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,13 +20,12 @@ uniform vec2 uPaintTextureSize;
|
|||
|
||||
in vec2 vColorTexCoord;
|
||||
in vec2 vMaskTexCoord;
|
||||
in float vBackdrop;
|
||||
in vec4 vColor;
|
||||
|
||||
out vec4 oFragColor;
|
||||
|
||||
void main(){
|
||||
float coverage = abs(texture(uStencilTexture, vMaskTexCoord). r + vBackdrop);
|
||||
float coverage = texture(uStencilTexture, vMaskTexCoord). r;
|
||||
vec4 color = texture(uPaintTexture, vColorTexCoord);
|
||||
oFragColor = vec4(color . rgb, color . a * coverage);
|
||||
}
|
||||
|
|
|
@ -21,18 +21,15 @@ uniform vec2 uStencilTextureSize;
|
|||
in ivec2 aTilePosition;
|
||||
in vec2 aColorTexCoord;
|
||||
in vec2 aMaskTexCoord;
|
||||
in int aBackdrop;
|
||||
|
||||
out vec2 vColorTexCoord;
|
||||
out vec2 vMaskTexCoord;
|
||||
out float vBackdrop;
|
||||
|
||||
void main(){
|
||||
vec2 position = aTilePosition * uTileSize;
|
||||
|
||||
vMaskTexCoord = aMaskTexCoord;
|
||||
vColorTexCoord = aColorTexCoord;
|
||||
vBackdrop = float(aBackdrop);
|
||||
gl_Position = uTransform * vec4(position, 0.0, 1.0);
|
||||
}
|
||||
|
||||
|
|
|
@ -21,13 +21,12 @@ struct main0_in
|
|||
{
|
||||
float2 vColorTexCoord [[user(locn0)]];
|
||||
float2 vMaskTexCoord [[user(locn1)]];
|
||||
float vBackdrop [[user(locn2)]];
|
||||
};
|
||||
|
||||
fragment main0_out main0(main0_in in [[stage_in]], constant spvDescriptorSetBuffer0& spvDescriptorSet0 [[buffer(0)]])
|
||||
{
|
||||
main0_out out = {};
|
||||
float coverage = abs(spvDescriptorSet0.uStencilTexture.sample(spvDescriptorSet0.uStencilTextureSmplr, in.vMaskTexCoord).x + in.vBackdrop);
|
||||
float coverage = spvDescriptorSet0.uStencilTexture.sample(spvDescriptorSet0.uStencilTextureSmplr, in.vMaskTexCoord).x;
|
||||
float4 color = spvDescriptorSet0.uPaintTexture.sample(spvDescriptorSet0.uPaintTextureSmplr, in.vColorTexCoord);
|
||||
out.oFragColor = float4(color.xyz, color.w * coverage);
|
||||
return out;
|
||||
|
|
|
@ -14,7 +14,6 @@ struct main0_out
|
|||
{
|
||||
float2 vColorTexCoord [[user(locn0)]];
|
||||
float2 vMaskTexCoord [[user(locn1)]];
|
||||
float vBackdrop [[user(locn2)]];
|
||||
float4 gl_Position [[position]];
|
||||
};
|
||||
|
||||
|
@ -23,7 +22,6 @@ struct main0_in
|
|||
int2 aTilePosition [[attribute(0)]];
|
||||
float2 aColorTexCoord [[attribute(1)]];
|
||||
float2 aMaskTexCoord [[attribute(2)]];
|
||||
int aBackdrop [[attribute(3)]];
|
||||
};
|
||||
|
||||
vertex main0_out main0(main0_in in [[stage_in]], constant spvDescriptorSetBuffer0& spvDescriptorSet0 [[buffer(0)]])
|
||||
|
@ -32,7 +30,6 @@ vertex main0_out main0(main0_in in [[stage_in]], constant spvDescriptorSetBuffer
|
|||
float2 position = float2(in.aTilePosition) * (*spvDescriptorSet0.uTileSize);
|
||||
out.vMaskTexCoord = in.aMaskTexCoord;
|
||||
out.vColorTexCoord = in.aColorTexCoord;
|
||||
out.vBackdrop = float(in.aBackdrop);
|
||||
out.gl_Position = (*spvDescriptorSet0.uTransform) * float4(position, 0.0, 1.0);
|
||||
return out;
|
||||
}
|
||||
|
|
|
@ -11,6 +11,8 @@ SHADERS=\
|
|||
demo_ground.vs.glsl \
|
||||
fill.fs.glsl \
|
||||
fill.vs.glsl \
|
||||
mask_winding.fs.glsl \
|
||||
mask_winding.vs.glsl \
|
||||
post.fs.glsl \
|
||||
post.vs.glsl \
|
||||
reproject.fs.glsl \
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
#version 330
|
||||
|
||||
// pathfinder/shaders/mask_winding.fs.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;
|
||||
|
||||
uniform sampler2D uMaskTexture;
|
||||
|
||||
in vec2 vMaskTexCoord;
|
||||
in float vBackdrop;
|
||||
|
||||
out vec4 oFragColor;
|
||||
|
||||
void main() {
|
||||
oFragColor = vec4(abs(texture(uMaskTexture, vMaskTexCoord).r + vBackdrop));
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
#version 330
|
||||
|
||||
// pathfinder/shaders/mask_winding.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;
|
||||
in vec2 aMaskTexCoord;
|
||||
in int aBackdrop;
|
||||
|
||||
out vec2 vMaskTexCoord;
|
||||
out float vBackdrop;
|
||||
|
||||
void main() {
|
||||
vMaskTexCoord = aMaskTexCoord;
|
||||
vBackdrop = float(aBackdrop);
|
||||
gl_Position = vec4(mix(vec2(-1.0, -1.0), vec2(1.0, 1.0), aPosition), 0.0, 1.0);
|
||||
}
|
|
@ -18,13 +18,12 @@ uniform vec2 uPaintTextureSize;
|
|||
|
||||
in vec2 vColorTexCoord;
|
||||
in vec2 vMaskTexCoord;
|
||||
in float vBackdrop;
|
||||
in vec4 vColor;
|
||||
|
||||
out vec4 oFragColor;
|
||||
|
||||
void main() {
|
||||
float coverage = abs(texture(uStencilTexture, vMaskTexCoord).r + vBackdrop);
|
||||
float coverage = texture(uStencilTexture, vMaskTexCoord).r;
|
||||
vec4 color = texture(uPaintTexture, vColorTexCoord);
|
||||
oFragColor = vec4(color.rgb, color.a * coverage);
|
||||
}
|
||||
|
|
|
@ -19,17 +19,14 @@ uniform vec2 uStencilTextureSize;
|
|||
in ivec2 aTilePosition;
|
||||
in vec2 aColorTexCoord;
|
||||
in vec2 aMaskTexCoord;
|
||||
in int aBackdrop;
|
||||
|
||||
out vec2 vColorTexCoord;
|
||||
out vec2 vMaskTexCoord;
|
||||
out float vBackdrop;
|
||||
|
||||
void main() {
|
||||
vec2 position = aTilePosition * uTileSize;
|
||||
|
||||
vMaskTexCoord = aMaskTexCoord;
|
||||
vColorTexCoord = aColorTexCoord;
|
||||
vBackdrop = float(aBackdrop);
|
||||
gl_Position = uTransform * vec4(position, 0.0, 1.0);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue