xref: /openbsd-src/sys/dev/rasops/rasops8.c (revision b2ea75c1b17e1a9a339660e7ed45cd24946b230e)
1 /*	$OpenBSD: rasops8.c,v 1.1 2001/03/18 04:32:45 nate 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/cdefs.h>
41 //__KERNEL_RCSID(0, "$NetBSD: rasops8.c,v 1.8 2000/04/12 14:22:29 pk 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 
52 static void 	rasops8_putchar __P((void *, int, int, u_int, long attr));
53 #ifndef RASOPS_SMALL
54 static void 	rasops8_putchar8 __P((void *, int, int, u_int, long attr));
55 static void 	rasops8_putchar12 __P((void *, int, int, u_int, long attr));
56 static void 	rasops8_putchar16 __P((void *, int, int, u_int, long attr));
57 static void	rasops8_makestamp __P((struct rasops_info *ri, long));
58 #endif
59 
60 /*
61  * 4x1 stamp for optimized character blitting
62  */
63 static int32_t	stamp[16];
64 static long	stamp_attr;
65 static 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 = STAMP_READ(offset)
73  */
74 #define STAMP_SHIFT(fb,n)	((n*4-2) >= 0 ? (fb)>>(n*4-2):(fb)<<-(n*4-2))
75 #define STAMP_MASK		(0xf << 2)
76 #define STAMP_READ(o)		(*(int32_t *)((caddr_t)stamp + (o)))
77 
78 /*
79  * Initalize a 'rasops_info' descriptor for this depth.
80  */
81 void
82 rasops8_init(ri)
83 	struct rasops_info *ri;
84 {
85 
86 	switch (ri->ri_font->fontwidth) {
87 #ifndef RASOPS_SMALL
88 	case 8:
89 		ri->ri_ops.putchar = rasops8_putchar8;
90 		break;
91 	case 12:
92 		ri->ri_ops.putchar = rasops8_putchar12;
93 		break;
94 	case 16:
95 		ri->ri_ops.putchar = rasops8_putchar16;
96 		break;
97 #endif /* !RASOPS_SMALL */
98 	default:
99 		ri->ri_ops.putchar = rasops8_putchar;
100 		break;
101 	}
102 }
103 
104 /*
105  * Put a single character.
106  */
107 static void
108 rasops8_putchar(cookie, row, col, uc, attr)
109 	void *cookie;
110 	int row, col;
111 	u_int uc;
112 	long attr;
113 {
114 	int width, height, cnt, fs, fb;
115 	u_char *dp, *rp, *fr, clr[2];
116 	struct rasops_info *ri;
117 
118 	ri = (struct rasops_info *)cookie;
119 
120 #ifdef RASOPS_CLIPPING
121 	/* Catches 'row < 0' case too */
122 	if ((unsigned)row >= (unsigned)ri->ri_rows)
123 		return;
124 
125 	if ((unsigned)col >= (unsigned)ri->ri_cols)
126 		return;
127 #endif
128 	rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
129 
130 	height = ri->ri_font->fontheight;
131 	width = ri->ri_font->fontwidth;
132 	clr[0] = (u_char)ri->ri_devcmap[(attr >> 16) & 0xf];
133 	clr[1] = (u_char)ri->ri_devcmap[(attr >> 24) & 0xf];
134 
135 	if (uc == ' ') {
136 		u_char c = clr[0];
137 
138 		while (height--) {
139 			dp = rp;
140 			rp += ri->ri_stride;
141 
142 			for (cnt = width; cnt; cnt--)
143 				*dp++ = c;
144 		}
145 	} else {
146 		uc -= ri->ri_font->firstchar;
147 		fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
148 		fs = ri->ri_font->stride;
149 
150 		while (height--) {
151 			dp = rp;
152 			fb = fr[3] | (fr[2] << 8) | (fr[1] << 16) | (fr[0] << 24);
153 			fr += fs;
154 			rp += ri->ri_stride;
155 
156 			for (cnt = width; cnt; cnt--) {
157 				*dp++ = clr[(fb >> 31) & 1];
158 				fb <<= 1;
159 			}
160 		}
161 	}
162 
163 	/* Do underline */
164 	if ((attr & 1) != 0) {
165 		u_char c = clr[1];
166 
167 		rp -= (ri->ri_stride << 1);
168 
169 		while (width--)
170 			*rp++ = c;
171 	}
172 }
173 
174 #ifndef RASOPS_SMALL
175 /*
176  * Recompute the 4x1 blitting stamp.
177  */
178 static void
179 rasops8_makestamp(ri, attr)
180 	struct rasops_info *ri;
181 	long attr;
182 {
183 	int32_t fg, bg;
184 	int i;
185 
186 	fg = ri->ri_devcmap[(attr >> 24) & 0xf] & 0xff;
187 	bg = ri->ri_devcmap[(attr >> 16) & 0xf] & 0xff;
188 	stamp_attr = attr;
189 
190 	for (i = 0; i < 16; i++) {
191 #if BYTE_ORDER == LITTLE_ENDIAN
192 		stamp[i] = (i & 8 ? fg : bg);
193 		stamp[i] |= ((i & 4 ? fg : bg) << 8);
194 		stamp[i] |= ((i & 2 ? fg : bg) << 16);
195 		stamp[i] |= ((i & 1 ? fg : bg) << 24);
196 #else
197 		stamp[i] = (i & 1 ? fg : bg);
198 		stamp[i] |= ((i & 2 ? fg : bg) << 8);
199 		stamp[i] |= ((i & 4 ? fg : bg) << 16);
200 		stamp[i] |= ((i & 8 ? fg : bg) << 24);
201 #endif
202 	}
203 }
204 
205 /*
206  * Put a single character. This is for 8-pixel wide fonts.
207  */
208 static void
209 rasops8_putchar8(cookie, row, col, uc, attr)
210 	void *cookie;
211 	int row, col;
212 	u_int uc;
213 	long attr;
214 {
215 	struct rasops_info *ri;
216 	int height, fs;
217 	int32_t *rp;
218 	u_char *fr;
219 
220 	/* Can't risk remaking the stamp if it's already in use */
221 	if (stamp_mutex++) {
222 		stamp_mutex--;
223 		rasops8_putchar(cookie, row, col, uc, attr);
224 		return;
225 	}
226 
227 	ri = (struct rasops_info *)cookie;
228 
229 #ifdef RASOPS_CLIPPING
230 	if ((unsigned)row >= (unsigned)ri->ri_rows) {
231 		stamp_mutex--;
232 		return;
233 	}
234 
235 	if ((unsigned)col >= (unsigned)ri->ri_cols) {
236 		stamp_mutex--;
237 		return;
238 	}
239 #endif
240 
241 	/* Recompute stamp? */
242 	if (attr != stamp_attr)
243 		rasops8_makestamp(ri, attr);
244 
245 	rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
246 	height = ri->ri_font->fontheight;
247 
248 	if (uc == ' ') {
249 		while (height--) {
250 			rp[0] = rp[1] = stamp[0];
251 			DELTA(rp, ri->ri_stride, int32_t *);
252 		}
253 	} else {
254 		uc -= ri->ri_font->firstchar;
255 		fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
256 		fs = ri->ri_font->stride;
257 
258 		while (height--) {
259 			rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
260 			rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
261 
262 			fr += fs;
263 			DELTA(rp, ri->ri_stride, int32_t *);
264 		}
265 	}
266 
267 	/* Do underline */
268 	if ((attr & 1) != 0) {
269 		DELTA(rp, -(ri->ri_stride << 1), int32_t *);
270 		rp[0] = rp[1] = stamp[15];
271 	}
272 
273 	stamp_mutex--;
274 }
275 
276 /*
277  * Put a single character. This is for 12-pixel wide fonts.
278  */
279 static void
280 rasops8_putchar12(cookie, row, col, uc, attr)
281 	void *cookie;
282 	int row, col;
283 	u_int uc;
284 	long attr;
285 {
286 	struct rasops_info *ri;
287 	int height, fs;
288 	int32_t *rp;
289 	u_char *fr;
290 
291 	/* Can't risk remaking the stamp if it's already in use */
292 	if (stamp_mutex++) {
293 		stamp_mutex--;
294 		rasops8_putchar(cookie, row, col, uc, attr);
295 		return;
296 	}
297 
298 	ri = (struct rasops_info *)cookie;
299 
300 #ifdef RASOPS_CLIPPING
301 	if ((unsigned)row >= (unsigned)ri->ri_rows) {
302 		stamp_mutex--;
303 		return;
304 	}
305 
306 	if ((unsigned)col >= (unsigned)ri->ri_cols) {
307 		stamp_mutex--;
308 		return;
309 	}
310 #endif
311 
312 	/* Recompute stamp? */
313 	if (attr != stamp_attr)
314 		rasops8_makestamp(ri, attr);
315 
316 	rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
317 	height = ri->ri_font->fontheight;
318 
319 	if (uc == ' ') {
320 		while (height--) {
321 			int32_t c = stamp[0];
322 
323 			rp[0] = rp[1] = rp[2] = c;
324 			DELTA(rp, ri->ri_stride, int32_t *);
325 		}
326 	} else {
327 		uc -= ri->ri_font->firstchar;
328 		fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
329 		fs = ri->ri_font->stride;
330 
331 		while (height--) {
332 			rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
333 			rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
334 			rp[2] = STAMP_READ(STAMP_SHIFT(fr[1], 1) & STAMP_MASK);
335 
336 			fr += fs;
337 			DELTA(rp, ri->ri_stride, int32_t *);
338 		}
339 	}
340 
341 	/* Do underline */
342 	if ((attr & 1) != 0) {
343 		DELTA(rp, -(ri->ri_stride << 1), int32_t *);
344 		rp[0] = rp[1] = rp[2] = stamp[15];
345 	}
346 
347 	stamp_mutex--;
348 }
349 
350 /*
351  * Put a single character. This is for 16-pixel wide fonts.
352  */
353 static void
354 rasops8_putchar16(cookie, row, col, uc, attr)
355 	void *cookie;
356 	int row, col;
357 	u_int uc;
358 	long attr;
359 {
360 	struct rasops_info *ri;
361 	int height, fs;
362 	int32_t *rp;
363 	u_char *fr;
364 
365 	/* Can't risk remaking the stamp if it's already in use */
366 	if (stamp_mutex++) {
367 		stamp_mutex--;
368 		rasops8_putchar(cookie, row, col, uc, attr);
369 		return;
370 	}
371 
372 	ri = (struct rasops_info *)cookie;
373 
374 #ifdef RASOPS_CLIPPING
375 	if ((unsigned)row >= (unsigned)ri->ri_rows) {
376 		stamp_mutex--;
377 		return;
378 	}
379 
380 	if ((unsigned)col >= (unsigned)ri->ri_cols) {
381 		stamp_mutex--;
382 		return;
383 	}
384 #endif
385 
386 	/* Recompute stamp? */
387 	if (attr != stamp_attr)
388 		rasops8_makestamp(ri, attr);
389 
390 	rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
391 	height = ri->ri_font->fontheight;
392 
393 	if (uc == ' ') {
394 		while (height--)
395 			rp[0] = rp[1] = rp[2] = rp[3] = stamp[0];
396 	} else {
397 		uc -= ri->ri_font->firstchar;
398 		fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
399 		fs = ri->ri_font->stride;
400 
401 		while (height--) {
402 			rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
403 			rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
404 			rp[2] = STAMP_READ(STAMP_SHIFT(fr[1], 1) & STAMP_MASK);
405 			rp[3] = STAMP_READ(STAMP_SHIFT(fr[1], 0) & STAMP_MASK);
406 
407 			fr += fs;
408 			DELTA(rp, ri->ri_stride, int32_t *);
409 		}
410 	}
411 
412 	/* Do underline */
413 	if ((attr & 1) != 0) {
414 		DELTA(rp, -(ri->ri_stride << 1), int32_t *);
415 		rp[0] = rp[1] = rp[2] = rp[3] = stamp[15];
416 	}
417 
418 	stamp_mutex--;
419 }
420 #endif /* !RASOPS_SMALL */
421