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