summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVito Caputo <vcaputo@pengaru.com>2021-02-14 22:43:08 -0800
committerVito Caputo <vcaputo@pengaru.com>2021-02-14 22:51:37 -0800
commit11b87c843e20f66bd68e02353ba4a1072e1230a6 (patch)
tree15458ff0ac2b61b51517fb26ca3cd4b148c2a96f
parent950d6abb1ffd126a3200044de31b631ac987ed7e (diff)
*: split rototiller.[ch] into lib and main
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.
-rwxr-xr-xbootstrap4
-rw-r--r--configure.ac2
-rw-r--r--src/Makefile.am11
-rw-r--r--src/libs/ascii/Makefile.am6
-rw-r--r--src/libs/din/Makefile.am6
-rw-r--r--src/libs/grid/Makefile.am6
-rw-r--r--src/libs/puddle/Makefile.am6
-rw-r--r--src/libs/ray/Makefile.am8
-rw-r--r--src/libs/sig/Makefile.am6
-rw-r--r--src/libs/txt/Makefile.am6
-rw-r--r--src/main.c340
-rw-r--r--src/modules/compose/Makefile.am6
-rw-r--r--src/modules/drizzle/Makefile.am6
-rw-r--r--src/modules/flui2d/Makefile.am6
-rw-r--r--src/modules/julia/Makefile.am6
-rw-r--r--src/modules/meta2d/Makefile.am6
-rw-r--r--src/modules/montage/Makefile.am6
-rw-r--r--src/modules/pixbounce/Makefile.am6
-rw-r--r--src/modules/plasma/Makefile.am6
-rw-r--r--src/modules/plato/Makefile.am6
-rw-r--r--src/modules/ray/Makefile.am8
-rw-r--r--src/modules/roto/Makefile.am6
-rw-r--r--src/modules/rtv/Makefile.am6
-rw-r--r--src/modules/snow/Makefile.am6
-rw-r--r--src/modules/sparkler/Makefile.am8
-rw-r--r--src/modules/spiro/Makefile.am6
-rw-r--r--src/modules/stars/Makefile.am6
-rw-r--r--src/modules/submit/Makefile.am6
-rw-r--r--src/modules/swab/Makefile.am6
-rw-r--r--src/modules/swarm/Makefile.am6
-rw-r--r--src/rototiller.c345
-rw-r--r--src/rototiller.h4
32 files changed, 468 insertions, 400 deletions
diff --git a/bootstrap b/bootstrap
index 99f6f06..c5a7472 100755
--- a/bootstrap
+++ b/bootstrap
@@ -1,5 +1,3 @@
#!/bin/sh
-aclocal \
-&& automake --gnu --add-missing \
-&& autoconf
+autoreconf --install
diff --git a/configure.ac b/configure.ac
index 3121644..3abca76 100644
--- a/configure.ac
+++ b/configure.ac
@@ -4,8 +4,8 @@ AC_CONFIG_MACRO_DIRS([m4])
AC_PROG_CC
AM_PROG_CC_C_O
AM_PROG_AR
-AC_PROG_RANLIB
AM_SILENT_RULES([yes])
+LT_INIT([disable-shared])
PKG_CHECK_MODULES(DRM, libdrm,
AM_CONDITIONAL(ENABLE_DRM, true)
diff --git a/src/Makefile.am b/src/Makefile.am
index d65eb5c..c2e8653 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,7 +1,14 @@
SUBDIRS = libs modules
+
+noinst_LTLIBRARIES = librototiller.la
+librototiller_la_SOURCES = fb.c fb.h knobs.h rototiller.c rototiller.h settings.h settings.c threads.c threads.h util.c util.h
+librototiller_la_CPPFLAGS = -I@top_srcdir@/src
+librototiller_la_LIBADD = modules/compose/libcompose.la modules/drizzle/libdrizzle.la modules/flui2d/libflui2d.la modules/julia/libjulia.la modules/meta2d/libmeta2d.la modules/montage/libmontage.la modules/pixbounce/libpixbounce.la modules/plasma/libplasma.la modules/plato/libplato.la modules/ray/libray.la modules/roto/libroto.la modules/rtv/librtv.la modules/snow/libsnow.la modules/sparkler/libsparkler.la modules/spiro/libspiro.la modules/stars/libstars.la modules/submit/libsubmit.la modules/swab/libswab.la modules/swarm/libswarm.la libs/grid/libgrid.la libs/puddle/libpuddle.la libs/ray/libray.la libs/sig/libsig.la libs/txt/libtxt.la libs/ascii/libascii.la libs/din/libdin.la
+
bin_PROGRAMS = rototiller
-rototiller_SOURCES = fb.c fb.h fps.c fps.h knobs.h rototiller.c rototiller.h sdl_fb.c settings.h settings.c setup.h setup.c threads.c threads.h util.c util.h
+rototiller_SOURCES = fb.c fb.h fps.c fps.h knobs.h main.c rototiller.h sdl_fb.c settings.h settings.c setup.h setup.c threads.c threads.h util.c util.h
if ENABLE_DRM
rototiller_SOURCES += drm_fb.c
endif
-rototiller_LDADD = modules/compose/libcompose.a modules/drizzle/libdrizzle.a modules/flui2d/libflui2d.a modules/julia/libjulia.a modules/meta2d/libmeta2d.a modules/montage/libmontage.a modules/pixbounce/libpixbounce.a modules/plasma/libplasma.a modules/plato/libplato.a modules/ray/libray.a modules/roto/libroto.a modules/rtv/librtv.a modules/snow/libsnow.a modules/sparkler/libsparkler.a modules/spiro/libspiro.a modules/stars/libstars.a modules/submit/libsubmit.a modules/swab/libswab.a modules/swarm/libswarm.a libs/grid/libgrid.a libs/puddle/libpuddle.a libs/ray/libray.a libs/sig/libsig.a libs/txt/libtxt.a libs/ascii/libascii.a libs/din/libdin.a -lm
+rototiller_LDADD = librototiller.la -lm
+#rototiller_LDADD = modules/compose/libcompose.a modules/drizzle/libdrizzle.a modules/flui2d/libflui2d.a modules/julia/libjulia.a modules/meta2d/libmeta2d.a modules/montage/libmontage.a modules/pixbounce/libpixbounce.a modules/plasma/libplasma.a modules/plato/libplato.a modules/ray/libray.a modules/roto/libroto.a modules/rtv/librtv.a modules/snow/libsnow.a modules/sparkler/libsparkler.a modules/spiro/libspiro.a modules/stars/libstars.a modules/submit/libsubmit.a modules/swab/libswab.a modules/swarm/libswarm.a libs/grid/libgrid.a libs/puddle/libpuddle.a libs/ray/libray.a libs/sig/libsig.a libs/txt/libtxt.a libs/ascii/libascii.a libs/din/libdin.a -lm
diff --git a/src/libs/ascii/Makefile.am b/src/libs/ascii/Makefile.am
index 41476bb..bc8ab4a 100644
--- a/src/libs/ascii/Makefile.am
+++ b/src/libs/ascii/Makefile.am
@@ -1,3 +1,3 @@
-noinst_LIBRARIES = libascii.a
-libascii_a_SOURCES = ascii.c ascii.h
-libascii_a_CPPFLAGS = -I@top_srcdir@/src
+noinst_LTLIBRARIES = libascii.la
+libascii_la_SOURCES = ascii.c ascii.h
+libascii_la_CPPFLAGS = -I@top_srcdir@/src
diff --git a/src/libs/din/Makefile.am b/src/libs/din/Makefile.am
index b918de6..dfbf9bf 100644
--- a/src/libs/din/Makefile.am
+++ b/src/libs/din/Makefile.am
@@ -1,3 +1,3 @@
-noinst_LIBRARIES = libdin.a
-libdin_a_SOURCES = din.c din.h v3f.h
-libdin_a_CPPFLAGS = -I@top_srcdir@/src
+noinst_LTLIBRARIES = libdin.la
+libdin_la_SOURCES = din.c din.h v3f.h
+libdin_la_CPPFLAGS = -I@top_srcdir@/src
diff --git a/src/libs/grid/Makefile.am b/src/libs/grid/Makefile.am
index e9c8f3a..2d93699 100644
--- a/src/libs/grid/Makefile.am
+++ b/src/libs/grid/Makefile.am
@@ -1,3 +1,3 @@
-noinst_LIBRARIES = libgrid.a
-libgrid_a_SOURCES = grid.c grid.h macros.h
-libgrid_a_CPPFLAGS = -I@top_srcdir@/src
+noinst_LTLIBRARIES = libgrid.la
+libgrid_la_SOURCES = grid.c grid.h macros.h
+libgrid_la_CPPFLAGS = -I@top_srcdir@/src
diff --git a/src/libs/puddle/Makefile.am b/src/libs/puddle/Makefile.am
index faacb49..b3cc0f8 100644
--- a/src/libs/puddle/Makefile.am
+++ b/src/libs/puddle/Makefile.am
@@ -1,3 +1,3 @@
-noinst_LIBRARIES = libpuddle.a
-libpuddle_a_SOURCES = puddle.c puddle.h
-libpuddle_a_CPPFLAGS = -I@top_srcdir@/src
+noinst_LTLIBRARIES = libpuddle.la
+libpuddle_la_SOURCES = puddle.c puddle.h
+libpuddle_la_CPPFLAGS = -I@top_srcdir@/src
diff --git a/src/libs/ray/Makefile.am b/src/libs/ray/Makefile.am
index f055d94..6439f63 100644
--- a/src/libs/ray/Makefile.am
+++ b/src/libs/ray/Makefile.am
@@ -1,4 +1,4 @@
-noinst_LIBRARIES = libray.a
-libray_a_SOURCES = ray_3f.h ray_camera.c ray_camera.h ray_color.h ray_euler.c ray_euler.h ray_gamma.c ray_gamma.h ray_light_emitter.h ray_object.h ray_object_light.h ray_object_plane.h ray_object_point.h ray_object_sphere.h ray_object_type.h ray_ray.h ray_render.c ray_render.h ray_render_object.h ray_render_object_plane.h ray_render_object_point.h ray_render_object_sphere.h ray_scene.h ray_surface.h
-libray_a_CFLAGS = -ffast-math
-libray_a_CPPFLAGS = -I@top_srcdir@/src
+noinst_LTLIBRARIES = libray.la
+libray_la_SOURCES = ray_3f.h ray_camera.c ray_camera.h ray_color.h ray_euler.c ray_euler.h ray_gamma.c ray_gamma.h ray_light_emitter.h ray_object.h ray_object_light.h ray_object_plane.h ray_object_point.h ray_object_sphere.h ray_object_type.h ray_ray.h ray_render.c ray_render.h ray_render_object.h ray_render_object_plane.h ray_render_object_point.h ray_render_object_sphere.h ray_scene.h ray_surface.h
+libray_la_CFLAGS = -ffast-math
+libray_la_CPPFLAGS = -I@top_srcdir@/src
diff --git a/src/libs/sig/Makefile.am b/src/libs/sig/Makefile.am
index 7e2537c..d81ae95 100644
--- a/src/libs/sig/Makefile.am
+++ b/src/libs/sig/Makefile.am
@@ -1,3 +1,3 @@
-noinst_LIBRARIES = libsig.a
-libsig_a_SOURCES = ops_abs.c ops_add.c ops_ceil.c ops_clamp.c ops_const.c ops_div.c ops_expand.c ops_floor.c ops_inv.c ops_lerp.c ops_max.c ops_min.c ops_mult.c ops_neg.c ops_pow.c ops_rand.c ops_round.c ops_scale.c ops_sin.c ops_sub.c sig.c sig.h
-libsig_a_CPPFLAGS = -I@top_srcdir@/src
+noinst_LTLIBRARIES = libsig.la
+libsig_la_SOURCES = ops_abs.c ops_add.c ops_ceil.c ops_clamp.c ops_const.c ops_div.c ops_expand.c ops_floor.c ops_inv.c ops_lerp.c ops_max.c ops_min.c ops_mult.c ops_neg.c ops_pow.c ops_rand.c ops_round.c ops_scale.c ops_sin.c ops_sub.c sig.c sig.h
+libsig_la_CPPFLAGS = -I@top_srcdir@/src
diff --git a/src/libs/txt/Makefile.am b/src/libs/txt/Makefile.am
index 88aa79b..0d0db46 100644
--- a/src/libs/txt/Makefile.am
+++ b/src/libs/txt/Makefile.am
@@ -1,3 +1,3 @@
-noinst_LIBRARIES = libtxt.a
-libtxt_a_SOURCES = txt.c txt.h
-libtxt_a_CPPFLAGS = -I@top_srcdir@/src -I@top_srcdir@/src/libs
+noinst_LTLIBRARIES = libtxt.la
+libtxt_la_SOURCES = txt.c txt.h
+libtxt_la_CPPFLAGS = -I@top_srcdir@/src -I@top_srcdir@/src/libs
diff --git a/src/main.c b/src/main.c
new file mode 100644
index 0000000..5180529
--- /dev/null
+++ b/src/main.c
@@ -0,0 +1,340 @@
+#include <assert.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <sys/time.h>
+#include <unistd.h>
+
+#include "settings.h"
+#include "setup.h"
+#include "fb.h"
+#include "fps.h"
+#include "rototiller.h"
+#include "util.h"
+
+/* Copyright (C) 2016 Vito Caputo <vcaputo@pengaru.com> */
+
+#define NUM_FB_PAGES 3
+/* ^ By triple-buffering, we can have a page tied up being displayed, another
+ * tied up submitted and waiting for vsync, and still not block on getting
+ * another page so we can begin rendering another frame before vsync. With
+ * just two pages we end up twiddling thumbs until the vsync arrives.
+ */
+#define DEFAULT_VIDEO "sdl"
+
+extern fb_ops_t drm_fb_ops;
+extern fb_ops_t sdl_fb_ops;
+fb_ops_t *fb_ops;
+
+typedef struct rototiller_t {
+ const rototiller_module_t *module;
+ void *module_context;
+ pthread_t thread;
+ fb_t *fb;
+ struct timeval start_tv;
+ unsigned ticks_offset;
+} rototiller_t;
+
+static rototiller_t rototiller;
+
+
+typedef struct argv_t {
+ const char *module;
+ const char *video;
+
+ unsigned use_defaults:1;
+ unsigned help:1;
+} argv_t;
+
+/*
+ * ./rototiller --video=drm,dev=/dev/dri/card3,connector=VGA-1,mode=640x480@60
+ * ./rototiller --video=sdl,size=640x480
+ * ./rototiller --module=roto,foo=bar,module=settings
+ * ./rototiller --defaults
+ */
+static int parse_argv(int argc, const char *argv[], argv_t *res_args)
+{
+ int i;
+
+ assert(argc > 0);
+ assert(argv);
+ assert(res_args);
+
+ /* this is intentionally being kept very simple, no new dependencies like getopt. */
+
+ for (i = 1; i < argc; i++) {
+ if (!strncmp("--video=", argv[i], 8)) {
+ res_args->video = &argv[i][8];
+ } else if (!strncmp("--module=", argv[i], 9)) {
+ res_args->module = &argv[i][9];
+ } else if (!strcmp("--defaults", argv[i])) {
+ res_args->use_defaults = 1;
+ } else if (!strcmp("--help", argv[i])) {
+ res_args->help = 1;
+ } else {
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+
+typedef struct setup_t {
+ settings_t *module;
+ settings_t *video;
+} setup_t;
+
+/* FIXME: this is unnecessarily copy-pasta, i think modules should just be made
+ * more generic to encompass the setting up uniformly, then basically
+ * subclass the video backend vs. renderer stuff.
+ */
+
+/* select video backend if not yet selected, then setup the selected backend. */
+static int setup_video(settings_t *settings, setting_desc_t **next_setting)
+{
+ const char *video;
+
+ /* XXX: there's only one option currently, so this is simple */
+ video = settings_get_key(settings, 0);
+ if (!video) {
+ setting_desc_t *desc;
+ const char *values[] = {
+#ifdef HAVE_DRM
+ "drm",
+#endif
+ "sdl",
+ NULL,
+ };
+ int r;
+
+ r = setting_desc_clone(&(setting_desc_t){
+ .name = "Video Backend",
+ .key = NULL,
+ .regex = "[a-z]+",
+ .preferred = DEFAULT_VIDEO,
+ .values = values,
+ .annotations = NULL
+ }, next_setting);
+ if (r < 0)
+ return r;
+
+ return 1;
+ }
+
+ /* XXX: this is kind of hacky for now */
+#ifdef HAVE_DRM
+ if (!strcmp(video, "drm")) {
+ fb_ops = &drm_fb_ops;
+
+ return drm_fb_ops.setup(settings, next_setting);
+ } else
+#endif
+ if (!strcmp(video, "sdl")) {
+ fb_ops = &sdl_fb_ops;
+
+ return sdl_fb_ops.setup(settings, next_setting);
+ }
+
+ return -EINVAL;
+}
+
+
+/* turn args into settings, automatically applying defaults if appropriate, or interactively if appropriate. */
+/* returns negative value on error, 0 when settings unchanged from args, 1 when changed */
+static int setup_from_args(argv_t *args, setup_t *res_setup)
+{
+ int r, changes = 0;
+ setup_t setup;
+
+ setup.module = settings_new(args->module);
+ if (!setup.module)
+ return -ENOMEM;
+
+ setup.video = settings_new(args->video);
+ if (!setup.video) {
+ settings_free(setup.module);
+
+ return -ENOMEM;
+ }
+
+ r = setup_interactively(setup.module, rototiller_module_setup, args->use_defaults);
+ if (r < 0) {
+ settings_free(setup.module);
+ settings_free(setup.video);
+
+ return r;
+ }
+
+ if (r)
+ changes = 1;
+
+ r = setup_interactively(setup.video, setup_video, args->use_defaults);
+ if (r < 0) {
+ settings_free(setup.module);
+ settings_free(setup.video);
+
+ return r;
+ }
+
+ if (r)
+ changes = 1;
+
+ *res_setup = setup;
+
+ return changes;
+}
+
+
+static int print_setup_as_args(setup_t *setup)
+{
+ char *module_args, *video_args;
+ char buf[64];
+ int r;
+
+ module_args = settings_as_arg(setup->module);
+ if (!module_args) {
+ r = -ENOMEM;
+
+ goto _out;
+ }
+
+ video_args = settings_as_arg(setup->video);
+ if (!video_args) {
+ r = -ENOMEM;
+
+ goto _out_module;
+ }
+
+ r = printf("\nConfigured settings as flags:\n --module=%s --video=%s\n\nPress enter to continue...\n",
+ module_args,
+ video_args);
+
+ if (r < 0)
+ goto _out_video;
+
+ (void) fgets(buf, sizeof(buf), stdin);
+
+_out_video:
+ free(video_args);
+_out_module:
+ free(module_args);
+_out:
+ return r;
+}
+
+
+static int print_help(void)
+{
+ return printf(
+ "Run without any flags or partial settings for interactive mode.\n"
+ "\n"
+ "Supported flags:\n"
+ " --defaults use defaults for unspecified settings\n"
+ " --help this help\n"
+ " --module= module settings\n"
+ " --video= video settings\n"
+ );
+}
+
+
+static unsigned get_ticks(const struct timeval *start, const struct timeval *now, unsigned offset)
+{
+ return (unsigned)((now->tv_sec - start->tv_sec) * 1000 + (now->tv_usec - start->tv_usec) / 1000) + offset;
+}
+
+
+static void * rototiller_thread(void *_rt)
+{
+ rototiller_t *rt = _rt;
+ struct timeval now;
+
+ for (;;) {
+ fb_page_t *page;
+ unsigned ticks;
+
+ page = fb_page_get(rt->fb);
+
+ gettimeofday(&now, NULL);
+ ticks = get_ticks(&rt->start_tv, &now, rt->ticks_offset);
+
+ rototiller_module_render(rt->module, rt->module_context, ticks, &page->fragment);
+
+ fb_page_put(rt->fb, page);
+ }
+
+ return NULL;
+}
+
+
+/* When run with partial/no arguments, if stdin is a tty, enter an interactive setup.
+ * If stdin is not a tty, or if --defaults is supplied in argv, default settings are used.
+ * If any changes to the settings occur in the course of execution, either interactively or
+ * throught --defaults, then print out the explicit CLI invocation usable for reproducing
+ * the invocation.
+ */
+int main(int argc, const char *argv[])
+{
+ setup_t setup = {};
+ argv_t args = {};
+ int r;
+
+ exit_if(parse_argv(argc, argv, &args) < 0,
+ "unable to process arguments");
+
+ if (args.help)
+ return print_help() < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+
+ exit_if((r = setup_from_args(&args, &setup)) < 0,
+ "unable to setup: %s", strerror(-r));
+
+ exit_if(r && print_setup_as_args(&setup) < 0,
+ "unable to print setup");
+
+ exit_if(!(rototiller.module = rototiller_lookup_module(settings_get_key(setup.module, 0))),
+ "unable to lookup module from settings \"%s\"", settings_get_key(setup.module, 0));
+
+ exit_if((r = fb_new(fb_ops, setup.video, NUM_FB_PAGES, &rototiller.fb)) < 0,
+ "unable to create fb: %s", strerror(-r));
+
+ exit_if(!fps_setup(),
+ "unable to setup fps counter");
+
+ exit_if((r = rototiller_init()) < 0,
+ "unable to initialize librototiller: %s", strerror(-r));
+
+ gettimeofday(&rototiller.start_tv, NULL);
+ exit_if((r = rototiller_module_create_context(
+ rototiller.module,
+ get_ticks(&rototiller.start_tv,
+ &rototiller.start_tv,
+ rototiller.ticks_offset),
+ &rototiller.module_context)) < 0,
+ "unable to create module context: %s", strerror(-r));
+
+ pexit_if(pthread_create(&rototiller.thread, NULL, rototiller_thread, &rototiller) != 0,
+ "unable to create dispatch thread");
+
+ for (;;) {
+ if (fb_flip(rototiller.fb) < 0)
+ break;
+
+ fps_print(rototiller.fb);
+ }
+
+ pthread_cancel(rototiller.thread);
+ pthread_join(rototiller.thread, NULL);
+ rototiller_shutdown();
+
+ if (rototiller.module_context)
+ rototiller.module->destroy_context(rototiller.module_context);
+
+ fb_free(rototiller.fb);
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/modules/compose/Makefile.am b/src/modules/compose/Makefile.am
index 926db7e..e77bf69 100644
--- a/src/modules/compose/Makefile.am
+++ b/src/modules/compose/Makefile.am
@@ -1,3 +1,3 @@
-noinst_LIBRARIES = libcompose.a
-libcompose_a_SOURCES = compose.c
-libcompose_a_CPPFLAGS = -I@top_srcdir@/src -I@top_srcdir@/src/libs
+noinst_LTLIBRARIES = libcompose.la
+libcompose_la_SOURCES = compose.c
+libcompose_la_CPPFLAGS = -I@top_srcdir@/src -I@top_srcdir@/src/libs
diff --git a/src/modules/drizzle/Makefile.am b/src/modules/drizzle/Makefile.am
index caaa45f..a6bb00b 100644
--- a/src/modules/drizzle/Makefile.am
+++ b/src/modules/drizzle/Makefile.am
@@ -1,3 +1,3 @@
-noinst_LIBRARIES = libdrizzle.a
-libdrizzle_a_SOURCES = drizzle.c
-libdrizzle_a_CPPFLAGS = -I@top_srcdir@/src -I@top_srcdir@/src/libs
+noinst_LTLIBRARIES = libdrizzle.la
+libdrizzle_la_SOURCES = drizzle.c
+libdrizzle_la_CPPFLAGS = -I@top_srcdir@/src -I@top_srcdir@/src/libs
diff --git a/src/modules/flui2d/Makefile.am b/src/modules/flui2d/Makefile.am
index 239de9e..90fc109 100644
--- a/src/modules/flui2d/Makefile.am
+++ b/src/modules/flui2d/Makefile.am
@@ -1,3 +1,3 @@
-noinst_LIBRARIES = libflui2d.a
-libflui2d_a_SOURCES = flui2d.c
-libflui2d_a_CPPFLAGS = -I@top_srcdir@/src
+noinst_LTLIBRARIES = libflui2d.la
+libflui2d_la_SOURCES = flui2d.c
+libflui2d_la_CPPFLAGS = -I@top_srcdir@/src
diff --git a/src/modules/julia/Makefile.am b/src/modules/julia/Makefile.am
index 8e94f14..a61bad8 100644
--- a/src/modules/julia/Makefile.am
+++ b/src/modules/julia/Makefile.am
@@ -1,3 +1,3 @@
-noinst_LIBRARIES = libjulia.a
-libjulia_a_SOURCES = julia.c
-libjulia_a_CPPFLAGS = -I@top_srcdir@/src
+noinst_LTLIBRARIES = libjulia.la
+libjulia_la_SOURCES = julia.c
+libjulia_la_CPPFLAGS = -I@top_srcdir@/src
diff --git a/src/modules/meta2d/Makefile.am b/src/modules/meta2d/Makefile.am
index b1394d1..73b00f4 100644
--- a/src/modules/meta2d/Makefile.am
+++ b/src/modules/meta2d/Makefile.am
@@ -1,3 +1,3 @@
-noinst_LIBRARIES = libmeta2d.a
-libmeta2d_a_SOURCES = meta2d.c v2f.h v3f.h
-libmeta2d_a_CPPFLAGS = -I@top_srcdir@/src -I@top_srcdir@/src/libs
+noinst_LTLIBRARIES = libmeta2d.la
+libmeta2d_la_SOURCES = meta2d.c v2f.h v3f.h
+libmeta2d_la_CPPFLAGS = -I@top_srcdir@/src -I@top_srcdir@/src/libs
diff --git a/src/modules/montage/Makefile.am b/src/modules/montage/Makefile.am
index 7465510..0c2c376 100644
--- a/src/modules/montage/Makefile.am
+++ b/src/modules/montage/Makefile.am
@@ -1,3 +1,3 @@
-noinst_LIBRARIES = libmontage.a
-libmontage_a_SOURCES = montage.c
-libmontage_a_CPPFLAGS = -I@top_srcdir@/src -I@top_srcdir@/src/libs
+noinst_LTLIBRARIES = libmontage.la
+libmontage_la_SOURCES = montage.c
+libmontage_la_CPPFLAGS = -I@top_srcdir@/src -I@top_srcdir@/src/libs
diff --git a/src/modules/pixbounce/Makefile.am b/src/modules/pixbounce/Makefile.am
index a55374a..6464dcb 100644
--- a/src/modules/pixbounce/Makefile.am
+++ b/src/modules/pixbounce/Makefile.am
@@ -1,3 +1,3 @@
-noinst_LIBRARIES = libpixbounce.a
-libpixbounce_a_SOURCES = draw.h pixbounce.c
-libpixbounce_a_CPPFLAGS = -I@top_srcdir@/src
+noinst_LTLIBRARIES = libpixbounce.la
+libpixbounce_la_SOURCES = draw.h pixbounce.c
+libpixbounce_la_CPPFLAGS = -I@top_srcdir@/src
diff --git a/src/modules/plasma/Makefile.am b/src/modules/plasma/Makefile.am
index a856df1..edb3760 100644
--- a/src/modules/plasma/Makefile.am
+++ b/src/modules/plasma/Makefile.am
@@ -1,3 +1,3 @@
-noinst_LIBRARIES = libplasma.a
-libplasma_a_SOURCES = plasma.c
-libplasma_a_CPPFLAGS = -I@top_srcdir@/src
+noinst_LTLIBRARIES = libplasma.la
+libplasma_la_SOURCES = plasma.c
+libplasma_la_CPPFLAGS = -I@top_srcdir@/src
diff --git a/src/modules/plato/Makefile.am b/src/modules/plato/Makefile.am
index d0b9069..b0550d8 100644
--- a/src/modules/plato/Makefile.am
+++ b/src/modules/plato/Makefile.am
@@ -1,3 +1,3 @@
-noinst_LIBRARIES = libplato.a
-libplato_a_SOURCES = plato.c
-libplato_a_CPPFLAGS = -I@top_srcdir@/src -I@top_srcdir@/src/libs
+noinst_LTLIBRARIES = libplato.la
+libplato_la_SOURCES = plato.c
+libplato_la_CPPFLAGS = -I@top_srcdir@/src -I@top_srcdir@/src/libs
diff --git a/src/modules/ray/Makefile.am b/src/modules/ray/Makefile.am
index 637a921..f20850a 100644
--- a/src/modules/ray/Makefile.am
+++ b/src/modules/ray/Makefile.am
@@ -1,4 +1,4 @@
-noinst_LIBRARIES = libray.a
-libray_a_SOURCES = ray.c
-libray_a_CFLAGS = -ffast-math
-libray_a_CPPFLAGS = -I@top_srcdir@/src -I@top_srcdir@/src/libs
+noinst_LTLIBRARIES = libray.la
+libray_la_SOURCES = ray.c
+libray_la_CFLAGS = -ffast-math
+libray_la_CPPFLAGS = -I@top_srcdir@/src -I@top_srcdir@/src/libs
diff --git a/src/modules/roto/Makefile.am b/src/modules/roto/Makefile.am
index 6682751..2b704c1 100644
--- a/src/modules/roto/Makefile.am
+++ b/src/modules/roto/Makefile.am
@@ -1,3 +1,3 @@
-noinst_LIBRARIES = libroto.a
-libroto_a_SOURCES = roto.c
-libroto_a_CPPFLAGS = -I@top_srcdir@/src
+noinst_LTLIBRARIES = libroto.la
+libroto_la_SOURCES = roto.c
+libroto_la_CPPFLAGS = -I@top_srcdir@/src
diff --git a/src/modules/rtv/Makefile.am b/src/modules/rtv/Makefile.am
index 4d5cb6e..8a4f341 100644
--- a/src/modules/rtv/Makefile.am
+++ b/src/modules/rtv/Makefile.am
@@ -1,3 +1,3 @@
-noinst_LIBRARIES = librtv.a
-librtv_a_SOURCES = rtv.c
-librtv_a_CPPFLAGS = -I@top_srcdir@/src -I@top_srcdir@/src/libs
+noinst_LTLIBRARIES = librtv.la
+librtv_la_SOURCES = rtv.c
+librtv_la_CPPFLAGS = -I@top_srcdir@/src -I@top_srcdir@/src/libs
diff --git a/src/modules/snow/Makefile.am b/src/modules/snow/Makefile.am
index 73f767d..d4a602a 100644
--- a/src/modules/snow/Makefile.am
+++ b/src/modules/snow/Makefile.am
@@ -1,3 +1,3 @@
-noinst_LIBRARIES = libsnow.a
-libsnow_a_SOURCES = snow.c
-libsnow_a_CPPFLAGS = -I@top_srcdir@/src
+noinst_LTLIBRARIES = libsnow.la
+libsnow_la_SOURCES = snow.c
+libsnow_la_CPPFLAGS = -I@top_srcdir@/src
diff --git a/src/modules/sparkler/Makefile.am b/src/modules/sparkler/Makefile.am
index 40a9bc8..f056aac 100644
--- a/src/modules/sparkler/Makefile.am
+++ b/src/modules/sparkler/Makefile.am
@@ -1,4 +1,4 @@
-noinst_LIBRARIES = libsparkler.a
-libsparkler_a_SOURCES = bsp.c bsp.h burst.c chunker.c chunker.h container.h list.h particle.c particle.h particles.c particles.h rocket.c simple.c spark.c sparkler.c v3f.h xplode.c
-libsparkler_a_CFLAGS = -ffast-math
-libsparkler_a_CPPFLAGS = -I@top_srcdir@/src
+noinst_LTLIBRARIES = libsparkler.la
+libsparkler_la_SOURCES = bsp.c bsp.h burst.c chunker.c chunker.h container.h list.h particle.c particle.h particles.c particles.h rocket.c simple.c spark.c sparkler.c v3f.h xplode.c
+libsparkler_la_CFLAGS = -ffast-math
+libsparkler_la_CPPFLAGS = -I@top_srcdir@/src
diff --git a/src/modules/spiro/Makefile.am b/src/modules/spiro/Makefile.am
index f03d8cd..0f8a543 100644
--- a/src/modules/spiro/Makefile.am
+++ b/src/modules/spiro/Makefile.am
@@ -1,3 +1,3 @@
-noinst_LIBRARIES = libspiro.a
-libspiro_a_SOURCES = draw.h spiro.c
-libspiro_a_CPPFLAGS = -I@top_srcdir@/src
+noinst_LTLIBRARIES = libspiro.la
+libspiro_la_SOURCES = draw.h spiro.c
+libspiro_la_CPPFLAGS = -I@top_srcdir@/src
diff --git a/src/modules/stars/Makefile.am b/src/modules/stars/Makefile.am
index 20ee80e..ebeb4dd 100644
--- a/src/modules/stars/Makefile.am
+++ b/src/modules/stars/Makefile.am
@@ -1,3 +1,3 @@
-noinst_LIBRARIES = libstars.a
-libstars_a_SOURCES = draw.h stars.c
-libstars_a_CPPFLAGS = -I@top_srcdir@/src
+noinst_LTLIBRARIES = libstars.la
+libstars_la_SOURCES = draw.h stars.c
+libstars_la_CPPFLAGS = -I@top_srcdir@/src
diff --git a/src/modules/submit/Makefile.am b/src/modules/submit/Makefile.am
index d8a02e4..23a2fda 100644
--- a/src/modules/submit/Makefile.am
+++ b/src/modules/submit/Makefile.am
@@ -1,3 +1,3 @@
-noinst_LIBRARIES = libsubmit.a
-libsubmit_a_SOURCES = submit.c
-libsubmit_a_CPPFLAGS = -I@top_srcdir@/src -I@top_srcdir@/src/libs
+noinst_LTLIBRARIES = libsubmit.la
+libsubmit_la_SOURCES = submit.c
+libsubmit_la_CPPFLAGS = -I@top_srcdir@/src -I@top_srcdir@/src/libs
diff --git a/src/modules/swab/Makefile.am b/src/modules/swab/Makefile.am
index 4db914b..c99265a 100644
--- a/src/modules/swab/Makefile.am
+++ b/src/modules/swab/Makefile.am
@@ -1,3 +1,3 @@
-noinst_LIBRARIES = libswab.a
-libswab_a_SOURCES = swab.c
-libswab_a_CPPFLAGS = -I@top_srcdir@/src -I@top_srcdir@/src/libs
+noinst_LTLIBRARIES = libswab.la
+libswab_la_SOURCES = swab.c
+libswab_la_CPPFLAGS = -I@top_srcdir@/src -I@top_srcdir@/src/libs
diff --git a/src/modules/swarm/Makefile.am b/src/modules/swarm/Makefile.am
index 327aee8..555bd8e 100644
--- a/src/modules/swarm/Makefile.am
+++ b/src/modules/swarm/Makefile.am
@@ -1,3 +1,3 @@
-noinst_LIBRARIES = libswarm.a
-libswarm_a_SOURCES = swarm.c
-libswarm_a_CPPFLAGS = -I@top_srcdir@/src -I@top_srcdir@/src/libs
+noinst_LTLIBRARIES = libswarm.la
+libswarm_la_SOURCES = swarm.c
+libswarm_la_CPPFLAGS = -I@top_srcdir@/src -I@top_srcdir@/src/libs
diff --git a/src/rototiller.c b/src/rototiller.c
index 84898da..18f0376 100644
--- a/src/rototiller.c
+++ b/src/rototiller.c
@@ -11,27 +11,16 @@
#include <unistd.h>
#include "settings.h"
-#include "setup.h"
#include "fb.h"
-#include "fps.h"
#include "rototiller.h"
#include "threads.h"
#include "util.h"
/* Copyright (C) 2016 Vito Caputo <vcaputo@pengaru.com> */
-#define NUM_FB_PAGES 3
-/* ^ By triple-buffering, we can have a page tied up being displayed, another
- * tied up submitted and waiting for vsync, and still not block on getting
- * another page so we can begin rendering another frame before vsync. With
- * just two pages we end up twiddling thumbs until the vsync arrives.
- */
#define DEFAULT_MODULE "rtv"
-#define DEFAULT_VIDEO "sdl"
-extern fb_ops_t drm_fb_ops;
-extern fb_ops_t sdl_fb_ops;
-fb_ops_t *fb_ops;
+static threads_t *rototiller_threads;
extern rototiller_module_t compose_module;
extern rototiller_module_t drizzle_module;
@@ -75,17 +64,21 @@ static const rototiller_module_t *modules[] = {
&swarm_module,
};
-typedef struct rototiller_t {
- const rototiller_module_t *module;
- void *module_context;
- threads_t *threads;
- pthread_t thread;
- fb_t *fb;
- struct timeval start_tv;
- unsigned ticks_offset;
-} rototiller_t;
-static rototiller_t rototiller;
+/* initialize rototiller (create rendering threads) */
+int rototiller_init(void)
+{
+ if (!(rototiller_threads = threads_create()))
+ return -errno;
+
+ return 0;
+}
+
+
+void rototiller_shutdown(void)
+{
+ threads_destroy(rototiller_threads);
+}
const rototiller_module_t * rototiller_lookup_module(const char *name)
@@ -113,6 +106,10 @@ void rototiller_get_modules(const rototiller_module_t ***res_modules, size_t *re
static void module_render_fragment(const rototiller_module_t *module, void *context, threads_t *threads, unsigned ticks, fb_fragment_t *fragment)
{
+ assert(module);
+ assert(threads);
+ assert(fragment);
+
if (module->prepare_frame) {
rototiller_fragmenter_t fragmenter;
@@ -136,114 +133,31 @@ static void module_render_fragment(const rototiller_module_t *module, void *cont
*/
void rototiller_module_render(const rototiller_module_t *module, void *context, unsigned ticks, fb_fragment_t *fragment)
{
- module_render_fragment(module, context, rototiller.threads, ticks, fragment);
+ module_render_fragment(module, context, rototiller_threads, ticks, fragment);
}
-
-typedef struct argv_t {
- const char *module;
- const char *video;
-
- unsigned use_defaults:1;
- unsigned help:1;
-} argv_t;
-
-/*
- * ./rototiller --video=drm,dev=/dev/dri/card3,connector=VGA-1,mode=640x480@60
- * ./rototiller --video=sdl,size=640x480
- * ./rototiller --module=roto,foo=bar,module=settings
- * ./rototiller --defaults
- */
-static int parse_argv(int argc, const char *argv[], argv_t *res_args)
+int rototiller_module_create_context(const rototiller_module_t *module, unsigned ticks, void **res_context)
{
- int i;
-
- assert(argc > 0);
- assert(argv);
- assert(res_args);
-
- /* this is intentionally being kept very simple, no new dependencies like getopt. */
-
- for (i = 1; i < argc; i++) {
- if (!strncmp("--video=", argv[i], 8)) {
- res_args->video = &argv[i][8];
- } else if (!strncmp("--module=", argv[i], 9)) {
- res_args->module = &argv[i][9];
- } else if (!strcmp("--defaults", argv[i])) {
- res_args->use_defaults = 1;
- } else if (!strcmp("--help", argv[i])) {
- res_args->help = 1;
- } else {
- return -EINVAL;
- }
- }
-
- return 0;
-}
-
+ void *context;
-typedef struct setup_t {
- settings_t *module;
- settings_t *video;
-} setup_t;
+ assert(module);
+ assert(res_context);
-/* FIXME: this is unnecessarily copy-pasta, i think modules should just be made
- * more generic to encompass the setting up uniformly, then basically
- * subclass the video backend vs. renderer stuff.
- */
+ if (!module->create_context)
+ return 0;
-/* select video backend if not yet selected, then setup the selected backend. */
-static int setup_video(settings_t *settings, setting_desc_t **next_setting)
-{
- const char *video;
-
- /* XXX: there's only one option currently, so this is simple */
- video = settings_get_key(settings, 0);
- if (!video) {
- setting_desc_t *desc;
- const char *values[] = {
-#ifdef HAVE_DRM
- "drm",
-#endif
- "sdl",
- NULL,
- };
- int r;
-
- r = setting_desc_clone(&(setting_desc_t){
- .name = "Video Backend",
- .key = NULL,
- .regex = "[a-z]+",
- .preferred = DEFAULT_VIDEO,
- .values = values,
- .annotations = NULL
- }, next_setting);
- if (r < 0)
- return r;
-
- return 1;
- }
-
- /* XXX: this is kind of hacky for now */
-#ifdef HAVE_DRM
- if (!strcmp(video, "drm")) {
- fb_ops = &drm_fb_ops;
-
- return drm_fb_ops.setup(settings, next_setting);
- } else
-#endif
- if (!strcmp(video, "sdl")) {
- fb_ops = &sdl_fb_ops;
+ context = module->create_context(ticks, threads_num_threads(rototiller_threads));
+ if (!context)
+ return -ENOMEM;
- return sdl_fb_ops.setup(settings, next_setting);
- }
+ *res_context = context;
- return -EINVAL;
+ return 0;
}
/* select module if not yet selected, then setup the module. */
-static int setup_module(settings_t *settings, setting_desc_t **next_setting)
+int rototiller_module_setup(settings_t *settings, setting_desc_t **next_setting)
{
const rototiller_module_t *module;
const char *name;
@@ -284,198 +198,3 @@ static int setup_module(settings_t *settings, setting_desc_t **next_setting)
return 0;
}
-
-
-/* turn args into settings, automatically applying defaults if appropriate, or interactively if appropriate. */
-/* returns negative value on error, 0 when settings unchanged from args, 1 when changed */
-static int setup_from_args(argv_t *args, setup_t *res_setup)
-{
- int r, changes = 0;
- setup_t setup;
-
- setup.module = settings_new(args->module);
- if (!setup.module)
- return -ENOMEM;
-
- setup.video = settings_new(args->video);
- if (!setup.video) {
- settings_free(setup.module);
-
- return -ENOMEM;
- }
-
- r = setup_interactively(setup.module, setup_module, args->use_defaults);
- if (r < 0) {
- settings_free(setup.module);
- settings_free(setup.video);
-
- return r;
- }
-
- if (r)
- changes = 1;
-
- r = setup_interactively(setup.video, setup_video, args->use_defaults);
- if (r < 0) {
- settings_free(setup.module);
- settings_free(setup.video);
-
- return r;
- }
-
- if (r)
- changes = 1;
-
- *res_setup = setup;
-
- return changes;
-}
-
-
-static int print_setup_as_args(setup_t *setup)
-{
- char *module_args, *video_args;
- char buf[64];
- int r;
-
- module_args = settings_as_arg(setup->module);
- if (!module_args) {
- r = -ENOMEM;
-
- goto _out;
- }
-
- video_args = settings_as_arg(setup->video);
- if (!video_args) {
- r = -ENOMEM;
-
- goto _out_module;
- }
-
- r = printf("\nConfigured settings as flags:\n --module=%s --video=%s\n\nPress enter to continue...\n",
- module_args,
- video_args);
-
- if (r < 0)
- goto _out_video;
-
- (void) fgets(buf, sizeof(buf), stdin);
-
-_out_video:
- free(video_args);
-_out_module:
- free(module_args);
-_out:
- return r;
-}
-
-
-static int print_help(void)
-{
- return printf(
- "Run without any flags or partial settings for interactive mode.\n"
- "\n"
- "Supported flags:\n"
- " --defaults use defaults for unspecified settings\n"
- " --help this help\n"
- " --module= module settings\n"
- " --video= video settings\n"
- );
-}
-
-
-static unsigned get_ticks(const struct timeval *start, const struct timeval *now, unsigned offset)
-{
- return (unsigned)((now->tv_sec - start->tv_sec) * 1000 + (now->tv_usec - start->tv_usec) / 1000) + offset;
-}
-
-
-static void * rototiller_thread(void *_rt)
-{
- rototiller_t *rt = _rt;
- struct timeval now;
-
- for (;;) {
- fb_page_t *page;
- unsigned ticks;
-
- page = fb_page_get(rt->fb);
-
- gettimeofday(&now, NULL);
- ticks = get_ticks(&rt->start_tv, &now, rt->ticks_offset);
-
- module_render_fragment(rt->module, rt->module_context, rt->threads, ticks, &page->fragment);
-
- fb_page_put(rt->fb, page);
- }
-
- return NULL;
-}
-
-
-/* When run with partial/no arguments, if stdin is a tty, enter an interactive setup.
- * If stdin is not a tty, or if --defaults is supplied in argv, default settings are used.
- * If any changes to the settings occur in the course of execution, either interactively or
- * throught --defaults, then print out the explicit CLI invocation usable for reproducing
- * the invocation.
- */
-int main(int argc, const char *argv[])
-{
- setup_t setup = {};
- argv_t args = {};
- int r;
-
- exit_if(parse_argv(argc, argv, &args) < 0,
- "unable to process arguments");
-
- if (args.help)
- return print_help() < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
-
- exit_if((r = setup_from_args(&args, &setup)) < 0,
- "unable to setup: %s", strerror(-r));
-
- exit_if(r && print_setup_as_args(&setup) < 0,
- "unable to print setup");
-
- exit_if(!(rototiller.module = rototiller_lookup_module(settings_get_key(setup.module, 0))),
- "unable to lookup module from settings \"%s\"", settings_get_key(setup.module, 0));
-
- exit_if((r = fb_new(fb_ops, setup.video, NUM_FB_PAGES, &rototiller.fb)) < 0,
- "unable to create fb: %s", strerror(-r));
-
- exit_if(!fps_setup(),
- "unable to setup fps counter");
-
- pexit_if(!(rototiller.threads = threads_create()),
- "unable to create rendering threads");
-
- gettimeofday(&rototiller.start_tv, NULL);
- exit_if(rototiller.module->create_context &&
- !(rototiller.module_context = rototiller.module->create_context(
- get_ticks(&rototiller.start_tv,
- &rototiller.start_tv,
- rototiller.ticks_offset),
- threads_num_threads(rototiller.threads))),
- "unable to create module context");
-
- pexit_if(pthread_create(&rototiller.thread, NULL, rototiller_thread, &rototiller) != 0,
- "unable to create dispatch thread");
-
- for (;;) {
- if (fb_flip(rototiller.fb) < 0)
- break;
-
- fps_print(rototiller.fb);
- }
-
- pthread_cancel(rototiller.thread);
- pthread_join(rototiller.thread, NULL);
- threads_destroy(rototiller.threads);
-
- if (rototiller.module_context)
- rototiller.module->destroy_context(rototiller.module_context);
-
- fb_free(rototiller.fb);
-
- return EXIT_SUCCESS;
-}
diff --git a/src/rototiller.h b/src/rototiller.h
index e185624..fde7d43 100644
--- a/src/rototiller.h
+++ b/src/rototiller.h
@@ -25,8 +25,12 @@ typedef struct rototiller_module_t {
char *license;
} rototiller_module_t;
+int rototiller_init(void);
+void rototiller_shutdown(void);
const rototiller_module_t * rototiller_lookup_module(const char *name);
void rototiller_get_modules(const rototiller_module_t ***res_modules, size_t *res_n_modules);
void rototiller_module_render(const rototiller_module_t *module, void *context, unsigned ticks, fb_fragment_t *fragment);
+int rototiller_module_create_context(const rototiller_module_t *module, unsigned ticks, void **res_context);
+int rototiller_module_setup(settings_t *settings, setting_desc_t **next_setting);
#endif
© All Rights Reserved