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