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 #define GET_IMAGE_INTO_BUF(tx,ty,tw,th,buf) \
33 { char *fbptr = (cl->scaledScreen->frameBuffer \
34 + (cl->scaledScreen->paddedWidthInBytes * ty) \
35 + (tx * (cl->scaledScreen->bitsPerPixel / 8))); \
36 \
37 (*cl->translateFn)(cl->translateLookupTable, &cl->screen->serverFormat,\
38 &cl->format, fbptr, (char*)buf, \
39 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 #define BPP 8
47 #define ZYWRLE_ENDIAN ENDIAN_NO
48 #include <zrleencodetemplate.c>
49 #undef BPP
50 #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 #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 #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
rfbSendRectEncodingZRLE(rfbClientPtr cl,int x,int y,int w,int h)104 rfbBool rfbSendRectEncodingZRLE(rfbClientPtr cl, int x, int y, int w, int h)
105 {
106 zrleOutStream* zos;
107 rfbFramebufferUpdateRectHeader rect;
108 rfbZRLEHeader hdr;
109 int i;
110 char *zrleBeforeBuf;
111
112 if (cl->zrleBeforeBuf == NULL) {
113 cl->zrleBeforeBuf = (char *) malloc(rfbZRLETileWidth * rfbZRLETileHeight * 4 + 4);
114 }
115 zrleBeforeBuf = cl->zrleBeforeBuf;
116
117 if (cl->preferredEncoding == rfbEncodingZYWRLE) {
118 if (cl->tightQualityLevel < 0) {
119 cl->zywrleLevel = 1;
120 } else if (cl->tightQualityLevel < 3) {
121 cl->zywrleLevel = 3;
122 } else if (cl->tightQualityLevel < 6) {
123 cl->zywrleLevel = 2;
124 } else {
125 cl->zywrleLevel = 1;
126 }
127 } else
128 cl->zywrleLevel = 0;
129
130 if (!cl->zrleData)
131 cl->zrleData = zrleOutStreamNew();
132 zos = cl->zrleData;
133 zos->in.ptr = zos->in.start;
134 zos->out.ptr = zos->out.start;
135
136 switch (cl->format.bitsPerPixel) {
137
138 case 8:
139 zrleEncode8NE(x, y, w, h, zos, zrleBeforeBuf, cl);
140 break;
141
142 case 16:
143 if (cl->format.greenMax > 0x1F) {
144 if (cl->format.bigEndian)
145 zrleEncode16BE(x, y, w, h, zos, zrleBeforeBuf, cl);
146 else
147 zrleEncode16LE(x, y, w, h, zos, zrleBeforeBuf, cl);
148 } else {
149 if (cl->format.bigEndian)
150 zrleEncode15BE(x, y, w, h, zos, zrleBeforeBuf, cl);
151 else
152 zrleEncode15LE(x, y, w, h, zos, zrleBeforeBuf, cl);
153 }
154 break;
155
156 case 32: {
157 rfbBool fitsInLS3Bytes
158 = ((cl->format.redMax << cl->format.redShift) < (1<<24) &&
159 (cl->format.greenMax << cl->format.greenShift) < (1<<24) &&
160 (cl->format.blueMax << cl->format.blueShift) < (1<<24));
161
162 rfbBool fitsInMS3Bytes = (cl->format.redShift > 7 &&
163 cl->format.greenShift > 7 &&
164 cl->format.blueShift > 7);
165
166 if ((fitsInLS3Bytes && !cl->format.bigEndian) ||
167 (fitsInMS3Bytes && cl->format.bigEndian)) {
168 if (cl->format.bigEndian)
169 zrleEncode24ABE(x, y, w, h, zos, zrleBeforeBuf, cl);
170 else
171 zrleEncode24ALE(x, y, w, h, zos, zrleBeforeBuf, cl);
172 }
173 else if ((fitsInLS3Bytes && cl->format.bigEndian) ||
174 (fitsInMS3Bytes && !cl->format.bigEndian)) {
175 if (cl->format.bigEndian)
176 zrleEncode24BBE(x, y, w, h, zos, zrleBeforeBuf, cl);
177 else
178 zrleEncode24BLE(x, y, w, h, zos, zrleBeforeBuf, cl);
179 }
180 else {
181 if (cl->format.bigEndian)
182 zrleEncode32BE(x, y, w, h, zos, zrleBeforeBuf, cl);
183 else
184 zrleEncode32LE(x, y, w, h, zos, zrleBeforeBuf, cl);
185 }
186 }
187 break;
188 }
189
190 rfbStatRecordEncodingSent(cl, rfbEncodingZRLE, sz_rfbFramebufferUpdateRectHeader + sz_rfbZRLEHeader + ZRLE_BUFFER_LENGTH(&zos->out),
191 + w * (cl->format.bitsPerPixel / 8) * h);
192
193 if (cl->ublen + sz_rfbFramebufferUpdateRectHeader + sz_rfbZRLEHeader
194 > UPDATE_BUF_SIZE)
195 {
196 if (!rfbSendUpdateBuf(cl))
197 return FALSE;
198 }
199
200 rect.r.x = Swap16IfLE(x);
201 rect.r.y = Swap16IfLE(y);
202 rect.r.w = Swap16IfLE(w);
203 rect.r.h = Swap16IfLE(h);
204 rect.encoding = Swap32IfLE(cl->preferredEncoding);
205
206 memcpy(cl->updateBuf+cl->ublen, (char *)&rect,
207 sz_rfbFramebufferUpdateRectHeader);
208 cl->ublen += sz_rfbFramebufferUpdateRectHeader;
209
210 hdr.length = Swap32IfLE(ZRLE_BUFFER_LENGTH(&zos->out));
211
212 memcpy(cl->updateBuf+cl->ublen, (char *)&hdr, sz_rfbZRLEHeader);
213 cl->ublen += sz_rfbZRLEHeader;
214
215 /* copy into updateBuf and send from there. Maybe should send directly? */
216
217 for (i = 0; i < ZRLE_BUFFER_LENGTH(&zos->out);) {
218
219 int bytesToCopy = UPDATE_BUF_SIZE - cl->ublen;
220
221 if (i + bytesToCopy > ZRLE_BUFFER_LENGTH(&zos->out)) {
222 bytesToCopy = ZRLE_BUFFER_LENGTH(&zos->out) - i;
223 }
224
225 memcpy(cl->updateBuf+cl->ublen, (uint8_t*)zos->out.start + i, bytesToCopy);
226
227 cl->ublen += bytesToCopy;
228 i += bytesToCopy;
229
230 if (cl->ublen == UPDATE_BUF_SIZE) {
231 if (!rfbSendUpdateBuf(cl))
232 return FALSE;
233 }
234 }
235
236 return TRUE;
237 }
238
239
rfbFreeZrleData(rfbClientPtr cl)240 void rfbFreeZrleData(rfbClientPtr cl)
241 {
242 if (cl->zrleData) {
243 zrleOutStreamFree(cl->zrleData);
244 }
245 cl->zrleData = NULL;
246
247 if (cl->zrleBeforeBuf) {
248 free(cl->zrleBeforeBuf);
249 }
250 cl->zrleBeforeBuf = NULL;
251
252 if (cl->paletteHelper) {
253 free(cl->paletteHelper);
254 }
255 cl->paletteHelper = NULL;
256 }
257
258