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