vt_buf.c (219888) | vt_buf.c (256145) |
---|---|
1/*- 2 * Copyright (c) 2009 The FreeBSD Foundation 3 * All rights reserved. 4 * 5 * This software was developed by Ed Schouten under sponsorship from the 6 * FreeBSD Foundation. 7 * 8 * Redistribution and use in source and binary forms, with or without --- 14 unchanged lines hidden (view full) --- 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30#include <sys/cdefs.h> | 1/*- 2 * Copyright (c) 2009 The FreeBSD Foundation 3 * All rights reserved. 4 * 5 * This software was developed by Ed Schouten under sponsorship from the 6 * FreeBSD Foundation. 7 * 8 * Redistribution and use in source and binary forms, with or without --- 14 unchanged lines hidden (view full) --- 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30#include <sys/cdefs.h> |
31__FBSDID("$FreeBSD: user/ed/newcons/sys/dev/vt/vt_buf.c 219888 2011-03-22 21:31:31Z ed $"); | 31__FBSDID("$FreeBSD: user/ed/newcons/sys/dev/vt/vt_buf.c 256145 2013-10-08 12:40:04Z ray $"); |
32 33#include <sys/param.h> 34#include <sys/kernel.h> 35#include <sys/lock.h> 36#include <sys/malloc.h> 37#include <sys/mutex.h> 38#include <sys/systm.h> 39 40#include <dev/vt/vt.h> 41 42static MALLOC_DEFINE(M_VTBUF, "vtbuf", "vt buffer"); 43 44#define VTBUF_LOCK(vb) mtx_lock_spin(&(vb)->vb_lock) 45#define VTBUF_UNLOCK(vb) mtx_unlock_spin(&(vb)->vb_lock) | 32 33#include <sys/param.h> 34#include <sys/kernel.h> 35#include <sys/lock.h> 36#include <sys/malloc.h> 37#include <sys/mutex.h> 38#include <sys/systm.h> 39 40#include <dev/vt/vt.h> 41 42static MALLOC_DEFINE(M_VTBUF, "vtbuf", "vt buffer"); 43 44#define VTBUF_LOCK(vb) mtx_lock_spin(&(vb)->vb_lock) 45#define VTBUF_UNLOCK(vb) mtx_unlock_spin(&(vb)->vb_lock) |
46/* 47 * line4 48 * line5 <--- curroffset (terminal output to that line) 49 * line0 50 * line1 <--- roffset (history display from that point) 51 * line2 52 * line3 53 */ 54int 55vthistory_seek(struct vt_buf *vb, int offset, int whence) 56{ 57 int roffset; |
|
46 | 58 |
59 /* No scrolling if not enabled. */ 60 if ((vb->vb_flags & VBF_SCROLL) == 0) { 61 if (vb->vb_roffset != vb->vb_curroffset) { 62 vb->vb_roffset = vb->vb_curroffset; 63 return (1); 64 } 65 return (0); /* No changes */ 66 } 67 /* 68 * Operate on copy of offset value, since it temporary can be bigger 69 * than amount of rows in buffer. 70 */ 71 roffset = vb->vb_roffset; 72 switch (whence) { 73 case VHS_SET: 74 roffset = offset; 75 break; 76 case VHS_CUR: 77 roffset += offset; 78 break; 79 case VHS_END: 80 /* Go to current offset. */ 81 roffset = vb->vb_curroffset; 82 break; 83 } 84 85 if (roffset < 0) 86 roffset = 0; 87 if (roffset >= vb->vb_history_size) 88 /* Still have screen_height rows. */ 89 roffset %= VTBUF_MAX_HEIGHT(vb); 90 91 if (vb->vb_roffset != roffset) { 92 vb->vb_roffset = roffset; 93 return (1); /* Offset changed, please update sceen. */ 94 } 95 return (0); /* No changes */ 96} 97 98void 99vthistory_addlines(struct vt_buf *vb, int offset) 100{ 101 102 vb->vb_curroffset += offset; 103 if (vb->vb_curroffset < 0) 104 vb->vb_curroffset = 0; 105 vb->vb_curroffset %= vb->vb_history_size; 106 if ((vb->vb_flags & VBF_SCROLL) == 0) { 107 vb->vb_roffset = vb->vb_curroffset; 108 } 109} 110 111void 112vthistory_getpos(const struct vt_buf *vb, unsigned int *offset) 113{ 114 115 *offset = vb->vb_roffset; 116} 117 |
|
47static inline uint64_t 48vtbuf_dirty_axis(unsigned int begin, unsigned int end) 49{ 50 uint64_t left, right, mask; 51 52 /* 53 * Mark all bits between begin % 64 and end % 64 dirty. 54 * This code is functionally equivalent to: --- 52 unchanged lines hidden (view full) --- 107 area.tr_end.tp_col = p->tp_col + 1; 108 vtbuf_dirty(vb, &area); 109} 110 111static void 112vtbuf_make_undirty(struct vt_buf *vb) 113{ 114 | 118static inline uint64_t 119vtbuf_dirty_axis(unsigned int begin, unsigned int end) 120{ 121 uint64_t left, right, mask; 122 123 /* 124 * Mark all bits between begin % 64 and end % 64 dirty. 125 * This code is functionally equivalent to: --- 52 unchanged lines hidden (view full) --- 178 area.tr_end.tp_col = p->tp_col + 1; 179 vtbuf_dirty(vb, &area); 180} 181 182static void 183vtbuf_make_undirty(struct vt_buf *vb) 184{ 185 |
115 vb->vb_dirtyrect.tr_begin = vb->vb_size; | 186 vb->vb_dirtyrect.tr_begin = vb->vb_scr_size; |
116 vb->vb_dirtyrect.tr_end.tp_row = vb->vb_dirtyrect.tr_end.tp_col = 0; 117 vb->vb_dirtymask.vbm_row = vb->vb_dirtymask.vbm_col = 0; 118} 119 120void 121vtbuf_undirty(struct vt_buf *vb, term_rect_t *r, struct vt_bufmask *m) 122{ 123 --- 5 unchanged lines hidden (view full) --- 129} 130 131void 132vtbuf_copy(struct vt_buf *vb, const term_rect_t *r, const term_pos_t *p2) 133{ 134 const term_pos_t *p1 = &r->tr_begin; 135 term_rect_t area; 136 unsigned int rows, cols; | 187 vb->vb_dirtyrect.tr_end.tp_row = vb->vb_dirtyrect.tr_end.tp_col = 0; 188 vb->vb_dirtymask.vbm_row = vb->vb_dirtymask.vbm_col = 0; 189} 190 191void 192vtbuf_undirty(struct vt_buf *vb, term_rect_t *r, struct vt_bufmask *m) 193{ 194 --- 5 unchanged lines hidden (view full) --- 200} 201 202void 203vtbuf_copy(struct vt_buf *vb, const term_rect_t *r, const term_pos_t *p2) 204{ 205 const term_pos_t *p1 = &r->tr_begin; 206 term_rect_t area; 207 unsigned int rows, cols; |
137 int pr; | 208 int pr, rdiff; |
138 | 209 |
210 KASSERT(r->tr_begin.tp_row < vb->vb_scr_size.tp_row, 211 ("vtbuf_copy begin.tp_row %d must be less than screen width %d", 212 r->tr_begin.tp_row, vb->vb_scr_size.tp_row)); 213 KASSERT(r->tr_begin.tp_col < vb->vb_scr_size.tp_col, 214 ("vtbuf_copy begin.tp_col %d must be less than screen height %d", 215 r->tr_begin.tp_col, vb->vb_scr_size.tp_col)); 216 217 KASSERT(r->tr_end.tp_row <= vb->vb_scr_size.tp_row, 218 ("vtbuf_copy end.tp_row %d must be less than screen width %d", 219 r->tr_end.tp_row, vb->vb_scr_size.tp_row)); 220 KASSERT(r->tr_end.tp_col <= vb->vb_scr_size.tp_col, 221 ("vtbuf_copy end.tp_col %d must be less than screen height %d", 222 r->tr_end.tp_col, vb->vb_scr_size.tp_col)); 223 224 KASSERT(p2->tp_row < vb->vb_scr_size.tp_row, 225 ("vtbuf_copy tp_row %d must be less than screen width %d", 226 p2->tp_row, vb->vb_scr_size.tp_row)); 227 KASSERT(p2->tp_col < vb->vb_scr_size.tp_col, 228 ("vtbuf_copy tp_col %d must be less than screen height %d", 229 p2->tp_col, vb->vb_scr_size.tp_col)); 230 |
|
139 rows = r->tr_end.tp_row - r->tr_begin.tp_row; | 231 rows = r->tr_end.tp_row - r->tr_begin.tp_row; |
232 rdiff = r->tr_begin.tp_row - p2->tp_row; |
|
140 cols = r->tr_end.tp_col - r->tr_begin.tp_col; | 233 cols = r->tr_end.tp_col - r->tr_begin.tp_col; |
141 142 /* Handle overlapping copies. */ 143 if (p2->tp_row < p1->tp_row) { | 234 if (r->tr_begin.tp_row > p2->tp_row && r->tr_begin.tp_col == 0 && 235 r->tr_end.tp_col == vb->vb_scr_size.tp_col && /* Full row. */ 236 (rows + rdiff) == vb->vb_scr_size.tp_row && /* Whole screen. */ 237 rdiff > 0) { /* Only forward dirrection. Do not eat history. */ 238 vthistory_addlines(vb, rdiff); 239 } else if (p2->tp_row < p1->tp_row) { 240 /* Handle overlapping copies of line segments. */ |
144 /* Move data up. */ 145 for (pr = 0; pr < rows; pr++) 146 memmove( 147 &VTBUF_FIELD(vb, p2->tp_row + pr, p2->tp_col), 148 &VTBUF_FIELD(vb, p1->tp_row + pr, p1->tp_col), 149 cols * sizeof(term_char_t)); 150 } else { 151 /* Move data down. */ 152 for (pr = rows - 1; pr >= 0; pr--) 153 memmove( 154 &VTBUF_FIELD(vb, p2->tp_row + pr, p2->tp_col), 155 &VTBUF_FIELD(vb, p1->tp_row + pr, p1->tp_col), 156 cols * sizeof(term_char_t)); 157 } 158 159 area.tr_begin = *p2; | 241 /* Move data up. */ 242 for (pr = 0; pr < rows; pr++) 243 memmove( 244 &VTBUF_FIELD(vb, p2->tp_row + pr, p2->tp_col), 245 &VTBUF_FIELD(vb, p1->tp_row + pr, p1->tp_col), 246 cols * sizeof(term_char_t)); 247 } else { 248 /* Move data down. */ 249 for (pr = rows - 1; pr >= 0; pr--) 250 memmove( 251 &VTBUF_FIELD(vb, p2->tp_row + pr, p2->tp_col), 252 &VTBUF_FIELD(vb, p1->tp_row + pr, p1->tp_col), 253 cols * sizeof(term_char_t)); 254 } 255 256 area.tr_begin = *p2; |
160 area.tr_end.tp_row = p2->tp_row + rows; 161 area.tr_end.tp_col = p2->tp_col + cols; | 257 area.tr_end.tp_row = MIN(p2->tp_row + rows, vb->vb_scr_size.tp_row); 258 area.tr_end.tp_col = MIN(p2->tp_col + cols, vb->vb_scr_size.tp_col); |
162 vtbuf_dirty(vb, &area); 163} 164 | 259 vtbuf_dirty(vb, &area); 260} 261 |
165void | 262static void |
166vtbuf_fill(struct vt_buf *vb, const term_rect_t *r, term_char_t c) 167{ 168 unsigned int pr, pc; | 263vtbuf_fill(struct vt_buf *vb, const term_rect_t *r, term_char_t c) 264{ 265 unsigned int pr, pc; |
266 term_char_t *row; |
|
169 | 267 |
170 for (pr = r->tr_begin.tp_row; pr < r->tr_end.tp_row; pr++) 171 for (pc = r->tr_begin.tp_col; pc < r->tr_end.tp_col; pc++) 172 VTBUF_FIELD(vb, pr, pc) = c; | 268 for (pr = r->tr_begin.tp_row; pr < r->tr_end.tp_row; pr++) { 269 row = vb->vb_rows[(vb->vb_curroffset + pr) % 270 VTBUF_MAX_HEIGHT(vb)]; 271 for (pc = r->tr_begin.tp_col; pc < r->tr_end.tp_col; pc++) { 272 row[pc] = c; 273 } 274 } 275} |
173 | 276 |
277void 278vtbuf_fill_locked(struct vt_buf *vb, const term_rect_t *r, term_char_t c) 279{ 280 KASSERT(r->tr_begin.tp_row < vb->vb_scr_size.tp_row, 281 ("vtbuf_fill_locked begin.tp_row %d must be < screen width %d", 282 r->tr_begin.tp_row, vb->vb_scr_size.tp_row)); 283 KASSERT(r->tr_begin.tp_col < vb->vb_scr_size.tp_col, 284 ("vtbuf_fill_locked begin.tp_col %d must be < screen height %d", 285 r->tr_begin.tp_col, vb->vb_scr_size.tp_col)); 286 287 KASSERT(r->tr_end.tp_row <= vb->vb_scr_size.tp_row, 288 ("vtbuf_fill_locked end.tp_row %d must be <= screen width %d", 289 r->tr_end.tp_row, vb->vb_scr_size.tp_row)); 290 KASSERT(r->tr_end.tp_col <= vb->vb_scr_size.tp_col, 291 ("vtbuf_fill_locked end.tp_col %d must be <= screen height %d", 292 r->tr_end.tp_col, vb->vb_scr_size.tp_col)); 293 294 VTBUF_LOCK(vb); 295 vtbuf_fill(vb, r, c); 296 VTBUF_UNLOCK(vb); 297 |
|
174 vtbuf_dirty(vb, r); 175} 176 | 298 vtbuf_dirty(vb, r); 299} 300 |
301static void 302vtbuf_init_rows(struct vt_buf *vb) 303{ 304 int r; 305 306 vb->vb_history_size = MAX(vb->vb_history_size, vb->vb_scr_size.tp_row); 307 308 for (r = 0; r < vb->vb_history_size; r++) 309 vb->vb_rows[r] = &vb->vb_buffer[r * 310 vb->vb_scr_size.tp_col]; 311} 312 |
|
177void 178vtbuf_init_early(struct vt_buf *vb) 179{ 180 181 vb->vb_flags |= VBF_CURSOR; | 313void 314vtbuf_init_early(struct vt_buf *vb) 315{ 316 317 vb->vb_flags |= VBF_CURSOR; |
318 vb->vb_roffset = 0; 319 vb->vb_curroffset = 0; 320 321 vtbuf_init_rows(vb); |
|
182 vtbuf_make_undirty(vb); | 322 vtbuf_make_undirty(vb); |
183 mtx_init(&vb->vb_lock, "vtbuf", NULL, MTX_SPIN); | 323 if ((vb->vb_flags & VBF_MTX_INIT) == 0) { 324 mtx_init(&vb->vb_lock, "vtbuf", NULL, MTX_SPIN); 325 vb->vb_flags |= VBF_MTX_INIT; 326 } |
184} 185 186void 187vtbuf_init(struct vt_buf *vb, const term_pos_t *p) 188{ | 327} 328 329void 330vtbuf_init(struct vt_buf *vb, const term_pos_t *p) 331{ |
332 int sz; |
|
189 | 333 |
190 vb->vb_size = *p; 191 vb->vb_buffer = malloc(p->tp_row * p->tp_col * sizeof(term_char_t), 192 M_VTBUF, M_WAITOK); | 334 vb->vb_scr_size = *p; 335 vb->vb_history_size = VBF_DEFAULT_HISTORY_SIZE; 336 337 if ((vb->vb_flags & VBF_STATIC) == 0) { 338 sz = vb->vb_history_size * p->tp_col * sizeof(term_char_t); 339 vb->vb_buffer = malloc(sz, M_VTBUF, M_WAITOK); 340 341 sz = vb->vb_history_size * sizeof(term_char_t *); 342 vb->vb_rows = malloc(sz, M_VTBUF, M_WAITOK); 343 } 344 |
193 vtbuf_init_early(vb); 194} 195 196void | 345 vtbuf_init_early(vb); 346} 347 348void |
197vtbuf_grow(struct vt_buf *vb, const term_pos_t *p) | 349vtbuf_sethistory_size(struct vt_buf *vb, int size) |
198{ | 350{ |
199 term_char_t *old, *new; | 351 term_pos_t p; |
200 | 352 |
201 if (p->tp_row > vb->vb_size.tp_row || 202 p->tp_col > vb->vb_size.tp_col) { | 353 /* With same size */ 354 p.tp_row = vb->vb_scr_size.tp_row; 355 p.tp_col = vb->vb_scr_size.tp_col; 356 vtbuf_grow(vb, &p, size); 357} 358 359void 360vtbuf_grow(struct vt_buf *vb, const term_pos_t *p, int history_size) 361{ 362 term_char_t *old, *new, **rows, **oldrows, **copyrows, *row; 363 int bufsize, rowssize, w, h, c, r; 364 term_rect_t rect; 365 366 history_size = MAX(history_size, p->tp_row); 367 368 if (history_size > vb->vb_history_size || p->tp_col > 369 vb->vb_scr_size.tp_col) { |
203 /* Allocate new buffer. */ | 370 /* Allocate new buffer. */ |
204 new = malloc(p->tp_row * p->tp_col * sizeof(term_char_t), 205 M_VTBUF, M_WAITOK|M_ZERO); | 371 bufsize = history_size * p->tp_col * sizeof(term_char_t); 372 new = malloc(bufsize, M_VTBUF, M_WAITOK|M_ZERO); 373 rowssize = history_size * sizeof(term_pos_t *); 374 rows = malloc(rowssize, M_VTBUF, M_WAITOK|M_ZERO); |
206 207 /* Toggle it. */ 208 VTBUF_LOCK(vb); 209 old = vb->vb_flags & VBF_STATIC ? NULL : vb->vb_buffer; | 375 376 /* Toggle it. */ 377 VTBUF_LOCK(vb); 378 old = vb->vb_flags & VBF_STATIC ? NULL : vb->vb_buffer; |
379 oldrows = vb->vb_flags & VBF_STATIC ? NULL : vb->vb_rows; 380 copyrows = vb->vb_rows; 381 w = vb->vb_scr_size.tp_col; 382 h = vb->vb_history_size; 383 384 vb->vb_history_size = history_size; |
|
210 vb->vb_buffer = new; | 385 vb->vb_buffer = new; |
386 vb->vb_rows = rows; |
|
211 vb->vb_flags &= ~VBF_STATIC; | 387 vb->vb_flags &= ~VBF_STATIC; |
212 vb->vb_size = *p; | 388 vb->vb_scr_size = *p; 389 vtbuf_init_rows(vb); 390 391 /* Copy history and fill extra space. */ 392 for (r = 0; r < history_size; r ++) { 393 row = rows[r]; 394 if (r < h) { /* Copy. */ 395 memmove(rows[r], copyrows[r], 396 MIN(p->tp_col, w) * sizeof(term_char_t)); 397 for (c = MIN(p->tp_col, w); c < p->tp_col; 398 c++) { 399 row[c] = VTBUF_SPACE_CHAR; 400 } 401 } else { /* Just fill. */ 402 rect.tr_begin.tp_col = 0; 403 rect.tr_begin.tp_row = r; 404 rect.tr_end.tp_col = p->tp_col; 405 rect.tr_end.tp_row = p->tp_row; 406 vtbuf_fill(vb, &rect, VTBUF_SPACE_CHAR); 407 break; 408 } 409 } |
213 vtbuf_make_undirty(vb); 214 VTBUF_UNLOCK(vb); | 410 vtbuf_make_undirty(vb); 411 VTBUF_UNLOCK(vb); |
215 | |
216 /* Deallocate old buffer. */ | 412 /* Deallocate old buffer. */ |
217 if (old != NULL) 218 free(old, M_VTBUF); | 413 free(old, M_VTBUF); 414 free(oldrows, M_VTBUF); |
219 } 220} 221 222void 223vtbuf_putchar(struct vt_buf *vb, const term_pos_t *p, term_char_t c) 224{ | 415 } 416} 417 418void 419vtbuf_putchar(struct vt_buf *vb, const term_pos_t *p, term_char_t c) 420{ |
421 term_char_t *row; |
|
225 | 422 |
226 if (VTBUF_FIELD(vb, p->tp_row, p->tp_col) != c) { 227 VTBUF_FIELD(vb, p->tp_row, p->tp_col) = c; | 423 KASSERT(p->tp_row < vb->vb_scr_size.tp_row, 424 ("vtbuf_putchar tp_row %d must be less than screen width %d", 425 p->tp_row, vb->vb_scr_size.tp_row)); 426 KASSERT(p->tp_col < vb->vb_scr_size.tp_col, 427 ("vtbuf_putchar tp_col %d must be less than screen height %d", 428 p->tp_col, vb->vb_scr_size.tp_col)); 429 430 row = vb->vb_rows[(vb->vb_curroffset + p->tp_row) % 431 VTBUF_MAX_HEIGHT(vb)]; 432 if (row[p->tp_col] != c) { 433 VTBUF_LOCK(vb); 434 row[p->tp_col] = c; 435 VTBUF_UNLOCK(vb); |
228 vtbuf_dirty_cell(vb, p); 229 } 230} 231 232void 233vtbuf_cursor_position(struct vt_buf *vb, const term_pos_t *p) 234{ 235 --- 26 unchanged lines hidden --- | 436 vtbuf_dirty_cell(vb, p); 437 } 438} 439 440void 441vtbuf_cursor_position(struct vt_buf *vb, const term_pos_t *p) 442{ 443 --- 26 unchanged lines hidden --- |