svn commit: r338316 - in head/sys/dev/vt: . hw/efifb hw/fb hw/vga
Colin Percival
cperciva at FreeBSD.org
Sat Aug 25 16:14:59 UTC 2018
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
More information about the svn-src-all
mailing list