ref: 19b480838af1721b833f6cd7575e994a5d55071d
dir: /sys/src/cmd/vnc/color.c/
#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++]; } static void cvt16to32(uchar *dst, uchar *src, int npixel) { uchar *ed; int w, r, g, b; ed = dst+npixel*4; while(dst < ed){ w = src[1]<<8 | src[0]; b = (w >> 11) & 0x1F; g = (w >> 5) & 0x3F; r = (w >> 0) & 0x1F; dst[0] = b<<(8-5); dst[1] = g<<(8-6); dst[2] = r<<(8-5); dst += 4; src += 2; } } void choosecolor(Vnc *v) { int bpp, depth; ulong chan; chan = screen->chan; depth = screen->depth; bpp = depth; if((bpp / 8) * 8 != bpp) sysfatal("screen not supported"); if(bpp == 32 && v->Pixfmt.bpp == 16){ cvtpixels = cvt16to32; goto Done; } 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"); Done: 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); }