/* vi: set sw=4 ts=4: */ /* * CCE - Console Chinese Environment - * Copyright (C) 1998-2003 Rui He (rhe@3eti.com) * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE TERRENCE R. LAMBERT BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ /* This code is based on linux kernel' frame buffer code. I try to make it OS-independent, so it will also work on other OS's frame buffer memory Max font size 32x32 */ #include #include #include #include #include #include #include #include #include #if defined(SUPPORT_FRAMEBUF) static u_short nibbletab_cfb4[] = { #if defined(CCE_TARGETARCH_BIGENDIAN) 0x0000,0x000f,0x0f00,0x00ff, 0x0f00,0x0f0f,0x0ff0,0x0fff, 0xf000,0xf00f,0xf0f0,0xf0ff, 0xff00,0xff0f,0xfff0,0xffff #else 0x0000,0xf000,0x0f00,0xff00, 0x00f0,0xf0f0,0x0ff0,0xfff0, 0x000f,0xf00f,0x0f0f,0xff0f, 0x00ff,0xf0ff,0x0fff,0xffff #endif }; static void fbcon_cfb4_clear(int sy, int height, u_char bc) { u_char *dest, *p, bgx; int i; dest = gramMem + sy * dispInfo.glineByte; bgx = bc & 0x0F; bgx |= bgx << 4; while( height-- > 0) { p = dest; for(i = 0; i < dispInfo.gxdim/2; i++) { *p++ = bgx; } dest += dispInfo.glineByte; } } static void fbcon_cfb4_putc(u_char *cdat, u_char fc, u_char bc, int width, int height) { u_char *dest, bits; int rows; u_int eorx,fgx,bgx; dest = gramMem + writeAddr; fgx = fc; bgx = bc; fgx |= (fgx << 4); fgx |= (fgx << 8); bgx |= (bgx << 4); bgx |= (bgx << 8); eorx = fgx ^ bgx; for (rows = height ; rows-- ; dest += dispInfo.glineByte) { bits = *cdat++; ((u_short *)dest)[0]= (nibbletab_cfb4[bits >> 4] & eorx) ^ bgx; if (width < 8) continue; /* width = 4 */ ((u_short *)dest)[1] = (nibbletab_cfb4[bits & 0xf] & eorx) ^ bgx; if (width < 12) continue; /* width = 8 */ bits = *cdat++; ((u_short *)dest)[2]= (nibbletab_cfb4[bits >> 4] & eorx) ^ bgx; if (width < 16) continue; /* width = 12 */ ((u_short *)dest)[3] = (nibbletab_cfb4[bits & 0xf] & eorx) ^ bgx; if (width < 20) continue; /* width = 16 */ bits = *cdat++; ((u_short *)dest)[4]= (nibbletab_cfb4[bits >> 4] & eorx) ^ bgx; if (width < 24) continue; /* width = 20 */ ((u_short *)dest)[5] = (nibbletab_cfb4[bits & 0xf] & eorx) ^ bgx; if (width < 28) continue; /* width = 24 */ bits = *cdat++; ((u_short *)dest)[6]= (nibbletab_cfb4[bits >> 4] & eorx) ^ bgx; if (width < 32) continue; /* width = 28 */ ((u_short *)dest)[7] = (nibbletab_cfb4[bits & 0xf] & eorx) ^ bgx; } } static u_int nibbletab_cfb8[] = { #if defined(CCE_TARGETARCH_BIGENDIAN) 0x00000000,0x000000ff,0x0000ff00,0x0000ffff, 0x00ff0000,0x00ff00ff,0x00ffff00,0x00ffffff, 0xff000000,0xff0000ff,0xff00ff00,0xff00ffff, 0xffff0000,0xffff00ff,0xffffff00,0xffffffff #else 0x00000000,0xff000000,0x00ff0000,0xffff0000, 0x0000ff00,0xff00ff00,0x00ffff00,0xffffff00, 0x000000ff,0xff0000ff,0x00ff00ff,0xffff00ff, 0x0000ffff,0xff00ffff,0x00ffffff,0xffffffff #endif }; static void fbcon_cfb8_clear(int sy, int height, u_char bc) { u_char *dest,*p; int i; dest = gramMem + sy * dispInfo.glineByte; while( height-- > 0) { p = dest; for(i = 0; i < dispInfo.gxdim; i++) { *p++ = bc; } dest += dispInfo.glineByte; } } static void fbcon_cfb8_putc(u_char *cdat, u_char fc, u_char bc, int width, int height) { u_char *dest, bits; int rows; u_int eorx,fgx,bgx; dest = gramMem + writeAddr; fgx = fc; bgx = bc; fgx |= (fgx << 8); fgx |= (fgx << 16); bgx |= (bgx << 8); bgx |= (bgx << 16); eorx = fgx ^ bgx; for (rows = height ; rows-- ; dest += dispInfo.glineByte) { bits = *cdat++; ((u_int *)dest)[0]= (nibbletab_cfb8[bits >> 4] & eorx) ^ bgx; if (width < 8) continue; /* width = 4 */ ((u_int *)dest)[1]= (nibbletab_cfb8[bits & 0xf] & eorx) ^ bgx; if (width < 12) continue; /* width = 8 */ bits = *cdat++; ((u_int *)dest)[2]= (nibbletab_cfb8[bits >> 4] & eorx) ^ bgx; if (width < 16) continue; /* width = 12 */ ((u_int *)dest)[3]= (nibbletab_cfb8[bits & 0xf] & eorx) ^ bgx; if (width < 20) continue; /* width = 16 */ bits = *cdat++; ((u_int *)dest)[4]= (nibbletab_cfb8[bits >> 4] & eorx) ^ bgx; if (width < 24) continue; /* width = 20 */ ((u_int *)dest)[5]= (nibbletab_cfb8[bits & 0xf] & eorx) ^ bgx; if (width < 28) continue; /* width = 24 */ bits = *cdat++; ((u_int *)dest)[6]= (nibbletab_cfb8[bits >> 4] & eorx) ^ bgx; if (width < 32) continue; /* width = 28 */ ((u_int *)dest)[7]= (nibbletab_cfb8[bits & 0xf] & eorx) ^ bgx; } } static u_int nibbletab_cfb16[] = { #if defined(CCE_TARGETARCH_BIGENDIAN) 0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff #else 0x00000000, 0xffff0000, 0x0000ffff, 0xffffffff #endif }; static void fbcon_cfb16_clear(int sy, int height, u_char bc) { u_char *dest; u_short *p; int i; #ifdef DEBUG fprintf(stderr, "\rgramMem=%p, sy=%d, lineByte=%d\r\n", gramMem, sy, dispInfo.glineByte); #endif dest = gramMem + sy * dispInfo.glineByte; while( height-- > 0) { p = (u_short*)dest; #ifdef DEBUG #endif for(i = 0; i < dispInfo.gxdim; i++) { *p++ = fb_cmap.cfb16[bc]; } dest += dispInfo.glineByte; } #ifdef DEBUG #endif } static void fbcon_cfb16_putc(u_char *cdat, u_char fc, u_char bc,int width, int height) { u_char *dest, bits; int rows; u_int eorx, fgx, bgx; dest = gramMem + writeAddr; fgx = fb_cmap.cfb16[fc]; bgx = fb_cmap.cfb16[bc]; fgx |= (fgx << 16); bgx |= (bgx << 16); eorx = fgx ^ bgx; for (rows = height; rows--; dest += dispInfo.glineByte) { bits = *cdat++; ((u_int *)dest)[0] = (nibbletab_cfb16[bits >> 6] & eorx) ^ bgx; ((u_int *)dest)[1] = (nibbletab_cfb16[bits >> 4 & 3] & eorx) ^ bgx; if (width < 8) continue; /* width = 4 */ ((u_int *)dest)[2] = (nibbletab_cfb16[bits >> 2 & 3] & eorx) ^ bgx; ((u_int *)dest)[3] = (nibbletab_cfb16[bits & 3] & eorx) ^ bgx; if (width < 12) continue; /* width = 8 */ bits = *cdat++; ((u_int *)dest)[4] = (nibbletab_cfb16[bits >> 6] & eorx) ^ bgx; ((u_int *)dest)[5] = (nibbletab_cfb16[bits >> 4 & 3] & eorx) ^ bgx; if (width < 16) continue; /* width = 12 */ ((u_int *)dest)[6] = (nibbletab_cfb16[bits >> 2 & 3] & eorx) ^ bgx; ((u_int *)dest)[7] = (nibbletab_cfb16[bits & 3] & eorx) ^ bgx; if (width < 20) continue; /* width = 16 */ bits = *cdat++; ((u_int *)dest)[8] = (nibbletab_cfb16[bits >> 6] & eorx) ^ bgx; ((u_int *)dest)[9] = (nibbletab_cfb16[bits >> 4 & 3] & eorx) ^ bgx; if (width < 24) continue; /* width = 20 */ ((u_int *)dest)[10] = (nibbletab_cfb16[bits >> 2 & 3] & eorx) ^ bgx; ((u_int *)dest)[11] = (nibbletab_cfb16[bits & 3] & eorx) ^ bgx; if (width < 28) continue; /* width = 24 */ bits = *cdat++; ((u_int *)dest)[12] = (nibbletab_cfb16[bits >> 6] & eorx) ^ bgx; ((u_int *)dest)[13] = (nibbletab_cfb16[bits >> 4 & 3] & eorx) ^ bgx; if (width < 32) continue; /* width = 28 */ ((u_int *)dest)[14] = (nibbletab_cfb16[bits >> 2 & 3] & eorx) ^ bgx; ((u_int *)dest)[15] = (nibbletab_cfb16[bits & 3] & eorx) ^ bgx; } } static inline void store4pixels(u_int d1, u_int d2, u_int d3, u_int d4, u_int *dest) { #if defined(CCE_TARGETARCH_BIGENDIAN) *dest++ = (d1 << 8) | (d2 >> 16); *dest++ = (d2 << 16) | (d3 >> 8); *dest++ = (d3 << 24) | d4; #else *dest++ = d1 | (d2 << 24); *dest++ = (d2 >> 8) | (d3 << 16); *dest++ = (d3 >> 16) | (d4 << 8); #endif } static void fbcon_cfb24_clear(int sy, int height, u_char bc) { u_char *dest,*p, red, green, blue; int i; dest = gramMem + sy * dispInfo.glineByte; red = red16[bc] >> 8; green = green16[bc] >> 8; blue = blue16[bc] >> 8; while( height-- > 0) { p = dest; for(i = 0; i < dispInfo.gxdim; i++) { *p++ = blue; *p++ = green; *p++ = red; } dest += dispInfo.glineByte; } } static void fbcon_cfb24_putc(u_char *cdat, u_char fc, u_char bc, int width, int height) { u_char *dest, bits; int rows; u_int eorx, fgx, bgx, d1, d2, d3, d4; if (cdat == NULL) return; dest = gramMem + writeAddr; fgx = fb_cmap.cfb24[fc]; bgx = fb_cmap.cfb24[bc]; eorx = fgx ^ bgx; for (rows = height; rows--; dest += dispInfo.glineByte) { bits = *cdat++; d1 = (-(bits >> 7) & eorx) ^ bgx; d2 = (-(bits >> 6 & 1) & eorx) ^ bgx; d3 = (-(bits >> 5 & 1) & eorx) ^ bgx; d4 = (-(bits >> 4 & 1) & eorx) ^ bgx; store4pixels(d1, d2, d3, d4, (u_int *)dest); if (width < 8) continue; /* width = 4 */ d1 = (-(bits >> 3 & 1) & eorx) ^ bgx; d2 = (-(bits >> 2 & 1) & eorx) ^ bgx; d3 = (-(bits >> 1 & 1) & eorx) ^ bgx; d4 = (-(bits & 1) & eorx) ^ bgx; store4pixels(d1, d2, d3, d4, (u_int *)(dest+12)); if (width < 12) continue; /* width = 8 */ bits = *cdat++; d1 = (-(bits >> 7) & eorx) ^ bgx; d2 = (-(bits >> 6 & 1) & eorx) ^ bgx; d3 = (-(bits >> 5 & 1) & eorx) ^ bgx; d4 = (-(bits >> 4 & 1) & eorx) ^ bgx; store4pixels(d1, d2, d3, d4, (u_int *)(dest+24)); if (width < 16) continue; /* width = 12 */ d1 = (-(bits >> 3 & 1) & eorx) ^ bgx; d2 = (-(bits >> 2 & 1) & eorx) ^ bgx; d3 = (-(bits >> 1 & 1) & eorx) ^ bgx; d4 = (-(bits & 1) & eorx) ^ bgx; store4pixels(d1, d2, d3, d4, (u_int *)(dest+36)); if (width < 20) continue; /* width = 16 */ bits = *cdat++; d1 = (-(bits >> 7) & eorx) ^ bgx; d2 = (-(bits >> 6 & 1) & eorx) ^ bgx; d3 = (-(bits >> 5 & 1) & eorx) ^ bgx; d4 = (-(bits >> 4 & 1) & eorx) ^ bgx; store4pixels(d1, d2, d3, d4, (u_int *)(dest+48)); if (width < 24) continue; /* width = 20 */ d1 = (-(bits >> 3 & 1) & eorx) ^ bgx; d2 = (-(bits >> 2 & 1) & eorx) ^ bgx; d3 = (-(bits >> 1 & 1) & eorx) ^ bgx; d4 = (-(bits & 1) & eorx) ^ bgx; store4pixels(d1, d2, d3, d4, (u_int *)(dest+60)); if (width < 28) continue; /* width = 24 */ bits = *cdat++; d1 = (-(bits >> 7) & eorx) ^ bgx; d2 = (-(bits >> 6 & 1) & eorx) ^ bgx; d3 = (-(bits >> 5 & 1) & eorx) ^ bgx; d4 = (-(bits >> 4 & 1) & eorx) ^ bgx; store4pixels(d1, d2, d3, d4, (u_int *)(dest+72)); if (width < 32) continue; /* width = 28 */ d1 = (-(bits >> 3 & 1) & eorx) ^ bgx; d2 = (-(bits >> 2 & 1) & eorx) ^ bgx; d3 = (-(bits >> 1 & 1) & eorx) ^ bgx; d4 = (-(bits & 1) & eorx) ^ bgx; store4pixels(d1, d2, d3, d4, (u_int *)(dest+84)); } } #define fb_writel(b,addr) (*(volatile unsigned int *) (addr) = (b)) static void fbcon_cfb32_clear(int sy, int height, u_char bc) { u_char *dest; u_int *p; int i; dest = gramMem + sy * dispInfo.glineByte; while( height-- > 0) { p = (u_int *)dest; for(i = 0; i < dispInfo.gxdim; i++) { *p++ = fb_cmap.cfb32[bc]; } dest += dispInfo.glineByte; } } static void fbcon_cfb32_putc(u_char *cdat, u_char fc, u_char bc, int width, int height) { u_char *dest, bits; int rows; u_int eorx, fgx, bgx, *pt; if (cdat == NULL) return; dest = gramMem + writeAddr; fgx = fb_cmap.cfb32[fc]; bgx = fb_cmap.cfb32[bc]; eorx = fgx ^ bgx; for (rows = height; rows--; dest += dispInfo.glineByte) { bits = *cdat++; pt = (unsigned int *) dest; fb_writel((-(bits >> 7) & eorx) ^ bgx, pt++); fb_writel((-(bits >> 6 & 1) & eorx) ^ bgx, pt++); fb_writel((-(bits >> 5 & 1) & eorx) ^ bgx, pt++); fb_writel((-(bits >> 4 & 1) & eorx) ^ bgx, pt++); if (width < 8) continue; /* width = 4 */ fb_writel((-(bits >> 3 & 1) & eorx) ^ bgx, pt++); fb_writel((-(bits >> 2 & 1) & eorx) ^ bgx, pt++); fb_writel((-(bits >> 1 & 1) & eorx) ^ bgx, pt++); fb_writel((-(bits & 1) & eorx) ^ bgx, pt++); if (width < 12) continue; /* width = 8 */ bits = *cdat++; fb_writel((-(bits >> 7) & eorx) ^ bgx, pt++); fb_writel((-(bits >> 6 & 1) & eorx) ^ bgx, pt++); fb_writel((-(bits >> 5 & 1) & eorx) ^ bgx, pt++); fb_writel((-(bits >> 4 & 1) & eorx) ^ bgx, pt++); if (width < 16) continue; /* width = 12 */ fb_writel((-(bits >> 3 & 1) & eorx) ^ bgx, pt++); fb_writel((-(bits >> 2 & 1) & eorx) ^ bgx, pt++); fb_writel((-(bits >> 1 & 1) & eorx) ^ bgx, pt++); fb_writel((-(bits & 1) & eorx) ^ bgx, pt++); if (width < 20) continue; /* width = 16 */ bits = *cdat++; fb_writel((-(bits >> 7) & eorx) ^ bgx, pt++); fb_writel((-(bits >> 6 & 1) & eorx) ^ bgx, pt++); fb_writel((-(bits >> 5 & 1) & eorx) ^ bgx, pt++); fb_writel((-(bits >> 4 & 1) & eorx) ^ bgx, pt++); if (width < 24) continue; /* width = 20 */ fb_writel((-(bits >> 3 & 1) & eorx) ^ bgx, pt++); fb_writel((-(bits >> 2 & 1) & eorx) ^ bgx, pt++); fb_writel((-(bits >> 1 & 1) & eorx) ^ bgx, pt++); fb_writel((-(bits & 1) & eorx) ^ bgx, pt++); if (width < 28) continue; /* width = 24 */ bits = *cdat++; fb_writel((-(bits >> 7) & eorx) ^ bgx, pt++); fb_writel((-(bits >> 6 & 1) & eorx) ^ bgx, pt++); fb_writel((-(bits >> 5 & 1) & eorx) ^ bgx, pt++); fb_writel((-(bits >> 4 & 1) & eorx) ^ bgx, pt++); if (width < 32) continue; /* width = 28 */ fb_writel((-(bits >> 3 & 1) & eorx) ^ bgx, pt++); fb_writel((-(bits >> 2 & 1) & eorx) ^ bgx, pt++); fb_writel((-(bits >> 1 & 1) & eorx) ^ bgx, pt++); fb_writel((-(bits & 1) & eorx) ^ bgx, pt++); } } void FBOpCursor(CursorInfo *ci, int xpos, int ypos) { char *gram; u_char x; int i; int bottom = ( cursorBtm + 1 <= dispInfo.glineChar ? cursorBtm + 1 : dispInfo.glineChar ); gram = gramMem + ypos * dispInfo.glineByte + xpos * dispInfo.bpp/8; x = cursorTop; if (kanjiCursor && ci->kanji) { for (;x < bottom;x ++, gram += dispInfo.glineByte) { for( i = 0; i < fontwidth * dispInfo.bpp * 2 / 8; i++) if (dispInfo.bpp <= 8) /* palette-based */ gram[i] ^= 0x07; /* should we use 0x07 or 0x77 or 0xFF ? */ else gram[i] ^= 0xFF; } } else { for (;x < bottom;x ++, gram += dispInfo.glineByte) { for( i = 0; i < fontwidth * dispInfo.bpp / 8; i++) if (dispInfo.bpp <= 8) gram[i] ^= 0x07; else gram[i] ^= 0xFF; } } } void FBOpClear(int y, int height, int color) { switch(dispInfo.bpp) { case 4: fbcon_cfb4_clear(y, height, color); break; case 8: #ifdef __Darwin__ color = DarwinColorMap8[color & DARWIN_COLOR_MASK]; #endif fbcon_cfb8_clear(y, height, color); break; case 16: fbcon_cfb16_clear(y, height, color); break; case 24: fbcon_cfb24_clear(y, height, color); break; case 32: fbcon_cfb32_clear(y, height, color); break; } } void FBOpDraw(u_char *code, u_char fc, u_char bc, int width, int height) { switch(dispInfo.bpp) { case 4: fbcon_cfb4_putc(code, fc, bc, width, height); break; case 8: #ifdef __Darwin__ fc = DarwinColorMap8[fc & DARWIN_COLOR_MASK]; bc = DarwinColorMap8[bc & DARWIN_COLOR_MASK]; #endif fbcon_cfb8_putc(code, fc, bc, width, height); break; case 16: fbcon_cfb16_putc(code, fc, bc, width, height); break; case 24: fbcon_cfb24_putc(code, fc, bc, width, height); break; case 32: fbcon_cfb32_putc(code, fc, bc, width, height); break; } } #endif