diff options
Diffstat (limited to 'src/mem_fb.c')
-rw-r--r-- | src/mem_fb.c | 166 |
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 +}; |