diff --git a/gfx/layers/LayersLogging.cpp b/gfx/layers/LayersLogging.cpp index 1f57fbb6cbed..407c3509dc96 100644 --- a/gfx/layers/LayersLogging.cpp +++ b/gfx/layers/LayersLogging.cpp @@ -327,17 +327,9 @@ print_stderr(std::stringstream& aStr) // we usually use std::stringstream to build up giant multi-line gobs // of output. So to avoid the truncation we find the newlines and // print the lines individually. - char line[1024]; - while (!aStr.eof()) { - aStr.getline(line, sizeof(line)); - if (!aStr.eof() || strlen(line) > 0) { - printf_stderr("%s\n", line); - } - if (aStr.fail()) { - // line was too long, skip to next newline - aStr.clear(); - aStr.ignore(std::numeric_limits::max(), '\n'); - } + std::string line; + while (std::getline(aStr, line)) { + printf_stderr("%s\n", line.c_str()); } #else printf_stderr("%s", aStr.str().c_str()); diff --git a/gfx/layers/composite/CompositableHost.cpp b/gfx/layers/composite/CompositableHost.cpp index c62669f80bb1..514990326d05 100644 --- a/gfx/layers/composite/CompositableHost.cpp +++ b/gfx/layers/composite/CompositableHost.cpp @@ -223,8 +223,7 @@ CompositableHost::DumpTextureHost(std::stringstream& aStream, TextureHost* aText dSurf->GetSize(), dSurf->Stride(), dSurf->GetFormat()); - // TODO stream surface - gfxUtils::DumpAsDataURI(dt, stderr); + aStream << gfxUtils::GetAsDataURI(dt).get(); } #endif diff --git a/gfx/layers/composite/TextureHost.cpp b/gfx/layers/composite/TextureHost.cpp index b8d5834adbe9..f968e2921d56 100644 --- a/gfx/layers/composite/TextureHost.cpp +++ b/gfx/layers/composite/TextureHost.cpp @@ -27,6 +27,7 @@ #include "SharedSurfaceEGL.h" #include "SharedSurfaceGL.h" #include "../opengl/CompositorOGL.h" +#include "gfxUtils.h" #ifdef MOZ_ENABLE_D3D10_LAYER #include "../d3d11/CompositorD3D11.h" @@ -326,6 +327,18 @@ TextureHost::PrintInfo(std::stringstream& aStream, const char* aPrefix) Unlock(); } AppendToString(aStream, mFlags, " [flags=", "]"); +#ifdef MOZ_DUMP_PAINTING + if (gfxPrefs::LayersDumpTexture()) { + nsAutoCString pfx(aPrefix); + pfx += " "; + + aStream << "\n" << pfx.get() << "Surface: "; + RefPtr dSurf = GetAsSurface(); + if (dSurf) { + aStream << gfxUtils::GetAsDataURI(dSurf).get(); + } + } +#endif } TextureSource::TextureSource() diff --git a/gfx/layers/composite/TiledContentHost.cpp b/gfx/layers/composite/TiledContentHost.cpp index 5556ec3599b4..fe2f5743d3cd 100644 --- a/gfx/layers/composite/TiledContentHost.cpp +++ b/gfx/layers/composite/TiledContentHost.cpp @@ -606,6 +606,14 @@ TiledContentHost::PrintInfo(std::stringstream& aStream, const char* aPrefix) aStream << aPrefix; aStream << nsPrintfCString("TiledContentHost (0x%p)", this).get(); +#ifdef MOZ_DUMP_PAINTING + if (gfxPrefs::LayersDumpTexture()) { + nsAutoCString pfx(aPrefix); + pfx += " "; + + Dump(aStream, pfx.get(), false); + } +#endif } #ifdef MOZ_DUMP_PAINTING @@ -614,24 +622,37 @@ TiledContentHost::Dump(std::stringstream& aStream, const char* aPrefix, bool aDumpHtml) { - TiledLayerBufferComposite::Iterator it = mTiledBuffer.TilesBegin(); - TiledLayerBufferComposite::Iterator stop = mTiledBuffer.TilesEnd(); - if (aDumpHtml) { - aStream << ""; + + for (int32_t y = visibleRect.y; y < visibleRect.y + visibleRect.height;) { + int32_t tileStartY = mTiledBuffer.GetTileStart(y, scaledTileSize.height); + TileHost tileTexture = mTiledBuffer. + GetTile(nsIntPoint(mTiledBuffer.RoundDownToTileEdge(x, scaledTileSize.width), + mTiledBuffer.RoundDownToTileEdge(y, scaledTileSize.height))); + int32_t h = scaledTileSize.height - tileStartY; + if (y + h > visibleRect.y + visibleRect.height) { + h = visibleRect.y + visibleRect.height - y; + } + + aStream << "\n" << aPrefix << "Tile (x=" << + mTiledBuffer.RoundDownToTileEdge(x, scaledTileSize.width) << ", y=" << + mTiledBuffer.RoundDownToTileEdge(y, scaledTileSize.height) << "): "; + if (tileTexture != mTiledBuffer.GetPlaceholderTile()) { + DumpTextureHost(aStream, tileTexture.mTextureHost); + // TODO We should combine the OnWhite/OnBlack here an just output a single image. + } else { + aStream << "empty tile"; + } + y += h; + } + x += w; } } #endif diff --git a/gfx/layers/opengl/GrallocTextureHost.cpp b/gfx/layers/opengl/GrallocTextureHost.cpp index 8de2d4a17e96..20fc6dc55679 100644 --- a/gfx/layers/opengl/GrallocTextureHost.cpp +++ b/gfx/layers/opengl/GrallocTextureHost.cpp @@ -8,6 +8,8 @@ #include "gfx2DGlue.h" #include #include "GrallocImages.h" // for GrallocImage +#include "mozilla/gfx/2D.h" +#include "mozilla/gfx/DataSurfaceHelpers.h" #include "mozilla/layers/GrallocTextureHost.h" #include "mozilla/layers/SharedBufferManagerParent.h" #include "EGLImageHelpers.h" @@ -385,29 +387,45 @@ GrallocTextureHostOGL::GetRenderState() TemporaryRef GrallocTextureHostOGL::GetAsSurface() { - return mTilingTextureSource ? mTilingTextureSource->GetAsSurface() - : nullptr; + if (mTilingTextureSource) { + return mTilingTextureSource->GetAsSurface(); + } else { + android::GraphicBuffer* graphicBuffer = GetGraphicBufferFromDesc(mGrallocHandle).get(); + uint8_t* grallocData; + int32_t rv = graphicBuffer->lock(GRALLOC_USAGE_SW_READ_OFTEN, reinterpret_cast(&grallocData)); + RefPtr grallocTempSurf = + gfx::Factory::CreateWrappingDataSourceSurface(grallocData, + graphicBuffer->getStride() * android::bytesPerPixel(graphicBuffer->getPixelFormat()), + GetSize(), GetFormat()); + RefPtr surf = CreateDataSourceSurfaceByCloning(grallocTempSurf); + + graphicBuffer->unlock(); + + return surf.forget(); + } } TemporaryRef GrallocTextureSourceOGL::GetAsSurface() { - if (!IsValid() || !gl()->MakeCurrent()) { + if (!IsValid()) { return nullptr; } - GLuint tex = GetGLTexture(); - gl()->fActiveTexture(LOCAL_GL_TEXTURE0); - gl()->fBindTexture(GetTextureTarget(), tex); - if (!mEGLImage) { - mEGLImage = EGLImageCreateFromNativeBuffer(gl(), mGraphicBuffer->getNativeBuffer()); + uint8_t* grallocData; + int32_t rv = mGraphicBuffer->lock(GRALLOC_USAGE_SW_READ_OFTEN, reinterpret_cast(&grallocData)); + if (rv) { + return nullptr; } - BindEGLImage(); - RefPtr surf = - IsValid() ? ReadBackSurface(gl(), tex, false, GetFormat()) - : nullptr; + RefPtr grallocTempSurf = + gfx::Factory::CreateWrappingDataSourceSurface(grallocData, + mGraphicBuffer->getStride() * android::bytesPerPixel(mGraphicBuffer->getPixelFormat()), + GetSize(), GetFormat()); + + RefPtr surf = CreateDataSourceSurfaceByCloning(grallocTempSurf); + + mGraphicBuffer->unlock(); - gl()->fActiveTexture(LOCAL_GL_TEXTURE0); return surf.forget(); } diff --git a/gfx/thebes/gfxPrefs.h b/gfx/thebes/gfxPrefs.h index c3c54b6a8ce2..c5bfc9fe7dd3 100644 --- a/gfx/thebes/gfxPrefs.h +++ b/gfx/thebes/gfxPrefs.h @@ -270,6 +270,7 @@ private: DECL_GFX_PREF(Live, "layers.flash-borders", FlashLayerBorders, bool, false); DECL_GFX_PREF(Live, "layers.draw-layer-info", DrawLayerInfo, bool, false); DECL_GFX_PREF(Live, "layers.dump", LayersDump, bool, false); + DECL_GFX_PREF(Live, "layers.dump-texture", LayersDumpTexture, bool, false); // 0 is "no change" for contrast, positive values increase it, negative values // decrease it until we hit mid gray at -1 contrast, after that it gets weird. diff --git a/gfx/thebes/gfxUtils.cpp b/gfx/thebes/gfxUtils.cpp index bb3aa4ed6df6..70253dedfcd1 100644 --- a/gfx/thebes/gfxUtils.cpp +++ b/gfx/thebes/gfxUtils.cpp @@ -1110,14 +1110,15 @@ gfxUtils::GetColorForFrameNumber(uint64_t aFrameNumber) return colors[aFrameNumber % sNumFrameColors]; } -/* static */ nsresult -gfxUtils::EncodeSourceSurface(SourceSurface* aSurface, - const nsACString& aMimeType, - const nsAString& aOutputOptions, - BinaryOrData aBinaryOrData, - FILE* aFile) +static nsresult +EncodeSourceSurfaceInternal(SourceSurface* aSurface, + const nsACString& aMimeType, + const nsAString& aOutputOptions, + gfxUtils::BinaryOrData aBinaryOrData, + FILE* aFile, + nsCString* aStrOut) { - MOZ_ASSERT(aBinaryOrData == eDataURIEncode || aFile, + MOZ_ASSERT(aBinaryOrData == gfxUtils::eDataURIEncode || aFile || aStrOut, "Copying binary encoding to clipboard not currently supported"); const IntSize size = aSurface->GetSize(); @@ -1130,8 +1131,8 @@ gfxUtils::EncodeSourceSurface(SourceSurface* aSurface, if (aSurface->GetFormat() != SurfaceFormat::B8G8R8A8) { // FIXME bug 995807 (B8G8R8X8), bug 831898 (R5G6B5) dataSurface = - CopySurfaceToDataSourceSurfaceWithFormat(aSurface, - SurfaceFormat::B8G8R8A8); + gfxUtils::CopySurfaceToDataSourceSurfaceWithFormat(aSurface, + SurfaceFormat::B8G8R8A8); } else { dataSurface = aSurface->GetDataSurface(); } @@ -1214,7 +1215,7 @@ gfxUtils::EncodeSourceSurface(SourceSurface* aSurface, NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_TRUE(!imgData.empty(), NS_ERROR_FAILURE); - if (aBinaryOrData == eBinaryEncode) { + if (aBinaryOrData == gfxUtils::eBinaryEncode) { if (aFile) { fwrite(imgData.begin(), 1, imgSize, aFile); } @@ -1247,6 +1248,8 @@ gfxUtils::EncodeSourceSurface(SourceSurface* aSurface, } #endif fprintf(aFile, "%s", string.BeginReading()); + } else if (aStrOut) { + *aStrOut = string; } else { nsCOMPtr clipboard(do_GetService("@mozilla.org/widget/clipboardhelper;1", &rv)); if (clipboard) { @@ -1256,6 +1259,27 @@ gfxUtils::EncodeSourceSurface(SourceSurface* aSurface, return NS_OK; } +static nsCString +EncodeSourceSurfaceAsPNGURI(SourceSurface* aSurface) +{ + nsCString string; + EncodeSourceSurfaceInternal(aSurface, NS_LITERAL_CSTRING("image/png"), + EmptyString(), gfxUtils::eDataURIEncode, + nullptr, &string); + return string; +} + +/* static */ nsresult +gfxUtils::EncodeSourceSurface(SourceSurface* aSurface, + const nsACString& aMimeType, + const nsAString& aOutputOptions, + BinaryOrData aBinaryOrData, + FILE* aFile) +{ + return EncodeSourceSurfaceInternal(aSurface, aMimeType, aOutputOptions, + aBinaryOrData, aFile, nullptr); +} + /* static */ void gfxUtils::WriteAsPNG(SourceSurface* aSurface, const nsAString& aFile) { @@ -1337,6 +1361,12 @@ gfxUtils::DumpAsDataURI(SourceSurface* aSurface, FILE* aFile) EmptyString(), eDataURIEncode, aFile); } +/* static */ nsCString +gfxUtils::GetAsDataURI(SourceSurface* aSurface) +{ + return EncodeSourceSurfaceAsPNGURI(aSurface); +} + /* static */ void gfxUtils::DumpAsDataURI(DrawTarget* aDT, FILE* aFile) { @@ -1348,6 +1378,18 @@ gfxUtils::DumpAsDataURI(DrawTarget* aDT, FILE* aFile) } } +/* static */ nsCString +gfxUtils::GetAsDataURI(DrawTarget* aDT) +{ + RefPtr surface = aDT->Snapshot(); + if (surface) { + return EncodeSourceSurfaceAsPNGURI(surface); + } else { + NS_WARNING("Failed to get surface!"); + return nsCString(""); + } +} + /* static */ void gfxUtils::CopyAsDataURI(SourceSurface* aSurface) { diff --git a/gfx/thebes/gfxUtils.h b/gfx/thebes/gfxUtils.h index e03152a86bc8..fae9de3b1316 100644 --- a/gfx/thebes/gfxUtils.h +++ b/gfx/thebes/gfxUtils.h @@ -281,6 +281,8 @@ public: static inline void DumpAsDataURI(DrawTarget* aDT) { DumpAsDataURI(aDT, stdout); } + static nsCString GetAsDataURI(SourceSurface* aSourceSurface); + static nsCString GetAsDataURI(DrawTarget* aDT); /** * Copy to the clipboard as a PNG encoded Data URL. diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index fe5871e64e65..6974671d762b 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -3890,6 +3890,10 @@ pref("layers.acceleration.force-enabled", false); pref("layers.acceleration.draw-fps", false); pref("layers.dump", false); +#ifdef MOZ_DUMP_PAINTING +// If we're dumping layers, also dump the texture data +pref("layers.dump-texture", false); +#endif pref("layers.draw-borders", false); pref("layers.draw-tile-borders", false); pref("layers.draw-bigimage-borders", false);