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.
/* 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
}
+/**
+ * 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();
#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);
*/
int p_render_init(void);
+/*
+ * Sets up the frame buffer
+ */
+int p_render_init_framebuffer(void);
+
/**
* Quits rendering
*/
#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) {
#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;
}
+#include "r_color.h"
+#ifdef LRTS_COLOR_DEPTH_32
+r_target_color r_color_to_target(r_color c) {
+ return c;
+}
+#endif
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
#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();
#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();
#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;
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)
#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
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);