summaryrefslogtreecommitdiff
path: root/src/til_stream.c
AgeCommit message (Collapse)Author
2023-11-18til_stream: introduce "pre" module contexts on streamVito Caputo
This adds an api for maintaining a list of pre-render module contexts on-stream which will be rendered via til_stream_render() before rendering hte main module context on the stream that's been set via til_stream_set_module_context(). til_stream_add_pre_module_context() til_stream_del_pre_module_context() are the new functions, no references are taken for now (but comments note the possibility of adding that) This is just a preparatory commit, no real functional difference.
2023-11-18til_stream: drop til_stream_start_frame()Vito Caputo
til_stream_render() bumps the frame counter, so there's no more need for a discrete frame start mechanism.
2023-11-18til_stream: add til_stream_render()Vito Caputo
This introduces a concept of a stream's module context, which is used to render the stream via til_stream_render(). The context is set using til_stream_set_module_context(), but at this time no reference is taken - it just puts the context into the stream for use by the render calls. The caller is responsible for ensuring it persist as long as the stream uses it. This is a preparatory commit for implementing pre/post render module contexts that get hooked into a stream. The impetus for this is supporting background music via modules like playit, without requiring stuff like rkt scenes to always include the bgm context in the scene's module context heirarchy. Nothing is functionally different here, the commit only adds the new interfaces for setting the context and rendering via stream instead of til_module_render() of the context you'd now set on the stream.
2023-11-14til_stream,rkt,main: add stream audio controlVito Caputo
Until now everything interested in audio just used a plain getter on the stream to get at the context. But with how things work currently, audio is always left in a paused state until explicitly unpaused. This works fine with modules/rkt, which manages pause/unpause explicitly. When there's nothing like modules/rkt in charge though, the audio just sits stuck paused. Meaning if you do some simple thing like --module=playit, it won't ever get unpaused. With this commit, something like modules/rkt takes control of the stream's audio context, in a way that prevents anything else from taking control of the same context on the same stream. That enables having main try take control of the audio context after creating the module contexts, then in the rendering thread ensure the audio is unpaused if main is in control of the audio context and something's queueing audio frames. For now there's no mechanism for releasing control of the audio context. It doesn't seem appropriate to make this more elaborate than necessary. There's basically just two use cases WRT audio: 1. Something like rkt, which takes control once for the process and stays in control until process exit. 2. Something far simpler where nothing's taking control like rkt, and main just needs to get things unpaused when needed because something's generating audio frames.
2023-11-14til_stream: add til_audio_context_t to til_stream_tVito Caputo
Preliminary means of making the audio context available to modules.
2023-08-19til_stream: drop til_stream_pipe_set_owner()Vito Caputo
There are no users of this, it can come back if needed.
2023-08-19til_stream: the first tap per-frame should drive the pipeVito Caputo
In the case of clones there's multiple identical contexts at the same path, putting their taps on the same pipe. Since these clones likely exist for the purpose of parallel rendering, chaotically scheduled, it's arbitrary which of the clones will render first in a given frame. So it would just be a matter of luck if the first to render was also the driving tap established at context create time. Until the driving context rendered, the non-driving contexts would render potentially stale values from their taps, carried from the last frame. Then the driving tap's context would render, advancing all taps it drove, and it plus any subsequent renders sharing the pipe in the frame would have the new tapped values, producing randomly inconsistent results. You can easily cause this today with checkers::fill_module=plato, since plato has some taps for the orbit/spin rates, and checkers uses context clones for parallel fill_module= rendering. Note this is orthogonal to cases like modules/rkt, where hooks are used to steal ownership of the pipes when they're created. rkt also becomes the driver of the taps from its ctor hook, since it bridges Rocket data to the taps, and this commit does potentially interfere with that by introducing a per-frame competition to determine driver. But since rkt is the top-level rendering module when its in use, calling into the per-scene module contexts when appropriate, it's guaranteed to always win the race as long as it maintains its taps using Rocket-provided values before rendering the scene - which is the way it works today.
2023-08-19til_stream: set frame in til_stream_pipe_set_driving_tap()Vito Caputo
This needs the stream pulled in so the signature changed to accomodate that. Also modules/rkt was calling this conditionally which won't be compatible with the per-frame driver race model, so always call it to maintain the driving position every frame.
2023-08-19til_stream: track frame in til_stream_pipe_tVito Caputo
This is needed for determining which tap's first on a given pipe per-frame.
2023-08-18til_stream: introduce a per-stream frame counterVito Caputo
This adds til_stream_start_frame() which advances a per-stream counter. Subsequent commits will make use of this for implementing a pre-frame competition for pipe ownership.
2023-08-13til_stream: assert when gc leaks in til_stream_free()Vito Caputo
It's expected that all mondule contexts will have been cleaned up by the final gc in til_stream_free(). If the gc returns a non-zero skipped count, it suggests there's a program bug leaking registered contexts.
2023-08-13til_stream: return skipped count from til_stream_gc_module_contexts()Vito Caputo
Preparatory commit for making til_stream_free() assert on leaked module contexts.
2023-08-13til_stream: always assign n_module_contexts in registerVito Caputo
Leaving the larger n_module_contexts on reuse creates the potential for a NULL ptr dereference in places like gc which check the refcount of each countext in the set, without testing for NULL. Rather than making everything check for NULL, just shrink the count when it gets reused in a smaller case. This whole reuse thing is kind of a silly little optimization anyways, and will be revisited when cloning either happens or the sets become deprecated. For now just prevent creating situations that can crash.
2023-08-13til_stream: fix parent_path leak in til_stream_untap_owner()Vito Caputo
Plug a small leak
2023-08-13til_stream: gc module contexts on til_stream_free()Vito Caputo
Technically this was leaking contexts but it's only done on the road to process exit currently anyways.
2023-07-13til_stream: update tap ptr in til_stream_tap new pipe caseVito Caputo
The tap->ptr indirection must always be updated even when we're the driver on a fresh pipe created by us. This bug only triggers when the caller's tap was already on-stream, without being the driver, and the driving tap/context has since exited the stream, untapping itself which removed the associated pipes - even the ones it didn't own but was driving. In that scenario when pipe is created by the previously non-driving tap on its first update since the driver exited, its tap->ptr still points at the stale driver. This manifested as a UAF bug in that case. The fix is a simple matter of always updating tap->ptr to reflect the driving tap. This also fixes the real bug causing 468c78e3 to crash, such that the syncronous gc performed there shouldn't really be necessary to prevent crashing. It was the awkward overlapping existence of contexts at the same path which produced the triggering lifecycle pattern WRT driving taps at that path.
2023-07-12til_stream: loop gc passes until nothing gets freedVito Caputo
Due to how meta-modules reference other modules from within their context, they pin the related refcounts until their gc is performed. So repeat the gc passess until nothing gets freed, to gc those recursive references immediately. Fortunately this isn't intended to be done at perf-sensitive times...
2023-07-12til_stream: clarify c->n_contexts reuseVito Caputo
til_stream_register_module_contexts() reuses the container when c->n_contexts is sufficiently large, and deliberately leaves c->n_contexts as-is to potentially accomodate a larger set in the future. The excess was NULLified in prepping for reuse so it should be fine, just add a blurb about it so it doesn't look like an oversight.
2023-07-08til: measure til_module_render() durationsVito Caputo
This stows the duration (in ticks (which are ms for now)) of a given module context's most recent, as well as tracking the max, in til_module_context_t. For now it's also added to --print-module-contexts output, but this is still rather primitive and nearly inscrutible in practice... that output is a flickery and unsorted mess during playback. But this is just a start. Ticks may need to move up to microseconds if it'll also be the units for measuring timings. Right now things are slow enough that the low-hanging fruit stand out as multiple if not dozens of milliseconds so it's still useful for now.
2023-06-15til_stream: introduce til_stream_{end,active}()Vito Caputo
rkt needs a way to signal the end of a sequence, this will probably get more work in the future but something simple is fine for now
2023-06-13*: smattering of random small fixes to silence -WallVito Caputo
I thought the build was already using -Wall but that seems to not be the case, maybe got lost somewhere along the line or messed up in configure.ac After forcing a build with -Wall -Werror, these showed up. Fixed up in the obvious way, nothing too scary.
2023-06-12til_stream: introduce on-stream registered contextsVito Caputo
In order for modules like rkt to be able to do integrated transitions, there must be a way for discovering existing module contexts by path and using them for rendering in new compositions. This is a first stab at something along those lines. The whole multiple contexts at the same path pattern has been partially handled in this implementation, but I think it will just be going away and checkers::fill_module refactored to not do that.
2023-06-08til_stream: name pipe-oriented stream api as suchVito Caputo
When all the stream encapsulated were pipes/taps, naming was less precise. With module contexts in the process of being registered in the stream, there's a need to distinguish things more. This is a largely mechanical naming change...
2023-06-06til_stream: drop redundant til_stream_pipe_t typedefVito Caputo
This is already in the header
2023-06-05til_stream: s/buckets/pipe_buckets/Vito Caputo
Mechanical rename in preparation for context buckets for hashing all contexts existing on a stream.
2023-01-21til_stream: introduce til_stream_hooks_t et alVito Caputo
There needs to be a way for a meta module like rocket to take ownership of pipes immediately upon instantiation. Since the pipes are created on demand as they become tapped by the modules using htem, the simplest way to do this is to register some callbacks with the ability to intercept the pipe creation in terms of ownership and driving tap control etc. This commit forms a minimal implementation of that, with the ability to have a single intercepter hooked into a given stream. It's a first-come-first-served situation, but that should suffice for now since the rocket meta module would be the entrypoint for such constructions. It then calls into another module to produce on the stream, after it'll already have its hooks registered. There might be a need for stacking hooks to let multiple modules control pipes. GNU Rocket for instance only deals with floats/doubles, and doesn't make it particularly easy to work on higher order concepts like say orbiting a vector around a point spatially. It might make sense to allow compositing of editors where there's rocket controlling the simple floats, and another doing dimensional/spatial stuff, with separate stacked meta modules accomodating those editors. But that's putting the cart before the horse, let's do the stupid simple thing for now and see what this is like.
2023-01-21til_stream: teardown pipes when the driving_tap's owner matchesVito Caputo
The driving tap's owner and pipe's owner are decoupled. When tearing down an owner from a stream, any pipes its taps are driving should also just go away. Otherwise its taps could linger on pipes it doesn't own, which would be a UAF bug. If the pipe is still needed, it'll just get recreated by another tap. So there's a small perf hit, but this shouldn't be a continuos kind of occurrence.
2023-01-21til_stream: minor cosmetic naming/comments fixesVito Caputo
Some clarifications
2023-01-21til_stream: add til_stream_pipe_set_driving_tap()Vito Caputo
2023-01-21til_{tap,stream}: introduce til_tap_t.inactiveVito Caputo
When a driving tap becomes inactive, til_stream_tap() should be able to notice and replace the driver. An example driving tap becoming inactive would be a GNU Rocket track that once had keys in it, but then had them all deleted. This should set the inactive flag so the tap's automation can take over. This gives the user at the Rocket editor the ability to both take over from the tap automation and surrender control back, by populating vs. emptying the respective track.
2023-01-21til_stream: introduce stream iterator et alVito Caputo
In order to implement something like a rocket module there needs to be a way to iterate the pipes in the stream, and take owernship of them when not already owned by rocket. The way rocket's API works is you lookup tracks by name at runtime. The rocket module will be a meta module that calls into another module for rendering, arbitrarily configured via a rocket setting a la checkers::fill_module. So it won't be until the underlying modules do some rendering that their taps get their respective pipes established in the stream. Then the rocket module can look at all the pipes and for any it doesn't own yet, it can get the tracks for those names and take ownership while stowing the track handle in owner_foo for the pipe. While iterating all the pipes, the pipes already owned will have the tracks readily available which can produce the values to stick in the tap. Something like that anyways, the til_stream_t api changes in this commit are all preparatory for a rocket module.
2023-01-21til_stream: comment fix, and assert/error on mismatchVito Caputo
Just clarify some verbiage, and actually assert type+n_elems match. Note mismatch also fallsthrough to an -EINVAL just in case asserts() have been compiled out (-DNDEBUG).
2023-01-21til_stream: add a second void* to til_stream_pipe_tVito Caputo
It seems likely that pipe owners will need not only a way to differentiate themselves via the owner pointer, but also somewhere to register a pipe-specific reference. There probably needs to be a result pointer added for storing the owner_foo when the owner taps, so the owner can make use of it.
2023-01-11til_{stream,tap}: add GPL headersVito Caputo
Just some banal paperwork...
2023-01-11til_stream: first stab at implementing til_stream_tVito Caputo
Until now there's just been a forward declared type for til_fb_fragment_t.stream's type, and it's been completely unused. The purpose of the stream is to provide a continous inter-frame object where information can be stored pertaining to the stream of frames. Right now, that information is limited to emergent "pipes" formed by using taps against a given stream. Taps at new paths in the stream become added as pipes for those paths, with the responsible tap hooked in as the driving tap. Taps at existing paths become diverted to the driving taps, enabling potential for external drivers for tapped variables. This commit only adds the implementation, nothing is actually using it yet.
© All Rights Reserved