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 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 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