Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/vt/vt_buf.c
Show First 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | |||||
#include <sys/systm.h> | #include <sys/systm.h> | ||||
#include <dev/vt/vt.h> | #include <dev/vt/vt.h> | ||||
static MALLOC_DEFINE(M_VTBUF, "vtbuf", "vt buffer"); | static MALLOC_DEFINE(M_VTBUF, "vtbuf", "vt buffer"); | ||||
#define VTBUF_LOCK(vb) mtx_lock_spin(&(vb)->vb_lock) | #define VTBUF_LOCK(vb) mtx_lock_spin(&(vb)->vb_lock) | ||||
#define VTBUF_UNLOCK(vb) mtx_unlock_spin(&(vb)->vb_lock) | #define VTBUF_UNLOCK(vb) mtx_unlock_spin(&(vb)->vb_lock) | ||||
eadler: nit: please rename this to `ASSERT_VTBUF_IS_LOCKED` so that its more clear it is just an… | |||||
#define POS_INDEX(c, r) (((r) << 12) + (c)) | #define POS_INDEX(c, r) (((r) << 12) + (c)) | ||||
Not Done Inline Actionsalso, why bother defining this at all? Was this just a debugging artifact? eadler: also, why bother defining this at all? Was this just a debugging artifact? | |||||
#define POS_COPY(d, s) do { \ | #define POS_COPY(d, s) do { \ | ||||
(d).tp_col = (s).tp_col; \ | (d).tp_col = (s).tp_col; \ | ||||
(d).tp_row = (s).tp_row; \ | (d).tp_row = (s).tp_row; \ | ||||
} while (0) | } while (0) | ||||
#ifndef SC_NO_CUTPASTE | #ifndef SC_NO_CUTPASTE | ||||
static int vtbuf_htw(const struct vt_buf *vb, int row); | static int vtbuf_htw(const struct vt_buf *vb, int row); | ||||
static int vtbuf_wth(const struct vt_buf *vb, int row); | static int vtbuf_wth(const struct vt_buf *vb, int row); | ||||
▲ Show 20 Lines • Show All 185 Lines • ▼ Show 20 Lines | #ifndef SC_NO_CUTPASTE | ||||
if (vtbuf_in_this_range(POS_INDEX(sc, sr), POS_INDEX(col, row), | if (vtbuf_in_this_range(POS_INDEX(sc, sr), POS_INDEX(col, row), | ||||
POS_INDEX(ec, er), POS_INDEX(0, sz))) | POS_INDEX(ec, er), POS_INDEX(0, sz))) | ||||
return (1); | return (1); | ||||
#endif | #endif | ||||
return (0); | return (0); | ||||
} | } | ||||
static inline void | void | ||||
vtbuf_dirty_locked(struct vt_buf *vb, const term_rect_t *area) | vtbuf_lock(struct vt_buf *vb) | ||||
{ | { | ||||
VTBUF_LOCK(vb); | |||||
} | |||||
void | |||||
vtbuf_unlock(struct vt_buf *vb) | |||||
{ | |||||
VTBUF_UNLOCK(vb); | |||||
} | |||||
void | |||||
vtbuf_dirty(struct vt_buf *vb, const term_rect_t *area) | |||||
Not Done Inline ActionsWhy do we use functions here and macros for other things like vtbuf_is_locked? Can we not just use the macro directly? I have a mild preference for more functions and fewer macros (i.e., inline the macro into this function) as well. eadler: Why do we use functions here and macros for other things like `vtbuf_is_locked`? Can we not… | |||||
{ | |||||
if (vb->vb_dirtyrect.tr_begin.tp_row > area->tr_begin.tp_row) | if (vb->vb_dirtyrect.tr_begin.tp_row > area->tr_begin.tp_row) | ||||
vb->vb_dirtyrect.tr_begin.tp_row = area->tr_begin.tp_row; | vb->vb_dirtyrect.tr_begin.tp_row = area->tr_begin.tp_row; | ||||
if (vb->vb_dirtyrect.tr_begin.tp_col > area->tr_begin.tp_col) | if (vb->vb_dirtyrect.tr_begin.tp_col > area->tr_begin.tp_col) | ||||
vb->vb_dirtyrect.tr_begin.tp_col = area->tr_begin.tp_col; | vb->vb_dirtyrect.tr_begin.tp_col = area->tr_begin.tp_col; | ||||
if (vb->vb_dirtyrect.tr_end.tp_row < area->tr_end.tp_row) | if (vb->vb_dirtyrect.tr_end.tp_row < area->tr_end.tp_row) | ||||
vb->vb_dirtyrect.tr_end.tp_row = area->tr_end.tp_row; | vb->vb_dirtyrect.tr_end.tp_row = area->tr_end.tp_row; | ||||
if (vb->vb_dirtyrect.tr_end.tp_col < area->tr_end.tp_col) | if (vb->vb_dirtyrect.tr_end.tp_col < area->tr_end.tp_col) | ||||
vb->vb_dirtyrect.tr_end.tp_col = area->tr_end.tp_col; | vb->vb_dirtyrect.tr_end.tp_col = area->tr_end.tp_col; | ||||
} | } | ||||
void | |||||
vtbuf_dirty(struct vt_buf *vb, const term_rect_t *area) | |||||
{ | |||||
VTBUF_LOCK(vb); | |||||
vtbuf_dirty_locked(vb, area); | |||||
VTBUF_UNLOCK(vb); | |||||
} | |||||
static inline void | static inline void | ||||
vtbuf_dirty_cell_locked(struct vt_buf *vb, const term_pos_t *p) | vtbuf_dirty_cell(struct vt_buf *vb, const term_pos_t *p) | ||||
{ | { | ||||
term_rect_t area; | term_rect_t area; | ||||
area.tr_begin = *p; | area.tr_begin = *p; | ||||
area.tr_end.tp_row = p->tp_row + 1; | area.tr_end.tp_row = p->tp_row + 1; | ||||
area.tr_end.tp_col = p->tp_col + 1; | area.tr_end.tp_col = p->tp_col + 1; | ||||
vtbuf_dirty_locked(vb, &area); | vtbuf_dirty(vb, &area); | ||||
} | } | ||||
static void | static void | ||||
vtbuf_make_undirty(struct vt_buf *vb) | vtbuf_make_undirty(struct vt_buf *vb) | ||||
{ | { | ||||
vb->vb_dirtyrect.tr_begin = vb->vb_scr_size; | vb->vb_dirtyrect.tr_begin = vb->vb_scr_size; | ||||
vb->vb_dirtyrect.tr_end.tp_row = vb->vb_dirtyrect.tr_end.tp_col = 0; | vb->vb_dirtyrect.tr_end.tp_row = vb->vb_dirtyrect.tr_end.tp_col = 0; | ||||
} | } | ||||
void | void | ||||
vtbuf_undirty(struct vt_buf *vb, term_rect_t *r) | vtbuf_undirty(struct vt_buf *vb, term_rect_t *r) | ||||
{ | { | ||||
VTBUF_LOCK(vb); | |||||
*r = vb->vb_dirtyrect; | *r = vb->vb_dirtyrect; | ||||
vtbuf_make_undirty(vb); | vtbuf_make_undirty(vb); | ||||
VTBUF_UNLOCK(vb); | |||||
} | } | ||||
void | void | ||||
vtbuf_copy(struct vt_buf *vb, const term_rect_t *r, const term_pos_t *p2) | vtbuf_copy(struct vt_buf *vb, const term_rect_t *r, const term_pos_t *p2) | ||||
{ | { | ||||
const term_pos_t *p1 = &r->tr_begin; | const term_pos_t *p1 = &r->tr_begin; | ||||
term_rect_t area; | term_rect_t area; | ||||
unsigned int rows, cols; | unsigned int rows, cols; | ||||
▲ Show 20 Lines • Show All 47 Lines • ▼ Show 20 Lines | vtbuf_copy(struct vt_buf *vb, const term_rect_t *r, const term_pos_t *p2) | ||||
area.tr_begin = *p2; | area.tr_begin = *p2; | ||||
area.tr_end.tp_row = MIN(p2->tp_row + rows, vb->vb_scr_size.tp_row); | area.tr_end.tp_row = MIN(p2->tp_row + rows, vb->vb_scr_size.tp_row); | ||||
area.tr_end.tp_col = MIN(p2->tp_col + cols, vb->vb_scr_size.tp_col); | area.tr_end.tp_col = MIN(p2->tp_col + cols, vb->vb_scr_size.tp_col); | ||||
vtbuf_dirty(vb, &area); | vtbuf_dirty(vb, &area); | ||||
} | } | ||||
static void | static void | ||||
vtbuf_fill(struct vt_buf *vb, const term_rect_t *r, term_char_t c) | vtbuf_do_fill(struct vt_buf *vb, const term_rect_t *r, term_char_t c) | ||||
{ | { | ||||
unsigned int pr, pc; | unsigned int pr, pc; | ||||
term_char_t *row; | term_char_t *row; | ||||
for (pr = r->tr_begin.tp_row; pr < r->tr_end.tp_row; pr++) { | for (pr = r->tr_begin.tp_row; pr < r->tr_end.tp_row; pr++) { | ||||
row = vb->vb_rows[(vb->vb_curroffset + pr) % | row = vb->vb_rows[(vb->vb_curroffset + pr) % | ||||
VTBUF_MAX_HEIGHT(vb)]; | VTBUF_MAX_HEIGHT(vb)]; | ||||
for (pc = r->tr_begin.tp_col; pc < r->tr_end.tp_col; pc++) { | for (pc = r->tr_begin.tp_col; pc < r->tr_end.tp_col; pc++) { | ||||
row[pc] = c; | row[pc] = c; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
void | void | ||||
vtbuf_fill_locked(struct vt_buf *vb, const term_rect_t *r, term_char_t c) | vtbuf_fill(struct vt_buf *vb, const term_rect_t *r, term_char_t c) | ||||
{ | { | ||||
KASSERT(r->tr_begin.tp_row < vb->vb_scr_size.tp_row, | KASSERT(r->tr_begin.tp_row < vb->vb_scr_size.tp_row, | ||||
("vtbuf_fill_locked begin.tp_row %d must be < screen height %d", | ("vtbuf_fill begin.tp_row %d must be < screen height %d", | ||||
r->tr_begin.tp_row, vb->vb_scr_size.tp_row)); | r->tr_begin.tp_row, vb->vb_scr_size.tp_row)); | ||||
KASSERT(r->tr_begin.tp_col < vb->vb_scr_size.tp_col, | KASSERT(r->tr_begin.tp_col < vb->vb_scr_size.tp_col, | ||||
("vtbuf_fill_locked begin.tp_col %d must be < screen width %d", | ("vtbuf_fill begin.tp_col %d must be < screen width %d", | ||||
r->tr_begin.tp_col, vb->vb_scr_size.tp_col)); | r->tr_begin.tp_col, vb->vb_scr_size.tp_col)); | ||||
KASSERT(r->tr_end.tp_row <= vb->vb_scr_size.tp_row, | KASSERT(r->tr_end.tp_row <= vb->vb_scr_size.tp_row, | ||||
("vtbuf_fill_locked end.tp_row %d must be <= screen height %d", | ("vtbuf_fill end.tp_row %d must be <= screen height %d", | ||||
r->tr_end.tp_row, vb->vb_scr_size.tp_row)); | r->tr_end.tp_row, vb->vb_scr_size.tp_row)); | ||||
KASSERT(r->tr_end.tp_col <= vb->vb_scr_size.tp_col, | KASSERT(r->tr_end.tp_col <= vb->vb_scr_size.tp_col, | ||||
("vtbuf_fill_locked end.tp_col %d must be <= screen width %d", | ("vtbuf_fill end.tp_col %d must be <= screen width %d", | ||||
r->tr_end.tp_col, vb->vb_scr_size.tp_col)); | r->tr_end.tp_col, vb->vb_scr_size.tp_col)); | ||||
VTBUF_LOCK(vb); | vtbuf_do_fill(vb, r, c); | ||||
vtbuf_fill(vb, r, c); | vtbuf_dirty(vb, r); | ||||
vtbuf_dirty_locked(vb, r); | |||||
VTBUF_UNLOCK(vb); | |||||
} | } | ||||
static void | static void | ||||
vtbuf_init_rows(struct vt_buf *vb) | vtbuf_init_rows(struct vt_buf *vb) | ||||
{ | { | ||||
int r; | int r; | ||||
vb->vb_history_size = MAX(vb->vb_history_size, vb->vb_scr_size.tp_row); | vb->vb_history_size = MAX(vb->vb_history_size, vb->vb_scr_size.tp_row); | ||||
Show All 14 Lines | vtbuf_init_early(struct vt_buf *vb) | ||||
vb->vb_mark_start.tp_col = 0; | vb->vb_mark_start.tp_col = 0; | ||||
vb->vb_mark_end.tp_row = 0; | vb->vb_mark_end.tp_row = 0; | ||||
vb->vb_mark_end.tp_col = 0; | vb->vb_mark_end.tp_col = 0; | ||||
vtbuf_init_rows(vb); | vtbuf_init_rows(vb); | ||||
rect.tr_begin.tp_row = rect.tr_begin.tp_col = 0; | rect.tr_begin.tp_row = rect.tr_begin.tp_col = 0; | ||||
rect.tr_end.tp_col = vb->vb_scr_size.tp_col; | rect.tr_end.tp_col = vb->vb_scr_size.tp_col; | ||||
rect.tr_end.tp_row = vb->vb_history_size; | rect.tr_end.tp_row = vb->vb_history_size; | ||||
vtbuf_fill(vb, &rect, VTBUF_SPACE_CHAR(TERMINAL_NORM_ATTR)); | vtbuf_do_fill(vb, &rect, VTBUF_SPACE_CHAR(TERMINAL_NORM_ATTR)); | ||||
vtbuf_make_undirty(vb); | vtbuf_make_undirty(vb); | ||||
if ((vb->vb_flags & VBF_MTX_INIT) == 0) { | if ((vb->vb_flags & VBF_MTX_INIT) == 0) { | ||||
mtx_init(&vb->vb_lock, "vtbuf", NULL, MTX_SPIN); | mtx_init(&vb->vb_lock, "vtbuf", NULL, MTX_SPIN); | ||||
vb->vb_flags |= VBF_MTX_INIT; | vb->vb_flags |= VBF_MTX_INIT; | ||||
} | } | ||||
} | } | ||||
void | void | ||||
▲ Show 20 Lines • Show All 197 Lines • ▼ Show 20 Lines | KASSERT(p->tp_row < vb->vb_scr_size.tp_row, | ||||
p->tp_row, vb->vb_scr_size.tp_row)); | p->tp_row, vb->vb_scr_size.tp_row)); | ||||
KASSERT(p->tp_col < vb->vb_scr_size.tp_col, | KASSERT(p->tp_col < vb->vb_scr_size.tp_col, | ||||
("vtbuf_putchar tp_col %d must be less than screen height %d", | ("vtbuf_putchar tp_col %d must be less than screen height %d", | ||||
p->tp_col, vb->vb_scr_size.tp_col)); | p->tp_col, vb->vb_scr_size.tp_col)); | ||||
row = vb->vb_rows[(vb->vb_curroffset + p->tp_row) % | row = vb->vb_rows[(vb->vb_curroffset + p->tp_row) % | ||||
VTBUF_MAX_HEIGHT(vb)]; | VTBUF_MAX_HEIGHT(vb)]; | ||||
if (row[p->tp_col] != c) { | if (row[p->tp_col] != c) { | ||||
VTBUF_LOCK(vb); | |||||
row[p->tp_col] = c; | row[p->tp_col] = c; | ||||
vtbuf_dirty_cell_locked(vb, p); | vtbuf_dirty_cell(vb, p); | ||||
VTBUF_UNLOCK(vb); | |||||
} | } | ||||
} | } | ||||
void | void | ||||
vtbuf_cursor_position(struct vt_buf *vb, const term_pos_t *p) | vtbuf_cursor_position(struct vt_buf *vb, const term_pos_t *p) | ||||
{ | { | ||||
if (vb->vb_flags & VBF_CURSOR) { | if (vb->vb_flags & VBF_CURSOR) { | ||||
VTBUF_LOCK(vb); | vtbuf_dirty_cell(vb, &vb->vb_cursor); | ||||
vtbuf_dirty_cell_locked(vb, &vb->vb_cursor); | |||||
vb->vb_cursor = *p; | vb->vb_cursor = *p; | ||||
vtbuf_dirty_cell_locked(vb, &vb->vb_cursor); | vtbuf_dirty_cell(vb, &vb->vb_cursor); | ||||
VTBUF_UNLOCK(vb); | |||||
} else { | } else { | ||||
vb->vb_cursor = *p; | vb->vb_cursor = *p; | ||||
} | } | ||||
} | } | ||||
#ifndef SC_NO_CUTPASTE | #ifndef SC_NO_CUTPASTE | ||||
static void | static void | ||||
vtbuf_flush_mark(struct vt_buf *vb) | vtbuf_flush_mark(struct vt_buf *vb) | ||||
Show All 9 Lines | if ((vb->vb_mark_start.tp_col != vb->vb_mark_end.tp_col) || | ||||
e = vtbuf_htw(vb, vb->vb_mark_end.tp_row); | e = vtbuf_htw(vb, vb->vb_mark_end.tp_row); | ||||
area.tr_begin.tp_col = 0; | area.tr_begin.tp_col = 0; | ||||
area.tr_begin.tp_row = MIN(s, e); | area.tr_begin.tp_row = MIN(s, e); | ||||
area.tr_end.tp_col = vb->vb_scr_size.tp_col; | area.tr_end.tp_col = vb->vb_scr_size.tp_col; | ||||
area.tr_end.tp_row = MAX(s, e) + 1; | area.tr_end.tp_row = MAX(s, e) + 1; | ||||
VTBUF_LOCK(vb); | |||||
vtbuf_dirty(vb, &area); | vtbuf_dirty(vb, &area); | ||||
VTBUF_UNLOCK(vb); | |||||
} | } | ||||
} | } | ||||
int | int | ||||
vtbuf_get_marked_len(struct vt_buf *vb) | vtbuf_get_marked_len(struct vt_buf *vb) | ||||
{ | { | ||||
int ei, si, sz; | int ei, si, sz; | ||||
term_pos_t s, e; | term_pos_t s, e; | ||||
▲ Show 20 Lines • Show All 128 Lines • ▼ Show 20 Lines | vtbuf_cursor_visibility(struct vt_buf *vb, int yes) | ||||
oflags = vb->vb_flags; | oflags = vb->vb_flags; | ||||
if (yes) | if (yes) | ||||
vb->vb_flags |= VBF_CURSOR; | vb->vb_flags |= VBF_CURSOR; | ||||
else | else | ||||
vb->vb_flags &= ~VBF_CURSOR; | vb->vb_flags &= ~VBF_CURSOR; | ||||
nflags = vb->vb_flags; | nflags = vb->vb_flags; | ||||
if (oflags != nflags) | if (oflags != nflags) | ||||
vtbuf_dirty_cell_locked(vb, &vb->vb_cursor); | vtbuf_dirty_cell(vb, &vb->vb_cursor); | ||||
VTBUF_UNLOCK(vb); | VTBUF_UNLOCK(vb); | ||||
} | } | ||||
void | void | ||||
vtbuf_scroll_mode(struct vt_buf *vb, int yes) | vtbuf_scroll_mode(struct vt_buf *vb, int yes) | ||||
{ | { | ||||
int oflags, nflags; | int oflags, nflags; | ||||
VTBUF_LOCK(vb); | VTBUF_LOCK(vb); | ||||
oflags = vb->vb_flags; | oflags = vb->vb_flags; | ||||
if (yes) | if (yes) | ||||
vb->vb_flags |= VBF_SCROLL; | vb->vb_flags |= VBF_SCROLL; | ||||
else | else | ||||
vb->vb_flags &= ~VBF_SCROLL; | vb->vb_flags &= ~VBF_SCROLL; | ||||
nflags = vb->vb_flags; | nflags = vb->vb_flags; | ||||
if (oflags != nflags) | if (oflags != nflags) | ||||
vtbuf_dirty_cell_locked(vb, &vb->vb_cursor); | vtbuf_dirty_cell(vb, &vb->vb_cursor); | ||||
VTBUF_UNLOCK(vb); | VTBUF_UNLOCK(vb); | ||||
} | } | ||||
nit: please rename this to ASSERT_VTBUF_IS_LOCKED so that its more clear it is just an assertion