mirror of
https://github.com/italicsjenga/vello.git
synced 2025-01-10 12:41:30 +11:00
commit
61810b1bff
|
@ -7,6 +7,10 @@ piet_gpu! {
|
|||
rgba_color: u32,
|
||||
bbox: [f32; 4],
|
||||
}
|
||||
struct AnnoFillMask {
|
||||
mask: f32,
|
||||
bbox: [f32; 4],
|
||||
}
|
||||
struct AnnoStroke {
|
||||
rgba_color: u32,
|
||||
bbox: [f32; 4],
|
||||
|
@ -18,6 +22,8 @@ piet_gpu! {
|
|||
Nop,
|
||||
Stroke(AnnoStroke),
|
||||
Fill(AnnoFill),
|
||||
FillMask(AnnoFillMask),
|
||||
FillMaskInv(AnnoFillMask),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,9 +25,17 @@ piet_gpu! {
|
|||
backdrop: i32,
|
||||
rgba_color: u32,
|
||||
}
|
||||
struct CmdFillMask {
|
||||
tile_ref: u32,
|
||||
backdrop: i32,
|
||||
mask: f32,
|
||||
}
|
||||
struct CmdSolid {
|
||||
rgba_color: u32,
|
||||
}
|
||||
struct CmdSolidMask {
|
||||
mask: f32,
|
||||
}
|
||||
struct CmdJump {
|
||||
new_ref: u32,
|
||||
}
|
||||
|
@ -36,8 +44,11 @@ piet_gpu! {
|
|||
Circle(CmdCircle),
|
||||
Line(CmdLine),
|
||||
Fill(CmdFill),
|
||||
FillMask(CmdFillMask),
|
||||
FillMaskInv(CmdFillMask),
|
||||
Stroke(CmdStroke),
|
||||
Solid(CmdSolid),
|
||||
SolidMask(CmdSolidMask),
|
||||
Jump(CmdJump),
|
||||
}
|
||||
|
||||
|
|
|
@ -23,6 +23,9 @@ piet_gpu! {
|
|||
struct Fill {
|
||||
rgba_color: u32,
|
||||
}
|
||||
struct FillMask {
|
||||
mask: f32,
|
||||
}
|
||||
struct Stroke {
|
||||
rgba_color: u32,
|
||||
}
|
||||
|
@ -50,6 +53,8 @@ piet_gpu! {
|
|||
Fill(Fill),
|
||||
SetLineWidth(SetLineWidth),
|
||||
Transform(Transform),
|
||||
FillMask(FillMask),
|
||||
FillMaskInv(FillMask),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,10 @@ struct AnnoFillRef {
|
|||
uint offset;
|
||||
};
|
||||
|
||||
struct AnnoFillMaskRef {
|
||||
uint offset;
|
||||
};
|
||||
|
||||
struct AnnoStrokeRef {
|
||||
uint offset;
|
||||
};
|
||||
|
@ -23,6 +27,17 @@ AnnoFillRef AnnoFill_index(AnnoFillRef ref, uint index) {
|
|||
return AnnoFillRef(ref.offset + index * AnnoFill_size);
|
||||
}
|
||||
|
||||
struct AnnoFillMask {
|
||||
float mask;
|
||||
vec4 bbox;
|
||||
};
|
||||
|
||||
#define AnnoFillMask_size 20
|
||||
|
||||
AnnoFillMaskRef AnnoFillMask_index(AnnoFillMaskRef ref, uint index) {
|
||||
return AnnoFillMaskRef(ref.offset + index * AnnoFillMask_size);
|
||||
}
|
||||
|
||||
struct AnnoStroke {
|
||||
uint rgba_color;
|
||||
vec4 bbox;
|
||||
|
@ -38,6 +53,8 @@ AnnoStrokeRef AnnoStroke_index(AnnoStrokeRef ref, uint index) {
|
|||
#define Annotated_Nop 0
|
||||
#define Annotated_Stroke 1
|
||||
#define Annotated_Fill 2
|
||||
#define Annotated_FillMask 3
|
||||
#define Annotated_FillMaskInv 4
|
||||
#define Annotated_size 28
|
||||
|
||||
AnnotatedRef Annotated_index(AnnotatedRef ref, uint index) {
|
||||
|
@ -66,6 +83,28 @@ void AnnoFill_write(AnnoFillRef ref, AnnoFill s) {
|
|||
annotated[ix + 4] = floatBitsToUint(s.bbox.w);
|
||||
}
|
||||
|
||||
AnnoFillMask AnnoFillMask_read(AnnoFillMaskRef 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];
|
||||
uint raw4 = annotated[ix + 4];
|
||||
AnnoFillMask s;
|
||||
s.mask = uintBitsToFloat(raw0);
|
||||
s.bbox = vec4(uintBitsToFloat(raw1), uintBitsToFloat(raw2), uintBitsToFloat(raw3), uintBitsToFloat(raw4));
|
||||
return s;
|
||||
}
|
||||
|
||||
void AnnoFillMask_write(AnnoFillMaskRef ref, AnnoFillMask s) {
|
||||
uint ix = ref.offset >> 2;
|
||||
annotated[ix + 0] = floatBitsToUint(s.mask);
|
||||
annotated[ix + 1] = floatBitsToUint(s.bbox.x);
|
||||
annotated[ix + 2] = floatBitsToUint(s.bbox.y);
|
||||
annotated[ix + 3] = floatBitsToUint(s.bbox.z);
|
||||
annotated[ix + 4] = floatBitsToUint(s.bbox.w);
|
||||
}
|
||||
|
||||
AnnoStroke AnnoStroke_read(AnnoStrokeRef ref) {
|
||||
uint ix = ref.offset >> 2;
|
||||
uint raw0 = annotated[ix + 0];
|
||||
|
@ -103,6 +142,14 @@ AnnoFill Annotated_Fill_read(AnnotatedRef ref) {
|
|||
return AnnoFill_read(AnnoFillRef(ref.offset + 4));
|
||||
}
|
||||
|
||||
AnnoFillMask Annotated_FillMask_read(AnnotatedRef ref) {
|
||||
return AnnoFillMask_read(AnnoFillMaskRef(ref.offset + 4));
|
||||
}
|
||||
|
||||
AnnoFillMask Annotated_FillMaskInv_read(AnnotatedRef ref) {
|
||||
return AnnoFillMask_read(AnnoFillMaskRef(ref.offset + 4));
|
||||
}
|
||||
|
||||
void Annotated_Nop_write(AnnotatedRef ref) {
|
||||
annotated[ref.offset >> 2] = Annotated_Nop;
|
||||
}
|
||||
|
@ -117,3 +164,13 @@ void Annotated_Fill_write(AnnotatedRef ref, AnnoFill s) {
|
|||
AnnoFill_write(AnnoFillRef(ref.offset + 4), s);
|
||||
}
|
||||
|
||||
void Annotated_FillMask_write(AnnotatedRef ref, AnnoFillMask s) {
|
||||
annotated[ref.offset >> 2] = Annotated_FillMask;
|
||||
AnnoFillMask_write(AnnoFillMaskRef(ref.offset + 4), s);
|
||||
}
|
||||
|
||||
void Annotated_FillMaskInv_write(AnnotatedRef ref, AnnoFillMask s) {
|
||||
annotated[ref.offset >> 2] = Annotated_FillMaskInv;
|
||||
AnnoFillMask_write(AnnoFillMaskRef(ref.offset + 4), s);
|
||||
}
|
||||
|
||||
|
|
|
@ -53,7 +53,10 @@ void main() {
|
|||
uint row_count = 0;
|
||||
if (element_ix < n_elements) {
|
||||
uint tag = Annotated_tag(ref);
|
||||
if (tag == Annotated_Fill) {
|
||||
switch (tag) {
|
||||
case Annotated_Fill:
|
||||
case Annotated_FillMask:
|
||||
case Annotated_FillMaskInv:
|
||||
PathRef path_ref = PathRef(element_ix * Path_size);
|
||||
Path path = Path_read(path_ref);
|
||||
sh_row_width[th_ix] = path.bbox.z - path.bbox.x;
|
||||
|
|
Binary file not shown.
|
@ -60,6 +60,8 @@ void main() {
|
|||
float my_right_edge = INFINITY;
|
||||
switch (tag) {
|
||||
case Annotated_Fill:
|
||||
case Annotated_FillMask:
|
||||
case Annotated_FillMaskInv:
|
||||
case Annotated_Stroke:
|
||||
// Note: we take advantage of the fact that fills and strokes
|
||||
// have compatible layout.
|
||||
|
|
Binary file not shown.
|
@ -173,6 +173,8 @@ void main() {
|
|||
uint tile_count;
|
||||
switch (tag) {
|
||||
case Annotated_Fill:
|
||||
case Annotated_FillMask:
|
||||
case Annotated_FillMaskInv:
|
||||
case Annotated_Stroke:
|
||||
// Because the only elements we're processing right now are
|
||||
// paths, we can just use the element index as the path index.
|
||||
|
@ -222,12 +224,20 @@ void main() {
|
|||
el_ix = probe;
|
||||
}
|
||||
}
|
||||
AnnotatedRef ref = AnnotatedRef(el_ix * Annotated_size);
|
||||
uint tag = Annotated_tag(ref);
|
||||
uint seq_ix = ix - (el_ix > 0 ? sh_tile_count[el_ix - 1] : 0);
|
||||
uint width = sh_tile_width[el_ix];
|
||||
uint x = sh_tile_x0[el_ix] + seq_ix % width;
|
||||
uint y = sh_tile_y0[el_ix] + seq_ix / width;
|
||||
Tile tile = Tile_read(TileRef(sh_tile_base[el_ix] + (sh_tile_stride[el_ix] * y + x) * Tile_size));
|
||||
if (tile.tile.offset != 0 || tile.backdrop != 0) {
|
||||
// Include the path in the tile if
|
||||
// - the tile contains at least a segment (tile offset non-zero)
|
||||
// - the tile is completely covered (backdrop non-zero)
|
||||
// - the tile is not covered and we're filling everything outside the path (backdrop zero, inverse fills).
|
||||
bool inside = tile.backdrop != 0;
|
||||
bool fill = tag != Annotated_FillMaskInv;
|
||||
if (tile.tile.offset != 0 || inside == fill) {
|
||||
uint el_slice = el_ix / 32;
|
||||
uint el_mask = 1 << (el_ix & 31);
|
||||
atomicOr(sh_bitmaps[el_slice][y * N_TILE_X + x], el_mask);
|
||||
|
@ -281,6 +291,27 @@ void main() {
|
|||
}
|
||||
cmd_ref.offset += Cmd_size;
|
||||
break;
|
||||
case Annotated_FillMask:
|
||||
case Annotated_FillMaskInv:
|
||||
tile = Tile_read(TileRef(sh_tile_base[element_ref_ix]
|
||||
+ (sh_tile_stride[element_ref_ix] * tile_y + tile_x) * Tile_size));
|
||||
AnnoFillMask fill_mask = Annotated_FillMask_read(ref);
|
||||
alloc_cmd(cmd_ref, cmd_limit);
|
||||
if (tile.tile.offset != 0) {
|
||||
CmdFillMask cmd_fill;
|
||||
cmd_fill.tile_ref = tile.tile.offset;
|
||||
cmd_fill.backdrop = tile.backdrop;
|
||||
cmd_fill.mask = fill_mask.mask;
|
||||
if (tag == Annotated_FillMask) {
|
||||
Cmd_FillMask_write(cmd_ref, cmd_fill);
|
||||
} else {
|
||||
Cmd_FillMaskInv_write(cmd_ref, cmd_fill);
|
||||
}
|
||||
} else {
|
||||
Cmd_SolidMask_write(cmd_ref, CmdSolidMask(fill_mask.mask));
|
||||
}
|
||||
cmd_ref.offset += Cmd_size;
|
||||
break;
|
||||
case Annotated_Stroke:
|
||||
tile = Tile_read(TileRef(sh_tile_base[element_ref_ix]
|
||||
+ (sh_tile_stride[element_ref_ix] * tile_y + tile_x) * Tile_size));
|
||||
|
|
Binary file not shown.
|
@ -130,6 +130,8 @@ State map_element(ElementRef ref, inout bool is_fill) {
|
|||
c.pathseg_count = 1;
|
||||
break;
|
||||
case Element_Fill:
|
||||
case Element_FillMask:
|
||||
case Element_FillMaskInv:
|
||||
is_fill = true;
|
||||
// fall-through
|
||||
case Element_Stroke:
|
||||
|
@ -289,10 +291,6 @@ void main() {
|
|||
for (uint i = 0; i < N_ROWS; i++) {
|
||||
State st = combine_state(row, th_state[i]);
|
||||
|
||||
// We write the state now for development purposes, but the
|
||||
// actual goal is to write transformed and annotated elements.
|
||||
//State_write(StateRef((ix + i) * State_size), st);
|
||||
|
||||
// Here we read again from the original scene. There may be
|
||||
// gains to be had from stashing in shared memory or possibly
|
||||
// registers (though register pressure is an issue).
|
||||
|
@ -385,6 +383,23 @@ void main() {
|
|||
out_ref = AnnotatedRef((st.path_count - 1) * Annotated_size);
|
||||
Annotated_Fill_write(out_ref, anno_fill);
|
||||
break;
|
||||
case Element_FillMask:
|
||||
FillMask fill_mask = Element_FillMask_read(this_ref);
|
||||
AnnoFillMask anno_fill_mask;
|
||||
anno_fill_mask.mask = fill_mask.mask;
|
||||
anno_fill_mask.bbox = st.bbox;
|
||||
out_ref = AnnotatedRef((st.path_count - 1) * Annotated_size);
|
||||
Annotated_FillMask_write(out_ref, anno_fill_mask);
|
||||
break;
|
||||
case Element_FillMaskInv:
|
||||
fill_mask = Element_FillMaskInv_read(this_ref);
|
||||
anno_fill_mask.mask = fill_mask.mask;
|
||||
// The inverse fill conceptually takes up the entire screen.
|
||||
// TODO: Tighten bounds to contain only affected paths.
|
||||
anno_fill_mask.bbox = vec4(0, 0, 1e9, 1e9);
|
||||
out_ref = AnnotatedRef((st.path_count - 1) * Annotated_size);
|
||||
Annotated_FillMaskInv_write(out_ref, anno_fill_mask);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Binary file not shown.
|
@ -27,6 +27,40 @@ layout(rgba8, set = 0, binding = 2) uniform writeonly image2D image;
|
|||
#include "ptcl.h"
|
||||
#include "tile.h"
|
||||
|
||||
// Calculate coverage based on backdrop + coverage of each line segment
|
||||
float[CHUNK] computeArea(vec2 xy, int backdrop, uint tile_ref) {
|
||||
// Probably better to store as float, but conversion is no doubt cheap.
|
||||
float area[CHUNK];
|
||||
for (uint k = 0; k < CHUNK; k++) area[k] = float(backdrop);
|
||||
TileSegRef tile_seg_ref = TileSegRef(tile_ref);
|
||||
do {
|
||||
TileSeg seg = TileSeg_read(tile_seg_ref);
|
||||
for (uint k = 0; k < CHUNK; k++) {
|
||||
vec2 my_xy = vec2(xy.x, xy.y + float(k * CHUNK_DY));
|
||||
vec2 start = seg.start - my_xy;
|
||||
vec2 end = seg.end - my_xy;
|
||||
vec2 window = clamp(vec2(start.y, end.y), 0.0, 1.0);
|
||||
if (window.x != window.y) {
|
||||
vec2 t = (window - start.y) / (end.y - start.y);
|
||||
vec2 xs = vec2(mix(start.x, end.x, t.x), mix(start.x, end.x, t.y));
|
||||
float xmin = min(min(xs.x, xs.y), 1.0) - 1e-6;
|
||||
float xmax = max(xs.x, xs.y);
|
||||
float b = min(xmax, 1.0);
|
||||
float c = max(b, 0.0);
|
||||
float d = max(xmin, 0.0);
|
||||
float a = (b + 0.5 * (d * d - c * c) - xmin) / (xmax - xmin);
|
||||
area[k] += a * (window.x - window.y);
|
||||
}
|
||||
area[k] += sign(end.x - start.x) * clamp(my_xy.y - seg.y_edge + 1.0, 0.0, 1.0);
|
||||
}
|
||||
tile_seg_ref = seg.next;
|
||||
} while (tile_seg_ref.offset != 0);
|
||||
for (uint k = 0; k < CHUNK; k++) {
|
||||
area[k] = min(abs(area[k]), 1.0);
|
||||
}
|
||||
return area;
|
||||
}
|
||||
|
||||
void main() {
|
||||
uint tile_ix = gl_WorkGroupID.y * WIDTH_IN_TILES + gl_WorkGroupID.x;
|
||||
CmdRef cmd_ref = CmdRef(tile_ix * PTCL_INITIAL_ALLOC);
|
||||
|
@ -34,8 +68,10 @@ void main() {
|
|||
uvec2 xy_uint = uvec2(gl_GlobalInvocationID.x, gl_LocalInvocationID.y + TILE_HEIGHT_PX * gl_WorkGroupID.y);
|
||||
vec2 xy = vec2(xy_uint);
|
||||
vec3 rgb[CHUNK];
|
||||
float mask[CHUNK];
|
||||
for (uint i = 0; i < CHUNK; i++) {
|
||||
rgb[i] = vec3(0.5);
|
||||
mask[i] = 1.0;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
|
@ -52,7 +88,7 @@ void main() {
|
|||
float r = length(vec2(xy.x, xy.y + dy) + vec2(0.5, 0.5) - circle.center.xy);
|
||||
float alpha = clamp(0.5 + circle.radius - r, 0.0, 1.0);
|
||||
// TODO: sRGB
|
||||
rgb[i] = mix(rgb[i], fg_rgba.rgb, alpha * fg_rgba.a);
|
||||
rgb[i] = mix(rgb[i], fg_rgba.rgb, mask[i] * alpha * fg_rgba.a);
|
||||
}
|
||||
break;
|
||||
case Cmd_Stroke:
|
||||
|
@ -75,49 +111,43 @@ void main() {
|
|||
fg_rgba = unpackUnorm4x8(stroke.rgba_color).wzyx;
|
||||
for (uint k = 0; k < CHUNK; k++) {
|
||||
float alpha = clamp(stroke.half_width + 0.5 - df[k], 0.0, 1.0);
|
||||
rgb[k] = mix(rgb[k], fg_rgba.rgb, alpha * fg_rgba.a);
|
||||
rgb[k] = mix(rgb[k], fg_rgba.rgb, mask[k] * alpha * fg_rgba.a);
|
||||
}
|
||||
break;
|
||||
case Cmd_Fill:
|
||||
// Calculate coverage based on backdrop + coverage of each line segment
|
||||
CmdFill fill = Cmd_Fill_read(cmd_ref);
|
||||
// Probably better to store as float, but conversion is no doubt cheap.
|
||||
float area[CHUNK];
|
||||
for (uint k = 0; k < CHUNK; k++) area[k] = float(fill.backdrop);
|
||||
tile_seg_ref = TileSegRef(fill.tile_ref);
|
||||
do {
|
||||
TileSeg seg = TileSeg_read(tile_seg_ref);
|
||||
for (uint k = 0; k < CHUNK; k++) {
|
||||
vec2 my_xy = vec2(xy.x, xy.y + float(k * CHUNK_DY));
|
||||
vec2 start = seg.start - my_xy;
|
||||
vec2 end = seg.end - my_xy;
|
||||
vec2 window = clamp(vec2(start.y, end.y), 0.0, 1.0);
|
||||
if (window.x != window.y) {
|
||||
vec2 t = (window - start.y) / (end.y - start.y);
|
||||
vec2 xs = vec2(mix(start.x, end.x, t.x), mix(start.x, end.x, t.y));
|
||||
float xmin = min(min(xs.x, xs.y), 1.0) - 1e-6;
|
||||
float xmax = max(xs.x, xs.y);
|
||||
float b = min(xmax, 1.0);
|
||||
float c = max(b, 0.0);
|
||||
float d = max(xmin, 0.0);
|
||||
float a = (b + 0.5 * (d * d - c * c) - xmin) / (xmax - xmin);
|
||||
area[k] += a * (window.x - window.y);
|
||||
}
|
||||
area[k] += sign(end.x - start.x) * clamp(my_xy.y - seg.y_edge + 1.0, 0.0, 1.0);
|
||||
}
|
||||
tile_seg_ref = seg.next;
|
||||
} while (tile_seg_ref.offset != 0);
|
||||
area = computeArea(xy, fill.backdrop, fill.tile_ref);
|
||||
fg_rgba = unpackUnorm4x8(fill.rgba_color).wzyx;
|
||||
for (uint k = 0; k < CHUNK; k++) {
|
||||
float alpha = min(abs(area[k]), 1.0);
|
||||
rgb[k] = mix(rgb[k], fg_rgba.rgb, alpha * fg_rgba.a);
|
||||
rgb[k] = mix(rgb[k], fg_rgba.rgb, mask[k] * area[k] * fg_rgba.a);
|
||||
}
|
||||
break;
|
||||
case Cmd_FillMask:
|
||||
CmdFillMask fill_mask = Cmd_FillMask_read(cmd_ref);
|
||||
area = computeArea(xy, fill_mask.backdrop, fill_mask.tile_ref);
|
||||
for (uint k = 0; k < CHUNK; k++) {
|
||||
mask[k] = mix(mask[k], fill_mask.mask, area[k]);
|
||||
}
|
||||
break;
|
||||
case Cmd_FillMaskInv:
|
||||
fill_mask = Cmd_FillMask_read(cmd_ref);
|
||||
area = computeArea(xy, fill_mask.backdrop, fill_mask.tile_ref);
|
||||
for (uint k = 0; k < CHUNK; k++) {
|
||||
mask[k] = mix(mask[k], fill_mask.mask, 1.0 - area[k]);
|
||||
}
|
||||
break;
|
||||
case Cmd_Solid:
|
||||
CmdSolid solid = Cmd_Solid_read(cmd_ref);
|
||||
fg_rgba = unpackUnorm4x8(solid.rgba_color).wzyx;
|
||||
for (uint k = 0; k < CHUNK; k++) {
|
||||
rgb[k] = mix(rgb[k], fg_rgba.rgb, fg_rgba.a);
|
||||
rgb[k] = mix(rgb[k], fg_rgba.rgb, mask[k] * fg_rgba.a);
|
||||
}
|
||||
break;
|
||||
case Cmd_SolidMask:
|
||||
CmdSolidMask solid_mask = Cmd_SolidMask_read(cmd_ref);
|
||||
for (uint k = 0; k < CHUNK; k++) {
|
||||
mask[k] = solid_mask.mask;
|
||||
}
|
||||
break;
|
||||
case Cmd_Jump:
|
||||
|
|
Binary file not shown.
|
@ -16,10 +16,18 @@ struct CmdFillRef {
|
|||
uint offset;
|
||||
};
|
||||
|
||||
struct CmdFillMaskRef {
|
||||
uint offset;
|
||||
};
|
||||
|
||||
struct CmdSolidRef {
|
||||
uint offset;
|
||||
};
|
||||
|
||||
struct CmdSolidMaskRef {
|
||||
uint offset;
|
||||
};
|
||||
|
||||
struct CmdJumpRef {
|
||||
uint offset;
|
||||
};
|
||||
|
@ -83,6 +91,18 @@ CmdFillRef CmdFill_index(CmdFillRef ref, uint index) {
|
|||
return CmdFillRef(ref.offset + index * CmdFill_size);
|
||||
}
|
||||
|
||||
struct CmdFillMask {
|
||||
uint tile_ref;
|
||||
int backdrop;
|
||||
float mask;
|
||||
};
|
||||
|
||||
#define CmdFillMask_size 12
|
||||
|
||||
CmdFillMaskRef CmdFillMask_index(CmdFillMaskRef ref, uint index) {
|
||||
return CmdFillMaskRef(ref.offset + index * CmdFillMask_size);
|
||||
}
|
||||
|
||||
struct CmdSolid {
|
||||
uint rgba_color;
|
||||
};
|
||||
|
@ -93,6 +113,16 @@ CmdSolidRef CmdSolid_index(CmdSolidRef ref, uint index) {
|
|||
return CmdSolidRef(ref.offset + index * CmdSolid_size);
|
||||
}
|
||||
|
||||
struct CmdSolidMask {
|
||||
float mask;
|
||||
};
|
||||
|
||||
#define CmdSolidMask_size 4
|
||||
|
||||
CmdSolidMaskRef CmdSolidMask_index(CmdSolidMaskRef ref, uint index) {
|
||||
return CmdSolidMaskRef(ref.offset + index * CmdSolidMask_size);
|
||||
}
|
||||
|
||||
struct CmdJump {
|
||||
uint new_ref;
|
||||
};
|
||||
|
@ -107,9 +137,12 @@ CmdJumpRef CmdJump_index(CmdJumpRef ref, uint index) {
|
|||
#define Cmd_Circle 1
|
||||
#define Cmd_Line 2
|
||||
#define Cmd_Fill 3
|
||||
#define Cmd_Stroke 4
|
||||
#define Cmd_Solid 5
|
||||
#define Cmd_Jump 6
|
||||
#define Cmd_FillMask 4
|
||||
#define Cmd_FillMaskInv 5
|
||||
#define Cmd_Stroke 6
|
||||
#define Cmd_Solid 7
|
||||
#define Cmd_SolidMask 8
|
||||
#define Cmd_Jump 9
|
||||
#define Cmd_size 20
|
||||
|
||||
CmdRef Cmd_index(CmdRef ref, uint index) {
|
||||
|
@ -219,6 +252,25 @@ void CmdFill_write(CmdFillRef ref, CmdFill s) {
|
|||
ptcl[ix + 2] = s.rgba_color;
|
||||
}
|
||||
|
||||
CmdFillMask CmdFillMask_read(CmdFillMaskRef ref) {
|
||||
uint ix = ref.offset >> 2;
|
||||
uint raw0 = ptcl[ix + 0];
|
||||
uint raw1 = ptcl[ix + 1];
|
||||
uint raw2 = ptcl[ix + 2];
|
||||
CmdFillMask s;
|
||||
s.tile_ref = raw0;
|
||||
s.backdrop = int(raw1);
|
||||
s.mask = uintBitsToFloat(raw2);
|
||||
return s;
|
||||
}
|
||||
|
||||
void CmdFillMask_write(CmdFillMaskRef ref, CmdFillMask s) {
|
||||
uint ix = ref.offset >> 2;
|
||||
ptcl[ix + 0] = s.tile_ref;
|
||||
ptcl[ix + 1] = uint(s.backdrop);
|
||||
ptcl[ix + 2] = floatBitsToUint(s.mask);
|
||||
}
|
||||
|
||||
CmdSolid CmdSolid_read(CmdSolidRef ref) {
|
||||
uint ix = ref.offset >> 2;
|
||||
uint raw0 = ptcl[ix + 0];
|
||||
|
@ -232,6 +284,19 @@ void CmdSolid_write(CmdSolidRef ref, CmdSolid s) {
|
|||
ptcl[ix + 0] = s.rgba_color;
|
||||
}
|
||||
|
||||
CmdSolidMask CmdSolidMask_read(CmdSolidMaskRef ref) {
|
||||
uint ix = ref.offset >> 2;
|
||||
uint raw0 = ptcl[ix + 0];
|
||||
CmdSolidMask s;
|
||||
s.mask = uintBitsToFloat(raw0);
|
||||
return s;
|
||||
}
|
||||
|
||||
void CmdSolidMask_write(CmdSolidMaskRef ref, CmdSolidMask s) {
|
||||
uint ix = ref.offset >> 2;
|
||||
ptcl[ix + 0] = floatBitsToUint(s.mask);
|
||||
}
|
||||
|
||||
CmdJump CmdJump_read(CmdJumpRef ref) {
|
||||
uint ix = ref.offset >> 2;
|
||||
uint raw0 = ptcl[ix + 0];
|
||||
|
@ -261,6 +326,14 @@ CmdFill Cmd_Fill_read(CmdRef ref) {
|
|||
return CmdFill_read(CmdFillRef(ref.offset + 4));
|
||||
}
|
||||
|
||||
CmdFillMask Cmd_FillMask_read(CmdRef ref) {
|
||||
return CmdFillMask_read(CmdFillMaskRef(ref.offset + 4));
|
||||
}
|
||||
|
||||
CmdFillMask Cmd_FillMaskInv_read(CmdRef ref) {
|
||||
return CmdFillMask_read(CmdFillMaskRef(ref.offset + 4));
|
||||
}
|
||||
|
||||
CmdStroke Cmd_Stroke_read(CmdRef ref) {
|
||||
return CmdStroke_read(CmdStrokeRef(ref.offset + 4));
|
||||
}
|
||||
|
@ -269,6 +342,10 @@ CmdSolid Cmd_Solid_read(CmdRef ref) {
|
|||
return CmdSolid_read(CmdSolidRef(ref.offset + 4));
|
||||
}
|
||||
|
||||
CmdSolidMask Cmd_SolidMask_read(CmdRef ref) {
|
||||
return CmdSolidMask_read(CmdSolidMaskRef(ref.offset + 4));
|
||||
}
|
||||
|
||||
CmdJump Cmd_Jump_read(CmdRef ref) {
|
||||
return CmdJump_read(CmdJumpRef(ref.offset + 4));
|
||||
}
|
||||
|
@ -292,6 +369,16 @@ void Cmd_Fill_write(CmdRef ref, CmdFill s) {
|
|||
CmdFill_write(CmdFillRef(ref.offset + 4), s);
|
||||
}
|
||||
|
||||
void Cmd_FillMask_write(CmdRef ref, CmdFillMask s) {
|
||||
ptcl[ref.offset >> 2] = Cmd_FillMask;
|
||||
CmdFillMask_write(CmdFillMaskRef(ref.offset + 4), s);
|
||||
}
|
||||
|
||||
void Cmd_FillMaskInv_write(CmdRef ref, CmdFillMask s) {
|
||||
ptcl[ref.offset >> 2] = Cmd_FillMaskInv;
|
||||
CmdFillMask_write(CmdFillMaskRef(ref.offset + 4), s);
|
||||
}
|
||||
|
||||
void Cmd_Stroke_write(CmdRef ref, CmdStroke s) {
|
||||
ptcl[ref.offset >> 2] = Cmd_Stroke;
|
||||
CmdStroke_write(CmdStrokeRef(ref.offset + 4), s);
|
||||
|
@ -302,6 +389,11 @@ void Cmd_Solid_write(CmdRef ref, CmdSolid s) {
|
|||
CmdSolid_write(CmdSolidRef(ref.offset + 4), s);
|
||||
}
|
||||
|
||||
void Cmd_SolidMask_write(CmdRef ref, CmdSolidMask s) {
|
||||
ptcl[ref.offset >> 2] = Cmd_SolidMask;
|
||||
CmdSolidMask_write(CmdSolidMaskRef(ref.offset + 4), s);
|
||||
}
|
||||
|
||||
void Cmd_Jump_write(CmdRef ref, CmdJump s) {
|
||||
ptcl[ref.offset >> 2] = Cmd_Jump;
|
||||
CmdJump_write(CmdJumpRef(ref.offset + 4), s);
|
||||
|
|
|
@ -16,6 +16,10 @@ struct FillRef {
|
|||
uint offset;
|
||||
};
|
||||
|
||||
struct FillMaskRef {
|
||||
uint offset;
|
||||
};
|
||||
|
||||
struct StrokeRef {
|
||||
uint offset;
|
||||
};
|
||||
|
@ -78,6 +82,16 @@ FillRef Fill_index(FillRef ref, uint index) {
|
|||
return FillRef(ref.offset + index * Fill_size);
|
||||
}
|
||||
|
||||
struct FillMask {
|
||||
float mask;
|
||||
};
|
||||
|
||||
#define FillMask_size 4
|
||||
|
||||
FillMaskRef FillMask_index(FillMaskRef ref, uint index) {
|
||||
return FillMaskRef(ref.offset + index * FillMask_size);
|
||||
}
|
||||
|
||||
struct Stroke {
|
||||
uint rgba_color;
|
||||
};
|
||||
|
@ -120,6 +134,8 @@ TransformRef Transform_index(TransformRef ref, uint index) {
|
|||
#define Element_Fill 8
|
||||
#define Element_SetLineWidth 9
|
||||
#define Element_Transform 10
|
||||
#define Element_FillMask 11
|
||||
#define Element_FillMaskInv 12
|
||||
#define Element_size 36
|
||||
|
||||
ElementRef Element_index(ElementRef ref, uint index) {
|
||||
|
@ -179,6 +195,14 @@ Fill Fill_read(FillRef ref) {
|
|||
return s;
|
||||
}
|
||||
|
||||
FillMask FillMask_read(FillMaskRef ref) {
|
||||
uint ix = ref.offset >> 2;
|
||||
uint raw0 = scene[ix + 0];
|
||||
FillMask s;
|
||||
s.mask = uintBitsToFloat(raw0);
|
||||
return s;
|
||||
}
|
||||
|
||||
Stroke Stroke_read(StrokeRef ref) {
|
||||
uint ix = ref.offset >> 2;
|
||||
uint raw0 = scene[ix + 0];
|
||||
|
@ -253,3 +277,11 @@ Transform Element_Transform_read(ElementRef ref) {
|
|||
return Transform_read(TransformRef(ref.offset + 4));
|
||||
}
|
||||
|
||||
FillMask Element_FillMask_read(ElementRef ref) {
|
||||
return FillMask_read(FillMaskRef(ref.offset + 4));
|
||||
}
|
||||
|
||||
FillMask Element_FillMaskInv_read(ElementRef ref) {
|
||||
return FillMask_read(FillMaskRef(ref.offset + 4));
|
||||
}
|
||||
|
||||
|
|
|
@ -47,6 +47,8 @@ void main() {
|
|||
int x0 = 0, y0 = 0, x1 = 0, y1 = 0;
|
||||
switch (tag) {
|
||||
case Annotated_Fill:
|
||||
case Annotated_FillMask:
|
||||
case Annotated_FillMaskInv:
|
||||
case Annotated_Stroke:
|
||||
// Note: we take advantage of the fact that fills and strokes
|
||||
// have compatible layout.
|
||||
|
|
Binary file not shown.
Loading…
Reference in a new issue