rasops24.c revision 1.6 1 /* $NetBSD: rasops24.c,v 1.6 1999/05/18 21:51:59 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 "opt_rasops.h"
40 #include <sys/cdefs.h>
41 __KERNEL_RCSID(0, "$NetBSD: rasops24.c,v 1.6 1999/05/18 21:51:59 ad Exp $");
42
43 #include <sys/types.h>
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/time.h>
47
48 #include <machine/endian.h>
49 #include <machine/bswap.h>
50
51 #include <dev/wscons/wsdisplayvar.h>
52 #include <dev/wscons/wsconsio.h>
53 #include <dev/rasops/rasops.h>
54
55 static void rasops24_putchar __P((void *, int, int, u_int, long attr));
56 static void rasops24_putchar8 __P((void *, int, int, u_int, long attr));
57 static void rasops24_putchar12 __P((void *, int, int, u_int, long attr));
58 static void rasops24_putchar16 __P((void *, int, int, u_int, long attr));
59 static void rasops24_erasecols __P((void *, int, int, int, long));
60 static void rasops24_eraserows __P((void *, int, int, long));
61 static void rasops24_makestamp __P((struct rasops_info *, long));
62
63 void rasops24_init __P((struct rasops_info *ri));
64
65 /*
66 * 4x1 stamp for optimized character blitting
67 */
68 static int32_t stamp[64];
69 static long stamp_attr;
70 static int stamp_mutex; /* XXX see note in readme */
71
72 /*
73 * XXX this confuses the hell out of gcc2 (not egcs) which always insists
74 * that the shift count is negative.
75 *
76 * offset = STAMP_SHIFT(fontbits, nibble #) & STAMP_MASK
77 * destination int32_t[0] = STAMP_READ(offset)
78 * destination int32_t[1] = STAMP_READ(offset + 4)
79 * destination int32_t[2] = STAMP_READ(offset + 8)
80 */
81 #define STAMP_SHIFT(fb,n) ((n*4-4) >= 0 ? (fb)>>(n*4-4):(fb)<<-(n*4-4))
82 #define STAMP_MASK (15 << 4)
83 #define STAMP_READ(o) (*(int32_t *)((caddr_t)stamp + (o)))
84
85
86 /*
87 * Initalize rasops_info struct for this colordepth.
88 */
89 void
90 rasops24_init(ri)
91 struct rasops_info *ri;
92 {
93
94 switch (ri->ri_font->fontwidth) {
95 case 8:
96 ri->ri_ops.putchar = rasops24_putchar8;
97 break;
98
99 case 12:
100 ri->ri_ops.putchar = rasops24_putchar12;
101 break;
102
103 case 16:
104 ri->ri_ops.putchar = rasops24_putchar16;
105 break;
106
107 default:
108 ri->ri_ops.putchar = rasops24_putchar;
109 break;
110 }
111
112 if (ri->ri_rnum == 0) {
113 ri->ri_rnum = 8;
114 ri->ri_rpos = 0;
115 ri->ri_gnum = 8;
116 ri->ri_gpos = 8;
117 ri->ri_bnum = 8;
118 ri->ri_bpos = 16;
119 }
120
121 ri->ri_ops.erasecols = rasops24_erasecols;
122 ri->ri_ops.eraserows = rasops24_eraserows;
123 }
124
125
126 /*
127 * Recompute the blitting stamp.
128 */
129 static void
130 rasops24_makestamp(ri, attr)
131 struct rasops_info *ri;
132 long attr;
133 {
134 u_int32_t fg, bg, c1, c2, c3, c4;
135 int i;
136
137 fg = ri->ri_devcmap[((u_int)attr >> 24) & 15] & 0xffffff;
138 bg = ri->ri_devcmap[((u_int)attr >> 16) & 15] & 0xffffff;
139 stamp_attr = attr;
140
141 for (i = 0; i < 64; i += 4) {
142 #if BYTE_ORDER == LITTLE_ENDIAN
143 c1 = (i & 32 ? fg : bg);
144 c2 = (i & 16 ? fg : bg);
145 c3 = (i & 8 ? fg : bg);
146 c4 = (i & 4 ? fg : bg);
147 #else
148 c1 = (i & 8 ? fg : bg);
149 c2 = (i & 4 ? fg : bg);
150 c3 = (i & 16 ? fg : bg);
151 c4 = (i & 32 ? fg : bg);
152 #endif
153 stamp[i+0] = (c1 << 8) | (c2 >> 16);
154 stamp[i+1] = (c2 << 16) | (c3 >> 8);
155 stamp[i+2] = (c3 << 24) | c4;
156
157 #if BYTE_ORDER == LITTLE_ENDIAN
158 if (!ri->ri_swab) {
159 #else
160 if (ri->ri_swab) {
161 #endif
162 stamp[i+0] = bswap32(stamp[i+0]);
163 stamp[i+1] = bswap32(stamp[i+1]);
164 stamp[i+2] = bswap32(stamp[i+2]);
165 }
166 }
167 }
168
169
170 /*
171 * Put a single character. This is the generic version.
172 * XXX this bites - we should use masks.
173 */
174 static void
175 rasops24_putchar(cookie, row, col, uc, attr)
176 void *cookie;
177 int row, col;
178 u_int uc;
179 long attr;
180 {
181 struct rasops_info *ri;
182 int fb, width, height, cnt, clr[2];
183 u_char *dp, *rp, *fr;
184
185 ri = (struct rasops_info *)cookie;
186
187 #ifdef RASOPS_CLIPPING
188 /* Catches 'row < 0' case too */
189 if ((unsigned)row >= (unsigned)ri->ri_rows)
190 return;
191
192 if ((unsigned)col >= (unsigned)ri->ri_cols)
193 return;
194 #endif
195
196 rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
197 height = ri->ri_font->fontheight;
198 width = ri->ri_font->fontwidth;
199
200 clr[1] = ri->ri_devcmap[((u_int)attr >> 24) & 15];
201 clr[0] = ri->ri_devcmap[((u_int)attr >> 16) & 15];
202
203 if (uc == ' ') {
204 while (height--) {
205 dp = rp;
206 rp += ri->ri_stride;
207
208 for (cnt = width; cnt; cnt--) {
209 *dp++ = clr[0] >> 16;
210 *dp++ = clr[0] >> 8;
211 *dp++ = clr[0];
212 }
213 }
214 } else {
215 uc -= ri->ri_font->firstchar;
216 fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
217
218 while (height--) {
219 dp = rp;
220 fb = fr[3] | (fr[2] << 8) | (fr[1] << 16) | (fr[0] << 24);
221 fr += ri->ri_font->stride;
222 rp += ri->ri_stride;
223
224 for (cnt = width; cnt; cnt--, fb <<= 1) {
225 if ((fb >> 31) & 1) {
226 *dp++ = clr[1] >> 16;
227 *dp++ = clr[1] >> 8;
228 *dp++ = clr[1];
229 } else {
230 *dp++ = clr[0] >> 16;
231 *dp++ = clr[0] >> 8;
232 *dp++ = clr[0];
233 }
234 }
235 }
236 }
237
238 /* Do underline */
239 if (attr & 1) {
240 rp -= ri->ri_stride << 1;
241
242 while (width--) {
243 *rp++ = clr[1] >> 16;
244 *rp++ = clr[1] >> 8;
245 *rp++ = clr[1];
246 }
247 }
248 }
249
250
251 /*
252 * Put a single character. This is for 8-pixel wide fonts.
253 */
254 static void
255 rasops24_putchar8(cookie, row, col, uc, attr)
256 void *cookie;
257 int row, col;
258 u_int uc;
259 long attr;
260 {
261 struct rasops_info *ri;
262 int height, so, fs;
263 int32_t *rp;
264 u_char *fr;
265
266 /* Can't risk remaking the stamp if it's already in use */
267 if (stamp_mutex++) {
268 stamp_mutex--;
269 rasops24_putchar(cookie, row, col, uc, attr);
270 return;
271 }
272
273 ri = (struct rasops_info *)cookie;
274
275 #ifdef RASOPS_CLIPPING
276 if ((unsigned)row >= (unsigned)ri->ri_rows) {
277 stamp_mutex--;
278 return;
279 }
280
281 if ((unsigned)col >= (unsigned)ri->ri_cols) {
282 stamp_mutex--;
283 return;
284 }
285 #endif
286
287 /* Recompute stamp? */
288 if (attr != stamp_attr)
289 rasops24_makestamp(ri, attr);
290
291 rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
292 height = ri->ri_font->fontheight;
293
294 if (uc == (u_int)-1) {
295 while (height--) {
296 rp[0] = stamp[0];
297 rp[1] = stamp[0];
298 rp[2] = stamp[0];
299 rp[3] = stamp[0];
300 rp[4] = stamp[0];
301 rp[5] = stamp[0];
302 DELTA(rp, ri->ri_stride, int32_t *);
303 }
304 } else {
305 uc -= ri->ri_font->firstchar;
306 fr = (u_char *)ri->ri_font->data + uc*ri->ri_fontscale;
307 fs = ri->ri_font->stride;
308
309 while (height--) {
310 so = STAMP_SHIFT(fr[0], 1) & STAMP_MASK;
311 rp[0] = STAMP_READ(so);
312 rp[1] = STAMP_READ(so + 4);
313 rp[2] = STAMP_READ(so + 8);
314
315 so = STAMP_SHIFT(fr[0], 0) & STAMP_MASK;
316 rp[3] = STAMP_READ(so);
317 rp[4] = STAMP_READ(so + 4);
318 rp[5] = STAMP_READ(so + 8);
319
320 fr += fs;
321 DELTA(rp, ri->ri_stride, int32_t *);
322 }
323 }
324
325 /* Do underline */
326 if (attr & 1) {
327 DELTA(rp, -(ri->ri_stride << 1), int32_t *);
328 rp[0] = STAMP_READ(30);
329 rp[1] = STAMP_READ(30);
330 rp[2] = STAMP_READ(30);
331 rp[3] = STAMP_READ(30);
332 rp[4] = STAMP_READ(30);
333 rp[5] = STAMP_READ(30);
334 }
335
336 stamp_mutex--;
337 }
338
339
340 /*
341 * Put a single character. This is for 12-pixel wide fonts.
342 */
343 static void
344 rasops24_putchar12(cookie, row, col, uc, attr)
345 void *cookie;
346 int row, col;
347 u_int uc;
348 long attr;
349 {
350 struct rasops_info *ri;
351 int height, so, fs;
352 int32_t *rp;
353 u_char *fr;
354
355 /* Can't risk remaking the stamp if it's already in use */
356 if (stamp_mutex++) {
357 stamp_mutex--;
358 rasops24_putchar(cookie, row, col, uc, attr);
359 return;
360 }
361
362 ri = (struct rasops_info *)cookie;
363
364 #ifdef RASOPS_CLIPPING
365 if ((unsigned)row >= (unsigned)ri->ri_rows) {
366 stamp_mutex--;
367 return;
368 }
369
370 if ((unsigned)col >= (unsigned)ri->ri_cols) {
371 stamp_mutex--;
372 return;
373 }
374 #endif
375
376 /* Recompute stamp? */
377 if (attr != stamp_attr)
378 rasops24_makestamp(ri, attr);
379
380 rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
381 height = ri->ri_font->fontheight;
382
383 if (uc == (u_int)-1) {
384 while (height--) {
385 rp[0] = stamp[0];
386 rp[1] = stamp[0];
387 rp[2] = stamp[0];
388 rp[3] = stamp[0];
389 rp[4] = stamp[0];
390 rp[5] = stamp[0];
391 rp[6] = stamp[0];
392 rp[7] = stamp[0];
393 rp[8] = stamp[0];
394 DELTA(rp, ri->ri_stride, int32_t *);
395 }
396 } else {
397 uc -= ri->ri_font->firstchar;
398 fr = (u_char *)ri->ri_font->data + uc*ri->ri_fontscale;
399 fs = ri->ri_font->stride;
400
401 while (height--) {
402 so = STAMP_SHIFT(fr[0], 1) & STAMP_MASK;
403 rp[0] = STAMP_READ(so);
404 rp[1] = STAMP_READ(so + 4);
405 rp[2] = STAMP_READ(so + 8);
406
407 so = STAMP_SHIFT(fr[0], 0) & STAMP_MASK;
408 rp[3] = STAMP_READ(so);
409 rp[4] = STAMP_READ(so + 4);
410 rp[5] = STAMP_READ(so + 8);
411
412 so = STAMP_SHIFT(fr[1], 1) & STAMP_MASK;
413 rp[6] = STAMP_READ(so);
414 rp[7] = STAMP_READ(so + 4);
415 rp[8] = STAMP_READ(so + 8);
416
417 fr += fs;
418 DELTA(rp, ri->ri_stride, int32_t *);
419 }
420 }
421
422 /* Do underline */
423 if (attr & 1) {
424 DELTA(rp, -(ri->ri_stride << 1), int32_t *);
425 rp[0] = STAMP_READ(30);
426 rp[1] = STAMP_READ(30);
427 rp[2] = STAMP_READ(30);
428 rp[3] = STAMP_READ(30);
429 rp[4] = STAMP_READ(30);
430 rp[5] = STAMP_READ(30);
431 rp[6] = STAMP_READ(30);
432 rp[7] = STAMP_READ(30);
433 rp[8] = STAMP_READ(30);
434 }
435
436 stamp_mutex--;
437 }
438
439
440 /*
441 * Put a single character. This is for 16-pixel wide fonts.
442 */
443 static void
444 rasops24_putchar16(cookie, row, col, uc, attr)
445 void *cookie;
446 int row, col;
447 u_int uc;
448 long attr;
449 {
450 struct rasops_info *ri;
451 int height, so, fs;
452 int32_t *rp;
453 u_char *fr;
454
455 /* Can't risk remaking the stamp if it's already in use */
456 if (stamp_mutex++) {
457 stamp_mutex--;
458 rasops24_putchar(cookie, row, col, uc, attr);
459 return;
460 }
461
462 ri = (struct rasops_info *)cookie;
463
464 #ifdef RASOPS_CLIPPING
465 if ((unsigned)row >= (unsigned)ri->ri_rows) {
466 stamp_mutex--;
467 return;
468 }
469
470 if ((unsigned)col >= (unsigned)ri->ri_cols) {
471 stamp_mutex--;
472 return;
473 }
474 #endif
475
476 /* Recompute stamp? */
477 if (attr != stamp_attr)
478 rasops24_makestamp(ri, attr);
479
480 rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
481 height = ri->ri_font->fontheight;
482
483 if (uc == (u_int)-1) {
484 while (height--) {
485 rp[0] = stamp[0];
486 rp[1] = stamp[0];
487 rp[2] = stamp[0];
488 rp[3] = stamp[0];
489 rp[4] = stamp[0];
490 rp[5] = stamp[0];
491 rp[6] = stamp[0];
492 rp[7] = stamp[0];
493 rp[8] = stamp[0];
494 rp[9] = stamp[0];
495 rp[10] = stamp[0];
496 rp[11] = stamp[0];
497 DELTA(rp, ri->ri_stride, int32_t *);
498 }
499 } else {
500 uc -= ri->ri_font->firstchar;
501 fr = (u_char *)ri->ri_font->data + uc*ri->ri_fontscale;
502 fs = ri->ri_font->stride;
503
504 while (height--) {
505 so = STAMP_SHIFT(fr[0], 1) & STAMP_MASK;
506 rp[0] = STAMP_READ(so);
507 rp[1] = STAMP_READ(so + 4);
508 rp[2] = STAMP_READ(so + 8);
509
510 so = STAMP_SHIFT(fr[0], 0) & STAMP_MASK;
511 rp[3] = STAMP_READ(so);
512 rp[4] = STAMP_READ(so + 4);
513 rp[5] = STAMP_READ(so + 8);
514
515 so = STAMP_SHIFT(fr[1], 1) & STAMP_MASK;
516 rp[6] = STAMP_READ(so);
517 rp[7] = STAMP_READ(so + 4);
518 rp[8] = STAMP_READ(so + 8);
519
520 so = STAMP_SHIFT(fr[1], 0) & STAMP_MASK;
521 rp[9] = STAMP_READ(so);
522 rp[10] = STAMP_READ(so + 4);
523 rp[11] = STAMP_READ(so + 8);
524
525 DELTA(rp, ri->ri_stride, int32_t *);
526 fr += fs;
527 }
528 }
529
530 /* Do underline */
531 if (attr & 1) {
532 DELTA(rp, -(ri->ri_stride << 1), int32_t *);
533 rp[0] = STAMP_READ(30);
534 rp[1] = STAMP_READ(30);
535 rp[2] = STAMP_READ(30);
536 rp[3] = STAMP_READ(30);
537 rp[4] = STAMP_READ(30);
538 rp[5] = STAMP_READ(30);
539 rp[6] = STAMP_READ(30);
540 rp[7] = STAMP_READ(30);
541 rp[8] = STAMP_READ(30);
542 rp[9] = STAMP_READ(30);
543 rp[10] = STAMP_READ(30);
544 rp[11] = STAMP_READ(30);
545 }
546
547 stamp_mutex--;
548 }
549
550
551 /*
552 * Erase rows. This is nice and easy due to alignment.
553 */
554 static void
555 rasops24_eraserows(cookie, row, num, attr)
556 void *cookie;
557 int row, num;
558 long attr;
559 {
560 struct rasops_info *ri;
561 u_int32_t *dp, clr, stamp[3];
562 int n9, n3, n1, cnt;
563
564 /*
565 * If the color is gray, we can cheat and use the generic routines
566 * (which are faster, hopefully) since the r,g,b values are the same.
567 */
568 if (attr & 4) {
569 rasops_eraserows(cookie, row, num, attr);
570 return;
571 }
572
573 ri = (struct rasops_info *)cookie;
574
575 #ifdef RASOPS_CLIPPING
576 if (row < 0) {
577 num += row;
578 row = 0;
579 }
580
581 if ((row + num) > ri->ri_rows)
582 num = ri->ri_rows - row;
583
584 if (num <= 0)
585 return;
586 #endif
587
588 clr = ri->ri_devcmap[(attr >> 16) & 15] & 0xffffff;
589 stamp[0] = (clr << 8) | (clr >> 16);
590 stamp[1] = (clr << 16) | (clr >> 8);
591 stamp[2] = (clr << 24) | clr;
592
593 #if BYTE_ORDER == LITTLE_ENDIAN
594 if (!ri->ri_swab) {
595 #else
596 if (ri->ri_swab) {
597 #endif
598 stamp[0] = bswap32(stamp[0]);
599 stamp[1] = bswap32(stamp[1]);
600 stamp[2] = bswap32(stamp[2]);
601 }
602
603 num *= ri->ri_font->fontheight;
604 dp = (int32_t *)(ri->ri_bits + row * ri->ri_yscale);
605
606 n9 = ri->ri_emustride / 36;
607 cnt = (n9 << 5) + (n9 << 2); /* (32*n9) + (4*n9) */
608 n3 = (ri->ri_emustride - cnt) / 12;
609 cnt += (n3 << 3) + (n3 << 2); /* (8*n3) + (4*n3) */
610 n1 = (ri->ri_emustride - cnt) >> 2;
611
612 while (num--) {
613 for (cnt = n9; cnt; cnt--) {
614 dp[0] = stamp[0];
615 dp[1] = stamp[1];
616 dp[2] = stamp[2];
617 dp[3] = stamp[0];
618 dp[4] = stamp[1];
619 dp[5] = stamp[2];
620 dp[6] = stamp[0];
621 dp[7] = stamp[1];
622 dp[8] = stamp[2];
623 dp += 9;
624 }
625
626 for (cnt = n3; cnt; cnt--) {
627 dp[0] = stamp[0];
628 dp[1] = stamp[1];
629 dp[2] = stamp[2];
630 dp += 3;
631 }
632
633 for (cnt = 0; cnt < n1; cnt++)
634 *dp++ = stamp[cnt];
635
636 DELTA(dp, ri->ri_delta, int32_t *);
637 }
638 }
639
640
641 /*
642 * Erase columns.
643 */
644 static void
645 rasops24_erasecols(cookie, row, col, num, attr)
646 void *cookie;
647 int row, col, num;
648 long attr;
649 {
650 int n12, n4, height, cnt, slop, clr, stamp[3];
651 struct rasops_info *ri;
652 int32_t *dp, *rp;
653 u_char *dbp;
654
655 /*
656 * If the color is gray, we can cheat and use the generic routines
657 * (which are faster, hopefully) since the r,g,b values are the same.
658 */
659 if (attr & 4) {
660 rasops_erasecols(cookie, row, col, num, attr);
661 return;
662 }
663
664 ri = (struct rasops_info *)cookie;
665
666 #ifdef RASOPS_CLIPPING
667 /* Catches 'row < 0' case too */
668 if ((unsigned)row >= (unsigned)ri->ri_rows)
669 return;
670
671 if (col < 0) {
672 num += col;
673 col = 0;
674 }
675
676 if ((col + num) > ri->ri_cols)
677 num = ri->ri_cols - col;
678
679 if (num <= 0)
680 return;
681 #endif
682
683 rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
684 num *= ri->ri_font->fontwidth;
685 height = ri->ri_font->fontheight;
686
687 clr = ri->ri_devcmap[(attr >> 16) & 15] & 0xffffff;
688 stamp[0] = (clr << 8) | (clr >> 16);
689 stamp[1] = (clr << 16) | (clr >> 8);
690 stamp[2] = (clr << 24) | clr;
691
692 #if BYTE_ORDER == LITTLE_ENDIAN
693 if (!ri->ri_swab) {
694 #else
695 if (ri->ri_swab) {
696 #endif
697 stamp[0] = bswap32(stamp[0]);
698 stamp[1] = bswap32(stamp[1]);
699 stamp[2] = bswap32(stamp[2]);
700 }
701
702 /*
703 * The current byte offset mod 4 tells us the number of 24-bit pels
704 * we need to write for alignment to 32-bits. Once we're aligned on
705 * a 32-bit boundary, we're also aligned on a 4 pixel boundary, so
706 * the stamp does not need to be rotated. The following shows the
707 * layout of 4 pels (a, b, and c) in a 3 word region and illustrates
708 * this:
709 *
710 * aaab bbcc cddd
711 */
712 slop = (int)rp & 3; num -= slop;
713 n12 = num / 12; num -= (n12 << 3) + (n12 << 2);
714 n4 = num >> 2; num &= 3;
715
716 while (height--) {
717 dbp = (u_char *)rp;
718 DELTA(rp, ri->ri_stride, int32_t *);
719
720 /* Align to 4 bytes */
721 /* XXX handle with masks, bring under control of ri_swab */
722 for (cnt = slop; cnt; cnt--) {
723 *dbp++ = (clr >> 16);
724 *dbp++ = (clr >> 8);
725 *dbp++ = clr;
726 }
727
728 dp = (int32_t *)dbp;
729
730 /* 12 pels per loop */
731 for (cnt = n12; cnt; cnt--) {
732 dp[0] = stamp[0];
733 dp[1] = stamp[1];
734 dp[2] = stamp[2];
735 dp[3] = stamp[0];
736 dp[4] = stamp[1];
737 dp[5] = stamp[2];
738 dp[6] = stamp[0];
739 dp[7] = stamp[1];
740 dp[8] = stamp[2];
741 dp += 9;
742 }
743
744 /* 4 pels per loop */
745 for (cnt = n4; cnt; cnt--) {
746 dp[0] = stamp[0];
747 dp[1] = stamp[1];
748 dp[2] = stamp[2];
749 dp += 3;
750 }
751
752 /* Trailing slop */
753 /* XXX handle with masks, bring under control of ri_swab */
754 dbp = (u_char *)dp;
755 for (cnt = num; cnt; cnt--) {
756 *dbp++ = (clr >> 16);
757 *dbp++ = (clr >> 8);
758 *dbp++ = clr;
759 }
760 }
761 }
762