LCOV - code coverage report
Current view: top level - gfx/layers/wr - ScrollingLayersHelper.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 81 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 4 0.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
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : #include "mozilla/layers/ScrollingLayersHelper.h"
       7             : 
       8             : #include "FrameMetrics.h"
       9             : #include "mozilla/layers/StackingContextHelper.h"
      10             : #include "mozilla/layers/WebRenderLayer.h"
      11             : #include "mozilla/layers/WebRenderLayerManager.h"
      12             : #include "mozilla/webrender/WebRenderAPI.h"
      13             : #include "UnitTransforms.h"
      14             : 
      15             : namespace mozilla {
      16             : namespace layers {
      17             : 
      18           0 : ScrollingLayersHelper::ScrollingLayersHelper(WebRenderLayer* aLayer,
      19             :                                              wr::DisplayListBuilder& aBuilder,
      20           0 :                                              const StackingContextHelper& aStackingContext)
      21             :   : mLayer(aLayer)
      22             :   , mBuilder(&aBuilder)
      23           0 :   , mPushedLayerLocalClip(false)
      24             : {
      25           0 :   if (!mLayer->WrManager()->AsyncPanZoomEnabled()) {
      26             :     // If APZ is disabled then we don't need to push the scrolling clips. We
      27             :     // still want to push the layer's local clip though.
      28           0 :     PushLayerLocalClip(aStackingContext);
      29           0 :     return;
      30             :   }
      31             : 
      32           0 :   Layer* layer = mLayer->GetLayer();
      33           0 :   for (uint32_t i = layer->GetScrollMetadataCount(); i > 0; i--) {
      34           0 :     const ScrollMetadata& metadata = layer->GetScrollMetadata(i - 1);
      35             :     // The scroll clip on a given metadata is affected by all async transforms
      36             :     // from metadatas "above" it, but not the async transform on the metadata
      37             :     // itself. Therefore we need to push this clip before we push the
      38             :     // corresponding scroll layer, so that when we set an async scroll position
      39             :     // on the scroll layer, the clip isn't affected by it.
      40           0 :     if (const Maybe<LayerClip>& clip = metadata.GetScrollClip()) {
      41           0 :       PushLayerClip(clip.ref(), aStackingContext);
      42             :     }
      43             : 
      44           0 :     const FrameMetrics& fm = layer->GetFrameMetrics(i - 1);
      45           0 :     if (layer->GetIsFixedPosition() &&
      46           0 :         layer->GetFixedPositionScrollContainerId() == fm.GetScrollId()) {
      47             :       // If the layer contents are fixed for this metadata onwards, we need
      48             :       // to insert the layer's local clip at this point in the clip tree,
      49             :       // as a child of whatever's on the stack.
      50           0 :       PushLayerLocalClip(aStackingContext);
      51             :     }
      52             : 
      53           0 :     if (!fm.IsScrollable()) {
      54           0 :       continue;
      55             :     }
      56             :     LayerRect contentRect = ViewAs<LayerPixel>(
      57           0 :         fm.GetExpandedScrollableRect() * fm.GetDevPixelsPerCSSPixel(),
      58           0 :         PixelCastJustification::WebRenderHasUnitResolution);
      59             :     // TODO: check coordinate systems are sane here
      60             :     LayerRect clipBounds = ViewAs<LayerPixel>(
      61           0 :         fm.GetCompositionBounds(),
      62           0 :         PixelCastJustification::MovingDownToChildren);
      63             :     // The content rect that we hand to PushScrollLayer should be relative to
      64             :     // the same origin as the clipBounds that we hand to PushScrollLayer - that
      65             :     // is, both of them should be relative to the stacking context `aStackingContext`.
      66             :     // However, when we get the scrollable rect from the FrameMetrics, the origin
      67             :     // has nothing to do with the position of the frame but instead represents
      68             :     // the minimum allowed scroll offset of the scrollable content. While APZ
      69             :     // uses this to clamp the scroll position, we don't need to send this to
      70             :     // WebRender at all. Instead, we take the position from the composition
      71             :     // bounds.
      72           0 :     contentRect.MoveTo(clipBounds.TopLeft());
      73           0 :     mBuilder->PushScrollLayer(fm.GetScrollId(),
      74           0 :         aStackingContext.ToRelativeWrRect(contentRect),
      75           0 :         aStackingContext.ToRelativeWrRect(clipBounds));
      76             :   }
      77             : 
      78             :   // The scrolled clip on the layer is "inside" all of the scrollable metadatas
      79             :   // on that layer. That is, the clip scrolls along with the content in
      80             :   // child layers. So we need to apply this after pushing all the scroll layers,
      81             :   // which we do above.
      82           0 :   if (const Maybe<LayerClip>& scrolledClip = layer->GetScrolledClip()) {
      83           0 :     PushLayerClip(scrolledClip.ref(), aStackingContext);
      84             :   }
      85             : 
      86             :   // If the layer is marked as fixed-position, it is fixed relative to something
      87             :   // (the scroll layer referred to by GetFixedPositionScrollContainerId, hereafter
      88             :   // referred to as the "scroll container"). What this really means is that we
      89             :   // don't want this content to scroll with any scroll layer on the stack up to
      90             :   // and including the scroll container, but we do want it to scroll with any
      91             :   // ancestor scroll layers.
      92             :   // Also, the local clip on the layer (defined by layer->GetClipRect() and
      93             :   // layer->GetMaskLayer()) also need to be fixed relative to the scroll
      94             :   // container. This is why we inserted it into the clip tree during the
      95             :   // loop above when we encountered the scroll container.
      96             :   // At this point we do a PushClipAndScrollInfo that maintains
      97             :   // the current non-scrolling clip stack, but resets the scrolling clip stack
      98             :   // to the ancestor of the scroll container.
      99           0 :   if (layer->GetIsFixedPosition()) {
     100           0 :     FrameMetrics::ViewID fixedFor = layer->GetFixedPositionScrollContainerId();
     101           0 :     Maybe<FrameMetrics::ViewID> scrollsWith = mBuilder->ParentScrollIdFor(fixedFor);
     102           0 :     Maybe<wr::WrClipId> clipId = mBuilder->TopmostClipId();
     103             :     // Default to 0 if there is no ancestor, because 0 refers to the root scrollframe.
     104           0 :     mBuilder->PushClipAndScrollInfo(scrollsWith.valueOr(0), clipId.ptrOr(nullptr));
     105             :   } else {
     106           0 :     PushLayerLocalClip(aStackingContext);
     107             :   }
     108             : }
     109             : 
     110             : void
     111           0 : ScrollingLayersHelper::PushLayerLocalClip(const StackingContextHelper& aStackingContext)
     112             : {
     113           0 :   Layer* layer = mLayer->GetLayer();
     114           0 :   Maybe<ParentLayerRect> clip;
     115           0 :   if (const Maybe<ParentLayerIntRect>& rect = layer->GetClipRect()) {
     116           0 :     clip = Some(IntRectToRect(rect.ref()));
     117           0 :   } else if (layer->GetMaskLayer()) {
     118             :     // this layer has a mask, but no clip rect. so let's use the transformed
     119             :     // visible bounds as the clip rect.
     120           0 :     clip = Some(layer->GetLocalTransformTyped().TransformBounds(mLayer->Bounds()));
     121             :   }
     122           0 :   if (clip) {
     123           0 :     Maybe<WrImageMask> mask = mLayer->BuildWrMaskLayer(aStackingContext);
     124           0 :     LayerRect clipRect = ViewAs<LayerPixel>(clip.ref(),
     125           0 :         PixelCastJustification::MovingDownToChildren);
     126           0 :     mBuilder->PushClip(aStackingContext.ToRelativeWrRect(clipRect), mask.ptrOr(nullptr));
     127           0 :     mPushedLayerLocalClip = true;
     128             :   }
     129           0 : }
     130             : 
     131             : void
     132           0 : ScrollingLayersHelper::PushLayerClip(const LayerClip& aClip,
     133             :                                      const StackingContextHelper& aSc)
     134             : {
     135           0 :   LayerRect clipRect = IntRectToRect(ViewAs<LayerPixel>(aClip.GetClipRect(),
     136           0 :         PixelCastJustification::MovingDownToChildren));
     137           0 :   Maybe<WrImageMask> mask;
     138           0 :   if (Maybe<size_t> maskLayerIndex = aClip.GetMaskLayerIndex()) {
     139           0 :     Layer* maskLayer = mLayer->GetLayer()->GetAncestorMaskLayerAt(maskLayerIndex.value());
     140           0 :     WebRenderLayer* maskWrLayer = WebRenderLayer::ToWebRenderLayer(maskLayer);
     141             :     // TODO: check this transform is correct in all cases
     142           0 :     mask = maskWrLayer->RenderMaskLayer(aSc, maskLayer->GetTransform());
     143             :   }
     144           0 :   mBuilder->PushClip(aSc.ToRelativeWrRect(clipRect), mask.ptrOr(nullptr));
     145           0 : }
     146             : 
     147           0 : ScrollingLayersHelper::~ScrollingLayersHelper()
     148             : {
     149           0 :   Layer* layer = mLayer->GetLayer();
     150           0 :   if (!mLayer->WrManager()->AsyncPanZoomEnabled()) {
     151           0 :     if (mPushedLayerLocalClip) {
     152           0 :       mBuilder->PopClip();
     153             :     }
     154           0 :     return;
     155             :   }
     156             : 
     157           0 :   if (layer->GetIsFixedPosition()) {
     158           0 :     mBuilder->PopClipAndScrollInfo();
     159           0 :   } else if (mPushedLayerLocalClip) {
     160           0 :     mBuilder->PopClip();
     161             :   }
     162           0 :   if (layer->GetScrolledClip()) {
     163           0 :     mBuilder->PopClip();
     164             :   }
     165           0 :   for (uint32_t i = 0; i < layer->GetScrollMetadataCount(); i++) {
     166           0 :     const FrameMetrics& fm = layer->GetFrameMetrics(i);
     167           0 :     if (fm.IsScrollable()) {
     168           0 :       mBuilder->PopScrollLayer();
     169             :     }
     170           0 :     if (layer->GetIsFixedPosition() &&
     171           0 :         layer->GetFixedPositionScrollContainerId() == fm.GetScrollId() &&
     172           0 :         mPushedLayerLocalClip) {
     173           0 :       mBuilder->PopClip();
     174             :     }
     175           0 :     const ScrollMetadata& metadata = layer->GetScrollMetadata(i);
     176           0 :     if (metadata.GetScrollClip()) {
     177           0 :       mBuilder->PopClip();
     178             :     }
     179             :   }
     180           0 : }
     181             : 
     182             : } // namespace layers
     183             : } // namespace mozilla

Generated by: LCOV version 1.13