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