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