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