rasops15.c revision 1.3 1 /* $NetBSD: rasops15.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: rasops15.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 rasops15_putchar __P((void *, int, int, u_int, long attr));
44 static void rasops15_putchar8 __P((void *, int, int, u_int, long attr));
45 static void rasops15_putchar12 __P((void *, int, int, u_int, long attr));
46 static void rasops15_putchar16 __P((void *, int, int, u_int, long attr));
47 static void rasops15_makestamp __P((struct rasops_info *, long));
48
49 void rasops15_init __P((struct rasops_info *ri));
50
51 /*
52 * (2x2)x1 stamp for optimized character blitting
53 */
54 static int32_t stamp[32];
55 static long stamp_attr;
56 static int stamp_mutex; /* XXX see note in readme */
57
58 /*
59 * XXX this confuses the hell out of gcc2 (not egcs) which always insists
60 * that the shift count is negative.
61 *
62 * offset = STAMP_SHIFT(fontbits, nibble #) & STAMP_MASK
63 * destination int32_t[0] = STAMP_READ(offset)
64 * destination int32_t[1] = STAMP_READ(offset + 4)
65 */
66 #define STAMP_SHIFT(fb,n) ((n*4-3) >= 0 ? (fb)>>(n*4-3):(fb)<<-(n*4-3))
67 #define STAMP_MASK (15 << 3)
68 #define STAMP_READ(o) (*(int32_t *)((caddr_t)stamp + (o)))
69
70
71 /*
72 * Initalize rasops_info struct for this colordepth.
73 */
74 void
75 rasops15_init(ri)
76 struct rasops_info *ri;
77 {
78
79 switch (ri->ri_font->fontwidth) {
80 case 8:
81 ri->ri_ops.putchar = rasops15_putchar8;
82 break;
83
84 case 12:
85 ri->ri_ops.putchar = rasops15_putchar12;
86 break;
87
88 case 16:
89 ri->ri_ops.putchar = rasops15_putchar16;
90 break;
91
92 default:
93 ri->ri_ops.putchar = rasops15_putchar;
94 break;
95 }
96
97 if (ri->ri_rnum == 0) {
98 ri->ri_rnum = 5;
99 ri->ri_rpos = 0;
100 ri->ri_gnum = 5 + (ri->ri_depth == 16);
101 ri->ri_gpos = 5;
102 ri->ri_bnum = 5;
103 ri->ri_bpos = 10 + (ri->ri_depth == 16);
104 }
105 }
106
107
108 /*
109 * Paint a single character.
110 */
111 static void
112 rasops15_putchar(cookie, row, col, uc, attr)
113 void *cookie;
114 int row, col;
115 u_int uc;
116 long attr;
117 {
118 struct rasops_info *ri;
119 int fb, width, height, cnt, clr[2];
120 u_char *dp, *rp, *fr;
121
122 ri = (struct rasops_info *)cookie;
123
124 #ifdef RASOPS_CLIPPING
125 /* Catches 'row < 0' case too */
126 if ((unsigned)row >= (unsigned)ri->ri_rows)
127 return;
128
129 if ((unsigned)col >= (unsigned)ri->ri_cols)
130 return;
131 #endif
132
133 rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
134 height = ri->ri_font->fontheight;
135 width = ri->ri_font->fontwidth;
136
137 clr[1] = ri->ri_devcmap[((u_int)attr >> 24) & 15];
138 clr[0] = ri->ri_devcmap[((u_int)attr >> 16) & 15];
139
140 if (uc == ' ') {
141 while (height--) {
142 dp = rp;
143 rp += ri->ri_stride;
144
145 for (cnt = width; cnt; cnt--) {
146 *(int16_t *)dp = (int16_t)clr[0];
147 dp += 2;
148 }
149 }
150 } else {
151 uc -= ri->ri_font->firstchar;
152 fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
153
154 while (height--) {
155 dp = rp;
156 fb = fr[3] | (fr[2] << 8) | (fr[1] << 16) | (fr[0] << 24);
157 fr += ri->ri_font->stride;
158 rp += ri->ri_stride;
159
160 for (cnt = width; cnt; cnt--) {
161 *(int16_t *)dp = (int16_t)clr[(fb >> 31) & 1];
162 fb <<= 1;
163 dp += 2;
164 }
165 }
166 }
167
168 /* Do underline */
169 if (attr & 1) {
170 rp -= ri->ri_stride << 1;
171
172 while (width--) {
173 *(int16_t *)rp = clr[1];
174 rp += 2;
175 }
176 }
177 }
178
179
180 /*
181 * Recompute the (2x2)x1 blitting stamp.
182 */
183 static void
184 rasops15_makestamp(ri, attr)
185 struct rasops_info *ri;
186 long attr;
187 {
188 int32_t fg, bg;
189 int i;
190
191 fg = ri->ri_devcmap[((u_int)attr >> 24) & 15] & 0xffff;
192 bg = ri->ri_devcmap[((u_int)attr >> 16) & 15] & 0xffff;
193 stamp_attr = attr;
194
195 for (i = 0; i < 32; i += 2) {
196 #if BYTE_ORDER == LITTLE_ENDIAN
197 stamp[i] = (i & 16 ? fg : bg);
198 stamp[i] |= ((i & 8 ? fg : bg) << 16);
199 stamp[i + 1] = (i & 4 ? fg : bg);
200 stamp[i + 1] |= ((i & 2 ? fg : bg) << 16);
201 #else
202 stamp[i] = (i & 2 ? fg : bg);
203 stamp[i] |= ((i & 4 ? fg : bg) << 16);
204 stamp[i + 1] = (i & 8 ? fg : bg);
205 stamp[i + 1] |= ((i & 16 ? fg : bg) << 16);
206 #endif
207 }
208 }
209
210
211 /*
212 * Paint a single character. This is for 8-pixel wide fonts.
213 */
214 static void
215 rasops15_putchar8(cookie, row, col, uc, attr)
216 void *cookie;
217 int row, col;
218 u_int uc;
219 long attr;
220 {
221 struct rasops_info *ri;
222 int height, so, fs;
223 int32_t *rp;
224 u_char *fr;
225
226 /* Can't risk remaking the stamp if it's already in use */
227 if (stamp_mutex++) {
228 stamp_mutex--;
229 rasops15_putchar(cookie, row, col, uc, attr);
230 return;
231 }
232
233 ri = (struct rasops_info *)cookie;
234
235 #ifdef RASOPS_CLIPPING
236 if ((unsigned)row >= (unsigned)ri->ri_rows) {
237 stamp_mutex--;
238 return;
239 }
240
241 if ((unsigned)col >= (unsigned)ri->ri_cols) {
242 stamp_mutex--;
243 return;
244 }
245 #endif
246
247 /* Recompute stamp? */
248 if (attr != stamp_attr)
249 rasops15_makestamp(ri, attr);
250
251 rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
252 height = ri->ri_font->fontheight;
253
254 if (uc == (u_int)-1) {
255 while (height--) {
256 rp[0] = stamp[0];
257 rp[1] = stamp[0];
258 rp[2] = stamp[0];
259 rp[3] = stamp[0];
260 DELTA(rp, ri->ri_stride, int32_t *);
261 }
262 } else {
263 uc -= ri->ri_font->firstchar;
264 fr = (u_char *)ri->ri_font->data + uc*ri->ri_fontscale;
265 fs = ri->ri_font->stride;
266
267 while (height--) {
268 so = STAMP_SHIFT(fr[0], 1) & STAMP_MASK;
269 rp[0] = STAMP_READ(so);
270 rp[1] = STAMP_READ(so + 4);
271
272 so = STAMP_SHIFT(fr[0], 0) & STAMP_MASK;
273 rp[2] = STAMP_READ(so);
274 rp[3] = STAMP_READ(so + 4);
275
276 fr += fs;
277 DELTA(rp, ri->ri_stride, int32_t *);
278 }
279 }
280
281 /* Do underline */
282 if (attr & 1) {
283 DELTA(rp, -(ri->ri_stride << 1), int32_t *);
284 rp[0] = STAMP_READ(30);
285 rp[1] = STAMP_READ(30);
286 rp[2] = STAMP_READ(30);
287 rp[3] = STAMP_READ(30);
288 }
289
290 stamp_mutex--;
291 }
292
293
294 /*
295 * Paint a single character. This is for 12-pixel wide fonts.
296 */
297 static void
298 rasops15_putchar12(cookie, row, col, uc, attr)
299 void *cookie;
300 int row, col;
301 u_int uc;
302 long attr;
303 {
304 struct rasops_info *ri;
305 int height, so, fs;
306 int32_t *rp;
307 u_char *fr;
308
309 /* Can't risk remaking the stamp if it's already in use */
310 if (stamp_mutex++) {
311 stamp_mutex--;
312 rasops15_putchar(cookie, row, col, uc, attr);
313 return;
314 }
315
316 ri = (struct rasops_info *)cookie;
317
318 #ifdef RASOPS_CLIPPING
319 if ((unsigned)row >= (unsigned)ri->ri_rows) {
320 stamp_mutex--;
321 return;
322 }
323
324 if ((unsigned)col >= (unsigned)ri->ri_cols) {
325 stamp_mutex--;
326 return;
327 }
328 #endif
329
330 /* Recompute stamp? */
331 if (attr != stamp_attr)
332 rasops15_makestamp(ri, attr);
333
334 rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
335 height = ri->ri_font->fontheight;
336
337 if (uc == (u_int)-1) {
338 while (height--) {
339 rp[0] = stamp[0];
340 rp[1] = stamp[0];
341 rp[2] = stamp[0];
342 rp[3] = stamp[0];
343 rp[4] = stamp[0];
344 rp[5] = stamp[0];
345 DELTA(rp, ri->ri_stride, int32_t *);
346 }
347 } else {
348 uc -= ri->ri_font->firstchar;
349 fr = (u_char *)ri->ri_font->data + uc*ri->ri_fontscale;
350 fs = ri->ri_font->stride;
351
352 while (height--) {
353 so = STAMP_SHIFT(fr[0], 1) & STAMP_MASK;
354 rp[0] = STAMP_READ(so);
355 rp[1] = STAMP_READ(so + 4);
356
357 so = STAMP_SHIFT(fr[0], 0) & STAMP_MASK;
358 rp[2] = STAMP_READ(so);
359 rp[3] = STAMP_READ(so + 4);
360
361 so = STAMP_SHIFT(fr[1], 1) & STAMP_MASK;
362 rp[4] = STAMP_READ(so);
363 rp[5] = STAMP_READ(so + 4);
364
365 fr += fs;
366 DELTA(rp, ri->ri_stride, int32_t *);
367 }
368 }
369
370 /* Do underline */
371 if (attr & 1) {
372 DELTA(rp, -(ri->ri_stride << 1), int32_t *);
373 rp[0] = STAMP_READ(30);
374 rp[1] = STAMP_READ(30);
375 rp[2] = STAMP_READ(30);
376 rp[3] = STAMP_READ(30);
377 rp[4] = STAMP_READ(30);
378 rp[5] = STAMP_READ(30);
379 }
380
381 stamp_mutex--;
382 }
383
384
385 /*
386 * Paint a single character. This is for 16-pixel wide fonts.
387 */
388 static void
389 rasops15_putchar16(cookie, row, col, uc, attr)
390 void *cookie;
391 int row, col;
392 u_int uc;
393 long attr;
394 {
395 struct rasops_info *ri;
396 int height, so, fs;
397 int32_t *rp;
398 u_char *fr;
399
400 /* Can't risk remaking the stamp if it's already in use */
401 if (stamp_mutex++) {
402 stamp_mutex--;
403 rasops15_putchar(cookie, row, col, uc, attr);
404 return;
405 }
406
407 ri = (struct rasops_info *)cookie;
408
409 #ifdef RASOPS_CLIPPING
410 if ((unsigned)row >= (unsigned)ri->ri_rows) {
411 stamp_mutex--;
412 return;
413 }
414
415 if ((unsigned)col >= (unsigned)ri->ri_cols) {
416 stamp_mutex--;
417 return;
418 }
419 #endif
420
421 /* Recompute stamp? */
422 if (attr != stamp_attr)
423 rasops15_makestamp(ri, attr);
424
425 rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
426 height = ri->ri_font->fontheight;
427
428 if (uc == (u_int)-1) {
429 while (height--) {
430 rp[0] = stamp[0];
431 rp[1] = stamp[0];
432 rp[2] = stamp[0];
433 rp[3] = stamp[0];
434 rp[4] = stamp[0];
435 rp[5] = stamp[0];
436 rp[6] = stamp[0];
437 rp[7] = stamp[0];
438 DELTA(rp, ri->ri_stride, int32_t *);
439 }
440 } else {
441 uc -= ri->ri_font->firstchar;
442 fr = (u_char *)ri->ri_font->data + uc*ri->ri_fontscale;
443 fs = ri->ri_font->stride;
444
445 while (height--) {
446 so = STAMP_SHIFT(fr[0], 1) & STAMP_MASK;
447 rp[0] = STAMP_READ(so);
448 rp[1] = STAMP_READ(so + 4);
449
450 so = STAMP_SHIFT(fr[0], 0) & STAMP_MASK;
451 rp[2] = STAMP_READ(so);
452 rp[3] = STAMP_READ(so + 4);
453
454 so = STAMP_SHIFT(fr[1], 1) & STAMP_MASK;
455 rp[4] = STAMP_READ(so);
456 rp[5] = STAMP_READ(so + 4);
457
458 so = STAMP_SHIFT(fr[1], 0) & STAMP_MASK;
459 rp[6] = STAMP_READ(so);
460 rp[7] = STAMP_READ(so + 4);
461
462 DELTA(rp, ri->ri_stride, int32_t *);
463 fr += fs;
464 }
465 }
466
467 /* Do underline */
468 if (attr & 1) {
469 DELTA(rp, -(ri->ri_stride << 1), int32_t *);
470 rp[0] = STAMP_READ(30);
471 rp[1] = STAMP_READ(30);
472 rp[2] = STAMP_READ(30);
473 rp[3] = STAMP_READ(30);
474 rp[4] = STAMP_READ(30);
475 rp[5] = STAMP_READ(30);
476 rp[6] = STAMP_READ(30);
477 rp[7] = STAMP_READ(30);
478 }
479
480 stamp_mutex--;
481 }
482