]> source.dussan.org Git - tigervnc.git/commitdiff
Implemented new polling algorithm with video detection.
authorConstantin Kaplinsky <const@tightvnc.com>
Wed, 19 Oct 2005 13:57:16 +0000 (13:57 +0000)
committerConstantin Kaplinsky <const@tightvnc.com>
Wed, 19 Oct 2005 13:57:16 +0000 (13:57 +0000)
Continuously-changed areas like video windows would be updated with
reduced rate, to improve responsiveness of other screen elements.

git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@355 3789f03b-4d11-0410-bbf8-ca57d06f2519

x0vncserver/PollingManager.cxx
x0vncserver/PollingManager.h

index 25111cdf3fd195a4905d4adde20fdd029d3829db..3c6aab9268a6e60bcb8ced03dbd5cff0b9ac5d1c 100644 (file)
@@ -29,7 +29,7 @@
 #include <x0vncserver/Image.h>
 #include <x0vncserver/PollingManager.h>
 
-IntParameter pollingType("PollingType", "Polling algorithm to use (0..2)", 2);
+IntParameter pollingType("PollingType", "Polling algorithm to use (0..3)", 3);
 
 const int PollingManager::m_pollingOrder[32] = {
    0, 16,  8, 24,  4, 20, 12, 28,
@@ -62,16 +62,32 @@ PollingManager::PollingManager(Display *dpy, Image *image,
   m_rowImage = factory->newImage(m_dpy, m_width, 1);
   m_tileImage = factory->newImage(m_dpy, 32, 32);
 
+  // FIXME: Extend the comment.
   // Create a matrix with one byte per each 32x32 tile. It will be
   // used to limit the rate of updates on continuously-changed screen
   // areas (like video).
   int numTiles = m_widthTiles * m_heightTiles;
   m_statusMatrix = new char[numTiles];
   memset(m_statusMatrix, 0, numTiles);
+
+  // FIXME: Extend the comment.
+  // Create a matrix with one byte per each 32x32 tile. It will be
+  // used to limit the rate of updates on continuously-changed screen
+  // areas (like video).
+  m_rateMatrix = new char[numTiles];
+  m_videoFlags = new char[numTiles];
+  m_changedFlags = new char[numTiles];
+  memset(m_rateMatrix, 0, numTiles);
+  memset(m_videoFlags, 0, numTiles);
+  memset(m_changedFlags, 0, numTiles);
 }
 
 PollingManager::~PollingManager()
 {
+  delete[] m_changedFlags;
+  delete[] m_videoFlags;
+  delete[] m_rateMatrix;
+
   delete[] m_statusMatrix;
 }
 
@@ -118,11 +134,86 @@ void PollingManager::poll()
   case 1:
     poll_Traditional();
     break;
-//case 2:
-  default:
+  case 2:
     poll_SkipCycles();
     break;
+//case 3:
+  default:
+    poll_DetectVideo();
+    break;
+  }
+}
+
+void PollingManager::poll_DetectVideo()
+{
+  if (!m_server)
+    return;
+
+  const int GRAND_STEP_DIVISOR = 8;
+  const int VIDEO_THRESHOLD_0 = 3;
+  const int VIDEO_THRESHOLD_1 = 5;
+
+  bool grandStep = (m_pollingStep % GRAND_STEP_DIVISOR == 0);
+
+  // FIXME: Save shortcuts in member variables.
+  int scanLine = m_pollingOrder[m_pollingStep++ % 32];
+  int bytesPerPixel = m_image->xim->bits_per_pixel / 8;
+  int bytesPerLine = m_image->xim->bytes_per_line;
+
+  Rect rect;
+  int nTilesChanged = 0;
+  int idx = 0;
+
+  for (int y = 0; y * 32 < m_height; y++) {
+    int tile_h = (m_height - y * 32 >= 32) ? 32 : m_height - y * 32;
+    if (scanLine >= tile_h)
+      break;
+    int scan_y = y * 32 + scanLine;
+    m_rowImage->get(DefaultRootWindow(m_dpy), 0, scan_y);
+    char *ptr_old = m_image->xim->data + scan_y * bytesPerLine;
+    char *ptr_new = m_rowImage->xim->data;
+    for (int x = 0; x * 32 < m_width; x++) {
+      int tile_w = (m_width - x * 32 >= 32) ? 32 : m_width - x * 32;
+      int nBytes = tile_w * bytesPerPixel;
+
+      char wasChanged = (memcmp(ptr_old, ptr_new, nBytes) != 0);
+      m_rateMatrix[idx] += wasChanged;
+
+      if (grandStep) {
+        if (m_rateMatrix[idx] <= VIDEO_THRESHOLD_0) {
+          m_videoFlags[idx] = 0;
+        } else if (m_rateMatrix[idx] >= VIDEO_THRESHOLD_1) {
+          m_videoFlags[idx] = 1;
+        }
+        m_rateMatrix[idx] = 0;
+      }
+
+      m_changedFlags[idx] |= wasChanged;
+      if ( m_changedFlags[idx] && (!m_videoFlags[idx] || grandStep) ) {
+        if (tile_w == 32 && tile_h == 32) {
+          m_tileImage->get(DefaultRootWindow(m_dpy), x * 32, y * 32);
+        } else {
+          m_tileImage->get(DefaultRootWindow(m_dpy), x * 32, y * 32,
+                           tile_w, tile_h);
+        }
+        m_image->updateRect(m_tileImage, x * 32, y * 32);
+        rect.setXYWH(x * 32, y * 32, tile_w, tile_h);
+        m_server->add_changed(rect);
+        nTilesChanged++;
+        m_changedFlags[idx] = 0;
+      }
+
+      if (wasChanged) {
+      }
+
+      ptr_old += nBytes;
+      ptr_new += nBytes;
+      idx++;
+    }
   }
+
+  if (nTilesChanged)
+    m_server->tryUpdate();
 }
 
 void PollingManager::poll_SkipCycles()
index 9befee9b8724169e3b889819d8c6ff8efa20ba95..59eb22e06cc3ab39203890a3e0d29374af1e2dd0 100644 (file)
@@ -43,6 +43,7 @@ public:
 
 protected:
 
+  void poll_DetectVideo();
   void poll_SkipCycles();
   void poll_Traditional();
   void poll_Dumb();
@@ -61,9 +62,12 @@ protected:
 
   char *m_statusMatrix;
 
+  char *m_rateMatrix;
+  char *m_videoFlags;
+  char *m_changedFlags;
+
   unsigned int m_pollingStep;
   static const int m_pollingOrder[];
-  static const char m_bitsSet[];
 
 };