Index: head/sys/dev/vt/hw/efifb/efifb.c =================================================================== --- head/sys/dev/vt/hw/efifb/efifb.c +++ head/sys/dev/vt/hw/efifb/efifb.c @@ -58,6 +58,7 @@ .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, Index: head/sys/dev/vt/hw/fb/vt_early_fb.c =================================================================== --- head/sys/dev/vt/hw/fb/vt_early_fb.c +++ head/sys/dev/vt/hw/fb/vt_early_fb.c @@ -60,6 +60,7 @@ .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, Index: head/sys/dev/vt/hw/fb/vt_fb.h =================================================================== --- head/sys/dev/vt/hw/fb/vt_fb.h +++ head/sys/dev/vt/hw/fb/vt_fb.h @@ -43,6 +43,7 @@ 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; Index: head/sys/dev/vt/hw/fb/vt_fb.c =================================================================== --- head/sys/dev/vt/hw/fb/vt_fb.c +++ head/sys/dev/vt/hw/fb/vt_fb.c @@ -50,6 +50,7 @@ .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 @@ 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_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 @@ 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 Index: head/sys/dev/vt/hw/vga/vt_vga.c =================================================================== --- head/sys/dev/vt/hw/vga/vt_vga.c +++ head/sys/dev/vt/hw/vga/vt_vga.c @@ -97,6 +97,7 @@ 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 @@ .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 @@ 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 @@ 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 @@ 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_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; + } } } Index: head/sys/dev/vt/vt.h =================================================================== --- head/sys/dev/vt/vt.h +++ head/sys/dev/vt/vt.h @@ -156,11 +156,15 @@ #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_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 @@ 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. */ Index: head/sys/dev/vt/vt_core.c =================================================================== --- head/sys/dev/vt/vt_core.c +++ head/sys/dev/vt/vt_core.c @@ -190,6 +190,11 @@ 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 @@ .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 @@ 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 @@ 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 @@ 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 @@ 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