mirror of
https://github.com/KDE/krfb
synced 2026-07-01 07:31:16 -07:00
This is currently required to be able to split off the event processing code in small functions so that it is possible to integrate libvncserver's event loop code with Qt's event loop properly. This is also what vino does; the whole event loop integration idea was taken from there. svn path=/trunk/KDE/kdenetwork/krfb/; revision=1195283
246 lines
6.8 KiB
C
246 lines
6.8 KiB
C
/*
|
|
* Copyright (C) 2002 RealVNC Ltd. All Rights Reserved.
|
|
* Copyright (C) 2003 Sun Microsystems, Inc.
|
|
*
|
|
* 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.
|
|
*/
|
|
|
|
/*
|
|
* zrle.c
|
|
*
|
|
* Routines to implement Zlib Run-length Encoding (ZRLE).
|
|
*/
|
|
|
|
#include "rfb/rfb.h"
|
|
#include "private.h"
|
|
#include "zrleoutstream.h"
|
|
|
|
|
|
#define GET_IMAGE_INTO_BUF(tx,ty,tw,th,buf) \
|
|
{ char *fbptr = (cl->scaledScreen->frameBuffer \
|
|
+ (cl->scaledScreen->paddedWidthInBytes * ty) \
|
|
+ (tx * (cl->scaledScreen->bitsPerPixel / 8))); \
|
|
\
|
|
(*cl->translateFn)(cl->translateLookupTable, &cl->screen->serverFormat,\
|
|
&cl->format, fbptr, (char*)buf, \
|
|
cl->scaledScreen->paddedWidthInBytes, tw, th); }
|
|
|
|
#define EXTRA_ARGS , rfbClientPtr cl
|
|
|
|
#define ENDIAN_LITTLE 0
|
|
#define ENDIAN_BIG 1
|
|
#define ENDIAN_NO 2
|
|
#define BPP 8
|
|
#define ZYWRLE_ENDIAN ENDIAN_NO
|
|
#include <zrleencodetemplate.c>
|
|
#undef BPP
|
|
#define BPP 15
|
|
#undef ZYWRLE_ENDIAN
|
|
#define ZYWRLE_ENDIAN ENDIAN_LITTLE
|
|
#include <zrleencodetemplate.c>
|
|
#undef ZYWRLE_ENDIAN
|
|
#define ZYWRLE_ENDIAN ENDIAN_BIG
|
|
#include <zrleencodetemplate.c>
|
|
#undef BPP
|
|
#define BPP 16
|
|
#undef ZYWRLE_ENDIAN
|
|
#define ZYWRLE_ENDIAN ENDIAN_LITTLE
|
|
#include <zrleencodetemplate.c>
|
|
#undef ZYWRLE_ENDIAN
|
|
#define ZYWRLE_ENDIAN ENDIAN_BIG
|
|
#include <zrleencodetemplate.c>
|
|
#undef BPP
|
|
#define BPP 32
|
|
#undef ZYWRLE_ENDIAN
|
|
#define ZYWRLE_ENDIAN ENDIAN_LITTLE
|
|
#include <zrleencodetemplate.c>
|
|
#undef ZYWRLE_ENDIAN
|
|
#define ZYWRLE_ENDIAN ENDIAN_BIG
|
|
#include <zrleencodetemplate.c>
|
|
#define CPIXEL 24A
|
|
#undef ZYWRLE_ENDIAN
|
|
#define ZYWRLE_ENDIAN ENDIAN_LITTLE
|
|
#include <zrleencodetemplate.c>
|
|
#undef ZYWRLE_ENDIAN
|
|
#define ZYWRLE_ENDIAN ENDIAN_BIG
|
|
#include <zrleencodetemplate.c>
|
|
#undef CPIXEL
|
|
#define CPIXEL 24B
|
|
#undef ZYWRLE_ENDIAN
|
|
#define ZYWRLE_ENDIAN ENDIAN_LITTLE
|
|
#include <zrleencodetemplate.c>
|
|
#undef ZYWRLE_ENDIAN
|
|
#define ZYWRLE_ENDIAN ENDIAN_BIG
|
|
#include <zrleencodetemplate.c>
|
|
#undef CPIXEL
|
|
#undef BPP
|
|
|
|
|
|
/*
|
|
* zrleBeforeBuf contains pixel data in the client's format. It must be at
|
|
* least one pixel bigger than the largest tile of pixel data, since the
|
|
* ZRLE encoding algorithm writes to the position one past the end of the pixel
|
|
* data.
|
|
*/
|
|
|
|
/* TODO: put into rfbClient struct */
|
|
static char zrleBeforeBuf[rfbZRLETileWidth * rfbZRLETileHeight * 4 + 4];
|
|
|
|
|
|
|
|
/*
|
|
* rfbSendRectEncodingZRLE - send a given rectangle using ZRLE encoding.
|
|
*/
|
|
|
|
|
|
rfbBool rfbSendRectEncodingZRLE(rfbClientPtr cl, int x, int y, int w, int h)
|
|
{
|
|
zrleOutStream* zos;
|
|
rfbFramebufferUpdateRectHeader rect;
|
|
rfbZRLEHeader hdr;
|
|
int i;
|
|
|
|
if (cl->preferredEncoding == rfbEncodingZYWRLE) {
|
|
if (cl->tightQualityLevel < 0) {
|
|
cl->zywrleLevel = 1;
|
|
} else if (cl->tightQualityLevel < 3) {
|
|
cl->zywrleLevel = 3;
|
|
} else if (cl->tightQualityLevel < 6) {
|
|
cl->zywrleLevel = 2;
|
|
} else {
|
|
cl->zywrleLevel = 1;
|
|
}
|
|
} else
|
|
cl->zywrleLevel = 0;
|
|
|
|
if (!cl->zrleData)
|
|
cl->zrleData = zrleOutStreamNew();
|
|
zos = cl->zrleData;
|
|
zos->in.ptr = zos->in.start;
|
|
zos->out.ptr = zos->out.start;
|
|
|
|
switch (cl->format.bitsPerPixel) {
|
|
|
|
case 8:
|
|
zrleEncode8NE(x, y, w, h, zos, zrleBeforeBuf, cl);
|
|
break;
|
|
|
|
case 16:
|
|
if (cl->format.greenMax > 0x1F) {
|
|
if (cl->format.bigEndian)
|
|
zrleEncode16BE(x, y, w, h, zos, zrleBeforeBuf, cl);
|
|
else
|
|
zrleEncode16LE(x, y, w, h, zos, zrleBeforeBuf, cl);
|
|
} else {
|
|
if (cl->format.bigEndian)
|
|
zrleEncode15BE(x, y, w, h, zos, zrleBeforeBuf, cl);
|
|
else
|
|
zrleEncode15LE(x, y, w, h, zos, zrleBeforeBuf, cl);
|
|
}
|
|
break;
|
|
|
|
case 32: {
|
|
rfbBool fitsInLS3Bytes
|
|
= ((cl->format.redMax << cl->format.redShift) < (1<<24) &&
|
|
(cl->format.greenMax << cl->format.greenShift) < (1<<24) &&
|
|
(cl->format.blueMax << cl->format.blueShift) < (1<<24));
|
|
|
|
rfbBool fitsInMS3Bytes = (cl->format.redShift > 7 &&
|
|
cl->format.greenShift > 7 &&
|
|
cl->format.blueShift > 7);
|
|
|
|
if ((fitsInLS3Bytes && !cl->format.bigEndian) ||
|
|
(fitsInMS3Bytes && cl->format.bigEndian)) {
|
|
if (cl->format.bigEndian)
|
|
zrleEncode24ABE(x, y, w, h, zos, zrleBeforeBuf, cl);
|
|
else
|
|
zrleEncode24ALE(x, y, w, h, zos, zrleBeforeBuf, cl);
|
|
}
|
|
else if ((fitsInLS3Bytes && cl->format.bigEndian) ||
|
|
(fitsInMS3Bytes && !cl->format.bigEndian)) {
|
|
if (cl->format.bigEndian)
|
|
zrleEncode24BBE(x, y, w, h, zos, zrleBeforeBuf, cl);
|
|
else
|
|
zrleEncode24BLE(x, y, w, h, zos, zrleBeforeBuf, cl);
|
|
}
|
|
else {
|
|
if (cl->format.bigEndian)
|
|
zrleEncode32BE(x, y, w, h, zos, zrleBeforeBuf, cl);
|
|
else
|
|
zrleEncode32LE(x, y, w, h, zos, zrleBeforeBuf, cl);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
rfbStatRecordEncodingSent(cl, rfbEncodingZRLE, sz_rfbFramebufferUpdateRectHeader + sz_rfbZRLEHeader + ZRLE_BUFFER_LENGTH(&zos->out),
|
|
+ w * (cl->format.bitsPerPixel / 8) * h);
|
|
|
|
if (cl->ublen + sz_rfbFramebufferUpdateRectHeader + sz_rfbZRLEHeader
|
|
> UPDATE_BUF_SIZE)
|
|
{
|
|
if (!rfbSendUpdateBuf(cl))
|
|
return FALSE;
|
|
}
|
|
|
|
rect.r.x = Swap16IfLE(x);
|
|
rect.r.y = Swap16IfLE(y);
|
|
rect.r.w = Swap16IfLE(w);
|
|
rect.r.h = Swap16IfLE(h);
|
|
rect.encoding = Swap32IfLE(cl->preferredEncoding);
|
|
|
|
memcpy(cl->updateBuf+cl->ublen, (char *)&rect,
|
|
sz_rfbFramebufferUpdateRectHeader);
|
|
cl->ublen += sz_rfbFramebufferUpdateRectHeader;
|
|
|
|
hdr.length = Swap32IfLE(ZRLE_BUFFER_LENGTH(&zos->out));
|
|
|
|
memcpy(cl->updateBuf+cl->ublen, (char *)&hdr, sz_rfbZRLEHeader);
|
|
cl->ublen += sz_rfbZRLEHeader;
|
|
|
|
/* copy into updateBuf and send from there. Maybe should send directly? */
|
|
|
|
for (i = 0; i < ZRLE_BUFFER_LENGTH(&zos->out);) {
|
|
|
|
int bytesToCopy = UPDATE_BUF_SIZE - cl->ublen;
|
|
|
|
if (i + bytesToCopy > ZRLE_BUFFER_LENGTH(&zos->out)) {
|
|
bytesToCopy = ZRLE_BUFFER_LENGTH(&zos->out) - i;
|
|
}
|
|
|
|
memcpy(cl->updateBuf+cl->ublen, (uint8_t*)zos->out.start + i, bytesToCopy);
|
|
|
|
cl->ublen += bytesToCopy;
|
|
i += bytesToCopy;
|
|
|
|
if (cl->ublen == UPDATE_BUF_SIZE) {
|
|
if (!rfbSendUpdateBuf(cl))
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
void rfbFreeZrleData(rfbClientPtr cl)
|
|
{
|
|
if (cl->zrleData)
|
|
zrleOutStreamFree(cl->zrleData);
|
|
cl->zrleData = NULL;
|
|
}
|
|
|