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