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