rasops8.c revision 1.27.12.1 1 /* $NetBSD: rasops8.c,v 1.27.12.1 2012/02/18 07:34:57 mrg Exp $ */
2
3 /*-
4 * Copyright (c) 1999 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Andrew Doran.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: rasops8.c,v 1.27.12.1 2012/02/18 07:34:57 mrg Exp $");
34
35 #include "opt_rasops.h"
36
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/time.h>
40
41 #include <dev/wscons/wsdisplayvar.h>
42 #include <dev/wscons/wsconsio.h>
43 #include <dev/rasops/rasops.h>
44
45 static void rasops8_putchar(void *, int, int, u_int, long attr);
46 static void rasops8_putchar_aa(void *, int, int, u_int, long attr);
47 #ifndef RASOPS_SMALL
48 static void rasops8_putchar8(void *, int, int, u_int, long attr);
49 static void rasops8_putchar12(void *, int, int, u_int, long attr);
50 static void rasops8_putchar16(void *, int, int, u_int, long attr);
51 static void rasops8_makestamp(struct rasops_info *ri, long);
52
53 /*
54 * 4x1 stamp for optimized character blitting
55 */
56 static int32_t stamp[16];
57 static long stamp_attr;
58 static int stamp_mutex; /* XXX see note in README */
59 #endif
60
61 /*
62 * XXX this confuses the hell out of gcc2 (not egcs) which always insists
63 * that the shift count is negative.
64 *
65 * offset = STAMP_SHIFT(fontbits, nibble #) & STAMP_MASK
66 * destination = STAMP_READ(offset)
67 */
68 #define STAMP_SHIFT(fb,n) ((n*4-2) >= 0 ? (fb)>>(n*4-2):(fb)<<-(n*4-2))
69 #define STAMP_MASK (0xf << 2)
70 #define STAMP_READ(o) (*(int32_t *)((char *)stamp + (o)))
71
72 /*
73 * Initialize a 'rasops_info' descriptor for this depth.
74 */
75 void
76 rasops8_init(struct rasops_info *ri)
77 {
78
79 if FONT_IS_ALPHA(ri->ri_font) {
80 ri->ri_ops.putchar = rasops8_putchar_aa;
81 } else {
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 if (ri->ri_flg & RI_8BIT_IS_RGB) {
100 ri->ri_rnum = 3;
101 ri->ri_rpos = 5;
102 ri->ri_gnum = 3;
103 ri->ri_gpos = 2;
104 ri->ri_bnum = 2;
105 ri->ri_bpos = 0;
106 }
107 }
108
109 /*
110 * Put a single character.
111 */
112 static void
113 rasops8_putchar(void *cookie, int row, int col, u_int uc, long attr)
114 {
115 int width, height, cnt, fs, fb;
116 u_char *dp, *rp, *hp, *hrp, *fr, clr[2];
117 struct rasops_info *ri = (struct rasops_info *)cookie;
118 struct wsdisplay_font *font = PICK_FONT(ri, uc);
119
120 hp = hrp = NULL;
121
122 if (!CHAR_IN_FONT(uc, font))
123 return;
124
125 #ifdef RASOPS_CLIPPING
126 /* Catches 'row < 0' case too */
127 if ((unsigned)row >= (unsigned)ri->ri_rows)
128 return;
129
130 if ((unsigned)col >= (unsigned)ri->ri_cols)
131 return;
132 #endif
133 rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
134 if (ri->ri_hwbits)
135 hrp = ri->ri_hwbits + row * ri->ri_yscale + col *
136 ri->ri_xscale;
137
138 height = font->fontheight;
139 width = font->fontwidth;
140 clr[0] = (u_char)ri->ri_devcmap[(attr >> 16) & 0xf];
141 clr[1] = (u_char)ri->ri_devcmap[(attr >> 24) & 0xf];
142
143 if (uc == ' ') {
144 u_char c = clr[0];
145
146 while (height--) {
147 memset(rp, c, width);
148 if (ri->ri_hwbits) {
149 memset(hrp, c, width);
150 hrp += ri->ri_stride;
151 }
152 rp += ri->ri_stride;
153 }
154 } else {
155 fr = WSFONT_GLYPH(uc, font);
156 fs = font->stride;
157
158 while (height--) {
159 dp = rp;
160 if (ri->ri_hwbits)
161 hp = hrp;
162 fb = fr[3] | (fr[2] << 8) | (fr[1] << 16) | (fr[0] << 24);
163 fr += fs;
164 rp += ri->ri_stride;
165 if (ri->ri_hwbits)
166 hrp += ri->ri_stride;
167
168 for (cnt = width; cnt; cnt--) {
169 *dp++ = clr[(fb >> 31) & 1];
170 if (ri->ri_hwbits)
171 *hp++ = clr[(fb >> 31) & 1];
172 fb <<= 1;
173 }
174 }
175 }
176
177 /* Do underline */
178 if ((attr & 1) != 0) {
179 u_char c = clr[1];
180
181 rp -= (ri->ri_stride << 1);
182 if (ri->ri_hwbits)
183 hrp -= (ri->ri_stride << 1);
184
185 while (width--) {
186 *rp++ = c;
187 if (ri->ri_hwbits)
188 *hrp++ = c;
189 }
190 }
191 }
192
193 static void
194 rasops8_putchar_aa(void *cookie, int row, int col, u_int uc, long attr)
195 {
196 int width, height, fs;
197 u_char *dp, *rp, *hp, *hrp, *fr, bg, fg, pixel;
198 struct rasops_info *ri = (struct rasops_info *)cookie;
199 struct wsdisplay_font *font = PICK_FONT(ri, uc);
200 int x, y, r, g, b, aval;
201 int r1, g1, b1, r0, g0, b0, fgo, bgo;
202 uint8_t scanline[32] __attribute__ ((aligned(8)));
203
204 hp = hrp = NULL;
205
206 if (!CHAR_IN_FONT(uc, font))
207 return;
208
209 #ifdef RASOPS_CLIPPING
210 /* Catches 'row < 0' case too */
211 if ((unsigned)row >= (unsigned)ri->ri_rows)
212 return;
213
214 if ((unsigned)col >= (unsigned)ri->ri_cols)
215 return;
216 #endif
217 rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
218 if (ri->ri_hwbits)
219 hrp = ri->ri_hwbits + row * ri->ri_yscale + col *
220 ri->ri_xscale;
221
222 height = font->fontheight;
223 width = font->fontwidth;
224 bg = (u_char)ri->ri_devcmap[(attr >> 16) & 0xf];
225 fg = (u_char)ri->ri_devcmap[(attr >> 24) & 0xf];
226
227 if (uc == ' ') {
228
229 while (height--) {
230 memset(rp, bg, width);
231 if (ri->ri_hwbits) {
232 memset(hrp, bg, width);
233 hrp += ri->ri_stride;
234 }
235 rp += ri->ri_stride;
236 }
237 } else {
238 fr = WSFONT_GLYPH(uc, font);
239 fs = font->stride;
240 /*
241 * we need the RGB colours here, get offsets into rasops_cmap
242 */
243 fgo = ((attr >> 24) & 0xf) * 3;
244 bgo = ((attr >> 16) & 0xf) * 3;
245
246 r0 = rasops_cmap[bgo];
247 r1 = rasops_cmap[fgo];
248 g0 = rasops_cmap[bgo + 1];
249 g1 = rasops_cmap[fgo + 1];
250 b0 = rasops_cmap[bgo + 2];
251 b1 = rasops_cmap[fgo + 2];
252
253 for (y = 0; y < height; y++) {
254 dp = rp;
255 for (x = 0; x < width; x++) {
256 aval = *fr;
257 fr++;
258 if (aval == 0) {
259 pixel = bg;
260 } else if (aval == 255) {
261 pixel = fg;
262 } else {
263 r = aval * r1 + (255 - aval) * r0;
264 g = aval * g1 + (255 - aval) * g0;
265 b = aval * b1 + (255 - aval) * b0;
266 pixel = ((r & 0xe000) >> 8) |
267 ((g & 0xe000) >> 11) |
268 ((b & 0xc000) >> 14);
269 }
270 scanline[x] = pixel;
271 }
272 memcpy(rp, scanline, width);
273 if (ri->ri_hwbits) {
274 memcpy(hrp, scanline, width);
275 hrp += ri->ri_stride;
276 }
277 rp += ri->ri_stride;
278
279 }
280 }
281
282 /* Do underline */
283 if ((attr & 1) != 0) {
284
285 rp -= (ri->ri_stride << 1);
286 if (ri->ri_hwbits)
287 hrp -= (ri->ri_stride << 1);
288
289 while (width--) {
290 *rp++ = fg;
291 if (ri->ri_hwbits)
292 *hrp++ = fg;
293 }
294 }
295 }
296
297 #ifndef RASOPS_SMALL
298 /*
299 * Recompute the 4x1 blitting stamp.
300 */
301 static void
302 rasops8_makestamp(struct rasops_info *ri, long attr)
303 {
304 int32_t fg, bg;
305 int i;
306
307 fg = ri->ri_devcmap[(attr >> 24) & 0xf] & 0xff;
308 bg = ri->ri_devcmap[(attr >> 16) & 0xf] & 0xff;
309 stamp_attr = attr;
310
311 for (i = 0; i < 16; i++) {
312 #if BYTE_ORDER == BIG_ENDIAN
313 #define NEED_LITTLE_ENDIAN_STAMP RI_BSWAP
314 #else
315 #define NEED_LITTLE_ENDIAN_STAMP 0
316 #endif
317 if ((ri->ri_flg & RI_BSWAP) == NEED_LITTLE_ENDIAN_STAMP) {
318 /* little endian */
319 stamp[i] = (i & 8 ? fg : bg);
320 stamp[i] |= ((i & 4 ? fg : bg) << 8);
321 stamp[i] |= ((i & 2 ? fg : bg) << 16);
322 stamp[i] |= ((i & 1 ? fg : bg) << 24);
323 } else {
324 /* big endian */
325 stamp[i] = (i & 1 ? fg : bg);
326 stamp[i] |= ((i & 2 ? fg : bg) << 8);
327 stamp[i] |= ((i & 4 ? fg : bg) << 16);
328 stamp[i] |= ((i & 8 ? fg : bg) << 24);
329 }
330 }
331 }
332
333 /*
334 * Put a single character. This is for 8-pixel wide fonts.
335 */
336 static void
337 rasops8_putchar8(void *cookie, int row, int col, u_int uc, long attr)
338 {
339 struct rasops_info *ri = (struct rasops_info *)cookie;
340 struct wsdisplay_font *font = PICK_FONT(ri, uc);
341 int height, fs;
342 int32_t *rp, *hp;
343 u_char *fr;
344
345 /* Can't risk remaking the stamp if it's already in use */
346 if (stamp_mutex++) {
347 stamp_mutex--;
348 rasops8_putchar(cookie, row, col, uc, attr);
349 return;
350 }
351
352 hp = NULL;
353
354 if (!CHAR_IN_FONT(uc, font))
355 return;
356
357 #ifdef RASOPS_CLIPPING
358 if ((unsigned)row >= (unsigned)ri->ri_rows) {
359 stamp_mutex--;
360 return;
361 }
362
363 if ((unsigned)col >= (unsigned)ri->ri_cols) {
364 stamp_mutex--;
365 return;
366 }
367 #endif
368
369 /* Recompute stamp? */
370 if (attr != stamp_attr)
371 rasops8_makestamp(ri, attr);
372
373 rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
374 if (ri->ri_hwbits)
375 hp = (int32_t *)(ri->ri_hwbits + row*ri->ri_yscale +
376 col*ri->ri_xscale);
377 height = font->fontheight;
378
379 if (uc == ' ') {
380 while (height--) {
381 rp[0] = rp[1] = stamp[0];
382 DELTA(rp, ri->ri_stride, int32_t *);
383 if (ri->ri_hwbits) {
384 hp[0] = stamp[0];
385 hp[1] = stamp[0];
386 DELTA(hp, ri->ri_stride, int32_t *);
387 }
388 }
389 } else {
390 fr = WSFONT_GLYPH(uc, font);
391 fs = font->stride;
392
393 while (height--) {
394 rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
395 rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
396 if (ri->ri_hwbits) {
397 hp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) &
398 STAMP_MASK);
399 hp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) &
400 STAMP_MASK);
401 }
402
403 fr += fs;
404 DELTA(rp, ri->ri_stride, int32_t *);
405 if (ri->ri_hwbits)
406 DELTA(hp, 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] = stamp[15];
414 if (ri->ri_hwbits) {
415 DELTA(hp, -(ri->ri_stride << 1), int32_t *);
416 hp[0] = stamp[15];
417 hp[1] = stamp[15];
418 }
419 }
420
421 stamp_mutex--;
422 }
423
424 /*
425 * Put a single character. This is for 12-pixel wide fonts.
426 */
427 static void
428 rasops8_putchar12(void *cookie, int row, int col, u_int uc, long attr)
429 {
430 struct rasops_info *ri = (struct rasops_info *)cookie;
431 struct wsdisplay_font *font = PICK_FONT(ri, uc);
432 int height, fs;
433 int32_t *rp, *hrp;
434 u_char *fr;
435
436 /* Can't risk remaking the stamp if it's already in use */
437 if (stamp_mutex++) {
438 stamp_mutex--;
439 rasops8_putchar(cookie, row, col, uc, attr);
440 return;
441 }
442
443 hrp = NULL;
444
445 if (!CHAR_IN_FONT(uc, font))
446 return;
447
448 #ifdef RASOPS_CLIPPING
449 if ((unsigned)row >= (unsigned)ri->ri_rows) {
450 stamp_mutex--;
451 return;
452 }
453
454 if ((unsigned)col >= (unsigned)ri->ri_cols) {
455 stamp_mutex--;
456 return;
457 }
458 #endif
459
460 /* Recompute stamp? */
461 if (attr != stamp_attr)
462 rasops8_makestamp(ri, attr);
463
464 rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
465 if (ri->ri_hwbits)
466 hrp = (int32_t *)(ri->ri_hwbits + row*ri->ri_yscale +
467 col*ri->ri_xscale);
468 height = font->fontheight;
469
470 if (uc == ' ') {
471 while (height--) {
472 int32_t c = stamp[0];
473
474 rp[0] = rp[1] = rp[2] = c;
475 DELTA(rp, ri->ri_stride, int32_t *);
476 if (ri->ri_hwbits) {
477 hrp[0] = c;
478 hrp[1] = c;
479 hrp[2] = c;
480 DELTA(hrp, ri->ri_stride, int32_t *);
481 }
482 }
483 } else {
484 fr = WSFONT_GLYPH(uc, font);
485 fs = font->stride;
486
487 while (height--) {
488 rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
489 rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
490 rp[2] = STAMP_READ(STAMP_SHIFT(fr[1], 1) & STAMP_MASK);
491 if (ri->ri_hwbits) {
492 hrp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
493 hrp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
494 hrp[2] = STAMP_READ(STAMP_SHIFT(fr[1], 1) & STAMP_MASK);
495 }
496
497 fr += fs;
498 DELTA(rp, ri->ri_stride, int32_t *);
499 if (ri->ri_hwbits)
500 DELTA(hrp, ri->ri_stride, int32_t *);
501 }
502 }
503
504 /* Do underline */
505 if ((attr & 1) != 0) {
506 DELTA(rp, -(ri->ri_stride << 1), int32_t *);
507 rp[0] = rp[1] = rp[2] = stamp[15];
508 if (ri->ri_hwbits) {
509 DELTA(hrp, -(ri->ri_stride << 1), int32_t *);
510 hrp[0] = stamp[15];
511 hrp[1] = stamp[15];
512 hrp[2] = stamp[15];
513 }
514 }
515
516 stamp_mutex--;
517 }
518
519 /*
520 * Put a single character. This is for 16-pixel wide fonts.
521 */
522 static void
523 rasops8_putchar16(void *cookie, int row, int col, u_int uc, long attr)
524 {
525 struct rasops_info *ri = (struct rasops_info *)cookie;
526 struct wsdisplay_font *font = PICK_FONT(ri, uc);
527 int height, fs;
528 int32_t *rp, *hrp;
529 u_char *fr;
530
531 /* Can't risk remaking the stamp if it's already in use */
532 if (stamp_mutex++) {
533 stamp_mutex--;
534 rasops8_putchar(cookie, row, col, uc, attr);
535 return;
536 }
537
538 hrp = NULL;
539
540 if (!CHAR_IN_FONT(uc, font))
541 return;
542
543 #ifdef RASOPS_CLIPPING
544 if ((unsigned)row >= (unsigned)ri->ri_rows) {
545 stamp_mutex--;
546 return;
547 }
548
549 if ((unsigned)col >= (unsigned)ri->ri_cols) {
550 stamp_mutex--;
551 return;
552 }
553 #endif
554
555 /* Recompute stamp? */
556 if (attr != stamp_attr)
557 rasops8_makestamp(ri, attr);
558
559 rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
560 if (ri->ri_hwbits)
561 hrp = (int32_t *)(ri->ri_hwbits + row*ri->ri_yscale +
562 col*ri->ri_xscale);
563
564 height = font->fontheight;
565
566 if (uc == ' ') {
567 while (height--) {
568 rp[0] = rp[1] = rp[2] = rp[3] = stamp[0];
569 if (ri->ri_hwbits) {
570 hrp[0] = stamp[0];
571 hrp[1] = stamp[0];
572 hrp[2] = stamp[0];
573 hrp[3] = stamp[0];
574 }
575 }
576 } else {
577 fr = WSFONT_GLYPH(uc, font);
578 fs = font->stride;
579
580 while (height--) {
581 rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
582 rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
583 rp[2] = STAMP_READ(STAMP_SHIFT(fr[1], 1) & STAMP_MASK);
584 rp[3] = STAMP_READ(STAMP_SHIFT(fr[1], 0) & STAMP_MASK);
585 if (ri->ri_hwbits) {
586 hrp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
587 hrp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
588 hrp[2] = STAMP_READ(STAMP_SHIFT(fr[1], 1) & STAMP_MASK);
589 hrp[3] = STAMP_READ(STAMP_SHIFT(fr[1], 0) & STAMP_MASK);
590 }
591
592 fr += fs;
593 DELTA(rp, ri->ri_stride, int32_t *);
594 if (ri->ri_hwbits)
595 DELTA(hrp, ri->ri_stride, int32_t *);
596 }
597 }
598
599 /* Do underline */
600 if ((attr & 1) != 0) {
601 DELTA(rp, -(ri->ri_stride << 1), int32_t *);
602 rp[0] = rp[1] = rp[2] = rp[3] = stamp[15];
603 if (ri->ri_hwbits) {
604 DELTA(hrp, -(ri->ri_stride << 1), int32_t *);
605 hrp[0] = stamp[15];
606 hrp[1] = stamp[15];
607 hrp[2] = stamp[15];
608 hrp[3] = stamp[15];
609 }
610 }
611
612 stamp_mutex--;
613 }
614 #endif /* !RASOPS_SMALL */
615