LCOV - code coverage report
Current view: top level - gfx/layers - LayerTreeInvalidation.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 212 350 60.6 %
Date: 2017-07-14 16:53:18 Functions: 32 50 64.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
       2             :  * This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
       4             :  * You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : #include "LayerTreeInvalidation.h"
       7             : 
       8             : #include <stdint.h>                     // for uint32_t
       9             : #include "ImageContainer.h"             // for ImageContainer
      10             : #include "ImageLayers.h"                // for ImageLayer, etc
      11             : #include "Layers.h"                     // for Layer, ContainerLayer, etc
      12             : #include "Units.h"                      // for ParentLayerIntRect
      13             : #include "gfxRect.h"                    // for gfxRect
      14             : #include "gfxUtils.h"                   // for gfxUtils
      15             : #include "mozilla/gfx/BaseSize.h"       // for BaseSize
      16             : #include "mozilla/gfx/Point.h"          // for IntSize
      17             : #include "mozilla/mozalloc.h"           // for operator new, etc
      18             : #include "nsDataHashtable.h"            // for nsDataHashtable
      19             : #include "nsDebug.h"                    // for NS_ASSERTION
      20             : #include "nsHashKeys.h"                 // for nsPtrHashKey
      21             : #include "nsISupportsImpl.h"            // for Layer::AddRef, etc
      22             : #include "nsRect.h"                     // for IntRect
      23             : #include "nsTArray.h"                   // for AutoTArray, nsTArray_Impl
      24             : #include "mozilla/Poison.h"
      25             : #include "mozilla/layers/ImageHost.h"
      26             : #include "mozilla/layers/LayerManagerComposite.h"
      27             : #include "TreeTraversal.h"              // for ForEachNode
      28             : #include "LayersLogging.h"
      29             : 
      30             : // LayerTreeInvalidation debugging
      31             : #define LTI_DEBUG 0
      32             : 
      33             : #if LTI_DEBUG
      34             : #  define LTI_DEEPER(aPrefix) nsPrintfCString("%s  ", aPrefix).get()
      35             : #  define LTI_DUMP(rgn, label) if (!(rgn).IsEmpty()) printf_stderr("%s%p: " label " portion is %s\n", aPrefix, mLayer.get(), Stringify(rgn).c_str());
      36             : #  define LTI_LOG(...) printf_stderr(__VA_ARGS__)
      37             : #else
      38             : #  define LTI_DEEPER(aPrefix) nullptr
      39             : #  define LTI_DUMP(rgn, label)
      40             : #  define LTI_LOG(...)
      41             : #endif
      42             : 
      43             : using namespace mozilla::gfx;
      44             : 
      45             : namespace mozilla {
      46             : namespace layers {
      47             : 
      48             : struct LayerPropertiesBase;
      49             : UniquePtr<LayerPropertiesBase> CloneLayerTreePropertiesInternal(Layer* aRoot, bool aIsMask = false);
      50             : 
      51             : /**
      52             :  * Get accumulated transform of from the context creating layer to the
      53             :  * given layer.
      54             :  */
      55             : static Matrix4x4
      56           0 : GetTransformIn3DContext(Layer* aLayer) {
      57           0 :   Matrix4x4 transform = aLayer->GetLocalTransform();
      58           0 :   for (Layer* layer = aLayer->GetParent();
      59           0 :        layer && layer->Extend3DContext();
      60             :        layer = layer->GetParent()) {
      61           0 :     transform = transform * layer->GetLocalTransform();
      62             :   }
      63           0 :   return transform;
      64             : }
      65             : 
      66             : /**
      67             :  * Get a transform for the given layer depending on extending 3D
      68             :  * context.
      69             :  *
      70             :  * @return local transform for layers not participating 3D rendering
      71             :  * context, or the accmulated transform in the context for else.
      72             :  */
      73             : static Matrix4x4
      74        1557 : GetTransformForInvalidation(Layer* aLayer) {
      75        1557 :   return (!aLayer->Is3DContextLeaf() && !aLayer->Extend3DContext() ?
      76        1557 :           aLayer->GetLocalTransform() : GetTransformIn3DContext(aLayer));
      77             : }
      78             : 
      79             : static IntRect
      80         292 : TransformRect(const IntRect& aRect, const Matrix4x4& aTransform)
      81             : {
      82         292 :   if (aRect.IsEmpty()) {
      83         119 :     return IntRect();
      84             :   }
      85             : 
      86         173 :   Rect rect(aRect.x, aRect.y, aRect.width, aRect.height);
      87         173 :   rect = aTransform.TransformAndClipBounds(rect, Rect::MaxIntRect());
      88         173 :   rect.RoundOut();
      89             : 
      90         173 :   IntRect intRect;
      91         173 :   if (!gfxUtils::GfxRectToIntRect(ThebesRect(rect), &intRect)) {
      92           0 :     return IntRect();
      93             :   }
      94             : 
      95         173 :   return intRect;
      96             : }
      97             : 
      98             : static void
      99         649 : AddTransformedRegion(nsIntRegion& aDest, const nsIntRegion& aSource, const Matrix4x4& aTransform)
     100             : {
     101         788 :   for (auto iter = aSource.RectIter(); !iter.Done(); iter.Next()) {
     102         139 :     aDest.Or(aDest, TransformRect(iter.Get(), aTransform));
     103             :   }
     104         649 :   aDest.SimplifyOutward(20);
     105         649 : }
     106             : 
     107             : static void
     108         733 : AddRegion(nsIntRegion& aDest, const nsIntRegion& aSource)
     109             : {
     110         733 :   aDest.Or(aDest, aSource);
     111         733 :   aDest.SimplifyOutward(20);
     112         733 : }
     113             : 
     114             : /**
     115             :  * Walks over this layer, and all descendant layers.
     116             :  * If any of these are a ContainerLayer that reports invalidations to a PresShell,
     117             :  * then report that the entire bounds have changed.
     118             :  */
     119             : static void
     120          21 : NotifySubdocumentInvalidation(Layer* aLayer, NotifySubDocInvalidationFunc aCallback)
     121             : {
     122          42 :   ForEachNode<ForwardIterator>(
     123             :       aLayer,
     124          29 :       [aCallback] (Layer* layer)
     125           0 :       {
     126          29 :         layer->ClearInvalidRegion();
     127          29 :         if (layer->GetMaskLayer()) {
     128           0 :           NotifySubdocumentInvalidation(layer->GetMaskLayer(), aCallback);
     129             :         }
     130          29 :         for (size_t i = 0; i < layer->GetAncestorMaskLayerCount(); i++) {
     131           0 :           Layer* maskLayer = layer->GetAncestorMaskLayerAt(i);
     132           0 :           NotifySubdocumentInvalidation(maskLayer, aCallback);
     133             :         }
     134          29 :       },
     135          29 :       [aCallback] (Layer* layer)
     136           5 :       {
     137          29 :         ContainerLayer* container = layer->AsContainerLayer();
     138          29 :         if (container) {
     139           5 :           aCallback(container, container->GetLocalVisibleRegion().ToUnknownRegion());
     140             :         }
     141          50 :       });
     142          21 : }
     143             : 
     144             : struct LayerPropertiesBase : public LayerProperties
     145             : {
     146         633 :   explicit LayerPropertiesBase(Layer* aLayer)
     147         633 :     : mLayer(aLayer)
     148             :     , mMaskLayer(nullptr)
     149         633 :     , mVisibleRegion(mLayer->GetLocalVisibleRegion().ToUnknownRegion())
     150         633 :     , mPostXScale(aLayer->GetPostXScale())
     151         633 :     , mPostYScale(aLayer->GetPostYScale())
     152         633 :     , mOpacity(aLayer->GetLocalOpacity())
     153        3165 :     , mUseClipRect(!!aLayer->GetLocalClipRect())
     154             :   {
     155         633 :     MOZ_COUNT_CTOR(LayerPropertiesBase);
     156         633 :     if (aLayer->GetMaskLayer()) {
     157           0 :       mMaskLayer = CloneLayerTreePropertiesInternal(aLayer->GetMaskLayer(), true);
     158             :     }
     159         633 :     for (size_t i = 0; i < aLayer->GetAncestorMaskLayerCount(); i++) {
     160           0 :       Layer* maskLayer = aLayer->GetAncestorMaskLayerAt(i);
     161           0 :       mAncestorMaskLayers.AppendElement(CloneLayerTreePropertiesInternal(maskLayer, true));
     162             :     }
     163         633 :     if (mUseClipRect) {
     164         108 :       mClipRect = *aLayer->GetLocalClipRect();
     165             :     }
     166         633 :     mTransform = GetTransformForInvalidation(aLayer);
     167         633 :   }
     168          13 :   LayerPropertiesBase()
     169          13 :     : mLayer(nullptr)
     170          13 :     , mMaskLayer(nullptr)
     171             :   {
     172          13 :     MOZ_COUNT_CTOR(LayerPropertiesBase);
     173          13 :   }
     174         943 :   ~LayerPropertiesBase() override
     175        1278 :   {
     176         639 :     MOZ_COUNT_DTOR(LayerPropertiesBase);
     177        1247 :   }
     178             : 
     179             : protected:
     180             :   LayerPropertiesBase(const LayerPropertiesBase& a) = delete;
     181             :   LayerPropertiesBase& operator=(const LayerPropertiesBase& a) = delete;
     182             : 
     183             : public:
     184             :   nsIntRegion ComputeDifferences(Layer* aRoot,
     185             :                                  NotifySubDocInvalidationFunc aCallback) override;
     186             : 
     187             :   void MoveBy(const IntPoint& aOffset) override;
     188             : 
     189         510 :   nsIntRegion ComputeChange(const char* aPrefix,
     190             :                             NotifySubDocInvalidationFunc aCallback)
     191             :   {
     192             :     // Bug 1251615: This canary is sometimes hit. We're still not sure why.
     193         510 :     mCanary.Check();
     194        2544 :     bool transformChanged = !mTransform.FuzzyEqual(GetTransformForInvalidation(mLayer)) ||
     195        2034 :                              mLayer->GetPostXScale() != mPostXScale ||
     196        1014 :                              mLayer->GetPostYScale() != mPostYScale;
     197         510 :     const Maybe<ParentLayerIntRect>& otherClip = mLayer->GetLocalClipRect();
     198         510 :     nsIntRegion result;
     199             : 
     200         510 :     bool ancestorMaskChanged = mAncestorMaskLayers.Length() != mLayer->GetAncestorMaskLayerCount();
     201         510 :     if (!ancestorMaskChanged) {
     202         510 :       for (size_t i = 0; i < mAncestorMaskLayers.Length(); i++) {
     203           0 :         if (mLayer->GetAncestorMaskLayerAt(i) != mAncestorMaskLayers[i]->mLayer) {
     204           0 :           ancestorMaskChanged = true;
     205           0 :           break;
     206             :         }
     207             :       }
     208             :     }
     209             : 
     210         510 :     Layer* otherMask = mLayer->GetMaskLayer();
     211        2040 :     if ((mMaskLayer ? mMaskLayer->mLayer : nullptr) != otherMask ||
     212         510 :         ancestorMaskChanged ||
     213        1019 :         (mUseClipRect != !!otherClip) ||
     214        2548 :         mLayer->GetLocalOpacity() != mOpacity ||
     215             :         transformChanged)
     216             :     {
     217           7 :       result = OldTransformedBounds();
     218             :       LTI_DUMP(result, "oldtransform");
     219             :       LTI_DUMP(NewTransformedBounds(), "newtransform");
     220           7 :       AddRegion(result, NewTransformedBounds());
     221             : 
     222             :       // We can't bail out early because we need to update mChildrenChanged.
     223             :     }
     224             : 
     225        1020 :     nsIntRegion internal = ComputeChangeInternal(aPrefix, aCallback);
     226             :     LTI_DUMP(internal, "internal");
     227         510 :     AddRegion(result, internal);
     228             :     LTI_DUMP(mLayer->GetInvalidRegion().GetRegion(), "invalid");
     229         510 :     AddTransformedRegion(result, mLayer->GetInvalidRegion().GetRegion(), mTransform);
     230             : 
     231         510 :     if (mMaskLayer && otherMask) {
     232           0 :       nsIntRegion mask = mMaskLayer->ComputeChange(aPrefix, aCallback);
     233             :       LTI_DUMP(mask, "mask");
     234           0 :       AddTransformedRegion(result, mask, mTransform);
     235             :     }
     236             : 
     237        1530 :     for (size_t i = 0;
     238        1020 :          i < std::min(mAncestorMaskLayers.Length(), mLayer->GetAncestorMaskLayerCount());
     239             :          i++)
     240             :     {
     241           0 :       nsIntRegion mask = mAncestorMaskLayers[i]->ComputeChange(aPrefix, aCallback);
     242             :       LTI_DUMP(mask, "ancestormask");
     243           0 :       AddTransformedRegion(result, mask, mTransform);
     244             :     }
     245             : 
     246         510 :     if (mUseClipRect && otherClip) {
     247         101 :       if (!mClipRect.IsEqualInterior(*otherClip)) {
     248           6 :         nsIntRegion tmp;
     249           3 :         tmp.Xor(mClipRect.ToUnknownRect(), otherClip->ToUnknownRect());
     250             :         LTI_DUMP(tmp, "clip");
     251           3 :         AddRegion(result, tmp);
     252             :       }
     253             :     }
     254             : 
     255         510 :     mLayer->ClearInvalidRegion();
     256        1020 :     return result;
     257             :   }
     258             : 
     259         437 :   void CheckCanary()
     260             :   {
     261         437 :     mCanary.Check();
     262         437 :     mLayer->CheckCanary();
     263         437 :   }
     264             : 
     265           7 :   virtual IntRect NewTransformedBounds()
     266             :   {
     267          14 :     return TransformRect(mLayer->GetLocalVisibleRegion().ToUnknownRegion().GetBounds(),
     268          21 :                          GetTransformForInvalidation(mLayer));
     269             :   }
     270             : 
     271         132 :   virtual IntRect OldTransformedBounds()
     272             :   {
     273         132 :     return TransformRect(mVisibleRegion.ToUnknownRegion().GetBounds(), mTransform);
     274             :   }
     275             : 
     276         184 :   virtual nsIntRegion ComputeChangeInternal(const char* aPrefix,
     277             :                                             NotifySubDocInvalidationFunc aCallback)
     278             :   {
     279         184 :     return IntRect();
     280             :   }
     281             : 
     282             :   RefPtr<Layer> mLayer;
     283             :   UniquePtr<LayerPropertiesBase> mMaskLayer;
     284             :   nsTArray<UniquePtr<LayerPropertiesBase>> mAncestorMaskLayers;
     285             :   nsIntRegion mVisibleRegion;
     286             :   Matrix4x4 mTransform;
     287             :   float mPostXScale;
     288             :   float mPostYScale;
     289             :   float mOpacity;
     290             :   ParentLayerIntRect mClipRect;
     291             :   bool mUseClipRect;
     292             :   mozilla::CorruptionCanary mCanary;
     293             : };
     294             : 
     295         903 : struct ContainerLayerProperties : public LayerPropertiesBase
     296             : {
     297         304 :   explicit ContainerLayerProperties(ContainerLayer* aLayer)
     298         304 :     : LayerPropertiesBase(aLayer)
     299         304 :     , mPreXScale(aLayer->GetPreXScale())
     300         608 :     , mPreYScale(aLayer->GetPreYScale())
     301             :   {
     302         751 :     for (Layer* child = aLayer->GetFirstChild(); child; child = child->GetNextSibling()) {
     303         447 :       child->CheckCanary();
     304         447 :       mChildren.AppendElement(Move(CloneLayerTreePropertiesInternal(child)));
     305             :     }
     306         304 :   }
     307             : 
     308             : protected:
     309             :   ContainerLayerProperties(const ContainerLayerProperties& a) = delete;
     310             :   ContainerLayerProperties& operator=(const ContainerLayerProperties& a) = delete;
     311             : 
     312             : public:
     313         297 :   nsIntRegion ComputeChangeInternal(const char *aPrefix,
     314             :                                     NotifySubDocInvalidationFunc aCallback) override
     315             :   {
     316             :     // Make sure we got our virtual call right
     317         297 :     mSubtypeCanary.Check();
     318         297 :     ContainerLayer* container = mLayer->AsContainerLayer();
     319         594 :     nsIntRegion invalidOfLayer; // Invalid regions of this layer.
     320         297 :     nsIntRegion result;         // Invliad regions for children only.
     321             : 
     322         297 :     container->CheckCanary();
     323             : 
     324         297 :     bool childrenChanged = false;
     325         297 :     bool invalidateWholeLayer = false;
     326         594 :     if (mPreXScale != container->GetPreXScale() ||
     327         297 :         mPreYScale != container->GetPreYScale()) {
     328           0 :       invalidOfLayer = OldTransformedBounds();
     329           0 :       AddRegion(invalidOfLayer, NewTransformedBounds());
     330           0 :       childrenChanged = true;
     331           0 :       invalidateWholeLayer = true;
     332             : 
     333             :       // Can't bail out early, we need to update the child container layers
     334             :     }
     335             : 
     336             :     // A low frame rate is especially visible to users when scrolling, so we
     337             :     // particularly want to avoid unnecessary invalidation at that time. For us
     338             :     // here, that means avoiding unnecessary invalidation of child items when
     339             :     // other children are added to or removed from our container layer, since
     340             :     // that may be caused by children being scrolled in or out of view. We are
     341             :     // less concerned with children changing order.
     342             :     // TODO: Consider how we could avoid unnecessary invalidation when children
     343             :     // change order, and whether the overhead would be worth it.
     344             : 
     345         594 :     nsDataHashtable<nsPtrHashKey<Layer>, uint32_t> oldIndexMap(mChildren.Length());
     346         734 :     for (uint32_t i = 0; i < mChildren.Length(); ++i) {
     347         437 :       mChildren[i]->CheckCanary();
     348         437 :       oldIndexMap.Put(mChildren[i]->mLayer, i);
     349             :     }
     350             : 
     351         297 :     uint32_t i = 0; // cursor into the old child list mChildren
     352         733 :     for (Layer* child = container->GetFirstChild(); child; child = child->GetNextSibling()) {
     353         436 :       bool invalidateChildsCurrentArea = false;
     354         436 :       if (i < mChildren.Length()) {
     355             :         uint32_t childsOldIndex;
     356         431 :         if (oldIndexMap.Get(child, &childsOldIndex)) {
     357         326 :           if (childsOldIndex >= i) {
     358             :             // Invalidate the old areas of layers that used to be between the
     359             :             // current |child| and the previous |child| that was also in the
     360             :             // old list mChildren (if any of those children have been reordered
     361             :             // rather than removed, we will invalidate their new area when we
     362             :             // encounter them in the new list):
     363         326 :             for (uint32_t j = i; j < childsOldIndex; ++j) {
     364             :               LTI_DUMP(mChildren[j]->OldTransformedBounds(), "reordered child");
     365           0 :               AddRegion(result, mChildren[j]->OldTransformedBounds());
     366           0 :               childrenChanged |= true;
     367             :             }
     368         326 :             if (childsOldIndex >= mChildren.Length()) {
     369           0 :               MOZ_CRASH("Out of bounds");
     370             :             }
     371             :             // Invalidate any regions of the child that have changed:
     372         652 :             nsIntRegion region = mChildren[childsOldIndex]->ComputeChange(LTI_DEEPER(aPrefix), aCallback);
     373         326 :             i = childsOldIndex + 1;
     374         326 :             if (!region.IsEmpty()) {
     375             :               LTI_LOG("%s%p: child %p produced %s\n", aPrefix, mLayer.get(),
     376             :                 mChildren[childsOldIndex]->mLayer.get(), Stringify(region).c_str());
     377         102 :               AddRegion(result, region);
     378         102 :               childrenChanged |= true;
     379             :             }
     380             :           } else {
     381             :             // We've already seen this child in mChildren (which means it must
     382             :             // have been reordered) and invalidated its old area. We need to
     383             :             // invalidate its new area too:
     384           0 :             invalidateChildsCurrentArea = true;
     385             :           }
     386             :         } else {
     387             :           // |child| is new
     388         105 :           invalidateChildsCurrentArea = true;
     389             :         }
     390             :       } else {
     391             :         // |child| is new, or was reordered to a higher index
     392           5 :         invalidateChildsCurrentArea = true;
     393             :       }
     394         436 :       if (invalidateChildsCurrentArea) {
     395             :         LTI_DUMP(child->GetLocalVisibleRegion().ToUnknownRegion(), "invalidateChidlsCurrentArea");
     396         220 :         AddTransformedRegion(result, child->GetLocalVisibleRegion().ToUnknownRegion(),
     397         330 :                              GetTransformForInvalidation(child));
     398         110 :         if (aCallback) {
     399          19 :           NotifySubdocumentInvalidation(child, aCallback);
     400             :         } else {
     401          91 :           ClearInvalidations(child);
     402             :         }
     403             :       }
     404         436 :       childrenChanged |= invalidateChildsCurrentArea;
     405             :     }
     406             : 
     407             :     // Process remaining removed children.
     408         519 :     while (i < mChildren.Length()) {
     409         111 :       childrenChanged |= true;
     410             :       LTI_DUMP(mChildren[i]->OldTransformedBounds(), "removed child");
     411         111 :       AddRegion(result, mChildren[i]->OldTransformedBounds());
     412         111 :       i++;
     413             :     }
     414             : 
     415         297 :     if (aCallback) {
     416          77 :       aCallback(container, result);
     417             :     }
     418             : 
     419         297 :     if (childrenChanged) {
     420         158 :       container->SetChildrenChanged(true);
     421             :     }
     422             : 
     423         297 :     if (container->UseIntermediateSurface()) {
     424             :       IntRect bounds = invalidateWholeLayer
     425           0 :                        ? mLayer->GetLocalVisibleRegion().ToUnknownRegion().GetBounds()
     426           0 :                        : result.GetBounds();
     427           0 :       container->SetInvalidCompositeRect(bounds);
     428             :     }
     429             : 
     430         297 :     if (!mLayer->Extend3DContext()) {
     431             :       // |result| contains invalid regions only of children.
     432         297 :       result.Transform(GetTransformForInvalidation(mLayer));
     433             :     }
     434             :     // else, effective transforms have applied on children.
     435             : 
     436             :     LTI_DUMP(invalidOfLayer, "invalidOfLayer");
     437         297 :     result.OrWith(invalidOfLayer);
     438         594 :     return result;
     439             :   }
     440             : 
     441           5 :   IntRect NewTransformedBounds() override
     442             :   {
     443           5 :     if (mLayer->Extend3DContext()) {
     444           0 :       IntRect result;
     445           0 :       for (UniquePtr<LayerPropertiesBase>& child : mChildren) {
     446           0 :         result = result.Union(child->NewTransformedBounds());
     447             :       }
     448           0 :       return result;
     449             :     }
     450             : 
     451           5 :     return LayerPropertiesBase::NewTransformedBounds();
     452             :   }
     453             : 
     454           9 :   IntRect OldTransformedBounds() override
     455             :   {
     456           9 :     if (mLayer->Extend3DContext()) {
     457           0 :       IntRect result;
     458           0 :       for (UniquePtr<LayerPropertiesBase>& child : mChildren) {
     459           0 :         result = result.Union(child->OldTransformedBounds());
     460             :       }
     461           0 :       return result;
     462             :     }
     463           9 :     return LayerPropertiesBase::OldTransformedBounds();
     464             :   }
     465             : 
     466             :   // The old list of children:
     467             :   mozilla::CorruptionCanary mSubtypeCanary;
     468             :   nsTArray<UniquePtr<LayerPropertiesBase>> mChildren;
     469             :   float mPreXScale;
     470             :   float mPreYScale;
     471             : };
     472             : 
     473         102 : struct ColorLayerProperties : public LayerPropertiesBase
     474             : {
     475          35 :   explicit ColorLayerProperties(ColorLayer *aLayer)
     476          35 :     : LayerPropertiesBase(aLayer)
     477          35 :     , mColor(aLayer->GetColor())
     478          70 :     , mBounds(aLayer->GetBounds())
     479          35 :   { }
     480             : 
     481             : protected:
     482             :   ColorLayerProperties(const ColorLayerProperties& a) = delete;
     483             :   ColorLayerProperties& operator=(const ColorLayerProperties& a) = delete;
     484             : 
     485             : public:
     486          29 :   nsIntRegion ComputeChangeInternal(const char* aPrefix,
     487             :                                     NotifySubDocInvalidationFunc aCallback) override
     488             :   {
     489          29 :     ColorLayer* color = static_cast<ColorLayer*>(mLayer.get());
     490             : 
     491          29 :     if (mColor != color->GetColor()) {
     492             :       LTI_DUMP(NewTransformedBounds(), "color");
     493           0 :       return NewTransformedBounds();
     494             :     }
     495             : 
     496          58 :     nsIntRegion boundsDiff;
     497          29 :     boundsDiff.Xor(mBounds, color->GetBounds());
     498             :     LTI_DUMP(boundsDiff, "colorbounds");
     499             : 
     500          58 :     nsIntRegion result;
     501          29 :     AddTransformedRegion(result, boundsDiff, mTransform);
     502             : 
     503          29 :     return result;
     504             :   }
     505             : 
     506             :   Color mColor;
     507             :   IntRect mBounds;
     508             : };
     509             : 
     510           0 : struct BorderLayerProperties : public LayerPropertiesBase
     511             : {
     512           0 :   explicit BorderLayerProperties(BorderLayer *aLayer)
     513           0 :     : LayerPropertiesBase(aLayer)
     514           0 :     , mColors(aLayer->GetColors())
     515           0 :     , mRect(aLayer->GetRect())
     516           0 :     , mCorners(aLayer->GetCorners())
     517           0 :     , mWidths(aLayer->GetWidths())
     518           0 :   { }
     519             : 
     520             : protected:
     521             :   BorderLayerProperties(const BorderLayerProperties& a) = delete;
     522             :   BorderLayerProperties& operator=(const BorderLayerProperties& a) = delete;
     523             : 
     524             : public:
     525           0 :   nsIntRegion ComputeChangeInternal(const char* aPrefix,
     526             :                                     NotifySubDocInvalidationFunc aCallback) override
     527             :   {
     528           0 :     BorderLayer* border = static_cast<BorderLayer*>(mLayer.get());
     529             : 
     530           0 :     if (!border->GetLocalVisibleRegion().ToUnknownRegion().IsEqual(mVisibleRegion)) {
     531           0 :       IntRect result = NewTransformedBounds();
     532           0 :       result = result.Union(OldTransformedBounds());
     533           0 :       return result;
     534             :     }
     535             : 
     536           0 :     if (!PodEqual(&mColors[0], &border->GetColors()[0], 4) ||
     537           0 :         !PodEqual(&mWidths[0], &border->GetWidths()[0], 4) ||
     538           0 :         !PodEqual(&mCorners[0], &border->GetCorners()[0], 4) ||
     539           0 :         !mRect.IsEqualEdges(border->GetRect())) {
     540             :       LTI_DUMP(NewTransformedBounds(), "bounds");
     541           0 :       return NewTransformedBounds();
     542             :     }
     543             : 
     544           0 :     return nsIntRegion();
     545             :   }
     546             : 
     547             :   BorderColors mColors;
     548             :   LayerRect mRect;
     549             :   BorderCorners mCorners;
     550             :   BorderWidths mWidths;
     551             : };
     552             : 
     553           0 : struct TextLayerProperties : public LayerPropertiesBase
     554             : {
     555           0 :   explicit TextLayerProperties(TextLayer *aLayer)
     556           0 :     : LayerPropertiesBase(aLayer)
     557           0 :     , mBounds(aLayer->GetBounds())
     558             :     , mGlyphs(aLayer->GetGlyphs())
     559           0 :     , mFont(aLayer->GetScaledFont())
     560           0 :   { }
     561             : 
     562             : protected:
     563             :   TextLayerProperties(const TextLayerProperties& a) = delete;
     564             :   TextLayerProperties& operator=(const TextLayerProperties& a) = delete;
     565             : 
     566             : public:
     567           0 :   nsIntRegion ComputeChangeInternal(const char* aPrefix,
     568             :                                     NotifySubDocInvalidationFunc aCallback) override
     569             :   {
     570           0 :     TextLayer* text = static_cast<TextLayer*>(mLayer.get());
     571             : 
     572           0 :     if (!text->GetLocalVisibleRegion().ToUnknownRegion().IsEqual(mVisibleRegion)) {
     573           0 :       IntRect result = NewTransformedBounds();
     574           0 :       result = result.Union(OldTransformedBounds());
     575           0 :       return result;
     576             :     }
     577             : 
     578           0 :     if (!mBounds.IsEqualEdges(text->GetBounds()) ||
     579           0 :         mGlyphs != text->GetGlyphs() ||
     580           0 :         mFont != text->GetScaledFont()) {
     581             :       LTI_DUMP(NewTransformedBounds(), "bounds");
     582           0 :       return NewTransformedBounds();
     583             :     }
     584             : 
     585           0 :     return nsIntRegion();
     586             :   }
     587             : 
     588             :   gfx::IntRect mBounds;
     589             :   nsTArray<GlyphArray> mGlyphs;
     590             :   gfx::ScaledFont* mFont;
     591             : };
     592             : 
     593           0 : static ImageHost* GetImageHost(Layer* aLayer)
     594             : {
     595           0 :   HostLayer* compositor = aLayer->AsHostLayer();
     596           0 :   if (compositor) {
     597           0 :     return static_cast<ImageHost*>(compositor->GetCompositableHost());
     598             :   }
     599           0 :   return nullptr;
     600             : }
     601             : 
     602           0 : struct ImageLayerProperties : public LayerPropertiesBase
     603             : {
     604           0 :   explicit ImageLayerProperties(ImageLayer* aImage, bool aIsMask)
     605           0 :     : LayerPropertiesBase(aImage)
     606             :     , mContainer(aImage->GetContainer())
     607             :     , mImageHost(GetImageHost(aImage))
     608           0 :     , mSamplingFilter(aImage->GetSamplingFilter())
     609           0 :     , mScaleToSize(aImage->GetScaleToSize())
     610           0 :     , mScaleMode(aImage->GetScaleMode())
     611             :     , mLastProducerID(-1)
     612             :     , mLastFrameID(-1)
     613           0 :     , mIsMask(aIsMask)
     614             :   {
     615           0 :     if (mImageHost) {
     616           0 :       mLastProducerID = mImageHost->GetLastProducerID();
     617           0 :       mLastFrameID = mImageHost->GetLastFrameID();
     618             :     }
     619           0 :   }
     620             : 
     621           0 :   nsIntRegion ComputeChangeInternal(const char* aPrefix,
     622             :                                     NotifySubDocInvalidationFunc aCallback) override
     623             :   {
     624           0 :     ImageLayer* imageLayer = static_cast<ImageLayer*>(mLayer.get());
     625             : 
     626           0 :     if (!imageLayer->GetLocalVisibleRegion().ToUnknownRegion().IsEqual(mVisibleRegion)) {
     627           0 :       IntRect result = NewTransformedBounds();
     628           0 :       result = result.Union(OldTransformedBounds());
     629           0 :       return result;
     630             :     }
     631             : 
     632           0 :     ImageContainer* container = imageLayer->GetContainer();
     633           0 :     ImageHost* host = GetImageHost(imageLayer);
     634           0 :     if (mContainer != container ||
     635           0 :         mSamplingFilter != imageLayer->GetSamplingFilter() ||
     636           0 :         mScaleToSize != imageLayer->GetScaleToSize() ||
     637           0 :         mScaleMode != imageLayer->GetScaleMode() ||
     638           0 :         host != mImageHost ||
     639           0 :         (host && host->GetProducerID() != mLastProducerID) ||
     640           0 :         (host && host->GetFrameID() != mLastFrameID)) {
     641             : 
     642           0 :       if (mIsMask) {
     643             :         // Mask layers have an empty visible region, so we have to
     644             :         // use the image size instead.
     645           0 :         IntSize size;
     646           0 :         if (container) {
     647           0 :           size = container->GetCurrentSize();
     648             :         }
     649           0 :         if (host) {
     650           0 :           size = host->GetImageSize();
     651             :         }
     652           0 :         IntRect rect(0, 0, size.width, size.height);
     653             :         LTI_DUMP(rect, "mask");
     654           0 :         return TransformRect(rect, GetTransformForInvalidation(mLayer));
     655             :       }
     656             :       LTI_DUMP(NewTransformedBounds(), "bounds");
     657           0 :       return NewTransformedBounds();
     658             :     }
     659             : 
     660           0 :     return IntRect();
     661             :   }
     662             : 
     663             :   RefPtr<ImageContainer> mContainer;
     664             :   RefPtr<ImageHost> mImageHost;
     665             :   SamplingFilter mSamplingFilter;
     666             :   gfx::IntSize mScaleToSize;
     667             :   ScaleMode mScaleMode;
     668             :   int32_t mLastProducerID;
     669             :   int32_t mLastFrameID;
     670             :   bool mIsMask;
     671             : };
     672             : 
     673           0 : struct CanvasLayerProperties : public LayerPropertiesBase
     674             : {
     675           0 :   explicit CanvasLayerProperties(CanvasLayer* aCanvas)
     676           0 :     : LayerPropertiesBase(aCanvas)
     677           0 :     , mImageHost(GetImageHost(aCanvas))
     678             :   {
     679           0 :     mFrameID = mImageHost ? mImageHost->GetFrameID() : -1;
     680           0 :   }
     681             : 
     682           0 :   nsIntRegion ComputeChangeInternal(const char* aPrefix,
     683             :                                     NotifySubDocInvalidationFunc aCallback) override
     684             :   {
     685           0 :     CanvasLayer* canvasLayer = static_cast<CanvasLayer*>(mLayer.get());
     686             : 
     687           0 :     ImageHost* host = GetImageHost(canvasLayer);
     688           0 :     if (host && host->GetFrameID() != mFrameID) {
     689             :       LTI_DUMP(NewTransformedBounds(), "frameId");
     690           0 :       return NewTransformedBounds();
     691             :     }
     692             : 
     693           0 :     return IntRect();
     694             :   }
     695             : 
     696             :   RefPtr<ImageHost> mImageHost;
     697             :   int32_t mFrameID;
     698             : };
     699             : 
     700             : UniquePtr<LayerPropertiesBase>
     701         646 : CloneLayerTreePropertiesInternal(Layer* aRoot, bool aIsMask /* = false */)
     702             : {
     703         646 :   if (!aRoot) {
     704          13 :     return MakeUnique<LayerPropertiesBase>();
     705             :   }
     706             : 
     707         633 :   MOZ_ASSERT(!aIsMask || aRoot->GetType() == Layer::TYPE_IMAGE);
     708             : 
     709         633 :   aRoot->CheckCanary();
     710             : 
     711         633 :   switch (aRoot->GetType()) {
     712             :     case Layer::TYPE_CONTAINER:
     713             :     case Layer::TYPE_REF:
     714         304 :       return MakeUnique<ContainerLayerProperties>(aRoot->AsContainerLayer());
     715             :     case Layer::TYPE_COLOR:
     716          35 :       return MakeUnique<ColorLayerProperties>(static_cast<ColorLayer*>(aRoot));
     717             :     case Layer::TYPE_IMAGE:
     718           0 :       return MakeUnique<ImageLayerProperties>(static_cast<ImageLayer*>(aRoot), aIsMask);
     719             :     case Layer::TYPE_CANVAS:
     720           0 :       return MakeUnique<CanvasLayerProperties>(static_cast<CanvasLayer*>(aRoot));
     721             :     case Layer::TYPE_BORDER:
     722           0 :       return MakeUnique<BorderLayerProperties>(static_cast<BorderLayer*>(aRoot));
     723             :     case Layer::TYPE_TEXT:
     724           0 :       return MakeUnique<TextLayerProperties>(static_cast<TextLayer*>(aRoot));
     725             :     case Layer::TYPE_DISPLAYITEM:
     726             :     case Layer::TYPE_READBACK:
     727             :     case Layer::TYPE_SHADOW:
     728             :     case Layer::TYPE_PAINTED:
     729         294 :       return MakeUnique<LayerPropertiesBase>(aRoot);
     730             :   }
     731             : 
     732           0 :   MOZ_ASSERT_UNREACHABLE("Unexpected root layer type");
     733             :   return MakeUnique<LayerPropertiesBase>(aRoot);
     734             : }
     735             : 
     736             : /* static */ UniquePtr<LayerProperties>
     737         199 : LayerProperties::CloneFrom(Layer* aRoot)
     738             : {
     739         199 :   return CloneLayerTreePropertiesInternal(aRoot);
     740             : }
     741             : 
     742             : /* static */ void
     743         103 : LayerProperties::ClearInvalidations(Layer *aLayer)
     744             : {
     745         103 :   ForEachNode<ForwardIterator>(
     746             :         aLayer,
     747         123 :         [] (Layer* layer)
     748             :         {
     749         123 :           layer->ClearInvalidRegion();
     750         123 :           if (layer->GetMaskLayer()) {
     751           0 :             ClearInvalidations(layer->GetMaskLayer());
     752             :           }
     753         123 :           for (size_t i = 0; i < layer->GetAncestorMaskLayerCount(); i++) {
     754           0 :             ClearInvalidations(layer->GetAncestorMaskLayerAt(i));
     755             :           }
     756             : 
     757         123 :         }
     758         103 :       );
     759         103 : }
     760             : 
     761             : nsIntRegion
     762         198 : LayerPropertiesBase::ComputeDifferences(Layer* aRoot, NotifySubDocInvalidationFunc aCallback)
     763             : {
     764         198 :   NS_ASSERTION(aRoot, "Must have a layer tree to compare against!");
     765         198 :   if (mLayer != aRoot) {
     766          14 :     if (aCallback) {
     767           2 :       NotifySubdocumentInvalidation(aRoot, aCallback);
     768             :     } else {
     769          12 :       ClearInvalidations(aRoot);
     770             :     }
     771             :     IntRect result = TransformRect(
     772          28 :       aRoot->GetLocalVisibleRegion().ToUnknownRegion().GetBounds(),
     773          42 :       aRoot->GetLocalTransform());
     774          14 :     result = result.Union(OldTransformedBounds());
     775          14 :     return result;
     776             :   }
     777         368 :   nsIntRegion invalid = ComputeChange("  ", aCallback);
     778         184 :   return invalid;
     779             : }
     780             : 
     781             : void
     782         143 : LayerPropertiesBase::MoveBy(const IntPoint& aOffset)
     783             : {
     784         143 :   mTransform.PostTranslate(aOffset.x, aOffset.y, 0);
     785         143 : }
     786             : 
     787             : } // namespace layers
     788             : } // namespace mozilla

Generated by: LCOV version 1.13