/apps/desktop/libvncserver/zrle.c

http://ftk.googlecode.com/ · C · 183 lines · 111 code · 38 blank · 34 comment · 17 complexity · 8727cc84eaf099afd72ea35789aa216e MD5 · raw file

  1. /*
  2. * Copyright (C) 2002 RealVNC Ltd. All Rights Reserved.
  3. * Copyright (C) 2003 Sun Microsystems, Inc.
  4. *
  5. * This is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This software is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this software; if not, write to the Free Software
  17. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
  18. * USA.
  19. */
  20. /*
  21. * zrle.c
  22. *
  23. * Routines to implement Zlib Run-length Encoding (ZRLE).
  24. */
  25. #include "rfb/rfb.h"
  26. #include "private.h"
  27. #include "zrleoutstream.h"
  28. #define GET_IMAGE_INTO_BUF(tx,ty,tw,th,buf) \
  29. { char *fbptr = (cl->scaledScreen->frameBuffer \
  30. + (cl->scaledScreen->paddedWidthInBytes * ty) \
  31. + (tx * (cl->scaledScreen->bitsPerPixel / 8))); \
  32. \
  33. (*cl->translateFn)(cl->translateLookupTable, &cl->screen->serverFormat,\
  34. &cl->format, fbptr, (char*)buf, \
  35. cl->scaledScreen->paddedWidthInBytes, tw, th); }
  36. #define EXTRA_ARGS , rfbClientPtr cl
  37. #define BPP 8
  38. #include <zrleencodetemplate.c>
  39. #undef BPP
  40. #define BPP 16
  41. #include <zrleencodetemplate.c>
  42. #undef BPP
  43. #define BPP 32
  44. #include <zrleencodetemplate.c>
  45. #define CPIXEL 24A
  46. #include <zrleencodetemplate.c>
  47. #undef CPIXEL
  48. #define CPIXEL 24B
  49. #include <zrleencodetemplate.c>
  50. #undef CPIXEL
  51. #undef BPP
  52. /*
  53. * zrleBeforeBuf contains pixel data in the client's format. It must be at
  54. * least one pixel bigger than the largest tile of pixel data, since the
  55. * ZRLE encoding algorithm writes to the position one past the end of the pixel
  56. * data.
  57. */
  58. static char zrleBeforeBuf[rfbZRLETileWidth * rfbZRLETileHeight * 4 + 4];
  59. /*
  60. * rfbSendRectEncodingZRLE - send a given rectangle using ZRLE encoding.
  61. */
  62. rfbBool rfbSendRectEncodingZRLE(rfbClientPtr cl, int x, int y, int w, int h)
  63. {
  64. zrleOutStream* zos;
  65. rfbFramebufferUpdateRectHeader rect;
  66. rfbZRLEHeader hdr;
  67. int i;
  68. if (!cl->zrleData)
  69. cl->zrleData = zrleOutStreamNew();
  70. zos = cl->zrleData;
  71. zos->in.ptr = zos->in.start;
  72. zos->out.ptr = zos->out.start;
  73. switch (cl->format.bitsPerPixel) {
  74. case 8:
  75. zrleEncode8( x, y, w, h, zos, zrleBeforeBuf, cl);
  76. break;
  77. case 16:
  78. zrleEncode16(x, y, w, h, zos, zrleBeforeBuf, cl);
  79. break;
  80. case 32: {
  81. rfbBool fitsInLS3Bytes
  82. = ((cl->format.redMax << cl->format.redShift) < (1<<24) &&
  83. (cl->format.greenMax << cl->format.greenShift) < (1<<24) &&
  84. (cl->format.blueMax << cl->format.blueShift) < (1<<24));
  85. rfbBool fitsInMS3Bytes = (cl->format.redShift > 7 &&
  86. cl->format.greenShift > 7 &&
  87. cl->format.blueShift > 7);
  88. if ((fitsInLS3Bytes && !cl->format.bigEndian) ||
  89. (fitsInMS3Bytes && cl->format.bigEndian))
  90. {
  91. zrleEncode24A(x, y, w, h, zos, zrleBeforeBuf, cl);
  92. }
  93. else if ((fitsInLS3Bytes && cl->format.bigEndian) ||
  94. (fitsInMS3Bytes && !cl->format.bigEndian))
  95. {
  96. zrleEncode24B(x, y, w, h, zos, zrleBeforeBuf, cl);
  97. }
  98. else
  99. {
  100. zrleEncode32(x, y, w, h, zos, zrleBeforeBuf, cl);
  101. }
  102. }
  103. break;
  104. }
  105. rfbStatRecordEncodingSent(cl, rfbEncodingZRLE, sz_rfbFramebufferUpdateRectHeader + sz_rfbZRLEHeader + ZRLE_BUFFER_LENGTH(&zos->out),
  106. + w * (cl->format.bitsPerPixel / 8) * h);
  107. if (cl->ublen + sz_rfbFramebufferUpdateRectHeader + sz_rfbZRLEHeader
  108. > UPDATE_BUF_SIZE)
  109. {
  110. if (!rfbSendUpdateBuf(cl))
  111. return FALSE;
  112. }
  113. rect.r.x = Swap16IfLE(x);
  114. rect.r.y = Swap16IfLE(y);
  115. rect.r.w = Swap16IfLE(w);
  116. rect.r.h = Swap16IfLE(h);
  117. rect.encoding = Swap32IfLE(rfbEncodingZRLE);
  118. memcpy(cl->updateBuf+cl->ublen, (char *)&rect,
  119. sz_rfbFramebufferUpdateRectHeader);
  120. cl->ublen += sz_rfbFramebufferUpdateRectHeader;
  121. hdr.length = Swap32IfLE(ZRLE_BUFFER_LENGTH(&zos->out));
  122. memcpy(cl->updateBuf+cl->ublen, (char *)&hdr, sz_rfbZRLEHeader);
  123. cl->ublen += sz_rfbZRLEHeader;
  124. /* copy into updateBuf and send from there. Maybe should send directly? */
  125. for (i = 0; i < ZRLE_BUFFER_LENGTH(&zos->out);) {
  126. int bytesToCopy = UPDATE_BUF_SIZE - cl->ublen;
  127. if (i + bytesToCopy > ZRLE_BUFFER_LENGTH(&zos->out)) {
  128. bytesToCopy = ZRLE_BUFFER_LENGTH(&zos->out) - i;
  129. }
  130. memcpy(cl->updateBuf+cl->ublen, (uint8_t*)zos->out.start + i, bytesToCopy);
  131. cl->ublen += bytesToCopy;
  132. i += bytesToCopy;
  133. if (cl->ublen == UPDATE_BUF_SIZE) {
  134. if (!rfbSendUpdateBuf(cl))
  135. return FALSE;
  136. }
  137. }
  138. return TRUE;
  139. }
  140. void rfbFreeZrleData(rfbClientPtr cl)
  141. {
  142. if (cl->zrleData)
  143. zrleOutStreamFree(cl->zrleData);
  144. cl->zrleData = NULL;
  145. }