rasops.c revision 1.1 1 /* $NetBSD: rasops.c,v 1.1 1999/04/13 00:17:58 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 <sys/cdefs.h>
39 __KERNEL_RCSID(0, "$NetBSD: rasops.c,v 1.1 1999/04/13 00:17:58 ad Exp $");
40
41 #include "opt_rasops.h"
42
43 #include <sys/types.h>
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/time.h>
47
48 #include <dev/wscons/wsdisplayvar.h>
49 #include <dev/wscons/wsconsio.h>
50 #include <dev/wsfont/wsfont.h>
51 #include <dev/rasops/rasops.h>
52
53 /* ANSI colormap (R,G,B). Upper 8 are high-intensity */
54 u_char rasops_cmap[256*3] = {
55 0x00, 0x00, 0x00, /* black */
56 0x7f, 0x00, 0x00, /* red */
57 0x00, 0x7f, 0x00, /* green */
58 0x7f, 0x7f, 0x00, /* brown */
59 0x00, 0x00, 0x7f, /* blue */
60 0x7f, 0x00, 0x7f, /* magenta */
61 0x00, 0x7f, 0x7f, /* cyan */
62 0xc7, 0xc7, 0xc7, /* white - XXX too dim? */
63
64 0x7f, 0x7f, 0x7f, /* black */
65 0xff, 0x00, 0x00, /* red */
66 0x00, 0xff, 0x00, /* green */
67 0xff, 0xff, 0x00, /* brown */
68 0x00, 0x00, 0xff, /* blue */
69 0xff, 0x00, 0xff, /* magenta */
70 0x00, 0xff, 0xff, /* cyan */
71 0xff, 0xff, 0xff, /* white */
72 };
73
74 /* True if color is gray */
75 u_char rasops_isgray[16] = {
76 1, 0, 0, 0,
77 0, 0, 0, 1,
78 1, 0, 0, 0,
79 0, 0, 0, 1
80 };
81
82 /* Common functions */
83 static void rasops_copycols __P((void *, int, int, int, int));
84 static void rasops_copyrows __P((void *, int, int, int));
85 static int rasops_mapchar __P((void *, int, u_int *));
86 static void rasops_cursor __P((void *, int, int, int));
87 static int rasops_alloc_cattr __P((void *, int, int, int, long *));
88 static int rasops_alloc_mattr __P((void *, int, int, int, long *));
89
90 /* Per-depth initalization functions */
91 void rasops1_init __P((struct rasops_info *));
92 void rasops8_init __P((struct rasops_info *));
93 void rasops15_init __P((struct rasops_info *));
94 void rasops24_init __P((struct rasops_info *));
95 void rasops32_init __P((struct rasops_info *));
96
97 /*
98 * Initalize a 'rasops_info' descriptor.
99 */
100 int
101 rasops_init(ri, wantrows, wantcols, clear, center)
102 struct rasops_info *ri;
103 int wantrows, wantcols, clear, center;
104 {
105
106 /* Select a font if the caller doesn't care */
107 if (ri->ri_font == NULL) {
108 int cookie;
109
110 wsfont_init();
111
112 /* Want 8 pixel wide, don't care about aestethics */
113 if ((cookie = wsfont_find(NULL, 8, 0, 0)) < 0)
114 cookie = wsfont_find(NULL, 0, 0, 0);
115
116 if (cookie < 0) {
117 printf("rasops_init: font table is empty\n");
118 return (-1);
119 }
120
121 if (wsfont_lock(cookie, &ri->ri_font,
122 WSFONT_LITTLE, WSFONT_LITTLE) < 0) {
123 printf("rasops_init: couldn't lock font\n");
124 return (-1);
125 }
126 }
127
128 /* This should never happen in reality... */
129 #ifdef DEBUG
130 if ((int)ri->ri_bits & 3) {
131 printf("rasops_init: bits not aligned on 32-bit boundary\n");
132 return (-1);
133 }
134
135 if ((int)ri->ri_stride & 3) {
136 printf("rasops_init: stride not aligned on 32-bit boundary\n");
137 return (-1);
138 }
139
140 if (ri->ri_font->fontwidth > 32) {
141 printf("rasops_init: fontwidth > 32\n");
142 return (-1);
143 }
144 #endif
145
146 /* Fix color palette. We need this for the cursor to work. */
147 rasops_cmap[255*3+0] = 0xff;
148 rasops_cmap[255*3+1] = 0xff;
149 rasops_cmap[255*3+2] = 0xff;
150
151 /* Don't care if the caller wants a hideously small console */
152 if (wantrows < 10)
153 wantrows = 5000;
154
155 if (wantcols < 20)
156 wantcols = 5000;
157
158 /* Now constrain what they get */
159 ri->ri_emuwidth = ri->ri_font->fontwidth * wantcols;
160 ri->ri_emuheight = ri->ri_font->fontheight * wantrows;
161
162 if (ri->ri_emuwidth > ri->ri_width)
163 ri->ri_emuwidth = ri->ri_width;
164
165 if (ri->ri_emuheight > ri->ri_height)
166 ri->ri_emuheight = ri->ri_height;
167
168 /* Reduce width until aligned on a 32-bit boundary */
169 while ((ri->ri_emuwidth*ri->ri_depth & 31) != 0)
170 ri->ri_emuwidth--;
171
172 ri->ri_cols = ri->ri_emuwidth / ri->ri_font->fontwidth;
173 ri->ri_rows = ri->ri_emuheight / ri->ri_font->fontheight;
174 ri->ri_emustride = ri->ri_emuwidth * ri->ri_depth >> 3;
175 ri->ri_delta = ri->ri_stride - ri->ri_emustride;
176 ri->ri_ccol = 0;
177 ri->ri_crow = 0;
178 ri->ri_pelbytes = ri->ri_depth >> 3;
179
180 ri->ri_xscale = (ri->ri_font->fontwidth * ri->ri_depth) >> 3;
181 ri->ri_yscale = ri->ri_font->fontheight * ri->ri_stride;
182 ri->ri_fontscale = ri->ri_font->fontheight * ri->ri_font->stride;
183
184 #ifdef DEBUG
185 if (ri->ri_delta & 3)
186 panic("rasops_init: delta isn't aligned on 32-bit boundary!");
187 #endif
188 /* Clear the entire display */
189 if (clear)
190 bzero(ri->ri_bits, ri->ri_stride * ri->ri_height);
191
192 /* Now centre our window if needs be */
193 ri->ri_origbits = ri->ri_bits;
194
195 if (center) {
196 ri->ri_bits += ((ri->ri_stride - ri->ri_emustride) >> 1) & ~3;
197 ri->ri_bits += ((ri->ri_height - ri->ri_emuheight) >> 1) *
198 ri->ri_stride;
199 }
200
201 /* Fill in defaults for operations set */
202 ri->ri_ops.mapchar = rasops_mapchar;
203 ri->ri_ops.copyrows = rasops_copyrows;
204 ri->ri_ops.copycols = rasops_copycols;
205 ri->ri_ops.cursor = rasops_cursor;
206
207 if (ri->ri_depth == 1 || ri->ri_forcemono)
208 ri->ri_ops.alloc_attr = rasops_alloc_mattr;
209 else
210 ri->ri_ops.alloc_attr = rasops_alloc_cattr;
211
212 switch (ri->ri_depth) {
213 #ifdef RASOPS1
214 case 1:
215 rasops1_init(ri);
216 break;
217 #endif
218
219 #ifdef RASOPS8
220 case 8:
221 rasops8_init(ri);
222 break;
223 #endif
224
225 #if defined(RASOPS15) || defined(RASOPS16)
226 case 15:
227 case 16:
228 rasops15_init(ri);
229 break;
230 #endif
231
232 #ifdef RASOPS24
233 case 24:
234 rasops24_init(ri);
235 break;
236 #endif
237
238 #ifdef RASOPS24
239 case 32:
240 rasops32_init(ri);
241 break;
242 #endif
243 default:
244 ri->ri_flg = 0;
245 return (-1);
246 }
247
248 ri->ri_flg = RASOPS_INITTED;
249 return (0);
250 }
251
252
253 /*
254 * Map a character.
255 */
256 static int
257 rasops_mapchar(cookie, c, cp)
258 void *cookie;
259 int c;
260 u_int *cp;
261 {
262 struct rasops_info *ri;
263
264 ri = (struct rasops_info *)cookie;
265
266 if (c < ri->ri_font->firstchar) {
267 *cp = ' ';
268 return (0);
269 }
270
271 if (c - ri->ri_font->firstchar >= ri->ri_font->numchars) {
272 *cp = ' ';
273 return (0);
274 }
275
276 *cp = c;
277 return (5);
278 }
279
280
281 /*
282 * Allocate a color attribute.
283 */
284 static int
285 rasops_alloc_cattr(cookie, fg, bg, flg, attr)
286 void *cookie;
287 int fg, bg, flg;
288 long *attr;
289 {
290 int swap;
291
292 #ifdef RASOPS_CLIPPING
293 fg &= 7;
294 bg &= 7;
295 flg &= 255;
296 #endif
297 if (flg & WSATTR_BLINK)
298 return (EINVAL);
299
300 if (flg & WSATTR_REVERSE) {
301 swap = fg;
302 fg = bg;
303 bg = swap;
304 }
305
306 if (flg & WSATTR_HILIT)
307 fg += 8;
308
309 flg = ((flg & WSATTR_UNDERLINE) ? 1 : 0);
310
311 if (rasops_isgray[fg])
312 flg |= 2;
313
314 if (rasops_isgray[bg])
315 flg |= 4;
316
317 *attr = (bg << 16) | (fg << 24) | flg;
318 return 0;
319 }
320
321
322 /*
323 * Allocate a mono attribute.
324 */
325 static int
326 rasops_alloc_mattr(cookie, fg, bg, flg, attr)
327 void *cookie;
328 int fg, bg, flg;
329 long *attr;
330 {
331 int swap;
332
333 #ifdef RASOPS_CLIPPING
334 flg &= 255;
335 #endif
336 fg = fg ? 1 : 0;
337 bg = bg ? 1 : 0;
338
339 if (flg & WSATTR_BLINK)
340 return (EINVAL);
341
342 if (!(flg & WSATTR_REVERSE) ^ !(flg & WSATTR_HILIT)) {
343 swap = fg;
344 fg = bg;
345 bg = swap;
346 }
347
348 *attr = (bg << 16) | (fg << 24) | ((flg & WSATTR_UNDERLINE) ? 7 : 6);
349 return 0;
350 }
351
352
353 /*
354 * Copy rows.
355 */
356 static void
357 rasops_copyrows(cookie, src, dst, num)
358 void *cookie;
359 int src, dst, num;
360 {
361 struct rasops_info *ri;
362 int32_t *sp, *dp, *srp, *drp;
363 int n8, n1, cnt;
364
365 ri = (struct rasops_info *)cookie;
366
367 #ifdef RASOPS_CLIPPING
368 if (dst == src)
369 return;
370
371 if (src < 0) {
372 num += src;
373 src = 0;
374 }
375
376 if ((src + num) > ri->ri_rows)
377 num = ri->ri_rows - src;
378
379 if (dst < 0) {
380 num += dst;
381 dst = 0;
382 }
383
384 if ((dst + num) > ri->ri_rows)
385 num = ri->ri_rows - dst;
386
387 if (num <= 0)
388 return;
389 #endif
390
391 num *= ri->ri_font->fontheight;
392 n8 = ri->ri_emustride >> 5;
393 n1 = (ri->ri_emustride >> 2) & 7;
394
395 if (dst < src) {
396 sp = (int32_t *)(ri->ri_bits + src * ri->ri_yscale);
397 dp = (int32_t *)(ri->ri_bits + dst * ri->ri_yscale);
398
399 while (num--) {
400 for (cnt = n8; cnt; cnt--) {
401 dp[0] = sp[0];
402 dp[1] = sp[1];
403 dp[2] = sp[2];
404 dp[3] = sp[3];
405 dp[4] = sp[4];
406 dp[5] = sp[5];
407 dp[6] = sp[6];
408 dp[7] = sp[7];
409 dp += 8;
410 sp += 8;
411 }
412
413 for (cnt = n1; cnt; cnt--)
414 *dp++ = *sp++;
415
416 DELTA(dp, ri->ri_delta, int32_t *);
417 DELTA(sp, ri->ri_delta, int32_t *);
418 }
419 } else {
420 src = ri->ri_font->fontheight * src + num - 1;
421 dst = ri->ri_font->fontheight * dst + num - 1;
422
423 srp = (int32_t *)(ri->ri_bits + src * ri->ri_stride);
424 drp = (int32_t *)(ri->ri_bits + dst * ri->ri_stride);
425
426 while (num--) {
427 dp = drp;
428 sp = srp;
429 DELTA(srp, -ri->ri_stride, int32_t *);
430 DELTA(drp, -ri->ri_stride, int32_t *);
431
432 for (cnt = n8; cnt; cnt--) {
433 dp[0] = sp[0];
434 dp[1] = sp[1];
435 dp[2] = sp[2];
436 dp[3] = sp[3];
437 dp[4] = sp[4];
438 dp[5] = sp[5];
439 dp[6] = sp[6];
440 dp[7] = sp[7];
441 dp += 8;
442 sp += 8;
443 }
444
445 for (cnt = n1; cnt; cnt--)
446 *dp++ = *sp++;
447 }
448 }
449 }
450
451
452 /*
453 * Copy columns. This is slow, and hard to optimize due to alignment,
454 * and the fact that we have to copy both left->right and right->left.
455 * We simply cop-out here and use bcopy(), since it handles all of
456 * these cases anyway.
457 */
458 static void
459 rasops_copycols(cookie, row, src, dst, num)
460 void *cookie;
461 int row, src, dst, num;
462 {
463 struct rasops_info *ri;
464 u_char *sp, *dp;
465 int height;
466
467 ri = (struct rasops_info *)cookie;
468
469 #ifdef RASOPS_CLIPPING
470 if (dst == src)
471 return;
472
473 if (row < 0 || row >= ri->ri_rows)
474 return;
475
476 if (src < 0) {
477 num += src;
478 src = 0;
479 }
480
481 if ((src + num) > ri->ri_cols)
482 num = ri->ri_cols - src;
483
484 if (dst < 0) {
485 num += dst;
486 dst = 0;
487 }
488
489 if ((dst + num) > ri->ri_cols)
490 num = ri->ri_cols - dst;
491
492 if (num <= 0)
493 return;
494 #endif
495
496 num *= ri->ri_xscale;
497 row *= ri->ri_yscale;
498 height = ri->ri_font->fontheight;
499
500 sp = ri->ri_bits + row + src * ri->ri_xscale;
501 dp = ri->ri_bits + row + dst * ri->ri_xscale;
502
503 while (height--) {
504 bcopy(sp, dp, num);
505 dp += ri->ri_stride;
506 sp += ri->ri_stride;
507 }
508 }
509
510
511 /*
512 * Turn cursor off/on.
513 */
514 static void
515 rasops_cursor(cookie, on, row, col)
516 void *cookie;
517 int on, row, col;
518 {
519 struct rasops_info *ri;
520
521 ri = (struct rasops_info *)cookie;
522
523 /* Turn old cursor off */
524 if (ri->ri_flg & RASOPS_CURSOR)
525 #ifdef RASOPS_CLIPPING
526 if (!(ri->ri_flg & RASOPS_CURSOR_CLIPPED))
527 #endif
528 ri->ri_do_cursor(ri);
529
530 /* Select new cursor */
531 #ifdef RASOPS_CLIPPING
532 ri->ri_flg &= ~RASOPS_CURSOR_CLIPPED;
533
534 if (row < 0 || row >= ri->ri_rows)
535 ri->ri_flg |= RASOPS_CURSOR_CLIPPED;
536 else if (col < 0 || col >= ri->ri_cols)
537 ri->ri_flg |= RASOPS_CURSOR_CLIPPED;
538 #endif
539 ri->ri_crow = row;
540 ri->ri_ccol = col;
541
542 if (on) {
543 ri->ri_flg |= RASOPS_CURSOR;
544 #ifdef RASOPS_CLIPPING
545 if (!(ri->ri_flg & RASOPS_CURSOR_CLIPPED))
546 #endif
547 ri->ri_do_cursor(ri);
548 } else
549 ri->ri_flg &= ~RASOPS_CURSOR;
550 }
551
552
553 #if (RASOPS15 + RASOPS16 + RASOPS32)
554 /*
555 * Make the device colormap
556 */
557 void
558 rasops_init_devcmap(ri)
559 struct rasops_info *ri;
560 {
561 int i, c;
562 u_char *p;
563
564 p = rasops_cmap;
565
566 for (i = 0; i < 16; i++) {
567 if (ri->ri_rnum <= 8)
568 c = (*p++ >> (8 - ri->ri_rnum)) << ri->ri_rpos;
569 else
570 c = (*p++ << (ri->ri_rnum - 8)) << ri->ri_rpos;
571
572 if (ri->ri_gnum <= 8)
573 c = (*p++ >> (8 - ri->ri_gnum)) << ri->ri_gpos;
574 else
575 c = (*p++ << (ri->ri_gnum - 8)) << ri->ri_gpos;
576
577 if (ri->ri_bnum <= 8)
578 c = (*p++ >> (8 - ri->ri_bnum)) << ri->ri_bpos;
579 else
580 c = (*p++ << (ri->ri_bnum - 8)) << ri->ri_bpos;
581
582 ri->ri_devcmap[i] = c;
583 }
584 }
585 #endif
586
587
588 /*
589 * Unpack a rasops attribute
590 */
591 void
592 rasops_unpack_attr(attr, fg, bg, underline)
593 long attr;
594 int *fg, *bg, *underline;
595 {
596
597 *fg = ((u_int)attr >> 24) & 15;
598 *bg = ((u_int)attr >> 16) & 15;
599 *underline = (u_int)attr & 1;
600 }
601