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