Browse Source

Use PixelBuffer objects as the interface for encoders and decoders

This avoid a lot of unnecessary middle men. This also pushes the
responsibility for pixel format conversion into the encoders and
decoders. The new bufferFromBuffer() is used for direct conversion,
rather than PixelTransformer/TransImageGetter.
tags/v1.3.90
Pierre Ossman 10 years ago
parent
commit
0c9bd4b0ba
45 changed files with 200 additions and 363 deletions
  1. 0
    9
      common/rfb/CMsgHandler.h
  2. 2
    3
      common/rfb/CopyRectDecoder.cxx
  3. 1
    1
      common/rfb/CopyRectDecoder.h
  4. 8
    2
      common/rfb/Decoder.h
  5. 6
    5
      common/rfb/Encoder.h
  6. 7
    6
      common/rfb/HextileDecoder.cxx
  7. 1
    1
      common/rfb/HextileDecoder.h
  8. 11
    9
      common/rfb/HextileEncoder.cxx
  9. 1
    1
      common/rfb/HextileEncoder.h
  10. 7
    6
      common/rfb/RREDecoder.cxx
  11. 1
    1
      common/rfb/RREDecoder.h
  12. 5
    4
      common/rfb/RREEncoder.cxx
  13. 1
    1
      common/rfb/RREEncoder.h
  14. 5
    4
      common/rfb/RawDecoder.cxx
  15. 1
    1
      common/rfb/RawDecoder.h
  16. 7
    17
      common/rfb/RawEncoder.cxx
  17. 1
    1
      common/rfb/RawEncoder.h
  18. 5
    5
      common/rfb/TightDecoder.cxx
  19. 2
    2
      common/rfb/TightDecoder.h
  20. 6
    7
      common/rfb/TightEncoder.cxx
  21. 3
    3
      common/rfb/TightEncoder.h
  22. 15
    15
      common/rfb/VNCSConnectionST.cxx
  23. 0
    2
      common/rfb/VNCSConnectionST.h
  24. 0
    1
      common/rfb/VNCServerST.cxx
  25. 1
    8
      common/rfb/VNCServerST.h
  26. 9
    10
      common/rfb/ZRLEDecoder.cxx
  27. 1
    1
      common/rfb/ZRLEDecoder.h
  28. 9
    10
      common/rfb/ZRLEEncoder.cxx
  29. 1
    1
      common/rfb/ZRLEEncoder.h
  30. 3
    3
      common/rfb/hextileDecode.h
  31. 4
    3
      common/rfb/hextileEncode.h
  32. 3
    2
      common/rfb/hextileEncodeBetter.h
  33. 4
    3
      common/rfb/rreDecode.h
  34. 6
    6
      common/rfb/tightDecode.h
  35. 11
    10
      common/rfb/tightEncode.h
  36. 3
    3
      common/rfb/zrleDecode.h
  37. 3
    2
      common/rfb/zrleEncode.h
  38. 1
    26
      vncviewer/CConn.cxx
  39. 0
    10
      vncviewer/CConn.h
  40. 3
    24
      vncviewer/DesktopWindow.cxx
  41. 7
    9
      vncviewer/DesktopWindow.h
  42. 16
    0
      vncviewer/PlatformPixelBuffer.cxx
  43. 6
    0
      vncviewer/PlatformPixelBuffer.h
  44. 8
    106
      vncviewer/Viewport.cxx
  45. 5
    19
      vncviewer/Viewport.h

+ 0
- 9
common/rfb/CMsgHandler.h View File

virtual void bell() = 0; virtual void bell() = 0;
virtual void serverCutText(const char* str, rdr::U32 len) = 0; virtual void serverCutText(const char* str, rdr::U32 len) = 0;


virtual void fillRect(const Rect& r, Pixel pix) = 0;
virtual void imageRect(const Rect& r, void* pixels) = 0;
virtual void copyRect(const Rect& r, int srcX, int srcY) = 0;

virtual rdr::U8* getRawBufferRW(const Rect& r, int* stride) = 0;
virtual void releaseRawBuffer(const Rect& r) = 0;

virtual const PixelFormat &getPreferredPF(void) = 0;

ConnParams cp; ConnParams cp;
}; };
} }

+ 2
- 3
common/rfb/CopyRectDecoder.cxx View File

*/ */
#include <rdr/InStream.h> #include <rdr/InStream.h>
#include <rfb/CConnection.h> #include <rfb/CConnection.h>
#include <rfb/CMsgHandler.h>
#include <rfb/PixelBuffer.h> #include <rfb/PixelBuffer.h>
#include <rfb/CopyRectDecoder.h> #include <rfb/CopyRectDecoder.h>


{ {
} }


void CopyRectDecoder::readRect(const Rect& r, CMsgHandler* handler)
void CopyRectDecoder::readRect(const Rect& r, ModifiablePixelBuffer* pb)
{ {
int srcX = conn->getInStream()->readU16(); int srcX = conn->getInStream()->readU16();
int srcY = conn->getInStream()->readU16(); int srcY = conn->getInStream()->readU16();
handler->copyRect(r, srcX, srcY);
pb->copyRect(r, Point(r.tl.x-srcX, r.tl.y-srcY));
} }

+ 1
- 1
common/rfb/CopyRectDecoder.h View File

public: public:
CopyRectDecoder(CConnection* conn); CopyRectDecoder(CConnection* conn);
virtual ~CopyRectDecoder(); virtual ~CopyRectDecoder();
virtual void readRect(const Rect& r, CMsgHandler* handler);
virtual void readRect(const Rect& r, ModifiablePixelBuffer* pb);
}; };
} }
#endif #endif

+ 8
- 2
common/rfb/Decoder.h View File



namespace rfb { namespace rfb {
class CConnection; class CConnection;
class CMsgHandler;
class ModifiablePixelBuffer;


class Decoder { class Decoder {
public: public:
Decoder(CConnection* conn); Decoder(CConnection* conn);
virtual ~Decoder(); virtual ~Decoder();
virtual void readRect(const Rect& r, CMsgHandler* handler)=0;

// readRect() is the main interface that decodes the given rectangle
// with data from the CConnection, given at decoder creation, onto
// the ModifiablePixelBuffer. The PixelFormat of the PixelBuffer might
// not match the ConnParams and it is up to the decoder to do
// any necessary conversion.
virtual void readRect(const Rect& r, ModifiablePixelBuffer* pb)=0;


static bool supported(int encoding); static bool supported(int encoding);
static Decoder* createDecoder(int encoding, CConnection* conn); static Decoder* createDecoder(int encoding, CConnection* conn);

+ 6
- 5
common/rfb/Encoder.h View File

#define __RFB_ENCODER_H__ #define __RFB_ENCODER_H__


#include <rfb/Rect.h> #include <rfb/Rect.h>
#include <rfb/TransImageGetter.h>


namespace rfb { namespace rfb {
class SConnection; class SConnection;
class TransImageGetter;
class PixelBuffer;


class Encoder { class Encoder {
public: public:
virtual int getNumRects(const Rect &r) { return 1; } virtual int getNumRects(const Rect &r) { return 1; }


// writeRect() is the main interface that encodes the given rectangle // 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;
// with data from the PixelBuffer onto the SConnection given at
// encoder creation. The PixelFormat of the PixelBuffer might not
// match the ConnParams and it is up ot the encoder to do
// any necessary conversion.
virtual void writeRect(const Rect& r, PixelBuffer* pb)=0;


static bool supported(int encoding); static bool supported(int encoding);
static Encoder* createEncoder(int encoding, SConnection* conn); static Encoder* createEncoder(int encoding, SConnection* conn);

+ 7
- 6
common/rfb/HextileDecoder.cxx View File

*/ */
#include <rfb/CMsgReader.h> #include <rfb/CMsgReader.h>
#include <rfb/CConnection.h> #include <rfb/CConnection.h>
#include <rfb/CMsgHandler.h>
#include <rfb/PixelBuffer.h>
#include <rfb/HextileDecoder.h> #include <rfb/HextileDecoder.h>


using namespace rfb; using namespace rfb;
{ {
} }


void HextileDecoder::readRect(const Rect& r, CMsgHandler* handler)
void HextileDecoder::readRect(const Rect& r, ModifiablePixelBuffer* pb)
{ {
rdr::InStream* is = conn->getInStream(); rdr::InStream* is = conn->getInStream();
rdr::U8* buf = conn->reader()->getImageBuf(16 * 16 * 4); 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;
const PixelFormat& pf = conn->cp.pf();
switch (pf.bpp) {
case 8: hextileDecode8 (r, is, (rdr::U8*) buf, pf, pb); break;
case 16: hextileDecode16(r, is, (rdr::U16*)buf, pf, pb); break;
case 32: hextileDecode32(r, is, (rdr::U32*)buf, pf, pb); break;
} }
} }

+ 1
- 1
common/rfb/HextileDecoder.h View File

public: public:
HextileDecoder(CConnection* conn); HextileDecoder(CConnection* conn);
virtual ~HextileDecoder(); virtual ~HextileDecoder();
virtual void readRect(const Rect& r, CMsgHandler* handler);
virtual void readRect(const Rect& r, ModifiablePixelBuffer* pb);
}; };
} }
#endif #endif

+ 11
- 9
common/rfb/HextileEncoder.cxx View File

* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA. * USA.
*/ */
#include <rfb/TransImageGetter.h>
#include <rfb/encodings.h> #include <rfb/encodings.h>
#include <rfb/SMsgWriter.h> #include <rfb/SMsgWriter.h>
#include <rfb/SConnection.h> #include <rfb/SConnection.h>
#include <rfb/HextileEncoder.h> #include <rfb/HextileEncoder.h>
#include <rfb/PixelFormat.h>
#include <rfb/PixelBuffer.h>
#include <rfb/Configuration.h> #include <rfb/Configuration.h>


using namespace rfb; using namespace rfb;
{ {
} }


void HextileEncoder::writeRect(const Rect& r, TransImageGetter* ig)
void HextileEncoder::writeRect(const Rect& r, PixelBuffer* pb)
{ {
conn->writer()->startRect(r, encodingHextile); conn->writer()->startRect(r, encodingHextile);
rdr::OutStream* os = conn->getOutStream(); rdr::OutStream* os = conn->getOutStream();
switch (conn->cp.pf().bpp) {
const PixelFormat& pf = conn->cp.pf();
switch (pf.bpp) {
case 8: case 8:
if (improvedHextile) { if (improvedHextile) {
hextileEncodeBetter8(r, os, ig);
hextileEncodeBetter8(r, os, pf, pb);
} else { } else {
hextileEncode8(r, os, ig);
hextileEncode8(r, os, pf, pb);
} }
break; break;
case 16: case 16:
if (improvedHextile) { if (improvedHextile) {
hextileEncodeBetter16(r, os, ig);
hextileEncodeBetter16(r, os, pf, pb);
} else { } else {
hextileEncode16(r, os, ig);
hextileEncode16(r, os, pf, pb);
} }
break; break;
case 32: case 32:
if (improvedHextile) { if (improvedHextile) {
hextileEncodeBetter32(r, os, ig);
hextileEncodeBetter32(r, os, pf, pb);
} else { } else {
hextileEncode32(r, os, ig);
hextileEncode32(r, os, pf, pb);
} }
break; break;
} }

+ 1
- 1
common/rfb/HextileEncoder.h View File

public: public:
HextileEncoder(SConnection* conn); HextileEncoder(SConnection* conn);
virtual ~HextileEncoder(); virtual ~HextileEncoder();
virtual void writeRect(const Rect& r, TransImageGetter* ig);
virtual void writeRect(const Rect& r, PixelBuffer* pb);
}; };
} }
#endif #endif

+ 7
- 6
common/rfb/RREDecoder.cxx View File

*/ */
#include <rfb/CMsgReader.h> #include <rfb/CMsgReader.h>
#include <rfb/CConnection.h> #include <rfb/CConnection.h>
#include <rfb/CMsgHandler.h>
#include <rfb/PixelBuffer.h>
#include <rfb/RREDecoder.h> #include <rfb/RREDecoder.h>


using namespace rfb; using namespace rfb;
{ {
} }


void RREDecoder::readRect(const Rect& r, CMsgHandler* handler)
void RREDecoder::readRect(const Rect& r, ModifiablePixelBuffer* pb)
{ {
rdr::InStream* is = conn->getInStream(); 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;
const PixelFormat& pf = conn->cp.pf();
switch (pf.bpp) {
case 8: rreDecode8 (r, is, pf, pb); break;
case 16: rreDecode16(r, is, pf, pb); break;
case 32: rreDecode32(r, is, pf, pb); break;
} }
} }

+ 1
- 1
common/rfb/RREDecoder.h View File

public: public:
RREDecoder(CConnection* conn); RREDecoder(CConnection* conn);
virtual ~RREDecoder(); virtual ~RREDecoder();
virtual void readRect(const Rect& r, CMsgHandler* handler);
virtual void readRect(const Rect& r, ModifiablePixelBuffer* pb);
}; };
} }
#endif #endif

+ 5
- 4
common/rfb/RREEncoder.cxx View File

* USA. * USA.
*/ */
#include <rdr/OutStream.h> #include <rdr/OutStream.h>
#include <rfb/TransImageGetter.h>
#include <rfb/encodings.h> #include <rfb/encodings.h>
#include <rfb/SMsgWriter.h> #include <rfb/SMsgWriter.h>
#include <rfb/SConnection.h> #include <rfb/SConnection.h>
#include <rfb/PixelFormat.h>
#include <rfb/PixelBuffer.h>
#include <rfb/RREEncoder.h> #include <rfb/RREEncoder.h>


using namespace rfb; using namespace rfb;
{ {
} }


void RREEncoder::writeRect(const Rect& r, TransImageGetter* ig)
void RREEncoder::writeRect(const Rect& r, PixelBuffer* pb)
{ {
int w = r.width(); int w = r.width();
int h = r.height(); int h = r.height();
rdr::U8* imageBuf = conn->writer()->getImageBuf(w*h); rdr::U8* imageBuf = conn->writer()->getImageBuf(w*h);
ig->getImage(imageBuf, r);
pb->getImage(conn->cp.pf(), imageBuf, r);


mos.clear(); mos.clear();


} }
if (nSubrects < 0) { if (nSubrects < 0) {
RawEncoder::writeRect(r, ig);
RawEncoder::writeRect(r, pb);
return; return;
} }



+ 1
- 1
common/rfb/RREEncoder.h View File

public: public:
RREEncoder(SConnection* conn); RREEncoder(SConnection* conn);
virtual ~RREEncoder(); virtual ~RREEncoder();
virtual void writeRect(const Rect& r, TransImageGetter* ig);
virtual void writeRect(const Rect& r, PixelBuffer* pb);
private: private:
rdr::MemOutStream mos; rdr::MemOutStream mos;
}; };

+ 5
- 4
common/rfb/RawDecoder.cxx View File

#include <rdr/InStream.h> #include <rdr/InStream.h>
#include <rfb/CMsgReader.h> #include <rfb/CMsgReader.h>
#include <rfb/CConnection.h> #include <rfb/CConnection.h>
#include <rfb/CMsgHandler.h>
#include <rfb/PixelBuffer.h>
#include <rfb/RawDecoder.h> #include <rfb/RawDecoder.h>


using namespace rfb; using namespace rfb;
{ {
} }


void RawDecoder::readRect(const Rect& r, CMsgHandler* handler)
void RawDecoder::readRect(const Rect& r, ModifiablePixelBuffer* pb)
{ {
int x = r.tl.x; int x = r.tl.x;
int y = r.tl.y; int y = r.tl.y;
int h = r.height(); int h = r.height();
int nPixels; int nPixels;
rdr::U8* imageBuf = conn->reader()->getImageBuf(w, w*h, &nPixels); rdr::U8* imageBuf = conn->reader()->getImageBuf(w, w*h, &nPixels);
int bytesPerRow = w * (conn->cp.pf().bpp / 8);
const PixelFormat& pf = conn->cp.pf();
int bytesPerRow = w * (pf.bpp / 8);
while (h > 0) { while (h > 0) {
int nRows = nPixels / w; int nRows = nPixels / w;
if (nRows > h) nRows = h; if (nRows > h) nRows = h;
conn->getInStream()->readBytes(imageBuf, nRows * bytesPerRow); conn->getInStream()->readBytes(imageBuf, nRows * bytesPerRow);
handler->imageRect(Rect(x, y, x+w, y+nRows), imageBuf);
pb->imageRect(pf, Rect(x, y, x+w, y+nRows), imageBuf);
h -= nRows; h -= nRows;
y += nRows; y += nRows;
} }

+ 1
- 1
common/rfb/RawDecoder.h View File

public: public:
RawDecoder(CConnection* conn); RawDecoder(CConnection* conn);
virtual ~RawDecoder(); virtual ~RawDecoder();
virtual void readRect(const Rect& r, CMsgHandler* handler);
virtual void readRect(const Rect& r, ModifiablePixelBuffer* pb);
}; };
} }
#endif #endif

+ 7
- 17
common/rfb/RawEncoder.cxx View File

* USA. * USA.
*/ */
#include <rdr/OutStream.h> #include <rdr/OutStream.h>
#include <rfb/TransImageGetter.h>
#include <rfb/encodings.h> #include <rfb/encodings.h>
#include <rfb/SMsgWriter.h> #include <rfb/SMsgWriter.h>
#include <rfb/SConnection.h> #include <rfb/SConnection.h>
#include <rfb/PixelBuffer.h>
#include <rfb/RawEncoder.h> #include <rfb/RawEncoder.h>


using namespace rfb; using namespace rfb;
{ {
} }


void RawEncoder::writeRect(const Rect& r, TransImageGetter* ig)
void RawEncoder::writeRect(const Rect& r, PixelBuffer* pb)
{ {
int x = r.tl.x;
int y = r.tl.y;
int w = r.width();
int h = r.height();
int nPixels;
rdr::U8* imageBuf = conn->writer()->getImageBuf(w, w*h, &nPixels);
int bytesPerRow = w * (conn->cp.pf().bpp / 8);
rdr::U8* buf = conn->writer()->getImageBuf(r.area());

pb->getImage(conn->cp.pf(), buf, r);

conn->writer()->startRect(r, encodingRaw); 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));
conn->getOutStream()->writeBytes(imageBuf, nRows * bytesPerRow);
h -= nRows;
y += nRows;
}
conn->getOutStream()->writeBytes(buf, r.area() * conn->cp.pf().bpp/8);
conn->writer()->endRect(); conn->writer()->endRect();
} }

+ 1
- 1
common/rfb/RawEncoder.h View File

public: public:
RawEncoder(SConnection* conn); RawEncoder(SConnection* conn);
virtual ~RawEncoder(); virtual ~RawEncoder();
virtual void writeRect(const Rect& r, TransImageGetter* ig);
virtual void writeRect(const Rect& r, PixelBuffer* pb);
}; };
} }
#endif #endif

+ 5
- 5
common/rfb/TightDecoder.cxx View File

*/ */
#include <rfb/CMsgReader.h> #include <rfb/CMsgReader.h>
#include <rfb/CConnection.h> #include <rfb/CConnection.h>
#include <rfb/CMsgHandler.h>
#include <rfb/PixelBuffer.h>
#include <rfb/TightDecoder.h> #include <rfb/TightDecoder.h>


using namespace rfb; using namespace rfb;
{ {
} }


void TightDecoder::readRect(const Rect& r, CMsgHandler* handler)
void TightDecoder::readRect(const Rect& r, ModifiablePixelBuffer* pb)
{ {
is = conn->getInStream(); is = conn->getInStream();
this->handler = handler;
clientpf = handler->getPreferredPF();
serverpf = handler->cp.pf();
this->pb = pb;
clientpf = pb->getPF();
serverpf = conn->cp.pf();


if (clientpf.equal(serverpf)) { if (clientpf.equal(serverpf)) {
/* Decode directly into the framebuffer (fast path) */ /* Decode directly into the framebuffer (fast path) */

+ 2
- 2
common/rfb/TightDecoder.h View File

public: public:
TightDecoder(CConnection* conn); TightDecoder(CConnection* conn);
virtual ~TightDecoder(); virtual ~TightDecoder();
virtual void readRect(const Rect& r, CMsgHandler* handler);
virtual void readRect(const Rect& r, ModifiablePixelBuffer* pb);


private: private:
rdr::U32 readCompact(rdr::InStream* is); rdr::U32 readCompact(rdr::InStream* is);
void directFillRect16(const Rect& r, Pixel pix); void directFillRect16(const Rect& r, Pixel pix);
void directFillRect32(const Rect& r, Pixel pix); void directFillRect32(const Rect& r, Pixel pix);


CMsgHandler* handler;
ModifiablePixelBuffer* pb;
rdr::InStream* is; rdr::InStream* is;
rdr::ZlibInStream zis[4]; rdr::ZlibInStream zis[4];
JpegDecompressor jd; JpegDecompressor jd;

+ 6
- 7
common/rfb/TightEncoder.cxx View File

* USA. * USA.
*/ */
#include <rdr/OutStream.h> #include <rdr/OutStream.h>
#include <rfb/TransImageGetter.h>
#include <rfb/PixelBuffer.h> #include <rfb/PixelBuffer.h>
#include <rfb/encodings.h> #include <rfb/encodings.h>
#include <rfb/ConnParams.h> #include <rfb/ConnParams.h>
} }
} }


void TightEncoder::writeRect(const Rect& _r, TransImageGetter* _ig)
void TightEncoder::writeRect(const Rect& _r, PixelBuffer* _pb)
{ {
ig = _ig;
serverpf = ig->getPixelBuffer()->getPF();
pb = _pb;
serverpf = pb->getPF();
ConnParams* cp = &conn->cp; ConnParams* cp = &conn->cp;
clientpf = cp->pf(); clientpf = cp->pf();


} }
if (bestr.tl.x != x) { if (bestr.tl.x != x) {
sr.setXYWH(x, bestr.tl.y, bestr.tl.x - x, bestr.height()); sr.setXYWH(x, bestr.tl.y, bestr.tl.x - x, bestr.height());
writeRect(sr, _ig);
writeRect(sr, _pb);
} }


// Send solid-color rectangle. // Send solid-color rectangle.
if (bestr.br.x != r.br.x) { if (bestr.br.x != r.br.x) {
sr.setXYWH(bestr.br.x, bestr.tl.y, r.br.x - bestr.br.x, sr.setXYWH(bestr.br.x, bestr.tl.y, r.br.x - bestr.br.x,
bestr.height()); bestr.height());
writeRect(sr, _ig);
writeRect(sr, _pb);
} }
if (bestr.br.y != r.br.y) { if (bestr.br.y != r.br.y) {
sr.setXYWH(x, bestr.br.y, w, r.br.y - bestr.br.y); sr.setXYWH(x, bestr.br.y, w, r.br.y - bestr.br.y);
writeRect(sr, _ig);
writeRect(sr, _pb);
} }


return; return;

+ 3
- 3
common/rfb/TightEncoder.h View File



namespace rfb { namespace rfb {


class TransImageGetter;
class PixelBuffer;


struct TIGHT_CONF { struct TIGHT_CONF {
unsigned int maxRectSize, maxRectWidth; unsigned int maxRectSize, maxRectWidth;
virtual void setQualityLevel(int level); virtual void setQualityLevel(int level);
virtual void setFineQualityLevel(int quality, int subsampling); virtual void setFineQualityLevel(int quality, int subsampling);
virtual int getNumRects(const Rect &r); virtual int getNumRects(const Rect &r);
virtual void writeRect(const Rect& r, TransImageGetter* ig);
virtual void writeRect(const Rect& r, PixelBuffer* pb);


private: private:
bool checkSolidTile(Rect& r, rdr::U32* colorPtr, bool needSameColor); bool checkSolidTile(Rect& r, rdr::U32* colorPtr, bool needSameColor);
rdr::MemOutStream mos; rdr::MemOutStream mos;
rdr::ZlibOutStream zos[4]; rdr::ZlibOutStream zos[4];
JpegCompressor jc; JpegCompressor jc;
TransImageGetter *ig;
PixelBuffer *pb;
PixelFormat serverpf, clientpf; PixelFormat serverpf, clientpf;


bool pack24; bool pack24;

+ 15
- 15
common/rfb/VNCSConnectionST.cxx View File

fenceDataLen(0), fenceData(NULL), fenceDataLen(0), fenceData(NULL),
baseRTT(-1), minRTT(-1), seenCongestion(false), pingCounter(0), baseRTT(-1), minRTT(-1), seenCongestion(false), pingCounter(0),
ackedOffset(0), sentOffset(0), congWindow(0), congestionTimer(this), ackedOffset(0), sentOffset(0), congWindow(0), congestionTimer(this),
server(server_),
updates(false), image_getter(server->useEconomicTranslate),
server(server_), updates(false),
drawRenderedCursor(false), removeRenderedCursor(false), drawRenderedCursor(false), removeRenderedCursor(false),
continuousUpdates(false), continuousUpdates(false),
updateTimer(this), pointerEventTime(0), updateTimer(this), pointerEventTime(0),
// work out what's actually changed. // work out what's actually changed.
updates.clear(); updates.clear();
updates.add_changed(server->pb->getRect()); updates.add_changed(server->pb->getRect());
vlog.debug("pixel buffer changed - re-initialising image getter");
image_getter.init(server->pb, cp.pf(), writer());
writeFramebufferUpdate(); writeFramebufferUpdate();
} catch(rdr::Exception &e) { } catch(rdr::Exception &e) {
close(e.str()); close(e.str());
char buffer[256]; char buffer[256];
cp.pf().print(buffer, 256); cp.pf().print(buffer, 256);
vlog.info("Server default pixel format %s", buffer); vlog.info("Server default pixel format %s", buffer);
image_getter.init(server->pb, cp.pf(), 0);


// - Mark the entire display as "dirty" // - Mark the entire display as "dirty"
updates.add_changed(server->pb->getRect()); updates.add_changed(server->pb->getRect());
char buffer[256]; char buffer[256];
pf.print(buffer, 256); pf.print(buffer, 256);
vlog.info("Client pixel format %s", buffer); vlog.info("Client pixel format %s", buffer);
image_getter.init(server->pb, pf, writer());
setCursor(); setCursor();
} }


std::vector<Rect>::const_iterator i; std::vector<Rect>::const_iterator i;
int encoding; int encoding;


Encoder* encoder;
PixelBuffer* pb;

// Make sure the encoder has the latest settings // Make sure the encoder has the latest settings
encoding = cp.currentEncoding(); encoding = cp.currentEncoding();


if (!encoders[encoding]) if (!encoders[encoding])
encoders[encoding] = Encoder::createEncoder(encoding, this); encoders[encoding] = Encoder::createEncoder(encoding, this);


encoders[encoding]->setCompressLevel(cp.compressLevel);
encoders[encoding]->setQualityLevel(cp.qualityLevel);
encoders[encoding]->setFineQualityLevel(cp.fineQualityLevel,
cp.subsampling);
encoder = encoders[encoding];

encoder->setCompressLevel(cp.compressLevel);
encoder->setQualityLevel(cp.qualityLevel);
encoder->setFineQualityLevel(cp.fineQualityLevel, cp.subsampling);


// Compute the number of rectangles. Tight encoder makes the things more // Compute the number of rectangles. Tight encoder makes the things more
// complicated as compared to the original VNC4. // complicated as compared to the original VNC4.
ui.changed.get_rects(&rects); ui.changed.get_rects(&rects);
for (i = rects.begin(); i != rects.end(); i++) { for (i = rects.begin(); i != rects.end(); i++) {
if (i->width() && i->height()) { if (i->width() && i->height()) {
int nUpdateRects = encoders[encoding]->getNumRects(*i);
int nUpdateRects = encoder->getNumRects(*i);
if (nUpdateRects == 0 && cp.currentEncoding() == encodingTight) { if (nUpdateRects == 0 && cp.currentEncoding() == encodingTight) {
// With Tight encoding and LastRect support, the client does not // With Tight encoding and LastRect support, the client does not
// care about the number of rectangles in the update - it will // care about the number of rectangles in the update - it will
writer()->writeCopyRect(*i, i->tl.x - ui.copy_delta.x, writer()->writeCopyRect(*i, i->tl.x - ui.copy_delta.x,
i->tl.y - ui.copy_delta.y); i->tl.y - ui.copy_delta.y);


pb = server->getPixelBuffer();

ui.changed.get_rects(&rects); ui.changed.get_rects(&rects);
for (i = rects.begin(); i != rects.end(); i++) for (i = rects.begin(); i != rects.end(); i++)
encoders[encoding]->writeRect(*i, &image_getter);
encoder->writeRect(*i, pb);


if (drawRenderedCursor) { if (drawRenderedCursor) {
image_getter.setPixelBuffer(&server->renderedCursor);
encoders[encoding]->writeRect(renderedCursorRect, &image_getter);
image_getter.setPixelBuffer(server->pb);
renderedCursorRect = server->renderedCursor.getEffectiveRect();
encoder->writeRect(renderedCursorRect, &server->renderedCursor);


drawRenderedCursor = false; drawRenderedCursor = false;
} }

+ 0
- 2
common/rfb/VNCSConnectionST.h View File

#include <set> #include <set>
#include <rfb/SConnection.h> #include <rfb/SConnection.h>
#include <rfb/SMsgWriter.h> #include <rfb/SMsgWriter.h>
#include <rfb/TransImageGetter.h>
#include <rfb/VNCServerST.h> #include <rfb/VNCServerST.h>
#include <rfb/Timer.h> #include <rfb/Timer.h>




VNCServerST* server; VNCServerST* server;
SimpleUpdateTracker updates; SimpleUpdateTracker updates;
TransImageGetter image_getter;
Region requested; Region requested;
bool drawRenderedCursor, removeRenderedCursor; bool drawRenderedCursor, removeRenderedCursor;
Rect renderedCursorRect; Rect renderedCursorRect;

+ 0
- 1
common/rfb/VNCServerST.cxx View File

name(strDup(name_)), pointerClient(0), comparer(0), name(strDup(name_)), pointerClient(0), comparer(0),
renderedCursorInvalid(false), renderedCursorInvalid(false),
queryConnectionHandler(0), keyRemapper(&KeyRemapper::defInstance), queryConnectionHandler(0), keyRemapper(&KeyRemapper::defInstance),
useEconomicTranslate(false),
lastConnectionTime(0), disableclients(false), lastConnectionTime(0), disableclients(false),
deferTimer(this), deferPending(false) deferTimer(this), deferPending(false)
{ {

+ 1
- 8
common/rfb/VNCServerST.h View File

// Blacklist to be shared by multiple VNCServerST instances. // Blacklist to be shared by multiple VNCServerST instances.
void setBlacklist(Blacklist* bl) {blHosts = bl ? bl : &blacklist;} void setBlacklist(Blacklist* bl) {blHosts = bl ? bl : &blacklist;}


// setEconomicTranslate() determines (for new connections) whether pixels
// should be translated for <=16bpp clients using a large lookup table
// (fast) or separate, smaller R, G and B tables (slower). If set to true,
// small tables are used, to save memory.
void setEconomicTranslate(bool et) { useEconomicTranslate = et; }

// setKeyRemapper() replaces the VNCServerST's default key remapper. // setKeyRemapper() replaces the VNCServerST's default key remapper.
// NB: A null pointer is valid here. // NB: A null pointer is valid here.
void setKeyRemapper(KeyRemapper* kr) { keyRemapper = kr; } void setKeyRemapper(KeyRemapper* kr) { keyRemapper = kr; }


QueryConnectionHandler* queryConnectionHandler; QueryConnectionHandler* queryConnectionHandler;
KeyRemapper* keyRemapper; KeyRemapper* keyRemapper;
bool useEconomicTranslate;

time_t lastUserInputTime; time_t lastUserInputTime;
time_t lastDisconnectTime; time_t lastDisconnectTime;
time_t lastConnectionTime; time_t lastConnectionTime;

+ 9
- 10
common/rfb/ZRLEDecoder.cxx View File

*/ */
#include <rfb/CMsgReader.h> #include <rfb/CMsgReader.h>
#include <rfb/CConnection.h> #include <rfb/CConnection.h>
#include <rfb/CMsgHandler.h>
#include <rfb/PixelBuffer.h>
#include <rfb/ZRLEDecoder.h> #include <rfb/ZRLEDecoder.h>


using namespace rfb; using namespace rfb;
{ {
} }


void ZRLEDecoder::readRect(const Rect& r, CMsgHandler* handler)
void ZRLEDecoder::readRect(const Rect& r, ModifiablePixelBuffer* pb)
{ {
rdr::InStream* is = conn->getInStream(); rdr::InStream* is = conn->getInStream();
rdr::U8* buf = conn->reader()->getImageBuf(64 * 64 * 4); 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;
const rfb::PixelFormat& pf = conn->cp.pf();
switch (pf.bpp) {
case 8: zrleDecode8 (r, is, &zis, (rdr::U8*) buf, pf, pb); break;
case 16: zrleDecode16(r, is, &zis, (rdr::U16*)buf, pf, pb); break;
case 32: case 32:
{ {
const rfb::PixelFormat& pf = handler->cp.pf();

Pixel maxPixel = pf.pixelFromRGB((rdr::U16)-1, (rdr::U16)-1, (rdr::U16)-1); Pixel maxPixel = pf.pixelFromRGB((rdr::U16)-1, (rdr::U16)-1, (rdr::U16)-1);
bool fitsInLS3Bytes = maxPixel < (1<<24); bool fitsInLS3Bytes = maxPixel < (1<<24);
bool fitsInMS3Bytes = (maxPixel & 0xff) == 0; bool fitsInMS3Bytes = (maxPixel & 0xff) == 0;
if ((fitsInLS3Bytes && pf.isLittleEndian()) || if ((fitsInLS3Bytes && pf.isLittleEndian()) ||
(fitsInMS3Bytes && pf.isBigEndian())) (fitsInMS3Bytes && pf.isBigEndian()))
{ {
zrleDecode24A(r, is, &zis, (rdr::U32*)buf, handler);
zrleDecode24A(r, is, &zis, (rdr::U32*)buf, pf, pb);
} }
else if ((fitsInLS3Bytes && pf.isBigEndian()) || else if ((fitsInLS3Bytes && pf.isBigEndian()) ||
(fitsInMS3Bytes && pf.isLittleEndian())) (fitsInMS3Bytes && pf.isLittleEndian()))
{ {
zrleDecode24B(r, is, &zis, (rdr::U32*)buf, handler);
zrleDecode24B(r, is, &zis, (rdr::U32*)buf, pf, pb);
} }
else else
{ {
zrleDecode32(r, is, &zis, (rdr::U32*)buf, handler);
zrleDecode32(r, is, &zis, (rdr::U32*)buf, pf, pb);
} }
break; break;
} }

+ 1
- 1
common/rfb/ZRLEDecoder.h View File

public: public:
ZRLEDecoder(CConnection* conn); ZRLEDecoder(CConnection* conn);
virtual ~ZRLEDecoder(); virtual ~ZRLEDecoder();
virtual void readRect(const Rect& r, CMsgHandler* handler);
virtual void readRect(const Rect& r, ModifiablePixelBuffer* pb);
private: private:
rdr::ZlibInStream zis; rdr::ZlibInStream zis;
}; };

+ 9
- 10
common/rfb/ZRLEEncoder.cxx View File

*/ */
#include <rdr/OutStream.h> #include <rdr/OutStream.h>
#include <rfb/Exception.h> #include <rfb/Exception.h>
#include <rfb/TransImageGetter.h>
#include <rfb/encodings.h> #include <rfb/encodings.h>
#include <rfb/ConnParams.h> #include <rfb/ConnParams.h>
#include <rfb/SMsgWriter.h> #include <rfb/SMsgWriter.h>
{ {
} }


void ZRLEEncoder::writeRect(const Rect& r, TransImageGetter* ig)
void ZRLEEncoder::writeRect(const Rect& r, PixelBuffer* pb)
{ {
const PixelFormat& pf = conn->cp.pf();

rdr::U8* imageBuf = conn->writer()->getImageBuf(64 * 64 * 4 + 4); rdr::U8* imageBuf = conn->writer()->getImageBuf(64 * 64 * 4 + 4);
mos.clear(); mos.clear();


switch (conn->cp.pf().bpp) {
switch (pf.bpp) {
case 8: case 8:
zrleEncode8(r, &mos, &zos, imageBuf, ig);
zrleEncode8(r, &mos, &zos, imageBuf, pf, pb);
break; break;
case 16: case 16:
zrleEncode16(r, &mos, &zos, imageBuf, ig);
zrleEncode16(r, &mos, &zos, imageBuf, pf, pb);
break; break;
case 32: case 32:
{ {
const PixelFormat& pf = conn->cp.pf();

Pixel maxPixel = pf.pixelFromRGB((rdr::U16)-1, (rdr::U16)-1, (rdr::U16)-1); Pixel maxPixel = pf.pixelFromRGB((rdr::U16)-1, (rdr::U16)-1, (rdr::U16)-1);
bool fitsInLS3Bytes = maxPixel < (1<<24); bool fitsInLS3Bytes = maxPixel < (1<<24);
bool fitsInMS3Bytes = (maxPixel & 0xff) == 0; bool fitsInMS3Bytes = (maxPixel & 0xff) == 0;
if ((fitsInLS3Bytes && pf.isLittleEndian()) || if ((fitsInLS3Bytes && pf.isLittleEndian()) ||
(fitsInMS3Bytes && pf.isBigEndian())) (fitsInMS3Bytes && pf.isBigEndian()))
{ {
zrleEncode24A(r, &mos, &zos, imageBuf, ig);
zrleEncode24A(r, &mos, &zos, imageBuf, pf, pb);
} }
else if ((fitsInLS3Bytes && pf.isBigEndian()) || else if ((fitsInLS3Bytes && pf.isBigEndian()) ||
(fitsInMS3Bytes && pf.isLittleEndian())) (fitsInMS3Bytes && pf.isLittleEndian()))
{ {
zrleEncode24B(r, &mos, &zos, imageBuf, ig);
zrleEncode24B(r, &mos, &zos, imageBuf, pf, pb);
} }
else else
{ {
zrleEncode32(r, &mos, &zos, imageBuf, ig);
zrleEncode32(r, &mos, &zos, imageBuf, pf, pb);
} }
break; break;
} }

+ 1
- 1
common/rfb/ZRLEEncoder.h View File

public: public:
ZRLEEncoder(SConnection* conn); ZRLEEncoder(SConnection* conn);
virtual ~ZRLEEncoder(); virtual ~ZRLEEncoder();
virtual void writeRect(const Rect& r, TransImageGetter* ig);
virtual void writeRect(const Rect& r, PixelBuffer* pb);
private: private:
rdr::ZlibOutStream zos; rdr::ZlibOutStream zos;
rdr::MemOutStream mos; rdr::MemOutStream mos;

+ 3
- 3
common/rfb/hextileDecode.h View File

#define HEXTILE_DECODE CONCAT2E(hextileDecode,BPP) #define HEXTILE_DECODE CONCAT2E(hextileDecode,BPP)


void HEXTILE_DECODE (const Rect& r, rdr::InStream* is, PIXEL_T* buf, void HEXTILE_DECODE (const Rect& r, rdr::InStream* is, PIXEL_T* buf,
CMsgHandler* handler)
const PixelFormat& pf, ModifiablePixelBuffer* pb)
{ {
Rect t; Rect t;
PIXEL_T bg = 0; PIXEL_T bg = 0;


if (tileType & hextileRaw) { if (tileType & hextileRaw) {
is->readBytes(buf, t.area() * (BPP/8)); is->readBytes(buf, t.area() * (BPP/8));
handler->imageRect(t, buf);
pb->imageRect(pf, t, buf);
continue; continue;
} }


} }
} }
} }
handler->imageRect(t, buf);
pb->imageRect(pf, t, buf);
} }
} }
} }

+ 4
- 3
common/rfb/hextileEncode.h View File

int HEXTILE_ENCODE_TILE (PIXEL_T* data, int w, int h, int tileType, int HEXTILE_ENCODE_TILE (PIXEL_T* data, int w, int h, int tileType,
rdr::U8* encoded, PIXEL_T bg); rdr::U8* encoded, PIXEL_T bg);


void HEXTILE_ENCODE(const Rect& r, rdr::OutStream* os, TransImageGetter *ig)
void HEXTILE_ENCODE(const Rect& r, rdr::OutStream* os,
const PixelFormat& pf, PixelBuffer* pb)
{ {
Rect t; Rect t;
PIXEL_T buf[256]; PIXEL_T buf[256];


t.br.x = __rfbmin(r.br.x, t.tl.x + 16); t.br.x = __rfbmin(r.br.x, t.tl.x + 16);


ig->getImage(buf, t);
pb->getImage(pf, buf, t);


PIXEL_T bg = 0, fg = 0; PIXEL_T bg = 0, fg = 0;
int tileType = TEST_TILE_TYPE(buf, t.width(), t.height(), &bg, &fg); int tileType = TEST_TILE_TYPE(buf, t.width(), t.height(), &bg, &fg);
encoded, bg); encoded, bg);


if (encodedLen < 0) { if (encodedLen < 0) {
ig->getImage(buf, t);
pb->getImage(pf, buf, t);
os->writeU8(hextileRaw); os->writeU8(hextileRaw);
os->writeBytes(buf, t.width() * t.height() * (BPP/8)); os->writeBytes(buf, t.width() * t.height() * (BPP/8));
oldBgValid = oldFgValid = false; oldBgValid = oldFgValid = false;

+ 3
- 2
common/rfb/hextileEncodeBetter.h View File

// Main encoding function. // Main encoding function.
// //


void HEXTILE_ENCODE(const Rect& r, rdr::OutStream* os, TransImageGetter *ig)
void HEXTILE_ENCODE(const Rect& r, rdr::OutStream* os,
const PixelFormat& pf, PixelBuffer* pb)
{ {
Rect t; Rect t;
PIXEL_T buf[256]; PIXEL_T buf[256];


t.br.x = __rfbmin(r.br.x, t.tl.x + 16); t.br.x = __rfbmin(r.br.x, t.tl.x + 16);


ig->getImage(buf, t);
pb->getImage(pf, buf, t);


tile.newTile(buf, t.width(), t.height()); tile.newTile(buf, t.width(), t.height());
int tileType = tile.getFlags(); int tileType = tile.getFlags();

+ 4
- 3
common/rfb/rreDecode.h View File

#define READ_PIXEL CONCAT2E(readOpaque,BPP) #define READ_PIXEL CONCAT2E(readOpaque,BPP)
#define RRE_DECODE CONCAT2E(rreDecode,BPP) #define RRE_DECODE CONCAT2E(rreDecode,BPP)


void RRE_DECODE (const Rect& r, rdr::InStream* is, CMsgHandler* handler)
void RRE_DECODE (const Rect& r, rdr::InStream* is,
const PixelFormat& pf, ModifiablePixelBuffer* pb)
{ {
int nSubrects = is->readU32(); int nSubrects = is->readU32();
PIXEL_T bg = is->READ_PIXEL(); PIXEL_T bg = is->READ_PIXEL();
handler->fillRect(r, bg);
pb->fillRect(pf, r, bg);


for (int i = 0; i < nSubrects; i++) { for (int i = 0; i < nSubrects; i++) {
PIXEL_T pix = is->READ_PIXEL(); PIXEL_T pix = is->READ_PIXEL();
int y = is->readU16(); int y = is->readU16();
int w = is->readU16(); int w = is->readU16();
int h = is->readU16(); int h = is->readU16();
handler->fillRect(Rect(r.tl.x+x, r.tl.y+y, r.tl.x+x+w, r.tl.y+y+h), pix);
pb->fillRect(pf, Rect(r.tl.x+x, r.tl.y+y, r.tl.x+x+w, r.tl.y+y+h), pix);
} }
} }



+ 6
- 6
common/rfb/tightDecode.h View File

} else { } else {
pix = is->READ_PIXEL(); pix = is->READ_PIXEL();
} }
handler->fillRect(r, pix);
pb->fillRect(serverpf, r, pix);
return; return;
} }




PIXEL_T *buf; PIXEL_T *buf;
int stride = r.width(); int stride = r.width();
if (directDecode) buf = (PIXEL_T *)handler->getRawBufferRW(r, &stride);
if (directDecode) buf = (PIXEL_T *)pb->getBufferRW(r, &stride);
else buf = (PIXEL_T *)conn->reader()->getImageBuf(r.area()); else buf = (PIXEL_T *)conn->reader()->getImageBuf(r.area());


if (palSize == 0) { if (palSize == 0) {
} }
} }


if (directDecode) handler->releaseRawBuffer(r);
else handler->imageRect(r, buf);
if (directDecode) pb->commitBufferRW(r);
else pb->imageRect(serverpf, r, buf);


delete [] netbuf; delete [] netbuf;




// We always use direct decoding with JPEG images // We always use direct decoding with JPEG images
int stride; int stride;
rdr::U8 *buf = handler->getRawBufferRW(r, &stride);
rdr::U8 *buf = pb->getBufferRW(r, &stride);
jd.decompress(netbuf, compressedLen, buf, stride, r, clientpf); jd.decompress(netbuf, compressedLen, buf, stride, r, clientpf);
handler->releaseRawBuffer(r);
pb->commitBufferRW(r);


delete [] netbuf; delete [] netbuf;
} }

+ 11
- 10
common/rfb/tightEncode.h View File

{ {
int stride; int stride;
rdr::U32 solidColor; rdr::U32 solidColor;
const PIXEL_T *rawPixels = (const PIXEL_T *)ig->getRawBufferR(r, &stride);
const PIXEL_T *rawPixels = (const PIXEL_T *)pb->getBuffer(r, &stride);
PIXEL_T *pixels = NULL; PIXEL_T *pixels = NULL;
bool grayScaleJPEG = (jpegSubsampling == subsampleGray && jpegQuality != -1); bool grayScaleJPEG = (jpegSubsampling == subsampleGray && jpegQuality != -1);




if (forceSolid) { if (forceSolid) {
// Subrectangle has already been determined to be solid. // Subrectangle has already been determined to be solid.
ig->translatePixels(rawPixels, &solidColor, 1);
clientpf.bufferFromBuffer((rdr::U8*)&solidColor, serverpf,
(const rdr::U8*)rawPixels, 1);
pixels = (PIXEL_T *)&solidColor; pixels = (PIXEL_T *)&solidColor;
palette.clear(); palette.clear();
palette.insert(solidColor, 1); palette.insert(solidColor, 1);
if(palette.size() != 0 || jpegQuality == -1) { if(palette.size() != 0 || jpegQuality == -1) {
pixels = (PIXEL_T *)conn->writer()->getImageBuf(r.area()); pixels = (PIXEL_T *)conn->writer()->getImageBuf(r.area());
stride = r.width(); stride = r.width();
ig->getImage(pixels, r);
pb->getImage(clientpf, pixels, r);
} }
} else { } else {
// Pixel translation will be required, so create an intermediate buffer, // Pixel translation will be required, so create an intermediate buffer,
// translate the raw pixels into it, and count its colors. // translate the raw pixels into it, and count its colors.
pixels = (PIXEL_T *)conn->writer()->getImageBuf(r.area()); pixels = (PIXEL_T *)conn->writer()->getImageBuf(r.area());
stride = r.width(); stride = r.width();
ig->getImage(pixels, r);
pb->getImage(clientpf, pixels, r);


if (grayScaleJPEG) palette.clear(); if (grayScaleJPEG) palette.clear();
else FILL_PALETTE(pixels, r.area()); else FILL_PALETTE(pixels, r.area());
int w = r.width(), h = r.height(); int w = r.width(), h = r.height();
const PIXEL_T *rowptr, *colptr, *rowptr2, *colptr2, const PIXEL_T *rowptr, *colptr, *rowptr2, *colptr2,
*dataend = &data[stride * h]; *dataend = &data[stride * h];
bool willTransform = ig->willTransform();
bool willTransform = !serverpf.equal(clientpf);


serverpf.bufferFromPixel((rdr::U8*)&mask, ~0); serverpf.bufferFromPixel((rdr::U8*)&mask, ~0);




monodone: monodone:
if (willTransform) { if (willTransform) {
ig->translatePixels(&c0, &c0t, 1);
ig->translatePixels(&c1, &c1t, 1);
clientpf.bufferFromBuffer((rdr::U8*)&c0t, serverpf, (rdr::U8*)&c0, 1);
clientpf.bufferFromBuffer((rdr::U8*)&c1t, serverpf, (rdr::U8*)&c1, 1);
} }
else { else {
c0t = c0; c1t = c1; c0t = c0; c1t = c1;
ni++; ni++;
} else { } else {
if (willTransform) if (willTransform)
ig->translatePixels(&ci, &cit, 1);
clientpf.bufferFromBuffer((rdr::U8*)&cit, serverpf, (rdr::U8*)&ci, 1);
else else
cit = ci; cit = ci;
if (!palette.insert (cit, ni) || (palette.size() > palMaxColors)) { if (!palette.insert (cit, ni) || (palette.size() > palMaxColors)) {
rowptr += stride; rowptr += stride;
colptr = rowptr; colptr = rowptr;
} }
ig->translatePixels(&ci, &cit, 1);
clientpf.bufferFromBuffer((rdr::U8*)&cit, serverpf, (rdr::U8*)&ci, 1);
if (!palette.insert (cit, ni) || (palette.size() > palMaxColors)) if (!palette.insert (cit, ni) || (palette.size() > palMaxColors))
palette.clear(); palette.clear();
} }
int w = r.width(), h = r.height(); int w = r.width(), h = r.height();


int stride = w; int stride = w;
buf = (const PIXEL_T *)ig->getRawBufferR(r, &stride);
buf = (const PIXEL_T *)pb->getBuffer(r, &stride);


colorValue = *buf; colorValue = *buf;
if (needSameColor && (rdr::U32)colorValue != *colorPtr) if (needSameColor && (rdr::U32)colorValue != *colorPtr)

+ 3
- 3
common/rfb/zrleDecode.h View File



void ZRLE_DECODE (const Rect& r, rdr::InStream* is, void ZRLE_DECODE (const Rect& r, rdr::InStream* is,
rdr::ZlibInStream* zis, PIXEL_T* buf, rdr::ZlibInStream* zis, PIXEL_T* buf,
CMsgHandler* handler)
const PixelFormat& pf, ModifiablePixelBuffer* pb)
{ {
int length = is->readU32(); int length = is->readU32();
zis->setUnderlying(is, length); zis->setUnderlying(is, length);


if (palSize == 1) { if (palSize == 1) {
PIXEL_T pix = palette[0]; PIXEL_T pix = palette[0];
handler->fillRect(t, pix);
pb->fillRect(pf, t, pix);
continue; continue;
} }




//fprintf(stderr,"copying data to screen %dx%d at %d,%d\n", //fprintf(stderr,"copying data to screen %dx%d at %d,%d\n",
//t.width(),t.height(),t.tl.x,t.tl.y); //t.width(),t.height(),t.tl.x,t.tl.y);
handler->imageRect(t, buf);
pb->imageRect(pf, t, buf);
} }
} }



+ 3
- 2
common/rfb/zrleEncode.h View File

#include <rdr/OutStream.h> #include <rdr/OutStream.h>
#include <rdr/ZlibOutStream.h> #include <rdr/ZlibOutStream.h>
#include <rfb/Palette.h> #include <rfb/Palette.h>
#include <rfb/PixelBuffer.h>
#include <assert.h> #include <assert.h>


namespace rfb { namespace rfb {


void ZRLE_ENCODE (const Rect& r, rdr::OutStream* os, void ZRLE_ENCODE (const Rect& r, rdr::OutStream* os,
rdr::ZlibOutStream* zos, void* buf, rdr::ZlibOutStream* zos, void* buf,
TransImageGetter *ig)
const PixelFormat& pf, PixelBuffer* pb)
{ {
zos->setUnderlying(os); zos->setUnderlying(os);
// RLE overhead is at worst 1 byte per 64x64 (4Kpixel) block // RLE overhead is at worst 1 byte per 64x64 (4Kpixel) block


t.br.x = __rfbmin(r.br.x, t.tl.x + 64); t.br.x = __rfbmin(r.br.x, t.tl.x + 64);


ig->getImage(buf, t);
pb->getImage(pf, buf, t);


ZRLE_ENCODE_TILE((PIXEL_T*)buf, t.width(), t.height(), zos); ZRLE_ENCODE_TILE((PIXEL_T*)buf, t.width(), t.height(), zos);
} }

+ 1
- 26
vncviewer/CConn.cxx View File

// This initial update request is a bit of a corner case, so we need // This initial update request is a bit of a corner case, so we need
// to help out setting the correct format here. // to help out setting the correct format here.
assert(pendingPFChange); assert(pendingPFChange);
desktop->setServerPF(pendingPF);
cp.setPF(pendingPF); cp.setPF(pendingPF);
pendingPFChange = false; pendingPFChange = false;
} }
// A format change has been scheduled and we are now past the update // A format change has been scheduled and we are now past the update
// with the old format. Time to active the new one. // with the old format. Time to active the new one.
if (pendingPFChange) { if (pendingPFChange) {
desktop->setServerPF(pendingPF);
cp.setPF(pendingPF); cp.setPF(pendingPF);
pendingPFChange = false; pendingPFChange = false;
} }
throw Exception("Unknown rect encoding"); throw Exception("Unknown rect encoding");
} }
} }
decoders[encoding]->readRect(r, this);
decoders[encoding]->readRect(r, desktop->getFramebuffer());


sock->inStream().stopTiming(); sock->inStream().stopTiming();
} }


void CConn::fillRect(const rfb::Rect& r, rfb::Pixel p)
{
desktop->fillRect(r,p);
}

void CConn::imageRect(const rfb::Rect& r, void* p)
{
desktop->imageRect(r,p);
}

void CConn::copyRect(const rfb::Rect& r, int sx, int sy)
{
desktop->copyRect(r,sx,sy);
}

void CConn::setCursor(int width, int height, const Point& hotspot, void CConn::setCursor(int width, int height, const Point& hotspot,
void* data, void* mask) void* data, void* mask)
{ {


pf.read(&memStream); pf.read(&memStream);


desktop->setServerPF(pf);
cp.setPF(pf); cp.setPF(pf);
} }
} }


rdr::U8* CConn::getRawBufferRW(const rfb::Rect& r, int* stride) {
return desktop->getBufferRW(r, stride);
}
void CConn::releaseRawBuffer(const rfb::Rect& r) {
desktop->commitBufferRW(r);
}



////////////////////// Internal methods ////////////////////// ////////////////////// Internal methods //////////////////////



+ 0
- 10
vncviewer/CConn.h View File



void framebufferUpdateStart(); void framebufferUpdateStart();
void framebufferUpdateEnd(); void framebufferUpdateEnd();

void dataRect(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);
void copyRect(const rfb::Rect& r, int sx, int sy);

rdr::U8* getRawBufferRW(const rfb::Rect& r, int* stride);
void releaseRawBuffer(const rfb::Rect& r);

const rfb::PixelFormat &getPreferredPF() { return fullColourPF; }

void setCursor(int width, int height, const rfb::Point& hotspot, void setCursor(int width, int height, const rfb::Point& hotspot,
void* data, void* mask); void* data, void* mask);



+ 3
- 24
vncviewer/DesktopWindow.cxx View File

} }




void DesktopWindow::setServerPF(const rfb::PixelFormat& pf)
{
viewport->setServerPF(pf);
}


const rfb::PixelFormat &DesktopWindow::getPreferredPF() const rfb::PixelFormat &DesktopWindow::getPreferredPF()
{ {
return viewport->getPreferredPF(); return viewport->getPreferredPF();
} }




void DesktopWindow::fillRect(const rfb::Rect& r, rfb::Pixel pix) {
viewport->fillRect(r, pix);
}

void DesktopWindow::imageRect(const rfb::Rect& r, void* pixels) {
viewport->imageRect(r, pixels);
}

void DesktopWindow::copyRect(const rfb::Rect& r, int srcX, int srcY) {
viewport->copyRect(r, srcX, srcY);
}

rdr::U8* DesktopWindow::getBufferRW(const rfb::Rect& r, int* stride) {
return viewport->getBufferRW(r, stride);
}

void DesktopWindow::commitBufferRW(const rfb::Rect& r) {
viewport->commitBufferRW(r);
rfb::ModifiablePixelBuffer* DesktopWindow::getFramebuffer(void)
{
return viewport->getFramebuffer();
} }





+ 7
- 9
vncviewer/DesktopWindow.h View File



#include <FL/Fl_Window.H> #include <FL/Fl_Window.H>


namespace rfb { class ModifiablePixelBuffer; }

class CConn; class CConn;
class Viewport; class Viewport;


const rfb::PixelFormat& serverPF, CConn* cc_); const rfb::PixelFormat& serverPF, CConn* cc_);
~DesktopWindow(); ~DesktopWindow();


// PixelFormat of incoming write operations
void setServerPF(const rfb::PixelFormat& pf);
// Most efficient format (from DesktopWindow's point of view) // Most efficient format (from DesktopWindow's point of view)
const rfb::PixelFormat &getPreferredPF(); const rfb::PixelFormat &getPreferredPF();


// Flush updates to screen // Flush updates to screen
void updateWindow(); void updateWindow();


// Methods forwarded from CConn
// Updated session title
void setName(const char *name); void setName(const char *name);


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);

rdr::U8* getBufferRW(const rfb::Rect& r, int* stride);
void commitBufferRW(const rfb::Rect& r);
// Return a pointer to the framebuffer for decoders to write into
rfb::ModifiablePixelBuffer* getFramebuffer(void);


// Resize the current framebuffer, but retain the contents
void resizeFramebuffer(int new_w, int new_h); void resizeFramebuffer(int new_w, int new_h);


// New image for the locally rendered cursor
void setCursor(int width, int height, const rfb::Point& hotspot, void setCursor(int width, int height, const rfb::Point& hotspot,
void* data, void* mask); void* data, void* mask);



+ 16
- 0
vncviewer/PlatformPixelBuffer.cxx View File

FullFramePixelBuffer(pf, width, height, data, stride) FullFramePixelBuffer(pf, width, height, data, stride)
{ {
} }

void PlatformPixelBuffer::commitBufferRW(const rfb::Rect& r)
{
FullFramePixelBuffer::commitBufferRW(r);
damage.assign_union(rfb::Region(r));
}

rfb::Rect PlatformPixelBuffer::getDamage(void)
{
rfb::Rect r;

r = damage.get_bounding_rect();
damage.clear();

return r;
}

+ 6
- 0
vncviewer/PlatformPixelBuffer.h View File

#define __PLATFORMPIXELBUFFER_H__ #define __PLATFORMPIXELBUFFER_H__


#include <rfb/PixelBuffer.h> #include <rfb/PixelBuffer.h>
#include <rfb/Region.h>


class PlatformPixelBuffer: public rfb::FullFramePixelBuffer { class PlatformPixelBuffer: public rfb::FullFramePixelBuffer {
public: public:
PlatformPixelBuffer(const rfb::PixelFormat& pf, int width, int height, PlatformPixelBuffer(const rfb::PixelFormat& pf, int width, int height,
rdr::U8* data, int stride); rdr::U8* data, int stride);


virtual void commitBufferRW(const rfb::Rect& r);

virtual void draw(int src_x, int src_y, int x, int y, int w, int h) = 0; virtual void draw(int src_x, int src_y, int x, int y, int w, int h) = 0;
rfb::Rect getDamage(void);


protected:
rfb::Region damage;
}; };


#endif #endif

+ 8
- 106
vncviewer/Viewport.cxx View File



#include <rfb/CMsgWriter.h> #include <rfb/CMsgWriter.h>
#include <rfb/LogWriter.h> #include <rfb/LogWriter.h>
#include <rfb/PixelTransformer.h>


// FLTK can pull in the X11 headers on some systems // FLTK can pull in the X11 headers on some systems
#ifndef XK_VoidSymbol #ifndef XK_VoidSymbol
ID_REFRESH, ID_OPTIONS, ID_INFO, ID_ABOUT, ID_DISMISS }; ID_REFRESH, ID_OPTIONS, ID_INFO, ID_ABOUT, ID_DISMISS };


Viewport::Viewport(int w, int h, const rfb::PixelFormat& serverPF, CConn* cc_) Viewport::Viewport(int w, int h, const rfb::PixelFormat& serverPF, CConn* cc_)
: Fl_Widget(0, 0, w, h), cc(cc_), frameBuffer(NULL), pixelTrans(NULL),
: Fl_Widget(0, 0, w, h), cc(cc_), frameBuffer(NULL),
lastPointerPos(0, 0), lastButtonMask(0), lastPointerPos(0, 0), lastButtonMask(0),
cursor(NULL), menuCtrlKey(false), menuAltKey(false) cursor(NULL), menuCtrlKey(false), menuAltKey(false)
{ {
frameBuffer = createFramebuffer(w, h); frameBuffer = createFramebuffer(w, h);
assert(frameBuffer); assert(frameBuffer);


setServerPF(serverPF);

contextMenu = new Fl_Menu_Button(0, 0, 0, 0); contextMenu = new Fl_Menu_Button(0, 0, 0, 0);
// Setting box type to FL_NO_BOX prevents it from trying to draw the // Setting box type to FL_NO_BOX prevents it from trying to draw the
// button component (which we don't want) // button component (which we don't want)
{ {
// Unregister all timeouts in case they get a change tro trigger // Unregister all timeouts in case they get a change tro trigger
// again later when this object is already gone. // again later when this object is already gone.
Fl::remove_timeout(handleUpdateTimeout, this);
Fl::remove_timeout(handlePointerTimeout, this); Fl::remove_timeout(handlePointerTimeout, this);


#ifdef HAVE_FLTK_CLIPBOARD #ifdef HAVE_FLTK_CLIPBOARD


delete frameBuffer; delete frameBuffer;


if (pixelTrans)
delete pixelTrans;

if (cursor) { if (cursor) {
if (!cursor->alloc_array) if (!cursor->alloc_array)
delete [] cursor->array; delete [] cursor->array;
} }




void Viewport::setServerPF(const rfb::PixelFormat& pf)
{
if (pixelTrans)
delete pixelTrans;
pixelTrans = NULL;

if (pf.equal(getPreferredPF()))
return;

pixelTrans = new PixelTransformer();

// FIXME: This is an ugly (temporary) hack to get around a corner
// case during startup. The conversion routines cannot handle
// non-native source formats, and we can sometimes get that
// as the initial format. We will switch to a better format
// before getting any updates, but we need something for now.
// Our old client used something completely bogus and just
// hoped nothing would ever go wrong. We try to at least match
// the pixel size so that we don't get any memory access issues
// should a stray update appear.
static rdr::U32 endianTest = 1;
static bool nativeBigEndian = *(rdr::U8*)(&endianTest) != 1;
if ((pf.bpp > 8) && (pf.bigEndian != nativeBigEndian)) {
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, getPreferredPF());
return;
}

pixelTrans->init(pf, getPreferredPF());
}


const rfb::PixelFormat &Viewport::getPreferredPF() const rfb::PixelFormat &Viewport::getPreferredPF()
{ {
return frameBuffer->getPF(); return frameBuffer->getPF();


// Copy the areas of the framebuffer that have been changed (damaged) // Copy the areas of the framebuffer that have been changed (damaged)
// to the displayed window. // to the displayed window.
// FIXME: Make sure this gets called on slow updates


void Viewport::updateWindow() void Viewport::updateWindow()
{ {
Rect r; Rect r;


Fl::remove_timeout(handleUpdateTimeout, this);

r = damage.get_bounding_rect();
Fl_Widget::damage(FL_DAMAGE_USER1, r.tl.x + x(), r.tl.y + y(), r.width(), r.height());

damage.clear();
}

void Viewport::fillRect(const rfb::Rect& r, rfb::Pixel pix) {
if (pixelTrans) {
rfb::Pixel pix2;
pixelTrans->translatePixels(&pix, &pix2, 1);
pix = pix2;
}

frameBuffer->fillRect(r, pix);
damageRect(r);
r = frameBuffer->getDamage();
damage(FL_DAMAGE_USER1, r.tl.x + x(), r.tl.y + y(), r.width(), r.height());
} }


void Viewport::imageRect(const rfb::Rect& r, void* pixels) {
if (pixelTrans) {
rdr::U8* buffer;
int stride;
buffer = frameBuffer->getBufferRW(r, &stride);
pixelTrans->translateRect(pixels, r.width(),
rfb::Rect(0, 0, r.width(), r.height()),
buffer, stride, rfb::Point(0, 0));
frameBuffer->commitBufferRW(r);
} else {
frameBuffer->imageRect(r, pixels);
}
damageRect(r);
}

void Viewport::copyRect(const rfb::Rect& r, int srcX, int srcY) {
frameBuffer->copyRect(r, rfb::Point(r.tl.x-srcX, r.tl.y-srcY));
damageRect(r);
}

rdr::U8* Viewport::getBufferRW(const rfb::Rect& r, int* stride) {
return frameBuffer->getBufferRW(r, stride);
}

void Viewport::commitBufferRW(const rfb::Rect& r) {
frameBuffer->commitBufferRW(r);
damageRect(r);
rfb::ModifiablePixelBuffer* Viewport::getFramebuffer(void)
{
return frameBuffer;
} }


void Viewport::damageRect(const rfb::Rect& r) {
damage.assign_union(rfb::Region(r));
if (!Fl::has_timeout(handleUpdateTimeout, this))
Fl::add_timeout(0.500, handleUpdateTimeout, this);
};

#ifdef HAVE_FLTK_CURSOR #ifdef HAVE_FLTK_CURSOR
static const char * dotcursor_xpm[] = { static const char * dotcursor_xpm[] = {
"5 5 2 1", "5 5 2 1",


const PixelFormat *pf; const PixelFormat *pf;
if (pixelTrans)
pf = &pixelTrans->getInPF();
else
pf = &frameBuffer->getPF();
pf = &cc->cp.pf();


i = (U8*)data; i = (U8*)data;
o = buffer; o = buffer;
} }




void Viewport::handleUpdateTimeout(void *data)
{
Viewport *self = (Viewport *)data;

assert(self);

self->updateWindow();
}


void Viewport::handleClipboardChange(int source, void *data) void Viewport::handleClipboardChange(int source, void *data)
{ {
Viewport *self = (Viewport *)data; Viewport *self = (Viewport *)data;

+ 5
- 19
vncviewer/Viewport.h View File



#include <map> #include <map>


#include <FL/Fl_Widget.H>
namespace rfb { class ModifiablePixelBuffer; }


#include <rfb/Region.h>
#include <rfb/Pixel.h>
#include <FL/Fl_Widget.H>


class Fl_Menu_Button; class Fl_Menu_Button;
class Fl_RGB_Image; class Fl_RGB_Image;
Viewport(int w, int h, const rfb::PixelFormat& serverPF, CConn* cc_); Viewport(int w, int h, const rfb::PixelFormat& serverPF, CConn* cc_);
~Viewport(); ~Viewport();


// PixelFormat of incoming write operations
void setServerPF(const rfb::PixelFormat& pf);
// Most efficient format (from Viewport's point of view) // Most efficient format (from Viewport's point of view)
const rfb::PixelFormat &getPreferredPF(); const rfb::PixelFormat &getPreferredPF();


// Flush updates to screen // Flush updates to screen
void updateWindow(); void updateWindow();


// Methods forwarded from CConn

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);

rdr::U8* getBufferRW(const rfb::Rect& r, int* stride);
void commitBufferRW(const rfb::Rect& r);
// Return a pointer to the framebuffer for decoders to write into
rfb::ModifiablePixelBuffer* getFramebuffer(void);


// New image for the locally rendered cursor
void setCursor(int width, int height, const rfb::Point& hotspot, void setCursor(int width, int height, const rfb::Point& hotspot,
void* data, void* mask); void* data, void* mask);




private: private:


void damageRect(const rfb::Rect& r);

PlatformPixelBuffer* createFramebuffer(int w, int h); PlatformPixelBuffer* createFramebuffer(int w, int h);


static void handleUpdateTimeout(void *data);

static void handleClipboardChange(int source, void *data); static void handleClipboardChange(int source, void *data);


void handlePointerEvent(const rfb::Point& pos, int buttonMask); void handlePointerEvent(const rfb::Point& pos, int buttonMask);
CConn* cc; CConn* cc;


PlatformPixelBuffer* frameBuffer; PlatformPixelBuffer* frameBuffer;
rfb::PixelTransformer *pixelTrans;
rfb::Region damage;


rfb::Point lastPointerPos; rfb::Point lastPointerPos;
int lastButtonMask; int lastButtonMask;

Loading…
Cancel
Save