Use regular VBOs instead of textures to store vertex positions for ECAA.

This improves performance at small font sizes a bit by reducing vertex
shading load.
This commit is contained in:
Patrick Walton 2017-10-06 16:11:53 -07:00
parent 6a7c013e61
commit 2a236319d4
14 changed files with 521 additions and 474 deletions

View File

@ -18,6 +18,7 @@ import {SubpixelAAType} from "./aa-strategy";
import {DemoAppController} from "./app-controller";
import PathfinderBufferTexture from "./buffer-texture";
import {PerspectiveCamera} from "./camera";
import {UniformMap} from './gl-utils';
import {PathfinderMeshData} from "./meshes";
import {ShaderMap, ShaderProgramSource} from "./shader-loader";
import SSAAStrategy from "./ssaa-strategy";
@ -25,7 +26,6 @@ import {BUILTIN_FONT_URI, ExpandedMeshData} from "./text";
import {GlyphStore, Hint, PathfinderFont, TextFrame, TextRun} from "./text";
import {assert, panic, PathfinderError, unwrapNull} from "./utils";
import {DemoView, Timings} from "./view";
import { UniformMap } from './gl-utils';
const TEXT_AVAILABLE_WIDTH: number = 150000;
const TEXT_PADDING: number = 2000;

View File

@ -18,6 +18,7 @@ import {AppController, DemoAppController} from "./app-controller";
import PathfinderBufferTexture from './buffer-texture';
import {OrthographicCamera} from './camera';
import {ECAAMonochromeStrategy, ECAAStrategy} from './ecaa-strategy';
import {UniformMap} from './gl-utils';
import {PathfinderMeshData} from "./meshes";
import {ShaderMap, ShaderProgramSource} from "./shader-loader";
import SSAAStrategy from './ssaa-strategy';
@ -25,7 +26,6 @@ import {BUILTIN_FONT_URI, ExpandedMeshData, GlyphStore, PathfinderFont, TextFram
import {TextRun} from "./text";
import {assert, PathfinderError, unwrapNull, unwrapUndef} from "./utils";
import {DemoView, MonochromeDemoView, Timings } from "./view";
import { UniformMap } from './gl-utils';
const STRING: string = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";

View File

@ -17,7 +17,7 @@ import {createFramebufferDepthTexture, setTextureParameters, UniformMap} from '.
import {WebGLVertexArrayObject} from './gl-utils';
import {B_QUAD_LOWER_INDICES_OFFSET, B_QUAD_SIZE, B_QUAD_UPPER_INDICES_OFFSET} from './meshes';
import {PathfinderShaderProgram} from './shader-loader';
import {UINT32_SIZE, unwrapNull} from './utils';
import {FLOAT32_SIZE, UINT32_SIZE, unwrapNull} from './utils';
import {MonochromeDemoView} from './view';
interface UpperAndLower<T> {
@ -37,8 +37,6 @@ export abstract class ECAAStrategy extends AntialiasingStrategy {
protected subpixelAA: SubpixelAAType;
private bVertexPositionBufferTexture: PathfinderBufferTexture;
private bVertexPathIDBufferTexture: PathfinderBufferTexture;
private directFramebuffer: WebGLFramebuffer;
private aaAlphaTexture: WebGLTexture;
private aaFramebuffer: WebGLFramebuffer;
@ -58,16 +56,11 @@ export abstract class ECAAStrategy extends AntialiasingStrategy {
init(view: MonochromeDemoView) {
super.init(view);
this.bVertexPositionBufferTexture = new PathfinderBufferTexture(view.gl,
'uBVertexPosition');
this.bVertexPathIDBufferTexture = new PathfinderBufferTexture(view.gl, 'uBVertexPathID');
}
attachMeshes(view: MonochromeDemoView) {
const bVertexPositions = new Float32Array(view.meshData[0].bVertexPositions);
const bVertexPathIDs = new Uint8Array(view.meshData[0].bVertexPathIDs);
this.bVertexPositionBufferTexture.upload(view.gl, bVertexPositions);
this.bVertexPathIDBufferTexture.upload(view.gl, bVertexPathIDs);
this.createEdgeDetectVAO(view);
this.createCoverVAO(view);
@ -212,24 +205,33 @@ export abstract class ECAAStrategy extends AntialiasingStrategy {
view.gl.useProgram(coverProgram.program);
view.gl.bindBuffer(view.gl.ARRAY_BUFFER, view.quadPositionsBuffer);
view.gl.vertexAttribPointer(attributes.aQuadPosition, 2, view.gl.FLOAT, false, 0, 0);
view.gl.bindBuffer(view.gl.ARRAY_BUFFER, view.meshes[0].bQuads);
view.gl.vertexAttribPointer(attributes.aUpperPointIndices,
4,
view.gl.bindBuffer(view.gl.ARRAY_BUFFER, view.meshes[0].edgeBoundingBoxVertexPositions);
view.gl.vertexAttribPointer(attributes.aUpperLeftPosition,
2,
view.gl.FLOAT,
false,
FLOAT32_SIZE * 4,
0);
view.gl.vertexAttribPointer(attributes.aLowerRightPosition,
2,
view.gl.FLOAT,
false,
FLOAT32_SIZE * 4,
FLOAT32_SIZE * 2);
view.gl.bindBuffer(view.gl.ARRAY_BUFFER, view.meshes[0].edgeBoundingBoxPathIDs);
view.gl.vertexAttribPointer(attributes.aPathID,
1,
view.gl.UNSIGNED_SHORT,
false,
B_QUAD_SIZE,
B_QUAD_UPPER_INDICES_OFFSET);
view.gl.vertexAttribPointer(attributes.aLowerPointIndices,
4,
view.gl.UNSIGNED_SHORT,
false,
B_QUAD_SIZE,
B_QUAD_LOWER_INDICES_OFFSET);
0,
0);
view.gl.enableVertexAttribArray(attributes.aQuadPosition);
view.gl.enableVertexAttribArray(attributes.aUpperPointIndices);
view.gl.enableVertexAttribArray(attributes.aLowerPointIndices);
view.instancedArraysExt.vertexAttribDivisorANGLE(attributes.aUpperPointIndices, 1);
view.instancedArraysExt.vertexAttribDivisorANGLE(attributes.aLowerPointIndices, 1);
view.gl.enableVertexAttribArray(attributes.aUpperLeftPosition);
view.gl.enableVertexAttribArray(attributes.aLowerRightPosition);
view.gl.enableVertexAttribArray(attributes.aPathID);
view.instancedArraysExt.vertexAttribDivisorANGLE(attributes.aUpperLeftPosition, 1);
view.instancedArraysExt.vertexAttribDivisorANGLE(attributes.aLowerRightPosition, 1);
view.instancedArraysExt.vertexAttribDivisorANGLE(attributes.aPathID, 1);
view.gl.bindBuffer(view.gl.ELEMENT_ARRAY_BUFFER, view.quadElementsBuffer);
view.vertexArrayObjectExt.bindVertexArrayOES(null);
@ -244,24 +246,45 @@ export abstract class ECAAStrategy extends AntialiasingStrategy {
vaos[direction] = view.vertexArrayObjectExt.createVertexArrayOES();
view.vertexArrayObjectExt.bindVertexArrayOES(vaos[direction]);
const lineIndexBuffer = {
lower: view.meshes[0].edgeLowerLineIndices,
upper: view.meshes[0].edgeUpperLineIndices,
const lineVertexPositionsBuffer = {
lower: view.meshes[0].edgeLowerLineVertexPositions,
upper: view.meshes[0].edgeUpperLineVertexPositions,
}[direction];
const linePathIDsBuffer = {
lower: view.meshes[0].edgeLowerLinePathIDs,
upper: view.meshes[0].edgeUpperLinePathIDs,
}[direction];
view.gl.useProgram(lineProgram.program);
view.gl.bindBuffer(view.gl.ARRAY_BUFFER, view.quadPositionsBuffer);
view.gl.vertexAttribPointer(attributes.aQuadPosition, 2, view.gl.FLOAT, false, 0, 0);
view.gl.bindBuffer(view.gl.ARRAY_BUFFER, lineIndexBuffer);
view.gl.vertexAttribPointer(attributes.aLineIndices,
4,
view.gl.bindBuffer(view.gl.ARRAY_BUFFER, lineVertexPositionsBuffer);
view.gl.vertexAttribPointer(attributes.aLeftPosition,
2,
view.gl.FLOAT,
false,
FLOAT32_SIZE * 4,
0);
view.gl.vertexAttribPointer(attributes.aRightPosition,
2,
view.gl.FLOAT,
false,
FLOAT32_SIZE * 4,
FLOAT32_SIZE * 2);
view.gl.bindBuffer(view.gl.ARRAY_BUFFER, linePathIDsBuffer);
view.gl.vertexAttribPointer(attributes.aPathID,
1,
view.gl.UNSIGNED_SHORT,
false,
0,
0);
view.gl.enableVertexAttribArray(attributes.aQuadPosition);
view.gl.enableVertexAttribArray(attributes.aLineIndices);
view.instancedArraysExt.vertexAttribDivisorANGLE(attributes.aLineIndices, 1);
view.gl.enableVertexAttribArray(attributes.aLeftPosition);
view.gl.enableVertexAttribArray(attributes.aRightPosition);
view.gl.enableVertexAttribArray(attributes.aPathID);
view.instancedArraysExt.vertexAttribDivisorANGLE(attributes.aLeftPosition, 1);
view.instancedArraysExt.vertexAttribDivisorANGLE(attributes.aRightPosition, 1);
view.instancedArraysExt.vertexAttribDivisorANGLE(attributes.aPathID, 1);
view.gl.bindBuffer(view.gl.ELEMENT_ARRAY_BUFFER, view.quadElementsBuffer);
}
@ -279,32 +302,53 @@ export abstract class ECAAStrategy extends AntialiasingStrategy {
vaos[direction] = view.vertexArrayObjectExt.createVertexArrayOES();
view.vertexArrayObjectExt.bindVertexArrayOES(vaos[direction]);
const curveIndexBuffer = {
lower: view.meshes[0].edgeLowerCurveIndices,
upper: view.meshes[0].edgeUpperCurveIndices,
const curveVertexPositionsBuffer = {
lower: view.meshes[0].edgeLowerCurveVertexPositions,
upper: view.meshes[0].edgeUpperCurveVertexPositions,
}[direction];
const curvePathIDsBuffer = {
lower: view.meshes[0].edgeLowerCurvePathIDs,
upper: view.meshes[0].edgeUpperCurvePathIDs,
}[direction];
view.gl.useProgram(curveProgram.program);
view.gl.bindBuffer(view.gl.ARRAY_BUFFER, view.quadPositionsBuffer);
view.gl.vertexAttribPointer(attributes.aQuadPosition, 2, view.gl.FLOAT, false, 0, 0);
view.gl.bindBuffer(view.gl.ARRAY_BUFFER, curveIndexBuffer);
view.gl.vertexAttribPointer(attributes.aCurveEndpointIndices,
4,
view.gl.UNSIGNED_SHORT,
false,
UINT32_SIZE * 4,
0);
view.gl.vertexAttribPointer(attributes.aCurveControlPointIndex,
view.gl.bindBuffer(view.gl.ARRAY_BUFFER, curveVertexPositionsBuffer);
view.gl.vertexAttribPointer(attributes.aLeftPosition,
2,
view.gl.FLOAT,
false,
FLOAT32_SIZE * 6,
0);
view.gl.vertexAttribPointer(attributes.aControlPointPosition,
2,
view.gl.FLOAT,
false,
FLOAT32_SIZE * 6,
FLOAT32_SIZE * 2);
view.gl.vertexAttribPointer(attributes.aRightPosition,
2,
view.gl.FLOAT,
false,
FLOAT32_SIZE * 6,
FLOAT32_SIZE * 4);
view.gl.bindBuffer(view.gl.ARRAY_BUFFER, curvePathIDsBuffer);
view.gl.vertexAttribPointer(attributes.aPathID,
1,
view.gl.UNSIGNED_SHORT,
false,
UINT32_SIZE * 4,
UINT32_SIZE * 2);
0,
0);
view.gl.enableVertexAttribArray(attributes.aQuadPosition);
view.gl.enableVertexAttribArray(attributes.aCurveEndpointIndices);
view.gl.enableVertexAttribArray(attributes.aCurveControlPointIndex);
view.instancedArraysExt.vertexAttribDivisorANGLE(attributes.aCurveEndpointIndices, 1);
view.instancedArraysExt.vertexAttribDivisorANGLE(attributes.aCurveControlPointIndex, 1);
view.gl.enableVertexAttribArray(attributes.aLeftPosition);
view.gl.enableVertexAttribArray(attributes.aControlPointPosition);
view.gl.enableVertexAttribArray(attributes.aRightPosition);
view.gl.enableVertexAttribArray(attributes.aPathID);
view.instancedArraysExt.vertexAttribDivisorANGLE(attributes.aLeftPosition, 1);
view.instancedArraysExt.vertexAttribDivisorANGLE(attributes.aControlPointPosition, 1);
view.instancedArraysExt.vertexAttribDivisorANGLE(attributes.aRightPosition, 1);
view.instancedArraysExt.vertexAttribDivisorANGLE(attributes.aPathID, 1);
view.gl.bindBuffer(view.gl.ELEMENT_ARRAY_BUFFER, view.quadElementsBuffer);
}
@ -376,9 +420,7 @@ export abstract class ECAAStrategy extends AntialiasingStrategy {
private setAAUniforms(view: MonochromeDemoView, uniforms: UniformMap) {
view.setTransformSTUniform(uniforms, 0);
view.setFramebufferSizeUniform(uniforms);
this.bVertexPositionBufferTexture.bind(view.gl, uniforms, 0);
this.bVertexPathIDBufferTexture.bind(view.gl, uniforms, 1);
view.pathTransformBufferTextures[0].bind(view.gl, uniforms, 2);
view.pathTransformBufferTextures[0].bind(view.gl, uniforms, 0);
view.setHintsUniform(uniforms);
}
@ -394,8 +436,8 @@ export abstract class ECAAStrategy extends AntialiasingStrategy {
view.vertexArrayObjectExt.bindVertexArrayOES(this.lineVAOs[direction]);
view.gl.uniform1i(uniforms.uLowerPart, direction === 'lower' ? 1 : 0);
const count = {
lower: view.meshData[0].edgeLowerLineIndexCount,
upper: view.meshData[0].edgeUpperLineIndexCount,
lower: view.meshData[0].edgeLowerLineCount,
upper: view.meshData[0].edgeUpperLineCount,
}[direction];
view.instancedArraysExt.drawElementsInstancedANGLE(view.gl.TRIANGLES,
6,
@ -419,8 +461,8 @@ export abstract class ECAAStrategy extends AntialiasingStrategy {
view.vertexArrayObjectExt.bindVertexArrayOES(this.curveVAOs[direction]);
view.gl.uniform1i(uniforms.uLowerPart, direction === 'lower' ? 1 : 0);
const count = {
lower: view.meshData[0].edgeLowerCurveIndexCount,
upper: view.meshData[0].edgeUpperCurveIndexCount,
lower: view.meshData[0].edgeLowerCurveCount,
upper: view.meshData[0].edgeUpperCurveCount,
}[direction];
view.instancedArraysExt.drawElementsInstancedANGLE(view.gl.TRIANGLES,
6,

View File

@ -18,35 +18,36 @@ interface BufferTypeFourCCTable {
[fourCC: string]: keyof Meshes<void>;
}
const BUFFER_TYPES: Meshes<BufferType> = {
bQuads: 'ARRAY_BUFFER',
bVertexLoopBlinnData: 'ARRAY_BUFFER',
bVertexPathIDs: 'ARRAY_BUFFER',
bVertexPositions: 'ARRAY_BUFFER',
coverCurveIndices: 'ELEMENT_ARRAY_BUFFER',
coverInteriorIndices: 'ELEMENT_ARRAY_BUFFER',
edgeLowerCurveIndices: 'ARRAY_BUFFER',
edgeLowerLineIndices: 'ARRAY_BUFFER',
edgeUpperCurveIndices: 'ARRAY_BUFFER',
edgeUpperLineIndices: 'ARRAY_BUFFER',
};
interface ArrayLike<T> {
[index: number]: T;
}
const RIFF_FOURCC: string = 'RIFF';
interface VertexExpansionDescriptor<T> {
expanded: T[];
original: ArrayLike<T>;
size: number;
}
const MESH_LIBRARY_FOURCC: string = 'PFML';
interface VertexCopyResult {
originalStartIndex: number;
originalEndIndex: number;
expandedStartIndex: number;
expandedEndIndex: number;
}
// Must match the FourCCs in `pathfinder_partitioner::mesh_library::MeshLibrary::serialize_into()`.
const BUFFER_TYPE_FOURCCS: BufferTypeFourCCTable = {
bqua: 'bQuads',
bvlb: 'bVertexLoopBlinnData',
bvpi: 'bVertexPathIDs',
bvpo: 'bVertexPositions',
cvci: 'coverCurveIndices',
cvii: 'coverInteriorIndices',
elci: 'edgeLowerCurveIndices',
elli: 'edgeLowerLineIndices',
euci: 'edgeUpperCurveIndices',
euli: 'edgeUpperLineIndices',
type PrimitiveType = 'Uint16' | 'Uint32' | 'Float32';
type PrimitiveTypeArray = Float32Array | Uint16Array | Uint32Array;
interface MeshBufferTypeDescriptor {
type: PrimitiveType;
size: number;
}
const PRIMITIVE_TYPE_ARRAY_CONSTRUCTORS = {
Float32: Float32Array,
Uint16: Uint16Array,
Uint32: Uint32Array,
};
export const B_QUAD_SIZE: number = 4 * 8;
@ -61,6 +62,70 @@ export const B_QUAD_LOWER_INDICES_OFFSET: number = B_QUAD_LOWER_LEFT_VERTEX_OFFS
const B_QUAD_FIELD_COUNT: number = B_QUAD_SIZE / UINT32_SIZE;
const MESH_TYPES: Meshes<MeshBufferTypeDescriptor> = {
bQuads: { type: 'Uint32', size: B_QUAD_FIELD_COUNT },
bVertexLoopBlinnData: { type: 'Uint32', size: 1 },
bVertexPathIDs: { type: 'Uint16', size: 1 },
bVertexPositions: { type: 'Float32', size: 2 },
coverCurveIndices: { type: 'Uint32', size: 1 },
coverInteriorIndices: { type: 'Uint32', size: 1 },
edgeBoundingBoxPathIDs: { type: 'Uint16', size: 1 },
edgeBoundingBoxVertexPositions: { type: 'Float32', size: 4 },
edgeLowerCurvePathIDs: { type: 'Uint16', size: 1 },
edgeLowerCurveVertexPositions: { type: 'Float32', size: 6 },
edgeLowerLinePathIDs: { type: 'Uint16', size: 1 },
edgeLowerLineVertexPositions: { type: 'Float32', size: 4 },
edgeUpperCurvePathIDs: { type: 'Uint16', size: 1 },
edgeUpperCurveVertexPositions: { type: 'Float32', size: 6 },
edgeUpperLinePathIDs: { type: 'Uint16', size: 1 },
edgeUpperLineVertexPositions: { type: 'Float32', size: 4 },
};
const BUFFER_TYPES: Meshes<BufferType> = {
bQuads: 'ARRAY_BUFFER',
bVertexLoopBlinnData: 'ARRAY_BUFFER',
bVertexPathIDs: 'ARRAY_BUFFER',
bVertexPositions: 'ARRAY_BUFFER',
coverCurveIndices: 'ELEMENT_ARRAY_BUFFER',
coverInteriorIndices: 'ELEMENT_ARRAY_BUFFER',
edgeBoundingBoxPathIDs: 'ARRAY_BUFFER',
edgeBoundingBoxVertexPositions: 'ARRAY_BUFFER',
edgeLowerCurvePathIDs: 'ARRAY_BUFFER',
edgeLowerCurveVertexPositions: 'ARRAY_BUFFER',
edgeLowerLinePathIDs: 'ARRAY_BUFFER',
edgeLowerLineVertexPositions: 'ARRAY_BUFFER',
edgeUpperCurvePathIDs: 'ARRAY_BUFFER',
edgeUpperCurveVertexPositions: 'ARRAY_BUFFER',
edgeUpperLinePathIDs: 'ARRAY_BUFFER',
edgeUpperLineVertexPositions: 'ARRAY_BUFFER',
};
const EDGE_BUFFER_NAMES = ['BoundingBox', 'UpperLine', 'UpperCurve', 'LowerLine', 'LowerCurve'];
const RIFF_FOURCC: string = 'RIFF';
const MESH_LIBRARY_FOURCC: string = 'PFML';
// Must match the FourCCs in `pathfinder_partitioner::mesh_library::MeshLibrary::serialize_into()`.
const BUFFER_TYPE_FOURCCS: BufferTypeFourCCTable = {
bqua: 'bQuads',
bvlb: 'bVertexLoopBlinnData',
bvpi: 'bVertexPathIDs',
bvpo: 'bVertexPositions',
cvci: 'coverCurveIndices',
cvii: 'coverInteriorIndices',
ebbp: 'edgeBoundingBoxPathIDs',
ebbv: 'edgeBoundingBoxVertexPositions',
elcp: 'edgeLowerCurvePathIDs',
elcv: 'edgeLowerCurveVertexPositions',
ellp: 'edgeLowerLinePathIDs',
ellv: 'edgeLowerLineVertexPositions',
eucp: 'edgeUpperCurvePathIDs',
eucv: 'edgeUpperCurveVertexPositions',
eulp: 'edgeUpperLinePathIDs',
eulv: 'edgeUpperLineVertexPositions',
};
type BufferType = 'ARRAY_BUFFER' | 'ELEMENT_ARRAY_BUFFER';
export interface Meshes<T> {
@ -70,10 +135,16 @@ export interface Meshes<T> {
readonly bVertexLoopBlinnData: T;
readonly coverInteriorIndices: T;
readonly coverCurveIndices: T;
readonly edgeUpperLineIndices: T;
readonly edgeLowerLineIndices: T;
readonly edgeUpperCurveIndices: T;
readonly edgeLowerCurveIndices: T;
readonly edgeBoundingBoxPathIDs: T;
readonly edgeBoundingBoxVertexPositions: T;
readonly edgeLowerCurvePathIDs: T;
readonly edgeLowerCurveVertexPositions: T;
readonly edgeLowerLinePathIDs: T;
readonly edgeLowerLineVertexPositions: T;
readonly edgeUpperCurvePathIDs: T;
readonly edgeUpperCurveVertexPositions: T;
readonly edgeUpperLinePathIDs: T;
readonly edgeUpperLineVertexPositions: T;
}
export class PathfinderMeshData implements Meshes<ArrayBuffer> {
@ -83,16 +154,22 @@ export class PathfinderMeshData implements Meshes<ArrayBuffer> {
readonly bVertexLoopBlinnData: ArrayBuffer;
readonly coverInteriorIndices: ArrayBuffer;
readonly coverCurveIndices: ArrayBuffer;
readonly edgeUpperLineIndices: ArrayBuffer;
readonly edgeLowerLineIndices: ArrayBuffer;
readonly edgeUpperCurveIndices: ArrayBuffer;
readonly edgeLowerCurveIndices: ArrayBuffer;
readonly edgeBoundingBoxPathIDs: ArrayBuffer;
readonly edgeBoundingBoxVertexPositions: ArrayBuffer;
readonly edgeLowerCurvePathIDs: ArrayBuffer;
readonly edgeLowerCurveVertexPositions: ArrayBuffer;
readonly edgeLowerLinePathIDs: ArrayBuffer;
readonly edgeLowerLineVertexPositions: ArrayBuffer;
readonly edgeUpperCurvePathIDs: ArrayBuffer;
readonly edgeUpperCurveVertexPositions: ArrayBuffer;
readonly edgeUpperLinePathIDs: ArrayBuffer;
readonly edgeUpperLineVertexPositions: ArrayBuffer;
readonly bQuadCount: number;
readonly edgeUpperLineIndexCount: number;
readonly edgeLowerLineIndexCount: number;
readonly edgeUpperCurveIndexCount: number;
readonly edgeLowerCurveIndexCount: number;
readonly edgeLowerCurveCount: number;
readonly edgeUpperCurveCount: number;
readonly edgeLowerLineCount: number;
readonly edgeUpperLineCount: number;
constructor(meshes: ArrayBuffer | Meshes<ArrayBuffer>) {
if (meshes instanceof ArrayBuffer) {
@ -119,160 +196,104 @@ export class PathfinderMeshData implements Meshes<ArrayBuffer> {
}
this.bQuadCount = this.bQuads.byteLength / B_QUAD_SIZE;
this.edgeUpperLineIndexCount = this.edgeUpperLineIndices.byteLength / 8;
this.edgeLowerLineIndexCount = this.edgeLowerLineIndices.byteLength / 8;
this.edgeUpperCurveIndexCount = this.edgeUpperCurveIndices.byteLength / 16;
this.edgeLowerCurveIndexCount = this.edgeLowerCurveIndices.byteLength / 16;
this.edgeUpperLineCount = this.edgeUpperLinePathIDs.byteLength / 2;
this.edgeLowerLineCount = this.edgeLowerLinePathIDs.byteLength / 2;
this.edgeUpperCurveCount = this.edgeUpperCurvePathIDs.byteLength / 2;
this.edgeLowerCurveCount = this.edgeLowerCurvePathIDs.byteLength / 2;
}
expand(pathIDs: number[]): PathfinderMeshData {
const bQuads = new Uint32Array(this.bQuads);
const bVertexPositions = new Float32Array(this.bVertexPositions);
const bVertexPathIDs = new Uint16Array(this.bVertexPathIDs);
const bVertexLoopBlinnData = new Uint32Array(this.bVertexLoopBlinnData);
const tempOriginalBuffers: any = {}, tempExpandedArrays: any = {};
for (const key of Object.keys(BUFFER_TYPES) as Array<keyof Meshes<void>>) {
const arrayConstructor = PRIMITIVE_TYPE_ARRAY_CONSTRUCTORS[MESH_TYPES[key].type];
tempOriginalBuffers[key] = new arrayConstructor(this[key]);
tempExpandedArrays[key] = [];
}
const edgeUpperCurveIndices = new Uint32Array(this.edgeUpperCurveIndices);
const edgeLowerCurveIndices = new Uint32Array(this.edgeLowerCurveIndices);
for (let indexIndex = 3; indexIndex < edgeUpperCurveIndices.length; indexIndex += 4)
edgeUpperCurveIndices[indexIndex] = 0;
for (let indexIndex = 3; indexIndex < edgeLowerCurveIndices.length; indexIndex += 4)
edgeLowerCurveIndices[indexIndex] = 0;
const originalBuffers: Meshes<PrimitiveTypeArray> = tempOriginalBuffers;
const expandedArrays: Meshes<number[]> = tempExpandedArrays;
const coverInteriorIndices = new Uint32Array(this.coverInteriorIndices);
const coverCurveIndices = new Uint32Array(this.coverCurveIndices);
const edgeUpperLineIndices = new Uint32Array(this.edgeUpperLineIndices);
const edgeLowerLineIndices = new Uint32Array(this.edgeLowerLineIndices);
for (let newPathIndex = 0; newPathIndex < pathIDs.length; newPathIndex++) {
const expandedPathID = newPathIndex + 1;
const originalPathID = pathIDs[newPathIndex];
const expandedBQuads: number[] = [];
const expandedBVertexPositions: number[] = [];
const expandedBVertexPathIDs: number[] = [];
const expandedBVertexLoopBlinnData: number[] = [];
const expandedCoverInteriorIndices: number[] = [];
const expandedCoverCurveIndices: number[] = [];
const expandedEdgeUpperCurveIndices: number[] = [];
const expandedEdgeUpperLineIndices: number[] = [];
const expandedEdgeLowerCurveIndices: number[] = [];
const expandedEdgeLowerLineIndices: number[] = [];
const bVertexCopyResult =
copyVertices(['bVertexPositions', 'bVertexLoopBlinnData'],
'bVertexPathIDs',
expandedArrays,
originalBuffers,
expandedPathID,
originalPathID);
let textGlyphIndex = 0;
for (const pathID of pathIDs) {
const firstBVertexIndex = _.sortedIndex(bVertexPathIDs, pathID);
if (firstBVertexIndex < 0)
if (bVertexCopyResult == null)
continue;
// Copy over vertices.
let bVertexIndex = firstBVertexIndex;
const firstExpandedBVertexIndex = expandedBVertexPathIDs.length;
while (bVertexIndex < bVertexPathIDs.length &&
bVertexPathIDs[bVertexIndex] === pathID) {
expandedBVertexPositions.push(bVertexPositions[bVertexIndex * 2 + 0],
bVertexPositions[bVertexIndex * 2 + 1]);
expandedBVertexPathIDs.push(textGlyphIndex + 1);
expandedBVertexLoopBlinnData.push(bVertexLoopBlinnData[bVertexIndex]);
bVertexIndex++;
const firstExpandedBVertexIndex = bVertexCopyResult.expandedStartIndex;
const firstBVertexIndex = bVertexCopyResult.originalStartIndex;
const lastBVertexIndex = bVertexCopyResult.originalEndIndex;
// Copy over edge data.
for (const edgeBufferName of EDGE_BUFFER_NAMES) {
copyVertices([`edge${edgeBufferName}VertexPositions` as keyof Meshes<void>],
`edge${edgeBufferName}PathIDs` as keyof Meshes<void>,
expandedArrays,
originalBuffers,
expandedPathID,
originalPathID);
}
// Copy over indices.
copyIndices(expandedCoverInteriorIndices,
coverInteriorIndices,
copyIndices(expandedArrays.coverInteriorIndices,
originalBuffers.coverInteriorIndices as Uint32Array,
firstExpandedBVertexIndex,
firstBVertexIndex,
bVertexIndex);
copyIndices(expandedCoverCurveIndices,
coverCurveIndices,
lastBVertexIndex);
copyIndices(expandedArrays.coverCurveIndices,
originalBuffers.coverCurveIndices as Uint32Array,
firstExpandedBVertexIndex,
firstBVertexIndex,
bVertexIndex);
copyIndices(expandedEdgeUpperLineIndices,
edgeUpperLineIndices,
firstExpandedBVertexIndex,
firstBVertexIndex,
bVertexIndex);
copyIndices(expandedEdgeUpperCurveIndices,
edgeUpperCurveIndices,
firstExpandedBVertexIndex,
firstBVertexIndex,
bVertexIndex,
indexIndex => indexIndex % 4 < 3);
copyIndices(expandedEdgeLowerLineIndices,
edgeLowerLineIndices,
firstExpandedBVertexIndex,
firstBVertexIndex,
bVertexIndex);
copyIndices(expandedEdgeLowerCurveIndices,
edgeLowerCurveIndices,
firstExpandedBVertexIndex,
firstBVertexIndex,
bVertexIndex,
indexIndex => indexIndex % 4 < 3);
lastBVertexIndex);
// Copy over B-quads.
let firstBQuadIndex = findFirstBQuadIndex(bQuads, bVertexPathIDs, pathID);
let firstBQuadIndex =
findFirstBQuadIndex(originalBuffers.bQuads as Uint32Array,
originalBuffers.bVertexPathIDs as Uint16Array,
originalPathID);
if (firstBQuadIndex == null)
firstBQuadIndex = bQuads.length;
firstBQuadIndex = originalBuffers.bQuads.length;
const indexDelta = firstExpandedBVertexIndex - firstBVertexIndex;
for (let bQuadIndex = firstBQuadIndex;
bQuadIndex < bQuads.length / B_QUAD_FIELD_COUNT;
bQuadIndex < originalBuffers.bQuads.length / B_QUAD_FIELD_COUNT;
bQuadIndex++) {
const bQuad = bQuads[bQuadIndex];
if (bVertexPathIDs[bQuads[bQuadIndex * B_QUAD_FIELD_COUNT]] !== pathID)
const bQuad = originalBuffers.bQuads[bQuadIndex];
if (originalBuffers.bVertexPathIDs[originalBuffers.bQuads[bQuadIndex *
B_QUAD_FIELD_COUNT]] !==
originalPathID) {
break;
}
for (let indexIndex = 0; indexIndex < B_QUAD_FIELD_COUNT; indexIndex++) {
const srcIndex = bQuads[bQuadIndex * B_QUAD_FIELD_COUNT + indexIndex];
const srcIndex = originalBuffers.bQuads[bQuadIndex * B_QUAD_FIELD_COUNT +
indexIndex];
if (srcIndex === UINT32_MAX)
expandedBQuads.push(srcIndex);
expandedArrays.bQuads.push(srcIndex);
else
expandedBQuads.push(srcIndex + indexDelta);
expandedArrays.bQuads.push(srcIndex + indexDelta);
}
}
textGlyphIndex++;
}
const expandedBQuadsBuffer = new ArrayBuffer(expandedBQuads.length * UINT32_SIZE);
const expandedBVertexLoopBlinnDataBuffer =
new ArrayBuffer(expandedBVertexLoopBlinnData.length * UINT32_SIZE);
const expandedBVertexPathIDsBuffer =
new ArrayBuffer(expandedBVertexPathIDs.length * UINT16_SIZE);
const expandedBVertexPositionsBuffer =
new ArrayBuffer(expandedBVertexPositions.length * FLOAT32_SIZE);
const expandedCoverCurveIndicesBuffer =
new ArrayBuffer(expandedCoverCurveIndices.length * UINT32_SIZE);
const expandedCoverInteriorIndicesBuffer =
new ArrayBuffer(expandedCoverInteriorIndices.length * UINT32_SIZE);
const expandedEdgeLowerCurveIndicesBuffer =
new ArrayBuffer(expandedEdgeLowerCurveIndices.length * UINT32_SIZE);
const expandedEdgeLowerLineIndicesBuffer =
new ArrayBuffer(expandedEdgeLowerLineIndices.length * UINT32_SIZE);
const expandedEdgeUpperCurveIndicesBuffer =
new ArrayBuffer(expandedEdgeUpperCurveIndices.length * UINT32_SIZE);
const expandedEdgeUpperLineIndicesBuffer =
new ArrayBuffer(expandedEdgeUpperLineIndices.length * UINT32_SIZE);
const tempExpandedBuffers: any = {};
for (const key of Object.keys(MESH_TYPES) as Array<keyof Meshes<void>>) {
const bufferType = MESH_TYPES[key].type;
const arrayConstructor = PRIMITIVE_TYPE_ARRAY_CONSTRUCTORS[bufferType];
const expandedBuffer = new ArrayBuffer(expandedArrays[key].length *
sizeOfPrimitive(bufferType));
(new arrayConstructor(expandedBuffer)).set(expandedArrays[key]);
tempExpandedBuffers[key] = expandedBuffer;
}
(new Uint32Array(expandedBQuadsBuffer)).set(expandedBQuads);
(new Uint32Array(expandedBVertexLoopBlinnDataBuffer)).set(expandedBVertexLoopBlinnData);
(new Uint16Array(expandedBVertexPathIDsBuffer)).set(expandedBVertexPathIDs);
(new Float32Array(expandedBVertexPositionsBuffer)).set(expandedBVertexPositions);
(new Uint32Array(expandedCoverCurveIndicesBuffer)).set(expandedCoverCurveIndices);
(new Uint32Array(expandedCoverInteriorIndicesBuffer)).set(expandedCoverInteriorIndices);
(new Uint32Array(expandedEdgeLowerCurveIndicesBuffer)).set(expandedEdgeLowerCurveIndices);
(new Uint32Array(expandedEdgeLowerLineIndicesBuffer)).set(expandedEdgeLowerLineIndices);
(new Uint32Array(expandedEdgeUpperCurveIndicesBuffer)).set(expandedEdgeUpperCurveIndices);
(new Uint32Array(expandedEdgeUpperLineIndicesBuffer)).set(expandedEdgeUpperLineIndices);
return new PathfinderMeshData({
bQuads: expandedBQuadsBuffer,
bVertexLoopBlinnData: expandedBVertexLoopBlinnDataBuffer,
bVertexPathIDs: expandedBVertexPathIDsBuffer,
bVertexPositions: expandedBVertexPositionsBuffer,
coverCurveIndices: expandedCoverCurveIndicesBuffer,
coverInteriorIndices: expandedCoverInteriorIndicesBuffer,
edgeLowerCurveIndices: expandedEdgeLowerCurveIndicesBuffer,
edgeLowerLineIndices: expandedEdgeLowerLineIndicesBuffer,
edgeUpperCurveIndices: expandedEdgeUpperCurveIndicesBuffer,
edgeUpperLineIndices: expandedEdgeUpperLineIndicesBuffer,
});
const expandedBuffers = tempExpandedBuffers as Meshes<ArrayBuffer>;
return new PathfinderMeshData(expandedBuffers);
}
}
@ -283,10 +304,16 @@ export class PathfinderMeshBuffers implements Meshes<WebGLBuffer> {
readonly bVertexLoopBlinnData: WebGLBuffer;
readonly coverInteriorIndices: WebGLBuffer;
readonly coverCurveIndices: WebGLBuffer;
readonly edgeUpperLineIndices: WebGLBuffer;
readonly edgeUpperCurveIndices: WebGLBuffer;
readonly edgeLowerLineIndices: WebGLBuffer;
readonly edgeLowerCurveIndices: WebGLBuffer;
readonly edgeBoundingBoxPathIDs: WebGLBuffer;
readonly edgeBoundingBoxVertexPositions: WebGLBuffer;
readonly edgeLowerCurvePathIDs: WebGLBuffer;
readonly edgeLowerCurveVertexPositions: WebGLBuffer;
readonly edgeLowerLinePathIDs: WebGLBuffer;
readonly edgeLowerLineVertexPositions: WebGLBuffer;
readonly edgeUpperCurvePathIDs: WebGLBuffer;
readonly edgeUpperCurveVertexPositions: WebGLBuffer;
readonly edgeUpperLinePathIDs: WebGLBuffer;
readonly edgeUpperLineVertexPositions: WebGLBuffer;
constructor(gl: WebGLRenderingContext, meshData: PathfinderMeshData) {
for (const bufferName of Object.keys(BUFFER_TYPES) as Array<keyof PathfinderMeshBuffers>) {
@ -299,6 +326,48 @@ export class PathfinderMeshBuffers implements Meshes<WebGLBuffer> {
}
}
function copyVertices<T>(vertexBufferNames: Array<keyof Meshes<void>>,
pathIDBufferName: keyof Meshes<void>,
expandedMeshes: Meshes<number[]>,
originalMeshes: Meshes<PrimitiveTypeArray>,
expandedPathID: number,
originalPathID: number):
VertexCopyResult | null {
const expandedPathIDs = expandedMeshes[pathIDBufferName];
const originalPathIDs = originalMeshes[pathIDBufferName];
const firstOriginalVertexIndex = _.sortedIndex(originalPathIDs, originalPathID);
if (firstOriginalVertexIndex < 0)
return null;
const firstExpandedVertexIndex = expandedPathIDs.length;
let lastOriginalVertexIndex = firstOriginalVertexIndex;
while (lastOriginalVertexIndex < originalPathIDs.length &&
originalPathIDs[lastOriginalVertexIndex] === originalPathID) {
for (const vertexBufferName of vertexBufferNames) {
const expanded = expandedMeshes[vertexBufferName];
const original = originalMeshes[vertexBufferName];
const size = MESH_TYPES[vertexBufferName].size;
for (let elementIndex = 0; elementIndex < size; elementIndex++) {
const globalIndex = size * lastOriginalVertexIndex + elementIndex;
expanded.push(original[globalIndex]);
}
}
expandedPathIDs.push(expandedPathID);
lastOriginalVertexIndex++;
}
return {
expandedEndIndex: expandedPathIDs.length,
expandedStartIndex: firstExpandedVertexIndex,
originalEndIndex: lastOriginalVertexIndex,
originalStartIndex: firstOriginalVertexIndex,
};
}
function copyIndices(destIndices: number[],
srcIndices: Uint32Array,
firstExpandedIndex: number,
@ -327,6 +396,14 @@ function copyIndices(destIndices: number[],
}
}
function sizeOfPrimitive(primitiveType: PrimitiveType): number {
switch (primitiveType) {
case 'Uint16': return UINT16_SIZE;
case 'Uint32': return UINT32_SIZE;
case 'Float32': return FLOAT32_SIZE;
}
}
function findFirstBQuadIndex(bQuads: Uint32Array,
bVertexPathIDs: Uint16Array,
queryPathID: number):

View File

@ -17,13 +17,13 @@ import {DemoAppController} from './app-controller';
import PathfinderBufferTexture from "./buffer-texture";
import {OrthographicCamera} from "./camera";
import {ECAAMulticolorStrategy, ECAAStrategy} from "./ecaa-strategy";
import {UniformMap} from './gl-utils';
import {PathfinderMeshData} from "./meshes";
import {ShaderMap, ShaderProgramSource} from './shader-loader';
import SSAAStrategy from "./ssaa-strategy";
import {BUILTIN_SVG_URI, SVGLoader} from './svg-loader';
import {panic, unwrapNull} from './utils';
import {DemoView, Timings} from './view';
import { UniformMap } from './gl-utils';
const parseColor = require('parse-color');

View File

@ -7,7 +7,7 @@ authors = ["Patrick Walton <pcwalton@mimiga.net>"]
app_units = "0.5"
base64 = "0.6"
bincode = "0.8"
env_logger = "0.3"
env_logger = "0.4"
euclid = "0.15"
lazy_static = "0.2"
log = "0.3"

View File

@ -7,7 +7,7 @@ use std::slice;
use mesh_library::MeshLibrary;
use partitioner::Partitioner;
use {BQuad, BVertexLoopBlinnData, CurveIndices, Endpoint, LineIndices, Subpath};
use {BQuad, BVertexLoopBlinnData, Endpoint, Subpath};
#[derive(Clone, Copy)]
#[repr(C)]
@ -43,19 +43,6 @@ pub struct CoverIndices {
pub curve_indices_len: u32,
}
#[derive(Clone, Copy)]
#[repr(C)]
pub struct EdgeIndices {
pub upper_line_indices: *const LineIndices,
pub upper_line_indices_len: u32,
pub upper_curve_indices: *const CurveIndices,
pub upper_curve_indices_len: u32,
pub lower_line_indices: *const LineIndices,
pub lower_line_indices_len: u32,
pub lower_curve_indices: *const CurveIndices,
pub lower_curve_indices_len: u32,
}
#[no_mangle]
pub unsafe extern fn pf_partitioner_new() -> *mut Partitioner<'static> {
let mut partitioner = Box::new(Partitioner::new(MeshLibrary::new()));
@ -146,20 +133,6 @@ pub unsafe extern fn pf_partitioner_cover_indices<'a>(partitioner: *const Partit
(*out_cover_indices).curve_indices_len = cover_indices.curve_indices.len() as u32;
}
#[no_mangle]
pub unsafe extern fn pf_partitioner_edge_indices<'a>(partitioner: *const Partitioner<'a>,
out_edge_indices: *mut EdgeIndices) {
let edge_indices = &(*partitioner).library().edge_indices;
(*out_edge_indices).upper_line_indices = edge_indices.upper_line_indices.as_ptr();
(*out_edge_indices).upper_line_indices_len = edge_indices.upper_line_indices.len() as u32;
(*out_edge_indices).upper_curve_indices = edge_indices.upper_curve_indices.as_ptr();
(*out_edge_indices).upper_curve_indices_len = edge_indices.upper_curve_indices.len() as u32;
(*out_edge_indices).lower_line_indices = edge_indices.lower_line_indices.as_ptr();
(*out_edge_indices).lower_line_indices_len = edge_indices.lower_line_indices.len() as u32;
(*out_edge_indices).lower_curve_indices = edge_indices.lower_curve_indices.as_ptr();
(*out_edge_indices).lower_curve_indices_len = edge_indices.lower_curve_indices.len() as u32;
}
#[no_mangle]
pub unsafe extern fn pf_init_env_logger() -> u32 {
env_logger::init().is_ok() as u32

View File

@ -145,57 +145,3 @@ impl BVertexLoopBlinnData {
BVertexLoopBlinnData::new(endpoint_kind)
}
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
#[repr(C)]
pub struct LineIndices {
pub left_vertex_index: u32,
pub right_vertex_index: u32,
}
impl LineIndices {
#[inline]
pub fn new(left_vertex_index: u32, right_vertex_index: u32) -> LineIndices {
LineIndices {
left_vertex_index: left_vertex_index,
right_vertex_index: right_vertex_index,
}
}
#[inline]
pub fn offset(&mut self, delta: u32) {
self.left_vertex_index += delta;
self.right_vertex_index += delta;
}
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
#[repr(C)]
pub struct CurveIndices {
pub left_vertex_index: u32,
pub right_vertex_index: u32,
pub control_point_vertex_index: u32,
pad: u32,
}
impl CurveIndices {
#[inline]
pub fn new(left_vertex_index: u32, control_point_vertex_index: u32, right_vertex_index: u32)
-> CurveIndices {
CurveIndices {
left_vertex_index: left_vertex_index,
right_vertex_index: right_vertex_index,
control_point_vertex_index: control_point_vertex_index,
pad: 0,
}
}
#[inline]
pub fn offset(&mut self, delta: u32) {
self.left_vertex_index += delta;
self.right_vertex_index += delta;
if self.control_point_vertex_index < u32::MAX {
self.control_point_vertex_index += delta;
}
}
}

View File

@ -14,8 +14,9 @@ use euclid::Point2D;
use serde::Serialize;
use std::io::{self, ErrorKind, Seek, SeekFrom, Write};
use std::ops::Range;
use std::u32;
use {BQuad, BVertexLoopBlinnData, CurveIndices, LineIndices};
use {BQuad, BVertexLoopBlinnData};
#[derive(Debug, Clone)]
pub struct MeshLibrary {
@ -24,7 +25,7 @@ pub struct MeshLibrary {
pub b_vertex_path_ids: Vec<u16>,
pub b_vertex_loop_blinn_data: Vec<BVertexLoopBlinnData>,
pub cover_indices: MeshLibraryCoverIndices,
pub edge_indices: MeshLibraryEdgeIndices,
pub edge_data: MeshLibraryEdgeData,
}
impl MeshLibrary {
@ -36,7 +37,7 @@ impl MeshLibrary {
b_vertex_path_ids: vec![],
b_vertex_loop_blinn_data: vec![],
cover_indices: MeshLibraryCoverIndices::new(),
edge_indices: MeshLibraryEdgeIndices::new(),
edge_data: MeshLibraryEdgeData::new(),
}
}
@ -46,7 +47,69 @@ impl MeshLibrary {
self.b_vertex_path_ids.clear();
self.b_vertex_loop_blinn_data.clear();
self.cover_indices.clear();
self.edge_indices.clear();
self.edge_data.clear();
}
pub(crate) fn add_b_quad(&mut self, b_quad: &BQuad) {
self.b_quads.push(*b_quad);
let path_id = self.b_vertex_path_ids[b_quad.upper_left_vertex_index as usize];
let upper_left_position =
&self.b_vertex_positions[b_quad.upper_left_vertex_index as usize];
let upper_right_position =
&self.b_vertex_positions[b_quad.upper_right_vertex_index as usize];
let lower_left_position =
&self.b_vertex_positions[b_quad.lower_left_vertex_index as usize];
let lower_right_position =
&self.b_vertex_positions[b_quad.lower_right_vertex_index as usize];
let upper_left_bounding_box_position =
Point2D::new(upper_left_position.x,
f32::min(upper_left_position.y, upper_right_position.y));
let lower_right_bounding_box_position =
Point2D::new(lower_right_position.x,
f32::max(lower_left_position.y, lower_right_position.y));
self.edge_data.bounding_box_vertex_positions.push(EdgeBoundingBoxVertexPositions {
upper_left: upper_left_bounding_box_position,
lower_right: lower_right_bounding_box_position,
});
self.edge_data.bounding_box_path_ids.push(path_id);
if b_quad.upper_control_point_vertex_index == u32::MAX {
self.edge_data.upper_line_vertex_positions.push(EdgeLineVertexPositions {
left: *upper_left_position,
right: *upper_right_position,
});
self.edge_data.upper_line_path_ids.push(path_id);
} else {
let upper_control_point_position =
&self.b_vertex_positions[b_quad.upper_control_point_vertex_index as usize];
self.edge_data.upper_curve_vertex_positions.push(EdgeCurveVertexPositions {
left: *upper_left_position,
control_point: *upper_control_point_position,
right: *upper_right_position,
});
self.edge_data.upper_curve_path_ids.push(path_id);
}
if b_quad.lower_control_point_vertex_index == u32::MAX {
self.edge_data.lower_line_vertex_positions.push(EdgeLineVertexPositions {
left: *lower_left_position,
right: *lower_right_position,
});
self.edge_data.lower_line_path_ids.push(path_id);
} else {
let lower_control_point_position =
&self.b_vertex_positions[b_quad.lower_control_point_vertex_index as usize];
self.edge_data.lower_curve_vertex_positions.push(EdgeCurveVertexPositions {
left: *lower_left_position,
control_point: *lower_control_point_position,
right: *lower_right_position,
});
self.edge_data.lower_curve_path_ids.push(path_id);
}
}
/// Reverses interior indices so that they draw front-to-back.
@ -97,10 +160,16 @@ impl MeshLibrary {
try!(write_chunk(writer, b"bvlb", &self.b_vertex_loop_blinn_data));
try!(write_chunk(writer, b"cvii", &self.cover_indices.interior_indices));
try!(write_chunk(writer, b"cvci", &self.cover_indices.curve_indices));
try!(write_chunk(writer, b"euli", &self.edge_indices.upper_line_indices));
try!(write_chunk(writer, b"euci", &self.edge_indices.upper_curve_indices));
try!(write_chunk(writer, b"elli", &self.edge_indices.lower_line_indices));
try!(write_chunk(writer, b"elci", &self.edge_indices.lower_curve_indices));
try!(write_chunk(writer, b"ebbv", &self.edge_data.bounding_box_vertex_positions));
try!(write_chunk(writer, b"eulv", &self.edge_data.upper_line_vertex_positions));
try!(write_chunk(writer, b"ellv", &self.edge_data.lower_line_vertex_positions));
try!(write_chunk(writer, b"eucv", &self.edge_data.upper_curve_vertex_positions));
try!(write_chunk(writer, b"elcv", &self.edge_data.lower_curve_vertex_positions));
try!(write_chunk(writer, b"ebbp", &self.edge_data.bounding_box_path_ids));
try!(write_chunk(writer, b"eulp", &self.edge_data.upper_line_path_ids));
try!(write_chunk(writer, b"ellp", &self.edge_data.lower_line_path_ids));
try!(write_chunk(writer, b"eucp", &self.edge_data.upper_curve_path_ids));
try!(write_chunk(writer, b"elcp", &self.edge_data.lower_curve_path_ids));
let total_length = try!(writer.seek(SeekFrom::Current(0)));
try!(writer.seek(SeekFrom::Start(4)));
@ -133,10 +202,11 @@ impl MeshLibrary {
b_vertices: self.b_vertex_positions.len(),
cover_interior_indices: self.cover_indices.interior_indices.len(),
cover_curve_indices: self.cover_indices.curve_indices.len(),
edge_upper_line_indices: self.edge_indices.upper_line_indices.len(),
edge_upper_curve_indices: self.edge_indices.upper_curve_indices.len(),
edge_lower_line_indices: self.edge_indices.lower_line_indices.len(),
edge_lower_curve_indices: self.edge_indices.lower_curve_indices.len(),
edge_bounding_box_indices: self.edge_data.bounding_box_vertex_positions.len(),
edge_upper_line_indices: self.edge_data.upper_line_vertex_positions.len(),
edge_upper_curve_indices: self.edge_data.upper_curve_vertex_positions.len(),
edge_lower_line_indices: self.edge_data.lower_line_vertex_positions.len(),
edge_lower_curve_indices: self.edge_data.lower_curve_vertex_positions.len(),
}
}
}
@ -162,38 +232,12 @@ impl MeshLibraryCoverIndices {
}
}
#[derive(Debug, Clone)]
pub struct MeshLibraryEdgeIndices {
pub upper_line_indices: Vec<LineIndices>,
pub upper_curve_indices: Vec<CurveIndices>,
pub lower_line_indices: Vec<LineIndices>,
pub lower_curve_indices: Vec<CurveIndices>,
}
impl MeshLibraryEdgeIndices {
#[inline]
fn new() -> MeshLibraryEdgeIndices {
MeshLibraryEdgeIndices {
upper_line_indices: vec![],
upper_curve_indices: vec![],
lower_line_indices: vec![],
lower_curve_indices: vec![],
}
}
fn clear(&mut self) {
self.upper_line_indices.clear();
self.upper_curve_indices.clear();
self.lower_line_indices.clear();
self.lower_curve_indices.clear();
}
}
pub(crate) struct MeshLibraryLengths {
b_quads: usize,
b_vertices: usize,
cover_interior_indices: usize,
cover_curve_indices: usize,
edge_bounding_box_indices: usize,
edge_upper_line_indices: usize,
edge_upper_curve_indices: usize,
edge_lower_line_indices: usize,
@ -205,6 +249,7 @@ pub struct MeshLibraryIndexRanges {
pub b_vertices: Range<usize>,
pub cover_interior_indices: Range<usize>,
pub cover_curve_indices: Range<usize>,
pub edge_bounding_box_indices: Range<usize>,
pub edge_upper_line_indices: Range<usize>,
pub edge_upper_curve_indices: Range<usize>,
pub edge_lower_line_indices: Range<usize>,
@ -219,6 +264,8 @@ impl MeshLibraryIndexRanges {
b_vertices: start.b_vertices..end.b_vertices,
cover_interior_indices: start.cover_interior_indices..end.cover_interior_indices,
cover_curve_indices: start.cover_curve_indices..end.cover_curve_indices,
edge_bounding_box_indices:
start.edge_bounding_box_indices..end.edge_bounding_box_indices,
edge_upper_line_indices: start.edge_upper_line_indices..end.edge_upper_line_indices,
edge_upper_curve_indices: start.edge_upper_curve_indices..end.edge_upper_curve_indices,
edge_lower_line_indices: start.edge_lower_line_indices..end.edge_lower_line_indices,
@ -226,3 +273,66 @@ impl MeshLibraryIndexRanges {
}
}
}
#[derive(Clone, Debug)]
pub struct MeshLibraryEdgeData {
pub bounding_box_vertex_positions: Vec<EdgeBoundingBoxVertexPositions>,
pub upper_line_vertex_positions: Vec<EdgeLineVertexPositions>,
pub lower_line_vertex_positions: Vec<EdgeLineVertexPositions>,
pub upper_curve_vertex_positions: Vec<EdgeCurveVertexPositions>,
pub lower_curve_vertex_positions: Vec<EdgeCurveVertexPositions>,
pub bounding_box_path_ids: Vec<u16>,
pub upper_line_path_ids: Vec<u16>,
pub lower_line_path_ids: Vec<u16>,
pub upper_curve_path_ids: Vec<u16>,
pub lower_curve_path_ids: Vec<u16>,
}
impl MeshLibraryEdgeData {
fn new() -> MeshLibraryEdgeData {
MeshLibraryEdgeData {
bounding_box_vertex_positions: vec![],
upper_line_vertex_positions: vec![],
lower_line_vertex_positions: vec![],
upper_curve_vertex_positions: vec![],
lower_curve_vertex_positions: vec![],
bounding_box_path_ids: vec![],
upper_line_path_ids: vec![],
lower_line_path_ids: vec![],
upper_curve_path_ids: vec![],
lower_curve_path_ids: vec![],
}
}
fn clear(&mut self) {
self.bounding_box_vertex_positions.clear();
self.upper_line_vertex_positions.clear();
self.upper_curve_vertex_positions.clear();
self.lower_line_vertex_positions.clear();
self.lower_curve_vertex_positions.clear();
self.bounding_box_path_ids.clear();
self.upper_line_path_ids.clear();
self.upper_curve_path_ids.clear();
self.lower_line_path_ids.clear();
self.lower_curve_path_ids.clear();
}
}
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
pub struct EdgeBoundingBoxVertexPositions {
pub upper_left: Point2D<f32>,
pub lower_right: Point2D<f32>,
}
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
pub struct EdgeLineVertexPositions {
pub left: Point2D<f32>,
pub right: Point2D<f32>,
}
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
pub struct EdgeCurveVertexPositions {
pub left: Point2D<f32>,
pub control_point: Point2D<f32>,
pub right: Point2D<f32>,
}

View File

@ -22,8 +22,7 @@ use std::iter;
use std::u32;
use mesh_library::{MeshLibrary, MeshLibraryIndexRanges};
use {BQuad, BVertexLoopBlinnData, BVertexKind, CurveIndices, Endpoint, FillRule};
use {LineIndices, Subpath};
use {BQuad, BVertexLoopBlinnData, BVertexKind, Endpoint, FillRule, Subpath};
const MAX_B_QUAD_SUBDIVISIONS: u8 = 8;
@ -610,41 +609,6 @@ impl<'a> Partitioner<'a> {
}
}
match upper_shape {
Shape::Flat => {
self.library
.edge_indices
.upper_line_indices
.push(LineIndices::new(upper_subdivision.left_curve_left,
upper_subdivision.middle_point))
}
Shape::Convex | Shape::Concave => {
self.library
.edge_indices
.upper_curve_indices
.push(CurveIndices::new(upper_subdivision.left_curve_left,
upper_subdivision.left_curve_control_point,
upper_subdivision.middle_point))
}
}
match lower_shape {
Shape::Flat => {
self.library
.edge_indices
.lower_line_indices
.push(LineIndices::new(lower_subdivision.left_curve_left,
lower_subdivision.middle_point))
}
Shape::Convex | Shape::Concave => {
self.library
.edge_indices
.lower_curve_indices
.push(CurveIndices::new(lower_subdivision.left_curve_left,
lower_subdivision.left_curve_control_point,
lower_subdivision.middle_point))
}
}
debug!("... emitting B-quad: UL {} BL {} UR {} BR {}",
upper_subdivision.left_curve_left,
lower_subdivision.left_curve_left,
@ -773,12 +737,12 @@ impl<'a> Partitioner<'a> {
}
}
self.library.b_quads.push(BQuad::new(upper_subdivision.left_curve_left,
upper_subdivision.left_curve_control_point,
upper_subdivision.middle_point,
lower_subdivision.left_curve_left,
lower_subdivision.left_curve_control_point,
lower_subdivision.middle_point))
self.library.add_b_quad(&BQuad::new(upper_subdivision.left_curve_left,
upper_subdivision.left_curve_control_point,
upper_subdivision.middle_point,
lower_subdivision.left_curve_left,
lower_subdivision.left_curve_control_point,
lower_subdivision.middle_point))
}
fn subdivide_active_edge_again_at_t(&mut self,

View File

@ -192,29 +192,11 @@ int unpackUInt16(vec2 packedValue) {
return valueBytes.y * 256 + valueBytes.x;
}
int unpackUInt32Attribute(vec2 packedValue) {
ivec2 valueWords = ivec2(packedValue);
return valueWords.y * 65536 + valueWords.x;
}
vec4 fetchFloat4Data(sampler2D dataTexture, int index, ivec2 dimensions) {
ivec2 pixelCoord = ivec2(imod(index, dimensions.x), index / dimensions.x);
return texture2D(dataTexture, (vec2(pixelCoord) + 0.5) / vec2(dimensions));
}
vec4 fetchFloat4NormIndexedData(sampler2D dataTexture, float normIndex, ivec2 dimensions) {
return fetchFloat4Data(dataTexture, int(normIndex * float(dimensions.x)), dimensions);
}
vec2 fetchFloat2Data(sampler2D dataTexture, int index, ivec2 dimensions) {
vec4 float4Data = fetchFloat4Data(dataTexture, index / 2, dimensions);
return index / 2 * 2 == index ? float4Data.xy : float4Data.zw;
}
int fetchUInt16Data(sampler2D dataTexture, int index, ivec2 dimensions) {
return unpackUInt16(fetchFloat2Data(dataTexture, index, dimensions));
}
vec2 packPathID(int pathID) {
return vec2(imod(pathID, 256), pathID / 256) / 255.0;
}

View File

@ -13,47 +13,23 @@ precision highp float;
uniform vec4 uTransformST;
uniform vec4 uHints;
uniform ivec2 uFramebufferSize;
uniform ivec2 uBVertexPositionDimensions;
uniform ivec2 uBVertexPathIDDimensions;
uniform ivec2 uPathTransformDimensions;
uniform sampler2D uBVertexPosition;
uniform sampler2D uBVertexPathID;
uniform sampler2D uPathTransform;
attribute vec2 aQuadPosition;
attribute vec4 aUpperPointIndices;
attribute vec4 aLowerPointIndices;
attribute vec2 aUpperLeftPosition;
attribute vec2 aLowerRightPosition;
attribute float aPathID;
varying vec2 vHorizontalExtents;
void main() {
// Fetch B-vertex positions.
ivec4 pointIndices = ivec4(unpackUInt32Attribute(aUpperPointIndices.xy),
unpackUInt32Attribute(aUpperPointIndices.zw),
unpackUInt32Attribute(aLowerPointIndices.xy),
unpackUInt32Attribute(aLowerPointIndices.zw));
vec2 upperLeftPosition = fetchFloat2Data(uBVertexPosition,
pointIndices.x,
uBVertexPositionDimensions);
vec2 upperRightPosition = fetchFloat2Data(uBVertexPosition,
pointIndices.y,
uBVertexPositionDimensions);
vec2 lowerLeftPosition = fetchFloat2Data(uBVertexPosition,
pointIndices.z,
uBVertexPositionDimensions);
vec2 lowerRightPosition = fetchFloat2Data(uBVertexPosition,
pointIndices.w,
uBVertexPositionDimensions);
upperLeftPosition.y = min(upperLeftPosition.y, upperRightPosition.y);
lowerRightPosition.y = max(lowerLeftPosition.y, lowerRightPosition.y);
int pathID = fetchUInt16Data(uBVertexPathID, pointIndices.x, uBVertexPathIDDimensions);
int pathID = int(aPathID);
vec4 transform = fetchFloat4Data(uPathTransform, pathID, uPathTransformDimensions);
upperLeftPosition = hintPosition(upperLeftPosition, uHints);
lowerRightPosition = hintPosition(lowerRightPosition, uHints);
vec2 upperLeftPosition = hintPosition(aUpperLeftPosition, uHints);
vec2 lowerRightPosition = hintPosition(aLowerRightPosition, uHints);
upperLeftPosition = transformVertexPositionST(upperLeftPosition, transform);
lowerRightPosition = transformVertexPositionST(lowerRightPosition, transform);

View File

@ -13,37 +13,24 @@ precision highp float;
uniform vec4 uTransformST;
uniform vec4 uHints;
uniform ivec2 uFramebufferSize;
uniform ivec2 uBVertexPositionDimensions;
uniform ivec2 uBVertexPathIDDimensions;
uniform ivec2 uPathTransformDimensions;
uniform sampler2D uBVertexPosition;
uniform sampler2D uBVertexPathID;
uniform sampler2D uPathTransform;
uniform bool uLowerPart;
attribute vec2 aQuadPosition;
attribute vec4 aCurveEndpointIndices;
attribute vec2 aCurveControlPointIndex;
attribute vec2 aLeftPosition;
attribute vec2 aControlPointPosition;
attribute vec2 aRightPosition;
attribute float aPathID;
varying vec4 vEndpoints;
varying vec2 vControlPoint;
void main() {
// Fetch B-vertex positions.
ivec3 pointIndices = ivec3(unpackUInt32Attribute(aCurveEndpointIndices.xy),
unpackUInt32Attribute(aCurveEndpointIndices.zw),
unpackUInt32Attribute(aCurveControlPointIndex));
vec2 leftPosition = fetchFloat2Data(uBVertexPosition,
pointIndices.x,
uBVertexPositionDimensions);
vec2 rightPosition = fetchFloat2Data(uBVertexPosition,
pointIndices.y,
uBVertexPositionDimensions);
vec2 controlPointPosition = fetchFloat2Data(uBVertexPosition,
pointIndices.z,
uBVertexPositionDimensions);
int pathID = fetchUInt16Data(uBVertexPathID, pointIndices.x, uBVertexPathIDDimensions);
vec2 leftPosition = aLeftPosition;
vec2 controlPointPosition = aControlPointPosition;
vec2 rightPosition = aRightPosition;
int pathID = int(aPathID);
vec4 transform = fetchFloat4Data(uPathTransform, pathID, uPathTransformDimensions);
@ -57,7 +44,7 @@ void main() {
transform,
uTransformST,
uHints)) {
controlPointPosition = hintPosition(controlPointPosition, uHints);
controlPointPosition = hintPosition(aControlPointPosition, uHints);
controlPointPosition = transformVertexPositionST(controlPointPosition, transform);
controlPointPosition = transformVertexPositionST(controlPointPosition, uTransformST);
controlPointPosition = convertClipToScreenSpace(controlPointPosition, uFramebufferSize);

View File

@ -13,31 +13,21 @@ precision highp float;
uniform vec4 uTransformST;
uniform vec4 uHints;
uniform ivec2 uFramebufferSize;
uniform ivec2 uBVertexPositionDimensions;
uniform ivec2 uBVertexPathIDDimensions;
uniform ivec2 uPathTransformDimensions;
uniform sampler2D uBVertexPosition;
uniform sampler2D uBVertexPathID;
uniform sampler2D uPathTransform;
uniform bool uLowerPart;
attribute vec2 aQuadPosition;
attribute vec4 aLineIndices;
attribute vec2 aLeftPosition;
attribute vec2 aRightPosition;
attribute float aPathID;
varying vec4 vEndpoints;
void main() {
// Fetch B-vertex positions.
ivec2 pointIndices = ivec2(unpackUInt32Attribute(aLineIndices.xy),
unpackUInt32Attribute(aLineIndices.zw));
vec2 leftPosition = fetchFloat2Data(uBVertexPosition,
pointIndices.x,
uBVertexPositionDimensions);
vec2 rightPosition = fetchFloat2Data(uBVertexPosition,
pointIndices.y,
uBVertexPositionDimensions);
int pathID = fetchUInt16Data(uBVertexPathID, pointIndices.x, uBVertexPathIDDimensions);
vec2 leftPosition = aLeftPosition;
vec2 rightPosition = aRightPosition;
int pathID = int(aPathID);
vec4 transform = fetchFloat4Data(uPathTransform, pathID, uPathTransformDimensions);