diff --git a/piet-gpu-types/src/annotated.rs b/piet-gpu-types/src/annotated.rs index 247ab12..f7a6ad6 100644 --- a/piet-gpu-types/src/annotated.rs +++ b/piet-gpu-types/src/annotated.rs @@ -3,7 +3,14 @@ use piet_gpu_derive::piet_gpu; piet_gpu! { #[gpu_write] mod annotated { - struct AnnoLineSeg { + struct AnnoFillLineSeg { + p0: [f32; 2], + p1: [f32; 2], + // A note: the layout of this struct is shared with + // AnnoStrokeLineSeg. In that case, we actually write + // [0.0, 0.0] as the stroke field, to minimize divergence. + } + struct AnnoStrokeLineSeg { p0: [f32; 2], p1: [f32; 2], // halfwidth in both x and y for binning @@ -35,8 +42,8 @@ piet_gpu! { } enum Annotated { Nop, - // The segments need a flag to indicate fill/stroke - Line(AnnoLineSeg), + FillLine(AnnoFillLineSeg), + StrokeLine(AnnoStrokeLineSeg), Quad(AnnoQuadSeg), Cubic(AnnoCubicSeg), Stroke(AnnoStroke), diff --git a/piet-gpu-types/src/bins.rs b/piet-gpu-types/src/bins.rs index 88f16f1..1ac2413 100644 --- a/piet-gpu-types/src/bins.rs +++ b/piet-gpu-types/src/bins.rs @@ -7,6 +7,9 @@ piet_gpu! { mod bins { struct BinInstance { element_ix: u32, + // Right edge of the bounding box of the associated fill + // element; used in backdrop computation. + right_edge: f32, } struct BinChunk { diff --git a/piet-gpu-types/src/scene.rs b/piet-gpu-types/src/scene.rs index 7451c9c..5792c94 100644 --- a/piet-gpu-types/src/scene.rs +++ b/piet-gpu-types/src/scene.rs @@ -85,8 +85,15 @@ piet_gpu! { } enum Element { Nop, - // The segments need a flag to indicate fill/stroke - Line(LineSeg), + // Another approach to encoding would be to use a single + // variant but have a bool for fill/stroke. This could be + // packed into the tag, so the on-the-wire representation + // would be very similar to what's here. + StrokeLine(LineSeg), + FillLine(LineSeg), + + // Note: we'll need to handle the stroke/fill distinction + // for these as well, when we do flattening on the GPU. Quad(QuadSeg), Cubic(CubicSeg), Stroke(Stroke), diff --git a/piet-gpu/shader/annotated.h b/piet-gpu/shader/annotated.h index a3fc464..9812264 100644 --- a/piet-gpu/shader/annotated.h +++ b/piet-gpu/shader/annotated.h @@ -1,6 +1,10 @@ // Code auto-generated by piet-gpu-derive -struct AnnoLineSegRef { +struct AnnoFillLineSegRef { + uint offset; +}; + +struct AnnoStrokeLineSegRef { uint offset; }; @@ -24,16 +28,27 @@ struct AnnotatedRef { uint offset; }; -struct AnnoLineSeg { +struct AnnoFillLineSeg { + vec2 p0; + vec2 p1; +}; + +#define AnnoFillLineSeg_size 16 + +AnnoFillLineSegRef AnnoFillLineSeg_index(AnnoFillLineSegRef ref, uint index) { + return AnnoFillLineSegRef(ref.offset + index * AnnoFillLineSeg_size); +} + +struct AnnoStrokeLineSeg { vec2 p0; vec2 p1; vec2 stroke; }; -#define AnnoLineSeg_size 24 +#define AnnoStrokeLineSeg_size 24 -AnnoLineSegRef AnnoLineSeg_index(AnnoLineSegRef ref, uint index) { - return AnnoLineSegRef(ref.offset + index * AnnoLineSeg_size); +AnnoStrokeLineSegRef AnnoStrokeLineSeg_index(AnnoStrokeLineSegRef ref, uint index) { + return AnnoStrokeLineSegRef(ref.offset + index * AnnoStrokeLineSeg_size); } struct AnnoQuadSeg { @@ -87,18 +102,39 @@ AnnoStrokeRef AnnoStroke_index(AnnoStrokeRef ref, uint index) { } #define Annotated_Nop 0 -#define Annotated_Line 1 -#define Annotated_Quad 2 -#define Annotated_Cubic 3 -#define Annotated_Stroke 4 -#define Annotated_Fill 5 +#define Annotated_FillLine 1 +#define Annotated_StrokeLine 2 +#define Annotated_Quad 3 +#define Annotated_Cubic 4 +#define Annotated_Stroke 5 +#define Annotated_Fill 6 #define Annotated_size 44 AnnotatedRef Annotated_index(AnnotatedRef ref, uint index) { return AnnotatedRef(ref.offset + index * Annotated_size); } -AnnoLineSeg AnnoLineSeg_read(AnnoLineSegRef ref) { +AnnoFillLineSeg AnnoFillLineSeg_read(AnnoFillLineSegRef ref) { + uint ix = ref.offset >> 2; + uint raw0 = annotated[ix + 0]; + uint raw1 = annotated[ix + 1]; + uint raw2 = annotated[ix + 2]; + uint raw3 = annotated[ix + 3]; + AnnoFillLineSeg s; + s.p0 = vec2(uintBitsToFloat(raw0), uintBitsToFloat(raw1)); + s.p1 = vec2(uintBitsToFloat(raw2), uintBitsToFloat(raw3)); + return s; +} + +void AnnoFillLineSeg_write(AnnoFillLineSegRef ref, AnnoFillLineSeg s) { + uint ix = ref.offset >> 2; + annotated[ix + 0] = floatBitsToUint(s.p0.x); + annotated[ix + 1] = floatBitsToUint(s.p0.y); + annotated[ix + 2] = floatBitsToUint(s.p1.x); + annotated[ix + 3] = floatBitsToUint(s.p1.y); +} + +AnnoStrokeLineSeg AnnoStrokeLineSeg_read(AnnoStrokeLineSegRef ref) { uint ix = ref.offset >> 2; uint raw0 = annotated[ix + 0]; uint raw1 = annotated[ix + 1]; @@ -106,14 +142,14 @@ AnnoLineSeg AnnoLineSeg_read(AnnoLineSegRef ref) { uint raw3 = annotated[ix + 3]; uint raw4 = annotated[ix + 4]; uint raw5 = annotated[ix + 5]; - AnnoLineSeg s; + AnnoStrokeLineSeg s; s.p0 = vec2(uintBitsToFloat(raw0), uintBitsToFloat(raw1)); s.p1 = vec2(uintBitsToFloat(raw2), uintBitsToFloat(raw3)); s.stroke = vec2(uintBitsToFloat(raw4), uintBitsToFloat(raw5)); return s; } -void AnnoLineSeg_write(AnnoLineSegRef ref, AnnoLineSeg s) { +void AnnoStrokeLineSeg_write(AnnoStrokeLineSegRef ref, AnnoStrokeLineSeg s) { uint ix = ref.offset >> 2; annotated[ix + 0] = floatBitsToUint(s.p0.x); annotated[ix + 1] = floatBitsToUint(s.p0.y); @@ -239,8 +275,12 @@ uint Annotated_tag(AnnotatedRef ref) { return annotated[ref.offset >> 2]; } -AnnoLineSeg Annotated_Line_read(AnnotatedRef ref) { - return AnnoLineSeg_read(AnnoLineSegRef(ref.offset + 4)); +AnnoFillLineSeg Annotated_FillLine_read(AnnotatedRef ref) { + return AnnoFillLineSeg_read(AnnoFillLineSegRef(ref.offset + 4)); +} + +AnnoStrokeLineSeg Annotated_StrokeLine_read(AnnotatedRef ref) { + return AnnoStrokeLineSeg_read(AnnoStrokeLineSegRef(ref.offset + 4)); } AnnoQuadSeg Annotated_Quad_read(AnnotatedRef ref) { @@ -263,9 +303,14 @@ void Annotated_Nop_write(AnnotatedRef ref) { annotated[ref.offset >> 2] = Annotated_Nop; } -void Annotated_Line_write(AnnotatedRef ref, AnnoLineSeg s) { - annotated[ref.offset >> 2] = Annotated_Line; - AnnoLineSeg_write(AnnoLineSegRef(ref.offset + 4), s); +void Annotated_FillLine_write(AnnotatedRef ref, AnnoFillLineSeg s) { + annotated[ref.offset >> 2] = Annotated_FillLine; + AnnoFillLineSeg_write(AnnoFillLineSegRef(ref.offset + 4), s); +} + +void Annotated_StrokeLine_write(AnnotatedRef ref, AnnoStrokeLineSeg s) { + annotated[ref.offset >> 2] = Annotated_StrokeLine; + AnnoStrokeLineSeg_write(AnnoStrokeLineSegRef(ref.offset + 4), s); } void Annotated_Quad_write(AnnotatedRef ref, AnnoQuadSeg s) { diff --git a/piet-gpu/shader/binning.comp b/piet-gpu/shader/binning.comp index cba0217..60b12e0 100644 --- a/piet-gpu/shader/binning.comp +++ b/piet-gpu/shader/binning.comp @@ -84,8 +84,9 @@ void main() { int x0 = 0, y0 = 0, x1 = 0, y1 = 0; float my_right_edge = INFINITY; switch (tag) { - case Annotated_Line: - AnnoLineSeg line = Annotated_Line_read(ref); + case Annotated_FillLine: + case Annotated_StrokeLine: + AnnoStrokeLineSeg line = Annotated_StrokeLine_read(ref); x0 = int(floor((min(line.p0.x, line.p1.x) - line.stroke.x) * SX)); y0 = int(floor((min(line.p0.y, line.p1.y) - line.stroke.y) * SY)); x1 = int(ceil((max(line.p0.x, line.p1.x) + line.stroke.x) * SX)); @@ -107,7 +108,7 @@ void main() { // If the last element in this partition is a fill edge, then we need to do a // look-forward to find the right edge of its corresponding fill. That data is // recorded in aggregates computed in the element processing pass. - if (gl_LocalInvocationID.x == N_TILE - 1 && tag == Annotated_Line) { + if (gl_LocalInvocationID.x == N_TILE - 1 && tag == Annotated_FillLine) { uint aggregate_ix = (my_tile + 1) * ELEMENT_BINNING_RATIO; // This is sequential but the expectation is that the amount of // look-forward is small (performance may degrade in the case @@ -165,9 +166,9 @@ void main() { uint chunk_new_start; // Refactor to reduce code duplication? if (chunk_n > 0) { - uint next_chunk = chunk_ref.offset + BinChunk_size + chunk_n * 4; - if (next_chunk + BinChunk_size + min(24, element_count * 4) > wr_limit) { - uint alloc_amount = max(BIN_ALLOC, BinChunk_size + element_count * 4); + uint next_chunk = chunk_ref.offset + BinChunk_size + chunk_n * BinInstance_size; + if (next_chunk + BinChunk_size + min(24, element_count * BinInstance_size) > wr_limit) { + uint alloc_amount = max(BIN_ALLOC, BinChunk_size + element_count * BinInstance_size); // could try to reduce fragmentation if BIN_ALLOC is only a bit above needed next_chunk = atomicAdd(alloc, alloc_amount); wr_limit = next_chunk + alloc_amount; @@ -176,10 +177,10 @@ void main() { chunk_ref = BinChunkRef(next_chunk); } BinInstanceRef instance_ref = BinInstanceRef(chunk_ref.offset + BinChunk_size); - if (instance_ref.offset + element_count * 4 > wr_limit) { + if (instance_ref.offset + element_count * BinInstance_size > wr_limit) { chunk_end = wr_limit; - chunk_n = (wr_limit - instance_ref.offset) / 4; - uint alloc_amount = max(BIN_ALLOC, BinChunk_size + (element_count - chunk_n) * 4); + chunk_n = (wr_limit - instance_ref.offset) / BinInstance_size; + uint alloc_amount = max(BIN_ALLOC, BinChunk_size + (element_count - chunk_n) * BinInstance_size); chunk_new_start = atomicAdd(alloc, alloc_amount); wr_limit = chunk_new_start + alloc_amount; BinChunk_write(chunk_ref, BinChunk(chunk_n, BinChunkRef(chunk_new_start))); @@ -209,11 +210,11 @@ void main() { if (my_slice > 0) { idx += count[my_slice - 1][bin_ix]; } - uint out_offset = sh_chunk_start[bin_ix] + idx * 4; + uint out_offset = sh_chunk_start[bin_ix] + idx * BinInstance_size; if (out_offset >= sh_chunk_end[bin_ix]) { out_offset += sh_chunk_jump[bin_ix]; } - BinInstance_write(BinInstanceRef(out_offset), BinInstance(element_ix)); + BinInstance_write(BinInstanceRef(out_offset), BinInstance(element_ix, my_right_edge)); } x++; if (x == x1) { diff --git a/piet-gpu/shader/binning.spv b/piet-gpu/shader/binning.spv index a5379e6..4fda673 100644 Binary files a/piet-gpu/shader/binning.spv and b/piet-gpu/shader/binning.spv differ diff --git a/piet-gpu/shader/bins.h b/piet-gpu/shader/bins.h index 3ce06e0..85f7536 100644 --- a/piet-gpu/shader/bins.h +++ b/piet-gpu/shader/bins.h @@ -10,9 +10,10 @@ struct BinChunkRef { struct BinInstance { uint element_ix; + float right_edge; }; -#define BinInstance_size 4 +#define BinInstance_size 8 BinInstanceRef BinInstance_index(BinInstanceRef ref, uint index) { return BinInstanceRef(ref.offset + index * BinInstance_size); @@ -32,14 +33,17 @@ BinChunkRef BinChunk_index(BinChunkRef ref, uint index) { BinInstance BinInstance_read(BinInstanceRef ref) { uint ix = ref.offset >> 2; uint raw0 = bins[ix + 0]; + uint raw1 = bins[ix + 1]; BinInstance s; s.element_ix = raw0; + s.right_edge = uintBitsToFloat(raw1); return s; } void BinInstance_write(BinInstanceRef ref, BinInstance s) { uint ix = ref.offset >> 2; bins[ix + 0] = s.element_ix; + bins[ix + 1] = floatBitsToUint(s.right_edge); } BinChunk BinChunk_read(BinChunkRef ref) { diff --git a/piet-gpu/shader/coarse.comp b/piet-gpu/shader/coarse.comp index e331076..57abd73 100644 --- a/piet-gpu/shader/coarse.comp +++ b/piet-gpu/shader/coarse.comp @@ -30,6 +30,7 @@ layout(set = 0, binding = 3) buffer PtclBuf { #define N_RINGBUF 512 shared uint sh_elements[N_RINGBUF]; +shared float sh_right_edge[N_RINGBUF]; shared uint sh_chunk[N_WG]; shared uint sh_chunk_next[N_WG]; shared uint sh_chunk_n[N_WG]; @@ -41,6 +42,7 @@ shared uint sh_selected_n; shared uint sh_elements_ref; shared uint sh_bitmaps[N_SLICE][N_TILE]; +shared uint sh_backdrop[N_SLICE][N_TILE]; // scale factors useful for converting coordinates to tiles #define SX (1.0 / float(TILE_WIDTH_PX)) @@ -113,6 +115,7 @@ void main() { while (true) { for (uint i = 0; i < N_SLICE; i++) { sh_bitmaps[i][th_ix] = 0; + sh_backdrop[i][th_ix] = 0; } while (wr_ix - rd_ix <= N_TILE) { @@ -157,8 +160,10 @@ void main() { } BinInstanceRef inst_ref = BinInstanceRef(sh_elements_ref); if (th_ix < chunk_n) { - uint el = BinInstance_read(BinInstance_index(inst_ref, th_ix)).element_ix; - sh_elements[(wr_ix + th_ix) % N_RINGBUF] = el; + BinInstance inst = BinInstance_read(BinInstance_index(inst_ref, th_ix)); + uint wr_el_ix = (wr_ix + th_ix) % N_RINGBUF; + sh_elements[wr_el_ix] = inst.element_ix; + sh_right_edge[wr_el_ix] = inst.right_edge; } wr_ix += chunk_n; } @@ -180,8 +185,9 @@ void main() { // Bounding box of element in pixel coordinates. float xmin, xmax, ymin, ymax; switch (tag) { - case Annotated_Line: - AnnoLineSeg line = Annotated_Line_read(ref); + case Annotated_FillLine: + case Annotated_StrokeLine: + AnnoStrokeLineSeg line = Annotated_StrokeLine_read(ref); xmin = min(line.p0.x, line.p1.x) - line.stroke.x; xmax = max(line.p0.x, line.p1.x) + line.stroke.x; ymin = min(line.p0.y, line.p1.y) - line.stroke.y; @@ -214,7 +220,7 @@ void main() { break; } - // Draw the coverage area into the bitmaks. This uses an algorithm + // Draw the coverage area into the bitmasks. This uses an algorithm // that computes the coverage of a span for given scanline. // Compute bounding box in tiles and clip to this bin. @@ -263,15 +269,27 @@ void main() { tag = Annotated_tag(ref); switch (tag) { - case Annotated_Line: - AnnoLineSeg line = Annotated_Line_read(ref); + case Annotated_FillLine: + case Annotated_StrokeLine: + AnnoStrokeLineSeg line = Annotated_StrokeLine_read(ref); Segment seg = Segment(line.p0, line.p1); alloc_chunk(chunk_n_segs, seg_chunk_ref, first_seg_chunk, seg_limit); Segment_write(SegmentRef(seg_chunk_ref.offset + SegChunk_size + Segment_size * chunk_n_segs), seg); chunk_n_segs++; break; case Annotated_Fill: - chunk_n_segs = 0; + if (chunk_n_segs > 0) { + AnnoFill fill = Annotated_Fill_read(ref); + SegChunk_write(seg_chunk_ref, SegChunk(chunk_n_segs, SegChunkRef(0))); + seg_chunk_ref.offset += SegChunk_size + Segment_size * chunk_n_segs; + CmdFill cmd_fill; + cmd_fill.seg_ref = first_seg_chunk.offset; + cmd_fill.rgba_color = fill.rgba_color; + alloc_cmd(cmd_ref, cmd_limit); + Cmd_Fill_write(cmd_ref, cmd_fill); + cmd_ref.offset += Cmd_size; + chunk_n_segs = 0; + } break; case Annotated_Stroke: if (chunk_n_segs > 0) { diff --git a/piet-gpu/shader/coarse.spv b/piet-gpu/shader/coarse.spv index d61b227..e201c5e 100644 Binary files a/piet-gpu/shader/coarse.spv and b/piet-gpu/shader/coarse.spv differ diff --git a/piet-gpu/shader/elements.comp b/piet-gpu/shader/elements.comp index 15ad80d..341952b 100644 --- a/piet-gpu/shader/elements.comp +++ b/piet-gpu/shader/elements.comp @@ -98,8 +98,9 @@ State map_element(ElementRef ref) { c.linewidth = 1.0; // TODO should be 0.0 c.flags = 0; switch (tag) { - case Element_Line: - LineSeg line = Element_Line_read(ref); + case Element_FillLine: + case Element_StrokeLine: + LineSeg line = Element_FillLine_read(ref); c.bbox.xy = min(line.p0, line.p1); c.bbox.zw = max(line.p0, line.p1); break; @@ -272,13 +273,22 @@ void main() { AnnotatedRef out_ref = AnnotatedRef((ix + i) * Annotated_size); uint tag = Element_tag(this_ref); switch (tag) { - case Element_Line: - LineSeg line = Element_Line_read(this_ref); - AnnoLineSeg anno_line; + case Element_FillLine: + case Element_StrokeLine: + LineSeg line = Element_StrokeLine_read(this_ref); + AnnoStrokeLineSeg anno_line; anno_line.p0 = st.mat.xz * line.p0.x + st.mat.yw * line.p0.y + st.translate; anno_line.p1 = st.mat.xz * line.p1.x + st.mat.yw * line.p1.y + st.translate; - anno_line.stroke = get_linewidth(st); - Annotated_Line_write(out_ref, anno_line); + if (tag == Element_StrokeLine) { + anno_line.stroke = get_linewidth(st); + } else { + anno_line.stroke = vec2(0.0); + } + // We do encoding a bit by hand to minimize divergence. Another approach + // would be to have a fill/stroke bool. + uint out_tag = tag == Element_FillLine ? Annotated_FillLine : Annotated_StrokeLine; + annotated[out_ref.offset >> 2] = out_tag; + AnnoStrokeLineSeg_write(AnnoStrokeLineSegRef(out_ref.offset + 4), anno_line); break; case Element_Stroke: Stroke stroke = Element_Stroke_read(this_ref); diff --git a/piet-gpu/shader/elements.spv b/piet-gpu/shader/elements.spv index ff0ae2d..c947240 100644 Binary files a/piet-gpu/shader/elements.spv and b/piet-gpu/shader/elements.spv differ diff --git a/piet-gpu/shader/scene.h b/piet-gpu/shader/scene.h index 84ef80d..5bb879b 100644 --- a/piet-gpu/shader/scene.h +++ b/piet-gpu/shader/scene.h @@ -238,13 +238,14 @@ TransformRef Transform_index(TransformRef ref, uint index) { } #define Element_Nop 0 -#define Element_Line 1 -#define Element_Quad 2 -#define Element_Cubic 3 -#define Element_Stroke 4 -#define Element_Fill 5 -#define Element_SetLineWidth 6 -#define Element_Transform 7 +#define Element_StrokeLine 1 +#define Element_FillLine 2 +#define Element_Quad 3 +#define Element_Cubic 4 +#define Element_Stroke 5 +#define Element_Fill 6 +#define Element_SetLineWidth 7 +#define Element_Transform 8 #define Element_size 36 ElementRef Element_index(ElementRef ref, uint index) { @@ -446,7 +447,11 @@ uint Element_tag(ElementRef ref) { return scene[ref.offset >> 2]; } -LineSeg Element_Line_read(ElementRef ref) { +LineSeg Element_StrokeLine_read(ElementRef ref) { + return LineSeg_read(LineSegRef(ref.offset + 4)); +} + +LineSeg Element_FillLine_read(ElementRef ref) { return LineSeg_read(LineSegRef(ref.offset + 4)); } diff --git a/piet-gpu/src/pico_svg.rs b/piet-gpu/src/pico_svg.rs index 9cf5cc3..b2f054c 100644 --- a/piet-gpu/src/pico_svg.rs +++ b/piet-gpu/src/pico_svg.rs @@ -61,8 +61,8 @@ impl PicoSvg { for item in &self.items { match item { Item::Fill(fill_item) => { - //rc.fill(&fill_item.path, &fill_item.color); - rc.stroke(&fill_item.path, &fill_item.color, 1.0); + rc.fill(&fill_item.path, &fill_item.color); + //rc.stroke(&fill_item.path, &fill_item.color, 1.0); } Item::Stroke(stroke_item) => { rc.stroke(&stroke_item.path, &stroke_item.color, stroke_item.width); diff --git a/piet-gpu/src/render_ctx.rs b/piet-gpu/src/render_ctx.rs index e01a6ae..8d68b0c 100644 --- a/piet-gpu/src/render_ctx.rs +++ b/piet-gpu/src/render_ctx.rs @@ -94,7 +94,7 @@ impl RenderContext for PietGpuRenderContext { } let brush = brush.make_brush(self, || shape.bounding_box()).into_owned(); let path = shape.to_bez_path(TOLERANCE); - self.encode_path(path); + self.encode_path(path, false); match brush { PietGpuBrush::Solid(rgba_color) => { let stroke = Stroke { rgba_color }; @@ -116,7 +116,7 @@ impl RenderContext for PietGpuRenderContext { fn fill(&mut self, shape: impl Shape, brush: &impl IntoBrush) { let brush = brush.make_brush(self, || shape.bounding_box()).into_owned(); let path = shape.to_bez_path(TOLERANCE); - self.encode_path(path); + self.encode_path(path, true); match brush { PietGpuBrush::Solid(rgba_color) => { let fill = Fill { rgba_color }; @@ -198,7 +198,15 @@ impl RenderContext for PietGpuRenderContext { } impl PietGpuRenderContext { - fn encode_path(&mut self, path: impl Iterator) { + fn encode_line_seg(&mut self, seg: LineSeg, is_fill: bool) { + if is_fill { + self.elements.push(Element::FillLine(seg)); + } else { + self.elements.push(Element::StrokeLine(seg)); + } + } + + fn encode_path(&mut self, path: impl Iterator, is_fill: bool) { let flatten = true; if flatten { let mut start_pt = None; @@ -215,7 +223,7 @@ impl PietGpuRenderContext { p0: last_pt.unwrap(), p1: scene_pt, }; - self.elements.push(Element::Line(seg)); + self.encode_line_seg(seg, is_fill); last_pt = Some(scene_pt); } PathEl::ClosePath => { @@ -224,7 +232,7 @@ impl PietGpuRenderContext { p0: last, p1: start, }; - self.elements.push(Element::Line(seg)); + self.encode_line_seg(seg, is_fill); } } _ => (), @@ -246,7 +254,7 @@ impl PietGpuRenderContext { p0: last_pt.unwrap(), p1: scene_pt, }; - self.elements.push(Element::Line(seg)); + self.encode_line_seg(seg, is_fill); last_pt = Some(scene_pt); } PathEl::QuadTo(p1, p2) => { @@ -279,7 +287,7 @@ impl PietGpuRenderContext { p0: last, p1: start, }; - self.elements.push(Element::Line(seg)); + self.encode_line_seg(seg, is_fill); } } }