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>