Bug 1446309 - Store a shared surface's dirty rect update if we cannot process it immediately. r=nical
☠☠ backed out by b44b01a42d8c ☠ ☠
authorAndrew Osmond <aosmond@mozilla.com>
Fri, 10 Aug 2018 09:30:24 -0400
changeset 431003 3f41992ab77ee921028fb0e05b719e128eb9ec71
parent 430971 1d475ec08b135446685a267b9a0e8d876a3d4c7f
child 431004 b44b01a42d8c47688ad9af21fd9463c8e19f791b
push id34419
push userbtara@mozilla.com
push dateSat, 11 Aug 2018 03:43:33 +0000
treeherdermozilla-central@7ed5ed3d4814 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnical
bugs1446309
milestone63.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1446309 - Store a shared surface's dirty rect update if we cannot process it immediately. r=nical Multiple tabs in the same process could be viewing the same image. If it is an image we are taking some time to download from the network, it may not be displayed all at once. As a result, it could generate several dirty rects for the newly decoded lines each time we paint. Since we only apply the dirty rect to the active tab, and forget it afterwards, then when one returns to the other tab(s), it may not reupload all of the modified image data. Now we save the dirty rect and accumulate it for the handles which weren't able to be updated immediately.
gfx/layers/ipc/SharedSurfacesChild.cpp
--- a/gfx/layers/ipc/SharedSurfacesChild.cpp
+++ b/gfx/layers/ipc/SharedSurfacesChild.cpp
@@ -25,30 +25,49 @@ public:
   ImageKeyData(WebRenderLayerManager* aManager,
                const wr::ImageKey& aImageKey)
     : mManager(aManager)
     , mImageKey(aImageKey)
   { }
 
   ImageKeyData(ImageKeyData&& aOther)
     : mManager(std::move(aOther.mManager))
+    , mDirtyRect(std::move(aOther.mDirtyRect))
     , mImageKey(aOther.mImageKey)
   { }
 
   ImageKeyData& operator=(ImageKeyData&& aOther)
   {
     mManager = std::move(aOther.mManager);
+    mDirtyRect = std::move(aOther.mDirtyRect);
     mImageKey = aOther.mImageKey;
     return *this;
   }
 
+  void MergeDirtyRect(const Maybe<IntRect>& aDirtyRect)
+  {
+    if (mDirtyRect) {
+      if (aDirtyRect) {
+        mDirtyRect->UnionRect(mDirtyRect.ref(), aDirtyRect.ref());
+      }
+    } else {
+      mDirtyRect = aDirtyRect;
+    }
+  }
+
+  Maybe<IntRect> TakeDirtyRect()
+  {
+    return std::move(mDirtyRect);
+  }
+
   ImageKeyData(const ImageKeyData&) = delete;
   ImageKeyData& operator=(const ImageKeyData&) = delete;
 
   RefPtr<WebRenderLayerManager> mManager;
+  Maybe<IntRect> mDirtyRect;
   wr::ImageKey mImageKey;
 };
 
 class SharedSurfacesChild::SharedUserData final
 {
 public:
   explicit SharedUserData(const wr::ExternalImageId& aId)
     : mId(aId)
@@ -138,24 +157,33 @@ public:
         MOZ_ASSERT(wrBridge);
 
         // Even if the manager is the same, its underlying WebRenderBridgeChild
         // can change state. If our namespace differs, then our old key has
         // already been discarded.
         bool ownsKey = wrBridge->GetNamespace() == entry.mImageKey.mNamespace;
         if (!ownsKey) {
           entry.mImageKey = wrBridge->GetNextImageKey();
+          entry.TakeDirtyRect();
           aResources.AddExternalImage(mId, entry.mImageKey);
-        } else if (aDirtyRect) {
-          aResources.UpdateExternalImage(mId, entry.mImageKey,
-                                         ViewAs<ImagePixel>(aDirtyRect.ref()));
+        } else {
+          entry.MergeDirtyRect(aDirtyRect);
+          Maybe<IntRect> dirtyRect = entry.TakeDirtyRect();
+          if (dirtyRect) {
+            aResources.UpdateExternalImage(mId, entry.mImageKey,
+                                           ViewAs<ImagePixel>(dirtyRect.ref()));
+          }
         }
 
         key = entry.mImageKey;
         found = true;
+      } else {
+        // We don't have the resource update queue for this manager, so just
+        // accumulate the dirty rects until it is requested.
+        entry.MergeDirtyRect(aDirtyRect);
       }
     }
 
     if (!found) {
       key = aManager->WrBridge()->GetNextImageKey();
       ImageKeyData data(aManager, key);
       mKeys.AppendElement(std::move(data));
       aResources.AddExternalImage(mId, key);
@@ -311,17 +339,17 @@ SharedSurfacesChild::Share(SourceSurface
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(aSurface);
   MOZ_ASSERT(aManager);
 
   // Each time the surface changes, the producers of SourceSurfaceSharedData
   // surfaces promise to increment the invalidation counter each time the
   // surface has changed. We can use this counter to determine whether or not
-  // we should upate our paired ImageKey.
+  // we should update our paired ImageKey.
   Maybe<IntRect> dirtyRect = aSurface->TakeDirtyRect();
   SharedUserData* data = nullptr;
   nsresult rv = SharedSurfacesChild::ShareInternal(aSurface, &data);
   if (NS_SUCCEEDED(rv)) {
     MOZ_ASSERT(data);
     aKey = data->UpdateKey(aManager, aResources, dirtyRect);
   }