From 0097ffab190f1d695e8030ce7217f4264970a11d Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Tue, 15 Jan 2019 11:42:25 -0800 Subject: [PATCH] wip --- demo3/shaders/mask_tile.fs.glsl | 2 +- demo3/shaders/mask_tile.vs.glsl | 2 +- demo3/shaders/solid_tile.vs.glsl | 4 +- demo3/src/main.rs | 94 +++++++++++++++++++++----------- geometry/src/line_segment.rs | 21 +++++++ geometry/src/outline.rs | 16 +++++- renderer/src/gpu_data.rs | 1 + renderer/src/scene.rs | 12 +++- renderer/src/tiles.rs | 2 +- 9 files changed, 113 insertions(+), 41 deletions(-) diff --git a/demo3/shaders/mask_tile.fs.glsl b/demo3/shaders/mask_tile.fs.glsl index 2596e026..c6efffe8 100644 --- a/demo3/shaders/mask_tile.fs.glsl +++ b/demo3/shaders/mask_tile.fs.glsl @@ -1,6 +1,6 @@ #version 330 -// pathfinder/demo2/cover.fs.glsl +// pathfinder/demo3/resources/shaders/mask_tile.fs.glsl // // Copyright © 2018 The Pathfinder Project Developers. // diff --git a/demo3/shaders/mask_tile.vs.glsl b/demo3/shaders/mask_tile.vs.glsl index 6f51b2a7..93656834 100644 --- a/demo3/shaders/mask_tile.vs.glsl +++ b/demo3/shaders/mask_tile.vs.glsl @@ -1,6 +1,6 @@ #version 330 -// pathfinder/demo2/cover.vs.glsl +// pathfinder/demo3/resources/shaders/mask_tile.vs.glsl // // Copyright © 2018 The Pathfinder Project Developers. // diff --git a/demo3/shaders/solid_tile.vs.glsl b/demo3/shaders/solid_tile.vs.glsl index b25cdfc0..bd906262 100644 --- a/demo3/shaders/solid_tile.vs.glsl +++ b/demo3/shaders/solid_tile.vs.glsl @@ -1,8 +1,8 @@ #version 330 -// pathfinder/demo2/opaque.vs.glsl +// pathfinder/demo3/resources/shaders/solid_tile.vs.glsl // -// Copyright © 2018 The Pathfinder Project Developers. +// Copyright © 2019 The Pathfinder Project Developers. // // Licensed under the Apache License, Version 2.0 or the MIT license diff --git a/demo3/src/main.rs b/demo3/src/main.rs index 1000a463..c944d979 100644 --- a/demo3/src/main.rs +++ b/demo3/src/main.rs @@ -12,6 +12,8 @@ use clap::{App, Arg}; use euclid::Size2D; use gl::types::{GLchar, GLfloat, GLint, GLsizei, GLsizeiptr, GLuint, GLvoid}; use jemallocator; +use pathfinder_geometry::point::Point2DF32; +use pathfinder_geometry::transform::Transform2DF32; use pathfinder_renderer::builder::SceneBuilder; use pathfinder_renderer::gpu_data::{Batch, BuiltScene, SolidTileScenePrimitive}; use pathfinder_renderer::paint::ObjectShader; @@ -52,7 +54,8 @@ const FILL_COLORS_TEXTURE_WIDTH: u32 = 256; const FILL_COLORS_TEXTURE_HEIGHT: u32 = 256; fn main() { - let scene = load_scene(); + let options = Options::get(); + let base_scene = load_scene(&options); let sdl_context = sdl2::init().unwrap(); let sdl_video = sdl_context.video().unwrap(); @@ -68,7 +71,7 @@ fn main() { .build() .unwrap(); - let gl_context = window.gl_create_context().unwrap(); + let _gl_context = window.gl_create_context().unwrap(); gl::load_with(|name| sdl_video.gl_get_proc_address(name) as *const _); let mut sdl_event_pump = sdl_context.event_pump().unwrap(); @@ -77,11 +80,19 @@ fn main() { let (drawable_width, drawable_height) = window.drawable_size(); let mut renderer = Renderer::new(&Size2D::new(drawable_width, drawable_height)); + let mut scale = 1.0; + while !exit { + let mut scene = base_scene.clone(); + scene.transform(&Transform2DF32::from_scale(&Point2DF32::new(scale, scale))); + scale -= 0.1; + + let built_scene = build_scene(&scene, &options); + unsafe { gl::ClearColor(1.0, 1.0, 1.0, 1.0); gl::Clear(gl::COLOR_BUFFER_BIT); - renderer.render_scene(&scene); + renderer.render_scene(&built_scene); } window.gl_swap_window(); @@ -97,37 +108,48 @@ fn main() { } } -fn load_scene() -> BuiltScene { - let matches = App::new("tile-svg") - .arg( - Arg::with_name("jobs") - .short("j") - .long("jobs") - .value_name("THREADS") - .takes_value(true) - .help("Number of threads to use"), - ) - .arg( - Arg::with_name("INPUT") - .help("Path to the SVG file to render") - .required(true) - .index(1), - ) - .get_matches(); - let jobs: Option = matches - .value_of("jobs") - .map(|string| string.parse().unwrap()); - let input_path = PathBuf::from(matches.value_of("INPUT").unwrap()); +struct Options { + jobs: Option, + input_path: PathBuf, +} - // Set up Rayon. - let mut thread_pool_builder = ThreadPoolBuilder::new(); - if let Some(jobs) = jobs { - thread_pool_builder = thread_pool_builder.num_threads(jobs); +impl Options { + fn get() -> Options { + let matches = App::new("tile-svg") + .arg( + Arg::with_name("jobs") + .short("j") + .long("jobs") + .value_name("THREADS") + .takes_value(true) + .help("Number of threads to use"), + ) + .arg( + Arg::with_name("INPUT") + .help("Path to the SVG file to render") + .required(true) + .index(1), + ) + .get_matches(); + let jobs: Option = matches + .value_of("jobs") + .map(|string| string.parse().unwrap()); + let input_path = PathBuf::from(matches.value_of("INPUT").unwrap()); + + // Set up Rayon. + let mut thread_pool_builder = ThreadPoolBuilder::new(); + if let Some(jobs) = jobs { + thread_pool_builder = thread_pool_builder.num_threads(jobs); + } + thread_pool_builder.build_global().unwrap(); + + Options { jobs, input_path } } - thread_pool_builder.build_global().unwrap(); +} +fn load_scene(options: &Options) -> Scene { // Build scene. - let usvg = Tree::from_file(&input_path, &UsvgOptions::default()).unwrap(); + let usvg = Tree::from_file(&options.input_path, &UsvgOptions::default()).unwrap(); let scene = Scene::from_tree(usvg); println!( @@ -140,20 +162,23 @@ fn load_scene() -> BuiltScene { scene.paints.len() ); + scene +} + +fn build_scene(scene: &Scene, options: &Options) -> BuiltScene { let (mut elapsed_object_build_time, mut elapsed_scene_build_time) = (0.0, 0.0); - let mut built_scene = BuiltScene::new(&scene.view_box); let z_buffer = ZBuffer::new(&scene.view_box); let start_time = Instant::now(); - let built_objects = match jobs { + let built_objects = match options.jobs { Some(1) => scene.build_objects_sequentially(&z_buffer), _ => scene.build_objects(&z_buffer), }; elapsed_object_build_time += duration_to_ms(&(Instant::now() - start_time)); let start_time = Instant::now(); - built_scene = BuiltScene::new(&scene.view_box); + let mut built_scene = BuiltScene::new(&scene.view_box); built_scene.shaders = scene.build_shaders(); let mut scene_builder = SceneBuilder::new(built_objects, z_buffer, &scene.view_box); built_scene.solid_tiles = scene_builder.build_solid_tiles(); @@ -191,6 +216,7 @@ struct Renderer { solid_tile_program: SolidTileProgram, mask_tile_program: MaskTileProgram, area_lut_texture: Texture, + #[allow(dead_code)] quad_vertex_positions_buffer: Buffer, fill_vertex_array: FillVertexArray, mask_tile_vertex_array: MaskTileVertexArray, @@ -676,7 +702,9 @@ impl Uniform { struct Program { gl_program: GLuint, + #[allow(dead_code)] vertex_shader: Shader, + #[allow(dead_code)] fragment_shader: Shader, } diff --git a/geometry/src/line_segment.rs b/geometry/src/line_segment.rs index ae32d569..44bb9b62 100644 --- a/geometry/src/line_segment.rs +++ b/geometry/src/line_segment.rs @@ -81,6 +81,17 @@ impl LineSegmentF32 { LineSegmentF32(mid_mid.as_f64x2().interleave(to_to.as_f64x2()).0.as_f32x4())) } + // Returns the left segment first, followed by the right segment. + #[inline] + pub fn split_at_x(&self, x: f32) -> (LineSegmentF32, LineSegmentF32) { + let (min_part, max_part) = self.split(self.solve_t_for_x(x)); + if min_part.from_x() < max_part.from_x() { + (min_part, max_part) + } else { + (max_part, min_part) + } + } + // Returns the upper segment first, followed by the lower segment. #[inline] pub fn split_at_y(&self, y: f32) -> (LineSegmentF32, LineSegmentF32) { @@ -121,6 +132,16 @@ impl LineSegmentF32 { } } + #[inline] + pub fn min_x(&self) -> f32 { + f32::min(self.from_x(), self.to_x()) + } + + #[inline] + pub fn max_x(&self) -> f32 { + f32::max(self.from_x(), self.to_x()) + } + #[inline] pub fn min_y(&self) -> f32 { f32::min(self.from_y(), self.to_y()) diff --git a/geometry/src/outline.rs b/geometry/src/outline.rs index b61672c3..deaf439c 100644 --- a/geometry/src/outline.rs +++ b/geometry/src/outline.rs @@ -12,17 +12,19 @@ use crate::point::Point2DF32; use crate::segment::{Segment, SegmentFlags, SegmentKind}; +use crate::transform::Transform2DF32; use euclid::{Point2D, Rect}; use lyon_path::PathEvent; use std::fmt::{self, Debug, Formatter}; use std::mem; -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct Outline { pub contours: Vec, bounds: Rect, } +#[derive(Clone)] pub struct Contour { points: Vec, flags: Vec, @@ -118,6 +120,11 @@ impl Outline { pub fn bounds(&self) -> &Rect { &self.bounds } + + #[inline] + pub fn transform(&mut self, transform: &Transform2DF32) { + self.contours.iter_mut().for_each(|contour| contour.transform(transform)); + } } impl Contour { @@ -261,6 +268,13 @@ impl Contour { point_index + 1 } } + + #[inline] + pub fn transform(&mut self, transform: &Transform2DF32) { + for point in &mut self.points { + *point = transform.transform_point(point) + } + } } impl Debug for Contour { diff --git a/renderer/src/gpu_data.rs b/renderer/src/gpu_data.rs index 42d93351..816a28ce 100644 --- a/renderer/src/gpu_data.rs +++ b/renderer/src/gpu_data.rs @@ -59,6 +59,7 @@ pub struct TileObjectPrimitive { pub backdrop: i16, } +// FIXME(pcwalton): Move `subpx` before `px` and remove `repr(packed)`. #[derive(Clone, Copy, Debug)] #[repr(packed)] pub struct FillBatchPrimitive { diff --git a/renderer/src/scene.rs b/renderer/src/scene.rs index 894aac21..96d2079a 100644 --- a/renderer/src/scene.rs +++ b/renderer/src/scene.rs @@ -17,9 +17,10 @@ use crate::z_buffer::ZBuffer; use euclid::Rect; use hashbrown::HashMap; use pathfinder_geometry::outline::Outline; +use pathfinder_geometry::transform::Transform2DF32; use rayon::iter::{IndexedParallelIterator, IntoParallelRefIterator, ParallelIterator}; -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct Scene { pub objects: Vec, pub paints: Vec, @@ -96,9 +97,16 @@ impl Scene { }) .collect() } + + pub fn transform(&mut self, transform: &Transform2DF32) { + // TODO(pcwalton): Transform bounds? + for object in &mut self.objects { + object.outline.transform(transform) + } + } } -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct PathObject { outline: Outline, paint: PaintId, diff --git a/renderer/src/tiles.rs b/renderer/src/tiles.rs index 2ea4651f..c7c2cd25 100644 --- a/renderer/src/tiles.rs +++ b/renderer/src/tiles.rs @@ -177,7 +177,7 @@ impl<'o, 'z> Tiler<'o, 'z> { } // Do final subtile fill, if necessary. - debug_assert!(current_tile_x == segment_tile_x); + debug_assert_eq!(current_tile_x, segment_tile_x); debug_assert!(current_tile_x < self.built_object.tile_rect.max_x()); let segment_subtile_x = segment_x - (i32::from(current_tile_x) * TILE_WIDTH as i32) as f32;