diff options
author | quou <quou@disroot.org> | 2024-06-01 12:19:16 +1000 |
---|---|---|
committer | quou <quou@disroot.org> | 2024-06-01 12:20:17 +1000 |
commit | ea7cd94f7aeb177618db3907a6c86b7252e018f0 (patch) | |
tree | e972f9cf590ef756c2e41f3eac5b03e16db08300 /rcache.c |
Initial commit.
Diffstat (limited to 'rcache.c')
-rw-r--r-- | rcache.c | 467 |
1 files changed, 467 insertions, 0 deletions
diff --git a/rcache.c b/rcache.c new file mode 100644 index 0000000..9170f71 --- /dev/null +++ b/rcache.c @@ -0,0 +1,467 @@ +#include "error.h" +#include "memory.h" +#include "maths.h" +#include "plat.h" +#include "rcache.h" +#include "render.h" + +#if rcache_enable +unsigned* hgrid, * ohgrid, * hgrid1, * hgrid2; +char* cmd_buf; +int cmd_count; +int rcache_cell_w, rcache_cell_h; + +void rc_init(void) { + int i, e; + rcache_cell_w = get_render_w() / rcache_gw; + rcache_cell_h = get_render_h() / rcache_gh; + cmd_buf = stack_alloc(rcache_cmd_buf_size); + e = rcache_gw * rcache_gh * sizeof *hgrid1; + hgrid1 = stack_alloc(e); + hgrid2 = stack_alloc(e); + hgrid = hgrid1; + ohgrid = hgrid2; + cmd_count = 0; + e /= sizeof *hgrid1; + for (i = 0; i < e; i++) + hgrid1[i] = hgrid2[i] = 0; +} + +RC_Cmd* rc_add_cmd(RC_Cmd* cmd) { + int i; + RC_Cmd* r; + cmd->size = (cmd->size + 7) & -8; +#ifdef DEBUG + if (cmd_count + cmd->size >= rcache_cmd_buf_size) { + print_err("Out of render command space."); + pbreak(error_out_of_memory); + return 0; + } +#endif + r = (RC_Cmd*)&cmd_buf[cmd_count]; + for (i = 0; i < cmd->size; i++) { + cmd_buf[cmd_count++] = ((char*)cmd)[i]; + } + return r; +} + +void rc_add_cmd_bmp( + const Bitmap* bmp, + int x, + int y, + const Rectangle* src +) { + RC_Cmd_Bmp cmd; + cmd.cmd.type = rc_cmd_bmp; + cmd.cmd.size = sizeof cmd; + cmd.cmd.x = x; + cmd.cmd.y = y; + cmd.cmd.w = src->w; + cmd.cmd.h = src->h; + cmd.sx = src->x; + cmd.sy = src->y; + cmd.bmp = bmp; + rc_add_cmd((RC_Cmd*)&cmd); +} + +void rc_add_cmd_bmp_col( + const Bitmap* bmp, + int x, + int y, + const Rectangle* src, + Colour col +) { + RC_Cmd_Bmp_Mod cmd; + cmd.cmd.type = rc_cmd_bmp_mod; + cmd.cmd.size = sizeof cmd; + cmd.cmd.x = x; + cmd.cmd.y = y; + cmd.cmd.w = src->w; + cmd.cmd.h = src->h; + cmd.sx = src->x; + cmd.sy = src->y; + cmd.bmp = bmp; + cmd.col = col; + rc_add_cmd((RC_Cmd*)&cmd); +} + +void rc_add_cmd_bmp_cp( + const Bitmap* bmp, + int x, + int y, + const Rectangle* src +) { + RC_Cmd_Bmp_Cp cmd; + cmd.cmd.type = rc_cmd_bmp_cp; + cmd.cmd.size = sizeof cmd; + cmd.cmd.x = x; + cmd.cmd.y = y; + cmd.cmd.w = src->w; + cmd.cmd.h = src->h; + cmd.sx = src->x; + cmd.sy = src->y; + cmd.bmp = *bmp; + rc_add_cmd((RC_Cmd*)&cmd); +} + +void rc_add_cmd_bmp_cp_col( + const Bitmap* bmp, + int x, + int y, + const Rectangle* src, + Colour col +) { + RC_Cmd_Bmp_Cp_Mod cmd; + cmd.cmd.type = rc_cmd_bmp_cp_mod; + cmd.cmd.size = sizeof cmd; + cmd.cmd.x = x; + cmd.cmd.y = y; + cmd.cmd.w = src->w; + cmd.cmd.h = src->h; + cmd.sx = src->x; + cmd.sy = src->y; + cmd.bmp = *bmp; + cmd.col = col; + rc_add_cmd((RC_Cmd*)&cmd); +} + +void rc_add_cmd_rfont_text( + Font* font, + int x, + int y, + const char* text +) { + RC_Cmd_RFont_Text cmd; + RC_Cmd_RFont_Text* dc; + Rectangle r; + const char* c; + char* d; + r = text_rect(font, text); + cmd.cmd.type = rc_cmd_rfont_text; + cmd.cmd.x = x; + cmd.cmd.y = y; + cmd.cmd.w = r.w; + cmd.cmd.h = r.h; + cmd.font = font; + for (c = text; *c; c++); + cmd.cmd.size = sizeof cmd + (c - text) + 1; + dc = (void*)rc_add_cmd((RC_Cmd*)&cmd); + for ( + c = text, d = (char*)(dc + 1); + *c; + c++, d++ + ) *d = *c; + *d = 0; +} + +void rc_add_cmd_rfont_text_col( + Font* font, + int x, + int y, + const char* text, + Colour col +) { + RC_Cmd_RFont_Text_Col cmd; + RC_Cmd_RFont_Text_Col* dc; + Rectangle r; + const char* c; + char* d; + r = text_rect(font, text); + cmd.cmd.type = rc_cmd_rfont_text_col; + cmd.cmd.x = x; + cmd.cmd.y = y; + cmd.cmd.w = r.w; + cmd.cmd.h = r.h; + cmd.font = font; + cmd.col = col; + for (c = text; *c; c++); + cmd.cmd.size = sizeof cmd + (c - text) + 1; + dc = (void*)rc_add_cmd((RC_Cmd*)&cmd); + for ( + c = text, d = (char*)(dc + 1); + *c; + c++, d++ + ) *d = *c; + *d = 0; +} + +void rc_add_cmd_clip( + const Rectangle* rect +) { + RC_Cmd cmd; + cmd.type = rc_cmd_set_clip; + cmd.size = sizeof cmd; + cmd.x = rect->x; + cmd.y = rect->y; + cmd.w = rect->w - rect->x; + cmd.h = rect->h - rect->y; + rc_add_cmd(&cmd); +} + +void rc_add_cmd_reset_clip(void) { + RC_Cmd cmd; + cmd.type = rc_cmd_set_clip; + cmd.size = sizeof cmd; + cmd.x = 0; + cmd.y = 0; + cmd.w = get_render_w(); + cmd.h = get_render_h(); + rc_add_cmd(&cmd); +} + +void rc_add_cmd_rect( + const Rectangle* r, + Colour col +) { + RC_Cmd_Rect cmd; + cmd.cmd.type = rc_cmd_rect; + cmd.cmd.size = sizeof cmd; + cmd.cmd.x = r->x; + cmd.cmd.y = r->y; + cmd.cmd.w = r->w; + cmd.cmd.h = r->h; + cmd.col = col; + rc_add_cmd((RC_Cmd*)&cmd); +} + +static void hash(unsigned* hash, const void* data, int size) { + const unsigned char *p = data; + while (size--) + *hash = (*hash ^ *p++) * 16777619; +} + +void update_hgrid(unsigned* g) { + int x, y, x1, y1, x2, y2, w; + unsigned* d; + RC_Cmd* cmd, * end; + w = rcache_gw; + x = rcache_gw * rcache_gh; + for (y = 0; y < x; y++) + g[y] = rcache_hash_seed; + cmd = (RC_Cmd*)cmd_buf; + end = (RC_Cmd*)(cmd_buf + cmd_count); + for ( + ; + cmd != end; + cmd = (RC_Cmd*)((char*)cmd + cmd->size) + ) { + if ( + cmd->type == rc_cmd_set_clip || + cmd->type == rc_cmd_reset_clip + ) continue; + x1 = maxi(0, cmd->x / rcache_cell_w); + y1 = maxi(0, cmd->y / rcache_cell_h); + if (x1 >= rcache_gw) continue; + if (y1 >= rcache_gh) continue; + x2 = mini( + (cmd->x + cmd->w) / rcache_cell_w, + rcache_gw - 1 + ); + y2 = mini( + (cmd->y + cmd->h) / rcache_cell_h, + rcache_gh - 1 + ); + if (x2 < 0) continue; + if (y2 < 0) continue; + for (y = y1; y <= y2; y++) + for (x = x1; x <= x2; x++) { + d = &g[x + y * w]; + hash(d, cmd, cmd->size); + } + } +} + +void rc_flush_rect(int x, int y, int w, int h) { + RC_Cmd* cmd, * end; + RC_Cmd_Bmp* bmpcmd; + RC_Cmd_Bmp_Mod* bmpmcmd; + RC_Cmd_Bmp_Cp* bmpcpcmd; + RC_Cmd_Bmp_Cp_Mod* bmpmcpcmd; + RC_Cmd_RFont_Text* txtrfcmd; + RC_Cmd_RFont_Text_Col* txtrfccmd; + Rectangle c, r; + cmd = (RC_Cmd*)cmd_buf; + end = (RC_Cmd*)(cmd_buf + cmd_count); + int n, rw, rh; + rw = get_render_w(); + rh = get_render_h(); + if (x > rw) return; + if (y > rh) return; + x = maxi(x, 0); + y = maxi(y, 0); + if ((n = x + w - rw) > 0) + w -= n; + if ((n = y + h - rh) > 0) + h -= n; + if (w <= 0) return; + if (h <= 0) return; + c.x = x; + c.y = y; + c.w = x + w; + c.h = y + h; + render_clip(&c); + render_clear(); + while (cmd != end) { + switch (cmd->type) { + case rc_cmd_bmp: + bmpcmd = (RC_Cmd_Bmp*)cmd; + r.x = bmpcmd->sx; + r.y = bmpcmd->sy; + r.w = cmd->w; + r.h = cmd->h; + render_bitmap( + bmpcmd->bmp, + cmd->x, + cmd->y, + &r + ); + break; + case rc_cmd_bmp_mod: + bmpmcmd = (RC_Cmd_Bmp_Mod*)cmd; + r.x = bmpmcmd->sx; + r.y = bmpmcmd->sy; + r.w = cmd->w; + r.h = cmd->h; + render_bitmap_col( + bmpmcmd->bmp, + cmd->x, + cmd->y, + &r, + bmpmcmd->col + ); + break; + case rc_cmd_bmp_cp: + bmpcpcmd = (RC_Cmd_Bmp_Cp*)cmd; + r.x = bmpcpcmd->sx; + r.y = bmpcpcmd->sy; + r.w = cmd->w; + r.h = cmd->h; + render_bitmap( + &bmpcpcmd->bmp, + cmd->x, + cmd->y, + &r + ); + break; + case rc_cmd_bmp_cp_mod: + bmpmcpcmd = (RC_Cmd_Bmp_Cp_Mod*)cmd; + r.x = bmpmcpcmd->sx; + r.y = bmpmcpcmd->sy; + r.w = cmd->w; + r.h = cmd->h; + render_bitmap_col( + &bmpmcpcmd->bmp, + cmd->x, + cmd->y, + &r, + bmpmcpcmd->col + ); + break; + case rc_cmd_rfont_text: + txtrfcmd = (RC_Cmd_RFont_Text*)cmd; + rfont_text( + txtrfcmd->font, + cmd->x, + cmd->y, + (char*)(txtrfcmd + 1) + ); + break; + case rc_cmd_rfont_text_col: + txtrfccmd = (RC_Cmd_RFont_Text_Col*)cmd; + rfont_text_col( + txtrfccmd->font, + cmd->x, + cmd->y, + (char*)(txtrfccmd + 1), + txtrfccmd->col + ); + break; + case rc_cmd_set_clip: + r.x = cmd->x; + r.y = cmd->y; + r.w = cmd->w; + r.h = cmd->h; + r = rect_intersect(&c, &r); + r.w += r.x; + r.h += r.y; + render_clip(&r); + break; + case rc_cmd_reset_clip: + render_clip(&c); + break; + case rc_cmd_rect: + r.x = cmd->x; + r.y = cmd->y; + r.w = cmd->w; + r.h = cmd->h; + render_rect( + &r, + ((RC_Cmd_Rect*)cmd)->col + ); + break; + } + cmd = (RC_Cmd*)((char*)cmd + cmd->size); + } + plat_present(x, y, w, h); + render_reset_clip(); +} + +void rc_flush(void) { + int x, y, w, h, i; + w = rcache_gw; + h = rcache_gh; + update_hgrid(hgrid); + for (y = 0; y < h; y++) + for (x = 0; x < w; x++) { + i = x + y * w; + if (hgrid[i] != ohgrid[i]) + rc_flush_rect( + x * rcache_cell_w, + y * rcache_cell_h, + rcache_cell_w, + rcache_cell_h + ); + } + cmd_count = 0; + x = rcache_gw * rcache_gh; + for (y = 0; y < x; y++) + ohgrid[y] = hgrid[y]; + ohgrid = hgrid; + hgrid = hgrid == hgrid1? hgrid2: hgrid1; +} + +void rc_begin(void) { + rcache_cell_w = (get_render_w() / rcache_gw) + 1; + rcache_cell_h = (get_render_h() / rcache_gh) + 1; +} + +void rc_invalidate(const Rectangle* r) { + int x, y, x1, y1, x2, y2, w; + x1 = maxi(0, r->x / rcache_cell_w); + y1 = maxi(0, r->y / rcache_cell_h); + x2 = mini( + (r->x + r->w) / rcache_cell_w, + rcache_gw - 1 + ); + y2 = mini( + (r->y + r->h) / rcache_cell_h, + rcache_gh - 1 + ); + w = rcache_gw; + for (y = y1; y <= y2; y++) + for (x = x1; x <= x2; x++) { + ohgrid[x + y * w] = -1; + } +} +#else + +void rc_init(void) { + render_init(); +} + +void rc_flush(void) { + plat_present(0, 0, get_render_w(), get_render_h()); + render_begin(); +} + +#endif |