]> source.dussan.org Git - tigervnc.git/commitdiff
Send lossless refresh even with pending updates 622/head
authorPierre Ossman <ossman@cendio.se>
Fri, 23 Mar 2018 10:45:51 +0000 (11:45 +0100)
committerPierre Ossman <ossman@cendio.se>
Wed, 28 Mar 2018 10:50:41 +0000 (12:50 +0200)
There might be parts of the screen that haven't changed and can
therefore be refreshed. Figure which parts these are and send just
those.

common/rfb/VNCSConnectionST.cxx
common/rfb/VNCServerST.cxx
common/rfb/VNCServerST.h

index 3f92a4293d924ee48dadc096bc924e3a9d70dda0..126fb4e8eb8e868b8035231cd47ff035fb5ba8c5 100644 (file)
@@ -965,18 +965,13 @@ void VNCSConnectionST::writeNoDataUpdate()
 
 void VNCSConnectionST::writeDataUpdate()
 {
-  Region req;
+  Region req, pending;
   UpdateInfo ui;
   bool needNewUpdateInfo;
   const RenderedCursor *cursor;
 
   updates.enable_copyrect(cp.useCopyRect);
 
-  // See if we are allowed to send anything right now (the framebuffer
-  // might have changed in ways we haven't yet been informed of).
-  if (!server->checkUpdate())
-    return;
-
   // See what the client has requested (if anything)
   if (continuousUpdates)
     req = cuRegion.union_(requested);
@@ -986,6 +981,9 @@ void VNCSConnectionST::writeDataUpdate()
   if (req.is_empty())
     return;
 
+  // Get any framebuffer changes we haven't yet been informed of
+  pending = server->getPendingRegion();
+
   // Get the lists of updates. Prior to exporting the data to the `ui' object,
   // getUpdateInfo() will normalize the `updates' object such way that its
   // `changed' and `copied' regions would not intersect.
@@ -1027,17 +1025,24 @@ void VNCSConnectionST::writeDataUpdate()
     updateRenderedCursor = false;
   }
 
-  // Return if there is nothing to send the client.
-
-  if (updates.is_empty() && !writer()->needFakeUpdate() &&
-      !encodeManager.needsLosslessRefresh(req))
-    return;
-
   // The `updates' object could change, make sure we have valid update info.
 
   if (needNewUpdateInfo)
     updates.getUpdateInfo(&ui, req);
 
+  // If there are queued updates then we cannot safely send an update
+  // without risking a partially updated screen
+
+  if (!pending.is_empty()) {
+    // However we might still be able to send a lossless refresh
+    req.assign_subtract(pending);
+    req.assign_subtract(ui.changed);
+    req.assign_subtract(ui.copied);
+
+    ui.changed.clear();
+    ui.copied.clear();
+  }
+
   // Does the client need a server-side rendered cursor?
 
   cursor = NULL;
@@ -1059,6 +1064,8 @@ void VNCSConnectionST::writeDataUpdate()
     damagedCursorRegion.assign_union(ui.changed.intersect(renderedCursorRect));
   }
 
+  // Return if there is nothing to send the client.
+
   if (ui.is_empty() && !writer()->needFakeUpdate() &&
       !encodeManager.needsLosslessRefresh(req))
     return;
index 15df71b9c465ddf5269808148f577ac748798605..95870c9266368ff9b08d952bdc9266162cbffa97 100644 (file)
@@ -656,17 +656,21 @@ void VNCServerST::writeUpdate()
 // checkUpdate() is called by clients to see if it is safe to read from
 // the framebuffer at this time.
 
-bool VNCServerST::checkUpdate()
+Region VNCServerST::getPendingRegion()
 {
+  UpdateInfo ui;
+
   // Block clients as the frame buffer cannot be safely accessed
   if (blockCounter > 0)
-    return false;
+    return pb->getRect();
 
   // Block client from updating if there are pending updates
-  if (!comparer->is_empty())
-    return false;
+  if (comparer->is_empty())
+    return Region();
+
+  comparer->getUpdateInfo(&ui, pb->getRect());
 
-  return true;
+  return ui.changed.union_(ui.copied);
 }
 
 const RenderedCursor* VNCServerST::getRenderedCursor()
index 9a1a44d139152dea721bc9a5728def34ec4fd7bc..b7845ddd0595d79e67cdeaf0ddd9a80ccb4e38a5 100644 (file)
@@ -229,7 +229,7 @@ namespace rfb {
     void stopFrameClock();
     int msToNextUpdate();
     void writeUpdate();
-    bool checkUpdate();
+    Region getPendingRegion();
     const RenderedCursor* getRenderedCursor();
 
     void notifyScreenLayoutChange(VNCSConnectionST *requester);