summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am2
-rw-r--r--src/main.c7
-rw-r--r--src/mem_fb.c166
3 files changed, 174 insertions, 1 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 65b7626..89120ad 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -7,7 +7,7 @@ libtil_la_LIBADD = modules/blinds/libblinds.la modules/checkers/libcheckers.la m
if ENABLE_ROTOTILLER
bin_PROGRAMS = rototiller
-rototiller_SOURCES = fps.c fps.h main.c setup.h setup.c til.h til_fb.c til_fb.h til_knobs.h til_settings.c til_settings.h til_threads.c til_threads.h til_util.c til_util.h
+rototiller_SOURCES = fps.c fps.h main.c mem_fb.c setup.h setup.c til.h til_fb.c til_fb.h til_knobs.h til_settings.c til_settings.h til_threads.c til_threads.h til_util.c til_util.h
if ENABLE_SDL
rototiller_SOURCES += sdl_fb.c
endif
diff --git a/src/main.c b/src/main.c
index 68ff1da..c22eb3c 100644
--- a/src/main.c
+++ b/src/main.c
@@ -34,6 +34,7 @@
#endif
extern til_fb_ops_t drm_fb_ops;
+extern til_fb_ops_t mem_fb_ops;
extern til_fb_ops_t sdl_fb_ops;
static til_fb_ops_t *fb_ops;
@@ -74,6 +75,7 @@ static int setup_video(til_settings_t *settings, til_setting_t **res_setting, co
#ifdef HAVE_DRM
"drm",
#endif
+ "mem",
#ifdef HAVE_SDL
"sdl",
#endif
@@ -106,6 +108,11 @@ static int setup_video(til_settings_t *settings, til_setting_t **res_setting, co
return drm_fb_ops.setup(settings, res_setting, res_desc, res_setup);
}
#endif
+ if (!strcasecmp(video, "mem")) {
+ fb_ops = &mem_fb_ops;
+
+ return mem_fb_ops.setup(settings, res_setting, res_desc, res_setup);
+ }
#ifdef HAVE_SDL
if (!strcasecmp(video, "sdl")) {
fb_ops = &sdl_fb_ops;
diff --git a/src/mem_fb.c b/src/mem_fb.c
new file mode 100644
index 0000000..a564c1f
--- /dev/null
+++ b/src/mem_fb.c
@@ -0,0 +1,166 @@
+#include <assert.h>
+#include <stdlib.h>
+
+#include "til_fb.h"
+#include "til_settings.h"
+#include "til_util.h"
+
+/* dummy mem_fb backend; render to anonymous memory */
+/* useful for testing/debugging, and benchmarking systems even if headless */
+
+typedef struct mem_fb_page_t mem_fb_page_t;
+
+struct mem_fb_page_t {
+ void *unused;
+ uint32_t buf[];
+};
+
+typedef struct mem_fb_setup_t {
+ til_setup_t til_setup;
+ unsigned width, height;
+} mem_fb_setup_t;
+
+typedef struct mem_fb_t {
+ mem_fb_setup_t setup;
+} mem_fb_t;
+
+
+static int mem_fb_setup(const til_settings_t *settings, til_setting_t **res_setting, const til_setting_desc_t **res_desc, til_setup_t **res_setup)
+{
+ const char *size;
+ int r;
+
+ r = til_settings_get_and_describe_value(settings,
+ &(til_setting_desc_t){
+ .name = "Virtual window size",
+ .key = "size",
+ .regex = "[1-9][0-9]*[xX][1-9][0-9]*",
+ .preferred = "640x480",
+ .values = NULL,
+ .annotations = NULL
+ },
+ &size,
+ res_setting,
+ res_desc);
+ if (r)
+ return r;
+
+ if (res_setup) {
+ mem_fb_setup_t *setup;
+
+ setup = til_setup_new(sizeof(*setup), (void(*)(til_setup_t *))free);
+ if (!setup)
+ return -ENOMEM;
+
+ /* TODO FIXME: parse errors */
+ sscanf(size, "%ux%u", &setup->width, &setup->height);
+
+ *res_setup = &setup->til_setup;
+ }
+
+ return 0;
+}
+
+
+static int mem_fb_init(const til_setup_t *setup, void **res_context)
+{
+ mem_fb_t *c;
+ int r;
+
+ assert(setup);
+ assert(res_context);
+
+ c = calloc(1, sizeof(mem_fb_t));
+ if (!c) {
+ r = -ENOMEM;
+ goto _err;
+ }
+
+ c->setup = *(mem_fb_setup_t *)setup;
+
+ *res_context = c;
+
+ return 0;
+
+_err:
+ return r;
+}
+
+
+static void mem_fb_shutdown(til_fb_t *fb, void *context)
+{
+ mem_fb_t *c = context;
+
+ assert(c);
+
+ free(c);
+}
+
+
+static int mem_fb_acquire(til_fb_t *fb, void *context, void *page)
+{
+ mem_fb_t *c = context;
+ mem_fb_page_t *p = page;
+
+ return 0;
+}
+
+
+static void mem_fb_release(til_fb_t *fb, void *context)
+{
+}
+
+
+static void * mem_fb_page_alloc(til_fb_t *fb, void *context, til_fb_page_t *res_page)
+{
+ mem_fb_t *c = context;
+ mem_fb_page_t *p;
+
+ p = calloc(1, sizeof(mem_fb_page_t) + c->setup.width * c->setup.height * sizeof(uint32_t));
+ if (!p)
+ return NULL;
+
+ *res_page = (til_fb_page_t){
+ .fragment.buf = p->buf,
+ .fragment.width = c->setup.width,
+ .fragment.frame_width = c->setup.width,
+ .fragment.height = c->setup.height,
+ .fragment.frame_height = c->setup.height,
+ .fragment.pitch = c->setup.width,
+ };
+
+ return p;
+}
+
+
+static int mem_fb_page_free(til_fb_t *fb, void *context, void *page)
+{
+ mem_fb_t *c = context;
+ mem_fb_page_t *p = page;
+
+ free(p);
+
+ return 0;
+}
+
+
+static int mem_fb_page_flip(til_fb_t *fb, void *context, void *page)
+{
+ mem_fb_t *c = context;
+ mem_fb_page_t *p = page;
+
+ /* TODO: add a timer for supporting an fps setting? */
+ return 0;
+}
+
+
+til_fb_ops_t mem_fb_ops = {
+ .setup = mem_fb_setup,
+ .init = mem_fb_init,
+ .shutdown = mem_fb_shutdown,
+ .acquire = mem_fb_acquire,
+ .release = mem_fb_release,
+ .page_alloc = mem_fb_page_alloc,
+ .page_free = mem_fb_page_free,
+ .page_flip = mem_fb_page_flip
+};
© All Rights Reserved