]> source.dussan.org Git - tigervnc.git/commitdiff
Support and use fences in the client. This allows more aggressive use of
authorPierre Ossman <ossman@cendio.se>
Mon, 14 Nov 2011 16:02:06 +0000 (16:02 +0000)
committerPierre Ossman <ossman@cendio.se>
Mon, 14 Nov 2011 16:02:06 +0000 (16:02 +0000)
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

vncviewer/CConn.cxx
vncviewer/CConn.h

index 3e008ca973a3812ba9ed999fc2d17796601ae5cb..4cc09f226794bd7aff7a9697d1f281c38ebe7410 100644 (file)
 #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();
+  }
 }
index 6dd32043021ed42d9ba46767f08e750d38fcb8c3..25d10e78ecc5181d1d6e5d89b6600e4b3a40ec0e 100644 (file)
@@ -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