summaryrefslogtreecommitdiff
path: root/src
AgeCommit message (Collapse)Author
2023-03-13modules/rocket: %s/rocket/rkt/gVito Caputo
It's annoying to have the til module called rocket, and the sync tracker protocol/library called rocket, so let's at least differentiate it in code/comments/textual discussion. Plus this results in shorter module context paths i.e.: /rkt:scene /rkt/compose/drizzle:rain /rkt/compose/drizzle:viscosity /rkt/compose/plato:spin_rate /rkt/compose/plato:orbit_rate vs. /rocket:scene etc... These names are shown in the editor, and they'll tend to be long but let's at least get the root name down to three chars this way. A rename of the files and build system update will come in a subsequent commit
2023-02-23libs/rocket: bump submodule and enable TCP_NODELAYVito Caputo
Upstream merged my TCP_NODELAY PR, so let's get it in rototiller. Note I'm blindly setting USE_NODELAY now, but it might actually break the build for win32 - still need to test that.
2023-02-06til: get rid of the partial knobs implementationVito Caputo
With taps more or less fully implemented, it seems appropriate to get rid of the stubbed out knobs for now. Taps don't express the same things about range and usage knobs aspired towards, but they don't preclude adding such things either. But it seems clear that the way knobs were stubbed won't be complementing taps as things stand currently to add those aspects.
2023-02-06modules/meta2d: add some taps for controlling visible bandVito Caputo
There should probably be others for the ball radiuses, and colors
2023-01-22modules/flui2d: add taps for viscosity,diffusion,decayVito Caputo
this needs more work to really be useful... clockstep should be tapped, there should probably be a T tap to control the emitters' cycle im doubtful how useful this module will generally be though. It really needs interactions with other things, like fluid going around pixbounce
2023-01-22modules/drizzle: add taps for viscosity,rainfallVito Caputo
Just some obvious taps... Note the actual usable range for viscosity is quite small, like no greater than .05 really works. There still needs to be some way to describe bounds on the taps, that or normalizing things to always be 0-1 or -1..+1 kind of thing, and expecting the modules or the tap api to map those to the sane ranges. Just leave everything raw for now, wiring up the taps at least opens up experimentation and getting a feel for what makes most sense.
2023-01-22modules/blinds: add taps for T,step,countVito Caputo
Part of me wants to give the blinds arbitrary angle instead of the vert/horiz options. But part of the beauty of blinds is the jaggy-free aliasing-free sharp edges by virtue of always being orthonormal using whole pixels. Maybe in the future there could be a orientation setting where you pick horiz/vert/angular. Then only when angular does it get a theta tap and use angled blinds with anti-aliased imperfect edges...
2023-01-21modules/rocket: implement GNU Rocket integrationVito Caputo
This adds a rudimentary but functional rocket module for sequencing "tapped" variables in rototiller modules according to a timeline via GNU Rocket editors. Currently this only supports a single seq_module= as a setting which will be used for rendering. Any tapped variables present in the nested modules under seq_module will be available for sequencing, and should automatically appear in a connected rocket editor. If you specify connect=off then rocket sync tracks will be read from the filesystem if present. It's a bit clumsy as-is due to how the GNU Rocket library handles this currently. There's a "base" label concept for the virtual rocket device, and the tracks are intended to be files in a directory named using that base= setting. The way you create those track files is by triggering a remote export from the editor while connected. The location of the directory is relative to the cwd of the rototiller process, and you can't specify absolute paths as the base= setting to be explicit about where things go. The setting isn't really a path, as that's not what the library wants it to be. It's an area in need of improvement. In any case, as long as you start with the same base= setting, from the same CWD, as when you did the remote export, you can re-run with connect=off and the exported tracks will be used automagically and things should replay without the editor connected. If you start with connect=on, which is the default, you need to have the editor already running. Otherwise the rocket module will fail @ context create, and you'll get a confusing error about being unable to allocate memory. This is just for now, the context create needs to start returning an errno instead of just the context pointer so the error messages can be more informative now that context create may be doing complicated things like connecting to sockets. Another thing to improve is probably having the module just reconnect periodically if connect=on but it failed @ context create. It could just start anyways and not fail the context create at all there, and just start working once you get the editor online. That'd be a better user experience. This is a good first step regardless...
2023-01-21modules/rocket: preliminary rocket moduleVito Caputo
This just stubs out a rocket meta module that renders with another module. Future commits will integrate GNU Rocket here. When recursive settings formally lands you'll be able to nest as much settings content as necessary for the underlying module used, as part of the rocket settings. That should enable describing stuff like complex compose scenarios for rocket to sequence.
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-21til_tap: introduce til_tap_t.ownerVito Caputo
We need a way to identify owners of taps when cleaning up their containing contexts, especially once they're hanging off streams.
2023-01-20til: pass module to .context_create()/til_module_context_new()Vito Caputo
Let's make it so til_module_context_t as returned from til_module_context_new() can immediately be freed via til_module_context_free(). Previously it was only after the context propagated out to til_module_context_create() that it could be freed that way, as that was where the module member was being assigned. With this change, and wiring up the module pointer into til_module_t.create_context() as well for convenient providing to til_module_context_new(), til_module_t.create_context() error paths can easily cleanup via `return til_module_context_free()` But this does require the til_module_t.destroy_context() be able to safely handle partially constructed contexts, since the mid-create failure freeing won't necessarily have all the members initialized. There will probably be some NULL derefs to fix up, but at least the contexts are zero-initialized @ new.
2023-01-20libs/rocket: add GNU Rocket submoduleVito Caputo
Preparatory commit for experimenting with a GNU Rocket integration for controlling the stream pipes on a timeline. Since rocket doesn't support things like arbitrary strings, it's not a natural fit for rototiller where the obvious thing would be to describe scene compositions as settings strings as if you were invoking rototiller. But a temporary hack might be to just tell a rocket module up-front all the scenes as settings strings you provide to its setup. Those get assigned numeric identifiers, then rocket tracks can control when they come on/off numerically. It just requires describing all the scenes up front rather than in the pattern editor which is less than ideal. Being able to experiment with this half-ass solution may prove useful anyways, and shouldn't be too much work.
2023-01-17til_fb: don't dereference NULL fragment opsVito Caputo
For strictly logical fragments (e.g. tiled fragmenters) there won't be any ops, and that's even documented in the comments. But the snapshot and reclaim functoins were assuming the ops would be non-NULL. Snapshot in particular trips on this assumption when a module snapshots a subfragment, like drizzle in montage. I'm surprised I haven't encountered this crash before...
2023-01-12modules/compose: fix segfault introduced by 83e41dVito Caputo
It was assumed (n_modules - n_overlayable) would give the number of non-overlayable modules appropriate as base layers. But with the skipping of hermetic and experimental modules the base_idx could be out of reach leaving layers NULL after the loop, which will segfault later when strlen() assumes it's non-NULL. This commit does the simple thing and also counts the unusable modules to subtract from those eligible for base layers along with n_overlayable.
2023-01-11til_{stream,tap}: add GPL headersVito Caputo
Just some banal paperwork...
2023-01-11til: omit experimental modules from til_module_setup()Vito Caputo
Don't make experimental modules available to the regular/potentially-interactive setup routine. There should be a flag like --experimental to generally enable these.
2023-01-11modules/montage: omit experimental and hermetic modulesVito Caputo
As with the other composite modules, if --experimental happens this will need adjustment to honor it. For now let's just prevent things from breaking when those modules start appearing.
2023-01-11modules/compose: omit experimental and hermetic modulesVito Caputo
This only omits the modules from the random layers Note the texture_values list is enumerated in compose_setup, so there's no corresponding change needed there. It might make sense to change that to a runtime-discovered list though, I think that was done in the pre-flags era.
2023-01-11modules/rtv: skip hermetic/experimental modules for "all"Vito Caputo
This allows explicit listing of such modules as channels, while protecting the automagic/defaults scenario. If there's a future --experimental flag or such added, then the TIL_MODULE_EXPERIMENTAL check will have to become conditional on it.
2023-01-11main: experimenting with ANSI codes for --print-pipesVito Caputo
This turns --print-pipes into a more top-like display. Redirect the FPS on stderr somewhere else to get less flickering e.g. 2>/dev/null pipes print to stdout.
2023-01-11til: intrdouce a couple new module flagsVito Caputo
TIL_MODULE_HERMETIC: There's likely to be some new modules that are more orchestration style components having external runtime dependencies. Think stuff like a sequencer talking to GNU Rocket, or something that plays back pattern data from external files. Those would need a GNU Rocket process to talk to somewhere, or input pattern file paths. So they shouldn't participate in stuff like random rtv shows unless they have some fallbacks for when the dependencies are unavailable. For pattern data it's realistic to include some builtin patterns to fallback on, but we're not there yet. So this flag when specified should opt out of things like rtv or checkers fill_module random selections. TIL_MODULE_EXPERIMENTAL: Theres no current way to have knowingly unstable/unfinished modules available in-tree for development/collaboration purposes without having them also make stuff like rtv unstable. Modules having this flag set should be excluded from random inclusion without a --experimental or some such runtime flag specified. This commit only assigns values and names for the flags, it doesn't implement anything.
2023-01-11* turn til_fb_fragment_t.stream into a discrete parameterVito Caputo
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).
2023-01-11main,til_args: employ the stream, add --print-pipesVito Caputo
This is a rudimentary integration of the new til_stream_t into rototiller. If the stream is going to continue living in til_fb_fragment_t, the fragmenters and other nested frame scenarios likely need to be updated to copy the stream through to make the pipes available to the nested renders. --print-pipes dumps the values found at the pipes' driver taps to stdout on every frame. Right now there's no way to externally write these values, but with --print-pipes you can already see where things are going and it's a nice visibility tool for tapped variables in modules. Only stars and plato tap variables presently, but that will improve.
2023-01-11fps: move FPS printing to stderrVito Caputo
With --print-pipes there will be a potential shitload of stuff getting printed out, and it'd be nice to easily distinguish that content from the FPS counter. Since stderr is normally less buffered than stdout (line buffered) not lose debugging information, just put the low-bandwidth periodic FPS print there instead. This leaves stdout for --print-pipes output which occurs every frame *and* may have a lot of content per print.
2023-01-11main: move args to rototiller_tVito Caputo
Particularly for simple boolean args it's desirable to just access their values directly in the args without any further cooking required. Rather than pointlessly duplicating those cases, just give visibility into the raw args.
2023-01-11src/modules/{stars,plato}: stream tapped variablesVito Caputo
Now that til_stream_t is implemented, let's wire up the taps. Note that nothing actually creates the stream and puts it in the fragment yet, so stream is still always NULL for these effectively turning this into a NOP.
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.
2023-01-10til_module_context: hash the pathVito Caputo
The purpose of the context path is to aid in locating the context instance. The initial application of this will be in service of the taps, which require their module's path as a sort of containing directory of the tap name. It'd be convenient to simply add the path hash with the tap hash to produce the tap's "absolute path" hash when looking up in the hash table.
2023-01-10til_tap: hash tap nameVito Caputo
The purpose of the tap is ultimately to be indexed by name so it's discoverable. I'm leaning towards using a hash table for that, and it'd be silly to keep recomputing the hash of an unchanging name.
2023-01-10til_jenkins: add a rudimentary hash functionVito Caputo
Presently just for hashing paths and names
2023-01-10*: introduce paths for module contextsVito Caputo
There needs to be a way to address module context instances by name externally, in a manner complementary to settings and taps. This commit adds a string-based path to til_module_context_t, and modifies til_module_create_context() to accept a parent path which is then concatenated with the name of the module to produce the module instance's new path. The name separator used in the paths is '/' just like filesystem paths, but these paths have no relationship to filesystems or files. The root module context creation in rototiller's main simply passes "" as the parent path, resulting in a "/" root as one would expect. There are some obvious complications introduced here however: - checkers in particular creates a context per cpu, simply using the same seed and setup to try make the contexts identical at the same ticks value. With this commit I'm simply passing the incoming path as the parent for creating those contexts, but it's unclear to me if that will work OK. With an eye towards taps deriving their parent path from the context path, I guess these taps would all get the same parent and hash to the same value despite being duplicated. Maybe it Just Works, but one thing is clear - there won't be any way to address the per-cpu taps as-is. Maybe that's desirable though, there's probably not much use in trying to control the taps at the CPU granularity. - when the recursive settings stuff lands, it should bring along the ability to explicitly name settings blocks. Those names should override the module name in constructing the path. I've noted as such in the code. - these paths probably need to be hashed @ initialization time so there needs to be a hash function added to til, and a hash value accompanying the name in the module context. It'd be dumb to keep recomputing the hash when these paths get used for hash table lookups multiple times per frame... there's probably more I'm forgetting right now, but this seems like a good first step. fixup root path
2023-01-10modules/stars: add taps for some varsVito Caputo
Wiring up some minimal taps to see how this will work... This only initializes the taps and changes the render to access the rates indirectly via the tapped pointers.
2023-01-10modules/plato: add taps for {spin,orbit}_rate varsVito Caputo
Wiring up some minimal taps to see how this will work... This only initializes the taps and changes the render to access the rates indirectly via the tapped pointers.
2023-01-10til_tap: return tap by value instead of taking ptrVito Caputo
this is slightly more ergonomic by having one less pointer to get in the right place in the parameters
2023-01-10til_tap: convert taps to intrusive public structsVito Caputo
The previous commit implemented taps in a way requiring allocations and cleanup. Let's experiment a bit and just make them absolutely minimal named typed variable+indirection bindings. The helpers are retained, but converted to initializers rather than new() style constructors. They provide type-checking of the variable and indirection pointer, and prevent incorrect TIL_TYPE values going in til_type_t.type for the supplied bound elems+ptr.
2023-01-09til_tap: first stab at a tap interfaceVito Caputo
The idea here is for modules to bind variables to names @ context create time w/til_tap_new(). Pseudo-code sample: ``` typedef struct foo_context_t { struct { til_tap_t *position; } taps; struct { v2f_t position; } vars; v2f_t *position; } foo_context_t; foo_context_t * foo_create_context(void) { foo_context_t *foo = malloc(sizeof(foo_context_t)); /* This creates an isolated (pipe-)tap binding our local position variable and pointer * to a name for later "tapping" onto a stream. */ foo->taps.position = til_tap_new_v2f(&foo->position, "position", 1, &foo->vars.position); return foo; } foo_render(foo_context_t *foo, til_fb_fragment_t *fragment) { if (!til_stream_tap(fragment->stream, &foo->pipes.position)) { /* got nothing, we're driving */ foo->position->x = cosf(ticks); foo->position->y = sinf(ticks); } /* else { got something, just use foo->position as-is */ draw_stuff_using_position(foo->position); } ``` Note til_stream_tap() doesn't exist yet, this commit only adds the tap (til_tap_new()). The stream will probably implement a hash table for looking up the tap by name, verifying its type and nelems match if found, and update the pointer to point at the instance actually driving for the name. (in the example that's the foo_context_t.position pointer which draw_stuff_using_position() then dereferences) Also note that in the example, "position" alone is too simplistic for handling complex real-life compositions where a given module may recur in a given stream. That identifier would need to be derived from the module's context/setup producing a distinctly unique path to the tap. i.e. "/compose/layers/checkers/fill_module/foo:position" or something, to be dynamically generated. And the foo:position syntax isn't set in stone either. Maybe foo/position would suffice, the whole heirarchical syntax needs to be thought through and defined yet. Since the absolute path to the tap would be setup-dependent, there will have to be some glue tying together the setup used by the context and the tap within that context. The stream may be the natural place where that occurs. This also currently is barebones in terms of the tap types supported. The only higher-order types are rudimentary 2-4d vectors and 4x4 matrices. There are no semantics associated with the types, and it's likely in the future either the tap types themselves will expand to be semantic. Think things like a camera type, composed both a point and direction vector. As-is the few higher-order types in til_tap.h are simply forward declared, and at least in terms of the taps alone further type visibility isn't necessary. It may make more sense to build upon these bare taps with another semantic layer bringing the higher-order types to the table in a more concrete form. All those higher-order types would then be composed from the bare taps. There's some conceptual overlap with the knobs stubbed out in til_knobs.h as well. I think this likely at least partially replaces what's there, and what it doesn't will probably end up somewhere else.
2023-01-07til_fb: introduce til_fb_fragment_t.streamVito Caputo
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.
2022-11-12modules/compose: more robust texture preservationVito Caputo
The existing code only really cared about preserving the incoming texture on behalf of the caller when the compose code itself was doing something with the texture. But there's scenarios where the underlying module being rendered (or its descendants) might play with the texture, and in such a situation when the outer compose wasn't involving a texture it'd let the descandants installed texture leak out to the callers making the texture apply more than one'd expect. Arguably none of the modules should be missing restoration of the incoming texture after installing+rendering with their own. But with this change in place, compose will clean up after nested modules leaking their texture up.
2022-11-09modules/strobe: force flash even at low FPSPhilip J Freeman
At low framerates, the strobe module timer can expire from frame to frame. This has the effect of appearing "always on." This condition was obscuring output in compose mode. #BirdwalkCommit #WinterStormWarning
2022-09-05modules/roto: move tables init to context createVito Caputo
Mechanical rearrangement, but ultimately there probably needs to be an initialize function added to til_module_t. With all the threading chaos going on, this approach to implicit initialization with a static flag is racy without using atomics. For now it's probably marginally better to do this in context create vs. prepare frame. Context creates *tend* to happen in single-threaded phases of execution, and infrequently. Prepare frame is a serialized phase of the rendering for a given context, but there can be many contexts in-flight simultaneously now with all the forms of compositing happening, sometimes from multiple threads. So that assumption no longer holds...
2022-09-05modules/blinds: use til_ticks_to_rads(ticks)Vito Caputo
This gets rid of the static accumulator hack used for the blinds phase.
2022-09-05til_util: add helper for turning ticks into radiansVito Caputo
There's still a handful of modules doing ad-hoc radians accumulation in a static variable by simply adding a small value like .01 every render. This worked OK in the early days when 1. no rototiller instance was ever run long enough for that accumulator to become a large value where floating point precision started rearing its ugly head. and 2. rototiller never really drew the same module multiple times in compositing a frame. Now that rototiller can produce some rather interesting outputs the first assumption isn't really true - I've fixed memory leaks to enable long-running sessions, so these potential precision problems should get dealth with. And with rtv+compose/checkers+fill_module it's quite common to have a module rendering things many times in a single frame. So that previously tolerable laziness of using a static accumulator is no longer acceptable, since every invocation of the module's renderer would bump the accumulator. When you have something like checkers using blinds for the filler, every individual cell is unintentionally advancing the blinds when they're intended to be at the same phase. So this helper is being added to conveniently turn ticks into something you'd pass directly into cosf/sinf without worrying about precision issues. Future commits will start bringing modules over to use this helper instead of whatever they're doing with static variables or in-context accumulators etc. There's also another reason to prefer deriving "T" from ticks on every frame; we can do things like fast-forward/rewind effects on modules by manipulating the ticks input value. If the modules are accumulating this state privately, manipulating ticks won't have the intended effect. Of course not all modules are amenable to this kind of thing, stuff like swarm and sparkler where they do a sort of simulation contain a pile of state that isn't ticks-derived on every frame and can't really be converted to do so.
© All Rights Reserved