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