Bug 705904 - [2/6] - Kill nsRefPtrHashtables of WebGL objects, allow unreferenced objects to be freed, fix about:memory reporting of deleted objects - r=jgilbert
authorBenoit Jacob <bjacob@mozilla.com>
Sun, 04 Dec 2011 14:15:43 -0500
changeset 82011 eaf41f64aad7d983a7b1d0a01195c4231cc5f13b
parent 82010 a9f0158d9494d608d3bce49c8fed487c89dfd4e3
child 82012 111be7b1a9e89843248d214cc6f50244b8eccb17
push idunknown
push userunknown
push dateunknown
reviewersjgilbert
bugs705904
milestone11.0a1
Bug 705904 - [2/6] - Kill nsRefPtrHashtables of WebGL objects, allow unreferenced objects to be freed, fix about:memory reporting of deleted objects - r=jgilbert This patch takes care of WebGLBuffer.
content/canvas/src/WebGLContext.cpp
content/canvas/src/WebGLContext.h
content/canvas/src/WebGLContextGL.cpp
content/canvas/src/WebGLContextValidate.cpp
--- a/content/canvas/src/WebGLContext.cpp
+++ b/content/canvas/src/WebGLContext.cpp
@@ -231,17 +231,16 @@ WebGLContext::WebGLContext()
     mActiveTexture = 0;
     mWebGLError = LOCAL_GL_NO_ERROR;
     mPixelStoreFlipY = false;
     mPixelStorePremultiplyAlpha = false;
     mPixelStoreColorspaceConversion = BROWSER_DEFAULT_WEBGL;
 
     mShaderValidation = true;
 
-    mMapBuffers.Init();
     mMapPrograms.Init();
     mMapShaders.Init();
     mMapFramebuffers.Init();
     mMapRenderbuffers.Init();
 
     mBlackTexturesAreInitialized = false;
     mFakeBlackStatus = DoNotNeedFakeBlack;
 
@@ -344,19 +343,20 @@ WebGLContext::DestroyResourcesAndContext
     mCurrentProgram = nsnull;
     mBoundFramebuffer = nsnull;
     mBoundRenderbuffer = nsnull;
 
     mAttribBuffers.Clear();
 
     while (mTextures.Length())
         mTextures.Last()->DeleteOnce();
+    while (mBuffers.Length())
+        mBuffers.Last()->DeleteOnce();
     DeleteWebGLObjectsHashTable(mMapRenderbuffers);
     DeleteWebGLObjectsHashTable(mMapFramebuffers);
-    DeleteWebGLObjectsHashTable(mMapBuffers);
     DeleteWebGLObjectsHashTable(mMapShaders);
     DeleteWebGLObjectsHashTable(mMapPrograms);
 
     if (mBlackTexturesAreInitialized) {
         gl->fDeleteTextures(1, &mBlackTexture2D);
         gl->fDeleteTextures(1, &mBlackTextureCubeMap);
         mBlackTexturesAreInitialized = false;
     }
--- a/content/canvas/src/WebGLContext.h
+++ b/content/canvas/src/WebGLContext.h
@@ -819,19 +819,18 @@ protected:
 
     WebGLRefPtr<WebGLProgram> mCurrentProgram;
 
     PRUint32 mMaxFramebufferColorAttachments;
 
     WebGLRefPtr<WebGLFramebuffer> mBoundFramebuffer;
     WebGLRefPtr<WebGLRenderbuffer> mBoundRenderbuffer;
 
-    // lookup tables for GL name -> object wrapper
     WebGLFastArray<WebGLTexture*> mTextures;
-    nsRefPtrHashtable<nsUint32HashKey, WebGLBuffer> mMapBuffers;
+    WebGLFastArray<WebGLBuffer*> mBuffers;
     nsRefPtrHashtable<nsUint32HashKey, WebGLProgram> mMapPrograms;
     nsRefPtrHashtable<nsUint32HashKey, WebGLShader> mMapShaders;
     nsRefPtrHashtable<nsUint32HashKey, WebGLFramebuffer> mMapFramebuffers;
     nsRefPtrHashtable<nsUint32HashKey, WebGLRenderbuffer> mMapRenderbuffers;
 
     // PixelStore parameters
     PRUint32 mPixelStorePackAlignment, mPixelStoreUnpackAlignment, mPixelStoreColorspaceConversion;
     bool mPixelStoreFlipY, mPixelStorePremultiplyAlpha;
@@ -996,28 +995,30 @@ public:
         : WebGLContextBoundObject(context)
         , mHasEverBeenBound(false)
         , mByteLength(0)
         , mTarget(LOCAL_GL_NONE)
         , mData(nsnull)
     {
         mContext->MakeContextCurrent();
         mContext->gl->fGenBuffers(1, &mGLName);
+        mMonotonicHandle = mContext->mBuffers.AppendElement(this);
     }
 
     ~WebGLBuffer() {
         DeleteOnce();
     }
 
     void Delete() {
         mContext->MakeContextCurrent();
         mContext->gl->fDeleteBuffers(1, &mGLName);
         free(mData);
         mData = nsnull;
         mByteLength = 0;
+        mContext->mBuffers.RemoveElement(mMonotonicHandle);
     }
 
     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; }
@@ -1103,16 +1104,17 @@ public:
     NS_DECL_NSIWEBGLBUFFER
 
 protected:
 
     WebGLuint mGLName;
     bool mHasEverBeenBound;
     GLuint mByteLength;
     GLenum mTarget;
+    WebGLMonotonicHandle mMonotonicHandle;
 
     PRUint8 mCachedMaxUbyteElement;
     bool mHasCachedMaxUbyteElement;
     PRUint16 mCachedMaxUshortElement;
     bool mHasCachedMaxUshortElement;
 
     void* mData; // in the case of an Element Array Buffer, we keep a copy.
 };
@@ -2481,63 +2483,43 @@ class WebGLMemoryReporter
     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 PLDHashOperator BufferMemoryUsageFunction(const PRUint32&, WebGLBuffer *aValue, void *aData)
-    {
-        PRInt64 *result = (PRInt64*) aData;
-        *result += aValue->ByteLength();
-        return PL_DHASH_NEXT;
-    }
-
     static PRInt64 GetBufferMemoryUsed() {
         const ContextsArrayType & contexts = Contexts();
         PRInt64 result = 0;
-        for(size_t i = 0; i < contexts.Length(); ++i) {
-            PRInt64 bufferMemoryUsageForThisContext = 0;
-            contexts[i]->mMapBuffers.EnumerateRead(BufferMemoryUsageFunction, &bufferMemoryUsageForThisContext);
-            result += bufferMemoryUsageForThisContext;
-        }
+        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();
         return result;
     }
-    
-    static PLDHashOperator BufferCacheMemoryUsageFunction(const PRUint32&, WebGLBuffer *aValue, void *aData)
-    {
-        PRInt64 *result = (PRInt64*) aData;
-        // element array buffers are cached in the WebGL implementation. Other buffers aren't.
-        if (aValue->Target() == LOCAL_GL_ELEMENT_ARRAY_BUFFER)
-          *result += aValue->ByteLength();
-        return PL_DHASH_NEXT;
-    }
 
     static PRInt64 GetBufferCacheMemoryUsed() {
         const ContextsArrayType & contexts = Contexts();
         PRInt64 result = 0;
-        for(size_t i = 0; i < contexts.Length(); ++i) {
-            PRInt64 bufferCacheMemoryUsageForThisContext = 0;
-            contexts[i]->mMapBuffers.EnumerateRead(BufferCacheMemoryUsageFunction, &bufferCacheMemoryUsageForThisContext);
-            result += bufferCacheMemoryUsageForThisContext;
-        }
+        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 GetBufferCount() {
         const ContextsArrayType & contexts = Contexts();
         PRInt64 result = 0;
-        for(size_t i = 0; i < contexts.Length(); ++i) {
-            result += contexts[i]->mMapBuffers.Count();
-        }
+        for(size_t i = 0; i < contexts.Length(); ++i)
+            result += contexts[i]->mBuffers.Length();
         return result;
     }
-    
+
     static PLDHashOperator RenderbufferMemoryUsageFunction(const PRUint32&, WebGLRenderbuffer *aValue, void *aData)
     {
         PRInt64 *result = (PRInt64*) aData;
         *result += aValue->MemoryUsage();
         return PL_DHASH_NEXT;
     }
 
     static PRInt64 GetRenderbufferMemoryUsed() {
--- a/content/canvas/src/WebGLContextGL.cpp
+++ b/content/canvas/src/WebGLContextGL.cpp
@@ -1146,17 +1146,16 @@ WebGLContext::DeleteBuffer(nsIWebGLBuffe
         BindBuffer(LOCAL_GL_ELEMENT_ARRAY_BUFFER, nsnull);
 
     for (int i = 0; i < mGLMaxVertexAttribs; i++) {
         if (mAttribBuffers[i].buf == buf)
             mAttribBuffers[i].buf = nsnull;
     }
 
     buf->RequestDelete();
-    mMapBuffers.Remove(bufname);
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
 WebGLContext::DeleteFramebuffer(nsIWebGLFramebuffer *fbobj)
 {
     if (mContextLost)
@@ -2528,17 +2527,16 @@ WebGLContext::CreateBuffer(nsIWebGLBuffe
 {
     if (mContextLost)
         return NS_OK;
 
     *retval = nsnull;
 
     WebGLBuffer *globj = new WebGLBuffer(this);
     NS_ADDREF(*retval = globj);
-    mMapBuffers.Put(globj->GLName(), globj);
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
 WebGLContext::CreateTexture(nsIWebGLTexture **retval)
 {
     if (mContextLost)
--- a/content/canvas/src/WebGLContextValidate.cpp
+++ b/content/canvas/src/WebGLContextValidate.cpp
@@ -520,17 +520,16 @@ WebGLContext::InitAndValidateGL()
 
     mBoundArrayBuffer = nsnull;
     mBoundElementArrayBuffer = nsnull;
     mCurrentProgram = nsnull;
 
     mBoundFramebuffer = nsnull;
     mBoundRenderbuffer = nsnull;
 
-    mMapBuffers.Clear();
     mMapPrograms.Clear();
     mMapShaders.Clear();
     mMapFramebuffers.Clear();
     mMapRenderbuffers.Clear();
 
     MakeContextCurrent();
 
     // on desktop OpenGL, we always keep vertex attrib 0 array enabled