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