rasops8.c revision 1.9.4.5 1 /* $NetBSD: rasops8.c,v 1.9.4.5 2002/02/28 04:14:19 nathanw 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.9.4.5 2002/02/28 04:14:19 nathanw Exp $");
41
42 #include "opt_rasops.h"
43
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/time.h>
47 #include <sys/bswap.h>
48
49 #include <dev/wscons/wsdisplayvar.h>
50 #include <dev/wscons/wsconsio.h>
51 #include <dev/rasops/rasops.h>
52
53 static void rasops8_putchar __P((void *, int, int, u_int, long attr));
54 #ifndef RASOPS_SMALL
55 static void rasops8_putchar8 __P((void *, int, int, u_int, long attr));
56 static void rasops8_putchar12 __P((void *, int, int, u_int, long attr));
57 static void rasops8_putchar16 __P((void *, int, int, u_int, long attr));
58 static void rasops8_makestamp __P((struct rasops_info *ri, long));
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 #endif
67
68 /*
69 * XXX this confuses the hell out of gcc2 (not egcs) which always insists
70 * that the shift count is negative.
71 *
72 * offset = STAMP_SHIFT(fontbits, nibble #) & STAMP_MASK
73 * destination = STAMP_READ(offset)
74 */
75 #define STAMP_SHIFT(fb,n) ((n*4-2) >= 0 ? (fb)>>(n*4-2):(fb)<<-(n*4-2))
76 #define STAMP_MASK (0xf << 2)
77 #define STAMP_READ(o) (*(int32_t *)((caddr_t)stamp + (o)))
78
79 /*
80 * Initialize a 'rasops_info' descriptor for this depth.
81 */
82 void
83 rasops8_init(ri)
84 struct rasops_info *ri;
85 {
86
87 switch (ri->ri_font->fontwidth) {
88 #ifndef RASOPS_SMALL
89 case 8:
90 ri->ri_ops.putchar = rasops8_putchar8;
91 break;
92 case 12:
93 ri->ri_ops.putchar = rasops8_putchar12;
94 break;
95 case 16:
96 ri->ri_ops.putchar = rasops8_putchar16;
97 break;
98 #endif /* !RASOPS_SMALL */
99 default:
100 ri->ri_ops.putchar = rasops8_putchar;
101 break;
102 }
103 }
104
105 /*
106 * Put a single character.
107 */
108 static void
109 rasops8_putchar(cookie, row, col, uc, attr)
110 void *cookie;
111 int row, col;
112 u_int uc;
113 long attr;
114 {
115 int width, height, cnt, fs, fb;
116 u_char *dp, *rp, *fr, clr[2];
117 struct rasops_info *ri;
118
119 ri = (struct rasops_info *)cookie;
120
121 #ifdef RASOPS_CLIPPING
122 /* Catches 'row < 0' case too */
123 if ((unsigned)row >= (unsigned)ri->ri_rows)
124 return;
125
126 if ((unsigned)col >= (unsigned)ri->ri_cols)
127 return;
128 #endif
129 rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
130
131 height = ri->ri_font->fontheight;
132 width = ri->ri_font->fontwidth;
133 clr[0] = (u_char)ri->ri_devcmap[(attr >> 16) & 0xf];
134 clr[1] = (u_char)ri->ri_devcmap[(attr >> 24) & 0xf];
135
136 if (uc == ' ') {
137 u_char c = clr[0];
138
139 while (height--) {
140 dp = rp;
141 rp += ri->ri_stride;
142
143 for (cnt = width; cnt; cnt--)
144 *dp++ = c;
145 }
146 } else {
147 uc -= ri->ri_font->firstchar;
148 fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
149 fs = ri->ri_font->stride;
150
151 while (height--) {
152 dp = rp;
153 fb = fr[3] | (fr[2] << 8) | (fr[1] << 16) | (fr[0] << 24);
154 fr += fs;
155 rp += ri->ri_stride;
156
157 for (cnt = width; cnt; cnt--) {
158 *dp++ = clr[(fb >> 31) & 1];
159 fb <<= 1;
160 }
161 }
162 }
163
164 /* Do underline */
165 if ((attr & 1) != 0) {
166 u_char c = clr[1];
167
168 rp -= (ri->ri_stride << 1);
169
170 while (width--)
171 *rp++ = c;
172 }
173 }
174
175 #ifndef RASOPS_SMALL
176 /*
177 * Recompute the 4x1 blitting stamp.
178 */
179 static void
180 rasops8_makestamp(ri, attr)
181 struct rasops_info *ri;
182 long attr;
183 {
184 int32_t fg, bg;
185 int i;
186
187 fg = ri->ri_devcmap[(attr >> 24) & 0xf] & 0xff;
188 bg = ri->ri_devcmap[(attr >> 16) & 0xf] & 0xff;
189 stamp_attr = attr;
190
191 for (i = 0; i < 16; i++) {
192 #if BYTE_ORDER == BIG_ENDIAN
193 #define NEED_LITTLE_ENDIAN_STAMP RI_BSWAP
194 #else
195 #define NEED_LITTLE_ENDIAN_STAMP 0
196 #endif
197 if ((ri->ri_flg & RI_BSWAP) == NEED_LITTLE_ENDIAN_STAMP) {
198 /* little endian */
199 stamp[i] = (i & 8 ? fg : bg);
200 stamp[i] |= ((i & 4 ? fg : bg) << 8);
201 stamp[i] |= ((i & 2 ? fg : bg) << 16);
202 stamp[i] |= ((i & 1 ? fg : bg) << 24);
203 } else {
204 /* big endian */
205 stamp[i] = (i & 1 ? fg : bg);
206 stamp[i] |= ((i & 2 ? fg : bg) << 8);
207 stamp[i] |= ((i & 4 ? fg : bg) << 16);
208 stamp[i] |= ((i & 8 ? fg : bg) << 24);
209 }
210 }
211 }
212
213 /*
214 * Put a single character. This is for 8-pixel wide fonts.
215 */
216 static void
217 rasops8_putchar8(cookie, row, col, uc, attr)
218 void *cookie;
219 int row, col;
220 u_int uc;
221 long attr;
222 {
223 struct rasops_info *ri;
224 int height, fs;
225 int32_t *rp;
226 u_char *fr;
227
228 /* Can't risk remaking the stamp if it's already in use */
229 if (stamp_mutex++) {
230 stamp_mutex--;
231 rasops8_putchar(cookie, row, col, uc, attr);
232 return;
233 }
234
235 ri = (struct rasops_info *)cookie;
236
237 #ifdef RASOPS_CLIPPING
238 if ((unsigned)row >= (unsigned)ri->ri_rows) {
239 stamp_mutex--;
240 return;
241 }
242
243 if ((unsigned)col >= (unsigned)ri->ri_cols) {
244 stamp_mutex--;
245 return;
246 }
247 #endif
248
249 /* Recompute stamp? */
250 if (attr != stamp_attr)
251 rasops8_makestamp(ri, attr);
252
253 rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
254 height = ri->ri_font->fontheight;
255
256 if (uc == ' ') {
257 while (height--) {
258 rp[0] = rp[1] = stamp[0];
259 DELTA(rp, ri->ri_stride, int32_t *);
260 }
261 } else {
262 uc -= ri->ri_font->firstchar;
263 fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
264 fs = ri->ri_font->stride;
265
266 while (height--) {
267 rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
268 rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
269
270 fr += fs;
271 DELTA(rp, ri->ri_stride, int32_t *);
272 }
273 }
274
275 /* Do underline */
276 if ((attr & 1) != 0) {
277 DELTA(rp, -(ri->ri_stride << 1), int32_t *);
278 rp[0] = rp[1] = stamp[15];
279 }
280
281 stamp_mutex--;
282 }
283
284 /*
285 * Put a single character. This is for 12-pixel wide fonts.
286 */
287 static void
288 rasops8_putchar12(cookie, row, col, uc, attr)
289 void *cookie;
290 int row, col;
291 u_int uc;
292 long attr;
293 {
294 struct rasops_info *ri;
295 int height, fs;
296 int32_t *rp;
297 u_char *fr;
298
299 /* Can't risk remaking the stamp if it's already in use */
300 if (stamp_mutex++) {
301 stamp_mutex--;
302 rasops8_putchar(cookie, row, col, uc, attr);
303 return;
304 }
305
306 ri = (struct rasops_info *)cookie;
307
308 #ifdef RASOPS_CLIPPING
309 if ((unsigned)row >= (unsigned)ri->ri_rows) {
310 stamp_mutex--;
311 return;
312 }
313
314 if ((unsigned)col >= (unsigned)ri->ri_cols) {
315 stamp_mutex--;
316 return;
317 }
318 #endif
319
320 /* Recompute stamp? */
321 if (attr != stamp_attr)
322 rasops8_makestamp(ri, attr);
323
324 rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
325 height = ri->ri_font->fontheight;
326
327 if (uc == ' ') {
328 while (height--) {
329 int32_t c = stamp[0];
330
331 rp[0] = rp[1] = rp[2] = c;
332 DELTA(rp, ri->ri_stride, int32_t *);
333 }
334 } else {
335 uc -= ri->ri_font->firstchar;
336 fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
337 fs = ri->ri_font->stride;
338
339 while (height--) {
340 rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
341 rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
342 rp[2] = STAMP_READ(STAMP_SHIFT(fr[1], 1) & STAMP_MASK);
343
344 fr += fs;
345 DELTA(rp, ri->ri_stride, int32_t *);
346 }
347 }
348
349 /* Do underline */
350 if ((attr & 1) != 0) {
351 DELTA(rp, -(ri->ri_stride << 1), int32_t *);
352 rp[0] = rp[1] = rp[2] = stamp[15];
353 }
354
355 stamp_mutex--;
356 }
357
358 /*
359 * Put a single character. This is for 16-pixel wide fonts.
360 */
361 static void
362 rasops8_putchar16(cookie, row, col, uc, attr)
363 void *cookie;
364 int row, col;
365 u_int uc;
366 long attr;
367 {
368 struct rasops_info *ri;
369 int height, fs;
370 int32_t *rp;
371 u_char *fr;
372
373 /* Can't risk remaking the stamp if it's already in use */
374 if (stamp_mutex++) {
375 stamp_mutex--;
376 rasops8_putchar(cookie, row, col, uc, attr);
377 return;
378 }
379
380 ri = (struct rasops_info *)cookie;
381
382 #ifdef RASOPS_CLIPPING
383 if ((unsigned)row >= (unsigned)ri->ri_rows) {
384 stamp_mutex--;
385 return;
386 }
387
388 if ((unsigned)col >= (unsigned)ri->ri_cols) {
389 stamp_mutex--;
390 return;
391 }
392 #endif
393
394 /* Recompute stamp? */
395 if (attr != stamp_attr)
396 rasops8_makestamp(ri, attr);
397
398 rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
399 height = ri->ri_font->fontheight;
400
401 if (uc == ' ') {
402 while (height--)
403 rp[0] = rp[1] = rp[2] = rp[3] = stamp[0];
404 } else {
405 uc -= ri->ri_font->firstchar;
406 fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
407 fs = ri->ri_font->stride;
408
409 while (height--) {
410 rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
411 rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
412 rp[2] = STAMP_READ(STAMP_SHIFT(fr[1], 1) & STAMP_MASK);
413 rp[3] = STAMP_READ(STAMP_SHIFT(fr[1], 0) & STAMP_MASK);
414
415 fr += fs;
416 DELTA(rp, ri->ri_stride, int32_t *);
417 }
418 }
419
420 /* Do underline */
421 if ((attr & 1) != 0) {
422 DELTA(rp, -(ri->ri_stride << 1), int32_t *);
423 rp[0] = rp[1] = rp[2] = rp[3] = stamp[15];
424 }
425
426 stamp_mutex--;
427 }
428 #endif /* !RASOPS_SMALL */
429