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