aboutsummaryrefslogtreecommitdiffstats
path: root/common/rfb
diff options
context:
space:
mode:
authorPierre Ossman <ossman@cendio.se>2018-09-20 10:52:15 +0200
committerPierre Ossman <ossman@cendio.se>2018-09-21 10:38:41 +0200
commitbeab2b6e4adcdab1fd71964c5ab7533c6050edbf (patch)
treedebf0b7f8ad3c74e45a9076531ec5f7b8db0468d /common/rfb
parentab9fd6b4d5060cd02bfad7846fa5164353f5c277 (diff)
downloadtigervnc-beab2b6e4adcdab1fd71964c5ab7533c6050edbf.tar.gz
tigervnc-beab2b6e4adcdab1fd71964c5ab7533c6050edbf.zip
Allow perceptually lossless refresh
Loosen the definition of "lossless" a bit so that we can use high quality JPEG to refresh damaged parts of the screen. Although this isn't bit perfect, it is close enough that most users will not be able to tell the difference. Level 9 is used rather than level 8 because some monitors have exaggerated contrast that allows the artefacts from level 8 to be noticeable.
Diffstat (limited to 'common/rfb')
-rw-r--r--common/rfb/EncodeManager.cxx32
-rw-r--r--common/rfb/Encoder.cxx6
-rw-r--r--common/rfb/Encoder.h7
-rw-r--r--common/rfb/TightJPEGEncoder.cxx3
4 files changed, 36 insertions, 12 deletions
diff --git a/common/rfb/EncodeManager.cxx b/common/rfb/EncodeManager.cxx
index d783d54b..02128f7f 100644
--- a/common/rfb/EncodeManager.cxx
+++ b/common/rfb/EncodeManager.cxx
@@ -364,6 +364,8 @@ void EncodeManager::prepareEncoders(bool allowLossy)
enum EncoderClass solid, bitmap, bitmapRLE;
enum EncoderClass indexed, indexedRLE, fullColour;
+ bool allowJPEG;
+
rdr::S32 preferred;
std::vector<int>::iterator iter;
@@ -371,6 +373,12 @@ void EncodeManager::prepareEncoders(bool allowLossy)
solid = bitmap = bitmapRLE = encoderRaw;
indexed = indexedRLE = fullColour = encoderRaw;
+ allowJPEG = conn->cp.pf().bpp >= 16;
+ if (!allowLossy) {
+ if (encoders[encoderTightJPEG]->losslessQuality == -1)
+ allowJPEG = false;
+ }
+
// Try to respect the client's wishes
preferred = conn->getPreferredEncoding();
switch (preferred) {
@@ -383,8 +391,7 @@ void EncodeManager::prepareEncoders(bool allowLossy)
bitmapRLE = indexedRLE = fullColour = encoderHextile;
break;
case encodingTight:
- if (encoders[encoderTightJPEG]->isSupported() &&
- (conn->cp.pf().bpp >= 16) && allowLossy)
+ if (encoders[encoderTightJPEG]->isSupported() && allowJPEG)
fullColour = encoderTightJPEG;
else
fullColour = encoderTight;
@@ -401,8 +408,7 @@ void EncodeManager::prepareEncoders(bool allowLossy)
// Any encoders still unassigned?
if (fullColour == encoderRaw) {
- if (encoders[encoderTightJPEG]->isSupported() &&
- (conn->cp.pf().bpp >= 16) && allowLossy)
+ if (encoders[encoderTightJPEG]->isSupported() && allowJPEG)
fullColour = encoderTightJPEG;
else if (encoders[encoderZRLE]->isSupported())
fullColour = encoderZRLE;
@@ -460,9 +466,17 @@ void EncodeManager::prepareEncoders(bool allowLossy)
encoder = encoders[*iter];
encoder->setCompressLevel(conn->cp.compressLevel);
- encoder->setQualityLevel(conn->cp.qualityLevel);
- encoder->setFineQualityLevel(conn->cp.fineQualityLevel,
- conn->cp.subsampling);
+
+ if (allowLossy) {
+ encoder->setQualityLevel(conn->cp.qualityLevel);
+ encoder->setFineQualityLevel(conn->cp.fineQualityLevel,
+ conn->cp.subsampling);
+ } else {
+ int level = __rfbmax(conn->cp.qualityLevel,
+ encoder->losslessQuality);
+ encoder->setQualityLevel(level);
+ encoder->setFineQualityLevel(-1, subsampleUndefined);
+ }
}
}
@@ -567,7 +581,9 @@ Encoder *EncodeManager::startRect(const Rect& rect, int type)
encoder = encoders[klass];
conn->writer()->startRect(rect, encoder->encoding);
- if (encoder->flags & EncoderLossy)
+ if ((encoder->flags & EncoderLossy) &&
+ ((encoder->losslessQuality == -1) ||
+ (encoder->getQualityLevel() < encoder->losslessQuality)))
lossyRegion.assign_union(Region(rect));
else
lossyRegion.assign_subtract(Region(rect));
diff --git a/common/rfb/Encoder.cxx b/common/rfb/Encoder.cxx
index 18b66809..0e29f1df 100644
--- a/common/rfb/Encoder.cxx
+++ b/common/rfb/Encoder.cxx
@@ -24,9 +24,11 @@
using namespace rfb;
Encoder::Encoder(SConnection *conn_, int encoding_,
- enum EncoderFlags flags_, unsigned int maxPaletteSize_) :
+ enum EncoderFlags flags_,
+ unsigned int maxPaletteSize_, int losslessQuality_) :
encoding(encoding_), flags(flags_),
- maxPaletteSize(maxPaletteSize_), conn(conn_)
+ maxPaletteSize(maxPaletteSize_), losslessQuality(losslessQuality_),
+ conn(conn_)
{
}
diff --git a/common/rfb/Encoder.h b/common/rfb/Encoder.h
index e135ec0e..d5a0288e 100644
--- a/common/rfb/Encoder.h
+++ b/common/rfb/Encoder.h
@@ -42,7 +42,8 @@ namespace rfb {
class Encoder {
public:
Encoder(SConnection* conn, int encoding,
- enum EncoderFlags flags, unsigned int maxPaletteSize=-1);
+ enum EncoderFlags flags, unsigned int maxPaletteSize=-1,
+ int losslessQuality=-1);
virtual ~Encoder();
// isSupported() should return a boolean indicating if this encoder
@@ -95,6 +96,10 @@ namespace rfb {
// Maximum size of the palette per rect
const unsigned int maxPaletteSize;
+ // Minimum level where the quality loss will not be noticed by
+ // most users (only relevant with EncoderLossy flag)
+ const int losslessQuality;
+
protected:
SConnection* conn;
};
diff --git a/common/rfb/TightJPEGEncoder.cxx b/common/rfb/TightJPEGEncoder.cxx
index bbe4f8fa..38cb4eb7 100644
--- a/common/rfb/TightJPEGEncoder.cxx
+++ b/common/rfb/TightJPEGEncoder.cxx
@@ -64,7 +64,8 @@ static const struct TightJPEGConfiguration conf[10] = {
TightJPEGEncoder::TightJPEGEncoder(SConnection* conn) :
- Encoder(conn, encodingTight, (EncoderFlags)(EncoderUseNativePF | EncoderLossy)),
+ Encoder(conn, encodingTight,
+ (EncoderFlags)(EncoderUseNativePF | EncoderLossy), -1, 9),
qualityLevel(-1), fineQuality(-1), fineSubsampling(subsampleUndefined)
{
}