diff options
author | Vito Caputo <vcaputo@pengaru.com> | 2025-02-03 00:14:34 -0800 |
---|---|---|
committer | Vito Caputo <vcaputo@pengaru.com> | 2025-02-03 00:14:34 -0800 |
commit | fb5618f33eb964fc8106e5b3297a028538d48e58 (patch) | |
tree | 3474b7f6e3ca3d6e755adfecdbc66e0ee68bb37f /src | |
parent | fb5281288369191da3af8ee12d15fa1110d8f044 (diff) |
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
Diffstat (limited to 'src')
-rw-r--r-- | src/modules/mixer/mixer.c | 87 |
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: |