Coverage Report

Created: 2025-11-11 06:04

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libvncserver/src/libvncserver/zrle.c
Line
Count
Source
1
/*
2
 * Copyright (C) 2002 RealVNC Ltd.  All Rights Reserved.
3
 * Copyright (C) 2003 Sun Microsystems, Inc.
4
 *
5
 * This is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License as published by
7
 * the Free Software Foundation; either version 2 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * This software is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this software; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
18
 * USA.
19
 */
20
21
/*
22
 * zrle.c
23
 *
24
 * Routines to implement Zlib Run-length Encoding (ZRLE).
25
 */
26
27
#include "rfb/rfb.h"
28
#include "private.h"
29
#include "zrleoutstream.h"
30
31
32
0
#define GET_IMAGE_INTO_BUF(tx,ty,tw,th,buf)                                \
33
0
{  char *fbptr = (cl->scaledScreen->frameBuffer                                   \
34
0
     + (cl->scaledScreen->paddedWidthInBytes * ty)                   \
35
0
                 + (tx * (cl->scaledScreen->bitsPerPixel / 8)));                 \
36
0
                                                                           \
37
0
  (*cl->translateFn)(cl->translateLookupTable, &cl->screen->serverFormat,\
38
0
                     &cl->format, fbptr, (char*)buf,                       \
39
0
                     cl->scaledScreen->paddedWidthInBytes, tw, th); }
40
41
#define EXTRA_ARGS , rfbClientPtr cl
42
43
#define ENDIAN_LITTLE 0
44
#define ENDIAN_BIG 1
45
#define ENDIAN_NO 2
46
0
#define BPP 8
47
#define ZYWRLE_ENDIAN ENDIAN_NO
48
#include "zrleencodetemplate.c"
49
#undef BPP
50
0
#define BPP 15
51
#undef ZYWRLE_ENDIAN
52
#define ZYWRLE_ENDIAN ENDIAN_LITTLE
53
#include "zrleencodetemplate.c"
54
#undef ZYWRLE_ENDIAN
55
#define ZYWRLE_ENDIAN ENDIAN_BIG
56
#include "zrleencodetemplate.c"
57
#undef BPP
58
0
#define BPP 16
59
#undef ZYWRLE_ENDIAN
60
#define ZYWRLE_ENDIAN ENDIAN_LITTLE
61
#include "zrleencodetemplate.c"
62
#undef ZYWRLE_ENDIAN
63
#define ZYWRLE_ENDIAN ENDIAN_BIG
64
#include "zrleencodetemplate.c"
65
#undef BPP
66
0
#define BPP 32
67
#undef ZYWRLE_ENDIAN
68
#define ZYWRLE_ENDIAN ENDIAN_LITTLE
69
#include "zrleencodetemplate.c"
70
#undef ZYWRLE_ENDIAN
71
#define ZYWRLE_ENDIAN ENDIAN_BIG
72
#include "zrleencodetemplate.c"
73
#define CPIXEL 24A
74
#undef ZYWRLE_ENDIAN
75
#define ZYWRLE_ENDIAN ENDIAN_LITTLE
76
#include "zrleencodetemplate.c"
77
#undef ZYWRLE_ENDIAN
78
#define ZYWRLE_ENDIAN ENDIAN_BIG
79
#include "zrleencodetemplate.c"
80
#undef CPIXEL
81
#define CPIXEL 24B
82
#undef ZYWRLE_ENDIAN
83
#define ZYWRLE_ENDIAN ENDIAN_LITTLE
84
#include "zrleencodetemplate.c"
85
#undef ZYWRLE_ENDIAN
86
#define ZYWRLE_ENDIAN ENDIAN_BIG
87
#include "zrleencodetemplate.c"
88
#undef CPIXEL
89
#undef BPP
90
91
92
/*
93
 * zrleBeforeBuf contains pixel data in the client's format.  It must be at
94
 * least one pixel bigger than the largest tile of pixel data, since the
95
 * ZRLE encoding algorithm writes to the position one past the end of the pixel
96
 * data.
97
 */
98
99
100
/*
101
 * rfbSendRectEncodingZRLE - send a given rectangle using ZRLE encoding.
102
 */
103
104
rfbBool rfbSendRectEncodingZRLE(rfbClientPtr cl, int x, int y, int w, int h)
105
0
{
106
0
  zrleOutStream* zos;
107
0
  rfbFramebufferUpdateRectHeader rect;
108
0
  rfbZRLEHeader hdr;
109
0
  int i;
110
0
  char *zrleBeforeBuf;
111
112
0
  if (cl->zrleBeforeBuf == NULL) {
113
0
  cl->zrleBeforeBuf = (char *) malloc(rfbZRLETileWidth * rfbZRLETileHeight * 4 + 4);
114
0
  }
115
0
  zrleBeforeBuf = cl->zrleBeforeBuf;
116
117
0
  if (cl->preferredEncoding == rfbEncodingZYWRLE) {
118
0
    if (cl->tightQualityLevel < 0) {
119
0
      cl->zywrleLevel = 1;
120
0
    } else if (cl->tightQualityLevel < 3) {
121
0
      cl->zywrleLevel = 3;
122
0
    } else if (cl->tightQualityLevel < 6) {
123
0
      cl->zywrleLevel = 2;
124
0
    } else {
125
0
      cl->zywrleLevel = 1;
126
0
    }
127
0
  } else
128
0
    cl->zywrleLevel = 0;
129
130
0
  if (!cl->zrleData)
131
0
    cl->zrleData = zrleOutStreamNew();
132
0
  zos = cl->zrleData;
133
0
  zos->in.ptr = zos->in.start;
134
0
  zos->out.ptr = zos->out.start;
135
136
0
  switch (cl->format.bitsPerPixel) {
137
138
0
  case 8:
139
0
    zrleEncode8NE(x, y, w, h, zos, zrleBeforeBuf, cl);
140
0
    break;
141
142
0
  case 16:
143
0
  if (cl->format.greenMax > 0x1F) {
144
0
    if (cl->format.bigEndian)
145
0
      zrleEncode16BE(x, y, w, h, zos, zrleBeforeBuf, cl);
146
0
    else
147
0
      zrleEncode16LE(x, y, w, h, zos, zrleBeforeBuf, cl);
148
0
  } else {
149
0
    if (cl->format.bigEndian)
150
0
      zrleEncode15BE(x, y, w, h, zos, zrleBeforeBuf, cl);
151
0
    else
152
0
      zrleEncode15LE(x, y, w, h, zos, zrleBeforeBuf, cl);
153
0
  }
154
0
    break;
155
156
0
  case 32: {
157
0
    rfbBool fitsInLS3Bytes
158
0
      = ((cl->format.redMax   << cl->format.redShift)   < (1<<24) &&
159
0
         (cl->format.greenMax << cl->format.greenShift) < (1<<24) &&
160
0
         (cl->format.blueMax  << cl->format.blueShift)  < (1<<24));
161
162
0
    rfbBool fitsInMS3Bytes = (cl->format.redShift   > 7  &&
163
0
                           cl->format.greenShift > 7  &&
164
0
                           cl->format.blueShift  > 7);
165
166
0
    if ((fitsInLS3Bytes && !cl->format.bigEndian) ||
167
0
        (fitsInMS3Bytes && cl->format.bigEndian)) {
168
0
  if (cl->format.bigEndian)
169
0
    zrleEncode24ABE(x, y, w, h, zos, zrleBeforeBuf, cl);
170
0
  else
171
0
    zrleEncode24ALE(x, y, w, h, zos, zrleBeforeBuf, cl);
172
0
    }
173
0
    else if ((fitsInLS3Bytes && cl->format.bigEndian) ||
174
0
             (fitsInMS3Bytes && !cl->format.bigEndian)) {
175
0
  if (cl->format.bigEndian)
176
0
    zrleEncode24BBE(x, y, w, h, zos, zrleBeforeBuf, cl);
177
0
  else
178
0
    zrleEncode24BLE(x, y, w, h, zos, zrleBeforeBuf, cl);
179
0
    }
180
0
    else {
181
0
  if (cl->format.bigEndian)
182
0
    zrleEncode32BE(x, y, w, h, zos, zrleBeforeBuf, cl);
183
0
  else
184
0
    zrleEncode32LE(x, y, w, h, zos, zrleBeforeBuf, cl);
185
0
    }
186
0
  }
187
0
    break;
188
0
  }
189
190
0
  rfbStatRecordEncodingSent(cl, rfbEncodingZRLE, sz_rfbFramebufferUpdateRectHeader + sz_rfbZRLEHeader + ZRLE_BUFFER_LENGTH(&zos->out),
191
0
      + w * (cl->format.bitsPerPixel / 8) * h);
192
193
0
  if (cl->ublen + sz_rfbFramebufferUpdateRectHeader + sz_rfbZRLEHeader
194
0
      > UPDATE_BUF_SIZE)
195
0
    {
196
0
      if (!rfbSendUpdateBuf(cl))
197
0
        return FALSE;
198
0
    }
199
200
0
  rect.r.x = Swap16IfLE(x);
201
0
  rect.r.y = Swap16IfLE(y);
202
0
  rect.r.w = Swap16IfLE(w);
203
0
  rect.r.h = Swap16IfLE(h);
204
0
  rect.encoding = Swap32IfLE(cl->preferredEncoding);
205
206
0
  memcpy(cl->updateBuf+cl->ublen, (char *)&rect,
207
0
         sz_rfbFramebufferUpdateRectHeader);
208
0
  cl->ublen += sz_rfbFramebufferUpdateRectHeader;
209
210
0
  hdr.length = Swap32IfLE(ZRLE_BUFFER_LENGTH(&zos->out));
211
212
0
  memcpy(cl->updateBuf+cl->ublen, (char *)&hdr, sz_rfbZRLEHeader);
213
0
  cl->ublen += sz_rfbZRLEHeader;
214
215
  /* copy into updateBuf and send from there.  Maybe should send directly? */
216
217
0
  for (i = 0; i < ZRLE_BUFFER_LENGTH(&zos->out);) {
218
219
0
    int bytesToCopy = UPDATE_BUF_SIZE - cl->ublen;
220
221
0
    if (i + bytesToCopy > ZRLE_BUFFER_LENGTH(&zos->out)) {
222
0
      bytesToCopy = ZRLE_BUFFER_LENGTH(&zos->out) - i;
223
0
    }
224
225
0
    memcpy(cl->updateBuf+cl->ublen, (uint8_t*)zos->out.start + i, bytesToCopy);
226
227
0
    cl->ublen += bytesToCopy;
228
0
    i += bytesToCopy;
229
230
0
    if (cl->ublen == UPDATE_BUF_SIZE) {
231
0
      if (!rfbSendUpdateBuf(cl))
232
0
        return FALSE;
233
0
    }
234
0
  }
235
236
0
  return TRUE;
237
0
}
238
239
240
void rfbFreeZrleData(rfbClientPtr cl)
241
2.37k
{
242
2.37k
  if (cl->zrleData) {
243
0
    zrleOutStreamFree(cl->zrleData);
244
0
  }
245
2.37k
  cl->zrleData = NULL;
246
247
2.37k
  if (cl->zrleBeforeBuf) {
248
0
    free(cl->zrleBeforeBuf);
249
0
  }
250
2.37k
  cl->zrleBeforeBuf = NULL;
251
252
2.37k
  if (cl->paletteHelper) {
253
0
    free(cl->paletteHelper);
254
0
  }
255
  cl->paletteHelper = NULL;
256
2.37k
}
257