rasops15.c revision 1.12
1/* 	$NetBSD: rasops15.c,v 1.12 2005/02/04 02:10:47 perry 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.12 2005/02/04 02:10:47 perry 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/*
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 * Initialize rasops_info struct for this colordepth.
81 */
82void
83rasops15_init(ri)
84	struct rasops_info *ri;
85{
86
87	switch (ri->ri_font->fontwidth) {
88#ifndef RASOPS_SMALL
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#endif	/* !RASOPS_SMALL */
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 * Paint a single character.
118 */
119static void
120rasops15_putchar(cookie, row, col, uc, attr)
121	void *cookie;
122	int row, col;
123	u_int uc;
124	long attr;
125{
126	int fb, width, height, cnt, clr[2];
127	struct rasops_info *ri;
128	u_char *dp, *rp, *fr;
129
130	ri = (struct rasops_info *)cookie;
131
132#ifdef RASOPS_CLIPPING
133	/* Catches 'row < 0' case too */
134	if ((unsigned)row >= (unsigned)ri->ri_rows)
135		return;
136
137	if ((unsigned)col >= (unsigned)ri->ri_cols)
138		return;
139#endif
140
141	rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
142	height = ri->ri_font->fontheight;
143	width = ri->ri_font->fontwidth;
144
145	clr[1] = ri->ri_devcmap[((u_int)attr >> 24) & 0xf];
146	clr[0] = ri->ri_devcmap[((u_int)attr >> 16) & 0xf];
147
148	if (uc == ' ') {
149		int16_t c = (int16_t)clr[0];
150		while (height--) {
151			dp = rp;
152			rp += ri->ri_stride;
153
154			for (cnt = width; cnt; cnt--) {
155				*(int16_t *)dp = c;
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) != 0) {
179		int16_t c = (int16_t)clr[1];
180		rp -= ri->ri_stride << 1;
181
182		while (width--) {
183			*(int16_t *)rp = c;
184			rp += 2;
185		}
186	}
187}
188
189#ifndef RASOPS_SMALL
190/*
191 * Recompute the (2x2)x1 blitting stamp.
192 */
193static void
194rasops15_makestamp(ri, attr)
195	struct rasops_info *ri;
196	long attr;
197{
198	int32_t fg, bg;
199	int i;
200
201	fg = ri->ri_devcmap[((u_int)attr >> 24) & 0xf] & 0xffff;
202	bg = ri->ri_devcmap[((u_int)attr >> 16) & 0xf] & 0xffff;
203	stamp_attr = attr;
204
205	for (i = 0; i < 32; i += 2) {
206#if BYTE_ORDER == LITTLE_ENDIAN
207		stamp[i] = (i & 16 ? fg : bg);
208		stamp[i] |= ((i & 8 ? fg : bg) << 16);
209		stamp[i + 1] = (i & 4 ? fg : bg);
210		stamp[i + 1] |= ((i & 2 ? fg : bg) << 16);
211#else
212		stamp[i] = (i & 2 ? fg : bg);
213		stamp[i] |= ((i & 4 ? fg : bg) << 16);
214		stamp[i + 1] = (i & 8 ? fg : bg);
215		stamp[i + 1] |= ((i & 16 ? fg : bg) << 16);
216#endif
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		int32_t c = stamp[0];
265		while (height--) {
266			rp[0] = rp[1] = rp[2] = rp[3] = c;
267			DELTA(rp, ri->ri_stride, int32_t *);
268		}
269	} else {
270		uc -= ri->ri_font->firstchar;
271		fr = (u_char *)ri->ri_font->data + uc*ri->ri_fontscale;
272		fs = ri->ri_font->stride;
273
274		while (height--) {
275			so = STAMP_SHIFT(fr[0], 1) & STAMP_MASK;
276			rp[0] = STAMP_READ(so);
277			rp[1] = STAMP_READ(so + 4);
278
279			so = STAMP_SHIFT(fr[0], 0) & STAMP_MASK;
280			rp[2] = STAMP_READ(so);
281			rp[3] = STAMP_READ(so + 4);
282
283			fr += fs;
284			DELTA(rp, ri->ri_stride, int32_t *);
285		}
286	}
287
288	/* Do underline */
289	if ((attr & 1) != 0) {
290		int32_t c = STAMP_READ(28);
291
292		DELTA(rp, -(ri->ri_stride << 1), int32_t *);
293		rp[0] = rp[1] = rp[2] = rp[3] = c;
294	}
295
296	stamp_mutex--;
297}
298
299/*
300 * Paint a single character. This is for 12-pixel wide fonts.
301 */
302static void
303rasops15_putchar12(cookie, row, col, uc, attr)
304	void *cookie;
305	int row, col;
306	u_int uc;
307	long attr;
308{
309	struct rasops_info *ri;
310	int height, so, fs;
311	int32_t *rp;
312	u_char *fr;
313
314	/* Can't risk remaking the stamp if it's already in use */
315	if (stamp_mutex++) {
316		stamp_mutex--;
317		rasops15_putchar(cookie, row, col, uc, attr);
318		return;
319	}
320
321	ri = (struct rasops_info *)cookie;
322
323#ifdef RASOPS_CLIPPING
324	if ((unsigned)row >= (unsigned)ri->ri_rows) {
325		stamp_mutex--;
326		return;
327	}
328
329	if ((unsigned)col >= (unsigned)ri->ri_cols) {
330		stamp_mutex--;
331		return;
332	}
333#endif
334
335	/* Recompute stamp? */
336	if (attr != stamp_attr)
337		rasops15_makestamp(ri, attr);
338
339	rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
340	height = ri->ri_font->fontheight;
341
342	if (uc == (u_int)-1) {
343		int32_t c = stamp[0];
344		while (height--) {
345			rp[0] = rp[1] = rp[2] = rp[3] = rp[4] = rp[5] = c;
346			DELTA(rp, ri->ri_stride, int32_t *);
347		}
348	} else {
349		uc -= ri->ri_font->firstchar;
350		fr = (u_char *)ri->ri_font->data + uc*ri->ri_fontscale;
351		fs = ri->ri_font->stride;
352
353		while (height--) {
354			so = STAMP_SHIFT(fr[0], 1) & STAMP_MASK;
355			rp[0] = STAMP_READ(so);
356			rp[1] = STAMP_READ(so + 4);
357
358			so = STAMP_SHIFT(fr[0], 0) & STAMP_MASK;
359			rp[2] = STAMP_READ(so);
360			rp[3] = STAMP_READ(so + 4);
361
362			so = STAMP_SHIFT(fr[1], 1) & STAMP_MASK;
363			rp[4] = STAMP_READ(so);
364			rp[5] = STAMP_READ(so + 4);
365
366			fr += fs;
367			DELTA(rp, ri->ri_stride, int32_t *);
368		}
369	}
370
371	/* Do underline */
372	if (attr & 1) {
373		int32_t c = STAMP_READ(28);
374
375		DELTA(rp, -(ri->ri_stride << 1), int32_t *);
376		rp[0] = rp[1] = rp[2] = rp[3] = rp[4] = rp[5] = c;
377	}
378
379	stamp_mutex--;
380}
381
382/*
383 * Paint a single character. This is for 16-pixel wide fonts.
384 */
385static void
386rasops15_putchar16(cookie, row, col, uc, attr)
387	void *cookie;
388	int row, col;
389	u_int uc;
390	long attr;
391{
392	struct rasops_info *ri;
393	int height, so, fs;
394	int32_t *rp;
395	u_char *fr;
396
397	/* Can't risk remaking the stamp if it's already in use */
398	if (stamp_mutex++) {
399		stamp_mutex--;
400		rasops15_putchar(cookie, row, col, uc, attr);
401		return;
402	}
403
404	ri = (struct rasops_info *)cookie;
405
406#ifdef RASOPS_CLIPPING
407	if ((unsigned)row >= (unsigned)ri->ri_rows) {
408		stamp_mutex--;
409		return;
410	}
411
412	if ((unsigned)col >= (unsigned)ri->ri_cols) {
413		stamp_mutex--;
414		return;
415	}
416#endif
417
418	/* Recompute stamp? */
419	if (attr != stamp_attr)
420		rasops15_makestamp(ri, attr);
421
422	rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
423	height = ri->ri_font->fontheight;
424
425	if (uc == (u_int)-1) {
426		int32_t c = stamp[0];
427		while (height--) {
428			rp[0] = rp[1] = rp[2] = rp[3] =
429			rp[4] = rp[5] = rp[6] = rp[7] = c;
430			DELTA(rp, ri->ri_stride, int32_t *);
431		}
432	} else {
433		uc -= ri->ri_font->firstchar;
434		fr = (u_char *)ri->ri_font->data + uc*ri->ri_fontscale;
435		fs = ri->ri_font->stride;
436
437		while (height--) {
438			so = STAMP_SHIFT(fr[0], 1) & STAMP_MASK;
439			rp[0] = STAMP_READ(so);
440			rp[1] = STAMP_READ(so + 4);
441
442			so = STAMP_SHIFT(fr[0], 0) & STAMP_MASK;
443			rp[2] = STAMP_READ(so);
444			rp[3] = STAMP_READ(so + 4);
445
446			so = STAMP_SHIFT(fr[1], 1) & STAMP_MASK;
447			rp[4] = STAMP_READ(so);
448			rp[5] = STAMP_READ(so + 4);
449
450			so = STAMP_SHIFT(fr[1], 0) & STAMP_MASK;
451			rp[6] = STAMP_READ(so);
452			rp[7] = STAMP_READ(so + 4);
453
454			DELTA(rp, ri->ri_stride, int32_t *);
455			fr += fs;
456		}
457	}
458
459	/* Do underline */
460	if (attr & 1) {
461		int32_t c = STAMP_READ(28);
462
463		DELTA(rp, -(ri->ri_stride << 1), int32_t *);
464		rp[0] = rp[1] = rp[2] = rp[3] =
465		rp[4] = rp[5] = rp[6] = rp[7] = c;
466	}
467
468	stamp_mutex--;
469}
470#endif	/* !RASOPS_SMALL */
471