xref: /netbsd-src/sys/dev/rasops/rasops8.c (revision fad4c9f71477ae11cea2ee75ec82151ac770a534)
1 /* 	$NetBSD: rasops8.c,v 1.21 2006/02/18 13:57:33 jmcneill 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.21 2006/02/18 13:57:33 jmcneill Exp $");
41 
42 #include "opt_rasops.h"
43 
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/time.h>
47 
48 #include <dev/wscons/wsdisplayvar.h>
49 #include <dev/wscons/wsconsio.h>
50 #include <dev/rasops/rasops.h>
51 
52 static void 	rasops8_putchar(void *, int, int, u_int, long attr);
53 #ifndef RASOPS_SMALL
54 static void 	rasops8_putchar8(void *, int, int, u_int, long attr);
55 static void 	rasops8_putchar12(void *, int, int, u_int, long attr);
56 static void 	rasops8_putchar16(void *, int, int, u_int, long attr);
57 static void	rasops8_makestamp(struct rasops_info *ri, long);
58 
59 /*
60  * 4x1 stamp for optimized character blitting
61  */
62 static int32_t	stamp[16];
63 static long	stamp_attr;
64 static int	stamp_mutex;	/* XXX see note in README */
65 #endif
66 
67 /*
68  * XXX this confuses the hell out of gcc2 (not egcs) which always insists
69  * that the shift count is negative.
70  *
71  * offset = STAMP_SHIFT(fontbits, nibble #) & STAMP_MASK
72  * destination = STAMP_READ(offset)
73  */
74 #define STAMP_SHIFT(fb,n)	((n*4-2) >= 0 ? (fb)>>(n*4-2):(fb)<<-(n*4-2))
75 #define STAMP_MASK		(0xf << 2)
76 #define STAMP_READ(o)		(*(int32_t *)((caddr_t)stamp + (o)))
77 
78 /*
79  * Initialize a 'rasops_info' descriptor for this depth.
80  */
81 void
82 rasops8_init(ri)
83 	struct rasops_info *ri;
84 {
85 
86 	switch (ri->ri_font->fontwidth) {
87 #ifndef RASOPS_SMALL
88 	case 8:
89 		ri->ri_ops.putchar = rasops8_putchar8;
90 		break;
91 	case 12:
92 		ri->ri_ops.putchar = rasops8_putchar12;
93 		break;
94 	case 16:
95 		ri->ri_ops.putchar = rasops8_putchar16;
96 		break;
97 #endif /* !RASOPS_SMALL */
98 	default:
99 		ri->ri_ops.putchar = rasops8_putchar;
100 		break;
101 	}
102 }
103 
104 /*
105  * Put a single character.
106  */
107 static void
108 rasops8_putchar(cookie, row, col, uc, attr)
109 	void *cookie;
110 	int row, col;
111 	u_int uc;
112 	long attr;
113 {
114 	int width, height, cnt, fs, fb;
115 	u_char *dp, *rp, *hp, *hrp, *fr, clr[2];
116 	struct rasops_info *ri;
117 
118 	ri = (struct rasops_info *)cookie;
119 	hp = hrp = NULL;
120 
121 	if (!CHAR_IN_FONT(uc, ri->ri_font))
122 		return;
123 
124 #ifdef RASOPS_CLIPPING
125 	/* Catches 'row < 0' case too */
126 	if ((unsigned)row >= (unsigned)ri->ri_rows)
127 		return;
128 
129 	if ((unsigned)col >= (unsigned)ri->ri_cols)
130 		return;
131 #endif
132 	rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
133 	if (ri->ri_hwbits)
134 		hrp = ri->ri_hwbits + row * ri->ri_yscale + col *
135 		    ri->ri_xscale;
136 
137 	height = ri->ri_font->fontheight;
138 	width = ri->ri_font->fontwidth;
139 	clr[0] = (u_char)ri->ri_devcmap[(attr >> 16) & 0xf];
140 	clr[1] = (u_char)ri->ri_devcmap[(attr >> 24) & 0xf];
141 
142 	if (uc == ' ') {
143 		u_char c = clr[0];
144 
145 		while (height--) {
146 			dp = rp;
147 			rp += ri->ri_stride;
148 			if (ri->ri_hwbits) {
149 				hp = hrp;
150 				hrp += ri->ri_stride;
151 			}
152 
153 			for (cnt = width; cnt; cnt--) {
154 				*dp++ = c;
155 				if (ri->ri_hwbits)
156 					*hp++ = c;
157 			}
158 		}
159 	} else {
160 		uc -= ri->ri_font->firstchar;
161 		fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
162 		fs = ri->ri_font->stride;
163 
164 		while (height--) {
165 			dp = rp;
166 			if (ri->ri_hwbits)
167 				hp = hrp;
168 			fb = fr[3] | (fr[2] << 8) | (fr[1] << 16) | (fr[0] << 24);
169 			fr += fs;
170 			rp += ri->ri_stride;
171 			if (ri->ri_hwbits)
172 				hrp += ri->ri_stride;
173 
174 			for (cnt = width; cnt; cnt--) {
175 				*dp++ = clr[(fb >> 31) & 1];
176 				if (ri->ri_hwbits)
177 					*hp++ = clr[(fb >> 31) & 1];
178 				fb <<= 1;
179 			}
180 		}
181 	}
182 
183 	/* Do underline */
184 	if ((attr & 1) != 0) {
185 		u_char c = clr[1];
186 
187 		rp -= (ri->ri_stride << 1);
188 		if (ri->ri_hwbits)
189 			hrp -= (ri->ri_stride << 1);
190 
191 		while (width--) {
192 			*rp++ = c;
193 			if (ri->ri_hwbits)
194 				*hrp++ = c;
195 		}
196 	}
197 }
198 
199 #ifndef RASOPS_SMALL
200 /*
201  * Recompute the 4x1 blitting stamp.
202  */
203 static void
204 rasops8_makestamp(ri, attr)
205 	struct rasops_info *ri;
206 	long attr;
207 {
208 	int32_t fg, bg;
209 	int i;
210 
211 	fg = ri->ri_devcmap[(attr >> 24) & 0xf] & 0xff;
212 	bg = ri->ri_devcmap[(attr >> 16) & 0xf] & 0xff;
213 	stamp_attr = attr;
214 
215 	for (i = 0; i < 16; i++) {
216 #if BYTE_ORDER == BIG_ENDIAN
217 #define NEED_LITTLE_ENDIAN_STAMP RI_BSWAP
218 #else
219 #define NEED_LITTLE_ENDIAN_STAMP 0
220 #endif
221 		if ((ri->ri_flg & RI_BSWAP) == NEED_LITTLE_ENDIAN_STAMP) {
222 			/* little endian */
223 			stamp[i] = (i & 8 ? fg : bg);
224 			stamp[i] |= ((i & 4 ? fg : bg) << 8);
225 			stamp[i] |= ((i & 2 ? fg : bg) << 16);
226 			stamp[i] |= ((i & 1 ? fg : bg) << 24);
227 		} else {
228 			/* big endian */
229 			stamp[i] = (i & 1 ? fg : bg);
230 			stamp[i] |= ((i & 2 ? fg : bg) << 8);
231 			stamp[i] |= ((i & 4 ? fg : bg) << 16);
232 			stamp[i] |= ((i & 8 ? fg : bg) << 24);
233 		}
234 	}
235 }
236 
237 /*
238  * Put a single character. This is for 8-pixel wide fonts.
239  */
240 static void
241 rasops8_putchar8(cookie, row, col, uc, attr)
242 	void *cookie;
243 	int row, col;
244 	u_int uc;
245 	long attr;
246 {
247 	struct rasops_info *ri;
248 	int height, fs;
249 	int32_t *rp, *hp;
250 	u_char *fr;
251 
252 	/* Can't risk remaking the stamp if it's already in use */
253 	if (stamp_mutex++) {
254 		stamp_mutex--;
255 		rasops8_putchar(cookie, row, col, uc, attr);
256 		return;
257 	}
258 
259 	ri = (struct rasops_info *)cookie;
260 	hp = NULL;
261 
262 	if (!CHAR_IN_FONT(uc, ri->ri_font))
263 		return;
264 
265 #ifdef RASOPS_CLIPPING
266 	if ((unsigned)row >= (unsigned)ri->ri_rows) {
267 		stamp_mutex--;
268 		return;
269 	}
270 
271 	if ((unsigned)col >= (unsigned)ri->ri_cols) {
272 		stamp_mutex--;
273 		return;
274 	}
275 #endif
276 
277 	/* Recompute stamp? */
278 	if (attr != stamp_attr)
279 		rasops8_makestamp(ri, attr);
280 
281 	rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
282 	if (ri->ri_hwbits)
283 		hp = (int32_t *)(ri->ri_hwbits + row*ri->ri_yscale +
284 		    col*ri->ri_xscale);
285 	height = ri->ri_font->fontheight;
286 
287 	if (uc == ' ') {
288 		while (height--) {
289 			rp[0] = rp[1] = stamp[0];
290 			DELTA(rp, ri->ri_stride, int32_t *);
291 			if (ri->ri_hwbits) {
292 				hp[0] = hp[1] = stamp[0];
293 				DELTA(hp, ri->ri_stride, int32_t *);
294 			}
295 		}
296 	} else {
297 		uc -= ri->ri_font->firstchar;
298 		fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
299 		fs = ri->ri_font->stride;
300 
301 		while (height--) {
302 			rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
303 			rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
304 			if (ri->ri_hwbits) {
305 				hp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) &
306 				    STAMP_MASK);
307 				hp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) &
308 				    STAMP_MASK);
309 			}
310 
311 			fr += fs;
312 			DELTA(rp, ri->ri_stride, int32_t *);
313 			if (ri->ri_hwbits)
314 				DELTA(hp, ri->ri_stride, int32_t *);
315 		}
316 	}
317 
318 	/* Do underline */
319 	if ((attr & 1) != 0) {
320 		DELTA(rp, -(ri->ri_stride << 1), int32_t *);
321 		rp[0] = rp[1] = stamp[15];
322 		if (ri->ri_hwbits) {
323 			DELTA(hp, -(ri->ri_stride << 1), int32_t *);
324 			hp[0] = hp[1] = stamp[15];
325 		}
326 	}
327 
328 	stamp_mutex--;
329 }
330 
331 /*
332  * Put a single character. This is for 12-pixel wide fonts.
333  */
334 static void
335 rasops8_putchar12(cookie, row, col, uc, attr)
336 	void *cookie;
337 	int row, col;
338 	u_int uc;
339 	long attr;
340 {
341 	struct rasops_info *ri;
342 	int height, fs;
343 	int32_t *rp,  *hrp;
344 	u_char *fr;
345 
346 	/* Can't risk remaking the stamp if it's already in use */
347 	if (stamp_mutex++) {
348 		stamp_mutex--;
349 		rasops8_putchar(cookie, row, col, uc, attr);
350 		return;
351 	}
352 
353 	ri = (struct rasops_info *)cookie;
354 	hrp = NULL;
355 
356 	if (!CHAR_IN_FONT(uc, ri->ri_font))
357 	    return;
358 
359 #ifdef RASOPS_CLIPPING
360 	if ((unsigned)row >= (unsigned)ri->ri_rows) {
361 		stamp_mutex--;
362 		return;
363 	}
364 
365 	if ((unsigned)col >= (unsigned)ri->ri_cols) {
366 		stamp_mutex--;
367 		return;
368 	}
369 #endif
370 
371 	/* Recompute stamp? */
372 	if (attr != stamp_attr)
373 		rasops8_makestamp(ri, attr);
374 
375 	rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
376 	if (ri->ri_hwbits)
377 		hrp = (int32_t *)(ri->ri_hwbits + row*ri->ri_yscale +
378 		    col*ri->ri_xscale);
379 	height = ri->ri_font->fontheight;
380 
381 	if (uc == ' ') {
382 		while (height--) {
383 			int32_t c = stamp[0];
384 
385 			rp[0] = rp[1] = rp[2] = c;
386 			DELTA(rp, ri->ri_stride, int32_t *);
387 			if (ri->ri_hwbits) {
388 				hrp[0] = hrp[1] = hrp[2] = c;
389 				DELTA(hrp, ri->ri_stride, int32_t *);
390 			}
391 		}
392 	} else {
393 		uc -= ri->ri_font->firstchar;
394 		fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
395 		fs = ri->ri_font->stride;
396 
397 		while (height--) {
398 			rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
399 			rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
400 			rp[2] = STAMP_READ(STAMP_SHIFT(fr[1], 1) & STAMP_MASK);
401 			if (ri->ri_hwbits) {
402 				hrp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
403 				hrp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
404 				hrp[2] = STAMP_READ(STAMP_SHIFT(fr[1], 1) & STAMP_MASK);
405 			}
406 
407 			fr += fs;
408 			DELTA(rp, ri->ri_stride, int32_t *);
409 			if (ri->ri_hwbits)
410 				DELTA(hrp, ri->ri_stride, int32_t *);
411 		}
412 	}
413 
414 	/* Do underline */
415 	if ((attr & 1) != 0) {
416 		DELTA(rp, -(ri->ri_stride << 1), int32_t *);
417 		rp[0] = rp[1] = rp[2] = stamp[15];
418 		if (ri->ri_hwbits) {
419 			DELTA(hrp, -(ri->ri_stride << 1), int32_t *);
420 			hrp[0] = hrp[1] = hrp[2] = stamp[15];
421 		}
422 	}
423 
424 	stamp_mutex--;
425 }
426 
427 /*
428  * Put a single character. This is for 16-pixel wide fonts.
429  */
430 static void
431 rasops8_putchar16(cookie, row, col, uc, attr)
432 	void *cookie;
433 	int row, col;
434 	u_int uc;
435 	long attr;
436 {
437 	struct rasops_info *ri;
438 	int height, fs;
439 	int32_t *rp, *hrp;
440 	u_char *fr;
441 
442 	/* Can't risk remaking the stamp if it's already in use */
443 	if (stamp_mutex++) {
444 		stamp_mutex--;
445 		rasops8_putchar(cookie, row, col, uc, attr);
446 		return;
447 	}
448 
449 	ri = (struct rasops_info *)cookie;
450 	hrp = NULL;
451 
452 	if (!CHAR_IN_FONT(uc, ri->ri_font))
453 		return;
454 
455 #ifdef RASOPS_CLIPPING
456 	if ((unsigned)row >= (unsigned)ri->ri_rows) {
457 		stamp_mutex--;
458 		return;
459 	}
460 
461 	if ((unsigned)col >= (unsigned)ri->ri_cols) {
462 		stamp_mutex--;
463 		return;
464 	}
465 #endif
466 
467 	/* Recompute stamp? */
468 	if (attr != stamp_attr)
469 		rasops8_makestamp(ri, attr);
470 
471 	rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
472 	if (ri->ri_hwbits)
473 		hrp = (int32_t *)(ri->ri_hwbits + row*ri->ri_yscale +
474 		    col*ri->ri_xscale);
475 
476 	height = ri->ri_font->fontheight;
477 
478 	if (uc == ' ') {
479 		while (height--) {
480 			rp[0] = rp[1] = rp[2] = rp[3] = stamp[0];
481 			if (ri->ri_hwbits)
482 				hrp[0] = hrp[1] = hrp[2] = hrp[3] = stamp[0];
483 		}
484 	} else {
485 		uc -= ri->ri_font->firstchar;
486 		fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
487 		fs = ri->ri_font->stride;
488 
489 		while (height--) {
490 			rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
491 			rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
492 			rp[2] = STAMP_READ(STAMP_SHIFT(fr[1], 1) & STAMP_MASK);
493 			rp[3] = STAMP_READ(STAMP_SHIFT(fr[1], 0) & STAMP_MASK);
494 			if (ri->ri_hwbits) {
495 				hrp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
496 				hrp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
497 				hrp[2] = STAMP_READ(STAMP_SHIFT(fr[1], 1) & STAMP_MASK);
498 				hrp[3] = STAMP_READ(STAMP_SHIFT(fr[1], 0) & STAMP_MASK);
499 			}
500 
501 			fr += fs;
502 			DELTA(rp, ri->ri_stride, int32_t *);
503 			if (ri->ri_hwbits)
504 				DELTA(hrp, ri->ri_stride, int32_t *);
505 		}
506 	}
507 
508 	/* Do underline */
509 	if ((attr & 1) != 0) {
510 		DELTA(rp, -(ri->ri_stride << 1), int32_t *);
511 		rp[0] = rp[1] = rp[2] = rp[3] = stamp[15];
512 		if (ri->ri_hwbits) {
513 			DELTA(hrp, -(ri->ri_stride << 1), int32_t *);
514 			hrp[0] = hrp[1] = hrp[2] = hrp[3] = stamp[15];
515 		}
516 	}
517 
518 	stamp_mutex--;
519 }
520 #endif /* !RASOPS_SMALL */
521