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