Age | Commit message (Collapse) | Author |
|
Most of the threaded modules have settled down on two basic forms
of fragmenter function:
1. a slice per cpu, where tile-oriented locality isn't useful
2. ~64x64 tiles, in scenarios where screen-space locality helps
Now that n_cpus is wired up to the fragmenter, #1 can be
fulfilled without requiring a module-private context plumbing
n_cpus from create_context().
A future commit will replace some module-specific fragmenters by
returning one of these instead as res_fragmenter in their
prepare_frame(), wherever applicable.
|
|
Fragmenting is often dimensioned according to the number of cpus,
and by not supplying this to the fragmenter it was made rather
common for module contexts to plumb this themselves - in some
cases incorporating a context type/create/destroy rigamarole
for the n_cpus circuit alone.
So just plumb it in libtil, and the prepare_frame functions can
choose to ignore it if they have something more desirable onhand.
Future commits will remove a bunch of n_cpus from module contexts
in favor of this.
|
|
The code was deliberately showing a single frame of snow when
snow_duration=0, since the durations are integral seconds ther
was no way to have a sub 1-second snow otherwise.
snow_module=none just means cleared for the snow_duration, not no
snow mechanism whatsoever. So the combination of 0 duration and
"none" was still flashing a single blank frame.
With this commit the combination of "none" and 0 snow_duration
prevents even a single frame of blank snow from being rendered.
|
|
cosmetic indentation fixup
|
|
Mechanical rename to something less ambiguous in a world with
til_settings_t, til_setting_t, and til_setup_t etc.
|
|
This adds a voronoi diagram module, which when used as an overlay
produces a mosaic effect.
Some settings:
cells=N number of voronoi cells
randomize={on,off} randomizes the cell locations every frame
dirty={on,off} uses a faster sloppy/dithery-looking method
Some TODO items:
- use a more space efficient representation of the distance
buffer, maybe use uint16_t relative offsets into the cells
rather than pointers - capping their quantity to 64KiB
- anti-alias edges between cells
|
|
This just slows things down, and now that the code is mature
enough to never trigger these asserts just get rid of them.
|
|
short-circuit by directly returning bound when exceeded
|
|
dotgradient() is very hot and needs this result when indexing
din->grid[]. Since it doesn't change for a given din instance,
just cache the result @ din_new().
|
|
compute scaled x/y coordinates less often by reusing them
|
|
Quick FPS based comparisons shows this simple change gets a
nearly 10% FPS boost on this particular 4-core i7 laptop.
|
|
|
|
|
|
|
|
Originally it seemed sensible to make these units of bytes, for
flexibility reasons.
But it's advantageous for everything to be able to assume pixels
are always 4-byte/32-bit aligned. Having the stride/pitch be in
bytes of units made it theoretically possible to produce
unaligned rows of pixels, which would break that assumption.
I don't think anything was ever actually producing such things,
and I've added some asserts to the {sdl,drm}_fb.c page
acquisition code to go fatal on such pages.
This change required going through all the modules and get rid of
their uint32_t vs. void* dances and other such 1-byte vs. 4-byte
scaling arithmetic.
Code is simpler now, and probably faster in some cases. And now
allows future work to just assume things cna always occur 4-bytes
at a time without concern for unaligned accesses.
|
|
This braino wasn't actually showing itself in any output since it
was always being used to fill either 0xffffffff or 0x00000000.
But if an actual pixel having distinct RGB values were supplied,
it wouldn't have worked right as just the low char was being
written to the destination buffer's bytes.
Additionally I think the til_fb_fragment_t.{pitch,stride} members
should probably change to the number of pixels (uint32_t) vs.
bytes. The thinking initially was to facilitate describing
fragments having rows split up with arbitrary numbers of bytes.
Having a constraint of requiring the pixels always be 32-bit
aligned ensures dword-at-a-time optimized copies can always
succeed without something like SIGBUS occurring. When such a
constraint is respected, the pitch/stride will always be 32-bit
aligned so they should just describe numbers of pixels.
Except, one can imagine scenarios where writing bytes at a time
instead of uint32_t's at a time can produce interesting
color-staggerring effects, and introducing a deliberate offset in
the pitch/stride making it unaligned can be interesting.
I'm leaving it all alone for now, but there's already assumptions
being made about doing uint32_t-grained operations on the
fragment's buf. Even the til_fb_fragment_t.buf's type is a
uint32_t* already, and it forces us to use a void* or char*
version of the pointer to apply pitch/stride as in this commit.
|
|
Without gamma correction the linear colors don't really pop, this
helps tremendously.
The gamma factor is hard-coded at 1.4 currently but may make
sense as a runtime setting.
|
|
This is a first approximation at introducing colors to flui2d, the
emitter colors aren't really well tuned or anything yet.
|
|
Inspired by my little fomo match-four game PoC, this is a similar
style phased emitter grid layout producing some neat turbulent
interactions.
Introduces an emitters={figure8,clockgrid} setting, and when
clockgrid is used, a clockstep=[.05-.99] for the radians step
made from one grid cell's emitter to the next where 1=2PI.
|
|
|
|
During rtv runs we'd occasionally segfault in the unchecked line
drawing. This needs to be fixed, but for now just go slower.
|
|
@Ph1l tripped over this after installing just build-essential
|
|
This adds count=N and orientation={horizontal,vertical} settings.
Which was precipitated by the introduction of a vertical blinds
mode.
e.g.:
--module=blinds,count=32,orientation=vertical
or for a quick tour of the possibilities:
--module=rtv,channels=blinds,duration=1,context_duration=1,snow_duration=0
weeeee
|
|
It's getting crazy in here, this is fun:
--module=rtv,channels=compose,duration=1,snow_duration=0,context_duration=1
which will rejigger the commpose module w/randomized layers every second.
|
|
In the interests of facilitating randomized automagic layered
compositing, tell the world when you're overlay-appropriate.
|
|
For modules which are overlay-appropriate, they should indicate
it when initializing their respective til_module_t. If they
intend to participate in automagic compositing as overlays
anyways.
|
|
Just some fixups after a quick review
|
|
This should plug a bulk of the setup leaks. Some of the
free_funcs still need to be changed to bespoke ones in modules
that allocate nested things in their respective setup, so those
are still leaking the nested things which are usually just a
small strdup of some kind.
|
|
simple wrapper around til_setup_t.free()
|
|
This brings something resembling an actual type to the private
objects returrned in *res_setup. Internally libtil/rototiller
wants this to be a til_setup_t, and it's up to the private users
of what's returned in *res_setup to embed this appropriately and
either use container_of() or casting when simply embedded at the
start to go between til_setup_t and their private containing
struct.
Everywhere *res_setup was previously allocated using calloc() is
now using til_setup_new() with a free_func, which til_setup_new()
will initialize appropriately. There's still some remaining work
to do with the supplied free_func in some modules, where free()
isn't quite appropriate.
Setup freeing isn't actually being performed yet, but this sets
the foundation for that to happen in a subsequent commit that
cleans up the setup leaks.
Many modules use a static default setup for when no setup has
been provided. In those cases, the free_func would be NULL,
which til_setup_new() refuses to do. When setup freeing actually
starts happening, it'll simply skip freeing when
til_setup_t.free_func is NULL.
|
|
For use when setup functions allocate their private setup to
return in *res_setup.
They specify the size of their private setup, and supply the free
function to use. This may be libc's free() when it's a simple
setup struct, or a bespoke free function when deep/complex
freeing is required for cleanup.
It's expected that callers will be embedding til_setup_t at the
start of their private setup struct, and returning a pointer to
this in *res_setup which would be the same value as a pointer to
to their private setup struct.
|
|
Preparatory commit for providing a res_setup type to replace
void*.
The impetus for this isn't just pursuit of less void*, but
primarily implementing setup freeing by embedding this struct
into the private setup types.
An alternative method of adding setup freeing would have been to
introduce something like til_module_t.free_setup(). But that
would require having the til_module_t on hand, and the whole
setup machinery is more generalized than til_module_t anyways.
This way anything can simply embed the struct in their private
setup instance and return the pointer to that in *res_setup.
They should always be able to find their containing struct's
offset from the til_setup_t* they returned. Either by using
container_of(), or simply placing it at the start of the private
setup struct.
|
|
Randomize the setting of the layered modules like rtv does.
This needs to free the setup, similarly to the others, once
that facility is added.
|
|
Instead of always showing defaults, randomize the setup like rtv
does.
|
|
This makes the arg return optional by using a res_arg pointer,
instead returning -ENOMEM when it would have returned NULL on
allocation failures.
This also makes it possible to detect when no setup was
performed, by returning 0 in such a case. Now returns 1 when
setup occurs and res pointers populated.
|
|
This commit pulls the setup randomizer out of rtv into libtil
proper, so other modules may make use of it.
Other than adding an assert no functional changes occurred.
It may make sense to split this into two functions; one which
takes a til_module_t as-is, and a lower-level bare setup function
callback based function that doesn't know about til_module_t the
former would call into. That way generic setup randomization can
occur (the same setup machinery is used in video contexts for
example) without necessarily having a til_module_t on hand.
|
|
expose the checkers module to the rest of the world
|
|
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.
|
|
There's been a longstanding todo item in montage where it was
ignoring the fragmenter returned by a module's prepare_frame().
This commit continues with the single-threaded rendering of the
modules within their respective tiles, still ad-hoc open coded.
But now actually applies the fragmenter returned as if the
rendering were being threaded, since when a module returns a
fragmenter from its prepare_frame() it may strongly depend on
that fragmenting for its output.
|
|
This isn't super interesting but I might just start adding
simplistic overlay style modules for compositing/transition use.
|
|
Mechanical renaming of "zero" to "clear" throughout for this
context.
|
|
Just adding a convenience function targeting simple overlay use
cases where the fragmenter is exploited for producing patterns
and the renderer may wish to fill those fragments vs. zero them.
A future commit should also really rename til_fb_fragment_zero()
to til_fb_fragment_clear()
|
|
Currently when a threaded renderer performed
til_fb_fragment_zero() in render_fragment() vs. prepare_frame(),
the til_fb_fragment.zeroed maintenance would stay isolated to the
ephemeral fragment generated by the fragmenter.
With this commit, when all ephemeral fragments rendered in a
threaded fashion for a given frame returned a set .zeroed member,
the outer frame's .zeroed member gets set.
This should enable proper threaded zeroing of the frame in
render_fragment().
Note that since it's careful to actually count the number of
zeroed ephemeral subfragments and only propagates when that count
matches the number of subfragments rendered in the entire frame,
it's also supported to use til_fb_fragment_zero() conditionally
on just some fragments while not zeroing others and the entire
frame will not get its .zeroed member set. Imagine a renderer
which randomly zeroes out some fragments, while drawing into
others, this will be honored as a non-zeroed frame on the whole.
|
|
Oversight from when zeroed tracking was introduced in d9db26.
|
|
Just rely on til_init()'s srand() ensuring things are fresh.
|
|
A future commit will remove srand() calls from modules, relying
instead on this srand() in til_init().
As mentioned in the comment, if modules actually want
reproducible deterministic pseudo-random values they should use
rand_r() (or their own PRNG) where they can control the seed.
|
|
This was removed before, despite being left in the header by mistake.
Putting back for glimmer's sake.
|
|
Things have become sufficiently mature and featureful that
attempting to describe their usage seemed worthwhile.
There's still no cleanup of setups returned in *res_setup and
that should be both fixed and documented at some point. The
settings in general are still rather leaky as-is, even the
example in this document leaks. But it's relatively harmless for
now.
|
|
The til_settings_get_and_describe_value() helper (and the calling
setup methods in the modules) can be useful in independently
spitting out a baked setup instance from a fully resolved
til_settings_t which has already gone through the whole
rigamarole of getting populated and described.
Normally when this all happens in one place with the setup
instance then either immediately fed to create_context(), or
stowed somewhere for future use, it's not a problem to always
require the res_desc,res_setting parameters.
But especially in GUI scenarios (glimmer) the whole populate and
describe phase of til_settings_t can very easily be done in a
separate place from the convenient place to produce a setup out
of it. So when the caller /knows/ the setup is finished and a
subsequent call with the same til_settings_t would produce a
res_setup immediately, the caller should be able to omit
res_setting and res_desc as they're of no use now.
This is all kind of crufty, but it's nice to have all this
happening in a single setup method to help keep the res_setup
phase from diverging/becoming out of sync with the
populate+describe phase. Will live with it for now. Frontends
get written far less than modules, so the API cruft from the
frontend perspective is relatively benign. It's still relatively
sane and ergonomic from the module writer's perspective.
|
|
Now modules allocate and return an opaque setup pointer in
res_setup when they implement a setup method.
Defaults are utilized when ${module}_create_context() receives a
NULL setup. The default setup used in this case should match the
defaults/preferred values emitted by the module's setup method.
But performing setup should always be optional, so a NULL setup
provided to create_context() is to be expected.
No cleanup of these setup instances is currently performed, so
it's a small memory leak for now. Since these are opaque and may
contain nested references to other allocations, simply using
free() somewhere in the frontend is insufficient. There will
probably need to be something like a til_module_t.setup_free()
method added in the future which modules may assign libc's free()
to when appropriate, or their own more elaborate version.
Lifecycle for the settings is very simple; the setup method
returns an instance, the caller is expected to free it when no
longer needed (once free is implemented). The create_context
consumer of a given setup must make its own copy of the settings
if necessary, and may not keep a reference - it must assume the
setup will be freed immediately after create_context() returns.
This enables the ability to reuse a setup instance across
multiple create_context() calls if desired, one can imagine
something like running the same module with the same settings
multiple times across multiple displays for instance. If the
module has significant entropy the output will differ despite
being configured identically...
With this commit one may change settings for any of the modules
*while* the modules are actively rendering a given context, and
the settings should *not* be visible. They should only affect
the context they're supplied to.
|