1 /* 2 * Copyright (C) 2000 Tridia Corporation. All Rights Reserved. 3 * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. 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 * ultrazip.c - handle ultrazip encoding. 23 * 24 * This file shouldn't be compiled directly. It is included multiple times by 25 * rfbproto.c, each time with a different definition of the macro BPP. For 26 * each value of BPP, this file defines a function which handles an zlib 27 * encoded rectangle with BPP bits per pixel. 28 */ 29 30 #define HandleUltraZipBPP CONCAT2E(HandleUltraZip,BPP) 31 #define HandleUltraBPP CONCAT2E(HandleUltra,BPP) 32 #define CARDBPP CONCAT3E(uint,BPP,_t) 33 34 static rfbBool 35 HandleUltraBPP (rfbClient* client, int rx, int ry, int rw, int rh) 36 { 37 rfbZlibHeader hdr; 38 int toRead=0; 39 int inflateResult=0; 40 lzo_uint uncompressedBytes = (( rw * rh ) * ( BPP / 8 )); 41 42 if (!ReadFromRFBServer(client, (char *)&hdr, sz_rfbZlibHeader)) 43 return FALSE; 44 45 toRead = rfbClientSwap32IfLE(hdr.nBytes); 46 if (toRead==0) return TRUE; 47 48 if (uncompressedBytes==0) 49 { 50 rfbClientLog("ultra error: rectangle has 0 uncomressed bytes ((%dw * %dh) * (%d / 8))\n", rw, rh, BPP); 51 return FALSE; 52 } 53 54 /* First make sure we have a large enough raw buffer to hold the 55 * decompressed data. In practice, with a fixed BPP, fixed frame 56 * buffer size and the first update containing the entire frame 57 * buffer, this buffer allocation should only happen once, on the 58 * first update. 59 */ 60 if ( client->raw_buffer_size < (int)uncompressedBytes) { 61 if ( client->raw_buffer != NULL ) { 62 free( client->raw_buffer ); 63 } 64 client->raw_buffer_size = uncompressedBytes; 65 /* buffer needs to be aligned on 4-byte boundaries */ 66 if ((client->raw_buffer_size % 4)!=0) 67 client->raw_buffer_size += (4-(client->raw_buffer_size % 4)); 68 client->raw_buffer = (char*) malloc( client->raw_buffer_size ); 69 } 70 71 /* allocate enough space to store the incoming compressed packet */ 72 if ( client->ultra_buffer_size < toRead ) { 73 if ( client->ultra_buffer != NULL ) { 74 free( client->ultra_buffer ); 75 } 76 client->ultra_buffer_size = toRead; 77 /* buffer needs to be aligned on 4-byte boundaries */ 78 if ((client->ultra_buffer_size % 4)!=0) 79 client->ultra_buffer_size += (4-(client->ultra_buffer_size % 4)); 80 client->ultra_buffer = (char*) malloc( client->ultra_buffer_size ); 81 } 82 83 /* Fill the buffer, obtaining data from the server. */ 84 if (!ReadFromRFBServer(client, client->ultra_buffer, toRead)) 85 return FALSE; 86 87 /* uncompress the data */ 88 uncompressedBytes = client->raw_buffer_size; 89 inflateResult = lzo1x_decompress( 90 (lzo_byte *)client->ultra_buffer, toRead, 91 (lzo_byte *)client->raw_buffer, (lzo_uintp) &uncompressedBytes, 92 NULL); 93 94 95 if ((rw * rh * (BPP / 8)) != uncompressedBytes) 96 rfbClientLog("Ultra decompressed too little (%d < %d)", (rw * rh * (BPP / 8)), uncompressedBytes); 97 98 /* Put the uncompressed contents of the update on the screen. */ 99 if ( inflateResult == LZO_E_OK ) 100 { 101 CopyRectangle(client, (unsigned char *)client->raw_buffer, rx, ry, rw, rh); 102 } 103 else 104 { 105 rfbClientLog("ultra decompress returned error: %d\n", 106 inflateResult); 107 return FALSE; 108 } 109 return TRUE; 110 } 111 112 113 /* UltraZip is like rre in that it is composed of subrects */ 114 static rfbBool 115 HandleUltraZipBPP (rfbClient* client, int rx, int ry, int rw, int rh) 116 { 117 rfbZlibHeader hdr; 118 int i=0; 119 int toRead=0; 120 int inflateResult=0; 121 unsigned char *ptr=NULL; 122 lzo_uint uncompressedBytes = ry + (rw * 65535); 123 unsigned int numCacheRects = rx; 124 125 if (!ReadFromRFBServer(client, (char *)&hdr, sz_rfbZlibHeader)) 126 return FALSE; 127 128 toRead = rfbClientSwap32IfLE(hdr.nBytes); 129 130 if (toRead==0) return TRUE; 131 132 if (uncompressedBytes==0) 133 { 134 rfbClientLog("ultrazip error: rectangle has 0 uncomressed bytes (%dy + (%dw * 65535)) (%d rectangles)\n", ry, rw, rx); 135 return FALSE; 136 } 137 138 /* First make sure we have a large enough raw buffer to hold the 139 * decompressed data. In practice, with a fixed BPP, fixed frame 140 * buffer size and the first update containing the entire frame 141 * buffer, this buffer allocation should only happen once, on the 142 * first update. 143 */ 144 if ( client->raw_buffer_size < (int)(uncompressedBytes + 500)) { 145 if ( client->raw_buffer != NULL ) { 146 free( client->raw_buffer ); 147 } 148 client->raw_buffer_size = uncompressedBytes + 500; 149 /* buffer needs to be aligned on 4-byte boundaries */ 150 if ((client->raw_buffer_size % 4)!=0) 151 client->raw_buffer_size += (4-(client->raw_buffer_size % 4)); 152 client->raw_buffer = (char*) malloc( client->raw_buffer_size ); 153 } 154 155 156 /* allocate enough space to store the incoming compressed packet */ 157 if ( client->ultra_buffer_size < toRead ) { 158 if ( client->ultra_buffer != NULL ) { 159 free( client->ultra_buffer ); 160 } 161 client->ultra_buffer_size = toRead; 162 client->ultra_buffer = (char*) malloc( client->ultra_buffer_size ); 163 } 164 165 /* Fill the buffer, obtaining data from the server. */ 166 if (!ReadFromRFBServer(client, client->ultra_buffer, toRead)) 167 return FALSE; 168 169 /* uncompress the data */ 170 uncompressedBytes = client->raw_buffer_size; 171 inflateResult = lzo1x_decompress( 172 (lzo_byte *)client->ultra_buffer, toRead, 173 (lzo_byte *)client->raw_buffer, &uncompressedBytes, NULL); 174 if ( inflateResult != LZO_E_OK ) 175 { 176 rfbClientLog("ultra decompress returned error: %d\n", 177 inflateResult); 178 return FALSE; 179 } 180 181 /* Put the uncompressed contents of the update on the screen. */ 182 ptr = (unsigned char *)client->raw_buffer; 183 for (i=0; i<numCacheRects; i++) 184 { 185 unsigned short sx, sy, sw, sh; 186 unsigned int se; 187 188 memcpy((char *)&sx, ptr, 2); ptr += 2; 189 memcpy((char *)&sy, ptr, 2); ptr += 2; 190 memcpy((char *)&sw, ptr, 2); ptr += 2; 191 memcpy((char *)&sh, ptr, 2); ptr += 2; 192 memcpy((char *)&se, ptr, 4); ptr += 4; 193 194 sx = rfbClientSwap16IfLE(sx); 195 sy = rfbClientSwap16IfLE(sy); 196 sw = rfbClientSwap16IfLE(sw); 197 sh = rfbClientSwap16IfLE(sh); 198 se = rfbClientSwap32IfLE(se); 199 200 if (se == rfbEncodingRaw) 201 { 202 CopyRectangle(client, (unsigned char *)ptr, sx, sy, sw, sh); 203 ptr += ((sw * sh) * (BPP / 8)); 204 } 205 } 206 207 return TRUE; 208 } 209 210 #undef CARDBPP 211