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