You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

SMsgWriter.cxx 5.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
  2. *
  3. * This is free software; you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License as published by
  5. * the Free Software Foundation; either version 2 of the License, or
  6. * (at your option) any later version.
  7. *
  8. * This software is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License
  14. * along with this software; if not, write to the Free Software
  15. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
  16. * USA.
  17. */
  18. #include <stdio.h>
  19. #include <assert.h>
  20. #include <rdr/OutStream.h>
  21. #include <rfb/msgTypes.h>
  22. #include <rfb/ColourMap.h>
  23. #include <rfb/ConnParams.h>
  24. #include <rfb/UpdateTracker.h>
  25. #include <rfb/SMsgWriter.h>
  26. #include <rfb/LogWriter.h>
  27. using namespace rfb;
  28. static LogWriter vlog("SMsgWriter");
  29. SMsgWriter::SMsgWriter(ConnParams* cp_, rdr::OutStream* os_)
  30. : imageBufIdealSize(0), cp(cp_), os(os_), lenBeforeRect(0),
  31. currentEncoding(0), updatesSent(0), rawBytesEquivalent(0),
  32. imageBuf(0), imageBufSize(0)
  33. {
  34. for (int i = 0; i <= encodingMax; i++) {
  35. encoders[i] = 0;
  36. bytesSent[i] = 0;
  37. rectsSent[i] = 0;
  38. }
  39. }
  40. SMsgWriter::~SMsgWriter()
  41. {
  42. vlog.info("framebuffer updates %d",updatesSent);
  43. int bytes = 0;
  44. for (int i = 0; i <= encodingMax; i++) {
  45. delete encoders[i];
  46. if (i != encodingCopyRect)
  47. bytes += bytesSent[i];
  48. if (rectsSent[i])
  49. vlog.info(" %s rects %d, bytes %d",
  50. encodingName(i), rectsSent[i], bytesSent[i]);
  51. }
  52. vlog.info(" raw bytes equivalent %d, compression ratio %f",
  53. rawBytesEquivalent, (double)rawBytesEquivalent / bytes);
  54. delete [] imageBuf;
  55. }
  56. void SMsgWriter::writeSetColourMapEntries(int firstColour, int nColours,
  57. ColourMap* cm)
  58. {
  59. startMsg(msgTypeSetColourMapEntries);
  60. os->pad(1);
  61. os->writeU16(firstColour);
  62. os->writeU16(nColours);
  63. for (int i = firstColour; i < firstColour+nColours; i++) {
  64. int r, g, b;
  65. cm->lookup(i, &r, &g, &b);
  66. os->writeU16(r);
  67. os->writeU16(g);
  68. os->writeU16(b);
  69. }
  70. endMsg();
  71. }
  72. void SMsgWriter::writeBell()
  73. {
  74. startMsg(msgTypeBell);
  75. endMsg();
  76. }
  77. void SMsgWriter::writeServerCutText(const char* str, int len)
  78. {
  79. startMsg(msgTypeServerCutText);
  80. os->pad(3);
  81. os->writeU32(len);
  82. os->writeBytes(str, len);
  83. endMsg();
  84. }
  85. void SMsgWriter::setupCurrentEncoder()
  86. {
  87. int encoding = cp->currentEncoding();
  88. // FIXME: Code duplication, see writeRect().
  89. if (!encoders[encoding]) {
  90. encoders[encoding] = Encoder::createEncoder(encoding, this);
  91. assert(encoders[encoding]);
  92. }
  93. encoders[encoding]->setCompressLevel(cp->compressLevel);
  94. encoders[encoding]->setQualityLevel(cp->qualityLevel);
  95. }
  96. int SMsgWriter::getNumRects(const Rect &r)
  97. {
  98. int encoding = cp->currentEncoding();
  99. if (!encoders[encoding])
  100. setupCurrentEncoder();
  101. return encoders[encoding]->getNumRects(r);
  102. }
  103. bool SMsgWriter::needFakeUpdate()
  104. {
  105. return false;
  106. }
  107. // FIXME: This functions is not used because it incorrectly computes
  108. // the number of rectangles if the Tight encoder is used.
  109. /*
  110. void SMsgWriter::writeFramebufferUpdate(const UpdateInfo& ui, ImageGetter* ig,
  111. Region* updatedRegion)
  112. {
  113. writeFramebufferUpdateStart(ui.numRects());
  114. writeRects(ui, ig, updatedRegion);
  115. writeFramebufferUpdateEnd();
  116. }
  117. */
  118. bool SMsgWriter::needNoDataUpdate()
  119. {
  120. return false;
  121. }
  122. void SMsgWriter::writeNoDataUpdate()
  123. {
  124. // This class has no pseudo-rectangles so there is nothing to do here
  125. vlog.error("writeNoDataUpdate() called");
  126. }
  127. void SMsgWriter::writeRects(const UpdateInfo& ui, ImageGetter* ig,
  128. Region* updatedRegion)
  129. {
  130. std::vector<Rect> rects;
  131. std::vector<Rect>::const_iterator i;
  132. updatedRegion->copyFrom(ui.changed);
  133. updatedRegion->assign_union(ui.copied);
  134. ui.copied.get_rects(&rects, ui.copy_delta.x <= 0, ui.copy_delta.y <= 0);
  135. for (i = rects.begin(); i != rects.end(); i++)
  136. writeCopyRect(*i, i->tl.x - ui.copy_delta.x, i->tl.y - ui.copy_delta.y);
  137. ui.changed.get_rects(&rects);
  138. for (i = rects.begin(); i != rects.end(); i++) {
  139. Rect actual;
  140. if (!writeRect(*i, ig, &actual)) {
  141. updatedRegion->assign_subtract(*i);
  142. updatedRegion->assign_union(actual);
  143. }
  144. }
  145. }
  146. bool SMsgWriter::writeRect(const Rect& r, ImageGetter* ig, Rect* actual)
  147. {
  148. return writeRect(r, cp->currentEncoding(), ig, actual);
  149. }
  150. bool SMsgWriter::writeRect(const Rect& r, int encoding,
  151. ImageGetter* ig, Rect* actual)
  152. {
  153. if (!encoders[encoding]) {
  154. encoders[encoding] = Encoder::createEncoder(encoding, this);
  155. assert(encoders[encoding]);
  156. }
  157. return encoders[encoding]->writeRect(r, ig, actual);
  158. }
  159. void SMsgWriter::writeCopyRect(const Rect& r, int srcX, int srcY)
  160. {
  161. startRect(r,encodingCopyRect);
  162. os->writeU16(srcX);
  163. os->writeU16(srcY);
  164. endRect();
  165. }
  166. rdr::U8* SMsgWriter::getImageBuf(int required, int requested, int* nPixels)
  167. {
  168. int requiredBytes = required * (cp->pf().bpp / 8);
  169. int requestedBytes = requested * (cp->pf().bpp / 8);
  170. int size = requestedBytes;
  171. if (size > imageBufIdealSize) size = imageBufIdealSize;
  172. if (size < requiredBytes)
  173. size = requiredBytes;
  174. if (imageBufSize < size) {
  175. imageBufSize = size;
  176. delete [] imageBuf;
  177. imageBuf = new rdr::U8[imageBufSize];
  178. }
  179. if (nPixels)
  180. *nPixels = imageBufSize / (cp->pf().bpp / 8);
  181. return imageBuf;
  182. }
  183. int SMsgWriter::bpp()
  184. {
  185. return cp->pf().bpp;
  186. }