/apps/desktop/libvncserver/hextile.c

http://ftk.googlecode.com/ · C · 342 lines · 285 code · 19 blank · 38 comment · 54 complexity · 0253938fb7129cd57ba904d7ec571601 MD5 · raw file

  1. /*
  2. * hextile.c
  3. *
  4. * Routines to implement Hextile Encoding
  5. */
  6. /*
  7. * OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
  8. * Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge.
  9. * All Rights Reserved.
  10. *
  11. * This is free software; you can redistribute it and/or modify
  12. * it under the terms of the GNU General Public License as published by
  13. * the Free Software Foundation; either version 2 of the License, or
  14. * (at your option) any later version.
  15. *
  16. * This software is distributed in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. * GNU General Public License for more details.
  20. *
  21. * You should have received a copy of the GNU General Public License
  22. * along with this software; if not, write to the Free Software
  23. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
  24. * USA.
  25. */
  26. #include <rfb/rfb.h>
  27. static rfbBool sendHextiles8(rfbClientPtr cl, int x, int y, int w, int h);
  28. static rfbBool sendHextiles16(rfbClientPtr cl, int x, int y, int w, int h);
  29. static rfbBool sendHextiles32(rfbClientPtr cl, int x, int y, int w, int h);
  30. /*
  31. * rfbSendRectEncodingHextile - send a rectangle using hextile encoding.
  32. */
  33. rfbBool
  34. rfbSendRectEncodingHextile(rfbClientPtr cl,
  35. int x,
  36. int y,
  37. int w,
  38. int h)
  39. {
  40. rfbFramebufferUpdateRectHeader rect;
  41. if (cl->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) {
  42. if (!rfbSendUpdateBuf(cl))
  43. return FALSE;
  44. }
  45. rect.r.x = Swap16IfLE(x);
  46. rect.r.y = Swap16IfLE(y);
  47. rect.r.w = Swap16IfLE(w);
  48. rect.r.h = Swap16IfLE(h);
  49. rect.encoding = Swap32IfLE(rfbEncodingHextile);
  50. memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
  51. sz_rfbFramebufferUpdateRectHeader);
  52. cl->ublen += sz_rfbFramebufferUpdateRectHeader;
  53. rfbStatRecordEncodingSent(cl, rfbEncodingHextile,
  54. sz_rfbFramebufferUpdateRectHeader,
  55. sz_rfbFramebufferUpdateRectHeader + w * (cl->format.bitsPerPixel / 8) * h);
  56. switch (cl->format.bitsPerPixel) {
  57. case 8:
  58. return sendHextiles8(cl, x, y, w, h);
  59. case 16:
  60. return sendHextiles16(cl, x, y, w, h);
  61. case 32:
  62. return sendHextiles32(cl, x, y, w, h);
  63. }
  64. rfbLog("rfbSendRectEncodingHextile: bpp %d?\n", cl->format.bitsPerPixel);
  65. return FALSE;
  66. }
  67. #define PUT_PIXEL8(pix) (cl->updateBuf[cl->ublen++] = (pix))
  68. #define PUT_PIXEL16(pix) (cl->updateBuf[cl->ublen++] = ((char*)&(pix))[0], \
  69. cl->updateBuf[cl->ublen++] = ((char*)&(pix))[1])
  70. #define PUT_PIXEL32(pix) (cl->updateBuf[cl->ublen++] = ((char*)&(pix))[0], \
  71. cl->updateBuf[cl->ublen++] = ((char*)&(pix))[1], \
  72. cl->updateBuf[cl->ublen++] = ((char*)&(pix))[2], \
  73. cl->updateBuf[cl->ublen++] = ((char*)&(pix))[3])
  74. #define DEFINE_SEND_HEXTILES(bpp) \
  75. \
  76. \
  77. static rfbBool subrectEncode##bpp(rfbClientPtr cli, uint##bpp##_t *data, \
  78. int w, int h, uint##bpp##_t bg, uint##bpp##_t fg, rfbBool mono);\
  79. static void testColours##bpp(uint##bpp##_t *data, int size, rfbBool *mono, \
  80. rfbBool *solid, uint##bpp##_t *bg, uint##bpp##_t *fg); \
  81. \
  82. \
  83. /* \
  84. * rfbSendHextiles \
  85. */ \
  86. \
  87. static rfbBool \
  88. sendHextiles##bpp(rfbClientPtr cl, int rx, int ry, int rw, int rh) { \
  89. int x, y, w, h; \
  90. int startUblen; \
  91. char *fbptr; \
  92. uint##bpp##_t bg = 0, fg = 0, newBg, newFg; \
  93. rfbBool mono, solid; \
  94. rfbBool validBg = FALSE; \
  95. rfbBool validFg = FALSE; \
  96. uint##bpp##_t clientPixelData[16*16*(bpp/8)]; \
  97. \
  98. for (y = ry; y < ry+rh; y += 16) { \
  99. for (x = rx; x < rx+rw; x += 16) { \
  100. w = h = 16; \
  101. if (rx+rw - x < 16) \
  102. w = rx+rw - x; \
  103. if (ry+rh - y < 16) \
  104. h = ry+rh - y; \
  105. \
  106. if ((cl->ublen + 1 + (2 + 16 * 16) * (bpp/8)) > \
  107. UPDATE_BUF_SIZE) { \
  108. if (!rfbSendUpdateBuf(cl)) \
  109. return FALSE; \
  110. } \
  111. \
  112. fbptr = (cl->scaledScreen->frameBuffer + (cl->scaledScreen->paddedWidthInBytes * y) \
  113. + (x * (cl->scaledScreen->bitsPerPixel / 8))); \
  114. \
  115. (*cl->translateFn)(cl->translateLookupTable, &(cl->screen->serverFormat), \
  116. &cl->format, fbptr, (char *)clientPixelData, \
  117. cl->scaledScreen->paddedWidthInBytes, w, h); \
  118. \
  119. startUblen = cl->ublen; \
  120. cl->updateBuf[startUblen] = 0; \
  121. cl->ublen++; \
  122. rfbStatRecordEncodingSentAdd(cl, rfbEncodingHextile, 1); \
  123. \
  124. testColours##bpp(clientPixelData, w * h, \
  125. &mono, &solid, &newBg, &newFg); \
  126. \
  127. if (!validBg || (newBg != bg)) { \
  128. validBg = TRUE; \
  129. bg = newBg; \
  130. cl->updateBuf[startUblen] |= rfbHextileBackgroundSpecified; \
  131. PUT_PIXEL##bpp(bg); \
  132. } \
  133. \
  134. if (solid) { \
  135. continue; \
  136. } \
  137. \
  138. cl->updateBuf[startUblen] |= rfbHextileAnySubrects; \
  139. \
  140. if (mono) { \
  141. if (!validFg || (newFg != fg)) { \
  142. validFg = TRUE; \
  143. fg = newFg; \
  144. cl->updateBuf[startUblen] |= rfbHextileForegroundSpecified; \
  145. PUT_PIXEL##bpp(fg); \
  146. } \
  147. } else { \
  148. validFg = FALSE; \
  149. cl->updateBuf[startUblen] |= rfbHextileSubrectsColoured; \
  150. } \
  151. \
  152. if (!subrectEncode##bpp(cl, clientPixelData, w, h, bg, fg, mono)) { \
  153. /* encoding was too large, use raw */ \
  154. validBg = FALSE; \
  155. validFg = FALSE; \
  156. cl->ublen = startUblen; \
  157. cl->updateBuf[cl->ublen++] = rfbHextileRaw; \
  158. (*cl->translateFn)(cl->translateLookupTable, \
  159. &(cl->screen->serverFormat), &cl->format, fbptr, \
  160. (char *)clientPixelData, \
  161. cl->scaledScreen->paddedWidthInBytes, w, h); \
  162. \
  163. memcpy(&cl->updateBuf[cl->ublen], (char *)clientPixelData, \
  164. w * h * (bpp/8)); \
  165. \
  166. cl->ublen += w * h * (bpp/8); \
  167. rfbStatRecordEncodingSentAdd(cl, rfbEncodingHextile, \
  168. w * h * (bpp/8)); \
  169. } \
  170. } \
  171. } \
  172. \
  173. return TRUE; \
  174. } \
  175. \
  176. \
  177. static rfbBool \
  178. subrectEncode##bpp(rfbClientPtr cl, uint##bpp##_t *data, int w, int h, \
  179. uint##bpp##_t bg, uint##bpp##_t fg, rfbBool mono) \
  180. { \
  181. uint##bpp##_t cl2; \
  182. int x,y; \
  183. int i,j; \
  184. int hx=0,hy,vx=0,vy; \
  185. int hyflag; \
  186. uint##bpp##_t *seg; \
  187. uint##bpp##_t *line; \
  188. int hw,hh,vw,vh; \
  189. int thex,they,thew,theh; \
  190. int numsubs = 0; \
  191. int newLen; \
  192. int nSubrectsUblen; \
  193. \
  194. nSubrectsUblen = cl->ublen; \
  195. cl->ublen++; \
  196. rfbStatRecordEncodingSentAdd(cl, rfbEncodingHextile, 1); \
  197. \
  198. for (y=0; y<h; y++) { \
  199. line = data+(y*w); \
  200. for (x=0; x<w; x++) { \
  201. if (line[x] != bg) { \
  202. cl2 = line[x]; \
  203. hy = y-1; \
  204. hyflag = 1; \
  205. for (j=y; j<h; j++) { \
  206. seg = data+(j*w); \
  207. if (seg[x] != cl2) {break;} \
  208. i = x; \
  209. while ((seg[i] == cl2) && (i < w)) i += 1; \
  210. i -= 1; \
  211. if (j == y) vx = hx = i; \
  212. if (i < vx) vx = i; \
  213. if ((hyflag > 0) && (i >= hx)) { \
  214. hy += 1; \
  215. } else { \
  216. hyflag = 0; \
  217. } \
  218. } \
  219. vy = j-1; \
  220. \
  221. /* We now have two possible subrects: (x,y,hx,hy) and \
  222. * (x,y,vx,vy). We'll choose the bigger of the two. \
  223. */ \
  224. hw = hx-x+1; \
  225. hh = hy-y+1; \
  226. vw = vx-x+1; \
  227. vh = vy-y+1; \
  228. \
  229. thex = x; \
  230. they = y; \
  231. \
  232. if ((hw*hh) > (vw*vh)) { \
  233. thew = hw; \
  234. theh = hh; \
  235. } else { \
  236. thew = vw; \
  237. theh = vh; \
  238. } \
  239. \
  240. if (mono) { \
  241. newLen = cl->ublen - nSubrectsUblen + 2; \
  242. } else { \
  243. newLen = cl->ublen - nSubrectsUblen + bpp/8 + 2; \
  244. } \
  245. \
  246. if (newLen > (w * h * (bpp/8))) \
  247. return FALSE; \
  248. \
  249. numsubs += 1; \
  250. \
  251. if (!mono) PUT_PIXEL##bpp(cl2); \
  252. \
  253. cl->updateBuf[cl->ublen++] = rfbHextilePackXY(thex,they); \
  254. cl->updateBuf[cl->ublen++] = rfbHextilePackWH(thew,theh); \
  255. rfbStatRecordEncodingSentAdd(cl, rfbEncodingHextile, 1); \
  256. \
  257. /* \
  258. * Now mark the subrect as done. \
  259. */ \
  260. for (j=they; j < (they+theh); j++) { \
  261. for (i=thex; i < (thex+thew); i++) { \
  262. data[j*w+i] = bg; \
  263. } \
  264. } \
  265. } \
  266. } \
  267. } \
  268. \
  269. cl->updateBuf[nSubrectsUblen] = numsubs; \
  270. \
  271. return TRUE; \
  272. } \
  273. \
  274. \
  275. /* \
  276. * testColours() tests if there are one (solid), two (mono) or more \
  277. * colours in a tile and gets a reasonable guess at the best background \
  278. * pixel, and the foreground pixel for mono. \
  279. */ \
  280. \
  281. static void \
  282. testColours##bpp(uint##bpp##_t *data, int size, rfbBool *mono, rfbBool *solid, \
  283. uint##bpp##_t *bg, uint##bpp##_t *fg) { \
  284. uint##bpp##_t colour1 = 0, colour2 = 0; \
  285. int n1 = 0, n2 = 0; \
  286. *mono = TRUE; \
  287. *solid = TRUE; \
  288. \
  289. for (; size > 0; size--, data++) { \
  290. \
  291. if (n1 == 0) \
  292. colour1 = *data; \
  293. \
  294. if (*data == colour1) { \
  295. n1++; \
  296. continue; \
  297. } \
  298. \
  299. if (n2 == 0) { \
  300. *solid = FALSE; \
  301. colour2 = *data; \
  302. } \
  303. \
  304. if (*data == colour2) { \
  305. n2++; \
  306. continue; \
  307. } \
  308. \
  309. *mono = FALSE; \
  310. break; \
  311. } \
  312. \
  313. if (n1 > n2) { \
  314. *bg = colour1; \
  315. *fg = colour2; \
  316. } else { \
  317. *bg = colour2; \
  318. *fg = colour1; \
  319. } \
  320. }
  321. DEFINE_SEND_HEXTILES(8)
  322. DEFINE_SEND_HEXTILES(16)
  323. DEFINE_SEND_HEXTILES(32)