summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPierre Ossman <ossman@cendio.se>2014-07-14 16:15:16 +0200
committerPierre Ossman <ossman@cendio.se>2014-07-14 16:15:16 +0200
commitff7a923a61154b04d8202039651a66db195affa1 (patch)
treed9b3db2ac42beb09fe831e14317ac9689a68ae73
parent15bb3b07d86f073857bbeeadb9b1cb1a6db066e3 (diff)
parent2e5a10608394186fd1324c97b17d7f08e0c0aaf6 (diff)
downloadtigervnc-ff7a923a61154b04d8202039651a66db195affa1.tar.gz
tigervnc-ff7a923a61154b04d8202039651a66db195affa1.zip
Merge branch 'nocolourmap' of https://github.com/CendioOssman/tigervnc
-rw-r--r--common/rdr/InStream.h23
-rw-r--r--common/rdr/OutStream.h25
-rw-r--r--common/rfb/CConnection.cxx8
-rw-r--r--common/rfb/CMakeLists.txt6
-rw-r--r--common/rfb/CMsgHandler.h3
-rw-r--r--common/rfb/CMsgReader.cxx190
-rw-r--r--common/rfb/CMsgReader.h32
-rw-r--r--common/rfb/CMsgReaderV3.cxx174
-rw-r--r--common/rfb/CMsgWriter.cxx88
-rw-r--r--common/rfb/CMsgWriter.h37
-rw-r--r--common/rfb/CMsgWriterV3.cxx117
-rw-r--r--common/rfb/CMsgWriterV3.h41
-rw-r--r--common/rfb/ColourCube.h96
-rw-r--r--common/rfb/ColourMap.h51
-rw-r--r--common/rfb/CopyRectDecoder.cxx (renamed from common/rfb/SMsgReaderV3.h)38
-rw-r--r--common/rfb/CopyRectDecoder.h (renamed from common/rfb/ImageGetter.h)17
-rw-r--r--common/rfb/Decoder.cxx20
-rw-r--r--common/rfb/Decoder.h7
-rw-r--r--common/rfb/Encoder.cxx17
-rw-r--r--common/rfb/Encoder.h17
-rw-r--r--common/rfb/HextileDecoder.cxx12
-rw-r--r--common/rfb/HextileDecoder.h4
-rw-r--r--common/rfb/HextileEncoder.cxx17
-rw-r--r--common/rfb/HextileEncoder.h6
-rw-r--r--common/rfb/Palette.h190
-rw-r--r--common/rfb/PixelBuffer.cxx136
-rw-r--r--common/rfb/PixelBuffer.h51
-rw-r--r--common/rfb/PixelFormat.cxx148
-rw-r--r--common/rfb/PixelFormat.h30
-rw-r--r--common/rfb/PixelFormat.inl168
-rw-r--r--common/rfb/PixelTransformer.cxx148
-rw-r--r--common/rfb/PixelTransformer.h33
-rw-r--r--common/rfb/RREDecoder.cxx10
-rw-r--r--common/rfb/RREDecoder.h4
-rw-r--r--common/rfb/RREEncoder.cxx19
-rw-r--r--common/rfb/RREEncoder.h9
-rw-r--r--common/rfb/RawDecoder.cxx9
-rw-r--r--common/rfb/RawDecoder.h4
-rw-r--r--common/rfb/RawEncoder.cxx16
-rw-r--r--common/rfb/RawEncoder.h6
-rw-r--r--common/rfb/SConnection.cxx27
-rw-r--r--common/rfb/SConnection.h6
-rw-r--r--common/rfb/SDesktop.h4
-rw-r--r--common/rfb/SMsgReader.cxx112
-rw-r--r--common/rfb/SMsgReader.h24
-rw-r--r--common/rfb/SMsgReaderV3.cxx131
-rw-r--r--common/rfb/SMsgWriter.cxx387
-rw-r--r--common/rfb/SMsgWriter.h163
-rw-r--r--common/rfb/SMsgWriterV3.cxx399
-rw-r--r--common/rfb/SMsgWriterV3.h84
-rw-r--r--common/rfb/TightDecoder.cxx26
-rw-r--r--common/rfb/TightDecoder.h5
-rw-r--r--common/rfb/TightEncoder.cxx53
-rw-r--r--common/rfb/TightEncoder.h38
-rw-r--r--common/rfb/TightPalette.cxx110
-rw-r--r--common/rfb/TightPalette.h127
-rw-r--r--common/rfb/TransImageGetter.cxx25
-rw-r--r--common/rfb/TransImageGetter.h31
-rw-r--r--common/rfb/VNCSConnectionST.cxx113
-rw-r--r--common/rfb/VNCSConnectionST.h7
-rw-r--r--common/rfb/VNCServer.h8
-rw-r--r--common/rfb/VNCServerST.cxx26
-rw-r--r--common/rfb/VNCServerST.h3
-rw-r--r--common/rfb/ZRLEDecoder.cxx32
-rw-r--r--common/rfb/ZRLEDecoder.h3
-rw-r--r--common/rfb/ZRLEEncoder.cxx49
-rw-r--r--common/rfb/ZRLEEncoder.h5
-rw-r--r--common/rfb/hextileDecode.h16
-rw-r--r--common/rfb/hextileEncode.h14
-rw-r--r--common/rfb/hextileEncodeBetter.h28
-rw-r--r--common/rfb/rreDecode.h14
-rw-r--r--common/rfb/rreEncode.h2
-rw-r--r--common/rfb/tightDecode.h33
-rw-r--r--common/rfb/tightEncode.h218
-rw-r--r--common/rfb/transInitTempl.h139
-rw-r--r--common/rfb/transTempl.h33
-rw-r--r--common/rfb/zrleDecode.h26
-rw-r--r--common/rfb/zrleEncode.h120
-rw-r--r--tests/pixelconv.cxx2
-rw-r--r--unix/x0vncserver/XPixelBuffer.cxx8
-rw-r--r--unix/x0vncserver/XPixelBuffer.h9
-rw-r--r--unix/x0vncserver/x0vncserver.cxx18
-rw-r--r--unix/xserver/hw/vnc/XserverDesktop.cc147
-rw-r--r--unix/xserver/hw/vnc/XserverDesktop.h12
-rw-r--r--unix/xserver/hw/vnc/vncExtInit.cc9
-rw-r--r--unix/xserver/hw/vnc/vncHooks.cc38
-rw-r--r--vncviewer/CConn.cxx39
-rw-r--r--vncviewer/CConn.h10
-rw-r--r--vncviewer/CMakeLists.txt2
-rw-r--r--vncviewer/DesktopWindow.cxx6
-rw-r--r--vncviewer/DesktopWindow.h2
-rw-r--r--vncviewer/FLTKPixelBuffer.cxx52
-rw-r--r--vncviewer/FLTKPixelBuffer.h (renamed from common/rfb/TrueColourMap.h)32
-rw-r--r--vncviewer/OSXPixelBuffer.cxx21
-rw-r--r--vncviewer/OSXPixelBuffer.h12
-rw-r--r--vncviewer/PlatformPixelBuffer.cxx (renamed from common/rfb/CMsgReaderV3.h)28
-rw-r--r--vncviewer/PlatformPixelBuffer.h30
-rw-r--r--vncviewer/Viewport.cxx82
-rw-r--r--vncviewer/Viewport.h11
-rw-r--r--vncviewer/Win32PixelBuffer.cxx16
-rw-r--r--vncviewer/Win32PixelBuffer.h12
-rw-r--r--vncviewer/X11PixelBuffer.cxx20
-rw-r--r--vncviewer/X11PixelBuffer.h14
-rw-r--r--win/rfb_win32/DIBSectionBuffer.cxx90
-rw-r--r--win/rfb_win32/DIBSectionBuffer.h24
-rw-r--r--win/rfb_win32/DeviceFrameBuffer.cxx75
-rw-r--r--win/rfb_win32/DeviceFrameBuffer.h1
-rw-r--r--win/rfb_win32/SDisplay.cxx6
-rw-r--r--win/rfb_win32/WMNotifier.cxx6
-rw-r--r--win/rfb_win32/WMNotifier.h2
110 files changed, 1990 insertions, 3514 deletions
diff --git a/common/rdr/InStream.h b/common/rdr/InStream.h
index 6d22ac6a..760fb3dc 100644
--- a/common/rdr/InStream.h
+++ b/common/rdr/InStream.h
@@ -71,23 +71,6 @@ namespace rdr {
inline S16 readS16() { return (S16)readU16(); }
inline S32 readS32() { return (S32)readU32(); }
- // readCompactLength() reads 1..3 bytes representing length of the data
- // following. This method is used by the Tight decoder.
-
- inline unsigned int readCompactLength() {
- U8 b = readU8();
- int result = (int)b & 0x7F;
- if (b & 0x80) {
- b = readU8();
- result |= ((int)b & 0x7F) << 7;
- if (b & 0x80) {
- b = readU8();
- result |= ((int)b & 0xFF) << 14;
- }
- }
- return result;
- }
-
// readString() reads a string - a U32 length followed by the data.
// Returns a null-terminated string - the caller should delete[] it
// afterwards.
@@ -128,12 +111,6 @@ namespace rdr {
inline U32 readOpaque32() { check(4); U32 r; ((U8*)&r)[0] = *ptr++;
((U8*)&r)[1] = *ptr++; ((U8*)&r)[2] = *ptr++;
((U8*)&r)[3] = *ptr++; return r; }
- inline U32 readOpaque24A() { check(3); U32 r=0; ((U8*)&r)[0] = *ptr++;
- ((U8*)&r)[1] = *ptr++; ((U8*)&r)[2] = *ptr++;
- return r; }
- inline U32 readOpaque24B() { check(3); U32 r=0; ((U8*)&r)[1] = *ptr++;
- ((U8*)&r)[2] = *ptr++; ((U8*)&r)[3] = *ptr++;
- return r; }
// pos() returns the position in the stream.
diff --git a/common/rdr/OutStream.h b/common/rdr/OutStream.h
index aed2eea1..4afd4bfb 100644
--- a/common/rdr/OutStream.h
+++ b/common/rdr/OutStream.h
@@ -65,25 +65,6 @@ namespace rdr {
inline void writeS16(S16 s) { writeU16((U16)s); }
inline void writeS32(S32 s) { writeU32((U32)s); }
- // writeCompactLength() writes 1..3 bytes representing length of the data
- // following. This method is used by the Tight encoder.
-
- inline void writeCompactLength(unsigned int len) {
- U8 b = len & 0x7F;
- if (len <= 0x7F) {
- writeU8(b);
- } else {
- writeU8(b | 0x80);
- b = len >> 7 & 0x7F;
- if (len <= 0x3FFF) {
- writeU8(b);
- } else {
- writeU8(b | 0x80);
- writeU8(len >> 14 & 0xFF);
- }
- }
- }
-
// writeString() writes a string - a U32 length followed by the data. The
// given string should be null-terminated (but the terminating null is not
// written to the stream).
@@ -128,12 +109,6 @@ namespace rdr {
*ptr++ = ((U8*)&u)[1];
*ptr++ = ((U8*)&u)[2];
*ptr++ = ((U8*)&u)[3]; }
- inline void writeOpaque24A(U32 u) { check(3); *ptr++ = ((U8*)&u)[0];
- *ptr++ = ((U8*)&u)[1];
- *ptr++ = ((U8*)&u)[2]; }
- inline void writeOpaque24B(U32 u) { check(3); *ptr++ = ((U8*)&u)[1];
- *ptr++ = ((U8*)&u)[2];
- *ptr++ = ((U8*)&u)[3]; }
// length() returns the length of the stream.
diff --git a/common/rfb/CConnection.cxx b/common/rfb/CConnection.cxx
index e73b02e6..1695c3a6 100644
--- a/common/rfb/CConnection.cxx
+++ b/common/rfb/CConnection.cxx
@@ -19,8 +19,8 @@
#include <string.h>
#include <rfb/Exception.h>
#include <rfb/fenceTypes.h>
-#include <rfb/CMsgReaderV3.h>
-#include <rfb/CMsgWriterV3.h>
+#include <rfb/CMsgReader.h>
+#include <rfb/CMsgWriter.h>
#include <rfb/CSecurity.h>
#include <rfb/Security.h>
#include <rfb/CConnection.h>
@@ -254,8 +254,8 @@ void CConnection::throwConnFailedException()
void CConnection::securityCompleted()
{
state_ = RFBSTATE_INITIALISATION;
- reader_ = new CMsgReaderV3(this, is);
- writer_ = new CMsgWriterV3(&cp, os);
+ reader_ = new CMsgReader(this, is);
+ writer_ = new CMsgWriter(&cp, os);
vlog.debug("Authentication success!");
authSuccess();
writer_->writeClientInit(shared);
diff --git a/common/rfb/CMakeLists.txt b/common/rfb/CMakeLists.txt
index 9f5b59ec..48590f36 100644
--- a/common/rfb/CMakeLists.txt
+++ b/common/rfb/CMakeLists.txt
@@ -5,9 +5,7 @@ set(RFB_SOURCES
CConnection.cxx
CMsgHandler.cxx
CMsgReader.cxx
- CMsgReaderV3.cxx
CMsgWriter.cxx
- CMsgWriterV3.cxx
CSecurityPlain.cxx
CSecurityStack.cxx
CSecurityVeNCrypt.cxx
@@ -15,6 +13,7 @@ set(RFB_SOURCES
ComparingUpdateTracker.cxx
Configuration.cxx
ConnParams.cxx
+ CopyRectDecoder.cxx
Cursor.cxx
Decoder.cxx
d3des.c
@@ -41,9 +40,7 @@ set(RFB_SOURCES
SConnection.cxx
SMsgHandler.cxx
SMsgReader.cxx
- SMsgReaderV3.cxx
SMsgWriter.cxx
- SMsgWriterV3.cxx
ServerCore.cxx
Security.cxx
SecurityServer.cxx
@@ -56,7 +53,6 @@ set(RFB_SOURCES
Timer.cxx
TightDecoder.cxx
TightEncoder.cxx
- TightPalette.cxx
TransImageGetter.cxx
UpdateTracker.cxx
VNCSConnectionST.cxx
diff --git a/common/rfb/CMsgHandler.h b/common/rfb/CMsgHandler.h
index d7ffd65b..8b58e0e5 100644
--- a/common/rfb/CMsgHandler.h
+++ b/common/rfb/CMsgHandler.h
@@ -59,8 +59,7 @@ namespace rfb {
virtual void framebufferUpdateStart() = 0;
virtual void framebufferUpdateEnd() = 0;
- virtual void beginRect(const Rect& r, int encoding) = 0;
- virtual void endRect(const Rect& r, int encoding) = 0;
+ virtual void dataRect(const Rect& r, int encoding) = 0;
virtual void setColourMapEntries(int firstColour, int nColours,
rdr::U16* rgbs) = 0;
diff --git a/common/rfb/CMsgReader.cxx b/common/rfb/CMsgReader.cxx
index 63d31d1a..04846ef4 100644
--- a/common/rfb/CMsgReader.cxx
+++ b/common/rfb/CMsgReader.cxx
@@ -1,4 +1,5 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
+ * Copyright 2009-2014 Pierre Ossman for Cendio AB
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -16,31 +17,102 @@
* USA.
*/
#include <stdio.h>
+#include <rfb/msgTypes.h>
#include <rdr/InStream.h>
#include <rfb/Exception.h>
#include <rfb/util.h>
#include <rfb/CMsgHandler.h>
#include <rfb/CMsgReader.h>
+#include <rfb/Decoder.h>
using namespace rfb;
CMsgReader::CMsgReader(CMsgHandler* handler_, rdr::InStream* is_)
: imageBufIdealSize(0), handler(handler_), is(is_),
- imageBuf(0), imageBufSize(0)
+ imageBuf(0), imageBufSize(0), nUpdateRectsLeft(0)
{
- for (int i = 0; i <= encodingMax; i++) {
- decoders[i] = 0;
- }
}
CMsgReader::~CMsgReader()
{
- for (int i = 0; i <= encodingMax; i++) {
- delete decoders[i];
- }
delete [] imageBuf;
}
+void CMsgReader::readServerInit()
+{
+ int width = is->readU16();
+ int height = is->readU16();
+ handler->setDesktopSize(width, height);
+ PixelFormat pf;
+ pf.read(is);
+ handler->setPixelFormat(pf);
+ CharArray name(is->readString());
+ handler->setName(name.buf);
+ handler->serverInit();
+}
+
+void CMsgReader::readMsg()
+{
+ if (nUpdateRectsLeft == 0) {
+ int type = is->readU8();
+
+ switch (type) {
+ case msgTypeSetColourMapEntries:
+ readSetColourMapEntries();
+ break;
+ case msgTypeBell:
+ readBell();
+ break;
+ case msgTypeServerCutText:
+ readServerCutText();
+ break;
+ case msgTypeFramebufferUpdate:
+ readFramebufferUpdate();
+ break;
+ case msgTypeServerFence:
+ readFence();
+ break;
+ case msgTypeEndOfContinuousUpdates:
+ readEndOfContinuousUpdates();
+ break;
+ default:
+ fprintf(stderr, "unknown message type %d\n", type);
+ throw Exception("unknown message type");
+ }
+ } else {
+ int x = is->readU16();
+ int y = is->readU16();
+ int w = is->readU16();
+ int h = is->readU16();
+ int encoding = is->readS32();
+
+ switch (encoding) {
+ case pseudoEncodingLastRect:
+ nUpdateRectsLeft = 1; // this rectangle is the last one
+ break;
+ case pseudoEncodingCursor:
+ readSetCursor(w, h, Point(x,y));
+ break;
+ case pseudoEncodingDesktopName:
+ readSetDesktopName(x, y, w, h);
+ break;
+ case pseudoEncodingDesktopSize:
+ handler->setDesktopSize(w, h);
+ break;
+ case pseudoEncodingExtendedDesktopSize:
+ readExtendedDesktopSize(x, y, w, h);
+ break;
+ default:
+ readRect(Rect(x, y, x+w, y+h), encoding);
+ break;
+ };
+
+ nUpdateRectsLeft--;
+ if (nUpdateRectsLeft == 0)
+ handler->framebufferUpdateEnd();
+ }
+}
+
void CMsgReader::readSetColourMapEntries()
{
is->skip(1);
@@ -72,14 +144,38 @@ void CMsgReader::readServerCutText()
handler->serverCutText(ca.buf, len);
}
-void CMsgReader::readFramebufferUpdateStart()
+void CMsgReader::readFence()
{
- handler->framebufferUpdateStart();
+ rdr::U32 flags;
+ rdr::U8 len;
+ char data[64];
+
+ is->skip(3);
+
+ flags = is->readU32();
+
+ len = is->readU8();
+ if (len > sizeof(data)) {
+ fprintf(stderr, "Ignoring fence with too large payload\n");
+ is->skip(len);
+ return;
+ }
+
+ is->readBytes(data, len);
+
+ handler->fence(flags, len, data);
}
-void CMsgReader::readFramebufferUpdateEnd()
+void CMsgReader::readEndOfContinuousUpdates()
{
- handler->framebufferUpdateEnd();
+ handler->endOfContinuousUpdates();
+}
+
+void CMsgReader::readFramebufferUpdate()
+{
+ is->skip(1);
+ nUpdateRectsLeft = is->readU16();
+ handler->framebufferUpdateStart();
}
void CMsgReader::readRect(const Rect& r, int encoding)
@@ -94,35 +190,7 @@ void CMsgReader::readRect(const Rect& r, int encoding)
if (r.is_empty())
fprintf(stderr, "Warning: zero size rect\n");
- handler->beginRect(r, encoding);
-
- if (encoding == encodingCopyRect) {
- readCopyRect(r);
- } else {
-
- if (!Decoder::supported(encoding)) {
- fprintf(stderr, "Unknown rect encoding %d\n", encoding);
- throw Exception("Unknown rect encoding");
- }
-
- if (!decoders[encoding]) {
- decoders[encoding] = Decoder::createDecoder(encoding, this);
- if (!decoders[encoding]) {
- fprintf(stderr, "Unknown rect encoding %d\n", encoding);
- throw Exception("Unknown rect encoding");
- }
- }
- decoders[encoding]->readRect(r, handler);
- }
-
- handler->endRect(r, encoding);
-}
-
-void CMsgReader::readCopyRect(const Rect& r)
-{
- int srcX = is->readU16();
- int srcY = is->readU16();
- handler->copyRect(r, srcX, srcY);
+ handler->dataRect(r, encoding);
}
void CMsgReader::readSetCursor(int width, int height, const Point& hotspot)
@@ -138,6 +206,43 @@ void CMsgReader::readSetCursor(int width, int height, const Point& hotspot)
handler->setCursor(width, height, hotspot, data.buf, mask.buf);
}
+void CMsgReader::readSetDesktopName(int x, int y, int w, int h)
+{
+ char* name = is->readString();
+
+ if (x || y || w || h) {
+ fprintf(stderr, "Ignoring DesktopName rect with non-zero position/size\n");
+ } else {
+ handler->setName(name);
+ }
+
+ delete [] name;
+}
+
+void CMsgReader::readExtendedDesktopSize(int x, int y, int w, int h)
+{
+ unsigned int screens, i;
+ rdr::U32 id, flags;
+ int sx, sy, sw, sh;
+ ScreenSet layout;
+
+ screens = is->readU8();
+ is->skip(3);
+
+ for (i = 0;i < screens;i++) {
+ id = is->readU32();
+ sx = is->readU16();
+ sy = is->readU16();
+ sw = is->readU16();
+ sh = is->readU16();
+ flags = is->readU32();
+
+ layout.add_screen(Screen(id, sx, sy, sw, sh, flags));
+ }
+
+ handler->setExtendedDesktopSize(x, y, w, h, layout);
+}
+
rdr::U8* CMsgReader::getImageBuf(int required, int requested, int* nPixels)
{
int requiredBytes = required * (handler->cp.pf().bpp / 8);
@@ -157,8 +262,3 @@ rdr::U8* CMsgReader::getImageBuf(int required, int requested, int* nPixels)
*nPixels = imageBufSize / (handler->cp.pf().bpp / 8);
return imageBuf;
}
-
-int CMsgReader::bpp()
-{
- return handler->cp.pf().bpp;
-}
diff --git a/common/rfb/CMsgReader.h b/common/rfb/CMsgReader.h
index 7b361609..3592ef87 100644
--- a/common/rfb/CMsgReader.h
+++ b/common/rfb/CMsgReader.h
@@ -1,4 +1,5 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
+ * Copyright 2009-2014 Pierre Ossman for Cendio AB
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -24,8 +25,9 @@
#define __RFB_CMSGREADER_H__
#include <rdr/types.h>
+
+#include <rfb/Rect.h>
#include <rfb/encodings.h>
-#include <rfb/Decoder.h>
namespace rdr { class InStream; }
@@ -35,39 +37,39 @@ namespace rfb {
class CMsgReader {
public:
+ CMsgReader(CMsgHandler* handler, rdr::InStream* is);
virtual ~CMsgReader();
- virtual void readServerInit()=0;
+ void readServerInit();
// readMsg() reads a message, calling the handler as appropriate.
- virtual void readMsg()=0;
+ void readMsg();
rdr::InStream* getInStream() { return is; }
rdr::U8* getImageBuf(int required, int requested=0, int* nPixels=0);
- int bpp();
int imageBufIdealSize;
protected:
- virtual void readSetColourMapEntries();
- virtual void readBell();
- virtual void readServerCutText();
+ void readSetColourMapEntries();
+ void readBell();
+ void readServerCutText();
+ void readFence();
+ void readEndOfContinuousUpdates();
- virtual void readFramebufferUpdateStart();
- virtual void readFramebufferUpdateEnd();
- virtual void readRect(const Rect& r, int encoding);
+ void readFramebufferUpdate();
- virtual void readCopyRect(const Rect& r);
+ void readRect(const Rect& r, int encoding);
- virtual void readSetCursor(int width, int height, const Point& hotspot);
-
- CMsgReader(CMsgHandler* handler, rdr::InStream* is);
+ void readSetCursor(int width, int height, const Point& hotspot);
+ void readSetDesktopName(int x, int y, int w, int h);
+ void readExtendedDesktopSize(int x, int y, int w, int h);
CMsgHandler* handler;
rdr::InStream* is;
- Decoder* decoders[encodingMax+1];
rdr::U8* imageBuf;
int imageBufSize;
+ int nUpdateRectsLeft;
};
}
#endif
diff --git a/common/rfb/CMsgReaderV3.cxx b/common/rfb/CMsgReaderV3.cxx
deleted file mode 100644
index 085cc5ad..00000000
--- a/common/rfb/CMsgReaderV3.cxx
+++ /dev/null
@@ -1,174 +0,0 @@
-/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
- * Copyright 2009-2011 Pierre Ossman for Cendio AB
- *
- * 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.
- */
-#include <rfb/PixelFormat.h>
-#include <rfb/msgTypes.h>
-#include <rfb/Exception.h>
-#include <rdr/InStream.h>
-#include <rfb/CMsgReaderV3.h>
-#include <rfb/CMsgHandler.h>
-#include <rfb/util.h>
-#include <rfb/ScreenSet.h>
-#include <stdio.h>
-
-using namespace rfb;
-
-CMsgReaderV3::CMsgReaderV3(CMsgHandler* handler, rdr::InStream* is)
- : CMsgReader(handler, is), nUpdateRectsLeft(0)
-{
-}
-
-CMsgReaderV3::~CMsgReaderV3()
-{
-}
-
-void CMsgReaderV3::readServerInit()
-{
- int width = is->readU16();
- int height = is->readU16();
- handler->setDesktopSize(width, height);
- PixelFormat pf;
- pf.read(is);
- handler->setPixelFormat(pf);
- CharArray name(is->readString());
- handler->setName(name.buf);
- handler->serverInit();
-}
-
-void CMsgReaderV3::readMsg()
-{
- if (nUpdateRectsLeft == 0) {
-
- int type = is->readU8();
- switch (type) {
- case msgTypeFramebufferUpdate: readFramebufferUpdate(); break;
- case msgTypeSetColourMapEntries: readSetColourMapEntries(); break;
- case msgTypeBell: readBell(); break;
- case msgTypeServerCutText: readServerCutText(); break;
- case msgTypeServerFence: readFence(); break;
- case msgTypeEndOfContinuousUpdates: readEndOfContinuousUpdates(); break;
-
- default:
- fprintf(stderr, "unknown message type %d\n", type);
- throw Exception("unknown message type");
- }
-
- } else {
-
- int x = is->readU16();
- int y = is->readU16();
- int w = is->readU16();
- int h = is->readU16();
- int encoding = is->readS32();
-
- switch (encoding) {
- case pseudoEncodingDesktopSize:
- handler->setDesktopSize(w, h);
- break;
- case pseudoEncodingExtendedDesktopSize:
- readExtendedDesktopSize(x, y, w, h);
- break;
- case pseudoEncodingDesktopName:
- readSetDesktopName(x, y, w, h);
- break;
- case pseudoEncodingCursor:
- readSetCursor(w, h, Point(x,y));
- break;
- case pseudoEncodingLastRect:
- nUpdateRectsLeft = 1; // this rectangle is the last one
- break;
- default:
- readRect(Rect(x, y, x+w, y+h), encoding);
- break;
- };
-
- nUpdateRectsLeft--;
- if (nUpdateRectsLeft == 0) handler->framebufferUpdateEnd();
- }
-}
-
-void CMsgReaderV3::readFramebufferUpdate()
-{
- is->skip(1);
- nUpdateRectsLeft = is->readU16();
- handler->framebufferUpdateStart();
-}
-
-void CMsgReaderV3::readSetDesktopName(int x, int y, int w, int h)
-{
- char* name = is->readString();
-
- if (x || y || w || h) {
- fprintf(stderr, "Ignoring DesktopName rect with non-zero position/size\n");
- } else {
- handler->setName(name);
- }
-
- delete [] name;
-}
-
-void CMsgReaderV3::readExtendedDesktopSize(int x, int y, int w, int h)
-{
- unsigned int screens, i;
- rdr::U32 id, flags;
- int sx, sy, sw, sh;
- ScreenSet layout;
-
- screens = is->readU8();
- is->skip(3);
-
- for (i = 0;i < screens;i++) {
- id = is->readU32();
- sx = is->readU16();
- sy = is->readU16();
- sw = is->readU16();
- sh = is->readU16();
- flags = is->readU32();
-
- layout.add_screen(Screen(id, sx, sy, sw, sh, flags));
- }
-
- handler->setExtendedDesktopSize(x, y, w, h, layout);
-}
-
-void CMsgReaderV3::readFence()
-{
- rdr::U32 flags;
- rdr::U8 len;
- char data[64];
-
- is->skip(3);
-
- flags = is->readU32();
-
- len = is->readU8();
- if (len > sizeof(data)) {
- fprintf(stderr, "Ignoring fence with too large payload\n");
- is->skip(len);
- return;
- }
-
- is->readBytes(data, len);
-
- handler->fence(flags, len, data);
-}
-
-void CMsgReaderV3::readEndOfContinuousUpdates()
-{
- handler->endOfContinuousUpdates();
-}
diff --git a/common/rfb/CMsgWriter.cxx b/common/rfb/CMsgWriter.cxx
index 9ee7a02f..6536eaf2 100644
--- a/common/rfb/CMsgWriter.cxx
+++ b/common/rfb/CMsgWriter.cxx
@@ -1,4 +1,5 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
+ * Copyright 2009-2014 Pierre Ossman for Cendio AB
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -18,7 +19,9 @@
#include <stdio.h>
#include <rdr/OutStream.h>
#include <rfb/msgTypes.h>
+#include <rfb/fenceTypes.h>
#include <rfb/encodings.h>
+#include <rfb/Exception.h>
#include <rfb/PixelFormat.h>
#include <rfb/Rect.h>
#include <rfb/ConnParams.h>
@@ -36,6 +39,12 @@ CMsgWriter::~CMsgWriter()
{
}
+void CMsgWriter::writeClientInit(bool shared)
+{
+ os->writeU8(shared);
+ endMsg();
+}
+
void CMsgWriter::writeSetPixelFormat(const PixelFormat& pf)
{
startMsg(msgTypeSetPixelFormat);
@@ -104,9 +113,11 @@ void CMsgWriter::writeSetEncodings(int preferredEncoding, bool useCopyRect)
// Remaining encodings
for (int i = encodingMax; i >= 0; i--) {
switch (i) {
+ case encodingCopyRect:
case encodingTight:
case encodingZRLE:
case encodingHextile:
+ /* These have already been sent earlier */
break;
default:
if ((i != preferredEncoding) && Decoder::supported(i))
@@ -121,7 +132,35 @@ void CMsgWriter::writeSetEncodings(int preferredEncoding, bool useCopyRect)
writeSetEncodings(nEncodings, encodings);
}
-
+
+void CMsgWriter::writeSetDesktopSize(int width, int height,
+ const ScreenSet& layout)
+{
+ if (!cp->supportsSetDesktopSize)
+ throw Exception("Server does not support SetDesktopSize");
+
+ startMsg(msgTypeSetDesktopSize);
+ os->pad(1);
+
+ os->writeU16(width);
+ os->writeU16(height);
+
+ os->writeU8(layout.num_screens());
+ os->pad(1);
+
+ ScreenSet::const_iterator iter;
+ for (iter = layout.begin();iter != layout.end();++iter) {
+ os->writeU32(iter->id);
+ os->writeU16(iter->dimensions.tl.x);
+ os->writeU16(iter->dimensions.tl.y);
+ os->writeU16(iter->dimensions.width());
+ os->writeU16(iter->dimensions.height());
+ os->writeU32(iter->flags);
+ }
+
+ endMsg();
+}
+
void CMsgWriter::writeFramebufferUpdateRequest(const Rect& r, bool incremental)
{
startMsg(msgTypeFramebufferUpdateRequest);
@@ -133,6 +172,43 @@ void CMsgWriter::writeFramebufferUpdateRequest(const Rect& r, bool incremental)
endMsg();
}
+void CMsgWriter::writeEnableContinuousUpdates(bool enable,
+ int x, int y, int w, int h)
+{
+ if (!cp->supportsContinuousUpdates)
+ throw Exception("Server does not support continuous updates");
+
+ startMsg(msgTypeEnableContinuousUpdates);
+
+ os->writeU8(!!enable);
+
+ os->writeU16(x);
+ os->writeU16(y);
+ os->writeU16(w);
+ os->writeU16(h);
+
+ endMsg();
+}
+
+void CMsgWriter::writeFence(rdr::U32 flags, unsigned len, const char data[])
+{
+ if (!cp->supportsFence)
+ throw Exception("Server does not support fences");
+ if (len > 64)
+ throw Exception("Too large fence payload");
+ if ((flags & ~fenceFlagsSupported) != 0)
+ throw Exception("Unknown fence flags");
+
+ startMsg(msgTypeClientFence);
+ os->pad(3);
+
+ os->writeU32(flags);
+
+ os->writeU8(len);
+ os->writeBytes(data, len);
+
+ endMsg();
+}
void CMsgWriter::keyEvent(rdr::U32 key, bool down)
{
@@ -168,3 +244,13 @@ void CMsgWriter::clientCutText(const char* str, rdr::U32 len)
os->writeBytes(str, len);
endMsg();
}
+
+void CMsgWriter::startMsg(int type)
+{
+ os->writeU8(type);
+}
+
+void CMsgWriter::endMsg()
+{
+ os->flush();
+}
diff --git a/common/rfb/CMsgWriter.h b/common/rfb/CMsgWriter.h
index 66174598..06ecbe7d 100644
--- a/common/rfb/CMsgWriter.h
+++ b/common/rfb/CMsgWriter.h
@@ -1,5 +1,5 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
- * Copyright 2009-2011 Pierre Ossman for Cendio AB
+ * Copyright 2009-2014 Pierre Ossman for Cendio AB
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -23,8 +23,9 @@
#ifndef __RFB_CMSGWRITER_H__
#define __RFB_CMSGWRITER_H__
+#include <rdr/types.h>
+
#include <rfb/InputHandler.h>
-#include <rfb/ScreenSet.h>
namespace rdr { class OutStream; }
@@ -32,39 +33,35 @@ namespace rfb {
class PixelFormat;
class ConnParams;
+ class ScreenSet;
struct Rect;
class CMsgWriter : public InputHandler {
public:
+ CMsgWriter(ConnParams* cp, rdr::OutStream* os);
virtual ~CMsgWriter();
- // CMsgWriter abstract interface methods
- virtual void writeClientInit(bool shared)=0;
- virtual void startMsg(int type)=0;
- virtual void endMsg()=0;
+ void writeClientInit(bool shared);
+
+ void writeSetPixelFormat(const PixelFormat& pf);
+ void writeSetEncodings(int nEncodings, rdr::U32* encodings);
+ void writeSetEncodings(int preferredEncoding, bool useCopyRect);
+ void writeSetDesktopSize(int width, int height, const ScreenSet& layout);
- virtual void writeSetDesktopSize(int width, int height,
- const ScreenSet& layout)=0;
- virtual void writeFence(rdr::U32 flags, unsigned len, const char data[])=0;
- virtual void writeEnableContinuousUpdates(bool enable,
- int x, int y, int w, int h)=0;
+ void writeFramebufferUpdateRequest(const Rect& r,bool incremental);
+ void writeEnableContinuousUpdates(bool enable, int x, int y, int w, int h);
- // CMsgWriter implemented methods
- virtual void writeSetPixelFormat(const PixelFormat& pf);
- virtual void writeSetEncodings(int nEncodings, rdr::U32* encodings);
- virtual void writeSetEncodings(int preferredEncoding, bool useCopyRect);
- virtual void writeFramebufferUpdateRequest(const Rect& r,bool incremental);
+ void writeFence(rdr::U32 flags, unsigned len, const char data[]);
// InputHandler implementation
+
virtual void keyEvent(rdr::U32 key, bool down);
virtual void pointerEvent(const Point& pos, int buttonMask);
virtual void clientCutText(const char* str, rdr::U32 len);
- ConnParams* getConnParams() { return cp; }
- rdr::OutStream* getOutStream() { return os; }
-
protected:
- CMsgWriter(ConnParams* cp, rdr::OutStream* os);
+ void startMsg(int type);
+ void endMsg();
ConnParams* cp;
rdr::OutStream* os;
diff --git a/common/rfb/CMsgWriterV3.cxx b/common/rfb/CMsgWriterV3.cxx
deleted file mode 100644
index b96e2b37..00000000
--- a/common/rfb/CMsgWriterV3.cxx
+++ /dev/null
@@ -1,117 +0,0 @@
-/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
- * Copyright 2009-2011 Pierre Ossman for Cendio AB
- *
- * 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.
- */
-#include <rdr/OutStream.h>
-#include <rfb/msgTypes.h>
-#include <rfb/fenceTypes.h>
-#include <rfb/Exception.h>
-#include <rfb/ConnParams.h>
-#include <rfb/CMsgWriterV3.h>
-
-using namespace rfb;
-
-CMsgWriterV3::CMsgWriterV3(ConnParams* cp, rdr::OutStream* os)
- : CMsgWriter(cp, os)
-{
-}
-
-CMsgWriterV3::~CMsgWriterV3()
-{
-}
-
-void CMsgWriterV3::writeClientInit(bool shared)
-{
- os->writeU8(shared);
- endMsg();
-}
-
-void CMsgWriterV3::startMsg(int type)
-{
- os->writeU8(type);
-}
-
-void CMsgWriterV3::endMsg()
-{
- os->flush();
-}
-
-void CMsgWriterV3::writeSetDesktopSize(int width, int height,
- const ScreenSet& layout)
-{
- if (!cp->supportsSetDesktopSize)
- throw Exception("Server does not support SetDesktopSize");
-
- startMsg(msgTypeSetDesktopSize);
- os->pad(1);
-
- os->writeU16(width);
- os->writeU16(height);
-
- os->writeU8(layout.num_screens());
- os->pad(1);
-
- ScreenSet::const_iterator iter;
- for (iter = layout.begin();iter != layout.end();++iter) {
- os->writeU32(iter->id);
- os->writeU16(iter->dimensions.tl.x);
- os->writeU16(iter->dimensions.tl.y);
- os->writeU16(iter->dimensions.width());
- os->writeU16(iter->dimensions.height());
- os->writeU32(iter->flags);
- }
-
- endMsg();
-}
-
-void CMsgWriterV3::writeFence(rdr::U32 flags, unsigned len, const char data[])
-{
- if (!cp->supportsFence)
- throw Exception("Server does not support fences");
- if (len > 64)
- throw Exception("Too large fence payload");
- if ((flags & ~fenceFlagsSupported) != 0)
- throw Exception("Unknown fence flags");
-
- startMsg(msgTypeClientFence);
- os->pad(3);
-
- os->writeU32(flags);
-
- os->writeU8(len);
- os->writeBytes(data, len);
-
- endMsg();
-}
-
-void CMsgWriterV3::writeEnableContinuousUpdates(bool enable,
- int x, int y, int w, int h)
-{
- if (!cp->supportsContinuousUpdates)
- throw Exception("Server does not support continuous updates");
-
- startMsg(msgTypeEnableContinuousUpdates);
-
- os->writeU8(!!enable);
-
- os->writeU16(x);
- os->writeU16(y);
- os->writeU16(w);
- os->writeU16(h);
-
- endMsg();
-}
diff --git a/common/rfb/CMsgWriterV3.h b/common/rfb/CMsgWriterV3.h
deleted file mode 100644
index fb1c42c0..00000000
--- a/common/rfb/CMsgWriterV3.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
- * Copyright 2009-2011 Pierre Ossman for Cendio AB
- *
- * 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.
- */
-#ifndef __RFB_CMSGWRITERV3_H__
-#define __RFB_CMSGWRITERV3_H__
-
-#include <rfb/CMsgWriter.h>
-
-namespace rfb {
- class CMsgWriterV3 : public CMsgWriter {
- public:
- CMsgWriterV3(ConnParams* cp, rdr::OutStream* os);
- virtual ~CMsgWriterV3();
-
- virtual void writeClientInit(bool shared);
- virtual void startMsg(int type);
- virtual void endMsg();
-
- virtual void writeSetDesktopSize(int width, int height,
- const ScreenSet& layout);
- virtual void writeFence(rdr::U32 flags, unsigned len, const char data[]);
- virtual void writeEnableContinuousUpdates(bool enable,
- int x, int y, int w, int h);
- };
-}
-#endif
diff --git a/common/rfb/ColourCube.h b/common/rfb/ColourCube.h
deleted file mode 100644
index b83cbba8..00000000
--- a/common/rfb/ColourCube.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/* Copyright (C) 2002-2005 RealVNC Ltd. 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.
- */
-//
-// ColourCube - structure to represent a colour cube. The colour cube consists
-// of its dimensions (nRed x nGreen x nBlue) and a table mapping an (r,g,b)
-// triple to a pixel value.
-//
-// A colour cube is used in two cases. The first is internally in a viewer
-// when it cannot use a trueColour format, nor can it have exclusive access to
-// a writable colour map. This is most notably the case for an X viewer
-// wishing to use a PseudoColor X server's default colormap.
-//
-// The second use is on the server side when a client has asked for a colour
-// map and the server is trueColour. Instead of setting an uneven trueColour
-// format like bgr233, it can set the client's colour map up with a 6x6x6
-// colour cube. For this use the colour cube table has a null mapping, which
-// makes it easy to perform the reverse lookup operation from pixel value to
-// r,g,b values.
-
-#ifndef __RFB_COLOURCUBE_H__
-#define __RFB_COLOURCUBE_H__
-
-#include <rfb/Pixel.h>
-#include <rfb/ColourMap.h>
-
-namespace rfb {
-
- class ColourCube : public ColourMap {
- public:
- ColourCube(int nr, int ng, int nb, Pixel* table_=0)
- : nRed(nr), nGreen(ng), nBlue(nb), table(table_), deleteTable(false)
- {
- if (!table) {
- table = new Pixel[size()];
- deleteTable = true;
- // set a null mapping by default
- for (int i = 0; i < size(); i++)
- table[i] = i;
- }
- }
-
- ColourCube() : deleteTable(false) {}
-
- virtual ~ColourCube() {
- if (deleteTable) delete [] table;
- }
-
- void set(int r, int g, int b, Pixel p) {
- table[(r * nGreen + g) * nBlue + b] = p;
- }
-
- Pixel lookup(int r, int g, int b) const {
- return table[(r * nGreen + g) * nBlue + b];
- }
-
- int size() const { return nRed*nGreen*nBlue; }
- int redMult() const { return nGreen*nBlue; }
- int greenMult() const { return nBlue; }
- int blueMult() const { return 1; }
-
- // ColourMap lookup() method. Note that this only works when the table has
- // the default null mapping.
- virtual void lookup(int i, int* r, int* g, int* b) {
- if (i >= size()) return;
- *b = i % nBlue;
- i /= nBlue;
- *g = i % nGreen;
- *r = i / nGreen;
- *r = (*r * 65535 + (nRed-1) / 2) / (nRed-1);
- *g = (*g * 65535 + (nGreen-1) / 2) / (nGreen-1);
- *b = (*b * 65535 + (nBlue-1) / 2) / (nBlue-1);
- }
-
- int nRed;
- int nGreen;
- int nBlue;
- Pixel* table;
- bool deleteTable;
- };
-}
-#endif
diff --git a/common/rfb/ColourMap.h b/common/rfb/ColourMap.h
deleted file mode 100644
index c024adce..00000000
--- a/common/rfb/ColourMap.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
- * Copyright 2011 Pierre Ossman <ossman@cendio.se> for Cendio AB
- *
- * 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.
- */
-#ifndef __RFB_COLOURMAP_H__
-#define __RFB_COLOURMAP_H__
-namespace rfb {
- struct Colour {
- Colour() : r(0), g(0), b(0) {}
- Colour(int r_, int g_, int b_) : r(r_), g(g_), b(b_) {}
- int r, g, b;
- bool operator==(const Colour& c) const {return c.r == r && c.g == g && c.b == b;}
- bool operator!=(const Colour& c) const {return !(c == *this);}
- };
-
- class ColourMap {
- public:
- virtual void lookup(int index, int* r, int* g, int* b)=0;
- virtual ~ColourMap() {}
- };
-
- class SimpleColourMap : public ColourMap {
- public:
- SimpleColourMap(int size = 256) { table = new Colour[size]; };
- virtual ~SimpleColourMap() { delete [] table; };
-
- void lookup(int index, int* r, int* g, int* b)
- { *r = table[index].r; *g = table[index].g; *b = table[index].b; };
-
- void set(int index, int r, int g, int b)
- { table[index].r = r; table[index].g = g; table[index].b = b; };
-
- protected:
- Colour *table;
- };
-}
-#endif
diff --git a/common/rfb/SMsgReaderV3.h b/common/rfb/CopyRectDecoder.cxx
index 805fd876..bb3084fd 100644
--- a/common/rfb/SMsgReaderV3.h
+++ b/common/rfb/CopyRectDecoder.cxx
@@ -1,5 +1,4 @@
-/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
- * Copyright 2009-2011 Pierre Ossman for Cendio AB
+/* Copyright 2014 Pierre Ossman <ossman@cendio.se> for Cendio AB
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -16,22 +15,25 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
-#ifndef __RFB_SMSGREADERV3_H__
-#define __RFB_SMSGREADERV3_H__
+#include <rdr/InStream.h>
+#include <rfb/CConnection.h>
+#include <rfb/CMsgHandler.h>
+#include <rfb/PixelBuffer.h>
+#include <rfb/CopyRectDecoder.h>
-#include <rfb/SMsgReader.h>
+using namespace rfb;
-namespace rfb {
- class SMsgReaderV3 : public SMsgReader {
- public:
- SMsgReaderV3(SMsgHandler* handler, rdr::InStream* is);
- virtual ~SMsgReaderV3();
- virtual void readClientInit();
- virtual void readMsg();
- protected:
- virtual void readSetDesktopSize();
- virtual void readFence();
- virtual void readEnableContinuousUpdates();
- };
+CopyRectDecoder::CopyRectDecoder(CConnection* conn) : Decoder(conn)
+{
+}
+
+CopyRectDecoder::~CopyRectDecoder()
+{
+}
+
+void CopyRectDecoder::readRect(const Rect& r, CMsgHandler* handler)
+{
+ int srcX = conn->getInStream()->readU16();
+ int srcY = conn->getInStream()->readU16();
+ handler->copyRect(r, srcX, srcY);
}
-#endif
diff --git a/common/rfb/ImageGetter.h b/common/rfb/CopyRectDecoder.h
index 2e7bf376..5932066b 100644
--- a/common/rfb/ImageGetter.h
+++ b/common/rfb/CopyRectDecoder.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
+/* Copyright 2014 Pierre Ossman <ossman@cendio.se> for Cendio AB
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,17 +15,18 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
-#ifndef __RFB_IMAGEGETTER_H__
-#define __RFB_IMAGEGETTER_H__
+#ifndef __RFB_COPYRECTDECODER_H__
+#define __RFB_COPYRECTDECODER_H__
-#include <rfb/Rect.h>
+#include <rfb/Decoder.h>
namespace rfb {
- class ImageGetter {
+
+ class CopyRectDecoder : public Decoder {
public:
- virtual void getImage(void* imageBuf,
- const Rect& r, int stride=0) = 0;
- virtual ~ImageGetter() {}
+ CopyRectDecoder(CConnection* conn);
+ virtual ~CopyRectDecoder();
+ virtual void readRect(const Rect& r, CMsgHandler* handler);
};
}
#endif
diff --git a/common/rfb/Decoder.cxx b/common/rfb/Decoder.cxx
index e201821f..3faa9753 100644
--- a/common/rfb/Decoder.cxx
+++ b/common/rfb/Decoder.cxx
@@ -20,6 +20,7 @@
#include <rfb/encodings.h>
#include <rfb/Decoder.h>
#include <rfb/RawDecoder.h>
+#include <rfb/CopyRectDecoder.h>
#include <rfb/RREDecoder.h>
#include <rfb/HextileDecoder.h>
#include <rfb/ZRLEDecoder.h>
@@ -27,6 +28,10 @@
using namespace rfb;
+Decoder::Decoder(CConnection* conn_) : conn(conn_)
+{
+}
+
Decoder::~Decoder()
{
}
@@ -35,6 +40,7 @@ bool Decoder::supported(int encoding)
{
switch (encoding) {
case encodingRaw:
+ case encodingCopyRect:
case encodingRRE:
case encodingHextile:
case encodingZRLE:
@@ -45,19 +51,21 @@ bool Decoder::supported(int encoding)
}
}
-Decoder* Decoder::createDecoder(int encoding, CMsgReader* reader)
+Decoder* Decoder::createDecoder(int encoding, CConnection* conn)
{
switch (encoding) {
case encodingRaw:
- return new RawDecoder(reader);
+ return new RawDecoder(conn);
+ case encodingCopyRect:
+ return new CopyRectDecoder(conn);
case encodingRRE:
- return new RREDecoder(reader);
+ return new RREDecoder(conn);
case encodingHextile:
- return new HextileDecoder(reader);
+ return new HextileDecoder(conn);
case encodingZRLE:
- return new ZRLEDecoder(reader);
+ return new ZRLEDecoder(conn);
case encodingTight:
- return new TightDecoder(reader);
+ return new TightDecoder(conn);
default:
return NULL;
}
diff --git a/common/rfb/Decoder.h b/common/rfb/Decoder.h
index 025d63f5..870fa80e 100644
--- a/common/rfb/Decoder.h
+++ b/common/rfb/Decoder.h
@@ -22,16 +22,19 @@
#include <rfb/Rect.h>
namespace rfb {
- class CMsgReader;
+ class CConnection;
class CMsgHandler;
class Decoder {
public:
+ Decoder(CConnection* conn);
virtual ~Decoder();
virtual void readRect(const Rect& r, CMsgHandler* handler)=0;
static bool supported(int encoding);
- static Decoder* createDecoder(int encoding, CMsgReader* reader);
+ static Decoder* createDecoder(int encoding, CConnection* conn);
+ protected:
+ CConnection* conn;
};
}
diff --git a/common/rfb/Encoder.cxx b/common/rfb/Encoder.cxx
index 1733c8ec..89a5f149 100644
--- a/common/rfb/Encoder.cxx
+++ b/common/rfb/Encoder.cxx
@@ -25,9 +25,14 @@
#include <rfb/HextileEncoder.h>
#include <rfb/ZRLEEncoder.h>
#include <rfb/TightEncoder.h>
+#include <rfb/SConnection.h>
using namespace rfb;
+Encoder::Encoder(SConnection *conn_) : conn(conn_)
+{
+}
+
Encoder::~Encoder()
{
}
@@ -46,19 +51,19 @@ bool Encoder::supported(int encoding)
}
}
-Encoder* Encoder::createEncoder(int encoding, SMsgWriter* writer)
+Encoder* Encoder::createEncoder(int encoding, SConnection* conn)
{
switch (encoding) {
case encodingRaw:
- return new RawEncoder(writer);
+ return new RawEncoder(conn);
case encodingRRE:
- return new RREEncoder(writer);
+ return new RREEncoder(conn);
case encodingHextile:
- return new HextileEncoder(writer);
+ return new HextileEncoder(conn);
case encodingZRLE:
- return new ZRLEEncoder(writer);
+ return new ZRLEEncoder(conn);
case encodingTight:
- return new TightEncoder(writer);
+ return new TightEncoder(conn);
default:
return NULL;
}
diff --git a/common/rfb/Encoder.h b/common/rfb/Encoder.h
index 26d57963..2897f9f8 100644
--- a/common/rfb/Encoder.h
+++ b/common/rfb/Encoder.h
@@ -24,11 +24,12 @@
#include <rfb/TransImageGetter.h>
namespace rfb {
- class SMsgWriter;
+ class SConnection;
class TransImageGetter;
class Encoder {
public:
+ Encoder(SConnection* conn);
virtual ~Encoder();
virtual void setCompressLevel(int level) {};
@@ -36,14 +37,16 @@ namespace rfb {
virtual void setFineQualityLevel(int quality, int subsampling) {};
virtual int getNumRects(const Rect &r) { return 1; }
- // writeRect() tries to write the given rectangle. If it is unable to
- // write the whole rectangle it returns false and sets actual to the actual
- // rectangle which was updated.
- virtual bool writeRect(const Rect& r, TransImageGetter* ig,
- Rect* actual)=0;
+ // writeRect() is the main interface that encodes the given rectangle
+ // with data from the ImageGetter onto the SMsgWriter given at
+ // encoder creation.
+ virtual void writeRect(const Rect& r, TransImageGetter* ig)=0;
static bool supported(int encoding);
- static Encoder* createEncoder(int encoding, SMsgWriter* writer);
+ static Encoder* createEncoder(int encoding, SConnection* conn);
+
+ protected:
+ SConnection* conn;
};
}
diff --git a/common/rfb/HextileDecoder.cxx b/common/rfb/HextileDecoder.cxx
index ae612676..9b335fe9 100644
--- a/common/rfb/HextileDecoder.cxx
+++ b/common/rfb/HextileDecoder.cxx
@@ -16,14 +16,12 @@
* USA.
*/
#include <rfb/CMsgReader.h>
+#include <rfb/CConnection.h>
#include <rfb/CMsgHandler.h>
#include <rfb/HextileDecoder.h>
using namespace rfb;
-#define EXTRA_ARGS CMsgHandler* handler
-#define FILL_RECT(r, p) handler->fillRect(r, p)
-#define IMAGE_RECT(r, p) handler->imageRect(r, p)
#define BPP 8
#include <rfb/hextileDecode.h>
#undef BPP
@@ -34,7 +32,7 @@ using namespace rfb;
#include <rfb/hextileDecode.h>
#undef BPP
-HextileDecoder::HextileDecoder(CMsgReader* reader_) : reader(reader_)
+HextileDecoder::HextileDecoder(CConnection* conn) : Decoder(conn)
{
}
@@ -44,9 +42,9 @@ HextileDecoder::~HextileDecoder()
void HextileDecoder::readRect(const Rect& r, CMsgHandler* handler)
{
- rdr::InStream* is = reader->getInStream();
- rdr::U8* buf = reader->getImageBuf(16 * 16 * 4);
- switch (reader->bpp()) {
+ rdr::InStream* is = conn->getInStream();
+ rdr::U8* buf = conn->reader()->getImageBuf(16 * 16 * 4);
+ switch (conn->cp.pf().bpp) {
case 8: hextileDecode8 (r, is, (rdr::U8*) buf, handler); break;
case 16: hextileDecode16(r, is, (rdr::U16*)buf, handler); break;
case 32: hextileDecode32(r, is, (rdr::U32*)buf, handler); break;
diff --git a/common/rfb/HextileDecoder.h b/common/rfb/HextileDecoder.h
index 95a7f8a4..67dc791a 100644
--- a/common/rfb/HextileDecoder.h
+++ b/common/rfb/HextileDecoder.h
@@ -24,11 +24,9 @@ namespace rfb {
class HextileDecoder : public Decoder {
public:
- HextileDecoder(CMsgReader* reader);
+ HextileDecoder(CConnection* conn);
virtual ~HextileDecoder();
virtual void readRect(const Rect& r, CMsgHandler* handler);
- private:
- CMsgReader* reader;
};
}
#endif
diff --git a/common/rfb/HextileEncoder.cxx b/common/rfb/HextileEncoder.cxx
index 0907bab8..aa1b218a 100644
--- a/common/rfb/HextileEncoder.cxx
+++ b/common/rfb/HextileEncoder.cxx
@@ -19,6 +19,7 @@
#include <rfb/TransImageGetter.h>
#include <rfb/encodings.h>
#include <rfb/SMsgWriter.h>
+#include <rfb/SConnection.h>
#include <rfb/HextileEncoder.h>
#include <rfb/Configuration.h>
@@ -30,8 +31,6 @@ BoolParameter improvedHextile("ImprovedHextile",
"ratios by the cost of using more CPU time",
true);
-#define EXTRA_ARGS ImageGetter* ig
-#define GET_IMAGE_INTO_BUF(r,buf) ig->getImage(buf, r);
#define BPP 8
#include <rfb/hextileEncode.h>
#include <rfb/hextileEncodeBetter.h>
@@ -45,7 +44,7 @@ BoolParameter improvedHextile("ImprovedHextile",
#include <rfb/hextileEncodeBetter.h>
#undef BPP
-HextileEncoder::HextileEncoder(SMsgWriter* writer_) : writer(writer_)
+HextileEncoder::HextileEncoder(SConnection* conn) : Encoder(conn)
{
}
@@ -53,12 +52,11 @@ HextileEncoder::~HextileEncoder()
{
}
-bool HextileEncoder::writeRect(const Rect& r, TransImageGetter* ig,
- Rect* actual)
+void HextileEncoder::writeRect(const Rect& r, TransImageGetter* ig)
{
- writer->startRect(r, encodingHextile);
- rdr::OutStream* os = writer->getOutStream();
- switch (writer->bpp()) {
+ conn->writer()->startRect(r, encodingHextile);
+ rdr::OutStream* os = conn->getOutStream();
+ switch (conn->cp.pf().bpp) {
case 8:
if (improvedHextile) {
hextileEncodeBetter8(r, os, ig);
@@ -81,6 +79,5 @@ bool HextileEncoder::writeRect(const Rect& r, TransImageGetter* ig,
}
break;
}
- writer->endRect();
- return true;
+ conn->writer()->endRect();
}
diff --git a/common/rfb/HextileEncoder.h b/common/rfb/HextileEncoder.h
index 0c475a8e..723f5391 100644
--- a/common/rfb/HextileEncoder.h
+++ b/common/rfb/HextileEncoder.h
@@ -24,11 +24,9 @@ namespace rfb {
class HextileEncoder : public Encoder {
public:
- HextileEncoder(SMsgWriter* writer);
+ HextileEncoder(SConnection* conn);
virtual ~HextileEncoder();
- virtual bool writeRect(const Rect& r, TransImageGetter* ig, Rect* actual);
- private:
- SMsgWriter* writer;
+ virtual void writeRect(const Rect& r, TransImageGetter* ig);
};
}
#endif
diff --git a/common/rfb/Palette.h b/common/rfb/Palette.h
new file mode 100644
index 00000000..a9003354
--- /dev/null
+++ b/common/rfb/Palette.h
@@ -0,0 +1,190 @@
+/* Copyright (C) 2000-2005 Constantin Kaplinsky. All Rights Reserved.
+ * Copyright (C) 2011 D. R. Commander. All Rights Reserved.
+ * Copyright 2014 Pierre Ossman for Cendio AB
+ *
+ * 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.
+ */
+#ifndef __RFB_PALETTE_H__
+#define __RFB_PALETTE_H__
+
+#include <assert.h>
+#include <string.h>
+
+#include <rdr/types.h>
+
+namespace rfb {
+ class Palette {
+ public:
+ Palette() { clear(); }
+ ~Palette() {}
+
+ int size() const { return numColours; }
+
+ void clear() { numColours = 0; memset(hash, 0, sizeof(hash)); }
+
+ inline bool insert(rdr::U32 colour, int numPixels);
+ inline unsigned char lookup(rdr::U32 colour) const;
+ inline rdr::U32 getColour(unsigned char index) const;
+ inline int getCount(unsigned char index) const;
+
+ protected:
+ inline unsigned char genHash(rdr::U32 colour) const;
+
+ protected:
+ int numColours;
+
+ struct PaletteListNode {
+ PaletteListNode *next;
+ unsigned char idx;
+ rdr::U32 colour;
+ };
+
+ struct PaletteEntry {
+ PaletteListNode *listNode;
+ int numPixels;
+ };
+
+ // This is the raw list of colours, allocated from 0 and up
+ PaletteListNode list[256];
+ // Hash table for quick lookup into the list above
+ PaletteListNode *hash[256];
+ // Occurances of each colour, where the 0:th entry is the most common.
+ // Indices also refer to this array.
+ PaletteEntry entry[256];
+ };
+}
+
+inline bool rfb::Palette::insert(rdr::U32 colour, int numPixels)
+{
+ PaletteListNode* pnode;
+ PaletteListNode* prev_pnode;
+ unsigned char hash_key, idx;
+
+ hash_key = genHash(colour);
+
+ pnode = hash[hash_key];
+ prev_pnode = NULL;
+
+ // Do we already have an entry for this colour?
+ while (pnode != NULL) {
+ if (pnode->colour == colour) {
+ // Yup
+
+ idx = pnode->idx;
+ numPixels = entry[idx].numPixels + numPixels;
+
+ // The extra pixels might mean we have to adjust the sort list
+ while (idx > 0) {
+ if (entry[idx-1].numPixels >= numPixels)
+ break;
+ entry[idx] = entry[idx-1];
+ entry[idx].listNode->idx = idx;
+ idx--;
+ }
+
+ if (idx != pnode->idx) {
+ entry[idx].listNode = pnode;
+ pnode->idx = idx;
+ }
+
+ entry[idx].numPixels = numPixels;
+
+ return true;
+ }
+
+ prev_pnode = pnode;
+ pnode = pnode->next;
+ }
+
+ // Check if palette is full.
+ if (numColours == 256)
+ return false;
+
+ // Create a new colour entry
+ pnode = &list[numColours];
+ pnode->next = NULL;
+ pnode->idx = 0;
+ pnode->colour = colour;
+
+ // Add it to the hash table
+ if (prev_pnode != NULL)
+ prev_pnode->next = pnode;
+ else
+ hash[hash_key] = pnode;
+
+ // Move palette entries with lesser pixel counts.
+ idx = numColours;
+ while (idx > 0) {
+ if (entry[idx-1].numPixels >= numPixels)
+ break;
+ entry[idx] = entry[idx-1];
+ entry[idx].listNode->idx = idx;
+ idx--;
+ }
+
+ // And add it into the freed slot.
+ pnode->idx = idx;
+ entry[idx].listNode = pnode;
+ entry[idx].numPixels = numPixels;
+
+ numColours++;
+
+ return true;
+}
+
+inline unsigned char rfb::Palette::lookup(rdr::U32 colour) const
+{
+ unsigned char hash_key;
+ PaletteListNode* pnode;
+
+ hash_key = genHash(colour);
+ pnode = hash[hash_key];
+
+ while (pnode != NULL) {
+ if (pnode->colour == colour)
+ return pnode->idx;
+ pnode = pnode->next;
+ }
+
+ // We are being fed a bad colour
+ assert(false);
+
+ return 0;
+}
+
+inline rdr::U32 rfb::Palette::getColour(unsigned char index) const
+{
+ return entry[index].listNode->colour;
+}
+
+inline int rfb::Palette::getCount(unsigned char index) const
+{
+ return entry[index].numPixels;
+}
+
+inline unsigned char rfb::Palette::genHash(rdr::U32 colour) const
+{
+ unsigned char hash_key;
+
+ // djb2 hash function
+ hash_key = 5; // 5381 & 0xff
+ for (int i = 0; i < 32; i += 8)
+ hash_key = ((hash_key << 5) + hash_key) ^ (colour >> i);
+
+ return hash_key;
+}
+
+#endif
diff --git a/common/rfb/PixelBuffer.cxx b/common/rfb/PixelBuffer.cxx
index 9d151b97..ea19d183 100644
--- a/common/rfb/PixelBuffer.cxx
+++ b/common/rfb/PixelBuffer.cxx
@@ -1,4 +1,5 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
+ * Copyright 2014 Pierre Ossman for Cendio AB
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -33,18 +34,13 @@ static LogWriter vlog("PixelBuffer");
// -=- Generic pixel buffer class
-PixelBuffer::PixelBuffer(const PixelFormat& pf, int w, int h, ColourMap* cm)
- : format(pf), width_(w), height_(h), colourmap(cm) {}
-PixelBuffer::PixelBuffer() : width_(0), height_(0), colourmap(0) {}
+PixelBuffer::PixelBuffer(const PixelFormat& pf, int w, int h)
+ : format(pf), width_(w), height_(h) {}
+PixelBuffer::PixelBuffer() : width_(0), height_(0) {}
PixelBuffer::~PixelBuffer() {}
-void PixelBuffer::setPF(const PixelFormat &pf) {format = pf;}
-const PixelFormat& PixelBuffer::getPF() const {return format;}
-ColourMap* PixelBuffer::getColourMap() const {return colourmap;}
-
-
void
PixelBuffer::getImage(void* imageBuf, const Rect& r, int outStride) {
int inStride;
@@ -65,63 +61,10 @@ PixelBuffer::getImage(void* imageBuf, const Rect& r, int outStride) {
}
-static void fillRect8(U8 *buf, int stride, const Rect& r, Pixel pix)
-{
- U8* ptr = buf;
- int w = r.width(), h = r.height();
-
- while (h > 0) {
- memset(ptr, pix, w);
- ptr += stride;
- h--;
- }
-}
-
-static void fillRect16(U8 *buf, int stride, const Rect& r, Pixel pix)
-{
- U16* ptr = (U16 *)buf;
- int w = r.width(), h = r.height(), wBytes = w * 2;
-
- while (w > 0) {
- *ptr++ = pix; w--;
- }
- h--;
-
- ptr = (U16 *)buf;
-
- while (h > 0) {
- U16 *oldptr = ptr;
- memcpy(ptr += stride, oldptr, wBytes);
- h--;
- }
-}
-
-static void fillRect32(U8 *buf, int stride, const Rect& r, Pixel pix)
-{
- U32* ptr = (U32 *)buf;
- int w = r.width(), h = r.height(), wBytes = w * 4;
-
- while (w > 0) {
- *ptr++ = pix; w--;
- }
- h--;
-
- ptr = (U32 *)buf;
-
- while (h > 0) {
- U32 *oldptr = ptr;
- memcpy(ptr += stride, oldptr, wBytes);
- h--;
- }
-}
-
-
FullFramePixelBuffer::FullFramePixelBuffer(const PixelFormat& pf, int w, int h,
- rdr::U8* data_, ColourMap* cm)
- : PixelBuffer(pf, w, h, cm), data(data_)
+ rdr::U8* data_, int stride_)
+ : PixelBuffer(pf, w, h), data(data_), stride(stride_)
{
- // Called again to configure the fill function
- setPF(pf);
}
FullFramePixelBuffer::FullFramePixelBuffer() : data(0) {}
@@ -129,42 +72,33 @@ FullFramePixelBuffer::FullFramePixelBuffer() : data(0) {}
FullFramePixelBuffer::~FullFramePixelBuffer() {}
-void FullFramePixelBuffer::setPF(const PixelFormat &pf) {
- // We have this as a separate method for ManagedPixelBuffer's
- // sake. Direct users of FullFramePixelBuffer aren't allowed
- // to call it.
-
- PixelBuffer::setPF(pf);
-
- switch(pf.bpp) {
- case 8:
- fillRectFn = fillRect8;
- break;
- case 16:
- fillRectFn = fillRect16;
- break;
- case 32:
- fillRectFn = fillRect32;
- break;
- default:
- throw Exception("rfb::FullFramePixelBuffer - Unsupported pixel format");
- }
-}
-
-
-int FullFramePixelBuffer::getStride() const { return width(); }
-
-rdr::U8* FullFramePixelBuffer::getBufferRW(const Rect& r, int* stride)
+rdr::U8* FullFramePixelBuffer::getBufferRW(const Rect& r, int* stride_)
{
- *stride = getStride();
- return &data[(r.tl.x + (r.tl.y * *stride)) * format.bpp/8];
+ *stride_ = stride;
+ return &data[(r.tl.x + (r.tl.y * stride)) * format.bpp/8];
}
void FullFramePixelBuffer::fillRect(const Rect& r, Pixel pix) {
int stride;
- U8 *buf = getBufferRW(r, &stride);
- fillRectFn(buf, stride, r, pix);
+ U8 *buf, pixbuf[4];
+ int w, h, b;
+
+ buf = getBufferRW(r, &stride);
+ w = r.width();
+ h = r.height();
+ b = format.bpp/8;
+
+ format.bufferFromPixel(pixbuf, pix);
+
+ while (h--) {
+ int w_ = w;
+ while (w_--) {
+ memcpy(buf, pixbuf, b);
+ buf += b;
+ }
+ buf += (stride - w) * b;
+ }
}
void FullFramePixelBuffer::imageRect(const Rect& r, const void* pixels, int srcStride) {
@@ -314,40 +248,32 @@ void FullFramePixelBuffer::copyRect(const Rect &rect, const Point &move_by_delta
// Automatically allocates enough space for the specified format & area
ManagedPixelBuffer::ManagedPixelBuffer()
- : datasize(0), own_colourmap(false)
+ : datasize(0)
{
checkDataSize();
};
ManagedPixelBuffer::ManagedPixelBuffer(const PixelFormat& pf, int w, int h)
- : FullFramePixelBuffer(pf, w, h, 0, 0), datasize(0), own_colourmap(false)
+ : FullFramePixelBuffer(pf, w, h, NULL, w), datasize(0)
{
checkDataSize();
};
ManagedPixelBuffer::~ManagedPixelBuffer() {
if (data) delete [] data;
- if (colourmap && own_colourmap) delete colourmap;
};
void
ManagedPixelBuffer::setPF(const PixelFormat &pf) {
- FullFramePixelBuffer::setPF(pf); checkDataSize();
+ format = pf; checkDataSize();
};
void
ManagedPixelBuffer::setSize(int w, int h) {
- width_ = w; height_ = h; checkDataSize();
+ width_ = w; height_ = h; stride = w; checkDataSize();
};
-void
-ManagedPixelBuffer::setColourMap(ColourMap* cm, bool own_cm) {
- if (colourmap && own_colourmap) delete colourmap;
- colourmap = cm;
- own_colourmap = own_cm;
-}
-
inline void
ManagedPixelBuffer::checkDataSize() {
unsigned long new_datasize = width_ * height_ * (format.bpp/8);
diff --git a/common/rfb/PixelBuffer.h b/common/rfb/PixelBuffer.h
index 5c4f9666..59d71c79 100644
--- a/common/rfb/PixelBuffer.h
+++ b/common/rfb/PixelBuffer.h
@@ -1,4 +1,5 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
+ * Copyright 2014 Pierre Ossman for Cendio AB
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -24,9 +25,7 @@
#ifndef __RFB_PIXEL_BUFFER_H__
#define __RFB_PIXEL_BUFFER_H__
-#include <rfb/ImageGetter.h>
#include <rfb/PixelFormat.h>
-#include <rfb/ColourMap.h>
#include <rfb/Rect.h>
#include <rfb/Pixel.h>
@@ -34,22 +33,18 @@ namespace rfb {
class Region;
- class PixelBuffer : public ImageGetter {
+ class PixelBuffer {
public:
- PixelBuffer(const PixelFormat& pf, int width, int height, ColourMap* cm);
+ PixelBuffer(const PixelFormat& pf, int width, int height);
virtual ~PixelBuffer();
///////////////////////////////////////////////
// Format / Layout
//
- // Set/get pixel format & colourmap
- protected:
- // Only for subclasses that support changing parameters
- virtual void setPF(const PixelFormat &pf);
public:
- virtual const PixelFormat &getPF() const;
- virtual ColourMap* getColourMap() const;
+ // Get pixel format
+ const PixelFormat &getPF() const { return format; }
// Get width, height and number of pixels
int width() const { return width_; }
@@ -75,8 +70,9 @@ namespace rfb {
// Get pixel data for a given part of the buffer
// Data is copied into the supplied buffer, with the specified
- // stride.
- virtual void getImage(void* imageBuf, const Rect& r, int stride=0);
+ // stride. Try to avoid using this though as getBuffer() will in
+ // most cases avoid the extra memory copy.
+ void getImage(void* imageBuf, const Rect& r, int stride=0);
///////////////////////////////////////////////
// Framebuffer update methods
@@ -91,7 +87,6 @@ namespace rfb {
PixelBuffer();
PixelFormat format;
int width_, height_;
- ColourMap* colourmap;
};
// FullFramePixelBuffer
@@ -99,17 +94,10 @@ namespace rfb {
class FullFramePixelBuffer : public PixelBuffer {
public:
FullFramePixelBuffer(const PixelFormat& pf, int width, int height,
- rdr::U8* data_, ColourMap* cm);
+ rdr::U8* data, int stride);
virtual ~FullFramePixelBuffer();
- protected:
- virtual void setPF(const PixelFormat &pf);
-
public:
- // - Get the number of pixels per row in the actual pixel buffer data area
- // This may in some cases NOT be the same as width().
- virtual int getStride() const;
-
// Get a pointer to specified pixel data
virtual const rdr::U8* getBuffer(const Rect& r, int* stride) {
return getBufferRW(r, stride);
@@ -121,30 +109,29 @@ namespace rfb {
// These operations DO NOT clip to the pixelbuffer area, or trap overruns.
// Fill a rectangle
- virtual void fillRect(const Rect &dest, Pixel pix);
+ void fillRect(const Rect &dest, Pixel pix);
// Copy pixel data to the buffer
- virtual void imageRect(const Rect &dest, const void* pixels, int stride=0);
+ void imageRect(const Rect &dest, const void* pixels, int stride=0);
// Copy pixel data from one PixelBuffer location to another
- virtual void copyRect(const Rect &dest, const Point &move_by_delta);
+ void copyRect(const Rect &dest, const Point& move_by_delta);
// Copy pixel data to the buffer through a mask
// pixels is a pointer to the pixel to be copied to r.tl.
// maskPos specifies the pixel offset in the mask to start from.
// mask_ is a pointer to the mask bits at (0,0).
// pStride and mStride are the strides of the pixel and mask buffers.
- virtual void maskRect(const Rect& r, const void* pixels, const void* mask_);
+ void maskRect(const Rect& r, const void* pixels, const void* mask_);
// pixel is the Pixel value to be used where mask_ is set
- virtual void maskRect(const Rect& r, Pixel pixel, const void* mask_);
-
- // *** Should this be visible?
- rdr::U8* data;
+ void maskRect(const Rect& r, Pixel pixel, const void* mask_);
protected:
FullFramePixelBuffer();
- void (*fillRectFn)(rdr::U8 *, int, const Rect&, Pixel);
+
+ rdr::U8* data;
+ int stride;
};
// -=- Managed pixel buffer class
@@ -160,15 +147,11 @@ namespace rfb {
virtual void setPF(const PixelFormat &pf);
virtual void setSize(int w, int h);
- // Assign a colour map to the buffer
- virtual void setColourMap(ColourMap* cm, bool own_cm);
-
// Return the total number of bytes of pixel data in the buffer
int dataLen() const { return width_ * height_ * (format.bpp/8); }
protected:
unsigned long datasize;
- bool own_colourmap;
void checkDataSize();
};
diff --git a/common/rfb/PixelFormat.cxx b/common/rfb/PixelFormat.cxx
index b11f8836..9e762d9d 100644
--- a/common/rfb/PixelFormat.cxx
+++ b/common/rfb/PixelFormat.cxx
@@ -53,16 +53,51 @@ PixelFormat::PixelFormat()
bool PixelFormat::equal(const PixelFormat& other) const
{
- return (bpp == other.bpp &&
- depth == other.depth &&
- (bigEndian == other.bigEndian || bpp == 8) &&
- trueColour == other.trueColour &&
- (!trueColour || (redMax == other.redMax &&
- greenMax == other.greenMax &&
- blueMax == other.blueMax &&
- redShift == other.redShift &&
- greenShift == other.greenShift &&
- blueShift == other.blueShift)));
+ if (bpp != other.bpp || depth != other.depth)
+ return false;
+
+ if (redMax != other.redMax)
+ return false;
+ if (greenMax != other.greenMax)
+ return false;
+ if (blueMax != other.blueMax)
+ return false;
+
+ // Endianness requires more care to determine compatibility
+ if (bigEndian == other.bigEndian || bpp == 8) {
+ if (redShift != other.redShift)
+ return false;
+ if (greenShift != other.greenShift)
+ return false;
+ if (blueShift != other.blueShift)
+ return false;
+ } else {
+ // Has to be the same byte for each channel
+ if (redShift/8 != (3 - other.redShift/8))
+ return false;
+ if (greenShift/8 != (3 - other.greenShift/8))
+ return false;
+ if (blueShift/8 != (3 - other.blueShift/8))
+ return false;
+
+ // And the same bit offset within the byte
+ if (redShift%8 != other.redShift%8)
+ return false;
+ if (greenShift%8 != other.greenShift%8)
+ return false;
+ if (blueShift%8 != other.blueShift%8)
+ return false;
+
+ // And not cross a byte boundary
+ if (redShift/8 != (redShift + redBits - 1)/8)
+ return false;
+ if (greenShift/8 != (greenShift + greenBits - 1)/8)
+ return false;
+ if (blueShift/8 != (blueShift + blueBits - 1)/8)
+ return false;
+ }
+
+ return true;
}
void PixelFormat::read(rdr::InStream* is)
@@ -79,6 +114,18 @@ void PixelFormat::read(rdr::InStream* is)
blueShift = is->readU8();
is->skip(3);
+ // We have no real support for colour maps. If the client
+ // wants one, then we force a 8-bit true colour format and
+ // pretend it's a colour map.
+ if (!trueColour) {
+ redMax = 7;
+ greenMax = 7;
+ blueMax = 3;
+ redShift = 0;
+ greenShift = 3;
+ blueShift = 6;
+ }
+
if (!isSane())
throw Exception("invalid pixel format");
@@ -132,14 +179,13 @@ bool PixelFormat::isLittleEndian(void) const
}
-void PixelFormat::bufferFromRGB(rdr::U8 *dst, const rdr::U8* src,
- int pixels, ColourMap* cm) const
+void PixelFormat::bufferFromRGB(rdr::U8 *dst, const rdr::U8* src, int pixels) const
{
- bufferFromRGB(dst, src, pixels, pixels, 1, cm);
+ bufferFromRGB(dst, src, pixels, pixels, 1);
}
void PixelFormat::bufferFromRGB(rdr::U8 *dst, const rdr::U8* src,
- int w, int stride, int h, ColourMap* cm) const
+ int w, int stride, int h) const
{
if (is888()) {
// Optimised common case
@@ -188,7 +234,7 @@ void PixelFormat::bufferFromRGB(rdr::U8 *dst, const rdr::U8* src,
g = *(src++);
b = *(src++);
- p = pixelFromRGB(r, g, b, cm);
+ p = pixelFromRGB(r, g, b);
bufferFromPixel(dst, p);
dst += bpp/8;
@@ -199,26 +245,14 @@ void PixelFormat::bufferFromRGB(rdr::U8 *dst, const rdr::U8* src,
}
-void PixelFormat::rgbFromPixel(Pixel p, ColourMap* cm, Colour* rgb) const
-{
- rdr::U16 r, g, b;
-
- rgbFromPixel(p, cm, &r, &g, &b);
-
- rgb->r = r;
- rgb->g = g;
- rgb->b = b;
-}
-
-
-void PixelFormat::rgbFromBuffer(rdr::U8* dst, const rdr::U8* src, int pixels, ColourMap* cm) const
+void PixelFormat::rgbFromBuffer(rdr::U8* dst, const rdr::U8* src, int pixels) const
{
- rgbFromBuffer(dst, src, pixels, pixels, 1, cm);
+ rgbFromBuffer(dst, src, pixels, pixels, 1);
}
void PixelFormat::rgbFromBuffer(rdr::U8* dst, const rdr::U8* src,
- int w, int stride, int h, ColourMap* cm) const
+ int w, int stride, int h) const
{
if (is888()) {
// Optimised common case
@@ -260,7 +294,7 @@ void PixelFormat::rgbFromBuffer(rdr::U8* dst, const rdr::U8* src,
p = pixelFromBuffer(src);
- rgbFromPixel(p, cm, &r, &g, &b);
+ rgbFromPixel(p, &r, &g, &b);
*(dst++) = r;
*(dst++) = g;
@@ -449,36 +483,34 @@ bool PixelFormat::isSane(void)
if (!trueColour && (depth != 8))
return false;
- if (trueColour) {
- if ((redMax & (redMax + 1)) != 0)
- return false;
- if ((greenMax & (greenMax + 1)) != 0)
- return false;
- if ((blueMax & (blueMax + 1)) != 0)
- return false;
+ if ((redMax & (redMax + 1)) != 0)
+ return false;
+ if ((greenMax & (greenMax + 1)) != 0)
+ return false;
+ if ((blueMax & (blueMax + 1)) != 0)
+ return false;
- /*
- * We don't allow individual channels > 8 bits in order to keep our
- * conversions simple.
- */
- if (redMax >= (1 << 8))
- return false;
- if (greenMax >= (1 << 8))
- return false;
- if (blueMax >= (1 << 8))
- return false;
+ /*
+ * We don't allow individual channels > 8 bits in order to keep our
+ * conversions simple.
+ */
+ if (redMax >= (1 << 8))
+ return false;
+ if (greenMax >= (1 << 8))
+ return false;
+ if (blueMax >= (1 << 8))
+ return false;
- totalBits = bits(redMax) + bits(greenMax) + bits(blueMax);
- if (totalBits > bpp)
- return false;
+ totalBits = bits(redMax) + bits(greenMax) + bits(blueMax);
+ if (totalBits > bpp)
+ return false;
- if (((redMax << redShift) & (greenMax << greenShift)) != 0)
- return false;
- if (((redMax << redShift) & (blueMax << blueShift)) != 0)
- return false;
- if (((greenMax << greenShift) & (blueMax << blueShift)) != 0)
- return false;
- }
+ if (((redMax << redShift) & (greenMax << greenShift)) != 0)
+ return false;
+ if (((redMax << redShift) & (blueMax << blueShift)) != 0)
+ return false;
+ if (((greenMax << greenShift) & (blueMax << blueShift)) != 0)
+ return false;
return true;
}
diff --git a/common/rfb/PixelFormat.h b/common/rfb/PixelFormat.h
index a8408ddd..c3db8783 100644
--- a/common/rfb/PixelFormat.h
+++ b/common/rfb/PixelFormat.h
@@ -35,7 +35,6 @@
#define __RFB_PIXELFORMAT_H__
#include <rfb/Pixel.h>
-#include <rfb/ColourMap.h>
namespace rdr { class InStream; class OutStream; }
@@ -44,9 +43,12 @@ namespace rfb {
class PixelFormat {
public:
PixelFormat(int b, int d, bool e, bool t,
- int rm=0, int gm=0, int bm=0, int rs=0, int gs=0, int bs=0);
+ int rm, int gm, int bm, int rs, int gs, int bs);
PixelFormat();
+ // Checks if the formats have identical buffer representation.
+ // They might still have different pixel representation, endianness
+ // or true colour state.
bool equal(const PixelFormat& other) const;
void read(rdr::InStream* is);
@@ -59,20 +61,19 @@ namespace rfb {
inline Pixel pixelFromBuffer(const rdr::U8* buffer) const;
inline void bufferFromPixel(rdr::U8* buffer, Pixel pixel) const;
- inline Pixel pixelFromRGB(rdr::U16 red, rdr::U16 green, rdr::U16 blue, ColourMap* cm=0) const;
- inline Pixel pixelFromRGB(rdr::U8 red, rdr::U8 green, rdr::U8 blue, ColourMap* cm=0) const;
+ inline Pixel pixelFromRGB(rdr::U16 red, rdr::U16 green, rdr::U16 blue) const;
+ inline Pixel pixelFromRGB(rdr::U8 red, rdr::U8 green, rdr::U8 blue) const;
- void bufferFromRGB(rdr::U8 *dst, const rdr::U8* src, int pixels, ColourMap* cm=0) const;
- void bufferFromRGB(rdr::U8 *dst, const rdr::U8* src, int w, int stride,
- int h, ColourMap* cm=0) const;
+ void bufferFromRGB(rdr::U8 *dst, const rdr::U8* src, int pixels) const;
+ void bufferFromRGB(rdr::U8 *dst, const rdr::U8* src,
+ int w, int stride, int h) const;
- void rgbFromPixel(Pixel pix, ColourMap* cm, Colour* rgb) const;
- inline void rgbFromPixel(Pixel pix, ColourMap* cm, rdr::U16 *r, rdr::U16 *g, rdr::U16 *b) const;
- inline void rgbFromPixel(Pixel pix, ColourMap* cm, rdr::U8 *r, rdr::U8 *g, rdr::U8 *b) const;
+ inline void rgbFromPixel(Pixel pix, rdr::U16 *r, rdr::U16 *g, rdr::U16 *b) const;
+ inline void rgbFromPixel(Pixel pix, rdr::U8 *r, rdr::U8 *g, rdr::U8 *b) const;
- void rgbFromBuffer(rdr::U8* dst, const rdr::U8* src, int pixels, ColourMap* cm=0) const;
- void rgbFromBuffer(rdr::U8* dst, const rdr::U8* src, int w, int stride,
- int h, ColourMap* cm=0) const;
+ void rgbFromBuffer(rdr::U8* dst, const rdr::U8* src, int pixels) const;
+ void rgbFromBuffer(rdr::U8* dst, const rdr::U8* src,
+ int w, int stride, int h) const;
void print(char* str, int len) const;
bool parse(const char* str);
@@ -84,6 +85,9 @@ namespace rfb {
public:
int bpp;
int depth;
+
+ // This only tracks if the client thinks it is in colour map mode.
+ // In practice we are always in true colour mode.
bool trueColour;
// FIXME: These should be protected, but we need to fix TransImageGetter first.
diff --git a/common/rfb/PixelFormat.inl b/common/rfb/PixelFormat.inl
index 547fae5d..4bc4a709 100644
--- a/common/rfb/PixelFormat.inl
+++ b/common/rfb/PixelFormat.inl
@@ -75,131 +75,81 @@ inline void PixelFormat::bufferFromPixel(rdr::U8* buffer, Pixel p) const
}
-inline Pixel PixelFormat::pixelFromRGB(rdr::U16 red, rdr::U16 green, rdr::U16 blue, ColourMap* cm) const
+inline Pixel PixelFormat::pixelFromRGB(rdr::U16 red, rdr::U16 green, rdr::U16 blue) const
{
- if (trueColour) {
- Pixel p;
-
- /* We don't need to mask since we shift out unwanted bits */
- p = ((Pixel)red >> (16 - redBits)) << redShift;
- p |= ((Pixel)green >> (16 - greenBits)) << greenShift;
- p |= ((Pixel)blue >> (16 - blueBits)) << blueShift;
- } else if (cm) {
- // Try to find the closest pixel by Cartesian distance
- int colours = 1 << depth;
- int diff = 256 * 256 * 4;
- int col = 0;
- for (int i=0; i<colours; i++) {
- int r, g, b;
- cm->lookup(i, &r, &g, &b);
- int rd = (r-red) >> 8;
- int gd = (g-green) >> 8;
- int bd = (b-blue) >> 8;
- int d = rd*rd + gd*gd + bd*bd;
- if (d < diff) {
- col = i;
- diff = d;
- }
- }
- return col;
- } else {
- // XXX just return 0 for colour map?
- return 0;
- }
+ Pixel p;
+
+ /* We don't need to mask since we shift out unwanted bits */
+ p = ((Pixel)red >> (16 - redBits)) << redShift;
+ p |= ((Pixel)green >> (16 - greenBits)) << greenShift;
+ p |= ((Pixel)blue >> (16 - blueBits)) << blueShift;
+
+ return p;
}
-inline Pixel PixelFormat::pixelFromRGB(rdr::U8 red, rdr::U8 green, rdr::U8 blue, ColourMap* cm) const
+inline Pixel PixelFormat::pixelFromRGB(rdr::U8 red, rdr::U8 green, rdr::U8 blue) const
{
- if (trueColour) {
- Pixel p;
+ Pixel p;
- p = ((Pixel)red >> (8 - redBits)) << redShift;
- p |= ((Pixel)green >> (8 - greenBits)) << greenShift;
- p |= ((Pixel)blue >> (8 - blueBits)) << blueShift;
+ p = ((Pixel)red >> (8 - redBits)) << redShift;
+ p |= ((Pixel)green >> (8 - greenBits)) << greenShift;
+ p |= ((Pixel)blue >> (8 - blueBits)) << blueShift;
- return p;
- } else {
- return pixelFromRGB((rdr::U16)(red << 8 | red),
- (rdr::U16)(green << 8 | green),
- (rdr::U16)(blue << 8 | blue), cm);
- }
+ return p;
}
-inline void PixelFormat::rgbFromPixel(Pixel p, ColourMap* cm, rdr::U16 *r, rdr::U16 *g, rdr::U16 *b) const
+inline void PixelFormat::rgbFromPixel(Pixel p, rdr::U16 *r, rdr::U16 *g, rdr::U16 *b) const
{
- if (trueColour) {
- int mb, rb, gb, bb;
-
- /* Bit replication is much cheaper than multiplication and division */
-
- mb = minBits;
- rb = redBits;
- gb = greenBits;
- bb = blueBits;
-
- *r = (p >> redShift) << (16 - rb);
- *g = (p >> greenShift) << (16 - gb);
- *b = (p >> blueShift) << (16 - bb);
-
- while (mb < 16) {
- *r = *r | (*r >> rb);
- *g = *g | (*g >> gb);
- *b = *b | (*b >> bb);
- mb <<= 1;
- rb <<= 1;
- gb <<= 1;
- bb <<= 1;
- }
- } else if (cm) {
- int ir, ig, ib;
- cm->lookup(p, &ir, &ig, &ib);
- *r = ir;
- *g = ig;
- *b = ib;
- } else {
- // XXX just return 0 for colour map?
- *r = 0;
- *g = 0;
- *b = 0;
+ int mb, rb, gb, bb;
+
+ /* Bit replication is much cheaper than multiplication and division */
+
+ mb = minBits;
+ rb = redBits;
+ gb = greenBits;
+ bb = blueBits;
+
+ *r = (p >> redShift) << (16 - rb);
+ *g = (p >> greenShift) << (16 - gb);
+ *b = (p >> blueShift) << (16 - bb);
+
+ while (mb < 16) {
+ *r = *r | (*r >> rb);
+ *g = *g | (*g >> gb);
+ *b = *b | (*b >> bb);
+ mb <<= 1;
+ rb <<= 1;
+ gb <<= 1;
+ bb <<= 1;
}
}
-inline void PixelFormat::rgbFromPixel(Pixel p, ColourMap* cm, rdr::U8 *r, rdr::U8 *g, rdr::U8 *b) const
+inline void PixelFormat::rgbFromPixel(Pixel p, rdr::U8 *r, rdr::U8 *g, rdr::U8 *b) const
{
- if (trueColour) {
- int mb, rb, gb, bb;
-
- /* Bit replication is much cheaper than multiplication and division */
-
- mb = minBits;
- rb = redBits;
- gb = greenBits;
- bb = blueBits;
-
- *r = (p >> redShift) << (8 - rb);
- *g = (p >> greenShift) << (8 - gb);
- *b = (p >> blueShift) << (8 - bb);
-
- while (mb < 8) {
- *r = *r | (*r >> rb);
- *g = *g | (*g >> gb);
- *b = *b | (*b >> bb);
- mb <<= 1;
- rb <<= 1;
- gb <<= 1;
- bb <<= 1;
- }
- } else {
- rdr::U16 r2, g2, b2;
-
- rgbFromPixel(p, cm, &r2, &g2, &b2);
-
- *r = r2 >> 8;
- *g = g2 >> 8;
- *b = b2 >> 8;
+ int mb, rb, gb, bb;
+
+ /* Bit replication is much cheaper than multiplication and division */
+
+ mb = minBits;
+ rb = redBits;
+ gb = greenBits;
+ bb = blueBits;
+
+ *r = (p >> redShift) << (8 - rb);
+ *g = (p >> greenShift) << (8 - gb);
+ *b = (p >> blueShift) << (8 - bb);
+
+ while (mb < 8) {
+ *r = *r | (*r >> rb);
+ *g = *g | (*g >> gb);
+ *b = *b | (*b >> bb);
+ mb <<= 1;
+ rb <<= 1;
+ gb <<= 1;
+ bb <<= 1;
}
}
diff --git a/common/rfb/PixelTransformer.cxx b/common/rfb/PixelTransformer.cxx
index cedf9000..73ec349b 100644
--- a/common/rfb/PixelTransformer.cxx
+++ b/common/rfb/PixelTransformer.cxx
@@ -22,10 +22,7 @@
#include <string.h>
#include <rfb/PixelFormat.h>
#include <rfb/Exception.h>
-#include <rfb/ColourMap.h>
-#include <rfb/TrueColourMap.h>
#include <rfb/PixelBuffer.h>
-#include <rfb/ColourCube.h>
#include <rfb/PixelTransformer.h>
using namespace rfb;
@@ -100,50 +97,23 @@ static transFnType transRGBFns[][3] = {
{ transRGB16to8, transRGB16to16, transRGB16to32 },
{ transRGB32to8, transRGB32to16, transRGB32to32 }
};
-static transFnType transRGBCubeFns[][3] = {
- { transRGBCube16to8, transRGBCube16to16, transRGBCube16to32 },
- { transRGBCube32to8, transRGBCube32to16, transRGBCube32to32 }
-};
// Table initialisation functions.
-typedef void (*initCMtoTCFnType)(rdr::U8** tablep, const PixelFormat& inPF,
- ColourMap* cm, const PixelFormat& outPF);
-typedef void (*initTCtoTCFnType)(rdr::U8** tablep, const PixelFormat& inPF,
- const PixelFormat& outPF);
-typedef void (*initCMtoCubeFnType)(rdr::U8** tablep, const PixelFormat& inPF,
- ColourMap* cm, ColourCube* cube);
-typedef void (*initTCtoCubeFnType)(rdr::U8** tablep, const PixelFormat& inPF,
- ColourCube* cube);
-
+typedef void (*initFnType)(rdr::U8** tablep, const PixelFormat& inPF,
+ const PixelFormat& outPF);
-static initCMtoTCFnType initSimpleCMtoTCFns[] = {
- initSimpleCMtoTC8, initSimpleCMtoTC16, initSimpleCMtoTC32
+static initFnType initSimpleFns[] = {
+ initSimple8, initSimple16, initSimple32
};
-static initTCtoTCFnType initSimpleTCtoTCFns[] = {
- initSimpleTCtoTC8, initSimpleTCtoTC16, initSimpleTCtoTC32
-};
-
-static initCMtoCubeFnType initSimpleCMtoCubeFns[] = {
- initSimpleCMtoCube8, initSimpleCMtoCube16, initSimpleCMtoCube32
-};
-
-static initTCtoCubeFnType initSimpleTCtoCubeFns[] = {
- initSimpleTCtoCube8, initSimpleTCtoCube16, initSimpleTCtoCube32
-};
-
-static initTCtoTCFnType initRGBTCtoTCFns[] = {
- initRGBTCtoTC8, initRGBTCtoTC16, initRGBTCtoTC32
-};
-
-static initTCtoCubeFnType initRGBTCtoCubeFns[] = {
- initRGBTCtoCube8, initRGBTCtoCube16, initRGBTCtoCube32
+static initFnType initRGBFns[] = {
+ initRGB8, initRGB16, initRGB32
};
PixelTransformer::PixelTransformer(bool econ)
- : economic(econ), cmCallback(0), cube(0), table(0), transFn(0)
+ : economic(econ), table(0), transFn(0)
{
}
@@ -152,17 +122,11 @@ PixelTransformer::~PixelTransformer()
delete [] table;
}
-void PixelTransformer::init(const PixelFormat& inPF_, ColourMap* inCM_,
- const PixelFormat& outPF_, ColourCube* cube_,
- setCMFnType cmCallback_, void *cbData_)
+void PixelTransformer::init(const PixelFormat& inPF_,
+ const PixelFormat& outPF_)
{
inPF = inPF_;
- inCM = inCM_;
-
outPF = outPF_;
- cube = cube_;
- cmCallback = cmCallback_;
- cbData = cbData_;
if (table)
delete [] table;
@@ -175,79 +139,17 @@ void PixelTransformer::init(const PixelFormat& inPF_, ColourMap* inCM_,
if ((outPF.bpp != 8) && (outPF.bpp != 16) && (outPF.bpp != 32))
throw Exception("PixelTransformer: bpp out not 8, 16 or 32");
- if (!outPF.trueColour) {
- if (outPF.bpp != 8)
- throw Exception("PixelTransformer: outPF has color map but not 8bpp");
-
- if (!inPF.trueColour) {
- if (inPF.bpp != 8)
- throw Exception("PixelTransformer: inPF has colorMap but not 8bpp");
- if (!inCM)
- throw Exception("PixelTransformer: inPF has colorMap but no colour map specified");
-
- // CM to CM/Cube
-
- if (cube) {
- transFn = transSimpleFns[0][0];
- (*initSimpleCMtoCubeFns[0]) (&table, inPF, inCM, cube);
- } else {
- transFn = noTransFn;
- setColourMapEntries(0, 256);
- }
- return;
- }
-
- // TC to CM/Cube
-
- ColourCube defaultCube(6,6,6);
- if (!cube) cube = &defaultCube;
-
- if ((inPF.bpp > 16) || (economic && (inPF.bpp == 16))) {
- transFn = transRGBCubeFns[inPF.bpp/32][0];
- (*initRGBTCtoCubeFns[0]) (&table, inPF, cube);
- } else {
- transFn = transSimpleFns[inPF.bpp/16][0];
- (*initSimpleTCtoCubeFns[0]) (&table, inPF, cube);
- }
-
- if (cube != &defaultCube)
- return;
-
- if (!cmCallback)
- throw Exception("PixelTransformer: Neither colour map callback nor colour cube provided");
-
- cmCallback(0, 216, cube, cbData);
- cube = 0;
- return;
- }
-
if (inPF.equal(outPF)) {
transFn = noTransFn;
return;
}
- if (!inPF.trueColour) {
-
- // CM to TC
-
- if (inPF.bpp != 8)
- throw Exception("PixelTransformer: inPF has colorMap but not 8bpp");
- if (!inCM)
- throw Exception("PixelTransformer: inPF has colorMap but no colour map specified");
-
- transFn = transSimpleFns[0][outPF.bpp/16];
- (*initSimpleCMtoTCFns[outPF.bpp/16]) (&table, inPF, inCM, outPF);
- return;
- }
-
- // TC to TC
-
if ((inPF.bpp > 16) || (economic && (inPF.bpp == 16))) {
transFn = transRGBFns[inPF.bpp/32][outPF.bpp/16];
- (*initRGBTCtoTCFns[outPF.bpp/16]) (&table, inPF, outPF);
+ (*initRGBFns[outPF.bpp/16]) (&table, inPF, outPF);
} else {
transFn = transSimpleFns[inPF.bpp/16][outPF.bpp/16];
- (*initSimpleTCtoTCFns[outPF.bpp/16]) (&table, inPF, outPF);
+ (*initSimpleFns[outPF.bpp/16]) (&table, inPF, outPF);
}
}
@@ -256,39 +158,11 @@ const PixelFormat &PixelTransformer::getInPF() const
return inPF;
}
-const ColourMap *PixelTransformer::getInColourMap() const
-{
- return inCM;
-}
-
const PixelFormat &PixelTransformer::getOutPF() const
{
return outPF;
}
-const ColourCube *PixelTransformer::getOutColourCube() const
-{
- return cube;
-}
-
-void PixelTransformer::setColourMapEntries(int firstCol, int nCols)
-{
- if (nCols == 0)
- nCols = (1 << inPF.depth) - firstCol;
-
- if (inPF.trueColour) return; // shouldn't be called in this case
-
- if (outPF.trueColour) {
- (*initSimpleCMtoTCFns[outPF.bpp/16]) (&table, inPF, inCM, outPF);
- } else if (cube) {
- (*initSimpleCMtoCubeFns[outPF.bpp/16]) (&table, inPF, inCM, cube);
- } else {
- if (!cmCallback)
- throw Exception("PixelTransformer: Neither colour map callback nor colour cube provided");
- cmCallback(firstCol, nCols, inCM, cbData);
- }
-}
-
void PixelTransformer::translatePixels(const void* inPtr, void* outPtr,
int nPixels) const
{
diff --git a/common/rfb/PixelTransformer.h b/common/rfb/PixelTransformer.h
index 88ec7c40..818daf66 100644
--- a/common/rfb/PixelTransformer.h
+++ b/common/rfb/PixelTransformer.h
@@ -33,11 +33,7 @@ namespace rfb {
int outStride, int width, int height);
class SMsgWriter;
- class ColourMap;
class PixelBuffer;
- class ColourCube;
-
- typedef void (*setCMFnType)(int firstColour, int nColours, ColourMap* cm, void* data);
class PixelTransformer {
public:
@@ -47,32 +43,12 @@ namespace rfb {
// init() is called to initialise the translation tables. The inPF and
// inCM arguments give the source format details, outPF gives the
- // target pixel format. If the target has a colour map, then the you
- // must specify either a colour map callback or a colour cube to indicate
- // how the target colour map should be handled. If both are specified
- // then the cube will be used.
+ // target pixel format.
- void init(const PixelFormat& inPF, ColourMap* inCM,
- const PixelFormat& outPF, ColourCube* cube = NULL,
- setCMFnType cmCallback = NULL, void *cbData = NULL);
+ void init(const PixelFormat& inPF, const PixelFormat& outPF);
const PixelFormat &getInPF() const;
- const ColourMap *getInColourMap() const;
-
const PixelFormat &getOutPF() const;
- const ColourCube *getOutColourCube() const;
-
- // setColourMapEntries() is called when the colour map specified to init()
- // has changed. firstColour and nColours specify which part of the
- // colour map has changed. If nColours is 0, this means the rest of the
- // colour map. If the target also has a colour map, then the callback or
- // cube specified to init() will be used. If the target is true colour
- // then instead we update the internal translation table - in this case
- // the caller should also make sure that the target surface receives an
- // update of the relevant parts (the simplest thing to do is just update
- // the whole framebuffer, though it is possible to be smarter than this).
-
- void setColourMapEntries(int firstColour, int nColours);
// translatePixels() translates the given number of pixels from inPtr,
// putting it into the buffer pointed to by outPtr. The pixels at inPtr
@@ -91,12 +67,7 @@ namespace rfb {
bool economic;
PixelFormat inPF;
- ColourMap* inCM;
-
PixelFormat outPF;
- setCMFnType cmCallback;
- void *cbData;
- ColourCube* cube;
rdr::U8* table;
transFnType transFn;
diff --git a/common/rfb/RREDecoder.cxx b/common/rfb/RREDecoder.cxx
index b81a4a82..ecc97136 100644
--- a/common/rfb/RREDecoder.cxx
+++ b/common/rfb/RREDecoder.cxx
@@ -16,14 +16,12 @@
* USA.
*/
#include <rfb/CMsgReader.h>
+#include <rfb/CConnection.h>
#include <rfb/CMsgHandler.h>
#include <rfb/RREDecoder.h>
using namespace rfb;
-#define EXTRA_ARGS CMsgHandler* handler
-#define FILL_RECT(r, p) handler->fillRect(r, p)
-#define IMAGE_RECT(r, p) handler->imageRect(r, p)
#define BPP 8
#include <rfb/rreDecode.h>
#undef BPP
@@ -34,7 +32,7 @@ using namespace rfb;
#include <rfb/rreDecode.h>
#undef BPP
-RREDecoder::RREDecoder(CMsgReader* reader_) : reader(reader_)
+RREDecoder::RREDecoder(CConnection* conn) : Decoder(conn)
{
}
@@ -44,8 +42,8 @@ RREDecoder::~RREDecoder()
void RREDecoder::readRect(const Rect& r, CMsgHandler* handler)
{
- rdr::InStream* is = reader->getInStream();
- switch (reader->bpp()) {
+ rdr::InStream* is = conn->getInStream();
+ switch (conn->cp.pf().bpp) {
case 8: rreDecode8 (r, is, handler); break;
case 16: rreDecode16(r, is, handler); break;
case 32: rreDecode32(r, is, handler); break;
diff --git a/common/rfb/RREDecoder.h b/common/rfb/RREDecoder.h
index 98abf982..7b6cc458 100644
--- a/common/rfb/RREDecoder.h
+++ b/common/rfb/RREDecoder.h
@@ -24,11 +24,9 @@ namespace rfb {
class RREDecoder : public Decoder {
public:
- RREDecoder(CMsgReader* reader);
+ RREDecoder(CConnection* conn);
virtual ~RREDecoder();
virtual void readRect(const Rect& r, CMsgHandler* handler);
- private:
- CMsgReader* reader;
};
}
#endif
diff --git a/common/rfb/RREEncoder.cxx b/common/rfb/RREEncoder.cxx
index 36d46955..a7af25db 100644
--- a/common/rfb/RREEncoder.cxx
+++ b/common/rfb/RREEncoder.cxx
@@ -19,6 +19,7 @@
#include <rfb/TransImageGetter.h>
#include <rfb/encodings.h>
#include <rfb/SMsgWriter.h>
+#include <rfb/SConnection.h>
#include <rfb/RREEncoder.h>
using namespace rfb;
@@ -33,7 +34,7 @@ using namespace rfb;
#include <rfb/rreEncode.h>
#undef BPP
-RREEncoder::RREEncoder(SMsgWriter* writer_) : writer(writer_)
+RREEncoder::RREEncoder(SConnection* conn) : RawEncoder(conn)
{
}
@@ -41,30 +42,30 @@ RREEncoder::~RREEncoder()
{
}
-bool RREEncoder::writeRect(const Rect& r, TransImageGetter* ig, Rect* actual)
+void RREEncoder::writeRect(const Rect& r, TransImageGetter* ig)
{
int w = r.width();
int h = r.height();
- rdr::U8* imageBuf = writer->getImageBuf(w*h);
+ rdr::U8* imageBuf = conn->writer()->getImageBuf(w*h);
ig->getImage(imageBuf, r);
mos.clear();
int nSubrects = -1;
- switch (writer->bpp()) {
+ switch (conn->cp.pf().bpp) {
case 8: nSubrects = rreEncode8(imageBuf, w, h, &mos); break;
case 16: nSubrects = rreEncode16(imageBuf, w, h, &mos); break;
case 32: nSubrects = rreEncode32(imageBuf, w, h, &mos); break;
}
if (nSubrects < 0) {
- return writer->writeRect(r, encodingRaw, ig, actual);
+ RawEncoder::writeRect(r, ig);
+ return;
}
- writer->startRect(r, encodingRRE);
- rdr::OutStream* os = writer->getOutStream();
+ conn->writer()->startRect(r, encodingRRE);
+ rdr::OutStream* os = conn->getOutStream();
os->writeU32(nSubrects);
os->writeBytes(mos.data(), mos.length());
- writer->endRect();
- return true;
+ conn->writer()->endRect();
}
diff --git a/common/rfb/RREEncoder.h b/common/rfb/RREEncoder.h
index f7d576eb..487344f2 100644
--- a/common/rfb/RREEncoder.h
+++ b/common/rfb/RREEncoder.h
@@ -19,17 +19,16 @@
#define __RFB_RREENCODER_H__
#include <rdr/MemOutStream.h>
-#include <rfb/Encoder.h>
+#include <rfb/RawEncoder.h>
namespace rfb {
- class RREEncoder : public Encoder {
+ class RREEncoder : public RawEncoder {
public:
- RREEncoder(SMsgWriter* writer);
+ RREEncoder(SConnection* conn);
virtual ~RREEncoder();
- virtual bool writeRect(const Rect& r, TransImageGetter* ig, Rect* actual);
+ virtual void writeRect(const Rect& r, TransImageGetter* ig);
private:
- SMsgWriter* writer;
rdr::MemOutStream mos;
};
}
diff --git a/common/rfb/RawDecoder.cxx b/common/rfb/RawDecoder.cxx
index 5fd3b7c1..6ca02026 100644
--- a/common/rfb/RawDecoder.cxx
+++ b/common/rfb/RawDecoder.cxx
@@ -17,12 +17,13 @@
*/
#include <rdr/InStream.h>
#include <rfb/CMsgReader.h>
+#include <rfb/CConnection.h>
#include <rfb/CMsgHandler.h>
#include <rfb/RawDecoder.h>
using namespace rfb;
-RawDecoder::RawDecoder(CMsgReader* reader_) : reader(reader_)
+RawDecoder::RawDecoder(CConnection* conn) : Decoder(conn)
{
}
@@ -37,12 +38,12 @@ void RawDecoder::readRect(const Rect& r, CMsgHandler* handler)
int w = r.width();
int h = r.height();
int nPixels;
- rdr::U8* imageBuf = reader->getImageBuf(w, w*h, &nPixels);
- int bytesPerRow = w * (reader->bpp() / 8);
+ rdr::U8* imageBuf = conn->reader()->getImageBuf(w, w*h, &nPixels);
+ int bytesPerRow = w * (conn->cp.pf().bpp / 8);
while (h > 0) {
int nRows = nPixels / w;
if (nRows > h) nRows = h;
- reader->getInStream()->readBytes(imageBuf, nRows * bytesPerRow);
+ conn->getInStream()->readBytes(imageBuf, nRows * bytesPerRow);
handler->imageRect(Rect(x, y, x+w, y+nRows), imageBuf);
h -= nRows;
y += nRows;
diff --git a/common/rfb/RawDecoder.h b/common/rfb/RawDecoder.h
index e09cca2d..ca7c4017 100644
--- a/common/rfb/RawDecoder.h
+++ b/common/rfb/RawDecoder.h
@@ -24,11 +24,9 @@ namespace rfb {
class RawDecoder : public Decoder {
public:
- RawDecoder(CMsgReader* reader);
+ RawDecoder(CConnection* conn);
virtual ~RawDecoder();
virtual void readRect(const Rect& r, CMsgHandler* handler);
- private:
- CMsgReader* reader;
};
}
#endif
diff --git a/common/rfb/RawEncoder.cxx b/common/rfb/RawEncoder.cxx
index 4b8de6ba..f7a4f3b8 100644
--- a/common/rfb/RawEncoder.cxx
+++ b/common/rfb/RawEncoder.cxx
@@ -19,11 +19,12 @@
#include <rfb/TransImageGetter.h>
#include <rfb/encodings.h>
#include <rfb/SMsgWriter.h>
+#include <rfb/SConnection.h>
#include <rfb/RawEncoder.h>
using namespace rfb;
-RawEncoder::RawEncoder(SMsgWriter* writer_) : writer(writer_)
+RawEncoder::RawEncoder(SConnection* conn) : Encoder(conn)
{
}
@@ -31,24 +32,23 @@ RawEncoder::~RawEncoder()
{
}
-bool RawEncoder::writeRect(const Rect& r, TransImageGetter* ig, Rect* actual)
+void RawEncoder::writeRect(const Rect& r, TransImageGetter* ig)
{
int x = r.tl.x;
int y = r.tl.y;
int w = r.width();
int h = r.height();
int nPixels;
- rdr::U8* imageBuf = writer->getImageBuf(w, w*h, &nPixels);
- int bytesPerRow = w * (writer->bpp() / 8);
- writer->startRect(r, encodingRaw);
+ rdr::U8* imageBuf = conn->writer()->getImageBuf(w, w*h, &nPixels);
+ int bytesPerRow = w * (conn->cp.pf().bpp / 8);
+ conn->writer()->startRect(r, encodingRaw);
while (h > 0) {
int nRows = nPixels / w;
if (nRows > h) nRows = h;
ig->getImage(imageBuf, Rect(x, y, x+w, y+nRows));
- writer->getOutStream()->writeBytes(imageBuf, nRows * bytesPerRow);
+ conn->getOutStream()->writeBytes(imageBuf, nRows * bytesPerRow);
h -= nRows;
y += nRows;
}
- writer->endRect();
- return true;
+ conn->writer()->endRect();
}
diff --git a/common/rfb/RawEncoder.h b/common/rfb/RawEncoder.h
index 22d45dbf..59e3a6de 100644
--- a/common/rfb/RawEncoder.h
+++ b/common/rfb/RawEncoder.h
@@ -24,11 +24,9 @@ namespace rfb {
class RawEncoder : public Encoder {
public:
- RawEncoder(SMsgWriter* writer);
+ RawEncoder(SConnection* conn);
virtual ~RawEncoder();
- virtual bool writeRect(const Rect& r, TransImageGetter* ig, Rect* actual);
- private:
- SMsgWriter* writer;
+ virtual void writeRect(const Rect& r, TransImageGetter* ig);
};
}
#endif
diff --git a/common/rfb/SConnection.cxx b/common/rfb/SConnection.cxx
index ee573365..48acf0ac 100644
--- a/common/rfb/SConnection.cxx
+++ b/common/rfb/SConnection.cxx
@@ -22,8 +22,8 @@
#include <rfb/Security.h>
#include <rfb/msgTypes.h>
#include <rfb/fenceTypes.h>
-#include <rfb/SMsgReaderV3.h>
-#include <rfb/SMsgWriterV3.h>
+#include <rfb/SMsgReader.h>
+#include <rfb/SMsgWriter.h>
#include <rfb/SConnection.h>
#include <rfb/ServerCore.h>
@@ -297,8 +297,8 @@ void SConnection::approveConnection(bool accept, const char* reason)
if (accept) {
state_ = RFBSTATE_INITIALISATION;
- reader_ = new SMsgReaderV3(this, is);
- writer_ = new SMsgWriterV3(&cp, os);
+ reader_ = new SMsgReader(this, is);
+ writer_ = new SMsgWriter(&cp, os);
authSuccess();
} else {
state_ = RFBSTATE_INVALID;
@@ -306,10 +306,6 @@ void SConnection::approveConnection(bool accept, const char* reason)
}
}
-void SConnection::setInitialColourMap()
-{
-}
-
void SConnection::clientInit(bool shared)
{
writer_->writeServerInit();
@@ -320,6 +316,8 @@ void SConnection::setPixelFormat(const PixelFormat& pf)
{
SMsgHandler::setPixelFormat(pf);
readyForSetColourMapEntries = true;
+ if (!pf.trueColour)
+ writeFakeColourMap();
}
void SConnection::framebufferUpdateRequest(const Rect& r, bool incremental)
@@ -327,7 +325,7 @@ void SConnection::framebufferUpdateRequest(const Rect& r, bool incremental)
if (!readyForSetColourMapEntries) {
readyForSetColourMapEntries = true;
if (!cp.pf().trueColour) {
- setInitialColourMap();
+ writeFakeColourMap();
}
}
}
@@ -347,3 +345,14 @@ void SConnection::enableContinuousUpdates(bool enable,
int x, int y, int w, int h)
{
}
+
+void SConnection::writeFakeColourMap(void)
+{
+ int i;
+ rdr::U16 red[256], green[256], blue[256];
+
+ for (i = 0;i < 256;i++)
+ cp.pf().rgbFromPixel(i, &red[i], &green[i], &blue[i]);
+
+ writer()->writeSetColourMapEntries(0, 256, red, green, blue);
+}
diff --git a/common/rfb/SConnection.h b/common/rfb/SConnection.h
index a3a9fc8f..b6ff7cd5 100644
--- a/common/rfb/SConnection.h
+++ b/common/rfb/SConnection.h
@@ -102,11 +102,6 @@ namespace rfb {
// SConnection::framebufferUpdateRequest().
virtual void framebufferUpdateRequest(const Rect& r, bool incremental);
- // setInitialColourMap() is called when the client needs an initial
- // SetColourMapEntries message. In fact this only happens when the client
- // accepts the server's default pixel format and it uses a colour map.
- virtual void setInitialColourMap();
-
// fence() is called when we get a fence request or response. By default
// it responds directly to requests (stating it doesn't support any
// synchronisation) and drops responses. Override to implement more proper
@@ -180,6 +175,7 @@ namespace rfb {
protected:
void setState(stateEnum s) { state_ = s; }
+ void writeFakeColourMap(void);
bool readyForSetColourMapEntries;
diff --git a/common/rfb/SDesktop.h b/common/rfb/SDesktop.h
index 57ceb076..546506a9 100644
--- a/common/rfb/SDesktop.h
+++ b/common/rfb/SDesktop.h
@@ -93,11 +93,11 @@ namespace rfb {
SStaticDesktop(const Point& size) : server(0), buffer(0) {
PixelFormat pf;
buffer = new ManagedPixelBuffer(pf, size.x, size.y);
- if (buffer) memset(buffer->data, 0, (pf.bpp/8) * (size.x*size.y));
+ if (buffer) buffer->fillRect(buffer->getRect(), 0);
}
SStaticDesktop(const Point& size, const PixelFormat& pf) : buffer(0) {
buffer = new ManagedPixelBuffer(pf, size.x, size.y);
- if (buffer) memset(buffer->data, 0, (pf.bpp/8) * (size.x*size.y));
+ if (buffer) buffer->fillRect(buffer->getRect(), 0);
}
virtual ~SStaticDesktop() {
if (buffer) delete buffer;
diff --git a/common/rfb/SMsgReader.cxx b/common/rfb/SMsgReader.cxx
index 49d8dcf1..89c9a8fd 100644
--- a/common/rfb/SMsgReader.cxx
+++ b/common/rfb/SMsgReader.cxx
@@ -1,4 +1,5 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
+ * Copyright 2009-2014 Pierre Ossman for Cendio AB
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -17,6 +18,7 @@
*/
#include <stdio.h>
#include <rdr/InStream.h>
+#include <rfb/msgTypes.h>
#include <rfb/Exception.h>
#include <rfb/util.h>
#include <rfb/SMsgHandler.h>
@@ -39,6 +41,49 @@ SMsgReader::~SMsgReader()
{
}
+void SMsgReader::readClientInit()
+{
+ bool shared = is->readU8();
+ handler->clientInit(shared);
+}
+
+void SMsgReader::readMsg()
+{
+ int msgType = is->readU8();
+ switch (msgType) {
+ case msgTypeSetPixelFormat:
+ readSetPixelFormat();
+ break;
+ case msgTypeSetEncodings:
+ readSetEncodings();
+ break;
+ case msgTypeSetDesktopSize:
+ readSetDesktopSize();
+ break;
+ case msgTypeFramebufferUpdateRequest:
+ readFramebufferUpdateRequest();
+ break;
+ case msgTypeEnableContinuousUpdates:
+ readEnableContinuousUpdates();
+ break;
+ case msgTypeClientFence:
+ readFence();
+ break;
+ case msgTypeKeyEvent:
+ readKeyEvent();
+ break;
+ case msgTypePointerEvent:
+ readPointerEvent();
+ break;
+ case msgTypeClientCutText:
+ readClientCutText();
+ break;
+ default:
+ fprintf(stderr, "unknown message type %d\n", msgType);
+ throw Exception("unknown message type");
+ }
+}
+
void SMsgReader::readSetPixelFormat()
{
is->skip(3);
@@ -57,6 +102,36 @@ void SMsgReader::readSetEncodings()
handler->setEncodings(nEncodings, encodings.buf);
}
+void SMsgReader::readSetDesktopSize()
+{
+ int width, height;
+ int screens, i;
+ rdr::U32 id, flags;
+ int sx, sy, sw, sh;
+ ScreenSet layout;
+
+ is->skip(1);
+
+ width = is->readU16();
+ height = is->readU16();
+
+ screens = is->readU8();
+ is->skip(1);
+
+ for (i = 0;i < screens;i++) {
+ id = is->readU32();
+ sx = is->readU16();
+ sy = is->readU16();
+ sw = is->readU16();
+ sh = is->readU16();
+ flags = is->readU32();
+
+ layout.add_screen(Screen(id, sx, sy, sw, sh, flags));
+ }
+
+ handler->setDesktopSize(width, height, layout);
+}
+
void SMsgReader::readFramebufferUpdateRequest()
{
bool inc = is->readU8();
@@ -67,6 +142,43 @@ void SMsgReader::readFramebufferUpdateRequest()
handler->framebufferUpdateRequest(Rect(x, y, x+w, y+h), inc);
}
+void SMsgReader::readEnableContinuousUpdates()
+{
+ bool enable;
+ int x, y, w, h;
+
+ enable = is->readU8();
+
+ x = is->readU16();
+ y = is->readU16();
+ w = is->readU16();
+ h = is->readU16();
+
+ handler->enableContinuousUpdates(enable, x, y, w, h);
+}
+
+void SMsgReader::readFence()
+{
+ rdr::U32 flags;
+ rdr::U8 len;
+ char data[64];
+
+ is->skip(3);
+
+ flags = is->readU32();
+
+ len = is->readU8();
+ if (len > sizeof(data)) {
+ fprintf(stderr, "Ignoring fence with too large payload\n");
+ is->skip(len);
+ return;
+ }
+
+ is->readBytes(data, len);
+
+ handler->fence(flags, len, data);
+}
+
void SMsgReader::readKeyEvent()
{
bool down = is->readU8();
diff --git a/common/rfb/SMsgReader.h b/common/rfb/SMsgReader.h
index e6e40448..00cb3031 100644
--- a/common/rfb/SMsgReader.h
+++ b/common/rfb/SMsgReader.h
@@ -1,4 +1,5 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
+ * Copyright 2009-2014 Pierre Ossman for Cendio AB
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -30,24 +31,29 @@ namespace rfb {
class SMsgReader {
public:
+ SMsgReader(SMsgHandler* handler, rdr::InStream* is);
virtual ~SMsgReader();
- virtual void readClientInit()=0;
+ void readClientInit();
// readMsg() reads a message, calling the handler as appropriate.
- virtual void readMsg()=0;
+ void readMsg();
rdr::InStream* getInStream() { return is; }
protected:
- virtual void readSetPixelFormat();
- virtual void readSetEncodings();
- virtual void readFramebufferUpdateRequest();
- virtual void readKeyEvent();
- virtual void readPointerEvent();
- virtual void readClientCutText();
+ void readSetPixelFormat();
+ void readSetEncodings();
+ void readSetDesktopSize();
- SMsgReader(SMsgHandler* handler, rdr::InStream* is);
+ void readFramebufferUpdateRequest();
+ void readEnableContinuousUpdates();
+
+ void readFence();
+
+ void readKeyEvent();
+ void readPointerEvent();
+ void readClientCutText();
SMsgHandler* handler;
rdr::InStream* is;
diff --git a/common/rfb/SMsgReaderV3.cxx b/common/rfb/SMsgReaderV3.cxx
deleted file mode 100644
index cd957b9a..00000000
--- a/common/rfb/SMsgReaderV3.cxx
+++ /dev/null
@@ -1,131 +0,0 @@
-/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
- * Copyright 2009-2011 Pierre Ossman for Cendio AB
- *
- * 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.
- */
-
-#include <stdio.h>
-#include <rfb/PixelFormat.h>
-#include <rfb/msgTypes.h>
-#include <rfb/Exception.h>
-#include <rdr/InStream.h>
-#include <rfb/SMsgReaderV3.h>
-#include <rfb/SMsgHandler.h>
-#include <rfb/ScreenSet.h>
-
-using namespace rfb;
-
-SMsgReaderV3::SMsgReaderV3(SMsgHandler* handler, rdr::InStream* is)
- : SMsgReader(handler, is)
-{
-}
-
-SMsgReaderV3::~SMsgReaderV3()
-{
-}
-
-void SMsgReaderV3::readClientInit()
-{
- bool shared = is->readU8();
- handler->clientInit(shared);
-}
-
-void SMsgReaderV3::readMsg()
-{
- int msgType = is->readU8();
- switch (msgType) {
- case msgTypeSetPixelFormat: readSetPixelFormat(); break;
- case msgTypeSetEncodings: readSetEncodings(); break;
- case msgTypeFramebufferUpdateRequest: readFramebufferUpdateRequest(); break;
- case msgTypeKeyEvent: readKeyEvent(); break;
- case msgTypePointerEvent: readPointerEvent(); break;
- case msgTypeClientCutText: readClientCutText(); break;
- case msgTypeSetDesktopSize: readSetDesktopSize(); break;
- case msgTypeClientFence: readFence(); break;
- case msgTypeEnableContinuousUpdates: readEnableContinuousUpdates(); break;
-
- default:
- fprintf(stderr, "unknown message type %d\n", msgType);
- throw Exception("unknown message type");
- }
-}
-
-void SMsgReaderV3::readSetDesktopSize()
-{
- int width, height;
- int screens, i;
- rdr::U32 id, flags;
- int sx, sy, sw, sh;
- ScreenSet layout;
-
- is->skip(1);
-
- width = is->readU16();
- height = is->readU16();
-
- screens = is->readU8();
- is->skip(1);
-
- for (i = 0;i < screens;i++) {
- id = is->readU32();
- sx = is->readU16();
- sy = is->readU16();
- sw = is->readU16();
- sh = is->readU16();
- flags = is->readU32();
-
- layout.add_screen(Screen(id, sx, sy, sw, sh, flags));
- }
-
- handler->setDesktopSize(width, height, layout);
-}
-
-void SMsgReaderV3::readFence()
-{
- rdr::U32 flags;
- rdr::U8 len;
- char data[64];
-
- is->skip(3);
-
- flags = is->readU32();
-
- len = is->readU8();
- if (len > sizeof(data)) {
- fprintf(stderr, "Ignoring fence with too large payload\n");
- is->skip(len);
- return;
- }
-
- is->readBytes(data, len);
-
- handler->fence(flags, len, data);
-}
-
-void SMsgReaderV3::readEnableContinuousUpdates()
-{
- bool enable;
- int x, y, w, h;
-
- enable = is->readU8();
-
- x = is->readU16();
- y = is->readU16();
- w = is->readU16();
- h = is->readU16();
-
- handler->enableContinuousUpdates(enable, x, y, w, h);
-}
diff --git a/common/rfb/SMsgWriter.cxx b/common/rfb/SMsgWriter.cxx
index 509ffbf5..40e6d7f6 100644
--- a/common/rfb/SMsgWriter.cxx
+++ b/common/rfb/SMsgWriter.cxx
@@ -1,5 +1,6 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
* Copyright (C) 2011 D. R. Commander. All Rights Reserved.
+ * Copyright 2009-2014 Pierre Ossman for Cendio AB
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -20,9 +21,11 @@
#include <assert.h>
#include <rdr/OutStream.h>
#include <rfb/msgTypes.h>
-#include <rfb/ColourMap.h>
+#include <rfb/fenceTypes.h>
+#include <rfb/Exception.h>
#include <rfb/ConnParams.h>
#include <rfb/UpdateTracker.h>
+#include <rfb/Encoder.h>
#include <rfb/SMsgWriter.h>
#include <rfb/LogWriter.h>
@@ -31,12 +34,14 @@ using namespace rfb;
static LogWriter vlog("SMsgWriter");
SMsgWriter::SMsgWriter(ConnParams* cp_, rdr::OutStream* os_)
- : imageBufIdealSize(0), cp(cp_), os(os_), lenBeforeRect(0),
- currentEncoding(0), updatesSent(0), rawBytesEquivalent(0),
+ : imageBufIdealSize(0), cp(cp_), os(os_), currentEncoding(0),
+ nRectsInUpdate(0), nRectsInHeader(0),
+ wsccb(0), needSetDesktopSize(false),
+ needExtendedDesktopSize(false), needSetDesktopName(false),
+ lenBeforeRect(0), updatesSent(0), rawBytesEquivalent(0),
imageBuf(0), imageBufSize(0)
{
for (int i = 0; i <= encodingMax; i++) {
- encoders[i] = 0;
bytesSent[i] = 0;
rectsSent[i] = 0;
}
@@ -47,7 +52,6 @@ SMsgWriter::~SMsgWriter()
vlog.info("framebuffer updates %d",updatesSent);
int bytes = 0;
for (int i = 0; i <= encodingMax; i++) {
- delete encoders[i];
if (i != encodingCopyRect)
bytes += bytesSent[i];
if (rectsSent[i])
@@ -59,19 +63,28 @@ SMsgWriter::~SMsgWriter()
delete [] imageBuf;
}
+void SMsgWriter::writeServerInit()
+{
+ os->writeU16(cp->width);
+ os->writeU16(cp->height);
+ cp->pf().write(os);
+ os->writeString(cp->name());
+ endMsg();
+}
+
void SMsgWriter::writeSetColourMapEntries(int firstColour, int nColours,
- ColourMap* cm)
+ const rdr::U16 red[],
+ const rdr::U16 green[],
+ const rdr::U16 blue[])
{
startMsg(msgTypeSetColourMapEntries);
os->pad(1);
os->writeU16(firstColour);
os->writeU16(nColours);
for (int i = firstColour; i < firstColour+nColours; i++) {
- int r, g, b;
- cm->lookup(i, &r, &g, &b);
- os->writeU16(r);
- os->writeU16(g);
- os->writeU16(b);
+ os->writeU16(red[i]);
+ os->writeU16(green[i]);
+ os->writeU16(blue[i]);
}
endMsg();
}
@@ -91,83 +104,204 @@ void SMsgWriter::writeServerCutText(const char* str, int len)
endMsg();
}
-void SMsgWriter::setupCurrentEncoder()
+void SMsgWriter::writeFence(rdr::U32 flags, unsigned len, const char data[])
{
- int encoding = cp->currentEncoding();
+ if (!cp->supportsFence)
+ throw Exception("Client does not support fences");
+ if (len > 64)
+ throw Exception("Too large fence payload");
+ if ((flags & ~fenceFlagsSupported) != 0)
+ throw Exception("Unknown fence flags");
- // FIXME: Code duplication, see writeRect().
- if (!encoders[encoding]) {
- encoders[encoding] = Encoder::createEncoder(encoding, this);
- assert(encoders[encoding]);
- }
+ startMsg(msgTypeServerFence);
+ os->pad(3);
+
+ os->writeU32(flags);
+
+ os->writeU8(len);
+ os->writeBytes(data, len);
+
+ endMsg();
+}
+
+void SMsgWriter::writeEndOfContinuousUpdates()
+{
+ if (!cp->supportsContinuousUpdates)
+ throw Exception("Client does not support continuous updates");
+
+ startMsg(msgTypeEndOfContinuousUpdates);
+ endMsg();
+}
+
+bool SMsgWriter::writeSetDesktopSize() {
+ if (!cp->supportsDesktopResize)
+ return false;
+
+ needSetDesktopSize = true;
+
+ return true;
+}
+
+bool SMsgWriter::writeExtendedDesktopSize() {
+ if (!cp->supportsExtendedDesktopSize)
+ return false;
+
+ needExtendedDesktopSize = true;
+
+ return true;
+}
+
+bool SMsgWriter::writeExtendedDesktopSize(rdr::U16 reason, rdr::U16 result,
+ int fb_width, int fb_height,
+ const ScreenSet& layout) {
+ ExtendedDesktopSizeMsg msg;
- encoders[encoding]->setCompressLevel(cp->compressLevel);
- encoders[encoding]->setQualityLevel(cp->qualityLevel);
- encoders[encoding]->setFineQualityLevel(cp->fineQualityLevel,
- cp->subsampling);
+ if (!cp->supportsExtendedDesktopSize)
+ return false;
+
+ msg.reason = reason;
+ msg.result = result;
+ msg.fb_width = fb_width;
+ msg.fb_height = fb_height;
+ msg.layout = layout;
+
+ extendedDesktopSizeMsgs.push_back(msg);
+
+ return true;
+}
+
+bool SMsgWriter::writeSetDesktopName() {
+ if (!cp->supportsDesktopRename)
+ return false;
+
+ needSetDesktopName = true;
+
+ return true;
}
-int SMsgWriter::getNumRects(const Rect &r)
+void SMsgWriter::cursorChange(WriteSetCursorCallback* cb)
{
- int encoding = cp->currentEncoding();
+ wsccb = cb;
+}
+
+void SMsgWriter::writeSetCursor(int width, int height, const Point& hotspot,
+ void* data, void* mask)
+{
+ if (!wsccb)
+ return;
- if (!encoders[encoding])
- setupCurrentEncoder();
+ if (++nRectsInUpdate > nRectsInHeader && nRectsInHeader)
+ throw Exception("SMsgWriter::writeSetCursor: nRects out of sync");
- return encoders[encoding]->getNumRects(r);
+ os->writeS16(hotspot.x);
+ os->writeS16(hotspot.y);
+ os->writeU16(width);
+ os->writeU16(height);
+ os->writeU32(pseudoEncodingCursor);
+ os->writeBytes(data, width * height * (cp->pf().bpp/8));
+ os->writeBytes(mask, (width+7)/8 * height);
+}
+
+void SMsgWriter::writeSetXCursor(int width, int height, int hotspotX,
+ int hotspotY, void* data, void* mask)
+{
+ if (!wsccb)
+ return;
+
+ if (++nRectsInUpdate > nRectsInHeader && nRectsInHeader)
+ throw Exception("SMsgWriter::writeSetXCursor: nRects out of sync");
+
+ os->writeS16(hotspotX);
+ os->writeS16(hotspotY);
+ os->writeU16(width);
+ os->writeU16(height);
+ os->writeU32(pseudoEncodingXCursor);
+ // FIXME: We only support black and white cursors, currently. We
+ // could pass the correct color by using the pix0/pix1 values
+ // returned from getBitmap, in writeSetCursorCallback. However, we
+ // would then need to undo the conversion from rgb to Pixel that is
+ // done by FakeAllocColor.
+ if (width * height) {
+ os->writeU8(0);
+ os->writeU8(0);
+ os->writeU8(0);
+ os->writeU8(255);
+ os->writeU8(255);
+ os->writeU8(255);
+ os->writeBytes(data, (width+7)/8 * height);
+ os->writeBytes(mask, (width+7)/8 * height);
+ }
}
bool SMsgWriter::needFakeUpdate()
{
- return false;
+ return wsccb || needSetDesktopName || needNoDataUpdate();
}
bool SMsgWriter::needNoDataUpdate()
{
- return false;
+ return needSetDesktopSize || needExtendedDesktopSize ||
+ !extendedDesktopSizeMsgs.empty();
}
void SMsgWriter::writeNoDataUpdate()
{
- // This class has no pseudo-rectangles so there is nothing to do here
- vlog.error("writeNoDataUpdate() called");
-}
+ int nRects;
-void SMsgWriter::writeRects(const UpdateInfo& ui, TransImageGetter* ig,
- Region* updatedRegion)
-{
- std::vector<Rect> rects;
- std::vector<Rect>::const_iterator i;
- updatedRegion->copyFrom(ui.changed);
- updatedRegion->assign_union(ui.copied);
+ nRects = 0;
- ui.copied.get_rects(&rects, ui.copy_delta.x <= 0, ui.copy_delta.y <= 0);
- for (i = rects.begin(); i != rects.end(); i++)
- writeCopyRect(*i, i->tl.x - ui.copy_delta.x, i->tl.y - ui.copy_delta.y);
+ if (needSetDesktopSize)
+ nRects++;
+ if (needExtendedDesktopSize)
+ nRects++;
+ if (!extendedDesktopSizeMsgs.empty())
+ nRects += extendedDesktopSizeMsgs.size();
- ui.changed.get_rects(&rects);
- for (i = rects.begin(); i != rects.end(); i++) {
- Rect actual;
- if (!writeRect(*i, ig, &actual)) {
- updatedRegion->assign_subtract(*i);
- updatedRegion->assign_union(actual);
- }
- }
+ writeFramebufferUpdateStart(nRects);
+ writeNoDataRects();
+ writeFramebufferUpdateEnd();
}
-bool SMsgWriter::writeRect(const Rect& r, TransImageGetter* ig, Rect* actual)
+void SMsgWriter::writeFramebufferUpdateStart(int nRects)
{
- return writeRect(r, cp->currentEncoding(), ig, actual);
+ startMsg(msgTypeFramebufferUpdate);
+ os->pad(1);
+
+ if (nRects != 0xFFFF) {
+ if (wsccb)
+ nRects++;
+ if (needSetDesktopName)
+ nRects++;
+ }
+
+ os->writeU16(nRects);
+
+ nRectsInUpdate = 0;
+ if (nRects == 0xFFFF)
+ nRectsInHeader = 0;
+ else
+ nRectsInHeader = nRects;
+
+ writePseudoRects();
}
-bool SMsgWriter::writeRect(const Rect& r, int encoding,
- TransImageGetter* ig, Rect* actual)
+void SMsgWriter::writeFramebufferUpdateEnd()
{
- if (!encoders[encoding]) {
- encoders[encoding] = Encoder::createEncoder(encoding, this);
- assert(encoders[encoding]);
+ if (nRectsInUpdate != nRectsInHeader && nRectsInHeader)
+ throw Exception("SMsgWriter::writeFramebufferUpdateEnd: "
+ "nRects out of sync");
+
+ if (nRectsInHeader == 0) {
+ // Send last rect. marker
+ os->writeS16(0);
+ os->writeS16(0);
+ os->writeU16(0);
+ os->writeU16(0);
+ os->writeU32(pseudoEncodingLastRect);
}
- return encoders[encoding]->writeRect(r, ig, actual);
+
+ updatesSent++;
+ endMsg();
}
void SMsgWriter::writeCopyRect(const Rect& r, int srcX, int srcY)
@@ -178,6 +312,31 @@ void SMsgWriter::writeCopyRect(const Rect& r, int srcX, int srcY)
endRect();
}
+void SMsgWriter::startRect(const Rect& r, int encoding)
+{
+ if (++nRectsInUpdate > nRectsInHeader && nRectsInHeader)
+ throw Exception("SMsgWriter::startRect: nRects out of sync");
+
+ currentEncoding = encoding;
+ lenBeforeRect = os->length();
+ if (encoding != encodingCopyRect)
+ rawBytesEquivalent += 12 + r.width() * r.height() * (cp->pf().bpp/8);
+
+ os->writeS16(r.tl.x);
+ os->writeS16(r.tl.y);
+ os->writeU16(r.width());
+ os->writeU16(r.height());
+ os->writeU32(encoding);
+}
+
+void SMsgWriter::endRect()
+{
+ if (currentEncoding <= encodingMax) {
+ bytesSent[currentEncoding] += os->length() - lenBeforeRect;
+ rectsSent[currentEncoding]++;
+ }
+}
+
rdr::U8* SMsgWriter::getImageBuf(int required, int requested, int* nPixels)
{
int requiredBytes = required * (cp->pf().bpp / 8);
@@ -198,7 +357,115 @@ rdr::U8* SMsgWriter::getImageBuf(int required, int requested, int* nPixels)
return imageBuf;
}
-int SMsgWriter::bpp()
+void SMsgWriter::startMsg(int type)
+{
+ os->writeU8(type);
+}
+
+void SMsgWriter::endMsg()
+{
+ os->flush();
+}
+
+void SMsgWriter::writePseudoRects()
+{
+ if (wsccb) {
+ wsccb->writeSetCursorCallback();
+ wsccb = 0;
+ }
+
+ if (needSetDesktopName) {
+ writeSetDesktopNameRect(cp->name());
+ needSetDesktopName = false;
+ }
+}
+
+void SMsgWriter::writeNoDataRects()
{
- return cp->pf().bpp;
+ // Start with specific ExtendedDesktopSize messages
+ if (!extendedDesktopSizeMsgs.empty()) {
+ std::list<ExtendedDesktopSizeMsg>::const_iterator ri;
+
+ for (ri = extendedDesktopSizeMsgs.begin();ri != extendedDesktopSizeMsgs.end();++ri) {
+ writeExtendedDesktopSizeRect(ri->reason, ri->result,
+ ri->fb_width, ri->fb_height, ri->layout);
+ }
+
+ extendedDesktopSizeMsgs.clear();
+ }
+
+ // Send this before SetDesktopSize to make life easier on the clients
+ if (needExtendedDesktopSize) {
+ writeExtendedDesktopSizeRect(0, 0, cp->width, cp->height,
+ cp->screenLayout);
+ needExtendedDesktopSize = false;
+ }
+
+ // Some clients assume this is the last rectangle so don't send anything
+ // more after this
+ if (needSetDesktopSize) {
+ writeSetDesktopSizeRect(cp->width, cp->height);
+ needSetDesktopSize = false;
+ }
+}
+
+void SMsgWriter::writeSetDesktopSizeRect(int width, int height)
+{
+ if (!cp->supportsDesktopResize)
+ throw Exception("Client does not support desktop resize");
+ if (++nRectsInUpdate > nRectsInHeader && nRectsInHeader)
+ throw Exception("SMsgWriter::writeSetDesktopSizeRect: nRects out of sync");
+
+ os->writeS16(0);
+ os->writeS16(0);
+ os->writeU16(width);
+ os->writeU16(height);
+ os->writeU32(pseudoEncodingDesktopSize);
+}
+
+void SMsgWriter::writeExtendedDesktopSizeRect(rdr::U16 reason,
+ rdr::U16 result,
+ int fb_width,
+ int fb_height,
+ const ScreenSet& layout)
+{
+ ScreenSet::const_iterator si;
+
+ if (!cp->supportsExtendedDesktopSize)
+ throw Exception("Client does not support extended desktop resize");
+ if (++nRectsInUpdate > nRectsInHeader && nRectsInHeader)
+ throw Exception("SMsgWriter::writeExtendedDesktopSizeRect: nRects out of sync");
+
+ os->writeU16(reason);
+ os->writeU16(result);
+ os->writeU16(fb_width);
+ os->writeU16(fb_height);
+ os->writeU32(pseudoEncodingExtendedDesktopSize);
+
+ os->writeU8(layout.num_screens());
+ os->pad(3);
+
+ for (si = layout.begin();si != layout.end();++si) {
+ os->writeU32(si->id);
+ os->writeU16(si->dimensions.tl.x);
+ os->writeU16(si->dimensions.tl.y);
+ os->writeU16(si->dimensions.width());
+ os->writeU16(si->dimensions.height());
+ os->writeU32(si->flags);
+ }
+}
+
+void SMsgWriter::writeSetDesktopNameRect(const char *name)
+{
+ if (!cp->supportsDesktopRename)
+ throw Exception("Client does not support desktop rename");
+ if (++nRectsInUpdate > nRectsInHeader && nRectsInHeader)
+ throw Exception("SMsgWriter::writeSetDesktopNameRect: nRects out of sync");
+
+ os->writeS16(0);
+ os->writeS16(0);
+ os->writeU16(0);
+ os->writeU16(0);
+ os->writeU32(pseudoEncodingDesktopName);
+ os->writeString(name);
}
diff --git a/common/rfb/SMsgWriter.h b/common/rfb/SMsgWriter.h
index edf29447..c3ee4577 100644
--- a/common/rfb/SMsgWriter.h
+++ b/common/rfb/SMsgWriter.h
@@ -1,5 +1,5 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
- * Copyright 2009-2011 Pierre Ossman for Cendio AB
+ * Copyright 2009-2014 Pierre Ossman for Cendio AB
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -25,21 +25,14 @@
#include <rdr/types.h>
#include <rfb/encodings.h>
-#include <rfb/screenTypes.h>
-#include <rfb/Encoder.h>
-#include <rfb/PixelBuffer.h>
#include <rfb/ScreenSet.h>
namespace rdr { class OutStream; }
namespace rfb {
- class PixelFormat;
class ConnParams;
- class ImageGetter;
- class ColourMap;
- class Region;
- class UpdateInfo;
+ class ScreenSet;
class WriteSetCursorCallback {
public:
@@ -48,111 +41,86 @@ namespace rfb {
class SMsgWriter {
public:
+ SMsgWriter(ConnParams* cp, rdr::OutStream* os);
virtual ~SMsgWriter();
// writeServerInit() must only be called at the appropriate time in the
// protocol initialisation.
- virtual void writeServerInit()=0;
+ void writeServerInit();
// Methods to write normal protocol messages
// writeSetColourMapEntries() writes a setColourMapEntries message, using
- // the given ColourMap object to lookup the RGB values of the given range
- // of colours.
- virtual void writeSetColourMapEntries(int firstColour, int nColours,
- ColourMap* cm);
+ // the given colour entries.
+ void writeSetColourMapEntries(int firstColour, int nColours,
+ const rdr::U16 red[],
+ const rdr::U16 green[],
+ const rdr::U16 blue[]);
// writeBell() and writeServerCutText() do the obvious thing.
- virtual void writeBell();
- virtual void writeServerCutText(const char* str, int len);
+ void writeBell();
+ void writeServerCutText(const char* str, int len);
// writeFence() sends a new fence request or response to the client.
- virtual void writeFence(rdr::U32 flags, unsigned len, const char data[])=0;
+ void writeFence(rdr::U32 flags, unsigned len, const char data[]);
// writeEndOfContinuousUpdates() indicates that we have left continuous
// updates mode.
- virtual void writeEndOfContinuousUpdates()=0;
-
- // setupCurrentEncoder() should be called before each framebuffer update,
- // prior to calling getNumRects() or writeFramebufferUpdateStart().
- void setupCurrentEncoder();
-
- // getNumRects() computes the number of sub-rectangles that will compose a
- // given rectangle, for current encoder.
- int getNumRects(const Rect &r);
+ void writeEndOfContinuousUpdates();
- // writeSetDesktopSize() on a V3 writer won't actually write immediately,
- // but will write the relevant pseudo-rectangle as part of the next update.
- virtual bool writeSetDesktopSize()=0;
+ // writeSetDesktopSize() won't actually write immediately, but will
+ // write the relevant pseudo-rectangle as part of the next update.
+ bool writeSetDesktopSize();
// Same thing for the extended version. The first version queues up a
// generic update of the current server state, but the second queues a
// specific message.
- virtual bool writeExtendedDesktopSize()=0;
- virtual bool writeExtendedDesktopSize(rdr::U16 reason, rdr::U16 result,
- int fb_width, int fb_height,
- const ScreenSet& layout)=0;
+ bool writeExtendedDesktopSize();
+ bool writeExtendedDesktopSize(rdr::U16 reason, rdr::U16 result,
+ int fb_width, int fb_height,
+ const ScreenSet& layout);
- virtual bool writeSetDesktopName()=0;
+ bool writeSetDesktopName();
// Like setDesktopSize, we can't just write out a setCursor message
- // immediately on a V3 writer. Instead of calling writeSetCursor()
- // directly, you must call cursorChange(), and then invoke writeSetCursor()
- // in response to the writeSetCursorCallback() callback. For a V3 writer
- // this will happen when the next update is sent.
- virtual void cursorChange(WriteSetCursorCallback* cb)=0;
- virtual void writeSetCursor(int width, int height, const Point& hotspot,
- void* data, void* mask)=0;
- virtual void writeSetXCursor(int width, int height, int hotspotX,
- int hotspotY, void* data, void* mask)=0;
+ // immediately. Instead of calling writeSetCursor() directly,
+ // you must call cursorChange(), and then invoke writeSetCursor()
+ // in response to the writeSetCursorCallback() callback. This will
+ // happen when the next update is sent.
+ void cursorChange(WriteSetCursorCallback* cb);
+ void writeSetCursor(int width, int height, const Point& hotspot,
+ void* data, void* mask);
+ void writeSetXCursor(int width, int height, int hotspotX, int hotspotY,
+ void* data, void* mask);
// needFakeUpdate() returns true when an immediate update is needed in
// order to flush out pseudo-rectangles to the client.
- virtual bool needFakeUpdate();
+ bool needFakeUpdate();
// needNoDataUpdate() returns true when an update without any
// framebuffer changes need to be sent (using writeNoDataUpdate()).
// Commonly this is an update that modifies the size of the framebuffer
// or the screen layout.
- virtual bool needNoDataUpdate();
+ bool needNoDataUpdate();
// writeNoDataUpdate() write a framebuffer update containing only
// pseudo-rectangles.
- virtual void writeNoDataUpdate();
-
- // writeRects() accepts an UpdateInfo (changed & copied regions) and an
- // ImageGetter to fetch pixels from. It then calls writeCopyRect() and
- // writeRect() as appropriate. writeFramebufferUpdateStart() must be used
- // before the first writeRects() call and writeFrameBufferUpdateEnd() after
- // the last one. It returns the actual region sent to the client, which
- // may be smaller than the update passed in.
- virtual void writeRects(const UpdateInfo& update, TransImageGetter* ig,
- Region* updatedRegion);
-
- // To construct a framebuffer update you can call
- // writeFramebufferUpdateStart(), followed by a number of writeCopyRect()s
- // and writeRect()s, finishing with writeFramebufferUpdateEnd(). If you
- // know the exact number of rectangles ahead of time you can specify it to
- // writeFramebufferUpdateStart() which can be more efficient.
- virtual void writeFramebufferUpdateStart(int nRects)=0;
- virtual void writeFramebufferUpdateStart()=0;
- virtual void writeFramebufferUpdateEnd()=0;
-
- // writeRect() tries to write the given rectangle. If it is unable to
- // write the whole rectangle it returns false and sets actual to the actual
- // rectangle which was updated.
- virtual bool writeRect(const Rect& r, TransImageGetter* ig, Rect* actual);
- virtual bool writeRect(const Rect& r, int encoding,
- TransImageGetter* ig, Rect* actual);
-
- virtual void writeCopyRect(const Rect& r, int srcX, int srcY);
-
- virtual void startRect(const Rect& r, int enc)=0;
- virtual void endRect()=0;
-
- ConnParams* getConnParams() { return cp; }
- rdr::OutStream* getOutStream() { return os; }
+ void writeNoDataUpdate();
+
+ // writeFramebufferUpdateStart() initiates an update which you can fill
+ // in using writeCopyRect() and encoders. Finishing the update by calling
+ // writeFramebufferUpdateEnd().
+ void writeFramebufferUpdateStart(int nRects);
+ void writeFramebufferUpdateEnd();
+
+ // There is no explicit encoder for CopyRect rects.
+ void writeCopyRect(const Rect& r, int srcX, int srcY);
+
+ // Encoders should call these to mark the start and stop of individual
+ // rects.
+ void startRect(const Rect& r, int enc);
+ void endRect();
+
rdr::U8* getImageBuf(int required, int requested=0, int* nPixels=0);
- int bpp();
int getUpdatesSent() { return updatesSent; }
int getRectsSent(int encoding) { return rectsSent[encoding]; }
@@ -162,17 +130,34 @@ namespace rfb {
int imageBufIdealSize;
protected:
- SMsgWriter(ConnParams* cp, rdr::OutStream* os);
+ void startMsg(int type);
+ void endMsg();
+
+ void writePseudoRects();
+ void writeNoDataRects();
- virtual void startMsg(int type)=0;
- virtual void endMsg()=0;
+ void writeSetDesktopSizeRect(int width, int height);
+ void writeExtendedDesktopSizeRect(rdr::U16 reason, rdr::U16 result,
+ int fb_width, int fb_height,
+ const ScreenSet& layout);
+ void writeSetDesktopNameRect(const char *name);
ConnParams* cp;
rdr::OutStream* os;
- Encoder* encoders[encodingMax+1];
- int lenBeforeRect;
int currentEncoding;
+
+ int nRectsInUpdate;
+ int nRectsInHeader;
+
+ WriteSetCursorCallback* wsccb;
+
+ bool needSetDesktopSize;
+ bool needExtendedDesktopSize;
+ bool needSetDesktopName;
+ bool needLastRect;
+
+ int lenBeforeRect;
int updatesSent;
int bytesSent[encodingMax+1];
int rectsSent[encodingMax+1];
@@ -180,6 +165,14 @@ namespace rfb {
rdr::U8* imageBuf;
int imageBufSize;
+
+ typedef struct {
+ rdr::U16 reason, result;
+ int fb_width, fb_height;
+ ScreenSet layout;
+ } ExtendedDesktopSizeMsg;
+
+ std::list<ExtendedDesktopSizeMsg> extendedDesktopSizeMsgs;
};
}
#endif
diff --git a/common/rfb/SMsgWriterV3.cxx b/common/rfb/SMsgWriterV3.cxx
deleted file mode 100644
index 86f35078..00000000
--- a/common/rfb/SMsgWriterV3.cxx
+++ /dev/null
@@ -1,399 +0,0 @@
-/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
- * Copyright 2009-2011 Pierre Ossman for Cendio AB
- * Copyright (C) 2011 D. R. Commander. 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.
- */
-#include <rdr/OutStream.h>
-#include <rdr/MemOutStream.h>
-#include <rfb/msgTypes.h>
-#include <rfb/screenTypes.h>
-#include <rfb/fenceTypes.h>
-#include <rfb/Exception.h>
-#include <rfb/ConnParams.h>
-#include <rfb/SMsgWriterV3.h>
-
-using namespace rfb;
-
-SMsgWriterV3::SMsgWriterV3(ConnParams* cp, rdr::OutStream* os)
- : SMsgWriter(cp, os), updateOS(0), realOS(os), nRectsInUpdate(0),
- nRectsInHeader(0), wsccb(0), needSetDesktopSize(false),
- needExtendedDesktopSize(false), needSetDesktopName(false)
-{
-}
-
-SMsgWriterV3::~SMsgWriterV3()
-{
- delete updateOS;
-}
-
-void SMsgWriterV3::writeServerInit()
-{
- os->writeU16(cp->width);
- os->writeU16(cp->height);
- cp->pf().write(os);
- os->writeString(cp->name());
- endMsg();
-}
-
-void SMsgWriterV3::startMsg(int type)
-{
- if (os != realOS)
- throw Exception("startMsg called while writing an update?");
-
- os->writeU8(type);
-}
-
-void SMsgWriterV3::endMsg()
-{
- os->flush();
-}
-
-void SMsgWriterV3::writeFence(rdr::U32 flags, unsigned len, const char data[])
-{
- if (!cp->supportsFence)
- throw Exception("Client does not support fences");
- if (len > 64)
- throw Exception("Too large fence payload");
- if ((flags & ~fenceFlagsSupported) != 0)
- throw Exception("Unknown fence flags");
-
- startMsg(msgTypeServerFence);
- os->pad(3);
-
- os->writeU32(flags);
-
- os->writeU8(len);
- os->writeBytes(data, len);
-
- endMsg();
-}
-
-void SMsgWriterV3::writeEndOfContinuousUpdates()
-{
- if (!cp->supportsContinuousUpdates)
- throw Exception("Client does not support continuous updates");
-
- startMsg(msgTypeEndOfContinuousUpdates);
- endMsg();
-}
-
-bool SMsgWriterV3::writeSetDesktopSize() {
- if (!cp->supportsDesktopResize) return false;
- needSetDesktopSize = true;
- return true;
-}
-
-bool SMsgWriterV3::writeExtendedDesktopSize() {
- if (!cp->supportsExtendedDesktopSize) return false;
- needExtendedDesktopSize = true;
- return true;
-}
-
-bool SMsgWriterV3::writeExtendedDesktopSize(rdr::U16 reason, rdr::U16 result,
- int fb_width, int fb_height,
- const ScreenSet& layout) {
- ExtendedDesktopSizeMsg msg;
-
- if (!cp->supportsExtendedDesktopSize) return false;
-
- msg.reason = reason;
- msg.result = result;
- msg.fb_width = fb_width;
- msg.fb_height = fb_height;
- msg.layout = layout;
-
- extendedDesktopSizeMsgs.push_back(msg);
-
- return true;
-}
-
-bool SMsgWriterV3::writeSetDesktopName() {
- if (!cp->supportsDesktopRename) return false;
- needSetDesktopName = true;
- return true;
-}
-
-void SMsgWriterV3::cursorChange(WriteSetCursorCallback* cb)
-{
- wsccb = cb;
-}
-
-void SMsgWriterV3::writeSetCursor(int width, int height, const Point& hotspot,
- void* data, void* mask)
-{
- if (!wsccb) return;
- if (++nRectsInUpdate > nRectsInHeader && nRectsInHeader)
- throw Exception("SMsgWriterV3::writeSetCursor: nRects out of sync");
- os->writeS16(hotspot.x);
- os->writeS16(hotspot.y);
- os->writeU16(width);
- os->writeU16(height);
- os->writeU32(pseudoEncodingCursor);
- os->writeBytes(data, width * height * (cp->pf().bpp/8));
- os->writeBytes(mask, (width+7)/8 * height);
-}
-
-void SMsgWriterV3::writeSetXCursor(int width, int height, int hotspotX,
- int hotspotY, void* data, void* mask)
-{
- if (!wsccb) return;
- if (++nRectsInUpdate > nRectsInHeader && nRectsInHeader)
- throw Exception("SMsgWriterV3::writeSetXCursor: nRects out of sync");
- os->writeS16(hotspotX);
- os->writeS16(hotspotY);
- os->writeU16(width);
- os->writeU16(height);
- os->writeU32(pseudoEncodingXCursor);
- // FIXME: We only support black and white cursors, currently. We
- // could pass the correct color by using the pix0/pix1 values
- // returned from getBitmap, in writeSetCursorCallback. However, we
- // would then need to undo the conversion from rgb to Pixel that is
- // done by FakeAllocColor.
- if (width * height) {
- os->writeU8(0);
- os->writeU8(0);
- os->writeU8(0);
- os->writeU8(255);
- os->writeU8(255);
- os->writeU8(255);
- os->writeBytes(data, (width+7)/8 * height);
- os->writeBytes(mask, (width+7)/8 * height);
- }
-}
-
-bool SMsgWriterV3::needFakeUpdate()
-{
- return wsccb || needSetDesktopName || needNoDataUpdate();
-}
-
-bool SMsgWriterV3::needNoDataUpdate()
-{
- return needSetDesktopSize || needExtendedDesktopSize ||
- !extendedDesktopSizeMsgs.empty();
-}
-
-void SMsgWriterV3::writeNoDataUpdate()
-{
- int nRects;
-
- nRects = 0;
-
- if (needSetDesktopSize)
- nRects++;
- if (needExtendedDesktopSize)
- nRects++;
- if (!extendedDesktopSizeMsgs.empty())
- nRects += extendedDesktopSizeMsgs.size();
-
- writeFramebufferUpdateStart(nRects);
- writeNoDataRects();
- writeFramebufferUpdateEnd();
-}
-
-void SMsgWriterV3::writeFramebufferUpdateStart(int nRects)
-{
- startMsg(msgTypeFramebufferUpdate);
- os->pad(1);
-
- if (nRects != 0xFFFF) {
- if (wsccb)
- nRects++;
- if (needSetDesktopName)
- nRects++;
- }
-
- os->writeU16(nRects);
-
- nRectsInUpdate = 0;
- if (nRects == 0xFFFF)
- nRectsInHeader = 0;
- else
- nRectsInHeader = nRects;
-
- writePseudoRects();
-}
-
-void SMsgWriterV3::writeFramebufferUpdateStart()
-{
- nRectsInUpdate = nRectsInHeader = 0;
-
- if (!updateOS)
- updateOS = new rdr::MemOutStream;
- os = updateOS;
-
- writePseudoRects();
-}
-
-void SMsgWriterV3::writeFramebufferUpdateEnd()
-{
- if (nRectsInUpdate != nRectsInHeader && nRectsInHeader)
- throw Exception("SMsgWriterV3::writeFramebufferUpdateEnd: "
- "nRects out of sync");
-
- if (nRectsInHeader == 0) {
- // Send last rect. marker
- os->writeS16(0);
- os->writeS16(0);
- os->writeU16(0);
- os->writeU16(0);
- os->writeU32(pseudoEncodingLastRect);
- }
-
- if (os == updateOS) {
- os = realOS;
- startMsg(msgTypeFramebufferUpdate);
- os->pad(1);
- os->writeU16(nRectsInUpdate);
- os->writeBytes(updateOS->data(), updateOS->length());
- updateOS->clear();
- }
-
- updatesSent++;
- endMsg();
-}
-
-void SMsgWriterV3::startRect(const Rect& r, int encoding)
-{
- if (++nRectsInUpdate > nRectsInHeader && nRectsInHeader)
- throw Exception("SMsgWriterV3::startRect: nRects out of sync");
-
- currentEncoding = encoding;
- lenBeforeRect = os->length();
- if (encoding != encodingCopyRect)
- rawBytesEquivalent += 12 + r.width() * r.height() * (bpp()/8);
-
- os->writeS16(r.tl.x);
- os->writeS16(r.tl.y);
- os->writeU16(r.width());
- os->writeU16(r.height());
- os->writeU32(encoding);
-}
-
-void SMsgWriterV3::endRect()
-{
- if (currentEncoding <= encodingMax) {
- bytesSent[currentEncoding] += os->length() - lenBeforeRect;
- rectsSent[currentEncoding]++;
- }
-}
-
-void SMsgWriterV3::writePseudoRects()
-{
- if (wsccb) {
- wsccb->writeSetCursorCallback();
- wsccb = 0;
- }
-
- if (needSetDesktopName) {
- if (!cp->supportsDesktopRename)
- throw Exception("Client does not support desktop rename");
- if (++nRectsInUpdate > nRectsInHeader && nRectsInHeader)
- throw Exception("SMsgWriterV3 setDesktopName: nRects out of sync");
-
- os->writeS16(0);
- os->writeS16(0);
- os->writeU16(0);
- os->writeU16(0);
- os->writeU32(pseudoEncodingDesktopName);
- os->writeString(cp->name());
-
- needSetDesktopName = false;
- }
-}
-
-void SMsgWriterV3::writeNoDataRects()
-{
- // Start with specific ExtendedDesktopSize messages
- if (!extendedDesktopSizeMsgs.empty()) {
- std::list<ExtendedDesktopSizeMsg>::const_iterator ri;
- ScreenSet::const_iterator si;
-
- if (!cp->supportsExtendedDesktopSize)
- throw Exception("Client does not support extended desktop resize");
- if ((nRectsInUpdate += extendedDesktopSizeMsgs.size()) > nRectsInHeader && nRectsInHeader)
- throw Exception("SMsgWriterV3 SetDesktopSize reply: nRects out of sync");
-
- for (ri = extendedDesktopSizeMsgs.begin();ri != extendedDesktopSizeMsgs.end();++ri) {
- os->writeU16(ri->reason);
- os->writeU16(ri->result);
- os->writeU16(ri->fb_width);
- os->writeU16(ri->fb_height);
- os->writeU32(pseudoEncodingExtendedDesktopSize);
-
- os->writeU8(ri->layout.num_screens());
- os->pad(3);
-
- for (si = ri->layout.begin();si != ri->layout.end();++si) {
- os->writeU32(si->id);
- os->writeU16(si->dimensions.tl.x);
- os->writeU16(si->dimensions.tl.y);
- os->writeU16(si->dimensions.width());
- os->writeU16(si->dimensions.height());
- os->writeU32(si->flags);
- }
- }
-
- extendedDesktopSizeMsgs.clear();
- }
-
- // Send this before SetDesktopSize to make life easier on the clients
- if (needExtendedDesktopSize) {
- if (!cp->supportsExtendedDesktopSize)
- throw Exception("Client does not support extended desktop resize");
- if (++nRectsInUpdate > nRectsInHeader && nRectsInHeader)
- throw Exception("SMsgWriterV3 setExtendedDesktopSize: nRects out of sync");
-
- os->writeU16(0);
- os->writeU16(0);
- os->writeU16(cp->width);
- os->writeU16(cp->height);
- os->writeU32(pseudoEncodingExtendedDesktopSize);
-
- os->writeU8(cp->screenLayout.num_screens());
- os->pad(3);
-
- ScreenSet::const_iterator iter;
- for (iter = cp->screenLayout.begin();iter != cp->screenLayout.end();++iter) {
- os->writeU32(iter->id);
- os->writeU16(iter->dimensions.tl.x);
- os->writeU16(iter->dimensions.tl.y);
- os->writeU16(iter->dimensions.width());
- os->writeU16(iter->dimensions.height());
- os->writeU32(iter->flags);
- }
-
- needExtendedDesktopSize = false;
- }
-
- // Some clients assume this is the last rectangle so don't send anything
- // more after this
- if (needSetDesktopSize) {
- if (!cp->supportsDesktopResize)
- throw Exception("Client does not support desktop resize");
- if (++nRectsInUpdate > nRectsInHeader && nRectsInHeader)
- throw Exception("SMsgWriterV3 setDesktopSize: nRects out of sync");
-
- os->writeS16(0);
- os->writeS16(0);
- os->writeU16(cp->width);
- os->writeU16(cp->height);
- os->writeU32(pseudoEncodingDesktopSize);
-
- needSetDesktopSize = false;
- }
-}
-
diff --git a/common/rfb/SMsgWriterV3.h b/common/rfb/SMsgWriterV3.h
deleted file mode 100644
index 6710fa6b..00000000
--- a/common/rfb/SMsgWriterV3.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
- * Copyright 2009-2011 Pierre Ossman for Cendio AB
- *
- * 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.
- */
-#ifndef __RFB_SMSGWRITERV3_H__
-#define __RFB_SMSGWRITERV3_H__
-
-#include <list>
-#include <utility>
-
-#include <rfb/SMsgWriter.h>
-
-namespace rdr { class MemOutStream; }
-
-namespace rfb {
- class SMsgWriterV3 : public SMsgWriter {
- public:
- SMsgWriterV3(ConnParams* cp, rdr::OutStream* os);
- virtual ~SMsgWriterV3();
-
- virtual void writeServerInit();
- virtual void startMsg(int type);
- virtual void endMsg();
- virtual void writeFence(rdr::U32 flags, unsigned len, const char data[]);
- virtual void writeEndOfContinuousUpdates();
- virtual bool writeSetDesktopSize();
- virtual bool writeExtendedDesktopSize();
- virtual bool writeExtendedDesktopSize(rdr::U16 reason, rdr::U16 result,
- int fb_width, int fb_height,
- const ScreenSet& layout);
- virtual bool writeSetDesktopName();
- virtual void cursorChange(WriteSetCursorCallback* cb);
- virtual void writeSetCursor(int width, int height, const Point& hotspot,
- void* data, void* mask);
- virtual void writeSetXCursor(int width, int height, int hotspotX,
- int hotspotY, void* data, void* mask);
- virtual bool needFakeUpdate();
- virtual bool needNoDataUpdate();
- virtual void writeNoDataUpdate();
- virtual void writeFramebufferUpdateStart(int nRects);
- virtual void writeFramebufferUpdateStart();
- virtual void writeFramebufferUpdateEnd();
- virtual void startRect(const Rect& r, int encoding);
- virtual void endRect();
-
- protected:
- virtual void writePseudoRects();
- virtual void writeNoDataRects();
-
- private:
- rdr::MemOutStream* updateOS;
- rdr::OutStream* realOS;
- int nRectsInUpdate;
- int nRectsInHeader;
- WriteSetCursorCallback* wsccb;
- bool needSetDesktopSize;
- bool needExtendedDesktopSize;
- bool needSetDesktopName;
- bool needLastRect;
-
- typedef struct {
- rdr::U16 reason, result;
- int fb_width, fb_height;
- ScreenSet layout;
- } ExtendedDesktopSizeMsg;
- std::list<ExtendedDesktopSizeMsg> extendedDesktopSizeMsgs;
-
- };
-}
-#endif
diff --git a/common/rfb/TightDecoder.cxx b/common/rfb/TightDecoder.cxx
index d4ee877f..bfc3352b 100644
--- a/common/rfb/TightDecoder.cxx
+++ b/common/rfb/TightDecoder.cxx
@@ -18,6 +18,7 @@
* USA.
*/
#include <rfb/CMsgReader.h>
+#include <rfb/CConnection.h>
#include <rfb/CMsgHandler.h>
#include <rfb/TightDecoder.h>
@@ -25,8 +26,6 @@ using namespace rfb;
#define TIGHT_MAX_WIDTH 2048
-#define FILL_RECT(r, p) handler->fillRect(r, p)
-#define IMAGE_RECT(r, p) handler->imageRect(r, p)
#define BPP 8
#include <rfb/tightDecode.h>
#undef BPP
@@ -37,7 +36,7 @@ using namespace rfb;
#include <rfb/tightDecode.h>
#undef BPP
-TightDecoder::TightDecoder(CMsgReader* reader_) : reader(reader_)
+TightDecoder::TightDecoder(CConnection* conn) : Decoder(conn)
{
}
@@ -47,7 +46,7 @@ TightDecoder::~TightDecoder()
void TightDecoder::readRect(const Rect& r, CMsgHandler* handler)
{
- is = reader->getInStream();
+ is = conn->getInStream();
this->handler = handler;
clientpf = handler->getPreferredPF();
serverpf = handler->cp.pf();
@@ -69,3 +68,22 @@ void TightDecoder::readRect(const Rect& r, CMsgHandler* handler)
tightDecode32(r); break;
}
}
+
+rdr::U32 TightDecoder::readCompact(rdr::InStream* is)
+{
+ rdr::U8 b;
+ rdr::U32 result;
+
+ b = is->readU8();
+ result = (int)b & 0x7F;
+ if (b & 0x80) {
+ b = is->readU8();
+ result |= ((int)b & 0x7F) << 7;
+ if (b & 0x80) {
+ b = is->readU8();
+ result |= ((int)b & 0xFF) << 14;
+ }
+ }
+
+ return result;
+}
diff --git a/common/rfb/TightDecoder.h b/common/rfb/TightDecoder.h
index 8200d2b8..2ca4ecd6 100644
--- a/common/rfb/TightDecoder.h
+++ b/common/rfb/TightDecoder.h
@@ -28,11 +28,13 @@ namespace rfb {
class TightDecoder : public Decoder {
public:
- TightDecoder(CMsgReader* reader);
+ TightDecoder(CConnection* conn);
virtual ~TightDecoder();
virtual void readRect(const Rect& r, CMsgHandler* handler);
private:
+ rdr::U32 readCompact(rdr::InStream* is);
+
void tightDecode8(const Rect& r);
void tightDecode16(const Rect& r);
void tightDecode32(const Rect& r);
@@ -54,7 +56,6 @@ namespace rfb {
void directFillRect16(const Rect& r, Pixel pix);
void directFillRect32(const Rect& r, Pixel pix);
- CMsgReader* reader;
CMsgHandler* handler;
rdr::InStream* is;
rdr::ZlibInStream zis[4];
diff --git a/common/rfb/TightEncoder.cxx b/common/rfb/TightEncoder.cxx
index 733365e0..c3f87dab 100644
--- a/common/rfb/TightEncoder.cxx
+++ b/common/rfb/TightEncoder.cxx
@@ -18,9 +18,11 @@
*/
#include <rdr/OutStream.h>
#include <rfb/TransImageGetter.h>
+#include <rfb/PixelBuffer.h>
#include <rfb/encodings.h>
#include <rfb/ConnParams.h>
#include <rfb/SMsgWriter.h>
+#include <rfb/SConnection.h>
#include <rfb/TightEncoder.h>
using namespace rfb;
@@ -92,7 +94,7 @@ const int TightEncoder::defaultCompressLevel = 2;
#include <rfb/tightEncode.h>
#undef BPP
-TightEncoder::TightEncoder(SMsgWriter* writer_) : writer(writer_)
+TightEncoder::TightEncoder(SConnection* conn) : Encoder(conn)
{
setCompressLevel(defaultCompressLevel);
setQualityLevel(-1);
@@ -225,7 +227,7 @@ void TightEncoder::extendSolidArea(const Rect& r, rdr::U32 colorValue,
int TightEncoder::getNumRects(const Rect &r)
{
- ConnParams* cp = writer->getConnParams();
+ ConnParams* cp = &conn->cp;
const unsigned int w = r.width();
const unsigned int h = r.height();
@@ -285,12 +287,11 @@ void TightEncoder::sendRectSimple(const Rect& r)
}
}
-bool TightEncoder::writeRect(const Rect& _r, TransImageGetter* _ig,
- Rect* actual)
+void TightEncoder::writeRect(const Rect& _r, TransImageGetter* _ig)
{
ig = _ig;
serverpf = ig->getPixelBuffer()->getPF();
- ConnParams* cp = writer->getConnParams();
+ ConnParams* cp = &conn->cp;
clientpf = cp->pf();
// Shortcuts to rectangle coordinates and dimensions.
@@ -303,7 +304,7 @@ bool TightEncoder::writeRect(const Rect& _r, TransImageGetter* _ig,
// Encode small rects as is.
if (!cp->supportsLastRect || w * h < TIGHT_MIN_SPLIT_RECT_SIZE) {
sendRectSimple(r);
- return true;
+ return;
}
// Split big rects into separately encoded subrects.
@@ -338,9 +339,9 @@ bool TightEncoder::writeRect(const Rect& _r, TransImageGetter* _ig,
if (checkSolidTile(sr, &colorValue, false)) {
if (jpegSubsampling == subsampleGray && jpegQuality != -1) {
- Colour rgb;
- serverpf.rgbFromPixel(colorValue, NULL, &rgb);
- rdr::U32 lum = ((257 * rgb.r) + (504 * rgb.g) + (98 * rgb.b)
+ rdr::U16 r, g, b;
+ serverpf.rgbFromPixel(colorValue, &r, &g, &b);
+ rdr::U32 lum = ((257 * r) + (504 * g) + (98 * b)
+ 16500) / 1000;
colorValue = lum + (lum << 8) + (lum << 16);
}
@@ -365,7 +366,7 @@ bool TightEncoder::writeRect(const Rect& _r, TransImageGetter* _ig,
}
if (bestr.tl.x != x) {
sr.setXYWH(x, bestr.tl.y, bestr.tl.x - x, bestr.height());
- writeRect(sr, _ig, NULL);
+ writeRect(sr, _ig);
}
// Send solid-color rectangle.
@@ -375,21 +376,21 @@ bool TightEncoder::writeRect(const Rect& _r, TransImageGetter* _ig,
if (bestr.br.x != r.br.x) {
sr.setXYWH(bestr.br.x, bestr.tl.y, r.br.x - bestr.br.x,
bestr.height());
- writeRect(sr, _ig, NULL);
+ writeRect(sr, _ig);
}
if (bestr.br.y != r.br.y) {
sr.setXYWH(x, bestr.br.y, w, r.br.y - bestr.br.y);
- writeRect(sr, _ig, NULL);
+ writeRect(sr, _ig);
}
- return true;
+ return;
}
}
}
// No suitable solid-color rectangles found.
sendRectSimple(r);
- return true;
+ return;
}
void TightEncoder::writeSubrect(const Rect& r, bool forceSolid)
@@ -405,8 +406,26 @@ void TightEncoder::writeSubrect(const Rect& r, bool forceSolid)
tightEncode32(r, &mos, forceSolid); break;
}
- writer->startRect(r, encodingTight);
- rdr::OutStream* os = writer->getOutStream();
+ conn->writer()->startRect(r, encodingTight);
+ rdr::OutStream* os = conn->getOutStream();
os->writeBytes(mos.data(), mos.length());
- writer->endRect();
+ conn->writer()->endRect();
+}
+
+void TightEncoder::writeCompact(rdr::OutStream* os, rdr::U32 value)
+{
+ rdr::U8 b;
+ b = value & 0x7F;
+ if (value <= 0x7F) {
+ os->writeU8(b);
+ } else {
+ os->writeU8(b | 0x80);
+ b = value >> 7 & 0x7F;
+ if (value <= 0x3FFF) {
+ os->writeU8(b);
+ } else {
+ os->writeU8(b | 0x80);
+ os->writeU8(value >> 14 & 0xFF);
+ }
+ }
}
diff --git a/common/rfb/TightEncoder.h b/common/rfb/TightEncoder.h
index 3632539d..8a58985e 100644
--- a/common/rfb/TightEncoder.h
+++ b/common/rfb/TightEncoder.h
@@ -23,6 +23,7 @@
#include <rdr/ZlibOutStream.h>
#include <rfb/Encoder.h>
#include <rfb/JpegCompressor.h>
+#include <rfb/Palette.h>
// FIXME: Check if specifying extern "C" is really necessary.
#include <stdio.h>
@@ -45,28 +46,6 @@ namespace rfb {
};
//
- // C-style structures to store palette entries and compression paramentes.
- // Such code probably should be converted into C++ classes.
- //
-
- struct TIGHT_COLOR_LIST {
- TIGHT_COLOR_LIST *next;
- int idx;
- rdr::U32 rgb;
- };
-
- struct TIGHT_PALETTE_ENTRY {
- TIGHT_COLOR_LIST *listNode;
- int numPixels;
- };
-
- struct TIGHT_PALETTE {
- TIGHT_PALETTE_ENTRY entry[256];
- TIGHT_COLOR_LIST *hash[256];
- TIGHT_COLOR_LIST list[256];
- };
-
- //
// Compression level stuff. The following array contains various
// encoder parameters for each of 10 compression levels (0..9).
// Last three parameters correspond to JPEG quality levels (0..9).
@@ -79,14 +58,14 @@ namespace rfb {
class TightEncoder : public Encoder {
public:
- TightEncoder(SMsgWriter* writer);
+ TightEncoder(SConnection* conn);
virtual ~TightEncoder();
virtual void setCompressLevel(int level);
virtual void setQualityLevel(int level);
virtual void setFineQualityLevel(int quality, int subsampling);
virtual int getNumRects(const Rect &r);
- virtual bool writeRect(const Rect& r, TransImageGetter* ig, Rect* actual);
+ virtual void writeRect(const Rect& r, TransImageGetter* ig);
private:
bool checkSolidTile(Rect& r, rdr::U32* colorPtr, bool needSameColor);
@@ -95,13 +74,12 @@ namespace rfb {
void sendRectSimple(const Rect& r);
void writeSubrect(const Rect& r, bool forceSolid = false);
+ void writeCompact(rdr::OutStream* os, rdr::U32 value);
+
void compressData(const void *buf, unsigned int length,
rdr::ZlibOutStream *zos, int zlibLevel,
rdr::OutStream *os);
- int paletteInsert(rdr::U32 rgb, int numPixels, int bpp);
- void paletteReset(void);
-
void fastFillPalette8(const rdr::U8 *data, int stride, const Rect &r);
void fastFillPalette16(const rdr::U16 *data, int stride, const Rect &r);
void fastFillPalette32(const rdr::U32 *data, int stride, const Rect &r);
@@ -142,7 +120,6 @@ namespace rfb {
void encodeJpegRect32(rdr::U32 *buf, int stride, const Rect& r,
rdr::OutStream *os);
- SMsgWriter* writer;
rdr::MemOutStream mos;
rdr::ZlibOutStream zos[4];
JpegCompressor jc;
@@ -150,9 +127,8 @@ namespace rfb {
PixelFormat serverpf, clientpf;
bool pack24;
- int palMaxColors, palNumColors;
- rdr::U32 monoBackground, monoForeground;
- TIGHT_PALETTE palette;
+ int palMaxColors;
+ Palette palette;
static const int defaultCompressLevel;
static const TIGHT_CONF conf[];
diff --git a/common/rfb/TightPalette.cxx b/common/rfb/TightPalette.cxx
deleted file mode 100644
index c4ed04e4..00000000
--- a/common/rfb/TightPalette.cxx
+++ /dev/null
@@ -1,110 +0,0 @@
-/* Copyright (C) 2000-2005 Constantin Kaplinsky. 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.
- */
-
-//
-// TightPalette class implementation.
-//
-
-#include <rfb/TightPalette.h>
-
-using namespace rfb;
-
-TightPalette::TightPalette(int maxColors)
-{
- setMaxColors(maxColors);
- reset();
-}
-
-void TightPalette::reset()
-{
- m_numColors = 0;
- memset(m_hash, 0, 256 * sizeof(TightColorList *));
-}
-
-void TightPalette::setMaxColors(int maxColors)
-{
- m_maxColors = maxColors;
- if (m_maxColors < 0) {
- m_maxColors = 0;
- } else if (m_maxColors > 254) {
- m_maxColors = 254;
- }
-}
-
-int TightPalette::insert(rdr::U32 rgb, int numPixels)
-{
- TightColorList *pnode;
- TightColorList *prev_pnode = NULL;
- int hash_key, idx, new_idx, count;
-
- hash_key = hashFunc(rgb);
-
- pnode = m_hash[hash_key];
-
- while (pnode != NULL) {
- if (pnode->rgb == rgb) {
- // Such palette entry already exists.
- new_idx = idx = pnode->idx;
- count = m_entry[idx].numPixels + numPixels;
- if (new_idx && m_entry[new_idx-1].numPixels < count) {
- do {
- m_entry[new_idx] = m_entry[new_idx-1];
- m_entry[new_idx].listNode->idx = new_idx;
- new_idx--;
- }
- while (new_idx && m_entry[new_idx-1].numPixels < count);
-
- m_entry[new_idx].listNode = pnode;
- pnode->idx = new_idx;
- }
- m_entry[new_idx].numPixels = count;
- return m_numColors;
- }
- prev_pnode = pnode;
- pnode = pnode->next;
- }
-
- // Check if the palette is full.
- if (m_numColors == 256 || m_numColors == m_maxColors) {
- m_numColors = 0;
- return 0;
- }
-
- // Move palette entries with lesser pixel counts.
- for ( idx = m_numColors;
- idx > 0 && m_entry[idx-1].numPixels < numPixels;
- idx-- ) {
- m_entry[idx] = m_entry[idx-1];
- m_entry[idx].listNode->idx = idx;
- }
-
- // Add new palette entry into the freed slot.
- pnode = &m_list[m_numColors];
- if (prev_pnode != NULL) {
- prev_pnode->next = pnode;
- } else {
- m_hash[hash_key] = pnode;
- }
- pnode->next = NULL;
- pnode->idx = idx;
- pnode->rgb = rgb;
- m_entry[idx].listNode = pnode;
- m_entry[idx].numPixels = numPixels;
-
- return ++m_numColors;
-}
diff --git a/common/rfb/TightPalette.h b/common/rfb/TightPalette.h
deleted file mode 100644
index 2f6448ea..00000000
--- a/common/rfb/TightPalette.h
+++ /dev/null
@@ -1,127 +0,0 @@
-/* Copyright (C) 2000-2005 Constantin Kaplinsky. 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.
- */
-
-//
-// TightPalette class is a container for ordered color values. Colors
-// are keys in a hash where values are frequency counts. Also, there
-// is a list where colors are always sorted by these counts (more
-// frequent first).
-//
-
-#ifndef __RFB_TIGHTPALETTE_H__
-#define __RFB_TIGHTPALETTE_H__
-
-#include <string.h>
-#include <rdr/types.h>
-
-namespace rfb {
-
- struct TightColorList {
- TightColorList *next;
- int idx;
- rdr::U32 rgb;
- };
-
- struct TightPaletteEntry {
- TightColorList *listNode;
- int numPixels;
- };
-
- class TightPalette {
-
- protected:
-
- // FIXME: Bigger hash table? Better hash function?
- inline static int hashFunc(rdr::U32 rgb) {
- return (rgb ^ (rgb >> 13)) & 0xFF;
- }
-
- public:
-
- TightPalette(int maxColors = 254);
-
- //
- // Re-initialize the object. This does not change maximum number
- // of colors.
- //
- void reset();
-
- //
- // Set limit on the number of colors in the palette. Note that
- // this value cannot exceed 254.
- //
- void setMaxColors(int maxColors);
-
- //
- // Insert new color into the palette, or increment its counter if
- // the color is already there. Returns new number of colors, or
- // zero if the palette is full. If the palette becomes full, it
- // reports zero colors and cannot be used any more without calling
- // reset().
- //
- int insert(rdr::U32 rgb, int numPixels);
-
- //
- // Return number of colors in the palette.
- //
- inline int getNumColors() const {
- return m_numColors;
- }
-
- //
- // Return the color specified by its index in the palette.
- //
- inline rdr::U32 getEntry(int i) const {
- return (i < m_numColors) ? m_entry[i].listNode->rgb : (rdr::U32)-1;
- }
-
- //
- // Return the pixel counter of the color specified by its index.
- //
- inline int getCount(int i) const {
- return (i < m_numColors) ? m_entry[i].numPixels : 0;
- }
-
- //
- // Return the index of a specified color.
- //
- inline rdr::U8 getIndex(rdr::U32 rgb) const {
- TightColorList *pnode = m_hash[hashFunc(rgb)];
- while (pnode != NULL) {
- if (pnode->rgb == rgb) {
- return (rdr::U8)pnode->idx;
- }
- pnode = pnode->next;
- }
- return 0xFF; // no such color
- }
-
- protected:
-
- int m_maxColors;
- int m_numColors;
-
- TightPaletteEntry m_entry[256];
- TightColorList *m_hash[256];
- TightColorList m_list[256];
-
- };
-
-} // namespace rfb
-
-#endif // __RFB_TIGHTPALETTE_H__
diff --git a/common/rfb/TransImageGetter.cxx b/common/rfb/TransImageGetter.cxx
index 3900d065..05df1a98 100644
--- a/common/rfb/TransImageGetter.cxx
+++ b/common/rfb/TransImageGetter.cxx
@@ -24,10 +24,7 @@
#include <rfb/Exception.h>
#include <rfb/ConnParams.h>
#include <rfb/SMsgWriter.h>
-#include <rfb/ColourMap.h>
-#include <rfb/TrueColourMap.h>
#include <rfb/PixelBuffer.h>
-#include <rfb/ColourCube.h>
#include <rfb/TransImageGetter.h>
using namespace rfb;
@@ -42,18 +39,12 @@ TransImageGetter::~TransImageGetter()
}
void TransImageGetter::init(PixelBuffer* pb_, const PixelFormat& out,
- SMsgWriter* writer_, ColourCube* cube_)
+ SMsgWriter* writer_)
{
pb = pb_;
writer = writer_;
- PixelTransformer::init(pb->getPF(), pb->getColourMap(), out, cube_,
- cmCallback, this);
-}
-
-void TransImageGetter::setColourMapEntries(int firstCol, int nCols)
-{
- PixelTransformer::setColourMapEntries(firstCol, nCols);
+ PixelTransformer::init(pb->getPF(), out);
}
const rdr::U8 *TransImageGetter::getRawBufferR(const Rect &r, int *stride)
@@ -74,15 +65,3 @@ void TransImageGetter::getImage(void* outPtr, const Rect& r, int outStride)
translateRect((void*)inPtr, inStride, Rect(0, 0, r.width(), r.height()),
outPtr, outStride, Point(0, 0));
}
-
-void TransImageGetter::cmCallback(int firstColour, int nColours,
- ColourMap* cm, void* data)
-{
- TransImageGetter *self;
-
- assert(data);
- self = (TransImageGetter*)data;
-
- if (self->writer)
- self->writer->writeSetColourMapEntries(firstColour, nColours, cm);
-}
diff --git a/common/rfb/TransImageGetter.h b/common/rfb/TransImageGetter.h
index b241b83c..bfd9c2fa 100644
--- a/common/rfb/TransImageGetter.h
+++ b/common/rfb/TransImageGetter.h
@@ -27,17 +27,13 @@
#include <rfb/Rect.h>
#include <rfb/PixelFormat.h>
#include <rfb/PixelTransformer.h>
-#include <rfb/ImageGetter.h>
namespace rfb {
class SMsgWriter;
- class ColourMap;
class PixelBuffer;
- class ColourCube;
- class TransImageGetter : public ImageGetter,
- public PixelTransformer {
+ class TransImageGetter : public PixelTransformer {
public:
TransImageGetter(bool econ=false);
@@ -45,25 +41,9 @@ namespace rfb {
// init() is called to initialise the translation tables. The PixelBuffer
// argument gives the source data and format details, outPF gives the
- // client's pixel format. If the client has a colour map, then the writer
- // argument is used to send a SetColourMapEntries message to the client.
+ // client's pixel format.
- void init(PixelBuffer* pb, const PixelFormat& outPF, SMsgWriter* writer=0,
- ColourCube* cube=0);
-
- // setColourMapEntries() is called when the PixelBuffer has a colour map
- // which has changed. firstColour and nColours specify which part of the
- // colour map has changed. If nColours is 0, this means the rest of the
- // colour map. The PixelBuffer previously passed to init() must have a
- // valid ColourMap object. If the client also has a colour map, then the
- // writer argument is used to send a SetColourMapEntries message to the
- // client. If the client is true colour then instead we update the
- // internal translation table - in this case the caller should also make
- // sure that the client receives an update of the relevant parts of the
- // framebuffer (the simplest thing to do is just update the whole
- // framebuffer, though it is possible to be smarter than this).
-
- void setColourMapEntries(int firstColour, int nColours);
+ void init(PixelBuffer* pb, const PixelFormat& outPF, SMsgWriter* writer=0);
// getImage() gets the given rectangle of data from the PixelBuffer,
// translates it into the client's pixel format and puts it in the buffer
@@ -90,17 +70,12 @@ namespace rfb {
void setOffset(const Point& offset_) { offset = offset_; }
private:
- static void cmCallback(int firstColour, int nColours,
- ColourMap* cm, void* data);
-
- private:
bool economic;
PixelBuffer* pb;
PixelFormat outPF;
SMsgWriter* writer;
rdr::U8* table;
transFnType transFn;
- ColourCube* cube;
Point offset;
};
}
diff --git a/common/rfb/VNCSConnectionST.cxx b/common/rfb/VNCSConnectionST.cxx
index 381ee216..fcb678ad 100644
--- a/common/rfb/VNCSConnectionST.cxx
+++ b/common/rfb/VNCSConnectionST.cxx
@@ -1,5 +1,5 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
- * Copyright 2009-2011 Pierre Ossman for Cendio AB
+ * Copyright 2009-2014 Pierre Ossman for Cendio AB
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -37,6 +37,7 @@
#include <rfb/ServerCore.h>
#include <rfb/ComparingUpdateTracker.h>
#include <rfb/KeyRemapper.h>
+#include <rfb/Encoder.h>
#define XK_MISCELLANY
#define XK_XKB_KEYS
#include <rfb/keysymdef.h>
@@ -81,6 +82,8 @@ VNCSConnectionST::VNCSConnectionST(VNCServerST* server_, network::Socket *s,
peerEndpoint.buf = sock->getPeerEndpoint();
VNCServerST::connectionsLog.write(1,"accepted: %s", peerEndpoint.buf);
+ memset(encoders, 0, sizeof(encoders));
+
// Configure the socket
setSocketTimeouts();
lastEventTime = time(0);
@@ -106,6 +109,9 @@ VNCSConnectionST::~VNCSConnectionST()
// Remove this client from the server
server->clients.remove(this);
+ for (int i = 0; i <= encodingMax; i++)
+ delete encoders[i];
+
delete [] fenceData;
}
@@ -253,15 +259,6 @@ void VNCSConnectionST::screenLayoutChangeOrClose(rdr::U16 reason)
}
}
-void VNCSConnectionST::setColourMapEntriesOrClose(int firstColour,int nColours)
-{
- try {
- setColourMapEntries(firstColour, nColours);
- } catch(rdr::Exception& e) {
- close(e.str());
- }
-}
-
void VNCSConnectionST::bellOrClose()
{
try {
@@ -625,11 +622,6 @@ void VNCSConnectionST::setDesktopSize(int fb_width, int fb_height,
writeFramebufferUpdate();
}
-void VNCSConnectionST::setInitialColourMap()
-{
- setColourMapEntries(0, 0);
-}
-
void VNCSConnectionST::fence(rdr::U32 flags, unsigned len, const char data[])
{
if (flags & fenceFlagRequest) {
@@ -745,13 +737,19 @@ void VNCSConnectionST::writeSetCursorCallback()
}
// Use RichCursor
- rdr::U8* transData = writer()->getImageBuf(server->cursor.area());
- image_getter.translatePixels(server->cursor.data, transData,
- server->cursor.area());
+ rdr::U8* transBuffer;
+ int stride;
+ const rdr::U8* buffer;
+
+ transBuffer = writer()->getImageBuf(server->cursor.area());
+
+ buffer = server->cursor.getBuffer(server->cursor.getRect(), &stride);
+ image_getter.translatePixels(buffer, transBuffer, server->cursor.area());
+
writer()->writeSetCursor(server->cursor.width(),
server->cursor.height(),
server->cursor.hotspot,
- transData, server->cursor.mask.buf);
+ transBuffer, server->cursor.mask.buf);
}
@@ -1074,18 +1072,30 @@ void VNCSConnectionST::writeFramebufferUpdate()
}
if (!ui.is_empty() || writer()->needFakeUpdate() || drawRenderedCursor) {
+ std::vector<Rect> rects;
+ std::vector<Rect>::const_iterator i;
+ int encoding;
+
+ // Make sure the encoder has the latest settings
+ encoding = cp.currentEncoding();
+
+ if (!encoders[encoding])
+ encoders[encoding] = Encoder::createEncoder(encoding, this);
+
+ encoders[encoding]->setCompressLevel(cp.compressLevel);
+ encoders[encoding]->setQualityLevel(cp.qualityLevel);
+ encoders[encoding]->setFineQualityLevel(cp.fineQualityLevel,
+ cp.subsampling);
+
// Compute the number of rectangles. Tight encoder makes the things more
// complicated as compared to the original VNC4.
- writer()->setupCurrentEncoder();
int nRects = (ui.copied.numRects() +
(drawRenderedCursor ? 1 : 0));
- std::vector<Rect> rects;
- std::vector<Rect>::const_iterator i;
ui.changed.get_rects(&rects);
for (i = rects.begin(); i != rects.end(); i++) {
if (i->width() && i->height()) {
- int nUpdateRects = writer()->getNumRects(*i);
+ int nUpdateRects = encoders[encoding]->getNumRects(*i);
if (nUpdateRects == 0 && cp.currentEncoding() == encodingTight) {
// With Tight encoding and LastRect support, the client does not
// care about the number of rectangles in the update - it will
@@ -1102,18 +1112,33 @@ void VNCSConnectionST::writeFramebufferUpdate()
writer()->writeFramebufferUpdateStart(nRects);
- Region updatedRegion;
- writer()->writeRects(ui, &image_getter, &updatedRegion);
- updates.subtract(updatedRegion);
+ ui.copied.get_rects(&rects);
+ for (i = rects.begin(); i != rects.end(); i++)
+ writer()->writeCopyRect(*i, i->tl.x - ui.copy_delta.x,
+ i->tl.y - ui.copy_delta.y);
+
+ ui.changed.get_rects(&rects);
+ for (i = rects.begin(); i != rects.end(); i++)
+ encoders[encoding]->writeRect(*i, &image_getter);
+
+ if (drawRenderedCursor) {
+ image_getter.setPixelBuffer(&server->renderedCursor);
+ image_getter.setOffset(server->renderedCursorTL);
+
+ encoders[encoding]->writeRect(renderedCursorRect, &image_getter);
- if (drawRenderedCursor)
- writeRenderedCursorRect();
+ image_getter.setPixelBuffer(server->pb);
+ image_getter.setOffset(Point(0,0));
+
+ drawRenderedCursor = false;
+ }
writer()->writeFramebufferUpdateEnd();
writeRTTPing();
requested.clear();
+ updates.clear();
}
out:
@@ -1121,23 +1146,6 @@ out:
}
-// writeRenderedCursorRect() writes a single rectangle drawing the rendered
-// cursor on the client.
-
-void VNCSConnectionST::writeRenderedCursorRect()
-{
- image_getter.setPixelBuffer(&server->renderedCursor);
- image_getter.setOffset(server->renderedCursorTL);
-
- Rect actual;
- writer()->writeRect(renderedCursorRect, &image_getter, &actual);
-
- image_getter.setPixelBuffer(server->pb);
- image_getter.setOffset(Point(0,0));
-
- drawRenderedCursor = false;
-}
-
void VNCSConnectionST::screenLayoutChange(rdr::U16 reason)
{
if (!authenticated())
@@ -1153,21 +1161,6 @@ void VNCSConnectionST::screenLayoutChange(rdr::U16 reason)
writeFramebufferUpdate();
}
-void VNCSConnectionST::setColourMapEntries(int firstColour, int nColours)
-{
- if (!readyForSetColourMapEntries)
- return;
- if (server->pb->getPF().trueColour)
- return;
-
- image_getter.setColourMapEntries(firstColour, nColours);
-
- if (cp.pf().trueColour) {
- updates.add_changed(server->pb->getRect());
- writeFramebufferUpdate();
- }
-}
-
// setCursor() is called whenever the cursor has changed shape or pixel format.
// If the client supports local cursor then it will arrange for the cursor to
diff --git a/common/rfb/VNCSConnectionST.h b/common/rfb/VNCSConnectionST.h
index 5eb908ab..ca5c4f01 100644
--- a/common/rfb/VNCSConnectionST.h
+++ b/common/rfb/VNCSConnectionST.h
@@ -37,6 +37,8 @@
struct RTTInfo;
namespace rfb {
+ class Encoder;
+
class VNCSConnectionST : public SConnection,
public WriteSetCursorCallback,
public Timer::Callback {
@@ -71,7 +73,6 @@ namespace rfb {
// Wrappers to make these methods "safe" for VNCServerST.
void writeFramebufferUpdateOrClose();
void screenLayoutChangeOrClose(rdr::U16 reason);
- void setColourMapEntriesOrClose(int firstColour, int nColours);
void setCursorOrClose();
void bellOrClose();
void serverCutTextOrClose(const char *str, int len);
@@ -138,7 +139,6 @@ namespace rfb {
virtual void framebufferUpdateRequest(const Rect& r, bool incremental);
virtual void setDesktopSize(int fb_width, int fb_height,
const ScreenSet& layout);
- virtual void setInitialColourMap();
virtual void fence(rdr::U32 flags, unsigned len, const char data[]);
virtual void enableContinuousUpdates(bool enable,
int x, int y, int w, int h);
@@ -171,9 +171,7 @@ namespace rfb {
void writeFramebufferUpdate();
- void writeRenderedCursorRect();
void screenLayoutChange(rdr::U16 reason);
- void setColourMapEntries(int firstColour, int nColours);
void setCursor();
void setDesktopName(const char *name);
void setSocketTimeouts();
@@ -205,6 +203,7 @@ namespace rfb {
Rect renderedCursorRect;
bool continuousUpdates;
Region cuRegion;
+ Encoder* encoders[encodingMax+1];
Timer updateTimer;
diff --git a/common/rfb/VNCServer.h b/common/rfb/VNCServer.h
index 280b68b4..c76e5c9c 100644
--- a/common/rfb/VNCServer.h
+++ b/common/rfb/VNCServer.h
@@ -52,12 +52,6 @@ namespace rfb {
// getPixelBuffer() returns a pointer to the PixelBuffer object.
virtual PixelBuffer* getPixelBuffer() const = 0;
- // setColourMapEntries() tells the server that some entries in the colour
- // map have changed. The server will retrieve them via the PixelBuffer's
- // ColourMap object. This may result in protocol messages being sent.
- // If nColours is 0, this means the rest of the colour map.
- virtual void setColourMapEntries(int firstColour=0, int nColours=0) = 0;
-
// serverCutText() tells the server that the cut text has changed. This
// will normally be sent to all clients.
virtual void serverCutText(const char* str, int len) = 0;
@@ -79,7 +73,7 @@ namespace rfb {
// in left-to-right order. The server takes its own copy of the data in
// cursorData and mask.
virtual void setCursor(int width, int height, const Point& hotspot,
- void* cursorData, void* mask) = 0;
+ const void* cursorData, const void* mask) = 0;
// setCursorPos() tells the server the current position of the cursor.
virtual void setCursorPos(const Point& p) = 0;
diff --git a/common/rfb/VNCServerST.cxx b/common/rfb/VNCServerST.cxx
index b07f5c35..f1e378ed 100644
--- a/common/rfb/VNCServerST.cxx
+++ b/common/rfb/VNCServerST.cxx
@@ -1,4 +1,5 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
+ * Copyright 2009-2014 Pierre Ossman for Cendio AB
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -359,15 +360,6 @@ void VNCServerST::setScreenLayout(const ScreenSet& layout)
}
}
-void VNCServerST::setColourMapEntries(int firstColour, int nColours)
-{
- std::list<VNCSConnectionST*>::iterator ci, ci_next;
- for (ci = clients.begin(); ci != clients.end(); ci = ci_next) {
- ci_next = ci; ci_next++;
- (*ci)->setColourMapEntriesOrClose(firstColour, nColours);
- }
-}
-
void VNCServerST::bell()
{
std::list<VNCSConnectionST*>::iterator ci, ci_next;
@@ -417,11 +409,11 @@ void VNCServerST::add_copied(const Region& dest, const Point& delta)
}
void VNCServerST::setCursor(int width, int height, const Point& newHotspot,
- void* data, void* mask)
+ const void* data, const void* mask)
{
cursor.hotspot = newHotspot;
cursor.setSize(width, height);
- memcpy(cursor.data, data, cursor.dataLen());
+ cursor.imageRect(cursor.getRect(), data);
memcpy(cursor.mask.buf, mask, cursor.maskLen());
cursor.crop();
@@ -630,11 +622,17 @@ bool VNCServerST::checkUpdate()
comparer->getUpdateInfo(&ui, pb->getRect());
if (renderCursor) {
- pb->getImage(renderedCursor.data,
- renderedCursor.getRect(renderedCursorTL));
+ const rdr::U8* buffer;
+ int stride;
+
+ buffer = pb->getBuffer(renderedCursor.getRect(renderedCursorTL), &stride);
+ renderedCursor.imageRect(renderedCursor.getRect(), buffer, stride);
+
+ buffer = cursor.getBuffer(cursor.getRect(), &stride);
renderedCursor.maskRect(cursor.getRect(cursorTL()
.subtract(renderedCursorTL)),
- cursor.data, cursor.mask.buf);
+ buffer, cursor.mask.buf);
+
renderedCursorInvalid = false;
}
diff --git a/common/rfb/VNCServerST.h b/common/rfb/VNCServerST.h
index e75954fc..ed7833ab 100644
--- a/common/rfb/VNCServerST.h
+++ b/common/rfb/VNCServerST.h
@@ -88,12 +88,11 @@ namespace rfb {
virtual void setPixelBuffer(PixelBuffer* pb);
virtual void setScreenLayout(const ScreenSet& layout);
virtual PixelBuffer* getPixelBuffer() const { return pb; }
- virtual void setColourMapEntries(int firstColour=0, int nColours=0);
virtual void serverCutText(const char* str, int len);
virtual void add_changed(const Region &region);
virtual void add_copied(const Region &dest, const Point &delta);
virtual void setCursor(int width, int height, const Point& hotspot,
- void* cursorData, void* mask);
+ const void* cursorData, const void* mask);
virtual void setCursorPos(const Point& p);
virtual void bell();
diff --git a/common/rfb/ZRLEDecoder.cxx b/common/rfb/ZRLEDecoder.cxx
index 111e2de6..7e933a8f 100644
--- a/common/rfb/ZRLEDecoder.cxx
+++ b/common/rfb/ZRLEDecoder.cxx
@@ -16,14 +16,32 @@
* USA.
*/
#include <rfb/CMsgReader.h>
+#include <rfb/CConnection.h>
#include <rfb/CMsgHandler.h>
#include <rfb/ZRLEDecoder.h>
using namespace rfb;
-#define EXTRA_ARGS CMsgHandler* handler
-#define FILL_RECT(r, p) handler->fillRect(r, p)
-#define IMAGE_RECT(r, p) handler->imageRect(r, p)
+static inline rdr::U32 readOpaque24A(rdr::InStream* is)
+{
+ is->check(3);
+ rdr::U32 r=0;
+ ((rdr::U8*)&r)[0] = is->readU8();
+ ((rdr::U8*)&r)[1] = is->readU8();
+ ((rdr::U8*)&r)[2] = is->readU8();
+ return r;
+
+}
+static inline rdr::U32 readOpaque24B(rdr::InStream* is)
+{
+ is->check(3);
+ rdr::U32 r=0;
+ ((rdr::U8*)&r)[1] = is->readU8();
+ ((rdr::U8*)&r)[2] = is->readU8();
+ ((rdr::U8*)&r)[3] = is->readU8();
+ return r;
+}
+
#define BPP 8
#include <rfb/zrleDecode.h>
#undef BPP
@@ -40,7 +58,7 @@ using namespace rfb;
#undef CPIXEL
#undef BPP
-ZRLEDecoder::ZRLEDecoder(CMsgReader* reader_) : reader(reader_)
+ZRLEDecoder::ZRLEDecoder(CConnection* conn) : Decoder(conn)
{
}
@@ -50,9 +68,9 @@ ZRLEDecoder::~ZRLEDecoder()
void ZRLEDecoder::readRect(const Rect& r, CMsgHandler* handler)
{
- rdr::InStream* is = reader->getInStream();
- rdr::U8* buf = reader->getImageBuf(64 * 64 * 4);
- switch (reader->bpp()) {
+ rdr::InStream* is = conn->getInStream();
+ rdr::U8* buf = conn->reader()->getImageBuf(64 * 64 * 4);
+ switch (conn->cp.pf().bpp) {
case 8: zrleDecode8 (r, is, &zis, (rdr::U8*) buf, handler); break;
case 16: zrleDecode16(r, is, &zis, (rdr::U16*)buf, handler); break;
case 32:
diff --git a/common/rfb/ZRLEDecoder.h b/common/rfb/ZRLEDecoder.h
index 2128ab91..e7e2b8cb 100644
--- a/common/rfb/ZRLEDecoder.h
+++ b/common/rfb/ZRLEDecoder.h
@@ -25,11 +25,10 @@ namespace rfb {
class ZRLEDecoder : public Decoder {
public:
- ZRLEDecoder(CMsgReader* reader);
+ ZRLEDecoder(CConnection* conn);
virtual ~ZRLEDecoder();
virtual void readRect(const Rect& r, CMsgHandler* handler);
private:
- CMsgReader* reader;
rdr::ZlibInStream zis;
};
}
diff --git a/common/rfb/ZRLEEncoder.cxx b/common/rfb/ZRLEEncoder.cxx
index e70706b5..968edcfb 100644
--- a/common/rfb/ZRLEEncoder.cxx
+++ b/common/rfb/ZRLEEncoder.cxx
@@ -21,6 +21,7 @@
#include <rfb/encodings.h>
#include <rfb/ConnParams.h>
#include <rfb/SMsgWriter.h>
+#include <rfb/SConnection.h>
#include <rfb/ZRLEEncoder.h>
#include <rfb/Configuration.h>
@@ -28,8 +29,21 @@ using namespace rfb;
IntParameter zlibLevel("ZlibLevel","Zlib compression level",-1);
-#define EXTRA_ARGS ImageGetter* ig
-#define GET_IMAGE_INTO_BUF(r,buf) ig->getImage(buf, r);
+static inline void writeOpaque24A(rdr::OutStream* os, rdr::U32 u)
+{
+ os->check(3);
+ os->writeU8(((rdr::U8*)&u)[0]);
+ os->writeU8(((rdr::U8*)&u)[1]);
+ os->writeU8(((rdr::U8*)&u)[2]);
+}
+static inline void writeOpaque24B(rdr::OutStream* os, rdr::U32 u)
+{
+ os->check(3);
+ os->writeU8(((rdr::U8*)&u)[1]);
+ os->writeU8(((rdr::U8*)&u)[2]);
+ os->writeU8(((rdr::U8*)&u)[3]);
+}
+
#define BPP 8
#include <rfb/zrleEncode.h>
#undef BPP
@@ -46,8 +60,8 @@ IntParameter zlibLevel("ZlibLevel","Zlib compression level",-1);
#undef CPIXEL
#undef BPP
-ZRLEEncoder::ZRLEEncoder(SMsgWriter* writer_)
- : writer(writer_), zos(0,0,zlibLevel), mos(129*1024)
+ZRLEEncoder::ZRLEEncoder(SConnection* conn)
+ : Encoder(conn), zos(0,0,zlibLevel), mos(129*1024)
{
}
@@ -55,23 +69,21 @@ ZRLEEncoder::~ZRLEEncoder()
{
}
-bool ZRLEEncoder::writeRect(const Rect& r, TransImageGetter* ig, Rect* actual)
+void ZRLEEncoder::writeRect(const Rect& r, TransImageGetter* ig)
{
- rdr::U8* imageBuf = writer->getImageBuf(64 * 64 * 4 + 4);
+ rdr::U8* imageBuf = conn->writer()->getImageBuf(64 * 64 * 4 + 4);
mos.clear();
- bool wroteAll = true;
- *actual = r;
- switch (writer->bpp()) {
+ switch (conn->cp.pf().bpp) {
case 8:
- wroteAll = zrleEncode8(r, &mos, &zos, imageBuf, actual, ig);
+ zrleEncode8(r, &mos, &zos, imageBuf, ig);
break;
case 16:
- wroteAll = zrleEncode16(r, &mos, &zos, imageBuf, actual, ig);
+ zrleEncode16(r, &mos, &zos, imageBuf, ig);
break;
case 32:
{
- const PixelFormat& pf = writer->getConnParams()->pf();
+ const PixelFormat& pf = conn->cp.pf();
Pixel maxPixel = pf.pixelFromRGB((rdr::U16)-1, (rdr::U16)-1, (rdr::U16)-1);
bool fitsInLS3Bytes = maxPixel < (1<<24);
@@ -80,25 +92,24 @@ bool ZRLEEncoder::writeRect(const Rect& r, TransImageGetter* ig, Rect* actual)
if ((fitsInLS3Bytes && pf.isLittleEndian()) ||
(fitsInMS3Bytes && pf.isBigEndian()))
{
- wroteAll = zrleEncode24A(r, &mos, &zos, imageBuf, actual, ig);
+ zrleEncode24A(r, &mos, &zos, imageBuf, ig);
}
else if ((fitsInLS3Bytes && pf.isBigEndian()) ||
(fitsInMS3Bytes && pf.isLittleEndian()))
{
- wroteAll = zrleEncode24B(r, &mos, &zos, imageBuf, actual, ig);
+ zrleEncode24B(r, &mos, &zos, imageBuf, ig);
}
else
{
- wroteAll = zrleEncode32(r, &mos, &zos, imageBuf, actual, ig);
+ zrleEncode32(r, &mos, &zos, imageBuf, ig);
}
break;
}
}
- writer->startRect(*actual, encodingZRLE);
- rdr::OutStream* os = writer->getOutStream();
+ conn->writer()->startRect(r, encodingZRLE);
+ rdr::OutStream* os = conn->getOutStream();
os->writeU32(mos.length());
os->writeBytes(mos.data(), mos.length());
- writer->endRect();
- return wroteAll;
+ conn->writer()->endRect();
}
diff --git a/common/rfb/ZRLEEncoder.h b/common/rfb/ZRLEEncoder.h
index e3517c13..d285967e 100644
--- a/common/rfb/ZRLEEncoder.h
+++ b/common/rfb/ZRLEEncoder.h
@@ -26,11 +26,10 @@ namespace rfb {
class ZRLEEncoder : public Encoder {
public:
- ZRLEEncoder(SMsgWriter* writer);
+ ZRLEEncoder(SConnection* conn);
virtual ~ZRLEEncoder();
- virtual bool writeRect(const Rect& r, TransImageGetter* ig, Rect* actual);
+ virtual void writeRect(const Rect& r, TransImageGetter* ig);
private:
- SMsgWriter* writer;
rdr::ZlibOutStream zos;
rdr::MemOutStream mos;
};
diff --git a/common/rfb/hextileDecode.h b/common/rfb/hextileDecode.h
index 7aa04d91..518a6063 100644
--- a/common/rfb/hextileDecode.h
+++ b/common/rfb/hextileDecode.h
@@ -18,11 +18,8 @@
//
// Hextile decoding function.
//
-// This file is #included after having set the following macros:
+// This file is #included after having set the following macro:
// BPP - 8, 16 or 32
-// EXTRA_ARGS - optional extra arguments
-// FILL_RECT - fill a rectangle with a single colour
-// IMAGE_RECT - draw a rectangle of pixel data from a buffer
#include <rdr/InStream.h>
#include <rfb/hextileConstants.h>
@@ -40,11 +37,8 @@ namespace rfb {
#define READ_PIXEL CONCAT2E(readOpaque,BPP)
#define HEXTILE_DECODE CONCAT2E(hextileDecode,BPP)
-void HEXTILE_DECODE (const Rect& r, rdr::InStream* is, PIXEL_T* buf
-#ifdef EXTRA_ARGS
- , EXTRA_ARGS
-#endif
- )
+void HEXTILE_DECODE (const Rect& r, rdr::InStream* is, PIXEL_T* buf,
+ CMsgHandler* handler)
{
Rect t;
PIXEL_T bg = 0;
@@ -62,7 +56,7 @@ void HEXTILE_DECODE (const Rect& r, rdr::InStream* is, PIXEL_T* buf
if (tileType & hextileRaw) {
is->readBytes(buf, t.area() * (BPP/8));
- IMAGE_RECT(t, buf);
+ handler->imageRect(t, buf);
continue;
}
@@ -100,7 +94,7 @@ void HEXTILE_DECODE (const Rect& r, rdr::InStream* is, PIXEL_T* buf
}
}
}
- IMAGE_RECT(t, buf);
+ handler->imageRect(t, buf);
}
}
}
diff --git a/common/rfb/hextileEncode.h b/common/rfb/hextileEncode.h
index 0d2e8aba..7e5b2db7 100644
--- a/common/rfb/hextileEncode.h
+++ b/common/rfb/hextileEncode.h
@@ -19,10 +19,8 @@
//
// Hextile encoding function.
//
-// This file is #included after having set the following macros:
+// This file is #included after having set the following macro:
// BPP - 8, 16 or 32
-// EXTRA_ARGS - optional extra arguments
-// GET_IMAGE_INTO_BUF - gets a rectangle of pixel data into a buffer
#include <rdr/OutStream.h>
#include <rfb/hextileConstants.h>
@@ -46,11 +44,7 @@ int TEST_TILE_TYPE (PIXEL_T* data, int w, int h, PIXEL_T* bg, PIXEL_T* fg);
int HEXTILE_ENCODE_TILE (PIXEL_T* data, int w, int h, int tileType,
rdr::U8* encoded, PIXEL_T bg);
-void HEXTILE_ENCODE(const Rect& r, rdr::OutStream* os
-#ifdef EXTRA_ARGS
- , EXTRA_ARGS
-#endif
- )
+void HEXTILE_ENCODE(const Rect& r, rdr::OutStream* os, TransImageGetter *ig)
{
Rect t;
PIXEL_T buf[256];
@@ -67,7 +61,7 @@ void HEXTILE_ENCODE(const Rect& r, rdr::OutStream* os
t.br.x = __rfbmin(r.br.x, t.tl.x + 16);
- GET_IMAGE_INTO_BUF(t,buf);
+ ig->getImage(buf, t);
PIXEL_T bg = 0, fg = 0;
int tileType = TEST_TILE_TYPE(buf, t.width(), t.height(), &bg, &fg);
@@ -96,7 +90,7 @@ void HEXTILE_ENCODE(const Rect& r, rdr::OutStream* os
encoded, bg);
if (encodedLen < 0) {
- GET_IMAGE_INTO_BUF(t,buf);
+ ig->getImage(buf, t);
os->writeU8(hextileRaw);
os->writeBytes(buf, t.width() * t.height() * (BPP/8));
oldBgValid = oldFgValid = false;
diff --git a/common/rfb/hextileEncodeBetter.h b/common/rfb/hextileEncodeBetter.h
index 2b6b160a..3a96ab63 100644
--- a/common/rfb/hextileEncodeBetter.h
+++ b/common/rfb/hextileEncodeBetter.h
@@ -19,14 +19,12 @@
//
// Hextile encoding function.
//
-// This file is #included after having set the following macros:
+// This file is #included after having set the following macro:
// BPP - 8, 16 or 32
-// EXTRA_ARGS - optional extra arguments
-// GET_IMAGE_INTO_BUF - gets a rectangle of pixel data into a buffer
#include <rdr/OutStream.h>
#include <rfb/hextileConstants.h>
-#include <rfb/TightPalette.h>
+#include <rfb/Palette.h>
#include <assert.h>
@@ -114,13 +112,13 @@ class HEXTILE_TILE {
private:
bool m_processed[16][16];
- TightPalette m_pal;
+ Palette m_pal;
};
HEXTILE_TILE::HEXTILE_TILE()
: m_tile(NULL), m_width(0), m_height(0),
m_size(0), m_flags(0), m_background(0), m_foreground(0),
- m_numSubrects(0), m_pal(48 + 2 * BPP)
+ m_numSubrects(0)
{
}
@@ -156,7 +154,7 @@ void HEXTILE_TILE::analyze()
PIXEL_T *colorsPtr = m_colors;
rdr::U8 *coordsPtr = m_coords;
- m_pal.reset();
+ m_pal.clear();
m_numSubrects = 0;
// Have we found the first subrect already?
@@ -200,7 +198,7 @@ void HEXTILE_TILE::analyze()
*coordsPtr++ = (rdr::U8)((x << 4) | (y & 0x0F));
*coordsPtr++ = (rdr::U8)(((sw - 1) << 4) | ((sh - 1) & 0x0F));
- if (m_pal.insert(color, 1) == 0) {
+ if (!m_pal.insert(color, 1) || (m_pal.size() > (48 + 2 * BPP))) {
// Handle palette overflow
m_flags = hextileRaw;
m_size = 0;
@@ -221,16 +219,16 @@ void HEXTILE_TILE::analyze()
}
// Save number of colors in this tile (should be no less than 2)
- int numColors = m_pal.getNumColors();
+ int numColors = m_pal.size();
assert(numColors >= 2);
- m_background = (PIXEL_T)m_pal.getEntry(0);
+ m_background = (PIXEL_T)m_pal.getColour(0);
m_flags = hextileAnySubrects;
int numSubrects = m_numSubrects - m_pal.getCount(0);
if (numColors == 2) {
// Monochrome tile
- m_foreground = (PIXEL_T)m_pal.getEntry(1);
+ m_foreground = (PIXEL_T)m_pal.getColour(1);
m_size = 1 + 2 * numSubrects;
} else {
// Colored tile
@@ -277,11 +275,7 @@ void HEXTILE_TILE::encode(rdr::U8 *dst) const
// Main encoding function.
//
-void HEXTILE_ENCODE(const Rect& r, rdr::OutStream* os
-#ifdef EXTRA_ARGS
- , EXTRA_ARGS
-#endif
- )
+void HEXTILE_ENCODE(const Rect& r, rdr::OutStream* os, TransImageGetter *ig)
{
Rect t;
PIXEL_T buf[256];
@@ -300,7 +294,7 @@ void HEXTILE_ENCODE(const Rect& r, rdr::OutStream* os
t.br.x = __rfbmin(r.br.x, t.tl.x + 16);
- GET_IMAGE_INTO_BUF(t,buf);
+ ig->getImage(buf, t);
tile.newTile(buf, t.width(), t.height());
int tileType = tile.getFlags();
diff --git a/common/rfb/rreDecode.h b/common/rfb/rreDecode.h
index 1f5bdf8b..d37461f9 100644
--- a/common/rfb/rreDecode.h
+++ b/common/rfb/rreDecode.h
@@ -18,10 +18,8 @@
//
// RRE decoding function.
//
-// This file is #included after having set the following macros:
+// This file is #included after having set the following macro:
// BPP - 8, 16 or 32
-// EXTRA_ARGS - optional extra arguments
-// FILL_RECT - fill a rectangle with a single colour
#include <rdr/InStream.h>
@@ -38,15 +36,11 @@ namespace rfb {
#define READ_PIXEL CONCAT2E(readOpaque,BPP)
#define RRE_DECODE CONCAT2E(rreDecode,BPP)
-void RRE_DECODE (const Rect& r, rdr::InStream* is
-#ifdef EXTRA_ARGS
- , EXTRA_ARGS
-#endif
- )
+void RRE_DECODE (const Rect& r, rdr::InStream* is, CMsgHandler* handler)
{
int nSubrects = is->readU32();
PIXEL_T bg = is->READ_PIXEL();
- FILL_RECT(r, bg);
+ handler->fillRect(r, bg);
for (int i = 0; i < nSubrects; i++) {
PIXEL_T pix = is->READ_PIXEL();
@@ -54,7 +48,7 @@ void RRE_DECODE (const Rect& r, rdr::InStream* is
int y = is->readU16();
int w = is->readU16();
int h = is->readU16();
- FILL_RECT(Rect(r.tl.x+x, r.tl.y+y, r.tl.x+x+w, r.tl.y+y+h), pix);
+ handler->fillRect(Rect(r.tl.x+x, r.tl.y+y, r.tl.x+x+w, r.tl.y+y+h), pix);
}
}
diff --git a/common/rfb/rreEncode.h b/common/rfb/rreEncode.h
index 3f834877..e3710575 100644
--- a/common/rfb/rreEncode.h
+++ b/common/rfb/rreEncode.h
@@ -18,7 +18,7 @@
//
// RRE encoding function.
//
-// This file is #included after having set the following macros:
+// This file is #included after having set the following macro:
// BPP - 8, 16 or 32
//
// The data argument to RRE_ENCODE contains the pixel data, and it writes the
diff --git a/common/rfb/tightDecode.h b/common/rfb/tightDecode.h
index 06c84775..a5963119 100644
--- a/common/rfb/tightDecode.h
+++ b/common/rfb/tightDecode.h
@@ -21,11 +21,8 @@
//
// Tight decoding functions.
//
-// This file is #included after having set the following macros:
+// This file is #included after having set the following macro:
// BPP - 8, 16 or 32
-// EXTRA_ARGS - optional extra arguments
-// FILL_RECT - fill a rectangle with a single color
-// IMAGE_RECT - draw a rectangle of pixel data from a buffer
#include <rdr/InStream.h>
#include <rdr/ZlibInStream.h>
@@ -76,11 +73,11 @@ void TIGHT_DECODE (const Rect& r)
if (cutZeros) {
rdr::U8 bytebuf[3];
is->readBytes(bytebuf, 3);
- serverpf.bufferFromRGB((rdr::U8*)&pix, bytebuf, 1, NULL);
+ serverpf.bufferFromRGB((rdr::U8*)&pix, bytebuf, 1);
} else {
pix = is->READ_PIXEL();
}
- FILL_RECT(r, pix);
+ handler->fillRect(r, pix);
return;
}
@@ -110,7 +107,7 @@ void TIGHT_DECODE (const Rect& r)
if (cutZeros) {
rdr::U8 tightPalette[256 * 3];
is->readBytes(tightPalette, palSize * 3);
- serverpf.bufferFromRGB((rdr::U8*)palette, tightPalette, palSize, NULL);
+ serverpf.bufferFromRGB((rdr::U8*)palette, tightPalette, palSize);
} else {
is->readBytes(palette, palSize * sizeof(PIXEL_T));
}
@@ -141,7 +138,7 @@ void TIGHT_DECODE (const Rect& r)
if (dataSize < TIGHT_MIN_TO_COMPRESS) {
input = is;
} else {
- int length = is->readCompactLength();
+ int length = readCompact(is);
streamId = comp_ctl & 0x03;
zis[streamId].setUnderlying(is, length);
input = &zis[streamId];
@@ -157,7 +154,7 @@ void TIGHT_DECODE (const Rect& r)
PIXEL_T *buf;
int stride = r.width();
if (directDecode) buf = (PIXEL_T *)handler->getRawBufferRW(r, &stride);
- else buf = (PIXEL_T *)reader->getImageBuf(r.area());
+ else buf = (PIXEL_T *)conn->reader()->getImageBuf(r.area());
if (palSize == 0) {
// Truecolor data
@@ -178,7 +175,7 @@ void TIGHT_DECODE (const Rect& r)
int w = r.width();
if (cutZeros) {
while (h > 0) {
- serverpf.bufferFromRGB((rdr::U8*)ptr, srcPtr, w, NULL);
+ serverpf.bufferFromRGB((rdr::U8*)ptr, srcPtr, w);
ptr += stride;
srcPtr += w * 3;
h--;
@@ -229,7 +226,7 @@ void TIGHT_DECODE (const Rect& r)
}
if (directDecode) handler->releaseRawBuffer(r);
- else IMAGE_RECT(r, buf);
+ else handler->imageRect(r, buf);
delete [] netbuf;
@@ -242,7 +239,7 @@ void
DECOMPRESS_JPEG_RECT(const Rect& r)
{
// Read length
- int compressedLen = is->readCompactLength();
+ int compressedLen = readCompact(is);
if (compressedLen <= 0) {
throw Exception("Incorrect data received from the server.\n");
}
@@ -287,7 +284,7 @@ TightDecoder::FilterGradient24(rdr::U8 *netbuf, PIXEL_T* buf, int stride,
pix[c] = netbuf[y*rectWidth*3+c] + prevRow[c];
thisRow[c] = pix[c];
}
- serverpf.bufferFromRGB((rdr::U8*)&buf[y*stride], pix, 1, NULL);
+ serverpf.bufferFromRGB((rdr::U8*)&buf[y*stride], pix, 1);
/* Remaining pixels of a row */
for (x = 1; x < rectWidth; x++) {
@@ -301,7 +298,7 @@ TightDecoder::FilterGradient24(rdr::U8 *netbuf, PIXEL_T* buf, int stride,
pix[c] = netbuf[(y*rectWidth+x)*3+c] + est[c];
thisRow[x*3+c] = pix[c];
}
- serverpf.bufferFromRGB((rdr::U8*)&buf[y*stride+x], pix, 1, NULL);
+ serverpf.bufferFromRGB((rdr::U8*)&buf[y*stride+x], pix, 1);
}
memcpy(prevRow, thisRow, sizeof(prevRow));
@@ -327,13 +324,13 @@ FILTER_GRADIENT(rdr::U8 *netbuf, PIXEL_T* buf, int stride, const Rect& r)
for (y = 0; y < rectHeight; y++) {
/* First pixel in a row */
- serverpf.rgbFromBuffer(pix, (rdr::U8*)&netbuf[y*rectWidth], 1, NULL);
+ serverpf.rgbFromBuffer(pix, (rdr::U8*)&netbuf[y*rectWidth], 1);
for (c = 0; c < 3; c++)
pix[c] += prevRow[c];
memcpy(thisRow, pix, sizeof(pix));
- serverpf.bufferFromRGB((rdr::U8*)&buf[y*stride], pix, 1, NULL);
+ serverpf.bufferFromRGB((rdr::U8*)&buf[y*stride], pix, 1);
/* Remaining pixels of a row */
for (x = 1; x < rectWidth; x++) {
@@ -346,13 +343,13 @@ FILTER_GRADIENT(rdr::U8 *netbuf, PIXEL_T* buf, int stride, const Rect& r)
}
}
- serverpf.rgbFromBuffer(pix, (rdr::U8*)&netbuf[y*rectWidth+x], 1, NULL);
+ serverpf.rgbFromBuffer(pix, (rdr::U8*)&netbuf[y*rectWidth+x], 1);
for (c = 0; c < 3; c++)
pix[c] += est[c];
memcpy(&thisRow[x*3], pix, sizeof(pix));
- serverpf.bufferFromRGB((rdr::U8*)&buf[y*stride+x], pix, 1, NULL);
+ serverpf.bufferFromRGB((rdr::U8*)&buf[y*stride+x], pix, 1);
}
memcpy(prevRow, thisRow, sizeof(prevRow));
diff --git a/common/rfb/tightEncode.h b/common/rfb/tightEncode.h
index c121b7aa..5d32cce3 100644
--- a/common/rfb/tightEncode.h
+++ b/common/rfb/tightEncode.h
@@ -1,5 +1,6 @@
/* Copyright (C) 2000-2003 Constantin Kaplinsky. All Rights Reserved.
* Copyright (C) 2011 D. R. Commander. All Rights Reserved.
+ * Copyright 2014 Pierre Ossman for Cendio AB.
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -20,10 +21,8 @@
//
// tightEncode.h - Tight encoding function.
//
-// This file is #included after having set the following macros:
+// This file is #included after having set the following macro:
// BPP - 8, 16 or 32
-// EXTRA_ARGS - optional extra arguments
-// GET_IMAGE_INTO_BUF - gets a rectangle of pixel data into a buffer
//
#include <assert.h>
@@ -54,82 +53,6 @@ namespace rfb {
#define TIGHT_ONCE
//
-// Functions to operate on palette structures.
-//
-
-#define HASH_FUNC16(rgb) ((int)(((rgb >> 8) + rgb) & 0xFF))
-#define HASH_FUNC32(rgb) ((int)(((rgb >> 16) + (rgb >> 8)) & 0xFF))
-
-void TightEncoder::paletteReset(void)
-{
- palNumColors = 0;
- memset(palette.hash, 0, 256 * sizeof(TIGHT_COLOR_LIST *));
-}
-
-int TightEncoder::paletteInsert(rdr::U32 rgb, int numPixels, int bpp)
-{
- TIGHT_COLOR_LIST *pnode;
- TIGHT_COLOR_LIST *prev_pnode = NULL;
- int hash_key, idx, new_idx, count;
-
- hash_key = (bpp == 16) ? HASH_FUNC16(rgb) : HASH_FUNC32(rgb);
-
- pnode = palette.hash[hash_key];
-
- while (pnode != NULL) {
- if (pnode->rgb == rgb) {
- // Such palette entry already exists.
- new_idx = idx = pnode->idx;
- count = palette.entry[idx].numPixels + numPixels;
- if (new_idx && palette.entry[new_idx-1].numPixels < count) {
- do {
- palette.entry[new_idx] = palette.entry[new_idx-1];
- palette.entry[new_idx].listNode->idx = new_idx;
- new_idx--;
- }
- while (new_idx &&
- palette.entry[new_idx-1].numPixels < count);
- palette.entry[new_idx].listNode = pnode;
- pnode->idx = new_idx;
- }
- palette.entry[new_idx].numPixels = count;
- return palNumColors;
- }
- prev_pnode = pnode;
- pnode = pnode->next;
- }
-
- // Check if palette is full.
- if ( palNumColors == 256 || palNumColors == palMaxColors ) {
- palNumColors = 0;
- return 0;
- }
-
- // Move palette entries with lesser pixel counts.
- for ( idx = palNumColors;
- idx > 0 && palette.entry[idx-1].numPixels < numPixels;
- idx-- ) {
- palette.entry[idx] = palette.entry[idx-1];
- palette.entry[idx].listNode->idx = idx;
- }
-
- // Add new palette entry into the freed slot.
- pnode = &palette.list[palNumColors];
- if (prev_pnode != NULL) {
- prev_pnode->next = pnode;
- } else {
- palette.hash[hash_key] = pnode;
- }
- pnode->next = NULL;
- pnode->idx = idx;
- pnode->rgb = rgb;
- palette.entry[idx].listNode = pnode;
- palette.entry[idx].numPixels = numPixels;
-
- return (++palNumColors);
-}
-
-//
// Compress the data (but do not perform actual compression if the data
// size is less than TIGHT_MIN_TO_COMPRESS bytes.
//
@@ -151,7 +74,7 @@ void TightEncoder::compressData(const void *buf, unsigned int length,
zos->writeBytes(buf, length);
zos->flush();
zos->setUnderlying(NULL);
- os->writeCompactLength(mem_os.length());
+ writeCompact(os, mem_os.length());
os->writeBytes(mem_os.data(), mem_os.length());
}
}
@@ -176,7 +99,7 @@ unsigned int PACK_PIXELS (PIXEL_T *buf, unsigned int count)
rdr::U8 *dst = (rdr::U8 *)buf;
for (unsigned int i = 0; i < count; i++) {
pix = *buf++;
- clientpf.rgbFromBuffer(dst, (rdr::U8*)&pix, 1, NULL);
+ clientpf.rgbFromBuffer(dst, (rdr::U8*)&pix, 1);
dst += 3;
}
return count * 3;
@@ -203,9 +126,10 @@ void TIGHT_ENCODE (const Rect& r, rdr::OutStream *os, bool forceSolid)
if (forceSolid) {
// Subrectangle has already been determined to be solid.
- palNumColors = 1;
ig->translatePixels(rawPixels, &solidColor, 1);
pixels = (PIXEL_T *)&solidColor;
+ palette.clear();
+ palette.insert(solidColor, 1);
} else {
// Analyze subrectangle's colors to determine best encoding method.
palMaxColors = r.area() / pconf->idxMaxColorsDivisor;
@@ -217,29 +141,29 @@ void TIGHT_ENCODE (const Rect& r, rdr::OutStream *os, bool forceSolid)
if (clientpf.equal(serverpf) && clientpf.bpp >= 16) {
// Count the colors in the raw buffer, so we can avoid unnecessary pixel
// translation when encoding with JPEG.
- if (grayScaleJPEG) palNumColors = 0;
+ if (grayScaleJPEG) palette.clear();
else FAST_FILL_PALETTE(rawPixels, stride, r);
// JPEG can read from the raw buffer, but for the other methods, we need
// to translate the raw pixels into an intermediate buffer.
- if(palNumColors != 0 || jpegQuality == -1) {
- pixels = (PIXEL_T *)writer->getImageBuf(r.area());
+ if(palette.size() != 0 || jpegQuality == -1) {
+ pixels = (PIXEL_T *)conn->writer()->getImageBuf(r.area());
stride = r.width();
ig->getImage(pixels, r);
}
} else {
// Pixel translation will be required, so create an intermediate buffer,
// translate the raw pixels into it, and count its colors.
- pixels = (PIXEL_T *)writer->getImageBuf(r.area());
+ pixels = (PIXEL_T *)conn->writer()->getImageBuf(r.area());
stride = r.width();
ig->getImage(pixels, r);
- if (grayScaleJPEG) palNumColors = 0;
+ if (grayScaleJPEG) palette.clear();
else FILL_PALETTE(pixels, r.area());
}
}
- switch (palNumColors) {
+ switch (palette.size()) {
case 0:
// Truecolor image
#if (BPP != 8)
@@ -297,7 +221,8 @@ void ENCODE_MONO_RECT (PIXEL_T *buf, const Rect& r, rdr::OutStream *os)
os->writeU8(0x01);
// Write the palette
- PIXEL_T pal[2] = { (PIXEL_T)monoBackground, (PIXEL_T)monoForeground };
+ PIXEL_T pal[2] = { (PIXEL_T)palette.getColour(0),
+ (PIXEL_T)palette.getColour(1) };
os->writeU8(1);
os->writeBytes(pal, PACK_PIXELS(pal, 2));
@@ -311,7 +236,7 @@ void ENCODE_MONO_RECT (PIXEL_T *buf, const Rect& r, rdr::OutStream *os)
int aligned_width;
int x, y, bg_bits;
- bg = (PIXEL_T) monoBackground;
+ bg = (PIXEL_T) pal[0];
aligned_width = w - w % 8;
for (y = 0; y < h; y++) {
@@ -365,10 +290,10 @@ void ENCODE_INDEXED_RECT (PIXEL_T *buf, const Rect& r, rdr::OutStream *os)
// Write the palette
{
PIXEL_T pal[256];
- for (int i = 0; i < palNumColors; i++)
- pal[i] = (PIXEL_T)palette.entry[i].listNode->rgb;
- os->writeU8((rdr::U8)(palNumColors - 1));
- os->writeBytes(pal, PACK_PIXELS(pal, palNumColors));
+ for (int i = 0; i < palette.size(); i++)
+ pal[i] = (PIXEL_T)palette.getColour(i);
+ os->writeU8((rdr::U8)(palette.size() - 1));
+ os->writeBytes(pal, PACK_PIXELS(pal, palette.size()));
}
// Encode data in-place
@@ -376,25 +301,19 @@ void ENCODE_INDEXED_RECT (PIXEL_T *buf, const Rect& r, rdr::OutStream *os)
rdr::U8 *dst = (rdr::U8 *)buf;
int count = r.area();
PIXEL_T rgb;
- TIGHT_COLOR_LIST *pnode;
int rep = 0;
+ unsigned char idx;
while (count--) {
rgb = *src++;
while (count && *src == rgb) {
rep++, src++, count--;
}
- pnode = palette.hash[HASH_FUNCTION(rgb)];
- while (pnode != NULL) {
- if ((PIXEL_T)pnode->rgb == rgb) {
- *dst++ = (rdr::U8)pnode->idx;
- while (rep) {
- *dst++ = (rdr::U8)pnode->idx;
- rep--;
- }
- break;
- }
- pnode = pnode->next;
+ idx = palette.lookup(rgb);
+ *dst++ = idx;
+ while (rep) {
+ *dst++ = idx;
+ rep--;
}
}
@@ -415,7 +334,7 @@ void ENCODE_JPEG_RECT (PIXEL_T *buf, int stride, const Rect& r,
jc.compress((rdr::U8 *)buf, stride, r, clientpf,
jpegQuality, jpegSubsampling);
os->writeU8(0x09 << 4);
- os->writeCompactLength(jc.length());
+ writeCompact(os, jc.length());
os->writeBytes(jc.data(), jc.length());
}
#endif // #if (BPP != 8)
@@ -431,12 +350,12 @@ void FILL_PALETTE (PIXEL_T *data, int count)
PIXEL_T c0, c1;
int i, n0, n1;
- palNumColors = 0;
+ palette.clear();
c0 = data[0];
for (i = 1; i < count && data[i] == c0; i++);
if (i == count) {
- palNumColors = 1;
+ palette.insert(c0, i);
return; // Solid rectangle
}
@@ -455,14 +374,8 @@ void FILL_PALETTE (PIXEL_T *data, int count)
break;
}
if (i == count) {
- if (n0 > n1) {
- monoBackground = (rdr::U32)c0;
- monoForeground = (rdr::U32)c1;
- } else {
- monoBackground = (rdr::U32)c1;
- monoForeground = (rdr::U32)c0;
- }
- palNumColors = 2; // Two colors
+ palette.insert(c0, n0); // Two colors
+ palette.insert(c1, n1);
}
}
@@ -477,17 +390,17 @@ void FILL_PALETTE (PIXEL_T *data, int count)
PIXEL_T c0, c1, ci = 0;
int i, n0, n1, ni;
+ palette.clear();
+
c0 = data[0];
for (i = 1; i < count && data[i] == c0; i++);
if (i >= count) {
- palNumColors = 1; // Solid rectangle
+ palette.insert(c0, i); // Solid rectangle
return;
}
- if (palMaxColors < 2) {
- palNumColors = 0; // Full-color format preferred
- return;
- }
+ if (palMaxColors < 2)
+ return; // Full-color format preferred
n0 = i;
c1 = data[i];
@@ -501,34 +414,26 @@ void FILL_PALETTE (PIXEL_T *data, int count)
} else
break;
}
- if (i >= count) {
- if (n0 > n1) {
- monoBackground = (rdr::U32)c0;
- monoForeground = (rdr::U32)c1;
- } else {
- monoBackground = (rdr::U32)c1;
- monoForeground = (rdr::U32)c0;
- }
- palNumColors = 2; // Two colors
- return;
- }
-
- paletteReset();
- paletteInsert (c0, (rdr::U32)n0, BPP);
- paletteInsert (c1, (rdr::U32)n1, BPP);
+ palette.insert(c0, n0);
+ palette.insert(c1, n1);
+ if (i >= count)
+ return; // Two colors
ni = 1;
for (i++; i < count; i++) {
if (data[i] == ci) {
ni++;
} else {
- if (!paletteInsert (ci, (rdr::U32)ni, BPP))
+ if (!palette.insert (ci, ni) || (palette.size() > palMaxColors)) {
+ palette.clear();
return;
+ }
ci = data[i];
ni = 1;
}
}
- paletteInsert (ci, (rdr::U32)ni, BPP);
+ if (!palette.insert (ci, ni) || (palette.size() > palMaxColors))
+ palette.clear();
}
void FAST_FILL_PALETTE (const PIXEL_T *data, int stride, const Rect& r)
@@ -542,6 +447,8 @@ void FAST_FILL_PALETTE (const PIXEL_T *data, int stride, const Rect& r)
serverpf.bufferFromPixel((rdr::U8*)&mask, ~0);
+ palette.clear();
+
c0 = data[0] & mask;
n0 = 0;
for (rowptr = data; rowptr < dataend; rowptr += stride) {
@@ -554,13 +461,11 @@ void FAST_FILL_PALETTE (const PIXEL_T *data, int stride, const Rect& r)
soliddone:
if (rowptr >= dataend) {
- palNumColors = 1; // Solid rectangle
- return;
- }
- if (palMaxColors < 2) {
- palNumColors = 0; // Full-color format preferred
+ palette.insert(c0, 1); // Solid rectangle
return;
}
+ if (palMaxColors < 2)
+ return; // Full-color format preferred
c1 = *colptr & mask;
n1 = 0;
@@ -592,21 +497,11 @@ void FAST_FILL_PALETTE (const PIXEL_T *data, int stride, const Rect& r)
c0t = c0; c1t = c1;
}
- if (colptr2 >= dataend) {
- if (n0 > n1) {
- monoBackground = (rdr::U32)c0t;
- monoForeground = (rdr::U32)c1t;
- } else {
- monoBackground = (rdr::U32)c1t;
- monoForeground = (rdr::U32)c0t;
- }
- palNumColors = 2; // Two colors
- return;
- }
+ palette.insert(c0t, n0);
+ palette.insert(c1t, n1);
- paletteReset();
- paletteInsert (c0t, (rdr::U32)n0, BPP);
- paletteInsert (c1t, (rdr::U32)n1, BPP);
+ if (colptr2 >= dataend)
+ return; // Two colors
ni = 1;
colptr2++;
@@ -623,8 +518,10 @@ void FAST_FILL_PALETTE (const PIXEL_T *data, int stride, const Rect& r)
ig->translatePixels(&ci, &cit, 1);
else
cit = ci;
- if (!paletteInsert (cit, (rdr::U32)ni, BPP))
+ if (!palette.insert (cit, ni) || (palette.size() > palMaxColors)) {
+ palette.clear();
return;
+ }
ci = (*colptr) & mask;
ni = 1;
}
@@ -633,7 +530,8 @@ void FAST_FILL_PALETTE (const PIXEL_T *data, int stride, const Rect& r)
colptr = rowptr;
}
ig->translatePixels(&ci, &cit, 1);
- paletteInsert (cit, (rdr::U32)ni, BPP);
+ if (!palette.insert (cit, ni) || (palette.size() > palMaxColors))
+ palette.clear();
}
#endif // #if (BPP == 8)
diff --git a/common/rfb/transInitTempl.h b/common/rfb/transInitTempl.h
index 464cfdfc..348f12b9 100644
--- a/common/rfb/transInitTempl.h
+++ b/common/rfb/transInitTempl.h
@@ -46,12 +46,8 @@ namespace rfb {
#define OUTPIXEL rdr::CONCAT2E(U,BPPOUT)
#define SWAPOUT CONCAT2E(SWAP,BPPOUT)
-#define initSimpleCMtoTCOUT CONCAT2E(initSimpleCMtoTC,BPPOUT)
-#define initSimpleTCtoTCOUT CONCAT2E(initSimpleTCtoTC,BPPOUT)
-#define initSimpleCMtoCubeOUT CONCAT2E(initSimpleCMtoCube,BPPOUT)
-#define initSimpleTCtoCubeOUT CONCAT2E(initSimpleTCtoCube,BPPOUT)
-#define initRGBTCtoTCOUT CONCAT2E(initRGBTCtoTC,BPPOUT)
-#define initRGBTCtoCubeOUT CONCAT2E(initRGBTCtoCube,BPPOUT)
+#define initSimpleOUT CONCAT2E(initSimple,BPPOUT)
+#define initRGBOUT CONCAT2E(initRGB,BPPOUT)
#define initOneRGBTableOUT CONCAT2E(initOneRGBTable,BPPOUT)
#define initOneRGBCubeTableOUT CONCAT2E(initOneRGBCubeTable,BPPOUT)
@@ -61,34 +57,8 @@ namespace rfb {
static bool nativeBigEndian = *(rdr::U8*)(&endianTest) != 1;
#endif
-void initSimpleCMtoTCOUT (rdr::U8** tablep, const PixelFormat& inPF,
- ColourMap* cm, const PixelFormat& outPF)
-{
- if (inPF.bpp != 8 && inPF.bigEndian != nativeBigEndian)
- throw Exception("Internal error: inPF is not native endian");
-
- int size = 1 << inPF.bpp;
-
- delete [] *tablep;
- *tablep = new rdr::U8[size * sizeof(OUTPIXEL)];
- OUTPIXEL* table = (OUTPIXEL*)*tablep;
-
- for (int i = 0; i < size; i++) {
- int r,g,b;
- cm->lookup(i,&r,&g,&b);
-
- table[i] = ((((r * outPF.redMax + 32767) / 65535) << outPF.redShift) |
- (((g * outPF.greenMax + 32767) / 65535) << outPF.greenShift) |
- (((b * outPF.blueMax + 32767) / 65535) << outPF.blueShift));
-#if (BPPOUT != 8)
- if (outPF.bigEndian != nativeBigEndian)
- table[i] = SWAPOUT (table[i]);
-#endif
- }
-}
-
-void initSimpleTCtoTCOUT (rdr::U8** tablep, const PixelFormat& inPF,
- const PixelFormat& outPF)
+void initSimpleOUT (rdr::U8** tablep, const PixelFormat& inPF,
+ const PixelFormat& outPF)
{
if (inPF.bpp != 8 && inPF.bigEndian != nativeBigEndian)
throw Exception("Internal error: inPF is not native endian");
@@ -118,55 +88,8 @@ void initSimpleTCtoTCOUT (rdr::U8** tablep, const PixelFormat& inPF,
}
}
-void initSimpleCMtoCubeOUT (rdr::U8** tablep, const PixelFormat& inPF,
- ColourMap* cm, ColourCube* cube)
-{
- if (inPF.bpp != 8 && inPF.bigEndian != nativeBigEndian)
- throw Exception("Internal error: inPF is not native endian");
-
- int size = 1 << inPF.bpp;
-
- delete [] *tablep;
- *tablep = new rdr::U8[size * sizeof(OUTPIXEL)];
- OUTPIXEL* table = (OUTPIXEL*)*tablep;
-
- for (int i = 0; i < size; i++) {
- int r,g,b;
- cm->lookup(i,&r,&g,&b);
- r = (r * (cube->nRed-1) + 32767) / 65535;
- g = (g * (cube->nGreen-1) + 32767) / 65535;
- b = (b * (cube->nBlue-1) + 32767) / 65535;
- table[i] = cube->lookup(r, g, b);
- }
-}
-
-void initSimpleTCtoCubeOUT (rdr::U8** tablep, const PixelFormat& inPF,
- ColourCube* cube)
-{
- if (inPF.bpp != 8 && inPF.bigEndian != nativeBigEndian)
- throw Exception("Internal error: inPF is not native endian");
-
- int size = 1 << inPF.bpp;
-
- delete [] *tablep;
- *tablep = new rdr::U8[size * sizeof(OUTPIXEL)];
- OUTPIXEL* table = (OUTPIXEL*)*tablep;
-
- for (int i = 0; i < size; i++) {
- int r = (i >> inPF.redShift) & inPF.redMax;
- int g = (i >> inPF.greenShift) & inPF.greenMax;
- int b = (i >> inPF.blueShift) & inPF.blueMax;
-
- r = (r * (cube->nRed-1) + inPF.redMax/2) / inPF.redMax;
- g = (g * (cube->nGreen-1) + inPF.greenMax/2) / inPF.greenMax;
- b = (b * (cube->nBlue-1) + inPF.blueMax/2) / inPF.blueMax;
-
- table[i] = cube->lookup(r, g, b);
- }
-}
-
-void initOneRGBTableOUT (OUTPIXEL* table, int inMax, int outMax,
- int outShift, bool swap)
+static void initOneRGBTableOUT (OUTPIXEL* table, int inMax, int outMax,
+ int outShift, bool swap)
{
int size = inMax + 1;
@@ -179,8 +102,8 @@ void initOneRGBTableOUT (OUTPIXEL* table, int inMax, int outMax,
}
}
-void initRGBTCtoTCOUT (rdr::U8** tablep, const PixelFormat& inPF,
- const PixelFormat& outPF)
+void initRGBOUT (rdr::U8** tablep, const PixelFormat& inPF,
+ const PixelFormat& outPF)
{
if (inPF.bpp != 8 && inPF.bigEndian != nativeBigEndian)
throw Exception("Internal error: inPF is not native endian");
@@ -205,50 +128,8 @@ void initRGBTCtoTCOUT (rdr::U8** tablep, const PixelFormat& inPF,
}
-void initOneRGBCubeTableOUT (OUTPIXEL* table, int inMax, int outMax,
- int outMult)
-{
- int size = inMax + 1;
-
- for (int i = 0; i < size; i++) {
- table[i] = ((i * outMax + inMax / 2) / inMax) * outMult;
- }
-}
-
-void initRGBTCtoCubeOUT (rdr::U8** tablep, const PixelFormat& inPF,
- ColourCube* cube)
-{
- if (inPF.bpp != 8 && inPF.bigEndian != nativeBigEndian)
- throw Exception("Internal error: inPF is not native endian");
-
- int size = inPF.redMax + inPF.greenMax + inPF.blueMax + 3 + cube->size();
-
- delete [] *tablep;
- *tablep = new rdr::U8[size * sizeof(OUTPIXEL)];
-
- OUTPIXEL* redTable = (OUTPIXEL*)*tablep;
- OUTPIXEL* greenTable = redTable + inPF.redMax + 1;
- OUTPIXEL* blueTable = greenTable + inPF.greenMax + 1;
- OUTPIXEL* cubeTable = blueTable + inPF.blueMax + 1;
-
- initOneRGBCubeTableOUT (redTable, inPF.redMax, cube->nRed-1,
- cube->redMult());
- initOneRGBCubeTableOUT (greenTable, inPF.greenMax, cube->nGreen-1,
- cube->greenMult());
- initOneRGBCubeTableOUT (blueTable, inPF.blueMax, cube->nBlue-1,
- cube->blueMult());
- for (int i = 0; i < cube->size(); i++) {
- cubeTable[i] = cube->table[i];
- }
-}
-
#undef OUTPIXEL
-#undef initSimpleCMtoTCOUT
-#undef initSimpleTCtoTCOUT
-#undef initSimpleCMtoCubeOUT
-#undef initSimpleTCtoCubeOUT
-#undef initRGBTCtoTCOUT
-#undef initRGBTCtoCubeOUT
+#undef initSimpleOUT
+#undef initRGBOUT
#undef initOneRGBTableOUT
-#undef initOneRGBCubeTableOUT
}
diff --git a/common/rfb/transTempl.h b/common/rfb/transTempl.h
index b133e869..49edb0ac 100644
--- a/common/rfb/transTempl.h
+++ b/common/rfb/transTempl.h
@@ -42,7 +42,6 @@
#define OUTPIXEL rdr::CONCAT2E(U,BPPOUT)
#define transSimpleINtoOUT CONCAT4E(transSimple,BPPIN,to,BPPOUT)
#define transRGBINtoOUT CONCAT4E(transRGB,BPPIN,to,BPPOUT)
-#define transRGBCubeINtoOUT CONCAT4E(transRGBCube,BPPIN,to,BPPOUT)
#if (BPPIN <= 16)
@@ -111,41 +110,9 @@ void transRGBINtoOUT (void* table,
}
}
-// transRGBCubeINtoOUT is similar to transRGBINtoOUT but also looks up the
-// colour cube index in a fourth table to yield a pixel value.
-
-void transRGBCubeINtoOUT (void* table,
- const PixelFormat& inPF, const void* inPtr, int inStride,
- const PixelFormat& outPF, void* outPtr,
- int outStride, int width, int height)
-{
- OUTPIXEL* redTable = (OUTPIXEL*)table;
- OUTPIXEL* greenTable = redTable + inPF.redMax + 1;
- OUTPIXEL* blueTable = greenTable + inPF.greenMax + 1;
- OUTPIXEL* cubeTable = blueTable + inPF.blueMax + 1;
- INPIXEL* ip = (INPIXEL*)inPtr;
- OUTPIXEL* op = (OUTPIXEL*)outPtr;
- int inExtra = inStride - width;
- int outExtra = outStride - width;
-
- while (height > 0) {
- OUTPIXEL* opEndOfRow = op + width;
- while (op < opEndOfRow) {
- *op++ = cubeTable[(redTable [(*ip >> inPF.redShift) & inPF.redMax] +
- greenTable[(*ip >> inPF.greenShift) & inPF.greenMax] +
- blueTable [(*ip >> inPF.blueShift) & inPF.blueMax])];
- ip++;
- }
- ip += inExtra;
- op += outExtra;
- height--;
- }
-}
-
#endif
#undef INPIXEL
#undef OUTPIXEL
#undef transSimpleINtoOUT
#undef transRGBINtoOUT
-#undef transRGBCubeINtoOUT
diff --git a/common/rfb/zrleDecode.h b/common/rfb/zrleDecode.h
index d26d4d3e..4bcbf1f0 100644
--- a/common/rfb/zrleDecode.h
+++ b/common/rfb/zrleDecode.h
@@ -19,11 +19,8 @@
//
// ZRLE decoding function.
//
-// This file is #included after having set the following macros:
+// This file is #included after having set the following macro:
// BPP - 8, 16 or 32
-// EXTRA_ARGS - optional extra arguments
-// FILL_RECT - fill a rectangle with a single colour
-// IMAGE_RECT - draw a rectangle of pixel data from a buffer
#include <stdio.h>
#include <rdr/InStream.h>
@@ -41,20 +38,17 @@ namespace rfb {
#ifdef CPIXEL
#define PIXEL_T rdr::CONCAT2E(U,BPP)
-#define READ_PIXEL CONCAT2E(readOpaque,CPIXEL)
+#define READ_PIXEL(is) CONCAT2E(readOpaque,CPIXEL)(is)
#define ZRLE_DECODE CONCAT2E(zrleDecode,CPIXEL)
#else
#define PIXEL_T rdr::CONCAT2E(U,BPP)
-#define READ_PIXEL CONCAT2E(readOpaque,BPP)
+#define READ_PIXEL(is) is->CONCAT2E(readOpaque,BPP)()
#define ZRLE_DECODE CONCAT2E(zrleDecode,BPP)
#endif
void ZRLE_DECODE (const Rect& r, rdr::InStream* is,
- rdr::ZlibInStream* zis, PIXEL_T* buf
-#ifdef EXTRA_ARGS
- , EXTRA_ARGS
-#endif
- )
+ rdr::ZlibInStream* zis, PIXEL_T* buf,
+ CMsgHandler* handler)
{
int length = is->readU32();
zis->setUnderlying(is, length);
@@ -74,12 +68,12 @@ void ZRLE_DECODE (const Rect& r, rdr::InStream* is,
PIXEL_T palette[128];
for (int i = 0; i < palSize; i++) {
- palette[i] = zis->READ_PIXEL();
+ palette[i] = READ_PIXEL(zis);
}
if (palSize == 1) {
PIXEL_T pix = palette[0];
- FILL_RECT(t,pix);
+ handler->fillRect(t, pix);
continue;
}
@@ -90,7 +84,7 @@ void ZRLE_DECODE (const Rect& r, rdr::InStream* is,
#ifdef CPIXEL
for (PIXEL_T* ptr = buf; ptr < buf+t.area(); ptr++) {
- *ptr = zis->READ_PIXEL();
+ *ptr = READ_PIXEL(zis);
}
#else
zis->readBytes(buf, t.area() * (BPP / 8));
@@ -130,7 +124,7 @@ void ZRLE_DECODE (const Rect& r, rdr::InStream* is,
PIXEL_T* ptr = buf;
PIXEL_T* end = ptr + t.area();
while (ptr < end) {
- PIXEL_T pix = zis->READ_PIXEL();
+ PIXEL_T pix = READ_PIXEL(zis);
int len = 1;
int b;
do {
@@ -179,7 +173,7 @@ void ZRLE_DECODE (const Rect& r, rdr::InStream* is,
//fprintf(stderr,"copying data to screen %dx%d at %d,%d\n",
//t.width(),t.height(),t.tl.x,t.tl.y);
- IMAGE_RECT(t,buf);
+ handler->imageRect(t, buf);
}
}
diff --git a/common/rfb/zrleEncode.h b/common/rfb/zrleEncode.h
index 0c622b88..8767d541 100644
--- a/common/rfb/zrleEncode.h
+++ b/common/rfb/zrleEncode.h
@@ -19,10 +19,8 @@
//
// zrleEncode.h - zrle encoding function.
//
-// This file is #included after having set the following macros:
+// This file is #included after having set the following macro:
// BPP - 8, 16 or 32
-// EXTRA_ARGS - optional extra arguments
-// GET_IMAGE_INTO_BUF - gets a rectangle of pixel data into a buffer
//
// Note that the buf argument to ZRLE_ENCODE needs to be at least one pixel
// bigger than the largest tile of pixel data, since the ZRLE encoding
@@ -31,6 +29,7 @@
#include <rdr/OutStream.h>
#include <rdr/ZlibOutStream.h>
+#include <rfb/Palette.h>
#include <assert.h>
namespace rfb {
@@ -44,13 +43,13 @@ namespace rfb {
#ifdef CPIXEL
#define PIXEL_T rdr::CONCAT2E(U,BPP)
-#define WRITE_PIXEL CONCAT2E(writeOpaque,CPIXEL)
+#define WRITE_PIXEL(os, u) CONCAT2E(writeOpaque,CPIXEL)(os, u)
#define ZRLE_ENCODE CONCAT2E(zrleEncode,CPIXEL)
#define ZRLE_ENCODE_TILE CONCAT2E(zrleEncodeTile,CPIXEL)
#define BPPOUT 24
#else
#define PIXEL_T rdr::CONCAT2E(U,BPP)
-#define WRITE_PIXEL CONCAT2E(writeOpaque,BPP)
+#define WRITE_PIXEL(os, u) os->CONCAT2E(writeOpaque,BPP)(u)
#define ZRLE_ENCODE CONCAT2E(zrleEncode,BPP)
#define ZRLE_ENCODE_TILE CONCAT2E(zrleEncodeTile,BPP)
#define BPPOUT BPP
@@ -61,65 +60,13 @@ namespace rfb {
static const int bitsPerPackedPixel[] = {
0, 1, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4
};
-
-// The PaletteHelper class helps us build up the palette from pixel data by
-// storing a reverse index using a simple hash-table
-
-class PaletteHelper {
-public:
- enum { MAX_SIZE = 127 };
-
- PaletteHelper()
- {
- memset(index, 255, sizeof(index));
- size = 0;
- }
-
- inline int hash(rdr::U32 pix)
- {
- return (pix ^ (pix >> 17)) & 4095;
- }
-
- inline void insert(rdr::U32 pix)
- {
- if (size < MAX_SIZE) {
- int i = hash(pix);
- while (index[i] != 255 && key[i] != pix)
- i++;
- if (index[i] != 255) return;
-
- index[i] = size;
- key[i] = pix;
- palette[size] = pix;
- }
- size++;
- }
-
- inline int lookup(rdr::U32 pix)
- {
- assert(size <= MAX_SIZE);
- int i = hash(pix);
- while (index[i] != 255 && key[i] != pix)
- i++;
- if (index[i] != 255) return index[i];
- return -1;
- }
-
- rdr::U32 palette[MAX_SIZE];
- rdr::U8 index[4096+MAX_SIZE];
- rdr::U32 key[4096+MAX_SIZE];
- int size;
-};
#endif
void ZRLE_ENCODE_TILE (PIXEL_T* data, int w, int h, rdr::OutStream* os);
-bool ZRLE_ENCODE (const Rect& r, rdr::OutStream* os,
- rdr::ZlibOutStream* zos, void* buf, Rect* actual
-#ifdef EXTRA_ARGS
- , EXTRA_ARGS
-#endif
- )
+void ZRLE_ENCODE (const Rect& r, rdr::OutStream* os,
+ rdr::ZlibOutStream* zos, void* buf,
+ TransImageGetter *ig)
{
zos->setUnderlying(os);
// RLE overhead is at worst 1 byte per 64x64 (4Kpixel) block
@@ -132,28 +79,17 @@ bool ZRLE_ENCODE (const Rect& r, rdr::OutStream* os,
t.br.y = __rfbmin(r.br.y, t.tl.y + 64);
- // enough for width 16384 32-bit pixels
- if (os->length() + worstCaseLine > 4097 * 1024) {
- if (t.tl.y == r.tl.y)
- throw Exception("ZRLE: not enough space for first line?");
- actual->tl = r.tl;
- actual->br.x = r.br.x;
- actual->br.y = t.tl.y;
- return false;
- }
-
for (t.tl.x = r.tl.x; t.tl.x < r.br.x; t.tl.x += 64) {
t.br.x = __rfbmin(r.br.x, t.tl.x + 64);
- GET_IMAGE_INTO_BUF(t,buf);
+ ig->getImage(buf, t);
ZRLE_ENCODE_TILE((PIXEL_T*)buf, t.width(), t.height(), zos);
}
zos->flush();
}
- return true;
}
@@ -161,7 +97,7 @@ void ZRLE_ENCODE_TILE (PIXEL_T* data, int w, int h, rdr::OutStream* os)
{
// First find the palette and the number of runs
- PaletteHelper ph;
+ Palette palette;
int runs = 0;
int singlePixels = 0;
@@ -178,7 +114,7 @@ void ZRLE_ENCODE_TILE (PIXEL_T* data, int w, int h, rdr::OutStream* os)
while (*++ptr == pix) ;
runs++;
}
- ph.insert(pix);
+ palette.insert(pix, 1);
}
//fprintf(stderr,"runs %d, single pixels %d, paletteSize %d\n",
@@ -186,9 +122,9 @@ void ZRLE_ENCODE_TILE (PIXEL_T* data, int w, int h, rdr::OutStream* os)
// Solid tile is a special case
- if (ph.size == 1) {
+ if (palette.size() == 1) {
os->writeU8(1);
- os->WRITE_PIXEL(ph.palette[0]);
+ WRITE_PIXEL(os, palette.getColour(0));
return;
}
@@ -209,8 +145,8 @@ void ZRLE_ENCODE_TILE (PIXEL_T* data, int w, int h, rdr::OutStream* os)
estimatedBytes = plainRleBytes;
}
- if (ph.size < 128) {
- int paletteRleBytes = (BPPOUT/8) * ph.size + 2 * runs + singlePixels;
+ if (palette.size() < 128) {
+ int paletteRleBytes = (BPPOUT/8) * palette.size() + 2 * runs + singlePixels;
if (paletteRleBytes < estimatedBytes) {
useRle = true;
@@ -218,9 +154,9 @@ void ZRLE_ENCODE_TILE (PIXEL_T* data, int w, int h, rdr::OutStream* os)
estimatedBytes = paletteRleBytes;
}
- if (ph.size < 17) {
- int packedBytes = ((BPPOUT/8) * ph.size +
- w * h * bitsPerPackedPixel[ph.size-1] / 8);
+ if (palette.size() < 17) {
+ int packedBytes = ((BPPOUT/8) * palette.size() +
+ w * h * bitsPerPackedPixel[palette.size()-1] / 8);
if (packedBytes < estimatedBytes) {
useRle = false;
@@ -230,12 +166,12 @@ void ZRLE_ENCODE_TILE (PIXEL_T* data, int w, int h, rdr::OutStream* os)
}
}
- if (!usePalette) ph.size = 0;
+ if (!usePalette) palette.clear();
- os->writeU8((useRle ? 128 : 0) | ph.size);
+ os->writeU8((useRle ? 128 : 0) | palette.size());
- for (int i = 0; i < ph.size; i++) {
- os->WRITE_PIXEL(ph.palette[i]);
+ for (int i = 0; i < palette.size(); i++) {
+ WRITE_PIXEL(os, palette.getColour(i));
}
if (useRle) {
@@ -251,17 +187,17 @@ void ZRLE_ENCODE_TILE (PIXEL_T* data, int w, int h, rdr::OutStream* os)
ptr++;
int len = ptr - runStart;
if (len <= 2 && usePalette) {
- int index = ph.lookup(pix);
+ int index = palette.lookup(pix);
if (len == 2)
os->writeU8(index);
os->writeU8(index);
continue;
}
if (usePalette) {
- int index = ph.lookup(pix);
+ int index = palette.lookup(pix);
os->writeU8(index | 128);
} else {
- os->WRITE_PIXEL(pix);
+ WRITE_PIXEL(os, pix);
}
len -= 1;
while (len >= 255) {
@@ -279,9 +215,9 @@ void ZRLE_ENCODE_TILE (PIXEL_T* data, int w, int h, rdr::OutStream* os)
// packed pixels
- assert (ph.size < 17);
+ assert (palette.size() < 17);
- int bppp = bitsPerPackedPixel[ph.size-1];
+ int bppp = bitsPerPackedPixel[palette.size()-1];
PIXEL_T* ptr = data;
@@ -293,7 +229,7 @@ void ZRLE_ENCODE_TILE (PIXEL_T* data, int w, int h, rdr::OutStream* os)
while (ptr < eol) {
PIXEL_T pix = *ptr++;
- rdr::U8 index = ph.lookup(pix);
+ rdr::U8 index = palette.lookup(pix);
byte = (byte << bppp) | index;
nbits += bppp;
if (nbits >= 8) {
@@ -312,7 +248,7 @@ void ZRLE_ENCODE_TILE (PIXEL_T* data, int w, int h, rdr::OutStream* os)
#ifdef CPIXEL
for (PIXEL_T* ptr = data; ptr < data+w*h; ptr++) {
- os->WRITE_PIXEL(*ptr);
+ WRITE_PIXEL(os, *ptr);
}
#else
os->writeBytes(data, w*h*(BPP/8));
diff --git a/tests/pixelconv.cxx b/tests/pixelconv.cxx
index ef9d3aac..1d19b88e 100644
--- a/tests/pixelconv.cxx
+++ b/tests/pixelconv.cxx
@@ -101,7 +101,7 @@ static void doTests(rfb::PixelFormat &dstpf, rfb::PixelFormat &srcpf)
if (srcpf.isLittleEndian()) {
delete pt;
pt = new rfb::PixelTransformer;
- pt->init(srcpf, NULL, dstpf);
+ pt->init(srcpf, dstpf);
}
printf("%s,%s", srcb, dstb);
diff --git a/unix/x0vncserver/XPixelBuffer.cxx b/unix/x0vncserver/XPixelBuffer.cxx
index aa52620a..f4641825 100644
--- a/unix/x0vncserver/XPixelBuffer.cxx
+++ b/unix/x0vncserver/XPixelBuffer.cxx
@@ -29,14 +29,13 @@
using namespace rfb;
XPixelBuffer::XPixelBuffer(Display *dpy, ImageFactory &factory,
- const Rect &rect, ColourMap* cm)
+ const Rect &rect)
: FullFramePixelBuffer(),
m_poller(0),
m_dpy(dpy),
m_image(factory.newImage(dpy, rect.width(), rect.height())),
m_offsetLeft(rect.tl.x),
- m_offsetTop(rect.tl.y),
- m_stride(0)
+ m_offsetTop(rect.tl.y)
{
// Fill in the PixelFormat structure of the parent class.
format = PixelFormat(m_image->xim->bits_per_pixel,
@@ -54,11 +53,10 @@ XPixelBuffer::XPixelBuffer(Display *dpy, ImageFactory &factory,
width_ = rect.width();
height_ = rect.height();
data = (rdr::U8 *)m_image->xim->data;
- colourmap = cm;
// Calculate the distance in pixels between two subsequent scan
// lines of the framebuffer. This may differ from image width.
- m_stride = m_image->xim->bytes_per_line * 8 / m_image->xim->bits_per_pixel;
+ stride = m_image->xim->bytes_per_line * 8 / m_image->xim->bits_per_pixel;
// Get initial screen image from the X display.
m_image->get(DefaultRootWindow(m_dpy), m_offsetLeft, m_offsetTop);
diff --git a/unix/x0vncserver/XPixelBuffer.h b/unix/x0vncserver/XPixelBuffer.h
index 29ae94a8..da031615 100644
--- a/unix/x0vncserver/XPixelBuffer.h
+++ b/unix/x0vncserver/XPixelBuffer.h
@@ -37,8 +37,7 @@ using namespace rfb;
class XPixelBuffer : public FullFramePixelBuffer
{
public:
- XPixelBuffer(Display *dpy, ImageFactory &factory,
- const Rect &rect, ColourMap* cm);
+ XPixelBuffer(Display *dpy, ImageFactory &factory, const Rect &rect);
virtual ~XPixelBuffer();
// Provide access to the underlying Image object.
@@ -47,9 +46,6 @@ public:
// Detect changed pixels, notify the server.
inline void poll(VNCServer *server) { m_poller->poll(server); }
- // Override PixelBuffer::getStride().
- virtual int getStride() const { return m_stride; }
-
// Override PixelBuffer::grabRegion().
virtual void grabRegion(const rfb::Region& region);
@@ -61,9 +57,6 @@ protected:
int m_offsetLeft;
int m_offsetTop;
- // The number of pixels in a row, with padding included.
- int m_stride;
-
// Copy pixels from the screen to the pixel buffer,
// for the specified rectangular area of the buffer.
inline void grabRect(const Rect &r) {
diff --git a/unix/x0vncserver/x0vncserver.cxx b/unix/x0vncserver/x0vncserver.cxx
index 165441fe..ee39fae1 100644
--- a/unix/x0vncserver/x0vncserver.cxx
+++ b/unix/x0vncserver/x0vncserver.cxx
@@ -135,7 +135,7 @@ private:
};
-class XDesktop : public SDesktop, public ColourMap, public TXGlobalEventHandler
+class XDesktop : public SDesktop, public TXGlobalEventHandler
{
public:
XDesktop(Display* dpy_, Geometry *geometry_)
@@ -199,7 +199,7 @@ public:
ImageFactory factory((bool)useShm, (bool)useOverlay);
// Create pixel buffer and provide it to the server object.
- pb = new XPixelBuffer(dpy, factory, geometry->getRect(), this);
+ pb = new XPixelBuffer(dpy, factory, geometry->getRect());
vlog.info("Allocated %s", pb->getImage()->classDesc());
server = (VNCServerST *)vs;
@@ -269,20 +269,6 @@ public:
return Point(pb->width(), pb->height());
}
- // -=- ColourMap callbacks
- virtual void lookup(int index, int* r, int* g, int* b) {
- XColor xc;
- xc.pixel = index;
- if (index < DisplayCells(dpy,DefaultScreen(dpy))) {
- XQueryColor(dpy, DefaultColormap(dpy,DefaultScreen(dpy)), &xc);
- } else {
- xc.red = xc.green = xc.blue = 0;
- }
- *r = xc.red;
- *g = xc.green;
- *b = xc.blue;
- }
-
// -=- TXGlobalEventHandler interface
virtual bool handleGlobalEvent(XEvent* ev) {
diff --git a/unix/xserver/hw/vnc/XserverDesktop.cc b/unix/xserver/hw/vnc/XserverDesktop.cc
index 8f426cce..e5cc3dc1 100644
--- a/unix/xserver/hw/vnc/XserverDesktop.cc
+++ b/unix/xserver/hw/vnc/XserverDesktop.cc
@@ -51,7 +51,6 @@ extern "C" {
extern char *display;
-#include "colormapst.h"
#ifdef RANDR
#include "randrstr.h"
#endif
@@ -143,14 +142,11 @@ XserverDesktop::XserverDesktop(ScreenPtr pScreen_,
: pScreen(pScreen_),
server(0), httpServer(0),
listener(listener_), httpListener(httpListener_),
- cmap(0), deferredUpdateTimerSet(false),
+ deferredUpdateTimerSet(false),
grabbing(false), ignoreHooks_(false), directFbptr(true),
queryConnectId(0)
{
format = pf;
- colourmap = this;
-
- serverReset(pScreen);
server = new VNCServerST(name, this);
setFramebuffer(pScreen->width, pScreen->height, fbptr, stride);
@@ -168,24 +164,6 @@ XserverDesktop::~XserverDesktop()
delete server;
}
-void XserverDesktop::serverReset(ScreenPtr pScreen_)
-{
- pScreen = pScreen_;
- int i;
- pointer retval;
-
-#if XORG >= 17
-#define dixLookupResource dixLookupResourceByType
-#endif
- i = dixLookupResource(&retval, pScreen->defColormap, RT_COLORMAP, NullClient,
- DixReadAccess);
-
- /* Handle suspicious conditions */
- assert(i == Success);
-
- cmap = (ColormapPtr) retval;
-}
-
void XserverDesktop::blockUpdates()
{
server->blockUpdates();
@@ -196,7 +174,7 @@ void XserverDesktop::unblockUpdates()
server->unblockUpdates();
}
-void XserverDesktop::setFramebuffer(int w, int h, void* fbptr, int stride)
+void XserverDesktop::setFramebuffer(int w, int h, void* fbptr, int stride_)
{
ScreenSet layout;
@@ -210,12 +188,12 @@ void XserverDesktop::setFramebuffer(int w, int h, void* fbptr, int stride)
if (!fbptr) {
fbptr = new rdr::U8[w * h * (format.bpp/8)];
- stride = w;
+ stride_ = w;
directFbptr = false;
}
data = (rdr::U8*)fbptr;
- stride_ = stride;
+ stride = stride_;
layout = computeScreenLayout();
@@ -376,44 +354,6 @@ XserverDesktop::queryConnection(network::Socket* sock,
return rfb::VNCServerST::PENDING;
}
-
-void XserverDesktop::setColormap(ColormapPtr cmap_)
-{
- if (cmap != cmap_) {
- cmap = cmap_;
- setColourMapEntries(0, 0);
- }
-}
-
-void XserverDesktop::setColourMapEntries(ColormapPtr pColormap, int ndef,
- xColorItem* pdef)
-{
- if (cmap != pColormap || ndef <= 0) return;
-
- unsigned int first = pdef[0].pixel;
- unsigned int n = 1;
-
- for (int i = 1; i < ndef; i++) {
- if (first + n == pdef[i].pixel) {
- n++;
- } else {
- setColourMapEntries(first, n);
- first = pdef[i].pixel;
- n = 1;
- }
- }
- setColourMapEntries(first, n);
-}
-
-void XserverDesktop::setColourMapEntries(int firstColour, int nColours)
-{
- try {
- server->setColourMapEntries(firstColour, nColours);
- } catch (rdr::Exception& e) {
- vlog.error("XserverDesktop::setColourMapEntries: %s",e.str());
- }
-}
-
void XserverDesktop::bell()
{
server->bell();
@@ -466,7 +406,7 @@ void XserverDesktop::setCursor(CursorPtr cursor)
rgb[1] = (*in >> 8) & 0xff;
rgb[2] = (*in >> 0) & 0xff;
- getPF().bufferFromRGB(out, rgb, 1, this);
+ getPF().bufferFromRGB(out, rgb, 1);
if (((*in >> 24) & 0xff) > 127)
cursorMask[y * rfbMaskBytesPerRow + x/8] |= 0x80>>(x%8);
@@ -477,42 +417,42 @@ void XserverDesktop::setCursor(CursorPtr cursor)
}
} else {
#endif
- xColorItem fg, bg;
- fg.red = cursor->foreRed;
- fg.green = cursor->foreGreen;
- fg.blue = cursor->foreBlue;
- FakeAllocColor(cmap, &fg);
- bg.red = cursor->backRed;
- bg.green = cursor->backGreen;
- bg.blue = cursor->backBlue;
- FakeAllocColor(cmap, &bg);
- FakeFreeColor(cmap, fg.pixel);
- FakeFreeColor(cmap, bg.pixel);
+ rdr::U8 rgb[3];
+ rdr::U8 fg[4], bg[4];
+
+ rdr::U8* buffer;
+
+ rgb[0] = cursor->foreRed;
+ rgb[1] = cursor->foreGreen;
+ rgb[2] = cursor->foreBlue;
+ getPF().bufferFromRGB(fg, rgb, 1);
+
+ rgb[0] = cursor->backRed;
+ rgb[1] = cursor->backGreen;
+ rgb[2] = cursor->backBlue;
+ getPF().bufferFromRGB(bg, rgb, 1);
int xMaskBytesPerRow = BitmapBytePad(w);
+ buffer = cursorData;
+
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
+ rdr::U8 *pixel;
int byte = y * xMaskBytesPerRow + x / 8;
#if (BITMAP_BIT_ORDER == MSBFirst)
int bit = 7 - x % 8;
#else
int bit = x % 8;
#endif
- switch (getPF().bpp) {
- case 8:
- ((rdr::U8*)cursorData)[y * w + x]
- = (cursor->bits->source[byte] & (1 << bit)) ? fg.pixel : bg.pixel;
- break;
- case 16:
- ((rdr::U16*)cursorData)[y * w + x]
- = (cursor->bits->source[byte] & (1 << bit)) ? fg.pixel : bg.pixel;
- break;
- case 32:
- ((rdr::U32*)cursorData)[y * w + x]
- = (cursor->bits->source[byte] & (1 << bit)) ? fg.pixel : bg.pixel;
- break;
- }
+
+ if (cursor->bits->source[byte] & (1 << bit))
+ pixel = fg;
+ else
+ pixel = bg;
+
+ memcpy(buffer, pixel, getPF().bpp/8);
+ buffer += getPF().bpp/8;
}
}
@@ -1105,33 +1045,6 @@ void XserverDesktop::grabRegion(const rfb::Region& region)
grabbing = false;
}
-int XserverDesktop::getStride() const
-{
- return stride_;
-}
-
-void XserverDesktop::lookup(int index, int* r, int* g, int* b)
-{
- if ((cmap->c_class | DynamicClass) == DirectColor) {
- VisualPtr v = cmap->pVisual;
- *r = cmap->red [(index & v->redMask ) >> v->offsetRed ].co.local.red;
- *g = cmap->green[(index & v->greenMask) >> v->offsetGreen].co.local.green;
- *b = cmap->blue [(index & v->blueMask ) >> v->offsetBlue ].co.local.blue;
- } else {
- EntryPtr pent;
- pent = (EntryPtr)&cmap->red[index];
- if (pent->fShared) {
- *r = pent->co.shco.red->color;
- *g = pent->co.shco.green->color;
- *b = pent->co.shco.blue->color;
- } else {
- *r = pent->co.local.red;
- *g = pent->co.local.green;
- *b = pent->co.local.blue;
- }
- }
-}
-
void XserverDesktop::keyEvent(rdr::U32 keysym, bool down)
{
if (down)
diff --git a/unix/xserver/hw/vnc/XserverDesktop.h b/unix/xserver/hw/vnc/XserverDesktop.h
index 20c89dc5..5b4c2300 100644
--- a/unix/xserver/hw/vnc/XserverDesktop.h
+++ b/unix/xserver/hw/vnc/XserverDesktop.h
@@ -54,7 +54,7 @@ namespace rfb {
namespace network { class TcpListener; class Socket; }
class XserverDesktop : public rfb::SDesktop, public rfb::FullFramePixelBuffer,
- public rfb::ColourMap, public rdr::Substitutor,
+ public rdr::Substitutor,
public rfb::VNCServerST::QueryConnectionHandler {
public:
@@ -65,13 +65,10 @@ public:
virtual ~XserverDesktop();
// methods called from X server code
- void serverReset(ScreenPtr pScreen);
void blockUpdates();
void unblockUpdates();
void setFramebuffer(int w, int h, void* fbptr, int stride);
void refreshScreenLayout();
- void setColormap(ColormapPtr cmap);
- void setColourMapEntries(ColormapPtr pColormap, int ndef, xColorItem* pdef);
void bell();
void serverCutText(const char* str, int len);
void setDesktopName(const char* name);
@@ -112,10 +109,6 @@ public:
// rfb::PixelBuffer callbacks
virtual void grabRegion(const rfb::Region& r);
- virtual int getStride() const;
-
- // rfb::ColourMap callbacks
- virtual void lookup(int index, int* r, int* g, int* b);
// rdr::Substitutor callback
virtual char* substitute(const char* varName);
@@ -126,7 +119,6 @@ public:
char** reason);
private:
- void setColourMapEntries(int firstColour, int nColours);
rfb::ScreenSet computeScreenLayout();
#ifdef RANDR
RRModePtr findRandRMode(RROutputPtr output, int width, int height);
@@ -137,8 +129,6 @@ private:
rfb::HTTPServer* httpServer;
network::TcpListener* listener;
network::TcpListener* httpListener;
- ColormapPtr cmap;
- int stride_;
bool deferredUpdateTimerSet;
bool grabbing;
bool ignoreHooks_;
diff --git a/unix/xserver/hw/vnc/vncExtInit.cc b/unix/xserver/hw/vnc/vncExtInit.cc
index a9fd0e9f..732fa69b 100644
--- a/unix/xserver/hw/vnc/vncExtInit.cc
+++ b/unix/xserver/hw/vnc/vncExtInit.cc
@@ -168,8 +168,10 @@ static PixelFormat vncGetPixelFormat(ScreenPtr pScreen)
trueColour = (vis->c_class == TrueColor);
- if (!trueColour && bpp != 8)
- throw rfb::Exception("X server uses unsupported visual");
+ if (!trueColour) {
+ fprintf(stderr,"pseudocolour not supported");
+ abort();
+ }
redShift = ffs(vis->redMask) - 1;
greenShift = ffs(vis->greenMask) - 1;
@@ -266,9 +268,6 @@ void vncExtensionInit()
desktop[scr]->addClient(sock, false);
vlog.info("added inetd sock");
}
-
- } else {
- desktop[scr]->serverReset(screenInfo.screens[scr]);
}
vncHooksInit(screenInfo.screens[scr], desktop[scr]);
diff --git a/unix/xserver/hw/vnc/vncHooks.cc b/unix/xserver/hw/vnc/vncHooks.cc
index 6756da7a..94693872 100644
--- a/unix/xserver/hw/vnc/vncHooks.cc
+++ b/unix/xserver/hw/vnc/vncHooks.cc
@@ -75,8 +75,6 @@ typedef struct {
#if XORG < 110
RestoreAreasProcPtr RestoreAreas;
#endif
- InstallColormapProcPtr InstallColormap;
- StoreColorsProcPtr StoreColors;
DisplayCursorProcPtr DisplayCursor;
ScreenBlockHandlerProcPtr BlockHandler;
#ifdef RENDER
@@ -132,9 +130,6 @@ static void vncHooksClearToBackground(WindowPtr pWin, int x, int y, int w,
#if XORG < 110
static RegionPtr vncHooksRestoreAreas(WindowPtr pWin, RegionPtr prgnExposed);
#endif
-static void vncHooksInstallColormap(ColormapPtr pColormap);
-static void vncHooksStoreColors(ColormapPtr pColormap, int ndef,
- xColorItem* pdef);
static Bool vncHooksDisplayCursor(
#if XORG >= 16
DeviceIntPtr pDev,
@@ -289,8 +284,6 @@ Bool vncHooksInit(ScreenPtr pScreen, XserverDesktop* desktop)
#if XORG < 110
vncHooksScreen->RestoreAreas = pScreen->RestoreAreas;
#endif
- vncHooksScreen->InstallColormap = pScreen->InstallColormap;
- vncHooksScreen->StoreColors = pScreen->StoreColors;
vncHooksScreen->DisplayCursor = pScreen->DisplayCursor;
vncHooksScreen->BlockHandler = pScreen->BlockHandler;
#ifdef RENDER
@@ -318,8 +311,6 @@ Bool vncHooksInit(ScreenPtr pScreen, XserverDesktop* desktop)
#if XORG < 110
pScreen->RestoreAreas = vncHooksRestoreAreas;
#endif
- pScreen->InstallColormap = vncHooksInstallColormap;
- pScreen->StoreColors = vncHooksStoreColors;
pScreen->DisplayCursor = vncHooksDisplayCursor;
pScreen->BlockHandler = vncHooksBlockHandler;
#ifdef RENDER
@@ -381,8 +372,6 @@ static Bool vncHooksCloseScreen(ScreenPtr pScreen_)
#if XORG < 110
pScreen->RestoreAreas = vncHooksScreen->RestoreAreas;
#endif
- pScreen->InstallColormap = vncHooksScreen->InstallColormap;
- pScreen->StoreColors = vncHooksScreen->StoreColors;
pScreen->DisplayCursor = vncHooksScreen->DisplayCursor;
pScreen->BlockHandler = vncHooksScreen->BlockHandler;
#ifdef RENDER
@@ -512,33 +501,6 @@ static RegionPtr vncHooksRestoreAreas(WindowPtr pWin, RegionPtr pRegion)
}
#endif
-// InstallColormap - get the new colormap
-
-static void vncHooksInstallColormap(ColormapPtr pColormap)
-{
- SCREEN_UNWRAP(pColormap->pScreen, InstallColormap);
-
- (*pScreen->InstallColormap) (pColormap);
-
- vncHooksScreen->desktop->setColormap(pColormap);
-
- SCREEN_REWRAP(InstallColormap);
-}
-
-// StoreColors - get the colormap changes
-
-static void vncHooksStoreColors(ColormapPtr pColormap, int ndef,
- xColorItem* pdef)
-{
- SCREEN_UNWRAP(pColormap->pScreen, StoreColors);
-
- (*pScreen->StoreColors) (pColormap, ndef, pdef);
-
- vncHooksScreen->desktop->setColourMapEntries(pColormap, ndef, pdef);
-
- SCREEN_REWRAP(StoreColors);
-}
-
// DisplayCursor - get the cursor shape
static Bool vncHooksDisplayCursor(
diff --git a/vncviewer/CConn.cxx b/vncviewer/CConn.cxx
index 789cf09e..db1a08a5 100644
--- a/vncviewer/CConn.cxx
+++ b/vncviewer/CConn.cxx
@@ -1,6 +1,6 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
- * Copyright 2009-2011 Pierre Ossman <ossman@cendio.se> for Cendio AB
* Copyright (C) 2011 D. R. Commander. All Rights Reserved.
+ * Copyright 2009-2014 Pierre Ossman for Cendio AB
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -29,6 +29,7 @@
#include <rfb/CMsgWriter.h>
#include <rfb/encodings.h>
+#include <rfb/Decoder.h>
#include <rfb/Hostname.h>
#include <rfb/LogWriter.h>
#include <rfb/util.h>
@@ -65,8 +66,9 @@ static const PixelFormat verylowColourPF(8, 3,false, true,
// 64 colours (2 bits per component)
static const PixelFormat lowColourPF(8, 6, false, true,
3, 3, 3, 4, 2, 0);
-// 256 colours (palette)
-static const PixelFormat mediumColourPF(8, 8, false, false);
+// 256 colours (2-3 bits per component)
+static const PixelFormat mediumColourPF(8, 8, false, true,
+ 7, 7, 3, 5, 2, 0);
CConn::CConn(const char* vncServerName, network::Socket* socket=NULL)
: serverHost(0), serverPort(0), desktop(NULL),
@@ -79,6 +81,8 @@ CConn::CConn(const char* vncServerName, network::Socket* socket=NULL)
setShared(::shared);
sock = socket;
+ memset(decoders, 0, sizeof(decoders));
+
int encNum = encodingNum(preferredEncoding);
if (encNum != -1)
currentEncoding = encNum;
@@ -130,6 +134,9 @@ CConn::~CConn()
{
OptionsDialog::removeCallback(handleOptions);
+ for (int i = 0; i < sizeof(decoders)/sizeof(decoders[0]); i++)
+ delete decoders[i];
+
if (desktop)
delete desktop;
@@ -342,7 +349,7 @@ void CConn::framebufferUpdateEnd()
void CConn::setColourMapEntries(int firstColour, int nColours, rdr::U16* rgbs)
{
- desktop->setColourMapEntries(firstColour, nColours, rgbs);
+ vlog.error("Invalid SetColourMapEntries from server!");
}
void CConn::bell()
@@ -379,19 +386,27 @@ void CConn::serverCutText(const char* str, rdr::U32 len)
delete [] buffer;
}
-// We start timing on beginRect and stop timing on endRect, to
-// avoid skewing the bandwidth estimation as a result of the server
-// being slow or the network having high latency
-void CConn::beginRect(const Rect& r, int encoding)
+void CConn::dataRect(const Rect& r, int encoding)
{
sock->inStream().startTiming();
- if (encoding != encodingCopyRect) {
+
+ if (encoding != encodingCopyRect)
lastServerEncoding = encoding;
+
+ if (!Decoder::supported(encoding)) {
+ fprintf(stderr, "Unknown rect encoding %d\n", encoding);
+ throw Exception("Unknown rect encoding");
}
-}
-void CConn::endRect(const Rect& r, int encoding)
-{
+ if (!decoders[encoding]) {
+ decoders[encoding] = Decoder::createDecoder(encoding, this);
+ if (!decoders[encoding]) {
+ fprintf(stderr, "Unknown rect encoding %d\n", encoding);
+ throw Exception("Unknown rect encoding");
+ }
+ }
+ decoders[encoding]->readRect(r, this);
+
sock->inStream().stopTiming();
}
diff --git a/vncviewer/CConn.h b/vncviewer/CConn.h
index 286a09ed..f7f560bc 100644
--- a/vncviewer/CConn.h
+++ b/vncviewer/CConn.h
@@ -1,5 +1,5 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
- * Copyright 2009-2011 Pierre Ossman <ossman@cendio.se> for Cendio AB
+ * Copyright 2009-2014 Pierre Ossman for Cendio AB
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -23,8 +23,11 @@
#include <FL/Fl.H>
#include <rfb/CConnection.h>
+#include <rfb/encodings.h>
#include <network/Socket.h>
+namespace rfb { class Decoder; }
+
class DesktopWindow;
class CConn : public rfb::CConnection,
@@ -62,8 +65,7 @@ public:
void framebufferUpdateStart();
void framebufferUpdateEnd();
- void beginRect(const rfb::Rect& r, int encoding);
- void endRect(const rfb::Rect& r, int encoding);
+ void dataRect(const rfb::Rect& r, int encoding);
void fillRect(const rfb::Rect& r, rfb::Pixel p);
void imageRect(const rfb::Rect& r, void* p);
@@ -102,6 +104,8 @@ private:
bool pendingPFChange;
rfb::PixelFormat pendingPF;
+ rfb::Decoder *decoders[rfb::encodingMax+1];
+
int currentEncoding, lastServerEncoding;
bool formatChange;
diff --git a/vncviewer/CMakeLists.txt b/vncviewer/CMakeLists.txt
index c1facc67..9b815a39 100644
--- a/vncviewer/CMakeLists.txt
+++ b/vncviewer/CMakeLists.txt
@@ -7,9 +7,11 @@ set(VNCVIEWER_SOURCES
menukey.cxx
CConn.cxx
DesktopWindow.cxx
+ FLTKPixelBuffer.cxx
UserDialog.cxx
ServerDialog.cxx
OptionsDialog.cxx
+ PlatformPixelBuffer.cxx
Viewport.cxx
parameters.cxx
keysym2ucs.c
diff --git a/vncviewer/DesktopWindow.cxx b/vncviewer/DesktopWindow.cxx
index 2a2f8734..3e9b57e6 100644
--- a/vncviewer/DesktopWindow.cxx
+++ b/vncviewer/DesktopWindow.cxx
@@ -216,12 +216,6 @@ void DesktopWindow::setName(const char *name)
}
-void DesktopWindow::setColourMapEntries(int firstColour, int nColours,
- rdr::U16* rgbs)
-{
- viewport->setColourMapEntries(firstColour, nColours, rgbs);
-}
-
void DesktopWindow::fillRect(const rfb::Rect& r, rfb::Pixel pix) {
viewport->fillRect(r, pix);
}
diff --git a/vncviewer/DesktopWindow.h b/vncviewer/DesktopWindow.h
index 06f25f55..08a66522 100644
--- a/vncviewer/DesktopWindow.h
+++ b/vncviewer/DesktopWindow.h
@@ -50,8 +50,6 @@ public:
// Methods forwarded from CConn
void setName(const char *name);
- void setColourMapEntries(int firstColour, int nColours, rdr::U16* rgbs);
-
void fillRect(const rfb::Rect& r, rfb::Pixel pix);
void imageRect(const rfb::Rect& r, void* pixels);
void copyRect(const rfb::Rect& r, int srcX, int srcY);
diff --git a/vncviewer/FLTKPixelBuffer.cxx b/vncviewer/FLTKPixelBuffer.cxx
new file mode 100644
index 00000000..588e2f83
--- /dev/null
+++ b/vncviewer/FLTKPixelBuffer.cxx
@@ -0,0 +1,52 @@
+/* Copyright 2011-2014 Pierre Ossman for Cendio AB
+ *
+ * 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.
+ */
+
+#include <FL/fl_draw.H>
+
+#include <rfb/Exception.h>
+
+#include "FLTKPixelBuffer.h"
+
+FLTKPixelBuffer::FLTKPixelBuffer(int width, int height) :
+ PlatformPixelBuffer(rfb::PixelFormat(32, 24, false, true,
+ 255, 255, 255, 0, 8, 16),
+ width, height, NULL, width)
+{
+ data = new rdr::U8[width * height * format.bpp/8];
+ if (data == NULL)
+ throw rfb::Exception("Error: Not enough memory for framebuffer");
+}
+
+FLTKPixelBuffer::~FLTKPixelBuffer()
+{
+ delete [] data;
+}
+
+void FLTKPixelBuffer::draw(int src_x, int src_y, int x, int y, int w, int h)
+{
+ int pixel_bytes, stride_bytes;
+ const uchar *buf_start;
+
+ pixel_bytes = format.bpp/8;
+ stride_bytes = pixel_bytes * stride;
+ buf_start = data +
+ pixel_bytes * src_x +
+ stride_bytes * src_y;
+
+ fl_draw_image(buf_start, x, y, w, h, pixel_bytes, stride_bytes);
+}
diff --git a/common/rfb/TrueColourMap.h b/vncviewer/FLTKPixelBuffer.h
index d79647e3..148c6264 100644
--- a/common/rfb/TrueColourMap.h
+++ b/vncviewer/FLTKPixelBuffer.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
+/* Copyright 2011-2014 Pierre Ossman for Cendio AB
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,27 +15,19 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
-#ifndef __RFB_TRUECOLOURMAP_H__
-#define __RFB_TRUECOLOURMAP_H__
-#include <rfb/ColourMap.h>
+#ifndef __FLTKPIXELBUFFER_H__
+#define __FLTKPIXELBUFFER_H__
-namespace rfb {
+#include "PlatformPixelBuffer.h"
+
+class FLTKPixelBuffer: public PlatformPixelBuffer {
+public:
+ FLTKPixelBuffer(int width, int height);
+ ~FLTKPixelBuffer();
+
+ virtual void draw(int src_x, int src_y, int x, int y, int w, int h);
+};
- class TrueColourMap : public ColourMap {
- public:
- TrueColourMap(const PixelFormat& pf_) : pf(pf_) {}
- virtual void lookup(int i, int* r, int* g, int* b)
- {
- rdr::U16 _r, _g, _b;
- pf.rgbFromPixel(i, NULL, &_r, &_g, &_b);
- *r = _r;
- *g = _g;
- *b = _b;
- }
- private:
- PixelFormat pf;
- };
-}
#endif
diff --git a/vncviewer/OSXPixelBuffer.cxx b/vncviewer/OSXPixelBuffer.cxx
index 0e03fc98..d196497f 100644
--- a/vncviewer/OSXPixelBuffer.cxx
+++ b/vncviewer/OSXPixelBuffer.cxx
@@ -1,4 +1,4 @@
-/* Copyright 2011 Pierre Ossman <ossman@cendio.se> for Cendio AB
+/* Copyright 2011-2014 Pierre Ossman for Cendio AB
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -34,16 +34,20 @@
using namespace rfb;
-static rfb::LogWriter vlog("PlatformPixelBuffer");
+static rfb::LogWriter vlog("OSXPixelBuffer");
-PlatformPixelBuffer::PlatformPixelBuffer(int width, int height) :
- ManagedPixelBuffer(rfb::PixelFormat(32, 24, false, true,
- 255, 255, 255, 16, 8, 0),
- width, height),
+OSXPixelBuffer::OSXPixelBuffer(int width, int height) :
+ PlatformPixelBuffer(rfb::PixelFormat(32, 24, false, true,
+ 255, 255, 255, 16, 8, 0),
+ width, height, NULL, width),
bitmap(NULL)
{
CGColorSpaceRef lut;
+ data = new rdr::U8[width * height * format.bpp/8];
+ if (data == NULL)
+ throw rfb::Exception("Error: Not enough memory for framebuffer");
+
lut = CGColorSpaceCreateDeviceRGB();
assert(lut);
@@ -55,13 +59,14 @@ PlatformPixelBuffer::PlatformPixelBuffer(int width, int height) :
}
-PlatformPixelBuffer::~PlatformPixelBuffer()
+OSXPixelBuffer::~OSXPixelBuffer()
{
CFRelease((CGContextRef)bitmap);
+ delete [] data;
}
-void PlatformPixelBuffer::draw(int src_x, int src_y, int x, int y, int w, int h)
+void OSXPixelBuffer::draw(int src_x, int src_y, int x, int y, int w, int h)
{
CGRect rect;
CGContextRef gc;
diff --git a/vncviewer/OSXPixelBuffer.h b/vncviewer/OSXPixelBuffer.h
index e59015e5..8ae01848 100644
--- a/vncviewer/OSXPixelBuffer.h
+++ b/vncviewer/OSXPixelBuffer.h
@@ -1,4 +1,4 @@
-/* Copyright 2011 Pierre Ossman <ossman@cendio.se> for Cendio AB
+/* Copyright 2011-2014 Pierre Ossman for Cendio AB
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -19,14 +19,14 @@
#ifndef __OSXPIXELBUFFER_H__
#define __OSXPIXELBUFFER_H__
-#include <rfb/PixelBuffer.h>
+#include "PlatformPixelBuffer.h"
-class PlatformPixelBuffer: public rfb::ManagedPixelBuffer {
+class OSXPixelBuffer: public PlatformPixelBuffer {
public:
- PlatformPixelBuffer(int width, int height);
- ~PlatformPixelBuffer();
+ OSXPixelBuffer(int width, int height);
+ ~OSXPixelBuffer();
- void draw(int src_x, int src_y, int x, int y, int w, int h);
+ virtual void draw(int src_x, int src_y, int x, int y, int w, int h);
protected:
// This is really a CGContextRef, but Apple headers conflict with FLTK
diff --git a/common/rfb/CMsgReaderV3.h b/vncviewer/PlatformPixelBuffer.cxx
index bff70ef4..ced04467 100644
--- a/common/rfb/CMsgReaderV3.h
+++ b/vncviewer/PlatformPixelBuffer.cxx
@@ -1,5 +1,4 @@
-/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
- * Copyright 2009-2011 Pierre Ossman for Cendio AB
+/* Copyright 2011-2014 Pierre Ossman for Cendio AB
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -16,25 +15,12 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
-#ifndef __RFB_CMSGREADERV3_H__
-#define __RFB_CMSGREADERV3_H__
-#include <rfb/CMsgReader.h>
+#include "PlatformPixelBuffer.h"
-namespace rfb {
- class CMsgReaderV3 : public CMsgReader {
- public:
- CMsgReaderV3(CMsgHandler* handler, rdr::InStream* is);
- virtual ~CMsgReaderV3();
- virtual void readServerInit();
- virtual void readMsg();
- private:
- virtual void readFramebufferUpdate();
- virtual void readSetDesktopName(int x, int y, int w, int h);
- virtual void readExtendedDesktopSize(int x, int y, int w, int h);
- virtual void readFence();
- virtual void readEndOfContinuousUpdates();
- int nUpdateRectsLeft;
- };
+PlatformPixelBuffer::PlatformPixelBuffer(const rfb::PixelFormat& pf,
+ int width, int height,
+ rdr::U8* data, int stride) :
+ FullFramePixelBuffer(pf, width, height, data, stride)
+{
}
-#endif
diff --git a/vncviewer/PlatformPixelBuffer.h b/vncviewer/PlatformPixelBuffer.h
index f634ccd4..03842ac8 100644
--- a/vncviewer/PlatformPixelBuffer.h
+++ b/vncviewer/PlatformPixelBuffer.h
@@ -1,4 +1,4 @@
-/* Copyright 2011 Pierre Ossman <ossman@cendio.se> for Cendio AB
+/* Copyright 2011-2014 Pierre Ossman for Cendio AB
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -21,31 +21,13 @@
#include <rfb/PixelBuffer.h>
-#include <FL/fl_draw.H>
-
-class PlatformPixelBuffer: public rfb::ManagedPixelBuffer {
+class PlatformPixelBuffer: public rfb::FullFramePixelBuffer {
public:
- PlatformPixelBuffer(int width, int height) :
- rfb::ManagedPixelBuffer(rfb::PixelFormat(32, 24, false, true,
- 255, 255, 255, 0, 8, 16),
- width, height)
- {};
-
- inline void draw(int src_x, int src_y, int x, int y, int w, int h);
-};
+ PlatformPixelBuffer(const rfb::PixelFormat& pf, int width, int height,
+ rdr::U8* data, int stride);
-inline void PlatformPixelBuffer::draw(int src_x, int src_y, int x, int y, int w, int h)
-{
- int pixel_bytes, stride_bytes;
- const uchar *buf_start;
+ virtual void draw(int src_x, int src_y, int x, int y, int w, int h) = 0;
- pixel_bytes = getPF().bpp/8;
- stride_bytes = pixel_bytes * getStride();
- buf_start = data +
- pixel_bytes * src_x +
- stride_bytes * src_y;
-
- fl_draw_image(buf_start, x, y, w, h, pixel_bytes, stride_bytes);
-}
+};
#endif
diff --git a/vncviewer/Viewport.cxx b/vncviewer/Viewport.cxx
index 0ac76024..d1d51622 100644
--- a/vncviewer/Viewport.cxx
+++ b/vncviewer/Viewport.cxx
@@ -1,5 +1,5 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
- * Copyright 2011 Pierre Ossman <ossman@cendio.se> for Cendio AB
+ * Copyright 2011-2014 Pierre Ossman for Cendio AB
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -51,6 +51,9 @@
#include "menukey.h"
#include "vncviewer.h"
+#include "PlatformPixelBuffer.h"
+#include "FLTKPixelBuffer.h"
+
#if defined(WIN32)
#include "Win32PixelBuffer.h"
#elif defined(__APPLE__)
@@ -59,11 +62,6 @@
#include "X11PixelBuffer.h"
#endif
-// We also have a generic version of the above, using pure FLTK:
-//
-// #include "PlatformPixelBuffer.h"
-//
-
#include <FL/fl_draw.H>
#include <FL/fl_ask.H>
@@ -87,7 +85,7 @@ enum { ID_EXIT, ID_FULLSCREEN, ID_RESIZE,
Viewport::Viewport(int w, int h, const rfb::PixelFormat& serverPF, CConn* cc_)
: Fl_Widget(0, 0, w, h), cc(cc_), frameBuffer(NULL), pixelTrans(NULL),
- colourMapChange(false), lastPointerPos(0, 0), lastButtonMask(0),
+ lastPointerPos(0, 0), lastButtonMask(0),
cursor(NULL), menuCtrlKey(false), menuAltKey(false)
{
// FLTK STR #2599 must be fixed for proper dead keys support
@@ -100,7 +98,7 @@ Viewport::Viewport(int w, int h, const rfb::PixelFormat& serverPF, CConn* cc_)
Fl::add_clipboard_notify(handleClipboardChange, this);
#endif
- frameBuffer = new PlatformPixelBuffer(w, h);
+ frameBuffer = createFramebuffer(w, h);
assert(frameBuffer);
setServerPF(serverPF);
@@ -183,11 +181,11 @@ void Viewport::setServerPF(const rfb::PixelFormat& pf)
PixelFormat fake_pf(pf.bpp, pf.depth, nativeBigEndian, pf.trueColour,
pf.redMax, pf.greenMax, pf.blueMax,
pf.redShift, pf.greenShift, pf.blueShift);
- pixelTrans->init(fake_pf, &colourMap, getPreferredPF());
+ pixelTrans->init(fake_pf, getPreferredPF());
return;
}
- pixelTrans->init(pf, &colourMap, getPreferredPF());
+ pixelTrans->init(pf, getPreferredPF());
}
@@ -197,21 +195,6 @@ const rfb::PixelFormat &Viewport::getPreferredPF()
}
-// setColourMapEntries() changes some of the entries in the colourmap.
-// We don't actually act on these changes until we need to. This is
-// because recalculating the internal translation table can be expensive.
-// This also solves the issue of silly servers sending colour maps in
-// multiple pieces.
-void Viewport::setColourMapEntries(int firstColour, int nColours,
- rdr::U16* rgbs)
-{
- for (int i = 0; i < nColours; i++)
- colourMap.set(firstColour+i, rgbs[i*3], rgbs[i*3+1], rgbs[i*3+2]);
-
- colourMapChange = true;
-}
-
-
// Copy the areas of the framebuffer that have been changed (damaged)
// to the displayed window.
@@ -230,8 +213,6 @@ void Viewport::updateWindow()
void Viewport::fillRect(const rfb::Rect& r, rfb::Pixel pix) {
if (pixelTrans) {
rfb::Pixel pix2;
- if (colourMapChange)
- commitColourMap();
pixelTrans->translatePixels(&pix, &pix2, 1);
pix = pix2;
}
@@ -242,12 +223,12 @@ void Viewport::fillRect(const rfb::Rect& r, rfb::Pixel pix) {
void Viewport::imageRect(const rfb::Rect& r, void* pixels) {
if (pixelTrans) {
- if (colourMapChange)
- commitColourMap();
+ rdr::U8* buffer;
+ int stride;
+ buffer = frameBuffer->getBufferRW(r, &stride);
pixelTrans->translateRect(pixels, r.width(),
rfb::Rect(0, 0, r.width(), r.height()),
- frameBuffer->data, frameBuffer->getStride(),
- r.tl);
+ buffer, stride, rfb::Point(0, 0));
} else {
frameBuffer->imageRect(r, pixels);
}
@@ -327,7 +308,7 @@ void Viewport::setCursor(int width, int height, const Point& hotspot,
m_width = (width+7)/8;
for (int y = 0;y < height;y++) {
for (int x = 0;x < width;x++) {
- pf->rgbFromBuffer(o, i, 1, &colourMap);
+ pf->rgbFromBuffer(o, i, 1);
if (m[(m_width*y)+(x/8)] & 0x80>>(x%8))
o[3] = 255;
@@ -369,6 +350,9 @@ void Viewport::resize(int x, int y, int w, int h)
PlatformPixelBuffer* newBuffer;
rfb::Rect rect;
+ const rdr::U8* data;
+ int stride;
+
// FIXME: Resize should probably be a feature of the pixel buffer itself
if ((w == frameBuffer->width()) && (h == frameBuffer->height()))
@@ -377,13 +361,14 @@ void Viewport::resize(int x, int y, int w, int h)
vlog.debug("Resizing framebuffer from %dx%d to %dx%d",
frameBuffer->width(), frameBuffer->height(), w, h);
- newBuffer = new PlatformPixelBuffer(w, h);
+ newBuffer = createFramebuffer(w, h);
assert(newBuffer);
rect.setXYWH(0, 0,
__rfbmin(newBuffer->width(), frameBuffer->width()),
__rfbmin(newBuffer->height(), frameBuffer->height()));
- newBuffer->imageRect(rect, frameBuffer->data, frameBuffer->getStride());
+ data = frameBuffer->getBuffer(frameBuffer->getRect(), &stride);
+ newBuffer->imageRect(rect, data, stride);
// Black out any new areas
@@ -519,26 +504,33 @@ int Viewport::handle(int event)
}
-void Viewport::handleUpdateTimeout(void *data)
+PlatformPixelBuffer* Viewport::createFramebuffer(int w, int h)
{
- Viewport *self = (Viewport *)data;
+ PlatformPixelBuffer *fb;
- assert(self);
+ try {
+#if defined(WIN32)
+ fb = new Win32PixelBuffer(w, h);
+#elif defined(__APPLE__)
+ fb = new OSXPixelBuffer(w, h);
+#else
+ fb = new X11PixelBuffer(w, h);
+#endif
+ } catch (rdr::Exception& e) {
+ fb = new FLTKPixelBuffer(w, h);
+ }
- self->updateWindow();
+ return fb;
}
-void Viewport::commitColourMap()
+void Viewport::handleUpdateTimeout(void *data)
{
- if (pixelTrans == NULL)
- return;
- if (!colourMapChange)
- return;
+ Viewport *self = (Viewport *)data;
- colourMapChange = false;
+ assert(self);
- pixelTrans->setColourMapEntries(0, 0);
+ self->updateWindow();
}
diff --git a/vncviewer/Viewport.h b/vncviewer/Viewport.h
index e83a14ba..bd17655a 100644
--- a/vncviewer/Viewport.h
+++ b/vncviewer/Viewport.h
@@ -26,7 +26,6 @@
#include <rfb/Region.h>
#include <rfb/Pixel.h>
-#include <rfb/ColourMap.h>
class Fl_Menu_Button;
class Fl_RGB_Image;
@@ -52,8 +51,6 @@ public:
// Methods forwarded from CConn
- void setColourMapEntries(int firstColour, int nColours, rdr::U16* rgbs);
-
void fillRect(const rfb::Rect& r, rfb::Pixel pix);
void imageRect(const rfb::Rect& r, void* pixels);
void copyRect(const rfb::Rect& r, int srcX, int srcY);
@@ -75,9 +72,9 @@ public:
private:
- static void handleUpdateTimeout(void *data);
+ PlatformPixelBuffer* createFramebuffer(int w, int h);
- void commitColourMap();
+ static void handleUpdateTimeout(void *data);
static void handleClipboardChange(int source, void *data);
@@ -98,11 +95,7 @@ private:
CConn* cc;
PlatformPixelBuffer* frameBuffer;
-
rfb::PixelTransformer *pixelTrans;
- rfb::SimpleColourMap colourMap;
- bool colourMapChange;
-
rfb::Region damage;
rfb::Point lastPointerPos;
diff --git a/vncviewer/Win32PixelBuffer.cxx b/vncviewer/Win32PixelBuffer.cxx
index 626bb967..9fb04145 100644
--- a/vncviewer/Win32PixelBuffer.cxx
+++ b/vncviewer/Win32PixelBuffer.cxx
@@ -1,5 +1,5 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
- * Copyright 2011 Pierre Ossman <ossman@cendio.se> for Cendio AB
+ * Copyright 2011-2014 Pierre Ossman for Cendio AB
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -35,12 +35,12 @@
using namespace rfb;
-static rfb::LogWriter vlog("PlatformPixelBuffer");
+static rfb::LogWriter vlog("Win32PixelBuffer");
-PlatformPixelBuffer::PlatformPixelBuffer(int width, int height) :
- FullFramePixelBuffer(rfb::PixelFormat(32, 24, false, true,
- 255, 255, 255, 16, 8, 0),
- width, height, NULL, NULL),
+Win32PixelBuffer::Win32PixelBuffer(int width, int height) :
+ PlatformPixelBuffer(rfb::PixelFormat(32, 24, false, true,
+ 255, 255, 255, 16, 8, 0),
+ width, height, NULL, width),
bitmap(NULL)
{
BITMAPINFOHEADER bih;
@@ -64,13 +64,13 @@ PlatformPixelBuffer::PlatformPixelBuffer(int width, int height) :
}
-PlatformPixelBuffer::~PlatformPixelBuffer()
+Win32PixelBuffer::~Win32PixelBuffer()
{
DeleteObject(bitmap);
}
-void PlatformPixelBuffer::draw(int src_x, int src_y, int x, int y, int w, int h)
+void Win32PixelBuffer::draw(int src_x, int src_y, int x, int y, int w, int h)
{
HDC dc;
diff --git a/vncviewer/Win32PixelBuffer.h b/vncviewer/Win32PixelBuffer.h
index 7d91e09d..728e5948 100644
--- a/vncviewer/Win32PixelBuffer.h
+++ b/vncviewer/Win32PixelBuffer.h
@@ -1,4 +1,4 @@
-/* Copyright 2011 Pierre Ossman <ossman@cendio.se> for Cendio AB
+/* Copyright 2011-2014 Pierre Ossman for Cendio AB
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -21,14 +21,14 @@
#include <windows.h>
-#include <rfb/PixelBuffer.h>
+#include "PlatformPixelBuffer.h"
-class PlatformPixelBuffer: public rfb::FullFramePixelBuffer {
+class Win32PixelBuffer: public PlatformPixelBuffer {
public:
- PlatformPixelBuffer(int width, int height);
- ~PlatformPixelBuffer();
+ Win32PixelBuffer(int width, int height);
+ ~Win32PixelBuffer();
- void draw(int src_x, int src_y, int x, int y, int w, int h);
+ virtual void draw(int src_x, int src_y, int x, int y, int w, int h);
protected:
HBITMAP bitmap;
diff --git a/vncviewer/X11PixelBuffer.cxx b/vncviewer/X11PixelBuffer.cxx
index 548591e1..c709984b 100644
--- a/vncviewer/X11PixelBuffer.cxx
+++ b/vncviewer/X11PixelBuffer.cxx
@@ -1,5 +1,5 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
- * Copyright 2011 Pierre Ossman <ossman@cendio.se> for Cendio AB
+ * Copyright 2011-2014 Pierre Ossman for Cendio AB
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -33,7 +33,7 @@
using namespace rfb;
-static rfb::LogWriter vlog("PlatformPixelBuffer");
+static rfb::LogWriter vlog("X11PixelBuffer");
static PixelFormat display_pf()
{
@@ -93,8 +93,8 @@ static PixelFormat display_pf()
redShift, greenShift, blueShift);
}
-PlatformPixelBuffer::PlatformPixelBuffer(int width, int height) :
- FullFramePixelBuffer(display_pf(), width, height, NULL, NULL),
+X11PixelBuffer::X11PixelBuffer(int width, int height) :
+ PlatformPixelBuffer(display_pf(), width, height, NULL, 0),
shminfo(NULL), xim(NULL)
{
// Might not be open at this point
@@ -110,10 +110,11 @@ PlatformPixelBuffer::PlatformPixelBuffer(int width, int height) :
}
data = (rdr::U8*)xim->data;
+ stride = xim->bytes_per_line / (getPF().bpp/8);
}
-PlatformPixelBuffer::~PlatformPixelBuffer()
+X11PixelBuffer::~X11PixelBuffer()
{
if (shminfo) {
vlog.debug("Freeing shared memory XImage");
@@ -130,7 +131,7 @@ PlatformPixelBuffer::~PlatformPixelBuffer()
}
-void PlatformPixelBuffer::draw(int src_x, int src_y, int x, int y, int w, int h)
+void X11PixelBuffer::draw(int src_x, int src_y, int x, int y, int w, int h)
{
if (shminfo)
XShmPutImage(fl_display, fl_window, fl_gc, xim, src_x, src_y, x, y, w, h, False);
@@ -139,11 +140,6 @@ void PlatformPixelBuffer::draw(int src_x, int src_y, int x, int y, int w, int h)
}
-int PlatformPixelBuffer::getStride() const
-{
- return xim->bytes_per_line / (getPF().bpp/8);
-}
-
static bool caughtError;
static int XShmAttachErrorHandler(Display *dpy, XErrorEvent *error)
@@ -152,7 +148,7 @@ static int XShmAttachErrorHandler(Display *dpy, XErrorEvent *error)
return 0;
}
-int PlatformPixelBuffer::setupShm()
+int X11PixelBuffer::setupShm()
{
int major, minor;
Bool pixmaps;
diff --git a/vncviewer/X11PixelBuffer.h b/vncviewer/X11PixelBuffer.h
index 0b0cee01..c2ffdc28 100644
--- a/vncviewer/X11PixelBuffer.h
+++ b/vncviewer/X11PixelBuffer.h
@@ -1,4 +1,4 @@
-/* Copyright 2011 Pierre Ossman <ossman@cendio.se> for Cendio AB
+/* Copyright 2011-2014 Pierre Ossman for Cendio AB
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -24,16 +24,14 @@
#include <sys/shm.h>
#include <X11/extensions/XShm.h>
-#include <rfb/PixelBuffer.h>
+#include "PlatformPixelBuffer.h"
-class PlatformPixelBuffer: public rfb::FullFramePixelBuffer {
+class X11PixelBuffer: public PlatformPixelBuffer {
public:
- PlatformPixelBuffer(int width, int height);
- ~PlatformPixelBuffer();
+ X11PixelBuffer(int width, int height);
+ ~X11PixelBuffer();
- void draw(int src_x, int src_y, int x, int y, int w, int h);
-
- int getStride() const;
+ virtual void draw(int src_x, int src_y, int x, int y, int w, int h);
protected:
int setupShm();
diff --git a/win/rfb_win32/DIBSectionBuffer.cxx b/win/rfb_win32/DIBSectionBuffer.cxx
index 0c266b00..e2b0d641 100644
--- a/win/rfb_win32/DIBSectionBuffer.cxx
+++ b/win/rfb_win32/DIBSectionBuffer.cxx
@@ -31,13 +31,11 @@ static LogWriter vlog("DIBSectionBuffer");
DIBSectionBuffer::DIBSectionBuffer(HWND window_)
: bitmap(0), window(window_), device(0) {
memset(&format, 0, sizeof(format));
- memset(palette, 0, sizeof(palette));
}
DIBSectionBuffer::DIBSectionBuffer(HDC device_)
: bitmap(0), window(0), device(device_) {
memset(&format, 0, sizeof(format));
- memset(palette, 0, sizeof(palette));
}
DIBSectionBuffer::~DIBSectionBuffer() {
@@ -51,19 +49,10 @@ void DIBSectionBuffer::setPF(const PixelFormat& pf) {
vlog.debug("pixel format unchanged by setPF()");
return;
}
+ if (!pf.trueColour)
+ throw rfb::Exception("palette format not supported");
format = pf;
recreateBuffer();
- if ((pf.bpp <= 8) && pf.trueColour) {
- vlog.info("creating %d-bit TrueColour palette", pf.depth);
- for (int i=0; i < (1<<(pf.depth)); i++) {
- rdr::U16 r, g, b;
- pf.rgbFromPixel(i, NULL, &r, &g, &b);
- palette[i].r = r;
- palette[i].g = g;
- palette[i].b = b;
- }
- refreshPalette();
- }
}
void DIBSectionBuffer::setSize(int w, int h) {
@@ -77,20 +66,6 @@ void DIBSectionBuffer::setSize(int w, int h) {
}
-// * copyPaletteToDIB MUST NEVER be called on a truecolour DIB! *
-
-void copyPaletteToDIB(Colour palette[256], HDC wndDC, HBITMAP dib) {
- BitmapDC dibDC(wndDC, dib);
- RGBQUAD rgb[256];
- for (unsigned int i=0;i<256;i++) {
- rgb[i].rgbRed = palette[i].r >> 8;
- rgb[i].rgbGreen = palette[i].g >> 8;
- rgb[i].rgbBlue = palette[i].b >> 8;
- }
- if (!SetDIBColorTable(dibDC, 0, 256, (RGBQUAD*) rgb))
- throw rdr::SystemException("unable to SetDIBColorTable", GetLastError());
-}
-
inline void initMaxAndShift(DWORD mask, int* max, int* shift) {
for ((*shift) = 0; (mask & 1) == 0; (*shift)++) mask >>= 1;
(*max) = (rdr::U16)mask;
@@ -103,9 +78,7 @@ void DIBSectionBuffer::recreateBuffer() {
if (width_ && height_ && (format.depth != 0)) {
BitmapInfo bi;
memset(&bi, 0, sizeof(bi));
- // *** wrong?
- UINT iUsage = format.trueColour ? DIB_RGB_COLORS : DIB_PAL_COLORS;
- // ***
+ UINT iUsage = DIB_RGB_COLORS;
bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bi.bmiHeader.biBitCount = format.bpp;
bi.bmiHeader.biSizeImage = (format.bpp / 8) * width_ * height_;
@@ -140,15 +113,11 @@ void DIBSectionBuffer::recreateBuffer() {
// Copy the contents across
if (device) {
- if (format.bpp <= 8)
- copyPaletteToDIB(palette, device, new_bitmap);
BitmapDC src_dev(device, bitmap);
BitmapDC dest_dev(device, new_bitmap);
BitBlt(dest_dev, 0, 0, width_, height_, src_dev, 0, 0, SRCCOPY);
} else {
WindowDC wndDC(window);
- if (format.bpp <= 8)
- copyPaletteToDIB(palette, wndDC, new_bitmap);
BitmapDC src_dev(wndDC, bitmap);
BitmapDC dest_dev(wndDC, new_bitmap);
BitBlt(dest_dev, 0, 0, width_, height_, src_dev, 0, 0, SRCCOPY);
@@ -164,7 +133,6 @@ void DIBSectionBuffer::recreateBuffer() {
if (new_bitmap) {
int bpp, depth;
- bool trueColour;
int redMax, greenMax, blueMax;
int redShift, greenShift, blueShift;
@@ -189,46 +157,24 @@ void DIBSectionBuffer::recreateBuffer() {
// Calculate the PixelFormat for the DIB
bpp = depth = ds.dsBm.bmBitsPixel;
- trueColour = format.trueColour || format.bpp > 8;
-
- if (trueColour) {
- // Get the truecolour format used by the DIBSection
- initMaxAndShift(ds.dsBitfields[0], &redMax, &redShift);
- initMaxAndShift(ds.dsBitfields[1], &greenMax, &greenShift);
- initMaxAndShift(ds.dsBitfields[2], &blueMax, &blueShift);
-
- // Calculate the effective depth
- depth = 0;
- Pixel bits = ds.dsBitfields[0] | ds.dsBitfields[1] | ds.dsBitfields[2];
- while (bits) {
- depth++;
- bits = bits >> 1;
- }
- if (depth > bpp)
- throw Exception("Bad DIBSection format (depth exceeds bpp)");
+
+ // Get the truecolour format used by the DIBSection
+ initMaxAndShift(ds.dsBitfields[0], &redMax, &redShift);
+ initMaxAndShift(ds.dsBitfields[1], &greenMax, &greenShift);
+ initMaxAndShift(ds.dsBitfields[2], &blueMax, &blueShift);
+
+ // Calculate the effective depth
+ depth = 0;
+ Pixel bits = ds.dsBitfields[0] | ds.dsBitfields[1] | ds.dsBitfields[2];
+ while (bits) {
+ depth++;
+ bits = bits >> 1;
}
+ if (depth > bpp)
+ throw Exception("Bad DIBSection format (depth exceeds bpp)");
- format = PixelFormat(bpp, depth, false, trueColour,
+ format = PixelFormat(bpp, depth, false, true,
redMax, greenMax, blueMax,
redShift, greenShift, blueShift);
-
- if (!trueColour) {
- // Set the DIBSection's palette
- refreshPalette();
- }
}
}
-
-void DIBSectionBuffer::refreshPalette() {
- if (format.bpp > 8) {
- vlog.error("refresh palette called for truecolor DIB");
- return;
- }
- vlog.debug("refreshing palette");
- if (device)
- copyPaletteToDIB(palette, device, bitmap);
- else
- copyPaletteToDIB(palette, WindowDC(window), bitmap);
-}
-
-
diff --git a/win/rfb_win32/DIBSectionBuffer.h b/win/rfb_win32/DIBSectionBuffer.h
index ad1a310c..cf9e7bc1 100644
--- a/win/rfb_win32/DIBSectionBuffer.h
+++ b/win/rfb_win32/DIBSectionBuffer.h
@@ -28,7 +28,6 @@
#include <windows.h>
#include <rfb/PixelBuffer.h>
#include <rfb/Region.h>
-#include <rfb/ColourMap.h>
#include <rfb/Exception.h>
namespace rfb {
@@ -39,7 +38,7 @@ namespace rfb {
// -=- DIBSectionBuffer
//
- class DIBSectionBuffer : public FullFramePixelBuffer, ColourMap {
+ class DIBSectionBuffer : public FullFramePixelBuffer {
public:
DIBSectionBuffer(HWND window);
DIBSectionBuffer(HDC device);
@@ -48,32 +47,11 @@ namespace rfb {
virtual void setPF(const PixelFormat &pf);
virtual void setSize(int w, int h);
- virtual int getStride() const {return stride;}
-
- virtual ColourMap* getColourMap() const {return (ColourMap*)this;}
-
- // - ColourMap interface
- virtual void lookup(int index, int* r, int *g, int* b) {
- *r = palette[index].r;
- *g = palette[index].g;
- *b = palette[index].b;
- }
-
- // Custom colourmap interface
- void setColour(int index, int r, int g, int b) {
- palette[index].r = r;
- palette[index].g = g;
- palette[index].b = b;
- }
- void refreshPalette();
-
// *** virtual void copyRect(const Rect &dest, const Point &move_by_delta);
public:
HBITMAP bitmap;
protected:
void recreateBuffer();
- Colour palette[256];
- int stride;
HWND window;
HDC device;
};
diff --git a/win/rfb_win32/DeviceFrameBuffer.cxx b/win/rfb_win32/DeviceFrameBuffer.cxx
index cc9bbcad..0ad06e9e 100644
--- a/win/rfb_win32/DeviceFrameBuffer.cxx
+++ b/win/rfb_win32/DeviceFrameBuffer.cxx
@@ -1,4 +1,5 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
+ * Copyright 2014 Pierre Ossman for Cendio AB
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -79,10 +80,6 @@ DeviceFrameBuffer::DeviceFrameBuffer(HDC deviceContext, const Rect& wRect)
// Configure the cursor buffer
cursorBm.setPF(format);
-
- // Set up a palette if required
- if (!format.trueColour)
- updateColourMap();
}
DeviceFrameBuffer::~DeviceFrameBuffer() {
@@ -134,37 +131,6 @@ DeviceFrameBuffer::grabRegion(const Region &rgn) {
}
-void copyDevicePaletteToDIB(HDC dc, DIBSectionBuffer* dib) {
- // - Fetch the system palette for the framebuffer
- PALETTEENTRY syspalette[256];
- UINT entries = ::GetSystemPaletteEntries(dc, 0, 256, syspalette);
-
- if (entries == 0) {
- vlog.info("resorting to standard 16 color palette");
- for (unsigned int i=0;i<256;i++) {
- int v = (i%16) >= 8 ? 127 : 255;
- syspalette[i].peRed = i & 1 ? v : 0;
- syspalette[i].peGreen = i & 2 ? v : 0;
- syspalette[i].peBlue = i & 4 ? v : 0;
- }
- } else {
- vlog.info("framebuffer has %u palette entries", entries);
- }
-
- // - Update the bitmap's stored copy of the palette
- for (unsigned int i=0;i<256;i++) {
- int r, g, b;
- r = (syspalette[i].peRed << 8) + 0x80;
- g = (syspalette[i].peGreen << 8) + 0x80;
- b = (syspalette[i].peBlue << 8) + 0x80;
- dib->setColour(i, r, g, b);
- }
-
- // - Update the DIB section to use the palette
- dib->refreshPalette();
-}
-
-
void DeviceFrameBuffer::setCursor(HCURSOR hCursor, VNCServer* server)
{
// - If hCursor is null then there is no cursor - clear the old one
@@ -176,6 +142,10 @@ void DeviceFrameBuffer::setCursor(HCURSOR hCursor, VNCServer* server)
try {
+ const rdr::U8* buffer;
+ rdr::U8* rwbuffer;
+ int stride;
+
// - Get the size and other details about the cursor.
IconInfo iconInfo((HICON)hCursor);
@@ -211,10 +181,6 @@ void DeviceFrameBuffer::setCursor(HCURSOR hCursor, VNCServer* server)
// Configure the cursor bitmap
cursorBm.setSize(cursor.width(), cursor.height());
- // Copy the palette into it if required
- if (format.bpp <= 8)
- copyDevicePaletteToDIB(device, &cursorBm);
-
// Draw the cursor into the bitmap
BitmapDC dc(device, cursorBm.bitmap);
if (!DrawIconEx(dc, 0, 0, hCursor, 0, 0, 0, NULL, DI_NORMAL | DI_COMPAT))
@@ -231,7 +197,8 @@ void DeviceFrameBuffer::setCursor(HCURSOR hCursor, VNCServer* server)
bool doOutline = false;
if (!iconInfo.hbmColor) {
- Pixel xorColour = format.pixelFromRGB((rdr::U16)0, (rdr::U16)0, (rdr::U16)0, cursorBm.getColourMap());
+ rwbuffer = cursorBm.getBufferRW(cursorBm.getRect(), &stride);
+ Pixel xorColour = format.pixelFromRGB((rdr::U16)0, (rdr::U16)0, (rdr::U16)0);
for (int y = 0; y < cursor.height(); y++) {
for (int x = 0; x < cursor.width(); x++) {
int byte = y * maskInfo.bmWidthBytes + x / 8;
@@ -242,11 +209,11 @@ void DeviceFrameBuffer::setCursor(HCURSOR hCursor, VNCServer* server)
switch (format.bpp) {
case 8:
- ((rdr::U8*)cursorBm.data)[y * cursor.width() + x] = xorColour; break;
+ rwbuffer[y * cursor.width() + x] = xorColour; break;
case 16:
- ((rdr::U16*)cursorBm.data)[y * cursor.width() + x] = xorColour; break;
+ rwbuffer[y * cursor.width() + x] = xorColour; break;
case 32:
- ((rdr::U32*)cursorBm.data)[y * cursor.width() + x] = xorColour; break;
+ rwbuffer[y * cursor.width() + x] = xorColour; break;
}
doOutline = true;
@@ -268,21 +235,21 @@ void DeviceFrameBuffer::setCursor(HCURSOR hCursor, VNCServer* server)
if (doOutline) {
vlog.debug("drawing cursor outline!");
- memcpy(cursor.data, cursorBm.data, cursor.dataLen());
- cursor.drawOutline(format.pixelFromRGB((rdr::U16)0xffff, (rdr::U16)0xffff, (rdr::U16)0xffff, cursorBm.getColourMap()));
- memcpy(cursorBm.data, cursor.data, cursor.dataLen());
+
+ buffer = cursorBm.getBuffer(cursorBm.getRect(), &stride);
+ cursor.imageRect(cursorBm.getRect(), buffer, stride);
+
+ cursor.drawOutline(format.pixelFromRGB((rdr::U16)0xffff, (rdr::U16)0xffff, (rdr::U16)0xffff));
+
+ buffer = cursor.getBuffer(cursor.getRect(), &stride);
+ cursorBm.imageRect(cursor.getRect(), buffer, stride);
}
+ buffer = cursorBm.getBuffer(cursorBm.getRect(), &stride);
server->setCursor(cursor.width(), cursor.height(), cursor.hotspot,
- cursorBm.data, cursor.mask.buf);
+ buffer, cursor.mask.buf);
+
} catch (rdr::Exception& e) {
vlog.error("%s", e.str());
}
}
-
-
-void
-DeviceFrameBuffer::updateColourMap() {
- if (!format.trueColour)
- copyDevicePaletteToDIB(device, this);
-}
diff --git a/win/rfb_win32/DeviceFrameBuffer.h b/win/rfb_win32/DeviceFrameBuffer.h
index 7718c339..8e280f8a 100644
--- a/win/rfb_win32/DeviceFrameBuffer.h
+++ b/win/rfb_win32/DeviceFrameBuffer.h
@@ -79,7 +79,6 @@ namespace rfb {
// - DeviceFrameBuffer specific methods
void setCursor(HCURSOR c, VNCServer* server);
- void updateColourMap();
// Set whether grabRect should ignore errors or throw exceptions
// Only set this if you are sure you'll capture the errors some other way!
diff --git a/win/rfb_win32/SDisplay.cxx b/win/rfb_win32/SDisplay.cxx
index 6d0c924f..26a7bbce 100644
--- a/win/rfb_win32/SDisplay.cxx
+++ b/win/rfb_win32/SDisplay.cxx
@@ -350,12 +350,6 @@ SDisplay::notifyDisplayEvent(WMMonitor::Notifier::DisplayEventType evt) {
vlog.debug("desktop format changed");
recreatePixelBuffer();
break;
- case WMMonitor::Notifier::DisplayColourMapChanged:
- vlog.debug("desktop colormap changed");
- pb->updateColourMap();
- if (server)
- server->setColourMapEntries();
- break;
default:
vlog.error("unknown display event received");
}
diff --git a/win/rfb_win32/WMNotifier.cxx b/win/rfb_win32/WMNotifier.cxx
index 20a5445f..159dacaf 100644
--- a/win/rfb_win32/WMNotifier.cxx
+++ b/win/rfb_win32/WMNotifier.cxx
@@ -46,12 +46,6 @@ WMMonitor::processMessage(UINT msg, WPARAM wParam, LPARAM lParam) {
notifier->notifyDisplayEvent(Notifier::DisplayPixelFormatChanged);
}
break;
- case WM_SYSCOLORCHANGE:
- case WM_PALETTECHANGED:
- if (notifier) {
- notifier->notifyDisplayEvent(Notifier::DisplayColourMapChanged);
- }
- break;
};
return MsgWindow::processMessage(msg, wParam, lParam);
}
diff --git a/win/rfb_win32/WMNotifier.h b/win/rfb_win32/WMNotifier.h
index a7609642..ada45d09 100644
--- a/win/rfb_win32/WMNotifier.h
+++ b/win/rfb_win32/WMNotifier.h
@@ -44,7 +44,7 @@ namespace rfb {
class Notifier {
public:
- typedef enum {DisplaySizeChanged, DisplayColourMapChanged,
+ typedef enum {DisplaySizeChanged,
DisplayPixelFormatChanged} DisplayEventType;
virtual void notifyDisplayEvent(DisplayEventType evt) = 0;
};