Home | History | Annotate | Line # | Download | only in rasops
      1  1.50      rin /* 	$NetBSD: rasops24.c,v 1.50 2019/08/14 00:51:10 rin Exp $	*/
      2   1.1       ad 
      3   1.6       ad /*-
      4   1.6       ad  * Copyright (c) 1999 The NetBSD Foundation, Inc.
      5   1.1       ad  * All rights reserved.
      6   1.1       ad  *
      7   1.6       ad  * This code is derived from software contributed to The NetBSD Foundation
      8  1.13       ad  * by Andrew Doran.
      9   1.6       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.6       ad  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20   1.6       ad  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21   1.6       ad  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22   1.6       ad  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23   1.6       ad  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24   1.6       ad  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25   1.6       ad  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26   1.6       ad  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27   1.6       ad  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28   1.6       ad  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29   1.6       ad  * POSSIBILITY OF SUCH DAMAGE.
     30   1.1       ad  */
     31   1.2       ad 
     32  1.15    lukem #include <sys/cdefs.h>
     33  1.50      rin __KERNEL_RCSID(0, "$NetBSD: rasops24.c,v 1.50 2019/08/14 00:51:10 rin Exp $");
     34  1.15    lukem 
     35  1.49      rin #ifdef _KERNEL_OPT
     36   1.1       ad #include "opt_rasops.h"
     37  1.49      rin #endif
     38   1.1       ad 
     39   1.1       ad #include <sys/param.h>
     40  1.49      rin #include <sys/bswap.h>
     41   1.1       ad 
     42   1.4       ad #include <machine/endian.h>
     43   1.4       ad 
     44   1.1       ad #include <dev/wscons/wsdisplayvar.h>
     45   1.1       ad #include <dev/wscons/wsconsio.h>
     46  1.40      rin 
     47  1.40      rin #define	_RASOPS_PRIVATE
     48  1.44      rin #define	RASOPS_DEPTH	24
     49   1.1       ad #include <dev/rasops/rasops.h>
     50   1.1       ad 
     51  1.18    perry static void 	rasops24_erasecols(void *, int, int, int, long);
     52  1.18    perry static void 	rasops24_eraserows(void *, int, int, long);
     53  1.36      rin static void 	rasops24_putchar(void *, int, int, u_int, long);
     54  1.37      rin static void 	rasops24_putchar_aa(void *, int, int, u_int, long);
     55  1.43      rin static __inline void
     56  1.43      rin 		rasops24_makestamp1(struct rasops_info *, uint32_t *,
     57  1.43      rin 				    uint32_t, uint32_t, uint32_t, uint32_t);
     58   1.9       ad #ifndef RASOPS_SMALL
     59  1.36      rin static void 	rasops24_putchar8(void *, int, int, u_int, long);
     60  1.36      rin static void 	rasops24_putchar12(void *, int, int, u_int, long);
     61  1.36      rin static void 	rasops24_putchar16(void *, int, int, u_int, long);
     62  1.18    perry static void	rasops24_makestamp(struct rasops_info *, long);
     63  1.29    njoly #endif
     64   1.4       ad 
     65  1.47      rin #ifndef RASOPS_SMALL
     66  1.49      rin /* stamp for optimized character blitting */
     67  1.47      rin static uint32_t			stamp[64];
     68  1.47      rin static long			stamp_attr;
     69  1.47      rin static struct rasops_info	*stamp_ri;
     70  1.47      rin 
     71   1.4       ad /*
     72   1.4       ad  * offset = STAMP_SHIFT(fontbits, nibble #) & STAMP_MASK
     73  1.32      rin  * destination uint32_t[0] = STAMP_READ(offset)
     74  1.32      rin  * destination uint32_t[1] = STAMP_READ(offset + 4)
     75  1.32      rin  * destination uint32_t[2] = STAMP_READ(offset + 8)
     76   1.4       ad  */
     77  1.36      rin #define	STAMP_SHIFT(fb, n)	((n) ? (fb) : (fb) << 4)
     78  1.36      rin #define	STAMP_MASK		(0xf << 4)
     79  1.36      rin #define	STAMP_READ(o)		(*(uint32_t *)((uint8_t *)stamp + (o)))
     80  1.47      rin #endif
     81   1.4       ad 
     82   1.1       ad /*
     83  1.14      wiz  * Initialize rasops_info struct for this colordepth.
     84   1.1       ad  */
     85   1.1       ad void
     86  1.26      dsl rasops24_init(struct rasops_info *ri)
     87   1.1       ad {
     88   1.1       ad 
     89  1.36      rin 	if (ri->ri_rnum == 0) {
     90  1.36      rin 		ri->ri_rnum = ri->ri_gnum = ri->ri_bnum = 8;
     91  1.36      rin 
     92  1.36      rin 		ri->ri_rpos = 0;
     93  1.36      rin 		ri->ri_gpos = 8;
     94  1.36      rin 		ri->ri_bpos = 16;
     95  1.36      rin 	}
     96  1.36      rin 
     97  1.36      rin 	ri->ri_ops.erasecols = rasops24_erasecols;
     98  1.36      rin 	ri->ri_ops.eraserows = rasops24_eraserows;
     99  1.36      rin 
    100  1.37      rin 	if (FONT_IS_ALPHA(ri->ri_font)) {
    101  1.37      rin 		ri->ri_ops.putchar = rasops24_putchar_aa;
    102  1.37      rin 		return;
    103  1.37      rin 	}
    104  1.37      rin 
    105   1.1       ad 	switch (ri->ri_font->fontwidth) {
    106   1.9       ad #ifndef RASOPS_SMALL
    107   1.1       ad 	case 8:
    108   1.4       ad 		ri->ri_ops.putchar = rasops24_putchar8;
    109   1.1       ad 		break;
    110   1.1       ad 	case 12:
    111   1.4       ad 		ri->ri_ops.putchar = rasops24_putchar12;
    112   1.1       ad 		break;
    113   1.1       ad 	case 16:
    114   1.4       ad 		ri->ri_ops.putchar = rasops24_putchar16;
    115   1.1       ad 		break;
    116   1.9       ad #endif
    117   1.1       ad 	default:
    118   1.4       ad 		ri->ri_ops.putchar = rasops24_putchar;
    119  1.41      rin 		return;
    120   1.1       ad 	}
    121  1.41      rin 
    122  1.41      rin #ifndef RASOPS_SMALL
    123  1.50      rin 	stamp_attr = -1;
    124  1.47      rin 	stamp_ri = NULL;
    125  1.41      rin #endif
    126   1.1       ad }
    127   1.1       ad 
    128  1.49      rin /* rasops24_putchar */
    129  1.48      rin #undef	RASOPS_AA
    130  1.49      rin #include <dev/rasops/rasops_putchar.h>
    131  1.48      rin 
    132  1.49      rin /* rasops24_putchar_aa */
    133  1.48      rin #define	RASOPS_AA
    134  1.49      rin #include <dev/rasops/rasops_putchar.h>
    135  1.48      rin #undef	RASOPS_AA
    136   1.1       ad 
    137  1.43      rin static __inline void
    138  1.47      rin rasops24_makestamp1(struct rasops_info *ri, uint32_t *xstamp,
    139  1.43      rin     uint32_t c1, uint32_t c2, uint32_t c3, uint32_t c4)
    140  1.43      rin {
    141  1.43      rin 
    142  1.47      rin 	xstamp[0] = (c1 <<  8) | (c2 >> 16);
    143  1.47      rin 	xstamp[1] = (c2 << 16) | (c3 >>  8);
    144  1.47      rin 	xstamp[2] = (c3 << 24) |  c4;
    145  1.43      rin 
    146  1.43      rin #if BYTE_ORDER == LITTLE_ENDIAN
    147  1.43      rin 	if ((ri->ri_flg & RI_BSWAP) == 0)
    148  1.43      rin #else
    149  1.43      rin 	if ((ri->ri_flg & RI_BSWAP) != 0)
    150  1.43      rin #endif
    151  1.43      rin 	{
    152  1.47      rin 		xstamp[0] = bswap32(xstamp[0]);
    153  1.47      rin 		xstamp[1] = bswap32(xstamp[1]);
    154  1.47      rin 		xstamp[2] = bswap32(xstamp[2]);
    155  1.43      rin 	}
    156  1.43      rin }
    157  1.43      rin 
    158   1.9       ad #ifndef RASOPS_SMALL
    159   1.9       ad /*
    160   1.9       ad  * Recompute the blitting stamp.
    161   1.9       ad  */
    162   1.9       ad static void
    163  1.26      dsl rasops24_makestamp(struct rasops_info *ri, long attr)
    164   1.9       ad {
    165   1.9       ad 	int i;
    166  1.49      rin 	uint32_t bg, fg, c1, c2, c3, c4;
    167  1.12       pk 
    168  1.47      rin 	stamp_attr = attr;
    169  1.47      rin 	stamp_ri = ri;
    170  1.47      rin 
    171  1.49      rin 	bg = ATTR_BG(ri, attr) & 0xffffff;
    172  1.49      rin 	fg = ATTR_FG(ri, attr) & 0xffffff;
    173  1.12       pk 
    174   1.9       ad 	for (i = 0; i < 64; i += 4) {
    175   1.9       ad #if BYTE_ORDER == LITTLE_ENDIAN
    176  1.36      rin 		c1 = i & 32 ? fg : bg;
    177  1.36      rin 		c2 = i & 16 ? fg : bg;
    178  1.36      rin 		c3 = i &  8 ? fg : bg;
    179  1.36      rin 		c4 = i &  4 ? fg : bg;
    180   1.9       ad #else
    181  1.36      rin 		c1 = i &  8 ? fg : bg;
    182  1.36      rin 		c2 = i &  4 ? fg : bg;
    183  1.36      rin 		c3 = i & 16 ? fg : bg;
    184  1.36      rin 		c4 = i & 32 ? fg : bg;
    185   1.9       ad #endif
    186  1.43      rin 		rasops24_makestamp1(ri, &stamp[i], c1, c2, c3, c4);
    187   1.9       ad 	}
    188   1.9       ad }
    189   1.1       ad 
    190  1.49      rin /*
    191  1.49      rin  * Width-optimized putchar functions
    192  1.49      rin  */
    193  1.35      rin #define	RASOPS_WIDTH	8
    194  1.49      rin #include <dev/rasops/rasops_putchar_width.h>
    195  1.35      rin #undef	RASOPS_WIDTH
    196  1.35      rin 
    197  1.35      rin #define	RASOPS_WIDTH	12
    198  1.49      rin #include <dev/rasops/rasops_putchar_width.h>
    199  1.35      rin #undef	RASOPS_WIDTH
    200  1.35      rin 
    201  1.35      rin #define	RASOPS_WIDTH	16
    202  1.49      rin #include <dev/rasops/rasops_putchar_width.h>
    203  1.35      rin #undef	RASOPS_WIDTH
    204  1.12       pk 
    205  1.11       ad #endif	/* !RASOPS_SMALL */
    206   1.1       ad 
    207   1.1       ad /*
    208   1.4       ad  * Erase rows. This is nice and easy due to alignment.
    209   1.1       ad  */
    210   1.1       ad static void
    211  1.27      dsl rasops24_eraserows(void *cookie, int row, int num, long attr)
    212   1.1       ad {
    213  1.39      rin 	struct rasops_info *ri = (struct rasops_info *)cookie;
    214  1.49      rin 	int bytes, full, slop, cnt;
    215  1.49      rin 	uint32_t bg, xstamp[3];
    216  1.49      rin 	uint32_t *dp, *rp, *hp;
    217  1.39      rin 
    218  1.39      rin 	hp = NULL;	/* XXX GCC */
    219  1.12       pk 
    220  1.12       pk 	/*
    221   1.4       ad 	 * If the color is gray, we can cheat and use the generic routines
    222   1.4       ad 	 * (which are faster, hopefully) since the r,g,b values are the same.
    223   1.4       ad 	 */
    224  1.30  mlelstv 	if ((attr & WSATTR_PRIVATE2) != 0) {
    225   1.4       ad 		rasops_eraserows(cookie, row, num, attr);
    226   1.4       ad 		return;
    227   1.4       ad 	}
    228   1.4       ad 
    229   1.1       ad #ifdef RASOPS_CLIPPING
    230   1.1       ad 	if (row < 0) {
    231   1.1       ad 		num += row;
    232   1.1       ad 		row = 0;
    233   1.1       ad 	}
    234   1.1       ad 
    235  1.39      rin 	if (row + num > ri->ri_rows)
    236   1.1       ad 		num = ri->ri_rows - row;
    237  1.12       pk 
    238   1.1       ad 	if (num <= 0)
    239   1.1       ad 		return;
    240   1.1       ad #endif
    241  1.12       pk 
    242  1.49      rin 	bg = ATTR_BG(ri, attr) & 0xffffff;
    243  1.49      rin 	rasops24_makestamp1(ri, xstamp, bg, bg, bg, bg);
    244   1.4       ad 
    245  1.12       pk 	/*
    246   1.7       ad 	 * XXX the wsdisplay_emulops interface seems a little deficient in
    247  1.12       pk 	 * that there is no way to clear the *entire* screen. We provide a
    248  1.12       pk 	 * workaround here: if the entire console area is being cleared, and
    249   1.7       ad 	 * the RI_FULLCLEAR flag is set, clear the entire display.
    250  1.12       pk 	 */
    251   1.7       ad 	if (num == ri->ri_rows && (ri->ri_flg & RI_FULLCLEAR) != 0) {
    252  1.49      rin 		bytes = ri->ri_stride;
    253   1.7       ad 		num = ri->ri_height;
    254  1.39      rin 		rp = (uint32_t *)ri->ri_origbits;
    255  1.39      rin 		if (ri->ri_hwbits)
    256  1.39      rin 			hp = (uint32_t *)ri->ri_hworigbits;
    257   1.7       ad 	} else {
    258  1.49      rin 		bytes = ri->ri_emustride;
    259   1.7       ad 		num *= ri->ri_font->fontheight;
    260  1.39      rin 		rp = (uint32_t *)(ri->ri_bits + row * ri->ri_yscale);
    261  1.39      rin 		if (ri->ri_hwbits)
    262  1.39      rin 			hp = (uint32_t *)(ri->ri_hwbits + row * ri->ri_yscale);
    263   1.7       ad 	}
    264   1.7       ad 
    265  1.49      rin 	full = bytes / (4 * 3);
    266  1.49      rin 	slop = (bytes - full * (4 * 3)) / 4;
    267  1.12       pk 
    268  1.47      rin 	while (num--) {
    269  1.47      rin 		dp = rp;
    270  1.49      rin 
    271  1.47      rin 		for (cnt = full; cnt; cnt--) {
    272  1.47      rin 			dp[0] = xstamp[0];
    273  1.47      rin 			dp[1] = xstamp[1];
    274  1.47      rin 			dp[2] = xstamp[2];
    275  1.47      rin 			dp += 3;
    276  1.47      rin 		}
    277  1.49      rin 
    278  1.47      rin 		for (cnt = 0; cnt < slop; cnt++)
    279  1.47      rin 			*dp++ = xstamp[cnt];
    280   1.1       ad 
    281  1.39      rin 		if (ri->ri_hwbits) {
    282  1.49      rin 			memcpy(hp, rp, bytes);
    283  1.39      rin 			DELTA(hp, ri->ri_stride, uint32_t *);
    284  1.39      rin 		}
    285  1.47      rin 
    286  1.47      rin 		DELTA(rp, ri->ri_stride, uint32_t *);
    287   1.4       ad 	}
    288   1.4       ad }
    289   1.4       ad 
    290   1.4       ad /*
    291   1.4       ad  * Erase columns.
    292   1.4       ad  */
    293   1.4       ad static void
    294  1.27      dsl rasops24_erasecols(void *cookie, int row, int col, int num, long attr)
    295   1.4       ad {
    296  1.39      rin 	struct rasops_info *ri = (struct rasops_info *)cookie;
    297  1.49      rin 	int height, slop1, slop2, full, cnt;
    298  1.49      rin 	uint32_t bg, xstamp[3];
    299  1.49      rin 	uint32_t *dp;
    300  1.49      rin 	uint8_t *bp, *rp, *hp;
    301  1.39      rin 
    302  1.39      rin 	hp = NULL;	/* XXX GCC */
    303   1.4       ad 
    304  1.12       pk 	/*
    305   1.4       ad 	 * If the color is gray, we can cheat and use the generic routines
    306   1.4       ad 	 * (which are faster, hopefully) since the r,g,b values are the same.
    307   1.4       ad 	 */
    308  1.30  mlelstv 	if ((attr & WSATTR_PRIVATE2) != 0) {
    309   1.4       ad 		rasops_erasecols(cookie, row, col, num, attr);
    310   1.4       ad 		return;
    311   1.4       ad 	}
    312  1.12       pk 
    313  1.12       pk #ifdef RASOPS_CLIPPING
    314  1.12       pk 	/* Catches 'row < 0' case too */
    315   1.4       ad 	if ((unsigned)row >= (unsigned)ri->ri_rows)
    316   1.4       ad 		return;
    317   1.4       ad 
    318   1.4       ad 	if (col < 0) {
    319   1.4       ad 		num += col;
    320   1.4       ad 		col = 0;
    321   1.4       ad 	}
    322   1.4       ad 
    323  1.39      rin 	if (col + num > ri->ri_cols)
    324   1.4       ad 		num = ri->ri_cols - col;
    325  1.12       pk 
    326   1.4       ad 	if (num <= 0)
    327   1.4       ad 		return;
    328   1.4       ad #endif
    329  1.12       pk 
    330  1.49      rin 	height = ri->ri_font->fontheight;
    331  1.49      rin 	num *= ri->ri_xscale;
    332  1.49      rin 
    333  1.39      rin 	rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
    334  1.39      rin 	if (ri->ri_hwbits)
    335  1.39      rin 		hp = ri->ri_hwbits + row * ri->ri_yscale + col * ri->ri_xscale;
    336  1.39      rin 
    337  1.49      rin 	bg = ATTR_BG(ri, attr) & 0xffffff;
    338  1.49      rin 	rasops24_makestamp1(ri, xstamp, bg, bg, bg, bg);
    339  1.12       pk 
    340  1.47      rin 	/*
    341  1.47      rin 	 * Align to word boundary by 24-bit-wise operations:
    342  1.47      rin 	 *
    343  1.47      rin 	 * rp % 4 == 1 ---> slop1 = 3:
    344  1.47      rin 	 *	0123
    345  1.47      rin 	 *	-RGB
    346  1.47      rin 	 *
    347  1.47      rin 	 * rp % 4 == 2 ---> slop1 = 6:
    348  1.47      rin 	 *	0123 0123
    349  1.47      rin 	 *	--RG BRGB
    350  1.47      rin 	 *
    351  1.47      rin 	 * rp % 4 == 3 ---> slop1 = 9:
    352  1.47      rin 	 *	0123 0123 0123
    353  1.47      rin 	 *	---R GBRG BRGB
    354  1.47      rin 	 */
    355  1.47      rin 	slop1 = 3 * ((uintptr_t)rp % 4);
    356  1.47      rin 	slop2 = (num - slop1) % 12;
    357  1.47      rin 	full = (num - slop1 /* - slop2 */) / 12;
    358  1.47      rin 
    359  1.47      rin 	while (height--) {
    360  1.47      rin 		/* Align to word boundary */
    361  1.49      rin 		bp = rp;
    362  1.47      rin 		for (cnt = slop1; cnt; cnt -= 3) {
    363  1.49      rin 			*bp++ = (bg >> 16);
    364  1.49      rin 			*bp++ = (bg >> 8);
    365  1.49      rin 			*bp++ = bg;
    366  1.47      rin 		}
    367  1.47      rin 
    368  1.47      rin 		/* 4 pels per loop */
    369  1.49      rin 		dp = (uint32_t *)bp;
    370  1.47      rin 		for (cnt = full; cnt; cnt--) {
    371  1.47      rin 			dp[0] = xstamp[0];
    372  1.47      rin 			dp[1] = xstamp[1];
    373  1.47      rin 			dp[2] = xstamp[2];
    374  1.47      rin 			dp += 3;
    375  1.47      rin 		}
    376   1.4       ad 
    377  1.47      rin 		/* Trailing slop */
    378  1.49      rin 		bp = (uint8_t *)dp;
    379  1.47      rin 		for (cnt = slop2; cnt; cnt -= 3) {
    380  1.49      rin 			*bp++ = (bg >> 16);
    381  1.49      rin 			*bp++ = (bg >> 8);
    382  1.49      rin 			*bp++ = bg;
    383  1.47      rin 		}
    384  1.39      rin 
    385  1.39      rin 		if (ri->ri_hwbits) {
    386  1.47      rin 			memcpy(hp, rp, num);
    387  1.39      rin 			hp += ri->ri_stride;
    388  1.12       pk 		}
    389  1.47      rin 
    390  1.47      rin 		rp += ri->ri_stride;
    391   1.1       ad 	}
    392   1.1       ad }
    393