Age | Commit message (Collapse) | Author |
|
|
|
- clear padding when {letter,pillar}boxed
- limit costly rendering to shape size area when boxed
- fix <= inclusion tests in circle and rhombus: s/<=/</
|
|
I'm not sure why this was being done, it was probably just
vestigial from whatever I bootstrapped the compose module with
and never thought to remove it.
The first compose layer rendered will clear the frame if
necessary. By compose doing it ahead of time, it's performing
potentially unnecessary work clearing if the first layer is a
frame-filler style render where no clear is ever performed.
|
|
Just assume a fragment has been logically cleared after
til_module_render() has done all its potential steps.
I'm not certain this doesn't break some existing assumptions WRT
fragmented/threaded clears and their propagation out to the outer
frame.
But I've been operating under the assumption that this was
already happening in terms of an implicit setting of
til_fb_fragment_t.cleared after a module's render happened.
Except I don't see anything in the existing code or history
actually doing that, which is odd.
For modules that don't invoke til_fb_fragment_clear() explicitly
because they are frame-fillers (think submit, swab, ray, julia,
plasma, these are all full-frame renders that don't benefit from
pre-clearing), they weren't leaving fragment->cleared set,
despite having fully initialized the frame's contents.
We should be able to just assume after prepare/render/finish has
happened for a given module, the target fragment has been
cleared.
Commit 4e5286 had introduced somewhat complicated .cleared
maintenance and propagation for threaded renders, but when we
just treat all finished module renders into a given fragment as
logically clearing the fragment we can just skip all that.
|
|
This is a mostly mechanical change of using rand_r() in place of
rand(), using the provided seed as the seed state.
There's some outstanding rand()s outside of create_context()
which should probably get switched over, with the seed being
stowed in the context struct. I didn't bother going deeper on
this at the moment in the interests of getting to sleep soon.
|
|
n_cells is a size_t, use %zu
clang complained, gcc doesn't, huh
|
|
In the recent surge of ADD-style rtv+compose focused development,
a bunch of modules were changed to randomize initial states at
context_create() so they wouldn't be so repetitive.
But the way this was done in a way that made it impossible to
suppress the randomized initial state, which sometimes may be
desirable in compositions. Imagine for instance something like
the checkers module, rendering one module in the odd cells, and
another module into the even cells. Imagine if these modules are
actually the same, but if checkers used one seed for all the odd
cells and another seed for all the even cells. If the modules
used actually utilized the seed provided, checkers would be able
to differentiate the odd from even by seeding them differently
even when the modules are the same.
This commit is a step in that direction, but rototiller and all
the composite modules (rtv,compose,montage) are simply passing
rand() as the seeds. Also none of the modules have yet been
modified to actually make use of these seeds.
Subsequent commits will update modules to seed their
pseudo-randomized initial state from the seed value rather than
always calling things like rand() themselves.
|
|
Mostly for compositing purposes, here will be a corpus of 2D
shapes, parameterized/procedurally generated and able to rotate
and perhaps have other dynamics added.
What shapes are there presently I had started implementing in
checkers as "styles", before realizing they really should just be
a separate module checkers can call into.
Not terribly interesting by itself, but as blinds and checkers
demonstrated, these things deliver a lot of value in
compositional situations. They're creating the palette to draw
from.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
We don't actually want to produce indices 0-width and 0-height
|
|
|
|
There's more to cleanup in rtv destruction, but this is the major
one.
|
|
Found via -fsanitize=address, this is a quick and dirty way to
prevent the OOB access without adding more conditionals, just
prevent scaling the fragment dimensions to the full grid
dimensions.
This could be done better by reworking things a bit and putting
zero at the center of the grid with a -1..+1 mapping, so rounding
towards zero would land in the middle as opposed to off the
start, with the existing .5f offset.
But for now just fix the bug, nobody will notice the slight LCD
overscan-style difference of bilerp=on vs. off due to this way.
|
|
This was causing the snow module to scribble via montage, since
snow uses per-cpu rand seeds indexed using the cpu value.
I didn't dig in to see if this was a vestigial thing where
fragnum once was passed as a parameter (it's also in
til_fb_fragment_t.number, but probably wasn't always that way).
But it's now used as a cpu idx, but since they're the same type
nothing complained, they say programming is hard.
|
|
Also shortened the durations across the board, and defaulted snow
to "none".
With "compose" being another meta module, and the randomized
settings, this actually gives a more interesting grand tour of
everything possible.
|
|
Just adds TIL_FB_DRAW_FLAG_TEXTURABLE so callers can granularly
inhibit texturing if desired.
|
|
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.
|
|
Same as for roto and plasma...
|
|
As with roto, it's important to differentiate plasma instances
when layered... plus it's kind of boring to always start plasma
identically.
|
|
Just something quick and dirty to differentiate roto layers, plus
it's kind of boring having roto always start at the same state.
|
|
It's no longer necessary to specify both snow_duration=0 AND
snow_module=none to disable snow, just specify snow_module=none.
A future commit should really make describing the "snow_duration"
setting contingent on snow_module != "none".
|
|
rtv special-cased handling a nil module to mean clear the
fragment, and called this "none"
But it really makes more sense for rtv to treat "none" as not
doing anything at all for its snow_module - not even blanking.
And it would be nice to have a consistent way to express a blank
module throughout rototiller, so this introduces a concept of
built-in modules accessible only via explicit lookup by name
which don't get enumerated via til_get_modules(), as they're
inherently uninteresting more utility-oriented modules for use by
other modules.
For now it's only "blank" that constitutes the built-ins list,
but expanding this is only a matter of introducing more modules
there. Future commits will rework rtv to use "blank" in place of
its current "none", and rtv's "none" will be reworked to
represent no snow mechanism at all, obviating the need to specify
snow_duration=0,snow_module=none required today.
|
|
Just one case, modules/submit, was using 32x32 tiles and is now
using 64x64. I don't expect it to make any difference.
While here I fixed up the num_cpus/n_cpus naming inconsistencies,
normalizing on n_cpus.
|
|
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
|