1 /* $NetBSD: rasops.c,v 1.59 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: rasops.c,v 1.59 2009/03/14 15:36:20 dsl Exp $");
35 #include "opt_rasops.h"
36 #include "rasops_glue.h"
37 #include "opt_wsmsgattrs.h"
39 #include <sys/param.h>
40 #include <sys/systm.h>
43 #include <sys/bswap.h>
44 #include <machine/endian.h>
46 #include <dev/wscons/wsdisplayvar.h>
47 #include <dev/wscons/wsconsio.h>
48 #include <dev/wsfont/wsfont.h>
49 #include <dev/rasops/rasops.h>
55 /* ANSI colormap (R,G,B). Upper 8 are high-intensity */
56 const u_char rasops_cmap
[256*3] = {
57 0x00, 0x00, 0x00, /* black */
58 0x7f, 0x00, 0x00, /* red */
59 0x00, 0x7f, 0x00, /* green */
60 0x7f, 0x7f, 0x00, /* brown */
61 0x00, 0x00, 0x7f, /* blue */
62 0x7f, 0x00, 0x7f, /* magenta */
63 0x00, 0x7f, 0x7f, /* cyan */
64 0xc7, 0xc7, 0xc7, /* white - XXX too dim? */
66 0x7f, 0x7f, 0x7f, /* black */
67 0xff, 0x00, 0x00, /* red */
68 0x00, 0xff, 0x00, /* green */
69 0xff, 0xff, 0x00, /* brown */
70 0x00, 0x00, 0xff, /* blue */
71 0xff, 0x00, 0xff, /* magenta */
72 0x00, 0xff, 0xff, /* cyan */
73 0xff, 0xff, 0xff, /* white */
76 * For the cursor, we need at least the last (255th)
77 * color to be white. Fill up white completely for
80 #define _CMWHITE 0xff, 0xff, 0xff,
81 #define _CMWHITE16 _CMWHITE _CMWHITE _CMWHITE _CMWHITE \
82 _CMWHITE _CMWHITE _CMWHITE _CMWHITE \
83 _CMWHITE _CMWHITE _CMWHITE _CMWHITE \
84 _CMWHITE _CMWHITE _CMWHITE _CMWHITE
85 _CMWHITE16 _CMWHITE16 _CMWHITE16 _CMWHITE16 _CMWHITE16
86 _CMWHITE16 _CMWHITE16 _CMWHITE16 _CMWHITE16 _CMWHITE16
87 _CMWHITE16 _CMWHITE16 _CMWHITE16 _CMWHITE16
/* but not the last one */
92 * For the cursor the fg/bg indices are bit inverted, so
93 * provide complimentary colors in the upper 16 entries.
95 0x7f, 0x7f, 0x7f, /* black */
96 0xff, 0x00, 0x00, /* red */
97 0x00, 0xff, 0x00, /* green */
98 0xff, 0xff, 0x00, /* brown */
99 0x00, 0x00, 0xff, /* blue */
100 0xff, 0x00, 0xff, /* magenta */
101 0x00, 0xff, 0xff, /* cyan */
102 0xff, 0xff, 0xff, /* white */
104 0x00, 0x00, 0x00, /* black */
105 0x7f, 0x00, 0x00, /* red */
106 0x00, 0x7f, 0x00, /* green */
107 0x7f, 0x7f, 0x00, /* brown */
108 0x00, 0x00, 0x7f, /* blue */
109 0x7f, 0x00, 0x7f, /* magenta */
110 0x00, 0x7f, 0x7f, /* cyan */
111 0xc7, 0xc7, 0xc7, /* white - XXX too dim? */
114 /* True if color is gray */
115 const u_char rasops_isgray
[16] = {
122 /* Generic functions */
123 static void rasops_copyrows(void *, int, int, int);
124 static int rasops_mapchar(void *, int, u_int
*);
125 static void rasops_cursor(void *, int, int, int);
126 static int rasops_allocattr_color(void *, int, int, int, long *);
127 static int rasops_allocattr_mono(void *, int, int, int, long *);
128 static void rasops_do_cursor(struct rasops_info
*);
129 static void rasops_init_devcmap(struct rasops_info
*);
131 #if NRASOPS_ROTATION > 0
132 static void rasops_copychar(void *, int, int, int, int);
133 static void rasops_copycols_rotated(void *, int, int, int, int);
134 static void rasops_copyrows_rotated(void *, int, int, int);
135 static void rasops_erasecols_rotated(void *, int, int, int, long);
136 static void rasops_eraserows_rotated(void *, int, int, long);
137 static void rasops_putchar_rotated(void *, int, int, u_int
, long);
138 static void rasops_rotate_font(int *);
141 * List of all rotated fonts
143 SLIST_HEAD(, rotatedfont
) rotatedfonts
= SLIST_HEAD_INITIALIZER(rotatedfonts
);
145 SLIST_ENTRY(rotatedfont
) rf_next
;
149 #endif /* NRASOPS_ROTATION > 0 */
152 * Initialize a 'rasops_info' descriptor.
155 rasops_init(struct rasops_info
*ri
, int wantrows
, int wantcols
)
159 /* Select a font if the caller doesn't care */
160 if (ri
->ri_font
== NULL
) {
165 /* Want 8 pixel wide, don't care about aestethics */
166 cookie
= wsfont_find(NULL
, 8, 0, 0, WSDISPLAY_FONTORDER_L2R
,
167 WSDISPLAY_FONTORDER_L2R
);
169 cookie
= wsfont_find(NULL
, 0, 0, 0,
170 WSDISPLAY_FONTORDER_L2R
, WSDISPLAY_FONTORDER_L2R
);
173 printf("rasops_init: font table is empty\n");
177 #if NRASOPS_ROTATION > 0
179 * Pick the rotated version of this font. This will create it
182 if (ri
->ri_flg
& RI_ROTATE_CW
)
183 rasops_rotate_font(&cookie
);
186 if (wsfont_lock(cookie
, &ri
->ri_font
)) {
187 printf("rasops_init: couldn't lock font\n");
191 ri
->ri_wsfcookie
= cookie
;
195 /* This should never happen in reality... */
197 if ((long)ri
->ri_bits
& 3) {
198 printf("rasops_init: bits not aligned on 32-bit boundary\n");
202 if ((int)ri
->ri_stride
& 3) {
203 printf("rasops_init: stride not aligned on 32-bit boundary\n");
208 if (rasops_reconfig(ri
, wantrows
, wantcols
))
211 rasops_init_devcmap(ri
);
216 * Reconfigure (because parameters have changed in some way).
219 rasops_reconfig(struct rasops_info
*ri
, int wantrows
, int wantcols
)
225 if (ri
->ri_font
->fontwidth
> 32 || ri
->ri_font
->fontwidth
< 4)
226 panic("rasops_init: fontwidth assumptions botched!");
228 /* Need this to frob the setup below */
229 bpp
= (ri
->ri_depth
== 15 ? 16 : ri
->ri_depth
);
231 if ((ri
->ri_flg
& RI_CFGDONE
) != 0)
232 ri
->ri_bits
= ri
->ri_origbits
;
234 /* Don't care if the caller wants a hideously small console */
241 /* Now constrain what they get */
242 ri
->ri_emuwidth
= ri
->ri_font
->fontwidth
* wantcols
;
243 ri
->ri_emuheight
= ri
->ri_font
->fontheight
* wantrows
;
245 if (ri
->ri_emuwidth
> ri
->ri_width
)
246 ri
->ri_emuwidth
= ri
->ri_width
;
248 if (ri
->ri_emuheight
> ri
->ri_height
)
249 ri
->ri_emuheight
= ri
->ri_height
;
251 /* Reduce width until aligned on a 32-bit boundary */
252 while ((ri
->ri_emuwidth
* bpp
& 31) != 0)
255 #if NRASOPS_ROTATION > 0
256 if (ri
->ri_flg
& RI_ROTATE_CW
) {
257 ri
->ri_rows
= ri
->ri_emuwidth
/ ri
->ri_font
->fontwidth
;
258 ri
->ri_cols
= ri
->ri_emuheight
/ ri
->ri_font
->fontheight
;
263 ri
->ri_cols
= ri
->ri_emuwidth
/ ri
->ri_font
->fontwidth
;
264 ri
->ri_rows
= ri
->ri_emuheight
/ ri
->ri_font
->fontheight
;
266 ri
->ri_emustride
= ri
->ri_emuwidth
* bpp
>> 3;
267 ri
->ri_delta
= ri
->ri_stride
- ri
->ri_emustride
;
270 ri
->ri_pelbytes
= bpp
>> 3;
272 ri
->ri_xscale
= (ri
->ri_font
->fontwidth
* bpp
) >> 3;
273 ri
->ri_yscale
= ri
->ri_font
->fontheight
* ri
->ri_stride
;
274 ri
->ri_fontscale
= ri
->ri_font
->fontheight
* ri
->ri_font
->stride
;
277 if ((ri
->ri_delta
& 3) != 0)
278 panic("rasops_init: ri_delta not aligned on 32-bit boundary");
280 /* Clear the entire display */
281 if ((ri
->ri_flg
& RI_CLEAR
) != 0)
282 memset(ri
->ri_bits
, 0, ri
->ri_stride
* ri
->ri_height
);
284 /* Now centre our window if needs be */
285 ri
->ri_origbits
= ri
->ri_bits
;
287 if ((ri
->ri_flg
& RI_CENTER
) != 0) {
288 ri
->ri_bits
+= (((ri
->ri_width
* bpp
>> 3) -
289 ri
->ri_emustride
) >> 1) & ~3;
290 ri
->ri_bits
+= ((ri
->ri_height
- ri
->ri_emuheight
) >> 1) *
293 ri
->ri_yorigin
= (int)(ri
->ri_bits
- ri
->ri_origbits
)
295 ri
->ri_xorigin
= (((int)(ri
->ri_bits
- ri
->ri_origbits
)
296 % ri
->ri_stride
) * 8 / bpp
);
298 ri
->ri_xorigin
= ri
->ri_yorigin
= 0;
301 * Fill in defaults for operations set. XXX this nukes private
302 * routines used by accelerated fb drivers.
304 ri
->ri_ops
.mapchar
= rasops_mapchar
;
305 ri
->ri_ops
.copyrows
= rasops_copyrows
;
306 ri
->ri_ops
.copycols
= rasops_copycols
;
307 ri
->ri_ops
.erasecols
= rasops_erasecols
;
308 ri
->ri_ops
.eraserows
= rasops_eraserows
;
309 ri
->ri_ops
.cursor
= rasops_cursor
;
310 ri
->ri_do_cursor
= rasops_do_cursor
;
312 if (ri
->ri_depth
< 8 || (ri
->ri_flg
& RI_FORCEMONO
) != 0) {
313 ri
->ri_ops
.allocattr
= rasops_allocattr_mono
;
314 ri
->ri_caps
= WSSCREEN_UNDERLINE
| WSSCREEN_REVERSE
;
316 ri
->ri_ops
.allocattr
= rasops_allocattr_color
;
317 ri
->ri_caps
= WSSCREEN_UNDERLINE
| WSSCREEN_HILIT
|
318 WSSCREEN_WSCOLORS
| WSSCREEN_REVERSE
;
321 switch (ri
->ri_depth
) {
342 #if NRASOPS15 > 0 || NRASOPS16 > 0
359 ri
->ri_flg
&= ~RI_CFGDONE
;
364 #if NRASOPS_ROTATION > 0
365 if (ri
->ri_flg
& RI_ROTATE_CW
) {
366 ri
->ri_real_ops
= ri
->ri_ops
;
367 ri
->ri_ops
.copycols
= rasops_copycols_rotated
;
368 ri
->ri_ops
.copyrows
= rasops_copyrows_rotated
;
369 ri
->ri_ops
.erasecols
= rasops_erasecols_rotated
;
370 ri
->ri_ops
.eraserows
= rasops_eraserows_rotated
;
371 ri
->ri_ops
.putchar
= rasops_putchar_rotated
;
375 ri
->ri_flg
|= RI_CFGDONE
;
384 rasops_mapchar(void *cookie
, int c
, u_int
*cp
)
386 struct rasops_info
*ri
;
388 ri
= (struct rasops_info
*)cookie
;
391 if (ri
->ri_font
== NULL
)
392 panic("rasops_mapchar: no font selected");
395 if (ri
->ri_font
->encoding
!= WSDISPLAY_FONTENC_ISO
) {
396 if ( (c
= wsfont_map_unichar(ri
->ri_font
, c
)) < 0) {
403 if (c
< ri
->ri_font
->firstchar
) {
408 if (c
- ri
->ri_font
->firstchar
>= ri
->ri_font
->numchars
) {
418 * Allocate a color attribute.
421 rasops_allocattr_color(void *cookie
, int fg
, int bg
, int flg
,
426 if (__predict_false((unsigned int)fg
>= sizeof(rasops_isgray
) ||
427 (unsigned int)bg
>= sizeof(rasops_isgray
)))
430 #ifdef RASOPS_CLIPPING
434 if ((flg
& WSATTR_BLINK
) != 0)
437 if ((flg
& WSATTR_WSCOLORS
) == 0) {
450 if ((flg
& WSATTR_REVERSE
) != 0) {
456 if ((flg
& WSATTR_HILIT
) != 0)
459 flg
= ((flg
& WSATTR_UNDERLINE
) ? 1 : 0);
461 if (rasops_isgray
[fg
])
464 if (rasops_isgray
[bg
])
467 *attr
= (bg
<< 16) | (fg
<< 24) | flg
;
472 * Allocate a mono attribute.
475 rasops_allocattr_mono(void *cookie
, int fg
, int bg
, int flg
,
480 if ((flg
& (WSATTR_BLINK
| WSATTR_HILIT
| WSATTR_WSCOLORS
)) != 0)
486 if ((flg
& WSATTR_REVERSE
) != 0) {
492 *attr
= (bg
<< 16) | (fg
<< 24) | ((flg
& WSATTR_UNDERLINE
) ? 7 : 6);
500 rasops_copyrows(void *cookie
, int src
, int dst
, int num
)
502 int32_t *sp
, *dp
, *hp
, *srp
, *drp
, *hrp
;
503 struct rasops_info
*ri
;
504 int n8
, n1
, cnt
, delta
;
506 ri
= (struct rasops_info
*)cookie
;
509 #ifdef RASOPS_CLIPPING
518 if ((src
+ num
) > ri
->ri_rows
)
519 num
= ri
->ri_rows
- src
;
526 if ((dst
+ num
) > ri
->ri_rows
)
527 num
= ri
->ri_rows
- dst
;
533 num
*= ri
->ri_font
->fontheight
;
534 n8
= ri
->ri_emustride
>> 5;
535 n1
= (ri
->ri_emustride
>> 2) & 7;
538 srp
= (int32_t *)(ri
->ri_bits
+ src
* ri
->ri_yscale
);
539 drp
= (int32_t *)(ri
->ri_bits
+ dst
* ri
->ri_yscale
);
541 hrp
= (int32_t *)(ri
->ri_hwbits
+ dst
*
543 delta
= ri
->ri_stride
;
545 src
= ri
->ri_font
->fontheight
* src
+ num
- 1;
546 dst
= ri
->ri_font
->fontheight
* dst
+ num
- 1;
547 srp
= (int32_t *)(ri
->ri_bits
+ src
* ri
->ri_stride
);
548 drp
= (int32_t *)(ri
->ri_bits
+ dst
* ri
->ri_stride
);
550 hrp
= (int32_t *)(ri
->ri_hwbits
+ dst
*
553 delta
= -ri
->ri_stride
;
562 DELTA(drp
, delta
, int32_t *);
563 DELTA(srp
, delta
, int32_t *);
565 DELTA(hrp
, delta
, int32_t *);
567 for (cnt
= n8
; cnt
; cnt
--) {
581 for (cnt
= n8
; cnt
; cnt
--) {
595 for (cnt
= n1
; cnt
; cnt
--) {
604 * Copy columns. This is slow, and hard to optimize due to alignment,
605 * and the fact that we have to copy both left->right and right->left.
606 * We simply cop-out here and use memmove(), since it handles all of
607 * these cases anyway.
610 rasops_copycols(void *cookie
, int row
, int src
, int dst
, int num
)
612 struct rasops_info
*ri
;
613 u_char
*sp
, *dp
, *hp
;
616 ri
= (struct rasops_info
*)cookie
;
619 #ifdef RASOPS_CLIPPING
623 /* Catches < 0 case too */
624 if ((unsigned)row
>= (unsigned)ri
->ri_rows
)
632 if ((src
+ num
) > ri
->ri_cols
)
633 num
= ri
->ri_cols
- src
;
640 if ((dst
+ num
) > ri
->ri_cols
)
641 num
= ri
->ri_cols
- dst
;
647 num
*= ri
->ri_xscale
;
648 row
*= ri
->ri_yscale
;
649 height
= ri
->ri_font
->fontheight
;
651 sp
= ri
->ri_bits
+ row
+ src
* ri
->ri_xscale
;
652 dp
= ri
->ri_bits
+ row
+ dst
* ri
->ri_xscale
;
654 hp
= ri
->ri_hwbits
+ row
+ dst
* ri
->ri_xscale
;
657 memmove(dp
, sp
, num
);
668 * Turn cursor off/on.
671 rasops_cursor(void *cookie
, int on
, int row
, int col
)
673 struct rasops_info
*ri
;
675 ri
= (struct rasops_info
*)cookie
;
677 /* Turn old cursor off */
678 if ((ri
->ri_flg
& RI_CURSOR
) != 0)
679 #ifdef RASOPS_CLIPPING
680 if ((ri
->ri_flg
& RI_CURSORCLIP
) == 0)
682 ri
->ri_do_cursor(ri
);
684 /* Select new cursor */
685 #ifdef RASOPS_CLIPPING
686 ri
->ri_flg
&= ~RI_CURSORCLIP
;
688 if (row
< 0 || row
>= ri
->ri_rows
)
689 ri
->ri_flg
|= RI_CURSORCLIP
;
690 else if (col
< 0 || col
>= ri
->ri_cols
)
691 ri
->ri_flg
|= RI_CURSORCLIP
;
697 ri
->ri_flg
|= RI_CURSOR
;
698 #ifdef RASOPS_CLIPPING
699 if ((ri
->ri_flg
& RI_CURSORCLIP
) == 0)
701 ri
->ri_do_cursor(ri
);
703 ri
->ri_flg
&= ~RI_CURSOR
;
707 * Make the device colormap
710 rasops_init_devcmap(struct rasops_info
*ri
)
715 switch (ri
->ri_depth
) {
717 ri
->ri_devcmap
[0] = 0;
718 for (i
= 1; i
< 16; i
++)
719 ri
->ri_devcmap
[i
] = -1;
723 for (i
= 1; i
< 15; i
++)
724 ri
->ri_devcmap
[i
] = 0xaaaaaaaa;
726 ri
->ri_devcmap
[0] = 0;
727 ri
->ri_devcmap
[8] = 0x55555555;
728 ri
->ri_devcmap
[15] = -1;
732 for (i
= 0; i
< 16; i
++)
733 ri
->ri_devcmap
[i
] = i
| (i
<<8) | (i
<<16) | (i
<<24);
739 for (i
= 0; i
< 16; i
++) {
740 if (ri
->ri_rnum
<= 8)
741 c
= (*p
>> (8 - ri
->ri_rnum
)) << ri
->ri_rpos
;
743 c
= (*p
<< (ri
->ri_rnum
- 8)) << ri
->ri_rpos
;
746 if (ri
->ri_gnum
<= 8)
747 c
|= (*p
>> (8 - ri
->ri_gnum
)) << ri
->ri_gpos
;
749 c
|= (*p
<< (ri
->ri_gnum
- 8)) << ri
->ri_gpos
;
752 if (ri
->ri_bnum
<= 8)
753 c
|= (*p
>> (8 - ri
->ri_bnum
)) << ri
->ri_bpos
;
755 c
|= (*p
<< (ri
->ri_bnum
- 8)) << ri
->ri_bpos
;
758 /* Fill the word for generic routines, which want this */
759 if (ri
->ri_depth
== 24)
760 c
= c
| ((c
& 0xff) << 24);
761 else if (ri
->ri_depth
<= 16)
764 /* 24bpp does bswap on the fly. {32,16,15}bpp do it here. */
765 if ((ri
->ri_flg
& RI_BSWAP
) == 0)
766 ri
->ri_devcmap
[i
] = c
;
767 else if (ri
->ri_depth
== 32)
768 ri
->ri_devcmap
[i
] = bswap32(c
);
769 else if (ri
->ri_depth
== 16 || ri
->ri_depth
== 15)
770 ri
->ri_devcmap
[i
] = bswap16(c
);
772 ri
->ri_devcmap
[i
] = c
;
777 * Unpack a rasops attribute
780 rasops_unpack_attr(long attr
, int *fg
, int *bg
, int *underline
)
783 *fg
= ((u_int
)attr
>> 24) & 0xf;
784 *bg
= ((u_int
)attr
>> 16) & 0xf;
785 if (underline
!= NULL
)
786 *underline
= (u_int
)attr
& 1;
790 * Erase rows. This isn't static, since 24-bpp uses it in special cases.
793 rasops_eraserows(void *cookie
, int row
, int num
, long attr
)
795 struct rasops_info
*ri
;
796 int np
, nw
, cnt
, delta
;
797 int32_t *dp
, *hp
, clr
;
800 ri
= (struct rasops_info
*)cookie
;
803 #ifdef RASOPS_CLIPPING
809 if ((row
+ num
) > ri
->ri_rows
)
810 num
= ri
->ri_rows
- row
;
816 clr
= ri
->ri_devcmap
[(attr
>> 16) & 0xf];
819 * XXX The wsdisplay_emulops interface seems a little deficient in
820 * that there is no way to clear the *entire* screen. We provide a
821 * workaround here: if the entire console area is being cleared, and
822 * the RI_FULLCLEAR flag is set, clear the entire display.
824 if (num
== ri
->ri_rows
&& (ri
->ri_flg
& RI_FULLCLEAR
) != 0) {
825 np
= ri
->ri_stride
>> 5;
826 nw
= (ri
->ri_stride
>> 2) & 7;
828 dp
= (int32_t *)ri
->ri_origbits
;
830 hp
= (int32_t *)ri
->ri_hwbits
;
833 np
= ri
->ri_emustride
>> 5;
834 nw
= (ri
->ri_emustride
>> 2) & 7;
835 num
*= ri
->ri_font
->fontheight
;
836 dp
= (int32_t *)(ri
->ri_bits
+ row
* ri
->ri_yscale
);
838 hp
= (int32_t *)(ri
->ri_hwbits
+ row
*
840 delta
= ri
->ri_delta
;
844 for (cnt
= np
; cnt
; cnt
--) {
845 for (i
= 0; i
< 8; i
++) {
855 for (cnt
= nw
; cnt
; cnt
--) {
856 *(int32_t *)dp
= clr
;
857 DELTA(dp
, 4, int32_t *);
859 *(int32_t *)hp
= clr
;
860 DELTA(hp
, 4, int32_t *);
864 DELTA(dp
, delta
, int32_t *);
866 DELTA(hp
, delta
, int32_t *);
871 * Actually turn the cursor on or off. This does the dirty work for
875 rasops_do_cursor(struct rasops_info
*ri
)
877 int full1
, height
, cnt
, slop1
, slop2
, row
, col
;
878 u_char
*dp
, *rp
, *hrp
, *hp
;
882 #if NRASOPS_ROTATION > 0
883 if (ri
->ri_flg
& RI_ROTATE_CW
) {
884 /* Rotate rows/columns */
886 col
= ri
->ri_rows
- ri
->ri_crow
- 1;
894 rp
= ri
->ri_bits
+ row
* ri
->ri_yscale
+ col
* ri
->ri_xscale
;
896 hrp
= ri
->ri_hwbits
+ row
* ri
->ri_yscale
+ col
898 height
= ri
->ri_font
->fontheight
;
899 slop1
= (4 - ((long)rp
& 3)) & 3;
901 if (slop1
> ri
->ri_xscale
)
902 slop1
= ri
->ri_xscale
;
904 slop2
= (ri
->ri_xscale
- slop1
) & 3;
905 full1
= (ri
->ri_xscale
- slop1
- slop2
) >> 2;
907 if ((slop1
| slop2
) == 0) {
914 hrp
+= ri
->ri_stride
;
917 for (cnt
= full1
; cnt
; cnt
--) {
918 *(int32_t *)dp
^= ~0;
922 *(int32_t *)hp
= *(int32_t *)dp
;
929 /* XXX this is stupid.. use masks instead */
935 hrp
+= ri
->ri_stride
;
946 *(int16_t *)dp
^= ~0;
950 *(int16_t *)hp
= *(int16_t *)dp
;
956 for (cnt
= full1
; cnt
; cnt
--) {
957 *(int32_t *)dp
^= ~0;
961 *(int32_t *)hp
= *(int32_t *)dp
;
974 *(int16_t *)dp
^= ~0;
976 *(int16_t *)hp
= *(int16_t *)(dp
- 2);
986 rasops_erasecols(void *cookie
, int row
, int col
, int num
, long attr
)
988 int n8
, height
, cnt
, slop1
, slop2
, clr
;
989 struct rasops_info
*ri
;
990 int32_t *rp
, *dp
, *hrp
, *hp
;
993 ri
= (struct rasops_info
*)cookie
;
996 #ifdef RASOPS_CLIPPING
997 if ((unsigned)row
>= (unsigned)ri
->ri_rows
)
1005 if ((col
+ num
) > ri
->ri_cols
)
1006 num
= ri
->ri_cols
- col
;
1012 num
= num
* ri
->ri_xscale
;
1013 rp
= (int32_t *)(ri
->ri_bits
+ row
*ri
->ri_yscale
+ col
*ri
->ri_xscale
);
1015 hrp
= (int32_t *)(ri
->ri_hwbits
+ row
*ri
->ri_yscale
+
1017 height
= ri
->ri_font
->fontheight
;
1018 clr
= ri
->ri_devcmap
[(attr
>> 16) & 0xf];
1020 /* Don't bother using the full loop for <= 32 pels */
1022 if (((num
| ri
->ri_xscale
) & 3) == 0) {
1023 /* Word aligned blt */
1028 DELTA(rp
, ri
->ri_stride
, int32_t *);
1029 if (ri
->ri_hwbits
) {
1031 DELTA(hrp
, ri
->ri_stride
, int32_t *);
1034 for (cnt
= num
; cnt
; cnt
--) {
1040 } else if (((num
| ri
->ri_xscale
) & 1) == 0) {
1042 * Halfword aligned blt. This is needed so the
1043 * 15/16 bit ops can use this function.
1049 DELTA(rp
, ri
->ri_stride
, int32_t *);
1050 if (ri
->ri_hwbits
) {
1052 DELTA(hrp
, ri
->ri_stride
, int32_t *);
1055 for (cnt
= num
; cnt
; cnt
--) {
1056 *(int16_t *)dp
= clr
;
1057 DELTA(dp
, 2, int32_t *);
1058 if (ri
->ri_hwbits
) {
1059 *(int16_t *)hp
= clr
;
1060 DELTA(hp
, 2, int32_t *);
1067 DELTA(rp
, ri
->ri_stride
, int32_t *);
1068 if (ri
->ri_hwbits
) {
1070 DELTA(hrp
, ri
->ri_stride
, int32_t *);
1073 for (cnt
= num
; cnt
; cnt
--) {
1074 *(u_char
*)dp
= clr
;
1075 DELTA(dp
, 1, int32_t *);
1076 if (ri
->ri_hwbits
) {
1077 *(u_char
*)hp
= clr
;
1078 DELTA(hp
, 1, int32_t *);
1087 slop1
= (4 - ((long)rp
& 3)) & 3;
1088 slop2
= (num
- slop1
) & 3;
1089 num
-= slop1
+ slop2
;
1091 num
= (num
>> 2) & 7;
1095 DELTA(rp
, ri
->ri_stride
, int32_t *);
1096 if (ri
->ri_hwbits
) {
1098 DELTA(hrp
, ri
->ri_stride
, int32_t *);
1101 /* Align span to 4 bytes */
1103 *(u_char
*)dp
= clr
;
1104 DELTA(dp
, 1, int32_t *);
1105 if (ri
->ri_hwbits
) {
1106 *(u_char
*)hp
= clr
;
1107 DELTA(hp
, 1, int32_t *);
1112 *(int16_t *)dp
= clr
;
1113 DELTA(dp
, 2, int32_t *);
1114 if (ri
->ri_hwbits
) {
1115 *(int16_t *)hp
= clr
;
1116 DELTA(hp
, 2, int32_t *);
1120 /* Write 32 bytes per loop */
1121 for (cnt
= n8
; cnt
; cnt
--) {
1122 for (i
= 0; i
< 8; i
++) {
1132 /* Write 4 bytes per loop */
1133 for (cnt
= num
; cnt
; cnt
--) {
1139 /* Write unaligned trailing slop */
1141 *(u_char
*)dp
= clr
;
1142 DELTA(dp
, 1, int32_t *);
1143 if (ri
->ri_hwbits
) {
1144 *(u_char
*)hp
= clr
;
1145 DELTA(hp
, 1, int32_t *);
1150 *(int16_t *)dp
= clr
;
1152 *(int16_t *)hp
= clr
;
1157 #if NRASOPS_ROTATION > 0
1159 * Quarter clockwise rotation routines (originally intended for the
1160 * built-in Zaurus C3x00 display in 16bpp).
1163 #include <sys/malloc.h>
1166 rasops_rotate_font(int *cookie
)
1168 struct rotatedfont
*f
;
1171 SLIST_FOREACH(f
, &rotatedfonts
, rf_next
) {
1172 if (f
->rf_cookie
== *cookie
) {
1173 *cookie
= f
->rf_rotated
;
1179 * We did not find a rotated version of this font. Ask the wsfont
1180 * code to compute one for us.
1183 f
= malloc(sizeof(struct rotatedfont
), M_DEVBUF
, M_WAITOK
);
1187 if ((ncookie
= wsfont_rotate(*cookie
)) == -1)
1190 f
->rf_cookie
= *cookie
;
1191 f
->rf_rotated
= ncookie
;
1192 SLIST_INSERT_HEAD(&rotatedfonts
, f
, rf_next
);
1198 rasops_copychar(void *cookie
, int srcrow
, int dstrow
, int srccol
, int dstcol
)
1200 struct rasops_info
*ri
;
1203 int r_srcrow
, r_dstrow
, r_srccol
, r_dstcol
;
1205 ri
= (struct rasops_info
*)cookie
;
1209 r_srccol
= ri
->ri_rows
- srcrow
- 1;
1210 r_dstcol
= ri
->ri_rows
- dstrow
- 1;
1212 r_srcrow
*= ri
->ri_yscale
;
1213 r_dstrow
*= ri
->ri_yscale
;
1214 height
= ri
->ri_font
->fontheight
;
1216 sp
= ri
->ri_bits
+ r_srcrow
+ r_srccol
* ri
->ri_xscale
;
1217 dp
= ri
->ri_bits
+ r_dstrow
+ r_dstcol
* ri
->ri_xscale
;
1220 memmove(dp
, sp
, ri
->ri_xscale
);
1221 dp
+= ri
->ri_stride
;
1222 sp
+= ri
->ri_stride
;
1227 rasops_putchar_rotated(void *cookie
, int row
, int col
, u_int uc
, long attr
)
1229 struct rasops_info
*ri
;
1233 ri
= (struct rasops_info
*)cookie
;
1235 if (__predict_false((unsigned int)row
> ri
->ri_rows
||
1236 (unsigned int)col
> ri
->ri_cols
))
1239 /* Avoid underflow */
1240 if ((ri
->ri_rows
- row
- 1) < 0)
1243 /* Do rotated char sans (side)underline */
1244 ri
->ri_real_ops
.putchar(cookie
, col
, ri
->ri_rows
- row
- 1, uc
,
1247 /* Do rotated underline */
1248 rp
= ri
->ri_bits
+ col
* ri
->ri_yscale
+ (ri
->ri_rows
- row
- 1) *
1250 height
= ri
->ri_font
->fontheight
;
1252 /* XXX this assumes 16-bit color depth */
1253 if ((attr
& 1) != 0) {
1254 int16_t c
= (int16_t)ri
->ri_devcmap
[((u_int
)attr
>> 24) & 0xf];
1258 rp
+= ri
->ri_stride
;
1264 rasops_erasecols_rotated(void *cookie
, int row
, int col
, int num
, long attr
)
1266 struct rasops_info
*ri
;
1269 ri
= (struct rasops_info
*)cookie
;
1271 for (i
= col
; i
< col
+ num
; i
++)
1272 ri
->ri_ops
.putchar(cookie
, row
, i
, ' ', attr
);
1275 /* XXX: these could likely be optimised somewhat. */
1277 rasops_copyrows_rotated(void *cookie
, int src
, int dst
, int num
)
1279 struct rasops_info
*ri
= (struct rasops_info
*)cookie
;
1283 for (roff
= 0; roff
< num
; roff
++)
1284 for (col
= 0; col
< ri
->ri_cols
; col
++)
1285 rasops_copychar(cookie
, src
+ roff
, dst
+ roff
,
1288 for (roff
= num
- 1; roff
>= 0; roff
--)
1289 for (col
= 0; col
< ri
->ri_cols
; col
++)
1290 rasops_copychar(cookie
, src
+ roff
, dst
+ roff
,
1295 rasops_copycols_rotated(void *cookie
, int row
, int src
, int dst
, int num
)
1300 for (coff
= 0; coff
< num
; coff
++)
1301 rasops_copychar(cookie
, row
, row
, src
+ coff
, dst
+ coff
);
1303 for (coff
= num
- 1; coff
>= 0; coff
--)
1304 rasops_copychar(cookie
, row
, row
, src
+ coff
, dst
+ coff
);
1308 rasops_eraserows_rotated(void *cookie
, int row
, int num
, long attr
)
1310 struct rasops_info
*ri
;
1313 ri
= (struct rasops_info
*)cookie
;
1315 for (rn
= row
; rn
< row
+ num
; rn
++)
1316 for (col
= 0; col
< ri
->ri_cols
; col
++)
1317 ri
->ri_ops
.putchar(cookie
, rn
, col
, ' ', attr
);
1319 #endif /* NRASOPS_ROTATION */