~ubuntu-branches/debian/lenny/italc/lenny

« back to all changes in this revision

Viewing changes to common/ivs/libvncserver/corre.c

  • Committer: Bazaar Package Importer
  • Author(s): Patrick Winnertz
  • Date: 2008-06-17 13:46:54 UTC
  • mfrom: (1.2.1 upstream) (4.1.1 gutsy)
  • Revision ID: james.westby@ubuntu.com-20080617134654-cl0gi4u524cv1ici
Tags: 1:1.0.9~rc3-1
* Package new upstream version
  - upstream ported the code to qt4.4 (Closes: #481974)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * corre.c
3
 
 *
4
 
 * Routines to implement Compact Rise-and-Run-length Encoding (CoRRE).  This
5
 
 * code is based on krw's original javatel rfbserver.
6
 
 */
7
 
 
8
 
/*
9
 
 *  Copyright (C) 2002 RealVNC Ltd.
10
 
 *  OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
11
 
 *  Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge.  
12
 
 *  All Rights Reserved.
13
 
 *
14
 
 *  This is free software; you can redistribute it and/or modify
15
 
 *  it under the terms of the GNU General Public License as published by
16
 
 *  the Free Software Foundation; either version 2 of the License, or
17
 
 *  (at your option) any later version.
18
 
 *
19
 
 *  This software is distributed in the hope that it will be useful,
20
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
21
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22
 
 *  GNU General Public License for more details.
23
 
 *
24
 
 *  You should have received a copy of the GNU General Public License
25
 
 *  along with this software; if not, write to the Free Software
26
 
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
27
 
 *  USA.
28
 
 */
29
 
 
30
 
#include <rfb/rfb.h>
31
 
 
32
 
/*
33
 
 * rreBeforeBuf contains pixel data in the client's format.
34
 
 * rreAfterBuf contains the RRE encoded version.  If the RRE encoded version is
35
 
 * larger than the raw data or if it exceeds rreAfterBufSize then
36
 
 * raw encoding is used instead.
37
 
 */
38
 
 
39
 
static int rreBeforeBufSize = 0;
40
 
static char *rreBeforeBuf = NULL;
41
 
 
42
 
static int rreAfterBufSize = 0;
43
 
static char *rreAfterBuf = NULL;
44
 
static int rreAfterBufLen;
45
 
 
46
 
static int subrectEncode8(uint8_t *data, int w, int h);
47
 
static int subrectEncode16(uint16_t *data, int w, int h);
48
 
static int subrectEncode32(uint32_t *data, int w, int h);
49
 
static uint32_t getBgColour(char *data, int size, int bpp);
50
 
static rfbBool rfbSendSmallRectEncodingCoRRE(rfbClientPtr cl, int x, int y,
51
 
                                          int w, int h);
52
 
 
53
 
 
54
 
/*
55
 
 * rfbSendRectEncodingCoRRE - send an arbitrary size rectangle using CoRRE
56
 
 * encoding.
57
 
 */
58
 
 
59
 
rfbBool
60
 
rfbSendRectEncodingCoRRE(cl, x, y, w, h)
61
 
    rfbClientPtr cl;
62
 
    int x, y, w, h;
63
 
{
64
 
    if (h > cl->correMaxHeight) {
65
 
        return (rfbSendRectEncodingCoRRE(cl, x, y, w, cl->correMaxHeight) &&
66
 
                rfbSendRectEncodingCoRRE(cl, x, y + cl->correMaxHeight, w,
67
 
                                         h - cl->correMaxHeight));
68
 
    }
69
 
 
70
 
    if (w > cl->correMaxWidth) {
71
 
        return (rfbSendRectEncodingCoRRE(cl, x, y, cl->correMaxWidth, h) &&
72
 
                rfbSendRectEncodingCoRRE(cl, x + cl->correMaxWidth, y,
73
 
                                         w - cl->correMaxWidth, h));
74
 
    }
75
 
 
76
 
    rfbSendSmallRectEncodingCoRRE(cl, x, y, w, h);
77
 
    return TRUE;
78
 
}
79
 
 
80
 
 
81
 
 
82
 
/*
83
 
 * rfbSendSmallRectEncodingCoRRE - send a small (guaranteed < 256x256)
84
 
 * rectangle using CoRRE encoding.
85
 
 */
86
 
 
87
 
static rfbBool
88
 
rfbSendSmallRectEncodingCoRRE(cl, x, y, w, h)
89
 
    rfbClientPtr cl;
90
 
    int x, y, w, h;
91
 
{
92
 
    rfbFramebufferUpdateRectHeader rect;
93
 
    rfbRREHeader hdr;
94
 
    int nSubrects;
95
 
    int i;
96
 
    char *fbptr = (cl->screen->frameBuffer + (cl->screen->paddedWidthInBytes * y)
97
 
                   + (x * (cl->screen->bitsPerPixel / 8)));
98
 
 
99
 
    int maxRawSize = (cl->screen->width * cl->screen->height
100
 
                      * (cl->format.bitsPerPixel / 8));
101
 
 
102
 
    if (rreBeforeBufSize < maxRawSize) {
103
 
        rreBeforeBufSize = maxRawSize;
104
 
        if (rreBeforeBuf == NULL)
105
 
            rreBeforeBuf = (char *)malloc(rreBeforeBufSize);
106
 
        else
107
 
            rreBeforeBuf = (char *)realloc(rreBeforeBuf, rreBeforeBufSize);
108
 
    }
109
 
 
110
 
    if (rreAfterBufSize < maxRawSize) {
111
 
        rreAfterBufSize = maxRawSize;
112
 
        if (rreAfterBuf == NULL)
113
 
            rreAfterBuf = (char *)malloc(rreAfterBufSize);
114
 
        else
115
 
            rreAfterBuf = (char *)realloc(rreAfterBuf, rreAfterBufSize);
116
 
    }
117
 
 
118
 
    (*cl->translateFn)(cl->translateLookupTable,&(cl->screen->rfbServerFormat),
119
 
                       &cl->format, fbptr, rreBeforeBuf,
120
 
                       cl->screen->paddedWidthInBytes, w, h);
121
 
 
122
 
    switch (cl->format.bitsPerPixel) {
123
 
    case 8:
124
 
        nSubrects = subrectEncode8((uint8_t *)rreBeforeBuf, w, h);
125
 
        break;
126
 
    case 16:
127
 
        nSubrects = subrectEncode16((uint16_t *)rreBeforeBuf, w, h);
128
 
        break;
129
 
    case 32:
130
 
        nSubrects = subrectEncode32((uint32_t *)rreBeforeBuf, w, h);
131
 
        break;
132
 
    default:
133
 
        rfbLog("getBgColour: bpp %d?\n",cl->format.bitsPerPixel);
134
 
        return FALSE;
135
 
    }
136
 
        
137
 
    if (nSubrects < 0) {
138
 
 
139
 
        /* RRE encoding was too large, use raw */
140
 
 
141
 
        return rfbSendRectEncodingRaw(cl, x, y, w, h);
142
 
    }
143
 
 
144
 
    cl->rfbRectanglesSent[rfbEncodingCoRRE]++;
145
 
    cl->rfbBytesSent[rfbEncodingCoRRE] += (sz_rfbFramebufferUpdateRectHeader
146
 
                                           + sz_rfbRREHeader + rreAfterBufLen);
147
 
 
148
 
    if (cl->ublen + sz_rfbFramebufferUpdateRectHeader + sz_rfbRREHeader
149
 
        > UPDATE_BUF_SIZE)
150
 
    {
151
 
        if (!rfbSendUpdateBuf(cl))
152
 
            return FALSE;
153
 
    }
154
 
 
155
 
    rect.r.x = Swap16IfLE(x);
156
 
    rect.r.y = Swap16IfLE(y);
157
 
    rect.r.w = Swap16IfLE(w);
158
 
    rect.r.h = Swap16IfLE(h);
159
 
    rect.encoding = Swap32IfLE(rfbEncodingCoRRE);
160
 
 
161
 
    memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
162
 
           sz_rfbFramebufferUpdateRectHeader);
163
 
    cl->ublen += sz_rfbFramebufferUpdateRectHeader;
164
 
 
165
 
    hdr.nSubrects = Swap32IfLE(nSubrects);
166
 
 
167
 
    memcpy(&cl->updateBuf[cl->ublen], (char *)&hdr, sz_rfbRREHeader);
168
 
    cl->ublen += sz_rfbRREHeader;
169
 
 
170
 
    for (i = 0; i < rreAfterBufLen;) {
171
 
 
172
 
        int bytesToCopy = UPDATE_BUF_SIZE - cl->ublen;
173
 
 
174
 
        if (i + bytesToCopy > rreAfterBufLen) {
175
 
            bytesToCopy = rreAfterBufLen - i;
176
 
        }
177
 
 
178
 
        memcpy(&cl->updateBuf[cl->ublen], &rreAfterBuf[i], bytesToCopy);
179
 
 
180
 
        cl->ublen += bytesToCopy;
181
 
        i += bytesToCopy;
182
 
 
183
 
        if (cl->ublen == UPDATE_BUF_SIZE) {
184
 
            if (!rfbSendUpdateBuf(cl))
185
 
                return FALSE;
186
 
        }
187
 
    }
188
 
 
189
 
    return TRUE;
190
 
}
191
 
 
192
 
 
193
 
 
194
 
/*
195
 
 * subrectEncode() encodes the given multicoloured rectangle as a background 
196
 
 * colour overwritten by single-coloured rectangles.  It returns the number 
197
 
 * of subrectangles in the encoded buffer, or -1 if subrect encoding won't
198
 
 * fit in the buffer.  It puts the encoded rectangles in rreAfterBuf.  The
199
 
 * single-colour rectangle partition is not optimal, but does find the biggest
200
 
 * horizontal or vertical rectangle top-left anchored to each consecutive 
201
 
 * coordinate position.
202
 
 *
203
 
 * The coding scheme is simply [<bgcolour><subrect><subrect>...] where each 
204
 
 * <subrect> is [<colour><x><y><w><h>].
205
 
 */
206
 
 
207
 
#define DEFINE_SUBRECT_ENCODE(bpp)                                            \
208
 
static int                                                                    \
209
 
subrectEncode##bpp(data,w,h)                                                  \
210
 
    uint##bpp##_t *data;                                                      \
211
 
    int w;                                                                    \
212
 
    int h;                                                                    \
213
 
{                                                                             \
214
 
    uint##bpp##_t cl;                                                         \
215
 
    rfbCoRRERectangle subrect;                                                \
216
 
    int x,y;                                                                  \
217
 
    int i,j;                                                                  \
218
 
    int hx=0,hy,vx=0,vy;                                                      \
219
 
    int hyflag;                                                               \
220
 
    uint##bpp##_t *seg;                                                       \
221
 
    uint##bpp##_t *line;                                                      \
222
 
    int hw,hh,vw,vh;                                                          \
223
 
    int thex,they,thew,theh;                                                  \
224
 
    int numsubs = 0;                                                          \
225
 
    int newLen;                                                               \
226
 
    uint##bpp##_t bg = (uint##bpp##_t)getBgColour((char*)data,w*h,bpp);       \
227
 
                                                                              \
228
 
    *((uint##bpp##_t*)rreAfterBuf) = bg;                                      \
229
 
                                                                              \
230
 
    rreAfterBufLen = (bpp/8);                                                 \
231
 
                                                                              \
232
 
    for (y=0; y<h; y++) {                                                     \
233
 
      line = data+(y*w);                                                      \
234
 
      for (x=0; x<w; x++) {                                                   \
235
 
        if (line[x] != bg) {                                                  \
236
 
          cl = line[x];                                                       \
237
 
          hy = y-1;                                                           \
238
 
          hyflag = 1;                                                         \
239
 
          for (j=y; j<h; j++) {                                               \
240
 
            seg = data+(j*w);                                                 \
241
 
            if (seg[x] != cl) {break;}                                        \
242
 
            i = x;                                                            \
243
 
            while ((seg[i] == cl) && (i < w)) i += 1;                         \
244
 
            i -= 1;                                                           \
245
 
            if (j == y) vx = hx = i;                                          \
246
 
            if (i < vx) vx = i;                                               \
247
 
            if ((hyflag > 0) && (i >= hx)) {hy += 1;} else {hyflag = 0;}      \
248
 
          }                                                                   \
249
 
          vy = j-1;                                                           \
250
 
                                                                              \
251
 
          /*  We now have two possible subrects: (x,y,hx,hy) and (x,y,vx,vy)  \
252
 
           *  We'll choose the bigger of the two.                             \
253
 
           */                                                                 \
254
 
          hw = hx-x+1;                                                        \
255
 
          hh = hy-y+1;                                                        \
256
 
          vw = vx-x+1;                                                        \
257
 
          vh = vy-y+1;                                                        \
258
 
                                                                              \
259
 
          thex = x;                                                           \
260
 
          they = y;                                                           \
261
 
                                                                              \
262
 
          if ((hw*hh) > (vw*vh)) {                                            \
263
 
            thew = hw;                                                        \
264
 
            theh = hh;                                                        \
265
 
          } else {                                                            \
266
 
            thew = vw;                                                        \
267
 
            theh = vh;                                                        \
268
 
          }                                                                   \
269
 
                                                                              \
270
 
          subrect.x = thex;                                                   \
271
 
          subrect.y = they;                                                   \
272
 
          subrect.w = thew;                                                   \
273
 
          subrect.h = theh;                                                   \
274
 
                                                                              \
275
 
          newLen = rreAfterBufLen + (bpp/8) + sz_rfbCoRRERectangle;           \
276
 
          if ((newLen > (w * h * (bpp/8))) || (newLen > rreAfterBufSize))     \
277
 
            return -1;                                                        \
278
 
                                                                              \
279
 
          numsubs += 1;                                                       \
280
 
          *((uint##bpp##_t*)(rreAfterBuf + rreAfterBufLen)) = cl;                 \
281
 
          rreAfterBufLen += (bpp/8);                                          \
282
 
          memcpy(&rreAfterBuf[rreAfterBufLen],&subrect,sz_rfbCoRRERectangle); \
283
 
          rreAfterBufLen += sz_rfbCoRRERectangle;                             \
284
 
                                                                              \
285
 
          /*                                                                  \
286
 
           * Now mark the subrect as done.                                    \
287
 
           */                                                                 \
288
 
          for (j=they; j < (they+theh); j++) {                                \
289
 
            for (i=thex; i < (thex+thew); i++) {                              \
290
 
              data[j*w+i] = bg;                                               \
291
 
            }                                                                 \
292
 
          }                                                                   \
293
 
        }                                                                     \
294
 
      }                                                                       \
295
 
    }                                                                         \
296
 
                                                                              \
297
 
    return numsubs;                                                           \
298
 
}
299
 
 
300
 
DEFINE_SUBRECT_ENCODE(8)
301
 
DEFINE_SUBRECT_ENCODE(16)
302
 
DEFINE_SUBRECT_ENCODE(32)
303
 
 
304
 
 
305
 
/*
306
 
 * getBgColour() gets the most prevalent colour in a byte array.
307
 
 */
308
 
static uint32_t
309
 
getBgColour(data,size,bpp)
310
 
    char *data;
311
 
    int size;
312
 
    int bpp;
313
 
{
314
 
    
315
 
#define NUMCLRS 256
316
 
  
317
 
  static int counts[NUMCLRS];
318
 
  int i,j,k;
319
 
 
320
 
  int maxcount = 0;
321
 
  uint8_t maxclr = 0;
322
 
 
323
 
  if (bpp != 8) {
324
 
    if (bpp == 16) {
325
 
      return ((uint16_t *)data)[0];
326
 
    } else if (bpp == 32) {
327
 
      return ((uint32_t *)data)[0];
328
 
    } else {
329
 
      rfbLog("getBgColour: bpp %d?\n",bpp);
330
 
      return 0;
331
 
    }
332
 
  }
333
 
 
334
 
  for (i=0; i<NUMCLRS; i++) {
335
 
    counts[i] = 0;
336
 
  }
337
 
 
338
 
  for (j=0; j<size; j++) {
339
 
    k = (int)(((uint8_t *)data)[j]);
340
 
    if (k >= NUMCLRS) {
341
 
      rfbLog("getBgColour: unusual colour = %d\n", k);
342
 
      return 0;
343
 
    }
344
 
    counts[k] += 1;
345
 
    if (counts[k] > maxcount) {
346
 
      maxcount = counts[k];
347
 
      maxclr = ((uint8_t *)data)[j];
348
 
    }
349
 
  }
350
 
  
351
 
  return maxclr;
352
 
}