summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVito Caputo <vcaputo@pengaru.com>2022-04-19 15:27:30 -0700
committerVito Caputo <vcaputo@pengaru.com>2022-04-22 00:50:39 -0700
commitf8929c9f06eff1dc2efa8331a26fb0f7b1ab3252 (patch)
treecd61010c66eba98513e5741bacff8dcafaf9af3b
parent8e1330d60cb94629cbc09f65f558d47cdbfe633b (diff)
modules/checkers: experimenting with a checkers overlay
This adds a checkers style overlay module, it's not terribly interesting but may be made more useful if modules start differentiating themselves as substantial vs. overlay effects. It'd be nice if rtv/compose could automagically apply and randomize overlay modules atop others, which would make use of this type of thing as well as encourage more small modules like these be written.
-rw-r--r--configure.ac1
-rw-r--r--src/Makefile.am2
-rw-r--r--src/modules/Makefile.am2
-rw-r--r--src/modules/checkers/Makefile.am3
-rw-r--r--src/modules/checkers/checkers.c302
5 files changed, 308 insertions, 2 deletions
diff --git a/configure.ac b/configure.ac
index 51cbe05..8331d2f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -42,6 +42,7 @@ AC_CONFIG_FILES([
src/libs/txt/Makefile
src/modules/Makefile
src/modules/blinds/Makefile
+ src/modules/checkers/Makefile
src/modules/compose/Makefile
src/modules/drizzle/Makefile
src/modules/flui2d/Makefile
diff --git a/src/Makefile.am b/src/Makefile.am
index a676ce4..733c459 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -3,7 +3,7 @@ SUBDIRS = libs modules
noinst_LTLIBRARIES = libtil.la
libtil_la_SOURCES = til_args.c til_args.h til_fb.c til_fb.h til_knobs.h til.c til.h til_settings.h til_settings.c til_threads.c til_threads.h til_util.c til_util.h
libtil_la_CPPFLAGS = -I@top_srcdir@/src
-libtil_la_LIBADD = modules/blinds/libblinds.la modules/compose/libcompose.la modules/drizzle/libdrizzle.la modules/flui2d/libflui2d.la modules/julia/libjulia.la modules/meta2d/libmeta2d.la modules/montage/libmontage.la modules/pixbounce/libpixbounce.la modules/plasma/libplasma.la modules/plato/libplato.la modules/ray/libray.la modules/roto/libroto.la modules/rtv/librtv.la modules/snow/libsnow.la modules/sparkler/libsparkler.la modules/spiro/libspiro.la modules/stars/libstars.la modules/submit/libsubmit.la modules/swab/libswab.la modules/swarm/libswarm.la libs/grid/libgrid.la libs/puddle/libpuddle.la libs/ray/libray.la libs/sig/libsig.la libs/txt/libtxt.la libs/ascii/libascii.la libs/din/libdin.la
+libtil_la_LIBADD = modules/blinds/libblinds.la modules/checkers/libcheckers.la modules/compose/libcompose.la modules/drizzle/libdrizzle.la modules/flui2d/libflui2d.la modules/julia/libjulia.la modules/meta2d/libmeta2d.la modules/montage/libmontage.la modules/pixbounce/libpixbounce.la modules/plasma/libplasma.la modules/plato/libplato.la modules/ray/libray.la modules/roto/libroto.la modules/rtv/librtv.la modules/snow/libsnow.la modules/sparkler/libsparkler.la modules/spiro/libspiro.la modules/stars/libstars.la modules/submit/libsubmit.la modules/swab/libswab.la modules/swarm/libswarm.la libs/grid/libgrid.la libs/puddle/libpuddle.la libs/ray/libray.la libs/sig/libsig.la libs/txt/libtxt.la libs/ascii/libascii.la libs/din/libdin.la
if ENABLE_ROTOTILLER
bin_PROGRAMS = rototiller
diff --git a/src/modules/Makefile.am b/src/modules/Makefile.am
index c791bc9..92a4145 100644
--- a/src/modules/Makefile.am
+++ b/src/modules/Makefile.am
@@ -1 +1 @@
-SUBDIRS = blinds compose drizzle flui2d julia meta2d montage pixbounce plasma plato ray roto rtv snow sparkler spiro stars submit swab swarm
+SUBDIRS = blinds checkers compose drizzle flui2d julia meta2d montage pixbounce plasma plato ray roto rtv snow sparkler spiro stars submit swab swarm
diff --git a/src/modules/checkers/Makefile.am b/src/modules/checkers/Makefile.am
new file mode 100644
index 0000000..817e88f
--- /dev/null
+++ b/src/modules/checkers/Makefile.am
@@ -0,0 +1,3 @@
+noinst_LTLIBRARIES = libcheckers.la
+libcheckers_la_SOURCES = checkers.c
+libcheckers_la_CPPFLAGS = -I@top_srcdir@/src
diff --git a/src/modules/checkers/checkers.c b/src/modules/checkers/checkers.c
new file mode 100644
index 0000000..a88f17c
--- /dev/null
+++ b/src/modules/checkers/checkers.c
@@ -0,0 +1,302 @@
+/*
+ * Copyright (C) 2022 - Vito Caputo - <vcaputo@pengaru.com>
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "til.h"
+#include "til_fb.h"
+
+
+#define CHECKERS_DEFAULT_SIZE 32
+#define CHECKERS_DEFAULT_PATTERN CHECKERS_PATTERN_CHECKERED
+#define CHECKERS_DEFAULT_DYNAMICS CHECKERS_DYNAMICS_ODD
+#define CHECKERS_DEFAULT_DYNAMICS_RATE 1.0
+
+
+typedef enum checkers_pattern_t {
+ CHECKERS_PATTERN_CHECKERED,
+ CHECKERS_PATTERN_RANDOM,
+} checkers_pattern_t;
+
+typedef enum checkers_dynamics_t {
+ CHECKERS_DYNAMICS_ODD,
+ CHECKERS_DYNAMICS_EVEN,
+ CHECKERS_DYNAMICS_ALTERNATING,
+ CHECKERS_DYNAMICS_RANDOM,
+} checkers_dynamics_t;
+
+typedef struct checkers_setup_t {
+ unsigned size;
+ checkers_pattern_t pattern;
+ checkers_dynamics_t dynamics;
+ float rate;
+} checkers_setup_t;
+
+typedef struct checkers_context_t {
+ checkers_setup_t setup;
+} checkers_context_t;
+
+
+static checkers_setup_t checkers_default_setup = {
+ .size = CHECKERS_DEFAULT_SIZE,
+ .pattern = CHECKERS_DEFAULT_PATTERN,
+ .dynamics = CHECKERS_DEFAULT_DYNAMICS,
+ .rate = CHECKERS_DEFAULT_DYNAMICS_RATE,
+};
+
+
+static void * checkers_create_context(unsigned ticks, unsigned num_cpus, void *setup)
+{
+ checkers_context_t *ctxt;
+
+ if (!setup)
+ setup = &checkers_default_setup;
+
+ ctxt = calloc(1, sizeof(checkers_context_t));
+ if (!ctxt)
+ return NULL;
+
+ ctxt->setup = *(checkers_setup_t *)setup;
+
+ return ctxt;
+}
+
+
+static void checkers_destroy_context(void *context)
+{
+ free(context);
+}
+
+
+static int checkers_fragmenter(void *context, const til_fb_fragment_t *fragment, unsigned number, til_fb_fragment_t *res_fragment)
+{
+ checkers_context_t *ctxt = context;
+
+ return til_fb_fragment_tile_single(fragment, ctxt->setup.size, number, res_fragment);
+}
+
+
+static void checkers_prepare_frame(void *context, unsigned ticks, unsigned n_cpus, til_fb_fragment_t *fragment, til_fragmenter_t *res_fragmenter)
+{
+ *res_fragmenter = checkers_fragmenter;
+}
+
+
+static inline unsigned hash(unsigned x)
+{
+ x = ((x >> 16) ^ x) * 0x61C88647;
+ x = ((x >> 16) ^ x) * 0x61C88647;
+ x = ((x >> 16) ^ x) * 0x61C88647;
+ x = (x >> 16) ^ x;
+
+ return x;
+}
+
+
+static void checkers_render_fragment(void *context, unsigned ticks, unsigned cpu, til_fb_fragment_t *fragment)
+{
+ checkers_context_t *ctxt = context;
+ int state;
+
+ switch (ctxt->setup.pattern) {
+ case CHECKERS_PATTERN_CHECKERED: {
+ unsigned tiles_per_row;
+
+ 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;
+ break;
+ }
+ case CHECKERS_PATTERN_RANDOM:
+ state = hash(fragment->number * 0x61C88647) & 0x1;
+ break;
+ }
+
+ switch (ctxt->setup.dynamics) {
+ case CHECKERS_DYNAMICS_ODD:
+ break;
+ case CHECKERS_DYNAMICS_EVEN:
+ state = ~state & 0x1;
+ break;
+ case CHECKERS_DYNAMICS_ALTERNATING:
+ state ^= ((unsigned)((float)ticks * ctxt->setup.rate) & 0x1);
+ break;
+ case CHECKERS_DYNAMICS_RANDOM: /* note: the big multiply here is just to get up out of the low bits */
+ state &= hash(fragment->number * 0x61C88647 + (unsigned)((float)ticks * ctxt->setup.rate)) & 0x1;
+ break;
+ }
+
+ if (!state)
+ til_fb_fragment_clear(fragment);
+ else
+ til_fb_fragment_fill(fragment, 0xffffffff);
+}
+
+
+static int checkers_setup(const til_settings_t *settings, til_setting_t **res_setting, const til_setting_desc_t **res_desc, void **res_setup)
+{
+ const char *size;
+ const char *pattern;
+ const char *dynamics;
+ const char *dynamics_rate;
+ const char *size_values[] = {
+ "4",
+ "8",
+ "16",
+ "32",
+ "64",
+ "128",
+ NULL
+ };
+ const char *pattern_values[] = {
+ "checkered",
+ "random",
+ NULL
+ };
+ const char *dynamics_values[] = {
+ "odd",
+ "even",
+ "alternating",
+ "random",
+ NULL
+ };
+ const char *dynamics_rate_values[] = {
+ "1.0",
+ ".75",
+ ".5",
+ ".25",
+ ".1",
+ ".01",
+ ".001",
+ ".0001",
+ NULL
+ };
+ int r;
+
+ r = til_settings_get_and_describe_value(settings,
+ &(til_setting_desc_t){
+ .name = "Checker size",
+ .key = "size",
+ .regex = "\\.[0-9]+",
+ .preferred = TIL_SETTINGS_STR(CHECKERS_DEFAULT_SIZE),
+ .values = size_values,
+ .annotations = NULL
+ },
+ &size,
+ res_setting,
+ res_desc);
+ if (r)
+ return r;
+
+ r = til_settings_get_and_describe_value(settings,
+ &(til_setting_desc_t){
+ .name = "Checkers pattern",
+ .key = "pattern",
+ .preferred = pattern_values[0],
+ .values = pattern_values,
+ .annotations = NULL
+ },
+ &pattern,
+ res_setting,
+ res_desc);
+ if (r)
+ return r;
+
+ r = til_settings_get_and_describe_value(settings,
+ &(til_setting_desc_t){
+ .name = "Checkers dynamics",
+ .key = "dynamics",
+ .preferred = dynamics_values[0],
+ .values = dynamics_values,
+ .annotations = NULL
+ },
+ &dynamics,
+ res_setting,
+ res_desc);
+ if (r)
+ return r;
+
+ if (strcasecmp(dynamics, "odd") && strcasecmp(dynamics, "even")) {
+ r = til_settings_get_and_describe_value(settings,
+ &(til_setting_desc_t){
+ .name = "Checkers dynamics rate",
+ .key = "dynamics_rate",
+ .preferred = dynamics_rate_values[0],
+ .values = dynamics_rate_values,
+ .annotations = NULL
+ },
+ &dynamics_rate,
+ res_setting,
+ res_desc);
+ if (r)
+ return r;
+ }
+
+ if (res_setup) {
+ checkers_setup_t *setup;
+
+ setup = calloc(1, sizeof(*setup));
+ if (!setup)
+ return -ENOMEM;
+
+ sscanf(size, "%u", &setup->size);
+
+ if (!strcmp(pattern, "checkered"))
+ setup->pattern = CHECKERS_PATTERN_CHECKERED;
+ else if (!strcmp(pattern, "random"))
+ setup->pattern = CHECKERS_PATTERN_RANDOM;
+ else {
+ free(setup);
+ return -EINVAL;
+ }
+
+ if (!strcmp(dynamics, "odd"))
+ setup->dynamics = CHECKERS_DYNAMICS_ODD;
+ else if (!strcmp(dynamics, "even"))
+ setup->dynamics = CHECKERS_DYNAMICS_EVEN;
+ else if (!strcmp(dynamics, "alternating"))
+ setup->dynamics = CHECKERS_DYNAMICS_ALTERNATING;
+ else if (!strcmp(dynamics, "random"))
+ setup->dynamics = CHECKERS_DYNAMICS_RANDOM;
+ else {
+ free(setup);
+ return -EINVAL;
+ }
+
+ if (setup->dynamics != CHECKERS_DYNAMICS_ODD && setup->dynamics != CHECKERS_DYNAMICS_EVEN)
+ sscanf(dynamics_rate, "%f", &setup->rate);
+
+ *res_setup = setup;
+ }
+
+ return 0;
+}
+
+
+til_module_t checkers_module = {
+ .create_context = checkers_create_context,
+ .destroy_context = checkers_destroy_context,
+ .prepare_frame = checkers_prepare_frame,
+ .render_fragment = checkers_render_fragment,
+ .name = "checkers",
+ .description = "Checker-patterned overlay (threaded)",
+ .author = "Vito Caputo <vcaputo@pengaru.com>",
+ .setup = checkers_setup,
+};
© All Rights Reserved