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