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
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to