diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/vnc/color.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/vnc/color.c')
-rwxr-xr-x | sys/src/cmd/vnc/color.c | 169 |
1 files changed, 169 insertions, 0 deletions
diff --git a/sys/src/cmd/vnc/color.c b/sys/src/cmd/vnc/color.c new file mode 100755 index 000000000..485ad4c65 --- /dev/null +++ b/sys/src/cmd/vnc/color.c @@ -0,0 +1,169 @@ +#include "vnc.h" +#include "vncv.h" + +enum { + RGB12 = CHAN4(CIgnore, 4, CRed, 4, CGreen, 4, CBlue, 4), + BGR12 = CHAN4(CIgnore, 4, CBlue, 4, CGreen, 4, CRed, 4), + BGR8 = CHAN3(CBlue, 2, CGreen, 3, CRed, 3), +}; + +void (*cvtpixels)(uchar*, uchar*, int); + +static void +chan2fmt(Pixfmt *fmt, ulong chan) +{ + ulong c, rc, shift; + + shift = 0; + for(rc = chan; rc; rc >>=8){ + c = rc & 0xFF; + switch(TYPE(c)){ + case CRed: + fmt->red = (Colorfmt){(1<<NBITS(c))-1, shift}; + break; + case CBlue: + fmt->blue = (Colorfmt){(1<<NBITS(c))-1, shift}; + break; + case CGreen: + fmt->green = (Colorfmt){(1<<NBITS(c))-1, shift}; + break; + } + shift += NBITS(c); + } +} + +/* + * convert 32-bit data to 24-bit data by skipping + * the last of every four bytes. we skip the last + * because we keep the server in little endian mode. + */ +static void +cvt32to24(uchar *dst, uchar *src, int npixel) +{ + int i; + + for(i=0; i<npixel; i++){ + *dst++ = *src++; + *dst++ = *src++; + *dst++ = *src++; + src++; + } +} + +/* + * convert RGB12 (x4r4g4b4) into CMAP8 + */ +static uchar rgb12[16*16*16]; +static void +mkrgbtab(void) +{ + int r, g, b; + + for(r=0; r<16; r++) + for(g=0; g<16; g++) + for(b=0; b<16; b++) + rgb12[r*256+g*16+b] = rgb2cmap(r*0x11, g*0x11, b*0x11); +} + +static void +cvtrgb12tocmap8(uchar *dst, uchar *src, int npixel) +{ + int i, s; + + for(i=0; i<npixel; i++){ + s = (src[0] | (src[1]<<8)) & 0xFFF; + *dst++ = rgb12[s]; + src += 2; + } +} + +/* + * convert BGR8 (b2g3r3, default VNC format) to CMAP8 + * some bits are lost. + */ +static uchar bgr8[256]; +static void +mkbgrtab(void) +{ + int i, r, g, b; + + for(i=0; i<256; i++){ + b = i>>6; + b = (b<<6)|(b<<4)|(b<<2)|b; + g = (i>>3) & 7; + g = (g<<5)|(g<<2)|(g>>1); + r = i & 7; + r = (r<<5)|(r<<2)|(r>>1); + bgr8[i] = rgb2cmap(r, g, b); + } +} + +static void +cvtbgr332tocmap8(uchar *dst, uchar *src, int npixel) +{ + uchar *ed; + + ed = dst+npixel; + while(dst < ed) + *dst++ = bgr8[*src++]; +} + +void +choosecolor(Vnc *v) +{ + int bpp, depth; + ulong chan; + + bpp = screen->depth; + if((bpp / 8) * 8 != bpp) + sysfatal("screen not supported"); + + depth = screen->depth; + chan = screen->chan; + + if(bpp == 24){ + if(verbose) + fprint(2, "24bit emulation using 32bpp\n"); + bpp = 32; + cvtpixels = cvt32to24; + } + + if(chan == CMAP8){ + if(bpp12){ + if(verbose) + fprint(2, "8bit emulation using 12bpp\n"); + bpp = 16; + depth = 12; + chan = RGB12; + cvtpixels = cvtrgb12tocmap8; + mkrgbtab(); + }else{ + if(verbose) + fprint(2, "8bit emulation using 6bpp\n"); /* 6: we throw away 1 r, g bit */ + bpp = 8; + depth = 8; + chan = BGR8; + cvtpixels = cvtbgr332tocmap8; + mkbgrtab(); + } + } + + v->bpp = bpp; + v->depth = depth; + v->truecolor = 1; + v->bigendian = 0; + chan2fmt(v, chan); + if(v->red.max == 0 || v->green.max == 0 || v->blue.max == 0) + sysfatal("screen not supported"); + + if(verbose) + fprint(2, "%d bpp, %d depth, 0x%lx chan, %d truecolor, %d bigendian\n", + v->bpp, v->depth, screen->chan, v->truecolor, v->bigendian); + + /* send information to server */ + vncwrchar(v, MPixFmt); + vncwrchar(v, 0); /* padding */ + vncwrshort(v, 0); + vncwrpixfmt(v, &v->Pixfmt); + vncflush(v); +} |