1*9a747e4fSDavid du Colombier #include "vnc.h"
2*9a747e4fSDavid du Colombier #include "vncv.h"
3*9a747e4fSDavid du Colombier
4*9a747e4fSDavid du Colombier enum {
5*9a747e4fSDavid du Colombier RGB12 = CHAN4(CIgnore, 4, CRed, 4, CGreen, 4, CBlue, 4),
6*9a747e4fSDavid du Colombier BGR12 = CHAN4(CIgnore, 4, CBlue, 4, CGreen, 4, CRed, 4),
7*9a747e4fSDavid du Colombier BGR8 = CHAN3(CBlue, 2, CGreen, 3, CRed, 3),
8*9a747e4fSDavid du Colombier };
9*9a747e4fSDavid du Colombier
10*9a747e4fSDavid du Colombier void (*cvtpixels)(uchar*, uchar*, int);
11*9a747e4fSDavid du Colombier
12*9a747e4fSDavid du Colombier static void
chan2fmt(Pixfmt * fmt,ulong chan)13*9a747e4fSDavid du Colombier chan2fmt(Pixfmt *fmt, ulong chan)
14*9a747e4fSDavid du Colombier {
15*9a747e4fSDavid du Colombier ulong c, rc, shift;
16*9a747e4fSDavid du Colombier
17*9a747e4fSDavid du Colombier shift = 0;
18*9a747e4fSDavid du Colombier for(rc = chan; rc; rc >>=8){
19*9a747e4fSDavid du Colombier c = rc & 0xFF;
20*9a747e4fSDavid du Colombier switch(TYPE(c)){
21*9a747e4fSDavid du Colombier case CRed:
22*9a747e4fSDavid du Colombier fmt->red = (Colorfmt){(1<<NBITS(c))-1, shift};
23*9a747e4fSDavid du Colombier break;
24*9a747e4fSDavid du Colombier case CBlue:
25*9a747e4fSDavid du Colombier fmt->blue = (Colorfmt){(1<<NBITS(c))-1, shift};
26*9a747e4fSDavid du Colombier break;
27*9a747e4fSDavid du Colombier case CGreen:
28*9a747e4fSDavid du Colombier fmt->green = (Colorfmt){(1<<NBITS(c))-1, shift};
29*9a747e4fSDavid du Colombier break;
30*9a747e4fSDavid du Colombier }
31*9a747e4fSDavid du Colombier shift += NBITS(c);
32*9a747e4fSDavid du Colombier }
33*9a747e4fSDavid du Colombier }
34*9a747e4fSDavid du Colombier
35*9a747e4fSDavid du Colombier /*
36*9a747e4fSDavid du Colombier * convert 32-bit data to 24-bit data by skipping
37*9a747e4fSDavid du Colombier * the last of every four bytes. we skip the last
38*9a747e4fSDavid du Colombier * because we keep the server in little endian mode.
39*9a747e4fSDavid du Colombier */
40*9a747e4fSDavid du Colombier static void
cvt32to24(uchar * dst,uchar * src,int npixel)41*9a747e4fSDavid du Colombier cvt32to24(uchar *dst, uchar *src, int npixel)
42*9a747e4fSDavid du Colombier {
43*9a747e4fSDavid du Colombier int i;
44*9a747e4fSDavid du Colombier
45*9a747e4fSDavid du Colombier for(i=0; i<npixel; i++){
46*9a747e4fSDavid du Colombier *dst++ = *src++;
47*9a747e4fSDavid du Colombier *dst++ = *src++;
48*9a747e4fSDavid du Colombier *dst++ = *src++;
49*9a747e4fSDavid du Colombier src++;
50*9a747e4fSDavid du Colombier }
51*9a747e4fSDavid du Colombier }
52*9a747e4fSDavid du Colombier
53*9a747e4fSDavid du Colombier /*
54*9a747e4fSDavid du Colombier * convert RGB12 (x4r4g4b4) into CMAP8
55*9a747e4fSDavid du Colombier */
56*9a747e4fSDavid du Colombier static uchar rgb12[16*16*16];
57*9a747e4fSDavid du Colombier static void
mkrgbtab(void)58*9a747e4fSDavid du Colombier mkrgbtab(void)
59*9a747e4fSDavid du Colombier {
60*9a747e4fSDavid du Colombier int r, g, b;
61*9a747e4fSDavid du Colombier
62*9a747e4fSDavid du Colombier for(r=0; r<16; r++)
63*9a747e4fSDavid du Colombier for(g=0; g<16; g++)
64*9a747e4fSDavid du Colombier for(b=0; b<16; b++)
65*9a747e4fSDavid du Colombier rgb12[r*256+g*16+b] = rgb2cmap(r*0x11, g*0x11, b*0x11);
66*9a747e4fSDavid du Colombier }
67*9a747e4fSDavid du Colombier
68*9a747e4fSDavid du Colombier static void
cvtrgb12tocmap8(uchar * dst,uchar * src,int npixel)69*9a747e4fSDavid du Colombier cvtrgb12tocmap8(uchar *dst, uchar *src, int npixel)
70*9a747e4fSDavid du Colombier {
71*9a747e4fSDavid du Colombier int i, s;
72*9a747e4fSDavid du Colombier
73*9a747e4fSDavid du Colombier for(i=0; i<npixel; i++){
74*9a747e4fSDavid du Colombier s = (src[0] | (src[1]<<8)) & 0xFFF;
75*9a747e4fSDavid du Colombier *dst++ = rgb12[s];
76*9a747e4fSDavid du Colombier src += 2;
77*9a747e4fSDavid du Colombier }
78*9a747e4fSDavid du Colombier }
79*9a747e4fSDavid du Colombier
80*9a747e4fSDavid du Colombier /*
81*9a747e4fSDavid du Colombier * convert BGR8 (b2g3r3, default VNC format) to CMAP8
82*9a747e4fSDavid du Colombier * some bits are lost.
83*9a747e4fSDavid du Colombier */
84*9a747e4fSDavid du Colombier static uchar bgr8[256];
85*9a747e4fSDavid du Colombier static void
mkbgrtab(void)86*9a747e4fSDavid du Colombier mkbgrtab(void)
87*9a747e4fSDavid du Colombier {
88*9a747e4fSDavid du Colombier int i, r, g, b;
89*9a747e4fSDavid du Colombier
90*9a747e4fSDavid du Colombier for(i=0; i<256; i++){
91*9a747e4fSDavid du Colombier b = i>>6;
92*9a747e4fSDavid du Colombier b = (b<<6)|(b<<4)|(b<<2)|b;
93*9a747e4fSDavid du Colombier g = (i>>3) & 7;
94*9a747e4fSDavid du Colombier g = (g<<5)|(g<<2)|(g>>1);
95*9a747e4fSDavid du Colombier r = i & 7;
96*9a747e4fSDavid du Colombier r = (r<<5)|(r<<2)|(r>>1);
97*9a747e4fSDavid du Colombier bgr8[i] = rgb2cmap(r, g, b);
98*9a747e4fSDavid du Colombier }
99*9a747e4fSDavid du Colombier }
100*9a747e4fSDavid du Colombier
101*9a747e4fSDavid du Colombier static void
cvtbgr332tocmap8(uchar * dst,uchar * src,int npixel)102*9a747e4fSDavid du Colombier cvtbgr332tocmap8(uchar *dst, uchar *src, int npixel)
103*9a747e4fSDavid du Colombier {
104*9a747e4fSDavid du Colombier uchar *ed;
105*9a747e4fSDavid du Colombier
106*9a747e4fSDavid du Colombier ed = dst+npixel;
107*9a747e4fSDavid du Colombier while(dst < ed)
108*9a747e4fSDavid du Colombier *dst++ = bgr8[*src++];
109*9a747e4fSDavid du Colombier }
110*9a747e4fSDavid du Colombier
111*9a747e4fSDavid du Colombier void
choosecolor(Vnc * v)112*9a747e4fSDavid du Colombier choosecolor(Vnc *v)
113*9a747e4fSDavid du Colombier {
114*9a747e4fSDavid du Colombier int bpp, depth;
115*9a747e4fSDavid du Colombier ulong chan;
116*9a747e4fSDavid du Colombier
117*9a747e4fSDavid du Colombier bpp = screen->depth;
118*9a747e4fSDavid du Colombier if((bpp / 8) * 8 != bpp)
119*9a747e4fSDavid du Colombier sysfatal("screen not supported");
120*9a747e4fSDavid du Colombier
121*9a747e4fSDavid du Colombier depth = screen->depth;
122*9a747e4fSDavid du Colombier chan = screen->chan;
123*9a747e4fSDavid du Colombier
124*9a747e4fSDavid du Colombier if(bpp == 24){
125*9a747e4fSDavid du Colombier if(verbose)
126*9a747e4fSDavid du Colombier fprint(2, "24bit emulation using 32bpp\n");
127*9a747e4fSDavid du Colombier bpp = 32;
128*9a747e4fSDavid du Colombier cvtpixels = cvt32to24;
129*9a747e4fSDavid du Colombier }
130*9a747e4fSDavid du Colombier
131*9a747e4fSDavid du Colombier if(chan == CMAP8){
132*9a747e4fSDavid du Colombier if(bpp12){
133*9a747e4fSDavid du Colombier if(verbose)
134*9a747e4fSDavid du Colombier fprint(2, "8bit emulation using 12bpp\n");
135*9a747e4fSDavid du Colombier bpp = 16;
136*9a747e4fSDavid du Colombier depth = 12;
137*9a747e4fSDavid du Colombier chan = RGB12;
138*9a747e4fSDavid du Colombier cvtpixels = cvtrgb12tocmap8;
139*9a747e4fSDavid du Colombier mkrgbtab();
140*9a747e4fSDavid du Colombier }else{
141*9a747e4fSDavid du Colombier if(verbose)
142*9a747e4fSDavid du Colombier fprint(2, "8bit emulation using 6bpp\n"); /* 6: we throw away 1 r, g bit */
143*9a747e4fSDavid du Colombier bpp = 8;
144*9a747e4fSDavid du Colombier depth = 8;
145*9a747e4fSDavid du Colombier chan = BGR8;
146*9a747e4fSDavid du Colombier cvtpixels = cvtbgr332tocmap8;
147*9a747e4fSDavid du Colombier mkbgrtab();
148*9a747e4fSDavid du Colombier }
149*9a747e4fSDavid du Colombier }
150*9a747e4fSDavid du Colombier
151*9a747e4fSDavid du Colombier v->bpp = bpp;
152*9a747e4fSDavid du Colombier v->depth = depth;
153*9a747e4fSDavid du Colombier v->truecolor = 1;
154*9a747e4fSDavid du Colombier v->bigendian = 0;
155*9a747e4fSDavid du Colombier chan2fmt(v, chan);
156*9a747e4fSDavid du Colombier if(v->red.max == 0 || v->green.max == 0 || v->blue.max == 0)
157*9a747e4fSDavid du Colombier sysfatal("screen not supported");
158*9a747e4fSDavid du Colombier
159*9a747e4fSDavid du Colombier if(verbose)
160*9a747e4fSDavid du Colombier fprint(2, "%d bpp, %d depth, 0x%lx chan, %d truecolor, %d bigendian\n",
161*9a747e4fSDavid du Colombier v->bpp, v->depth, screen->chan, v->truecolor, v->bigendian);
162*9a747e4fSDavid du Colombier
163*9a747e4fSDavid du Colombier /* send information to server */
164*9a747e4fSDavid du Colombier vncwrchar(v, MPixFmt);
165*9a747e4fSDavid du Colombier vncwrchar(v, 0); /* padding */
166*9a747e4fSDavid du Colombier vncwrshort(v, 0);
167*9a747e4fSDavid du Colombier vncwrpixfmt(v, &v->Pixfmt);
168*9a747e4fSDavid du Colombier vncflush(v);
169*9a747e4fSDavid du Colombier }
170