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