1 /* $NetBSD: rasops8.c,v 1.25 2009/03/14 15:36:20 dsl Exp $ */
4 * Copyright (c) 1999 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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.
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.
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: rasops8.c,v 1.25 2009/03/14 15:36:20 dsl Exp $");
35 #include "opt_rasops.h"
37 #include <sys/param.h>
38 #include <sys/systm.h>
41 #include <dev/wscons/wsdisplayvar.h>
42 #include <dev/wscons/wsconsio.h>
43 #include <dev/rasops/rasops.h>
45 static void rasops8_putchar(void *, int, int, u_int
, long attr
);
47 static void rasops8_putchar8(void *, int, int, u_int
, long attr
);
48 static void rasops8_putchar12(void *, int, int, u_int
, long attr
);
49 static void rasops8_putchar16(void *, int, int, u_int
, long attr
);
50 static void rasops8_makestamp(struct rasops_info
*ri
, long);
53 * 4x1 stamp for optimized character blitting
55 static int32_t stamp
[16];
56 static long stamp_attr
;
57 static int stamp_mutex
; /* XXX see note in README */
61 * XXX this confuses the hell out of gcc2 (not egcs) which always insists
62 * that the shift count is negative.
64 * offset = STAMP_SHIFT(fontbits, nibble #) & STAMP_MASK
65 * destination = STAMP_READ(offset)
67 #define STAMP_SHIFT(fb,n) ((n*4-2) >= 0 ? (fb)>>(n*4-2):(fb)<<-(n*4-2))
68 #define STAMP_MASK (0xf << 2)
69 #define STAMP_READ(o) (*(int32_t *)((char *)stamp + (o)))
72 * Initialize a 'rasops_info' descriptor for this depth.
75 rasops8_init(struct rasops_info
*ri
)
78 switch (ri
->ri_font
->fontwidth
) {
81 ri
->ri_ops
.putchar
= rasops8_putchar8
;
84 ri
->ri_ops
.putchar
= rasops8_putchar12
;
87 ri
->ri_ops
.putchar
= rasops8_putchar16
;
89 #endif /* !RASOPS_SMALL */
91 ri
->ri_ops
.putchar
= rasops8_putchar
;
97 * Put a single character.
100 rasops8_putchar(void *cookie
, int row
, int col
, u_int uc
, long attr
)
102 int width
, height
, cnt
, fs
, fb
;
103 u_char
*dp
, *rp
, *hp
, *hrp
, *fr
, clr
[2];
104 struct rasops_info
*ri
;
106 ri
= (struct rasops_info
*)cookie
;
109 if (!CHAR_IN_FONT(uc
, ri
->ri_font
))
112 #ifdef RASOPS_CLIPPING
113 /* Catches 'row < 0' case too */
114 if ((unsigned)row
>= (unsigned)ri
->ri_rows
)
117 if ((unsigned)col
>= (unsigned)ri
->ri_cols
)
120 rp
= ri
->ri_bits
+ row
* ri
->ri_yscale
+ col
* ri
->ri_xscale
;
122 hrp
= ri
->ri_hwbits
+ row
* ri
->ri_yscale
+ col
*
125 height
= ri
->ri_font
->fontheight
;
126 width
= ri
->ri_font
->fontwidth
;
127 clr
[0] = (u_char
)ri
->ri_devcmap
[(attr
>> 16) & 0xf];
128 clr
[1] = (u_char
)ri
->ri_devcmap
[(attr
>> 24) & 0xf];
138 hrp
+= ri
->ri_stride
;
141 for (cnt
= width
; cnt
; cnt
--) {
148 uc
-= ri
->ri_font
->firstchar
;
149 fr
= (u_char
*)ri
->ri_font
->data
+ uc
* ri
->ri_fontscale
;
150 fs
= ri
->ri_font
->stride
;
156 fb
= fr
[3] | (fr
[2] << 8) | (fr
[1] << 16) | (fr
[0] << 24);
160 hrp
+= ri
->ri_stride
;
162 for (cnt
= width
; cnt
; cnt
--) {
163 *dp
++ = clr
[(fb
>> 31) & 1];
165 *hp
++ = clr
[(fb
>> 31) & 1];
172 if ((attr
& 1) != 0) {
175 rp
-= (ri
->ri_stride
<< 1);
177 hrp
-= (ri
->ri_stride
<< 1);
189 * Recompute the 4x1 blitting stamp.
192 rasops8_makestamp(struct rasops_info
*ri
, long attr
)
197 fg
= ri
->ri_devcmap
[(attr
>> 24) & 0xf] & 0xff;
198 bg
= ri
->ri_devcmap
[(attr
>> 16) & 0xf] & 0xff;
201 for (i
= 0; i
< 16; i
++) {
202 #if BYTE_ORDER == BIG_ENDIAN
203 #define NEED_LITTLE_ENDIAN_STAMP RI_BSWAP
205 #define NEED_LITTLE_ENDIAN_STAMP 0
207 if ((ri
->ri_flg
& RI_BSWAP
) == NEED_LITTLE_ENDIAN_STAMP
) {
209 stamp
[i
] = (i
& 8 ? fg
: bg
);
210 stamp
[i
] |= ((i
& 4 ? fg
: bg
) << 8);
211 stamp
[i
] |= ((i
& 2 ? fg
: bg
) << 16);
212 stamp
[i
] |= ((i
& 1 ? fg
: bg
) << 24);
215 stamp
[i
] = (i
& 1 ? fg
: bg
);
216 stamp
[i
] |= ((i
& 2 ? fg
: bg
) << 8);
217 stamp
[i
] |= ((i
& 4 ? fg
: bg
) << 16);
218 stamp
[i
] |= ((i
& 8 ? fg
: bg
) << 24);
224 * Put a single character. This is for 8-pixel wide fonts.
227 rasops8_putchar8(void *cookie
, int row
, int col
, u_int uc
, long attr
)
229 struct rasops_info
*ri
;
234 /* Can't risk remaking the stamp if it's already in use */
237 rasops8_putchar(cookie
, row
, col
, uc
, attr
);
241 ri
= (struct rasops_info
*)cookie
;
244 if (!CHAR_IN_FONT(uc
, ri
->ri_font
))
247 #ifdef RASOPS_CLIPPING
248 if ((unsigned)row
>= (unsigned)ri
->ri_rows
) {
253 if ((unsigned)col
>= (unsigned)ri
->ri_cols
) {
259 /* Recompute stamp? */
260 if (attr
!= stamp_attr
)
261 rasops8_makestamp(ri
, attr
);
263 rp
= (int32_t *)(ri
->ri_bits
+ row
*ri
->ri_yscale
+ col
*ri
->ri_xscale
);
265 hp
= (int32_t *)(ri
->ri_hwbits
+ row
*ri
->ri_yscale
+
267 height
= ri
->ri_font
->fontheight
;
271 rp
[0] = rp
[1] = stamp
[0];
272 DELTA(rp
, ri
->ri_stride
, int32_t *);
276 DELTA(hp
, ri
->ri_stride
, int32_t *);
280 uc
-= ri
->ri_font
->firstchar
;
281 fr
= (u_char
*)ri
->ri_font
->data
+ uc
* ri
->ri_fontscale
;
282 fs
= ri
->ri_font
->stride
;
285 rp
[0] = STAMP_READ(STAMP_SHIFT(fr
[0], 1) & STAMP_MASK
);
286 rp
[1] = STAMP_READ(STAMP_SHIFT(fr
[0], 0) & STAMP_MASK
);
288 hp
[0] = STAMP_READ(STAMP_SHIFT(fr
[0], 1) &
290 hp
[1] = STAMP_READ(STAMP_SHIFT(fr
[0], 0) &
295 DELTA(rp
, ri
->ri_stride
, int32_t *);
297 DELTA(hp
, ri
->ri_stride
, int32_t *);
302 if ((attr
& 1) != 0) {
303 DELTA(rp
, -(ri
->ri_stride
<< 1), int32_t *);
304 rp
[0] = rp
[1] = stamp
[15];
306 DELTA(hp
, -(ri
->ri_stride
<< 1), int32_t *);
316 * Put a single character. This is for 12-pixel wide fonts.
319 rasops8_putchar12(void *cookie
, int row
, int col
, u_int uc
, long attr
)
321 struct rasops_info
*ri
;
326 /* Can't risk remaking the stamp if it's already in use */
329 rasops8_putchar(cookie
, row
, col
, uc
, attr
);
333 ri
= (struct rasops_info
*)cookie
;
336 if (!CHAR_IN_FONT(uc
, ri
->ri_font
))
339 #ifdef RASOPS_CLIPPING
340 if ((unsigned)row
>= (unsigned)ri
->ri_rows
) {
345 if ((unsigned)col
>= (unsigned)ri
->ri_cols
) {
351 /* Recompute stamp? */
352 if (attr
!= stamp_attr
)
353 rasops8_makestamp(ri
, attr
);
355 rp
= (int32_t *)(ri
->ri_bits
+ row
*ri
->ri_yscale
+ col
*ri
->ri_xscale
);
357 hrp
= (int32_t *)(ri
->ri_hwbits
+ row
*ri
->ri_yscale
+
359 height
= ri
->ri_font
->fontheight
;
363 int32_t c
= stamp
[0];
365 rp
[0] = rp
[1] = rp
[2] = c
;
366 DELTA(rp
, ri
->ri_stride
, int32_t *);
371 DELTA(hrp
, ri
->ri_stride
, int32_t *);
375 uc
-= ri
->ri_font
->firstchar
;
376 fr
= (u_char
*)ri
->ri_font
->data
+ uc
* ri
->ri_fontscale
;
377 fs
= ri
->ri_font
->stride
;
380 rp
[0] = STAMP_READ(STAMP_SHIFT(fr
[0], 1) & STAMP_MASK
);
381 rp
[1] = STAMP_READ(STAMP_SHIFT(fr
[0], 0) & STAMP_MASK
);
382 rp
[2] = STAMP_READ(STAMP_SHIFT(fr
[1], 1) & STAMP_MASK
);
384 hrp
[0] = STAMP_READ(STAMP_SHIFT(fr
[0], 1) & STAMP_MASK
);
385 hrp
[1] = STAMP_READ(STAMP_SHIFT(fr
[0], 0) & STAMP_MASK
);
386 hrp
[2] = STAMP_READ(STAMP_SHIFT(fr
[1], 1) & STAMP_MASK
);
390 DELTA(rp
, ri
->ri_stride
, int32_t *);
392 DELTA(hrp
, ri
->ri_stride
, int32_t *);
397 if ((attr
& 1) != 0) {
398 DELTA(rp
, -(ri
->ri_stride
<< 1), int32_t *);
399 rp
[0] = rp
[1] = rp
[2] = stamp
[15];
401 DELTA(hrp
, -(ri
->ri_stride
<< 1), int32_t *);
412 * Put a single character. This is for 16-pixel wide fonts.
415 rasops8_putchar16(void *cookie
, int row
, int col
, u_int uc
, long attr
)
417 struct rasops_info
*ri
;
422 /* Can't risk remaking the stamp if it's already in use */
425 rasops8_putchar(cookie
, row
, col
, uc
, attr
);
429 ri
= (struct rasops_info
*)cookie
;
432 if (!CHAR_IN_FONT(uc
, ri
->ri_font
))
435 #ifdef RASOPS_CLIPPING
436 if ((unsigned)row
>= (unsigned)ri
->ri_rows
) {
441 if ((unsigned)col
>= (unsigned)ri
->ri_cols
) {
447 /* Recompute stamp? */
448 if (attr
!= stamp_attr
)
449 rasops8_makestamp(ri
, attr
);
451 rp
= (int32_t *)(ri
->ri_bits
+ row
*ri
->ri_yscale
+ col
*ri
->ri_xscale
);
453 hrp
= (int32_t *)(ri
->ri_hwbits
+ row
*ri
->ri_yscale
+
456 height
= ri
->ri_font
->fontheight
;
460 rp
[0] = rp
[1] = rp
[2] = rp
[3] = stamp
[0];
469 uc
-= ri
->ri_font
->firstchar
;
470 fr
= (u_char
*)ri
->ri_font
->data
+ uc
* ri
->ri_fontscale
;
471 fs
= ri
->ri_font
->stride
;
474 rp
[0] = STAMP_READ(STAMP_SHIFT(fr
[0], 1) & STAMP_MASK
);
475 rp
[1] = STAMP_READ(STAMP_SHIFT(fr
[0], 0) & STAMP_MASK
);
476 rp
[2] = STAMP_READ(STAMP_SHIFT(fr
[1], 1) & STAMP_MASK
);
477 rp
[3] = STAMP_READ(STAMP_SHIFT(fr
[1], 0) & STAMP_MASK
);
479 hrp
[0] = STAMP_READ(STAMP_SHIFT(fr
[0], 1) & STAMP_MASK
);
480 hrp
[1] = STAMP_READ(STAMP_SHIFT(fr
[0], 0) & STAMP_MASK
);
481 hrp
[2] = STAMP_READ(STAMP_SHIFT(fr
[1], 1) & STAMP_MASK
);
482 hrp
[3] = STAMP_READ(STAMP_SHIFT(fr
[1], 0) & STAMP_MASK
);
486 DELTA(rp
, ri
->ri_stride
, int32_t *);
488 DELTA(hrp
, ri
->ri_stride
, int32_t *);
493 if ((attr
& 1) != 0) {
494 DELTA(rp
, -(ri
->ri_stride
<< 1), int32_t *);
495 rp
[0] = rp
[1] = rp
[2] = rp
[3] = stamp
[15];
497 DELTA(hrp
, -(ri
->ri_stride
<< 1), int32_t *);
507 #endif /* !RASOPS_SMALL */