Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 25 Aug 2018 16:14:56 +0000 (UTC)
From:      Colin Percival <cperciva@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r338316 - in head/sys/dev/vt: . hw/efifb hw/fb hw/vga
Message-ID:  <201808251614.w7PGEujb000632@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: cperciva
Date: Sat Aug 25 16:14:56 2018
New Revision: 338316
URL: https://svnweb.freebsd.org/changeset/base/338316

Log:
  Speed up vt(4) by keeping a record of the most recently drawn character and
  the foreground and background colours.  In bitblt_text functions, compare
  values to this cache and don't re-draw the characters if they haven't changed.
  When invalidating the display, clear this cache in order to force characters
  to be redrawn; also force full redraws between suspend/resume pairs since odd
  artifacts can otherwise result.
  
  When scrolling the display (which is where most time is spent within the vt
  driver) this yields a significant performance improvement if most lines are
  less than the width of the terminal, since this avoids re-drawing blanks on
  top of blanks.
  
  (Note that "re-drawing" here includes writing to the VGA text mode buffer; on
  virtualized systems this can be extremely slow since it triggers a glyph
  being rendered onto a 640x480 screen).
  
  On a c5.4xlarge EC2 instance (with emulated text mode VGA) this cuts the time
  spent in vt(4) during the kernel boot from 1200 ms to 700ms; on my laptop
  (with a 3200x1800 display) the corresponding time is reduced from 970 ms down
  to 155 ms.
  
  Reviewed by:	imp, cem
  Approved by:	re (gjb)
  Relnotes:	Significant speedup in vt(4) and the system boot generally.
  Differential Revision:	https://reviews.freebsd.org/D16723

Modified:
  head/sys/dev/vt/hw/efifb/efifb.c
  head/sys/dev/vt/hw/fb/vt_early_fb.c
  head/sys/dev/vt/hw/fb/vt_fb.c
  head/sys/dev/vt/hw/fb/vt_fb.h
  head/sys/dev/vt/hw/vga/vt_vga.c
  head/sys/dev/vt/vt.h
  head/sys/dev/vt/vt_core.c

Modified: head/sys/dev/vt/hw/efifb/efifb.c
==============================================================================
--- head/sys/dev/vt/hw/efifb/efifb.c	Sat Aug 25 15:59:51 2018	(r338315)
+++ head/sys/dev/vt/hw/efifb/efifb.c	Sat Aug 25 16:14:56 2018	(r338316)
@@ -58,6 +58,7 @@ static struct vt_driver vt_efifb_driver = {
 	.vd_init = vt_efifb_init,
 	.vd_blank = vt_fb_blank,
 	.vd_bitblt_text = vt_fb_bitblt_text,
+	.vd_invalidate_text = vt_fb_invalidate_text,
 	.vd_bitblt_bmp = vt_fb_bitblt_bitmap,
 	.vd_drawrect = vt_fb_drawrect,
 	.vd_setpixel = vt_fb_setpixel,

Modified: head/sys/dev/vt/hw/fb/vt_early_fb.c
==============================================================================
--- head/sys/dev/vt/hw/fb/vt_early_fb.c	Sat Aug 25 15:59:51 2018	(r338315)
+++ head/sys/dev/vt/hw/fb/vt_early_fb.c	Sat Aug 25 16:14:56 2018	(r338316)
@@ -60,6 +60,7 @@ static struct vt_driver vt_fb_early_driver = {
 	.vd_init = vt_efb_init,
 	.vd_blank = vt_fb_blank,
 	.vd_bitblt_text = vt_fb_bitblt_text,
+	.vd_invalidate_text = vt_fb_invalidate_text,
 	.vd_bitblt_bmp = vt_fb_bitblt_bitmap,
 	.vd_drawrect = vt_fb_drawrect,
 	.vd_setpixel = vt_fb_setpixel,

Modified: head/sys/dev/vt/hw/fb/vt_fb.c
==============================================================================
--- head/sys/dev/vt/hw/fb/vt_fb.c	Sat Aug 25 15:59:51 2018	(r338315)
+++ head/sys/dev/vt/hw/fb/vt_fb.c	Sat Aug 25 16:14:56 2018	(r338316)
@@ -50,6 +50,7 @@ static struct vt_driver vt_fb_driver = {
 	.vd_fini = vt_fb_fini,
 	.vd_blank = vt_fb_blank,
 	.vd_bitblt_text = vt_fb_bitblt_text,
+	.vd_invalidate_text = vt_fb_invalidate_text,
 	.vd_bitblt_bmp = vt_fb_bitblt_bitmap,
 	.vd_drawrect = vt_fb_drawrect,
 	.vd_setpixel = vt_fb_setpixel,
@@ -335,6 +336,7 @@ vt_fb_bitblt_text(struct vt_device *vd, const struct v
 	term_char_t c;
 	term_color_t fg, bg;
 	const uint8_t *pattern;
+	size_t z;
 
 	vf = vw->vw_font;
 
@@ -351,9 +353,22 @@ vt_fb_bitblt_text(struct vt_device *vd, const struct v
 			vt_determine_colors(c,
 			    VTBUF_ISCURSOR(&vw->vw_buf, row, col), &fg, &bg);
 
+			z = row * PIXEL_WIDTH(VT_FB_MAX_WIDTH) + col;
+			if (vd->vd_drawn && (vd->vd_drawn[z] == c) &&
+			    vd->vd_drawnfg && (vd->vd_drawnfg[z] == fg) &&
+			    vd->vd_drawnbg && (vd->vd_drawnbg[z] == bg))
+				continue;
+
 			vt_fb_bitblt_bitmap(vd, vw,
 			    pattern, NULL, vf->vf_width, vf->vf_height,
 			    x, y, fg, bg);
+
+			if (vd->vd_drawn)
+				vd->vd_drawn[z] = c;
+			if (vd->vd_drawnfg)
+				vd->vd_drawnfg[z] = fg;
+			if (vd->vd_drawnbg)
+				vd->vd_drawnbg[z] = bg;
 		}
 	}
 
@@ -377,6 +392,26 @@ vt_fb_bitblt_text(struct vt_device *vd, const struct v
 		    vd->vd_mcursor_fg, vd->vd_mcursor_bg);
 	}
 #endif
+}
+
+void
+vt_fb_invalidate_text(struct vt_device *vd, const term_rect_t *area)
+{
+	unsigned int col, row;
+	size_t z;
+
+	for (row = area->tr_begin.tp_row; row < area->tr_end.tp_row; ++row) {
+		for (col = area->tr_begin.tp_col; col < area->tr_end.tp_col;
+		    ++col) {
+			z = row * PIXEL_WIDTH(VT_FB_MAX_WIDTH) + col;
+			if (vd->vd_drawn)
+				vd->vd_drawn[z] = 0;
+			if (vd->vd_drawnfg)
+				vd->vd_drawnfg[z] = 0;
+			if (vd->vd_drawnbg)
+				vd->vd_drawnbg[z] = 0;
+		}
+	}
 }
 
 void

Modified: head/sys/dev/vt/hw/fb/vt_fb.h
==============================================================================
--- head/sys/dev/vt/hw/fb/vt_fb.h	Sat Aug 25 15:59:51 2018	(r338315)
+++ head/sys/dev/vt/hw/fb/vt_fb.h	Sat Aug 25 16:14:56 2018	(r338316)
@@ -43,6 +43,7 @@ vd_init_t		vt_fb_init;
 vd_fini_t		vt_fb_fini;
 vd_blank_t		vt_fb_blank;
 vd_bitblt_text_t	vt_fb_bitblt_text;
+vd_invalidate_text_t	vt_fb_invalidate_text;
 vd_bitblt_bmp_t		vt_fb_bitblt_bitmap;
 vd_drawrect_t		vt_fb_drawrect;
 vd_setpixel_t		vt_fb_setpixel;

Modified: head/sys/dev/vt/hw/vga/vt_vga.c
==============================================================================
--- head/sys/dev/vt/hw/vga/vt_vga.c	Sat Aug 25 15:59:51 2018	(r338315)
+++ head/sys/dev/vt/hw/vga/vt_vga.c	Sat Aug 25 16:14:56 2018	(r338316)
@@ -97,6 +97,7 @@ static vd_probe_t	vga_probe;
 static vd_init_t	vga_init;
 static vd_blank_t	vga_blank;
 static vd_bitblt_text_t	vga_bitblt_text;
+static vd_invalidate_text_t	vga_invalidate_text;
 static vd_bitblt_bmp_t	vga_bitblt_bitmap;
 static vd_drawrect_t	vga_drawrect;
 static vd_setpixel_t	vga_setpixel;
@@ -108,6 +109,7 @@ static const struct vt_driver vt_vga_driver = {
 	.vd_init	= vga_init,
 	.vd_blank	= vga_blank,
 	.vd_bitblt_text	= vga_bitblt_text,
+	.vd_invalidate_text = vga_invalidate_text,
 	.vd_bitblt_bmp	= vga_bitblt_bitmap,
 	.vd_drawrect	= vga_drawrect,
 	.vd_setpixel	= vga_setpixel,
@@ -868,6 +870,7 @@ vga_bitblt_text_txtmode(struct vt_device *vd, const st
 	term_char_t c;
 	term_color_t fg, bg;
 	uint8_t ch, attr;
+	size_t z;
 
 	sc = vd->vd_softc;
 	vb = &vw->vw_buf;
@@ -884,6 +887,12 @@ vga_bitblt_text_txtmode(struct vt_device *vd, const st
 			vt_determine_colors(c, VTBUF_ISCURSOR(vb, row, col),
 			    &fg, &bg);
 
+			z = row * PIXEL_WIDTH(VT_FB_MAX_WIDTH) + col;
+			if (vd->vd_drawn && (vd->vd_drawn[z] == c) &&
+			    vd->vd_drawnfg && (vd->vd_drawnfg[z] == fg) &&
+			    vd->vd_drawnbg && (vd->vd_drawnbg[z] == bg))
+				continue;
+
 			/*
 			 * Convert character to CP437, which is the
 			 * character set used by the VGA hardware by
@@ -898,6 +907,13 @@ vga_bitblt_text_txtmode(struct vt_device *vd, const st
 
 			MEM_WRITE2(sc, (row * 80 + col) * 2 + 0,
 			    ch + ((uint16_t)(attr) << 8));
+
+			if (vd->vd_drawn)
+				vd->vd_drawn[z] = c;
+			if (vd->vd_drawnfg)
+				vd->vd_drawnfg[z] = fg;
+			if (vd->vd_drawnbg)
+				vd->vd_drawnbg[z] = bg;
 		}
 	}
 }
@@ -911,6 +927,27 @@ vga_bitblt_text(struct vt_device *vd, const struct vt_
 		vga_bitblt_text_gfxmode(vd, vw, area);
 	} else {
 		vga_bitblt_text_txtmode(vd, vw, area);
+	}
+}
+
+void
+vga_invalidate_text(struct vt_device *vd, const term_rect_t *area)
+{
+	unsigned int col, row;
+	size_t z;
+
+	for (row = area->tr_begin.tp_row; row < area->tr_end.tp_row; ++row) {
+		for (col = area->tr_begin.tp_col;
+		    col < area->tr_end.tp_col;
+		    ++col) {
+			z = row * PIXEL_WIDTH(VT_FB_MAX_WIDTH) + col;
+			if (vd->vd_drawn)
+				vd->vd_drawn[z] = 0;
+			if (vd->vd_drawnfg)
+				vd->vd_drawnfg[z] = 0;
+			if (vd->vd_drawnbg)
+				vd->vd_drawnbg[z] = 0;
+		}
 	}
 }
 

Modified: head/sys/dev/vt/vt.h
==============================================================================
--- head/sys/dev/vt/vt.h	Sat Aug 25 15:59:51 2018	(r338315)
+++ head/sys/dev/vt/vt.h	Sat Aug 25 16:14:56 2018	(r338316)
@@ -156,11 +156,15 @@ struct vt_device {
 #define	VDF_INITIALIZED	0x20	/* vtterm_cnprobe already done. */
 #define	VDF_MOUSECURSOR	0x40	/* Mouse cursor visible. */
 #define	VDF_QUIET_BELL	0x80	/* Disable bell. */
+#define	VDF_SUSPENDED	0x100	/* Device has been suspended. */
 #define	VDF_DOWNGRADE	0x8000	/* The driver is being downgraded. */
 	int			 vd_keyboard;	/* (G) Keyboard index. */
 	unsigned int		 vd_kbstate;	/* (?) Device unit. */
 	unsigned int		 vd_unit;	/* (c) Device unit. */
 	int			 vd_altbrk;	/* (?) Alt break seq. state */
+	term_char_t		*vd_drawn;	/* (?) Most recent char drawn. */
+	term_color_t		*vd_drawnfg;	/* (?) Most recent fg color drawn. */
+	term_color_t		*vd_drawnbg;	/* (?) Most recent bg color drawn. */
 };
 
 #define	VD_PASTEBUF(vd)	((vd)->vd_pastebuf.vpb_buf)
@@ -320,6 +324,8 @@ typedef void vd_postswitch_t(struct vt_device *vd);
 typedef void vd_blank_t(struct vt_device *vd, term_color_t color);
 typedef void vd_bitblt_text_t(struct vt_device *vd, const struct vt_window *vw,
     const term_rect_t *area);
+typedef void vd_invalidate_text_t(struct vt_device *vd,
+    const term_rect_t *area);
 typedef void vd_bitblt_bmp_t(struct vt_device *vd, const struct vt_window *vw,
     const uint8_t *pattern, const uint8_t *mask,
     unsigned int width, unsigned int height,
@@ -345,6 +351,7 @@ struct vt_driver {
 	vd_drawrect_t	*vd_drawrect;
 	vd_setpixel_t	*vd_setpixel;
 	vd_bitblt_text_t *vd_bitblt_text;
+	vd_invalidate_text_t *vd_invalidate_text;
 	vd_bitblt_bmp_t	*vd_bitblt_bmp;
 
 	/* Framebuffer ioctls, if present. */

Modified: head/sys/dev/vt/vt_core.c
==============================================================================
--- head/sys/dev/vt/vt_core.c	Sat Aug 25 15:59:51 2018	(r338315)
+++ head/sys/dev/vt/vt_core.c	Sat Aug 25 16:14:56 2018	(r338316)
@@ -190,6 +190,11 @@ SET_DECLARE(vt_drv_set, struct vt_driver);
 
 struct terminal	vt_consterm;
 static struct vt_window	vt_conswindow;
+#ifndef SC_NO_CONSDRAWN
+static term_char_t vt_consdrawn[PIXEL_HEIGHT(VT_FB_MAX_HEIGHT) * PIXEL_WIDTH(VT_FB_MAX_WIDTH)];
+static term_color_t vt_consdrawnfg[PIXEL_HEIGHT(VT_FB_MAX_HEIGHT) * PIXEL_WIDTH(VT_FB_MAX_WIDTH)];
+static term_color_t vt_consdrawnbg[PIXEL_HEIGHT(VT_FB_MAX_HEIGHT) * PIXEL_WIDTH(VT_FB_MAX_WIDTH)];
+#endif
 struct vt_device	vt_consdev = {
 	.vd_driver = NULL,
 	.vd_softc = NULL,
@@ -210,6 +215,12 @@ struct vt_device	vt_consdev = {
 	.vd_mcursor_fg = TC_WHITE,
 	.vd_mcursor_bg = TC_BLACK,
 #endif
+
+#ifndef SC_NO_CONSDRAWN
+	.vd_drawn = vt_consdrawn,
+	.vd_drawnfg = vt_consdrawnfg,
+	.vd_drawnbg = vt_consdrawnbg,
+#endif
 };
 static term_char_t vt_constextbuf[(_VTDEFW) * (VBF_DEFAULT_HISTORY_SIZE)];
 static term_char_t *vt_constextbufrows[VBF_DEFAULT_HISTORY_SIZE];
@@ -1181,6 +1192,8 @@ vt_mark_mouse_position_as_dirty(struct vt_device *vd, 
 
 	if (!locked)
 		vtbuf_lock(&vw->vw_buf);
+	if (vd->vd_driver->vd_invalidate_text)
+		vd->vd_driver->vd_invalidate_text(vd, &area);
 	vtbuf_dirty(&vw->vw_buf, &area);
 	if (!locked)
 		vtbuf_unlock(&vw->vw_buf);
@@ -1280,12 +1293,14 @@ vt_flush(struct vt_device *vd)
 
 	vtbuf_undirty(&vw->vw_buf, &tarea);
 
-	/* Force a full redraw when the screen contents are invalid. */
-	if (vd->vd_flags & VDF_INVALID) {
+	/* Force a full redraw when the screen contents might be invalid. */
+	if (vd->vd_flags & (VDF_INVALID | VDF_SUSPENDED)) {
 		vd->vd_flags &= ~VDF_INVALID;
 
 		vt_set_border(vd, &vw->vw_draw_area, TC_BLACK);
 		vt_termrect(vd, vf, &tarea);
+		if (vd->vd_driver->vd_invalidate_text)
+			vd->vd_driver->vd_invalidate_text(vd, &tarea);
 		if (vt_draw_logo_cpus)
 			vtterm_draw_cpu_logos(vd);
 	}
@@ -2824,6 +2839,7 @@ vt_suspend_handler(void *priv)
 	struct vt_device *vd;
 
 	vd = priv;
+	vd->vd_flags |= VDF_SUSPENDED;
 	if (vd->vd_driver != NULL && vd->vd_driver->vd_suspend != NULL)
 		vd->vd_driver->vd_suspend(vd);
 }
@@ -2836,6 +2852,7 @@ vt_resume_handler(void *priv)
 	vd = priv;
 	if (vd->vd_driver != NULL && vd->vd_driver->vd_resume != NULL)
 		vd->vd_driver->vd_resume(vd);
+	vd->vd_flags &= ~VDF_SUSPENDED;
 }
 
 void



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201808251614.w7PGEujb000632>