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