rasops8.c revision 1.2 1 /* $NetBSD: rasops8.c,v 1.2 1999/04/13 00:40:09 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 #ifdef RASOPS8
32
33 #include <sys/cdefs.h>
34 __KERNEL_RCSID(0, "$NetBSD: rasops8.c,v 1.2 1999/04/13 00:40:09 ad Exp $");
35
36 #include <sys/types.h>
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/time.h>
40
41 #include <dev/wscons/wsdisplayvar.h>
42 #include <dev/wscons/wsconsio.h>
43 #include <dev/rasops/rasops.h>
44
45 static void rasops8_putchar __P((void *, int, int, u_int, long attr));
46 static void rasops8_putchar8 __P((void *, int, int, u_int, long attr));
47 static void rasops8_putchar12 __P((void *, int, int, u_int, long attr));
48 static void rasops8_putchar16 __P((void *, int, int, u_int, long attr));
49 static void rasops8_erasecols __P((void *, int, int, int, long));
50 static void rasops8_eraserows __P((void *, int, int, long));
51 static void rasops8_makestamp __P((long));
52 static int32_t rasops8_bg_color __P((long));
53 static void rasops8_do_cursor __P((struct rasops_info *));
54 void rasops8_init __P((struct rasops_info *ri));
55
56 /*
57 * 4x1 stamp for optimized character blitting
58 */
59 static int32_t stamp[16];
60 static long stamp_attr;
61 static int stamp_mutex; /* XXX see note in README */
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 (15 << 2)
72 #define STAMP_READ(o) (*(int32_t *)((caddr_t)stamp + (o)))
73
74
75 /*
76 * Initalize a 'rasops_info' descriptor for this depth.
77 */
78 void
79 rasops8_init(ri)
80 struct rasops_info *ri;
81 {
82
83 switch (ri->ri_font->fontwidth) {
84 case 8:
85 ri->ri_ops.putchar = rasops8_putchar8;
86 break;
87
88 case 12:
89 ri->ri_ops.putchar = rasops8_putchar12;
90 break;
91
92 case 16:
93 ri->ri_ops.putchar = rasops8_putchar16;
94 break;
95
96 default:
97 ri->ri_ops.putchar = rasops8_putchar;
98 break;
99 }
100
101 ri->ri_ops.erasecols = rasops8_erasecols;
102 ri->ri_ops.eraserows = rasops8_eraserows;
103 ri->ri_do_cursor = rasops8_do_cursor;
104 }
105
106
107 /*
108 * Get background color from attribute and copy across all 4 bytes
109 * of an int32_t.
110 */
111 static __inline__ int32_t
112 rasops8_bg_color(attr)
113 long attr;
114 {
115 int32_t bg;
116
117 bg = ((int32_t)attr >> 16) & 15;
118 return bg | (bg << 8) | (bg << 16) | (bg << 24);
119 }
120
121
122 /*
123 * Actually turn the cursor on or off. This does the dirty work for
124 * rasops_cursor().
125 */
126 static void
127 rasops8_do_cursor(ri)
128 struct rasops_info *ri;
129 {
130 u_char *dp, *rp;
131 int full1, height, cnt, slop1, slop2, row, col;
132
133 row = ri->ri_crow;
134 col = ri->ri_ccol;
135
136 rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
137 height = ri->ri_font->fontheight;
138
139 slop1 = (int)rp & 3;
140 slop2 = (ri->ri_xscale - slop1) & 3;
141 full1 = (ri->ri_xscale - slop1 - slop2) >> 2;
142
143 while (height--) {
144 dp = rp;
145 rp += ri->ri_stride;
146
147 for (cnt = slop1; cnt; cnt--)
148 *dp++ ^= 0xff;
149
150 for (cnt = full1; cnt; cnt--) {
151 *(int32_t *)dp ^= 0xffffffff;
152 dp += 4;
153 }
154
155 for (cnt = slop2; cnt; cnt--)
156 *dp++ ^= 0xff;
157 }
158 }
159
160
161 /*
162 * Paint a single character.
163 */
164 static void
165 rasops8_putchar(cookie, row, col, uc, attr)
166 void *cookie;
167 int row, col;
168 u_int uc;
169 long attr;
170 {
171 struct rasops_info *ri;
172 u_char *dp, *rp, *fr, clr[2];
173 int width, height, cnt, fs, fb;
174
175 ri = (struct rasops_info *)cookie;
176
177 #ifdef RASOPS_CLIPPING
178 /* Catches 'row < 0' case too */
179 if ((unsigned)row >= (unsigned)ri->ri_rows)
180 return;
181
182 if ((unsigned)col >= (unsigned)ri->ri_cols)
183 return;
184 #endif
185 rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
186
187 height = ri->ri_font->fontheight;
188 width = ri->ri_font->fontwidth;
189 clr[0] = (u_char)(attr >> 16);
190 clr[1] = (u_char)(attr >> 24);
191
192 if (uc == ' ') {
193 while (height--) {
194 dp = rp;
195 rp += ri->ri_stride;
196
197 for (cnt = width; cnt; cnt--)
198 *dp++ = clr[0];
199 }
200 } else {
201 uc -= ri->ri_font->firstchar;
202 fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
203 fs = ri->ri_font->stride;
204
205 while (height--) {
206 dp = rp;
207 fb = fr[3] | (fr[2] << 8) | (fr[1] << 16) | (fr[0] << 24);
208 fr += fs;
209 rp += ri->ri_stride;
210
211 for (cnt = width; cnt; cnt--) {
212 *dp++ = clr[(fb >> 31) & 1];
213 fb <<= 1;
214 }
215 }
216 }
217
218 /* Do underline */
219 if (attr & 1) {
220 rp -= (ri->ri_stride << 1);
221
222 while (width--)
223 *rp++ = clr[1];
224 }
225
226 }
227
228
229 /*
230 * Recompute the 4x1 blitting stamp.
231 */
232 static void
233 rasops8_makestamp(long attr)
234 {
235 int i;
236 int32_t fg, bg;
237
238 fg = (attr >> 24) & 15;
239 bg = (attr >> 16) & 15;
240 stamp_attr = attr;
241
242 for (i = 0; i < 16; i++) {
243 #if BYTE_ORDER == LITTLE_ENDIAN
244 stamp[i] = (i & 8 ? fg : bg);
245 stamp[i] |= ((i & 4 ? fg : bg) << 8);
246 stamp[i] |= ((i & 2 ? fg : bg) << 16);
247 stamp[i] |= ((i & 1 ? fg : bg) << 24);
248 #else
249 stamp[i] = (i & 1 ? fg : bg);
250 stamp[i] |= ((i & 2 ? fg : bg) << 8);
251 stamp[i] |= ((i & 4 ? fg : bg) << 16);
252 stamp[i] |= ((i & 8 ? fg : bg) << 24);
253 #endif
254 }
255 }
256
257
258 /*
259 * Paint a single character. This is for 8-pixel wide fonts.
260 */
261 static void
262 rasops8_putchar8(cookie, row, col, uc, attr)
263 void *cookie;
264 int row, col;
265 u_int uc;
266 long attr;
267 {
268 struct rasops_info *ri;
269 int height, fs;
270 int32_t *rp;
271 u_char *fr;
272
273 /* Can't risk remaking the stamp if it's already in use */
274 if (stamp_mutex++) {
275 stamp_mutex--;
276 rasops8_putchar(cookie, row, col, uc, attr);
277 return;
278 }
279
280 ri = (struct rasops_info *)cookie;
281
282 #ifdef RASOPS_CLIPPING
283 if ((unsigned)row >= (unsigned)ri->ri_rows) {
284 stamp_mutex--;
285 return;
286 }
287
288 if ((unsigned)col >= (unsigned)ri->ri_cols) {
289 stamp_mutex--;
290 return;
291 }
292 #endif
293
294 /* Recompute stamp? */
295 if (attr != stamp_attr)
296 rasops8_makestamp(attr);
297
298 rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
299 height = ri->ri_font->fontheight;
300
301 if (uc == ' ') {
302 while (height--) {
303 rp[0] = stamp[0];
304 rp[1] = stamp[0];
305 DELTA(rp, ri->ri_stride, int32_t *);
306 }
307 } else {
308 uc -= ri->ri_font->firstchar;
309 fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
310 fs = ri->ri_font->stride;
311
312 while (height--) {
313 rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
314 rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
315
316 fr += fs;
317 DELTA(rp, ri->ri_stride, int32_t *);
318 }
319 }
320
321 /* Do underline */
322 if (attr & 1) {
323 DELTA(rp, -(ri->ri_stride << 1), int32_t *);
324 rp[0] = stamp[15];
325 rp[1] = stamp[15];
326 }
327
328 stamp_mutex--;
329 }
330
331
332 /*
333 * Paint a single character. This is for 12-pixel wide fonts.
334 */
335 static void
336 rasops8_putchar12(cookie, row, col, uc, attr)
337 void *cookie;
338 int row, col;
339 u_int uc;
340 long attr;
341 {
342 struct rasops_info *ri;
343 int height, fs;
344 int32_t *rp;
345 u_char *fr;
346
347 /* Can't risk remaking the stamp if it's already in use */
348 if (stamp_mutex++) {
349 stamp_mutex--;
350 rasops8_putchar(cookie, row, col, uc, attr);
351 return;
352 }
353
354 ri = (struct rasops_info *)cookie;
355
356 #ifdef RASOPS_CLIPPING
357 if ((unsigned)row >= (unsigned)ri->ri_rows) {
358 stamp_mutex--;
359 return;
360 }
361
362 if ((unsigned)col >= (unsigned)ri->ri_cols) {
363 stamp_mutex--;
364 return;
365 }
366 #endif
367
368 /* Recompute stamp? */
369 if (attr != stamp_attr)
370 rasops8_makestamp(attr);
371
372 rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
373 height = ri->ri_font->fontheight;
374
375 if (uc == ' ') {
376 while (height--) {
377 rp[0] = stamp[0];
378 rp[1] = stamp[0];
379 rp[2] = stamp[0];
380 DELTA(rp, ri->ri_stride, int32_t *);
381 }
382 } else {
383 uc -= ri->ri_font->firstchar;
384 fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
385 fs = ri->ri_font->stride;
386
387 while (height--) {
388 rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
389 rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
390 rp[2] = STAMP_READ(STAMP_SHIFT(fr[1], 1) & STAMP_MASK);
391
392 fr += fs;
393 DELTA(rp, ri->ri_stride, int32_t *);
394 }
395 }
396
397 /* Do underline */
398 if (attr & 1) {
399 DELTA(rp, -(ri->ri_stride << 1), int32_t *);
400 rp[0] = stamp[15];
401 rp[1] = stamp[15];
402 rp[2] = stamp[15];
403 }
404
405 stamp_mutex--;
406 }
407
408
409 /*
410 * Paint a single character. This is for 16-pixel wide fonts.
411 */
412 static void
413 rasops8_putchar16(cookie, row, col, uc, attr)
414 void *cookie;
415 int row, col;
416 u_int uc;
417 long attr;
418 {
419 struct rasops_info *ri;
420 int height, fs;
421 int32_t *rp;
422 u_char *fr;
423
424 /* Can't risk remaking the stamp if it's already in use */
425 if (stamp_mutex++) {
426 stamp_mutex--;
427 rasops8_putchar(cookie, row, col, uc, attr);
428 return;
429 }
430
431 ri = (struct rasops_info *)cookie;
432
433 #ifdef RASOPS_CLIPPING
434 if ((unsigned)row >= (unsigned)ri->ri_rows) {
435 stamp_mutex--;
436 return;
437 }
438
439 if ((unsigned)col >= (unsigned)ri->ri_cols) {
440 stamp_mutex--;
441 return;
442 }
443 #endif
444
445 /* Recompute stamp? */
446 if (attr != stamp_attr)
447 rasops8_makestamp(attr);
448
449 rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
450 height = ri->ri_font->fontheight;
451
452 if (uc == ' ') {
453 while (height--) {
454 rp[0] = stamp[0];
455 rp[1] = stamp[0];
456 rp[2] = stamp[0];
457 rp[3] = stamp[0];
458 DELTA(rp, ri->ri_stride, int32_t *);
459 }
460 } else {
461 uc -= ri->ri_font->firstchar;
462 fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
463 fs = ri->ri_font->stride;
464
465 while (height--) {
466 rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
467 rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
468 rp[2] = STAMP_READ(STAMP_SHIFT(fr[1], 1) & STAMP_MASK);
469 rp[3] = STAMP_READ(STAMP_SHIFT(fr[1], 0) & STAMP_MASK);
470
471 fr += fs;
472 DELTA(rp, ri->ri_stride, int32_t *);
473 }
474 }
475
476 /* Do underline */
477 if (attr & 1) {
478 DELTA(rp, -(ri->ri_stride << 1), int32_t *);
479 rp[0] = stamp[15];
480 rp[1] = stamp[15];
481 rp[2] = stamp[15];
482 rp[3] = stamp[15];
483 }
484
485 stamp_mutex--;
486 }
487
488
489 /*
490 * Erase rows.
491 */
492 static void
493 rasops8_eraserows(cookie, row, num, attr)
494 void *cookie;
495 int row, num;
496 long attr;
497 {
498 struct rasops_info *ri;
499 int32_t *dp, clr;
500 int n8, n1, cnt;
501
502 ri = (struct rasops_info *)cookie;
503
504 #ifdef RASOPS_CLIPPING
505 if (row < 0) {
506 num += row;
507 row = 0;
508 }
509
510 if ((row + num) > ri->ri_rows)
511 num = ri->ri_rows - row;
512
513 if (num <= 0)
514 return;
515 #endif
516
517 num *= ri->ri_font->fontheight;
518 dp = (int32_t *)(ri->ri_bits + row * ri->ri_yscale);
519 clr = rasops8_bg_color(attr);
520
521 n8 = ri->ri_emustride >> 5;
522 n1 = (ri->ri_emustride >> 2) & 7;
523
524 while (num--) {
525 for (cnt = n8; cnt; cnt--) {
526 dp[0] = clr;
527 dp[1] = clr;
528 dp[2] = clr;
529 dp[3] = clr;
530 dp[4] = clr;
531 dp[5] = clr;
532 dp[6] = clr;
533 dp[7] = clr;
534 dp += 8;
535 }
536
537 for (cnt = n1; cnt; cnt--)
538 *dp++ = clr;
539
540 DELTA(dp, ri->ri_delta, int32_t *);
541 }
542 }
543
544
545 /*
546 * Erase columns.
547 */
548 static void
549 rasops8_erasecols(cookie, row, col, num, attr)
550 void *cookie;
551 int row, col, num;
552 long attr;
553 {
554 int n8, clr, height, cnt, slop1, slop2;
555 struct rasops_info *ri;
556 int32_t *dst;
557 u_char *dstb, *rp;
558
559 ri = (struct rasops_info *)cookie;
560
561 #ifdef RASOPS_CLIPPING
562 if ((unsigned)row >= (unsigned)ri->ri_rows)
563 return;
564
565 if (col < 0) {
566 num += col;
567 col = 0;
568 }
569
570 if ((col + num) > ri->ri_cols)
571 num = ri->ri_cols - col;
572
573 if (num <= 0)
574 return;
575 #endif
576
577 num = num * ri->ri_xscale;
578 rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
579 clr = rasops8_bg_color(attr);
580 height = ri->ri_font->fontheight;
581
582 slop1 = (int)rp & 3;
583 slop2 = (num - slop1) & 3;
584 num -= slop1 + slop2;
585 n8 = num >> 5;
586 num = (num >> 2) & 7;
587
588 while (height--) {
589 dstb = rp;
590 rp += ri->ri_stride;
591
592 /* Align span to 4 bytes */
593 for (cnt = slop1; cnt; cnt--)
594 *dstb++ = (u_char)clr;
595
596 dst = (int32_t *)dstb;
597
598 /* Write 32 bytes per loop */
599 for (cnt = n8; cnt; cnt--) {
600 dst[0] = clr;
601 dst[1] = clr;
602 dst[2] = clr;
603 dst[3] = clr;
604 dst[4] = clr;
605 dst[5] = clr;
606 dst[6] = clr;
607 dst[7] = clr;
608 dst += 8;
609 }
610
611 /* Write 4 bytes per loop */
612 for (cnt = num; cnt; cnt--)
613 *dst++ = clr;
614
615 /* Write unaligned trailing slop */
616 if (slop2 == 0)
617 continue;
618
619 dstb = (u_char *)dst;
620
621 for (cnt = slop2; cnt; cnt--)
622 *dstb++ = (u_char)clr;
623 }
624 }
625
626 #endif /* RASOPS8 */
627