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