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