From ad15c41672a28355dd2e2f1ed3aa594a0fcc285d Mon Sep 17 00:00:00 2001 From: Chris Jones Date: Wed, 21 Jul 2010 13:06:33 -0500 Subject: [PATCH] Bug 567421, part 2: Implement Dump[Self](FILE*) and Log[Self]() methods for layers. r=roc --- gfx/layers/ImageLayers.h | 2 + gfx/layers/Layers.cpp | 368 ++++++++++++++++++++++++++++++ gfx/layers/Layers.h | 91 +++++++- gfx/layers/Makefile.in | 1 + gfx/layers/basic/BasicLayers.cpp | 10 + layout/base/FrameLayerBuilder.cpp | 86 +------ layout/base/FrameLayerBuilder.h | 5 - 7 files changed, 467 insertions(+), 96 deletions(-) create mode 100644 gfx/layers/Layers.cpp diff --git a/gfx/layers/ImageLayers.h b/gfx/layers/ImageLayers.h index 50a6df2c8392..cc14cdc52412 100644 --- a/gfx/layers/ImageLayers.h +++ b/gfx/layers/ImageLayers.h @@ -204,6 +204,8 @@ protected: ImageLayer(LayerManager* aManager, void* aImplData) : Layer(aManager, aImplData), mFilter(gfxPattern::FILTER_GOOD) {} + virtual nsACString& PrintInfo(nsACString& aTo, const char* aPrefix); + nsRefPtr mContainer; gfxPattern::GraphicsFilter mFilter; }; diff --git a/gfx/layers/Layers.cpp b/gfx/layers/Layers.cpp new file mode 100644 index 000000000000..c9df3216a3d4 --- /dev/null +++ b/gfx/layers/Layers.cpp @@ -0,0 +1,368 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim: sw=2 ts=8 et : + */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at: + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Code. + * + * The Initial Developer of the Original Code is + * The Mozilla Foundation + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Chris Jones + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "ImageLayers.h" + #include "Layers.h" + +#ifdef MOZ_LAYERS_HAVE_LOG +FILE* +FILEOrDefault(FILE* aFile) +{ + return aFile ? aFile : stderr; +} +#endif // MOZ_LAYERS_HAVE_LOG + +namespace { + +// XXX pretty general utilities, could centralize + +nsACString& +AppendToString(nsACString& s, const gfxPattern::GraphicsFilter& f, + const char* pfx="", const char* sfx="") +{ + s += pfx; + switch (f) { + case gfxPattern::FILTER_FAST: s += "fast"; break; + case gfxPattern::FILTER_GOOD: s += "good"; break; + case gfxPattern::FILTER_BEST: s += "best"; break; + case gfxPattern::FILTER_NEAREST: s += "nearest"; break; + case gfxPattern::FILTER_BILINEAR: s += "bilinear"; break; + case gfxPattern::FILTER_GAUSSIAN: s += "gaussian"; break; + default: + NS_ERROR("unknown filter type"); + s += "???"; + } + return s += sfx; +} + +nsACString& +AppendToString(nsACString& s, const gfxRGBA& c, + const char* pfx="", const char* sfx="") +{ + s += pfx; + s += nsPrintfCString( + 128, "rgba(%d, %d, %d, %g)", + PRUint8(c.r*255.0), PRUint8(c.g*255.0), PRUint8(c.b*255.0), c.a); + return s += sfx; +} + +nsACString& +AppendToString(nsACString& s, const gfx3DMatrix& m, + const char* pfx="", const char* sfx="") +{ + s += pfx; + if (m.IsIdentity()) + s += "[ I ]"; + else { + gfxMatrix matrix; + if (m.Is2D(&matrix)) { + s += nsPrintfCString( + "[ %g %g; %g %g; %g %g; ]", + 96, matrix.xx, matrix.yx, matrix.xy, matrix.yy, matrix.x0, matrix.y0); + } else { + s += nsPrintfCString( + 256, "[ %g %g %g %g; %g %g %g %g; %g %g %g %g; %g %g %g %g; ]", + m._11, m._12, m._13, m._14, + m._21, m._22, m._23, m._24, + m._31, m._32, m._33, m._34, + m._41, m._42, m._43, m._44); + } + } + return s += sfx; +} + +nsACString& +AppendToString(nsACString& s, const nsIntRect& r, + const char* pfx="", const char* sfx="") +{ + s += pfx; + s += nsPrintfCString( + 256, "(x=%d, y=%d, w=%d, h=%d)", + r.x, r.y, r.width, r.height); + return s += sfx; +} + +nsACString& +AppendToString(nsACString& s, const nsIntRegion& r, + const char* pfx="", const char* sfx="") +{ + s += pfx; + + nsIntRegionRectIterator it(r); + s += "< "; + while (const nsIntRect* sr = it.Next()) + AppendToString(s, *sr) += "; "; + s += ">"; + + return s += sfx; +} + +} // namespace + +namespace mozilla { +namespace layers { + +//-------------------------------------------------- +// Layer + +#ifdef MOZ_LAYERS_HAVE_LOG + +void +Layer::Dump(FILE* aFile, const char* aPrefix) +{ + DumpSelf(aFile, aPrefix); + + if (Layer* kid = GetFirstChild()) { + nsCAutoString pfx(aPrefix); + pfx += " "; + kid->Dump(aFile, pfx.get()); + } + + if (Layer* next = GetNextSibling()) + next->Dump(aFile, aPrefix); +} + +void +Layer::DumpSelf(FILE* aFile, const char* aPrefix) +{ + nsCAutoString str; + PrintInfo(str, aPrefix); + fprintf(FILEOrDefault(aFile), "%s\n", str.get()); +} + +void +Layer::Log(const char* aPrefix) +{ + if (!IsLogEnabled()) + return; + + LogSelf(aPrefix); + + if (Layer* kid = GetFirstChild()) { + nsCAutoString pfx(aPrefix); + pfx += " "; + kid->Log(pfx.get()); + } + + if (Layer* next = GetNextSibling()) + next->Log(aPrefix); +} + +void +Layer::LogSelf(const char* aPrefix) +{ + if (!IsLogEnabled()) + return; + + nsCAutoString str; + PrintInfo(str, aPrefix); + MOZ_LAYERS_LOG(("%s", str.get())); +} + +nsACString& +Layer::PrintInfo(nsACString& aTo, const char* aPrefix) +{ + aTo += aPrefix; + aTo += nsPrintfCString(64, "%s%s (0x%p)", mManager->Name(), Name(), this); + + if (!mVisibleRegion.IsEmpty()) + AppendToString(aTo, mVisibleRegion, " [visible=", "]"); + if (!mTransform.IsIdentity()) + AppendToString(aTo, mTransform, " [transform=", "]"); + if (1.0 != mOpacity) + aTo.AppendPrintf(" [opacity=%g]", mOpacity); + if (IsOpaqueContent()) + aTo += " [opaqueContent]"; + + return aTo; +} + +nsACString& +ThebesLayer::PrintInfo(nsACString& aTo, const char* aPrefix) +{ + Layer::PrintInfo(aTo, aPrefix); + return mValidRegion.IsEmpty() ? + aTo : AppendToString(aTo, mValidRegion, " [valid=", "]"); +} + +nsACString& +ColorLayer::PrintInfo(nsACString& aTo, const char* aPrefix) +{ + Layer::PrintInfo(aTo, aPrefix); + AppendToString(aTo, mColor, " [color=", "]"); + return aTo; +} + +nsACString& +CanvasLayer::PrintInfo(nsACString& aTo, const char* aPrefix) +{ + Layer::PrintInfo(aTo, aPrefix); + AppendToString(aTo, mFilter, " [filter=", "]"); + return aTo; +} + +nsACString& +ImageLayer::PrintInfo(nsACString& aTo, const char* aPrefix) +{ + Layer::PrintInfo(aTo, aPrefix); + AppendToString(aTo, mFilter, " [filter=", "]"); + return aTo; +} + +//-------------------------------------------------- +// LayerManager + +void +LayerManager::Dump(FILE* aFile, const char* aPrefix) +{ + FILE* file = FILEOrDefault(aFile); + + DumpSelf(file, aPrefix); + + nsCAutoString pfx(aPrefix); + pfx += " "; + if (!mRoot) { + fprintf(file, "%s(null)", pfx.get()); + return; + } + + mRoot->Dump(file, pfx.get()); +} + +void +LayerManager::DumpSelf(FILE* aFile, const char* aPrefix) +{ + nsCAutoString str; + PrintInfo(str, aPrefix); + fprintf(FILEOrDefault(aFile), "%s\n", str.get()); +} + +void +LayerManager::Log(const char* aPrefix) +{ + if (!IsLogEnabled()) + return; + + LogSelf(aPrefix); + + nsCAutoString pfx(aPrefix); + pfx += " "; + if (!mRoot) { + MOZ_LAYERS_LOG(("%s(null)", pfx.get())); + return; + } + + mRoot->Log(pfx.get()); +} + +void +LayerManager::LogSelf(const char* aPrefix) +{ + nsCAutoString str; + PrintInfo(str, aPrefix); + MOZ_LAYERS_LOG(("%s", str.get())); +} + +nsACString& +LayerManager::PrintInfo(nsACString& aTo, const char* aPrefix) +{ + aTo += aPrefix; + return aTo += nsPrintfCString(64, "%sLayerManager (0x%p)", Name(), this); +} + +/*static*/ void +LayerManager::InitLog() +{ + if (!sLog) + sLog = PR_NewLogModule("Layers"); +} + +/*static*/ bool +LayerManager::IsLogEnabled() +{ + NS_ABORT_IF_FALSE(!!sLog, + "layer manager must be created before logging is allowed"); + return PR_LOG_TEST(sLog, PR_LOG_DEBUG); +} + +#else // !MOZ_LAYERS_HAVE_LOG + +void Layer::Dump(FILE* aFile, const char* aPrefix) {} +void Layer::DumpSelf(FILE* aFile, const char* aPrefix) {} +void Layer::Log(const char* aPrefix) {} +void Layer::LogSelf(const char* aPrefix) {} +nsACString& +Layer::PrintInfo(nsACString& aTo, const char* aPrefix) +{ return aTo; } + +nsACString& +ThebesLayer::PrintInfo(nsACString& aTo, const char* aPrefix) +{ return aTo; } + +nsACString& +ColorLayer::PrintInfo(nsACString& aTo, const char* aPrefix) +{ return aTo; } + +nsACString& +CanvasLayer::PrintInfo(nsACString& aTo, const char* aPrefix) +{ return aTo; } + +nsACString& +ImageLayer::PrintInfo(nsACString& aTo, const char* aPrefix) +{ return aTo; } + +void LayerManager::Dump(FILE* aFile, const char* aPrefix) {} +void LayerManager::DumpSelf(FILE* aFile, const char* aPrefix) {} +void LayerManager::Log(const char* aPrefix) {} +void LayerManager::LogSelf(const char* aPrefix) {} + +nsACString& +LayerManager::PrintInfo(nsACString& aTo, const char* aPrefix) +{ return aTo; } + +/*static*/ void LayerManager::InitLog() {} +/*static*/ bool LayerManager::IsLogEnabled() { return false; } + +#endif // MOZ_LAYERS_HAVE_LOG + +PRLogModuleInfo* LayerManager::sLog; + +} // namespace layers +} // namespace mozilla diff --git a/gfx/layers/Layers.h b/gfx/layers/Layers.h index 3f855903654f..fb93601b1026 100644 --- a/gfx/layers/Layers.h +++ b/gfx/layers/Layers.h @@ -50,8 +50,15 @@ #include "gfxPattern.h" #if defined(DEBUG) || defined(PR_LOGGING) +# include // FILE +# include "prlog.h" # define MOZ_LAYERS_HAVE_LOG -#endif +# define MOZ_LAYERS_LOG(_args) \ + PR_LOG(LayerManager::GetLog(), PR_LOG_DEBUG, _args) +#else +struct PRLogModuleInfo; +# define MOZ_LAYERS_LOG(_args) +#endif // if defined(DEBUG) || defined(PR_LOGGING) class gfxContext; class nsPaintEvent; @@ -134,7 +141,10 @@ public: LAYERS_D3D9 }; - LayerManager() : mUserData(nsnull) {} + LayerManager() : mUserData(nsnull) + { + InitLog(); + } virtual ~LayerManager() {} /** @@ -246,13 +256,47 @@ public: void SetUserData(void* aData) { mUserData = aData; } void* GetUserData() { return mUserData; } -#ifdef MOZ_LAYERS_HAVE_LOG + // We always declare the following logging symbols, because it's + // extremely tricky to conditionally declare them. However, for + // ifndef MOZ_LAYERS_HAVE_LOG builds, they only have trivial + // definitions in Layers.cpp. virtual const char* Name() const { return "???"; } -#endif // MOZ_LAYERS_HAVE_LOG + + /** + * Dump information about this layer manager and its managed tree to + * aFile, which defaults to stderr. + */ + void Dump(FILE* aFile=NULL, const char* aPrefix=""); + /** + * Dump information about just this layer manager itself to aFile, + * which defaults to stderr. + */ + void DumpSelf(FILE* aFile=NULL, const char* aPrefix=""); + + /** + * Log information about this layer manager and its managed tree to + * the NSPR log (if enabled for "Layers"). + */ + void Log(const char* aPrefix=""); + /** + * Log information about just this layer manager itself to the NSPR + * log (if enabled for "Layers"). + */ + void LogSelf(const char* aPrefix=""); + + static bool IsLogEnabled(); + static PRLogModuleInfo* GetLog() { return sLog; } protected: nsRefPtr mRoot; void* mUserData; + + // Print interesting information about this into aTo. Internally + // used to implement Dump*() and Log*(). + virtual nsACString& PrintInfo(nsACString& aTo, const char* aPrefix); + + static void InitLog(); + static PRLogModuleInfo* sLog; }; class ThebesLayer; @@ -373,9 +417,7 @@ public: */ virtual ThebesLayer* AsThebesLayer() { return nsnull; } -#ifdef MOZ_LAYERS_HAVE_LOG virtual const char* Name() const =0; -#endif virtual LayerType GetType() const =0; /** @@ -392,6 +434,30 @@ public: void SetNextSibling(Layer* aSibling) { mNextSibling = aSibling; } void SetPrevSibling(Layer* aSibling) { mPrevSibling = aSibling; } + /** + * Dump information about this layer manager and its managed tree to + * aFile, which defaults to stderr. + */ + void Dump(FILE* aFile=NULL, const char* aPrefix=""); + /** + * Dump information about just this layer manager itself to aFile, + * which defaults to stderr. + */ + void DumpSelf(FILE* aFile=NULL, const char* aPrefix=""); + + /** + * Log information about this layer manager and its managed tree to + * the NSPR log (if enabled for "Layers"). + */ + void Log(const char* aPrefix=""); + /** + * Log information about just this layer manager itself to the NSPR + * log (if enabled for "Layers"). + */ + void LogSelf(const char* aPrefix=""); + + static bool IsLogEnabled() { return LayerManager::IsLogEnabled(); } + protected: Layer(LayerManager* aManager, void* aImplData) : mManager(aManager), @@ -405,6 +471,13 @@ protected: mIsOpaqueContent(PR_FALSE) {} + // Print interesting information about this into aTo. Internally + // used to implement Dump*() and Log*(). If subclasses have + // additional interesting properties, they should override this with + // an implementation that first calls the base implementation then + // appends additional info to aTo. + virtual nsACString& PrintInfo(nsACString& aTo, const char* aPrefix); + LayerManager* mManager; ContainerLayer* mParent; Layer* mNextSibling; @@ -453,6 +526,8 @@ protected: ThebesLayer(LayerManager* aManager, void* aImplData) : Layer(aManager, aImplData) {} + virtual nsACString& PrintInfo(nsACString& aTo, const char* aPrefix); + nsIntRegion mValidRegion; }; @@ -518,6 +593,8 @@ protected: mColor(0.0, 0.0, 0.0, 0.0) {} + virtual nsACString& PrintInfo(nsACString& aTo, const char* aPrefix); + gfxRGBA mColor; }; @@ -584,6 +661,8 @@ protected: CanvasLayer(LayerManager* aManager, void* aImplData) : Layer(aManager, aImplData), mFilter(gfxPattern::FILTER_GOOD) {} + virtual nsACString& PrintInfo(nsACString& aTo, const char* aPrefix); + gfxPattern::GraphicsFilter mFilter; }; diff --git a/gfx/layers/Makefile.in b/gfx/layers/Makefile.in index 4eab1b94bb88..011b78c8d038 100644 --- a/gfx/layers/Makefile.in +++ b/gfx/layers/Makefile.in @@ -66,6 +66,7 @@ EXPORTS = \ $(NULL) CPPSRCS = \ + Layers.cpp \ BasicImages.cpp \ BasicLayers.cpp \ ThebesLayerBuffer.cpp \ diff --git a/gfx/layers/basic/BasicLayers.cpp b/gfx/layers/basic/BasicLayers.cpp index 8090d5bdceec..6b657f58e6d9 100644 --- a/gfx/layers/basic/BasicLayers.cpp +++ b/gfx/layers/basic/BasicLayers.cpp @@ -812,6 +812,11 @@ BasicLayerManager::PopGroupWithCachedSurface(gfxContext *aTarget, void BasicLayerManager::BeginTransactionWithTarget(gfxContext* aTarget) { +#ifdef MOZ_LAYERS_HAVE_LOG + MOZ_LAYERS_LOG(("[----- BeginTransaction")); + Log(); +#endif + NS_ASSERTION(!InTransaction(), "Nested transactions not allowed"); #ifdef DEBUG mPhase = PHASE_CONSTRUCTION; @@ -823,6 +828,11 @@ void BasicLayerManager::EndTransaction(DrawThebesLayerCallback aCallback, void* aCallbackData) { +#ifdef MOZ_LAYERS_HAVE_LOG + Log(); + MOZ_LAYERS_LOG(("]----- EndTransaction")); +#endif + NS_ASSERTION(InConstruction(), "Should be in construction phase"); #ifdef DEBUG mPhase = PHASE_DRAWING; diff --git a/layout/base/FrameLayerBuilder.cpp b/layout/base/FrameLayerBuilder.cpp index e78c8100af13..91ae62d0eb5e 100644 --- a/layout/base/FrameLayerBuilder.cpp +++ b/layout/base/FrameLayerBuilder.cpp @@ -1404,95 +1404,11 @@ FrameLayerBuilder::DrawThebesLayer(ThebesLayer* aLayer, } #ifdef DEBUG -static void -DumpIntRegion(FILE* aStream, const char* aName, const nsIntRegion& aRegion) -{ - if (aRegion.IsEmpty()) - return; - - fprintf(aStream, " [%s=", aName); - nsIntRegionRectIterator iter(aRegion); - const nsIntRect* r; - PRBool first = PR_TRUE; - while ((r = iter.Next()) != nsnull) { - if (!first) { - fputs(";", aStream); - } else { - first = PR_FALSE; - } - fprintf(aStream, "%d,%d,%d,%d", r->x, r->y, r->width, r->height); - } - fputs("]", aStream); -} - -static void -DumpLayer(FILE* aStream, Layer* aLayer, PRUint32 aIndent) -{ - if (!aLayer) - return; - - for (PRUint32 i = 0; i < aIndent; ++i) { - fputs(" ", aStream); - } - const char* name = aLayer->Name(); - ThebesLayer* thebes = aLayer->AsThebesLayer(); - fprintf(aStream, "%s(%p)", name, aLayer); - - DumpIntRegion(aStream, "visible", aLayer->GetVisibleRegion()); - - gfx3DMatrix transform = aLayer->GetTransform(); - if (!transform.IsIdentity()) { - gfxMatrix matrix; - if (transform.Is2D(&matrix)) { - fprintf(aStream, " [transform=%g,%g; %g,%g; %g,%g]", - matrix.xx, matrix.yx, matrix.xy, matrix.yy, matrix.x0, matrix.y0); - } else { - fprintf(aStream, " [transform=%g,%g,%g,%g; %g,%g,%g,%g; %g,%g,%g,%g; %g,%g,%g,%g]", - transform._11, transform._12, transform._13, transform._14, - transform._21, transform._22, transform._23, transform._24, - transform._31, transform._32, transform._33, transform._34, - transform._41, transform._42, transform._43, transform._44); - } - } - - const nsIntRect* clip = aLayer->GetClipRect(); - if (clip) { - fprintf(aStream, " [clip=%d,%d,%d,%d]", - clip->x, clip->y, clip->width, clip->height); - } - - float opacity = aLayer->GetOpacity(); - if (opacity != 1.0) { - fprintf(aStream, " [opacity=%f]", opacity); - } - - if (aLayer->IsOpaqueContent()) { - fputs(" [opaqueContent]", aStream); - } - - if (thebes) { - DumpIntRegion(aStream, "valid", thebes->GetValidRegion()); - } - - fputs("\n", aStream); - - for (Layer* child = aLayer->GetFirstChild(); child; - child = child->GetNextSibling()) { - DumpLayer(aStream, child, aIndent + 1); - } -} - -/* static */ void -FrameLayerBuilder::DumpLayerTree(LayerManager* aManager) -{ - DumpLayer(stderr, aManager->GetRoot(), 0); -} - void FrameLayerBuilder::DumpRetainedLayerTree() { if (mRetainingManager) { - DumpLayerTree(mRetainingManager); + mRetainingManager->Dump(stderr); } } #endif diff --git a/layout/base/FrameLayerBuilder.h b/layout/base/FrameLayerBuilder.h index 05e05ba40d9c..456f08ef849d 100644 --- a/layout/base/FrameLayerBuilder.h +++ b/layout/base/FrameLayerBuilder.h @@ -201,11 +201,6 @@ public: void* aCallbackData); #ifdef DEBUG - /** - * Dumps aManager's layer tree to stderr. - */ - static void DumpLayerTree(LayerManager* aManager); - /** * Dumps this FrameLayerBuilder's retained layer manager's retained * layer tree to stderr.