From d9a68339d5aa18af349e347d6ed74bc01824cec7 Mon Sep 17 00:00:00 2001
From: Dave Parks <davep@lindenlab.com>
Date: Wed, 23 Feb 2022 16:51:33 -0600
Subject: [PATCH] SL-16815 and SL-16906 Avoid redundant bumpmap generation, add
 some assertions around ref counting and (hack) fix crash on shutdown from
 dangling texture reference (reduced to 1 dangling texture from several
 hundred, can't find the remaining reference).

---
 indra/llcommon/llrefcount.cpp     |  5 ++++-
 indra/llcommon/llrefcount.h       | 16 ++++++++++++++--
 indra/llrender/llimagegl.cpp      |  8 +++++---
 indra/newview/lldrawpoolbump.cpp  |  4 ++--
 indra/newview/llviewertexture.cpp |  3 +--
 5 files changed, 26 insertions(+), 10 deletions(-)

diff --git a/indra/llcommon/llrefcount.cpp b/indra/llcommon/llrefcount.cpp
index 29a5ca6f245..5cbd3464115 100644
--- a/indra/llcommon/llrefcount.cpp
+++ b/indra/llcommon/llrefcount.cpp
@@ -29,6 +29,9 @@
 
 #include "llerror.h"
 
+// maximum reference count before sounding memory leak alarm
+const S32 gMaxRefCount = 65536;
+
 LLRefCount::LLRefCount(const LLRefCount& other)
 :	mRef(0)
 {
@@ -47,7 +50,7 @@ LLRefCount::LLRefCount() :
 
 LLRefCount::~LLRefCount()
 { 
-	if (mRef != 0)
+	if (mRef != LL_REFCOUNT_FREE && mRef != 0)
 	{
 		LL_ERRS() << "deleting non-zero reference" << LL_ENDL;
 	}
diff --git a/indra/llcommon/llrefcount.h b/indra/llcommon/llrefcount.h
index 7e4af6ea66a..2080da15653 100644
--- a/indra/llcommon/llrefcount.h
+++ b/indra/llcommon/llrefcount.h
@@ -37,6 +37,10 @@ class LLMutex;
 // see llthread.h for LLThreadSafeRefCount
 //----------------------------------------------------------------------------
 
+//nonsense but recognizable value for freed LLRefCount (aids in debugging)
+#define LL_REFCOUNT_FREE 1234567890
+extern const S32 gMaxRefCount;
+
 class LL_COMMON_API LLRefCount
 {
 protected:
@@ -47,17 +51,25 @@ class LL_COMMON_API LLRefCount
 public:
 	LLRefCount();
 
+    inline void validateRefCount() const
+    {
+        llassert(mRef > 0); // ref count below 0, likely corrupted
+        llassert(mRef < gMaxRefCount); // ref count excessive, likely memory leak
+    }
+
 	inline void ref() const
 	{ 
 		mRef++; 
+        validateRefCount();
 	} 
 
 	inline S32 unref() const
 	{
-		llassert(mRef >= 1);
+        validateRefCount();
 		if (0 == --mRef)
 		{
-			delete this; 
+            mRef = LL_REFCOUNT_FREE; // set to nonsense yet recognizable value to aid in debugging
+			delete this;
 			return 0;
 		}
 		return mRef;
diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp
index 9e26247e1e2..5cf3a2a15f7 100644
--- a/indra/llrender/llimagegl.cpp
+++ b/indra/llrender/llimagegl.cpp
@@ -437,7 +437,7 @@ LLImageGL::LLImageGL(
 
 LLImageGL::~LLImageGL()
 {
-    if (!mExternalTexture)
+    if (!mExternalTexture && gGLManager.mInited)
     {
 	    LLImageGL::cleanup();
 	    sImageList.erase(this);
@@ -1629,14 +1629,16 @@ void LLImageGLThread::updateClass()
         }
     };
 
+    
     // post update to background thread if available, otherwise execute immediately
-    auto queue = LLImageGLThread::sEnabled ? LL::WorkQueue::getInstance("LLImageGL") : nullptr;
-    if (queue)
+    auto queue = LL::WorkQueue::getInstance("LLImageGL");
+    if (sEnabled)
     {
         queue->post(func);
     }
     else
     {
+        llassert(queue == nullptr);
         func();
     }
 }
diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp
index 2b151487fdd..1d5419b515a 100644
--- a/indra/newview/lldrawpoolbump.cpp
+++ b/indra/newview/lldrawpoolbump.cpp
@@ -1051,8 +1051,8 @@ void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerTexture *src_vi, LLI
 			}
 		}
 
-		//if (iter->second->getWidth() != src->getWidth() ||
-		//	iter->second->getHeight() != src->getHeight()) // bump not cached yet or has changed resolution
+		if (iter->second->getWidth() != src->getWidth() ||
+			iter->second->getHeight() != src->getHeight()) // bump not cached yet or has changed resolution
 		{
 			LLPointer<LLImageRaw> dst_image = new LLImageRaw(src->getWidth(), src->getHeight(), 1);
 			U8* dst_data = dst_image->getData();
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index fa2c070ea06..e3ac56d0d39 100644
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -1619,7 +1619,6 @@ void LLViewerFetchedTexture::scheduleCreateTexture()
         mNeedsCreateTexture = TRUE;
         if (preCreateTexture())
         {
-            ref();
 #if LL_IMAGEGL_THREAD_CHECK
             //grab a copy of the raw image data to make sure it isn't modified pending texture creation
             U8* data = mRawImage->getData();
@@ -1635,6 +1634,7 @@ void LLViewerFetchedTexture::scheduleCreateTexture()
             auto mainq = LLImageGLThread::sEnabled ? mMainQueue.lock() : nullptr;
             if (mainq)
             {
+                ref();
                 mainq->postTo(
                     mImageQueue,
                     // work to be done on LLImageGL worker thread
@@ -1681,7 +1681,6 @@ void LLViewerFetchedTexture::scheduleCreateTexture()
             else
             {
                 gTextureList.mCreateTextureList.insert(this);
-                unref();
             }
         }
     }
-- 
GitLab