rasops8.c revision 1.23 1 /* $NetBSD: rasops8.c,v 1.23 2007/12/09 20:28:14 jmcneill 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.23 2007/12/09 20:28:14 jmcneill Exp $");
41
42 #include "opt_rasops.h"
43
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(void *, int, int, u_int, long attr);
53 #ifndef RASOPS_SMALL
54 static void rasops8_putchar8(void *, int, int, u_int, long attr);
55 static void rasops8_putchar12(void *, int, int, u_int, long attr);
56 static void rasops8_putchar16(void *, int, int, u_int, long attr);
57 static void rasops8_makestamp(struct rasops_info *ri, long);
58
59 /*
60 * 4x1 stamp for optimized character blitting
61 */
62 static int32_t stamp[16];
63 static long stamp_attr;
64 static int stamp_mutex; /* XXX see note in README */
65 #endif
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 *)((char *)stamp + (o)))
77
78 /*
79 * Initialize 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, *hp, *hrp, *fr, clr[2];
116 struct rasops_info *ri;
117
118 ri = (struct rasops_info *)cookie;
119 hp = hrp = NULL;
120
121 if (!CHAR_IN_FONT(uc, ri->ri_font))
122 return;
123
124 #ifdef RASOPS_CLIPPING
125 /* Catches 'row < 0' case too */
126 if ((unsigned)row >= (unsigned)ri->ri_rows)
127 return;
128
129 if ((unsigned)col >= (unsigned)ri->ri_cols)
130 return;
131 #endif
132 rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
133 if (ri->ri_hwbits)
134 hrp = ri->ri_hwbits + row * ri->ri_yscale + col *
135 ri->ri_xscale;
136
137 height = ri->ri_font->fontheight;
138 width = ri->ri_font->fontwidth;
139 clr[0] = (u_char)ri->ri_devcmap[(attr >> 16) & 0xf];
140 clr[1] = (u_char)ri->ri_devcmap[(attr >> 24) & 0xf];
141
142 if (uc == ' ') {
143 u_char c = clr[0];
144
145 while (height--) {
146 dp = rp;
147 rp += ri->ri_stride;
148 if (ri->ri_hwbits) {
149 hp = hrp;
150 hrp += ri->ri_stride;
151 }
152
153 for (cnt = width; cnt; cnt--) {
154 *dp++ = c;
155 if (ri->ri_hwbits)
156 *hp++ = c;
157 }
158 }
159 } else {
160 uc -= ri->ri_font->firstchar;
161 fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
162 fs = ri->ri_font->stride;
163
164 while (height--) {
165 dp = rp;
166 if (ri->ri_hwbits)
167 hp = hrp;
168 fb = fr[3] | (fr[2] << 8) | (fr[1] << 16) | (fr[0] << 24);
169 fr += fs;
170 rp += ri->ri_stride;
171 if (ri->ri_hwbits)
172 hrp += ri->ri_stride;
173
174 for (cnt = width; cnt; cnt--) {
175 *dp++ = clr[(fb >> 31) & 1];
176 if (ri->ri_hwbits)
177 *hp++ = clr[(fb >> 31) & 1];
178 fb <<= 1;
179 }
180 }
181 }
182
183 /* Do underline */
184 if ((attr & 1) != 0) {
185 u_char c = clr[1];
186
187 rp -= (ri->ri_stride << 1);
188 if (ri->ri_hwbits)
189 hrp -= (ri->ri_stride << 1);
190
191 while (width--) {
192 *rp++ = c;
193 if (ri->ri_hwbits)
194 *hrp++ = c;
195 }
196 }
197 }
198
199 #ifndef RASOPS_SMALL
200 /*
201 * Recompute the 4x1 blitting stamp.
202 */
203 static void
204 rasops8_makestamp(ri, attr)
205 struct rasops_info *ri;
206 long attr;
207 {
208 int32_t fg, bg;
209 int i;
210
211 fg = ri->ri_devcmap[(attr >> 24) & 0xf] & 0xff;
212 bg = ri->ri_devcmap[(attr >> 16) & 0xf] & 0xff;
213 stamp_attr = attr;
214
215 for (i = 0; i < 16; i++) {
216 #if BYTE_ORDER == BIG_ENDIAN
217 #define NEED_LITTLE_ENDIAN_STAMP RI_BSWAP
218 #else
219 #define NEED_LITTLE_ENDIAN_STAMP 0
220 #endif
221 if ((ri->ri_flg & RI_BSWAP) == NEED_LITTLE_ENDIAN_STAMP) {
222 /* little endian */
223 stamp[i] = (i & 8 ? fg : bg);
224 stamp[i] |= ((i & 4 ? fg : bg) << 8);
225 stamp[i] |= ((i & 2 ? fg : bg) << 16);
226 stamp[i] |= ((i & 1 ? fg : bg) << 24);
227 } else {
228 /* big endian */
229 stamp[i] = (i & 1 ? fg : bg);
230 stamp[i] |= ((i & 2 ? fg : bg) << 8);
231 stamp[i] |= ((i & 4 ? fg : bg) << 16);
232 stamp[i] |= ((i & 8 ? fg : bg) << 24);
233 }
234 }
235 }
236
237 /*
238 * Put a single character. This is for 8-pixel wide fonts.
239 */
240 static void
241 rasops8_putchar8(cookie, row, col, uc, attr)
242 void *cookie;
243 int row, col;
244 u_int uc;
245 long attr;
246 {
247 struct rasops_info *ri;
248 int height, fs;
249 int32_t *rp, *hp;
250 u_char *fr;
251
252 /* Can't risk remaking the stamp if it's already in use */
253 if (stamp_mutex++) {
254 stamp_mutex--;
255 rasops8_putchar(cookie, row, col, uc, attr);
256 return;
257 }
258
259 ri = (struct rasops_info *)cookie;
260 hp = NULL;
261
262 if (!CHAR_IN_FONT(uc, ri->ri_font))
263 return;
264
265 #ifdef RASOPS_CLIPPING
266 if ((unsigned)row >= (unsigned)ri->ri_rows) {
267 stamp_mutex--;
268 return;
269 }
270
271 if ((unsigned)col >= (unsigned)ri->ri_cols) {
272 stamp_mutex--;
273 return;
274 }
275 #endif
276
277 /* Recompute stamp? */
278 if (attr != stamp_attr)
279 rasops8_makestamp(ri, attr);
280
281 rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
282 if (ri->ri_hwbits)
283 hp = (int32_t *)(ri->ri_hwbits + row*ri->ri_yscale +
284 col*ri->ri_xscale);
285 height = ri->ri_font->fontheight;
286
287 if (uc == ' ') {
288 while (height--) {
289 rp[0] = rp[1] = stamp[0];
290 DELTA(rp, ri->ri_stride, int32_t *);
291 if (ri->ri_hwbits) {
292 hp[0] = stamp[0];
293 hp[1] = stamp[0];
294 DELTA(hp, ri->ri_stride, int32_t *);
295 }
296 }
297 } else {
298 uc -= ri->ri_font->firstchar;
299 fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
300 fs = ri->ri_font->stride;
301
302 while (height--) {
303 rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
304 rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
305 if (ri->ri_hwbits) {
306 hp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) &
307 STAMP_MASK);
308 hp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) &
309 STAMP_MASK);
310 }
311
312 fr += fs;
313 DELTA(rp, ri->ri_stride, int32_t *);
314 if (ri->ri_hwbits)
315 DELTA(hp, ri->ri_stride, int32_t *);
316 }
317 }
318
319 /* Do underline */
320 if ((attr & 1) != 0) {
321 DELTA(rp, -(ri->ri_stride << 1), int32_t *);
322 rp[0] = rp[1] = stamp[15];
323 if (ri->ri_hwbits) {
324 DELTA(hp, -(ri->ri_stride << 1), int32_t *);
325 hp[0] = stamp[15];
326 hp[1] = stamp[15];
327 }
328 }
329
330 stamp_mutex--;
331 }
332
333 /*
334 * Put a single character. This is for 12-pixel wide fonts.
335 */
336 static void
337 rasops8_putchar12(cookie, row, col, uc, attr)
338 void *cookie;
339 int row, col;
340 u_int uc;
341 long attr;
342 {
343 struct rasops_info *ri;
344 int height, fs;
345 int32_t *rp, *hrp;
346 u_char *fr;
347
348 /* Can't risk remaking the stamp if it's already in use */
349 if (stamp_mutex++) {
350 stamp_mutex--;
351 rasops8_putchar(cookie, row, col, uc, attr);
352 return;
353 }
354
355 ri = (struct rasops_info *)cookie;
356 hrp = NULL;
357
358 if (!CHAR_IN_FONT(uc, ri->ri_font))
359 return;
360
361 #ifdef RASOPS_CLIPPING
362 if ((unsigned)row >= (unsigned)ri->ri_rows) {
363 stamp_mutex--;
364 return;
365 }
366
367 if ((unsigned)col >= (unsigned)ri->ri_cols) {
368 stamp_mutex--;
369 return;
370 }
371 #endif
372
373 /* Recompute stamp? */
374 if (attr != stamp_attr)
375 rasops8_makestamp(ri, attr);
376
377 rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
378 if (ri->ri_hwbits)
379 hrp = (int32_t *)(ri->ri_hwbits + row*ri->ri_yscale +
380 col*ri->ri_xscale);
381 height = ri->ri_font->fontheight;
382
383 if (uc == ' ') {
384 while (height--) {
385 int32_t c = stamp[0];
386
387 rp[0] = rp[1] = rp[2] = c;
388 DELTA(rp, ri->ri_stride, int32_t *);
389 if (ri->ri_hwbits) {
390 hrp[0] = c;
391 hrp[1] = c;
392 hrp[2] = c;
393 DELTA(hrp, ri->ri_stride, int32_t *);
394 }
395 }
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 if (ri->ri_hwbits) {
406 hrp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
407 hrp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
408 hrp[2] = STAMP_READ(STAMP_SHIFT(fr[1], 1) & STAMP_MASK);
409 }
410
411 fr += fs;
412 DELTA(rp, ri->ri_stride, int32_t *);
413 if (ri->ri_hwbits)
414 DELTA(hrp, ri->ri_stride, int32_t *);
415 }
416 }
417
418 /* Do underline */
419 if ((attr & 1) != 0) {
420 DELTA(rp, -(ri->ri_stride << 1), int32_t *);
421 rp[0] = rp[1] = rp[2] = stamp[15];
422 if (ri->ri_hwbits) {
423 DELTA(hrp, -(ri->ri_stride << 1), int32_t *);
424 hrp[0] = stamp[15];
425 hrp[1] = stamp[15];
426 hrp[2] = stamp[15];
427 }
428 }
429
430 stamp_mutex--;
431 }
432
433 /*
434 * Put a single character. This is for 16-pixel wide fonts.
435 */
436 static void
437 rasops8_putchar16(cookie, row, col, uc, attr)
438 void *cookie;
439 int row, col;
440 u_int uc;
441 long attr;
442 {
443 struct rasops_info *ri;
444 int height, fs;
445 int32_t *rp, *hrp;
446 u_char *fr;
447
448 /* Can't risk remaking the stamp if it's already in use */
449 if (stamp_mutex++) {
450 stamp_mutex--;
451 rasops8_putchar(cookie, row, col, uc, attr);
452 return;
453 }
454
455 ri = (struct rasops_info *)cookie;
456 hrp = NULL;
457
458 if (!CHAR_IN_FONT(uc, ri->ri_font))
459 return;
460
461 #ifdef RASOPS_CLIPPING
462 if ((unsigned)row >= (unsigned)ri->ri_rows) {
463 stamp_mutex--;
464 return;
465 }
466
467 if ((unsigned)col >= (unsigned)ri->ri_cols) {
468 stamp_mutex--;
469 return;
470 }
471 #endif
472
473 /* Recompute stamp? */
474 if (attr != stamp_attr)
475 rasops8_makestamp(ri, attr);
476
477 rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
478 if (ri->ri_hwbits)
479 hrp = (int32_t *)(ri->ri_hwbits + row*ri->ri_yscale +
480 col*ri->ri_xscale);
481
482 height = ri->ri_font->fontheight;
483
484 if (uc == ' ') {
485 while (height--) {
486 rp[0] = rp[1] = rp[2] = rp[3] = stamp[0];
487 if (ri->ri_hwbits) {
488 hrp[0] = stamp[0];
489 hrp[1] = stamp[0];
490 hrp[2] = stamp[0];
491 hrp[3] = stamp[0];
492 }
493 }
494 } else {
495 uc -= ri->ri_font->firstchar;
496 fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
497 fs = ri->ri_font->stride;
498
499 while (height--) {
500 rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
501 rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
502 rp[2] = STAMP_READ(STAMP_SHIFT(fr[1], 1) & STAMP_MASK);
503 rp[3] = STAMP_READ(STAMP_SHIFT(fr[1], 0) & STAMP_MASK);
504 if (ri->ri_hwbits) {
505 hrp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
506 hrp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
507 hrp[2] = STAMP_READ(STAMP_SHIFT(fr[1], 1) & STAMP_MASK);
508 hrp[3] = STAMP_READ(STAMP_SHIFT(fr[1], 0) & STAMP_MASK);
509 }
510
511 fr += fs;
512 DELTA(rp, ri->ri_stride, int32_t *);
513 if (ri->ri_hwbits)
514 DELTA(hrp, ri->ri_stride, int32_t *);
515 }
516 }
517
518 /* Do underline */
519 if ((attr & 1) != 0) {
520 DELTA(rp, -(ri->ri_stride << 1), int32_t *);
521 rp[0] = rp[1] = rp[2] = rp[3] = stamp[15];
522 if (ri->ri_hwbits) {
523 DELTA(hrp, -(ri->ri_stride << 1), int32_t *);
524 hrp[0] = stamp[15];
525 hrp[1] = stamp[15];
526 hrp[2] = stamp[15];
527 hrp[3] = stamp[15];
528 }
529 }
530
531 stamp_mutex--;
532 }
533 #endif /* !RASOPS_SMALL */
534