rasops8.c revision 1.9 1 /* $NetBSD: rasops8.c,v 1.9 2000/06/13 13:36:59 ad 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 "opt_rasops.h"
40 #include <sys/cdefs.h>
41 __KERNEL_RCSID(0, "$NetBSD: rasops8.c,v 1.9 2000/06/13 13:36:59 ad Exp $");
42
43 #include <sys/types.h>
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 __P((void *, int, int, u_int, long attr));
53 #ifndef RASOPS_SMALL
54 static void rasops8_putchar8 __P((void *, int, int, u_int, long attr));
55 static void rasops8_putchar12 __P((void *, int, int, u_int, long attr));
56 static void rasops8_putchar16 __P((void *, int, int, u_int, long attr));
57 static void rasops8_makestamp __P((struct rasops_info *ri, long));
58 #endif
59
60 /*
61 * 4x1 stamp for optimized character blitting
62 */
63 static int32_t stamp[16];
64 static long stamp_attr;
65 static int stamp_mutex; /* XXX see note in README */
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 * Initalize 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 #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
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
142 for (cnt = width; cnt; cnt--)
143 *dp++ = c;
144 }
145 } else {
146 uc -= ri->ri_font->firstchar;
147 fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
148 fs = ri->ri_font->stride;
149
150 while (height--) {
151 dp = rp;
152 fb = fr[3] | (fr[2] << 8) | (fr[1] << 16) | (fr[0] << 24);
153 fr += fs;
154 rp += ri->ri_stride;
155
156 for (cnt = width; cnt; cnt--) {
157 *dp++ = clr[(fb >> 31) & 1];
158 fb <<= 1;
159 }
160 }
161 }
162
163 /* Do underline */
164 if ((attr & 1) != 0) {
165 u_char c = clr[1];
166
167 rp -= (ri->ri_stride << 1);
168
169 while (width--)
170 *rp++ = c;
171 }
172 }
173
174 #ifndef RASOPS_SMALL
175 /*
176 * Recompute the 4x1 blitting stamp.
177 */
178 static void
179 rasops8_makestamp(ri, attr)
180 struct rasops_info *ri;
181 long attr;
182 {
183 int32_t fg, bg;
184 int i;
185
186 fg = ri->ri_devcmap[(attr >> 24) & 0xf] & 0xff;
187 bg = ri->ri_devcmap[(attr >> 16) & 0xf] & 0xff;
188 stamp_attr = attr;
189
190 for (i = 0; i < 16; i++) {
191 #if BYTE_ORDER == LITTLE_ENDIAN
192 stamp[i] = (i & 8 ? fg : bg);
193 stamp[i] |= ((i & 4 ? fg : bg) << 8);
194 stamp[i] |= ((i & 2 ? fg : bg) << 16);
195 stamp[i] |= ((i & 1 ? fg : bg) << 24);
196 #else
197 stamp[i] = (i & 1 ? fg : bg);
198 stamp[i] |= ((i & 2 ? fg : bg) << 8);
199 stamp[i] |= ((i & 4 ? fg : bg) << 16);
200 stamp[i] |= ((i & 8 ? fg : bg) << 24);
201 #endif
202 }
203 }
204
205 /*
206 * Put a single character. This is for 8-pixel wide fonts.
207 */
208 static void
209 rasops8_putchar8(cookie, row, col, uc, attr)
210 void *cookie;
211 int row, col;
212 u_int uc;
213 long attr;
214 {
215 struct rasops_info *ri;
216 int height, fs;
217 int32_t *rp;
218 u_char *fr;
219
220 /* Can't risk remaking the stamp if it's already in use */
221 if (stamp_mutex++) {
222 stamp_mutex--;
223 rasops8_putchar(cookie, row, col, uc, attr);
224 return;
225 }
226
227 ri = (struct rasops_info *)cookie;
228
229 #ifdef RASOPS_CLIPPING
230 if ((unsigned)row >= (unsigned)ri->ri_rows) {
231 stamp_mutex--;
232 return;
233 }
234
235 if ((unsigned)col >= (unsigned)ri->ri_cols) {
236 stamp_mutex--;
237 return;
238 }
239 #endif
240
241 /* Recompute stamp? */
242 if (attr != stamp_attr)
243 rasops8_makestamp(ri, attr);
244
245 rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
246 height = ri->ri_font->fontheight;
247
248 if (uc == ' ') {
249 while (height--) {
250 rp[0] = rp[1] = stamp[0];
251 DELTA(rp, ri->ri_stride, int32_t *);
252 }
253 } else {
254 uc -= ri->ri_font->firstchar;
255 fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
256 fs = ri->ri_font->stride;
257
258 while (height--) {
259 rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
260 rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
261
262 fr += fs;
263 DELTA(rp, ri->ri_stride, int32_t *);
264 }
265 }
266
267 /* Do underline */
268 if ((attr & 1) != 0) {
269 DELTA(rp, -(ri->ri_stride << 1), int32_t *);
270 rp[0] = rp[1] = stamp[15];
271 }
272
273 stamp_mutex--;
274 }
275
276 /*
277 * Put a single character. This is for 12-pixel wide fonts.
278 */
279 static void
280 rasops8_putchar12(cookie, row, col, uc, attr)
281 void *cookie;
282 int row, col;
283 u_int uc;
284 long attr;
285 {
286 struct rasops_info *ri;
287 int height, fs;
288 int32_t *rp;
289 u_char *fr;
290
291 /* Can't risk remaking the stamp if it's already in use */
292 if (stamp_mutex++) {
293 stamp_mutex--;
294 rasops8_putchar(cookie, row, col, uc, attr);
295 return;
296 }
297
298 ri = (struct rasops_info *)cookie;
299
300 #ifdef RASOPS_CLIPPING
301 if ((unsigned)row >= (unsigned)ri->ri_rows) {
302 stamp_mutex--;
303 return;
304 }
305
306 if ((unsigned)col >= (unsigned)ri->ri_cols) {
307 stamp_mutex--;
308 return;
309 }
310 #endif
311
312 /* Recompute stamp? */
313 if (attr != stamp_attr)
314 rasops8_makestamp(ri, attr);
315
316 rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
317 height = ri->ri_font->fontheight;
318
319 if (uc == ' ') {
320 while (height--) {
321 int32_t c = stamp[0];
322
323 rp[0] = rp[1] = rp[2] = c;
324 DELTA(rp, ri->ri_stride, int32_t *);
325 }
326 } else {
327 uc -= ri->ri_font->firstchar;
328 fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
329 fs = ri->ri_font->stride;
330
331 while (height--) {
332 rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
333 rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
334 rp[2] = STAMP_READ(STAMP_SHIFT(fr[1], 1) & STAMP_MASK);
335
336 fr += fs;
337 DELTA(rp, ri->ri_stride, int32_t *);
338 }
339 }
340
341 /* Do underline */
342 if ((attr & 1) != 0) {
343 DELTA(rp, -(ri->ri_stride << 1), int32_t *);
344 rp[0] = rp[1] = rp[2] = stamp[15];
345 }
346
347 stamp_mutex--;
348 }
349
350 /*
351 * Put a single character. This is for 16-pixel wide fonts.
352 */
353 static void
354 rasops8_putchar16(cookie, row, col, uc, attr)
355 void *cookie;
356 int row, col;
357 u_int uc;
358 long attr;
359 {
360 struct rasops_info *ri;
361 int height, fs;
362 int32_t *rp;
363 u_char *fr;
364
365 /* Can't risk remaking the stamp if it's already in use */
366 if (stamp_mutex++) {
367 stamp_mutex--;
368 rasops8_putchar(cookie, row, col, uc, attr);
369 return;
370 }
371
372 ri = (struct rasops_info *)cookie;
373
374 #ifdef RASOPS_CLIPPING
375 if ((unsigned)row >= (unsigned)ri->ri_rows) {
376 stamp_mutex--;
377 return;
378 }
379
380 if ((unsigned)col >= (unsigned)ri->ri_cols) {
381 stamp_mutex--;
382 return;
383 }
384 #endif
385
386 /* Recompute stamp? */
387 if (attr != stamp_attr)
388 rasops8_makestamp(ri, attr);
389
390 rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
391 height = ri->ri_font->fontheight;
392
393 if (uc == ' ') {
394 while (height--)
395 rp[0] = rp[1] = rp[2] = rp[3] = stamp[0];
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 rp[3] = STAMP_READ(STAMP_SHIFT(fr[1], 0) & STAMP_MASK);
406
407 fr += fs;
408 DELTA(rp, ri->ri_stride, int32_t *);
409 }
410 }
411
412 /* Do underline */
413 if ((attr & 1) != 0) {
414 DELTA(rp, -(ri->ri_stride << 1), int32_t *);
415 rp[0] = rp[1] = rp[2] = rp[3] = stamp[15];
416 }
417
418 stamp_mutex--;
419 }
420 #endif /* !RASOPS_SMALL */
421