rasops1.c revision 1.2 1 /* $NetBSD: rasops1.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 RASOPS1
32
33 #include <sys/cdefs.h>
34 __KERNEL_RCSID(0, "$NetBSD: rasops1.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 #include <machine/endian.h>
41
42 #include <dev/wscons/wsdisplayvar.h>
43 #include <dev/rasops/rasops.h>
44
45 static void rasops1_putchar __P((void *, int, int col, u_int, long));
46 static void rasops1_putchar8 __P((void *, int, int col, u_int, long));
47 static void rasops1_putchar16 __P((void *, int, int col, u_int, long));
48 static void rasops1_copycols __P((void *, int, int, int, int));
49 static void rasops1_erasecols __P((void *, int, int, int));
50 static void rasops1_erasecols8 __P((void *, int, int, int));
51 static void rasops1_eraserows __P((void *, int, int));
52 static int32_t rasops1_fg_color __P((long));
53 static int32_t rasops1_bg_color __P((long));
54 static void rasops1_do_cursor __P((struct rasops_info *));
55 static void rasops1_do_cursor8 __P((struct rasops_info *));
56
57 void rasops1_init __P((struct rasops_info *ri));
58
59 #if BYTE_ORDER == LITTLE_ENDIAN
60 static u_int32_t rightmask[32] = {
61 #else
62 static u_int32_t leftmask[32] = {
63 #endif
64 0x00000000, 0x80000000, 0xc0000000, 0xe0000000,
65 0xf0000000, 0xf8000000, 0xfc000000, 0xfe000000,
66 0xff000000, 0xff800000, 0xffc00000, 0xffe00000,
67 0xfff00000, 0xfff80000, 0xfffc0000, 0xfffe0000,
68 0xffff0000, 0xffff8000, 0xffffc000, 0xffffe000,
69 0xfffff000, 0xfffff800, 0xfffffc00, 0xfffffe00,
70 0xffffff00, 0xffffff80, 0xffffffc0, 0xffffffe0,
71 0xfffffff0, 0xfffffff8, 0xfffffffc, 0xfffffffe,
72 };
73
74 #if BYTE_ORDER == LITTLE_ENDIAN
75 static u_int32_t leftmask[32] = {
76 #else
77 static u_int32_t rightmask[32] = {
78 #endif
79 0x00000000, 0x00000001, 0x00000003, 0x00000007,
80 0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f,
81 0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff,
82 0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff,
83 0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff,
84 0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff,
85 0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff,
86 0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff,
87 };
88
89
90 /*
91 * Initalize rasops_info struct for this colordepth.
92 */
93 void
94 rasops1_init(ri)
95 struct rasops_info *ri;
96 {
97
98 switch (ri->ri_font->fontwidth) {
99 case 8:
100 ri->ri_ops.putchar = rasops1_putchar8;
101 break;
102 case 16:
103 ri->ri_ops.putchar = rasops1_putchar16;
104 break;
105 default:
106 /*
107 * XXX we don't support anything other than 8 and 16 pel
108 * wide fonts yet. rasops1_copycols needs to be finished, the
109 * other routines will need to be checked.
110 */
111 panic("rasops1_init: not completed - see this location in src for details");
112 ri->ri_ops.putchar = rasops1_putchar;
113 break;
114 }
115
116 if (ri->ri_font->fontwidth & 7) {
117 ri->ri_ops.erasecols = rasops1_erasecols;
118 ri->ri_ops.copycols = rasops1_copycols;
119 ri->ri_do_cursor = rasops1_do_cursor;
120 } else {
121 ri->ri_ops.erasecols = rasops1_erasecols8;
122 /* use default copycols */
123 ri->ri_do_cursor = rasops1_do_cursor8;
124 }
125
126 ri->ri_ops.eraserows = rasops1_eraserows;
127 }
128
129
130 /*
131 * Get foreground color from attribute and copy across all 4 bytes
132 * in a int32_t.
133 */
134 static __inline__ int32_t
135 rasops1_fg_color(long attr)
136 {
137
138 return (attr & 0x0f000000) ? 0xffffffff : 0;
139 }
140
141
142 /*
143 * Get background color from attribute and copy across all 4 bytes
144 * in a int32_t.
145 */
146 static __inline__ int32_t
147 rasops1_bg_color(long attr)
148 {
149
150 return (attr & 0x000f0000) ? 0xffffffff : 0;
151 }
152
153
154 /*
155 * Paint a single character. This is the generic version.
156 */
157 static void
158 rasops1_putchar(cookie, row, col, uc, attr)
159 void *cookie;
160 int row, col;
161 u_int uc;
162 long attr;
163 {
164
165 /* XXX i need implemention */
166 }
167
168
169 /*
170 * Paint a single character. This is for 8-pixel wide fonts.
171 */
172 static void
173 rasops1_putchar8(cookie, row, col, uc, attr)
174 void *cookie;
175 int row, col;
176 u_int uc;
177 long attr;
178 {
179 int height, fs, rs, bg, fg;
180 struct rasops_info *ri;
181 u_char *fr, *rp;
182
183 ri = (struct rasops_info *)cookie;
184
185 #ifdef RASOPS_CLIPPING
186 if (row < 0 || row >= ri->ri_rows)
187 return;
188
189 if (col < 0 || col >= ri->ri_cols)
190 return;
191 #endif
192
193 rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
194 height = ri->ri_font->fontheight;
195 rs = ri->ri_stride;
196
197 bg = (attr & 0x000f0000) ? 0xff : 0;
198 fg = (attr & 0x0f000000) ? 0xff : 0;
199
200 /* If fg and bg match this becomes a space character */
201 if (fg == bg || uc == ' ') {
202 while (height--) {
203 *rp = bg;
204 rp += rs;
205 }
206 } else {
207 uc -= ri->ri_font->firstchar;
208 fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
209 fs = ri->ri_font->stride;
210
211 /* NOT fontbits if bg is white */
212 if (bg) {
213 while (height--) {
214 *rp = ~*fr;
215 fr += fs;
216 rp += rs;
217 }
218 } else {
219 while (height--) {
220 *rp = *fr;
221 fr += fs;
222 rp += rs;
223 }
224 }
225 }
226
227 /* Do underline */
228 if (attr & 1)
229 rp[-(ri->ri_stride << 1)] = fg;
230 }
231
232
233 /*
234 * Paint a single character. This is for 16-pixel wide fonts.
235 */
236 static void
237 rasops1_putchar16(cookie, row, col, uc, attr)
238 void *cookie;
239 int row, col;
240 u_int uc;
241 long attr;
242 {
243 int height, fs, rs, bg, fg;
244 struct rasops_info *ri;
245 u_char *fr, *rp;
246
247 ri = (struct rasops_info *)cookie;
248
249 #ifdef RASOPS_CLIPPING
250 if (row < 0 || row >= ri->ri_rows)
251 return;
252
253 if (col < 0 || col >= ri->ri_cols)
254 return;
255 #endif
256
257 rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
258 height = ri->ri_font->fontheight;
259 rs = ri->ri_stride;
260
261 bg = (attr & 0x000f0000) ? 0xffff : 0;
262 fg = (attr & 0x0f000000) ? 0xffff : 0;
263
264 /* If fg and bg match this becomes a space character */
265 if (fg == bg || uc == ' ') {
266 while (height--) {
267 *(int16_t *)rp = bg;
268 rp += rs;
269 }
270 } else {
271 uc -= ri->ri_font->firstchar;
272 fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
273 fs = ri->ri_font->stride;
274
275 /* NOT fontbits if bg is white */
276 if (bg) {
277 while (height--) {
278 rp[0] = ~fr[0];
279 rp[1] = ~fr[1];
280 fr += fs;
281 rp += rs;
282 }
283 } else {
284 while (height--) {
285 rp[0] = fr[0];
286 rp[1] = fr[1];
287 fr += fs;
288 rp += rs;
289 }
290 }
291 }
292
293 /* Do underline */
294 if (attr & 1)
295 *(int16_t *)(rp - (ri->ri_stride << 1)) = fg;
296 }
297
298
299 /*
300 * Erase columns.
301 */
302 static void
303 rasops1_erasecols(cookie, row, col, num, attr)
304 void *cookie;
305 int row, num;
306 long attr;
307 {
308 int32_t *dp, *rp, lmask, rmask, lclr, rclr, clr;
309 struct rasops_info *ri;
310 int nint, height, cnt;
311
312 ri = (struct rasops_info *)cookie;
313
314 #ifdef RASOPS_CLIPPING
315 if (row < 0 || row > ri->ri_rows)
316 return;
317
318 if (col < 0) {
319 num += col;
320 col = 0;
321 }
322
323 if ((col + num) > ri->ri_cols)
324 num = ri->ri_cols - col;
325
326 if (num <= 0)
327 return;
328 #endif
329 col *= ri->ri_fontwidth;
330 num *= ri->ri_fontwidth;
331
332 /*
333 * lmask: mask for leftmost int32
334 * rmask: mask for rightmost int32
335 * nint: number of full int32s
336 */
337 lmask = leftmask[col & 31];
338 rmask = rightmask[(col + num) & 31];
339 nint = ((col + num) & ~31) - ((col + 31) & ~31) >> 5;
340
341 /* Merge both masks if the span is encapsulated within one int32 */
342 if (col & ~31 == (col + num) & ~31) {
343 lmask &= rmask;
344 rmask = 0;
345 }
346
347 clr = rasops1_bg_color(attr);
348 lclr = clr & lmask;
349 rclr = clr & rmask;
350 lmask = ~lmask;
351 rmask = ~rmask;
352 height = ri->ri_fontheight;
353 rp = ri->ri_bits + row*ri->ri_yscale + ((col >> 3) & ~3);
354
355 while (height--) {
356 dp = rp;
357 DELTA(rp, ri->ri_stride, int32_t *);
358
359 if (lmask != 0xffffffffU)
360 *dp++ = (*dp & lmask) | lclr;
361
362 for (cnt = nint; cnt; cnt--)
363 *dp++ = clr;
364
365 if (rmask != 0xffffffffU)
366 *dp = (*dp & rmask) | rclr;
367 }
368 }
369
370
371 /*
372 * Erase columns for fonts that are a multiple of 8 pels in width.
373 */
374 static void
375 rasops1_erasecols8(cookie, row, col, num, attr)
376 void *cookie;
377 int row, col, num;
378 long attr;
379 {
380 struct rasops_info *ri;
381 int32_t *dst;
382 u_char *dstb, *rp;
383 int clr, height, cnt, slop1, slop2;
384
385 ri = (struct rasops_info *)cookie;
386
387 #ifdef RASOPS_CLIPPING
388 if (row < 0 || row >= ri->ri_rows)
389 return;
390
391 if (col < 0) {
392 num += col;
393 col = 0;
394 }
395
396 if ((col + num) > ri->ri_cols)
397 num = ri->ri_cols - col;
398
399 if (num <= 0)
400 return;
401 #endif
402
403 num = num * ri->ri_xscale;
404 rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
405 clr = rasops1_bg_color(attr);
406 height = ri->ri_font->fontheight;
407
408 slop1 = (int)rp & 3;
409 slop2 = (num - slop1) & 3;
410 num = (num - slop1 - slop2) >> 2;
411
412 while (height--) {
413 dstb = rp;
414 rp += ri->ri_stride;
415
416 /* Align span to 4 bytes */
417 for (cnt = slop1; cnt; cnt--)
418 *dstb++ = (u_char)clr;
419
420 dst = (int32_t *)dstb;
421
422 /* Write 4 bytes per loop */
423 for (cnt = num; cnt; cnt--)
424 *dst++ = clr;
425
426 /* Write unaligned trailing slop */
427 if (slop2 == 0)
428 continue;
429
430 dstb = (u_char *)dst;
431
432 for (cnt = slop2; cnt; cnt--)
433 *dstb++ = (u_char)clr;
434 }
435 }
436
437
438 /*
439 * Actually paint the cursor.
440 */
441 static void
442 rasops1_do_cursor(ri)
443 struct rasops_info *ri;
444 {
445 int32_t *dp, *rp, lmask, rmask;
446 int height, row, col;
447
448 row = ri->ri_crow;
449 col = ri->ri_ccol * ri->ri_fontwidth;
450
451 /*
452 * lmask: mask for leftmost int32
453 * rmask: mask for rightmost int32
454 */
455 lmask = leftmask[col & 31];
456 rmask = rightmask[(col + ri->ri_fontwidth) & 31];
457
458 /* Merge both masks if the span is encapsulated within one int32 */
459 if (col & ~31 == (col + ri->ri_fontwidth) & ~31) {
460 lmask &= rmask;
461 rmask = 0;
462 }
463
464 lmask = ~lmask;
465 rmask = ~rmask;
466 height = ri->ri_fontheight;
467 rp = ri->ri_bits + row*ri->ri_yscale + ((col >> 3) & ~3);
468
469 while (height--) {
470 dp = rp;
471 DELTA(rp, ri->ri_stride, int32_t *);
472
473 *dp++ = ((*dp & lmask) ^ lmask) | (*dp & ~lmask);
474
475 if (rmask != 0xffffffffU)
476 *dp = ((*dp & rmask) ^ rmask) | (*dp & ~rmask);
477 }
478 }
479
480
481 /*
482 * Paint cursors that are a multiple of 8 pels in size.
483 */
484 static void
485 rasops1_do_cursor8(ri)
486 struct rasops_info *ri;
487 {
488 int width, height, cnt;
489 u_char *dp, *rp;
490
491 height = ri->ri_fontheight;
492 width = ri->ri_fontwidth >> 3;
493 rp = ri->ri_bits + ri->ri_crow * ri->ri_yscale +
494 ri->ri_ccol * ri->ri_xscale;
495
496 while (height--) {
497 dp = rp;
498 rp += ri->ri_stride;
499
500 for (cnt = width; cnt; cnt--)
501 *dp++ ^= 0xff;
502 }
503 }
504
505
506 /*
507 * Erase rows.
508 */
509 static void
510 rasops1_eraserows(cookie, row, num, attr)
511 void *cookie;
512 int row, num;
513 long attr;
514 {
515 struct rasops_info *ri;
516 int32_t *dp, clr;
517 int n8, n1, cnt;
518
519 ri = (struct rasops_info *)cookie;
520
521 #ifdef RASOPS_CLIPPING
522 if (row < 0) {
523 num += row;
524 row = 0;
525 }
526
527 if ((row + num) > ri->ri_rows)
528 num = ri->ri_rows - row;
529
530 if (num <= 0)
531 return;
532 #endif
533
534 num *= ri->ri_font->fontheight;
535 dp = (int32_t *)(ri->ri_bits + row * ri->ri_yscale);
536 clr = rasops1_bg_color(attr);
537
538 n8 = ri->ri_emustride >> 5;
539 n1 = (ri->ri_emustride >> 2) & 7;
540
541 while (num--) {
542 for (cnt = n8; cnt; cnt--) {
543 dp[0] = clr;
544 dp[1] = clr;
545 dp[2] = clr;
546 dp[3] = clr;
547 dp[4] = clr;
548 dp[5] = clr;
549 dp[6] = clr;
550 dp[7] = clr;
551 dp += 8;
552 }
553
554 for (cnt = n1; cnt; cnt--)
555 *dp++ = clr;
556
557 DELTA(dp, ri->ri_delta, int32_t *);
558 }
559 }
560
561
562 /*
563 * Copy columns. This is slow. Ick! You'd better use a font with
564 * a width that's a multiple of 8 pels, otherwise this is used...
565 */
566 static void
567 rasops1_copycols(cookie, row, src, src)
568 void *cookie;
569 int row, src, dst;
570 {
571 #ifdef notyet
572 struct rasops_info *ri;
573 int32_t *dp, *drp, *sp, *srp, lmask, rmask;
574 int nint, height, cnt;
575
576 ri = (struct rasops_info *)cookie;
577
578 #ifdef RASOPS_CLIPPING
579 if (row < 0 || row >= ri->ri_rows)
580 return;
581
582 if (col < 0) {
583 num += col;
584 col = 0;
585 }
586
587 if ((col + num) > ri->ri_cols)
588 num = ri->ri_cols - col;
589
590 if (num <= 0)
591 return;
592 #endif
593 src *= ri->ri_fontwidth;
594 dst *= ri->ri_fontwidth;
595 num *= ri->ri_fontwidth;
596
597 /*
598 * lmask: mask for leftmost int32
599 * rmask: mask for rightmost int32
600 * nint: number of full int32s
601 */
602 lmask = leftmask[col & 31];
603 rmask = rightmask[(col + num) & 31];
604 nint = ((col + num) & ~31) - ((col + 31) & ~31) >> 5;
605
606 /* Merge both masks if the span is encapsulated within one int32 */
607 if (col & ~31 == (col + num) & ~31) {
608 lmask &= rmask;
609 rmask = 0;
610 }
611
612 lmask = ~lmask;
613 rmask = ~rmask;
614 height = ri->ri_fontheight;
615 drp = ri->ri_bits + row*ri->ri_yscale + ((dst >> 3) & ~3);
616 srp = ri->ri_bits + row*ri->ri_yscale + ((src >> 3) & ~3);
617
618 while (height--) {
619 dp = rp;
620 DELTA(rp, ri->ri_stride, int32_t *);
621
622 if (lmask != 0xffffffffU)
623 *dp++ = (*dp & lmask) | lclr;
624
625 for (cnt = nint; cnt; cnt--)
626 *dp++ = clr;
627
628 if (rmask != 0xffffffffU)
629 *dp = (*dp & rmask) | rclr;
630 }
631 #endif
632 }
633
634 #endif /* RASOPS1 */
635