summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorfcambus <fcambus@openbsd.org>2020-07-11 15:02:52 +0000
committerfcambus <fcambus@openbsd.org>2020-07-11 15:02:52 +0000
commit0464d59668f0aaada84238c6ab0ea92e16ed13e8 (patch)
treebf96b73c68f76bfab5639a2597e603e6133fe4bf
parentImplement linear and power-of-two histograms: hist() and lhist() keywords. (diff)
downloadwireguard-openbsd-0464d59668f0aaada84238c6ab0ea92e16ed13e8.tar.xz
wireguard-openbsd-0464d59668f0aaada84238c6ab0ea92e16ed13e8.zip
Optimize rasops_vcons_copyrows() so write-only framebuffer consoles
only redraw the characters that differ between the start and end positions. This makes scrolling significantly faster. From John Carmack, thanks! OK jcs@
-rw-r--r--sys/dev/rasops/rasops.c37
1 files changed, 26 insertions, 11 deletions
diff --git a/sys/dev/rasops/rasops.c b/sys/dev/rasops/rasops.c
index d827efec44a..87dbe409d95 100644
--- a/sys/dev/rasops/rasops.c
+++ b/sys/dev/rasops/rasops.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rasops.c,v 1.62 2020/06/16 21:49:30 mortimer Exp $ */
+/* $OpenBSD: rasops.c,v 1.63 2020/07/11 15:02:52 fcambus Exp $ */
/* $NetBSD: rasops.c,v 1.35 2001/02/02 06:01:01 marcus Exp $ */
/*-
@@ -1627,28 +1627,43 @@ rasops_vcons_copyrows(void *cookie, int src, int dst, int num)
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));
- 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;
}