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