summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/modules/checkers/checkers.c78
1 files changed, 71 insertions, 7 deletions
diff --git a/src/modules/checkers/checkers.c b/src/modules/checkers/checkers.c
index 5554e21..20ecd63 100644
--- a/src/modules/checkers/checkers.c
+++ b/src/modules/checkers/checkers.c
@@ -130,11 +130,73 @@ static void checkers_destroy_context(til_module_context_t *context)
}
+/* This is derived from til_fb_fragment_tile_single() with two variations:
+ * 1. when the size doesn't align with frame size, the start tiles are offset
+ * to center the checkers letting the edge checkers all clip as needed
+ * 2. the incoming frame width isn't propagated down to the tiled fragments,
+ * though for the potentially clipped boundary tiles the frame_{width,height}
+ * won't match the incoming width,height.
+ *
+ * XXX note this fragmenter in particular really exercises fill_modules' correct handling
+ * of frame vs. fragment dimensions and clipping semantics
+ */
+int checkers_fragment_tile_single(const til_fb_fragment_t *fragment, unsigned tile_size, unsigned number, til_fb_fragment_t *res_fragment)
+{
+ unsigned w = fragment->width / tile_size, h = fragment->height / tile_size;
+ unsigned tiled_w = w * tile_size, tiled_h = h * tile_size;
+ unsigned x, y, xoff, yoff, xshift = 0, yshift = 0;
+
+ /* Detect the need for fractional tiles on both axis and shift the fragments
+ * to keep the overall checkered output centered. This complicates res_fragment.{x,y,width,height}
+ * calculations for the peripheral checker tiles as those must clip when shifted.
+ */
+ if (tiled_w < fragment->width) {
+ tiled_w += tile_size;
+ xshift = (tiled_w - fragment->width) >> 1;
+ w++;
+ }
+
+ if (tiled_h < fragment->height) {
+ tiled_h += tile_size;
+ yshift = (tiled_h - fragment->height) >> 1;
+ h++;
+ }
+
+ y = number / w;
+ if (y >= h)
+ return 0;
+
+ x = number - (y * w);
+
+ xoff = x * tile_size;
+ yoff = y * tile_size;
+
+ *res_fragment = (til_fb_fragment_t){
+ .texture = fragment->texture,
+ .buf = fragment->buf + (yoff * fragment->pitch) - (y ? (yshift * fragment->pitch) : 0) + (xoff - (x ? xshift : 0)),
+ .width = MIN(fragment->width - (xoff - xshift), x ? tile_size : (tile_size - xshift)),
+ .height = MIN(fragment->height - (yoff - yshift), y ? tile_size : (tile_size - yshift)),
+ .x = x ? 0 : xshift,
+ .y = y ? 0 : yshift,
+ // this is a little janky but leave frame_width to be set by render_fragment
+ // so it can use the old frame_width for determining checkered state
+ .frame_width = fragment->width, // becomes tile_size
+ .frame_height = fragment->height, // becomes tile_size
+ .stride = fragment->stride + (fragment->width - MIN(fragment->width - (xoff - xshift), x ? tile_size : (tile_size - xshift))),
+ .pitch = fragment->pitch,
+ .number = number,
+ .cleared = fragment->cleared,
+ };
+
+ return 1;
+}
+
+
static int checkers_fragmenter(til_module_context_t *context, const til_fb_fragment_t *fragment, unsigned number, til_fb_fragment_t *res_fragment)
{
checkers_context_t *ctxt = (checkers_context_t *)context;
- return til_fb_fragment_tile_single(fragment, ctxt->setup.size, number, res_fragment);
+ return checkers_fragment_tile_single(fragment, ctxt->setup.size, number, res_fragment);
}
@@ -174,13 +236,15 @@ static void checkers_render_fragment(til_module_context_t *context, unsigned tic
switch (ctxt->setup.pattern) {
case CHECKERS_PATTERN_CHECKERED: {
- unsigned tiles_per_row;
+ unsigned tiles_per_row, row, col;
tiles_per_row = fragment->frame_width / ctxt->setup.size;
if (tiles_per_row * ctxt->setup.size < fragment->frame_width)
tiles_per_row++;
- state = (fragment->number + (fragment->y / ctxt->setup.size) * !(tiles_per_row & 0x1)) & 0x1;
+ row = fragment->number / tiles_per_row;
+ col = fragment->number % tiles_per_row;
+ state = (row ^ col) & 0x1;
break;
}
case CHECKERS_PATTERN_RANDOM:
@@ -188,6 +252,10 @@ static void checkers_render_fragment(til_module_context_t *context, unsigned tic
break;
}
+ /* now that state has been determined, set the frame size */
+ fragment->frame_width = ctxt->setup.size;
+ fragment->frame_height = ctxt->setup.size;
+
switch (ctxt->setup.dynamics) {
case CHECKERS_DYNAMICS_ODD:
break;
@@ -224,10 +292,6 @@ static void checkers_render_fragment(til_module_context_t *context, unsigned tic
if (!ctxt->setup.fill_module)
til_fb_fragment_fill(fragment, flags, color);
else {
- fragment->frame_width = ctxt->setup.size;
- fragment->frame_height = ctxt->setup.size;
- fragment->x = fragment->y = 0;
-
/* TODO: we need a way to send down color and flags, and use the module render as a brush of sorts */
til_module_render(ctxt->fill_module_contexts[cpu], ticks, fragment);
}
© All Rights Reserved