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