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