rasops.c revision 1.70
1/* $NetBSD: rasops.c,v 1.70 2012/01/11 15:52:32 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 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32#include <sys/cdefs.h> 33__KERNEL_RCSID(0, "$NetBSD: rasops.c,v 1.70 2012/01/11 15:52:32 macallan Exp $"); 34 35#include "opt_rasops.h" 36#include "rasops_glue.h" 37#include "opt_wsmsgattrs.h" 38 39#include <sys/param.h> 40#include <sys/systm.h> 41#include <sys/time.h> 42#include <sys/kmem.h> 43 44#include <sys/bswap.h> 45#include <machine/endian.h> 46 47#include <dev/wscons/wsdisplayvar.h> 48#include <dev/wscons/wsconsio.h> 49#include <dev/wsfont/wsfont.h> 50#include <dev/rasops/rasops.h> 51 52#ifndef _KERNEL 53#include <errno.h> 54#endif 55 56#ifdef RASOPS_DEBUG 57#define DPRINTF aprint_error 58#else 59#define DPRINTF while (0) printf 60#endif 61 62struct rasops_matchdata { 63 struct rasops_info *ri; 64 int wantcols, wantrows; 65 int bestscore; 66 struct wsdisplay_font *pick; 67 int ident; 68}; 69 70/* ANSI colormap (R,G,B). Upper 8 are high-intensity */ 71const u_char rasops_cmap[256*3] = { 72 0x00, 0x00, 0x00, /* black */ 73 0x7f, 0x00, 0x00, /* red */ 74 0x00, 0x7f, 0x00, /* green */ 75 0x7f, 0x7f, 0x00, /* brown */ 76 0x00, 0x00, 0x7f, /* blue */ 77 0x7f, 0x00, 0x7f, /* magenta */ 78 0x00, 0x7f, 0x7f, /* cyan */ 79 0xc7, 0xc7, 0xc7, /* white - XXX too dim? */ 80 81 0x7f, 0x7f, 0x7f, /* black */ 82 0xff, 0x00, 0x00, /* red */ 83 0x00, 0xff, 0x00, /* green */ 84 0xff, 0xff, 0x00, /* brown */ 85 0x00, 0x00, 0xff, /* blue */ 86 0xff, 0x00, 0xff, /* magenta */ 87 0x00, 0xff, 0xff, /* cyan */ 88 0xff, 0xff, 0xff, /* white */ 89 90 /* 91 * For the cursor, we need at least the last (255th) 92 * color to be white. Fill up white completely for 93 * simplicity. 94 */ 95#define _CMWHITE 0xff, 0xff, 0xff, 96#define _CMWHITE16 _CMWHITE _CMWHITE _CMWHITE _CMWHITE \ 97 _CMWHITE _CMWHITE _CMWHITE _CMWHITE \ 98 _CMWHITE _CMWHITE _CMWHITE _CMWHITE \ 99 _CMWHITE _CMWHITE _CMWHITE _CMWHITE 100 _CMWHITE16 _CMWHITE16 _CMWHITE16 _CMWHITE16 _CMWHITE16 101 _CMWHITE16 _CMWHITE16 _CMWHITE16 _CMWHITE16 _CMWHITE16 102 _CMWHITE16 _CMWHITE16 _CMWHITE16 _CMWHITE16 /* but not the last one */ 103#undef _CMWHITE16 104#undef _CMWHITE 105 106 /* 107 * For the cursor the fg/bg indices are bit inverted, so 108 * provide complimentary colors in the upper 16 entries. 109 */ 110 0x7f, 0x7f, 0x7f, /* black */ 111 0xff, 0x00, 0x00, /* red */ 112 0x00, 0xff, 0x00, /* green */ 113 0xff, 0xff, 0x00, /* brown */ 114 0x00, 0x00, 0xff, /* blue */ 115 0xff, 0x00, 0xff, /* magenta */ 116 0x00, 0xff, 0xff, /* cyan */ 117 0xff, 0xff, 0xff, /* white */ 118 119 0x00, 0x00, 0x00, /* black */ 120 0x7f, 0x00, 0x00, /* red */ 121 0x00, 0x7f, 0x00, /* green */ 122 0x7f, 0x7f, 0x00, /* brown */ 123 0x00, 0x00, 0x7f, /* blue */ 124 0x7f, 0x00, 0x7f, /* magenta */ 125 0x00, 0x7f, 0x7f, /* cyan */ 126 0xc7, 0xc7, 0xc7, /* white - XXX too dim? */ 127}; 128 129/* True if color is gray */ 130const u_char rasops_isgray[16] = { 131 1, 0, 0, 0, 132 0, 0, 0, 1, 133 1, 0, 0, 0, 134 0, 0, 0, 1 135}; 136 137/* Generic functions */ 138static void rasops_copyrows(void *, int, int, int); 139static int rasops_mapchar(void *, int, u_int *); 140static void rasops_cursor(void *, int, int, int); 141static int rasops_allocattr_color(void *, int, int, int, long *); 142static int rasops_allocattr_mono(void *, int, int, int, long *); 143static void rasops_do_cursor(struct rasops_info *); 144static void rasops_init_devcmap(struct rasops_info *); 145 146#if NRASOPS_ROTATION > 0 147static void rasops_rotate_font(int *, int); 148static void rasops_copychar(void *, int, int, int, int); 149 150/* rotate clockwise */ 151static void rasops_copycols_rotated_cw(void *, int, int, int, int); 152static void rasops_copyrows_rotated_cw(void *, int, int, int); 153static void rasops_erasecols_rotated_cw(void *, int, int, int, long); 154static void rasops_eraserows_rotated_cw(void *, int, int, long); 155static void rasops_putchar_rotated_cw(void *, int, int, u_int, long); 156 157/* rotate counter-clockwise */ 158static void rasops_copychar_ccw(void *, int, int, int, int); 159static void rasops_copycols_rotated_ccw(void *, int, int, int, int); 160static void rasops_copyrows_rotated_ccw(void *, int, int, int); 161#define rasops_erasecols_rotated_ccw rasops_erasecols_rotated_cw 162#define rasops_eraserows_rotated_ccw rasops_eraserows_rotated_cw 163static void rasops_putchar_rotated_ccw(void *, int, int, u_int, long); 164 165/* 166 * List of all rotated fonts 167 */ 168SLIST_HEAD(, rotatedfont) rotatedfonts = SLIST_HEAD_INITIALIZER(rotatedfonts); 169struct rotatedfont { 170 SLIST_ENTRY(rotatedfont) rf_next; 171 int rf_cookie; 172 int rf_rotated; 173}; 174#endif /* NRASOPS_ROTATION > 0 */ 175 176void rasops_make_box_chars_8(struct rasops_info *); 177void rasops_make_box_chars_16(struct rasops_info *); 178void rasops_make_box_chars_32(struct rasops_info *); 179void rasops_make_box_chars_alpha(struct rasops_info *); 180 181extern int cold; 182 183/* 184 * Rate a font based on how many character cells we would get out of it in the 185 * current video mode. Lower is better. 186 */ 187static void 188rasops_matches(struct wsdisplay_font *font, void *cookie, int ident) 189{ 190 struct rasops_matchdata *md = cookie; 191 struct rasops_info *ri = md->ri; 192 int cols, score = 1; 193 194 /* first weed out fonts the caller doesn't claim support for */ 195 if (FONT_IS_ALPHA(font)) { 196 /* 197 * If we end up with a bitmap font and an alpha font with 198 * otherwise identical scores, prefer alpha 199 */ 200 score = 0; 201 if ((ri->ri_flg & RI_ENABLE_ALPHA) == 0) 202 return; 203 } 204 cols = ri->ri_width / font->fontwidth; 205 /* 206 * if the font is too small to allow 80 columns give those closer to 207 * 80 a better score but with a huge penalty compared to fonts that 208 * give us 80 columns or more 209 */ 210 if (cols < md->wantcols) { 211 score += 100000 + 2 * (md->wantcols - cols); 212 } else 213 score += 2 * cols; 214 DPRINTF("%s: %d\n", font->name, score); 215 if (score < md->bestscore) { 216 md->bestscore = score; 217 md->pick = font; 218 md->ident = ident; 219 } 220} 221 222static int 223rasops_find(struct rasops_info *ri, int wantrows, int wantcols) 224{ 225 struct rasops_matchdata md = 226 { ri, wantcols, wantrows, 1000000, NULL, 0}; 227 228 wsfont_walk(rasops_matches, &md); 229 if (md.pick == NULL) 230 return -1; 231 return (wsfont_make_cookie(md.ident, WSDISPLAY_FONTORDER_L2R, 232 WSDISPLAY_FONTORDER_L2R)); 233} 234/* 235 * Initialize a 'rasops_info' descriptor. 236 */ 237int 238rasops_init(struct rasops_info *ri, int wantrows, int wantcols) 239{ 240 241 memset (&ri->ri_optfont, 0, sizeof(ri->ri_optfont)); 242#ifdef _KERNEL 243 /* Select a font if the caller doesn't care */ 244 if (ri->ri_font == NULL) { 245 int cookie = -1; 246 247 wsfont_init(); 248 249 /* 250 * first, try to find something that's as close as possible 251 * to the caller's requested terminal size 252 */ 253 if (wantrows == 0) 254 wantrows = RASOPS_DEFAULT_HEIGHT; 255 if (wantcols == 0) 256 wantcols = RASOPS_DEFAULT_WIDTH; 257 cookie = rasops_find(ri, wantrows, wantcols); 258 259 /* 260 * this means there is no supported font in the list 261 */ 262 if (cookie <= 0) { 263 aprint_error("rasops_init: font table is empty\n"); 264 return (-1); 265 } 266 267#if NRASOPS_ROTATION > 0 268 /* 269 * Pick the rotated version of this font. This will create it 270 * if necessary. 271 */ 272 if (ri->ri_flg & RI_ROTATE_MASK) { 273 if (ri->ri_flg & RI_ROTATE_CW) 274 rasops_rotate_font(&cookie, WSFONT_ROTATE_CW); 275 else if (ri->ri_flg & RI_ROTATE_CCW) 276 rasops_rotate_font(&cookie, WSFONT_ROTATE_CCW); 277 } 278#endif 279 280 if (wsfont_lock(cookie, &ri->ri_font)) { 281 aprint_error("rasops_init: couldn't lock font\n"); 282 return (-1); 283 } 284 285 ri->ri_wsfcookie = cookie; 286 } 287#endif 288 289 /* This should never happen in reality... */ 290#ifdef DEBUG 291 if ((long)ri->ri_bits & 3) { 292 aprint_error("rasops_init: bits not aligned on 32-bit boundary\n"); 293 return (-1); 294 } 295 296 if ((int)ri->ri_stride & 3) { 297 aprint_error("rasops_init: stride not aligned on 32-bit boundary\n"); 298 return (-1); 299 } 300#endif 301 302 if (rasops_reconfig(ri, wantrows, wantcols)) 303 return (-1); 304 305 rasops_init_devcmap(ri); 306 return (0); 307} 308 309/* 310 * Reconfigure (because parameters have changed in some way). 311 */ 312int 313rasops_reconfig(struct rasops_info *ri, int wantrows, int wantcols) 314{ 315 int bpp, s, len; 316 317 s = splhigh(); 318 319 if (wantrows == 0) 320 wantrows = RASOPS_DEFAULT_HEIGHT; 321 if (wantcols == 0) 322 wantcols = RASOPS_DEFAULT_WIDTH; 323 324 /* throw away old line drawing character bitmaps, if we have any */ 325 if (ri->ri_optfont.data != NULL) { 326 kmem_free(ri->ri_optfont.data, ri->ri_optfont.stride * 327 ri->ri_optfont.fontheight * ri->ri_optfont.numchars); 328 ri->ri_optfont.data = NULL; 329 } 330 331 /* autogenerate box drawing characters */ 332 ri->ri_optfont.firstchar = WSFONT_FLAG_OPT; 333 ri->ri_optfont.numchars = 16; 334 ri->ri_optfont.fontwidth = ri->ri_font->fontwidth; 335 ri->ri_optfont.fontheight = ri->ri_font->fontheight; 336 ri->ri_optfont.stride = ri->ri_font->stride; 337 len = ri->ri_optfont.fontheight * ri->ri_optfont.stride * 338 ri->ri_optfont.numchars; 339 340 if (((ri->ri_flg & RI_NO_AUTO) == 0) && 341 ((ri->ri_optfont.data = kmem_zalloc(len, KM_SLEEP)) != NULL)) { 342 343 if (ri->ri_optfont.stride < ri->ri_optfont.fontwidth) { 344 switch (ri->ri_optfont.stride) { 345 case 1: 346 rasops_make_box_chars_8(ri); 347 break; 348 case 2: 349 rasops_make_box_chars_16(ri); 350 break; 351 case 4: 352 rasops_make_box_chars_32(ri); 353 break; 354 } 355 } else { 356 rasops_make_box_chars_alpha(ri); 357 } 358 } else 359 memset(&ri->ri_optfont, 0, sizeof(ri->ri_optfont)); 360 361 if (ri->ri_font->fontwidth > 32 || ri->ri_font->fontwidth < 4) 362 panic("rasops_init: fontwidth assumptions botched!"); 363 364 /* Need this to frob the setup below */ 365 bpp = (ri->ri_depth == 15 ? 16 : ri->ri_depth); 366 367 if ((ri->ri_flg & RI_CFGDONE) != 0) 368 ri->ri_bits = ri->ri_origbits; 369 370 /* Don't care if the caller wants a hideously small console */ 371 if (wantrows < 10) 372 wantrows = 10; 373 374 if (wantcols < 20) 375 wantcols = 20; 376 377 /* Now constrain what they get */ 378 ri->ri_emuwidth = ri->ri_font->fontwidth * wantcols; 379 ri->ri_emuheight = ri->ri_font->fontheight * wantrows; 380 381 if (ri->ri_emuwidth > ri->ri_width) 382 ri->ri_emuwidth = ri->ri_width; 383 384 if (ri->ri_emuheight > ri->ri_height) 385 ri->ri_emuheight = ri->ri_height; 386 387 /* Reduce width until aligned on a 32-bit boundary */ 388 while ((ri->ri_emuwidth * bpp & 31) != 0) 389 ri->ri_emuwidth--; 390 391#if NRASOPS_ROTATION > 0 392 if (ri->ri_flg & (RI_ROTATE_CW|RI_ROTATE_CCW)) { 393 ri->ri_rows = ri->ri_emuwidth / ri->ri_font->fontwidth; 394 ri->ri_cols = ri->ri_emuheight / ri->ri_font->fontheight; 395 } else 396#endif 397 { 398 399 ri->ri_cols = ri->ri_emuwidth / ri->ri_font->fontwidth; 400 ri->ri_rows = ri->ri_emuheight / ri->ri_font->fontheight; 401 } 402 ri->ri_emustride = ri->ri_emuwidth * bpp >> 3; 403 ri->ri_delta = ri->ri_stride - ri->ri_emustride; 404 ri->ri_ccol = 0; 405 ri->ri_crow = 0; 406 ri->ri_pelbytes = bpp >> 3; 407 408 ri->ri_xscale = (ri->ri_font->fontwidth * bpp) >> 3; 409 ri->ri_yscale = ri->ri_font->fontheight * ri->ri_stride; 410 ri->ri_fontscale = ri->ri_font->fontheight * ri->ri_font->stride; 411 412#ifdef DEBUG 413 if ((ri->ri_delta & 3) != 0) 414 panic("rasops_init: ri_delta not aligned on 32-bit boundary"); 415#endif 416 /* Clear the entire display */ 417 if ((ri->ri_flg & RI_CLEAR) != 0) 418 memset(ri->ri_bits, 0, ri->ri_stride * ri->ri_height); 419 420 /* Now centre our window if needs be */ 421 ri->ri_origbits = ri->ri_bits; 422 ri->ri_hworigbits = ri->ri_hwbits; 423 424 if ((ri->ri_flg & RI_CENTER) != 0) { 425 ri->ri_bits += (((ri->ri_width * bpp >> 3) - 426 ri->ri_emustride) >> 1) & ~3; 427 ri->ri_bits += ((ri->ri_height - ri->ri_emuheight) >> 1) * 428 ri->ri_stride; 429 if (ri->ri_hwbits != NULL) { 430 ri->ri_hwbits += (((ri->ri_width * bpp >> 3) - 431 ri->ri_emustride) >> 1) & ~3; 432 ri->ri_hwbits += ((ri->ri_height - ri->ri_emuheight) >> 1) * 433 ri->ri_stride; 434 } 435 ri->ri_yorigin = (int)(ri->ri_bits - ri->ri_origbits) 436 / ri->ri_stride; 437 ri->ri_xorigin = (((int)(ri->ri_bits - ri->ri_origbits) 438 % ri->ri_stride) * 8 / bpp); 439 } else 440 ri->ri_xorigin = ri->ri_yorigin = 0; 441 442 /* 443 * Fill in defaults for operations set. XXX this nukes private 444 * routines used by accelerated fb drivers. 445 */ 446 ri->ri_ops.mapchar = rasops_mapchar; 447 ri->ri_ops.copyrows = rasops_copyrows; 448 ri->ri_ops.copycols = rasops_copycols; 449 ri->ri_ops.erasecols = rasops_erasecols; 450 ri->ri_ops.eraserows = rasops_eraserows; 451 ri->ri_ops.cursor = rasops_cursor; 452 ri->ri_do_cursor = rasops_do_cursor; 453 454 if (ri->ri_depth < 8 || (ri->ri_flg & RI_FORCEMONO) != 0) { 455 ri->ri_ops.allocattr = rasops_allocattr_mono; 456 ri->ri_caps = WSSCREEN_UNDERLINE | WSSCREEN_REVERSE; 457 } else { 458 ri->ri_ops.allocattr = rasops_allocattr_color; 459 ri->ri_caps = WSSCREEN_UNDERLINE | WSSCREEN_HILIT | 460 WSSCREEN_WSCOLORS | WSSCREEN_REVERSE; 461 } 462 463 switch (ri->ri_depth) { 464#if NRASOPS1 > 0 465 case 1: 466 rasops1_init(ri); 467 break; 468#endif 469#if NRASOPS2 > 0 470 case 2: 471 rasops2_init(ri); 472 break; 473#endif 474#if NRASOPS4 > 0 475 case 4: 476 rasops4_init(ri); 477 break; 478#endif 479#if NRASOPS8 > 0 480 case 8: 481 rasops8_init(ri); 482 break; 483#endif 484#if NRASOPS15 > 0 || NRASOPS16 > 0 485 case 15: 486 case 16: 487 rasops15_init(ri); 488 break; 489#endif 490#if NRASOPS24 > 0 491 case 24: 492 rasops24_init(ri); 493 break; 494#endif 495#if NRASOPS32 > 0 496 case 32: 497 rasops32_init(ri); 498 break; 499#endif 500 default: 501 ri->ri_flg &= ~RI_CFGDONE; 502 splx(s); 503 return (-1); 504 } 505 506#if NRASOPS_ROTATION > 0 507 if (ri->ri_flg & RI_ROTATE_MASK) { 508 if (ri->ri_flg & RI_ROTATE_CW) { 509 ri->ri_real_ops = ri->ri_ops; 510 ri->ri_ops.copycols = rasops_copycols_rotated_cw; 511 ri->ri_ops.copyrows = rasops_copyrows_rotated_cw; 512 ri->ri_ops.erasecols = rasops_erasecols_rotated_cw; 513 ri->ri_ops.eraserows = rasops_eraserows_rotated_cw; 514 ri->ri_ops.putchar = rasops_putchar_rotated_cw; 515 } else if (ri->ri_flg & RI_ROTATE_CCW) { 516 ri->ri_real_ops = ri->ri_ops; 517 ri->ri_ops.copycols = rasops_copycols_rotated_ccw; 518 ri->ri_ops.copyrows = rasops_copyrows_rotated_ccw; 519 ri->ri_ops.erasecols = rasops_erasecols_rotated_ccw; 520 ri->ri_ops.eraserows = rasops_eraserows_rotated_ccw; 521 ri->ri_ops.putchar = rasops_putchar_rotated_ccw; 522 } 523 } 524#endif 525 526 ri->ri_flg |= RI_CFGDONE; 527 splx(s); 528 return (0); 529} 530 531/* 532 * Map a character. 533 */ 534static int 535rasops_mapchar(void *cookie, int c, u_int *cp) 536{ 537 struct rasops_info *ri; 538 539 ri = (struct rasops_info *)cookie; 540 541#ifdef DIAGNOSTIC 542 if (ri->ri_font == NULL) 543 panic("rasops_mapchar: no font selected"); 544#endif 545 546 if ( (c = wsfont_map_unichar(ri->ri_font, c)) < 0) { 547 *cp = ' '; 548 return (0); 549 } 550 551 if (c < ri->ri_font->firstchar) { 552 *cp = ' '; 553 return (0); 554 } 555 556#if 0 557 if (c - ri->ri_font->firstchar >= ri->ri_font->numchars) { 558 *cp = ' '; 559 return (0); 560 } 561#endif 562 *cp = c; 563 return (5); 564} 565 566/* 567 * Allocate a color attribute. 568 */ 569static int 570rasops_allocattr_color(void *cookie, int fg, int bg, int flg, 571 long *attr) 572{ 573 int swap; 574 575 if (__predict_false((unsigned int)fg >= sizeof(rasops_isgray) || 576 (unsigned int)bg >= sizeof(rasops_isgray))) 577 return (EINVAL); 578 579#ifdef RASOPS_CLIPPING 580 fg &= 7; 581 bg &= 7; 582#endif 583 if ((flg & WSATTR_BLINK) != 0) 584 return (EINVAL); 585 586 if ((flg & WSATTR_WSCOLORS) == 0) { 587#ifdef WS_DEFAULT_FG 588 fg = WS_DEFAULT_FG; 589#else 590 fg = WSCOL_WHITE; 591#endif 592#ifdef WS_DEFAULT_BG 593 bg = WS_DEFAULT_BG; 594#else 595 bg = WSCOL_BLACK; 596#endif 597 } 598 599 if ((flg & WSATTR_REVERSE) != 0) { 600 swap = fg; 601 fg = bg; 602 bg = swap; 603 } 604 605 if ((flg & WSATTR_HILIT) != 0) 606 fg += 8; 607 608 flg = ((flg & WSATTR_UNDERLINE) ? 1 : 0); 609 610 if (rasops_isgray[fg]) 611 flg |= 2; 612 613 if (rasops_isgray[bg]) 614 flg |= 4; 615 616 *attr = (bg << 16) | (fg << 24) | flg; 617 return (0); 618} 619 620/* 621 * Allocate a mono attribute. 622 */ 623static int 624rasops_allocattr_mono(void *cookie, int fg, int bg, int flg, 625 long *attr) 626{ 627 int swap; 628 629 if ((flg & (WSATTR_BLINK | WSATTR_HILIT | WSATTR_WSCOLORS)) != 0) 630 return (EINVAL); 631 632 fg = 1; 633 bg = 0; 634 635 if ((flg & WSATTR_REVERSE) != 0) { 636 swap = fg; 637 fg = bg; 638 bg = swap; 639 } 640 641 *attr = (bg << 16) | (fg << 24) | ((flg & WSATTR_UNDERLINE) ? 7 : 6); 642 return (0); 643} 644 645/* 646 * Copy rows. 647 */ 648static void 649rasops_copyrows(void *cookie, int src, int dst, int num) 650{ 651 int32_t *sp, *dp, *hp, *srp, *drp, *hrp; 652 struct rasops_info *ri; 653 int n8, n1, cnt, delta; 654 655 ri = (struct rasops_info *)cookie; 656 hp = hrp = NULL; 657 658#ifdef RASOPS_CLIPPING 659 if (dst == src) 660 return; 661 662 if (src < 0) { 663 num += src; 664 src = 0; 665 } 666 667 if ((src + num) > ri->ri_rows) 668 num = ri->ri_rows - src; 669 670 if (dst < 0) { 671 num += dst; 672 dst = 0; 673 } 674 675 if ((dst + num) > ri->ri_rows) 676 num = ri->ri_rows - dst; 677 678 if (num <= 0) 679 return; 680#endif 681 682 num *= ri->ri_font->fontheight; 683 n8 = ri->ri_emustride >> 5; 684 n1 = (ri->ri_emustride >> 2) & 7; 685 686 if (dst < src) { 687 srp = (int32_t *)(ri->ri_bits + src * ri->ri_yscale); 688 drp = (int32_t *)(ri->ri_bits + dst * ri->ri_yscale); 689 if (ri->ri_hwbits) 690 hrp = (int32_t *)(ri->ri_hwbits + dst * 691 ri->ri_yscale); 692 delta = ri->ri_stride; 693 } else { 694 src = ri->ri_font->fontheight * src + num - 1; 695 dst = ri->ri_font->fontheight * dst + num - 1; 696 srp = (int32_t *)(ri->ri_bits + src * ri->ri_stride); 697 drp = (int32_t *)(ri->ri_bits + dst * ri->ri_stride); 698 if (ri->ri_hwbits) 699 hrp = (int32_t *)(ri->ri_hwbits + dst * 700 ri->ri_stride); 701 702 delta = -ri->ri_stride; 703 } 704 705 while (num--) { 706 dp = drp; 707 sp = srp; 708 if (ri->ri_hwbits) 709 hp = hrp; 710 711 DELTA(drp, delta, int32_t *); 712 DELTA(srp, delta, int32_t *); 713 if (ri->ri_hwbits) 714 DELTA(hrp, delta, int32_t *); 715 716 for (cnt = n8; cnt; cnt--) { 717 dp[0] = sp[0]; 718 dp[1] = sp[1]; 719 dp[2] = sp[2]; 720 dp[3] = sp[3]; 721 dp[4] = sp[4]; 722 dp[5] = sp[5]; 723 dp[6] = sp[6]; 724 dp[7] = sp[7]; 725 dp += 8; 726 sp += 8; 727 } 728 if (ri->ri_hwbits) { 729 sp -= (8 * n8); 730 for (cnt = n8; cnt; cnt--) { 731 hp[0] = sp[0]; 732 hp[1] = sp[1]; 733 hp[2] = sp[2]; 734 hp[3] = sp[3]; 735 hp[4] = sp[4]; 736 hp[5] = sp[5]; 737 hp[6] = sp[6]; 738 hp[7] = sp[7]; 739 hp += 8; 740 sp += 8; 741 } 742 } 743 744 for (cnt = n1; cnt; cnt--) { 745 *dp++ = *sp++; 746 if (ri->ri_hwbits) 747 *hp++ = *(sp - 1); 748 } 749 } 750} 751 752/* 753 * Copy columns. This is slow, and hard to optimize due to alignment, 754 * and the fact that we have to copy both left->right and right->left. 755 * We simply cop-out here and use memmove(), since it handles all of 756 * these cases anyway. 757 */ 758void 759rasops_copycols(void *cookie, int row, int src, int dst, int num) 760{ 761 struct rasops_info *ri; 762 u_char *sp, *dp, *hp; 763 int height; 764 765 ri = (struct rasops_info *)cookie; 766 hp = NULL; 767 768#ifdef RASOPS_CLIPPING 769 if (dst == src) 770 return; 771 772 /* Catches < 0 case too */ 773 if ((unsigned)row >= (unsigned)ri->ri_rows) 774 return; 775 776 if (src < 0) { 777 num += src; 778 src = 0; 779 } 780 781 if ((src + num) > ri->ri_cols) 782 num = ri->ri_cols - src; 783 784 if (dst < 0) { 785 num += dst; 786 dst = 0; 787 } 788 789 if ((dst + num) > ri->ri_cols) 790 num = ri->ri_cols - dst; 791 792 if (num <= 0) 793 return; 794#endif 795 796 num *= ri->ri_xscale; 797 row *= ri->ri_yscale; 798 height = ri->ri_font->fontheight; 799 800 sp = ri->ri_bits + row + src * ri->ri_xscale; 801 dp = ri->ri_bits + row + dst * ri->ri_xscale; 802 if (ri->ri_hwbits) 803 hp = ri->ri_hwbits + row + dst * ri->ri_xscale; 804 805 while (height--) { 806 memmove(dp, sp, num); 807 if (ri->ri_hwbits) { 808 memcpy(hp, sp, num); 809 hp += ri->ri_stride; 810 } 811 dp += ri->ri_stride; 812 sp += ri->ri_stride; 813 } 814} 815 816/* 817 * Turn cursor off/on. 818 */ 819static void 820rasops_cursor(void *cookie, int on, int row, int col) 821{ 822 struct rasops_info *ri; 823 824 ri = (struct rasops_info *)cookie; 825 826 /* Turn old cursor off */ 827 if ((ri->ri_flg & RI_CURSOR) != 0) 828#ifdef RASOPS_CLIPPING 829 if ((ri->ri_flg & RI_CURSORCLIP) == 0) 830#endif 831 ri->ri_do_cursor(ri); 832 833 /* Select new cursor */ 834#ifdef RASOPS_CLIPPING 835 ri->ri_flg &= ~RI_CURSORCLIP; 836 837 if (row < 0 || row >= ri->ri_rows) 838 ri->ri_flg |= RI_CURSORCLIP; 839 else if (col < 0 || col >= ri->ri_cols) 840 ri->ri_flg |= RI_CURSORCLIP; 841#endif 842 ri->ri_crow = row; 843 ri->ri_ccol = col; 844 845 if (on) { 846 ri->ri_flg |= RI_CURSOR; 847#ifdef RASOPS_CLIPPING 848 if ((ri->ri_flg & RI_CURSORCLIP) == 0) 849#endif 850 ri->ri_do_cursor(ri); 851 } else 852 ri->ri_flg &= ~RI_CURSOR; 853} 854 855/* 856 * Make the device colormap 857 */ 858static void 859rasops_init_devcmap(struct rasops_info *ri) 860{ 861 const u_char *p; 862 int i, c; 863 864 switch (ri->ri_depth) { 865 case 1: 866 ri->ri_devcmap[0] = 0; 867 for (i = 1; i < 16; i++) 868 ri->ri_devcmap[i] = -1; 869 return; 870 871 case 2: 872 for (i = 1; i < 15; i++) 873 ri->ri_devcmap[i] = 0xaaaaaaaa; 874 875 ri->ri_devcmap[0] = 0; 876 ri->ri_devcmap[8] = 0x55555555; 877 ri->ri_devcmap[15] = -1; 878 return; 879 880 case 8: 881 if ((ri->ri_flg & RI_8BIT_IS_RGB) == 0) { 882 for (i = 0; i < 16; i++) 883 ri->ri_devcmap[i] = 884 i | (i<<8) | (i<<16) | (i<<24); 885 return; 886 } 887 } 888 889 p = rasops_cmap; 890 891 for (i = 0; i < 16; i++) { 892 if (ri->ri_rnum <= 8) 893 c = (*p >> (8 - ri->ri_rnum)) << ri->ri_rpos; 894 else 895 c = (*p << (ri->ri_rnum - 8)) << ri->ri_rpos; 896 p++; 897 898 if (ri->ri_gnum <= 8) 899 c |= (*p >> (8 - ri->ri_gnum)) << ri->ri_gpos; 900 else 901 c |= (*p << (ri->ri_gnum - 8)) << ri->ri_gpos; 902 p++; 903 904 if (ri->ri_bnum <= 8) 905 c |= (*p >> (8 - ri->ri_bnum)) << ri->ri_bpos; 906 else 907 c |= (*p << (ri->ri_bnum - 8)) << ri->ri_bpos; 908 p++; 909 910 /* Fill the word for generic routines, which want this */ 911 if (ri->ri_depth == 24) 912 c = c | ((c & 0xff) << 24); 913 else if (ri->ri_depth == 8) { 914 c = c | (c << 8); 915 c |= c << 16; 916 } else if (ri->ri_depth <= 16) 917 c = c | (c << 16); 918 919 /* 24bpp does bswap on the fly. {32,16,15}bpp do it here. */ 920 if ((ri->ri_flg & RI_BSWAP) == 0) 921 ri->ri_devcmap[i] = c; 922 else if (ri->ri_depth == 32) 923 ri->ri_devcmap[i] = bswap32(c); 924 else if (ri->ri_depth == 16 || ri->ri_depth == 15) 925 ri->ri_devcmap[i] = bswap16(c); 926 else 927 ri->ri_devcmap[i] = c; 928 } 929} 930 931/* 932 * Unpack a rasops attribute 933 */ 934void 935rasops_unpack_attr(long attr, int *fg, int *bg, int *underline) 936{ 937 938 *fg = ((u_int)attr >> 24) & 0xf; 939 *bg = ((u_int)attr >> 16) & 0xf; 940 if (underline != NULL) 941 *underline = (u_int)attr & 1; 942} 943 944/* 945 * Erase rows. This isn't static, since 24-bpp uses it in special cases. 946 */ 947void 948rasops_eraserows(void *cookie, int row, int num, long attr) 949{ 950 struct rasops_info *ri; 951 int np, nw, cnt, delta; 952 int32_t *dp, *hp, clr; 953 int i; 954 955 ri = (struct rasops_info *)cookie; 956 hp = NULL; 957 958#ifdef RASOPS_CLIPPING 959 if (row < 0) { 960 num += row; 961 row = 0; 962 } 963 964 if ((row + num) > ri->ri_rows) 965 num = ri->ri_rows - row; 966 967 if (num <= 0) 968 return; 969#endif 970 971 clr = ri->ri_devcmap[(attr >> 16) & 0xf]; 972 973 /* 974 * XXX The wsdisplay_emulops interface seems a little deficient in 975 * that there is no way to clear the *entire* screen. We provide a 976 * workaround here: if the entire console area is being cleared, and 977 * the RI_FULLCLEAR flag is set, clear the entire display. 978 */ 979 if (num == ri->ri_rows && (ri->ri_flg & RI_FULLCLEAR) != 0) { 980 np = ri->ri_stride >> 5; 981 nw = (ri->ri_stride >> 2) & 7; 982 num = ri->ri_height; 983 dp = (int32_t *)ri->ri_origbits; 984 if (ri->ri_hwbits) 985 hp = (int32_t *)ri->ri_hworigbits; 986 delta = 0; 987 } else { 988 np = ri->ri_emustride >> 5; 989 nw = (ri->ri_emustride >> 2) & 7; 990 num *= ri->ri_font->fontheight; 991 dp = (int32_t *)(ri->ri_bits + row * ri->ri_yscale); 992 if (ri->ri_hwbits) 993 hp = (int32_t *)(ri->ri_hwbits + row * 994 ri->ri_yscale); 995 delta = ri->ri_delta; 996 } 997 998 while (num--) { 999 for (cnt = np; cnt; cnt--) { 1000 for (i = 0; i < 8; i++) { 1001 dp[i] = clr; 1002 if (ri->ri_hwbits) 1003 hp[i] = clr; 1004 } 1005 dp += 8; 1006 if (ri->ri_hwbits) 1007 hp += 8; 1008 } 1009 1010 for (cnt = nw; cnt; cnt--) { 1011 *(int32_t *)dp = clr; 1012 DELTA(dp, 4, int32_t *); 1013 if (ri->ri_hwbits) { 1014 *(int32_t *)hp = clr; 1015 DELTA(hp, 4, int32_t *); 1016 } 1017 } 1018 1019 DELTA(dp, delta, int32_t *); 1020 if (ri->ri_hwbits) 1021 DELTA(hp, delta, int32_t *); 1022 } 1023} 1024 1025/* 1026 * Actually turn the cursor on or off. This does the dirty work for 1027 * rasops_cursor(). 1028 */ 1029static void 1030rasops_do_cursor(struct rasops_info *ri) 1031{ 1032 int full1, height, cnt, slop1, slop2, row, col; 1033 u_char *dp, *rp, *hrp, *hp, tmp = 0; 1034 1035 hrp = hp = NULL; 1036 1037#if NRASOPS_ROTATION > 0 1038 if (ri->ri_flg & RI_ROTATE_MASK) { 1039 if (ri->ri_flg & RI_ROTATE_CW) { 1040 /* Rotate rows/columns */ 1041 row = ri->ri_ccol; 1042 col = ri->ri_rows - ri->ri_crow - 1; 1043 } else if (ri->ri_flg & RI_ROTATE_CCW) { 1044 /* Rotate rows/columns */ 1045 row = ri->ri_cols - ri->ri_ccol - 1; 1046 col = ri->ri_crow; 1047 } else { /* upside-down */ 1048 row = ri->ri_crow; 1049 col = ri->ri_ccol; 1050 } 1051 } else 1052#endif 1053 { 1054 row = ri->ri_crow; 1055 col = ri->ri_ccol; 1056 } 1057 1058 rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale; 1059 if (ri->ri_hwbits) 1060 hrp = ri->ri_hwbits + row * ri->ri_yscale + col 1061 * ri->ri_xscale; 1062 height = ri->ri_font->fontheight; 1063 slop1 = (4 - ((long)rp & 3)) & 3; 1064 1065 if (slop1 > ri->ri_xscale) 1066 slop1 = ri->ri_xscale; 1067 1068 slop2 = (ri->ri_xscale - slop1) & 3; 1069 full1 = (ri->ri_xscale - slop1 - slop2) >> 2; 1070 1071 if ((slop1 | slop2) == 0) { 1072 uint32_t tmp32; 1073 /* A common case */ 1074 while (height--) { 1075 dp = rp; 1076 rp += ri->ri_stride; 1077 if (ri->ri_hwbits) { 1078 hp = hrp; 1079 hrp += ri->ri_stride; 1080 } 1081 1082 for (cnt = full1; cnt; cnt--) { 1083 tmp32 = *(int32_t *)dp ^ ~0; 1084 *(int32_t *)dp = tmp32; 1085 dp += 4; 1086 if (ri->ri_hwbits) { 1087 *(int32_t *)hp = tmp32; 1088 hp += 4; 1089 } 1090 } 1091 } 1092 } else { 1093 uint16_t tmp16; 1094 uint32_t tmp32; 1095 /* XXX this is stupid.. use masks instead */ 1096 while (height--) { 1097 dp = rp; 1098 rp += ri->ri_stride; 1099 if (ri->ri_hwbits) { 1100 hp = hrp; 1101 hrp += ri->ri_stride; 1102 } 1103 1104 if (slop1 & 1) { 1105 tmp = *dp ^ ~0; 1106 *dp = tmp; 1107 dp++; 1108 if (ri->ri_hwbits) { 1109 *hp++ = tmp; 1110 } 1111 } 1112 1113 if (slop1 & 2) { 1114 tmp16 = *(int16_t *)dp ^ ~0; 1115 *(uint16_t *)dp = tmp16; 1116 dp += 2; 1117 if (ri->ri_hwbits) { 1118 *(int16_t *)hp = tmp16; 1119 hp += 2; 1120 } 1121 } 1122 1123 for (cnt = full1; cnt; cnt--) { 1124 tmp32 = *(int32_t *)dp ^ ~0; 1125 *(uint32_t *)dp = tmp32; 1126 dp += 4; 1127 if (ri->ri_hwbits) { 1128 *(int32_t *)hp = tmp32; 1129 hp += 4; 1130 } 1131 } 1132 1133 if (slop2 & 1) { 1134 tmp = *dp ^ ~0; 1135 *dp = tmp; 1136 dp++; 1137 if (ri->ri_hwbits) 1138 *hp++ = tmp; 1139 } 1140 1141 if (slop2 & 2) { 1142 tmp16 = *(int16_t *)dp ^ ~0; 1143 *(uint16_t *)dp = tmp16; 1144 if (ri->ri_hwbits) 1145 *(int16_t *)hp = tmp16; 1146 } 1147 } 1148 } 1149} 1150 1151/* 1152 * Erase columns. 1153 */ 1154void 1155rasops_erasecols(void *cookie, int row, int col, int num, long attr) 1156{ 1157 int n8, height, cnt, slop1, slop2, clr; 1158 struct rasops_info *ri; 1159 int32_t *rp, *dp, *hrp, *hp; 1160 int i; 1161 1162 ri = (struct rasops_info *)cookie; 1163 hrp = hp = NULL; 1164 1165#ifdef RASOPS_CLIPPING 1166 if ((unsigned)row >= (unsigned)ri->ri_rows) 1167 return; 1168 1169 if (col < 0) { 1170 num += col; 1171 col = 0; 1172 } 1173 1174 if ((col + num) > ri->ri_cols) 1175 num = ri->ri_cols - col; 1176 1177 if (num <= 0) 1178 return; 1179#endif 1180 1181 num = num * ri->ri_xscale; 1182 rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale); 1183 if (ri->ri_hwbits) 1184 hrp = (int32_t *)(ri->ri_hwbits + row*ri->ri_yscale + 1185 col*ri->ri_xscale); 1186 height = ri->ri_font->fontheight; 1187 clr = ri->ri_devcmap[(attr >> 16) & 0xf]; 1188 1189 /* Don't bother using the full loop for <= 32 pels */ 1190 if (num <= 32) { 1191 if (((num | ri->ri_xscale) & 3) == 0) { 1192 /* Word aligned blt */ 1193 num >>= 2; 1194 1195 while (height--) { 1196 dp = rp; 1197 DELTA(rp, ri->ri_stride, int32_t *); 1198 if (ri->ri_hwbits) { 1199 hp = hrp; 1200 DELTA(hrp, ri->ri_stride, int32_t *); 1201 } 1202 1203 for (cnt = num; cnt; cnt--) { 1204 *dp++ = clr; 1205 if (ri->ri_hwbits) 1206 *hp++ = clr; 1207 } 1208 } 1209 } else if (((num | ri->ri_xscale) & 1) == 0) { 1210 /* 1211 * Halfword aligned blt. This is needed so the 1212 * 15/16 bit ops can use this function. 1213 */ 1214 num >>= 1; 1215 1216 while (height--) { 1217 dp = rp; 1218 DELTA(rp, ri->ri_stride, int32_t *); 1219 if (ri->ri_hwbits) { 1220 hp = hrp; 1221 DELTA(hrp, ri->ri_stride, int32_t *); 1222 } 1223 1224 for (cnt = num; cnt; cnt--) { 1225 *(int16_t *)dp = clr; 1226 DELTA(dp, 2, int32_t *); 1227 if (ri->ri_hwbits) { 1228 *(int16_t *)hp = clr; 1229 DELTA(hp, 2, int32_t *); 1230 } 1231 } 1232 } 1233 } else { 1234 while (height--) { 1235 dp = rp; 1236 DELTA(rp, ri->ri_stride, int32_t *); 1237 if (ri->ri_hwbits) { 1238 hp = hrp; 1239 DELTA(hrp, ri->ri_stride, int32_t *); 1240 } 1241 1242 for (cnt = num; cnt; cnt--) { 1243 *(u_char *)dp = clr; 1244 DELTA(dp, 1, int32_t *); 1245 if (ri->ri_hwbits) { 1246 *(u_char *)hp = clr; 1247 DELTA(hp, 1, int32_t *); 1248 } 1249 } 1250 } 1251 } 1252 1253 return; 1254 } 1255 1256 slop1 = (4 - ((long)rp & 3)) & 3; 1257 slop2 = (num - slop1) & 3; 1258 num -= slop1 + slop2; 1259 n8 = num >> 5; 1260 num = (num >> 2) & 7; 1261 1262 while (height--) { 1263 dp = rp; 1264 DELTA(rp, ri->ri_stride, int32_t *); 1265 if (ri->ri_hwbits) { 1266 hp = hrp; 1267 DELTA(hrp, ri->ri_stride, int32_t *); 1268 } 1269 1270 /* Align span to 4 bytes */ 1271 if (slop1 & 1) { 1272 *(u_char *)dp = clr; 1273 DELTA(dp, 1, int32_t *); 1274 if (ri->ri_hwbits) { 1275 *(u_char *)hp = clr; 1276 DELTA(hp, 1, int32_t *); 1277 } 1278 } 1279 1280 if (slop1 & 2) { 1281 *(int16_t *)dp = clr; 1282 DELTA(dp, 2, int32_t *); 1283 if (ri->ri_hwbits) { 1284 *(int16_t *)hp = clr; 1285 DELTA(hp, 2, int32_t *); 1286 } 1287 } 1288 1289 /* Write 32 bytes per loop */ 1290 for (cnt = n8; cnt; cnt--) { 1291 for (i = 0; i < 8; i++) { 1292 dp[i] = clr; 1293 if (ri->ri_hwbits) 1294 hp[i] = clr; 1295 } 1296 dp += 8; 1297 if (ri->ri_hwbits) 1298 hp += 8; 1299 } 1300 1301 /* Write 4 bytes per loop */ 1302 for (cnt = num; cnt; cnt--) { 1303 *dp++ = clr; 1304 if (ri->ri_hwbits) 1305 *hp++ = clr; 1306 } 1307 1308 /* Write unaligned trailing slop */ 1309 if (slop2 & 1) { 1310 *(u_char *)dp = clr; 1311 DELTA(dp, 1, int32_t *); 1312 if (ri->ri_hwbits) { 1313 *(u_char *)hp = clr; 1314 DELTA(hp, 1, int32_t *); 1315 } 1316 } 1317 1318 if (slop2 & 2) { 1319 *(int16_t *)dp = clr; 1320 if (ri->ri_hwbits) 1321 *(int16_t *)hp = clr; 1322 } 1323 } 1324} 1325 1326#if NRASOPS_ROTATION > 0 1327/* 1328 * Quarter clockwise rotation routines (originally intended for the 1329 * built-in Zaurus C3x00 display in 16bpp). 1330 */ 1331 1332#include <sys/malloc.h> 1333 1334static void 1335rasops_rotate_font(int *cookie, int rotate) 1336{ 1337 struct rotatedfont *f; 1338 int ncookie; 1339 1340 SLIST_FOREACH(f, &rotatedfonts, rf_next) { 1341 if (f->rf_cookie == *cookie) { 1342 *cookie = f->rf_rotated; 1343 return; 1344 } 1345 } 1346 1347 /* 1348 * We did not find a rotated version of this font. Ask the wsfont 1349 * code to compute one for us. 1350 */ 1351 1352 f = malloc(sizeof(struct rotatedfont), M_DEVBUF, M_WAITOK); 1353 if (f == NULL) 1354 return; 1355 1356 if ((ncookie = wsfont_rotate(*cookie, rotate)) == -1) 1357 return; 1358 1359 f->rf_cookie = *cookie; 1360 f->rf_rotated = ncookie; 1361 SLIST_INSERT_HEAD(&rotatedfonts, f, rf_next); 1362 1363 *cookie = ncookie; 1364} 1365 1366static void 1367rasops_copychar(void *cookie, int srcrow, int dstrow, int srccol, int dstcol) 1368{ 1369 struct rasops_info *ri; 1370 u_char *sp, *dp; 1371 int height; 1372 int r_srcrow, r_dstrow, r_srccol, r_dstcol; 1373 1374 ri = (struct rasops_info *)cookie; 1375 1376 r_srcrow = srccol; 1377 r_dstrow = dstcol; 1378 r_srccol = ri->ri_rows - srcrow - 1; 1379 r_dstcol = ri->ri_rows - dstrow - 1; 1380 1381 r_srcrow *= ri->ri_yscale; 1382 r_dstrow *= ri->ri_yscale; 1383 height = ri->ri_font->fontheight; 1384 1385 sp = ri->ri_bits + r_srcrow + r_srccol * ri->ri_xscale; 1386 dp = ri->ri_bits + r_dstrow + r_dstcol * ri->ri_xscale; 1387 1388 while (height--) { 1389 memmove(dp, sp, ri->ri_xscale); 1390 dp += ri->ri_stride; 1391 sp += ri->ri_stride; 1392 } 1393} 1394 1395static void 1396rasops_putchar_rotated_cw(void *cookie, int row, int col, u_int uc, long attr) 1397{ 1398 struct rasops_info *ri; 1399 u_char *rp; 1400 int height; 1401 1402 ri = (struct rasops_info *)cookie; 1403 1404 if (__predict_false((unsigned int)row > ri->ri_rows || 1405 (unsigned int)col > ri->ri_cols)) 1406 return; 1407 1408 /* Avoid underflow */ 1409 if ((ri->ri_rows - row - 1) < 0) 1410 return; 1411 1412 /* Do rotated char sans (side)underline */ 1413 ri->ri_real_ops.putchar(cookie, col, ri->ri_rows - row - 1, uc, 1414 attr & ~1); 1415 1416 /* Do rotated underline */ 1417 rp = ri->ri_bits + col * ri->ri_yscale + (ri->ri_rows - row - 1) * 1418 ri->ri_xscale; 1419 height = ri->ri_font->fontheight; 1420 1421 /* XXX this assumes 16-bit color depth */ 1422 if ((attr & 1) != 0) { 1423 int16_t c = (int16_t)ri->ri_devcmap[((u_int)attr >> 24) & 0xf]; 1424 1425 while (height--) { 1426 *(int16_t *)rp = c; 1427 rp += ri->ri_stride; 1428 } 1429 } 1430} 1431 1432static void 1433rasops_erasecols_rotated_cw(void *cookie, int row, int col, int num, long attr) 1434{ 1435 struct rasops_info *ri; 1436 int i; 1437 1438 ri = (struct rasops_info *)cookie; 1439 1440 for (i = col; i < col + num; i++) 1441 ri->ri_ops.putchar(cookie, row, i, ' ', attr); 1442} 1443 1444/* XXX: these could likely be optimised somewhat. */ 1445static void 1446rasops_copyrows_rotated_cw(void *cookie, int src, int dst, int num) 1447{ 1448 struct rasops_info *ri = (struct rasops_info *)cookie; 1449 int col, roff; 1450 1451 if (src > dst) 1452 for (roff = 0; roff < num; roff++) 1453 for (col = 0; col < ri->ri_cols; col++) 1454 rasops_copychar(cookie, src + roff, dst + roff, 1455 col, col); 1456 else 1457 for (roff = num - 1; roff >= 0; roff--) 1458 for (col = 0; col < ri->ri_cols; col++) 1459 rasops_copychar(cookie, src + roff, dst + roff, 1460 col, col); 1461} 1462 1463static void 1464rasops_copycols_rotated_cw(void *cookie, int row, int src, int dst, int num) 1465{ 1466 int coff; 1467 1468 if (src > dst) 1469 for (coff = 0; coff < num; coff++) 1470 rasops_copychar(cookie, row, row, src + coff, dst + coff); 1471 else 1472 for (coff = num - 1; coff >= 0; coff--) 1473 rasops_copychar(cookie, row, row, src + coff, dst + coff); 1474} 1475 1476static void 1477rasops_eraserows_rotated_cw(void *cookie, int row, int num, long attr) 1478{ 1479 struct rasops_info *ri; 1480 int col, rn; 1481 1482 ri = (struct rasops_info *)cookie; 1483 1484 for (rn = row; rn < row + num; rn++) 1485 for (col = 0; col < ri->ri_cols; col++) 1486 ri->ri_ops.putchar(cookie, rn, col, ' ', attr); 1487} 1488 1489/* 1490 * Quarter counter-clockwise rotation routines (originally intended for the 1491 * built-in Sharp W-ZERO3 display in 16bpp). 1492 */ 1493static void 1494rasops_copychar_ccw(void *cookie, int srcrow, int dstrow, int srccol, int dstcol) 1495{ 1496 struct rasops_info *ri; 1497 u_char *sp, *dp; 1498 int height; 1499 int r_srcrow, r_dstrow, r_srccol, r_dstcol; 1500 1501 ri = (struct rasops_info *)cookie; 1502 1503 r_srcrow = ri->ri_cols - srccol - 1; 1504 r_dstrow = ri->ri_cols - dstcol - 1; 1505 r_srccol = srcrow; 1506 r_dstcol = dstrow; 1507 1508 r_srcrow *= ri->ri_yscale; 1509 r_dstrow *= ri->ri_yscale; 1510 height = ri->ri_font->fontheight; 1511 1512 sp = ri->ri_bits + r_srcrow + r_srccol * ri->ri_xscale; 1513 dp = ri->ri_bits + r_dstrow + r_dstcol * ri->ri_xscale; 1514 1515 while (height--) { 1516 memmove(dp, sp, ri->ri_xscale); 1517 dp += ri->ri_stride; 1518 sp += ri->ri_stride; 1519 } 1520} 1521 1522static void 1523rasops_putchar_rotated_ccw(void *cookie, int row, int col, u_int uc, long attr) 1524{ 1525 struct rasops_info *ri; 1526 u_char *rp; 1527 int height; 1528 1529 ri = (struct rasops_info *)cookie; 1530 1531 if (__predict_false((unsigned int)row > ri->ri_rows || 1532 (unsigned int)col > ri->ri_cols)) 1533 return; 1534 1535 /* Avoid underflow */ 1536 if ((ri->ri_cols - col - 1) < 0) 1537 return; 1538 1539 /* Do rotated char sans (side)underline */ 1540 ri->ri_real_ops.putchar(cookie, ri->ri_cols - col - 1, row, uc, 1541 attr & ~1); 1542 1543 /* Do rotated underline */ 1544 rp = ri->ri_bits + (ri->ri_cols - col - 1) * ri->ri_yscale + 1545 row * ri->ri_xscale + 1546 (ri->ri_font->fontwidth - 1) * ri->ri_pelbytes; 1547 height = ri->ri_font->fontheight; 1548 1549 /* XXX this assumes 16-bit color depth */ 1550 if ((attr & 1) != 0) { 1551 int16_t c = (int16_t)ri->ri_devcmap[((u_int)attr >> 24) & 0xf]; 1552 1553 while (height--) { 1554 *(int16_t *)rp = c; 1555 rp += ri->ri_stride; 1556 } 1557 } 1558} 1559 1560/* XXX: these could likely be optimised somewhat. */ 1561static void 1562rasops_copyrows_rotated_ccw(void *cookie, int src, int dst, int num) 1563{ 1564 struct rasops_info *ri = (struct rasops_info *)cookie; 1565 int col, roff; 1566 1567 if (src > dst) 1568 for (roff = 0; roff < num; roff++) 1569 for (col = 0; col < ri->ri_cols; col++) 1570 rasops_copychar_ccw(cookie, 1571 src + roff, dst + roff, col, col); 1572 else 1573 for (roff = num - 1; roff >= 0; roff--) 1574 for (col = 0; col < ri->ri_cols; col++) 1575 rasops_copychar_ccw(cookie, 1576 src + roff, dst + roff, col, col); 1577} 1578 1579static void 1580rasops_copycols_rotated_ccw(void *cookie, int row, int src, int dst, int num) 1581{ 1582 int coff; 1583 1584 if (src > dst) 1585 for (coff = 0; coff < num; coff++) 1586 rasops_copychar_ccw(cookie, row, row, 1587 src + coff, dst + coff); 1588 else 1589 for (coff = num - 1; coff >= 0; coff--) 1590 rasops_copychar_ccw(cookie, row, row, 1591 src + coff, dst + coff); 1592} 1593#endif /* NRASOPS_ROTATION */ 1594 1595void 1596rasops_make_box_chars_16(struct rasops_info *ri) 1597{ 1598 uint16_t vert_mask, hmask_left, hmask_right; 1599 uint16_t *data = (uint16_t *)ri->ri_optfont.data; 1600 int c, i, mid; 1601 1602 vert_mask = 0xc000 >> ((ri->ri_font->fontwidth >> 1) - 1); 1603 hmask_left = 0xff00 << (8 - (ri->ri_font->fontwidth >> 1)); 1604 hmask_right = hmask_left >> ((ri->ri_font->fontwidth + 1)>> 1); 1605 mid = (ri->ri_font->fontheight + 1) >> 1; 1606 1607 /* 0x00 would be empty anyway so don't bother */ 1608 for (c = 1; c < 16; c++) { 1609 data += ri->ri_font->fontheight; 1610 if (c & 1) { 1611 /* upper segment */ 1612 for (i = 0; i < mid; i++) 1613 data[i] = vert_mask; 1614 } 1615 if (c & 4) { 1616 /* lower segment */ 1617 for (i = mid; i < ri->ri_font->fontheight; i++) 1618 data[i] = vert_mask; 1619 } 1620 if (c & 2) { 1621 /* right segment */ 1622 i = ri->ri_font->fontheight >> 1; 1623 data[mid - 1] |= hmask_right; 1624 data[mid] |= hmask_right; 1625 } 1626 if (c & 8) { 1627 /* left segment */ 1628 data[mid - 1] |= hmask_left; 1629 data[mid] |= hmask_left; 1630 } 1631 } 1632} 1633 1634void 1635rasops_make_box_chars_8(struct rasops_info *ri) 1636{ 1637 uint8_t vert_mask, hmask_left, hmask_right; 1638 uint8_t *data = (uint8_t *)ri->ri_optfont.data; 1639 int c, i, mid; 1640 1641 vert_mask = 0xc0 >> ((ri->ri_font->fontwidth >> 1) - 1); 1642 hmask_left = 0xf0 << (4 - (ri->ri_font->fontwidth >> 1)); 1643 hmask_right = hmask_left >> ((ri->ri_font->fontwidth + 1)>> 1); 1644 mid = (ri->ri_font->fontheight + 1) >> 1; 1645 1646 /* 0x00 would be empty anyway so don't bother */ 1647 for (c = 1; c < 16; c++) { 1648 data += ri->ri_font->fontheight; 1649 if (c & 1) { 1650 /* upper segment */ 1651 for (i = 0; i < mid; i++) 1652 data[i] = vert_mask; 1653 } 1654 if (c & 4) { 1655 /* lower segment */ 1656 for (i = mid; i < ri->ri_font->fontheight; i++) 1657 data[i] = vert_mask; 1658 } 1659 if (c & 2) { 1660 /* right segment */ 1661 i = ri->ri_font->fontheight >> 1; 1662 data[mid - 1] |= hmask_right; 1663 data[mid] |= hmask_right; 1664 } 1665 if (c & 8) { 1666 /* left segment */ 1667 data[mid - 1] |= hmask_left; 1668 data[mid] |= hmask_left; 1669 } 1670 } 1671} 1672 1673void 1674rasops_make_box_chars_32(struct rasops_info *ri) 1675{ 1676 uint32_t vert_mask, hmask_left, hmask_right; 1677 uint32_t *data = (uint32_t *)ri->ri_optfont.data; 1678 int c, i, mid; 1679 1680 vert_mask = 0xc0000000 >> ((ri->ri_font->fontwidth >> 1) - 1); 1681 hmask_left = 0xffff0000 << (16 - (ri->ri_font->fontwidth >> 1)); 1682 hmask_right = hmask_left >> ((ri->ri_font->fontwidth + 1)>> 1); 1683 mid = (ri->ri_font->fontheight + 1) >> 1; 1684 1685 /* 0x00 would be empty anyway so don't bother */ 1686 for (c = 1; c < 16; c++) { 1687 data += ri->ri_font->fontheight; 1688 if (c & 1) { 1689 /* upper segment */ 1690 for (i = 0; i < mid; i++) 1691 data[i] = vert_mask; 1692 } 1693 if (c & 4) { 1694 /* lower segment */ 1695 for (i = mid; i < ri->ri_font->fontheight; i++) 1696 data[i] = vert_mask; 1697 } 1698 if (c & 2) { 1699 /* right segment */ 1700 i = ri->ri_font->fontheight >> 1; 1701 data[mid - 1] |= hmask_right; 1702 data[mid] |= hmask_right; 1703 } 1704 if (c & 8) { 1705 /* left segment */ 1706 data[mid - 1] |= hmask_left; 1707 data[mid] |= hmask_left; 1708 } 1709 } 1710} 1711 1712void 1713rasops_make_box_chars_alpha(struct rasops_info *ri) 1714{ 1715 uint8_t *data = (uint8_t *)ri->ri_optfont.data; 1716 uint8_t *ddata; 1717 int c, i, hmid, vmid, wi, he; 1718 1719 wi = ri->ri_font->fontwidth; 1720 he = ri->ri_font->fontheight; 1721 1722 vmid = (he + 1) >> 1; 1723 hmid = (wi + 1) >> 1; 1724 1725 /* 0x00 would be empty anyway so don't bother */ 1726 for (c = 1; c < 16; c++) { 1727 data += ri->ri_fontscale; 1728 if (c & 1) { 1729 /* upper segment */ 1730 ddata = data + hmid; 1731 for (i = 0; i <= vmid; i++) { 1732 *ddata = 0xff; 1733 ddata += wi; 1734 } 1735 } 1736 if (c & 4) { 1737 /* lower segment */ 1738 ddata = data + wi * vmid + hmid; 1739 for (i = vmid; i < he; i++) { 1740 *ddata = 0xff; 1741 ddata += wi; 1742 } 1743 } 1744 if (c & 2) { 1745 /* right segment */ 1746 ddata = data + wi * vmid + hmid; 1747 for (i = hmid; i < wi; i++) { 1748 *ddata = 0xff; 1749 ddata++; 1750 } 1751 } 1752 if (c & 8) { 1753 /* left segment */ 1754 ddata = data + wi * vmid; 1755 for (i = 0; i <= hmid; i++) { 1756 *ddata = 0xff; 1757 ddata++; 1758 } 1759 } 1760 } 1761} 1762