From a0e9ee475758c1825ba4a0957f4047e1dc24c8a3 Mon Sep 17 00:00:00 2001
From: andreykproductengine <akleshchev@productengine.com>
Date: Tue, 16 Feb 2016 20:44:53 +0200
Subject: MAINT-2199 separating UI elements from in-world textures.

---
 indra/newview/lllocalbitmaps.cpp      |  10 ++--
 indra/newview/llpanelface.cpp         |   2 +-
 indra/newview/lltexturefetch.cpp      | 103 +++++++++++++++++++++------------
 indra/newview/lltexturefetch.h        |   2 +-
 indra/newview/llviewertexture.cpp     |  68 ++++++++++++++--------
 indra/newview/llviewertexture.h       |   9 ++-
 indra/newview/llviewertexturelist.cpp | 106 ++++++++++++++++++++++++----------
 indra/newview/llviewertexturelist.h   |  34 +++++++++--
 indra/newview/llvoavatar.cpp          |   8 +--
 9 files changed, 231 insertions(+), 111 deletions(-)

(limited to 'indra/newview')

diff --git a/indra/newview/lllocalbitmaps.cpp b/indra/newview/lllocalbitmaps.cpp
index 46c1ffa789..766b1e3eaf 100755
--- a/indra/newview/lllocalbitmaps.cpp
+++ b/indra/newview/lllocalbitmaps.cpp
@@ -135,7 +135,7 @@ LLLocalBitmap::~LLLocalBitmap()
 	}
 
 	// delete self from gimagelist
-	LLViewerFetchedTexture* image = gTextureList.findImage(mWorldID);
+	LLViewerFetchedTexture* image = gTextureList.findImage(mWorldID, false);
 	gTextureList.deleteImage(image);
 
 	if (image)
@@ -207,7 +207,7 @@ bool LLLocalBitmap::updateSelf(EUpdateType optional_firstupdate)
 					texture->setCachedRawImage(LL_LOCAL_DISCARD_LEVEL, raw_image);
 					texture->ref(); 
 
-					gTextureList.addImage(texture);
+					gTextureList.addImage(texture, false);
 			
 					if (optional_firstupdate != UT_FIRSTUSE)
 					{
@@ -215,7 +215,7 @@ bool LLLocalBitmap::updateSelf(EUpdateType optional_firstupdate)
 						replaceIDs(old_id, mWorldID);
 
 						// remove old_id from gimagelist
-						LLViewerFetchedTexture* image = gTextureList.findImage(old_id);
+						LLViewerFetchedTexture* image = gTextureList.findImage(old_id, false);
 						if (image != NULL)
 						{
 							gTextureList.deleteImage(image);
@@ -384,7 +384,7 @@ void LLLocalBitmap::replaceIDs(LLUUID old_id, LLUUID new_id)
 std::vector<LLViewerObject*> LLLocalBitmap::prepUpdateObjects(LLUUID old_id, U32 channel)
 {
 	std::vector<LLViewerObject*> obj_list;
-	LLViewerFetchedTexture* old_texture = gTextureList.findImage(old_id);
+	LLViewerFetchedTexture* old_texture = gTextureList.findImage(old_id, false);
 
 	for(U32 face_iterator = 0; face_iterator < old_texture->getNumFaces(channel); face_iterator++)
 	{
@@ -502,7 +502,7 @@ void LLLocalBitmap::updateUserPrims(LLUUID old_id, LLUUID new_id, U32 channel)
 
 void LLLocalBitmap::updateUserSculpts(LLUUID old_id, LLUUID new_id)
 {
-	LLViewerFetchedTexture* old_texture = gTextureList.findImage(old_id);
+	LLViewerFetchedTexture* old_texture = gTextureList.findImage(old_id, false);
 	for(U32 volume_iter = 0; volume_iter < old_texture->getNumVolumes(); volume_iter++)
 	{
 		LLVOVolume* volume_to_object = (*old_texture->getVolumeList())[volume_iter];
diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp
index 21d8b4248c..58da73727a 100755
--- a/indra/newview/llpanelface.cpp
+++ b/indra/newview/llpanelface.cpp
@@ -2214,7 +2214,7 @@ void LLPanelFace::LLSelectedTE::getTexId(LLUUID& id, bool& identical)
 				LLTextureEntry *te = object->getTE(te_index);
 				if (te)
 				{
-					LLViewerTexture* tex = te->getID().notNull() ? gTextureList.findImage(te->getID()) : NULL;
+					LLViewerTexture* tex = te->getID().notNull() ? gTextureList.findImage(te->getID(), false) : NULL;
 					if(!tex)
 					{
 						tex = LLViewerFetchedTexture::sDefaultImagep;
diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp
index 17b273f316..f845ecc455 100755
--- a/indra/newview/lltexturefetch.cpp
+++ b/indra/newview/lltexturefetch.cpp
@@ -2066,11 +2066,18 @@ void LLTextureFetchWorker::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRe
 			
 	if (log_texture_traffic && data_size > 0)
 	{
-		LLViewerTexture* tex = LLViewerTextureManager::findTexture(mID);
-		if (tex)
-		{
-			gTotalTextureBytesPerBoostLevel[tex->getBoostLevel()] += data_size ;
-		}
+        // one worker per multiple textures
+        std::vector<LLViewerTexture*> textures;
+        LLViewerTextureManager::findTextures(mID, textures);
+        std::vector<LLViewerTexture*>::iterator iter = textures.begin();
+        while (iter != textures.end())
+        {
+            LLViewerTexture* tex = *iter++;
+            if (tex)
+            {
+                gTotalTextureBytesPerBoostLevel[tex->getBoostLevel()] += data_size;
+            }
+        }
 	}
 
 	mFetcher->removeFromHTTPQueue(mID, data_size);
@@ -4326,26 +4333,33 @@ bool LLTextureFetchDebugger::processStartDebug(F32 max_time)
 			fetched_textures.insert(mFetchingHistory[i].mID);
 			in_list = false;
 		}
-		
-		LLViewerFetchedTexture* tex = LLViewerTextureManager::findFetchedTexture(mFetchingHistory[i].mID);
-		if(tex && tex->isJustBound()) //visible
-		{
-			if(!in_list)
-			{
-				mNumVisibleFetchedTextures++;
-			}
-			mNumVisibleFetchingRequests++;
-	
-			mVisibleFetchedData += mFetchingHistory[i].mFetchedSize;
-			mVisibleDecodedData += mFetchingHistory[i].mDecodedSize;
-	
-			if(tex->getDiscardLevel() >= mFetchingHistory[i].mDecodedLevel)
-			{
-				mRenderedData += mFetchingHistory[i].mFetchedSize;
-				mRenderedDecodedData += mFetchingHistory[i].mDecodedSize;
-				mRenderedPixels += tex->getWidth() * tex->getHeight();
-			}
-		}
+
+        std::vector<LLViewerFetchedTexture*> textures;
+        LLViewerTextureManager::findFetchedTextures(mFetchingHistory[i].mID, textures);
+        std::vector<LLViewerFetchedTexture*>::iterator iter = textures.begin();
+        while (iter != textures.end())
+        {
+            LLViewerFetchedTexture* tex = *iter++;
+            // fetched data will be counted for both ui and regular elements
+            if (tex && tex->isJustBound()) //visible
+            {
+                if (!in_list)
+                {
+                    mNumVisibleFetchedTextures++;
+                }
+                mNumVisibleFetchingRequests++;
+
+                mVisibleFetchedData += mFetchingHistory[i].mFetchedSize;
+                mVisibleDecodedData += mFetchingHistory[i].mDecodedSize;
+
+                if (tex->getDiscardLevel() >= mFetchingHistory[i].mDecodedLevel)
+                {
+                    mRenderedData += mFetchingHistory[i].mFetchedSize;
+                    mRenderedDecodedData += mFetchingHistory[i].mDecodedSize;
+                    mRenderedPixels += tex->getWidth() * tex->getHeight();
+                }
+            }
+        }
 	}
 
 	mNumFetchedTextures = fetched_textures.size();
@@ -4445,7 +4459,8 @@ void LLTextureFetchDebugger::addHistoryEntry(LLTextureFetchWorker* worker)
 			mRefetchedAllPixels += worker->mRawImage->getWidth() * worker->mRawImage->getHeight();
 			mRefetchedAllData += worker->mFormattedImage->getDataSize();
 
-			LLViewerFetchedTexture* tex = LLViewerTextureManager::findFetchedTexture(worker->mID);
+			// refetch list only requests/creates normal images, so requesting ui='false'
+			LLViewerFetchedTexture* tex = LLViewerTextureManager::findFetchedTexture(worker->mID, false);
 			if(tex && mRefetchList[tex].begin() != mRefetchList[tex].end())
 			{
 				if(worker->mDecodedDiscard == mFetchingHistory[mRefetchList[tex][0]].mDecodedLevel)
@@ -4672,12 +4687,18 @@ void LLTextureFetchDebugger::debugGLTextureCreation()
 	{
 		if(mFetchingHistory[i].mRawImage.notNull())
 		{
-			LLViewerFetchedTexture* tex = gTextureList.findImage(mFetchingHistory[i].mID) ;
-			if(tex && !tex->isForSculptOnly())
-			{
-				tex->destroyGLTexture() ;
-				mTempTexList.push_back(tex);
-			}
+            std::vector<LLViewerFetchedTexture*> textures;
+            gTextureList.findTexturesByID(mFetchingHistory[i].mID, textures);
+            std::vector<LLViewerFetchedTexture*>::iterator iter = textures.begin();
+            while (iter != textures.end())
+            {
+                LLViewerFetchedTexture* tex = *iter++;
+                if (tex && !tex->isForSculptOnly())
+                {
+                    tex->destroyGLTexture();
+                    mTempTexList.push_back(tex);
+                }
+            }
 		}
 	}
 	
@@ -4732,11 +4753,17 @@ void LLTextureFetchDebugger::clearTextures()
 	S32 size = mFetchingHistory.size();
 	for(S32 i = 0 ; i < size ; i++)
 	{
-		LLViewerFetchedTexture* tex = gTextureList.findImage(mFetchingHistory[i].mID) ;
-		if(tex)
-		{
-			tex->clearFetchedResults() ;
-		}
+        std::vector<LLViewerFetchedTexture*> textures;
+        gTextureList.findTexturesByID(mFetchingHistory[i].mID, textures);
+        std::vector<LLViewerFetchedTexture*>::iterator iter = textures.begin();
+        while (iter != textures.end())
+        {
+            LLViewerFetchedTexture* tex = *iter++;
+            if (tex)
+            {
+                tex->clearFetchedResults();
+            }
+        }
 	}
 }
 
@@ -4752,6 +4779,8 @@ void LLTextureFetchDebugger::makeRefetchList()
 			continue; //the texture fetch pipeline will take care of visible textures.
 		}
 
+		// todo: Will attempt to refetch icons and ui elements as normal images (boost_none)
+		// thus will create unnesesary LLViewerFetchedTexture, consider supporting separate UI textures
 		mRefetchList[tex].push_back(i); 		
 	}
 }
diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h
index a2658ecd85..dc9df71c67 100755
--- a/indra/newview/lltexturefetch.h
+++ b/indra/newview/lltexturefetch.h
@@ -540,7 +540,7 @@ private:
 	S32 mNbCurlRequests;
 	S32 mNbCurlCompleted;
 
-	std::map< LLPointer<LLViewerFetchedTexture>, std::vector<S32> > mRefetchList;
+	std::map< LLPointer<LLViewerFetchedTexture>, std::vector<S32> > mRefetchList; // treats UI textures as normal textures
 	std::vector< LLPointer<LLViewerFetchedTexture> > mTempTexList;
 	S32 mTempIndex;
 	S32 mHistoryListIndex;
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index c8c71b74b7..50d9467b4a 100755
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -131,7 +131,7 @@ LLLoadedCallbackEntry::LLLoadedCallbackEntry(loaded_callback_func cb,
 {
 	if(mSourceCallbackList)
 	{
-		mSourceCallbackList->insert(target->getID());
+		mSourceCallbackList->insert(LLTextureKey(target->getID(), target->isUITexture()));
 	}
 }
 
@@ -143,7 +143,7 @@ void LLLoadedCallbackEntry::removeTexture(LLViewerFetchedTexture* tex)
 {
 	if(mSourceCallbackList)
 	{
-		mSourceCallbackList->erase(tex->getID());
+		mSourceCallbackList->erase(LLTextureKey(tex->getID(), tex->isUITexture()));
 	}
 }
 
@@ -170,24 +170,39 @@ LLViewerMediaTexture* LLViewerTextureManager::createMediaTexture(const LLUUID &m
 {
 	return new LLViewerMediaTexture(media_id, usemipmaps, gl_image);		
 }
- 
-LLViewerTexture*  LLViewerTextureManager::findTexture(const LLUUID& id) 
+
+void LLViewerTextureManager::findFetchedTextures(const LLUUID& id, std::vector<LLViewerFetchedTexture*> &output)
 {
-	LLViewerTexture* tex;
-	//search fetched texture list
-	tex = gTextureList.findImage(id);
-	
-	//search media texture list
-	if(!tex)
-	{
-		tex = LLViewerTextureManager::findMediaTexture(id);
-	}
-	return tex;
+    return gTextureList.findTexturesByID(id, output);
+}
+
+void  LLViewerTextureManager::findTextures(const LLUUID& id, std::vector<LLViewerTexture*> &output)
+{
+    std::vector<LLViewerFetchedTexture*> fetched_output;
+    gTextureList.findTexturesByID(id, fetched_output);
+    std::vector<LLViewerFetchedTexture*>::iterator iter = fetched_output.begin();
+    while (iter != fetched_output.end())
+    {
+        output.push_back(*iter);
+        iter++;
+    }
+
+    //search media texture list
+    if (output.empty())
+    {
+        LLViewerTexture* tex;
+        tex = LLViewerTextureManager::findMediaTexture(id);
+        if (tex)
+        {
+            output.push_back(tex);
+        }
+    }
+
 }
 
-LLViewerFetchedTexture*  LLViewerTextureManager::findFetchedTexture(const LLUUID& id) 
+LLViewerFetchedTexture* LLViewerTextureManager::findFetchedTexture(const LLUUID& id, bool is_ui)
 {
-	return gTextureList.findImage(id);
+	return gTextureList.findImage(id, is_ui);
 }
 
 LLViewerMediaTexture* LLViewerTextureManager::findMediaTexture(const LLUUID &media_id)
@@ -714,6 +729,13 @@ void LLViewerTexture::setBoostLevel(S32 level)
 
 }
 
+bool LLViewerTexture::isUITexture()
+{
+    // can be substituted with mDontDiscard
+    return mBoostLevel == LLViewerTexture::BOOST_ICON
+        || mBoostLevel == LLViewerTexture::BOOST_UI;
+}
+
 bool LLViewerTexture::isActiveFetching()
 {
 	return false;
@@ -3307,7 +3329,7 @@ LLViewerMediaTexture::LLViewerMediaTexture(const LLUUID& id, BOOL usemipmaps, LL
 
 	setCategory(LLGLTexture::MEDIA);
 	
-	LLViewerTexture* tex = gTextureList.findImage(mID);
+	LLViewerTexture* tex = gTextureList.findImage(mID, false);
 	if(tex) //this media is a parcel media for tex.
 	{
 		tex->setParcelMedia(this);
@@ -3317,7 +3339,7 @@ LLViewerMediaTexture::LLViewerMediaTexture(const LLUUID& id, BOOL usemipmaps, LL
 //virtual 
 LLViewerMediaTexture::~LLViewerMediaTexture() 
 {	
-	LLViewerTexture* tex = gTextureList.findImage(mID);
+	LLViewerTexture* tex = gTextureList.findImage(mID, false);
 	if(tex) //this media is a parcel media for tex.
 	{
 		tex->setParcelMedia(NULL);
@@ -3372,7 +3394,7 @@ BOOL LLViewerMediaTexture::findFaces()
 
 	BOOL ret = TRUE;
 	
-	LLViewerTexture* tex = gTextureList.findImage(mID);
+	LLViewerTexture* tex = gTextureList.findImage(mID, false);
 	if(tex) //this media is a parcel media for tex.
 	{
 		for (U32 ch = 0; ch < LLRender::NUM_TEXTURE_CHANNELS; ++ch)
@@ -3481,7 +3503,7 @@ void LLViewerMediaTexture::addFace(U32 ch, LLFace* facep)
 	const LLTextureEntry* te = facep->getTextureEntry();
 	if(te && te->getID().notNull())
 	{
-		LLViewerTexture* tex = gTextureList.findImage(te->getID());
+		LLViewerTexture* tex = gTextureList.findImage(te->getID(), false);
 		if(tex)
 		{
 			mTextureList.push_back(tex);//increase the reference number by one for tex to avoid deleting it.
@@ -3510,7 +3532,7 @@ void LLViewerMediaTexture::removeFace(U32 ch, LLFace* facep)
 	const LLTextureEntry* te = facep->getTextureEntry();
 	if(te && te->getID().notNull())
 	{
-		LLViewerTexture* tex = gTextureList.findImage(te->getID());
+		LLViewerTexture* tex = gTextureList.findImage(te->getID(), false);
 		if(tex)
 		{
 			for(std::list< LLPointer<LLViewerTexture> >::iterator iter = mTextureList.begin();
@@ -3619,10 +3641,10 @@ void LLViewerMediaTexture::switchTexture(U32 ch, LLFace* facep)
 			const LLTextureEntry* te = facep->getTextureEntry();
 			if(te)
 			{
-				LLViewerTexture* tex = te->getID().notNull() ? gTextureList.findImage(te->getID()) : NULL;
+				LLViewerTexture* tex = te->getID().notNull() ? gTextureList.findImage(te->getID(), false) : NULL;
 				if(!tex && te->getID() != mID)//try parcel media.
 				{
-					tex = gTextureList.findImage(mID);
+					tex = gTextureList.findImage(mID, false);
 				}
 				if(!tex)
 				{
diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h
index aed7e94945..a5e5a35f91 100755
--- a/indra/newview/llviewertexture.h
+++ b/indra/newview/llviewertexture.h
@@ -58,11 +58,12 @@ class LLVFile;
 class LLMessageSystem;
 class LLViewerMediaImpl ;
 class LLVOVolume ;
+struct LLTextureKey;
 
 class LLLoadedCallbackEntry
 {
 public:
-	typedef std::set< LLUUID > source_callback_list_t;
+    typedef std::set< LLTextureKey > source_callback_list_t;
 
 public:
 	LLLoadedCallbackEntry(loaded_callback_func cb,
@@ -132,6 +133,7 @@ public:
 	/*virtual*/ const LLUUID& getID() const { return mID; }
 	void setBoostLevel(S32 level);
 	S32  getBoostLevel() { return mBoostLevel; }
+	bool isUITexture();
 
 	void addTextureStats(F32 virtual_size, BOOL needs_gltexture = TRUE) const;
 	void resetTextureStats();	
@@ -626,8 +628,9 @@ public:
 	//
 	//"find-texture" just check if the texture exists, if yes, return it, otherwise return null.
 	//
-	static LLViewerTexture*           findTexture(const LLUUID& id) ;
-	static LLViewerFetchedTexture*    findFetchedTexture(const LLUUID& id) ;
+	static void                       findFetchedTextures(const LLUUID& id, std::vector<LLViewerFetchedTexture*> &output);
+	static void                       findTextures(const LLUUID& id, std::vector<LLViewerTexture*> &output);
+	static LLViewerFetchedTexture*    findFetchedTexture(const LLUUID& id, bool is_ui);
 	static LLViewerMediaTexture*      findMediaTexture(const LLUUID& id) ;
 	
 	static LLViewerMediaTexture*      createMediaTexture(const LLUUID& id, BOOL usemipmaps = TRUE, LLImageGL* gl_image = NULL) ;
diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp
index 926c40307b..10fbc8bd25 100755
--- a/indra/newview/llviewertexturelist.cpp
+++ b/indra/newview/llviewertexturelist.cpp
@@ -70,6 +70,25 @@ S32 LLViewerTextureList::sNumImages = 0;
 LLViewerTextureList gTextureList;
 static LLTrace::BlockTimerStatHandle FTM_PROCESS_IMAGES("Process Images");
 
+bool is_ui_element(S32 priority)
+{
+    // alternatively don't discard flag can be used
+    return priority == LLViewerFetchedTexture::BOOST_ICON
+           || priority == LLViewerFetchedTexture::BOOST_UI;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+LLTextureKey::LLTextureKey()
+: textureId(LLUUID::null),
+isUI(false)
+{
+}
+
+LLTextureKey::LLTextureKey(LLUUID id, bool is_ui)
+: textureId(id), isUI(is_ui)
+{
+}
 
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -351,7 +370,8 @@ LLViewerFetchedTexture* LLViewerTextureList::getImageFromFile(const std::string&
 	if (full_path.empty())
 	{
 		LL_WARNS() << "Failed to find local image file: " << filename << LL_ENDL;
-		return LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_UI);
+		LLViewerTexture::EBoostLevel priority = LLGLTexture::BOOST_UI;
+		return LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT, FTT_DEFAULT, TRUE, priority);
 	}
 
 	std::string url = "file://" + full_path;
@@ -384,7 +404,7 @@ LLViewerFetchedTexture* LLViewerTextureList::getImageFromUrl(const std::string&
 		new_id.generate(url);
 	}
 
-	LLPointer<LLViewerFetchedTexture> imagep = findImage(new_id);
+	LLPointer<LLViewerFetchedTexture> imagep = findImage(new_id, is_ui_element(boost_priority));
 
 	if (!imagep.isNull())
 	{
@@ -422,12 +442,12 @@ LLViewerFetchedTexture* LLViewerTextureList::getImageFromUrl(const std::string&
 			imagep->setExplicitFormat(internal_format, primary_format);
 		}
 
-		addImage(imagep);
-		
+		bool is_ui = is_ui_element(boost_priority);
+		addImage(imagep, is_ui);
+
 		if (boost_priority != 0)
 		{
-			if (boost_priority == LLViewerFetchedTexture::BOOST_UI ||
-				boost_priority == LLViewerFetchedTexture::BOOST_ICON)
+			if (is_ui)
 			{
 				imagep->dontDiscard();
 			}
@@ -464,7 +484,7 @@ LLViewerFetchedTexture* LLViewerTextureList::getImage(const LLUUID &image_id,
 		return (LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_UI));
 	}
 	
-	LLPointer<LLViewerFetchedTexture> imagep = findImage(image_id);
+	LLPointer<LLViewerFetchedTexture> imagep = findImage(image_id, is_ui_element(boost_priority));
 	if (!imagep.isNull())
 	{
 		LLViewerFetchedTexture *texture = imagep.get();
@@ -525,13 +545,13 @@ LLViewerFetchedTexture* LLViewerTextureList::createImage(const LLUUID &image_id,
 	{
 		imagep->setExplicitFormat(internal_format, primary_format);
 	}
-	
-	addImage(imagep);
-	
+
+	bool is_ui = is_ui_element(boost_priority);
+	addImage(imagep, is_ui);
+
 	if (boost_priority != 0)
 	{
-		if (boost_priority == LLViewerFetchedTexture::BOOST_UI ||
-			boost_priority == LLViewerFetchedTexture::BOOST_ICON)
+		if (is_ui)
 		{
 			imagep->dontDiscard();
 		}
@@ -553,12 +573,28 @@ LLViewerFetchedTexture* LLViewerTextureList::createImage(const LLUUID &image_id,
 	return imagep ;
 }
 
-LLViewerFetchedTexture *LLViewerTextureList::findImage(const LLUUID &image_id)
+void LLViewerTextureList::findTexturesByID(const LLUUID &image_id, std::vector<LLViewerFetchedTexture*> &output)
+{
+    LLTextureKey search_key(image_id, false);
+    uuid_map_t::iterator iter = mUUIDMap.lower_bound(search_key);
+    while (iter != mUUIDMap.end() && iter->first.textureId == image_id)
+    {
+        output.push_back(iter->second);
+        iter++;
+    }
+}
+
+LLViewerFetchedTexture *LLViewerTextureList::findImage(const LLTextureKey &search_key)
+{
+    uuid_map_t::iterator iter = mUUIDMap.find(search_key);
+    if (iter == mUUIDMap.end())
+        return NULL;
+    return iter->second;
+}
+
+LLViewerFetchedTexture *LLViewerTextureList::findImage(const LLUUID &image_id, bool is_ui)
 {
-	uuid_map_t::iterator iter = mUUIDMap.find(image_id);
-	if(iter == mUUIDMap.end())
-		return NULL;
-	return iter->second;
+    return findImage(LLTextureKey(image_id, is_ui));
 }
 
 void LLViewerTextureList::addImageToList(LLViewerFetchedTexture *image)
@@ -603,7 +639,7 @@ void LLViewerTextureList::removeImageFromList(LLViewerFetchedTexture *image)
 			<< " but doesn't have mInImageList set"
 			<< " ref count is " << image->getNumRefs()
 			<< LL_ENDL;
-		uuid_map_t::iterator iter = mUUIDMap.find(image->getID());
+		uuid_map_t::iterator iter = mUUIDMap.find(LLTextureKey(image->getID(), image->isUITexture()));
 		if(iter == mUUIDMap.end())
 		{
 			LL_INFOS() << "Image  " << image->getID() << " is also not in mUUIDMap!" << LL_ENDL ;
@@ -628,7 +664,7 @@ void LLViewerTextureList::removeImageFromList(LLViewerFetchedTexture *image)
 	image->setInImageList(FALSE) ;
 }
 
-void LLViewerTextureList::addImage(LLViewerFetchedTexture *new_image)
+void LLViewerTextureList::addImage(LLViewerFetchedTexture *new_image, bool add_ui)
 {
 	if (!new_image)
 	{
@@ -636,16 +672,17 @@ void LLViewerTextureList::addImage(LLViewerFetchedTexture *new_image)
 	}
 	//llassert(new_image);
 	LLUUID image_id = new_image->getID();
+    LLTextureKey key(image_id, add_ui);
 	
-	LLViewerFetchedTexture *image = findImage(image_id);
+	LLViewerFetchedTexture *image = findImage(key);
 	if (image)
 	{
 		LL_INFOS() << "Image with ID " << image_id << " already in list" << LL_ENDL;
 	}
 	sNumImages++;
-	
+
 	addImageToList(new_image);
-	mUUIDMap[image_id] = new_image;
+	mUUIDMap[key] = new_image;
 }
 
 
@@ -657,8 +694,8 @@ void LLViewerTextureList::deleteImage(LLViewerFetchedTexture *image)
 		{
 			mCallbackList.erase(image);
 		}
-
-		llverify(mUUIDMap.erase(image->getID()) == 1);
+		LLTextureKey key(image->getID(), image->isUITexture());
+		llverify(mUUIDMap.erase(key) == 1);
 		sNumImages--;
 		removeImageFromList(image);
 	}
@@ -801,14 +838,14 @@ void LLViewerTextureList::updateImagesDecodePriorities()
         static const S32 MAX_PRIO_UPDATES = gSavedSettings.getS32("TextureFetchUpdatePriorities");         // default: 32
 		const size_t max_update_count = llmin((S32) (MAX_PRIO_UPDATES*MAX_PRIO_UPDATES*gFrameIntervalSeconds.value()) + 1, MAX_PRIO_UPDATES);
 		S32 update_counter = llmin(max_update_count, mUUIDMap.size());
-		uuid_map_t::iterator iter = mUUIDMap.upper_bound(mLastUpdateUUID);
+		uuid_map_t::iterator iter = mUUIDMap.upper_bound(mLastUpdateKey);
 		while ((update_counter-- > 0) && !mUUIDMap.empty())
 		{
 			if (iter == mUUIDMap.end())
 			{
 				iter = mUUIDMap.begin();
-			}
-			mLastUpdateUUID = iter->first;
+            }
+            mLastUpdateKey = iter->first;
 			LLPointer<LLViewerFetchedTexture> imagep = iter->second;
 			++iter; // safe to increment now
 
@@ -1061,7 +1098,7 @@ F32 LLViewerTextureList::updateImagesFetchTextures(F32 max_time)
 	update_counter = max_update_count;	
 	if(update_counter > 0)
 	{
-		uuid_map_t::iterator iter2 = mUUIDMap.upper_bound(mLastFetchUUID);
+		uuid_map_t::iterator iter2 = mUUIDMap.upper_bound(mLastFetchKey);
 		while ((update_counter > 0) && (total_update_count > 0))
 		{
 			if (iter2 == mUUIDMap.end())
@@ -1091,7 +1128,7 @@ F32 LLViewerTextureList::updateImagesFetchTextures(F32 max_time)
 		fetch_count += (imagep->updateFetch() ? 1 : 0);
 		if (min_count <= min_update_count)
 		{
-			mLastFetchUUID = imagep->getID();
+			mLastFetchKey = LLTextureKey(imagep->getID(), imagep->isUITexture());
 		}
 		if ((min_count-- <= 0) && (image_op_timer.getElapsedTimeF32() > max_time))
 		{
@@ -1543,12 +1580,19 @@ void LLViewerTextureList::processImageNotInDatabase(LLMessageSystem *msg,void **
 	LLUUID image_id;
 	msg->getUUIDFast(_PREHASH_ImageID, _PREHASH_ID, image_id);
 	
-	LLViewerFetchedTexture* image = gTextureList.findImage( image_id );
+	LLViewerFetchedTexture* image = gTextureList.findImage( image_id, false);
 	if( image )
 	{
-		LL_WARNS() << "not in db" << LL_ENDL;
+		LL_WARNS() << "Image not in db" << LL_ENDL;
 		image->setIsMissingAsset();
 	}
+
+    image = gTextureList.findImage(image_id, true);
+    if (image)
+    {
+        LL_WARNS() << "Icon not in db" << LL_ENDL;
+        image->setIsMissingAsset();
+    }
 }
 
 
diff --git a/indra/newview/llviewertexturelist.h b/indra/newview/llviewertexturelist.h
index fbbfe9a7d4..b1b6f4d2aa 100755
--- a/indra/newview/llviewertexturelist.h
+++ b/indra/newview/llviewertexturelist.h
@@ -59,6 +59,26 @@ typedef	void (*LLImageCallback)(BOOL success,
 								BOOL final,
 								void* userdata);
 
+struct LLTextureKey
+{
+    LLTextureKey();
+    LLTextureKey(LLUUID id, bool is_ui);
+    LLUUID textureId;
+    bool isUI;
+
+    friend bool operator<(const LLTextureKey& key1, const LLTextureKey& key2)
+    {
+        if (key1.textureId != key2.textureId)
+        {
+            return key1.textureId < key2.textureId;
+        }
+        else
+        {
+            return key1.isUI < key2.isUI;
+        }
+    }
+};
+
 class LLViewerTextureList
 {
 	friend class LLTextureView;
@@ -83,7 +103,9 @@ public:
 	void restoreGL();
 	BOOL isInitialized() const {return mInitialized;}
 
-	LLViewerFetchedTexture *findImage(const LLUUID &image_id);
+	void findTexturesByID(const LLUUID &image_id, std::vector<LLViewerFetchedTexture*> &output);
+	LLViewerFetchedTexture *findImage(const LLUUID &image_id, bool is_ui);
+	LLViewerFetchedTexture *findImage(const LLTextureKey &search_key);
 
 	void dirtyImage(LLViewerFetchedTexture *image);
 	
@@ -120,7 +142,7 @@ private:
 	void updateImagesUpdateStats();
 	F32  updateImagesLoadingFastCache(F32 max_time);
 
-	void addImage(LLViewerFetchedTexture *image);
+	void addImage(LLViewerFetchedTexture *image, bool add_ui);
 	void deleteImage(LLViewerFetchedTexture *image);
 
 	void addImageToList(LLViewerFetchedTexture *image);
@@ -184,10 +206,10 @@ public:
 	BOOL mForceResetTextureStats;
     
 private:
-	typedef std::map< LLUUID, LLPointer<LLViewerFetchedTexture> > uuid_map_t;
-	uuid_map_t mUUIDMap;
-	LLUUID mLastUpdateUUID;
-	LLUUID mLastFetchUUID;
+    typedef std::map< LLTextureKey, LLPointer<LLViewerFetchedTexture> > uuid_map_t;
+    uuid_map_t mUUIDMap;
+    LLTextureKey mLastUpdateKey;
+    LLTextureKey mLastFetchKey;
 	
 	typedef std::set<LLPointer<LLViewerFetchedTexture>, LLViewerFetchedTexture::Compare> image_priority_list_t;	
 	image_priority_list_t mImageList;
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 6f7b23ba01..654d0ccfc8 100755
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -1992,7 +1992,7 @@ LLViewerFetchedTexture *LLVOAvatar::getBakedTextureImage(const U8 te, const LLUU
 		uuid == IMG_INVISIBLE)
 	{
 		// Should already exist, don't need to find it on sim or baked-texture host.
-		result = gTextureList.findImage(uuid);
+		result = gTextureList.findImage(uuid, false);
 	}
 	if (!result)
 	{
@@ -4313,7 +4313,7 @@ bool LLVOAvatar::allTexturesCompletelyDownloaded(std::set<LLUUID>& ids) const
 {
 	for (std::set<LLUUID>::const_iterator it = ids.begin(); it != ids.end(); ++it)
 	{
-		LLViewerFetchedTexture *imagep = gTextureList.findImage(*it);
+		LLViewerFetchedTexture *imagep = gTextureList.findImage(*it, false);
 		if (imagep && imagep->getDiscardLevel()!=0)
 		{
 			return false;
@@ -4385,7 +4385,7 @@ S32Bytes LLVOAvatar::totalTextureMemForUUIDS(std::set<LLUUID>& ids)
 	S32Bytes result(0);
 	for (std::set<LLUUID>::const_iterator it = ids.begin(); it != ids.end(); ++it)
 	{
-		LLViewerFetchedTexture *imagep = gTextureList.findImage(*it);
+		LLViewerFetchedTexture *imagep = gTextureList.findImage(*it, false);
 		if (imagep)
 		{
 			result += imagep->getTextureMemory();
@@ -4473,7 +4473,7 @@ void LLVOAvatar::releaseOldTextures()
 	{
 		if (new_texture_ids.find(*it) == new_texture_ids.end())
 		{
-			LLViewerFetchedTexture *imagep = gTextureList.findImage(*it);
+			LLViewerFetchedTexture *imagep = gTextureList.findImage(*it, false);
 			if (imagep)
 			{
 				current_texture_mem += imagep->getTextureMemory();
-- 
cgit v1.2.3