Polling algorithm was extended. Now, if it detected any changes, it will also check vertical borders of neighboring tiles at the right.


git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@2388 3789f03b-4d11-0410-bbf8-ca57d06f2519
diff --git a/unix/x0vncserver/PollingManager.cxx b/unix/x0vncserver/PollingManager.cxx
index ffc9ed3..b0c0efb 100644
--- a/unix/x0vncserver/PollingManager.cxx
+++ b/unix/x0vncserver/PollingManager.cxx
@@ -209,8 +209,15 @@
     }
   }
 
-  // Inform the server about the changes.
+  // If some changes have been detected:
   if (nTilesChanged) {
+    // Try to find more changes around. Before doing that, mark the
+    // video area as changed, to skip comparisons of its pixels.
+    flagVideoArea(changeFlags, true);
+    checkNeighbors(changeFlags);
+
+    // Inform the server about the changes. This time, we mark the
+    // video area as NOT changed, to prevent reading its pixels again.
     flagVideoArea(changeFlags, false);
     sendChanges(changeFlags);
   }
@@ -265,6 +272,37 @@
   return nTilesChanged;
 }
 
+int PollingManager::checkColumn(int x, int y, int h, bool *pChangeFlags)
+{
+  int bytesPerPixel = m_image->xim->bits_per_pixel / 8;
+
+  getColumn(x, y, h);
+
+  int nTilesChanged = 0;
+  for (int nTile = 0; nTile < (h + 31) / 32; nTile++) {
+    if (!*pChangeFlags) {
+      int tile_h = (h - nTile * 32 >= 32) ? 32 : h - nTile * 32;
+      for (int i = 0; i < tile_h; i++) {
+        // FIXME: Provide an inline function Image::locatePixel(x, y).
+        // FIXME: Do not compute these pointers in the inner cycle.
+        char *ptr_old = (m_image->xim->data +
+                         (y + nTile * 32 + i) * m_image->xim->bytes_per_line +
+                         x * bytesPerPixel);
+        char *ptr_new = (m_columnImage->xim->data +
+                         (nTile * 32 + i) * m_columnImage->xim->bytes_per_line);
+        if (memcmp(ptr_old, ptr_new, bytesPerPixel)) {
+          *pChangeFlags = true;
+          nTilesChanged++;
+          break;
+        }
+      }
+    }
+    pChangeFlags += m_widthTiles;
+  }
+
+  return nTilesChanged;
+}
+
 void PollingManager::sendChanges(const bool *pChangeFlags)
 {
   Rect rect;
@@ -321,6 +359,24 @@
 }
 
 void
+PollingManager::checkNeighbors(bool *pChangeFlags)
+{
+  // Check neighboring pixels at the right of changed tiles.
+  for (int x = 0; x < m_widthTiles - 1; x++) {
+    for (int y = 0; y < m_heightTiles; y++) {
+      if (pChangeFlags[y * m_widthTiles + x] &&
+          !pChangeFlags[y * m_widthTiles + x + 1]) {
+        // FIXME: Check pChangeFlags[] to decrease height of the column.
+        // FIXME: Check _only_ the tiles neighboring to changed tiles?
+        checkColumn((x + 1) * 32, y * 32, m_height - y * 32,
+                    &pChangeFlags[y * m_widthTiles + x + 1]);
+        break;
+      }
+    }
+  }
+}
+
+void
 PollingManager::detectVideo()
 {
   // Configurable parameters.