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 "AnimationCommon.h" // for ComputedTimingFunction
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
18 #include "gfxUtils.h" // for gfxUtils, etc
19 #include "mozilla/DebugOnly.h" // for DebugOnly
20 #include "mozilla/Preferences.h" // for Preferences
21 #include "mozilla/Telemetry.h" // for Accumulate
22 #include "mozilla/TelemetryHistogramEnums.h"
23 #include "mozilla/gfx/2D.h" // for DrawTarget
24 #include "mozilla/gfx/BaseSize.h" // for BaseSize
25 #include "mozilla/layers/AsyncPanZoomController.h"
26 #include "mozilla/layers/Compositor.h" // for Compositor
27 #include "mozilla/layers/CompositorTypes.h"
28 #include "mozilla/layers/LayerManagerComposite.h" // for LayerComposite
29 #include "mozilla/layers/LayersMessages.h" // for TransformFunction, etc
30 #include "nsAString.h"
31 #include "nsCSSValue.h" // for nsCSSValue::Array, etc
32 #include "nsPrintfCString.h" // for nsPrintfCString
33 #include "nsStyleStruct.h" // for nsTimingFunction, etc
35 using namespace mozilla::layers
;
36 using namespace mozilla::gfx
;
38 typedef FrameMetrics::ViewID ViewID
;
39 const ViewID
FrameMetrics::NULL_SCROLL_ID
= 0;
40 const ViewID
FrameMetrics::ROOT_SCROLL_ID
= 1;
41 const ViewID
FrameMetrics::START_SCROLL_ID
= 2;
43 uint8_t gLayerManagerLayerBuilder
;
45 #ifdef MOZ_LAYERS_HAVE_LOG
47 FILEOrDefault(FILE* aFile
)
49 return aFile
? aFile
: stderr
;
51 #endif // MOZ_LAYERS_HAVE_LOG
56 //--------------------------------------------------
59 LayerManager::GetPrimaryScrollableLayer()
65 nsTArray
<Layer
*> queue
;
66 queue
.AppendElement(mRoot
);
67 while (queue
.Length()) {
68 ContainerLayer
* containerLayer
= queue
[0]->AsContainerLayer();
69 queue
.RemoveElementAt(0);
70 if (!containerLayer
) {
74 const FrameMetrics
& frameMetrics
= containerLayer
->GetFrameMetrics();
75 if (frameMetrics
.IsScrollable()) {
76 return containerLayer
;
79 Layer
* child
= containerLayer
->GetFirstChild();
81 queue
.AppendElement(child
);
82 child
= child
->GetNextSibling();
90 LayerManager::GetScrollableLayers(nsTArray
<Layer
*>& aArray
)
96 nsTArray
<Layer
*> queue
;
97 queue
.AppendElement(mRoot
);
98 while (!queue
.IsEmpty()) {
99 ContainerLayer
* containerLayer
= queue
.LastElement()->AsContainerLayer();
100 queue
.RemoveElementAt(queue
.Length() - 1);
101 if (!containerLayer
) {
105 const FrameMetrics
& frameMetrics
= containerLayer
->GetFrameMetrics();
106 if (frameMetrics
.IsScrollable()) {
107 aArray
.AppendElement(containerLayer
);
111 Layer
* child
= containerLayer
->GetFirstChild();
113 queue
.AppendElement(child
);
114 child
= child
->GetNextSibling();
119 already_AddRefed
<gfxASurface
>
120 LayerManager::CreateOptimalSurface(const gfxIntSize
&aSize
,
121 gfxImageFormat aFormat
)
123 return gfxPlatform::GetPlatform()->
124 CreateOffscreenSurface(aSize
, gfxASurface::ContentFromFormat(aFormat
));
127 already_AddRefed
<gfxASurface
>
128 LayerManager::CreateOptimalMaskSurface(const gfxIntSize
&aSize
)
130 return CreateOptimalSurface(aSize
, gfxImageFormatA8
);
133 TemporaryRef
<DrawTarget
>
134 LayerManager::CreateDrawTarget(const IntSize
&aSize
,
135 SurfaceFormat aFormat
)
137 return gfxPlatform::GetPlatform()->
138 CreateOffscreenCanvasDrawTarget(aSize
, aFormat
);
141 TextureFactoryIdentifier
142 LayerManager::GetTextureFactoryIdentifier()
144 //TODO[nrc] make pure virtual when all layer managers use Compositor
145 NS_ERROR("Should have been overridden");
146 return TextureFactoryIdentifier();
152 LayerManager::Mutated(Layer
* aLayer
)
157 already_AddRefed
<ImageContainer
>
158 LayerManager::CreateImageContainer()
160 nsRefPtr
<ImageContainer
> container
= new ImageContainer(ImageContainer::DISABLE_ASYNC
);
161 return container
.forget();
164 already_AddRefed
<ImageContainer
>
165 LayerManager::CreateAsynchronousImageContainer()
167 nsRefPtr
<ImageContainer
> container
= new ImageContainer(ImageContainer::ENABLE_ASYNC
);
168 return container
.forget();
171 //--------------------------------------------------
174 Layer::Layer(LayerManager
* aManager
, void* aImplData
) :
177 mNextSibling(nullptr),
178 mPrevSibling(nullptr),
179 mImplData(aImplData
),
184 mMixBlendMode(gfxContext::OPERATOR_OVER
),
185 mForceIsolatedGroup(false),
188 mUseTileSourceRect(false),
189 mIsFixedPosition(false),
190 mMargins(0, 0, 0, 0),
191 mStickyPositionData(nullptr),
193 mAnimationGeneration(0)
200 Layer::AddAnimation(TimeStamp aStart
, TimeDuration aDuration
, float aIterations
,
201 int aDirection
, nsCSSProperty aProperty
, const AnimationData
& aData
)
203 MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) AddAnimation", this));
205 Animation
* anim
= mAnimations
.AppendElement();
206 anim
->startTime() = aStart
;
207 anim
->duration() = aDuration
;
208 anim
->numIterations() = aIterations
;
209 anim
->direction() = aDirection
;
210 anim
->property() = aProperty
;
211 anim
->data() = aData
;
218 Layer::ClearAnimations()
220 if (mAnimations
.IsEmpty() && mAnimationData
.IsEmpty()) {
224 MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) ClearAnimations", this));
226 mAnimationData
.Clear();
230 static nsCSSValueList
*
231 CreateCSSValueList(const InfallibleTArray
<TransformFunction
>& aFunctions
)
233 nsAutoPtr
<nsCSSValueList
> result
;
234 nsCSSValueList
** resultTail
= getter_Transfers(result
);
235 for (uint32_t i
= 0; i
< aFunctions
.Length(); i
++) {
236 nsRefPtr
<nsCSSValue::Array
> arr
;
237 switch (aFunctions
[i
].type()) {
238 case TransformFunction::TRotationX
:
240 float theta
= aFunctions
[i
].get_RotationX().radians();
241 arr
= nsStyleAnimation::AppendTransformFunction(eCSSKeyword_rotatex
, resultTail
);
242 arr
->Item(1).SetFloatValue(theta
, eCSSUnit_Radian
);
245 case TransformFunction::TRotationY
:
247 float theta
= aFunctions
[i
].get_RotationY().radians();
248 arr
= nsStyleAnimation::AppendTransformFunction(eCSSKeyword_rotatey
, resultTail
);
249 arr
->Item(1).SetFloatValue(theta
, eCSSUnit_Radian
);
252 case TransformFunction::TRotationZ
:
254 float theta
= aFunctions
[i
].get_RotationZ().radians();
255 arr
= nsStyleAnimation::AppendTransformFunction(eCSSKeyword_rotatez
, resultTail
);
256 arr
->Item(1).SetFloatValue(theta
, eCSSUnit_Radian
);
259 case TransformFunction::TRotation
:
261 float theta
= aFunctions
[i
].get_Rotation().radians();
262 arr
= nsStyleAnimation::AppendTransformFunction(eCSSKeyword_rotate
, resultTail
);
263 arr
->Item(1).SetFloatValue(theta
, eCSSUnit_Radian
);
266 case TransformFunction::TRotation3D
:
268 float x
= aFunctions
[i
].get_Rotation3D().x();
269 float y
= aFunctions
[i
].get_Rotation3D().y();
270 float z
= aFunctions
[i
].get_Rotation3D().z();
271 float theta
= aFunctions
[i
].get_Rotation3D().radians();
272 arr
= nsStyleAnimation::AppendTransformFunction(eCSSKeyword_rotate3d
, resultTail
);
273 arr
->Item(1).SetFloatValue(x
, eCSSUnit_Number
);
274 arr
->Item(2).SetFloatValue(y
, eCSSUnit_Number
);
275 arr
->Item(3).SetFloatValue(z
, eCSSUnit_Number
);
276 arr
->Item(4).SetFloatValue(theta
, eCSSUnit_Radian
);
279 case TransformFunction::TScale
:
281 arr
= nsStyleAnimation::AppendTransformFunction(eCSSKeyword_scale3d
, resultTail
);
282 arr
->Item(1).SetFloatValue(aFunctions
[i
].get_Scale().x(), eCSSUnit_Number
);
283 arr
->Item(2).SetFloatValue(aFunctions
[i
].get_Scale().y(), eCSSUnit_Number
);
284 arr
->Item(3).SetFloatValue(aFunctions
[i
].get_Scale().z(), eCSSUnit_Number
);
287 case TransformFunction::TTranslation
:
289 arr
= nsStyleAnimation::AppendTransformFunction(eCSSKeyword_translate3d
, resultTail
);
290 arr
->Item(1).SetFloatValue(aFunctions
[i
].get_Translation().x(), eCSSUnit_Pixel
);
291 arr
->Item(2).SetFloatValue(aFunctions
[i
].get_Translation().y(), eCSSUnit_Pixel
);
292 arr
->Item(3).SetFloatValue(aFunctions
[i
].get_Translation().z(), eCSSUnit_Pixel
);
295 case TransformFunction::TSkewX
:
297 float x
= aFunctions
[i
].get_SkewX().x();
298 arr
= nsStyleAnimation::AppendTransformFunction(eCSSKeyword_skewx
, resultTail
);
299 arr
->Item(1).SetFloatValue(x
, eCSSUnit_Radian
);
302 case TransformFunction::TSkewY
:
304 float y
= aFunctions
[i
].get_SkewY().y();
305 arr
= nsStyleAnimation::AppendTransformFunction(eCSSKeyword_skewy
, resultTail
);
306 arr
->Item(1).SetFloatValue(y
, eCSSUnit_Radian
);
309 case TransformFunction::TSkew
:
311 arr
= nsStyleAnimation::AppendTransformFunction(eCSSKeyword_skew
, resultTail
);
312 arr
->Item(1).SetFloatValue(aFunctions
[i
].get_Skew().x(), eCSSUnit_Radian
);
313 arr
->Item(2).SetFloatValue(aFunctions
[i
].get_Skew().y(), eCSSUnit_Radian
);
316 case TransformFunction::TTransformMatrix
:
318 arr
= nsStyleAnimation::AppendTransformFunction(eCSSKeyword_matrix3d
, resultTail
);
319 const gfx3DMatrix
& matrix
= aFunctions
[i
].get_TransformMatrix().value();
320 arr
->Item(1).SetFloatValue(matrix
._11
, eCSSUnit_Number
);
321 arr
->Item(2).SetFloatValue(matrix
._12
, eCSSUnit_Number
);
322 arr
->Item(3).SetFloatValue(matrix
._13
, eCSSUnit_Number
);
323 arr
->Item(4).SetFloatValue(matrix
._14
, eCSSUnit_Number
);
324 arr
->Item(5).SetFloatValue(matrix
._21
, eCSSUnit_Number
);
325 arr
->Item(6).SetFloatValue(matrix
._22
, eCSSUnit_Number
);
326 arr
->Item(7).SetFloatValue(matrix
._23
, eCSSUnit_Number
);
327 arr
->Item(8).SetFloatValue(matrix
._24
, eCSSUnit_Number
);
328 arr
->Item(9).SetFloatValue(matrix
._31
, eCSSUnit_Number
);
329 arr
->Item(10).SetFloatValue(matrix
._32
, eCSSUnit_Number
);
330 arr
->Item(11).SetFloatValue(matrix
._33
, eCSSUnit_Number
);
331 arr
->Item(12).SetFloatValue(matrix
._34
, eCSSUnit_Number
);
332 arr
->Item(13).SetFloatValue(matrix
._41
, eCSSUnit_Number
);
333 arr
->Item(14).SetFloatValue(matrix
._42
, eCSSUnit_Number
);
334 arr
->Item(15).SetFloatValue(matrix
._43
, eCSSUnit_Number
);
335 arr
->Item(16).SetFloatValue(matrix
._44
, eCSSUnit_Number
);
338 case TransformFunction::TPerspective
:
340 float perspective
= aFunctions
[i
].get_Perspective().value();
341 arr
= nsStyleAnimation::AppendTransformFunction(eCSSKeyword_perspective
, resultTail
);
342 arr
->Item(1).SetFloatValue(perspective
, eCSSUnit_Pixel
);
346 NS_ASSERTION(false, "All functions should be implemented?");
349 if (aFunctions
.Length() == 0) {
350 result
= new nsCSSValueList();
351 result
->mValue
.SetNoneValue();
353 return result
.forget();
357 Layer::SetAnimations(const AnimationArray
& aAnimations
)
359 MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) SetAnimations", this));
361 mAnimations
= aAnimations
;
362 mAnimationData
.Clear();
363 for (uint32_t i
= 0; i
< mAnimations
.Length(); i
++) {
364 AnimData
* data
= mAnimationData
.AppendElement();
365 InfallibleTArray
<nsAutoPtr
<css::ComputedTimingFunction
> >& functions
= data
->mFunctions
;
366 const InfallibleTArray
<AnimationSegment
>& segments
=
367 mAnimations
.ElementAt(i
).segments();
368 for (uint32_t j
= 0; j
< segments
.Length(); j
++) {
369 TimingFunction tf
= segments
.ElementAt(j
).sampleFn();
370 css::ComputedTimingFunction
* ctf
= new css::ComputedTimingFunction();
372 case TimingFunction::TCubicBezierFunction
: {
373 CubicBezierFunction cbf
= tf
.get_CubicBezierFunction();
374 ctf
->Init(nsTimingFunction(cbf
.x1(), cbf
.y1(), cbf
.x2(), cbf
.y2()));
378 NS_ASSERTION(tf
.type() == TimingFunction::TStepFunction
,
379 "Function must be bezier or step");
380 StepFunction sf
= tf
.get_StepFunction();
381 nsTimingFunction::Type type
= sf
.type() == 1 ? nsTimingFunction::StepStart
382 : nsTimingFunction::StepEnd
;
383 ctf
->Init(nsTimingFunction(type
, sf
.steps()));
387 functions
.AppendElement(ctf
);
390 // Precompute the nsStyleAnimation::Values that we need if this is a transform
392 InfallibleTArray
<nsStyleAnimation::Value
>& startValues
= data
->mStartValues
;
393 InfallibleTArray
<nsStyleAnimation::Value
>& endValues
= data
->mEndValues
;
394 for (uint32_t j
= 0; j
< mAnimations
[i
].segments().Length(); j
++) {
395 const AnimationSegment
& segment
= mAnimations
[i
].segments()[j
];
396 nsStyleAnimation::Value
* startValue
= startValues
.AppendElement();
397 nsStyleAnimation::Value
* endValue
= endValues
.AppendElement();
398 if (segment
.endState().type() == Animatable::TArrayOfTransformFunction
) {
399 const InfallibleTArray
<TransformFunction
>& startFunctions
=
400 segment
.startState().get_ArrayOfTransformFunction();
401 startValue
->SetAndAdoptCSSValueListValue(CreateCSSValueList(startFunctions
),
402 nsStyleAnimation::eUnit_Transform
);
404 const InfallibleTArray
<TransformFunction
>& endFunctions
=
405 segment
.endState().get_ArrayOfTransformFunction();
406 endValue
->SetAndAdoptCSSValueListValue(CreateCSSValueList(endFunctions
),
407 nsStyleAnimation::eUnit_Transform
);
409 NS_ASSERTION(segment
.endState().type() == Animatable::Tfloat
,
410 "Unknown Animatable type");
411 startValue
->SetFloatValue(segment
.startState().get_float());
412 endValue
->SetFloatValue(segment
.endState().get_float());
421 ContainerLayer::SetAsyncPanZoomController(AsyncPanZoomController
*controller
)
426 AsyncPanZoomController
*
427 ContainerLayer::GetAsyncPanZoomController() const
431 MOZ_ASSERT(GetFrameMetrics().IsScrollable());
438 Layer::ApplyPendingUpdatesToSubtree()
440 ApplyPendingUpdatesForThisTransaction();
441 for (Layer
* child
= GetFirstChild(); child
; child
= child
->GetNextSibling()) {
442 child
->ApplyPendingUpdatesToSubtree();
447 Layer::CanUseOpaqueSurface()
449 // If the visible content in the layer is opaque, there is no need
450 // for an alpha channel.
451 if (GetContentFlags() & CONTENT_OPAQUE
)
453 // Also, if this layer is the bottommost layer in a container which
454 // doesn't need an alpha channel, we can use an opaque surface for this
455 // layer too. Any transparent areas must be covered by something else
457 ContainerLayer
* parent
= GetParent();
458 return parent
&& parent
->GetFirstChild() == this &&
459 parent
->CanUseOpaqueSurface();
462 // NB: eventually these methods will be defined unconditionally, and
463 // can be moved into Layers.h
465 Layer::GetEffectiveClipRect()
467 if (LayerComposite
* shadow
= AsLayerComposite()) {
468 return shadow
->GetShadowClipRect();
470 return GetClipRect();
474 Layer::GetEffectiveVisibleRegion()
476 if (LayerComposite
* shadow
= AsLayerComposite()) {
477 return shadow
->GetShadowVisibleRegion();
479 return GetVisibleRegion();
483 Layer::SnapTransformTranslation(const gfx3DMatrix
& aTransform
,
484 gfxMatrix
* aResidualTransform
)
486 if (aResidualTransform
) {
487 *aResidualTransform
= gfxMatrix();
492 if (mManager
->IsSnappingEffectiveTransforms() &&
493 aTransform
.Is2D(&matrix2D
) &&
494 !matrix2D
.HasNonTranslation() &&
495 matrix2D
.HasNonIntegerTranslation()) {
496 gfxPoint
snappedTranslation(matrix2D
.GetTranslation());
497 snappedTranslation
.Round();
498 gfxMatrix snappedMatrix
= gfxMatrix().Translate(snappedTranslation
);
499 result
= gfx3DMatrix::From2D(snappedMatrix
);
500 if (aResidualTransform
) {
501 // set aResidualTransform so that aResidual * snappedMatrix == matrix2D.
502 // (I.e., appying snappedMatrix after aResidualTransform gives the
504 *aResidualTransform
=
505 gfxMatrix().Translate(matrix2D
.GetTranslation() - snappedTranslation
);
514 Layer::SnapTransform(const gfx3DMatrix
& aTransform
,
515 const gfxRect
& aSnapRect
,
516 gfxMatrix
* aResidualTransform
)
518 if (aResidualTransform
) {
519 *aResidualTransform
= gfxMatrix();
524 if (mManager
->IsSnappingEffectiveTransforms() &&
525 aTransform
.Is2D(&matrix2D
) &&
526 gfxSize(1.0, 1.0) <= aSnapRect
.Size() &&
527 matrix2D
.PreservesAxisAlignedRectangles()) {
528 gfxPoint transformedTopLeft
= matrix2D
.Transform(aSnapRect
.TopLeft());
529 transformedTopLeft
.Round();
530 gfxPoint transformedTopRight
= matrix2D
.Transform(aSnapRect
.TopRight());
531 transformedTopRight
.Round();
532 gfxPoint transformedBottomRight
= matrix2D
.Transform(aSnapRect
.BottomRight());
533 transformedBottomRight
.Round();
535 gfxMatrix snappedMatrix
= gfxUtils::TransformRectToRect(aSnapRect
,
536 transformedTopLeft
, transformedTopRight
, transformedBottomRight
);
538 result
= gfx3DMatrix::From2D(snappedMatrix
);
539 if (aResidualTransform
&& !snappedMatrix
.IsSingular()) {
540 // set aResidualTransform so that aResidual * snappedMatrix == matrix2D.
541 // (i.e., appying snappedMatrix after aResidualTransform gives the
543 gfxMatrix snappedMatrixInverse
= snappedMatrix
;
544 snappedMatrixInverse
.Invert();
545 *aResidualTransform
= matrix2D
* snappedMatrixInverse
;
554 AncestorLayerMayChangeTransform(Layer
* aLayer
)
556 for (Layer
* l
= aLayer
; l
; l
= l
->GetParent()) {
557 if (l
->GetContentFlags() & Layer::CONTENT_MAY_CHANGE_TRANSFORM
) {
567 gfxMatrix transform2d
;
568 return !GetEffectiveTransform().Is2D(&transform2d
) ||
569 transform2d
.HasNonIntegerTranslation() ||
570 AncestorLayerMayChangeTransform(this);
574 Layer::CalculateScissorRect(const nsIntRect
& aCurrentScissorRect
,
575 const gfxMatrix
* aWorldTransform
)
577 ContainerLayer
* container
= GetParent();
578 NS_ASSERTION(container
, "This can't be called on the root!");
580 // Establish initial clip rect: it's either the one passed in, or
581 // if the parent has an intermediate surface, it's the extents of that surface.
582 nsIntRect currentClip
;
583 if (container
->UseIntermediateSurface()) {
584 currentClip
.SizeTo(container
->GetIntermediateSurfaceRect().Size());
586 currentClip
= aCurrentScissorRect
;
589 const nsIntRect
*clipRect
= GetEffectiveClipRect();
593 if (clipRect
->IsEmpty()) {
594 // We might have a non-translation transform in the container so we can't
595 // use the code path below.
596 return nsIntRect(currentClip
.TopLeft(), nsIntSize(0, 0));
599 nsIntRect scissor
= *clipRect
;
600 if (!container
->UseIntermediateSurface()) {
602 DebugOnly
<bool> is2D
= container
->GetEffectiveTransform().Is2D(&matrix
);
603 // See DefaultComputeEffectiveTransforms below
604 NS_ASSERTION(is2D
&& matrix
.PreservesAxisAlignedRectangles(),
605 "Non preserves axis aligned transform with clipped child should have forced intermediate surface");
606 gfxRect
r(scissor
.x
, scissor
.y
, scissor
.width
, scissor
.height
);
607 gfxRect trScissor
= matrix
.TransformBounds(r
);
609 if (!gfxUtils::GfxRectToIntRect(trScissor
, &scissor
)) {
610 return nsIntRect(currentClip
.TopLeft(), nsIntSize(0, 0));
613 // Find the nearest ancestor with an intermediate surface
615 container
= container
->GetParent();
616 } while (container
&& !container
->UseIntermediateSurface());
619 scissor
.MoveBy(-container
->GetIntermediateSurfaceRect().TopLeft());
620 } else if (aWorldTransform
) {
621 gfxRect
r(scissor
.x
, scissor
.y
, scissor
.width
, scissor
.height
);
622 gfxRect trScissor
= aWorldTransform
->TransformBounds(r
);
624 if (!gfxUtils::GfxRectToIntRect(trScissor
, &scissor
))
625 return nsIntRect(currentClip
.TopLeft(), nsIntSize(0, 0));
627 return currentClip
.Intersect(scissor
);
631 Layer::GetTransform() const
633 gfx3DMatrix transform
= mTransform
;
634 if (const ContainerLayer
* c
= AsContainerLayer()) {
635 transform
.Scale(c
->GetPreXScale(), c
->GetPreYScale(), 1.0f
);
637 transform
.ScalePost(mPostXScale
, mPostYScale
, 1.0f
);
642 Layer::GetLocalTransform()
644 gfx3DMatrix transform
;
645 if (LayerComposite
* shadow
= AsLayerComposite())
646 transform
= shadow
->GetShadowTransform();
648 transform
= mTransform
;
649 if (ContainerLayer
* c
= AsContainerLayer()) {
650 transform
.Scale(c
->GetPreXScale(), c
->GetPreYScale(), 1.0f
);
652 transform
.ScalePost(mPostXScale
, mPostYScale
, 1.0f
);
657 Layer::ApplyPendingUpdatesForThisTransaction()
659 if (mPendingTransform
&& *mPendingTransform
!= mTransform
) {
660 MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) PendingUpdatesForThisTransaction", this));
661 mTransform
= *mPendingTransform
;
664 mPendingTransform
= nullptr;
668 Layer::GetLocalOpacity()
670 if (LayerComposite
* shadow
= AsLayerComposite())
671 return shadow
->GetShadowOpacity();
676 Layer::GetEffectiveOpacity()
678 float opacity
= GetLocalOpacity();
679 for (ContainerLayer
* c
= GetParent(); c
&& !c
->UseIntermediateSurface();
680 c
= c
->GetParent()) {
681 opacity
*= c
->GetLocalOpacity();
686 gfxContext::GraphicsOperator
687 Layer::GetEffectiveMixBlendMode()
689 if(mMixBlendMode
!= gfxContext::OPERATOR_OVER
)
690 return mMixBlendMode
;
691 for (ContainerLayer
* c
= GetParent(); c
&& !c
->UseIntermediateSurface();
692 c
= c
->GetParent()) {
693 if(c
->mMixBlendMode
!= gfxContext::OPERATOR_OVER
)
694 return c
->mMixBlendMode
;
697 return mMixBlendMode
;
701 Layer::ComputeEffectiveTransformForMaskLayer(const gfx3DMatrix
& aTransformToSurface
)
704 mMaskLayer
->mEffectiveTransform
= aTransformToSurface
;
707 gfxMatrix maskTranslation
;
708 bool maskIs2D
= mMaskLayer
->GetTransform().CanDraw2D(&maskTranslation
);
709 NS_ASSERTION(maskIs2D
, "How did we end up with a 3D transform here?!");
711 mMaskLayer
->mEffectiveTransform
.PreMultiply(mMaskLayer
->GetTransform());
715 ContainerLayer::ContainerLayer(LayerManager
* aManager
, void* aImplData
)
716 : Layer(aManager
, aImplData
),
717 mFirstChild(nullptr),
721 mInheritedXScale(1.0f
),
722 mInheritedYScale(1.0f
),
723 mUseIntermediateSurface(false),
724 mSupportsComponentAlphaChildren(false),
725 mMayHaveReadbackChild(false)
727 mContentFlags
= 0; // Clear NO_TEXT, NO_TEXT_OVER_TRANSPARENT
730 ContainerLayer::~ContainerLayer() {}
733 ContainerLayer::InsertAfter(Layer
* aChild
, Layer
* aAfter
)
735 NS_ASSERTION(aChild
->Manager() == Manager(),
736 "Child has wrong manager");
737 NS_ASSERTION(!aChild
->GetParent(),
738 "aChild already in the tree");
739 NS_ASSERTION(!aChild
->GetNextSibling() && !aChild
->GetPrevSibling(),
740 "aChild already has siblings?");
741 NS_ASSERTION(!aAfter
||
742 (aAfter
->Manager() == Manager() &&
743 aAfter
->GetParent() == this),
744 "aAfter is not our child");
746 aChild
->SetParent(this);
747 if (aAfter
== mLastChild
) {
751 aChild
->SetNextSibling(mFirstChild
);
753 mFirstChild
->SetPrevSibling(aChild
);
755 mFirstChild
= aChild
;
757 DidInsertChild(aChild
);
761 Layer
* next
= aAfter
->GetNextSibling();
762 aChild
->SetNextSibling(next
);
763 aChild
->SetPrevSibling(aAfter
);
765 next
->SetPrevSibling(aChild
);
767 aAfter
->SetNextSibling(aChild
);
769 DidInsertChild(aChild
);
773 ContainerLayer::RemoveChild(Layer
*aChild
)
775 NS_ASSERTION(aChild
->Manager() == Manager(),
776 "Child has wrong manager");
777 NS_ASSERTION(aChild
->GetParent() == this,
778 "aChild not our child");
780 Layer
* prev
= aChild
->GetPrevSibling();
781 Layer
* next
= aChild
->GetNextSibling();
783 prev
->SetNextSibling(next
);
785 this->mFirstChild
= next
;
788 next
->SetPrevSibling(prev
);
790 this->mLastChild
= prev
;
793 aChild
->SetNextSibling(nullptr);
794 aChild
->SetPrevSibling(nullptr);
795 aChild
->SetParent(nullptr);
797 this->DidRemoveChild(aChild
);
803 ContainerLayer::RepositionChild(Layer
* aChild
, Layer
* aAfter
)
805 NS_ASSERTION(aChild
->Manager() == Manager(),
806 "Child has wrong manager");
807 NS_ASSERTION(aChild
->GetParent() == this,
808 "aChild not our child");
809 NS_ASSERTION(!aAfter
||
810 (aAfter
->Manager() == Manager() &&
811 aAfter
->GetParent() == this),
812 "aAfter is not our child");
814 Layer
* prev
= aChild
->GetPrevSibling();
815 Layer
* next
= aChild
->GetNextSibling();
816 if (prev
== aAfter
) {
817 // aChild is already in the correct position, nothing to do.
821 prev
->SetNextSibling(next
);
824 next
->SetPrevSibling(prev
);
827 aChild
->SetPrevSibling(nullptr);
828 aChild
->SetNextSibling(mFirstChild
);
830 mFirstChild
->SetPrevSibling(aChild
);
832 mFirstChild
= aChild
;
836 Layer
* afterNext
= aAfter
->GetNextSibling();
838 afterNext
->SetPrevSibling(aChild
);
842 aAfter
->SetNextSibling(aChild
);
843 aChild
->SetPrevSibling(aAfter
);
844 aChild
->SetNextSibling(afterNext
);
848 ContainerLayer::FillSpecificAttributes(SpecificLayerAttributes
& aAttrs
)
850 aAttrs
= ContainerLayerAttributes(GetFrameMetrics(), mPreXScale
, mPreYScale
,
851 mInheritedXScale
, mInheritedYScale
);
855 ContainerLayer::HasMultipleChildren()
858 for (Layer
* child
= GetFirstChild(); child
; child
= child
->GetNextSibling()) {
859 const nsIntRect
*clipRect
= child
->GetEffectiveClipRect();
860 if (clipRect
&& clipRect
->IsEmpty())
862 if (child
->GetVisibleRegion().IsEmpty())
873 ContainerLayer::SortChildrenBy3DZOrder(nsTArray
<Layer
*>& aArray
)
875 nsAutoTArray
<Layer
*, 10> toSort
;
877 for (Layer
* l
= GetFirstChild(); l
; l
= l
->GetNextSibling()) {
878 ContainerLayer
* container
= l
->AsContainerLayer();
879 if (container
&& container
->GetContentFlags() & CONTENT_PRESERVE_3D
) {
880 toSort
.AppendElement(l
);
882 if (toSort
.Length() > 0) {
883 SortLayersBy3DZOrder(toSort
);
884 aArray
.MoveElementsFrom(toSort
);
886 aArray
.AppendElement(l
);
889 if (toSort
.Length() > 0) {
890 SortLayersBy3DZOrder(toSort
);
891 aArray
.MoveElementsFrom(toSort
);
896 ContainerLayer::DefaultComputeEffectiveTransforms(const gfx3DMatrix
& aTransformToSurface
)
899 gfx3DMatrix idealTransform
= GetLocalTransform()*aTransformToSurface
;
900 idealTransform
.ProjectTo2D();
901 mEffectiveTransform
= SnapTransformTranslation(idealTransform
, &residual
);
903 bool useIntermediateSurface
;
904 if (GetMaskLayer()) {
905 useIntermediateSurface
= true;
906 #ifdef MOZ_DUMP_PAINTING
907 } else if (gfxUtils::sDumpPainting
) {
908 useIntermediateSurface
= true;
911 float opacity
= GetEffectiveOpacity();
912 if (opacity
!= 1.0f
&& HasMultipleChildren()) {
913 useIntermediateSurface
= true;
915 useIntermediateSurface
= false;
916 gfxMatrix contTransform
;
917 if (!mEffectiveTransform
.Is2D(&contTransform
) ||
918 #ifdef MOZ_GFX_OPTIMIZE_MOBILE
919 !contTransform
.PreservesAxisAlignedRectangles()) {
921 contTransform
.HasNonIntegerTranslation()) {
923 for (Layer
* child
= GetFirstChild(); child
; child
= child
->GetNextSibling()) {
924 const nsIntRect
*clipRect
= child
->GetEffectiveClipRect();
925 /* We can't (easily) forward our transform to children with a non-empty clip
926 * rect since it would need to be adjusted for the transform. See
927 * the calculations performed by CalculateScissorRect above.
928 * Nor for a child with a mask layer.
930 if ((clipRect
&& !clipRect
->IsEmpty() && !child
->GetVisibleRegion().IsEmpty()) ||
931 child
->GetMaskLayer()) {
932 useIntermediateSurface
= true;
940 mUseIntermediateSurface
= useIntermediateSurface
;
941 if (useIntermediateSurface
) {
942 ComputeEffectiveTransformsForChildren(gfx3DMatrix::From2D(residual
));
944 ComputeEffectiveTransformsForChildren(idealTransform
);
947 if (idealTransform
.CanDraw2D()) {
948 ComputeEffectiveTransformForMaskLayer(aTransformToSurface
);
950 ComputeEffectiveTransformForMaskLayer(gfx3DMatrix());
955 ContainerLayer::ComputeEffectiveTransformsForChildren(const gfx3DMatrix
& aTransformToSurface
)
957 for (Layer
* l
= mFirstChild
; l
; l
= l
->GetNextSibling()) {
958 l
->ComputeEffectiveTransforms(aTransformToSurface
);
963 ContainerLayer::HasOpaqueAncestorLayer(Layer
* aLayer
)
965 for (Layer
* l
= aLayer
->GetParent(); l
; l
= l
->GetParent()) {
966 if (l
->GetContentFlags() & Layer::CONTENT_OPAQUE
)
973 ContainerLayer::DidRemoveChild(Layer
* aLayer
)
975 ThebesLayer
* tl
= aLayer
->AsThebesLayer();
976 if (tl
&& tl
->UsedForReadback()) {
977 for (Layer
* l
= mFirstChild
; l
; l
= l
->GetNextSibling()) {
978 if (l
->GetType() == TYPE_READBACK
) {
979 static_cast<ReadbackLayer
*>(l
)->NotifyThebesLayerRemoved(tl
);
983 if (aLayer
->GetType() == TYPE_READBACK
) {
984 static_cast<ReadbackLayer
*>(aLayer
)->NotifyRemoved();
989 ContainerLayer::DidInsertChild(Layer
* aLayer
)
991 if (aLayer
->GetType() == TYPE_READBACK
) {
992 mMayHaveReadbackChild
= true;
997 RefLayer::FillSpecificAttributes(SpecificLayerAttributes
& aAttrs
)
999 aAttrs
= RefLayerAttributes(GetReferentId());
1003 * StartFrameTimeRecording, together with StopFrameTimeRecording
1004 * enable recording of frame intrvals and paint times.
1005 * (Paint start time is set from the refresh driver right before starting
1006 * flush/paint and ends at PostPresent. Intervals are measured at PostPresent).
1008 * To allow concurrent consumers, 2 cyclic arrays are used (for intervals, paints)
1009 * which serve all consumers, practically stateless with regard to consumers.
1011 * To save resources, the buffers are allocated on first call to StartFrameTimeRecording
1012 * and recording is paused if no consumer which called StartFrameTimeRecording is able
1013 * to get valid results (because the cyclic buffers were overwritten since that call).
1015 * To determine availability of the data upon StopFrameTimeRecording:
1016 * - mRecording.mNextIndex increases on each PostPresent, and never resets.
1017 * - Cyclic buffer position is realized as mNextIndex % bufferSize.
1018 * - StartFrameTimeRecording returns mNextIndex. When StopFrameTimeRecording is called,
1019 * the required start index is passed as an arg, and we're able to calculate the required
1020 * length. If this length is bigger than bufferSize, it means data was overwritten.
1021 * otherwise, we can return the entire sequence.
1022 * - To determine if we need to pause, mLatestStartIndex is updated to mNextIndex
1023 * on each call to StartFrameTimeRecording. If this index gets overwritten,
1024 * it means that all earlier start indices obtained via StartFrameTimeRecording
1025 * were also overwritten, hence, no point in recording, so pause.
1026 * - mCurrentRunStartIndex indicates the oldest index of the recording after which
1027 * the recording was not paused. If StopFrameTimeRecording is invoked with a start index
1028 * older than this, it means that some frames were not recorded, so data is invalid.
1031 LayerManager::StartFrameTimeRecording()
1033 if (mRecording
.mIsPaused
) {
1034 mRecording
.mIsPaused
= false;
1036 if (!mRecording
.mIntervals
.Length()) { // Initialize recording buffers
1037 const uint32_t kRecordingMinSize
= 60 * 10; // 10 seconds @60 fps.
1038 const uint32_t kRecordingMaxSize
= 60 * 60 * 60; // One hour
1039 uint32_t bufferSize
= Preferences::GetUint("toolkit.framesRecording.bufferSize",
1041 bufferSize
= std::min(bufferSize
, kRecordingMaxSize
);
1042 bufferSize
= std::max(bufferSize
, kRecordingMinSize
);
1044 if (!mRecording
.mIntervals
.SetLength(bufferSize
) || !mRecording
.mPaints
.SetLength(bufferSize
)) {
1045 mRecording
.mIsPaused
= true; // OOM
1046 mRecording
.mIntervals
.Clear();
1047 mRecording
.mPaints
.Clear();
1051 // After being paused, recent values got invalid. Update them to now.
1052 mRecording
.mLastFrameTime
= TimeStamp::Now();
1053 mRecording
.mPaintStartTime
= mRecording
.mLastFrameTime
;
1055 // Any recording which started before this is invalid, since we were paused.
1056 mRecording
.mCurrentRunStartIndex
= mRecording
.mNextIndex
;
1059 // If we'll overwrite this index, there are no more consumers with aStartIndex
1060 // for which we're able to provide the full recording, so no point in keep recording.
1061 mRecording
.mLatestStartIndex
= mRecording
.mNextIndex
;
1062 return mRecording
.mNextIndex
;
1066 LayerManager::SetPaintStartTime(TimeStamp
& aTime
)
1068 if (!mRecording
.mIsPaused
) {
1069 mRecording
.mPaintStartTime
= aTime
;
1074 LayerManager::PostPresent()
1076 if (!mRecording
.mIsPaused
) {
1077 TimeStamp now
= TimeStamp::Now();
1078 uint32_t i
= mRecording
.mNextIndex
% mRecording
.mIntervals
.Length();
1079 mRecording
.mIntervals
[i
] = static_cast<float>((now
- mRecording
.mLastFrameTime
)
1081 mRecording
.mPaints
[i
] = static_cast<float>((now
- mRecording
.mPaintStartTime
)
1083 mRecording
.mNextIndex
++;
1084 mRecording
.mLastFrameTime
= now
;
1086 if (mRecording
.mNextIndex
> (mRecording
.mLatestStartIndex
+ mRecording
.mIntervals
.Length())) {
1087 // We've just overwritten the most recent recording start -> pause.
1088 mRecording
.mIsPaused
= true;
1091 if (!mTabSwitchStart
.IsNull()) {
1092 Telemetry::Accumulate(Telemetry::FX_TAB_SWITCH_TOTAL_MS
,
1093 uint32_t((TimeStamp::Now() - mTabSwitchStart
).ToMilliseconds()));
1094 mTabSwitchStart
= TimeStamp();
1099 LayerManager::StopFrameTimeRecording(uint32_t aStartIndex
,
1100 nsTArray
<float>& aFrameIntervals
,
1101 nsTArray
<float>& aPaintTimes
)
1103 uint32_t bufferSize
= mRecording
.mIntervals
.Length();
1104 uint32_t length
= mRecording
.mNextIndex
- aStartIndex
;
1105 if (mRecording
.mIsPaused
|| length
> bufferSize
|| aStartIndex
< mRecording
.mCurrentRunStartIndex
) {
1106 // aStartIndex is too old. Also if aStartIndex was issued before mRecordingNextIndex overflowed (uint32_t)
1107 // and stopped after the overflow (would happen once every 828 days of constant 60fps).
1111 // Set length in advance to avoid possibly repeated reallocations (and OOM checks).
1112 if (!length
|| !aFrameIntervals
.SetLength(length
) || !aPaintTimes
.SetLength(length
)) {
1113 aFrameIntervals
.Clear();
1114 aPaintTimes
.Clear();
1115 return; // empty recording or OOM, return empty arrays.
1118 uint32_t cyclicPos
= aStartIndex
% bufferSize
;
1119 for (uint32_t i
= 0; i
< length
; i
++, cyclicPos
++) {
1120 if (cyclicPos
== bufferSize
) {
1123 aFrameIntervals
[i
] = mRecording
.mIntervals
[cyclicPos
];
1124 aPaintTimes
[i
] = mRecording
.mPaints
[cyclicPos
];
1129 LayerManager::BeginTabSwitch()
1131 mTabSwitchStart
= TimeStamp::Now();
1134 #ifdef MOZ_LAYERS_HAVE_LOG
1136 static nsACString
& PrintInfo(nsACString
& aTo
, LayerComposite
* aLayerComposite
);
1138 #ifdef MOZ_DUMP_PAINTING
1139 template <typename T
>
1140 void WriteSnapshotLinkToDumpFile(T
* aObj
, FILE* aFile
)
1145 nsCString
string(aObj
->Name());
1147 string
.AppendInt((uint64_t)aObj
);
1148 fprintf(aFile
, "href=\"javascript:ViewImage('%s')\"", string
.BeginReading());
1151 template <typename T
>
1152 void WriteSnapshotToDumpFile_internal(T
* aObj
, gfxASurface
* aSurf
)
1154 nsCString
string(aObj
->Name());
1156 string
.AppendInt((uint64_t)aObj
);
1157 if (gfxUtils::sDumpPaintFile
)
1158 fprintf(gfxUtils::sDumpPaintFile
, "array[\"%s\"]=\"", string
.BeginReading());
1159 aSurf
->DumpAsDataURL(gfxUtils::sDumpPaintFile
);
1160 if (gfxUtils::sDumpPaintFile
)
1161 fprintf(gfxUtils::sDumpPaintFile
, "\";");
1164 void WriteSnapshotToDumpFile(Layer
* aLayer
, gfxASurface
* aSurf
)
1166 WriteSnapshotToDumpFile_internal(aLayer
, aSurf
);
1169 void WriteSnapshotToDumpFile(LayerManager
* aManager
, gfxASurface
* aSurf
)
1171 WriteSnapshotToDumpFile_internal(aManager
, aSurf
);
1174 void WriteSnapshotToDumpFile(Compositor
* aCompositor
, DrawTarget
* aTarget
)
1176 nsRefPtr
<gfxASurface
> surf
= gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(aTarget
);
1177 WriteSnapshotToDumpFile_internal(aCompositor
, surf
);
1182 Layer::Dump(FILE* aFile
, const char* aPrefix
, bool aDumpHtml
)
1185 fprintf(aFile
, "<li><a id=\"%p\" ", this);
1186 #ifdef MOZ_DUMP_PAINTING
1187 if (GetType() == TYPE_CONTAINER
|| GetType() == TYPE_THEBES
) {
1188 WriteSnapshotLinkToDumpFile(this, aFile
);
1191 fprintf(aFile
, ">");
1193 DumpSelf(aFile
, aPrefix
);
1195 #ifdef MOZ_DUMP_PAINTING
1196 if (AsLayerComposite() && AsLayerComposite()->GetCompositableHost()) {
1197 AsLayerComposite()->GetCompositableHost()->Dump(aFile
, aPrefix
, aDumpHtml
);
1202 fprintf(aFile
, "</a>");
1205 if (Layer
* mask
= GetMaskLayer()) {
1206 nsAutoCString
pfx(aPrefix
);
1207 pfx
+= " Mask layer: ";
1208 mask
->Dump(aFile
, pfx
.get(), aDumpHtml
);
1211 if (Layer
* kid
= GetFirstChild()) {
1212 nsAutoCString
pfx(aPrefix
);
1215 fprintf(aFile
, "<ul>");
1217 kid
->Dump(aFile
, pfx
.get(), aDumpHtml
);
1219 fprintf(aFile
, "</ul>");
1224 fprintf(aFile
, "</li>");
1226 if (Layer
* next
= GetNextSibling())
1227 next
->Dump(aFile
, aPrefix
, aDumpHtml
);
1231 Layer::DumpSelf(FILE* aFile
, const char* aPrefix
)
1234 PrintInfo(str
, aPrefix
);
1235 if (!aFile
|| aFile
== stderr
) {
1236 printf_stderr("%s\n", str
.get());
1238 fprintf(aFile
, "%s\n", str
.get());
1243 Layer::Log(const char* aPrefix
)
1245 if (!IsLogEnabled())
1250 if (Layer
* kid
= GetFirstChild()) {
1251 nsAutoCString
pfx(aPrefix
);
1253 kid
->Log(pfx
.get());
1256 if (Layer
* next
= GetNextSibling())
1261 Layer::LogSelf(const char* aPrefix
)
1263 if (!IsLogEnabled())
1267 PrintInfo(str
, aPrefix
);
1268 MOZ_LAYERS_LOG(("%s", str
.get()));
1272 Layer::PrintInfo(nsACString
& aTo
, const char* aPrefix
)
1275 aTo
+= nsPrintfCString("%s%s (0x%p)", mManager
->Name(), Name(), this);
1277 ::PrintInfo(aTo
, AsLayerComposite());
1280 AppendToString(aTo
, mClipRect
, " [clip=", "]");
1282 if (1.0 != mPostXScale
|| 1.0 != mPostYScale
) {
1283 aTo
.AppendPrintf(" [postScale=%g, %g]", mPostXScale
, mPostYScale
);
1285 if (!mTransform
.IsIdentity()) {
1286 AppendToString(aTo
, mTransform
, " [transform=", "]");
1288 if (!mVisibleRegion
.IsEmpty()) {
1289 AppendToString(aTo
, mVisibleRegion
, " [visible=", "]");
1291 aTo
+= " [not visible]";
1293 if (1.0 != mOpacity
) {
1294 aTo
.AppendPrintf(" [opacity=%g]", mOpacity
);
1296 if (GetContentFlags() & CONTENT_OPAQUE
) {
1297 aTo
+= " [opaqueContent]";
1299 if (GetContentFlags() & CONTENT_COMPONENT_ALPHA
) {
1300 aTo
+= " [componentAlpha]";
1302 if (GetIsFixedPosition()) {
1303 aTo
.AppendPrintf(" [isFixedPosition anchor=%f,%f]", mAnchor
.x
, mAnchor
.y
);
1305 if (GetIsStickyPosition()) {
1306 aTo
.AppendPrintf(" [isStickyPosition scrollId=%d outer=%f,%f %fx%f "
1307 "inner=%f,%f %fx%f]", mStickyPositionData
->mScrollId
,
1308 mStickyPositionData
->mOuter
.x
, mStickyPositionData
->mOuter
.y
,
1309 mStickyPositionData
->mOuter
.width
, mStickyPositionData
->mOuter
.height
,
1310 mStickyPositionData
->mInner
.x
, mStickyPositionData
->mInner
.y
,
1311 mStickyPositionData
->mInner
.width
, mStickyPositionData
->mInner
.height
);
1318 ThebesLayer::PrintInfo(nsACString
& aTo
, const char* aPrefix
)
1320 Layer::PrintInfo(aTo
, aPrefix
);
1321 if (!mValidRegion
.IsEmpty()) {
1322 AppendToString(aTo
, mValidRegion
, " [valid=", "]");
1328 ContainerLayer::PrintInfo(nsACString
& aTo
, const char* aPrefix
)
1330 Layer::PrintInfo(aTo
, aPrefix
);
1331 if (!mFrameMetrics
.IsDefault()) {
1332 AppendToString(aTo
, mFrameMetrics
, " [metrics=", "]");
1334 if (UseIntermediateSurface()) {
1335 aTo
+= " [usesTmpSurf]";
1337 if (1.0 != mPreXScale
|| 1.0 != mPreYScale
) {
1338 aTo
.AppendPrintf(" [preScale=%g, %g]", mPreXScale
, mPreYScale
);
1344 ColorLayer::PrintInfo(nsACString
& aTo
, const char* aPrefix
)
1346 Layer::PrintInfo(aTo
, aPrefix
);
1347 AppendToString(aTo
, mColor
, " [color=", "]");
1352 CanvasLayer::PrintInfo(nsACString
& aTo
, const char* aPrefix
)
1354 Layer::PrintInfo(aTo
, aPrefix
);
1355 if (mFilter
!= GraphicsFilter::FILTER_GOOD
) {
1356 AppendToString(aTo
, mFilter
, " [filter=", "]");
1362 ImageLayer::PrintInfo(nsACString
& aTo
, const char* aPrefix
)
1364 Layer::PrintInfo(aTo
, aPrefix
);
1365 if (mFilter
!= GraphicsFilter::FILTER_GOOD
) {
1366 AppendToString(aTo
, mFilter
, " [filter=", "]");
1372 RefLayer::PrintInfo(nsACString
& aTo
, const char* aPrefix
)
1374 ContainerLayer::PrintInfo(aTo
, aPrefix
);
1376 AppendToString(aTo
, mId
, " [id=", "]");
1382 ReadbackLayer::PrintInfo(nsACString
& aTo
, const char* aPrefix
)
1384 Layer::PrintInfo(aTo
, aPrefix
);
1385 AppendToString(aTo
, mSize
, " [size=", "]");
1386 if (mBackgroundLayer
) {
1387 AppendToString(aTo
, mBackgroundLayer
, " [backgroundLayer=", "]");
1388 AppendToString(aTo
, mBackgroundLayerOffset
, " [backgroundOffset=", "]");
1389 } else if (mBackgroundColor
.a
== 1.0) {
1390 AppendToString(aTo
, mBackgroundColor
, " [backgroundColor=", "]");
1392 aTo
+= " [nobackground]";
1397 //--------------------------------------------------
1401 LayerManager::Dump(FILE* aFile
, const char* aPrefix
, bool aDumpHtml
)
1403 FILE* file
= FILEOrDefault(aFile
);
1405 #ifdef MOZ_DUMP_PAINTING
1407 fprintf(file
, "<ul><li><a ");
1408 WriteSnapshotLinkToDumpFile(this, file
);
1412 DumpSelf(file
, aPrefix
);
1413 #ifdef MOZ_DUMP_PAINTING
1415 fprintf(file
, "</a>");
1419 nsAutoCString
pfx(aPrefix
);
1422 fprintf(file
, "%s(null)", pfx
.get());
1424 fprintf(file
, "</li></ul>");
1430 fprintf(file
, "<ul>");
1432 GetRoot()->Dump(file
, pfx
.get(), aDumpHtml
);
1434 fprintf(file
, "</ul></li></ul>");
1440 LayerManager::DumpSelf(FILE* aFile
, const char* aPrefix
)
1443 PrintInfo(str
, aPrefix
);
1444 fprintf(FILEOrDefault(aFile
), "%s\n", str
.get());
1448 LayerManager::Log(const char* aPrefix
)
1450 if (!IsLogEnabled())
1455 nsAutoCString
pfx(aPrefix
);
1458 MOZ_LAYERS_LOG(("%s(null)", pfx
.get()));
1462 GetRoot()->Log(pfx
.get());
1466 LayerManager::LogSelf(const char* aPrefix
)
1469 PrintInfo(str
, aPrefix
);
1470 MOZ_LAYERS_LOG(("%s", str
.get()));
1474 LayerManager::PrintInfo(nsACString
& aTo
, const char* aPrefix
)
1477 return aTo
+= nsPrintfCString("%sLayerManager (0x%p)", Name(), this);
1481 LayerManager::InitLog()
1484 sLog
= PR_NewLogModule("Layers");
1488 LayerManager::IsLogEnabled()
1490 NS_ABORT_IF_FALSE(!!sLog
,
1491 "layer manager must be created before logging is allowed");
1492 return PR_LOG_TEST(sLog
, PR_LOG_DEBUG
);
1496 PrintInfo(nsACString
& aTo
, LayerComposite
* aLayerComposite
)
1498 if (!aLayerComposite
) {
1501 if (const nsIntRect
* clipRect
= aLayerComposite
->GetShadowClipRect()) {
1502 AppendToString(aTo
, *clipRect
, " [shadow-clip=", "]");
1504 if (!aLayerComposite
->GetShadowTransform().IsIdentity()) {
1505 AppendToString(aTo
, aLayerComposite
->GetShadowTransform(), " [shadow-transform=", "]");
1507 if (!aLayerComposite
->GetShadowVisibleRegion().IsEmpty()) {
1508 AppendToString(aTo
, aLayerComposite
->GetShadowVisibleRegion(), " [shadow-visible=", "]");
1513 #else // !MOZ_LAYERS_HAVE_LOG
1515 void Layer::Dump(FILE* aFile
, const char* aPrefix
, bool aDumpHtml
) {}
1516 void Layer::DumpSelf(FILE* aFile
, const char* aPrefix
) {}
1517 void Layer::Log(const char* aPrefix
) {}
1518 void Layer::LogSelf(const char* aPrefix
) {}
1520 Layer::PrintInfo(nsACString
& aTo
, const char* aPrefix
)
1524 ThebesLayer::PrintInfo(nsACString
& aTo
, const char* aPrefix
)
1528 ContainerLayer::PrintInfo(nsACString
& aTo
, const char* aPrefix
)
1532 ColorLayer::PrintInfo(nsACString
& aTo
, const char* aPrefix
)
1536 CanvasLayer::PrintInfo(nsACString
& aTo
, const char* aPrefix
)
1540 ImageLayer::PrintInfo(nsACString
& aTo
, const char* aPrefix
)
1544 RefLayer::PrintInfo(nsACString
& aTo
, const char* aPrefix
)
1548 ReadbackLayer::PrintInfo(nsACString
& aTo
, const char* aPrefix
)
1551 void LayerManager::Dump(FILE* aFile
, const char* aPrefix
, bool aDumpHtml
) {}
1552 void LayerManager::DumpSelf(FILE* aFile
, const char* aPrefix
) {}
1553 void LayerManager::Log(const char* aPrefix
) {}
1554 void LayerManager::LogSelf(const char* aPrefix
) {}
1557 LayerManager::PrintInfo(nsACString
& aTo
, const char* aPrefix
)
1560 /*static*/ void LayerManager::InitLog() {}
1561 /*static*/ bool LayerManager::IsLogEnabled() { return false; }
1563 #endif // MOZ_LAYERS_HAVE_LOG
1565 PRLogModuleInfo
* LayerManager::sLog
;
1567 } // namespace layers
1568 } // namespace mozilla