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