From f43e46bc9c0007d30cef6f0a2b2b07b9bbadd996 Mon Sep 17 00:00:00 2001
From: Stinson Linden <stinson@lindenlab.com>
Date: Mon, 28 Apr 2014 19:44:02 +0100
Subject: [PATCH] MAINT-4009: Ensuring that the pick mask for the LLImageGL is
 always properly freed during its cleanup method.

---
 indra/llrender/llimagegl.cpp | 61 ++++++++++++++++++++++--------------
 indra/llrender/llimagegl.h   |  3 ++
 2 files changed, 41 insertions(+), 23 deletions(-)

diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp
index ddf38c67456..5b989da911f 100755
--- a/indra/llrender/llimagegl.cpp
+++ b/indra/llrender/llimagegl.cpp
@@ -390,9 +390,7 @@ LLImageGL::~LLImageGL()
 {
 	LLImageGL::cleanup();
 	sImageList.erase(this);
-	disclaimMem((mPickMaskWidth * mPickMaskHeight + 7) / 8);
-	delete [] mPickMask;
-	mPickMask = NULL;
+	freePickMask();
 	sCount--;
 }
 
@@ -461,6 +459,8 @@ void LLImageGL::cleanup()
 	{
 		destroyGLTexture();
 	}
+	freePickMask();
+
 	mSaveData = NULL; // deletes data
 }
 
@@ -504,10 +504,7 @@ void LLImageGL::setSize(S32 width, S32 height, S32 ncomponents, S32 discard_leve
 		}
 
 		// pickmask validity depends on old image size, delete it
-		disclaimMem((mPickMaskWidth * mPickMaskHeight + 7) / 8);
-		delete [] mPickMask;
-		mPickMask = NULL;
-		mPickMaskWidth = mPickMaskHeight = 0;
+		freePickMask();
 
 		mWidth = width;
 		mHeight = height;
@@ -1885,6 +1882,37 @@ void LLImageGL::analyzeAlpha(const void* data_in, U32 w, U32 h)
 	}
 }
 
+//----------------------------------------------------------------------------
+U32 LLImageGL::createPickMask(S32 pWidth, S32 pHeight)
+{
+	U32 pick_width = pWidth/2 + 1;
+	U32 pick_height = pHeight/2 + 1;
+
+	U32 size = pick_width * pick_height;
+	size = (size + 7) / 8; // pixelcount-to-bits
+	mPickMask = new U8[size];
+	claimMem(size);
+	mPickMaskWidth = pick_width - 1;
+	mPickMaskHeight = pick_height - 1;
+
+	memset(mPickMask, 0, sizeof(U8) * size);
+
+	return size;
+}
+
+//----------------------------------------------------------------------------
+void LLImageGL::freePickMask()
+{
+	// pickmask validity depends on old image size, delete it
+	if (mPickMask != NULL)
+	{
+		disclaimMem((mPickMaskWidth * mPickMaskHeight + 7) / 8);
+		delete [] mPickMask;
+	}
+	mPickMask = NULL;
+	mPickMaskWidth = mPickMaskHeight = 0;
+}
+
 //----------------------------------------------------------------------------
 void LLImageGL::updatePickMask(S32 width, S32 height, const U8* data_in)
 {
@@ -1893,10 +1921,7 @@ void LLImageGL::updatePickMask(S32 width, S32 height, const U8* data_in)
 		return ;
 	}
 
-	disclaimMem((mPickMaskWidth * mPickMaskHeight + 7) / 8);
-	delete [] mPickMask;
-	mPickMask = NULL;
-	mPickMaskWidth = mPickMaskHeight = 0;
+	freePickMask();
 
 	if (mFormatType != GL_UNSIGNED_BYTE ||
 	    mFormatPrimary != GL_RGBA)
@@ -1905,17 +1930,7 @@ void LLImageGL::updatePickMask(S32 width, S32 height, const U8* data_in)
 		return;
 	}
 
-	U32 pick_width = width/2 + 1;
-	U32 pick_height = height/2 + 1;
-
-	U32 size = pick_width * pick_height;
-	size = (size + 7) / 8; // pixelcount-to-bits
-	mPickMask = new U8[size];
-	claimMem(size);
-	mPickMaskWidth = pick_width - 1;
-	mPickMaskHeight = pick_height - 1;
-
-	memset(mPickMask, 0, sizeof(U8) * size);
+	U32 pickSize = createPickMask(width, height);
 
 	U32 pick_bit = 0;
 	
@@ -1929,7 +1944,7 @@ void LLImageGL::updatePickMask(S32 width, S32 height, const U8* data_in)
 			{
 				U32 pick_idx = pick_bit/8;
 				U32 pick_offset = pick_bit%8;
-				llassert(pick_idx < size);
+				llassert(pick_idx < pickSize);
 
 				mPickMask[pick_idx] |= 1 << pick_offset;
 			}
diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h
index 6ca814af6fc..21982eab1dd 100755
--- a/indra/llrender/llimagegl.h
+++ b/indra/llrender/llimagegl.h
@@ -186,6 +186,9 @@ class LLImageGL : public LLRefCount, public LLTrace::MemTrackable<LLImageGL>
 	mutable F32  mLastBindTime;	// last time this was bound, by discard level
 	
 private:
+	U32 createPickMask(S32 pWidth, S32 pHeight);
+	void freePickMask();
+
 	LLPointer<LLImageRaw> mSaveData; // used for destroyGL/restoreGL
 	U8* mPickMask;  //downsampled bitmap approximation of alpha channel.  NULL if no alpha channel
 	U16 mPickMaskWidth;
-- 
GitLab