summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorVito Caputo <vcaputo@pengaru.com>2019-11-24 17:44:53 -0800
committerVito Caputo <vcaputo@pengaru.com>2019-11-24 17:50:18 -0800
commit4d87a91891a2ff29f399edebfcd3590316a14445 (patch)
tree0560129e41949191082fbb4611ebca328269d414 /src
parent0b2f0d406657515559c697533f5e27cf05437507 (diff)
montage: rework fragmenter
This repurposes the generic fb_fragment_tile_single() to better fit the montage use case. Partially covered areas are simply skipped, and tiles no longer need to be square. In determining the tile width and height, I'm just using the sqrt of the number of modules and dividing the frame width and height. But when the sqrt has a fraction, it's rounded up on the width divide and rounded down on the height divide. So the width gets the extra column of tiles, and the height just throws away the fraction. I think it's OK for now, until someone gets a bug up their ass and wants to avoid having vacant tiles in the bottom right corner when the number of modules doesn't cooperate. One problem with the just skipping partially covered areas is they don't get zeroed out - no fragment is ever generated for them. To fix that there will prolly have to be a fb_fragment_zero() of the frame @ prepare :(. I guess it wouldn't be the end of the world if the fragmenter itself zeroed out skipped regions. It's kind of an ugly layering violation but this is a private montage- specific fragmenter.
Diffstat (limited to 'src')
-rw-r--r--src/modules/montage/montage.c59
1 files changed, 51 insertions, 8 deletions
diff --git a/src/modules/montage/montage.c b/src/modules/montage/montage.c
index 697c28d..bf5aef4 100644
--- a/src/modules/montage/montage.c
+++ b/src/modules/montage/montage.c
@@ -109,6 +109,50 @@ static void montage_destroy_context(void *context)
}
+
+/* this is a hacked up derivative of fb_fragment_tile_single() */
+static int montage_fragment_tile(const fb_fragment_t *fragment, unsigned tile_width, unsigned tile_height, unsigned number, fb_fragment_t *res_fragment)
+{
+ unsigned w = fragment->width / tile_width, h = fragment->height / tile_height;
+ unsigned x, y, xoff, yoff;
+
+#if 0
+ /* total coverage isn't important in montage, leave blank gaps */
+ /* I'm keeping this here for posterity though and to record a TODO:
+ * it might be desirable to try center the montage when there must be gaps,
+ * rather than letting the gaps always fall on the far side.
+ */
+ if (w * tile_width < fragment->width)
+ w++;
+
+ if (h * tile_height < fragment->height)
+ h++;
+#endif
+
+ y = number / w;
+ if (y >= h)
+ return 0;
+
+ x = number - (y * w);
+
+ xoff = x * tile_width;
+ yoff = y * tile_height;
+
+ res_fragment->buf = (void *)fragment->buf + (yoff * fragment->pitch) + (xoff * 4);
+ res_fragment->x = 0; /* fragment is a new frame */
+ res_fragment->y = 0; /* fragment is a new frame */
+ res_fragment->width = MIN(fragment->width - xoff, tile_width);
+ res_fragment->height = MIN(fragment->height - yoff, tile_height);
+ res_fragment->frame_width = res_fragment->width; /* fragment is a new frame */
+ res_fragment->frame_height = res_fragment->height; /* fragment is a new frame */
+ res_fragment->stride = fragment->stride + ((fragment->width - res_fragment->width) * 4);
+ res_fragment->pitch = fragment->pitch;
+ res_fragment->number = number;
+
+ return 1;
+}
+
+
/* The fragmenter in montage is serving double-duty:
* 1. it divides the frame into subfragments for threaded rendering
* 2. it determines which modules will be rendered where via fragment->number
@@ -116,18 +160,18 @@ static void montage_destroy_context(void *context)
static int montage_fragmenter(void *context, const fb_fragment_t *fragment, unsigned number, fb_fragment_t *res_fragment)
{
montage_context_t *ctxt = context;
- float root = sqrtf((float)ctxt->n_modules);
+ float root = sqrtf(ctxt->n_modules);
+ unsigned tile_width = fragment->frame_width / ceilf(root); /* screens are wide, give excess to the width */
+ unsigned tile_height = fragment->frame_height / floorf(root); /* take from the height */
int ret;
- ret = fb_fragment_tile_single(fragment, fragment->frame_height / root, number, res_fragment);
+ /* XXX: this could all be more clever and make some tiles bigger than others to deal with fractional square roots,
+ * but this is good enough for now considering the simplicity.
+ */
+ ret = montage_fragment_tile(fragment, tile_width, tile_height, number, res_fragment);
if (!ret)
return 0;
- /* as these tiles are frames of their own rather than subfragments, override these values */
- res_fragment->x = res_fragment->y = 0;
- res_fragment->frame_width = res_fragment->width;
- res_fragment->frame_height = res_fragment->height;
-
return ret;
}
@@ -147,7 +191,6 @@ static void montage_render_fragment(void *context, unsigned cpu, fb_fragment_t *
const rototiller_module_t *module = ctxt->modules[fragment->number];
if (fragment->number >= ctxt->n_modules) {
-
fb_fragment_zero(fragment);
return;
© All Rights Reserved