diff --git a/partitionfinder/.gitignore b/partitioner/.gitignore similarity index 100% rename from partitionfinder/.gitignore rename to partitioner/.gitignore diff --git a/partitionfinder/Cargo.toml b/partitioner/Cargo.toml similarity index 76% rename from partitionfinder/Cargo.toml rename to partitioner/Cargo.toml index b2db7dde..dc526f22 100644 --- a/partitionfinder/Cargo.toml +++ b/partitioner/Cargo.toml @@ -1,10 +1,10 @@ [package] -name = "partitionfinder" +name = "pathfinder_partitioner" version = "0.1.0" authors = ["Patrick Walton "] [lib] -name = "partitionfinder" +name = "pathfinder_partitioner" crate-type = ["dylib", "rlib"] [dependencies] diff --git a/partitionfinder/LICENSE-APACHE b/partitioner/LICENSE-APACHE similarity index 100% rename from partitionfinder/LICENSE-APACHE rename to partitioner/LICENSE-APACHE diff --git a/partitionfinder/LICENSE-MIT b/partitioner/LICENSE-MIT similarity index 100% rename from partitionfinder/LICENSE-MIT rename to partitioner/LICENSE-MIT diff --git a/partitionfinder/src/capi.rs b/partitioner/src/capi.rs similarity index 67% rename from partitionfinder/src/capi.rs rename to partitioner/src/capi.rs index e5c17002..3ce31fc6 100644 --- a/partitionfinder/src/capi.rs +++ b/partitioner/src/capi.rs @@ -1,14 +1,12 @@ // partitionfinder/capi.rs use env_logger; -use euclid::{Point2D, Transform2D}; +use euclid::Point2D; use legalizer::Legalizer; use partitioner::Partitioner; -use tessellator::{QuadTessLevels, Tessellator}; use std::mem; use std::slice; -use {AntialiasingMode, BQuad, BVertex, CurveIndices, EdgeInstance, Endpoint, LineIndices}; -use {Subpath, Vertex}; +use {BQuad, BVertex, CurveIndices, Endpoint, LineIndices, Subpath}; #[derive(Clone, Copy)] #[repr(C)] @@ -221,95 +219,6 @@ pub unsafe extern fn pf_partitioner_edge_indices<'a>(partitioner: *const Partiti (*out_edge_indices).lower_curve_indices_len = edge_indices.lower_curve_indices.len() as u32; } -#[no_mangle] -pub unsafe extern fn pf_tessellator_new(antialiasing_mode: AntialiasingMode) - -> *mut Tessellator<'static> { - let mut tessellator = Box::new(Tessellator::new(antialiasing_mode)); - let tessellator_ptr: *mut Tessellator<'static> = &mut *tessellator; - mem::forget(tessellator); - tessellator_ptr -} - -#[no_mangle] -pub unsafe extern fn pf_tessellator_destroy<'a>(tessellator: *mut Tessellator<'a>) { - drop(mem::transmute::<*mut Tessellator<'a>, Box>(tessellator)) -} - -#[no_mangle] -pub unsafe extern fn pf_tessellator_init<'a>(tessellator: *mut Tessellator<'a>, - b_quads: *const BQuad, - b_quad_count: u32, - b_vertices: *const BVertex, - b_vertex_count: u32, - b_indices: *const u32, - b_index_count: u32) { - // FIXME(pcwalton): This is unsafe! `Point2D` and `Point2DF32` may have different layouts! - (*tessellator).init(slice::from_raw_parts(b_quads, b_quad_count as usize), - slice::from_raw_parts(b_vertices as *const BVertex, - b_vertex_count as usize), - slice::from_raw_parts(b_indices as *const u32, b_index_count as usize)) -} - -#[no_mangle] -pub unsafe extern fn pf_tessellator_compute_hull<'a>(tessellator: *mut Tessellator<'a>, - transform: *const Matrix2DF32) { - (*tessellator).compute_hull(&Transform2D::column_major((*transform).m00, - (*transform).m01, - (*transform).m02, - (*transform).m10, - (*transform).m11, - (*transform).m12)) -} - -#[no_mangle] -pub unsafe extern fn pf_tessellator_compute_domain<'a>(tessellator: *mut Tessellator<'a>) { - (*tessellator).compute_domain() -} - -#[no_mangle] -pub unsafe extern fn pf_tessellator_tess_levels<'a>(tessellator: *mut Tessellator<'a>, - out_tess_levels_count: *mut u32) - -> *const QuadTessLevels { - let tess_levels = (*tessellator).tess_levels(); - if !out_tess_levels_count.is_null() { - *out_tess_levels_count = tess_levels.len() as u32 - } - tess_levels.as_ptr() -} - -#[no_mangle] -pub unsafe extern fn pf_tessellator_vertices<'a>(tessellator: *mut Tessellator<'a>, - out_vertex_count: *mut u32) - -> *const Vertex { - let vertices = (*tessellator).vertices(); - if !out_vertex_count.is_null() { - *out_vertex_count = vertices.len() as u32 - } - vertices.as_ptr() -} - -#[no_mangle] -pub unsafe extern fn pf_tessellator_msaa_indices<'a>(tessellator: *mut Tessellator<'a>, - out_msaa_index_count: *mut u32) - -> *const u32 { - let msaa_indices = (*tessellator).msaa_indices(); - if !out_msaa_index_count.is_null() { - *out_msaa_index_count = msaa_indices.len() as u32 - } - msaa_indices.as_ptr() -} - -#[no_mangle] -pub unsafe extern fn pf_tessellator_edge_instances<'a>(tessellator: *mut Tessellator<'a>, - out_edge_instance_count: *mut u32) - -> *const EdgeInstance { - let edge_instances = (*tessellator).edge_instances(); - if !out_edge_instance_count.is_null() { - *out_edge_instance_count = edge_instances.len() as u32 - } - edge_instances.as_ptr() -} - #[no_mangle] pub unsafe extern fn pf_init_env_logger() -> u32 { env_logger::init().is_ok() as u32 diff --git a/partitionfinder/src/geometry.rs b/partitioner/src/geometry.rs similarity index 100% rename from partitionfinder/src/geometry.rs rename to partitioner/src/geometry.rs diff --git a/partitionfinder/src/legalizer.rs b/partitioner/src/legalizer.rs similarity index 100% rename from partitionfinder/src/legalizer.rs rename to partitioner/src/legalizer.rs diff --git a/partitionfinder/src/lib.rs b/partitioner/src/lib.rs similarity index 79% rename from partitionfinder/src/lib.rs rename to partitioner/src/lib.rs index abadf7b7..2321e80b 100644 --- a/partitionfinder/src/lib.rs +++ b/partitioner/src/lib.rs @@ -18,7 +18,6 @@ pub mod capi; pub mod geometry; pub mod legalizer; pub mod partitioner; -pub mod tessellator; #[repr(C)] #[derive(Debug, Clone, Copy)] @@ -130,36 +129,6 @@ impl BVertex { } } -#[derive(Clone, Copy, Debug)] -#[repr(C)] -pub struct Vertex { - pub left_b_vertex_index: u32, - pub control_point_b_vertex_index: u32, - pub right_b_vertex_index: u32, - pub time: f32, - pub path_id: u32, - pad: u32, -} - -impl Vertex { - #[inline] - pub fn new(path_id: u32, - left_b_vertex_index: u32, - control_point_b_vertex_index: u32, - right_b_vertex_index: u32, - time: f32) - -> Vertex { - Vertex { - path_id: path_id, - left_b_vertex_index: left_b_vertex_index, - control_point_b_vertex_index: control_point_b_vertex_index, - right_b_vertex_index: right_b_vertex_index, - time: time, - pad: 0, - } - } -} - #[derive(Debug, Clone, Copy)] #[repr(C)] pub struct LineIndices { @@ -198,20 +167,3 @@ impl CurveIndices { } } } - -#[derive(Clone, Copy, Debug)] -#[repr(C)] -pub struct EdgeInstance { - pub left_vertex_index: u32, - pub right_vertex_index: u32, -} - -impl EdgeInstance { - #[inline] - pub fn new(left_vertex_index: u32, right_vertex_index: u32) -> EdgeInstance { - EdgeInstance { - left_vertex_index: left_vertex_index, - right_vertex_index: right_vertex_index, - } - } -} diff --git a/partitionfinder/src/partitionfinder.h b/partitioner/src/partitioner.h similarity index 72% rename from partitionfinder/src/partitionfinder.h rename to partitioner/src/partitioner.h index 200944f1..c61cc8b4 100644 --- a/partitionfinder/src/partitionfinder.h +++ b/partitioner/src/partitioner.h @@ -1,7 +1,7 @@ -// partitionfinder/partitionfinder.h +// pathfinder/partitioner/partitioner.h -#ifndef PARTITIONFINDER_H -#define PARTITIONFINDER_H +#ifndef PATHFINDER_PARTITIONER_H +#define PATHFINDER_PARTITIONER_H #include #include @@ -47,18 +47,6 @@ struct pf_b_vertex { typedef struct pf_b_vertex pf_b_vertex_t; -struct pf_vertex { - uint32_t left_b_vertex_index; - uint32_t control_point_b_vertex_index; - uint32_t right_b_vertex_index; - float time; - uint32_t path_id; - uint8_t bottom; - uint8_t pad0, pad1, pad2; -}; - -typedef struct pf_vertex pf_vertex_t; - struct pf_cover_indices { const uint32_t *interior_indices; uint32_t interior_indices_len; @@ -97,20 +85,6 @@ struct pf_edge_indices { typedef struct pf_edge_indices pf_edge_indices_t; -struct pf_edge_instance { - uint32_t left_vertex; - uint32_t right_vertex; -}; - -typedef struct pf_edge_instance pf_edge_instance_t; - -struct pf_quad_tess_levels { - pf_float16_t outer[4]; - pf_float16_t inner[2]; -}; - -typedef struct pf_quad_tess_levels pf_quad_tess_levels_t; - struct pf_b_quad { uint32_t upper_left_vertex_index; uint32_t upper_control_point_vertex_index; @@ -146,10 +120,6 @@ struct pf_partitioner; typedef struct pf_partitioner pf_partitioner_t; -struct pf_tessellator; - -typedef struct pf_tessellator pf_tessellator_t; - pf_legalizer_t *pf_legalizer_new(); void pf_legalizer_destroy(pf_legalizer_t *legalizer); @@ -207,34 +177,6 @@ const void pf_partitioner_cover_indices(const pf_partitioner_t *partitioner, const void pf_partitioner_edge_indices(const pf_partitioner_t *partitioner, pf_edge_indices_t *out_edge_indices); -pf_tessellator_t *pf_tessellator_new(pf_antialiasing_mode_t antialiasing_mode); - -void pf_tessellator_destroy(pf_tessellator_t *tessellator); - -void pf_tessellator_init(pf_tessellator_t *tessellator, - const pf_b_quad_t *b_quads, - uint32_t b_quad_count, - const pf_point2d_f32_t *b_vertices, - uint32_t b_vertex_count, - const uint32_t *b_indices, - uint32_t b_index_count); - -void pf_tessellator_compute_hull(pf_tessellator_t *tessellator, const pf_matrix2d_f32_t *transform); - -void pf_tessellator_compute_domain(pf_tessellator_t *tessellator); - -const pf_quad_tess_levels_t *pf_tessellator_tess_levels(const pf_tessellator_t *tessellator, - uint32_t *out_tess_levels_count); - -const pf_vertex_t *pf_tessellator_vertices(const pf_tessellator_t *tessellator, - uint32_t *out_vertex_count); - -const uint32_t *pf_tessellator_msaa_indices(const pf_tessellator_t *tessellator, - uint32_t *out_msaa_index_count); - -const pf_edge_instance_t *pf_tessellator_edge_instances(const pf_tessellator_t *tessellator, - uint32_t *out_edge_instance_count); - uint32_t pf_init_env_logger(); #ifdef __cplusplus diff --git a/partitionfinder/src/partitioner.rs b/partitioner/src/partitioner.rs similarity index 99% rename from partitionfinder/src/partitioner.rs rename to partitioner/src/partitioner.rs index 1e2ea832..a091d534 100644 --- a/partitionfinder/src/partitioner.rs +++ b/partitioner/src/partitioner.rs @@ -5,7 +5,7 @@ use euclid::Point2D; use geometry::{self, SubdividedQuadraticBezier}; use log::LogLevel; use std::collections::BinaryHeap; -use std::cmp::{self, Ordering}; +use std::cmp::Ordering; use std::f32; use std::u32; use {BQuad, BVertex, BVertexKind, CurveIndices, Endpoint, LineIndices, Subpath}; diff --git a/partitionfinder/src/tessellator.rs b/partitionfinder/src/tessellator.rs deleted file mode 100644 index c98ed16b..00000000 --- a/partitionfinder/src/tessellator.rs +++ /dev/null @@ -1,191 +0,0 @@ -// partitionfinder/tessellator.rs - -#![allow(dead_code)] - -use euclid::Transform2D; -use half::{f16, self}; -use std::cmp; -use std::u32; -use {AntialiasingMode, BQuad, BVertex, EdgeInstance, Vertex}; - -const TOLERANCE: f32 = 0.25; - -pub struct Tessellator<'a> { - b_quads: &'a [BQuad], - b_vertices: &'a [BVertex], - b_indices: &'a [u32], - antialiasing_mode: AntialiasingMode, - - tess_levels: Vec, - vertices: Vec, - msaa_indices: Vec, - edge_instances: Vec, -} - -// NB: This must match the layout of `MTLQuadTessellationFactorsHalf` in Metal in order for the -// Pathfinder demo to work. -#[derive(Clone, Copy, Debug)] -#[repr(C)] -pub struct QuadTessLevels { - pub outer: [f16; 4], - pub inner: [f16; 2], -} - -impl QuadTessLevels { - fn new() -> QuadTessLevels { - QuadTessLevels { - outer: [half::consts::ZERO; 4], - inner: [half::consts::ZERO; 2], - } - } -} - -impl<'a> Tessellator<'a> { - pub fn new<'b>(antialiasing_mode: AntialiasingMode) -> Tessellator<'b> { - Tessellator { - b_quads: &[], - b_vertices: &[], - b_indices: &[], - antialiasing_mode: antialiasing_mode, - - tess_levels: vec![], - vertices: vec![], - msaa_indices: vec![], - edge_instances: vec![], - } - } - - pub fn init(&mut self, b_quads: &'a [BQuad], b_vertices: &'a [BVertex], b_indices: &'a [u32]) { - self.b_quads = b_quads; - self.b_vertices = b_vertices; - self.b_indices = b_indices; - self.tess_levels = vec![QuadTessLevels::new(); b_quads.len()]; - } - - pub fn compute_hull(&mut self, transform: &Transform2D) { - for b_quad_index in 0..self.tess_levels.len() { - let b_quad = &self.b_quads[b_quad_index as usize]; - - let upper_tess_level = tess_level_for_edge(b_quad.upper_left_vertex_index, - b_quad.upper_control_point_vertex_index, - b_quad.upper_right_vertex_index, - transform, - self.b_vertices); - let lower_tess_level = tess_level_for_edge(b_quad.lower_left_vertex_index, - b_quad.lower_control_point_vertex_index, - b_quad.lower_right_vertex_index, - transform, - self.b_vertices); - - // TODO(pcwalton): Use fewer thin triangles. - let mut tess_levels = &mut self.tess_levels[b_quad_index as usize]; - tess_levels.outer[0] = half::consts::ONE; - tess_levels.outer[1] = f16::from_f32(upper_tess_level as f32); - tess_levels.outer[2] = half::consts::ONE; - tess_levels.outer[3] = f16::from_f32(lower_tess_level as f32); - tess_levels.inner[0] = f16::from_f32(cmp::max(upper_tess_level, - lower_tess_level) as f32); - tess_levels.inner[1] = half::consts::ZERO; - } - } - - // TODO(pcwalton): Do a better tessellation that doesn't make so many sliver triangles. - pub fn compute_domain(&mut self) { - for (b_quad_index, tess_levels) in self.tess_levels.iter().enumerate() { - let b_quad = &self.b_quads[b_quad_index as usize]; - - let upper_tess_level = f32::from(tess_levels.outer[1]) as u32; - let lower_tess_level = f32::from(tess_levels.outer[3]) as u32; - let tess_level = cmp::max(upper_tess_level, lower_tess_level); - - let path_id = self.b_vertices[b_quad.upper_left_vertex_index as usize].path_id; - - let first_upper_vertex_index = self.vertices.len() as u32; - self.vertices.extend((0..(tess_level + 1)).map(|index| { - Vertex::new(path_id, - b_quad.upper_left_vertex_index, - b_quad.upper_control_point_vertex_index, - b_quad.upper_right_vertex_index, - index as f32 / tess_level as f32) - })); - - let first_lower_vertex_index = self.vertices.len() as u32; - self.vertices.extend((0..(tess_level + 1)).map(|index| { - Vertex::new(path_id, - b_quad.lower_left_vertex_index, - b_quad.lower_control_point_vertex_index, - b_quad.lower_right_vertex_index, - index as f32 / tess_level as f32) - })); - - // Emit a triangle strip. - self.msaa_indices.reserve(tess_level as usize * 6); - for index in 0..tess_level { - self.msaa_indices.extend([ - first_upper_vertex_index + index + 0, - first_upper_vertex_index + index + 1, - first_lower_vertex_index + index + 0, - first_upper_vertex_index + index + 1, - first_lower_vertex_index + index + 1, - first_lower_vertex_index + index + 0, - ].into_iter()) - } - - // If ECAA is in use, then emit edge instances. - if self.antialiasing_mode == AntialiasingMode::Ecaa { - for index in 0..tess_level { - self.edge_instances.extend([ - EdgeInstance::new(first_upper_vertex_index + index + 0, - first_upper_vertex_index + index + 1), - EdgeInstance::new(first_lower_vertex_index + index + 0, - first_lower_vertex_index + index + 1) - ].into_iter()) - } - } - } - } - - #[inline] - pub fn tess_levels(&self) -> &[QuadTessLevels] { - &self.tess_levels - } - - #[inline] - pub fn vertices(&self) -> &[Vertex] { - &self.vertices - } - - #[inline] - pub fn msaa_indices(&self) -> &[u32] { - &self.msaa_indices - } - - #[inline] - pub fn edge_instances(&self) -> &[EdgeInstance] { - &self.edge_instances - } -} - -// http://antigrain.com/research/adaptive_bezier/ -fn tess_level_for_edge(left_endpoint_index: u32, - control_point_index: u32, - right_endpoint_index: u32, - transform: &Transform2D, - b_vertices: &[BVertex]) - -> u32 { - if control_point_index == u32::MAX { - return 1 - } - - let left_endpoint = &b_vertices[left_endpoint_index as usize].position; - let right_endpoint = &b_vertices[right_endpoint_index as usize].position; - let control_point = &b_vertices[control_point_index as usize].position; - - let p0 = transform.transform_point(left_endpoint); - let p1 = transform.transform_point(control_point); - let p2 = transform.transform_point(right_endpoint); - - // FIXME(pcwalton): Is this good for quadratics? - let length = (p1 - p0).length() + (p2 - p1).length(); - 1 + (length * TOLERANCE) as u32 -}