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