mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-07 02:15:34 +00:00
gpu,gpu/shaders: revert attempt to fix path gaps
This is effectively a revert of [0], reintroducing the path gaps described in [1]. A follow-up change will implement another attempt. [0] https://gioui.org/commit/2feec23561cd84d6b8ddbab84a202df66b123208 [1] https://github.com/linebender/piet-gpu/issues/62 Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
+8
-47
@@ -173,16 +173,12 @@ const (
|
|||||||
|
|
||||||
pathSize = 12
|
pathSize = 12
|
||||||
binSize = 8
|
binSize = 8
|
||||||
pathsegSize = 44
|
pathsegSize = 48
|
||||||
annoSize = 28
|
annoSize = 28
|
||||||
stateSize = 60
|
stateSize = 56
|
||||||
stateStride = 4 + 2*stateSize
|
stateStride = 4 + 2*stateSize
|
||||||
)
|
)
|
||||||
|
|
||||||
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
|
||||||
@@ -680,49 +676,14 @@ func encodePath(pathData []byte, stroke clip.StrokeStyle, dashes dashOp) encoder
|
|||||||
q := quad.quad
|
q := quad.quad
|
||||||
enc.quad(q.From, q.Ctrl, q.To, false)
|
enc.quad(q.From, q.Ctrl, q.To, false)
|
||||||
}
|
}
|
||||||
if len(quads) > 0 {
|
|
||||||
enc.scene[len(enc.scene)-1][0] |= (flagEndPath << 16)
|
|
||||||
}
|
|
||||||
return enc
|
return enc
|
||||||
}
|
}
|
||||||
var (
|
|
||||||
prevTo f32.Point
|
|
||||||
hasPrev bool
|
|
||||||
)
|
|
||||||
for len(pathData) >= scene.CommandSize+4 {
|
for len(pathData) >= scene.CommandSize+4 {
|
||||||
cmd := ops.DecodeCommand(pathData[4:])
|
cmd := ops.DecodeCommand(pathData[4:])
|
||||||
switch cmd.Op() {
|
|
||||||
case scene.OpFillLine:
|
|
||||||
from, to := scene.DecodeLine(cmd)
|
|
||||||
if hasPrev && from != prevTo {
|
|
||||||
enc.scene[len(enc.scene)-1][0] |= (flagEndPath << 16)
|
|
||||||
}
|
|
||||||
hasPrev = true
|
|
||||||
prevTo = to
|
|
||||||
case scene.OpFillQuad:
|
|
||||||
from, _, to := scene.DecodeQuad(cmd)
|
|
||||||
if hasPrev && from != prevTo {
|
|
||||||
enc.scene[len(enc.scene)-1][0] |= (flagEndPath << 16)
|
|
||||||
}
|
|
||||||
hasPrev = true
|
|
||||||
prevTo = to
|
|
||||||
case scene.OpFillCubic:
|
|
||||||
from, _, _, to := scene.DecodeCubic(cmd)
|
|
||||||
if hasPrev && from != prevTo {
|
|
||||||
enc.scene[len(enc.scene)-1][0] |= (flagEndPath << 16)
|
|
||||||
}
|
|
||||||
hasPrev = true
|
|
||||||
prevTo = to
|
|
||||||
default:
|
|
||||||
panic("unsupported path scene command")
|
|
||||||
}
|
|
||||||
enc.scene = append(enc.scene, cmd)
|
enc.scene = append(enc.scene, cmd)
|
||||||
enc.npathseg++
|
enc.npathseg++
|
||||||
pathData = pathData[scene.CommandSize+4:]
|
pathData = pathData[scene.CommandSize+4:]
|
||||||
}
|
}
|
||||||
if hasPrev {
|
|
||||||
enc.scene[len(enc.scene)-1][0] |= (flagEndPath << 16)
|
|
||||||
}
|
|
||||||
return enc
|
return enc
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1049,10 +1010,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, 0)
|
e.line(c0, c1, stroke)
|
||||||
e.line(c1, c2, stroke, 0)
|
e.line(c1, c2, stroke)
|
||||||
e.line(c2, c3, stroke, 0)
|
e.line(c2, c3, stroke)
|
||||||
e.line(c3, c0, stroke, flagEndPath)
|
e.line(c3, c0, stroke)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *encoder) fill(col color.RGBA) {
|
func (e *encoder) fill(col color.RGBA) {
|
||||||
@@ -1071,8 +1032,8 @@ func (e *encoder) fillImage(index int) {
|
|||||||
e.npath++
|
e.npath++
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *encoder) line(start, end f32.Point, stroke bool, flags uint32) {
|
func (e *encoder) line(start, end f32.Point, stroke bool) {
|
||||||
e.scene = append(e.scene, scene.Line(start, end, stroke, flags))
|
e.scene = append(e.scene, scene.Line(start, end, stroke))
|
||||||
e.npathseg++
|
e.npathseg++
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+4
-4
@@ -1506,16 +1506,16 @@ func (d *drawOps) boundsForTransformedRect(r f32.Rectangle, tr f32.Affine2D) (au
|
|||||||
buf := aux
|
buf := aux
|
||||||
bo := binary.LittleEndian
|
bo := binary.LittleEndian
|
||||||
bo.PutUint32(buf, 0) // Contour
|
bo.PutUint32(buf, 0) // Contour
|
||||||
ops.EncodeCommand(buf[4:], scene.Line(r.Min, f32.Pt(r.Max.X, r.Min.Y), false, 0))
|
ops.EncodeCommand(buf[4:], scene.Line(r.Min, f32.Pt(r.Max.X, r.Min.Y), false))
|
||||||
buf = buf[4+scene.CommandSize:]
|
buf = buf[4+scene.CommandSize:]
|
||||||
bo.PutUint32(buf, 0)
|
bo.PutUint32(buf, 0)
|
||||||
ops.EncodeCommand(buf[4:], scene.Line(f32.Pt(r.Max.X, r.Min.Y), r.Max, false, 0))
|
ops.EncodeCommand(buf[4:], scene.Line(f32.Pt(r.Max.X, r.Min.Y), r.Max, false))
|
||||||
buf = buf[4+scene.CommandSize:]
|
buf = buf[4+scene.CommandSize:]
|
||||||
bo.PutUint32(buf, 0)
|
bo.PutUint32(buf, 0)
|
||||||
ops.EncodeCommand(buf[4:], scene.Line(r.Max, f32.Pt(r.Min.X, r.Max.Y), false, 0))
|
ops.EncodeCommand(buf[4:], scene.Line(r.Max, f32.Pt(r.Min.X, r.Max.Y), false))
|
||||||
buf = buf[4+scene.CommandSize:]
|
buf = buf[4+scene.CommandSize:]
|
||||||
bo.PutUint32(buf, 0)
|
bo.PutUint32(buf, 0)
|
||||||
ops.EncodeCommand(buf[4:], scene.Line(f32.Pt(r.Min.X, r.Max.Y), r.Min, false, 0))
|
ops.EncodeCommand(buf[4:], scene.Line(f32.Pt(r.Min.X, r.Max.Y), r.Min, false))
|
||||||
}
|
}
|
||||||
|
|
||||||
// establish the transform mapping from bounds rectangle to transformed corners
|
// establish the transform mapping from bounds rectangle to transformed corners
|
||||||
|
|||||||
+2
-2
File diff suppressed because one or more lines are too long
@@ -62,8 +62,6 @@ 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)
|
||||||
@@ -89,45 +87,32 @@ 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 | FLAG_START_PATH)) | b.flags;
|
c.flags = (a.flags & (FLAG_SET_LINEWIDTH | FLAG_SET_BBOX)) | 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_flags = Element_tag(ref);
|
uint tag = 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;
|
||||||
// flags contain FLAG_END_PATH for segments last in their path.
|
switch (tag) {
|
||||||
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:
|
||||||
@@ -135,7 +120,6 @@ 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:
|
||||||
@@ -143,7 +127,6 @@ 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:
|
||||||
@@ -183,7 +166,6 @@ 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];
|
||||||
|
|
||||||
@@ -218,7 +200,6 @@ 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;
|
||||||
@@ -232,7 +213,6 @@ 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);
|
||||||
@@ -243,7 +223,6 @@ 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;
|
||||||
}
|
}
|
||||||
@@ -254,7 +233,6 @@ 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;
|
||||||
|
|
||||||
@@ -334,7 +312,6 @@ 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);
|
||||||
@@ -346,9 +323,7 @@ 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_flags = Element_tag(this_ref);
|
uint tag = 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:
|
||||||
@@ -359,7 +334,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.succ_ix = (flags & FLAG_END_PATH) == 0 ? st.pathseg_count : st.tail;
|
path_cubic.p3 = p1;
|
||||||
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);
|
||||||
@@ -383,7 +358,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.succ_ix = (flags & FLAG_END_PATH) == 0 ? st.pathseg_count : st.tail;
|
path_cubic.p3 = p2;
|
||||||
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);
|
||||||
@@ -404,7 +379,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.succ_ix = (flags & FLAG_END_PATH) == 0 ? st.pathseg_count : st.tail;
|
path_cubic.p3 = st.mat.xy * cubic.p3.x + st.mat.zw * cubic.p3.y + st.translate;
|
||||||
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);
|
||||||
|
|||||||
@@ -86,14 +86,6 @@ 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;
|
||||||
@@ -110,9 +102,7 @@ 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);
|
||||||
PathSegRef succ_ref = PathSegRef(conf.pathseg_alloc.offset + cubic.succ_ix * PathSeg_size);
|
vec2 err_v = 3.0 * (cubic.p2 - cubic.p1) + cubic.p0 - cubic.p3;
|
||||||
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);
|
||||||
@@ -122,8 +112,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, p3, t);
|
vec2 qp2 = eval_cubic(cubic.p0, cubic.p1, cubic.p2, cubic.p3, t);
|
||||||
vec2 qp1 = eval_cubic(cubic.p0, cubic.p1, cubic.p2, p3, t - 0.5 * step);
|
vec2 qp1 = eval_cubic(cubic.p0, cubic.p1, cubic.p2, cubic.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;
|
||||||
@@ -143,8 +133,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, p3, t);
|
vec2 qp2 = eval_cubic(cubic.p0, cubic.p1, cubic.p2, cubic.p3, t);
|
||||||
vec2 qp1 = eval_cubic(cubic.p0, cubic.p1, cubic.p2, p3, t - 0.5 * step);
|
vec2 qp1 = eval_cubic(cubic.p0, cubic.p1, cubic.p2, cubic.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);
|
||||||
@@ -154,7 +144,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 = p3;
|
p1 = cubic.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);
|
||||||
|
|||||||
+20
-16
@@ -18,11 +18,11 @@ struct PathFillCubic {
|
|||||||
vec2 p0;
|
vec2 p0;
|
||||||
vec2 p1;
|
vec2 p1;
|
||||||
vec2 p2;
|
vec2 p2;
|
||||||
uint succ_ix;
|
vec2 p3;
|
||||||
uint path_ix;
|
uint path_ix;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define PathFillCubic_size 32
|
#define PathFillCubic_size 36
|
||||||
|
|
||||||
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);
|
||||||
@@ -32,12 +32,12 @@ struct PathStrokeCubic {
|
|||||||
vec2 p0;
|
vec2 p0;
|
||||||
vec2 p1;
|
vec2 p1;
|
||||||
vec2 p2;
|
vec2 p2;
|
||||||
uint succ_ix;
|
vec2 p3;
|
||||||
uint path_ix;
|
uint path_ix;
|
||||||
vec2 stroke;
|
vec2 stroke;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define PathStrokeCubic_size 40
|
#define PathStrokeCubic_size 44
|
||||||
|
|
||||||
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);
|
||||||
@@ -46,7 +46,7 @@ PathStrokeCubicRef PathStrokeCubic_index(PathStrokeCubicRef ref, uint index) {
|
|||||||
#define PathSeg_Nop 0
|
#define PathSeg_Nop 0
|
||||||
#define PathSeg_FillCubic 1
|
#define PathSeg_FillCubic 1
|
||||||
#define PathSeg_StrokeCubic 2
|
#define PathSeg_StrokeCubic 2
|
||||||
#define PathSeg_size 44
|
#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);
|
||||||
@@ -62,12 +62,13 @@ 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.succ_ix = raw6;
|
s.p3 = vec2(uintBitsToFloat(raw6), uintBitsToFloat(raw7));
|
||||||
s.path_ix = raw7;
|
s.path_ix = raw8;
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,8 +80,9 @@ 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, s.succ_ix);
|
write_mem(a, ix + 6, floatBitsToUint(s.p3.x));
|
||||||
write_mem(a, ix + 7, s.path_ix);
|
write_mem(a, ix + 7, floatBitsToUint(s.p3.y));
|
||||||
|
write_mem(a, ix + 8, s.path_ix);
|
||||||
}
|
}
|
||||||
|
|
||||||
PathStrokeCubic PathStrokeCubic_read(Alloc a, PathStrokeCubicRef ref) {
|
PathStrokeCubic PathStrokeCubic_read(Alloc a, PathStrokeCubicRef ref) {
|
||||||
@@ -95,13 +97,14 @@ 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.succ_ix = raw6;
|
s.p3 = vec2(uintBitsToFloat(raw6), uintBitsToFloat(raw7));
|
||||||
s.path_ix = raw7;
|
s.path_ix = raw8;
|
||||||
s.stroke = vec2(uintBitsToFloat(raw8), uintBitsToFloat(raw9));
|
s.stroke = vec2(uintBitsToFloat(raw9), uintBitsToFloat(raw10));
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,10 +116,11 @@ 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, s.succ_ix);
|
write_mem(a, ix + 6, floatBitsToUint(s.p3.x));
|
||||||
write_mem(a, ix + 7, s.path_ix);
|
write_mem(a, ix + 7, floatBitsToUint(s.p3.y));
|
||||||
write_mem(a, ix + 8, floatBitsToUint(s.stroke.x));
|
write_mem(a, ix + 8, s.path_ix);
|
||||||
write_mem(a, ix + 9, floatBitsToUint(s.stroke.y));
|
write_mem(a, ix + 9, floatBitsToUint(s.stroke.x));
|
||||||
|
write_mem(a, ix + 10, floatBitsToUint(s.stroke.y));
|
||||||
}
|
}
|
||||||
|
|
||||||
uint PathSeg_tag(Alloc a, PathSegRef ref) {
|
uint PathSeg_tag(Alloc a, PathSegRef ref) {
|
||||||
|
|||||||
+9
-13
@@ -10,14 +10,13 @@ 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 60
|
#define State_size 56
|
||||||
|
|
||||||
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);
|
||||||
@@ -39,16 +38,14 @@ 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.tail = raw10;
|
s.linewidth = uintBitsToFloat(raw10);
|
||||||
s.linewidth = uintBitsToFloat(raw11);
|
s.flags = raw11;
|
||||||
s.flags = raw12;
|
s.path_count = raw12;
|
||||||
s.path_count = raw13;
|
s.pathseg_count = raw13;
|
||||||
s.pathseg_count = raw14;
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,10 +61,9 @@ 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] = s.tail;
|
state[ix + 10] = floatBitsToUint(s.linewidth);
|
||||||
state[ix + 11] = floatBitsToUint(s.linewidth);
|
state[ix + 11] = s.flags;
|
||||||
state[ix + 12] = s.flags;
|
state[ix + 12] = s.path_count;
|
||||||
state[ix + 13] = s.path_count;
|
state[ix + 13] = s.pathseg_count;
|
||||||
state[ix + 14] = s.pathseg_count;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -42,13 +42,13 @@ func (c Command) Op() Op {
|
|||||||
return Op(c[0])
|
return Op(c[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
func Line(start, end f32.Point, stroke bool, flags uint32) Command {
|
func Line(start, end f32.Point, stroke bool) Command {
|
||||||
tag := uint32(OpFillLine)
|
tag := uint32(OpFillLine)
|
||||||
if stroke {
|
if stroke {
|
||||||
tag = uint32(OpStrokeLine)
|
tag = uint32(OpStrokeLine)
|
||||||
}
|
}
|
||||||
return Command{
|
return Command{
|
||||||
0: flags<<16 | tag,
|
0: 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),
|
||||||
|
|||||||
+1
-1
@@ -141,7 +141,7 @@ func (p *Path) LineTo(to f32.Point) {
|
|||||||
data := p.ops.Write(scene.CommandSize + 4)
|
data := p.ops.Write(scene.CommandSize + 4)
|
||||||
bo := binary.LittleEndian
|
bo := binary.LittleEndian
|
||||||
bo.PutUint32(data[0:], uint32(p.contour))
|
bo.PutUint32(data[0:], uint32(p.contour))
|
||||||
ops.EncodeCommand(data[4:], scene.Line(p.pen, to, false, 0))
|
ops.EncodeCommand(data[4:], scene.Line(p.pen, to, false))
|
||||||
p.pen = to
|
p.pen = to
|
||||||
p.hasSegments = true
|
p.hasSegments = true
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user