Bug 710594 - Adapt WebGL about:memory reporters to the new memory reporting API. r=njn,bjacob.
authorAndrew Quartey <andrew.quartey@gmail.com>
Sun, 19 Feb 2012 19:58:08 -0800
changeset 87252 ac02ca06e1273e3c0d4e73589fd6655767d3fc26
parent 87251 c714722a7aad88ec64b96c59adc22de4608bd6d5
child 87253 f07a6060cc5a15f7435d1429dad813baf8992687
push id22103
push userbmo@edmorley.co.uk
push dateTue, 21 Feb 2012 12:01:45 +0000
treeherdermozilla-central@4038ffaa5d82 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnjn, bjacob
bugs710594
milestone13.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 710594 - Adapt WebGL about:memory reporters to the new memory reporting API. r=njn,bjacob.
content/canvas/src/Makefile.in
content/canvas/src/WebGLContext.cpp
content/canvas/src/WebGLContext.h
content/canvas/src/WebGLContextReporter.cpp
--- a/content/canvas/src/Makefile.in
+++ b/content/canvas/src/Makefile.in
@@ -63,16 +63,17 @@ CPPSRCS	= \
 	$(NULL)
 
 ifdef MOZ_WEBGL
 
 CPPSRCS += \
 	WebGLContext.cpp \
 	WebGLContextGL.cpp \
 	WebGLContextUtils.cpp \
+	WebGLContextReporter.cpp \
 	WebGLContextValidate.cpp \
 	WebGLExtensionStandardDerivatives.cpp \
 	WebGLExtensionLoseContext.cpp \
 	$(NULL)
 
 DEFINES += -DUSE_ANGLE
 USE_ANGLE=1
 
--- a/content/canvas/src/WebGLContext.cpp
+++ b/content/canvas/src/WebGLContext.cpp
@@ -70,143 +70,16 @@
 
 #include "mozilla/Preferences.h"
 #include "mozilla/Telemetry.h"
 
 using namespace mozilla;
 using namespace mozilla::gl;
 using namespace mozilla::layers;
 
-WebGLMemoryReporter* WebGLMemoryReporter::sUniqueInstance = nsnull;
-
-NS_MEMORY_REPORTER_IMPLEMENT(WebGLTextureMemoryUsed,
-                             "webgl-texture-memory",
-                             KIND_OTHER,
-                             UNITS_BYTES,
-                             WebGLMemoryReporter::GetTextureMemoryUsed,
-                             "Memory used by WebGL textures. The OpenGL implementation is free to store these textures in either video memory or main memory. This measurement is only a lower bound, actual memory usage may be higher for example if the storage is strided.")
-
-NS_MEMORY_REPORTER_IMPLEMENT(WebGLTextureCount,
-                             "webgl-texture-count",
-                             KIND_OTHER,
-                             UNITS_COUNT,
-                             WebGLMemoryReporter::GetTextureCount,
-                             "Number of WebGL textures.")
-
-NS_MEMORY_REPORTER_IMPLEMENT(WebGLBufferMemoryUsed,
-                             "webgl-buffer-memory",
-                             KIND_OTHER,
-                             UNITS_BYTES,
-                             WebGLMemoryReporter::GetBufferMemoryUsed,
-                             "Memory used by WebGL buffers. The OpenGL implementation is free to store these buffers in either video memory or main memory. This measurement is only a lower bound, actual memory usage may be higher for example if the storage is strided.")
-
-NS_MEMORY_REPORTER_IMPLEMENT(WebGLBufferCacheMemoryUsed,
-                             "explicit/webgl/buffer-cache-memory",
-                             KIND_HEAP,
-                             UNITS_BYTES,
-                             WebGLMemoryReporter::GetBufferCacheMemoryUsed,
-                             "Memory used by WebGL buffer caches. The WebGL implementation caches the contents of element array buffers only. This adds up with the webgl-buffer-memory value, but contrary to it, this one represents bytes on the heap, not managed by OpenGL.")
-
-NS_MEMORY_REPORTER_IMPLEMENT(WebGLBufferCount,
-                             "webgl-buffer-count",
-                             KIND_OTHER,
-                             UNITS_COUNT,
-                             WebGLMemoryReporter::GetBufferCount,
-                             "Number of WebGL buffers.")
-
-NS_MEMORY_REPORTER_IMPLEMENT(WebGLRenderbufferMemoryUsed,
-                             "webgl-renderbuffer-memory",
-                             KIND_OTHER,
-                             UNITS_BYTES,
-                             WebGLMemoryReporter::GetRenderbufferMemoryUsed,
-                             "Memory used by WebGL renderbuffers. The OpenGL implementation is free to store these renderbuffers in either video memory or main memory. This measurement is only a lower bound, actual memory usage may be higher for example if the storage is strided.")
-
-NS_MEMORY_REPORTER_IMPLEMENT(WebGLRenderbufferCount,
-                             "webgl-renderbuffer-count",
-                             KIND_OTHER,
-                             UNITS_COUNT,
-                             WebGLMemoryReporter::GetRenderbufferCount,
-                             "Number of WebGL renderbuffers.")
-
-NS_MEMORY_REPORTER_IMPLEMENT(WebGLShaderSourcesSize,
-                             "explicit/webgl/shader-sources-size",
-                             KIND_HEAP,
-                             UNITS_BYTES,
-                             WebGLMemoryReporter::GetShaderSourcesSize,
-                             "Combined size of WebGL shader ASCII sources, cached on the heap. This should always be at most a few kilobytes, or dozen kilobytes for very shader-intensive WebGL demos.")
-
-NS_MEMORY_REPORTER_IMPLEMENT(WebGLShaderTranslationLogsSize,
-                             "explicit/webgl/shader-translationlogs-size",
-                             KIND_HEAP,
-                             UNITS_BYTES,
-                             WebGLMemoryReporter::GetShaderTranslationLogsSize,
-                             "Combined size of WebGL shader ASCII translation logs, cached on the heap.")
-
-NS_MEMORY_REPORTER_IMPLEMENT(WebGLShaderCount,
-                             "webgl-shader-count",
-                             KIND_OTHER,
-                             UNITS_COUNT,
-                             WebGLMemoryReporter::GetShaderCount,
-                             "Number of WebGL shaders.")
-
-NS_MEMORY_REPORTER_IMPLEMENT(WebGLContextCount,
-                             "webgl-context-count",
-                             KIND_OTHER,
-                             UNITS_COUNT,
-                             WebGLMemoryReporter::GetContextCount,
-                             "Number of WebGL contexts.")
-
-WebGLMemoryReporter* WebGLMemoryReporter::UniqueInstance()
-{
-    if (!sUniqueInstance) {
-        sUniqueInstance = new WebGLMemoryReporter;
-    }
-    return sUniqueInstance;
-}
-
-WebGLMemoryReporter::WebGLMemoryReporter()
-    : mTextureMemoryUsageReporter(new NS_MEMORY_REPORTER_NAME(WebGLTextureMemoryUsed))
-    , mTextureCountReporter(new NS_MEMORY_REPORTER_NAME(WebGLTextureCount))
-    , mBufferMemoryUsageReporter(new NS_MEMORY_REPORTER_NAME(WebGLBufferMemoryUsed))
-    , mBufferCacheMemoryUsageReporter(new NS_MEMORY_REPORTER_NAME(WebGLBufferCacheMemoryUsed))
-    , mBufferCountReporter(new NS_MEMORY_REPORTER_NAME(WebGLBufferCount))
-    , mRenderbufferMemoryUsageReporter(new NS_MEMORY_REPORTER_NAME(WebGLRenderbufferMemoryUsed))
-    , mRenderbufferCountReporter(new NS_MEMORY_REPORTER_NAME(WebGLRenderbufferCount))
-    , mShaderSourcesSizeReporter(new NS_MEMORY_REPORTER_NAME(WebGLShaderSourcesSize))
-    , mShaderTranslationLogsSizeReporter(new NS_MEMORY_REPORTER_NAME(WebGLShaderTranslationLogsSize))
-    , mShaderCountReporter(new NS_MEMORY_REPORTER_NAME(WebGLShaderCount))
-    , mContextCountReporter(new NS_MEMORY_REPORTER_NAME(WebGLContextCount))
-{
-    NS_RegisterMemoryReporter(mTextureMemoryUsageReporter);
-    NS_RegisterMemoryReporter(mTextureCountReporter);
-    NS_RegisterMemoryReporter(mBufferMemoryUsageReporter);
-    NS_RegisterMemoryReporter(mBufferCacheMemoryUsageReporter);    
-    NS_RegisterMemoryReporter(mBufferCountReporter);
-    NS_RegisterMemoryReporter(mRenderbufferMemoryUsageReporter);
-    NS_RegisterMemoryReporter(mRenderbufferCountReporter);
-    NS_RegisterMemoryReporter(mShaderSourcesSizeReporter);
-    NS_RegisterMemoryReporter(mShaderTranslationLogsSizeReporter);
-    NS_RegisterMemoryReporter(mShaderCountReporter);
-    NS_RegisterMemoryReporter(mContextCountReporter);
-}
-
-WebGLMemoryReporter::~WebGLMemoryReporter()
-{
-    NS_UnregisterMemoryReporter(mTextureMemoryUsageReporter);
-    NS_UnregisterMemoryReporter(mTextureCountReporter);
-    NS_UnregisterMemoryReporter(mBufferMemoryUsageReporter);
-    NS_UnregisterMemoryReporter(mBufferCacheMemoryUsageReporter);
-    NS_UnregisterMemoryReporter(mBufferCountReporter);
-    NS_UnregisterMemoryReporter(mRenderbufferMemoryUsageReporter);
-    NS_UnregisterMemoryReporter(mRenderbufferCountReporter);
-    NS_UnregisterMemoryReporter(mShaderSourcesSizeReporter);
-    NS_UnregisterMemoryReporter(mShaderTranslationLogsSizeReporter);
-    NS_UnregisterMemoryReporter(mShaderCountReporter);
-    NS_UnregisterMemoryReporter(mContextCountReporter);
-}
 
 nsresult NS_NewCanvasRenderingContextWebGL(nsIDOMWebGLRenderingContext** aResult);
 
 nsresult
 NS_NewCanvasRenderingContextWebGL(nsIDOMWebGLRenderingContext** aResult)
 {
     Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_USED, 1);
     nsIDOMWebGLRenderingContext* ctx = new WebGLContext();
@@ -284,31 +157,31 @@ WebGLContext::WebGLContext()
     mGLMaxVaryingVectors = 0;
     mGLMaxFragmentUniformVectors = 0;
     mGLMaxVertexUniformVectors = 0;
     
     // See OpenGL ES 2.0.25 spec, 6.2 State Tables, table 6.13
     mPixelStorePackAlignment = 4;
     mPixelStoreUnpackAlignment = 4;
 
-    WebGLMemoryReporter::AddWebGLContext(this);
+    WebGLMemoryMultiReporterWrapper::AddWebGLContext(this);
 
     mAllowRestore = true;
     mRobustnessTimerRunning = false;
     mDrawSinceRobustnessTimerSet = false;
     mContextRestorer = do_CreateInstance("@mozilla.org/timer;1");
     mContextStatus = ContextStable;
     mContextLostErrorSet = false;
     mContextLostDueToTest = false;
 }
 
 WebGLContext::~WebGLContext()
 {
     DestroyResourcesAndContext();
-    WebGLMemoryReporter::RemoveWebGLContext(this);
+    WebGLMemoryMultiReporterWrapper::RemoveWebGLContext(this);
     TerminateRobustnessTimer();
     mContextRestorer = nsnull;
 }
 
 void
 WebGLContext::DestroyResourcesAndContext()
 {
     if (!gl)
--- a/content/canvas/src/WebGLContext.h
+++ b/content/canvas/src/WebGLContext.h
@@ -50,18 +50,18 @@
 
 #include "nsIDocShell.h"
 
 #include "nsIDOMWebGLRenderingContext.h"
 #include "nsICanvasRenderingContextInternal.h"
 #include "nsHTMLCanvasElement.h"
 #include "nsWeakReference.h"
 #include "nsIDOMHTMLElement.h"
+#include "nsIMemoryReporter.h"
 #include "nsIJSNativeInitializer.h"
-#include "nsIMemoryReporter.h"
 #include "nsContentUtils.h"
 
 #include "GLContextProvider.h"
 #include "Layers.h"
 
 #include "CheckedInt.h"
 
 /* 
@@ -509,17 +509,17 @@ struct WebGLContextOptions {
 
 class WebGLContext :
     public nsIDOMWebGLRenderingContext,
     public nsICanvasRenderingContextInternal,
     public nsSupportsWeakReference,
     public nsITimerCallback,
     public WebGLRectangleObject
 {
-    friend class WebGLMemoryReporter;
+    friend class WebGLMemoryMultiReporterWrapper;
     friend class WebGLExtensionLoseContext;
     friend class WebGLContextUserData;
 
 public:
     WebGLContext();
     virtual ~WebGLContext();
 
     NS_DECL_CYCLE_COLLECTING_ISUPPORTS
@@ -1050,16 +1050,20 @@ public:
         mContext->MakeContextCurrent();
         mContext->gl->fDeleteBuffers(1, &mGLName);
         free(mData);
         mData = nsnull;
         mByteLength = 0;
         mContext->mBuffers.RemoveElement(mMonotonicHandle);
     }
 
+    size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const {
+        return aMallocSizeOf(this) + aMallocSizeOf(mData);
+    }
+   
     bool HasEverBeenBound() { return mHasEverBeenBound; }
     void SetHasEverBeenBound(bool x) { mHasEverBeenBound = x; }
     GLuint GLName() const { return mGLName; }
     GLuint ByteLength() const { return mByteLength; }
     GLenum Target() const { return mTarget; }
     const void *Data() const { return mData; }
 
     void SetByteLength(GLuint byteLength) { mByteLength = byteLength; }
@@ -1622,16 +1626,22 @@ public:
         mContext->MakeContextCurrent();
         mGLName = mContext->gl->fCreateShader(mType);
         mMonotonicHandle = mContext->mShaders.AppendElement(this);
     }
 
     ~WebGLShader() {
         DeleteOnce();
     }
+    
+    size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) {
+        return aMallocSizeOf(this) +
+               mSource.SizeOfExcludingThisIfUnshared(aMallocSizeOf) +
+               mTranslationLog.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
+    }
 
     void Delete() {
         mSource.Truncate();
         mTranslationLog.Truncate();
         mContext->MakeContextCurrent();
         mContext->gl->fDeleteShader(mGLName);
         mContext->mShaders.RemoveElement(mMonotonicHandle);
     }
@@ -2510,136 +2520,103 @@ WebGLContext::CanGetConcreteObject(const
                               BaseInterfaceType *aInterface,
                               bool *isNull,
                               bool *isDeleted)
 {
     ConcreteObjectType *aConcreteObject;
     return GetConcreteObject(info, aInterface, &aConcreteObject, isNull, isDeleted, false);
 }
 
-class WebGLMemoryReporter
+class WebGLMemoryMultiReporterWrapper
 {
-    WebGLMemoryReporter();
-    ~WebGLMemoryReporter();
-    static WebGLMemoryReporter* sUniqueInstance;
-
-    // here we store plain pointers, not RefPtrs: we don't want the WebGLMemoryReporter unique instance to keep alive all
+    WebGLMemoryMultiReporterWrapper();
+    ~WebGLMemoryMultiReporterWrapper();
+    static WebGLMemoryMultiReporterWrapper* sUniqueInstance;
+
+    // here we store plain pointers, not RefPtrs: we don't want the 
+    // WebGLMemoryMultiReporterWrapper unique instance to keep alive all		
     // WebGLContexts ever created.
     typedef nsTArray<const WebGLContext*> ContextsArrayType;
     ContextsArrayType mContexts;
     
-    nsCOMPtr<nsIMemoryReporter> mTextureMemoryUsageReporter;
-    nsCOMPtr<nsIMemoryReporter> mTextureCountReporter;
-    nsCOMPtr<nsIMemoryReporter> mBufferMemoryUsageReporter;
-    nsCOMPtr<nsIMemoryReporter> mBufferCacheMemoryUsageReporter;
-    nsCOMPtr<nsIMemoryReporter> mBufferCountReporter;
-    nsCOMPtr<nsIMemoryReporter> mRenderbufferMemoryUsageReporter;
-    nsCOMPtr<nsIMemoryReporter> mRenderbufferCountReporter;
-    nsCOMPtr<nsIMemoryReporter> mShaderSourcesSizeReporter;
-    nsCOMPtr<nsIMemoryReporter> mShaderTranslationLogsSizeReporter;
-    nsCOMPtr<nsIMemoryReporter> mShaderCountReporter;
-    nsCOMPtr<nsIMemoryReporter> mContextCountReporter;
-
-    static WebGLMemoryReporter* UniqueInstance();
+    nsCOMPtr<nsIMemoryMultiReporter> mReporter;
+
+    static WebGLMemoryMultiReporterWrapper* UniqueInstance();
 
     static ContextsArrayType & Contexts() { return UniqueInstance()->mContexts; }
 
   public:
 
     static void AddWebGLContext(const WebGLContext* c) {
         Contexts().AppendElement(c);
     }
 
     static void RemoveWebGLContext(const WebGLContext* c) {
         ContextsArrayType & contexts = Contexts();
         contexts.RemoveElement(c);
         if (contexts.IsEmpty()) {
-            delete sUniqueInstance;
+            delete sUniqueInstance; 
             sUniqueInstance = nsnull;
         }
     }
 
     static PRInt64 GetTextureMemoryUsed() {
         const ContextsArrayType & contexts = Contexts();
         PRInt64 result = 0;
         for(size_t i = 0; i < contexts.Length(); ++i)
-            for (size_t t = 0; t < contexts[i]->mTextures.Length(); ++t)
-              result += contexts[i]->mTextures[t]->MemoryUsage();
+            for (size_t j = 0; j < contexts[i]->mTextures.Length(); ++j)
+              result += contexts[i]->mTextures[j]->MemoryUsage();
         return result;
     }
 
     static PRInt64 GetTextureCount() {
         const ContextsArrayType & contexts = Contexts();
         PRInt64 result = 0;
         for(size_t i = 0; i < contexts.Length(); ++i)
             result += contexts[i]->mTextures.Length();
         return result;
     }
 
     static PRInt64 GetBufferMemoryUsed() {
         const ContextsArrayType & contexts = Contexts();
         PRInt64 result = 0;
         for(size_t i = 0; i < contexts.Length(); ++i)
-            for (size_t b = 0; b < contexts[i]->mBuffers.Length(); ++b)
-                result += contexts[i]->mBuffers[b]->ByteLength();
+            for (size_t j = 0; j < contexts[i]->mBuffers.Length(); ++j)
+                result += contexts[i]->mBuffers[j]->ByteLength();
         return result;
     }
 
-    static PRInt64 GetBufferCacheMemoryUsed() {
-        const ContextsArrayType & contexts = Contexts();
-        PRInt64 result = 0;
-        for(size_t i = 0; i < contexts.Length(); ++i)
-            for (size_t b = 0; b < contexts[i]->mBuffers.Length(); ++b)
-                if (contexts[i]->mBuffers[b]->Target() == LOCAL_GL_ELEMENT_ARRAY_BUFFER)
-                    result += contexts[i]->mBuffers[b]->ByteLength();
-        return result;
-    }
+    static PRInt64 GetBufferCacheMemoryUsed();
 
     static PRInt64 GetBufferCount() {
         const ContextsArrayType & contexts = Contexts();
         PRInt64 result = 0;
         for(size_t i = 0; i < contexts.Length(); ++i)
             result += contexts[i]->mBuffers.Length();
         return result;
     }
 
     static PRInt64 GetRenderbufferMemoryUsed() {
         const ContextsArrayType & contexts = Contexts();
         PRInt64 result = 0;
         for(size_t i = 0; i < contexts.Length(); ++i)
-            for (size_t r = 0; r < contexts[i]->mRenderbuffers.Length(); ++r)
-              result += contexts[i]->mRenderbuffers[r]->MemoryUsage();
+            for (size_t j = 0; j < contexts[i]->mRenderbuffers.Length(); ++j)
+              result += contexts[i]->mRenderbuffers[j]->MemoryUsage();
         return result;
     }
 
     static PRInt64 GetRenderbufferCount() {
         const ContextsArrayType & contexts = Contexts();
         PRInt64 result = 0;
         for(size_t i = 0; i < contexts.Length(); ++i)
             result += contexts[i]->mRenderbuffers.Length();
         return result;
     }
 
-    static PRInt64 GetShaderSourcesSize() {
-        const ContextsArrayType & contexts = Contexts();
-        PRInt64 result = 0;
-        for(size_t i = 0; i < contexts.Length(); ++i)
-            for (size_t s = 0; s < contexts[i]->mShaders.Length(); ++s)
-                result += contexts[i]->mShaders[s]->Source().Length();
-        return result;
-    }
-
-    static PRInt64 GetShaderTranslationLogsSize() {
-        const ContextsArrayType & contexts = Contexts();
-        PRInt64 result = 0;
-        for(size_t i = 0; i < contexts.Length(); ++i)
-            for (size_t s = 0; s < contexts[i]->mShaders.Length(); ++s)
-                result += contexts[i]->mShaders[s]->TranslationLog().Length();
-        return result;
-    }
+    static PRInt64 GetShaderSize();
 
     static PRInt64 GetShaderCount() {
         const ContextsArrayType & contexts = Contexts();
         PRInt64 result = 0;
         for(size_t i = 0; i < contexts.Length(); ++i)
             result += contexts[i]->mShaders.Length();
         return result;
     }
new file mode 100644
--- /dev/null
+++ b/content/canvas/src/WebGLContextReporter.cpp
@@ -0,0 +1,218 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ *   Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "WebGLContext.h"
+#include "nsIMemoryReporter.h"
+
+using namespace mozilla;
+
+
+class WebGLMemoryMultiReporter : public nsIMemoryMultiReporter 
+{
+  public:
+    NS_DECL_ISUPPORTS
+    NS_DECL_NSIMEMORYMULTIREPORTER
+};
+
+NS_IMPL_ISUPPORTS1(WebGLMemoryMultiReporter, nsIMemoryMultiReporter)
+
+NS_IMETHODIMP
+WebGLMemoryMultiReporter::GetName(nsACString &aName)
+{
+  aName.AssignLiteral("webgl");
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+WebGLMemoryMultiReporter::GetExplicitNonHeap(PRInt64 *aAmount)
+{
+    // WebGLMemoryMultiReporterWrapper has no KIND_NONHEAP measurements.
+    *aAmount = 0;
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+WebGLMemoryMultiReporter::CollectReports(nsIMemoryMultiReporterCallback* aCb, 
+                                         nsISupports* aClosure)
+{
+    aCb->Callback(
+        EmptyCString(), 
+        NS_LITERAL_CSTRING("webgl-texture-memory"),
+        nsIMemoryReporter::KIND_OTHER, nsIMemoryReporter::UNITS_BYTES,
+        WebGLMemoryMultiReporterWrapper::GetTextureMemoryUsed(),
+        NS_LITERAL_CSTRING("Memory used by WebGL textures.The OpenGL"
+            " implementation is free to store these textures in either video"
+            " memory or main memory. This measurement is only a lower bound,"
+            " actual memory usage may be higher for example if the storage" 
+            " is strided."),  
+        aClosure);
+   
+    aCb->Callback(
+        EmptyCString(), 
+        NS_LITERAL_CSTRING("webgl-texture-count"),
+        nsIMemoryReporter::KIND_OTHER, nsIMemoryReporter::UNITS_COUNT,
+         WebGLMemoryMultiReporterWrapper::GetTextureCount(), 
+        NS_LITERAL_CSTRING("Number of WebGL textures."), 
+        aClosure);
+
+    aCb->Callback(
+        EmptyCString(), 
+        NS_LITERAL_CSTRING("webgl-buffer-memory"),
+        nsIMemoryReporter::KIND_OTHER, nsIMemoryReporter::UNITS_BYTES,
+         WebGLMemoryMultiReporterWrapper::GetBufferMemoryUsed(), 
+        NS_LITERAL_CSTRING("Memory used by WebGL buffers. The OpenGL"
+            " implementation is free to store these buffers in either video"
+            " memory or main memory. This measurement is only a lower bound,"
+            " actual memory usage may be higher for example if the storage"
+            " is strided."),
+        aClosure);
+
+    aCb->Callback(
+        EmptyCString(), 
+        NS_LITERAL_CSTRING("explicit/webgl/buffer-cache-memory"),
+        nsIMemoryReporter::KIND_HEAP, nsIMemoryReporter::UNITS_BYTES,
+        WebGLMemoryMultiReporterWrapper::GetBufferCacheMemoryUsed(),
+        NS_LITERAL_CSTRING("Memory used by WebGL buffer caches. The WebGL"
+            " implementation caches the contents of element array buffers"
+            " only.This adds up with the webgl-buffer-memory value, but"
+            " contrary to it, this one represents bytes on the heap,"
+            " not managed by OpenGL."),
+        aClosure);
+
+    aCb->Callback(
+        EmptyCString(), NS_LITERAL_CSTRING("webgl-buffer-count"),
+        nsIMemoryReporter::KIND_OTHER, nsIMemoryReporter::UNITS_COUNT,
+        WebGLMemoryMultiReporterWrapper::GetBufferCount(),
+        NS_LITERAL_CSTRING("Number of WebGL buffers."), 
+        aClosure);
+   
+    aCb->Callback(
+        EmptyCString(), 
+        NS_LITERAL_CSTRING("webgl-renderbuffer-memory"),
+        nsIMemoryReporter::KIND_OTHER, nsIMemoryReporter::UNITS_BYTES,
+        WebGLMemoryMultiReporterWrapper::GetRenderbufferMemoryUsed(), 
+        NS_LITERAL_CSTRING("Memory used by WebGL renderbuffers. The OpenGL"
+            " implementation is free to store these renderbuffers in either"
+            " video memory or main memory. This measurement is only a lower"
+            " bound, actual memory usage may be higher for example if the"
+            " storage is strided."),
+        aClosure);
+   
+    aCb->Callback(
+        EmptyCString(),
+        NS_LITERAL_CSTRING("webgl-renderbuffer-count"),
+        nsIMemoryReporter::KIND_OTHER, nsIMemoryReporter::UNITS_COUNT,
+        WebGLMemoryMultiReporterWrapper::GetRenderbufferCount(),
+        NS_LITERAL_CSTRING("Number of WebGL renderbuffers."),
+        aClosure);
+  
+    aCb->Callback(
+        EmptyCString(),
+        NS_LITERAL_CSTRING("explicit/webgl/shader"),
+        nsIMemoryReporter::KIND_HEAP, nsIMemoryReporter::UNITS_BYTES,
+        WebGLMemoryMultiReporterWrapper::GetShaderSize(), 
+        NS_LITERAL_CSTRING("Combined size of WebGL shader ASCII sources and"
+            " translation logs cached on the heap."), 
+        aClosure);
+
+    aCb->Callback(
+        EmptyCString(), 
+        NS_LITERAL_CSTRING("webgl-shader-count"),
+        nsIMemoryReporter::KIND_OTHER, nsIMemoryReporter::UNITS_COUNT,
+        WebGLMemoryMultiReporterWrapper::GetShaderCount(), 
+        NS_LITERAL_CSTRING("Number of WebGL shaders."), 
+        aClosure);
+
+    aCb->Callback(
+        EmptyCString(), 
+        NS_LITERAL_CSTRING("webgl-context-count"),
+        nsIMemoryReporter::KIND_OTHER, nsIMemoryReporter::UNITS_COUNT,
+        WebGLMemoryMultiReporterWrapper::GetContextCount(), 
+        NS_LITERAL_CSTRING("Number of WebGL contexts."), 
+        aClosure);
+
+    return NS_OK;
+}
+
+WebGLMemoryMultiReporterWrapper* WebGLMemoryMultiReporterWrapper::sUniqueInstance = nsnull;
+
+WebGLMemoryMultiReporterWrapper* WebGLMemoryMultiReporterWrapper::UniqueInstance()
+{
+    if (!sUniqueInstance) {
+        sUniqueInstance = new WebGLMemoryMultiReporterWrapper;
+    }
+    return sUniqueInstance;     
+}
+
+WebGLMemoryMultiReporterWrapper::WebGLMemoryMultiReporterWrapper()
+{ 
+    mReporter = new WebGLMemoryMultiReporter;   
+    NS_RegisterMemoryMultiReporter(mReporter);
+}
+
+WebGLMemoryMultiReporterWrapper::~WebGLMemoryMultiReporterWrapper()
+{
+    NS_UnregisterMemoryMultiReporter(mReporter);
+}
+
+NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(WebGLBufferMallocSizeOfFun, "webgl-buffer")
+
+PRInt64 
+WebGLMemoryMultiReporterWrapper::GetBufferCacheMemoryUsed() {
+    const ContextsArrayType & contexts = Contexts();
+    PRInt64 result = 0;
+    for (size_t i = 0; i < contexts.Length(); ++i) {
+        for (size_t j = 0; j < contexts[i]->mBuffers.Length(); ++j) 
+            if (contexts[i]->mBuffers[j]->Target() == LOCAL_GL_ELEMENT_ARRAY_BUFFER)
+               result += contexts[i]->mBuffers[j]->SizeOfIncludingThis(WebGLBufferMallocSizeOfFun);
+    }
+    return result;
+}
+
+NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(WebGLShaderMallocSizeOfFun, "webgl-shader")
+
+PRInt64 
+WebGLMemoryMultiReporterWrapper::GetShaderSize() {
+    const ContextsArrayType & contexts = Contexts();
+    PRInt64 result = 0;
+    for (size_t i = 0; i < contexts.Length(); ++i) {
+        for (size_t j = 0; j < contexts[i]->mShaders.Length(); ++j) 
+            result += contexts[i]->mShaders[j]->SizeOfIncludingThis(WebGLShaderMallocSizeOfFun);
+    }
+    return result;
+}