diff --git a/indra/llrender/lltexture.h b/indra/llrender/lltexture.h
index c18917b66346296b862584875fb58f9a34d1ccf8..0cd96676444b18222b33cc4bacb766b951c62367 100644
--- a/indra/llrender/lltexture.h
+++ b/indra/llrender/lltexture.h
@@ -61,6 +61,8 @@ class LLTexture : public LLRefCount
 	//
 	//interfaces to access LLViewerTexture
 	//
+	virtual S8         getType() const = 0 ;
+	virtual void       setKnownDrawSize(S32 width, S32 height) = 0 ;
 	virtual bool       bindDefaultImage(const S32 stage = 0) const = 0 ;
 	virtual void       forceImmediateUpdate() = 0 ;
 	virtual void       setActive() = 0 ;
diff --git a/indra/llui/lliconctrl.cpp b/indra/llui/lliconctrl.cpp
index 66c2ba682fc474b115c511c31c87ed0bd5ede5c5..82ffac9580f0fcba517492cd8f33704d6fc2df20 100644
--- a/indra/llui/lliconctrl.cpp
+++ b/indra/llui/lliconctrl.cpp
@@ -57,7 +57,9 @@ LLIconCtrl::LLIconCtrl(const LLIconCtrl::Params& p)
 :	LLUICtrl(p),
 	mColor(p.color()),
 	mImagep(p.image),
-	mPriority(0)
+	mPriority(0),
+	mDrawWidth(0),
+	mDrawHeight(0)
 {
 	if (mImagep.notNull())
 	{
@@ -100,6 +102,8 @@ void LLIconCtrl::setValue(const LLSD& value )
 	{
 		mImagep = LLUI::getUIImage(tvalue.asString(), mPriority);
 	}
+
+	setIconImageDrawSize();
 }
 
 std::string LLIconCtrl::getImageName() const
@@ -109,3 +113,14 @@ std::string LLIconCtrl::getImageName() const
 	else
 		return std::string();
 }
+
+void LLIconCtrl::setIconImageDrawSize()
+{
+	if(mImagep.notNull() && mDrawWidth && mDrawHeight)
+	{
+		if(mImagep->getImage().notNull())
+		{
+			mImagep->getImage()->setKnownDrawSize(mDrawWidth, mDrawHeight) ;
+		}
+	}
+}
\ No newline at end of file
diff --git a/indra/llui/lliconctrl.h b/indra/llui/lliconctrl.h
index 90f1693060475846f53eb0526a9390cf6f64a0e4..66368f979b6a74d9baedc8294fe1f6d5c6d6b844 100644
--- a/indra/llui/lliconctrl.h
+++ b/indra/llui/lliconctrl.h
@@ -60,6 +60,7 @@ class LLIconCtrl
 protected:
 	LLIconCtrl(const Params&);
 	friend class LLUICtrlFactory;
+
 public:
 	virtual ~LLIconCtrl();
 
@@ -73,9 +74,16 @@ class LLIconCtrl
 
 	void			setColor(const LLColor4& color) { mColor = color; }
 	
+private:
+	void setIconImageDrawSize() ;
+
 protected:
 	S32 mPriority;
 
+	//the output size of the icon image if set.
+	S32 mDrawWidth ;
+	S32 mDrawHeight ;
+
 private:
 	LLUIColor mColor;
 	LLPointer<LLUIImage> mImagep;
diff --git a/indra/newview/llavatariconctrl.cpp b/indra/newview/llavatariconctrl.cpp
index ebcda13dd495310df29805b485192122db4f353c..b56e8d1ec2546009a1dcf2d893cec0b5680dc9ef 100644
--- a/indra/newview/llavatariconctrl.cpp
+++ b/indra/newview/llavatariconctrl.cpp
@@ -155,6 +155,8 @@ LLAvatarIconCtrl::LLAvatarIconCtrl(const LLAvatarIconCtrl::Params& p)
 	mPriority = LLViewerFetchedTexture::BOOST_ICON;
 	
 	LLRect rect = p.rect;
+	mDrawWidth  = llmax(32, rect.getWidth()) ;
+	mDrawHeight = llmax(32, rect.getHeight()) ;
 
 	static LLUICachedControl<S32> llavatariconctrl_symbol_hpad("UIAvatariconctrlSymbolHPad", 2);
 	static LLUICachedControl<S32> llavatariconctrl_symbol_vpad("UIAvatariconctrlSymbolVPad", 2);
@@ -193,7 +195,6 @@ LLAvatarIconCtrl::LLAvatarIconCtrl(const LLAvatarIconCtrl::Params& p)
 		LLIconCtrl::setValue("default_profile_picture.j2c");
 	}
 
-
 	LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
 
 	registrar.add("AvatarIcon.Action", boost::bind(&LLAvatarIconCtrl::onAvatarIconContextMenuItemClicked, this, _2));
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index e5c53c91c90b03feff444d15dee23a9337dffedf..2368a2da33a4b70dc89dee5cd7ef688da3c8ce7b 100644
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -93,6 +93,7 @@ BOOL LLViewerTexture::sUseTextureAtlas        = FALSE ;
 
 const F32 desired_discard_bias_min = -2.0f; // -max number of levels to improve image quality by
 const F32 desired_discard_bias_max = 1.5f; // max number of levels to reduce image quality by
+const F64 log_2 = log(2.0);
 
 //----------------------------------------------------------------------------------------------
 //namespace: LLViewerTextureAccess
@@ -134,7 +135,7 @@ LLViewerMediaTexture*  LLViewerTextureManager::getMediaTexture(const LLUUID& id,
 	return tex ;
 }
 
-LLViewerFetchedTexture* LLViewerTextureManager::staticCastToFetchedTexture(LLViewerTexture* tex, BOOL report_error)
+LLViewerFetchedTexture* LLViewerTextureManager::staticCastToFetchedTexture(LLTexture* tex, BOOL report_error)
 {
 	if(!tex)
 	{
@@ -522,6 +523,12 @@ F32 LLViewerTexture::getMaxVirtualSize()
 	return mMaxVirtualSize ;
 }
 
+//virtual 
+void LLViewerTexture::setKnownDrawSize(S32 width, S32 height)
+{
+	//nothing here.
+}
+
 //virtual
 void LLViewerTexture::addFace(LLFace* facep) 
 {
@@ -852,6 +859,7 @@ void LLViewerFetchedTexture::init(bool firstinit)
 
 	mKnownDrawWidth = 0;
 	mKnownDrawHeight = 0;
+	mKnownDrawSizeChanged = FALSE ;
 
 	if (firstinit)
 	{
@@ -1084,10 +1092,17 @@ BOOL LLViewerFetchedTexture::createTexture(S32 usename/*= 0*/)
 }
 
 // Call with 0,0 to turn this feature off.
+//virtual
 void LLViewerFetchedTexture::setKnownDrawSize(S32 width, S32 height)
 {
-	mKnownDrawWidth = width;
-	mKnownDrawHeight = height;
+	if(mKnownDrawWidth != width || mKnownDrawHeight != height)
+	{
+		mKnownDrawWidth = width;
+		mKnownDrawHeight = height;
+
+		mKnownDrawSizeChanged = TRUE ;
+		mFullyLoaded = FALSE ;
+	}
 	addTextureStats((F32)(width * height));
 }
 
@@ -1104,13 +1119,26 @@ void LLViewerFetchedTexture::processTextureStats()
 		mDesiredDiscardLevel = 	getMaxDiscardLevel() ;
 	}
 	else
-	{
-		mDesiredDiscardLevel = 0;
-		if (mFullWidth > MAX_IMAGE_SIZE_DEFAULT || mFullHeight > MAX_IMAGE_SIZE_DEFAULT)
+	{	
+		if(!mKnownDrawWidth || !mKnownDrawHeight || mFullWidth <= mKnownDrawWidth || mFullHeight <= mKnownDrawHeight)
 		{
-			mDesiredDiscardLevel = 1; // MAX_IMAGE_SIZE_DEFAULT = 1024 and max size ever is 2048
+			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(mKnownDrawSizeChanged)//known draw size is set
+		{			
+			mDesiredDiscardLevel = (S8)llmin(log((F32)mFullWidth / mKnownDrawWidth) / log_2, 
+					                             log((F32)mFullHeight / mKnownDrawHeight) / log_2) ;
+			mDesiredDiscardLevel = 	llclamp(mDesiredDiscardLevel, (S8)0, (S8)getMaxDiscardLevel()) ;
+		}
+		mKnownDrawSizeChanged = FALSE ;
+		
 		if(getDiscardLevel() >= 0 && (getDiscardLevel() <= mDesiredDiscardLevel))
 		{
 			mFullyLoaded = TRUE ;
@@ -1121,8 +1149,6 @@ void LLViewerFetchedTexture::processTextureStats()
 //texture does not have any data, so we don't know the size of the image, treat it like 32 * 32.
 F32 LLViewerFetchedTexture::calcDecodePriorityForUnknownTexture(F32 pixel_priority)
 {
-	static const F64 log_2 = log(2.0);
-
 	F32 desired = (F32)(log(32.0/pixel_priority) / log_2);
 	S32 ddiscard = MAX_DISCARD_LEVEL - (S32)desired + 1;
 	ddiscard = llclamp(ddiscard, 1, 9);
@@ -1169,7 +1195,7 @@ F32 LLViewerFetchedTexture::calcDecodePriority()
 		// Don't decode anything we don't need
 		priority = -1.0f;
 	}
-	else if (mBoostLevel == LLViewerTexture::BOOST_UI && !have_all_data)
+	else if ((mBoostLevel == LLViewerTexture::BOOST_UI || mBoostLevel == LLViewerTexture::BOOST_ICON) && !have_all_data)
 	{
 		priority = 1.f;
 	}
diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h
index 480e1c1cbcc2d38bd429210f6e0fea26a85063ca..ef298319d2986953ef4d0ed2ce13de08578de942 100644
--- a/indra/newview/llviewertexture.h
+++ b/indra/newview/llviewertexture.h
@@ -163,6 +163,7 @@ class LLViewerTexture : public LLTexture
 	
 	S32 getFullWidth() const { return mFullWidth; }
 	S32 getFullHeight() const { return mFullHeight; }	
+	/*virtual*/ void setKnownDrawSize(S32 width, S32 height);
 
 	virtual void addFace(LLFace* facep) ;
 	virtual void removeFace(LLFace* facep) ; 
@@ -357,7 +358,7 @@ class LLViewerFetchedTexture : public LLViewerTexture
 	// Override the computation of discard levels if we know the exact output
 	// size of the image.  Used for UI textures to not decode, even if we have
 	// more data.
-	void setKnownDrawSize(S32 width, S32 height);
+	/*virtual*/ void setKnownDrawSize(S32 width, S32 height);
 
 	void setIsMissingAsset();
 	/*virtual*/ BOOL isMissingAsset()	const		{ return mIsMissingAsset; }
@@ -406,6 +407,8 @@ class LLViewerFetchedTexture : public LLViewerTexture
 	BOOL  mFullyLoaded;
 
 protected:		
+	std::string mLocalFileName;
+
 	S32 mOrigWidth;
 	S32 mOrigHeight;
 
@@ -413,8 +416,7 @@ class LLViewerFetchedTexture : public LLViewerTexture
 	// Used for UI textures to not decode, even if we have more data.
 	S32 mKnownDrawWidth;
 	S32	mKnownDrawHeight;
-
-	std::string mLocalFileName;
+	BOOL mKnownDrawSizeChanged ;
 
 	S8  mDesiredDiscardLevel;			// The discard level we'd LIKE to have - if we have it and there's space	
 	S8  mMinDesiredDiscardLevel;	// The minimum discard level we'd like to have
@@ -570,7 +572,7 @@ class LLViewerTextureManager
 	static LLTexturePipelineTester* sTesterp ;
 
 	//returns NULL if tex is not a LLViewerFetchedTexture nor derived from LLViewerFetchedTexture.
-	static LLViewerFetchedTexture*    staticCastToFetchedTexture(LLViewerTexture* tex, BOOL report_error = FALSE) ;
+	static LLViewerFetchedTexture*    staticCastToFetchedTexture(LLTexture* tex, BOOL report_error = FALSE) ;
 
 	//
 	//"find-texture" just check if the texture exists, if yes, return it, otherwise return null.