+++ /dev/null
-/*
- * Copyright (C) 2005 Johannes E. Schindelin. All Rights Reserved.
- *
- * This is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this software; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
- * USA.
- */
-
-#ifdef LIBVNCSERVER_HAVE_LIBZ
-
-/*
- * zrle.c - handle zrle encoding.
- *
- * This file shouldn't be compiled directly. It is included multiple times by
- * rfbproto.c, each time with a different definition of the macro BPP. For
- * each value of BPP, this file defines a function which handles an zrle
- * encoded rectangle with BPP bits per pixel.
- */
-
-#ifndef REALBPP
-#define REALBPP BPP
-#endif
-
-#if !defined(UNCOMP) || UNCOMP==0
-#define HandleZRLE CONCAT2E(HandleZRLE,REALBPP)
-#define HandleZRLETile CONCAT2E(HandleZRLETile,REALBPP)
-#elif UNCOMP>0
-#define HandleZRLE CONCAT3E(HandleZRLE,REALBPP,Down)
-#define HandleZRLETile CONCAT3E(HandleZRLETile,REALBPP,Down)
-#else
-#define HandleZRLE CONCAT3E(HandleZRLE,REALBPP,Up)
-#define HandleZRLETile CONCAT3E(HandleZRLETile,REALBPP,Up)
-#endif
-#define CARDBPP CONCAT3E(uint,BPP,_t)
-#define CARDREALBPP CONCAT3E(uint,REALBPP,_t)
-
-#define ENDIAN_LITTLE 0
-#define ENDIAN_BIG 1
-#define ENDIAN_NO 2
-#define ZYWRLE_ENDIAN ENDIAN_LITTLE
-#undef END_FIX
-#if ZYWRLE_ENDIAN == ENDIAN_LITTLE
-# define END_FIX LE
-#elif ZYWRLE_ENDIAN == ENDIAN_BIG
-# define END_FIX BE
-#else
-# define END_FIX NE
-#endif
-#define __RFB_CONCAT3E(a,b,c) CONCAT3E(a,b,c)
-#define __RFB_CONCAT2E(a,b) CONCAT2E(a,b)
-#undef CPIXEL
-#if REALBPP != BPP
-#if UNCOMP == 0
-#define CPIXEL REALBPP
-#elif UNCOMP>0
-#define CPIXEL CONCAT2E(REALBPP,Down)
-#else
-#define CPIXEL CONCAT2E(REALBPP,Up)
-#endif
-#endif
-#define PIXEL_T __RFB_CONCAT3E(uint,BPP,_t)
-#if BPP!=8
-#define ZYWRLE_DECODE 1
-#include "../libvncserver/zywrletemplate.c"
-#endif
-#undef CPIXEL
-
-static int HandleZRLETile(rfbClient* client,
- uint8_t* buffer,size_t buffer_length,
- int x,int y,int w,int h);
-
-static rfbBool
-HandleZRLE (rfbClient* client, int rx, int ry, int rw, int rh)
-{
- rfbZRLEHeader header;
- int remaining;
- int inflateResult;
- int toRead;
- int min_buffer_size = rw * rh * (REALBPP / 8) * 2;
-
- /* First make sure we have a large enough raw buffer to hold the
- * decompressed data. In practice, with a fixed REALBPP, fixed frame
- * buffer size and the first update containing the entire frame
- * buffer, this buffer allocation should only happen once, on the
- * first update.
- */
- if ( client->raw_buffer_size < min_buffer_size) {
-
- if ( client->raw_buffer != NULL ) {
-
- free( client->raw_buffer );
-
- }
-
- client->raw_buffer_size = min_buffer_size;
- client->raw_buffer = (char*) malloc( client->raw_buffer_size );
-
- }
-
- if (!ReadFromRFBServer(client, (char *)&header, sz_rfbZRLEHeader))
- return FALSE;
-
- remaining = rfbClientSwap32IfLE(header.length);
-
- /* Need to initialize the decompressor state. */
- client->decompStream.next_in = ( Bytef * )client->buffer;
- client->decompStream.avail_in = 0;
- client->decompStream.next_out = ( Bytef * )client->raw_buffer;
- client->decompStream.avail_out = client->raw_buffer_size;
- client->decompStream.data_type = Z_BINARY;
-
- /* Initialize the decompression stream structures on the first invocation. */
- if ( client->decompStreamInited == FALSE ) {
-
- inflateResult = inflateInit( &client->decompStream );
-
- if ( inflateResult != Z_OK ) {
- rfbClientLog(
- "inflateInit returned error: %d, msg: %s\n",
- inflateResult,
- client->decompStream.msg);
- return FALSE;
- }
-
- client->decompStreamInited = TRUE;
-
- }
-
- inflateResult = Z_OK;
-
- /* Process buffer full of data until no more to process, or
- * some type of inflater error, or Z_STREAM_END.
- */
- while (( remaining > 0 ) &&
- ( inflateResult == Z_OK )) {
-
- if ( remaining > RFB_BUFFER_SIZE ) {
- toRead = RFB_BUFFER_SIZE;
- }
- else {
- toRead = remaining;
- }
-
- /* Fill the buffer, obtaining data from the server. */
- if (!ReadFromRFBServer(client, client->buffer,toRead))
- return FALSE;
-
- client->decompStream.next_in = ( Bytef * )client->buffer;
- client->decompStream.avail_in = toRead;
-
- /* Need to uncompress buffer full. */
- inflateResult = inflate( &client->decompStream, Z_SYNC_FLUSH );
-
- /* We never supply a dictionary for compression. */
- if ( inflateResult == Z_NEED_DICT ) {
- rfbClientLog("zlib inflate needs a dictionary!\n");
- return FALSE;
- }
- if ( inflateResult < 0 ) {
- rfbClientLog(
- "zlib inflate returned error: %d, msg: %s\n",
- inflateResult,
- client->decompStream.msg);
- return FALSE;
- }
-
- /* Result buffer allocated to be at least large enough. We should
- * never run out of space!
- */
- if (( client->decompStream.avail_in > 0 ) &&
- ( client->decompStream.avail_out <= 0 )) {
- rfbClientLog("zlib inflate ran out of space!\n");
- return FALSE;
- }
-
- remaining -= toRead;
-
- } /* while ( remaining > 0 ) */
-
- if ( inflateResult == Z_OK ) {
- void* buf=client->raw_buffer;
- int i,j;
-
- remaining = client->raw_buffer_size-client->decompStream.avail_out;
-
- for(j=0; j<rh; j+=rfbZRLETileHeight)
- for(i=0; i<rw; i+=rfbZRLETileWidth) {
- int subWidth=(i+rfbZRLETileWidth>rw)?rw-i:rfbZRLETileWidth;
- int subHeight=(j+rfbZRLETileHeight>rh)?rh-j:rfbZRLETileHeight;
- int result=HandleZRLETile(client,buf,remaining,rx+i,ry+j,subWidth,subHeight);
-
- if(result<0) {
- rfbClientLog("ZRLE decoding failed (%d)\n",result);
-return TRUE;
- return FALSE;
- }
-
- buf+=result;
- remaining-=result;
- }
- }
- else {
-
- rfbClientLog(
- "zlib inflate returned error: %d, msg: %s\n",
- inflateResult,
- client->decompStream.msg);
- return FALSE;
-
- }
-
- return TRUE;
-}
-
-#if REALBPP!=BPP && defined(UNCOMP) && UNCOMP!=0
-#if UNCOMP>0
-#define UncompressCPixel(pointer) ((*(CARDBPP*)pointer)>>UNCOMP)
-#else
-#define UncompressCPixel(pointer) ((*(CARDBPP*)pointer)<<(-(UNCOMP)))
-#endif
-#else
-#define UncompressCPixel(pointer) (*(CARDBPP*)pointer)
-#endif
-
-static int HandleZRLETile(rfbClient* client,
- uint8_t* buffer,size_t buffer_length,
- int x,int y,int w,int h) {
- uint8_t* buffer_copy = buffer;
- uint8_t* buffer_end = buffer+buffer_length;
- uint8_t type;
- uint8_t zywrle_level = (client->appData.qualityLevel & 0x80) ?
- 0 : (3 - client->appData.qualityLevel / 3);
-
- if(buffer_length<1)
- return -2;
-
- type = *buffer;
- buffer++;
- {
- if( type == 0 ) /* raw */
-#if BPP!=8
- if( zywrle_level > 0 ){
- CARDBPP* pFrame = (CARDBPP*)client->frameBuffer + y*client->width+x;
- int ret;
- client->appData.qualityLevel |= 0x80;
- ret = HandleZRLETile(client, buffer, buffer_end-buffer, x, y, w, h);
- client->appData.qualityLevel &= 0x7F;
- if( ret < 0 ){
- return ret;
- }
- ZYWRLE_SYNTHESIZE( pFrame, pFrame, w, h, client->width, zywrle_level, (int*)client->zlib_buffer );
- buffer += ret;
- }else
-#endif
- {
-#if REALBPP!=BPP
- int i,j;
-
- if(1+w*h*REALBPP/8>buffer_length) {
- rfbClientLog("expected %d bytes, got only %d (%dx%d)\n",1+w*h*REALBPP/8,buffer_length,w,h);
- return -3;
- }
-
- for(j=y*client->width; j<(y+h)*client->width; j+=client->width)
- for(i=x; i<x+w; i++,buffer+=REALBPP/8)
- ((CARDBPP*)client->frameBuffer)[j+i] = UncompressCPixel(buffer);
-#else
- CopyRectangle(client, buffer, x, y, w, h);
- buffer+=w*h*REALBPP/8;
-#endif
- }
- else if( type == 1 ) /* solid */
- {
- CARDBPP color = UncompressCPixel(buffer);
-
- if(1+REALBPP/8>buffer_length)
- return -4;
-
- FillRectangle(client, x, y, w, h, color);
-
- buffer+=REALBPP/8;
-
- }
- else if( (type >= 2)&&(type <= 127) ) /* packed Palette */
- {
- CARDBPP palette[16];
- int i,j,shift,
- bpp=(type>4?(type>16?8:4):(type>2?2:1)),
- mask=(1<<bpp)-1,
- divider=(8/bpp);
-
- if(1+type*REALBPP/8+((w+divider-1)/divider)*h>buffer_length)
- return -5;
-
- /* read palette */
- for(i=0; i<type; i++,buffer+=REALBPP/8)
- palette[i] = UncompressCPixel(buffer);
-
- /* read palettized pixels */
- for(j=y*client->width; j<(y+h)*client->width; j+=client->width) {
- for(i=x,shift=8-bpp; i<x+w; i++) {
- ((CARDBPP*)client->frameBuffer)[j+i] = palette[((*buffer)>>shift)&mask];
- shift-=bpp;
- if(shift<0) {
- shift=8-bpp;
- buffer++;
- }
- }
- if(shift<8-bpp)
- buffer++;
- }
-
- }
- /* case 17 ... 127: not used, but valid */
- else if( type == 128 ) /* plain RLE */
- {
- int i=0,j=0;
- while(j<h) {
- int color,length;
- /* read color */
- if(buffer+REALBPP/8+1>buffer_end)
- return -7;
- color = UncompressCPixel(buffer);
- buffer+=REALBPP/8;
- /* read run length */
- length=1;
- while(*buffer==0xff) {
- if(buffer+1>=buffer_end)
- return -8;
- length+=*buffer;
- buffer++;
- }
- length+=*buffer;
- buffer++;
- while(j<h && length>0) {
- ((CARDBPP*)client->frameBuffer)[(y+j)*client->width+x+i] = color;
- length--;
- i++;
- if(i>=w) {
- i=0;
- j++;
- }
- }
- if(length>0)
- rfbClientLog("Warning: possible ZRLE corruption\n");
- }
-
- }
- else if( type == 129 ) /* unused */
- {
- return -8;
- }
- else if( (type >= 130)&&(type <= 255) ) /* palette RLE */
- {
- CARDBPP palette[128];
- int i,j;
-
- if(2+(type-128)*REALBPP/8>buffer_length)
- return -9;
-
- /* read palette */
- for(i=0; i<type-128; i++,buffer+=REALBPP/8)
- palette[i] = UncompressCPixel(buffer);
- /* read palettized pixels */
- i=j=0;
- while(j<h) {
- int color,length;
- /* read color */
- if(buffer>=buffer_end)
- return -10;
- color = palette[(*buffer)&0x7f];
- length=1;
- if(*buffer&0x80) {
- if(buffer+1>=buffer_end)
- return -11;
- buffer++;
- /* read run length */
- while(*buffer==0xff) {
- if(buffer+1>=buffer_end)
- return -8;
- length+=*buffer;
- buffer++;
- }
- length+=*buffer;
- }
- buffer++;
- while(j<h && length>0) {
- ((CARDBPP*)client->frameBuffer)[(y+j)*client->width+x+i] = color;
- length--;
- i++;
- if(i>=w) {
- i=0;
- j++;
- }
- }
- if(length>0)
- rfbClientLog("Warning: possible ZRLE corruption\n");
- }
- }
- }
-
- return buffer-buffer_copy;
-}
-
-#undef CARDBPP
-#undef CARDREALBPP
-#undef HandleZRLE
-#undef HandleZRLETile
-#undef UncompressCPixel
-#undef REALBPP
-
-#endif
-
-#undef UNCOMP