gpu: [compute] fix path gaps by eliminating redundant path points

See https://github.com/linebender/piet-gpu/issues/62 for description
of the issue. The fix is the Gio copy of the piet-gpu fix.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
Elias Naur
2021-02-15 20:04:01 +01:00
parent b5d21b209c
commit 2feec23561
6 changed files with 105 additions and 158 deletions
+24 -8
View File
@@ -153,9 +153,9 @@ const (
pathSize = 12 pathSize = 12
binSize = 8 binSize = 8
pathsegSize = 48 pathsegSize = 44
annoSize = 28 annoSize = 28
stateSize = 56 stateSize = 60
stateStride = 4 + 2*stateSize stateStride = 4 + 2*stateSize
sceneElemSize = 36 sceneElemSize = 36
) )
@@ -178,6 +178,10 @@ const (
elemFillImage elemFillImage
) )
const (
flagEndPath = 16 // FLAG_END_PATH from elements.comp
)
// mem.h constants. // mem.h constants.
const ( const (
memNoError = 0 // NO_ERROR memNoError = 0 // NO_ERROR
@@ -647,6 +651,10 @@ func (g *compute) encodeClipStack(clip, bounds f32.Rectangle, p *pathOp) int {
// renderer. // renderer.
func encodePath(p []byte) encoder { func encodePath(p []byte) encoder {
var enc encoder var enc encoder
var (
prevTo f32.Point
hasPrev bool
)
for len(p) > 0 { for len(p) > 0 {
// p contains quadratic curves encoded in vertex structs. // p contains quadratic curves encoded in vertex structs.
vertex := p[:vertStride] vertex := p[:vertStride]
@@ -663,12 +671,20 @@ func encodePath(p []byte) encoder {
math.Float32frombits(bo.Uint32(vertex[24:])), math.Float32frombits(bo.Uint32(vertex[24:])),
math.Float32frombits(bo.Uint32(vertex[28:])), math.Float32frombits(bo.Uint32(vertex[28:])),
) )
if hasPrev && from != prevTo {
enc.scene[len(enc.scene)-1][0] = (flagEndPath << 16) | enc.scene[len(enc.scene)-1][0]
}
hasPrev = true
prevTo = to
enc.quad(from, ctrl, to, false) enc.quad(from, ctrl, to, false)
// The vertex is duplicated 4 times, one for each corner of quads drawn // The vertex is duplicated 4 times, one for each corner of quads drawn
// by the old renderer. // by the old renderer.
p = p[vertStride*4:] p = p[vertStride*4:]
} }
if hasPrev {
enc.scene[len(enc.scene)-1][0] = (flagEndPath << 16) | enc.scene[len(enc.scene)-1][0]
}
return enc return enc
} }
@@ -1018,10 +1034,10 @@ func (e *encoder) endClip(bbox f32.Rectangle) {
func (e *encoder) rect(r f32.Rectangle, stroke bool) { func (e *encoder) rect(r f32.Rectangle, stroke bool) {
// Rectangle corners, clock-wise. // Rectangle corners, clock-wise.
c0, c1, c2, c3 := r.Min, f32.Pt(r.Min.X, r.Max.Y), r.Max, f32.Pt(r.Max.X, r.Min.Y) c0, c1, c2, c3 := r.Min, f32.Pt(r.Min.X, r.Max.Y), r.Max, f32.Pt(r.Max.X, r.Min.Y)
e.line(c0, c1, stroke) e.line(c0, c1, stroke, 0)
e.line(c1, c2, stroke) e.line(c1, c2, stroke, 0)
e.line(c2, c3, stroke) e.line(c2, c3, stroke, 0)
e.line(c3, c0, stroke) e.line(c3, c0, stroke, flagEndPath)
} }
func (e *encoder) fill(col color.RGBA) { func (e *encoder) fill(col color.RGBA) {
@@ -1043,13 +1059,13 @@ func (e *encoder) fillImage(index int, offset image.Point) {
e.npath++ e.npath++
} }
func (e *encoder) line(start, end f32.Point, stroke bool) { func (e *encoder) line(start, end f32.Point, stroke bool, flags uint32) {
tag := uint32(elemFillLine) tag := uint32(elemFillLine)
if stroke { if stroke {
tag = elemStrokeLine tag = elemStrokeLine
} }
e.scene = append(e.scene, sceneElem{ e.scene = append(e.scene, sceneElem{
0: tag, 0: flags<<16 | tag,
1: math.Float32bits(start.X), 1: math.Float32bits(start.X),
2: math.Float32bits(start.Y), 2: math.Float32bits(start.Y),
3: math.Float32bits(end.X), 3: math.Float32bits(end.X),
+2 -2
View File
File diff suppressed because one or more lines are too long
+32 -7
View File
@@ -62,6 +62,8 @@ uint state_flag_index(uint partition_ix) {
#define FLAG_SET_LINEWIDTH 1 #define FLAG_SET_LINEWIDTH 1
#define FLAG_SET_BBOX 2 #define FLAG_SET_BBOX 2
#define FLAG_RESET_BBOX 4 #define FLAG_RESET_BBOX 4
#define FLAG_START_PATH 8
#define FLAG_END_PATH 16
// This is almost like a monoid (the interaction between transformation and // This is almost like a monoid (the interaction between transformation and
// bounding boxes is approximate) // bounding boxes is approximate)
@@ -87,32 +89,45 @@ State combine_state(State a, State b) {
c.translate.x = a.mat.x * b.translate.x + a.mat.z * b.translate.y + a.translate.x; c.translate.x = a.mat.x * b.translate.x + a.mat.z * b.translate.y + a.translate.x;
c.translate.y = a.mat.y * b.translate.x + a.mat.w * b.translate.y + a.translate.y; c.translate.y = a.mat.y * b.translate.x + a.mat.w * b.translate.y + a.translate.y;
c.linewidth = (b.flags & FLAG_SET_LINEWIDTH) == 0 ? a.linewidth : b.linewidth; c.linewidth = (b.flags & FLAG_SET_LINEWIDTH) == 0 ? a.linewidth : b.linewidth;
c.flags = (a.flags & (FLAG_SET_LINEWIDTH | FLAG_SET_BBOX)) | b.flags; c.flags = (a.flags & (FLAG_SET_LINEWIDTH | FLAG_SET_BBOX | FLAG_START_PATH)) | b.flags;
c.flags |= (a.flags & FLAG_RESET_BBOX) >> 1; c.flags |= (a.flags & FLAG_RESET_BBOX) >> 1;
c.flags |= (a.flags & FLAG_END_PATH) >> 1;
c.path_count = a.path_count + b.path_count; c.path_count = a.path_count + b.path_count;
c.pathseg_count = a.pathseg_count + b.pathseg_count; c.pathseg_count = a.pathseg_count + b.pathseg_count;
c.tail = a.tail;
if ((a.flags & FLAG_END_PATH) != 0 && (b.flags & FLAG_START_PATH) == 0) {
c.tail = a.pathseg_count;
} else if ((b.flags & FLAG_START_PATH) != 0) {
c.tail = b.tail + a.pathseg_count;
}
return c; return c;
} }
State map_element(ElementRef ref) { State map_element(ElementRef ref) {
// TODO: it would *probably* be more efficient to make the memory read patterns less // TODO: it would *probably* be more efficient to make the memory read patterns less
// divergent, though it would be more wasted memory. // divergent, though it would be more wasted memory.
uint tag = Element_tag(ref); uint tag_flags = Element_tag(ref);
State c; State c;
c.bbox = vec4(0.0, 0.0, 0.0, 0.0); c.bbox = vec4(0.0, 0.0, 0.0, 0.0);
c.mat = vec4(1.0, 0.0, 0.0, 1.0); c.mat = vec4(1.0, 0.0, 0.0, 1.0);
c.translate = vec2(0.0, 0.0); c.translate = vec2(0.0, 0.0);
c.linewidth = 1.0; // TODO should be 0.0 c.linewidth = 1.0; // TODO should be 0.0
c.flags = 0; c.flags = 0;
c.tail = 0;
c.path_count = 0; c.path_count = 0;
c.pathseg_count = 0; c.pathseg_count = 0;
switch (tag) { // flags contain FLAG_END_PATH for segments last in their path.
uint flags = tag_flags >> 16;
switch (tag_flags & 0xffff) {
case Element_FillLine: case Element_FillLine:
case Element_StrokeLine: case Element_StrokeLine:
LineSeg line = Element_FillLine_read(ref); LineSeg line = Element_FillLine_read(ref);
c.bbox.xy = min(line.p0, line.p1); c.bbox.xy = min(line.p0, line.p1);
c.bbox.zw = max(line.p0, line.p1); c.bbox.zw = max(line.p0, line.p1);
c.pathseg_count = 1; c.pathseg_count = 1;
c.flags = flags;
break; break;
case Element_FillQuad: case Element_FillQuad:
case Element_StrokeQuad: case Element_StrokeQuad:
@@ -120,6 +135,7 @@ State map_element(ElementRef ref) {
c.bbox.xy = min(min(quad.p0, quad.p1), quad.p2); c.bbox.xy = min(min(quad.p0, quad.p1), quad.p2);
c.bbox.zw = max(max(quad.p0, quad.p1), quad.p2); c.bbox.zw = max(max(quad.p0, quad.p1), quad.p2);
c.pathseg_count = 1; c.pathseg_count = 1;
c.flags = flags;
break; break;
case Element_FillCubic: case Element_FillCubic:
case Element_StrokeCubic: case Element_StrokeCubic:
@@ -127,6 +143,7 @@ State map_element(ElementRef ref) {
c.bbox.xy = min(min(cubic.p0, cubic.p1), min(cubic.p2, cubic.p3)); c.bbox.xy = min(min(cubic.p0, cubic.p1), min(cubic.p2, cubic.p3));
c.bbox.zw = max(max(cubic.p0, cubic.p1), max(cubic.p2, cubic.p3)); c.bbox.zw = max(max(cubic.p0, cubic.p1), max(cubic.p2, cubic.p3));
c.pathseg_count = 1; c.pathseg_count = 1;
c.flags = flags;
break; break;
case Element_Fill: case Element_Fill:
case Element_FillImage: case Element_FillImage:
@@ -166,6 +183,7 @@ shared vec2 sh_translate[WG_SIZE];
shared vec4 sh_bbox[WG_SIZE]; shared vec4 sh_bbox[WG_SIZE];
shared float sh_width[WG_SIZE]; shared float sh_width[WG_SIZE];
shared uint sh_flags[WG_SIZE]; shared uint sh_flags[WG_SIZE];
shared uint sh_tail[WG_SIZE];
shared uint sh_path_count[WG_SIZE]; shared uint sh_path_count[WG_SIZE];
shared uint sh_pathseg_count[WG_SIZE]; shared uint sh_pathseg_count[WG_SIZE];
@@ -200,6 +218,7 @@ void main() {
sh_translate[gl_LocalInvocationID.x] = agg.translate; sh_translate[gl_LocalInvocationID.x] = agg.translate;
sh_bbox[gl_LocalInvocationID.x] = agg.bbox; sh_bbox[gl_LocalInvocationID.x] = agg.bbox;
sh_width[gl_LocalInvocationID.x] = agg.linewidth; sh_width[gl_LocalInvocationID.x] = agg.linewidth;
sh_tail[gl_LocalInvocationID.x] = agg.tail;
sh_flags[gl_LocalInvocationID.x] = agg.flags; sh_flags[gl_LocalInvocationID.x] = agg.flags;
sh_path_count[gl_LocalInvocationID.x] = agg.path_count; sh_path_count[gl_LocalInvocationID.x] = agg.path_count;
sh_pathseg_count[gl_LocalInvocationID.x] = agg.pathseg_count; sh_pathseg_count[gl_LocalInvocationID.x] = agg.pathseg_count;
@@ -213,6 +232,7 @@ void main() {
other.bbox = sh_bbox[ix]; other.bbox = sh_bbox[ix];
other.linewidth = sh_width[ix]; other.linewidth = sh_width[ix];
other.flags = sh_flags[ix]; other.flags = sh_flags[ix];
other.tail = sh_tail[ix];
other.path_count = sh_path_count[ix]; other.path_count = sh_path_count[ix];
other.pathseg_count = sh_pathseg_count[ix]; other.pathseg_count = sh_pathseg_count[ix];
agg = combine_state(other, agg); agg = combine_state(other, agg);
@@ -223,6 +243,7 @@ void main() {
sh_bbox[gl_LocalInvocationID.x] = agg.bbox; sh_bbox[gl_LocalInvocationID.x] = agg.bbox;
sh_width[gl_LocalInvocationID.x] = agg.linewidth; sh_width[gl_LocalInvocationID.x] = agg.linewidth;
sh_flags[gl_LocalInvocationID.x] = agg.flags; sh_flags[gl_LocalInvocationID.x] = agg.flags;
sh_tail[gl_LocalInvocationID.x] = agg.tail;
sh_path_count[gl_LocalInvocationID.x] = agg.path_count; sh_path_count[gl_LocalInvocationID.x] = agg.path_count;
sh_pathseg_count[gl_LocalInvocationID.x] = agg.pathseg_count; sh_pathseg_count[gl_LocalInvocationID.x] = agg.pathseg_count;
} }
@@ -233,6 +254,7 @@ void main() {
exclusive.translate = vec2(0.0, 0.0); exclusive.translate = vec2(0.0, 0.0);
exclusive.linewidth = 1.0; //TODO should be 0.0 exclusive.linewidth = 1.0; //TODO should be 0.0
exclusive.flags = 0; exclusive.flags = 0;
exclusive.tail = 0;
exclusive.path_count = 0; exclusive.path_count = 0;
exclusive.pathseg_count = 0; exclusive.pathseg_count = 0;
@@ -312,6 +334,7 @@ void main() {
other.bbox = sh_bbox[ix]; other.bbox = sh_bbox[ix];
other.linewidth = sh_width[ix]; other.linewidth = sh_width[ix];
other.flags = sh_flags[ix]; other.flags = sh_flags[ix];
other.tail = sh_tail[ix];
other.path_count = sh_path_count[ix]; other.path_count = sh_path_count[ix];
other.pathseg_count = sh_pathseg_count[ix]; other.pathseg_count = sh_pathseg_count[ix];
row = combine_state(row, other); row = combine_state(row, other);
@@ -323,7 +346,9 @@ void main() {
// gains to be had from stashing in shared memory or possibly // gains to be had from stashing in shared memory or possibly
// registers (though register pressure is an issue). // registers (though register pressure is an issue).
ElementRef this_ref = Element_index(ref, i); ElementRef this_ref = Element_index(ref, i);
uint tag = Element_tag(this_ref); uint tag_flags = Element_tag(this_ref);
uint tag = tag_flags & 0xffff;
uint flags = tag_flags >> 16;
switch (tag) { switch (tag) {
case Element_FillLine: case Element_FillLine:
case Element_StrokeLine: case Element_StrokeLine:
@@ -334,7 +359,7 @@ void main() {
path_cubic.p0 = p0; path_cubic.p0 = p0;
path_cubic.p1 = mix(p0, p1, 1.0 / 3.0); path_cubic.p1 = mix(p0, p1, 1.0 / 3.0);
path_cubic.p2 = mix(p1, p0, 1.0 / 3.0); path_cubic.p2 = mix(p1, p0, 1.0 / 3.0);
path_cubic.p3 = p1; path_cubic.succ_ix = (flags & FLAG_END_PATH) == 0 ? st.pathseg_count : st.tail;
path_cubic.path_ix = st.path_count; path_cubic.path_ix = st.path_count;
if (tag == Element_StrokeLine) { if (tag == Element_StrokeLine) {
path_cubic.stroke = get_linewidth(st); path_cubic.stroke = get_linewidth(st);
@@ -358,7 +383,7 @@ void main() {
path_cubic.p0 = p0; path_cubic.p0 = p0;
path_cubic.p1 = mix(p1, p0, 1.0 / 3.0); path_cubic.p1 = mix(p1, p0, 1.0 / 3.0);
path_cubic.p2 = mix(p1, p2, 1.0 / 3.0); path_cubic.p2 = mix(p1, p2, 1.0 / 3.0);
path_cubic.p3 = p2; path_cubic.succ_ix = (flags & FLAG_END_PATH) == 0 ? st.pathseg_count : st.tail;
path_cubic.path_ix = st.path_count; path_cubic.path_ix = st.path_count;
if (tag == Element_StrokeQuad) { if (tag == Element_StrokeQuad) {
path_cubic.stroke = get_linewidth(st); path_cubic.stroke = get_linewidth(st);
@@ -379,7 +404,7 @@ void main() {
path_cubic.p0 = st.mat.xy * cubic.p0.x + st.mat.zw * cubic.p0.y + st.translate; path_cubic.p0 = st.mat.xy * cubic.p0.x + st.mat.zw * cubic.p0.y + st.translate;
path_cubic.p1 = st.mat.xy * cubic.p1.x + st.mat.zw * cubic.p1.y + st.translate; path_cubic.p1 = st.mat.xy * cubic.p1.x + st.mat.zw * cubic.p1.y + st.translate;
path_cubic.p2 = st.mat.xy * cubic.p2.x + st.mat.zw * cubic.p2.y + st.translate; path_cubic.p2 = st.mat.xy * cubic.p2.x + st.mat.zw * cubic.p2.y + st.translate;
path_cubic.p3 = st.mat.xy * cubic.p3.x + st.mat.zw * cubic.p3.y + st.translate; path_cubic.succ_ix = (flags & FLAG_END_PATH) == 0 ? st.pathseg_count : st.tail;
path_cubic.path_ix = st.path_count; path_cubic.path_ix = st.path_count;
if (tag == Element_StrokeCubic) { if (tag == Element_StrokeCubic) {
path_cubic.stroke = get_linewidth(st); path_cubic.stroke = get_linewidth(st);
+16 -6
View File
@@ -86,6 +86,14 @@ SubdivResult estimate_subdiv(vec2 p0, vec2 p1, vec2 p2, float sqrt_tol) {
return SubdivResult(val, a0, a2); return SubdivResult(val, a0, a2);
} }
// PathSeg_Cubic_read_p0 is like PathSeg_StrokeCubic_read except it only reads p0.
vec2 PathSeg_Cubic_read_p0(Alloc a, PathSegRef ref) {
uint ix = (ref.offset + 4) >> 2;
uint raw0 = read_mem(a, ix + 0);
uint raw1 = read_mem(a, ix + 1);
return vec2(uintBitsToFloat(raw0), uintBitsToFloat(raw1));
}
void main() { void main() {
if (mem_error != NO_ERROR) { if (mem_error != NO_ERROR) {
return; return;
@@ -102,7 +110,9 @@ void main() {
case PathSeg_FillCubic: case PathSeg_FillCubic:
case PathSeg_StrokeCubic: case PathSeg_StrokeCubic:
PathStrokeCubic cubic = PathSeg_StrokeCubic_read(conf.pathseg_alloc, ref); PathStrokeCubic cubic = PathSeg_StrokeCubic_read(conf.pathseg_alloc, ref);
vec2 err_v = 3.0 * (cubic.p2 - cubic.p1) + cubic.p0 - cubic.p3; PathSegRef succ_ref = PathSegRef(conf.pathseg_alloc.offset + cubic.succ_ix * PathSeg_size);
vec2 p3 = PathSeg_Cubic_read_p0(conf.pathseg_alloc, succ_ref);
vec2 err_v = 3.0 * (cubic.p2 - cubic.p1) + cubic.p0 - p3;
float err = err_v.x * err_v.x + err_v.y * err_v.y; float err = err_v.x * err_v.x + err_v.y * err_v.y;
// The number of quadratics. // The number of quadratics.
uint n_quads = max(uint(ceil(pow(err * (1.0 / MAX_HYPOT2), 1.0 / 6.0))), 1); uint n_quads = max(uint(ceil(pow(err * (1.0 / MAX_HYPOT2), 1.0 / 6.0))), 1);
@@ -112,8 +122,8 @@ void main() {
float step = 1.0 / float(n_quads); float step = 1.0 / float(n_quads);
for (uint i = 0; i < n_quads; i++) { for (uint i = 0; i < n_quads; i++) {
float t = float(i + 1) * step; float t = float(i + 1) * step;
vec2 qp2 = eval_cubic(cubic.p0, cubic.p1, cubic.p2, cubic.p3, t); vec2 qp2 = eval_cubic(cubic.p0, cubic.p1, cubic.p2, p3, t);
vec2 qp1 = eval_cubic(cubic.p0, cubic.p1, cubic.p2, cubic.p3, t - 0.5 * step); vec2 qp1 = eval_cubic(cubic.p0, cubic.p1, cubic.p2, p3, t - 0.5 * step);
qp1 = 2.0 * qp1 - 0.5 * (qp0 + qp2); qp1 = 2.0 * qp1 - 0.5 * (qp0 + qp2);
SubdivResult params = estimate_subdiv(qp0, qp1, qp2, sqrt(REM_ACCURACY)); SubdivResult params = estimate_subdiv(qp0, qp1, qp2, sqrt(REM_ACCURACY));
val += params.val; val += params.val;
@@ -133,8 +143,8 @@ void main() {
float val_sum = 0.0; float val_sum = 0.0;
for (uint i = 0; i < n_quads; i++) { for (uint i = 0; i < n_quads; i++) {
float t = float(i + 1) * step; float t = float(i + 1) * step;
vec2 qp2 = eval_cubic(cubic.p0, cubic.p1, cubic.p2, cubic.p3, t); vec2 qp2 = eval_cubic(cubic.p0, cubic.p1, cubic.p2, p3, t);
vec2 qp1 = eval_cubic(cubic.p0, cubic.p1, cubic.p2, cubic.p3, t - 0.5 * step); vec2 qp1 = eval_cubic(cubic.p0, cubic.p1, cubic.p2, p3, t - 0.5 * step);
qp1 = 2.0 * qp1 - 0.5 * (qp0 + qp2); qp1 = 2.0 * qp1 - 0.5 * (qp0 + qp2);
SubdivResult params = estimate_subdiv(qp0, qp1, qp2, sqrt(REM_ACCURACY)); SubdivResult params = estimate_subdiv(qp0, qp1, qp2, sqrt(REM_ACCURACY));
float u0 = approx_parabola_inv_integral(params.a0); float u0 = approx_parabola_inv_integral(params.a0);
@@ -144,7 +154,7 @@ void main() {
while (n_out == n || target < val_sum + params.val) { while (n_out == n || target < val_sum + params.val) {
vec2 p1; vec2 p1;
if (n_out == n) { if (n_out == n) {
p1 = cubic.p3; p1 = p3;
} else { } else {
float u = (target - val_sum) / params.val; float u = (target - val_sum) / params.val;
float a = mix(params.a0, params.a2, u); float a = mix(params.a0, params.a2, u);
+18 -126
View File
@@ -2,14 +2,6 @@
// Code auto-generated by piet-gpu-derive // Code auto-generated by piet-gpu-derive
struct PathFillLineRef {
uint offset;
};
struct PathStrokeLineRef {
uint offset;
};
struct PathFillCubicRef { struct PathFillCubicRef {
uint offset; uint offset;
}; };
@@ -22,40 +14,15 @@ struct PathSegRef {
uint offset; uint offset;
}; };
struct PathFillLine {
vec2 p0;
vec2 p1;
uint path_ix;
};
#define PathFillLine_size 20
PathFillLineRef PathFillLine_index(PathFillLineRef ref, uint index) {
return PathFillLineRef(ref.offset + index * PathFillLine_size);
}
struct PathStrokeLine {
vec2 p0;
vec2 p1;
uint path_ix;
vec2 stroke;
};
#define PathStrokeLine_size 28
PathStrokeLineRef PathStrokeLine_index(PathStrokeLineRef ref, uint index) {
return PathStrokeLineRef(ref.offset + index * PathStrokeLine_size);
}
struct PathFillCubic { struct PathFillCubic {
vec2 p0; vec2 p0;
vec2 p1; vec2 p1;
vec2 p2; vec2 p2;
vec2 p3; uint succ_ix;
uint path_ix; uint path_ix;
}; };
#define PathFillCubic_size 36 #define PathFillCubic_size 32
PathFillCubicRef PathFillCubic_index(PathFillCubicRef ref, uint index) { PathFillCubicRef PathFillCubic_index(PathFillCubicRef ref, uint index) {
return PathFillCubicRef(ref.offset + index * PathFillCubic_size); return PathFillCubicRef(ref.offset + index * PathFillCubic_size);
@@ -65,79 +32,26 @@ struct PathStrokeCubic {
vec2 p0; vec2 p0;
vec2 p1; vec2 p1;
vec2 p2; vec2 p2;
vec2 p3; uint succ_ix;
uint path_ix; uint path_ix;
vec2 stroke; vec2 stroke;
}; };
#define PathStrokeCubic_size 44 #define PathStrokeCubic_size 40
PathStrokeCubicRef PathStrokeCubic_index(PathStrokeCubicRef ref, uint index) { PathStrokeCubicRef PathStrokeCubic_index(PathStrokeCubicRef ref, uint index) {
return PathStrokeCubicRef(ref.offset + index * PathStrokeCubic_size); return PathStrokeCubicRef(ref.offset + index * PathStrokeCubic_size);
} }
#define PathSeg_Nop 0 #define PathSeg_Nop 0
#define PathSeg_FillLine 1 #define PathSeg_FillCubic 1
#define PathSeg_StrokeLine 2 #define PathSeg_StrokeCubic 2
#define PathSeg_FillCubic 3 #define PathSeg_size 44
#define PathSeg_StrokeCubic 4
#define PathSeg_size 48
PathSegRef PathSeg_index(PathSegRef ref, uint index) { PathSegRef PathSeg_index(PathSegRef ref, uint index) {
return PathSegRef(ref.offset + index * PathSeg_size); return PathSegRef(ref.offset + index * PathSeg_size);
} }
PathFillLine PathFillLine_read(Alloc a, PathFillLineRef ref) {
uint ix = ref.offset >> 2;
uint raw0 = read_mem(a, ix + 0);
uint raw1 = read_mem(a, ix + 1);
uint raw2 = read_mem(a, ix + 2);
uint raw3 = read_mem(a, ix + 3);
uint raw4 = read_mem(a, ix + 4);
PathFillLine s;
s.p0 = vec2(uintBitsToFloat(raw0), uintBitsToFloat(raw1));
s.p1 = vec2(uintBitsToFloat(raw2), uintBitsToFloat(raw3));
s.path_ix = raw4;
return s;
}
void PathFillLine_write(Alloc a, PathFillLineRef ref, PathFillLine s) {
uint ix = ref.offset >> 2;
write_mem(a, ix + 0, floatBitsToUint(s.p0.x));
write_mem(a, ix + 1, floatBitsToUint(s.p0.y));
write_mem(a, ix + 2, floatBitsToUint(s.p1.x));
write_mem(a, ix + 3, floatBitsToUint(s.p1.y));
write_mem(a, ix + 4, s.path_ix);
}
PathStrokeLine PathStrokeLine_read(Alloc a, PathStrokeLineRef ref) {
uint ix = ref.offset >> 2;
uint raw0 = read_mem(a, ix + 0);
uint raw1 = read_mem(a, ix + 1);
uint raw2 = read_mem(a, ix + 2);
uint raw3 = read_mem(a, ix + 3);
uint raw4 = read_mem(a, ix + 4);
uint raw5 = read_mem(a, ix + 5);
uint raw6 = read_mem(a, ix + 6);
PathStrokeLine s;
s.p0 = vec2(uintBitsToFloat(raw0), uintBitsToFloat(raw1));
s.p1 = vec2(uintBitsToFloat(raw2), uintBitsToFloat(raw3));
s.path_ix = raw4;
s.stroke = vec2(uintBitsToFloat(raw5), uintBitsToFloat(raw6));
return s;
}
void PathStrokeLine_write(Alloc a, PathStrokeLineRef ref, PathStrokeLine s) {
uint ix = ref.offset >> 2;
write_mem(a, ix + 0, floatBitsToUint(s.p0.x));
write_mem(a, ix + 1, floatBitsToUint(s.p0.y));
write_mem(a, ix + 2, floatBitsToUint(s.p1.x));
write_mem(a, ix + 3, floatBitsToUint(s.p1.y));
write_mem(a, ix + 4, s.path_ix);
write_mem(a, ix + 5, floatBitsToUint(s.stroke.x));
write_mem(a, ix + 6, floatBitsToUint(s.stroke.y));
}
PathFillCubic PathFillCubic_read(Alloc a, PathFillCubicRef ref) { PathFillCubic PathFillCubic_read(Alloc a, PathFillCubicRef ref) {
uint ix = ref.offset >> 2; uint ix = ref.offset >> 2;
uint raw0 = read_mem(a, ix + 0); uint raw0 = read_mem(a, ix + 0);
@@ -148,13 +62,12 @@ PathFillCubic PathFillCubic_read(Alloc a, PathFillCubicRef ref) {
uint raw5 = read_mem(a, ix + 5); uint raw5 = read_mem(a, ix + 5);
uint raw6 = read_mem(a, ix + 6); uint raw6 = read_mem(a, ix + 6);
uint raw7 = read_mem(a, ix + 7); uint raw7 = read_mem(a, ix + 7);
uint raw8 = read_mem(a, ix + 8);
PathFillCubic s; PathFillCubic s;
s.p0 = vec2(uintBitsToFloat(raw0), uintBitsToFloat(raw1)); s.p0 = vec2(uintBitsToFloat(raw0), uintBitsToFloat(raw1));
s.p1 = vec2(uintBitsToFloat(raw2), uintBitsToFloat(raw3)); s.p1 = vec2(uintBitsToFloat(raw2), uintBitsToFloat(raw3));
s.p2 = vec2(uintBitsToFloat(raw4), uintBitsToFloat(raw5)); s.p2 = vec2(uintBitsToFloat(raw4), uintBitsToFloat(raw5));
s.p3 = vec2(uintBitsToFloat(raw6), uintBitsToFloat(raw7)); s.succ_ix = raw6;
s.path_ix = raw8; s.path_ix = raw7;
return s; return s;
} }
@@ -166,9 +79,8 @@ void PathFillCubic_write(Alloc a, PathFillCubicRef ref, PathFillCubic s) {
write_mem(a, ix + 3, floatBitsToUint(s.p1.y)); write_mem(a, ix + 3, floatBitsToUint(s.p1.y));
write_mem(a, ix + 4, floatBitsToUint(s.p2.x)); write_mem(a, ix + 4, floatBitsToUint(s.p2.x));
write_mem(a, ix + 5, floatBitsToUint(s.p2.y)); write_mem(a, ix + 5, floatBitsToUint(s.p2.y));
write_mem(a, ix + 6, floatBitsToUint(s.p3.x)); write_mem(a, ix + 6, s.succ_ix);
write_mem(a, ix + 7, floatBitsToUint(s.p3.y)); write_mem(a, ix + 7, s.path_ix);
write_mem(a, ix + 8, s.path_ix);
} }
PathStrokeCubic PathStrokeCubic_read(Alloc a, PathStrokeCubicRef ref) { PathStrokeCubic PathStrokeCubic_read(Alloc a, PathStrokeCubicRef ref) {
@@ -183,14 +95,13 @@ PathStrokeCubic PathStrokeCubic_read(Alloc a, PathStrokeCubicRef ref) {
uint raw7 = read_mem(a, ix + 7); uint raw7 = read_mem(a, ix + 7);
uint raw8 = read_mem(a, ix + 8); uint raw8 = read_mem(a, ix + 8);
uint raw9 = read_mem(a, ix + 9); uint raw9 = read_mem(a, ix + 9);
uint raw10 = read_mem(a, ix + 10);
PathStrokeCubic s; PathStrokeCubic s;
s.p0 = vec2(uintBitsToFloat(raw0), uintBitsToFloat(raw1)); s.p0 = vec2(uintBitsToFloat(raw0), uintBitsToFloat(raw1));
s.p1 = vec2(uintBitsToFloat(raw2), uintBitsToFloat(raw3)); s.p1 = vec2(uintBitsToFloat(raw2), uintBitsToFloat(raw3));
s.p2 = vec2(uintBitsToFloat(raw4), uintBitsToFloat(raw5)); s.p2 = vec2(uintBitsToFloat(raw4), uintBitsToFloat(raw5));
s.p3 = vec2(uintBitsToFloat(raw6), uintBitsToFloat(raw7)); s.succ_ix = raw6;
s.path_ix = raw8; s.path_ix = raw7;
s.stroke = vec2(uintBitsToFloat(raw9), uintBitsToFloat(raw10)); s.stroke = vec2(uintBitsToFloat(raw8), uintBitsToFloat(raw9));
return s; return s;
} }
@@ -202,25 +113,16 @@ void PathStrokeCubic_write(Alloc a, PathStrokeCubicRef ref, PathStrokeCubic s) {
write_mem(a, ix + 3, floatBitsToUint(s.p1.y)); write_mem(a, ix + 3, floatBitsToUint(s.p1.y));
write_mem(a, ix + 4, floatBitsToUint(s.p2.x)); write_mem(a, ix + 4, floatBitsToUint(s.p2.x));
write_mem(a, ix + 5, floatBitsToUint(s.p2.y)); write_mem(a, ix + 5, floatBitsToUint(s.p2.y));
write_mem(a, ix + 6, floatBitsToUint(s.p3.x)); write_mem(a, ix + 6, s.succ_ix);
write_mem(a, ix + 7, floatBitsToUint(s.p3.y)); write_mem(a, ix + 7, s.path_ix);
write_mem(a, ix + 8, s.path_ix); write_mem(a, ix + 8, floatBitsToUint(s.stroke.x));
write_mem(a, ix + 9, floatBitsToUint(s.stroke.x)); write_mem(a, ix + 9, floatBitsToUint(s.stroke.y));
write_mem(a, ix + 10, floatBitsToUint(s.stroke.y));
} }
uint PathSeg_tag(Alloc a, PathSegRef ref) { uint PathSeg_tag(Alloc a, PathSegRef ref) {
return read_mem(a, ref.offset >> 2); return read_mem(a, ref.offset >> 2);
} }
PathFillLine PathSeg_FillLine_read(Alloc a, PathSegRef ref) {
return PathFillLine_read(a, PathFillLineRef(ref.offset + 4));
}
PathStrokeLine PathSeg_StrokeLine_read(Alloc a, PathSegRef ref) {
return PathStrokeLine_read(a, PathStrokeLineRef(ref.offset + 4));
}
PathFillCubic PathSeg_FillCubic_read(Alloc a, PathSegRef ref) { PathFillCubic PathSeg_FillCubic_read(Alloc a, PathSegRef ref) {
return PathFillCubic_read(a, PathFillCubicRef(ref.offset + 4)); return PathFillCubic_read(a, PathFillCubicRef(ref.offset + 4));
} }
@@ -233,16 +135,6 @@ void PathSeg_Nop_write(Alloc a, PathSegRef ref) {
write_mem(a, ref.offset >> 2, PathSeg_Nop); write_mem(a, ref.offset >> 2, PathSeg_Nop);
} }
void PathSeg_FillLine_write(Alloc a, PathSegRef ref, PathFillLine s) {
write_mem(a, ref.offset >> 2, PathSeg_FillLine);
PathFillLine_write(a, PathFillLineRef(ref.offset + 4), s);
}
void PathSeg_StrokeLine_write(Alloc a, PathSegRef ref, PathStrokeLine s) {
write_mem(a, ref.offset >> 2, PathSeg_StrokeLine);
PathStrokeLine_write(a, PathStrokeLineRef(ref.offset + 4), s);
}
void PathSeg_FillCubic_write(Alloc a, PathSegRef ref, PathFillCubic s) { void PathSeg_FillCubic_write(Alloc a, PathSegRef ref, PathFillCubic s) {
write_mem(a, ref.offset >> 2, PathSeg_FillCubic); write_mem(a, ref.offset >> 2, PathSeg_FillCubic);
PathFillCubic_write(a, PathFillCubicRef(ref.offset + 4), s); PathFillCubic_write(a, PathFillCubicRef(ref.offset + 4), s);
+13 -9
View File
@@ -10,13 +10,14 @@ struct State {
vec4 mat; vec4 mat;
vec2 translate; vec2 translate;
vec4 bbox; vec4 bbox;
uint tail;
float linewidth; float linewidth;
uint flags; uint flags;
uint path_count; uint path_count;
uint pathseg_count; uint pathseg_count;
}; };
#define State_size 56 #define State_size 60
StateRef State_index(StateRef ref, uint index) { StateRef State_index(StateRef ref, uint index) {
return StateRef(ref.offset + index * State_size); return StateRef(ref.offset + index * State_size);
@@ -38,14 +39,16 @@ State State_read(StateRef ref) {
uint raw11 = state[ix + 11]; uint raw11 = state[ix + 11];
uint raw12 = state[ix + 12]; uint raw12 = state[ix + 12];
uint raw13 = state[ix + 13]; uint raw13 = state[ix + 13];
uint raw14 = state[ix + 14];
State s; State s;
s.mat = vec4(uintBitsToFloat(raw0), uintBitsToFloat(raw1), uintBitsToFloat(raw2), uintBitsToFloat(raw3)); s.mat = vec4(uintBitsToFloat(raw0), uintBitsToFloat(raw1), uintBitsToFloat(raw2), uintBitsToFloat(raw3));
s.translate = vec2(uintBitsToFloat(raw4), uintBitsToFloat(raw5)); s.translate = vec2(uintBitsToFloat(raw4), uintBitsToFloat(raw5));
s.bbox = vec4(uintBitsToFloat(raw6), uintBitsToFloat(raw7), uintBitsToFloat(raw8), uintBitsToFloat(raw9)); s.bbox = vec4(uintBitsToFloat(raw6), uintBitsToFloat(raw7), uintBitsToFloat(raw8), uintBitsToFloat(raw9));
s.linewidth = uintBitsToFloat(raw10); s.tail = raw10;
s.flags = raw11; s.linewidth = uintBitsToFloat(raw11);
s.path_count = raw12; s.flags = raw12;
s.pathseg_count = raw13; s.path_count = raw13;
s.pathseg_count = raw14;
return s; return s;
} }
@@ -61,9 +64,10 @@ void State_write(StateRef ref, State s) {
state[ix + 7] = floatBitsToUint(s.bbox.y); state[ix + 7] = floatBitsToUint(s.bbox.y);
state[ix + 8] = floatBitsToUint(s.bbox.z); state[ix + 8] = floatBitsToUint(s.bbox.z);
state[ix + 9] = floatBitsToUint(s.bbox.w); state[ix + 9] = floatBitsToUint(s.bbox.w);
state[ix + 10] = floatBitsToUint(s.linewidth); state[ix + 10] = s.tail;
state[ix + 11] = s.flags; state[ix + 11] = floatBitsToUint(s.linewidth);
state[ix + 12] = s.path_count; state[ix + 12] = s.flags;
state[ix + 13] = s.pathseg_count; state[ix + 13] = s.path_count;
state[ix + 14] = s.pathseg_count;
} }