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