#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<blue = (Colorfmt){(1<green = (Colorfmt){(1<>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); }