summaryrefslogtreecommitdiff
path: root/src/main.c
AgeCommit message (Collapse)Author
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.
2022-03-30*: wire up context-specific setup instancesVito Caputo
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
2022-03-29build: make sdl2 and rototiller bin optionalVito Caputo
Now that there's a decoupled libtil usable by alternative frontends by vendoring rototiller, the build should support fb-less rototiller-less configurations. In lieu of this change glimmer's build requires sdl2 despite not actually utilizing sdl_fb. Now that shouldn't be necessary, should there be neither libdrm or sdl2 present we'll only produce libtil and no rototiller binary at all.
2022-03-19*: de-constify til_setting_t throughoutVito Caputo
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.
2022-03-19*: use til_module_destroy_context()Vito Caputo
Mechanically replaced ad-hoc til_module_t.destroy_context() invocations with helper calls.
2022-03-19*: normalize setting description capitalizationsVito Caputo
Always only capitalize the first letter, never capitalize like titles.
2022-03-12til_settings: always describe relevant settingsVito Caputo
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.
2022-03-11main: move til_init() to start of mainVito Caputo
Currently this was done rather late for vestigial pre-libtil reasons; it used to be a local function for specifically "create rendering threads" purpose. But it's rather awkward now to see such an initializer called late after myriad other til_* API is being used, and there's nothing gauranteeing til_init() will continue to strictly create rendering threads. Nothing is actually changing in what til_init() does here, it's just a cosmetic movement of the call site and s/librototiller/libtil/ in the error message.
2022-03-11main: simplify setup_from_args()Vito Caputo
Just removing some copy pasta from the error paths, nothing functionally different.
2021-10-03args: move argument parsing/help output to libtilVito Caputo
This is totally opt-in for libtil callers, but is a step towards enabling uniform cli invocations across frontends. The help side of this is particularly janky, but since what's appropriate there is directly related to the args parsing it seems appropriate to bring along. The janky part is the implicit output formatting assumptions being made, as-is it doesn't really lend itself well to being augmented into broader frontend help output. Alas, this is rototiller playground, so let's just go easy and assume frontends will largely spit out whatever this provides - or completely replace it if appropriate.
2021-10-01*: librototiller->libtilVito Caputo
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_.
2021-02-14*: split rototiller.[ch] into lib and mainVito Caputo
This is a first approximation of separating the core modules and threaded rendering from the cli-centric rototiller program and its sdl+drm video backends. Unfortunately this seemed to require switching over to libtool archives (.la) to permit consolidating the per-lib and per-module .a files into the librototiller.a and linking just with librototiller.a to depend on the aggregate of libs+modules+librototiller-glue in a simple fashion. If an alternative to .la comes up I will switch over to it, using libtool really slows down the build process. Those are implementation/build system details though. What's important in these changes is establishing something resembling a librototiller API boundary, enabling creating alternative frontends which vendor this tree as a submodule and link just to librototiller.{la,a} for all the modules+threaded rendering of them, while providing their own fb_ops_t for outputting into, and their own settings applicators for driving the modules setup.
© All Rights Reserved