rasops8.c revision 1.16.16.5 1 /* $NetBSD: rasops8.c,v 1.16.16.5 2005/11/10 14:07:47 skrll 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.16.16.5 2005/11/10 14:07:47 skrll 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 *)((caddr_t)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, *fr, clr[2];
116 struct rasops_info *ri;
117
118 ri = (struct rasops_info *)cookie;
119
120 if (!CHAR_IN_FONT(uc, ri->ri_font))
121 return;
122
123 #ifdef RASOPS_CLIPPING
124 /* Catches 'row < 0' case too */
125 if ((unsigned)row >= (unsigned)ri->ri_rows)
126 return;
127
128 if ((unsigned)col >= (unsigned)ri->ri_cols)
129 return;
130 #endif
131 rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
132
133 height = ri->ri_font->fontheight;
134 width = ri->ri_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
145 for (cnt = width; cnt; cnt--)
146 *dp++ = c;
147 }
148 } else {
149 uc -= ri->ri_font->firstchar;
150 fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
151 fs = ri->ri_font->stride;
152
153 while (height--) {
154 dp = rp;
155 fb = fr[3] | (fr[2] << 8) | (fr[1] << 16) | (fr[0] << 24);
156 fr += fs;
157 rp += ri->ri_stride;
158
159 for (cnt = width; cnt; cnt--) {
160 *dp++ = clr[(fb >> 31) & 1];
161 fb <<= 1;
162 }
163 }
164 }
165
166 /* Do underline */
167 if ((attr & 1) != 0) {
168 u_char c = clr[1];
169
170 rp -= (ri->ri_stride << 1);
171
172 while (width--)
173 *rp++ = c;
174 }
175 }
176
177 #ifndef RASOPS_SMALL
178 /*
179 * Recompute the 4x1 blitting stamp.
180 */
181 static void
182 rasops8_makestamp(ri, attr)
183 struct rasops_info *ri;
184 long attr;
185 {
186 int32_t fg, bg;
187 int i;
188
189 fg = ri->ri_devcmap[(attr >> 24) & 0xf] & 0xff;
190 bg = ri->ri_devcmap[(attr >> 16) & 0xf] & 0xff;
191 stamp_attr = attr;
192
193 for (i = 0; i < 16; i++) {
194 #if BYTE_ORDER == BIG_ENDIAN
195 #define NEED_LITTLE_ENDIAN_STAMP RI_BSWAP
196 #else
197 #define NEED_LITTLE_ENDIAN_STAMP 0
198 #endif
199 if ((ri->ri_flg & RI_BSWAP) == NEED_LITTLE_ENDIAN_STAMP) {
200 /* little endian */
201 stamp[i] = (i & 8 ? fg : bg);
202 stamp[i] |= ((i & 4 ? fg : bg) << 8);
203 stamp[i] |= ((i & 2 ? fg : bg) << 16);
204 stamp[i] |= ((i & 1 ? fg : bg) << 24);
205 } else {
206 /* big endian */
207 stamp[i] = (i & 1 ? fg : bg);
208 stamp[i] |= ((i & 2 ? fg : bg) << 8);
209 stamp[i] |= ((i & 4 ? fg : bg) << 16);
210 stamp[i] |= ((i & 8 ? fg : bg) << 24);
211 }
212 }
213 }
214
215 /*
216 * Put a single character. This is for 8-pixel wide fonts.
217 */
218 static void
219 rasops8_putchar8(cookie, row, col, uc, attr)
220 void *cookie;
221 int row, col;
222 u_int uc;
223 long attr;
224 {
225 struct rasops_info *ri;
226 int height, fs;
227 int32_t *rp;
228 u_char *fr;
229
230 /* Can't risk remaking the stamp if it's already in use */
231 if (stamp_mutex++) {
232 stamp_mutex--;
233 rasops8_putchar(cookie, row, col, uc, attr);
234 return;
235 }
236
237 ri = (struct rasops_info *)cookie;
238
239 if (!CHAR_IN_FONT(uc, ri->ri_font))
240 return;
241
242 #ifdef RASOPS_CLIPPING
243 if ((unsigned)row >= (unsigned)ri->ri_rows) {
244 stamp_mutex--;
245 return;
246 }
247
248 if ((unsigned)col >= (unsigned)ri->ri_cols) {
249 stamp_mutex--;
250 return;
251 }
252 #endif
253
254 /* Recompute stamp? */
255 if (attr != stamp_attr)
256 rasops8_makestamp(ri, attr);
257
258 rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
259 height = ri->ri_font->fontheight;
260
261 if (uc == ' ') {
262 while (height--) {
263 rp[0] = rp[1] = stamp[0];
264 DELTA(rp, ri->ri_stride, int32_t *);
265 }
266 } else {
267 uc -= ri->ri_font->firstchar;
268 fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
269 fs = ri->ri_font->stride;
270
271 while (height--) {
272 rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
273 rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
274
275 fr += fs;
276 DELTA(rp, ri->ri_stride, int32_t *);
277 }
278 }
279
280 /* Do underline */
281 if ((attr & 1) != 0) {
282 DELTA(rp, -(ri->ri_stride << 1), int32_t *);
283 rp[0] = rp[1] = stamp[15];
284 }
285
286 stamp_mutex--;
287 }
288
289 /*
290 * Put a single character. This is for 12-pixel wide fonts.
291 */
292 static void
293 rasops8_putchar12(cookie, row, col, uc, attr)
294 void *cookie;
295 int row, col;
296 u_int uc;
297 long attr;
298 {
299 struct rasops_info *ri;
300 int height, fs;
301 int32_t *rp;
302 u_char *fr;
303
304 /* Can't risk remaking the stamp if it's already in use */
305 if (stamp_mutex++) {
306 stamp_mutex--;
307 rasops8_putchar(cookie, row, col, uc, attr);
308 return;
309 }
310
311 ri = (struct rasops_info *)cookie;
312
313 if (!CHAR_IN_FONT(uc, ri->ri_font))
314 return;
315
316 #ifdef RASOPS_CLIPPING
317 if ((unsigned)row >= (unsigned)ri->ri_rows) {
318 stamp_mutex--;
319 return;
320 }
321
322 if ((unsigned)col >= (unsigned)ri->ri_cols) {
323 stamp_mutex--;
324 return;
325 }
326 #endif
327
328 /* Recompute stamp? */
329 if (attr != stamp_attr)
330 rasops8_makestamp(ri, attr);
331
332 rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
333 height = ri->ri_font->fontheight;
334
335 if (uc == ' ') {
336 while (height--) {
337 int32_t c = stamp[0];
338
339 rp[0] = rp[1] = rp[2] = c;
340 DELTA(rp, ri->ri_stride, int32_t *);
341 }
342 } else {
343 uc -= ri->ri_font->firstchar;
344 fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
345 fs = ri->ri_font->stride;
346
347 while (height--) {
348 rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
349 rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
350 rp[2] = STAMP_READ(STAMP_SHIFT(fr[1], 1) & STAMP_MASK);
351
352 fr += fs;
353 DELTA(rp, ri->ri_stride, int32_t *);
354 }
355 }
356
357 /* Do underline */
358 if ((attr & 1) != 0) {
359 DELTA(rp, -(ri->ri_stride << 1), int32_t *);
360 rp[0] = rp[1] = rp[2] = stamp[15];
361 }
362
363 stamp_mutex--;
364 }
365
366 /*
367 * Put a single character. This is for 16-pixel wide fonts.
368 */
369 static void
370 rasops8_putchar16(cookie, row, col, uc, attr)
371 void *cookie;
372 int row, col;
373 u_int uc;
374 long attr;
375 {
376 struct rasops_info *ri;
377 int height, fs;
378 int32_t *rp;
379 u_char *fr;
380
381 /* Can't risk remaking the stamp if it's already in use */
382 if (stamp_mutex++) {
383 stamp_mutex--;
384 rasops8_putchar(cookie, row, col, uc, attr);
385 return;
386 }
387
388 ri = (struct rasops_info *)cookie;
389
390 if (!CHAR_IN_FONT(uc, ri->ri_font))
391 return;
392
393 #ifdef RASOPS_CLIPPING
394 if ((unsigned)row >= (unsigned)ri->ri_rows) {
395 stamp_mutex--;
396 return;
397 }
398
399 if ((unsigned)col >= (unsigned)ri->ri_cols) {
400 stamp_mutex--;
401 return;
402 }
403 #endif
404
405 /* Recompute stamp? */
406 if (attr != stamp_attr)
407 rasops8_makestamp(ri, attr);
408
409 rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
410 height = ri->ri_font->fontheight;
411
412 if (uc == ' ') {
413 while (height--)
414 rp[0] = rp[1] = rp[2] = rp[3] = stamp[0];
415 } else {
416 uc -= ri->ri_font->firstchar;
417 fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
418 fs = ri->ri_font->stride;
419
420 while (height--) {
421 rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
422 rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
423 rp[2] = STAMP_READ(STAMP_SHIFT(fr[1], 1) & STAMP_MASK);
424 rp[3] = STAMP_READ(STAMP_SHIFT(fr[1], 0) & STAMP_MASK);
425
426 fr += fs;
427 DELTA(rp, ri->ri_stride, int32_t *);
428 }
429 }
430
431 /* Do underline */
432 if ((attr & 1) != 0) {
433 DELTA(rp, -(ri->ri_stride << 1), int32_t *);
434 rp[0] = rp[1] = rp[2] = rp[3] = stamp[15];
435 }
436
437 stamp_mutex--;
438 }
439 #endif /* !RASOPS_SMALL */
440