1 /* $OpenBSD: rasops8.c,v 1.7 2006/12/02 15:55:18 miod Exp $ */
2 /* $NetBSD: rasops8.c,v 1.8 2000/04/12 14:22:29 pk Exp $ */
3
4 /*-
5 * Copyright (c) 1999 The NetBSD Foundation, Inc.
6 * All rights reserved.
7 *
8 * This code is derived from software contributed to The NetBSD Foundation
9 * by Andrew Doran.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed by the NetBSD
22 * Foundation, Inc. and its contributors.
23 * 4. Neither the name of The NetBSD Foundation nor the names of its
24 * contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 * POSSIBILITY OF SUCH DAMAGE.
38 */
39
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/time.h>
43
44 #include <dev/wscons/wsdisplayvar.h>
45 #include <dev/wscons/wsconsio.h>
46 #include <dev/rasops/rasops.h>
47
48 void rasops8_putchar(void *, int, int, u_int, long attr);
49 #ifndef RASOPS_SMALL
50 void rasops8_putchar8(void *, int, int, u_int, long attr);
51 void rasops8_putchar12(void *, int, int, u_int, long attr);
52 void rasops8_putchar16(void *, int, int, u_int, long attr);
53 void rasops8_makestamp(struct rasops_info *ri, long);
54
55 /*
56 * 4x1 stamp for optimized character blitting
57 */
58 static int32_t stamp[16];
59 static long stamp_attr;
60 static int stamp_mutex; /* XXX see note in README */
61 #endif
62
63 /*
64 * XXX this confuses the hell out of gcc2 (not egcs) which always insists
65 * that the shift count is negative.
66 *
67 * offset = STAMP_SHIFT(fontbits, nibble #) & STAMP_MASK
68 * destination = STAMP_READ(offset)
69 */
70 #define STAMP_SHIFT(fb,n) ((n*4-2) >= 0 ? (fb)>>(n*4-2):(fb)<<-(n*4-2))
71 #define STAMP_MASK (0xf << 2)
72 #define STAMP_READ(o) (*(int32_t *)((caddr_t)stamp + (o)))
73
74 /*
75 * Initialize a 'rasops_info' descriptor for this depth.
76 */
77 void
rasops8_init(ri)78 rasops8_init(ri)
79 struct rasops_info *ri;
80 {
81
82 switch (ri->ri_font->fontwidth) {
83 #ifndef RASOPS_SMALL
84 case 8:
85 ri->ri_ops.putchar = rasops8_putchar8;
86 break;
87 case 12:
88 ri->ri_ops.putchar = rasops8_putchar12;
89 break;
90 case 16:
91 ri->ri_ops.putchar = rasops8_putchar16;
92 break;
93 #endif /* !RASOPS_SMALL */
94 default:
95 ri->ri_ops.putchar = rasops8_putchar;
96 break;
97 }
98 }
99
100 /*
101 * Put a single character.
102 */
103 void
rasops8_putchar(cookie,row,col,uc,attr)104 rasops8_putchar(cookie, row, col, uc, attr)
105 void *cookie;
106 int row, col;
107 u_int uc;
108 long attr;
109 {
110 int width, height, cnt, fs, fb;
111 u_char *dp, *rp, *fr, clr[2];
112 struct rasops_info *ri;
113
114 ri = (struct rasops_info *)cookie;
115
116 #ifdef RASOPS_CLIPPING
117 /* Catches 'row < 0' case too */
118 if ((unsigned)row >= (unsigned)ri->ri_rows)
119 return;
120
121 if ((unsigned)col >= (unsigned)ri->ri_cols)
122 return;
123 #endif
124 rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
125
126 height = ri->ri_font->fontheight;
127 width = ri->ri_font->fontwidth;
128 clr[0] = (u_char)ri->ri_devcmap[(attr >> 16) & 0xf];
129 clr[1] = (u_char)ri->ri_devcmap[(attr >> 24) & 0xf];
130
131 if (uc == ' ') {
132 u_char c = clr[0];
133
134 while (height--) {
135 dp = rp;
136 rp += ri->ri_stride;
137
138 for (cnt = width; cnt; cnt--)
139 *dp++ = c;
140 }
141 } else {
142 uc -= ri->ri_font->firstchar;
143 fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
144 fs = ri->ri_font->stride;
145
146 while (height--) {
147 dp = rp;
148 fb = fr[3] | (fr[2] << 8) | (fr[1] << 16) | (fr[0] << 24);
149 fr += fs;
150 rp += ri->ri_stride;
151
152 for (cnt = width; cnt; cnt--) {
153 *dp++ = clr[(fb >> 31) & 1];
154 fb <<= 1;
155 }
156 }
157 }
158
159 /* Do underline */
160 if ((attr & 1) != 0) {
161 u_char c = clr[1];
162
163 rp -= (ri->ri_stride << 1);
164
165 while (width--)
166 *rp++ = c;
167 }
168 }
169
170 #ifndef RASOPS_SMALL
171 /*
172 * Recompute the 4x1 blitting stamp.
173 */
174 void
rasops8_makestamp(ri,attr)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) & 0xf] & 0xff;
183 bg = ri->ri_devcmap[(attr >> 16) & 0xf] & 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 #if NRASOPS_BSWAP > 0
199 if (ri->ri_flg & RI_BSWAP)
200 stamp[i] = swap32(stamp[i]);
201 #endif
202 }
203 }
204
205 /*
206 * Put a single character. This is for 8-pixel wide fonts.
207 */
208 void
rasops8_putchar8(cookie,row,col,uc,attr)209 rasops8_putchar8(cookie, row, col, uc, attr)
210 void *cookie;
211 int row, col;
212 u_int uc;
213 long attr;
214 {
215 struct rasops_info *ri;
216 int height, fs;
217 int32_t *rp;
218 u_char *fr;
219
220 /* Can't risk remaking the stamp if it's already in use */
221 if (stamp_mutex++) {
222 stamp_mutex--;
223 rasops8_putchar(cookie, row, col, uc, attr);
224 return;
225 }
226
227 ri = (struct rasops_info *)cookie;
228
229 #ifdef RASOPS_CLIPPING
230 if ((unsigned)row >= (unsigned)ri->ri_rows) {
231 stamp_mutex--;
232 return;
233 }
234
235 if ((unsigned)col >= (unsigned)ri->ri_cols) {
236 stamp_mutex--;
237 return;
238 }
239 #endif
240
241 /* Recompute stamp? */
242 if (attr != stamp_attr)
243 rasops8_makestamp(ri, attr);
244
245 rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
246 height = ri->ri_font->fontheight;
247
248 if (uc == ' ') {
249 while (height--) {
250 rp[0] = 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) != 0) {
269 DELTA(rp, -(ri->ri_stride << 1), int32_t *);
270 rp[0] = rp[1] = stamp[15];
271 }
272
273 stamp_mutex--;
274 }
275
276 /*
277 * Put a single character. This is for 12-pixel wide fonts.
278 */
279 void
rasops8_putchar12(cookie,row,col,uc,attr)280 rasops8_putchar12(cookie, row, col, uc, attr)
281 void *cookie;
282 int row, col;
283 u_int uc;
284 long attr;
285 {
286 struct rasops_info *ri;
287 int height, fs;
288 int32_t *rp;
289 u_char *fr;
290
291 /* Can't risk remaking the stamp if it's already in use */
292 if (stamp_mutex++) {
293 stamp_mutex--;
294 rasops8_putchar(cookie, row, col, uc, attr);
295 return;
296 }
297
298 ri = (struct rasops_info *)cookie;
299
300 #ifdef RASOPS_CLIPPING
301 if ((unsigned)row >= (unsigned)ri->ri_rows) {
302 stamp_mutex--;
303 return;
304 }
305
306 if ((unsigned)col >= (unsigned)ri->ri_cols) {
307 stamp_mutex--;
308 return;
309 }
310 #endif
311
312 /* Recompute stamp? */
313 if (attr != stamp_attr)
314 rasops8_makestamp(ri, attr);
315
316 rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
317 height = ri->ri_font->fontheight;
318
319 if (uc == ' ') {
320 while (height--) {
321 int32_t c = stamp[0];
322
323 rp[0] = rp[1] = rp[2] = c;
324 DELTA(rp, ri->ri_stride, int32_t *);
325 }
326 } else {
327 uc -= ri->ri_font->firstchar;
328 fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
329 fs = ri->ri_font->stride;
330
331 while (height--) {
332 rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
333 rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
334 rp[2] = STAMP_READ(STAMP_SHIFT(fr[1], 1) & STAMP_MASK);
335
336 fr += fs;
337 DELTA(rp, ri->ri_stride, int32_t *);
338 }
339 }
340
341 /* Do underline */
342 if ((attr & 1) != 0) {
343 DELTA(rp, -(ri->ri_stride << 1), int32_t *);
344 rp[0] = rp[1] = 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 void
rasops8_putchar16(cookie,row,col,uc,attr)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] = rp[1] = rp[2] = rp[3] = stamp[0];
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) != 0) {
414 DELTA(rp, -(ri->ri_stride << 1), int32_t *);
415 rp[0] = rp[1] = rp[2] = rp[3] = stamp[15];
416 }
417
418 stamp_mutex--;
419 }
420 #endif /* !RASOPS_SMALL */
421