rasops.c revision 1.37 1 /* $NetBSD: rasops.c,v 1.37 2001/09/18 18:15:53 wiz Exp $ */
2
3 /*-
4 * Copyright (c) 1999 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Andrew Doran.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the NetBSD
21 * Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
39 #include <sys/cdefs.h>
40 __KERNEL_RCSID(0, "$NetBSD: rasops.c,v 1.37 2001/09/18 18:15:53 wiz Exp $");
41
42 #include "opt_rasops.h"
43 #include "rasops_glue.h"
44
45 #include <sys/types.h>
46 #include <sys/param.h>
47 #include <sys/systm.h>
48 #include <sys/time.h>
49
50 #include <machine/bswap.h>
51 #include <machine/endian.h>
52
53 #include <dev/wscons/wsdisplayvar.h>
54 #include <dev/wscons/wsconsio.h>
55 #include <dev/wsfont/wsfont.h>
56 #include <dev/rasops/rasops.h>
57
58 #ifndef _KERNEL
59 #include <errno.h>
60 #endif
61
62 /* ANSI colormap (R,G,B). Upper 8 are high-intensity */
63 const u_char rasops_cmap[256*3] = {
64 0x00, 0x00, 0x00, /* black */
65 0x7f, 0x00, 0x00, /* red */
66 0x00, 0x7f, 0x00, /* green */
67 0x7f, 0x7f, 0x00, /* brown */
68 0x00, 0x00, 0x7f, /* blue */
69 0x7f, 0x00, 0x7f, /* magenta */
70 0x00, 0x7f, 0x7f, /* cyan */
71 0xc7, 0xc7, 0xc7, /* white - XXX too dim? */
72
73 0x7f, 0x7f, 0x7f, /* black */
74 0xff, 0x00, 0x00, /* red */
75 0x00, 0xff, 0x00, /* green */
76 0xff, 0xff, 0x00, /* brown */
77 0x00, 0x00, 0xff, /* blue */
78 0xff, 0x00, 0xff, /* magenta */
79 0x00, 0xff, 0xff, /* cyan */
80 0xff, 0xff, 0xff, /* white */
81
82 /*
83 * For the cursor, we need at least the last (255th)
84 * color to be white. Fill up white completely for
85 * simplicity.
86 */
87 #define _CMWHITE 0xff, 0xff, 0xff,
88 #define _CMWHITE16 _CMWHITE _CMWHITE _CMWHITE _CMWHITE \
89 _CMWHITE _CMWHITE _CMWHITE _CMWHITE \
90 _CMWHITE _CMWHITE _CMWHITE _CMWHITE \
91 _CMWHITE _CMWHITE _CMWHITE _CMWHITE
92 _CMWHITE16 _CMWHITE16 _CMWHITE16 _CMWHITE16 _CMWHITE16
93 _CMWHITE16 _CMWHITE16 _CMWHITE16 _CMWHITE16 _CMWHITE16
94 _CMWHITE16 _CMWHITE16 _CMWHITE16 _CMWHITE16 _CMWHITE16
95 #undef _CMWHITE16
96 #undef _CMWHITE
97 };
98
99 /* True if color is gray */
100 const u_char rasops_isgray[16] = {
101 1, 0, 0, 0,
102 0, 0, 0, 1,
103 1, 0, 0, 0,
104 0, 0, 0, 1
105 };
106
107 /* Generic functions */
108 static void rasops_copyrows __P((void *, int, int, int));
109 static int rasops_mapchar __P((void *, int, u_int *));
110 static void rasops_cursor __P((void *, int, int, int));
111 static int rasops_alloc_cattr __P((void *, int, int, int, long *));
112 static int rasops_alloc_mattr __P((void *, int, int, int, long *));
113 static void rasops_do_cursor __P((struct rasops_info *));
114 static void rasops_init_devcmap __P((struct rasops_info *));
115
116 /*
117 * Initialize a 'rasops_info' descriptor.
118 */
119 int
120 rasops_init(ri, wantrows, wantcols)
121 struct rasops_info *ri;
122 int wantrows, wantcols;
123 {
124
125 #ifdef _KERNEL
126 /* Select a font if the caller doesn't care */
127 if (ri->ri_font == NULL) {
128 int cookie;
129
130 wsfont_init();
131
132 /* Want 8 pixel wide, don't care about aestethics */
133 if ((cookie = wsfont_find(NULL, 8, 0, 0)) <= 0)
134 cookie = wsfont_find(NULL, 0, 0, 0);
135
136 if (cookie <= 0) {
137 printf("rasops_init: font table is empty\n");
138 return (-1);
139 }
140
141 if (wsfont_lock(cookie, &ri->ri_font,
142 WSDISPLAY_FONTORDER_L2R, WSDISPLAY_FONTORDER_L2R) <= 0) {
143 printf("rasops_init: couldn't lock font\n");
144 return (-1);
145 }
146
147 ri->ri_wsfcookie = cookie;
148 }
149 #endif
150
151 /* This should never happen in reality... */
152 #ifdef DEBUG
153 if ((long)ri->ri_bits & 3) {
154 printf("rasops_init: bits not aligned on 32-bit boundary\n");
155 return (-1);
156 }
157
158 if ((int)ri->ri_stride & 3) {
159 printf("rasops_init: stride not aligned on 32-bit boundary\n");
160 return (-1);
161 }
162 #endif
163
164 if (rasops_reconfig(ri, wantrows, wantcols))
165 return (-1);
166
167 rasops_init_devcmap(ri);
168 return (0);
169 }
170
171 /*
172 * Reconfigure (because parameters have changed in some way).
173 */
174 int
175 rasops_reconfig(ri, wantrows, wantcols)
176 struct rasops_info *ri;
177 int wantrows, wantcols;
178 {
179 int bpp, s;
180
181 s = splhigh();
182
183 if (ri->ri_font->fontwidth > 32 || ri->ri_font->fontwidth < 4)
184 panic("rasops_init: fontwidth assumptions botched!\n");
185
186 /* Need this to frob the setup below */
187 bpp = (ri->ri_depth == 15 ? 16 : ri->ri_depth);
188
189 if ((ri->ri_flg & RI_CFGDONE) != 0)
190 ri->ri_bits = ri->ri_origbits;
191
192 /* Don't care if the caller wants a hideously small console */
193 if (wantrows < 10)
194 wantrows = 10;
195
196 if (wantcols < 20)
197 wantcols = 20;
198
199 /* Now constrain what they get */
200 ri->ri_emuwidth = ri->ri_font->fontwidth * wantcols;
201 ri->ri_emuheight = ri->ri_font->fontheight * wantrows;
202
203 if (ri->ri_emuwidth > ri->ri_width)
204 ri->ri_emuwidth = ri->ri_width;
205
206 if (ri->ri_emuheight > ri->ri_height)
207 ri->ri_emuheight = ri->ri_height;
208
209 /* Reduce width until aligned on a 32-bit boundary */
210 while ((ri->ri_emuwidth * bpp & 31) != 0)
211 ri->ri_emuwidth--;
212
213 ri->ri_cols = ri->ri_emuwidth / ri->ri_font->fontwidth;
214 ri->ri_rows = ri->ri_emuheight / ri->ri_font->fontheight;
215 ri->ri_emustride = ri->ri_emuwidth * bpp >> 3;
216 ri->ri_delta = ri->ri_stride - ri->ri_emustride;
217 ri->ri_ccol = 0;
218 ri->ri_crow = 0;
219 ri->ri_pelbytes = bpp >> 3;
220
221 ri->ri_xscale = (ri->ri_font->fontwidth * bpp) >> 3;
222 ri->ri_yscale = ri->ri_font->fontheight * ri->ri_stride;
223 ri->ri_fontscale = ri->ri_font->fontheight * ri->ri_font->stride;
224
225 #ifdef DEBUG
226 if ((ri->ri_delta & 3) != 0)
227 panic("rasops_init: ri_delta not aligned on 32-bit boundary");
228 #endif
229 /* Clear the entire display */
230 if ((ri->ri_flg & RI_CLEAR) != 0)
231 memset(ri->ri_bits, 0, ri->ri_stride * ri->ri_height);
232
233 /* Now centre our window if needs be */
234 ri->ri_origbits = ri->ri_bits;
235
236 if ((ri->ri_flg & RI_CENTER) != 0) {
237 ri->ri_bits += (((ri->ri_width * bpp >> 3) -
238 ri->ri_emustride) >> 1) & ~3;
239 ri->ri_bits += ((ri->ri_height - ri->ri_emuheight) >> 1) *
240 ri->ri_stride;
241
242 ri->ri_yorigin = (int)(ri->ri_bits - ri->ri_origbits)
243 / ri->ri_stride;
244 ri->ri_xorigin = (((int)(ri->ri_bits - ri->ri_origbits)
245 % ri->ri_stride) * 8 / bpp);
246 } else
247 ri->ri_xorigin = ri->ri_yorigin = 0;
248
249 /*
250 * Fill in defaults for operations set. XXX this nukes private
251 * routines used by accelerated fb drivers.
252 */
253 ri->ri_ops.mapchar = rasops_mapchar;
254 ri->ri_ops.copyrows = rasops_copyrows;
255 ri->ri_ops.copycols = rasops_copycols;
256 ri->ri_ops.erasecols = rasops_erasecols;
257 ri->ri_ops.eraserows = rasops_eraserows;
258 ri->ri_ops.cursor = rasops_cursor;
259 ri->ri_do_cursor = rasops_do_cursor;
260
261 if (ri->ri_depth < 8 || (ri->ri_flg & RI_FORCEMONO) != 0) {
262 ri->ri_ops.alloc_attr = rasops_alloc_mattr;
263 ri->ri_caps = WSSCREEN_UNDERLINE | WSSCREEN_REVERSE;
264 } else {
265 ri->ri_ops.alloc_attr = rasops_alloc_cattr;
266 ri->ri_caps = WSSCREEN_UNDERLINE | WSSCREEN_HILIT |
267 WSSCREEN_WSCOLORS | WSSCREEN_REVERSE;
268 }
269
270 switch (ri->ri_depth) {
271 #if NRASOPS1 > 0
272 case 1:
273 rasops1_init(ri);
274 break;
275 #endif
276 #if NRASOPS2 > 0
277 case 2:
278 rasops2_init(ri);
279 break;
280 #endif
281 #if NRASOPS4 > 0
282 case 4:
283 rasops4_init(ri);
284 break;
285 #endif
286 #if NRASOPS8 > 0
287 case 8:
288 rasops8_init(ri);
289 break;
290 #endif
291 #if NRASOPS15 > 0 || NRASOPS16 > 0
292 case 15:
293 case 16:
294 rasops15_init(ri);
295 break;
296 #endif
297 #if NRASOPS24 > 0
298 case 24:
299 rasops24_init(ri);
300 break;
301 #endif
302 #if NRASOPS32 > 0
303 case 32:
304 rasops32_init(ri);
305 break;
306 #endif
307 default:
308 ri->ri_flg &= ~RI_CFGDONE;
309 splx(s);
310 return (-1);
311 }
312
313 ri->ri_flg |= RI_CFGDONE;
314 splx(s);
315 return (0);
316 }
317
318 /*
319 * Map a character.
320 */
321 static int
322 rasops_mapchar(cookie, c, cp)
323 void *cookie;
324 int c;
325 u_int *cp;
326 {
327 struct rasops_info *ri;
328
329 ri = (struct rasops_info *)cookie;
330
331 #ifdef DIAGNOSTIC
332 if (ri->ri_font == NULL)
333 panic("rasops_mapchar: no font selected\n");
334 #endif
335 if (ri->ri_font->encoding != WSDISPLAY_FONTENC_ISO) {
336
337 if ( (c = wsfont_map_unichar(ri->ri_font, c)) < 0) {
338
339 *cp = ' ';
340 return (0);
341
342 }
343 }
344
345
346 if (c < ri->ri_font->firstchar) {
347 *cp = ' ';
348 return (0);
349 }
350
351 if (c - ri->ri_font->firstchar >= ri->ri_font->numchars) {
352 *cp = ' ';
353 return (0);
354 }
355
356 *cp = c;
357 return (5);
358 }
359
360 /*
361 * Allocate a color attribute.
362 */
363 static int
364 rasops_alloc_cattr(cookie, fg, bg, flg, attr)
365 void *cookie;
366 int fg, bg, flg;
367 long *attr;
368 {
369 int swap;
370
371 #ifdef RASOPS_CLIPPING
372 fg &= 7;
373 bg &= 7;
374 #endif
375 if ((flg & WSATTR_BLINK) != 0)
376 return (EINVAL);
377
378 if ((flg & WSATTR_WSCOLORS) == 0) {
379 fg = WSCOL_WHITE;
380 bg = WSCOL_BLACK;
381 }
382
383 if ((flg & WSATTR_REVERSE) != 0) {
384 swap = fg;
385 fg = bg;
386 bg = swap;
387 }
388
389 if ((flg & WSATTR_HILIT) != 0)
390 fg += 8;
391
392 flg = ((flg & WSATTR_UNDERLINE) ? 1 : 0);
393
394 if (rasops_isgray[fg])
395 flg |= 2;
396
397 if (rasops_isgray[bg])
398 flg |= 4;
399
400 *attr = (bg << 16) | (fg << 24) | flg;
401 return (0);
402 }
403
404 /*
405 * Allocate a mono attribute.
406 */
407 static int
408 rasops_alloc_mattr(cookie, fg, bg, flg, attr)
409 void *cookie;
410 int fg, bg, flg;
411 long *attr;
412 {
413 int swap;
414
415 if ((flg & (WSATTR_BLINK | WSATTR_HILIT | WSATTR_WSCOLORS)) != 0)
416 return (EINVAL);
417
418 fg = 1;
419 bg = 0;
420
421 if ((flg & WSATTR_REVERSE) != 0) {
422 swap = fg;
423 fg = bg;
424 bg = swap;
425 }
426
427 *attr = (bg << 16) | (fg << 24) | ((flg & WSATTR_UNDERLINE) ? 7 : 6);
428 return (0);
429 }
430
431 /*
432 * Copy rows.
433 */
434 static void
435 rasops_copyrows(cookie, src, dst, num)
436 void *cookie;
437 int src, dst, num;
438 {
439 int32_t *sp, *dp, *srp, *drp;
440 struct rasops_info *ri;
441 int n8, n1, cnt, delta;
442
443 ri = (struct rasops_info *)cookie;
444
445 #ifdef RASOPS_CLIPPING
446 if (dst == src)
447 return;
448
449 if (src < 0) {
450 num += src;
451 src = 0;
452 }
453
454 if ((src + num) > ri->ri_rows)
455 num = ri->ri_rows - src;
456
457 if (dst < 0) {
458 num += dst;
459 dst = 0;
460 }
461
462 if ((dst + num) > ri->ri_rows)
463 num = ri->ri_rows - dst;
464
465 if (num <= 0)
466 return;
467 #endif
468
469 num *= ri->ri_font->fontheight;
470 n8 = ri->ri_emustride >> 5;
471 n1 = (ri->ri_emustride >> 2) & 7;
472
473 if (dst < src) {
474 srp = (int32_t *)(ri->ri_bits + src * ri->ri_yscale);
475 drp = (int32_t *)(ri->ri_bits + dst * ri->ri_yscale);
476 delta = ri->ri_stride;
477 } else {
478 src = ri->ri_font->fontheight * src + num - 1;
479 dst = ri->ri_font->fontheight * dst + num - 1;
480 srp = (int32_t *)(ri->ri_bits + src * ri->ri_stride);
481 drp = (int32_t *)(ri->ri_bits + dst * ri->ri_stride);
482 delta = -ri->ri_stride;
483 }
484
485 while (num--) {
486 dp = drp;
487 sp = srp;
488 DELTA(drp, delta, int32_t *);
489 DELTA(srp, delta, int32_t *);
490
491 for (cnt = n8; cnt; cnt--) {
492 dp[0] = sp[0];
493 dp[1] = sp[1];
494 dp[2] = sp[2];
495 dp[3] = sp[3];
496 dp[4] = sp[4];
497 dp[5] = sp[5];
498 dp[6] = sp[6];
499 dp[7] = sp[7];
500 dp += 8;
501 sp += 8;
502 }
503
504 for (cnt = n1; cnt; cnt--)
505 *dp++ = *sp++;
506 }
507 }
508
509 /*
510 * Copy columns. This is slow, and hard to optimize due to alignment,
511 * and the fact that we have to copy both left->right and right->left.
512 * We simply cop-out here and use bcopy(), since it handles all of
513 * these cases anyway.
514 */
515 void
516 rasops_copycols(cookie, row, src, dst, num)
517 void *cookie;
518 int row, src, dst, num;
519 {
520 struct rasops_info *ri;
521 u_char *sp, *dp;
522 int height;
523
524 ri = (struct rasops_info *)cookie;
525
526 #ifdef RASOPS_CLIPPING
527 if (dst == src)
528 return;
529
530 /* Catches < 0 case too */
531 if ((unsigned)row >= (unsigned)ri->ri_rows)
532 return;
533
534 if (src < 0) {
535 num += src;
536 src = 0;
537 }
538
539 if ((src + num) > ri->ri_cols)
540 num = ri->ri_cols - src;
541
542 if (dst < 0) {
543 num += dst;
544 dst = 0;
545 }
546
547 if ((dst + num) > ri->ri_cols)
548 num = ri->ri_cols - dst;
549
550 if (num <= 0)
551 return;
552 #endif
553
554 num *= ri->ri_xscale;
555 row *= ri->ri_yscale;
556 height = ri->ri_font->fontheight;
557
558 sp = ri->ri_bits + row + src * ri->ri_xscale;
559 dp = ri->ri_bits + row + dst * ri->ri_xscale;
560
561 while (height--) {
562 bcopy(sp, dp, num);
563 dp += ri->ri_stride;
564 sp += ri->ri_stride;
565 }
566 }
567
568 /*
569 * Turn cursor off/on.
570 */
571 static void
572 rasops_cursor(cookie, on, row, col)
573 void *cookie;
574 int on, row, col;
575 {
576 struct rasops_info *ri;
577
578 ri = (struct rasops_info *)cookie;
579
580 /* Turn old cursor off */
581 if ((ri->ri_flg & RI_CURSOR) != 0)
582 #ifdef RASOPS_CLIPPING
583 if ((ri->ri_flg & RI_CURSORCLIP) == 0)
584 #endif
585 ri->ri_do_cursor(ri);
586
587 /* Select new cursor */
588 #ifdef RASOPS_CLIPPING
589 ri->ri_flg &= ~RI_CURSORCLIP;
590
591 if (row < 0 || row >= ri->ri_rows)
592 ri->ri_flg |= RI_CURSORCLIP;
593 else if (col < 0 || col >= ri->ri_cols)
594 ri->ri_flg |= RI_CURSORCLIP;
595 #endif
596 ri->ri_crow = row;
597 ri->ri_ccol = col;
598
599 if (on) {
600 ri->ri_flg |= RI_CURSOR;
601 #ifdef RASOPS_CLIPPING
602 if ((ri->ri_flg & RI_CURSORCLIP) == 0)
603 #endif
604 ri->ri_do_cursor(ri);
605 } else
606 ri->ri_flg &= ~RI_CURSOR;
607 }
608
609 /*
610 * Make the device colormap
611 */
612 static void
613 rasops_init_devcmap(ri)
614 struct rasops_info *ri;
615 {
616 const u_char *p;
617 int i, c;
618
619 switch (ri->ri_depth) {
620 case 1:
621 ri->ri_devcmap[0] = 0;
622 for (i = 1; i < 16; i++)
623 ri->ri_devcmap[i] = -1;
624 return;
625
626 case 2:
627 for (i = 1; i < 15; i++)
628 ri->ri_devcmap[i] = 0xaaaaaaaa;
629
630 ri->ri_devcmap[0] = 0;
631 ri->ri_devcmap[8] = 0x55555555;
632 ri->ri_devcmap[15] = -1;
633 return;
634
635 case 8:
636 for (i = 0; i < 16; i++)
637 ri->ri_devcmap[i] = i | (i<<8) | (i<<16) | (i<<24);
638 return;
639 }
640
641 p = rasops_cmap;
642
643 for (i = 0; i < 16; i++) {
644 if (ri->ri_rnum <= 8)
645 c = (*p >> (8 - ri->ri_rnum)) << ri->ri_rpos;
646 else
647 c = (*p << (ri->ri_rnum - 8)) << ri->ri_rpos;
648 p++;
649
650 if (ri->ri_gnum <= 8)
651 c |= (*p >> (8 - ri->ri_gnum)) << ri->ri_gpos;
652 else
653 c |= (*p << (ri->ri_gnum - 8)) << ri->ri_gpos;
654 p++;
655
656 if (ri->ri_bnum <= 8)
657 c |= (*p >> (8 - ri->ri_bnum)) << ri->ri_bpos;
658 else
659 c |= (*p << (ri->ri_bnum - 8)) << ri->ri_bpos;
660 p++;
661
662 /* Fill the word for generic routines, which want this */
663 if (ri->ri_depth == 24)
664 c = c | ((c & 0xff) << 24);
665 else if (ri->ri_depth <= 16)
666 c = c | (c << 16);
667
668 /* 24bpp does bswap on the fly. {32,16,15}bpp do it here. */
669 if ((ri->ri_flg & RI_BSWAP) == 0)
670 ri->ri_devcmap[i] = c;
671 else if (ri->ri_depth == 32)
672 ri->ri_devcmap[i] = bswap32(c);
673 else if (ri->ri_depth == 16 || ri->ri_depth == 15)
674 ri->ri_devcmap[i] = bswap16(c);
675 else
676 ri->ri_devcmap[i] = c;
677 }
678 }
679
680 /*
681 * Unpack a rasops attribute
682 */
683 void
684 rasops_unpack_attr(attr, fg, bg, underline)
685 long attr;
686 int *fg, *bg, *underline;
687 {
688
689 *fg = ((u_int)attr >> 24) & 0xf;
690 *bg = ((u_int)attr >> 16) & 0xf;
691 if (underline != NULL)
692 *underline = (u_int)attr & 1;
693 }
694
695 /*
696 * Erase rows. This isn't static, since 24-bpp uses it in special cases.
697 */
698 void
699 rasops_eraserows(cookie, row, num, attr)
700 void *cookie;
701 int row, num;
702 long attr;
703 {
704 struct rasops_info *ri;
705 int np, nw, cnt, delta;
706 int32_t *dp, clr;
707
708 ri = (struct rasops_info *)cookie;
709
710 #ifdef RASOPS_CLIPPING
711 if (row < 0) {
712 num += row;
713 row = 0;
714 }
715
716 if ((row + num) > ri->ri_rows)
717 num = ri->ri_rows - row;
718
719 if (num <= 0)
720 return;
721 #endif
722
723 clr = ri->ri_devcmap[(attr >> 16) & 0xf];
724
725 /*
726 * XXX The wsdisplay_emulops interface seems a little deficient in
727 * that there is no way to clear the *entire* screen. We provide a
728 * workaround here: if the entire console area is being cleared, and
729 * the RI_FULLCLEAR flag is set, clear the entire display.
730 */
731 if (num == ri->ri_rows && (ri->ri_flg & RI_FULLCLEAR) != 0) {
732 np = ri->ri_stride >> 5;
733 nw = (ri->ri_stride >> 2) & 7;
734 num = ri->ri_height;
735 dp = (int32_t *)ri->ri_origbits;
736 delta = 0;
737 } else {
738 np = ri->ri_emustride >> 5;
739 nw = (ri->ri_emustride >> 2) & 7;
740 num *= ri->ri_font->fontheight;
741 dp = (int32_t *)(ri->ri_bits + row * ri->ri_yscale);
742 delta = ri->ri_delta;
743 }
744
745 while (num--) {
746 for (cnt = np; cnt; cnt--) {
747 dp[0] = clr;
748 dp[1] = clr;
749 dp[2] = clr;
750 dp[3] = clr;
751 dp[4] = clr;
752 dp[5] = clr;
753 dp[6] = clr;
754 dp[7] = clr;
755 dp += 8;
756 }
757
758 for (cnt = nw; cnt; cnt--) {
759 *(int32_t *)dp = clr;
760 DELTA(dp, 4, int32_t *);
761 }
762
763 DELTA(dp, delta, int32_t *);
764 }
765 }
766
767 /*
768 * Actually turn the cursor on or off. This does the dirty work for
769 * rasops_cursor().
770 */
771 static void
772 rasops_do_cursor(ri)
773 struct rasops_info *ri;
774 {
775 int full1, height, cnt, slop1, slop2, row, col;
776 u_char *dp, *rp;
777
778 row = ri->ri_crow;
779 col = ri->ri_ccol;
780
781 rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
782 height = ri->ri_font->fontheight;
783 slop1 = (4 - ((long)rp & 3)) & 3;
784
785 if (slop1 > ri->ri_xscale)
786 slop1 = ri->ri_xscale;
787
788 slop2 = (ri->ri_xscale - slop1) & 3;
789 full1 = (ri->ri_xscale - slop1 - slop2) >> 2;
790
791 if ((slop1 | slop2) == 0) {
792 /* A common case */
793 while (height--) {
794 dp = rp;
795 rp += ri->ri_stride;
796
797 for (cnt = full1; cnt; cnt--) {
798 *(int32_t *)dp ^= ~0;
799 dp += 4;
800 }
801 }
802 } else {
803 /* XXX this is stupid.. use masks instead */
804 while (height--) {
805 dp = rp;
806 rp += ri->ri_stride;
807
808 if (slop1 & 1)
809 *dp++ ^= ~0;
810
811 if (slop1 & 2) {
812 *(int16_t *)dp ^= ~0;
813 dp += 2;
814 }
815
816 for (cnt = full1; cnt; cnt--) {
817 *(int32_t *)dp ^= ~0;
818 dp += 4;
819 }
820
821 if (slop2 & 1)
822 *dp++ ^= ~0;
823
824 if (slop2 & 2)
825 *(int16_t *)dp ^= ~0;
826 }
827 }
828 }
829
830 /*
831 * Erase columns.
832 */
833 void
834 rasops_erasecols(cookie, row, col, num, attr)
835 void *cookie;
836 int row, col, num;
837 long attr;
838 {
839 int n8, height, cnt, slop1, slop2, clr;
840 struct rasops_info *ri;
841 int32_t *rp, *dp;
842
843 ri = (struct rasops_info *)cookie;
844
845 #ifdef RASOPS_CLIPPING
846 if ((unsigned)row >= (unsigned)ri->ri_rows)
847 return;
848
849 if (col < 0) {
850 num += col;
851 col = 0;
852 }
853
854 if ((col + num) > ri->ri_cols)
855 num = ri->ri_cols - col;
856
857 if (num <= 0)
858 return;
859 #endif
860
861 num = num * ri->ri_xscale;
862 rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
863 height = ri->ri_font->fontheight;
864 clr = ri->ri_devcmap[(attr >> 16) & 0xf];
865
866 /* Don't bother using the full loop for <= 32 pels */
867 if (num <= 32) {
868 if (((num | ri->ri_xscale) & 3) == 0) {
869 /* Word aligned blt */
870 num >>= 2;
871
872 while (height--) {
873 dp = rp;
874 DELTA(rp, ri->ri_stride, int32_t *);
875
876 for (cnt = num; cnt; cnt--)
877 *dp++ = clr;
878 }
879 } else if (((num | ri->ri_xscale) & 1) == 0) {
880 /*
881 * Halfword aligned blt. This is needed so the
882 * 15/16 bit ops can use this function.
883 */
884 num >>= 1;
885
886 while (height--) {
887 dp = rp;
888 DELTA(rp, ri->ri_stride, int32_t *);
889
890 for (cnt = num; cnt; cnt--) {
891 *(int16_t *)dp = clr;
892 DELTA(dp, 2, int32_t *);
893 }
894 }
895 } else {
896 while (height--) {
897 dp = rp;
898 DELTA(rp, ri->ri_stride, int32_t *);
899
900 for (cnt = num; cnt; cnt--) {
901 *(u_char *)dp = clr;
902 DELTA(dp, 1, int32_t *);
903 }
904 }
905 }
906
907 return;
908 }
909
910 slop1 = (4 - ((long)rp & 3)) & 3;
911 slop2 = (num - slop1) & 3;
912 num -= slop1 + slop2;
913 n8 = num >> 5;
914 num = (num >> 2) & 7;
915
916 while (height--) {
917 dp = rp;
918 DELTA(rp, ri->ri_stride, int32_t *);
919
920 /* Align span to 4 bytes */
921 if (slop1 & 1) {
922 *(u_char *)dp = clr;
923 DELTA(dp, 1, int32_t *);
924 }
925
926 if (slop1 & 2) {
927 *(int16_t *)dp = clr;
928 DELTA(dp, 2, int32_t *);
929 }
930
931 /* Write 32 bytes per loop */
932 for (cnt = n8; cnt; cnt--) {
933 dp[0] = clr;
934 dp[1] = clr;
935 dp[2] = clr;
936 dp[3] = clr;
937 dp[4] = clr;
938 dp[5] = clr;
939 dp[6] = clr;
940 dp[7] = clr;
941 dp += 8;
942 }
943
944 /* Write 4 bytes per loop */
945 for (cnt = num; cnt; cnt--)
946 *dp++ = clr;
947
948 /* Write unaligned trailing slop */
949 if (slop2 & 1) {
950 *(u_char *)dp = clr;
951 DELTA(dp, 1, int32_t *);
952 }
953
954 if (slop2 & 2)
955 *(int16_t *)dp = clr;
956 }
957 }
958