1 /* $OpenBSD: rasops4.c,v 1.9 2009/09/05 14:09:35 miod Exp $ */ 2 /* $NetBSD: rasops4.c,v 1.4 2001/11/15 09:48:15 lukem Exp $ */ 3 4 /*- 5 * Copyright (c) 1999 The NetBSD Foundation, Inc. 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to The NetBSD Foundation 9 * by Andrew Doran. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 #include <sys/param.h> 34 #include <sys/systm.h> 35 #include <sys/time.h> 36 #include <machine/endian.h> 37 38 #include <dev/wscons/wsdisplayvar.h> 39 #include <dev/wscons/wsconsio.h> 40 #include <dev/rasops/rasops.h> 41 #include <dev/rasops/rasops_masks.h> 42 43 int rasops4_copycols(void *, int, int, int, int); 44 int rasops4_erasecols(void *, int, int, int, long); 45 int rasops4_do_cursor(struct rasops_info *); 46 int rasops4_putchar(void *, int, int col, u_int, long); 47 #ifndef RASOPS_SMALL 48 int rasops4_putchar8(void *, int, int col, u_int, long); 49 int rasops4_putchar12(void *, int, int col, u_int, long); 50 int rasops4_putchar16(void *, int, int col, u_int, long); 51 void rasops4_makestamp(struct rasops_info *, long); 52 53 /* 54 * 4x1 stamp for optimized character blitting 55 */ 56 static u_int16_t stamp[16]; 57 static long stamp_attr; 58 static int stamp_mutex; /* XXX see note in README */ 59 #endif 60 61 /* 62 * Initialize rasops_info struct for this colordepth. 63 */ 64 void 65 rasops4_init(ri) 66 struct rasops_info *ri; 67 { 68 rasops_masks_init(); 69 70 switch (ri->ri_font->fontwidth) { 71 #ifndef RASOPS_SMALL 72 case 8: 73 ri->ri_ops.putchar = rasops4_putchar8; 74 break; 75 case 12: 76 ri->ri_ops.putchar = rasops4_putchar12; 77 break; 78 case 16: 79 ri->ri_ops.putchar = rasops4_putchar16; 80 break; 81 #endif /* !RASOPS_SMALL */ 82 default: 83 panic("fontwidth not 8/12/16 or RASOPS_SMALL - fixme!"); 84 ri->ri_ops.putchar = rasops4_putchar; 85 break; 86 } 87 88 if ((ri->ri_font->fontwidth & 1) != 0) { 89 ri->ri_ops.erasecols = rasops4_erasecols; 90 ri->ri_ops.copycols = rasops4_copycols; 91 ri->ri_do_cursor = rasops4_do_cursor; 92 } 93 } 94 95 #ifdef notyet 96 /* 97 * Paint a single character. This is the generic version, this is ugly. 98 */ 99 int 100 rasops4_putchar(cookie, row, col, uc, attr) 101 void *cookie; 102 int row, col; 103 u_int uc; 104 long attr; 105 { 106 int height, width, fs, rs, fb, bg, fg, lmask, rmask; 107 struct rasops_info *ri; 108 int32_t *rp; 109 u_char *fr; 110 111 ri = (struct rasops_info *)cookie; 112 113 #ifdef RASOPS_CLIPPING 114 /* Catches 'row < 0' case too */ 115 if ((unsigned)row >= (unsigned)ri->ri_rows) 116 return 0; 117 118 if ((unsigned)col >= (unsigned)ri->ri_cols) 119 return 0; 120 #endif 121 122 width = ri->ri_font->fontwidth << 1; 123 height = ri->ri_font->fontheight; 124 col *= width; 125 rp = (int32_t *)(ri->ri_bits + row * ri->ri_yscale + ((col >> 3) & ~3)); 126 col = col & 31; 127 rs = ri->ri_stride; 128 129 bg = ri->ri_devcmap[(attr >> 16) & 0xf]; 130 fg = ri->ri_devcmap[(attr >> 24) & 0xf]; 131 132 /* If fg and bg match this becomes a space character */ 133 if (fg == bg || uc == ' ') { 134 uc = (u_int)-1; 135 fr = 0; /* shutup gcc */ 136 fs = 0; /* shutup gcc */ 137 } else { 138 uc -= ri->ri_font->firstchar; 139 fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale; 140 fs = ri->ri_font->stride; 141 } 142 143 /* Single word, one mask */ 144 if ((col + width) <= 32) { 145 rmask = rasops_pmask[col][width]; 146 lmask = ~rmask; 147 148 if (uc == (u_int)-1) { 149 bg &= rmask; 150 151 while (height--) { 152 *rp = (*rp & lmask) | bg; 153 DELTA(rp, rs, int32_t *); 154 } 155 } else { 156 while (height--) { 157 /* get bits, mask */ 158 /* compose sl */ 159 /* mask sl */ 160 /* put word */ 161 } 162 } 163 164 /* Do underline */ 165 if (attr & 1) { 166 DELTA(rp, -(ri->ri_stride << 1), int32_t *); 167 *rp = (*rp & lmask) | (fg & rmask); 168 } 169 } else { 170 lmask = ~rasops_lmask[col]; 171 rmask = ~rasops_rmask[(col + width) & 31]; 172 173 if (uc == (u_int)-1) { 174 bg = bg & ~lmask; 175 width = bg & ~rmask; 176 177 while (height--) { 178 rp[0] = (rp[0] & lmask) | bg; 179 rp[1] = (rp[1] & rmask) | width; 180 DELTA(rp, rs, int32_t *); 181 } 182 } else { 183 width = 32 - col; 184 185 /* NOT fontbits if bg is white */ 186 while (height--) { 187 fb = ~(fr[3] | (fr[2] << 8) | 188 (fr[1] << 16) | (fr[0] << 24)); 189 190 rp[0] = (rp[0] & lmask) 191 | MBE((u_int)fb >> col); 192 193 rp[1] = (rp[1] & rmask) 194 | (MBE((u_int)fb << width) & ~rmask); 195 196 fr += fs; 197 DELTA(rp, rs, int32_t *); 198 } 199 } 200 201 /* Do underline */ 202 if (attr & 1) { 203 DELTA(rp, -(ri->ri_stride << 1), int32_t *); 204 rp[0] = (rp[0] & lmask) | (fg & ~lmask); 205 rp[1] = (rp[1] & rmask) | (fg & ~rmask); 206 } 207 } 208 209 return 0; 210 } 211 #endif 212 213 /* 214 * Put a single character. This is the generic version. 215 */ 216 int 217 rasops4_putchar(cookie, row, col, uc, attr) 218 void *cookie; 219 int row, col; 220 u_int uc; 221 long attr; 222 { 223 224 /* XXX punt */ 225 return (EAGAIN); 226 } 227 228 #ifndef RASOPS_SMALL 229 /* 230 * Recompute the blitting stamp. 231 */ 232 void 233 rasops4_makestamp(ri, attr) 234 struct rasops_info *ri; 235 long attr; 236 { 237 int i, fg, bg; 238 239 fg = ri->ri_devcmap[(attr >> 24) & 0xf] & 0xf; 240 bg = ri->ri_devcmap[(attr >> 16) & 0xf] & 0xf; 241 stamp_attr = attr; 242 243 for (i = 0; i < 16; i++) { 244 #if BYTE_ORDER == LITTLE_ENDIAN 245 stamp[i] = (i & 1 ? fg : bg) << 8; 246 stamp[i] |= (i & 2 ? fg : bg) << 12; 247 stamp[i] |= (i & 4 ? fg : bg) << 0; 248 stamp[i] |= (i & 8 ? fg : bg) << 4; 249 #else 250 stamp[i] = (i & 1 ? fg : bg) << 0; 251 stamp[i] |= (i & 2 ? fg : bg) << 4; 252 stamp[i] |= (i & 4 ? fg : bg) << 8; 253 stamp[i] |= (i & 8 ? fg : bg) << 12; 254 #endif 255 } 256 } 257 258 /* 259 * Put a single character. This is for 8-pixel wide fonts. 260 */ 261 int 262 rasops4_putchar8(cookie, row, col, uc, attr) 263 void *cookie; 264 int row, col; 265 u_int uc; 266 long attr; 267 { 268 struct rasops_info *ri; 269 int height, fs, rs; 270 u_char *fr; 271 u_int16_t *rp; 272 273 /* Can't risk remaking the stamp if it's already in use */ 274 if (stamp_mutex++) { 275 stamp_mutex--; 276 return rasops4_putchar(cookie, row, col, uc, attr); 277 } 278 279 ri = (struct rasops_info *)cookie; 280 281 #ifdef RASOPS_CLIPPING 282 /* Catches 'row < 0' case too */ 283 if ((unsigned)row >= (unsigned)ri->ri_rows) { 284 stamp_mutex--; 285 return 0; 286 } 287 288 if ((unsigned)col >= (unsigned)ri->ri_cols) { 289 stamp_mutex--; 290 return 0; 291 } 292 #endif 293 294 rp = (u_int16_t *)(ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale); 295 height = ri->ri_font->fontheight; 296 rs = ri->ri_stride / sizeof(*rp); 297 298 /* Recompute stamp? */ 299 if (attr != stamp_attr) 300 rasops4_makestamp(ri, attr); 301 302 if (uc == ' ') { 303 u_int16_t c = stamp[0]; 304 while (height--) { 305 rp[0] = c; 306 rp[1] = c; 307 rp += rs; 308 } 309 } else { 310 uc -= ri->ri_font->firstchar; 311 fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale; 312 fs = ri->ri_font->stride; 313 314 while (height--) { 315 rp[0] = stamp[(*fr >> 4) & 0xf]; 316 rp[1] = stamp[*fr & 0xf]; 317 fr += fs; 318 rp += rs; 319 } 320 } 321 322 /* Do underline */ 323 if ((attr & 1) != 0) { 324 rp -= (rs << 1); 325 rp[0] = stamp[15]; 326 rp[1] = stamp[15]; 327 } 328 329 stamp_mutex--; 330 331 return 0; 332 } 333 334 /* 335 * Put a single character. This is for 12-pixel wide fonts. 336 */ 337 int 338 rasops4_putchar12(cookie, row, col, uc, attr) 339 void *cookie; 340 int row, col; 341 u_int uc; 342 long attr; 343 { 344 struct rasops_info *ri; 345 int height, fs, rs; 346 u_char *fr; 347 u_int16_t *rp; 348 349 /* Can't risk remaking the stamp if it's already in use */ 350 if (stamp_mutex++) { 351 stamp_mutex--; 352 return rasops4_putchar(cookie, row, col, uc, attr); 353 } 354 355 ri = (struct rasops_info *)cookie; 356 357 #ifdef RASOPS_CLIPPING 358 /* Catches 'row < 0' case too */ 359 if ((unsigned)row >= (unsigned)ri->ri_rows) { 360 stamp_mutex--; 361 return 0; 362 } 363 364 if ((unsigned)col >= (unsigned)ri->ri_cols) { 365 stamp_mutex--; 366 return 0; 367 } 368 #endif 369 370 rp = (u_int16_t *)(ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale); 371 height = ri->ri_font->fontheight; 372 rs = ri->ri_stride / sizeof(*rp); 373 374 /* Recompute stamp? */ 375 if (attr != stamp_attr) 376 rasops4_makestamp(ri, attr); 377 378 if (uc == ' ') { 379 u_int16_t c = stamp[0]; 380 while (height--) { 381 rp[0] = c; 382 rp[1] = c; 383 rp[2] = c; 384 rp += rs; 385 } 386 } else { 387 uc -= ri->ri_font->firstchar; 388 fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale; 389 fs = ri->ri_font->stride; 390 391 while (height--) { 392 rp[0] = stamp[(fr[0] >> 4) & 0xf]; 393 rp[1] = stamp[fr[0] & 0xf]; 394 rp[2] = stamp[(fr[1] >> 4) & 0xf]; 395 fr += fs; 396 rp += rs; 397 } 398 } 399 400 /* Do underline */ 401 if ((attr & 1) != 0) { 402 rp -= (rs << 1); 403 rp[0] = stamp[15]; 404 rp[1] = stamp[15]; 405 rp[2] = stamp[15]; 406 } 407 408 stamp_mutex--; 409 410 return 0; 411 } 412 413 /* 414 * Put a single character. This is for 16-pixel wide fonts. 415 */ 416 int 417 rasops4_putchar16(cookie, row, col, uc, attr) 418 void *cookie; 419 int row, col; 420 u_int uc; 421 long attr; 422 { 423 struct rasops_info *ri; 424 int height, fs, rs; 425 u_char *fr; 426 u_int16_t *rp; 427 428 /* Can't risk remaking the stamp if it's already in use */ 429 if (stamp_mutex++) { 430 stamp_mutex--; 431 return rasops4_putchar(cookie, row, col, uc, attr); 432 } 433 434 ri = (struct rasops_info *)cookie; 435 436 #ifdef RASOPS_CLIPPING 437 /* Catches 'row < 0' case too */ 438 if ((unsigned)row >= (unsigned)ri->ri_rows) { 439 stamp_mutex--; 440 return 0; 441 } 442 443 if ((unsigned)col >= (unsigned)ri->ri_cols) { 444 stamp_mutex--; 445 return 0; 446 } 447 #endif 448 449 rp = (u_int16_t *)(ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale); 450 height = ri->ri_font->fontheight; 451 rs = ri->ri_stride / sizeof(*rp); 452 453 /* Recompute stamp? */ 454 if (attr != stamp_attr) 455 rasops4_makestamp(ri, attr); 456 457 if (uc == ' ') { 458 u_int16_t c = stamp[0]; 459 while (height--) { 460 rp[0] = c; 461 rp[1] = c; 462 rp[2] = c; 463 rp[3] = c; 464 rp += rs; 465 } 466 } else { 467 uc -= ri->ri_font->firstchar; 468 fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale; 469 fs = ri->ri_font->stride; 470 471 while (height--) { 472 rp[0] = stamp[(fr[0] >> 4) & 0xf]; 473 rp[1] = stamp[fr[0] & 0xf]; 474 rp[2] = stamp[(fr[1] >> 4) & 0xf]; 475 rp[3] = stamp[fr[1] & 0xf]; 476 fr += fs; 477 rp += rs; 478 } 479 } 480 481 /* Do underline */ 482 if ((attr & 1) != 0) { 483 rp -= (rs << 1); 484 rp[0] = stamp[15]; 485 rp[1] = stamp[15]; 486 rp[2] = stamp[15]; 487 rp[3] = stamp[15]; 488 } 489 490 stamp_mutex--; 491 492 return 0; 493 } 494 #endif /* !RASOPS_SMALL */ 495 496 /* 497 * Grab routines common to depths where (bpp < 8) 498 */ 499 #define NAME(ident) rasops4_##ident 500 #define PIXEL_SHIFT 2 501 502 #include <dev/rasops/rasops_bitops.h> 503