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