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