From 1326affa398914105b7a7352f84f44a740b595ca Mon Sep 17 00:00:00 2001 From: dzwdz Date: Sat, 6 Aug 2022 15:08:07 +0200 Subject: user/vterm: 2d flushing --- src/user/app/vterm/draw.c | 50 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 41 insertions(+), 9 deletions(-) diff --git a/src/user/app/vterm/draw.c b/src/user/app/vterm/draw.c index 44d3ffe..1a40ede 100644 --- a/src/user/app/vterm/draw.c +++ b/src/user/app/vterm/draw.c @@ -1,4 +1,5 @@ #include "vterm.h" +#include #include #include @@ -14,19 +15,50 @@ void dirty_mark(uint32_t x, uint32_t y) { if (dirty.y2 < y) dirty.y2 = y; } +static void flush_combined(struct rect pix) { + size_t low = fb.pitch * pix.y1 + 4 * pix.x1; + size_t high = fb.pitch * pix.y2 + 4 * pix.y2 + 4; + + _syscall_write(fb_fd, fb.b + low, high - low, low, 0); +} + +static void flush_split(struct rect pix) { + static uint64_t execbuf[EXECBUF_MAX_LEN / sizeof(uint64_t)]; + if (7 * (pix.y2 - pix.y1) * sizeof(uint64_t) >= sizeof execbuf) { + flush_combined(pix); + return; + } + + size_t epos = 0; + for (uint32_t y = pix.y1; y < pix.y2; y++) { + size_t low = fb.pitch * y + 4 * pix.x1; + size_t high = fb.pitch * y + 4 * pix.x2 + 4; + + execbuf[epos++] = EXECBUF_SYSCALL; + execbuf[epos++] = _SYSCALL_WRITE; + execbuf[epos++] = fb_fd; + execbuf[epos++] = fb.b + low; + execbuf[epos++] = high - low; + execbuf[epos++] = low; + execbuf[epos++] = 0; + } + _syscall_execbuf(execbuf, epos * sizeof(uint64_t)); +} + void flush(void) { - size_t low, high; if (~dirty.x1 == 0) return; - // still not optimal, copies 80 characters instead of 1 - low = fb.pitch * ( dirty.y1 * font.h) + 4 * ( dirty.x1 * font.w); - high = fb.pitch * ((dirty.y2+1) * font.h) + 4 * ((dirty.x2+1) * font.w) + 3; - - if (~dirty.y2 == 0) high = fb.len; - if (high > fb.len) high = fb.len; + struct rect pix; + pix.x1 = dirty.x1 * font.w; + pix.x2 = dirty.x2 * font.w + font.w - 1; + pix.y1 = dirty.y1 * font.h; + pix.y2 = dirty.y2 * font.h + font.h - 1; + if (pix.x2 >= fb.width) pix.x2 = fb.width - 1; + if (pix.y2 >= fb.height) pix.y2 = fb.height - 1; - while (low < high) - low += _syscall_write(fb_fd, fb.b + low, high - low, low, 0); + /* the threshold is mostly arbitrary, wasn't based on any real benchmarks */ + if (pix.x2 - pix.x1 > fb.width - 600) flush_combined(pix); + else flush_split(pix); dirty.x1 = ~0; dirty.y1 = ~0; dirty.x2 = 0; dirty.y2 = 0; -- cgit v1.2.3