From cdb3c018af9fc75064dc63537e61c5df567c331a Mon Sep 17 00:00:00 2001
From: Rye Mutt <rye@alchemyviewer.org>
Date: Wed, 1 Mar 2023 10:26:34 -0500
Subject: [PATCH] SL-19336 Unload avatar and group icons from memory when not
 visible to reduce memory pressure on extremely large friends lists

---
 doc/contributions.txt     |  1 +
 indra/llui/lliconctrl.cpp | 26 ++++++++++++++++++++++++++
 indra/llui/lliconctrl.h   |  3 +++
 indra/llui/lltextbase.cpp |  4 ++--
 indra/llui/llview.h       |  1 +
 5 files changed, 33 insertions(+), 2 deletions(-)

diff --git a/doc/contributions.txt b/doc/contributions.txt
index 4c56ef86dca..90e1bba3137 100755
--- a/doc/contributions.txt
+++ b/doc/contributions.txt
@@ -1397,6 +1397,7 @@ Sovereign Engineer
     SL-18497
     SL-18525
     SL-18534
+    SL-19336
 SpacedOut Frye
 	VWR-34
 	VWR-45
diff --git a/indra/llui/lliconctrl.cpp b/indra/llui/lliconctrl.cpp
index e01aba402e5..2791377a5ef 100644
--- a/indra/llui/lliconctrl.cpp
+++ b/indra/llui/lliconctrl.cpp
@@ -37,6 +37,8 @@
 #include "lluiimage.h"
 #include "llwindow.h"
 
+#include "llgltexture.h"
+
 static LLDefaultChildRegistry::Register<LLIconCtrl> r("icon");
 
 LLIconCtrl::Params::Params()
@@ -94,6 +96,22 @@ BOOL LLIconCtrl::handleHover(S32 x, S32 y, MASK mask)
     return LLUICtrl::handleHover(x, y, mask);
 }
 
+void LLIconCtrl::onVisibilityChange(BOOL new_visibility)
+{
+	LLUICtrl::onVisibilityChange(new_visibility);
+	if (mPriority == LLGLTexture::BOOST_ICON)
+	{
+		if (new_visibility)
+		{
+			loadImage(getValue(), mPriority);
+		}
+		else
+		{
+			mImagep = nullptr;
+		}
+	}
+}
+
 // virtual
 // value might be a string or a UUID
 void LLIconCtrl::setValue(const LLSD& value)
@@ -110,6 +128,14 @@ void LLIconCtrl::setValue(const LLSD& value, S32 priority)
 		tvalue = LLSD(LLUUID(value.asString()));
 	}
 	LLUICtrl::setValue(tvalue);
+
+	loadImage(tvalue, priority);
+}
+
+void LLIconCtrl::loadImage(const LLSD& tvalue, S32 priority)
+{
+	if(mPriority == LLGLTexture::BOOST_ICON && !getVisible()) return;
+
 	if (tvalue.isUUID())
 	{
         mImagep = LLUI::getUIImageByID(tvalue.asUUID(), priority);
diff --git a/indra/llui/lliconctrl.h b/indra/llui/lliconctrl.h
index 9c3b517bca8..5d6c544571e 100644
--- a/indra/llui/lliconctrl.h
+++ b/indra/llui/lliconctrl.h
@@ -72,6 +72,7 @@ class LLIconCtrl
     virtual BOOL handleHover(S32 x, S32 y, MASK mask);
 
 	// lluictrl overrides
+	void onVisibilityChange(BOOL new_visibility);
 	virtual void	setValue(const LLSD& value );
 
 	std::string	getImageName() const;
@@ -95,6 +96,8 @@ class LLIconCtrl
     bool mInteractable;
 
 private:
+	void loadImage(const LLSD& value, S32 priority);
+
 	LLUIColor mColor;
 	LLPointer<LLUIImage> mImagep;
 };
diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp
index 82a3c01c6d9..3d8cf74855d 100644
--- a/indra/llui/lltextbase.cpp
+++ b/indra/llui/lltextbase.cpp
@@ -1356,9 +1356,9 @@ void LLTextBase::draw()
 		drawCursor();
 	}
  
-	mDocumentView->setVisible(FALSE);
+	mDocumentView->setVisibleDirect(FALSE);
 	LLUICtrl::draw();
-	mDocumentView->setVisible(TRUE);
+	mDocumentView->setVisibleDirect(TRUE);
 }
 
 
diff --git a/indra/llui/llview.h b/indra/llui/llview.h
index bec45df78a9..8aa97aac397 100644
--- a/indra/llui/llview.h
+++ b/indra/llui/llview.h
@@ -287,6 +287,7 @@ class LLView
 	void 	setAllChildrenEnabled(BOOL b);
 
 	virtual void	setVisible(BOOL visible);
+	void			setVisibleDirect(BOOL visible) { mVisible = visible; }
 	const BOOL&		getVisible() const			{ return mVisible; }
 	virtual void	setEnabled(BOOL enabled);
 	BOOL			getEnabled() const			{ return mEnabled; }
-- 
GitLab