LCOV - code coverage report
Current view: top level - gfx/layers - LayerMetricsWrapper.h (source / functions) Hit Total Coverage
Test: output.info Lines: 115 172 66.9 %
Date: 2017-07-14 16:53:18 Functions: 28 38 73.7 %
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
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : #ifndef GFX_LAYERMETRICSWRAPPER_H
       7             : #define GFX_LAYERMETRICSWRAPPER_H
       8             : 
       9             : #include "Layers.h"
      10             : #include "UnitTransforms.h"
      11             : 
      12             : namespace mozilla {
      13             : namespace layers {
      14             : 
      15             : /**
      16             :  * A wrapper class around a target Layer with that allows user code to
      17             :  * walk through the FrameMetrics objects on the layer the same way it
      18             :  * would walk through a ContainerLayer hierarchy. Consider the following
      19             :  * layer tree:
      20             :  *
      21             :  *                    +---+
      22             :  *                    | A |
      23             :  *                    +---+
      24             :  *                   /  |  \
      25             :  *                  /   |   \
      26             :  *                 /    |    \
      27             :  *            +---+  +-----+  +---+
      28             :  *            | B |  |  C  |  | D |
      29             :  *            +---+  +-----+  +---+
      30             :  *                   | FMn |
      31             :  *                   |  .  |
      32             :  *                   |  .  |
      33             :  *                   |  .  |
      34             :  *                   | FM1 |
      35             :  *                   | FM0 |
      36             :  *                   +-----+
      37             :  *                   /     \
      38             :  *                  /       \
      39             :  *             +---+         +---+
      40             :  *             | E |         | F |
      41             :  *             +---+         +---+
      42             :  *
      43             :  * In this layer tree, there are six layers with A being the root and B,D,E,F
      44             :  * being leaf nodes. Layer C is in the middle and has n+1 FrameMetrics, labelled
      45             :  * FM0...FMn. FM0 is the FrameMetrics you get by calling c->GetFrameMetrics(0)
      46             :  * and FMn is the FrameMetrics you can obtain by calling
      47             :  * c->GetFrameMetrics(c->GetScrollMetadataCount() - 1). This layer tree is
      48             :  * conceptually equivalent to this one below:
      49             :  *
      50             :  *                    +---+
      51             :  *                    | A |
      52             :  *                    +---+
      53             :  *                   /  |  \
      54             :  *                  /   |   \
      55             :  *                 /    |    \
      56             :  *            +---+  +-----+  +---+
      57             :  *            | B |  | Cn  |  | D |
      58             :  *            +---+  +-----+  +---+
      59             :  *                      |
      60             :  *                      .
      61             :  *                      .
      62             :  *                      .
      63             :  *                      |
      64             :  *                   +-----+
      65             :  *                   | C1  |
      66             :  *                   +-----+
      67             :  *                      |
      68             :  *                   +-----+
      69             :  *                   | C0  |
      70             :  *                   +-----+
      71             :  *                   /     \
      72             :  *                  /       \
      73             :  *             +---+         +---+
      74             :  *             | E |         | F |
      75             :  *             +---+         +---+
      76             :  *
      77             :  * In this layer tree, the layer C has been expanded into a stack of container
      78             :  * layers C1...Cn, where C1 has FrameMetrics FM1 and Cn has FrameMetrics Fn.
      79             :  * Although in this example C (in the first layer tree) and C0 (in the second
      80             :  * layer tree) are both ContainerLayers (because they have children), they
      81             :  * do not have to be. They may just be PaintedLayers or ColorLayers, for example,
      82             :  * which do not have any children. However, the type of C will always be the
      83             :  * same as the type of C0.
      84             :  *
      85             :  * The LayerMetricsWrapper class allows client code to treat the first layer
      86             :  * tree as though it were the second. That is, instead of client code having
      87             :  * to iterate through the FrameMetrics objects directly, it can use a
      88             :  * LayerMetricsWrapper to encapsulate that aspect of the layer tree and just
      89             :  * walk the tree as if it were a stack of ContainerLayers.
      90             :  *
      91             :  * The functions on this class do different things depending on which
      92             :  * simulated ContainerLayer is being wrapped. For example, if the
      93             :  * LayerMetricsWrapper is pretending to be C0, the GetNextSibling() function
      94             :  * will return null even though the underlying layer C does actually have
      95             :  * a next sibling. The LayerMetricsWrapper pretending to be Cn will return
      96             :  * D as the next sibling.
      97             :  *
      98             :  * Implementation notes:
      99             :  *
     100             :  * The AtTopLayer() and AtBottomLayer() functions in this class refer to
     101             :  * Cn and C0 in the second layer tree above; that is, they are predicates
     102             :  * to test if the LayerMetricsWrapper is simulating the topmost or bottommost
     103             :  * layer, as those will have special behaviour.
     104             :  *
     105             :  * It is possible to wrap a nullptr in a LayerMetricsWrapper, in which case
     106             :  * the IsValid() function will return false. This is required to allow
     107             :  * LayerMetricsWrapper to be a MOZ_STACK_CLASS (desirable because it is used
     108             :  * in loops and recursion).
     109             :  *
     110             :  * This class purposely does not expose the wrapped layer directly to avoid
     111             :  * user code from accidentally calling functions directly on it. Instead
     112             :  * any necessary functions should be wrapped in this class. It does expose
     113             :  * the wrapped layer as a void* for printf purposes.
     114             :  *
     115             :  * The implementation may look like it special-cases mIndex == 0 and/or
     116             :  * GetScrollMetadataCount() == 0. This is an artifact of the fact that both
     117             :  * mIndex and GetScrollMetadataCount() are uint32_t and GetScrollMetadataCount()
     118             :  * can return 0 but mIndex cannot store -1. This seems better than the
     119             :  * alternative of making mIndex a int32_t that can store -1, but then having
     120             :  * to cast to uint32_t all over the place.
     121             :  */
     122             : class MOZ_STACK_CLASS LayerMetricsWrapper {
     123             : public:
     124             :   enum StartAt {
     125             :     TOP,
     126             :     BOTTOM,
     127             :   };
     128             : 
     129           0 :   LayerMetricsWrapper()
     130           0 :     : mLayer(nullptr)
     131           0 :     , mIndex(0)
     132             :   {
     133           0 :   }
     134             : 
     135         852 :   explicit LayerMetricsWrapper(Layer* aRoot, StartAt aStart = StartAt::TOP)
     136         852 :     : mLayer(aRoot)
     137         852 :     , mIndex(0)
     138             :   {
     139         852 :     if (!mLayer) {
     140         426 :       return;
     141             :     }
     142             : 
     143         426 :     switch (aStart) {
     144             :       case StartAt::TOP:
     145         426 :         mIndex = mLayer->GetScrollMetadataCount();
     146         426 :         if (mIndex > 0) {
     147          79 :           mIndex--;
     148             :         }
     149         426 :         break;
     150             :       case StartAt::BOTTOM:
     151           0 :         mIndex = 0;
     152           0 :         break;
     153             :       default:
     154           0 :         MOZ_ASSERT_UNREACHABLE("Unknown startAt value");
     155             :         break;
     156             :     }
     157             :   }
     158             : 
     159           0 :   explicit LayerMetricsWrapper(Layer* aLayer, uint32_t aMetricsIndex)
     160           0 :     : mLayer(aLayer)
     161           0 :     , mIndex(aMetricsIndex)
     162             :   {
     163           0 :     MOZ_ASSERT(mLayer);
     164           0 :     MOZ_ASSERT(mIndex == 0 || mIndex < mLayer->GetScrollMetadataCount());
     165           0 :   }
     166             : 
     167        6646 :   bool IsValid() const
     168             :   {
     169        6646 :     return mLayer != nullptr;
     170             :   }
     171             : 
     172        1249 :   explicit operator bool() const
     173             :   {
     174        1249 :     return IsValid();
     175             :   }
     176             : 
     177         250 :   bool IsScrollInfoLayer() const
     178             :   {
     179         250 :     MOZ_ASSERT(IsValid());
     180             : 
     181             :     // If we are not at the bottommost layer then it's
     182             :     // a stack of container layers all the way down to
     183             :     // mLayer, which we can ignore. We only care about
     184             :     // non-container descendants.
     185         250 :     return Metrics().IsScrollable()
     186          78 :         && mLayer->AsContainerLayer()
     187         306 :         && !mLayer->GetFirstChild();
     188             :   }
     189             : 
     190           0 :   LayerMetricsWrapper GetParent() const
     191             :   {
     192           0 :     MOZ_ASSERT(IsValid());
     193             : 
     194           0 :     if (!AtTopLayer()) {
     195           0 :       return LayerMetricsWrapper(mLayer, mIndex + 1);
     196             :     }
     197           0 :     if (mLayer->GetParent()) {
     198           0 :       return LayerMetricsWrapper(mLayer->GetParent(), StartAt::BOTTOM);
     199             :     }
     200           0 :     return LayerMetricsWrapper(nullptr);
     201             :   }
     202             : 
     203         215 :   LayerMetricsWrapper GetFirstChild() const
     204             :   {
     205         215 :     MOZ_ASSERT(IsValid());
     206             : 
     207         215 :     if (!AtBottomLayer()) {
     208           0 :       return LayerMetricsWrapper(mLayer, mIndex - 1);
     209             :     }
     210         215 :     return LayerMetricsWrapper(mLayer->GetFirstChild());
     211             :   }
     212             : 
     213         211 :   LayerMetricsWrapper GetLastChild() const
     214             :   {
     215         211 :     MOZ_ASSERT(IsValid());
     216             : 
     217         211 :     if (!AtBottomLayer()) {
     218           0 :       return LayerMetricsWrapper(mLayer, mIndex - 1);
     219             :     }
     220         211 :     return LayerMetricsWrapper(mLayer->GetLastChild());
     221             :   }
     222             : 
     223         183 :   LayerMetricsWrapper GetPrevSibling() const
     224             :   {
     225         183 :     MOZ_ASSERT(IsValid());
     226             : 
     227         183 :     if (AtTopLayer()) {
     228         183 :       return LayerMetricsWrapper(mLayer->GetPrevSibling());
     229             :     }
     230           0 :     return LayerMetricsWrapper(nullptr);
     231             :   }
     232             : 
     233         186 :   LayerMetricsWrapper GetNextSibling() const
     234             :   {
     235         186 :     MOZ_ASSERT(IsValid());
     236             : 
     237         186 :     if (AtTopLayer()) {
     238         186 :       return LayerMetricsWrapper(mLayer->GetNextSibling());
     239             :     }
     240           0 :     return LayerMetricsWrapper(nullptr);
     241             :   }
     242             : 
     243         875 :   const ScrollMetadata& Metadata() const
     244             :   {
     245         875 :     MOZ_ASSERT(IsValid());
     246             : 
     247         875 :     if (mIndex >= mLayer->GetScrollMetadataCount()) {
     248         568 :       return *ScrollMetadata::sNullMetadata;
     249             :     }
     250         307 :     return mLayer->GetScrollMetadata(mIndex);
     251             :   }
     252             : 
     253         528 :   const FrameMetrics& Metrics() const
     254             :   {
     255         528 :     return Metadata().GetMetrics();
     256             :   }
     257             : 
     258         249 :   AsyncPanZoomController* GetApzc() const
     259             :   {
     260         249 :     MOZ_ASSERT(IsValid());
     261             : 
     262         249 :     if (mIndex >= mLayer->GetScrollMetadataCount()) {
     263         175 :       return nullptr;
     264             :     }
     265          74 :     return mLayer->GetAsyncPanZoomController(mIndex);
     266             :   }
     267             : 
     268         211 :   void SetApzc(AsyncPanZoomController* aApzc) const
     269             :   {
     270         211 :     MOZ_ASSERT(IsValid());
     271             : 
     272         211 :     if (mLayer->GetScrollMetadataCount() == 0) {
     273         172 :       MOZ_ASSERT(mIndex == 0);
     274         172 :       MOZ_ASSERT(aApzc == nullptr);
     275         172 :       return;
     276             :     }
     277          39 :     MOZ_ASSERT(mIndex < mLayer->GetScrollMetadataCount());
     278          39 :     mLayer->SetAsyncPanZoomController(mIndex, aApzc);
     279             :   }
     280             : 
     281         211 :   const char* Name() const
     282             :   {
     283         211 :     MOZ_ASSERT(IsValid());
     284             : 
     285         211 :     if (AtBottomLayer()) {
     286         211 :       return mLayer->Name();
     287             :     }
     288           0 :     return "DummyContainerLayer";
     289             :   }
     290             : 
     291           0 :   LayerManager* Manager() const
     292             :   {
     293           0 :     MOZ_ASSERT(IsValid());
     294             : 
     295           0 :     return mLayer->Manager();
     296             :   }
     297             : 
     298         422 :   gfx::Matrix4x4 GetTransform() const
     299             :   {
     300         422 :     MOZ_ASSERT(IsValid());
     301             : 
     302         422 :     if (AtBottomLayer()) {
     303         422 :       return mLayer->GetTransform();
     304             :     }
     305           0 :     return gfx::Matrix4x4();
     306             :   }
     307             : 
     308         211 :   CSSTransformMatrix GetTransformTyped() const
     309             :   {
     310         211 :     return ViewAs<CSSTransformMatrix>(GetTransform());
     311             :   }
     312             : 
     313         211 :   bool TransformIsPerspective() const
     314             :   {
     315         211 :     MOZ_ASSERT(IsValid());
     316             : 
     317             :     // mLayer->GetTransformIsPerspective() tells us whether
     318             :     // mLayer->GetTransform() is a perspective transform. Since
     319             :     // mLayer->GetTransform() is only used at the bottom layer, we only
     320             :     // need to check GetTransformIsPerspective() at the bottom layer too.
     321         211 :     if (AtBottomLayer()) {
     322         211 :       return mLayer->GetTransformIsPerspective();
     323             :     }
     324           0 :     return false;
     325             :   }
     326             : 
     327         211 :   EventRegions GetEventRegions() const
     328             :   {
     329         211 :     MOZ_ASSERT(IsValid());
     330             : 
     331         211 :     if (AtBottomLayer()) {
     332         211 :       return mLayer->GetEventRegions();
     333             :     }
     334           0 :     return EventRegions();
     335             :   }
     336             : 
     337         211 :   LayerIntRegion GetVisibleRegion() const
     338             :   {
     339         211 :     MOZ_ASSERT(IsValid());
     340             : 
     341         211 :     if (AtBottomLayer()) {
     342         211 :       return mLayer->GetVisibleRegion();
     343             :     }
     344             : 
     345             :     return ViewAs<LayerPixel>(
     346           0 :         TransformBy(mLayer->GetTransformTyped(), mLayer->GetVisibleRegion()),
     347           0 :         PixelCastJustification::MovingDownToChildren);
     348             :   }
     349             : 
     350           0 :   bool HasTransformAnimation() const
     351             :   {
     352           0 :     MOZ_ASSERT(IsValid());
     353             : 
     354           0 :     if (AtBottomLayer()) {
     355           0 :       return mLayer->HasTransformAnimation();
     356             :     }
     357           0 :     return false;
     358             :   }
     359             : 
     360           0 :   RefLayer* AsRefLayer() const
     361             :   {
     362           0 :     MOZ_ASSERT(IsValid());
     363             : 
     364           0 :     if (AtBottomLayer()) {
     365           0 :       return mLayer->AsRefLayer();
     366             :     }
     367           0 :     return nullptr;
     368             :   }
     369             : 
     370         211 :   Maybe<uint64_t> GetReferentId() const
     371             :   {
     372         211 :     MOZ_ASSERT(IsValid());
     373             : 
     374         211 :     if (AtBottomLayer()) {
     375         211 :       return mLayer->AsRefLayer()
     376         267 :            ? Some(mLayer->AsRefLayer()->GetReferentId())
     377         422 :            : Nothing();
     378             :     }
     379           0 :     return Nothing();
     380             :   }
     381             : 
     382         274 :   Maybe<ParentLayerIntRect> GetClipRect() const
     383             :   {
     384         274 :     MOZ_ASSERT(IsValid());
     385             : 
     386         274 :     Maybe<ParentLayerIntRect> result;
     387             : 
     388             :     // The layer can have a clip rect and a scrolled clip, which are considered
     389             :     // to apply only to the bottommost LayerMetricsWrapper.
     390             :     // TODO: These actually apply in a different coordinate space than the
     391             :     // scroll clip of the bottommost metrics, so we shouldn't be intersecting
     392             :     // them with the scroll clip; bug 1269537 tracks fixing this.
     393         274 :     if (AtBottomLayer()) {
     394         274 :       result = mLayer->GetClipRect();
     395         274 :       result = IntersectMaybeRects(result, mLayer->GetScrolledClipRect());
     396             :     }
     397             : 
     398             :     // The scroll metadata can have a clip rect as well.
     399         274 :     result = IntersectMaybeRects(result, Metadata().GetClipRect());
     400             : 
     401         274 :     return result;
     402             :   }
     403             : 
     404           0 :   float GetPresShellResolution() const
     405             :   {
     406           0 :     MOZ_ASSERT(IsValid());
     407             : 
     408           0 :     if (AtTopLayer() && mLayer->AsContainerLayer()) {
     409           0 :       return mLayer->AsContainerLayer()->GetPresShellResolution();
     410             :     }
     411             : 
     412           0 :     return 1.0f;
     413             :   }
     414             : 
     415         211 :   EventRegionsOverride GetEventRegionsOverride() const
     416             :   {
     417         211 :     MOZ_ASSERT(IsValid());
     418             : 
     419         211 :     if (mLayer->AsContainerLayer()) {
     420          92 :       return mLayer->AsContainerLayer()->GetEventRegionsOverride();
     421             :     }
     422         119 :     return EventRegionsOverride::NoOverride;
     423             :   }
     424             : 
     425         211 :   const ScrollThumbData& GetScrollThumbData() const
     426             :   {
     427         211 :     MOZ_ASSERT(IsValid());
     428             : 
     429         211 :     return mLayer->GetScrollThumbData();
     430             :   }
     431             : 
     432         211 :   uint64_t GetScrollbarAnimationId() const
     433             :   {
     434         211 :     MOZ_ASSERT(IsValid());
     435             :     // This function is only really needed for template-compatibility with
     436             :     // WebRenderScrollDataWrapper. Although it will be called, the return
     437             :     // value is not used.
     438         211 :     return 0;
     439             :   }
     440             : 
     441         211 :   FrameMetrics::ViewID GetScrollbarTargetContainerId() const
     442             :   {
     443         211 :     MOZ_ASSERT(IsValid());
     444             : 
     445         211 :     return mLayer->GetScrollbarTargetContainerId();
     446             :   }
     447             : 
     448         211 :   bool IsScrollbarContainer() const
     449             :   {
     450         211 :     MOZ_ASSERT(IsValid());
     451         211 :     return mLayer->IsScrollbarContainer();
     452             :   }
     453             : 
     454         211 :   FrameMetrics::ViewID GetFixedPositionScrollContainerId() const
     455             :   {
     456         211 :     MOZ_ASSERT(IsValid());
     457             : 
     458         211 :     return mLayer->GetFixedPositionScrollContainerId();
     459             :   }
     460             : 
     461             :   // Expose an opaque pointer to the layer. Mostly used for printf
     462             :   // purposes. This is not intended to be a general-purpose accessor
     463             :   // for the underlying layer.
     464           0 :   const void* GetLayer() const
     465             :   {
     466           0 :     MOZ_ASSERT(IsValid());
     467             : 
     468           0 :     return (void*)mLayer;
     469             :   }
     470             : 
     471           0 :   bool operator==(const LayerMetricsWrapper& aOther) const
     472             :   {
     473           0 :     return mLayer == aOther.mLayer
     474           0 :         && mIndex == aOther.mIndex;
     475             :   }
     476             : 
     477           0 :   bool operator!=(const LayerMetricsWrapper& aOther) const
     478             :   {
     479           0 :     return !(*this == aOther);
     480             :   }
     481             : 
     482             : private:
     483        2177 :   bool AtBottomLayer() const
     484             :   {
     485        2177 :     return mIndex == 0;
     486             :   }
     487             : 
     488         369 :   bool AtTopLayer() const
     489             :   {
     490         369 :     return mLayer->GetScrollMetadataCount() == 0 || mIndex == mLayer->GetScrollMetadataCount() - 1;
     491             :   }
     492             : 
     493             : private:
     494             :   Layer* mLayer;
     495             :   uint32_t mIndex;
     496             : };
     497             : 
     498             : } // namespace layers
     499             : } // namespace mozilla
     500             : 
     501             : #endif /* GFX_LAYERMETRICSWRAPPER_H */

Generated by: LCOV version 1.13