From eb37db1b057f9d4107f4a6cb98281388c1251a15 Mon Sep 17 00:00:00 2001 From: Elias Naur Date: Fri, 19 Mar 2021 13:49:47 +0100 Subject: [PATCH] replace per-element fill mode flags with a SetFillMode element Fixes #70 Signed-off-by: Elias Naur --- piet-gpu-types/src/scene.rs | 14 +++++--- piet-gpu/shader/elements.comp | 16 +++++++-- piet-gpu/shader/elements.spv | Bin 69644 -> 71296 bytes piet-gpu/shader/scene.h | 27 +++++++++++++++ piet-gpu/src/render_ctx.rs | 62 ++++++++++++++++++---------------- 5 files changed, 82 insertions(+), 37 deletions(-) diff --git a/piet-gpu-types/src/scene.rs b/piet-gpu-types/src/scene.rs index 9480ea3..c4a9b9a 100644 --- a/piet-gpu-types/src/scene.rs +++ b/piet-gpu-types/src/scene.rs @@ -1,7 +1,7 @@ use piet_gpu_derive::piet_gpu; pub use self::scene::{ - Clip, CubicSeg, Element, FillColor, LineSeg, QuadSeg, SetLineWidth, Transform, + Clip, CubicSeg, Element, FillColor, LineSeg, QuadSeg, SetFillMode, SetLineWidth, Transform, }; piet_gpu! { @@ -40,19 +40,23 @@ piet_gpu! { bbox: [f32; 4], // TODO: add alpha? } + struct SetFillMode { + fill_mode: u32, + } enum Element { Nop, - Line(TagFlags, LineSeg), - Quad(TagFlags, QuadSeg), - Cubic(TagFlags, CubicSeg), + Line(LineSeg), + Quad(QuadSeg), + Cubic(CubicSeg), - FillColor(TagFlags, FillColor), + FillColor(FillColor), SetLineWidth(SetLineWidth), Transform(Transform), BeginClip(Clip), EndClip(Clip), FillImage(FillImage), + SetFillMode(SetFillMode), } } } diff --git a/piet-gpu/shader/elements.comp b/piet-gpu/shader/elements.comp index 80a456d..7fb02fc 100644 --- a/piet-gpu/shader/elements.comp +++ b/piet-gpu/shader/elements.comp @@ -63,6 +63,11 @@ uint state_flag_index(uint partition_ix) { #define FLAG_SET_LINEWIDTH 1 #define FLAG_SET_BBOX 2 #define FLAG_RESET_BBOX 4 +#define FLAG_SET_FILL_MODE 8 +// Fill modes take up the next bit. Non-zero fill is 0, stroke is 1. +#define LG_FILL_MODE 4 +#define FILL_MODE_BITS 1 +#define FILL_MODE_MASK (FILL_MODE_BITS << LG_FILL_MODE) // This is almost like a monoid (the interaction between transformation and // bounding boxes is approximate) @@ -88,8 +93,11 @@ 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.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.flags = (a.flags & (FLAG_SET_LINEWIDTH | FLAG_SET_BBOX)) | b.flags; + c.flags = (a.flags & (FLAG_SET_LINEWIDTH | FLAG_SET_BBOX | FLAG_SET_FILL_MODE)) | b.flags; c.flags |= (a.flags & FLAG_RESET_BBOX) >> 1; + uint fill_mode = (b.flags & FLAG_SET_FILL_MODE) == 0 ? a.flags : b.flags; + fill_mode &= FILL_MODE_MASK; + c.flags = (c.flags & ~FILL_MODE_MASK) | fill_mode; c.path_count = a.path_count + b.path_count; c.pathseg_count = a.pathseg_count + b.pathseg_count; c.trans_count = a.trans_count + b.trans_count; @@ -148,6 +156,10 @@ State map_element(ElementRef ref) { c.translate = t.translate; c.trans_count = 1; break; + case Element_SetFillMode: + SetFillMode fm = Element_SetFillMode_read(ref); + c.flags = FLAG_SET_FILL_MODE | (fm.fill_mode << LG_FILL_MODE); + break; } return c; } @@ -288,7 +300,7 @@ void main() { // registers (though register pressure is an issue). ElementRef this_ref = Element_index(ref, i); ElementTag tag = Element_tag(this_ref); - uint fill_mode = fill_mode_from_flags(tag.flags); + uint fill_mode = fill_mode_from_flags(st.flags >> LG_FILL_MODE); bool is_stroke = fill_mode == MODE_STROKE; switch (tag.tag) { case Element_Line: diff --git a/piet-gpu/shader/elements.spv b/piet-gpu/shader/elements.spv index c7bade59f2a50152f553f445771e9e7a723b2560..d1ca8dd4f2d9240477bf14ab198f8eff4b1beb20 100644 GIT binary patch literal 71296 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%0A6XU>Y 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 WFW5e9A2SB$=m(Z}e9ob^bNC1DGLaGh diff --git a/piet-gpu/shader/scene.h b/piet-gpu/shader/scene.h index 5dd38b2..38c2549 100644 --- a/piet-gpu/shader/scene.h +++ b/piet-gpu/shader/scene.h @@ -34,6 +34,10 @@ struct ClipRef { uint offset; }; +struct SetFillModeRef { + uint offset; +}; + struct ElementRef { uint offset; }; @@ -126,6 +130,16 @@ ClipRef Clip_index(ClipRef ref, uint index) { return ClipRef(ref.offset + index * Clip_size); } +struct SetFillMode { + uint fill_mode; +}; + +#define SetFillMode_size 4 + +SetFillModeRef SetFillMode_index(SetFillModeRef ref, uint index) { + return SetFillModeRef(ref.offset + index * SetFillMode_size); +} + #define Element_Nop 0 #define Element_Line 1 #define Element_Quad 2 @@ -136,6 +150,7 @@ ClipRef Clip_index(ClipRef ref, uint index) { #define Element_BeginClip 7 #define Element_EndClip 8 #define Element_FillImage 9 +#define Element_SetFillMode 10 #define Element_size 36 ElementRef Element_index(ElementRef ref, uint index) { @@ -243,6 +258,14 @@ Clip Clip_read(ClipRef ref) { return s; } +SetFillMode SetFillMode_read(SetFillModeRef ref) { + uint ix = ref.offset >> 2; + uint raw0 = scene[ix + 0]; + SetFillMode s; + s.fill_mode = raw0; + return s; +} + ElementTag Element_tag(ElementRef ref) { uint tag_and_flags = scene[ref.offset >> 2]; return ElementTag(tag_and_flags & 0xffff, tag_and_flags >> 16); @@ -284,3 +307,7 @@ FillImage Element_FillImage_read(ElementRef ref) { return FillImage_read(FillImageRef(ref.offset + 4)); } +SetFillMode Element_SetFillMode_read(ElementRef ref) { + return SetFillMode_read(SetFillModeRef(ref.offset + 4)); +} + diff --git a/piet-gpu/src/render_ctx.rs b/piet-gpu/src/render_ctx.rs index 06db5a4..e80d67d 100644 --- a/piet-gpu/src/render_ctx.rs +++ b/piet-gpu/src/render_ctx.rs @@ -3,7 +3,7 @@ use std::{borrow::Cow, ops::RangeBounds}; use piet_gpu_types::encoder::{Encode, Encoder}; use piet_gpu_types::scene::{ - Clip, CubicSeg, Element, FillColor, LineSeg, QuadSeg, SetLineWidth, Transform, + Clip, CubicSeg, Element, FillColor, SetFillMode, LineSeg, QuadSeg, SetLineWidth, Transform, }; use piet::{ @@ -32,6 +32,7 @@ pub struct PietGpuRenderContext { // Will probably need direct accesss to hal Device to create images etc. inner_text: PietGpuText, stroke_width: f32, + fill_mode: FillMode, // We're tallying these cpu-side for expedience, but will probably // move this to some kind of readback from element processing. /// The count of elements that make it through to coarse rasterization. @@ -69,6 +70,7 @@ struct ClipElement { bbox: Option, } +#[derive(Clone,Copy,PartialEq)] enum FillMode { // Fill path according to the non-zero winding rule. Nonzero = 0, @@ -89,6 +91,7 @@ impl PietGpuRenderContext { elements, inner_text, stroke_width, + fill_mode: FillMode::Nonzero, path_count: 0, pathseg_count: 0, trans_count: 0, @@ -116,6 +119,14 @@ impl PietGpuRenderContext { } } +fn set_fill_mode(ctx: &mut PietGpuRenderContext, fill_mode: FillMode) { + if ctx.fill_mode != fill_mode { + ctx.elements + .push(Element::SetFillMode(SetFillMode { fill_mode: fill_mode as u32 })); + ctx.fill_mode = fill_mode; + } +} + impl RenderContext for PietGpuRenderContext { type Brush = PietGpuBrush; type Image = PietGpuImage; @@ -143,6 +154,7 @@ impl RenderContext for PietGpuRenderContext { .push(Element::SetLineWidth(SetLineWidth { width: width_f32 })); self.stroke_width = width_f32; } + set_fill_mode(self, FillMode::Stroke); let brush = brush.make_brush(self, || shape.bounding_box()).into_owned(); match brush { PietGpuBrush::Solid(rgba_color) => { @@ -151,7 +163,7 @@ impl RenderContext for PietGpuRenderContext { let path = shape.path_elements(TOLERANCE); self.encode_path(path, false); let stroke = FillColor { rgba_color }; - self.elements.push(Element::FillColor(FillMode::Stroke as u16, stroke)); + self.elements.push(Element::FillColor(stroke)); self.path_count += 1; } _ => (), @@ -174,9 +186,10 @@ impl RenderContext for PietGpuRenderContext { // Perhaps that should be added to kurbo. self.accumulate_bbox(|| shape.bounding_box()); let path = shape.path_elements(TOLERANCE); + set_fill_mode(self, FillMode::Nonzero); self.encode_path(path, true); let fill = FillColor { rgba_color }; - self.elements.push(Element::FillColor(FillMode::Nonzero as u16, fill)); + self.elements.push(Element::FillColor(fill)); self.path_count += 1; } } @@ -184,6 +197,7 @@ impl RenderContext for PietGpuRenderContext { fn fill_even_odd(&mut self, _shape: impl Shape, _brush: &impl IntoBrush) {} fn clip(&mut self, shape: impl Shape) { + set_fill_mode(self, FillMode::Nonzero); let path = shape.path_elements(TOLERANCE); self.encode_path(path, true); let begin_ix = self.elements.len(); @@ -291,30 +305,18 @@ impl RenderContext for PietGpuRenderContext { } impl PietGpuRenderContext { - fn encode_line_seg(&mut self, seg: LineSeg, is_fill: bool) { - if is_fill { - self.elements.push(Element::Line(FillMode::Nonzero as u16, seg)); - } else { - self.elements.push(Element::Line(FillMode::Stroke as u16, seg)); - } + fn encode_line_seg(&mut self, seg: LineSeg) { + self.elements.push(Element::Line(seg)); self.pathseg_count += 1; } - fn encode_quad_seg(&mut self, seg: QuadSeg, is_fill: bool) { - if is_fill { - self.elements.push(Element::Quad(FillMode::Nonzero as u16, seg)); - } else { - self.elements.push(Element::Quad(FillMode::Stroke as u16, seg)); - } + fn encode_quad_seg(&mut self, seg: QuadSeg) { + self.elements.push(Element::Quad(seg)); self.pathseg_count += 1; } - fn encode_cubic_seg(&mut self, seg: CubicSeg, is_fill: bool) { - if is_fill { - self.elements.push(Element::Cubic(FillMode::Nonzero as u16, seg)); - } else { - self.elements.push(Element::Cubic(FillMode::Stroke as u16, seg)); - } + fn encode_cubic_seg(&mut self, seg: CubicSeg) { + self.elements.push(Element::Cubic(seg)); self.pathseg_count += 1; } @@ -327,13 +329,13 @@ impl PietGpuRenderContext { } _ => None }.into_iter().chain(Some(el)) - }).chain(Some(PathEl::ClosePath)), is_fill) + }).chain(Some(PathEl::ClosePath))) } else { - self.encode_path_inner(path, is_fill) + self.encode_path_inner(path) } } - fn encode_path_inner(&mut self, path: impl Iterator, is_fill: bool) { + fn encode_path_inner(&mut self, path: impl Iterator) { let flatten = false; if flatten { let mut start_pt = None; @@ -351,7 +353,7 @@ impl PietGpuRenderContext { p0: last_pt.unwrap(), p1: scene_pt, }; - self.encode_line_seg(seg, is_fill); + self.encode_line_seg(seg); last_pt = Some(scene_pt); } PathEl::ClosePath => { @@ -361,7 +363,7 @@ impl PietGpuRenderContext { p0: last, p1: start, }; - self.encode_line_seg(seg, is_fill); + self.encode_line_seg(seg); } } } @@ -385,7 +387,7 @@ impl PietGpuRenderContext { p0: last_pt.unwrap(), p1: scene_pt, }; - self.encode_line_seg(seg, is_fill); + self.encode_line_seg(seg); last_pt = Some(scene_pt); } PathEl::QuadTo(p1, p2) => { @@ -396,7 +398,7 @@ impl PietGpuRenderContext { p1: scene_p1, p2: scene_p2, }; - self.encode_quad_seg(seg, is_fill); + self.encode_quad_seg(seg); last_pt = Some(scene_p2); } PathEl::CurveTo(p1, p2, p3) => { @@ -409,7 +411,7 @@ impl PietGpuRenderContext { p2: scene_p2, p3: scene_p3, }; - self.encode_cubic_seg(seg, is_fill); + self.encode_cubic_seg(seg); last_pt = Some(scene_p3); } PathEl::ClosePath => { @@ -419,7 +421,7 @@ impl PietGpuRenderContext { p0: last, p1: start, }; - self.encode_line_seg(seg, is_fill); + self.encode_line_seg(seg); } } }