Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #include <rfb/rfb.h>
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048 #if LIBVNCSERVER_HAVE_LIBPTHREAD && LIBVNCSERVER_HAVE_TLS && !defined(TLS) && defined(__linux__)
00049 #define TLS __thread
00050 #endif
00051 #ifndef TLS
00052 #define TLS
00053 #endif
00054
00055 static TLS int zlibBeforeBufSize = 0;
00056 static TLS char *zlibBeforeBuf = NULL;
00057
00058 static TLS int zlibAfterBufSize = 0;
00059 static TLS char *zlibAfterBuf = NULL;
00060 static TLS int zlibAfterBufLen = 0;
00061
00062 void rfbZlibCleanup(rfbScreenInfoPtr screen)
00063 {
00064 if (zlibBeforeBufSize) {
00065 free(zlibBeforeBuf);
00066 zlibBeforeBufSize=0;
00067 }
00068 if (zlibAfterBufSize) {
00069 zlibAfterBufSize=0;
00070 free(zlibAfterBuf);
00071 }
00072 }
00073
00074
00075
00076
00077
00078
00079
00080 static rfbBool
00081 rfbSendOneRectEncodingZlib(rfbClientPtr cl,
00082 int x,
00083 int y,
00084 int w,
00085 int h)
00086 {
00087 rfbFramebufferUpdateRectHeader rect;
00088 rfbZlibHeader hdr;
00089 int deflateResult;
00090 int previousOut;
00091 int i;
00092 char *fbptr = (cl->scaledScreen->frameBuffer + (cl->scaledScreen->paddedWidthInBytes * y)
00093 + (x * (cl->scaledScreen->bitsPerPixel / 8)));
00094
00095 int maxRawSize;
00096 int maxCompSize;
00097
00098 maxRawSize = (cl->scaledScreen->width * cl->scaledScreen->height
00099 * (cl->format.bitsPerPixel / 8));
00100
00101 if (zlibBeforeBufSize < maxRawSize) {
00102 zlibBeforeBufSize = maxRawSize;
00103 if (zlibBeforeBuf == NULL)
00104 zlibBeforeBuf = (char *)malloc(zlibBeforeBufSize);
00105 else
00106 zlibBeforeBuf = (char *)realloc(zlibBeforeBuf, zlibBeforeBufSize);
00107 }
00108
00109
00110
00111
00112 if (( w * h * (cl->scaledScreen->bitsPerPixel / 8)) <
00113 VNC_ENCODE_ZLIB_MIN_COMP_SIZE ) {
00114
00115 int result;
00116
00117
00118
00119
00120
00121
00122
00123 if (( cl->format.bitsPerPixel > 8 ) &&
00124 ( cl->ublen % ( cl->format.bitsPerPixel / 8 )) != 0 ) {
00125 if (!rfbSendUpdateBuf(cl))
00126 return FALSE;
00127 }
00128
00129 result = rfbSendRectEncodingRaw(cl, x, y, w, h);
00130
00131 return result;
00132
00133 }
00134
00135
00136
00137
00138
00139 maxCompSize = maxRawSize + (( maxRawSize + 99 ) / 100 ) + 12;
00140
00141 if (zlibAfterBufSize < maxCompSize) {
00142 zlibAfterBufSize = maxCompSize;
00143 if (zlibAfterBuf == NULL)
00144 zlibAfterBuf = (char *)malloc(zlibAfterBufSize);
00145 else
00146 zlibAfterBuf = (char *)realloc(zlibAfterBuf, zlibAfterBufSize);
00147 }
00148
00149
00150
00151
00152
00153 (*cl->translateFn)(cl->translateLookupTable, &cl->screen->serverFormat,
00154 &cl->format, fbptr, zlibBeforeBuf,
00155 cl->scaledScreen->paddedWidthInBytes, w, h);
00156
00157 cl->compStream.next_in = ( Bytef * )zlibBeforeBuf;
00158 cl->compStream.avail_in = w * h * (cl->format.bitsPerPixel / 8);
00159 cl->compStream.next_out = ( Bytef * )zlibAfterBuf;
00160 cl->compStream.avail_out = maxCompSize;
00161 cl->compStream.data_type = Z_BINARY;
00162
00163
00164 if ( cl->compStreamInited == FALSE ) {
00165
00166 cl->compStream.total_in = 0;
00167 cl->compStream.total_out = 0;
00168 cl->compStream.zalloc = Z_NULL;
00169 cl->compStream.zfree = Z_NULL;
00170 cl->compStream.opaque = Z_NULL;
00171
00172 deflateInit2( &(cl->compStream),
00173 cl->zlibCompressLevel,
00174 Z_DEFLATED,
00175 MAX_WBITS,
00176 MAX_MEM_LEVEL,
00177 Z_DEFAULT_STRATEGY );
00178
00179
00180 cl->compStreamInited = TRUE;
00181
00182 }
00183
00184 previousOut = cl->compStream.total_out;
00185
00186
00187 deflateResult = deflate( &(cl->compStream), Z_SYNC_FLUSH );
00188
00189
00190 zlibAfterBufLen = cl->compStream.total_out - previousOut;
00191
00192 if ( deflateResult != Z_OK ) {
00193 rfbErr("zlib deflation error: %s\n", cl->compStream.msg);
00194 return FALSE;
00195 }
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205 rfbStatRecordEncodingSent(cl, rfbEncodingZlib, sz_rfbFramebufferUpdateRectHeader + sz_rfbZlibHeader + zlibAfterBufLen,
00206 + w * (cl->format.bitsPerPixel / 8) * h);
00207
00208 if (cl->ublen + sz_rfbFramebufferUpdateRectHeader + sz_rfbZlibHeader
00209 > UPDATE_BUF_SIZE)
00210 {
00211 if (!rfbSendUpdateBuf(cl))
00212 return FALSE;
00213 }
00214
00215 rect.r.x = Swap16IfLE(x);
00216 rect.r.y = Swap16IfLE(y);
00217 rect.r.w = Swap16IfLE(w);
00218 rect.r.h = Swap16IfLE(h);
00219 rect.encoding = Swap32IfLE(rfbEncodingZlib);
00220
00221 memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
00222 sz_rfbFramebufferUpdateRectHeader);
00223 cl->ublen += sz_rfbFramebufferUpdateRectHeader;
00224
00225 hdr.nBytes = Swap32IfLE(zlibAfterBufLen);
00226
00227 memcpy(&cl->updateBuf[cl->ublen], (char *)&hdr, sz_rfbZlibHeader);
00228 cl->ublen += sz_rfbZlibHeader;
00229
00230 for (i = 0; i < zlibAfterBufLen;) {
00231
00232 int bytesToCopy = UPDATE_BUF_SIZE - cl->ublen;
00233
00234 if (i + bytesToCopy > zlibAfterBufLen) {
00235 bytesToCopy = zlibAfterBufLen - i;
00236 }
00237
00238 memcpy(&cl->updateBuf[cl->ublen], &zlibAfterBuf[i], bytesToCopy);
00239
00240 cl->ublen += bytesToCopy;
00241 i += bytesToCopy;
00242
00243 if (cl->ublen == UPDATE_BUF_SIZE) {
00244 if (!rfbSendUpdateBuf(cl))
00245 return FALSE;
00246 }
00247 }
00248
00249 return TRUE;
00250
00251 }
00252
00253
00254
00255
00256
00257
00258
00259 rfbBool
00260 rfbSendRectEncodingZlib(rfbClientPtr cl,
00261 int x,
00262 int y,
00263 int w,
00264 int h)
00265 {
00266 int maxLines;
00267 int linesRemaining;
00268 rfbRectangle partialRect;
00269
00270 partialRect.x = x;
00271 partialRect.y = y;
00272 partialRect.w = w;
00273 partialRect.h = h;
00274
00275
00276 maxLines = ( ZLIB_MAX_SIZE(w) / w );
00277
00278
00279 linesRemaining = h;
00280
00281
00282 while ( linesRemaining > 0 ) {
00283
00284 int linesToComp;
00285
00286 if ( maxLines < linesRemaining )
00287 linesToComp = maxLines;
00288 else
00289 linesToComp = linesRemaining;
00290
00291 partialRect.h = linesToComp;
00292
00293
00294 if ( ! rfbSendOneRectEncodingZlib( cl,
00295 partialRect.x,
00296 partialRect.y,
00297 partialRect.w,
00298 partialRect.h )) {
00299
00300 return FALSE;
00301 }
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314 if (( cl->ublen > 0 ) &&
00315 ( linesToComp == maxLines )) {
00316 if (!rfbSendUpdateBuf(cl)) {
00317
00318 return FALSE;
00319 }
00320 }
00321
00322
00323 linesRemaining -= linesToComp;
00324 partialRect.y += linesToComp;
00325
00326 }
00327
00328 return TRUE;
00329
00330 }
00331