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