rasops8.c revision 1.7 1 /* $NetBSD: rasops8.c,v 1.7 1999/10/23 23:14:14 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 Andy 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.7 1999/10/23 23:14:14 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 (15 << 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) & 15];
133 clr[1] = (u_char)ri->ri_devcmap[(attr >> 24) & 15];
134
135 if (uc == ' ') {
136 while (height--) {
137 dp = rp;
138 rp += ri->ri_stride;
139
140 for (cnt = width; cnt; cnt--)
141 *dp++ = clr[0];
142 }
143 } else {
144 uc -= ri->ri_font->firstchar;
145 fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
146 fs = ri->ri_font->stride;
147
148 while (height--) {
149 dp = rp;
150 fb = fr[3] | (fr[2] << 8) | (fr[1] << 16) | (fr[0] << 24);
151 fr += fs;
152 rp += ri->ri_stride;
153
154 for (cnt = width; cnt; cnt--) {
155 *dp++ = clr[(fb >> 31) & 1];
156 fb <<= 1;
157 }
158 }
159 }
160
161 /* Do underline */
162 if ((attr & 1) != 0) {
163 rp -= (ri->ri_stride << 1);
164
165 while (width--)
166 *rp++ = clr[1];
167 }
168 }
169
170 #ifndef RASOPS_SMALL
171 /*
172 * Recompute the 4x1 blitting stamp.
173 */
174 static void
175 rasops8_makestamp(ri, attr)
176 struct rasops_info *ri;
177 long attr;
178 {
179 int32_t fg, bg;
180 int i;
181
182 fg = ri->ri_devcmap[(attr >> 24) & 15] & 0xff;
183 bg = ri->ri_devcmap[(attr >> 16) & 15] & 0xff;
184 stamp_attr = attr;
185
186 for (i = 0; i < 16; i++) {
187 #if BYTE_ORDER == LITTLE_ENDIAN
188 stamp[i] = (i & 8 ? fg : bg);
189 stamp[i] |= ((i & 4 ? fg : bg) << 8);
190 stamp[i] |= ((i & 2 ? fg : bg) << 16);
191 stamp[i] |= ((i & 1 ? fg : bg) << 24);
192 #else
193 stamp[i] = (i & 1 ? fg : bg);
194 stamp[i] |= ((i & 2 ? fg : bg) << 8);
195 stamp[i] |= ((i & 4 ? fg : bg) << 16);
196 stamp[i] |= ((i & 8 ? fg : bg) << 24);
197 #endif
198 }
199 }
200
201 /*
202 * Put a single character. This is for 8-pixel wide fonts.
203 */
204 static void
205 rasops8_putchar8(cookie, row, col, uc, attr)
206 void *cookie;
207 int row, col;
208 u_int uc;
209 long attr;
210 {
211 struct rasops_info *ri;
212 int height, fs;
213 int32_t *rp;
214 u_char *fr;
215
216 /* Can't risk remaking the stamp if it's already in use */
217 if (stamp_mutex++) {
218 stamp_mutex--;
219 rasops8_putchar(cookie, row, col, uc, attr);
220 return;
221 }
222
223 ri = (struct rasops_info *)cookie;
224
225 #ifdef RASOPS_CLIPPING
226 if ((unsigned)row >= (unsigned)ri->ri_rows) {
227 stamp_mutex--;
228 return;
229 }
230
231 if ((unsigned)col >= (unsigned)ri->ri_cols) {
232 stamp_mutex--;
233 return;
234 }
235 #endif
236
237 /* Recompute stamp? */
238 if (attr != stamp_attr)
239 rasops8_makestamp(ri, attr);
240
241 rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
242 height = ri->ri_font->fontheight;
243
244 if (uc == ' ') {
245 while (height--) {
246 rp[0] = stamp[0];
247 rp[1] = stamp[0];
248 DELTA(rp, ri->ri_stride, int32_t *);
249 }
250 } else {
251 uc -= ri->ri_font->firstchar;
252 fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
253 fs = ri->ri_font->stride;
254
255 while (height--) {
256 rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
257 rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
258
259 fr += fs;
260 DELTA(rp, ri->ri_stride, int32_t *);
261 }
262 }
263
264 /* Do underline */
265 if ((attr & 1) != 0) {
266 DELTA(rp, -(ri->ri_stride << 1), int32_t *);
267 rp[0] = stamp[15];
268 rp[1] = stamp[15];
269 }
270
271 stamp_mutex--;
272 }
273
274 /*
275 * Put a single character. This is for 12-pixel wide fonts.
276 */
277 static void
278 rasops8_putchar12(cookie, row, col, uc, attr)
279 void *cookie;
280 int row, col;
281 u_int uc;
282 long attr;
283 {
284 struct rasops_info *ri;
285 int height, fs;
286 int32_t *rp;
287 u_char *fr;
288
289 /* Can't risk remaking the stamp if it's already in use */
290 if (stamp_mutex++) {
291 stamp_mutex--;
292 rasops8_putchar(cookie, row, col, uc, attr);
293 return;
294 }
295
296 ri = (struct rasops_info *)cookie;
297
298 #ifdef RASOPS_CLIPPING
299 if ((unsigned)row >= (unsigned)ri->ri_rows) {
300 stamp_mutex--;
301 return;
302 }
303
304 if ((unsigned)col >= (unsigned)ri->ri_cols) {
305 stamp_mutex--;
306 return;
307 }
308 #endif
309
310 /* Recompute stamp? */
311 if (attr != stamp_attr)
312 rasops8_makestamp(ri, attr);
313
314 rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
315 height = ri->ri_font->fontheight;
316
317 if (uc == ' ') {
318 while (height--) {
319 rp[0] = stamp[0];
320 rp[1] = stamp[0];
321 rp[2] = stamp[0];
322 DELTA(rp, ri->ri_stride, int32_t *);
323 }
324 } else {
325 uc -= ri->ri_font->firstchar;
326 fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
327 fs = ri->ri_font->stride;
328
329 while (height--) {
330 rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
331 rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
332 rp[2] = STAMP_READ(STAMP_SHIFT(fr[1], 1) & STAMP_MASK);
333
334 fr += fs;
335 DELTA(rp, ri->ri_stride, int32_t *);
336 }
337 }
338
339 /* Do underline */
340 if ((attr & 1) != 0) {
341 DELTA(rp, -(ri->ri_stride << 1), int32_t *);
342 rp[0] = stamp[15];
343 rp[1] = stamp[15];
344 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] = stamp[0];
396 rp[1] = stamp[0];
397 rp[2] = stamp[0];
398 rp[3] = stamp[0];
399 DELTA(rp, ri->ri_stride, int32_t *);
400 }
401 } else {
402 uc -= ri->ri_font->firstchar;
403 fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
404 fs = ri->ri_font->stride;
405
406 while (height--) {
407 rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
408 rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
409 rp[2] = STAMP_READ(STAMP_SHIFT(fr[1], 1) & STAMP_MASK);
410 rp[3] = STAMP_READ(STAMP_SHIFT(fr[1], 0) & STAMP_MASK);
411
412 fr += fs;
413 DELTA(rp, ri->ri_stride, int32_t *);
414 }
415 }
416
417 /* Do underline */
418 if ((attr & 1) != 0) {
419 DELTA(rp, -(ri->ri_stride << 1), int32_t *);
420 rp[0] = stamp[15];
421 rp[1] = stamp[15];
422 rp[2] = stamp[15];
423 rp[3] = stamp[15];
424 }
425
426 stamp_mutex--;
427 }
428
429 #endif /* !RASOPS_SMALL */
430