summaryrefslogtreecommitdiff
path: root/sys/src/cmd/vnc/color.c
diff options
context:
space:
mode:
authorTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
committerTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
commite5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch)
treed8d51eac403f07814b9e936eed0c9a79195e2450 /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-xsys/src/cmd/vnc/color.c169
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);
+}