summaryrefslogtreecommitdiff
path: root/src/main.c
AgeCommit message (Collapse)Author
2023-11-30til,main: introduce ratio= --video settingVito Caputo
First stab at supporting explicit aspect ratios. This performs the adjustment when needed in til_fb so it's automatically applied to all fb backends. The syntax is ratio=W:H with ratio=full being special cased for when no aspect ratio adjustment is desired (just use whatever the fb page dimensions are, usually specified via size= in the fb backend's settings, or display native res when fullscreen=on) For now when an aspect ratio is specified it always fits the content within the alotted space... there is no full-but-ratio-preserved-by-clipping-if-needed variant like widescreen TVs often have.
2023-11-30til: wire up til_video_setup_t throughout *_fbVito Caputo
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.
2023-11-18main: use new til_stream_render() apiVito Caputo
Instead of just calling til_module_render() with the top-level module context, use the newly added til_stream_render() and til_stream_set_module_context() to achieve the same thing. This is a preparatory commit for handling pre/post-render module contexts automagically in til_stream_render(). e.g. stuff like background music would be hooked into the stream as a pre-render context.
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-11-14til: add preliminary audio backendVito Caputo
This is an early implementation of something resembling an audio backend for rototiller/libtil. The assumption for now is that everything will use signed 16-bit native-endian stereo output @ 44.1khz.
2023-08-29main: prevent ticks from going backwardsVito Caputo
Outside of overflow (which I'm ignoring for now) ticks shouldn't go backwards. With the introduction of adding the frame-buffer delays, which vary, there's the potential for the delay to go from large to short in quick succession, to such a degree that the next render's now+delay is in the past relative to the previous now+delay. For now this simple fix is to just track the last_ticks and always use the maximum of the last_ticks and now+delay, ensuring it never goes backwards. This was making alphazed exit prematurely at spurious times by sending the rocket_row into oblivion because (ticks - last_ticks) was negative w/unsigned arithmetic. This will all get more work, and maybe ticks should be allowed to go backwards actually, but some things are assuming that's not the case as-is. Regardless, it's not desirable for ticks to go backwards because of the frame-buffer delay. In that case just chill on the ticks advancement for a frame. This will need revisiting for sure, as I don't think re-rendering the exact same tick as the last frame is likely to be what's wanted either. Probably some little advancement should still be performed...
2023-08-29main: apply submit-to-present delay to ticksVito Caputo
This should push the ticks value ahead by 1-2 frames worth of time, when rendering is meeting/exceeding the frame rate. Which is the appropriate thing to do, since rendering is effectively slightly ahead of the clock, producing visuals for now+N-frames into the future. When rendering lags behind, there's basically no delay, and rendering is just operating on the "now" ticks which will be flipped to ASAP once submitted. This will probably be revisited once audio is rolled in, since that too will need to be kept in sync with the visuals' perspective of time.
2023-08-29til_fb: return queue delay from til_fb_page_get()Vito Caputo
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.
2023-08-20main: drop get_ticks() in favor of til_ticks_now()Vito Caputo
This was made redundant by til_ticks_now(), and get_ticks() looks buggy in its usecs arithmetic on top of it.
2023-08-18main: call til_stream_start_frame()Vito Caputo
Tell the stream when starting a new frame...
2023-08-13main: free setups and settings in shutdownVito Caputo
more cleaning up stuff on exit
2023-08-13main: switch to til_fb_halt()Vito Caputo
This gets rid of the rototiller_thread() pthread_cancel() based exit which seemed to rarely make clang's ASAN (-fsanitize=address) very angry with a segfault in libc somewhere Instead of trying to chase that down I'm just getting rid of it, it's unnecessary.
2023-08-05main: handle NULL res_setup a la "none" builtinVito Caputo
This will just quietly exit successfully if "none" is provided as the root rendering module. It's not really a case worth bothering with doing something more about... the user did this pointless thing on purpose. Let's just not crash. While here I may have fixed a bug surrounding til_quiesce() not being called on the teardown path.
2023-07-17main: fix UAF bug on shutdownVito Caputo
When introducing the **fragment_ptr model in 5a0776f, the rototiller_thread() introduced a local place to put the pointer to point at when rendering. But this pointer then ends up outliving the thread on shutdown within any queued frames until quiescent. Fixed in the obvious way by sticking it in rototiller_t instead.
2023-07-13til_args,*_fb: introduce --title= and wire up to til_fb_tVito Caputo
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.
2023-07-05setup: return failed desc _path_ from setup_interactively()Vito Caputo
Returning the failed desc was just a lazy half-assed thing that was sort of the best option in the simpler, pre-paths world. But now that everything has paths thanks to recursive settings, let's just return the path to the failed setting's desc. This conveniently gets rid of a UAF bug when setup returned the setting->desc as the failed desc, and main would print the desc *after* freeing all the settings in its final moments. But the best part is now more of the errors parsing settings should be accompanied by an illuminatingly relevant setting path. Previously you'd at best get a bare key from the desc, but often no failed desc was returned at all and you saw no guidance at all. But with the recent improvements to the setup error handling I think those cases should be few if not entirely eliminated.
2023-06-15main: quit when the stream endsVito Caputo
I can't see this staying so simple for very long, but for now this at least enables making rototiller-based rkt-sequenced demos that exit gracefully when they're finished. In a future where rtv may play embedded rkt configs+tracks, it needs a way to detect the end of stream without making main exit. But I'll cross that bridge when I get there...
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_args: introduce --print-module-contextsVito Caputo
Some rudimentary instrumentation for monitoring the active module contexts alongside the pipes You probably want to redirect stderr to a file when using --print-pipes and/or --print-module-contexts... e.g. ``` rototiller --defaults --go --print-pipes --print-module-contexts 2>/dev/null ``` or, if you still want to monitor FPS or log_channels=on in rtv, 2>/file/to/tail then tail -F /file/to/tail in another terminal.
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-03til_settings: add an optional til_settings_t.prefixVito Caputo
Preparatory commit for bridging the gap separating a baked til_setup_t from a runtime-populated descendant til_settings_t like modules::rtv produces for its channels via til_module_setup_randomize(). For these currently orphaned til_settings_t instances we don't readily have access to the logical ancestor til_settings_t that was used to produce the module_context's bound til_setup_t. But we don't really need the ancestor til_settings_t, all we _really_ want is the ancestral path to prefix the orphan til_settings_t instances. So this commit introduces supplying a prefix which gets prepended to paths printed via the settings instance. A later commit will make use of this in modules::rtv when producing the settings instance passed to til_module_setup_randomize()
2023-05-30til,*: pivot to til_setup_t for context pathsVito Caputo
This changes til_setup_t* from optional to required for til_module_context_t creation, while dropping the separate path parameter construction and passing throughout.
2023-05-26til_settings: add til_setting_spec_t.as_labelVito Caputo
Currently settings instances get labels from three sources: 1. explicitly labeled by a root-level til_settings_new() call, like main.c::til_settings_new(NULL, "video", args->video); 2. implicitly labeled in a spec.as_nested_settings w/spec.key 3. positionally labeled in a spec.as_nested_settings w/o spec.key But when constructing setting/desc paths, using strictly these settings instance labels as the "directory name path component" equivalent, leaves something to be desired. Take this hypothetical module setting path for example: /module/layers/[0]/viscosity Strictly using settings instance labels as-is, the above is what you'd get for the drizzle::viscosity setting in something like: --module=compose,layers=drizzle Which is really awkward. What's really desired is more like: /module/compose/layers/[0]/drizzle/viscosity Now one way to achieve that is to just create more settings instances to hold these module names as labels and things would Just Work more or less. But that would be rather annoying and heavyweight, when what's _really_ wanted is a way to turn the first entry's value of a given setting instance into a sort of synthetic directory component in the path. So that's what this commit does. When a spec has .as_label specified, it's saying that path construction should treat this setting's value as if it were a label on a settings instance. But it's special cased to only apply to descs hanging off the first entry of a settings instance, as that's the only scenario we're making use of, and it avoids having to do crazy things like search all the entries for specs w/.as_label set. It feels a bit janky but it does achieve what's needed with little pain/churn.
2023-05-24til_settings: til_setting_t,til_settings_t get parent pointersVito Caputo
Preparatory for constructing unique paths from a given setting/settings instance by walking up the tree
2023-05-11til_settings: introduce til_setting_spec_t concept vs. descVito Caputo
For recursive settings the individual setting being described needs to get added to a potentially different settings instance than the one being operated on at the top of the current setup_func phase. The settings instance being passed around for a setup_func to operate on is constified, mainly to try ensure modules don't start directly mucking with the settings. They're supposed to just describe what they want next and iterate back and forth, with the front-end creating the settings from the returned descs however is appropriate, eventually building up the settings to completion. But since it's the setup_func that decides which settings instance is appropriate for containing the setting.. at some point it must associate a settings instance with the desc it's producing, one that is going to be necessarily written to. So here I'm just turning the existing til_setting_desc_t to a "spec", unchanged. And introducing a new til_setting_desc_t embedding the spec, accompanied by a non-const til_settings_t* "container". Now what setup_funcs use to express settings are a spec, otherwise identically to before. Instead of cloning a desc to allocate it for returning to the front-end, the desc is created from a spec with the target settings instance passed in. This turns the desc step where we take a constified settings instance and cast it into a non-const a more formal act of going from spec->desc, binding the spec to a specific settings instance. It will also serve to isolate that hacky cast to a til_settings function, and all the accessors of til_setting_desc_t needing to operate on the containing settings instance can just do so. As of this commit, the container pointer is just sitting in the desc_t but isn't being made use of or even assigned yet. This is just to minimize the amount of churn happening in this otherwise mostly mechanical and sprawling commit. There's also been some small changes surrounding the desc generators and plumbing of the settings instance where there previously wasn't any. It's unclear to me if desc generators will stay desc generators or turn into spec generators. For now those are mostly just used by the drm_fb stuff anyways, modules haven't made use of them, so they can stay a little crufty harmlessly for now.
2023-05-11til_settings: rework setting get/add for bare valuesVito Caputo
The core thing here is rather than turning a bare value into a key as I was doing before - we just leave the bare value as a bare value and its setting must be located positionally via get_value_by_idx since there's no key. Existing callers that used to get_key() positionally now get_value_by_idx() positionally all the same, except it's the value instead of the key. This is mostly done for things like the module or fb name at the front of a settings instance. The impetus for this change is partially just cosmetic/ergonomics, but it's also rather strange for what's really a key-less value to be treated as a value-less key. It was also awkward to talk/reason about on the road to recursive settings where bare values would be supported as a standalone settings instance if properly escaped... This also adds unescaping of keys, and adds a dependency on the somewhat linux-specific open_memstream() which may need changing in the future (see comments).
2023-05-11setup: constify settings passed to setup_funcVito Caputo
setup_func isn't formally defined for libtil, but setup_interactively() defacto establishes it and til_module_t.setup() reflects the same signature and calling convention except with til_settings_t constified. This change makes them all consistent in this regard, but there should probably be a formal typedef added for the function. The reason for constifying this is I don't want setup functions directly manipulating the settings instance. In the case of rototiller::setup_interactively() we ensure the stdio-based interactive setup is always the side doing the manipulation of the settings. For a libtil-user like glimmer, it's slightly different beast with GTK+ in the loop, but by preventing the setup_funcs from messing directly with the settings (instead having to describe what they want done iteratively), the front-end always gets its opportunity to maintain its state while doing the described things. Of course, this is mostly a lie, and within libtil the constified til_settings_t gets cast away to modify it in places. But keeping that limited to within libtil is tolerable IMO. We just don't want to see such casts in module code.
2023-05-11main: quote shown flags/argsVito Caputo
Preparatory commit for recursive settings going cray-cray with escaping. At least single-quote these so it's directly copy-and-pasteable into a shell prompt.
2023-05-10til_settings: label til_settings_t instancesVito Caputo
This adds a mandatory label string to til_setttings_new() and updates call sites accordingly. For now the root-level settings created by main.c are simply named "module" and "video" respectively. Any nested settings creations on behalf of modules will be labeled using the module's name the settings are being created for use with. This might evolve with time, for now it's just a minimum churn kind of decision. I can see it changing such that the top-level settings also become labeled by the module/video driver name rather than the obtuse "module" "video" strings. How these will be leveraged is unclear presently. At the least it'll be nice to have a label for debugging til_settings_t heirarchies once recursive settings support lands. In a sense this is a preparatory commit for that work. But I could see the labels ending up in serialization contents as markup/syntactic sugar just to self-document things as well. There might also be a need to address til_settings_t instances in the settings heirarchy, which may be something like a "label/label/label/label" path style thing - though there'd be a need to deal with name collisions in that approach. I'm just thinking a bit about how knobs will become addressed when those become a real thing. The settings label heirarchy might be the convenient place to name everything in a tree, which knobs could then inherit their parent paths from under which their respective knob labels will reside. For the whole name collision issue there could just be some builtin settings keys for overriding the automatic module name labeling, something like: --module=compose,layers=checkers\,label=first\,fill_module=shapes:checkers\,label=second\,fill_module=shapes would result in: /module/first/shapes /module/second/shapes or in a world where the root settings weren't just named "module" and "video": /compose/first/shapes /compose/second/shapes then if there were knobs under checkers and shapes, say checkers had a "foo" knob and checkers had a "bar" knob, they'd be under .knobs in each directory: /compose/first/.knobs/foo /compose/first/shapes/.knobs/bar /compose/second/.knobs/foo /compose/second/shapes/.knobs/bar something along those lines, and of course if compose had knobs they'd be under /compose/.knobs This is just a brain dump and will surely all change before implemented.
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-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-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
2022-08-07main: still show configured flags with --goVito Caputo
Show the info, but skip the wait step.
2022-08-07til: experimentally fragment-centric page apiVito Caputo
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.
2022-08-07til: til_fb_fragment_t **fragment_ptr all the thingsVito Caputo
Preparatory commit for enabling cloneable/swappable fragments There's an outstanding issue with the til_fb_page_t submission, see comments. Doesn't matter for now since cloning doesn't happen yet, but will need to be addressed before they do.
2022-07-20main: show --seed with print_setup_as_args()Vito Caputo
The purpose of printing the setup is to enable reproducing it, the seed is part of that reconstruction - especially when it's been autogenerated.
2022-07-18til_args: add --seed= explicit PRNG seeding supportVito Caputo
This enables reproducible yet pseudo-randomized visuals, at least for the fully procedural modules. The modules that are more simulation-y like sparkler and swarm will still have runtime variations since they are dependent on how much the simulation can run and there's been a lot of sloppiness surrounding delta-t correctness and such. But still, in a general sense, you'll find more or less similar results even when doing randomized things like module=rtv,channels=compose using the same seed value. For the moment it only accepts a hexadecimal value, the leading 0x is optional. e.g. these are all valid: --seed=0xdeadbeef --seed=0xdEAdBeFf --seed=0x (produces 0) --seed=0xff --seed=deadbeef --seed=ff --seed= (produces 0) --seed=0 (produces 0) when you exceed the natural word size of an unsigned int on your host architecture, an overflow error will be returned. there are remaining issues to be fixed surrounding PRNG reproducibility, in that things like til_module_randomize_setup() doesn't currently accept a seed value. However it doesn't even use rand_r() currently, but when it invokes desc->random() the module's random() implementation should be able to use rand_r() and needs to be fed the seed. So that all still needs wiring up to propagate the root seed down everywhere it may be relevant.
2022-07-15build: always build the rototiller binVito Caputo
Now that there's the mem_fb backend, there's no need to disable producing a rototiller binary in lieu of libdrm and libsdl2. This commit also rejiggers some of the DEFAULT_VIDEO junk in main.c to ensure it falls back on "mem" should there be no drm or sdl2. For now I'm going to leave the AM_CONDITIONAL junk surrounding enabling rototiller in configure.ac, the define can just be ignored for now.
2022-07-15mem_fb: introduce --video=mem; a dummy in-memory video backendVito Caputo
The immediate impetus for adding this is to enable running rototiller even on headless machines just for the sake of getting some FPS measurements. It'd be nice to get a sense for what FPS rototiller would experience on larger modern machines like big EPYC or Threadripper systems. But it seems most of those I can get access to via others running them on work hardware or the like can at most just run it over ssh without any display or risk of disrupting the physical console. But this is probably also useful for testing/debugging purposes, especially since it doesn't bother to synchronize flips on anything not even a timer. So a bunch of display complexity is removed running with video=mem as well as letting the framerate run unbounded. Having said that, it might be nice to add an fps=N setting where mem_fb uses a plain timer for scheduling the flips. Currently the only setting is size=WxH identical to the sdl_fb size= setting, defaulting to 640x480.
2022-07-15til_fb: switch til_fb_ops_t.init() to use til_setup_tVito Caputo
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.
2022-05-29*: pivot to til_module_context_tVito Caputo
- modules now allocate their contexts using til_module_context_new() instead of [cm]alloc(). - modules simply embed til_module_context_t at the start of their respective private context structs, if they do anything with contexts - modules that do nothing with contexts (lack a create_context() method), will now *always* get a til_module_context_t supplied to their other methods regardless of their create_context() presence. So even if you don't have a create_context(), your prepare_frame() and/or render_fragment() methods can still access seed and n_cpus from within the til_module_context_t passed in as context, *always*. - modules that *do* have a create_context() method, implying they have their own private context type, will have to cast the til_module_context_t supplied to the other methods to their private context type. By embedding the til_module_context_t at the *start* of their private context struct, a simple cast is all that's needed. If it's placed somewhere else, more annoying container_of() style macros are needed - this is strongly discouraged, just put it at the start of struct. - til_module_create_context() now takes n_cpus, which may be set to 0 for automatically assigning the number of threads in its place. Any non-zero value is treated as an explicit n_cpus, primarily intended for setting it to 1 for single-threaded contexts necessary when embedded within an already-threaded composite module. - modules like montage which open-coded a single-threaded render are now using the same til_module_render_fragment() as everything else, since til_module_create_context() is accepting n_cpus. - til_module_create_context() now produces a real type, not void *, that is til_module_context_t *. All the other module context functions now operate on this type, and since til_module_context_t.module tracks the module this context relates to, those functions no longer require both the module and context be passed in. This is especially helpful for compositing modules which do a lot of module context creation and destruction; the module handle is now only needed to create the contexts. Everything else operating on that context only needs the single context pointer, not module+context pairs, which was unnecessarily annoying. - if your module's context can be destroyed with a simple free(), without any deeper knowledge or freeing of nested pointers, you can now simply omit destroy_context() altogether. When destroy_context() is missing, til_module_context_free() will automatically use libc's free() on the pointer returned from your create_context() (or on the pointer that was automatically created if you omitted create_context() too, for the bare til_module_context_t that got created on your behalf anyways). For the most part, these changes don't affect module creation. In some ways this eases module creation by making it more convenient access seed and n_cpus if you had no further requirement for a context struct. In other ways it's slightly annoying to have to do type-casts when you're working with your own context type, since before it was all void* and didn't require casts when assigning to your typed context variables. The elimination for requiring a destroy_context() method in simple free() of private context scenarios removes some boilerplate in simple cases. I think it's a wash for module writers, or maybe a slight win for the simple cases.
2022-05-25setup: return the desc for failed setting on errorVito Caputo
This commit improves the error printed when cli-supplied args fail, adding at least the key name to what used to be just a stringified errno: ``` $ src/rototiller --module=shapes,scale=99 Shape type: 0: circle 1: pinwheel 2: rhombus 3: star Enter a value 0-3 [1 (pinwheel)]: Fatal error: unable to use args for setting "scale": Invalid argument $ ```
2022-05-25til: add --go to supported argsVito Caputo
In rototiller this disables the automatic displaying of settings actually used when they differ from what was explicitly specified as args. Which also disables the waiting to press a key. This should also get used by glimmer to automatically start rendering without just putting up the configured settings panel and waiting for a click on "go!".
2022-05-25*: normalize on all case-insensitive comparisonsVito Caputo
I don't think rototiller is an appropriate place for being so uncooperative, if someone gets the case wrong anywhere just make it work. We should avoid making different things so subtly different that case alone is the distinction anyways, so I don't see this creating any future namespace collision problems.
2022-05-21til: supply a seed to til_module_t.create_context()Vito Caputo
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.
2022-04-24*: s/void */til_setup_t */Vito Caputo
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.
© All Rights Reserved