xref: /netbsd/sys/dev/rasops/rasops8.c (revision bf9ec67e)
1 /* 	$NetBSD: rasops8.c,v 1.16 2002/02/11 20:50:58 uwe 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  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *	This product includes software developed by the NetBSD
21  *	Foundation, Inc. and its contributors.
22  * 4. Neither the name of The NetBSD Foundation nor the names of its
23  *    contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36  * POSSIBILITY OF SUCH DAMAGE.
37  */
38 
39 #include <sys/cdefs.h>
40 __KERNEL_RCSID(0, "$NetBSD: rasops8.c,v 1.16 2002/02/11 20:50:58 uwe Exp $");
41 
42 #include "opt_rasops.h"
43 
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/time.h>
47 #include <sys/bswap.h>
48 
49 #include <dev/wscons/wsdisplayvar.h>
50 #include <dev/wscons/wsconsio.h>
51 #include <dev/rasops/rasops.h>
52 
53 static void 	rasops8_putchar __P((void *, int, int, u_int, long attr));
54 #ifndef RASOPS_SMALL
55 static void 	rasops8_putchar8 __P((void *, int, int, u_int, long attr));
56 static void 	rasops8_putchar12 __P((void *, int, int, u_int, long attr));
57 static void 	rasops8_putchar16 __P((void *, int, int, u_int, long attr));
58 static void	rasops8_makestamp __P((struct rasops_info *ri, long));
59 
60 /*
61  * 4x1 stamp for optimized character blitting
62  */
63 static int32_t	stamp[16];
64 static long	stamp_attr;
65 static int	stamp_mutex;	/* XXX see note in README */
66 #endif
67 
68 /*
69  * XXX this confuses the hell out of gcc2 (not egcs) which always insists
70  * that the shift count is negative.
71  *
72  * offset = STAMP_SHIFT(fontbits, nibble #) & STAMP_MASK
73  * destination = STAMP_READ(offset)
74  */
75 #define STAMP_SHIFT(fb,n)	((n*4-2) >= 0 ? (fb)>>(n*4-2):(fb)<<-(n*4-2))
76 #define STAMP_MASK		(0xf << 2)
77 #define STAMP_READ(o)		(*(int32_t *)((caddr_t)stamp + (o)))
78 
79 /*
80  * Initialize a 'rasops_info' descriptor for this depth.
81  */
82 void
83 rasops8_init(ri)
84 	struct rasops_info *ri;
85 {
86 
87 	switch (ri->ri_font->fontwidth) {
88 #ifndef RASOPS_SMALL
89 	case 8:
90 		ri->ri_ops.putchar = rasops8_putchar8;
91 		break;
92 	case 12:
93 		ri->ri_ops.putchar = rasops8_putchar12;
94 		break;
95 	case 16:
96 		ri->ri_ops.putchar = rasops8_putchar16;
97 		break;
98 #endif /* !RASOPS_SMALL */
99 	default:
100 		ri->ri_ops.putchar = rasops8_putchar;
101 		break;
102 	}
103 }
104 
105 /*
106  * Put a single character.
107  */
108 static void
109 rasops8_putchar(cookie, row, col, uc, attr)
110 	void *cookie;
111 	int row, col;
112 	u_int uc;
113 	long attr;
114 {
115 	int width, height, cnt, fs, fb;
116 	u_char *dp, *rp, *fr, clr[2];
117 	struct rasops_info *ri;
118 
119 	ri = (struct rasops_info *)cookie;
120 
121 #ifdef RASOPS_CLIPPING
122 	/* Catches 'row < 0' case too */
123 	if ((unsigned)row >= (unsigned)ri->ri_rows)
124 		return;
125 
126 	if ((unsigned)col >= (unsigned)ri->ri_cols)
127 		return;
128 #endif
129 	rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
130 
131 	height = ri->ri_font->fontheight;
132 	width = ri->ri_font->fontwidth;
133 	clr[0] = (u_char)ri->ri_devcmap[(attr >> 16) & 0xf];
134 	clr[1] = (u_char)ri->ri_devcmap[(attr >> 24) & 0xf];
135 
136 	if (uc == ' ') {
137 		u_char c = clr[0];
138 
139 		while (height--) {
140 			dp = rp;
141 			rp += ri->ri_stride;
142 
143 			for (cnt = width; cnt; cnt--)
144 				*dp++ = c;
145 		}
146 	} else {
147 		uc -= ri->ri_font->firstchar;
148 		fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
149 		fs = ri->ri_font->stride;
150 
151 		while (height--) {
152 			dp = rp;
153 			fb = fr[3] | (fr[2] << 8) | (fr[1] << 16) | (fr[0] << 24);
154 			fr += fs;
155 			rp += ri->ri_stride;
156 
157 			for (cnt = width; cnt; cnt--) {
158 				*dp++ = clr[(fb >> 31) & 1];
159 				fb <<= 1;
160 			}
161 		}
162 	}
163 
164 	/* Do underline */
165 	if ((attr & 1) != 0) {
166 		u_char c = clr[1];
167 
168 		rp -= (ri->ri_stride << 1);
169 
170 		while (width--)
171 			*rp++ = c;
172 	}
173 }
174 
175 #ifndef RASOPS_SMALL
176 /*
177  * Recompute the 4x1 blitting stamp.
178  */
179 static void
180 rasops8_makestamp(ri, attr)
181 	struct rasops_info *ri;
182 	long attr;
183 {
184 	int32_t fg, bg;
185 	int i;
186 
187 	fg = ri->ri_devcmap[(attr >> 24) & 0xf] & 0xff;
188 	bg = ri->ri_devcmap[(attr >> 16) & 0xf] & 0xff;
189 	stamp_attr = attr;
190 
191 	for (i = 0; i < 16; i++) {
192 #if BYTE_ORDER == BIG_ENDIAN
193 #define NEED_LITTLE_ENDIAN_STAMP RI_BSWAP
194 #else
195 #define NEED_LITTLE_ENDIAN_STAMP 0
196 #endif
197 		if ((ri->ri_flg & RI_BSWAP) == NEED_LITTLE_ENDIAN_STAMP) {
198 			/* little endian */
199 			stamp[i] = (i & 8 ? fg : bg);
200 			stamp[i] |= ((i & 4 ? fg : bg) << 8);
201 			stamp[i] |= ((i & 2 ? fg : bg) << 16);
202 			stamp[i] |= ((i & 1 ? fg : bg) << 24);
203 		} else {
204 			/* big endian */
205 			stamp[i] = (i & 1 ? fg : bg);
206 			stamp[i] |= ((i & 2 ? fg : bg) << 8);
207 			stamp[i] |= ((i & 4 ? fg : bg) << 16);
208 			stamp[i] |= ((i & 8 ? fg : bg) << 24);
209 		}
210 	}
211 }
212 
213 /*
214  * Put a single character. This is for 8-pixel wide fonts.
215  */
216 static void
217 rasops8_putchar8(cookie, row, col, uc, attr)
218 	void *cookie;
219 	int row, col;
220 	u_int uc;
221 	long attr;
222 {
223 	struct rasops_info *ri;
224 	int height, fs;
225 	int32_t *rp;
226 	u_char *fr;
227 
228 	/* Can't risk remaking the stamp if it's already in use */
229 	if (stamp_mutex++) {
230 		stamp_mutex--;
231 		rasops8_putchar(cookie, row, col, uc, attr);
232 		return;
233 	}
234 
235 	ri = (struct rasops_info *)cookie;
236 
237 #ifdef RASOPS_CLIPPING
238 	if ((unsigned)row >= (unsigned)ri->ri_rows) {
239 		stamp_mutex--;
240 		return;
241 	}
242 
243 	if ((unsigned)col >= (unsigned)ri->ri_cols) {
244 		stamp_mutex--;
245 		return;
246 	}
247 #endif
248 
249 	/* Recompute stamp? */
250 	if (attr != stamp_attr)
251 		rasops8_makestamp(ri, attr);
252 
253 	rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
254 	height = ri->ri_font->fontheight;
255 
256 	if (uc == ' ') {
257 		while (height--) {
258 			rp[0] = rp[1] = stamp[0];
259 			DELTA(rp, ri->ri_stride, int32_t *);
260 		}
261 	} else {
262 		uc -= ri->ri_font->firstchar;
263 		fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
264 		fs = ri->ri_font->stride;
265 
266 		while (height--) {
267 			rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
268 			rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
269 
270 			fr += fs;
271 			DELTA(rp, ri->ri_stride, int32_t *);
272 		}
273 	}
274 
275 	/* Do underline */
276 	if ((attr & 1) != 0) {
277 		DELTA(rp, -(ri->ri_stride << 1), int32_t *);
278 		rp[0] = rp[1] = stamp[15];
279 	}
280 
281 	stamp_mutex--;
282 }
283 
284 /*
285  * Put a single character. This is for 12-pixel wide fonts.
286  */
287 static void
288 rasops8_putchar12(cookie, row, col, uc, attr)
289 	void *cookie;
290 	int row, col;
291 	u_int uc;
292 	long attr;
293 {
294 	struct rasops_info *ri;
295 	int height, fs;
296 	int32_t *rp;
297 	u_char *fr;
298 
299 	/* Can't risk remaking the stamp if it's already in use */
300 	if (stamp_mutex++) {
301 		stamp_mutex--;
302 		rasops8_putchar(cookie, row, col, uc, attr);
303 		return;
304 	}
305 
306 	ri = (struct rasops_info *)cookie;
307 
308 #ifdef RASOPS_CLIPPING
309 	if ((unsigned)row >= (unsigned)ri->ri_rows) {
310 		stamp_mutex--;
311 		return;
312 	}
313 
314 	if ((unsigned)col >= (unsigned)ri->ri_cols) {
315 		stamp_mutex--;
316 		return;
317 	}
318 #endif
319 
320 	/* Recompute stamp? */
321 	if (attr != stamp_attr)
322 		rasops8_makestamp(ri, attr);
323 
324 	rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
325 	height = ri->ri_font->fontheight;
326 
327 	if (uc == ' ') {
328 		while (height--) {
329 			int32_t c = stamp[0];
330 
331 			rp[0] = rp[1] = rp[2] = c;
332 			DELTA(rp, ri->ri_stride, int32_t *);
333 		}
334 	} else {
335 		uc -= ri->ri_font->firstchar;
336 		fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
337 		fs = ri->ri_font->stride;
338 
339 		while (height--) {
340 			rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
341 			rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
342 			rp[2] = STAMP_READ(STAMP_SHIFT(fr[1], 1) & STAMP_MASK);
343 
344 			fr += fs;
345 			DELTA(rp, ri->ri_stride, int32_t *);
346 		}
347 	}
348 
349 	/* Do underline */
350 	if ((attr & 1) != 0) {
351 		DELTA(rp, -(ri->ri_stride << 1), int32_t *);
352 		rp[0] = rp[1] = rp[2] = stamp[15];
353 	}
354 
355 	stamp_mutex--;
356 }
357 
358 /*
359  * Put a single character. This is for 16-pixel wide fonts.
360  */
361 static void
362 rasops8_putchar16(cookie, row, col, uc, attr)
363 	void *cookie;
364 	int row, col;
365 	u_int uc;
366 	long attr;
367 {
368 	struct rasops_info *ri;
369 	int height, fs;
370 	int32_t *rp;
371 	u_char *fr;
372 
373 	/* Can't risk remaking the stamp if it's already in use */
374 	if (stamp_mutex++) {
375 		stamp_mutex--;
376 		rasops8_putchar(cookie, row, col, uc, attr);
377 		return;
378 	}
379 
380 	ri = (struct rasops_info *)cookie;
381 
382 #ifdef RASOPS_CLIPPING
383 	if ((unsigned)row >= (unsigned)ri->ri_rows) {
384 		stamp_mutex--;
385 		return;
386 	}
387 
388 	if ((unsigned)col >= (unsigned)ri->ri_cols) {
389 		stamp_mutex--;
390 		return;
391 	}
392 #endif
393 
394 	/* Recompute stamp? */
395 	if (attr != stamp_attr)
396 		rasops8_makestamp(ri, attr);
397 
398 	rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
399 	height = ri->ri_font->fontheight;
400 
401 	if (uc == ' ') {
402 		while (height--)
403 			rp[0] = rp[1] = rp[2] = rp[3] = stamp[0];
404 	} else {
405 		uc -= ri->ri_font->firstchar;
406 		fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
407 		fs = ri->ri_font->stride;
408 
409 		while (height--) {
410 			rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
411 			rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
412 			rp[2] = STAMP_READ(STAMP_SHIFT(fr[1], 1) & STAMP_MASK);
413 			rp[3] = STAMP_READ(STAMP_SHIFT(fr[1], 0) & STAMP_MASK);
414 
415 			fr += fs;
416 			DELTA(rp, ri->ri_stride, int32_t *);
417 		}
418 	}
419 
420 	/* Do underline */
421 	if ((attr & 1) != 0) {
422 		DELTA(rp, -(ri->ri_stride << 1), int32_t *);
423 		rp[0] = rp[1] = rp[2] = rp[3] = stamp[15];
424 	}
425 
426 	stamp_mutex--;
427 }
428 #endif /* !RASOPS_SMALL */
429