Line data Source code
1 : /* $OpenBSD: rasops.c,v 1.56 2018/08/27 09:30:07 kettenis Exp $ */
2 : /* $NetBSD: rasops.c,v 1.35 2001/02/02 06:01:01 marcus Exp $ */
3 :
4 : /*-
5 : * Copyright (c) 1999 The NetBSD Foundation, Inc.
6 : * All rights reserved.
7 : *
8 : * This code is derived from software contributed to The NetBSD Foundation
9 : * by Andrew Doran.
10 : *
11 : * Redistribution and use in source and binary forms, with or without
12 : * modification, are permitted provided that the following conditions
13 : * are met:
14 : * 1. Redistributions of source code must retain the above copyright
15 : * notice, this list of conditions and the following disclaimer.
16 : * 2. Redistributions in binary form must reproduce the above copyright
17 : * notice, this list of conditions and the following disclaimer in the
18 : * documentation and/or other materials provided with the distribution.
19 : *
20 : * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 : * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 : * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 : * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 : * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 : * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 : * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 : * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 : * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 : * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 : * POSSIBILITY OF SUCH DAMAGE.
31 : */
32 :
33 : #include <sys/param.h>
34 : #include <sys/malloc.h>
35 : #include <sys/systm.h>
36 : #include <sys/time.h>
37 : #include <sys/task.h>
38 :
39 : #include <dev/wscons/wsdisplayvar.h>
40 : #include <dev/wscons/wsconsio.h>
41 : #include <dev/wsfont/wsfont.h>
42 : #include <dev/rasops/rasops.h>
43 :
44 : #ifndef _KERNEL
45 : #include <errno.h>
46 : #endif
47 :
48 : /* ANSI colormap (R,G,B) */
49 :
50 : #define NORMAL_BLACK 0x000000
51 : #define NORMAL_RED 0x7f0000
52 : #define NORMAL_GREEN 0x007f00
53 : #define NORMAL_BROWN 0x7f7f00
54 : #define NORMAL_BLUE 0x00007f
55 : #define NORMAL_MAGENTA 0x7f007f
56 : #define NORMAL_CYAN 0x007f7f
57 : #define NORMAL_WHITE 0xc7c7c7 /* XXX too dim? */
58 :
59 : #define HILITE_BLACK 0x7f7f7f
60 : #define HILITE_RED 0xff0000
61 : #define HILITE_GREEN 0x00ff00
62 : #define HILITE_BROWN 0xffff00
63 : #define HILITE_BLUE 0x0000ff
64 : #define HILITE_MAGENTA 0xff00ff
65 : #define HILITE_CYAN 0x00ffff
66 : #define HILITE_WHITE 0xffffff
67 :
68 : const u_char rasops_cmap[256 * 3] = {
69 : #define _C(x) ((x) & 0xff0000) >> 16, ((x) & 0x00ff00) >> 8, ((x) & 0x0000ff)
70 :
71 : _C(NORMAL_BLACK),
72 : _C(NORMAL_RED),
73 : _C(NORMAL_GREEN),
74 : _C(NORMAL_BROWN),
75 : _C(NORMAL_BLUE),
76 : _C(NORMAL_MAGENTA),
77 : _C(NORMAL_CYAN),
78 : _C(NORMAL_WHITE),
79 :
80 : _C(HILITE_BLACK),
81 : _C(HILITE_RED),
82 : _C(HILITE_GREEN),
83 : _C(HILITE_BROWN),
84 : _C(HILITE_BLUE),
85 : _C(HILITE_MAGENTA),
86 : _C(HILITE_CYAN),
87 : _C(HILITE_WHITE),
88 :
89 : /*
90 : * For the cursor, we need the last 16 colors to be the
91 : * opposite of the first 16. Fill the intermediate space with
92 : * white completely for simplicity.
93 : */
94 : #define _CMWHITE16 \
95 : _C(HILITE_WHITE), _C(HILITE_WHITE), _C(HILITE_WHITE), _C(HILITE_WHITE), \
96 : _C(HILITE_WHITE), _C(HILITE_WHITE), _C(HILITE_WHITE), _C(HILITE_WHITE), \
97 : _C(HILITE_WHITE), _C(HILITE_WHITE), _C(HILITE_WHITE), _C(HILITE_WHITE), \
98 : _C(HILITE_WHITE), _C(HILITE_WHITE), _C(HILITE_WHITE), _C(HILITE_WHITE),
99 : _CMWHITE16 _CMWHITE16 _CMWHITE16 _CMWHITE16 _CMWHITE16
100 : _CMWHITE16 _CMWHITE16 _CMWHITE16 _CMWHITE16 _CMWHITE16
101 : _CMWHITE16 _CMWHITE16 _CMWHITE16 _CMWHITE16
102 : #undef _CMWHITE16
103 :
104 : _C(~HILITE_WHITE),
105 : _C(~HILITE_CYAN),
106 : _C(~HILITE_MAGENTA),
107 : _C(~HILITE_BLUE),
108 : _C(~HILITE_BROWN),
109 : _C(~HILITE_GREEN),
110 : _C(~HILITE_RED),
111 : _C(~HILITE_BLACK),
112 :
113 : _C(~NORMAL_WHITE),
114 : _C(~NORMAL_CYAN),
115 : _C(~NORMAL_MAGENTA),
116 : _C(~NORMAL_BLUE),
117 : _C(~NORMAL_BROWN),
118 : _C(~NORMAL_GREEN),
119 : _C(~NORMAL_RED),
120 : _C(~NORMAL_BLACK),
121 :
122 : #undef _C
123 : };
124 :
125 : /* True if color is gray */
126 : const u_char rasops_isgray[16] = {
127 : 1, 0, 0, 0,
128 : 0, 0, 0, 1,
129 : 1, 0, 0, 0,
130 : 0, 0, 0, 1
131 : };
132 :
133 : struct rasops_screen {
134 : LIST_ENTRY(rasops_screen) rs_next;
135 : struct rasops_info *rs_ri;
136 :
137 : struct wsdisplay_charcell *rs_bs;
138 : int rs_visible;
139 : int rs_crow;
140 : int rs_ccol;
141 : long rs_defattr;
142 :
143 : int rs_sbscreens;
144 : #define RS_SCROLLBACK_SCREENS 5
145 : int rs_dispoffset; /* rs_bs index, start of our actual screen */
146 : int rs_visibleoffset; /* rs_bs index, current scrollback screen */
147 : };
148 :
149 : /* Generic functions */
150 : int rasops_copycols(void *, int, int, int, int);
151 : int rasops_copyrows(void *, int, int, int);
152 : int rasops_mapchar(void *, int, u_int *);
153 : int rasops_cursor(void *, int, int, int);
154 : int rasops_alloc_cattr(void *, int, int, int, long *);
155 : int rasops_alloc_mattr(void *, int, int, int, long *);
156 : int rasops_do_cursor(struct rasops_info *);
157 : void rasops_init_devcmap(struct rasops_info *);
158 : void rasops_unpack_attr(void *, long, int *, int *, int *);
159 : #if NRASOPS_BSWAP > 0
160 : static void slow_bcopy(void *, void *, size_t);
161 : #endif
162 : #if NRASOPS_ROTATION > 0
163 : void rasops_copychar(void *, int, int, int, int);
164 : int rasops_copycols_rotated(void *, int, int, int, int);
165 : int rasops_copyrows_rotated(void *, int, int, int);
166 : int rasops_erasecols_rotated(void *, int, int, int, long);
167 : int rasops_eraserows_rotated(void *, int, int, long);
168 : int rasops_putchar_rotated(void *, int, int, u_int, long);
169 : void rasops_rotate_font(int *, int);
170 :
171 : /*
172 : * List of all rotated fonts
173 : */
174 : SLIST_HEAD(, rotatedfont) rotatedfonts = SLIST_HEAD_INITIALIZER(rotatedfonts);
175 : struct rotatedfont {
176 : SLIST_ENTRY(rotatedfont) rf_next;
177 : int rf_cookie;
178 : int rf_rotated;
179 : };
180 : #endif
181 :
182 : void rasops_doswitch(void *);
183 : int rasops_vcons_cursor(void *, int, int, int);
184 : int rasops_vcons_mapchar(void *, int, u_int *);
185 : int rasops_vcons_putchar(void *, int, int, u_int, long);
186 : int rasops_vcons_copycols(void *, int, int, int, int);
187 : int rasops_vcons_erasecols(void *, int, int, int, long);
188 : int rasops_vcons_copyrows(void *, int, int, int);
189 : int rasops_vcons_eraserows(void *, int, int, long);
190 : int rasops_vcons_alloc_attr(void *, int, int, int, long *);
191 : void rasops_vcons_unpack_attr(void *, long, int *, int *, int *);
192 :
193 : int rasops_wronly_putchar(void *, int, int, u_int, long);
194 : int rasops_wronly_copycols(void *, int, int, int, int);
195 : int rasops_wronly_erasecols(void *, int, int, int, long);
196 : int rasops_wronly_copyrows(void *, int, int, int);
197 : int rasops_wronly_eraserows(void *, int, int, long);
198 : int rasops_wronly_do_cursor(struct rasops_info *);
199 :
200 : int rasops_add_font(struct rasops_info *, struct wsdisplay_font *);
201 : int rasops_use_font(struct rasops_info *, struct wsdisplay_font *);
202 : int rasops_list_font_cb(void *, struct wsdisplay_font *);
203 :
204 : /*
205 : * Initialize a 'rasops_info' descriptor.
206 : */
207 : int
208 0 : rasops_init(struct rasops_info *ri, int wantrows, int wantcols)
209 : {
210 :
211 : #ifdef _KERNEL
212 : /* Select a font if the caller doesn't care */
213 0 : if (ri->ri_font == NULL) {
214 0 : int cookie;
215 :
216 0 : wsfont_init();
217 :
218 0 : if (ri->ri_width > 80*12)
219 : /* High res screen, choose a big font */
220 0 : cookie = wsfont_find(NULL, 12, 0, 0);
221 : else
222 : /* lower res, choose a 8 pixel wide font */
223 0 : cookie = wsfont_find(NULL, 8, 0, 0);
224 :
225 0 : if (cookie <= 0)
226 0 : cookie = wsfont_find(NULL, 0, 0, 0);
227 :
228 0 : if (cookie <= 0) {
229 0 : printf("rasops_init: font table is empty\n");
230 0 : return (-1);
231 : }
232 :
233 : #if NRASOPS_ROTATION > 0
234 : /*
235 : * Pick the rotated version of this font. This will create it
236 : * if necessary.
237 : */
238 0 : if (ri->ri_flg & (RI_ROTATE_CW | RI_ROTATE_CCW))
239 0 : rasops_rotate_font(&cookie,
240 0 : ISSET(ri->ri_flg, RI_ROTATE_CCW));
241 : #endif
242 :
243 0 : if (wsfont_lock(cookie, &ri->ri_font,
244 0 : WSDISPLAY_FONTORDER_L2R, WSDISPLAY_FONTORDER_L2R) <= 0) {
245 0 : printf("rasops_init: couldn't lock font\n");
246 0 : return (-1);
247 : }
248 :
249 0 : ri->ri_wsfcookie = cookie;
250 0 : }
251 : #endif
252 :
253 : /* This should never happen in reality... */
254 : #ifdef DEBUG
255 : if ((long)ri->ri_bits & 3) {
256 : printf("rasops_init: bits not aligned on 32-bit boundary\n");
257 : return (-1);
258 : }
259 :
260 : if ((int)ri->ri_stride & 3) {
261 : printf("rasops_init: stride not aligned on 32-bit boundary\n");
262 : return (-1);
263 : }
264 : #endif
265 :
266 0 : if (rasops_reconfig(ri, wantrows, wantcols))
267 0 : return (-1);
268 :
269 0 : LIST_INIT(&ri->ri_screens);
270 0 : ri->ri_nscreens = 0;
271 :
272 0 : ri->ri_putchar = ri->ri_ops.putchar;
273 0 : ri->ri_copycols = ri->ri_ops.copycols;
274 0 : ri->ri_erasecols = ri->ri_ops.erasecols;
275 0 : ri->ri_copyrows = ri->ri_ops.copyrows;
276 0 : ri->ri_eraserows = ri->ri_ops.eraserows;
277 0 : ri->ri_alloc_attr = ri->ri_ops.alloc_attr;
278 :
279 0 : if (ri->ri_flg & RI_VCONS) {
280 0 : void *cookie;
281 0 : int curx, cury;
282 0 : long attr;
283 :
284 0 : if (rasops_alloc_screen(ri, &cookie, &curx, &cury, &attr))
285 0 : return (-1);
286 :
287 0 : ri->ri_active = cookie;
288 0 : ri->ri_bs =
289 0 : &ri->ri_active->rs_bs[ri->ri_active->rs_dispoffset];
290 :
291 0 : ri->ri_ops.cursor = rasops_vcons_cursor;
292 0 : ri->ri_ops.mapchar = rasops_vcons_mapchar;
293 0 : ri->ri_ops.putchar = rasops_vcons_putchar;
294 0 : ri->ri_ops.copycols = rasops_vcons_copycols;
295 0 : ri->ri_ops.erasecols = rasops_vcons_erasecols;
296 0 : ri->ri_ops.copyrows = rasops_vcons_copyrows;
297 0 : ri->ri_ops.eraserows = rasops_vcons_eraserows;
298 0 : ri->ri_ops.alloc_attr = rasops_vcons_alloc_attr;
299 0 : ri->ri_ops.unpack_attr = rasops_vcons_unpack_attr;
300 0 : ri->ri_do_cursor = rasops_wronly_do_cursor;
301 0 : } else if ((ri->ri_flg & RI_WRONLY) && ri->ri_bs != NULL) {
302 0 : long attr;
303 : int i;
304 :
305 0 : ri->ri_ops.putchar = rasops_wronly_putchar;
306 0 : ri->ri_ops.copycols = rasops_wronly_copycols;
307 0 : ri->ri_ops.erasecols = rasops_wronly_erasecols;
308 0 : ri->ri_ops.copyrows = rasops_wronly_copyrows;
309 0 : ri->ri_ops.eraserows = rasops_wronly_eraserows;
310 0 : ri->ri_do_cursor = rasops_wronly_do_cursor;
311 :
312 0 : ri->ri_alloc_attr(ri, 0, 0, 0, &attr);
313 0 : for (i = 0; i < ri->ri_rows * ri->ri_cols; i++) {
314 0 : ri->ri_bs[i].uc = ' ';
315 0 : ri->ri_bs[i].attr = attr;
316 : }
317 0 : }
318 :
319 0 : task_set(&ri->ri_switchtask, rasops_doswitch, ri);
320 :
321 0 : rasops_init_devcmap(ri);
322 0 : return (0);
323 0 : }
324 :
325 : /*
326 : * Reconfigure (because parameters have changed in some way).
327 : */
328 : int
329 0 : rasops_reconfig(struct rasops_info *ri, int wantrows, int wantcols)
330 : {
331 : int l, bpp, s;
332 :
333 0 : s = splhigh();
334 :
335 0 : if (ri->ri_font->fontwidth > 32 || ri->ri_font->fontwidth < 4)
336 0 : panic("rasops_init: fontwidth assumptions botched!");
337 :
338 : /* Need this to frob the setup below */
339 0 : bpp = (ri->ri_depth == 15 ? 16 : ri->ri_depth);
340 :
341 0 : if ((ri->ri_flg & RI_CFGDONE) != 0)
342 0 : ri->ri_bits = ri->ri_origbits;
343 :
344 : /* Don't care if the caller wants a hideously small console */
345 0 : if (wantrows < 10)
346 0 : wantrows = 10;
347 :
348 0 : if (wantcols < 20)
349 0 : wantcols = 20;
350 :
351 : /* Now constrain what they get */
352 0 : ri->ri_emuwidth = ri->ri_font->fontwidth * wantcols;
353 0 : ri->ri_emuheight = ri->ri_font->fontheight * wantrows;
354 :
355 0 : if (ri->ri_emuwidth > ri->ri_width)
356 0 : ri->ri_emuwidth = ri->ri_width;
357 :
358 0 : if (ri->ri_emuheight > ri->ri_height)
359 0 : ri->ri_emuheight = ri->ri_height;
360 :
361 : /* Reduce width until aligned on a 32-bit boundary */
362 0 : while ((ri->ri_emuwidth * bpp & 31) != 0)
363 0 : ri->ri_emuwidth--;
364 :
365 : #if NRASOPS_ROTATION > 0
366 0 : if (ri->ri_flg & (RI_ROTATE_CW | RI_ROTATE_CCW)) {
367 0 : ri->ri_rows = ri->ri_emuwidth / ri->ri_font->fontwidth;
368 0 : ri->ri_cols = ri->ri_emuheight / ri->ri_font->fontheight;
369 0 : } else
370 : #endif
371 : {
372 0 : ri->ri_cols = ri->ri_emuwidth / ri->ri_font->fontwidth;
373 0 : ri->ri_rows = ri->ri_emuheight / ri->ri_font->fontheight;
374 : }
375 0 : ri->ri_emustride = ri->ri_emuwidth * bpp >> 3;
376 0 : ri->ri_delta = ri->ri_stride - ri->ri_emustride;
377 0 : ri->ri_ccol = 0;
378 0 : ri->ri_crow = 0;
379 0 : ri->ri_pelbytes = bpp >> 3;
380 :
381 0 : ri->ri_xscale = (ri->ri_font->fontwidth * bpp) >> 3;
382 0 : ri->ri_yscale = ri->ri_font->fontheight * ri->ri_stride;
383 0 : ri->ri_fontscale = ri->ri_font->fontheight * ri->ri_font->stride;
384 :
385 : #ifdef DEBUG
386 : if ((ri->ri_delta & 3) != 0)
387 : panic("rasops_init: ri_delta not aligned on 32-bit boundary");
388 : #endif
389 : /* Clear the entire display */
390 0 : if ((ri->ri_flg & RI_CLEAR) != 0) {
391 0 : memset(ri->ri_bits, 0, ri->ri_stride * ri->ri_height);
392 0 : ri->ri_flg &= ~RI_CLEARMARGINS;
393 0 : }
394 :
395 : /* Now centre our window if needs be */
396 0 : ri->ri_origbits = ri->ri_bits;
397 :
398 0 : if ((ri->ri_flg & RI_CENTER) != 0) {
399 0 : ri->ri_bits += (((ri->ri_width * bpp >> 3) -
400 0 : ri->ri_emustride) >> 1) & ~3;
401 0 : ri->ri_bits += ((ri->ri_height - ri->ri_emuheight) >> 1) *
402 0 : ri->ri_stride;
403 :
404 0 : ri->ri_yorigin = (int)(ri->ri_bits - ri->ri_origbits)
405 0 : / ri->ri_stride;
406 0 : ri->ri_xorigin = (((int)(ri->ri_bits - ri->ri_origbits)
407 0 : % ri->ri_stride) * 8 / bpp);
408 0 : } else
409 0 : ri->ri_xorigin = ri->ri_yorigin = 0;
410 :
411 : /* Clear the margins */
412 0 : if ((ri->ri_flg & RI_CLEARMARGINS) != 0) {
413 0 : memset(ri->ri_origbits, 0, ri->ri_bits - ri->ri_origbits);
414 0 : for (l = 0; l < ri->ri_emuheight; l++)
415 0 : memset(ri->ri_bits + ri->ri_emustride +
416 : l * ri->ri_stride, 0,
417 : ri->ri_stride - ri->ri_emustride);
418 0 : memset(ri->ri_bits + ri->ri_emuheight * ri->ri_stride, 0,
419 : (ri->ri_origbits + ri->ri_height * ri->ri_stride) -
420 : (ri->ri_bits + ri->ri_emuheight * ri->ri_stride));
421 0 : }
422 :
423 : /*
424 : * Fill in defaults for operations set. XXX this nukes private
425 : * routines used by accelerated fb drivers.
426 : */
427 0 : ri->ri_ops.mapchar = rasops_mapchar;
428 0 : ri->ri_ops.copyrows = rasops_copyrows;
429 0 : ri->ri_ops.copycols = rasops_copycols;
430 0 : ri->ri_ops.erasecols = rasops_erasecols;
431 0 : ri->ri_ops.eraserows = rasops_eraserows;
432 0 : ri->ri_ops.cursor = rasops_cursor;
433 0 : ri->ri_ops.unpack_attr = rasops_unpack_attr;
434 0 : ri->ri_do_cursor = rasops_do_cursor;
435 0 : ri->ri_updatecursor = NULL;
436 :
437 0 : if (ri->ri_depth < 8 || (ri->ri_flg & RI_FORCEMONO) != 0) {
438 0 : ri->ri_ops.alloc_attr = rasops_alloc_mattr;
439 0 : ri->ri_caps = WSSCREEN_UNDERLINE | WSSCREEN_REVERSE;
440 0 : } else {
441 0 : ri->ri_ops.alloc_attr = rasops_alloc_cattr;
442 0 : ri->ri_caps = WSSCREEN_UNDERLINE | WSSCREEN_HILIT |
443 : WSSCREEN_WSCOLORS | WSSCREEN_REVERSE;
444 : }
445 :
446 0 : switch (ri->ri_depth) {
447 : #if NRASOPS1 > 0
448 : case 1:
449 : rasops1_init(ri);
450 : break;
451 : #endif
452 : #if NRASOPS4 > 0
453 : case 4:
454 : rasops4_init(ri);
455 : break;
456 : #endif
457 : #if NRASOPS8 > 0
458 : case 8:
459 0 : rasops8_init(ri);
460 0 : break;
461 : #endif
462 : #if NRASOPS15 > 0 || NRASOPS16 > 0
463 : case 15:
464 : case 16:
465 0 : rasops15_init(ri);
466 0 : break;
467 : #endif
468 : #if NRASOPS24 > 0
469 : case 24:
470 0 : rasops24_init(ri);
471 0 : break;
472 : #endif
473 : #if NRASOPS32 > 0
474 : case 32:
475 0 : rasops32_init(ri);
476 0 : break;
477 : #endif
478 : default:
479 0 : ri->ri_flg &= ~RI_CFGDONE;
480 0 : splx(s);
481 0 : return (-1);
482 : }
483 :
484 : #if NRASOPS_ROTATION > 0
485 0 : if (ri->ri_flg & (RI_ROTATE_CW | RI_ROTATE_CCW)) {
486 0 : ri->ri_real_ops = ri->ri_ops;
487 0 : ri->ri_ops.copycols = rasops_copycols_rotated;
488 0 : ri->ri_ops.copyrows = rasops_copyrows_rotated;
489 0 : ri->ri_ops.erasecols = rasops_erasecols_rotated;
490 0 : ri->ri_ops.eraserows = rasops_eraserows_rotated;
491 0 : ri->ri_ops.putchar = rasops_putchar_rotated;
492 0 : }
493 : #endif
494 :
495 0 : ri->ri_flg |= RI_CFGDONE;
496 0 : splx(s);
497 0 : return (0);
498 0 : }
499 :
500 : /*
501 : * Map a character.
502 : */
503 : int
504 0 : rasops_mapchar(void *cookie, int c, u_int *cp)
505 : {
506 : struct rasops_info *ri;
507 :
508 0 : ri = (struct rasops_info *)cookie;
509 :
510 : #ifdef DIAGNOSTIC
511 0 : if (ri->ri_font == NULL)
512 0 : panic("rasops_mapchar: no font selected");
513 : #endif
514 0 : if (ri->ri_font->encoding != WSDISPLAY_FONTENC_ISO) {
515 :
516 0 : if ( (c = wsfont_map_unichar(ri->ri_font, c)) < 0) {
517 :
518 0 : *cp = '?';
519 0 : return (0);
520 :
521 : }
522 : }
523 :
524 :
525 0 : if (c < ri->ri_font->firstchar) {
526 0 : *cp = '?';
527 0 : return (0);
528 : }
529 :
530 0 : if (c - ri->ri_font->firstchar >= ri->ri_font->numchars) {
531 0 : *cp = '?';
532 0 : return (0);
533 : }
534 :
535 0 : *cp = c;
536 0 : return (5);
537 0 : }
538 :
539 : /*
540 : * Allocate a color attribute.
541 : */
542 : int
543 0 : rasops_alloc_cattr(void *cookie, int fg, int bg, int flg, long *attr)
544 : {
545 : int swap;
546 :
547 : #ifdef RASOPS_CLIPPING
548 : fg &= 7;
549 : bg &= 7;
550 : #endif
551 0 : if ((flg & WSATTR_BLINK) != 0)
552 0 : return (EINVAL);
553 :
554 0 : if ((flg & WSATTR_WSCOLORS) == 0) {
555 : fg = WS_DEFAULT_FG;
556 : bg = WS_DEFAULT_BG;
557 0 : }
558 :
559 0 : if ((flg & WSATTR_REVERSE) != 0) {
560 : swap = fg;
561 : fg = bg;
562 : bg = swap;
563 0 : }
564 :
565 0 : if ((flg & WSATTR_HILIT) != 0)
566 0 : fg += 8;
567 :
568 0 : flg = ((flg & WSATTR_UNDERLINE) ? 1 : 0);
569 :
570 0 : if (rasops_isgray[fg])
571 0 : flg |= 2;
572 :
573 0 : if (rasops_isgray[bg])
574 0 : flg |= 4;
575 :
576 0 : *attr = (bg << 16) | (fg << 24) | flg;
577 0 : return (0);
578 0 : }
579 :
580 : /*
581 : * Allocate a mono attribute.
582 : */
583 : int
584 0 : rasops_alloc_mattr(void *cookie, int fg, int bg, int flg, long *attr)
585 : {
586 : int swap;
587 :
588 0 : if ((flg & (WSATTR_BLINK | WSATTR_HILIT | WSATTR_WSCOLORS)) != 0)
589 0 : return (EINVAL);
590 :
591 : fg = 1;
592 : bg = 0;
593 :
594 0 : if ((flg & WSATTR_REVERSE) != 0) {
595 : swap = fg;
596 : fg = bg;
597 : bg = swap;
598 0 : }
599 :
600 0 : *attr = (bg << 16) | (fg << 24) | ((flg & WSATTR_UNDERLINE) ? 7 : 6);
601 0 : return (0);
602 0 : }
603 :
604 : /*
605 : * Copy rows.
606 : */
607 : int
608 0 : rasops_copyrows(void *cookie, int src, int dst, int num)
609 : {
610 : int32_t *sp, *dp, *srp, *drp;
611 : struct rasops_info *ri;
612 : int n8, n1, cnt, delta;
613 :
614 0 : ri = (struct rasops_info *)cookie;
615 :
616 : #ifdef RASOPS_CLIPPING
617 : if (dst == src)
618 : return 0;
619 :
620 : if (src < 0) {
621 : num += src;
622 : src = 0;
623 : }
624 :
625 : if ((src + num) > ri->ri_rows)
626 : num = ri->ri_rows - src;
627 :
628 : if (dst < 0) {
629 : num += dst;
630 : dst = 0;
631 : }
632 :
633 : if ((dst + num) > ri->ri_rows)
634 : num = ri->ri_rows - dst;
635 :
636 : if (num <= 0)
637 : return 0;
638 : #endif
639 :
640 0 : num *= ri->ri_font->fontheight;
641 0 : n8 = ri->ri_emustride >> 5;
642 0 : n1 = (ri->ri_emustride >> 2) & 7;
643 :
644 0 : if (dst < src) {
645 0 : srp = (int32_t *)(ri->ri_bits + src * ri->ri_yscale);
646 0 : drp = (int32_t *)(ri->ri_bits + dst * ri->ri_yscale);
647 0 : delta = ri->ri_stride;
648 0 : } else {
649 0 : src = ri->ri_font->fontheight * src + num - 1;
650 0 : dst = ri->ri_font->fontheight * dst + num - 1;
651 0 : srp = (int32_t *)(ri->ri_bits + src * ri->ri_stride);
652 0 : drp = (int32_t *)(ri->ri_bits + dst * ri->ri_stride);
653 0 : delta = -ri->ri_stride;
654 : }
655 :
656 0 : while (num--) {
657 : dp = drp;
658 : sp = srp;
659 0 : DELTA(drp, delta, int32_t *);
660 0 : DELTA(srp, delta, int32_t *);
661 :
662 0 : for (cnt = n8; cnt; cnt--) {
663 0 : dp[0] = sp[0];
664 0 : dp[1] = sp[1];
665 0 : dp[2] = sp[2];
666 0 : dp[3] = sp[3];
667 0 : dp[4] = sp[4];
668 0 : dp[5] = sp[5];
669 0 : dp[6] = sp[6];
670 0 : dp[7] = sp[7];
671 0 : dp += 8;
672 0 : sp += 8;
673 : }
674 :
675 0 : for (cnt = n1; cnt; cnt--)
676 0 : *dp++ = *sp++;
677 : }
678 :
679 0 : return 0;
680 : }
681 :
682 : /*
683 : * Copy columns. This is slow, and hard to optimize due to alignment,
684 : * and the fact that we have to copy both left->right and right->left.
685 : * We simply cop-out here and use either memmove() or slow_bcopy(),
686 : * since they handle all of these cases anyway.
687 : */
688 : int
689 0 : rasops_copycols(void *cookie, int row, int src, int dst, int num)
690 : {
691 : struct rasops_info *ri;
692 : u_char *sp, *dp;
693 : int height;
694 :
695 0 : ri = (struct rasops_info *)cookie;
696 :
697 : #ifdef RASOPS_CLIPPING
698 : if (dst == src)
699 : return 0;
700 :
701 : /* Catches < 0 case too */
702 : if ((unsigned)row >= (unsigned)ri->ri_rows)
703 : return 0;
704 :
705 : if (src < 0) {
706 : num += src;
707 : src = 0;
708 : }
709 :
710 : if ((src + num) > ri->ri_cols)
711 : num = ri->ri_cols - src;
712 :
713 : if (dst < 0) {
714 : num += dst;
715 : dst = 0;
716 : }
717 :
718 : if ((dst + num) > ri->ri_cols)
719 : num = ri->ri_cols - dst;
720 :
721 : if (num <= 0)
722 : return 0;
723 : #endif
724 :
725 0 : num *= ri->ri_xscale;
726 0 : row *= ri->ri_yscale;
727 0 : height = ri->ri_font->fontheight;
728 :
729 0 : sp = ri->ri_bits + row + src * ri->ri_xscale;
730 0 : dp = ri->ri_bits + row + dst * ri->ri_xscale;
731 :
732 : #if NRASOPS_BSWAP > 0
733 : if (ri->ri_flg & RI_BSWAP) {
734 : while (height--) {
735 : slow_bcopy(sp, dp, num);
736 : dp += ri->ri_stride;
737 : sp += ri->ri_stride;
738 : }
739 : } else
740 : #endif
741 : {
742 0 : while (height--) {
743 0 : memmove(dp, sp, num);
744 0 : dp += ri->ri_stride;
745 0 : sp += ri->ri_stride;
746 : }
747 : }
748 :
749 0 : return 0;
750 : }
751 :
752 : /*
753 : * Turn cursor off/on.
754 : */
755 : int
756 0 : rasops_cursor(void *cookie, int on, int row, int col)
757 : {
758 : struct rasops_info *ri;
759 : int rc;
760 :
761 0 : ri = (struct rasops_info *)cookie;
762 :
763 : /* Turn old cursor off */
764 0 : if ((ri->ri_flg & RI_CURSOR) != 0) {
765 : #ifdef RASOPS_CLIPPING
766 : if ((ri->ri_flg & RI_CURSORCLIP) == 0)
767 : #endif
768 0 : if ((rc = ri->ri_do_cursor(ri)) != 0)
769 0 : return rc;
770 0 : ri->ri_flg &= ~RI_CURSOR;
771 0 : }
772 :
773 : /* Select new cursor */
774 : #ifdef RASOPS_CLIPPING
775 : ri->ri_flg &= ~RI_CURSORCLIP;
776 :
777 : if (row < 0 || row >= ri->ri_rows)
778 : ri->ri_flg |= RI_CURSORCLIP;
779 : else if (col < 0 || col >= ri->ri_cols)
780 : ri->ri_flg |= RI_CURSORCLIP;
781 : #endif
782 0 : ri->ri_crow = row;
783 0 : ri->ri_ccol = col;
784 :
785 0 : if (ri->ri_updatecursor != NULL)
786 0 : ri->ri_updatecursor(ri);
787 :
788 0 : if (on) {
789 : #ifdef RASOPS_CLIPPING
790 : if ((ri->ri_flg & RI_CURSORCLIP) == 0)
791 : #endif
792 0 : if ((rc = ri->ri_do_cursor(ri)) != 0)
793 0 : return rc;
794 0 : ri->ri_flg |= RI_CURSOR;
795 0 : }
796 :
797 0 : return 0;
798 0 : }
799 :
800 : /*
801 : * Make the device colormap
802 : */
803 : void
804 0 : rasops_init_devcmap(struct rasops_info *ri)
805 : {
806 : int i;
807 : #if NRASOPS15 > 0 || NRASOPS16 > 0 || NRASOPS24 > 0 || NRASOPS32 > 0
808 : const u_char *p;
809 : #endif
810 : #if NRASOPS4 > 0 || NRASOPS15 > 0 || NRASOPS16 > 0 || NRASOPS24 > 0 || NRASOPS32 > 0
811 : int c;
812 : #endif
813 :
814 0 : if (ri->ri_depth == 1 || (ri->ri_flg & RI_FORCEMONO) != 0) {
815 0 : ri->ri_devcmap[0] = 0;
816 0 : for (i = 1; i < 16; i++)
817 0 : ri->ri_devcmap[i] = 0xffffffff;
818 0 : return;
819 : }
820 :
821 0 : switch (ri->ri_depth) {
822 : #if NRASOPS4 > 0
823 : case 4:
824 : for (i = 0; i < 16; i++) {
825 : c = i | (i << 4);
826 : ri->ri_devcmap[i] = c | (c<<8) | (c<<16) | (c<<24);
827 : }
828 : return;
829 : #endif
830 : #if NRASOPS8 > 0
831 : case 8:
832 0 : for (i = 0; i < 16; i++)
833 0 : ri->ri_devcmap[i] = i | (i<<8) | (i<<16) | (i<<24);
834 0 : return;
835 : #endif
836 : default:
837 : break;
838 : }
839 :
840 : #if NRASOPS15 > 0 || NRASOPS16 > 0 || NRASOPS24 > 0 || NRASOPS32 > 0
841 : p = rasops_cmap;
842 :
843 0 : for (i = 0; i < 16; i++) {
844 0 : if (ri->ri_rnum <= 8)
845 0 : c = (*p >> (8 - ri->ri_rnum)) << ri->ri_rpos;
846 : else
847 0 : c = (*p << (ri->ri_rnum - 8)) << ri->ri_rpos;
848 0 : p++;
849 :
850 0 : if (ri->ri_gnum <= 8)
851 0 : c |= (*p >> (8 - ri->ri_gnum)) << ri->ri_gpos;
852 : else
853 0 : c |= (*p << (ri->ri_gnum - 8)) << ri->ri_gpos;
854 0 : p++;
855 :
856 0 : if (ri->ri_bnum <= 8)
857 0 : c |= (*p >> (8 - ri->ri_bnum)) << ri->ri_bpos;
858 : else
859 0 : c |= (*p << (ri->ri_bnum - 8)) << ri->ri_bpos;
860 0 : p++;
861 :
862 : /* Fill the word for generic routines, which want this */
863 0 : if (ri->ri_depth == 24)
864 0 : c = c | ((c & 0xff) << 24);
865 0 : else if (ri->ri_depth <= 16)
866 0 : c = c | (c << 16);
867 :
868 : /* 24bpp does bswap on the fly. {32,16,15}bpp do it here. */
869 : #if NRASOPS_BSWAP > 0
870 : if ((ri->ri_flg & RI_BSWAP) == 0)
871 : ri->ri_devcmap[i] = c;
872 : else if (ri->ri_depth == 32)
873 : ri->ri_devcmap[i] = swap32(c);
874 : else if (ri->ri_depth == 16 || ri->ri_depth == 15)
875 : ri->ri_devcmap[i] = swap16(c);
876 : else
877 : ri->ri_devcmap[i] = c;
878 : #else
879 0 : ri->ri_devcmap[i] = c;
880 : #endif
881 : }
882 : #endif
883 0 : }
884 :
885 : /*
886 : * Unpack a rasops attribute
887 : */
888 : void
889 0 : rasops_unpack_attr(void *cookie, long attr, int *fg, int *bg, int *underline)
890 : {
891 0 : *fg = ((u_int)attr >> 24) & 0xf;
892 0 : *bg = ((u_int)attr >> 16) & 0xf;
893 0 : if (underline != NULL)
894 0 : *underline = (u_int)attr & 1;
895 0 : }
896 :
897 : /*
898 : * Erase rows
899 : */
900 : int
901 0 : rasops_eraserows(void *cookie, int row, int num, long attr)
902 : {
903 : struct rasops_info *ri;
904 : int np, nw, cnt, delta;
905 : int32_t *dp, clr;
906 :
907 0 : ri = (struct rasops_info *)cookie;
908 :
909 : #ifdef RASOPS_CLIPPING
910 : if (row < 0) {
911 : num += row;
912 : row = 0;
913 : }
914 :
915 : if ((row + num) > ri->ri_rows)
916 : num = ri->ri_rows - row;
917 :
918 : if (num <= 0)
919 : return 0;
920 : #endif
921 :
922 0 : clr = ri->ri_devcmap[(attr >> 16) & 0xf];
923 :
924 : /*
925 : * XXX The wsdisplay_emulops interface seems a little deficient in
926 : * that there is no way to clear the *entire* screen. We provide a
927 : * workaround here: if the entire console area is being cleared, and
928 : * the RI_FULLCLEAR flag is set, clear the entire display.
929 : */
930 0 : if (num == ri->ri_rows && (ri->ri_flg & RI_FULLCLEAR) != 0) {
931 0 : np = ri->ri_stride >> 5;
932 0 : nw = (ri->ri_stride >> 2) & 7;
933 0 : num = ri->ri_height;
934 0 : dp = (int32_t *)ri->ri_origbits;
935 : delta = 0;
936 0 : } else {
937 0 : np = ri->ri_emustride >> 5;
938 0 : nw = (ri->ri_emustride >> 2) & 7;
939 0 : num *= ri->ri_font->fontheight;
940 0 : dp = (int32_t *)(ri->ri_bits + row * ri->ri_yscale);
941 0 : delta = ri->ri_delta;
942 : }
943 :
944 0 : while (num--) {
945 0 : for (cnt = np; cnt; cnt--) {
946 0 : dp[0] = clr;
947 0 : dp[1] = clr;
948 0 : dp[2] = clr;
949 0 : dp[3] = clr;
950 0 : dp[4] = clr;
951 0 : dp[5] = clr;
952 0 : dp[6] = clr;
953 0 : dp[7] = clr;
954 0 : dp += 8;
955 : }
956 :
957 0 : for (cnt = nw; cnt; cnt--) {
958 0 : *(int32_t *)dp = clr;
959 0 : DELTA(dp, 4, int32_t *);
960 : }
961 :
962 0 : DELTA(dp, delta, int32_t *);
963 : }
964 :
965 0 : return 0;
966 : }
967 :
968 : /*
969 : * Actually turn the cursor on or off. This does the dirty work for
970 : * rasops_cursor().
971 : */
972 : int
973 0 : rasops_do_cursor(struct rasops_info *ri)
974 : {
975 : int full1, height, cnt, slop1, slop2, row, col;
976 : u_char *dp, *rp;
977 :
978 : #if NRASOPS_ROTATION > 0
979 0 : if (ri->ri_flg & RI_ROTATE_CW) {
980 : /* Rotate rows/columns */
981 0 : row = ri->ri_ccol;
982 0 : col = ri->ri_rows - ri->ri_crow - 1;
983 0 : } else if (ri->ri_flg & RI_ROTATE_CCW) {
984 : /* Rotate rows/columns */
985 0 : row = ri->ri_cols - ri->ri_ccol - 1;
986 0 : col = ri->ri_crow;
987 0 : } else
988 : #endif
989 : {
990 0 : row = ri->ri_crow;
991 0 : col = ri->ri_ccol;
992 : }
993 :
994 0 : rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
995 0 : height = ri->ri_font->fontheight;
996 0 : slop1 = (4 - ((long)rp & 3)) & 3;
997 :
998 0 : if (slop1 > ri->ri_xscale)
999 0 : slop1 = ri->ri_xscale;
1000 :
1001 0 : slop2 = (ri->ri_xscale - slop1) & 3;
1002 0 : full1 = (ri->ri_xscale - slop1 - slop2) >> 2;
1003 :
1004 0 : if ((slop1 | slop2) == 0) {
1005 : /* A common case */
1006 0 : while (height--) {
1007 : dp = rp;
1008 0 : rp += ri->ri_stride;
1009 :
1010 0 : for (cnt = full1; cnt; cnt--) {
1011 0 : *(int32_t *)dp ^= ~0;
1012 0 : dp += 4;
1013 : }
1014 : }
1015 : } else {
1016 : /* XXX this is stupid.. use masks instead */
1017 0 : while (height--) {
1018 : dp = rp;
1019 0 : rp += ri->ri_stride;
1020 :
1021 0 : if (slop1 & 1)
1022 0 : *dp++ ^= ~0;
1023 :
1024 0 : if (slop1 & 2) {
1025 0 : *(int16_t *)dp ^= ~0;
1026 0 : dp += 2;
1027 0 : }
1028 :
1029 0 : for (cnt = full1; cnt; cnt--) {
1030 0 : *(int32_t *)dp ^= ~0;
1031 0 : dp += 4;
1032 : }
1033 :
1034 0 : if (slop2 & 1)
1035 0 : *dp++ ^= ~0;
1036 :
1037 0 : if (slop2 & 2)
1038 0 : *(int16_t *)dp ^= ~0;
1039 : }
1040 : }
1041 :
1042 0 : return 0;
1043 : }
1044 :
1045 : /*
1046 : * Erase columns.
1047 : */
1048 : int
1049 0 : rasops_erasecols(void *cookie, int row, int col, int num, long attr)
1050 : {
1051 : int n8, height, cnt, slop1, slop2, clr;
1052 : struct rasops_info *ri;
1053 : int32_t *rp, *dp;
1054 :
1055 0 : ri = (struct rasops_info *)cookie;
1056 :
1057 : #ifdef RASOPS_CLIPPING
1058 : if ((unsigned)row >= (unsigned)ri->ri_rows)
1059 : return 0;
1060 :
1061 : if (col < 0) {
1062 : num += col;
1063 : col = 0;
1064 : }
1065 :
1066 : if ((col + num) > ri->ri_cols)
1067 : num = ri->ri_cols - col;
1068 :
1069 : if (num <= 0)
1070 : return 0;
1071 : #endif
1072 :
1073 0 : num = num * ri->ri_xscale;
1074 0 : rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
1075 0 : height = ri->ri_font->fontheight;
1076 0 : clr = ri->ri_devcmap[(attr >> 16) & 0xf];
1077 :
1078 : /* Don't bother using the full loop for <= 32 pels */
1079 0 : if (num <= 32) {
1080 0 : if (((num | ri->ri_xscale) & 3) == 0) {
1081 : /* Word aligned blt */
1082 0 : num >>= 2;
1083 :
1084 0 : while (height--) {
1085 : dp = rp;
1086 0 : DELTA(rp, ri->ri_stride, int32_t *);
1087 :
1088 0 : for (cnt = num; cnt; cnt--)
1089 0 : *dp++ = clr;
1090 : }
1091 0 : } else if (((num | ri->ri_xscale) & 1) == 0) {
1092 : /*
1093 : * Halfword aligned blt. This is needed so the
1094 : * 15/16 bit ops can use this function.
1095 : */
1096 0 : num >>= 1;
1097 :
1098 0 : while (height--) {
1099 : dp = rp;
1100 0 : DELTA(rp, ri->ri_stride, int32_t *);
1101 :
1102 0 : for (cnt = num; cnt; cnt--) {
1103 0 : *(int16_t *)dp = clr;
1104 0 : DELTA(dp, 2, int32_t *);
1105 : }
1106 : }
1107 : } else {
1108 0 : while (height--) {
1109 : dp = rp;
1110 0 : DELTA(rp, ri->ri_stride, int32_t *);
1111 :
1112 0 : for (cnt = num; cnt; cnt--) {
1113 0 : *(u_char *)dp = clr;
1114 0 : DELTA(dp, 1, int32_t *);
1115 : }
1116 : }
1117 : }
1118 :
1119 0 : return 0;
1120 : }
1121 :
1122 0 : slop1 = (4 - ((long)rp & 3)) & 3;
1123 0 : slop2 = (num - slop1) & 3;
1124 0 : num -= slop1 + slop2;
1125 0 : n8 = num >> 5;
1126 0 : num = (num >> 2) & 7;
1127 :
1128 0 : while (height--) {
1129 : dp = rp;
1130 0 : DELTA(rp, ri->ri_stride, int32_t *);
1131 :
1132 : /* Align span to 4 bytes */
1133 0 : if (slop1 & 1) {
1134 0 : *(u_char *)dp = clr;
1135 0 : DELTA(dp, 1, int32_t *);
1136 0 : }
1137 :
1138 0 : if (slop1 & 2) {
1139 0 : *(int16_t *)dp = clr;
1140 0 : DELTA(dp, 2, int32_t *);
1141 0 : }
1142 :
1143 : /* Write 32 bytes per loop */
1144 0 : for (cnt = n8; cnt; cnt--) {
1145 0 : dp[0] = clr;
1146 0 : dp[1] = clr;
1147 0 : dp[2] = clr;
1148 0 : dp[3] = clr;
1149 0 : dp[4] = clr;
1150 0 : dp[5] = clr;
1151 0 : dp[6] = clr;
1152 0 : dp[7] = clr;
1153 0 : dp += 8;
1154 : }
1155 :
1156 : /* Write 4 bytes per loop */
1157 0 : for (cnt = num; cnt; cnt--)
1158 0 : *dp++ = clr;
1159 :
1160 : /* Write unaligned trailing slop */
1161 0 : if (slop2 & 1) {
1162 0 : *(u_char *)dp = clr;
1163 0 : DELTA(dp, 1, int32_t *);
1164 0 : }
1165 :
1166 0 : if (slop2 & 2)
1167 0 : *(int16_t *)dp = clr;
1168 : }
1169 :
1170 0 : return 0;
1171 0 : }
1172 :
1173 : #if NRASOPS_ROTATION > 0
1174 : /*
1175 : * Quarter clockwise rotation routines (originally intended for the
1176 : * built-in Zaurus C3x00 display in 16bpp).
1177 : */
1178 :
1179 : #include <sys/malloc.h>
1180 :
1181 : void
1182 0 : rasops_rotate_font(int *cookie, int ccw)
1183 : {
1184 : struct rotatedfont *f;
1185 : int ncookie;
1186 :
1187 0 : SLIST_FOREACH(f, &rotatedfonts, rf_next) {
1188 0 : if (f->rf_cookie == *cookie) {
1189 0 : *cookie = f->rf_rotated;
1190 0 : return;
1191 : }
1192 : }
1193 :
1194 : /*
1195 : * We did not find a rotated version of this font. Ask the wsfont
1196 : * code to compute one for us.
1197 : */
1198 0 : if ((ncookie = wsfont_rotate(*cookie, ccw)) == -1)
1199 0 : return;
1200 :
1201 0 : f = malloc(sizeof(struct rotatedfont), M_DEVBUF, M_WAITOK);
1202 0 : f->rf_cookie = *cookie;
1203 0 : f->rf_rotated = ncookie;
1204 0 : SLIST_INSERT_HEAD(&rotatedfonts, f, rf_next);
1205 :
1206 0 : *cookie = ncookie;
1207 0 : }
1208 :
1209 : void
1210 0 : rasops_copychar(void *cookie, int srcrow, int dstrow, int srccol, int dstcol)
1211 : {
1212 : struct rasops_info *ri;
1213 : u_char *sp, *dp;
1214 : int height;
1215 : int r_srcrow, r_dstrow, r_srccol, r_dstcol;
1216 :
1217 0 : ri = (struct rasops_info *)cookie;
1218 :
1219 : r_srcrow = srccol;
1220 : r_dstrow = dstcol;
1221 0 : r_srccol = ri->ri_rows - srcrow - 1;
1222 0 : r_dstcol = ri->ri_rows - dstrow - 1;
1223 :
1224 0 : r_srcrow *= ri->ri_yscale;
1225 0 : r_dstrow *= ri->ri_yscale;
1226 0 : height = ri->ri_font->fontheight;
1227 :
1228 0 : sp = ri->ri_bits + r_srcrow + r_srccol * ri->ri_xscale;
1229 0 : dp = ri->ri_bits + r_dstrow + r_dstcol * ri->ri_xscale;
1230 :
1231 : #if NRASOPS_BSWAP > 0
1232 : if (ri->ri_flg & RI_BSWAP) {
1233 : while (height--) {
1234 : slow_bcopy(sp, dp, ri->ri_xscale);
1235 : dp += ri->ri_stride;
1236 : sp += ri->ri_stride;
1237 : }
1238 : } else
1239 : #endif
1240 : {
1241 0 : while (height--) {
1242 0 : memmove(dp, sp, ri->ri_xscale);
1243 0 : dp += ri->ri_stride;
1244 0 : sp += ri->ri_stride;
1245 : }
1246 : }
1247 0 : }
1248 :
1249 : int
1250 0 : rasops_putchar_rotated(void *cookie, int row, int col, u_int uc, long attr)
1251 : {
1252 : struct rasops_info *ri;
1253 : u_char *rp;
1254 : int height;
1255 : int rc;
1256 :
1257 0 : ri = (struct rasops_info *)cookie;
1258 :
1259 0 : if (ri->ri_flg & RI_ROTATE_CW)
1260 0 : row = ri->ri_rows - row - 1;
1261 : else
1262 0 : col = ri->ri_cols - col - 1;
1263 :
1264 : /* Do rotated char sans (side)underline */
1265 0 : rc = ri->ri_real_ops.putchar(cookie, col, row, uc, attr & ~1);
1266 0 : if (rc != 0)
1267 0 : return rc;
1268 :
1269 : /* Do rotated underline */
1270 0 : rp = ri->ri_bits + col * ri->ri_yscale + row * ri->ri_xscale;
1271 0 : if (ri->ri_flg & RI_ROTATE_CCW)
1272 0 : rp += (ri->ri_font->fontwidth - 1) * ri->ri_pelbytes;
1273 0 : height = ri->ri_font->fontheight;
1274 :
1275 : /* XXX this assumes 16-bit color depth */
1276 0 : if ((attr & 1) != 0) {
1277 0 : int16_t c = (int16_t)ri->ri_devcmap[((u_int)attr >> 24) & 0xf];
1278 :
1279 0 : while (height--) {
1280 0 : *(int16_t *)rp = c;
1281 0 : rp += ri->ri_stride;
1282 : }
1283 0 : }
1284 :
1285 0 : return 0;
1286 0 : }
1287 :
1288 : int
1289 0 : rasops_erasecols_rotated(void *cookie, int row, int col, int num, long attr)
1290 : {
1291 : int i;
1292 : int rc;
1293 :
1294 0 : for (i = col; i < col + num; i++) {
1295 0 : rc = rasops_putchar_rotated(cookie, row, i, ' ', attr);
1296 0 : if (rc != 0)
1297 0 : return rc;
1298 : }
1299 :
1300 0 : return 0;
1301 0 : }
1302 :
1303 : /* XXX: these could likely be optimised somewhat. */
1304 : int
1305 0 : rasops_copyrows_rotated(void *cookie, int src, int dst, int num)
1306 : {
1307 0 : struct rasops_info *ri = (struct rasops_info *)cookie;
1308 : int col, roff;
1309 :
1310 0 : if (src > dst) {
1311 0 : for (roff = 0; roff < num; roff++)
1312 0 : for (col = 0; col < ri->ri_cols; col++)
1313 0 : rasops_copychar(cookie, src + roff, dst + roff,
1314 : col, col);
1315 : } else {
1316 0 : for (roff = num - 1; roff >= 0; roff--)
1317 0 : for (col = 0; col < ri->ri_cols; col++)
1318 0 : rasops_copychar(cookie, src + roff, dst + roff,
1319 : col, col);
1320 : }
1321 :
1322 0 : return 0;
1323 : }
1324 :
1325 : int
1326 0 : rasops_copycols_rotated(void *cookie, int row, int src, int dst, int num)
1327 : {
1328 : int coff;
1329 :
1330 0 : if (src > dst) {
1331 0 : for (coff = 0; coff < num; coff++)
1332 0 : rasops_copychar(cookie, row, row, src + coff,
1333 0 : dst + coff);
1334 : } else {
1335 0 : for (coff = num - 1; coff >= 0; coff--)
1336 0 : rasops_copychar(cookie, row, row, src + coff,
1337 0 : dst + coff);
1338 : }
1339 :
1340 0 : return 0;
1341 : }
1342 :
1343 : int
1344 0 : rasops_eraserows_rotated(void *cookie, int row, int num, long attr)
1345 : {
1346 : struct rasops_info *ri;
1347 : int col, rn;
1348 : int rc;
1349 :
1350 0 : ri = (struct rasops_info *)cookie;
1351 :
1352 0 : for (rn = row; rn < row + num; rn++)
1353 0 : for (col = 0; col < ri->ri_cols; col++) {
1354 0 : rc = rasops_putchar_rotated(cookie, rn, col, ' ', attr);
1355 0 : if (rc != 0)
1356 0 : return rc;
1357 : }
1358 :
1359 0 : return 0;
1360 0 : }
1361 : #endif /* NRASOPS_ROTATION */
1362 :
1363 : #if NRASOPS_BSWAP > 0
1364 : /*
1365 : * Strictly byte-only bcopy() version, to be used with RI_BSWAP, as the
1366 : * regular bcopy() may want to optimize things by doing larger-than-byte
1367 : * reads or write. This may confuse things if src and dst have different
1368 : * alignments.
1369 : */
1370 : void
1371 : slow_bcopy(void *s, void *d, size_t len)
1372 : {
1373 : u_int8_t *src = s;
1374 : u_int8_t *dst = d;
1375 :
1376 : if ((vaddr_t)dst <= (vaddr_t)src) {
1377 : while (len-- != 0)
1378 : *dst++ = *src++;
1379 : } else {
1380 : src += len;
1381 : dst += len;
1382 : if (len != 0)
1383 : while (--len != 0)
1384 : *--dst = *--src;
1385 : }
1386 : }
1387 : #endif /* NRASOPS_BSWAP */
1388 :
1389 : int
1390 0 : rasops_alloc_screen(void *v, void **cookiep,
1391 : int *curxp, int *curyp, long *attrp)
1392 : {
1393 0 : struct rasops_info *ri = v;
1394 : struct rasops_screen *scr;
1395 : int i;
1396 :
1397 0 : scr = malloc(sizeof(*scr), M_DEVBUF, M_NOWAIT);
1398 0 : if (scr == NULL)
1399 0 : return (ENOMEM);
1400 :
1401 0 : scr->rs_sbscreens = RS_SCROLLBACK_SCREENS;
1402 0 : scr->rs_bs = mallocarray(ri->ri_rows * (scr->rs_sbscreens + 1),
1403 0 : ri->ri_cols * sizeof(struct wsdisplay_charcell), M_DEVBUF,
1404 : M_NOWAIT);
1405 0 : if (scr->rs_bs == NULL) {
1406 0 : free(scr, M_DEVBUF, sizeof(*scr));
1407 0 : return (ENOMEM);
1408 : }
1409 0 : scr->rs_visibleoffset = scr->rs_dispoffset = ri->ri_rows *
1410 0 : scr->rs_sbscreens * ri->ri_cols;
1411 :
1412 0 : *cookiep = scr;
1413 0 : *curxp = 0;
1414 0 : *curyp = 0;
1415 0 : ri->ri_alloc_attr(ri, 0, 0, 0, attrp);
1416 :
1417 0 : scr->rs_ri = ri;
1418 0 : scr->rs_visible = (ri->ri_nscreens == 0);
1419 0 : scr->rs_crow = -1;
1420 0 : scr->rs_ccol = -1;
1421 0 : scr->rs_defattr = *attrp;
1422 :
1423 0 : for (i = 0; i < scr->rs_dispoffset; i++) {
1424 0 : scr->rs_bs[i].uc = ' ';
1425 0 : scr->rs_bs[i].attr = scr->rs_defattr;
1426 : }
1427 :
1428 0 : if (ri->ri_bs && scr->rs_visible) {
1429 0 : memcpy(scr->rs_bs + scr->rs_dispoffset, ri->ri_bs,
1430 : ri->ri_rows * ri->ri_cols *
1431 : sizeof(struct wsdisplay_charcell));
1432 0 : } else {
1433 0 : for (i = 0; i < ri->ri_rows * ri->ri_cols; i++) {
1434 0 : scr->rs_bs[scr->rs_dispoffset + i].uc = ' ';
1435 0 : scr->rs_bs[scr->rs_dispoffset + i].attr =
1436 0 : scr->rs_defattr;
1437 : }
1438 : }
1439 :
1440 0 : LIST_INSERT_HEAD(&ri->ri_screens, scr, rs_next);
1441 0 : ri->ri_nscreens++;
1442 :
1443 0 : return (0);
1444 0 : }
1445 :
1446 : void
1447 0 : rasops_free_screen(void *v, void *cookie)
1448 : {
1449 0 : struct rasops_info *ri = v;
1450 0 : struct rasops_screen *scr = cookie;
1451 :
1452 0 : LIST_REMOVE(scr, rs_next);
1453 0 : ri->ri_nscreens--;
1454 :
1455 0 : free(scr->rs_bs, M_DEVBUF,
1456 0 : ri->ri_rows * (scr->rs_sbscreens + 1) * ri->ri_cols *
1457 : sizeof(struct wsdisplay_charcell));
1458 0 : free(scr, M_DEVBUF, sizeof(*scr));
1459 0 : }
1460 :
1461 : int
1462 0 : rasops_show_screen(void *v, void *cookie, int waitok,
1463 : void (*cb)(void *, int, int), void *cbarg)
1464 : {
1465 0 : struct rasops_info *ri = v;
1466 :
1467 0 : ri->ri_switchcookie = cookie;
1468 0 : if (cb) {
1469 0 : ri->ri_switchcb = cb;
1470 0 : ri->ri_switchcbarg = cbarg;
1471 0 : task_add(systq, &ri->ri_switchtask);
1472 0 : return (EAGAIN);
1473 : }
1474 :
1475 0 : rasops_doswitch(ri);
1476 0 : return (0);
1477 0 : }
1478 :
1479 : void
1480 0 : rasops_doswitch(void *v)
1481 : {
1482 0 : struct rasops_info *ri = v;
1483 0 : struct rasops_screen *scr = ri->ri_switchcookie;
1484 : int row, col;
1485 :
1486 0 : rasops_cursor(ri, 0, 0, 0);
1487 0 : ri->ri_active->rs_visible = 0;
1488 0 : ri->ri_eraserows(ri, 0, ri->ri_rows, scr->rs_defattr);
1489 0 : ri->ri_active = scr;
1490 0 : ri->ri_bs = &ri->ri_active->rs_bs[ri->ri_active->rs_dispoffset];
1491 0 : ri->ri_active->rs_visible = 1;
1492 0 : ri->ri_active->rs_visibleoffset = ri->ri_active->rs_dispoffset;
1493 0 : for (row = 0; row < ri->ri_rows; row++) {
1494 0 : for (col = 0; col < ri->ri_cols; col++) {
1495 0 : int off = row * scr->rs_ri->ri_cols + col +
1496 0 : scr->rs_visibleoffset;
1497 :
1498 0 : ri->ri_putchar(ri, row, col, scr->rs_bs[off].uc,
1499 0 : scr->rs_bs[off].attr);
1500 : }
1501 : }
1502 0 : if (scr->rs_crow != -1)
1503 0 : rasops_cursor(ri, 1, scr->rs_crow, scr->rs_ccol);
1504 :
1505 0 : if (ri->ri_switchcb)
1506 0 : (*ri->ri_switchcb)(ri->ri_switchcbarg, 0, 0);
1507 0 : }
1508 :
1509 : int
1510 0 : rasops_getchar(void *v, int row, int col, struct wsdisplay_charcell *cell)
1511 : {
1512 0 : struct rasops_info *ri = v;
1513 0 : struct rasops_screen *scr = ri->ri_active;
1514 :
1515 0 : if (scr == NULL || scr->rs_bs == NULL)
1516 0 : return (1);
1517 :
1518 0 : *cell = scr->rs_bs[row * ri->ri_cols + col + scr->rs_dispoffset];
1519 0 : return (0);
1520 0 : }
1521 :
1522 : int
1523 0 : rasops_vcons_cursor(void *cookie, int on, int row, int col)
1524 : {
1525 0 : struct rasops_screen *scr = cookie;
1526 :
1527 0 : scr->rs_crow = on ? row : -1;
1528 0 : scr->rs_ccol = on ? col : -1;
1529 :
1530 0 : if (!scr->rs_visible)
1531 0 : return 0;
1532 :
1533 0 : return rasops_cursor(scr->rs_ri, on, row, col);
1534 0 : }
1535 :
1536 : int
1537 0 : rasops_vcons_mapchar(void *cookie, int c, u_int *cp)
1538 : {
1539 0 : struct rasops_screen *scr = cookie;
1540 :
1541 0 : return rasops_mapchar(scr->rs_ri, c, cp);
1542 : }
1543 :
1544 : int
1545 0 : rasops_vcons_putchar(void *cookie, int row, int col, u_int uc, long attr)
1546 : {
1547 0 : struct rasops_screen *scr = cookie;
1548 0 : int off = row * scr->rs_ri->ri_cols + col + scr->rs_dispoffset;
1549 :
1550 0 : if (scr->rs_visible && scr->rs_visibleoffset != scr->rs_dispoffset)
1551 0 : rasops_scrollback(scr->rs_ri, scr, 0);
1552 :
1553 0 : scr->rs_bs[off].uc = uc;
1554 0 : scr->rs_bs[off].attr = attr;
1555 :
1556 0 : if (!scr->rs_visible)
1557 0 : return 0;
1558 :
1559 0 : return scr->rs_ri->ri_putchar(scr->rs_ri, row, col, uc, attr);
1560 0 : }
1561 :
1562 : int
1563 0 : rasops_vcons_copycols(void *cookie, int row, int src, int dst, int num)
1564 : {
1565 0 : struct rasops_screen *scr = cookie;
1566 0 : struct rasops_info *ri = scr->rs_ri;
1567 0 : int cols = scr->rs_ri->ri_cols;
1568 : int col, rc;
1569 :
1570 0 : memmove(&scr->rs_bs[row * cols + dst + scr->rs_dispoffset],
1571 : &scr->rs_bs[row * cols + src + scr->rs_dispoffset],
1572 : num * sizeof(struct wsdisplay_charcell));
1573 :
1574 0 : if (!scr->rs_visible)
1575 0 : return 0;
1576 :
1577 0 : if ((ri->ri_flg & RI_WRONLY) == 0)
1578 0 : return ri->ri_copycols(ri, row, src, dst, num);
1579 :
1580 0 : for (col = dst; col < dst + num; col++) {
1581 0 : int off = row * cols + col + scr->rs_dispoffset;
1582 :
1583 0 : rc = ri->ri_putchar(ri, row, col,
1584 0 : scr->rs_bs[off].uc, scr->rs_bs[off].attr);
1585 0 : if (rc != 0)
1586 0 : return rc;
1587 0 : }
1588 :
1589 0 : return 0;
1590 0 : }
1591 :
1592 : int
1593 0 : rasops_vcons_erasecols(void *cookie, int row, int col, int num, long attr)
1594 : {
1595 0 : struct rasops_screen *scr = cookie;
1596 0 : int cols = scr->rs_ri->ri_cols;
1597 : int i;
1598 :
1599 0 : for (i = 0; i < num; i++) {
1600 0 : int off = row * cols + col + i + scr->rs_dispoffset;
1601 :
1602 0 : scr->rs_bs[off].uc = ' ';
1603 0 : scr->rs_bs[off].attr = attr;
1604 : }
1605 :
1606 0 : if (!scr->rs_visible)
1607 0 : return 0;
1608 :
1609 0 : return scr->rs_ri->ri_erasecols(scr->rs_ri, row, col, num, attr);
1610 0 : }
1611 :
1612 : int
1613 0 : rasops_vcons_copyrows(void *cookie, int src, int dst, int num)
1614 : {
1615 0 : struct rasops_screen *scr = cookie;
1616 0 : struct rasops_info *ri = scr->rs_ri;
1617 0 : int cols = ri->ri_cols;
1618 : int row, col, rc;
1619 :
1620 0 : if (dst == 0 && (src + num == ri->ri_rows) && scr->rs_sbscreens > 0)
1621 0 : memmove(&scr->rs_bs[dst], &scr->rs_bs[src * cols],
1622 : ((ri->ri_rows * (scr->rs_sbscreens + 1) * cols) -
1623 : (src * cols)) * sizeof(struct wsdisplay_charcell));
1624 : else
1625 0 : memmove(&scr->rs_bs[dst * cols + scr->rs_dispoffset],
1626 : &scr->rs_bs[src * cols + scr->rs_dispoffset],
1627 : num * cols * sizeof(struct wsdisplay_charcell));
1628 :
1629 0 : if (!scr->rs_visible)
1630 0 : return 0;
1631 :
1632 0 : if ((ri->ri_flg & RI_WRONLY) == 0)
1633 0 : return ri->ri_copyrows(ri, src, dst, num);
1634 :
1635 0 : for (row = dst; row < dst + num; row++) {
1636 0 : for (col = 0; col < cols; col++) {
1637 0 : int off = row * cols + col + scr->rs_dispoffset;
1638 :
1639 0 : rc = ri->ri_putchar(ri, row, col,
1640 0 : scr->rs_bs[off].uc, scr->rs_bs[off].attr);
1641 0 : if (rc != 0)
1642 0 : return rc;
1643 0 : }
1644 : }
1645 :
1646 0 : return 0;
1647 0 : }
1648 :
1649 : int
1650 0 : rasops_vcons_eraserows(void *cookie, int row, int num, long attr)
1651 : {
1652 0 : struct rasops_screen *scr = cookie;
1653 0 : int cols = scr->rs_ri->ri_cols;
1654 : int i;
1655 :
1656 0 : for (i = 0; i < num * cols; i++) {
1657 0 : int off = row * cols + i + scr->rs_dispoffset;
1658 :
1659 0 : scr->rs_bs[off].uc = ' ';
1660 0 : scr->rs_bs[off].attr = attr;
1661 : }
1662 :
1663 0 : if (!scr->rs_visible)
1664 0 : return 0;
1665 :
1666 0 : return scr->rs_ri->ri_eraserows(scr->rs_ri, row, num, attr);
1667 0 : }
1668 :
1669 : int
1670 0 : rasops_vcons_alloc_attr(void *cookie, int fg, int bg, int flg, long *attr)
1671 : {
1672 0 : struct rasops_screen *scr = cookie;
1673 :
1674 0 : return scr->rs_ri->ri_alloc_attr(scr->rs_ri, fg, bg, flg, attr);
1675 : }
1676 :
1677 : void
1678 0 : rasops_vcons_unpack_attr(void *cookie, long attr, int *fg, int *bg,
1679 : int *underline)
1680 : {
1681 0 : struct rasops_screen *scr = cookie;
1682 :
1683 0 : rasops_unpack_attr(scr->rs_ri, attr, fg, bg, underline);
1684 0 : }
1685 :
1686 : int
1687 0 : rasops_wronly_putchar(void *cookie, int row, int col, u_int uc, long attr)
1688 : {
1689 0 : struct rasops_info *ri = cookie;
1690 0 : int off = row * ri->ri_cols + col;
1691 :
1692 0 : ri->ri_bs[off].uc = uc;
1693 0 : ri->ri_bs[off].attr = attr;
1694 :
1695 0 : return ri->ri_putchar(ri, row, col, uc, attr);
1696 : }
1697 :
1698 : int
1699 0 : rasops_wronly_copycols(void *cookie, int row, int src, int dst, int num)
1700 : {
1701 0 : struct rasops_info *ri = cookie;
1702 0 : int cols = ri->ri_cols;
1703 : int col, rc;
1704 :
1705 0 : memmove(&ri->ri_bs[row * cols + dst], &ri->ri_bs[row * cols + src],
1706 : num * sizeof(struct wsdisplay_charcell));
1707 :
1708 0 : for (col = dst; col < dst + num; col++) {
1709 0 : int off = row * cols + col;
1710 :
1711 0 : rc = ri->ri_putchar(ri, row, col,
1712 0 : ri->ri_bs[off].uc, ri->ri_bs[off].attr);
1713 0 : if (rc != 0)
1714 0 : return rc;
1715 0 : }
1716 :
1717 0 : return 0;
1718 0 : }
1719 :
1720 : int
1721 0 : rasops_wronly_erasecols(void *cookie, int row, int col, int num, long attr)
1722 : {
1723 0 : struct rasops_info *ri = cookie;
1724 0 : int cols = ri->ri_cols;
1725 : int i;
1726 :
1727 0 : for (i = 0; i < num; i++) {
1728 0 : int off = row * cols + col + i;
1729 :
1730 0 : ri->ri_bs[off].uc = ' ';
1731 0 : ri->ri_bs[off].attr = attr;
1732 : }
1733 :
1734 0 : return ri->ri_erasecols(ri, row, col, num, attr);
1735 : }
1736 :
1737 : int
1738 0 : rasops_wronly_copyrows(void *cookie, int src, int dst, int num)
1739 : {
1740 0 : struct rasops_info *ri = cookie;
1741 0 : int cols = ri->ri_cols;
1742 : int row, col, rc;
1743 :
1744 0 : memmove(&ri->ri_bs[dst * cols], &ri->ri_bs[src * cols],
1745 : num * cols * sizeof(struct wsdisplay_charcell));
1746 :
1747 0 : for (row = dst; row < dst + num; row++) {
1748 0 : for (col = 0; col < cols; col++) {
1749 0 : int off = row * cols + col;
1750 :
1751 0 : rc = ri->ri_putchar(ri, row, col,
1752 0 : ri->ri_bs[off].uc, ri->ri_bs[off].attr);
1753 0 : if (rc != 0)
1754 0 : return rc;
1755 0 : }
1756 : }
1757 :
1758 0 : return 0;
1759 0 : }
1760 :
1761 : int
1762 0 : rasops_wronly_eraserows(void *cookie, int row, int num, long attr)
1763 : {
1764 0 : struct rasops_info *ri = cookie;
1765 0 : int cols = ri->ri_cols;
1766 : int i;
1767 :
1768 0 : for (i = 0; i < num * cols; i++) {
1769 0 : int off = row * cols + i;
1770 :
1771 0 : ri->ri_bs[off].uc = ' ';
1772 0 : ri->ri_bs[off].attr = attr;
1773 : }
1774 :
1775 0 : return ri->ri_eraserows(ri, row, num, attr);
1776 : }
1777 :
1778 : int
1779 0 : rasops_wronly_do_cursor(struct rasops_info *ri)
1780 : {
1781 0 : int off = ri->ri_crow * ri->ri_cols + ri->ri_ccol;
1782 : u_int uc;
1783 : long attr;
1784 : int fg, bg;
1785 :
1786 0 : uc = ri->ri_bs[off].uc;
1787 0 : attr = ri->ri_bs[off].attr;
1788 :
1789 0 : if ((ri->ri_flg & RI_CURSOR) == 0) {
1790 0 : fg = ((u_int)attr >> 24) & 0xf;
1791 0 : bg = ((u_int)attr >> 16) & 0xf;
1792 0 : attr &= ~0x0ffff0000;
1793 0 : attr |= (fg << 16) | (bg << 24);
1794 0 : }
1795 :
1796 0 : return ri->ri_putchar(ri, ri->ri_crow, ri->ri_ccol, uc, attr);
1797 : }
1798 :
1799 : /*
1800 : * Font management.
1801 : *
1802 : * Fonts usable on raster frame buffers are managed by wsfont, and are not
1803 : * tied to any particular display.
1804 : */
1805 :
1806 : int
1807 0 : rasops_add_font(struct rasops_info *ri, struct wsdisplay_font *font)
1808 : {
1809 : /* only accept matching metrics */
1810 0 : if (font->fontwidth != ri->ri_font->fontwidth ||
1811 0 : font->fontheight != ri->ri_font->fontheight)
1812 0 : return EINVAL;
1813 :
1814 : /* for raster consoles, only accept ISO Latin-1 or Unicode encoding */
1815 0 : if (font->encoding != WSDISPLAY_FONTENC_ISO)
1816 0 : return EINVAL;
1817 :
1818 0 : if (wsfont_add(font, 1) != 0)
1819 0 : return EEXIST; /* name collision */
1820 :
1821 0 : font->index = -1; /* do not store in wsdisplay_softc */
1822 :
1823 0 : return 0;
1824 0 : }
1825 :
1826 : int
1827 0 : rasops_use_font(struct rasops_info *ri, struct wsdisplay_font *font)
1828 : {
1829 : int wsfcookie;
1830 0 : struct wsdisplay_font *wsf;
1831 : const char *name;
1832 :
1833 : /* allow an empty font name to revert to the initial font choice */
1834 0 : name = font->name;
1835 0 : if (*name == '\0')
1836 : name = NULL;
1837 :
1838 0 : wsfcookie = wsfont_find(name, ri->ri_font->fontwidth,
1839 0 : ri->ri_font->fontheight, 0);
1840 0 : if (wsfcookie < 0) {
1841 0 : wsfcookie = wsfont_find(name, 0, 0, 0);
1842 0 : if (wsfcookie < 0)
1843 0 : return ENOENT; /* font exist, but different metrics */
1844 : else
1845 0 : return EINVAL;
1846 : }
1847 0 : if (wsfont_lock(wsfcookie, &wsf, WSDISPLAY_FONTORDER_KNOWN,
1848 0 : WSDISPLAY_FONTORDER_KNOWN) < 0)
1849 0 : return EINVAL;
1850 :
1851 : /* if (ri->ri_wsfcookie >= 0) */
1852 0 : wsfont_unlock(ri->ri_wsfcookie);
1853 0 : ri->ri_wsfcookie = wsfcookie;
1854 0 : ri->ri_font = wsf;
1855 0 : ri->ri_fontscale = ri->ri_font->fontheight * ri->ri_font->stride;
1856 :
1857 0 : return 0;
1858 0 : }
1859 :
1860 : int
1861 0 : rasops_load_font(void *v, void *cookie, struct wsdisplay_font *font)
1862 : {
1863 0 : struct rasops_info *ri = v;
1864 :
1865 : /*
1866 : * For now, we want to only allow loading fonts of the same
1867 : * metrics as the currently in-use font. This requires the
1868 : * rasops struct to have been correctly configured, and a
1869 : * font to have been selected.
1870 : */
1871 0 : if ((ri->ri_flg & RI_CFGDONE) == 0 || ri->ri_font == NULL)
1872 0 : return EINVAL;
1873 :
1874 0 : if (font->data != NULL)
1875 0 : return rasops_add_font(ri, font);
1876 : else
1877 0 : return rasops_use_font(ri, font);
1878 0 : }
1879 :
1880 : struct rasops_list_font_ctx {
1881 : struct rasops_info *ri;
1882 : int cnt;
1883 : struct wsdisplay_font *font;
1884 : };
1885 :
1886 : int
1887 0 : rasops_list_font_cb(void *cbarg, struct wsdisplay_font *font)
1888 : {
1889 0 : struct rasops_list_font_ctx *ctx = cbarg;
1890 :
1891 0 : if (font->fontheight != ctx->ri->ri_font->fontheight ||
1892 0 : font->fontwidth != ctx->ri->ri_font->fontwidth)
1893 0 : return 0;
1894 :
1895 0 : if (ctx->cnt-- == 0) {
1896 0 : ctx->font = font;
1897 0 : return 1;
1898 : }
1899 :
1900 0 : return 0;
1901 0 : }
1902 :
1903 : int
1904 0 : rasops_list_font(void *v, struct wsdisplay_font *font)
1905 : {
1906 0 : struct rasops_info *ri = v;
1907 0 : struct rasops_list_font_ctx ctx;
1908 : int idx;
1909 :
1910 0 : if ((ri->ri_flg & RI_CFGDONE) == 0 || ri->ri_font == NULL)
1911 0 : return EINVAL;
1912 :
1913 0 : if (font->index < 0)
1914 0 : return EINVAL;
1915 :
1916 0 : ctx.ri = ri;
1917 0 : ctx.cnt = font->index;
1918 0 : ctx.font = NULL;
1919 0 : wsfont_enum(rasops_list_font_cb, &ctx);
1920 :
1921 0 : if (ctx.font == NULL)
1922 0 : return EINVAL;
1923 :
1924 0 : idx = font->index;
1925 0 : *font = *ctx.font; /* struct copy */
1926 0 : font->index = idx;
1927 0 : font->cookie = font->data = NULL; /* don't leak kernel pointers */
1928 0 : return 0;
1929 0 : }
1930 :
1931 : void
1932 0 : rasops_scrollback(void *v, void *cookie, int lines)
1933 : {
1934 0 : struct rasops_info *ri = v;
1935 0 : struct rasops_screen *scr = cookie;
1936 : int row, col, oldvoff;
1937 :
1938 0 : oldvoff = scr->rs_visibleoffset;
1939 :
1940 0 : if (lines == 0)
1941 0 : scr->rs_visibleoffset = scr->rs_dispoffset;
1942 : else {
1943 0 : int off = scr->rs_visibleoffset + (lines * ri->ri_cols);
1944 :
1945 0 : if (off < 0)
1946 0 : off = 0;
1947 0 : else if (off > scr->rs_dispoffset)
1948 0 : off = scr->rs_dispoffset;
1949 :
1950 0 : scr->rs_visibleoffset = off;
1951 : }
1952 :
1953 0 : if (scr->rs_visibleoffset == oldvoff)
1954 0 : return;
1955 :
1956 0 : rasops_cursor(ri, 0, 0, 0);
1957 0 : ri->ri_eraserows(ri, 0, ri->ri_rows, scr->rs_defattr);
1958 0 : for (row = 0; row < ri->ri_rows; row++) {
1959 0 : for (col = 0; col < ri->ri_cols; col++) {
1960 0 : int off = row * scr->rs_ri->ri_cols + col +
1961 0 : scr->rs_visibleoffset;
1962 :
1963 0 : ri->ri_putchar(ri, row, col, scr->rs_bs[off].uc,
1964 0 : scr->rs_bs[off].attr);
1965 : }
1966 : }
1967 :
1968 0 : if (scr->rs_crow != -1 && scr->rs_visibleoffset == scr->rs_dispoffset)
1969 0 : rasops_cursor(ri, 1, scr->rs_crow, scr->rs_ccol);
1970 0 : }
1971 :
1972 : struct rasops_framebuffer {
1973 : SLIST_ENTRY(rasops_framebuffer) rf_list;
1974 : paddr_t rf_base;
1975 : psize_t rf_size;
1976 : struct device *rf_dev;
1977 : };
1978 :
1979 : SLIST_HEAD(, rasops_framebuffer) rasops_framebuffers =
1980 : SLIST_HEAD_INITIALIZER(&rasops_framebuffers);
1981 :
1982 : void
1983 0 : rasops_claim_framebuffer(paddr_t base, psize_t size, struct device *dev)
1984 : {
1985 : struct rasops_framebuffer *rf;
1986 :
1987 0 : rf = malloc(sizeof(*rf), M_DEVBUF, M_WAITOK);
1988 0 : rf->rf_base = base;
1989 0 : rf->rf_size = size;
1990 0 : rf->rf_dev = dev;
1991 :
1992 0 : SLIST_INSERT_HEAD(&rasops_framebuffers, rf, rf_list);
1993 0 : }
1994 :
1995 : int
1996 0 : rasops_check_framebuffer(paddr_t base)
1997 : {
1998 : struct rasops_framebuffer *rf;
1999 :
2000 0 : SLIST_FOREACH(rf, &rasops_framebuffers, rf_list) {
2001 0 : if (base >= rf->rf_base && base < rf->rf_base + rf->rf_size)
2002 0 : return 1;
2003 : }
2004 :
2005 0 : return 0;
2006 0 : }
|