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 #include <rfb/rfb.h>
00031
00032
00033
00034
00035
00036
00037
00038
00039 static int subrectEncode8(rfbClientPtr cl, uint8_t *data, int w, int h);
00040 static int subrectEncode16(rfbClientPtr cl, uint16_t *data, int w, int h);
00041 static int subrectEncode32(rfbClientPtr cl, uint32_t *data, int w, int h);
00042 static uint32_t getBgColour(char *data, int size, int bpp);
00043 static rfbBool rfbSendSmallRectEncodingCoRRE(rfbClientPtr cl, int x, int y,
00044 int w, int h);
00045
00046
00047
00048
00049
00050
00051
00052 rfbBool
00053 rfbSendRectEncodingCoRRE(rfbClientPtr cl,
00054 int x,
00055 int y,
00056 int w,
00057 int h)
00058 {
00059 if (h > cl->correMaxHeight) {
00060 return (rfbSendRectEncodingCoRRE(cl, x, y, w, cl->correMaxHeight) &&
00061 rfbSendRectEncodingCoRRE(cl, x, y + cl->correMaxHeight, w,
00062 h - cl->correMaxHeight));
00063 }
00064
00065 if (w > cl->correMaxWidth) {
00066 return (rfbSendRectEncodingCoRRE(cl, x, y, cl->correMaxWidth, h) &&
00067 rfbSendRectEncodingCoRRE(cl, x + cl->correMaxWidth, y,
00068 w - cl->correMaxWidth, h));
00069 }
00070
00071 rfbSendSmallRectEncodingCoRRE(cl, x, y, w, h);
00072 return TRUE;
00073 }
00074
00075
00076
00077
00078
00079
00080
00081
00082 static rfbBool
00083 rfbSendSmallRectEncodingCoRRE(rfbClientPtr cl,
00084 int x,
00085 int y,
00086 int w,
00087 int h)
00088 {
00089 rfbFramebufferUpdateRectHeader rect;
00090 rfbRREHeader hdr;
00091 int nSubrects;
00092 int i;
00093 char *fbptr = (cl->scaledScreen->frameBuffer + (cl->scaledScreen->paddedWidthInBytes * y)
00094 + (x * (cl->scaledScreen->bitsPerPixel / 8)));
00095
00096 int maxRawSize = (cl->scaledScreen->width * cl->scaledScreen->height
00097 * (cl->format.bitsPerPixel / 8));
00098
00099 if (cl->beforeEncBufSize < maxRawSize) {
00100 cl->beforeEncBufSize = maxRawSize;
00101 if (cl->beforeEncBuf == NULL)
00102 cl->beforeEncBuf = (char *)malloc(cl->beforeEncBufSize);
00103 else
00104 cl->beforeEncBuf = (char *)realloc(cl->beforeEncBuf, cl->beforeEncBufSize);
00105 }
00106
00107 if (cl->afterEncBufSize < maxRawSize) {
00108 cl->afterEncBufSize = maxRawSize;
00109 if (cl->afterEncBuf == NULL)
00110 cl->afterEncBuf = (char *)malloc(cl->afterEncBufSize);
00111 else
00112 cl->afterEncBuf = (char *)realloc(cl->afterEncBuf, cl->afterEncBufSize);
00113 }
00114
00115 (*cl->translateFn)(cl->translateLookupTable,&(cl->screen->serverFormat),
00116 &cl->format, fbptr, cl->beforeEncBuf,
00117 cl->scaledScreen->paddedWidthInBytes, w, h);
00118
00119 switch (cl->format.bitsPerPixel) {
00120 case 8:
00121 nSubrects = subrectEncode8(cl, (uint8_t *)cl->beforeEncBuf, w, h);
00122 break;
00123 case 16:
00124 nSubrects = subrectEncode16(cl, (uint16_t *)cl->beforeEncBuf, w, h);
00125 break;
00126 case 32:
00127 nSubrects = subrectEncode32(cl, (uint32_t *)cl->beforeEncBuf, w, h);
00128 break;
00129 default:
00130 rfbLog("getBgColour: bpp %d?\n",cl->format.bitsPerPixel);
00131 return FALSE;
00132 }
00133
00134 if (nSubrects < 0) {
00135
00136
00137
00138 return rfbSendRectEncodingRaw(cl, x, y, w, h);
00139 }
00140
00141 rfbStatRecordEncodingSent(cl,rfbEncodingCoRRE,
00142 sz_rfbFramebufferUpdateRectHeader + sz_rfbRREHeader + cl->afterEncBufLen,
00143 sz_rfbFramebufferUpdateRectHeader + w * h * (cl->format.bitsPerPixel / 8));
00144
00145 if (cl->ublen + sz_rfbFramebufferUpdateRectHeader + sz_rfbRREHeader
00146 > UPDATE_BUF_SIZE)
00147 {
00148 if (!rfbSendUpdateBuf(cl))
00149 return FALSE;
00150 }
00151
00152 rect.r.x = Swap16IfLE(x);
00153 rect.r.y = Swap16IfLE(y);
00154 rect.r.w = Swap16IfLE(w);
00155 rect.r.h = Swap16IfLE(h);
00156 rect.encoding = Swap32IfLE(rfbEncodingCoRRE);
00157
00158 memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
00159 sz_rfbFramebufferUpdateRectHeader);
00160 cl->ublen += sz_rfbFramebufferUpdateRectHeader;
00161
00162 hdr.nSubrects = Swap32IfLE(nSubrects);
00163
00164 memcpy(&cl->updateBuf[cl->ublen], (char *)&hdr, sz_rfbRREHeader);
00165 cl->ublen += sz_rfbRREHeader;
00166
00167 for (i = 0; i < cl->afterEncBufLen;) {
00168
00169 int bytesToCopy = UPDATE_BUF_SIZE - cl->ublen;
00170
00171 if (i + bytesToCopy > cl->afterEncBufLen) {
00172 bytesToCopy = cl->afterEncBufLen - i;
00173 }
00174
00175 memcpy(&cl->updateBuf[cl->ublen], &cl->afterEncBuf[i], bytesToCopy);
00176
00177 cl->ublen += bytesToCopy;
00178 i += bytesToCopy;
00179
00180 if (cl->ublen == UPDATE_BUF_SIZE) {
00181 if (!rfbSendUpdateBuf(cl))
00182 return FALSE;
00183 }
00184 }
00185
00186 return TRUE;
00187 }
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204 #define DEFINE_SUBRECT_ENCODE(bpp) \
00205 static int \
00206 subrectEncode##bpp(rfbClientPtr client, uint##bpp##_t *data, int w, int h) { \
00207 uint##bpp##_t cl; \
00208 rfbCoRRERectangle subrect; \
00209 int x,y; \
00210 int i,j; \
00211 int hx=0,hy,vx=0,vy; \
00212 int hyflag; \
00213 uint##bpp##_t *seg; \
00214 uint##bpp##_t *line; \
00215 int hw,hh,vw,vh; \
00216 int thex,they,thew,theh; \
00217 int numsubs = 0; \
00218 int newLen; \
00219 uint##bpp##_t bg = (uint##bpp##_t)getBgColour((char*)data,w*h,bpp); \
00220 \
00221 *((uint##bpp##_t*)client->afterEncBuf) = bg; \
00222 \
00223 client->afterEncBufLen = (bpp/8); \
00224 \
00225 for (y=0; y<h; y++) { \
00226 line = data+(y*w); \
00227 for (x=0; x<w; x++) { \
00228 if (line[x] != bg) { \
00229 cl = line[x]; \
00230 hy = y-1; \
00231 hyflag = 1; \
00232 for (j=y; j<h; j++) { \
00233 seg = data+(j*w); \
00234 if (seg[x] != cl) {break;} \
00235 i = x; \
00236 while ((seg[i] == cl) && (i < w)) i += 1; \
00237 i -= 1; \
00238 if (j == y) vx = hx = i; \
00239 if (i < vx) vx = i; \
00240 if ((hyflag > 0) && (i >= hx)) {hy += 1;} else {hyflag = 0;} \
00241 } \
00242 vy = j-1; \
00243 \
00244
00245
00246 \
00247 hw = hx-x+1; \
00248 hh = hy-y+1; \
00249 vw = vx-x+1; \
00250 vh = vy-y+1; \
00251 \
00252 thex = x; \
00253 they = y; \
00254 \
00255 if ((hw*hh) > (vw*vh)) { \
00256 thew = hw; \
00257 theh = hh; \
00258 } else { \
00259 thew = vw; \
00260 theh = vh; \
00261 } \
00262 \
00263 subrect.x = thex; \
00264 subrect.y = they; \
00265 subrect.w = thew; \
00266 subrect.h = theh; \
00267 \
00268 newLen = client->afterEncBufLen + (bpp/8) + sz_rfbCoRRERectangle; \
00269 if ((newLen > (w * h * (bpp/8))) || (newLen > client->afterEncBufSize)) \
00270 return -1; \
00271 \
00272 numsubs += 1; \
00273 *((uint##bpp##_t*)(client->afterEncBuf + client->afterEncBufLen)) = cl; \
00274 client->afterEncBufLen += (bpp/8); \
00275 memcpy(&client->afterEncBuf[client->afterEncBufLen],&subrect,sz_rfbCoRRERectangle); \
00276 client->afterEncBufLen += sz_rfbCoRRERectangle; \
00277 \
00278
00279
00280 \
00281 for (j=they; j < (they+theh); j++) { \
00282 for (i=thex; i < (thex+thew); i++) { \
00283 data[j*w+i] = bg; \
00284 } \
00285 } \
00286 } \
00287 } \
00288 } \
00289 \
00290 return numsubs; \
00291 }
00292
00293 DEFINE_SUBRECT_ENCODE(8)
00294 DEFINE_SUBRECT_ENCODE(16)
00295 DEFINE_SUBRECT_ENCODE(32)
00296
00297
00298
00299
00300
00301 static uint32_t
00302 getBgColour(char *data, int size, int bpp)
00303 {
00304
00305 #define NUMCLRS 256
00306
00307 static int counts[NUMCLRS];
00308 int i,j,k;
00309
00310 int maxcount = 0;
00311 uint8_t maxclr = 0;
00312
00313 if (bpp != 8) {
00314 if (bpp == 16) {
00315 return ((uint16_t *)data)[0];
00316 } else if (bpp == 32) {
00317 return ((uint32_t *)data)[0];
00318 } else {
00319 rfbLog("getBgColour: bpp %d?\n",bpp);
00320 return 0;
00321 }
00322 }
00323
00324 for (i=0; i<NUMCLRS; i++) {
00325 counts[i] = 0;
00326 }
00327
00328 for (j=0; j<size; j++) {
00329 k = (int)(((uint8_t *)data)[j]);
00330 if (k >= NUMCLRS) {
00331 rfbLog("getBgColour: unusual colour = %d\n", k);
00332 return 0;
00333 }
00334 counts[k] += 1;
00335 if (counts[k] > maxcount) {
00336 maxcount = counts[k];
00337 maxclr = ((uint8_t *)data)[j];
00338 }
00339 }
00340
00341 return maxclr;
00342 }