Revision: 4800
          http://tigervnc.svn.sourceforge.net/tigervnc/?rev=4800&view=rev
Author:   ossman_
Date:     2011-11-14 16:02:06 +0000 (Mon, 14 Nov 2011)
Log Message:
-----------
Support and use fences in the client. This allows more aggressive use of
update requests as we can now synchronise format changes.

Modified Paths:
--------------
    trunk/vncviewer/CConn.cxx
    trunk/vncviewer/CConn.h

Modified: trunk/vncviewer/CConn.cxx
===================================================================
--- trunk/vncviewer/CConn.cxx   2011-11-14 15:54:30 UTC (rev 4799)
+++ trunk/vncviewer/CConn.cxx   2011-11-14 16:02:06 UTC (rev 4800)
@@ -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 @@
     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 @@
 
 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 @@
 // one.
 void CConn::framebufferUpdateStart()
 {
+  // Note: This might not be true if sync fences are supported
   pendingUpdate = false;
 
   requestNewUpdate();
@@ -300,6 +306,11 @@
   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 @@
   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 @@
     PixelFormat pf;
 
     /* Catch incorrect requestNewUpdate calls */
-    assert(pendingUpdate == false);
+    assert(!pendingUpdate || supportsSyncFence);
 
     if (fullColour) {
       pf = fullColourPF;
@@ -542,12 +581,24 @@
         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);
     vlog.info(_("Using pixel format %s"),str);
@@ -607,6 +658,12 @@
       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();
+  }
 }

Modified: trunk/vncviewer/CConn.h
===================================================================
--- trunk/vncviewer/CConn.h     2011-11-14 15:54:30 UTC (rev 4799)
+++ trunk/vncviewer/CConn.h     2011-11-14 16:02:06 UTC (rev 4800)
@@ -75,6 +75,8 @@
   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 @@
   bool pendingUpdate;
 
   bool forceNonincremental;
+
+  bool supportsSyncFence;
 };
 
 #endif

This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.


------------------------------------------------------------------------------
RSA(R) Conference 2012
Save $700 by Nov 18
Register now
http://p.sf.net/sfu/rsa-sfdev2dev1
_______________________________________________
Tigervnc-commits mailing list
Tigervnc-commits@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/tigervnc-commits

Reply via email to