mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-08 19:04:45 +00:00
Bug 700240 - Print display lists to a file. r=roc,bjacob
This commit is contained in:
parent
63d5bd1d56
commit
72f481f48f
@ -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*)¤tPackAlignment);
|
||||
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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -1345,6 +1345,11 @@ protected:
|
||||
bool mDirty;
|
||||
};
|
||||
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
void WriteSnapshotToDumpFile(Layer* aLayer, gfxASurface* aSurf);
|
||||
void WriteSnapshotToDumpFile(LayerManager* aManager, gfxASurface* aSurf);
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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[] = {
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 ********/
|
||||
|
@ -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
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -728,7 +728,8 @@ public:
|
||||
public:
|
||||
|
||||
static void PrintDisplayList(nsDisplayListBuilder* aBuilder,
|
||||
const nsDisplayList& aList);
|
||||
const nsDisplayList& aList,
|
||||
FILE* aFile = stdout);
|
||||
|
||||
#endif
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user