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