1 /* $NetBSD: rasops.c,v 1.42 2002/09/27 15:37:31 provos 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 Andrew 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.42 2002/09/27 15:37:31 provos Exp $"); 41 42 #include "opt_rasops.h" 43 #include "rasops_glue.h" 44 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 */ 62 const u_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 * For the cursor, we need at least the last (255th) 83 * color to be white. Fill up white completely for 84 * simplicity. 85 */ 86 #define _CMWHITE 0xff, 0xff, 0xff, 87 #define _CMWHITE16 _CMWHITE _CMWHITE _CMWHITE _CMWHITE \ 88 _CMWHITE _CMWHITE _CMWHITE _CMWHITE \ 89 _CMWHITE _CMWHITE _CMWHITE _CMWHITE \ 90 _CMWHITE _CMWHITE _CMWHITE _CMWHITE 91 _CMWHITE16 _CMWHITE16 _CMWHITE16 _CMWHITE16 _CMWHITE16 92 _CMWHITE16 _CMWHITE16 _CMWHITE16 _CMWHITE16 _CMWHITE16 93 _CMWHITE16 _CMWHITE16 _CMWHITE16 _CMWHITE16 _CMWHITE16 94 #undef _CMWHITE16 95 #undef _CMWHITE 96 }; 97 98 /* True if color is gray */ 99 const u_char rasops_isgray[16] = { 100 1, 0, 0, 0, 101 0, 0, 0, 1, 102 1, 0, 0, 0, 103 0, 0, 0, 1 104 }; 105 106 /* Generic functions */ 107 static void rasops_copyrows __P((void *, int, int, int)); 108 static int rasops_mapchar __P((void *, int, u_int *)); 109 static void rasops_cursor __P((void *, int, int, int)); 110 static int rasops_allocattr_color __P((void *, int, int, int, long *)); 111 static int rasops_allocattr_mono __P((void *, int, int, int, long *)); 112 static void rasops_do_cursor __P((struct rasops_info *)); 113 static void rasops_init_devcmap __P((struct rasops_info *)); 114 115 /* 116 * Initialize a 'rasops_info' descriptor. 117 */ 118 int 119 rasops_init(ri, wantrows, wantcols) 120 struct rasops_info *ri; 121 int wantrows, wantcols; 122 { 123 124 #ifdef _KERNEL 125 /* Select a font if the caller doesn't care */ 126 if (ri->ri_font == NULL) { 127 int cookie; 128 129 wsfont_init(); 130 131 /* Want 8 pixel wide, don't care about aestethics */ 132 cookie = wsfont_find(NULL, 8, 0, 0, WSDISPLAY_FONTORDER_L2R, 133 WSDISPLAY_FONTORDER_L2R); 134 if (cookie <= 0) 135 cookie = wsfont_find(NULL, 0, 0, 0, 136 WSDISPLAY_FONTORDER_L2R, WSDISPLAY_FONTORDER_L2R); 137 138 if (cookie <= 0) { 139 printf("rasops_init: font table is empty\n"); 140 return (-1); 141 } 142 143 if (wsfont_lock(cookie, &ri->ri_font)) { 144 printf("rasops_init: couldn't lock font\n"); 145 return (-1); 146 } 147 148 ri->ri_wsfcookie = cookie; 149 } 150 #endif 151 152 /* This should never happen in reality... */ 153 #ifdef DEBUG 154 if ((long)ri->ri_bits & 3) { 155 printf("rasops_init: bits not aligned on 32-bit boundary\n"); 156 return (-1); 157 } 158 159 if ((int)ri->ri_stride & 3) { 160 printf("rasops_init: stride not aligned on 32-bit boundary\n"); 161 return (-1); 162 } 163 #endif 164 165 if (rasops_reconfig(ri, wantrows, wantcols)) 166 return (-1); 167 168 rasops_init_devcmap(ri); 169 return (0); 170 } 171 172 /* 173 * Reconfigure (because parameters have changed in some way). 174 */ 175 int 176 rasops_reconfig(ri, wantrows, wantcols) 177 struct rasops_info *ri; 178 int wantrows, wantcols; 179 { 180 int bpp, s; 181 182 s = splhigh(); 183 184 if (ri->ri_font->fontwidth > 32 || ri->ri_font->fontwidth < 4) 185 panic("rasops_init: fontwidth assumptions botched!"); 186 187 /* Need this to frob the setup below */ 188 bpp = (ri->ri_depth == 15 ? 16 : ri->ri_depth); 189 190 if ((ri->ri_flg & RI_CFGDONE) != 0) 191 ri->ri_bits = ri->ri_origbits; 192 193 /* Don't care if the caller wants a hideously small console */ 194 if (wantrows < 10) 195 wantrows = 10; 196 197 if (wantcols < 20) 198 wantcols = 20; 199 200 /* Now constrain what they get */ 201 ri->ri_emuwidth = ri->ri_font->fontwidth * wantcols; 202 ri->ri_emuheight = ri->ri_font->fontheight * wantrows; 203 204 if (ri->ri_emuwidth > ri->ri_width) 205 ri->ri_emuwidth = ri->ri_width; 206 207 if (ri->ri_emuheight > ri->ri_height) 208 ri->ri_emuheight = ri->ri_height; 209 210 /* Reduce width until aligned on a 32-bit boundary */ 211 while ((ri->ri_emuwidth * bpp & 31) != 0) 212 ri->ri_emuwidth--; 213 214 ri->ri_cols = ri->ri_emuwidth / ri->ri_font->fontwidth; 215 ri->ri_rows = ri->ri_emuheight / ri->ri_font->fontheight; 216 ri->ri_emustride = ri->ri_emuwidth * bpp >> 3; 217 ri->ri_delta = ri->ri_stride - ri->ri_emustride; 218 ri->ri_ccol = 0; 219 ri->ri_crow = 0; 220 ri->ri_pelbytes = bpp >> 3; 221 222 ri->ri_xscale = (ri->ri_font->fontwidth * bpp) >> 3; 223 ri->ri_yscale = ri->ri_font->fontheight * ri->ri_stride; 224 ri->ri_fontscale = ri->ri_font->fontheight * ri->ri_font->stride; 225 226 #ifdef DEBUG 227 if ((ri->ri_delta & 3) != 0) 228 panic("rasops_init: ri_delta not aligned on 32-bit boundary"); 229 #endif 230 /* Clear the entire display */ 231 if ((ri->ri_flg & RI_CLEAR) != 0) 232 memset(ri->ri_bits, 0, ri->ri_stride * ri->ri_height); 233 234 /* Now centre our window if needs be */ 235 ri->ri_origbits = ri->ri_bits; 236 237 if ((ri->ri_flg & RI_CENTER) != 0) { 238 ri->ri_bits += (((ri->ri_width * bpp >> 3) - 239 ri->ri_emustride) >> 1) & ~3; 240 ri->ri_bits += ((ri->ri_height - ri->ri_emuheight) >> 1) * 241 ri->ri_stride; 242 243 ri->ri_yorigin = (int)(ri->ri_bits - ri->ri_origbits) 244 / ri->ri_stride; 245 ri->ri_xorigin = (((int)(ri->ri_bits - ri->ri_origbits) 246 % ri->ri_stride) * 8 / bpp); 247 } else 248 ri->ri_xorigin = ri->ri_yorigin = 0; 249 250 /* 251 * Fill in defaults for operations set. XXX this nukes private 252 * routines used by accelerated fb drivers. 253 */ 254 ri->ri_ops.mapchar = rasops_mapchar; 255 ri->ri_ops.copyrows = rasops_copyrows; 256 ri->ri_ops.copycols = rasops_copycols; 257 ri->ri_ops.erasecols = rasops_erasecols; 258 ri->ri_ops.eraserows = rasops_eraserows; 259 ri->ri_ops.cursor = rasops_cursor; 260 ri->ri_do_cursor = rasops_do_cursor; 261 262 if (ri->ri_depth < 8 || (ri->ri_flg & RI_FORCEMONO) != 0) { 263 ri->ri_ops.allocattr = rasops_allocattr_mono; 264 ri->ri_caps = WSSCREEN_UNDERLINE | WSSCREEN_REVERSE; 265 } else { 266 ri->ri_ops.allocattr = rasops_allocattr_color; 267 ri->ri_caps = WSSCREEN_UNDERLINE | WSSCREEN_HILIT | 268 WSSCREEN_WSCOLORS | WSSCREEN_REVERSE; 269 } 270 271 switch (ri->ri_depth) { 272 #if NRASOPS1 > 0 273 case 1: 274 rasops1_init(ri); 275 break; 276 #endif 277 #if NRASOPS2 > 0 278 case 2: 279 rasops2_init(ri); 280 break; 281 #endif 282 #if NRASOPS4 > 0 283 case 4: 284 rasops4_init(ri); 285 break; 286 #endif 287 #if NRASOPS8 > 0 288 case 8: 289 rasops8_init(ri); 290 break; 291 #endif 292 #if NRASOPS15 > 0 || NRASOPS16 > 0 293 case 15: 294 case 16: 295 rasops15_init(ri); 296 break; 297 #endif 298 #if NRASOPS24 > 0 299 case 24: 300 rasops24_init(ri); 301 break; 302 #endif 303 #if NRASOPS32 > 0 304 case 32: 305 rasops32_init(ri); 306 break; 307 #endif 308 default: 309 ri->ri_flg &= ~RI_CFGDONE; 310 splx(s); 311 return (-1); 312 } 313 314 ri->ri_flg |= RI_CFGDONE; 315 splx(s); 316 return (0); 317 } 318 319 /* 320 * Map a character. 321 */ 322 static int 323 rasops_mapchar(cookie, c, cp) 324 void *cookie; 325 int c; 326 u_int *cp; 327 { 328 struct rasops_info *ri; 329 330 ri = (struct rasops_info *)cookie; 331 332 #ifdef DIAGNOSTIC 333 if (ri->ri_font == NULL) 334 panic("rasops_mapchar: no font selected"); 335 #endif 336 337 if (ri->ri_font->encoding != WSDISPLAY_FONTENC_ISO) { 338 if ( (c = wsfont_map_unichar(ri->ri_font, c)) < 0) { 339 *cp = ' '; 340 return (0); 341 342 } 343 } 344 345 if (c < ri->ri_font->firstchar) { 346 *cp = ' '; 347 return (0); 348 } 349 350 if (c - ri->ri_font->firstchar >= ri->ri_font->numchars) { 351 *cp = ' '; 352 return (0); 353 } 354 355 *cp = c; 356 return (5); 357 } 358 359 /* 360 * Allocate a color attribute. 361 */ 362 static int 363 rasops_allocattr_color(cookie, fg, bg, flg, attr) 364 void *cookie; 365 int fg, bg, flg; 366 long *attr; 367 { 368 int swap; 369 370 #ifdef RASOPS_CLIPPING 371 fg &= 7; 372 bg &= 7; 373 #endif 374 if ((flg & WSATTR_BLINK) != 0) 375 return (EINVAL); 376 377 if ((flg & WSATTR_WSCOLORS) == 0) { 378 fg = WSCOL_WHITE; 379 bg = WSCOL_BLACK; 380 } 381 382 if ((flg & WSATTR_REVERSE) != 0) { 383 swap = fg; 384 fg = bg; 385 bg = swap; 386 } 387 388 if ((flg & WSATTR_HILIT) != 0) 389 fg += 8; 390 391 flg = ((flg & WSATTR_UNDERLINE) ? 1 : 0); 392 393 if (rasops_isgray[fg]) 394 flg |= 2; 395 396 if (rasops_isgray[bg]) 397 flg |= 4; 398 399 *attr = (bg << 16) | (fg << 24) | flg; 400 return (0); 401 } 402 403 /* 404 * Allocate a mono attribute. 405 */ 406 static int 407 rasops_allocattr_mono(cookie, fg, bg, flg, attr) 408 void *cookie; 409 int fg, bg, flg; 410 long *attr; 411 { 412 int swap; 413 414 if ((flg & (WSATTR_BLINK | WSATTR_HILIT | WSATTR_WSCOLORS)) != 0) 415 return (EINVAL); 416 417 fg = 1; 418 bg = 0; 419 420 if ((flg & WSATTR_REVERSE) != 0) { 421 swap = fg; 422 fg = bg; 423 bg = swap; 424 } 425 426 *attr = (bg << 16) | (fg << 24) | ((flg & WSATTR_UNDERLINE) ? 7 : 6); 427 return (0); 428 } 429 430 /* 431 * Copy rows. 432 */ 433 static void 434 rasops_copyrows(cookie, src, dst, num) 435 void *cookie; 436 int src, dst, num; 437 { 438 int32_t *sp, *dp, *srp, *drp; 439 struct rasops_info *ri; 440 int n8, n1, cnt, delta; 441 442 ri = (struct rasops_info *)cookie; 443 444 #ifdef RASOPS_CLIPPING 445 if (dst == src) 446 return; 447 448 if (src < 0) { 449 num += src; 450 src = 0; 451 } 452 453 if ((src + num) > ri->ri_rows) 454 num = ri->ri_rows - src; 455 456 if (dst < 0) { 457 num += dst; 458 dst = 0; 459 } 460 461 if ((dst + num) > ri->ri_rows) 462 num = ri->ri_rows - dst; 463 464 if (num <= 0) 465 return; 466 #endif 467 468 num *= ri->ri_font->fontheight; 469 n8 = ri->ri_emustride >> 5; 470 n1 = (ri->ri_emustride >> 2) & 7; 471 472 if (dst < src) { 473 srp = (int32_t *)(ri->ri_bits + src * ri->ri_yscale); 474 drp = (int32_t *)(ri->ri_bits + dst * ri->ri_yscale); 475 delta = ri->ri_stride; 476 } else { 477 src = ri->ri_font->fontheight * src + num - 1; 478 dst = ri->ri_font->fontheight * dst + num - 1; 479 srp = (int32_t *)(ri->ri_bits + src * ri->ri_stride); 480 drp = (int32_t *)(ri->ri_bits + dst * ri->ri_stride); 481 delta = -ri->ri_stride; 482 } 483 484 while (num--) { 485 dp = drp; 486 sp = srp; 487 DELTA(drp, delta, int32_t *); 488 DELTA(srp, delta, int32_t *); 489 490 for (cnt = n8; cnt; cnt--) { 491 dp[0] = sp[0]; 492 dp[1] = sp[1]; 493 dp[2] = sp[2]; 494 dp[3] = sp[3]; 495 dp[4] = sp[4]; 496 dp[5] = sp[5]; 497 dp[6] = sp[6]; 498 dp[7] = sp[7]; 499 dp += 8; 500 sp += 8; 501 } 502 503 for (cnt = n1; cnt; cnt--) 504 *dp++ = *sp++; 505 } 506 } 507 508 /* 509 * Copy columns. This is slow, and hard to optimize due to alignment, 510 * and the fact that we have to copy both left->right and right->left. 511 * We simply cop-out here and use bcopy(), since it handles all of 512 * these cases anyway. 513 */ 514 void 515 rasops_copycols(cookie, row, src, dst, num) 516 void *cookie; 517 int row, src, dst, num; 518 { 519 struct rasops_info *ri; 520 u_char *sp, *dp; 521 int height; 522 523 ri = (struct rasops_info *)cookie; 524 525 #ifdef RASOPS_CLIPPING 526 if (dst == src) 527 return; 528 529 /* Catches < 0 case too */ 530 if ((unsigned)row >= (unsigned)ri->ri_rows) 531 return; 532 533 if (src < 0) { 534 num += src; 535 src = 0; 536 } 537 538 if ((src + num) > ri->ri_cols) 539 num = ri->ri_cols - src; 540 541 if (dst < 0) { 542 num += dst; 543 dst = 0; 544 } 545 546 if ((dst + num) > ri->ri_cols) 547 num = ri->ri_cols - dst; 548 549 if (num <= 0) 550 return; 551 #endif 552 553 num *= ri->ri_xscale; 554 row *= ri->ri_yscale; 555 height = ri->ri_font->fontheight; 556 557 sp = ri->ri_bits + row + src * ri->ri_xscale; 558 dp = ri->ri_bits + row + dst * ri->ri_xscale; 559 560 while (height--) { 561 bcopy(sp, dp, num); 562 dp += ri->ri_stride; 563 sp += ri->ri_stride; 564 } 565 } 566 567 /* 568 * Turn cursor off/on. 569 */ 570 static void 571 rasops_cursor(cookie, on, row, col) 572 void *cookie; 573 int on, row, col; 574 { 575 struct rasops_info *ri; 576 577 ri = (struct rasops_info *)cookie; 578 579 /* Turn old cursor off */ 580 if ((ri->ri_flg & RI_CURSOR) != 0) 581 #ifdef RASOPS_CLIPPING 582 if ((ri->ri_flg & RI_CURSORCLIP) == 0) 583 #endif 584 ri->ri_do_cursor(ri); 585 586 /* Select new cursor */ 587 #ifdef RASOPS_CLIPPING 588 ri->ri_flg &= ~RI_CURSORCLIP; 589 590 if (row < 0 || row >= ri->ri_rows) 591 ri->ri_flg |= RI_CURSORCLIP; 592 else if (col < 0 || col >= ri->ri_cols) 593 ri->ri_flg |= RI_CURSORCLIP; 594 #endif 595 ri->ri_crow = row; 596 ri->ri_ccol = col; 597 598 if (on) { 599 ri->ri_flg |= RI_CURSOR; 600 #ifdef RASOPS_CLIPPING 601 if ((ri->ri_flg & RI_CURSORCLIP) == 0) 602 #endif 603 ri->ri_do_cursor(ri); 604 } else 605 ri->ri_flg &= ~RI_CURSOR; 606 } 607 608 /* 609 * Make the device colormap 610 */ 611 static void 612 rasops_init_devcmap(ri) 613 struct rasops_info *ri; 614 { 615 const u_char *p; 616 int i, c; 617 618 switch (ri->ri_depth) { 619 case 1: 620 ri->ri_devcmap[0] = 0; 621 for (i = 1; i < 16; i++) 622 ri->ri_devcmap[i] = -1; 623 return; 624 625 case 2: 626 for (i = 1; i < 15; i++) 627 ri->ri_devcmap[i] = 0xaaaaaaaa; 628 629 ri->ri_devcmap[0] = 0; 630 ri->ri_devcmap[8] = 0x55555555; 631 ri->ri_devcmap[15] = -1; 632 return; 633 634 case 8: 635 for (i = 0; i < 16; i++) 636 ri->ri_devcmap[i] = i | (i<<8) | (i<<16) | (i<<24); 637 return; 638 } 639 640 p = rasops_cmap; 641 642 for (i = 0; i < 16; i++) { 643 if (ri->ri_rnum <= 8) 644 c = (*p >> (8 - ri->ri_rnum)) << ri->ri_rpos; 645 else 646 c = (*p << (ri->ri_rnum - 8)) << ri->ri_rpos; 647 p++; 648 649 if (ri->ri_gnum <= 8) 650 c |= (*p >> (8 - ri->ri_gnum)) << ri->ri_gpos; 651 else 652 c |= (*p << (ri->ri_gnum - 8)) << ri->ri_gpos; 653 p++; 654 655 if (ri->ri_bnum <= 8) 656 c |= (*p >> (8 - ri->ri_bnum)) << ri->ri_bpos; 657 else 658 c |= (*p << (ri->ri_bnum - 8)) << ri->ri_bpos; 659 p++; 660 661 /* Fill the word for generic routines, which want this */ 662 if (ri->ri_depth == 24) 663 c = c | ((c & 0xff) << 24); 664 else if (ri->ri_depth <= 16) 665 c = c | (c << 16); 666 667 /* 24bpp does bswap on the fly. {32,16,15}bpp do it here. */ 668 if ((ri->ri_flg & RI_BSWAP) == 0) 669 ri->ri_devcmap[i] = c; 670 else if (ri->ri_depth == 32) 671 ri->ri_devcmap[i] = bswap32(c); 672 else if (ri->ri_depth == 16 || ri->ri_depth == 15) 673 ri->ri_devcmap[i] = bswap16(c); 674 else 675 ri->ri_devcmap[i] = c; 676 } 677 } 678 679 /* 680 * Unpack a rasops attribute 681 */ 682 void 683 rasops_unpack_attr(attr, fg, bg, underline) 684 long attr; 685 int *fg, *bg, *underline; 686 { 687 688 *fg = ((u_int)attr >> 24) & 0xf; 689 *bg = ((u_int)attr >> 16) & 0xf; 690 if (underline != NULL) 691 *underline = (u_int)attr & 1; 692 } 693 694 /* 695 * Erase rows. This isn't static, since 24-bpp uses it in special cases. 696 */ 697 void 698 rasops_eraserows(cookie, row, num, attr) 699 void *cookie; 700 int row, num; 701 long attr; 702 { 703 struct rasops_info *ri; 704 int np, nw, cnt, delta; 705 int32_t *dp, clr; 706 707 ri = (struct rasops_info *)cookie; 708 709 #ifdef RASOPS_CLIPPING 710 if (row < 0) { 711 num += row; 712 row = 0; 713 } 714 715 if ((row + num) > ri->ri_rows) 716 num = ri->ri_rows - row; 717 718 if (num <= 0) 719 return; 720 #endif 721 722 clr = ri->ri_devcmap[(attr >> 16) & 0xf]; 723 724 /* 725 * XXX The wsdisplay_emulops interface seems a little deficient in 726 * that there is no way to clear the *entire* screen. We provide a 727 * workaround here: if the entire console area is being cleared, and 728 * the RI_FULLCLEAR flag is set, clear the entire display. 729 */ 730 if (num == ri->ri_rows && (ri->ri_flg & RI_FULLCLEAR) != 0) { 731 np = ri->ri_stride >> 5; 732 nw = (ri->ri_stride >> 2) & 7; 733 num = ri->ri_height; 734 dp = (int32_t *)ri->ri_origbits; 735 delta = 0; 736 } else { 737 np = ri->ri_emustride >> 5; 738 nw = (ri->ri_emustride >> 2) & 7; 739 num *= ri->ri_font->fontheight; 740 dp = (int32_t *)(ri->ri_bits + row * ri->ri_yscale); 741 delta = ri->ri_delta; 742 } 743 744 while (num--) { 745 for (cnt = np; cnt; cnt--) { 746 dp[0] = clr; 747 dp[1] = clr; 748 dp[2] = clr; 749 dp[3] = clr; 750 dp[4] = clr; 751 dp[5] = clr; 752 dp[6] = clr; 753 dp[7] = clr; 754 dp += 8; 755 } 756 757 for (cnt = nw; cnt; cnt--) { 758 *(int32_t *)dp = clr; 759 DELTA(dp, 4, int32_t *); 760 } 761 762 DELTA(dp, delta, int32_t *); 763 } 764 } 765 766 /* 767 * Actually turn the cursor on or off. This does the dirty work for 768 * rasops_cursor(). 769 */ 770 static void 771 rasops_do_cursor(ri) 772 struct rasops_info *ri; 773 { 774 int full1, height, cnt, slop1, slop2, row, col; 775 u_char *dp, *rp; 776 777 row = ri->ri_crow; 778 col = ri->ri_ccol; 779 780 rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale; 781 height = ri->ri_font->fontheight; 782 slop1 = (4 - ((long)rp & 3)) & 3; 783 784 if (slop1 > ri->ri_xscale) 785 slop1 = ri->ri_xscale; 786 787 slop2 = (ri->ri_xscale - slop1) & 3; 788 full1 = (ri->ri_xscale - slop1 - slop2) >> 2; 789 790 if ((slop1 | slop2) == 0) { 791 /* A common case */ 792 while (height--) { 793 dp = rp; 794 rp += ri->ri_stride; 795 796 for (cnt = full1; cnt; cnt--) { 797 *(int32_t *)dp ^= ~0; 798 dp += 4; 799 } 800 } 801 } else { 802 /* XXX this is stupid.. use masks instead */ 803 while (height--) { 804 dp = rp; 805 rp += ri->ri_stride; 806 807 if (slop1 & 1) 808 *dp++ ^= ~0; 809 810 if (slop1 & 2) { 811 *(int16_t *)dp ^= ~0; 812 dp += 2; 813 } 814 815 for (cnt = full1; cnt; cnt--) { 816 *(int32_t *)dp ^= ~0; 817 dp += 4; 818 } 819 820 if (slop2 & 1) 821 *dp++ ^= ~0; 822 823 if (slop2 & 2) 824 *(int16_t *)dp ^= ~0; 825 } 826 } 827 } 828 829 /* 830 * Erase columns. 831 */ 832 void 833 rasops_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) & 0xf]; 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 - ((long)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