Skip to content

Commit 55783e5

Browse files
committed
Introduce interface to backends
Functions twin_{create,destroy} are introduced along with the refined backend interface, allowing for an incoming Linux framebuffer backend. This commit simplifies backend development and consolidates consistent APIs, meaning that a single source can be built for supported backends without conditional compilation.
1 parent 2d85c45 commit 55783e5

File tree

8 files changed

+180
-124
lines changed

8 files changed

+180
-124
lines changed

Makefile

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ target.o-y :=
1010
TARGET_LIBS :=
1111

1212
target.a-y = \
13-
libbackend.a \
1413
libapps.a \
15-
libtwin.a
14+
libtwin.a \
15+
libbackend.a
1616

1717
# Core library
1818

@@ -46,7 +46,8 @@ libtwin.a_files-y = \
4646
src/hull.c \
4747
src/icon.c \
4848
src/pixmap.c \
49-
src/timeout.c
49+
src/timeout.c \
50+
src/api.c
5051

5152
libtwin.a_includes-y := include
5253

@@ -77,29 +78,28 @@ libapps.a_files-y = \
7778
libapps.a_includes-y := include
7879

7980
# Graphical backends
81+
BACKEND := none
8082

8183
libbackend.a_files-y :=
8284
libbackend.a_cflags-y :=
83-
libbackend.a_includes-y := include
85+
libbackend.a_includes-y := \
86+
include \
87+
src
8488

8589
ifeq ($(CONFIG_BACKEND_SDL), y)
90+
BACKEND = sdl
8691
libbackend.a_files-y += backend/sdl.c
8792
libbackend.a_cflags-y += $(shell sdl2-config --cflags)
8893
TARGET_LIBS += $(shell sdl2-config --libs)
8994
endif
9095

9196
# Platform-specific executables
97+
target-y += demo-$(BACKEND)
98+
demo-$(BACKEND)_depends-y += $(target.a-y)
99+
demo-$(BACKEND)_files-y = apps/main.c
100+
demo-$(BACKEND)_includes-y := include
92101

93102
ifeq ($(CONFIG_BACKEND_SDL), y)
94-
target-y += demo-sdl
95-
96-
demo-sdl_depends-y += $(target.a-y)
97-
demo-sdl_files-y = \
98-
apps/twin-sdl.c
99-
100-
demo-sdl_includes-y := include
101-
demo-sdl_includes-y += backend
102-
103103
demo-sdl_cflags-y = $(shell sdl2-config --cflags)
104104
demo-sdl_ldflags-y := $(target.a-y)
105105
demo-sdl_ldflags-y += $(TARGET_LIBS)

apps/twin-sdl.c renamed to apps/main.c

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@
1111
#include <time.h>
1212
#include <unistd.h>
1313

14-
#include "twin_sdl.h"
15-
1614
#include "apps_calc.h"
1715
#include "apps_clock.h"
1816
#include "apps_demo.h"
@@ -70,18 +68,20 @@ static twin_pixmap_t *load_background(twin_screen_t *screen,
7068

7169
int main(void)
7270
{
73-
twin_sdl_t *sdl = twin_sdl_create(WIDTH, HEIGHT);
71+
twin_context_t *x = twin_create(WIDTH, HEIGHT);
7472

7573
twin_screen_set_background(
76-
sdl->screen, load_background(sdl->screen, ASSET_PATH "/tux.png"));
74+
x->screen, load_background(x->screen, ASSET_PATH "/tux.png"));
7775

78-
apps_demo_start(sdl->screen, "Demo", 100, 100, 400, 400);
79-
apps_hello_start(sdl->screen, "Hello, World", 0, 0, 200, 200);
80-
apps_clock_start(sdl->screen, "Clock", 10, 10, 200, 200);
81-
apps_calc_start(sdl->screen, "Calculator", 100, 100, 200, 200);
82-
apps_line_start(sdl->screen, "Line", 0, 0, 200, 200);
83-
apps_spline_start(sdl->screen, "Spline", 20, 20, 400, 400);
76+
apps_demo_start(x->screen, "Demo", 100, 100, 400, 400);
77+
apps_hello_start(x->screen, "Hello, World", 0, 0, 200, 200);
78+
apps_clock_start(x->screen, "Clock", 10, 10, 200, 200);
79+
apps_calc_start(x->screen, "Calculator", 100, 100, 200, 200);
80+
apps_line_start(x->screen, "Line", 0, 0, 200, 200);
81+
apps_spline_start(x->screen, "Spline", 20, 20, 400, 400);
8482

8583
twin_dispatch();
84+
85+
twin_destroy(x);
8686
return 0;
8787
}

backend/sdl.c

Lines changed: 92 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,31 @@
44
* All rights reserved.
55
*/
66

7+
#include <SDL.h>
8+
#include <SDL_render.h>
79
#include <stdio.h>
10+
#include <twin.h>
811

9-
#include "twin_private.h"
10-
#include "twin_sdl.h"
12+
#include "twin_backend.h"
13+
14+
typedef struct {
15+
SDL_Window *win;
16+
int *pixels;
17+
SDL_Renderer *render;
18+
SDL_Texture *texture;
19+
twin_coord_t width, height;
20+
int image_y;
21+
} twin_sdl_t;
22+
23+
#define PRIV(x) ((twin_sdl_t *) ((twin_context_t *) x)->priv)
1124

1225
static void _twin_sdl_put_begin(twin_coord_t left,
1326
twin_coord_t top,
1427
twin_coord_t right,
1528
twin_coord_t bottom,
1629
void *closure)
1730
{
18-
twin_sdl_t *tx = closure;
31+
twin_sdl_t *tx = PRIV(closure);
1932
tx->width = right - left;
2033
tx->height = bottom - top;
2134
tx->image_y = top;
@@ -27,41 +40,55 @@ static void _twin_sdl_put_span(twin_coord_t left,
2740
twin_argb32_t *pixels,
2841
void *closure)
2942
{
30-
twin_sdl_t *tx = closure;
43+
twin_screen_t *screen = ((twin_context_t *) closure)->screen;
44+
twin_sdl_t *tx = PRIV(closure);
3145

3246
for (twin_coord_t ix = left, iy = top; ix < right; ix++) {
3347
twin_argb32_t pixel = *pixels++;
34-
35-
if (tx->depth == 16)
36-
pixel = twin_argb32_to_rgb16(pixel);
37-
38-
tx->pixels[iy * tx->screen->width + ix] = pixel;
48+
tx->pixels[iy * screen->width + ix] = pixel;
3949
}
4050
if ((top + 1 - tx->image_y) == tx->height) {
4151
SDL_UpdateTexture(tx->texture, NULL, tx->pixels,
42-
tx->screen->width * sizeof(uint32_t));
52+
screen->width * sizeof(uint32_t));
4353
SDL_RenderCopy(tx->render, tx->texture, NULL, NULL);
4454
SDL_RenderPresent(tx->render);
4555
}
4656
}
4757

58+
static void _twin_sdl_destroy(twin_screen_t *screen, twin_sdl_t *tx)
59+
{
60+
twin_screen_destroy(screen);
61+
SDL_DestroyRenderer(tx->render);
62+
SDL_DestroyWindow(tx->win);
63+
SDL_Quit();
64+
}
65+
66+
static void twin_sdl_damage(twin_screen_t *screen, twin_sdl_t *tx)
67+
{
68+
int width, height;
69+
SDL_GetWindowSize(tx->win, &width, &height);
70+
twin_screen_damage(screen, 0, 0, width, height);
71+
}
72+
4873
static bool twin_sdl_read_events(int file maybe_unused,
4974
twin_file_op_t ops maybe_unused,
5075
void *closure)
5176
{
52-
twin_sdl_t *tx = closure;
77+
twin_screen_t *screen = ((twin_context_t *) closure)->screen;
78+
twin_sdl_t *tx = PRIV(closure);
79+
5380
SDL_Event ev;
5481
while (SDL_PollEvent(&ev)) {
5582
twin_event_t tev;
5683
switch (ev.type) {
5784
case SDL_WINDOWEVENT:
5885
if (ev.window.event == SDL_WINDOWEVENT_EXPOSED ||
5986
ev.window.event == SDL_WINDOWEVENT_SHOWN) {
60-
twin_sdl_damage(tx, &ev);
87+
twin_sdl_damage(screen, tx);
6188
}
6289
break;
6390
case SDL_QUIT:
64-
twin_sdl_destroy(tx);
91+
_twin_sdl_destroy(screen, tx);
6592
return false;
6693
case SDL_MOUSEBUTTONDOWN:
6794
case SDL_MOUSEBUTTONUP:
@@ -71,21 +98,21 @@ static bool twin_sdl_read_events(int file maybe_unused,
7198
((ev.button.state >> 8) | (1 << (ev.button.button - 1)));
7299
tev.kind = ((ev.type == SDL_MOUSEBUTTONDOWN) ? TwinEventButtonDown
73100
: TwinEventButtonUp);
74-
twin_screen_dispatch(tx->screen, &tev);
101+
twin_screen_dispatch(screen, &tev);
75102
break;
76103
case SDL_KEYDOWN:
77104
case SDL_KEYUP:
78105
tev.u.key.key = ev.key.keysym.sym;
79106
tev.kind = ((ev.key.type == SDL_KEYDOWN) ? TwinEventKeyDown
80107
: TwinEventKeyUp);
81-
twin_screen_dispatch(tx->screen, &tev);
108+
twin_screen_dispatch(screen, &tev);
82109
break;
83110
case SDL_MOUSEMOTION:
84111
tev.u.pointer.screen_x = ev.motion.x;
85112
tev.u.pointer.screen_y = ev.motion.y;
86113
tev.kind = TwinEventMotion;
87114
tev.u.pointer.button = ev.motion.state;
88-
twin_screen_dispatch(tx->screen, &tev);
115+
twin_screen_dispatch(screen, &tev);
89116
break;
90117
}
91118
}
@@ -94,85 +121,89 @@ static bool twin_sdl_read_events(int file maybe_unused,
94121

95122
static bool twin_sdl_work(void *closure)
96123
{
97-
twin_sdl_t *tx = closure;
124+
twin_screen_t *screen = ((twin_context_t *) closure)->screen;
98125

99-
if (twin_screen_damaged(tx->screen))
100-
twin_sdl_update(tx);
126+
if (twin_screen_damaged(screen))
127+
twin_screen_update(screen);
101128
return true;
102129
}
103130

104-
twin_sdl_t *twin_sdl_create(int width, int height)
131+
twin_context_t *twin_sdl_init(int width, int height)
105132
{
106-
static char *title = "twin-sdl";
107-
108-
twin_sdl_t *tx = malloc(sizeof(twin_sdl_t));
109-
if (!tx)
133+
twin_context_t *ctx = calloc(1, sizeof(twin_context_t));
134+
if (!ctx)
135+
return NULL;
136+
ctx->priv = calloc(1, sizeof(twin_sdl_t));
137+
if (!ctx->priv)
110138
return NULL;
111139

112-
if (SDL_Init(SDL_INIT_VIDEO) < 0)
140+
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
113141
printf("error : %s\n", SDL_GetError());
142+
goto bail;
143+
}
144+
145+
twin_sdl_t *tx = ctx->priv;
146+
147+
static char *title = "twin-sdl";
114148
tx->win = SDL_CreateWindow(title, SDL_WINDOWPOS_UNDEFINED,
115149
SDL_WINDOWPOS_UNDEFINED, width, height,
116150
SDL_WINDOW_SHOWN);
117-
if (!tx->win)
151+
if (!tx->win) {
118152
printf("error : %s\n", SDL_GetError());
153+
goto bail;
154+
}
155+
119156
tx->pixels = malloc(width * height * sizeof(uint32_t));
120157
memset(tx->pixels, 255, width * height * sizeof(uint32_t));
121158

122159
tx->render = SDL_CreateRenderer(tx->win, -1, SDL_RENDERER_ACCELERATED);
123-
if (!tx->render)
160+
if (!tx->render) {
124161
printf("error : %s\n", SDL_GetError());
162+
goto bail_pixels;
163+
}
125164
SDL_SetRenderDrawColor(tx->render, 255, 255, 255, 255);
126165
SDL_RenderClear(tx->render);
127166

128167
tx->texture = SDL_CreateTexture(tx->render, SDL_PIXELFORMAT_ARGB8888,
129168
SDL_TEXTUREACCESS_STREAMING, width, height);
130169

131-
tx->screen = twin_screen_create(width, height, _twin_sdl_put_begin,
132-
_twin_sdl_put_span, tx);
133-
134-
twin_set_file(twin_sdl_read_events, 0, TWIN_READ, tx);
170+
ctx->screen = twin_screen_create(width, height, _twin_sdl_put_begin,
171+
_twin_sdl_put_span, ctx);
135172

136-
twin_set_work(twin_sdl_work, TWIN_WORK_REDISPLAY, tx);
173+
twin_set_file(twin_sdl_read_events, 0, TWIN_READ, ctx);
137174

138-
return tx;
139-
}
175+
twin_set_work(twin_sdl_work, TWIN_WORK_REDISPLAY, ctx);
140176

141-
void twin_sdl_destroy(twin_sdl_t *tx)
142-
{
143-
SDL_DestroyRenderer(tx->render);
144-
SDL_DestroyWindow(tx->win);
145-
tx->win = 0;
146-
twin_screen_destroy(tx->screen);
147-
SDL_Quit();
148-
}
177+
return ctx;
149178

150-
void twin_sdl_damage(twin_sdl_t *tx, SDL_Event *ev maybe_unused)
151-
{
152-
int width, height;
153-
SDL_GetWindowSize(tx->win, &width, &height);
154-
twin_screen_damage(tx->screen, 0, 0, width, height);
179+
bail_pixels:
180+
free(tx->pixels);
181+
bail:
182+
free(ctx->priv);
183+
free(ctx);
184+
return NULL;
155185
}
156186

157-
void twin_sdl_configure(twin_sdl_t *tx, SDL_Event *ev maybe_unused)
187+
static void twin_sdl_configure(twin_context_t *ctx)
158188
{
159189
int width, height;
160-
SDL_GetWindowSize(tx->win, &width, &height);
161-
twin_screen_resize(tx->screen, width, height);
190+
SDL_GetWindowSize(PRIV(ctx)->win, &width, &height);
191+
twin_screen_resize(ctx->screen, width, height);
162192
}
163193

164-
void twin_sdl_update(twin_sdl_t *tx)
194+
static void twin_sdl_exit(twin_context_t *ctx)
165195
{
166-
twin_screen_update(tx->screen);
196+
if (!ctx)
197+
return;
198+
free(PRIV(ctx)->pixels);
199+
free(ctx->priv);
200+
free(ctx);
167201
}
168202

169-
bool twin_sdl_process_events(twin_sdl_t *tx)
170-
{
171-
bool result;
203+
/* Register the SDL backend */
172204

173-
_twin_run_work();
174-
result = twin_sdl_read_events(0, 0, tx);
175-
_twin_run_work();
176-
177-
return result;
178-
}
205+
const twin_backend_t g_twin_backend = {
206+
.init = twin_sdl_init,
207+
.configure = twin_sdl_configure,
208+
.exit = twin_sdl_exit,
209+
};

backend/twin_sdl.h

Lines changed: 0 additions & 38 deletions
This file was deleted.

0 commit comments

Comments
 (0)