1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
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/. */
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 "ReadbackLayer.h" // for ReadbackLayer
17 #include "gfxPlatform.h" // for gfxPlatform
19 #include "gfxUtils.h" // for gfxUtils, etc
20 #include "gfx2DGlue.h"
21 #include "mozilla/DebugOnly.h" // for DebugOnly
22 #include "mozilla/Telemetry.h" // for Accumulate
23 #include "mozilla/dom/AnimationPlayer.h" // for ComputedTimingFunction
24 #include "mozilla/gfx/2D.h" // for DrawTarget
25 #include "mozilla/gfx/BaseSize.h" // for BaseSize
26 #include "mozilla/gfx/Matrix.h" // for Matrix4x4
27 #include "mozilla/layers/Compositor.h" // for Compositor
28 #include "mozilla/layers/CompositorTypes.h"
29 #include "mozilla/layers/LayerManagerComposite.h" // for LayerComposite
30 #include "mozilla/layers/LayerMetricsWrapper.h" // for LayerMetricsWrapper
31 #include "mozilla/layers/LayersMessages.h" // for TransformFunction, etc
32 #include "nsAString.h"
33 #include "nsCSSValue.h" // for nsCSSValue::Array, etc
34 #include "nsPrintfCString.h" // for nsPrintfCString
35 #include "nsStyleStruct.h" // for nsTimingFunction, etc
36 #include "protobuf/LayerScopePacket.pb.h"
38 uint8_t gLayerManagerLayerBuilder
;
44 FILEOrDefault(FILE* aFile
)
46 return aFile
? aFile
: stderr
;
49 typedef FrameMetrics::ViewID ViewID
;
50 const ViewID
FrameMetrics::NULL_SCROLL_ID
= 0;
51 const FrameMetrics
FrameMetrics::sNullMetrics
;
53 using namespace mozilla::gfx
;
55 //--------------------------------------------------
58 LayerManager::GetRootScrollableLayerId()
61 return FrameMetrics::NULL_SCROLL_ID
;
64 nsTArray
<LayerMetricsWrapper
> queue
;
65 queue
.AppendElement(LayerMetricsWrapper(mRoot
));
66 while (queue
.Length()) {
67 LayerMetricsWrapper layer
= queue
[0];
68 queue
.RemoveElementAt(0);
70 const FrameMetrics
& frameMetrics
= layer
.Metrics();
71 if (frameMetrics
.IsScrollable()) {
72 return frameMetrics
.GetScrollId();
75 LayerMetricsWrapper child
= layer
.GetFirstChild();
77 queue
.AppendElement(child
);
78 child
= child
.GetNextSibling();
82 return FrameMetrics::NULL_SCROLL_ID
;
86 LayerManager::GetRootScrollableLayers(nsTArray
<Layer
*>& aArray
)
92 FrameMetrics::ViewID rootScrollableId
= GetRootScrollableLayerId();
93 if (rootScrollableId
== FrameMetrics::NULL_SCROLL_ID
) {
94 aArray
.AppendElement(mRoot
);
98 nsTArray
<Layer
*> queue
;
99 queue
.AppendElement(mRoot
);
100 while (queue
.Length()) {
101 Layer
* layer
= queue
[0];
102 queue
.RemoveElementAt(0);
104 if (LayerMetricsWrapper::TopmostScrollableMetrics(layer
).GetScrollId() == rootScrollableId
) {
105 aArray
.AppendElement(layer
);
109 for (Layer
* child
= layer
->GetFirstChild(); child
; child
= child
->GetNextSibling()) {
110 queue
.AppendElement(child
);
116 LayerManager::GetScrollableLayers(nsTArray
<Layer
*>& aArray
)
122 nsTArray
<Layer
*> queue
;
123 queue
.AppendElement(mRoot
);
124 while (!queue
.IsEmpty()) {
125 Layer
* layer
= queue
.LastElement();
126 queue
.RemoveElementAt(queue
.Length() - 1);
128 if (layer
->HasScrollableFrameMetrics()) {
129 aArray
.AppendElement(layer
);
133 for (Layer
* child
= layer
->GetFirstChild(); child
; child
= child
->GetNextSibling()) {
134 queue
.AppendElement(child
);
139 TemporaryRef
<DrawTarget
>
140 LayerManager::CreateOptimalDrawTarget(const gfx::IntSize
&aSize
,
141 SurfaceFormat aFormat
)
143 return gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(aSize
,
147 TemporaryRef
<DrawTarget
>
148 LayerManager::CreateOptimalMaskDrawTarget(const gfx::IntSize
&aSize
)
150 return CreateOptimalDrawTarget(aSize
, SurfaceFormat::A8
);
153 TemporaryRef
<DrawTarget
>
154 LayerManager::CreateDrawTarget(const IntSize
&aSize
,
155 SurfaceFormat aFormat
)
157 return gfxPlatform::GetPlatform()->
158 CreateOffscreenCanvasDrawTarget(aSize
, aFormat
);
163 LayerManager::Mutated(Layer
* aLayer
)
168 already_AddRefed
<ImageContainer
>
169 LayerManager::CreateImageContainer()
171 nsRefPtr
<ImageContainer
> container
= new ImageContainer(ImageContainer::DISABLE_ASYNC
);
172 return container
.forget();
175 already_AddRefed
<ImageContainer
>
176 LayerManager::CreateAsynchronousImageContainer()
178 nsRefPtr
<ImageContainer
> container
= new ImageContainer(ImageContainer::ENABLE_ASYNC
);
179 return container
.forget();
183 LayerManager::AreComponentAlphaLayersEnabled()
185 return gfxPrefs::ComponentAlphaEnabled();
188 //--------------------------------------------------
191 Layer::Layer(LayerManager
* aManager
, void* aImplData
) :
194 mNextSibling(nullptr),
195 mPrevSibling(nullptr),
196 mImplData(aImplData
),
201 mMixBlendMode(CompositionOp::OP_OVER
),
202 mForceIsolatedGroup(false),
205 mUseTileSourceRect(false),
206 mIsFixedPosition(false),
207 mMargins(0, 0, 0, 0),
208 mStickyPositionData(nullptr),
209 mScrollbarTargetId(FrameMetrics::NULL_SCROLL_ID
),
210 mScrollbarDirection(ScrollDirection::NONE
),
212 mAnimationGeneration(0)
219 Layer::AddAnimation()
221 MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) AddAnimation", this));
223 MOZ_ASSERT(!mPendingAnimations
, "should have called ClearAnimations first");
225 Animation
* anim
= mAnimations
.AppendElement();
232 Layer::ClearAnimations()
234 mPendingAnimations
= nullptr;
236 if (mAnimations
.IsEmpty() && mAnimationData
.IsEmpty()) {
240 MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) ClearAnimations", this));
242 mAnimationData
.Clear();
247 Layer::AddAnimationForNextTransaction()
249 MOZ_ASSERT(mPendingAnimations
,
250 "should have called ClearAnimationsForNextTransaction first");
252 Animation
* anim
= mPendingAnimations
->AppendElement();
258 Layer::ClearAnimationsForNextTransaction()
260 // Ensure we have a non-null mPendingAnimations to mark a future clear.
261 if (!mPendingAnimations
) {
262 mPendingAnimations
= new AnimationArray
;
265 mPendingAnimations
->Clear();
268 static nsCSSValueSharedList
*
269 CreateCSSValueList(const InfallibleTArray
<TransformFunction
>& aFunctions
)
271 nsAutoPtr
<nsCSSValueList
> result
;
272 nsCSSValueList
** resultTail
= getter_Transfers(result
);
273 for (uint32_t i
= 0; i
< aFunctions
.Length(); i
++) {
274 nsRefPtr
<nsCSSValue::Array
> arr
;
275 switch (aFunctions
[i
].type()) {
276 case TransformFunction::TRotationX
:
278 float theta
= aFunctions
[i
].get_RotationX().radians();
279 arr
= StyleAnimationValue::AppendTransformFunction(eCSSKeyword_rotatex
,
281 arr
->Item(1).SetFloatValue(theta
, eCSSUnit_Radian
);
284 case TransformFunction::TRotationY
:
286 float theta
= aFunctions
[i
].get_RotationY().radians();
287 arr
= StyleAnimationValue::AppendTransformFunction(eCSSKeyword_rotatey
,
289 arr
->Item(1).SetFloatValue(theta
, eCSSUnit_Radian
);
292 case TransformFunction::TRotationZ
:
294 float theta
= aFunctions
[i
].get_RotationZ().radians();
295 arr
= StyleAnimationValue::AppendTransformFunction(eCSSKeyword_rotatez
,
297 arr
->Item(1).SetFloatValue(theta
, eCSSUnit_Radian
);
300 case TransformFunction::TRotation
:
302 float theta
= aFunctions
[i
].get_Rotation().radians();
303 arr
= StyleAnimationValue::AppendTransformFunction(eCSSKeyword_rotate
,
305 arr
->Item(1).SetFloatValue(theta
, eCSSUnit_Radian
);
308 case TransformFunction::TRotation3D
:
310 float x
= aFunctions
[i
].get_Rotation3D().x();
311 float y
= aFunctions
[i
].get_Rotation3D().y();
312 float z
= aFunctions
[i
].get_Rotation3D().z();
313 float theta
= aFunctions
[i
].get_Rotation3D().radians();
315 StyleAnimationValue::AppendTransformFunction(eCSSKeyword_rotate3d
,
317 arr
->Item(1).SetFloatValue(x
, eCSSUnit_Number
);
318 arr
->Item(2).SetFloatValue(y
, eCSSUnit_Number
);
319 arr
->Item(3).SetFloatValue(z
, eCSSUnit_Number
);
320 arr
->Item(4).SetFloatValue(theta
, eCSSUnit_Radian
);
323 case TransformFunction::TScale
:
326 StyleAnimationValue::AppendTransformFunction(eCSSKeyword_scale3d
,
328 arr
->Item(1).SetFloatValue(aFunctions
[i
].get_Scale().x(), eCSSUnit_Number
);
329 arr
->Item(2).SetFloatValue(aFunctions
[i
].get_Scale().y(), eCSSUnit_Number
);
330 arr
->Item(3).SetFloatValue(aFunctions
[i
].get_Scale().z(), eCSSUnit_Number
);
333 case TransformFunction::TTranslation
:
336 StyleAnimationValue::AppendTransformFunction(eCSSKeyword_translate3d
,
338 arr
->Item(1).SetFloatValue(aFunctions
[i
].get_Translation().x(), eCSSUnit_Pixel
);
339 arr
->Item(2).SetFloatValue(aFunctions
[i
].get_Translation().y(), eCSSUnit_Pixel
);
340 arr
->Item(3).SetFloatValue(aFunctions
[i
].get_Translation().z(), eCSSUnit_Pixel
);
343 case TransformFunction::TSkewX
:
345 float x
= aFunctions
[i
].get_SkewX().x();
346 arr
= StyleAnimationValue::AppendTransformFunction(eCSSKeyword_skewx
,
348 arr
->Item(1).SetFloatValue(x
, eCSSUnit_Radian
);
351 case TransformFunction::TSkewY
:
353 float y
= aFunctions
[i
].get_SkewY().y();
354 arr
= StyleAnimationValue::AppendTransformFunction(eCSSKeyword_skewy
,
356 arr
->Item(1).SetFloatValue(y
, eCSSUnit_Radian
);
359 case TransformFunction::TSkew
:
361 arr
= StyleAnimationValue::AppendTransformFunction(eCSSKeyword_skew
,
363 arr
->Item(1).SetFloatValue(aFunctions
[i
].get_Skew().x(), eCSSUnit_Radian
);
364 arr
->Item(2).SetFloatValue(aFunctions
[i
].get_Skew().y(), eCSSUnit_Radian
);
367 case TransformFunction::TTransformMatrix
:
370 StyleAnimationValue::AppendTransformFunction(eCSSKeyword_matrix3d
,
372 const gfx::Matrix4x4
& matrix
= aFunctions
[i
].get_TransformMatrix().value();
373 arr
->Item(1).SetFloatValue(matrix
._11
, eCSSUnit_Number
);
374 arr
->Item(2).SetFloatValue(matrix
._12
, eCSSUnit_Number
);
375 arr
->Item(3).SetFloatValue(matrix
._13
, eCSSUnit_Number
);
376 arr
->Item(4).SetFloatValue(matrix
._14
, eCSSUnit_Number
);
377 arr
->Item(5).SetFloatValue(matrix
._21
, eCSSUnit_Number
);
378 arr
->Item(6).SetFloatValue(matrix
._22
, eCSSUnit_Number
);
379 arr
->Item(7).SetFloatValue(matrix
._23
, eCSSUnit_Number
);
380 arr
->Item(8).SetFloatValue(matrix
._24
, eCSSUnit_Number
);
381 arr
->Item(9).SetFloatValue(matrix
._31
, eCSSUnit_Number
);
382 arr
->Item(10).SetFloatValue(matrix
._32
, eCSSUnit_Number
);
383 arr
->Item(11).SetFloatValue(matrix
._33
, eCSSUnit_Number
);
384 arr
->Item(12).SetFloatValue(matrix
._34
, eCSSUnit_Number
);
385 arr
->Item(13).SetFloatValue(matrix
._41
, eCSSUnit_Number
);
386 arr
->Item(14).SetFloatValue(matrix
._42
, eCSSUnit_Number
);
387 arr
->Item(15).SetFloatValue(matrix
._43
, eCSSUnit_Number
);
388 arr
->Item(16).SetFloatValue(matrix
._44
, eCSSUnit_Number
);
391 case TransformFunction::TPerspective
:
393 float perspective
= aFunctions
[i
].get_Perspective().value();
395 StyleAnimationValue::AppendTransformFunction(eCSSKeyword_perspective
,
397 arr
->Item(1).SetFloatValue(perspective
, eCSSUnit_Pixel
);
401 NS_ASSERTION(false, "All functions should be implemented?");
404 if (aFunctions
.Length() == 0) {
405 result
= new nsCSSValueList();
406 result
->mValue
.SetNoneValue();
408 return new nsCSSValueSharedList(result
.forget());
412 Layer::SetAnimations(const AnimationArray
& aAnimations
)
414 MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) SetAnimations", this));
416 mAnimations
= aAnimations
;
417 mAnimationData
.Clear();
418 for (uint32_t i
= 0; i
< mAnimations
.Length(); i
++) {
419 AnimData
* data
= mAnimationData
.AppendElement();
420 InfallibleTArray
<nsAutoPtr
<ComputedTimingFunction
> >& functions
=
422 const InfallibleTArray
<AnimationSegment
>& segments
=
423 mAnimations
.ElementAt(i
).segments();
424 for (uint32_t j
= 0; j
< segments
.Length(); j
++) {
425 TimingFunction tf
= segments
.ElementAt(j
).sampleFn();
426 ComputedTimingFunction
* ctf
= new ComputedTimingFunction();
428 case TimingFunction::TCubicBezierFunction
: {
429 CubicBezierFunction cbf
= tf
.get_CubicBezierFunction();
430 ctf
->Init(nsTimingFunction(cbf
.x1(), cbf
.y1(), cbf
.x2(), cbf
.y2()));
434 NS_ASSERTION(tf
.type() == TimingFunction::TStepFunction
,
435 "Function must be bezier or step");
436 StepFunction sf
= tf
.get_StepFunction();
437 nsTimingFunction::Type type
= sf
.type() == 1 ? nsTimingFunction::StepStart
438 : nsTimingFunction::StepEnd
;
439 ctf
->Init(nsTimingFunction(type
, sf
.steps()));
443 functions
.AppendElement(ctf
);
446 // Precompute the StyleAnimationValues that we need if this is a transform
448 InfallibleTArray
<StyleAnimationValue
>& startValues
= data
->mStartValues
;
449 InfallibleTArray
<StyleAnimationValue
>& endValues
= data
->mEndValues
;
450 for (uint32_t j
= 0; j
< mAnimations
[i
].segments().Length(); j
++) {
451 const AnimationSegment
& segment
= mAnimations
[i
].segments()[j
];
452 StyleAnimationValue
* startValue
= startValues
.AppendElement();
453 StyleAnimationValue
* endValue
= endValues
.AppendElement();
454 if (segment
.endState().type() == Animatable::TArrayOfTransformFunction
) {
455 const InfallibleTArray
<TransformFunction
>& startFunctions
=
456 segment
.startState().get_ArrayOfTransformFunction();
457 startValue
->SetTransformValue(CreateCSSValueList(startFunctions
));
459 const InfallibleTArray
<TransformFunction
>& endFunctions
=
460 segment
.endState().get_ArrayOfTransformFunction();
461 endValue
->SetTransformValue(CreateCSSValueList(endFunctions
));
463 NS_ASSERTION(segment
.endState().type() == Animatable::Tfloat
,
464 "Unknown Animatable type");
465 startValue
->SetFloatValue(segment
.startState().get_float());
466 endValue
->SetFloatValue(segment
.endState().get_float());
475 Layer::StartPendingAnimations(const TimeStamp
& aReadyTime
)
477 bool updated
= false;
478 for (size_t animIdx
= 0, animEnd
= mAnimations
.Length();
479 animIdx
< animEnd
; animIdx
++) {
480 Animation
& anim
= mAnimations
[animIdx
];
481 if (anim
.startTime().IsNull()) {
482 anim
.startTime() = aReadyTime
- anim
.initialCurrentTime();
491 for (Layer
* child
= GetFirstChild(); child
; child
= child
->GetNextSibling()) {
492 child
->StartPendingAnimations(aReadyTime
);
497 Layer::SetAsyncPanZoomController(uint32_t aIndex
, AsyncPanZoomController
*controller
)
499 MOZ_ASSERT(aIndex
< GetFrameMetricsCount());
500 mApzcs
[aIndex
] = controller
;
503 AsyncPanZoomController
*
504 Layer::GetAsyncPanZoomController(uint32_t aIndex
) const
506 MOZ_ASSERT(aIndex
< GetFrameMetricsCount());
508 if (mApzcs
[aIndex
]) {
509 MOZ_ASSERT(GetFrameMetrics(aIndex
).IsScrollable());
512 return mApzcs
[aIndex
];
516 Layer::FrameMetricsChanged()
518 mApzcs
.SetLength(GetFrameMetricsCount());
522 Layer::ApplyPendingUpdatesToSubtree()
524 ApplyPendingUpdatesForThisTransaction();
525 for (Layer
* child
= GetFirstChild(); child
; child
= child
->GetNextSibling()) {
526 child
->ApplyPendingUpdatesToSubtree();
531 Layer::CanUseOpaqueSurface()
533 // If the visible content in the layer is opaque, there is no need
534 // for an alpha channel.
535 if (GetContentFlags() & CONTENT_OPAQUE
)
537 // Also, if this layer is the bottommost layer in a container which
538 // doesn't need an alpha channel, we can use an opaque surface for this
539 // layer too. Any transparent areas must be covered by something else
541 ContainerLayer
* parent
= GetParent();
542 return parent
&& parent
->GetFirstChild() == this &&
543 parent
->CanUseOpaqueSurface();
546 // NB: eventually these methods will be defined unconditionally, and
547 // can be moved into Layers.h
549 Layer::GetEffectiveClipRect()
551 if (LayerComposite
* shadow
= AsLayerComposite()) {
552 return shadow
->GetShadowClipRect();
554 return GetClipRect();
558 Layer::GetEffectiveVisibleRegion()
560 if (LayerComposite
* shadow
= AsLayerComposite()) {
561 return shadow
->GetShadowVisibleRegion();
563 return GetVisibleRegion();
567 Layer::SnapTransformTranslation(const Matrix4x4
& aTransform
,
568 Matrix
* aResidualTransform
)
570 if (aResidualTransform
) {
571 *aResidualTransform
= Matrix();
576 if (mManager
->IsSnappingEffectiveTransforms() &&
577 aTransform
.Is2D(&matrix2D
) &&
578 !matrix2D
.HasNonTranslation() &&
579 matrix2D
.HasNonIntegerTranslation()) {
580 IntPoint snappedTranslation
= RoundedToInt(matrix2D
.GetTranslation());
581 Matrix snappedMatrix
= Matrix::Translation(snappedTranslation
.x
,
582 snappedTranslation
.y
);
583 result
= Matrix4x4::From2D(snappedMatrix
);
584 if (aResidualTransform
) {
585 // set aResidualTransform so that aResidual * snappedMatrix == matrix2D.
586 // (I.e., appying snappedMatrix after aResidualTransform gives the
588 *aResidualTransform
=
589 Matrix::Translation(matrix2D
._31
- snappedTranslation
.x
,
590 matrix2D
._32
- snappedTranslation
.y
);
599 Layer::SnapTransform(const Matrix4x4
& aTransform
,
600 const gfxRect
& aSnapRect
,
601 Matrix
* aResidualTransform
)
603 if (aResidualTransform
) {
604 *aResidualTransform
= Matrix();
609 if (mManager
->IsSnappingEffectiveTransforms() &&
610 aTransform
.Is2D(&matrix2D
) &&
611 gfx::Size(1.0, 1.0) <= ToSize(aSnapRect
.Size()) &&
612 matrix2D
.PreservesAxisAlignedRectangles()) {
613 IntPoint transformedTopLeft
= RoundedToInt(matrix2D
* ToPoint(aSnapRect
.TopLeft()));
614 IntPoint transformedTopRight
= RoundedToInt(matrix2D
* ToPoint(aSnapRect
.TopRight()));
615 IntPoint transformedBottomRight
= RoundedToInt(matrix2D
* ToPoint(aSnapRect
.BottomRight()));
617 Matrix snappedMatrix
= gfxUtils::TransformRectToRect(aSnapRect
,
618 transformedTopLeft
, transformedTopRight
, transformedBottomRight
);
620 result
= Matrix4x4::From2D(snappedMatrix
);
621 if (aResidualTransform
&& !snappedMatrix
.IsSingular()) {
622 // set aResidualTransform so that aResidual * snappedMatrix == matrix2D.
623 // (i.e., appying snappedMatrix after aResidualTransform gives the
625 Matrix snappedMatrixInverse
= snappedMatrix
;
626 snappedMatrixInverse
.Invert();
627 *aResidualTransform
= matrix2D
* snappedMatrixInverse
;
636 AncestorLayerMayChangeTransform(Layer
* aLayer
)
638 for (Layer
* l
= aLayer
; l
; l
= l
->GetParent()) {
639 if (l
->GetContentFlags() & Layer::CONTENT_MAY_CHANGE_TRANSFORM
) {
650 return !GetEffectiveTransform().Is2D(&transform2d
) ||
651 ThebesMatrix(transform2d
).HasNonIntegerTranslation() ||
652 AncestorLayerMayChangeTransform(this);
656 Layer::CalculateScissorRect(const RenderTargetIntRect
& aCurrentScissorRect
)
658 ContainerLayer
* container
= GetParent();
659 NS_ASSERTION(container
, "This can't be called on the root!");
661 // Establish initial clip rect: it's either the one passed in, or
662 // if the parent has an intermediate surface, it's the extents of that surface.
663 RenderTargetIntRect currentClip
;
664 if (container
->UseIntermediateSurface()) {
665 currentClip
.SizeTo(container
->GetIntermediateSurfaceRect().Size());
667 currentClip
= aCurrentScissorRect
;
670 if (!GetEffectiveClipRect()) {
674 const RenderTargetIntRect clipRect
= RenderTargetPixel::FromUntyped(*GetEffectiveClipRect());
675 if (clipRect
.IsEmpty()) {
676 // We might have a non-translation transform in the container so we can't
677 // use the code path below.
678 return RenderTargetIntRect(currentClip
.TopLeft(), RenderTargetIntSize(0, 0));
681 RenderTargetIntRect scissor
= clipRect
;
682 if (!container
->UseIntermediateSurface()) {
684 DebugOnly
<bool> is2D
= container
->GetEffectiveTransform().Is2D(&matrix
);
685 // See DefaultComputeEffectiveTransforms below
686 NS_ASSERTION(is2D
&& matrix
.PreservesAxisAlignedRectangles(),
687 "Non preserves axis aligned transform with clipped child should have forced intermediate surface");
688 gfx::Rect
r(scissor
.x
, scissor
.y
, scissor
.width
, scissor
.height
);
689 gfxRect trScissor
= gfx::ThebesRect(matrix
.TransformBounds(r
));
692 if (!gfxUtils::GfxRectToIntRect(trScissor
, &tmp
)) {
693 return RenderTargetIntRect(currentClip
.TopLeft(), RenderTargetIntSize(0, 0));
695 scissor
= RenderTargetPixel::FromUntyped(tmp
);
697 // Find the nearest ancestor with an intermediate surface
699 container
= container
->GetParent();
700 } while (container
&& !container
->UseIntermediateSurface());
704 scissor
.MoveBy(-container
->GetIntermediateSurfaceRect().TopLeft());
706 return currentClip
.Intersect(scissor
);
710 Layer::GetFrameMetrics(uint32_t aIndex
) const
712 MOZ_ASSERT(aIndex
< GetFrameMetricsCount());
713 return mFrameMetrics
[aIndex
];
717 Layer::HasScrollableFrameMetrics() const
719 for (uint32_t i
= 0; i
< GetFrameMetricsCount(); i
++) {
720 if (GetFrameMetrics(i
).IsScrollable()) {
728 Layer::IsScrollInfoLayer() const
730 // A scrollable container layer with no children
731 return AsContainerLayer()
732 && HasScrollableFrameMetrics()
737 Layer::GetTransform() const
739 Matrix4x4 transform
= mTransform
;
740 transform
.PostScale(GetPostXScale(), GetPostYScale(), 1.0f
);
741 if (const ContainerLayer
* c
= AsContainerLayer()) {
742 transform
.PreScale(c
->GetPreXScale(), c
->GetPreYScale(), 1.0f
);
748 Layer::GetLocalTransform()
751 if (LayerComposite
* shadow
= AsLayerComposite())
752 transform
= shadow
->GetShadowTransform();
754 transform
= mTransform
;
756 transform
.PostScale(GetPostXScale(), GetPostYScale(), 1.0f
);
757 if (ContainerLayer
* c
= AsContainerLayer()) {
758 transform
.PreScale(c
->GetPreXScale(), c
->GetPreYScale(), 1.0f
);
765 Layer::HasTransformAnimation() const
767 for (uint32_t i
= 0; i
< mAnimations
.Length(); i
++) {
768 if (mAnimations
[i
].property() == eCSSProperty_transform
) {
776 Layer::ApplyPendingUpdatesForThisTransaction()
778 if (mPendingTransform
&& *mPendingTransform
!= mTransform
) {
779 MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) PendingUpdatesForThisTransaction", this));
780 mTransform
= *mPendingTransform
;
783 mPendingTransform
= nullptr;
785 if (mPendingAnimations
) {
786 MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) PendingUpdatesForThisTransaction", this));
787 mPendingAnimations
->SwapElements(mAnimations
);
788 mPendingAnimations
= nullptr;
794 Layer::GetLocalOpacity()
796 if (LayerComposite
* shadow
= AsLayerComposite())
797 return shadow
->GetShadowOpacity();
802 Layer::GetEffectiveOpacity()
804 float opacity
= GetLocalOpacity();
805 for (ContainerLayer
* c
= GetParent(); c
&& !c
->UseIntermediateSurface();
806 c
= c
->GetParent()) {
807 opacity
*= c
->GetLocalOpacity();
813 Layer::GetEffectiveMixBlendMode()
815 if(mMixBlendMode
!= CompositionOp::OP_OVER
)
816 return mMixBlendMode
;
817 for (ContainerLayer
* c
= GetParent(); c
&& !c
->UseIntermediateSurface();
818 c
= c
->GetParent()) {
819 if(c
->mMixBlendMode
!= CompositionOp::OP_OVER
)
820 return c
->mMixBlendMode
;
823 return mMixBlendMode
;
826 gfxContext::GraphicsOperator
827 Layer::DeprecatedGetEffectiveMixBlendMode()
829 return ThebesOp(GetEffectiveMixBlendMode());
833 Layer::ComputeEffectiveTransformForMaskLayer(const Matrix4x4
& aTransformToSurface
)
836 mMaskLayer
->mEffectiveTransform
= aTransformToSurface
;
839 bool maskIs2D
= mMaskLayer
->GetTransform().CanDraw2D();
840 NS_ASSERTION(maskIs2D
, "How did we end up with a 3D transform here?!");
842 // The mask layer can have an async transform applied to it in some
843 // situations, so be sure to use its GetLocalTransform() rather than
844 // its GetTransform().
845 mMaskLayer
->mEffectiveTransform
= mMaskLayer
->GetLocalTransform() *
846 mMaskLayer
->mEffectiveTransform
;
851 Layer::TransformRectToRenderTarget(const LayerIntRect
& aRect
)
853 LayerRect
rect(aRect
);
854 RenderTargetRect quad
= RenderTargetRect::FromUnknown(
855 GetEffectiveTransform().TransformBounds(
856 LayerPixel::ToUnknown(rect
)));
860 ContainerLayer::ContainerLayer(LayerManager
* aManager
, void* aImplData
)
861 : Layer(aManager
, aImplData
),
862 mFirstChild(nullptr),
866 mInheritedXScale(1.0f
),
867 mInheritedYScale(1.0f
),
868 mPresShellResolution(1.0f
),
869 mScaleToResolution(false),
870 mUseIntermediateSurface(false),
871 mSupportsComponentAlphaChildren(false),
872 mMayHaveReadbackChild(false),
873 mChildrenChanged(false),
874 mEventRegionsOverride(EventRegionsOverride::NoOverride
)
876 mContentFlags
= 0; // Clear NO_TEXT, NO_TEXT_OVER_TRANSPARENT
879 ContainerLayer::~ContainerLayer() {}
882 ContainerLayer::InsertAfter(Layer
* aChild
, Layer
* aAfter
)
884 if(aChild
->Manager() != Manager()) {
885 NS_ERROR("Child has wrong manager");
888 if(aChild
->GetParent()) {
889 NS_ERROR("aChild already in the tree");
892 if (aChild
->GetNextSibling() || aChild
->GetPrevSibling()) {
893 NS_ERROR("aChild already has siblings?");
896 if (aAfter
&& (aAfter
->Manager() != Manager() ||
897 aAfter
->GetParent() != this))
899 NS_ERROR("aAfter is not our child");
903 aChild
->SetParent(this);
904 if (aAfter
== mLastChild
) {
908 aChild
->SetNextSibling(mFirstChild
);
910 mFirstChild
->SetPrevSibling(aChild
);
912 mFirstChild
= aChild
;
914 DidInsertChild(aChild
);
918 Layer
* next
= aAfter
->GetNextSibling();
919 aChild
->SetNextSibling(next
);
920 aChild
->SetPrevSibling(aAfter
);
922 next
->SetPrevSibling(aChild
);
924 aAfter
->SetNextSibling(aChild
);
926 DidInsertChild(aChild
);
931 ContainerLayer::RemoveChild(Layer
*aChild
)
933 if (aChild
->Manager() != Manager()) {
934 NS_ERROR("Child has wrong manager");
937 if (aChild
->GetParent() != this) {
938 NS_ERROR("aChild not our child");
942 Layer
* prev
= aChild
->GetPrevSibling();
943 Layer
* next
= aChild
->GetNextSibling();
945 prev
->SetNextSibling(next
);
947 this->mFirstChild
= next
;
950 next
->SetPrevSibling(prev
);
952 this->mLastChild
= prev
;
955 aChild
->SetNextSibling(nullptr);
956 aChild
->SetPrevSibling(nullptr);
957 aChild
->SetParent(nullptr);
959 this->DidRemoveChild(aChild
);
966 ContainerLayer::RepositionChild(Layer
* aChild
, Layer
* aAfter
)
968 if (aChild
->Manager() != Manager()) {
969 NS_ERROR("Child has wrong manager");
972 if (aChild
->GetParent() != this) {
973 NS_ERROR("aChild not our child");
976 if (aAfter
&& (aAfter
->Manager() != Manager() ||
977 aAfter
->GetParent() != this))
979 NS_ERROR("aAfter is not our child");
982 if (aChild
== aAfter
) {
983 NS_ERROR("aChild cannot be the same as aAfter");
987 Layer
* prev
= aChild
->GetPrevSibling();
988 Layer
* next
= aChild
->GetNextSibling();
989 if (prev
== aAfter
) {
990 // aChild is already in the correct position, nothing to do.
994 prev
->SetNextSibling(next
);
999 next
->SetPrevSibling(prev
);
1004 aChild
->SetPrevSibling(nullptr);
1005 aChild
->SetNextSibling(mFirstChild
);
1007 mFirstChild
->SetPrevSibling(aChild
);
1009 mFirstChild
= aChild
;
1013 Layer
* afterNext
= aAfter
->GetNextSibling();
1015 afterNext
->SetPrevSibling(aChild
);
1017 mLastChild
= aChild
;
1019 aAfter
->SetNextSibling(aChild
);
1020 aChild
->SetPrevSibling(aAfter
);
1021 aChild
->SetNextSibling(afterNext
);
1026 ContainerLayer::FillSpecificAttributes(SpecificLayerAttributes
& aAttrs
)
1028 aAttrs
= ContainerLayerAttributes(mPreXScale
, mPreYScale
,
1029 mInheritedXScale
, mInheritedYScale
,
1030 mPresShellResolution
, mScaleToResolution
,
1031 mEventRegionsOverride
,
1032 reinterpret_cast<uint64_t>(mHMDInfo
.get()));
1036 ContainerLayer::HasMultipleChildren()
1039 for (Layer
* child
= GetFirstChild(); child
; child
= child
->GetNextSibling()) {
1040 const nsIntRect
*clipRect
= child
->GetEffectiveClipRect();
1041 if (clipRect
&& clipRect
->IsEmpty())
1043 if (child
->GetVisibleRegion().IsEmpty())
1054 ContainerLayer::SortChildrenBy3DZOrder(nsTArray
<Layer
*>& aArray
)
1056 nsAutoTArray
<Layer
*, 10> toSort
;
1058 for (Layer
* l
= GetFirstChild(); l
; l
= l
->GetNextSibling()) {
1059 ContainerLayer
* container
= l
->AsContainerLayer();
1060 if (container
&& container
->GetContentFlags() & CONTENT_PRESERVE_3D
) {
1061 toSort
.AppendElement(l
);
1063 if (toSort
.Length() > 0) {
1064 SortLayersBy3DZOrder(toSort
);
1065 aArray
.MoveElementsFrom(toSort
);
1067 aArray
.AppendElement(l
);
1070 if (toSort
.Length() > 0) {
1071 SortLayersBy3DZOrder(toSort
);
1072 aArray
.MoveElementsFrom(toSort
);
1077 ContainerLayer::DefaultComputeEffectiveTransforms(const Matrix4x4
& aTransformToSurface
)
1080 Matrix4x4 idealTransform
= GetLocalTransform() * aTransformToSurface
;
1081 idealTransform
.ProjectTo2D();
1082 mEffectiveTransform
= SnapTransformTranslation(idealTransform
, &residual
);
1084 bool useIntermediateSurface
;
1085 if (GetMaskLayer() ||
1086 GetForceIsolatedGroup()) {
1087 useIntermediateSurface
= true;
1088 #ifdef MOZ_DUMP_PAINTING
1089 } else if (gfxUtils::sDumpPainting
) {
1090 useIntermediateSurface
= true;
1093 float opacity
= GetEffectiveOpacity();
1094 CompositionOp blendMode
= GetEffectiveMixBlendMode();
1095 if ((opacity
!= 1.0f
|| blendMode
!= CompositionOp::OP_OVER
) && HasMultipleChildren()) {
1096 useIntermediateSurface
= true;
1098 useIntermediateSurface
= false;
1099 gfx::Matrix contTransform
;
1100 if (!mEffectiveTransform
.Is2D(&contTransform
) ||
1101 #ifdef MOZ_GFX_OPTIMIZE_MOBILE
1102 !contTransform
.PreservesAxisAlignedRectangles()) {
1104 gfx::ThebesMatrix(contTransform
).HasNonIntegerTranslation()) {
1106 for (Layer
* child
= GetFirstChild(); child
; child
= child
->GetNextSibling()) {
1107 const nsIntRect
*clipRect
= child
->GetEffectiveClipRect();
1108 /* We can't (easily) forward our transform to children with a non-empty clip
1109 * rect since it would need to be adjusted for the transform. See
1110 * the calculations performed by CalculateScissorRect above.
1111 * Nor for a child with a mask layer.
1113 if ((clipRect
&& !clipRect
->IsEmpty() && !child
->GetVisibleRegion().IsEmpty()) ||
1114 child
->GetMaskLayer()) {
1115 useIntermediateSurface
= true;
1123 mUseIntermediateSurface
= useIntermediateSurface
&& !GetEffectiveVisibleRegion().IsEmpty();
1124 if (useIntermediateSurface
) {
1125 ComputeEffectiveTransformsForChildren(Matrix4x4::From2D(residual
));
1127 ComputeEffectiveTransformsForChildren(idealTransform
);
1130 if (idealTransform
.CanDraw2D()) {
1131 ComputeEffectiveTransformForMaskLayer(aTransformToSurface
);
1133 ComputeEffectiveTransformForMaskLayer(Matrix4x4());
1138 ContainerLayer::DefaultComputeSupportsComponentAlphaChildren(bool* aNeedsSurfaceCopy
)
1140 if (!(GetContentFlags() & Layer::CONTENT_COMPONENT_ALPHA_DESCENDANT
) ||
1141 !Manager()->AreComponentAlphaLayersEnabled()) {
1142 mSupportsComponentAlphaChildren
= false;
1143 if (aNeedsSurfaceCopy
) {
1144 *aNeedsSurfaceCopy
= false;
1149 mSupportsComponentAlphaChildren
= false;
1150 bool needsSurfaceCopy
= false;
1151 CompositionOp blendMode
= GetEffectiveMixBlendMode();
1152 if (UseIntermediateSurface()) {
1153 if (GetEffectiveVisibleRegion().GetNumRects() == 1 &&
1154 (GetContentFlags() & Layer::CONTENT_OPAQUE
))
1156 mSupportsComponentAlphaChildren
= true;
1158 gfx::Matrix transform
;
1159 if (HasOpaqueAncestorLayer(this) &&
1160 GetEffectiveTransform().Is2D(&transform
) &&
1161 !gfx::ThebesMatrix(transform
).HasNonIntegerTranslation() &&
1162 blendMode
== gfx::CompositionOp::OP_OVER
) {
1163 mSupportsComponentAlphaChildren
= true;
1164 needsSurfaceCopy
= true;
1167 } else if (blendMode
== gfx::CompositionOp::OP_OVER
) {
1168 mSupportsComponentAlphaChildren
=
1169 (GetContentFlags() & Layer::CONTENT_OPAQUE
) ||
1170 (GetParent() && GetParent()->SupportsComponentAlphaChildren());
1173 if (aNeedsSurfaceCopy
) {
1174 *aNeedsSurfaceCopy
= mSupportsComponentAlphaChildren
&& needsSurfaceCopy
;
1179 ContainerLayer::ComputeEffectiveTransformsForChildren(const Matrix4x4
& aTransformToSurface
)
1181 for (Layer
* l
= mFirstChild
; l
; l
= l
->GetNextSibling()) {
1182 l
->ComputeEffectiveTransforms(aTransformToSurface
);
1187 ContainerLayer::HasOpaqueAncestorLayer(Layer
* aLayer
)
1189 for (Layer
* l
= aLayer
->GetParent(); l
; l
= l
->GetParent()) {
1190 if (l
->GetContentFlags() & Layer::CONTENT_OPAQUE
)
1197 ContainerLayer::DidRemoveChild(Layer
* aLayer
)
1199 PaintedLayer
* tl
= aLayer
->AsPaintedLayer();
1200 if (tl
&& tl
->UsedForReadback()) {
1201 for (Layer
* l
= mFirstChild
; l
; l
= l
->GetNextSibling()) {
1202 if (l
->GetType() == TYPE_READBACK
) {
1203 static_cast<ReadbackLayer
*>(l
)->NotifyPaintedLayerRemoved(tl
);
1207 if (aLayer
->GetType() == TYPE_READBACK
) {
1208 static_cast<ReadbackLayer
*>(aLayer
)->NotifyRemoved();
1213 ContainerLayer::DidInsertChild(Layer
* aLayer
)
1215 if (aLayer
->GetType() == TYPE_READBACK
) {
1216 mMayHaveReadbackChild
= true;
1221 RefLayer::FillSpecificAttributes(SpecificLayerAttributes
& aAttrs
)
1223 aAttrs
= RefLayerAttributes(GetReferentId(), mEventRegionsOverride
);
1227 * StartFrameTimeRecording, together with StopFrameTimeRecording
1228 * enable recording of frame intervals.
1230 * To allow concurrent consumers, a cyclic array is used which serves all
1231 * consumers, practically stateless with regard to consumers.
1233 * To save resources, the buffer is allocated on first call to StartFrameTimeRecording
1234 * and recording is paused if no consumer which called StartFrameTimeRecording is able
1235 * to get valid results (because the cyclic buffer was overwritten since that call).
1237 * To determine availability of the data upon StopFrameTimeRecording:
1238 * - mRecording.mNextIndex increases on each PostPresent, and never resets.
1239 * - Cyclic buffer position is realized as mNextIndex % bufferSize.
1240 * - StartFrameTimeRecording returns mNextIndex. When StopFrameTimeRecording is called,
1241 * the required start index is passed as an arg, and we're able to calculate the required
1242 * length. If this length is bigger than bufferSize, it means data was overwritten.
1243 * otherwise, we can return the entire sequence.
1244 * - To determine if we need to pause, mLatestStartIndex is updated to mNextIndex
1245 * on each call to StartFrameTimeRecording. If this index gets overwritten,
1246 * it means that all earlier start indices obtained via StartFrameTimeRecording
1247 * were also overwritten, hence, no point in recording, so pause.
1248 * - mCurrentRunStartIndex indicates the oldest index of the recording after which
1249 * the recording was not paused. If StopFrameTimeRecording is invoked with a start index
1250 * older than this, it means that some frames were not recorded, so data is invalid.
1253 LayerManager::StartFrameTimeRecording(int32_t aBufferSize
)
1255 if (mRecording
.mIsPaused
) {
1256 mRecording
.mIsPaused
= false;
1258 if (!mRecording
.mIntervals
.Length()) { // Initialize recording buffers
1259 mRecording
.mIntervals
.SetLength(aBufferSize
);
1262 // After being paused, recent values got invalid. Update them to now.
1263 mRecording
.mLastFrameTime
= TimeStamp::Now();
1265 // Any recording which started before this is invalid, since we were paused.
1266 mRecording
.mCurrentRunStartIndex
= mRecording
.mNextIndex
;
1269 // If we'll overwrite this index, there are no more consumers with aStartIndex
1270 // for which we're able to provide the full recording, so no point in keep recording.
1271 mRecording
.mLatestStartIndex
= mRecording
.mNextIndex
;
1272 return mRecording
.mNextIndex
;
1276 LayerManager::RecordFrame()
1278 if (!mRecording
.mIsPaused
) {
1279 TimeStamp now
= TimeStamp::Now();
1280 uint32_t i
= mRecording
.mNextIndex
% mRecording
.mIntervals
.Length();
1281 mRecording
.mIntervals
[i
] = static_cast<float>((now
- mRecording
.mLastFrameTime
)
1283 mRecording
.mNextIndex
++;
1284 mRecording
.mLastFrameTime
= now
;
1286 if (mRecording
.mNextIndex
> (mRecording
.mLatestStartIndex
+ mRecording
.mIntervals
.Length())) {
1287 // We've just overwritten the most recent recording start -> pause.
1288 mRecording
.mIsPaused
= true;
1294 LayerManager::PostPresent()
1296 if (!mTabSwitchStart
.IsNull()) {
1297 Telemetry::Accumulate(Telemetry::FX_TAB_SWITCH_TOTAL_MS
,
1298 uint32_t((TimeStamp::Now() - mTabSwitchStart
).ToMilliseconds()));
1299 mTabSwitchStart
= TimeStamp();
1304 LayerManager::StopFrameTimeRecording(uint32_t aStartIndex
,
1305 nsTArray
<float>& aFrameIntervals
)
1307 uint32_t bufferSize
= mRecording
.mIntervals
.Length();
1308 uint32_t length
= mRecording
.mNextIndex
- aStartIndex
;
1309 if (mRecording
.mIsPaused
|| length
> bufferSize
|| aStartIndex
< mRecording
.mCurrentRunStartIndex
) {
1310 // aStartIndex is too old. Also if aStartIndex was issued before mRecordingNextIndex overflowed (uint32_t)
1311 // and stopped after the overflow (would happen once every 828 days of constant 60fps).
1316 aFrameIntervals
.Clear();
1317 return; // empty recording, return empty arrays.
1319 // Set length in advance to avoid possibly repeated reallocations
1320 aFrameIntervals
.SetLength(length
);
1322 uint32_t cyclicPos
= aStartIndex
% bufferSize
;
1323 for (uint32_t i
= 0; i
< length
; i
++, cyclicPos
++) {
1324 if (cyclicPos
== bufferSize
) {
1327 aFrameIntervals
[i
] = mRecording
.mIntervals
[cyclicPos
];
1332 LayerManager::BeginTabSwitch()
1334 mTabSwitchStart
= TimeStamp::Now();
1337 static void PrintInfo(std::stringstream
& aStream
, LayerComposite
* aLayerComposite
);
1339 #ifdef MOZ_DUMP_PAINTING
1340 template <typename T
>
1341 void WriteSnapshotLinkToDumpFile(T
* aObj
, std::stringstream
& aStream
)
1346 nsCString
string(aObj
->Name());
1348 string
.AppendInt((uint64_t)aObj
);
1349 aStream
<< nsPrintfCString("href=\"javascript:ViewImage('%s')\"", string
.BeginReading()).get();
1352 template <typename T
>
1353 void WriteSnapshotToDumpFile_internal(T
* aObj
, DataSourceSurface
* aSurf
)
1355 nsCString
string(aObj
->Name());
1357 string
.AppendInt((uint64_t)aObj
);
1358 if (gfxUtils::sDumpPaintFile
) {
1359 fprintf_stderr(gfxUtils::sDumpPaintFile
, "array[\"%s\"]=\"", string
.BeginReading());
1361 gfxUtils::DumpAsDataURI(aSurf
, gfxUtils::sDumpPaintFile
);
1362 if (gfxUtils::sDumpPaintFile
) {
1363 fprintf_stderr(gfxUtils::sDumpPaintFile
, "\";");
1367 void WriteSnapshotToDumpFile(Layer
* aLayer
, DataSourceSurface
* aSurf
)
1369 WriteSnapshotToDumpFile_internal(aLayer
, aSurf
);
1372 void WriteSnapshotToDumpFile(LayerManager
* aManager
, DataSourceSurface
* aSurf
)
1374 WriteSnapshotToDumpFile_internal(aManager
, aSurf
);
1377 void WriteSnapshotToDumpFile(Compositor
* aCompositor
, DrawTarget
* aTarget
)
1379 RefPtr
<SourceSurface
> surf
= aTarget
->Snapshot();
1380 RefPtr
<DataSourceSurface
> dSurf
= surf
->GetDataSurface();
1381 WriteSnapshotToDumpFile_internal(aCompositor
, dSurf
);
1386 Layer::Dump(std::stringstream
& aStream
, const char* aPrefix
, bool aDumpHtml
)
1389 aStream
<< nsPrintfCString("<li><a id=\"%p\" ", this).get();
1390 #ifdef MOZ_DUMP_PAINTING
1391 if (GetType() == TYPE_CONTAINER
|| GetType() == TYPE_PAINTED
) {
1392 WriteSnapshotLinkToDumpFile(this, aStream
);
1397 DumpSelf(aStream
, aPrefix
);
1399 #ifdef MOZ_DUMP_PAINTING
1400 if (gfxUtils::sDumpPainting
&& AsLayerComposite() && AsLayerComposite()->GetCompositableHost()) {
1401 AsLayerComposite()->GetCompositableHost()->Dump(aStream
, aPrefix
, aDumpHtml
);
1409 if (Layer
* mask
= GetMaskLayer()) {
1410 aStream
<< nsPrintfCString("%s Mask layer:\n", aPrefix
).get();
1411 nsAutoCString
pfx(aPrefix
);
1413 mask
->Dump(aStream
, pfx
.get(), aDumpHtml
);
1416 #ifdef MOZ_DUMP_PAINTING
1417 for (size_t i
= 0; i
< mExtraDumpInfo
.Length(); i
++) {
1418 const nsCString
& str
= mExtraDumpInfo
[i
];
1419 aStream
<< aPrefix
<< " Info:\n" << str
.get();
1423 if (Layer
* kid
= GetFirstChild()) {
1424 nsAutoCString
pfx(aPrefix
);
1429 kid
->Dump(aStream
, pfx
.get(), aDumpHtml
);
1438 if (Layer
* next
= GetNextSibling())
1439 next
->Dump(aStream
, aPrefix
, aDumpHtml
);
1443 Layer::DumpSelf(std::stringstream
& aStream
, const char* aPrefix
)
1445 PrintInfo(aStream
, aPrefix
);
1450 Layer::Dump(layerscope::LayersPacket
* aPacket
, const void* aParent
)
1452 DumpPacket(aPacket
, aParent
);
1454 if (Layer
* kid
= GetFirstChild()) {
1455 kid
->Dump(aPacket
, this);
1458 if (Layer
* next
= GetNextSibling()) {
1459 next
->Dump(aPacket
, aParent
);
1464 Layer::Log(const char* aPrefix
)
1466 if (!IsLogEnabled())
1471 if (Layer
* kid
= GetFirstChild()) {
1472 nsAutoCString
pfx(aPrefix
);
1474 kid
->Log(pfx
.get());
1477 if (Layer
* next
= GetNextSibling())
1482 Layer::LogSelf(const char* aPrefix
)
1484 if (!IsLogEnabled())
1487 std::stringstream ss
;
1488 PrintInfo(ss
, aPrefix
);
1489 MOZ_LAYERS_LOG(("%s", ss
.str().c_str()));
1492 nsAutoCString
pfx(aPrefix
);
1493 pfx
+= " \\ MaskLayer ";
1494 mMaskLayer
->LogSelf(pfx
.get());
1499 Layer::PrintInfo(std::stringstream
& aStream
, const char* aPrefix
)
1502 aStream
<< nsPrintfCString("%s%s (0x%p)", mManager
->Name(), Name(), this).get();
1504 layers::PrintInfo(aStream
, AsLayerComposite());
1507 AppendToString(aStream
, mClipRect
, " [clip=", "]");
1509 if (1.0 != mPostXScale
|| 1.0 != mPostYScale
) {
1510 aStream
<< nsPrintfCString(" [postScale=%g, %g]", mPostXScale
, mPostYScale
).get();
1512 if (!mTransform
.IsIdentity()) {
1513 AppendToString(aStream
, mTransform
, " [transform=", "]");
1515 if (!mLayerBounds
.IsEmpty()) {
1516 AppendToString(aStream
, mLayerBounds
, " [bounds=", "]");
1518 if (!mVisibleRegion
.IsEmpty()) {
1519 AppendToString(aStream
, mVisibleRegion
, " [visible=", "]");
1521 aStream
<< " [not visible]";
1523 if (!mEventRegions
.IsEmpty()) {
1524 AppendToString(aStream
, mEventRegions
, " ", "");
1526 if (1.0 != mOpacity
) {
1527 aStream
<< nsPrintfCString(" [opacity=%g]", mOpacity
).get();
1529 if (GetContentFlags() & CONTENT_OPAQUE
) {
1530 aStream
<< " [opaqueContent]";
1532 if (GetContentFlags() & CONTENT_COMPONENT_ALPHA
) {
1533 aStream
<< " [componentAlpha]";
1535 if (GetScrollbarDirection() == VERTICAL
) {
1536 aStream
<< nsPrintfCString(" [vscrollbar=%lld]", GetScrollbarTargetContainerId()).get();
1538 if (GetScrollbarDirection() == HORIZONTAL
) {
1539 aStream
<< nsPrintfCString(" [hscrollbar=%lld]", GetScrollbarTargetContainerId()).get();
1541 if (GetIsFixedPosition()) {
1542 aStream
<< nsPrintfCString(" [isFixedPosition anchor=%s margin=%f,%f,%f,%f]",
1543 ToString(mAnchor
).c_str(),
1544 mMargins
.top
, mMargins
.right
, mMargins
.bottom
, mMargins
.left
).get();
1546 if (GetIsStickyPosition()) {
1547 aStream
<< nsPrintfCString(" [isStickyPosition scrollId=%d outer=%f,%f %fx%f "
1548 "inner=%f,%f %fx%f]", mStickyPositionData
->mScrollId
,
1549 mStickyPositionData
->mOuter
.x
, mStickyPositionData
->mOuter
.y
,
1550 mStickyPositionData
->mOuter
.width
, mStickyPositionData
->mOuter
.height
,
1551 mStickyPositionData
->mInner
.x
, mStickyPositionData
->mInner
.y
,
1552 mStickyPositionData
->mInner
.width
, mStickyPositionData
->mInner
.height
).get();
1555 aStream
<< nsPrintfCString(" [mMaskLayer=%p]", mMaskLayer
.get()).get();
1557 for (uint32_t i
= 0; i
< mFrameMetrics
.Length(); i
++) {
1558 if (!mFrameMetrics
[i
].IsDefault()) {
1559 aStream
<< nsPrintfCString(" [metrics%d=", i
).get();
1560 AppendToString(aStream
, mFrameMetrics
[i
], "", "]");
1565 // The static helper function sets the transform matrix into the packet
1567 DumpTransform(layerscope::LayersPacket::Layer::Matrix
* aLayerMatrix
, const Matrix4x4
& aMatrix
)
1569 aLayerMatrix
->set_is2d(aMatrix
.Is2D());
1570 if (aMatrix
.Is2D()) {
1571 Matrix m
= aMatrix
.As2D();
1572 aLayerMatrix
->set_isid(m
.IsIdentity());
1573 if (!m
.IsIdentity()) {
1574 aLayerMatrix
->add_m(m
._11
), aLayerMatrix
->add_m(m
._12
);
1575 aLayerMatrix
->add_m(m
._21
), aLayerMatrix
->add_m(m
._22
);
1576 aLayerMatrix
->add_m(m
._31
), aLayerMatrix
->add_m(m
._32
);
1579 aLayerMatrix
->add_m(aMatrix
._11
), aLayerMatrix
->add_m(aMatrix
._12
);
1580 aLayerMatrix
->add_m(aMatrix
._13
), aLayerMatrix
->add_m(aMatrix
._14
);
1581 aLayerMatrix
->add_m(aMatrix
._21
), aLayerMatrix
->add_m(aMatrix
._22
);
1582 aLayerMatrix
->add_m(aMatrix
._23
), aLayerMatrix
->add_m(aMatrix
._24
);
1583 aLayerMatrix
->add_m(aMatrix
._31
), aLayerMatrix
->add_m(aMatrix
._32
);
1584 aLayerMatrix
->add_m(aMatrix
._33
), aLayerMatrix
->add_m(aMatrix
._34
);
1585 aLayerMatrix
->add_m(aMatrix
._41
), aLayerMatrix
->add_m(aMatrix
._42
);
1586 aLayerMatrix
->add_m(aMatrix
._43
), aLayerMatrix
->add_m(aMatrix
._44
);
1590 // The static helper function sets the nsIntRect into the packet
1592 DumpRect(layerscope::LayersPacket::Layer::Rect
* aLayerRect
, const nsIntRect
& aRect
)
1594 aLayerRect
->set_x(aRect
.x
);
1595 aLayerRect
->set_y(aRect
.y
);
1596 aLayerRect
->set_w(aRect
.width
);
1597 aLayerRect
->set_h(aRect
.height
);
1600 // The static helper function sets the nsIntRegion into the packet
1602 DumpRegion(layerscope::LayersPacket::Layer::Region
* aLayerRegion
, const nsIntRegion
& aRegion
)
1604 nsIntRegionRectIterator
it(aRegion
);
1605 while (const nsIntRect
* sr
= it
.Next()) {
1606 DumpRect(aLayerRegion
->add_r(), *sr
);
1611 Layer::DumpPacket(layerscope::LayersPacket
* aPacket
, const void* aParent
)
1613 // Add a new layer (UnknownLayer)
1614 using namespace layerscope
;
1615 LayersPacket::Layer
* layer
= aPacket
->add_layer();
1616 // Basic information
1617 layer
->set_type(LayersPacket::Layer::UnknownLayer
);
1618 layer
->set_ptr(reinterpret_cast<uint64_t>(this));
1619 layer
->set_parentptr(reinterpret_cast<uint64_t>(aParent
));
1621 if (LayerComposite
* lc
= AsLayerComposite()) {
1622 LayersPacket::Layer::Shadow
* s
= layer
->mutable_shadow();
1623 if (const nsIntRect
* clipRect
= lc
->GetShadowClipRect()) {
1624 DumpRect(s
->mutable_clip(), *clipRect
);
1626 if (!lc
->GetShadowTransform().IsIdentity()) {
1627 DumpTransform(s
->mutable_transform(), lc
->GetShadowTransform());
1629 if (!lc
->GetShadowVisibleRegion().IsEmpty()) {
1630 DumpRegion(s
->mutable_vregion(), lc
->GetShadowVisibleRegion());
1635 DumpRect(layer
->mutable_clip(), mClipRect
);
1638 if (!mTransform
.IsIdentity()) {
1639 DumpTransform(layer
->mutable_transform(), mTransform
);
1642 if (!mVisibleRegion
.IsEmpty()) {
1643 DumpRegion(layer
->mutable_vregion(), mVisibleRegion
);
1646 layer
->set_opacity(mOpacity
);
1648 layer
->set_copaque(static_cast<bool>(GetContentFlags() & CONTENT_OPAQUE
));
1650 layer
->set_calpha(static_cast<bool>(GetContentFlags() & CONTENT_COMPONENT_ALPHA
));
1651 // Vertical or horizontal bar
1652 if (GetScrollbarDirection() != NONE
) {
1653 layer
->set_direct(GetScrollbarDirection() == VERTICAL
?
1654 LayersPacket::Layer::VERTICAL
:
1655 LayersPacket::Layer::HORIZONTAL
);
1656 layer
->set_barid(GetScrollbarTargetContainerId());
1660 layer
->set_mask(reinterpret_cast<uint64_t>(mMaskLayer
.get()));
1665 PaintedLayer::PrintInfo(std::stringstream
& aStream
, const char* aPrefix
)
1667 Layer::PrintInfo(aStream
, aPrefix
);
1668 if (!mValidRegion
.IsEmpty()) {
1669 AppendToString(aStream
, mValidRegion
, " [valid=", "]");
1674 PaintedLayer::DumpPacket(layerscope::LayersPacket
* aPacket
, const void* aParent
)
1676 Layer::DumpPacket(aPacket
, aParent
);
1677 // get this layer data
1678 using namespace layerscope
;
1679 LayersPacket::Layer
* layer
= aPacket
->mutable_layer(aPacket
->layer_size()-1);
1680 layer
->set_type(LayersPacket::Layer::PaintedLayer
);
1681 if (!mValidRegion
.IsEmpty()) {
1682 DumpRegion(layer
->mutable_valid(), mValidRegion
);
1687 ContainerLayer::PrintInfo(std::stringstream
& aStream
, const char* aPrefix
)
1689 Layer::PrintInfo(aStream
, aPrefix
);
1690 if (UseIntermediateSurface()) {
1691 aStream
<< " [usesTmpSurf]";
1693 if (1.0 != mPreXScale
|| 1.0 != mPreYScale
) {
1694 aStream
<< nsPrintfCString(" [preScale=%g, %g]", mPreXScale
, mPreYScale
).get();
1696 if (mScaleToResolution
) {
1697 aStream
<< nsPrintfCString(" [presShellResolution=%g]", mPresShellResolution
).get();
1699 if (mEventRegionsOverride
& EventRegionsOverride::ForceDispatchToContent
) {
1700 aStream
<< " [force-dtc]";
1702 if (mEventRegionsOverride
& EventRegionsOverride::ForceEmptyHitRegion
) {
1703 aStream
<< " [force-ehr]";
1706 aStream
<< nsPrintfCString(" [hmd=%p]", mHMDInfo
.get()).get();
1711 ContainerLayer::DumpPacket(layerscope::LayersPacket
* aPacket
, const void* aParent
)
1713 Layer::DumpPacket(aPacket
, aParent
);
1714 // Get this layer data
1715 using namespace layerscope
;
1716 LayersPacket::Layer
* layer
= aPacket
->mutable_layer(aPacket
->layer_size()-1);
1717 layer
->set_type(LayersPacket::Layer::ContainerLayer
);
1721 ColorLayer::PrintInfo(std::stringstream
& aStream
, const char* aPrefix
)
1723 Layer::PrintInfo(aStream
, aPrefix
);
1724 AppendToString(aStream
, mColor
, " [color=", "]");
1728 ColorLayer::DumpPacket(layerscope::LayersPacket
* aPacket
, const void* aParent
)
1730 Layer::DumpPacket(aPacket
, aParent
);
1731 // Get this layer data
1732 using namespace layerscope
;
1733 LayersPacket::Layer
* layer
= aPacket
->mutable_layer(aPacket
->layer_size()-1);
1734 layer
->set_type(LayersPacket::Layer::ColorLayer
);
1735 layer
->set_color(mColor
.Packed());
1739 CanvasLayer::PrintInfo(std::stringstream
& aStream
, const char* aPrefix
)
1741 Layer::PrintInfo(aStream
, aPrefix
);
1742 if (mFilter
!= GraphicsFilter::FILTER_GOOD
) {
1743 AppendToString(aStream
, mFilter
, " [filter=", "]");
1747 // This help function is used to assign the correct enum value
1750 DumpFilter(layerscope::LayersPacket::Layer
* aLayer
, const GraphicsFilter
& aFilter
)
1752 using namespace layerscope
;
1754 case GraphicsFilter::FILTER_FAST
:
1755 aLayer
->set_filter(LayersPacket::Layer::FILTER_FAST
);
1757 case GraphicsFilter::FILTER_GOOD
:
1758 aLayer
->set_filter(LayersPacket::Layer::FILTER_GOOD
);
1760 case GraphicsFilter::FILTER_BEST
:
1761 aLayer
->set_filter(LayersPacket::Layer::FILTER_BEST
);
1763 case GraphicsFilter::FILTER_NEAREST
:
1764 aLayer
->set_filter(LayersPacket::Layer::FILTER_NEAREST
);
1766 case GraphicsFilter::FILTER_BILINEAR
:
1767 aLayer
->set_filter(LayersPacket::Layer::FILTER_BILINEAR
);
1769 case GraphicsFilter::FILTER_GAUSSIAN
:
1770 aLayer
->set_filter(LayersPacket::Layer::FILTER_GAUSSIAN
);
1779 CanvasLayer::DumpPacket(layerscope::LayersPacket
* aPacket
, const void* aParent
)
1781 Layer::DumpPacket(aPacket
, aParent
);
1782 // Get this layer data
1783 using namespace layerscope
;
1784 LayersPacket::Layer
* layer
= aPacket
->mutable_layer(aPacket
->layer_size()-1);
1785 layer
->set_type(LayersPacket::Layer::CanvasLayer
);
1786 DumpFilter(layer
, mFilter
);
1790 ImageLayer::PrintInfo(std::stringstream
& aStream
, const char* aPrefix
)
1792 Layer::PrintInfo(aStream
, aPrefix
);
1793 if (mFilter
!= GraphicsFilter::FILTER_GOOD
) {
1794 AppendToString(aStream
, mFilter
, " [filter=", "]");
1799 ImageLayer::DumpPacket(layerscope::LayersPacket
* aPacket
, const void* aParent
)
1801 Layer::DumpPacket(aPacket
, aParent
);
1802 // Get this layer data
1803 using namespace layerscope
;
1804 LayersPacket::Layer
* layer
= aPacket
->mutable_layer(aPacket
->layer_size()-1);
1805 layer
->set_type(LayersPacket::Layer::ImageLayer
);
1806 DumpFilter(layer
, mFilter
);
1810 RefLayer::PrintInfo(std::stringstream
& aStream
, const char* aPrefix
)
1812 ContainerLayer::PrintInfo(aStream
, aPrefix
);
1814 AppendToString(aStream
, mId
, " [id=", "]");
1819 RefLayer::DumpPacket(layerscope::LayersPacket
* aPacket
, const void* aParent
)
1821 Layer::DumpPacket(aPacket
, aParent
);
1822 // Get this layer data
1823 using namespace layerscope
;
1824 LayersPacket::Layer
* layer
= aPacket
->mutable_layer(aPacket
->layer_size()-1);
1825 layer
->set_type(LayersPacket::Layer::RefLayer
);
1826 layer
->set_refid(mId
);
1830 ReadbackLayer::PrintInfo(std::stringstream
& aStream
, const char* aPrefix
)
1832 Layer::PrintInfo(aStream
, aPrefix
);
1833 AppendToString(aStream
, mSize
, " [size=", "]");
1834 if (mBackgroundLayer
) {
1835 AppendToString(aStream
, mBackgroundLayer
, " [backgroundLayer=", "]");
1836 AppendToString(aStream
, mBackgroundLayerOffset
, " [backgroundOffset=", "]");
1837 } else if (mBackgroundColor
.a
== 1.0) {
1838 AppendToString(aStream
, mBackgroundColor
, " [backgroundColor=", "]");
1840 aStream
<< " [nobackground]";
1845 ReadbackLayer::DumpPacket(layerscope::LayersPacket
* aPacket
, const void* aParent
)
1847 Layer::DumpPacket(aPacket
, aParent
);
1848 // Get this layer data
1849 using namespace layerscope
;
1850 LayersPacket::Layer
* layer
= aPacket
->mutable_layer(aPacket
->layer_size()-1);
1851 layer
->set_type(LayersPacket::Layer::ReadbackLayer
);
1852 LayersPacket::Layer::Size
* size
= layer
->mutable_size();
1853 size
->set_w(mSize
.width
);
1854 size
->set_h(mSize
.height
);
1857 //--------------------------------------------------
1861 LayerManager::Dump(std::stringstream
& aStream
, const char* aPrefix
, bool aDumpHtml
)
1863 #ifdef MOZ_DUMP_PAINTING
1865 aStream
<< "<ul><li><a ";
1866 WriteSnapshotLinkToDumpFile(this, aStream
);
1870 DumpSelf(aStream
, aPrefix
);
1871 #ifdef MOZ_DUMP_PAINTING
1877 nsAutoCString
pfx(aPrefix
);
1880 aStream
<< nsPrintfCString("%s(null)", pfx
.get()).get();
1882 aStream
<< "</li></ul>";
1890 GetRoot()->Dump(aStream
, pfx
.get(), aDumpHtml
);
1892 aStream
<< "</ul></li></ul>";
1898 LayerManager::DumpSelf(std::stringstream
& aStream
, const char* aPrefix
)
1900 PrintInfo(aStream
, aPrefix
);
1905 LayerManager::Dump()
1907 std::stringstream ss
;
1913 LayerManager::Dump(layerscope::LayersPacket
* aPacket
)
1915 DumpPacket(aPacket
);
1918 GetRoot()->Dump(aPacket
, this);
1923 LayerManager::Log(const char* aPrefix
)
1925 if (!IsLogEnabled())
1930 nsAutoCString
pfx(aPrefix
);
1933 MOZ_LAYERS_LOG(("%s(null)", pfx
.get()));
1937 GetRoot()->Log(pfx
.get());
1941 LayerManager::LogSelf(const char* aPrefix
)
1944 std::stringstream ss
;
1945 PrintInfo(ss
, aPrefix
);
1946 MOZ_LAYERS_LOG(("%s", ss
.str().c_str()));
1950 LayerManager::PrintInfo(std::stringstream
& aStream
, const char* aPrefix
)
1952 aStream
<< aPrefix
<< nsPrintfCString("%sLayerManager (0x%p)", Name(), this).get();
1956 LayerManager::DumpPacket(layerscope::LayersPacket
* aPacket
)
1958 using namespace layerscope
;
1959 // Add a new layer data (LayerManager)
1960 LayersPacket::Layer
* layer
= aPacket
->add_layer();
1961 layer
->set_type(LayersPacket::Layer::LayerManager
);
1962 layer
->set_ptr(reinterpret_cast<uint64_t>(this));
1964 layer
->set_parentptr(0);
1968 LayerManager::InitLog()
1971 sLog
= PR_NewLogModule("Layers");
1975 LayerManager::IsLogEnabled()
1977 NS_ABORT_IF_FALSE(!!sLog
,
1978 "layer manager must be created before logging is allowed");
1979 return PR_LOG_TEST(sLog
, PR_LOG_DEBUG
);
1983 PrintInfo(std::stringstream
& aStream
, LayerComposite
* aLayerComposite
)
1985 if (!aLayerComposite
) {
1988 if (const nsIntRect
* clipRect
= aLayerComposite
->GetShadowClipRect()) {
1989 AppendToString(aStream
, *clipRect
, " [shadow-clip=", "]");
1991 if (!aLayerComposite
->GetShadowTransform().IsIdentity()) {
1992 AppendToString(aStream
, aLayerComposite
->GetShadowTransform(), " [shadow-transform=", "]");
1994 if (!aLayerComposite
->GetShadowVisibleRegion().IsEmpty()) {
1995 AppendToString(aStream
, aLayerComposite
->GetShadowVisibleRegion(), " [shadow-visible=", "]");
2000 SetAntialiasingFlags(Layer
* aLayer
, DrawTarget
* aTarget
)
2002 bool permitSubpixelAA
= !(aLayer
->GetContentFlags() & Layer::CONTENT_DISABLE_SUBPIXEL_AA
);
2003 if (aTarget
->GetFormat() != SurfaceFormat::B8G8R8A8
) {
2004 aTarget
->SetPermitSubpixelAA(permitSubpixelAA
);
2008 const nsIntRect
& bounds
= aLayer
->GetVisibleRegion().GetBounds();
2009 gfx::Rect transformedBounds
= aTarget
->GetTransform().TransformBounds(gfx::Rect(Float(bounds
.x
), Float(bounds
.y
),
2010 Float(bounds
.width
), Float(bounds
.height
)));
2011 transformedBounds
.RoundOut();
2012 IntRect intTransformedBounds
;
2013 transformedBounds
.ToIntRect(&intTransformedBounds
);
2014 permitSubpixelAA
&= !(aLayer
->GetContentFlags() & Layer::CONTENT_COMPONENT_ALPHA
) ||
2015 aTarget
->GetOpaqueRect().Contains(intTransformedBounds
);
2016 aTarget
->SetPermitSubpixelAA(permitSubpixelAA
);
2020 ToOutsideIntRect(const gfxRect
&aRect
)
2024 return nsIntRect(r
.X(), r
.Y(), r
.Width(), r
.Height());
2027 PRLogModuleInfo
* LayerManager::sLog
;
2029 } // namespace layers
2030 } // namespace mozilla