rasops8.c revision 1.3 1 /* $NetBSD: rasops8.c,v 1.3 1999/04/26 04:27:47 ad Exp $ */
2
3 /*
4 * Copyright (c) 1999 Andy Doran <ad (at) NetBSD.org>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 *
28 */
29
30 #include "opt_rasops.h"
31 #include <sys/cdefs.h>
32 __KERNEL_RCSID(0, "$NetBSD: rasops8.c,v 1.3 1999/04/26 04:27:47 ad Exp $");
33
34 #include <sys/types.h>
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/time.h>
38
39 #include <dev/wscons/wsdisplayvar.h>
40 #include <dev/wscons/wsconsio.h>
41 #include <dev/rasops/rasops.h>
42
43 static void rasops8_putchar __P((void *, int, int, u_int, long attr));
44 static void rasops8_putchar8 __P((void *, int, int, u_int, long attr));
45 static void rasops8_putchar12 __P((void *, int, int, u_int, long attr));
46 static void rasops8_putchar16 __P((void *, int, int, u_int, long attr));
47 static void rasops8_makestamp __P((long));
48 void rasops8_init __P((struct rasops_info *ri));
49
50 /*
51 * 4x1 stamp for optimized character blitting
52 */
53 static int32_t stamp[16];
54 static long stamp_attr;
55 static int stamp_mutex; /* XXX see note in README */
56
57 /*
58 * XXX this confuses the hell out of gcc2 (not egcs) which always insists
59 * that the shift count is negative.
60 *
61 * offset = STAMP_SHIFT(fontbits, nibble #) & STAMP_MASK
62 * destination = STAMP_READ(offset)
63 */
64 #define STAMP_SHIFT(fb,n) ((n*4-2) >= 0 ? (fb)>>(n*4-2):(fb)<<-(n*4-2))
65 #define STAMP_MASK (15 << 2)
66 #define STAMP_READ(o) (*(int32_t *)((caddr_t)stamp + (o)))
67
68
69 /*
70 * Initalize a 'rasops_info' descriptor for this depth.
71 */
72 void
73 rasops8_init(ri)
74 struct rasops_info *ri;
75 {
76
77 switch (ri->ri_font->fontwidth) {
78 case 8:
79 ri->ri_ops.putchar = rasops8_putchar8;
80 break;
81
82 case 12:
83 ri->ri_ops.putchar = rasops8_putchar12;
84 break;
85
86 case 16:
87 ri->ri_ops.putchar = rasops8_putchar16;
88 break;
89
90 default:
91 ri->ri_ops.putchar = rasops8_putchar;
92 break;
93 }
94 }
95
96
97 /*
98 * Put a single character.
99 */
100 static void
101 rasops8_putchar(cookie, row, col, uc, attr)
102 void *cookie;
103 int row, col;
104 u_int uc;
105 long attr;
106 {
107 struct rasops_info *ri;
108 u_char *dp, *rp, *fr, clr[2];
109 int width, height, cnt, fs, fb;
110
111 ri = (struct rasops_info *)cookie;
112
113 #ifdef RASOPS_CLIPPING
114 /* Catches 'row < 0' case too */
115 if ((unsigned)row >= (unsigned)ri->ri_rows)
116 return;
117
118 if ((unsigned)col >= (unsigned)ri->ri_cols)
119 return;
120 #endif
121 rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
122
123 height = ri->ri_font->fontheight;
124 width = ri->ri_font->fontwidth;
125 clr[0] = (u_char)(attr >> 16);
126 clr[1] = (u_char)(attr >> 24);
127
128 if (uc == ' ') {
129 while (height--) {
130 dp = rp;
131 rp += ri->ri_stride;
132
133 for (cnt = width; cnt; cnt--)
134 *dp++ = clr[0];
135 }
136 } else {
137 uc -= ri->ri_font->firstchar;
138 fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
139 fs = ri->ri_font->stride;
140
141 while (height--) {
142 dp = rp;
143 fb = fr[3] | (fr[2] << 8) | (fr[1] << 16) | (fr[0] << 24);
144 fr += fs;
145 rp += ri->ri_stride;
146
147 for (cnt = width; cnt; cnt--) {
148 *dp++ = clr[(fb >> 31) & 1];
149 fb <<= 1;
150 }
151 }
152 }
153
154 /* Do underline */
155 if (attr & 1) {
156 rp -= (ri->ri_stride << 1);
157
158 while (width--)
159 *rp++ = clr[1];
160 }
161 }
162
163
164 /*
165 * Recompute the 4x1 blitting stamp.
166 */
167 static void
168 rasops8_makestamp(attr)
169 long attr;
170 {
171 int i;
172 int32_t fg, bg;
173
174 fg = (attr >> 24) & 15;
175 bg = (attr >> 16) & 15;
176 stamp_attr = attr;
177
178 for (i = 0; i < 16; i++) {
179 #if BYTE_ORDER == LITTLE_ENDIAN
180 stamp[i] = (i & 8 ? fg : bg);
181 stamp[i] |= ((i & 4 ? fg : bg) << 8);
182 stamp[i] |= ((i & 2 ? fg : bg) << 16);
183 stamp[i] |= ((i & 1 ? fg : bg) << 24);
184 #else
185 stamp[i] = (i & 1 ? fg : bg);
186 stamp[i] |= ((i & 2 ? fg : bg) << 8);
187 stamp[i] |= ((i & 4 ? fg : bg) << 16);
188 stamp[i] |= ((i & 8 ? fg : bg) << 24);
189 #endif
190 }
191 }
192
193
194 /*
195 * Put a single character. This is for 8-pixel wide fonts.
196 */
197 static void
198 rasops8_putchar8(cookie, row, col, uc, attr)
199 void *cookie;
200 int row, col;
201 u_int uc;
202 long attr;
203 {
204 struct rasops_info *ri;
205 int height, fs;
206 int32_t *rp;
207 u_char *fr;
208
209 /* Can't risk remaking the stamp if it's already in use */
210 if (stamp_mutex++) {
211 stamp_mutex--;
212 rasops8_putchar(cookie, row, col, uc, attr);
213 return;
214 }
215
216 ri = (struct rasops_info *)cookie;
217
218 #ifdef RASOPS_CLIPPING
219 if ((unsigned)row >= (unsigned)ri->ri_rows) {
220 stamp_mutex--;
221 return;
222 }
223
224 if ((unsigned)col >= (unsigned)ri->ri_cols) {
225 stamp_mutex--;
226 return;
227 }
228 #endif
229
230 /* Recompute stamp? */
231 if (attr != stamp_attr)
232 rasops8_makestamp(attr);
233
234 rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
235 height = ri->ri_font->fontheight;
236
237 if (uc == ' ') {
238 while (height--) {
239 rp[0] = stamp[0];
240 rp[1] = stamp[0];
241 DELTA(rp, ri->ri_stride, int32_t *);
242 }
243 } else {
244 uc -= ri->ri_font->firstchar;
245 fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
246 fs = ri->ri_font->stride;
247
248 while (height--) {
249 rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
250 rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
251
252 fr += fs;
253 DELTA(rp, ri->ri_stride, int32_t *);
254 }
255 }
256
257 /* Do underline */
258 if (attr & 1) {
259 DELTA(rp, -(ri->ri_stride << 1), int32_t *);
260 rp[0] = stamp[15];
261 rp[1] = stamp[15];
262 }
263
264 stamp_mutex--;
265 }
266
267
268 /*
269 * Put a single character. This is for 12-pixel wide fonts.
270 */
271 static void
272 rasops8_putchar12(cookie, row, col, uc, attr)
273 void *cookie;
274 int row, col;
275 u_int uc;
276 long attr;
277 {
278 struct rasops_info *ri;
279 int height, fs;
280 int32_t *rp;
281 u_char *fr;
282
283 /* Can't risk remaking the stamp if it's already in use */
284 if (stamp_mutex++) {
285 stamp_mutex--;
286 rasops8_putchar(cookie, row, col, uc, attr);
287 return;
288 }
289
290 ri = (struct rasops_info *)cookie;
291
292 #ifdef RASOPS_CLIPPING
293 if ((unsigned)row >= (unsigned)ri->ri_rows) {
294 stamp_mutex--;
295 return;
296 }
297
298 if ((unsigned)col >= (unsigned)ri->ri_cols) {
299 stamp_mutex--;
300 return;
301 }
302 #endif
303
304 /* Recompute stamp? */
305 if (attr != stamp_attr)
306 rasops8_makestamp(attr);
307
308 rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
309 height = ri->ri_font->fontheight;
310
311 if (uc == ' ') {
312 while (height--) {
313 rp[0] = stamp[0];
314 rp[1] = stamp[0];
315 rp[2] = stamp[0];
316 DELTA(rp, ri->ri_stride, int32_t *);
317 }
318 } else {
319 uc -= ri->ri_font->firstchar;
320 fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
321 fs = ri->ri_font->stride;
322
323 while (height--) {
324 rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
325 rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
326 rp[2] = STAMP_READ(STAMP_SHIFT(fr[1], 1) & STAMP_MASK);
327
328 fr += fs;
329 DELTA(rp, ri->ri_stride, int32_t *);
330 }
331 }
332
333 /* Do underline */
334 if (attr & 1) {
335 DELTA(rp, -(ri->ri_stride << 1), int32_t *);
336 rp[0] = stamp[15];
337 rp[1] = stamp[15];
338 rp[2] = stamp[15];
339 }
340
341 stamp_mutex--;
342 }
343
344
345 /*
346 * Put a single character. This is for 16-pixel wide fonts.
347 */
348 static void
349 rasops8_putchar16(cookie, row, col, uc, attr)
350 void *cookie;
351 int row, col;
352 u_int uc;
353 long attr;
354 {
355 struct rasops_info *ri;
356 int height, fs;
357 int32_t *rp;
358 u_char *fr;
359
360 /* Can't risk remaking the stamp if it's already in use */
361 if (stamp_mutex++) {
362 stamp_mutex--;
363 rasops8_putchar(cookie, row, col, uc, attr);
364 return;
365 }
366
367 ri = (struct rasops_info *)cookie;
368
369 #ifdef RASOPS_CLIPPING
370 if ((unsigned)row >= (unsigned)ri->ri_rows) {
371 stamp_mutex--;
372 return;
373 }
374
375 if ((unsigned)col >= (unsigned)ri->ri_cols) {
376 stamp_mutex--;
377 return;
378 }
379 #endif
380
381 /* Recompute stamp? */
382 if (attr != stamp_attr)
383 rasops8_makestamp(attr);
384
385 rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
386 height = ri->ri_font->fontheight;
387
388 if (uc == ' ') {
389 while (height--) {
390 rp[0] = stamp[0];
391 rp[1] = stamp[0];
392 rp[2] = stamp[0];
393 rp[3] = stamp[0];
394 DELTA(rp, ri->ri_stride, int32_t *);
395 }
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) {
414 DELTA(rp, -(ri->ri_stride << 1), int32_t *);
415 rp[0] = stamp[15];
416 rp[1] = stamp[15];
417 rp[2] = stamp[15];
418 rp[3] = stamp[15];
419 }
420
421 stamp_mutex--;
422 }
423