1 /* $NetBSD: rasops15.c,v 1.17 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: rasops15.c,v 1.17 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 rasops15_putchar(void *, int, int, u_int
, long attr
);
47 static void rasops15_putchar8(void *, int, int, u_int
, long attr
);
48 static void rasops15_putchar12(void *, int, int, u_int
, long attr
);
49 static void rasops15_putchar16(void *, int, int, u_int
, long attr
);
50 static void rasops15_makestamp(struct rasops_info
*, long);
55 * (2x2)x1 stamp for optimized character blitting
57 static int32_t stamp
[32];
58 static long stamp_attr
;
59 static int stamp_mutex
; /* XXX see note in readme */
62 * XXX this confuses the hell out of gcc2 (not egcs) which always insists
63 * that the shift count is negative.
65 * offset = STAMP_SHIFT(fontbits, nibble #) & STAMP_MASK
66 * destination int32_t[0] = STAMP_READ(offset)
67 * destination int32_t[1] = STAMP_READ(offset + 4)
69 #define STAMP_SHIFT(fb,n) ((n*4-3) >= 0 ? (fb)>>(n*4-3):(fb)<<-(n*4-3))
70 #define STAMP_MASK (15 << 3)
71 #define STAMP_READ(o) (*(int32_t *)((char *)stamp + (o)))
75 * Initialize rasops_info struct for this colordepth.
78 rasops15_init(struct rasops_info
*ri
)
81 switch (ri
->ri_font
->fontwidth
) {
84 ri
->ri_ops
.putchar
= rasops15_putchar8
;
88 ri
->ri_ops
.putchar
= rasops15_putchar12
;
92 ri
->ri_ops
.putchar
= rasops15_putchar16
;
94 #endif /* !RASOPS_SMALL */
96 ri
->ri_ops
.putchar
= rasops15_putchar
;
100 if (ri
->ri_rnum
== 0) {
103 ri
->ri_gnum
= 5 + (ri
->ri_depth
== 16);
106 ri
->ri_bpos
= 10 + (ri
->ri_depth
== 16);
111 * Paint a single character.
114 rasops15_putchar(void *cookie
, int row
, int col
, u_int uc
, long attr
)
116 int fb
, width
, height
, cnt
, clr
[2];
117 struct rasops_info
*ri
;
118 u_char
*dp
, *rp
, *hp
, *hrp
, *fr
;
120 ri
= (struct rasops_info
*)cookie
;
123 #ifdef RASOPS_CLIPPING
124 /* Catches 'row < 0' case too */
125 if ((unsigned)row
>= (unsigned)ri
->ri_rows
)
128 if ((unsigned)col
>= (unsigned)ri
->ri_cols
)
132 rp
= ri
->ri_bits
+ row
* ri
->ri_yscale
+ col
* ri
->ri_xscale
;
134 hrp
= ri
->ri_hwbits
+ row
* ri
->ri_yscale
+
136 height
= ri
->ri_font
->fontheight
;
137 width
= ri
->ri_font
->fontwidth
;
139 clr
[1] = ri
->ri_devcmap
[((u_int
)attr
>> 24) & 0xf];
140 clr
[0] = ri
->ri_devcmap
[((u_int
)attr
>> 16) & 0xf];
143 int16_t c
= (int16_t)clr
[0];
149 hrp
+= ri
->ri_stride
;
152 for (cnt
= width
; cnt
; cnt
--) {
162 uc
-= ri
->ri_font
->firstchar
;
163 fr
= (u_char
*)ri
->ri_font
->data
+ uc
* ri
->ri_fontscale
;
167 fb
= fr
[3] | (fr
[2] << 8) | (fr
[1] << 16) | (fr
[0] << 24);
168 fr
+= ri
->ri_font
->stride
;
172 hrp
+= ri
->ri_stride
;
175 for (cnt
= width
; cnt
; cnt
--) {
176 *(int16_t *)dp
= (int16_t)clr
[(fb
>> 31) & 1];
179 (int16_t)clr
[(fb
>> 31) & 1];
189 if ((attr
& 1) != 0) {
190 int16_t c
= (int16_t)clr
[1];
191 rp
-= ri
->ri_stride
<< 1;
193 hrp
-= ri
->ri_stride
<< 1;
208 * Recompute the (2x2)x1 blitting stamp.
211 rasops15_makestamp(struct rasops_info
*ri
, long attr
)
216 fg
= ri
->ri_devcmap
[((u_int
)attr
>> 24) & 0xf] & 0xffff;
217 bg
= ri
->ri_devcmap
[((u_int
)attr
>> 16) & 0xf] & 0xffff;
220 for (i
= 0; i
< 32; i
+= 2) {
221 #if BYTE_ORDER == LITTLE_ENDIAN
222 stamp
[i
] = (i
& 16 ? fg
: bg
);
223 stamp
[i
] |= ((i
& 8 ? fg
: bg
) << 16);
224 stamp
[i
+ 1] = (i
& 4 ? fg
: bg
);
225 stamp
[i
+ 1] |= ((i
& 2 ? fg
: bg
) << 16);
227 stamp
[i
] = (i
& 2 ? fg
: bg
);
228 stamp
[i
] |= ((i
& 4 ? fg
: bg
) << 16);
229 stamp
[i
+ 1] = (i
& 8 ? fg
: bg
);
230 stamp
[i
+ 1] |= ((i
& 16 ? fg
: bg
) << 16);
236 * Paint a single character. This is for 8-pixel wide fonts.
239 rasops15_putchar8(void *cookie
, int row
, int col
, u_int uc
, long attr
)
241 struct rasops_info
*ri
;
246 /* Can't risk remaking the stamp if it's already in use */
249 rasops15_putchar(cookie
, row
, col
, uc
, attr
);
253 ri
= (struct rasops_info
*)cookie
;
256 #ifdef RASOPS_CLIPPING
257 if ((unsigned)row
>= (unsigned)ri
->ri_rows
) {
262 if ((unsigned)col
>= (unsigned)ri
->ri_cols
) {
268 /* Recompute stamp? */
269 if (attr
!= stamp_attr
)
270 rasops15_makestamp(ri
, attr
);
272 rp
= (int32_t *)(ri
->ri_bits
+ row
*ri
->ri_yscale
+ col
*ri
->ri_xscale
);
274 hrp
= (int32_t *)(ri
->ri_hwbits
+ row
*ri
->ri_yscale
+
276 height
= ri
->ri_font
->fontheight
;
278 if (uc
== (u_int
)-1) {
279 int32_t c
= stamp
[0];
281 rp
[0] = rp
[1] = rp
[2] = rp
[3] = c
;
282 DELTA(rp
, ri
->ri_stride
, int32_t *);
284 hrp
[0] = hrp
[1] = hrp
[2] = hrp
[3] = c
;
285 DELTA(hrp
, ri
->ri_stride
, int32_t *);
289 uc
-= ri
->ri_font
->firstchar
;
290 fr
= (u_char
*)ri
->ri_font
->data
+ uc
*ri
->ri_fontscale
;
291 fs
= ri
->ri_font
->stride
;
294 so
= STAMP_SHIFT(fr
[0], 1) & STAMP_MASK
;
295 rp
[0] = STAMP_READ(so
);
296 rp
[1] = STAMP_READ(so
+ 4);
298 hrp
[0] = STAMP_READ(so
);
299 hrp
[1] = STAMP_READ(so
+ 4);
302 so
= STAMP_SHIFT(fr
[0], 0) & STAMP_MASK
;
303 rp
[2] = STAMP_READ(so
);
304 rp
[3] = STAMP_READ(so
+ 4);
306 hrp
[2] = STAMP_READ(so
);
307 hrp
[3] = STAMP_READ(so
+ 4);
311 DELTA(rp
, ri
->ri_stride
, int32_t *);
313 DELTA(hrp
, ri
->ri_stride
, int32_t *);
318 if ((attr
& 1) != 0) {
319 int32_t c
= STAMP_READ(28);
321 DELTA(rp
, -(ri
->ri_stride
<< 1), int32_t *);
322 rp
[0] = rp
[1] = rp
[2] = rp
[3] = c
;
324 DELTA(hrp
, -(ri
->ri_stride
<< 1), int32_t *);
325 hrp
[0] = hrp
[1] = hrp
[2] = hrp
[3] = c
;
333 * Paint a single character. This is for 12-pixel wide fonts.
336 rasops15_putchar12(void *cookie
, int row
, int col
, u_int uc
, long attr
)
338 struct rasops_info
*ri
;
343 /* Can't risk remaking the stamp if it's already in use */
346 rasops15_putchar(cookie
, row
, col
, uc
, attr
);
350 ri
= (struct rasops_info
*)cookie
;
353 #ifdef RASOPS_CLIPPING
354 if ((unsigned)row
>= (unsigned)ri
->ri_rows
) {
359 if ((unsigned)col
>= (unsigned)ri
->ri_cols
) {
365 /* Recompute stamp? */
366 if (attr
!= stamp_attr
)
367 rasops15_makestamp(ri
, attr
);
369 rp
= (int32_t *)(ri
->ri_bits
+ row
*ri
->ri_yscale
+ col
*ri
->ri_xscale
);
371 hrp
= (int32_t *)(ri
->ri_hwbits
+ row
*ri
->ri_yscale
+
373 height
= ri
->ri_font
->fontheight
;
375 if (uc
== (u_int
)-1) {
376 int32_t c
= stamp
[0];
378 rp
[0] = rp
[1] = rp
[2] = rp
[3] = rp
[4] = rp
[5] = c
;
379 DELTA(rp
, ri
->ri_stride
, int32_t *);
381 hrp
[0] = hrp
[1] = hrp
[2] = hrp
[3] = hrp
[4] =
383 DELTA(hrp
, ri
->ri_stride
, int32_t *);
387 uc
-= ri
->ri_font
->firstchar
;
388 fr
= (u_char
*)ri
->ri_font
->data
+ uc
*ri
->ri_fontscale
;
389 fs
= ri
->ri_font
->stride
;
392 so
= STAMP_SHIFT(fr
[0], 1) & STAMP_MASK
;
393 rp
[0] = STAMP_READ(so
);
394 rp
[1] = STAMP_READ(so
+ 4);
396 hrp
[0] = STAMP_READ(so
);
397 hrp
[1] = STAMP_READ(so
+ 4);
400 so
= STAMP_SHIFT(fr
[0], 0) & STAMP_MASK
;
401 rp
[2] = STAMP_READ(so
);
402 rp
[3] = STAMP_READ(so
+ 4);
404 hrp
[2] = STAMP_READ(so
);
405 hrp
[3] = STAMP_READ(so
+ 4);
408 so
= STAMP_SHIFT(fr
[1], 1) & STAMP_MASK
;
409 rp
[4] = STAMP_READ(so
);
410 rp
[5] = STAMP_READ(so
+ 4);
412 hrp
[4] = STAMP_READ(so
);
413 hrp
[5] = STAMP_READ(so
+ 4);
417 DELTA(rp
, ri
->ri_stride
, int32_t *);
419 DELTA(hrp
, ri
->ri_stride
, int32_t *);
425 int32_t c
= STAMP_READ(28);
427 DELTA(rp
, -(ri
->ri_stride
<< 1), int32_t *);
428 rp
[0] = rp
[1] = rp
[2] = rp
[3] = rp
[4] = rp
[5] = c
;
430 DELTA(hrp
, -(ri
->ri_stride
<< 1), int32_t *);
431 hrp
[0] = hrp
[1] = hrp
[2] = hrp
[3] = hrp
[4] = hrp
[5] = c
;
439 * Paint a single character. This is for 16-pixel wide fonts.
442 rasops15_putchar16(void *cookie
, int row
, int col
, u_int uc
, long attr
)
444 struct rasops_info
*ri
;
449 /* Can't risk remaking the stamp if it's already in use */
452 rasops15_putchar(cookie
, row
, col
, uc
, attr
);
456 ri
= (struct rasops_info
*)cookie
;
459 #ifdef RASOPS_CLIPPING
460 if ((unsigned)row
>= (unsigned)ri
->ri_rows
) {
465 if ((unsigned)col
>= (unsigned)ri
->ri_cols
) {
471 /* Recompute stamp? */
472 if (attr
!= stamp_attr
)
473 rasops15_makestamp(ri
, attr
);
475 rp
= (int32_t *)(ri
->ri_bits
+ row
*ri
->ri_yscale
+ col
*ri
->ri_xscale
);
477 hrp
= (int32_t *)(ri
->ri_hwbits
+ row
*ri
->ri_yscale
+
479 height
= ri
->ri_font
->fontheight
;
481 if (uc
== (u_int
)-1) {
482 int32_t c
= stamp
[0];
484 rp
[0] = rp
[1] = rp
[2] = rp
[3] =
485 rp
[4] = rp
[5] = rp
[6] = rp
[7] = c
;
486 DELTA(rp
, ri
->ri_stride
, int32_t *);
488 hrp
[0] = hrp
[1] = hrp
[2] = hrp
[3] =
489 hrp
[4] = hrp
[5] = hrp
[6] = hrp
[7] = c
;
490 DELTA(hrp
, ri
->ri_stride
, int32_t *);
494 uc
-= ri
->ri_font
->firstchar
;
495 fr
= (u_char
*)ri
->ri_font
->data
+ uc
*ri
->ri_fontscale
;
496 fs
= ri
->ri_font
->stride
;
499 so
= STAMP_SHIFT(fr
[0], 1) & STAMP_MASK
;
500 rp
[0] = STAMP_READ(so
);
501 rp
[1] = STAMP_READ(so
+ 4);
503 hrp
[0] = STAMP_READ(so
);
504 hrp
[1] = STAMP_READ(so
+ 4);
507 so
= STAMP_SHIFT(fr
[0], 0) & STAMP_MASK
;
508 rp
[2] = STAMP_READ(so
);
509 rp
[3] = STAMP_READ(so
+ 4);
511 hrp
[2] = STAMP_READ(so
);
512 hrp
[3] = STAMP_READ(so
+ 4);
515 so
= STAMP_SHIFT(fr
[1], 1) & STAMP_MASK
;
516 rp
[4] = STAMP_READ(so
);
517 rp
[5] = STAMP_READ(so
+ 4);
519 hrp
[4] = STAMP_READ(so
);
520 hrp
[5] = STAMP_READ(so
+ 4);
523 so
= STAMP_SHIFT(fr
[1], 0) & STAMP_MASK
;
524 rp
[6] = STAMP_READ(so
);
525 rp
[7] = STAMP_READ(so
+ 4);
527 hrp
[6] = STAMP_READ(so
);
528 hrp
[7] = STAMP_READ(so
+ 4);
531 DELTA(rp
, ri
->ri_stride
, int32_t *);
533 DELTA(hrp
, ri
->ri_stride
, int32_t *);
540 int32_t c
= STAMP_READ(28);
542 DELTA(rp
, -(ri
->ri_stride
<< 1), int32_t *);
543 rp
[0] = rp
[1] = rp
[2] = rp
[3] =
544 rp
[4] = rp
[5] = rp
[6] = rp
[7] = c
;
546 DELTA(hrp
, -(ri
->ri_stride
<< 1), int32_t *);
547 hrp
[0] = hrp
[1] = hrp
[2] = hrp
[3] =
548 hrp
[4] = hrp
[5] = hrp
[6] = hrp
[7] = c
;
554 #endif /* !RASOPS_SMALL */