diff options
author | Pierre Ossman <ossman@cendio.se> | 2011-11-08 12:44:10 +0000 |
---|---|---|
committer | Pierre Ossman <ossman@cendio.se> | 2011-11-08 12:44:10 +0000 |
commit | bbf955ebd77320fb7f95efc3ac140feced109ed8 (patch) | |
tree | 6fe96cab7fa2e0d52689db4c58ce386c0f4183dc /common | |
parent | 5bc20a699359dfba501880bc776f8fd3c8e5b889 (diff) | |
download | tigervnc-bbf955ebd77320fb7f95efc3ac140feced109ed8.tar.gz tigervnc-bbf955ebd77320fb7f95efc3ac140feced109ed8.zip |
Reimplement the deferred update handling, this time in a more robust and
well-behaved manner.
git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@4784 3789f03b-4d11-0410-bbf8-ca57d06f2519
Diffstat (limited to 'common')
-rw-r--r-- | common/rfb/VNCSConnectionST.cxx | 6 | ||||
-rw-r--r-- | common/rfb/VNCServer.h | 4 | ||||
-rw-r--r-- | common/rfb/VNCServerST.cxx | 93 | ||||
-rw-r--r-- | common/rfb/VNCServerST.h | 22 |
4 files changed, 100 insertions, 25 deletions
diff --git a/common/rfb/VNCSConnectionST.cxx b/common/rfb/VNCSConnectionST.cxx index bcc7f234..30d9b6ad 100644 --- a/common/rfb/VNCSConnectionST.cxx +++ b/common/rfb/VNCSConnectionST.cxx @@ -668,7 +668,11 @@ void VNCSConnectionST::writeFramebufferUpdate() updates.enable_copyrect(cp.useCopyRect); - server->checkUpdate(); + // Fetch updates from server object, and see if we are allowed to send + // anything right now (the framebuffer might have changed in ways we + // haven't yet been informed of). + if (!server->checkUpdate()) + return; // Get the lists of updates. Prior to exporting the data to the `ui' object, // getUpdateInfo() will normalize the `updates' object such way that its diff --git a/common/rfb/VNCServer.h b/common/rfb/VNCServer.h index 1c8d38e0..4e554792 100644 --- a/common/rfb/VNCServer.h +++ b/common/rfb/VNCServer.h @@ -62,10 +62,6 @@ namespace rfb { // their close() method with the supplied reason. virtual void closeClients(const char* reason) = 0; - // tryUpdate() causes the server to attempt to send updates to any waiting - // clients. - virtual void tryUpdate() = 0; - // setCursor() tells the server that the cursor has changed. The // cursorData argument contains width*height pixel values in the pixel // buffer's format. The mask argument is a bitmask with a 1-bit meaning diff --git a/common/rfb/VNCServerST.cxx b/common/rfb/VNCServerST.cxx index eea6565d..5c135969 100644 --- a/common/rfb/VNCServerST.cxx +++ b/common/rfb/VNCServerST.cxx @@ -64,6 +64,12 @@ using namespace rfb; static LogWriter slog("VNCServerST"); LogWriter VNCServerST::connectionsLog("Connections"); +rfb::IntParameter deferUpdateTime("DeferUpdate", + "Time in milliseconds to defer updates",10); + +rfb::BoolParameter alwaysSetDeferUpdateTimer("AlwaysSetDeferUpdateTimer", + "Always reset the defer update timer on every change",false); + // // -=- VNCServerST Implementation // @@ -76,7 +82,8 @@ VNCServerST::VNCServerST(const char* name_, SDesktop* desktop_) renderedCursorInvalid(false), queryConnectionHandler(0), keyRemapper(&KeyRemapper::defInstance), useEconomicTranslate(false), - lastConnectionTime(0), disableclients(false) + lastConnectionTime(0), disableclients(false), + deferTimer(this), deferPending(false) { lastUserInputTime = lastDisconnectTime = time(0); slog.debug("creating single-threaded server %s", name.buf); @@ -373,25 +380,22 @@ void VNCServerST::setName(const char* name_) void VNCServerST::add_changed(const Region& region) { - if (comparer != 0) { - comparer->add_changed(region); - } + if (comparer == NULL) + return; + + comparer->add_changed(region); + startDefer(); + tryUpdate(); } void VNCServerST::add_copied(const Region& dest, const Point& delta) { - if (comparer != 0) { - comparer->add_copied(dest, delta); - } -} + if (comparer == NULL) + return; -void VNCServerST::tryUpdate() -{ - std::list<VNCSConnectionST*>::iterator ci, ci_next; - for (ci = clients.begin(); ci != clients.end(); ci = ci_next) { - ci_next = ci; ci_next++; - (*ci)->writeFramebufferUpdateOrClose(); - } + comparer->add_copied(dest, delta); + startDefer(); + tryUpdate(); } void VNCServerST::setCursor(int width, int height, const Point& newHotspot, @@ -471,6 +475,15 @@ SConnection* VNCServerST::getSConnection(network::Socket* sock) { return 0; } +bool VNCServerST::handleTimeout(Timer* t) +{ + if (t != &deferTimer) + return false; + + tryUpdate(); + + return false; +} // -=- Internal methods @@ -503,6 +516,44 @@ inline bool VNCServerST::needRenderedCursor() return false; } +inline void VNCServerST::startDefer() +{ + if (deferUpdateTime == 0) + return; + + if (deferPending && !alwaysSetDeferUpdateTimer) + return; + + gettimeofday(&deferStart, NULL); + deferTimer.start(deferUpdateTime); + + deferPending = true; +} + +inline bool VNCServerST::checkDefer() +{ + if (!deferPending) + return true; + + if (msSince(&deferStart) >= deferUpdateTime) + return true; + + return false; +} + +void VNCServerST::tryUpdate() +{ + std::list<VNCSConnectionST*>::iterator ci, ci_next; + + if (!checkDefer()) + return; + + for (ci = clients.begin(); ci != clients.end(); ci = ci_next) { + ci_next = ci; ci_next++; + (*ci)->writeFramebufferUpdateOrClose(); + } +} + // checkUpdate() is called just before sending an update. It checks to see // what updates are pending and propagates them to the update tracker for each // client. It uses the ComparingUpdateTracker's compare() method to filter out @@ -510,7 +561,7 @@ inline bool VNCServerST::needRenderedCursor() // state of the (server-side) rendered cursor, if necessary rendering it again // with the correct background. -void VNCServerST::checkUpdate() +bool VNCServerST::checkUpdate() { UpdateInfo ui; comparer->getUpdateInfo(&ui, pb->getRect()); @@ -518,7 +569,13 @@ void VNCServerST::checkUpdate() bool renderCursor = needRenderedCursor(); if (ui.is_empty() && !(renderCursor && renderedCursorInvalid)) - return; + return true; + + // Block client from updating if we are currently deferring updates + if (!checkDefer()) + return false; + + deferPending = false; Region toCheck = ui.changed.union_(ui.copied); @@ -561,6 +618,8 @@ void VNCServerST::checkUpdate() } comparer->clear(); + + return true; } void VNCServerST::getConnInfo(ListConnInfo * listConn) diff --git a/common/rfb/VNCServerST.h b/common/rfb/VNCServerST.h index c74be903..47a48019 100644 --- a/common/rfb/VNCServerST.h +++ b/common/rfb/VNCServerST.h @@ -23,6 +23,8 @@ #ifndef __RFB_VNCSERVERST_H__ #define __RFB_VNCSERVERST_H__ +#include <sys/time.h> + #include <list> #include <rfb/SDesktop.h> @@ -31,6 +33,7 @@ #include <rfb/LogWriter.h> #include <rfb/Blacklist.h> #include <rfb/Cursor.h> +#include <rfb/Timer.h> #include <network/Socket.h> #include <rfb/ListConnInfo.h> #include <rfb/ScreenSet.h> @@ -42,7 +45,9 @@ namespace rfb { class PixelBuffer; class KeyRemapper; - class VNCServerST : public VNCServer, public network::SocketServer { + class VNCServerST : public VNCServer, + public Timer::Callback, + public network::SocketServer { public: // -=- Constructors @@ -85,7 +90,6 @@ namespace rfb { virtual void serverCutText(const char* str, int len); virtual void add_changed(const Region ®ion); virtual void add_copied(const Region &dest, const Point &delta); - virtual void tryUpdate(); virtual void setCursor(int width, int height, const Point& hotspot, void* cursorData, void* mask); virtual void setCursorPos(const Point& p); @@ -192,6 +196,11 @@ namespace rfb { friend class VNCSConnectionST; + // Timer callbacks + virtual bool handleTimeout(Timer* t); + + // - Internal methods + void startDesktop(); static LogWriter connectionsLog; @@ -222,7 +231,10 @@ namespace rfb { int authClientCount(); bool needRenderedCursor(); - void checkUpdate(); + void startDefer(); + bool checkDefer(); + void tryUpdate(); + bool checkUpdate(); void notifyScreenLayoutChange(VNCSConnectionST *requester); @@ -235,6 +247,10 @@ namespace rfb { time_t lastConnectionTime; bool disableclients; + + Timer deferTimer; + bool deferPending; + struct timeval deferStart; }; }; |