Page MenuHomeFreeBSD

D42057.diff
No OneTemporary

D42057.diff

diff --git a/sys/dev/vt/vt.h b/sys/dev/vt/vt.h
--- a/sys/dev/vt/vt.h
+++ b/sys/dev/vt/vt.h
@@ -165,6 +165,9 @@
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. */
+
+ struct mtx vd_flush_lock; /* (?) vt_flush() lock. */
+ bool *vd_pos_to_flush;/* (?) Positions to flush. */
};
#define VD_PASTEBUF(vd) ((vd)->vd_pastebuf.vpb_buf)
@@ -175,6 +178,14 @@
#define VT_UNLOCK(vd) mtx_unlock(&(vd)->vd_lock)
#define VT_LOCK_ASSERT(vd, what) mtx_assert(&(vd)->vd_lock, what)
+#define VT_FLUSH_LOCK(vd) \
+ if ((vd)->vd_driver->vd_bitblt_after_vtbuf_unlock) \
+ mtx_lock(&(vd)->vd_flush_lock)
+
+#define VT_FLUSH_UNLOCK(vd) \
+ if ((vd)->vd_driver->vd_bitblt_after_vtbuf_unlock) \
+ mtx_unlock(&(vd)->vd_flush_lock)
+
void vt_resume(struct vt_device *vd);
void vt_resume_flush_timer(struct vt_window *vw, int ms);
void vt_suspend(struct vt_device *vd);
@@ -376,6 +387,14 @@
#define VD_PRIORITY_DUMB 10
#define VD_PRIORITY_GENERIC 100
#define VD_PRIORITY_SPECIFIC 1000
+
+ /*
+ * Should vd_bitblt_text() be called after unlocking vtbuf? If true,
+ * characters are copied before vd_bitblt_bmp() is called.
+ *
+ * This is only valid when the default bitblt_text callback is used.
+ */
+ bool vd_bitblt_after_vtbuf_unlock;
};
/*
diff --git a/sys/dev/vt/vt_core.c b/sys/dev/vt/vt_core.c
--- a/sys/dev/vt/vt_core.c
+++ b/sys/dev/vt/vt_core.c
@@ -202,11 +202,10 @@
static 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
+static bool vt_cons_pos_to_flush[PIXEL_HEIGHT(VT_FB_MAX_HEIGHT) * PIXEL_WIDTH(VT_FB_MAX_WIDTH)];
struct vt_device vt_consdev = {
.vd_driver = NULL,
.vd_softc = NULL,
@@ -228,11 +227,11 @@
.vd_mcursor_bg = TC_BLACK,
#endif
-#ifndef SC_NO_CONSDRAWN
.vd_drawn = vt_consdrawn,
.vd_drawnfg = vt_consdrawnfg,
.vd_drawnbg = vt_consdrawnbg,
-#endif
+
+ .vd_pos_to_flush = vt_cons_pos_to_flush,
};
static term_char_t vt_constextbuf[(_VTDEFW) * (VBF_DEFAULT_HISTORY_SIZE)];
static term_char_t *vt_constextbufrows[VBF_DEFAULT_HISTORY_SIZE];
@@ -292,6 +291,7 @@
printf("VT: init without driver.\n");
mtx_init(&main_vd->vd_lock, "vtdev", NULL, MTX_DEF);
+ mtx_init(&main_vd->vd_flush_lock, "vtdev flush", NULL, MTX_DEF);
cv_init(&main_vd->vd_winswitch, "vtwswt");
}
@@ -1348,6 +1348,122 @@
vd->vd_height - 1, 1, c);
}
+static void
+vt_flush_to_buffer(struct vt_device *vd,
+ const struct vt_window *vw, const term_rect_t *area)
+{
+ unsigned int col, row;
+ term_char_t c;
+ term_color_t fg, bg;
+ 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 (z >= PIXEL_HEIGHT(VT_FB_MAX_HEIGHT) *
+ PIXEL_WIDTH(VT_FB_MAX_WIDTH))
+ continue;
+
+ c = VTBUF_GET_FIELD(&vw->vw_buf, row, col);
+ vt_determine_colors(c,
+ VTBUF_ISCURSOR(&vw->vw_buf, row, col), &fg, &bg);
+
+ 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)) {
+ vd->vd_pos_to_flush[z] = false;
+ continue;
+ }
+
+ vd->vd_pos_to_flush[z] = true;
+
+ 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;
+ }
+ }
+}
+
+static void
+vt_bitblt_buffer(struct vt_device *vd, const struct vt_window *vw,
+ const term_rect_t *area)
+{
+ unsigned int col, row, x, y;
+ struct vt_font *vf;
+ term_char_t c;
+ term_color_t fg, bg;
+ const uint8_t *pattern;
+ size_t z;
+
+ vf = vw->vw_font;
+
+ 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) {
+ x = col * vf->vf_width +
+ vw->vw_draw_area.tr_begin.tp_col;
+ y = row * vf->vf_height +
+ vw->vw_draw_area.tr_begin.tp_row;
+
+ z = row * PIXEL_WIDTH(VT_FB_MAX_WIDTH) + col;
+ if (z >= PIXEL_HEIGHT(VT_FB_MAX_HEIGHT) *
+ PIXEL_WIDTH(VT_FB_MAX_WIDTH))
+ continue;
+ if (!vd->vd_pos_to_flush[z])
+ continue;
+
+ c = vd->vd_drawn[z];
+ fg = vd->vd_drawnfg[z];
+ bg = vd->vd_drawnbg[z];
+
+ pattern = vtfont_lookup(vf, c);
+ vd->vd_driver->vd_bitblt_bmp(vd, vw,
+ pattern, NULL, vf->vf_width, vf->vf_height,
+ x, y, fg, bg);
+ }
+ }
+
+#ifndef SC_NO_CUTPASTE
+ if (!vd->vd_mshown)
+ return;
+
+ term_rect_t drawn_area;
+
+ drawn_area.tr_begin.tp_col = area->tr_begin.tp_col * vf->vf_width;
+ drawn_area.tr_begin.tp_row = area->tr_begin.tp_row * vf->vf_height;
+ drawn_area.tr_end.tp_col = area->tr_end.tp_col * vf->vf_width;
+ drawn_area.tr_end.tp_row = area->tr_end.tp_row * vf->vf_height;
+
+ if (vt_is_cursor_in_area(vd, &drawn_area)) {
+ vd->vd_driver->vd_bitblt_bmp(vd, vw,
+ vd->vd_mcursor->map, vd->vd_mcursor->mask,
+ vd->vd_mcursor->width, vd->vd_mcursor->height,
+ vd->vd_mx_drawn + vw->vw_draw_area.tr_begin.tp_col,
+ vd->vd_my_drawn + vw->vw_draw_area.tr_begin.tp_row,
+ vd->vd_mcursor_fg, vd->vd_mcursor_bg);
+ }
+#endif
+}
+
+static void
+vt_draw_decorations(struct vt_device *vd)
+{
+ struct vt_window *vw;
+ const teken_attr_t *a;
+
+ vw = vd->vd_curwindow;
+
+ a = teken_get_curattr(&vw->vw_terminal->tm_emulator);
+ vt_set_border(vd, &vw->vw_draw_area, a->ta_bgcolor);
+
+ if (vt_draw_logo_cpus)
+ vtterm_draw_cpu_logos(vd);
+}
+
static int
vt_flush(struct vt_device *vd)
{
@@ -1357,6 +1473,7 @@
#ifndef SC_NO_CUTPASTE
int cursor_was_shown, cursor_moved;
#endif
+ bool needs_refresh;
if (inside_vt_flush && KERNEL_PANICKED())
return (0);
@@ -1372,8 +1489,9 @@
if (((vd->vd_flags & VDF_TEXTMODE) == 0) && (vf == NULL))
return (0);
- vtbuf_lock(&vw->vw_buf);
+ VT_FLUSH_LOCK(vd);
+ vtbuf_lock(&vw->vw_buf);
inside_vt_flush = true;
#ifndef SC_NO_CUTPASTE
@@ -1417,29 +1535,63 @@
vtbuf_undirty(&vw->vw_buf, &tarea);
/* Force a full redraw when the screen contents might be invalid. */
+ needs_refresh = false;
if (vd->vd_flags & (VDF_INVALID | VDF_SUSPENDED)) {
- const teken_attr_t *a;
-
+ needs_refresh = true;
vd->vd_flags &= ~VDF_INVALID;
- a = teken_get_curattr(&vw->vw_terminal->tm_emulator);
- vt_set_border(vd, &vw->vw_draw_area, a->ta_bgcolor);
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);
}
if (tarea.tr_begin.tp_col < tarea.tr_end.tp_col) {
- vd->vd_driver->vd_bitblt_text(vd, vw, &tarea);
- inside_vt_flush = false;
- vtbuf_unlock(&vw->vw_buf);
+ if (vd->vd_driver->vd_bitblt_after_vtbuf_unlock) {
+ /*
+ * When `vd_bitblt_after_vtbuf_unlock` is set to true,
+ * we first remember the characters to redraw. They are
+ * already copied to the `vd_drawn` arrays.
+ *
+ * We then unlock vt_buf and proceed with the actual
+ * drawing using the backend driver.
+ */
+ vt_flush_to_buffer(vd, vw, &tarea);
+ vtbuf_unlock(&vw->vw_buf);
+ vt_bitblt_buffer(vd, vw, &tarea);
+
+ if (needs_refresh)
+ vt_draw_decorations(vd);
+
+ /*
+ * We can reset `inside_vt_flush` after unlocking vtbuf
+ * here because we also hold vt_flush_lock in this code
+ * path.
+ */
+ inside_vt_flush = false;
+ } else {
+ /*
+ * When `vd_bitblt_after_vtbuf_unlock` is false, we use
+ * the backend's `vd_bitblt_text` callback directly.
+ */
+ vd->vd_driver->vd_bitblt_text(vd, vw, &tarea);
+
+ if (needs_refresh)
+ vt_draw_decorations(vd);
+
+ inside_vt_flush = false;
+ vtbuf_unlock(&vw->vw_buf);
+ }
+
+ VT_FLUSH_UNLOCK(vd);
+
return (1);
}
inside_vt_flush = false;
vtbuf_unlock(&vw->vw_buf);
+
+ VT_FLUSH_UNLOCK(vd);
+
return (0);
}

File Metadata

Mime Type
text/plain
Expires
Sun, Nov 17, 5:46 AM (21 h, 43 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
14671227
Default Alt Text
D42057.diff (8 KB)

Event Timeline