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