1 /* $NetBSD: rasops8.c,v 1.24 2008/04/28 20:23:56 martin 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: rasops8.c,v 1.24 2008/04/28 20:23:56 martin Exp $"); 34 35 #include "opt_rasops.h" 36 37 #include <sys/param.h> 38 #include <sys/systm.h> 39 #include <sys/time.h> 40 41 #include <dev/wscons/wsdisplayvar.h> 42 #include <dev/wscons/wsconsio.h> 43 #include <dev/rasops/rasops.h> 44 45 static void rasops8_putchar(void *, int, int, u_int, long attr); 46 #ifndef RASOPS_SMALL 47 static void rasops8_putchar8(void *, int, int, u_int, long attr); 48 static void rasops8_putchar12(void *, int, int, u_int, long attr); 49 static void rasops8_putchar16(void *, int, int, u_int, long attr); 50 static void rasops8_makestamp(struct rasops_info *ri, long); 51 52 /* 53 * 4x1 stamp for optimized character blitting 54 */ 55 static int32_t stamp[16]; 56 static long stamp_attr; 57 static int stamp_mutex; /* XXX see note in README */ 58 #endif 59 60 /* 61 * XXX this confuses the hell out of gcc2 (not egcs) which always insists 62 * that the shift count is negative. 63 * 64 * offset = STAMP_SHIFT(fontbits, nibble #) & STAMP_MASK 65 * destination = STAMP_READ(offset) 66 */ 67 #define STAMP_SHIFT(fb,n) ((n*4-2) >= 0 ? (fb)>>(n*4-2):(fb)<<-(n*4-2)) 68 #define STAMP_MASK (0xf << 2) 69 #define STAMP_READ(o) (*(int32_t *)((char *)stamp + (o))) 70 71 /* 72 * Initialize a 'rasops_info' descriptor for this depth. 73 */ 74 void 75 rasops8_init(ri) 76 struct rasops_info *ri; 77 { 78 79 switch (ri->ri_font->fontwidth) { 80 #ifndef RASOPS_SMALL 81 case 8: 82 ri->ri_ops.putchar = rasops8_putchar8; 83 break; 84 case 12: 85 ri->ri_ops.putchar = rasops8_putchar12; 86 break; 87 case 16: 88 ri->ri_ops.putchar = rasops8_putchar16; 89 break; 90 #endif /* !RASOPS_SMALL */ 91 default: 92 ri->ri_ops.putchar = rasops8_putchar; 93 break; 94 } 95 } 96 97 /* 98 * Put a single character. 99 */ 100 static void 101 rasops8_putchar(cookie, row, col, uc, attr) 102 void *cookie; 103 int row, col; 104 u_int uc; 105 long attr; 106 { 107 int width, height, cnt, fs, fb; 108 u_char *dp, *rp, *hp, *hrp, *fr, clr[2]; 109 struct rasops_info *ri; 110 111 ri = (struct rasops_info *)cookie; 112 hp = hrp = NULL; 113 114 if (!CHAR_IN_FONT(uc, ri->ri_font)) 115 return; 116 117 #ifdef RASOPS_CLIPPING 118 /* Catches 'row < 0' case too */ 119 if ((unsigned)row >= (unsigned)ri->ri_rows) 120 return; 121 122 if ((unsigned)col >= (unsigned)ri->ri_cols) 123 return; 124 #endif 125 rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale; 126 if (ri->ri_hwbits) 127 hrp = ri->ri_hwbits + row * ri->ri_yscale + col * 128 ri->ri_xscale; 129 130 height = ri->ri_font->fontheight; 131 width = ri->ri_font->fontwidth; 132 clr[0] = (u_char)ri->ri_devcmap[(attr >> 16) & 0xf]; 133 clr[1] = (u_char)ri->ri_devcmap[(attr >> 24) & 0xf]; 134 135 if (uc == ' ') { 136 u_char c = clr[0]; 137 138 while (height--) { 139 dp = rp; 140 rp += ri->ri_stride; 141 if (ri->ri_hwbits) { 142 hp = hrp; 143 hrp += ri->ri_stride; 144 } 145 146 for (cnt = width; cnt; cnt--) { 147 *dp++ = c; 148 if (ri->ri_hwbits) 149 *hp++ = c; 150 } 151 } 152 } else { 153 uc -= ri->ri_font->firstchar; 154 fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale; 155 fs = ri->ri_font->stride; 156 157 while (height--) { 158 dp = rp; 159 if (ri->ri_hwbits) 160 hp = hrp; 161 fb = fr[3] | (fr[2] << 8) | (fr[1] << 16) | (fr[0] << 24); 162 fr += fs; 163 rp += ri->ri_stride; 164 if (ri->ri_hwbits) 165 hrp += ri->ri_stride; 166 167 for (cnt = width; cnt; cnt--) { 168 *dp++ = clr[(fb >> 31) & 1]; 169 if (ri->ri_hwbits) 170 *hp++ = clr[(fb >> 31) & 1]; 171 fb <<= 1; 172 } 173 } 174 } 175 176 /* Do underline */ 177 if ((attr & 1) != 0) { 178 u_char c = clr[1]; 179 180 rp -= (ri->ri_stride << 1); 181 if (ri->ri_hwbits) 182 hrp -= (ri->ri_stride << 1); 183 184 while (width--) { 185 *rp++ = c; 186 if (ri->ri_hwbits) 187 *hrp++ = c; 188 } 189 } 190 } 191 192 #ifndef RASOPS_SMALL 193 /* 194 * Recompute the 4x1 blitting stamp. 195 */ 196 static void 197 rasops8_makestamp(ri, attr) 198 struct rasops_info *ri; 199 long attr; 200 { 201 int32_t fg, bg; 202 int i; 203 204 fg = ri->ri_devcmap[(attr >> 24) & 0xf] & 0xff; 205 bg = ri->ri_devcmap[(attr >> 16) & 0xf] & 0xff; 206 stamp_attr = attr; 207 208 for (i = 0; i < 16; i++) { 209 #if BYTE_ORDER == BIG_ENDIAN 210 #define NEED_LITTLE_ENDIAN_STAMP RI_BSWAP 211 #else 212 #define NEED_LITTLE_ENDIAN_STAMP 0 213 #endif 214 if ((ri->ri_flg & RI_BSWAP) == NEED_LITTLE_ENDIAN_STAMP) { 215 /* little endian */ 216 stamp[i] = (i & 8 ? fg : bg); 217 stamp[i] |= ((i & 4 ? fg : bg) << 8); 218 stamp[i] |= ((i & 2 ? fg : bg) << 16); 219 stamp[i] |= ((i & 1 ? fg : bg) << 24); 220 } else { 221 /* big endian */ 222 stamp[i] = (i & 1 ? fg : bg); 223 stamp[i] |= ((i & 2 ? fg : bg) << 8); 224 stamp[i] |= ((i & 4 ? fg : bg) << 16); 225 stamp[i] |= ((i & 8 ? fg : bg) << 24); 226 } 227 } 228 } 229 230 /* 231 * Put a single character. This is for 8-pixel wide fonts. 232 */ 233 static void 234 rasops8_putchar8(cookie, row, col, uc, attr) 235 void *cookie; 236 int row, col; 237 u_int uc; 238 long attr; 239 { 240 struct rasops_info *ri; 241 int height, fs; 242 int32_t *rp, *hp; 243 u_char *fr; 244 245 /* Can't risk remaking the stamp if it's already in use */ 246 if (stamp_mutex++) { 247 stamp_mutex--; 248 rasops8_putchar(cookie, row, col, uc, attr); 249 return; 250 } 251 252 ri = (struct rasops_info *)cookie; 253 hp = NULL; 254 255 if (!CHAR_IN_FONT(uc, ri->ri_font)) 256 return; 257 258 #ifdef RASOPS_CLIPPING 259 if ((unsigned)row >= (unsigned)ri->ri_rows) { 260 stamp_mutex--; 261 return; 262 } 263 264 if ((unsigned)col >= (unsigned)ri->ri_cols) { 265 stamp_mutex--; 266 return; 267 } 268 #endif 269 270 /* Recompute stamp? */ 271 if (attr != stamp_attr) 272 rasops8_makestamp(ri, attr); 273 274 rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale); 275 if (ri->ri_hwbits) 276 hp = (int32_t *)(ri->ri_hwbits + row*ri->ri_yscale + 277 col*ri->ri_xscale); 278 height = ri->ri_font->fontheight; 279 280 if (uc == ' ') { 281 while (height--) { 282 rp[0] = rp[1] = stamp[0]; 283 DELTA(rp, ri->ri_stride, int32_t *); 284 if (ri->ri_hwbits) { 285 hp[0] = stamp[0]; 286 hp[1] = stamp[0]; 287 DELTA(hp, ri->ri_stride, int32_t *); 288 } 289 } 290 } else { 291 uc -= ri->ri_font->firstchar; 292 fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale; 293 fs = ri->ri_font->stride; 294 295 while (height--) { 296 rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK); 297 rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK); 298 if (ri->ri_hwbits) { 299 hp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & 300 STAMP_MASK); 301 hp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & 302 STAMP_MASK); 303 } 304 305 fr += fs; 306 DELTA(rp, ri->ri_stride, int32_t *); 307 if (ri->ri_hwbits) 308 DELTA(hp, ri->ri_stride, int32_t *); 309 } 310 } 311 312 /* Do underline */ 313 if ((attr & 1) != 0) { 314 DELTA(rp, -(ri->ri_stride << 1), int32_t *); 315 rp[0] = rp[1] = stamp[15]; 316 if (ri->ri_hwbits) { 317 DELTA(hp, -(ri->ri_stride << 1), int32_t *); 318 hp[0] = stamp[15]; 319 hp[1] = stamp[15]; 320 } 321 } 322 323 stamp_mutex--; 324 } 325 326 /* 327 * Put a single character. This is for 12-pixel wide fonts. 328 */ 329 static void 330 rasops8_putchar12(cookie, row, col, uc, attr) 331 void *cookie; 332 int row, col; 333 u_int uc; 334 long attr; 335 { 336 struct rasops_info *ri; 337 int height, fs; 338 int32_t *rp, *hrp; 339 u_char *fr; 340 341 /* Can't risk remaking the stamp if it's already in use */ 342 if (stamp_mutex++) { 343 stamp_mutex--; 344 rasops8_putchar(cookie, row, col, uc, attr); 345 return; 346 } 347 348 ri = (struct rasops_info *)cookie; 349 hrp = NULL; 350 351 if (!CHAR_IN_FONT(uc, ri->ri_font)) 352 return; 353 354 #ifdef RASOPS_CLIPPING 355 if ((unsigned)row >= (unsigned)ri->ri_rows) { 356 stamp_mutex--; 357 return; 358 } 359 360 if ((unsigned)col >= (unsigned)ri->ri_cols) { 361 stamp_mutex--; 362 return; 363 } 364 #endif 365 366 /* Recompute stamp? */ 367 if (attr != stamp_attr) 368 rasops8_makestamp(ri, attr); 369 370 rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale); 371 if (ri->ri_hwbits) 372 hrp = (int32_t *)(ri->ri_hwbits + row*ri->ri_yscale + 373 col*ri->ri_xscale); 374 height = ri->ri_font->fontheight; 375 376 if (uc == ' ') { 377 while (height--) { 378 int32_t c = stamp[0]; 379 380 rp[0] = rp[1] = rp[2] = c; 381 DELTA(rp, ri->ri_stride, int32_t *); 382 if (ri->ri_hwbits) { 383 hrp[0] = c; 384 hrp[1] = c; 385 hrp[2] = c; 386 DELTA(hrp, ri->ri_stride, int32_t *); 387 } 388 } 389 } else { 390 uc -= ri->ri_font->firstchar; 391 fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale; 392 fs = ri->ri_font->stride; 393 394 while (height--) { 395 rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK); 396 rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK); 397 rp[2] = STAMP_READ(STAMP_SHIFT(fr[1], 1) & STAMP_MASK); 398 if (ri->ri_hwbits) { 399 hrp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK); 400 hrp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK); 401 hrp[2] = STAMP_READ(STAMP_SHIFT(fr[1], 1) & STAMP_MASK); 402 } 403 404 fr += fs; 405 DELTA(rp, ri->ri_stride, int32_t *); 406 if (ri->ri_hwbits) 407 DELTA(hrp, ri->ri_stride, int32_t *); 408 } 409 } 410 411 /* Do underline */ 412 if ((attr & 1) != 0) { 413 DELTA(rp, -(ri->ri_stride << 1), int32_t *); 414 rp[0] = rp[1] = rp[2] = stamp[15]; 415 if (ri->ri_hwbits) { 416 DELTA(hrp, -(ri->ri_stride << 1), int32_t *); 417 hrp[0] = stamp[15]; 418 hrp[1] = stamp[15]; 419 hrp[2] = stamp[15]; 420 } 421 } 422 423 stamp_mutex--; 424 } 425 426 /* 427 * Put a single character. This is for 16-pixel wide fonts. 428 */ 429 static void 430 rasops8_putchar16(cookie, row, col, uc, attr) 431 void *cookie; 432 int row, col; 433 u_int uc; 434 long attr; 435 { 436 struct rasops_info *ri; 437 int height, fs; 438 int32_t *rp, *hrp; 439 u_char *fr; 440 441 /* Can't risk remaking the stamp if it's already in use */ 442 if (stamp_mutex++) { 443 stamp_mutex--; 444 rasops8_putchar(cookie, row, col, uc, attr); 445 return; 446 } 447 448 ri = (struct rasops_info *)cookie; 449 hrp = NULL; 450 451 if (!CHAR_IN_FONT(uc, ri->ri_font)) 452 return; 453 454 #ifdef RASOPS_CLIPPING 455 if ((unsigned)row >= (unsigned)ri->ri_rows) { 456 stamp_mutex--; 457 return; 458 } 459 460 if ((unsigned)col >= (unsigned)ri->ri_cols) { 461 stamp_mutex--; 462 return; 463 } 464 #endif 465 466 /* Recompute stamp? */ 467 if (attr != stamp_attr) 468 rasops8_makestamp(ri, attr); 469 470 rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale); 471 if (ri->ri_hwbits) 472 hrp = (int32_t *)(ri->ri_hwbits + row*ri->ri_yscale + 473 col*ri->ri_xscale); 474 475 height = ri->ri_font->fontheight; 476 477 if (uc == ' ') { 478 while (height--) { 479 rp[0] = rp[1] = rp[2] = rp[3] = stamp[0]; 480 if (ri->ri_hwbits) { 481 hrp[0] = stamp[0]; 482 hrp[1] = stamp[0]; 483 hrp[2] = stamp[0]; 484 hrp[3] = stamp[0]; 485 } 486 } 487 } else { 488 uc -= ri->ri_font->firstchar; 489 fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale; 490 fs = ri->ri_font->stride; 491 492 while (height--) { 493 rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK); 494 rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK); 495 rp[2] = STAMP_READ(STAMP_SHIFT(fr[1], 1) & STAMP_MASK); 496 rp[3] = STAMP_READ(STAMP_SHIFT(fr[1], 0) & STAMP_MASK); 497 if (ri->ri_hwbits) { 498 hrp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK); 499 hrp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK); 500 hrp[2] = STAMP_READ(STAMP_SHIFT(fr[1], 1) & STAMP_MASK); 501 hrp[3] = STAMP_READ(STAMP_SHIFT(fr[1], 0) & STAMP_MASK); 502 } 503 504 fr += fs; 505 DELTA(rp, ri->ri_stride, int32_t *); 506 if (ri->ri_hwbits) 507 DELTA(hrp, ri->ri_stride, int32_t *); 508 } 509 } 510 511 /* Do underline */ 512 if ((attr & 1) != 0) { 513 DELTA(rp, -(ri->ri_stride << 1), int32_t *); 514 rp[0] = rp[1] = rp[2] = rp[3] = stamp[15]; 515 if (ri->ri_hwbits) { 516 DELTA(hrp, -(ri->ri_stride << 1), int32_t *); 517 hrp[0] = stamp[15]; 518 hrp[1] = stamp[15]; 519 hrp[2] = stamp[15]; 520 hrp[3] = stamp[15]; 521 } 522 } 523 524 stamp_mutex--; 525 } 526 #endif /* !RASOPS_SMALL */ 527