Module Name:    src
Committed By:   martin
Date:           Thu Aug 15 12:21:28 UTC 2019

Modified Files:
        src/share/man/man9 [netbsd-9]: rasops.9
        src/sys/arch/luna68k/dev [netbsd-9]: omrasops.c
        src/sys/dev/rasops [netbsd-9]: README rasops.c rasops.h rasops1.c
            rasops15.c rasops1_putchar_width.h rasops2.c rasops24.c rasops32.c
            rasops4.c rasops8.c rasops_bitops.h rasops_masks.c rasops_masks.h
            rasops_putchar.h rasops_putchar_width.h
        src/sys/dev/wscons [netbsd-9]: wsdisplay_vcons.c
        src/sys/dev/wsfb [netbsd-9]: genfb.c
Added Files:
        src/sys/dev/rasops [netbsd-9]: rasops1-4_putchar.h
Removed Files:
        src/sys/dev/rasops [netbsd-9]: rasops_putchar_aa.h

Log Message:
Pull up following revision(s) (requested by rin in ticket #56):

        sys/dev/rasops/rasops.c: revision 1.120
        sys/dev/rasops/rasops.h: revision 1.40
        sys/dev/rasops/rasops.c: revision 1.121
        sys/dev/rasops/rasops.h: revision 1.41
        sys/dev/rasops/rasops.c: revision 1.122
        sys/dev/rasops/rasops.h: revision 1.42
        sys/dev/rasops/rasops.h: revision 1.43
        sys/dev/rasops/rasops.h: revision 1.44
        sys/dev/rasops/rasops.h: revision 1.45
        sys/dev/rasops/rasops.h: revision 1.46
        sys/dev/rasops/rasops.h: revision 1.47
        sys/dev/rasops/rasops.h: revision 1.48
        sys/dev/rasops/rasops32.c: revision 1.40
        sys/dev/rasops/rasops32.c: revision 1.41
        sys/dev/rasops/rasops32.c: revision 1.42
        sys/dev/rasops/rasops32.c: revision 1.43
        sys/dev/rasops/rasops32.c: revision 1.44
        sys/dev/rasops/rasops32.c: revision 1.45
        sys/dev/rasops/rasops32.c: revision 1.46
        sys/dev/rasops/rasops1-4_putchar.h: revision 1.1
        sys/dev/rasops/rasops1-4_putchar.h: revision 1.2
        sys/dev/rasops/rasops1-4_putchar.h: revision 1.3
        sys/dev/rasops/rasops1_putchar_width.h: revision 1.3
        sys/dev/rasops/rasops1_putchar_width.h: revision 1.4
        sys/dev/rasops/rasops1_putchar_width.h: revision 1.5
        sys/dev/rasops/rasops1_putchar_width.h: revision 1.6
        sys/dev/rasops/README: revision 1.7
        sys/dev/rasops/rasops_putchar_aa.h: revision 1.5
        sys/dev/rasops/rasops_putchar_aa.h: revision 1.6
        sys/dev/rasops/rasops8.c: revision 1.45
        sys/dev/rasops/rasops8.c: revision 1.46
        sys/dev/rasops/rasops8.c: revision 1.47
        sys/dev/rasops/rasops24.c: revision 1.40
        sys/dev/rasops/rasops8.c: revision 1.48
        sys/dev/rasops/rasops24.c: revision 1.41
        sys/dev/rasops/rasops8.c: revision 1.49
        sys/dev/rasops/rasops24.c: revision 1.42
        sys/dev/rasops/rasops24.c: revision 1.43
        sys/dev/rasops/rasops24.c: revision 1.44
        sys/dev/rasops/rasops_masks.c: revision 1.10
        doc/CHANGES: revision 1.2566
        sys/dev/rasops/rasops24.c: revision 1.45
        doc/CHANGES: revision 1.2567
        sys/dev/rasops/rasops24.c: revision 1.46
        sys/dev/rasops/rasops24.c: revision 1.47
        sys/dev/rasops/rasops24.c: revision 1.48
        sys/dev/rasops/rasops24.c: revision 1.49
        sys/dev/rasops/rasops_bitops.h: revision 1.19
        sys/dev/rasops/rasops_putchar_aa.h: file removal
        sys/dev/wscons/wsdisplay_vcons.c: revision 1.40
        sys/dev/rasops/rasops8.c: revision 1.50
        sys/dev/rasops/rasops8.c: revision 1.51
        sys/dev/rasops/rasops24.c: revision 1.50
        sys/arch/luna68k/dev/omrasops.c: revision 1.21
        sys/dev/rasops/rasops_bitops.h: revision 1.20
        sys/dev/wsfb/genfb.c: revision 1.68
        sys/dev/rasops/rasops_bitops.h: revision 1.21
        sys/dev/wsfb/genfb.c: revision 1.69
        sys/dev/rasops/rasops_putchar_width.h: revision 1.10
        sys/dev/rasops/rasops_bitops.h: revision 1.22
        sys/dev/rasops/rasops_putchar_width.h: revision 1.11
        sys/dev/rasops/rasops_bitops.h: revision 1.23
        sys/dev/rasops/rasops_putchar_width.h: revision 1.12
        sys/dev/rasops/rasops_bitops.h: revision 1.24
        sys/dev/rasops/rasops_putchar_width.h: revision 1.13
        sys/dev/rasops/rasops_bitops.h: revision 1.25
        sys/dev/rasops/rasops_putchar_width.h: revision 1.14
        sys/dev/rasops/rasops_putchar_width.h: revision 1.15
        sys/dev/rasops/rasops1.c: revision 1.32
        sys/dev/rasops/rasops1.c: revision 1.33
        sys/dev/rasops/rasops1.c: revision 1.34
        sys/dev/rasops/rasops1.c: revision 1.35
        sys/dev/rasops/rasops1.c: revision 1.36
        sys/dev/rasops/rasops1.c: revision 1.37
        sys/dev/rasops/rasops4.c: revision 1.21
        sys/dev/rasops/rasops4.c: revision 1.22
        sys/dev/rasops/rasops4.c: revision 1.23
        sys/dev/rasops/rasops4.c: revision 1.24
        sys/dev/rasops/rasops4.c: revision 1.25
        sys/dev/rasops/rasops4.c: revision 1.26
        sys/dev/rasops/rasops4.c: revision 1.27
        sys/dev/rasops/rasops4.c: revision 1.28
        sys/dev/wsfb/genfb.c: revision 1.70
        sys/dev/rasops/rasops2.c: revision 1.27
        sys/dev/rasops/rasops2.c: revision 1.28
        share/man/man9/rasops.9: revision 1.18
        sys/dev/rasops/rasops.c: revision 1.102
        sys/dev/rasops/rasops2.c: revision 1.29
        share/man/man9/rasops.9: revision 1.19
        sys/dev/rasops/rasops.c: revision 1.103
        sys/dev/rasops/rasops.c: revision 1.104
        sys/dev/rasops/rasops.c: revision 1.105
        sys/dev/rasops/rasops.c: revision 1.106
        sys/dev/rasops/rasops.c: revision 1.107
        sys/dev/rasops/rasops_putchar.h: revision 1.6
        sys/dev/rasops/rasops.c: revision 1.108
        sys/dev/rasops/rasops_putchar.h: revision 1.7
        sys/dev/rasops/rasops.c: revision 1.109
        sys/dev/rasops/rasops_putchar.h: revision 1.8
        sys/dev/rasops/rasops2.c: revision 1.30
        sys/dev/rasops/rasops2.c: revision 1.31
        sys/dev/rasops/rasops15.c: revision 1.32
        sys/dev/rasops/rasops2.c: revision 1.32
        sys/dev/rasops/rasops15.c: revision 1.33
        sys/dev/rasops/rasops2.c: revision 1.33
        sys/dev/rasops/rasops15.c: revision 1.34
        sys/dev/rasops/rasops15.c: revision 1.35
        sys/dev/rasops/rasops15.c: revision 1.36
        sys/dev/rasops/rasops.c: revision 1.110
        sys/dev/rasops/rasops15.c: revision 1.37
        sys/dev/rasops/rasops.c: revision 1.111
        sys/dev/rasops/rasops15.c: revision 1.38
        sys/dev/rasops/rasops.c: revision 1.112
        sys/dev/rasops/rasops15.c: revision 1.39
        sys/dev/rasops/rasops.c: revision 1.113
        sys/dev/rasops/rasops.c: revision 1.114
        sys/dev/rasops/rasops.c: revision 1.115
        sys/dev/rasops/rasops_masks.h: revision 1.9
        sys/dev/rasops/rasops.c: revision 1.116
        sys/dev/rasops/rasops.c: revision 1.117
        sys/dev/rasops/rasops.c: revision 1.118
        sys/dev/rasops/rasops.c: revision 1.119
        sys/dev/rasops/rasops.h: revision 1.39

Misc clean-up's:
- protect private stuff in rasops.h by _RASOPS_PRIVATE
- staticify rasops_copycols() and rasops_isgray[]
- G/C unused extern int cold
Switch to per-device stamp, and retire stamp_mutex.

Provide buffer capable of single-row pixels in order to make things simpler.

Factor out copy-paste. No functional changes.
When font is switched, not only putchar, but also other ri_ops can be
changed by backend driver, e.g., see rasops1.c:
https://nxr.netbsd.org/xref/src/sys/dev/rasops/rasops1.c#58
4 is 1 << 2, not 1 << 3...

Fix erasecols and do_cursor for font width >= 32 bits.
Also, some cosmetic clean-up's.

Oops, for rasops_copycols(), we cannot use memmove even if src == dst.
On the other hand, memmove is safe for rasops_copyrows().
Fix unaligned writes to buffer, that are introduced in 1.105:
http://cvsweb.netbsd.org/bsdweb.cgi/src/sys/dev/rasops/rasops.c#rev1.105

Support font width 32 on monochrome screen.

Remove duplicate substitution. Style. No functional changes.

Correct copy count. This affects ``left-to-right'' copy for region
including word boundary.

Fix a bug in shadow fb support for copycols on 1, 2, and 4bpp screen,
which was introduced in 1.18:
http://cvsweb.netbsd.org/bsdweb.cgi/src/sys/dev/rasops/rasops_bitops.h#rev1.18

Add general putchar functions for 2 and 4bpp.
Note that 1bpp continues to use its local version in rasops1.c,
which is much faster and simpler.

Cosmetic changes. No functional changes.

Reflect reality.

Notify size of shadow framebuffer if enabled.

Fix unaligned word write's to buffer, introduced in rev 1.42:
http://cvsweb.netbsd.org/bsdweb.cgi/src/sys/dev/rasops/rasops24.c#rev1.42

Real fix for 24-bpp color:
- When centering screen, locate effective base address of framebuffer to
  both word and 24-bit color boundary.
- Consistently convert ri_devcmap to ``big endian'' if not RI_BSWAP.

Also, fix possible bug for 15/16-bpp with RI_BSWAP (not tested).

Protect rasops_copy{rows,cols}() by _RASOPS_PRIVATE.

Use _KERNEL_OPT.

Simplify calculation for 12-byte alignment.
No functional changes.

Fix black color-attribution for depths 2 and 4.

Depth 2 is monochrome.
IMO, it is impossible to support ANSI colors on 2-bpp display; fore-
and background can be same value even if they are different colors
logically.

Fix a critical bug for rasops_copyrows() introduced in rev. 1.90:
http://cvsweb.netbsd.org/bsdweb.cgi/src/sys/dev/rasops/rasops.c#rev1.90
When src < dst, we have to copy backward.

Simplify rasops_do_cursor():
- Use static masks similar to that used in rasops_bitops.h,
  rather than generating them on the fly.
- Use pointer for proper type to avoid unnecessary casts.

Use "hp" instead of "hrp" consistently with other files.
No functional changes.

Stop allocating ri_buf and ri_stamp dynamically. As commented in
rasops.h, it is not safe to use kmem_alloc(9) in rasops_init();
rasops routines can be used for early putchar, which means that
UVM is not fully initialized.

Should fix a problem reported by macallan:
http://mail-index.netbsd.org/tech-kern/2019/08/02/msg025327.html

Instead of using ri_buf, inline function rasops_memcpy32() is
introduced to fill 32bit data efficiently.

Instead of using ri_stamp (per device stamp), stamp_ri is
introduced to distinguish for which device stamp is calculated.

Oops, revert an unintentional change for now.

If RI_CLEAR is set, do not forget to clear real framebuffer.

Modify struct rasops_info again (ride 9.99.4 bump).
- remove ri_buf and friends.
- remove ri_stamp and frieds.
- introduce ri_ul, which will be used for scaling underline with font.

Also add hack for ri_ul; adjust its size to obsoleted member, ri_delta,
which was only used rasops routines internally. Now, size and offsets of
all members of struct rasops_info become same with netbsd-9, -8, and -7,
again. So we can safelly pull up fixes to any release branches!

Scaling dimensions of underline by font height.

Currently,
- offset of underline is fixed to 1-row from bottom of characters, and
- height of underline is fixed to 1.
Both are good for standard 8x16 fonts. However, it is too thin for
larger fonts, especially when used on display of high resolution.
Also, 1-row offset of underline is ugly for small fonts, e.g.,
spleen5x8.
Therefore, adjust offset and height as,
- no changes for standard 16-height fonts.
- scaling by font height for larger fonts.
- set offset to zero for fonts of height smaller than 16.

Merge rasops_putchar_aa.h into rasops_putchar.h.

Support scaling underline dimensions by font height.

Separate general putchar for 1-4bpp from rasops_bitops:
- Support anti-aliasing for 2bpp, which works perfectly!
- Support scaling underline dimensions with font height.

We support anti-aliasing for depth 2.
Use switch appropriately.
- Stop showing struct rasops_info; readers can read the header itself.
- Correct description for optimized font widths.
- Remove strange blank line.

Try to improve formatting and naration.

Make rasops_erase{rows,cols}() public again; hp300/diofb uses them.
Pointed out by martin.

When legacy Apple 4-bpp color palette is used, make green dark so that
kernel messages are printed nicely on white background.

Fix color range overflow; we cannot make bright colors more brighter.

Correctly check whether character is in font in rasops_mapchar().
Also, make sure that in putchar functions for completeness.

Fix bug introduced in rev. 1.69:
http://cvsweb.netbsd.org/bsdweb.cgi/src/sys/dev/wsfb/genfb.c#rev1.69
is_bgr should be initialized to false. Otherwise, color becomes strange
for depths 24 and 32 unless backend explicitly set "is_bgr" property.

Set 4-bpp devcmap in a similar manner to non-RGB case of 8-bpp.
No functional changes since this is not in use (4-bpp is monochrome).

Misc style clean up's.
- Introduce and use proper macros.
- Use not ambiguous variable names.
- Unify similar functions as possible as I can.
- G/C unused headers.
- Use #include <dev/rasops/foo.h> instead of "foo.h"

No particular functional changes intended.

My work for rasops(9) was finished (hopefully).

I will send pull-up request for netbsd-9, if there are no new failures
reported within few days.

Fix format in order not to confuse changes2html script.
Minor improvements of wording for my entry.

When using stamp, drop attributions other than back and foreground
colors so that stamp is not updated unnecessarily.


To generate a diff of this commit:
cvs rdiff -u -r1.17 -r1.17.8.1 src/share/man/man9/rasops.9
cvs rdiff -u -r1.20 -r1.20.6.1 src/sys/arch/luna68k/dev/omrasops.c
cvs rdiff -u -r1.6 -r1.6.36.1 src/sys/dev/rasops/README
cvs rdiff -u -r1.101 -r1.101.2.1 src/sys/dev/rasops/rasops.c
cvs rdiff -u -r1.38 -r1.38.2.1 src/sys/dev/rasops/rasops.h
cvs rdiff -u -r0 -r1.3.2.2 src/sys/dev/rasops/rasops1-4_putchar.h
cvs rdiff -u -r1.31 -r1.31.2.1 src/sys/dev/rasops/rasops1.c \
    src/sys/dev/rasops/rasops15.c
cvs rdiff -u -r1.2 -r1.2.2.1 src/sys/dev/rasops/rasops1_putchar_width.h
cvs rdiff -u -r1.26 -r1.26.2.1 src/sys/dev/rasops/rasops2.c
cvs rdiff -u -r1.39 -r1.39.2.1 src/sys/dev/rasops/rasops24.c \
    src/sys/dev/rasops/rasops32.c
cvs rdiff -u -r1.20 -r1.20.2.1 src/sys/dev/rasops/rasops4.c
cvs rdiff -u -r1.44 -r1.44.2.1 src/sys/dev/rasops/rasops8.c
cvs rdiff -u -r1.18 -r1.18.2.1 src/sys/dev/rasops/rasops_bitops.h
cvs rdiff -u -r1.9 -r1.9.36.1 src/sys/dev/rasops/rasops_masks.c
cvs rdiff -u -r1.8 -r1.8.36.1 src/sys/dev/rasops/rasops_masks.h
cvs rdiff -u -r1.5 -r1.5.2.1 src/sys/dev/rasops/rasops_putchar.h
cvs rdiff -u -r1.4 -r0 src/sys/dev/rasops/rasops_putchar_aa.h
cvs rdiff -u -r1.9 -r1.9.2.1 src/sys/dev/rasops/rasops_putchar_width.h
cvs rdiff -u -r1.39 -r1.39.4.1 src/sys/dev/wscons/wsdisplay_vcons.c
cvs rdiff -u -r1.67 -r1.67.2.1 src/sys/dev/wsfb/genfb.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/share/man/man9/rasops.9
diff -u src/share/man/man9/rasops.9:1.17 src/share/man/man9/rasops.9:1.17.8.1
--- src/share/man/man9/rasops.9:1.17	Mon Jul  3 21:28:48 2017
+++ src/share/man/man9/rasops.9	Thu Aug 15 12:21:27 2019
@@ -1,4 +1,4 @@
-.\"     $NetBSD: rasops.9,v 1.17 2017/07/03 21:28:48 wiz Exp $
+.\"     $NetBSD: rasops.9,v 1.17.8.1 2019/08/15 12:21:27 martin Exp $
 .\"
 .\" Copyright (c) 2001 The NetBSD Foundation, Inc.
 .\" All rights reserved.
@@ -27,7 +27,7 @@
 .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 .\" POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd January 13, 2012
+.Dd August 7, 2019
 .Dt RASOPS 9
 .Os
 .Sh NAME
@@ -42,6 +42,9 @@
 .Fn rasops_init "struct rasops_info *ri" "int wantrows" "int wantcols"
 .Ft int
 .Fn rasops_reconfig "struct rasops_info *ri" "int wantrows" "int wantcols"
+.Pp
+.Cd options RASOPS_DEFAULT_WIDTH=80
+.Cd options RASOPS_DEFAULT_HEIGHT=25
 .Sh DESCRIPTION
 The
 .Nm
@@ -49,86 +52,15 @@ subsystem is a set of raster operations 
 .Xr wscons 9 .
 .Pp
 The primary data type for using the raster operations is the
-.Em rasops_info
+.Vt rasops_info
 structure in
-.Pa dev/rasops/rasops.h :
-.Bd -literal
-struct rasops_info {
-
-	/*
-	 * These must be filled in by the caller
-	 */
-	int	ri_depth;	/* depth in bits */
-	u_char	*ri_bits;	/* ptr to bits */
-	int	ri_width;	/* width (pels) */
-	int	ri_height;	/* height (pels) */
-	int	ri_stride;	/* stride in bytes */
-
-	/*
-	 * If you want shadow framebuffer support, point ri_hwbits
-	 * to the real framebuffer, and ri_bits to the shadow framebuffer
-	 */
-	u_char	*ri_hwbits;
-
-	/*
-	 * These can optionally be left zeroed out. If you fill ri_font,
-	 * but aren't using wsfont, set ri_wsfcookie to -1.
-	 */
-	struct	wsdisplay_font *ri_font;
-	int	ri_wsfcookie;	/* wsfont cookie */
-	void	*ri_hw;		/* driver private data */
-	int	ri_crow;	/* cursor row */
-	int	ri_ccol;	/* cursor column */
-	int	ri_flg;		/* various operational flags */
-
-	/*
-	 * These are optional and will default if zero. Meaningless
-	 * on depths other than 15, 16, 24 and 32 bits per pel. On
-	 * 24 bit displays, ri_{r,g,b}num must be 8.
-	 */
-	u_char	ri_rnum;	/* number of bits for red */
-	u_char	ri_gnum;	/* number of bits for green */
-	u_char	ri_bnum;	/* number of bits for blue */
-	u_char	ri_rpos;	/* which bit red starts at */
-	u_char	ri_gpos;	/* which bit green starts at */
-	u_char	ri_bpos;	/* which bit blue starts at */
-
-	/*
-	 * These are filled in by rasops_init()
-	 */
-	int	ri_emuwidth;	/* width we actually care about */
-	int	ri_emuheight;	/* height we actually care about */
-	int	ri_emustride;	/* bytes per row we actually care about */
-	int	ri_rows;	/* number of rows (characters) */
-	int	ri_cols;	/* number of columns (characters) */
-	int	ri_delta;	/* row delta in bytes */
-	int	ri_pelbytes;	/* bytes per pel (may be zero) */
-	int	ri_fontscale;	/* fontheight * fontstride */
-	int	ri_xscale;	/* fontwidth * pelbytes */
-	int	ri_yscale;	/* fontheight * stride */
-	u_char	*ri_origbits;	/* where screen bits actually start */
-	int	ri_xorigin;	/* where ri_bits begins (x) */
-	int	ri_yorigin;	/* where ri_bits begins (y) */
-	int32_t	ri_devcmap[16]; /* color -> framebuffer data */
-
-	/*
-	 * The emulops you need to use, and the screen caps for wscons
-	 */
-	struct	wsdisplay_emulops ri_ops;
-	int	ri_caps;
-
-	/*
-	 * Callbacks so we can share some code
-	 */
-	void	(*ri_do_cursor)(struct rasops_info *);
-};
-.Ed
+.In dev/rasops/rasops.h .
 .Pp
 Valid values for the
-.Em ri_flg
+.Fa ri_flg
 member are:
 .Pp
-.Bl -tag -offset indent -width RI_ENABLE_ALPHA_XX -compact
+.Bl -tag -width ".Dv RI_ENABLE_ALPHA" -offset indent -compact
 .It Dv RI_FULLCLEAR
 .Fn eraserows
 hack to clear full screen
@@ -152,50 +84,47 @@ do not generate box drawing characters f
 Use this when it is not safe to allocate memory, for example when setting up
 an early console.
 .It Dv RI_ENABLE_ALPHA
-set this if the caller supports anti-aliased fonts in the given colour depth.
+the caller supports anti-aliased fonts in the given colour depth.
 Without this flag
 .Fn rasops_init
 will only pick bitmap fonts.
 .It Dv RI_8BIT_IS_RGB
-set this if the caller uses an R3G3B2 colour map in 8 bit.
+the caller uses an R3G3B2 colour map in 8 bit.
 .Fn rasops_init
-will generate an appropriate ri_devcmap[] but the caller still needs to set up
-the actual colour map.
+will generate an appropriate
+.Fa ri_devcmap Ns Li []
+but the caller still needs to set up the actual colour map.
 .El
 .Sh FUNCTIONS
-.Bl -tag -width compact
-.It Fn rasops_init "ri" "wantrows" "wantcols"
-Initialise a
-.Em rasops_info
+.Fn rasops_init
+initialises a
+.Vt rasops_info
 descriptor.
+.Fn rasops_reconfig
+is used to reconfigure it if parameters have changed in some way.
+.Pp
 The arguments
 .Fa wantrows
 and
 .Fa wantcols
 are the number of rows and columns we'd like.
-In terms of optimization, fonts that are a multiple of 8 pixels wide
-work the best.
-.It Fn rasops_reconfig "ri" "wantrows" "wantcols"
-Reconfigure a
-.Em rasops_info
-descriptor because parameters have changed in some way.
-The arguments
-.Fa wantrows
+Passing zero for either one of them uses the default \(em normally
+80 by 25 but it can be changed with config options
+.Dv RASOPS_DEFAULT_WIDTH
 and
-.Fa wantcols
-are the number of rows and columns we'd like.
-Passing zero for either one of
-them uses the default - normally 80x25 but it can be changed with
-.Bd -literal -offset indent
-options RASOPS_DEFAULT_WIDTH=80
-options RASOPS_DEFAULT_HEIGHT=25
-.Ed
+.Dv RASOPS_DEFAULT_HEIGHT .
+.Pp
+In terms of optimization, bitmap fonts of width 8 or 16 work the best
+for all depths.
+For depths other than 1 the fonts of width 12 are also optimized.
+.Pp
 If calling
 .Fn rasops_reconfig
-to change the font and ri_wsfcookie \*[Ge] 0, you must call
+to change the font and
+.Fa ri_wsfcookie
+is non-negative, you must call
 .Fn wsfont_unlock
-on it, and reset it to -1 (or a new, valid cookie).
-.El
+on it, and reset it to \-1 or a new, valid cookie.
 .Sh CODE REFERENCES
 The rasops subsystem is implemented within the directory
 .Pa sys/dev/rasops .

Index: src/sys/arch/luna68k/dev/omrasops.c
diff -u src/sys/arch/luna68k/dev/omrasops.c:1.20 src/sys/arch/luna68k/dev/omrasops.c:1.20.6.1
--- src/sys/arch/luna68k/dev/omrasops.c:1.20	Wed Jun  6 01:49:08 2018
+++ src/sys/arch/luna68k/dev/omrasops.c	Thu Aug 15 12:21:27 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: omrasops.c,v 1.20 2018/06/06 01:49:08 maya Exp $ */
+/* $NetBSD: omrasops.c,v 1.20.6.1 2019/08/15 12:21:27 martin Exp $ */
 
 /*-
  * Copyright (c) 2000 The NetBSD Foundation, Inc.
@@ -31,7 +31,7 @@
 
 #include <sys/cdefs.h>			/* RCS ID & Copyright macro defns */
 
-__KERNEL_RCSID(0, "$NetBSD: omrasops.c,v 1.20 2018/06/06 01:49:08 maya Exp $");
+__KERNEL_RCSID(0, "$NetBSD: omrasops.c,v 1.20.6.1 2019/08/15 12:21:27 martin Exp $");
 
 /*
  * Designed speficically for 'm68k bitorder';
@@ -1202,7 +1202,6 @@ omrasops_init(struct rasops_info *ri, in
 	ri->ri_cols = ri->ri_emuwidth / ri->ri_font->fontwidth;
 	ri->ri_rows = ri->ri_emuheight / ri->ri_font->fontheight;
 	ri->ri_emustride = ri->ri_emuwidth * bpp >> 3;
-	ri->ri_delta = ri->ri_stride - ri->ri_emustride;
 	ri->ri_ccol = 0;
 	ri->ri_crow = 0;
 	ri->ri_pelbytes = bpp >> 3;

Index: src/sys/dev/rasops/README
diff -u src/sys/dev/rasops/README:1.6 src/sys/dev/rasops/README:1.6.36.1
--- src/sys/dev/rasops/README:1.6	Mon Dec  2 14:05:51 2013
+++ src/sys/dev/rasops/README	Thu Aug 15 12:21:27 2019
@@ -1,4 +1,4 @@
-$NetBSD: README,v 1.6 2013/12/02 14:05:51 tsutsui Exp $
+$NetBSD: README,v 1.6.36.1 2019/08/15 12:21:27 martin Exp $
 
 This directory contains `rasops', a set of raster operations intended to
 replace the dev/rcons/raster stuff for both wscons and rcons. It yields
@@ -6,11 +6,9 @@ significantly improved performance, supp
 
 Issues/TODO:
 
-- There is no generic `putchar' function for 2bpp
 - Color handling for 2bpp is broken
 - 64-bit types are not used on machines that are 64-bit
 - We should never be doing reads/writes of less than 32-bits
-- Flags in attribute values are hardcoded
 - Need a manpage
 - Should handle multiple fonts simulatneously
 - Generate an `empty' box character when we have no match?

Index: src/sys/dev/rasops/rasops.c
diff -u src/sys/dev/rasops/rasops.c:1.101 src/sys/dev/rasops/rasops.c:1.101.2.1
--- src/sys/dev/rasops/rasops.c:1.101	Tue Jul 30 15:29:40 2019
+++ src/sys/dev/rasops/rasops.c	Thu Aug 15 12:21:27 2019
@@ -1,4 +1,4 @@
-/*	 $NetBSD: rasops.c,v 1.101 2019/07/30 15:29:40 rin Exp $	*/
+/*	 $NetBSD: rasops.c,v 1.101.2.1 2019/08/15 12:21:27 martin Exp $	*/
 
 /*-
  * Copyright (c) 1999 The NetBSD Foundation, Inc.
@@ -30,24 +30,27 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: rasops.c,v 1.101 2019/07/30 15:29:40 rin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: rasops.c,v 1.101.2.1 2019/08/15 12:21:27 martin Exp $");
 
+#ifdef _KERNEL_OPT
 #include "opt_rasops.h"
-#include "rasops_glue.h"
 #include "opt_wsmsgattrs.h"
+#include "rasops_glue.h"
+#endif
 
 #include <sys/param.h>
 #include <sys/bswap.h>
 #include <sys/kmem.h>
-#include <sys/systm.h>
-#include <sys/time.h>
 
 #include <machine/endian.h>
 
 #include <dev/wscons/wsdisplayvar.h>
 #include <dev/wscons/wsconsio.h>
 #include <dev/wsfont/wsfont.h>
+
+#define	_RASOPS_PRIVATE
 #include <dev/rasops/rasops.h>
+#include <dev/rasops/rasops_masks.h>	/* XXX for MBE */
 
 #ifndef _KERNEL
 #include <errno.h>
@@ -67,6 +70,16 @@ struct rasops_matchdata {
 	int ident;
 };	
 
+static const uint32_t rasops_lmask32[4 + 1] = {
+	MBE(0x00000000), MBE(0x00ffffff), MBE(0x0000ffff), MBE(0x000000ff),
+	MBE(0x00000000),
+};
+
+static const uint32_t rasops_rmask32[4 + 1] = {
+	MBE(0x00000000), MBE(0xff000000), MBE(0xffff0000), MBE(0xffffff00),
+	MBE(0xffffffff),
+};
+
 /* ANSI colormap (R,G,B). Upper 8 are high-intensity */
 const uint8_t rasops_cmap[256 * 3] = {
 	0x00, 0x00, 0x00, /* black */
@@ -127,11 +140,9 @@ const uint8_t rasops_cmap[256 * 3] = {
 };
 
 /* True if color is gray */
-const uint8_t rasops_isgray[16] = {
-	1, 0, 0, 0,
-	0, 0, 0, 1,
-	1, 0, 0, 0,
-	0, 0, 0, 1,
+static const uint8_t rasops_isgray[16] = {
+	1, 0, 0, 0, 0, 0, 0, 1,
+	1, 0, 0, 0, 0, 0, 0, 1,
 };
 
 #ifdef RASOPS_APPLE_PALETTE
@@ -161,7 +172,7 @@ static const uint8_t apple8_devcmap[16] 
 static const uint8_t apple4_devcmap[16] = {
 	15,	/* black	*/
 	 3,	/* red		*/
-	 8,	/* green	*/
+	 9,	/* dark green	*/
 	 1,	/* yellow	*/
 	 6,	/* blue		*/
 	 4,	/* magenta	*/
@@ -170,7 +181,7 @@ static const uint8_t apple4_devcmap[16] 
 
 	13,	/* medium grey	*/
 	 3,	/* red		*/
-	 8,	/* green	*/
+	 9,	/* dark green	*/
 	 1,	/* yellow	*/
 	 6,	/* blue		*/
 	 4,	/* magenta	*/
@@ -181,12 +192,17 @@ static const uint8_t apple4_devcmap[16] 
 
 /* Generic functions */
 static void	rasops_copyrows(void *, int, int, int);
+static void	rasops_copycols(void *, int, int, int, int);
 static int	rasops_mapchar(void *, int, u_int *);
 static void	rasops_cursor(void *, int, int, int);
 static int	rasops_allocattr_color(void *, int, int, int, long *);
 static int	rasops_allocattr_mono(void *, int, int, int, long *);
 static void	rasops_do_cursor(struct rasops_info *);
 static void	rasops_init_devcmap(struct rasops_info *);
+static void	rasops_make_box_chars_8(struct rasops_info *);
+static void	rasops_make_box_chars_16(struct rasops_info *);
+static void	rasops_make_box_chars_32(struct rasops_info *);
+static void	rasops_make_box_chars_alpha(struct rasops_info *);
 
 #if NRASOPS_ROTATION > 0
 static void	rasops_rotate_font(int *, int);
@@ -218,13 +234,6 @@ struct rotatedfont {
 };
 #endif	/* NRASOPS_ROTATION > 0 */
 
-void	rasops_make_box_chars_8(struct rasops_info *);
-void	rasops_make_box_chars_16(struct rasops_info *);
-void	rasops_make_box_chars_32(struct rasops_info *);
-void	rasops_make_box_chars_alpha(struct rasops_info *);
-
-extern int cold;
-
 /*
  * Initialize a 'rasops_info' descriptor.
  */
@@ -319,7 +328,7 @@ rasops_init(struct rasops_info *ri, int 
 int
 rasops_reconfig(struct rasops_info *ri, int wantrows, int wantcols)
 {
-	int bpp, s;
+	int bpp, height, s;
 	size_t len;
 
 	s = splhigh();
@@ -413,12 +422,10 @@ rasops_reconfig(struct rasops_info *ri, 
 	} else
 #endif
 	{
-
 		ri->ri_cols = ri->ri_emuwidth / ri->ri_font->fontwidth;
 		ri->ri_rows = ri->ri_emuheight / ri->ri_font->fontheight;
 	}
 	ri->ri_emustride = ri->ri_emuwidth * bpp >> 3;
-	ri->ri_delta = ri->ri_stride - ri->ri_emustride;
 	ri->ri_ccol = 0;
 	ri->ri_crow = 0;
 	ri->ri_pelbytes = bpp >> 3;
@@ -427,32 +434,44 @@ rasops_reconfig(struct rasops_info *ri, 
 	ri->ri_yscale = ri->ri_font->fontheight * ri->ri_stride;
 	ri->ri_fontscale = ri->ri_font->fontheight * ri->ri_font->stride;
 
-	if ((ri->ri_delta & 3) != 0) {
-		aprint_error(
-		    "%s: ri_delta not aligned on 32-bit boundary", __func__);
-		splx(s);
-		return -1;
-	}
 	ri->ri_origbits = ri->ri_bits;
 	ri->ri_hworigbits = ri->ri_hwbits;
 
 	/* Clear the entire display */
-	if ((ri->ri_flg & RI_CLEAR) != 0)
-		memset(ri->ri_bits, 0, ri->ri_stride * ri->ri_height);
+	if ((ri->ri_flg & RI_CLEAR) != 0) {
+		rasops_memset32(ri->ri_bits, 0, ri->ri_stride * ri->ri_height);
+		if (ri->ri_hwbits)
+			rasops_memset32(ri->ri_hwbits, 0,
+			    ri->ri_stride * ri->ri_height);
+	}
 
 	/* Now centre our window if needs be */
 	if ((ri->ri_flg & RI_CENTER) != 0) {
-		ri->ri_bits += (((ri->ri_width * bpp >> 3) -
-		    ri->ri_emustride) >> 1) & ~3;
-		ri->ri_bits += ((ri->ri_height - ri->ri_emuheight) >> 1) *
+		uint32_t xoff, yoff;
+
+		xoff = ((ri->ri_width * bpp >> 3) - ri->ri_emustride) >> 1;
+		if (ri->ri_depth != 24) {
+			/*
+			 * Truncate to word boundary.
+			 */
+			xoff &= ~3;
+		} else {
+			/*
+			 * Truncate to both word and 24-bit color boundary.
+			 */
+			xoff -= xoff % 12;
+		}
+
+		yoff = ((ri->ri_height - ri->ri_emuheight) >> 1) *
 		    ri->ri_stride;
+
+		ri->ri_bits += xoff;
+		ri->ri_bits += yoff;
 		if (ri->ri_hwbits != NULL) {
-			ri->ri_hwbits += (((ri->ri_width * bpp >> 3) -
-			    ri->ri_emustride) >> 1) & ~3;
-			ri->ri_hwbits +=
-			    ((ri->ri_height - ri->ri_emuheight) >> 1) *
-			    ri->ri_stride;
+			ri->ri_hwbits += xoff;
+			ri->ri_hwbits += yoff;
 		}
+
 		ri->ri_yorigin = (int)(ri->ri_bits - ri->ri_origbits) /
 		    ri->ri_stride;
 		ri->ri_xorigin = (((int)(ri->ri_bits - ri->ri_origbits) %
@@ -460,6 +479,11 @@ rasops_reconfig(struct rasops_info *ri, 
 	} else
 		ri->ri_xorigin = ri->ri_yorigin = 0;
 
+	/* Scaling underline by font height */
+	height = ri->ri_font->fontheight;
+	ri->ri_ul.off = rounddown(height, 16) / 16;	/* offset from bottom */
+	ri->ri_ul.height = roundup(height, 16) / 16;	/* height */
+
 	/*
 	 * Fill in defaults for operations set.  XXX this nukes private
 	 * routines used by accelerated fb drivers.
@@ -476,10 +500,10 @@ rasops_reconfig(struct rasops_info *ri, 
 		    WSSCREEN_WSCOLORS | WSSCREEN_REVERSE);
 
 	if ((ri->ri_flg & RI_FORCEMONO) != 0 ||
-#ifdef RASOPS_APPLE_PALETTE
-	    ri->ri_depth == 1
-#else
+#ifndef RASOPS_APPLE_PALETTE
 	    ri->ri_depth < 8
+#else
+	    ri->ri_depth < 4
 #endif
 	) {
 		ri->ri_ops.allocattr = rasops_allocattr_mono;
@@ -570,17 +594,10 @@ rasops_mapchar(void *cookie, int c, u_in
 	KASSERT(ri->ri_font != NULL);
 
 	if ((c = wsfont_map_unichar(ri->ri_font, c)) < 0 ||
-	    c < ri->ri_font->firstchar) {
-		*cp = ' ';
-		return 0;
-	}
-
-#if 0 /* XXXRO */
-	if (CHAR_IN_FONT(c, ri->ri_font)) {
+	    !CHAR_IN_FONT(c, ri->ri_font)) {
 		*cp = ' ';
 		return 0;
 	}
-#endif
 
 	*cp = c;
 	return 5;
@@ -602,6 +619,7 @@ rasops_allocattr_color(void *cookie, int
 	fg &= 7;
 	bg &= 7;
 #endif
+
 	if ((flg & WSATTR_BLINK) != 0)
 		return EINVAL;
 
@@ -618,7 +636,7 @@ rasops_allocattr_color(void *cookie, int
 #endif
 	}
 
-	if ((flg & WSATTR_HILIT) != 0)
+	if ((flg & WSATTR_HILIT) != 0 && fg < 8)
 		fg += 8;
 
 	if ((flg & WSATTR_REVERSE) != 0) {
@@ -650,7 +668,7 @@ rasops_allocattr_mono(void *cookie, int 
 	if ((flg & (WSATTR_BLINK | WSATTR_HILIT | WSATTR_WSCOLORS)) != 0)
 		return EINVAL;
 
-	fg = 1;
+	fg = 0xff;
 	bg = 0;
 
 	if ((flg & WSATTR_REVERSE) != 0) {
@@ -670,8 +688,8 @@ static void
 rasops_copyrows(void *cookie, int src, int dst, int num)
 {
 	struct rasops_info *ri = (struct rasops_info *)cookie;
+	int stride;
 	uint8_t *sp, *dp, *hp;
-	int n, stride;
 
 	hp = NULL;	/* XXX GCC */
 
@@ -699,23 +717,31 @@ rasops_copyrows(void *cookie, int src, i
 		return;
 #endif
 
+	src *= ri->ri_yscale;
+	dst *= ri->ri_yscale;
 	num *= ri->ri_font->fontheight;
-	n = ri->ri_emustride;
 	stride = ri->ri_stride;
 
-	sp = ri->ri_bits + src * ri->ri_yscale;
-	dp = ri->ri_bits + dst * ri->ri_yscale;
+	if (src < dst) {
+		/* backward copy */
+		src += (num - 1) * stride;
+		dst += (num - 1) * stride;
+		stride *= -1;
+	}
+
+	sp = ri->ri_bits + src;
+	dp = ri->ri_bits + dst;
 	if (ri->ri_hwbits)
-		hp = ri->ri_hwbits + dst * ri->ri_yscale;
+		hp = ri->ri_hwbits + dst;
 
 	while (num--) {
-		memcpy(dp, sp, n);
-		dp += stride;
+		memcpy(dp, sp, ri->ri_emustride);
 		if (ri->ri_hwbits) {
-			memcpy(hp, sp, n);
+			memcpy(hp, dp, ri->ri_emustride);
 			hp += stride;
 		}
 		sp += stride;
+		dp += stride;
 	}
 }
 
@@ -725,12 +751,12 @@ rasops_copyrows(void *cookie, int src, i
  * We simply cop-out here and use memmove(), since it handles all of
  * these cases anyway.
  */
-void
+static void
 rasops_copycols(void *cookie, int row, int src, int dst, int num)
 {
 	struct rasops_info *ri = (struct rasops_info *)cookie;
-	uint8_t *sp, *dp, *hp;
 	int height;
+	uint8_t *sp, *dp, *hp;
 
 	hp = NULL;	/* XXX GCC */
 
@@ -762,9 +788,9 @@ rasops_copycols(void *cookie, int row, i
 		return;
 #endif
 
-	num *= ri->ri_xscale;
-	row *= ri->ri_yscale;
 	height = ri->ri_font->fontheight;
+	row *= ri->ri_yscale;
+	num *= ri->ri_xscale;
 
 	sp = ri->ri_bits + row + src * ri->ri_xscale;
 	dp = ri->ri_bits + row + dst * ri->ri_xscale;
@@ -772,13 +798,13 @@ rasops_copycols(void *cookie, int row, i
 		hp = ri->ri_hwbits + row + dst * ri->ri_xscale;
 
 	while (height--) {
-		memcpy(dp, sp, num);
-		dp += ri->ri_stride;
+		memmove(dp, sp, num);
 		if (ri->ri_hwbits) {
-			memcpy(hp, sp, num);
+			memcpy(hp, dp, num);
 			hp += ri->ri_stride;
 		}
 		sp += ri->ri_stride;
+		dp += ri->ri_stride;
 	}
 }
 
@@ -798,16 +824,16 @@ rasops_cursor(void *cookie, int on, int 
 			ri->ri_do_cursor(ri);
 
 	/* Select new cursor */
+	ri->ri_crow = row;
+	ri->ri_ccol = col;
+
 #ifdef RASOPS_CLIPPING
 	ri->ri_flg &= ~RI_CURSORCLIP;
-
 	if (row < 0 || row >= ri->ri_rows)
 		ri->ri_flg |= RI_CURSORCLIP;
 	else if (col < 0 || col >= ri->ri_cols)
 		ri->ri_flg |= RI_CURSORCLIP;
 #endif
-	ri->ri_crow = row;
-	ri->ri_ccol = col;
 
 	if (on) {
 		ri->ri_flg |= RI_CURSOR;
@@ -845,18 +871,18 @@ rasops_init_devcmap(struct rasops_info *
 		ri->ri_devcmap[15] = -1;
 		return;
 
-#ifdef RASOPS_APPLE_PALETTE
 	case 4:
 		for (i = 0; i < 16; i++) {
+#ifdef RASOPS_APPLE_PALETTE
 			c = apple4_devcmap[i];
+#else
+			c = i;
+#endif
 			ri->ri_devcmap[i] =
 			    (c <<  0) | (c <<  4) | (c <<  8) | (c << 12) |
 			    (c << 16) | (c << 20) | (c << 24) | (c << 28);
 		}
 		return;
-#else
-	/* XXXRO What should we do here? */
-#endif
 
 	case 8:
 		if ((ri->ri_flg & RI_8BIT_IS_RGB) == 0) {
@@ -894,39 +920,48 @@ rasops_init_devcmap(struct rasops_info *
 			c |= (uint32_t)(*p << (ri->ri_bnum - 8)) << ri->ri_bpos;
 		p++;
 
-		/* Fill the word for generic routines, which want this */
-		if (ri->ri_depth == 8) {
+		/*
+		 * Swap byte order if necessary. Then, fill the word for
+		 * generic routines, which want this.
+		 */
+		switch (ri->ri_depth) {
+		case 8:
 			c |= c << 8;
 			c |= c << 16;
-		} else if (ri->ri_depth == 15 || ri->ri_depth == 16)
+			break;
+		case 15:
+		case 16:
+			if ((ri->ri_flg & RI_BSWAP) != 0)
+				c = bswap16(c);
 			c |= c << 16;
-		else if (ri->ri_depth == 24) {
+			break;
+		case 24:
 #if BYTE_ORDER == LITTLE_ENDIAN
-#  ifndef RASOPS_SMALL
-			if (ri->ri_font->fontwidth != 12)
-#  endif
-				c = (c & 0x0000ff) << 16 | (c & 0x00ff00) |
-				    (c & 0xff0000) >> 16;
-#  ifndef RASOPS_SMALL
-			else
-				c = (c & 0x0000ff) | (c & 0x00ff00) << 8 |
-				    (c & 0xff0000) >> 8;
-#  endif
+			if ((ri->ri_flg & RI_BSWAP) == 0)
 #else
-			/* XXXRO What should we do here? */
+			if ((ri->ri_flg & RI_BSWAP) != 0)
 #endif
+			{
+				/*
+				 * Convert to ``big endian'' if not RI_BSWAP.
+				 */
+				c = (c & 0x0000ff) << 16|
+				    (c & 0x00ff00) |
+				    (c & 0xff0000) >> 16;
+			}
+			/*
+			 * No worries, we use generic routines only for
+			 * gray colors, where all 3 bytes are same.
+			 */
 			c |= (c & 0xff) << 24;
+			break;
+		case 32:
+			if ((ri->ri_flg & RI_BSWAP) != 0)
+				c = bswap32(c);
+			break;
 		}
 
-		/* 24bpp does bswap on the fly. {32,16,15}bpp do it here. */
-		if ((ri->ri_flg & RI_BSWAP) == 0)
-			ri->ri_devcmap[i] = c;
-		else if (ri->ri_depth == 15 || ri->ri_depth == 16)
-			ri->ri_devcmap[i] = bswap16(c);
-		else if (ri->ri_depth == 32)
-			ri->ri_devcmap[i] = bswap32(c);
-		else /* 8, 24 */
-			ri->ri_devcmap[i] = c;
+		ri->ri_devcmap[i] = c;
 	}
 }
 
@@ -950,8 +985,8 @@ void
 rasops_eraserows(void *cookie, int row, int num, long attr)
 {
 	struct rasops_info *ri = (struct rasops_info *)cookie;
-	uint32_t *rp, *dp, *hp, clr;
-	int n, cnt;
+	int bytes;
+	uint32_t bg, *rp, *hp;
 
 	hp = NULL;	/* XXX GCC */
 
@@ -968,8 +1003,6 @@ rasops_eraserows(void *cookie, int row, 
 		return;
 #endif
 
-	clr = ri->ri_devcmap[((uint32_t)attr >> 16) & 0xf];
-
 	/*
 	 * XXX The wsdisplay_emulops interface seems a little deficient in
 	 * that there is no way to clear the *entire* screen. We provide a
@@ -977,25 +1010,25 @@ rasops_eraserows(void *cookie, int row, 
 	 * the RI_FULLCLEAR flag is set, clear the entire display.
 	 */
 	if (num == ri->ri_rows && (ri->ri_flg & RI_FULLCLEAR) != 0) {
-		n = ri->ri_stride >> 2;
+		bytes = ri->ri_stride;
 		num = ri->ri_height;
 		rp = (uint32_t *)ri->ri_origbits;
 		if (ri->ri_hwbits)
 			hp = (uint32_t *)ri->ri_hworigbits;
 	} else {
-		n = ri->ri_emustride >> 2;
+		bytes = ri->ri_emustride;
 		num *= ri->ri_font->fontheight;
 		rp = (uint32_t *)(ri->ri_bits + row * ri->ri_yscale);
 		if (ri->ri_hwbits)
 			hp = (uint32_t *)(ri->ri_hwbits + row * ri->ri_yscale);
 	}
 
+	bg = ATTR_BG(ri, attr);
+
 	while (num--) {
-		dp = rp;
-		for (cnt = n; cnt; cnt--)
-			*dp++ = clr;
+		rasops_memset32(rp, bg, bytes);
 		if (ri->ri_hwbits) {
-			memcpy(hp, rp, n << 2);
+			memcpy(hp, rp, bytes);
 			DELTA(hp, ri->ri_stride, uint32_t *);
 		}
 		DELTA(rp, ri->ri_stride, uint32_t *);
@@ -1009,10 +1042,9 @@ rasops_eraserows(void *cookie, int row, 
 static void
 rasops_do_cursor(struct rasops_info *ri)
 {
-	int full, height, cnt, slop1, slop2, row, col;
-	uint32_t tmp32, msk1, msk2;
-	uint8_t tmp8;
-	uint8_t *dp, *rp, *hp;
+	int row, col, height, slop1, slop2, full, cnt;
+	uint32_t mask1, mask2, *dp;
+	uint8_t tmp, *rp, *hp;
 
 	hp = NULL;	/* XXX GCC */
 
@@ -1037,11 +1069,12 @@ rasops_do_cursor(struct rasops_info *ri)
 		col = ri->ri_ccol;
 	}
 
-	rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
-	if (ri->ri_hwbits)
-		hp = ri->ri_hwbits + row * ri->ri_yscale + col * ri->ri_xscale;
 	height = ri->ri_font->fontheight;
 
+	rp = ri->ri_bits + FBOFFSET(ri, row, col);
+	if (ri->ri_hwbits)
+		hp = ri->ri_hwbits + FBOFFSET(ri, row, col);
+
 	/*
 	 * For ri_xscale = 1:
 	 *
@@ -1050,15 +1083,13 @@ rasops_do_cursor(struct rasops_info *ri)
 	 */
 	if (ri->ri_xscale == 1) {
 		while (height--) {
-			tmp8 = ~*rp;
-
-			*rp = tmp8;
-			rp += ri->ri_stride;
-
+			tmp = ~*rp;
+			*rp = tmp;
 			if (ri->ri_hwbits) {
-				*hp = tmp8;
+				*hp = tmp;
 				hp += ri->ri_stride;
 			}
+			rp += ri->ri_stride;
 		}
 		return;
 	}
@@ -1076,28 +1107,24 @@ rasops_do_cursor(struct rasops_info *ri)
 	rp = (uint8_t *)((uintptr_t)rp & ~3);
 	hp = (uint8_t *)((uintptr_t)hp & ~3);
 
-	msk1 = !slop1 ? 0 : be32toh(0xffffffffU >> (32 - (8 * slop1)));
-	msk2 = !slop2 ? 0 : be32toh(0xffffffffU << (32 - (8 * slop2)));
+	mask1 = rasops_lmask32[4 - slop1];
+	mask2 = rasops_rmask32[slop2];
 
 	while (height--) {
-		dp = rp;
+		dp = (uint32_t *)rp;
 
 		if (slop1) {
-			tmp32 = *(uint32_t *)dp ^ msk1;
-			*(uint32_t *)dp = tmp32;
-			dp += 4;
+			*dp = *dp ^ mask1;
+			dp++;
 		}
 
 		for (cnt = full; cnt; cnt--) {
-			tmp32 = ~*(uint32_t *)dp;
-			*(uint32_t *)dp = tmp32;
-			dp += 4;
+			*dp = ~*(uint32_t *)dp;
+			dp++;
 		}
 
-		if (slop2) {
-			tmp32 = *(uint32_t *)dp ^ msk2;
-			*(uint32_t *)dp = tmp32;
-		}
+		if (slop2)
+			*dp = *dp ^ mask2;
 
 		if (ri->ri_hwbits) {
 			memcpy(hp, rp, ((slop1 != 0) + full +
@@ -1115,8 +1142,8 @@ void
 rasops_erasecols(void *cookie, int row, int col, int num, long attr)
 {
 	struct rasops_info *ri = (struct rasops_info *)cookie;
-	int height, cnt, slop1, slop2, clr;
-	uint32_t *rp, *dp, *hp;
+	int height;
+	uint32_t bg, *rp, *hp;
 
 	hp = NULL;	/* XXX GCC */
 
@@ -1136,158 +1163,288 @@ rasops_erasecols(void *cookie, int row, 
 		return;
 #endif
 
+	height = ri->ri_font->fontheight;
 	num *= ri->ri_xscale;
-	rp = (uint32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
+
+	rp = (uint32_t *)(ri->ri_bits + FBOFFSET(ri, row, col));
 	if (ri->ri_hwbits)
-		hp = (uint32_t *)(ri->ri_hwbits + row*ri->ri_yscale +
-		    col*ri->ri_xscale);
-	height = ri->ri_font->fontheight;
-	clr = ri->ri_devcmap[((uint32_t)attr >> 16) & 0xf];
+		hp = (uint32_t *)(ri->ri_hwbits + FBOFFSET(ri, row, col));
 
-	/* Don't bother using the full loop for <= 32 pels */
-	if (num <= 32) {
-		if (((num | ri->ri_xscale) & 3) == 0) {
-			/* Word aligned blt */
-			num >>= 2;
-
-			while (height--) {
-				dp = rp;
-				for (cnt = num; cnt; cnt--)
-					*dp++ = clr;
-				if (ri->ri_hwbits) {
-					memcpy(hp, rp, num << 2);
-					DELTA(hp, ri->ri_stride, uint32_t *);
-				}
-				DELTA(rp, ri->ri_stride, uint32_t *);
-			}
-		} else if (((num | ri->ri_xscale) & 1) == 0) {
-			/*
-			 * Halfword aligned blt. This is needed so the
-			 * 15/16 bit ops can use this function.
-			 */
-			num >>= 1;
+	bg = ATTR_BG(ri, attr);
 
-			while (height--) {
-				dp = rp;
-				for (cnt = num; cnt; cnt--) {
-					*(uint16_t *)dp = clr;
-					DELTA(dp, 2, uint32_t *);
-				}
-				if (ri->ri_hwbits) {
-					memcpy(hp, rp, num << 1);
-					DELTA(hp, ri->ri_stride, uint32_t *);
-				}
-				DELTA(rp, ri->ri_stride, uint32_t *);
-			}
-		} else {
-			while (height--) {
-				dp = rp;
-				for (cnt = num; cnt; cnt--) {
-					*(uint8_t *)dp = clr;
-					DELTA(dp, 1, uint32_t *);
-				}
-				if (ri->ri_hwbits) {
-					memcpy(hp, rp, num);
-					DELTA(hp, ri->ri_stride, uint32_t *);
-				}
-				DELTA(rp, ri->ri_stride, uint32_t *);
-			}
+	while (height--) {
+		rasops_memset32(rp, bg, num);
+		if (ri->ri_hwbits) {
+			memcpy(hp, rp, num);
+			DELTA(hp, ri->ri_stride, uint32_t *);
 		}
-
-		return;
+		DELTA(rp, ri->ri_stride, uint32_t *);
 	}
+}
 
-	slop1 = (4 - ((uintptr_t)rp & 3)) & 3;
-	slop2 = (num - slop1) & 3;
-	num = (num - slop1 /* - slop2 */) >> 2;
+void
+rasops_make_box_chars_16(struct rasops_info *ri)
+{
+	int c, i, mid;
+	uint16_t vert_mask, hmask_left, hmask_right;
+	uint16_t *data = (uint16_t *)ri->ri_optfont.data;
 
-	while (height--) {
-		dp = rp;
+	vert_mask = 0xc000U >> ((ri->ri_font->fontwidth >> 1) - 1);
+	hmask_left = 0xff00U << (8 - (ri->ri_font->fontwidth >> 1));
+	hmask_right = hmask_left >> ((ri->ri_font->fontwidth + 1) >> 1);
+	mid = (ri->ri_font->fontheight + 1) >> 1;
 
-		/* Align span to 4 bytes */
-		if (slop1 & 1) {
-			*(uint8_t *)dp = clr;
-			DELTA(dp, 1, uint32_t *);
+	/* 0x00 would be empty anyway so don't bother */
+	for (c = 1; c < 16; c++) {
+		data += ri->ri_font->fontheight;
+		if (c & 1) {
+			/* upper segment */
+			for (i = 0; i < mid; i++)
+				data[i] = vert_mask;
 		}
-
-		if (slop1 & 2) {
-			*(uint16_t *)dp = clr;
-			DELTA(dp, 2, uint32_t *);
+		if (c & 4) {
+			/* lower segment */
+			for (i = mid; i < ri->ri_font->fontheight; i++)
+				data[i] = vert_mask;
 		}
-
-		/* Write 4 bytes per loop */
-		for (cnt = num; cnt; cnt--)
-			*dp++ = clr;
-
-		/* Write unaligned trailing slop */
-		if (slop2 & 1) {
-			*(uint8_t *)dp = clr;
-			DELTA(dp, 1, uint32_t *);
+		if (c & 2) {
+			/* right segment */
+			i = ri->ri_font->fontheight >> 1;
+			data[mid - 1] |= hmask_right;
+			data[mid] |= hmask_right;
 		}
-
-		if (slop2 & 2)
-			*(uint16_t *)dp = clr;
-
-		if (ri->ri_hwbits) {
-			memcpy(hp, rp, slop1 + (num << 2) + slop2);
-			DELTA(hp, ri->ri_stride, uint32_t *);
+		if (c & 8) {
+			/* left segment */
+			data[mid - 1] |= hmask_left;
+			data[mid] |= hmask_left;
 		}
-		DELTA(rp, ri->ri_stride, uint32_t *);
 	}
 }
 
-#if NRASOPS_ROTATION > 0
-/*
- * Quarter clockwise rotation routines (originally intended for the
- * built-in Zaurus C3x00 display in 16bpp).
- */
-
-static void
-rasops_rotate_font(int *cookie, int rotate)
+void
+rasops_make_box_chars_8(struct rasops_info *ri)
 {
-	struct rotatedfont *f;
-	int ncookie;
+	int c, i, mid;
+	uint8_t vert_mask, hmask_left, hmask_right;
+	uint8_t *data = (uint8_t *)ri->ri_optfont.data;
 
-	SLIST_FOREACH(f, &rotatedfonts, rf_next) {
-		if (f->rf_cookie == *cookie) {
-			*cookie = f->rf_rotated;
-			return;
+	vert_mask = 0xc0U >> ((ri->ri_font->fontwidth >> 1) - 1);
+	hmask_left = 0xf0U << (4 - (ri->ri_font->fontwidth >> 1));
+	hmask_right = hmask_left >> ((ri->ri_font->fontwidth + 1) >> 1);
+	mid = (ri->ri_font->fontheight + 1) >> 1;
+
+	/* 0x00 would be empty anyway so don't bother */
+	for (c = 1; c < 16; c++) {
+		data += ri->ri_font->fontheight;
+		if (c & 1) {
+			/* upper segment */
+			for (i = 0; i < mid; i++)
+				data[i] = vert_mask;
+		}
+		if (c & 4) {
+			/* lower segment */
+			for (i = mid; i < ri->ri_font->fontheight; i++)
+				data[i] = vert_mask;
+		}
+		if (c & 2) {
+			/* right segment */
+			i = ri->ri_font->fontheight >> 1;
+			data[mid - 1] |= hmask_right;
+			data[mid] |= hmask_right;
+		}
+		if (c & 8) {
+			/* left segment */
+			data[mid - 1] |= hmask_left;
+			data[mid] |= hmask_left;
 		}
 	}
+}
 
-	/*
-	 * We did not find a rotated version of this font. Ask the wsfont
-	 * code to compute one for us.
-	 */
-
-	f = kmem_alloc(sizeof(*f), KM_SLEEP);
-
-	if ((ncookie = wsfont_rotate(*cookie, rotate)) == -1)
-		goto fail;
-
-	f->rf_cookie = *cookie;
-	f->rf_rotated = ncookie;
-	SLIST_INSERT_HEAD(&rotatedfonts, f, rf_next);
+void
+rasops_make_box_chars_32(struct rasops_info *ri)
+{
+	int c, i, mid;
+	uint32_t vert_mask, hmask_left, hmask_right;
+	uint32_t *data = (uint32_t *)ri->ri_optfont.data;
 
-	*cookie = ncookie;
-	return;
+	vert_mask = 0xc0000000U >> ((ri->ri_font->fontwidth >> 1) - 1);
+	hmask_left = 0xffff0000U << (16 - (ri->ri_font->fontwidth >> 1));
+	hmask_right = hmask_left >> ((ri->ri_font->fontwidth + 1) >> 1);
+	mid = (ri->ri_font->fontheight + 1) >> 1;
 
-fail:	kmem_free(f, sizeof(*f));
-	return;
+	/* 0x00 would be empty anyway so don't bother */
+	for (c = 1; c < 16; c++) {
+		data += ri->ri_font->fontheight;
+		if (c & 1) {
+			/* upper segment */
+			for (i = 0; i < mid; i++)
+				data[i] = vert_mask;
+		}
+		if (c & 4) {
+			/* lower segment */
+			for (i = mid; i < ri->ri_font->fontheight; i++)
+				data[i] = vert_mask;
+		}
+		if (c & 2) {
+			/* right segment */
+			i = ri->ri_font->fontheight >> 1;
+			data[mid - 1] |= hmask_right;
+			data[mid] |= hmask_right;
+		}
+		if (c & 8) {
+			/* left segment */
+			data[mid - 1] |= hmask_left;
+			data[mid] |= hmask_left;
+		}
+	}
 }
 
-static void
-rasops_copychar(void *cookie, int srcrow, int dstrow, int srccol, int dstcol)
+void
+rasops_make_box_chars_alpha(struct rasops_info *ri)
 {
-	struct rasops_info *ri = (struct rasops_info *)cookie;
-	int height;
-	int r_srcrow, r_dstrow, r_srccol, r_dstcol;
-	uint8_t *sp, *dp;
+	int c, i, hmid, vmid, wi, he;
+	uint8_t *data = (uint8_t *)ri->ri_optfont.data;
+	uint8_t *ddata;
 
-	r_srcrow = srccol;
-	r_dstrow = dstcol;
-	r_srccol = ri->ri_rows - srcrow - 1;
-	r_dstcol = ri->ri_rows - dstrow - 1;
+	he = ri->ri_font->fontheight;
+	wi = ri->ri_font->fontwidth;
+	
+	vmid = (he + 1) >> 1;
+	hmid = (wi + 1) >> 1;
+
+	/* 0x00 would be empty anyway so don't bother */
+	for (c = 1; c < 16; c++) {
+		data += ri->ri_fontscale;
+		if (c & 1) {
+			/* upper segment */
+			ddata = data + hmid;
+			for (i = 0; i <= vmid; i++) {
+				*ddata = 0xff;
+				ddata += wi;
+			}
+		}
+		if (c & 4) {
+			/* lower segment */
+			ddata = data + wi * vmid + hmid;
+			for (i = vmid; i < he; i++) {
+				*ddata = 0xff;
+				ddata += wi;
+			}
+		}
+		if (c & 2) {
+			/* right segment */
+			ddata = data + wi * vmid + hmid;
+			for (i = hmid; i < wi; i++) {
+				*ddata = 0xff;
+				ddata++;
+			}
+		}
+		if (c & 8) {
+			/* left segment */
+			ddata = data + wi * vmid;
+			for (i = 0; i <= hmid; i++) {
+				*ddata = 0xff;
+				ddata++;
+			}
+		}
+	}
+}
+ 
+/*
+ * Return a colour map appropriate for the given struct rasops_info in the
+ * same form used by rasops_cmap[]
+ * For now this is either a copy of rasops_cmap[] or an R3G3B2 map, it should
+ * probably be a linear ( or gamma corrected? ) ramp for higher depths.
+ */
+int
+rasops_get_cmap(struct rasops_info *ri, uint8_t *palette, size_t bytes)
+{
+
+	if ((ri->ri_depth == 8) && ((ri->ri_flg & RI_8BIT_IS_RGB) != 0)) {
+		/* generate an R3G3B2 palette */
+		int i, idx = 0;
+		uint8_t tmp;
+
+		if (bytes < 256 * 3)
+			return EINVAL;
+		for (i = 0; i < 256; i++) {
+			tmp = i & 0xe0;
+			/*
+			 * replicate bits so 0xe0 maps to a red value of 0xff
+			 * in order to make white look actually white
+			 */
+			tmp |= (tmp >> 3) | (tmp >> 6);
+			palette[idx] = tmp;
+			idx++;
+
+			tmp = (i & 0x1c) << 3;
+			tmp |= (tmp >> 3) | (tmp >> 6);
+			palette[idx] = tmp;
+			idx++;
+
+			tmp = (i & 0x03) << 6;
+			tmp |= tmp >> 2;
+			tmp |= tmp >> 4;
+			palette[idx] = tmp;
+			idx++;
+		}
+	} else
+		memcpy(palette, rasops_cmap, uimin(bytes, sizeof(rasops_cmap)));
+
+	return 0;
+}
+
+#if NRASOPS_ROTATION > 0
+/*
+ * Quarter clockwise rotation routines (originally intended for the
+ * built-in Zaurus C3x00 display in 16bpp).
+ */
+
+static void
+rasops_rotate_font(int *cookie, int rotate)
+{
+	struct rotatedfont *f;
+	int ncookie;
+
+	SLIST_FOREACH(f, &rotatedfonts, rf_next) {
+		if (f->rf_cookie == *cookie) {
+			*cookie = f->rf_rotated;
+			return;
+		}
+	}
+
+	/*
+	 * We did not find a rotated version of this font. Ask the wsfont
+	 * code to compute one for us.
+	 */
+
+	f = kmem_alloc(sizeof(*f), KM_SLEEP);
+
+	if ((ncookie = wsfont_rotate(*cookie, rotate)) == -1)
+		goto fail;
+
+	f->rf_cookie = *cookie;
+	f->rf_rotated = ncookie;
+	SLIST_INSERT_HEAD(&rotatedfonts, f, rf_next);
+
+	*cookie = ncookie;
+	return;
+
+fail:	kmem_free(f, sizeof(*f));
+	return;
+}
+
+static void
+rasops_copychar(void *cookie, int srcrow, int dstrow, int srccol, int dstcol)
+{
+	struct rasops_info *ri = (struct rasops_info *)cookie;
+	int r_srcrow, r_dstrow, r_srccol, r_dstcol, height;
+	uint8_t *sp, *dp;
+
+	r_srcrow = srccol;
+	r_dstrow = dstcol;
+	r_srccol = ri->ri_rows - srcrow - 1;
+	r_dstcol = ri->ri_rows - dstrow - 1;
 
 	r_srcrow *= ri->ri_yscale;
 	r_dstrow *= ri->ri_yscale;
@@ -1308,7 +1465,7 @@ rasops_putchar_rotated_cw(void *cookie, 
 {
 	struct rasops_info *ri = (struct rasops_info *)cookie;
 	int height;
-	uint8_t *rp;
+	uint16_t fg, *rp;
 
 	if (__predict_false((unsigned int)row > ri->ri_rows ||
 	    (unsigned int)col > ri->ri_cols))
@@ -1322,19 +1479,21 @@ rasops_putchar_rotated_cw(void *cookie, 
 	ri->ri_real_ops.putchar(cookie, col, ri->ri_rows - row - 1, uc,
 	    attr & ~WSATTR_UNDERLINE);
 
-	/* Do rotated underline */
-	rp = ri->ri_bits + col * ri->ri_yscale + (ri->ri_rows - row - 1) * 
-	    ri->ri_xscale;
-	height = ri->ri_font->fontheight;
-
-	/* XXX this assumes 16-bit color depth */
+	/*
+	 * Do rotated underline
+	 * XXX this assumes 16-bit color depth
+	 */
 	if ((attr & WSATTR_UNDERLINE) != 0) {
-		uint16_t c =
-		    (uint16_t)ri->ri_devcmap[((uint32_t)attr >> 24) & 0xf];
+		height = ri->ri_font->fontheight;
+
+		rp = (uint16_t *)(ri->ri_bits + col * ri->ri_yscale +
+		    (ri->ri_rows - row - 1) * ri->ri_xscale);
+
+		fg = (uint16_t)ATTR_FG(ri, attr);
 
 		while (height--) {
-			*(uint16_t *)rp = c;
-			rp += ri->ri_stride;
+			*rp = fg;
+			DELTA(rp, ri->ri_stride, uint16_t *);
 		}
 	}
 }
@@ -1403,7 +1562,7 @@ rasops_copychar_ccw(void *cookie, int sr
     int dstcol)
 {
 	struct rasops_info *ri = (struct rasops_info *)cookie;
-	int height, r_srcrow, r_dstrow, r_srccol, r_dstcol;
+	int r_srcrow, r_dstrow, r_srccol, r_dstcol, height;
 	uint8_t *sp, *dp;
 
 	r_srcrow = ri->ri_cols - srccol - 1;
@@ -1430,7 +1589,7 @@ rasops_putchar_rotated_ccw(void *cookie,
 {
 	struct rasops_info *ri = (struct rasops_info *)cookie;
 	int height;
-	uint8_t *rp;
+	uint16_t fg, *rp;
 
 	if (__predict_false((unsigned int)row > ri->ri_rows ||
 	    (unsigned int)col > ri->ri_cols))
@@ -1444,20 +1603,23 @@ rasops_putchar_rotated_ccw(void *cookie,
 	ri->ri_real_ops.putchar(cookie, ri->ri_cols - col - 1, row, uc,
 	    attr & ~WSATTR_UNDERLINE);
 
-	/* Do rotated underline */
-	rp = ri->ri_bits + (ri->ri_cols - col - 1) * ri->ri_yscale +
-	    row * ri->ri_xscale +
-	    (ri->ri_font->fontwidth - 1) * ri->ri_pelbytes;
-	height = ri->ri_font->fontheight;
-
-	/* XXX this assumes 16-bit color depth */
+	/*
+	 * Do rotated underline
+	 * XXX this assumes 16-bit color depth
+	 */
 	if ((attr & WSATTR_UNDERLINE) != 0) {
-		uint16_t c =
-		    (uint16_t)ri->ri_devcmap[((uint32_t)attr >> 24) & 0xf];
+		height = ri->ri_font->fontheight;
+
+		rp = (uint16_t *)(ri->ri_bits +
+		    (ri->ri_cols - col - 1) * ri->ri_yscale +
+		    row * ri->ri_xscale +
+		    (ri->ri_font->fontwidth - 1) * ri->ri_pelbytes);
+
+		fg = (uint16_t)ATTR_FG(ri, attr);
 
 		while (height--) {
-			*(uint16_t *)rp = c;
-			rp += ri->ri_stride;
+			*rp = fg;
+			DELTA(rp, ri->ri_stride, uint16_t *);
 		}
 	}
 }
@@ -1496,215 +1658,3 @@ rasops_copycols_rotated_ccw(void *cookie
 			    src + coff, dst + coff);
 }
 #endif	/* NRASOPS_ROTATION */
-
-void
-rasops_make_box_chars_16(struct rasops_info *ri)
-{
-	int c, i, mid;
-	uint16_t vert_mask, hmask_left, hmask_right;
-	uint16_t *data = (uint16_t *)ri->ri_optfont.data;
-
-	vert_mask = 0xc000U >> ((ri->ri_font->fontwidth >> 1) - 1);
-	hmask_left = 0xff00U << (8 - (ri->ri_font->fontwidth >> 1));
-	hmask_right = hmask_left >> ((ri->ri_font->fontwidth + 1) >> 1);
-	mid = (ri->ri_font->fontheight + 1) >> 1;
-
-	/* 0x00 would be empty anyway so don't bother */
-	for (c = 1; c < 16; c++) {
-		data += ri->ri_font->fontheight;
-		if (c & 1) {
-			/* upper segment */
-			for (i = 0; i < mid; i++)
-				data[i] = vert_mask;
-		}
-		if (c & 4) {
-			/* lower segment */
-			for (i = mid; i < ri->ri_font->fontheight; i++)
-				data[i] = vert_mask;
-		}
-		if (c & 2) {
-			/* right segment */
-			i = ri->ri_font->fontheight >> 1;
-			data[mid - 1] |= hmask_right;
-			data[mid] |= hmask_right;
-		}
-		if (c & 8) {
-			/* left segment */
-			data[mid - 1] |= hmask_left;
-			data[mid] |= hmask_left;
-		}
-	}
-}
-
-void
-rasops_make_box_chars_8(struct rasops_info *ri)
-{
-	int c, i, mid;
-	uint8_t vert_mask, hmask_left, hmask_right;
-	uint8_t *data = (uint8_t *)ri->ri_optfont.data;
-
-	vert_mask = 0xc0U >> ((ri->ri_font->fontwidth >> 1) - 1);
-	hmask_left = 0xf0U << (4 - (ri->ri_font->fontwidth >> 1));
-	hmask_right = hmask_left >> ((ri->ri_font->fontwidth + 1) >> 1);
-	mid = (ri->ri_font->fontheight + 1) >> 1;
-
-	/* 0x00 would be empty anyway so don't bother */
-	for (c = 1; c < 16; c++) {
-		data += ri->ri_font->fontheight;
-		if (c & 1) {
-			/* upper segment */
-			for (i = 0; i < mid; i++)
-				data[i] = vert_mask;
-		}
-		if (c & 4) {
-			/* lower segment */
-			for (i = mid; i < ri->ri_font->fontheight; i++)
-				data[i] = vert_mask;
-		}
-		if (c & 2) {
-			/* right segment */
-			i = ri->ri_font->fontheight >> 1;
-			data[mid - 1] |= hmask_right;
-			data[mid] |= hmask_right;
-		}
-		if (c & 8) {
-			/* left segment */
-			data[mid - 1] |= hmask_left;
-			data[mid] |= hmask_left;
-		}
-	}
-}
-
-void
-rasops_make_box_chars_32(struct rasops_info *ri)
-{
-	int c, i, mid;
-	uint32_t vert_mask, hmask_left, hmask_right;
-	uint32_t *data = (uint32_t *)ri->ri_optfont.data;
-
-	vert_mask = 0xc0000000U >> ((ri->ri_font->fontwidth >> 1) - 1);
-	hmask_left = 0xffff0000U << (16 - (ri->ri_font->fontwidth >> 1));
-	hmask_right = hmask_left >> ((ri->ri_font->fontwidth + 1) >> 1);
-	mid = (ri->ri_font->fontheight + 1) >> 1;
-
-	/* 0x00 would be empty anyway so don't bother */
-	for (c = 1; c < 16; c++) {
-		data += ri->ri_font->fontheight;
-		if (c & 1) {
-			/* upper segment */
-			for (i = 0; i < mid; i++)
-				data[i] = vert_mask;
-		}
-		if (c & 4) {
-			/* lower segment */
-			for (i = mid; i < ri->ri_font->fontheight; i++)
-				data[i] = vert_mask;
-		}
-		if (c & 2) {
-			/* right segment */
-			i = ri->ri_font->fontheight >> 1;
-			data[mid - 1] |= hmask_right;
-			data[mid] |= hmask_right;
-		}
-		if (c & 8) {
-			/* left segment */
-			data[mid - 1] |= hmask_left;
-			data[mid] |= hmask_left;
-		}
-	}
-}
-
-void
-rasops_make_box_chars_alpha(struct rasops_info *ri)
-{
-	int c, i, hmid, vmid, wi, he;
-	uint8_t *data = (uint8_t *)ri->ri_optfont.data;
-	uint8_t *ddata;
-
-	he = ri->ri_font->fontheight;
-	wi = ri->ri_font->fontwidth;
-	
-	vmid = (he + 1) >> 1;
-	hmid = (wi + 1) >> 1;
-
-	/* 0x00 would be empty anyway so don't bother */
-	for (c = 1; c < 16; c++) {
-		data += ri->ri_fontscale;
-		if (c & 1) {
-			/* upper segment */
-			ddata = data + hmid;
-			for (i = 0; i <= vmid; i++) {
-				*ddata = 0xff;
-				ddata += wi;
-			}
-		}
-		if (c & 4) {
-			/* lower segment */
-			ddata = data + wi * vmid + hmid;
-			for (i = vmid; i < he; i++) {
-				*ddata = 0xff;
-				ddata += wi;
-			}
-		}
-		if (c & 2) {
-			/* right segment */
-			ddata = data + wi * vmid + hmid;
-			for (i = hmid; i < wi; i++) {
-				*ddata = 0xff;
-				ddata++;
-			}
-		}
-		if (c & 8) {
-			/* left segment */
-			ddata = data + wi * vmid;
-			for (i = 0; i <= hmid; i++) {
-				*ddata = 0xff;
-				ddata++;
-			}
-		}
-	}
-}
- 
-/*
- * Return a colour map appropriate for the given struct rasops_info in the
- * same form used by rasops_cmap[]
- * For now this is either a copy of rasops_cmap[] or an R3G3B2 map, it should
- * probably be a linear ( or gamma corrected? ) ramp for higher depths.
- */
- 
-int
-rasops_get_cmap(struct rasops_info *ri, uint8_t *palette, size_t bytes)
-{
-
-	if ((ri->ri_depth == 8) && ((ri->ri_flg & RI_8BIT_IS_RGB) != 0)) {
-		/* generate an R3G3B2 palette */
-		int i, idx = 0;
-		uint8_t tmp;
-
-		if (bytes < 768)
-			return EINVAL;
-		for (i = 0; i < 256; i++) {
-			tmp = i & 0xe0;
-			/*
-			 * replicate bits so 0xe0 maps to a red value of 0xff
-			 * in order to make white look actually white
-			 */
-			tmp |= (tmp >> 3) | (tmp >> 6);
-			palette[idx] = tmp;
-			idx++;
-
-			tmp = (i & 0x1c) << 3;
-			tmp |= (tmp >> 3) | (tmp >> 6);
-			palette[idx] = tmp;
-			idx++;
-
-			tmp = (i & 0x03) << 6;
-			tmp |= tmp >> 2;
-			tmp |= tmp >> 4;
-			palette[idx] = tmp;
-			idx++;
-		}
-	} else
-		memcpy(palette, rasops_cmap, uimin(bytes, sizeof(rasops_cmap)));
-	return 0;
-}

Index: src/sys/dev/rasops/rasops.h
diff -u src/sys/dev/rasops/rasops.h:1.38 src/sys/dev/rasops/rasops.h:1.38.2.1
--- src/sys/dev/rasops/rasops.h:1.38	Mon Jul 29 08:13:50 2019
+++ src/sys/dev/rasops/rasops.h	Thu Aug 15 12:21:27 2019
@@ -1,4 +1,4 @@
-/* 	$NetBSD: rasops.h,v 1.38 2019/07/29 08:13:50 rin Exp $ */
+/* 	$NetBSD: rasops.h,v 1.38.2.1 2019/08/15 12:21:27 martin Exp $ */
 
 /*-
  * Copyright (c) 1999 The NetBSD Foundation, Inc.
@@ -32,6 +32,8 @@
 #ifndef _RASOPS_H_
 #define _RASOPS_H_ 1
 
+#include <sys/param.h>
+
 #include <dev/wscons/wsconsio.h>
 #include <dev/wsfont/wsfont.h>
 
@@ -100,8 +102,7 @@ struct rasops_info {
 	 * on depths other than 15, 16, 24 and 32 bits per pel. On
 	 * 24 bit displays, ri_{r,g,b}num must be 8.
 	 */
-	uint8_t	ri_rnum;
-	/* number of bits for red */
+	uint8_t	ri_rnum;	/* number of bits for red */
 	uint8_t	ri_gnum;	/* number of bits for green */
 	uint8_t	ri_bnum;	/* number of bits for blue */
 	uint8_t	ri_rpos;	/* which bit red starts at */
@@ -114,7 +115,22 @@ struct rasops_info {
 	int	ri_emustride;	/* bytes per row we actually care about */
 	int	ri_rows;	/* number of rows (characters, not pels) */
 	int	ri_cols;	/* number of columns (characters, not pels) */
-	int	ri_delta;	/* row delta in bytes */
+#if __NetBSD_Prereq__(9, 99, 1)
+	struct {
+		int	off;	/* offset of underline from bottom */
+		int	height;	/* height of underline */
+	} ri_ul;
+#else
+	/*
+	 * XXX
+	 * hack to keep ABI compatibility for netbsd-9, -8, and -7.
+	 */
+	// int	ri_delta;	/* obsoleted */
+	struct {
+		short	off;
+		short	height;
+	} __packed ri_ul;
+#endif
 	int	ri_pelbytes;	/* bytes per pel (may be zero) */
 	int	ri_fontscale;	/* fontheight * fontstride */
 	int	ri_xscale;	/* fontwidth * pelbytes */
@@ -139,31 +155,14 @@ struct rasops_info {
 #endif
 };
 
-#define DELTA(p, d, cast) ((p) = (cast)((uint8_t *)(p) + (d)))
-
-#define CHAR_IN_FONT(c,font) 					\
-       ((c) >= (font)->firstchar && 				\
-	((c) - (font)->firstchar) < (font)->numchars)
-
-#define PICK_FONT(ri, c) (((c & WSFONT_FLAGS_MASK) == WSFONT_FLAG_OPT) && \
-			  (ri->ri_optfont.data != NULL)) ? \
-			 &ri->ri_optfont : ri->ri_font
-
-#define	FONT_GLYPH(uc, font, ri)					\
-	((uint8_t *)(font)->data + ((uc) - ((font)->firstchar)) *	\
-	    (ri)->ri_fontscale)
-
-static __inline uint32_t
-be32uatoh(uint8_t *p)
-{
-	uint32_t u;
-
-	u  = p[0]; u <<= 8;
-	u |= p[1]; u <<= 8;
-	u |= p[2]; u <<= 8;
-	u |= p[3];
-	return u;
-}
+#define CHAR_IN_FONT(c, font)						\
+	((c) >= (font)->firstchar &&					\
+	    (c) - (font)->firstchar < (font)->numchars)
+
+#define PICK_FONT(ri, c)						\
+	((((c) & WSFONT_FLAGS_MASK) == WSFONT_FLAG_OPT &&		\
+	    (ri)->ri_optfont.data != NULL) ?				\
+		&(ri)->ri_optfont : (ri)->ri_font)
 
 /*
  * rasops_init().
@@ -179,9 +178,19 @@ be32uatoh(uint8_t *p)
  * to -1 (or a new, valid cookie).
  */
 
+/* rasops.c */
+int	rasops_init(struct rasops_info *, int, int);
+int	rasops_reconfig(struct rasops_info *, int, int);
+void	rasops_unpack_attr(long, int *, int *, int *);
+void	rasops_eraserows(void *, int, int, long);
+void	rasops_erasecols(void *, int, int, int, long);
+int	rasops_get_cmap(struct rasops_info *, uint8_t *, size_t);
+
+extern const uint8_t	rasops_cmap[256 * 3];
+
+#ifdef _RASOPS_PRIVATE
 /*
- * Per-depth initialization functions. These should not be called outside
- * the rasops code.
+ * Per-depth initialization functions.
  */
 void	rasops1_init(struct rasops_info *);
 void	rasops2_init(struct rasops_info *);
@@ -191,17 +200,71 @@ void	rasops15_init(struct rasops_info *)
 void	rasops24_init(struct rasops_info *);
 void	rasops32_init(struct rasops_info *);
 
-/* rasops.c */
-int	rasops_init(struct rasops_info *, int, int);
-int	rasops_reconfig(struct rasops_info *, int, int);
-void	rasops_unpack_attr(long, int *, int *, int *);
-void	rasops_eraserows(void *, int, int, long);
-void	rasops_erasecols(void *, int, int, int, long);
-void	rasops_copycols(void *, int, int, int, int);
-int	rasops_get_cmap(struct rasops_info *, uint8_t *, size_t);
+#define	ATTR_BG(ri, attr) ((ri)->ri_devcmap[((uint32_t)(attr) >> 16) & 0xf])
+#define	ATTR_FG(ri, attr) ((ri)->ri_devcmap[((uint32_t)(attr) >> 24) & 0xf])
+
+#define	ATTR_MASK_BG __BITS(16, 19)
+#define	ATTR_MASK_FG __BITS(24, 27)
 
+#define	DELTA(p, d, cast) ((p) = (cast)((uint8_t *)(p) + (d)))
+
+#define	FBOFFSET(ri, row, col)						\
+	((row) * (ri)->ri_yscale + (col) * (ri)->ri_xscale)
+
+#define	FONT_GLYPH(uc, font, ri)					\
+	((uint8_t *)(font)->data + ((uc) - ((font)->firstchar)) *	\
+	    (ri)->ri_fontscale)
+
+static __inline void
+rasops_memset32(void *p, uint32_t val, size_t bytes)
+{
+	int slop1, slop2, full;
+	uint8_t *dp = (uint8_t *)p;
 
-extern const uint8_t	rasops_isgray[16];
-extern const uint8_t	rasops_cmap[256*3];
+	if (bytes == 1) {
+		*dp = val;
+		return;
+	}
+
+	slop1 = (4 - ((uintptr_t)dp & 3)) & 3;
+	slop2 = (bytes - slop1) & 3;
+	full = (bytes - slop1 /* - slop2 */) >> 2;
+
+	if (slop1 & 1)
+		*dp++ = val;
+
+	if (slop1 & 2) {
+		*(uint16_t *)dp = val;
+		dp += 2;
+	}
+
+	for (; full; full--) {
+		*(uint32_t *)dp = val;
+		dp += 4;
+	}
+
+	if (slop2 & 2) {
+		*(uint16_t *)dp = val;
+		dp += 2;
+	}
+
+	if (slop2 & 1)
+		*dp = val;
+
+	return;
+}
+
+static __inline uint32_t
+rasops_be32uatoh(uint8_t *p)
+{
+	uint32_t u;
+
+	u  = p[0]; u <<= 8;
+	u |= p[1]; u <<= 8;
+	u |= p[2]; u <<= 8;
+	u |= p[3];
+	return u;
+}
+#endif /* _RASOPS_PRIVATE */
 
 #endif /* _RASOPS_H_ */

Index: src/sys/dev/rasops/rasops1.c
diff -u src/sys/dev/rasops/rasops1.c:1.31 src/sys/dev/rasops/rasops1.c:1.31.2.1
--- src/sys/dev/rasops/rasops1.c:1.31	Tue Jul 30 15:29:40 2019
+++ src/sys/dev/rasops/rasops1.c	Thu Aug 15 12:21:27 2019
@@ -1,4 +1,4 @@
-/* 	$NetBSD: rasops1.c,v 1.31 2019/07/30 15:29:40 rin Exp $	*/
+/* 	$NetBSD: rasops1.c,v 1.31.2.1 2019/08/15 12:21:27 martin Exp $	*/
 
 /*-
  * Copyright (c) 1999 The NetBSD Foundation, Inc.
@@ -30,17 +30,21 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: rasops1.c,v 1.31 2019/07/30 15:29:40 rin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: rasops1.c,v 1.31.2.1 2019/08/15 12:21:27 martin Exp $");
 
+#ifdef _KERNEL_OPT
 #include "opt_rasops.h"
+#endif
 
 #include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/time.h>
+
 #include <machine/endian.h>
 
 #include <dev/wscons/wsdisplayvar.h>
 #include <dev/wscons/wsconsio.h>
+
+#define	_RASOPS_PRIVATE
+#define	RASOPS_DEPTH	1
 #include <dev/rasops/rasops.h>
 #include <dev/rasops/rasops_masks.h>
 
@@ -89,14 +93,17 @@ rasops1_putchar(void *cookie, int row, i
 {
 	struct rasops_info *ri = (struct rasops_info *)cookie;
 	struct wsdisplay_font *font = PICK_FONT(ri, uc);
-	uint32_t fs, rs, fb, bg, fg, lmask, rmask;
-	uint32_t height, width;
-	uint32_t *rp, *hp, tmp, tmp0, tmp1;
+	int height, width;
+	uint32_t bg, fg, lbg, rbg, fb, lmask, rmask, tmp, tmp0, tmp1;
+	uint32_t *rp, *hp;
 	uint8_t *fr;
 	bool space;
 
 	hp = NULL;	/* XXX GCC */
 
+	if (__predict_false(!CHAR_IN_FONT(uc, font)))
+		return;
+
 #ifdef RASOPS_CLIPPING
 	/* Catches 'row < 0' case too */
 	if ((unsigned)row >= (unsigned)ri->ri_rows)
@@ -106,35 +113,33 @@ rasops1_putchar(void *cookie, int row, i
 		return;
 #endif
 
-	col *= ri->ri_font->fontwidth;
+	height = font->fontheight;
+	width = font->fontwidth;
+	col *= width;
+
 	rp = (uint32_t *)(ri->ri_bits + row * ri->ri_yscale +
 	    ((col >> 3) & ~3));
 	if (ri->ri_hwbits)
 		hp = (uint32_t *)(ri->ri_hwbits + row * ri->ri_yscale +
 		    ((col >> 3) & ~3));
-	height = font->fontheight;
-	width = font->fontwidth;
+
 	col &= 31;
-	rs = ri->ri_stride;
 
-	bg = (attr & 0x000f0000) ? ri->ri_devcmap[1] : ri->ri_devcmap[0];
-	fg = (attr & 0x0f000000) ? ri->ri_devcmap[1] : ri->ri_devcmap[0];
+	bg = ATTR_BG(ri, attr);
+	fg = ATTR_FG(ri, attr);
 
 	/* If fg and bg match this becomes a space character */
-	if (uc == ' ' || fg == bg) {
+	if (uc == ' ' || __predict_false(fg == bg)) {
 		space = true;
 		fr = NULL;	/* XXX GCC */
-		fs = 0;		/* XXX GCC */
 	} else {
 		space = false;
 		fr = FONT_GLYPH(uc, font, ri);
-		fs = font->stride;
 	}
 
 	if (col + width <= 32) {
 		/* Single word, only one mask */
-
-		rmask = rasops_pmask[col][width];
+		rmask = rasops_pmask[col][width & 31];
 		lmask = ~rmask;
 
 		if (space) {
@@ -142,106 +147,134 @@ rasops1_putchar(void *cookie, int row, i
 			while (height--) {
 				tmp = (*rp & lmask) | bg;
 				*rp = tmp;
-				DELTA(rp, rs, uint32_t *);
 				if (ri->ri_hwbits) {
 					*hp = tmp;
-					DELTA(hp, rs, uint32_t *);
+					DELTA(hp, ri->ri_stride, uint32_t *);
 				}
+				DELTA(rp, ri->ri_stride, uint32_t *);
 			}
 		} else {
 			while (height--) {
-				tmp = *rp & lmask;
-				fb = be32uatoh(fr);
-				fr += fs;
+				fb = rasops_be32uatoh(fr);
+				fr += font->stride;
 				if (bg)
 					fb = ~fb;
+
+				tmp = *rp & lmask;
 				tmp |= (MBE(fb >> col) & rmask);
 				*rp = tmp;
-				DELTA(rp, rs, uint32_t *);
+
 				if (ri->ri_hwbits) {
 					*hp = tmp;
-					DELTA(hp, rs, uint32_t *);
+					DELTA(hp, ri->ri_stride, uint32_t *);
 				}
+
+				DELTA(rp, ri->ri_stride, uint32_t *);
 			}
 		}
 
 		/* Do underline */
 		if ((attr & WSATTR_UNDERLINE) != 0) {
-			DELTA(rp, -(ri->ri_stride << 1), uint32_t *);
-			tmp = (*rp & lmask) | (fg & rmask);
-			*rp = tmp;
-			if (ri->ri_hwbits) {
-				DELTA(hp, -(ri->ri_stride << 1), uint32_t *);
-				*hp = tmp;
+			DELTA(rp, - ri->ri_stride * ri->ri_ul.off, uint32_t *);
+			if (ri->ri_hwbits)
+				DELTA(hp, - ri->ri_stride * ri->ri_ul.off,
+				    uint32_t *);
+
+			for (height = ri->ri_ul.height; height; height--) {
+				DELTA(rp, - ri->ri_stride, uint32_t *);
+				tmp = (*rp & lmask) | (fg & rmask);
+				*rp = tmp;
+				if (ri->ri_hwbits) {
+					DELTA(hp, - ri->ri_stride, uint32_t *);
+					*hp = tmp;
+				}
 			}
 		}
 	} else {
 		/* Word boundary, two masks needed */
-
 		lmask = ~rasops_lmask[col];
 		rmask = ~rasops_rmask[(col + width) & 31];
 
 		if (space) {
-			width = bg & ~rmask;
-			bg = bg & ~lmask;
+			lbg = bg & ~lmask;
+			rbg = bg & ~rmask;
+
 			while (height--) {
-				tmp0 = (rp[0] & lmask) | bg;
-				tmp1 = (rp[1] & rmask) | width;
+				tmp0 = (rp[0] & lmask) | lbg;
+				tmp1 = (rp[1] & rmask) | rbg;
+
 				rp[0] = tmp0;
 				rp[1] = tmp1;
-				DELTA(rp, rs, uint32_t *);
+
 				if (ri->ri_hwbits) {
 					hp[0] = tmp0;
 					hp[1] = tmp1;
-					DELTA(hp, rs, uint32_t *);
+					DELTA(hp, ri->ri_stride, uint32_t *);
 				}
+
+				DELTA(rp, ri->ri_stride, uint32_t *);
 			}
 		} else {
 			width = 32 - col;
+
 			while (height--) {
-				tmp0 = rp[0] & lmask;
-				tmp1 = rp[1] & rmask;
-				fb = be32uatoh(fr);
-				fr += fs;
+				fb = rasops_be32uatoh(fr);
+				fr += font->stride;
 				if (bg)
 					fb = ~fb;
+
+				tmp0 = rp[0] & lmask;
 				tmp0 |= MBE(fb >> col);
+
+				tmp1 = rp[1] & rmask;
 				tmp1 |= (MBE(fb << width) & ~rmask);
+
 				rp[0] = tmp0;
 				rp[1] = tmp1;
-				DELTA(rp, rs, uint32_t *);
+
 				if (ri->ri_hwbits) {
 					hp[0] = tmp0;
 					hp[1] = tmp1;
-					DELTA(hp, rs, uint32_t *);
+					DELTA(hp, ri->ri_stride, uint32_t *);
 				}
+
+				DELTA(rp, ri->ri_stride, uint32_t *);
 			}
 		}
 
 		/* Do underline */
 		if ((attr & WSATTR_UNDERLINE) != 0) {
-			DELTA(rp, -(ri->ri_stride << 1), uint32_t *);
-			tmp0 = (rp[0] & lmask) | (fg & ~lmask);
-			tmp1 = (rp[1] & rmask) | (fg & ~rmask);
-			rp[0] = tmp0;
-			rp[1] = tmp1;
-			if (ri->ri_hwbits) {
-				DELTA(hp, -(ri->ri_stride << 1), uint32_t *);
-				hp[0] = tmp0;
-				hp[1] = tmp1;
+			DELTA(rp, - ri->ri_stride * ri->ri_ul.off, uint32_t *);
+			if (ri->ri_hwbits)
+				DELTA(hp, - ri->ri_stride * ri->ri_ul.off,
+				    uint32_t *);
+
+			for (height = ri->ri_ul.height; height; height--) {
+				DELTA(rp, - ri->ri_stride, uint32_t *);
+				tmp0 = (rp[0] & lmask) | (fg & ~lmask);
+				tmp1 = (rp[1] & rmask) | (fg & ~rmask);
+				rp[0] = tmp0;
+				rp[1] = tmp1;
+				if (ri->ri_hwbits) {
+					DELTA(hp, - ri->ri_stride, uint32_t *);
+					hp[0] = tmp0;
+					hp[1] = tmp1;
+				}
 			}
 		}
 	}
 }
 
 #ifndef RASOPS_SMALL
-
+/*
+ * Width-optimized putchar functions
+ */
 #define	RASOPS_WIDTH	8
-#include "rasops1_putchar_width.h"
+#include <dev/rasops/rasops1_putchar_width.h>
 #undef	RASOPS_WIDTH
 
 #define	RASOPS_WIDTH	16
-#include "rasops1_putchar_width.h"
+#include <dev/rasops/rasops1_putchar_width.h>
 #undef	RASOPS_WIDTH
 
 #endif	/* !RASOPS_SMALL */
@@ -249,7 +282,4 @@ rasops1_putchar(void *cookie, int row, i
 /*
  * Grab routines common to depths where (bpp < 8)
  */
-#define NAME(ident)	rasops1_##ident
-#define PIXEL_SHIFT	0
-
 #include <dev/rasops/rasops_bitops.h>
Index: src/sys/dev/rasops/rasops15.c
diff -u src/sys/dev/rasops/rasops15.c:1.31 src/sys/dev/rasops/rasops15.c:1.31.2.1
--- src/sys/dev/rasops/rasops15.c:1.31	Mon Jul 29 10:55:56 2019
+++ src/sys/dev/rasops/rasops15.c	Thu Aug 15 12:21:27 2019
@@ -1,4 +1,4 @@
-/* 	$NetBSD: rasops15.c,v 1.31 2019/07/29 10:55:56 rin Exp $	*/
+/* 	$NetBSD: rasops15.c,v 1.31.2.1 2019/08/15 12:21:27 martin Exp $	*/
 
 /*-
  * Copyright (c) 1999 The NetBSD Foundation, Inc.
@@ -30,16 +30,19 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: rasops15.c,v 1.31 2019/07/29 10:55:56 rin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: rasops15.c,v 1.31.2.1 2019/08/15 12:21:27 martin Exp $");
 
+#ifdef _KERNEL_OPT
 #include "opt_rasops.h"
+#endif
 
 #include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/time.h>
 
 #include <dev/wscons/wsdisplayvar.h>
 #include <dev/wscons/wsconsio.h>
+
+#define	_RASOPS_PRIVATE
+#define	RASOPS_DEPTH	15
 #include <dev/rasops/rasops.h>
 
 static void 	rasops15_putchar(void *, int, int, u_int, long);
@@ -52,12 +55,10 @@ static void	rasops15_makestamp(struct ra
 #endif
 
 #ifndef RASOPS_SMALL
-/*
- * 4x1 stamp for optimized character blitting
- */
-static uint32_t	stamp[32];
-static long	stamp_attr;
-static int	stamp_mutex;	/* XXX see note in readme */
+/* stamp for optimized character blitting */
+static uint32_t			stamp[32];
+static long			stamp_attr;
+static struct rasops_info	*stamp_ri;
 
 /*
  * offset = STAMP_SHIFT(fontbits, nibble #) & STAMP_MASK
@@ -104,13 +105,23 @@ rasops15_init(struct rasops_info *ri)
 #endif	/* !RASOPS_SMALL */
 	default:
 		ri->ri_ops.putchar = rasops15_putchar;
-		break;
+		return;
 	}
+
+#ifndef RASOPS_SMALL
+	stamp_attr = -1;
+	stamp_ri = NULL;
+#endif
 }
 
-#define	RASOPS_DEPTH	15
-#include "rasops_putchar.h"
-#include "rasops_putchar_aa.h"
+/* rasops15_putchar */
+#undef	RASOPS_AA
+#include <dev/rasops/rasops_putchar.h>
+
+/* rasops15_putchar_aa */
+#define	RASOPS_AA
+#include <dev/rasops/rasops_putchar.h>
+#undef	RASOPS_AA
 
 #ifndef RASOPS_SMALL
 /*
@@ -119,12 +130,14 @@ rasops15_init(struct rasops_info *ri)
 static void
 rasops15_makestamp(struct rasops_info *ri, long attr)
 {
-	uint32_t fg, bg;
 	int i;
+	uint32_t bg, fg;
 
-	fg = ri->ri_devcmap[((uint32_t)attr >> 24) & 0xf] & 0xffff;
-	bg = ri->ri_devcmap[((uint32_t)attr >> 16) & 0xf] & 0xffff;
 	stamp_attr = attr;
+	stamp_ri = ri;
+
+	bg = ATTR_BG(ri, attr) & 0xffff;
+	fg = ATTR_FG(ri, attr) & 0xffff;
 
 	for (i = 0; i < 32; i += 2) {
 #if BYTE_ORDER == LITTLE_ENDIAN
@@ -141,16 +154,19 @@ rasops15_makestamp(struct rasops_info *r
 	}
 }
 
+/*
+ * Width-optimized putchar functions
+ */
 #define	RASOPS_WIDTH	8
-#include "rasops_putchar_width.h"
+#include <dev/rasops/rasops_putchar_width.h>
 #undef	RASOPS_WIDTH
 
 #define	RASOPS_WIDTH	12
-#include "rasops_putchar_width.h"
+#include <dev/rasops/rasops_putchar_width.h>
 #undef	RASOPS_WIDTH
 
 #define	RASOPS_WIDTH	16
-#include "rasops_putchar_width.h"
+#include <dev/rasops/rasops_putchar_width.h>
 #undef	RASOPS_WIDTH
 
 #endif /* !RASOPS_SMALL */

Index: src/sys/dev/rasops/rasops1_putchar_width.h
diff -u src/sys/dev/rasops/rasops1_putchar_width.h:1.2 src/sys/dev/rasops/rasops1_putchar_width.h:1.2.2.1
--- src/sys/dev/rasops/rasops1_putchar_width.h:1.2	Mon Jul 29 17:22:19 2019
+++ src/sys/dev/rasops/rasops1_putchar_width.h	Thu Aug 15 12:21:27 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: rasops1_putchar_width.h,v 1.2 2019/07/29 17:22:19 rin Exp $ */
+/* $NetBSD: rasops1_putchar_width.h,v 1.2.2.1 2019/08/15 12:21:27 martin Exp $ */
 
 /* NetBSD: rasops1.c,v 1.28 2019/07/25 03:02:44 rin Exp */
 /*-
@@ -34,40 +34,44 @@
 #error "Width not supported"
 #endif
 
-#define	PUTCHAR_WIDTH1(width)	rasops1_putchar ## width
-#define	PUTCHAR_WIDTH(width)	PUTCHAR_WIDTH1(width)
-
 #if RASOPS_WIDTH == 8
-#define	COPY_UNIT	uint8_t
-#define	GET_GLYPH	tmp = fr[0]
+#define	SUBST_UNIT	uint8_t
+#define	GET_GLYPH(fr)	(fr)[0]
 #endif
 
 #if RASOPS_WIDTH == 16
 /*
- * rp and hrp are always half-word aligned, whereas
+ * rp and hp are always half-word aligned, whereas
  * fr may not be aligned in half-word boundary.
  */
-#define	COPY_UNIT	uint16_t
+#define	SUBST_UNIT	uint16_t
 #  if BYTE_ORDER == BIG_ENDIAN
-#define	GET_GLYPH	tmp = (fr[0] << 8) | fr[1]
+#define	GET_GLYPH(fr)	((fr)[0] << 8) | (fr)[1]
 #  else
-#define	GET_GLYPH	tmp = fr[0] | (fr[1] << 8)
+#define	GET_GLYPH(fr)	(fr)[0] | ((fr)[1] << 8)
 #  endif
 #endif /* RASOPS_WIDTH == 16 */
 
+#define	NAME(width)	NAME1(width)
+#define	NAME1(width)	rasops1_putchar ## width
+
 /*
  * Width-optimized putchar function.
  */
 static void
-PUTCHAR_WIDTH(RASOPS_WIDTH)(void *cookie, int row, int col, u_int uc, long attr)
+NAME(RASOPS_WIDTH)(void *cookie, int row, int col, u_int uc, long attr)
 {
 	struct rasops_info *ri = (struct rasops_info *)cookie;
 	struct wsdisplay_font *font = PICK_FONT(ri, uc);
-	int height, fs, rs, bg, fg;
+	int height;
+	uint32_t bg, fg;
 	uint8_t *fr;
-	COPY_UNIT *rp, *hrp, tmp;
+	SUBST_UNIT tmp, *rp, *hp;
 
-	hrp = NULL;	/* XXX GCC */
+	hp = NULL;	/* XXX GCC */
+
+	if (__predict_false(!CHAR_IN_FONT(uc, font)))
+		return;
 
 #ifdef RASOPS_CLIPPING
 	/* Catches 'row < 0' case too */
@@ -78,58 +82,67 @@ PUTCHAR_WIDTH(RASOPS_WIDTH)(void *cookie
 		return;
 #endif
 
-	rp = (COPY_UNIT *)(ri->ri_bits + row * ri->ri_yscale +
-	    col * sizeof(COPY_UNIT));
-	if (ri->ri_hwbits)
-		hrp = (COPY_UNIT *)(ri->ri_hwbits + row * ri->ri_yscale +
-		    col * sizeof(COPY_UNIT));
 	height = font->fontheight;
-	rs = ri->ri_stride;
 
-	bg = (attr & 0x000f0000) ? ri->ri_devcmap[1] : ri->ri_devcmap[0];
-	fg = (attr & 0x0f000000) ? ri->ri_devcmap[1] : ri->ri_devcmap[0];
+	rp = (SUBST_UNIT *)(ri->ri_bits + row * ri->ri_yscale +
+	    col * sizeof(SUBST_UNIT));
+	if (ri->ri_hwbits)
+		hp = (SUBST_UNIT *)(ri->ri_hwbits + row * ri->ri_yscale +
+		    col * sizeof(SUBST_UNIT));
+
+	bg = ATTR_BG(ri, attr);
+	fg = ATTR_FG(ri, attr);
 
 	/* If fg and bg match this becomes a space character */
-	if (uc == ' ' || fg == bg) {
+	if (uc == ' ' || __predict_false(fg == bg)) {
 		while (height--) {
 			*rp = bg;
-			DELTA(rp, rs, COPY_UNIT *);
 			if (ri->ri_hwbits) {
-				*hrp = bg;
-				DELTA(hrp, rs, COPY_UNIT *);
+				*hp = bg;
+				DELTA(hp, ri->ri_stride, SUBST_UNIT *);
 			}
+			DELTA(rp, ri->ri_stride, SUBST_UNIT *);
 		}
 	} else {
 		fr = FONT_GLYPH(uc, font, ri);
-		fs = font->stride;
 
 		while (height--) {
-			GET_GLYPH;
+			tmp = GET_GLYPH(fr);
+			fr += font->stride;
 			if (bg)
 				tmp = ~tmp;
+
 			*rp = tmp;
-			DELTA(rp, rs, COPY_UNIT *);
+
 			if (ri->ri_hwbits) {
-				*hrp = tmp;
-				DELTA(hrp, rs, COPY_UNIT *);
+				*hp = tmp;
+				DELTA(hp, ri->ri_stride, SUBST_UNIT *);
 			}
-			fr += fs;
+
+			DELTA(rp, ri->ri_stride, SUBST_UNIT *);
 		}
 	}
 
 	/* Do underline */
 	if ((attr & WSATTR_UNDERLINE) != 0) {
-		DELTA(rp, -(ri->ri_stride << 1), COPY_UNIT *);
-		*rp = fg;
-		if (ri->ri_hwbits) {
-			DELTA(hrp, -(ri->ri_stride << 1), COPY_UNIT *);
-			*hrp = fg;
+		DELTA(rp, - ri->ri_stride * ri->ri_ul.off, SUBST_UNIT *);
+		if (ri->ri_hwbits)
+			DELTA(hp, - ri->ri_stride * ri->ri_ul.off,
+			    SUBST_UNIT *);
+
+		for (height = ri->ri_ul.height; height; height--) {
+			DELTA(rp, - ri->ri_stride, SUBST_UNIT *);
+			*rp = fg;
+			if (ri->ri_hwbits) {
+				DELTA(hp, - ri->ri_stride, SUBST_UNIT *);
+				*hp = fg;
+			}
 		}
 	}
 }
 
-#undef	PUTCHAR_WIDTH1
-#undef	PUTCHAR_WIDTH
-
-#undef	COPY_UNIT
+#undef	SUBST_UNIT
 #undef	GET_GLYPH
+
+#undef	NAME
+#undef	NAME1

Index: src/sys/dev/rasops/rasops2.c
diff -u src/sys/dev/rasops/rasops2.c:1.26 src/sys/dev/rasops/rasops2.c:1.26.2.1
--- src/sys/dev/rasops/rasops2.c:1.26	Mon Jul 29 03:01:09 2019
+++ src/sys/dev/rasops/rasops2.c	Thu Aug 15 12:21:27 2019
@@ -1,4 +1,4 @@
-/* 	$NetBSD: rasops2.c,v 1.26 2019/07/29 03:01:09 rin Exp $	*/
+/* 	$NetBSD: rasops2.c,v 1.26.2.1 2019/08/15 12:21:27 martin Exp $	*/
 
 /*-
  * Copyright (c) 1999 The NetBSD Foundation, Inc.
@@ -30,17 +30,21 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: rasops2.c,v 1.26 2019/07/29 03:01:09 rin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: rasops2.c,v 1.26.2.1 2019/08/15 12:21:27 martin Exp $");
 
+#ifdef _KERNEL_OPT
 #include "opt_rasops.h"
+#endif
 
 #include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/time.h>
+
 #include <machine/endian.h>
 
 #include <dev/wscons/wsdisplayvar.h>
 #include <dev/wscons/wsconsio.h>
+
+#define	_RASOPS_PRIVATE
+#define	RASOPS_DEPTH	2
 #include <dev/rasops/rasops.h>
 #include <dev/rasops/rasops_masks.h>
 
@@ -48,20 +52,20 @@ static void	rasops2_copycols(void *, int
 static void	rasops2_erasecols(void *, int, int, int, long);
 static void	rasops2_do_cursor(struct rasops_info *);
 static void	rasops2_putchar(void *, int, int col, u_int, long);
+static void	rasops2_putchar_aa(void *, int, int col, u_int, long);
 #ifndef RASOPS_SMALL
 static void	rasops2_putchar8(void *, int, int col, u_int, long);
 static void	rasops2_putchar12(void *, int, int col, u_int, long);
 static void	rasops2_putchar16(void *, int, int col, u_int, long);
 static void	rasops2_makestamp(struct rasops_info *, long);
-
-/*
- * 4x1 stamp for optimized character blitting
- */
-static uint8_t	stamp[16];
-static long	stamp_attr;
-static int	stamp_mutex;	/* XXX see note in README */
 #endif
 
+#ifndef RASOPS_SMALL
+/* stamp for optimized character blitting */
+static uint8_t			stamp[16];
+static long			stamp_attr;
+static struct rasops_info	*stamp_ri;
+
 /*
  * offset = STAMP_SHIFT(fontbits, nibble #) & STAMP_MASK
  * destination = STAMP_READ(offset)
@@ -69,6 +73,7 @@ static int	stamp_mutex;	/* XXX see note 
 #define	STAMP_SHIFT(fb, n)	((n) ? (fb) >> 4 : (fb))
 #define	STAMP_MASK		0xf
 #define	STAMP_READ(o)		stamp[o]
+#endif
 
 /*
  * Initialize rasops_info struct for this colordepth.
@@ -77,6 +82,17 @@ void
 rasops2_init(struct rasops_info *ri)
 {
 
+	if ((ri->ri_font->fontwidth & 3) != 0) {
+		ri->ri_ops.erasecols = rasops2_erasecols;
+		ri->ri_ops.copycols = rasops2_copycols;
+		ri->ri_do_cursor = rasops2_do_cursor;
+	}
+
+	if (FONT_IS_ALPHA(ri->ri_font)) {
+		ri->ri_ops.putchar = rasops2_putchar_aa;
+		return;
+	}
+
 	switch (ri->ri_font->fontwidth) {
 #ifndef RASOPS_SMALL
 	case 8:
@@ -88,28 +104,16 @@ rasops2_init(struct rasops_info *ri)
 	case 16:
 		ri->ri_ops.putchar = rasops2_putchar16;
 		break;
-#endif	/* !RASOPS_SMALL */
+#endif
 	default:
-		panic("fontwidth not 8/12/16 or RASOPS_SMALL - fixme!");
 		ri->ri_ops.putchar = rasops2_putchar;
-		break;
+		return;
 	}
 
-	if ((ri->ri_font->fontwidth & 3) != 0) {
-		ri->ri_ops.erasecols = rasops2_erasecols;
-		ri->ri_ops.copycols = rasops2_copycols;
-		ri->ri_do_cursor = rasops2_do_cursor;
-	}
-}
-
-/*
- * Put a single character. This is the generic version.
- */
-static void
-rasops2_putchar(void *cookie, int row, int col, u_int uc, long attr)
-{
-
-	/* XXX punt */
+#ifndef RASOPS_SMALL
+	stamp_attr = -1;
+	stamp_ri = NULL;
+#endif
 }
 
 #ifndef RASOPS_SMALL
@@ -119,19 +123,22 @@ rasops2_putchar(void *cookie, int row, i
 static void
 rasops2_makestamp(struct rasops_info *ri, long attr)
 {
-	int i, fg, bg;
+	int i;
+	uint32_t bg, fg;
 
-	fg = ri->ri_devcmap[((uint32_t)attr >> 24) & 0xf] & 3;
-	bg = ri->ri_devcmap[((uint32_t)attr >> 16) & 0xf] & 3;
 	stamp_attr = attr;
+	stamp_ri = ri;
+
+	bg = ATTR_BG(ri, attr) & 3;
+	fg = ATTR_FG(ri, attr) & 3;
 
 	for (i = 0; i < 16; i++) {
-#if BYTE_ORDER == BIG_ENDIAN
-#define NEED_LITTLE_ENDIAN_STAMP RI_BSWAP
+#if BYTE_ORDER == LITTLE_ENDIAN
+		if ((ri->ri_flg & RI_BSWAP) == 0)
 #else
-#define NEED_LITTLE_ENDIAN_STAMP 0
+		if ((ri->ri_flg & RI_BSWAP) != 0)
 #endif
-		if ((ri->ri_flg & RI_BSWAP) == NEED_LITTLE_ENDIAN_STAMP) {
+		{
 			/* littel endian */
 			stamp[i]  = (i & 8 ? fg : bg);
 			stamp[i] |= (i & 4 ? fg : bg) << 2;
@@ -147,26 +154,33 @@ rasops2_makestamp(struct rasops_info *ri
 	}
 }
 
-#define	RASOPS_DEPTH	2
-
+/*
+ * Width-optimized putchar functions
+ */
 #define	RASOPS_WIDTH	8
-#include "rasops_putchar_width.h"
+#include <dev/rasops/rasops_putchar_width.h>
 #undef	RASOPS_WIDTH
 
 #define	RASOPS_WIDTH	12
-#include "rasops_putchar_width.h"
+#include <dev/rasops/rasops_putchar_width.h>
 #undef	RASOPS_WIDTH
 
 #define	RASOPS_WIDTH	16
-#include "rasops_putchar_width.h"
+#include <dev/rasops/rasops_putchar_width.h>
 #undef	RASOPS_WIDTH
 
 #endif	/* !RASOPS_SMALL */
 
+/* rasops2_putchar */
+#undef	RASOPS_AA
+#include <dev/rasops/rasops1-4_putchar.h>
+
+/* rasops2_putchar_aa */
+#define	RASOPS_AA
+#include <dev/rasops/rasops1-4_putchar.h>
+#undef	RASOPS_AA
+
 /*
  * Grab routines common to depths where (bpp < 8)
  */
-#define NAME(ident)	rasops2_##ident
-#define PIXEL_SHIFT	1
-
 #include <dev/rasops/rasops_bitops.h>

Index: src/sys/dev/rasops/rasops24.c
diff -u src/sys/dev/rasops/rasops24.c:1.39 src/sys/dev/rasops/rasops24.c:1.39.2.1
--- src/sys/dev/rasops/rasops24.c:1.39	Tue Jul 30 15:23:23 2019
+++ src/sys/dev/rasops/rasops24.c	Thu Aug 15 12:21:27 2019
@@ -1,4 +1,4 @@
-/* 	$NetBSD: rasops24.c,v 1.39 2019/07/30 15:23:23 rin Exp $	*/
+/* 	$NetBSD: rasops24.c,v 1.39.2.1 2019/08/15 12:21:27 martin Exp $	*/
 
 /*-
  * Copyright (c) 1999 The NetBSD Foundation, Inc.
@@ -30,39 +30,44 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: rasops24.c,v 1.39 2019/07/30 15:23:23 rin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: rasops24.c,v 1.39.2.1 2019/08/15 12:21:27 martin Exp $");
 
+#ifdef _KERNEL_OPT
 #include "opt_rasops.h"
+#endif
 
 #include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/time.h>
+#include <sys/bswap.h>
 
 #include <machine/endian.h>
-#include <sys/bswap.h>
 
 #include <dev/wscons/wsdisplayvar.h>
 #include <dev/wscons/wsconsio.h>
+
+#define	_RASOPS_PRIVATE
+#define	RASOPS_DEPTH	24
 #include <dev/rasops/rasops.h>
 
 static void 	rasops24_erasecols(void *, int, int, int, long);
 static void 	rasops24_eraserows(void *, int, int, long);
 static void 	rasops24_putchar(void *, int, int, u_int, long);
 static void 	rasops24_putchar_aa(void *, int, int, u_int, long);
+static __inline void
+		rasops24_makestamp1(struct rasops_info *, uint32_t *,
+				    uint32_t, uint32_t, uint32_t, uint32_t);
 #ifndef RASOPS_SMALL
 static void 	rasops24_putchar8(void *, int, int, u_int, long);
 static void 	rasops24_putchar12(void *, int, int, u_int, long);
 static void 	rasops24_putchar16(void *, int, int, u_int, long);
 static void	rasops24_makestamp(struct rasops_info *, long);
-
-/*
- * 4x1 stamp for optimized character blitting
- */
-static uint32_t	stamp[64];
-static long	stamp_attr;
-static int	stamp_mutex;	/* XXX see note in readme */
 #endif
 
+#ifndef RASOPS_SMALL
+/* stamp for optimized character blitting */
+static uint32_t			stamp[64];
+static long			stamp_attr;
+static struct rasops_info	*stamp_ri;
+
 /*
  * offset = STAMP_SHIFT(fontbits, nibble #) & STAMP_MASK
  * destination uint32_t[0] = STAMP_READ(offset)
@@ -72,6 +77,7 @@ static int	stamp_mutex;	/* XXX see note 
 #define	STAMP_SHIFT(fb, n)	((n) ? (fb) : (fb) << 4)
 #define	STAMP_MASK		(0xf << 4)
 #define	STAMP_READ(o)		(*(uint32_t *)((uint8_t *)stamp + (o)))
+#endif
 
 /*
  * Initialize rasops_info struct for this colordepth.
@@ -80,14 +86,6 @@ void
 rasops24_init(struct rasops_info *ri)
 {
 
-#ifndef RASOPS_SMALL
-	/*
-	 * Different devcmap's are used depending on font widths,
-	 * therefore we need reset stamp here.
-	 */
-	stamp_attr = 0;
-#endif
-
 	if (ri->ri_rnum == 0) {
 		ri->ri_rnum = ri->ri_gnum = ri->ri_bnum = 8;
 
@@ -118,13 +116,44 @@ rasops24_init(struct rasops_info *ri)
 #endif
 	default:
 		ri->ri_ops.putchar = rasops24_putchar;
-		break;
+		return;
 	}
+
+#ifndef RASOPS_SMALL
+	stamp_attr = -1;
+	stamp_ri = NULL;
+#endif
 }
 
-#define	RASOPS_DEPTH	24
-#include "rasops_putchar.h"
-#include "rasops_putchar_aa.h"
+/* rasops24_putchar */
+#undef	RASOPS_AA
+#include <dev/rasops/rasops_putchar.h>
+
+/* rasops24_putchar_aa */
+#define	RASOPS_AA
+#include <dev/rasops/rasops_putchar.h>
+#undef	RASOPS_AA
+
+static __inline void
+rasops24_makestamp1(struct rasops_info *ri, uint32_t *xstamp,
+    uint32_t c1, uint32_t c2, uint32_t c3, uint32_t c4)
+{
+
+	xstamp[0] = (c1 <<  8) | (c2 >> 16);
+	xstamp[1] = (c2 << 16) | (c3 >>  8);
+	xstamp[2] = (c3 << 24) |  c4;
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+	if ((ri->ri_flg & RI_BSWAP) == 0)
+#else
+	if ((ri->ri_flg & RI_BSWAP) != 0)
+#endif
+	{
+		xstamp[0] = bswap32(xstamp[0]);
+		xstamp[1] = bswap32(xstamp[1]);
+		xstamp[2] = bswap32(xstamp[2]);
+	}
+}
 
 #ifndef RASOPS_SMALL
 /*
@@ -133,12 +162,14 @@ rasops24_init(struct rasops_info *ri)
 static void
 rasops24_makestamp(struct rasops_info *ri, long attr)
 {
-	uint32_t fg, bg, c1, c2, c3, c4;
 	int i;
+	uint32_t bg, fg, c1, c2, c3, c4;
 
-	fg = ri->ri_devcmap[((uint32_t)attr >> 24) & 0xf] & 0xffffff;
-	bg = ri->ri_devcmap[((uint32_t)attr >> 16) & 0xf] & 0xffffff;
 	stamp_attr = attr;
+	stamp_ri = ri;
+
+	bg = ATTR_BG(ri, attr) & 0xffffff;
+	fg = ATTR_FG(ri, attr) & 0xffffff;
 
 	for (i = 0; i < 64; i += 4) {
 #if BYTE_ORDER == LITTLE_ENDIAN
@@ -152,32 +183,23 @@ rasops24_makestamp(struct rasops_info *r
 		c3 = i & 16 ? fg : bg;
 		c4 = i & 32 ? fg : bg;
 #endif
-		stamp[i + 0] = (c1 <<  8) | (c2 >> 16);
-		stamp[i + 1] = (c2 << 16) | (c3 >>  8);
-		stamp[i + 2] = (c3 << 24) |  c4;
-
-#if BYTE_ORDER == LITTLE_ENDIAN
-		if ((ri->ri_flg & RI_BSWAP) == 0) {
-#else
-		if ((ri->ri_flg & RI_BSWAP) != 0) {
-#endif
-			stamp[i + 0] = bswap32(stamp[i + 0]);
-			stamp[i + 1] = bswap32(stamp[i + 1]);
-			stamp[i + 2] = bswap32(stamp[i + 2]);
-		}
+		rasops24_makestamp1(ri, &stamp[i], c1, c2, c3, c4);
 	}
 }
 
+/*
+ * Width-optimized putchar functions
+ */
 #define	RASOPS_WIDTH	8
-#include "rasops_putchar_width.h"
+#include <dev/rasops/rasops_putchar_width.h>
 #undef	RASOPS_WIDTH
 
 #define	RASOPS_WIDTH	12
-#include "rasops_putchar_width.h"
+#include <dev/rasops/rasops_putchar_width.h>
 #undef	RASOPS_WIDTH
 
 #define	RASOPS_WIDTH	16
-#include "rasops_putchar_width.h"
+#include <dev/rasops/rasops_putchar_width.h>
 #undef	RASOPS_WIDTH
 
 #endif	/* !RASOPS_SMALL */
@@ -189,8 +211,9 @@ static void
 rasops24_eraserows(void *cookie, int row, int num, long attr)
 {
 	struct rasops_info *ri = (struct rasops_info *)cookie;
-	int n9, n3, n1, cnt, stride;
-	uint32_t *rp, *dp, *hp, clr, xstamp[3];
+	int bytes, full, slop, cnt;
+	uint32_t bg, xstamp[3];
+	uint32_t *dp, *rp, *hp;
 
 	hp = NULL;	/* XXX GCC */
 
@@ -216,20 +239,8 @@ rasops24_eraserows(void *cookie, int row
 		return;
 #endif
 
-	clr = ri->ri_devcmap[((uint32_t)attr >> 16) & 0xf] & 0xffffff;
-	xstamp[0] = (clr <<  8) | (clr >> 16);
-	xstamp[1] = (clr << 16) | (clr >>  8);
-	xstamp[2] = (clr << 24) |  clr;
-
-#if BYTE_ORDER == LITTLE_ENDIAN
-	if ((ri->ri_flg & RI_BSWAP) == 0) {
-#else
-	if ((ri->ri_flg & RI_BSWAP) != 0) {
-#endif
-		xstamp[0] = bswap32(xstamp[0]);
-		xstamp[1] = bswap32(xstamp[1]);
-		xstamp[2] = bswap32(xstamp[2]);
-	}
+	bg = ATTR_BG(ri, attr) & 0xffffff;
+	rasops24_makestamp1(ri, xstamp, bg, bg, bg, bg);
 
 	/*
 	 * XXX the wsdisplay_emulops interface seems a little deficient in
@@ -238,46 +249,40 @@ rasops24_eraserows(void *cookie, int row
 	 * the RI_FULLCLEAR flag is set, clear the entire display.
 	 */
 	if (num == ri->ri_rows && (ri->ri_flg & RI_FULLCLEAR) != 0) {
-		stride = ri->ri_stride;
+		bytes = ri->ri_stride;
 		num = ri->ri_height;
 		rp = (uint32_t *)ri->ri_origbits;
 		if (ri->ri_hwbits)
 			hp = (uint32_t *)ri->ri_hworigbits;
 	} else {
-		stride = ri->ri_emustride;
+		bytes = ri->ri_emustride;
 		num *= ri->ri_font->fontheight;
 		rp = (uint32_t *)(ri->ri_bits + row * ri->ri_yscale);
 		if (ri->ri_hwbits)
 			hp = (uint32_t *)(ri->ri_hwbits + row * ri->ri_yscale);
 	}
 
-	n9 = stride / (4 * 9);
-	cnt = n9 * (4 * 9);
-	n3 = (stride - cnt) / (4 * 3);
-	cnt += n3 * (4 * 3);
-	n1 = (stride - cnt) / 4;
+	full = bytes / (4 * 3);
+	slop = (bytes - full * (4 * 3)) / 4;
 
 	while (num--) {
 		dp = rp;
-		for (cnt = n9; cnt; cnt--) {
-			dp[0] = xstamp[0]; dp[1] = xstamp[1]; dp[2] = xstamp[2];
-			dp[3] = xstamp[0]; dp[4] = xstamp[1]; dp[5] = xstamp[2];
-			dp[6] = xstamp[0]; dp[7] = xstamp[1]; dp[8] = xstamp[2];
-			dp += 9;
-		}
 
-		for (cnt = n3; cnt; cnt--) {
-			dp[0] = xstamp[0]; dp[1] = xstamp[1]; dp[2] = xstamp[2];
+		for (cnt = full; cnt; cnt--) {
+			dp[0] = xstamp[0];
+			dp[1] = xstamp[1];
+			dp[2] = xstamp[2];
 			dp += 3;
 		}
 
-		for (cnt = 0; cnt < n1; cnt++)
+		for (cnt = 0; cnt < slop; cnt++)
 			*dp++ = xstamp[cnt];
 
 		if (ri->ri_hwbits) {
-			memcpy(hp, rp, stride);
+			memcpy(hp, rp, bytes);
 			DELTA(hp, ri->ri_stride, uint32_t *);
 		}
+
 		DELTA(rp, ri->ri_stride, uint32_t *);
 	}
 }
@@ -289,9 +294,10 @@ static void
 rasops24_erasecols(void *cookie, int row, int col, int num, long attr)
 {
 	struct rasops_info *ri = (struct rasops_info *)cookie;
-	int n12, n4, height, cnt, slop1, slop2, clr, xstamp[3];
+	int height, slop1, slop2, full, cnt;
+	uint32_t bg, xstamp[3];
 	uint32_t *dp;
-	uint8_t *rp, *hp, *dbp;
+	uint8_t *bp, *rp, *hp;
 
 	hp = NULL;	/* XXX GCC */
 
@@ -321,85 +327,66 @@ rasops24_erasecols(void *cookie, int row
 		return;
 #endif
 
+	height = ri->ri_font->fontheight;
+	num *= ri->ri_xscale;
+
 	rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
 	if (ri->ri_hwbits)
 		hp = ri->ri_hwbits + row * ri->ri_yscale + col * ri->ri_xscale;
 
-	num *= ri->ri_font->fontwidth;
-	height = ri->ri_font->fontheight;
-
-	clr = ri->ri_devcmap[((uint32_t)attr >> 16) & 0xf] & 0xffffff;
-	xstamp[0] = (clr <<  8) | (clr >> 16);
-	xstamp[1] = (clr << 16) | (clr >>  8);
-	xstamp[2] = (clr << 24) |  clr;
-
-#if BYTE_ORDER == LITTLE_ENDIAN
-	if ((ri->ri_flg & RI_BSWAP) == 0) {
-#else
-	if ((ri->ri_flg & RI_BSWAP) != 0) {
-#endif
-		xstamp[0] = bswap32(xstamp[0]);
-		xstamp[1] = bswap32(xstamp[1]);
-		xstamp[2] = bswap32(xstamp[2]);
-	}
+	bg = ATTR_BG(ri, attr) & 0xffffff;
+	rasops24_makestamp1(ri, xstamp, bg, bg, bg, bg);
 
 	/*
-	 * The current byte offset mod 4 tells us the number of 24-bit pels
-	 * we need to write for alignment to 32-bits. Once we're aligned on
-	 * a 32-bit boundary, we're also aligned on a 4 pixel boundary, so
-	 * the stamp does not need to be rotated. The following shows the
-	 * layout of 4 pels in a 3 word region and illustrates this:
+	 * Align to word boundary by 24-bit-wise operations:
+	 *
+	 * rp % 4 == 1 ---> slop1 = 3:
+	 *	0123
+	 *	-RGB
 	 *
-	 *	aaab bbcc cddd
+	 * rp % 4 == 2 ---> slop1 = 6:
+	 *	0123 0123
+	 *	--RG BRGB
+	 *
+	 * rp % 4 == 3 ---> slop1 = 9:
+	 *	0123 0123 0123
+	 *	---R GBRG BRGB
 	 */
-	slop1 = (uintptr_t)rp & 3;
-	cnt = slop1;
-	n12 = (num - cnt) / 12;
-	cnt += n12 * 12;
-	n4 = (num - cnt) / 4;
-	cnt += n4 * 4;
-	slop2 = num - cnt;
+	slop1 = 3 * ((uintptr_t)rp % 4);
+	slop2 = (num - slop1) % 12;
+	full = (num - slop1 /* - slop2 */) / 12;
 
 	while (height--) {
-		dbp = rp;
-
-		/* Align to 4 bytes */
-		/* XXX handle with masks, bring under control of RI_BSWAP */
-		for (cnt = slop1; cnt; cnt--) {
-			*dbp++ = (clr >> 16);
-			*dbp++ = (clr >> 8);
-			*dbp++ =  clr;
-		}
-
-		dp = (uint32_t *)dbp;
-
-		/* 12 pels per loop */
-		for (cnt = n12; cnt; cnt--) {
-			dp[0] = xstamp[0]; dp[1] = xstamp[1]; dp[2] = xstamp[2];
-			dp[3] = xstamp[0]; dp[4] = xstamp[1]; dp[5] = xstamp[2];
-			dp[6] = xstamp[0]; dp[7] = xstamp[1]; dp[8] = xstamp[2];
-			dp += 9;
+		/* Align to word boundary */
+		bp = rp;
+		for (cnt = slop1; cnt; cnt -= 3) {
+			*bp++ = (bg >> 16);
+			*bp++ = (bg >> 8);
+			*bp++ = bg;
 		}
 
 		/* 4 pels per loop */
-		for (cnt = n4; cnt; cnt--) {
-			dp[0] = xstamp[0]; dp[1] = xstamp[1]; dp[2] = xstamp[2];
+		dp = (uint32_t *)bp;
+		for (cnt = full; cnt; cnt--) {
+			dp[0] = xstamp[0];
+			dp[1] = xstamp[1];
+			dp[2] = xstamp[2];
 			dp += 3;
 		}
 
 		/* Trailing slop */
-		/* XXX handle with masks, bring under control of RI_BSWAP */
-		dbp = (uint8_t *)dp;
-		for (cnt = slop2; cnt; cnt--) {
-			*dbp++ = (clr >> 16);
-			*dbp++ = (clr >> 8);
-			*dbp++ =  clr;
+		bp = (uint8_t *)dp;
+		for (cnt = slop2; cnt; cnt -= 3) {
+			*bp++ = (bg >> 16);
+			*bp++ = (bg >> 8);
+			*bp++ = bg;
 		}
 
 		if (ri->ri_hwbits) {
-			memcpy(hp, rp, num * 3);
+			memcpy(hp, rp, num);
 			hp += ri->ri_stride;
 		}
+
 		rp += ri->ri_stride;
 	}
 }
Index: src/sys/dev/rasops/rasops32.c
diff -u src/sys/dev/rasops/rasops32.c:1.39 src/sys/dev/rasops/rasops32.c:1.39.2.1
--- src/sys/dev/rasops/rasops32.c:1.39	Mon Jul 29 10:55:56 2019
+++ src/sys/dev/rasops/rasops32.c	Thu Aug 15 12:21:27 2019
@@ -1,4 +1,4 @@
-/*	 $NetBSD: rasops32.c,v 1.39 2019/07/29 10:55:56 rin Exp $	*/
+/*	 $NetBSD: rasops32.c,v 1.39.2.1 2019/08/15 12:21:27 martin Exp $	*/
 
 /*-
  * Copyright (c) 1999 The NetBSD Foundation, Inc.
@@ -30,16 +30,19 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: rasops32.c,v 1.39 2019/07/29 10:55:56 rin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: rasops32.c,v 1.39.2.1 2019/08/15 12:21:27 martin Exp $");
 
+#ifdef _KERNEL_OPT
 #include "opt_rasops.h"
+#endif
 
 #include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/time.h>
 
 #include <dev/wscons/wsdisplayvar.h>
 #include <dev/wscons/wsconsio.h>
+
+#define	_RASOPS_PRIVATE
+#define	RASOPS_DEPTH	32
 #include <dev/rasops/rasops.h>
 
 static void 	rasops32_putchar(void *, int, int, u_int, long);
@@ -49,15 +52,14 @@ static void	rasops32_putchar8(void *, in
 static void	rasops32_putchar12(void *, int, int, u_int, long);
 static void	rasops32_putchar16(void *, int, int, u_int, long);
 static void	rasops32_makestamp(struct rasops_info *, long);
-
-/*
- * 4x1 stamp for optimized character blitting
- */
-static uint32_t	stamp[64];
-static long	stamp_attr;
-static int	stamp_mutex;	/* XXX see note in readme */
 #endif
 
+#ifndef RASOPS_SMALL
+/* stamp for optimized character blitting */
+static uint32_t			stamp[64];
+static long			stamp_attr;
+static struct rasops_info	*stamp_ri;
+
 /*
  * offset = STAMP_SHIFT(fontbits, nibble #) & STAMP_MASK
  * destination uint32_t[0] = STAMP_READ(offset)
@@ -68,6 +70,7 @@ static int	stamp_mutex;	/* XXX see note 
 #define	STAMP_SHIFT(fb, n)	((n) ? (fb) : (fb) << 4)
 #define	STAMP_MASK		(0xf << 4)
 #define	STAMP_READ(o)		(*(uint32_t *)((uint8_t *)stamp + (o)))
+#endif
 
 /*
  * Initialize a 'rasops_info' descriptor for this depth.
@@ -103,13 +106,23 @@ rasops32_init(struct rasops_info *ri)
 #endif
 	default:
 		ri->ri_ops.putchar = rasops32_putchar;
-		break;
+		return;
 	}
+
+#ifndef RASOPS_SMALL
+	stamp_attr = -1;
+	stamp_ri = NULL;
+#endif
 }
 
-#define	RASOPS_DEPTH	32
-#include "rasops_putchar.h"
-#include "rasops_putchar_aa.h"
+/* rasops32_putchar */
+#undef	RASOPS_AA
+#include <dev/rasops/rasops_putchar.h>
+
+/* rasops32_putchar_aa */
+#define	RASOPS_AA
+#include <dev/rasops/rasops_putchar.h>
+#undef	RASOPS_AA
 
 #ifndef RASOPS_SMALL
 /*
@@ -121,9 +134,11 @@ rasops32_makestamp(struct rasops_info *r
 	uint32_t fg, bg;
 	int i;
 
-	fg = ri->ri_devcmap[((uint32_t)attr >> 24) & 0xf];
-	bg = ri->ri_devcmap[((uint32_t)attr >> 16) & 0xf];
 	stamp_attr = attr;
+	stamp_ri = ri;
+
+	bg = ATTR_BG(ri, attr);
+	fg = ATTR_FG(ri, attr);
 
 	for (i = 0; i < 64; i += 4) {
 		stamp[i + 0] = i & 32 ? fg : bg;
@@ -133,16 +148,19 @@ rasops32_makestamp(struct rasops_info *r
 	}
 }
 
+/*
+ * Width-optimized putchar functions
+ */
 #define	RASOPS_WIDTH	8
-#include "rasops_putchar_width.h"
+#include <dev/rasops/rasops_putchar_width.h>
 #undef	RASOPS_WIDTH
 
 #define	RASOPS_WIDTH	12
-#include "rasops_putchar_width.h"
+#include <dev/rasops/rasops_putchar_width.h>
 #undef	RASOPS_WIDTH
 
 #define	RASOPS_WIDTH	16
-#include "rasops_putchar_width.h"
+#include <dev/rasops/rasops_putchar_width.h>
 #undef	RASOPS_WIDTH
 
 #endif /* !RASOPS_SMALL */

Index: src/sys/dev/rasops/rasops4.c
diff -u src/sys/dev/rasops/rasops4.c:1.20 src/sys/dev/rasops/rasops4.c:1.20.2.1
--- src/sys/dev/rasops/rasops4.c:1.20	Mon Jul 29 03:01:09 2019
+++ src/sys/dev/rasops/rasops4.c	Thu Aug 15 12:21:27 2019
@@ -1,4 +1,4 @@
-/* 	$NetBSD: rasops4.c,v 1.20 2019/07/29 03:01:09 rin Exp $	*/
+/* 	$NetBSD: rasops4.c,v 1.20.2.1 2019/08/15 12:21:27 martin Exp $	*/
 
 /*-
  * Copyright (c) 1999 The NetBSD Foundation, Inc.
@@ -30,17 +30,21 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: rasops4.c,v 1.20 2019/07/29 03:01:09 rin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: rasops4.c,v 1.20.2.1 2019/08/15 12:21:27 martin Exp $");
 
+#ifdef _KERNEL_OPT
 #include "opt_rasops.h"
+#endif
 
 #include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/time.h>
+
 #include <machine/endian.h>
 
 #include <dev/wscons/wsdisplayvar.h>
 #include <dev/wscons/wsconsio.h>
+
+#define	_RASOPS_PRIVATE
+#define	RASOPS_DEPTH	4
 #include <dev/rasops/rasops.h>
 #include <dev/rasops/rasops_masks.h>
 
@@ -53,15 +57,14 @@ static void	rasops4_putchar8(void *, int
 static void	rasops4_putchar12(void *, int, int col, u_int, long);
 static void	rasops4_putchar16(void *, int, int col, u_int, long);
 static void	rasops4_makestamp(struct rasops_info *, long);
-
-/*
- * 4x1 stamp for optimized character blitting
- */
-static uint16_t	stamp[16];
-static long	stamp_attr;
-static int	stamp_mutex;	/* XXX see note in README */
 #endif
 
+#ifndef RASOPS_SMALL
+/* stamp for optimized character blitting */
+static uint16_t			stamp[16];
+static long			stamp_attr;
+static struct rasops_info	*stamp_ri;
+
 /*
  * offset = STAMP_SHIFT(fontbits, nibble #) & STAMP_MASK
  * destination = STAMP_READ(offset)
@@ -69,6 +72,7 @@ static int	stamp_mutex;	/* XXX see note 
 #define STAMP_SHIFT(fb, n)	((n) ? (fb) >> 4 : (fb))
 #define STAMP_MASK		0xf
 #define STAMP_READ(o)		stamp[o]
+#endif
 
 /*
  * Initialize rasops_info struct for this colordepth.
@@ -96,20 +100,14 @@ rasops4_init(struct rasops_info *ri)
 		break;
 #endif	/* !RASOPS_SMALL */
 	default:
-		panic("fontwidth not 8/12/16 or RASOPS_SMALL - fixme!");
 		ri->ri_ops.putchar = rasops4_putchar;
-		break;
+		return;
 	}
-}
-
-/*
- * Put a single character. This is the generic version.
- */
-static void
-rasops4_putchar(void *cookie, int row, int col, u_int uc, long attr)
-{
 
-	/* XXX punt */
+#ifndef RASOPS_SMALL
+	stamp_attr = -1;
+	stamp_ri = NULL;
+#endif
 }
 
 #ifndef RASOPS_SMALL
@@ -119,19 +117,22 @@ rasops4_putchar(void *cookie, int row, i
 static void
 rasops4_makestamp(struct rasops_info *ri, long attr)
 {
-	int i, fg, bg;
+	int i;
+	uint32_t bg, fg;
 
-	fg = ri->ri_devcmap[((uint32_t)attr >> 24) & 0xf] & 0xf;
-	bg = ri->ri_devcmap[((uint32_t)attr >> 16) & 0xf] & 0xf;
 	stamp_attr = attr;
+	stamp_ri = ri;
+
+	bg = ATTR_BG(ri, attr) & 0xf;
+	fg = ATTR_FG(ri, attr) & 0xf;
 
 	for (i = 0; i < 16; i++) {
-#if BYTE_ORDER == BIG_ENDIAN
-#define NEED_LITTLE_ENDIAN_STAMP RI_BSWAP
+#if BYTE_ORDER == LITTLE_ENDIAN
+		if ((ri->ri_flg & RI_BSWAP) == 0)
 #else
-#define NEED_LITTLE_ENDIAN_STAMP 0
+		if ((ri->ri_flg & RI_BSWAP) != 0)
 #endif
-		if ((ri->ri_flg & RI_BSWAP) == NEED_LITTLE_ENDIAN_STAMP) {
+		{
 			/* little endian */
 			stamp[i]  = (i & 1 ? fg : bg) << 12;
 			stamp[i] |= (i & 2 ? fg : bg) << 8;
@@ -147,26 +148,28 @@ rasops4_makestamp(struct rasops_info *ri
 	}
 }
 
-#define	RASOPS_DEPTH	4
-
+/*
+ * Width-optimized putchar functions
+ */
 #define	RASOPS_WIDTH	8
-#include "rasops_putchar_width.h"
+#include <dev/rasops/rasops_putchar_width.h>
 #undef	RASOPS_WIDTH
 
 #define	RASOPS_WIDTH	12
-#include "rasops_putchar_width.h"
+#include <dev/rasops/rasops_putchar_width.h>
 #undef	RASOPS_WIDTH
 
 #define	RASOPS_WIDTH	16
-#include "rasops_putchar_width.h"
+#include <dev/rasops/rasops_putchar_width.h>
 #undef	RASOPS_WIDTH
 
 #endif	/* !RASOPS_SMALL */
 
+/* rasops4_putchar */
+#undef	RASOPS_AA
+#include <dev/rasops/rasops1-4_putchar.h>
+
 /*
  * Grab routines common to depths where (bpp < 8)
  */
-#define NAME(ident)	rasops4_##ident
-#define PIXEL_SHIFT	3
-
 #include <dev/rasops/rasops_bitops.h>

Index: src/sys/dev/rasops/rasops8.c
diff -u src/sys/dev/rasops/rasops8.c:1.44 src/sys/dev/rasops/rasops8.c:1.44.2.1
--- src/sys/dev/rasops/rasops8.c:1.44	Mon Jul 29 10:55:56 2019
+++ src/sys/dev/rasops/rasops8.c	Thu Aug 15 12:21:27 2019
@@ -1,4 +1,4 @@
-/* 	$NetBSD: rasops8.c,v 1.44 2019/07/29 10:55:56 rin Exp $	*/
+/* 	$NetBSD: rasops8.c,v 1.44.2.1 2019/08/15 12:21:27 martin Exp $	*/
 
 /*-
  * Copyright (c) 1999 The NetBSD Foundation, Inc.
@@ -30,16 +30,19 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: rasops8.c,v 1.44 2019/07/29 10:55:56 rin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: rasops8.c,v 1.44.2.1 2019/08/15 12:21:27 martin Exp $");
 
+#ifdef _KERNEL_OPT
 #include "opt_rasops.h"
+#endif
 
 #include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/time.h>
 
 #include <dev/wscons/wsdisplayvar.h>
 #include <dev/wscons/wsconsio.h>
+
+#define	_RASOPS_PRIVATE
+#define	RASOPS_DEPTH	8
 #include <dev/rasops/rasops.h>
 
 static void 	rasops8_putchar(void *, int, int, u_int, long);
@@ -49,15 +52,14 @@ static void 	rasops8_putchar8(void *, in
 static void 	rasops8_putchar12(void *, int, int, u_int, long);
 static void 	rasops8_putchar16(void *, int, int, u_int, long);
 static void	rasops8_makestamp(struct rasops_info *ri, long);
-
-/*
- * 4x1 stamp for optimized character blitting
- */
-static uint32_t	stamp[16];
-static long	stamp_attr;
-static int	stamp_mutex;	/* XXX see note in README */
 #endif
 
+#ifndef RASOPS_SMALL
+/* stamp for optimized character blitting */
+static uint32_t			stamp[16];
+static long			stamp_attr;
+static struct rasops_info	*stamp_ri;
+
 /*
  * offset = STAMP_SHIFT(fontbits, nibble #) & STAMP_MASK
  * destination = STAMP_READ(offset)
@@ -65,6 +67,7 @@ static int	stamp_mutex;	/* XXX see note 
 #define	STAMP_SHIFT(fb, n)	((n) ? (fb) >> 2 : (fb) << 2)
 #define	STAMP_MASK		(0xf << 2)
 #define	STAMP_READ(o)		(*(uint32_t *)((uint8_t *)stamp + (o)))
+#endif
 
 /*
  * Initialize a 'rasops_info' descriptor for this depth.
@@ -101,35 +104,47 @@ rasops8_init(struct rasops_info *ri)
 #endif /* !RASOPS_SMALL */
 	default:
 		ri->ri_ops.putchar = rasops8_putchar;
-		break;
+		return;
 	}
+
+#ifndef RASOPS_SMALL
+	stamp_attr = -1;
+	stamp_ri = NULL;
+#endif
 }
 
-#define	RASOPS_DEPTH	8
-#include "rasops_putchar.h"
-#include "rasops_putchar_aa.h"
+/* rasops8_putchar */
+#undef	RASOPS_AA
+#include <dev/rasops/rasops_putchar.h>
+
+/* rasops8_putchar_aa */
+#define	RASOPS_AA
+#include <dev/rasops/rasops_putchar.h>
+#undef	RASOPS_AA
 
 #ifndef RASOPS_SMALL
 /*
- * Recompute the 4x1 blitting stamp.
+ * Recompute the blitting stamp.
  */
 static void
 rasops8_makestamp(struct rasops_info *ri, long attr)
 {
-	uint32_t fg, bg;
 	int i;
+	uint32_t bg, fg;
 
-	fg = ri->ri_devcmap[((uint32_t)attr >> 24) & 0xf] & 0xff;
-	bg = ri->ri_devcmap[((uint32_t)attr >> 16) & 0xf] & 0xff;
 	stamp_attr = attr;
+	stamp_ri = ri;
+
+	bg = ATTR_BG(ri, attr) & 0xff;
+	fg = ATTR_FG(ri, attr) & 0xff;
 
 	for (i = 0; i < 16; i++) {
-#if BYTE_ORDER == BIG_ENDIAN
-#define NEED_LITTLE_ENDIAN_STAMP RI_BSWAP
+#if BYTE_ORDER == LITTLE_ENDIAN
+		if ((ri->ri_flg & RI_BSWAP) == 0)
 #else
-#define NEED_LITTLE_ENDIAN_STAMP 0
+		if ((ri->ri_flg & RI_BSWAP) != 0)
 #endif
-		if ((ri->ri_flg & RI_BSWAP) == NEED_LITTLE_ENDIAN_STAMP) {
+		{
 			/* little endian */
 			stamp[i]  = (i & 8 ? fg : bg);
 			stamp[i] |= (i & 4 ? fg : bg) << 8;
@@ -145,16 +160,19 @@ rasops8_makestamp(struct rasops_info *ri
 	}
 }
 
+/*
+ * Width-optimized putchar functions
+ */
 #define	RASOPS_WIDTH	8
-#include "rasops_putchar_width.h"
+#include <dev/rasops/rasops_putchar_width.h>
 #undef	RASOPS_WIDTH
 
 #define	RASOPS_WIDTH	12
-#include "rasops_putchar_width.h"
+#include <dev/rasops/rasops_putchar_width.h>
 #undef	RASOPS_WIDTH
 
 #define	RASOPS_WIDTH	16
-#include "rasops_putchar_width.h"
+#include <dev/rasops/rasops_putchar_width.h>
 #undef	RASOPS_WIDTH
 
-#endif
+#endif /* !RASOPS_SMALL */

Index: src/sys/dev/rasops/rasops_bitops.h
diff -u src/sys/dev/rasops/rasops_bitops.h:1.18 src/sys/dev/rasops/rasops_bitops.h:1.18.2.1
--- src/sys/dev/rasops/rasops_bitops.h:1.18	Tue Jul 30 15:29:40 2019
+++ src/sys/dev/rasops/rasops_bitops.h	Thu Aug 15 12:21:27 2019
@@ -1,4 +1,4 @@
-/* 	$NetBSD: rasops_bitops.h,v 1.18 2019/07/30 15:29:40 rin Exp $	*/
+/* 	$NetBSD: rasops_bitops.h,v 1.18.2.1 2019/08/15 12:21:27 martin Exp $	*/
 
 /*-
  * Copyright (c) 1999 The NetBSD Foundation, Inc.
@@ -32,21 +32,33 @@
 #ifndef _RASOPS_BITOPS_H_
 #define _RASOPS_BITOPS_H_ 1
 
+#if   RASOPS_DEPTH == 1
+#define	PIXEL_SHIFT	0
+#elif RASOPS_DEPTH == 2
+#define	PIXEL_SHIFT	1
+#elif RASOPS_DEPTH == 4
+#define	PIXEL_SHIFT	2
+#else
+#error "Depth not supported"
+#endif
+
+#define	NAME(name)		NAME1(RASOPS_DEPTH, name)
+#define	NAME1(depth, name)	NAME2(depth, name)
+#define	NAME2(depth, name)	rasops ## depth ## _ ## name
+
 /*
  * Erase columns.
  */
 static void
 NAME(erasecols)(void *cookie, int row, int col, int num, long attr)
 {
-	int lclr, rclr, clr;
-	struct rasops_info *ri;
-	uint32_t *dp, *rp, *hp, tmp, lmask, rmask;
+	struct rasops_info *ri = (struct rasops_info *)cookie;
 	int height, cnt;
+	uint32_t bg, lbg, rbg, lmask, rmask, tmp;
+	uint32_t *dp, *rp, *hp;
 
 	hp = NULL;	/* XXX GCC */
 
-	ri = (struct rasops_info *)cookie;
-
 #ifdef RASOPS_CLIPPING
 	if ((unsigned)row >= (unsigned)ri->ri_rows)
 		return;
@@ -56,66 +68,73 @@ NAME(erasecols)(void *cookie, int row, i
 		col = 0;
 	}
 
-	if ((col + num) > ri->ri_cols)
+	if (col + num > ri->ri_cols)
 		num = ri->ri_cols - col;
 
 	if (num <= 0)
 		return;
 #endif
+
+	height = ri->ri_font->fontheight;
 	col *= ri->ri_font->fontwidth << PIXEL_SHIFT;
 	num *= ri->ri_font->fontwidth << PIXEL_SHIFT;
-	height = ri->ri_font->fontheight;
-	clr = ri->ri_devcmap[((uint32_t)attr >> 16) & 0xf];
+
 	rp = (uint32_t *)(ri->ri_bits + row*ri->ri_yscale + ((col >> 3) & ~3));
 	if (ri->ri_hwbits)
 		hp = (uint32_t *)(ri->ri_hwbits + row*ri->ri_yscale +
 		    ((col >> 3) & ~3));
-	if ((col & 31) + num <= 32) {
-		lmask = ~rasops_pmask[col & 31][num];
-		lclr = clr & ~lmask;
+
+	col &= 31;
+
+	bg = ATTR_BG(ri, attr);
+
+	if (col + num <= 32) {
+		lmask = ~rasops_pmask[col][num & 31];
+		bg &= ~lmask;
 
 		while (height--) {
-			dp = rp;
-			DELTA(rp, ri->ri_stride, uint32_t *);
+			tmp = (*rp & lmask) | bg;
+			*rp = tmp;
 
-			tmp = (*dp & lmask) | lclr;
-			*dp = tmp;
 			if (ri->ri_hwbits) {
 				*hp = tmp;
 				DELTA(hp, ri->ri_stride, uint32_t *);
 			}
+
+			DELTA(rp, ri->ri_stride, uint32_t *);
 		}
 	} else {
-		lmask = rasops_rmask[col & 31];
+		lmask = rasops_rmask[col];
 		rmask = rasops_lmask[(col + num) & 31];
 
 		if (lmask)
-			num = (num - (32 - (col & 31))) >> 5;
+			num = (num - (32 - col)) >> 5;
 		else
 			num = num >> 5;
 
-		lclr = clr & ~lmask;
-		rclr = clr & ~rmask;
+		lbg = bg & ~lmask;
+		rbg = bg & ~rmask;
 
 		while (height--) {
 			dp = rp;
 
 			if (lmask) {
-				*dp = (*dp & lmask) | lclr;
+				*dp = (*dp & lmask) | lbg;
 				dp++;
 			}
 
 			for (cnt = num; cnt > 0; cnt--)
-				*dp++ = clr;
+				*dp++ = bg;
 
 			if (rmask)
-				*dp = (*dp & rmask) | rclr;
+				*dp = (*dp & rmask) | rbg;
 
 			if (ri->ri_hwbits) {
 				memcpy(hp, rp, ((lmask != 0) + num +
 				    (rmask != 0)) << 2);
 				DELTA(hp, ri->ri_stride, uint32_t *);
 			}
+
 			DELTA(rp, ri->ri_stride, uint32_t *);
 		}
 	}
@@ -127,61 +146,68 @@ NAME(erasecols)(void *cookie, int row, i
 static void
 NAME(do_cursor)(struct rasops_info *ri)
 {
-	int height, row, col, num;
-	uint32_t *dp, *rp, *hrp, *hp, tmp, lmask, rmask;
+	int row, col, height, width, cnt;
+	uint32_t lmask, rmask, tmp;
+	uint32_t *dp, *rp, *hp;
 
-	hrp = hp = NULL;	/* XXX GCC */
+	hp = NULL;	/* XXX GCC */
 
 	row = ri->ri_crow;
 	col = ri->ri_ccol * ri->ri_font->fontwidth << PIXEL_SHIFT;
+
 	height = ri->ri_font->fontheight;
-	num = ri->ri_font->fontwidth << PIXEL_SHIFT;
+	width = ri->ri_font->fontwidth << PIXEL_SHIFT;
+
 	rp = (uint32_t *)(ri->ri_bits + row * ri->ri_yscale +
 	    ((col >> 3) & ~3));
 	if (ri->ri_hwbits)
-		hrp = (uint32_t *)(ri->ri_hwbits + row * ri->ri_yscale +
+		hp = (uint32_t *)(ri->ri_hwbits + row * ri->ri_yscale +
 		    ((col >> 3) & ~3));
 
-	if ((col & 31) + num <= 32) {
-		lmask = rasops_pmask[col & 31][num];
+	col &= 31;
+
+	if (col + width <= 32) {
+		lmask = rasops_pmask[col][width & 31];
 
 		while (height--) {
 			tmp = *rp ^ lmask;
 			*rp = tmp;
 			if (ri->ri_hwbits) {
-				*hrp = tmp;
-				DELTA(hrp, ri->ri_stride, uint32_t *);
+				*hp = tmp;
+				DELTA(hp, ri->ri_stride, uint32_t *);
 			}
 			DELTA(rp, ri->ri_stride, uint32_t *);
 		}
 	} else {
-		lmask = ~rasops_rmask[col & 31];
-		rmask = ~rasops_lmask[(col + num) & 31];
+		lmask = ~rasops_rmask[col];
+		rmask = ~rasops_lmask[(col + width) & 31];
+
+		if (lmask != -1)
+			width = (width - (32 - col)) >> 5;
+		else
+			width = width >> 5;
 
 		while (height--) {
 			dp = rp;
-			DELTA(rp, ri->ri_stride, uint32_t *);
-			if (ri->ri_hwbits) {
-				hp = hrp;
-				DELTA(hrp, ri->ri_stride, uint32_t *);
-			}
 
-			if (lmask != -1) {
-				tmp = *dp ^ lmask;
-				*dp = tmp;
+			if (lmask != -1)
+				*dp++ ^= lmask;
+
+			for (cnt = width; cnt; cnt--) {
+				*dp = ~*dp;
 				dp++;
-				if (ri->ri_hwbits) {
-					*hp = tmp;
-					hp++;
-				}
 			}
 
-			if (rmask != -1) {
-				tmp = *dp ^ rmask;
-				*dp = tmp;
-				if (ri->ri_hwbits)
-					*hp = tmp;
+			if (rmask != -1)
+				*dp ^= rmask;
+
+			if (ri->ri_hwbits) {
+				memcpy(hp, rp, ((lmask != -1) + width +
+				    (rmask != -1)) << 2);
+				DELTA(hp, ri->ri_stride, uint32_t *);
 			}
+
+			DELTA(rp, ri->ri_stride, uint32_t *);
 		}
 	}
 }
@@ -193,16 +219,17 @@ static void
 NAME(copycols)(void *cookie, int row, int src, int dst, int num)
 {
 	struct rasops_info *ri = (struct rasops_info *)cookie;
-	int height, lnum, rnum, sb, db, cnt, full;
-	uint32_t tmp, lmask, rmask;
-	uint32_t *sp, *dp, *srp, *drp, *dhp, *hp;
+	int height, width, lnum, rnum, sb, db, full, cnt, sboff;
+	uint32_t lmask, rmask, tmp;
+	uint32_t *sp, *dp, *srp, *drp, *hp;
+	bool sbover;
 
-	dhp = hp = NULL;	/* XXX GCC */
+	hp = NULL;	/* XXX GCC */
 
-#ifdef RASOPS_CLIPPING
-	if (dst == src)
+	if (__predict_false(dst == src))
 		return;
 
+#ifdef RASOPS_CLIPPING
 	/* Catches < 0 case too */
 	if ((unsigned)row >= (unsigned)ri->ri_rows)
 		return;
@@ -227,12 +254,16 @@ NAME(copycols)(void *cookie, int row, in
 		return;
 #endif
 
-	cnt = ri->ri_font->fontwidth << PIXEL_SHIFT;
-	src *= cnt;
-	dst *= cnt;
-	num *= cnt;
-	row *= ri->ri_yscale;
 	height = ri->ri_font->fontheight;
+	width = ri->ri_font->fontwidth << PIXEL_SHIFT;
+
+	row *= ri->ri_yscale;
+
+	src *= width;
+	dst *= width;
+	num *= width;
+
+	sb = src & 31;
 	db = dst & 31;
 
 	if (db + num <= 32) {
@@ -240,16 +271,15 @@ NAME(copycols)(void *cookie, int row, in
 		srp = (uint32_t *)(ri->ri_bits + row + ((src >> 3) & ~3));
 		drp = (uint32_t *)(ri->ri_bits + row + ((dst >> 3) & ~3));
 		if (ri->ri_hwbits)
-			dhp = (uint32_t *)(ri->ri_hwbits + row +
+			hp = (uint32_t *)(ri->ri_hwbits + row +
 			    ((dst >> 3) & ~3));
-		sb = src & 31;
 
 		while (height--) {
 			GETBITS(srp, sb, num, tmp);
 			PUTBITS(tmp, db, num, drp);
 			if (ri->ri_hwbits) {
-				PUTBITS(tmp, db, num, dhp);
-				DELTA(dhp, ri->ri_stride, uint32_t *);
+				*hp = *drp;
+				DELTA(hp, ri->ri_stride, uint32_t *);
 			}	
 			DELTA(srp, ri->ri_stride, uint32_t *);
 			DELTA(drp, ri->ri_stride, uint32_t *);
@@ -263,27 +293,25 @@ NAME(copycols)(void *cookie, int row, in
 	lnum = (32 - db) & 31;
 	rnum = (dst + num) & 31;
 
-	if (lmask)
-		full = (num - (32 - (dst & 31))) >> 5;
+	if (lmask != 0)
+		full = (num - lnum) >> 5;
 	else
 		full = num >> 5;
 
 	if (src < dst && src + num > dst) {
 		/* Copy right-to-left */
-		bool sbover;
-		int sboff;
-
 		srp = (uint32_t *)(ri->ri_bits + row +
 		    (((src + num) >> 3) & ~3));
 		drp = (uint32_t *)(ri->ri_bits + row +
 		    (((dst + num) >> 3) & ~3));
-		if (ri->ri_hwbits)
-			dhp = (uint32_t *)(ri->ri_hwbits + row +
+		if (ri->ri_hwbits) {
+			hp = (uint32_t *)(ri->ri_hwbits + row +
 			    (((dst + num) >> 3) & ~3));
+			hp -= (lmask != 0) + full;
+		}
 
-		sb = src & 31;
-		sbover = (sb + lnum) >= 32;
 		sboff = (src + num) & 31;
+		sbover = sb + lnum >= 32;
 		if ((sboff -= rnum) < 0) {
 			srp--;
 			sboff += 32;
@@ -292,10 +320,8 @@ NAME(copycols)(void *cookie, int row, in
 		while (height--) {
 			sp = srp;
 			dp = drp;
-			DELTA(srp, ri->ri_stride, uint32_t *);
-			DELTA(drp, ri->ri_stride, uint32_t *);
 
-			if (rnum) {
+			if (rmask != 0) {
 				GETBITS(sp, sboff, rnum, tmp);
 				PUTBITS(tmp, 0, rnum, dp);
 			}
@@ -308,7 +334,7 @@ NAME(copycols)(void *cookie, int row, in
 				*dp = tmp;
 			}
 
-			if (lmask) {
+			if (lmask != 0) {
 				if (sbover)
 					--sp;
 				--dp;
@@ -317,53 +343,54 @@ NAME(copycols)(void *cookie, int row, in
  			}
 
 			if (ri->ri_hwbits) {
-				hp = dhp;
-				hp -= full + (lmask != 0);
-				memcpy(hp, dp, ((rmask != 0) + cnt +
-				    (lmask != 0)) << 2);
-				DELTA(dhp, ri->ri_stride, uint32_t *);
+				memcpy(hp, dp, ((lmask != 0) + full +
+				    (rmask != 0)) << 2);
+				DELTA(hp, ri->ri_stride, uint32_t *);
 			}
+
+			DELTA(srp, ri->ri_stride, uint32_t *);
+			DELTA(drp, ri->ri_stride, uint32_t *);
  		}
 	} else {
 		/* Copy left-to-right */
 		srp = (uint32_t *)(ri->ri_bits + row + ((src >> 3) & ~3));
 		drp = (uint32_t *)(ri->ri_bits + row + ((dst >> 3) & ~3));
 		if (ri->ri_hwbits)
-			dhp = (uint32_t *)(ri->ri_hwbits + row +
+			hp = (uint32_t *)(ri->ri_hwbits + row +
 			    ((dst >> 3) & ~3));
-		db = dst & 31;
 
 		while (height--) {
-			sb = src & 31;
 			sp = srp;
 			dp = drp;
 
-			if (lmask) {
-				GETBITS(sp, sb, lnum, tmp);
+			sboff = sb;
+
+			if (lmask != 0) {
+				GETBITS(sp, sboff, lnum, tmp);
 				PUTBITS(tmp, db, lnum, dp);
 				dp++;
 
-				if (sb += lnum > 31) {
+				if ((sboff += lnum) > 31) {
 					sp++;
-					sb -= 32;
+					sboff -= 32;
 				}
 			}
 
 			/* Now aligned to 32-bits wrt dp */
 			for (cnt = full; cnt; cnt--, sp++) {
-				GETBITS(sp, sb, 32, tmp);
+				GETBITS(sp, sboff, 32, tmp);
 				*dp++ = tmp;
 			}
 
-			if (rmask) {
-				GETBITS(sp, sb, rnum, tmp);
+			if (rmask != 0) {
+				GETBITS(sp, sboff, rnum, tmp);
 				PUTBITS(tmp, 0, rnum, dp);
  			}
 
 			if (ri->ri_hwbits) {
-				memcpy(dhp, drp, ((lmask != 0) + full +
+				memcpy(hp, drp, ((lmask != 0) + full +
 				    (rmask != 0)) << 2);
-				DELTA(dhp, ri->ri_stride, uint32_t *);
+				DELTA(hp, ri->ri_stride, uint32_t *);
 			}
 
 			DELTA(srp, ri->ri_stride, uint32_t *);
@@ -372,4 +399,10 @@ NAME(copycols)(void *cookie, int row, in
  	}
 }
 
+#undef	PIXEL_SHIFT
+
+#undef	NAME
+#undef	NAME1
+#undef	NAME2
+
 #endif /* _RASOPS_BITOPS_H_ */

Index: src/sys/dev/rasops/rasops_masks.c
diff -u src/sys/dev/rasops/rasops_masks.c:1.9 src/sys/dev/rasops/rasops_masks.c:1.9.36.1
--- src/sys/dev/rasops/rasops_masks.c:1.9	Mon Dec  2 14:05:51 2013
+++ src/sys/dev/rasops/rasops_masks.c	Thu Aug 15 12:21:27 2019
@@ -1,4 +1,4 @@
-/* 	$NetBSD: rasops_masks.c,v 1.9 2013/12/02 14:05:51 tsutsui Exp $	*/
+/* 	$NetBSD: rasops_masks.c,v 1.9.36.1 2019/08/15 12:21:27 martin Exp $	*/
 
 /*-
  * Copyright (c) 1999 The NetBSD Foundation, Inc.
@@ -30,12 +30,12 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: rasops_masks.c,v 1.9 2013/12/02 14:05:51 tsutsui Exp $");
+__KERNEL_RCSID(0, "$NetBSD: rasops_masks.c,v 1.9.36.1 2019/08/15 12:21:27 martin Exp $");
 
-#include "rasops_masks.h"
+#include <dev/rasops/rasops_masks.h>
 
 /* `ragged edge' bitmasks */
-const uint32_t rasops_lmask[32+1] = {
+const uint32_t rasops_lmask[32 + 1] = {
 	MBE(0x00000000), MBE(0x7fffffff), MBE(0x3fffffff), MBE(0x1fffffff),
 	MBE(0x0fffffff), MBE(0x07ffffff), MBE(0x03ffffff), MBE(0x01ffffff),
 	MBE(0x00ffffff), MBE(0x007fffff), MBE(0x003fffff), MBE(0x001fffff),
@@ -47,7 +47,7 @@ const uint32_t rasops_lmask[32+1] = {
 	MBE(0x00000000)
 };
 
-const uint32_t rasops_rmask[32+1] = {
+const uint32_t rasops_rmask[32 + 1] = {
 	MBE(0x00000000), MBE(0x80000000), MBE(0xc0000000), MBE(0xe0000000),
 	MBE(0xf0000000), MBE(0xf8000000), MBE(0xfc000000), MBE(0xfe000000),
 	MBE(0xff000000), MBE(0xff800000), MBE(0xffc00000), MBE(0xffe00000),

Index: src/sys/dev/rasops/rasops_masks.h
diff -u src/sys/dev/rasops/rasops_masks.h:1.8 src/sys/dev/rasops/rasops_masks.h:1.8.36.1
--- src/sys/dev/rasops/rasops_masks.h:1.8	Mon Dec  2 14:05:51 2013
+++ src/sys/dev/rasops/rasops_masks.h	Thu Aug 15 12:21:27 2019
@@ -1,4 +1,4 @@
-/* 	$NetBSD: rasops_masks.h,v 1.8 2013/12/02 14:05:51 tsutsui Exp $	*/
+/* 	$NetBSD: rasops_masks.h,v 1.8.36.1 2019/08/15 12:21:27 martin Exp $	*/
 
 /*-
  * Copyright (c) 1999 The NetBSD Foundation, Inc.
@@ -33,6 +33,7 @@
 #define _RASOPS_MASKS_H_ 1
 
 #include <sys/types.h>
+
 #include <machine/endian.h>
 
 /*
@@ -71,25 +72,24 @@
 	dw = MBL(*(sp), (x));						\
 	if (((x) + (w)) > 32)						\
 		dw |= (MBR((sp)[1], 32 - (x))); 			\
-} while(0);
+} while (0 /* CONSTCOND */)
 
 /* Put a number of bits ( <= 32 ) from sw to *dp */
 #define PUTBITS(sw, x, w, dp) do {					\
 	int n = (x) + (w) - 32;						\
-									\
 	if (n <= 0) {							\
-		n = rasops_pmask[x & 31][w & 31];			\
-		*(dp) = (*(dp) & ~n) | (MBR(sw, x) & n);		\
+		uint32_t mask = rasops_pmask[(x) & 31][(w) & 31];	\
+		*(dp) = (*(dp) & ~mask) | (MBR(sw, x) & mask);		\
 	} else {							\
-		*(dp) = (*(dp) & rasops_rmask[x]) | (MBR((sw), x));	\
+		*(dp) = (*(dp) & rasops_rmask[x]) | (MBR(sw, x));	\
 		(dp)[1] = ((dp)[1] & rasops_rmask[n]) |			\
 			(MBL(sw, 32-(x)) & rasops_lmask[n]);		\
 	}								\
-} while(0);
+} while (0 /* CONSTCOND */)
 
 /* rasops_masks.c */
-extern const uint32_t	rasops_lmask[32+1];
-extern const uint32_t	rasops_rmask[32+1];
+extern const uint32_t	rasops_lmask[32 + 1];
+extern const uint32_t	rasops_rmask[32 + 1];
 extern const uint32_t	rasops_pmask[32][32];
 
 #endif /* _RASOPS_MASKS_H_ */

Index: src/sys/dev/rasops/rasops_putchar.h
diff -u src/sys/dev/rasops/rasops_putchar.h:1.5 src/sys/dev/rasops/rasops_putchar.h:1.5.2.1
--- src/sys/dev/rasops/rasops_putchar.h:1.5	Tue Jul 30 15:29:40 2019
+++ src/sys/dev/rasops/rasops_putchar.h	Thu Aug 15 12:21:27 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: rasops_putchar.h,v 1.5 2019/07/30 15:29:40 rin Exp $ */
+/* $NetBSD: rasops_putchar.h,v 1.5.2.1 2019/08/15 12:21:27 martin Exp $ */
 
 /* NetBSD: rasops8.c,v 1.41 2019/07/25 03:02:44 rin Exp  */
 /*-
@@ -35,9 +35,6 @@
 #error "Depth not supported"
 #endif
 
-#define PUTCHAR(depth)	PUTCHAR1(depth)
-#define PUTCHAR1(depth)	rasops ## depth ## _putchar
-
 #if   RASOPS_DEPTH == 8
 #define	COLOR_TYPE		uint8_t
 #elif RASOPS_DEPTH ==  15
@@ -47,41 +44,69 @@
 #endif
 
 #if RASOPS_DEPTH != 24
-#define	PIXEL_BYTES		sizeof(COLOR_TYPE)
-#define	SET_PIXEL(p, index)						\
-	do {								\
-		*(COLOR_TYPE *)(p) = clr[index];			\
-		(p) += sizeof(COLOR_TYPE);				\
-	} while (0 /* CONSTCOND */)
+#define	PIXEL_TYPE		COLOR_TYPE
+#define	PIXEL_BYTES		sizeof(PIXEL_TYPE)
+#define	SET_COLOR(p, index)	*(p)++ = clr[index]
+#define	SET_RGB(p, r, g, b)						\
+	*(p)++ = (((r) >> (8 - ri->ri_rnum)) << ri->ri_rpos) |		\
+		 (((g) >> (8 - ri->ri_gnum)) << ri->ri_gpos) |		\
+		 (((b) >> (8 - ri->ri_bnum)) << ri->ri_bpos)
 #endif
 
 #if RASOPS_DEPTH == 24
+#define	PIXEL_TYPE		uint8_t
 #define	PIXEL_BYTES		3
-#define	SET_PIXEL(p, index)						\
+#define	SET_COLOR(p, index)						\
 	do {								\
 		COLOR_TYPE c = clr[index];				\
 		*(p)++ = c >> 16;					\
 		*(p)++ = c >> 8;					\
 		*(p)++ = c;						\
 	} while (0 /* CONSTCOND */)
+#define	SET_RGB(p, r, g, b)						\
+	do {								\
+		(p)[R_OFF] = (r);					\
+		(p)[G_OFF] = (g);					\
+		(p)[B_OFF] = (b);					\
+		(p) += 3;						\
+	} while (0 /* CONSTCOND */)
+#endif
+
+#define	AV(p, w)	(((w) * (p)[1] + (0xff - (w)) * (p)[0]) >> 8)
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+#define	R_OFF	(ri->ri_rpos / 8)
+#define	G_OFF	(ri->ri_gpos / 8)
+#define	B_OFF	(ri->ri_bpos / 8)
+#else /* BIG_ENDIAN XXX not tested */
+#define	R_OFF	(2 - ri->ri_rpos / 8)
+#define	G_OFF	(2 - ri->ri_gpos / 8)
+#define	B_OFF	(2 - ri->ri_bpos / 8)
+#endif
+
+#define NAME(depth)	NAME1(depth)
+#ifndef RASOPS_AA
+#define NAME1(depth)	rasops ## depth ## _putchar
+#else
+#define NAME1(depth)	rasops ## depth ## _putchar_aa
 #endif
 
 /*
  * Put a single character.
  */
 static void
-PUTCHAR(RASOPS_DEPTH)(void *cookie, int row, int col, u_int uc, long attr)
+NAME(RASOPS_DEPTH)(void *cookie, int row, int col, u_int uc, long attr)
 {
 	struct rasops_info *ri = (struct rasops_info *)cookie;
 	struct wsdisplay_font *font = PICK_FONT(ri, uc);
-	int width, height, cnt, fs;
-	uint32_t fb;
-	uint8_t *dp, *rp, *hp, *fr;
+	int height, width, cnt;
+	uint8_t *fr;
 	COLOR_TYPE clr[2];
+	PIXEL_TYPE *dp, *rp, *hp;
 
 	hp = NULL;	/* XXX GCC */
 
-	if (!CHAR_IN_FONT(uc, font))
+	if (__predict_false(!CHAR_IN_FONT(uc, font)))
 		return;
 
 #ifdef RASOPS_CLIPPING
@@ -93,66 +118,117 @@ PUTCHAR(RASOPS_DEPTH)(void *cookie, int 
 		return;
 #endif
 
-	rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
-	if (ri->ri_hwbits)
-		hp = ri->ri_hwbits + row * ri->ri_yscale + col * ri->ri_xscale;
-
 	height = font->fontheight;
 	width = font->fontwidth;
 
-	clr[0] = (COLOR_TYPE)ri->ri_devcmap[((uint32_t)attr >> 16) & 0xf];
-	clr[1] = (COLOR_TYPE)ri->ri_devcmap[((uint32_t)attr >> 24) & 0xf];
+	rp = (PIXEL_TYPE *)(ri->ri_bits + FBOFFSET(ri, row, col));
+	if (ri->ri_hwbits)
+		hp = (PIXEL_TYPE *)(ri->ri_hwbits + FBOFFSET(ri, row, col));
+
+	clr[0] = (COLOR_TYPE)ATTR_BG(ri, attr);
+	clr[1] = (COLOR_TYPE)ATTR_FG(ri, attr);
 
 	if (uc == ' ') {
 		while (height--) {
 			dp = rp;
 			for (cnt = width; cnt; cnt--)
-				SET_PIXEL(dp, 0);
+				SET_COLOR(dp, 0);
 			if (ri->ri_hwbits) {
 				uint16_t bytes = width * PIXEL_BYTES;
 					/* XXX GCC */
 				memcpy(hp, rp, bytes);
-				hp += ri->ri_stride;
+				DELTA(hp, ri->ri_stride, PIXEL_TYPE *);
 			}
-			rp += ri->ri_stride;
+			DELTA(rp, ri->ri_stride, PIXEL_TYPE *);
 		}
 	} else {
 		fr = FONT_GLYPH(uc, font, ri);
-		fs = font->stride;
+
+#ifdef RASOPS_AA
+		int off[2];
+		uint8_t r[2], g[2], b[2];
+
+		/*
+	 	 * This is independent to positions/lengths of RGB in pixel.
+	 	 */
+		off[0] = (((uint32_t)attr >> 16) & 0xf) * 3;
+		off[1] = (((uint32_t)attr >> 24) & 0xf) * 3;
+
+		r[0] = rasops_cmap[off[0]];
+		r[1] = rasops_cmap[off[1]];
+		g[0] = rasops_cmap[off[0] + 1];
+		g[1] = rasops_cmap[off[1] + 1];
+		b[0] = rasops_cmap[off[0] + 2];
+		b[1] = rasops_cmap[off[1] + 2];
+#endif
 
 		while (height--) {
 			dp = rp;
-			fb = be32uatoh(fr);
-			fr += fs;
+
+#ifndef RASOPS_AA
+			uint32_t fb = rasops_be32uatoh(fr);
+			fr += ri->ri_font->stride;
+
 			for (cnt = width; cnt; cnt--) {
-				SET_PIXEL(dp, (fb >> 31) & 1);
+				SET_COLOR(dp, (fb >> 31) & 1);
 				fb <<= 1;
 			}
+#else /* RASOPS_AA */
+			for (cnt = width; cnt; cnt--) {
+				int w = *fr++;
+				if (w == 0xff)
+					SET_COLOR(dp, 1);
+				else if (w == 0)
+					SET_COLOR(dp, 0);
+				else
+					SET_RGB(dp,
+					    AV(r, w), AV(g, w), AV(b, w));
+			}
+#endif
 			if (ri->ri_hwbits) {
 				uint16_t bytes = width * PIXEL_BYTES;
 					/* XXX GCC */
 				memcpy(hp, rp, bytes);
-				hp += ri->ri_stride;
+				DELTA(hp, ri->ri_stride, PIXEL_TYPE *);
 			}
-			rp += ri->ri_stride;
+			DELTA(rp, ri->ri_stride, PIXEL_TYPE *);
 		}
 	}
 
 	/* Do underline */
 	if ((attr & WSATTR_UNDERLINE) != 0) {
-		rp -= (ri->ri_stride << 1);
-		dp = rp;
-		while (width--)
-			SET_PIXEL(dp, 1);
-		if (ri->ri_hwbits) {
-			hp -= (ri->ri_stride << 1);
-			uint16_t bytes = width * PIXEL_BYTES; /* XXX GCC */
-			memcpy(hp, rp, bytes);
+		DELTA(rp, - ri->ri_stride * ri->ri_ul.off, PIXEL_TYPE *);
+		if (ri->ri_hwbits)
+			DELTA(hp, - ri->ri_stride * ri->ri_ul.off,
+			    PIXEL_TYPE *);
+
+		for (height = ri->ri_ul.height; height; height--) {
+			DELTA(rp, - ri->ri_stride, PIXEL_TYPE *);
+			dp = rp;
+			for (cnt = width; cnt; cnt--)
+				SET_COLOR(dp, 1);
+			if (ri->ri_hwbits) {
+				DELTA(hp, - ri->ri_stride, PIXEL_TYPE *);
+				uint16_t bytes = width * PIXEL_BYTES;
+					/* XXX GCC */
+				memcpy(hp, rp, bytes);
+			}
 		}
 	}
 }
 
-#undef	PUTCHAR
 #undef	COLOR_TYPE
+
+#undef	PIXEL_TYPE
 #undef	PIXEL_BYTES
-#undef	SET_PIXEL
+#undef	SET_COLOR
+#undef	SET_RGB
+
+#undef	AV
+
+#undef	R_OFF
+#undef	G_OFF
+#undef	B_OFF
+
+#undef	NAME
+#undef	NAME1

Index: src/sys/dev/rasops/rasops_putchar_width.h
diff -u src/sys/dev/rasops/rasops_putchar_width.h:1.9 src/sys/dev/rasops/rasops_putchar_width.h:1.9.2.1
--- src/sys/dev/rasops/rasops_putchar_width.h:1.9	Tue Jul 30 15:29:40 2019
+++ src/sys/dev/rasops/rasops_putchar_width.h	Thu Aug 15 12:21:27 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: rasops_putchar_width.h,v 1.9 2019/07/30 15:29:40 rin Exp $ */
+/* $NetBSD: rasops_putchar_width.h,v 1.9.2.1 2019/08/15 12:21:27 martin Exp $ */
 
 /* NetBSD: rasops8.c,v 1.41 2019/07/25 03:02:44 rin Exp  */
 /*-
@@ -39,15 +39,6 @@
 #error "Width not supported"
 #endif
 
-#define	PUTCHAR_WIDTH1(depth, width)	rasops ## depth ## _putchar ## width
-#define	PUTCHAR_WIDTH(depth, width)	PUTCHAR_WIDTH1(depth, width)
-
-#define	PUTCHAR1(depth)			rasops ## depth ## _putchar
-#define	PUTCHAR(depth)			PUTCHAR1(depth)
-
-#define	MAKESTAMP1(depth)		rasops ## depth ## _makestamp
-#define	MAKESTAMP(depth)		MAKESTAMP1(depth)
-
 #if   RASOPS_DEPTH == 2
 #define	STAMP_TYPE	uint8_t
 #elif RASOPS_DEPTH == 4
@@ -172,6 +163,8 @@
 	} while (0 /* CONSTCOND */)
 #endif
 
+/* ################################################################### */
+
 #if   RASOPS_WIDTH == 8
 #define	SUBST_GLYPH				\
 	do {					\
@@ -195,21 +188,37 @@
 	} while (0 /* CONSTCOND */)
 #endif
 
+/* ################################################################### */
+
+#define	NAME(depth, width)	NAME1(depth, width)
+#define	NAME1(depth, width)	rasops ## depth ## _putchar ## width
+
+#define	PUTCHAR(depth)		PUTCHAR1(depth)
+#define	PUTCHAR1(depth)		rasops ## depth ## _putchar
+
+#define	MAKESTAMP(depth)	MAKESTAMP1(depth)
+#define	MAKESTAMP1(depth)	rasops ## depth ## _makestamp
+
 /*
  * Width-optimized putchar function.
  */
 static void
-PUTCHAR_WIDTH(RASOPS_DEPTH, RASOPS_WIDTH)(void *cookie, int row, int col,
-    u_int uc, long attr)
+NAME(RASOPS_DEPTH, RASOPS_WIDTH)(void *cookie, int row, int col, u_int uc,
+    long attr)
 {
 	struct rasops_info *ri = (struct rasops_info *)cookie;
 	struct wsdisplay_font *font = PICK_FONT(ri, uc);
-	int height, fs;
-	STAMP_TYPE *rp, *hp;
+	int height;
 	uint8_t *fr;
+	bool do_ul;
+	STAMP_TYPE *rp, *hp;
 
 	hp = NULL; /* XXX GCC */
 
+	/* check if character fits into font limits */
+	if (__predict_false(!CHAR_IN_FONT(uc, font)))
+		return;
+
 #ifdef RASOPS_CLIPPING
 	/* Catches 'row < 0' case too */
 	if ((unsigned)row >= (unsigned)ri->ri_rows)
@@ -219,29 +228,23 @@ PUTCHAR_WIDTH(RASOPS_DEPTH, RASOPS_WIDTH
 		return;
 #endif
 
-	/* check if character fits into font limits */
-	if (!CHAR_IN_FONT(uc, font))
-		return;
-
-	/* Can't risk remaking the stamp if it's already in use */
-	if (stamp_mutex++) {
-		stamp_mutex--;
-		PUTCHAR(RASOPS_DEPTH)(cookie, row, col, uc, attr);
-		return;
-	}
+	/*
+	 * We don't care attributions other than back/foreground
+	 * colors when using stamp.
+	 */
+	do_ul = (attr & WSATTR_UNDERLINE) != 0;
+	attr &= (ATTR_MASK_BG | ATTR_MASK_FG);
 
 	/* Recompute stamp? */
-	if (attr != stamp_attr)
+	if (attr != stamp_attr || __predict_false(ri != stamp_ri))
 		MAKESTAMP(RASOPS_DEPTH)(ri, attr);
 
-	rp = (STAMP_TYPE *)(ri->ri_bits + row * ri->ri_yscale +
-	    col * ri->ri_xscale);
-	if (ri->ri_hwbits)
-		hp = (STAMP_TYPE *)(ri->ri_hwbits + row * ri->ri_yscale +
-		    col * ri->ri_xscale);
-
 	height = font->fontheight;
 
+	rp = (STAMP_TYPE *)(ri->ri_bits + FBOFFSET(ri, row, col));
+	if (ri->ri_hwbits)
+		hp = (STAMP_TYPE *)(ri->ri_hwbits + FBOFFSET(ri, row, col));
+
 	if (uc == ' ') {
 		while (height--) {
 			SUBST_STAMP(0);
@@ -253,11 +256,9 @@ PUTCHAR_WIDTH(RASOPS_DEPTH, RASOPS_WIDTH
 		}
 	} else {
 		fr = FONT_GLYPH(uc, font, ri);
-		fs = font->stride;
-
 		while (height--) {
 			SUBST_GLYPH;
-			fr += fs;
+			fr += font->stride;
 			if (ri->ri_hwbits) {
 				memcpy(hp, rp, SUBST_BYTES);
 				DELTA(hp, ri->ri_stride, STAMP_TYPE *);
@@ -267,16 +268,21 @@ PUTCHAR_WIDTH(RASOPS_DEPTH, RASOPS_WIDTH
 	}
 
 	/* Do underline */
-	if ((attr & WSATTR_UNDERLINE) != 0) {
-		DELTA(rp, -(ri->ri_stride << 1), STAMP_TYPE *);
-		SUBST_STAMP(FILLED_STAMP);
-		if (ri->ri_hwbits) {
-			DELTA(hp, -(ri->ri_stride << 1), STAMP_TYPE *);
-			memcpy(hp, rp, SUBST_BYTES);
+	if (do_ul) {
+		DELTA(rp, - ri->ri_stride * ri->ri_ul.off, STAMP_TYPE *);
+		if (ri->ri_hwbits)
+			DELTA(hp, - ri->ri_stride * ri->ri_ul.off,
+			    STAMP_TYPE *);
+
+		for (height = ri->ri_ul.height; height; height--) {
+			DELTA(rp, - ri->ri_stride, STAMP_TYPE *);
+			SUBST_STAMP(FILLED_STAMP);
+			if (ri->ri_hwbits) {
+				DELTA(hp, - ri->ri_stride, STAMP_TYPE *);
+				memcpy(hp, rp, SUBST_BYTES);
+			}
 		}
 	}
-
-	stamp_mutex--;
 }
 
 #undef	STAMP_TYPE
@@ -286,17 +292,17 @@ PUTCHAR_WIDTH(RASOPS_DEPTH, RASOPS_WIDTH
 
 #undef	FILLED_STAMP
 
-#undef	PUTCHAR_WIDTH1
-#undef	PUTCHAR_WIDTH
-
-#undef	PUTCHAR1
-#undef	PUTCHAR
-
-#undef	MAKESTAMP1
-#undef	MAKESTAMP
-
 #undef	SUBST_STAMP1
 #undef	SUBST_STAMP
 
 #undef	SUBST_GLYPH1
 #undef	SUBST_GLYPH
+
+#undef	NAME
+#undef	NAME1
+
+#undef	PUTCHAR
+#undef	PUTCHAR1
+
+#undef	MAKESTAMP
+#undef	MAKESTAMP1

Index: src/sys/dev/wscons/wsdisplay_vcons.c
diff -u src/sys/dev/wscons/wsdisplay_vcons.c:1.39 src/sys/dev/wscons/wsdisplay_vcons.c:1.39.4.1
--- src/sys/dev/wscons/wsdisplay_vcons.c:1.39	Sat Dec  1 00:28:45 2018
+++ src/sys/dev/wscons/wsdisplay_vcons.c	Thu Aug 15 12:21:27 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: wsdisplay_vcons.c,v 1.39 2018/12/01 00:28:45 msaitoh Exp $ */
+/*	$NetBSD: wsdisplay_vcons.c,v 1.39.4.1 2019/08/15 12:21:27 martin Exp $ */
 
 /*-
  * Copyright (c) 2005, 2006 Michael Lorenz
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: wsdisplay_vcons.c,v 1.39 2018/12/01 00:28:45 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: wsdisplay_vcons.c,v 1.39.4.1 2019/08/15 12:21:27 martin Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -430,8 +430,23 @@ vcons_load_font(void *v, void *cookie, s
 	/* allocate new buffers */
 	vcons_alloc_buffers(vd, scr);
 	
-	/* save the potentially changed putchar */ 
+	/* save the potentially changed ri_ops */ 
+	vd->eraserows = ri->ri_ops.eraserows;
+	vd->erasecols = ri->ri_ops.erasecols;
 	scr->putchar   = ri->ri_ops.putchar;
+	vd->cursor    = ri->ri_ops.cursor;
+
+	if (scr->scr_flags & VCONS_NO_COPYCOLS) {
+		vd->copycols  = vcons_copycols_noread;
+	} else {
+		vd->copycols = ri->ri_ops.copycols;
+	}
+
+	if (scr->scr_flags & VCONS_NO_COPYROWS) {
+		vd->copyrows  = vcons_copyrows_noread;
+	} else {
+		vd->copyrows = ri->ri_ops.copyrows;
+	}
 
 	/* and put our wrappers back */
 	ri->ri_ops.eraserows = vcons_eraserows;	

Index: src/sys/dev/wsfb/genfb.c
diff -u src/sys/dev/wsfb/genfb.c:1.67 src/sys/dev/wsfb/genfb.c:1.67.2.1
--- src/sys/dev/wsfb/genfb.c:1.67	Mon Jul 29 14:07:37 2019
+++ src/sys/dev/wsfb/genfb.c	Thu Aug 15 12:21:27 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: genfb.c,v 1.67 2019/07/29 14:07:37 rin Exp $ */
+/*	$NetBSD: genfb.c,v 1.67.2.1 2019/08/15 12:21:27 martin Exp $ */
 
 /*-
  * Copyright (c) 2007 Michael Lorenz
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: genfb.c,v 1.67 2019/07/29 14:07:37 rin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: genfb.c,v 1.67.2.1 2019/08/15 12:21:27 martin Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -261,6 +261,9 @@ genfb_attach(struct genfb_softc *sc, str
 		sc->sc_shadowfb = kmem_alloc(sc->sc_fbsize, KM_SLEEP);
 		if (sc->sc_want_clear == false)
 			memcpy(sc->sc_shadowfb, sc->sc_fbaddr, sc->sc_fbsize);
+		aprint_verbose_dev(sc->sc_dev,
+		    "shadow framebuffer enabled, size %zu KB\n",
+		    sc->sc_fbsize >> 10);
 	}
 
 	vcons_init(&sc->vd, sc, &sc->sc_defaultscreen_descr,
@@ -538,6 +541,7 @@ genfb_init_screen(void *cookie, struct v
 	struct genfb_softc *sc = cookie;
 	struct rasops_info *ri = &scr->scr_ri;
 	int wantcols;
+	bool is_bgr;
 
 	ri->ri_depth = sc->sc_depth;
 	ri->ri_width = sc->sc_width;
@@ -560,10 +564,12 @@ genfb_init_screen(void *cookie, struct v
 	if (existing && sc->sc_want_clear)
 		ri->ri_flg |= RI_CLEAR;
 
-	if (ri->ri_depth == 32 || ri->ri_depth == 24) {
+	switch (ri->ri_depth) {
+	case 32:
+	case 24:
 		ri->ri_flg |= RI_ENABLE_ALPHA;
 
-		bool is_bgr = false;
+		is_bgr = false;
 		prop_dictionary_get_bool(device_properties(sc->sc_dev),
 		    "is_bgr", &is_bgr);
 		if (is_bgr) {
@@ -583,13 +589,25 @@ genfb_init_screen(void *cookie, struct v
 			ri->ri_gpos = 8;
 			ri->ri_bpos = 0;
 		}
-	}
+		break;
 
-	if (ri->ri_depth == 16 || ri->ri_depth == 15)
+	case 16:
+	case 15:
 		ri->ri_flg |= RI_ENABLE_ALPHA;
+		break;
+
+	case 8:
+		if (sc->sc_cmcb != NULL)
+			ri->ri_flg |= RI_ENABLE_ALPHA | RI_8BIT_IS_RGB;
+		break;
 
-	if (ri->ri_depth == 8 && sc->sc_cmcb != NULL)
-		ri->ri_flg |= RI_ENABLE_ALPHA | RI_8BIT_IS_RGB;
+	case 2:
+		ri->ri_flg |= RI_ENABLE_ALPHA;
+		break;
+
+	default:
+		break;
+	}
 
 	wantcols = genfb_calc_cols(sc);
 

Added files:

Index: src/sys/dev/rasops/rasops1-4_putchar.h
diff -u /dev/null src/sys/dev/rasops/rasops1-4_putchar.h:1.3.2.2
--- /dev/null	Thu Aug 15 12:21:28 2019
+++ src/sys/dev/rasops/rasops1-4_putchar.h	Thu Aug 15 12:21:27 2019
@@ -0,0 +1,311 @@
+/* $NetBSD: rasops1-4_putchar.h,v 1.3.2.2 2019/08/15 12:21:27 martin Exp $ */
+
+/* NetBSD: rasops_bitops.h,v 1.23 2019/08/02 04:39:09 rin Exp */
+/*-
+ * Copyright (c) 1999 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Andrew Doran.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define	PIXEL_BITS	RASOPS_DEPTH
+
+#if   RASOPS_DEPTH == 1
+#define	PIXEL_SHIFT	0
+#elif RASOPS_DEPTH == 2
+#define	PIXEL_SHIFT	1
+#elif RASOPS_DEPTH == 4
+#define	PIXEL_SHIFT	2
+#else
+#error "Depth not supported"
+#endif
+
+#ifndef RASOPS_AA
+#define	COLOR_MASK	__BITS(32 - PIXEL_BITS, 31)
+#else
+#  if RASOPS_DEPTH == 2
+#define	COLOR_MASK	0x3
+#  else
+#error "Anti-aliasing not supported"
+#  endif
+#endif
+
+#ifndef RASOPS_AA
+#define	PIXEL_OR(tmp)							\
+	do {								\
+		(tmp) |= clr[(fb >> 31) & 1] >> bit;			\
+		fb <<= 1;						\
+	} while (0 /* CONSTCOND */)
+#else
+#define	PIXEL_OR(tmp)							\
+	do {								\
+		uint8_t c, w = *fr++;					\
+		if (w == 0xff)						\
+			c = clr[1];					\
+		else if (w == 0)					\
+			c = clr[0];					\
+		else							\
+			c = (w * clr[1] + (0xff - w) * clr[0]) >> 8;	\
+		(tmp) |= c << (32 - PIXEL_BITS - bit);			\
+	} while (0 /* CONSTCOND */)
+#endif
+
+#define	NAME(depth)	NAME1(depth)
+#ifndef RASOPS_AA
+#define	NAME1(depth)	rasops ## depth ## _ ## putchar
+#else
+#define	NAME1(depth)	rasops ## depth ## _ ## putchar_aa
+#endif
+
+/*
+ * Paint a single character. This function is also applicable to
+ * monochrome, but that in rasops1.c is much simpler and faster.
+ */
+static void
+NAME(RASOPS_DEPTH)(void *cookie, int row, int col, u_int uc, long attr)
+{
+	struct rasops_info *ri = (struct rasops_info *)cookie;
+	struct wsdisplay_font *font = PICK_FONT(ri, uc);
+	int height, width, full, cnt, bit;
+	uint32_t bg, fg, lbg, rbg, clr[2], lmask, rmask, tmp;
+	uint32_t *rp, *bp, *hp;
+	uint8_t *fr;
+	bool space;
+
+	hp = NULL;	/* XXX GCC */
+
+	if (__predict_false(!CHAR_IN_FONT(uc, font)))
+		return;
+
+#ifdef RASOPS_CLIPPING
+	/* Catches 'row < 0' case too */
+	if ((unsigned)row >= (unsigned)ri->ri_rows)
+		return;
+
+	if ((unsigned)col >= (unsigned)ri->ri_cols)
+		return;
+#endif
+
+	height = font->fontheight;
+	width = font->fontwidth << PIXEL_SHIFT;
+	col *= width;
+
+	rp = (uint32_t *)(ri->ri_bits + row * ri->ri_yscale +
+	    ((col >> 3) & ~3));
+	if (ri->ri_hwbits)
+		hp = (uint32_t *)(ri->ri_hwbits + row * ri->ri_yscale +
+		    ((col >> 3) & ~3));
+
+	col &= 31;
+
+	bg = ATTR_BG(ri, attr);
+	fg = ATTR_FG(ri, attr);
+
+	/* If fg and bg match this becomes a space character */
+	if (uc == ' ' || __predict_false(fg == bg)) {
+		space = true;
+		fr = NULL;	/* XXX GCC */
+	} else {
+		space = false;
+		fr = FONT_GLYPH(uc, font, ri);
+	}
+
+	if (col + width <= 32) {
+		/* Single word, only one mask */
+		rmask = rasops_pmask[col][width & 31];
+		lmask = ~rmask;
+
+		if (space) {
+			bg &= rmask;
+			while (height--) {
+				tmp = (*rp & lmask) | bg;
+				*rp = tmp;
+				if (ri->ri_hwbits) {
+					*hp = tmp;
+					DELTA(hp, ri->ri_stride, uint32_t *);
+				}
+				DELTA(rp, ri->ri_stride, uint32_t *);
+			}
+		} else {
+			clr[0] = bg & COLOR_MASK;
+			clr[1] = fg & COLOR_MASK;
+
+			while (height--) {
+#ifndef RASOPS_AA
+				uint32_t fb = rasops_be32uatoh(fr);
+				fr += ri->ri_font->stride;
+#endif
+
+				tmp = 0;
+				for (bit = col; bit < col + width;
+				    bit += PIXEL_BITS)
+					PIXEL_OR(tmp);
+				tmp = (*rp & lmask) | MBE(tmp);
+				*rp = tmp;
+
+				if (ri->ri_hwbits) {
+					*hp = tmp;
+					DELTA(hp, ri->ri_stride, uint32_t *);
+				}
+
+				DELTA(rp, ri->ri_stride, uint32_t *);
+			}
+		}
+
+		/* Do underline */
+		if ((attr & WSATTR_UNDERLINE) != 0) {
+			DELTA(rp, - ri->ri_stride * ri->ri_ul.off, uint32_t *);
+			if (ri->ri_hwbits)
+				DELTA(hp, - ri->ri_stride * ri->ri_ul.off,
+				    uint32_t *);
+
+			for (height = ri->ri_ul.height; height; height--) {
+				DELTA(rp, - ri->ri_stride, uint32_t *);
+				tmp = (*rp & lmask) | (fg & rmask);
+				*rp = tmp;
+				if (ri->ri_hwbits) {
+					DELTA(hp, - ri->ri_stride, uint32_t *);
+					*hp = tmp;
+				}
+			}
+		}
+
+		return;
+	}
+
+	/* Word boundary, two masks needed */
+	lmask = ~rasops_lmask[col];
+	rmask = ~rasops_rmask[(col + width) & 31];
+
+	if (lmask != -1)
+		width -= 32 - col;
+
+	full = width / 32;
+	width -= full * 32;
+
+	if (space) {
+		lbg = bg & ~lmask;
+		rbg = bg & ~rmask;
+
+		while (height--) {
+			bp = rp;
+
+			if (lmask != -1) {
+				*bp = (*bp & lmask) | lbg;
+				bp++;
+			}
+
+			for (cnt = full; cnt; cnt--)
+				*bp++ = bg;
+
+			if (rmask != -1)
+				*bp = (*bp & rmask) | rbg;
+
+			if (ri->ri_hwbits) {
+				memcpy(hp, rp, ((lmask != -1) + full +
+				    (rmask != -1)) << 2);
+				DELTA(hp, ri->ri_stride, uint32_t *);
+			}
+
+			DELTA(rp, ri->ri_stride, uint32_t *);
+		}
+	} else {
+		clr[0] = bg & COLOR_MASK;
+		clr[1] = fg & COLOR_MASK;
+
+		while (height--) {
+			bp = rp;
+
+#ifndef RASOPS_AA
+			uint32_t fb = rasops_be32uatoh(fr);
+			fr += ri->ri_font->stride;
+#endif
+
+			if (lmask != -1) {
+				tmp = 0;
+				for (bit = col; bit < 32; bit += PIXEL_BITS)
+					PIXEL_OR(tmp);
+				*bp = (*bp & lmask) | MBE(tmp);
+				bp++;
+			}
+
+			for (cnt = full; cnt; cnt--) {
+				tmp = 0;
+				for (bit = 0; bit < 32; bit += PIXEL_BITS)
+					PIXEL_OR(tmp);
+				*bp++ = MBE(tmp);
+			}
+
+			if (rmask != -1) {
+				tmp = 0;
+				for (bit = 0; bit < width; bit += PIXEL_BITS)
+					PIXEL_OR(tmp);
+				*bp = (*bp & rmask) | MBE(tmp);
+			}
+
+			if (ri->ri_hwbits) {
+				memcpy(hp, rp, ((lmask != -1) + full +
+				    (rmask != -1)) << 2);
+				DELTA(hp, ri->ri_stride, uint32_t *);
+			}
+
+			DELTA(rp, ri->ri_stride, uint32_t *);
+		}
+	}
+
+	/* Do underline */
+	if ((attr & WSATTR_UNDERLINE) != 0) {
+		DELTA(rp, - ri->ri_stride * ri->ri_ul.off, uint32_t *);
+		if (ri->ri_hwbits)
+			DELTA(hp, - ri->ri_stride * ri->ri_ul.off, uint32_t *);
+
+		for (height = ri->ri_ul.height; height; height--) {
+			DELTA(rp, - ri->ri_stride, uint32_t *);
+			bp = rp;
+			if (lmask != -1) {
+				*bp = (*bp & lmask) | (fg & ~lmask);
+				bp++;
+			}
+			for (cnt = full; cnt; cnt--)
+				*bp++ = fg;
+			if (rmask != -1)
+				*bp = (*bp & rmask) | (fg & ~rmask);
+			if (ri->ri_hwbits) {
+				DELTA(hp, - ri->ri_stride, uint32_t *);
+				memcpy(hp, rp, ((lmask != -1) + full +
+				    (rmask != -1)) << 2);
+			}
+		}
+	}
+}
+
+#undef	PIXEL_BITS
+#undef	PIXEL_SHIFT
+#undef	COLOR_MASK
+
+#undef	PIXEL_OR
+
+#undef	NAME
+#undef	NAME1

Reply via email to