This causes the write-only framebuffer console to only redraw the
chars that differ between the start and end positions.
'time ls -R /usr/src/sys' is 3x faster with this, because most of
the characters stay the same after a scroll.
If this looks good, I can do the same thing for clear rows and copy/
clear columns, although I will need to make a test case for them.
It would probably be a good idea to change the rasops interface to
have generic block copy and clear oeprations, versus the current
full-column / full-row interface, so tmux and friends could get the
full acceleration.
Index: rasops.c
===================================================================
RCS file: /cvs/src/sys/dev/rasops/rasops.c,v
retrieving revision 1.61
diff -u -p -r1.61 rasops.c
--- rasops.c 25 May 2020 09:55:49 -0000 1.61
+++ rasops.c 26 Jun 2020 04:14:13 -0000
@@ -1627,28 +1627,42 @@ rasops_vcons_copyrows(void *cookie, int
struct rasops_info *ri = scr->rs_ri;
int cols = ri->ri_cols;
int row, col, rc;
+ int srcofs;
+ int move;
+ /* update the scrollback buffer if the entire screen is moving */
if (dst == 0 && (src + num == ri->ri_rows) && scr->rs_sbscreens > 0)
memmove(&scr->rs_bs[dst], &scr->rs_bs[src * cols],
- ((ri->ri_rows * (scr->rs_sbscreens + 1) * cols) -
- (src * cols)) * sizeof(struct wsdisplay_charcell));
- else
+ ri->ri_rows * scr->rs_sbscreens * cols
+ * sizeof(struct wsdisplay_charcell));
+
+ /* copy everything */
+ if ((ri->ri_flg & RI_WRONLY) == 0 || !scr->rs_visible) {
memmove(&scr->rs_bs[dst * cols + scr->rs_dispoffset],
- &scr->rs_bs[src * cols + scr->rs_dispoffset],
- num * cols * sizeof(struct wsdisplay_charcell));
+ &scr->rs_bs[src * cols + scr->rs_dispoffset],
+ num * cols * sizeof(struct wsdisplay_charcell));
- if (!scr->rs_visible)
- return 0;
+ if (!scr->rs_visible)
+ return 0;
- if ((ri->ri_flg & RI_WRONLY) == 0)
return ri->ri_copyrows(ri, src, dst, num);
+ }
- for (row = dst; row < dst + num; row++) {
+ /* smart update, only redraw characters that are different */
+ srcofs = (src - dst) * cols;
+
+ for (move = 0 ; move < num ; move++) {
+ row = srcofs > 0 ? dst + move : dst + num - 1 - move;
for (col = 0; col < cols; col++) {
int off = row * cols + col + scr->rs_dispoffset;
-
- rc = ri->ri_putchar(ri, row, col,
- scr->rs_bs[off].uc, scr->rs_bs[off].attr);
+ int newc = scr->rs_bs[off+srcofs].uc;
+ int newa = scr->rs_bs[off+srcofs].attr;
+ if ( scr->rs_bs[off].uc == newc
+ && scr->rs_bs[off].attr == newa )
+ continue;
+ scr->rs_bs[off].uc = newc;
+ scr->rs_bs[off].attr = newa;
+ rc = ri->ri_putchar(ri, row, col, newc, newa);
if (rc != 0)
return rc;
}