diff --git a/common/rfb/EncodeManager.cxx b/common/rfb/EncodeManager.cxx index 53e0365..9e39859 100644 --- a/common/rfb/EncodeManager.cxx +++ b/common/rfb/EncodeManager.cxx @@ -1,6 +1,7 @@ /* Copyright (C) 2000-2003 Constantin Kaplinsky. All Rights Reserved. * Copyright (C) 2011 D. R. Commander. All Rights Reserved. * Copyright 2014-2018 Pierre Ossman for Cendio AB + * Copyright 2018 Peter Astrand 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 @@ -248,14 +249,22 @@ bool EncodeManager::supported(int encoding) } } +void EncodeManager::updateLosslessRefresh() +{ + delayedLossyRegion = lossyRegion; + delayedLossyRegion.assign_subtract(recentRegion); + recentRegion.clear(); +} + bool EncodeManager::needsLosslessRefresh(const Region& req) { - return !lossyRegion.intersect(req).is_empty(); + return !delayedLossyRegion.intersect(req).is_empty(); } void EncodeManager::pruneLosslessRefresh(const Region& limits) { lossyRegion.assign_intersect(limits); + delayedLossyRegion.assign_intersect(limits); } void EncodeManager::writeUpdate(const UpdateInfo& ui, const PixelBuffer* pb, @@ -438,7 +447,7 @@ Region EncodeManager::getLosslessRefresh(const Region& req, maxUpdateSize *= 2; area = 0; - lossyRegion.intersect(req).get_rects(&rects); + delayedLossyRegion.intersect(req).get_rects(&rects); while (!rects.empty()) { size_t idx; Rect rect; @@ -527,8 +536,11 @@ Encoder *EncodeManager::startRect(const Rect& rect, int type) if (encoder->flags & EncoderLossy) lossyRegion.assign_union(Region(rect)); - else + else { lossyRegion.assign_subtract(Region(rect)); + delayedLossyRegion.assign_subtract(Region(rect)); + } + recentRegion.assign_union(Region(rect)); return encoder; } @@ -574,6 +586,7 @@ void EncodeManager::writeCopyRects(const Region& copied, const Point& delta) lossyCopy.translate(delta); lossyCopy.assign_intersect(copied); lossyRegion.assign_union(lossyCopy); + recentRegion.assign_union(lossyCopy); } void EncodeManager::writeSolidRects(Region *changed, const PixelBuffer* pb) diff --git a/common/rfb/EncodeManager.h b/common/rfb/EncodeManager.h index a91c544..0f7d935 100644 --- a/common/rfb/EncodeManager.h +++ b/common/rfb/EncodeManager.h @@ -46,6 +46,7 @@ namespace rfb { // Hack to let ConnParams calculate the client's preferred encoding static bool supported(int encoding); + void updateLosslessRefresh(); bool needsLosslessRefresh(const Region& req); void pruneLosslessRefresh(const Region& limits); @@ -117,6 +118,8 @@ namespace rfb { std::vector activeEncoders; Region lossyRegion; + Region recentRegion; + Region delayedLossyRegion; struct EncoderStats { unsigned rects; diff --git a/common/rfb/VNCSConnectionST.cxx b/common/rfb/VNCSConnectionST.cxx index f22b993..c504cc5 100644 --- a/common/rfb/VNCSConnectionST.cxx +++ b/common/rfb/VNCSConnectionST.cxx @@ -1,5 +1,6 @@ /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. * Copyright 2009-2018 Pierre Ossman for Cendio AB + * Copyright 2018 Peter Astrand 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 @@ -36,6 +37,8 @@ #define XK_XKB_KEYS #include +#define ALR_TIMEOUT 59 // Slightly longer than 20 fps + using namespace rfb; static LogWriter vlog("VNCSConnST"); @@ -47,7 +50,7 @@ VNCSConnectionST::VNCSConnectionST(VNCServerST* server_, network::Socket *s, : sock(s), reverseConnection(reverse), inProcessMessages(false), pendingSyncFence(false), syncFence(false), fenceFlags(0), - fenceDataLen(0), fenceData(NULL), congestionTimer(this), + fenceDataLen(0), fenceData(NULL), congestionTimer(this), alrTimer(this), server(server_), updates(false), updateRenderedCursor(false), removeRenderedCursor(false), continuousUpdates(false), encodeManager(this), pointerEventTime(0), @@ -58,6 +61,8 @@ VNCSConnectionST::VNCSConnectionST(VNCServerST* server_, network::Socket *s, peerEndpoint.buf = sock->getPeerEndpoint(); VNCServerST::connectionsLog.write(1,"accepted: %s", peerEndpoint.buf); + alrTimer.start(ALR_TIMEOUT); + // Configure the socket setSocketTimeouts(); lastEventTime = time(0); @@ -841,6 +846,13 @@ bool VNCSConnectionST::handleTimeout(Timer* t) try { if (t == &congestionTimer) writeFramebufferUpdate(); + + if (t == &alrTimer) { + alrTimer.start(ALR_TIMEOUT); + encodeManager.updateLosslessRefresh(); + writeFramebufferUpdate(); + } + } catch (rdr::Exception& e) { close(e.str()); } diff --git a/common/rfb/VNCSConnectionST.h b/common/rfb/VNCSConnectionST.h index 2f075a6..c7227b1 100644 --- a/common/rfb/VNCSConnectionST.h +++ b/common/rfb/VNCSConnectionST.h @@ -191,6 +191,7 @@ namespace rfb { Congestion congestion; Timer congestionTimer; + Timer alrTimer; VNCServerST* server; SimpleUpdateTracker updates;