Rename `partitionfinder` to `partitioner` and remove the old tessellator

This commit is contained in:
Patrick Walton 2017-08-08 11:32:51 -07:00
parent ef040b61bf
commit 95b356435e
11 changed files with 8 additions and 396 deletions

View File

@ -1,10 +1,10 @@
[package]
name = "partitionfinder"
name = "pathfinder_partitioner"
version = "0.1.0"
authors = ["Patrick Walton <pcwalton@mimiga.net>"]
[lib]
name = "partitionfinder"
name = "pathfinder_partitioner"
crate-type = ["dylib", "rlib"]
[dependencies]

View File

@ -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>>(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<f32>` 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

View File

@ -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,
}
}
}

View File

@ -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 <limits.h>
#include <stdint.h>
@ -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

View File

@ -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};

View File

@ -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<QuadTessLevels>,
vertices: Vec<Vertex>,
msaa_indices: Vec<u32>,
edge_instances: Vec<EdgeInstance>,
}
// 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<f32>) {
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<f32>,
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
}