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