From a53caef1e8314f9cf2af3c0081bf57d5f20db560 Mon Sep 17 00:00:00 2001
From: andreykproductengine <akleshchev@productengine.com>
Date: Wed, 9 Dec 2015 18:35:36 +0200
Subject: [PATCH] MAINT-4018 Improvements to icon fetching.

---
 indra/llui/lliconctrl.cpp          | 14 +++++-
 indra/llui/lliconctrl.h            |  4 +-
 indra/newview/llavatariconctrl.cpp | 36 ++------------
 indra/newview/llgroupiconctrl.cpp  | 11 ++++-
 indra/newview/llviewertexture.cpp  | 76 ++++++++++++++++++++++++++++--
 5 files changed, 102 insertions(+), 39 deletions(-)

diff --git a/indra/llui/lliconctrl.cpp b/indra/llui/lliconctrl.cpp
index 58b66f60caa..f8419018014 100755
--- a/indra/llui/lliconctrl.cpp
+++ b/indra/llui/lliconctrl.cpp
@@ -54,7 +54,9 @@ LLIconCtrl::LLIconCtrl(const LLIconCtrl::Params& p)
 	mUseDrawContextAlpha(p.use_draw_context_alpha),
 	mPriority(0),
 	mMinWidth(p.min_width),
-	mMinHeight(p.min_height)
+	mMinHeight(p.min_height),
+	mMaxWidth(0),
+	mMaxHeight(0)
 {
 	if (mImagep.notNull())
 	{
@@ -104,7 +106,15 @@ void LLIconCtrl::setValue(const LLSD& value )
 		&& mMinWidth 
 		&& mMinHeight)
 	{
-		mImagep->getImage()->setKnownDrawSize(llmax(mMinWidth, mImagep->getWidth()), llmax(mMinHeight, mImagep->getHeight()));
+        S32 desired_draw_width = llmax(mMinWidth, mImagep->getWidth());
+        S32 desired_draw_height = llmax(mMinHeight, mImagep->getHeight());
+        if (mMaxWidth && mMaxHeight)
+        {
+            desired_draw_width = llmin(desired_draw_width, mMaxWidth);
+            desired_draw_height = llmin(desired_draw_height, mMaxHeight);
+        }
+
+        mImagep->getImage()->setKnownDrawSize(desired_draw_width, desired_draw_height);
 	}
 }
 
diff --git a/indra/llui/lliconctrl.h b/indra/llui/lliconctrl.h
index 8b1092df46f..7971cd44d3b 100755
--- a/indra/llui/lliconctrl.h
+++ b/indra/llui/lliconctrl.h
@@ -79,7 +79,9 @@ class LLIconCtrl
 
 	//the output size of the icon image if set.
 	S32 mMinWidth,
-		mMinHeight;
+		mMinHeight,
+		mMaxWidth,
+		mMaxHeight;
 
 	// If set to true (default), use the draw context transparency.
 	// If false, will use transparency returned by getCurrentTransparency(). See STORM-698.
diff --git a/indra/newview/llavatariconctrl.cpp b/indra/newview/llavatariconctrl.cpp
index 25a5df97819..932326acaeb 100755
--- a/indra/newview/llavatariconctrl.cpp
+++ b/indra/newview/llavatariconctrl.cpp
@@ -182,38 +182,12 @@ LLAvatarIconCtrl::LLAvatarIconCtrl(const LLAvatarIconCtrl::Params& p)
 	mSymbolPos(p.symbol_pos)
 {
 	mPriority = LLViewerFetchedTexture::BOOST_ICON;
-	
-	LLRect rect = p.rect;
-
-	// BottomRight is the default position
-	S32 left = rect.getWidth() - mSymbolSize - mSymbolHpad;
-	S32 bottom = mSymbolVpad;
 
-	switch(mSymbolPos)
-	{
-	case LLAvatarIconCtrlEnums::BOTTOM_LEFT:
-	{
-		left = mSymbolHpad;
-		bottom = mSymbolVpad;
-	}
-
-	case LLAvatarIconCtrlEnums::TOP_LEFT:
-	{
-		left = mSymbolHpad;
-		bottom = rect.getHeight() - mSymbolSize - mSymbolVpad;
-	}
-
-	case LLAvatarIconCtrlEnums::TOP_RIGHT:
-	{
-		left = rect.getWidth() - mSymbolSize - mSymbolHpad;
-		bottom = rect.getHeight() - mSymbolSize - mSymbolVpad;
-	}
-
-	case LLAvatarIconCtrlEnums::BOTTOM_RIGHT:
-		// fallthrough, is default
-	default:
-		rect.setOriginAndSize(left, bottom, mSymbolSize, mSymbolSize);
-	}
+    // don't request larger image then necessary to save gl memory,
+    // but ensure that quality is sufficient
+    LLRect rect = p.rect;
+    mMaxHeight = llmax((S32)p.min_height, rect.getHeight());
+    mMaxWidth = llmax((S32)p.min_width, rect.getWidth());
 
 	if (p.avatar_id.isProvided())
 	{
diff --git a/indra/newview/llgroupiconctrl.cpp b/indra/newview/llgroupiconctrl.cpp
index 6abf9ea6376..1974a073dd5 100755
--- a/indra/newview/llgroupiconctrl.cpp
+++ b/indra/newview/llgroupiconctrl.cpp
@@ -37,7 +37,10 @@ LLGroupIconCtrl::Params::Params()
 :	group_id("group_id"),
 	draw_tooltip("draw_tooltip", true),
 	default_icon_name("default_icon_name")
-{}
+{
+    changeDefault(min_width, 32);
+    changeDefault(min_height, 32);
+}
 
 
 LLGroupIconCtrl::LLGroupIconCtrl(const LLGroupIconCtrl::Params& p)
@@ -48,6 +51,12 @@ LLGroupIconCtrl::LLGroupIconCtrl(const LLGroupIconCtrl::Params& p)
 {
 	mPriority = LLViewerFetchedTexture::BOOST_ICON;
 
+    // don't request larger image then necessary to save gl memory,
+    // but ensure that quality is sufficient
+    LLRect rect = p.rect;
+    mMaxHeight = llmax((S32)p.min_height, rect.getHeight());
+    mMaxWidth = llmax((S32)p.min_width, rect.getWidth());
+
 	if (p.group_id.isProvided())
 	{
 		LLSD value(p.group_id);
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index a957367f61e..c8c71b74b73 100755
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -97,6 +97,7 @@ S32 LLViewerTexture::sMaxSculptRez = 128; //max sculpt image size
 const S32 MAX_CACHED_RAW_IMAGE_AREA = 64 * 64;
 const S32 MAX_CACHED_RAW_SCULPT_IMAGE_AREA = LLViewerTexture::sMaxSculptRez * LLViewerTexture::sMaxSculptRez;
 const S32 MAX_CACHED_RAW_TERRAIN_IMAGE_AREA = 128 * 128;
+const S32 DEFAULT_ICON_DIMENTIONS = 32;
 S32 LLViewerTexture::sMinLargeImageSize = 65536; //256 * 256.
 S32 LLViewerTexture::sMaxSmallImageSize = MAX_CACHED_RAW_IMAGE_AREA;
 BOOL LLViewerTexture::sFreezeImageScalingDown = FALSE;
@@ -1178,6 +1179,17 @@ void LLViewerFetchedTexture::loadFromFastCache()
 		}
 		else
 		{
+            if (mBoostLevel == LLGLTexture::BOOST_ICON)
+            {
+                S32 expected_width = mKnownDrawWidth > 0 ? mKnownDrawWidth : DEFAULT_ICON_DIMENTIONS;
+                S32 expected_height = mKnownDrawHeight > 0 ? mKnownDrawHeight : DEFAULT_ICON_DIMENTIONS;
+                if (mRawImage->getWidth() > expected_width || mRawImage->getHeight() > expected_height)
+                {
+                    // scale oversized icon, no need to give more work to gl
+                    mRawImage->scale(expected_width, expected_height);
+                }
+            }
+
 			mRequestedDiscardLevel = mDesiredDiscardLevel + 1;
 			mIsRawImageValid = TRUE;			
 			addToCreateTexture();
@@ -1506,6 +1518,17 @@ void LLViewerFetchedTexture::processTextureStats()
 		{
 			mDesiredDiscardLevel = 0;
 		}
+        else if (mDontDiscard && mBoostLevel == LLGLTexture::BOOST_ICON)
+        {
+            if (mFullWidth > MAX_IMAGE_SIZE_DEFAULT || mFullHeight > MAX_IMAGE_SIZE_DEFAULT)
+            {
+                mDesiredDiscardLevel = 1; // MAX_IMAGE_SIZE_DEFAULT = 1024 and max size ever is 2048
+            }
+            else
+            {
+                mDesiredDiscardLevel = 0;
+            }
+        }
 		else if(!mFullWidth || !mFullHeight)
 		{
 			mDesiredDiscardLevel = 	llmin(getMaxDiscardLevel(), (S32)mLoadedCallbackDesiredDiscardLevel);
@@ -1936,6 +1959,17 @@ bool LLViewerFetchedTexture::updateFetch()
 					addToCreateTexture();
 				}
 
+                if (mBoostLevel == LLGLTexture::BOOST_ICON)
+                {
+                    S32 expected_width = mKnownDrawWidth > 0 ? mKnownDrawWidth : DEFAULT_ICON_DIMENTIONS;
+                    S32 expected_height = mKnownDrawHeight > 0 ? mKnownDrawHeight : DEFAULT_ICON_DIMENTIONS;
+                    if (mRawImage->getWidth() > expected_width || mRawImage->getHeight() > expected_height)
+                    {
+                        // scale oversized icon, no need to give more work to gl
+                        mRawImage->scale(expected_width, expected_height);
+                    }
+                }
+
 				return TRUE;
 			}
 			else
@@ -2670,7 +2704,7 @@ LLImageRaw* LLViewerFetchedTexture::reloadRawImage(S8 discard_level)
 
 	if(mSavedRawDiscardLevel >= 0 && mSavedRawDiscardLevel <= discard_level)
 	{
-		if(mSavedRawDiscardLevel != discard_level)
+		if (mSavedRawDiscardLevel != discard_level && mBoostLevel != BOOST_ICON)
 		{
 			mRawImage = new LLImageRaw(getWidth(discard_level), getHeight(discard_level), getComponents());
 			mRawImage->copy(getSavedRawImage());
@@ -2771,8 +2805,25 @@ void LLViewerFetchedTexture::switchToCachedImage()
 void LLViewerFetchedTexture::setCachedRawImage(S32 discard_level, LLImageRaw* imageraw) 
 {
 	if(imageraw != mRawImage.get())
-	{
-		mCachedRawImage = imageraw;
+    {
+        if (mBoostLevel == LLGLTexture::BOOST_ICON)
+        {
+            S32 expected_width = mKnownDrawWidth > 0 ? mKnownDrawWidth : DEFAULT_ICON_DIMENTIONS;
+            S32 expected_height = mKnownDrawHeight > 0 ? mKnownDrawHeight : DEFAULT_ICON_DIMENTIONS;
+            if (mRawImage->getWidth() > expected_width || mRawImage->getHeight() > expected_height)
+            {
+                mCachedRawImage = new LLImageRaw(expected_width, expected_height, imageraw->getComponents());
+                mCachedRawImage->copyScaled(imageraw);
+            }
+            else
+            {
+                mCachedRawImage = imageraw;
+            }
+        }
+        else
+        {
+            mCachedRawImage = imageraw;
+        }
 		mCachedRawDiscardLevel = discard_level;
 		mCachedRawImageReady = TRUE;
 	}
@@ -2862,7 +2913,24 @@ void LLViewerFetchedTexture::saveRawImage()
 	}
 
 	mSavedRawDiscardLevel = mRawDiscardLevel;
-	mSavedRawImage = new LLImageRaw(mRawImage->getData(), mRawImage->getWidth(), mRawImage->getHeight(), mRawImage->getComponents());
+    if (mBoostLevel == LLGLTexture::BOOST_ICON)
+    {
+        S32 expected_width = mKnownDrawWidth > 0 ? mKnownDrawWidth : DEFAULT_ICON_DIMENTIONS;
+        S32 expected_height = mKnownDrawHeight > 0 ? mKnownDrawHeight : DEFAULT_ICON_DIMENTIONS;
+        if (mRawImage->getWidth() > expected_width || mRawImage->getHeight() > expected_height)
+        {
+            mSavedRawImage = new LLImageRaw(expected_width, expected_height, mRawImage->getComponents());
+            mSavedRawImage->copyScaled(mRawImage);
+        }
+        else
+        {
+            mSavedRawImage = new LLImageRaw(mRawImage->getData(), mRawImage->getWidth(), mRawImage->getHeight(), mRawImage->getComponents());
+        }
+    }
+    else
+    {
+        mSavedRawImage = new LLImageRaw(mRawImage->getData(), mRawImage->getWidth(), mRawImage->getHeight(), mRawImage->getComponents());
+    }
 
 	if(mForceToSaveRawImage && mSavedRawDiscardLevel <= mDesiredSavedRawDiscardLevel)
 	{
-- 
GitLab