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"
49 using namespace mozilla::layers
;
51 typedef FrameMetrics::ViewID ViewID
;
52 const ViewID
FrameMetrics::NULL_SCROLL_ID
= 0;
53 const ViewID
FrameMetrics::ROOT_SCROLL_ID
= 1;
54 const ViewID
FrameMetrics::START_SCROLL_ID
= 2;
56 #ifdef MOZ_LAYERS_HAVE_LOG
58 FILEOrDefault(FILE* aFile
)
60 return aFile
? aFile
: stderr
;
62 #endif // MOZ_LAYERS_HAVE_LOG
66 // XXX pretty general utilities, could centralize
69 AppendToString(nsACString
& s
, const gfxPattern::GraphicsFilter
& f
,
70 const char* pfx
="", const char* sfx
="")
74 case gfxPattern::FILTER_FAST
: s
+= "fast"; break;
75 case gfxPattern::FILTER_GOOD
: s
+= "good"; break;
76 case gfxPattern::FILTER_BEST
: s
+= "best"; break;
77 case gfxPattern::FILTER_NEAREST
: s
+= "nearest"; break;
78 case gfxPattern::FILTER_BILINEAR
: s
+= "bilinear"; break;
79 case gfxPattern::FILTER_GAUSSIAN
: s
+= "gaussian"; break;
81 NS_ERROR("unknown filter type");
88 AppendToString(nsACString
& s
, ViewID n
,
89 const char* pfx
="", const char* sfx
="")
97 AppendToString(nsACString
& s
, const gfxRGBA
& c
,
98 const char* pfx
="", const char* sfx
="")
101 s
+= nsPrintfCString(
102 128, "rgba(%d, %d, %d, %g)",
103 PRUint8(c
.r
*255.0), PRUint8(c
.g
*255.0), PRUint8(c
.b
*255.0), c
.a
);
108 AppendToString(nsACString
& s
, const gfx3DMatrix
& m
,
109 const char* pfx
="", const char* sfx
="")
116 if (m
.Is2D(&matrix
)) {
117 s
+= nsPrintfCString(
118 96, "[ %g %g; %g %g; %g %g; ]",
119 matrix
.xx
, matrix
.yx
, matrix
.xy
, matrix
.yy
, matrix
.x0
, matrix
.y0
);
121 s
+= nsPrintfCString(
122 256, "[ %g %g %g %g; %g %g %g %g; %g %g %g %g; %g %g %g %g; ]",
123 m
._11
, m
._12
, m
._13
, m
._14
,
124 m
._21
, m
._22
, m
._23
, m
._24
,
125 m
._31
, m
._32
, m
._33
, m
._34
,
126 m
._41
, m
._42
, m
._43
, m
._44
);
133 AppendToString(nsACString
& s
, const nsIntPoint
& p
,
134 const char* pfx
="", const char* sfx
="")
137 s
+= nsPrintfCString(128, "(x=%d, y=%d)", p
.x
, p
.y
);
142 AppendToString(nsACString
& s
, const nsIntRect
& r
,
143 const char* pfx
="", const char* sfx
="")
146 s
+= nsPrintfCString(
147 256, "(x=%d, y=%d, w=%d, h=%d)",
148 r
.x
, r
.y
, r
.width
, r
.height
);
153 AppendToString(nsACString
& s
, const nsIntRegion
& r
,
154 const char* pfx
="", const char* sfx
="")
158 nsIntRegionRectIterator
it(r
);
160 while (const nsIntRect
* sr
= it
.Next())
161 AppendToString(s
, *sr
) += "; ";
168 AppendToString(nsACString
& s
, const nsIntSize
& sz
,
169 const char* pfx
="", const char* sfx
="")
172 s
+= nsPrintfCString(128, "(w=%d, h=%d)", sz
.width
, sz
.height
);
177 AppendToString(nsACString
& s
, const FrameMetrics
& m
,
178 const char* pfx
="", const char* sfx
="")
181 AppendToString(s
, m
.mViewport
, "{ viewport=");
182 AppendToString(s
, m
.mViewportScrollOffset
, " viewportScroll=");
183 AppendToString(s
, m
.mDisplayPort
, " displayport=");
184 AppendToString(s
, m
.mScrollId
, " scrollId=", " }");
188 } // namespace <anon>
193 //--------------------------------------------------
195 already_AddRefed
<gfxASurface
>
196 LayerManager::CreateOptimalSurface(const gfxIntSize
&aSize
,
197 gfxASurface::gfxImageFormat aFormat
)
199 return gfxPlatform::GetPlatform()->
200 CreateOffscreenSurface(aSize
, gfxASurface::ContentFromFormat(aFormat
));
205 LayerManager::Mutated(Layer
* aLayer
)
207 NS_ABORT_IF_FALSE(!aLayer
->GetTileSourceRect() ||
208 (LAYERS_BASIC
== GetBackendType() &&
209 Layer::TYPE_IMAGE
== aLayer
->GetType()),
210 "Tiling not supported for this manager/layer type");
214 //--------------------------------------------------
218 Layer::CanUseOpaqueSurface()
220 // If the visible content in the layer is opaque, there is no need
221 // for an alpha channel.
222 if (GetContentFlags() & CONTENT_OPAQUE
)
224 // Also, if this layer is the bottommost layer in a container which
225 // doesn't need an alpha channel, we can use an opaque surface for this
226 // layer too. Any transparent areas must be covered by something else
228 ContainerLayer
* parent
= GetParent();
229 return parent
&& parent
->GetFirstChild() == this &&
230 parent
->CanUseOpaqueSurface();
234 // NB: eventually these methods will be defined unconditionally, and
235 // can be moved into Layers.h
237 Layer::GetEffectiveClipRect()
239 if (ShadowLayer
* shadow
= AsShadowLayer()) {
240 return shadow
->GetShadowClipRect();
242 return GetClipRect();
246 Layer::GetEffectiveVisibleRegion()
248 if (ShadowLayer
* shadow
= AsShadowLayer()) {
249 return shadow
->GetShadowVisibleRegion();
251 return GetVisibleRegion();
256 const nsIntRect
* Layer::GetEffectiveClipRect() { return GetClipRect(); }
257 const nsIntRegion
& Layer::GetEffectiveVisibleRegion() { return GetVisibleRegion(); }
262 Layer::SnapTransform(const gfx3DMatrix
& aTransform
,
263 const gfxRect
& aSnapRect
,
264 gfxMatrix
* aResidualTransform
)
266 if (aResidualTransform
) {
267 *aResidualTransform
= gfxMatrix();
272 if (mManager
->IsSnappingEffectiveTransforms() &&
273 aTransform
.Is2D(&matrix2D
) &&
274 matrix2D
.HasNonIntegerTranslation() &&
275 !matrix2D
.IsSingular() &&
276 !matrix2D
.HasNonAxisAlignedTransform()) {
277 gfxMatrix snappedMatrix
;
278 gfxPoint topLeft
= matrix2D
.Transform(aSnapRect
.TopLeft());
280 // first compute scale factors that scale aSnapRect to the snapped rect
281 if (aSnapRect
.IsEmpty()) {
282 snappedMatrix
.xx
= matrix2D
.xx
;
283 snappedMatrix
.yy
= matrix2D
.yy
;
285 gfxPoint bottomRight
= matrix2D
.Transform(aSnapRect
.BottomRight());
287 snappedMatrix
.xx
= (bottomRight
.x
- topLeft
.x
)/aSnapRect
.Width();
288 snappedMatrix
.yy
= (bottomRight
.y
- topLeft
.y
)/aSnapRect
.Height();
290 // compute translation factors that will move aSnapRect to the snapped rect
291 // given those scale factors
292 snappedMatrix
.x0
= topLeft
.x
- aSnapRect
.pos
.x
*snappedMatrix
.xx
;
293 snappedMatrix
.y0
= topLeft
.y
- aSnapRect
.pos
.y
*snappedMatrix
.yy
;
294 result
= gfx3DMatrix::From2D(snappedMatrix
);
295 if (aResidualTransform
&& !snappedMatrix
.IsSingular()) {
296 // set aResidualTransform so that aResidual * snappedMatrix == matrix2D.
297 // (i.e., appying snappedMatrix after aResidualTransform gives the
299 gfxMatrix snappedMatrixInverse
= snappedMatrix
;
300 snappedMatrixInverse
.Invert();
301 *aResidualTransform
= matrix2D
* snappedMatrixInverse
;
310 Layer::GetLocalTransform()
313 if (ShadowLayer
* shadow
= AsShadowLayer())
314 return shadow
->GetShadowTransform();
320 Layer::GetEffectiveOpacity()
322 float opacity
= GetOpacity();
323 for (ContainerLayer
* c
= GetParent(); c
&& !c
->UseIntermediateSurface();
324 c
= c
->GetParent()) {
325 opacity
*= c
->GetOpacity();
331 ContainerLayer::HasMultipleChildren()
334 for (Layer
* child
= GetFirstChild(); child
; child
= child
->GetNextSibling()) {
335 const nsIntRect
*clipRect
= child
->GetEffectiveClipRect();
336 if (clipRect
&& clipRect
->IsEmpty())
338 if (child
->GetVisibleRegion().IsEmpty())
349 ContainerLayer::DefaultComputeEffectiveTransforms(const gfx3DMatrix
& aTransformToSurface
)
352 gfx3DMatrix idealTransform
= GetLocalTransform()*aTransformToSurface
;
353 mEffectiveTransform
= SnapTransform(idealTransform
, gfxRect(0, 0, 0, 0), &residual
);
355 PRBool useIntermediateSurface
;
356 float opacity
= GetEffectiveOpacity();
357 if (opacity
!= 1.0f
&& HasMultipleChildren()) {
358 useIntermediateSurface
= PR_TRUE
;
360 useIntermediateSurface
= PR_FALSE
;
361 gfxMatrix contTransform
;
362 if (!mEffectiveTransform
.Is2D(&contTransform
) ||
363 !contTransform
.PreservesAxisAlignedRectangles()) {
364 for (Layer
* child
= GetFirstChild(); child
; child
= child
->GetNextSibling()) {
365 const nsIntRect
*clipRect
= child
->GetEffectiveClipRect();
366 /* We can't (easily) forward our transform to children with a non-empty clip
367 * rect since it would need to be adjusted for the transform.
368 * TODO: This is easily solvable for translation/scaling transforms.
370 if (clipRect
&& !clipRect
->IsEmpty() && !child
->GetVisibleRegion().IsEmpty()) {
371 useIntermediateSurface
= PR_TRUE
;
378 mUseIntermediateSurface
= useIntermediateSurface
;
379 if (useIntermediateSurface
) {
380 ComputeEffectiveTransformsForChildren(gfx3DMatrix::From2D(residual
));
382 ComputeEffectiveTransformsForChildren(idealTransform
);
387 ContainerLayer::ComputeEffectiveTransformsForChildren(const gfx3DMatrix
& aTransformToSurface
)
389 for (Layer
* l
= mFirstChild
; l
; l
= l
->GetNextSibling()) {
390 l
->ComputeEffectiveTransforms(aTransformToSurface
);
394 #ifdef MOZ_LAYERS_HAVE_LOG
396 static nsACString
& PrintInfo(nsACString
& aTo
, ShadowLayer
* aShadowLayer
);
399 Layer::Dump(FILE* aFile
, const char* aPrefix
)
401 DumpSelf(aFile
, aPrefix
);
403 if (Layer
* kid
= GetFirstChild()) {
404 nsCAutoString
pfx(aPrefix
);
406 kid
->Dump(aFile
, pfx
.get());
409 if (Layer
* next
= GetNextSibling())
410 next
->Dump(aFile
, aPrefix
);
414 Layer::DumpSelf(FILE* aFile
, const char* aPrefix
)
417 PrintInfo(str
, aPrefix
);
418 fprintf(FILEOrDefault(aFile
), "%s\n", str
.get());
422 Layer::Log(const char* aPrefix
)
429 if (Layer
* kid
= GetFirstChild()) {
430 nsCAutoString
pfx(aPrefix
);
435 if (Layer
* next
= GetNextSibling())
440 Layer::LogSelf(const char* aPrefix
)
446 PrintInfo(str
, aPrefix
);
447 MOZ_LAYERS_LOG(("%s", str
.get()));
451 Layer::PrintInfo(nsACString
& aTo
, const char* aPrefix
)
454 aTo
+= nsPrintfCString(64, "%s%s (0x%p)", mManager
->Name(), Name(), this);
456 ::PrintInfo(aTo
, AsShadowLayer());
459 AppendToString(aTo
, mClipRect
, " [clip=", "]");
461 if (!mTransform
.IsIdentity()) {
462 AppendToString(aTo
, mTransform
, " [transform=", "]");
464 if (!mVisibleRegion
.IsEmpty()) {
465 AppendToString(aTo
, mVisibleRegion
, " [visible=", "]");
467 if (1.0 != mOpacity
) {
468 aTo
.AppendPrintf(" [opacity=%g]", mOpacity
);
470 if (const nsIntRect
* tileSourceRect
= GetTileSourceRect()) {
471 AppendToString(aTo
, *tileSourceRect
, " [tileSrc=", "]");
473 if (GetContentFlags() & CONTENT_OPAQUE
) {
474 aTo
+= " [opaqueContent]";
476 if (GetContentFlags() & CONTENT_COMPONENT_ALPHA
) {
477 aTo
+= " [componentAlpha]";
484 ThebesLayer::PrintInfo(nsACString
& aTo
, const char* aPrefix
)
486 Layer::PrintInfo(aTo
, aPrefix
);
487 if (!mValidRegion
.IsEmpty()) {
488 AppendToString(aTo
, mValidRegion
, " [valid=", "]");
490 if (mXResolution
!= 1.0 || mYResolution
!= 1.0) {
491 aTo
.AppendPrintf(" [xres=%g yres=%g]", mXResolution
, mYResolution
);
497 ContainerLayer::PrintInfo(nsACString
& aTo
, const char* aPrefix
)
499 Layer::PrintInfo(aTo
, aPrefix
);
500 if (!mFrameMetrics
.IsDefault()) {
501 AppendToString(aTo
, mFrameMetrics
, " [metrics=", "]");
503 if (UseIntermediateSurface()) {
504 aTo
+= " [usesTmpSurf]";
510 ColorLayer::PrintInfo(nsACString
& aTo
, const char* aPrefix
)
512 Layer::PrintInfo(aTo
, aPrefix
);
513 AppendToString(aTo
, mColor
, " [color=", "]");
518 CanvasLayer::PrintInfo(nsACString
& aTo
, const char* aPrefix
)
520 Layer::PrintInfo(aTo
, aPrefix
);
521 if (mFilter
!= gfxPattern::FILTER_GOOD
) {
522 AppendToString(aTo
, mFilter
, " [filter=", "]");
528 ImageLayer::PrintInfo(nsACString
& aTo
, const char* aPrefix
)
530 Layer::PrintInfo(aTo
, aPrefix
);
531 if (mFilter
!= gfxPattern::FILTER_GOOD
) {
532 AppendToString(aTo
, mFilter
, " [filter=", "]");
537 //--------------------------------------------------
541 LayerManager::Dump(FILE* aFile
, const char* aPrefix
)
543 FILE* file
= FILEOrDefault(aFile
);
545 DumpSelf(file
, aPrefix
);
547 nsCAutoString
pfx(aPrefix
);
550 fprintf(file
, "%s(null)", pfx
.get());
554 GetRoot()->Dump(file
, pfx
.get());
558 LayerManager::DumpSelf(FILE* aFile
, const char* aPrefix
)
561 PrintInfo(str
, aPrefix
);
562 fprintf(FILEOrDefault(aFile
), "%s\n", str
.get());
566 LayerManager::Log(const char* aPrefix
)
573 nsCAutoString
pfx(aPrefix
);
576 MOZ_LAYERS_LOG(("%s(null)", pfx
.get()));
580 GetRoot()->Log(pfx
.get());
584 LayerManager::LogSelf(const char* aPrefix
)
587 PrintInfo(str
, aPrefix
);
588 MOZ_LAYERS_LOG(("%s", str
.get()));
592 LayerManager::PrintInfo(nsACString
& aTo
, const char* aPrefix
)
595 return aTo
+= nsPrintfCString(64, "%sLayerManager (0x%p)", Name(), this);
599 LayerManager::InitLog()
602 sLog
= PR_NewLogModule("Layers");
606 LayerManager::IsLogEnabled()
608 NS_ABORT_IF_FALSE(!!sLog
,
609 "layer manager must be created before logging is allowed");
610 return PR_LOG_TEST(sLog
, PR_LOG_DEBUG
);
615 PrintInfo(nsACString
& aTo
, ShadowLayer
* aShadowLayer
)
620 if (const nsIntRect
* clipRect
= aShadowLayer
->GetShadowClipRect()) {
621 AppendToString(aTo
, *clipRect
, " [shadow-clip=", "]");
623 if (!aShadowLayer
->GetShadowTransform().IsIdentity()) {
624 AppendToString(aTo
, aShadowLayer
->GetShadowTransform(), " [shadow-transform=", "]");
626 if (!aShadowLayer
->GetShadowVisibleRegion().IsEmpty()) {
627 AppendToString(aTo
, aShadowLayer
->GetShadowVisibleRegion(), " [shadow-visible=", "]");
632 static nsACString
& PrintInfo(nsACString
& aTo
, ShadowLayer
* aShadowLayer
)
638 #else // !MOZ_LAYERS_HAVE_LOG
640 void Layer::Dump(FILE* aFile
, const char* aPrefix
) {}
641 void Layer::DumpSelf(FILE* aFile
, const char* aPrefix
) {}
642 void Layer::Log(const char* aPrefix
) {}
643 void Layer::LogSelf(const char* aPrefix
) {}
645 Layer::PrintInfo(nsACString
& aTo
, const char* aPrefix
)
649 ThebesLayer::PrintInfo(nsACString
& aTo
, const char* aPrefix
)
653 ContainerLayer::PrintInfo(nsACString
& aTo
, const char* aPrefix
)
657 ColorLayer::PrintInfo(nsACString
& aTo
, const char* aPrefix
)
661 CanvasLayer::PrintInfo(nsACString
& aTo
, const char* aPrefix
)
665 ImageLayer::PrintInfo(nsACString
& aTo
, const char* aPrefix
)
668 void LayerManager::Dump(FILE* aFile
, const char* aPrefix
) {}
669 void LayerManager::DumpSelf(FILE* aFile
, const char* aPrefix
) {}
670 void LayerManager::Log(const char* aPrefix
) {}
671 void LayerManager::LogSelf(const char* aPrefix
) {}
674 LayerManager::PrintInfo(nsACString
& aTo
, const char* aPrefix
)
677 /*static*/ void LayerManager::InitLog() {}
678 /*static*/ bool LayerManager::IsLogEnabled() { return false; }
680 #endif // MOZ_LAYERS_HAVE_LOG
682 PRLogModuleInfo
* LayerManager::sLog
;
684 } // namespace layers
685 } // namespace mozilla