rasops8.c revision 1.28 1 /* $NetBSD: rasops8.c,v 1.28 2011/12/28 08:36:46 macallan 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.28 2011/12/28 08:36:46 macallan 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 if (ri->ri_flg & RI_8BIT_IS_RGB) {
95 ri->ri_rnum = 3;
96 ri->ri_rpos = 5;
97 ri->ri_gnum = 3;
98 ri->ri_gpos = 2;
99 ri->ri_bnum = 2;
100 ri->ri_bpos = 0;
101 }
102 }
103
104 /*
105 * Put a single character.
106 */
107 static void
108 rasops8_putchar(void *cookie, int row, int col, u_int uc, long attr)
109 {
110 int width, height, cnt, fs, fb;
111 u_char *dp, *rp, *hp, *hrp, *fr, clr[2];
112 struct rasops_info *ri = (struct rasops_info *)cookie;
113 struct wsdisplay_font *font = PICK_FONT(ri, uc);
114
115 hp = hrp = NULL;
116
117 if (!CHAR_IN_FONT(uc, font))
118 return;
119
120 #ifdef RASOPS_CLIPPING
121 /* Catches 'row < 0' case too */
122 if ((unsigned)row >= (unsigned)ri->ri_rows)
123 return;
124
125 if ((unsigned)col >= (unsigned)ri->ri_cols)
126 return;
127 #endif
128 rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
129 if (ri->ri_hwbits)
130 hrp = ri->ri_hwbits + row * ri->ri_yscale + col *
131 ri->ri_xscale;
132
133 height = font->fontheight;
134 width = font->fontwidth;
135 clr[0] = (u_char)ri->ri_devcmap[(attr >> 16) & 0xf];
136 clr[1] = (u_char)ri->ri_devcmap[(attr >> 24) & 0xf];
137
138 if (uc == ' ') {
139 u_char c = clr[0];
140
141 while (height--) {
142 dp = rp;
143 rp += ri->ri_stride;
144 if (ri->ri_hwbits) {
145 hp = hrp;
146 hrp += ri->ri_stride;
147 }
148
149 for (cnt = width; cnt; cnt--) {
150 *dp++ = c;
151 if (ri->ri_hwbits)
152 *hp++ = c;
153 }
154 }
155 } else {
156 uc -= font->firstchar;
157 fr = (u_char *)font->data + uc * ri->ri_fontscale;
158 fs = font->stride;
159
160 while (height--) {
161 dp = rp;
162 if (ri->ri_hwbits)
163 hp = hrp;
164 fb = fr[3] | (fr[2] << 8) | (fr[1] << 16) | (fr[0] << 24);
165 fr += fs;
166 rp += ri->ri_stride;
167 if (ri->ri_hwbits)
168 hrp += ri->ri_stride;
169
170 for (cnt = width; cnt; cnt--) {
171 *dp++ = clr[(fb >> 31) & 1];
172 if (ri->ri_hwbits)
173 *hp++ = clr[(fb >> 31) & 1];
174 fb <<= 1;
175 }
176 }
177 }
178
179 /* Do underline */
180 if ((attr & 1) != 0) {
181 u_char c = clr[1];
182
183 rp -= (ri->ri_stride << 1);
184 if (ri->ri_hwbits)
185 hrp -= (ri->ri_stride << 1);
186
187 while (width--) {
188 *rp++ = c;
189 if (ri->ri_hwbits)
190 *hrp++ = c;
191 }
192 }
193 }
194
195 #ifndef RASOPS_SMALL
196 /*
197 * Recompute the 4x1 blitting stamp.
198 */
199 static void
200 rasops8_makestamp(struct rasops_info *ri, long attr)
201 {
202 int32_t fg, bg;
203 int i;
204
205 fg = ri->ri_devcmap[(attr >> 24) & 0xf] & 0xff;
206 bg = ri->ri_devcmap[(attr >> 16) & 0xf] & 0xff;
207 stamp_attr = attr;
208
209 for (i = 0; i < 16; i++) {
210 #if BYTE_ORDER == BIG_ENDIAN
211 #define NEED_LITTLE_ENDIAN_STAMP RI_BSWAP
212 #else
213 #define NEED_LITTLE_ENDIAN_STAMP 0
214 #endif
215 if ((ri->ri_flg & RI_BSWAP) == NEED_LITTLE_ENDIAN_STAMP) {
216 /* little endian */
217 stamp[i] = (i & 8 ? fg : bg);
218 stamp[i] |= ((i & 4 ? fg : bg) << 8);
219 stamp[i] |= ((i & 2 ? fg : bg) << 16);
220 stamp[i] |= ((i & 1 ? fg : bg) << 24);
221 } else {
222 /* big endian */
223 stamp[i] = (i & 1 ? fg : bg);
224 stamp[i] |= ((i & 2 ? fg : bg) << 8);
225 stamp[i] |= ((i & 4 ? fg : bg) << 16);
226 stamp[i] |= ((i & 8 ? fg : bg) << 24);
227 }
228 }
229 }
230
231 /*
232 * Put a single character. This is for 8-pixel wide fonts.
233 */
234 static void
235 rasops8_putchar8(void *cookie, int row, int col, u_int uc, long attr)
236 {
237 struct rasops_info *ri = (struct rasops_info *)cookie;
238 struct wsdisplay_font *font = PICK_FONT(ri, uc);
239 int height, fs;
240 int32_t *rp, *hp;
241 u_char *fr;
242
243 /* Can't risk remaking the stamp if it's already in use */
244 if (stamp_mutex++) {
245 stamp_mutex--;
246 rasops8_putchar(cookie, row, col, uc, attr);
247 return;
248 }
249
250 hp = NULL;
251
252 if (!CHAR_IN_FONT(uc, 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 = 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 -= font->firstchar;
289 fr = (u_char *)font->data + uc * ri->ri_fontscale;
290 fs = 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(void *cookie, int row, int col, u_int uc, long attr)
328 {
329 struct rasops_info *ri = (struct rasops_info *)cookie;
330 struct wsdisplay_font *font = PICK_FONT(ri, uc);
331 int height, fs;
332 int32_t *rp, *hrp;
333 u_char *fr;
334
335 /* Can't risk remaking the stamp if it's already in use */
336 if (stamp_mutex++) {
337 stamp_mutex--;
338 rasops8_putchar(cookie, row, col, uc, attr);
339 return;
340 }
341
342 hrp = NULL;
343
344 if (!CHAR_IN_FONT(uc, font))
345 return;
346
347 #ifdef RASOPS_CLIPPING
348 if ((unsigned)row >= (unsigned)ri->ri_rows) {
349 stamp_mutex--;
350 return;
351 }
352
353 if ((unsigned)col >= (unsigned)ri->ri_cols) {
354 stamp_mutex--;
355 return;
356 }
357 #endif
358
359 /* Recompute stamp? */
360 if (attr != stamp_attr)
361 rasops8_makestamp(ri, attr);
362
363 rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
364 if (ri->ri_hwbits)
365 hrp = (int32_t *)(ri->ri_hwbits + row*ri->ri_yscale +
366 col*ri->ri_xscale);
367 height = font->fontheight;
368
369 if (uc == ' ') {
370 while (height--) {
371 int32_t c = stamp[0];
372
373 rp[0] = rp[1] = rp[2] = c;
374 DELTA(rp, ri->ri_stride, int32_t *);
375 if (ri->ri_hwbits) {
376 hrp[0] = c;
377 hrp[1] = c;
378 hrp[2] = c;
379 DELTA(hrp, ri->ri_stride, int32_t *);
380 }
381 }
382 } else {
383 uc -= font->firstchar;
384 fr = (u_char *)font->data + uc * ri->ri_fontscale;
385 fs = font->stride;
386
387 while (height--) {
388 rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
389 rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
390 rp[2] = STAMP_READ(STAMP_SHIFT(fr[1], 1) & STAMP_MASK);
391 if (ri->ri_hwbits) {
392 hrp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
393 hrp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
394 hrp[2] = STAMP_READ(STAMP_SHIFT(fr[1], 1) & STAMP_MASK);
395 }
396
397 fr += fs;
398 DELTA(rp, ri->ri_stride, int32_t *);
399 if (ri->ri_hwbits)
400 DELTA(hrp, ri->ri_stride, int32_t *);
401 }
402 }
403
404 /* Do underline */
405 if ((attr & 1) != 0) {
406 DELTA(rp, -(ri->ri_stride << 1), int32_t *);
407 rp[0] = rp[1] = rp[2] = stamp[15];
408 if (ri->ri_hwbits) {
409 DELTA(hrp, -(ri->ri_stride << 1), int32_t *);
410 hrp[0] = stamp[15];
411 hrp[1] = stamp[15];
412 hrp[2] = stamp[15];
413 }
414 }
415
416 stamp_mutex--;
417 }
418
419 /*
420 * Put a single character. This is for 16-pixel wide fonts.
421 */
422 static void
423 rasops8_putchar16(void *cookie, int row, int col, u_int uc, long attr)
424 {
425 struct rasops_info *ri = (struct rasops_info *)cookie;
426 struct wsdisplay_font *font = PICK_FONT(ri, uc);
427 int height, fs;
428 int32_t *rp, *hrp;
429 u_char *fr;
430
431 /* Can't risk remaking the stamp if it's already in use */
432 if (stamp_mutex++) {
433 stamp_mutex--;
434 rasops8_putchar(cookie, row, col, uc, attr);
435 return;
436 }
437
438 hrp = NULL;
439
440 if (!CHAR_IN_FONT(uc, font))
441 return;
442
443 #ifdef RASOPS_CLIPPING
444 if ((unsigned)row >= (unsigned)ri->ri_rows) {
445 stamp_mutex--;
446 return;
447 }
448
449 if ((unsigned)col >= (unsigned)ri->ri_cols) {
450 stamp_mutex--;
451 return;
452 }
453 #endif
454
455 /* Recompute stamp? */
456 if (attr != stamp_attr)
457 rasops8_makestamp(ri, attr);
458
459 rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
460 if (ri->ri_hwbits)
461 hrp = (int32_t *)(ri->ri_hwbits + row*ri->ri_yscale +
462 col*ri->ri_xscale);
463
464 height = font->fontheight;
465
466 if (uc == ' ') {
467 while (height--) {
468 rp[0] = rp[1] = rp[2] = rp[3] = stamp[0];
469 if (ri->ri_hwbits) {
470 hrp[0] = stamp[0];
471 hrp[1] = stamp[0];
472 hrp[2] = stamp[0];
473 hrp[3] = stamp[0];
474 }
475 }
476 } else {
477 uc -= font->firstchar;
478 fr = (u_char *)font->data + uc * ri->ri_fontscale;
479 fs = font->stride;
480
481 while (height--) {
482 rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
483 rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
484 rp[2] = STAMP_READ(STAMP_SHIFT(fr[1], 1) & STAMP_MASK);
485 rp[3] = STAMP_READ(STAMP_SHIFT(fr[1], 0) & STAMP_MASK);
486 if (ri->ri_hwbits) {
487 hrp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
488 hrp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
489 hrp[2] = STAMP_READ(STAMP_SHIFT(fr[1], 1) & STAMP_MASK);
490 hrp[3] = STAMP_READ(STAMP_SHIFT(fr[1], 0) & STAMP_MASK);
491 }
492
493 fr += fs;
494 DELTA(rp, ri->ri_stride, int32_t *);
495 if (ri->ri_hwbits)
496 DELTA(hrp, ri->ri_stride, int32_t *);
497 }
498 }
499
500 /* Do underline */
501 if ((attr & 1) != 0) {
502 DELTA(rp, -(ri->ri_stride << 1), int32_t *);
503 rp[0] = rp[1] = rp[2] = rp[3] = stamp[15];
504 if (ri->ri_hwbits) {
505 DELTA(hrp, -(ri->ri_stride << 1), int32_t *);
506 hrp[0] = stamp[15];
507 hrp[1] = stamp[15];
508 hrp[2] = stamp[15];
509 hrp[3] = stamp[15];
510 }
511 }
512
513 stamp_mutex--;
514 }
515 #endif /* !RASOPS_SMALL */
516