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 88766 ac02ca06e1273e3c0d4e73589fd6655767d3fc26
parent 88765 c714722a7aad88ec64b96c59adc22de4608bd6d5
child 88767 f07a6060cc5a15f7435d1429dad813baf8992687
push id975
push userffxbld
push dateTue, 13 Mar 2012 21:39:16 +0000
treeherdermozilla-aurora@99faebf9dc36 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnjn, bjacob
bugs710594
milestone13.0a1
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;
+}