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