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