LCOV - code coverage report
Current view: top level - gfx/layers - Layers.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 398 1283 31.0 %
Date: 2017-07-14 16:53:18 Functions: 65 153 42.5 %
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: sw=2 ts=8 et :
       3             :  */
       4             : /* This Source Code Form is subject to the terms of the Mozilla Public
       5             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       6             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       7             : 
       8             : #include "Layers.h"
       9             : #include <algorithm>                    // for max, min
      10             : #include "apz/src/AsyncPanZoomController.h"
      11             : #include "CompositableHost.h"           // for CompositableHost
      12             : #include "ImageContainer.h"             // for ImageContainer, etc
      13             : #include "ImageLayers.h"                // for ImageLayer
      14             : #include "LayerSorter.h"                // for SortLayersBy3DZOrder
      15             : #include "LayersLogging.h"              // for AppendToString
      16             : #include "LayerUserData.h"
      17             : #include "ReadbackLayer.h"              // for ReadbackLayer
      18             : #include "UnitTransforms.h"             // for ViewAs
      19             : #include "gfxEnv.h"
      20             : #include "gfxPlatform.h"                // for gfxPlatform
      21             : #include "gfxPrefs.h"
      22             : #include "gfxUtils.h"                   // for gfxUtils, etc
      23             : #include "gfx2DGlue.h"
      24             : #include "mozilla/DebugOnly.h"          // for DebugOnly
      25             : #include "mozilla/IntegerPrintfMacros.h"
      26             : #include "mozilla/Telemetry.h"          // for Accumulate
      27             : #include "mozilla/ToString.h"
      28             : #include "mozilla/gfx/2D.h"             // for DrawTarget
      29             : #include "mozilla/gfx/BaseSize.h"       // for BaseSize
      30             : #include "mozilla/gfx/Matrix.h"         // for Matrix4x4
      31             : #include "mozilla/gfx/Polygon.h"        // for Polygon
      32             : #include "mozilla/layers/AnimationHelper.h"
      33             : #include "mozilla/layers/AsyncCanvasRenderer.h"
      34             : #include "mozilla/layers/BSPTree.h"     // for BSPTree
      35             : #include "mozilla/layers/CompositableClient.h"  // for CompositableClient
      36             : #include "mozilla/layers/Compositor.h"  // for Compositor
      37             : #include "mozilla/layers/CompositorTypes.h"
      38             : #include "mozilla/layers/LayerManagerComposite.h"  // for LayerComposite
      39             : #include "mozilla/layers/LayerMetricsWrapper.h" // for LayerMetricsWrapper
      40             : #include "mozilla/layers/LayersMessages.h"  // for TransformFunction, etc
      41             : #include "mozilla/layers/LayersTypes.h"  // for TextureDumpMode
      42             : #include "mozilla/layers/PersistentBufferProvider.h"
      43             : #include "mozilla/layers/ShadowLayers.h"  // for ShadowableLayer
      44             : #include "nsAString.h"
      45             : #include "nsCSSValue.h"                 // for nsCSSValue::Array, etc
      46             : #include "nsDisplayList.h"              // for nsDisplayItem
      47             : #include "nsPrintfCString.h"            // for nsPrintfCString
      48             : #include "nsStyleStruct.h"              // for nsTimingFunction, etc
      49             : #include "protobuf/LayerScopePacket.pb.h"
      50             : #include "mozilla/Compression.h"
      51             : #include "TreeTraversal.h"              // for ForEachNode
      52             : 
      53             : #include <list>
      54             : #include <set>
      55             : 
      56             : uint8_t gLayerManagerLayerBuilder;
      57             : 
      58             : namespace mozilla {
      59             : namespace layers {
      60             : 
      61             : FILE*
      62           0 : FILEOrDefault(FILE* aFile)
      63             : {
      64           0 :   return aFile ? aFile : stderr;
      65             : }
      66             : 
      67             : typedef FrameMetrics::ViewID ViewID;
      68             : 
      69             : using namespace mozilla::gfx;
      70             : using namespace mozilla::Compression;
      71             : 
      72             : //--------------------------------------------------
      73             : // LayerManager
      74             : 
      75             : /* static */ mozilla::LogModule*
      76        1845 : LayerManager::GetLog()
      77             : {
      78             :   static LazyLogModule sLog("Layers");
      79        1845 :   return sLog;
      80             : }
      81             : 
      82             : FrameMetrics::ViewID
      83           0 : LayerManager::GetRootScrollableLayerId()
      84             : {
      85           0 :   if (!mRoot) {
      86           0 :     return FrameMetrics::NULL_SCROLL_ID;
      87             :   }
      88             : 
      89           0 :   LayerMetricsWrapper layerMetricsRoot = LayerMetricsWrapper(mRoot);
      90             : 
      91             :   LayerMetricsWrapper rootScrollableLayerMetrics =
      92             :       BreadthFirstSearch<ForwardIterator>(
      93             :           layerMetricsRoot,
      94           0 :           [](LayerMetricsWrapper aLayerMetrics)
      95             :           {
      96           0 :             return aLayerMetrics.Metrics().IsScrollable();
      97           0 :           }
      98           0 :       );
      99             : 
     100           0 :   return rootScrollableLayerMetrics.IsValid() ?
     101           0 :       rootScrollableLayerMetrics.Metrics().GetScrollId() :
     102           0 :       FrameMetrics::NULL_SCROLL_ID;
     103             : }
     104             : 
     105             : LayerMetricsWrapper
     106           0 : LayerManager::GetRootContentLayer()
     107             : {
     108           0 :   if (!mRoot) {
     109           0 :     return LayerMetricsWrapper();
     110             :   }
     111             : 
     112           0 :   LayerMetricsWrapper root(mRoot);
     113             : 
     114             :   return BreadthFirstSearch<ForwardIterator>(root,
     115           0 :       [](LayerMetricsWrapper aLayerMetrics)
     116             :       {
     117           0 :         return aLayerMetrics.Metrics().IsRootContent();
     118           0 :       }
     119           0 :   );
     120             : }
     121             : 
     122             : already_AddRefed<DrawTarget>
     123           0 : LayerManager::CreateOptimalDrawTarget(const gfx::IntSize &aSize,
     124             :                                       SurfaceFormat aFormat)
     125             : {
     126             :   return gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(aSize,
     127           0 :                                                                       aFormat);
     128             : }
     129             : 
     130             : already_AddRefed<DrawTarget>
     131           0 : LayerManager::CreateOptimalMaskDrawTarget(const gfx::IntSize &aSize)
     132             : {
     133           0 :   return CreateOptimalDrawTarget(aSize, SurfaceFormat::A8);
     134             : }
     135             : 
     136             : already_AddRefed<DrawTarget>
     137           0 : LayerManager::CreateDrawTarget(const IntSize &aSize,
     138             :                                SurfaceFormat aFormat)
     139             : {
     140             :   return gfxPlatform::GetPlatform()->
     141           0 :     CreateOffscreenCanvasDrawTarget(aSize, aFormat);
     142             : }
     143             : 
     144             : already_AddRefed<PersistentBufferProvider>
     145           0 : LayerManager::CreatePersistentBufferProvider(const mozilla::gfx::IntSize &aSize,
     146             :                                              mozilla::gfx::SurfaceFormat aFormat)
     147             : {
     148             :   RefPtr<PersistentBufferProviderBasic> bufferProvider =
     149           0 :     PersistentBufferProviderBasic::Create(aSize, aFormat,
     150           0 :       gfxPlatform::GetPlatform()->GetPreferredCanvasBackend());
     151             : 
     152           0 :   if (!bufferProvider) {
     153           0 :     bufferProvider = PersistentBufferProviderBasic::Create(aSize, aFormat,
     154           0 :       gfxPlatform::GetPlatform()->GetFallbackCanvasBackend());
     155             :   }
     156             : 
     157           0 :   return bufferProvider.forget();
     158             : }
     159             : 
     160             : already_AddRefed<ImageContainer>
     161           0 : LayerManager::CreateImageContainer(ImageContainer::Mode flag)
     162             : {
     163           0 :   RefPtr<ImageContainer> container = new ImageContainer(flag);
     164           0 :   return container.forget();
     165             : }
     166             : 
     167             : bool
     168           0 : LayerManager::AreComponentAlphaLayersEnabled()
     169             : {
     170           0 :   return gfxPrefs::ComponentAlphaEnabled();
     171             : }
     172             : 
     173             : /*static*/ void
     174         737 : LayerManager::LayerUserDataDestroy(void* data)
     175             : {
     176         737 :   delete static_cast<LayerUserData*>(data);
     177         737 : }
     178             : 
     179             : UniquePtr<LayerUserData>
     180           0 : LayerManager::RemoveUserData(void* aKey)
     181             : {
     182           0 :   UniquePtr<LayerUserData> d(static_cast<LayerUserData*>(mUserData.Remove(static_cast<gfx::UserDataKey*>(aKey))));
     183           0 :   return d;
     184             : }
     185             : 
     186             : //--------------------------------------------------
     187             : // Layer
     188             : 
     189         239 : Layer::Layer(LayerManager* aManager, void* aImplData) :
     190             :   mManager(aManager),
     191             :   mParent(nullptr),
     192             :   mNextSibling(nullptr),
     193             :   mPrevSibling(nullptr),
     194             :   mImplData(aImplData),
     195             :   mCompositorAnimationsId(0),
     196             :   mUseTileSourceRect(false),
     197             : #ifdef DEBUG
     198             :   mDebugColorIndex(0),
     199             : #endif
     200         239 :   mAnimationGeneration(0)
     201             : {
     202         239 : }
     203             : 
     204         211 : Layer::~Layer()
     205             : {
     206         211 : }
     207             : 
     208             : void
     209           0 : Layer::EnsureAnimationsId()
     210             : {
     211           0 :   if (!mCompositorAnimationsId) {
     212           0 :     mCompositorAnimationsId = AnimationHelper::GetNextCompositorAnimationsId();
     213             :   }
     214           0 : }
     215             : 
     216             : Animation*
     217           0 : Layer::AddAnimation()
     218             : {
     219             :   // Here generates a new id when the first animation is added and
     220             :   // this id is used to represent the animations in this layer.
     221           0 :   EnsureAnimationsId();
     222             : 
     223           0 :   MOZ_LAYERS_LOG_IF_SHADOWABLE(
     224             :     this, ("Layer::Mutated(%p) AddAnimation with id=%" PRIu64, this, mCompositorAnimationsId));
     225             : 
     226           0 :   MOZ_ASSERT(!mPendingAnimations, "should have called ClearAnimations first");
     227             : 
     228           0 :   Animation* anim = mAnimations.AppendElement();
     229             : 
     230           0 :   Mutated();
     231           0 :   return anim;
     232             : }
     233             : 
     234             : void
     235           0 : Layer::ClearAnimations()
     236             : {
     237           0 :   mPendingAnimations = nullptr;
     238             : 
     239           0 :   if (mAnimations.IsEmpty() && mAnimationData.IsEmpty()) {
     240           0 :     return;
     241             :   }
     242             : 
     243           0 :   MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) ClearAnimations", this));
     244           0 :   mAnimations.Clear();
     245           0 :   mAnimationData.Clear();
     246           0 :   Mutated();
     247             : }
     248             : 
     249             : Animation*
     250           0 : Layer::AddAnimationForNextTransaction()
     251             : {
     252           0 :   MOZ_ASSERT(mPendingAnimations,
     253             :              "should have called ClearAnimationsForNextTransaction first");
     254             : 
     255           0 :   Animation* anim = mPendingAnimations->AppendElement();
     256             : 
     257           0 :   return anim;
     258             : }
     259             : 
     260             : void
     261           0 : Layer::ClearAnimationsForNextTransaction()
     262             : {
     263             :   // Ensure we have a non-null mPendingAnimations to mark a future clear.
     264           0 :   if (!mPendingAnimations) {
     265           0 :     mPendingAnimations = new AnimationArray;
     266             :   }
     267             : 
     268           0 :   mPendingAnimations->Clear();
     269           0 : }
     270             : 
     271             : void
     272         124 : Layer::SetCompositorAnimations(const CompositorAnimations& aCompositorAnimations)
     273             : {
     274         124 :   MOZ_LAYERS_LOG_IF_SHADOWABLE(
     275             :     this, ("Layer::Mutated(%p) SetCompositorAnimations with id=%" PRIu64, this, mCompositorAnimationsId));
     276             : 
     277         124 :   mAnimations = aCompositorAnimations.animations();
     278         124 :   mCompositorAnimationsId = aCompositorAnimations.id();
     279         124 :   mAnimationData.Clear();
     280         124 :   AnimationHelper::SetAnimations(mAnimations,
     281             :                                  mAnimationData,
     282         124 :                                  mBaseAnimationStyle);
     283             : 
     284         124 :   Mutated();
     285         124 : }
     286             : 
     287             : void
     288          77 : Layer::StartPendingAnimations(const TimeStamp& aReadyTime)
     289             : {
     290         154 :   ForEachNode<ForwardIterator>(
     291             :       this,
     292         308 :       [&aReadyTime](Layer *layer)
     293           0 :       {
     294         308 :         bool updated = false;
     295         308 :         for (size_t animIdx = 0, animEnd = layer->mAnimations.Length();
     296         308 :              animIdx < animEnd; animIdx++) {
     297           0 :           Animation& anim = layer->mAnimations[animIdx];
     298             : 
     299             :           // If the animation is play-pending, resolve the start time.
     300             :           // This mirrors the calculation in Animation::StartTimeFromReadyTime.
     301           0 :           if (anim.startTime().type() == MaybeTimeDuration::Tnull_t &&
     302           0 :               !anim.originTime().IsNull() &&
     303           0 :               !anim.isNotPlaying()) {
     304           0 :             TimeDuration readyTime = aReadyTime - anim.originTime();
     305           0 :             anim.startTime() =
     306           0 :               anim.playbackRate() == 0
     307           0 :               ? readyTime
     308           0 :               : readyTime - anim.holdTime().MultDouble(1.0 /
     309           0 :                                                        anim.playbackRate());
     310           0 :             updated = true;
     311             :           }
     312             :         }
     313         308 :         if (updated) {
     314           0 :           layer->Mutated();
     315             :         }
     316         385 :       });
     317          77 : }
     318             : 
     319             : void
     320          39 : Layer::SetAsyncPanZoomController(uint32_t aIndex, AsyncPanZoomController *controller)
     321             : {
     322          39 :   MOZ_ASSERT(aIndex < GetScrollMetadataCount());
     323          39 :   mApzcs[aIndex] = controller;
     324          39 : }
     325             : 
     326             : AsyncPanZoomController*
     327         120 : Layer::GetAsyncPanZoomController(uint32_t aIndex) const
     328             : {
     329         120 :   MOZ_ASSERT(aIndex < GetScrollMetadataCount());
     330             : #ifdef DEBUG
     331         120 :   if (mApzcs[aIndex]) {
     332         118 :     MOZ_ASSERT(GetFrameMetrics(aIndex).IsScrollable());
     333             :   }
     334             : #endif
     335         120 :   return mApzcs[aIndex];
     336             : }
     337             : 
     338             : void
     339          57 : Layer::ScrollMetadataChanged()
     340             : {
     341          57 :   mApzcs.SetLength(GetScrollMetadataCount());
     342          57 : }
     343             : 
     344             : void
     345          29 : Layer::ApplyPendingUpdatesToSubtree()
     346             : {
     347          29 :   ForEachNode<ForwardIterator>(
     348             :       this,
     349         164 :       [] (Layer *layer)
     350             :       {
     351         164 :         layer->ApplyPendingUpdatesForThisTransaction();
     352         193 :       });
     353             : 
     354             :   // Once we're done recursing through the whole tree, clear the pending
     355             :   // updates from the manager.
     356          29 :   Manager()->ClearPendingScrollInfoUpdate();
     357          29 : }
     358             : 
     359             : bool
     360         121 : Layer::IsOpaqueForVisibility()
     361             : {
     362         242 :   return GetEffectiveOpacity() == 1.0f &&
     363         242 :          GetEffectiveMixBlendMode() == CompositionOp::OP_OVER;
     364             : }
     365             : 
     366             : bool
     367         256 : Layer::CanUseOpaqueSurface()
     368             : {
     369             :   // If the visible content in the layer is opaque, there is no need
     370             :   // for an alpha channel.
     371         256 :   if (GetContentFlags() & CONTENT_OPAQUE)
     372          92 :     return true;
     373             :   // Also, if this layer is the bottommost layer in a container which
     374             :   // doesn't need an alpha channel, we can use an opaque surface for this
     375             :   // layer too. Any transparent areas must be covered by something else
     376             :   // in the container.
     377         164 :   ContainerLayer* parent = GetParent();
     378         247 :   return parent && parent->GetFirstChild() == this &&
     379         247 :     parent->CanUseOpaqueSurface();
     380             : }
     381             : 
     382             : // NB: eventually these methods will be defined unconditionally, and
     383             : // can be moved into Layers.h
     384             : const Maybe<ParentLayerIntRect>&
     385        2242 : Layer::GetLocalClipRect()
     386             : {
     387        2242 :   if (HostLayer* shadow = AsHostLayer()) {
     388         826 :     return shadow->GetShadowClipRect();
     389             :   }
     390        1416 :   return GetClipRect();
     391             : }
     392             : 
     393             : const LayerIntRegion&
     394        2245 : Layer::GetLocalVisibleRegion()
     395             : {
     396        2245 :   if (HostLayer* shadow = AsHostLayer()) {
     397         787 :     return shadow->GetShadowVisibleRegion();
     398             :   }
     399        1458 :   return GetVisibleRegion();
     400             : }
     401             : 
     402             : Matrix4x4
     403         203 : Layer::SnapTransformTranslation(const Matrix4x4& aTransform,
     404             :                                 Matrix* aResidualTransform)
     405             : {
     406         203 :   if (aResidualTransform) {
     407           0 :     *aResidualTransform = Matrix();
     408             :   }
     409             : 
     410         203 :   if (!mManager->IsSnappingEffectiveTransforms()) {
     411           0 :     return aTransform;
     412             :   }
     413             : 
     414         203 :   Matrix matrix2D;
     415         609 :   if (aTransform.CanDraw2D(&matrix2D) &&
     416         406 :       !matrix2D.HasNonTranslation() &&
     417         203 :       matrix2D.HasNonIntegerTranslation()) {
     418           0 :     auto snappedTranslation = IntPoint::Round(matrix2D.GetTranslation());
     419           0 :     Matrix snappedMatrix = Matrix::Translation(snappedTranslation.x,
     420           0 :                                                snappedTranslation.y);
     421           0 :     Matrix4x4 result = Matrix4x4::From2D(snappedMatrix);
     422           0 :     if (aResidualTransform) {
     423             :       // set aResidualTransform so that aResidual * snappedMatrix == matrix2D.
     424             :       // (I.e., appying snappedMatrix after aResidualTransform gives the
     425             :       // ideal transform.)
     426             :       *aResidualTransform =
     427           0 :         Matrix::Translation(matrix2D._31 - snappedTranslation.x,
     428           0 :                             matrix2D._32 - snappedTranslation.y);
     429             :     }
     430           0 :     return result;
     431             :   }
     432             : 
     433         203 :   return SnapTransformTranslation3D(aTransform, aResidualTransform);
     434             : }
     435             : 
     436             : Matrix4x4
     437         203 : Layer::SnapTransformTranslation3D(const Matrix4x4& aTransform,
     438             :                                   Matrix* aResidualTransform)
     439             : {
     440         609 :   if(aTransform.IsSingular() ||
     441         406 :      aTransform.HasPerspectiveComponent() ||
     442         609 :      aTransform.HasNonTranslation() ||
     443         203 :      !aTransform.HasNonIntegerTranslation()) {
     444             :     // For a singular transform, there is no reversed matrix, so we
     445             :     // don't snap it.
     446             :     // For a perspective transform, the content is transformed in
     447             :     // non-linear, so we don't snap it too.
     448         203 :     return aTransform;
     449             :   }
     450             : 
     451             :   // Snap for 3D Transforms
     452             : 
     453           0 :   Point3D transformedOrigin = aTransform.TransformPoint(Point3D());
     454             : 
     455             :   // Compute the transformed snap by rounding the values of
     456             :   // transformed origin.
     457           0 :   auto transformedSnapXY = IntPoint::Round(transformedOrigin.x, transformedOrigin.y);
     458           0 :   Matrix4x4 inverse = aTransform;
     459           0 :   inverse.Invert();
     460             :   // see Matrix4x4::ProjectPoint()
     461             :   Float transformedSnapZ =
     462           0 :     inverse._33 == 0 ? 0 : (-(transformedSnapXY.x * inverse._13 +
     463           0 :                               transformedSnapXY.y * inverse._23 +
     464           0 :                               inverse._43) / inverse._33);
     465             :   Point3D transformedSnap =
     466           0 :     Point3D(transformedSnapXY.x, transformedSnapXY.y, transformedSnapZ);
     467           0 :   if (transformedOrigin == transformedSnap) {
     468           0 :     return aTransform;
     469             :   }
     470             : 
     471             :   // Compute the snap from the transformed snap.
     472           0 :   Point3D snap = inverse.TransformPoint(transformedSnap);
     473           0 :   if (snap.z > 0.001 || snap.z < -0.001) {
     474             :     // Allow some level of accumulated computation error.
     475           0 :     MOZ_ASSERT(inverse._33 == 0.0);
     476           0 :     return aTransform;
     477             :   }
     478             : 
     479             :   // The difference between the origin and snap is the residual transform.
     480           0 :   if (aResidualTransform) {
     481             :     // The residual transform is to translate the snap to the origin
     482             :     // of the content buffer.
     483           0 :     *aResidualTransform = Matrix::Translation(-snap.x, -snap.y);
     484             :   }
     485             : 
     486             :   // Translate transformed origin to transformed snap since the
     487             :   // residual transform would trnslate the snap to the origin.
     488           0 :   Point3D transformedShift = transformedSnap - transformedOrigin;
     489           0 :   Matrix4x4 result = aTransform;
     490             :   result.PostTranslate(transformedShift.x,
     491             :                        transformedShift.y,
     492           0 :                        transformedShift.z);
     493             : 
     494             :   // For non-2d transform, residual translation could be more than
     495             :   // 0.5 pixels for every axis.
     496             : 
     497           0 :   return result;
     498             : }
     499             : 
     500             : Matrix4x4
     501           0 : Layer::SnapTransform(const Matrix4x4& aTransform,
     502             :                      const gfxRect& aSnapRect,
     503             :                      Matrix* aResidualTransform)
     504             : {
     505           0 :   if (aResidualTransform) {
     506           0 :     *aResidualTransform = Matrix();
     507             :   }
     508             : 
     509           0 :   Matrix matrix2D;
     510           0 :   Matrix4x4 result;
     511           0 :   if (mManager->IsSnappingEffectiveTransforms() &&
     512           0 :       aTransform.Is2D(&matrix2D) &&
     513           0 :       gfxSize(1.0, 1.0) <= aSnapRect.Size() &&
     514           0 :       matrix2D.PreservesAxisAlignedRectangles()) {
     515           0 :     auto transformedTopLeft = IntPoint::Round(matrix2D.TransformPoint(ToPoint(aSnapRect.TopLeft())));
     516           0 :     auto transformedTopRight = IntPoint::Round(matrix2D.TransformPoint(ToPoint(aSnapRect.TopRight())));
     517           0 :     auto transformedBottomRight = IntPoint::Round(matrix2D.TransformPoint(ToPoint(aSnapRect.BottomRight())));
     518             : 
     519             :     Matrix snappedMatrix = gfxUtils::TransformRectToRect(aSnapRect,
     520           0 :       transformedTopLeft, transformedTopRight, transformedBottomRight);
     521             : 
     522           0 :     result = Matrix4x4::From2D(snappedMatrix);
     523           0 :     if (aResidualTransform && !snappedMatrix.IsSingular()) {
     524             :       // set aResidualTransform so that aResidual * snappedMatrix == matrix2D.
     525             :       // (i.e., appying snappedMatrix after aResidualTransform gives the
     526             :       // ideal transform.
     527           0 :       Matrix snappedMatrixInverse = snappedMatrix;
     528           0 :       snappedMatrixInverse.Invert();
     529           0 :       *aResidualTransform = matrix2D * snappedMatrixInverse;
     530             :     }
     531             :   } else {
     532           0 :     result = aTransform;
     533             :   }
     534           0 :   return result;
     535             : }
     536             : 
     537             : static bool
     538         133 : AncestorLayerMayChangeTransform(Layer* aLayer)
     539             : {
     540         459 :   for (Layer* l = aLayer; l; l = l->GetParent()) {
     541         326 :     if (l->GetContentFlags() & Layer::CONTENT_MAY_CHANGE_TRANSFORM) {
     542           0 :       return true;
     543             :     }
     544             :   }
     545         133 :   return false;
     546             : }
     547             : 
     548             : bool
     549         133 : Layer::MayResample()
     550             : {
     551         133 :   Matrix transform2d;
     552         399 :   return !GetEffectiveTransform().Is2D(&transform2d) ||
     553         798 :          ThebesMatrix(transform2d).HasNonIntegerTranslation() ||
     554         399 :          AncestorLayerMayChangeTransform(this);
     555             : }
     556             : 
     557             : RenderTargetIntRect
     558         175 : Layer::CalculateScissorRect(const RenderTargetIntRect& aCurrentScissorRect)
     559             : {
     560         175 :   ContainerLayer* container = GetParent();
     561         175 :   ContainerLayer* containerChild = nullptr;
     562         175 :   NS_ASSERTION(GetParent(), "This can't be called on the root!");
     563             : 
     564             :   // Find the layer creating the 3D context.
     565         175 :   while (container->Extend3DContext() &&
     566           0 :          !container->UseIntermediateSurface()) {
     567           0 :     containerChild = container;
     568           0 :     container = container->GetParent();
     569           0 :     MOZ_ASSERT(container);
     570             :   }
     571             : 
     572             :   // Find the nearest layer with a clip, or this layer.
     573             :   // ContainerState::SetupScrollingMetadata() may install a clip on
     574             :   // the layer.
     575             :   Layer *clipLayer =
     576         175 :     containerChild && containerChild->GetLocalClipRect() ?
     577         175 :     containerChild : this;
     578             : 
     579             :   // Establish initial clip rect: it's either the one passed in, or
     580             :   // if the parent has an intermediate surface, it's the extents of that surface.
     581         175 :   RenderTargetIntRect currentClip;
     582         175 :   if (container->UseIntermediateSurface()) {
     583           0 :     currentClip.SizeTo(container->GetIntermediateSurfaceRect().Size());
     584             :   } else {
     585         175 :     currentClip = aCurrentScissorRect;
     586             :   }
     587             : 
     588         175 :   if (!clipLayer->GetLocalClipRect()) {
     589         114 :     return currentClip;
     590             :   }
     591             : 
     592          61 :   if (GetLocalVisibleRegion().IsEmpty()) {
     593             :     // When our visible region is empty, our parent may not have created the
     594             :     // intermediate surface that we would require for correct clipping; however,
     595             :     // this does not matter since we are invisible.
     596             :     // Make sure we still compute a clip rect if we want to draw checkboarding
     597             :     // for this layer, since we want to do this even if the layer is invisible.
     598          11 :     return RenderTargetIntRect(currentClip.TopLeft(), RenderTargetIntSize(0, 0));
     599             :   }
     600             : 
     601             :   const RenderTargetIntRect clipRect =
     602          50 :     ViewAs<RenderTargetPixel>(*clipLayer->GetLocalClipRect(),
     603          50 :                               PixelCastJustification::RenderTargetIsParentLayerForRoot);
     604          50 :   if (clipRect.IsEmpty()) {
     605             :     // We might have a non-translation transform in the container so we can't
     606             :     // use the code path below.
     607           0 :     return RenderTargetIntRect(currentClip.TopLeft(), RenderTargetIntSize(0, 0));
     608             :   }
     609             : 
     610          50 :   RenderTargetIntRect scissor = clipRect;
     611          50 :   if (!container->UseIntermediateSurface()) {
     612          50 :     gfx::Matrix matrix;
     613         100 :     DebugOnly<bool> is2D = container->GetEffectiveTransform().Is2D(&matrix);
     614             :     // See DefaultComputeEffectiveTransforms below
     615          50 :     NS_ASSERTION(is2D && matrix.PreservesAxisAlignedRectangles(),
     616             :                  "Non preserves axis aligned transform with clipped child should have forced intermediate surface");
     617          50 :     gfx::Rect r(scissor.x, scissor.y, scissor.width, scissor.height);
     618          50 :     gfxRect trScissor = gfx::ThebesRect(matrix.TransformBounds(r));
     619          50 :     trScissor.Round();
     620          50 :     IntRect tmp;
     621          50 :     if (!gfxUtils::GfxRectToIntRect(trScissor, &tmp)) {
     622           0 :       return RenderTargetIntRect(currentClip.TopLeft(), RenderTargetIntSize(0, 0));
     623             :     }
     624          50 :     scissor = ViewAs<RenderTargetPixel>(tmp);
     625             : 
     626             :     // Find the nearest ancestor with an intermediate surface
     627          62 :     do {
     628          62 :       container = container->GetParent();
     629          62 :     } while (container && !container->UseIntermediateSurface());
     630             :   }
     631             : 
     632          50 :   if (container) {
     633           0 :     scissor.MoveBy(-container->GetIntermediateSurfaceRect().TopLeft());
     634             :   }
     635          50 :   return currentClip.Intersect(scissor);
     636             : }
     637             : 
     638             : Maybe<ParentLayerIntRect>
     639         703 : Layer::GetScrolledClipRect() const
     640             : {
     641        1406 :   const Maybe<LayerClip> clip = mSimpleAttrs.ScrolledClip();
     642        1406 :   return clip ? Some(clip->GetClipRect()) : Nothing();
     643             : }
     644             : 
     645             : const ScrollMetadata&
     646         511 : Layer::GetScrollMetadata(uint32_t aIndex) const
     647             : {
     648         511 :   MOZ_ASSERT(aIndex < GetScrollMetadataCount());
     649         511 :   return mScrollMetadata[aIndex];
     650             : }
     651             : 
     652             : const FrameMetrics&
     653         161 : Layer::GetFrameMetrics(uint32_t aIndex) const
     654             : {
     655         161 :   return GetScrollMetadata(aIndex).GetMetrics();
     656             : }
     657             : 
     658             : bool
     659          29 : Layer::HasScrollableFrameMetrics() const
     660             : {
     661          29 :   for (uint32_t i = 0; i < GetScrollMetadataCount(); i++) {
     662          29 :     if (GetFrameMetrics(i).IsScrollable()) {
     663          29 :       return true;
     664             :     }
     665             :   }
     666           0 :   return false;
     667             : }
     668             : 
     669             : bool
     670          40 : Layer::IsScrollInfoLayer() const
     671             : {
     672             :   // A scrollable container layer with no children
     673          40 :   return AsContainerLayer()
     674          29 :       && HasScrollableFrameMetrics()
     675          69 :       && !GetFirstChild();
     676             : }
     677             : 
     678             : Matrix4x4
     679        2929 : Layer::GetTransform() const
     680             : {
     681        2929 :   Matrix4x4 transform = mSimpleAttrs.Transform();
     682        2929 :   transform.PostScale(GetPostXScale(), GetPostYScale(), 1.0f);
     683        2929 :   if (const ContainerLayer* c = AsContainerLayer()) {
     684        1472 :     transform.PreScale(c->GetPreXScale(), c->GetPreYScale(), 1.0f);
     685             :   }
     686        2929 :   return transform;
     687             : }
     688             : 
     689             : const CSSTransformMatrix
     690         255 : Layer::GetTransformTyped() const
     691             : {
     692         255 :   return ViewAs<CSSTransformMatrix>(GetTransform());
     693             : }
     694             : 
     695             : Matrix4x4
     696        2537 : Layer::GetLocalTransform()
     697             : {
     698        2537 :   if (HostLayer* shadow = AsHostLayer()) {
     699         880 :     return shadow->GetShadowTransform();
     700             :   }
     701        1657 :   return GetTransform();
     702             : }
     703             : 
     704             : const LayerToParentLayerMatrix4x4
     705          40 : Layer::GetLocalTransformTyped()
     706             : {
     707          40 :   return ViewAs<LayerToParentLayerMatrix4x4>(GetLocalTransform());
     708             : }
     709             : 
     710             : bool
     711           0 : Layer::HasOpacityAnimation() const
     712             : {
     713           0 :   for (uint32_t i = 0; i < mAnimations.Length(); i++) {
     714           0 :     if (mAnimations[i].property() == eCSSProperty_opacity) {
     715           0 :       return true;
     716             :     }
     717             :   }
     718           0 :   return false;
     719             : }
     720             : 
     721             : bool
     722           0 : Layer::HasTransformAnimation() const
     723             : {
     724           0 :   for (uint32_t i = 0; i < mAnimations.Length(); i++) {
     725           0 :     if (mAnimations[i].property() == eCSSProperty_transform) {
     726           0 :       return true;
     727             :     }
     728             :   }
     729           0 :   return false;
     730             : }
     731             : 
     732             : void
     733         164 : Layer::ApplyPendingUpdatesForThisTransaction()
     734             : {
     735         164 :   if (mPendingTransform && *mPendingTransform != mSimpleAttrs.Transform()) {
     736           0 :     MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) PendingUpdatesForThisTransaction", this));
     737           0 :     mSimpleAttrs.SetTransform(*mPendingTransform);
     738           0 :     MutatedSimple();
     739             :   }
     740         164 :   mPendingTransform = nullptr;
     741             : 
     742         164 :   if (mPendingAnimations) {
     743           0 :     MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) PendingUpdatesForThisTransaction", this));
     744           0 :     mPendingAnimations->SwapElements(mAnimations);
     745           0 :     mPendingAnimations = nullptr;
     746           0 :     Mutated();
     747             :   }
     748             : 
     749         192 :   for (size_t i = 0; i < mScrollMetadata.Length(); i++) {
     750          28 :     FrameMetrics& fm = mScrollMetadata[i].GetMetrics();
     751          56 :     Maybe<ScrollUpdateInfo> update = Manager()->GetPendingScrollInfoUpdate(fm.GetScrollId());
     752          28 :     if (update) {
     753           0 :       fm.UpdatePendingScrollInfo(update.value());
     754           0 :       Mutated();
     755             :     }
     756             :   }
     757         164 : }
     758             : 
     759             : float
     760        2415 : Layer::GetLocalOpacity()
     761             : {
     762        2415 :   float opacity = mSimpleAttrs.Opacity();
     763        2415 :   if (HostLayer* shadow = AsHostLayer())
     764        1122 :     opacity = shadow->GetShadowOpacity();
     765        2415 :   return std::min(std::max(opacity, 0.0f), 1.0f);
     766             : }
     767             : 
     768             : float
     769         664 : Layer::GetEffectiveOpacity()
     770             : {
     771         664 :   float opacity = GetLocalOpacity();
     772        1273 :   for (ContainerLayer* c = GetParent(); c && !c->UseIntermediateSurface();
     773         609 :        c = c->GetParent()) {
     774         609 :     opacity *= c->GetLocalOpacity();
     775             :   }
     776         664 :   return opacity;
     777             : }
     778             : 
     779             : CompositionOp
     780         447 : Layer::GetEffectiveMixBlendMode()
     781             : {
     782         447 :   if (mSimpleAttrs.MixBlendMode() != CompositionOp::OP_OVER)
     783           0 :     return mSimpleAttrs.MixBlendMode();
     784        1028 :   for (ContainerLayer* c = GetParent(); c && !c->UseIntermediateSurface();
     785         581 :     c = c->GetParent()) {
     786         581 :     if(c->mSimpleAttrs.MixBlendMode() != CompositionOp::OP_OVER)
     787           0 :       return c->mSimpleAttrs.MixBlendMode();
     788             :   }
     789             : 
     790         447 :   return mSimpleAttrs.MixBlendMode();
     791             : }
     792             : 
     793             : void
     794         811 : Layer::ComputeEffectiveTransformForMaskLayers(const gfx::Matrix4x4& aTransformToSurface)
     795             : {
     796         811 :   if (GetMaskLayer()) {
     797           0 :     ComputeEffectiveTransformForMaskLayer(GetMaskLayer(), aTransformToSurface);
     798             :   }
     799         811 :   for (size_t i = 0; i < GetAncestorMaskLayerCount(); i++) {
     800           0 :     Layer* maskLayer = GetAncestorMaskLayerAt(i);
     801           0 :     ComputeEffectiveTransformForMaskLayer(maskLayer, aTransformToSurface);
     802             :   }
     803         811 : }
     804             : 
     805             : /* static */ void
     806           0 : Layer::ComputeEffectiveTransformForMaskLayer(Layer* aMaskLayer, const gfx::Matrix4x4& aTransformToSurface)
     807             : {
     808           0 :   aMaskLayer->mEffectiveTransform = aTransformToSurface;
     809             : 
     810             : #ifdef DEBUG
     811           0 :   bool maskIs2D = aMaskLayer->GetTransform().CanDraw2D();
     812           0 :   NS_ASSERTION(maskIs2D, "How did we end up with a 3D transform here?!");
     813             : #endif
     814             :   // The mask layer can have an async transform applied to it in some
     815             :   // situations, so be sure to use its GetLocalTransform() rather than
     816             :   // its GetTransform().
     817           0 :   aMaskLayer->mEffectiveTransform = aMaskLayer->GetLocalTransform() *
     818             :     aMaskLayer->mEffectiveTransform;
     819           0 : }
     820             : 
     821             : RenderTargetRect
     822           0 : Layer::TransformRectToRenderTarget(const LayerIntRect& aRect)
     823             : {
     824           0 :   LayerRect rect(aRect);
     825             :   RenderTargetRect quad = RenderTargetRect::FromUnknownRect(
     826           0 :     GetEffectiveTransform().TransformBounds(rect.ToUnknownRect()));
     827           0 :   return quad;
     828             : }
     829             : 
     830             : bool
     831           0 : Layer::GetVisibleRegionRelativeToRootLayer(nsIntRegion& aResult,
     832             :                                            IntPoint* aLayerOffset)
     833             : {
     834           0 :   MOZ_ASSERT(aLayerOffset, "invalid offset pointer");
     835             : 
     836           0 :   if (!GetParent()) {
     837           0 :     return false;
     838             :   }
     839             : 
     840           0 :   IntPoint offset;
     841           0 :   aResult = GetLocalVisibleRegion().ToUnknownRegion();
     842           0 :   for (Layer* layer = this; layer; layer = layer->GetParent()) {
     843           0 :     gfx::Matrix matrix;
     844           0 :     if (!layer->GetLocalTransform().Is2D(&matrix) ||
     845           0 :         !matrix.IsTranslation()) {
     846           0 :       return false;
     847             :     }
     848             : 
     849             :     // The offset of |layer| to its parent.
     850           0 :     auto currentLayerOffset = IntPoint::Round(matrix.GetTranslation());
     851             : 
     852             :     // Translate the accumulated visible region of |this| by the offset of
     853             :     // |layer|.
     854           0 :     aResult.MoveBy(currentLayerOffset.x, currentLayerOffset.y);
     855             : 
     856             :     // If the parent layer clips its lower layers, clip the visible region
     857             :     // we're accumulating.
     858           0 :     if (layer->GetLocalClipRect()) {
     859           0 :       aResult.AndWith(layer->GetLocalClipRect()->ToUnknownRect());
     860             :     }
     861             : 
     862             :     // Now we need to walk across the list of siblings for this parent layer,
     863             :     // checking to see if any of these layer trees obscure |this|. If so,
     864             :     // remove these areas from the visible region as well. This will pick up
     865             :     // chrome overlays like a tab modal prompt.
     866             :     Layer* sibling;
     867           0 :     for (sibling = layer->GetNextSibling(); sibling;
     868             :          sibling = sibling->GetNextSibling()) {
     869           0 :       gfx::Matrix siblingMatrix;
     870           0 :       if (!sibling->GetLocalTransform().Is2D(&siblingMatrix) ||
     871           0 :           !siblingMatrix.IsTranslation()) {
     872           0 :         continue;
     873             :       }
     874             : 
     875             :       // Retreive the translation from sibling to |layer|. The accumulated
     876             :       // visible region is currently oriented with |layer|.
     877           0 :       auto siblingOffset = IntPoint::Round(siblingMatrix.GetTranslation());
     878           0 :       nsIntRegion siblingVisibleRegion(sibling->GetLocalVisibleRegion().ToUnknownRegion());
     879             :       // Translate the siblings region to |layer|'s origin.
     880           0 :       siblingVisibleRegion.MoveBy(-siblingOffset.x, -siblingOffset.y);
     881             :       // Apply the sibling's clip.
     882             :       // Layer clip rects are not affected by the layer's transform.
     883           0 :       Maybe<ParentLayerIntRect> clipRect = sibling->GetLocalClipRect();
     884           0 :       if (clipRect) {
     885           0 :         siblingVisibleRegion.AndWith(clipRect->ToUnknownRect());
     886             :       }
     887             :       // Subtract the sibling visible region from the visible region of |this|.
     888           0 :       aResult.SubOut(siblingVisibleRegion);
     889             :     }
     890             : 
     891             :     // Keep track of the total offset for aLayerOffset.  We use this in plugin
     892             :     // positioning code.
     893           0 :     offset += currentLayerOffset;
     894             :   }
     895             : 
     896           0 :   *aLayerOffset = IntPoint(offset.x, offset.y);
     897           0 :   return true;
     898             : }
     899             : 
     900             : Maybe<ParentLayerIntRect>
     901          39 : Layer::GetCombinedClipRect() const
     902             : {
     903          39 :   Maybe<ParentLayerIntRect> clip = GetClipRect();
     904             : 
     905          39 :   clip = IntersectMaybeRects(clip, GetScrolledClipRect());
     906             : 
     907          41 :   for (size_t i = 0; i < mScrollMetadata.Length(); i++) {
     908           2 :     clip = IntersectMaybeRects(clip, mScrollMetadata[i].GetClipRect());
     909             :   }
     910             : 
     911          39 :   return clip;
     912             : }
     913             : 
     914          64 : ContainerLayer::ContainerLayer(LayerManager* aManager, void* aImplData)
     915             :   : Layer(aManager, aImplData),
     916             :     mFirstChild(nullptr),
     917             :     mLastChild(nullptr),
     918             :     mPreXScale(1.0f),
     919             :     mPreYScale(1.0f),
     920             :     mInheritedXScale(1.0f),
     921             :     mInheritedYScale(1.0f),
     922             :     mPresShellResolution(1.0f),
     923             :     mScaleToResolution(false),
     924             :     mUseIntermediateSurface(false),
     925             :     mSupportsComponentAlphaChildren(false),
     926             :     mMayHaveReadbackChild(false),
     927             :     mChildrenChanged(false),
     928          64 :     mEventRegionsOverride(EventRegionsOverride::NoOverride)
     929             : {
     930          64 : }
     931             : 
     932          52 : ContainerLayer::~ContainerLayer()
     933             : {
     934          52 : }
     935             : 
     936             : bool
     937         201 : ContainerLayer::InsertAfter(Layer* aChild, Layer* aAfter)
     938             : {
     939         201 :   if(aChild->Manager() != Manager()) {
     940           0 :     NS_ERROR("Child has wrong manager");
     941           0 :     return false;
     942             :   }
     943         201 :   if(aChild->GetParent()) {
     944           0 :     NS_ERROR("aChild already in the tree");
     945           0 :     return false;
     946             :   }
     947         201 :   if (aChild->GetNextSibling() || aChild->GetPrevSibling()) {
     948           0 :     NS_ERROR("aChild already has siblings?");
     949           0 :     return false;
     950             :   }
     951         271 :   if (aAfter && (aAfter->Manager() != Manager() ||
     952          70 :                  aAfter->GetParent() != this))
     953             :   {
     954           0 :     NS_ERROR("aAfter is not our child");
     955           0 :     return false;
     956             :   }
     957             : 
     958         201 :   aChild->SetParent(this);
     959         201 :   if (aAfter == mLastChild) {
     960          98 :     mLastChild = aChild;
     961             :   }
     962         201 :   if (!aAfter) {
     963         131 :     aChild->SetNextSibling(mFirstChild);
     964         131 :     if (mFirstChild) {
     965          69 :       mFirstChild->SetPrevSibling(aChild);
     966             :     }
     967         131 :     mFirstChild = aChild;
     968         131 :     NS_ADDREF(aChild);
     969         131 :     DidInsertChild(aChild);
     970         131 :     return true;
     971             :   }
     972             : 
     973          70 :   Layer* next = aAfter->GetNextSibling();
     974          70 :   aChild->SetNextSibling(next);
     975          70 :   aChild->SetPrevSibling(aAfter);
     976          70 :   if (next) {
     977          34 :     next->SetPrevSibling(aChild);
     978             :   }
     979          70 :   aAfter->SetNextSibling(aChild);
     980          70 :   NS_ADDREF(aChild);
     981          70 :   DidInsertChild(aChild);
     982          70 :   return true;
     983             : }
     984             : 
     985             : void
     986          50 : ContainerLayer::RemoveAllChildren()
     987             : {
     988             :   // Optimizes "while (mFirstChild) ContainerLayer::RemoveChild(mFirstChild);"
     989          50 :   Layer* current = mFirstChild;
     990             : 
     991             :   // This is inlining DidRemoveChild() on each layer; we can skip the calls
     992             :   // to NotifyPaintedLayerRemoved as it gets taken care of when as we call
     993             :   // NotifyRemoved prior to removing any layers.
     994         198 :   while (current) {
     995          74 :     Layer* next = current->GetNextSibling();
     996          74 :     if (current->GetType() == TYPE_READBACK) {
     997           0 :       static_cast<ReadbackLayer*>(current)->NotifyRemoved();
     998             :     }
     999          74 :     current = next;
    1000             :   }
    1001             : 
    1002          50 :   current = mFirstChild;
    1003          50 :   mFirstChild = nullptr;
    1004         198 :   while (current) {
    1005          74 :     MOZ_ASSERT(!current->GetPrevSibling());
    1006             : 
    1007          74 :     Layer* next = current->GetNextSibling();
    1008          74 :     current->SetParent(nullptr);
    1009          74 :     current->SetNextSibling(nullptr);
    1010          74 :     if (next) {
    1011          24 :       next->SetPrevSibling(nullptr);
    1012             :     }
    1013          74 :     NS_RELEASE(current);
    1014          74 :     current = next;
    1015             :   }
    1016          50 : }
    1017             : 
    1018             : // Note that ContainerLayer::RemoveAllChildren is an optimized
    1019             : // version of this code; if you make changes to ContainerLayer::RemoveChild
    1020             : // consider whether the matching changes need to be made to
    1021             : // ContainerLayer::RemoveAllChildren
    1022             : bool
    1023         111 : ContainerLayer::RemoveChild(Layer *aChild)
    1024             : {
    1025         111 :   if (aChild->Manager() != Manager()) {
    1026           0 :     NS_ERROR("Child has wrong manager");
    1027           0 :     return false;
    1028             :   }
    1029         111 :   if (aChild->GetParent() != this) {
    1030           0 :     NS_ERROR("aChild not our child");
    1031           0 :     return false;
    1032             :   }
    1033             : 
    1034         111 :   Layer* prev = aChild->GetPrevSibling();
    1035         111 :   Layer* next = aChild->GetNextSibling();
    1036         111 :   if (prev) {
    1037         109 :     prev->SetNextSibling(next);
    1038             :   } else {
    1039           2 :     this->mFirstChild = next;
    1040             :   }
    1041         111 :   if (next) {
    1042           4 :     next->SetPrevSibling(prev);
    1043             :   } else {
    1044         107 :     this->mLastChild = prev;
    1045             :   }
    1046             : 
    1047         111 :   aChild->SetNextSibling(nullptr);
    1048         111 :   aChild->SetPrevSibling(nullptr);
    1049         111 :   aChild->SetParent(nullptr);
    1050             : 
    1051         111 :   this->DidRemoveChild(aChild);
    1052         111 :   NS_RELEASE(aChild);
    1053         111 :   return true;
    1054             : }
    1055             : 
    1056             : 
    1057             : bool
    1058           0 : ContainerLayer::RepositionChild(Layer* aChild, Layer* aAfter)
    1059             : {
    1060           0 :   if (aChild->Manager() != Manager()) {
    1061           0 :     NS_ERROR("Child has wrong manager");
    1062           0 :     return false;
    1063             :   }
    1064           0 :   if (aChild->GetParent() != this) {
    1065           0 :     NS_ERROR("aChild not our child");
    1066           0 :     return false;
    1067             :   }
    1068           0 :   if (aAfter && (aAfter->Manager() != Manager() ||
    1069           0 :                  aAfter->GetParent() != this))
    1070             :   {
    1071           0 :     NS_ERROR("aAfter is not our child");
    1072           0 :     return false;
    1073             :   }
    1074           0 :   if (aChild == aAfter) {
    1075           0 :     NS_ERROR("aChild cannot be the same as aAfter");
    1076           0 :     return false;
    1077             :   }
    1078             : 
    1079           0 :   Layer* prev = aChild->GetPrevSibling();
    1080           0 :   Layer* next = aChild->GetNextSibling();
    1081           0 :   if (prev == aAfter) {
    1082             :     // aChild is already in the correct position, nothing to do.
    1083           0 :     return true;
    1084             :   }
    1085           0 :   if (prev) {
    1086           0 :     prev->SetNextSibling(next);
    1087             :   } else {
    1088           0 :     mFirstChild = next;
    1089             :   }
    1090           0 :   if (next) {
    1091           0 :     next->SetPrevSibling(prev);
    1092             :   } else {
    1093           0 :     mLastChild = prev;
    1094             :   }
    1095           0 :   if (!aAfter) {
    1096           0 :     aChild->SetPrevSibling(nullptr);
    1097           0 :     aChild->SetNextSibling(mFirstChild);
    1098           0 :     if (mFirstChild) {
    1099           0 :       mFirstChild->SetPrevSibling(aChild);
    1100             :     }
    1101           0 :     mFirstChild = aChild;
    1102           0 :     return true;
    1103             :   }
    1104             : 
    1105           0 :   Layer* afterNext = aAfter->GetNextSibling();
    1106           0 :   if (afterNext) {
    1107           0 :     afterNext->SetPrevSibling(aChild);
    1108             :   } else {
    1109           0 :     mLastChild = aChild;
    1110             :   }
    1111           0 :   aAfter->SetNextSibling(aChild);
    1112           0 :   aChild->SetPrevSibling(aAfter);
    1113           0 :   aChild->SetNextSibling(afterNext);
    1114           0 :   return true;
    1115             : }
    1116             : 
    1117             : void
    1118          43 : ContainerLayer::FillSpecificAttributes(SpecificLayerAttributes& aAttrs)
    1119             : {
    1120          86 :   aAttrs = ContainerLayerAttributes(mPreXScale, mPreYScale,
    1121             :                                     mInheritedXScale, mInheritedYScale,
    1122             :                                     mPresShellResolution, mScaleToResolution,
    1123          43 :                                     mEventRegionsOverride);
    1124          43 : }
    1125             : 
    1126             : bool
    1127         114 : ContainerLayer::Creates3DContextWithExtendingChildren()
    1128             : {
    1129         114 :   if (Extend3DContext()) {
    1130           0 :     return false;
    1131             :   }
    1132         201 :   for (Layer* child = GetFirstChild();
    1133         201 :        child;
    1134             :        child = child->GetNextSibling()) {
    1135          87 :       if (child->Extend3DContext()) {
    1136           0 :         return true;
    1137             :       }
    1138             :   }
    1139         114 :   return false;
    1140             : }
    1141             : 
    1142             : bool
    1143         554 : ContainerLayer::HasMultipleChildren()
    1144             : {
    1145         554 :   uint32_t count = 0;
    1146        1110 :   for (Layer* child = GetFirstChild(); child; child = child->GetNextSibling()) {
    1147         621 :     const Maybe<ParentLayerIntRect>& clipRect = child->GetLocalClipRect();
    1148         621 :     if (clipRect && clipRect->IsEmpty())
    1149          14 :       continue;
    1150         607 :     if (child->GetLocalVisibleRegion().IsEmpty())
    1151         171 :       continue;
    1152         436 :     ++count;
    1153         436 :     if (count > 1)
    1154          65 :       return true;
    1155             :   }
    1156             : 
    1157         489 :   return false;
    1158             : }
    1159             : 
    1160             : /**
    1161             :  * Collect all leaf descendants of the current 3D context.
    1162             :  */
    1163             : void
    1164           0 : ContainerLayer::Collect3DContextLeaves(nsTArray<Layer*>& aToSort)
    1165             : {
    1166           0 :   ForEachNode<ForwardIterator>(
    1167             :       (Layer*) this,
    1168           0 :       [this, &aToSort](Layer* layer)
    1169           0 :       {
    1170           0 :         ContainerLayer* container = layer->AsContainerLayer();
    1171           0 :         if (layer == this || (container && container->Extend3DContext() &&
    1172           0 :             !container->UseIntermediateSurface())) {
    1173           0 :           return TraversalFlag::Continue;
    1174             :         }
    1175           0 :         aToSort.AppendElement(layer);
    1176           0 :         return TraversalFlag::Skip;
    1177             :       }
    1178           0 :   );
    1179           0 : }
    1180             : 
    1181             : static nsTArray<LayerPolygon>
    1182           0 : SortLayersWithBSPTree(nsTArray<Layer*>& aArray)
    1183             : {
    1184           0 :   std::list<LayerPolygon> inputLayers;
    1185             : 
    1186             :   // Build a list of polygons to be sorted.
    1187           0 :   for (Layer* layer : aArray) {
    1188             :     // Ignore invisible layers.
    1189           0 :     if (!layer->IsVisible()) {
    1190           0 :       continue;
    1191             :     }
    1192             : 
    1193             :     const gfx::IntRect& bounds =
    1194           0 :       layer->GetLocalVisibleRegion().ToUnknownRegion().GetBounds();
    1195             : 
    1196           0 :     const gfx::Matrix4x4& transform = layer->GetEffectiveTransform();
    1197             : 
    1198           0 :     if (transform.IsSingular()) {
    1199             :       // Transform cannot be inverted.
    1200           0 :       continue;
    1201             :     }
    1202             : 
    1203           0 :     gfx::Polygon polygon = gfx::Polygon::FromRect(gfx::Rect(bounds));
    1204             : 
    1205             :     // Transform the polygon to screen space.
    1206           0 :     polygon.TransformToScreenSpace(transform);
    1207             : 
    1208           0 :     if (polygon.GetPoints().Length() >= 3) {
    1209           0 :       inputLayers.push_back(LayerPolygon(layer, Move(polygon)));
    1210             :     }
    1211             :   }
    1212             : 
    1213           0 :   if (inputLayers.empty()) {
    1214           0 :     return nsTArray<LayerPolygon>();
    1215             :   }
    1216             : 
    1217             :   // Build a BSP tree from the list of polygons.
    1218           0 :   BSPTree tree(inputLayers);
    1219             : 
    1220           0 :   nsTArray<LayerPolygon> orderedLayers(tree.GetDrawOrder());
    1221             : 
    1222             :   // Transform the polygons back to layer space.
    1223           0 :   for (LayerPolygon& layerPolygon : orderedLayers) {
    1224             :     gfx::Matrix4x4 inverse =
    1225           0 :       layerPolygon.layer->GetEffectiveTransform().Inverse();
    1226             : 
    1227           0 :     MOZ_ASSERT(layerPolygon.geometry);
    1228           0 :     layerPolygon.geometry->TransformToLayerSpace(inverse);
    1229             :   }
    1230             : 
    1231           0 :   return orderedLayers;
    1232             : }
    1233             : 
    1234             : static nsTArray<LayerPolygon>
    1235          72 : StripLayerGeometry(const nsTArray<LayerPolygon>& aLayers)
    1236             : {
    1237          72 :   nsTArray<LayerPolygon> layers;
    1238         144 :   std::set<Layer*> uniqueLayers;
    1239             : 
    1240         168 :   for (const LayerPolygon& layerPolygon : aLayers) {
    1241          96 :     auto result = uniqueLayers.insert(layerPolygon.layer);
    1242             : 
    1243          96 :     if (result.second) {
    1244             :       // Layer was added to the set.
    1245          96 :       layers.AppendElement(LayerPolygon(layerPolygon.layer));
    1246             :     }
    1247             :   }
    1248             : 
    1249         144 :   return layers;
    1250             : }
    1251             : 
    1252             : nsTArray<LayerPolygon>
    1253         160 : ContainerLayer::SortChildrenBy3DZOrder(SortMode aSortMode)
    1254             : {
    1255         320 :   AutoTArray<Layer*, 10> toSort;
    1256         320 :   nsTArray<LayerPolygon> drawOrder;
    1257             : 
    1258         431 :   for (Layer* layer = GetFirstChild(); layer; layer = layer->GetNextSibling()) {
    1259         271 :     ContainerLayer* container = layer->AsContainerLayer();
    1260             : 
    1261         271 :     if (container && container->Extend3DContext() &&
    1262           0 :         !container->UseIntermediateSurface()) {
    1263             : 
    1264             :       // Collect 3D layers in toSort array.
    1265           0 :       container->Collect3DContextLeaves(toSort);
    1266             : 
    1267             :       // Sort the 3D layers.
    1268           0 :       if (toSort.Length() > 0) {
    1269           0 :         nsTArray<LayerPolygon> sorted = SortLayersWithBSPTree(toSort);
    1270           0 :         drawOrder.AppendElements(Move(sorted));
    1271             : 
    1272           0 :         toSort.ClearAndRetainStorage();
    1273             :       }
    1274             : 
    1275           0 :       continue;
    1276             :     }
    1277             : 
    1278         271 :     drawOrder.AppendElement(LayerPolygon(layer));
    1279             :   }
    1280             : 
    1281         160 :   if (aSortMode == SortMode::WITHOUT_GEOMETRY) {
    1282             :     // Compositor does not support arbitrary layers, strip the layer geometry
    1283             :     // and duplicate layers.
    1284          72 :     return StripLayerGeometry(drawOrder);
    1285             :   }
    1286             : 
    1287          88 :   return drawOrder;
    1288             : }
    1289             : 
    1290             : bool
    1291         176 : ContainerLayer::AnyAncestorOrThisIs3DContextLeaf()
    1292             : {
    1293         176 :   Layer* parent = this;
    1294         780 :   while (parent != nullptr) {
    1295         302 :     if (parent->Is3DContextLeaf()) {
    1296           0 :       return true;
    1297             :     }
    1298             : 
    1299         302 :     parent = parent->GetParent();
    1300             :   }
    1301             : 
    1302         176 :   return false;
    1303             : }
    1304             : 
    1305             : void
    1306         176 : ContainerLayer::DefaultComputeEffectiveTransforms(const Matrix4x4& aTransformToSurface)
    1307             : {
    1308         176 :   Matrix residual;
    1309         176 :   Matrix4x4 idealTransform = GetLocalTransform() * aTransformToSurface;
    1310             : 
    1311             :   // Keep 3D transforms for leaves to keep z-order sorting correct.
    1312         176 :   if (!Extend3DContext() && !Is3DContextLeaf()) {
    1313         176 :     idealTransform.ProjectTo2D();
    1314             :   }
    1315             : 
    1316             :   bool useIntermediateSurface;
    1317         352 :   if (HasMaskLayers() ||
    1318         176 :       GetForceIsolatedGroup()) {
    1319           0 :     useIntermediateSurface = true;
    1320             : #ifdef MOZ_DUMP_PAINTING
    1321         176 :   } else if (gfxEnv::DumpPaintIntermediate() && !Extend3DContext()) {
    1322           0 :     useIntermediateSurface = true;
    1323             : #endif
    1324             :   } else {
    1325             :     /* Don't use an intermediate surface for opacity when it's within a 3d
    1326             :      * context, since we'd rather keep the 3d effects. This matches the
    1327             :      * WebKit/blink behaviour, but is changing in the latest spec.
    1328             :      */
    1329         176 :     float opacity = GetEffectiveOpacity();
    1330         176 :     CompositionOp blendMode = GetEffectiveMixBlendMode();
    1331         176 :     if ((HasMultipleChildren() || Creates3DContextWithExtendingChildren()) &&
    1332           0 :         ((opacity != 1.0f && !Extend3DContext()) ||
    1333             :          (blendMode != CompositionOp::OP_OVER))) {
    1334           0 :       useIntermediateSurface = true;
    1335         176 :     } else if ((!idealTransform.Is2D() || AnyAncestorOrThisIs3DContextLeaf()) &&
    1336           0 :                Creates3DContextWithExtendingChildren()) {
    1337           0 :       useIntermediateSurface = true;
    1338         176 :     } else if (blendMode != CompositionOp::OP_OVER &&
    1339           0 :                Manager()->BlendingRequiresIntermediateSurface()) {
    1340           0 :       useIntermediateSurface = true;
    1341             :     } else {
    1342         176 :       useIntermediateSurface = false;
    1343         176 :       gfx::Matrix contTransform;
    1344         176 :       bool checkClipRect = false;
    1345         176 :       bool checkMaskLayers = false;
    1346             : 
    1347         176 :       if (!idealTransform.Is2D(&contTransform)) {
    1348             :         // In 3D case, always check if we should use IntermediateSurface.
    1349           0 :         checkClipRect = true;
    1350           0 :         checkMaskLayers = true;
    1351             :       } else {
    1352             : #ifdef MOZ_GFX_OPTIMIZE_MOBILE
    1353             :         if (!contTransform.PreservesAxisAlignedRectangles()) {
    1354             : #else
    1355         176 :         if (gfx::ThebesMatrix(contTransform).HasNonIntegerTranslation()) {
    1356             : #endif
    1357           0 :           checkClipRect = true;
    1358             :         }
    1359             :         /* In 2D case, only translation and/or positive scaling can be done w/o using IntermediateSurface.
    1360             :          * Otherwise, when rotation or flip happen, we should check whether to use IntermediateSurface.
    1361             :          */
    1362         176 :         if (contTransform.HasNonAxisAlignedTransform() || contTransform.HasNegativeScaling()) {
    1363           0 :           checkMaskLayers = true;
    1364             :         }
    1365             :       }
    1366             : 
    1367         176 :       if (checkClipRect || checkMaskLayers) {
    1368           0 :         for (Layer* child = GetFirstChild(); child; child = child->GetNextSibling()) {
    1369           0 :           const Maybe<ParentLayerIntRect>& clipRect = child->GetLocalClipRect();
    1370             :           /* We can't (easily) forward our transform to children with a non-empty clip
    1371             :            * rect since it would need to be adjusted for the transform. See
    1372             :            * the calculations performed by CalculateScissorRect above.
    1373             :            * Nor for a child with a mask layer.
    1374             :            */
    1375           0 :           if (checkClipRect && (clipRect && !clipRect->IsEmpty() && !child->GetLocalVisibleRegion().IsEmpty())) {
    1376           0 :             useIntermediateSurface = true;
    1377           0 :             break;
    1378             :           }
    1379           0 :           if (checkMaskLayers && child->HasMaskLayers()) {
    1380           0 :             useIntermediateSurface = true;
    1381           0 :             break;
    1382             :           }
    1383             :         }
    1384             :       }
    1385             :     }
    1386             :   }
    1387             : 
    1388         176 :   NS_ASSERTION(!Extend3DContext() || !useIntermediateSurface, "Can't have an intermediate surface with preserve-3d!");
    1389             : 
    1390         176 :   if (useIntermediateSurface) {
    1391           0 :     mEffectiveTransform = SnapTransformTranslation(idealTransform, &residual);
    1392             :   } else {
    1393         176 :     mEffectiveTransform = idealTransform;
    1394             :   }
    1395             : 
    1396             :   // For layers extending 3d context, its ideal transform should be
    1397             :   // applied on children.
    1398         176 :   if (!Extend3DContext()) {
    1399             :     // Without this projection, non-container children would get a 3D
    1400             :     // transform while 2D is expected.
    1401         176 :     idealTransform.ProjectTo2D();
    1402             :   }
    1403         176 :   mUseIntermediateSurface = useIntermediateSurface && !GetLocalVisibleRegion().IsEmpty();
    1404         176 :   if (useIntermediateSurface) {
    1405           0 :     ComputeEffectiveTransformsForChildren(Matrix4x4::From2D(residual));
    1406             :   } else {
    1407         176 :     ComputeEffectiveTransformsForChildren(idealTransform);
    1408             :   }
    1409             : 
    1410         176 :   ComputeEffectiveTransformForMaskLayers(aTransformToSurface);
    1411         176 : }
    1412             : 
    1413             : void
    1414         145 : ContainerLayer::DefaultComputeSupportsComponentAlphaChildren(bool* aNeedsSurfaceCopy)
    1415             : {
    1416         145 :   if (!(GetContentFlags() & Layer::CONTENT_COMPONENT_ALPHA_DESCENDANT) ||
    1417           0 :       !Manager()->AreComponentAlphaLayersEnabled()) {
    1418         145 :     mSupportsComponentAlphaChildren = false;
    1419         145 :     if (aNeedsSurfaceCopy) {
    1420          88 :       *aNeedsSurfaceCopy = false;
    1421             :     }
    1422         145 :     return;
    1423             :   }
    1424             : 
    1425           0 :   mSupportsComponentAlphaChildren = false;
    1426           0 :   bool needsSurfaceCopy = false;
    1427           0 :   CompositionOp blendMode = GetEffectiveMixBlendMode();
    1428           0 :   if (UseIntermediateSurface()) {
    1429           0 :     if (GetLocalVisibleRegion().GetNumRects() == 1 &&
    1430           0 :         (GetContentFlags() & Layer::CONTENT_OPAQUE))
    1431             :     {
    1432           0 :       mSupportsComponentAlphaChildren = true;
    1433             :     } else {
    1434           0 :       gfx::Matrix transform;
    1435           0 :       if (HasOpaqueAncestorLayer(this) &&
    1436           0 :           GetEffectiveTransform().Is2D(&transform) &&
    1437           0 :           !gfx::ThebesMatrix(transform).HasNonIntegerTranslation() &&
    1438           0 :           blendMode == gfx::CompositionOp::OP_OVER &&
    1439           0 :           Manager()->SupportsBackdropCopyForComponentAlpha())
    1440             :       {
    1441           0 :         mSupportsComponentAlphaChildren = true;
    1442           0 :         needsSurfaceCopy = true;
    1443             :       }
    1444             :     }
    1445           0 :   } else if (blendMode == gfx::CompositionOp::OP_OVER) {
    1446           0 :     mSupportsComponentAlphaChildren =
    1447           0 :       (GetContentFlags() & Layer::CONTENT_OPAQUE) ||
    1448           0 :       (GetParent() && GetParent()->SupportsComponentAlphaChildren());
    1449             :   }
    1450             : 
    1451           0 :   if (aNeedsSurfaceCopy) {
    1452           0 :     *aNeedsSurfaceCopy = mSupportsComponentAlphaChildren && needsSurfaceCopy;
    1453             :   }
    1454             : }
    1455             : 
    1456             : void
    1457         393 : ContainerLayer::ComputeEffectiveTransformsForChildren(const Matrix4x4& aTransformToSurface)
    1458             : {
    1459         955 :   for (Layer* l = mFirstChild; l; l = l->GetNextSibling()) {
    1460         562 :     l->ComputeEffectiveTransforms(aTransformToSurface);
    1461             :   }
    1462         393 : }
    1463             : 
    1464             : /* static */ bool
    1465           0 : ContainerLayer::HasOpaqueAncestorLayer(Layer* aLayer)
    1466             : {
    1467           0 :   for (Layer* l = aLayer->GetParent(); l; l = l->GetParent()) {
    1468           0 :     if (l->GetContentFlags() & Layer::CONTENT_OPAQUE)
    1469           0 :       return true;
    1470             :   }
    1471           0 :   return false;
    1472             : }
    1473             : 
    1474             : // Note that ContainerLayer::RemoveAllChildren contains an optimized
    1475             : // version of this code; if you make changes to ContainerLayer::DidRemoveChild
    1476             : // consider whether the matching changes need to be made to
    1477             : // ContainerLayer::RemoveAllChildren
    1478             : void
    1479         111 : ContainerLayer::DidRemoveChild(Layer* aLayer)
    1480             : {
    1481         111 :   PaintedLayer* tl = aLayer->AsPaintedLayer();
    1482         111 :   if (tl && tl->UsedForReadback()) {
    1483           0 :     for (Layer* l = mFirstChild; l; l = l->GetNextSibling()) {
    1484           0 :       if (l->GetType() == TYPE_READBACK) {
    1485           0 :         static_cast<ReadbackLayer*>(l)->NotifyPaintedLayerRemoved(tl);
    1486             :       }
    1487             :     }
    1488             :   }
    1489         111 :   if (aLayer->GetType() == TYPE_READBACK) {
    1490           0 :     static_cast<ReadbackLayer*>(aLayer)->NotifyRemoved();
    1491             :   }
    1492         111 : }
    1493             : 
    1494             : void
    1495         201 : ContainerLayer::DidInsertChild(Layer* aLayer)
    1496             : {
    1497         201 :   if (aLayer->GetType() == TYPE_READBACK) {
    1498           0 :     mMayHaveReadbackChild = true;
    1499             :   }
    1500         201 : }
    1501             : 
    1502             : void
    1503          24 : RefLayer::FillSpecificAttributes(SpecificLayerAttributes& aAttrs)
    1504             : {
    1505          24 :   aAttrs = RefLayerAttributes(GetReferentId(), mEventRegionsOverride);
    1506          24 : }
    1507             : 
    1508             : /**
    1509             :  * StartFrameTimeRecording, together with StopFrameTimeRecording
    1510             :  * enable recording of frame intervals.
    1511             :  *
    1512             :  * To allow concurrent consumers, a cyclic array is used which serves all
    1513             :  * consumers, practically stateless with regard to consumers.
    1514             :  *
    1515             :  * To save resources, the buffer is allocated on first call to StartFrameTimeRecording
    1516             :  * and recording is paused if no consumer which called StartFrameTimeRecording is able
    1517             :  * to get valid results (because the cyclic buffer was overwritten since that call).
    1518             :  *
    1519             :  * To determine availability of the data upon StopFrameTimeRecording:
    1520             :  * - mRecording.mNextIndex increases on each RecordFrame, and never resets.
    1521             :  * - Cyclic buffer position is realized as mNextIndex % bufferSize.
    1522             :  * - StartFrameTimeRecording returns mNextIndex. When StopFrameTimeRecording is called,
    1523             :  *   the required start index is passed as an arg, and we're able to calculate the required
    1524             :  *   length. If this length is bigger than bufferSize, it means data was overwritten.
    1525             :  *   otherwise, we can return the entire sequence.
    1526             :  * - To determine if we need to pause, mLatestStartIndex is updated to mNextIndex
    1527             :  *   on each call to StartFrameTimeRecording. If this index gets overwritten,
    1528             :  *   it means that all earlier start indices obtained via StartFrameTimeRecording
    1529             :  *   were also overwritten, hence, no point in recording, so pause.
    1530             :  * - mCurrentRunStartIndex indicates the oldest index of the recording after which
    1531             :  *   the recording was not paused. If StopFrameTimeRecording is invoked with a start index
    1532             :  *   older than this, it means that some frames were not recorded, so data is invalid.
    1533             :  */
    1534             : uint32_t
    1535           0 : LayerManager::StartFrameTimeRecording(int32_t aBufferSize)
    1536             : {
    1537           0 :   if (mRecording.mIsPaused) {
    1538           0 :     mRecording.mIsPaused = false;
    1539             : 
    1540           0 :     if (!mRecording.mIntervals.Length()) { // Initialize recording buffers
    1541           0 :       mRecording.mIntervals.SetLength(aBufferSize);
    1542             :     }
    1543             : 
    1544             :     // After being paused, recent values got invalid. Update them to now.
    1545           0 :     mRecording.mLastFrameTime = TimeStamp::Now();
    1546             : 
    1547             :     // Any recording which started before this is invalid, since we were paused.
    1548           0 :     mRecording.mCurrentRunStartIndex = mRecording.mNextIndex;
    1549             :   }
    1550             : 
    1551             :   // If we'll overwrite this index, there are no more consumers with aStartIndex
    1552             :   // for which we're able to provide the full recording, so no point in keep recording.
    1553           0 :   mRecording.mLatestStartIndex = mRecording.mNextIndex;
    1554           0 :   return mRecording.mNextIndex;
    1555             : }
    1556             : 
    1557             : void
    1558          75 : LayerManager::RecordFrame()
    1559             : {
    1560          75 :   if (!mRecording.mIsPaused) {
    1561           0 :     TimeStamp now = TimeStamp::Now();
    1562           0 :     uint32_t i = mRecording.mNextIndex % mRecording.mIntervals.Length();
    1563           0 :     mRecording.mIntervals[i] = static_cast<float>((now - mRecording.mLastFrameTime)
    1564           0 :                                                   .ToMilliseconds());
    1565           0 :     mRecording.mNextIndex++;
    1566           0 :     mRecording.mLastFrameTime = now;
    1567             : 
    1568           0 :     if (mRecording.mNextIndex > (mRecording.mLatestStartIndex + mRecording.mIntervals.Length())) {
    1569             :       // We've just overwritten the most recent recording start -> pause.
    1570           0 :       mRecording.mIsPaused = true;
    1571             :     }
    1572             :   }
    1573          75 : }
    1574             : 
    1575             : void
    1576           0 : LayerManager::StopFrameTimeRecording(uint32_t         aStartIndex,
    1577             :                                      nsTArray<float>& aFrameIntervals)
    1578             : {
    1579           0 :   uint32_t bufferSize = mRecording.mIntervals.Length();
    1580           0 :   uint32_t length = mRecording.mNextIndex - aStartIndex;
    1581           0 :   if (mRecording.mIsPaused || length > bufferSize || aStartIndex < mRecording.mCurrentRunStartIndex) {
    1582             :     // aStartIndex is too old. Also if aStartIndex was issued before mRecordingNextIndex overflowed (uint32_t)
    1583             :     //   and stopped after the overflow (would happen once every 828 days of constant 60fps).
    1584           0 :     length = 0;
    1585             :   }
    1586             : 
    1587           0 :   if (!length) {
    1588           0 :     aFrameIntervals.Clear();
    1589           0 :     return; // empty recording, return empty arrays.
    1590             :   }
    1591             :   // Set length in advance to avoid possibly repeated reallocations
    1592           0 :   aFrameIntervals.SetLength(length);
    1593             : 
    1594           0 :   uint32_t cyclicPos = aStartIndex % bufferSize;
    1595           0 :   for (uint32_t i = 0; i < length; i++, cyclicPos++) {
    1596           0 :     if (cyclicPos == bufferSize) {
    1597           0 :       cyclicPos = 0;
    1598             :     }
    1599           0 :     aFrameIntervals[i] = mRecording.mIntervals[cyclicPos];
    1600             :   }
    1601             : }
    1602             : 
    1603             : static void PrintInfo(std::stringstream& aStream, HostLayer* aLayerComposite);
    1604             : 
    1605             : #ifdef MOZ_DUMP_PAINTING
    1606             : template <typename T>
    1607           0 : void WriteSnapshotToDumpFile_internal(T* aObj, DataSourceSurface* aSurf)
    1608             : {
    1609           0 :   nsCString string(aObj->Name());
    1610           0 :   string.Append('-');
    1611           0 :   string.AppendInt((uint64_t)aObj);
    1612           0 :   if (gfxUtils::sDumpPaintFile != stderr) {
    1613           0 :     fprintf_stderr(gfxUtils::sDumpPaintFile, R"(array["%s"]=")", string.BeginReading());
    1614             :   }
    1615           0 :   gfxUtils::DumpAsDataURI(aSurf, gfxUtils::sDumpPaintFile);
    1616           0 :   if (gfxUtils::sDumpPaintFile != stderr) {
    1617           0 :     fprintf_stderr(gfxUtils::sDumpPaintFile, R"(";)");
    1618             :   }
    1619           0 : }
    1620             : 
    1621           0 : void WriteSnapshotToDumpFile(Layer* aLayer, DataSourceSurface* aSurf)
    1622             : {
    1623           0 :   WriteSnapshotToDumpFile_internal(aLayer, aSurf);
    1624           0 : }
    1625             : 
    1626           0 : void WriteSnapshotToDumpFile(LayerManager* aManager, DataSourceSurface* aSurf)
    1627             : {
    1628           0 :   WriteSnapshotToDumpFile_internal(aManager, aSurf);
    1629           0 : }
    1630             : 
    1631           0 : void WriteSnapshotToDumpFile(Compositor* aCompositor, DrawTarget* aTarget)
    1632             : {
    1633           0 :   RefPtr<SourceSurface> surf = aTarget->Snapshot();
    1634           0 :   RefPtr<DataSourceSurface> dSurf = surf->GetDataSurface();
    1635           0 :   WriteSnapshotToDumpFile_internal(aCompositor, dSurf);
    1636           0 : }
    1637             : #endif
    1638             : 
    1639             : void
    1640           0 : Layer::Dump(std::stringstream& aStream, const char* aPrefix,
    1641             :             bool aDumpHtml, bool aSorted, const Maybe<gfx::Polygon>& aGeometry)
    1642             : {
    1643             : #ifdef MOZ_DUMP_PAINTING
    1644           0 :   bool dumpCompositorTexture = gfxEnv::DumpCompositorTextures() && AsHostLayer() &&
    1645           0 :                                AsHostLayer()->GetCompositableHost();
    1646           0 :   bool dumpClientTexture = gfxEnv::DumpPaint() && AsShadowableLayer() &&
    1647           0 :                            AsShadowableLayer()->GetCompositableClient();
    1648           0 :   nsCString layerId(Name());
    1649           0 :   layerId.Append('-');
    1650           0 :   layerId.AppendInt((uint64_t)this);
    1651             : #endif
    1652           0 :   if (aDumpHtml) {
    1653           0 :     aStream << nsPrintfCString(R"(<li><a id="%p" )", this).get();
    1654             : #ifdef MOZ_DUMP_PAINTING
    1655           0 :     if (dumpCompositorTexture || dumpClientTexture) {
    1656           0 :       aStream << nsPrintfCString(R"lit(href="javascript:ViewImage('%s')")lit", layerId.BeginReading()).get();
    1657             :     }
    1658             : #endif
    1659           0 :     aStream << ">";
    1660             :   }
    1661           0 :   DumpSelf(aStream, aPrefix, aGeometry);
    1662             : 
    1663             : #ifdef MOZ_DUMP_PAINTING
    1664           0 :   if (dumpCompositorTexture) {
    1665           0 :     AsHostLayer()->GetCompositableHost()->Dump(aStream, aPrefix, aDumpHtml);
    1666           0 :   } else if (dumpClientTexture) {
    1667           0 :     if (aDumpHtml) {
    1668           0 :       aStream << nsPrintfCString(R"(<script>array["%s"]=")", layerId.BeginReading()).get();
    1669             :     }
    1670           0 :     AsShadowableLayer()->GetCompositableClient()->Dump(aStream, aPrefix,
    1671           0 :         aDumpHtml, TextureDumpMode::DoNotCompress);
    1672           0 :     if (aDumpHtml) {
    1673           0 :       aStream << R"(";</script>)";
    1674             :     }
    1675             :   }
    1676             : #endif
    1677             : 
    1678           0 :   if (aDumpHtml) {
    1679           0 :     aStream << "</a>";
    1680             : #ifdef MOZ_DUMP_PAINTING
    1681           0 :     if (dumpClientTexture) {
    1682           0 :       aStream << nsPrintfCString("<br><img id=\"%s\">\n", layerId.BeginReading()).get();
    1683             :     }
    1684             : #endif
    1685             :   }
    1686             : 
    1687           0 :   if (Layer* mask = GetMaskLayer()) {
    1688           0 :     aStream << nsPrintfCString("%s  Mask layer:\n", aPrefix).get();
    1689           0 :     nsAutoCString pfx(aPrefix);
    1690           0 :     pfx += "    ";
    1691           0 :     mask->Dump(aStream, pfx.get(), aDumpHtml);
    1692             :   }
    1693             : 
    1694           0 :   for (size_t i = 0; i < GetAncestorMaskLayerCount(); i++) {
    1695           0 :     aStream << nsPrintfCString("%s  Ancestor mask layer %d:\n", aPrefix, uint32_t(i)).get();
    1696           0 :     nsAutoCString pfx(aPrefix);
    1697           0 :     pfx += "    ";
    1698           0 :     GetAncestorMaskLayerAt(i)->Dump(aStream, pfx.get(), aDumpHtml);
    1699             :   }
    1700             : 
    1701             : #ifdef MOZ_DUMP_PAINTING
    1702           0 :   for (size_t i = 0; i < mExtraDumpInfo.Length(); i++) {
    1703           0 :     const nsCString& str = mExtraDumpInfo[i];
    1704           0 :     aStream << aPrefix << "  Info:\n" << str.get();
    1705             :   }
    1706             : #endif
    1707             : 
    1708           0 :   if (ContainerLayer* container = AsContainerLayer()) {
    1709           0 :     nsTArray<LayerPolygon> children;
    1710           0 :     if (aSorted) {
    1711             :       children =
    1712           0 :         container->SortChildrenBy3DZOrder(ContainerLayer::SortMode::WITH_GEOMETRY);
    1713             :     } else {
    1714           0 :       for (Layer* l = container->GetFirstChild(); l; l = l->GetNextSibling()) {
    1715           0 :         children.AppendElement(LayerPolygon(l));
    1716             :       }
    1717             :     }
    1718           0 :     nsAutoCString pfx(aPrefix);
    1719           0 :     pfx += "  ";
    1720           0 :     if (aDumpHtml) {
    1721           0 :       aStream << "<ul>";
    1722             :     }
    1723             : 
    1724           0 :     for (LayerPolygon& child : children) {
    1725           0 :       child.layer->Dump(aStream, pfx.get(), aDumpHtml, aSorted, child.geometry);
    1726             :     }
    1727             : 
    1728           0 :     if (aDumpHtml) {
    1729           0 :       aStream << "</ul>";
    1730             :     }
    1731             :   }
    1732             : 
    1733           0 :   if (aDumpHtml) {
    1734           0 :     aStream << "</li>";
    1735             :   }
    1736           0 : }
    1737             : 
    1738             : static void
    1739           0 : DumpGeometry(std::stringstream& aStream, const Maybe<gfx::Polygon>& aGeometry)
    1740             : {
    1741           0 :   aStream << " [geometry=[";
    1742             : 
    1743           0 :   const nsTArray<gfx::Point4D>& points = aGeometry->GetPoints();
    1744           0 :   for (size_t i = 0; i < points.Length(); ++i) {
    1745           0 :     const gfx::IntPoint point = TruncatedToInt(points[i].As2DPoint());
    1746           0 :     const char* sfx = (i != points.Length() - 1) ? "," : "";
    1747           0 :     AppendToString(aStream, point, "", sfx);
    1748             :   }
    1749             : 
    1750           0 :   aStream << "]]";
    1751           0 : }
    1752             : 
    1753             : void
    1754           0 : Layer::DumpSelf(std::stringstream& aStream, const char* aPrefix,
    1755             :                 const Maybe<gfx::Polygon>& aGeometry)
    1756             : {
    1757           0 :   PrintInfo(aStream, aPrefix);
    1758             : 
    1759           0 :   if (aGeometry) {
    1760           0 :     DumpGeometry(aStream, aGeometry);
    1761             :   }
    1762             : 
    1763           0 :   aStream << "\n";
    1764           0 : }
    1765             : 
    1766             : void
    1767           0 : Layer::Dump(layerscope::LayersPacket* aPacket, const void* aParent)
    1768             : {
    1769           0 :   DumpPacket(aPacket, aParent);
    1770             : 
    1771           0 :   if (Layer* kid = GetFirstChild()) {
    1772           0 :     kid->Dump(aPacket, this);
    1773             :   }
    1774             : 
    1775           0 :   if (Layer* next = GetNextSibling()) {
    1776           0 :     next->Dump(aPacket, aParent);
    1777             :   }
    1778           0 : }
    1779             : 
    1780             : void
    1781         124 : Layer::SetDisplayListLog(const char* log)
    1782             : {
    1783         124 :   if (gfxUtils::DumpDisplayList()) {
    1784           0 :     mDisplayListLog = log;
    1785             :   }
    1786         124 : }
    1787             : 
    1788             : void
    1789         124 : Layer::GetDisplayListLog(nsCString& log)
    1790             : {
    1791         124 :   log.SetLength(0);
    1792             : 
    1793         124 :   if (gfxUtils::DumpDisplayList()) {
    1794             :     // This function returns a plain text string which consists of two things
    1795             :     //   1. DisplayList log.
    1796             :     //   2. Memory address of this layer.
    1797             :     // We know the target layer of each display item by information in #1.
    1798             :     // Here is an example of a Text display item line log in #1
    1799             :     //   Text p=0xa9850c00 f=0x0xaa405b00(.....
    1800             :     // f keeps the address of the target client layer of a display item.
    1801             :     // For LayerScope, display-item-to-client-layer mapping is not enough since
    1802             :     // LayerScope, which lives in the chrome process, knows only composite layers.
    1803             :     // As so, we need display-item-to-client-layer-to-layer-composite
    1804             :     // mapping. That's the reason we insert #2 into the log
    1805           0 :     log.AppendPrintf("0x%p\n%s",(void*) this, mDisplayListLog.get());
    1806             :   }
    1807         124 : }
    1808             : 
    1809             : void
    1810           0 : Layer::Log(const char* aPrefix)
    1811             : {
    1812           0 :   if (!IsLogEnabled())
    1813           0 :     return;
    1814             : 
    1815           0 :   LogSelf(aPrefix);
    1816             : 
    1817           0 :   if (Layer* kid = GetFirstChild()) {
    1818           0 :     nsAutoCString pfx(aPrefix);
    1819           0 :     pfx += "  ";
    1820           0 :     kid->Log(pfx.get());
    1821             :   }
    1822             : 
    1823           0 :   if (Layer* next = GetNextSibling())
    1824           0 :     next->Log(aPrefix);
    1825             : }
    1826             : 
    1827             : void
    1828           0 : Layer::LogSelf(const char* aPrefix)
    1829             : {
    1830           0 :   if (!IsLogEnabled())
    1831           0 :     return;
    1832             : 
    1833           0 :   std::stringstream ss;
    1834           0 :   PrintInfo(ss, aPrefix);
    1835           0 :   MOZ_LAYERS_LOG(("%s", ss.str().c_str()));
    1836             : 
    1837           0 :   if (mMaskLayer) {
    1838           0 :     nsAutoCString pfx(aPrefix);
    1839           0 :     pfx += R"(   \ MaskLayer )";
    1840           0 :     mMaskLayer->LogSelf(pfx.get());
    1841             :   }
    1842             : }
    1843             : 
    1844             : void
    1845           0 : Layer::PrintInfo(std::stringstream& aStream, const char* aPrefix)
    1846             : {
    1847           0 :   aStream << aPrefix;
    1848           0 :   aStream << nsPrintfCString("%s%s (0x%p)", mManager->Name(), Name(), this).get();
    1849             : 
    1850           0 :   layers::PrintInfo(aStream, AsHostLayer());
    1851             : 
    1852           0 :   if (mClipRect) {
    1853           0 :     AppendToString(aStream, *mClipRect, " [clip=", "]");
    1854             :   }
    1855           0 :   if (mSimpleAttrs.ScrolledClip()) {
    1856           0 :     AppendToString(aStream, mSimpleAttrs.ScrolledClip()->GetClipRect(), " [scrolled-clip=", "]");
    1857           0 :     if (const Maybe<size_t>& ix = mSimpleAttrs.ScrolledClip()->GetMaskLayerIndex()) {
    1858           0 :       AppendToString(aStream, ix.value(), " [scrolled-mask=", "]");
    1859             :     }
    1860             :   }
    1861           0 :   if (1.0 != mSimpleAttrs.PostXScale() || 1.0 != mSimpleAttrs.PostYScale()) {
    1862           0 :     aStream << nsPrintfCString(" [postScale=%g, %g]", mSimpleAttrs.PostXScale(), mSimpleAttrs.PostYScale()).get();
    1863             :   }
    1864           0 :   if (!GetBaseTransform().IsIdentity()) {
    1865           0 :     AppendToString(aStream, GetBaseTransform(), " [transform=", "]");
    1866             :   }
    1867           0 :   if (!GetEffectiveTransform().IsIdentity()) {
    1868           0 :     AppendToString(aStream, GetEffectiveTransform(), " [effective-transform=", "]");
    1869             :   }
    1870           0 :   if (GetTransformIsPerspective()) {
    1871           0 :     aStream << " [perspective]";
    1872             :   }
    1873           0 :   if (!mVisibleRegion.IsEmpty()) {
    1874           0 :     AppendToString(aStream, mVisibleRegion.ToUnknownRegion(), " [visible=", "]");
    1875             :   } else {
    1876           0 :     aStream << " [not visible]";
    1877             :   }
    1878           0 :   if (!mEventRegions.IsEmpty()) {
    1879           0 :     AppendToString(aStream, mEventRegions, " ", "");
    1880             :   }
    1881           0 :   if (1.0 != GetOpacity()) {
    1882           0 :     aStream << nsPrintfCString(" [opacity=%g]", GetOpacity()).get();
    1883             :   }
    1884           0 :   if (IsOpaque()) {
    1885           0 :     aStream << " [opaqueContent]";
    1886             :   }
    1887           0 :   if (GetContentFlags() & CONTENT_COMPONENT_ALPHA) {
    1888           0 :     aStream << " [componentAlpha]";
    1889             :   }
    1890           0 :   if (GetContentFlags() & CONTENT_BACKFACE_HIDDEN) {
    1891           0 :     aStream << " [backfaceHidden]";
    1892             :   }
    1893           0 :   if (Extend3DContext()) {
    1894           0 :     aStream << " [extend3DContext]";
    1895             :   }
    1896           0 :   if (Combines3DTransformWithAncestors()) {
    1897           0 :     aStream << " [combines3DTransformWithAncestors]";
    1898             :   }
    1899           0 :   if (Is3DContextLeaf()) {
    1900           0 :     aStream << " [is3DContextLeaf]";
    1901             :   }
    1902           0 :   if (IsScrollbarContainer()) {
    1903           0 :     aStream << " [scrollbar]";
    1904             :   }
    1905           0 :   ScrollDirection thumbDirection = GetScrollThumbData().mDirection;
    1906           0 :   if (thumbDirection == ScrollDirection::VERTICAL) {
    1907           0 :     aStream << nsPrintfCString(" [vscrollbar=%" PRIu64 "]", GetScrollbarTargetContainerId()).get();
    1908             :   }
    1909           0 :   if (thumbDirection == ScrollDirection::HORIZONTAL) {
    1910           0 :     aStream << nsPrintfCString(" [hscrollbar=%" PRIu64 "]", GetScrollbarTargetContainerId()).get();
    1911             :   }
    1912           0 :   if (GetIsFixedPosition()) {
    1913           0 :     LayerPoint anchor = GetFixedPositionAnchor();
    1914           0 :     aStream << nsPrintfCString(" [isFixedPosition scrollId=%" PRIu64 " sides=0x%x anchor=%s]",
    1915             :                      GetFixedPositionScrollContainerId(),
    1916             :                      GetFixedPositionSides(),
    1917           0 :                      ToString(anchor).c_str()).get();
    1918             :   }
    1919           0 :   if (GetIsStickyPosition()) {
    1920           0 :     aStream << nsPrintfCString(" [isStickyPosition scrollId=%" PRIu64 " outer=(%.3f,%.3f)-(%.3f,%.3f) "
    1921             :                      "inner=(%.3f,%.3f)-(%.3f,%.3f)]",
    1922             :                      GetStickyScrollContainerId(),
    1923           0 :                      GetStickyScrollRangeOuter().x,
    1924           0 :                      GetStickyScrollRangeOuter().y,
    1925           0 :                      GetStickyScrollRangeOuter().XMost(),
    1926           0 :                      GetStickyScrollRangeOuter().YMost(),
    1927           0 :                      GetStickyScrollRangeInner().x,
    1928           0 :                      GetStickyScrollRangeInner().y,
    1929           0 :                      GetStickyScrollRangeInner().XMost(),
    1930           0 :                      GetStickyScrollRangeInner().YMost()).get();
    1931             :   }
    1932           0 :   if (mMaskLayer) {
    1933           0 :     aStream << nsPrintfCString(" [mMaskLayer=%p]", mMaskLayer.get()).get();
    1934             :   }
    1935           0 :   for (uint32_t i = 0; i < mScrollMetadata.Length(); i++) {
    1936           0 :     if (!mScrollMetadata[i].IsDefault()) {
    1937           0 :       aStream << nsPrintfCString(" [metrics%d=", i).get();
    1938           0 :       AppendToString(aStream, mScrollMetadata[i], "", "]");
    1939             :     }
    1940             :   }
    1941           0 :   if (!mAnimations.IsEmpty()) {
    1942           0 :     aStream << nsPrintfCString(" [%d animations with id=%" PRIu64 " ]",
    1943           0 :                                (int) mAnimations.Length(),
    1944           0 :                                mCompositorAnimationsId).get();
    1945             :   }
    1946           0 : }
    1947             : 
    1948             : // The static helper function sets the transform matrix into the packet
    1949             : static void
    1950           0 : DumpTransform(layerscope::LayersPacket::Layer::Matrix* aLayerMatrix, const Matrix4x4& aMatrix)
    1951             : {
    1952           0 :   aLayerMatrix->set_is2d(aMatrix.Is2D());
    1953           0 :   if (aMatrix.Is2D()) {
    1954           0 :     Matrix m = aMatrix.As2D();
    1955           0 :     aLayerMatrix->set_isid(m.IsIdentity());
    1956           0 :     if (!m.IsIdentity()) {
    1957           0 :       aLayerMatrix->add_m(m._11); aLayerMatrix->add_m(m._12);
    1958           0 :       aLayerMatrix->add_m(m._21); aLayerMatrix->add_m(m._22);
    1959           0 :       aLayerMatrix->add_m(m._31); aLayerMatrix->add_m(m._32);
    1960             :     }
    1961             :   } else {
    1962           0 :     aLayerMatrix->add_m(aMatrix._11); aLayerMatrix->add_m(aMatrix._12);
    1963           0 :     aLayerMatrix->add_m(aMatrix._13); aLayerMatrix->add_m(aMatrix._14);
    1964           0 :     aLayerMatrix->add_m(aMatrix._21); aLayerMatrix->add_m(aMatrix._22);
    1965           0 :     aLayerMatrix->add_m(aMatrix._23); aLayerMatrix->add_m(aMatrix._24);
    1966           0 :     aLayerMatrix->add_m(aMatrix._31); aLayerMatrix->add_m(aMatrix._32);
    1967           0 :     aLayerMatrix->add_m(aMatrix._33); aLayerMatrix->add_m(aMatrix._34);
    1968           0 :     aLayerMatrix->add_m(aMatrix._41); aLayerMatrix->add_m(aMatrix._42);
    1969           0 :     aLayerMatrix->add_m(aMatrix._43); aLayerMatrix->add_m(aMatrix._44);
    1970             :   }
    1971           0 : }
    1972             : 
    1973             : // The static helper function sets the IntRect into the packet
    1974             : template <typename T, typename Sub, typename Point, typename SizeT, typename MarginT>
    1975             : static void
    1976           0 : DumpRect(layerscope::LayersPacket::Layer::Rect* aLayerRect,
    1977             :          const BaseRect<T, Sub, Point, SizeT, MarginT>& aRect)
    1978             : {
    1979           0 :   aLayerRect->set_x(aRect.x);
    1980           0 :   aLayerRect->set_y(aRect.y);
    1981           0 :   aLayerRect->set_w(aRect.width);
    1982           0 :   aLayerRect->set_h(aRect.height);
    1983           0 : }
    1984             : 
    1985             : // The static helper function sets the nsIntRegion into the packet
    1986             : static void
    1987           0 : DumpRegion(layerscope::LayersPacket::Layer::Region* aLayerRegion, const nsIntRegion& aRegion)
    1988             : {
    1989           0 :   for (auto iter = aRegion.RectIter(); !iter.Done(); iter.Next()) {
    1990           0 :     DumpRect(aLayerRegion->add_r(), iter.Get());
    1991             :   }
    1992           0 : }
    1993             : 
    1994             : void
    1995           0 : Layer::DumpPacket(layerscope::LayersPacket* aPacket, const void* aParent)
    1996             : {
    1997             :   // Add a new layer (UnknownLayer)
    1998             :   using namespace layerscope;
    1999           0 :   LayersPacket::Layer* layer = aPacket->add_layer();
    2000             :   // Basic information
    2001           0 :   layer->set_type(LayersPacket::Layer::UnknownLayer);
    2002           0 :   layer->set_ptr(reinterpret_cast<uint64_t>(this));
    2003           0 :   layer->set_parentptr(reinterpret_cast<uint64_t>(aParent));
    2004             :   // Shadow
    2005           0 :   if (HostLayer* lc = AsHostLayer()) {
    2006           0 :     LayersPacket::Layer::Shadow* s = layer->mutable_shadow();
    2007           0 :     if (const Maybe<ParentLayerIntRect>& clipRect = lc->GetShadowClipRect()) {
    2008           0 :       DumpRect(s->mutable_clip(), *clipRect);
    2009             :     }
    2010           0 :     if (!lc->GetShadowBaseTransform().IsIdentity()) {
    2011           0 :       DumpTransform(s->mutable_transform(), lc->GetShadowBaseTransform());
    2012             :     }
    2013           0 :     if (!lc->GetShadowVisibleRegion().IsEmpty()) {
    2014           0 :       DumpRegion(s->mutable_vregion(), lc->GetShadowVisibleRegion().ToUnknownRegion());
    2015             :     }
    2016             :   }
    2017             :   // Clip
    2018           0 :   if (mClipRect) {
    2019           0 :     DumpRect(layer->mutable_clip(), *mClipRect);
    2020             :   }
    2021             :   // Transform
    2022           0 :   if (!GetBaseTransform().IsIdentity()) {
    2023           0 :     DumpTransform(layer->mutable_transform(), GetBaseTransform());
    2024             :   }
    2025             :   // Visible region
    2026           0 :   if (!mVisibleRegion.ToUnknownRegion().IsEmpty()) {
    2027           0 :     DumpRegion(layer->mutable_vregion(), mVisibleRegion.ToUnknownRegion());
    2028             :   }
    2029             :   // EventRegions
    2030           0 :   if (!mEventRegions.IsEmpty()) {
    2031           0 :     const EventRegions &e = mEventRegions;
    2032           0 :     if (!e.mHitRegion.IsEmpty()) {
    2033           0 :       DumpRegion(layer->mutable_hitregion(), e.mHitRegion);
    2034             :     }
    2035           0 :     if (!e.mDispatchToContentHitRegion.IsEmpty()) {
    2036           0 :       DumpRegion(layer->mutable_dispatchregion(), e.mDispatchToContentHitRegion);
    2037             :     }
    2038           0 :     if (!e.mNoActionRegion.IsEmpty()) {
    2039           0 :       DumpRegion(layer->mutable_noactionregion(), e.mNoActionRegion);
    2040             :     }
    2041           0 :     if (!e.mHorizontalPanRegion.IsEmpty()) {
    2042           0 :       DumpRegion(layer->mutable_hpanregion(), e.mHorizontalPanRegion);
    2043             :     }
    2044           0 :     if (!e.mVerticalPanRegion.IsEmpty()) {
    2045           0 :       DumpRegion(layer->mutable_vpanregion(), e.mVerticalPanRegion);
    2046             :     }
    2047             :   }
    2048             :   // Opacity
    2049           0 :   layer->set_opacity(GetOpacity());
    2050             :   // Content opaque
    2051           0 :   layer->set_copaque(static_cast<bool>(GetContentFlags() & CONTENT_OPAQUE));
    2052             :   // Component alpha
    2053           0 :   layer->set_calpha(static_cast<bool>(GetContentFlags() & CONTENT_COMPONENT_ALPHA));
    2054             :   // Vertical or horizontal bar
    2055           0 :   ScrollDirection thumbDirection = GetScrollThumbData().mDirection;
    2056           0 :   if (thumbDirection != ScrollDirection::NONE) {
    2057           0 :     layer->set_direct(thumbDirection == ScrollDirection::VERTICAL ?
    2058             :                       LayersPacket::Layer::VERTICAL :
    2059           0 :                       LayersPacket::Layer::HORIZONTAL);
    2060           0 :     layer->set_barid(GetScrollbarTargetContainerId());
    2061             :   }
    2062             : 
    2063             :   // Mask layer
    2064           0 :   if (mMaskLayer) {
    2065           0 :     layer->set_mask(reinterpret_cast<uint64_t>(mMaskLayer.get()));
    2066             :   }
    2067             : 
    2068             :   // DisplayList log.
    2069           0 :   if (mDisplayListLog.Length() > 0) {
    2070           0 :     layer->set_displaylistloglength(mDisplayListLog.Length());
    2071             :     auto compressedData =
    2072           0 :       MakeUnique<char[]>(LZ4::maxCompressedSize(mDisplayListLog.Length()));
    2073           0 :     int compressedSize = LZ4::compress((char*)mDisplayListLog.get(),
    2074           0 :                                        mDisplayListLog.Length(),
    2075           0 :                                        compressedData.get());
    2076           0 :     layer->set_displaylistlog(compressedData.get(), compressedSize);
    2077             :   }
    2078           0 : }
    2079             : 
    2080             : bool
    2081         271 : Layer::IsBackfaceHidden()
    2082             : {
    2083         271 :   if (GetContentFlags() & CONTENT_BACKFACE_HIDDEN) {
    2084           0 :     Layer* container = AsContainerLayer() ? this : GetParent();
    2085           0 :     if (container) {
    2086             :       // The effective transform can include non-preserve-3d parent
    2087             :       // transforms, since we don't always require an intermediate.
    2088           0 :       if (container->Extend3DContext() || container->Is3DContextLeaf()) {
    2089           0 :         return container->GetEffectiveTransform().IsBackfaceVisible();
    2090             :       }
    2091           0 :       return container->GetBaseTransform().IsBackfaceVisible();
    2092             :     }
    2093             :   }
    2094         271 :   return false;
    2095             : }
    2096             : 
    2097             : UniquePtr<LayerUserData>
    2098          24 : Layer::RemoveUserData(void* aKey)
    2099             : {
    2100          24 :   UniquePtr<LayerUserData> d(static_cast<LayerUserData*>(mUserData.Remove(static_cast<gfx::UserDataKey*>(aKey))));
    2101          24 :   return d;
    2102             : }
    2103             : 
    2104             : void
    2105           0 : Layer::SetManager(LayerManager* aManager, HostLayer* aSelf)
    2106             : {
    2107             :   // No one should be calling this for weird reasons.
    2108           0 :   MOZ_ASSERT(aSelf);
    2109           0 :   MOZ_ASSERT(aSelf->GetLayer() == this);
    2110           0 :   mManager = aManager;
    2111           0 : }
    2112             : 
    2113             : void
    2114           0 : PaintedLayer::PrintInfo(std::stringstream& aStream, const char* aPrefix)
    2115             : {
    2116           0 :   Layer::PrintInfo(aStream, aPrefix);
    2117           0 :   nsIntRegion validRegion = GetValidRegion();
    2118           0 :   if (!validRegion.IsEmpty()) {
    2119           0 :     AppendToString(aStream, validRegion, " [valid=", "]");
    2120             :   }
    2121           0 : }
    2122             : 
    2123             : void
    2124           0 : PaintedLayer::DumpPacket(layerscope::LayersPacket* aPacket, const void* aParent)
    2125             : {
    2126           0 :   Layer::DumpPacket(aPacket, aParent);
    2127             :   // get this layer data
    2128             :   using namespace layerscope;
    2129           0 :   LayersPacket::Layer* layer = aPacket->mutable_layer(aPacket->layer_size()-1);
    2130           0 :   layer->set_type(LayersPacket::Layer::PaintedLayer);
    2131           0 :   nsIntRegion validRegion = GetValidRegion();
    2132           0 :   if (!validRegion.IsEmpty()) {
    2133           0 :     DumpRegion(layer->mutable_valid(), validRegion);
    2134             :   }
    2135           0 : }
    2136             : 
    2137             : void
    2138           0 : ContainerLayer::PrintInfo(std::stringstream& aStream, const char* aPrefix)
    2139             : {
    2140           0 :   Layer::PrintInfo(aStream, aPrefix);
    2141           0 :   if (UseIntermediateSurface()) {
    2142           0 :     aStream << " [usesTmpSurf]";
    2143             :   }
    2144           0 :   if (1.0 != mPreXScale || 1.0 != mPreYScale) {
    2145           0 :     aStream << nsPrintfCString(" [preScale=%g, %g]", mPreXScale, mPreYScale).get();
    2146             :   }
    2147           0 :   if (mScaleToResolution) {
    2148           0 :     aStream << nsPrintfCString(" [presShellResolution=%g]", mPresShellResolution).get();
    2149             :   }
    2150           0 :   if (mEventRegionsOverride & EventRegionsOverride::ForceDispatchToContent) {
    2151           0 :     aStream << " [force-dtc]";
    2152             :   }
    2153           0 :   if (mEventRegionsOverride & EventRegionsOverride::ForceEmptyHitRegion) {
    2154           0 :     aStream << " [force-ehr]";
    2155             :   }
    2156           0 : }
    2157             : 
    2158             : void
    2159           0 : ContainerLayer::DumpPacket(layerscope::LayersPacket* aPacket, const void* aParent)
    2160             : {
    2161           0 :   Layer::DumpPacket(aPacket, aParent);
    2162             :   // Get this layer data
    2163             :   using namespace layerscope;
    2164           0 :   LayersPacket::Layer* layer = aPacket->mutable_layer(aPacket->layer_size()-1);
    2165           0 :   layer->set_type(LayersPacket::Layer::ContainerLayer);
    2166           0 : }
    2167             : 
    2168             : void
    2169           0 : DisplayItemLayer::EndTransaction() {
    2170           0 :   mItem = nullptr;
    2171           0 :   mBuilder = nullptr;
    2172           0 : }
    2173             : 
    2174             : void
    2175           0 : DisplayItemLayer::PrintInfo(std::stringstream& aStream, const char* aPrefix)
    2176             : {
    2177           0 :   Layer::PrintInfo(aStream, aPrefix);
    2178           0 :   const char* type = "TYPE_UNKNOWN";
    2179           0 :   if (mItem) {
    2180           0 :     type = mItem->Name();
    2181             :   }
    2182             : 
    2183           0 :   aStream << " [itype type=" << type << "]";
    2184           0 : }
    2185             : 
    2186             : void
    2187           0 : DisplayItemLayer::DumpPacket(layerscope::LayersPacket* aPacket, const void* aParent)
    2188             : {
    2189           0 :   Layer::DumpPacket(aPacket, aParent);
    2190             :   // Get this layer data
    2191             :   using namespace layerscope;
    2192           0 :   LayersPacket::Layer* layer = aPacket->mutable_layer(aPacket->layer_size()-1);
    2193           0 :   layer->set_type(LayersPacket::Layer::DisplayItemLayer);
    2194           0 : }
    2195             : 
    2196             : void
    2197           0 : ColorLayer::PrintInfo(std::stringstream& aStream, const char* aPrefix)
    2198             : {
    2199           0 :   Layer::PrintInfo(aStream, aPrefix);
    2200           0 :   AppendToString(aStream, mColor, " [color=", "]");
    2201           0 :   AppendToString(aStream, mBounds, " [bounds=", "]");
    2202           0 : }
    2203             : 
    2204             : void
    2205           0 : ColorLayer::DumpPacket(layerscope::LayersPacket* aPacket, const void* aParent)
    2206             : {
    2207           0 :   Layer::DumpPacket(aPacket, aParent);
    2208             :   // Get this layer data
    2209             :   using namespace layerscope;
    2210           0 :   LayersPacket::Layer* layer = aPacket->mutable_layer(aPacket->layer_size()-1);
    2211           0 :   layer->set_type(LayersPacket::Layer::ColorLayer);
    2212           0 :   layer->set_color(mColor.ToABGR());
    2213           0 : }
    2214             : 
    2215             : void
    2216           0 : TextLayer::PrintInfo(std::stringstream& aStream, const char* aPrefix)
    2217             : {
    2218           0 :   Layer::PrintInfo(aStream, aPrefix);
    2219           0 :   AppendToString(aStream, mBounds, " [bounds=", "]");
    2220           0 : }
    2221             : 
    2222             : void
    2223           0 : TextLayer::DumpPacket(layerscope::LayersPacket* aPacket, const void* aParent)
    2224             : {
    2225           0 :   Layer::DumpPacket(aPacket, aParent);
    2226             :   // Get this layer data
    2227             :   using namespace layerscope;
    2228           0 :   LayersPacket::Layer* layer = aPacket->mutable_layer(aPacket->layer_size()-1);
    2229           0 :   layer->set_type(LayersPacket::Layer::TextLayer);
    2230           0 : }
    2231             : 
    2232             : void
    2233           0 : BorderLayer::PrintInfo(std::stringstream& aStream, const char* aPrefix)
    2234             : {
    2235           0 :   Layer::PrintInfo(aStream, aPrefix);
    2236           0 : }
    2237             : 
    2238             : void
    2239           0 : BorderLayer::DumpPacket(layerscope::LayersPacket* aPacket, const void* aParent)
    2240             : {
    2241           0 :   Layer::DumpPacket(aPacket, aParent);
    2242           0 : }
    2243             : 
    2244           0 : CanvasLayer::CanvasLayer(LayerManager* aManager, void* aImplData)
    2245             :   : Layer(aManager, aImplData)
    2246             :   , mPreTransCallback(nullptr)
    2247             :   , mPreTransCallbackData(nullptr)
    2248             :   , mPostTransCallback(nullptr)
    2249             :   , mPostTransCallbackData(nullptr)
    2250             :   , mSamplingFilter(gfx::SamplingFilter::GOOD)
    2251           0 :   , mDirty(false)
    2252           0 : {}
    2253             : 
    2254             : CanvasLayer::~CanvasLayer() = default;
    2255             : 
    2256             : void
    2257           0 : CanvasLayer::PrintInfo(std::stringstream& aStream, const char* aPrefix)
    2258             : {
    2259           0 :   Layer::PrintInfo(aStream, aPrefix);
    2260           0 :   if (mSamplingFilter != SamplingFilter::GOOD) {
    2261           0 :     AppendToString(aStream, mSamplingFilter, " [filter=", "]");
    2262             :   }
    2263           0 : }
    2264             : 
    2265             : // This help function is used to assign the correct enum value
    2266             : // to the packet
    2267             : static void
    2268           0 : DumpFilter(layerscope::LayersPacket::Layer* aLayer,
    2269             :            const SamplingFilter& aSamplingFilter)
    2270             : {
    2271             :   using namespace layerscope;
    2272           0 :   switch (aSamplingFilter) {
    2273             :     case SamplingFilter::GOOD:
    2274           0 :       aLayer->set_filter(LayersPacket::Layer::FILTER_GOOD);
    2275           0 :       break;
    2276             :     case SamplingFilter::LINEAR:
    2277           0 :       aLayer->set_filter(LayersPacket::Layer::FILTER_LINEAR);
    2278           0 :       break;
    2279             :     case SamplingFilter::POINT:
    2280           0 :       aLayer->set_filter(LayersPacket::Layer::FILTER_POINT);
    2281           0 :       break;
    2282             :     default:
    2283             :       // ignore it
    2284           0 :       break;
    2285             :   }
    2286           0 : }
    2287             : 
    2288             : void
    2289           0 : CanvasLayer::DumpPacket(layerscope::LayersPacket* aPacket, const void* aParent)
    2290             : {
    2291           0 :   Layer::DumpPacket(aPacket, aParent);
    2292             :   // Get this layer data
    2293             :   using namespace layerscope;
    2294           0 :   LayersPacket::Layer* layer = aPacket->mutable_layer(aPacket->layer_size()-1);
    2295           0 :   layer->set_type(LayersPacket::Layer::CanvasLayer);
    2296           0 :   DumpFilter(layer, mSamplingFilter);
    2297           0 : }
    2298             : 
    2299             : void
    2300           0 : ImageLayer::PrintInfo(std::stringstream& aStream, const char* aPrefix)
    2301             : {
    2302           0 :   Layer::PrintInfo(aStream, aPrefix);
    2303           0 :   if (mSamplingFilter != SamplingFilter::GOOD) {
    2304           0 :     AppendToString(aStream, mSamplingFilter, " [filter=", "]");
    2305             :   }
    2306           0 : }
    2307             : 
    2308             : void
    2309           0 : ImageLayer::DumpPacket(layerscope::LayersPacket* aPacket, const void* aParent)
    2310             : {
    2311           0 :   Layer::DumpPacket(aPacket, aParent);
    2312             :   // Get this layer data
    2313             :   using namespace layerscope;
    2314           0 :   LayersPacket::Layer* layer = aPacket->mutable_layer(aPacket->layer_size()-1);
    2315           0 :   layer->set_type(LayersPacket::Layer::ImageLayer);
    2316           0 :   DumpFilter(layer, mSamplingFilter);
    2317           0 : }
    2318             : 
    2319             : void
    2320           0 : RefLayer::PrintInfo(std::stringstream& aStream, const char* aPrefix)
    2321             : {
    2322           0 :   ContainerLayer::PrintInfo(aStream, aPrefix);
    2323           0 :   if (0 != mId) {
    2324           0 :     AppendToString(aStream, mId, " [id=", "]");
    2325             :   }
    2326           0 : }
    2327             : 
    2328             : void
    2329           0 : RefLayer::DumpPacket(layerscope::LayersPacket* aPacket, const void* aParent)
    2330             : {
    2331           0 :   Layer::DumpPacket(aPacket, aParent);
    2332             :   // Get this layer data
    2333             :   using namespace layerscope;
    2334           0 :   LayersPacket::Layer* layer = aPacket->mutable_layer(aPacket->layer_size()-1);
    2335           0 :   layer->set_type(LayersPacket::Layer::RefLayer);
    2336           0 :   layer->set_refid(mId);
    2337           0 : }
    2338             : 
    2339             : void
    2340           0 : ReadbackLayer::PrintInfo(std::stringstream& aStream, const char* aPrefix)
    2341             : {
    2342           0 :   Layer::PrintInfo(aStream, aPrefix);
    2343           0 :   AppendToString(aStream, mSize, " [size=", "]");
    2344           0 :   if (mBackgroundLayer) {
    2345           0 :     AppendToString(aStream, mBackgroundLayer, " [backgroundLayer=", "]");
    2346           0 :     AppendToString(aStream, mBackgroundLayerOffset, " [backgroundOffset=", "]");
    2347           0 :   } else if (mBackgroundColor.a == 1.f) {
    2348           0 :     AppendToString(aStream, mBackgroundColor, " [backgroundColor=", "]");
    2349             :   } else {
    2350           0 :     aStream << " [nobackground]";
    2351             :   }
    2352           0 : }
    2353             : 
    2354             : void
    2355           0 : ReadbackLayer::DumpPacket(layerscope::LayersPacket* aPacket, const void* aParent)
    2356             : {
    2357           0 :   Layer::DumpPacket(aPacket, aParent);
    2358             :   // Get this layer data
    2359             :   using namespace layerscope;
    2360           0 :   LayersPacket::Layer* layer = aPacket->mutable_layer(aPacket->layer_size()-1);
    2361           0 :   layer->set_type(LayersPacket::Layer::ReadbackLayer);
    2362           0 :   LayersPacket::Layer::Size* size = layer->mutable_size();
    2363           0 :   size->set_w(mSize.width);
    2364           0 :   size->set_h(mSize.height);
    2365           0 : }
    2366             : 
    2367             : //--------------------------------------------------
    2368             : // LayerManager
    2369             : 
    2370             : void
    2371           0 : LayerManager::Dump(std::stringstream& aStream, const char* aPrefix,
    2372             :                    bool aDumpHtml, bool aSorted)
    2373             : {
    2374             : #ifdef MOZ_DUMP_PAINTING
    2375           0 :   if (aDumpHtml) {
    2376           0 :     aStream << "<ul><li>";
    2377             :   }
    2378             : #endif
    2379           0 :   DumpSelf(aStream, aPrefix, aSorted);
    2380             : 
    2381           0 :   nsAutoCString pfx(aPrefix);
    2382           0 :   pfx += "  ";
    2383           0 :   if (!GetRoot()) {
    2384           0 :     aStream << nsPrintfCString("%s(null)", pfx.get()).get();
    2385           0 :     if (aDumpHtml) {
    2386           0 :       aStream << "</li></ul>";
    2387             :     }
    2388           0 :     return;
    2389             :   }
    2390             : 
    2391           0 :   if (aDumpHtml) {
    2392           0 :     aStream << "<ul>";
    2393             :   }
    2394           0 :   GetRoot()->Dump(aStream, pfx.get(), aDumpHtml, aSorted);
    2395           0 :   if (aDumpHtml) {
    2396           0 :     aStream << "</ul></li></ul>";
    2397             :   }
    2398           0 :   aStream << "\n";
    2399             : }
    2400             : 
    2401             : void
    2402           0 : LayerManager::DumpSelf(std::stringstream& aStream, const char* aPrefix, bool aSorted)
    2403             : {
    2404           0 :   PrintInfo(aStream, aPrefix);
    2405           0 :   aStream << " --- in " << (aSorted ? "3D-sorted rendering order" : "content order");
    2406           0 :   aStream << "\n";
    2407           0 : }
    2408             : 
    2409             : void
    2410           0 : LayerManager::Dump(bool aSorted)
    2411             : {
    2412           0 :   std::stringstream ss;
    2413           0 :   Dump(ss, "", false, aSorted);
    2414           0 :   print_stderr(ss);
    2415           0 : }
    2416             : 
    2417             : void
    2418           0 : LayerManager::Dump(layerscope::LayersPacket* aPacket)
    2419             : {
    2420           0 :   DumpPacket(aPacket);
    2421             : 
    2422           0 :   if (GetRoot()) {
    2423           0 :     GetRoot()->Dump(aPacket, this);
    2424             :   }
    2425           0 : }
    2426             : 
    2427             : void
    2428         459 : LayerManager::Log(const char* aPrefix)
    2429             : {
    2430         459 :   if (!IsLogEnabled())
    2431         918 :     return;
    2432             : 
    2433           0 :   LogSelf(aPrefix);
    2434             : 
    2435           0 :   nsAutoCString pfx(aPrefix);
    2436           0 :   pfx += "  ";
    2437           0 :   if (!GetRoot()) {
    2438           0 :     MOZ_LAYERS_LOG(("%s(null)", pfx.get()));
    2439           0 :     return;
    2440             :   }
    2441             : 
    2442           0 :   GetRoot()->Log(pfx.get());
    2443             : }
    2444             : 
    2445             : void
    2446           0 : LayerManager::LogSelf(const char* aPrefix)
    2447             : {
    2448           0 :   nsAutoCString str;
    2449           0 :   std::stringstream ss;
    2450           0 :   PrintInfo(ss, aPrefix);
    2451           0 :   MOZ_LAYERS_LOG(("%s", ss.str().c_str()));
    2452           0 : }
    2453             : 
    2454             : void
    2455           0 : LayerManager::PrintInfo(std::stringstream& aStream, const char* aPrefix)
    2456             : {
    2457           0 :   aStream << aPrefix << nsPrintfCString("%sLayerManager (0x%p)", Name(), this).get();
    2458           0 : }
    2459             : 
    2460             : void
    2461           0 : LayerManager::DumpPacket(layerscope::LayersPacket* aPacket)
    2462             : {
    2463             :   using namespace layerscope;
    2464             :   // Add a new layer data (LayerManager)
    2465           0 :   LayersPacket::Layer* layer = aPacket->add_layer();
    2466           0 :   layer->set_type(LayersPacket::Layer::LayerManager);
    2467           0 :   layer->set_ptr(reinterpret_cast<uint64_t>(this));
    2468             :   // Layer Tree Root
    2469           0 :   layer->set_parentptr(0);
    2470           0 : }
    2471             : 
    2472             : void
    2473           0 : LayerManager::TrackDisplayItemLayer(RefPtr<DisplayItemLayer> aLayer)
    2474             : {
    2475           0 :   mDisplayItemLayers.AppendElement(aLayer);
    2476           0 : }
    2477             : 
    2478             : void
    2479          48 : LayerManager::ClearDisplayItemLayers()
    2480             : {
    2481          48 :   for (uint32_t i = 0; i < mDisplayItemLayers.Length(); i++) {
    2482           0 :     mDisplayItemLayers[i]->EndTransaction();
    2483             :   }
    2484             : 
    2485          48 :   mDisplayItemLayers.Clear();
    2486          48 : }
    2487             : 
    2488             : /*static*/ bool
    2489         459 : LayerManager::IsLogEnabled()
    2490             : {
    2491         459 :   return MOZ_LOG_TEST(GetLog(), LogLevel::Debug);
    2492             : }
    2493             : 
    2494             : void
    2495           0 : LayerManager::SetPendingScrollUpdateForNextTransaction(FrameMetrics::ViewID aScrollId,
    2496             :                                                        const ScrollUpdateInfo& aUpdateInfo)
    2497             : {
    2498           0 :   mPendingScrollUpdates[aScrollId] = aUpdateInfo;
    2499           0 : }
    2500             : 
    2501             : Maybe<ScrollUpdateInfo>
    2502          28 : LayerManager::GetPendingScrollInfoUpdate(FrameMetrics::ViewID aScrollId)
    2503             : {
    2504          28 :   auto it = mPendingScrollUpdates.find(aScrollId);
    2505          28 :   if (it != mPendingScrollUpdates.end()) {
    2506           0 :     return Some(it->second);
    2507             :   }
    2508          28 :   return Nothing();
    2509             : }
    2510             : 
    2511             : void
    2512         214 : LayerManager::ClearPendingScrollInfoUpdate()
    2513             : {
    2514         214 :   mPendingScrollUpdates.clear();
    2515         214 : }
    2516             : 
    2517             : void
    2518           0 : PrintInfo(std::stringstream& aStream, HostLayer* aLayerComposite)
    2519             : {
    2520           0 :   if (!aLayerComposite) {
    2521           0 :     return;
    2522             :   }
    2523           0 :   if (const Maybe<ParentLayerIntRect>& clipRect = aLayerComposite->GetShadowClipRect()) {
    2524           0 :     AppendToString(aStream, *clipRect, " [shadow-clip=", "]");
    2525             :   }
    2526           0 :   if (!aLayerComposite->GetShadowBaseTransform().IsIdentity()) {
    2527           0 :     AppendToString(aStream, aLayerComposite->GetShadowBaseTransform(), " [shadow-transform=", "]");
    2528             :   }
    2529           0 :   if (!aLayerComposite->GetShadowVisibleRegion().IsEmpty()) {
    2530           0 :     AppendToString(aStream, aLayerComposite->GetShadowVisibleRegion().ToUnknownRegion(), " [shadow-visible=", "]");
    2531             :   }
    2532             : }
    2533             : 
    2534             : void
    2535          84 : SetAntialiasingFlags(Layer* aLayer, DrawTarget* aTarget)
    2536             : {
    2537          84 :   bool permitSubpixelAA = !(aLayer->GetContentFlags() & Layer::CONTENT_DISABLE_SUBPIXEL_AA);
    2538          84 :   if (aTarget->IsCurrentGroupOpaque()) {
    2539          39 :     aTarget->SetPermitSubpixelAA(permitSubpixelAA);
    2540          39 :     return;
    2541             :   }
    2542             : 
    2543          45 :   const IntRect& bounds = aLayer->GetVisibleRegion().ToUnknownRegion().GetBounds();
    2544         135 :   gfx::Rect transformedBounds = aTarget->GetTransform().TransformBounds(gfx::Rect(Float(bounds.x), Float(bounds.y),
    2545         135 :                                                                                   Float(bounds.width), Float(bounds.height)));
    2546          45 :   transformedBounds.RoundOut();
    2547          45 :   IntRect intTransformedBounds;
    2548          45 :   transformedBounds.ToIntRect(&intTransformedBounds);
    2549          90 :   permitSubpixelAA &= !(aLayer->GetContentFlags() & Layer::CONTENT_COMPONENT_ALPHA) ||
    2550          45 :                       aTarget->GetOpaqueRect().Contains(intTransformedBounds);
    2551          45 :   aTarget->SetPermitSubpixelAA(permitSubpixelAA);
    2552             : }
    2553             : 
    2554             : IntRect
    2555          48 : ToOutsideIntRect(const gfxRect &aRect)
    2556             : {
    2557          48 :   return IntRect::RoundOut(aRect.x, aRect.y, aRect.width, aRect.height);
    2558             : }
    2559             : 
    2560           0 : TextLayer::TextLayer(LayerManager* aManager, void* aImplData)
    2561           0 :   : Layer(aManager, aImplData)
    2562           0 : {}
    2563             : 
    2564           0 : TextLayer::~TextLayer()
    2565           0 : {}
    2566             : 
    2567             : void
    2568           0 : TextLayer::SetGlyphs(nsTArray<GlyphArray>&& aGlyphs)
    2569             : {
    2570           0 :   MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) Glyphs", this));
    2571           0 :   mGlyphs = Move(aGlyphs);
    2572           0 :   Mutated();
    2573           0 : }
    2574             : 
    2575             : } // namespace layers
    2576             : } // namespace mozilla

Generated by: LCOV version 1.13