2 * Copyright (C) 2000 Tridia Corporation. All Rights Reserved.
3 * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
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.
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.
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,
22 * ultrazip.c - handle ultrazip encoding.
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.
30 #define HandleUltraZipBPP CONCAT2E(HandleUltraZip,BPP)
31 #define HandleUltraBPP CONCAT2E(HandleUltra,BPP)
32 #define CARDBPP CONCAT3E(uint,BPP,_t)
35 HandleUltraBPP (rfbClient
* client
, int rx
, int ry
, int rw
, int rh
)
40 lzo_uint uncompressedBytes
= (( rw
* rh
) * ( BPP
/ 8 ));
42 if (!ReadFromRFBServer(client
, (char *)&hdr
, sz_rfbZlibHeader
))
45 toRead
= rfbClientSwap32IfLE(hdr
.nBytes
);
46 if (toRead
==0) return TRUE
;
48 if (uncompressedBytes
==0)
50 rfbClientLog("ultra error: rectangle has 0 uncomressed bytes ((%dw * %dh) * (%d / 8))\n", rw
, rh
, BPP
);
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
60 if ( client
->raw_buffer_size
< (int)uncompressedBytes
) {
61 if ( client
->raw_buffer
!= NULL
) {
62 free( client
->raw_buffer
);
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
);
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
);
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
);
83 /* Fill the buffer, obtaining data from the server. */
84 if (!ReadFromRFBServer(client
, client
->ultra_buffer
, toRead
))
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
,
95 if ((rw
* rh
* (BPP
/ 8)) != uncompressedBytes
)
96 rfbClientLog("Ultra decompressed too little (%d < %d)", (rw
* rh
* (BPP
/ 8)), uncompressedBytes
);
98 /* Put the uncompressed contents of the update on the screen. */
99 if ( inflateResult
== LZO_E_OK
)
101 CopyRectangle(client
, (unsigned char *)client
->raw_buffer
, rx
, ry
, rw
, rh
);
105 rfbClientLog("ultra decompress returned error: %d\n",
113 /* UltraZip is like rre in that it is composed of subrects */
115 HandleUltraZipBPP (rfbClient
* client
, int rx
, int ry
, int rw
, int rh
)
121 unsigned char *ptr
=NULL
;
122 lzo_uint uncompressedBytes
= ry
+ (rw
* 65535);
123 unsigned int numCacheRects
= rx
;
125 if (!ReadFromRFBServer(client
, (char *)&hdr
, sz_rfbZlibHeader
))
128 toRead
= rfbClientSwap32IfLE(hdr
.nBytes
);
130 if (toRead
==0) return TRUE
;
132 if (uncompressedBytes
==0)
134 rfbClientLog("ultrazip error: rectangle has 0 uncomressed bytes (%dy + (%dw * 65535)) (%d rectangles)\n", ry
, rw
, rx
);
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
144 if ( client
->raw_buffer_size
< (int)(uncompressedBytes
+ 500)) {
145 if ( client
->raw_buffer
!= NULL
) {
146 free( client
->raw_buffer
);
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
);
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
);
161 client
->ultra_buffer_size
= toRead
;
162 client
->ultra_buffer
= (char*) malloc( client
->ultra_buffer_size
);
165 /* Fill the buffer, obtaining data from the server. */
166 if (!ReadFromRFBServer(client
, client
->ultra_buffer
, toRead
))
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
)
176 rfbClientLog("ultra decompress returned error: %d\n",
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
++)
185 unsigned short sx
, sy
, sw
, sh
;
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;
194 sx
= rfbClientSwap16IfLE(sx
);
195 sy
= rfbClientSwap16IfLE(sy
);
196 sw
= rfbClientSwap16IfLE(sw
);
197 sh
= rfbClientSwap16IfLE(sh
);
198 se
= rfbClientSwap32IfLE(se
);
200 if (se
== rfbEncodingRaw
)
202 CopyRectangle(client
, (unsigned char *)ptr
, sx
, sy
, sw
, sh
);
203 ptr
+= ((sw
* sh
) * (BPP
/ 8));