diff --git a/indra/llrender/llgltexture.cpp b/indra/llrender/llgltexture.cpp
index 7fdef4a3b7d87b8389a1c80e1e372bb70f38709d..b616002b49c74d41ef794b392937641107ea3265 100644
--- a/indra/llrender/llgltexture.cpp
+++ b/indra/llrender/llgltexture.cpp
@@ -94,7 +94,8 @@ void LLGLTexture::setBoostLevel(S32 level)
 	{
 		mBoostLevel = level ;
 		if(mBoostLevel != LLGLTexture::BOOST_NONE
-		   && mBoostLevel != LLGLTexture::BOOST_ICON)
+		   && mBoostLevel != LLGLTexture::BOOST_ICON
+           && mBoostLevel != LLGLTexture::BOOST_THUMBNAIL)
 		{
 			setNoDelete() ;		
 		}
diff --git a/indra/llrender/llgltexture.h b/indra/llrender/llgltexture.h
index 5c693fc93c12bea6b81ddba0a4449e825973f74b..24849d1d1bc41c1fe4e94cb75efbbc6203cc8b81 100644
--- a/indra/llrender/llgltexture.h
+++ b/indra/llrender/llgltexture.h
@@ -62,6 +62,7 @@ class LLGLTexture : public LLTexture
 		BOOST_SUPER_HIGH    , //textures higher than this need to be downloaded at the required resolution without delay.
 		BOOST_HUD			,
 		BOOST_ICON			,
+        BOOST_THUMBNAIL		,
 		BOOST_UI			,
 		BOOST_PREVIEW		,
 		BOOST_MAP			,
diff --git a/indra/newview/llthumbnailctrl.cpp b/indra/newview/llthumbnailctrl.cpp
index 04130fc724d755b2bce5c48a90d845629c63e006..72818cf991db814ebe7cb602c2a3eef7b406861f 100644
--- a/indra/newview/llthumbnailctrl.cpp
+++ b/indra/newview/llthumbnailctrl.cpp
@@ -57,7 +57,6 @@ LLThumbnailCtrl::LLThumbnailCtrl(const LLThumbnailCtrl::Params& p)
 ,   mFallbackImagep(p.fallback_image)
 ,   mInteractable(p.interactable())
 ,   mShowLoadingPlaceholder(p.show_loading())
-,	mPriority(LLGLTexture::BOOST_PREVIEW)
 {
     mLoadingPlaceholderString = LLTrans::getString("texture_loading");
     
@@ -201,9 +200,8 @@ void LLThumbnailCtrl::setValue(const LLSD& value)
         if (mImageAssetID.notNull())
         {
             // Should it support baked textures?
-            mTexturep = LLViewerTextureManager::getFetchedTexture(mImageAssetID, FTT_DEFAULT, MIPMAP_YES, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
+            mTexturep = LLViewerTextureManager::getFetchedTexture(mImageAssetID, FTT_DEFAULT, MIPMAP_YES, LLGLTexture::BOOST_THUMBNAIL);
             
-            mTexturep->setBoostLevel(mPriority);
             mTexturep->forceToSaveRawImage(0);
             
             S32 desired_draw_width = mTexturep->getWidth();
diff --git a/indra/newview/llthumbnailctrl.h b/indra/newview/llthumbnailctrl.h
index 686603b37300c4c4993764d2f421a62d65dfa390..70f56c429cf1dfe7ebcfed77c1587f0f202eec3a 100644
--- a/indra/newview/llthumbnailctrl.h
+++ b/indra/newview/llthumbnailctrl.h
@@ -71,7 +71,6 @@ class LLThumbnailCtrl
     virtual BOOL handleHover(S32 x, S32 y, MASK mask) override;
 	
 private:
-	S32 mPriority;
     bool mBorderVisible;
     bool mInteractable;
     bool mShowLoadingPlaceholder;
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index 4a1cf0109e50e41584ef43c6baff2223db14d496..ec6f2c848fd6711bf02f7e84531671a05e711a84 100644
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -93,7 +93,8 @@ 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;
+const S32 DEFAULT_ICON_DIMENSIONS = 32;
+const S32 DEFAULT_THUMBNAIL_DIMENSIONS = 256;
 U32 LLViewerTexture::sMinLargeImageSize = 65536; //256 * 256.
 U32 LLViewerTexture::sMaxSmallImageSize = MAX_CACHED_RAW_IMAGE_AREA;
 bool LLViewerTexture::sFreezeImageUpdates = false;
@@ -665,7 +666,8 @@ void LLViewerTexture::setBoostLevel(S32 level)
 		mBoostLevel = level;
 		if(mBoostLevel != LLViewerTexture::BOOST_NONE && 
 			mBoostLevel != LLViewerTexture::BOOST_SELECTED && 
-			mBoostLevel != LLViewerTexture::BOOST_ICON)
+			mBoostLevel != LLViewerTexture::BOOST_ICON &&
+            mBoostLevel != LLViewerTexture::BOOST_THUMBNAIL)
 		{
 			setNoDelete();		
 		}
@@ -1180,8 +1182,19 @@ void LLViewerFetchedTexture::loadFromFastCache()
             {
                 // Shouldn't do anything usefull since texures in fast cache are 16x16,
                 // it is here in case fast cache changes.
-                S32 expected_width = mKnownDrawWidth > 0 ? mKnownDrawWidth : DEFAULT_ICON_DIMENTIONS;
-                S32 expected_height = mKnownDrawHeight > 0 ? mKnownDrawHeight : DEFAULT_ICON_DIMENTIONS;
+                S32 expected_width = mKnownDrawWidth > 0 ? mKnownDrawWidth : DEFAULT_ICON_DIMENSIONS;
+                S32 expected_height = mKnownDrawHeight > 0 ? mKnownDrawHeight : DEFAULT_ICON_DIMENSIONS;
+                if (mRawImage && (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);
+                }
+            }
+
+            if (mBoostLevel == LLGLTexture::BOOST_THUMBNAIL)
+            {
+                S32 expected_width = mKnownDrawWidth > 0 ? mKnownDrawWidth : DEFAULT_THUMBNAIL_DIMENSIONS;
+                S32 expected_height = mKnownDrawHeight > 0 ? mKnownDrawHeight : DEFAULT_THUMBNAIL_DIMENSIONS;
                 if (mRawImage && (mRawImage->getWidth() > expected_width || mRawImage->getHeight() > expected_height))
                 {
                     // scale oversized icon, no need to give more work to gl
@@ -1682,7 +1695,7 @@ void LLViewerFetchedTexture::processTextureStats()
 		{
 			mDesiredDiscardLevel = 0;
 		}
-        else if (mDontDiscard && mBoostLevel == LLGLTexture::BOOST_ICON)
+        else if (mDontDiscard && (mBoostLevel == LLGLTexture::BOOST_ICON || mBoostLevel == LLGLTexture::BOOST_THUMBNAIL))
         {
             if (mFullWidth > MAX_IMAGE_SIZE_DEFAULT || mFullHeight > MAX_IMAGE_SIZE_DEFAULT)
             {
@@ -1916,8 +1929,20 @@ bool LLViewerFetchedTexture::updateFetch()
 
                 if (mBoostLevel == LLGLTexture::BOOST_ICON)
                 {
-                    S32 expected_width = mKnownDrawWidth > 0 ? mKnownDrawWidth : DEFAULT_ICON_DIMENTIONS;
-                    S32 expected_height = mKnownDrawHeight > 0 ? mKnownDrawHeight : DEFAULT_ICON_DIMENTIONS;
+                    S32 expected_width = mKnownDrawWidth > 0 ? mKnownDrawWidth : DEFAULT_ICON_DIMENSIONS;
+                    S32 expected_height = mKnownDrawHeight > 0 ? mKnownDrawHeight : DEFAULT_ICON_DIMENSIONS;
+                    if (mRawImage && (mRawImage->getWidth() > expected_width || mRawImage->getHeight() > expected_height))
+                    {
+                        // scale oversized icon, no need to give more work to gl
+                        // since we got mRawImage from thread worker and image may be in use (ex: writing cache), make a copy
+                        mRawImage = mRawImage->scaled(expected_width, expected_height);
+                    }
+                }
+
+                if (mBoostLevel == LLGLTexture::BOOST_THUMBNAIL)
+                {
+                    S32 expected_width = mKnownDrawWidth > 0 ? mKnownDrawWidth : DEFAULT_THUMBNAIL_DIMENSIONS;
+                    S32 expected_height = mKnownDrawHeight > 0 ? mKnownDrawHeight : DEFAULT_THUMBNAIL_DIMENSIONS;
                     if (mRawImage && (mRawImage->getWidth() > expected_width || mRawImage->getHeight() > expected_height))
                     {
                         // scale oversized icon, no need to give more work to gl
@@ -2652,7 +2677,9 @@ LLImageRaw* LLViewerFetchedTexture::reloadRawImage(S8 discard_level)
 
 	if(mSavedRawDiscardLevel >= 0 && mSavedRawDiscardLevel <= discard_level)
 	{
-		if (mSavedRawDiscardLevel != discard_level && mBoostLevel != BOOST_ICON)
+		if (mSavedRawDiscardLevel != discard_level
+            && mBoostLevel != BOOST_ICON
+            && mBoostLevel != BOOST_THUMBNAIL)
 		{
 			mRawImage = new LLImageRaw(getWidth(discard_level), getHeight(discard_level), getComponents());
 			mRawImage->copy(getSavedRawImage());
@@ -2759,8 +2786,22 @@ void LLViewerFetchedTexture::setCachedRawImage(S32 discard_level, LLImageRaw* im
     {
         if (mBoostLevel == LLGLTexture::BOOST_ICON)
         {
-            S32 expected_width = mKnownDrawWidth > 0 ? mKnownDrawWidth : DEFAULT_ICON_DIMENTIONS;
-            S32 expected_height = mKnownDrawHeight > 0 ? mKnownDrawHeight : DEFAULT_ICON_DIMENTIONS;
+            S32 expected_width = mKnownDrawWidth > 0 ? mKnownDrawWidth : DEFAULT_ICON_DIMENSIONS;
+            S32 expected_height = mKnownDrawHeight > 0 ? mKnownDrawHeight : DEFAULT_ICON_DIMENSIONS;
+            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 if (mBoostLevel == LLGLTexture::BOOST_THUMBNAIL)
+        {
+            S32 expected_width = mKnownDrawWidth > 0 ? mKnownDrawWidth : DEFAULT_THUMBNAIL_DIMENSIONS;
+            S32 expected_height = mKnownDrawHeight > 0 ? mKnownDrawHeight : DEFAULT_THUMBNAIL_DIMENSIONS;
             if (mRawImage->getWidth() > expected_width || mRawImage->getHeight() > expected_height)
             {
                 mCachedRawImage = new LLImageRaw(expected_width, expected_height, imageraw->getComponents());
@@ -2867,8 +2908,22 @@ void LLViewerFetchedTexture::saveRawImage()
 	mSavedRawDiscardLevel = mRawDiscardLevel;
     if (mBoostLevel == LLGLTexture::BOOST_ICON)
     {
-        S32 expected_width = mKnownDrawWidth > 0 ? mKnownDrawWidth : DEFAULT_ICON_DIMENTIONS;
-        S32 expected_height = mKnownDrawHeight > 0 ? mKnownDrawHeight : DEFAULT_ICON_DIMENTIONS;
+        S32 expected_width = mKnownDrawWidth > 0 ? mKnownDrawWidth : DEFAULT_ICON_DIMENSIONS;
+        S32 expected_height = mKnownDrawHeight > 0 ? mKnownDrawHeight : DEFAULT_ICON_DIMENSIONS;
+        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 if (mBoostLevel == LLGLTexture::BOOST_THUMBNAIL)
+    {
+        S32 expected_width = mKnownDrawWidth > 0 ? mKnownDrawWidth : DEFAULT_THUMBNAIL_DIMENSIONS;
+        S32 expected_height = mKnownDrawHeight > 0 ? mKnownDrawHeight : DEFAULT_THUMBNAIL_DIMENSIONS;
         if (mRawImage->getWidth() > expected_width || mRawImage->getHeight() > expected_height)
         {
             mSavedRawImage = new LLImageRaw(expected_width, expected_height, mRawImage->getComponents());
diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp
index 9ee6f88183fd04c75bbca89dd62ffbfce4460202..f898fb714258f6e119a6edcd79a30748f51f28b2 100644
--- a/indra/newview/llviewertexturelist.cpp
+++ b/indra/newview/llviewertexturelist.cpp
@@ -72,7 +72,7 @@ LLViewerTextureList gTextureList;
 
 ETexListType get_element_type(S32 priority)
 {
-    return (priority == LLViewerFetchedTexture::BOOST_ICON) ? TEX_LIST_SCALE : TEX_LIST_STANDARD;
+    return (priority == LLViewerFetchedTexture::BOOST_ICON || priority == LLViewerFetchedTexture::BOOST_THUMBNAIL) ? TEX_LIST_SCALE : TEX_LIST_STANDARD;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -492,7 +492,8 @@ LLViewerFetchedTexture* LLViewerTextureList::getImageFromUrl(const std::string&
 			{
 				imagep->dontDiscard();
 			}
-			if (boost_priority == LLViewerFetchedTexture::BOOST_ICON)
+			if (boost_priority == LLViewerFetchedTexture::BOOST_ICON
+                || boost_priority == LLViewerFetchedTexture::BOOST_THUMBNAIL)
 			{
 				// Agent and group Icons are downloadable content, nothing manages
 				// icon deletion yet, so they should not persist
@@ -604,7 +605,8 @@ LLViewerFetchedTexture* LLViewerTextureList::createImage(const LLUUID &image_id,
 		{
 			imagep->dontDiscard();
 		}
-		if (boost_priority == LLViewerFetchedTexture::BOOST_ICON)
+		if (boost_priority == LLViewerFetchedTexture::BOOST_ICON
+            || boost_priority == LLViewerFetchedTexture::BOOST_THUMBNAIL)
 		{
 			// Agent and group Icons are downloadable content, nothing manages
 			// icon deletion yet, so they should not persist.
@@ -1510,8 +1512,9 @@ LLUIImagePtr LLUIImageList::loadUIImage(LLViewerFetchedTexture* imagep, const st
 	LLUIImagePtr new_imagep = new LLUIImage(name, imagep);
 	new_imagep->setScaleStyle(scale_style);
 
-	if (imagep->getBoostLevel() != LLGLTexture::BOOST_ICON &&
-		imagep->getBoostLevel() != LLGLTexture::BOOST_PREVIEW)
+	if (imagep->getBoostLevel() != LLGLTexture::BOOST_ICON
+        && imagep->getBoostLevel() != LLGLTexture::BOOST_THUMBNAIL
+		&& imagep->getBoostLevel() != LLGLTexture::BOOST_PREVIEW)
 	{
 		// Don't add downloadable content into this list
 		// all UI images are non-deletable and list does not support deletion