color.c 3.0 KB

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