1 /* $OpenBSD: rasops4.c,v 1.13 2023/01/18 11:08:49 nicm Exp $ */ 2 /* $NetBSD: rasops4.c,v 1.4 2001/11/15 09:48:15 lukem 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 #include <dev/rasops/rasops_masks.h> 42 43 int rasops4_copycols(void *, int, int, int, int); 44 int rasops4_erasecols(void *, int, int, int, uint32_t); 45 int rasops4_do_cursor(struct rasops_info *); 46 int rasops4_putchar(void *, int, int col, u_int, uint32_t); 47 #ifndef RASOPS_SMALL 48 int rasops4_putchar8(void *, int, int col, u_int, uint32_t); 49 int rasops4_putchar12(void *, int, int col, u_int, uint32_t); 50 int rasops4_putchar16(void *, int, int col, u_int, uint32_t); 51 void rasops4_makestamp(struct rasops_info *, uint32_t); 52 53 /* 54 * 4x1 stamp for optimized character blitting 55 */ 56 static u_int16_t stamp[16]; 57 static uint32_t stamp_attr; 58 static int stamp_mutex; /* XXX see note in README */ 59 #endif 60 61 /* 62 * Initialize rasops_info struct for this colordepth. 63 */ 64 void 65 rasops4_init(struct rasops_info *ri) 66 { 67 rasops_masks_init(); 68 69 switch (ri->ri_font->fontwidth) { 70 #ifndef RASOPS_SMALL 71 case 8: 72 ri->ri_ops.putchar = rasops4_putchar8; 73 break; 74 case 12: 75 ri->ri_ops.putchar = rasops4_putchar12; 76 break; 77 case 16: 78 ri->ri_ops.putchar = rasops4_putchar16; 79 break; 80 #endif /* !RASOPS_SMALL */ 81 default: 82 panic("fontwidth not 8/12/16 or RASOPS_SMALL - fixme!"); 83 ri->ri_ops.putchar = rasops4_putchar; 84 break; 85 } 86 87 if ((ri->ri_font->fontwidth & 1) != 0) { 88 ri->ri_ops.erasecols = rasops4_erasecols; 89 ri->ri_ops.copycols = rasops4_copycols; 90 ri->ri_do_cursor = rasops4_do_cursor; 91 } 92 } 93 94 #ifdef notyet 95 /* 96 * Paint a single character. This is the generic version, this is ugly. 97 */ 98 int 99 rasops4_putchar(void *cookie, int row, int col, u_int uc, uint32_t attr) 100 { 101 int height, width, fs, rs, fb, bg, fg, lmask, rmask; 102 struct rasops_info *ri; 103 int32_t *rp; 104 u_char *fr; 105 106 ri = (struct rasops_info *)cookie; 107 108 #ifdef RASOPS_CLIPPING 109 /* Catches 'row < 0' case too */ 110 if ((unsigned)row >= (unsigned)ri->ri_rows) 111 return 0; 112 113 if ((unsigned)col >= (unsigned)ri->ri_cols) 114 return 0; 115 #endif 116 117 width = ri->ri_font->fontwidth << 1; 118 height = ri->ri_font->fontheight; 119 col *= width; 120 rp = (int32_t *)(ri->ri_bits + row * ri->ri_yscale + ((col >> 3) & ~3)); 121 col = col & 31; 122 rs = ri->ri_stride; 123 124 bg = ri->ri_devcmap[(attr >> 16) & 0xf]; 125 fg = ri->ri_devcmap[(attr >> 24) & 0xf]; 126 127 /* If fg and bg match this becomes a space character */ 128 if (fg == bg || uc == ' ') { 129 uc = (u_int)-1; 130 fr = 0; /* shutup gcc */ 131 fs = 0; /* shutup gcc */ 132 } else { 133 uc -= ri->ri_font->firstchar; 134 fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale; 135 fs = ri->ri_font->stride; 136 } 137 138 /* Single word, one mask */ 139 if ((col + width) <= 32) { 140 rmask = rasops_pmask[col][width]; 141 lmask = ~rmask; 142 143 if (uc == (u_int)-1) { 144 bg &= rmask; 145 146 while (height--) { 147 *rp = (*rp & lmask) | bg; 148 DELTA(rp, rs, int32_t *); 149 } 150 } else { 151 while (height--) { 152 /* get bits, mask */ 153 /* compose sl */ 154 /* mask sl */ 155 /* put word */ 156 } 157 } 158 159 /* Do underline */ 160 if (attr & WSATTR_UNDERLINE) { 161 DELTA(rp, -(ri->ri_stride << 1), int32_t *); 162 *rp = (*rp & lmask) | (fg & rmask); 163 } 164 } else { 165 lmask = ~rasops_lmask[col]; 166 rmask = ~rasops_rmask[(col + width) & 31]; 167 168 if (uc == (u_int)-1) { 169 bg = bg & ~lmask; 170 width = bg & ~rmask; 171 172 while (height--) { 173 rp[0] = (rp[0] & lmask) | bg; 174 rp[1] = (rp[1] & rmask) | width; 175 DELTA(rp, rs, int32_t *); 176 } 177 } else { 178 width = 32 - col; 179 180 /* NOT fontbits if bg is white */ 181 while (height--) { 182 fb = ~(fr[3] | (fr[2] << 8) | 183 (fr[1] << 16) | (fr[0] << 24)); 184 185 rp[0] = (rp[0] & lmask) 186 | MBE((u_int)fb >> col); 187 188 rp[1] = (rp[1] & rmask) 189 | (MBE((u_int)fb << width) & ~rmask); 190 191 fr += fs; 192 DELTA(rp, rs, int32_t *); 193 } 194 } 195 196 /* Do underline */ 197 if (attr & WSATTR_UNDERLINE) { 198 DELTA(rp, -(ri->ri_stride << 1), int32_t *); 199 rp[0] = (rp[0] & lmask) | (fg & ~lmask); 200 rp[1] = (rp[1] & rmask) | (fg & ~rmask); 201 } 202 } 203 204 return 0; 205 } 206 #endif 207 208 /* 209 * Put a single character. This is the generic version. 210 */ 211 int 212 rasops4_putchar(void *cookie, int row, int col, u_int uc, uint32_t attr) 213 { 214 215 /* XXX punt */ 216 return (EAGAIN); 217 } 218 219 #ifndef RASOPS_SMALL 220 /* 221 * Recompute the blitting stamp. 222 */ 223 void 224 rasops4_makestamp(struct rasops_info *ri, uint32_t attr) 225 { 226 int i, fg, bg; 227 228 fg = ri->ri_devcmap[(attr >> 24) & 0xf] & 0xf; 229 bg = ri->ri_devcmap[(attr >> 16) & 0xf] & 0xf; 230 stamp_attr = attr; 231 232 for (i = 0; i < 16; i++) { 233 #if BYTE_ORDER == LITTLE_ENDIAN 234 stamp[i] = (i & 1 ? fg : bg) << 8; 235 stamp[i] |= (i & 2 ? fg : bg) << 12; 236 stamp[i] |= (i & 4 ? fg : bg) << 0; 237 stamp[i] |= (i & 8 ? fg : bg) << 4; 238 #else 239 stamp[i] = (i & 1 ? fg : bg) << 0; 240 stamp[i] |= (i & 2 ? fg : bg) << 4; 241 stamp[i] |= (i & 4 ? fg : bg) << 8; 242 stamp[i] |= (i & 8 ? fg : bg) << 12; 243 #endif 244 } 245 } 246 247 /* 248 * Put a single character. This is for 8-pixel wide fonts. 249 */ 250 int 251 rasops4_putchar8(void *cookie, int row, int col, u_int uc, uint32_t attr) 252 { 253 struct rasops_info *ri; 254 int height, fs, rs; 255 u_char *fr; 256 u_int16_t *rp; 257 258 /* Can't risk remaking the stamp if it's already in use */ 259 if (stamp_mutex++) { 260 stamp_mutex--; 261 return rasops4_putchar(cookie, row, col, uc, attr); 262 } 263 264 ri = (struct rasops_info *)cookie; 265 266 #ifdef RASOPS_CLIPPING 267 /* Catches 'row < 0' case too */ 268 if ((unsigned)row >= (unsigned)ri->ri_rows) { 269 stamp_mutex--; 270 return 0; 271 } 272 273 if ((unsigned)col >= (unsigned)ri->ri_cols) { 274 stamp_mutex--; 275 return 0; 276 } 277 #endif 278 279 rp = (u_int16_t *)(ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale); 280 height = ri->ri_font->fontheight; 281 rs = ri->ri_stride / sizeof(*rp); 282 283 /* Recompute stamp? */ 284 if (attr != stamp_attr) 285 rasops4_makestamp(ri, attr); 286 287 if (uc == ' ') { 288 u_int16_t c = stamp[0]; 289 while (height--) { 290 rp[0] = c; 291 rp[1] = c; 292 rp += rs; 293 } 294 } else { 295 uc -= ri->ri_font->firstchar; 296 fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale; 297 fs = ri->ri_font->stride; 298 299 while (height--) { 300 rp[0] = stamp[(*fr >> 4) & 0xf]; 301 rp[1] = stamp[*fr & 0xf]; 302 fr += fs; 303 rp += rs; 304 } 305 } 306 307 /* Do underline */ 308 if ((attr & WSATTR_UNDERLINE) != 0) { 309 rp -= (rs << 1); 310 rp[0] = stamp[15]; 311 rp[1] = stamp[15]; 312 } 313 314 stamp_mutex--; 315 316 return 0; 317 } 318 319 /* 320 * Put a single character. This is for 12-pixel wide fonts. 321 */ 322 int 323 rasops4_putchar12(void *cookie, int row, int col, u_int uc, uint32_t attr) 324 { 325 struct rasops_info *ri; 326 int height, fs, rs; 327 u_char *fr; 328 u_int16_t *rp; 329 330 /* Can't risk remaking the stamp if it's already in use */ 331 if (stamp_mutex++) { 332 stamp_mutex--; 333 return rasops4_putchar(cookie, row, col, uc, attr); 334 } 335 336 ri = (struct rasops_info *)cookie; 337 338 #ifdef RASOPS_CLIPPING 339 /* Catches 'row < 0' case too */ 340 if ((unsigned)row >= (unsigned)ri->ri_rows) { 341 stamp_mutex--; 342 return 0; 343 } 344 345 if ((unsigned)col >= (unsigned)ri->ri_cols) { 346 stamp_mutex--; 347 return 0; 348 } 349 #endif 350 351 rp = (u_int16_t *)(ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale); 352 height = ri->ri_font->fontheight; 353 rs = ri->ri_stride / sizeof(*rp); 354 355 /* Recompute stamp? */ 356 if (attr != stamp_attr) 357 rasops4_makestamp(ri, attr); 358 359 if (uc == ' ') { 360 u_int16_t c = stamp[0]; 361 while (height--) { 362 rp[0] = c; 363 rp[1] = c; 364 rp[2] = c; 365 rp += rs; 366 } 367 } else { 368 uc -= ri->ri_font->firstchar; 369 fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale; 370 fs = ri->ri_font->stride; 371 372 while (height--) { 373 rp[0] = stamp[(fr[0] >> 4) & 0xf]; 374 rp[1] = stamp[fr[0] & 0xf]; 375 rp[2] = stamp[(fr[1] >> 4) & 0xf]; 376 fr += fs; 377 rp += rs; 378 } 379 } 380 381 /* Do underline */ 382 if ((attr & WSATTR_UNDERLINE) != 0) { 383 rp -= (rs << 1); 384 rp[0] = stamp[15]; 385 rp[1] = stamp[15]; 386 rp[2] = stamp[15]; 387 } 388 389 stamp_mutex--; 390 391 return 0; 392 } 393 394 /* 395 * Put a single character. This is for 16-pixel wide fonts. 396 */ 397 int 398 rasops4_putchar16(void *cookie, int row, int col, u_int uc, uint32_t attr) 399 { 400 struct rasops_info *ri; 401 int height, fs, rs; 402 u_char *fr; 403 u_int16_t *rp; 404 405 /* Can't risk remaking the stamp if it's already in use */ 406 if (stamp_mutex++) { 407 stamp_mutex--; 408 return rasops4_putchar(cookie, row, col, uc, attr); 409 } 410 411 ri = (struct rasops_info *)cookie; 412 413 #ifdef RASOPS_CLIPPING 414 /* Catches 'row < 0' case too */ 415 if ((unsigned)row >= (unsigned)ri->ri_rows) { 416 stamp_mutex--; 417 return 0; 418 } 419 420 if ((unsigned)col >= (unsigned)ri->ri_cols) { 421 stamp_mutex--; 422 return 0; 423 } 424 #endif 425 426 rp = (u_int16_t *)(ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale); 427 height = ri->ri_font->fontheight; 428 rs = ri->ri_stride / sizeof(*rp); 429 430 /* Recompute stamp? */ 431 if (attr != stamp_attr) 432 rasops4_makestamp(ri, attr); 433 434 if (uc == ' ') { 435 u_int16_t c = stamp[0]; 436 while (height--) { 437 rp[0] = c; 438 rp[1] = c; 439 rp[2] = c; 440 rp[3] = c; 441 rp += rs; 442 } 443 } else { 444 uc -= ri->ri_font->firstchar; 445 fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale; 446 fs = ri->ri_font->stride; 447 448 while (height--) { 449 rp[0] = stamp[(fr[0] >> 4) & 0xf]; 450 rp[1] = stamp[fr[0] & 0xf]; 451 rp[2] = stamp[(fr[1] >> 4) & 0xf]; 452 rp[3] = stamp[fr[1] & 0xf]; 453 fr += fs; 454 rp += rs; 455 } 456 } 457 458 /* Do underline */ 459 if ((attr & WSATTR_UNDERLINE) != 0) { 460 rp -= (rs << 1); 461 rp[0] = stamp[15]; 462 rp[1] = stamp[15]; 463 rp[2] = stamp[15]; 464 rp[3] = stamp[15]; 465 } 466 467 stamp_mutex--; 468 469 return 0; 470 } 471 #endif /* !RASOPS_SMALL */ 472 473 /* 474 * Grab routines common to depths where (bpp < 8) 475 */ 476 #define NAME(ident) rasops4_##ident 477 #define PIXEL_SHIFT 2 478 479 #include <dev/rasops/rasops_bitops.h> 480