rasops8.c revision 1.4 1 /* $NetBSD: rasops8.c,v 1.4 1999/05/18 21:51:59 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.4 1999/05/18 21:51:59 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((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)(attr >> 16);
135 clr[1] = (u_char)(attr >> 24);
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(attr)
178 long attr;
179 {
180 int i;
181 int32_t fg, bg;
182
183 fg = (attr >> 24) & 15;
184 bg = (attr >> 16) & 15;
185 stamp_attr = attr;
186
187 for (i = 0; i < 16; i++) {
188 #if BYTE_ORDER == LITTLE_ENDIAN
189 stamp[i] = (i & 8 ? fg : bg);
190 stamp[i] |= ((i & 4 ? fg : bg) << 8);
191 stamp[i] |= ((i & 2 ? fg : bg) << 16);
192 stamp[i] |= ((i & 1 ? fg : bg) << 24);
193 #else
194 stamp[i] = (i & 1 ? fg : bg);
195 stamp[i] |= ((i & 2 ? fg : bg) << 8);
196 stamp[i] |= ((i & 4 ? fg : bg) << 16);
197 stamp[i] |= ((i & 8 ? fg : bg) << 24);
198 #endif
199 }
200 }
201
202
203 /*
204 * Put a single character. This is for 8-pixel wide fonts.
205 */
206 static void
207 rasops8_putchar8(cookie, row, col, uc, attr)
208 void *cookie;
209 int row, col;
210 u_int uc;
211 long attr;
212 {
213 struct rasops_info *ri;
214 int height, fs;
215 int32_t *rp;
216 u_char *fr;
217
218 /* Can't risk remaking the stamp if it's already in use */
219 if (stamp_mutex++) {
220 stamp_mutex--;
221 rasops8_putchar(cookie, row, col, uc, attr);
222 return;
223 }
224
225 ri = (struct rasops_info *)cookie;
226
227 #ifdef RASOPS_CLIPPING
228 if ((unsigned)row >= (unsigned)ri->ri_rows) {
229 stamp_mutex--;
230 return;
231 }
232
233 if ((unsigned)col >= (unsigned)ri->ri_cols) {
234 stamp_mutex--;
235 return;
236 }
237 #endif
238
239 /* Recompute stamp? */
240 if (attr != stamp_attr)
241 rasops8_makestamp(attr);
242
243 rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
244 height = ri->ri_font->fontheight;
245
246 if (uc == ' ') {
247 while (height--) {
248 rp[0] = stamp[0];
249 rp[1] = stamp[0];
250 DELTA(rp, ri->ri_stride, int32_t *);
251 }
252 } else {
253 uc -= ri->ri_font->firstchar;
254 fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
255 fs = ri->ri_font->stride;
256
257 while (height--) {
258 rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
259 rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
260
261 fr += fs;
262 DELTA(rp, ri->ri_stride, int32_t *);
263 }
264 }
265
266 /* Do underline */
267 if (attr & 1) {
268 DELTA(rp, -(ri->ri_stride << 1), int32_t *);
269 rp[0] = stamp[15];
270 rp[1] = stamp[15];
271 }
272
273 stamp_mutex--;
274 }
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(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 rp[0] = stamp[0];
323 rp[1] = stamp[0];
324 rp[2] = stamp[0];
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) {
344 DELTA(rp, -(ri->ri_stride << 1), int32_t *);
345 rp[0] = stamp[15];
346 rp[1] = stamp[15];
347 rp[2] = stamp[15];
348 }
349
350 stamp_mutex--;
351 }
352
353
354 /*
355 * Put a single character. This is for 16-pixel wide fonts.
356 */
357 static void
358 rasops8_putchar16(cookie, row, col, uc, attr)
359 void *cookie;
360 int row, col;
361 u_int uc;
362 long attr;
363 {
364 struct rasops_info *ri;
365 int height, fs;
366 int32_t *rp;
367 u_char *fr;
368
369 /* Can't risk remaking the stamp if it's already in use */
370 if (stamp_mutex++) {
371 stamp_mutex--;
372 rasops8_putchar(cookie, row, col, uc, attr);
373 return;
374 }
375
376 ri = (struct rasops_info *)cookie;
377
378 #ifdef RASOPS_CLIPPING
379 if ((unsigned)row >= (unsigned)ri->ri_rows) {
380 stamp_mutex--;
381 return;
382 }
383
384 if ((unsigned)col >= (unsigned)ri->ri_cols) {
385 stamp_mutex--;
386 return;
387 }
388 #endif
389
390 /* Recompute stamp? */
391 if (attr != stamp_attr)
392 rasops8_makestamp(attr);
393
394 rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
395 height = ri->ri_font->fontheight;
396
397 if (uc == ' ') {
398 while (height--) {
399 rp[0] = stamp[0];
400 rp[1] = stamp[0];
401 rp[2] = stamp[0];
402 rp[3] = stamp[0];
403 DELTA(rp, ri->ri_stride, int32_t *);
404 }
405 } else {
406 uc -= ri->ri_font->firstchar;
407 fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
408 fs = ri->ri_font->stride;
409
410 while (height--) {
411 rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
412 rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
413 rp[2] = STAMP_READ(STAMP_SHIFT(fr[1], 1) & STAMP_MASK);
414 rp[3] = STAMP_READ(STAMP_SHIFT(fr[1], 0) & STAMP_MASK);
415
416 fr += fs;
417 DELTA(rp, ri->ri_stride, int32_t *);
418 }
419 }
420
421 /* Do underline */
422 if (attr & 1) {
423 DELTA(rp, -(ri->ri_stride << 1), int32_t *);
424 rp[0] = stamp[15];
425 rp[1] = stamp[15];
426 rp[2] = stamp[15];
427 rp[3] = stamp[15];
428 }
429
430 stamp_mutex--;
431 }
432