add an overdraw buffer to allow for layered rendering

This commit is contained in:
2026-10-10 10:33:56 +02:00
parent 9deb40d080
commit ea1e99f022
14 changed files with 176 additions and 38 deletions
+42 -10
View File
@@ -42,9 +42,15 @@ mark_dirty_rect(int x, int y, int w, int h)
.h = h
};
if (!game_state->framebuffer_dirty) {
if (!game_state->framebuffer_base_dirty) {
game_state->dirty_rect = rect;
game_state->framebuffer_dirty = true;
game_state->framebuffer_base_dirty = true;
return;
}
if (!game_state->framebuffer_overdraw_dirty) {
game_state->dirty_rect = rect;
game_state->framebuffer_overdraw_dirty = true;
return;
}
@@ -83,9 +89,24 @@ mark_dirty_rect(int x, int y, int w, int h)
}
bool
upload_dirty_texture(void)
{
if (!game_state->framebuffer_dirty) {
upload_dirty_texture(
framebuffer_e framebuffer
) {
uint32_t *current_framebuffer;
switch (framebuffer) {
case BASE:
current_framebuffer = game_state->framebuffer_base;
break;
case OVERDRAW:
current_framebuffer = game_state->framebuffer_overdraw;
break;
default:
break;
}
if (!game_state->framebuffer_base_dirty &&
!game_state->framebuffer_overdraw_dirty
) {
return true;
}
@@ -117,7 +138,7 @@ upload_dirty_texture(void)
(size_t)rect.w * sizeof(uint32_t);
const uint8_t *source =
(const uint8_t *)game_state->framebuffer +
(const uint8_t *)current_framebuffer +
(size_t)rect.y * source_pitch +
(size_t)rect.x * sizeof(uint32_t);
@@ -134,7 +155,16 @@ upload_dirty_texture(void)
SDL_UnlockTexture(texture);
game_state->framebuffer_dirty = false;
switch (framebuffer) {
case BASE:
game_state->framebuffer_base_dirty = false;
break;
case OVERDRAW:
game_state->framebuffer_overdraw_dirty = false;
break;
default:
break;
}
return true;
}
@@ -152,7 +182,8 @@ engine_start() {
internal_state->engine_update_framebuffer();
// update the texture with the modified framebuffer
upload_dirty_texture();
upload_dirty_texture(BASE);
upload_dirty_texture(OVERDRAW);
SDL_RenderClear(
internal_state->sdl_state->renderer
@@ -174,6 +205,7 @@ void
engine_stop() {
engine_sdl_destroy(internal_state->sdl_state);
free(internal_state);
free(game_state->framebuffer);
free(game_state->framebuffer_base);
free(game_state->framebuffer_overdraw);
free(game_state);
}
}
+16 -5
View File
@@ -160,14 +160,23 @@ engine_init(
return RCODE_FAILURE;
}
game_state->framebuffer = (uint32_t *)
game_state->framebuffer_base = (uint32_t *)
malloc(sizeof(uint32_t) * window_width * window_height);
if (game_state->framebuffer == NULL) {
if (game_state->framebuffer_base == NULL) {
free(internal_state);
free(game_state);
return RCODE_FAILURE;
}
game_state->framebuffer_overdraw = (uint32_t *)
malloc(sizeof(uint32_t) * window_width * window_height);
if (game_state->framebuffer_overdraw == NULL) {
free(internal_state);
free(game_state->framebuffer_base);
free(game_state);
return RCODE_FAILURE;
}
internal_state->engine_poll_events
= engine_poll_events;
@@ -181,13 +190,15 @@ engine_init(
);
if (internal_state->sdl_state == NULL) {
free(internal_state);
free(game_state->framebuffer);
free(game_state->framebuffer_base);
free(game_state->framebuffer_overdraw);
free(game_state);
return RCODE_FAILURE;
}
game_state->is_running = true;
game_state->framebuffer_dirty = true;
game_state->framebuffer_base_dirty = true;
game_state->framebuffer_overdraw_dirty = true;
game_state->dirty_rect = (SDL_Rect) {
.x = 0,
.y = 0,
@@ -198,4 +209,4 @@ engine_init(
game_state->height = internal_state->sdl_state->height;
return RCODE_SUCCESS;
}
}
+22
View File
@@ -0,0 +1,22 @@
#include <dangerzone/render/anim.h>
void
anim_rect_pos(
uint32_t x0,
uint32_t y0,
uint32_t x1,
uint32_t y1,
uint32_t w,
uint32_t h,
uint32_t color
) {
// TODO: I THINK I NEED LAYERED BUFFERS
// one step is one pixel
uint32_t stepsx = x1 - x0;
uint32_t stepsy = y1 - y0;
/**
* 1. get the row / column in the direction of the movement
*/
}
+26 -3
View File
@@ -2,16 +2,36 @@
#include <dangerzone/render/misc.h>
#include <dangerzone/render/rect.h>
#include "internal/engine_internal.h"
#include "internal/util/error.h"
#include <stdint.h>
// helper function to return the correct pointer to a framebuffer for drawing selection
uint32_t*
get_framebuffer(
framebuffer_e framebuffer
) {
switch (framebuffer) {
case BASE:
return game_state->framebuffer_base;
case OVERDRAW:
return game_state->framebuffer_overdraw;
default:
return game_state->framebuffer_base;
}
}
// alter a pixel at an imaginary x & y coordinates
void
put_pixel(
framebuffer_e framebuffer,
unsigned int x,
unsigned int y,
uint32_t color
) {
uint32_t *current_framebuffer = get_framebuffer(framebuffer);
uint16_t w = game_state->width;
uint16_t h = game_state->height;
@@ -21,7 +41,7 @@ put_pixel(
"at x = %d, y = %d", x, y
);
} else {
game_state->framebuffer[game_state->width * y + x]
current_framebuffer[game_state->width * y + x]
= color;
mark_dirty_rect(x, y, 1, 1);
@@ -31,12 +51,15 @@ put_pixel(
// fill the entire framebuffer with a given color
void
clear_framebuffer(
framebuffer_e framebuffer,
uint32_t color
) {
uint32_t *current_framebuffer = get_framebuffer(framebuffer);
for (size_t i = 0;
i < (size_t)game_state->width * game_state->height;
++i) {
game_state->framebuffer[i] = color;
current_framebuffer[i] = color;
}
mark_dirty_rect(
@@ -45,4 +68,4 @@ clear_framebuffer(
game_state->width,
game_state->height
);
}
}
+5 -3
View File
@@ -10,20 +10,22 @@
*/
void
put_rect(
framebuffer_e framebuffer,
uint32_t x,
uint32_t y,
uint32_t w,
uint32_t h,
uint32_t color
) {
) {
for (int i = x; i < x + w; i++) {
for (int j = y; j < y + h; j++) {
put_pixel(i, j, color);
put_pixel(framebuffer, i, j, color);
}
}
mark_dirty_rect(x, y, w, h);
}
// TODO: remove, see rect.h
void
clear_rect(int x, int y, int w, int h, uint32_t color)
{
@@ -33,7 +35,7 @@ clear_rect(int x, int y, int w, int h, uint32_t color)
px < game_state->width &&
py >= 0 &&
py < game_state->height) {
game_state->framebuffer[
game_state->framebuffer_base[
py * game_state->width + px
] = color;
}
+4 -1
View File
@@ -81,6 +81,7 @@ static const uint8_t font[128][FONT_ROWS] = {
*/
void
put_char(
framebuffer_e framebuffer,
char c,
uint32_t x,
uint32_t y,
@@ -107,6 +108,7 @@ put_char(
? fg_color : bg_color;
put_rect(
framebuffer,
x + col * size,
y + row * size,
size,
@@ -121,6 +123,7 @@ put_char(
void
put_string(
framebuffer_e framebuffer,
const char *text,
uint32_t x,
uint32_t y,
@@ -137,7 +140,7 @@ put_string(
x = start_x;
y += (FONT_ROWS + line_spacing) * size;
} else {
put_char(*text, x, y, size, fg_color, bg_color);
put_char(framebuffer, *text, x, y, size, fg_color, bg_color);
x += (FONT_COLS + spacing) * size;
}