1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 : * vim: sw=2 ts=8 et :
3 : */
4 : /* ***** BEGIN LICENSE BLOCK *****
5 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 : *
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/
11 : *
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
15 : * License.
16 : *
17 : * The Original Code is Mozilla Code.
18 : *
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.
23 : *
24 : * Contributor(s):
25 : * Chris Jones <jones.chris.g@gmail.com>
26 : *
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.
38 : *
39 : * ***** END LICENSE BLOCK ***** */
40 :
41 : #include "mozilla/layers/PLayers.h"
42 : #include "mozilla/layers/ShadowLayers.h"
43 :
44 : #include "ImageLayers.h"
45 : #include "Layers.h"
46 : #include "gfxPlatform.h"
47 : #include "ReadbackLayer.h"
48 : #include "gfxUtils.h"
49 : #include "nsPrintfCString.h"
50 : #include "mozilla/Util.h"
51 : #include "LayerSorter.h"
52 :
53 : using namespace mozilla::layers;
54 : using namespace mozilla::gfx;
55 :
56 : typedef FrameMetrics::ViewID ViewID;
57 : const ViewID FrameMetrics::NULL_SCROLL_ID = 0;
58 : const ViewID FrameMetrics::ROOT_SCROLL_ID = 1;
59 : const ViewID FrameMetrics::START_SCROLL_ID = 2;
60 :
61 : #ifdef MOZ_LAYERS_HAVE_LOG
62 : FILE*
63 0 : FILEOrDefault(FILE* aFile)
64 : {
65 0 : return aFile ? aFile : stderr;
66 : }
67 : #endif // MOZ_LAYERS_HAVE_LOG
68 :
69 : namespace {
70 :
71 : // XXX pretty general utilities, could centralize
72 :
73 : nsACString&
74 0 : AppendToString(nsACString& s, const void* p,
75 : const char* pfx="", const char* sfx="")
76 : {
77 0 : s += pfx;
78 0 : s += nsPrintfCString(64, "%p", p);
79 0 : return s += sfx;
80 : }
81 :
82 : nsACString&
83 0 : AppendToString(nsACString& s, const gfxPattern::GraphicsFilter& f,
84 : const char* pfx="", const char* sfx="")
85 : {
86 0 : s += pfx;
87 0 : switch (f) {
88 0 : case gfxPattern::FILTER_FAST: s += "fast"; break;
89 0 : case gfxPattern::FILTER_GOOD: s += "good"; break;
90 0 : case gfxPattern::FILTER_BEST: s += "best"; break;
91 0 : case gfxPattern::FILTER_NEAREST: s += "nearest"; break;
92 0 : case gfxPattern::FILTER_BILINEAR: s += "bilinear"; break;
93 0 : case gfxPattern::FILTER_GAUSSIAN: s += "gaussian"; break;
94 : default:
95 0 : NS_ERROR("unknown filter type");
96 0 : s += "???";
97 : }
98 0 : return s += sfx;
99 : }
100 :
101 : nsACString&
102 0 : AppendToString(nsACString& s, ViewID n,
103 : const char* pfx="", const char* sfx="")
104 : {
105 0 : s += pfx;
106 0 : s.AppendInt(n);
107 0 : return s += sfx;
108 : }
109 :
110 : nsACString&
111 0 : AppendToString(nsACString& s, const gfxRGBA& c,
112 : const char* pfx="", const char* sfx="")
113 : {
114 0 : s += pfx;
115 : s += nsPrintfCString(
116 : 128, "rgba(%d, %d, %d, %g)",
117 0 : PRUint8(c.r*255.0), PRUint8(c.g*255.0), PRUint8(c.b*255.0), c.a);
118 0 : return s += sfx;
119 : }
120 :
121 : nsACString&
122 0 : AppendToString(nsACString& s, const gfx3DMatrix& m,
123 : const char* pfx="", const char* sfx="")
124 : {
125 0 : s += pfx;
126 0 : if (m.IsIdentity())
127 0 : s += "[ I ]";
128 : else {
129 0 : gfxMatrix matrix;
130 0 : if (m.Is2D(&matrix)) {
131 : s += nsPrintfCString(
132 : 96, "[ %g %g; %g %g; %g %g; ]",
133 0 : matrix.xx, matrix.yx, matrix.xy, matrix.yy, matrix.x0, matrix.y0);
134 : } else {
135 : s += nsPrintfCString(
136 : 256, "[ %g %g %g %g; %g %g %g %g; %g %g %g %g; %g %g %g %g; ]",
137 : m._11, m._12, m._13, m._14,
138 : m._21, m._22, m._23, m._24,
139 : m._31, m._32, m._33, m._34,
140 0 : m._41, m._42, m._43, m._44);
141 : }
142 : }
143 0 : return s += sfx;
144 : }
145 :
146 : nsACString&
147 0 : AppendToString(nsACString& s, const nsIntPoint& p,
148 : const char* pfx="", const char* sfx="")
149 : {
150 0 : s += pfx;
151 0 : s += nsPrintfCString(128, "(x=%d, y=%d)", p.x, p.y);
152 0 : return s += sfx;
153 : }
154 :
155 : nsACString&
156 0 : AppendToString(nsACString& s, const nsIntRect& r,
157 : const char* pfx="", const char* sfx="")
158 : {
159 0 : s += pfx;
160 : s += nsPrintfCString(
161 : 256, "(x=%d, y=%d, w=%d, h=%d)",
162 0 : r.x, r.y, r.width, r.height);
163 0 : return s += sfx;
164 : }
165 :
166 : nsACString&
167 0 : AppendToString(nsACString& s, const nsIntRegion& r,
168 : const char* pfx="", const char* sfx="")
169 : {
170 0 : s += pfx;
171 :
172 0 : nsIntRegionRectIterator it(r);
173 0 : s += "< ";
174 0 : while (const nsIntRect* sr = it.Next())
175 0 : AppendToString(s, *sr) += "; ";
176 0 : s += ">";
177 :
178 0 : return s += sfx;
179 : }
180 :
181 : nsACString&
182 0 : AppendToString(nsACString& s, const nsIntSize& sz,
183 : const char* pfx="", const char* sfx="")
184 : {
185 0 : s += pfx;
186 0 : s += nsPrintfCString(128, "(w=%d, h=%d)", sz.width, sz.height);
187 0 : return s += sfx;
188 : }
189 :
190 : nsACString&
191 0 : AppendToString(nsACString& s, const FrameMetrics& m,
192 : const char* pfx="", const char* sfx="")
193 : {
194 0 : s += pfx;
195 0 : AppendToString(s, m.mViewport, "{ viewport=");
196 0 : AppendToString(s, m.mViewportScrollOffset, " viewportScroll=");
197 0 : AppendToString(s, m.mDisplayPort, " displayport=");
198 0 : AppendToString(s, m.mScrollId, " scrollId=", " }");
199 0 : return s += sfx;
200 : }
201 :
202 : } // namespace <anon>
203 :
204 : namespace mozilla {
205 : namespace layers {
206 :
207 : //--------------------------------------------------
208 : // LayerManager
209 : already_AddRefed<gfxASurface>
210 0 : LayerManager::CreateOptimalSurface(const gfxIntSize &aSize,
211 : gfxASurface::gfxImageFormat aFormat)
212 : {
213 0 : return gfxPlatform::GetPlatform()->
214 0 : CreateOffscreenSurface(aSize, gfxASurface::ContentFromFormat(aFormat));
215 : }
216 :
217 : TemporaryRef<DrawTarget>
218 0 : LayerManager::CreateDrawTarget(const IntSize &aSize,
219 : SurfaceFormat aFormat)
220 : {
221 0 : return gfxPlatform::GetPlatform()->
222 0 : CreateOffscreenDrawTarget(aSize, aFormat);
223 : }
224 :
225 : #ifdef DEBUG
226 : void
227 0 : LayerManager::Mutated(Layer* aLayer)
228 : {
229 0 : }
230 : #endif // DEBUG
231 :
232 : already_AddRefed<ImageContainer>
233 0 : LayerManager::CreateImageContainer()
234 : {
235 0 : nsRefPtr<ImageContainer> container = new ImageContainer();
236 0 : return container.forget();
237 : }
238 :
239 : //--------------------------------------------------
240 : // Layer
241 :
242 : bool
243 0 : Layer::CanUseOpaqueSurface()
244 : {
245 : // If the visible content in the layer is opaque, there is no need
246 : // for an alpha channel.
247 0 : if (GetContentFlags() & CONTENT_OPAQUE)
248 0 : return true;
249 : // Also, if this layer is the bottommost layer in a container which
250 : // doesn't need an alpha channel, we can use an opaque surface for this
251 : // layer too. Any transparent areas must be covered by something else
252 : // in the container.
253 0 : ContainerLayer* parent = GetParent();
254 0 : return parent && parent->GetFirstChild() == this &&
255 0 : parent->CanUseOpaqueSurface();
256 : }
257 :
258 : // NB: eventually these methods will be defined unconditionally, and
259 : // can be moved into Layers.h
260 : const nsIntRect*
261 0 : Layer::GetEffectiveClipRect()
262 : {
263 0 : if (ShadowLayer* shadow = AsShadowLayer()) {
264 0 : return shadow->GetShadowClipRect();
265 : }
266 0 : return GetClipRect();
267 : }
268 :
269 : const nsIntRegion&
270 0 : Layer::GetEffectiveVisibleRegion()
271 : {
272 0 : if (ShadowLayer* shadow = AsShadowLayer()) {
273 0 : return shadow->GetShadowVisibleRegion();
274 : }
275 0 : return GetVisibleRegion();
276 : }
277 :
278 : gfx3DMatrix
279 0 : Layer::SnapTransform(const gfx3DMatrix& aTransform,
280 : const gfxRect& aSnapRect,
281 : gfxMatrix* aResidualTransform)
282 : {
283 0 : if (aResidualTransform) {
284 0 : *aResidualTransform = gfxMatrix();
285 : }
286 :
287 0 : gfxMatrix matrix2D;
288 0 : gfx3DMatrix result;
289 0 : if (mManager->IsSnappingEffectiveTransforms() &&
290 0 : aTransform.Is2D(&matrix2D) &&
291 0 : matrix2D.HasNonIntegerTranslation() &&
292 0 : !matrix2D.IsSingular() &&
293 0 : !matrix2D.HasNonAxisAlignedTransform()) {
294 0 : gfxMatrix snappedMatrix;
295 0 : gfxPoint topLeft = matrix2D.Transform(aSnapRect.TopLeft());
296 0 : topLeft.Round();
297 : // first compute scale factors that scale aSnapRect to the snapped rect
298 0 : if (aSnapRect.IsEmpty()) {
299 0 : snappedMatrix.xx = matrix2D.xx;
300 0 : snappedMatrix.yy = matrix2D.yy;
301 : } else {
302 0 : gfxPoint bottomRight = matrix2D.Transform(aSnapRect.BottomRight());
303 0 : bottomRight.Round();
304 0 : snappedMatrix.xx = (bottomRight.x - topLeft.x)/aSnapRect.Width();
305 0 : snappedMatrix.yy = (bottomRight.y - topLeft.y)/aSnapRect.Height();
306 : }
307 : // compute translation factors that will move aSnapRect to the snapped rect
308 : // given those scale factors
309 0 : snappedMatrix.x0 = topLeft.x - aSnapRect.X()*snappedMatrix.xx;
310 0 : snappedMatrix.y0 = topLeft.y - aSnapRect.Y()*snappedMatrix.yy;
311 0 : result = gfx3DMatrix::From2D(snappedMatrix);
312 0 : if (aResidualTransform && !snappedMatrix.IsSingular()) {
313 : // set aResidualTransform so that aResidual * snappedMatrix == matrix2D.
314 : // (i.e., appying snappedMatrix after aResidualTransform gives the
315 : // ideal transform.
316 0 : gfxMatrix snappedMatrixInverse = snappedMatrix;
317 0 : snappedMatrixInverse.Invert();
318 0 : *aResidualTransform = matrix2D * snappedMatrixInverse;
319 : }
320 : } else {
321 0 : result = aTransform;
322 : }
323 : return result;
324 : }
325 :
326 : nsIntRect
327 0 : Layer::CalculateScissorRect(const nsIntRect& aCurrentScissorRect,
328 : const gfxMatrix* aWorldTransform)
329 : {
330 0 : ContainerLayer* container = GetParent();
331 0 : NS_ASSERTION(container, "This can't be called on the root!");
332 :
333 : // Establish initial clip rect: it's either the one passed in, or
334 : // if the parent has an intermediate surface, it's the extents of that surface.
335 0 : nsIntRect currentClip;
336 0 : if (container->UseIntermediateSurface()) {
337 0 : currentClip.SizeTo(container->GetIntermediateSurfaceRect().Size());
338 : } else {
339 0 : currentClip = aCurrentScissorRect;
340 : }
341 :
342 0 : const nsIntRect *clipRect = GetEffectiveClipRect();
343 0 : if (!clipRect)
344 0 : return currentClip;
345 :
346 0 : if (clipRect->IsEmpty()) {
347 : // We might have a non-translation transform in the container so we can't
348 : // use the code path below.
349 0 : return nsIntRect(currentClip.TopLeft(), nsIntSize(0, 0));
350 : }
351 :
352 0 : nsIntRect scissor = *clipRect;
353 0 : if (!container->UseIntermediateSurface()) {
354 0 : gfxMatrix matrix;
355 0 : DebugOnly<bool> is2D = container->GetEffectiveTransform().Is2D(&matrix);
356 : // See DefaultComputeEffectiveTransforms below
357 0 : NS_ASSERTION(is2D && matrix.PreservesAxisAlignedRectangles(),
358 : "Non preserves axis aligned transform with clipped child should have forced intermediate surface");
359 0 : gfxRect r(scissor.x, scissor.y, scissor.width, scissor.height);
360 0 : gfxRect trScissor = matrix.TransformBounds(r);
361 0 : trScissor.Round();
362 0 : if (!gfxUtils::GfxRectToIntRect(trScissor, &scissor)) {
363 0 : return nsIntRect(currentClip.TopLeft(), nsIntSize(0, 0));
364 : }
365 :
366 : // Find the nearest ancestor with an intermediate surface
367 0 : do {
368 0 : container = container->GetParent();
369 0 : } while (container && !container->UseIntermediateSurface());
370 : }
371 0 : if (container) {
372 0 : scissor.MoveBy(-container->GetIntermediateSurfaceRect().TopLeft());
373 0 : } else if (aWorldTransform) {
374 0 : gfxRect r(scissor.x, scissor.y, scissor.width, scissor.height);
375 0 : gfxRect trScissor = aWorldTransform->TransformBounds(r);
376 0 : trScissor.Round();
377 0 : if (!gfxUtils::GfxRectToIntRect(trScissor, &scissor))
378 0 : return nsIntRect(currentClip.TopLeft(), nsIntSize(0, 0));
379 : }
380 0 : return currentClip.Intersect(scissor);
381 : }
382 :
383 : const gfx3DMatrix&
384 0 : Layer::GetLocalTransform()
385 : {
386 0 : if (ShadowLayer* shadow = AsShadowLayer())
387 0 : return shadow->GetShadowTransform();
388 0 : return mTransform;
389 : }
390 :
391 : float
392 0 : Layer::GetEffectiveOpacity()
393 : {
394 0 : float opacity = GetOpacity();
395 0 : for (ContainerLayer* c = GetParent(); c && !c->UseIntermediateSurface();
396 0 : c = c->GetParent()) {
397 0 : opacity *= c->GetOpacity();
398 : }
399 0 : return opacity;
400 : }
401 :
402 : void
403 0 : ContainerLayer::FillSpecificAttributes(SpecificLayerAttributes& aAttrs)
404 : {
405 0 : aAttrs = ContainerLayerAttributes(GetFrameMetrics());
406 0 : }
407 :
408 : bool
409 0 : ContainerLayer::HasMultipleChildren()
410 : {
411 0 : PRUint32 count = 0;
412 0 : for (Layer* child = GetFirstChild(); child; child = child->GetNextSibling()) {
413 0 : const nsIntRect *clipRect = child->GetEffectiveClipRect();
414 0 : if (clipRect && clipRect->IsEmpty())
415 0 : continue;
416 0 : if (child->GetVisibleRegion().IsEmpty())
417 0 : continue;
418 0 : ++count;
419 0 : if (count > 1)
420 0 : return true;
421 : }
422 :
423 0 : return false;
424 : }
425 :
426 : void
427 0 : ContainerLayer::SortChildrenBy3DZOrder(nsTArray<Layer*>& aArray)
428 : {
429 0 : nsAutoTArray<Layer*, 10> toSort;
430 :
431 0 : for (Layer* l = GetFirstChild(); l; l = l->GetNextSibling()) {
432 0 : ContainerLayer* container = l->AsContainerLayer();
433 0 : if (container && container->GetContentFlags() & CONTENT_PRESERVE_3D) {
434 0 : toSort.AppendElement(l);
435 : } else {
436 0 : if (toSort.Length() > 0) {
437 0 : SortLayersBy3DZOrder(toSort);
438 0 : aArray.MoveElementsFrom(toSort);
439 : }
440 0 : aArray.AppendElement(l);
441 : }
442 : }
443 0 : if (toSort.Length() > 0) {
444 0 : SortLayersBy3DZOrder(toSort);
445 0 : aArray.MoveElementsFrom(toSort);
446 : }
447 0 : }
448 :
449 : void
450 0 : ContainerLayer::DefaultComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface)
451 : {
452 0 : gfxMatrix residual;
453 0 : gfx3DMatrix idealTransform = GetLocalTransform()*aTransformToSurface;
454 0 : idealTransform.ProjectTo2D();
455 0 : mEffectiveTransform = SnapTransform(idealTransform, gfxRect(0, 0, 0, 0), &residual);
456 :
457 : bool useIntermediateSurface;
458 0 : float opacity = GetEffectiveOpacity();
459 0 : if (opacity != 1.0f && HasMultipleChildren()) {
460 0 : useIntermediateSurface = true;
461 : #ifdef MOZ_DUMP_PAINTING
462 0 : } else if (gfxUtils::sDumpPainting) {
463 0 : useIntermediateSurface = true;
464 : #endif
465 : } else {
466 0 : useIntermediateSurface = false;
467 0 : gfxMatrix contTransform;
468 0 : if (!mEffectiveTransform.Is2D(&contTransform) ||
469 : #ifdef MOZ_GFX_OPTIMIZE_MOBILE
470 : !contTransform.PreservesAxisAlignedRectangles()) {
471 : #else
472 0 : contTransform.HasNonIntegerTranslation()) {
473 : #endif
474 0 : for (Layer* child = GetFirstChild(); child; child = child->GetNextSibling()) {
475 0 : const nsIntRect *clipRect = child->GetEffectiveClipRect();
476 : /* We can't (easily) forward our transform to children with a non-empty clip
477 : * rect since it would need to be adjusted for the transform. See
478 : * the calculations performed by CalculateScissorRect above.
479 : */
480 0 : if (clipRect && !clipRect->IsEmpty() && !child->GetVisibleRegion().IsEmpty()) {
481 0 : useIntermediateSurface = true;
482 0 : break;
483 : }
484 : }
485 : }
486 : }
487 :
488 0 : mUseIntermediateSurface = useIntermediateSurface;
489 0 : if (useIntermediateSurface) {
490 0 : ComputeEffectiveTransformsForChildren(gfx3DMatrix::From2D(residual));
491 : } else {
492 0 : ComputeEffectiveTransformsForChildren(idealTransform);
493 : }
494 0 : }
495 :
496 : void
497 0 : ContainerLayer::ComputeEffectiveTransformsForChildren(const gfx3DMatrix& aTransformToSurface)
498 : {
499 0 : for (Layer* l = mFirstChild; l; l = l->GetNextSibling()) {
500 0 : l->ComputeEffectiveTransforms(aTransformToSurface);
501 : }
502 0 : }
503 :
504 : void
505 0 : ContainerLayer::DidRemoveChild(Layer* aLayer)
506 : {
507 0 : ThebesLayer* tl = aLayer->AsThebesLayer();
508 0 : if (tl && tl->UsedForReadback()) {
509 0 : for (Layer* l = mFirstChild; l; l = l->GetNextSibling()) {
510 0 : if (l->GetType() == TYPE_READBACK) {
511 0 : static_cast<ReadbackLayer*>(l)->NotifyThebesLayerRemoved(tl);
512 : }
513 : }
514 : }
515 0 : if (aLayer->GetType() == TYPE_READBACK) {
516 0 : static_cast<ReadbackLayer*>(aLayer)->NotifyRemoved();
517 : }
518 0 : }
519 :
520 : void
521 0 : ContainerLayer::DidInsertChild(Layer* aLayer)
522 : {
523 0 : if (aLayer->GetType() == TYPE_READBACK) {
524 0 : mMayHaveReadbackChild = true;
525 : }
526 0 : }
527 :
528 : void
529 0 : LayerManager::StartFrameTimeRecording()
530 : {
531 0 : mLastFrameTime = TimeStamp::Now();
532 0 : }
533 :
534 : void
535 0 : LayerManager::PostPresent()
536 : {
537 0 : if (!mLastFrameTime.IsNull()) {
538 0 : TimeStamp now = TimeStamp::Now();
539 0 : mFrameTimes.AppendElement((now - mLastFrameTime).ToMilliseconds());
540 0 : mLastFrameTime = now;
541 : }
542 0 : }
543 :
544 : nsTArray<float>
545 0 : LayerManager::StopFrameTimeRecording()
546 : {
547 0 : mLastFrameTime = TimeStamp();
548 0 : nsTArray<float> result = mFrameTimes;
549 0 : mFrameTimes.Clear();
550 : return result;
551 : }
552 :
553 :
554 :
555 : #ifdef MOZ_LAYERS_HAVE_LOG
556 :
557 : static nsACString& PrintInfo(nsACString& aTo, ShadowLayer* aShadowLayer);
558 :
559 : #ifdef MOZ_DUMP_PAINTING
560 : template <typename T>
561 0 : void WriteSnapshotLinkToDumpFile(T* aObj, FILE* aFile)
562 : {
563 0 : nsCString string(aObj->Name());
564 0 : string.Append("-");
565 0 : string.AppendInt((PRUint64)aObj);
566 0 : fprintf(aFile, "href=\"javascript:ViewImage('%s')\"", string.BeginReading());
567 0 : }
568 :
569 : template <typename T>
570 0 : void WriteSnapshotToDumpFile_internal(T* aObj, gfxASurface* aSurf)
571 : {
572 0 : nsCString string(aObj->Name());
573 0 : string.Append("-");
574 0 : string.AppendInt((PRUint64)aObj);
575 0 : fprintf(gfxUtils::sDumpPaintFile, "array[\"%s\"]=\"", string.BeginReading());
576 0 : aSurf->DumpAsDataURL(gfxUtils::sDumpPaintFile);
577 0 : fprintf(gfxUtils::sDumpPaintFile, "\";");
578 0 : }
579 :
580 0 : void WriteSnapshotToDumpFile(Layer* aLayer, gfxASurface* aSurf)
581 : {
582 0 : WriteSnapshotToDumpFile_internal(aLayer, aSurf);
583 0 : }
584 :
585 0 : void WriteSnapshotToDumpFile(LayerManager* aManager, gfxASurface* aSurf)
586 : {
587 0 : WriteSnapshotToDumpFile_internal(aManager, aSurf);
588 0 : }
589 : #endif
590 :
591 : void
592 0 : Layer::Dump(FILE* aFile, const char* aPrefix)
593 : {
594 0 : fprintf(aFile, "<li><a id=\"%p\" ", this);
595 : #ifdef MOZ_DUMP_PAINTING
596 0 : if (GetType() == TYPE_CONTAINER || GetType() == TYPE_THEBES) {
597 0 : WriteSnapshotLinkToDumpFile(this, aFile);
598 : }
599 : #endif
600 0 : fprintf(aFile, ">");
601 0 : DumpSelf(aFile, aPrefix);
602 0 : fprintf(aFile, "</a>");
603 :
604 0 : if (Layer* kid = GetFirstChild()) {
605 0 : nsCAutoString pfx(aPrefix);
606 0 : pfx += " ";
607 0 : fprintf(aFile, "<ul>");
608 0 : kid->Dump(aFile, pfx.get());
609 0 : fprintf(aFile, "</ul>");
610 : }
611 :
612 0 : fprintf(aFile, "</li>");
613 0 : if (Layer* next = GetNextSibling())
614 0 : next->Dump(aFile, aPrefix);
615 0 : }
616 :
617 : void
618 0 : Layer::DumpSelf(FILE* aFile, const char* aPrefix)
619 : {
620 0 : nsCAutoString str;
621 0 : PrintInfo(str, aPrefix);
622 0 : fprintf(FILEOrDefault(aFile), "%s\n", str.get());
623 0 : }
624 :
625 : void
626 0 : Layer::Log(const char* aPrefix)
627 : {
628 0 : if (!IsLogEnabled())
629 0 : return;
630 :
631 0 : LogSelf(aPrefix);
632 :
633 0 : if (Layer* kid = GetFirstChild()) {
634 0 : nsCAutoString pfx(aPrefix);
635 0 : pfx += " ";
636 0 : kid->Log(pfx.get());
637 : }
638 :
639 0 : if (Layer* next = GetNextSibling())
640 0 : next->Log(aPrefix);
641 : }
642 :
643 : void
644 0 : Layer::LogSelf(const char* aPrefix)
645 : {
646 0 : if (!IsLogEnabled())
647 0 : return;
648 :
649 0 : nsCAutoString str;
650 0 : PrintInfo(str, aPrefix);
651 0 : MOZ_LAYERS_LOG(("%s", str.get()));
652 : }
653 :
654 : nsACString&
655 0 : Layer::PrintInfo(nsACString& aTo, const char* aPrefix)
656 : {
657 0 : aTo += aPrefix;
658 0 : aTo += nsPrintfCString(64, "%s%s (0x%p)", mManager->Name(), Name(), this);
659 :
660 0 : ::PrintInfo(aTo, AsShadowLayer());
661 :
662 0 : if (mUseClipRect) {
663 0 : AppendToString(aTo, mClipRect, " [clip=", "]");
664 : }
665 0 : if (!mTransform.IsIdentity()) {
666 0 : AppendToString(aTo, mTransform, " [transform=", "]");
667 : }
668 0 : if (!mVisibleRegion.IsEmpty()) {
669 0 : AppendToString(aTo, mVisibleRegion, " [visible=", "]");
670 : }
671 0 : if (1.0 != mOpacity) {
672 0 : aTo.AppendPrintf(" [opacity=%g]", mOpacity);
673 : }
674 0 : if (const nsIntRect* tileSourceRect = GetTileSourceRect()) {
675 0 : AppendToString(aTo, *tileSourceRect, " [tileSrc=", "]");
676 : }
677 0 : if (GetContentFlags() & CONTENT_OPAQUE) {
678 0 : aTo += " [opaqueContent]";
679 : }
680 0 : if (GetContentFlags() & CONTENT_COMPONENT_ALPHA) {
681 0 : aTo += " [componentAlpha]";
682 : }
683 0 : if (GetIsFixedPosition()) {
684 0 : aTo += " [isFixedPosition]";
685 : }
686 :
687 0 : return aTo;
688 : }
689 :
690 : nsACString&
691 0 : ThebesLayer::PrintInfo(nsACString& aTo, const char* aPrefix)
692 : {
693 0 : Layer::PrintInfo(aTo, aPrefix);
694 0 : if (!mValidRegion.IsEmpty()) {
695 0 : AppendToString(aTo, mValidRegion, " [valid=", "]");
696 : }
697 0 : return aTo;
698 : }
699 :
700 : nsACString&
701 0 : ContainerLayer::PrintInfo(nsACString& aTo, const char* aPrefix)
702 : {
703 0 : Layer::PrintInfo(aTo, aPrefix);
704 0 : if (!mFrameMetrics.IsDefault()) {
705 0 : AppendToString(aTo, mFrameMetrics, " [metrics=", "]");
706 : }
707 0 : if (UseIntermediateSurface()) {
708 0 : aTo += " [usesTmpSurf]";
709 : }
710 0 : return aTo;
711 : }
712 :
713 : nsACString&
714 0 : ColorLayer::PrintInfo(nsACString& aTo, const char* aPrefix)
715 : {
716 0 : Layer::PrintInfo(aTo, aPrefix);
717 0 : AppendToString(aTo, mColor, " [color=", "]");
718 0 : return aTo;
719 : }
720 :
721 : nsACString&
722 0 : CanvasLayer::PrintInfo(nsACString& aTo, const char* aPrefix)
723 : {
724 0 : Layer::PrintInfo(aTo, aPrefix);
725 0 : if (mFilter != gfxPattern::FILTER_GOOD) {
726 0 : AppendToString(aTo, mFilter, " [filter=", "]");
727 : }
728 0 : return aTo;
729 : }
730 :
731 : nsACString&
732 0 : ImageLayer::PrintInfo(nsACString& aTo, const char* aPrefix)
733 : {
734 0 : Layer::PrintInfo(aTo, aPrefix);
735 0 : if (mFilter != gfxPattern::FILTER_GOOD) {
736 0 : AppendToString(aTo, mFilter, " [filter=", "]");
737 : }
738 0 : return aTo;
739 : }
740 :
741 : nsACString&
742 0 : ReadbackLayer::PrintInfo(nsACString& aTo, const char* aPrefix)
743 : {
744 0 : Layer::PrintInfo(aTo, aPrefix);
745 0 : AppendToString(aTo, mSize, " [size=", "]");
746 0 : if (mBackgroundLayer) {
747 0 : AppendToString(aTo, mBackgroundLayer, " [backgroundLayer=", "]");
748 0 : AppendToString(aTo, mBackgroundLayerOffset, " [backgroundOffset=", "]");
749 0 : } else if (mBackgroundColor.a == 1.0) {
750 0 : AppendToString(aTo, mBackgroundColor, " [backgroundColor=", "]");
751 : } else {
752 0 : aTo += " [nobackground]";
753 : }
754 0 : return aTo;
755 : }
756 :
757 : //--------------------------------------------------
758 : // LayerManager
759 :
760 : void
761 0 : LayerManager::Dump(FILE* aFile, const char* aPrefix)
762 : {
763 0 : FILE* file = FILEOrDefault(aFile);
764 :
765 0 : fprintf(file, "<ul><li><a ");
766 : #ifdef MOZ_DUMP_PAINTING
767 0 : WriteSnapshotLinkToDumpFile(this, aFile);
768 : #endif
769 0 : fprintf(file, ">");
770 0 : DumpSelf(file, aPrefix);
771 : #ifdef MOZ_DUMP_PAINTING
772 0 : fprintf(aFile, "</a>");
773 : #endif
774 :
775 0 : nsCAutoString pfx(aPrefix);
776 0 : pfx += " ";
777 0 : if (!GetRoot()) {
778 0 : fprintf(file, "%s(null)</li></ul>", pfx.get());
779 : return;
780 : }
781 :
782 0 : fprintf(file, "<ul>");
783 0 : GetRoot()->Dump(file, pfx.get());
784 0 : fprintf(file, "</ul></li></ul>");
785 : }
786 :
787 : void
788 0 : LayerManager::DumpSelf(FILE* aFile, const char* aPrefix)
789 : {
790 0 : nsCAutoString str;
791 0 : PrintInfo(str, aPrefix);
792 0 : fprintf(FILEOrDefault(aFile), "%s\n", str.get());
793 0 : }
794 :
795 : void
796 0 : LayerManager::Log(const char* aPrefix)
797 : {
798 0 : if (!IsLogEnabled())
799 0 : return;
800 :
801 0 : LogSelf(aPrefix);
802 :
803 0 : nsCAutoString pfx(aPrefix);
804 0 : pfx += " ";
805 0 : if (!GetRoot()) {
806 0 : MOZ_LAYERS_LOG(("%s(null)", pfx.get()));
807 : return;
808 : }
809 :
810 0 : GetRoot()->Log(pfx.get());
811 : }
812 :
813 : void
814 0 : LayerManager::LogSelf(const char* aPrefix)
815 : {
816 0 : nsCAutoString str;
817 0 : PrintInfo(str, aPrefix);
818 0 : MOZ_LAYERS_LOG(("%s", str.get()));
819 0 : }
820 :
821 : nsACString&
822 0 : LayerManager::PrintInfo(nsACString& aTo, const char* aPrefix)
823 : {
824 0 : aTo += aPrefix;
825 0 : return aTo += nsPrintfCString(64, "%sLayerManager (0x%p)", Name(), this);
826 : }
827 :
828 : /*static*/ void
829 0 : LayerManager::InitLog()
830 : {
831 0 : if (!sLog)
832 0 : sLog = PR_NewLogModule("Layers");
833 0 : }
834 :
835 : /*static*/ bool
836 0 : LayerManager::IsLogEnabled()
837 : {
838 0 : NS_ABORT_IF_FALSE(!!sLog,
839 : "layer manager must be created before logging is allowed");
840 0 : return PR_LOG_TEST(sLog, PR_LOG_DEBUG);
841 : }
842 :
843 : static nsACString&
844 0 : PrintInfo(nsACString& aTo, ShadowLayer* aShadowLayer)
845 : {
846 0 : if (!aShadowLayer) {
847 0 : return aTo;
848 : }
849 0 : if (const nsIntRect* clipRect = aShadowLayer->GetShadowClipRect()) {
850 0 : AppendToString(aTo, *clipRect, " [shadow-clip=", "]");
851 : }
852 0 : if (!aShadowLayer->GetShadowTransform().IsIdentity()) {
853 0 : AppendToString(aTo, aShadowLayer->GetShadowTransform(), " [shadow-transform=", "]");
854 : }
855 0 : if (!aShadowLayer->GetShadowVisibleRegion().IsEmpty()) {
856 0 : AppendToString(aTo, aShadowLayer->GetShadowVisibleRegion(), " [shadow-visible=", "]");
857 : }
858 0 : return aTo;
859 : }
860 :
861 : #else // !MOZ_LAYERS_HAVE_LOG
862 :
863 : void Layer::Dump(FILE* aFile, const char* aPrefix) {}
864 : void Layer::DumpSelf(FILE* aFile, const char* aPrefix) {}
865 : void Layer::Log(const char* aPrefix) {}
866 : void Layer::LogSelf(const char* aPrefix) {}
867 : nsACString&
868 : Layer::PrintInfo(nsACString& aTo, const char* aPrefix)
869 : { return aTo; }
870 :
871 : nsACString&
872 : ThebesLayer::PrintInfo(nsACString& aTo, const char* aPrefix)
873 : { return aTo; }
874 :
875 : nsACString&
876 : ContainerLayer::PrintInfo(nsACString& aTo, const char* aPrefix)
877 : { return aTo; }
878 :
879 : nsACString&
880 : ColorLayer::PrintInfo(nsACString& aTo, const char* aPrefix)
881 : { return aTo; }
882 :
883 : nsACString&
884 : CanvasLayer::PrintInfo(nsACString& aTo, const char* aPrefix)
885 : { return aTo; }
886 :
887 : nsACString&
888 : ImageLayer::PrintInfo(nsACString& aTo, const char* aPrefix)
889 : { return aTo; }
890 :
891 : nsACString&
892 : ReadbackLayer::PrintInfo(nsACString& aTo, const char* aPrefix)
893 : { return aTo; }
894 :
895 : void LayerManager::Dump(FILE* aFile, const char* aPrefix) {}
896 : void LayerManager::DumpSelf(FILE* aFile, const char* aPrefix) {}
897 : void LayerManager::Log(const char* aPrefix) {}
898 : void LayerManager::LogSelf(const char* aPrefix) {}
899 :
900 : nsACString&
901 : LayerManager::PrintInfo(nsACString& aTo, const char* aPrefix)
902 : { return aTo; }
903 :
904 : /*static*/ void LayerManager::InitLog() {}
905 : /*static*/ bool LayerManager::IsLogEnabled() { return false; }
906 :
907 : #endif // MOZ_LAYERS_HAVE_LOG
908 :
909 : PRLogModuleInfo* LayerManager::sLog;
910 :
911 : } // namespace layers
912 : } // namespace mozilla
|