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