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