rasops8.c revision 1.23.12.1 1 /* $NetBSD: rasops8.c,v 1.23.12.1 2008/05/18 12:34:41 yamt 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 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: rasops8.c,v 1.23.12.1 2008/05/18 12:34:41 yamt Exp $");
34
35 #include "opt_rasops.h"
36
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/time.h>
40
41 #include <dev/wscons/wsdisplayvar.h>
42 #include <dev/wscons/wsconsio.h>
43 #include <dev/rasops/rasops.h>
44
45 static void rasops8_putchar(void *, int, int, u_int, long attr);
46 #ifndef RASOPS_SMALL
47 static void rasops8_putchar8(void *, int, int, u_int, long attr);
48 static void rasops8_putchar12(void *, int, int, u_int, long attr);
49 static void rasops8_putchar16(void *, int, int, u_int, long attr);
50 static void rasops8_makestamp(struct rasops_info *ri, long);
51
52 /*
53 * 4x1 stamp for optimized character blitting
54 */
55 static int32_t stamp[16];
56 static long stamp_attr;
57 static int stamp_mutex; /* XXX see note in README */
58 #endif
59
60 /*
61 * XXX this confuses the hell out of gcc2 (not egcs) which always insists
62 * that the shift count is negative.
63 *
64 * offset = STAMP_SHIFT(fontbits, nibble #) & STAMP_MASK
65 * destination = STAMP_READ(offset)
66 */
67 #define STAMP_SHIFT(fb,n) ((n*4-2) >= 0 ? (fb)>>(n*4-2):(fb)<<-(n*4-2))
68 #define STAMP_MASK (0xf << 2)
69 #define STAMP_READ(o) (*(int32_t *)((char *)stamp + (o)))
70
71 /*
72 * Initialize a 'rasops_info' descriptor for this depth.
73 */
74 void
75 rasops8_init(ri)
76 struct rasops_info *ri;
77 {
78
79 switch (ri->ri_font->fontwidth) {
80 #ifndef RASOPS_SMALL
81 case 8:
82 ri->ri_ops.putchar = rasops8_putchar8;
83 break;
84 case 12:
85 ri->ri_ops.putchar = rasops8_putchar12;
86 break;
87 case 16:
88 ri->ri_ops.putchar = rasops8_putchar16;
89 break;
90 #endif /* !RASOPS_SMALL */
91 default:
92 ri->ri_ops.putchar = rasops8_putchar;
93 break;
94 }
95 }
96
97 /*
98 * Put a single character.
99 */
100 static void
101 rasops8_putchar(cookie, row, col, uc, attr)
102 void *cookie;
103 int row, col;
104 u_int uc;
105 long attr;
106 {
107 int width, height, cnt, fs, fb;
108 u_char *dp, *rp, *hp, *hrp, *fr, clr[2];
109 struct rasops_info *ri;
110
111 ri = (struct rasops_info *)cookie;
112 hp = hrp = NULL;
113
114 if (!CHAR_IN_FONT(uc, ri->ri_font))
115 return;
116
117 #ifdef RASOPS_CLIPPING
118 /* Catches 'row < 0' case too */
119 if ((unsigned)row >= (unsigned)ri->ri_rows)
120 return;
121
122 if ((unsigned)col >= (unsigned)ri->ri_cols)
123 return;
124 #endif
125 rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
126 if (ri->ri_hwbits)
127 hrp = ri->ri_hwbits + row * ri->ri_yscale + col *
128 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 if (ri->ri_hwbits) {
142 hp = hrp;
143 hrp += ri->ri_stride;
144 }
145
146 for (cnt = width; cnt; cnt--) {
147 *dp++ = c;
148 if (ri->ri_hwbits)
149 *hp++ = c;
150 }
151 }
152 } else {
153 uc -= ri->ri_font->firstchar;
154 fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
155 fs = ri->ri_font->stride;
156
157 while (height--) {
158 dp = rp;
159 if (ri->ri_hwbits)
160 hp = hrp;
161 fb = fr[3] | (fr[2] << 8) | (fr[1] << 16) | (fr[0] << 24);
162 fr += fs;
163 rp += ri->ri_stride;
164 if (ri->ri_hwbits)
165 hrp += ri->ri_stride;
166
167 for (cnt = width; cnt; cnt--) {
168 *dp++ = clr[(fb >> 31) & 1];
169 if (ri->ri_hwbits)
170 *hp++ = clr[(fb >> 31) & 1];
171 fb <<= 1;
172 }
173 }
174 }
175
176 /* Do underline */
177 if ((attr & 1) != 0) {
178 u_char c = clr[1];
179
180 rp -= (ri->ri_stride << 1);
181 if (ri->ri_hwbits)
182 hrp -= (ri->ri_stride << 1);
183
184 while (width--) {
185 *rp++ = c;
186 if (ri->ri_hwbits)
187 *hrp++ = c;
188 }
189 }
190 }
191
192 #ifndef RASOPS_SMALL
193 /*
194 * Recompute the 4x1 blitting stamp.
195 */
196 static void
197 rasops8_makestamp(ri, attr)
198 struct rasops_info *ri;
199 long attr;
200 {
201 int32_t fg, bg;
202 int i;
203
204 fg = ri->ri_devcmap[(attr >> 24) & 0xf] & 0xff;
205 bg = ri->ri_devcmap[(attr >> 16) & 0xf] & 0xff;
206 stamp_attr = attr;
207
208 for (i = 0; i < 16; i++) {
209 #if BYTE_ORDER == BIG_ENDIAN
210 #define NEED_LITTLE_ENDIAN_STAMP RI_BSWAP
211 #else
212 #define NEED_LITTLE_ENDIAN_STAMP 0
213 #endif
214 if ((ri->ri_flg & RI_BSWAP) == NEED_LITTLE_ENDIAN_STAMP) {
215 /* little endian */
216 stamp[i] = (i & 8 ? fg : bg);
217 stamp[i] |= ((i & 4 ? fg : bg) << 8);
218 stamp[i] |= ((i & 2 ? fg : bg) << 16);
219 stamp[i] |= ((i & 1 ? fg : bg) << 24);
220 } else {
221 /* big endian */
222 stamp[i] = (i & 1 ? fg : bg);
223 stamp[i] |= ((i & 2 ? fg : bg) << 8);
224 stamp[i] |= ((i & 4 ? fg : bg) << 16);
225 stamp[i] |= ((i & 8 ? fg : bg) << 24);
226 }
227 }
228 }
229
230 /*
231 * Put a single character. This is for 8-pixel wide fonts.
232 */
233 static void
234 rasops8_putchar8(cookie, row, col, uc, attr)
235 void *cookie;
236 int row, col;
237 u_int uc;
238 long attr;
239 {
240 struct rasops_info *ri;
241 int height, fs;
242 int32_t *rp, *hp;
243 u_char *fr;
244
245 /* Can't risk remaking the stamp if it's already in use */
246 if (stamp_mutex++) {
247 stamp_mutex--;
248 rasops8_putchar(cookie, row, col, uc, attr);
249 return;
250 }
251
252 ri = (struct rasops_info *)cookie;
253 hp = NULL;
254
255 if (!CHAR_IN_FONT(uc, ri->ri_font))
256 return;
257
258 #ifdef RASOPS_CLIPPING
259 if ((unsigned)row >= (unsigned)ri->ri_rows) {
260 stamp_mutex--;
261 return;
262 }
263
264 if ((unsigned)col >= (unsigned)ri->ri_cols) {
265 stamp_mutex--;
266 return;
267 }
268 #endif
269
270 /* Recompute stamp? */
271 if (attr != stamp_attr)
272 rasops8_makestamp(ri, attr);
273
274 rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
275 if (ri->ri_hwbits)
276 hp = (int32_t *)(ri->ri_hwbits + row*ri->ri_yscale +
277 col*ri->ri_xscale);
278 height = ri->ri_font->fontheight;
279
280 if (uc == ' ') {
281 while (height--) {
282 rp[0] = rp[1] = stamp[0];
283 DELTA(rp, ri->ri_stride, int32_t *);
284 if (ri->ri_hwbits) {
285 hp[0] = stamp[0];
286 hp[1] = stamp[0];
287 DELTA(hp, ri->ri_stride, int32_t *);
288 }
289 }
290 } else {
291 uc -= ri->ri_font->firstchar;
292 fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
293 fs = ri->ri_font->stride;
294
295 while (height--) {
296 rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
297 rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
298 if (ri->ri_hwbits) {
299 hp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) &
300 STAMP_MASK);
301 hp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) &
302 STAMP_MASK);
303 }
304
305 fr += fs;
306 DELTA(rp, ri->ri_stride, int32_t *);
307 if (ri->ri_hwbits)
308 DELTA(hp, ri->ri_stride, int32_t *);
309 }
310 }
311
312 /* Do underline */
313 if ((attr & 1) != 0) {
314 DELTA(rp, -(ri->ri_stride << 1), int32_t *);
315 rp[0] = rp[1] = stamp[15];
316 if (ri->ri_hwbits) {
317 DELTA(hp, -(ri->ri_stride << 1), int32_t *);
318 hp[0] = stamp[15];
319 hp[1] = stamp[15];
320 }
321 }
322
323 stamp_mutex--;
324 }
325
326 /*
327 * Put a single character. This is for 12-pixel wide fonts.
328 */
329 static void
330 rasops8_putchar12(cookie, row, col, uc, attr)
331 void *cookie;
332 int row, col;
333 u_int uc;
334 long attr;
335 {
336 struct rasops_info *ri;
337 int height, fs;
338 int32_t *rp, *hrp;
339 u_char *fr;
340
341 /* Can't risk remaking the stamp if it's already in use */
342 if (stamp_mutex++) {
343 stamp_mutex--;
344 rasops8_putchar(cookie, row, col, uc, attr);
345 return;
346 }
347
348 ri = (struct rasops_info *)cookie;
349 hrp = NULL;
350
351 if (!CHAR_IN_FONT(uc, ri->ri_font))
352 return;
353
354 #ifdef RASOPS_CLIPPING
355 if ((unsigned)row >= (unsigned)ri->ri_rows) {
356 stamp_mutex--;
357 return;
358 }
359
360 if ((unsigned)col >= (unsigned)ri->ri_cols) {
361 stamp_mutex--;
362 return;
363 }
364 #endif
365
366 /* Recompute stamp? */
367 if (attr != stamp_attr)
368 rasops8_makestamp(ri, attr);
369
370 rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
371 if (ri->ri_hwbits)
372 hrp = (int32_t *)(ri->ri_hwbits + row*ri->ri_yscale +
373 col*ri->ri_xscale);
374 height = ri->ri_font->fontheight;
375
376 if (uc == ' ') {
377 while (height--) {
378 int32_t c = stamp[0];
379
380 rp[0] = rp[1] = rp[2] = c;
381 DELTA(rp, ri->ri_stride, int32_t *);
382 if (ri->ri_hwbits) {
383 hrp[0] = c;
384 hrp[1] = c;
385 hrp[2] = c;
386 DELTA(hrp, ri->ri_stride, int32_t *);
387 }
388 }
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 if (ri->ri_hwbits) {
399 hrp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
400 hrp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
401 hrp[2] = STAMP_READ(STAMP_SHIFT(fr[1], 1) & STAMP_MASK);
402 }
403
404 fr += fs;
405 DELTA(rp, ri->ri_stride, int32_t *);
406 if (ri->ri_hwbits)
407 DELTA(hrp, ri->ri_stride, int32_t *);
408 }
409 }
410
411 /* Do underline */
412 if ((attr & 1) != 0) {
413 DELTA(rp, -(ri->ri_stride << 1), int32_t *);
414 rp[0] = rp[1] = rp[2] = stamp[15];
415 if (ri->ri_hwbits) {
416 DELTA(hrp, -(ri->ri_stride << 1), int32_t *);
417 hrp[0] = stamp[15];
418 hrp[1] = stamp[15];
419 hrp[2] = stamp[15];
420 }
421 }
422
423 stamp_mutex--;
424 }
425
426 /*
427 * Put a single character. This is for 16-pixel wide fonts.
428 */
429 static void
430 rasops8_putchar16(cookie, row, col, uc, attr)
431 void *cookie;
432 int row, col;
433 u_int uc;
434 long attr;
435 {
436 struct rasops_info *ri;
437 int height, fs;
438 int32_t *rp, *hrp;
439 u_char *fr;
440
441 /* Can't risk remaking the stamp if it's already in use */
442 if (stamp_mutex++) {
443 stamp_mutex--;
444 rasops8_putchar(cookie, row, col, uc, attr);
445 return;
446 }
447
448 ri = (struct rasops_info *)cookie;
449 hrp = NULL;
450
451 if (!CHAR_IN_FONT(uc, ri->ri_font))
452 return;
453
454 #ifdef RASOPS_CLIPPING
455 if ((unsigned)row >= (unsigned)ri->ri_rows) {
456 stamp_mutex--;
457 return;
458 }
459
460 if ((unsigned)col >= (unsigned)ri->ri_cols) {
461 stamp_mutex--;
462 return;
463 }
464 #endif
465
466 /* Recompute stamp? */
467 if (attr != stamp_attr)
468 rasops8_makestamp(ri, attr);
469
470 rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
471 if (ri->ri_hwbits)
472 hrp = (int32_t *)(ri->ri_hwbits + row*ri->ri_yscale +
473 col*ri->ri_xscale);
474
475 height = ri->ri_font->fontheight;
476
477 if (uc == ' ') {
478 while (height--) {
479 rp[0] = rp[1] = rp[2] = rp[3] = stamp[0];
480 if (ri->ri_hwbits) {
481 hrp[0] = stamp[0];
482 hrp[1] = stamp[0];
483 hrp[2] = stamp[0];
484 hrp[3] = stamp[0];
485 }
486 }
487 } else {
488 uc -= ri->ri_font->firstchar;
489 fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
490 fs = ri->ri_font->stride;
491
492 while (height--) {
493 rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
494 rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
495 rp[2] = STAMP_READ(STAMP_SHIFT(fr[1], 1) & STAMP_MASK);
496 rp[3] = STAMP_READ(STAMP_SHIFT(fr[1], 0) & STAMP_MASK);
497 if (ri->ri_hwbits) {
498 hrp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
499 hrp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
500 hrp[2] = STAMP_READ(STAMP_SHIFT(fr[1], 1) & STAMP_MASK);
501 hrp[3] = STAMP_READ(STAMP_SHIFT(fr[1], 0) & STAMP_MASK);
502 }
503
504 fr += fs;
505 DELTA(rp, ri->ri_stride, int32_t *);
506 if (ri->ri_hwbits)
507 DELTA(hrp, ri->ri_stride, int32_t *);
508 }
509 }
510
511 /* Do underline */
512 if ((attr & 1) != 0) {
513 DELTA(rp, -(ri->ri_stride << 1), int32_t *);
514 rp[0] = rp[1] = rp[2] = rp[3] = stamp[15];
515 if (ri->ri_hwbits) {
516 DELTA(hrp, -(ri->ri_stride << 1), int32_t *);
517 hrp[0] = stamp[15];
518 hrp[1] = stamp[15];
519 hrp[2] = stamp[15];
520 hrp[3] = stamp[15];
521 }
522 }
523
524 stamp_mutex--;
525 }
526 #endif /* !RASOPS_SMALL */
527