Age | Commit message (Collapse) | Author |
|
Preparatory commit for aspect ratio settings at the fb layer.
This slightly reworks how main::setup_video() integrates the
selected fb backend's setup_func to better resemble how the
module setup_funcs work now, with more clearly separated
settings-building and setup-baking/finalizing phases. Which
makes inserting the ratio setting in the middle of the front-end
and back-end setup_funcs fairly trivial.
Not a fan of all the casts, but there will probably be more
helpers introduced to take care of that and make
til_video_setup_t more of a first-class thing facilitating the fb
stuff.
|
|
If a caller wants to rely heavily on til_fb_fragment_copy() for
clipping, it'll be normal for situations like zero or negative
W/H of the clipped area. Those would just be zero copy
scenarios, so simply return instead of asserting.
|
|
Apparently no existing were really taking advantage of this
ability. The x,y,w,h parameters are also supposed to impart clip
bounds, should they be smaller than the union of the src and dest
fragments.
|
|
This is intended to perhaps be of use for threaded rendering that
don't actually produce pixels during their render phase, but
still need n_cpus fragments to dispatch the parallel work keying
off the fragment.number.
Such a renderer might then put its pixels on-screen serially @
finish_frame(), or maybe the rendering functions will get a
return value to trigger multi-pass rendering on the same tick.
|
|
til_fb is triple buffered, but when rendering lags behind the
queue is empty making present-to-delay intervals smaller than
when rendering is keeping up and the queue is kept full.
This returns the duration of the returned pages last
submit-to-present delay, effectively measuring how long a page
can expect to wait to be flipped to/presented currently.
A subsequent commit will apply this delay value to the ticks
supplied to rendering.
|
|
This makes it so til_fb_page_get() will return NULL when the fb
has been "halted". If til_fb_page_get() is already waiting for a
page to become available, it will be woken up by til_fb_halt().
Preparatory commit for eliminating the reliance on
pthread_cancel() to terminate rototiller_thread() on shutdown.
Cancellation is always a PITA, especially cross-platform, but in
general it's so easy to have subtle bugs when using it.
|
|
For meta-demo use cases like alphazed is experimenting with, it's
desirable to change the window title from "rototiller" to
"alphazed" or whatever if in windowed mode.
This adds a way to do that in the obvious fashion...
--title="alphazed" etc.
|
|
What this really should have is a general memset32()
implementation, but for now it's a small improvement at least for
clearing since that's known to be a 0-pixel case where memset()
is applicable.
memset() isn't usable for actual RGBA pixels since it operates
strictly on bytes. There's some hacks for using memmove() to get
closer where you store the first four bytes, then memove the
start of the buffer to the remaining, doubling the size of the
move each time for log(n) calls to memmove. Maybe that makes
sense as a stop-gap for the general case, it needs
implementing+benchmarking first.
This commit is dead simple though and an obvious little FPS gain
for clearing.
|
|
til_fb_fragment_get_pixel_clipped() was clipping to the frame
bounds, which are actually just a logical dimension for placing
and scaling fragments within a frame. drizzle in particular is
leaning on this clipped-get to prevent accessing outside of the
fragment's backing buffer. Let's just clip it to the fragment
bounds instead, see comment added for more information.
|
|
This was mostly done out of convenience at the expense of turning
the fragment struct into more of a junk drawer.
But properly cleaning up owned stream pipes on context destroy
makes the inappropriateness of being part of til_fb_fragment_t
glaringly apparent.
Now the stream is just a separate thing passed to context create,
with a reference kept in the context for use throughout. Cleanup
of the owned pipes on the stream supplied to context create is
automagic when the context gets destroyed.
Note that despite there being a stream in the module context, the
stream to use is still supplied to all the rendering family
functions (prepare/render/finish) and it's the passed-in stream
which should be used by these functions. This is done to support
the possibility of switching out the stream frame-to-frame, which
may be interesting. Imagine doing things like a latent stream
and a future stream and switching between them on the fly for
instance. If there's a sequencing composite module, it could
flip between multiple sets of tracks or jump around multiple
streams with the visuals immediately flipping accordingly.
This should fix the --print-pipes crashing issues caused by lack
of cleanup when contexts were removed (like rtv does so often).
|
|
This adds an optional stream member and type for introducing some
persistent potentially cross-fragment state bound to the logical
frame being rendered to by the fragment.
It's a preparatory commit for adding things like arbitrary
stream-bound state modules can create/read/modify for passing
non-pixel information between modules bound to the fragment's
frame that may vary frame to frame, but may also only be updated
occasionally within a stream while still being accessible by
every frame for the lifetime of the stream.
This may evolve to encompass the fragment's texture member,
turning the texture into just another arbitrary thingy tied to
the stream which modules/rendering primitives may lookup and make
use of if present.
This commit only adds the type and member though, no
implementation yet.
|
|
this introduces a style= setting with values:
style=mask simple alpha mask overlay
style=map displacement mapped overlay
I might add a lighting option for the style=map mode with a
moving light source or something like that, but it's already
pretty slow as-is.
This is mostly just for more testing of the snapshotting, but
there's some interesting compositions enabled like:
module=compose,layers=submit:moire:drizzle
or just moire:drizzle, when style=map happens.
|
|
It seems like it might be most ergonomic and convenient for
everything to just use til_fb_fragment_t and rely on ops.submit
to determine if the fragment is a page or not, and if it is how
to submit it.
This commit brings things into that state of the world, it feels
kind of gross at the til_fb_page_*() API. See the large comment
in til_fb.c added by this commit for more information.
I'm probably going to just run with this for now, it can always
get cleaned up later. What's important is to get the general
snapshotting concept and functionality in place so modules can
make use of it. There will always be things to cleanup in this
messy tangle of a program.
|
|
There's a need for the ability to efficiently snapshot fragments
via buffer swapping when possible, for modules that want to do
overlay effects which sample the input fragment at arbitrary
pixels other than the one being written to, while producing
output pixels.
Without first making a stable snapshot of the input fragment's
contents, you can't implement such algorithms because you destroy
the input fragment while writing the output pixels.
A simple solution would be to just allocate memory and copy the
input fragment's contents into the allocation, then sample the
copy while writing to the input (now output) fragment's memory.
But when the input fragment represents the entire framebuffer
page/window, it's technically practical to instead simply swap
out the input fragment for a fresh fragment acquired from the
framebuffer/window provider. Then just sample from the original
fragment while writing to the freshly acquired one now taking the
original's place.
Simple enough.
Except til_fb_fragment_t is also used to describe subfragments
within a larger buffer, and these can't be made discontiguous and
swapped out. For these fragments there's no escaping the need
for a copy to be made of the contents. So there needs to be a
way for the fragment itself to furnish an appropriate
snapshotting mechanism, and when what the cloning mechanism
returns can vary. Depending on the snapshotting mechanism's
implementation, there's also a need for the fragment to furnish
an appropriate free method. If the snapshot is an entire page
from the native video backend, the backend must free it. If it's
just libc heap-allocated memory, then a plain old free()
suffices. If for some reason the memory can't be freed, then a
NULL free() method would be appropriate to simply do nothing.
So this commit introduces such free() and snapshot() methods in
the form of a til_fb_fragment_ops_t struct. There's no
implementations or use of these as of yet, this is purely
preparatory.
In addition to free() and snapshot(), a submit() method has also
been introduced for submitting ready frames to be displayed. Not
all fragments may be submitted, only "root" fragments which
represent an entire page from the video backend. It's these
fragments which will have a non-NULL submit() method, which the
video backend will have initialized appropriately in returning
the page's root fragment. This is a preparatory change in
anticipation of removing the til_fb_page_t type altogether,
replacing it with a simple til_fb_fragment_t having the
ops.submit() method set.
|
|
Until now the fb init has been receiving a til_settings_t to
access its setup. Now that there's a til_setup_t for
representing the fully baked setup, let's bring the fb stuff
up to speed so their init() behaves more like
til_module_t.create_context() WRT settings/setup.
This involves some reworking of how settings are handled in
{drm,sdl}_fb.c but nothing majorly different.
The only real funcitonal change that happened in the course of
this work is I made it possible now to actually instruct SDL to
do a more legacy SDL_WINDOW_FULLSCREEN vs.
SDL_WINDOW_FULLSCREEN_DESKTOP where SDL will attempt to switch
the video mode.
This is triggered by specifying both a size=WxH and fullscreen=on
for video=sdl. Be careful though, I've observed some broken
display states when specifying goofy sizes, which look like Xorg
bugs.
|
|
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.
|
|
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.
|
|
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.
|
|
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()
|
|
This is a preparatory commit for cleaning up the existing sloppy
global-ish application of settings during the iterative _setup()
call sequences.
Due to how this has evolved from a very rudimentary thing
enjoying many assumptions about there ever only being a single
module instance being configured by the settings, there's a lot
of weirdness and inconsistency surrounding module setup WRT
changes being applied instantaneously to /all/ existing and
future context's renderings of a given module vs. requiring a new
context be created to realize changes.
This commit doesn't actually change any of that, but puts the
plumbing in place for the setup methods to allocate and
initialize a private struct encapsulating the parsed and
validated setup once the settings are complete. This opaque
setup pointer will then be provided to the associated
create_context() method as the setup pointer. Then the created
context can configure itself using the provided setup when
non-NULL, or simply use defaults when NULL.
A future commit will update the setup methods to allocate and
populate their respective setup structs, adding the structs as
needed, as well as updating their create_context() methods to
utilize those setups.
One consequence of these changes when fully realized will be that
every setting change will require a new context be created from
the changed settings for the change to be realized.
For settings appropriately manipulated at runtime the concept of
knobs was introduced but never finished. That will have to be
finished in the future to enable more immediate/interactive
changing of settings-like values appropriate for interactive
manipulation
|
|
Now that til_setting_t.desc is not only a thing, but a thing that
is intended to be refreshed regularly in the course of things
like GUI interactive settings construction, it's not really
appropriate to try even act like this these are const anymore.
|
|
The existing iterative *_setup() interface only described
settings not found, quietly accepting usable settings already
present in the til_settings_t.
This worked fine for the existing interactive text setup thing,
but it's especially problematic for providing a GUI setup
frontend.
This commit makes it so the *_setup() methods always describe
undescribed settings they recognize, leaving the setup frontend
loop calling into the *_setup() methods to both apply the
description validation if wanted and actually tie the description
to respective setting returned by the _setup() methods as being
related to the returned description.
A new helper called til_settings_get_and_describe_value() has
been introduced primarily for use of module setup methods to
simplify this nonsense, replacing the til_settings_get_value()
calls and surrounding logic, but retaining the til_setting_desc_t
definitions largely verbatim.
This also results in discarding of some ad-hoc
til_setting_desc_check() calls, now that there's a centralized
place where settings become "described" (setup_interactively in
the case of rototiller).
Now a GUI frontend (like glimmer) would just provide its own
setup_interactively() equivalent for constructing its widgets for
a given *_setup() method's chain of returned descs. Whereas in
the past this wasn't really feasible unless there was never going
to be pre-supplied settings.
I suspect the til_setting_desc_check() integration into
setup_interactively() needs more work, but I think this is good
enough for now and I'm out of spare time for the moment.
|
|
Largely mechanical rename of librototiller -> libtil, but
introducing a til_ prefix to all librototiller (now libtil)
functions and types where a rototiller prefix was absent.
This is just a step towards a more libized librototiller, and til
is just a nicer to type/read prefix than rototiller_.
|