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