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