Bug 700240 - Print display lists to a file. r=roc,bjacob

This commit is contained in:
Matt Woodrow 2012-03-01 21:26:09 +13:00
parent 63d5bd1d56
commit 72f481f48f
19 changed files with 392 additions and 48 deletions

View File

@ -253,6 +253,7 @@ GLContext::InitWithPrefix(const char *prefix, bool trygl)
{ (PRFuncPtr*) &mSymbols.fTexParameteri, { "TexParameteri", NULL } },
{ (PRFuncPtr*) &mSymbols.fTexParameterf, { "TexParameterf", NULL } },
{ (PRFuncPtr*) &mSymbols.fGetString, { "GetString", NULL } },
{ (PRFuncPtr*) &mSymbols.fGetTexLevelParameteriv, { "GetTexLevelParameteriv", NULL } },
{ (PRFuncPtr*) &mSymbols.fGetTexParameterfv, { "GetTexParameterfv", NULL } },
{ (PRFuncPtr*) &mSymbols.fGetTexParameteriv, { "GetTexParameteriv", NULL } },
{ (PRFuncPtr*) &mSymbols.fGetUniformfv, { "GetUniformfv", "GetUniformfvARB", NULL } },
@ -494,6 +495,13 @@ GLContext::InitWithPrefix(const char *prefix, bool trygl)
mInitialized = false;
}
}
// Load developer symbols, don't fail if we can't find them.
SymLoadStruct auxSymbols[] = {
{ (PRFuncPtr*) &mSymbols.fGetTexImage, { "GetTexImage", NULL } },
{ NULL, { NULL } },
};
LoadSymbols(&auxSymbols[0], trygl, prefix);
}
if (mInitialized) {
@ -1598,10 +1606,73 @@ GLContext::MarkDestroyed()
mSymbols.Zero();
}
static void SwapRAndBComponents(gfxImageSurface* aSurf)
{
gfxIntSize size = aSurf->GetSize();
for (int j = 0; j < size.height; ++j) {
PRUint32 *row = (PRUint32*) (aSurf->Data() + aSurf->Stride() * j);
for (int i = 0; i < size.width; ++i) {
*row = (*row & 0xff00ff00) | ((*row & 0xff) << 16) | ((*row & 0xff0000) >> 16);
row++;
}
}
}
static already_AddRefed<gfxImageSurface> YInvertImageSurface(gfxImageSurface* aSurf)
{
gfxIntSize size = aSurf->GetSize();
nsRefPtr<gfxImageSurface> temp = new gfxImageSurface(size, aSurf->Format());
nsRefPtr<gfxContext> ctx = new gfxContext(temp);
ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
ctx->Scale(1.0, -1.0);
ctx->Translate(-gfxPoint(0.0, size.height));
ctx->SetSource(aSurf);
ctx->Paint();
return temp.forget();
}
already_AddRefed<gfxImageSurface>
GLContext::GetTexImage(GLuint aTexture, bool aYInvert, ShaderProgramType aShader)
{
MakeCurrent();
fFinish();
fActiveTexture(LOCAL_GL_TEXTURE0);
fBindTexture(LOCAL_GL_TEXTURE_2D, aTexture);
gfxIntSize size;
fGetTexLevelParameteriv(LOCAL_GL_TEXTURE_2D, 0, LOCAL_GL_TEXTURE_WIDTH, &size.width);
fGetTexLevelParameteriv(LOCAL_GL_TEXTURE_2D, 0, LOCAL_GL_TEXTURE_HEIGHT, &size.height);
nsRefPtr<gfxImageSurface> surf = new gfxImageSurface(size, gfxASurface::ImageFormatARGB32);
if (!surf || surf->CairoStatus()) {
return NULL;
}
PRUint32 currentPackAlignment = 0;
fGetIntegerv(LOCAL_GL_PACK_ALIGNMENT, (GLint*)&currentPackAlignment);
if (currentPackAlignment != 4) {
fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, 4);
}
fGetTexImage(LOCAL_GL_TEXTURE_2D, 0, LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE, surf->Data());
if (currentPackAlignment != 4) {
fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, currentPackAlignment);
}
if (aShader == RGBALayerProgramType || aShader == RGBXLayerProgramType) {
SwapRAndBComponents(surf);
}
if (aYInvert) {
surf = YInvertImageSurface(surf);
}
return surf.forget();
}
already_AddRefed<gfxImageSurface>
GLContext::ReadTextureImage(GLuint aTexture,
const gfxIntSize& aSize,
GLenum aTextureFormat)
GLenum aTextureFormat,
bool aYInvert)
{
MakeCurrent();
@ -1664,6 +1735,8 @@ GLContext::ReadTextureImage(GLuint aTexture,
fs = fCreateShader(LOCAL_GL_FRAGMENT_SHADER);
fShaderSource(vs, 1, (const GLchar**) &vShader, NULL);
fShaderSource(fs, 1, (const GLchar**) &fShader, NULL);
fCompileShader(vs);
fCompileShader(fs);
prog = fCreateProgram();
fAttachShader(prog, vs);
fAttachShader(prog, fs);
@ -1707,9 +1780,15 @@ GLContext::ReadTextureImage(GLuint aTexture,
LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE,
isurf->Data());
SwapRAndBComponents(isurf);
if (oldPackAlignment != 4)
fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, oldPackAlignment);
if (aYInvert) {
isurf = YInvertImageSurface(isurf);
}
cleanup:
// note that deleting 0 has no effect in any of these calls
fDeleteRenderbuffers(1, &rb);

View File

@ -1233,7 +1233,10 @@ public:
*/
already_AddRefed<gfxImageSurface> ReadTextureImage(GLuint aTexture,
const gfxIntSize& aSize,
GLenum aTextureFormat);
GLenum aTextureFormat,
bool aYInvert = false);
already_AddRefed<gfxImageSurface> GetTexImage(GLuint aTexture, bool aYInvert, ShaderProgramType aShader);
/**
* Call ReadPixels into an existing gfxImageSurface for the given bounds.
@ -2122,6 +2125,22 @@ public:
return result;
}
void fGetTexImage(GLenum target, GLint level, GLenum format, GLenum type, GLvoid *img) {
if (!mSymbols.fGetTexImage) {
return;
}
BEFORE_GL_CALL;
mSymbols.fGetTexImage(target, level, format, type, img);
AFTER_GL_CALL;
};
void fGetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint *params)
{
BEFORE_GL_CALL;
mSymbols.fGetTexLevelParameteriv(target, level, pname, params);
AFTER_GL_CALL;
}
void fGetTexParameterfv(GLenum target, GLenum pname, const GLfloat *params) {
BEFORE_GL_CALL;
mSymbols.fGetTexParameterfv(target, pname, params);

View File

@ -155,6 +155,10 @@ struct GLContextSymbols
PFNGLTEXPARAMETERFPROC fTexParameterf;
typedef GLubyte* (GLAPIENTRY * PFNGLGETSTRINGPROC) (GLenum);
PFNGLGETSTRINGPROC fGetString;
typedef void (GLAPIENTRY * PFNGLGETTEXIMAGEPROC) (GLenum target, GLint level, GLenum format, GLenum type, GLvoid* image);
PFNGLGETTEXIMAGEPROC fGetTexImage;
typedef void (GLAPIENTRY * PFNGLGETTEXLEVELPARAMETERIVPROC) (GLenum target, GLint level, GLenum pname, GLint *params);
PFNGLGETTEXLEVELPARAMETERIVPROC fGetTexLevelParameteriv;
typedef void (GLAPIENTRY * PFNGLGETTEXPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params);
PFNGLGETTEXPARAMETERFVPROC fGetTexParameterfv;
typedef void (GLAPIENTRY * PFNGLGETTEXPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params);

View File

@ -458,6 +458,10 @@ ContainerLayer::DefaultComputeEffectiveTransforms(const gfx3DMatrix& aTransformT
float opacity = GetEffectiveOpacity();
if (opacity != 1.0f && HasMultipleChildren()) {
useIntermediateSurface = true;
#ifdef MOZ_DUMP_PAINTING
} else if (gfxUtils::sDumpPainting) {
useIntermediateSurface = true;
#endif
} else {
useIntermediateSurface = false;
gfxMatrix contTransform;
@ -552,17 +556,60 @@ LayerManager::StopFrameTimeRecording()
static nsACString& PrintInfo(nsACString& aTo, ShadowLayer* aShadowLayer);
#ifdef MOZ_DUMP_PAINTING
template <typename T>
void WriteSnapshotLinkToDumpFile(T* aObj, FILE* aFile)
{
nsCString string(aObj->Name());
string.Append("-");
string.AppendInt((PRUint64)aObj);
fprintf(aFile, "href=\"javascript:ViewImage('%s')\"", string.BeginReading());
}
template <typename T>
void WriteSnapshotToDumpFile_internal(T* aObj, gfxASurface* aSurf)
{
nsCString string(aObj->Name());
string.Append("-");
string.AppendInt((PRUint64)aObj);
fprintf(gfxUtils::sDumpPaintFile, "array[\"%s\"]=\"", string.BeginReading());
aSurf->DumpAsDataURL(gfxUtils::sDumpPaintFile);
fprintf(gfxUtils::sDumpPaintFile, "\";");
}
void WriteSnapshotToDumpFile(Layer* aLayer, gfxASurface* aSurf)
{
WriteSnapshotToDumpFile_internal(aLayer, aSurf);
}
void WriteSnapshotToDumpFile(LayerManager* aManager, gfxASurface* aSurf)
{
WriteSnapshotToDumpFile_internal(aManager, aSurf);
}
#endif
void
Layer::Dump(FILE* aFile, const char* aPrefix)
{
fprintf(aFile, "<li><a id=\"%p\" ", this);
#ifdef MOZ_DUMP_PAINTING
if (GetType() == TYPE_CONTAINER || GetType() == TYPE_THEBES) {
WriteSnapshotLinkToDumpFile(this, aFile);
}
#endif
fprintf(aFile, ">");
DumpSelf(aFile, aPrefix);
fprintf(aFile, "</a>");
if (Layer* kid = GetFirstChild()) {
nsCAutoString pfx(aPrefix);
pfx += " ";
fprintf(aFile, "<ul>");
kid->Dump(aFile, pfx.get());
fprintf(aFile, "</ul>");
}
fprintf(aFile, "</li>");
if (Layer* next = GetNextSibling())
next->Dump(aFile, aPrefix);
}
@ -714,17 +761,27 @@ void
LayerManager::Dump(FILE* aFile, const char* aPrefix)
{
FILE* file = FILEOrDefault(aFile);
fprintf(file, "<ul><li><a ");
#ifdef MOZ_DUMP_PAINTING
WriteSnapshotLinkToDumpFile(this, aFile);
#endif
fprintf(file, ">");
DumpSelf(file, aPrefix);
#ifdef MOZ_DUMP_PAINTING
fprintf(aFile, "</a>");
#endif
nsCAutoString pfx(aPrefix);
pfx += " ";
if (!GetRoot()) {
fprintf(file, "%s(null)", pfx.get());
fprintf(file, "%s(null)</li></ul>", pfx.get());
return;
}
fprintf(file, "<ul>");
GetRoot()->Dump(file, pfx.get());
fprintf(file, "</ul></li></ul>");
}
void

View File

@ -1345,6 +1345,11 @@ protected:
bool mDirty;
};
#ifdef MOZ_DUMP_PAINTING
void WriteSnapshotToDumpFile(Layer* aLayer, gfxASurface* aSurf);
void WriteSnapshotToDumpFile(LayerManager* aManager, gfxASurface* aSurf);
#endif
}
}

View File

@ -256,6 +256,14 @@ ContainerRender(Container* aContainer,
if (needsFramebuffer) {
// Unbind the current framebuffer and rebind the previous one.
#ifdef MOZ_DUMP_PAINTING
if (gfxUtils::sDumpPainting) {
nsRefPtr<gfxImageSurface> surf =
aContainer->gl()->GetTexImage(containerSurface, true, aManager->GetFBOLayerProgramType());
WriteSnapshotToDumpFile(aContainer, surf);
}
#endif
// Restore the viewport
aContainer->gl()->PopViewportRect();

View File

@ -54,6 +54,8 @@
#include "LayerManagerOGLShaders.h"
#include "gfxContext.h"
#include "gfxUtils.h"
#include "gfxPlatform.h"
#include "nsIWidget.h"
#include "GLContext.h"
@ -779,8 +781,20 @@ LayerManagerOGL::Render()
mWidget->DrawWindowOverlay(this, rect);
#ifdef MOZ_DUMP_PAINTING
if (gfxUtils::sDumpPainting) {
nsIntRect rect;
mWidget->GetBounds(rect);
nsRefPtr<gfxASurface> surf = gfxPlatform::GetPlatform()->CreateOffscreenSurface(rect.Size(), gfxASurface::CONTENT_COLOR_ALPHA);
nsRefPtr<gfxContext> ctx = new gfxContext(surf);
CopyToTarget(ctx);
WriteSnapshotToDumpFile(this, surf);
}
#endif
if (mTarget) {
CopyToTarget();
CopyToTarget(mTarget);
mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
return;
}
@ -986,7 +1000,7 @@ LayerManagerOGL::SetupBackBuffer(int aWidth, int aHeight)
}
void
LayerManagerOGL::CopyToTarget()
LayerManagerOGL::CopyToTarget(gfxContext *aTarget)
{
nsIntRect rect;
mWidget->GetBounds(rect);
@ -1050,11 +1064,11 @@ LayerManagerOGL::CopyToTarget()
}
}
mTarget->SetOperator(gfxContext::OPERATOR_SOURCE);
mTarget->Scale(1.0, -1.0);
mTarget->Translate(-gfxPoint(0.0, height));
mTarget->SetSource(imageSurface);
mTarget->Paint();
aTarget->SetOperator(gfxContext::OPERATOR_SOURCE);
aTarget->Scale(1.0, -1.0);
aTarget->Translate(-gfxPoint(0.0, height));
aTarget->SetSource(imageSurface);
aTarget->Paint();
}
LayerManagerOGL::ProgramType LayerManagerOGL::sLayerProgramTypes[] = {

View File

@ -236,9 +236,13 @@ public:
}
ColorTextureLayerProgram *GetFBOLayerProgram() {
return static_cast<ColorTextureLayerProgram*>(mPrograms[GetFBOLayerProgramType()]);
}
gl::ShaderProgramType GetFBOLayerProgramType() {
if (mFBOTextureTarget == LOCAL_GL_TEXTURE_RECTANGLE_ARB)
return static_cast<ColorTextureLayerProgram*>(mPrograms[gl::RGBARectLayerProgramType]);
return static_cast<ColorTextureLayerProgram*>(mPrograms[gl::RGBALayerProgramType]);
return gl::RGBARectLayerProgramType;
return gl::RGBALayerProgramType;
}
GLContext *gl() const { return mGLContext; }
@ -451,7 +455,7 @@ private:
/**
* Copies the content of our backbuffer to the set transaction target.
*/
void CopyToTarget();
void CopyToTarget(gfxContext *aTarget);
/**
* Updates all layer programs with a new projection matrix.

View File

@ -145,6 +145,15 @@ ThebesLayerBufferOGL::RenderTo(const nsIntPoint& aOffset,
mTexImageOnWhite->EndUpdate();
}
#ifdef MOZ_DUMP_PAINTING
if (gfxUtils::sDumpPainting) {
nsRefPtr<gfxImageSurface> surf =
gl()->GetTexImage(mTexImage->GetTextureID(), false, mTexImage->GetShaderProgramType());
WriteSnapshotToDumpFile(mLayer, surf);
}
#endif
PRInt32 passes = mTexImageOnWhite ? 2 : 1;
for (PRInt32 pass = 1; pass <= passes; ++pass) {
LayerProgram *program;

View File

@ -716,9 +716,16 @@ gfxASurface::WriteAsPNG(const char* aFile)
}
void
gfxASurface::DumpAsDataURL()
gfxASurface::DumpAsDataURL(FILE* aOutput)
{
WriteAsPNG_internal(aOutput, false);
}
void
gfxASurface::PrintAsDataURL()
{
WriteAsPNG_internal(stdout, false);
fprintf(stdout, "\n");
}
void
@ -776,7 +783,6 @@ gfxASurface::WriteAsPNG_internal(FILE* aFile, bool aBinary)
for (PRInt32 x = 0; x < w; ++x) {
printf("%x ", reinterpret_cast<PRUint32*>(imgsurf->Data())[y*imgsurf->Stride()+ x]);
}
printf("\n");
}
return;
}
@ -846,7 +852,6 @@ gfxASurface::WriteAsPNG_internal(FILE* aFile, bool aBinary)
if (aFile) {
fprintf(aFile, "%s", string.BeginReading());
fprintf(aFile, "\n");
} else {
nsCOMPtr<nsIClipboardHelper> clipboard(do_GetService("@mozilla.org/widget/clipboardhelper;1", &rv));
if (clipboard) {

View File

@ -257,10 +257,15 @@ public:
*/
void WriteAsPNG(const char* aFile);
/**
* Write as a PNG encoded Data URL to a file.
*/
void DumpAsDataURL(FILE* aOutput = stdout);
/**
* Write as a PNG encoded Data URL to stdout.
*/
void DumpAsDataURL();
void PrintAsDataURL();
/**
* Copy a PNG encoded Data URL to the clipboard.

View File

@ -692,4 +692,8 @@ gfxUtils::CopyAsDataURL(DrawTarget* aDT)
NS_WARNING("Failed to get Thebes surface!");
}
}
bool gfxUtils::sDumpPainting = getenv("MOZ_DUMP_PAINT_LIST") != 0;
bool gfxUtils::sDumpPaintingToFile = getenv("MOZ_DUMP_PAINT_TO_FILE") != 0;
FILE *gfxUtils::sDumpPaintFile = NULL;
#endif

View File

@ -167,7 +167,12 @@ public:
* Copy a PNG encoded Data URL to the clipboard.
*/
static void CopyAsDataURL(mozilla::gfx::DrawTarget* aDT);
static bool sDumpPainting;
static bool sDumpPaintingToFile;
static FILE* sDumpPaintFile;
#endif
};
#endif

View File

@ -1312,6 +1312,19 @@ ContainerState::FindThebesLayerFor(nsDisplayItem* aItem,
return layer.forget();
}
#ifdef MOZ_DUMP_PAINTING
static void
DumpPaintedImage(nsDisplayItem* aItem, gfxASurface* aSurf)
{
nsCString string(aItem->Name());
string.Append("-");
string.AppendInt((PRUint64)aItem);
fprintf(gfxUtils::sDumpPaintFile, "array[\"%s\"]=\"", string.BeginReading());
aSurf->DumpAsDataURL(gfxUtils::sDumpPaintFile);
fprintf(gfxUtils::sDumpPaintFile, "\";");
}
#endif
static void
PaintInactiveLayer(nsDisplayListBuilder* aBuilder,
nsDisplayItem* aItem,
@ -1319,23 +1332,47 @@ PaintInactiveLayer(nsDisplayListBuilder* aBuilder,
{
// This item has an inactive layer. Render it to a ThebesLayer
// using a temporary BasicLayerManager.
PRInt32 appUnitsPerDevPixel = AppUnitsPerDevPixel(aItem);
nsIntRect itemVisibleRect =
aItem->GetVisibleRect().ToOutsidePixels(appUnitsPerDevPixel);
nsRefPtr<gfxContext> context = aContext;
#ifdef MOZ_DUMP_PAINTING
nsRefPtr<gfxASurface> surf;
if (gfxUtils::sDumpPainting) {
surf = gfxPlatform::GetPlatform()->CreateOffscreenSurface(itemVisibleRect.Size(),
gfxASurface::CONTENT_COLOR_ALPHA);
surf->SetDeviceOffset(-itemVisibleRect.TopLeft());
context = new gfxContext(surf);
}
#endif
nsRefPtr<BasicLayerManager> tempManager = new BasicLayerManager();
tempManager->BeginTransactionWithTarget(aContext);
tempManager->BeginTransactionWithTarget(context);
nsRefPtr<Layer> layer =
aItem->BuildLayer(aBuilder, tempManager, FrameLayerBuilder::ContainerParameters());
if (!layer) {
tempManager->EndTransaction(nsnull, nsnull);
return;
}
PRInt32 appUnitsPerDevPixel = AppUnitsPerDevPixel(aItem);
nsIntRect itemVisibleRect =
aItem->GetVisibleRect().ToOutsidePixels(appUnitsPerDevPixel);
RestrictVisibleRegionForLayer(layer, itemVisibleRect);
tempManager->SetRoot(layer);
aBuilder->LayerBuilder()->WillEndTransaction(tempManager);
tempManager->EndTransaction(FrameLayerBuilder::DrawThebesLayer, aBuilder);
aBuilder->LayerBuilder()->DidEndTransaction(tempManager);
#ifdef MOZ_DUMP_PAINTING
if (gfxUtils::sDumpPainting) {
DumpPaintedImage(aItem, surf);
surf->SetDeviceOffset(gfxPoint(0, 0));
aContext->SetSource(surf, itemVisibleRect.TopLeft());
aContext->Rectangle(itemVisibleRect);
aContext->Fill();
aItem->SetPainted();
}
#endif
}
/*
@ -2002,6 +2039,32 @@ FrameLayerBuilder::GetDedicatedLayer(nsIFrame* aFrame, PRUint32 aDisplayItemKey)
return nsnull;
}
#ifdef MOZ_DUMP_PAINTING
static void DebugPaintItem(nsRenderingContext* aDest, nsDisplayItem *aItem, nsDisplayListBuilder* aBuilder)
{
nsRect appUnitBounds = aItem->GetBounds(aBuilder);
gfxRect bounds(appUnitBounds.x, appUnitBounds.y, appUnitBounds.width, appUnitBounds.height);
bounds.ScaleInverse(aDest->AppUnitsPerDevPixel());
nsRefPtr<gfxASurface> surf =
gfxPlatform::GetPlatform()->CreateOffscreenSurface(gfxIntSize(bounds.width, bounds.height),
gfxASurface::CONTENT_COLOR_ALPHA);
surf->SetDeviceOffset(-bounds.TopLeft());
nsRefPtr<gfxContext> context = new gfxContext(surf);
nsRefPtr<nsRenderingContext> ctx = new nsRenderingContext();
ctx->Init(aDest->DeviceContext(), context);
aItem->Paint(aBuilder, ctx);
DumpPaintedImage(aItem, surf);
aItem->SetPainted();
surf->SetDeviceOffset(gfxPoint(0, 0));
aDest->ThebesContext()->SetSource(surf, bounds.TopLeft());
aDest->ThebesContext()->Rectangle(bounds);
aDest->ThebesContext()->Fill();
}
#endif
/*
* A note on residual transforms:
*
@ -2176,7 +2239,16 @@ FrameLayerBuilder::DrawThebesLayer(ThebesLayer* aLayer,
if (frame) {
frame->AddStateBits(NS_FRAME_PAINTED_THEBES);
}
cdi->mItem->Paint(builder, rc);
#ifdef MOZ_DUMP_PAINTING
if (gfxUtils::sDumpPainting) {
DebugPaintItem(rc, cdi->mItem, builder);
} else {
#else
{
#endif
cdi->mItem->Paint(builder, rc);
}
}
if (builder->LayerBuilder()->CheckDOMModified())
@ -2210,10 +2282,10 @@ FrameLayerBuilder::CheckDOMModified()
#ifdef MOZ_DUMP_PAINTING
void
FrameLayerBuilder::DumpRetainedLayerTree()
FrameLayerBuilder::DumpRetainedLayerTree(FILE* aFile)
{
if (mRetainingManager) {
mRetainingManager->Dump(stdout);
mRetainingManager->Dump(aFile);
}
}
#endif

View File

@ -249,7 +249,7 @@ public:
* Dumps this FrameLayerBuilder's retained layer manager's retained
* layer tree to stderr.
*/
void DumpRetainedLayerTree();
void DumpRetainedLayerTree(FILE* aFile = stdout);
#endif
/******* PRIVATE METHODS to FrameLayerBuilder.cpp ********/

View File

@ -566,8 +566,12 @@ public:
// This is never instantiated directly (it has pure virtual methods), so no
// need to count constructors and destructors.
nsDisplayItem(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame) :
mFrame(aFrame) {
nsDisplayItem(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
: mFrame(aFrame)
#ifdef MOZ_DUMP_PAINTING
, mPainted(false)
#endif
{
if (aFrame) {
mToReferenceFrame = aBuilder->ToReferenceFrame(aFrame);
}
@ -715,6 +719,19 @@ public:
* aCtx must be set up as for nsDisplayList::Paint.
*/
virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) {}
#ifdef MOZ_DUMP_PAINTING
/**
* Mark this display item as being painted via FrameLayerBuilder::DrawThebesLayer.
*/
bool Painted() { return mPainted; }
/**
* Check if this display item has been painted.
*/
void SetPainted() { mPainted = true; }
#endif
/**
* Get the layer drawn by this display item. Call this only if
* GetLayerState() returns something other than LAYER_NONE.
@ -850,6 +867,10 @@ protected:
// of the item. Paint implementations can use this to limit their drawing.
// Guaranteed to be contained in GetBounds().
nsRect mVisibleRect;
#ifdef MOZ_DUMP_PAINTING
// True if this frame has been painted.
bool mPainted;
#endif
};
/**

View File

@ -153,16 +153,16 @@ nsLayoutDebugger::GetStyleSize(nsIPresShell* aPresentation,
#ifdef MOZ_DUMP_PAINTING
static void
PrintDisplayListTo(nsDisplayListBuilder* aBuilder, const nsDisplayList& aList,
PRInt32 aIndent, FILE* aOutput)
FILE* aOutput)
{
fprintf(aOutput, "<ul>");
for (nsDisplayItem* i = aList.GetBottom(); i != nsnull; i = i->GetAbove()) {
#ifdef DEBUG
if (aList.DidComputeVisibility() && i->GetVisibleRect().IsEmpty())
continue;
#endif
for (PRInt32 j = 0; j < aIndent; ++j) {
fputc(' ', aOutput);
}
fprintf(aOutput, "<li>");
nsIFrame* f = i->GetUnderlyingFrame();
nsAutoString fName;
#ifdef DEBUG
@ -194,17 +194,26 @@ PrintDisplayListTo(nsDisplayListBuilder* aBuilder, const nsDisplayList& aList,
opaque = i->GetOpaqueRegion(aBuilder);
}
#endif
if (i->Painted()) {
nsCString string(i->Name());
string.Append("-");
string.AppendInt((PRUint64)i);
fprintf(aOutput, "<a href=\"javascript:ViewImage('%s')\">", string.BeginReading());
}
fprintf(aOutput, "%s %p(%s) (%d,%d,%d,%d)(%d,%d,%d,%d)%s%s",
i->Name(), (void*)f, NS_ConvertUTF16toUTF8(fName).get(),
rect.x, rect.y, rect.width, rect.height,
vis.x, vis.y, vis.width, vis.height,
opaque.IsEmpty() ? "" : " opaque",
i->IsUniform(aBuilder, &color) ? " uniform" : "");
if (i->Painted()) {
fprintf(aOutput, "</a>");
}
if (f) {
PRUint32 key = i->GetPerFrameKey();
Layer* layer = aBuilder->LayerBuilder()->GetOldLayerFor(f, key);
if (layer) {
fprintf(aOutput, " layer=%p", layer);
fprintf(aOutput, " <a href=\"#%p\">layer=%p</a>", layer, layer);
}
}
if (i->GetType() == nsDisplayItem::TYPE_SVG_EFFECTS) {
@ -212,16 +221,20 @@ PrintDisplayListTo(nsDisplayListBuilder* aBuilder, const nsDisplayList& aList,
}
fputc('\n', aOutput);
if (list) {
PrintDisplayListTo(aBuilder, *list, aIndent + 4, aOutput);
PrintDisplayListTo(aBuilder, *list, aOutput);
}
fprintf(aOutput, "</li>");
}
fprintf(aOutput, "</ul>");
}
void
nsFrame::PrintDisplayList(nsDisplayListBuilder* aBuilder,
const nsDisplayList& aList)
const nsDisplayList& aList,
FILE* aFile)
{
PrintDisplayListTo(aBuilder, aList, 0, stdout);
PrintDisplayListTo(aBuilder, aList, aFile);
}
#endif

View File

@ -1381,8 +1381,8 @@ nsLayoutUtils::CombineBreakType(PRUint8 aOrigBreakType,
#ifdef MOZ_DUMP_PAINTING
#include <stdio.h>
static bool gDumpPaintList = getenv("MOZ_DUMP_PAINT_LIST") != 0;
static bool gDumpEventList = false;
int gPaintCount = 0;
#endif
nsresult
@ -1774,10 +1774,22 @@ nsLayoutUtils::PaintFrame(nsRenderingContext* aRenderingContext, nsIFrame* aFram
}
#ifdef MOZ_DUMP_PAINTING
if (gDumpPaintList) {
fprintf(stdout, "Painting --- before optimization (dirty %d,%d,%d,%d):\n",
if (gfxUtils::sDumpPainting) {
if (gfxUtils::sDumpPaintingToFile) {
nsCString string("dump-");
string.AppendInt(gPaintCount);
string.Append(".html");
gfxUtils::sDumpPaintFile = fopen(string.BeginReading(), "w");
} else {
gfxUtils::sDumpPaintFile = stdout;
}
fprintf(gfxUtils::sDumpPaintFile, "<html><head><script>var array = {}; function ViewImage(index) { window.location = array[index]; }</script></head><body>");
fprintf(gfxUtils::sDumpPaintFile, "Painting --- before optimization (dirty %d,%d,%d,%d):\n",
dirtyRect.x, dirtyRect.y, dirtyRect.width, dirtyRect.height);
nsFrame::PrintDisplayList(&builder, list);
nsFrame::PrintDisplayList(&builder, list, gfxUtils::sDumpPaintFile);
if (gfxUtils::sDumpPaintingToFile) {
fprintf(gfxUtils::sDumpPaintFile, "<script>");
}
}
#endif
@ -1826,12 +1838,19 @@ nsLayoutUtils::PaintFrame(nsRenderingContext* aRenderingContext, nsIFrame* aFram
}
#ifdef MOZ_DUMP_PAINTING
if (gDumpPaintList) {
fprintf(stdout, "Painting --- after optimization:\n");
nsFrame::PrintDisplayList(&builder, list);
if (gfxUtils::sDumpPainting) {
fprintf(gfxUtils::sDumpPaintFile, "</script>Painting --- after optimization:\n");
nsFrame::PrintDisplayList(&builder, list, gfxUtils::sDumpPaintFile);
fprintf(stdout, "Painting --- retained layer tree:\n");
builder.LayerBuilder()->DumpRetainedLayerTree();
fprintf(gfxUtils::sDumpPaintFile, "Painting --- retained layer tree:\n");
builder.LayerBuilder()->DumpRetainedLayerTree(gfxUtils::sDumpPaintFile);
fprintf(gfxUtils::sDumpPaintFile, "</body></html>");
if (gfxUtils::sDumpPaintingToFile) {
fclose(gfxUtils::sDumpPaintFile);
}
gfxUtils::sDumpPaintFile = NULL;
gPaintCount++;
}
#endif

View File

@ -728,7 +728,8 @@ public:
public:
static void PrintDisplayList(nsDisplayListBuilder* aBuilder,
const nsDisplayList& aList);
const nsDisplayList& aList,
FILE* aFile = stdout);
#endif
};