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