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