Bug 1105834 - Part 2: Add layers.dump-texture feature. r=mstange
☠☠ backed out by 7d799447add8 ☠ ☠
authorBenoit Girard <b56girard@gmail.com>
Fri, 28 Nov 2014 17:41:47 -0500
changeset 244749 47ba9f1d4762e19b8600763b2f850f0128047ff7
parent 244748 f0226c3be05138baec8ae610f07182d189d1a49f
child 244750 7aca6512211501c9ecdc69811f2895608ab083f0
push id4489
push userraliiev@mozilla.com
push dateMon, 23 Feb 2015 15:17:55 +0000
treeherdermozilla-beta@fd7c3dc24146 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmstange
bugs1105834
milestone37.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1105834 - Part 2: Add layers.dump-texture feature. r=mstange
gfx/layers/LayersLogging.cpp
gfx/layers/composite/CompositableHost.cpp
gfx/layers/composite/TextureHost.cpp
gfx/layers/composite/TiledContentHost.cpp
gfx/layers/opengl/GrallocTextureHost.cpp
gfx/thebes/gfxPrefs.h
gfx/thebes/gfxUtils.cpp
gfx/thebes/gfxUtils.h
modules/libpref/init/all.js
--- a/gfx/layers/LayersLogging.cpp
+++ b/gfx/layers/LayersLogging.cpp
@@ -322,27 +322,19 @@ AppendToString(std::stringstream& aStrea
 void
 print_stderr(std::stringstream& aStr)
 {
 #if defined(ANDROID)
   // On Android logcat output is truncated to 1024 chars per line, and
   // 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<std::streamsize>::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());
 #endif
 }
 
 void
 fprint_stderr(FILE* aFile, std::stringstream& aStr)
--- a/gfx/layers/composite/CompositableHost.cpp
+++ b/gfx/layers/composite/CompositableHost.cpp
@@ -218,18 +218,17 @@ CompositableHost::DumpTextureHost(std::s
   if (!dSurf) {
     return;
   }
   gfxPlatform *platform = gfxPlatform::GetPlatform();
   RefPtr<gfx::DrawTarget> dt = platform->CreateDrawTargetForData(dSurf->GetData(),
                                                                  dSurf->GetSize(),
                                                                  dSurf->Stride(),
                                                                  dSurf->GetFormat());
-  // TODO stream surface
-  gfxUtils::DumpAsDataURI(dt, stderr);
+  aStream << gfxUtils::GetAsDataURI(dt).get();
 }
 #endif
 
 namespace CompositableMap {
 
 typedef std::map<uint64_t, PCompositableParent*> CompositableMap_t;
 static CompositableMap_t* sCompositableMap = nullptr;
 bool IsCreated() {
--- a/gfx/layers/composite/TextureHost.cpp
+++ b/gfx/layers/composite/TextureHost.cpp
@@ -22,16 +22,17 @@
 #include "nsPrintfCString.h"            // for nsPrintfCString
 #include "mozilla/layers/PTextureParent.h"
 #include "mozilla/unused.h"
 #include <limits>
 #include "SharedSurface.h"
 #include "SharedSurfaceEGL.h"
 #include "SharedSurfaceGL.h"
 #include "../opengl/CompositorOGL.h"
+#include "gfxUtils.h"
 
 #ifdef MOZ_ENABLE_D3D10_LAYER
 #include "../d3d11/CompositorD3D11.h"
 #endif
 
 #ifdef MOZ_WIDGET_GONK
 #include "../opengl/GrallocTextureClient.h"
 #include "../opengl/GrallocTextureHost.h"
@@ -321,16 +322,28 @@ TextureHost::PrintInfo(std::stringstream
   // Note: the TextureHost needs to be locked before it is safe to call
   //       GetSize() and GetFormat() on it.
   if (Lock()) {
     AppendToString(aStream, GetSize(), " [size=", "]");
     AppendToString(aStream, GetFormat(), " [format=", "]");
     Unlock();
   }
   AppendToString(aStream, mFlags, " [flags=", "]");
+#ifdef MOZ_DUMP_PAINTING
+  if (gfxPrefs::LayersDumpTexture()) {
+    nsAutoCString pfx(aPrefix);
+    pfx += "  ";
+
+    aStream << "\n" << pfx.get() << "Surface: ";
+    RefPtr<gfx::DataSourceSurface> dSurf = GetAsSurface();
+    if (dSurf) {
+      aStream << gfxUtils::GetAsDataURI(dSurf).get();
+    }
+  }
+#endif
 }
 
 TextureSource::TextureSource()
 : mCompositableCount(0)
 {
     MOZ_COUNT_CTOR(TextureSource);
 }
 
--- a/gfx/layers/composite/TiledContentHost.cpp
+++ b/gfx/layers/composite/TiledContentHost.cpp
@@ -601,40 +601,61 @@ TiledContentHost::RenderLayerBuffer(Tile
 }
 
 void
 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
 void
 TiledContentHost::Dump(std::stringstream& aStream,
                        const char* aPrefix,
                        bool aDumpHtml)
 {
-  TiledLayerBufferComposite::Iterator it = mTiledBuffer.TilesBegin();
-  TiledLayerBufferComposite::Iterator stop = mTiledBuffer.TilesEnd();
-  if (aDumpHtml) {
-    aStream << "<ul>";
-  }
-  for (;it != stop; ++it) {
-    aStream << aPrefix;
-    aStream << (aDumpHtml ? "<li> <a href=" : "Tile ");
-    if (it->IsPlaceholderTile()) {
-      aStream << "empty tile";
-    } else {
-      DumpTextureHost(aStream, it->mTextureHost);
-      DumpTextureHost(aStream, it->mTextureHostOnWhite);
+  nsIntRect visibleRect = mTiledBuffer.GetValidRegion().GetBounds();
+  gfx::IntSize scaledTileSize = mTiledBuffer.GetScaledTileSize();
+  for (int32_t x = visibleRect.x; x < visibleRect.x + visibleRect.width;) {
+    int32_t tileStartX = mTiledBuffer.GetTileStart(x, scaledTileSize.width);
+    int32_t w = scaledTileSize.width - tileStartX;
+    if (x + w > visibleRect.x + visibleRect.width) {
+      w = visibleRect.x + visibleRect.width - x;
     }
-    aStream << (aDumpHtml ? " >Tile</a></li>" : " ");
-  }
-  if (aDumpHtml) {
-    aStream << "</ul>";
+
+    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
 
 } // namespace
 } // namespace
--- a/gfx/layers/opengl/GrallocTextureHost.cpp
+++ b/gfx/layers/opengl/GrallocTextureHost.cpp
@@ -3,16 +3,18 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "base/process.h"
 #include "GLContext.h"
 #include "gfx2DGlue.h"
 #include <ui/GraphicBuffer.h>
 #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"
 #include "GLReadTexImageHelper.h"
 
 namespace mozilla {
 namespace layers {
 
@@ -380,39 +382,55 @@ GrallocTextureHostOGL::GetRenderState()
                             this);
   }
 
   return LayerRenderState();
 }
 
 TemporaryRef<gfx::DataSourceSurface>
 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<void**>(&grallocData));
+    RefPtr<gfx::DataSourceSurface> grallocTempSurf =
+      gfx::Factory::CreateWrappingDataSourceSurface(grallocData,
+                                                    graphicBuffer->getStride() * android::bytesPerPixel(graphicBuffer->getPixelFormat()),
+                                                    GetSize(), GetFormat());
+    RefPtr<gfx::DataSourceSurface> surf = CreateDataSourceSurfaceByCloning(grallocTempSurf);
+
+    graphicBuffer->unlock();
+
+    return surf.forget();
+  }
 }
 
 TemporaryRef<gfx::DataSourceSurface>
 GrallocTextureSourceOGL::GetAsSurface() {
-  if (!IsValid() || !gl()->MakeCurrent()) {
+  if (!IsValid()) {
+    return nullptr;
+  }
+
+  uint8_t* grallocData;
+  int32_t rv = mGraphicBuffer->lock(GRALLOC_USAGE_SW_READ_OFTEN, reinterpret_cast<void**>(&grallocData));
+  if (rv) {
     return nullptr;
   }
 
-  GLuint tex = GetGLTexture();
-  gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
-  gl()->fBindTexture(GetTextureTarget(), tex);
-  if (!mEGLImage) {
-    mEGLImage = EGLImageCreateFromNativeBuffer(gl(), mGraphicBuffer->getNativeBuffer());
-  }
-  BindEGLImage();
+  RefPtr<gfx::DataSourceSurface> grallocTempSurf =
+    Factory::CreateWrappingDataSourceSurface(grallocData,
+                                             mGraphicBuffer->getStride() * android::bytesPerPixel(mGraphicBuffer->getPixelFormat()),
+                                             GetSize(), GetFormat());
 
-  RefPtr<gfx::DataSourceSurface> surf =
-    IsValid() ? ReadBackSurface(gl(), tex, false, GetFormat())
-              : nullptr;
+  RefPtr<gfx::DataSourceSurface> surf = CreateDataSourceSurfaceByCloning(grallocTempSurf);
 
-  gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
+  mGraphicBuffer->unlock();
+
   return surf.forget();
 }
 
 GLuint
 GrallocTextureSourceOGL::GetGLTexture()
 {
   return mTexture;
 }
--- a/gfx/thebes/gfxPrefs.h
+++ b/gfx/thebes/gfxPrefs.h
@@ -265,16 +265,17 @@ private:
   DECL_GFX_PREF(Once, "layers.componentalpha.enabled",         ComponentAlphaEnabled, bool, true);
 #endif
   DECL_GFX_PREF(Live, "layers.draw-bigimage-borders",          DrawBigImageBorders, bool, false);
   DECL_GFX_PREF(Live, "layers.draw-borders",                   DrawLayerBorders, bool, false);
   DECL_GFX_PREF(Live, "layers.draw-tile-borders",              DrawTileBorders, bool, false);
   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.
   DECL_GFX_PREF(Live, "layers.effect.contrast",                LayersEffectContrast, float, 0.0f);
   DECL_GFX_PREF(Live, "layers.effect.grayscale",               LayersEffectGrayscale, bool, false);
   DECL_GFX_PREF(Live, "layers.effect.invert",                  LayersEffectInvert, bool, false);
 
   DECL_GFX_PREF(Once, "layers.enable-tiles",                   LayersTilesEnabledDoNotUseDirectly, bool, false);
--- a/gfx/thebes/gfxUtils.cpp
+++ b/gfx/thebes/gfxUtils.cpp
@@ -1105,38 +1105,39 @@ gfxUtils::GetColorForFrameNumber(uint64_
         colors[i++] = gfx::Color::FromABGR(0xff999999);
         MOZ_ASSERT(i == sNumFrameColors);
         initialized = true;
     }
 
     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();
   if (size.IsEmpty()) {
     return NS_ERROR_INVALID_ARG;
   }
   const Size floatSize(size.width, size.height);
 
   RefPtr<DataSourceSurface> dataSurface;
   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();
   }
   if (!dataSurface) {
     return NS_ERROR_FAILURE;
   }
 
   DataSourceSurface::MappedSurface map;
@@ -1209,17 +1210,17 @@ gfxUtils::EncodeSourceSurface(SourceSurf
       if (!imgData.resizeUninitialized(bufSize)) {
         return NS_ERROR_OUT_OF_MEMORY;
       }
     }
   }
   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);
     }
     return NS_OK;
   }
 
   // base 64, result will be null-terminated
   nsCString encodedImg;
@@ -1242,25 +1243,48 @@ gfxUtils::EncodeSourceSurface(SourceSurf
         if (len <= 140)
           break;
         len -= 140;
         cStr += 140;
       }
     }
 #endif
     fprintf(aFile, "%s", string.BeginReading());
+  } else if (aStrOut) {
+    *aStrOut = string;
   } else {
     nsCOMPtr<nsIClipboardHelper> clipboard(do_GetService("@mozilla.org/widget/clipboardhelper;1", &rv));
     if (clipboard) {
       clipboard->CopyString(NS_ConvertASCIItoUTF16(string), nullptr);
     }
   }
   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)
 {
   WriteAsPNG(aSurface, NS_ConvertUTF16toUTF8(aFile).get());
 }
 
 /* static */ void
 gfxUtils::WriteAsPNG(SourceSurface* aSurface, const char* aFile)
@@ -1332,27 +1356,45 @@ gfxUtils::WriteAsPNG(nsIPresShell* aShel
 
 /* static */ void
 gfxUtils::DumpAsDataURI(SourceSurface* aSurface, FILE* aFile)
 {
   EncodeSourceSurface(aSurface, NS_LITERAL_CSTRING("image/png"),
                       EmptyString(), eDataURIEncode, aFile);
 }
 
+/* static */ nsCString
+gfxUtils::GetAsDataURI(SourceSurface* aSurface)
+{
+  return EncodeSourceSurfaceAsPNGURI(aSurface);
+}
+
 /* static */ void
 gfxUtils::DumpAsDataURI(DrawTarget* aDT, FILE* aFile)
 {
   RefPtr<SourceSurface> surface = aDT->Snapshot();
   if (surface) {
     DumpAsDataURI(surface, aFile);
   } else {
     NS_WARNING("Failed to get surface!");
   }
 }
 
+/* static */ nsCString
+gfxUtils::GetAsDataURI(DrawTarget* aDT)
+{
+  RefPtr<SourceSurface> surface = aDT->Snapshot();
+  if (surface) {
+    return EncodeSourceSurfaceAsPNGURI(surface);
+  } else {
+    NS_WARNING("Failed to get surface!");
+    return nsCString("");
+  }
+}
+
 /* static */ void
 gfxUtils::CopyAsDataURI(SourceSurface* aSurface)
 {
   EncodeSourceSurface(aSurface, NS_LITERAL_CSTRING("image/png"),
                       EmptyString(), eDataURIEncode, nullptr);
 }
 
 /* static */ void
--- a/gfx/thebes/gfxUtils.h
+++ b/gfx/thebes/gfxUtils.h
@@ -276,16 +276,18 @@ public:
     static void DumpAsDataURI(SourceSurface* aSourceSurface, FILE* aFile);
     static inline void DumpAsDataURI(SourceSurface* aSourceSurface) {
         DumpAsDataURI(aSourceSurface, stdout);
     }
     static void DumpAsDataURI(DrawTarget* aDT, FILE* aFile);
     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.
      */
     static void CopyAsDataURI(SourceSurface* aSourceSurface);
     static void CopyAsDataURI(DrawTarget* aDT);
 
 #ifdef MOZ_DUMP_PAINTING
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -3885,16 +3885,20 @@ pref("layers.bench.enabled", false);
 pref("layers.acceleration.force-enabled", true);
 #else
 pref("layers.acceleration.force-enabled", false);
 #endif
 
 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);
 pref("layers.frame-counter", false);
 pref("layers.enable-tiles", false);
 pref("layers.tiled-drawtarget.enabled", false);
 pref("layers.low-precision-buffer", false);
 pref("layers.progressive-paint", false);