rasops.c revision 1.11
1/* $NetBSD: rasops.c,v 1.11 1999/06/15 22:34:45 ad 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 Andy 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: rasops.c,v 1.11 1999/06/15 22:34:45 ad Exp $"); 41 42#include "rasops_glue.h" 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/bswap.h> 50#include <machine/endian.h> 51 52#include <dev/wscons/wsdisplayvar.h> 53#include <dev/wscons/wsconsio.h> 54#include <dev/wsfont/wsfont.h> 55#include <dev/rasops/rasops.h> 56 57#ifndef _KERNEL 58#include <errno.h> 59#endif 60 61/* ANSI colormap (R,G,B). Upper 8 are high-intensity */ 62u_char rasops_cmap[256*3] = { 63 0x00, 0x00, 0x00, /* black */ 64 0x7f, 0x00, 0x00, /* red */ 65 0x00, 0x7f, 0x00, /* green */ 66 0x7f, 0x7f, 0x00, /* brown */ 67 0x00, 0x00, 0x7f, /* blue */ 68 0x7f, 0x00, 0x7f, /* magenta */ 69 0x00, 0x7f, 0x7f, /* cyan */ 70 0xc7, 0xc7, 0xc7, /* white - XXX too dim? */ 71 72 0x7f, 0x7f, 0x7f, /* black */ 73 0xff, 0x00, 0x00, /* red */ 74 0x00, 0xff, 0x00, /* green */ 75 0xff, 0xff, 0x00, /* brown */ 76 0x00, 0x00, 0xff, /* blue */ 77 0xff, 0x00, 0xff, /* magenta */ 78 0x00, 0xff, 0xff, /* cyan */ 79 0xff, 0xff, 0xff, /* white */ 80}; 81 82/* True if color is gray */ 83u_char rasops_isgray[16] = { 84 1, 0, 0, 0, 85 0, 0, 0, 1, 86 1, 0, 0, 0, 87 0, 0, 0, 1 88}; 89 90/* Generic functions */ 91static void rasops_copyrows __P((void *, int, int, int)); 92static int rasops_mapchar __P((void *, int, u_int *)); 93static void rasops_cursor __P((void *, int, int, int)); 94static int rasops_alloc_cattr __P((void *, int, int, int, long *)); 95static int rasops_alloc_mattr __P((void *, int, int, int, long *)); 96static void rasops_do_cursor __P((struct rasops_info *)); 97static void rasops_init_devcmap __P((struct rasops_info *)); 98 99/* Per-depth initalization functions */ 100void rasops1_init __P((struct rasops_info *)); 101void rasops2_init __P((struct rasops_info *)); 102void rasops8_init __P((struct rasops_info *)); 103void rasops15_init __P((struct rasops_info *)); 104void rasops24_init __P((struct rasops_info *)); 105void rasops32_init __P((struct rasops_info *)); 106 107/* 108 * Initalize a 'rasops_info' descriptor. 109 */ 110int 111rasops_init(ri, wantrows, wantcols, clear, center) 112 struct rasops_info *ri; 113 int wantrows, wantcols, clear, center; 114{ 115#ifdef _KERNEL 116 /* Select a font if the caller doesn't care */ 117 if (ri->ri_font == NULL) { 118 int cookie; 119 120 wsfont_init(); 121 122 /* Want 8 pixel wide, don't care about aestethics */ 123 if ((cookie = wsfont_find(NULL, 8, 0, 0)) <= 0) 124 cookie = wsfont_find(NULL, 0, 0, 0); 125 126 if (cookie <= 0) { 127 printf("rasops_init: font table is empty\n"); 128 return (-1); 129 } 130 131 if (wsfont_lock(cookie, &ri->ri_font, 132 WSFONT_L2R, WSFONT_L2R) <= 0) { 133 printf("rasops_init: couldn't lock font\n"); 134 return (-1); 135 } 136 137#ifdef DIAGNOSTIC 138 if (ri->ri_font == NULL) 139 panic("rasops_init: locked font, but got no pointer\n"); 140#endif 141 ri->ri_wsfcookie = cookie; 142 } 143#endif 144 145 /* This should never happen in reality... */ 146#ifdef DEBUG 147 if ((int)ri->ri_bits & 3) { 148 printf("rasops_init: bits not aligned on 32-bit boundary\n"); 149 return (-1); 150 } 151 152 if ((int)ri->ri_stride & 3) { 153 printf("rasops_init: stride not aligned on 32-bit boundary\n"); 154 return (-1); 155 } 156#endif 157 158 /* Fix color palette. We need this for the cursor to work. */ 159 rasops_cmap[255*3+0] = 0xff; 160 rasops_cmap[255*3+1] = 0xff; 161 rasops_cmap[255*3+2] = 0xff; 162 163 /* setfont does most of the work */ 164 if (rasops_setfont(ri, wantrows, wantcols, clear, center)) 165 return (-1); 166 167 rasops_init_devcmap(ri); 168 ri->ri_flg = RASOPS_INITTED; 169 return (0); 170} 171 172 173/* 174 * Choose a different font. The new font will already be set in ri_font. 175 */ 176int 177rasops_setfont(ri, wantrows, wantcols, clear, center) 178 struct rasops_info *ri; 179 int wantrows, wantcols, clear, center; 180{ 181 int bpp; 182 183 if (ri->ri_font->fontwidth > 32 || ri->ri_font->fontwidth < 4) 184 panic("rasops_init: fontwidth assumptions botched!\n"); 185 186 /* Need this to frob the setup below */ 187 bpp = (ri->ri_depth == 15 ? 16 : ri->ri_depth); 188 189 if (ri->ri_flg & RASOPS_INITTED) 190 ri->ri_bits = ri->ri_origbits; 191 192 /* Don't care if the caller wants a hideously small console */ 193 if (wantrows < 10) 194 wantrows = 5000; 195 196 if (wantcols < 20) 197 wantcols = 5000; 198 199 /* Now constrain what they get */ 200 ri->ri_emuwidth = ri->ri_font->fontwidth * wantcols; 201 ri->ri_emuheight = ri->ri_font->fontheight * wantrows; 202 203 if (ri->ri_emuwidth > ri->ri_width) 204 ri->ri_emuwidth = ri->ri_width; 205 206 if (ri->ri_emuheight > ri->ri_height) 207 ri->ri_emuheight = ri->ri_height; 208 209 /* Reduce width until aligned on a 32-bit boundary */ 210 while ((ri->ri_emuwidth*bpp & 31) != 0) 211 ri->ri_emuwidth--; 212 213 ri->ri_cols = ri->ri_emuwidth / ri->ri_font->fontwidth; 214 ri->ri_rows = ri->ri_emuheight / ri->ri_font->fontheight; 215 ri->ri_emustride = ri->ri_emuwidth * bpp >> 3; 216 ri->ri_delta = ri->ri_stride - ri->ri_emustride; 217 ri->ri_ccol = 0; 218 ri->ri_crow = 0; 219 ri->ri_pelbytes = bpp >> 3; 220 221 ri->ri_xscale = (ri->ri_font->fontwidth * bpp) >> 3; 222 ri->ri_yscale = ri->ri_font->fontheight * ri->ri_stride; 223 ri->ri_fontscale = ri->ri_font->fontheight * ri->ri_font->stride; 224 225#ifdef DEBUG 226 if (ri->ri_delta & 3) 227 panic("rasops_init: delta isn't aligned on 32-bit boundary!"); 228#endif 229 /* Clear the entire display */ 230 if (clear) 231 bzero(ri->ri_bits, ri->ri_stride * ri->ri_height); 232 233 /* Now centre our window if needs be */ 234 ri->ri_origbits = ri->ri_bits; 235 236 if (center) { 237 ri->ri_bits += ((ri->ri_stride - ri->ri_emustride) >> 1) & ~3; 238 ri->ri_bits += ((ri->ri_height - ri->ri_emuheight) >> 1) * 239 ri->ri_stride; 240 241 ri->ri_yorigin = (int)(ri->ri_bits - ri->ri_origbits) 242 / ri->ri_stride; 243 ri->ri_xorigin = (((int)(ri->ri_bits - ri->ri_origbits) 244 % ri->ri_stride) * bpp) >> 3; 245 } else 246 ri->ri_xorigin = ri->ri_yorigin = 0; 247 248 /* 249 * Fill in defaults for operations set. XXX this nukes private 250 * routines used by accelerated fb drivers. 251 */ 252 ri->ri_ops.mapchar = rasops_mapchar; 253 ri->ri_ops.copyrows = rasops_copyrows; 254 ri->ri_ops.copycols = rasops_copycols; 255 ri->ri_ops.erasecols = rasops_erasecols; 256 ri->ri_ops.eraserows = rasops_eraserows; 257 ri->ri_ops.cursor = rasops_cursor; 258 ri->ri_do_cursor = rasops_do_cursor; 259 260 if (ri->ri_depth < 8 || ri->ri_forcemono) { 261 ri->ri_ops.alloc_attr = rasops_alloc_mattr; 262 ri->ri_caps = WSATTR_UNDERLINE | WSATTR_REVERSE; 263 } else { 264 ri->ri_ops.alloc_attr = rasops_alloc_cattr; 265 ri->ri_caps = WSATTR_UNDERLINE | WSATTR_HILIT | 266 WSATTR_WSCOLORS | WSATTR_REVERSE; 267 } 268 269 switch (ri->ri_depth) { 270#if NRASOPS1 271 case 1: 272 rasops1_init(ri); 273 break; 274#endif 275 276#if NRASOPS2 277 case 2: 278 rasops2_init(ri); 279 break; 280#endif 281 282#if NRASOPS8 283 case 8: 284 rasops8_init(ri); 285 break; 286#endif 287 288#if NRASOPS15 || NRASOPS16 289 case 15: 290 case 16: 291 rasops15_init(ri); 292 break; 293#endif 294 295#if NRASOPS24 296 case 24: 297 rasops24_init(ri); 298 break; 299#endif 300 301#if NRASOPS32 302 case 32: 303 rasops32_init(ri); 304 break; 305#endif 306 default: 307 ri->ri_flg = 0; 308 return (-1); 309 } 310 311 return (0); 312} 313 314 315/* 316 * Map a character. 317 */ 318static int 319rasops_mapchar(cookie, c, cp) 320 void *cookie; 321 int c; 322 u_int *cp; 323{ 324 struct rasops_info *ri; 325 326 ri = (struct rasops_info *)cookie; 327 328#ifdef DIAGNOSTIC 329 if (ri->ri_font == NULL) 330 panic("rasops_mapchar: no font selected\n"); 331#endif 332 333 if (c < ri->ri_font->firstchar) { 334 *cp = ' '; 335 return (0); 336 } 337 338 if (c - ri->ri_font->firstchar >= ri->ri_font->numchars) { 339 *cp = ' '; 340 return (0); 341 } 342 343 *cp = c; 344 return (5); 345} 346 347 348/* 349 * Allocate a color attribute. 350 */ 351static int 352rasops_alloc_cattr(cookie, fg, bg, flg, attr) 353 void *cookie; 354 int fg, bg, flg; 355 long *attr; 356{ 357 int swap; 358 359#ifdef RASOPS_CLIPPING 360 fg &= 7; 361 bg &= 7; 362 flg &= 255; 363#endif 364 if (flg & WSATTR_BLINK) 365 return (EINVAL); 366 367 if (flg & WSATTR_REVERSE) { 368 swap = fg; 369 fg = bg; 370 bg = swap; 371 } 372 373 if (flg & WSATTR_HILIT) 374 fg += 8; 375 376 flg = ((flg & WSATTR_UNDERLINE) ? 1 : 0); 377 378 if (rasops_isgray[fg]) 379 flg |= 2; 380 381 if (rasops_isgray[bg]) 382 flg |= 4; 383 384 *attr = (bg << 16) | (fg << 24) | flg; 385 return 0; 386} 387 388 389/* 390 * Allocate a mono attribute. 391 */ 392static int 393rasops_alloc_mattr(cookie, fg, bg, flg, attr) 394 void *cookie; 395 int fg, bg, flg; 396 long *attr; 397{ 398 int swap; 399 400#ifdef RASOPS_CLIPPING 401 flg &= 255; 402#endif 403 fg = fg ? 1 : 0; 404 bg = bg ? 1 : 0; 405 406 if (flg & WSATTR_BLINK) 407 return (EINVAL); 408 409 if ((flg & WSATTR_REVERSE) != 0) { 410 swap = fg; 411 fg = bg; 412 bg = swap; 413 } 414 415 *attr = (bg << 16) | (fg << 24) | ((flg & WSATTR_UNDERLINE) ? 7 : 6); 416 return 0; 417} 418 419 420/* 421 * Copy rows. 422 */ 423static void 424rasops_copyrows(cookie, src, dst, num) 425 void *cookie; 426 int src, dst, num; 427{ 428 struct rasops_info *ri; 429 int32_t *sp, *dp, *srp, *drp; 430 int n8, n1, cnt; 431 432 ri = (struct rasops_info *)cookie; 433 434#ifdef RASOPS_CLIPPING 435 if (dst == src) 436 return; 437 438 if (src < 0) { 439 num += src; 440 src = 0; 441 } 442 443 if ((src + num) > ri->ri_rows) 444 num = ri->ri_rows - src; 445 446 if (dst < 0) { 447 num += dst; 448 dst = 0; 449 } 450 451 if ((dst + num) > ri->ri_rows) 452 num = ri->ri_rows - dst; 453 454 if (num <= 0) 455 return; 456#endif 457 458 num *= ri->ri_font->fontheight; 459 n8 = ri->ri_emustride >> 5; 460 n1 = (ri->ri_emustride >> 2) & 7; 461 462 if (dst < src) { 463 sp = (int32_t *)(ri->ri_bits + src * ri->ri_yscale); 464 dp = (int32_t *)(ri->ri_bits + dst * ri->ri_yscale); 465 466 while (num--) { 467 for (cnt = n8; cnt; cnt--) { 468 dp[0] = sp[0]; 469 dp[1] = sp[1]; 470 dp[2] = sp[2]; 471 dp[3] = sp[3]; 472 dp[4] = sp[4]; 473 dp[5] = sp[5]; 474 dp[6] = sp[6]; 475 dp[7] = sp[7]; 476 dp += 8; 477 sp += 8; 478 } 479 480 for (cnt = n1; cnt; cnt--) 481 *dp++ = *sp++; 482 483 DELTA(dp, ri->ri_delta, int32_t *); 484 DELTA(sp, ri->ri_delta, int32_t *); 485 } 486 } else { 487 src = ri->ri_font->fontheight * src + num - 1; 488 dst = ri->ri_font->fontheight * dst + num - 1; 489 490 srp = (int32_t *)(ri->ri_bits + src * ri->ri_stride); 491 drp = (int32_t *)(ri->ri_bits + dst * ri->ri_stride); 492 493 while (num--) { 494 dp = drp; 495 sp = srp; 496 DELTA(srp, -ri->ri_stride, int32_t *); 497 DELTA(drp, -ri->ri_stride, int32_t *); 498 499 for (cnt = n8; cnt; cnt--) { 500 dp[0] = sp[0]; 501 dp[1] = sp[1]; 502 dp[2] = sp[2]; 503 dp[3] = sp[3]; 504 dp[4] = sp[4]; 505 dp[5] = sp[5]; 506 dp[6] = sp[6]; 507 dp[7] = sp[7]; 508 dp += 8; 509 sp += 8; 510 } 511 512 for (cnt = n1; cnt; cnt--) 513 *dp++ = *sp++; 514 } 515 } 516} 517 518 519/* 520 * Copy columns. This is slow, and hard to optimize due to alignment, 521 * and the fact that we have to copy both left->right and right->left. 522 * We simply cop-out here and use bcopy(), since it handles all of 523 * these cases anyway. 524 */ 525void 526rasops_copycols(cookie, row, src, dst, num) 527 void *cookie; 528 int row, src, dst, num; 529{ 530 struct rasops_info *ri; 531 u_char *sp, *dp; 532 int height; 533 534 ri = (struct rasops_info *)cookie; 535 536#ifdef RASOPS_CLIPPING 537 if (dst == src) 538 return; 539 540 /* Catches < 0 case too */ 541 if ((unsigned)row >= (unsigned)ri->ri_rows) 542 return; 543 544 if (src < 0) { 545 num += src; 546 src = 0; 547 } 548 549 if ((src + num) > ri->ri_cols) 550 num = ri->ri_cols - src; 551 552 if (dst < 0) { 553 num += dst; 554 dst = 0; 555 } 556 557 if ((dst + num) > ri->ri_cols) 558 num = ri->ri_cols - dst; 559 560 if (num <= 0) 561 return; 562#endif 563 564 num *= ri->ri_xscale; 565 row *= ri->ri_yscale; 566 height = ri->ri_font->fontheight; 567 568 sp = ri->ri_bits + row + src * ri->ri_xscale; 569 dp = ri->ri_bits + row + dst * ri->ri_xscale; 570 571 while (height--) { 572 bcopy(sp, dp, num); 573 dp += ri->ri_stride; 574 sp += ri->ri_stride; 575 } 576} 577 578 579/* 580 * Turn cursor off/on. 581 */ 582static void 583rasops_cursor(cookie, on, row, col) 584 void *cookie; 585 int on, row, col; 586{ 587 struct rasops_info *ri; 588 589 ri = (struct rasops_info *)cookie; 590 591 /* Turn old cursor off */ 592 if (ri->ri_flg & RASOPS_CURSOR) 593#ifdef RASOPS_CLIPPING 594 if (!(ri->ri_flg & RASOPS_CURSOR_CLIPPED)) 595#endif 596 ri->ri_do_cursor(ri); 597 598 /* Select new cursor */ 599#ifdef RASOPS_CLIPPING 600 ri->ri_flg &= ~RASOPS_CURSOR_CLIPPED; 601 602 if (row < 0 || row >= ri->ri_rows) 603 ri->ri_flg |= RASOPS_CURSOR_CLIPPED; 604 else if (col < 0 || col >= ri->ri_cols) 605 ri->ri_flg |= RASOPS_CURSOR_CLIPPED; 606#endif 607 ri->ri_crow = row; 608 ri->ri_ccol = col; 609 610 if (on) { 611 ri->ri_flg |= RASOPS_CURSOR; 612#ifdef RASOPS_CLIPPING 613 if (!(ri->ri_flg & RASOPS_CURSOR_CLIPPED)) 614#endif 615 ri->ri_do_cursor(ri); 616 } else 617 ri->ri_flg &= ~RASOPS_CURSOR; 618} 619 620 621/* 622 * Make the device colormap 623 */ 624static void 625rasops_init_devcmap(ri) 626 struct rasops_info *ri; 627{ 628 u_char *p; 629 int i, c; 630 631 switch (ri->ri_depth) { 632 case 1: 633 ri->ri_devcmap[0] = 0; 634 for (i = 1; i < 16; i++) 635 ri->ri_devcmap[i] = -1; 636 return; 637 638 case 2: 639 for (i = 1; i < 15; i++) 640 ri->ri_devcmap[i] = 0xaaaaaaaa; 641 642 ri->ri_devcmap[0] = 0; 643 ri->ri_devcmap[8] = 0x55555555; 644 ri->ri_devcmap[15] = -1; 645 return; 646 647 case 8: 648 for (i = 0; i < 16; i++) 649 ri->ri_devcmap[i] = i | (i<<8) | (i<<16) | (i<<24); 650 return; 651 } 652 653 p = rasops_cmap; 654 655 for (i = 0; i < 16; i++) { 656 if (ri->ri_rnum <= 8) 657 c = (*p++ >> (8 - ri->ri_rnum)) << ri->ri_rpos; 658 else 659 c = (*p++ << (ri->ri_rnum - 8)) << ri->ri_rpos; 660 661 if (ri->ri_gnum <= 8) 662 c |= (*p++ >> (8 - ri->ri_gnum)) << ri->ri_gpos; 663 else 664 c |= (*p++ << (ri->ri_gnum - 8)) << ri->ri_gpos; 665 666 if (ri->ri_bnum <= 8) 667 c |= (*p++ >> (8 - ri->ri_bnum)) << ri->ri_bpos; 668 else 669 c |= (*p++ << (ri->ri_bnum - 8)) << ri->ri_bpos; 670 671 /* Fill the word for generic routines, which want this */ 672 if (ri->ri_depth == 24) 673 c = c | ((c & 0xff) << 24); 674 else if (ri->ri_depth <= 16) 675 c = c | (c << 16); 676 677 /* 24bpp does bswap on the fly. {32,16,15}bpp do it here. */ 678 if (!ri->ri_swab) 679 ri->ri_devcmap[i] = c; 680 else if (ri->ri_depth == 32) 681 ri->ri_devcmap[i] = bswap32(c); 682 else if (ri->ri_depth == 16 || ri->ri_depth == 15) 683 ri->ri_devcmap[i] = bswap16(c); 684 else 685 ri->ri_devcmap[i] = c; 686 } 687} 688 689 690/* 691 * Unpack a rasops attribute 692 */ 693void 694rasops_unpack_attr(attr, fg, bg, underline) 695 long attr; 696 int *fg, *bg, *underline; 697{ 698 699 *fg = ((u_int)attr >> 24) & 15; 700 *bg = ((u_int)attr >> 16) & 15; 701 *underline = (u_int)attr & 1; 702} 703 704 705/* 706 * Erase rows. This isn't static, since 24-bpp uses it in special cases. 707 */ 708void 709rasops_eraserows(cookie, row, num, attr) 710 void *cookie; 711 int row, num; 712 long attr; 713{ 714 struct rasops_info *ri; 715 int np, nw, cnt; 716 int32_t *dp, clr; 717 718 ri = (struct rasops_info *)cookie; 719 720#ifdef RASOPS_CLIPPING 721 if (row < 0) { 722 num += row; 723 row = 0; 724 } 725 726 if ((row + num) > ri->ri_rows) 727 num = ri->ri_rows - row; 728 729 if (num <= 0) 730 return; 731#endif 732 733 clr = ri->ri_devcmap[(attr >> 16) & 15]; 734 num *= ri->ri_font->fontheight; 735 dp = (int32_t *)(ri->ri_bits + row * ri->ri_yscale); 736 737 np = ri->ri_emustride >> 5; 738 nw = (ri->ri_emustride >> 2) & 7; 739 740 while (num--) { 741 for (cnt = np; cnt; cnt--) { 742 dp[0] = clr; 743 dp[1] = clr; 744 dp[2] = clr; 745 dp[3] = clr; 746 dp[4] = clr; 747 dp[5] = clr; 748 dp[6] = clr; 749 dp[7] = clr; 750 dp += 8; 751 } 752 753 for (cnt = nw; cnt; cnt--) { 754 *(int32_t *)dp = clr; 755 DELTA(dp, 4, int32_t *); 756 } 757 758 DELTA(dp, ri->ri_delta, int32_t *); 759 } 760} 761 762 763/* 764 * Actually turn the cursor on or off. This does the dirty work for 765 * rasops_cursor(). 766 */ 767static void 768rasops_do_cursor(ri) 769 struct rasops_info *ri; 770{ 771 int full1, height, cnt, slop1, slop2, row, col, mask; 772 u_char *dp, *rp; 773 774 row = ri->ri_crow; 775 col = ri->ri_ccol; 776 777 rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale; 778 height = ri->ri_font->fontheight; 779 mask = ri->ri_devcmap[15]; 780 781 slop1 = (4 - ((int)rp & 3)) & 3; 782 783 if (slop1 > ri->ri_xscale) 784 slop1 = ri->ri_xscale; 785 786 slop2 = (ri->ri_xscale - slop1) & 3; 787 full1 = (ri->ri_xscale - slop1 - slop2) >> 2; 788 789 if ((slop1 | slop2) == 0) { 790 /* A common case */ 791 while (height--) { 792 dp = rp; 793 rp += ri->ri_stride; 794 795 for (cnt = full1; cnt; cnt--) { 796 *(int32_t *)dp ^= mask; 797 dp += 4; 798 } 799 } 800 } else { 801 /* XXX this is stupid.. use masks instead */ 802 while (height--) { 803 dp = rp; 804 rp += ri->ri_stride; 805 806 if (slop1 & 1) 807 *dp++ ^= mask; 808 809 if (slop1 & 2) { 810 *(int16_t *)dp ^= mask; 811 dp += 2; 812 } 813 814 for (cnt = full1; cnt; cnt--) { 815 *(int32_t *)dp ^= mask; 816 dp += 4; 817 } 818 819 if (slop2 & 1) 820 *dp++ ^= mask; 821 822 if (slop2 & 2) 823 *(int16_t *)dp ^= mask; 824 } 825 } 826} 827 828 829/* 830 * Erase columns. 831 */ 832void 833rasops_erasecols(cookie, row, col, num, attr) 834 void *cookie; 835 int row, col, num; 836 long attr; 837{ 838 int n8, height, cnt, slop1, slop2, clr; 839 struct rasops_info *ri; 840 int32_t *rp, *dp; 841 842 ri = (struct rasops_info *)cookie; 843 844#ifdef RASOPS_CLIPPING 845 if ((unsigned)row >= (unsigned)ri->ri_rows) 846 return; 847 848 if (col < 0) { 849 num += col; 850 col = 0; 851 } 852 853 if ((col + num) > ri->ri_cols) 854 num = ri->ri_cols - col; 855 856 if (num <= 0) 857 return; 858#endif 859 860 num = num * ri->ri_xscale; 861 rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale); 862 height = ri->ri_font->fontheight; 863 clr = ri->ri_devcmap[(attr >> 16) & 15]; 864 865 /* Don't bother using the full loop for <= 32 pels */ 866 if (num <= 32) { 867 if (((num | ri->ri_xscale) & 3) == 0) { 868 /* Word aligned blt */ 869 num >>= 2; 870 871 while (height--) { 872 dp = rp; 873 DELTA(rp, ri->ri_stride, int32_t *); 874 875 for (cnt = num; cnt; cnt--) 876 *dp++ = clr; 877 } 878 } else if (((num | ri->ri_xscale) & 1) == 0) { 879 /* 880 * Halfword aligned blt. This is needed so the 881 * 15/16 bit ops can use this function. 882 */ 883 num >>= 1; 884 885 while (height--) { 886 dp = rp; 887 DELTA(rp, ri->ri_stride, int32_t *); 888 889 for (cnt = num; cnt; cnt--) { 890 *(int16_t *)dp = clr; 891 DELTA(dp, 2, int32_t *); 892 } 893 } 894 } else { 895 while (height--) { 896 dp = rp; 897 DELTA(rp, ri->ri_stride, int32_t *); 898 899 for (cnt = num; cnt; cnt--) { 900 *(u_char *)dp = clr; 901 DELTA(dp, 1, int32_t *); 902 } 903 } 904 } 905 906 return; 907 } 908 909 slop1 = (4 - ((int)rp & 3)) & 3; 910 slop2 = (num - slop1) & 3; 911 num -= slop1 + slop2; 912 n8 = num >> 5; 913 num = (num >> 2) & 7; 914 915 while (height--) { 916 dp = rp; 917 DELTA(rp, ri->ri_stride, int32_t *); 918 919 /* Align span to 4 bytes */ 920 if (slop1 & 1) { 921 *(u_char *)dp = clr; 922 DELTA(dp, 1, int32_t *); 923 } 924 925 if (slop1 & 2) { 926 *(int16_t *)dp = clr; 927 DELTA(dp, 2, int32_t *); 928 } 929 930 /* Write 32 bytes per loop */ 931 for (cnt = n8; cnt; cnt--) { 932 dp[0] = clr; 933 dp[1] = clr; 934 dp[2] = clr; 935 dp[3] = clr; 936 dp[4] = clr; 937 dp[5] = clr; 938 dp[6] = clr; 939 dp[7] = clr; 940 dp += 8; 941 } 942 943 /* Write 4 bytes per loop */ 944 for (cnt = num; cnt; cnt--) 945 *dp++ = clr; 946 947 /* Write unaligned trailing slop */ 948 if (slop2 & 1) { 949 *(u_char *)dp = clr; 950 DELTA(dp, 1, int32_t *); 951 } 952 953 if (slop2 & 2) 954 *(int16_t *)dp = clr; 955 } 956} 957