:: commit bf9962e86f1affa2a72960b9338b79de418db959

mintsuki <mintsuki@protonmail.com> — 2021-04-08 22:22

parents: 8bd7cf743c

gterm: Speed up terminal by doing sub-character pixel comparisons and only printing differences

diff --git a/stage23/lib/gterm.c b/stage23/lib/gterm.c
index 9c9fa5d0..2da56970 100644
--- a/stage23/lib/gterm.c
+++ b/stage23/lib/gterm.c
@@ -136,6 +136,23 @@ struct gterm_char {
     int bg;
 };
 
+static void plot_char_mem(uint32_t *buf, struct gterm_char *c, int x, int y) {
+    uint8_t *glyph = &vga_font[(size_t)c->c * VGA_FONT_HEIGHT];
+
+    for (int i = 0; i < VGA_FONT_HEIGHT; i++) {
+        for (int j = 0; j < VGA_FONT_WIDTH; j++) {
+            if ((glyph[i] & (0x80 >> j))) {
+                buf[i * VGA_FONT_WIDTH + j] = ansi_colours[c->fg];
+            } else {
+                if (c->bg == 8)
+                    buf[i * VGA_FONT_WIDTH + j] = bg_canvas[(y + i) * gterm_width + (x + j)];
+                else
+                    buf[i * VGA_FONT_WIDTH + j] = ansi_colours[c->bg];
+            }
+        }
+    }
+}
+
 void gterm_plot_char(struct gterm_char *c, int x, int y) {
     uint8_t *glyph = &vga_font[(size_t)c->c * VGA_FONT_HEIGHT];
 
@@ -154,10 +171,25 @@ void gterm_plot_char(struct gterm_char *c, int x, int y) {
 }
 
 static void plot_char_grid(struct gterm_char *c, int x, int y) {
+    uint32_t old_char[VGA_FONT_WIDTH * VGA_FONT_HEIGHT];
+    uint32_t new_char[VGA_FONT_WIDTH * VGA_FONT_HEIGHT];
+
+    plot_char_mem(old_char, &grid[x + y * cols],
+                  x * VGA_FONT_WIDTH + frame_width, y * VGA_FONT_HEIGHT + frame_height);
+    plot_char_mem(new_char, c,
+                  x * VGA_FONT_WIDTH + frame_width, y * VGA_FONT_HEIGHT + frame_height);
+
     if (!double_buffer_enabled) {
-        gterm_plot_char(c, x * VGA_FONT_WIDTH + frame_width,
-                         y * VGA_FONT_HEIGHT + frame_height);
+        for (int i = 0; i < VGA_FONT_HEIGHT; i++) {
+            for (int j = 0; j < VGA_FONT_WIDTH; j++) {
+                if (old_char[i * VGA_FONT_WIDTH + j] != new_char[i * VGA_FONT_WIDTH + j])
+                    gterm_plot_px(x * VGA_FONT_WIDTH + frame_width + j,
+                                  y * VGA_FONT_HEIGHT + frame_height + i,
+                                  new_char[i * VGA_FONT_WIDTH + j]);
+            }
+        }
     }
+
     grid[x + y * cols] = *c;
 }
 
@@ -177,11 +209,15 @@ static void draw_cursor(void) {
     }
 }
 
+static inline bool compare_char(struct gterm_char *a, struct gterm_char *b) {
+    return !(a->c != b->c || a->bg != b->bg || a->fg != b->fg);
+}
+
 static void scroll(void) {
     clear_cursor();
 
     for (int i = cols; i < rows * cols; i++) {
-        if (memcmp(&grid[i], &grid[i - cols], sizeof(struct gterm_char) != 0))
+        if (!compare_char(&grid[i], &grid[i - cols]))
             plot_char_grid(&grid[i], (i - cols) % cols, (i - cols) / cols);
     }
 
@@ -191,7 +227,7 @@ static void scroll(void) {
     empty.fg = 9;
     empty.bg = 8;
     for (int i = rows * cols - cols; i < rows * cols; i++) {
-        if (memcmp(&grid[i], &empty, sizeof(struct gterm_char) != 0))
+        if (!compare_char(&grid[i], &empty))
             plot_char_grid(&empty, i % cols, i / cols);
     }
 
tab: 248 wrap: offon