From a59229c5513e73348c87bcfc5cc4b39a31012437 Mon Sep 17 00:00:00 2001 From: Vito Caputo Date: Thu, 28 Apr 2022 01:46:10 -0700 Subject: til_fb: introduce a fragment texture source Idea here is to provide texture sources for obtaining pixel colors at the til_fb_put_pixel/fill drawing API, making it possible for at least overlayable modules to serve as mask/stencil operators where their drawn areas are populated by the contents of another fragment produced dynamically, potentially by other modules altogether. This commit adds a texture=modulename option to the compose module for specifying if a texture should be used when compositing, excepting and defaulting to "none" for disabling texturing. A future commit should expand this compose option to accept a potential list of modules for composing the texture in the same way as the main layers= list functions. Something this all immediately makes clear is the need for a better settings syntax, probably in the form of all module setting specifiers optionally being followed by a squence of settings, with support for escaping to handle nested situations. --- src/modules/blinds/blinds.c | 14 ++++-- src/modules/compose/compose.c | 100 +++++++++++++++++++++++++++++++++++++++++- src/modules/montage/montage.c | 25 ++++++----- 3 files changed, 122 insertions(+), 17 deletions(-) (limited to 'src/modules') diff --git a/src/modules/blinds/blinds.c b/src/modules/blinds/blinds.c index b14997e..0a8342e 100644 --- a/src/modules/blinds/blinds.c +++ b/src/modules/blinds/blinds.c @@ -66,8 +66,11 @@ static inline void draw_blind_horizontal(til_fb_fragment_t *fragment, unsigned r unsigned row_height = fragment->frame_height / count; unsigned height = roundf(t * (float)row_height); - for (unsigned y = 0; y < height; y++) - memset(fragment->buf + ((row * row_height) + y ) * fragment->pitch, 0xff, fragment->width * 4); +/* XXX FIXME: use faster block style fill/copy if til_fb gets that */ + for (unsigned y = 0; y < height; y++) { + for (unsigned x = 0; x < fragment->width; x++) + til_fb_fragment_put_pixel_unchecked(fragment, fragment->x + x, fragment->y + y + row * row_height, 0xffffffff); + } } @@ -77,8 +80,11 @@ static inline void draw_blind_vertical(til_fb_fragment_t *fragment, unsigned col unsigned column_width = fragment->frame_width / count; unsigned width = roundf(t * (float)column_width); - for (unsigned y = 0; y < fragment->height; y++) - memset(fragment->buf + y * fragment->pitch + column * column_width, 0xff, width * 4); +/* XXX FIXME: use faster block style fill/copy if til_fb gets that */ + for (unsigned y = 0; y < fragment->height; y++) { + for (unsigned x = 0; x < width; x++) + til_fb_fragment_put_pixel_unchecked(fragment, fragment->x + x + column * column_width, fragment->y + y, 0xffffffff); + } } diff --git a/src/modules/compose/compose.c b/src/modules/compose/compose.c index d672bf0..a331b3f 100644 --- a/src/modules/compose/compose.c +++ b/src/modules/compose/compose.c @@ -33,12 +33,15 @@ typedef struct compose_layer_t { typedef struct compose_context_t { unsigned n_cpus; + til_fb_fragment_t texture_fb; + compose_layer_t texture; size_t n_layers; compose_layer_t layers[]; } compose_context_t; typedef struct compose_setup_t { til_setup_t til_setup; + char *texture; size_t n_layers; char *layers[]; } compose_setup_t; @@ -93,6 +96,16 @@ static void * compose_create_context(unsigned ticks, unsigned n_cpus, til_setup_ ctxt->n_layers++; } + if (((compose_setup_t *)setup)->texture) { + til_setup_t *texture_setup = NULL; + + ctxt->texture.module = til_lookup_module(((compose_setup_t *)setup)->texture); + (void) til_module_randomize_setup(ctxt->texture.module, &texture_setup, NULL); + + (void) til_module_create_context(ctxt->texture.module, ticks, texture_setup, &ctxt->texture.module_ctxt); + til_setup_free(texture_setup); + } + return ctxt; } @@ -103,6 +116,12 @@ static void compose_destroy_context(void *context) for (int i = 0; i < ctxt->n_layers; i++) til_module_destroy_context(ctxt->layers[i].module, ctxt->layers[i].module_ctxt); + + if (ctxt->texture.module) + til_module_destroy_context(ctxt->texture.module, ctxt->texture.module_ctxt); + + free(ctxt->texture_fb.buf); + free(context); } @@ -113,8 +132,38 @@ static void compose_prepare_frame(void *context, unsigned ticks, unsigned n_cpus til_fb_fragment_clear(fragment); - for (int i = 0; i < ctxt->n_layers; i++) - til_module_render(ctxt->layers[i].module, ctxt->layers[i].module_ctxt, ticks, fragment); + if (ctxt->texture.module) { + if (!ctxt->texture_fb.buf || + ctxt->texture_fb.frame_width != fragment->frame_width || + ctxt->texture_fb.frame_height != fragment->frame_height) { + + ctxt->texture_fb = (til_fb_fragment_t){ + .buf = realloc(ctxt->texture_fb.buf, fragment->frame_height * fragment->frame_width * sizeof(uint32_t)), + + .frame_width = fragment->frame_width, + .frame_height = fragment->frame_height, + .width = fragment->frame_width, + .height = fragment->frame_height, + .pitch = fragment->frame_width, + }; + } + + ctxt->texture_fb.cleared = 0; + til_module_render(ctxt->texture.module, ctxt->texture.module_ctxt, ticks, &ctxt->texture_fb); + + til_module_render(ctxt->layers[0].module, ctxt->layers[0].module_ctxt, ticks, fragment); + + for (size_t i = 1; i < ctxt->n_layers; i++) { + til_fb_fragment_t textured = *fragment; + + textured.texture = &ctxt->texture_fb; + + til_module_render(ctxt->layers[i].module, ctxt->layers[i].module_ctxt, ticks, &textured); + } + } else { + for (size_t i = 0; i < ctxt->n_layers; i++) + til_module_render(ctxt->layers[i].module, ctxt->layers[i].module_ctxt, ticks, fragment); + } } @@ -179,6 +228,21 @@ static char * compose_random_layers_setting(void) static int compose_setup(const til_settings_t *settings, til_setting_t **res_setting, const til_setting_desc_t **res_desc, til_setup_t **res_setup) { const char *layers; + const char *texture; + const char *texture_values[] = { + "none", + "blinds", + "checkers", + "drizzle", + "julia", + "plasma", + "roto", + "stars", + "submit", + "swab", + "voronoi", + NULL + }; int r; r = til_settings_get_and_describe_value(settings, @@ -195,6 +259,20 @@ static int compose_setup(const til_settings_t *settings, til_setting_t **res_set if (r) return r; + r = til_settings_get_and_describe_value(settings, + &(til_setting_desc_t){ + .name = "Module to use for source texture, \"none\" to disable", + .key = "texture", + .preferred = texture_values[0], + .annotations = NULL, + .values = texture_values, + }, + &texture, + res_setting, + res_desc); + if (r) + return r; + /* turn layers colon-separated list into a null-terminated array of strings */ if (res_setup) { compose_setup_t *setup; @@ -257,6 +335,24 @@ static int compose_setup(const til_settings_t *settings, til_setting_t **res_set setup = new; } while (layer = strtok(NULL, ":")); + if (strcasecmp(texture, "none")) { + const til_module_t *texture_module; + + texture_module = til_lookup_module(texture); + if (!texture_module) { + til_setup_free(&setup->til_setup); + + return -EINVAL; + } + + setup->texture = strdup(texture); + if (!setup->texture) { + til_setup_free(&setup->til_setup); + + return -ENOMEM; + } + } + *res_setup = &setup->til_setup; } diff --git a/src/modules/montage/montage.c b/src/modules/montage/montage.c index 8444616..65aabe6 100644 --- a/src/modules/montage/montage.c +++ b/src/modules/montage/montage.c @@ -141,17 +141,20 @@ static int montage_fragment_tile(const til_fb_fragment_t *fragment, unsigned til xoff = x * tile_width; yoff = y * tile_height; - res_fragment->buf = fragment->buf + (yoff * fragment->pitch) + xoff; - 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); - res_fragment->pitch = fragment->pitch; - res_fragment->number = number; - res_fragment->cleared = fragment->cleared; + *res_fragment = (til_fb_fragment_t){ + .texture = fragment->texture, + .buf = fragment->buf + (yoff * fragment->pitch) + xoff, + .x = 0, /* fragment is a new frame */ + .y = 0, /* fragment is a new frame */ + .width = MIN(fragment->width - xoff, tile_width), + .height = MIN(fragment->height - yoff, tile_height), + .frame_width = MIN(fragment->width - xoff, tile_width), /* fragment is a new frame */ + .frame_height = MIN(fragment->height - yoff, tile_height), /* fragment is a new frame */ + .stride = fragment->stride + (fragment->width - MIN(fragment->width - xoff, tile_width)), + .pitch = fragment->pitch, + .number = number, + .cleared = fragment->cleared, + }; return 1; } -- cgit v1.2.1