From: Lukas Krickl Date: Tue, 24 Feb 2026 06:57:19 +0000 (+0100) Subject: rendering: Added generic framebuffer X-Git-Url: https://git.krickl.dev/?a=commitdiff_plain;h=862361218a3cd49cc02a60372f971380a2c99177;p=lrts%2F.git rendering: Added generic framebuffer This can be used to render a frame to the screen. The setup of a framebuffer is done by the rendering backend. It should provide direct access to pixel data. --- diff --git a/src/config.h b/src/config.h index cdb4226..14d3201 100644 --- a/src/config.h +++ b/src/config.h @@ -12,6 +12,9 @@ /* Platform and renderer configuration */ #define LRTS_PLATFORM_POSIX #define LRTS_RENDERER_SDL + +/* Defines target color as 32 bit */ +#define LRTS_COLOR_DEPTH_32 /* #define LRTS_RENDERER_CLI */ #endif diff --git a/src/lrts.c b/src/lrts.c index f38a9fa..01149c0 100644 --- a/src/lrts.c +++ b/src/lrts.c @@ -25,11 +25,31 @@ void lrts_version(void) { } +/** + * The default render size + */ +#define U_RENDER_W 640 +#define U_RENDER_H 640 + +struct u_vec2 lrts_get_render_res(void) { + struct lrts_config *cfg = lrts_cfg(); + + struct u_vec2 render_res = cfg->render_res; + if (render_res.x == 0) { + render_res.x = U_RENDER_W; + } + if (render_res.y == 0) { + render_res.y = U_RENDER_H; + } + return render_res; +} + int lrts_main(int argc, char **argv) { p_io_init(); lrts_getopt(argc, argv, lrts_cfg()); p_render_init(); + p_render_init_framebuffer(); while (!lrts_cfg()->exit) { p_poll_events(); diff --git a/src/p_draw.h b/src/p_draw.h index c1f73e3..12ea206 100644 --- a/src/p_draw.h +++ b/src/p_draw.h @@ -5,11 +5,6 @@ #include "r_color.h" -/* draws a singel pixel directly to the screen */ -void p_draw_pixel(i32 x, i32 y, r_color color); - -/* clears the current screen buffer */ -void p_draw_clear(void); /* inits the draw of a frame */ void p_draw_begin(void); diff --git a/src/p_platform.h b/src/p_platform.h index dee0594..5de02c7 100644 --- a/src/p_platform.h +++ b/src/p_platform.h @@ -22,6 +22,11 @@ int p_io_finish(void); */ int p_render_init(void); +/* + * Sets up the frame buffer + */ +int p_render_init_framebuffer(void); + /** * Quits rendering */ diff --git a/src/p_r_sdl/p_draw.c b/src/p_r_sdl/p_draw.c index d4196c5..c465e42 100644 --- a/src/p_r_sdl/p_draw.c +++ b/src/p_r_sdl/p_draw.c @@ -3,27 +3,11 @@ #include "../u_assert.h" void p_draw_begin(void) { + SDL_LockSurface(r_target); } void p_draw_end(void) { -} - -void p_draw_clear(void) { - SDL_FillSurfaceRect(r_target, NULL, 0x000000FF); -} - -void p_draw_pixel(i32 x, i32 y, r_color color) { - u32 *pixel = LRTS_NULL; - /* drop the draw if out of bounds */ - if (x < 0 || x > r_target->w) { - return; - } - if (y < 0 || y > r_target->h) { - return; - } - - pixel = (unsigned int*)(((char*)r_target->pixels) + r_target->pitch * y + x); - *pixel = color; + SDL_UnlockSurface(r_target); } void p_draw_present(void) { diff --git a/src/p_r_sdl/p_init.c b/src/p_r_sdl/p_init.c index 35b3285..51de98d 100644 --- a/src/p_r_sdl/p_init.c +++ b/src/p_r_sdl/p_init.c @@ -3,29 +3,44 @@ #include "p_window.h" #include "../u_defs.h" #include "../u_log.h" +#include "../u_math.h" #include "p_window.c" int p_render_init(void) { + struct lrts_config *cfg = lrts_cfg(); + struct u_vec2 target_res = lrts_get_render_res(); + if (!SDL_Init(SDL_INIT_VIDEO)) { u_log(U_LOG_ERR, "Failed to init video: %s\n", SDL_GetError()); exit(-1); } - p_main_window = SDL_CreateWindow(lrts_cfg()->name, R_WIDTH, R_HEIGHT, 0); + /* TODO: allow scaled resolution */ + p_main_window = SDL_CreateWindow(cfg->name, target_res.x, target_res.y, 0); if (p_main_window == LRTS_NULL) { u_log(U_LOG_ERR, "Failed to create window: %s\n", SDL_GetError()); exit(-1); } - r_target = SDL_CreateSurface(R_WIDTH, R_HEIGHT, SDL_PIXELFORMAT_RGBX8888); + + u_log(U_LOG_DEBUG, "Init successful\n"); + + return 0; +} + +int p_render_init_framebuffer(void) { + struct u_vec2 target_res = lrts_get_render_res(); + r_target = SDL_CreateSurface(target_res.x, target_res.y, SDL_PIXELFORMAT_RGBX8888); if (r_target == LRTS_NULL) { u_log(U_LOG_ERR, "Failed to create surface: %s\n", SDL_GetError()); exit(-1); } - u_log(U_LOG_DEBUG, "Init successful\n"); + r_framebuffer.pixels = r_target->pixels; + r_framebuffer.width = r_target->w; + r_framebuffer.height = r_target->h; return 0; } diff --git a/src/r_color.c b/src/r_color.c index 8b13789..661d5d8 100644 --- a/src/r_color.c +++ b/src/r_color.c @@ -1 +1,7 @@ +#include "r_color.h" +#ifdef LRTS_COLOR_DEPTH_32 +r_target_color r_color_to_target(r_color c) { + return c; +} +#endif diff --git a/src/r_color.h b/src/r_color.h index 3a56e48..0fee111 100644 --- a/src/r_color.h +++ b/src/r_color.h @@ -5,4 +5,18 @@ typedef u32 r_color; +/* + * Define a render target color + * This is here to allow changng the color depth + * at compile time + */ + +#ifdef LRTS_COLOR_DEPTH_32 +typedef u32 r_target_color; +#endif + + +/** converts r_color to target color **/ +r_target_color r_color_to_target(r_color c); + #endif diff --git a/src/r_render.c b/src/r_render.c index 58c0972..d53c8b7 100644 --- a/src/r_render.c +++ b/src/r_render.c @@ -2,11 +2,31 @@ #include "r_color.h" #include "p_draw.h" + +struct r_framebuffer r_framebuffer; + +void r_draw_pixel(struct r_framebuffer *fb, i32 x, i32 y, r_color color) { + r_target_color *pixel = LRTS_NULL; + + /* drop the draw if out of bounds */ + if (x < 0 || x >= r_target->w) { + return; + } + if (y < 0 || y >= r_target->h) { + return; + } + + pixel = fb->pixels + fb->width * y + x; + *pixel = color; +} + void r_render_frame() { p_draw_begin(); - p_draw_clear(); - p_draw_pixel(0, 0, 0xFF0000FF); + r_draw_pixel(&r_framebuffer, 0, 0, 0xFF0000FF); + r_draw_pixel(&r_framebuffer, 1, 1, 0xFF0000FF); + r_draw_pixel(&r_framebuffer, 2, 2, 0xFF0000FF); + r_draw_pixel(&r_framebuffer, r_framebuffer.width-1, r_framebuffer.height-1, 0xFF0000FF); p_draw_end(); p_draw_present(); diff --git a/src/r_render.h b/src/r_render.h index 4cf94bb..c36390a 100644 --- a/src/r_render.h +++ b/src/r_render.h @@ -1,9 +1,26 @@ #ifndef R_RENDER_H__ #define R_RENDER_H__ -/* internal rendering resolution */ -#define R_WIDTH 800 -#define R_HEIGHT 600 +#include "r_color.h" + +/** + * A simple framebuffer + * containing color data + */ +struct r_framebuffer { + u32 width; + u32 height; + r_target_color *pixels; +}; + +/* The global frame buffer. + * This needs to be initialized by the + * rendering platform + */ +extern struct r_framebuffer r_framebuffer; + +/* draws a singel pixel directly to a frame buffer */ +void r_draw_pixel(struct r_framebuffer *fb, i32 x, i32 y, r_color color); void r_render_frame(); diff --git a/src/u_defs.h b/src/u_defs.h index 25b62df..f6f30fc 100644 --- a/src/u_defs.h +++ b/src/u_defs.h @@ -31,12 +31,16 @@ typedef unsigned char lrts_bool; #define LRTS_TRUE 1 #define LRTS_FALSE 0 +#include "u_math.h" + struct lrts_config { lrts_bool verbose; i8 exit; const char *name; + + struct u_vec2 render_res; char **argv; int argc; @@ -49,8 +53,11 @@ void lrts_version(void); void lrts_getopt(int argc, char **argv, struct lrts_config *cfg); int lrts_main(int argc, char **argv); -#define U_RENDER_W 640 -#define U_RENDER_H 640 +/** + * Returns the current render size as a vec2 + */ +struct u_vec2 lrts_get_render_res(void); + #define LRTS_UNUSED(x) (void)(x) diff --git a/src/u_math.h b/src/u_math.h index fd7ebf0..543c97b 100644 --- a/src/u_math.h +++ b/src/u_math.h @@ -1,7 +1,10 @@ #ifndef U_MATH_H__ #define U_MATH_H__ +#include "u_defs.h" + #define U_FP(n, f) {n, f} +#define U_V2(x, y) {x, y} /* fixed point number * n: whole part @@ -12,6 +15,22 @@ struct u_fp { u16 f; }; +/* + * A simple 2d vector + */ +struct u_vec2 { + u32 x; + u32 y; +}; + +/* + * A fixed point vector + */ +struct u_vecfp { + struct u_fp x; + struct u_fp y; +}; + struct u_fp u_fp_add(struct u_fp a, struct u_fp b); struct u_fp u_fp_sub(struct u_fp a, struct u_fp b); struct u_fp u_fp_mul(struct u_fp a, struct u_fp b);