LCOV - code coverage report
Current view: top level - gfx/layers/client - ClientTiledPaintedLayer.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 273 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 17 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* This Source Code Form is subject to the terms of the Mozilla Public
       2             :  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
       3             :  * You can obtain one at http://mozilla.org/MPL/2.0/. */
       4             : 
       5             : #include "ClientTiledPaintedLayer.h"
       6             : #include "FrameMetrics.h"               // for FrameMetrics
       7             : #include "Units.h"                      // for ScreenIntRect, CSSPoint, etc
       8             : #include "UnitTransforms.h"             // for TransformTo
       9             : #include "ClientLayerManager.h"         // for ClientLayerManager, etc
      10             : #include "gfxPlatform.h"                // for gfxPlatform
      11             : #include "gfxPrefs.h"                   // for gfxPrefs
      12             : #include "gfxRect.h"                    // for gfxRect
      13             : #include "mozilla/Assertions.h"         // for MOZ_ASSERT, etc
      14             : #include "mozilla/gfx/BaseSize.h"       // for BaseSize
      15             : #include "mozilla/gfx/gfxVars.h"
      16             : #include "mozilla/gfx/Rect.h"           // for Rect, RectTyped
      17             : #include "mozilla/layers/CompositorBridgeChild.h"
      18             : #include "mozilla/layers/LayerMetricsWrapper.h" // for LayerMetricsWrapper
      19             : #include "mozilla/layers/LayersMessages.h"
      20             : #include "mozilla/mozalloc.h"           // for operator delete, etc
      21             : #include "nsISupportsImpl.h"            // for MOZ_COUNT_CTOR, etc
      22             : #include "LayersLogging.h"
      23             : #include "mozilla/layers/SingleTiledContentClient.h"
      24             : 
      25             : namespace mozilla {
      26             : namespace layers {
      27             : 
      28             : using gfx::Rect;
      29             : using gfx::IntRect;
      30             : using gfx::IntSize;
      31             : 
      32           0 : ClientTiledPaintedLayer::ClientTiledPaintedLayer(ClientLayerManager* const aManager,
      33           0 :                                                ClientLayerManager::PaintedLayerCreationHint aCreationHint)
      34             :   : PaintedLayer(aManager, static_cast<ClientLayer*>(this), aCreationHint)
      35             :   , mContentClient()
      36           0 :   , mHaveSingleTiledContentClient(false)
      37             : {
      38           0 :   MOZ_COUNT_CTOR(ClientTiledPaintedLayer);
      39           0 :   mPaintData.mLastScrollOffset = ParentLayerPoint(0, 0);
      40           0 :   mPaintData.mFirstPaint = true;
      41           0 : }
      42             : 
      43           0 : ClientTiledPaintedLayer::~ClientTiledPaintedLayer()
      44             : {
      45           0 :   MOZ_COUNT_DTOR(ClientTiledPaintedLayer);
      46           0 : }
      47             : 
      48             : void
      49           0 : ClientTiledPaintedLayer::ClearCachedResources()
      50             : {
      51           0 :   if (mContentClient) {
      52           0 :     mContentClient->ClearCachedResources();
      53             :   }
      54           0 :   ClearValidRegion();
      55           0 :   mContentClient = nullptr;
      56           0 : }
      57             : 
      58             : void
      59           0 : ClientTiledPaintedLayer::FillSpecificAttributes(SpecificLayerAttributes& aAttrs)
      60             : {
      61           0 :   aAttrs = PaintedLayerAttributes(GetValidRegion());
      62           0 : }
      63             : 
      64             : static Maybe<LayerRect>
      65           0 : ApplyParentLayerToLayerTransform(const ParentLayerToLayerMatrix4x4& aTransform,
      66             :                                  const ParentLayerRect& aParentLayerRect,
      67             :                                  const LayerRect& aClip)
      68             : {
      69           0 :   return UntransformBy(aTransform, aParentLayerRect, aClip);
      70             : }
      71             : 
      72             : static LayerToParentLayerMatrix4x4
      73           0 : GetTransformToAncestorsParentLayer(Layer* aStart, const LayerMetricsWrapper& aAncestor)
      74             : {
      75           0 :   gfx::Matrix4x4 transform;
      76           0 :   const LayerMetricsWrapper& ancestorParent = aAncestor.GetParent();
      77           0 :   for (LayerMetricsWrapper iter(aStart, LayerMetricsWrapper::StartAt::BOTTOM);
      78           0 :        ancestorParent ? iter != ancestorParent : iter.IsValid();
      79           0 :        iter = iter.GetParent()) {
      80           0 :     transform = transform * iter.GetTransform();
      81             : 
      82           0 :     if (gfxPrefs::LayoutUseContainersForRootFrames()) {
      83             :       // When scrolling containers, layout adds a post-scale into the transform
      84             :       // of the displayport-ancestor (which we pick up in GetTransform() above)
      85             :       // to cancel out the pres shell resolution (for historical reasons). The
      86             :       // compositor in turn cancels out this post-scale (i.e., scales by the
      87             :       // pres shell resolution), and to get correct calculations, we need to do
      88             :       // so here, too.
      89             :       //
      90             :       // With containerless scrolling, the offending post-scale is on the
      91             :       // parent layer of the displayport-ancestor, which we don't reach in this
      92             :       // loop, so we don't need to worry about it.
      93           0 :       float presShellResolution = iter.GetPresShellResolution();
      94           0 :       transform.PostScale(presShellResolution, presShellResolution, 1.0f);
      95             :     }
      96             :   }
      97           0 :   return ViewAs<LayerToParentLayerMatrix4x4>(transform);
      98             : }
      99             : 
     100             : void
     101           0 : ClientTiledPaintedLayer::GetAncestorLayers(LayerMetricsWrapper* aOutScrollAncestor,
     102             :                                            LayerMetricsWrapper* aOutDisplayPortAncestor,
     103             :                                            bool* aOutHasTransformAnimation)
     104             : {
     105           0 :   LayerMetricsWrapper scrollAncestor;
     106           0 :   LayerMetricsWrapper displayPortAncestor;
     107           0 :   bool hasTransformAnimation = false;
     108           0 :   for (LayerMetricsWrapper ancestor(this, LayerMetricsWrapper::StartAt::BOTTOM); ancestor; ancestor = ancestor.GetParent()) {
     109           0 :     hasTransformAnimation |= ancestor.HasTransformAnimation();
     110           0 :     const FrameMetrics& metrics = ancestor.Metrics();
     111           0 :     if (!scrollAncestor && metrics.GetScrollId() != FrameMetrics::NULL_SCROLL_ID) {
     112           0 :       scrollAncestor = ancestor;
     113             :     }
     114           0 :     if (!metrics.GetDisplayPort().IsEmpty()) {
     115           0 :       displayPortAncestor = ancestor;
     116             :       // Any layer that has a displayport must be scrollable, so we can break
     117             :       // here.
     118           0 :       break;
     119             :     }
     120             :   }
     121           0 :   if (aOutScrollAncestor) {
     122           0 :     *aOutScrollAncestor = scrollAncestor;
     123             :   }
     124           0 :   if (aOutDisplayPortAncestor) {
     125           0 :     *aOutDisplayPortAncestor = displayPortAncestor;
     126             :   }
     127           0 :   if (aOutHasTransformAnimation) {
     128           0 :     *aOutHasTransformAnimation = hasTransformAnimation;
     129             :   }
     130           0 : }
     131             : 
     132             : void
     133           0 : ClientTiledPaintedLayer::BeginPaint()
     134             : {
     135           0 :   mPaintData.ResetPaintData();
     136             : 
     137           0 :   if (!GetBaseTransform().Is2D()) {
     138             :     // Give up if there is a complex CSS transform on the layer. We might
     139             :     // eventually support these but for now it's too complicated to handle
     140             :     // given that it's a pretty rare scenario.
     141           0 :     return;
     142             :   }
     143             : 
     144             :   // Get the metrics of the nearest scrollable layer and the nearest layer
     145             :   // with a displayport.
     146           0 :   LayerMetricsWrapper scrollAncestor;
     147           0 :   LayerMetricsWrapper displayPortAncestor;
     148             :   bool hasTransformAnimation;
     149           0 :   GetAncestorLayers(&scrollAncestor, &displayPortAncestor, &hasTransformAnimation);
     150             : 
     151           0 :   if (!displayPortAncestor || !scrollAncestor) {
     152             :     // No displayport or scroll ancestor, so we can't do progressive rendering.
     153             : #if defined(MOZ_WIDGET_ANDROID)
     154             :     // Android are guaranteed to have a displayport set, so this
     155             :     // should never happen.
     156             :     NS_WARNING("Tiled PaintedLayer with no scrollable container ancestor");
     157             : #endif
     158           0 :     return;
     159             :   }
     160             : 
     161             :   TILING_LOG("TILING %p: Found scrollAncestor %p, displayPortAncestor %p, transform %d\n", this,
     162             :     scrollAncestor.GetLayer(), displayPortAncestor.GetLayer(), hasTransformAnimation);
     163             : 
     164           0 :   const FrameMetrics& scrollMetrics = scrollAncestor.Metrics();
     165           0 :   const FrameMetrics& displayportMetrics = displayPortAncestor.Metrics();
     166             : 
     167             :   // Calculate the transform required to convert ParentLayer space of our
     168             :   // display port ancestor to the Layer space of this layer.
     169             :   ParentLayerToLayerMatrix4x4 transformDisplayPortToLayer =
     170           0 :     GetTransformToAncestorsParentLayer(this, displayPortAncestor).Inverse();
     171             : 
     172           0 :   LayerRect layerBounds(GetVisibleRegion().GetBounds());
     173             : 
     174             :   // Compute the critical display port that applies to this layer in the
     175             :   // LayoutDevice space of this layer, but only if there is no OMT animation
     176             :   // on this layer. If there is an OMT animation then we need to draw the whole
     177             :   // visible region of this layer as determined by layout, because we don't know
     178             :   // what parts of it might move into view in the compositor.
     179           0 :   mPaintData.mHasTransformAnimation = hasTransformAnimation;
     180           0 :   if (!mPaintData.mHasTransformAnimation &&
     181           0 :       mContentClient->GetLowPrecisionTiledBuffer()) {
     182             :     ParentLayerRect criticalDisplayPort =
     183           0 :       (displayportMetrics.GetCriticalDisplayPort() * displayportMetrics.GetZoom())
     184           0 :       + displayportMetrics.GetCompositionBounds().TopLeft();
     185             :     Maybe<LayerRect> criticalDisplayPortTransformed =
     186           0 :       ApplyParentLayerToLayerTransform(transformDisplayPortToLayer, criticalDisplayPort, layerBounds);
     187           0 :     if (criticalDisplayPortTransformed) {
     188           0 :       mPaintData.mCriticalDisplayPort = Some(RoundedToInt(*criticalDisplayPortTransformed));
     189             :     } else {
     190           0 :       mPaintData.mCriticalDisplayPort = Some(LayerIntRect(0, 0, 0, 0));
     191             :     }
     192             :   }
     193             :   TILING_LOG("TILING %p: Critical displayport %s\n", this,
     194             :              mPaintData.mCriticalDisplayPort ?
     195             :              Stringify(*mPaintData.mCriticalDisplayPort).c_str() : "not set");
     196             : 
     197             :   // Store the resolution from the displayport ancestor layer. Because this is Gecko-side,
     198             :   // before any async transforms have occurred, we can use the zoom for this.
     199           0 :   mPaintData.mResolution = displayportMetrics.GetZoom();
     200             :   TILING_LOG("TILING %p: Resolution %s\n", this, Stringify(mPaintData.mResolution).c_str());
     201             : 
     202             :   // Store the applicable composition bounds in this layer's Layer units.
     203           0 :   mPaintData.mTransformToCompBounds =
     204           0 :     GetTransformToAncestorsParentLayer(this, scrollAncestor);
     205           0 :   ParentLayerToLayerMatrix4x4 transformToBounds = mPaintData.mTransformToCompBounds.Inverse();
     206             :   Maybe<LayerRect> compositionBoundsTransformed = ApplyParentLayerToLayerTransform(
     207           0 :     transformToBounds, scrollMetrics.GetCompositionBounds(), layerBounds);
     208           0 :   if (compositionBoundsTransformed) {
     209           0 :     mPaintData.mCompositionBounds = *compositionBoundsTransformed;
     210             :   } else {
     211           0 :     mPaintData.mCompositionBounds.SetEmpty();
     212             :   }
     213             :   TILING_LOG("TILING %p: Composition bounds %s\n", this, Stringify(mPaintData.mCompositionBounds).c_str());
     214             : 
     215             :   // Calculate the scroll offset since the last transaction
     216           0 :   mPaintData.mScrollOffset = displayportMetrics.GetScrollOffset() * displayportMetrics.GetZoom();
     217             :   TILING_LOG("TILING %p: Scroll offset %s\n", this, Stringify(mPaintData.mScrollOffset).c_str());
     218             : }
     219             : 
     220             : bool
     221           0 : ClientTiledPaintedLayer::IsScrollingOnCompositor(const FrameMetrics& aParentMetrics)
     222             : {
     223           0 :   CompositorBridgeChild* compositor = nullptr;
     224           0 :   if (Manager() && Manager()->AsClientLayerManager()) {
     225           0 :     compositor = Manager()->AsClientLayerManager()->GetCompositorBridgeChild();
     226             :   }
     227             : 
     228           0 :   if (!compositor) {
     229           0 :     return false;
     230             :   }
     231             : 
     232           0 :   FrameMetrics compositorMetrics;
     233           0 :   if (!compositor->LookupCompositorFrameMetrics(aParentMetrics.GetScrollId(),
     234             :                                                 compositorMetrics)) {
     235           0 :     return false;
     236             :   }
     237             : 
     238             :   // 1 is a tad high for a fuzzy equals epsilon however if our scroll delta
     239             :   // is so small then we have nothing to gain from using paint heuristics.
     240           0 :   float COORDINATE_EPSILON = 1.f;
     241             : 
     242           0 :   return !FuzzyEqualsAdditive(compositorMetrics.GetScrollOffset().x,
     243           0 :                               aParentMetrics.GetScrollOffset().x,
     244           0 :                               COORDINATE_EPSILON) ||
     245           0 :          !FuzzyEqualsAdditive(compositorMetrics.GetScrollOffset().y,
     246           0 :                               aParentMetrics.GetScrollOffset().y,
     247           0 :                               COORDINATE_EPSILON);
     248             : }
     249             : 
     250             : bool
     251           0 : ClientTiledPaintedLayer::UseProgressiveDraw() {
     252           0 :   if (!gfxPrefs::ProgressivePaint()) {
     253             :     // pref is disabled, so never do progressive
     254           0 :     return false;
     255             :   }
     256             : 
     257           0 :   if (!mContentClient->GetTiledBuffer()->SupportsProgressiveUpdate()) {
     258           0 :     return false;
     259             :   }
     260             : 
     261           0 :   if (ClientManager()->HasShadowTarget()) {
     262             :     // This condition is true when we are in a reftest scenario. We don't want
     263             :     // to draw progressively here because it can cause intermittent reftest
     264             :     // failures because the harness won't wait for all the tiles to be drawn.
     265           0 :     return false;
     266             :   }
     267             : 
     268           0 :   if (GetIsFixedPosition() || GetParent()->GetIsFixedPosition()) {
     269             :     // This layer is fixed-position and so even if it does have a scrolling
     270             :     // ancestor it will likely be entirely on-screen all the time, so we
     271             :     // should draw it all at once
     272           0 :     return false;
     273             :   }
     274             : 
     275           0 :   if (mPaintData.mHasTransformAnimation) {
     276             :     // The compositor is going to animate this somehow, so we want it all
     277             :     // on the screen at once.
     278           0 :     return false;
     279             :   }
     280             : 
     281           0 :   if (ClientManager()->AsyncPanZoomEnabled()) {
     282           0 :     LayerMetricsWrapper scrollAncestor;
     283           0 :     GetAncestorLayers(&scrollAncestor, nullptr, nullptr);
     284           0 :     MOZ_ASSERT(scrollAncestor); // because mPaintData.mCriticalDisplayPort is set
     285           0 :     if (!scrollAncestor) {
     286           0 :       return false;
     287             :     }
     288           0 :     const FrameMetrics& parentMetrics = scrollAncestor.Metrics();
     289           0 :     if (!IsScrollingOnCompositor(parentMetrics)) {
     290           0 :       return false;
     291             :     }
     292             :   }
     293             : 
     294           0 :   return true;
     295             : }
     296             : 
     297             : bool
     298           0 : ClientTiledPaintedLayer::RenderHighPrecision(const nsIntRegion& aInvalidRegion,
     299             :                                             const nsIntRegion& aVisibleRegion,
     300             :                                             LayerManager::DrawPaintedLayerCallback aCallback,
     301             :                                             void* aCallbackData)
     302             : {
     303             :   // If we have started drawing low-precision already, then we
     304             :   // shouldn't do anything there.
     305           0 :   if (mPaintData.mLowPrecisionPaintCount != 0) {
     306           0 :     return false;
     307             :   }
     308             : 
     309             :   // Only draw progressively when there is something to paint and the
     310             :   // resolution is unchanged
     311           0 :   if (!aInvalidRegion.IsEmpty() &&
     312           0 :       UseProgressiveDraw() &&
     313           0 :       mContentClient->GetTiledBuffer()->GetFrameResolution() == mPaintData.mResolution) {
     314             :     // Store the old valid region, then clear it before painting.
     315             :     // We clip the old valid region to the visible region, as it only gets
     316             :     // used to decide stale content (currently valid and previously visible)
     317           0 :     nsIntRegion oldValidRegion = mContentClient->GetTiledBuffer()->GetValidRegion();
     318           0 :     oldValidRegion.And(oldValidRegion, aVisibleRegion);
     319           0 :     if (mPaintData.mCriticalDisplayPort) {
     320           0 :       oldValidRegion.And(oldValidRegion, mPaintData.mCriticalDisplayPort->ToUnknownRect());
     321             :     }
     322             : 
     323             :     TILING_LOG("TILING %p: Progressive update with old valid region %s\n", this, Stringify(oldValidRegion).c_str());
     324             : 
     325           0 :     nsIntRegion drawnRegion;
     326             :     bool updatedBuffer =
     327           0 :       mContentClient->GetTiledBuffer()->ProgressiveUpdate(GetValidRegion(), aInvalidRegion,
     328           0 :                       oldValidRegion, drawnRegion, &mPaintData, aCallback, aCallbackData);
     329           0 :     AddToValidRegion(drawnRegion);
     330           0 :     return updatedBuffer;
     331             :   }
     332             : 
     333             :   // Otherwise do a non-progressive paint. We must do this even when
     334             :   // the region to paint is empty as the valid region may have shrunk.
     335             : 
     336           0 :   nsIntRegion validRegion = aVisibleRegion;
     337           0 :   if (mPaintData.mCriticalDisplayPort) {
     338           0 :     validRegion.AndWith(mPaintData.mCriticalDisplayPort->ToUnknownRect());
     339             :   }
     340           0 :   SetValidRegion(validRegion);
     341             : 
     342             :   TILING_LOG("TILING %p: Non-progressive paint invalid region %s\n", this, Stringify(aInvalidRegion).c_str());
     343             :   TILING_LOG("TILING %p: Non-progressive paint new valid region %s\n", this, Stringify(GetValidRegion()).c_str());
     344             : 
     345           0 :   mContentClient->GetTiledBuffer()->SetFrameResolution(mPaintData.mResolution);
     346           0 :   mContentClient->GetTiledBuffer()->PaintThebes(GetValidRegion(), aInvalidRegion, aInvalidRegion,
     347           0 :                                                 aCallback, aCallbackData);
     348           0 :   mPaintData.mPaintFinished = true;
     349           0 :   return true;
     350             : }
     351             : 
     352             : bool
     353           0 : ClientTiledPaintedLayer::RenderLowPrecision(const nsIntRegion& aInvalidRegion,
     354             :                                            const nsIntRegion& aVisibleRegion,
     355             :                                            LayerManager::DrawPaintedLayerCallback aCallback,
     356             :                                            void* aCallbackData)
     357             : {
     358           0 :   nsIntRegion invalidRegion = aInvalidRegion;
     359             : 
     360             :   // Render the low precision buffer, if the visible region is larger than the
     361             :   // critical display port.
     362           0 :   if (!mPaintData.mCriticalDisplayPort ||
     363           0 :       !nsIntRegion(mPaintData.mCriticalDisplayPort->ToUnknownRect()).Contains(aVisibleRegion)) {
     364           0 :     nsIntRegion oldValidRegion = mContentClient->GetLowPrecisionTiledBuffer()->GetValidRegion();
     365           0 :     oldValidRegion.And(oldValidRegion, aVisibleRegion);
     366             : 
     367           0 :     bool updatedBuffer = false;
     368             : 
     369             :     // If the frame resolution or format have changed, invalidate the buffer
     370           0 :     if (mContentClient->GetLowPrecisionTiledBuffer()->GetFrameResolution() != mPaintData.mResolution ||
     371           0 :         mContentClient->GetLowPrecisionTiledBuffer()->HasFormatChanged()) {
     372           0 :       if (!mLowPrecisionValidRegion.IsEmpty()) {
     373           0 :         updatedBuffer = true;
     374             :       }
     375           0 :       oldValidRegion.SetEmpty();
     376           0 :       mLowPrecisionValidRegion.SetEmpty();
     377           0 :       mContentClient->GetLowPrecisionTiledBuffer()->ResetPaintedAndValidState();
     378           0 :       mContentClient->GetLowPrecisionTiledBuffer()->SetFrameResolution(mPaintData.mResolution);
     379           0 :       invalidRegion = aVisibleRegion;
     380             :     }
     381             : 
     382             :     // Invalidate previously valid content that is no longer visible
     383           0 :     if (mPaintData.mLowPrecisionPaintCount == 1) {
     384           0 :       mLowPrecisionValidRegion.And(mLowPrecisionValidRegion, aVisibleRegion);
     385             :     }
     386           0 :     mPaintData.mLowPrecisionPaintCount++;
     387             : 
     388             :     // Remove the valid high-precision region from the invalid low-precision
     389             :     // region. We don't want to spend time drawing things twice.
     390           0 :     invalidRegion.SubOut(GetValidRegion());
     391             : 
     392             :     TILING_LOG("TILING %p: Progressive paint: low-precision invalid region is %s\n", this, Stringify(invalidRegion).c_str());
     393             :     TILING_LOG("TILING %p: Progressive paint: low-precision old valid region is %s\n", this, Stringify(oldValidRegion).c_str());
     394             : 
     395           0 :     if (!invalidRegion.IsEmpty()) {
     396           0 :       nsIntRegion drawnRegion;
     397           0 :       updatedBuffer = mContentClient->GetLowPrecisionTiledBuffer()->ProgressiveUpdate(
     398             :                             mLowPrecisionValidRegion, invalidRegion, oldValidRegion,
     399           0 :                             drawnRegion, &mPaintData, aCallback, aCallbackData);
     400           0 :       mLowPrecisionValidRegion.OrWith(drawnRegion);
     401             :     }
     402             : 
     403             :     TILING_LOG("TILING %p: Progressive paint: low-precision new valid region is %s\n", this, Stringify(mLowPrecisionValidRegion).c_str());
     404           0 :     return updatedBuffer;
     405             :   }
     406           0 :   if (!mLowPrecisionValidRegion.IsEmpty()) {
     407             :     TILING_LOG("TILING %p: Clearing low-precision buffer\n", this);
     408             :     // Clear the low precision tiled buffer.
     409           0 :     mLowPrecisionValidRegion.SetEmpty();
     410           0 :     mContentClient->GetLowPrecisionTiledBuffer()->ResetPaintedAndValidState();
     411             :     // Return true here so we send a Painted callback after clearing the valid
     412             :     // region of the low precision buffer. This allows the shadow buffer's valid
     413             :     // region to be updated and the associated resources to be freed.
     414           0 :     return true;
     415             :   }
     416           0 :   return false;
     417             : }
     418             : 
     419             : void
     420           0 : ClientTiledPaintedLayer::EndPaint()
     421             : {
     422           0 :   mPaintData.mLastScrollOffset = mPaintData.mScrollOffset;
     423           0 :   mPaintData.mPaintFinished = true;
     424           0 :   mPaintData.mFirstPaint = false;
     425             :   TILING_LOG("TILING %p: Paint finished\n", this);
     426           0 : }
     427             : 
     428             : void
     429           0 : ClientTiledPaintedLayer::RenderLayer()
     430             : {
     431             :   LayerManager::DrawPaintedLayerCallback callback =
     432           0 :     ClientManager()->GetPaintedLayerCallback();
     433           0 :   void *data = ClientManager()->GetPaintedLayerCallbackData();
     434             : 
     435           0 :   IntSize layerSize = mVisibleRegion.ToUnknownRegion().GetBounds().Size();
     436           0 :   IntSize tileSize = gfx::gfxVars::TileSize();
     437           0 :   bool isHalfTileWidthOrHeight = layerSize.width <= tileSize.width / 2 ||
     438           0 :     layerSize.height <= tileSize.height / 2;
     439             : 
     440             :   // Use single tile when layer is not scrollable, is smaller than one
     441             :   // tile, or when more than half of the tiles' pixels in either
     442             :   // dimension would be wasted.
     443             :   bool wantSingleTiledContentClient =
     444           0 :       (mCreationHint == LayerManager::NONE ||
     445           0 :        layerSize <= tileSize ||
     446           0 :        isHalfTileWidthOrHeight) &&
     447           0 :       SingleTiledContentClient::ClientSupportsLayerSize(layerSize, ClientManager()) &&
     448           0 :       gfxPrefs::LayersSingleTileEnabled();
     449             : 
     450           0 :   if (mContentClient && mHaveSingleTiledContentClient && !wantSingleTiledContentClient) {
     451           0 :     mContentClient = nullptr;
     452           0 :     ClearValidRegion();
     453             :   }
     454             : 
     455           0 :   if (!mContentClient) {
     456           0 :     if (wantSingleTiledContentClient) {
     457           0 :       mContentClient = new SingleTiledContentClient(*this, ClientManager());
     458           0 :       mHaveSingleTiledContentClient = true;
     459             :     } else {
     460           0 :       mContentClient = new MultiTiledContentClient(*this, ClientManager());
     461           0 :       mHaveSingleTiledContentClient = false;
     462             :     }
     463             : 
     464           0 :     mContentClient->Connect();
     465           0 :     ClientManager()->AsShadowForwarder()->Attach(mContentClient, this);
     466           0 :     MOZ_ASSERT(mContentClient->GetForwarder());
     467             :   }
     468             : 
     469           0 :   if (mContentClient->GetTiledBuffer()->HasFormatChanged()) {
     470           0 :     ClearValidRegion();
     471           0 :     mContentClient->GetTiledBuffer()->ResetPaintedAndValidState();
     472             :   }
     473             : 
     474             :   TILING_LOG("TILING %p: Initial visible region %s\n", this, Stringify(mVisibleRegion).c_str());
     475             :   TILING_LOG("TILING %p: Initial valid region %s\n", this, Stringify(GetValidRegion()).c_str());
     476             :   TILING_LOG("TILING %p: Initial low-precision valid region %s\n", this, Stringify(mLowPrecisionValidRegion).c_str());
     477             : 
     478           0 :   nsIntRegion neededRegion = mVisibleRegion.ToUnknownRegion();
     479             : #ifndef MOZ_IGNORE_PAINT_WILL_RESAMPLE
     480             :   // This is handled by PadDrawTargetOutFromRegion in TiledContentClient for mobile
     481           0 :   if (MayResample()) {
     482             :     // If we're resampling then bilinear filtering can read up to 1 pixel
     483             :     // outside of our texture coords. Make the visible region a single rect,
     484             :     // and pad it out by 1 pixel (restricted to tile boundaries) so that
     485             :     // we always have valid content or transparent pixels to sample from.
     486           0 :     IntRect bounds = neededRegion.GetBounds();
     487           0 :     IntRect wholeTiles = bounds;
     488           0 :     wholeTiles.InflateToMultiple(gfx::gfxVars::TileSize());
     489           0 :     IntRect padded = bounds;
     490           0 :     padded.Inflate(1);
     491           0 :     padded.IntersectRect(padded, wholeTiles);
     492           0 :     neededRegion = padded;
     493             :   }
     494             : #endif
     495             : 
     496           0 :   nsIntRegion invalidRegion;
     497           0 :   invalidRegion.Sub(neededRegion, GetValidRegion());
     498           0 :   if (invalidRegion.IsEmpty()) {
     499           0 :     EndPaint();
     500           0 :     return;
     501             :   }
     502             : 
     503           0 :   if (!callback) {
     504           0 :     ClientManager()->SetTransactionIncomplete();
     505           0 :     return;
     506             :   }
     507             : 
     508           0 :   if (!ClientManager()->IsRepeatTransaction()) {
     509             :     // Only paint the mask layers on the first transaction.
     510           0 :     RenderMaskLayers(this);
     511             : 
     512             :     // For more complex cases we need to calculate a bunch of metrics before we
     513             :     // can do the paint.
     514           0 :     BeginPaint();
     515           0 :     if (mPaintData.mPaintFinished) {
     516           0 :       return;
     517             :     }
     518             : 
     519             :     // Make sure that tiles that fall outside of the visible region or outside of the
     520             :     // critical displayport are discarded on the first update. Also make sure that we
     521             :     // only draw stuff inside the critical displayport on the first update.
     522           0 :     nsIntRegion validRegion;
     523           0 :     validRegion.And(GetValidRegion(), neededRegion);
     524           0 :     if (mPaintData.mCriticalDisplayPort) {
     525           0 :       validRegion.AndWith(mPaintData.mCriticalDisplayPort->ToUnknownRect());
     526           0 :       invalidRegion.And(invalidRegion, mPaintData.mCriticalDisplayPort->ToUnknownRect());
     527             :     }
     528           0 :     SetValidRegion(validRegion);
     529             : 
     530             :     TILING_LOG("TILING %p: First-transaction valid region %s\n", this, Stringify(validRegion).c_str());
     531             :     TILING_LOG("TILING %p: First-transaction invalid region %s\n", this, Stringify(invalidRegion).c_str());
     532             :   } else {
     533           0 :     if (mPaintData.mCriticalDisplayPort) {
     534           0 :       invalidRegion.And(invalidRegion, mPaintData.mCriticalDisplayPort->ToUnknownRect());
     535             :     }
     536             :     TILING_LOG("TILING %p: Repeat-transaction invalid region %s\n", this, Stringify(invalidRegion).c_str());
     537             :   }
     538             : 
     539           0 :   nsIntRegion lowPrecisionInvalidRegion;
     540           0 :   if (mContentClient->GetLowPrecisionTiledBuffer()) {
     541             :     // Calculate the invalid region for the low precision buffer. Make sure
     542             :     // to remove the valid high-precision area so we don't double-paint it.
     543           0 :     lowPrecisionInvalidRegion.Sub(neededRegion, mLowPrecisionValidRegion);
     544           0 :     lowPrecisionInvalidRegion.Sub(lowPrecisionInvalidRegion, GetValidRegion());
     545             :   }
     546             :   TILING_LOG("TILING %p: Low-precision invalid region %s\n", this, Stringify(lowPrecisionInvalidRegion).c_str());
     547             : 
     548             :   bool updatedHighPrecision = RenderHighPrecision(invalidRegion,
     549             :                                                   neededRegion,
     550           0 :                                                   callback, data);
     551           0 :   if (updatedHighPrecision) {
     552           0 :     ClientManager()->Hold(this);
     553           0 :     mContentClient->UpdatedBuffer(TiledContentClient::TILED_BUFFER);
     554             : 
     555           0 :     if (!mPaintData.mPaintFinished) {
     556             :       // There is still more high-res stuff to paint, so we're not
     557             :       // done yet. A subsequent transaction will take care of this.
     558           0 :       ClientManager()->SetRepeatTransaction();
     559           0 :       return;
     560             :     }
     561             :   }
     562             : 
     563             :   // If there is nothing to draw in low-precision, then we're done.
     564           0 :   if (lowPrecisionInvalidRegion.IsEmpty()) {
     565           0 :     EndPaint();
     566           0 :     return;
     567             :   }
     568             : 
     569           0 :   if (updatedHighPrecision) {
     570             :     // If there are low precision updates, but we just did some high-precision
     571             :     // updates, then mark the paint as unfinished and request a repeat transaction.
     572             :     // This is so that we don't perform low-precision updates in the same transaction
     573             :     // as high-precision updates.
     574             :     TILING_LOG("TILING %p: Scheduling repeat transaction for low-precision painting\n", this);
     575           0 :     ClientManager()->SetRepeatTransaction();
     576           0 :     mPaintData.mLowPrecisionPaintCount = 1;
     577           0 :     mPaintData.mPaintFinished = false;
     578           0 :     return;
     579             :   }
     580             : 
     581             :   bool updatedLowPrecision = RenderLowPrecision(lowPrecisionInvalidRegion,
     582             :                                                 neededRegion,
     583           0 :                                                 callback, data);
     584           0 :   if (updatedLowPrecision) {
     585           0 :     ClientManager()->Hold(this);
     586           0 :     mContentClient->UpdatedBuffer(TiledContentClient::LOW_PRECISION_TILED_BUFFER);
     587             : 
     588           0 :     if (!mPaintData.mPaintFinished) {
     589             :       // There is still more low-res stuff to paint, so we're not
     590             :       // done yet. A subsequent transaction will take care of this.
     591           0 :       ClientManager()->SetRepeatTransaction();
     592           0 :       return;
     593             :     }
     594             :   }
     595             : 
     596             :   // If we get here, we've done all the high- and low-precision
     597             :   // paints we wanted to do, so we can finish the paint and chill.
     598           0 :   EndPaint();
     599             : }
     600             : 
     601             : bool
     602           0 : ClientTiledPaintedLayer::IsOptimizedFor(LayerManager::PaintedLayerCreationHint aHint)
     603             : {
     604             :   // The only creation hint is whether the layer is scrollable or not, and this
     605             :   // is only respected on OSX, where it's used to determine whether to
     606             :   // use a tiled content client or not.
     607             :   // There are pretty nasty performance consequences for not using tiles on
     608             :   // large, scrollable layers, so we want the layer to be recreated in this
     609             :   // situation.
     610           0 :   return aHint == GetCreationHint();
     611             : }
     612             : 
     613             : void
     614           0 : ClientTiledPaintedLayer::PrintInfo(std::stringstream& aStream, const char* aPrefix)
     615             : {
     616           0 :   PaintedLayer::PrintInfo(aStream, aPrefix);
     617           0 :   if (mContentClient) {
     618           0 :     aStream << "\n";
     619           0 :     nsAutoCString pfx(aPrefix);
     620           0 :     pfx += "  ";
     621           0 :     mContentClient->PrintInfo(aStream, pfx.get());
     622             :   }
     623           0 : }
     624             : 
     625             : } // namespace layers
     626             : } // namespace mozilla

Generated by: LCOV version 1.13