xref: /openbsd/sys/dev/rasops/rasops8.c (revision db3296cf)
1 /*	$OpenBSD: rasops8.c,v 1.6 2002/07/27 22:17:49 miod Exp $	*/
2 /*	$NetBSD: rasops8.c,v 1.8 2000/04/12 14:22:29 pk Exp $	*/
3 
4 /*-
5  * Copyright (c) 1999 The NetBSD Foundation, Inc.
6  * All rights reserved.
7  *
8  * This code is derived from software contributed to The NetBSD Foundation
9  * by Andrew Doran.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 3. All advertising materials mentioning features or use of this software
20  *    must display the following acknowledgement:
21  *	This product includes software developed by the NetBSD
22  *	Foundation, Inc. and its contributors.
23  * 4. Neither the name of The NetBSD Foundation nor the names of its
24  *    contributors may be used to endorse or promote products derived
25  *    from this software without specific prior written permission.
26  *
27  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37  * POSSIBILITY OF SUCH DAMAGE.
38  */
39 
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/time.h>
43 
44 #include <dev/wscons/wsdisplayvar.h>
45 #include <dev/wscons/wsconsio.h>
46 #include <dev/rasops/rasops.h>
47 
48 void 	rasops8_putchar(void *, int, int, u_int, long attr);
49 #ifndef RASOPS_SMALL
50 void 	rasops8_putchar8(void *, int, int, u_int, long attr);
51 void 	rasops8_putchar12(void *, int, int, u_int, long attr);
52 void 	rasops8_putchar16(void *, int, int, u_int, long attr);
53 void	rasops8_makestamp(struct rasops_info *ri, long);
54 
55 /*
56  * 4x1 stamp for optimized character blitting
57  */
58 static int32_t	stamp[16];
59 static long	stamp_attr;
60 static int	stamp_mutex;	/* XXX see note in README */
61 #endif
62 
63 /*
64  * XXX this confuses the hell out of gcc2 (not egcs) which always insists
65  * that the shift count is negative.
66  *
67  * offset = STAMP_SHIFT(fontbits, nibble #) & STAMP_MASK
68  * destination = STAMP_READ(offset)
69  */
70 #define STAMP_SHIFT(fb,n)	((n*4-2) >= 0 ? (fb)>>(n*4-2):(fb)<<-(n*4-2))
71 #define STAMP_MASK		(0xf << 2)
72 #define STAMP_READ(o)		(*(int32_t *)((caddr_t)stamp + (o)))
73 
74 /*
75  * Initialize a 'rasops_info' descriptor for this depth.
76  */
77 void
78 rasops8_init(ri)
79 	struct rasops_info *ri;
80 {
81 
82 	switch (ri->ri_font->fontwidth) {
83 #ifndef RASOPS_SMALL
84 	case 8:
85 		ri->ri_ops.putchar = rasops8_putchar8;
86 		break;
87 	case 12:
88 		ri->ri_ops.putchar = rasops8_putchar12;
89 		break;
90 	case 16:
91 		ri->ri_ops.putchar = rasops8_putchar16;
92 		break;
93 #endif /* !RASOPS_SMALL */
94 	default:
95 		ri->ri_ops.putchar = rasops8_putchar;
96 		break;
97 	}
98 }
99 
100 /*
101  * Put a single character.
102  */
103 void
104 rasops8_putchar(cookie, row, col, uc, attr)
105 	void *cookie;
106 	int row, col;
107 	u_int uc;
108 	long attr;
109 {
110 	int width, height, cnt, fs, fb;
111 	u_char *dp, *rp, *fr, clr[2];
112 	struct rasops_info *ri;
113 
114 	ri = (struct rasops_info *)cookie;
115 
116 #ifdef RASOPS_CLIPPING
117 	/* Catches 'row < 0' case too */
118 	if ((unsigned)row >= (unsigned)ri->ri_rows)
119 		return;
120 
121 	if ((unsigned)col >= (unsigned)ri->ri_cols)
122 		return;
123 #endif
124 	rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
125 
126 	height = ri->ri_font->fontheight;
127 	width = ri->ri_font->fontwidth;
128 	clr[0] = (u_char)ri->ri_devcmap[(attr >> 16) & 0xf];
129 	clr[1] = (u_char)ri->ri_devcmap[(attr >> 24) & 0xf];
130 
131 	if (uc == ' ') {
132 		u_char c = clr[0];
133 
134 		while (height--) {
135 			dp = rp;
136 			rp += ri->ri_stride;
137 
138 			for (cnt = width; cnt; cnt--)
139 				*dp++ = c;
140 		}
141 	} else {
142 		uc -= ri->ri_font->firstchar;
143 		fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
144 		fs = ri->ri_font->stride;
145 
146 		while (height--) {
147 			dp = rp;
148 			fb = fr[3] | (fr[2] << 8) | (fr[1] << 16) | (fr[0] << 24);
149 			fr += fs;
150 			rp += ri->ri_stride;
151 
152 			for (cnt = width; cnt; cnt--) {
153 				*dp++ = clr[(fb >> 31) & 1];
154 				fb <<= 1;
155 			}
156 		}
157 	}
158 
159 	/* Do underline */
160 	if ((attr & 1) != 0) {
161 		u_char c = clr[1];
162 
163 		rp -= (ri->ri_stride << 1);
164 
165 		while (width--)
166 			*rp++ = c;
167 	}
168 }
169 
170 #ifndef RASOPS_SMALL
171 /*
172  * Recompute the 4x1 blitting stamp.
173  */
174 void
175 rasops8_makestamp(ri, attr)
176 	struct rasops_info *ri;
177 	long attr;
178 {
179 	int32_t fg, bg;
180 	int i;
181 
182 	fg = ri->ri_devcmap[(attr >> 24) & 0xf] & 0xff;
183 	bg = ri->ri_devcmap[(attr >> 16) & 0xf] & 0xff;
184 	stamp_attr = attr;
185 
186 	for (i = 0; i < 16; i++) {
187 #if BYTE_ORDER == LITTLE_ENDIAN
188 		stamp[i] = (i & 8 ? fg : bg);
189 		stamp[i] |= ((i & 4 ? fg : bg) << 8);
190 		stamp[i] |= ((i & 2 ? fg : bg) << 16);
191 		stamp[i] |= ((i & 1 ? fg : bg) << 24);
192 #else
193 		stamp[i] = (i & 1 ? fg : bg);
194 		stamp[i] |= ((i & 2 ? fg : bg) << 8);
195 		stamp[i] |= ((i & 4 ? fg : bg) << 16);
196 		stamp[i] |= ((i & 8 ? fg : bg) << 24);
197 #endif
198 		if (ri->ri_flg & RI_BSWAP)
199 			stamp[i] = swap32(stamp[i]);
200 	}
201 }
202 
203 /*
204  * Put a single character. This is for 8-pixel wide fonts.
205  */
206 void
207 rasops8_putchar8(cookie, row, col, uc, attr)
208 	void *cookie;
209 	int row, col;
210 	u_int uc;
211 	long attr;
212 {
213 	struct rasops_info *ri;
214 	int height, fs;
215 	int32_t *rp;
216 	u_char *fr;
217 
218 	/* Can't risk remaking the stamp if it's already in use */
219 	if (stamp_mutex++) {
220 		stamp_mutex--;
221 		rasops8_putchar(cookie, row, col, uc, attr);
222 		return;
223 	}
224 
225 	ri = (struct rasops_info *)cookie;
226 
227 #ifdef RASOPS_CLIPPING
228 	if ((unsigned)row >= (unsigned)ri->ri_rows) {
229 		stamp_mutex--;
230 		return;
231 	}
232 
233 	if ((unsigned)col >= (unsigned)ri->ri_cols) {
234 		stamp_mutex--;
235 		return;
236 	}
237 #endif
238 
239 	/* Recompute stamp? */
240 	if (attr != stamp_attr)
241 		rasops8_makestamp(ri, attr);
242 
243 	rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
244 	height = ri->ri_font->fontheight;
245 
246 	if (uc == ' ') {
247 		while (height--) {
248 			rp[0] = rp[1] = stamp[0];
249 			DELTA(rp, ri->ri_stride, int32_t *);
250 		}
251 	} else {
252 		uc -= ri->ri_font->firstchar;
253 		fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
254 		fs = ri->ri_font->stride;
255 
256 		while (height--) {
257 			rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
258 			rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
259 
260 			fr += fs;
261 			DELTA(rp, ri->ri_stride, int32_t *);
262 		}
263 	}
264 
265 	/* Do underline */
266 	if ((attr & 1) != 0) {
267 		DELTA(rp, -(ri->ri_stride << 1), int32_t *);
268 		rp[0] = rp[1] = stamp[15];
269 	}
270 
271 	stamp_mutex--;
272 }
273 
274 /*
275  * Put a single character. This is for 12-pixel wide fonts.
276  */
277 void
278 rasops8_putchar12(cookie, row, col, uc, attr)
279 	void *cookie;
280 	int row, col;
281 	u_int uc;
282 	long attr;
283 {
284 	struct rasops_info *ri;
285 	int height, fs;
286 	int32_t *rp;
287 	u_char *fr;
288 
289 	/* Can't risk remaking the stamp if it's already in use */
290 	if (stamp_mutex++) {
291 		stamp_mutex--;
292 		rasops8_putchar(cookie, row, col, uc, attr);
293 		return;
294 	}
295 
296 	ri = (struct rasops_info *)cookie;
297 
298 #ifdef RASOPS_CLIPPING
299 	if ((unsigned)row >= (unsigned)ri->ri_rows) {
300 		stamp_mutex--;
301 		return;
302 	}
303 
304 	if ((unsigned)col >= (unsigned)ri->ri_cols) {
305 		stamp_mutex--;
306 		return;
307 	}
308 #endif
309 
310 	/* Recompute stamp? */
311 	if (attr != stamp_attr)
312 		rasops8_makestamp(ri, attr);
313 
314 	rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
315 	height = ri->ri_font->fontheight;
316 
317 	if (uc == ' ') {
318 		while (height--) {
319 			int32_t c = stamp[0];
320 
321 			rp[0] = rp[1] = rp[2] = c;
322 			DELTA(rp, ri->ri_stride, int32_t *);
323 		}
324 	} else {
325 		uc -= ri->ri_font->firstchar;
326 		fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
327 		fs = ri->ri_font->stride;
328 
329 		while (height--) {
330 			rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
331 			rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
332 			rp[2] = STAMP_READ(STAMP_SHIFT(fr[1], 1) & STAMP_MASK);
333 
334 			fr += fs;
335 			DELTA(rp, ri->ri_stride, int32_t *);
336 		}
337 	}
338 
339 	/* Do underline */
340 	if ((attr & 1) != 0) {
341 		DELTA(rp, -(ri->ri_stride << 1), int32_t *);
342 		rp[0] = rp[1] = rp[2] = stamp[15];
343 	}
344 
345 	stamp_mutex--;
346 }
347 
348 /*
349  * Put a single character. This is for 16-pixel wide fonts.
350  */
351 void
352 rasops8_putchar16(cookie, row, col, uc, attr)
353 	void *cookie;
354 	int row, col;
355 	u_int uc;
356 	long attr;
357 {
358 	struct rasops_info *ri;
359 	int height, fs;
360 	int32_t *rp;
361 	u_char *fr;
362 
363 	/* Can't risk remaking the stamp if it's already in use */
364 	if (stamp_mutex++) {
365 		stamp_mutex--;
366 		rasops8_putchar(cookie, row, col, uc, attr);
367 		return;
368 	}
369 
370 	ri = (struct rasops_info *)cookie;
371 
372 #ifdef RASOPS_CLIPPING
373 	if ((unsigned)row >= (unsigned)ri->ri_rows) {
374 		stamp_mutex--;
375 		return;
376 	}
377 
378 	if ((unsigned)col >= (unsigned)ri->ri_cols) {
379 		stamp_mutex--;
380 		return;
381 	}
382 #endif
383 
384 	/* Recompute stamp? */
385 	if (attr != stamp_attr)
386 		rasops8_makestamp(ri, attr);
387 
388 	rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
389 	height = ri->ri_font->fontheight;
390 
391 	if (uc == ' ') {
392 		while (height--)
393 			rp[0] = rp[1] = rp[2] = rp[3] = stamp[0];
394 	} else {
395 		uc -= ri->ri_font->firstchar;
396 		fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
397 		fs = ri->ri_font->stride;
398 
399 		while (height--) {
400 			rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
401 			rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
402 			rp[2] = STAMP_READ(STAMP_SHIFT(fr[1], 1) & STAMP_MASK);
403 			rp[3] = STAMP_READ(STAMP_SHIFT(fr[1], 0) & STAMP_MASK);
404 
405 			fr += fs;
406 			DELTA(rp, ri->ri_stride, int32_t *);
407 		}
408 	}
409 
410 	/* Do underline */
411 	if ((attr & 1) != 0) {
412 		DELTA(rp, -(ri->ri_stride << 1), int32_t *);
413 		rp[0] = rp[1] = rp[2] = rp[3] = stamp[15];
414 	}
415 
416 	stamp_mutex--;
417 }
418 #endif /* !RASOPS_SMALL */
419