Bug 738189: Add memory reporting for Azure VRAM usage. r=jrmuizel
authorBas Schouten <bschouten@mozilla.com>
Wed, 20 Jun 2012 23:41:16 +0200
changeset 97184 e7b9f828d4c1e233eed96a3ca898992a77abddc5
parent 97183 b35294da2c4bc65d3838a3108c616a5ef93c8e2e
child 97185 f328118d86b910aa5bb06571a2a55f949aaf7058
push id10921
push userbschouten@mozilla.com
push dateWed, 20 Jun 2012 21:43:39 +0000
treeherdermozilla-inbound@f328118d86b9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjrmuizel
bugs738189
milestone16.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 738189: Add memory reporting for Azure VRAM usage. r=jrmuizel
gfx/2d/2D.h
gfx/2d/DrawTargetD2D.cpp
gfx/2d/DrawTargetD2D.h
gfx/2d/Factory.cpp
gfx/2d/SourceSurfaceD2D.cpp
gfx/2d/SourceSurfaceD2D.h
gfx/2d/SourceSurfaceD2DTarget.cpp
gfx/2d/SourceSurfaceD2DTarget.h
gfx/thebes/gfxWindowsPlatform.cpp
--- a/gfx/2d/2D.h
+++ b/gfx/2d/2D.h
@@ -847,16 +847,19 @@ public:
                                          SurfaceFormat aFormat);
 
   static void SetDirect3D10Device(ID3D10Device1 *aDevice);
   static ID3D10Device1 *GetDirect3D10Device();
 
   static TemporaryRef<GlyphRenderingOptions>
     CreateDWriteGlyphRenderingOptions(IDWriteRenderingParams *aParams);
 
+  static uint64_t GetD2DVRAMUsageDrawTarget();
+  static uint64_t GetD2DVRAMUsageSourceSurface();
+
 private:
   static ID3D10Device1 *mD3D10Device;
 #endif
 };
 
 }
 }
 
--- a/gfx/2d/DrawTargetD2D.cpp
+++ b/gfx/2d/DrawTargetD2D.cpp
@@ -50,16 +50,18 @@ namespace gfx {
 
 struct Vertex {
   float x;
   float y;
 };
 
 ID2D1Factory *DrawTargetD2D::mFactory;
 IDWriteFactory *DrawTargetD2D::mDWriteFactory;
+uint64_t DrawTargetD2D::mVRAMUsageDT;
+uint64_t DrawTargetD2D::mVRAMUsageSS;
 
 // Helper class to restore surface contents that was clipped out but may have
 // been altered by a drawing call.
 class AutoSaveRestoreClippedOut
 {
 public:
   AutoSaveRestoreClippedOut(DrawTargetD2D *aDT)
     : mDT(aDT)
@@ -156,30 +158,34 @@ DrawTargetD2D::DrawTargetD2D()
 }
 
 DrawTargetD2D::~DrawTargetD2D()
 {
   if (mRT) {  
     PopAllClips();
 
     mRT->EndDraw();
+
+    mVRAMUsageDT -= GetByteSize();
   }
   if (mTempRT) {
     mTempRT->EndDraw();
+
+    mVRAMUsageDT -= GetByteSize();
   }
 
   if (mSnapshot) {
     // We may hold the only reference. MarkIndependent will clear mSnapshot;
-	// keep the snapshot object alive so it doesn't get destroyed while
-	// MarkIndependent is running.
+    // keep the snapshot object alive so it doesn't get destroyed while
+    // MarkIndependent is running.
     RefPtr<SourceSurfaceD2DTarget> deathGrip = mSnapshot;
-	// mSnapshot can be treated as independent of this DrawTarget since we know
-	// this DrawTarget won't change again.
-	deathGrip->MarkIndependent();
-	// mSnapshot will be cleared now.
+    // mSnapshot can be treated as independent of this DrawTarget since we know
+    // this DrawTarget won't change again.
+    deathGrip->MarkIndependent();
+    // mSnapshot will be cleared now.
   }
 
   // Targets depending on us can break that dependency, since we're obviously not going to
   // be modified in the future.
   for (TargetSet::iterator iter = mDependentTargets.begin();
        iter != mDependentTargets.end(); iter++) {
     (*iter)->mDependingOnTargets.erase(this);
   }
@@ -1269,16 +1275,22 @@ DrawTargetD2D::InitD3D10Data()
   }
 
   return true;
 }
 
 /*
  * Private helpers
  */
+uint32_t
+DrawTargetD2D::GetByteSize() const
+{
+  return mSize.width * mSize.height * BytesPerPixel(mFormat);
+}
+
 bool
 DrawTargetD2D::InitD2DRenderTarget()
 {
   if (!factory()) {
     return false;
   }
 
   mRT = CreateRTForTexture(mTexture, mFormat);
@@ -1288,16 +1300,18 @@ DrawTargetD2D::InitD2DRenderTarget()
   }
 
   mRT->BeginDraw();
 
   if (mFormat == FORMAT_B8G8R8X8) {
     mRT->SetTextAntialiasMode(D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE);
   }
 
+  mVRAMUsageDT += GetByteSize();
+
   return InitD3D10Data();
 }
 
 void
 DrawTargetD2D::PrepareForDrawing(ID2D1RenderTarget *aRT)
 {
   if (!mClipsArePushed || aRT == mTempRT) {
     if (mPushedClips.size()) {
@@ -1436,16 +1450,18 @@ DrawTargetD2D::GetRTForOperation(Composi
   }
 
   mTempRT = CreateRTForTexture(mTempTexture, FORMAT_B8G8R8A8);
 
   if (!mTempRT) {
     return mRT;
   }
 
+  mVRAMUsageDT += GetByteSize();
+
   mTempRT->BeginDraw();
 
   mTempRT->Clear(D2D1::ColorF(0, 0));
 
   return mTempRT;
 }
 
 /* This function blends back the content of a drawing operation (drawn to an
--- a/gfx/2d/DrawTargetD2D.h
+++ b/gfx/2d/DrawTargetD2D.h
@@ -116,26 +116,31 @@ public:
                         uint32_t aNumStops,
                         ExtendMode aExtendMode = EXTEND_CLAMP) const;
 
   virtual void *GetNativeSurface(NativeSurfaceType aType);
 
   bool Init(const IntSize &aSize, SurfaceFormat aFormat);
   bool Init(ID3D10Texture2D *aTexture, SurfaceFormat aFormat);
   bool InitD3D10Data();
+  uint32_t GetByteSize() const;
 
   static ID2D1Factory *factory();
   static TemporaryRef<ID2D1StrokeStyle> CreateStrokeStyleForOptions(const StrokeOptions &aStrokeOptions);
   static IDWriteFactory *GetDWriteFactory();
 
   operator std::string() const {
     std::stringstream stream;
     stream << "DrawTargetD2D(" << this << ")";
     return stream.str();
   }
+
+  static uint64_t mVRAMUsageDT;
+  static uint64_t mVRAMUsageSS;
+
 private:
   friend class AutoSaveRestoreClippedOut;
   friend class SourceSurfaceD2DTarget;
 
 #ifdef _MSC_VER
   typedef stdext::hash_set<DrawTargetD2D*> TargetSet;
 #else
   typedef std::unordered_set<DrawTargetD2D*> TargetSet;
--- a/gfx/2d/Factory.cpp
+++ b/gfx/2d/Factory.cpp
@@ -376,10 +376,22 @@ Factory::CreateWrappingDataSourceSurface
 
   if (newSurf->InitWrappingData(aData, aSize, aStride, aFormat, false)) {
     return newSurf;
   }
 
   return NULL;
 }
 
+uint64_t
+Factory::GetD2DVRAMUsageDrawTarget()
+{
+  return DrawTargetD2D::mVRAMUsageDT;
+}
+
+uint64_t
+Factory::GetD2DVRAMUsageSourceSurface()
+{
+  return DrawTargetD2D::mVRAMUsageSS;
+}
+
 }
 }
--- a/gfx/2d/SourceSurfaceD2D.cpp
+++ b/gfx/2d/SourceSurfaceD2D.cpp
@@ -1,25 +1,30 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * 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 "SourceSurfaceD2D.h"
+#include "DrawTargetD2D.h"
 #include "Logging.h"
+#include "Tools.h"
 
 namespace mozilla {
 namespace gfx {
 
 SourceSurfaceD2D::SourceSurfaceD2D()
 {
 }
 
 SourceSurfaceD2D::~SourceSurfaceD2D()
 {
+  if (mBitmap) {
+    DrawTargetD2D::mVRAMUsageSS -= GetByteSize();
+  }
 }
 
 IntSize
 SourceSurfaceD2D::GetSize() const
 {
   return mSize;
 }
 
@@ -57,16 +62,18 @@ SourceSurfaceD2D::InitFromData(unsigned 
     D2D1::BitmapProperties(D2D1::PixelFormat(DXGIFormat(aFormat), AlphaMode(aFormat)));
   hr = aRT->CreateBitmap(D2DIntSize(aSize), aData, aStride, props, byRef(mBitmap));
 
   if (FAILED(hr)) {
     gfxWarning() << "Failed to create D2D Bitmap for data. Code: " << hr;
     return false;
   }
 
+  DrawTargetD2D::mVRAMUsageSS += GetByteSize();
+
   return true;
 }
 
 bool
 SourceSurfaceD2D::InitFromTexture(ID3D10Texture2D *aTexture,
                                   SurfaceFormat aFormat,
                                   ID2D1RenderTarget *aRT)
 {
@@ -91,13 +98,21 @@ SourceSurfaceD2D::InitFromTexture(ID3D10
     D2D1::BitmapProperties(D2D1::PixelFormat(DXGIFormat(aFormat), AlphaMode(aFormat)));
   hr = aRT->CreateSharedBitmap(IID_IDXGISurface, surf, &props, byRef(mBitmap));
 
   if (FAILED(hr)) {
     gfxWarning() << "Failed to create SharedBitmap. Code: " << hr;
     return false;
   }
 
+  DrawTargetD2D::mVRAMUsageSS += GetByteSize();
+
   return true;
 }
 
+uint32_t
+SourceSurfaceD2D::GetByteSize() const
+{
+  return mSize.width * mSize.height * BytesPerPixel(mFormat);
+}
+
 }
 }
--- a/gfx/2d/SourceSurfaceD2D.h
+++ b/gfx/2d/SourceSurfaceD2D.h
@@ -33,16 +33,18 @@ public:
                     ID2D1RenderTarget *aRT);
   bool InitFromTexture(ID3D10Texture2D *aTexture,
                        SurfaceFormat aFormat,
                        ID2D1RenderTarget *aRT);
 
 private:
   friend class DrawTargetD2D;
 
+  uint32_t GetByteSize() const;
+
   RefPtr<ID2D1Bitmap> mBitmap;
   SurfaceFormat mFormat;
   IntSize mSize;
 };
 
 }
 }
 
--- a/gfx/2d/SourceSurfaceD2DTarget.cpp
+++ b/gfx/2d/SourceSurfaceD2DTarget.cpp
@@ -1,36 +1,43 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * 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 "SourceSurfaceD2DTarget.h"
 #include "Logging.h"
 #include "DrawTargetD2D.h"
+#include "Tools.h"
 
 #include <algorithm>
 
 namespace mozilla {
 namespace gfx {
 
 SourceSurfaceD2DTarget::SourceSurfaceD2DTarget(DrawTargetD2D* aDrawTarget,
                                                ID3D10Texture2D* aTexture,
                                                SurfaceFormat aFormat)
   : mDrawTarget(aDrawTarget)
   , mTexture(aTexture)
   , mFormat(aFormat)
+  , mOwnsCopy(false)
 {
 }
 
 SourceSurfaceD2DTarget::~SourceSurfaceD2DTarget()
 {
   // We don't need to do anything special here to notify our mDrawTarget. It must
   // already have cleared its mSnapshot field, otherwise this object would
   // be kept alive.
+  if (mOwnsCopy) {
+    IntSize size = GetSize();
+
+    DrawTargetD2D::mVRAMUsageSS -= size.width * size.height * BytesPerPixel(mFormat);
+  }
 }
 
 IntSize
 SourceSurfaceD2DTarget::GetSize() const
 {
   D3D10_TEXTURE2D_DESC desc;
   mTexture->GetDesc(&desc);
 
@@ -93,16 +100,19 @@ SourceSurfaceD2DTarget::DrawTargetWillCh
   mTexture->GetDesc(&desc);
 
   // Get a copy of the surface data so the content at snapshot time was saved.
   Factory::GetDirect3D10Device()->CreateTexture2D(&desc, NULL, byRef(mTexture));
   Factory::GetDirect3D10Device()->CopyResource(mTexture, oldTexture);
 
   mBitmap = NULL;
 
+  DrawTargetD2D::mVRAMUsageSS += desc.Width * desc.Height * BytesPerPixel(mFormat);
+  mOwnsCopy = true;
+
   // We now no longer depend on the source surface content remaining the same.
   MarkIndependent();
 }
 
 ID2D1Bitmap*
 SourceSurfaceD2DTarget::GetBitmap(ID2D1RenderTarget *aRT)
 {
   if (mBitmap) {
--- a/gfx/2d/SourceSurfaceD2DTarget.h
+++ b/gfx/2d/SourceSurfaceD2DTarget.h
@@ -47,16 +47,17 @@ private:
   RefPtr<ID2D1Bitmap> mBitmap;
   // Non-null if this is a "lazy copy" of the given draw target.
   // Null if we've made a copy. The target is not kept alive, otherwise we'd
   // have leaks since it might keep us alive. If the target is destroyed, it
   // will notify us.
   DrawTargetD2D* mDrawTarget;
   mutable RefPtr<ID3D10Texture2D> mTexture;
   SurfaceFormat mFormat;
+  bool mOwnsCopy;
 };
 
 class DataSourceSurfaceD2DTarget : public DataSourceSurface
 {
 public:
   DataSourceSurfaceD2DTarget();
   ~DataSourceSurfaceD2DTarget();
 
--- a/gfx/thebes/gfxWindowsPlatform.cpp
+++ b/gfx/thebes/gfxWindowsPlatform.cpp
@@ -113,16 +113,45 @@ NS_MEMORY_REPORTER_IMPLEMENT(
     "gfx-d2d-surfacevram",
     KIND_OTHER,
     UNITS_BYTES,
     GetD2DSurfaceVramUsage,
     "Video memory used by D2D surfaces.")
 
 #endif
 
+namespace
+{
+
+PRInt64 GetD2DVRAMUsageDrawTarget() {
+    return mozilla::gfx::Factory::GetD2DVRAMUsageDrawTarget();
+}
+
+PRInt64 GetD2DVRAMUsageSourceSurface() {
+    return mozilla::gfx::Factory::GetD2DVRAMUsageSourceSurface();
+}
+
+} // anonymous namespace
+
+NS_MEMORY_REPORTER_IMPLEMENT(
+    D2DVRAMDT,
+    "gfx-d2d-vram-drawtarget",
+    KIND_OTHER,
+    UNITS_BYTES,
+    GetD2DVRAMUsageDrawTarget,
+    "Video memory used by D2D DrawTargets.")
+
+NS_MEMORY_REPORTER_IMPLEMENT(
+    D2DVRAMSS,
+    "gfx-d2d-vram-sourcesurface",
+    KIND_OTHER,
+    UNITS_BYTES,
+    GetD2DVRAMUsageSourceSurface,
+    "Video memory used by D2D SourceSurfaces.")
+
 #define GFX_USE_CLEARTYPE_ALWAYS "gfx.font_rendering.cleartype.always_use_for_content"
 #define GFX_DOWNLOADABLE_FONTS_USE_CLEARTYPE "gfx.font_rendering.cleartype.use_for_downloadable_fonts"
 
 #define GFX_CLEARTYPE_PARAMS           "gfx.font_rendering.cleartype_params."
 #define GFX_CLEARTYPE_PARAMS_GAMMA     "gfx.font_rendering.cleartype_params.gamma"
 #define GFX_CLEARTYPE_PARAMS_CONTRAST  "gfx.font_rendering.cleartype_params.enhanced_contrast"
 #define GFX_CLEARTYPE_PARAMS_LEVEL     "gfx.font_rendering.cleartype_params.cleartype_level"
 #define GFX_CLEARTYPE_PARAMS_STRUCTURE "gfx.font_rendering.cleartype_params.pixel_structure"
@@ -325,16 +354,18 @@ gfxWindowsPlatform::gfxWindowsPlatform()
 
     mScreenDC = GetDC(NULL);
 
 #ifdef CAIRO_HAS_D2D_SURFACE
     NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(D2DCache));
     NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(D2DVram));
     mD2DDevice = nsnull;
 #endif
+    NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(D2DVRAMDT));
+    NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(D2DVRAMSS));
 
     UpdateRenderMode();
 
 #ifdef ENABLE_GPU_MEM_REPORTER
     mGPUAdapterMultiReporter = new GPUAdapterMultiReporter();
     NS_RegisterMemoryMultiReporter(mGPUAdapterMultiReporter);
 #endif
 }