rasops15.c revision 1.14
1/* 	$NetBSD: rasops15.c,v 1.14 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: rasops15.c,v 1.14 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
52static void 	rasops15_putchar(void *, int, int, u_int, long attr);
53#ifndef RASOPS_SMALL
54static void 	rasops15_putchar8(void *, int, int, u_int, long attr);
55static void 	rasops15_putchar12(void *, int, int, u_int, long attr);
56static void 	rasops15_putchar16(void *, int, int, u_int, long attr);
57static void	rasops15_makestamp(struct rasops_info *, long);
58#endif
59
60#ifndef RASOPS_SMALL
61/*
62 * (2x2)x1 stamp for optimized character blitting
63 */
64static int32_t	stamp[32];
65static long	stamp_attr;
66static int	stamp_mutex;	/* XXX see note in readme */
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 int32_t[0] = STAMP_READ(offset)
74 * destination int32_t[1] = STAMP_READ(offset + 4)
75 */
76#define STAMP_SHIFT(fb,n)	((n*4-3) >= 0 ? (fb)>>(n*4-3):(fb)<<-(n*4-3))
77#define STAMP_MASK		(15 << 3)
78#define STAMP_READ(o)		(*(int32_t *)((caddr_t)stamp + (o)))
79#endif
80
81/*
82 * Initialize rasops_info struct for this colordepth.
83 */
84void
85rasops15_init(ri)
86	struct rasops_info *ri;
87{
88
89	switch (ri->ri_font->fontwidth) {
90#ifndef RASOPS_SMALL
91	case 8:
92		ri->ri_ops.putchar = rasops15_putchar8;
93		break;
94
95	case 12:
96		ri->ri_ops.putchar = rasops15_putchar12;
97		break;
98
99	case 16:
100		ri->ri_ops.putchar = rasops15_putchar16;
101		break;
102#endif	/* !RASOPS_SMALL */
103	default:
104		ri->ri_ops.putchar = rasops15_putchar;
105		break;
106	}
107
108	if (ri->ri_rnum == 0) {
109		ri->ri_rnum = 5;
110		ri->ri_rpos = 0;
111		ri->ri_gnum = 5 + (ri->ri_depth == 16);
112		ri->ri_gpos = 5;
113		ri->ri_bnum = 5;
114		ri->ri_bpos = 10 + (ri->ri_depth == 16);
115	}
116}
117
118/*
119 * Paint a single character.
120 */
121static void
122rasops15_putchar(cookie, row, col, uc, attr)
123	void *cookie;
124	int row, col;
125	u_int uc;
126	long attr;
127{
128	int fb, width, height, cnt, clr[2];
129	struct rasops_info *ri;
130	u_char *dp, *rp, *hp, *hrp, *fr;
131
132	ri = (struct rasops_info *)cookie;
133	hp = hrp = NULL;
134
135#ifdef RASOPS_CLIPPING
136	/* Catches 'row < 0' case too */
137	if ((unsigned)row >= (unsigned)ri->ri_rows)
138		return;
139
140	if ((unsigned)col >= (unsigned)ri->ri_cols)
141		return;
142#endif
143
144	rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
145	if (ri->ri_hwbits)
146		hrp = ri->ri_hwbits + row * ri->ri_yscale +
147		    col * ri->ri_xscale;
148	height = ri->ri_font->fontheight;
149	width = ri->ri_font->fontwidth;
150
151	clr[1] = ri->ri_devcmap[((u_int)attr >> 24) & 0xf];
152	clr[0] = ri->ri_devcmap[((u_int)attr >> 16) & 0xf];
153
154	if (uc == ' ') {
155		int16_t c = (int16_t)clr[0];
156		while (height--) {
157			dp = rp;
158			rp += ri->ri_stride;
159			if (ri->ri_hwbits) {
160				hp = hrp;
161				hrp += ri->ri_stride;
162			}
163
164			for (cnt = width; cnt; cnt--) {
165				*(int16_t *)dp = c;
166				dp += 2;
167				if (ri->ri_hwbits) {
168					*(int16_t *)hp = c;
169					hp += 2;
170				}
171			}
172		}
173	} else {
174		uc -= ri->ri_font->firstchar;
175		fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
176
177		while (height--) {
178			dp = rp;
179			fb = fr[3] | (fr[2] << 8) | (fr[1] << 16) | (fr[0] << 24);
180			fr += ri->ri_font->stride;
181			rp += ri->ri_stride;
182			if (ri->ri_hwbits) {
183				hp = hrp;
184				hrp += ri->ri_stride;
185			}
186
187			for (cnt = width; cnt; cnt--) {
188				*(int16_t *)dp = (int16_t)clr[(fb >> 31) & 1];
189				if (ri->ri_hwbits)
190					*(int16_t *)hp =
191					    (int16_t)clr[(fb >> 31) & 1];
192				fb <<= 1;
193				dp += 2;
194				if (ri->ri_hwbits)
195					hp += 2;
196			}
197		}
198	}
199
200	/* Do underline */
201	if ((attr & 1) != 0) {
202		int16_t c = (int16_t)clr[1];
203		rp -= ri->ri_stride << 1;
204		if (ri->ri_hwbits)
205			hrp -= ri->ri_stride << 1;
206
207		while (width--) {
208			*(int16_t *)rp = c;
209			rp += 2;
210			if (ri->ri_hwbits) {
211				*(int16_t *)hrp = c;
212				hrp += 2;
213			}
214		}
215	}
216}
217
218#ifndef RASOPS_SMALL
219/*
220 * Recompute the (2x2)x1 blitting stamp.
221 */
222static void
223rasops15_makestamp(ri, attr)
224	struct rasops_info *ri;
225	long attr;
226{
227	int32_t fg, bg;
228	int i;
229
230	fg = ri->ri_devcmap[((u_int)attr >> 24) & 0xf] & 0xffff;
231	bg = ri->ri_devcmap[((u_int)attr >> 16) & 0xf] & 0xffff;
232	stamp_attr = attr;
233
234	for (i = 0; i < 32; i += 2) {
235#if BYTE_ORDER == LITTLE_ENDIAN
236		stamp[i] = (i & 16 ? fg : bg);
237		stamp[i] |= ((i & 8 ? fg : bg) << 16);
238		stamp[i + 1] = (i & 4 ? fg : bg);
239		stamp[i + 1] |= ((i & 2 ? fg : bg) << 16);
240#else
241		stamp[i] = (i & 2 ? fg : bg);
242		stamp[i] |= ((i & 4 ? fg : bg) << 16);
243		stamp[i + 1] = (i & 8 ? fg : bg);
244		stamp[i + 1] |= ((i & 16 ? fg : bg) << 16);
245#endif
246	}
247}
248
249/*
250 * Paint a single character. This is for 8-pixel wide fonts.
251 */
252static void
253rasops15_putchar8(cookie, row, col, uc, attr)
254	void *cookie;
255	int row, col;
256	u_int uc;
257	long attr;
258{
259	struct rasops_info *ri;
260	int height, so, fs;
261	int32_t *rp, *hrp;
262	u_char *fr;
263
264	/* Can't risk remaking the stamp if it's already in use */
265	if (stamp_mutex++) {
266		stamp_mutex--;
267		rasops15_putchar(cookie, row, col, uc, attr);
268		return;
269	}
270
271	ri = (struct rasops_info *)cookie;
272	hrp = NULL;
273
274#ifdef RASOPS_CLIPPING
275	if ((unsigned)row >= (unsigned)ri->ri_rows) {
276		stamp_mutex--;
277		return;
278	}
279
280	if ((unsigned)col >= (unsigned)ri->ri_cols) {
281		stamp_mutex--;
282		return;
283	}
284#endif
285
286	/* Recompute stamp? */
287	if (attr != stamp_attr)
288		rasops15_makestamp(ri, attr);
289
290	rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
291	if (ri->ri_hwbits)
292		hrp = (int32_t *)(ri->ri_hwbits + row*ri->ri_yscale +
293		    col*ri->ri_xscale);
294	height = ri->ri_font->fontheight;
295
296	if (uc == (u_int)-1) {
297		int32_t c = stamp[0];
298		while (height--) {
299			rp[0] = rp[1] = rp[2] = rp[3] = c;
300			DELTA(rp, ri->ri_stride, int32_t *);
301			if (ri->ri_hwbits) {
302				hrp[0] = hrp[1] = hrp[2] = hrp[3] = c;
303				DELTA(hrp, ri->ri_stride, int32_t *);
304			}
305		}
306	} else {
307		uc -= ri->ri_font->firstchar;
308		fr = (u_char *)ri->ri_font->data + uc*ri->ri_fontscale;
309		fs = ri->ri_font->stride;
310
311		while (height--) {
312			so = STAMP_SHIFT(fr[0], 1) & STAMP_MASK;
313			rp[0] = STAMP_READ(so);
314			rp[1] = STAMP_READ(so + 4);
315			if (ri->ri_hwbits) {
316				hrp[0] = STAMP_READ(so);
317				hrp[1] = STAMP_READ(so + 4);
318			}
319
320			so = STAMP_SHIFT(fr[0], 0) & STAMP_MASK;
321			rp[2] = STAMP_READ(so);
322			rp[3] = STAMP_READ(so + 4);
323			if (ri->ri_hwbits) {
324				hrp[2] = STAMP_READ(so);
325				hrp[3] = STAMP_READ(so + 4);
326			}
327
328			fr += fs;
329			DELTA(rp, ri->ri_stride, int32_t *);
330			if (ri->ri_hwbits)
331				DELTA(hrp, ri->ri_stride, int32_t *);
332		}
333	}
334
335	/* Do underline */
336	if ((attr & 1) != 0) {
337		int32_t c = STAMP_READ(28);
338
339		DELTA(rp, -(ri->ri_stride << 1), int32_t *);
340		rp[0] = rp[1] = rp[2] = rp[3] = c;
341		if (ri->ri_hwbits) {
342			DELTA(hrp, -(ri->ri_stride << 1), int32_t *);
343			hrp[0] = hrp[1] = hrp[2] = hrp[3] = c;
344		}
345	}
346
347	stamp_mutex--;
348}
349
350/*
351 * Paint a single character. This is for 12-pixel wide fonts.
352 */
353static void
354rasops15_putchar12(cookie, row, col, uc, attr)
355	void *cookie;
356	int row, col;
357	u_int uc;
358	long attr;
359{
360	struct rasops_info *ri;
361	int height, so, fs;
362	int32_t *rp, *hrp;
363	u_char *fr;
364
365	/* Can't risk remaking the stamp if it's already in use */
366	if (stamp_mutex++) {
367		stamp_mutex--;
368		rasops15_putchar(cookie, row, col, uc, attr);
369		return;
370	}
371
372	ri = (struct rasops_info *)cookie;
373	hrp = NULL;
374
375#ifdef RASOPS_CLIPPING
376	if ((unsigned)row >= (unsigned)ri->ri_rows) {
377		stamp_mutex--;
378		return;
379	}
380
381	if ((unsigned)col >= (unsigned)ri->ri_cols) {
382		stamp_mutex--;
383		return;
384	}
385#endif
386
387	/* Recompute stamp? */
388	if (attr != stamp_attr)
389		rasops15_makestamp(ri, attr);
390
391	rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
392	if (ri->ri_hwbits)
393		hrp = (int32_t *)(ri->ri_hwbits + row*ri->ri_yscale +
394		    col*ri->ri_xscale);
395	height = ri->ri_font->fontheight;
396
397	if (uc == (u_int)-1) {
398		int32_t c = stamp[0];
399		while (height--) {
400			rp[0] = rp[1] = rp[2] = rp[3] = rp[4] = rp[5] = c;
401			DELTA(rp, ri->ri_stride, int32_t *);
402			if (ri->ri_hwbits) {
403				hrp[0] = hrp[1] = hrp[2] = hrp[3] = hrp[4] =
404				    hrp[5] = c;
405				DELTA(hrp, ri->ri_stride, int32_t *);
406			}
407		}
408	} else {
409		uc -= ri->ri_font->firstchar;
410		fr = (u_char *)ri->ri_font->data + uc*ri->ri_fontscale;
411		fs = ri->ri_font->stride;
412
413		while (height--) {
414			so = STAMP_SHIFT(fr[0], 1) & STAMP_MASK;
415			rp[0] = STAMP_READ(so);
416			rp[1] = STAMP_READ(so + 4);
417			if (ri->ri_hwbits) {
418				hrp[0] = STAMP_READ(so);
419				hrp[1] = STAMP_READ(so + 4);
420			}
421
422			so = STAMP_SHIFT(fr[0], 0) & STAMP_MASK;
423			rp[2] = STAMP_READ(so);
424			rp[3] = STAMP_READ(so + 4);
425			if (ri->ri_hwbits) {
426				hrp[2] = STAMP_READ(so);
427				hrp[3] = STAMP_READ(so + 4);
428			}
429
430			so = STAMP_SHIFT(fr[1], 1) & STAMP_MASK;
431			rp[4] = STAMP_READ(so);
432			rp[5] = STAMP_READ(so + 4);
433			if (ri->ri_hwbits) {
434				hrp[4] = STAMP_READ(so);
435				hrp[5] = STAMP_READ(so + 4);
436			}
437
438			fr += fs;
439			DELTA(rp, ri->ri_stride, int32_t *);
440			if (ri->ri_hwbits)
441				DELTA(hrp, ri->ri_stride, int32_t *);
442		}
443	}
444
445	/* Do underline */
446	if (attr & 1) {
447		int32_t c = STAMP_READ(28);
448
449		DELTA(rp, -(ri->ri_stride << 1), int32_t *);
450		rp[0] = rp[1] = rp[2] = rp[3] = rp[4] = rp[5] = c;
451		if (ri->ri_hwbits) {
452			DELTA(hrp, -(ri->ri_stride << 1), int32_t *);
453			hrp[0] = hrp[1] = hrp[2] = hrp[3] = hrp[4] = hrp[5] = c;
454		}
455	}
456
457	stamp_mutex--;
458}
459
460/*
461 * Paint a single character. This is for 16-pixel wide fonts.
462 */
463static void
464rasops15_putchar16(cookie, row, col, uc, attr)
465	void *cookie;
466	int row, col;
467	u_int uc;
468	long attr;
469{
470	struct rasops_info *ri;
471	int height, so, fs;
472	int32_t *rp, *hrp;
473	u_char *fr;
474
475	/* Can't risk remaking the stamp if it's already in use */
476	if (stamp_mutex++) {
477		stamp_mutex--;
478		rasops15_putchar(cookie, row, col, uc, attr);
479		return;
480	}
481
482	ri = (struct rasops_info *)cookie;
483	hrp = NULL;
484
485#ifdef RASOPS_CLIPPING
486	if ((unsigned)row >= (unsigned)ri->ri_rows) {
487		stamp_mutex--;
488		return;
489	}
490
491	if ((unsigned)col >= (unsigned)ri->ri_cols) {
492		stamp_mutex--;
493		return;
494	}
495#endif
496
497	/* Recompute stamp? */
498	if (attr != stamp_attr)
499		rasops15_makestamp(ri, attr);
500
501	rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
502	if (ri->ri_hwbits)
503		hrp = (int32_t *)(ri->ri_hwbits + row*ri->ri_yscale +
504		    col*ri->ri_xscale);
505	height = ri->ri_font->fontheight;
506
507	if (uc == (u_int)-1) {
508		int32_t c = stamp[0];
509		while (height--) {
510			rp[0] = rp[1] = rp[2] = rp[3] =
511			rp[4] = rp[5] = rp[6] = rp[7] = c;
512			DELTA(rp, ri->ri_stride, int32_t *);
513			if (ri->ri_hwbits) {
514				hrp[0] = hrp[1] = hrp[2] = hrp[3] =
515				hrp[4] = hrp[5] = hrp[6] = hrp[7] = c;
516				DELTA(hrp, ri->ri_stride, int32_t *);
517			}
518		}
519	} else {
520		uc -= ri->ri_font->firstchar;
521		fr = (u_char *)ri->ri_font->data + uc*ri->ri_fontscale;
522		fs = ri->ri_font->stride;
523
524		while (height--) {
525			so = STAMP_SHIFT(fr[0], 1) & STAMP_MASK;
526			rp[0] = STAMP_READ(so);
527			rp[1] = STAMP_READ(so + 4);
528			if (ri->ri_hwbits) {
529				hrp[0] = STAMP_READ(so);
530				hrp[1] = STAMP_READ(so + 4);
531			}
532
533			so = STAMP_SHIFT(fr[0], 0) & STAMP_MASK;
534			rp[2] = STAMP_READ(so);
535			rp[3] = STAMP_READ(so + 4);
536			if (ri->ri_hwbits) {
537				hrp[2] = STAMP_READ(so);
538				hrp[3] = STAMP_READ(so + 4);
539			}
540
541			so = STAMP_SHIFT(fr[1], 1) & STAMP_MASK;
542			rp[4] = STAMP_READ(so);
543			rp[5] = STAMP_READ(so + 4);
544			if (ri->ri_hwbits) {
545				hrp[4] = STAMP_READ(so);
546				hrp[5] = STAMP_READ(so + 4);
547			}
548
549			so = STAMP_SHIFT(fr[1], 0) & STAMP_MASK;
550			rp[6] = STAMP_READ(so);
551			rp[7] = STAMP_READ(so + 4);
552			if (ri->ri_hwbits) {
553				hrp[6] = STAMP_READ(so);
554				hrp[7] = STAMP_READ(so + 4);
555			}
556
557			DELTA(rp, ri->ri_stride, int32_t *);
558			if (ri->ri_hwbits)
559				DELTA(hrp, ri->ri_stride, int32_t *);
560			fr += fs;
561		}
562	}
563
564	/* Do underline */
565	if (attr & 1) {
566		int32_t c = STAMP_READ(28);
567
568		DELTA(rp, -(ri->ri_stride << 1), int32_t *);
569		rp[0] = rp[1] = rp[2] = rp[3] =
570		rp[4] = rp[5] = rp[6] = rp[7] = c;
571		if (ri->ri_hwbits) {
572			DELTA(hrp, -(ri->ri_stride << 1), int32_t *);
573			hrp[0] = hrp[1] = hrp[2] = hrp[3] =
574			hrp[4] = hrp[5] = hrp[6] = hrp[7] = c;
575		}
576	}
577
578	stamp_mutex--;
579}
580#endif	/* !RASOPS_SMALL */
581