Home | History | Annotate | Line # | Download | only in rasops
rasops.c revision 1.90
      1  1.90       rin /*	 $NetBSD: rasops.c,v 1.90 2019/07/26 05:24:04 rin Exp $	*/
      2   1.1        ad 
      3   1.9        ad /*-
      4   1.9        ad  * Copyright (c) 1999 The NetBSD Foundation, Inc.
      5   1.1        ad  * All rights reserved.
      6   1.1        ad  *
      7   1.9        ad  * This code is derived from software contributed to The NetBSD Foundation
      8  1.32        ad  * by Andrew Doran.
      9   1.9        ad  *
     10   1.1        ad  * Redistribution and use in source and binary forms, with or without
     11   1.1        ad  * modification, are permitted provided that the following conditions
     12   1.1        ad  * are met:
     13   1.1        ad  * 1. Redistributions of source code must retain the above copyright
     14   1.1        ad  *    notice, this list of conditions and the following disclaimer.
     15   1.1        ad  * 2. Redistributions in binary form must reproduce the above copyright
     16   1.1        ad  *    notice, this list of conditions and the following disclaimer in the
     17   1.1        ad  *    documentation and/or other materials provided with the distribution.
     18   1.1        ad  *
     19   1.9        ad  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20   1.9        ad  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21   1.9        ad  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22   1.9        ad  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23   1.9        ad  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24   1.9        ad  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25   1.9        ad  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26   1.9        ad  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27   1.9        ad  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28   1.9        ad  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29   1.9        ad  * POSSIBILITY OF SUCH DAMAGE.
     30   1.1        ad  */
     31   1.2        ad 
     32   1.1        ad #include <sys/cdefs.h>
     33  1.90       rin __KERNEL_RCSID(0, "$NetBSD: rasops.c,v 1.90 2019/07/26 05:24:04 rin Exp $");
     34   1.1        ad 
     35  1.18        ad #include "opt_rasops.h"
     36   1.4        ad #include "rasops_glue.h"
     37  1.47  macallan #include "opt_wsmsgattrs.h"
     38   1.1        ad 
     39   1.1        ad #include <sys/param.h>
     40  1.89       rin #include <sys/bswap.h>
     41  1.89       rin #include <sys/kmem.h>
     42   1.1        ad #include <sys/systm.h>
     43   1.1        ad #include <sys/time.h>
     44   1.1        ad 
     45   1.4        ad #include <machine/endian.h>
     46   1.3        ad 
     47   1.1        ad #include <dev/wscons/wsdisplayvar.h>
     48   1.1        ad #include <dev/wscons/wsconsio.h>
     49   1.1        ad #include <dev/wsfont/wsfont.h>
     50   1.1        ad #include <dev/rasops/rasops.h>
     51   1.1        ad 
     52  1.11        ad #ifndef _KERNEL
     53  1.11        ad #include <errno.h>
     54  1.11        ad #endif
     55  1.11        ad 
     56  1.70  macallan #ifdef RASOPS_DEBUG
     57  1.88       rin #define DPRINTF(...) aprint_error(...)
     58  1.70  macallan #else
     59  1.88       rin #define DPRINTF(...) __nothing
     60  1.70  macallan #endif
     61  1.70  macallan 
     62  1.70  macallan struct rasops_matchdata {
     63  1.70  macallan 	struct rasops_info *ri;
     64  1.70  macallan 	int wantcols, wantrows;
     65  1.70  macallan 	int bestscore;
     66  1.70  macallan 	struct wsdisplay_font *pick;
     67  1.70  macallan 	int ident;
     68  1.70  macallan };
     69  1.70  macallan 
     70   1.1        ad /* ANSI colormap (R,G,B). Upper 8 are high-intensity */
     71  1.89       rin const uint8_t rasops_cmap[256 * 3] = {
     72   1.1        ad 	0x00, 0x00, 0x00, /* black */
     73   1.1        ad 	0x7f, 0x00, 0x00, /* red */
     74   1.1        ad 	0x00, 0x7f, 0x00, /* green */
     75   1.1        ad 	0x7f, 0x7f, 0x00, /* brown */
     76   1.1        ad 	0x00, 0x00, 0x7f, /* blue */
     77   1.1        ad 	0x7f, 0x00, 0x7f, /* magenta */
     78   1.1        ad 	0x00, 0x7f, 0x7f, /* cyan */
     79   1.1        ad 	0xc7, 0xc7, 0xc7, /* white - XXX too dim? */
     80   1.1        ad 
     81   1.1        ad 	0x7f, 0x7f, 0x7f, /* black */
     82   1.1        ad 	0xff, 0x00, 0x00, /* red */
     83   1.1        ad 	0x00, 0xff, 0x00, /* green */
     84   1.1        ad 	0xff, 0xff, 0x00, /* brown */
     85   1.1        ad 	0x00, 0x00, 0xff, /* blue */
     86   1.1        ad 	0xff, 0x00, 0xff, /* magenta */
     87   1.1        ad 	0x00, 0xff, 0xff, /* cyan */
     88   1.1        ad 	0xff, 0xff, 0xff, /* white */
     89  1.23  drochner 
     90  1.23  drochner 	/*
     91  1.23  drochner 	 * For the cursor, we need at least the last (255th)
     92  1.23  drochner 	 * color to be white. Fill up white completely for
     93  1.23  drochner 	 * simplicity.
     94  1.23  drochner 	 */
     95  1.23  drochner #define _CMWHITE 0xff, 0xff, 0xff,
     96  1.23  drochner #define _CMWHITE16	_CMWHITE _CMWHITE _CMWHITE _CMWHITE \
     97  1.23  drochner 			_CMWHITE _CMWHITE _CMWHITE _CMWHITE \
     98  1.23  drochner 			_CMWHITE _CMWHITE _CMWHITE _CMWHITE \
     99  1.23  drochner 			_CMWHITE _CMWHITE _CMWHITE _CMWHITE
    100  1.23  drochner 	_CMWHITE16 _CMWHITE16 _CMWHITE16 _CMWHITE16 _CMWHITE16
    101  1.23  drochner 	_CMWHITE16 _CMWHITE16 _CMWHITE16 _CMWHITE16 _CMWHITE16
    102  1.44       uwe 	_CMWHITE16 _CMWHITE16 _CMWHITE16 _CMWHITE16 /* but not the last one */
    103  1.23  drochner #undef _CMWHITE16
    104  1.23  drochner #undef _CMWHITE
    105  1.44       uwe 
    106  1.44       uwe 	/*
    107  1.44       uwe 	 * For the cursor the fg/bg indices are bit inverted, so
    108  1.44       uwe 	 * provide complimentary colors in the upper 16 entries.
    109  1.44       uwe 	 */
    110  1.44       uwe 	0x7f, 0x7f, 0x7f, /* black */
    111  1.44       uwe 	0xff, 0x00, 0x00, /* red */
    112  1.44       uwe 	0x00, 0xff, 0x00, /* green */
    113  1.44       uwe 	0xff, 0xff, 0x00, /* brown */
    114  1.44       uwe 	0x00, 0x00, 0xff, /* blue */
    115  1.44       uwe 	0xff, 0x00, 0xff, /* magenta */
    116  1.44       uwe 	0x00, 0xff, 0xff, /* cyan */
    117  1.44       uwe 	0xff, 0xff, 0xff, /* white */
    118  1.44       uwe 
    119  1.44       uwe 	0x00, 0x00, 0x00, /* black */
    120  1.44       uwe 	0x7f, 0x00, 0x00, /* red */
    121  1.44       uwe 	0x00, 0x7f, 0x00, /* green */
    122  1.44       uwe 	0x7f, 0x7f, 0x00, /* brown */
    123  1.44       uwe 	0x00, 0x00, 0x7f, /* blue */
    124  1.44       uwe 	0x7f, 0x00, 0x7f, /* magenta */
    125  1.44       uwe 	0x00, 0x7f, 0x7f, /* cyan */
    126  1.44       uwe 	0xc7, 0xc7, 0xc7, /* white - XXX too dim? */
    127   1.1        ad };
    128   1.1        ad 
    129   1.1        ad /* True if color is gray */
    130  1.81       rin const uint8_t rasops_isgray[16] = {
    131  1.30        pk 	1, 0, 0, 0,
    132   1.1        ad 	0, 0, 0, 1,
    133   1.1        ad 	1, 0, 0, 0,
    134  1.89       rin 	0, 0, 0, 1,
    135   1.1        ad };
    136   1.1        ad 
    137   1.4        ad /* Generic functions */
    138  1.45     perry static void	rasops_copyrows(void *, int, int, int);
    139  1.45     perry static int	rasops_mapchar(void *, int, u_int *);
    140  1.45     perry static void	rasops_cursor(void *, int, int, int);
    141  1.45     perry static int	rasops_allocattr_color(void *, int, int, int, long *);
    142  1.45     perry static int	rasops_allocattr_mono(void *, int, int, int, long *);
    143  1.45     perry static void	rasops_do_cursor(struct rasops_info *);
    144  1.45     perry static void	rasops_init_devcmap(struct rasops_info *);
    145   1.1        ad 
    146  1.55      ober #if NRASOPS_ROTATION > 0
    147  1.62    nonaka static void	rasops_rotate_font(int *, int);
    148  1.55      ober static void	rasops_copychar(void *, int, int, int, int);
    149  1.62    nonaka 
    150  1.62    nonaka /* rotate clockwise */
    151  1.62    nonaka static void	rasops_copycols_rotated_cw(void *, int, int, int, int);
    152  1.62    nonaka static void	rasops_copyrows_rotated_cw(void *, int, int, int);
    153  1.62    nonaka static void	rasops_erasecols_rotated_cw(void *, int, int, int, long);
    154  1.62    nonaka static void	rasops_eraserows_rotated_cw(void *, int, int, long);
    155  1.62    nonaka static void	rasops_putchar_rotated_cw(void *, int, int, u_int, long);
    156  1.62    nonaka 
    157  1.62    nonaka /* rotate counter-clockwise */
    158  1.62    nonaka static void	rasops_copychar_ccw(void *, int, int, int, int);
    159  1.62    nonaka static void	rasops_copycols_rotated_ccw(void *, int, int, int, int);
    160  1.62    nonaka static void	rasops_copyrows_rotated_ccw(void *, int, int, int);
    161  1.62    nonaka #define rasops_erasecols_rotated_ccw rasops_erasecols_rotated_cw
    162  1.62    nonaka #define rasops_eraserows_rotated_ccw rasops_eraserows_rotated_cw
    163  1.62    nonaka static void	rasops_putchar_rotated_ccw(void *, int, int, u_int, long);
    164  1.55      ober 
    165  1.55      ober /*
    166  1.55      ober  * List of all rotated fonts
    167  1.55      ober  */
    168  1.55      ober SLIST_HEAD(, rotatedfont) rotatedfonts = SLIST_HEAD_INITIALIZER(rotatedfonts);
    169  1.55      ober struct rotatedfont {
    170  1.55      ober 	SLIST_ENTRY(rotatedfont) rf_next;
    171  1.55      ober 	int rf_cookie;
    172  1.55      ober 	int rf_rotated;
    173  1.55      ober };
    174  1.55      ober #endif	/* NRASOPS_ROTATION > 0 */
    175  1.55      ober 
    176  1.63  macallan void	rasops_make_box_chars_8(struct rasops_info *);
    177  1.63  macallan void	rasops_make_box_chars_16(struct rasops_info *);
    178  1.63  macallan void	rasops_make_box_chars_32(struct rasops_info *);
    179  1.67  macallan void	rasops_make_box_chars_alpha(struct rasops_info *);
    180  1.63  macallan 
    181  1.64  macallan extern int cold;
    182  1.64  macallan 
    183   1.1        ad /*
    184  1.37       wiz  * Initialize a 'rasops_info' descriptor.
    185   1.1        ad  */
    186   1.1        ad int
    187  1.60       dsl rasops_init(struct rasops_info *ri, int wantrows, int wantcols)
    188   1.1        ad {
    189  1.20        ad 
    190  1.63  macallan 	memset (&ri->ri_optfont, 0, sizeof(ri->ri_optfont));
    191  1.30        pk #ifdef _KERNEL
    192   1.1        ad 	/* Select a font if the caller doesn't care */
    193   1.1        ad 	if (ri->ri_font == NULL) {
    194  1.67  macallan 		int cookie = -1;
    195  1.73   mlelstv 		int flags;
    196  1.30        pk 
    197   1.1        ad 		wsfont_init();
    198   1.1        ad 
    199  1.70  macallan 		/*
    200  1.70  macallan 		 * first, try to find something that's as close as possible
    201  1.70  macallan 		 * to the caller's requested terminal size
    202  1.70  macallan 		 */
    203  1.70  macallan 		if (wantrows == 0)
    204  1.70  macallan 			wantrows = RASOPS_DEFAULT_HEIGHT;
    205  1.70  macallan 		if (wantcols == 0)
    206  1.70  macallan 			wantcols = RASOPS_DEFAULT_WIDTH;
    207  1.73   mlelstv 
    208  1.73   mlelstv 		flags = WSFONT_FIND_BESTWIDTH | WSFONT_FIND_BITMAP;
    209  1.73   mlelstv 		if ((ri->ri_flg & RI_ENABLE_ALPHA) != 0)
    210  1.73   mlelstv 			flags |= WSFONT_FIND_ALPHA;
    211  1.75  macallan 		if ((ri->ri_flg & RI_PREFER_ALPHA) != 0)
    212  1.75  macallan 			flags |= WSFONT_PREFER_ALPHA;
    213  1.73   mlelstv 		cookie = wsfont_find(NULL,
    214  1.73   mlelstv 			ri->ri_width / wantcols,
    215  1.73   mlelstv 			0,
    216  1.73   mlelstv 			0,
    217  1.73   mlelstv 			WSDISPLAY_FONTORDER_L2R,
    218  1.73   mlelstv 			WSDISPLAY_FONTORDER_L2R,
    219  1.73   mlelstv 			flags);
    220   1.1        ad 
    221  1.70  macallan 		/*
    222  1.70  macallan 		 * this means there is no supported font in the list
    223  1.70  macallan 		 */
    224   1.7        ad 		if (cookie <= 0) {
    225  1.89       rin 			aprint_error("%s: font table is empty\n", __func__);
    226  1.88       rin 			return -1;
    227   1.1        ad 		}
    228  1.30        pk 
    229  1.55      ober #if NRASOPS_ROTATION > 0
    230  1.55      ober 		/*
    231  1.55      ober 		 * Pick the rotated version of this font. This will create it
    232  1.55      ober 		 * if necessary.
    233  1.55      ober 		 */
    234  1.62    nonaka 		if (ri->ri_flg & RI_ROTATE_MASK) {
    235  1.62    nonaka 			if (ri->ri_flg & RI_ROTATE_CW)
    236  1.62    nonaka 				rasops_rotate_font(&cookie, WSFONT_ROTATE_CW);
    237  1.62    nonaka 			else if (ri->ri_flg & RI_ROTATE_CCW)
    238  1.62    nonaka 				rasops_rotate_font(&cookie, WSFONT_ROTATE_CCW);
    239  1.62    nonaka 		}
    240  1.55      ober #endif
    241  1.55      ober 
    242  1.39        ad 		if (wsfont_lock(cookie, &ri->ri_font)) {
    243  1.89       rin 			aprint_error("%s: couldn't lock font\n", __func__);
    244  1.88       rin 			return -1;
    245   1.1        ad 		}
    246   1.8        ad 
    247   1.5        ad 		ri->ri_wsfcookie = cookie;
    248   1.1        ad 	}
    249   1.4        ad #endif
    250  1.30        pk 
    251   1.1        ad 	/* This should never happen in reality... */
    252  1.89       rin 	if ((uintptr_t)ri->ri_bits & 3) {
    253  1.89       rin 		aprint_error("%s: bits not aligned on 32-bit boundary\n",
    254  1.89       rin 		    __func__);
    255  1.88       rin 		return -1;
    256   1.1        ad 	}
    257   1.1        ad 
    258  1.89       rin 	if (ri->ri_stride & 3) {
    259  1.89       rin 		aprint_error("%s: stride not aligned on 32-bit boundary\n",
    260  1.89       rin 		    __func__);
    261  1.88       rin 		return -1;
    262   1.1        ad 	}
    263   1.4        ad 
    264  1.13        ad 	if (rasops_reconfig(ri, wantrows, wantcols))
    265  1.88       rin 		return -1;
    266  1.46     perry 
    267   1.4        ad 	rasops_init_devcmap(ri);
    268  1.88       rin 	return 0;
    269   1.4        ad }
    270   1.4        ad 
    271   1.4        ad /*
    272  1.13        ad  * Reconfigure (because parameters have changed in some way).
    273   1.4        ad  */
    274   1.4        ad int
    275  1.60       dsl rasops_reconfig(struct rasops_info *ri, int wantrows, int wantcols)
    276   1.4        ad {
    277  1.89       rin 	int bpp, s;
    278  1.89       rin 	size_t len;
    279  1.30        pk 
    280  1.13        ad 	s = splhigh();
    281  1.30        pk 
    282  1.70  macallan 	if (wantrows == 0)
    283  1.70  macallan 		wantrows = RASOPS_DEFAULT_HEIGHT;
    284  1.70  macallan 	if (wantcols == 0)
    285  1.70  macallan 		wantcols = RASOPS_DEFAULT_WIDTH;
    286  1.70  macallan 
    287  1.63  macallan 	/* throw away old line drawing character bitmaps, if we have any */
    288  1.63  macallan 	if (ri->ri_optfont.data != NULL) {
    289  1.63  macallan 		kmem_free(ri->ri_optfont.data, ri->ri_optfont.stride *
    290  1.63  macallan 		    ri->ri_optfont.fontheight * ri->ri_optfont.numchars);
    291  1.63  macallan 		ri->ri_optfont.data = NULL;
    292  1.63  macallan 	}
    293  1.63  macallan 
    294  1.63  macallan 	/* autogenerate box drawing characters */
    295  1.64  macallan 	ri->ri_optfont.firstchar = WSFONT_FLAG_OPT;
    296  1.64  macallan 	ri->ri_optfont.numchars = 16;
    297  1.63  macallan 	ri->ri_optfont.fontwidth = ri->ri_font->fontwidth;
    298  1.63  macallan 	ri->ri_optfont.fontheight = ri->ri_font->fontheight;
    299  1.63  macallan 	ri->ri_optfont.stride = ri->ri_font->stride;
    300  1.64  macallan 	len = ri->ri_optfont.fontheight * ri->ri_optfont.stride *
    301  1.89       rin 	    ri->ri_optfont.numchars;
    302  1.89       rin 
    303  1.89       rin 	if (ri->ri_font->fontwidth > 32 || ri->ri_font->fontwidth < 4) {
    304  1.89       rin 		aprint_error("%s: fontwidth assumptions botched", __func__);
    305  1.89       rin 		splx(s);
    306  1.89       rin 		return -1;
    307  1.89       rin 	}
    308  1.64  macallan 
    309  1.77       chs 	if ((ri->ri_flg & RI_NO_AUTO) == 0) {
    310  1.77       chs 		ri->ri_optfont.data = kmem_zalloc(len, KM_SLEEP);
    311  1.89       rin 		if (FONT_IS_ALPHA(&ri->ri_optfont))
    312  1.89       rin 			rasops_make_box_chars_alpha(ri);
    313  1.89       rin 		else {
    314  1.67  macallan 			switch (ri->ri_optfont.stride) {
    315  1.67  macallan 			case 1:
    316  1.67  macallan 				rasops_make_box_chars_8(ri);
    317  1.67  macallan 				break;
    318  1.67  macallan 			case 2:
    319  1.67  macallan 				rasops_make_box_chars_16(ri);
    320  1.67  macallan 				break;
    321  1.67  macallan 			case 4:
    322  1.67  macallan 				rasops_make_box_chars_32(ri);
    323  1.67  macallan 				break;
    324  1.89       rin 			default:
    325  1.89       rin 				aprint_error(
    326  1.89       rin 				    "%s: font stride assumptions botched",
    327  1.89       rin 				    __func__);
    328  1.89       rin 				splx(s);
    329  1.89       rin 				return -1;
    330  1.67  macallan 			}
    331  1.63  macallan 		}
    332  1.64  macallan 	} else
    333  1.64  macallan 		memset(&ri->ri_optfont, 0, sizeof(ri->ri_optfont));
    334  1.63  macallan 
    335   1.4        ad 	/* Need this to frob the setup below */
    336   1.4        ad 	bpp = (ri->ri_depth == 15 ? 16 : ri->ri_depth);
    337   1.4        ad 
    338  1.74    nonaka 	if ((ri->ri_flg & RI_CFGDONE) != 0) {
    339   1.4        ad 		ri->ri_bits = ri->ri_origbits;
    340  1.74    nonaka 		ri->ri_hwbits = ri->ri_hworigbits;
    341  1.74    nonaka 	}
    342  1.30        pk 
    343   1.1        ad 	/* Don't care if the caller wants a hideously small console */
    344   1.1        ad 	if (wantrows < 10)
    345  1.13        ad 		wantrows = 10;
    346  1.30        pk 
    347   1.1        ad 	if (wantcols < 20)
    348  1.13        ad 		wantcols = 20;
    349  1.30        pk 
    350   1.1        ad 	/* Now constrain what they get */
    351   1.1        ad 	ri->ri_emuwidth = ri->ri_font->fontwidth * wantcols;
    352   1.1        ad 	ri->ri_emuheight = ri->ri_font->fontheight * wantrows;
    353  1.30        pk 
    354   1.1        ad 	if (ri->ri_emuwidth > ri->ri_width)
    355   1.1        ad 		ri->ri_emuwidth = ri->ri_width;
    356  1.30        pk 
    357   1.1        ad 	if (ri->ri_emuheight > ri->ri_height)
    358   1.1        ad 		ri->ri_emuheight = ri->ri_height;
    359  1.30        pk 
    360   1.1        ad 	/* Reduce width until aligned on a 32-bit boundary */
    361  1.20        ad 	while ((ri->ri_emuwidth * bpp & 31) != 0)
    362   1.1        ad 		ri->ri_emuwidth--;
    363  1.30        pk 
    364  1.55      ober #if NRASOPS_ROTATION > 0
    365  1.62    nonaka 	if (ri->ri_flg & (RI_ROTATE_CW|RI_ROTATE_CCW)) {
    366  1.55      ober 		ri->ri_rows = ri->ri_emuwidth / ri->ri_font->fontwidth;
    367  1.55      ober 		ri->ri_cols = ri->ri_emuheight / ri->ri_font->fontheight;
    368  1.55      ober 	} else
    369  1.55      ober #endif
    370  1.55      ober 	{
    371  1.55      ober 
    372  1.55      ober 		ri->ri_cols = ri->ri_emuwidth / ri->ri_font->fontwidth;
    373  1.55      ober 		ri->ri_rows = ri->ri_emuheight / ri->ri_font->fontheight;
    374  1.55      ober 	}
    375   1.4        ad 	ri->ri_emustride = ri->ri_emuwidth * bpp >> 3;
    376   1.1        ad 	ri->ri_delta = ri->ri_stride - ri->ri_emustride;
    377   1.1        ad 	ri->ri_ccol = 0;
    378   1.1        ad 	ri->ri_crow = 0;
    379   1.4        ad 	ri->ri_pelbytes = bpp >> 3;
    380  1.30        pk 
    381   1.4        ad 	ri->ri_xscale = (ri->ri_font->fontwidth * bpp) >> 3;
    382   1.1        ad 	ri->ri_yscale = ri->ri_font->fontheight * ri->ri_stride;
    383   1.1        ad 	ri->ri_fontscale = ri->ri_font->fontheight * ri->ri_font->stride;
    384   1.1        ad 
    385  1.89       rin 	if ((ri->ri_delta & 3) != 0) {
    386  1.89       rin 		aprint_error(
    387  1.89       rin 		    "%s: ri_delta not aligned on 32-bit boundary", __func__);
    388  1.89       rin 		splx(s);
    389  1.89       rin 		return -1;
    390  1.89       rin 	}
    391  1.75  macallan 	ri->ri_origbits = ri->ri_bits;
    392  1.75  macallan 	ri->ri_hworigbits = ri->ri_hwbits;
    393  1.75  macallan 
    394   1.1        ad 	/* Clear the entire display */
    395  1.13        ad 	if ((ri->ri_flg & RI_CLEAR) != 0)
    396  1.13        ad 		memset(ri->ri_bits, 0, ri->ri_stride * ri->ri_height);
    397  1.30        pk 
    398  1.30        pk 	/* Now centre our window if needs be */
    399  1.13        ad 	if ((ri->ri_flg & RI_CENTER) != 0) {
    400  1.46     perry 		ri->ri_bits += (((ri->ri_width * bpp >> 3) -
    401  1.36   nathanw 		    ri->ri_emustride) >> 1) & ~3;
    402  1.30        pk 		ri->ri_bits += ((ri->ri_height - ri->ri_emuheight) >> 1) *
    403   1.1        ad 		    ri->ri_stride;
    404  1.61  macallan 		if (ri->ri_hwbits != NULL) {
    405  1.61  macallan 			ri->ri_hwbits += (((ri->ri_width * bpp >> 3) -
    406  1.61  macallan 			    ri->ri_emustride) >> 1) & ~3;
    407  1.88       rin 			ri->ri_hwbits +=
    408  1.88       rin 			    ((ri->ri_height - ri->ri_emuheight) >> 1) *
    409  1.61  macallan 			    ri->ri_stride;
    410  1.61  macallan 		}
    411  1.89       rin 		ri->ri_yorigin = (int)(ri->ri_bits - ri->ri_origbits) /
    412  1.89       rin 		    ri->ri_stride;
    413  1.89       rin 		ri->ri_xorigin = (((int)(ri->ri_bits - ri->ri_origbits) %
    414  1.89       rin 		    ri->ri_stride) * 8 / bpp);
    415   1.5        ad 	} else
    416   1.5        ad 		ri->ri_xorigin = ri->ri_yorigin = 0;
    417   1.4        ad 
    418  1.30        pk 	/*
    419   1.4        ad 	 * Fill in defaults for operations set.  XXX this nukes private
    420   1.4        ad 	 * routines used by accelerated fb drivers.
    421   1.4        ad 	 */
    422   1.1        ad 	ri->ri_ops.mapchar = rasops_mapchar;
    423   1.1        ad 	ri->ri_ops.copyrows = rasops_copyrows;
    424   1.1        ad 	ri->ri_ops.copycols = rasops_copycols;
    425   1.4        ad 	ri->ri_ops.erasecols = rasops_erasecols;
    426   1.4        ad 	ri->ri_ops.eraserows = rasops_eraserows;
    427   1.1        ad 	ri->ri_ops.cursor = rasops_cursor;
    428   1.4        ad 	ri->ri_do_cursor = rasops_do_cursor;
    429  1.30        pk 
    430  1.76  macallan 	ri->ri_caps &= ~(WSSCREEN_UNDERLINE | WSSCREEN_HILIT |
    431  1.76  macallan 		    WSSCREEN_WSCOLORS | WSSCREEN_REVERSE);
    432  1.13        ad 	if (ri->ri_depth < 8 || (ri->ri_flg & RI_FORCEMONO) != 0) {
    433  1.41  junyoung 		ri->ri_ops.allocattr = rasops_allocattr_mono;
    434  1.76  macallan 		ri->ri_caps |= WSSCREEN_UNDERLINE | WSSCREEN_REVERSE;
    435   1.4        ad 	} else {
    436  1.41  junyoung 		ri->ri_ops.allocattr = rasops_allocattr_color;
    437  1.76  macallan 		ri->ri_caps |= WSSCREEN_UNDERLINE | WSSCREEN_HILIT |
    438  1.24  drochner 		    WSSCREEN_WSCOLORS | WSSCREEN_REVERSE;
    439   1.4        ad 	}
    440   1.4        ad 
    441   1.1        ad 	switch (ri->ri_depth) {
    442  1.20        ad #if NRASOPS1 > 0
    443   1.1        ad 	case 1:
    444   1.1        ad 		rasops1_init(ri);
    445   1.1        ad 		break;
    446   1.1        ad #endif
    447  1.20        ad #if NRASOPS2 > 0
    448   1.4        ad 	case 2:
    449   1.4        ad 		rasops2_init(ri);
    450  1.34  takemura 		break;
    451  1.34  takemura #endif
    452  1.34  takemura #if NRASOPS4 > 0
    453  1.34  takemura 	case 4:
    454  1.34  takemura 		rasops4_init(ri);
    455   1.4        ad 		break;
    456   1.4        ad #endif
    457  1.20        ad #if NRASOPS8 > 0
    458   1.1        ad 	case 8:
    459   1.1        ad 		rasops8_init(ri);
    460   1.1        ad 		break;
    461   1.1        ad #endif
    462  1.20        ad #if NRASOPS15 > 0 || NRASOPS16 > 0
    463   1.1        ad 	case 15:
    464   1.1        ad 	case 16:
    465   1.1        ad 		rasops15_init(ri);
    466   1.1        ad 		break;
    467   1.1        ad #endif
    468  1.20        ad #if NRASOPS24 > 0
    469   1.1        ad 	case 24:
    470   1.1        ad 		rasops24_init(ri);
    471   1.1        ad 		break;
    472   1.1        ad #endif
    473  1.20        ad #if NRASOPS32 > 0
    474   1.1        ad 	case 32:
    475   1.1        ad 		rasops32_init(ri);
    476   1.1        ad 		break;
    477   1.1        ad #endif
    478   1.1        ad 	default:
    479  1.13        ad 		ri->ri_flg &= ~RI_CFGDONE;
    480  1.89       rin 		aprint_error("%s: depth not supported\n", __func__);
    481  1.13        ad 		splx(s);
    482  1.88       rin 		return -1;
    483   1.1        ad 	}
    484  1.30        pk 
    485  1.55      ober #if NRASOPS_ROTATION > 0
    486  1.62    nonaka 	if (ri->ri_flg & RI_ROTATE_MASK) {
    487  1.62    nonaka 		if (ri->ri_flg & RI_ROTATE_CW) {
    488  1.62    nonaka 			ri->ri_real_ops = ri->ri_ops;
    489  1.62    nonaka 			ri->ri_ops.copycols = rasops_copycols_rotated_cw;
    490  1.62    nonaka 			ri->ri_ops.copyrows = rasops_copyrows_rotated_cw;
    491  1.62    nonaka 			ri->ri_ops.erasecols = rasops_erasecols_rotated_cw;
    492  1.62    nonaka 			ri->ri_ops.eraserows = rasops_eraserows_rotated_cw;
    493  1.62    nonaka 			ri->ri_ops.putchar = rasops_putchar_rotated_cw;
    494  1.62    nonaka 		} else if (ri->ri_flg & RI_ROTATE_CCW) {
    495  1.62    nonaka 			ri->ri_real_ops = ri->ri_ops;
    496  1.62    nonaka 			ri->ri_ops.copycols = rasops_copycols_rotated_ccw;
    497  1.62    nonaka 			ri->ri_ops.copyrows = rasops_copyrows_rotated_ccw;
    498  1.62    nonaka 			ri->ri_ops.erasecols = rasops_erasecols_rotated_ccw;
    499  1.62    nonaka 			ri->ri_ops.eraserows = rasops_eraserows_rotated_ccw;
    500  1.62    nonaka 			ri->ri_ops.putchar = rasops_putchar_rotated_ccw;
    501  1.62    nonaka 		}
    502  1.55      ober 	}
    503  1.55      ober #endif
    504  1.55      ober 
    505  1.13        ad 	ri->ri_flg |= RI_CFGDONE;
    506  1.13        ad 	splx(s);
    507  1.88       rin 	return 0;
    508   1.1        ad }
    509   1.1        ad 
    510   1.1        ad /*
    511   1.1        ad  * Map a character.
    512   1.1        ad  */
    513   1.1        ad static int
    514  1.59       dsl rasops_mapchar(void *cookie, int c, u_int *cp)
    515   1.1        ad {
    516  1.89       rin 	struct rasops_info *ri = (struct rasops_info *)cookie;
    517   1.8        ad 
    518  1.88       rin 	KASSERT(ri->ri_font != NULL);
    519  1.39        ad 
    520  1.89       rin 	if ((c = wsfont_map_unichar(ri->ri_font, c)) < 0 ||
    521  1.89       rin 	    c < ri->ri_font->firstchar) {
    522  1.63  macallan 		*cp = ' ';
    523  1.88       rin 		return 0;
    524  1.35    marcus 	}
    525  1.30        pk 
    526  1.89       rin #if 0 /* XXXRO */
    527  1.89       rin 	if (CHAR_IN_FONT(c, ri->ri_font)) {
    528   1.1        ad 		*cp = ' ';
    529  1.88       rin 		return 0;
    530   1.1        ad 	}
    531  1.89       rin #endif
    532  1.30        pk 
    533   1.1        ad 	*cp = c;
    534  1.88       rin 	return 5;
    535   1.1        ad }
    536   1.1        ad 
    537   1.1        ad /*
    538   1.1        ad  * Allocate a color attribute.
    539   1.1        ad  */
    540   1.1        ad static int
    541  1.89       rin rasops_allocattr_color(void *cookie, int fg0, int bg0, int flg, long *attr)
    542   1.1        ad {
    543  1.89       rin 	uint32_t fg = fg0, bg = bg0;
    544   1.1        ad 
    545  1.89       rin 	if (__predict_false(fg >= sizeof(rasops_isgray) ||
    546  1.89       rin 	    bg >= sizeof(rasops_isgray)))
    547  1.88       rin 		return EINVAL;
    548  1.56       mjf 
    549   1.1        ad #ifdef RASOPS_CLIPPING
    550   1.1        ad 	fg &= 7;
    551   1.1        ad 	bg &= 7;
    552   1.1        ad #endif
    553  1.17        ad 	if ((flg & WSATTR_BLINK) != 0)
    554  1.88       rin 		return EINVAL;
    555  1.23  drochner 
    556  1.23  drochner 	if ((flg & WSATTR_WSCOLORS) == 0) {
    557  1.48  macallan #ifdef WS_DEFAULT_FG
    558  1.48  macallan 		fg = WS_DEFAULT_FG;
    559  1.48  macallan #else
    560  1.48  macallan 		fg = WSCOL_WHITE;
    561  1.48  macallan #endif
    562  1.48  macallan #ifdef WS_DEFAULT_BG
    563  1.48  macallan 		bg = WS_DEFAULT_BG;
    564  1.48  macallan #else
    565  1.48  macallan 		bg = WSCOL_BLACK;
    566  1.48  macallan #endif
    567  1.23  drochner 	}
    568  1.23  drochner 
    569  1.17        ad 	if ((flg & WSATTR_REVERSE) != 0) {
    570  1.89       rin 		uint32_t swap = fg;
    571   1.1        ad 		fg = bg;
    572   1.1        ad 		bg = swap;
    573   1.1        ad 	}
    574   1.1        ad 
    575  1.17        ad 	if ((flg & WSATTR_HILIT) != 0)
    576   1.1        ad 		fg += 8;
    577  1.30        pk 
    578  1.79   mlelstv 	flg = flg & WSATTR_USERMASK;
    579  1.30        pk 
    580   1.1        ad 	if (rasops_isgray[fg])
    581  1.79   mlelstv 		flg |= WSATTR_PRIVATE1;
    582   1.1        ad 
    583   1.1        ad 	if (rasops_isgray[bg])
    584  1.79   mlelstv 		flg |= WSATTR_PRIVATE2;
    585   1.1        ad 
    586   1.1        ad 	*attr = (bg << 16) | (fg << 24) | flg;
    587  1.88       rin 	return 0;
    588   1.1        ad }
    589   1.1        ad 
    590   1.1        ad /*
    591   1.1        ad  * Allocate a mono attribute.
    592   1.1        ad  */
    593   1.1        ad static int
    594  1.89       rin rasops_allocattr_mono(void *cookie, int fg0, int bg0, int flg, long *attr)
    595   1.1        ad {
    596  1.89       rin 	uint32_t fg = fg0, bg = bg0;
    597   1.1        ad 
    598  1.23  drochner 	if ((flg & (WSATTR_BLINK | WSATTR_HILIT | WSATTR_WSCOLORS)) != 0)
    599  1.88       rin 		return EINVAL;
    600  1.23  drochner 
    601  1.23  drochner 	fg = 1;
    602  1.23  drochner 	bg = 0;
    603  1.23  drochner 
    604  1.17        ad 	if ((flg & WSATTR_REVERSE) != 0) {
    605  1.89       rin 		uint32_t swap = fg;
    606   1.1        ad 		fg = bg;
    607   1.1        ad 		bg = swap;
    608   1.1        ad 	}
    609   1.1        ad 
    610   1.1        ad 	*attr = (bg << 16) | (fg << 24) | ((flg & WSATTR_UNDERLINE) ? 7 : 6);
    611  1.88       rin 	return 0;
    612   1.1        ad }
    613   1.1        ad 
    614   1.1        ad /*
    615   1.1        ad  * Copy rows.
    616   1.1        ad  */
    617   1.1        ad static void
    618  1.60       dsl rasops_copyrows(void *cookie, int src, int dst, int num)
    619   1.1        ad {
    620  1.90       rin 	struct rasops_info *ri = (struct rasops_info *)cookie;
    621  1.90       rin 	uint8_t *sp, *dp, *hp;
    622  1.90       rin 	int n;
    623  1.30        pk 
    624  1.90       rin 	hp = NULL;	/* XXX GCC */
    625   1.1        ad 
    626   1.1        ad #ifdef RASOPS_CLIPPING
    627   1.1        ad 	if (dst == src)
    628   1.1        ad 		return;
    629  1.30        pk 
    630   1.1        ad 	if (src < 0) {
    631   1.1        ad 		num += src;
    632   1.1        ad 		src = 0;
    633   1.1        ad 	}
    634   1.1        ad 
    635  1.89       rin 	if (src + num > ri->ri_rows)
    636   1.1        ad 		num = ri->ri_rows - src;
    637   1.1        ad 
    638   1.1        ad 	if (dst < 0) {
    639   1.1        ad 		num += dst;
    640   1.1        ad 		dst = 0;
    641   1.1        ad 	}
    642   1.1        ad 
    643  1.89       rin 	if (dst + num > ri->ri_rows)
    644   1.1        ad 		num = ri->ri_rows - dst;
    645  1.30        pk 
    646   1.1        ad 	if (num <= 0)
    647   1.1        ad 		return;
    648   1.1        ad #endif
    649   1.1        ad 
    650   1.1        ad 	num *= ri->ri_font->fontheight;
    651  1.90       rin 	n = ri->ri_emustride;
    652  1.30        pk 
    653  1.90       rin 	sp = ri->ri_bits + src * ri->ri_yscale;
    654  1.90       rin 	dp = ri->ri_bits + dst * ri->ri_yscale;
    655  1.90       rin 	if (ri->ri_hwbits)
    656  1.90       rin 		hp = ri->ri_hwbits + dst * ri->ri_yscale;
    657  1.30        pk 
    658  1.18        ad 	while (num--) {
    659  1.90       rin 		memmove(dp, sp, n);
    660  1.90       rin 		dp += n;
    661  1.52  jmcneill 		if (ri->ri_hwbits) {
    662  1.90       rin 			memcpy(hp, sp, n);
    663  1.90       rin 			hp += n;
    664  1.51  jmcneill 		}
    665  1.90       rin 		sp += n;
    666   1.1        ad 	}
    667   1.1        ad }
    668   1.1        ad 
    669   1.1        ad /*
    670   1.1        ad  * Copy columns. This is slow, and hard to optimize due to alignment,
    671   1.1        ad  * and the fact that we have to copy both left->right and right->left.
    672  1.43       uwe  * We simply cop-out here and use memmove(), since it handles all of
    673   1.1        ad  * these cases anyway.
    674   1.1        ad  */
    675   1.4        ad void
    676  1.60       dsl rasops_copycols(void *cookie, int row, int src, int dst, int num)
    677   1.1        ad {
    678  1.89       rin 	struct rasops_info *ri = (struct rasops_info *)cookie;
    679  1.81       rin 	uint8_t *sp, *dp, *hp;
    680   1.1        ad 	int height;
    681  1.30        pk 
    682  1.89       rin 	hp = NULL;	/* XXX GCC */
    683   1.1        ad 
    684   1.1        ad #ifdef RASOPS_CLIPPING
    685   1.1        ad 	if (dst == src)
    686   1.1        ad 		return;
    687  1.30        pk 
    688   1.3        ad 	/* Catches < 0 case too */
    689   1.3        ad 	if ((unsigned)row >= (unsigned)ri->ri_rows)
    690   1.1        ad 		return;
    691  1.30        pk 
    692   1.1        ad 	if (src < 0) {
    693   1.1        ad 		num += src;
    694   1.1        ad 		src = 0;
    695   1.1        ad 	}
    696   1.1        ad 
    697  1.89       rin 	if (src + num > ri->ri_cols)
    698   1.1        ad 		num = ri->ri_cols - src;
    699   1.1        ad 
    700   1.1        ad 	if (dst < 0) {
    701   1.1        ad 		num += dst;
    702   1.1        ad 		dst = 0;
    703   1.1        ad 	}
    704   1.1        ad 
    705  1.89       rin 	if (dst + num > ri->ri_cols)
    706   1.1        ad 		num = ri->ri_cols - dst;
    707  1.30        pk 
    708   1.1        ad 	if (num <= 0)
    709   1.1        ad 		return;
    710   1.1        ad #endif
    711  1.30        pk 
    712   1.1        ad 	num *= ri->ri_xscale;
    713   1.1        ad 	row *= ri->ri_yscale;
    714   1.1        ad 	height = ri->ri_font->fontheight;
    715  1.30        pk 
    716   1.1        ad 	sp = ri->ri_bits + row + src * ri->ri_xscale;
    717   1.1        ad 	dp = ri->ri_bits + row + dst * ri->ri_xscale;
    718  1.51  jmcneill 	if (ri->ri_hwbits)
    719  1.51  jmcneill 		hp = ri->ri_hwbits + row + dst * ri->ri_xscale;
    720  1.30        pk 
    721   1.1        ad 	while (height--) {
    722  1.43       uwe 		memmove(dp, sp, num);
    723  1.89       rin 		dp += ri->ri_stride;
    724  1.51  jmcneill 		if (ri->ri_hwbits) {
    725  1.51  jmcneill 			memcpy(hp, sp, num);
    726  1.51  jmcneill 			hp += ri->ri_stride;
    727  1.51  jmcneill 		}
    728   1.1        ad 		sp += ri->ri_stride;
    729   1.1        ad 	}
    730   1.1        ad }
    731   1.1        ad 
    732   1.1        ad /*
    733   1.1        ad  * Turn cursor off/on.
    734   1.1        ad  */
    735   1.1        ad static void
    736  1.60       dsl rasops_cursor(void *cookie, int on, int row, int col)
    737   1.1        ad {
    738  1.89       rin 	struct rasops_info *ri = (struct rasops_info *)cookie;
    739  1.30        pk 
    740   1.1        ad 	/* Turn old cursor off */
    741  1.13        ad 	if ((ri->ri_flg & RI_CURSOR) != 0)
    742  1.30        pk #ifdef RASOPS_CLIPPING
    743  1.13        ad 		if ((ri->ri_flg & RI_CURSORCLIP) == 0)
    744   1.1        ad #endif
    745   1.1        ad 			ri->ri_do_cursor(ri);
    746   1.1        ad 
    747   1.1        ad 	/* Select new cursor */
    748   1.1        ad #ifdef RASOPS_CLIPPING
    749  1.13        ad 	ri->ri_flg &= ~RI_CURSORCLIP;
    750  1.30        pk 
    751   1.1        ad 	if (row < 0 || row >= ri->ri_rows)
    752  1.13        ad 		ri->ri_flg |= RI_CURSORCLIP;
    753   1.1        ad 	else if (col < 0 || col >= ri->ri_cols)
    754  1.13        ad 		ri->ri_flg |= RI_CURSORCLIP;
    755   1.1        ad #endif
    756   1.1        ad 	ri->ri_crow = row;
    757   1.1        ad 	ri->ri_ccol = col;
    758   1.1        ad 
    759   1.1        ad 	if (on) {
    760  1.13        ad 		ri->ri_flg |= RI_CURSOR;
    761  1.30        pk #ifdef RASOPS_CLIPPING
    762  1.13        ad 		if ((ri->ri_flg & RI_CURSORCLIP) == 0)
    763   1.1        ad #endif
    764   1.1        ad 			ri->ri_do_cursor(ri);
    765  1.30        pk 	} else
    766  1.13        ad 		ri->ri_flg &= ~RI_CURSOR;
    767   1.1        ad }
    768   1.1        ad 
    769   1.1        ad /*
    770   1.1        ad  * Make the device colormap
    771   1.1        ad  */
    772   1.4        ad static void
    773  1.59       dsl rasops_init_devcmap(struct rasops_info *ri)
    774   1.1        ad {
    775  1.89       rin 	int i;
    776  1.89       rin 	uint32_t c;
    777  1.81       rin 	const uint8_t *p;
    778  1.30        pk 
    779   1.4        ad 	switch (ri->ri_depth) {
    780   1.4        ad 	case 1:
    781   1.4        ad 		ri->ri_devcmap[0] = 0;
    782   1.4        ad 		for (i = 1; i < 16; i++)
    783   1.4        ad 			ri->ri_devcmap[i] = -1;
    784   1.4        ad 		return;
    785   1.4        ad 
    786   1.4        ad 	case 2:
    787   1.4        ad 		for (i = 1; i < 15; i++)
    788  1.89       rin 			ri->ri_devcmap[i] = 0xaaaaaaaa;
    789  1.30        pk 
    790   1.4        ad 		ri->ri_devcmap[0] = 0;
    791  1.89       rin 		ri->ri_devcmap[8] = 0x55555555;
    792   1.4        ad 		ri->ri_devcmap[15] = -1;
    793   1.4        ad 		return;
    794   1.4        ad 
    795   1.4        ad 	case 8:
    796  1.68  macallan 		if ((ri->ri_flg & RI_8BIT_IS_RGB) == 0) {
    797  1.89       rin 			for (i = 0; i < 16; i++) {
    798  1.89       rin 				c = i;
    799  1.68  macallan 				ri->ri_devcmap[i] =
    800  1.89       rin 				    c | (c << 8) | (c << 16) | (c << 24);
    801  1.89       rin 			}
    802  1.68  macallan 			return;
    803  1.68  macallan 		}
    804   1.4        ad 	}
    805  1.30        pk 
    806   1.1        ad 	p = rasops_cmap;
    807  1.30        pk 
    808  1.29   nathanw 	for (i = 0; i < 16; i++) {
    809   1.1        ad 		if (ri->ri_rnum <= 8)
    810  1.89       rin 			c = (uint32_t)(*p >> (8 - ri->ri_rnum)) << ri->ri_rpos;
    811  1.30        pk 		else
    812  1.89       rin 			c = (uint32_t)(*p << (ri->ri_rnum - 8)) << ri->ri_rpos;
    813  1.29   nathanw 		p++;
    814   1.1        ad 
    815   1.1        ad 		if (ri->ri_gnum <= 8)
    816  1.89       rin 			c |= (uint32_t)(*p >> (8 - ri->ri_gnum)) << ri->ri_gpos;
    817  1.30        pk 		else
    818  1.89       rin 			c |= (uint32_t)(*p << (ri->ri_gnum - 8)) << ri->ri_gpos;
    819  1.29   nathanw 		p++;
    820   1.1        ad 
    821   1.1        ad 		if (ri->ri_bnum <= 8)
    822  1.89       rin 			c |= (uint32_t)(*p >> (8 - ri->ri_bnum)) << ri->ri_bpos;
    823  1.30        pk 		else
    824  1.89       rin 			c |= (uint32_t)(*p << (ri->ri_bnum - 8)) << ri->ri_bpos;
    825  1.29   nathanw 		p++;
    826   1.4        ad 
    827   1.4        ad 		/* Fill the word for generic routines, which want this */
    828  1.89       rin 		if (ri->ri_depth == 8) {
    829  1.89       rin 			c |= c << 8;
    830  1.89       rin 			c |= c << 16;
    831  1.89       rin 		} else if (ri->ri_depth == 15 || ri->ri_depth == 16)
    832  1.69  macallan 			c |= c << 16;
    833  1.89       rin 		else if (ri->ri_depth == 24)
    834  1.89       rin 			c |= (c & 0xff) << 24;
    835   1.1        ad 
    836   1.4        ad 		/* 24bpp does bswap on the fly. {32,16,15}bpp do it here. */
    837  1.13        ad 		if ((ri->ri_flg & RI_BSWAP) == 0)
    838   1.3        ad 			ri->ri_devcmap[i] = c;
    839  1.89       rin 		else if (ri->ri_depth == 15 || ri->ri_depth == 16)
    840  1.89       rin 			ri->ri_devcmap[i] = bswap16(c);
    841   1.4        ad 		else if (ri->ri_depth == 32)
    842   1.3        ad 			ri->ri_devcmap[i] = bswap32(c);
    843  1.89       rin 		else /* 8, 24 */
    844   1.4        ad 			ri->ri_devcmap[i] = c;
    845   1.1        ad 	}
    846   1.1        ad }
    847   1.1        ad 
    848   1.1        ad /*
    849   1.1        ad  * Unpack a rasops attribute
    850   1.1        ad  */
    851   1.1        ad void
    852  1.60       dsl rasops_unpack_attr(long attr, int *fg, int *bg, int *underline)
    853   1.1        ad {
    854  1.30        pk 
    855  1.89       rin 	*fg = ((uint32_t)attr >> 24) & 0xf;
    856  1.89       rin 	*bg = ((uint32_t)attr >> 16) & 0xf;
    857  1.25        ad 	if (underline != NULL)
    858  1.89       rin 		*underline = (uint32_t)attr & WSATTR_UNDERLINE;
    859   1.4        ad }
    860   1.4        ad 
    861   1.4        ad /*
    862   1.4        ad  * Erase rows. This isn't static, since 24-bpp uses it in special cases.
    863   1.4        ad  */
    864   1.4        ad void
    865  1.60       dsl rasops_eraserows(void *cookie, int row, int num, long attr)
    866   1.4        ad {
    867  1.90       rin 	struct rasops_info *ri = (struct rasops_info *)cookie;
    868  1.82       rin 	uint32_t *dp, *hp, clr;
    869  1.90       rin 	int n, cnt, delta;
    870  1.30        pk 
    871  1.90       rin 	hp = NULL;	/* XXX GCC */
    872   1.4        ad 
    873   1.4        ad #ifdef RASOPS_CLIPPING
    874   1.4        ad 	if (row < 0) {
    875   1.4        ad 		num += row;
    876   1.4        ad 		row = 0;
    877   1.4        ad 	}
    878   1.4        ad 
    879  1.89       rin 	if (row + num > ri->ri_rows)
    880   1.4        ad 		num = ri->ri_rows - row;
    881  1.30        pk 
    882   1.4        ad 	if (num <= 0)
    883   1.4        ad 		return;
    884   1.4        ad #endif
    885   1.4        ad 
    886  1.30        pk 	clr = ri->ri_devcmap[(attr >> 16) & 0xf];
    887   1.4        ad 
    888  1.30        pk 	/*
    889  1.20        ad 	 * XXX The wsdisplay_emulops interface seems a little deficient in
    890  1.30        pk 	 * that there is no way to clear the *entire* screen. We provide a
    891  1.30        pk 	 * workaround here: if the entire console area is being cleared, and
    892  1.13        ad 	 * the RI_FULLCLEAR flag is set, clear the entire display.
    893  1.30        pk 	 */
    894  1.13        ad 	if (num == ri->ri_rows && (ri->ri_flg & RI_FULLCLEAR) != 0) {
    895  1.90       rin 		n = ri->ri_stride >> 2;
    896  1.13        ad 		num = ri->ri_height;
    897  1.82       rin 		dp = (uint32_t *)ri->ri_origbits;
    898  1.51  jmcneill 		if (ri->ri_hwbits)
    899  1.82       rin 			hp = (uint32_t *)ri->ri_hworigbits;
    900  1.14        ad 		delta = 0;
    901  1.13        ad 	} else {
    902  1.90       rin 		n = ri->ri_emustride >> 2;
    903  1.13        ad 		num *= ri->ri_font->fontheight;
    904  1.82       rin 		dp = (uint32_t *)(ri->ri_bits + row * ri->ri_yscale);
    905  1.51  jmcneill 		if (ri->ri_hwbits)
    906  1.82       rin 			hp = (uint32_t *)(ri->ri_hwbits + row *
    907  1.51  jmcneill 			    ri->ri_yscale);
    908  1.14        ad 		delta = ri->ri_delta;
    909  1.13        ad 	}
    910  1.30        pk 
    911   1.4        ad 	while (num--) {
    912  1.90       rin 		for (cnt = n; cnt; cnt--) {
    913  1.90       rin 			*dp++ = clr;
    914  1.51  jmcneill 			if (ri->ri_hwbits)
    915  1.90       rin 				*hp++ = clr;
    916  1.30        pk 		}
    917  1.82       rin 		DELTA(dp, delta, uint32_t *);
    918  1.51  jmcneill 		if (ri->ri_hwbits)
    919  1.82       rin 			DELTA(hp, delta, uint32_t *);
    920   1.4        ad 	}
    921   1.4        ad }
    922   1.4        ad 
    923   1.4        ad /*
    924   1.4        ad  * Actually turn the cursor on or off. This does the dirty work for
    925   1.4        ad  * rasops_cursor().
    926   1.4        ad  */
    927   1.4        ad static void
    928  1.59       dsl rasops_do_cursor(struct rasops_info *ri)
    929   1.4        ad {
    930  1.84       rin 	int full, height, cnt, slop1, slop2, row, col;
    931  1.85       rin 	uint32_t tmp32, msk1, msk2;
    932  1.84       rin 	uint8_t tmp8;
    933  1.81       rin 	uint8_t *dp, *rp, *hrp, *hp;
    934  1.51  jmcneill 
    935  1.89       rin 	hrp = hp = NULL;	/* XXX GCC */
    936  1.30        pk 
    937  1.55      ober #if NRASOPS_ROTATION > 0
    938  1.62    nonaka 	if (ri->ri_flg & RI_ROTATE_MASK) {
    939  1.62    nonaka 		if (ri->ri_flg & RI_ROTATE_CW) {
    940  1.62    nonaka 			/* Rotate rows/columns */
    941  1.62    nonaka 			row = ri->ri_ccol;
    942  1.62    nonaka 			col = ri->ri_rows - ri->ri_crow - 1;
    943  1.62    nonaka 		} else if (ri->ri_flg & RI_ROTATE_CCW) {
    944  1.62    nonaka 			/* Rotate rows/columns */
    945  1.62    nonaka 			row = ri->ri_cols - ri->ri_ccol - 1;
    946  1.62    nonaka 			col = ri->ri_crow;
    947  1.62    nonaka 		} else {	/* upside-down */
    948  1.62    nonaka 			row = ri->ri_crow;
    949  1.62    nonaka 			col = ri->ri_ccol;
    950  1.62    nonaka 		}
    951  1.55      ober 	} else
    952  1.55      ober #endif
    953  1.55      ober 	{
    954  1.55      ober 		row = ri->ri_crow;
    955  1.55      ober 		col = ri->ri_ccol;
    956  1.55      ober 	}
    957  1.30        pk 
    958   1.4        ad 	rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
    959  1.51  jmcneill 	if (ri->ri_hwbits)
    960  1.51  jmcneill 		hrp = ri->ri_hwbits + row * ri->ri_yscale + col
    961  1.51  jmcneill 		    * ri->ri_xscale;
    962   1.4        ad 	height = ri->ri_font->fontheight;
    963  1.30        pk 
    964  1.80       rin 	/*
    965  1.80       rin 	 * For ri_xscale = 1:
    966  1.80       rin 	 *
    967  1.80       rin 	 * Logic below does not work for ri_xscale = 1, e.g.,
    968  1.80       rin 	 * fontwidth = 8 and bpp = 1. So we take care of it.
    969  1.80       rin 	 */
    970  1.80       rin 	if (ri->ri_xscale == 1) {
    971  1.80       rin 		while (height--) {
    972  1.84       rin 			tmp8 = ~*rp;
    973  1.80       rin 
    974  1.80       rin 			*rp = tmp8;
    975  1.80       rin 			rp += ri->ri_stride;
    976  1.30        pk 
    977  1.80       rin 			if (ri->ri_hwbits) {
    978  1.80       rin 				*hrp = tmp8;
    979  1.80       rin 				hrp += ri->ri_stride;
    980  1.80       rin 			}
    981  1.80       rin 		}
    982  1.80       rin 		return;
    983  1.80       rin 	}
    984  1.80       rin 
    985  1.80       rin 	/*
    986  1.80       rin 	 * For ri_xscale = 2, 3, 4, ...:
    987  1.80       rin 	 *
    988  1.80       rin 	 * Note that siop1 <= ri_xscale even for ri_xscale = 2,
    989  1.84       rin 	 * since rp % 3 = 0 or 2 (ri_stride % 4 = 0).
    990  1.80       rin 	 */
    991  1.80       rin 	slop1 = (4 - ((uintptr_t)rp & 3)) & 3;
    992   1.4        ad 	slop2 = (ri->ri_xscale - slop1) & 3;
    993  1.89       rin 	full = (ri->ri_xscale - slop1 /* - slop2 */) >> 2;
    994  1.30        pk 
    995  1.84       rin 	rp = (uint8_t *)((uintptr_t)rp & ~3);
    996  1.84       rin 	hrp = (uint8_t *)((uintptr_t)hrp & ~3);
    997  1.30        pk 
    998  1.87       rin 	msk1 = !slop1 ? 0 : be32toh(0xffffffffU >> (32 - (8 * slop1)));
    999  1.87       rin 	msk2 = !slop2 ? 0 : be32toh(0xffffffffU << (32 - (8 * slop2)));
   1000  1.85       rin 
   1001  1.84       rin 	while (height--) {
   1002  1.84       rin 		dp = rp;
   1003  1.84       rin 		rp += ri->ri_stride;
   1004  1.84       rin 		if (ri->ri_hwbits) {
   1005  1.84       rin 			hp = hrp;
   1006  1.84       rin 			hrp += ri->ri_stride;
   1007   1.4        ad 		}
   1008  1.78  macallan 
   1009  1.84       rin 		if (slop1) {
   1010  1.85       rin 			tmp32 = *(uint32_t *)dp ^ msk1;
   1011  1.84       rin 			*(uint32_t *)dp = tmp32;
   1012  1.84       rin 			dp += 4;
   1013  1.51  jmcneill 			if (ri->ri_hwbits) {
   1014  1.84       rin 				*(uint32_t *)hp = tmp32;
   1015  1.84       rin 				hp += 4;
   1016  1.51  jmcneill 			}
   1017  1.84       rin 		}
   1018  1.30        pk 
   1019  1.84       rin 		for (cnt = full; cnt; cnt--) {
   1020  1.84       rin 			tmp32 = ~*(uint32_t *)dp;
   1021  1.84       rin 			*(uint32_t *)dp = tmp32;
   1022  1.84       rin 			dp += 4;
   1023  1.84       rin 			if (ri->ri_hwbits) {
   1024  1.84       rin 				*(uint32_t *)hp = tmp32;
   1025  1.84       rin 				hp += 4;
   1026   1.4        ad 			}
   1027  1.84       rin 		}
   1028  1.30        pk 
   1029  1.84       rin 		if (slop2) {
   1030  1.85       rin 			tmp32 = *(uint32_t *)dp ^ msk2;
   1031  1.84       rin 			*(uint32_t *)dp = tmp32;
   1032  1.84       rin 			if (ri->ri_hwbits)
   1033  1.84       rin 				*(uint32_t *)hp = tmp32;
   1034   1.4        ad 		}
   1035   1.4        ad 	}
   1036   1.4        ad }
   1037   1.4        ad 
   1038   1.4        ad /*
   1039   1.4        ad  * Erase columns.
   1040   1.4        ad  */
   1041   1.4        ad void
   1042  1.60       dsl rasops_erasecols(void *cookie, int row, int col, int num, long attr)
   1043   1.4        ad {
   1044  1.90       rin 	struct rasops_info *ri = (struct rasops_info *)cookie;
   1045  1.90       rin 	int height, cnt, slop1, slop2, clr;
   1046  1.82       rin 	uint32_t *rp, *dp, *hrp, *hp;
   1047  1.30        pk 
   1048  1.90       rin 	hrp = hp = NULL;	/* XXX GCC */
   1049  1.30        pk 
   1050  1.30        pk #ifdef RASOPS_CLIPPING
   1051   1.4        ad 	if ((unsigned)row >= (unsigned)ri->ri_rows)
   1052   1.4        ad 		return;
   1053   1.4        ad 
   1054   1.4        ad 	if (col < 0) {
   1055   1.4        ad 		num += col;
   1056   1.4        ad 		col = 0;
   1057   1.4        ad 	}
   1058   1.4        ad 
   1059   1.4        ad 	if ((col + num) > ri->ri_cols)
   1060   1.4        ad 		num = ri->ri_cols - col;
   1061  1.30        pk 
   1062   1.4        ad 	if (num <= 0)
   1063   1.4        ad 		return;
   1064   1.4        ad #endif
   1065  1.30        pk 
   1066  1.90       rin 	num *= ri->ri_xscale;
   1067  1.82       rin 	rp = (uint32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
   1068  1.51  jmcneill 	if (ri->ri_hwbits)
   1069  1.82       rin 		hrp = (uint32_t *)(ri->ri_hwbits + row*ri->ri_yscale +
   1070  1.51  jmcneill 		    col*ri->ri_xscale);
   1071   1.4        ad 	height = ri->ri_font->fontheight;
   1072  1.30        pk 	clr = ri->ri_devcmap[(attr >> 16) & 0xf];
   1073  1.30        pk 
   1074   1.4        ad 	/* Don't bother using the full loop for <= 32 pels */
   1075   1.4        ad 	if (num <= 32) {
   1076   1.6        ad 		if (((num | ri->ri_xscale) & 3) == 0) {
   1077   1.6        ad 			/* Word aligned blt */
   1078   1.6        ad 			num >>= 2;
   1079   1.6        ad 
   1080   1.6        ad 			while (height--) {
   1081   1.6        ad 				dp = rp;
   1082  1.82       rin 				DELTA(rp, ri->ri_stride, uint32_t *);
   1083  1.51  jmcneill 				if (ri->ri_hwbits) {
   1084  1.51  jmcneill 					hp = hrp;
   1085  1.82       rin 					DELTA(hrp, ri->ri_stride, uint32_t *);
   1086  1.51  jmcneill 				}
   1087  1.30        pk 
   1088  1.51  jmcneill 				for (cnt = num; cnt; cnt--) {
   1089   1.6        ad 					*dp++ = clr;
   1090  1.51  jmcneill 					if (ri->ri_hwbits)
   1091  1.51  jmcneill 						*hp++ = clr;
   1092  1.51  jmcneill 				}
   1093   1.6        ad 			}
   1094   1.6        ad 		} else if (((num | ri->ri_xscale) & 1) == 0) {
   1095  1.30        pk 			/*
   1096   1.4        ad 			 * Halfword aligned blt. This is needed so the
   1097  1.30        pk 			 * 15/16 bit ops can use this function.
   1098   1.4        ad 			 */
   1099   1.4        ad 			num >>= 1;
   1100   1.4        ad 
   1101   1.4        ad 			while (height--) {
   1102   1.4        ad 				dp = rp;
   1103  1.82       rin 				DELTA(rp, ri->ri_stride, uint32_t *);
   1104  1.51  jmcneill 				if (ri->ri_hwbits) {
   1105  1.51  jmcneill 					hp = hrp;
   1106  1.82       rin 					DELTA(hrp, ri->ri_stride, uint32_t *);
   1107  1.51  jmcneill 				}
   1108   1.4        ad 
   1109   1.4        ad 				for (cnt = num; cnt; cnt--) {
   1110  1.82       rin 					*(uint16_t *)dp = clr;
   1111  1.82       rin 					DELTA(dp, 2, uint32_t *);
   1112  1.51  jmcneill 					if (ri->ri_hwbits) {
   1113  1.82       rin 						*(uint16_t *)hp = clr;
   1114  1.82       rin 						DELTA(hp, 2, uint32_t *);
   1115  1.51  jmcneill 					}
   1116   1.4        ad 				}
   1117   1.4        ad 			}
   1118   1.4        ad 		} else {
   1119   1.4        ad 			while (height--) {
   1120  1.90       rin 				memset(rp, clr, num);
   1121  1.82       rin 				DELTA(rp, ri->ri_stride, uint32_t *);
   1122  1.51  jmcneill 				if (ri->ri_hwbits) {
   1123  1.90       rin 					memset(hrp, clr, num);
   1124  1.82       rin 					DELTA(hrp, ri->ri_stride, uint32_t *);
   1125  1.51  jmcneill 				}
   1126   1.4        ad 			}
   1127   1.4        ad 		}
   1128  1.30        pk 
   1129   1.4        ad 		return;
   1130   1.4        ad 	}
   1131  1.30        pk 
   1132  1.90       rin 	slop1 = (4 - ((uintptr_t)rp & 3)) & 3;
   1133   1.4        ad 	slop2 = (num - slop1) & 3;
   1134  1.90       rin 	num = (num - slop1 /* - slop2 */) >> 2;
   1135   1.4        ad 
   1136   1.4        ad 	while (height--) {
   1137   1.4        ad 		dp = rp;
   1138  1.82       rin 		DELTA(rp, ri->ri_stride, uint32_t *);
   1139  1.51  jmcneill 		if (ri->ri_hwbits) {
   1140  1.51  jmcneill 			hp = hrp;
   1141  1.82       rin 			DELTA(hrp, ri->ri_stride, uint32_t *);
   1142  1.51  jmcneill 		}
   1143  1.30        pk 
   1144   1.4        ad 		/* Align span to 4 bytes */
   1145   1.4        ad 		if (slop1 & 1) {
   1146  1.81       rin 			*(uint8_t *)dp = clr;
   1147  1.82       rin 			DELTA(dp, 1, uint32_t *);
   1148  1.51  jmcneill 			if (ri->ri_hwbits) {
   1149  1.81       rin 				*(uint8_t *)hp = clr;
   1150  1.82       rin 				DELTA(hp, 1, uint32_t *);
   1151  1.51  jmcneill 			}
   1152   1.4        ad 		}
   1153   1.4        ad 
   1154   1.4        ad 		if (slop1 & 2) {
   1155  1.82       rin 			*(uint16_t *)dp = clr;
   1156  1.82       rin 			DELTA(dp, 2, uint32_t *);
   1157  1.51  jmcneill 			if (ri->ri_hwbits) {
   1158  1.82       rin 				*(uint16_t *)hp = clr;
   1159  1.82       rin 				DELTA(hp, 2, uint32_t *);
   1160  1.51  jmcneill 			}
   1161   1.4        ad 		}
   1162  1.30        pk 
   1163  1.30        pk 		/* Write 4 bytes per loop */
   1164  1.51  jmcneill 		for (cnt = num; cnt; cnt--) {
   1165   1.4        ad 			*dp++ = clr;
   1166  1.51  jmcneill 			if (ri->ri_hwbits)
   1167  1.51  jmcneill 				*hp++ = clr;
   1168  1.51  jmcneill 		}
   1169  1.30        pk 
   1170  1.30        pk 		/* Write unaligned trailing slop */
   1171   1.4        ad 		if (slop2 & 1) {
   1172  1.81       rin 			*(uint8_t *)dp = clr;
   1173  1.82       rin 			DELTA(dp, 1, uint32_t *);
   1174  1.51  jmcneill 			if (ri->ri_hwbits) {
   1175  1.81       rin 				*(uint8_t *)hp = clr;
   1176  1.82       rin 				DELTA(hp, 1, uint32_t *);
   1177  1.51  jmcneill 			}
   1178   1.4        ad 		}
   1179   1.4        ad 
   1180  1.51  jmcneill 		if (slop2 & 2) {
   1181  1.82       rin 			*(uint16_t *)dp = clr;
   1182  1.51  jmcneill 			if (ri->ri_hwbits)
   1183  1.82       rin 				*(uint16_t *)hp = clr;
   1184  1.51  jmcneill 		}
   1185   1.4        ad 	}
   1186   1.1        ad }
   1187  1.55      ober 
   1188  1.55      ober #if NRASOPS_ROTATION > 0
   1189  1.55      ober /*
   1190  1.55      ober  * Quarter clockwise rotation routines (originally intended for the
   1191  1.55      ober  * built-in Zaurus C3x00 display in 16bpp).
   1192  1.55      ober  */
   1193  1.55      ober 
   1194  1.55      ober static void
   1195  1.62    nonaka rasops_rotate_font(int *cookie, int rotate)
   1196  1.55      ober {
   1197  1.55      ober 	struct rotatedfont *f;
   1198  1.55      ober 	int ncookie;
   1199  1.55      ober 
   1200  1.55      ober 	SLIST_FOREACH(f, &rotatedfonts, rf_next) {
   1201  1.55      ober 		if (f->rf_cookie == *cookie) {
   1202  1.55      ober 			*cookie = f->rf_rotated;
   1203  1.55      ober 			return;
   1204  1.55      ober 		}
   1205  1.55      ober 	}
   1206  1.55      ober 
   1207  1.55      ober 	/*
   1208  1.55      ober 	 * We did not find a rotated version of this font. Ask the wsfont
   1209  1.55      ober 	 * code to compute one for us.
   1210  1.55      ober 	 */
   1211  1.55      ober 
   1212  1.89       rin 	f = kmem_alloc(sizeof(*f), KM_SLEEP);
   1213  1.55      ober 
   1214  1.62    nonaka 	if ((ncookie = wsfont_rotate(*cookie, rotate)) == -1)
   1215  1.89       rin 		goto fail;
   1216  1.55      ober 
   1217  1.55      ober 	f->rf_cookie = *cookie;
   1218  1.55      ober 	f->rf_rotated = ncookie;
   1219  1.55      ober 	SLIST_INSERT_HEAD(&rotatedfonts, f, rf_next);
   1220  1.55      ober 
   1221  1.55      ober 	*cookie = ncookie;
   1222  1.72  riastrad 	return;
   1223  1.72  riastrad 
   1224  1.89       rin fail:	free(f, sizeof(*f));
   1225  1.72  riastrad 	return;
   1226  1.55      ober }
   1227  1.55      ober 
   1228  1.55      ober static void
   1229  1.60       dsl rasops_copychar(void *cookie, int srcrow, int dstrow, int srccol, int dstcol)
   1230  1.55      ober {
   1231  1.89       rin 	struct rasops_info *ri = (struct rasops_info *)cookie;
   1232  1.55      ober 	int height;
   1233  1.55      ober 	int r_srcrow, r_dstrow, r_srccol, r_dstcol;
   1234  1.89       rin 	uint8_t *sp, *dp;
   1235  1.55      ober 
   1236  1.55      ober 	r_srcrow = srccol;
   1237  1.55      ober 	r_dstrow = dstcol;
   1238  1.55      ober 	r_srccol = ri->ri_rows - srcrow - 1;
   1239  1.55      ober 	r_dstcol = ri->ri_rows - dstrow - 1;
   1240  1.55      ober 
   1241  1.55      ober 	r_srcrow *= ri->ri_yscale;
   1242  1.55      ober 	r_dstrow *= ri->ri_yscale;
   1243  1.55      ober 	height = ri->ri_font->fontheight;
   1244  1.55      ober 
   1245  1.55      ober 	sp = ri->ri_bits + r_srcrow + r_srccol * ri->ri_xscale;
   1246  1.55      ober 	dp = ri->ri_bits + r_dstrow + r_dstcol * ri->ri_xscale;
   1247  1.55      ober 
   1248  1.55      ober 	while (height--) {
   1249  1.55      ober 		memmove(dp, sp, ri->ri_xscale);
   1250  1.55      ober 		dp += ri->ri_stride;
   1251  1.55      ober 		sp += ri->ri_stride;
   1252  1.55      ober 	}
   1253  1.55      ober }
   1254  1.55      ober 
   1255  1.55      ober static void
   1256  1.62    nonaka rasops_putchar_rotated_cw(void *cookie, int row, int col, u_int uc, long attr)
   1257  1.55      ober {
   1258  1.89       rin 	struct rasops_info *ri = (struct rasops_info *)cookie;
   1259  1.89       rin 	int height;
   1260  1.81       rin 	uint8_t *rp;
   1261  1.55      ober 
   1262  1.56       mjf 	if (__predict_false((unsigned int)row > ri->ri_rows ||
   1263  1.56       mjf 	    (unsigned int)col > ri->ri_cols))
   1264  1.56       mjf 		return;
   1265  1.56       mjf 
   1266  1.56       mjf 	/* Avoid underflow */
   1267  1.89       rin 	if (ri->ri_rows - row - 1 < 0)
   1268  1.56       mjf 		return;
   1269  1.56       mjf 
   1270  1.55      ober 	/* Do rotated char sans (side)underline */
   1271  1.55      ober 	ri->ri_real_ops.putchar(cookie, col, ri->ri_rows - row - 1, uc,
   1272  1.79   mlelstv 	    attr & ~WSATTR_UNDERLINE);
   1273  1.55      ober 
   1274  1.55      ober 	/* Do rotated underline */
   1275  1.55      ober 	rp = ri->ri_bits + col * ri->ri_yscale + (ri->ri_rows - row - 1) *
   1276  1.55      ober 	    ri->ri_xscale;
   1277  1.55      ober 	height = ri->ri_font->fontheight;
   1278  1.55      ober 
   1279  1.55      ober 	/* XXX this assumes 16-bit color depth */
   1280  1.79   mlelstv 	if ((attr & WSATTR_UNDERLINE) != 0) {
   1281  1.82       rin 		uint16_t c =
   1282  1.82       rin 		    (uint16_t)ri->ri_devcmap[((u_int)attr >> 24) & 0xf];
   1283  1.55      ober 
   1284  1.55      ober 		while (height--) {
   1285  1.82       rin 			*(uint16_t *)rp = c;
   1286  1.55      ober 			rp += ri->ri_stride;
   1287  1.55      ober 		}
   1288  1.55      ober 	}
   1289  1.55      ober }
   1290  1.55      ober 
   1291  1.55      ober static void
   1292  1.62    nonaka rasops_erasecols_rotated_cw(void *cookie, int row, int col, int num, long attr)
   1293  1.55      ober {
   1294  1.89       rin 	struct rasops_info *ri = (struct rasops_info *)cookie;
   1295  1.55      ober 	int i;
   1296  1.55      ober 
   1297  1.55      ober 	for (i = col; i < col + num; i++)
   1298  1.55      ober 		ri->ri_ops.putchar(cookie, row, i, ' ', attr);
   1299  1.55      ober }
   1300  1.55      ober 
   1301  1.55      ober /* XXX: these could likely be optimised somewhat. */
   1302  1.55      ober static void
   1303  1.62    nonaka rasops_copyrows_rotated_cw(void *cookie, int src, int dst, int num)
   1304  1.55      ober {
   1305  1.55      ober 	struct rasops_info *ri = (struct rasops_info *)cookie;
   1306  1.55      ober 	int col, roff;
   1307  1.55      ober 
   1308  1.55      ober 	if (src > dst)
   1309  1.55      ober 		for (roff = 0; roff < num; roff++)
   1310  1.55      ober 			for (col = 0; col < ri->ri_cols; col++)
   1311  1.55      ober 				rasops_copychar(cookie, src + roff, dst + roff,
   1312  1.55      ober 				    col, col);
   1313  1.55      ober 	else
   1314  1.55      ober 		for (roff = num - 1; roff >= 0; roff--)
   1315  1.55      ober 			for (col = 0; col < ri->ri_cols; col++)
   1316  1.55      ober 				rasops_copychar(cookie, src + roff, dst + roff,
   1317  1.55      ober 				    col, col);
   1318  1.55      ober }
   1319  1.55      ober 
   1320  1.55      ober static void
   1321  1.62    nonaka rasops_copycols_rotated_cw(void *cookie, int row, int src, int dst, int num)
   1322  1.55      ober {
   1323  1.55      ober 	int coff;
   1324  1.55      ober 
   1325  1.55      ober 	if (src > dst)
   1326  1.55      ober 		for (coff = 0; coff < num; coff++)
   1327  1.88       rin 			rasops_copychar(cookie, row, row, src + coff,
   1328  1.88       rin 			    dst + coff);
   1329  1.55      ober 	else
   1330  1.55      ober 		for (coff = num - 1; coff >= 0; coff--)
   1331  1.88       rin 			rasops_copychar(cookie, row, row, src + coff,
   1332  1.88       rin 			    dst + coff);
   1333  1.55      ober }
   1334  1.55      ober 
   1335  1.55      ober static void
   1336  1.62    nonaka rasops_eraserows_rotated_cw(void *cookie, int row, int num, long attr)
   1337  1.55      ober {
   1338  1.89       rin 	struct rasops_info *ri = (struct rasops_info *)cookie;
   1339  1.55      ober 	int col, rn;
   1340  1.55      ober 
   1341  1.55      ober 	for (rn = row; rn < row + num; rn++)
   1342  1.55      ober 		for (col = 0; col < ri->ri_cols; col++)
   1343  1.55      ober 			ri->ri_ops.putchar(cookie, rn, col, ' ', attr);
   1344  1.55      ober }
   1345  1.62    nonaka 
   1346  1.62    nonaka /*
   1347  1.62    nonaka  * Quarter counter-clockwise rotation routines (originally intended for the
   1348  1.62    nonaka  * built-in Sharp W-ZERO3 display in 16bpp).
   1349  1.62    nonaka  */
   1350  1.62    nonaka static void
   1351  1.88       rin rasops_copychar_ccw(void *cookie, int srcrow, int dstrow, int srccol,
   1352  1.88       rin     int dstcol)
   1353  1.62    nonaka {
   1354  1.89       rin 	struct rasops_info *ri = (struct rasops_info *)cookie;
   1355  1.89       rin 	int height, r_srcrow, r_dstrow, r_srccol, r_dstcol;
   1356  1.81       rin 	uint8_t *sp, *dp;
   1357  1.62    nonaka 
   1358  1.62    nonaka 	r_srcrow = ri->ri_cols - srccol - 1;
   1359  1.62    nonaka 	r_dstrow = ri->ri_cols - dstcol - 1;
   1360  1.62    nonaka 	r_srccol = srcrow;
   1361  1.62    nonaka 	r_dstcol = dstrow;
   1362  1.62    nonaka 
   1363  1.62    nonaka 	r_srcrow *= ri->ri_yscale;
   1364  1.62    nonaka 	r_dstrow *= ri->ri_yscale;
   1365  1.62    nonaka 	height = ri->ri_font->fontheight;
   1366  1.62    nonaka 
   1367  1.62    nonaka 	sp = ri->ri_bits + r_srcrow + r_srccol * ri->ri_xscale;
   1368  1.62    nonaka 	dp = ri->ri_bits + r_dstrow + r_dstcol * ri->ri_xscale;
   1369  1.62    nonaka 
   1370  1.62    nonaka 	while (height--) {
   1371  1.62    nonaka 		memmove(dp, sp, ri->ri_xscale);
   1372  1.62    nonaka 		dp += ri->ri_stride;
   1373  1.62    nonaka 		sp += ri->ri_stride;
   1374  1.62    nonaka 	}
   1375  1.62    nonaka }
   1376  1.62    nonaka 
   1377  1.62    nonaka static void
   1378  1.62    nonaka rasops_putchar_rotated_ccw(void *cookie, int row, int col, u_int uc, long attr)
   1379  1.62    nonaka {
   1380  1.89       rin 	struct rasops_info *ri = (struct rasops_info *)cookie;
   1381  1.89       rin 	int height;
   1382  1.81       rin 	uint8_t *rp;
   1383  1.62    nonaka 
   1384  1.62    nonaka 	if (__predict_false((unsigned int)row > ri->ri_rows ||
   1385  1.62    nonaka 	    (unsigned int)col > ri->ri_cols))
   1386  1.62    nonaka 		return;
   1387  1.62    nonaka 
   1388  1.62    nonaka 	/* Avoid underflow */
   1389  1.89       rin 	if (ri->ri_cols - col - 1 < 0)
   1390  1.62    nonaka 		return;
   1391  1.62    nonaka 
   1392  1.62    nonaka 	/* Do rotated char sans (side)underline */
   1393  1.62    nonaka 	ri->ri_real_ops.putchar(cookie, ri->ri_cols - col - 1, row, uc,
   1394  1.79   mlelstv 	    attr & ~WSATTR_UNDERLINE);
   1395  1.62    nonaka 
   1396  1.62    nonaka 	/* Do rotated underline */
   1397  1.62    nonaka 	rp = ri->ri_bits + (ri->ri_cols - col - 1) * ri->ri_yscale +
   1398  1.65   tsutsui 	    row * ri->ri_xscale +
   1399  1.65   tsutsui 	    (ri->ri_font->fontwidth - 1) * ri->ri_pelbytes;
   1400  1.62    nonaka 	height = ri->ri_font->fontheight;
   1401  1.62    nonaka 
   1402  1.62    nonaka 	/* XXX this assumes 16-bit color depth */
   1403  1.79   mlelstv 	if ((attr & WSATTR_UNDERLINE) != 0) {
   1404  1.82       rin 		uint16_t c =
   1405  1.82       rin 		    (uint16_t)ri->ri_devcmap[((u_int)attr >> 24) & 0xf];
   1406  1.62    nonaka 
   1407  1.62    nonaka 		while (height--) {
   1408  1.82       rin 			*(uint16_t *)rp = c;
   1409  1.62    nonaka 			rp += ri->ri_stride;
   1410  1.62    nonaka 		}
   1411  1.62    nonaka 	}
   1412  1.62    nonaka }
   1413  1.62    nonaka 
   1414  1.62    nonaka /* XXX: these could likely be optimised somewhat. */
   1415  1.62    nonaka static void
   1416  1.62    nonaka rasops_copyrows_rotated_ccw(void *cookie, int src, int dst, int num)
   1417  1.62    nonaka {
   1418  1.62    nonaka 	struct rasops_info *ri = (struct rasops_info *)cookie;
   1419  1.62    nonaka 	int col, roff;
   1420  1.62    nonaka 
   1421  1.62    nonaka 	if (src > dst)
   1422  1.62    nonaka 		for (roff = 0; roff < num; roff++)
   1423  1.62    nonaka 			for (col = 0; col < ri->ri_cols; col++)
   1424  1.62    nonaka 				rasops_copychar_ccw(cookie,
   1425  1.62    nonaka 				    src + roff, dst + roff, col, col);
   1426  1.62    nonaka 	else
   1427  1.62    nonaka 		for (roff = num - 1; roff >= 0; roff--)
   1428  1.62    nonaka 			for (col = 0; col < ri->ri_cols; col++)
   1429  1.62    nonaka 				rasops_copychar_ccw(cookie,
   1430  1.62    nonaka 				    src + roff, dst + roff, col, col);
   1431  1.62    nonaka }
   1432  1.62    nonaka 
   1433  1.62    nonaka static void
   1434  1.62    nonaka rasops_copycols_rotated_ccw(void *cookie, int row, int src, int dst, int num)
   1435  1.62    nonaka {
   1436  1.62    nonaka 	int coff;
   1437  1.62    nonaka 
   1438  1.62    nonaka 	if (src > dst)
   1439  1.62    nonaka 		for (coff = 0; coff < num; coff++)
   1440  1.62    nonaka 			rasops_copychar_ccw(cookie, row, row,
   1441  1.62    nonaka 			    src + coff, dst + coff);
   1442  1.62    nonaka 	else
   1443  1.62    nonaka 		for (coff = num - 1; coff >= 0; coff--)
   1444  1.62    nonaka 			rasops_copychar_ccw(cookie, row, row,
   1445  1.62    nonaka 			    src + coff, dst + coff);
   1446  1.62    nonaka }
   1447  1.55      ober #endif	/* NRASOPS_ROTATION */
   1448  1.63  macallan 
   1449  1.63  macallan void
   1450  1.63  macallan rasops_make_box_chars_16(struct rasops_info *ri)
   1451  1.63  macallan {
   1452  1.89       rin 	int c, i, mid;
   1453  1.63  macallan 	uint16_t vert_mask, hmask_left, hmask_right;
   1454  1.63  macallan 	uint16_t *data = (uint16_t *)ri->ri_optfont.data;
   1455  1.63  macallan 
   1456  1.89       rin 	vert_mask = 0xc000U >> ((ri->ri_font->fontwidth >> 1) - 1);
   1457  1.89       rin 	hmask_left = 0xff00U << (8 - (ri->ri_font->fontwidth >> 1));
   1458  1.88       rin 	hmask_right = hmask_left >> ((ri->ri_font->fontwidth + 1) >> 1);
   1459  1.63  macallan 	mid = (ri->ri_font->fontheight + 1) >> 1;
   1460  1.63  macallan 
   1461  1.63  macallan 	/* 0x00 would be empty anyway so don't bother */
   1462  1.63  macallan 	for (c = 1; c < 16; c++) {
   1463  1.63  macallan 		data += ri->ri_font->fontheight;
   1464  1.63  macallan 		if (c & 1) {
   1465  1.63  macallan 			/* upper segment */
   1466  1.63  macallan 			for (i = 0; i < mid; i++)
   1467  1.63  macallan 				data[i] = vert_mask;
   1468  1.63  macallan 		}
   1469  1.63  macallan 		if (c & 4) {
   1470  1.63  macallan 			/* lower segment */
   1471  1.63  macallan 			for (i = mid; i < ri->ri_font->fontheight; i++)
   1472  1.63  macallan 				data[i] = vert_mask;
   1473  1.63  macallan 		}
   1474  1.63  macallan 		if (c & 2) {
   1475  1.63  macallan 			/* right segment */
   1476  1.63  macallan 			i = ri->ri_font->fontheight >> 1;
   1477  1.63  macallan 			data[mid - 1] |= hmask_right;
   1478  1.63  macallan 			data[mid] |= hmask_right;
   1479  1.63  macallan 		}
   1480  1.63  macallan 		if (c & 8) {
   1481  1.63  macallan 			/* left segment */
   1482  1.63  macallan 			data[mid - 1] |= hmask_left;
   1483  1.63  macallan 			data[mid] |= hmask_left;
   1484  1.63  macallan 		}
   1485  1.63  macallan 	}
   1486  1.63  macallan }
   1487  1.63  macallan 
   1488  1.63  macallan void
   1489  1.63  macallan rasops_make_box_chars_8(struct rasops_info *ri)
   1490  1.63  macallan {
   1491  1.89       rin 	int c, i, mid;
   1492  1.63  macallan 	uint8_t vert_mask, hmask_left, hmask_right;
   1493  1.63  macallan 	uint8_t *data = (uint8_t *)ri->ri_optfont.data;
   1494  1.63  macallan 
   1495  1.89       rin 	vert_mask = 0xc0U >> ((ri->ri_font->fontwidth >> 1) - 1);
   1496  1.89       rin 	hmask_left = 0xf0U << (4 - (ri->ri_font->fontwidth >> 1));
   1497  1.88       rin 	hmask_right = hmask_left >> ((ri->ri_font->fontwidth + 1) >> 1);
   1498  1.63  macallan 	mid = (ri->ri_font->fontheight + 1) >> 1;
   1499  1.63  macallan 
   1500  1.63  macallan 	/* 0x00 would be empty anyway so don't bother */
   1501  1.63  macallan 	for (c = 1; c < 16; c++) {
   1502  1.63  macallan 		data += ri->ri_font->fontheight;
   1503  1.63  macallan 		if (c & 1) {
   1504  1.63  macallan 			/* upper segment */
   1505  1.63  macallan 			for (i = 0; i < mid; i++)
   1506  1.63  macallan 				data[i] = vert_mask;
   1507  1.63  macallan 		}
   1508  1.63  macallan 		if (c & 4) {
   1509  1.63  macallan 			/* lower segment */
   1510  1.63  macallan 			for (i = mid; i < ri->ri_font->fontheight; i++)
   1511  1.63  macallan 				data[i] = vert_mask;
   1512  1.63  macallan 		}
   1513  1.63  macallan 		if (c & 2) {
   1514  1.63  macallan 			/* right segment */
   1515  1.63  macallan 			i = ri->ri_font->fontheight >> 1;
   1516  1.63  macallan 			data[mid - 1] |= hmask_right;
   1517  1.63  macallan 			data[mid] |= hmask_right;
   1518  1.63  macallan 		}
   1519  1.63  macallan 		if (c & 8) {
   1520  1.63  macallan 			/* left segment */
   1521  1.63  macallan 			data[mid - 1] |= hmask_left;
   1522  1.63  macallan 			data[mid] |= hmask_left;
   1523  1.63  macallan 		}
   1524  1.63  macallan 	}
   1525  1.63  macallan }
   1526  1.63  macallan 
   1527  1.63  macallan void
   1528  1.63  macallan rasops_make_box_chars_32(struct rasops_info *ri)
   1529  1.63  macallan {
   1530  1.89       rin 	int c, i, mid;
   1531  1.63  macallan 	uint32_t vert_mask, hmask_left, hmask_right;
   1532  1.63  macallan 	uint32_t *data = (uint32_t *)ri->ri_optfont.data;
   1533  1.63  macallan 
   1534  1.88       rin 	vert_mask = 0xc0000000U >> ((ri->ri_font->fontwidth >> 1) - 1);
   1535  1.88       rin 	hmask_left = 0xffff0000U << (16 - (ri->ri_font->fontwidth >> 1));
   1536  1.88       rin 	hmask_right = hmask_left >> ((ri->ri_font->fontwidth + 1) >> 1);
   1537  1.63  macallan 	mid = (ri->ri_font->fontheight + 1) >> 1;
   1538  1.63  macallan 
   1539  1.63  macallan 	/* 0x00 would be empty anyway so don't bother */
   1540  1.63  macallan 	for (c = 1; c < 16; c++) {
   1541  1.63  macallan 		data += ri->ri_font->fontheight;
   1542  1.63  macallan 		if (c & 1) {
   1543  1.63  macallan 			/* upper segment */
   1544  1.63  macallan 			for (i = 0; i < mid; i++)
   1545  1.63  macallan 				data[i] = vert_mask;
   1546  1.63  macallan 		}
   1547  1.63  macallan 		if (c & 4) {
   1548  1.63  macallan 			/* lower segment */
   1549  1.63  macallan 			for (i = mid; i < ri->ri_font->fontheight; i++)
   1550  1.63  macallan 				data[i] = vert_mask;
   1551  1.63  macallan 		}
   1552  1.63  macallan 		if (c & 2) {
   1553  1.63  macallan 			/* right segment */
   1554  1.63  macallan 			i = ri->ri_font->fontheight >> 1;
   1555  1.63  macallan 			data[mid - 1] |= hmask_right;
   1556  1.63  macallan 			data[mid] |= hmask_right;
   1557  1.63  macallan 		}
   1558  1.63  macallan 		if (c & 8) {
   1559  1.63  macallan 			/* left segment */
   1560  1.63  macallan 			data[mid - 1] |= hmask_left;
   1561  1.63  macallan 			data[mid] |= hmask_left;
   1562  1.63  macallan 		}
   1563  1.63  macallan 	}
   1564  1.63  macallan }
   1565  1.67  macallan 
   1566  1.67  macallan void
   1567  1.67  macallan rasops_make_box_chars_alpha(struct rasops_info *ri)
   1568  1.67  macallan {
   1569  1.89       rin 	int c, i, hmid, vmid, wi, he;
   1570  1.67  macallan 	uint8_t *data = (uint8_t *)ri->ri_optfont.data;
   1571  1.67  macallan 	uint8_t *ddata;
   1572  1.67  macallan 
   1573  1.89       rin 	he = ri->ri_font->fontheight;
   1574  1.67  macallan 	wi = ri->ri_font->fontwidth;
   1575  1.67  macallan 
   1576  1.67  macallan 	vmid = (he + 1) >> 1;
   1577  1.67  macallan 	hmid = (wi + 1) >> 1;
   1578  1.67  macallan 
   1579  1.67  macallan 	/* 0x00 would be empty anyway so don't bother */
   1580  1.67  macallan 	for (c = 1; c < 16; c++) {
   1581  1.67  macallan 		data += ri->ri_fontscale;
   1582  1.67  macallan 		if (c & 1) {
   1583  1.67  macallan 			/* upper segment */
   1584  1.67  macallan 			ddata = data + hmid;
   1585  1.67  macallan 			for (i = 0; i <= vmid; i++) {
   1586  1.67  macallan 				*ddata = 0xff;
   1587  1.67  macallan 				ddata += wi;
   1588  1.67  macallan 			}
   1589  1.67  macallan 		}
   1590  1.67  macallan 		if (c & 4) {
   1591  1.67  macallan 			/* lower segment */
   1592  1.67  macallan 			ddata = data + wi * vmid + hmid;
   1593  1.67  macallan 			for (i = vmid; i < he; i++) {
   1594  1.67  macallan 				*ddata = 0xff;
   1595  1.67  macallan 				ddata += wi;
   1596  1.67  macallan 			}
   1597  1.67  macallan 		}
   1598  1.67  macallan 		if (c & 2) {
   1599  1.67  macallan 			/* right segment */
   1600  1.67  macallan 			ddata = data + wi * vmid + hmid;
   1601  1.67  macallan 			for (i = hmid; i < wi; i++) {
   1602  1.67  macallan 				*ddata = 0xff;
   1603  1.67  macallan 				ddata++;
   1604  1.67  macallan 			}
   1605  1.67  macallan 		}
   1606  1.67  macallan 		if (c & 8) {
   1607  1.67  macallan 			/* left segment */
   1608  1.67  macallan 			ddata = data + wi * vmid;
   1609  1.67  macallan 			for (i = 0; i <= hmid; i++) {
   1610  1.67  macallan 				*ddata = 0xff;
   1611  1.67  macallan 				ddata++;
   1612  1.67  macallan 			}
   1613  1.67  macallan 		}
   1614  1.67  macallan 	}
   1615  1.67  macallan }
   1616  1.75  macallan 
   1617  1.71  macallan /*
   1618  1.71  macallan  * Return a colour map appropriate for the given struct rasops_info in the
   1619  1.71  macallan  * same form used by rasops_cmap[]
   1620  1.71  macallan  * For now this is either a copy of rasops_cmap[] or an R3G3B2 map, it should
   1621  1.71  macallan  * probably be a linear ( or gamma corrected? ) ramp for higher depths.
   1622  1.71  macallan  */
   1623  1.71  macallan 
   1624  1.71  macallan int
   1625  1.71  macallan rasops_get_cmap(struct rasops_info *ri, uint8_t *palette, size_t bytes)
   1626  1.71  macallan {
   1627  1.88       rin 
   1628  1.89       rin 	if ((ri->ri_depth == 8) && ((ri->ri_flg & RI_8BIT_IS_RGB) != 0)) {
   1629  1.71  macallan 		/* generate an R3G3B2 palette */
   1630  1.71  macallan 		int i, idx = 0;
   1631  1.71  macallan 		uint8_t tmp;
   1632  1.71  macallan 
   1633  1.71  macallan 		if (bytes < 768)
   1634  1.71  macallan 			return EINVAL;
   1635  1.71  macallan 		for (i = 0; i < 256; i++) {
   1636  1.71  macallan 			tmp = i & 0xe0;
   1637  1.71  macallan 			/*
   1638  1.71  macallan 			 * replicate bits so 0xe0 maps to a red value of 0xff
   1639  1.71  macallan 			 * in order to make white look actually white
   1640  1.71  macallan 			 */
   1641  1.71  macallan 			tmp |= (tmp >> 3) | (tmp >> 6);
   1642  1.71  macallan 			palette[idx] = tmp;
   1643  1.71  macallan 			idx++;
   1644  1.71  macallan 
   1645  1.71  macallan 			tmp = (i & 0x1c) << 3;
   1646  1.71  macallan 			tmp |= (tmp >> 3) | (tmp >> 6);
   1647  1.71  macallan 			palette[idx] = tmp;
   1648  1.71  macallan 			idx++;
   1649  1.71  macallan 
   1650  1.71  macallan 			tmp = (i & 0x03) << 6;
   1651  1.71  macallan 			tmp |= tmp >> 2;
   1652  1.71  macallan 			tmp |= tmp >> 4;
   1653  1.71  macallan 			palette[idx] = tmp;
   1654  1.71  macallan 			idx++;
   1655  1.71  macallan 		}
   1656  1.88       rin 	} else
   1657  1.89       rin 		memcpy(palette, rasops_cmap, uimin(bytes, sizeof(rasops_cmap)));
   1658  1.71  macallan 	return 0;
   1659  1.71  macallan }
   1660