Annotation of sys/dev/rasops/rasops.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: rasops.c,v 1.17 2006/12/02 18:02:53 miod Exp $ */
2: /* $NetBSD: rasops.c,v 1.35 2001/02/02 06:01:01 marcus Exp $ */
3:
4: /*-
5: * Copyright (c) 1999 The NetBSD Foundation, Inc.
6: * All rights reserved.
7: *
8: * This code is derived from software contributed to The NetBSD Foundation
9: * by Andrew Doran.
10: *
11: * Redistribution and use in source and binary forms, with or without
12: * modification, are permitted provided that the following conditions
13: * are met:
14: * 1. Redistributions of source code must retain the above copyright
15: * notice, this list of conditions and the following disclaimer.
16: * 2. Redistributions in binary form must reproduce the above copyright
17: * notice, this list of conditions and the following disclaimer in the
18: * documentation and/or other materials provided with the distribution.
19: * 3. All advertising materials mentioning features or use of this software
20: * must display the following acknowledgement:
21: * This product includes software developed by the NetBSD
22: * Foundation, Inc. and its contributors.
23: * 4. Neither the name of The NetBSD Foundation nor the names of its
24: * contributors may be used to endorse or promote products derived
25: * from this software without specific prior written permission.
26: *
27: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37: * POSSIBILITY OF SUCH DAMAGE.
38: */
39:
40: #include <sys/param.h>
41: #include <sys/systm.h>
42: #include <sys/time.h>
43:
44: #include <machine/endian.h>
45:
46: #include <dev/wscons/wsdisplayvar.h>
47: #include <dev/wscons/wsconsio.h>
48: #include <dev/wsfont/wsfont.h>
49: #include <dev/rasops/rasops.h>
50:
51: #ifndef _KERNEL
52: #include <errno.h>
53: #endif
54:
55: /* ANSI colormap (R,G,B) */
56:
57: #define NORMAL_BLACK 0x000000
58: #define NORMAL_RED 0x7f0000
59: #define NORMAL_GREEN 0x007f00
60: #define NORMAL_BROWN 0x7f7f00
61: #define NORMAL_BLUE 0x00007f
62: #define NORMAL_MAGENTA 0x7f007f
63: #define NORMAL_CYAN 0x007f7f
64: #define NORMAL_WHITE 0xc7c7c7 /* XXX too dim? */
65:
66: #define HILITE_BLACK 0x7f7f7f
67: #define HILITE_RED 0xff0000
68: #define HILITE_GREEN 0x00ff00
69: #define HILITE_BROWN 0xffff00
70: #define HILITE_BLUE 0x0000ff
71: #define HILITE_MAGENTA 0xff00ff
72: #define HILITE_CYAN 0x00ffff
73: #define HILITE_WHITE 0xffffff
74:
75: const u_char rasops_cmap[256 * 3] = {
76: #define _C(x) ((x) & 0xff0000) >> 16, ((x) & 0x00ff00) >> 8, ((x) & 0x0000ff)
77:
78: _C(NORMAL_BLACK),
79: _C(NORMAL_RED),
80: _C(NORMAL_GREEN),
81: _C(NORMAL_BROWN),
82: _C(NORMAL_BLUE),
83: _C(NORMAL_MAGENTA),
84: _C(NORMAL_CYAN),
85: _C(NORMAL_WHITE),
86:
87: _C(HILITE_BLACK),
88: _C(HILITE_RED),
89: _C(HILITE_GREEN),
90: _C(HILITE_BROWN),
91: _C(HILITE_BLUE),
92: _C(HILITE_MAGENTA),
93: _C(HILITE_CYAN),
94: _C(HILITE_WHITE),
95:
96: /*
97: * For the cursor, we need the last 16 colors to be the
98: * opposite of the first 16. Fill the intermediate space with
99: * white completely for simplicity.
100: */
101: #define _CMWHITE16 \
102: _C(HILITE_WHITE), _C(HILITE_WHITE), _C(HILITE_WHITE), _C(HILITE_WHITE), \
103: _C(HILITE_WHITE), _C(HILITE_WHITE), _C(HILITE_WHITE), _C(HILITE_WHITE), \
104: _C(HILITE_WHITE), _C(HILITE_WHITE), _C(HILITE_WHITE), _C(HILITE_WHITE), \
105: _C(HILITE_WHITE), _C(HILITE_WHITE), _C(HILITE_WHITE), _C(HILITE_WHITE),
106: _CMWHITE16 _CMWHITE16 _CMWHITE16 _CMWHITE16 _CMWHITE16
107: _CMWHITE16 _CMWHITE16 _CMWHITE16 _CMWHITE16 _CMWHITE16
108: _CMWHITE16 _CMWHITE16 _CMWHITE16 _CMWHITE16
109: #undef _CMWHITE16
110:
111: _C(~HILITE_WHITE),
112: _C(~HILITE_CYAN),
113: _C(~HILITE_MAGENTA),
114: _C(~HILITE_BLUE),
115: _C(~HILITE_BROWN),
116: _C(~HILITE_GREEN),
117: _C(~HILITE_RED),
118: _C(~HILITE_BLACK),
119:
120: _C(~NORMAL_WHITE),
121: _C(~NORMAL_CYAN),
122: _C(~NORMAL_MAGENTA),
123: _C(~NORMAL_BLUE),
124: _C(~NORMAL_BROWN),
125: _C(~NORMAL_GREEN),
126: _C(~NORMAL_RED),
127: _C(~NORMAL_BLACK),
128:
129: #undef _C
130: };
131:
132: /* True if color is gray */
133: const u_char rasops_isgray[16] = {
134: 1, 0, 0, 0,
135: 0, 0, 0, 1,
136: 1, 0, 0, 0,
137: 0, 0, 0, 1
138: };
139:
140: /* Generic functions */
141: void rasops_copycols(void *, int, int, int, int);
142: void rasops_copyrows(void *, int, int, int);
143: int rasops_mapchar(void *, int, u_int *);
144: void rasops_cursor(void *, int, int, int);
145: int rasops_alloc_cattr(void *, int, int, int, long *);
146: int rasops_alloc_mattr(void *, int, int, int, long *);
147: void rasops_do_cursor(struct rasops_info *);
148: void rasops_init_devcmap(struct rasops_info *);
149: void rasops_unpack_attr(void *, long, int *, int *, int *);
150: #if NRASOPS_BSWAP > 0
151: static void slow_ovbcopy(void *, void *, size_t);
152: #endif
153: #if NRASOPS_ROTATION > 0
154: void rasops_copychar(void *, int, int, int, int);
155: void rasops_copycols_rotated(void *, int, int, int, int);
156: void rasops_copyrows_rotated(void *, int, int, int);
157: void rasops_erasecols_rotated(void *, int, int, int, long);
158: void rasops_eraserows_rotated(void *, int, int, long);
159: void rasops_putchar_rotated(void *, int, int, u_int, long);
160: void rasops_rotate_font(int *);
161:
162: /*
163: * List of all rotated fonts
164: */
165: SLIST_HEAD(, rotatedfont) rotatedfonts = SLIST_HEAD_INITIALIZER(rotatedfonts);
166: struct rotatedfont {
167: SLIST_ENTRY(rotatedfont) rf_next;
168: int rf_cookie;
169: int rf_rotated;
170: };
171: #endif
172:
173: /*
174: * Initialize a 'rasops_info' descriptor.
175: */
176: int
177: rasops_init(ri, wantrows, wantcols)
178: struct rasops_info *ri;
179: int wantrows, wantcols;
180: {
181:
182: #ifdef _KERNEL
183: /* Select a font if the caller doesn't care */
184: if (ri->ri_font == NULL) {
185: int cookie;
186:
187: wsfont_init();
188:
189: if (ri->ri_width > 80*12)
190: /* High res screen, choose a big font */
191: cookie = wsfont_find(NULL, 12, 0, 0);
192: else
193: /* lower res, choose a 8 pixel wide font */
194: cookie = wsfont_find(NULL, 8, 0, 0);
195:
196: if (cookie <= 0)
197: cookie = wsfont_find(NULL, 0, 0, 0);
198:
199: if (cookie <= 0) {
200: printf("rasops_init: font table is empty\n");
201: return (-1);
202: }
203:
204: #if NRASOPS_ROTATION > 0
205: /*
206: * Pick the rotated version of this font. This will create it
207: * if necessary.
208: */
209: if (ri->ri_flg & RI_ROTATE_CW)
210: rasops_rotate_font(&cookie);
211: #endif
212:
213: if (wsfont_lock(cookie, &ri->ri_font,
214: WSDISPLAY_FONTORDER_L2R, WSDISPLAY_FONTORDER_L2R) <= 0) {
215: printf("rasops_init: couldn't lock font\n");
216: return (-1);
217: }
218:
219: ri->ri_wsfcookie = cookie;
220: }
221: #endif
222:
223: /* This should never happen in reality... */
224: #ifdef DEBUG
225: if ((long)ri->ri_bits & 3) {
226: printf("rasops_init: bits not aligned on 32-bit boundary\n");
227: return (-1);
228: }
229:
230: if ((int)ri->ri_stride & 3) {
231: printf("rasops_init: stride not aligned on 32-bit boundary\n");
232: return (-1);
233: }
234: #endif
235:
236: if (rasops_reconfig(ri, wantrows, wantcols))
237: return (-1);
238:
239: rasops_init_devcmap(ri);
240: return (0);
241: }
242:
243: /*
244: * Reconfigure (because parameters have changed in some way).
245: */
246: int
247: rasops_reconfig(ri, wantrows, wantcols)
248: struct rasops_info *ri;
249: int wantrows, wantcols;
250: {
251: int l, bpp, s;
252:
253: s = splhigh();
254:
255: if (ri->ri_font->fontwidth > 32 || ri->ri_font->fontwidth < 4)
256: panic("rasops_init: fontwidth assumptions botched!");
257:
258: /* Need this to frob the setup below */
259: bpp = (ri->ri_depth == 15 ? 16 : ri->ri_depth);
260:
261: if ((ri->ri_flg & RI_CFGDONE) != 0)
262: ri->ri_bits = ri->ri_origbits;
263:
264: /* Don't care if the caller wants a hideously small console */
265: if (wantrows < 10)
266: wantrows = 10;
267:
268: if (wantcols < 20)
269: wantcols = 20;
270:
271: /* Now constrain what they get */
272: ri->ri_emuwidth = ri->ri_font->fontwidth * wantcols;
273: ri->ri_emuheight = ri->ri_font->fontheight * wantrows;
274:
275: if (ri->ri_emuwidth > ri->ri_width)
276: ri->ri_emuwidth = ri->ri_width;
277:
278: if (ri->ri_emuheight > ri->ri_height)
279: ri->ri_emuheight = ri->ri_height;
280:
281: /* Reduce width until aligned on a 32-bit boundary */
282: while ((ri->ri_emuwidth * bpp & 31) != 0)
283: ri->ri_emuwidth--;
284:
285: #if NRASOPS_ROTATION > 0
286: if (ri->ri_flg & RI_ROTATE_CW) {
287: ri->ri_rows = ri->ri_emuwidth / ri->ri_font->fontwidth;
288: ri->ri_cols = ri->ri_emuheight / ri->ri_font->fontheight;
289: } else
290: #endif
291: {
292: ri->ri_cols = ri->ri_emuwidth / ri->ri_font->fontwidth;
293: ri->ri_rows = ri->ri_emuheight / ri->ri_font->fontheight;
294: }
295: ri->ri_emustride = ri->ri_emuwidth * bpp >> 3;
296: ri->ri_delta = ri->ri_stride - ri->ri_emustride;
297: ri->ri_ccol = 0;
298: ri->ri_crow = 0;
299: ri->ri_pelbytes = bpp >> 3;
300:
301: ri->ri_xscale = (ri->ri_font->fontwidth * bpp) >> 3;
302: ri->ri_yscale = ri->ri_font->fontheight * ri->ri_stride;
303: ri->ri_fontscale = ri->ri_font->fontheight * ri->ri_font->stride;
304:
305: #ifdef DEBUG
306: if ((ri->ri_delta & 3) != 0)
307: panic("rasops_init: ri_delta not aligned on 32-bit boundary");
308: #endif
309: /* Clear the entire display */
310: if ((ri->ri_flg & RI_CLEAR) != 0) {
311: memset(ri->ri_bits, 0, ri->ri_stride * ri->ri_height);
312: ri->ri_flg &= ~RI_CLEARMARGINS;
313: }
314:
315: /* Now centre our window if needs be */
316: ri->ri_origbits = ri->ri_bits;
317:
318: if ((ri->ri_flg & RI_CENTER) != 0) {
319: ri->ri_bits += (((ri->ri_width * bpp >> 3) -
320: ri->ri_emustride) >> 1) & ~3;
321: ri->ri_bits += ((ri->ri_height - ri->ri_emuheight) >> 1) *
322: ri->ri_stride;
323:
324: ri->ri_yorigin = (int)(ri->ri_bits - ri->ri_origbits)
325: / ri->ri_stride;
326: ri->ri_xorigin = (((int)(ri->ri_bits - ri->ri_origbits)
327: % ri->ri_stride) * 8 / bpp);
328: } else
329: ri->ri_xorigin = ri->ri_yorigin = 0;
330:
331: /* Clear the margins */
332: if ((ri->ri_flg & RI_CLEARMARGINS) != 0) {
333: memset(ri->ri_origbits, 0, ri->ri_bits - ri->ri_origbits);
334: for (l = 0; l < ri->ri_emuheight; l++)
335: memset(ri->ri_bits + ri->ri_emustride +
336: l * ri->ri_stride, 0,
337: ri->ri_stride - ri->ri_emustride);
338: memset(ri->ri_bits + ri->ri_emuheight * ri->ri_stride, 0,
339: (ri->ri_origbits + ri->ri_height * ri->ri_stride) -
340: (ri->ri_bits + ri->ri_emuheight * ri->ri_stride));
341: }
342:
343: /*
344: * Fill in defaults for operations set. XXX this nukes private
345: * routines used by accelerated fb drivers.
346: */
347: ri->ri_ops.mapchar = rasops_mapchar;
348: ri->ri_ops.copyrows = rasops_copyrows;
349: ri->ri_ops.copycols = rasops_copycols;
350: ri->ri_ops.erasecols = rasops_erasecols;
351: ri->ri_ops.eraserows = rasops_eraserows;
352: ri->ri_ops.cursor = rasops_cursor;
353: ri->ri_ops.unpack_attr = rasops_unpack_attr;
354: ri->ri_do_cursor = rasops_do_cursor;
355: ri->ri_updatecursor = NULL;
356:
357: if (ri->ri_depth < 8 || (ri->ri_flg & RI_FORCEMONO) != 0) {
358: ri->ri_ops.alloc_attr = rasops_alloc_mattr;
359: ri->ri_caps = WSSCREEN_UNDERLINE | WSSCREEN_REVERSE;
360: } else {
361: ri->ri_ops.alloc_attr = rasops_alloc_cattr;
362: ri->ri_caps = WSSCREEN_UNDERLINE | WSSCREEN_HILIT |
363: WSSCREEN_WSCOLORS | WSSCREEN_REVERSE;
364: }
365:
366: switch (ri->ri_depth) {
367: #if NRASOPS1 > 0
368: case 1:
369: rasops1_init(ri);
370: break;
371: #endif
372: #if NRASOPS2 > 0
373: case 2:
374: rasops2_init(ri);
375: break;
376: #endif
377: #if NRASOPS4 > 0
378: case 4:
379: rasops4_init(ri);
380: break;
381: #endif
382: #if NRASOPS8 > 0
383: case 8:
384: rasops8_init(ri);
385: break;
386: #endif
387: #if NRASOPS15 > 0 || NRASOPS16 > 0
388: case 15:
389: case 16:
390: rasops15_init(ri);
391: break;
392: #endif
393: #if NRASOPS24 > 0
394: case 24:
395: rasops24_init(ri);
396: break;
397: #endif
398: #if NRASOPS32 > 0
399: case 32:
400: rasops32_init(ri);
401: break;
402: #endif
403: default:
404: ri->ri_flg &= ~RI_CFGDONE;
405: splx(s);
406: return (-1);
407: }
408:
409: #if NRASOPS_ROTATION > 0
410: if (ri->ri_flg & RI_ROTATE_CW) {
411: ri->ri_real_ops = ri->ri_ops;
412: ri->ri_ops.copycols = rasops_copycols_rotated;
413: ri->ri_ops.copyrows = rasops_copyrows_rotated;
414: ri->ri_ops.erasecols = rasops_erasecols_rotated;
415: ri->ri_ops.eraserows = rasops_eraserows_rotated;
416: ri->ri_ops.putchar = rasops_putchar_rotated;
417: }
418: #endif
419:
420: ri->ri_flg |= RI_CFGDONE;
421: splx(s);
422: return (0);
423: }
424:
425: /*
426: * Map a character.
427: */
428: int
429: rasops_mapchar(cookie, c, cp)
430: void *cookie;
431: int c;
432: u_int *cp;
433: {
434: struct rasops_info *ri;
435:
436: ri = (struct rasops_info *)cookie;
437:
438: #ifdef DIAGNOSTIC
439: if (ri->ri_font == NULL)
440: panic("rasops_mapchar: no font selected");
441: #endif
442: if (ri->ri_font->encoding != WSDISPLAY_FONTENC_ISO) {
443:
444: if ( (c = wsfont_map_unichar(ri->ri_font, c)) < 0) {
445:
446: *cp = ' ';
447: return (0);
448:
449: }
450: }
451:
452:
453: if (c < ri->ri_font->firstchar) {
454: *cp = ' ';
455: return (0);
456: }
457:
458: if (c - ri->ri_font->firstchar >= ri->ri_font->numchars) {
459: *cp = ' ';
460: return (0);
461: }
462:
463: *cp = c;
464: return (5);
465: }
466:
467: /*
468: * Allocate a color attribute.
469: */
470: int
471: rasops_alloc_cattr(cookie, fg, bg, flg, attr)
472: void *cookie;
473: int fg, bg, flg;
474: long *attr;
475: {
476: int swap;
477:
478: #ifdef RASOPS_CLIPPING
479: fg &= 7;
480: bg &= 7;
481: #endif
482: if ((flg & WSATTR_BLINK) != 0)
483: return (EINVAL);
484:
485: if ((flg & WSATTR_WSCOLORS) == 0) {
486: fg = WSCOL_WHITE;
487: bg = WSCOL_BLACK;
488: }
489:
490: if ((flg & WSATTR_REVERSE) != 0) {
491: swap = fg;
492: fg = bg;
493: bg = swap;
494: }
495:
496: if ((flg & WSATTR_HILIT) != 0)
497: fg += 8;
498:
499: flg = ((flg & WSATTR_UNDERLINE) ? 1 : 0);
500:
501: if (rasops_isgray[fg])
502: flg |= 2;
503:
504: if (rasops_isgray[bg])
505: flg |= 4;
506:
507: *attr = (bg << 16) | (fg << 24) | flg;
508: return (0);
509: }
510:
511: /*
512: * Allocate a mono attribute.
513: */
514: int
515: rasops_alloc_mattr(cookie, fg, bg, flg, attr)
516: void *cookie;
517: int fg, bg, flg;
518: long *attr;
519: {
520: int swap;
521:
522: if ((flg & (WSATTR_BLINK | WSATTR_HILIT | WSATTR_WSCOLORS)) != 0)
523: return (EINVAL);
524:
525: fg = 1;
526: bg = 0;
527:
528: if ((flg & WSATTR_REVERSE) != 0) {
529: swap = fg;
530: fg = bg;
531: bg = swap;
532: }
533:
534: *attr = (bg << 16) | (fg << 24) | ((flg & WSATTR_UNDERLINE) ? 7 : 6);
535: return (0);
536: }
537:
538: /*
539: * Copy rows.
540: */
541: void
542: rasops_copyrows(cookie, src, dst, num)
543: void *cookie;
544: int src, dst, num;
545: {
546: int32_t *sp, *dp, *srp, *drp;
547: struct rasops_info *ri;
548: int n8, n1, cnt, delta;
549:
550: ri = (struct rasops_info *)cookie;
551:
552: #ifdef RASOPS_CLIPPING
553: if (dst == src)
554: return;
555:
556: if (src < 0) {
557: num += src;
558: src = 0;
559: }
560:
561: if ((src + num) > ri->ri_rows)
562: num = ri->ri_rows - src;
563:
564: if (dst < 0) {
565: num += dst;
566: dst = 0;
567: }
568:
569: if ((dst + num) > ri->ri_rows)
570: num = ri->ri_rows - dst;
571:
572: if (num <= 0)
573: return;
574: #endif
575:
576: num *= ri->ri_font->fontheight;
577: n8 = ri->ri_emustride >> 5;
578: n1 = (ri->ri_emustride >> 2) & 7;
579:
580: if (dst < src) {
581: srp = (int32_t *)(ri->ri_bits + src * ri->ri_yscale);
582: drp = (int32_t *)(ri->ri_bits + dst * ri->ri_yscale);
583: delta = ri->ri_stride;
584: } else {
585: src = ri->ri_font->fontheight * src + num - 1;
586: dst = ri->ri_font->fontheight * dst + num - 1;
587: srp = (int32_t *)(ri->ri_bits + src * ri->ri_stride);
588: drp = (int32_t *)(ri->ri_bits + dst * ri->ri_stride);
589: delta = -ri->ri_stride;
590: }
591:
592: while (num--) {
593: dp = drp;
594: sp = srp;
595: DELTA(drp, delta, int32_t *);
596: DELTA(srp, delta, int32_t *);
597:
598: for (cnt = n8; cnt; cnt--) {
599: dp[0] = sp[0];
600: dp[1] = sp[1];
601: dp[2] = sp[2];
602: dp[3] = sp[3];
603: dp[4] = sp[4];
604: dp[5] = sp[5];
605: dp[6] = sp[6];
606: dp[7] = sp[7];
607: dp += 8;
608: sp += 8;
609: }
610:
611: for (cnt = n1; cnt; cnt--)
612: *dp++ = *sp++;
613: }
614: }
615:
616: /*
617: * Copy columns. This is slow, and hard to optimize due to alignment,
618: * and the fact that we have to copy both left->right and right->left.
619: * We simply cop-out here and use ovbcopy(), since it handles all of
620: * these cases anyway.
621: */
622: void
623: rasops_copycols(cookie, row, src, dst, num)
624: void *cookie;
625: int row, src, dst, num;
626: {
627: struct rasops_info *ri;
628: u_char *sp, *dp;
629: int height;
630:
631: ri = (struct rasops_info *)cookie;
632:
633: #ifdef RASOPS_CLIPPING
634: if (dst == src)
635: return;
636:
637: /* Catches < 0 case too */
638: if ((unsigned)row >= (unsigned)ri->ri_rows)
639: return;
640:
641: if (src < 0) {
642: num += src;
643: src = 0;
644: }
645:
646: if ((src + num) > ri->ri_cols)
647: num = ri->ri_cols - src;
648:
649: if (dst < 0) {
650: num += dst;
651: dst = 0;
652: }
653:
654: if ((dst + num) > ri->ri_cols)
655: num = ri->ri_cols - dst;
656:
657: if (num <= 0)
658: return;
659: #endif
660:
661: num *= ri->ri_xscale;
662: row *= ri->ri_yscale;
663: height = ri->ri_font->fontheight;
664:
665: sp = ri->ri_bits + row + src * ri->ri_xscale;
666: dp = ri->ri_bits + row + dst * ri->ri_xscale;
667:
668: #if NRASOPS_BSWAP > 0
669: if (ri->ri_flg & RI_BSWAP) {
670: while (height--) {
671: slow_ovbcopy(sp, dp, num);
672: dp += ri->ri_stride;
673: sp += ri->ri_stride;
674: }
675: } else
676: #endif
677: {
678: while (height--) {
679: ovbcopy(sp, dp, num);
680: dp += ri->ri_stride;
681: sp += ri->ri_stride;
682: }
683: }
684: }
685:
686: /*
687: * Turn cursor off/on.
688: */
689: void
690: rasops_cursor(cookie, on, row, col)
691: void *cookie;
692: int on, row, col;
693: {
694: struct rasops_info *ri;
695:
696: ri = (struct rasops_info *)cookie;
697:
698: /* Turn old cursor off */
699: if ((ri->ri_flg & RI_CURSOR) != 0)
700: #ifdef RASOPS_CLIPPING
701: if ((ri->ri_flg & RI_CURSORCLIP) == 0)
702: #endif
703: ri->ri_do_cursor(ri);
704:
705: /* Select new cursor */
706: #ifdef RASOPS_CLIPPING
707: ri->ri_flg &= ~RI_CURSORCLIP;
708:
709: if (row < 0 || row >= ri->ri_rows)
710: ri->ri_flg |= RI_CURSORCLIP;
711: else if (col < 0 || col >= ri->ri_cols)
712: ri->ri_flg |= RI_CURSORCLIP;
713: #endif
714: ri->ri_crow = row;
715: ri->ri_ccol = col;
716:
717: if (ri->ri_updatecursor != NULL)
718: ri->ri_updatecursor(ri);
719:
720: if (on) {
721: ri->ri_flg |= RI_CURSOR;
722: #ifdef RASOPS_CLIPPING
723: if ((ri->ri_flg & RI_CURSORCLIP) == 0)
724: #endif
725: ri->ri_do_cursor(ri);
726: } else
727: ri->ri_flg &= ~RI_CURSOR;
728: }
729:
730: /*
731: * Make the device colormap
732: */
733: void
734: rasops_init_devcmap(ri)
735: struct rasops_info *ri;
736: {
737: int i;
738: #if NRASOPS15 > 0 || NRASOPS16 > 0 || NRASOPS24 > 0 || NRASOPS32 > 0
739: const u_char *p;
740: #endif
741: #if NRASOPS4 > 0 || NRASOPS15 > 0 || NRASOPS16 > 0 || NRASOPS24 > 0 || NRASOPS32 > 0
742: int c;
743: #endif
744:
745: switch (ri->ri_depth) {
746: #if NRASOPS1 > 0
747: case 1:
748: ri->ri_devcmap[0] = 0;
749: for (i = 1; i < 16; i++)
750: ri->ri_devcmap[i] = 0xffffffff;
751: return;
752: #endif
753: #if NRASOPS2 > 0
754: case 2:
755: for (i = 1; i < 15; i++)
756: ri->ri_devcmap[i] = 0xaaaaaaaa;
757:
758: ri->ri_devcmap[0] = 0;
759: ri->ri_devcmap[8] = 0x55555555;
760: ri->ri_devcmap[15] = 0xffffffff;
761: return;
762: #endif
763: #if NRASOPS4 > 0
764: case 4:
765: for (i = 0; i < 16; i++) {
766: c = i | (i << 4);
767: ri->ri_devcmap[i] = c | (c<<8) | (c<<16) | (c<<24);
768: }
769: return;
770: #endif
771: #if NRASOPS8 > 0
772: case 8:
773: for (i = 0; i < 16; i++)
774: ri->ri_devcmap[i] = i | (i<<8) | (i<<16) | (i<<24);
775: return;
776: #endif
777: default:
778: break;
779: }
780:
781: #if NRASOPS15 > 0 || NRASOPS16 > 0 || NRASOPS24 > 0 || NRASOPS32 > 0
782: p = rasops_cmap;
783:
784: for (i = 0; i < 16; i++) {
785: if (ri->ri_rnum <= 8)
786: c = (*p >> (8 - ri->ri_rnum)) << ri->ri_rpos;
787: else
788: c = (*p << (ri->ri_rnum - 8)) << ri->ri_rpos;
789: p++;
790:
791: if (ri->ri_gnum <= 8)
792: c |= (*p >> (8 - ri->ri_gnum)) << ri->ri_gpos;
793: else
794: c |= (*p << (ri->ri_gnum - 8)) << ri->ri_gpos;
795: p++;
796:
797: if (ri->ri_bnum <= 8)
798: c |= (*p >> (8 - ri->ri_bnum)) << ri->ri_bpos;
799: else
800: c |= (*p << (ri->ri_bnum - 8)) << ri->ri_bpos;
801: p++;
802:
803: /* Fill the word for generic routines, which want this */
804: if (ri->ri_depth == 24)
805: c = c | ((c & 0xff) << 24);
806: else if (ri->ri_depth <= 16)
807: c = c | (c << 16);
808:
809: /* 24bpp does bswap on the fly. {32,16,15}bpp do it here. */
810: #if NRASOPS_BSWAP > 0
811: if ((ri->ri_flg & RI_BSWAP) == 0)
812: ri->ri_devcmap[i] = c;
813: else if (ri->ri_depth == 32)
814: ri->ri_devcmap[i] = swap32(c);
815: else if (ri->ri_depth == 16 || ri->ri_depth == 15)
816: ri->ri_devcmap[i] = swap16(c);
817: else
818: ri->ri_devcmap[i] = c;
819: #else
820: ri->ri_devcmap[i] = c;
821: #endif
822: }
823: #endif
824: }
825:
826: /*
827: * Unpack a rasops attribute
828: */
829: void
830: rasops_unpack_attr(cookie, attr, fg, bg, underline)
831: void *cookie;
832: long attr;
833: int *fg, *bg, *underline;
834: {
835: *fg = ((u_int)attr >> 24) & 0xf;
836: *bg = ((u_int)attr >> 16) & 0xf;
837: if (underline != NULL)
838: *underline = (u_int)attr & 1;
839: }
840:
841: /*
842: * Erase rows
843: */
844: void
845: rasops_eraserows(cookie, row, num, attr)
846: void *cookie;
847: int row, num;
848: long attr;
849: {
850: struct rasops_info *ri;
851: int np, nw, cnt, delta;
852: int32_t *dp, clr;
853:
854: ri = (struct rasops_info *)cookie;
855:
856: #ifdef RASOPS_CLIPPING
857: if (row < 0) {
858: num += row;
859: row = 0;
860: }
861:
862: if ((row + num) > ri->ri_rows)
863: num = ri->ri_rows - row;
864:
865: if (num <= 0)
866: return;
867: #endif
868:
869: clr = ri->ri_devcmap[(attr >> 16) & 0xf];
870:
871: /*
872: * XXX The wsdisplay_emulops interface seems a little deficient in
873: * that there is no way to clear the *entire* screen. We provide a
874: * workaround here: if the entire console area is being cleared, and
875: * the RI_FULLCLEAR flag is set, clear the entire display.
876: */
877: if (num == ri->ri_rows && (ri->ri_flg & RI_FULLCLEAR) != 0) {
878: np = ri->ri_stride >> 5;
879: nw = (ri->ri_stride >> 2) & 7;
880: num = ri->ri_height;
881: dp = (int32_t *)ri->ri_origbits;
882: delta = 0;
883: } else {
884: np = ri->ri_emustride >> 5;
885: nw = (ri->ri_emustride >> 2) & 7;
886: num *= ri->ri_font->fontheight;
887: dp = (int32_t *)(ri->ri_bits + row * ri->ri_yscale);
888: delta = ri->ri_delta;
889: }
890:
891: while (num--) {
892: for (cnt = np; cnt; cnt--) {
893: dp[0] = clr;
894: dp[1] = clr;
895: dp[2] = clr;
896: dp[3] = clr;
897: dp[4] = clr;
898: dp[5] = clr;
899: dp[6] = clr;
900: dp[7] = clr;
901: dp += 8;
902: }
903:
904: for (cnt = nw; cnt; cnt--) {
905: *(int32_t *)dp = clr;
906: DELTA(dp, 4, int32_t *);
907: }
908:
909: DELTA(dp, delta, int32_t *);
910: }
911: }
912:
913: /*
914: * Actually turn the cursor on or off. This does the dirty work for
915: * rasops_cursor().
916: */
917: void
918: rasops_do_cursor(ri)
919: struct rasops_info *ri;
920: {
921: int full1, height, cnt, slop1, slop2, row, col;
922: u_char *dp, *rp;
923:
924: #if NRASOPS_ROTATION > 0
925: if (ri->ri_flg & RI_ROTATE_CW) {
926: /* Rotate rows/columns */
927: row = ri->ri_ccol;
928: col = ri->ri_rows - ri->ri_crow - 1;
929: } else
930: #endif
931: {
932: row = ri->ri_crow;
933: col = ri->ri_ccol;
934: }
935:
936: rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
937: height = ri->ri_font->fontheight;
938: slop1 = (4 - ((long)rp & 3)) & 3;
939:
940: if (slop1 > ri->ri_xscale)
941: slop1 = ri->ri_xscale;
942:
943: slop2 = (ri->ri_xscale - slop1) & 3;
944: full1 = (ri->ri_xscale - slop1 - slop2) >> 2;
945:
946: if ((slop1 | slop2) == 0) {
947: /* A common case */
948: while (height--) {
949: dp = rp;
950: rp += ri->ri_stride;
951:
952: for (cnt = full1; cnt; cnt--) {
953: *(int32_t *)dp ^= ~0;
954: dp += 4;
955: }
956: }
957: } else {
958: /* XXX this is stupid.. use masks instead */
959: while (height--) {
960: dp = rp;
961: rp += ri->ri_stride;
962:
963: if (slop1 & 1)
964: *dp++ ^= ~0;
965:
966: if (slop1 & 2) {
967: *(int16_t *)dp ^= ~0;
968: dp += 2;
969: }
970:
971: for (cnt = full1; cnt; cnt--) {
972: *(int32_t *)dp ^= ~0;
973: dp += 4;
974: }
975:
976: if (slop2 & 1)
977: *dp++ ^= ~0;
978:
979: if (slop2 & 2)
980: *(int16_t *)dp ^= ~0;
981: }
982: }
983: }
984:
985: /*
986: * Erase columns.
987: */
988: void
989: rasops_erasecols(cookie, row, col, num, attr)
990: void *cookie;
991: int row, col, num;
992: long attr;
993: {
994: int n8, height, cnt, slop1, slop2, clr;
995: struct rasops_info *ri;
996: int32_t *rp, *dp;
997:
998: ri = (struct rasops_info *)cookie;
999:
1000: #ifdef RASOPS_CLIPPING
1001: if ((unsigned)row >= (unsigned)ri->ri_rows)
1002: return;
1003:
1004: if (col < 0) {
1005: num += col;
1006: col = 0;
1007: }
1008:
1009: if ((col + num) > ri->ri_cols)
1010: num = ri->ri_cols - col;
1011:
1012: if (num <= 0)
1013: return;
1014: #endif
1015:
1016: num = num * ri->ri_xscale;
1017: rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
1018: height = ri->ri_font->fontheight;
1019: clr = ri->ri_devcmap[(attr >> 16) & 0xf];
1020:
1021: /* Don't bother using the full loop for <= 32 pels */
1022: if (num <= 32) {
1023: if (((num | ri->ri_xscale) & 3) == 0) {
1024: /* Word aligned blt */
1025: num >>= 2;
1026:
1027: while (height--) {
1028: dp = rp;
1029: DELTA(rp, ri->ri_stride, int32_t *);
1030:
1031: for (cnt = num; cnt; cnt--)
1032: *dp++ = clr;
1033: }
1034: } else if (((num | ri->ri_xscale) & 1) == 0) {
1035: /*
1036: * Halfword aligned blt. This is needed so the
1037: * 15/16 bit ops can use this function.
1038: */
1039: num >>= 1;
1040:
1041: while (height--) {
1042: dp = rp;
1043: DELTA(rp, ri->ri_stride, int32_t *);
1044:
1045: for (cnt = num; cnt; cnt--) {
1046: *(int16_t *)dp = clr;
1047: DELTA(dp, 2, int32_t *);
1048: }
1049: }
1050: } else {
1051: while (height--) {
1052: dp = rp;
1053: DELTA(rp, ri->ri_stride, int32_t *);
1054:
1055: for (cnt = num; cnt; cnt--) {
1056: *(u_char *)dp = clr;
1057: DELTA(dp, 1, int32_t *);
1058: }
1059: }
1060: }
1061:
1062: return;
1063: }
1064:
1065: slop1 = (4 - ((long)rp & 3)) & 3;
1066: slop2 = (num - slop1) & 3;
1067: num -= slop1 + slop2;
1068: n8 = num >> 5;
1069: num = (num >> 2) & 7;
1070:
1071: while (height--) {
1072: dp = rp;
1073: DELTA(rp, ri->ri_stride, int32_t *);
1074:
1075: /* Align span to 4 bytes */
1076: if (slop1 & 1) {
1077: *(u_char *)dp = clr;
1078: DELTA(dp, 1, int32_t *);
1079: }
1080:
1081: if (slop1 & 2) {
1082: *(int16_t *)dp = clr;
1083: DELTA(dp, 2, int32_t *);
1084: }
1085:
1086: /* Write 32 bytes per loop */
1087: for (cnt = n8; cnt; cnt--) {
1088: dp[0] = clr;
1089: dp[1] = clr;
1090: dp[2] = clr;
1091: dp[3] = clr;
1092: dp[4] = clr;
1093: dp[5] = clr;
1094: dp[6] = clr;
1095: dp[7] = clr;
1096: dp += 8;
1097: }
1098:
1099: /* Write 4 bytes per loop */
1100: for (cnt = num; cnt; cnt--)
1101: *dp++ = clr;
1102:
1103: /* Write unaligned trailing slop */
1104: if (slop2 & 1) {
1105: *(u_char *)dp = clr;
1106: DELTA(dp, 1, int32_t *);
1107: }
1108:
1109: if (slop2 & 2)
1110: *(int16_t *)dp = clr;
1111: }
1112: }
1113:
1114: #if NRASOPS_ROTATION > 0
1115: /*
1116: * Quarter clockwise rotation routines (originally intended for the
1117: * built-in Zaurus C3x00 display in 16bpp).
1118: */
1119:
1120: #include <sys/malloc.h>
1121:
1122: void
1123: rasops_rotate_font(int *cookie)
1124: {
1125: struct rotatedfont *f;
1126: int ncookie;
1127:
1128: SLIST_FOREACH(f, &rotatedfonts, rf_next) {
1129: if (f->rf_cookie == *cookie) {
1130: *cookie = f->rf_rotated;
1131: return;
1132: }
1133: }
1134:
1135: /*
1136: * We did not find a rotated version of this font. Ask the wsfont
1137: * code to compute one for us.
1138: */
1139:
1140: f = malloc(sizeof(struct rotatedfont), M_DEVBUF, M_WAITOK);
1141: if (f == NULL)
1142: return;
1143:
1144: if ((ncookie = wsfont_rotate(*cookie)) == -1)
1145: return;
1146:
1147: f->rf_cookie = *cookie;
1148: f->rf_rotated = ncookie;
1149: SLIST_INSERT_HEAD(&rotatedfonts, f, rf_next);
1150:
1151: *cookie = ncookie;
1152: }
1153:
1154: void
1155: rasops_copychar(cookie, srcrow, dstrow, srccol, dstcol)
1156: void *cookie;
1157: int srcrow, dstrow, srccol, dstcol;
1158: {
1159: struct rasops_info *ri;
1160: u_char *sp, *dp;
1161: int height;
1162: int r_srcrow, r_dstrow, r_srccol, r_dstcol;
1163:
1164: ri = (struct rasops_info *)cookie;
1165:
1166: r_srcrow = srccol;
1167: r_dstrow = dstcol;
1168: r_srccol = ri->ri_rows - srcrow - 1;
1169: r_dstcol = ri->ri_rows - dstrow - 1;
1170:
1171: r_srcrow *= ri->ri_yscale;
1172: r_dstrow *= ri->ri_yscale;
1173: height = ri->ri_font->fontheight;
1174:
1175: sp = ri->ri_bits + r_srcrow + r_srccol * ri->ri_xscale;
1176: dp = ri->ri_bits + r_dstrow + r_dstcol * ri->ri_xscale;
1177:
1178: #if NRASOPS_BSWAP > 0
1179: if (ri->ri_flg & RI_BSWAP) {
1180: while (height--) {
1181: slow_ovbcopy(sp, dp, ri->ri_xscale);
1182: dp += ri->ri_stride;
1183: sp += ri->ri_stride;
1184: }
1185: } else
1186: #endif
1187: {
1188: while (height--) {
1189: ovbcopy(sp, dp, ri->ri_xscale);
1190: dp += ri->ri_stride;
1191: sp += ri->ri_stride;
1192: }
1193: }
1194: }
1195:
1196: void
1197: rasops_putchar_rotated(cookie, row, col, uc, attr)
1198: void *cookie;
1199: int row, col;
1200: u_int uc;
1201: long attr;
1202: {
1203: struct rasops_info *ri;
1204: u_char *rp;
1205: int height;
1206:
1207: ri = (struct rasops_info *)cookie;
1208:
1209: /* Do rotated char sans (side)underline */
1210: ri->ri_real_ops.putchar(cookie, col, ri->ri_rows - row - 1, uc,
1211: attr & ~1);
1212:
1213: /* Do rotated underline */
1214: rp = ri->ri_bits + col * ri->ri_yscale + (ri->ri_rows - row - 1) *
1215: ri->ri_xscale;
1216: height = ri->ri_font->fontheight;
1217:
1218: /* XXX this assumes 16-bit color depth */
1219: if ((attr & 1) != 0) {
1220: int16_t c = (int16_t)ri->ri_devcmap[((u_int)attr >> 24) & 0xf];
1221:
1222: while (height--) {
1223: *(int16_t *)rp = c;
1224: rp += ri->ri_stride;
1225: }
1226: }
1227: }
1228:
1229: void
1230: rasops_erasecols_rotated(cookie, row, col, num, attr)
1231: void *cookie;
1232: int row, col, num;
1233: long attr;
1234: {
1235: struct rasops_info *ri;
1236: int i;
1237:
1238: ri = (struct rasops_info *)cookie;
1239:
1240: for (i = col; i < col + num; i++)
1241: ri->ri_ops.putchar(cookie, row, i, ' ', attr);
1242: }
1243:
1244: /* XXX: these could likely be optimised somewhat. */
1245: void
1246: rasops_copyrows_rotated(cookie, src, dst, num)
1247: void *cookie;
1248: int src, dst, num;
1249: {
1250: struct rasops_info *ri = (struct rasops_info *)cookie;
1251: int col, roff;
1252:
1253: if (src > dst)
1254: for (roff = 0; roff < num; roff++)
1255: for (col = 0; col < ri->ri_cols; col++)
1256: rasops_copychar(cookie, src + roff, dst + roff,
1257: col, col);
1258: else
1259: for (roff = num - 1; roff >= 0; roff--)
1260: for (col = 0; col < ri->ri_cols; col++)
1261: rasops_copychar(cookie, src + roff, dst + roff,
1262: col, col);
1263: }
1264:
1265: void
1266: rasops_copycols_rotated(cookie, row, src, dst, num)
1267: void *cookie;
1268: int row, src, dst, num;
1269: {
1270: int coff;
1271:
1272: if (src > dst)
1273: for (coff = 0; coff < num; coff++)
1274: rasops_copychar(cookie, row, row, src + coff, dst + coff);
1275: else
1276: for (coff = num - 1; coff >= 0; coff--)
1277: rasops_copychar(cookie, row, row, src + coff, dst + coff);
1278: }
1279:
1280: void
1281: rasops_eraserows_rotated(cookie, row, num, attr)
1282: void *cookie;
1283: int row, num;
1284: long attr;
1285: {
1286: struct rasops_info *ri;
1287: int col, rn;
1288:
1289: ri = (struct rasops_info *)cookie;
1290:
1291: for (rn = row; rn < row + num; rn++)
1292: for (col = 0; col < ri->ri_cols; col++)
1293: ri->ri_ops.putchar(cookie, rn, col, ' ', attr);
1294: }
1295: #endif /* NRASOPS_ROTATION */
1296:
1297: #if NRASOPS_BSWAP > 0
1298: /*
1299: * Strictly byte-only ovbcopy() version, to be used with RI_BSWAP, as the
1300: * regular ovbcopy() may want to optimize things by doing larger-than-byte
1301: * reads or write. This may confuse things if src and dst have different
1302: * alignments.
1303: */
1304: void
1305: slow_ovbcopy(void *s, void *d, size_t len)
1306: {
1307: u_int8_t *src = s;
1308: u_int8_t *dst = d;
1309:
1310: if ((vaddr_t)dst <= (vaddr_t)src) {
1311: while (len-- != 0)
1312: *dst++ = *src++;
1313: } else {
1314: src += len;
1315: dst += len;
1316: if (len != 0)
1317: while (--len != 0)
1318: *--dst = *--src;
1319: }
1320: }
1321: #endif /* NRASOPS_BSWAP */
CVSweb