summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorVito Caputo <vcaputo@pengaru.com>2022-07-24 00:21:22 -0700
committerVito Caputo <vcaputo@pengaru.com>2022-07-24 04:25:28 -0700
commit3b6e34e70d2bf508156a03fb3e2357894f4f6ad9 (patch)
treec714fcdf9011c787993e6186a9ed082d7a26676f /src
parent3350c54719272d8c49b1b579c7711d13a8f290d5 (diff)
modules/shapes: fix up clipped fragment/frame
This is a first approximation of correct handling of arbitrarily clipped frames described by the incoming fragment. It's still relying on the _checked() put_pixel variants for clipping. That should probably be improved by constraining the loops to the clipped fragment edges.
Diffstat (limited to 'src')
-rw-r--r--src/modules/shapes/shapes.c135
1 files changed, 72 insertions, 63 deletions
diff --git a/src/modules/shapes/shapes.c b/src/modules/shapes/shapes.c
index 0a53a34..47bb8df 100644
--- a/src/modules/shapes/shapes.c
+++ b/src/modules/shapes/shapes.c
@@ -118,29 +118,29 @@ static til_module_context_t * shapes_create_context(unsigned seed, unsigned tick
static void shapes_render_fragment(til_module_context_t *context, unsigned ticks, unsigned cpu, til_fb_fragment_t *fragment)
{
shapes_context_t *ctxt = (shapes_context_t *)context;
- unsigned size = MIN(fragment->width, fragment->height) * ctxt->setup.scale;
- unsigned xoff = (fragment->width - size) >> 1;
- unsigned yoff = (fragment->height - size) >> 1;
+ unsigned size = MIN(fragment->frame_width, fragment->frame_height) * ctxt->setup.scale;
+ unsigned xoff = (fragment->frame_width - size) >> 1;
+ unsigned yoff = (fragment->frame_height - size) >> 1;
if (!fragment->cleared) {
/* when {letter,pillar}boxed we need to clear the padding */
- if (xoff) {
- for (int y = 0; y < fragment->height; y++) {
- for (int x = 0; x < xoff; x++)
- til_fb_fragment_put_pixel_unchecked(fragment, 0, fragment->x + x, fragment->y + y, 0x0);
- for (int x = fragment->width - (size + xoff); x < fragment->width; x++)
- til_fb_fragment_put_pixel_unchecked(fragment, 0, fragment->x + x, fragment->y + y, 0x0);
+ if (xoff > fragment->x) {
+ for (int y = fragment->y; y < fragment->y + fragment->height; y++) {
+ for (int x = fragment->x; x < xoff; x++)
+ til_fb_fragment_put_pixel_checked(fragment, 0, fragment->x, fragment->y, 0x0);
+ for (int x = fragment->frame_width - (size + xoff); x < fragment->x + fragment->width; x++)
+ til_fb_fragment_put_pixel_checked(fragment, 0, fragment->x, fragment->y, 0x0);
}
}
- if (yoff) {
- for (int y = 0; y < yoff; y++)
- for (int x = 0; x < fragment->width; x++)
- til_fb_fragment_put_pixel_unchecked(fragment, 0, fragment->x + x, fragment->y + y, 0x0);
+ if (yoff > fragment->y) {
+ for (int y = fragment->y; y < yoff; y++)
+ for (int x = fragment->x; x < fragment->x + fragment->width; x++)
+ til_fb_fragment_put_pixel_unchecked(fragment, 0, fragment->x, fragment->y, 0x0);
- for (int y = fragment->height - (size + yoff); y < fragment->height; y++)
- for (int x = 0; x < fragment->width; x++)
- til_fb_fragment_put_pixel_unchecked(fragment, 0, fragment->x + x, fragment->y + y, 0x0);
+ for (int y = fragment->frame_height - (size + yoff); y < fragment->y + fragment->height; y++)
+ for (int x = fragment->x; x < fragment->x + fragment->width; x++)
+ til_fb_fragment_put_pixel_unchecked(fragment, 0, fragment->x, fragment->y, 0x0);
}
}
@@ -149,22 +149,25 @@ static void shapes_render_fragment(til_module_context_t *context, unsigned ticks
*/
switch (ctxt->setup.type) {
case SHAPES_TYPE_CIRCLE: {
- int r_sq = (size >> 1);
- float s = 2.f / (float)size;
- float XX, YY;
-
- r_sq *= r_sq;
-
- YY = -1.f;
- for (int y = yoff, Y = -(size >> 1); y < yoff + size; y++, Y++, YY += s) {
- XX = -1.f;
- for (int x = xoff, X = -(size >> 1); x < xoff + size; x++, X++, XX += s) {
+ unsigned yskip = (fragment->y > yoff ? (fragment->y - yoff) : 0);
+ unsigned xskip = (fragment->x > xoff ? (fragment->x - xoff) : 0);
+ int r_sq = (size >> 1) * (size >> 1);
+ float s = 2.f / (float)size;
+ float XX, YY;
+ int X, Y;
+
+ YY = -1.f + yskip * s;
+ Y = -(size >> 1) + yskip;
+ for (unsigned y = MAX(fragment->y, yoff); y < yoff + size; y++, Y++, YY += s) {
+ XX = -1.f + xskip * s;
+ X = -(size >> 1) + xskip;
+ for (unsigned x = MAX(fragment->x, xoff); x < xoff + size; x++, X++, XX += s) {
float rad = atan2f(YY, XX);
if (Y*Y+X*X < r_sq * (1.f - fabsf(cosf(ctxt->setup.n_pinches * rad + (float)ticks * ctxt->setup.pinch_spin * SHAPES_SPIN_BASE)) * ctxt->setup.pinch))
- til_fb_fragment_put_pixel_unchecked(fragment, TIL_FB_DRAW_FLAG_TEXTURABLE, fragment->x + x, fragment->y + y, 0xffffffff);
+ til_fb_fragment_put_pixel_checked(fragment, TIL_FB_DRAW_FLAG_TEXTURABLE, x, y, 0xffffffff); /* TODO: stop relying on checked for clipping */
else if (!fragment->cleared)
- til_fb_fragment_put_pixel_unchecked(fragment, 0, fragment->x + x, fragment->y + y, 0x0);
+ til_fb_fragment_put_pixel_checked(fragment, 0, x, y, 0x0);
}
}
@@ -172,22 +175,24 @@ static void shapes_render_fragment(til_module_context_t *context, unsigned ticks
}
case SHAPES_TYPE_PINWHEEL: {
- float s = 2.f / (float)size;
- float X, Y;
-
- Y = -1.f;
- for (unsigned y = yoff; y < yoff + size; y++, Y += s) {
- X = -1.f;
- for (unsigned x = xoff; x < xoff + size; x++, X += s) {
- float rad = atan2f(Y, X);
+ unsigned yskip = (fragment->y > yoff ? (fragment->y - yoff) : 0);
+ unsigned xskip = (fragment->x > xoff ? (fragment->x - xoff) : 0);
+ float s = 2.f / (float)size;
+ float XX, YY;
+
+ YY = -1.f + yskip * s;
+ for (unsigned y = MAX(fragment->y, yoff); y < yoff + size; y++, YY += s) {
+ XX = -1.f + xskip * s;
+ for (unsigned x = MAX(fragment->x, xoff); x < xoff + size; x++, XX += s) {
+ float rad = atan2f(YY, XX);
float r = cosf((float)ctxt->setup.n_points * (rad + (float)ticks * ctxt->setup.spin * SHAPES_SPIN_BASE)) * .5f + .5f;
r *= 1.f - fabsf(cosf(ctxt->setup.n_pinches * rad + (float)ticks * ctxt->setup.pinch_spin * SHAPES_SPIN_BASE)) * ctxt->setup.pinch;
- if (X * X + Y * Y < r * r)
- til_fb_fragment_put_pixel_unchecked(fragment, TIL_FB_DRAW_FLAG_TEXTURABLE, fragment->x + x, fragment->y + y, 0xffffffff);
+ if (XX * XX + YY * YY < r * r)
+ til_fb_fragment_put_pixel_checked(fragment, TIL_FB_DRAW_FLAG_TEXTURABLE, x, y, 0xffffffff); /* stop relying on checked for clipping */
else if (!fragment->cleared)
- til_fb_fragment_put_pixel_unchecked(fragment, 0, fragment->x + x, fragment->y + y, 0x0);
+ til_fb_fragment_put_pixel_checked(fragment, 0, x, y, 0x0);
}
}
@@ -195,23 +200,25 @@ static void shapes_render_fragment(til_module_context_t *context, unsigned ticks
}
case SHAPES_TYPE_RHOMBUS: {
- int r = (size >> 1);
- float s = 2.f / (float)size;
- float XX, YY;
- int X, Y;
-
- YY = -1.f;
- Y = -(size >> 1);
- for (unsigned y = yoff; y < yoff + size; y++, Y++, YY += s) {
- XX = -1.f;
- X = -(size >> 1);
- for (unsigned x = xoff; x < xoff + size; x++, X++, XX += s) {
+ unsigned yskip = (fragment->y > yoff ? (fragment->y - yoff) : 0);
+ unsigned xskip = (fragment->x > xoff ? (fragment->x - xoff) : 0);
+ float s = 2.f / (float)size;
+ int r = (size >> 1);
+ float XX, YY;
+ int X, Y;
+
+ YY = -1.f + yskip * s;
+ Y = -(size >> 1) + yskip;
+ for (unsigned y = MAX(fragment->y, yoff); y < yoff + size; y++, Y++, YY += s) {
+ XX = -1.f + xskip * s;
+ X = -(size >> 1) + xskip;
+ for (unsigned x = MAX(fragment->x, xoff); x < xoff + size; x++, X++, XX += s) {
float rad = atan2f(YY, XX);
if (abs(Y) + abs(X) < r * (1.f - fabsf(cosf(ctxt->setup.n_pinches * rad + (float)ticks * ctxt->setup.pinch_spin * SHAPES_SPIN_BASE)) * ctxt->setup.pinch))
- til_fb_fragment_put_pixel_unchecked(fragment, TIL_FB_DRAW_FLAG_TEXTURABLE, fragment->x + x, fragment->y + y, 0xffffffff);
+ til_fb_fragment_put_pixel_checked(fragment, TIL_FB_DRAW_FLAG_TEXTURABLE, x, y, 0xffffffff);
else if (!fragment->cleared)
- til_fb_fragment_put_pixel_unchecked(fragment, 0, fragment->x + x, fragment->y + y, 0x0);
+ til_fb_fragment_put_pixel_checked(fragment, 0, x, y, 0x0);
}
}
@@ -219,23 +226,25 @@ static void shapes_render_fragment(til_module_context_t *context, unsigned ticks
}
case SHAPES_TYPE_STAR: {
- float s = 2.f / (float)size;
- float X, Y;
-
- Y = -1.f;
- for (unsigned y = yoff; y < yoff + size; y++, Y += s) {
- X = -1.f;
- for (unsigned x = xoff; x < xoff + size; x++, X += s) {
- float rad = atan2f(Y, X);
+ unsigned yskip = (fragment->y > yoff ? (fragment->y - yoff) : 0);
+ unsigned xskip = (fragment->x > xoff ? (fragment->x - xoff) : 0);
+ float s = 2.f / (float)size;
+ float XX, YY;
+
+ YY = -1.f + yskip * s;
+ for (unsigned y = MAX(fragment->y, yoff); y < yoff + size; y++, YY += s) {
+ XX = -1.f + xskip * s;
+ for (unsigned x = MAX(fragment->x, xoff); x < xoff + size; x++, XX += s) {
+ float rad = atan2f(YY, XX);
float r = (M_2_PI * asinf(sinf((float)ctxt->setup.n_points * (rad + (float)ticks * ctxt->setup.spin * SHAPES_SPIN_BASE)) * .5f + .5f)) * .5f + .5f;
/* ^^^^^^^^^^^^^^^^^^^ approximates a triangle wave */
r *= 1.f - fabsf(cosf(ctxt->setup.n_pinches * rad + (float)ticks * ctxt->setup.pinch_spin * SHAPES_SPIN_BASE)) * ctxt->setup.pinch;
- if (X * X + Y * Y < r * r)
- til_fb_fragment_put_pixel_unchecked(fragment, TIL_FB_DRAW_FLAG_TEXTURABLE, fragment->x + x, fragment->y + y, 0xffffffff);
+ if (XX * XX + YY * YY < r * r)
+ til_fb_fragment_put_pixel_checked(fragment, TIL_FB_DRAW_FLAG_TEXTURABLE, x, y, 0xffffffff);
else if (!fragment->cleared)
- til_fb_fragment_put_pixel_unchecked(fragment, 0, fragment->x + x, fragment->y + y, 0x0);
+ til_fb_fragment_put_pixel_checked(fragment, 0, x, y, 0x0);
}
}
break;
© All Rights Reserved