Split path IDs and Loop-Blinn data into separate VBOs

This commit is contained in:
Patrick Walton 2017-08-17 12:47:50 -07:00
parent 0a4d57580a
commit ec78a632dc
7 changed files with 160 additions and 125 deletions

View File

@ -14,10 +14,11 @@ const UINT32_SIZE: number = 4;
const B_POSITION_SIZE: number = 8; const B_POSITION_SIZE: number = 8;
const B_VERTEX_SIZE: number = 8; const B_PATH_INDEX_SIZE: number = 2;
const B_VERTEX_PATH_ID_OFFSET: number = 0;
const B_VERTEX_TEX_COORD_OFFSET: number = 4; const B_LOOP_BLINN_DATA_SIZE: number = 4;
const B_VERTEX_SIGN_OFFSET: number = 6; const B_LOOP_BLINN_DATA_TEX_COORD_OFFSET: number = 0;
const B_LOOP_BLINN_DATA_SIGN_OFFSET: number = 2;
const IDENTITY: Matrix4D = [ const IDENTITY: Matrix4D = [
1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0,
@ -249,7 +250,8 @@ function initQuadVAO(view: PathfinderView, attributes: any) {
interface Meshes<T> { interface Meshes<T> {
readonly bQuads: T; readonly bQuads: T;
readonly bVertexPositions: T; readonly bVertexPositions: T;
readonly bVertexInfo: T; readonly bVertexPathIDs: T;
readonly bVertexLoopBlinnData: T;
readonly coverInteriorIndices: T; readonly coverInteriorIndices: T;
readonly coverCurveIndices: T; readonly coverCurveIndices: T;
readonly edgeUpperLineIndices: T; readonly edgeUpperLineIndices: T;
@ -258,18 +260,19 @@ interface Meshes<T> {
readonly edgeLowerCurveIndices: T; readonly edgeLowerCurveIndices: T;
} }
type BufferType = number; type BufferType = 'ARRAY_BUFFER' | 'ELEMENT_ARRAY_BUFFER';
const BUFFER_TYPES: Meshes<BufferType> = { const BUFFER_TYPES: Meshes<BufferType> = {
bQuads: WebGLRenderingContext.ARRAY_BUFFER, bQuads: 'ARRAY_BUFFER',
bVertexPositions: WebGLRenderingContext.ARRAY_BUFFER, bVertexPositions: 'ARRAY_BUFFER',
bVertexInfo: WebGLRenderingContext.ARRAY_BUFFER, bVertexPathIDs: 'ARRAY_BUFFER',
coverInteriorIndices: WebGLRenderingContext.ELEMENT_ARRAY_BUFFER, bVertexLoopBlinnData: 'ARRAY_BUFFER',
coverCurveIndices: WebGLRenderingContext.ELEMENT_ARRAY_BUFFER, coverInteriorIndices: 'ELEMENT_ARRAY_BUFFER',
edgeUpperLineIndices: WebGLRenderingContext.ELEMENT_ARRAY_BUFFER, coverCurveIndices: 'ELEMENT_ARRAY_BUFFER',
edgeUpperCurveIndices: WebGLRenderingContext.ELEMENT_ARRAY_BUFFER, edgeUpperLineIndices: 'ELEMENT_ARRAY_BUFFER',
edgeLowerLineIndices: WebGLRenderingContext.ELEMENT_ARRAY_BUFFER, edgeUpperCurveIndices: 'ELEMENT_ARRAY_BUFFER',
edgeLowerCurveIndices: WebGLRenderingContext.ELEMENT_ARRAY_BUFFER, edgeLowerLineIndices: 'ELEMENT_ARRAY_BUFFER',
edgeLowerCurveIndices: 'ELEMENT_ARRAY_BUFFER',
}; };
class PathfinderMeshData implements Meshes<ArrayBuffer> { class PathfinderMeshData implements Meshes<ArrayBuffer> {
@ -284,7 +287,8 @@ class PathfinderMeshData implements Meshes<ArrayBuffer> {
readonly bQuads: ArrayBuffer; readonly bQuads: ArrayBuffer;
readonly bVertexPositions: ArrayBuffer; readonly bVertexPositions: ArrayBuffer;
readonly bVertexInfo: ArrayBuffer; readonly bVertexPathIDs: ArrayBuffer;
readonly bVertexLoopBlinnData: ArrayBuffer;
readonly coverInteriorIndices: ArrayBuffer; readonly coverInteriorIndices: ArrayBuffer;
readonly coverCurveIndices: ArrayBuffer; readonly coverCurveIndices: ArrayBuffer;
readonly edgeUpperLineIndices: ArrayBuffer; readonly edgeUpperLineIndices: ArrayBuffer;
@ -296,7 +300,7 @@ class PathfinderMeshData implements Meshes<ArrayBuffer> {
class PathfinderMeshBuffers implements Meshes<WebGLBuffer> { class PathfinderMeshBuffers implements Meshes<WebGLBuffer> {
constructor(gl: WebGLRenderingContext, meshData: PathfinderMeshData) { constructor(gl: WebGLRenderingContext, meshData: PathfinderMeshData) {
for (const bufferName of Object.keys(BUFFER_TYPES) as Array<keyof PathfinderMeshBuffers>) { for (const bufferName of Object.keys(BUFFER_TYPES) as Array<keyof PathfinderMeshBuffers>) {
const bufferType = BUFFER_TYPES[bufferName]; const bufferType = gl[BUFFER_TYPES[bufferName]];
const buffer = expectNotNull(gl.createBuffer(), "Failed to create buffer!"); const buffer = expectNotNull(gl.createBuffer(), "Failed to create buffer!");
gl.bindBuffer(bufferType, buffer); gl.bindBuffer(bufferType, buffer);
gl.bufferData(bufferType, meshData[bufferName], gl.STATIC_DRAW); gl.bufferData(bufferType, meshData[bufferName], gl.STATIC_DRAW);
@ -306,7 +310,8 @@ class PathfinderMeshBuffers implements Meshes<WebGLBuffer> {
readonly bQuads: WebGLBuffer; readonly bQuads: WebGLBuffer;
readonly bVertexPositions: WebGLBuffer; readonly bVertexPositions: WebGLBuffer;
readonly bVertexInfo: WebGLBuffer; readonly bVertexPathIDs: WebGLBuffer;
readonly bVertexLoopBlinnData: WebGLBuffer;
readonly coverInteriorIndices: WebGLBuffer; readonly coverInteriorIndices: WebGLBuffer;
readonly coverCurveIndices: WebGLBuffer; readonly coverCurveIndices: WebGLBuffer;
readonly edgeUpperLineIndices: WebGLBuffer; readonly edgeUpperLineIndices: WebGLBuffer;
@ -563,13 +568,13 @@ class PathfinderView {
false, false,
0, 0,
0); 0);
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.meshes.bVertexInfo); this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.meshes.bVertexPathIDs);
this.gl.vertexAttribPointer(directInteriorProgram.attributes.aPathID, this.gl.vertexAttribPointer(directInteriorProgram.attributes.aPathID,
1, 1,
this.gl.UNSIGNED_SHORT, // FIXME(pcwalton) this.gl.UNSIGNED_SHORT,
false, false,
B_VERTEX_SIZE, 0,
B_VERTEX_PATH_ID_OFFSET); 0);
this.gl.enableVertexAttribArray(directInteriorProgram.attributes.aPosition); this.gl.enableVertexAttribArray(directInteriorProgram.attributes.aPosition);
this.gl.enableVertexAttribArray(directInteriorProgram.attributes.aPathID); this.gl.enableVertexAttribArray(directInteriorProgram.attributes.aPathID);
this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, this.meshes.coverInteriorIndices); this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, this.meshes.coverInteriorIndices);
@ -605,25 +610,26 @@ class PathfinderView {
false, false,
0, 0,
0); 0);
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.meshes.bVertexInfo); this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.meshes.bVertexPathIDs);
this.gl.vertexAttribPointer(directCurveProgram.attributes.aPathID,
1,
this.gl.UNSIGNED_SHORT,
false,
0,
0);
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.meshes.bVertexLoopBlinnData);
this.gl.vertexAttribPointer(directCurveProgram.attributes.aTexCoord, this.gl.vertexAttribPointer(directCurveProgram.attributes.aTexCoord,
2, 2,
this.gl.UNSIGNED_BYTE, this.gl.UNSIGNED_BYTE,
false, false,
B_VERTEX_SIZE, B_LOOP_BLINN_DATA_SIZE,
B_VERTEX_TEX_COORD_OFFSET); B_LOOP_BLINN_DATA_TEX_COORD_OFFSET);
this.gl.vertexAttribPointer(directCurveProgram.attributes.aPathID,
1,
this.gl.UNSIGNED_SHORT, // FIXME(pcwalton)
false,
B_VERTEX_SIZE,
B_VERTEX_PATH_ID_OFFSET);
this.gl.vertexAttribPointer(directCurveProgram.attributes.aSign, this.gl.vertexAttribPointer(directCurveProgram.attributes.aSign,
1, 1,
this.gl.BYTE, this.gl.BYTE,
false, false,
B_VERTEX_SIZE, B_LOOP_BLINN_DATA_SIZE,
B_VERTEX_SIGN_OFFSET); B_LOOP_BLINN_DATA_SIGN_OFFSET);
this.gl.enableVertexAttribArray(directCurveProgram.attributes.aPosition); this.gl.enableVertexAttribArray(directCurveProgram.attributes.aPosition);
this.gl.enableVertexAttribArray(directCurveProgram.attributes.aTexCoord); this.gl.enableVertexAttribArray(directCurveProgram.attributes.aTexCoord);
this.gl.enableVertexAttribArray(directCurveProgram.attributes.aPathID); this.gl.enableVertexAttribArray(directCurveProgram.attributes.aPathID);

View File

@ -119,8 +119,10 @@ struct PartitionFontResponse {
bQuads: String, bQuads: String,
// Base64-encoded `bincode`-encoded `Point2D<f32>`s. // Base64-encoded `bincode`-encoded `Point2D<f32>`s.
bVertexPositions: String, bVertexPositions: String,
// Base64-encoded `bincode`-encoded `BVertexInfo`s. // Base64-encoded `bincode`-encoded `u16`s.
bVertexInfo: String, bVertexPathIDs: String,
// Base64-encoded `bincode`-encoded `BVertexLoopBlinnData`s.
bVertexLoopBlinnData: String,
// Base64-encoded `u32`s. // Base64-encoded `u32`s.
coverInteriorIndices: String, coverInteriorIndices: String,
// Base64-encoded `u32`s. // Base64-encoded `u32`s.
@ -195,7 +197,8 @@ fn partition_font(request: Json<PartitionFontRequest>)
// Partition the decoded glyph outlines. // Partition the decoded glyph outlines.
let mut partitioner = Partitioner::new(); let mut partitioner = Partitioner::new();
let (mut b_quads, mut b_vertex_positions, mut b_vertex_info) = (vec![], vec![], vec![]); let (mut b_quads, mut b_vertex_positions) = (vec![], vec![]);
let (mut b_vertex_path_ids, mut b_vertex_loop_blinn_data) = (vec![], vec![]);
let (mut cover_interior_indices, mut cover_curve_indices) = (vec![], vec![]); let (mut cover_interior_indices, mut cover_curve_indices) = (vec![], vec![]);
let (mut edge_upper_line_indices, mut edge_upper_curve_indices) = (vec![], vec![]); let (mut edge_upper_line_indices, mut edge_upper_curve_indices) = (vec![], vec![]);
let (mut edge_lower_line_indices, mut edge_lower_curve_indices) = (vec![], vec![]); let (mut edge_lower_line_indices, mut edge_lower_curve_indices) = (vec![], vec![]);
@ -224,27 +227,30 @@ fn partition_font(request: Json<PartitionFontRequest>)
} }
}; };
partitioner.partition((path_index + 1) as u32, partitioner.partition((path_index + 1) as u16,
decoded_outline_indices.subpath_indices.start as u32, decoded_outline_indices.subpath_indices.start as u32,
decoded_outline_indices.subpath_indices.end as u32); decoded_outline_indices.subpath_indices.end as u32);
let path_b_quads = partitioner.b_quads(); let path_b_quads = partitioner.b_quads();
let path_b_vertex_positions = partitioner.b_vertex_positions(); let path_b_vertex_positions = partitioner.b_vertex_positions();
let path_b_vertex_info = partitioner.b_vertex_info(); let path_b_vertex_path_ids = partitioner.b_vertex_path_ids();
let path_b_vertex_loop_blinn_data = partitioner.b_vertex_loop_blinn_data();
let cover_indices = partitioner.cover_indices(); let cover_indices = partitioner.cover_indices();
let edge_indices = partitioner.edge_indices(); let edge_indices = partitioner.edge_indices();
IndexRange::from_vector_append_and_serialization(&mut b_vertex_positions, IndexRange::from_vector_append_and_serialization(&mut b_vertex_positions,
path_b_vertex_positions).unwrap(); path_b_vertex_positions).unwrap();
IndexRange::from_vector_append_and_serialization(&mut b_vertex_path_ids,
path_b_vertex_path_ids).unwrap();
glyph_info.push(PartitionGlyphInfo { glyph_info.push(PartitionGlyphInfo {
id: glyph_id, id: glyph_id,
dimensions: dimensions, dimensions: dimensions,
bQuadIndices: IndexRange::from_vector_append_and_serialization(&mut b_quads, bQuadIndices: IndexRange::from_vector_append_and_serialization(&mut b_quads,
path_b_quads).unwrap(), path_b_quads).unwrap(),
bVertexIndices: bVertexIndices: IndexRange::from_vector_append_and_serialization(
IndexRange::from_vector_append_and_serialization(&mut b_vertex_info, &mut b_vertex_loop_blinn_data,
path_b_vertex_info).unwrap(), path_b_vertex_loop_blinn_data).unwrap(),
coverInteriorIndices: IndexRange::from_vector_append_and_serialization( coverInteriorIndices: IndexRange::from_vector_append_and_serialization(
&mut cover_interior_indices, &mut cover_interior_indices,
cover_indices.interior_indices).unwrap(), cover_indices.interior_indices).unwrap(),
@ -271,7 +277,8 @@ fn partition_font(request: Json<PartitionFontRequest>)
glyphInfo: glyph_info, glyphInfo: glyph_info,
bQuads: base64::encode(&b_quads), bQuads: base64::encode(&b_quads),
bVertexPositions: base64::encode(&b_vertex_positions), bVertexPositions: base64::encode(&b_vertex_positions),
bVertexInfo: base64::encode(&b_vertex_info), bVertexPathIDs: base64::encode(&b_vertex_path_ids),
bVertexLoopBlinnData: base64::encode(&b_vertex_loop_blinn_data),
coverInteriorIndices: base64::encode(&cover_interior_indices), coverInteriorIndices: base64::encode(&cover_interior_indices),
coverCurveIndices: base64::encode(&cover_curve_indices), coverCurveIndices: base64::encode(&cover_curve_indices),
edgeUpperLineIndices: base64::encode(&edge_upper_line_indices), edgeUpperLineIndices: base64::encode(&edge_upper_line_indices),

View File

@ -6,7 +6,7 @@ use legalizer::Legalizer;
use partitioner::Partitioner; use partitioner::Partitioner;
use std::mem; use std::mem;
use std::slice; use std::slice;
use {BQuad, BVertexInfo, CurveIndices, Endpoint, LineIndices, Subpath}; use {BQuad, BVertexLoopBlinnData, CurveIndices, Endpoint, LineIndices, Subpath};
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
#[repr(C)] #[repr(C)]
@ -166,7 +166,7 @@ pub unsafe extern fn pf_partitioner_init<'a>(partitioner: *mut Partitioner<'a>,
#[no_mangle] #[no_mangle]
pub unsafe extern fn pf_partitioner_partition<'a>(partitioner: *mut Partitioner<'a>, pub unsafe extern fn pf_partitioner_partition<'a>(partitioner: *mut Partitioner<'a>,
path_id: u32, path_id: u16,
first_subpath_index: u32, first_subpath_index: u32,
last_subpath_index: u32) { last_subpath_index: u32) {
(*partitioner).partition(path_id, first_subpath_index, last_subpath_index) (*partitioner).partition(path_id, first_subpath_index, last_subpath_index)
@ -195,14 +195,26 @@ pub unsafe extern fn pf_partitioner_b_vertex_positions<'a>(partitioner: *const P
} }
#[no_mangle] #[no_mangle]
pub unsafe extern fn pf_partitioner_b_vertex_info<'a>(partitioner: *const Partitioner<'a>, pub unsafe extern fn pf_partitioner_b_vertex_path_ids<'a>(partitioner: *const Partitioner<'a>,
out_b_vertex_count: *mut u32) out_b_vertex_count: *mut u32)
-> *const BVertexInfo { -> *const u16 {
let b_vertex_info = (*partitioner).b_vertex_info(); let b_vertex_path_ids = (*partitioner).b_vertex_path_ids();
if !out_b_vertex_count.is_null() { if !out_b_vertex_count.is_null() {
*out_b_vertex_count = b_vertex_info.len() as u32 *out_b_vertex_count = b_vertex_path_ids.len() as u32
} }
b_vertex_info.as_ptr() as *const BVertexInfo b_vertex_path_ids.as_ptr() as *const u16
}
#[no_mangle]
pub unsafe extern fn pf_partitioner_b_vertex_loop_blinn_data<'a>(
partitioner: *const Partitioner<'a>,
out_b_vertex_count: *mut u32)
-> *const BVertexLoopBlinnData {
let b_vertex_loop_blinn_data = (*partitioner).b_vertex_loop_blinn_data();
if !out_b_vertex_count.is_null() {
*out_b_vertex_count = b_vertex_loop_blinn_data.len() as u32
}
b_vertex_loop_blinn_data.as_ptr() as *const BVertexLoopBlinnData
} }
#[no_mangle] #[no_mangle]

View File

@ -91,24 +91,22 @@ pub(crate) enum BVertexKind {
#[derive(Clone, Copy, Debug, Serialize, Deserialize)] #[derive(Clone, Copy, Debug, Serialize, Deserialize)]
#[repr(C)] #[repr(C)]
pub struct BVertexInfo { pub struct BVertexLoopBlinnData {
pub path_id: u32,
pub tex_coord: [u8; 2], pub tex_coord: [u8; 2],
pub sign: i8, pub sign: i8,
pad: u8, pad: u8,
} }
impl BVertexInfo { impl BVertexLoopBlinnData {
#[inline] #[inline]
pub(crate) fn new(kind: BVertexKind, path_id: u32) -> BVertexInfo { pub(crate) fn new(kind: BVertexKind) -> BVertexLoopBlinnData {
let (tex_coord, sign) = match kind { let (tex_coord, sign) = match kind {
BVertexKind::Endpoint0 => ([0, 0], 0), BVertexKind::Endpoint0 => ([0, 0], 0),
BVertexKind::Endpoint1 => ([2, 2], 0), BVertexKind::Endpoint1 => ([2, 2], 0),
BVertexKind::ConcaveControlPoint => ([1, 0], 1), BVertexKind::ConcaveControlPoint => ([1, 0], 1),
BVertexKind::ConvexControlPoint => ([1, 0], -1), BVertexKind::ConvexControlPoint => ([1, 0], -1),
}; };
BVertexInfo { BVertexLoopBlinnData {
path_id: path_id,
tex_coord: tex_coord, tex_coord: tex_coord,
sign: sign, sign: sign,
pad: 0, pad: 0,
@ -118,9 +116,8 @@ impl BVertexInfo {
pub(crate) fn control_point(left_endpoint_position: &Point2D<f32>, pub(crate) fn control_point(left_endpoint_position: &Point2D<f32>,
control_point_position: &Point2D<f32>, control_point_position: &Point2D<f32>,
right_endpoint_position: &Point2D<f32>, right_endpoint_position: &Point2D<f32>,
path_id: u32,
bottom: bool) bottom: bool)
-> BVertexInfo { -> BVertexLoopBlinnData {
let control_point_vector = *control_point_position - *left_endpoint_position; let control_point_vector = *control_point_position - *left_endpoint_position;
let right_vector = *right_endpoint_position - *left_endpoint_position; let right_vector = *right_endpoint_position - *left_endpoint_position;
let determinant = right_vector.cross(control_point_vector); let determinant = right_vector.cross(control_point_vector);
@ -129,7 +126,7 @@ impl BVertexInfo {
} else { } else {
BVertexKind::ConcaveControlPoint BVertexKind::ConcaveControlPoint
}; };
BVertexInfo::new(endpoint_kind, path_id) BVertexLoopBlinnData::new(endpoint_kind)
} }
} }

View File

@ -6,15 +6,10 @@
#include <limits.h> #include <limits.h>
#include <stdint.h> #include <stdint.h>
#define PF_ANTIALIASING_MODE_MSAA 0
#define PF_ANTIALIASING_MODE_ECAA 1
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
typedef uint8_t pf_antialiasing_mode_t;
typedef uint16_t pf_float16_t; typedef uint16_t pf_float16_t;
struct pf_point2d_f32 { struct pf_point2d_f32 {
@ -30,14 +25,13 @@ struct pf_matrix2d_f32 {
typedef struct pf_matrix2d_f32 pf_matrix2d_f32_t; typedef struct pf_matrix2d_f32 pf_matrix2d_f32_t;
struct pf_b_vertex_info { struct pf_b_vertex_loop_blinn_data {
uint32_t path_id;
uint8_t tex_coord[2]; uint8_t tex_coord[2];
int8_t sign; int8_t sign;
uint8_t pad; uint8_t pad;
}; };
typedef struct pf_b_vertex_info pf_b_vertex_info_t; typedef struct pf_b_vertex_loop_blinn_data pf_b_vertex_loop_blinn_data_t;
struct pf_cover_indices { struct pf_cover_indices {
const uint32_t *interior_indices; const uint32_t *interior_indices;
@ -154,7 +148,7 @@ void pf_partitioner_init(pf_partitioner_t *partitioner,
uint32_t subpath_count); uint32_t subpath_count);
void pf_partitioner_partition(pf_partitioner_t *partitioner, void pf_partitioner_partition(pf_partitioner_t *partitioner,
uint32_t path_id, uint16_t path_id,
uint32_t first_subpath_index, uint32_t first_subpath_index,
uint32_t last_subpath_index); uint32_t last_subpath_index);
@ -164,7 +158,11 @@ const pf_b_quad_t *pf_partitioner_b_quads(const pf_partitioner_t *partitioner,
const pf_point2d_f32_t *pf_partitioner_b_vertex_positions(const pf_partitioner_t *partitioner, const pf_point2d_f32_t *pf_partitioner_b_vertex_positions(const pf_partitioner_t *partitioner,
uint32_t *out_b_vertex_count); uint32_t *out_b_vertex_count);
const pf_b_vertex_info_t *pf_partitioner_b_vertex_info(const pf_partitioner_t *partitioner, const uint16_t *pf_partitioner_b_vertex_path_ids(const pf_partitioner_t *partitioner,
uint32_t *out_b_vertex_count);
const pf_b_vertex_loop_blinn_data_t *pf_partitioner_b_vertex_loop_blinn_data(
const pf_partitioner_t *partitioner,
uint32_t *out_b_vertex_count); uint32_t *out_b_vertex_count);
const void pf_partitioner_cover_indices(const pf_partitioner_t *partitioner, const void pf_partitioner_cover_indices(const pf_partitioner_t *partitioner,

View File

@ -7,8 +7,9 @@ use log::LogLevel;
use std::collections::BinaryHeap; use std::collections::BinaryHeap;
use std::cmp::Ordering; use std::cmp::Ordering;
use std::f32; use std::f32;
use std::iter;
use std::u32; use std::u32;
use {BQuad, BVertexInfo, BVertexKind, CurveIndices, Endpoint, LineIndices, Subpath}; use {BQuad, BVertexLoopBlinnData, BVertexKind, CurveIndices, Endpoint, LineIndices, Subpath};
pub struct Partitioner<'a> { pub struct Partitioner<'a> {
endpoints: &'a [Endpoint], endpoints: &'a [Endpoint],
@ -17,14 +18,15 @@ pub struct Partitioner<'a> {
b_quads: Vec<BQuad>, b_quads: Vec<BQuad>,
b_vertex_positions: Vec<Point2D<f32>>, b_vertex_positions: Vec<Point2D<f32>>,
b_vertex_info: Vec<BVertexInfo>, b_vertex_path_ids: Vec<u16>,
b_vertex_loop_blinn_data: Vec<BVertexLoopBlinnData>,
cover_indices: CoverIndicesBuffer, cover_indices: CoverIndicesBuffer,
edge_indices: EdgeIndicesBuffer, edge_indices: EdgeIndicesBuffer,
heap: BinaryHeap<Point>, heap: BinaryHeap<Point>,
visited_points: BitVec, visited_points: BitVec,
active_edges: Vec<ActiveEdge>, active_edges: Vec<ActiveEdge>,
path_id: u32, path_id: u16,
} }
impl<'a> Partitioner<'a> { impl<'a> Partitioner<'a> {
@ -37,7 +39,8 @@ impl<'a> Partitioner<'a> {
b_quads: vec![], b_quads: vec![],
b_vertex_positions: vec![], b_vertex_positions: vec![],
b_vertex_info: vec![], b_vertex_path_ids: vec![],
b_vertex_loop_blinn_data: vec![],
cover_indices: CoverIndicesBuffer::new(), cover_indices: CoverIndicesBuffer::new(),
edge_indices: EdgeIndicesBuffer::new(), edge_indices: EdgeIndicesBuffer::new(),
@ -61,9 +64,10 @@ impl<'a> Partitioner<'a> {
self.visited_points = BitVec::from_elem(self.endpoints.len(), false); self.visited_points = BitVec::from_elem(self.endpoints.len(), false);
} }
pub fn partition(&mut self, path_id: u32, first_subpath_index: u32, last_subpath_index: u32) { pub fn partition(&mut self, path_id: u16, first_subpath_index: u32, last_subpath_index: u32) {
self.b_quads.clear(); self.b_quads.clear();
self.b_vertex_info.clear(); self.b_vertex_loop_blinn_data.clear();
self.b_vertex_path_ids.clear();
self.b_vertex_positions.clear(); self.b_vertex_positions.clear();
self.cover_indices.clear(); self.cover_indices.clear();
self.edge_indices.clear(); self.edge_indices.clear();
@ -88,8 +92,13 @@ impl<'a> Partitioner<'a> {
} }
#[inline] #[inline]
pub fn b_vertex_info(&self) -> &[BVertexInfo] { pub fn b_vertex_path_ids(&self) -> &[u16] {
&self.b_vertex_info &self.b_vertex_path_ids
}
#[inline]
pub fn b_vertex_loop_blinn_data(&self) -> &[BVertexLoopBlinnData] {
&self.b_vertex_loop_blinn_data
} }
#[inline] #[inline]
@ -180,13 +189,15 @@ impl<'a> Partitioner<'a> {
{ {
let active_edge = &mut self.active_edges[active_edge_index as usize]; let active_edge = &mut self.active_edges[active_edge_index as usize];
active_edge.left_vertex_index = self.b_vertex_info.len() as u32; active_edge.left_vertex_index = self.b_vertex_loop_blinn_data.len() as u32;
active_edge.control_point_vertex_index = active_edge.left_vertex_index + 1; active_edge.control_point_vertex_index = active_edge.left_vertex_index + 1;
let endpoint_position = self.endpoints[active_edge.right_endpoint_index as usize] let endpoint_position = self.endpoints[active_edge.right_endpoint_index as usize]
.position; .position;
self.b_vertex_positions.push(endpoint_position); self.b_vertex_positions.push(endpoint_position);
self.b_vertex_info.push(BVertexInfo::new(active_edge.endpoint_kind(), self.path_id)); self.b_vertex_path_ids.push(self.path_id);
self.b_vertex_loop_blinn_data.push(BVertexLoopBlinnData::new(
active_edge.endpoint_kind()));
active_edge.toggle_parity(); active_edge.toggle_parity();
@ -214,19 +225,19 @@ impl<'a> Partitioner<'a> {
} }
control_point_index => { control_point_index => {
self.active_edges[active_edge_index as usize].control_point_vertex_index = self.active_edges[active_edge_index as usize].control_point_vertex_index =
self.b_vertex_info.len() as u32; self.b_vertex_loop_blinn_data.len() as u32;
let left_vertex_index = self.active_edges[active_edge_index as usize] let left_vertex_index = self.active_edges[active_edge_index as usize]
.left_vertex_index; .left_vertex_index;
let control_point_position = &self.control_points[control_point_index as usize]; let control_point_position = &self.control_points[control_point_index as usize];
let control_point_b_vertex_info = BVertexInfo::control_point( let control_point_b_vertex_loop_blinn_data = BVertexLoopBlinnData::control_point(
&self.b_vertex_positions[left_vertex_index as usize], &self.b_vertex_positions[left_vertex_index as usize],
&control_point_position, &control_point_position,
&new_point.position, &new_point.position,
self.path_id,
bottom); bottom);
self.b_vertex_positions.push(*control_point_position); self.b_vertex_positions.push(*control_point_position);
self.b_vertex_info.push(control_point_b_vertex_info); self.b_vertex_path_ids.push(self.path_id);
self.b_vertex_loop_blinn_data.push(control_point_b_vertex_loop_blinn_data);
} }
} }
} }
@ -280,13 +291,14 @@ impl<'a> Partitioner<'a> {
let new_active_edges = &mut self.active_edges[next_active_edge_index as usize.. let new_active_edges = &mut self.active_edges[next_active_edge_index as usize..
next_active_edge_index as usize + 2]; next_active_edge_index as usize + 2];
let left_vertex_index = self.b_vertex_info.len() as u32; let left_vertex_index = self.b_vertex_loop_blinn_data.len() as u32;
new_active_edges[0].left_vertex_index = left_vertex_index; new_active_edges[0].left_vertex_index = left_vertex_index;
new_active_edges[1].left_vertex_index = left_vertex_index; new_active_edges[1].left_vertex_index = left_vertex_index;
let position = self.endpoints[endpoint_index as usize].position; let position = self.endpoints[endpoint_index as usize].position;
self.b_vertex_positions.push(position); self.b_vertex_positions.push(position);
self.b_vertex_info.push(BVertexInfo::new(BVertexKind::Endpoint0, self.path_id)); self.b_vertex_path_ids.push(self.path_id);
self.b_vertex_loop_blinn_data.push(BVertexLoopBlinnData::new(BVertexKind::Endpoint0));
new_active_edges[0].toggle_parity(); new_active_edges[0].toggle_parity();
new_active_edges[1].toggle_parity(); new_active_edges[1].toggle_parity();
@ -322,40 +334,42 @@ impl<'a> Partitioner<'a> {
match upper_control_point_index { match upper_control_point_index {
u32::MAX => new_active_edges[0].control_point_vertex_index = u32::MAX, u32::MAX => new_active_edges[0].control_point_vertex_index = u32::MAX,
upper_control_point_index => { upper_control_point_index => {
new_active_edges[0].control_point_vertex_index = self.b_vertex_info.len() as u32; new_active_edges[0].control_point_vertex_index =
self.b_vertex_loop_blinn_data.len() as u32;
let control_point_position = let control_point_position =
self.control_points[upper_control_point_index as usize]; self.control_points[upper_control_point_index as usize];
let right_vertex_position = let right_vertex_position =
self.endpoints[new_active_edges[0].right_endpoint_index as usize].position; self.endpoints[new_active_edges[0].right_endpoint_index as usize].position;
let control_point_b_vertex_info = let control_point_b_vertex_loop_blinn_data =
BVertexInfo::control_point(&position, BVertexLoopBlinnData::control_point(&position,
&control_point_position, &control_point_position,
&right_vertex_position, &right_vertex_position,
self.path_id,
false); false);
self.b_vertex_positions.push(control_point_position); self.b_vertex_positions.push(control_point_position);
self.b_vertex_info.push(control_point_b_vertex_info); self.b_vertex_path_ids.push(self.path_id);
self.b_vertex_loop_blinn_data.push(control_point_b_vertex_loop_blinn_data);
} }
} }
match lower_control_point_index { match lower_control_point_index {
u32::MAX => new_active_edges[1].control_point_vertex_index = u32::MAX, u32::MAX => new_active_edges[1].control_point_vertex_index = u32::MAX,
lower_control_point_index => { lower_control_point_index => {
new_active_edges[1].control_point_vertex_index = self.b_vertex_info.len() as u32; new_active_edges[1].control_point_vertex_index =
self.b_vertex_loop_blinn_data.len() as u32;
let control_point_position = let control_point_position =
self.control_points[lower_control_point_index as usize]; self.control_points[lower_control_point_index as usize];
let right_vertex_position = let right_vertex_position =
self.endpoints[new_active_edges[1].right_endpoint_index as usize].position; self.endpoints[new_active_edges[1].right_endpoint_index as usize].position;
let control_point_b_vertex_info = let control_point_b_vertex_loop_blinn_data =
BVertexInfo::control_point(&position, BVertexLoopBlinnData::control_point(&position,
&control_point_position, &control_point_position,
&right_vertex_position, &right_vertex_position,
self.path_id,
true); true);
self.b_vertex_positions.push(control_point_position); self.b_vertex_positions.push(control_point_position);
self.b_vertex_info.push(control_point_b_vertex_info); self.b_vertex_path_ids.push(self.path_id);
self.b_vertex_loop_blinn_data.push(control_point_b_vertex_loop_blinn_data);
} }
} }
} }
@ -433,8 +447,8 @@ impl<'a> Partitioner<'a> {
// NB: Order is important here—we depend on the provoking vertex! // NB: Order is important here—we depend on the provoking vertex!
let upper_shape = upper_curve.shape(&self.b_vertex_info); let upper_shape = upper_curve.shape(&self.b_vertex_loop_blinn_data);
let lower_shape = lower_curve.shape(&self.b_vertex_info); let lower_shape = lower_curve.shape(&self.b_vertex_loop_blinn_data);
match upper_shape { match upper_shape {
Shape::Flat => { Shape::Flat => {
@ -757,15 +771,17 @@ impl<'a> Partitioner<'a> {
let left_curve_control_point_vertex_index; let left_curve_control_point_vertex_index;
match active_edge.control_point_vertex_index { match active_edge.control_point_vertex_index {
u32::MAX => { u32::MAX => {
let path_id = self.b_vertex_info[left_curve_left as usize].path_id; let path_id = self.b_vertex_path_ids[left_curve_left as usize];
let left_point_position = self.b_vertex_positions[left_curve_left as usize]; let left_point_position = self.b_vertex_positions[left_curve_left as usize];
let right_point = self.endpoints[active_edge.right_endpoint_index as usize] let right_point = self.endpoints[active_edge.right_endpoint_index as usize]
.position; .position;
let middle_point = left_point_position.to_vector().lerp(right_point.to_vector(), t); let middle_point = left_point_position.to_vector().lerp(right_point.to_vector(), t);
active_edge.left_vertex_index = self.b_vertex_info.len() as u32; active_edge.left_vertex_index = self.b_vertex_loop_blinn_data.len() as u32;
self.b_vertex_positions.push(middle_point.to_point()); self.b_vertex_positions.push(middle_point.to_point());
self.b_vertex_info.push(BVertexInfo::new(active_edge.endpoint_kind(), path_id)); self.b_vertex_path_ids.push(path_id);
self.b_vertex_loop_blinn_data
.push(BVertexLoopBlinnData::new(active_edge.endpoint_kind()));
active_edge.toggle_parity(); active_edge.toggle_parity();
@ -782,7 +798,7 @@ impl<'a> Partitioner<'a> {
&self.b_vertex_positions[active_edge.control_point_vertex_index as usize], &self.b_vertex_positions[active_edge.control_point_vertex_index as usize],
&right_endpoint_position); &right_endpoint_position);
left_curve_control_point_vertex_index = self.b_vertex_info.len() as u32; left_curve_control_point_vertex_index = self.b_vertex_loop_blinn_data.len() as u32;
active_edge.left_vertex_index = left_curve_control_point_vertex_index + 1; active_edge.left_vertex_index = left_curve_control_point_vertex_index + 1;
active_edge.control_point_vertex_index = left_curve_control_point_vertex_index + 2; active_edge.control_point_vertex_index = left_curve_control_point_vertex_index + 2;
@ -791,17 +807,16 @@ impl<'a> Partitioner<'a> {
subdivided_quadratic_bezier.ap2bp0, subdivided_quadratic_bezier.ap2bp0,
subdivided_quadratic_bezier.bp1, subdivided_quadratic_bezier.bp1,
].into_iter()); ].into_iter());
self.b_vertex_info.extend([ self.b_vertex_path_ids.extend(iter::repeat(self.path_id).take(3));
BVertexInfo::control_point(&left_endpoint_position, self.b_vertex_loop_blinn_data.extend([
BVertexLoopBlinnData::control_point(&left_endpoint_position,
&subdivided_quadratic_bezier.ap1, &subdivided_quadratic_bezier.ap1,
&subdivided_quadratic_bezier.ap2bp0, &subdivided_quadratic_bezier.ap2bp0,
self.path_id,
bottom), bottom),
BVertexInfo::new(active_edge.endpoint_kind(), self.path_id), BVertexLoopBlinnData::new(active_edge.endpoint_kind()),
BVertexInfo::control_point(&subdivided_quadratic_bezier.ap2bp0, BVertexLoopBlinnData::control_point(&subdivided_quadratic_bezier.ap2bp0,
&subdivided_quadratic_bezier.bp1, &subdivided_quadratic_bezier.bp1,
&right_endpoint_position, &right_endpoint_position,
self.path_id,
bottom), bottom),
].into_iter()); ].into_iter());
@ -1015,10 +1030,10 @@ struct SubdividedActiveEdge {
} }
impl SubdividedActiveEdge { impl SubdividedActiveEdge {
fn shape(&self, b_vertex_info: &[BVertexInfo]) -> Shape { fn shape(&self, b_vertex_loop_blinn_data: &[BVertexLoopBlinnData]) -> Shape {
if self.left_curve_control_point == u32::MAX { if self.left_curve_control_point == u32::MAX {
Shape::Flat Shape::Flat
} else if b_vertex_info[self.left_curve_control_point as usize].sign < 0 { } else if b_vertex_loop_blinn_data[self.left_curve_control_point as usize].sign < 0 {
Shape::Convex Shape::Convex
} else { } else {
Shape::Concave Shape::Concave

View File

@ -7,9 +7,9 @@ precision highp float;
uniform mat4 uTransform; uniform mat4 uTransform;
uniform ivec2 uFramebufferSize; uniform ivec2 uFramebufferSize;
uniform ivec2 uBVertexPositionDimensions; uniform ivec2 uBVertexPositionDimensions;
uniform ivec2 uBVertexInfoDimensions; uniform ivec2 uBVertexPathIDDimensions;
uniform sampler2D uBVertexPosition; uniform sampler2D uBVertexPosition;
uniform sampler2D uBVertexInfo; uniform sampler2D uBVertexPathID;
attribute vec2 aQuadPosition; attribute vec2 aQuadPosition;
attribute vec3 aUpperPointIndices; attribute vec3 aUpperPointIndices;
@ -48,7 +48,7 @@ void main() {
vec4 roundedExtents = vec4(floor(extents.xy), ceil(extents.zw)); vec4 roundedExtents = vec4(floor(extents.xy), ceil(extents.zw));
int pathID = fetchUInt16Data(uBVertexInfo, pointIndices.x, uBVertexInfoDimensions); int pathID = fetchUInt16Data(uBVertexPathID, pointIndices.x, uBVertexPathIDDimensions);
vec2 position = mix(roundedExtents.xy, roundedExtents.zw, aQuadPosition); vec2 position = mix(roundedExtents.xy, roundedExtents.zw, aQuadPosition);
position = convertScreenToClipSpace(position, uFramebufferSize); position = convertScreenToClipSpace(position, uFramebufferSize);