/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
- * Copyright 2009-2015 Pierre Ossman for Cendio AB
+ * Copyright 2009-2016 Pierre Ossman 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
void VNCSConnectionST::writeFramebufferUpdate()
{
- Region req;
- UpdateInfo ui;
- bool needNewUpdateInfo;
- bool drawRenderedCursor;
-
// We're in the middle of processing a command that's supposed to be
// synchronised. Allowing an update to slip out right now might violate
// that synchronisation.
if (isCongested())
return;
- // In continuous mode, we will be outputting at least three distinct
- // messages. We need to aggregate these in order to not clog up TCP's
- // congestion window.
+ // Updates often consists of many small writes, and in continuous
+ // mode, we will also have small fence messages around the update. We
+ // need to aggregate these in order to not clog up TCP's congestion
+ // window.
network::TcpSocket::cork(sock->getFd(), true);
// First take care of any updates that cannot contain framebuffer data
// changes.
- if (writer()->needNoDataUpdate()) {
- writer()->writeNoDataUpdate();
- requested.clear();
- if (!continuousUpdates)
- goto out;
- }
+ writeNoDataUpdate();
+
+ // Then real data (if possible)
+ writeDataUpdate();
+
+ network::TcpSocket::cork(sock->getFd(), false);
+}
+
+void VNCSConnectionST::writeNoDataUpdate()
+{
+ if (!writer()->needNoDataUpdate())
+ return;
+
+ writer()->writeNoDataUpdate();
+
+ // Make sure no data update is sent until next request
+ requested.clear();
+}
+
+void VNCSConnectionST::writeDataUpdate()
+{
+ Region req;
+ UpdateInfo ui;
+ bool needNewUpdateInfo;
+ bool drawRenderedCursor;
+ RenderedCursor *cursor;
updates.enable_copyrect(cp.useCopyRect);
// anything right now (the framebuffer might have changed in ways we
// haven't yet been informed of).
if (!server->checkUpdate())
- goto out;
-
- // Get the lists of updates. Prior to exporting the data to the `ui' object,
- // getUpdateInfo() will normalize the `updates' object such way that its
- // `changed' and `copied' regions would not intersect.
+ return;
+ // See what the client has requested (if anything)
if (continuousUpdates)
req = cuRegion.union_(requested);
else
req = requested;
+ if (req.is_empty())
+ 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
+ // `changed' and `copied' regions would not intersect.
updates.getUpdateInfo(&ui, req);
needNewUpdateInfo = false;
// Return if there is nothing to send the client.
if (updates.is_empty() && !writer()->needFakeUpdate() && !updateRenderedCursor)
- goto out;
+ return;
// The `updates' object could change, make sure we have valid update info.
updateRenderedCursor = false;
}
- if (!ui.is_empty() || writer()->needFakeUpdate() || drawRenderedCursor) {
- RenderedCursor *cursor;
-
- cursor = NULL;
- if (drawRenderedCursor)
- cursor = &server->renderedCursor;
+ if (ui.is_empty() && !writer()->needFakeUpdate() && !drawRenderedCursor)
+ return;
- writeRTTPing();
+ cursor = NULL;
+ if (drawRenderedCursor)
+ cursor = &server->renderedCursor;
- encodeManager.writeUpdate(ui, server->getPixelBuffer(), cursor);
+ writeRTTPing();
- writeRTTPing();
+ encodeManager.writeUpdate(ui, server->getPixelBuffer(), cursor);
- // The request might be for just part of the screen, so we cannot
- // just clear the entire update tracker.
- updates.subtract(req);
+ writeRTTPing();
- requested.clear();
- }
+ // The request might be for just part of the screen, so we cannot
+ // just clear the entire update tracker.
+ updates.subtract(req);
-out:
- network::TcpSocket::cork(sock->getFd(), false);
+ requested.clear();
}