Index: arch/arm/xscale/files.pxa2x0 =================================================================== RCS file: /cvsroot/src/sys/arch/arm/xscale/files.pxa2x0,v retrieving revision 1.12 diff -u -r1.12 files.pxa2x0 --- arch/arm/xscale/files.pxa2x0 17 Dec 2006 16:03:33 -0000 1.12 +++ arch/arm/xscale/files.pxa2x0 18 Dec 2006 09:43:20 -0000 @@ -42,7 +42,7 @@ file arch/arm/sa11x0/sa11x0_ost.c saost needs-flag # LCD controller -device lcd: wsemuldisplaydev, rasops16, rasops8, rasops4 +device lcd: wsemuldisplaydev, rasops16, rasops8, rasops4, rasops_rotation file arch/arm/xscale/pxa2x0_lcd.c lcd needs-flag # XXX this is a hack to use dev/pcmcia without fdc.c Index: arch/zaurus/dev/zlcd.c =================================================================== RCS file: /cvsroot/src/sys/arch/zaurus/dev/zlcd.c,v retrieving revision 1.2 diff -u -r1.2 zlcd.c --- arch/zaurus/dev/zlcd.c 17 Dec 2006 16:07:11 -0000 1.2 +++ arch/zaurus/dev/zlcd.c 18 Dec 2006 09:43:20 -0000 @@ -77,7 +77,7 @@ .capabilities = WSSCREEN_WSCOLORS, }, .depth = 16, /* bits per pixel */ - .flags = 0/*RI_ROTATE_CW*/, /* quarter clockwise rotation */ + .flags = RI_ROTATE_CW, /* quarter clockwise rotation */ }; static const struct wsscreen_descr *lcd_scr_descr[] = { Index: conf/files =================================================================== RCS file: /cvsroot/src/sys/conf/files,v retrieving revision 1.820 diff -u -r1.820 files --- conf/files 11 Dec 2006 15:24:28 -0000 1.820 +++ conf/files 18 Dec 2006 09:43:21 -0000 @@ -297,6 +297,7 @@ define rasops16 define rasops24 define rasops32 +define rasops_rotation # splash screen support include "dev/splash/files.splash" Index: dev/wsfont/files.wsfont =================================================================== RCS file: /cvsroot/src/sys/dev/wsfont/files.wsfont,v retrieving revision 1.14 diff -u -r1.14 files.wsfont --- dev/wsfont/files.wsfont 11 Dec 2005 12:24:12 -0000 1.14 +++ dev/wsfont/files.wsfont 18 Dec 2006 09:43:21 -0000 @@ -2,7 +2,10 @@ defpseudo wsfont -file dev/wsfont/wsfont.c rasterconsole | wsdisplay | wsfont +# Note: `wsfont_glue' is only here to force the header file's name +# hence it must be mentioned first (shudder...) +file dev/wsfont/wsfont.c (wsfont_glue & rasops_rotation) | + rasterconsole | wsdisplay | wsfont needs-flag defflag opt_wsfont.h FONT_BOLD8x16 FONT_GALLANT12x22 Index: dev/wsfont/wsfont.c =================================================================== RCS file: /cvsroot/src/sys/dev/wsfont/wsfont.c,v retrieving revision 1.43 diff -u -r1.43 wsfont.c --- dev/wsfont/wsfont.c 28 Aug 2006 21:35:12 -0000 1.43 +++ dev/wsfont/wsfont.c 18 Dec 2006 09:43:22 -0000 @@ -51,6 +51,8 @@ #include #include +#include "wsfont_glue.h" /* NRASOPS_ROTATION */ + #undef HAVE_FONT #ifdef FONT_QVSS8x15 @@ -300,6 +302,100 @@ } } +#if NRASOPS_ROTATION > 0 + +struct wsdisplay_font *wsfont_rotate_internal(struct wsdisplay_font *); + +struct wsdisplay_font * +wsfont_rotate_internal(struct wsdisplay_font *font) +{ + int b, n, r, newstride; + struct wsdisplay_font *newfont; + char *newbits; + + /* Duplicate the existing font... */ + newfont = malloc(sizeof(*font), M_DEVBUF, M_WAITOK); + if (newfont == NULL) + return (NULL); + + memcpy(newfont, font, sizeof(*font)); + + /* Allocate a buffer big enough for the rotated font. */ + newstride = (font->fontheight + 7) / 8; + newbits = malloc(newstride * font->fontwidth * font->numchars, + M_DEVBUF, M_WAITOK); + if (newbits == NULL) { + free(newfont, M_DEVBUF); + return (NULL); + } + + memset(newbits, 0, newstride * font->fontwidth * font->numchars); + + /* Rotate the font a bit at a time. */ + for (n = 0; n < font->numchars; n++) { + char *ch = (char *)font->data + + (n * font->stride * font->fontheight); + + for (r = 0; r < font->fontheight; r++) { + for (b = 0; b < font->fontwidth; b++) { + unsigned char *rb; + + rb = ch + (font->stride * r) + (b / 8); + if (*rb & (0x80 >> (b % 8))) { + unsigned char *rrb; + + rrb = newbits + newstride - 1 - (r / 8) + + (n * newstride * font->fontwidth) + + (newstride * b); + *rrb |= (1 << (r % 8)); + } + } + } + } + + newfont->data = newbits; + + /* Update font sizes. */ + newfont->stride = newstride; + newfont->fontwidth = font->fontheight; + newfont->fontheight = font->fontwidth; + + if (wsfont_add(newfont, 0) != 0) { + /* + * If we seem to have rotated this font already, drop the + * new one... + */ + free(newbits, M_DEVBUF); + free(newfont, M_DEVBUF); + newfont = NULL; + } + + return (newfont); +} + +int +wsfont_rotate(int cookie) +{ + int s, ncookie; + struct wsdisplay_font *font; + struct font *origfont; + + s = splhigh(); + origfont = wsfont_find0(cookie, 0xffffffff); + splx(s); + + font = wsfont_rotate_internal(origfont->font); + if (font == NULL) + return (-1); + + ncookie = wsfont_find(font->name, font->fontwidth, font->fontheight, + font->stride, 0, 0); + + return (ncookie); +} + +#endif /* NRASOPS_ROTATION */ + void wsfont_init(void) { Index: dev/wsfont/wsfont.h =================================================================== RCS file: /cvsroot/src/sys/dev/wsfont/wsfont.h,v retrieving revision 1.17 diff -u -r1.17 wsfont.h --- dev/wsfont/wsfont.h 9 Feb 2003 10:29:38 -0000 1.17 +++ dev/wsfont/wsfont.h 18 Dec 2006 09:43:22 -0000 @@ -69,5 +69,6 @@ int wsfont_lock(int, struct wsdisplay_font **); int wsfont_unlock(int); int wsfont_map_unichar(struct wsdisplay_font *, int); +int wsfont_rotate(int); #endif /* !_WSFONT_H_ */ Index: dev/rasops/files.rasops =================================================================== RCS file: /cvsroot/src/sys/dev/rasops/files.rasops,v retrieving revision 1.11 diff -u -r1.11 files.rasops --- dev/rasops/files.rasops 11 Dec 2005 12:23:43 -0000 1.11 +++ dev/rasops/files.rasops 18 Dec 2006 09:43:22 -0000 @@ -4,7 +4,7 @@ # hence it must be mentioned first (shudder...) file dev/rasops/rasops.c ( (rasops_glue | rasops1 | rasops2 | rasops4 | rasops8 | rasops15 | rasops16 | rasops24 | - rasops32) & + rasops32 | rasops_rotation) & (rasterconsole | wsdisplay)) needs-flag file dev/rasops/rasops_masks.c ((rasterconsole | wsdisplay) & Index: dev/rasops/rasops.c =================================================================== RCS file: /cvsroot/src/sys/dev/rasops/rasops.c,v retrieving revision 1.54 diff -u -r1.54 rasops.c --- dev/rasops/rasops.c 16 Nov 2006 01:33:26 -0000 1.54 +++ dev/rasops/rasops.c 18 Dec 2006 09:43:23 -0000 @@ -135,6 +135,26 @@ static void rasops_do_cursor(struct rasops_info *); static void rasops_init_devcmap(struct rasops_info *); +#if NRASOPS_ROTATION > 0 +static void rasops_copychar(void *, int, int, int, int); +static void rasops_copycols_rotated(void *, int, int, int, int); +static void rasops_copyrows_rotated(void *, int, int, int); +static void rasops_erasecols_rotated(void *, int, int, int, long); +static void rasops_eraserows_rotated(void *, int, int, long); +static void rasops_putchar_rotated(void *, int, int, u_int, long); +static void rasops_rotate_font(int *); + +/* + * List of all rotated fonts + */ +SLIST_HEAD(, rotatedfont) rotatedfonts = SLIST_HEAD_INITIALIZER(rotatedfonts); +struct rotatedfont { + SLIST_ENTRY(rotatedfont) rf_next; + int rf_cookie; + int rf_rotated; +}; +#endif /* NRASOPS_ROTATION > 0 */ + /* * Initialize a 'rasops_info' descriptor. */ @@ -163,6 +183,15 @@ return (-1); } +#if NRASOPS_ROTATION > 0 + /* + * Pick the rotated version of this font. This will create it + * if necessary. + */ + if (ri->ri_flg & RI_ROTATE_CW) + rasops_rotate_font(&cookie); +#endif + if (wsfont_lock(cookie, &ri->ri_font)) { printf("rasops_init: couldn't lock font\n"); return (-1); @@ -234,8 +263,17 @@ while ((ri->ri_emuwidth * bpp & 31) != 0) ri->ri_emuwidth--; - ri->ri_cols = ri->ri_emuwidth / ri->ri_font->fontwidth; - ri->ri_rows = ri->ri_emuheight / ri->ri_font->fontheight; +#if NRASOPS_ROTATION > 0 + if (ri->ri_flg & RI_ROTATE_CW) { + ri->ri_rows = ri->ri_emuwidth / ri->ri_font->fontwidth; + ri->ri_cols = ri->ri_emuheight / ri->ri_font->fontheight; + } else +#endif + { + + ri->ri_cols = ri->ri_emuwidth / ri->ri_font->fontwidth; + ri->ri_rows = ri->ri_emuheight / ri->ri_font->fontheight; + } ri->ri_emustride = ri->ri_emuwidth * bpp >> 3; ri->ri_delta = ri->ri_stride - ri->ri_emustride; ri->ri_ccol = 0; @@ -334,6 +372,17 @@ return (-1); } +#if NRASOPS_ROTATION > 0 + if (ri->ri_flg & RI_ROTATE_CW) { + ri->ri_real_ops = ri->ri_ops; + ri->ri_ops.copycols = rasops_copycols_rotated; + ri->ri_ops.copyrows = rasops_copyrows_rotated; + ri->ri_ops.erasecols = rasops_erasecols_rotated; + ri->ri_ops.eraserows = rasops_eraserows_rotated; + ri->ri_ops.putchar = rasops_putchar_rotated; + } +#endif + ri->ri_flg |= RI_CFGDONE; splx(s); return (0); @@ -853,8 +902,17 @@ hrp = hp = NULL; - row = ri->ri_crow; - col = ri->ri_ccol; +#if NRASOPS_ROTATION > 0 + if (ri->ri_flg & RI_ROTATE_CW) { + /* Rotate rows/columns */ + row = ri->ri_ccol; + col = ri->ri_rows - ri->ri_crow - 1; + } else +#endif + { + row = ri->ri_crow; + col = ri->ri_ccol; + } rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale; if (ri->ri_hwbits) @@ -1114,3 +1172,175 @@ } } } + +#if NRASOPS_ROTATION > 0 +/* + * Quarter clockwise rotation routines (originally intended for the + * built-in Zaurus C3x00 display in 16bpp). + */ + +#include + +static void +rasops_rotate_font(int *cookie) +{ + struct rotatedfont *f; + int ncookie; + + SLIST_FOREACH(f, &rotatedfonts, rf_next) { + if (f->rf_cookie == *cookie) { + *cookie = f->rf_rotated; + return; + } + } + + /* + * We did not find a rotated version of this font. Ask the wsfont + * code to compute one for us. + */ + + f = malloc(sizeof(struct rotatedfont), M_DEVBUF, M_WAITOK); + if (f == NULL) + return; + + if ((ncookie = wsfont_rotate(*cookie)) == -1) + return; + + f->rf_cookie = *cookie; + f->rf_rotated = ncookie; + SLIST_INSERT_HEAD(&rotatedfonts, f, rf_next); + + *cookie = ncookie; +} + +static void +rasops_copychar(cookie, srcrow, dstrow, srccol, dstcol) + void *cookie; + int srcrow, dstrow, srccol, dstcol; +{ + struct rasops_info *ri; + u_char *sp, *dp; + int height; + int r_srcrow, r_dstrow, r_srccol, r_dstcol; + + ri = (struct rasops_info *)cookie; + + r_srcrow = srccol; + r_dstrow = dstcol; + r_srccol = ri->ri_rows - srcrow - 1; + r_dstcol = ri->ri_rows - dstrow - 1; + + r_srcrow *= ri->ri_yscale; + r_dstrow *= ri->ri_yscale; + height = ri->ri_font->fontheight; + + sp = ri->ri_bits + r_srcrow + r_srccol * ri->ri_xscale; + dp = ri->ri_bits + r_dstrow + r_dstcol * ri->ri_xscale; + + while (height--) { + memmove(dp, sp, ri->ri_xscale); + dp += ri->ri_stride; + sp += ri->ri_stride; + } +} + +static void +rasops_putchar_rotated(cookie, row, col, uc, attr) + void *cookie; + int row, col; + u_int uc; + long attr; +{ + struct rasops_info *ri; + u_char *rp; + int height; + + ri = (struct rasops_info *)cookie; + + /* Do rotated char sans (side)underline */ + ri->ri_real_ops.putchar(cookie, col, ri->ri_rows - row - 1, uc, + attr & ~1); + + /* Do rotated underline */ + rp = ri->ri_bits + col * ri->ri_yscale + (ri->ri_rows - row - 1) * + ri->ri_xscale; + height = ri->ri_font->fontheight; + + /* XXX this assumes 16-bit color depth */ + if ((attr & 1) != 0) { + int16_t c = (int16_t)ri->ri_devcmap[((u_int)attr >> 24) & 0xf]; + + while (height--) { + *(int16_t *)rp = c; + rp += ri->ri_stride; + } + } +} + +static void +rasops_erasecols_rotated(cookie, row, col, num, attr) + void *cookie; + int row, col, num; + long attr; +{ + struct rasops_info *ri; + int i; + + ri = (struct rasops_info *)cookie; + + for (i = col; i < col + num; i++) + ri->ri_ops.putchar(cookie, row, i, ' ', attr); +} + +/* XXX: these could likely be optimised somewhat. */ +static void +rasops_copyrows_rotated(cookie, src, dst, num) + void *cookie; + int src, dst, num; +{ + struct rasops_info *ri = (struct rasops_info *)cookie; + int col, roff; + + if (src > dst) + for (roff = 0; roff < num; roff++) + for (col = 0; col < ri->ri_cols; col++) + rasops_copychar(cookie, src + roff, dst + roff, + col, col); + else + for (roff = num - 1; roff >= 0; roff--) + for (col = 0; col < ri->ri_cols; col++) + rasops_copychar(cookie, src + roff, dst + roff, + col, col); +} + +static void +rasops_copycols_rotated(cookie, row, src, dst, num) + void *cookie; + int row, src, dst, num; +{ + int coff; + + if (src > dst) + for (coff = 0; coff < num; coff++) + rasops_copychar(cookie, row, row, src + coff, dst + coff); + else + for (coff = num - 1; coff >= 0; coff--) + rasops_copychar(cookie, row, row, src + coff, dst + coff); +} + +static void +rasops_eraserows_rotated(cookie, row, num, attr) + void *cookie; + int row, num; + long attr; +{ + struct rasops_info *ri; + int col, rn; + + ri = (struct rasops_info *)cookie; + + for (rn = row; rn < row + num; rn++) + for (col = 0; col < ri->ri_cols; col++) + ri->ri_ops.putchar(cookie, rn, col, ' ', attr); +} +#endif /* NRASOPS_ROTATION */ Index: dev/rasops/rasops.h =================================================================== RCS file: /cvsroot/src/sys/dev/rasops/rasops.h,v retrieving revision 1.19 diff -u -r1.19 rasops.h --- dev/rasops/rasops.h 18 Feb 2006 13:57:33 -0000 1.19 +++ dev/rasops/rasops.h 18 Dec 2006 09:43:23 -0000 @@ -50,6 +50,7 @@ #define RI_CENTER 0x20 /* center onscreen output */ #define RI_CURSORCLIP 0x40 /* cursor is currently clipped */ #define RI_CFGDONE 0x80 /* rasops_reconfig() completed successfully */ +#define RI_ROTATE_CW 0x100 /* display is rotated, quarter clockwise */ struct rasops_info { /* These must be filled in by the caller */ @@ -110,6 +111,11 @@ /* Callbacks so we can share some code */ void (*ri_do_cursor)(struct rasops_info *); + +#if NRASOPS_ROTATION > 0 + /* Used to intercept putchar to permit display rotation */ + struct wsdisplay_emulops ri_real_ops; +#endif }; #define DELTA(p, d, cast) ((p) = (cast)((caddr_t)(p) + (d)))