Deleted Added
full compact
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 ---