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