rasops8.c revision 1.12 1 /* $NetBSD: rasops8.c,v 1.12 2001/11/13 07:00:23 lukem 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.12 2001/11/13 07:00:23 lukem Exp $");
41
42 #include "opt_rasops.h"
43
44 #include <sys/types.h>
45 #include <sys/param.h>
46 #include <sys/systm.h>
47 #include <sys/time.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 == LITTLE_ENDIAN
193 stamp[i] = (i & 8 ? fg : bg);
194 stamp[i] |= ((i & 4 ? fg : bg) << 8);
195 stamp[i] |= ((i & 2 ? fg : bg) << 16);
196 stamp[i] |= ((i & 1 ? fg : bg) << 24);
197 #else
198 stamp[i] = (i & 1 ? fg : bg);
199 stamp[i] |= ((i & 2 ? fg : bg) << 8);
200 stamp[i] |= ((i & 4 ? fg : bg) << 16);
201 stamp[i] |= ((i & 8 ? fg : bg) << 24);
202 #endif
203 }
204 }
205
206 /*
207 * Put a single character. This is for 8-pixel wide fonts.
208 */
209 static void
210 rasops8_putchar8(cookie, row, col, uc, attr)
211 void *cookie;
212 int row, col;
213 u_int uc;
214 long attr;
215 {
216 struct rasops_info *ri;
217 int height, fs;
218 int32_t *rp;
219 u_char *fr;
220
221 /* Can't risk remaking the stamp if it's already in use */
222 if (stamp_mutex++) {
223 stamp_mutex--;
224 rasops8_putchar(cookie, row, col, uc, attr);
225 return;
226 }
227
228 ri = (struct rasops_info *)cookie;
229
230 #ifdef RASOPS_CLIPPING
231 if ((unsigned)row >= (unsigned)ri->ri_rows) {
232 stamp_mutex--;
233 return;
234 }
235
236 if ((unsigned)col >= (unsigned)ri->ri_cols) {
237 stamp_mutex--;
238 return;
239 }
240 #endif
241
242 /* Recompute stamp? */
243 if (attr != stamp_attr)
244 rasops8_makestamp(ri, attr);
245
246 rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
247 height = ri->ri_font->fontheight;
248
249 if (uc == ' ') {
250 while (height--) {
251 rp[0] = rp[1] = stamp[0];
252 DELTA(rp, ri->ri_stride, int32_t *);
253 }
254 } else {
255 uc -= ri->ri_font->firstchar;
256 fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
257 fs = ri->ri_font->stride;
258
259 while (height--) {
260 rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
261 rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
262
263 fr += fs;
264 DELTA(rp, ri->ri_stride, int32_t *);
265 }
266 }
267
268 /* Do underline */
269 if ((attr & 1) != 0) {
270 DELTA(rp, -(ri->ri_stride << 1), int32_t *);
271 rp[0] = rp[1] = stamp[15];
272 }
273
274 stamp_mutex--;
275 }
276
277 /*
278 * Put a single character. This is for 12-pixel wide fonts.
279 */
280 static void
281 rasops8_putchar12(cookie, row, col, uc, attr)
282 void *cookie;
283 int row, col;
284 u_int uc;
285 long attr;
286 {
287 struct rasops_info *ri;
288 int height, fs;
289 int32_t *rp;
290 u_char *fr;
291
292 /* Can't risk remaking the stamp if it's already in use */
293 if (stamp_mutex++) {
294 stamp_mutex--;
295 rasops8_putchar(cookie, row, col, uc, attr);
296 return;
297 }
298
299 ri = (struct rasops_info *)cookie;
300
301 #ifdef RASOPS_CLIPPING
302 if ((unsigned)row >= (unsigned)ri->ri_rows) {
303 stamp_mutex--;
304 return;
305 }
306
307 if ((unsigned)col >= (unsigned)ri->ri_cols) {
308 stamp_mutex--;
309 return;
310 }
311 #endif
312
313 /* Recompute stamp? */
314 if (attr != stamp_attr)
315 rasops8_makestamp(ri, attr);
316
317 rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
318 height = ri->ri_font->fontheight;
319
320 if (uc == ' ') {
321 while (height--) {
322 int32_t c = stamp[0];
323
324 rp[0] = rp[1] = rp[2] = c;
325 DELTA(rp, ri->ri_stride, int32_t *);
326 }
327 } else {
328 uc -= ri->ri_font->firstchar;
329 fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
330 fs = ri->ri_font->stride;
331
332 while (height--) {
333 rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
334 rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
335 rp[2] = STAMP_READ(STAMP_SHIFT(fr[1], 1) & STAMP_MASK);
336
337 fr += fs;
338 DELTA(rp, ri->ri_stride, int32_t *);
339 }
340 }
341
342 /* Do underline */
343 if ((attr & 1) != 0) {
344 DELTA(rp, -(ri->ri_stride << 1), int32_t *);
345 rp[0] = rp[1] = rp[2] = stamp[15];
346 }
347
348 stamp_mutex--;
349 }
350
351 /*
352 * Put a single character. This is for 16-pixel wide fonts.
353 */
354 static void
355 rasops8_putchar16(cookie, row, col, uc, attr)
356 void *cookie;
357 int row, col;
358 u_int uc;
359 long attr;
360 {
361 struct rasops_info *ri;
362 int height, fs;
363 int32_t *rp;
364 u_char *fr;
365
366 /* Can't risk remaking the stamp if it's already in use */
367 if (stamp_mutex++) {
368 stamp_mutex--;
369 rasops8_putchar(cookie, row, col, uc, attr);
370 return;
371 }
372
373 ri = (struct rasops_info *)cookie;
374
375 #ifdef RASOPS_CLIPPING
376 if ((unsigned)row >= (unsigned)ri->ri_rows) {
377 stamp_mutex--;
378 return;
379 }
380
381 if ((unsigned)col >= (unsigned)ri->ri_cols) {
382 stamp_mutex--;
383 return;
384 }
385 #endif
386
387 /* Recompute stamp? */
388 if (attr != stamp_attr)
389 rasops8_makestamp(ri, attr);
390
391 rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
392 height = ri->ri_font->fontheight;
393
394 if (uc == ' ') {
395 while (height--)
396 rp[0] = rp[1] = rp[2] = rp[3] = stamp[0];
397 } else {
398 uc -= ri->ri_font->firstchar;
399 fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
400 fs = ri->ri_font->stride;
401
402 while (height--) {
403 rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
404 rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
405 rp[2] = STAMP_READ(STAMP_SHIFT(fr[1], 1) & STAMP_MASK);
406 rp[3] = STAMP_READ(STAMP_SHIFT(fr[1], 0) & STAMP_MASK);
407
408 fr += fs;
409 DELTA(rp, ri->ri_stride, int32_t *);
410 }
411 }
412
413 /* Do underline */
414 if ((attr & 1) != 0) {
415 DELTA(rp, -(ri->ri_stride << 1), int32_t *);
416 rp[0] = rp[1] = rp[2] = rp[3] = stamp[15];
417 }
418
419 stamp_mutex--;
420 }
421 #endif /* !RASOPS_SMALL */
422