summaryrefslogtreecommitdiff
path: root/src/mem_fb.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mem_fb.c')
-rw-r--r--src/mem_fb.c166
1 files changed, 166 insertions, 0 deletions
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