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