aboutsummaryrefslogtreecommitdiffstats
path: root/common/rfb
diff options
context:
space:
mode:
Diffstat (limited to 'common/rfb')
-rw-r--r--common/rfb/ComparingUpdateTracker.cxx49
-rw-r--r--common/rfb/ComparingUpdateTracker.h13
-rw-r--r--common/rfb/ServerCore.cxx7
-rw-r--r--common/rfb/ServerCore.h2
-rw-r--r--common/rfb/VNCSConnectionST.cxx10
-rw-r--r--common/rfb/VNCSConnectionST.h4
-rw-r--r--common/rfb/VNCServerST.cxx25
-rw-r--r--common/rfb/VNCServerST.h2
8 files changed, 91 insertions, 21 deletions
diff --git a/common/rfb/ComparingUpdateTracker.cxx b/common/rfb/ComparingUpdateTracker.cxx
index 42a9e192..43287e07 100644
--- a/common/rfb/ComparingUpdateTracker.cxx
+++ b/common/rfb/ComparingUpdateTracker.cxx
@@ -25,7 +25,7 @@
using namespace rfb;
ComparingUpdateTracker::ComparingUpdateTracker(PixelBuffer* buffer)
- : fb(buffer), oldFb(fb->getPF(), 0, 0), firstCompare(true)
+ : fb(buffer), oldFb(fb->getPF(), 0, 0), firstCompare(true), enabled(true)
{
changed.assign_union(fb->getRect());
}
@@ -37,35 +37,60 @@ ComparingUpdateTracker::~ComparingUpdateTracker()
#define BLOCK_SIZE 16
-void ComparingUpdateTracker::compare()
+bool ComparingUpdateTracker::compare()
{
std::vector<Rect> rects;
std::vector<Rect>::iterator i;
+ if (!enabled)
+ return false;
+
if (firstCompare) {
// NB: We leave the change region untouched on this iteration,
// since in effect the entire framebuffer has changed.
oldFb.setSize(fb->width(), fb->height());
+
for (int y=0; y<fb->height(); y+=BLOCK_SIZE) {
Rect pos(0, y, fb->width(), __rfbmin(fb->height(), y+BLOCK_SIZE));
int srcStride;
const rdr::U8* srcData = fb->getPixelsR(pos, &srcStride);
oldFb.imageRect(pos, srcData, srcStride);
}
+
firstCompare = false;
- } else {
- copied.get_rects(&rects, copy_delta.x<=0, copy_delta.y<=0);
- for (i = rects.begin(); i != rects.end(); i++)
- oldFb.copyRect(*i, copy_delta);
- changed.get_rects(&rects);
+ return false;
+ }
+
+ copied.get_rects(&rects, copy_delta.x<=0, copy_delta.y<=0);
+ for (i = rects.begin(); i != rects.end(); i++)
+ oldFb.copyRect(*i, copy_delta);
- Region newChanged;
- for (i = rects.begin(); i != rects.end(); i++)
- compareRect(*i, &newChanged);
+ changed.get_rects(&rects);
- changed = newChanged;
- }
+ Region newChanged;
+ for (i = rects.begin(); i != rects.end(); i++)
+ compareRect(*i, &newChanged);
+
+ if (changed.equals(newChanged))
+ return false;
+
+ changed = newChanged;
+
+ return true;
+}
+
+void ComparingUpdateTracker::enable()
+{
+ enabled = true;
+}
+
+void ComparingUpdateTracker::disable()
+{
+ enabled = false;
+
+ // Make sure we update the framebuffer next time we get enabled
+ firstCompare = true;
}
void ComparingUpdateTracker::compareRect(const Rect& r, Region* newChanged)
diff --git a/common/rfb/ComparingUpdateTracker.h b/common/rfb/ComparingUpdateTracker.h
index 5d2e5edf..fccc2222 100644
--- a/common/rfb/ComparingUpdateTracker.h
+++ b/common/rfb/ComparingUpdateTracker.h
@@ -29,14 +29,23 @@ namespace rfb {
~ComparingUpdateTracker();
// compare() does the comparison and reduces its changed and copied regions
- // as appropriate.
+ // as appropriate. Returns true if the regions were altered.
- virtual void compare();
+ virtual bool compare();
+
+ // enable()/disable() turns the comparing functionality on/off. With it
+ // disabled, the object will behave like a dumb update tracker (i.e.
+ // compare() will be a no-op). It is harmless to repeatedly call these
+ // methods.
+
+ virtual void enable();
+ virtual void disable();
private:
void compareRect(const Rect& r, Region* newchanged);
PixelBuffer* fb;
ManagedPixelBuffer oldFb;
bool firstCompare;
+ bool enabled;
};
}
diff --git a/common/rfb/ServerCore.cxx b/common/rfb/ServerCore.cxx
index 27e116e3..ae2fd247 100644
--- a/common/rfb/ServerCore.cxx
+++ b/common/rfb/ServerCore.cxx
@@ -47,10 +47,11 @@ rfb::IntParameter rfb::Server::clientWaitTimeMillis
"The number of milliseconds to wait for a client which is no longer "
"responding",
20000, 0);
-rfb::BoolParameter rfb::Server::compareFB
+rfb::IntParameter rfb::Server::compareFB
("CompareFB",
- "Perform pixel comparison on framebuffer to reduce unnecessary updates",
- false);
+ "Perform pixel comparison on framebuffer to reduce unnecessary updates "
+ "(0: never, 1: always, 2: auto)",
+ 2);
rfb::BoolParameter rfb::Server::protocol3_3
("Protocol3.3",
"Always use protocol version 3.3 for backwards compatibility with "
diff --git a/common/rfb/ServerCore.h b/common/rfb/ServerCore.h
index 68d7b74b..e12a8bc8 100644
--- a/common/rfb/ServerCore.h
+++ b/common/rfb/ServerCore.h
@@ -37,7 +37,7 @@ namespace rfb {
static IntParameter maxConnectionTime;
static IntParameter maxIdleTime;
static IntParameter clientWaitTimeMillis;
- static BoolParameter compareFB;
+ static IntParameter compareFB;
static BoolParameter protocol3_3;
static BoolParameter alwaysShared;
static BoolParameter neverShared;
diff --git a/common/rfb/VNCSConnectionST.cxx b/common/rfb/VNCSConnectionST.cxx
index d0cdf869..466d6d5c 100644
--- a/common/rfb/VNCSConnectionST.cxx
+++ b/common/rfb/VNCSConnectionST.cxx
@@ -326,6 +326,16 @@ int VNCSConnectionST::checkIdleTimeout()
return secsToMillis(timeLeft);
}
+
+bool VNCSConnectionST::getComparerState()
+{
+ // We interpret a low compression level as an indication that the client
+ // wants to prioritise CPU usage over bandwidth, and hence disable the
+ // comparing update tracker.
+ return (cp.compressLevel == -1) || (cp.compressLevel > 1);
+}
+
+
// renderedCursorChange() is called whenever the server-side rendered cursor
// changes shape or position. It ensures that the next update will clean up
// the old rendered cursor and if necessary draw the new rendered cursor.
diff --git a/common/rfb/VNCSConnectionST.h b/common/rfb/VNCSConnectionST.h
index 8742fa67..72dc59c0 100644
--- a/common/rfb/VNCSConnectionST.h
+++ b/common/rfb/VNCSConnectionST.h
@@ -85,6 +85,10 @@ namespace rfb {
// The following methods never throw exceptions nor do they ever delete the
// SConnectionST object.
+ // getComparerState() returns if this client would like the framebuffer
+ // comparer to be enabled.
+ bool getComparerState();
+
// renderedCursorChange() is called whenever the server-side rendered
// cursor changes shape or position. It ensures that the next update will
// clean up the old rendered cursor and if necessary draw the new rendered
diff --git a/common/rfb/VNCServerST.cxx b/common/rfb/VNCServerST.cxx
index 5c135969..1e3f61a0 100644
--- a/common/rfb/VNCServerST.cxx
+++ b/common/rfb/VNCServerST.cxx
@@ -596,10 +596,13 @@ bool VNCServerST::checkUpdate()
pb->grabRegion(toCheck);
- if (rfb::Server::compareFB) {
- comparer->compare();
+ if (getComparerState())
+ comparer->enable();
+ else
+ comparer->disable();
+
+ if (comparer->compare())
comparer->getUpdateInfo(&ui, pb->getRect());
- }
if (renderCursor) {
pb->getImage(renderedCursor.data,
@@ -665,3 +668,19 @@ void VNCServerST::notifyScreenLayoutChange(VNCSConnectionST* requester)
(*ci)->screenLayoutChangeOrClose(reasonOtherClient);
}
}
+
+bool VNCServerST::getComparerState()
+{
+ if (rfb::Server::compareFB == 0)
+ return false;
+ if (rfb::Server::compareFB != 2)
+ return true;
+
+ std::list<VNCSConnectionST*>::iterator ci, ci_next;
+ for (ci=clients.begin();ci!=clients.end();ci=ci_next) {
+ ci_next = ci; ci_next++;
+ if ((*ci)->getComparerState())
+ return true;
+ }
+ return false;
+}
diff --git a/common/rfb/VNCServerST.h b/common/rfb/VNCServerST.h
index 47a48019..2fed0a87 100644
--- a/common/rfb/VNCServerST.h
+++ b/common/rfb/VNCServerST.h
@@ -238,6 +238,8 @@ namespace rfb {
void notifyScreenLayoutChange(VNCSConnectionST *requester);
+ bool getComparerState();
+
QueryConnectionHandler* queryConnectionHandler;
KeyRemapper* keyRemapper;
bool useEconomicTranslate;