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