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