LCOV - code coverage report
Current view: top level - gfx/layers/composite - ContainerLayerComposite.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 8 324 2.5 %
Date: 2018-08-07 16:42:27 Functions: 0 0 -
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #include "ContainerLayerComposite.h"
       8             : #include <algorithm>                    // for min
       9             : #include "FrameMetrics.h"               // for FrameMetrics
      10             : #include "Units.h"                      // for LayerRect, LayerPixel, etc
      11             : #include "CompositableHost.h"           // for CompositableHost
      12             : #include "gfxEnv.h"                     // for gfxEnv
      13             : #include "gfxPrefs.h"                   // for gfxPrefs
      14             : #include "mozilla/Assertions.h"         // for MOZ_ASSERT, etc
      15             : #include "mozilla/RefPtr.h"             // for RefPtr
      16             : #include "mozilla/UniquePtr.h"          // for UniquePtr
      17             : #include "mozilla/gfx/BaseRect.h"       // for BaseRect
      18             : #include "mozilla/gfx/Matrix.h"         // for Matrix4x4
      19             : #include "mozilla/gfx/Point.h"          // for Point, IntPoint
      20             : #include "mozilla/gfx/Rect.h"           // for IntRect, Rect
      21             : #include "mozilla/layers/APZSampler.h"  // for APZSampler
      22             : #include "mozilla/layers/Compositor.h"  // for Compositor, etc
      23             : #include "mozilla/layers/CompositorTypes.h"  // for DiagnosticFlags::CONTAINER
      24             : #include "mozilla/layers/Effects.h"     // for Effect, EffectChain, etc
      25             : #include "mozilla/layers/TextureHost.h"  // for CompositingRenderTarget
      26             : #include "mozilla/layers/AsyncCompositionManager.h" // for ViewTransform
      27             : #include "mozilla/layers/LayerMetricsWrapper.h" // for LayerMetricsWrapper
      28             : #include "mozilla/mozalloc.h"           // for operator delete, etc
      29             : #include "mozilla/RefPtr.h"                   // for nsRefPtr
      30             : #include "nsDebug.h"                    // for NS_ASSERTION
      31             : #include "nsISupportsImpl.h"            // for MOZ_COUNT_CTOR, etc
      32             : #include "nsISupportsUtils.h"           // for NS_ADDREF, NS_RELEASE
      33             : #include "nsRegion.h"                   // for nsIntRegion
      34             : #include "nsTArray.h"                   // for AutoTArray
      35             : #include <stack>
      36             : #include "TextRenderer.h"               // for TextRenderer
      37             : #include <vector>
      38             : #include "GeckoProfiler.h"              // for GeckoProfiler
      39             : 
      40             : #ifdef MOZ_GECKO_PROFILER
      41             : #include "ProfilerMarkerPayload.h"      // for LayerTranslationMarkerPayload
      42             : #endif
      43             : 
      44             : #define CULLING_LOG(...)
      45             : // #define CULLING_LOG(...) printf_stderr("CULLING: " __VA_ARGS__)
      46             : 
      47             : #define DUMP(...) do { if (gfxEnv::DumpDebug()) { printf_stderr(__VA_ARGS__); } } while(0)
      48             : #define XYWH(k)  (k).X(), (k).Y(), (k).Width(), (k).Height()
      49             : #define XY(k)    (k).X(), (k).Y()
      50             : #define WH(k)    (k).Width(), (k).Height()
      51             : 
      52             : namespace mozilla {
      53             : namespace layers {
      54             : 
      55             : using namespace gfx;
      56             : 
      57             : static void
      58           0 : DrawLayerInfo(const RenderTargetIntRect& aClipRect,
      59             :               LayerManagerComposite* aManager,
      60             :               Layer* aLayer)
      61             : {
      62           0 :   if (aLayer->GetType() == Layer::LayerType::TYPE_CONTAINER) {
      63             :     // XXX - should figure out a way to render this, but for now this
      64             :     // is hard to do, since it will often get superimposed over the first
      65             :     // child of the layer, which is bad.
      66           0 :     return;
      67             :   }
      68             : 
      69           0 :   std::stringstream ss;
      70           0 :   aLayer->PrintInfo(ss, "");
      71             : 
      72           0 :   LayerIntRegion visibleRegion = aLayer->GetVisibleRegion();
      73             : 
      74           0 :   uint32_t maxWidth = std::min<uint32_t>(visibleRegion.GetBounds().Width(), 500);
      75             : 
      76           0 :   IntPoint topLeft = visibleRegion.ToUnknownRegion().GetBounds().TopLeft();
      77           0 :   aManager->GetTextRenderer()->RenderText(
      78             :     aManager->GetCompositor(),
      79           0 :     ss.str().c_str(),
      80             :     topLeft,
      81             :     aLayer->GetEffectiveTransform(), 16,
      82           0 :     maxWidth);
      83             : }
      84             : 
      85             : static void
      86           0 : PrintUniformityInfo(Layer* aLayer)
      87             : {
      88             : #if defined(MOZ_GECKO_PROFILER)
      89           0 :   if (!profiler_is_active()) {
      90           0 :     return;
      91             :   }
      92             : 
      93             :   // Don't want to print a log for smaller layers
      94           0 :   if (aLayer->GetLocalVisibleRegion().GetBounds().Width() < 300 ||
      95           0 :       aLayer->GetLocalVisibleRegion().GetBounds().Height() < 300) {
      96             :     return;
      97             :   }
      98             : 
      99           0 :   Matrix4x4 transform = aLayer->AsHostLayer()->GetShadowBaseTransform();
     100           0 :   if (!transform.Is2D()) {
     101             :     return;
     102             :   }
     103             : 
     104           0 :   Point translation = transform.As2D().GetTranslation();
     105           0 :   profiler_add_marker(
     106             :     "LayerTranslation",
     107           0 :     MakeUnique<LayerTranslationMarkerPayload>(aLayer, translation,
     108           0 :                                               TimeStamp::Now()));
     109             : #endif
     110             : }
     111             : 
     112             : static Maybe<gfx::Polygon>
     113           0 : SelectLayerGeometry(const Maybe<gfx::Polygon>& aParentGeometry,
     114             :                     const Maybe<gfx::Polygon>& aChildGeometry)
     115             : {
     116             :   // Both the parent and the child layer were split.
     117           0 :   if (aParentGeometry && aChildGeometry) {
     118           0 :     return Some(aParentGeometry->ClipPolygon(*aChildGeometry));
     119             :   }
     120             : 
     121             :   // The parent layer was split.
     122           0 :   if (aParentGeometry) {
     123           0 :     return aParentGeometry;
     124             :   }
     125             : 
     126             :   // The child layer was split.
     127           0 :   if(aChildGeometry) {
     128           0 :     return aChildGeometry;
     129             :   }
     130             : 
     131             :   // No split.
     132             :   return Nothing();
     133             : }
     134             : 
     135             : void
     136           0 : TransformLayerGeometry(Layer* aLayer, Maybe<gfx::Polygon>& aGeometry)
     137             : {
     138           0 :   Layer* parent = aLayer;
     139           0 :   gfx::Matrix4x4 transform;
     140             : 
     141             :   // Collect all parent transforms.
     142           0 :   while (parent != nullptr && !parent->Is3DContextLeaf()) {
     143           0 :     transform = transform * parent->GetLocalTransform();
     144           0 :     parent = parent->GetParent();
     145             :   }
     146             : 
     147             :   // Transform the geometry to the parent 3D context leaf coordinate space.
     148           0 :   transform = transform.ProjectTo2D();
     149             : 
     150           0 :   if (!transform.IsSingular()) {
     151           0 :     aGeometry->TransformToScreenSpace(transform.Inverse());
     152             :   } else {
     153             :     // Discard the geometry since the result might not be correct.
     154           0 :     aGeometry.reset();
     155             :   }
     156           0 : }
     157             : 
     158             : 
     159             : template<class ContainerT>
     160           0 : static gfx::IntRect ContainerVisibleRect(ContainerT* aContainer)
     161             : {
     162           0 :   gfx::IntRect surfaceRect = aContainer->GetLocalVisibleRegion().ToUnknownRegion().GetBounds();
     163           0 :   return surfaceRect;
     164             : }
     165             : 
     166             : 
     167             : /* all of the per-layer prepared data we need to maintain */
     168           0 : struct PreparedLayer
     169             : {
     170           0 :   PreparedLayer(Layer *aLayer,
     171             :                 RenderTargetIntRect aClipRect,
     172             :                 Maybe<gfx::Polygon>&& aGeometry)
     173           0 :   : mLayer(aLayer), mClipRect(aClipRect), mGeometry(std::move(aGeometry)) {}
     174             : 
     175             :   RefPtr<Layer> mLayer;
     176             :   RenderTargetIntRect mClipRect;
     177             :   Maybe<Polygon> mGeometry;
     178             : };
     179             : 
     180             : /* all of the prepared data that we need in RenderLayer() */
     181           0 : struct PreparedData
     182             : {
     183             :   RefPtr<CompositingRenderTarget> mTmpTarget;
     184             :   AutoTArray<PreparedLayer, 12> mLayers;
     185             :   bool mNeedsSurfaceCopy;
     186             : };
     187             : 
     188             : // ContainerPrepare is shared between RefLayer and ContainerLayer
     189             : template<class ContainerT> void
     190           0 : ContainerPrepare(ContainerT* aContainer,
     191             :                  LayerManagerComposite* aManager,
     192             :                  const RenderTargetIntRect& aClipRect)
     193             : {
     194             :   // We can end up calling prepare multiple times if we duplicated
     195             :   // layers due to preserve-3d plane splitting. The results
     196             :   // should be identical, so we only need to do it once.
     197           0 :   if (aContainer->mPrepared) {
     198           0 :     return;
     199             :   }
     200           0 :   aContainer->mPrepared = MakeUnique<PreparedData>();
     201           0 :   aContainer->mPrepared->mNeedsSurfaceCopy = false;
     202             : 
     203             :   const ContainerLayerComposite::SortMode sortMode =
     204           0 :     aManager->GetCompositor()->SupportsLayerGeometry()
     205             :     ? ContainerLayerComposite::SortMode::WITH_GEOMETRY
     206           0 :     : ContainerLayerComposite::SortMode::WITHOUT_GEOMETRY;
     207             : 
     208             :   nsTArray<LayerPolygon> polygons =
     209           0 :     aContainer->SortChildrenBy3DZOrder(sortMode);
     210             : 
     211           0 :   for (LayerPolygon& layer : polygons) {
     212             :     LayerComposite* layerToRender =
     213           0 :       static_cast<LayerComposite*>(layer.layer->ImplData());
     214             : 
     215             :     RenderTargetIntRect clipRect =
     216           0 :       layerToRender->GetLayer()->CalculateScissorRect(aClipRect);
     217             : 
     218           0 :     if (layerToRender->GetLayer()->IsBackfaceHidden()) {
     219           0 :       continue;
     220             :     }
     221             : 
     222             :     // We don't want to skip container layers because otherwise their mPrepared
     223             :     // may be null which is not allowed.
     224           0 :     if (!layerToRender->GetLayer()->AsContainerLayer()) {
     225           0 :       if (!layerToRender->GetLayer()->IsVisible()) {
     226             :         CULLING_LOG("Sublayer %p has no effective visible region\n", layerToRender->GetLayer());
     227             :         continue;
     228             :       }
     229             : 
     230           0 :       if (clipRect.IsEmpty()) {
     231             :         CULLING_LOG("Sublayer %p has an empty world clip rect\n", layerToRender->GetLayer());
     232             :         continue;
     233             :       }
     234             :     }
     235             : 
     236             :     CULLING_LOG("Preparing sublayer %p\n", layerToRender->GetLayer());
     237             : 
     238           0 :     layerToRender->Prepare(clipRect);
     239           0 :     aContainer->mPrepared->mLayers.AppendElement(PreparedLayer(layerToRender->GetLayer(),
     240             :                                                                clipRect,
     241           0 :                                                                std::move(layer.geometry)));
     242             :   }
     243             : 
     244             :   CULLING_LOG("Preparing container layer %p\n", aContainer->GetLayer());
     245             : 
     246             :   /**
     247             :    * Setup our temporary surface for rendering the contents of this container.
     248             :    */
     249             : 
     250           0 :   gfx::IntRect surfaceRect = ContainerVisibleRect(aContainer);
     251           0 :   if (surfaceRect.IsEmpty()) {
     252             :     return;
     253             :   }
     254             : 
     255             :   bool surfaceCopyNeeded;
     256             :   // DefaultComputeSupportsComponentAlphaChildren can mutate aContainer so call it unconditionally
     257           0 :   aContainer->DefaultComputeSupportsComponentAlphaChildren(&surfaceCopyNeeded);
     258           0 :   if (aContainer->UseIntermediateSurface()) {
     259           0 :     if (!surfaceCopyNeeded) {
     260           0 :       RefPtr<CompositingRenderTarget> surface = nullptr;
     261             : 
     262           0 :       RefPtr<CompositingRenderTarget>& lastSurf = aContainer->mLastIntermediateSurface;
     263           0 :       if (lastSurf && !aContainer->mChildrenChanged && lastSurf->GetRect().IsEqualEdges(surfaceRect)) {
     264           0 :         surface = lastSurf;
     265             :       }
     266             : 
     267           0 :       if (!surface) {
     268             :         // If we don't need a copy we can render to the intermediate now to avoid
     269             :         // unecessary render target switching. This brings a big perf boost on mobile gpus.
     270           0 :         surface = CreateOrRecycleTarget(aContainer, aManager);
     271             : 
     272           0 :         MOZ_PERFORMANCE_WARNING("gfx", "[%p] Container layer requires intermediate surface rendering\n", aContainer);
     273           0 :         RenderIntermediate(aContainer, aManager, aClipRect.ToUnknownRect(), surface);
     274           0 :         aContainer->SetChildrenChanged(false);
     275             :       }
     276             : 
     277           0 :       aContainer->mPrepared->mTmpTarget = surface;
     278             :     } else {
     279           0 :       MOZ_PERFORMANCE_WARNING("gfx", "[%p] Container layer requires intermediate surface copy\n", aContainer);
     280           0 :       aContainer->mPrepared->mNeedsSurfaceCopy = true;
     281           0 :       aContainer->mLastIntermediateSurface = nullptr;
     282             :     }
     283             :   } else {
     284           0 :     aContainer->mLastIntermediateSurface = nullptr;
     285             :   }
     286             : }
     287             : 
     288             : template<class ContainerT> void
     289           0 : RenderMinimap(ContainerT* aContainer,
     290             :               const RefPtr<APZSampler>& aSampler,
     291             :               LayerManagerComposite* aManager,
     292             :               const RenderTargetIntRect& aClipRect, Layer* aLayer)
     293             : {
     294           0 :   Compositor* compositor = aManager->GetCompositor();
     295           0 :   MOZ_ASSERT(aSampler);
     296             : 
     297           0 :   if (aLayer->GetScrollMetadataCount() < 1) {
     298           0 :     return;
     299             :   }
     300             : 
     301           0 :   LayerMetricsWrapper wrapper(aLayer, 0);
     302           0 :   if (!wrapper.GetApzc()) {
     303             :     return;
     304             :   }
     305           0 :   const FrameMetrics& fm = wrapper.Metrics();
     306           0 :   MOZ_ASSERT(fm.IsScrollable());
     307             : 
     308           0 :   ParentLayerPoint scrollOffset = aSampler->GetCurrentAsyncScrollOffset(wrapper);
     309             : 
     310             :   // Options
     311           0 :   const int verticalPadding = 10;
     312           0 :   const int horizontalPadding = 5;
     313           0 :   gfx::Color backgroundColor(0.3f, 0.3f, 0.3f, 0.3f);
     314           0 :   gfx::Color tileActiveColor(1, 1, 1, 0.4f);
     315           0 :   gfx::Color tileBorderColor(0, 0, 0, 0.1f);
     316           0 :   gfx::Color pageBorderColor(0, 0, 0);
     317           0 :   gfx::Color criticalDisplayPortColor(1.f, 1.f, 0);
     318           0 :   gfx::Color displayPortColor(0, 1.f, 0);
     319           0 :   gfx::Color layoutPortColor(1.f, 0, 0);
     320           0 :   gfx::Color visualPortColor(0, 0, 1.f, 0.3f);
     321             : 
     322             :   // Rects
     323           0 :   ParentLayerRect compositionBounds = fm.GetCompositionBounds();
     324           0 :   LayerRect scrollRect = fm.GetScrollableRect() * fm.LayersPixelsPerCSSPixel();
     325           0 :   LayerRect visualRect = ParentLayerRect(scrollOffset, compositionBounds.Size()) / LayerToParentLayerScale(1);
     326           0 :   LayerRect dp = (fm.GetDisplayPort() + fm.GetScrollOffset()) * fm.LayersPixelsPerCSSPixel();
     327           0 :   Maybe<LayerRect> layoutRect;
     328           0 :   Maybe<LayerRect> cdp;
     329           0 :   if (fm.IsRootContent()) {
     330           0 :     CSSRect viewport = aSampler->GetCurrentAsyncLayoutViewport(wrapper);
     331           0 :     layoutRect = Some(viewport * fm.LayersPixelsPerCSSPixel());
     332             :   }
     333           0 :   if (!fm.GetCriticalDisplayPort().IsEmpty()) {
     334           0 :     cdp = Some((fm.GetCriticalDisplayPort() + fm.GetScrollOffset()) * fm.LayersPixelsPerCSSPixel());
     335             :   }
     336             : 
     337             :   // Don't render trivial minimap. They can show up from textboxes and other tiny frames.
     338           0 :   if (visualRect.Width() < 64 && visualRect.Height() < 64) {
     339           0 :     return;
     340             :   }
     341             : 
     342             :   // Compute a scale with an appropriate aspect ratio
     343             :   // We allocate up to 100px of width and the height of this layer.
     344             :   float scaleFactor;
     345             :   float scaleFactorX;
     346             :   float scaleFactorY;
     347           0 :   Rect dest = Rect(aClipRect.ToUnknownRect());
     348           0 :   if (aLayer->GetLocalClipRect()) {
     349           0 :     dest = Rect(aLayer->GetLocalClipRect().value().ToUnknownRect());
     350             :   } else {
     351           0 :     dest = aContainer->GetEffectiveTransform().Inverse().TransformBounds(dest);
     352             :   }
     353           0 :   dest = dest.Intersect(compositionBounds.ToUnknownRect());
     354           0 :   scaleFactorX = std::min(100.f, dest.Width() - (2 * horizontalPadding)) / scrollRect.Width();
     355           0 :   scaleFactorY = (dest.Height() - (2 * verticalPadding)) / scrollRect.Height();
     356           0 :   scaleFactor = std::min(scaleFactorX, scaleFactorY);
     357           0 :   if (scaleFactor <= 0) {
     358             :     return;
     359             :   }
     360             : 
     361           0 :   Matrix4x4 transform = Matrix4x4::Scaling(scaleFactor, scaleFactor, 1);
     362           0 :   transform.PostTranslate(horizontalPadding + dest.X(), verticalPadding + dest.Y(), 0);
     363             : 
     364           0 :   Rect transformedScrollRect = transform.TransformBounds(scrollRect.ToUnknownRect());
     365             : 
     366           0 :   IntRect clipRect = RoundedOut(aContainer->GetEffectiveTransform().TransformBounds(transformedScrollRect));
     367             : 
     368             :   // Render the scrollable area.
     369           0 :   compositor->FillRect(transformedScrollRect, backgroundColor, clipRect, aContainer->GetEffectiveTransform());
     370           0 :   compositor->SlowDrawRect(transformedScrollRect, pageBorderColor, clipRect, aContainer->GetEffectiveTransform());
     371             : 
     372             :   // Render the displayport.
     373           0 :   Rect r = transform.TransformBounds(dp.ToUnknownRect());
     374           0 :   compositor->FillRect(r, tileActiveColor, clipRect, aContainer->GetEffectiveTransform());
     375           0 :   compositor->SlowDrawRect(r, displayPortColor, clipRect, aContainer->GetEffectiveTransform());
     376             : 
     377             :   // Render the critical displayport if there is one
     378           0 :   if (cdp) {
     379           0 :     r = transform.TransformBounds(cdp->ToUnknownRect());
     380           0 :     compositor->SlowDrawRect(r, criticalDisplayPortColor, clipRect, aContainer->GetEffectiveTransform());
     381             :   }
     382             : 
     383             :   // Render the layout viewport if it exists (which is only in the root
     384             :   // content APZC).
     385           0 :   if (layoutRect) {
     386           0 :     r = transform.TransformBounds(layoutRect->ToUnknownRect());
     387           0 :     compositor->SlowDrawRect(r, layoutPortColor, clipRect, aContainer->GetEffectiveTransform());
     388             :   }
     389             : 
     390             :   // Render the visual viewport.
     391           0 :   r = transform.TransformBounds(visualRect.ToUnknownRect());
     392           0 :   compositor->SlowDrawRect(r, visualPortColor, clipRect, aContainer->GetEffectiveTransform(), 2);
     393             : }
     394             : 
     395             : template<class ContainerT> void
     396           0 : RenderLayers(ContainerT* aContainer, LayerManagerComposite* aManager,
     397             :              const RenderTargetIntRect& aClipRect,
     398             :              const Maybe<gfx::Polygon>& aGeometry)
     399             : {
     400           0 :   Compositor* compositor = aManager->GetCompositor();
     401             : 
     402           0 :   RefPtr<APZSampler> sampler;
     403           0 :   if (CompositorBridgeParent* cbp = compositor->GetCompositorBridgeParent()) {
     404           0 :     sampler = cbp->GetAPZSampler();
     405             :   }
     406             : 
     407           0 :   for (size_t i = 0u; i < aContainer->mPrepared->mLayers.Length(); i++) {
     408           0 :     PreparedLayer& preparedData = aContainer->mPrepared->mLayers[i];
     409             : 
     410           0 :     const gfx::IntRect clipRect = preparedData.mClipRect.ToUnknownRect();
     411           0 :     LayerComposite* layerToRender = static_cast<LayerComposite*>(preparedData.mLayer->ImplData());
     412           0 :     const Maybe<gfx::Polygon>& childGeometry = preparedData.mGeometry;
     413             : 
     414           0 :     Layer* layer = layerToRender->GetLayer();
     415             : 
     416           0 :     if (layerToRender->HasStaleCompositor()) {
     417           0 :       continue;
     418             :     }
     419             : 
     420           0 :     if (gfxPrefs::LayersDrawFPS()) {
     421           0 :       for (const auto& metadata : layer->GetAllScrollMetadata()) {
     422           0 :         if (metadata.IsApzForceDisabled()) {
     423           0 :           aManager->DisabledApzWarning();
     424             :           break;
     425             :         }
     426             :       }
     427             :     }
     428             : 
     429           0 :     if (layerToRender->HasLayerBeenComposited()) {
     430             :       // Composer2D will compose this layer so skip GPU composition
     431             :       // this time. The flag will be reset for the next composition phase
     432             :       // at the beginning of LayerManagerComposite::Rener().
     433           0 :       gfx::IntRect clearRect = layerToRender->GetClearRect();
     434           0 :       if (!clearRect.IsEmpty()) {
     435             :         // Clear layer's visible rect on FrameBuffer with transparent pixels
     436           0 :         gfx::Rect fbRect(clearRect.X(), clearRect.Y(), clearRect.Width(), clearRect.Height());
     437           0 :         compositor->ClearRect(fbRect);
     438           0 :         layerToRender->SetClearRect(gfx::IntRect(0, 0, 0, 0));
     439             :       }
     440             :     } else {
     441             :       // Since we force an intermediate surface for nested 3D contexts,
     442             :       // aGeometry and childGeometry are both in the same coordinate space.
     443             :       Maybe<gfx::Polygon> geometry =
     444           0 :         SelectLayerGeometry(aGeometry, childGeometry);
     445             : 
     446             :       // If we are dealing with a nested 3D context, we might need to transform
     447             :       // the geometry back to the coordinate space of the current layer before
     448             :       // rendering the layer.
     449           0 :       ContainerLayer* container = layer->AsContainerLayer();
     450           0 :       const bool isLeafLayer = !container || container->UseIntermediateSurface();
     451             : 
     452           0 :       if (geometry && isLeafLayer) {
     453           0 :         TransformLayerGeometry(layer, geometry);
     454             :       }
     455             : 
     456           0 :       layerToRender->RenderLayer(clipRect, geometry);
     457             :     }
     458             : 
     459           0 :     if (gfxPrefs::UniformityInfo()) {
     460           0 :       PrintUniformityInfo(layer);
     461             :     }
     462             : 
     463           0 :     if (gfxPrefs::DrawLayerInfo()) {
     464           0 :       DrawLayerInfo(preparedData.mClipRect, aManager, layer);
     465             :     }
     466             : 
     467             :     // Draw a border around scrollable layers.
     468             :     // A layer can be scrolled by multiple scroll frames. Draw a border
     469             :     // for each.
     470             :     // Within the list of scroll frames for a layer, the layer border for a
     471             :     // scroll frame lower down is affected by the async transforms on scroll
     472             :     // frames higher up, so loop from the top down, and accumulate an async
     473             :     // transform as we go along.
     474           0 :     Matrix4x4 asyncTransform;
     475           0 :     if (sampler) {
     476           0 :       for (uint32_t i = layer->GetScrollMetadataCount(); i > 0; --i) {
     477           0 :         LayerMetricsWrapper wrapper(layer, i - 1);
     478           0 :         if (wrapper.GetApzc()) {
     479           0 :           MOZ_ASSERT(wrapper.Metrics().IsScrollable());
     480             :           // Since the composition bounds are in the parent layer's coordinates,
     481             :           // use the parent's effective transform rather than the layer's own.
     482           0 :           ParentLayerRect compositionBounds = wrapper.Metrics().GetCompositionBounds();
     483           0 :           aManager->GetCompositor()->DrawDiagnostics(DiagnosticFlags::CONTAINER,
     484           0 :                                                      compositionBounds.ToUnknownRect(),
     485           0 :                                                      aClipRect.ToUnknownRect(),
     486           0 :                                                      asyncTransform * aContainer->GetEffectiveTransform());
     487           0 :           asyncTransform =
     488             :               sampler->GetCurrentAsyncTransformWithOverscroll(wrapper).ToUnknownMatrix()
     489             :               * asyncTransform;
     490             :         }
     491             :       }
     492             : 
     493           0 :       if (gfxPrefs::APZMinimap()) {
     494           0 :         RenderMinimap(aContainer, sampler, aManager, aClipRect, layer);
     495             :       }
     496             :     }
     497             : 
     498             :     // invariant: our GL context should be current here, I don't think we can
     499             :     // assert it though
     500             :   }
     501           0 : }
     502             : 
     503             : template<class ContainerT> RefPtr<CompositingRenderTarget>
     504           0 : CreateOrRecycleTarget(ContainerT* aContainer,
     505             :                       LayerManagerComposite* aManager)
     506             : {
     507           0 :   Compositor* compositor = aManager->GetCompositor();
     508           0 :   SurfaceInitMode mode = INIT_MODE_CLEAR;
     509           0 :   gfx::IntRect surfaceRect = ContainerVisibleRect(aContainer);
     510           0 :   if (aContainer->GetLocalVisibleRegion().GetNumRects() == 1 &&
     511           0 :       (aContainer->GetContentFlags() & Layer::CONTENT_OPAQUE))
     512             :   {
     513           0 :     mode = INIT_MODE_NONE;
     514             :   }
     515             : 
     516           0 :   RefPtr<CompositingRenderTarget>& lastSurf = aContainer->mLastIntermediateSurface;
     517           0 :   if (lastSurf && lastSurf->GetRect().IsEqualEdges(surfaceRect)) {
     518           0 :     if (mode == INIT_MODE_CLEAR) {
     519           0 :       lastSurf->ClearOnBind();
     520             :     }
     521             : 
     522           0 :     return lastSurf;
     523             :   } else {
     524           0 :     lastSurf = compositor->CreateRenderTarget(surfaceRect, mode);
     525             : 
     526           0 :     return lastSurf;
     527             :   }
     528             : }
     529             : 
     530             : template<class ContainerT> RefPtr<CompositingRenderTarget>
     531           0 : CreateTemporaryTargetAndCopyFromBackground(ContainerT* aContainer,
     532             :                                            LayerManagerComposite* aManager)
     533             : {
     534           0 :   Compositor* compositor = aManager->GetCompositor();
     535           0 :   gfx::IntRect visibleRect = aContainer->GetLocalVisibleRegion().ToUnknownRegion().GetBounds();
     536           0 :   RefPtr<CompositingRenderTarget> previousTarget = compositor->GetCurrentRenderTarget();
     537             :   gfx::IntRect surfaceRect = gfx::IntRect(visibleRect.X(), visibleRect.Y(),
     538           0 :                                           visibleRect.Width(), visibleRect.Height());
     539             : 
     540           0 :   gfx::IntPoint sourcePoint = gfx::IntPoint(visibleRect.X(), visibleRect.Y());
     541             : 
     542           0 :   gfx::Matrix4x4 transform = aContainer->GetEffectiveTransform();
     543           0 :   DebugOnly<gfx::Matrix> transform2d;
     544           0 :   MOZ_ASSERT(transform.Is2D(&transform2d) && !gfx::ThebesMatrix(transform2d).HasNonIntegerTranslation());
     545           0 :   sourcePoint += gfx::IntPoint::Truncate(transform._41, transform._42);
     546             : 
     547           0 :   sourcePoint -= compositor->GetCurrentRenderTarget()->GetOrigin();
     548             : 
     549           0 :   return compositor->CreateRenderTargetFromSource(surfaceRect, previousTarget, sourcePoint);
     550             : }
     551             : 
     552             : template<class ContainerT> void
     553           0 : RenderIntermediate(ContainerT* aContainer,
     554             :                    LayerManagerComposite* aManager,
     555             :                    const gfx::IntRect& aClipRect,
     556             :                    RefPtr<CompositingRenderTarget> surface)
     557             : {
     558           0 :   Compositor* compositor = aManager->GetCompositor();
     559           0 :   RefPtr<CompositingRenderTarget> previousTarget = compositor->GetCurrentRenderTarget();
     560             : 
     561           0 :   if (!surface) {
     562           0 :     return;
     563             :   }
     564             : 
     565           0 :   compositor->SetRenderTarget(surface);
     566             :   // pre-render all of the layers into our temporary
     567           0 :   RenderLayers(aContainer, aManager,
     568           0 :                RenderTargetIntRect::FromUnknownRect(aClipRect),
     569             :                Nothing());
     570             : 
     571             :   // Unbind the current surface and rebind the previous one.
     572           0 :   compositor->SetRenderTarget(previousTarget);
     573             : }
     574             : 
     575             : template<class ContainerT> void
     576           0 : ContainerRender(ContainerT* aContainer,
     577             :                  LayerManagerComposite* aManager,
     578             :                  const gfx::IntRect& aClipRect,
     579             :                  const Maybe<gfx::Polygon>& aGeometry)
     580             : {
     581           0 :   MOZ_ASSERT(aContainer->mPrepared);
     582             : 
     583           0 :   if (aContainer->UseIntermediateSurface()) {
     584           0 :     RefPtr<CompositingRenderTarget> surface;
     585             : 
     586           0 :     if (aContainer->mPrepared->mNeedsSurfaceCopy) {
     587             :       // we needed to copy the background so we waited until now to render the intermediate
     588           0 :       surface = CreateTemporaryTargetAndCopyFromBackground(aContainer, aManager);
     589           0 :       RenderIntermediate(aContainer, aManager,
     590             :                          aClipRect, surface);
     591             :     } else {
     592           0 :       surface = aContainer->mPrepared->mTmpTarget;
     593             :     }
     594             : 
     595           0 :     if (!surface) {
     596           0 :       return;
     597             :     }
     598             : 
     599           0 :     gfx::Rect visibleRect(aContainer->GetLocalVisibleRegion().ToUnknownRegion().GetBounds());
     600             : 
     601           0 :     RefPtr<Compositor> compositor = aManager->GetCompositor();
     602             : #ifdef MOZ_DUMP_PAINTING
     603           0 :     if (gfxEnv::DumpCompositorTextures()) {
     604           0 :       RefPtr<gfx::DataSourceSurface> surf = surface->Dump(compositor);
     605           0 :       if (surf) {
     606           0 :         WriteSnapshotToDumpFile(aContainer, surf);
     607             :       }
     608             :     }
     609             : #endif
     610             : 
     611           0 :     RefPtr<ContainerT> container = aContainer;
     612           0 :     RenderWithAllMasks(aContainer, compositor, aClipRect,
     613           0 :                        [&, surface, compositor, container](EffectChain& effectChain, const IntRect& clipRect) {
     614           0 :       effectChain.mPrimaryEffect = new EffectRenderTarget(surface);
     615             : 
     616           0 :       compositor->DrawGeometry(visibleRect, clipRect, effectChain,
     617           0 :                                container->GetEffectiveOpacity(),
     618           0 :                                container->GetEffectiveTransform(), aGeometry);
     619           0 :     });
     620             : 
     621             :   } else {
     622           0 :     RenderLayers(aContainer, aManager,
     623           0 :                  RenderTargetIntRect::FromUnknownRect(aClipRect),
     624             :                  aGeometry);
     625             :   }
     626             : 
     627             :   // If it is a scrollable container layer with no child layers, and one of the APZCs
     628             :   // attached to it has a nonempty async transform, then that transform is not applied
     629             :   // to any visible content. Display a warning box (conditioned on the FPS display being
     630             :   // enabled).
     631           0 :   if (gfxPrefs::LayersDrawFPS() && aContainer->IsScrollableWithoutContent()) {
     632           0 :     RefPtr<APZSampler> sampler = aManager->GetCompositor()->GetCompositorBridgeParent()->GetAPZSampler();
     633             :     // Since aContainer doesn't have any children we can just iterate from the top metrics
     634             :     // on it down to the bottom using GetFirstChild and not worry about walking onto another
     635             :     // underlying layer.
     636           0 :     for (LayerMetricsWrapper i(aContainer); i; i = i.GetFirstChild()) {
     637           0 :       if (sampler->HasUnusedAsyncTransform(i)) {
     638           0 :         aManager->UnusedApzTransformWarning();
     639             :         break;
     640             :       }
     641             :     }
     642             :   }
     643             : }
     644             : 
     645           2 : ContainerLayerComposite::ContainerLayerComposite(LayerManagerComposite *aManager)
     646             :   : ContainerLayer(aManager, nullptr)
     647           6 :   , LayerComposite(aManager)
     648             : {
     649           2 :   MOZ_COUNT_CTOR(ContainerLayerComposite);
     650           2 :   mImplData = static_cast<LayerComposite*>(this);
     651           2 : }
     652             : 
     653           0 : ContainerLayerComposite::~ContainerLayerComposite()
     654             : {
     655           0 :   MOZ_COUNT_DTOR(ContainerLayerComposite);
     656             : 
     657             :   // We don't Destroy() on destruction here because this destructor
     658             :   // can be called after remote content has crashed, and it may not be
     659             :   // safe to free the IPC resources of our children.  Those resources
     660             :   // are automatically cleaned up by IPDL-generated code.
     661             :   //
     662             :   // In the common case of normal shutdown, either
     663             :   // LayerManagerComposite::Destroy(), a parent
     664             :   // *ContainerLayerComposite::Destroy(), or Disconnect() will trigger
     665             :   // cleanup of our resources.
     666           0 :   RemoveAllChildren();
     667           0 : }
     668             : 
     669             : void
     670           0 : ContainerLayerComposite::Destroy()
     671             : {
     672           0 :   if (!mDestroyed) {
     673           0 :     while (mFirstChild) {
     674           0 :       GetFirstChildComposite()->Destroy();
     675           0 :       RemoveChild(mFirstChild);
     676             :     }
     677           0 :     mDestroyed = true;
     678             :   }
     679           0 : }
     680             : 
     681             : LayerComposite*
     682           0 : ContainerLayerComposite::GetFirstChildComposite()
     683             : {
     684           0 :   if (!mFirstChild) {
     685             :     return nullptr;
     686             :    }
     687           0 :   return static_cast<LayerComposite*>(mFirstChild->AsHostLayer());
     688             : }
     689             : 
     690             : void
     691           0 : ContainerLayerComposite::Cleanup()
     692             : {
     693           0 :   mPrepared = nullptr;
     694             : 
     695           0 :   for (Layer* l = GetFirstChild(); l; l = l->GetNextSibling()) {
     696           0 :     static_cast<LayerComposite*>(l->AsHostLayer())->Cleanup();
     697             :   }
     698           0 : }
     699             : 
     700             : void
     701           0 : ContainerLayerComposite::RenderLayer(const gfx::IntRect& aClipRect,
     702             :                                      const Maybe<gfx::Polygon>& aGeometry)
     703             : {
     704           0 :   ContainerRender(this, mCompositeManager, aClipRect, aGeometry);
     705           0 : }
     706             : 
     707             : void
     708           0 : ContainerLayerComposite::Prepare(const RenderTargetIntRect& aClipRect)
     709             : {
     710           0 :   ContainerPrepare(this, mCompositeManager, aClipRect);
     711           0 : }
     712             : 
     713             : void
     714           0 : ContainerLayerComposite::CleanupResources()
     715             : {
     716           0 :   mLastIntermediateSurface = nullptr;
     717           0 :   mPrepared = nullptr;
     718             : 
     719           0 :   for (Layer* l = GetFirstChild(); l; l = l->GetNextSibling()) {
     720           0 :     static_cast<LayerComposite*>(l->AsHostLayer())->CleanupResources();
     721             :   }
     722           0 : }
     723             : 
     724             : const LayerIntRegion&
     725           8 : ContainerLayerComposite::GetShadowVisibleRegion()
     726             : {
     727           0 :   if (!UseIntermediateSurface()) {
     728           8 :     RecomputeShadowVisibleRegionFromChildren();
     729             :   }
     730             : 
     731           8 :   return mShadowVisibleRegion;
     732             : }
     733             : 
     734             : const LayerIntRegion&
     735           0 : RefLayerComposite::GetShadowVisibleRegion()
     736             : {
     737           0 :   if (!UseIntermediateSurface()) {
     738           0 :     RecomputeShadowVisibleRegionFromChildren();
     739             :   }
     740             : 
     741           0 :   return mShadowVisibleRegion;
     742             : }
     743             : 
     744           0 : RefLayerComposite::RefLayerComposite(LayerManagerComposite* aManager)
     745             :   : RefLayer(aManager, nullptr)
     746           0 :   , LayerComposite(aManager)
     747             : {
     748           0 :   mImplData = static_cast<LayerComposite*>(this);
     749           0 : }
     750             : 
     751           0 : RefLayerComposite::~RefLayerComposite()
     752             : {
     753           0 :   Destroy();
     754           0 : }
     755             : 
     756             : void
     757           0 : RefLayerComposite::Destroy()
     758             : {
     759           0 :   MOZ_ASSERT(!mFirstChild);
     760           0 :   mDestroyed = true;
     761           0 : }
     762             : 
     763             : LayerComposite*
     764           0 : RefLayerComposite::GetFirstChildComposite()
     765             : {
     766           0 :   if (!mFirstChild) {
     767             :     return nullptr;
     768             :    }
     769           0 :   return static_cast<LayerComposite*>(mFirstChild->AsHostLayer());
     770             : }
     771             : 
     772             : void
     773           0 : RefLayerComposite::RenderLayer(const gfx::IntRect& aClipRect,
     774             :                                const Maybe<gfx::Polygon>& aGeometry)
     775             : {
     776           0 :   ContainerRender(this, mCompositeManager, aClipRect, aGeometry);
     777           0 : }
     778             : 
     779             : void
     780           0 : RefLayerComposite::Prepare(const RenderTargetIntRect& aClipRect)
     781             : {
     782           0 :   ContainerPrepare(this, mCompositeManager, aClipRect);
     783           0 : }
     784             : 
     785             : void
     786           0 : RefLayerComposite::Cleanup()
     787             : {
     788           0 :   mPrepared = nullptr;
     789             : 
     790             :   for (Layer* l = GetFirstChild(); l; l = l->GetNextSibling()) {
     791             :     static_cast<LayerComposite*>(l->AsHostLayer())->Cleanup();
     792             :   }
     793             : }
     794             : 
     795             : void
     796             : RefLayerComposite::CleanupResources()
     797             : {
     798             :   mLastIntermediateSurface = nullptr;
     799             :   mPrepared = nullptr;
     800             : }
     801             : 
     802             : } // namespace layers
     803             : } // namespace mozilla

Generated by: LCOV version 1.13-14-ga5dd952