1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
4 /* ***** BEGIN LICENSE BLOCK *****
5 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
7 * The contents of this file are subject to the Mozilla Public License Version
8 * 1.1 (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at:
10 * http://www.mozilla.org/MPL/
12 * Software distributed under the License is distributed on an "AS IS" basis,
13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 * for the specific language governing rights and limitations under the
17 * The Original Code is Mozilla Code.
19 * The Initial Developer of the Original Code is
20 * The Mozilla Foundation
21 * Portions created by the Initial Developer are Copyright (C) 2010
22 * the Initial Developer. All Rights Reserved.
25 * Chris Jones <jones.chris.g@gmail.com>
27 * Alternatively, the contents of this file may be used under the terms of
28 * either the GNU General Public License Version 2 or later (the "GPL"), or
29 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30 * in which case the provisions of the GPL or the LGPL are applicable instead
31 * of those above. If you wish to allow use of your version of this file only
32 * under the terms of either the GPL or the LGPL, and not to allow others to
33 * use your version of this file under the terms of the MPL, indicate your
34 * decision by deleting the provisions above and replace them with the notice
35 * and other provisions required by the GPL or the LGPL. If you do not delete
36 * the provisions above, a recipient may use your version of this file under
37 * the terms of any one of the MPL, the GPL or the LGPL.
39 * ***** END LICENSE BLOCK ***** */
42 # include "mozilla/layers/ShadowLayers.h"
45 #include "ImageLayers.h"
47 #include "gfxPlatform.h"
48 #include "ReadbackLayer.h"
50 using namespace mozilla::layers
;
52 typedef FrameMetrics::ViewID ViewID
;
53 const ViewID
FrameMetrics::NULL_SCROLL_ID
= 0;
54 const ViewID
FrameMetrics::ROOT_SCROLL_ID
= 1;
55 const ViewID
FrameMetrics::START_SCROLL_ID
= 2;
57 #ifdef MOZ_LAYERS_HAVE_LOG
59 FILEOrDefault(FILE* aFile
)
61 return aFile
? aFile
: stderr
;
63 #endif // MOZ_LAYERS_HAVE_LOG
67 // XXX pretty general utilities, could centralize
70 AppendToString(nsACString
& s
, const void* p
,
71 const char* pfx
="", const char* sfx
="")
74 s
+= nsPrintfCString(64, "%p", p
);
79 AppendToString(nsACString
& s
, const gfxPattern::GraphicsFilter
& f
,
80 const char* pfx
="", const char* sfx
="")
84 case gfxPattern::FILTER_FAST
: s
+= "fast"; break;
85 case gfxPattern::FILTER_GOOD
: s
+= "good"; break;
86 case gfxPattern::FILTER_BEST
: s
+= "best"; break;
87 case gfxPattern::FILTER_NEAREST
: s
+= "nearest"; break;
88 case gfxPattern::FILTER_BILINEAR
: s
+= "bilinear"; break;
89 case gfxPattern::FILTER_GAUSSIAN
: s
+= "gaussian"; break;
91 NS_ERROR("unknown filter type");
98 AppendToString(nsACString
& s
, ViewID n
,
99 const char* pfx
="", const char* sfx
="")
107 AppendToString(nsACString
& s
, const gfxRGBA
& c
,
108 const char* pfx
="", const char* sfx
="")
111 s
+= nsPrintfCString(
112 128, "rgba(%d, %d, %d, %g)",
113 PRUint8(c
.r
*255.0), PRUint8(c
.g
*255.0), PRUint8(c
.b
*255.0), c
.a
);
118 AppendToString(nsACString
& s
, const gfx3DMatrix
& m
,
119 const char* pfx
="", const char* sfx
="")
126 if (m
.Is2D(&matrix
)) {
127 s
+= nsPrintfCString(
128 96, "[ %g %g; %g %g; %g %g; ]",
129 matrix
.xx
, matrix
.yx
, matrix
.xy
, matrix
.yy
, matrix
.x0
, matrix
.y0
);
131 s
+= nsPrintfCString(
132 256, "[ %g %g %g %g; %g %g %g %g; %g %g %g %g; %g %g %g %g; ]",
133 m
._11
, m
._12
, m
._13
, m
._14
,
134 m
._21
, m
._22
, m
._23
, m
._24
,
135 m
._31
, m
._32
, m
._33
, m
._34
,
136 m
._41
, m
._42
, m
._43
, m
._44
);
143 AppendToString(nsACString
& s
, const nsIntPoint
& p
,
144 const char* pfx
="", const char* sfx
="")
147 s
+= nsPrintfCString(128, "(x=%d, y=%d)", p
.x
, p
.y
);
152 AppendToString(nsACString
& s
, const nsIntRect
& r
,
153 const char* pfx
="", const char* sfx
="")
156 s
+= nsPrintfCString(
157 256, "(x=%d, y=%d, w=%d, h=%d)",
158 r
.x
, r
.y
, r
.width
, r
.height
);
163 AppendToString(nsACString
& s
, const nsIntRegion
& r
,
164 const char* pfx
="", const char* sfx
="")
168 nsIntRegionRectIterator
it(r
);
170 while (const nsIntRect
* sr
= it
.Next())
171 AppendToString(s
, *sr
) += "; ";
178 AppendToString(nsACString
& s
, const nsIntSize
& sz
,
179 const char* pfx
="", const char* sfx
="")
182 s
+= nsPrintfCString(128, "(w=%d, h=%d)", sz
.width
, sz
.height
);
187 AppendToString(nsACString
& s
, const FrameMetrics
& m
,
188 const char* pfx
="", const char* sfx
="")
191 AppendToString(s
, m
.mViewport
, "{ viewport=");
192 AppendToString(s
, m
.mViewportScrollOffset
, " viewportScroll=");
193 AppendToString(s
, m
.mDisplayPort
, " displayport=");
194 AppendToString(s
, m
.mScrollId
, " scrollId=", " }");
198 } // namespace <anon>
203 //--------------------------------------------------
205 already_AddRefed
<gfxASurface
>
206 LayerManager::CreateOptimalSurface(const gfxIntSize
&aSize
,
207 gfxASurface::gfxImageFormat aFormat
)
209 return gfxPlatform::GetPlatform()->
210 CreateOffscreenSurface(aSize
, gfxASurface::ContentFromFormat(aFormat
));
215 LayerManager::Mutated(Layer
* aLayer
)
217 NS_ABORT_IF_FALSE(!aLayer
->GetTileSourceRect() ||
218 (LAYERS_BASIC
== GetBackendType() &&
219 Layer::TYPE_IMAGE
== aLayer
->GetType()),
220 "Tiling not supported for this manager/layer type");
224 //--------------------------------------------------
228 Layer::CanUseOpaqueSurface()
230 // If the visible content in the layer is opaque, there is no need
231 // for an alpha channel.
232 if (GetContentFlags() & CONTENT_OPAQUE
)
234 // Also, if this layer is the bottommost layer in a container which
235 // doesn't need an alpha channel, we can use an opaque surface for this
236 // layer too. Any transparent areas must be covered by something else
238 ContainerLayer
* parent
= GetParent();
239 return parent
&& parent
->GetFirstChild() == this &&
240 parent
->CanUseOpaqueSurface();
244 // NB: eventually these methods will be defined unconditionally, and
245 // can be moved into Layers.h
247 Layer::GetEffectiveClipRect()
249 if (ShadowLayer
* shadow
= AsShadowLayer()) {
250 return shadow
->GetShadowClipRect();
252 return GetClipRect();
256 Layer::GetEffectiveVisibleRegion()
258 if (ShadowLayer
* shadow
= AsShadowLayer()) {
259 return shadow
->GetShadowVisibleRegion();
261 return GetVisibleRegion();
266 const nsIntRect
* Layer::GetEffectiveClipRect() { return GetClipRect(); }
267 const nsIntRegion
& Layer::GetEffectiveVisibleRegion() { return GetVisibleRegion(); }
272 Layer::SnapTransform(const gfx3DMatrix
& aTransform
,
273 const gfxRect
& aSnapRect
,
274 gfxMatrix
* aResidualTransform
)
276 if (aResidualTransform
) {
277 *aResidualTransform
= gfxMatrix();
282 if (mManager
->IsSnappingEffectiveTransforms() &&
283 aTransform
.Is2D(&matrix2D
) &&
284 matrix2D
.HasNonIntegerTranslation() &&
285 !matrix2D
.IsSingular() &&
286 !matrix2D
.HasNonAxisAlignedTransform()) {
287 gfxMatrix snappedMatrix
;
288 gfxPoint topLeft
= matrix2D
.Transform(aSnapRect
.TopLeft());
290 // first compute scale factors that scale aSnapRect to the snapped rect
291 if (aSnapRect
.IsEmpty()) {
292 snappedMatrix
.xx
= matrix2D
.xx
;
293 snappedMatrix
.yy
= matrix2D
.yy
;
295 gfxPoint bottomRight
= matrix2D
.Transform(aSnapRect
.BottomRight());
297 snappedMatrix
.xx
= (bottomRight
.x
- topLeft
.x
)/aSnapRect
.Width();
298 snappedMatrix
.yy
= (bottomRight
.y
- topLeft
.y
)/aSnapRect
.Height();
300 // compute translation factors that will move aSnapRect to the snapped rect
301 // given those scale factors
302 snappedMatrix
.x0
= topLeft
.x
- aSnapRect
.pos
.x
*snappedMatrix
.xx
;
303 snappedMatrix
.y0
= topLeft
.y
- aSnapRect
.pos
.y
*snappedMatrix
.yy
;
304 result
= gfx3DMatrix::From2D(snappedMatrix
);
305 if (aResidualTransform
&& !snappedMatrix
.IsSingular()) {
306 // set aResidualTransform so that aResidual * snappedMatrix == matrix2D.
307 // (i.e., appying snappedMatrix after aResidualTransform gives the
309 gfxMatrix snappedMatrixInverse
= snappedMatrix
;
310 snappedMatrixInverse
.Invert();
311 *aResidualTransform
= matrix2D
* snappedMatrixInverse
;
320 Layer::GetLocalTransform()
323 if (ShadowLayer
* shadow
= AsShadowLayer())
324 return shadow
->GetShadowTransform();
330 Layer::GetEffectiveOpacity()
332 float opacity
= GetOpacity();
333 for (ContainerLayer
* c
= GetParent(); c
&& !c
->UseIntermediateSurface();
334 c
= c
->GetParent()) {
335 opacity
*= c
->GetOpacity();
341 ContainerLayer::HasMultipleChildren()
344 for (Layer
* child
= GetFirstChild(); child
; child
= child
->GetNextSibling()) {
345 const nsIntRect
*clipRect
= child
->GetEffectiveClipRect();
346 if (clipRect
&& clipRect
->IsEmpty())
348 if (child
->GetVisibleRegion().IsEmpty())
359 ContainerLayer::DefaultComputeEffectiveTransforms(const gfx3DMatrix
& aTransformToSurface
)
362 gfx3DMatrix idealTransform
= GetLocalTransform()*aTransformToSurface
;
363 mEffectiveTransform
= SnapTransform(idealTransform
, gfxRect(0, 0, 0, 0), &residual
);
365 PRBool useIntermediateSurface
;
366 float opacity
= GetEffectiveOpacity();
367 if (opacity
!= 1.0f
&& HasMultipleChildren()) {
368 useIntermediateSurface
= PR_TRUE
;
370 useIntermediateSurface
= PR_FALSE
;
371 gfxMatrix contTransform
;
372 if (!mEffectiveTransform
.Is2D(&contTransform
) ||
373 !contTransform
.PreservesAxisAlignedRectangles()) {
374 for (Layer
* child
= GetFirstChild(); child
; child
= child
->GetNextSibling()) {
375 const nsIntRect
*clipRect
= child
->GetEffectiveClipRect();
376 /* We can't (easily) forward our transform to children with a non-empty clip
377 * rect since it would need to be adjusted for the transform.
378 * TODO: This is easily solvable for translation/scaling transforms.
380 if (clipRect
&& !clipRect
->IsEmpty() && !child
->GetVisibleRegion().IsEmpty()) {
381 useIntermediateSurface
= PR_TRUE
;
388 mUseIntermediateSurface
= useIntermediateSurface
;
389 if (useIntermediateSurface
) {
390 ComputeEffectiveTransformsForChildren(gfx3DMatrix::From2D(residual
));
392 ComputeEffectiveTransformsForChildren(idealTransform
);
397 ContainerLayer::ComputeEffectiveTransformsForChildren(const gfx3DMatrix
& aTransformToSurface
)
399 for (Layer
* l
= mFirstChild
; l
; l
= l
->GetNextSibling()) {
400 l
->ComputeEffectiveTransforms(aTransformToSurface
);
405 ContainerLayer::DidRemoveChild(Layer
* aLayer
)
407 ThebesLayer
* tl
= aLayer
->AsThebesLayer();
408 if (tl
&& tl
->UsedForReadback()) {
409 for (Layer
* l
= mFirstChild
; l
; l
= l
->GetNextSibling()) {
410 if (l
->GetType() == TYPE_READBACK
) {
411 static_cast<ReadbackLayer
*>(l
)->NotifyThebesLayerRemoved(tl
);
415 if (aLayer
->GetType() == TYPE_READBACK
) {
416 static_cast<ReadbackLayer
*>(aLayer
)->NotifyRemoved();
421 ContainerLayer::DidInsertChild(Layer
* aLayer
)
423 if (aLayer
->GetType() == TYPE_READBACK
) {
424 mMayHaveReadbackChild
= PR_TRUE
;
428 #ifdef MOZ_LAYERS_HAVE_LOG
430 static nsACString
& PrintInfo(nsACString
& aTo
, ShadowLayer
* aShadowLayer
);
433 Layer::Dump(FILE* aFile
, const char* aPrefix
)
435 DumpSelf(aFile
, aPrefix
);
437 if (Layer
* kid
= GetFirstChild()) {
438 nsCAutoString
pfx(aPrefix
);
440 kid
->Dump(aFile
, pfx
.get());
443 if (Layer
* next
= GetNextSibling())
444 next
->Dump(aFile
, aPrefix
);
448 Layer::DumpSelf(FILE* aFile
, const char* aPrefix
)
451 PrintInfo(str
, aPrefix
);
452 fprintf(FILEOrDefault(aFile
), "%s\n", str
.get());
456 Layer::Log(const char* aPrefix
)
463 if (Layer
* kid
= GetFirstChild()) {
464 nsCAutoString
pfx(aPrefix
);
469 if (Layer
* next
= GetNextSibling())
474 Layer::LogSelf(const char* aPrefix
)
480 PrintInfo(str
, aPrefix
);
481 MOZ_LAYERS_LOG(("%s", str
.get()));
485 Layer::PrintInfo(nsACString
& aTo
, const char* aPrefix
)
488 aTo
+= nsPrintfCString(64, "%s%s (0x%p)", mManager
->Name(), Name(), this);
490 ::PrintInfo(aTo
, AsShadowLayer());
493 AppendToString(aTo
, mClipRect
, " [clip=", "]");
495 if (!mTransform
.IsIdentity()) {
496 AppendToString(aTo
, mTransform
, " [transform=", "]");
498 if (!mVisibleRegion
.IsEmpty()) {
499 AppendToString(aTo
, mVisibleRegion
, " [visible=", "]");
501 if (1.0 != mOpacity
) {
502 aTo
.AppendPrintf(" [opacity=%g]", mOpacity
);
504 if (const nsIntRect
* tileSourceRect
= GetTileSourceRect()) {
505 AppendToString(aTo
, *tileSourceRect
, " [tileSrc=", "]");
507 if (GetContentFlags() & CONTENT_OPAQUE
) {
508 aTo
+= " [opaqueContent]";
510 if (GetContentFlags() & CONTENT_COMPONENT_ALPHA
) {
511 aTo
+= " [componentAlpha]";
518 ThebesLayer::PrintInfo(nsACString
& aTo
, const char* aPrefix
)
520 Layer::PrintInfo(aTo
, aPrefix
);
521 if (!mValidRegion
.IsEmpty()) {
522 AppendToString(aTo
, mValidRegion
, " [valid=", "]");
524 if (mXResolution
!= 1.0 || mYResolution
!= 1.0) {
525 aTo
.AppendPrintf(" [xres=%g yres=%g]", mXResolution
, mYResolution
);
531 ContainerLayer::PrintInfo(nsACString
& aTo
, const char* aPrefix
)
533 Layer::PrintInfo(aTo
, aPrefix
);
534 if (!mFrameMetrics
.IsDefault()) {
535 AppendToString(aTo
, mFrameMetrics
, " [metrics=", "]");
537 if (UseIntermediateSurface()) {
538 aTo
+= " [usesTmpSurf]";
544 ColorLayer::PrintInfo(nsACString
& aTo
, const char* aPrefix
)
546 Layer::PrintInfo(aTo
, aPrefix
);
547 AppendToString(aTo
, mColor
, " [color=", "]");
552 CanvasLayer::PrintInfo(nsACString
& aTo
, const char* aPrefix
)
554 Layer::PrintInfo(aTo
, aPrefix
);
555 if (mFilter
!= gfxPattern::FILTER_GOOD
) {
556 AppendToString(aTo
, mFilter
, " [filter=", "]");
562 ImageLayer::PrintInfo(nsACString
& aTo
, const char* aPrefix
)
564 Layer::PrintInfo(aTo
, aPrefix
);
565 if (mFilter
!= gfxPattern::FILTER_GOOD
) {
566 AppendToString(aTo
, mFilter
, " [filter=", "]");
572 ReadbackLayer::PrintInfo(nsACString
& aTo
, const char* aPrefix
)
574 Layer::PrintInfo(aTo
, aPrefix
);
575 AppendToString(aTo
, mSize
, " [size=", "]");
576 if (mBackgroundLayer
) {
577 AppendToString(aTo
, mBackgroundLayer
, " [backgroundLayer=", "]");
578 AppendToString(aTo
, mBackgroundLayerOffset
, " [backgroundOffset=", "]");
579 } else if (mBackgroundColor
.a
== 1.0) {
580 AppendToString(aTo
, mBackgroundColor
, " [backgroundColor=", "]");
582 aTo
+= " [nobackground]";
587 //--------------------------------------------------
591 LayerManager::Dump(FILE* aFile
, const char* aPrefix
)
593 FILE* file
= FILEOrDefault(aFile
);
595 DumpSelf(file
, aPrefix
);
597 nsCAutoString
pfx(aPrefix
);
600 fprintf(file
, "%s(null)", pfx
.get());
604 GetRoot()->Dump(file
, pfx
.get());
608 LayerManager::DumpSelf(FILE* aFile
, const char* aPrefix
)
611 PrintInfo(str
, aPrefix
);
612 fprintf(FILEOrDefault(aFile
), "%s\n", str
.get());
616 LayerManager::Log(const char* aPrefix
)
623 nsCAutoString
pfx(aPrefix
);
626 MOZ_LAYERS_LOG(("%s(null)", pfx
.get()));
630 GetRoot()->Log(pfx
.get());
634 LayerManager::LogSelf(const char* aPrefix
)
637 PrintInfo(str
, aPrefix
);
638 MOZ_LAYERS_LOG(("%s", str
.get()));
642 LayerManager::PrintInfo(nsACString
& aTo
, const char* aPrefix
)
645 return aTo
+= nsPrintfCString(64, "%sLayerManager (0x%p)", Name(), this);
649 LayerManager::InitLog()
652 sLog
= PR_NewLogModule("Layers");
656 LayerManager::IsLogEnabled()
658 NS_ABORT_IF_FALSE(!!sLog
,
659 "layer manager must be created before logging is allowed");
660 return PR_LOG_TEST(sLog
, PR_LOG_DEBUG
);
665 PrintInfo(nsACString
& aTo
, ShadowLayer
* aShadowLayer
)
670 if (const nsIntRect
* clipRect
= aShadowLayer
->GetShadowClipRect()) {
671 AppendToString(aTo
, *clipRect
, " [shadow-clip=", "]");
673 if (!aShadowLayer
->GetShadowTransform().IsIdentity()) {
674 AppendToString(aTo
, aShadowLayer
->GetShadowTransform(), " [shadow-transform=", "]");
676 if (!aShadowLayer
->GetShadowVisibleRegion().IsEmpty()) {
677 AppendToString(aTo
, aShadowLayer
->GetShadowVisibleRegion(), " [shadow-visible=", "]");
682 static nsACString
& PrintInfo(nsACString
& aTo
, ShadowLayer
* aShadowLayer
)
688 #else // !MOZ_LAYERS_HAVE_LOG
690 void Layer::Dump(FILE* aFile
, const char* aPrefix
) {}
691 void Layer::DumpSelf(FILE* aFile
, const char* aPrefix
) {}
692 void Layer::Log(const char* aPrefix
) {}
693 void Layer::LogSelf(const char* aPrefix
) {}
695 Layer::PrintInfo(nsACString
& aTo
, const char* aPrefix
)
699 ThebesLayer::PrintInfo(nsACString
& aTo
, const char* aPrefix
)
703 ContainerLayer::PrintInfo(nsACString
& aTo
, const char* aPrefix
)
707 ColorLayer::PrintInfo(nsACString
& aTo
, const char* aPrefix
)
711 CanvasLayer::PrintInfo(nsACString
& aTo
, const char* aPrefix
)
715 ImageLayer::PrintInfo(nsACString
& aTo
, const char* aPrefix
)
719 ReadbackLayer::PrintInfo(nsACString
& aTo
, const char* aPrefix
)
722 void LayerManager::Dump(FILE* aFile
, const char* aPrefix
) {}
723 void LayerManager::DumpSelf(FILE* aFile
, const char* aPrefix
) {}
724 void LayerManager::Log(const char* aPrefix
) {}
725 void LayerManager::LogSelf(const char* aPrefix
) {}
728 LayerManager::PrintInfo(nsACString
& aTo
, const char* aPrefix
)
731 /*static*/ void LayerManager::InitLog() {}
732 /*static*/ bool LayerManager::IsLogEnabled() { return false; }
734 #endif // MOZ_LAYERS_HAVE_LOG
736 PRLogModuleInfo
* LayerManager::sLog
;
738 } // namespace layers
739 } // namespace mozilla