From 1101c551c96d8440aa19537f30ed47732bf2b4c8 Mon Sep 17 00:00:00 2001 From: WormHeamer Date: Tue, 4 Nov 2025 17:52:47 -0500 Subject: only do one fwrite() when blitting --- main.c | 132 ++++++++++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 85 insertions(+), 47 deletions(-) (limited to 'main.c') diff --git a/main.c b/main.c index fa0821d..c3de4f8 100644 --- a/main.c +++ b/main.c @@ -15,7 +15,6 @@ /* TODO * - * - one fwrite() per blit * - utf-8 input * - arrow keys * - KEY_RESIZE or draw callback @@ -225,39 +224,78 @@ static inline int bchr_equiv(VuiBuffer *back, VuiBuffer *front, int x, int y) { /* || BCHR(back,x,y) == ' ' */); } +static char vui_out[65536]; +static unsigned short vui_outn = 0; + +void vui_outf(const char *fmt, ...) { + va_list ap; + va_start(ap, fmt); + int n = vsnprintf(NULL, 0, fmt, ap); + va_end(ap); + va_start(ap, fmt); + vsprintf(&vui_out[vui_outn], fmt, ap); + vui_outn += n; + va_end(ap); +} + +static inline void vui_outc(char c) { + vui_out[vui_outn++] = c; +} + +static inline void vui_outsn(const char *s, unsigned n) { + memcpy(&vui_out[vui_outn], s, n); + vui_outn += n; +} + +static inline void vui_outs(const char *s) { + vui_outsn(s, strlen(s)); +} + +static inline void vui_out_flush(void) { + fwrite(vui_out, 1, vui_outn, stdout); + fflush(stdout); +#if 1 + static unsigned out_frame = 0; + FILE *f = fopen("out_log.txt", "a"); + assert(f); + fprintf(f, "\n\n:: OUTPUT FRAME %u ::\n", ++out_frame); + fwrite(vui_out, 1, vui_outn, f); + fclose(f); +#endif + vui_outn = 0; +} + static inline void curs_move(int src_x, int src_y, int dst_x, int dst_y) { if (src_x != dst_x && src_y != dst_y) { if (dst_x > 0) { - printf("\x1b[%d;%dH", dst_y + 1, dst_x + 1); + vui_outf("\x1b[%d;%dH", dst_y + 1, dst_x + 1); } else { - printf("\x1b[%dH", dst_y + 1); + vui_outf("\x1b[%dH", dst_y + 1); } } else if (src_x != dst_x) { - printf("\x1b[%dG", dst_x + 1); + vui_outf("\x1b[%dG", dst_x + 1); } else if (src_y != dst_y) { - printf("\x1b[%dd", dst_y + 1); + vui_outf("\x1b[%dd", dst_y + 1); } } static void attr_chg(VuiAttr *ptr, VuiAttr to) { VuiAttr from = *ptr; if (from == to) return; - char buf[64] = { 0 }; - char *s = buf; int chg_attr = (ATTR_A(from) != ATTR_A(to)); chg_attr = 0; + /* popcnt(f_attr ^ t_attr) to detect nr. of changes */ + if (chg_attr) { - *s++ = '\x1b'; - *s++ = '['; - *s++ = '0'; - if (to & A_BOLD) *s++ = ';', *s++ = '1'; - if (to & A_DIM) *s++ = ';', *s++ = '1'; - if (to & A_ITALIC) *s++ = ';', *s++ = '3'; - if (to & A_UNDERSCORE) *s++ = ';', *s++ = '4'; - if (to & A_BLINK) *s++ = ';', *s++ = '5'; - if (to & A_REVERSE) *s++ = ';', *s++ = '7'; + vui_outs("\x1b[0"); + if (to & A_BOLD) vui_outs(";1"); + if (to & A_DIM) vui_outs(";2"); + if (to & A_ITALIC) vui_outs(";3"); + if (to & A_UNDERSCORE) vui_outs(";4"); + if (to & A_BLINK) vui_outs(";5"); + if (to & A_REVERSE) vui_outs(";7"); from = ATTR_DEFAULT; assert(ATTR_FG(from) == FG_WHITE); assert(ATTR_BG(from) == BG_BLACK); @@ -271,35 +309,30 @@ static void attr_chg(VuiAttr *ptr, VuiAttr to) { int chg_fg = (t_fg != f_fg); int chg_bg = (t_bg != f_bg); if (chg_fg || chg_bg) { - if (chg_attr) *s++ = ';'; - else *s++ = '\x1b', *s++ = '['; + if (chg_attr) vui_outc(';'); + else vui_outs("\x1b["); if (chg_fg) { - *s++ = (t_fg > 7 ? '9' : '3'); - *s++ = (t_fg & 7) + '0'; + vui_outc(t_fg > 7 ? '9' : '3'); + vui_outc((t_fg & 7) + '0'); } if (chg_bg) { - if (chg_fg) *s++ = ';'; + if (chg_fg) vui_outc(';'); if (t_bg > 7) { - *s++ = '1'; - *s++ = '0'; + vui_outs("10"); } else { - *s++ = '4'; + vui_outc('4'); } - *s++ = (t_bg & 7) + '0'; + vui_outc((t_bg & 7) + '0'); } } - if (chg_fg || chg_bg || chg_attr) { - *s++ = 'm'; - fwrite(buf, 1, s - buf, stdout); - } - + if (chg_fg || chg_bg || chg_attr) vui_outc('m'); *ptr = to; } unsigned vui_changes = 0; unsigned vui_max_change = 0; -unsigned vui_repainted = 0; +unsigned vui_out_chars = 0; void vui_scroll_buf(VuiBuffer *b, int dx, int dy); @@ -307,7 +340,7 @@ void vui_blit(void) { VuiBuffer *front = vui_win.front; VuiBuffer *back = vui_win.back; - printf("\x1b[H\x1b[0m"); + vui_outf("\x1b[H\x1b[0m"); VuiAttr attr_last = ATTR_DEFAULT; if (vui_win.redraw_all) { @@ -315,20 +348,17 @@ void vui_blit(void) { for (unsigned y = 0; y < vui_win.height; y++) { for (unsigned x = 0; x < vui_win.width; x++) { attr_chg(&attr_last, ATTR(x, y)); - putchar(CHR(x, y)); + vui_outc(CHR(x, y)); } } - vui_repainted = vui_win.width * vui_win.height; vui_win.redraw_all = 0; goto copy_buf; } vui_changes = 0; vui_max_change = 0; - vui_repainted = 0; unsigned cur_x = 0, cur_y = 0; - /* TODO: * * Scroll without repainting whole screen: @@ -341,28 +371,35 @@ void vui_blit(void) { */ if (vui_win.scroll_x || vui_win.scroll_y) { + if (abs(vui_win.scroll_x) >= vui_win.width || abs(vui_win.scroll_y) > vui_win.height) { + vui_outs("\x1b[2J"); + goto scrolled; + } + if (vui_win.scroll_x < 0) { for (unsigned y = 0; y < vui_win.height; y++) { curs_move(cur_x, cur_y, 0, y); - printf("\x1b[%dP", -vui_win.scroll_x); + vui_outf("\x1b[%dP", -vui_win.scroll_x); cur_y = y; } } else if (vui_win.scroll_x > 0) { for (unsigned y = 0; y < vui_win.height; y++) { curs_move(cur_x, cur_y, 0, y); - printf("\x1b[%d@", vui_win.scroll_x); + vui_outf("\x1b[%d@", vui_win.scroll_x); cur_y = y; } } if (vui_win.scroll_y < 0) { curs_move(cur_x, cur_y, 0, 0); cur_x = (cur_y = 0); - printf("\x1b[%dM", -vui_win.scroll_y); + vui_outf("\x1b[%dM", -vui_win.scroll_y); } else if (vui_win.scroll_y > 0) { curs_move(cur_x, cur_y, 0, 0); cur_x = (cur_y = 0); - printf("\x1b[%dL", vui_win.scroll_y); + vui_outf("\x1b[%dL", vui_win.scroll_y); } + +scrolled: vui_scroll_buf(back, vui_win.scroll_x, vui_win.scroll_y); vui_win.scroll_x = 0; vui_win.scroll_y = 0; @@ -380,18 +417,17 @@ void vui_blit(void) { vui_changes++; curs_move(cur_x, cur_y, x0, y); attr_chg(&attr_last, a); - fwrite(&CHR(x0, y), 1, x - x0, stdout); - //printf("%.*s", x - x0, ); + vui_outsn(&CHR(x0, y), x - x0); cur_x = x; cur_y = y; - vui_repainted += x - x0; if (x - x0 > vui_max_change) vui_max_change = x - x0; } } } copy_buf: - fflush(stdout); + vui_out_chars = vui_outn; + vui_out_flush(); memcpy(back->chr, front->chr, sizeof(*back->chr) * (back->width * back->height)); memcpy(back->attr, front->attr, sizeof(*back->attr) * (back->width * back->height)); vui_win.front = back; @@ -509,15 +545,17 @@ int half_y = 1; void draw(void *ctx) { (void)ctx; + /* vui_chra(x, y, C, ((x + y) & 0xf) | BG_BBLUE); vui_chra(x-1, y, C, ((x + y) & 0xf) | BG_BLUE | A_UNDERSCORE); vui_chra(x+1, y, C, ((x + y) & 0xf) | BG_BLUE | A_UNDERSCORE); vui_chra(x, y-1, C, ((x + y) & 0xf) | BG_BLUE | A_UNDERSCORE); vui_chra(x, y+1, C, ((x + y) & 0xf) | BG_BLUE | A_UNDERSCORE); + */ vui_printf(-1, -1, "(%u, %u)", vui_win.width, vui_win.height); - vui_printf(0, -1, "front buffer = %p", (void*)vui_win.front); - vui_printf(-1, 0, "longest change = %3u, changes = %5u, repainted%% = %02u%%, chars = %5u", vui_max_change, vui_changes, vui_repainted * 100 / (vui_win.width * vui_win.height), vui_win.width * vui_win.height); + //vui_printf(0, -1, "front buffer = %p", (void*)vui_win.front); + vui_printf(-1, 0, "longest change = %3u, changes = %5u, output = %5u, chars = %5u", vui_max_change, vui_changes, vui_out_chars, vui_win.width * vui_win.height); vui_blit(); } @@ -560,7 +598,7 @@ int main(int argc, const char **argv) { static int paused = 0; vui_win.redraw_fn = draw; -#if 0 +#if 1 /* weird cellular automata */ if (!paused) { // int dx = 0, dy = 0; /* shadow on purpose */ -- cgit v1.2.3