rasops2.c revision 1.9
1/* 	$NetBSD: rasops2.c,v 1.9 2001/11/15 09:48:14 lukem 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: rasops2.c,v 1.9 2001/11/15 09:48:14 lukem Exp $");
41
42#include "opt_rasops.h"
43
44#include <sys/param.h>
45#include <sys/systm.h>
46#include <sys/time.h>
47#include <machine/endian.h>
48
49#include <dev/wscons/wsdisplayvar.h>
50#include <dev/wscons/wsconsio.h>
51#include <dev/rasops/rasops.h>
52#include <dev/rasops/rasops_masks.h>
53
54static void	rasops2_copycols __P((void *, int, int, int, int));
55static void	rasops2_erasecols __P((void *, int, int, int, long));
56static void	rasops2_do_cursor __P((struct rasops_info *));
57static void	rasops2_putchar __P((void *, int, int col, u_int, long));
58#ifndef RASOPS_SMALL
59static void	rasops2_putchar8 __P((void *, int, int col, u_int, long));
60static void	rasops2_putchar12 __P((void *, int, int col, u_int, long));
61static void	rasops2_putchar16 __P((void *, int, int col, u_int, long));
62static void	rasops2_makestamp __P((struct rasops_info *, long));
63
64/*
65 * 4x1 stamp for optimized character blitting
66 */
67static int8_t	stamp[16];
68static long	stamp_attr;
69static int	stamp_mutex;	/* XXX see note in README */
70#endif
71
72/*
73 * Initialize rasops_info struct for this colordepth.
74 */
75void
76rasops2_init(ri)
77	struct rasops_info *ri;
78{
79
80	switch (ri->ri_font->fontwidth) {
81#ifndef RASOPS_SMALL
82	case 8:
83		ri->ri_ops.putchar = rasops2_putchar8;
84		break;
85	case 12:
86		ri->ri_ops.putchar = rasops2_putchar12;
87		break;
88	case 16:
89		ri->ri_ops.putchar = rasops2_putchar16;
90		break;
91#endif	/* !RASOPS_SMALL */
92	default:
93		panic("fontwidth not 8/12/16 or RASOPS_SMALL - fixme!");
94		ri->ri_ops.putchar = rasops2_putchar;
95		break;
96	}
97
98	if ((ri->ri_font->fontwidth & 3) != 0) {
99		ri->ri_ops.erasecols = rasops2_erasecols;
100		ri->ri_ops.copycols = rasops2_copycols;
101		ri->ri_do_cursor = rasops2_do_cursor;
102	}
103}
104
105#ifdef notyet
106/*
107 * Paint a single character. This is the generic version, this is ugly.
108 */
109static void
110rasops2_putchar(cookie, row, col, uc, attr)
111	void *cookie;
112	int row, col;
113	u_int uc;
114	long attr;
115{
116	int height, width, fs, rs, fb, bg, fg, lmask, rmask;
117	struct rasops_info *ri;
118	int32_t *rp;
119	u_char *fr;
120
121	ri = (struct rasops_info *)cookie;
122
123#ifdef RASOPS_CLIPPING
124	/* Catches 'row < 0' case too */
125	if ((unsigned)row >= (unsigned)ri->ri_rows)
126		return;
127
128	if ((unsigned)col >= (unsigned)ri->ri_cols)
129		return;
130#endif
131
132	width = ri->ri_font->fontwidth << 1;
133	height = ri->ri_font->fontheight;
134	col *= width;
135	rp = (int32_t *)(ri->ri_bits + row * ri->ri_yscale + ((col >> 3) & ~3));
136	col = col & 31;
137	rs = ri->ri_stride;
138
139	bg = ri->ri_devcmap[(attr >> 16) & 0xf];
140	fg = ri->ri_devcmap[(attr >> 24) & 0xf];
141
142	/* If fg and bg match this becomes a space character */
143	if (fg == bg || uc == ' ') {
144		uc = (u_int)-1;
145		fr = 0;		/* shutup gcc */
146		fs = 0;		/* shutup gcc */
147	} else {
148		uc -= ri->ri_font->firstchar;
149		fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
150		fs = ri->ri_font->stride;
151	}
152
153	/* Single word, one mask */
154	if ((col + width) <= 32) {
155		rmask = rasops_pmask[col][width];
156		lmask = ~rmask;
157
158		if (uc == (u_int)-1) {
159			bg &= rmask;
160
161			while (height--) {
162				*rp = (*rp & lmask) | bg;
163				DELTA(rp, rs, int32_t *);
164			}
165		} else {
166			while (height--) {
167				/* get bits, mask */
168				/* compose sl */
169				/* mask sl */
170				/* put word */
171			}
172		}
173
174		/* Do underline */
175		if (attr & 1) {
176			DELTA(rp, -(ri->ri_stride << 1), int32_t *);
177			*rp = (*rp & lmask) | (fg & rmask);
178		}
179	} else {
180		lmask = ~rasops_lmask[col];
181		rmask = ~rasops_rmask[(col + width) & 31];
182
183		if (uc == (u_int)-1) {
184			bg = bg & ~lmask;
185			width = bg & ~rmask;
186
187			while (height--) {
188				rp[0] = (rp[0] & lmask) | bg;
189				rp[1] = (rp[1] & rmask) | width;
190				DELTA(rp, rs, int32_t *);
191			}
192		} else {
193			width = 32 - col;
194
195			/* NOT fontbits if bg is white */
196			while (height--) {
197				fb = ~(fr[3] | (fr[2] << 8) |
198				    (fr[1] << 16) | (fr[0] << 24));
199
200				rp[0] = (rp[0] & lmask)
201				    | MBE((u_int)fb >> col);
202
203				rp[1] = (rp[1] & rmask)
204				   | (MBE((u_int)fb << width) & ~rmask);
205
206				fr += fs;
207				DELTA(rp, rs, int32_t *);
208			}
209		}
210
211		/* Do underline */
212		if (attr & 1) {
213			DELTA(rp, -(ri->ri_stride << 1), int32_t *);
214			rp[0] = (rp[0] & lmask) | (fg & ~lmask);
215			rp[1] = (rp[1] & rmask) | (fg & ~rmask);
216		}
217	}
218}
219#endif
220
221/*
222 * Put a single character. This is the generic version.
223 */
224static void
225rasops2_putchar(cookie, row, col, uc, attr)
226	void *cookie;
227	int row, col;
228	u_int uc;
229	long attr;
230{
231
232	/* XXX punt */
233}
234
235#ifndef RASOPS_SMALL
236/*
237 * Recompute the blitting stamp.
238 */
239static void
240rasops2_makestamp(ri, attr)
241	struct rasops_info *ri;
242	long attr;
243{
244	int i, fg, bg;
245
246	fg = ri->ri_devcmap[(attr >> 24) & 0xf] & 3;
247	bg = ri->ri_devcmap[(attr >> 16) & 0xf] & 3;
248	stamp_attr = attr;
249
250	for (i = 0; i < 16; i++) {
251		stamp[i] = (i & 1 ? fg : bg);
252		stamp[i] |= (i & 2 ? fg : bg) << 2;
253		stamp[i] |= (i & 4 ? fg : bg) << 4;
254		stamp[i] |= (i & 8 ? fg : bg) << 6;
255	}
256}
257
258/*
259 * Put a single character. This is for 8-pixel wide fonts.
260 */
261static void
262rasops2_putchar8(cookie, row, col, uc, attr)
263	void *cookie;
264	int row, col;
265	u_int uc;
266	long attr;
267{
268	struct rasops_info *ri;
269	int height, fs, rs;
270	u_char *fr, *rp;
271
272	/* Can't risk remaking the stamp if it's already in use */
273	if (stamp_mutex++) {
274		stamp_mutex--;
275		rasops2_putchar(cookie, row, col, uc, attr);
276		return;
277	}
278
279	ri = (struct rasops_info *)cookie;
280
281#ifdef RASOPS_CLIPPING
282	/* Catches 'row < 0' case too */
283	if ((unsigned)row >= (unsigned)ri->ri_rows) {
284		stamp_mutex--;
285		return;
286	}
287
288	if ((unsigned)col >= (unsigned)ri->ri_cols) {
289		stamp_mutex--;
290		return;
291	}
292#endif
293
294	rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
295	height = ri->ri_font->fontheight;
296	rs = ri->ri_stride;
297
298	/* Recompute stamp? */
299	if (attr != stamp_attr)
300		rasops2_makestamp(ri, attr);
301
302	if (uc == ' ') {
303		int8_t c = stamp[0];
304		while (height--) {
305			*(int16_t *)rp = c;
306			rp += rs;
307		}
308	} else {
309		uc -= ri->ri_font->firstchar;
310		fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
311		fs = ri->ri_font->stride;
312
313		while (height--) {
314			rp[0] = stamp[(*fr >> 4) & 0xf];
315			rp[1] = stamp[*fr & 0xf];
316			fr += fs;
317			rp += rs;
318		}
319	}
320
321	/* Do underline */
322	if ((attr & 1) != 0)
323		*(int16_t *)(rp - (ri->ri_stride << 1)) = stamp[15];
324
325	stamp_mutex--;
326}
327
328/*
329 * Put a single character. This is for 12-pixel wide fonts.
330 */
331static void
332rasops2_putchar12(cookie, row, col, uc, attr)
333	void *cookie;
334	int row, col;
335	u_int uc;
336	long attr;
337{
338	struct rasops_info *ri;
339	int height, fs, rs;
340	u_char *fr, *rp;
341
342	/* Can't risk remaking the stamp if it's already in use */
343	if (stamp_mutex++) {
344		stamp_mutex--;
345		rasops2_putchar(cookie, row, col, uc, attr);
346		return;
347	}
348
349	ri = (struct rasops_info *)cookie;
350
351#ifdef RASOPS_CLIPPING
352	/* Catches 'row < 0' case too */
353	if ((unsigned)row >= (unsigned)ri->ri_rows) {
354		stamp_mutex--;
355		return;
356	}
357
358	if ((unsigned)col >= (unsigned)ri->ri_cols) {
359		stamp_mutex--;
360		return;
361	}
362#endif
363
364	rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
365	height = ri->ri_font->fontheight;
366	rs = ri->ri_stride;
367
368	/* Recompute stamp? */
369	if (attr != stamp_attr)
370		rasops2_makestamp(ri, attr);
371
372	if (uc == ' ') {
373		int8_t c = stamp[0];
374		while (height--) {
375			rp[0] = rp[1] = rp[2] = c;
376			rp += rs;
377		}
378	} else {
379		uc -= ri->ri_font->firstchar;
380		fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
381		fs = ri->ri_font->stride;
382
383		while (height--) {
384			rp[0] = stamp[(fr[0] >> 4) & 0xf];
385			rp[1] = stamp[fr[0] & 0xf];
386			rp[2] = stamp[(fr[1] >> 4) & 0xf];
387			fr += fs;
388			rp += rs;
389		}
390	}
391
392	/* Do underline */
393	if ((attr & 1) != 0) {
394		rp -= ri->ri_stride << 1;
395		rp[0] = rp[1] = rp[2] = stamp[15];
396	}
397
398	stamp_mutex--;
399}
400
401/*
402 * Put a single character. This is for 16-pixel wide fonts.
403 */
404static void
405rasops2_putchar16(cookie, row, col, uc, attr)
406	void *cookie;
407	int row, col;
408	u_int uc;
409	long attr;
410{
411	struct rasops_info *ri;
412	int height, fs, rs;
413	u_char *fr, *rp;
414
415	/* Can't risk remaking the stamp if it's already in use */
416	if (stamp_mutex++) {
417		stamp_mutex--;
418		rasops2_putchar(cookie, row, col, uc, attr);
419		return;
420	}
421
422	ri = (struct rasops_info *)cookie;
423
424#ifdef RASOPS_CLIPPING
425	/* Catches 'row < 0' case too */
426	if ((unsigned)row >= (unsigned)ri->ri_rows) {
427		stamp_mutex--;
428		return;
429	}
430
431	if ((unsigned)col >= (unsigned)ri->ri_cols) {
432		stamp_mutex--;
433		return;
434	}
435#endif
436
437	rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
438	height = ri->ri_font->fontheight;
439	rs = ri->ri_stride;
440
441	/* Recompute stamp? */
442	if (attr != stamp_attr)
443		rasops2_makestamp(ri, attr);
444
445	if (uc == ' ') {
446		int8_t c = stamp[0];
447		while (height--) {
448			*(int32_t *)rp = c;
449			rp += rs;
450		}
451	} else {
452		uc -= ri->ri_font->firstchar;
453		fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
454		fs = ri->ri_font->stride;
455
456		while (height--) {
457			rp[0] = stamp[(fr[0] >> 4) & 0xf];
458			rp[1] = stamp[fr[0] & 0xf];
459			rp[2] = stamp[(fr[1] >> 4) & 0xf];
460			rp[3] = stamp[fr[1] & 0xf];
461			fr += fs;
462			rp += rs;
463		}
464	}
465
466	/* Do underline */
467	if ((attr & 1) != 0)
468		*(int32_t *)(rp - (ri->ri_stride << 1)) = stamp[15];
469
470	stamp_mutex--;
471}
472#endif	/* !RASOPS_SMALL */
473
474/*
475 * Grab routines common to depths where (bpp < 8)
476 */
477#define NAME(ident)	rasops2_##ident
478#define PIXEL_SHIFT	1
479
480#include <dev/rasops/rasops_bitops.h>
481