From fa268acb0490f7f05bef96902aee84ad4f69151d Mon Sep 17 00:00:00 2001
From: Vito Caputo <vcaputo@pengaru.com>
Date: Tue, 11 Jul 2023 16:20:06 -0700
Subject: modules/blinds: make blinds threaded

This is a first stab at threading blinds, while here I got rid of
the reliance on _checked() put_pixel for clipping.

This could be better, things like using a block put/copy instead
of put_pixel would be a huge advantage for blinds due to its
naturally contiguous blocks per-blind.

While this module when non-threaded wasn't especially slow, any
module leaving cores idle is depriving other potentially threaded
modules of utilizing them for the duration of the non-threaded
render.  So now that rototiller is being used for compositions
and increasingly becoming something of a meta-demo, it's become
important to make everything as threaded as possible.
---
 src/modules/blinds/blinds.c | 71 +++++++++++++++++++++++++++++++++++----------
 1 file changed, 56 insertions(+), 15 deletions(-)

(limited to 'src/modules/blinds')

diff --git a/src/modules/blinds/blinds.c b/src/modules/blinds/blinds.c
index 8acfae8..c4ee07f 100644
--- a/src/modules/blinds/blinds.c
+++ b/src/modules/blinds/blinds.c
@@ -75,16 +75,39 @@ static til_module_context_t * blinds_create_context(const til_module_t *module,
 }
 
 
+static void blinds_prepare_frame(til_module_context_t *context, til_stream_t *stream, unsigned ticks, til_fb_fragment_t **fragment_ptr, til_frame_plan_t *res_frame_plan)
+{
+	*res_frame_plan = (til_frame_plan_t){ .fragmenter = til_fragmenter_tile64 };
+}
+
+
 /* draw a horizontal blind over fragment */
 static inline void draw_blind_horizontal(til_fb_fragment_t *fragment, unsigned row, unsigned count, float t)
 {
-	unsigned	row_height = fragment->frame_height / count;
-	unsigned	height = roundf(t * (float)row_height);
-
-/* XXX FIXME: use faster block style fill/copy if til_fb gets that */
-	for (unsigned y = 0; y < height; y++) {
-		for (unsigned x = 0; x < fragment->width; x++)
-			til_fb_fragment_put_pixel_checked(fragment, TIL_FB_DRAW_FLAG_TEXTURABLE, fragment->x + x, fragment->y + y + row * row_height, 0xffffffff); /* FIXME: use _unchecked() variant, but must not assume frame_height == height */
+	float		row_height = fragment->frame_height / (float)count;
+	unsigned	height = roundf(t * row_height);
+	unsigned	row_y = row * row_height;
+
+	if (row_y >= fragment->y + fragment->height)
+		return;
+
+	if (row_y + height <= fragment->y)
+		return;
+
+	{
+		unsigned	ystart = MAX(row_y, fragment->y);
+		unsigned	yend = MIN(row_y + height, fragment->y + fragment->height);
+		unsigned	xstart = fragment->x;
+		unsigned	xend = fragment->x + fragment->width;
+
+		for (unsigned y = ystart; y < yend; y++) {
+			/* XXX FIXME: use faster block style fill/copy if til_fb gets that */
+			for (unsigned x = xstart; x < xend; x++) {
+				til_fb_fragment_put_pixel_unchecked(fragment,
+								    TIL_FB_DRAW_FLAG_TEXTURABLE,
+								    x, y, 0xffffffff);
+			}
+		}
 	}
 }
 
@@ -92,13 +115,30 @@ static inline void draw_blind_horizontal(til_fb_fragment_t *fragment, unsigned r
 /* draw a vertical blind over fragment */
 static inline void draw_blind_vertical(til_fb_fragment_t *fragment, unsigned column, unsigned count, float t)
 {
-	unsigned	column_width = fragment->frame_width / count;
-	unsigned	width = roundf(t * (float)column_width);
-
-/* XXX FIXME: use faster block style fill/copy if til_fb gets that */
-	for (unsigned y = 0; y < fragment->height; y++) {
-		for (unsigned x = 0; x < width; x++)
-			til_fb_fragment_put_pixel_checked(fragment, TIL_FB_DRAW_FLAG_TEXTURABLE, fragment->x + x + column * column_width, fragment->y + y, 0xffffffff); /* FIXME: use _unchecked() variant, but must not assume frame_width == width */
+	float		column_width = fragment->frame_width / (float)count;
+	unsigned	width = roundf(t * column_width);
+	unsigned	column_x = column * column_width;
+
+	if (column_x >= fragment->x + fragment->width)
+		return;
+
+	if (column_x + width <= fragment->x)
+		return;
+
+	{
+		unsigned	xstart = MAX(column_x, fragment->x);
+		unsigned	xend = MIN(column_x + width, fragment->x + fragment->width);
+		unsigned	ystart = fragment->y;
+		unsigned	yend = fragment->y + fragment->height;
+
+		for (unsigned y = ystart; y < yend; y++) {
+			/* XXX FIXME: use faster block style fill/copy if/when til_fb gets that */
+			for (unsigned x = xstart; x < xend; x++) {
+				til_fb_fragment_put_pixel_unchecked(fragment,
+								    TIL_FB_DRAW_FLAG_TEXTURABLE,
+								    x, y, 0xffffffff);
+			}
+		}
 	}
 }
 
@@ -208,10 +248,11 @@ static int blinds_setup(const til_settings_t *settings, til_setting_t **res_sett
 
 til_module_t	blinds_module = {
 	.create_context = blinds_create_context,
+	.prepare_frame = blinds_prepare_frame,
 	.render_fragment = blinds_render_fragment,
 	.setup = blinds_setup,
 	.name = "blinds",
-	.description = "Retro 80s-inspired window blinds",
+	.description = "Retro 80s-inspired window blinds (threaded)",
 	.author = "Vito Caputo <vcaputo@pengaru.com>",
 	.flags = TIL_MODULE_OVERLAYABLE,
 };
-- 
cgit v1.2.3