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