PageRenderTime 348ms CodeModel.GetById 151ms app.highlight 12ms RepoModel.GetById 183ms app.codeStats 0ms

/apps/desktop/libvncserver/zrle.c

http://ftk.googlecode.com/
C | 183 lines | 111 code | 38 blank | 34 comment | 17 complexity | 8727cc84eaf099afd72ea35789aa216e MD5 | raw file
  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 BPP 8
 44#include <zrleencodetemplate.c>
 45#undef BPP
 46#define BPP 16
 47#include <zrleencodetemplate.c>
 48#undef BPP
 49#define BPP 32
 50#include <zrleencodetemplate.c>
 51#define CPIXEL 24A
 52#include <zrleencodetemplate.c>
 53#undef CPIXEL
 54#define CPIXEL 24B
 55#include <zrleencodetemplate.c>
 56#undef CPIXEL
 57#undef BPP
 58
 59
 60/*
 61 * zrleBeforeBuf contains pixel data in the client's format.  It must be at
 62 * least one pixel bigger than the largest tile of pixel data, since the
 63 * ZRLE encoding algorithm writes to the position one past the end of the pixel
 64 * data.
 65 */
 66
 67static char zrleBeforeBuf[rfbZRLETileWidth * rfbZRLETileHeight * 4 + 4];
 68
 69
 70
 71/*
 72 * rfbSendRectEncodingZRLE - send a given rectangle using ZRLE encoding.
 73 */
 74
 75
 76rfbBool rfbSendRectEncodingZRLE(rfbClientPtr cl, int x, int y, int w, int h)
 77{
 78  zrleOutStream* zos;
 79  rfbFramebufferUpdateRectHeader rect;
 80  rfbZRLEHeader hdr;
 81  int i;
 82
 83  if (!cl->zrleData)
 84    cl->zrleData = zrleOutStreamNew();
 85  zos = cl->zrleData;
 86  zos->in.ptr = zos->in.start;
 87  zos->out.ptr = zos->out.start;
 88
 89  switch (cl->format.bitsPerPixel) {
 90
 91  case 8:
 92    zrleEncode8( x, y, w, h, zos, zrleBeforeBuf, cl);
 93    break;
 94
 95  case 16:
 96    zrleEncode16(x, y, w, h, zos, zrleBeforeBuf, cl);
 97    break;
 98
 99  case 32: {
100    rfbBool fitsInLS3Bytes
101      = ((cl->format.redMax   << cl->format.redShift)   < (1<<24) &&
102         (cl->format.greenMax << cl->format.greenShift) < (1<<24) &&
103         (cl->format.blueMax  << cl->format.blueShift)  < (1<<24));
104
105    rfbBool fitsInMS3Bytes = (cl->format.redShift   > 7  &&
106                           cl->format.greenShift > 7  &&
107                           cl->format.blueShift  > 7);
108
109    if ((fitsInLS3Bytes && !cl->format.bigEndian) ||
110        (fitsInMS3Bytes && cl->format.bigEndian))
111    {
112      zrleEncode24A(x, y, w, h, zos, zrleBeforeBuf, cl);
113    }
114    else if ((fitsInLS3Bytes && cl->format.bigEndian) ||
115             (fitsInMS3Bytes && !cl->format.bigEndian))
116    {
117      zrleEncode24B(x, y, w, h, zos, zrleBeforeBuf, cl);
118    }
119    else
120    {
121      zrleEncode32(x, y, w, h, zos, zrleBeforeBuf, cl);
122    }
123  }
124    break;
125  }
126
127  rfbStatRecordEncodingSent(cl, rfbEncodingZRLE, sz_rfbFramebufferUpdateRectHeader + sz_rfbZRLEHeader + ZRLE_BUFFER_LENGTH(&zos->out),
128      + w * (cl->format.bitsPerPixel / 8) * h);
129
130  if (cl->ublen + sz_rfbFramebufferUpdateRectHeader + sz_rfbZRLEHeader
131      > UPDATE_BUF_SIZE)
132    {
133      if (!rfbSendUpdateBuf(cl))
134        return FALSE;
135    }
136
137  rect.r.x = Swap16IfLE(x);
138  rect.r.y = Swap16IfLE(y);
139  rect.r.w = Swap16IfLE(w);
140  rect.r.h = Swap16IfLE(h);
141  rect.encoding = Swap32IfLE(rfbEncodingZRLE);
142
143  memcpy(cl->updateBuf+cl->ublen, (char *)&rect,
144         sz_rfbFramebufferUpdateRectHeader);
145  cl->ublen += sz_rfbFramebufferUpdateRectHeader;
146
147  hdr.length = Swap32IfLE(ZRLE_BUFFER_LENGTH(&zos->out));
148
149  memcpy(cl->updateBuf+cl->ublen, (char *)&hdr, sz_rfbZRLEHeader);
150  cl->ublen += sz_rfbZRLEHeader;
151
152  /* copy into updateBuf and send from there.  Maybe should send directly? */
153
154  for (i = 0; i < ZRLE_BUFFER_LENGTH(&zos->out);) {
155
156    int bytesToCopy = UPDATE_BUF_SIZE - cl->ublen;
157
158    if (i + bytesToCopy > ZRLE_BUFFER_LENGTH(&zos->out)) {
159      bytesToCopy = ZRLE_BUFFER_LENGTH(&zos->out) - i;
160    }
161
162    memcpy(cl->updateBuf+cl->ublen, (uint8_t*)zos->out.start + i, bytesToCopy);
163
164    cl->ublen += bytesToCopy;
165    i += bytesToCopy;
166
167    if (cl->ublen == UPDATE_BUF_SIZE) {
168      if (!rfbSendUpdateBuf(cl))
169        return FALSE;
170    }
171  }
172
173  return TRUE;
174}
175
176
177void rfbFreeZrleData(rfbClientPtr cl)
178{
179  if (cl->zrleData)
180    zrleOutStreamFree(cl->zrleData);
181  cl->zrleData = NULL;
182}
183