1 /* $OpenBSD: rasops.c,v 1.1 2001/03/18 04:32:44 nate 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 <sys/cdefs.h> 41 //__KERNEL_RCSID(0, "$NetBSD: rasops.c,v 1.35 2001/02/02 06:01:01 marcus Exp $"); 42 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 ((long)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_width * bpp >> 3) - 238 ri->ri_emustride) >> 1) & ~3; 239 ri->ri_bits += ((ri->ri_height - ri->ri_emuheight) >> 1) * 240 ri->ri_stride; 241 242 ri->ri_yorigin = (int)(ri->ri_bits - ri->ri_origbits) 243 / ri->ri_stride; 244 ri->ri_xorigin = (((int)(ri->ri_bits - ri->ri_origbits) 245 % ri->ri_stride) * 8 / bpp); 246 } else 247 ri->ri_xorigin = ri->ri_yorigin = 0; 248 249 /* 250 * Fill in defaults for operations set. XXX this nukes private 251 * routines used by accelerated fb drivers. 252 */ 253 ri->ri_ops.mapchar = rasops_mapchar; 254 ri->ri_ops.copyrows = rasops_copyrows; 255 ri->ri_ops.copycols = rasops_copycols; 256 ri->ri_ops.erasecols = rasops_erasecols; 257 ri->ri_ops.eraserows = rasops_eraserows; 258 ri->ri_ops.cursor = rasops_cursor; 259 ri->ri_do_cursor = rasops_do_cursor; 260 261 if (ri->ri_depth < 8 || (ri->ri_flg & RI_FORCEMONO) != 0) { 262 ri->ri_ops.alloc_attr = rasops_alloc_mattr; 263 ri->ri_caps = WSSCREEN_UNDERLINE | WSSCREEN_REVERSE; 264 } else { 265 ri->ri_ops.alloc_attr = rasops_alloc_cattr; 266 ri->ri_caps = WSSCREEN_UNDERLINE | WSSCREEN_HILIT | 267 WSSCREEN_WSCOLORS | WSSCREEN_REVERSE; 268 } 269 270 switch (ri->ri_depth) { 271 #if NRASOPS1 > 0 272 case 1: 273 rasops1_init(ri); 274 break; 275 #endif 276 #if NRASOPS2 > 0 277 case 2: 278 rasops2_init(ri); 279 break; 280 #endif 281 #if NRASOPS4 > 0 282 case 4: 283 rasops4_init(ri); 284 break; 285 #endif 286 #if NRASOPS8 > 0 287 case 8: 288 rasops8_init(ri); 289 break; 290 #endif 291 #if NRASOPS15 > 0 || NRASOPS16 > 0 292 case 15: 293 case 16: 294 rasops15_init(ri); 295 break; 296 #endif 297 #if NRASOPS24 > 0 298 case 24: 299 rasops24_init(ri); 300 break; 301 #endif 302 #if NRASOPS32 > 0 303 case 32: 304 rasops32_init(ri); 305 break; 306 #endif 307 default: 308 ri->ri_flg &= ~RI_CFGDONE; 309 splx(s); 310 return (-1); 311 } 312 313 ri->ri_flg |= RI_CFGDONE; 314 splx(s); 315 return (0); 316 } 317 318 /* 319 * Map a character. 320 */ 321 static int 322 rasops_mapchar(cookie, c, cp) 323 void *cookie; 324 int c; 325 u_int *cp; 326 { 327 struct rasops_info *ri; 328 329 ri = (struct rasops_info *)cookie; 330 331 #ifdef DIAGNOSTIC 332 if (ri->ri_font == NULL) 333 panic("rasops_mapchar: no font selected\n"); 334 #endif 335 if (ri->ri_font->encoding != WSDISPLAY_FONTENC_ISO) { 336 337 if ( (c = wsfont_map_unichar(ri->ri_font, c)) < 0) { 338 339 *cp = ' '; 340 return (0); 341 342 } 343 } 344 345 346 if (c < ri->ri_font->firstchar) { 347 *cp = ' '; 348 return (0); 349 } 350 351 if (c - ri->ri_font->firstchar >= ri->ri_font->numchars) { 352 *cp = ' '; 353 return (0); 354 } 355 356 *cp = c; 357 return (5); 358 } 359 360 /* 361 * Allocate a color attribute. 362 */ 363 static int 364 rasops_alloc_cattr(cookie, fg, bg, flg, attr) 365 void *cookie; 366 int fg, bg, flg; 367 long *attr; 368 { 369 int swap; 370 371 #ifdef RASOPS_CLIPPING 372 fg &= 7; 373 bg &= 7; 374 #endif 375 if ((flg & WSATTR_BLINK) != 0) 376 return (EINVAL); 377 378 if ((flg & WSATTR_WSCOLORS) == 0) { 379 fg = WSCOL_WHITE; 380 bg = WSCOL_BLACK; 381 } 382 383 if ((flg & WSATTR_REVERSE) != 0) { 384 swap = fg; 385 fg = bg; 386 bg = swap; 387 } 388 389 if ((flg & WSATTR_HILIT) != 0) 390 fg += 8; 391 392 flg = ((flg & WSATTR_UNDERLINE) ? 1 : 0); 393 394 if (rasops_isgray[fg]) 395 flg |= 2; 396 397 if (rasops_isgray[bg]) 398 flg |= 4; 399 400 *attr = (bg << 16) | (fg << 24) | flg; 401 return (0); 402 } 403 404 /* 405 * Allocate a mono attribute. 406 */ 407 static int 408 rasops_alloc_mattr(cookie, fg, bg, flg, attr) 409 void *cookie; 410 int fg, bg, flg; 411 long *attr; 412 { 413 int swap; 414 415 if ((flg & (WSATTR_BLINK | WSATTR_HILIT | WSATTR_WSCOLORS)) != 0) 416 return (EINVAL); 417 418 fg = 1; 419 bg = 0; 420 421 if ((flg & WSATTR_REVERSE) != 0) { 422 swap = fg; 423 fg = bg; 424 bg = swap; 425 } 426 427 *attr = (bg << 16) | (fg << 24) | ((flg & WSATTR_UNDERLINE) ? 7 : 6); 428 return (0); 429 } 430 431 /* 432 * Copy rows. 433 */ 434 static void 435 rasops_copyrows(cookie, src, dst, num) 436 void *cookie; 437 int src, dst, num; 438 { 439 int32_t *sp, *dp, *srp, *drp; 440 struct rasops_info *ri; 441 int n8, n1, cnt, delta; 442 443 ri = (struct rasops_info *)cookie; 444 445 #ifdef RASOPS_CLIPPING 446 if (dst == src) 447 return; 448 449 if (src < 0) { 450 num += src; 451 src = 0; 452 } 453 454 if ((src + num) > ri->ri_rows) 455 num = ri->ri_rows - src; 456 457 if (dst < 0) { 458 num += dst; 459 dst = 0; 460 } 461 462 if ((dst + num) > ri->ri_rows) 463 num = ri->ri_rows - dst; 464 465 if (num <= 0) 466 return; 467 #endif 468 469 num *= ri->ri_font->fontheight; 470 n8 = ri->ri_emustride >> 5; 471 n1 = (ri->ri_emustride >> 2) & 7; 472 473 if (dst < src) { 474 srp = (int32_t *)(ri->ri_bits + src * ri->ri_yscale); 475 drp = (int32_t *)(ri->ri_bits + dst * ri->ri_yscale); 476 delta = ri->ri_stride; 477 } else { 478 src = ri->ri_font->fontheight * src + num - 1; 479 dst = ri->ri_font->fontheight * dst + num - 1; 480 srp = (int32_t *)(ri->ri_bits + src * ri->ri_stride); 481 drp = (int32_t *)(ri->ri_bits + dst * ri->ri_stride); 482 delta = -ri->ri_stride; 483 } 484 485 while (num--) { 486 dp = drp; 487 sp = srp; 488 DELTA(drp, delta, int32_t *); 489 DELTA(srp, delta, int32_t *); 490 491 for (cnt = n8; cnt; cnt--) { 492 dp[0] = sp[0]; 493 dp[1] = sp[1]; 494 dp[2] = sp[2]; 495 dp[3] = sp[3]; 496 dp[4] = sp[4]; 497 dp[5] = sp[5]; 498 dp[6] = sp[6]; 499 dp[7] = sp[7]; 500 dp += 8; 501 sp += 8; 502 } 503 504 for (cnt = n1; cnt; cnt--) 505 *dp++ = *sp++; 506 } 507 } 508 509 /* 510 * Copy columns. This is slow, and hard to optimize due to alignment, 511 * and the fact that we have to copy both left->right and right->left. 512 * We simply cop-out here and use bcopy(), since it handles all of 513 * these cases anyway. 514 */ 515 void 516 rasops_copycols(cookie, row, src, dst, num) 517 void *cookie; 518 int row, src, dst, num; 519 { 520 struct rasops_info *ri; 521 u_char *sp, *dp; 522 int height; 523 524 ri = (struct rasops_info *)cookie; 525 526 #ifdef RASOPS_CLIPPING 527 if (dst == src) 528 return; 529 530 /* Catches < 0 case too */ 531 if ((unsigned)row >= (unsigned)ri->ri_rows) 532 return; 533 534 if (src < 0) { 535 num += src; 536 src = 0; 537 } 538 539 if ((src + num) > ri->ri_cols) 540 num = ri->ri_cols - src; 541 542 if (dst < 0) { 543 num += dst; 544 dst = 0; 545 } 546 547 if ((dst + num) > ri->ri_cols) 548 num = ri->ri_cols - dst; 549 550 if (num <= 0) 551 return; 552 #endif 553 554 num *= ri->ri_xscale; 555 row *= ri->ri_yscale; 556 height = ri->ri_font->fontheight; 557 558 sp = ri->ri_bits + row + src * ri->ri_xscale; 559 dp = ri->ri_bits + row + dst * ri->ri_xscale; 560 561 while (height--) { 562 bcopy(sp, dp, num); 563 dp += ri->ri_stride; 564 sp += ri->ri_stride; 565 } 566 } 567 568 /* 569 * Turn cursor off/on. 570 */ 571 static void 572 rasops_cursor(cookie, on, row, col) 573 void *cookie; 574 int on, row, col; 575 { 576 struct rasops_info *ri; 577 578 ri = (struct rasops_info *)cookie; 579 580 /* Turn old cursor off */ 581 if ((ri->ri_flg & RI_CURSOR) != 0) 582 #ifdef RASOPS_CLIPPING 583 if ((ri->ri_flg & RI_CURSORCLIP) == 0) 584 #endif 585 ri->ri_do_cursor(ri); 586 587 /* Select new cursor */ 588 #ifdef RASOPS_CLIPPING 589 ri->ri_flg &= ~RI_CURSORCLIP; 590 591 if (row < 0 || row >= ri->ri_rows) 592 ri->ri_flg |= RI_CURSORCLIP; 593 else if (col < 0 || col >= ri->ri_cols) 594 ri->ri_flg |= RI_CURSORCLIP; 595 #endif 596 ri->ri_crow = row; 597 ri->ri_ccol = col; 598 599 if (on) { 600 ri->ri_flg |= RI_CURSOR; 601 #ifdef RASOPS_CLIPPING 602 if ((ri->ri_flg & RI_CURSORCLIP) == 0) 603 #endif 604 ri->ri_do_cursor(ri); 605 } else 606 ri->ri_flg &= ~RI_CURSOR; 607 } 608 609 /* 610 * Make the device colormap 611 */ 612 static void 613 rasops_init_devcmap(ri) 614 struct rasops_info *ri; 615 { 616 const u_char *p; 617 int i, c; 618 619 switch (ri->ri_depth) { 620 case 1: 621 ri->ri_devcmap[0] = 0; 622 for (i = 1; i < 16; i++) 623 ri->ri_devcmap[i] = -1; 624 return; 625 626 case 2: 627 for (i = 1; i < 15; i++) 628 ri->ri_devcmap[i] = 0xaaaaaaaa; 629 630 ri->ri_devcmap[0] = 0; 631 ri->ri_devcmap[8] = 0x55555555; 632 ri->ri_devcmap[15] = -1; 633 return; 634 635 case 8: 636 for (i = 0; i < 16; i++) 637 ri->ri_devcmap[i] = i | (i<<8) | (i<<16) | (i<<24); 638 return; 639 } 640 641 p = rasops_cmap; 642 643 for (i = 0; i < 16; i++) { 644 if (ri->ri_rnum <= 8) 645 c = (*p >> (8 - ri->ri_rnum)) << ri->ri_rpos; 646 else 647 c = (*p << (ri->ri_rnum - 8)) << ri->ri_rpos; 648 p++; 649 650 if (ri->ri_gnum <= 8) 651 c |= (*p >> (8 - ri->ri_gnum)) << ri->ri_gpos; 652 else 653 c |= (*p << (ri->ri_gnum - 8)) << ri->ri_gpos; 654 p++; 655 656 if (ri->ri_bnum <= 8) 657 c |= (*p >> (8 - ri->ri_bnum)) << ri->ri_bpos; 658 else 659 c |= (*p << (ri->ri_bnum - 8)) << ri->ri_bpos; 660 p++; 661 662 /* Fill the word for generic routines, which want this */ 663 if (ri->ri_depth == 24) 664 c = c | ((c & 0xff) << 24); 665 else if (ri->ri_depth <= 16) 666 c = c | (c << 16); 667 668 /* 24bpp does bswap on the fly. {32,16,15}bpp do it here. */ 669 if ((ri->ri_flg & RI_BSWAP) == 0) 670 ri->ri_devcmap[i] = c; 671 else if (ri->ri_depth == 32) 672 ri->ri_devcmap[i] = swap32(c); 673 else if (ri->ri_depth == 16 || ri->ri_depth == 15) 674 ri->ri_devcmap[i] = swap16(c); 675 else 676 ri->ri_devcmap[i] = c; 677 } 678 } 679 680 /* 681 * Unpack a rasops attribute 682 */ 683 void 684 rasops_unpack_attr(attr, fg, bg, underline) 685 long attr; 686 int *fg, *bg, *underline; 687 { 688 689 *fg = ((u_int)attr >> 24) & 0xf; 690 *bg = ((u_int)attr >> 16) & 0xf; 691 if (underline != NULL) 692 *underline = (u_int)attr & 1; 693 } 694 695 /* 696 * Erase rows. This isn't static, since 24-bpp uses it in special cases. 697 */ 698 void 699 rasops_eraserows(cookie, row, num, attr) 700 void *cookie; 701 int row, num; 702 long attr; 703 { 704 struct rasops_info *ri; 705 int np, nw, cnt, delta; 706 int32_t *dp, clr; 707 708 ri = (struct rasops_info *)cookie; 709 710 #ifdef RASOPS_CLIPPING 711 if (row < 0) { 712 num += row; 713 row = 0; 714 } 715 716 if ((row + num) > ri->ri_rows) 717 num = ri->ri_rows - row; 718 719 if (num <= 0) 720 return; 721 #endif 722 723 clr = ri->ri_devcmap[(attr >> 16) & 0xf]; 724 725 /* 726 * XXX The wsdisplay_emulops interface seems a little deficient in 727 * that there is no way to clear the *entire* screen. We provide a 728 * workaround here: if the entire console area is being cleared, and 729 * the RI_FULLCLEAR flag is set, clear the entire display. 730 */ 731 if (num == ri->ri_rows && (ri->ri_flg & RI_FULLCLEAR) != 0) { 732 np = ri->ri_stride >> 5; 733 nw = (ri->ri_stride >> 2) & 7; 734 num = ri->ri_height; 735 dp = (int32_t *)ri->ri_origbits; 736 delta = 0; 737 } else { 738 np = ri->ri_emustride >> 5; 739 nw = (ri->ri_emustride >> 2) & 7; 740 num *= ri->ri_font->fontheight; 741 dp = (int32_t *)(ri->ri_bits + row * ri->ri_yscale); 742 delta = ri->ri_delta; 743 } 744 745 while (num--) { 746 for (cnt = np; cnt; cnt--) { 747 dp[0] = clr; 748 dp[1] = clr; 749 dp[2] = clr; 750 dp[3] = clr; 751 dp[4] = clr; 752 dp[5] = clr; 753 dp[6] = clr; 754 dp[7] = clr; 755 dp += 8; 756 } 757 758 for (cnt = nw; cnt; cnt--) { 759 *(int32_t *)dp = clr; 760 DELTA(dp, 4, int32_t *); 761 } 762 763 DELTA(dp, delta, int32_t *); 764 } 765 } 766 767 /* 768 * Actually turn the cursor on or off. This does the dirty work for 769 * rasops_cursor(). 770 */ 771 static void 772 rasops_do_cursor(ri) 773 struct rasops_info *ri; 774 { 775 int full1, height, cnt, slop1, slop2, row, col; 776 u_char *dp, *rp; 777 778 row = ri->ri_crow; 779 col = ri->ri_ccol; 780 781 rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale; 782 height = ri->ri_font->fontheight; 783 slop1 = (4 - ((long)rp & 3)) & 3; 784 785 if (slop1 > ri->ri_xscale) 786 slop1 = ri->ri_xscale; 787 788 slop2 = (ri->ri_xscale - slop1) & 3; 789 full1 = (ri->ri_xscale - slop1 - slop2) >> 2; 790 791 if ((slop1 | slop2) == 0) { 792 /* A common case */ 793 while (height--) { 794 dp = rp; 795 rp += ri->ri_stride; 796 797 for (cnt = full1; cnt; cnt--) { 798 *(int32_t *)dp ^= ~0; 799 dp += 4; 800 } 801 } 802 } else { 803 /* XXX this is stupid.. use masks instead */ 804 while (height--) { 805 dp = rp; 806 rp += ri->ri_stride; 807 808 if (slop1 & 1) 809 *dp++ ^= ~0; 810 811 if (slop1 & 2) { 812 *(int16_t *)dp ^= ~0; 813 dp += 2; 814 } 815 816 for (cnt = full1; cnt; cnt--) { 817 *(int32_t *)dp ^= ~0; 818 dp += 4; 819 } 820 821 if (slop2 & 1) 822 *dp++ ^= ~0; 823 824 if (slop2 & 2) 825 *(int16_t *)dp ^= ~0; 826 } 827 } 828 } 829 830 /* 831 * Erase columns. 832 */ 833 void 834 rasops_erasecols(cookie, row, col, num, attr) 835 void *cookie; 836 int row, col, num; 837 long attr; 838 { 839 int n8, height, cnt, slop1, slop2, clr; 840 struct rasops_info *ri; 841 int32_t *rp, *dp; 842 843 ri = (struct rasops_info *)cookie; 844 845 #ifdef RASOPS_CLIPPING 846 if ((unsigned)row >= (unsigned)ri->ri_rows) 847 return; 848 849 if (col < 0) { 850 num += col; 851 col = 0; 852 } 853 854 if ((col + num) > ri->ri_cols) 855 num = ri->ri_cols - col; 856 857 if (num <= 0) 858 return; 859 #endif 860 861 num = num * ri->ri_xscale; 862 rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale); 863 height = ri->ri_font->fontheight; 864 clr = ri->ri_devcmap[(attr >> 16) & 0xf]; 865 866 /* Don't bother using the full loop for <= 32 pels */ 867 if (num <= 32) { 868 if (((num | ri->ri_xscale) & 3) == 0) { 869 /* Word aligned blt */ 870 num >>= 2; 871 872 while (height--) { 873 dp = rp; 874 DELTA(rp, ri->ri_stride, int32_t *); 875 876 for (cnt = num; cnt; cnt--) 877 *dp++ = clr; 878 } 879 } else if (((num | ri->ri_xscale) & 1) == 0) { 880 /* 881 * Halfword aligned blt. This is needed so the 882 * 15/16 bit ops can use this function. 883 */ 884 num >>= 1; 885 886 while (height--) { 887 dp = rp; 888 DELTA(rp, ri->ri_stride, int32_t *); 889 890 for (cnt = num; cnt; cnt--) { 891 *(int16_t *)dp = clr; 892 DELTA(dp, 2, int32_t *); 893 } 894 } 895 } else { 896 while (height--) { 897 dp = rp; 898 DELTA(rp, ri->ri_stride, int32_t *); 899 900 for (cnt = num; cnt; cnt--) { 901 *(u_char *)dp = clr; 902 DELTA(dp, 1, int32_t *); 903 } 904 } 905 } 906 907 return; 908 } 909 910 slop1 = (4 - ((long)rp & 3)) & 3; 911 slop2 = (num - slop1) & 3; 912 num -= slop1 + slop2; 913 n8 = num >> 5; 914 num = (num >> 2) & 7; 915 916 while (height--) { 917 dp = rp; 918 DELTA(rp, ri->ri_stride, int32_t *); 919 920 /* Align span to 4 bytes */ 921 if (slop1 & 1) { 922 *(u_char *)dp = clr; 923 DELTA(dp, 1, int32_t *); 924 } 925 926 if (slop1 & 2) { 927 *(int16_t *)dp = clr; 928 DELTA(dp, 2, int32_t *); 929 } 930 931 /* Write 32 bytes per loop */ 932 for (cnt = n8; cnt; cnt--) { 933 dp[0] = clr; 934 dp[1] = clr; 935 dp[2] = clr; 936 dp[3] = clr; 937 dp[4] = clr; 938 dp[5] = clr; 939 dp[6] = clr; 940 dp[7] = clr; 941 dp += 8; 942 } 943 944 /* Write 4 bytes per loop */ 945 for (cnt = num; cnt; cnt--) 946 *dp++ = clr; 947 948 /* Write unaligned trailing slop */ 949 if (slop2 & 1) { 950 *(u_char *)dp = clr; 951 DELTA(dp, 1, int32_t *); 952 } 953 954 if (slop2 & 2) 955 *(int16_t *)dp = clr; 956 } 957 } 958