Bug 1368386 - Make PaintedLayer::mValidRegion private so that its access can be tightly controlled. r?mattwoodrow draft
authorMarkus Stange <mstange@themasta.com>
Thu, 15 Jun 2017 18:20:53 -0400
changeset 595034 a8ce8f26acd2931e1a2ae8c50c95788e54116a0c
parent 595033 af414960e760cd9250ff2bc7dc5a2c2620198fac
child 595035 6eacda5d28307d80034ccd927c358c41ed393c0b
child 595112 b95969f0d6984b8b0aa296f64419709cdfa55c36
child 595144 71068805c8b668e78485eac76a6314ddbec605fc
push id64223
push userbmo:mstange@themasta.com
push dateThu, 15 Jun 2017 22:26:05 +0000
reviewersmattwoodrow
bugs1368386
milestone56.0a1
Bug 1368386 - Make PaintedLayer::mValidRegion private so that its access can be tightly controlled. r?mattwoodrow MozReview-Commit-ID: LdtH3hrXT5v
gfx/layers/Layers.cpp
gfx/layers/Layers.h
gfx/layers/basic/BasicPaintedLayer.cpp
gfx/layers/basic/BasicPaintedLayer.h
gfx/layers/client/ClientPaintedLayer.cpp
gfx/layers/client/ClientPaintedLayer.h
gfx/layers/client/ClientTiledPaintedLayer.cpp
gfx/layers/client/ClientTiledPaintedLayer.h
gfx/layers/wr/WebRenderPaintedLayer.cpp
gfx/layers/wr/WebRenderPaintedLayer.h
gfx/layers/wr/WebRenderPaintedLayerBlob.cpp
gfx/layers/wr/WebRenderPaintedLayerBlob.h
--- a/gfx/layers/Layers.cpp
+++ b/gfx/layers/Layers.cpp
@@ -2093,31 +2093,33 @@ Layer::RemoveUserData(void* aKey)
   UniquePtr<LayerUserData> d(static_cast<LayerUserData*>(mUserData.Remove(static_cast<gfx::UserDataKey*>(aKey))));
   return d;
 }
 
 void
 PaintedLayer::PrintInfo(std::stringstream& aStream, const char* aPrefix)
 {
   Layer::PrintInfo(aStream, aPrefix);
-  if (!mValidRegion.IsEmpty()) {
-    AppendToString(aStream, mValidRegion, " [valid=", "]");
+  nsIntRegion validRegion = GetValidRegion();
+  if (!validRegion.IsEmpty()) {
+    AppendToString(aStream, validRegion, " [valid=", "]");
   }
 }
 
 void
 PaintedLayer::DumpPacket(layerscope::LayersPacket* aPacket, const void* aParent)
 {
   Layer::DumpPacket(aPacket, aParent);
   // get this layer data
   using namespace layerscope;
   LayersPacket::Layer* layer = aPacket->mutable_layer(aPacket->layer_size()-1);
   layer->set_type(LayersPacket::Layer::PaintedLayer);
-  if (!mValidRegion.IsEmpty()) {
-    DumpRegion(layer->mutable_valid(), mValidRegion);
+  nsIntRegion validRegion = GetValidRegion();
+  if (!validRegion.IsEmpty()) {
+    DumpRegion(layer->mutable_valid(), validRegion);
   }
 }
 
 void
 ContainerLayer::PrintInfo(std::stringstream& aStream, const char* aPrefix)
 {
   Layer::PrintInfo(aStream, aPrefix);
   if (UseIntermediateSurface()) {
--- a/gfx/layers/Layers.h
+++ b/gfx/layers/Layers.h
@@ -2005,16 +2005,30 @@ public:
    */
   const nsIntRegion& GetValidRegion() const { return mValidRegion; }
 
   void InvalidateWholeLayer()
   {
     InvalidateRegion(GetValidRegion().GetBounds());
   }
 
+  void ClearValidRegion() { mValidRegion.SetEmpty(); }
+  void AddToValidRegion(const nsIntRegion& aRegion)
+  {
+    mValidRegion.OrWith(aRegion);
+  }
+  void SubtractFromValidRegion(const nsIntRegion& aRegion)
+  {
+    mValidRegion.SubOut(aRegion);
+  }
+  void UpdateValidRegionAfterInvalidRegionChanged()
+  {
+    SubtractFromValidRegion(mInvalidRegion.GetRegion());
+  }
+
   virtual PaintedLayer* AsPaintedLayer() override { return this; }
 
   MOZ_LAYER_DECL_NAME("PaintedLayer", TYPE_PAINTED)
 
   virtual void ComputeEffectiveTransforms(const gfx::Matrix4x4& aTransformToSurface) override
   {
     gfx::Matrix4x4 idealTransform = GetLocalTransform() * aTransformToSurface;
     gfx::Matrix residual;
@@ -2031,17 +2045,17 @@ public:
 #ifdef DEBUG
       DebugOnly<mozilla::gfx::Point> transformed = idealTransform.TransformPoint(
         mozilla::gfx::Point(mResidualTranslation.x, mResidualTranslation.y)
       ) - *&transformedOrig;
 #endif
       NS_ASSERTION(-0.5 <= (&transformed)->x && (&transformed)->x < 0.5 &&
                    -0.5 <= (&transformed)->y && (&transformed)->y < 0.5,
                    "Residual translation out of range");
-      mValidRegion.SetEmpty();
+      ClearValidRegion();
     }
     ComputeEffectiveTransformForMaskLayers(aTransformToSurface);
   }
 
   LayerManager::PaintedLayerCreationHint GetCreationHint() const { return mCreationHint; }
 
   bool UsedForReadback() { return mUsedForReadback; }
   void SetUsedForReadback(bool aUsed) { mUsedForReadback = aUsed; }
@@ -2078,17 +2092,21 @@ protected:
   virtual void DumpPacket(layerscope::LayersPacket* aPacket, const void* aParent) override;
 
   /**
    * 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;
+
+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
    * ReadbackLayer (may) be getting its background from this layer.
    */
--- a/gfx/layers/basic/BasicPaintedLayer.cpp
+++ b/gfx/layers/basic/BasicPaintedLayer.cpp
@@ -53,17 +53,17 @@ BasicPaintedLayer::PaintThebes(gfxContex
 
   NS_ASSERTION(BasicManager()->InDrawing(),
                "Can only draw in drawing phase");
 
   float opacity = GetEffectiveOpacity();
   CompositionOp effectiveOperator = GetEffectiveOperator(this);
 
   if (!BasicManager()->IsRetained()) {
-    mValidRegion.SetEmpty();
+    ClearValidRegion();
     mContentClient->Clear();
 
     nsIntRegion toDraw = IntersectWithClip(GetLocalVisibleRegion().ToUnknownRegion(), aContext);
 
     RenderTraceInvalidateStart(this, "FFFF00", toDraw.GetBounds());
 
     if (!toDraw.IsEmpty() && !IsHidden()) {
       if (!aCallback) {
@@ -159,17 +159,17 @@ BasicPaintedLayer::Validate(LayerManager
     }
   }
 #endif
   if (mDrawAtomically) {
     flags |= RotatedContentBuffer::PAINT_NO_ROTATION;
   }
   PaintState state =
     mContentClient->BeginPaintBuffer(this, flags);
-  mValidRegion.Sub(mValidRegion, state.mRegionToInvalidate);
+  SubtractFromValidRegion(state.mRegionToInvalidate);
 
   DrawTarget* target = mContentClient->BorrowDrawTargetForPainting(state);
   if (target && target->IsValid()) {
     // The area that became invalid and is visible needs to be repainted
     // (this could be the whole visible area if our buffer switched
     // from RGB to RGBA, because we might need to repaint with
     // subpixel AA)
     state.mRegionToInvalidate.And(state.mRegionToInvalidate,
--- a/gfx/layers/basic/BasicPaintedLayer.h
+++ b/gfx/layers/basic/BasicPaintedLayer.h
@@ -51,45 +51,45 @@ public:
                  "Can only set properties in construction phase");
     PaintedLayer::SetVisibleRegion(aRegion);
   }
   virtual void InvalidateRegion(const nsIntRegion& aRegion) override
   {
     NS_ASSERTION(BasicManager()->InConstruction(),
                  "Can only set properties in construction phase");
     mInvalidRegion.Add(aRegion);
-    mValidRegion.Sub(mValidRegion, mInvalidRegion.GetRegion());
+    UpdateValidRegionAfterInvalidRegionChanged();
   }
 
   virtual void PaintThebes(gfxContext* aContext,
                            Layer* aMaskLayer,
                            LayerManager::DrawPaintedLayerCallback aCallback,
                            void* aCallbackData) override;
 
   virtual void Validate(LayerManager::DrawPaintedLayerCallback aCallback,
                         void* aCallbackData,
                         ReadbackProcessor* aReadback) override;
 
   virtual void ClearCachedResources() override
   {
     if (mContentClient) {
       mContentClient->Clear();
     }
-    mValidRegion.SetEmpty();
+    ClearValidRegion();
   }
 
   virtual void ComputeEffectiveTransforms(const gfx::Matrix4x4& aTransformToSurface) override
   {
     if (!BasicManager()->IsRetained()) {
       // Don't do any snapping of our transform, since we're just going to
       // draw straight through without intermediate buffers.
       mEffectiveTransform = GetLocalTransform() * aTransformToSurface;
       if (gfxPoint(0,0) != mResidualTranslation) {
         mResidualTranslation = gfxPoint(0,0);
-        mValidRegion.SetEmpty();
+        ClearValidRegion();
       }
       ComputeEffectiveTransformForMaskLayers(aTransformToSurface);
       return;
     }
     PaintedLayer::ComputeEffectiveTransforms(aTransformToSurface);
   }
 
   BasicLayerManager* BasicManager()
@@ -115,17 +115,17 @@ protected:
     aCallback(this, aContext, aExtendedRegionToDraw, aExtendedRegionToDraw,
               aClip, aRegionToInvalidate, aCallbackData);
     // Everything that's visible has been validated. Do this instead of just
     // OR-ing with aRegionToDraw, since that can lead to a very complex region
     // here (OR doesn't automatically simplify to the simplest possible
     // representation of a region.)
     nsIntRegion tmp;
     tmp.Or(mVisibleRegion.ToUnknownRegion(), aExtendedRegionToDraw);
-    mValidRegion.Or(mValidRegion, tmp);
+    AddToValidRegion(tmp);
   }
 
   RefPtr<ContentClientBasic> mContentClient;
   gfx::BackendType mBackend;
 };
 
 } // namespace layers
 } // namespace mozilla
--- a/gfx/layers/client/ClientPaintedLayer.cpp
+++ b/gfx/layers/client/ClientPaintedLayer.cpp
@@ -48,17 +48,17 @@ ClientPaintedLayer::PaintThebes(nsTArray
   if (!(flags & RotatedContentBuffer::PAINT_WILL_RESAMPLE)) {
     if (MayResample()) {
       flags |= RotatedContentBuffer::PAINT_WILL_RESAMPLE;
     }
   }
 #endif
   PaintState state =
     mContentClient->BeginPaintBuffer(this, flags);
-  mValidRegion.Sub(mValidRegion, state.mRegionToInvalidate);
+  SubtractFromValidRegion(state.mRegionToInvalidate);
 
   if (!state.mRegionToDraw.IsEmpty() && !ClientManager()->GetPaintedLayerCallback()) {
     ClientManager()->SetTransactionIncomplete();
     mContentClient->EndPaint(nullptr);
     return;
   }
 
   // The area that became invalid and is visible needs to be repainted
@@ -96,17 +96,17 @@ ClientPaintedLayer::PaintThebes(nsTArray
     didUpdate = true;
   }
 
   mContentClient->EndPaint(aReadbackUpdates);
 
   if (didUpdate) {
     Mutated();
 
-    mValidRegion.Or(mValidRegion, state.mRegionToDraw);
+    AddToValidRegion(state.mRegionToDraw);
 
     ContentClientRemote* contentClientRemote = static_cast<ContentClientRemote*>(mContentClient.get());
     MOZ_ASSERT(contentClientRemote->GetIPCHandle());
 
     // Hold(this) ensures this layer is kept alive through the current transaction
     // The ContentClient assumes this layer is kept alive (e.g., in CreateBuffer),
     // so deleting this Hold for whatever reason will break things.
     ClientManager()->Hold(this);
--- a/gfx/layers/client/ClientPaintedLayer.h
+++ b/gfx/layers/client/ClientPaintedLayer.h
@@ -56,29 +56,29 @@ public:
                  "Can only set properties in construction phase");
     PaintedLayer::SetVisibleRegion(aRegion);
   }
   virtual void InvalidateRegion(const nsIntRegion& aRegion) override
   {
     NS_ASSERTION(ClientManager()->InConstruction(),
                  "Can only set properties in construction phase");
     mInvalidRegion.Add(aRegion);
-    mValidRegion.Sub(mValidRegion, mInvalidRegion.GetRegion());
+    UpdateValidRegionAfterInvalidRegionChanged();
   }
 
   virtual void RenderLayer() override { RenderLayerWithReadback(nullptr); }
 
   virtual void RenderLayerWithReadback(ReadbackProcessor *aReadback) override;
 
   virtual void ClearCachedResources() override
   {
     if (mContentClient) {
       mContentClient->Clear();
     }
-    mValidRegion.SetEmpty();
+    ClearValidRegion();
     DestroyBackBuffer();
   }
 
   virtual void HandleMemoryPressure() override
   {
     if (mContentClient) {
       mContentClient->HandleMemoryPressure();
     }
--- a/gfx/layers/client/ClientTiledPaintedLayer.cpp
+++ b/gfx/layers/client/ClientTiledPaintedLayer.cpp
@@ -46,17 +46,17 @@ ClientTiledPaintedLayer::~ClientTiledPai
 }
 
 void
 ClientTiledPaintedLayer::ClearCachedResources()
 {
   if (mContentClient) {
     mContentClient->ClearCachedResources();
   }
-  mValidRegion.SetEmpty();
+  ClearValidRegion();
   mContentClient = nullptr;
 }
 
 void
 ClientTiledPaintedLayer::FillSpecificAttributes(SpecificLayerAttributes& aAttrs)
 {
   aAttrs = PaintedLayerAttributes(GetValidRegion());
 }
@@ -319,35 +319,36 @@ ClientTiledPaintedLayer::RenderHighPreci
     if (mPaintData.mCriticalDisplayPort) {
       oldValidRegion.And(oldValidRegion, mPaintData.mCriticalDisplayPort->ToUnknownRect());
     }
 
     TILING_LOG("TILING %p: Progressive update with old valid region %s\n", this, Stringify(oldValidRegion).c_str());
 
     nsIntRegion drawnRegion;
     bool updatedBuffer =
-      mContentClient->GetTiledBuffer()->ProgressiveUpdate(mValidRegion, aInvalidRegion,
+      mContentClient->GetTiledBuffer()->ProgressiveUpdate(GetValidRegion(), aInvalidRegion,
                       oldValidRegion, drawnRegion, &mPaintData, aCallback, aCallbackData);
-    mValidRegion.OrWith(drawnRegion);
+    AddToValidRegion(drawnRegion);
     return updatedBuffer;
   }
 
   // Otherwise do a non-progressive paint. We must do this even when
   // the region to paint is empty as the valid region may have shrunk.
 
-  mValidRegion = aVisibleRegion;
+  nsIntRegion validRegion = aVisibleRegion;
   if (mPaintData.mCriticalDisplayPort) {
-    mValidRegion.And(mValidRegion, mPaintData.mCriticalDisplayPort->ToUnknownRect());
+    validRegion.AndWith(mPaintData.mCriticalDisplayPort->ToUnknownRect());
   }
+  SetValidRegion(validRegion);
 
   TILING_LOG("TILING %p: Non-progressive paint invalid region %s\n", this, Stringify(aInvalidRegion).c_str());
-  TILING_LOG("TILING %p: Non-progressive paint new valid region %s\n", this, Stringify(mValidRegion).c_str());
+  TILING_LOG("TILING %p: Non-progressive paint new valid region %s\n", this, Stringify(GetValidRegion()).c_str());
 
   mContentClient->GetTiledBuffer()->SetFrameResolution(mPaintData.mResolution);
-  mContentClient->GetTiledBuffer()->PaintThebes(mValidRegion, aInvalidRegion, aInvalidRegion,
+  mContentClient->GetTiledBuffer()->PaintThebes(GetValidRegion(), aInvalidRegion, aInvalidRegion,
                                                 aCallback, aCallbackData);
   mPaintData.mPaintFinished = true;
   return true;
 }
 
 bool
 ClientTiledPaintedLayer::RenderLowPrecision(const nsIntRegion& aInvalidRegion,
                                            const nsIntRegion& aVisibleRegion,
@@ -381,17 +382,17 @@ ClientTiledPaintedLayer::RenderLowPrecis
     // Invalidate previously valid content that is no longer visible
     if (mPaintData.mLowPrecisionPaintCount == 1) {
       mLowPrecisionValidRegion.And(mLowPrecisionValidRegion, aVisibleRegion);
     }
     mPaintData.mLowPrecisionPaintCount++;
 
     // Remove the valid high-precision region from the invalid low-precision
     // region. We don't want to spend time drawing things twice.
-    invalidRegion.SubOut(mValidRegion);
+    invalidRegion.SubOut(GetValidRegion());
 
     TILING_LOG("TILING %p: Progressive paint: low-precision invalid region is %s\n", this, Stringify(invalidRegion).c_str());
     TILING_LOG("TILING %p: Progressive paint: low-precision old valid region is %s\n", this, Stringify(oldValidRegion).c_str());
 
     if (!invalidRegion.IsEmpty()) {
       nsIntRegion drawnRegion;
       updatedBuffer = mContentClient->GetLowPrecisionTiledBuffer()->ProgressiveUpdate(
                             mLowPrecisionValidRegion, invalidRegion, oldValidRegion,
@@ -443,17 +444,17 @@ ClientTiledPaintedLayer::RenderLayer()
       (mCreationHint == LayerManager::NONE ||
        layerSize <= tileSize ||
        isHalfTileWidthOrHeight) &&
       SingleTiledContentClient::ClientSupportsLayerSize(layerSize, ClientManager()) &&
       gfxPrefs::LayersSingleTileEnabled();
 
   if (mContentClient && mHaveSingleTiledContentClient && !wantSingleTiledContentClient) {
     mContentClient = nullptr;
-    mValidRegion.SetEmpty();
+    ClearValidRegion();
   }
 
   if (!mContentClient) {
     if (wantSingleTiledContentClient) {
       mContentClient = new SingleTiledContentClient(*this, ClientManager());
       mHaveSingleTiledContentClient = true;
     } else {
       mContentClient = new MultiTiledContentClient(*this, ClientManager());
@@ -461,22 +462,22 @@ ClientTiledPaintedLayer::RenderLayer()
     }
 
     mContentClient->Connect();
     ClientManager()->AsShadowForwarder()->Attach(mContentClient, this);
     MOZ_ASSERT(mContentClient->GetForwarder());
   }
 
   if (mContentClient->GetTiledBuffer()->HasFormatChanged()) {
-    mValidRegion = nsIntRegion();
+    ClearValidRegion();
     mContentClient->GetTiledBuffer()->ResetPaintedAndValidState();
   }
 
   TILING_LOG("TILING %p: Initial visible region %s\n", this, Stringify(mVisibleRegion).c_str());
-  TILING_LOG("TILING %p: Initial valid region %s\n", this, Stringify(mValidRegion).c_str());
+  TILING_LOG("TILING %p: Initial valid region %s\n", this, Stringify(GetValidRegion()).c_str());
   TILING_LOG("TILING %p: Initial low-precision valid region %s\n", this, Stringify(mLowPrecisionValidRegion).c_str());
 
   nsIntRegion neededRegion = mVisibleRegion.ToUnknownRegion();
 #ifndef MOZ_IGNORE_PAINT_WILL_RESAMPLE
   // This is handled by PadDrawTargetOutFromRegion in TiledContentClient for mobile
   if (MayResample()) {
     // If we're resampling then bilinear filtering can read up to 1 pixel
     // outside of our texture coords. Make the visible region a single rect,
@@ -488,17 +489,17 @@ ClientTiledPaintedLayer::RenderLayer()
     IntRect padded = bounds;
     padded.Inflate(1);
     padded.IntersectRect(padded, wholeTiles);
     neededRegion = padded;
   }
 #endif
 
   nsIntRegion invalidRegion;
-  invalidRegion.Sub(neededRegion, mValidRegion);
+  invalidRegion.Sub(neededRegion, GetValidRegion());
   if (invalidRegion.IsEmpty()) {
     EndPaint();
     return;
   }
 
   if (!callback) {
     ClientManager()->SetTransactionIncomplete();
     return;
@@ -513,37 +514,39 @@ ClientTiledPaintedLayer::RenderLayer()
     BeginPaint();
     if (mPaintData.mPaintFinished) {
       return;
     }
 
     // Make sure that tiles that fall outside of the visible region or outside of the
     // critical displayport are discarded on the first update. Also make sure that we
     // only draw stuff inside the critical displayport on the first update.
-    mValidRegion.And(mValidRegion, neededRegion);
+    nsIntRegion validRegion;
+    validRegion.And(GetValidRegion(), neededRegion);
     if (mPaintData.mCriticalDisplayPort) {
-      mValidRegion.And(mValidRegion, mPaintData.mCriticalDisplayPort->ToUnknownRect());
+      validRegion.AndWith(mPaintData.mCriticalDisplayPort->ToUnknownRect());
       invalidRegion.And(invalidRegion, mPaintData.mCriticalDisplayPort->ToUnknownRect());
     }
+    SetValidRegion(validRegion);
 
-    TILING_LOG("TILING %p: First-transaction valid region %s\n", this, Stringify(mValidRegion).c_str());
+    TILING_LOG("TILING %p: First-transaction valid region %s\n", this, Stringify(validRegion).c_str());
     TILING_LOG("TILING %p: First-transaction invalid region %s\n", this, Stringify(invalidRegion).c_str());
   } else {
     if (mPaintData.mCriticalDisplayPort) {
       invalidRegion.And(invalidRegion, mPaintData.mCriticalDisplayPort->ToUnknownRect());
     }
     TILING_LOG("TILING %p: Repeat-transaction invalid region %s\n", this, Stringify(invalidRegion).c_str());
   }
 
   nsIntRegion lowPrecisionInvalidRegion;
   if (mContentClient->GetLowPrecisionTiledBuffer()) {
     // Calculate the invalid region for the low precision buffer. Make sure
     // to remove the valid high-precision area so we don't double-paint it.
     lowPrecisionInvalidRegion.Sub(neededRegion, mLowPrecisionValidRegion);
-    lowPrecisionInvalidRegion.Sub(lowPrecisionInvalidRegion, mValidRegion);
+    lowPrecisionInvalidRegion.Sub(lowPrecisionInvalidRegion, GetValidRegion());
   }
   TILING_LOG("TILING %p: Low-precision invalid region %s\n", this, Stringify(lowPrecisionInvalidRegion).c_str());
 
   bool updatedHighPrecision = RenderHighPrecision(invalidRegion,
                                                   neededRegion,
                                                   callback, data);
   if (updatedHighPrecision) {
     ClientManager()->Hold(this);
--- a/gfx/layers/client/ClientTiledPaintedLayer.h
+++ b/gfx/layers/client/ClientTiledPaintedLayer.h
@@ -50,19 +50,22 @@ protected:
 public:
   // Override name to distinguish it from ClientPaintedLayer in layer dumps
   virtual const char* Name() const override { return "TiledPaintedLayer"; }
 
   // PaintedLayer
   virtual Layer* AsLayer() override { return this; }
   virtual void InvalidateRegion(const nsIntRegion& aRegion) override {
     mInvalidRegion.Add(aRegion);
-    nsIntRegion invalidRegion = mInvalidRegion.GetRegion();
-    mValidRegion.Sub(mValidRegion, invalidRegion);
-    mLowPrecisionValidRegion.Sub(mLowPrecisionValidRegion, invalidRegion);
+    UpdateValidRegionAfterInvalidRegionChanged();
+    if (!mLowPrecisionValidRegion.IsEmpty()) {
+      // Also update mLowPrecisionValidRegion. Unfortunately we call
+      // mInvalidRegion.GetRegion() here, which is expensive.
+      mLowPrecisionValidRegion.SubOut(mInvalidRegion.GetRegion());
+    }
   }
 
   // Shadow methods
   virtual void FillSpecificAttributes(SpecificLayerAttributes& aAttrs) override;
   virtual ShadowableLayer* AsShadowableLayer() override { return this; }
 
   virtual void RenderLayer() override;
 
--- a/gfx/layers/wr/WebRenderPaintedLayer.cpp
+++ b/gfx/layers/wr/WebRenderPaintedLayer.cpp
@@ -123,17 +123,17 @@ WebRenderPaintedLayer::RenderLayer(wr::D
   if (GetVisibleRegion().IsEmpty()) {
     if (gfxPrefs::LayersDump()) {
       printf_stderr("PaintedLayer %p skipping\n", this->GetLayer());
     }
     return;
   }
 
   nsIntRegion regionToPaint;
-  regionToPaint.Sub(mVisibleRegion.ToUnknownRegion(), mValidRegion);
+  regionToPaint.Sub(mVisibleRegion.ToUnknownRegion(), GetValidRegion());
 
   // We have something to paint but can't. This usually happens only in
   // empty transactions
   if (!regionToPaint.IsEmpty() && !WrManager()->GetPaintedLayerCallback()) {
     WrManager()->SetTransactionIncomplete();
     return;
   }
 
--- a/gfx/layers/wr/WebRenderPaintedLayer.h
+++ b/gfx/layers/wr/WebRenderPaintedLayer.h
@@ -38,17 +38,17 @@ protected:
   }
 
   wr::MaybeExternalImageId mExternalImageId;
 
 public:
   virtual void InvalidateRegion(const nsIntRegion& aRegion) override
   {
     mInvalidRegion.Add(aRegion);
-    mValidRegion.Sub(mValidRegion, mInvalidRegion.GetRegion());
+    UpdateValidRegionAfterInvalidRegionChanged();
   }
 
   Layer* GetLayer() override { return this; }
   void RenderLayer(wr::DisplayListBuilder& aBuilder,
                    const StackingContextHelper& aSc) override;
   RefPtr<ImageContainer> mImageContainer;
   RefPtr<ImageClient> mImageClient;
 
--- a/gfx/layers/wr/WebRenderPaintedLayerBlob.cpp
+++ b/gfx/layers/wr/WebRenderPaintedLayerBlob.cpp
@@ -32,17 +32,17 @@ WebRenderPaintedLayerBlob::RenderLayer(w
   if (visibleRegion.IsEmpty()) {
     if (gfxPrefs::LayersDump()) {
       printf_stderr("PaintedLayer %p skipping\n", this->GetLayer());
     }
     return;
   }
 
   nsIntRegion regionToPaint;
-  regionToPaint.Sub(mVisibleRegion.ToUnknownRegion(), mValidRegion);
+  regionToPaint.Sub(mVisibleRegion.ToUnknownRegion(), GetValidRegion());
 
   // We have something to paint but can't. This usually happens only in
   // empty transactions
   if (!regionToPaint.IsEmpty() && !WrManager()->GetPaintedLayerCallback()) {
     WrManager()->SetTransactionIncomplete();
     return;
   }
 
--- a/gfx/layers/wr/WebRenderPaintedLayerBlob.h
+++ b/gfx/layers/wr/WebRenderPaintedLayerBlob.h
@@ -41,17 +41,17 @@ protected:
   }
 
   wr::MaybeExternalImageId mExternalImageId;
 
 public:
   virtual void InvalidateRegion(const nsIntRegion& aRegion) override
   {
     mInvalidRegion.Add(aRegion);
-    mValidRegion.Sub(mValidRegion, mInvalidRegion.GetRegion());
+    UpdateValidRegionAfterInvalidRegionChanged();
   }
 
   Layer* GetLayer() override { return this; }
   void RenderLayer(wr::DisplayListBuilder& aBuilder,
                    const StackingContextHelper& aSc) override;
 private:
   RefPtr<ImageContainer> mImageContainer;
   RefPtr<ImageClient> mImageClient;