diff options
author | Vito Caputo <vcaputo@pengaru.com> | 2018-01-02 00:49:29 -0800 |
---|---|---|
committer | Vito Caputo <vcaputo@pengaru.com> | 2018-02-22 14:26:05 -0800 |
commit | d58d959a94f24fa6f496380b1f085cda48560a63 (patch) | |
tree | 4b7ba5ed50312d0c3eb49571b5fe42d507275a45 | |
parent | 6e687a50a93ae780b5a7cbc03193f40f6e80eaa6 (diff) |
sdl_fb: implement rudimentary sdl fb backend
This uses a simple fixed 640x480 windowed mode (for now).
The SDL2 Renderer & Texture API is used for vsync-synchronized presents.
There's probably excessive copying going on because the rototiller fb
code manages pages and flips but SDL2 doesn't really expose low-level
control of such things.
This backend is quite useful for development purposes, allowing quick
iteration in a windowed environment.
Note this is just the backend implementation, it's dormant code but
trivially activated.
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/sdl_fb.c | 155 | ||||
-rw-r--r-- | src/sdl_fb.h | 9 |
3 files changed, 165 insertions, 1 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index a9cee3e..fe57d8c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,5 +1,5 @@ SUBDIRS = modules bin_PROGRAMS = rototiller -rototiller_SOURCES = drm_fb.c drm_fb.h fb.c fb.h fps.c fps.h rototiller.c rototiller.h settings.h settings.c setup.h setup.c threads.c threads.h util.c util.h +rototiller_SOURCES = drm_fb.c drm_fb.h fb.c fb.h fps.c fps.h rototiller.c rototiller.h sdl_fb.c sdl_fb.h settings.h settings.c setup.h setup.c threads.c threads.h util.c util.h rototiller_LDADD = @ROTOTILLER_LIBS@ -lm modules/julia/libjulia.a modules/plasma/libplasma.a modules/ray/libray.a modules/roto/libroto.a modules/sparkler/libsparkler.a modules/stars/libstars.a rototiller_CPPFLAGS = @ROTOTILLER_CFLAGS@ diff --git a/src/sdl_fb.c b/src/sdl_fb.c new file mode 100644 index 0000000..7047f4a --- /dev/null +++ b/src/sdl_fb.c @@ -0,0 +1,155 @@ +#include <SDL.h> +#include <stdlib.h> +#include <errno.h> + +#include "fb.h" +#include "settings.h" + + +/* sdl fb backend, everything sdl-specific in rototiller resides here. */ + +typedef struct sdl_fb_t { + SDL_Window *window; + SDL_Renderer *renderer; + SDL_Texture *texture; +} sdl_fb_t; + +typedef struct sdl_fb_page_t sdl_fb_page_t; + +struct sdl_fb_page_t { + SDL_Surface *surface; +}; + + +int sdl_fb_setup(settings_t *settings, setting_desc_t **next_setting) +{ + /* TODO: window size? fullscreen? vsync? etc. */ + return 0; +} + + +void * sdl_fb_init(settings_t *settings) +{ + sdl_fb_t *c; + + c = calloc(1, sizeof(sdl_fb_t)); + if (!c) + return NULL; + + if (SDL_Init(SDL_INIT_VIDEO) < 0) { + free(c); + return NULL; + } + + return c; +} + + +void sdl_fb_shutdown(void *context) +{ + sdl_fb_t *c = context; + + SDL_Quit(); + free(c); +} + + +static int sdl_fb_acquire(void *context, void *page) +{ + sdl_fb_t *c = context; + sdl_fb_page_t *p = page; + + c->window = SDL_CreateWindow("rototiller", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, 0); + if (!c->window) + return -1; + + c->renderer = SDL_CreateRenderer(c->window, -1, SDL_RENDERER_PRESENTVSYNC); + if (!c->renderer) + return -1; + + c->texture = SDL_CreateTexture(c->renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, 640, 480); + if (!c->texture) + return -1; + + return 0; +} + + +static void sdl_fb_release(void *context) +{ + sdl_fb_t *c = context; + + SDL_DestroyTexture(c->texture); + SDL_DestroyRenderer(c->renderer); + SDL_DestroyWindow(c->window); +} + + +static void * sdl_fb_page_alloc(void *context, fb_page_t *res_page) +{ + sdl_fb_t *c = context; + sdl_fb_page_t *p; + + p = calloc(1, sizeof(sdl_fb_page_t)); + if (!p) + return NULL; + + + p->surface = SDL_CreateRGBSurfaceWithFormat(0, 640, 480, 32, SDL_PIXELFORMAT_RGB888); + + res_page->fragment.buf = p->surface->pixels; + res_page->fragment.width = 640; + res_page->fragment.frame_width = 640; + res_page->fragment.height = 480; + res_page->fragment.frame_height = 480; + res_page->fragment.stride = p->surface->pitch - (640 * 4); + + return p; +} + + +static int sdl_fb_page_free(void *context, void *page) +{ + sdl_fb_t *c = context; + sdl_fb_page_t *p = page; + + SDL_FreeSurface(p->surface); + free(p); + + return 0; +} + + +static int sdl_fb_page_flip(void *context, void *page) +{ + sdl_fb_t *c = context; + sdl_fb_page_t *p = page; + + if (SDL_UpdateTexture(c->texture, NULL, p->surface->pixels, p->surface->pitch) < 0) + return -1; + + if (SDL_RenderClear(c->renderer) < 0) + return -1; + + if (SDL_RenderCopy(c->renderer, c->texture, NULL, NULL) < 0) + return -1; + + SDL_RenderPresent(c->renderer); + + if (SDL_QuitRequested()) + return -EPIPE; + + return 0; +} + + +fb_ops_t sdl_fb_ops = { + .setup = sdl_fb_setup, + .init = sdl_fb_init, + .shutdown = sdl_fb_shutdown, + .acquire = sdl_fb_acquire, + .release = sdl_fb_release, + .page_alloc = sdl_fb_page_alloc, + .page_free = sdl_fb_page_free, + .page_flip = sdl_fb_page_flip +}; diff --git a/src/sdl_fb.h b/src/sdl_fb.h new file mode 100644 index 0000000..4cd0ee9 --- /dev/null +++ b/src/sdl_fb.h @@ -0,0 +1,9 @@ +#ifndef _SDL_FB_H +#define _SDL_FB_H + +typedef struct sdl_fb_t sdl_fb_t; + +sdl_fb_t * sdl_fb_new(); +void sdl_fb_free(sdl_fb_t *fb); + +#endif |