aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPierre Ossman <ossman@cendio.se>2011-11-14 16:02:06 +0000
committerPierre Ossman <ossman@cendio.se>2011-11-14 16:02:06 +0000
commite28bdb22ff9cc95dfadee4437c1a5a4328d083cd (patch)
tree56732aa020e32b56f19ff1ef2ed98544055f49d8
parent2c7649422ecd811217bc85b4c493794b217014b7 (diff)
downloadtigervnc-e28bdb22ff9cc95dfadee4437c1a5a4328d083cd.tar.gz
tigervnc-e28bdb22ff9cc95dfadee4437c1a5a4328d083cd.zip
Support and use fences in the client. This allows more aggressive use of
update requests as we can now synchronise format changes. git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@4800 3789f03b-4d11-0410-bbf8-ca57d06f2519
-rw-r--r--vncviewer/CConn.cxx81
-rw-r--r--vncviewer/CConn.h4
2 files changed, 73 insertions, 12 deletions
diff --git a/vncviewer/CConn.cxx b/vncviewer/CConn.cxx
index 3e008ca9..4cc09f22 100644
--- a/vncviewer/CConn.cxx
+++ b/vncviewer/CConn.cxx
@@ -33,7 +33,10 @@
#include <rfb/LogWriter.h>
#include <rfb/util.h>
#include <rfb/screenTypes.h>
+#include <rfb/fenceTypes.h>
#include <rfb/Timer.h>
+#include <rdr/MemInStream.h>
+#include <rdr/MemOutStream.h>
#include <network/TcpSocket.h>
#include <FL/Fl.H>
@@ -70,7 +73,7 @@ CConn::CConn(const char* vncServerName)
currentEncoding(encodingTight), lastServerEncoding((unsigned int)-1),
formatChange(false), encodingChange(false),
firstUpdate(true), pendingUpdate(false),
- forceNonincremental(true)
+ forceNonincremental(true), supportsSyncFence(false)
{
setShared(::shared);
@@ -130,10 +133,12 @@ CConn::~CConn()
void CConn::refreshFramebuffer()
{
- // FIXME: We cannot safely trigger an update request directly but must
- // wait for the next update to arrive.
- if (!formatChange)
- forceNonincremental = true;
+ forceNonincremental = true;
+
+ // Without fences, we cannot safely trigger an update request directly
+ // but must wait for the next update to arrive.
+ if (supportsSyncFence)
+ requestNewUpdate();
}
const char *CConn::connectionInfo()
@@ -284,6 +289,7 @@ void CConn::setName(const char* name)
// one.
void CConn::framebufferUpdateStart()
{
+ // Note: This might not be true if sync fences are supported
pendingUpdate = false;
requestNewUpdate();
@@ -300,6 +306,11 @@ void CConn::framebufferUpdateEnd()
if (firstUpdate) {
int width, height;
+ // We need fences to make extra update requests "safe".
+ // See fence() for the next step.
+ if (cp.supportsFence)
+ writer()->writeFence(fenceFlagRequest | fenceFlagSyncNext, 0, NULL);
+
if (cp.supportsSetDesktopSize &&
sscanf(desktopSize.getValueStr(), "%dx%d", &width, &height) == 2) {
ScreenSet layout;
@@ -423,6 +434,34 @@ void CConn::setCursor(int width, int height, const Point& hotspot,
desktop->setCursor(width, height, hotspot, data, mask);
}
+void CConn::fence(rdr::U32 flags, unsigned len, const char data[])
+{
+ CMsgHandler::fence(flags, len, data);
+
+ if (flags & fenceFlagRequest) {
+ // We handle everything synchronously so we trivially honor these modes
+ flags = flags & (fenceFlagBlockBefore | fenceFlagBlockAfter);
+
+ writer()->writeFence(flags, len, data);
+ return;
+ }
+
+ if (len == 0) {
+ // Initial probe
+ if (flags & fenceFlagSyncNext)
+ supportsSyncFence = true;
+ } else {
+ // Pixel format change
+ rdr::MemInStream memStream(data, len);
+ PixelFormat pf;
+
+ pf.read(&memStream);
+
+ desktop->setServerPF(pf);
+ cp.setPF(pf);
+ }
+}
+
rdr::U8* CConn::getRawPixelsRW(const rfb::Rect& r, int* stride) {
return desktop->getPixelsRW(r, stride);
}
@@ -529,7 +568,7 @@ void CConn::requestNewUpdate()
PixelFormat pf;
/* Catch incorrect requestNewUpdate calls */
- assert(pendingUpdate == false);
+ assert(!pendingUpdate || supportsSyncFence);
if (fullColour) {
pf = fullColourPF;
@@ -542,11 +581,23 @@ void CConn::requestNewUpdate()
pf = mediumColourPF;
}
- // New requests are sent out at the start of processing the last
- // one, so we cannot switch our internal format right now (doing so
- // would mean misdecoding the current update).
- pendingPFChange = true;
- pendingPF = pf;
+ if (supportsSyncFence) {
+ // We let the fence carry the pixel format and switch once we
+ // get the response back. That way we will be synchronised with
+ // when the server switches.
+ rdr::MemOutStream memStream;
+
+ pf.write(&memStream);
+
+ writer()->writeFence(fenceFlagRequest | fenceFlagSyncNext,
+ memStream.length(), (const char*)memStream.data());
+ } else {
+ // New requests are sent out at the start of processing the last
+ // one, so we cannot switch our internal format right now (doing so
+ // would mean misdecoding the current update).
+ pendingPFChange = true;
+ pendingPF = pf;
+ }
char str[256];
pf.print(str, 256);
@@ -607,6 +658,12 @@ void CConn::handleOptions(void *data)
pf = mediumColourPF;
}
- if (!pf.equal(self->cp.pf()))
+ if (!pf.equal(self->cp.pf())) {
self->formatChange = true;
+
+ // Without fences, we cannot safely trigger an update request directly
+ // but must wait for the next update to arrive.
+ if (self->supportsSyncFence)
+ self->requestNewUpdate();
+ }
}
diff --git a/vncviewer/CConn.h b/vncviewer/CConn.h
index 6dd32043..25d10e78 100644
--- a/vncviewer/CConn.h
+++ b/vncviewer/CConn.h
@@ -75,6 +75,8 @@ public:
void setCursor(int width, int height, const rfb::Point& hotspot,
void* data, void* mask);
+ void fence(rdr::U32 flags, unsigned len, const char data[]);
+
private:
void resizeFramebuffer();
@@ -107,6 +109,8 @@ private:
bool pendingUpdate;
bool forceNonincremental;
+
+ bool supportsSyncFence;
};
#endif