summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVito Caputo <vcaputo@pengaru.com>2025-02-03 00:14:34 -0800
committerVito Caputo <vcaputo@pengaru.com>2025-02-03 00:14:34 -0800
commitfb5618f33eb964fc8106e5b3297a028538d48e58 (patch)
tree3474b7f6e3ca3d6e755adfecdbc66e0ee68bb37f
parentfb5281288369191da3af8ee12d15fa1110d8f044 (diff)
modules/mixer: introduce style=dissolveHEADmaster
This is an oldskool "dissolve" effect, with configurable stability - stability=stable: the OG dissolve where coverage unveils continuously stability=unstable: a randomized variant more resembling snow/noise
-rw-r--r--src/modules/mixer/mixer.c87
1 files changed, 86 insertions, 1 deletions
diff --git a/src/modules/mixer/mixer.c b/src/modules/mixer/mixer.c
index 3012f1e..0a3509c 100644
--- a/src/modules/mixer/mixer.c
+++ b/src/modules/mixer/mixer.c
@@ -28,6 +28,7 @@ typedef enum mixer_style_t {
MIXER_STYLE_INTERLACE,
MIXER_STYLE_PAINTROLLER,
MIXER_STYLE_SINE,
+ MIXER_STYLE_DISSOLVE,
} mixer_style_t;
typedef enum mixer_orientation_t {
@@ -45,6 +46,11 @@ typedef enum mixer_bottom_t {
MIXER_BOTTOM_B,
} mixer_bottom_t;
+typedef enum mixer_stability_t {
+ MIXER_STABILITY_UNSTABLE,
+ MIXER_STABILITY_STABLE,
+} mixer_stability_t;
+
typedef struct mixer_input_t {
til_module_context_t *module_ctxt;
/* XXX: it's expected that inputs will get more settable attributes to stick in here */
@@ -85,6 +91,7 @@ typedef struct mixer_setup_t {
mixer_orientation_t orientation;
mixer_tee_t tee;
mixer_bottom_t bottom;
+ mixer_stability_t stability;
unsigned n_passes;
} mixer_setup_t;
@@ -93,6 +100,7 @@ typedef struct mixer_setup_t {
#define MIXER_DEFAULT_ORIENTATION MIXER_ORIENTATION_VERTICAL
#define MIXER_DEFAULT_BOTTOM MIXER_BOTTOM_A
#define MIXER_DEFAULT_TEE MIXER_TEE_NORMAL
+#define MIXER_DEFAULT_STABILITY MIXER_STABILITY_STABLE
static void mixer_update_taps(mixer_context_t *ctxt, til_stream_t *stream, unsigned ticks)
{
@@ -186,6 +194,8 @@ static void mixer_prepare_frame(til_module_context_t *context, til_stream_t *str
break;
case MIXER_STYLE_INTERLACE:
+ /* fallthrough */
+ case MIXER_STYLE_DISSOLVE:
for (int i = 0; i < context->n_cpus; i++)
ctxt->seeds[i].state = rand_r(&context->seed);
/* fallthrough */
@@ -491,6 +501,50 @@ static void mixer_render_fragment(til_module_context_t *context, til_stream_t *s
break;
}
+ /* dissolve is like a static/noise transition, except stable for a given context */
+ case MIXER_STYLE_DISSOLVE: {
+ til_fb_fragment_t *snapshot_b;
+ float T = mixer_get_T(ctxt);
+
+ if (T <= 0.001f || T >= .999f)
+ break;
+
+ assert(ctxt->snapshots[1]);
+
+ /* to make the dissolve "stable" we deterministically set the random seed for
+ * a given fragment.
+ */
+ switch (((mixer_setup_t *)context->setup)->stability) {
+ case MIXER_STABILITY_UNSTABLE:
+ ctxt->seeds[cpu].state = rand_r(&(unsigned){context->seed + fragment->number});
+ break;
+ case MIXER_STABILITY_STABLE:
+ ctxt->seeds[cpu].state = rand_r(&(unsigned){fragment->number});
+ break;
+ default:
+ assert(0);
+ }
+
+ snapshot_b = ctxt->snapshots[1];
+
+ for (unsigned y = 0; y < fragment->height; y++) {
+ int ycoord = fragment->y + y;
+
+ for (unsigned x = 0; x < fragment->width; x++) {
+ int xcoord = fragment->x + x;
+ uint32_t pixel;
+
+ if (randf(&ctxt->seeds[cpu].state) >= T)
+ continue;
+
+ pixel = til_fb_fragment_get_pixel_unchecked(snapshot_b, xcoord, ycoord);
+ til_fb_fragment_put_pixel_unchecked(fragment, 0, xcoord, ycoord, pixel);
+ }
+ }
+ break;
+ }
+
+
default:
assert(0);
}
@@ -582,6 +636,7 @@ static int mixer_setup(const til_settings_t *settings, til_setting_t **res_setti
"interlace",
"paintroller",
"sine",
+ "dissolve",
NULL
};
const char *passes_values[] = {
@@ -611,11 +666,17 @@ static int mixer_setup(const til_settings_t *settings, til_setting_t **res_setti
"inverted",
NULL
};
+ const char *stability_values[] = {
+ "unstable",
+ "stable",
+ NULL
+ };
til_setting_t *style;
til_setting_t *passes;
til_setting_t *orientation;
til_setting_t *bottom;
til_setting_t *tee;
+ til_setting_t *stability;
const til_settings_t *inputs_settings[2];
til_setting_t *inputs[2];
int r;
@@ -655,7 +716,8 @@ static int mixer_setup(const til_settings_t *settings, til_setting_t **res_setti
*/
if (!strcasecmp(style->value, style_values[MIXER_STYLE_INTERLACE]) ||
!strcasecmp(style->value, style_values[MIXER_STYLE_PAINTROLLER]) ||
- !strcasecmp(style->value, style_values[MIXER_STYLE_SINE])) {
+ !strcasecmp(style->value, style_values[MIXER_STYLE_SINE]) ||
+ !strcasecmp(style->value, style_values[MIXER_STYLE_DISSOLVE])) {
r = til_settings_get_and_describe_setting(settings,
&(til_setting_spec_t){
@@ -698,6 +760,20 @@ static int mixer_setup(const til_settings_t *settings, til_setting_t **res_setti
res_desc);
if (r)
return r;
+
+ } else if (!strcasecmp(style->value, style_values[MIXER_STYLE_DISSOLVE])) {
+ r = til_settings_get_and_describe_setting(settings,
+ &(til_setting_spec_t){
+ .name = "Dissolve stability",
+ .key = "stability",
+ .values = stability_values,
+ .preferred = stability_values[MIXER_DEFAULT_STABILITY],
+ },
+ &stability,
+ res_setting,
+ res_desc);
+ if (r)
+ return r;
}
for (int i = 0; i < 2; i++) {
@@ -758,9 +834,18 @@ static int mixer_setup(const til_settings_t *settings, til_setting_t **res_setti
case MIXER_STYLE_INTERLACE:
/* fallthrough */
case MIXER_STYLE_SINE:
+ /* fallthrough */
+ case MIXER_STYLE_DISSOLVE:
r = til_value_to_pos(bottom_values, bottom->value, (unsigned *)&setup->bottom);
if (r < 0)
return til_setup_free_with_failed_setting_ret_err(&setup->til_setup, bottom, res_setting, -EINVAL);
+
+ if (setup->style == MIXER_STYLE_DISSOLVE) {
+ /* TODO: stability should likely apply to interlace too */
+ r = til_value_to_pos(stability_values, stability->value, (unsigned *)&setup->stability);
+ if (r < 0)
+ return til_setup_free_with_failed_setting_ret_err(&setup->til_setup, stability, res_setting, -EINVAL);
+ }
break;
default:
© All Rights Reserved