Bug 1368386 - Only call mInvalidRegion.GetRegion() when an up-to-date valid region is requested. r?mattwoodrow draft
authorMarkus Stange <mstange@themasta.com>
Thu, 15 Jun 2017 23:35:38 -0400
changeset 595144 71068805c8b668e78485eac76a6314ddbec605fc
parent 595034 a8ce8f26acd2931e1a2ae8c50c95788e54116a0c
child 633639 9448368ec81b542df262d764137c35696afee3e7
push id64264
push userbmo:mstange@themasta.com
push dateFri, 16 Jun 2017 03:36:02 +0000
reviewersmattwoodrow
bugs1368386
milestone56.0a1
Bug 1368386 - Only call mInvalidRegion.GetRegion() when an up-to-date valid region is requested. r?mattwoodrow MozReview-Commit-ID: IHb0fNAzyjj
gfx/layers/Layers.h
--- a/gfx/layers/Layers.h
+++ b/gfx/layers/Layers.h
@@ -1795,17 +1795,17 @@ public:
    * Adds to the current invalid rect.
    */
   void AddInvalidRect(const gfx::IntRect& aRect) { mInvalidRegion.Add(aRect); }
 
   /**
    * Clear the invalid rect, marking the layer as being identical to what is currently
    * composited.
    */
-  void ClearInvalidRect() { mInvalidRegion.SetEmpty(); }
+  virtual void ClearInvalidRect() { mInvalidRegion.SetEmpty(); }
 
   // These functions allow attaching an AsyncPanZoomController to this layer,
   // and can be used anytime.
   // A layer has an APZC at index aIndex only-if GetFrameMetrics(aIndex).IsScrollable();
   // attempting to get an APZC for a non-scrollable metrics will return null.
   // The aIndex for these functions must be less than GetScrollMetadataCount().
   void SetAsyncPanZoomController(uint32_t aIndex, AsyncPanZoomController *controller);
   AsyncPanZoomController* GetAsyncPanZoomController(uint32_t aIndex) const;
@@ -1992,41 +1992,64 @@ public:
    * performance.
    */
   void SetAllowResidualTranslation(bool aAllow) { mAllowResidualTranslation = aAllow; }
 
   void SetValidRegion(const nsIntRegion& aRegion)
   {
     MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) ValidRegion", this));
     mValidRegion = aRegion;
+    mValidRegionIsCurrent = true;
     Mutated();
   }
 
   /**
    * Can be used anytime
    */
-  const nsIntRegion& GetValidRegion() const { return mValidRegion; }
+  const nsIntRegion& GetValidRegion() const
+  {
+    EnsureValidRegionIsCurrent();
+    return mValidRegion;
+  }
 
   void InvalidateWholeLayer()
   {
-    InvalidateRegion(GetValidRegion().GetBounds());
+    mInvalidRegion.Add(GetValidRegion().GetBounds());
+    ClearValidRegion();
   }
 
-  void ClearValidRegion() { mValidRegion.SetEmpty(); }
+  void ClearValidRegion()
+  {
+    mValidRegion.SetEmpty();
+    mValidRegionIsCurrent = true;
+  }
   void AddToValidRegion(const nsIntRegion& aRegion)
   {
+    EnsureValidRegionIsCurrent();
     mValidRegion.OrWith(aRegion);
   }
   void SubtractFromValidRegion(const nsIntRegion& aRegion)
   {
+    EnsureValidRegionIsCurrent();
     mValidRegion.SubOut(aRegion);
   }
   void UpdateValidRegionAfterInvalidRegionChanged()
   {
-    SubtractFromValidRegion(mInvalidRegion.GetRegion());
+    // Changes to mInvalidRegion will be applied to mValidRegion on the next
+    // call to EnsureValidRegionIsCurrent().
+    mValidRegionIsCurrent = false;
+  }
+
+  void ClearInvalidRect() override
+  {
+    // mInvalidRegion is about to be reset. This is the last chance to apply
+    // any pending changes from it to mValidRegion. Do that by calling
+    // EnsureValidRegionIsCurrent().
+    EnsureValidRegionIsCurrent();
+    mInvalidRegion.SetEmpty();
   }
 
   virtual PaintedLayer* AsPaintedLayer() override { return this; }
 
   MOZ_LAYER_DECL_NAME("PaintedLayer", TYPE_PAINTED)
 
   virtual void ComputeEffectiveTransforms(const gfx::Matrix4x4& aTransformToSurface) override
   {
@@ -2076,16 +2099,17 @@ public:
    */
   gfxPoint GetResidualTranslation() const { return mResidualTranslation; }
 
 protected:
   PaintedLayer(LayerManager* aManager, void* aImplData,
               LayerManager::PaintedLayerCreationHint aCreationHint = LayerManager::NONE)
     : Layer(aManager, aImplData)
     , mValidRegion()
+    , mValidRegionIsCurrent(true)
     , mCreationHint(aCreationHint)
     , mUsedForReadback(false)
     , mAllowResidualTranslation(false)
   {
   }
 
   virtual void PrintInfo(std::stringstream& aStream, const char* aPrefix) override;
 
@@ -2094,17 +2118,44 @@ protected:
   /**
    * ComputeEffectiveTransforms snaps the ideal transform to get mEffectiveTransform.
    * mResidualTranslation is the translation that should be applied *before*
    * mEffectiveTransform to get the ideal transform.
    */
   gfxPoint mResidualTranslation;
 
 private:
-  nsIntRegion mValidRegion;
+  /**
+   * Needs to be called prior to accessing mValidRegion, unless mValidRegion is
+   * being completely overwritten.
+   */
+  void EnsureValidRegionIsCurrent() const
+  {
+    if (!mValidRegionIsCurrent) {
+      // Apply any pending mInvalidRegion changes to mValidRegion.
+      if (!mValidRegion.IsEmpty()) {
+        // Calling mInvalidRegion.GetRegion() is expensive.
+        // That's why we delay the adjustment of mValidRegion for as long as
+        // possible, so that multiple modifications to mInvalidRegion can be
+        // applied to mValidRegion in one go.
+        mValidRegion.SubOut(mInvalidRegion.GetRegion());
+      }
+      mValidRegionIsCurrent = true;
+    }
+  }
+
+  /**
+   * The layer's valid region. If mValidRegionIsCurrent is false, then
+   * mValidRegion has not yet been updated for recent changes to
+   * mInvalidRegion. Those pending changes can be applied by calling
+   * EnsureValidRegionIsCurrent().
+   */
+  mutable nsIntRegion mValidRegion;
+
+  mutable bool mValidRegionIsCurrent;
 
 protected:
   /**
    * The creation hint that was used when constructing this layer.
    */
   const LayerManager::PaintedLayerCreationHint mCreationHint;
   /**
    * Set when this PaintedLayer is participating in readback, i.e. some