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