1/* 	$NetBSD: rasops4.c,v 1.28 2019/08/14 00:51:10 rin Exp $	*/
2
3/*-
4 * Copyright (c) 1999 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Andrew Doran.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32#include <sys/cdefs.h>
33__KERNEL_RCSID(0, "$NetBSD: rasops4.c,v 1.28 2019/08/14 00:51:10 rin Exp $");
34
35#ifdef _KERNEL_OPT
36#include "opt_rasops.h"
37#endif
38
39#include <sys/param.h>
40
41#include <machine/endian.h>
42
43#include <dev/wscons/wsdisplayvar.h>
44#include <dev/wscons/wsconsio.h>
45
46#define	_RASOPS_PRIVATE
47#define	RASOPS_DEPTH	4
48#include <dev/rasops/rasops.h>
49#include <dev/rasops/rasops_masks.h>
50
51static void	rasops4_copycols(void *, int, int, int, int);
52static void	rasops4_erasecols(void *, int, int, int, long);
53static void	rasops4_do_cursor(struct rasops_info *);
54static void	rasops4_putchar(void *, int, int col, u_int, long);
55#ifndef RASOPS_SMALL
56static void	rasops4_putchar8(void *, int, int col, u_int, long);
57static void	rasops4_putchar12(void *, int, int col, u_int, long);
58static void	rasops4_putchar16(void *, int, int col, u_int, long);
59static void	rasops4_makestamp(struct rasops_info *, long);
60#endif
61
62#ifndef RASOPS_SMALL
63/* stamp for optimized character blitting */
64static uint16_t			stamp[16];
65static long			stamp_attr;
66static struct rasops_info	*stamp_ri;
67
68/*
69 * offset = STAMP_SHIFT(fontbits, nibble #) & STAMP_MASK
70 * destination = STAMP_READ(offset)
71 */
72#define STAMP_SHIFT(fb, n)	((n) ? (fb) >> 4 : (fb))
73#define STAMP_MASK		0xf
74#define STAMP_READ(o)		stamp[o]
75#endif
76
77/*
78 * Initialize rasops_info struct for this colordepth.
79 */
80void
81rasops4_init(struct rasops_info *ri)
82{
83
84	if ((ri->ri_font->fontwidth & 1) != 0) {
85		ri->ri_ops.erasecols = rasops4_erasecols;
86		ri->ri_ops.copycols = rasops4_copycols;
87		ri->ri_do_cursor = rasops4_do_cursor;
88	}
89
90	switch (ri->ri_font->fontwidth) {
91#ifndef RASOPS_SMALL
92	case 8:
93		ri->ri_ops.putchar = rasops4_putchar8;
94		break;
95	case 12:
96		ri->ri_ops.putchar = rasops4_putchar12;
97		break;
98	case 16:
99		ri->ri_ops.putchar = rasops4_putchar16;
100		break;
101#endif	/* !RASOPS_SMALL */
102	default:
103		ri->ri_ops.putchar = rasops4_putchar;
104		return;
105	}
106
107#ifndef RASOPS_SMALL
108	stamp_attr = -1;
109	stamp_ri = NULL;
110#endif
111}
112
113#ifndef RASOPS_SMALL
114/*
115 * Recompute the blitting stamp.
116 */
117static void
118rasops4_makestamp(struct rasops_info *ri, long attr)
119{
120	int i;
121	uint32_t bg, fg;
122
123	stamp_attr = attr;
124	stamp_ri = ri;
125
126	bg = ATTR_BG(ri, attr) & 0xf;
127	fg = ATTR_FG(ri, attr) & 0xf;
128
129	for (i = 0; i < 16; i++) {
130#if BYTE_ORDER == LITTLE_ENDIAN
131		if ((ri->ri_flg & RI_BSWAP) == 0)
132#else
133		if ((ri->ri_flg & RI_BSWAP) != 0)
134#endif
135		{
136			/* little endian */
137			stamp[i]  = (i & 1 ? fg : bg) << 12;
138			stamp[i] |= (i & 2 ? fg : bg) << 8;
139			stamp[i] |= (i & 4 ? fg : bg) << 4;
140			stamp[i] |= (i & 8 ? fg : bg) << 0;
141		} else {
142			/* big endian */
143			stamp[i]  = (i & 1 ? fg : bg) << 0;
144			stamp[i] |= (i & 2 ? fg : bg) << 4;
145			stamp[i] |= (i & 4 ? fg : bg) << 8;
146			stamp[i] |= (i & 8 ? fg : bg) << 12;
147		}
148	}
149}
150
151/*
152 * Width-optimized putchar functions
153 */
154#define	RASOPS_WIDTH	8
155#include <dev/rasops/rasops_putchar_width.h>
156#undef	RASOPS_WIDTH
157
158#define	RASOPS_WIDTH	12
159#include <dev/rasops/rasops_putchar_width.h>
160#undef	RASOPS_WIDTH
161
162#define	RASOPS_WIDTH	16
163#include <dev/rasops/rasops_putchar_width.h>
164#undef	RASOPS_WIDTH
165
166#endif	/* !RASOPS_SMALL */
167
168/* rasops4_putchar */
169#undef	RASOPS_AA
170#include <dev/rasops/rasops1-4_putchar.h>
171
172/*
173 * Grab routines common to depths where (bpp < 8)
174 */
175#include <dev/rasops/rasops_bitops.h>
176