wip
This commit is contained in:
parent
5bbb5a1b74
commit
0097ffab19
|
@ -1,6 +1,6 @@
|
||||||
#version 330
|
#version 330
|
||||||
|
|
||||||
// pathfinder/demo2/cover.fs.glsl
|
// pathfinder/demo3/resources/shaders/mask_tile.fs.glsl
|
||||||
//
|
//
|
||||||
// Copyright © 2018 The Pathfinder Project Developers.
|
// Copyright © 2018 The Pathfinder Project Developers.
|
||||||
//
|
//
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#version 330
|
#version 330
|
||||||
|
|
||||||
// pathfinder/demo2/cover.vs.glsl
|
// pathfinder/demo3/resources/shaders/mask_tile.vs.glsl
|
||||||
//
|
//
|
||||||
// Copyright © 2018 The Pathfinder Project Developers.
|
// Copyright © 2018 The Pathfinder Project Developers.
|
||||||
//
|
//
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#version 330
|
#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 <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
|
||||||
|
|
|
@ -12,6 +12,8 @@ use clap::{App, Arg};
|
||||||
use euclid::Size2D;
|
use euclid::Size2D;
|
||||||
use gl::types::{GLchar, GLfloat, GLint, GLsizei, GLsizeiptr, GLuint, GLvoid};
|
use gl::types::{GLchar, GLfloat, GLint, GLsizei, GLsizeiptr, GLuint, GLvoid};
|
||||||
use jemallocator;
|
use jemallocator;
|
||||||
|
use pathfinder_geometry::point::Point2DF32;
|
||||||
|
use pathfinder_geometry::transform::Transform2DF32;
|
||||||
use pathfinder_renderer::builder::SceneBuilder;
|
use pathfinder_renderer::builder::SceneBuilder;
|
||||||
use pathfinder_renderer::gpu_data::{Batch, BuiltScene, SolidTileScenePrimitive};
|
use pathfinder_renderer::gpu_data::{Batch, BuiltScene, SolidTileScenePrimitive};
|
||||||
use pathfinder_renderer::paint::ObjectShader;
|
use pathfinder_renderer::paint::ObjectShader;
|
||||||
|
@ -52,7 +54,8 @@ const FILL_COLORS_TEXTURE_WIDTH: u32 = 256;
|
||||||
const FILL_COLORS_TEXTURE_HEIGHT: u32 = 256;
|
const FILL_COLORS_TEXTURE_HEIGHT: u32 = 256;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let scene = load_scene();
|
let options = Options::get();
|
||||||
|
let base_scene = load_scene(&options);
|
||||||
|
|
||||||
let sdl_context = sdl2::init().unwrap();
|
let sdl_context = sdl2::init().unwrap();
|
||||||
let sdl_video = sdl_context.video().unwrap();
|
let sdl_video = sdl_context.video().unwrap();
|
||||||
|
@ -68,7 +71,7 @@ fn main() {
|
||||||
.build()
|
.build()
|
||||||
.unwrap();
|
.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 _);
|
gl::load_with(|name| sdl_video.gl_get_proc_address(name) as *const _);
|
||||||
|
|
||||||
let mut sdl_event_pump = sdl_context.event_pump().unwrap();
|
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 (drawable_width, drawable_height) = window.drawable_size();
|
||||||
let mut renderer = Renderer::new(&Size2D::new(drawable_width, drawable_height));
|
let mut renderer = Renderer::new(&Size2D::new(drawable_width, drawable_height));
|
||||||
|
|
||||||
|
let mut scale = 1.0;
|
||||||
|
|
||||||
while !exit {
|
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 {
|
unsafe {
|
||||||
gl::ClearColor(1.0, 1.0, 1.0, 1.0);
|
gl::ClearColor(1.0, 1.0, 1.0, 1.0);
|
||||||
gl::Clear(gl::COLOR_BUFFER_BIT);
|
gl::Clear(gl::COLOR_BUFFER_BIT);
|
||||||
renderer.render_scene(&scene);
|
renderer.render_scene(&built_scene);
|
||||||
}
|
}
|
||||||
|
|
||||||
window.gl_swap_window();
|
window.gl_swap_window();
|
||||||
|
@ -97,37 +108,48 @@ fn main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_scene() -> BuiltScene {
|
struct Options {
|
||||||
let matches = App::new("tile-svg")
|
jobs: Option<usize>,
|
||||||
.arg(
|
input_path: PathBuf,
|
||||||
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<usize> = matches
|
|
||||||
.value_of("jobs")
|
|
||||||
.map(|string| string.parse().unwrap());
|
|
||||||
let input_path = PathBuf::from(matches.value_of("INPUT").unwrap());
|
|
||||||
|
|
||||||
// Set up Rayon.
|
impl Options {
|
||||||
let mut thread_pool_builder = ThreadPoolBuilder::new();
|
fn get() -> Options {
|
||||||
if let Some(jobs) = jobs {
|
let matches = App::new("tile-svg")
|
||||||
thread_pool_builder = thread_pool_builder.num_threads(jobs);
|
.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<usize> = 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.
|
// 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);
|
let scene = Scene::from_tree(usvg);
|
||||||
|
|
||||||
println!(
|
println!(
|
||||||
|
@ -140,20 +162,23 @@ fn load_scene() -> BuiltScene {
|
||||||
scene.paints.len()
|
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 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 z_buffer = ZBuffer::new(&scene.view_box);
|
||||||
|
|
||||||
let start_time = Instant::now();
|
let start_time = Instant::now();
|
||||||
let built_objects = match jobs {
|
let built_objects = match options.jobs {
|
||||||
Some(1) => scene.build_objects_sequentially(&z_buffer),
|
Some(1) => scene.build_objects_sequentially(&z_buffer),
|
||||||
_ => scene.build_objects(&z_buffer),
|
_ => scene.build_objects(&z_buffer),
|
||||||
};
|
};
|
||||||
elapsed_object_build_time += duration_to_ms(&(Instant::now() - start_time));
|
elapsed_object_build_time += duration_to_ms(&(Instant::now() - start_time));
|
||||||
|
|
||||||
let start_time = Instant::now();
|
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();
|
built_scene.shaders = scene.build_shaders();
|
||||||
let mut scene_builder = SceneBuilder::new(built_objects, z_buffer, &scene.view_box);
|
let mut scene_builder = SceneBuilder::new(built_objects, z_buffer, &scene.view_box);
|
||||||
built_scene.solid_tiles = scene_builder.build_solid_tiles();
|
built_scene.solid_tiles = scene_builder.build_solid_tiles();
|
||||||
|
@ -191,6 +216,7 @@ struct Renderer {
|
||||||
solid_tile_program: SolidTileProgram,
|
solid_tile_program: SolidTileProgram,
|
||||||
mask_tile_program: MaskTileProgram,
|
mask_tile_program: MaskTileProgram,
|
||||||
area_lut_texture: Texture,
|
area_lut_texture: Texture,
|
||||||
|
#[allow(dead_code)]
|
||||||
quad_vertex_positions_buffer: Buffer,
|
quad_vertex_positions_buffer: Buffer,
|
||||||
fill_vertex_array: FillVertexArray,
|
fill_vertex_array: FillVertexArray,
|
||||||
mask_tile_vertex_array: MaskTileVertexArray,
|
mask_tile_vertex_array: MaskTileVertexArray,
|
||||||
|
@ -676,7 +702,9 @@ impl Uniform {
|
||||||
|
|
||||||
struct Program {
|
struct Program {
|
||||||
gl_program: GLuint,
|
gl_program: GLuint,
|
||||||
|
#[allow(dead_code)]
|
||||||
vertex_shader: Shader,
|
vertex_shader: Shader,
|
||||||
|
#[allow(dead_code)]
|
||||||
fragment_shader: Shader,
|
fragment_shader: Shader,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -81,6 +81,17 @@ impl LineSegmentF32 {
|
||||||
LineSegmentF32(mid_mid.as_f64x2().interleave(to_to.as_f64x2()).0.as_f32x4()))
|
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.
|
// Returns the upper segment first, followed by the lower segment.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn split_at_y(&self, y: f32) -> (LineSegmentF32, LineSegmentF32) {
|
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]
|
#[inline]
|
||||||
pub fn min_y(&self) -> f32 {
|
pub fn min_y(&self) -> f32 {
|
||||||
f32::min(self.from_y(), self.to_y())
|
f32::min(self.from_y(), self.to_y())
|
||||||
|
|
|
@ -12,17 +12,19 @@
|
||||||
|
|
||||||
use crate::point::Point2DF32;
|
use crate::point::Point2DF32;
|
||||||
use crate::segment::{Segment, SegmentFlags, SegmentKind};
|
use crate::segment::{Segment, SegmentFlags, SegmentKind};
|
||||||
|
use crate::transform::Transform2DF32;
|
||||||
use euclid::{Point2D, Rect};
|
use euclid::{Point2D, Rect};
|
||||||
use lyon_path::PathEvent;
|
use lyon_path::PathEvent;
|
||||||
use std::fmt::{self, Debug, Formatter};
|
use std::fmt::{self, Debug, Formatter};
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Outline {
|
pub struct Outline {
|
||||||
pub contours: Vec<Contour>,
|
pub contours: Vec<Contour>,
|
||||||
bounds: Rect<f32>,
|
bounds: Rect<f32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct Contour {
|
pub struct Contour {
|
||||||
points: Vec<Point2DF32>,
|
points: Vec<Point2DF32>,
|
||||||
flags: Vec<PointFlags>,
|
flags: Vec<PointFlags>,
|
||||||
|
@ -118,6 +120,11 @@ impl Outline {
|
||||||
pub fn bounds(&self) -> &Rect<f32> {
|
pub fn bounds(&self) -> &Rect<f32> {
|
||||||
&self.bounds
|
&self.bounds
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn transform(&mut self, transform: &Transform2DF32) {
|
||||||
|
self.contours.iter_mut().for_each(|contour| contour.transform(transform));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Contour {
|
impl Contour {
|
||||||
|
@ -261,6 +268,13 @@ impl Contour {
|
||||||
point_index + 1
|
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 {
|
impl Debug for Contour {
|
||||||
|
|
|
@ -59,6 +59,7 @@ pub struct TileObjectPrimitive {
|
||||||
pub backdrop: i16,
|
pub backdrop: i16,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME(pcwalton): Move `subpx` before `px` and remove `repr(packed)`.
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
#[repr(packed)]
|
#[repr(packed)]
|
||||||
pub struct FillBatchPrimitive {
|
pub struct FillBatchPrimitive {
|
||||||
|
|
|
@ -17,9 +17,10 @@ use crate::z_buffer::ZBuffer;
|
||||||
use euclid::Rect;
|
use euclid::Rect;
|
||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
use pathfinder_geometry::outline::Outline;
|
use pathfinder_geometry::outline::Outline;
|
||||||
|
use pathfinder_geometry::transform::Transform2DF32;
|
||||||
use rayon::iter::{IndexedParallelIterator, IntoParallelRefIterator, ParallelIterator};
|
use rayon::iter::{IndexedParallelIterator, IntoParallelRefIterator, ParallelIterator};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Scene {
|
pub struct Scene {
|
||||||
pub objects: Vec<PathObject>,
|
pub objects: Vec<PathObject>,
|
||||||
pub paints: Vec<Paint>,
|
pub paints: Vec<Paint>,
|
||||||
|
@ -96,9 +97,16 @@ impl Scene {
|
||||||
})
|
})
|
||||||
.collect()
|
.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 {
|
pub struct PathObject {
|
||||||
outline: Outline,
|
outline: Outline,
|
||||||
paint: PaintId,
|
paint: PaintId,
|
||||||
|
|
|
@ -177,7 +177,7 @@ impl<'o, 'z> Tiler<'o, 'z> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do final subtile fill, if necessary.
|
// 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());
|
debug_assert!(current_tile_x < self.built_object.tile_rect.max_x());
|
||||||
let segment_subtile_x =
|
let segment_subtile_x =
|
||||||
segment_x - (i32::from(current_tile_x) * TILE_WIDTH as i32) as f32;
|
segment_x - (i32::from(current_tile_x) * TILE_WIDTH as i32) as f32;
|
||||||
|
|
Loading…
Reference in New Issue