diff options
author | Vito Caputo <vcaputo@pengaru.com> | 2022-05-29 09:59:39 -0700 |
---|---|---|
committer | Vito Caputo <vcaputo@pengaru.com> | 2022-05-29 10:16:16 -0700 |
commit | 6d1d7f95529d826ea916ac80d236f5e8616daf64 (patch) | |
tree | 57ccc80e35ca5223b6b6ce6bf9daa476a03de58f /src/til.c | |
parent | cfe4e1196bb63824a3e56b84f5485a7c6cf04490 (diff) |
*: pivot to til_module_context_t
- modules now allocate their contexts using
til_module_context_new() instead of [cm]alloc().
- modules simply embed til_module_context_t at the start of their
respective private context structs, if they do anything with
contexts
- modules that do nothing with contexts (lack a create_context()
method), will now *always* get a til_module_context_t supplied
to their other methods regardless of their create_context()
presence. So even if you don't have a create_context(), your
prepare_frame() and/or render_fragment() methods can still
access seed and n_cpus from within the til_module_context_t
passed in as context, *always*.
- modules that *do* have a create_context() method, implying they
have their own private context type, will have to cast the
til_module_context_t supplied to the other methods to their
private context type. By embedding the til_module_context_t at
the *start* of their private context struct, a simple cast is
all that's needed. If it's placed somewhere else, more
annoying container_of() style macros are needed - this is
strongly discouraged, just put it at the start of struct.
- til_module_create_context() now takes n_cpus, which may be set
to 0 for automatically assigning the number of threads in its
place. Any non-zero value is treated as an explicit n_cpus,
primarily intended for setting it to 1 for single-threaded
contexts necessary when embedded within an already-threaded
composite module.
- modules like montage which open-coded a single-threaded render
are now using the same til_module_render_fragment() as
everything else, since til_module_create_context() is accepting
n_cpus.
- til_module_create_context() now produces a real type, not void
*, that is til_module_context_t *. All the other module
context functions now operate on this type, and since
til_module_context_t.module tracks the module this context
relates to, those functions no longer require both the module
and context be passed in. This is especially helpful for
compositing modules which do a lot of module context creation
and destruction; the module handle is now only needed to create
the contexts. Everything else operating on that context only
needs the single context pointer, not module+context pairs,
which was unnecessarily annoying.
- if your module's context can be destroyed with a simple free(),
without any deeper knowledge or freeing of nested pointers, you
can now simply omit destroy_context() altogether. When
destroy_context() is missing, til_module_context_free() will
automatically use libc's free() on the pointer returned from
your create_context() (or on the pointer that was automatically
created if you omitted create_context() too, for the
bare til_module_context_t that got created on your behalf
anyways).
For the most part, these changes don't affect module creation.
In some ways this eases module creation by making it more
convenient access seed and n_cpus if you had no further
requirement for a context struct.
In other ways it's slightly annoying to have to do type-casts
when you're working with your own context type, since before it
was all void* and didn't require casts when assigning to your
typed context variables.
The elimination for requiring a destroy_context() method in
simple free() of private context scenarios removes some
boilerplate in simple cases.
I think it's a wash for module writers, or maybe a slight win for
the simple cases.
Diffstat (limited to 'src/til.c')
-rw-r--r-- | src/til.c | 72 |
1 files changed, 42 insertions, 30 deletions
@@ -13,6 +13,7 @@ #include "til.h" #include "til_fb.h" +#include "til_module_context.h" #include "til_settings.h" #include "til_threads.h" #include "til_util.h" @@ -105,13 +106,13 @@ void til_shutdown(void) } -static void _blank_prepare_frame(void *context, unsigned ticks, unsigned n_cpus, til_fb_fragment_t *fragment, til_fragmenter_t *res_fragmenter) +static void _blank_prepare_frame(til_module_context_t *context, unsigned ticks, til_fb_fragment_t *fragment, til_fragmenter_t *res_fragmenter) { *res_fragmenter = til_fragmenter_slice_per_cpu; } -static void _blank_render_fragment(void *context, unsigned ticks, unsigned cpu, til_fb_fragment_t *fragment) +static void _blank_render_fragment(til_module_context_t *context, unsigned ticks, unsigned cpu, til_fb_fragment_t *fragment) { til_fb_fragment_clear(fragment); } @@ -167,22 +168,35 @@ void til_get_modules(const til_module_t ***res_modules, size_t *res_n_modules) } -static void module_render_fragment(const til_module_t *module, void *context, til_threads_t *threads, unsigned ticks, til_fb_fragment_t *fragment) +static void module_render_fragment(til_module_context_t *context, til_threads_t *threads, unsigned ticks, til_fb_fragment_t *fragment) { - assert(module); + const til_module_t *module; + + assert(context); + assert(context->module); assert(threads); assert(fragment); - if (module->prepare_frame) { + module = context->module; + + if (context->n_cpus > 1 && module->prepare_frame) { til_fragmenter_t fragmenter; - module->prepare_frame(context, ticks, til_threads_num_threads(threads), fragment, &fragmenter); + module->prepare_frame(context, ticks, fragment, &fragmenter); if (module->render_fragment) { til_threads_frame_submit(threads, fragment, fragmenter, module->render_fragment, context, ticks); til_threads_wait_idle(threads); } + } else if (module->prepare_frame) { + til_fragmenter_t fragmenter; + unsigned fragnum = 0; + til_fb_fragment_t frag; + module->prepare_frame(context, ticks, fragment, &fragmenter); + + while (fragmenter(context, fragment, fragnum++, &frag)) + module->render_fragment(context, ticks, 0, &frag); } else if (module->render_fragment) module->render_fragment(context, ticks, 0, fragment); @@ -196,45 +210,43 @@ static void module_render_fragment(const til_module_t *module, void *context, ti /* This is a public interface to the threaded module rendering intended for use by * modules that wish to get the output of other modules for their own use. */ -void til_module_render(const til_module_t *module, void *context, unsigned ticks, til_fb_fragment_t *fragment) +void til_module_render(til_module_context_t *context, unsigned ticks, til_fb_fragment_t *fragment) { - module_render_fragment(module, context, til_threads, ticks, fragment); + module_render_fragment(context, til_threads, ticks, fragment); } -int til_module_create_context(const til_module_t *module, unsigned seed, unsigned ticks, til_setup_t *setup, void **res_context) +/* if n_cpus == 0, it will be automatically set to n_threads. + * to explicitly set n_cpus, just pass the value. This is primarily intended for + * the purpose of explicitly constraining rendering parallelization to less than n_threads, + * if n_cpus is specified > n_threads it won't increase n_threads... + */ +int til_module_create_context(const til_module_t *module, unsigned seed, unsigned ticks, unsigned n_cpus, til_setup_t *setup, til_module_context_t **res_context) { - void *context; + til_module_context_t *context; assert(module); assert(res_context); + if (!n_cpus) + n_cpus = til_threads_num_threads(til_threads); + if (!module->create_context) - return 0; + context = til_module_context_new(sizeof(til_module_context_t), seed, n_cpus); + else + context = module->create_context(seed, ticks, n_cpus, setup); - context = module->create_context(seed, ticks, til_threads_num_threads(til_threads), setup); if (!context) return -ENOMEM; + context->module = module; + *res_context = context; return 0; } -void * til_module_destroy_context(const til_module_t *module, void *context) -{ - assert(module); - - if (!module->destroy_context) - return NULL; - - module->destroy_context(context); - - return NULL; -} - - /* select module if not yet selected, then setup the module. */ int til_module_setup(til_settings_t *settings, til_setting_t **res_setting, const til_setting_desc_t **res_desc, til_setup_t **res_setup) { @@ -336,15 +348,15 @@ int til_module_randomize_setup(const til_module_t *module, til_setup_t **res_set } -/* generic fragmenter using a horizontal slice per cpu according to n_cpus */ -int til_fragmenter_slice_per_cpu(void *context, unsigned n_cpus, const til_fb_fragment_t *fragment, unsigned number, til_fb_fragment_t *res_fragment) +/* generic fragmenter using a horizontal slice per cpu according to context->n_cpus */ +int til_fragmenter_slice_per_cpu(til_module_context_t *context, const til_fb_fragment_t *fragment, unsigned number, til_fb_fragment_t *res_fragment) { - return til_fb_fragment_slice_single(fragment, n_cpus, number, res_fragment); + return til_fb_fragment_slice_single(fragment, context->n_cpus, number, res_fragment); } -/* generic fragmenter using 64x64 tiles, ignores n_cpus */ -int til_fragmenter_tile64(void *context, unsigned n_cpus, const til_fb_fragment_t *fragment, unsigned number, til_fb_fragment_t *res_fragment) +/* generic fragmenter using 64x64 tiles */ +int til_fragmenter_tile64(til_module_context_t *context, const til_fb_fragment_t *fragment, unsigned number, til_fb_fragment_t *res_fragment) { return til_fb_fragment_tile_single(fragment, 64, number, res_fragment); } |