collapse annotated Fill and Stroke to Color with fill mode flag

No functionality changes, just different encoding.

Updates #70

Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
Elias Naur 2021-03-17 12:02:41 +01:00
parent e9ff509ab9
commit df055563bd
12 changed files with 70 additions and 131 deletions

View file

@ -3,20 +3,15 @@ use piet_gpu_derive::piet_gpu;
piet_gpu! { piet_gpu! {
#[gpu_write] #[gpu_write]
mod annotated { mod annotated {
struct AnnoFill {
// The bbox is always first, as we take advantage of common
// layout when binning.
bbox: [f32; 4],
rgba_color: u32,
}
struct AnnoFillImage { struct AnnoFillImage {
bbox: [f32; 4], bbox: [f32; 4],
index: u32, index: u32,
offset: [i16; 2], offset: [i16; 2],
} }
struct AnnoStroke { struct AnnoColor {
bbox: [f32; 4], bbox: [f32; 4],
rgba_color: u32, rgba_color: u32,
// For stroked fills.
// For the nonuniform scale case, this needs to be a 2x2 matrix. // For the nonuniform scale case, this needs to be a 2x2 matrix.
// That's expected to be uncommon, so we could special-case it. // That's expected to be uncommon, so we could special-case it.
linewidth: f32, linewidth: f32,
@ -26,8 +21,7 @@ piet_gpu! {
} }
enum Annotated { enum Annotated {
Nop, Nop,
Stroke(AnnoStroke), Color(TagFlags, AnnoColor),
Fill(AnnoFill),
FillImage(AnnoFillImage), FillImage(AnnoFillImage),
BeginClip(AnnoClip), BeginClip(AnnoClip),
EndClip(AnnoClip), EndClip(AnnoClip),

View file

@ -2,15 +2,11 @@
// Code auto-generated by piet-gpu-derive // Code auto-generated by piet-gpu-derive
struct AnnoFillRef {
uint offset;
};
struct AnnoFillImageRef { struct AnnoFillImageRef {
uint offset; uint offset;
}; };
struct AnnoStrokeRef { struct AnnoColorRef {
uint offset; uint offset;
}; };
@ -22,17 +18,6 @@ struct AnnotatedRef {
uint offset; uint offset;
}; };
struct AnnoFill {
vec4 bbox;
uint rgba_color;
};
#define AnnoFill_size 20
AnnoFillRef AnnoFill_index(AnnoFillRef ref, uint index) {
return AnnoFillRef(ref.offset + index * AnnoFill_size);
}
struct AnnoFillImage { struct AnnoFillImage {
vec4 bbox; vec4 bbox;
uint index; uint index;
@ -45,16 +30,16 @@ AnnoFillImageRef AnnoFillImage_index(AnnoFillImageRef ref, uint index) {
return AnnoFillImageRef(ref.offset + index * AnnoFillImage_size); return AnnoFillImageRef(ref.offset + index * AnnoFillImage_size);
} }
struct AnnoStroke { struct AnnoColor {
vec4 bbox; vec4 bbox;
uint rgba_color; uint rgba_color;
float linewidth; float linewidth;
}; };
#define AnnoStroke_size 24 #define AnnoColor_size 24
AnnoStrokeRef AnnoStroke_index(AnnoStrokeRef ref, uint index) { AnnoColorRef AnnoColor_index(AnnoColorRef ref, uint index) {
return AnnoStrokeRef(ref.offset + index * AnnoStroke_size); return AnnoColorRef(ref.offset + index * AnnoColor_size);
} }
struct AnnoClip { struct AnnoClip {
@ -68,11 +53,10 @@ AnnoClipRef AnnoClip_index(AnnoClipRef ref, uint index) {
} }
#define Annotated_Nop 0 #define Annotated_Nop 0
#define Annotated_Stroke 1 #define Annotated_Color 1
#define Annotated_Fill 2 #define Annotated_FillImage 2
#define Annotated_FillImage 3 #define Annotated_BeginClip 3
#define Annotated_BeginClip 4 #define Annotated_EndClip 4
#define Annotated_EndClip 5
#define Annotated_size 28 #define Annotated_size 28
AnnotatedRef Annotated_index(AnnotatedRef ref, uint index) { AnnotatedRef Annotated_index(AnnotatedRef ref, uint index) {
@ -84,28 +68,6 @@ struct AnnotatedTag {
uint flags; uint flags;
}; };
AnnoFill AnnoFill_read(Alloc a, AnnoFillRef 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);
AnnoFill s;
s.bbox = vec4(uintBitsToFloat(raw0), uintBitsToFloat(raw1), uintBitsToFloat(raw2), uintBitsToFloat(raw3));
s.rgba_color = raw4;
return s;
}
void AnnoFill_write(Alloc a, AnnoFillRef ref, AnnoFill s) {
uint ix = ref.offset >> 2;
write_mem(a, ix + 0, floatBitsToUint(s.bbox.x));
write_mem(a, ix + 1, floatBitsToUint(s.bbox.y));
write_mem(a, ix + 2, floatBitsToUint(s.bbox.z));
write_mem(a, ix + 3, floatBitsToUint(s.bbox.w));
write_mem(a, ix + 4, s.rgba_color);
}
AnnoFillImage AnnoFillImage_read(Alloc a, AnnoFillImageRef ref) { AnnoFillImage AnnoFillImage_read(Alloc a, AnnoFillImageRef 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);
@ -131,7 +93,7 @@ void AnnoFillImage_write(Alloc a, AnnoFillImageRef ref, AnnoFillImage s) {
write_mem(a, ix + 5, (uint(s.offset.x) & 0xffff) | (uint(s.offset.y) << 16)); write_mem(a, ix + 5, (uint(s.offset.x) & 0xffff) | (uint(s.offset.y) << 16));
} }
AnnoStroke AnnoStroke_read(Alloc a, AnnoStrokeRef ref) { AnnoColor AnnoColor_read(Alloc a, AnnoColorRef 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);
uint raw1 = read_mem(a, ix + 1); uint raw1 = read_mem(a, ix + 1);
@ -139,14 +101,14 @@ AnnoStroke AnnoStroke_read(Alloc a, AnnoStrokeRef ref) {
uint raw3 = read_mem(a, ix + 3); uint raw3 = read_mem(a, ix + 3);
uint raw4 = read_mem(a, ix + 4); uint raw4 = read_mem(a, ix + 4);
uint raw5 = read_mem(a, ix + 5); uint raw5 = read_mem(a, ix + 5);
AnnoStroke s; AnnoColor s;
s.bbox = vec4(uintBitsToFloat(raw0), uintBitsToFloat(raw1), uintBitsToFloat(raw2), uintBitsToFloat(raw3)); s.bbox = vec4(uintBitsToFloat(raw0), uintBitsToFloat(raw1), uintBitsToFloat(raw2), uintBitsToFloat(raw3));
s.rgba_color = raw4; s.rgba_color = raw4;
s.linewidth = uintBitsToFloat(raw5); s.linewidth = uintBitsToFloat(raw5);
return s; return s;
} }
void AnnoStroke_write(Alloc a, AnnoStrokeRef ref, AnnoStroke s) { void AnnoColor_write(Alloc a, AnnoColorRef ref, AnnoColor s) {
uint ix = ref.offset >> 2; uint ix = ref.offset >> 2;
write_mem(a, ix + 0, floatBitsToUint(s.bbox.x)); write_mem(a, ix + 0, floatBitsToUint(s.bbox.x));
write_mem(a, ix + 1, floatBitsToUint(s.bbox.y)); write_mem(a, ix + 1, floatBitsToUint(s.bbox.y));
@ -180,12 +142,8 @@ AnnotatedTag Annotated_tag(Alloc a, AnnotatedRef ref) {
return AnnotatedTag(tag_and_flags & 0xffff, tag_and_flags >> 16); return AnnotatedTag(tag_and_flags & 0xffff, tag_and_flags >> 16);
} }
AnnoStroke Annotated_Stroke_read(Alloc a, AnnotatedRef ref) { AnnoColor Annotated_Color_read(Alloc a, AnnotatedRef ref) {
return AnnoStroke_read(a, AnnoStrokeRef(ref.offset + 4)); return AnnoColor_read(a, AnnoColorRef(ref.offset + 4));
}
AnnoFill Annotated_Fill_read(Alloc a, AnnotatedRef ref) {
return AnnoFill_read(a, AnnoFillRef(ref.offset + 4));
} }
AnnoFillImage Annotated_FillImage_read(Alloc a, AnnotatedRef ref) { AnnoFillImage Annotated_FillImage_read(Alloc a, AnnotatedRef ref) {
@ -204,14 +162,9 @@ void Annotated_Nop_write(Alloc a, AnnotatedRef ref) {
write_mem(a, ref.offset >> 2, Annotated_Nop); write_mem(a, ref.offset >> 2, Annotated_Nop);
} }
void Annotated_Stroke_write(Alloc a, AnnotatedRef ref, AnnoStroke s) { void Annotated_Color_write(Alloc a, AnnotatedRef ref, uint flags, AnnoColor s) {
write_mem(a, ref.offset >> 2, Annotated_Stroke); write_mem(a, ref.offset >> 2, (flags << 16) | Annotated_Color);
AnnoStroke_write(a, AnnoStrokeRef(ref.offset + 4), s); AnnoColor_write(a, AnnoColorRef(ref.offset + 4), s);
}
void Annotated_Fill_write(Alloc a, AnnotatedRef ref, AnnoFill s) {
write_mem(a, ref.offset >> 2, Annotated_Fill);
AnnoFill_write(a, AnnoFillRef(ref.offset + 4), s);
} }
void Annotated_FillImage_write(Alloc a, AnnotatedRef ref, AnnoFillImage s) { void Annotated_FillImage_write(Alloc a, AnnotatedRef ref, AnnoFillImage s) {

View file

@ -46,9 +46,13 @@ void main() {
// Work assignment: 1 thread : 1 path element // Work assignment: 1 thread : 1 path element
uint row_count = 0; uint row_count = 0;
if (element_ix < conf.n_elements) { if (element_ix < conf.n_elements) {
uint tag = Annotated_tag(conf.anno_alloc, ref).tag; AnnotatedTag tag = Annotated_tag(conf.anno_alloc, ref);
switch (tag) { switch (tag.tag) {
case Annotated_Fill: case Annotated_Color:
if (fill_mode_from_flags(tag.flags) != MODE_NONZERO) {
break;
}
// Fall through.
case Annotated_FillImage: case Annotated_FillImage:
case Annotated_BeginClip: case Annotated_BeginClip:
PathRef path_ref = PathRef(conf.tile_alloc.offset + element_ix * Path_size); PathRef path_ref = PathRef(conf.tile_alloc.offset + element_ix * Path_size);

Binary file not shown.

View file

@ -60,18 +60,17 @@ void main() {
} }
int x0 = 0, y0 = 0, x1 = 0, y1 = 0; int x0 = 0, y0 = 0, x1 = 0, y1 = 0;
switch (tag) { switch (tag) {
case Annotated_Fill: case Annotated_Color:
case Annotated_FillImage: case Annotated_FillImage:
case Annotated_Stroke:
case Annotated_BeginClip: case Annotated_BeginClip:
case Annotated_EndClip: case Annotated_EndClip:
// Note: we take advantage of the fact that these drawing elements // Note: we take advantage of the fact that these drawing elements
// have the bbox at the same place in their layout. // have the bbox at the same place in their layout.
AnnoFill fill = Annotated_Fill_read(conf.anno_alloc, ref); AnnoClip clip = Annotated_BeginClip_read(conf.anno_alloc, ref);
x0 = int(floor(fill.bbox.x * SX)); x0 = int(floor(clip.bbox.x * SX));
y0 = int(floor(fill.bbox.y * SY)); y0 = int(floor(clip.bbox.y * SY));
x1 = int(ceil(fill.bbox.z * SX)); x1 = int(ceil(clip.bbox.z * SX));
y1 = int(ceil(fill.bbox.w * SY)); y1 = int(ceil(clip.bbox.w * SY));
break; break;
} }

Binary file not shown.

View file

@ -202,9 +202,8 @@ void main() {
// Bounding box of element in pixel coordinates. // Bounding box of element in pixel coordinates.
uint tile_count; uint tile_count;
switch (tag) { switch (tag) {
case Annotated_Fill: case Annotated_Color:
case Annotated_FillImage: case Annotated_FillImage:
case Annotated_Stroke:
case Annotated_BeginClip: case Annotated_BeginClip:
case Annotated_EndClip: case Annotated_EndClip:
// We have one "path" for each element, even if the element isn't // We have one "path" for each element, even if the element isn't
@ -305,25 +304,33 @@ void main() {
// If that turns out to be expensive, maybe we can pack it into // If that turns out to be expensive, maybe we can pack it into
// shared memory (or perhaps just the tag). // shared memory (or perhaps just the tag).
ref = AnnotatedRef(conf.anno_alloc.offset + element_ix * Annotated_size); ref = AnnotatedRef(conf.anno_alloc.offset + element_ix * Annotated_size);
tag = Annotated_tag(conf.anno_alloc, ref).tag; AnnotatedTag tag = Annotated_tag(conf.anno_alloc, ref);
if (clip_zero_depth == 0) { if (clip_zero_depth == 0) {
switch (tag) { switch (tag.tag) {
case Annotated_Fill: case Annotated_Color:
Tile tile = Tile_read(read_tile_alloc(element_ref_ix), TileRef(sh_tile_base[element_ref_ix] Tile tile = Tile_read(read_tile_alloc(element_ref_ix), TileRef(sh_tile_base[element_ref_ix]
+ (sh_tile_stride[element_ref_ix] * tile_y + tile_x) * Tile_size)); + (sh_tile_stride[element_ref_ix] * tile_y + tile_x) * Tile_size));
AnnoFill fill = Annotated_Fill_read(conf.anno_alloc, ref); AnnoColor fill = Annotated_Color_read(conf.anno_alloc, ref);
if (!alloc_cmd(cmd_alloc, cmd_ref, cmd_limit)) { if (!alloc_cmd(cmd_alloc, cmd_ref, cmd_limit)) {
break; break;
} }
if (tile.tile.offset != 0) { if (fill_mode_from_flags(tag.flags) == MODE_NONZERO) {
CmdFill cmd_fill; if (tile.tile.offset != 0) {
cmd_fill.tile_ref = tile.tile.offset; CmdFill cmd_fill;
cmd_fill.backdrop = tile.backdrop; cmd_fill.tile_ref = tile.tile.offset;
cmd_fill.rgba_color = fill.rgba_color; cmd_fill.backdrop = tile.backdrop;
Cmd_Fill_write(cmd_alloc, cmd_ref, cmd_fill); cmd_fill.rgba_color = fill.rgba_color;
Cmd_Fill_write(cmd_alloc, cmd_ref, cmd_fill);
} else {
Cmd_Solid_write(cmd_alloc, cmd_ref, CmdSolid(fill.rgba_color));
}
} else { } else {
Cmd_Solid_write(cmd_alloc, cmd_ref, CmdSolid(fill.rgba_color)); CmdStroke cmd_stroke;
cmd_stroke.tile_ref = tile.tile.offset;
cmd_stroke.half_width = 0.5 * fill.linewidth;
cmd_stroke.rgba_color = fill.rgba_color;
Cmd_Stroke_write(cmd_alloc, cmd_ref, cmd_stroke);
} }
cmd_ref.offset += Cmd_size; cmd_ref.offset += Cmd_size;
break; break;
@ -387,24 +394,10 @@ void main() {
cmd_ref.offset += Cmd_size; cmd_ref.offset += Cmd_size;
} }
break; break;
case Annotated_Stroke:
tile = Tile_read(read_tile_alloc(element_ref_ix), TileRef(sh_tile_base[element_ref_ix]
+ (sh_tile_stride[element_ref_ix] * tile_y + tile_x) * Tile_size));
AnnoStroke stroke = Annotated_Stroke_read(conf.anno_alloc, ref);
CmdStroke cmd_stroke;
cmd_stroke.tile_ref = tile.tile.offset;
cmd_stroke.half_width = 0.5 * stroke.linewidth;
cmd_stroke.rgba_color = stroke.rgba_color;
if (!alloc_cmd(cmd_alloc, cmd_ref, cmd_limit)) {
break;
}
Cmd_Stroke_write(cmd_alloc, cmd_ref, cmd_stroke);
cmd_ref.offset += Cmd_size;
break;
} }
} else { } else {
// In "clip zero" state, suppress all drawing // In "clip zero" state, suppress all drawing
switch (tag) { switch (tag.tag) {
case Annotated_BeginClip: case Annotated_BeginClip:
clip_depth++; clip_depth++;
break; break;

Binary file not shown.

View file

@ -288,7 +288,8 @@ void main() {
// 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);
ElementTag tag = Element_tag(this_ref); ElementTag tag = Element_tag(this_ref);
bool is_stroke = fill_mode_from_flags(tag.flags) == MODE_STROKE; uint fill_mode = fill_mode_from_flags(tag.flags);
bool is_stroke = fill_mode == MODE_STROKE;
switch (tag.tag) { switch (tag.tag) {
case Element_Line: case Element_Line:
LineSeg line = Element_Line_read(this_ref); LineSeg line = Element_Line_read(this_ref);
@ -353,22 +354,18 @@ void main() {
break; break;
case Element_FillColor: case Element_FillColor:
FillColor fill = Element_FillColor_read(this_ref); FillColor fill = Element_FillColor_read(this_ref);
// TODO: merge paths when annotations use tag flags. AnnoColor anno_fill;
anno_fill.rgba_color = fill.rgba_color;
if (is_stroke) { if (is_stroke) {
AnnoStroke anno_stroke;
anno_stroke.rgba_color = fill.rgba_color;
vec2 lw = get_linewidth(st); vec2 lw = get_linewidth(st);
anno_stroke.bbox = st.bbox + vec4(-lw, lw); anno_fill.bbox = st.bbox + vec4(-lw, lw);
anno_stroke.linewidth = st.linewidth * sqrt(abs(st.mat.x * st.mat.w - st.mat.y * st.mat.z)); anno_fill.linewidth = st.linewidth * sqrt(abs(st.mat.x * st.mat.w - st.mat.y * st.mat.z));
AnnotatedRef out_ref = AnnotatedRef(conf.anno_alloc.offset + (st.path_count - 1) * Annotated_size);
Annotated_Stroke_write(conf.anno_alloc, out_ref, anno_stroke);
} else { } else {
AnnoFill anno_fill;
anno_fill.rgba_color = fill.rgba_color;
anno_fill.bbox = st.bbox; anno_fill.bbox = st.bbox;
AnnotatedRef out_ref = AnnotatedRef(conf.anno_alloc.offset + (st.path_count - 1) * Annotated_size); anno_fill.linewidth = 0.0;
Annotated_Fill_write(conf.anno_alloc, out_ref, anno_fill);
} }
AnnotatedRef out_ref = AnnotatedRef(conf.anno_alloc.offset + (st.path_count - 1) * Annotated_size);
Annotated_Color_write(conf.anno_alloc, out_ref, fill_mode, anno_fill);
break; break;
case Element_FillImage: case Element_FillImage:
FillImage fill_img = Element_FillImage_read(this_ref); FillImage fill_img = Element_FillImage_read(this_ref);
@ -376,7 +373,7 @@ void main() {
anno_fill_img.index = fill_img.index; anno_fill_img.index = fill_img.index;
anno_fill_img.offset = fill_img.offset; anno_fill_img.offset = fill_img.offset;
anno_fill_img.bbox = st.bbox; anno_fill_img.bbox = st.bbox;
AnnotatedRef out_ref = AnnotatedRef(conf.anno_alloc.offset + (st.path_count - 1) * Annotated_size); out_ref = AnnotatedRef(conf.anno_alloc.offset + (st.path_count - 1) * Annotated_size);
Annotated_FillImage_write(conf.anno_alloc, out_ref, anno_fill_img); Annotated_FillImage_write(conf.anno_alloc, out_ref, anno_fill_img);
break; break;
case Element_BeginClip: case Element_BeginClip:

Binary file not shown.

View file

@ -43,18 +43,17 @@ void main() {
} }
int x0 = 0, y0 = 0, x1 = 0, y1 = 0; int x0 = 0, y0 = 0, x1 = 0, y1 = 0;
switch (tag) { switch (tag) {
case Annotated_Fill: case Annotated_Color:
case Annotated_FillImage: case Annotated_FillImage:
case Annotated_Stroke:
case Annotated_BeginClip: case Annotated_BeginClip:
case Annotated_EndClip: case Annotated_EndClip:
// Note: we take advantage of the fact that fills, strokes, and // Note: we take advantage of the fact that fills, strokes, and
// clips have compatible layout. // clips have compatible layout.
AnnoFill fill = Annotated_Fill_read(conf.anno_alloc, ref); AnnoClip clip = Annotated_BeginClip_read(conf.anno_alloc, ref);
x0 = int(floor(fill.bbox.x * SX)); x0 = int(floor(clip.bbox.x * SX));
y0 = int(floor(fill.bbox.y * SY)); y0 = int(floor(clip.bbox.y * SY));
x1 = int(ceil(fill.bbox.z * SX)); x1 = int(ceil(clip.bbox.z * SX));
y1 = int(ceil(fill.bbox.w * SY)); y1 = int(ceil(clip.bbox.w * SY));
break; break;
} }
x0 = clamp(x0, 0, int(conf.width_in_tiles)); x0 = clamp(x0, 0, int(conf.width_in_tiles));

Binary file not shown.