From 254db516c5db2bd2eda3329c1fae59df2e0510aa Mon Sep 17 00:00:00 2001
From: Xiaohong Bao <bao@lindenlab.com>
Date: Wed, 24 Feb 2010 12:09:22 -0700
Subject: fix for EXT-5710: improve the raw image reloading process in the
 texture pipeline; EXT-4612: failing assert
 LLViewerTexture::setDecodePriority: ASSERT (!mInImageList); EXT-4912: Texture
 alpha mask is not applied on the first frame after decode.

---
 indra/newview/lltexturefetch.cpp      |   2 +-
 indra/newview/llviewertexture.cpp     | 273 ++++++++++++++--------------------
 indra/newview/llviewertexture.h       |   5 +-
 indra/newview/llviewertexturelist.cpp |  12 +-
 4 files changed, 120 insertions(+), 172 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp
index 6c35464a51..0053ce8df8 100644
--- a/indra/newview/lltexturefetch.cpp
+++ b/indra/newview/lltexturefetch.cpp
@@ -491,7 +491,7 @@ U32 LLTextureFetchWorker::calcWorkPriority()
  	//llassert_always(mImagePriority >= 0 && mImagePriority <= LLViewerFetchedTexture::maxDecodePriority());
 	static const F32 PRIORITY_SCALE = (F32)LLWorkerThread::PRIORITY_LOWBITS / LLViewerFetchedTexture::maxDecodePriority();
 
-	mWorkPriority = (U32)(mImagePriority * PRIORITY_SCALE);
+	mWorkPriority = llmin((U32)LLWorkerThread::PRIORITY_LOWBITS, (U32)(mImagePriority * PRIORITY_SCALE));
 	return mWorkPriority;
 }
 
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index 6add8a7e92..01d437f9eb 100644
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -1257,20 +1257,30 @@ void LLViewerFetchedTexture::destroyTexture()
 	mFullyLoaded = FALSE ;
 }
 
-//
-//do not change the discard level of the loaded texture image.
-BOOL LLViewerFetchedTexture::keepReuestedDiscardLevel()
+void LLViewerFetchedTexture::addToCreateTexture()
 {
-	if (!mLoadedCallbackList.empty())
+	bool force_update = false ;
+	if (getComponents() != mRawImage->getComponents())
 	{
-		return TRUE ;
-	}
+		// We've changed the number of components, so we need to move any
+		// objects using this pool to a different pool.
+		mComponents = mRawImage->getComponents();
+		mGLTexturep->setComponents(mComponents) ;
+		force_update = true ;
 
-	return FALSE ;
-}
+		for(U32 i = 0 ; i < mNumFaces ; i++)
+		{
+			mFaceList[i]->dirtyTexture() ;
+		}
+
+		//discard the cached raw image and the saved raw image
+		mCachedRawImageReady = FALSE ;
+		mCachedRawDiscardLevel = -1 ;
+		mCachedRawImage = NULL ;
+		mSavedRawDiscardLevel = -1 ;
+		mSavedRawImage = NULL ;
+	}	
 
-void LLViewerFetchedTexture::addToCreateTexture()
-{
 	if(isForSculptOnly())
 	{
 		//just update some variables, not to create a real GL texture.
@@ -1278,6 +1288,11 @@ void LLViewerFetchedTexture::addToCreateTexture()
 		mNeedsCreateTexture = FALSE ;
 		destroyRawImage();
 	}
+	else if(!force_update && getDiscardLevel() > -1 && getDiscardLevel() <= mRawDiscardLevel)
+	{
+		mNeedsCreateTexture = FALSE ;
+		destroyRawImage();
+	}
 	else
 	{	
 #if 1
@@ -1286,7 +1301,7 @@ void LLViewerFetchedTexture::addToCreateTexture()
 		//so do not scale down the over qualified image.
 		//Note: scaling down image is expensensive. Do it only when very necessary.
 		//
-		if(mRequestedDiscardLevel <= mDesiredDiscardLevel && !keepReuestedDiscardLevel())
+		if(mRequestedDiscardLevel <= mDesiredDiscardLevel && !mForceToSaveRawImage)
 		{
 			S32 w = mFullWidth >> mRawDiscardLevel;
 			S32 h = mFullHeight >> mRawDiscardLevel;
@@ -1399,28 +1414,12 @@ BOOL LLViewerFetchedTexture::createTexture(S32 usename/*= 0*/)
 		setActive() ;
 	}
 
-	//
-	// Iterate through the list of image loading callbacks to see
-	// what sort of data they need.
-	//
-	// *TODO: Fix image callback code
-	BOOL imageraw_callbacks = FALSE;
-	for(callback_list_t::iterator iter = mLoadedCallbackList.begin();
-		iter != mLoadedCallbackList.end(); )
-	{
-		LLLoadedCallbackEntry *entryp = *iter++;
-		if (entryp->mNeedsImageRaw)
-		{
-			imageraw_callbacks = TRUE;
-			break;
-		}
-	}
-
-	if (!imageraw_callbacks)
+	if (!mForceToSaveRawImage)
 	{
 		mNeedsAux = FALSE;
-		destroyRawImage();
 	}
+		destroyRawImage();
+	
 	return res;
 }
 
@@ -1503,21 +1502,16 @@ F32 LLViewerFetchedTexture::calcDecodePriority()
 	}
 #endif
 	
-	if(mFullyLoaded)//already loaded for static texture
-	{
-		return -4.0f ; //alreay fetched
-	}
-
 	if (mNeedsCreateTexture)
 	{
 		return mDecodePriority; // no change while waiting to create
 	}
-	if(mForceToSaveRawImage)
+	if(mFullyLoaded && !mForceToSaveRawImage)//already loaded for static texture
 	{
-		return maxDecodePriority() ;
+		return -4.0f ; //alreay fetched
 	}
-	
-	S32 cur_discard = getDiscardLevel();
+
+	S32 cur_discard = getCurrentDiscardLevelForFetching();
 	bool have_all_data = (cur_discard >= 0 && (cur_discard <= mDesiredDiscardLevel));
 	F32 pixel_priority = fsqrtf(mMaxVirtualSize);
 
@@ -1642,11 +1636,8 @@ F32 LLViewerFetchedTexture::maxDecodePriority()
 
 void LLViewerFetchedTexture::setDecodePriority(F32 priority)
 {
-	//llassert(!mInImageList); // firing a lot, figure out why
-        if (mInImageList) // above llassert() softened to a warning
-        {
-                llwarns << "BAD STUFF!  mInImageList" << llendl;
-        }
+	llassert(!mInImageList); 
+    
 	mDecodePriority = priority;
 }
 
@@ -1666,6 +1657,11 @@ void LLViewerFetchedTexture::updateVirtualSize()
 		addTextureStats(0.f, FALSE) ;//reset
 	}
 
+	if(mForceToSaveRawImage)
+	{
+		setAdditionalDecodePriority(0.75f) ; //boost the fetching priority
+	}
+
 	for(U32 i = 0 ; i < mNumFaces ; i++)
 	{				
 		LLFace* facep = mFaceList[i] ;
@@ -1680,6 +1676,24 @@ void LLViewerFetchedTexture::updateVirtualSize()
 	reorganizeVolumeList();
 }
 
+S32 LLViewerFetchedTexture::getCurrentDiscardLevelForFetching()
+{
+	S32 current_discard = getDiscardLevel() ;
+	if(mForceToSaveRawImage)
+	{
+		if(mSavedRawDiscardLevel < 0 || current_discard < 0)
+		{
+			current_discard = -1 ;
+		}
+		else
+		{
+			current_discard = llmax(current_discard, mSavedRawDiscardLevel) ;
+		}		
+	}
+
+	return current_discard ;
+}
+
 bool LLViewerFetchedTexture::updateFetch()
 {
 	static LLCachedControl<bool> textures_decode_disabled(gSavedSettings,"TextureDecodeDisabled");
@@ -1716,7 +1730,7 @@ bool LLViewerFetchedTexture::updateFetch()
 		return false; // process any raw image data in callbacks before replacing
 	}
 	
-	S32 current_discard = getDiscardLevel() ;
+	S32 current_discard = getCurrentDiscardLevelForFetching() ;
 	S32 desired_discard = getDesiredDiscardLevel();
 	F32 decode_priority = getDecodePriority();
 	decode_priority = llmax(decode_priority, 0.0f);
@@ -1726,14 +1740,6 @@ bool LLViewerFetchedTexture::updateFetch()
 		// Sets mRawDiscardLevel, mRawImage, mAuxRawImage
 		S32 fetch_discard = current_discard;
 		
-		if(mForceToSaveRawImage)
-		{
-			if(fetch_discard >= 0)
-			{
-				fetch_discard = llmax(fetch_discard, mSavedRawDiscardLevel) ;
-			}
-		}
-
 		if (mRawImage.notNull()) sRawCount--;
 		if (mAuxRawImage.notNull()) sAuxCount--;
 		bool finished = LLAppViewer::getTextureFetch()->getRequestFinished(getID(), fetch_discard, mRawImage, mAuxRawImage);
@@ -1761,18 +1767,6 @@ bool LLViewerFetchedTexture::updateFetch()
 			if ((mRawImage->getDataSize() > 0 && mRawDiscardLevel >= 0) &&
 				(current_discard < 0 || mRawDiscardLevel < current_discard))
 			{
-				if (getComponents() != mRawImage->getComponents())
-				{
-					// We've changed the number of components, so we need to move any
-					// objects using this pool to a different pool.
-					mComponents = mRawImage->getComponents();
-					mGLTexturep->setComponents(mComponents) ;
-
-					for(U32 i = 0 ; i < mNumFaces ; i++)
-					{
-						mFaceList[i]->dirtyTexture() ;
-					}
-				}			
 				mFullWidth = mRawImage->getWidth() << mRawDiscardLevel;
 				mFullHeight = mRawImage->getHeight() << mRawDiscardLevel;
 
@@ -1838,18 +1832,6 @@ bool LLViewerFetchedTexture::updateFetch()
 		}
 	}
 
-	if (!mDontDiscard)
-	{
-		if (mBoostLevel == 0)
-		{
-			desired_discard = llmax(desired_discard, current_discard-1);
-		}
-		else
-		{
-			desired_discard = llmax(desired_discard, current_discard-2);
-		}
-	}
-
 	bool make_request = true;	
 	if (decode_priority <= 0)
 	{
@@ -1867,8 +1849,20 @@ bool LLViewerFetchedTexture::updateFetch()
 	//{
 	//	make_request = false;
 	//}
-	else
+	
+	if(make_request)
 	{
+		//load the texture progressively.
+		S32 delta_level = (mBoostLevel > LLViewerTexture::BOOST_NONE) ? 2 : 1 ; 
+		if(current_discard < 0)
+		{
+			desired_discard = llmax(desired_discard, getMaxDiscardLevel() - delta_level);
+		}
+		else
+		{
+			desired_discard = llmax(desired_discard, current_discard - delta_level);
+		}
+
 		if (mIsFetching)
 		{
 			if (mRequestedDiscardLevel <= desired_discard)
@@ -1888,7 +1882,7 @@ bool LLViewerFetchedTexture::updateFetch()
 	if (make_request)
 	{
 		S32 w=0, h=0, c=0;
-		if (current_discard >= 0)
+		if (getDiscardLevel() >= 0)
 		{
 			w = mGLTexturep->getWidth(0);
 			h = mGLTexturep->getHeight(0);
@@ -1929,73 +1923,6 @@ bool LLViewerFetchedTexture::updateFetch()
 	return mIsFetching ? true : false;
 }
 
-//
-//force to fetch a new raw image for this texture
-//
-BOOL LLViewerFetchedTexture::forceFetch()
-{
-	if(!mForceToSaveRawImage)
-	{
-		return false ;
-	}
-	//if(mDesiredSavedRawDiscardLevel < getDiscardLevel())
-	{
-		//no need to force fetching. normal fetching flow will do the work.
-		//return false ;
-	}
-	//if (mNeedsCreateTexture)
-	{
-		// We may be fetching still (e.g. waiting on write)
-		// but don't check until we've processed the raw data we have
-		//return false;
-	}
-	if(mIsFetching)
-	{
-		return false ;
-	}
-	if (mIsMissingAsset)
-	{
-		mForceToSaveRawImage = false ;
-		llassert_always(!mHasFetcher);
-		return false; // skip
-	}
-	if (!mLoadedCallbackList.empty() && mRawImage.notNull())
-	{
-		return false; // process any raw image data in callbacks before replacing
-	}
-	if(mRawImage.notNull() && mRawDiscardLevel <= mDesiredSavedRawDiscardLevel)
-	{
-		return false ; // mRawImage is enough
-	}
-
-	S32 desired_discard = mDesiredSavedRawDiscardLevel ;
-	S32 current_discard = getDiscardLevel();
-	
-	bool fetch_request_created = false;
-	S32 w=0, h=0, c=0;
-	if (current_discard >= 0)
-	{
-		w = getWidth(0);
-		h = getHeight(0);
-		c = getComponents();
-	}
-	setDecodePriority(maxDecodePriority()) ;
-	fetch_request_created = LLAppViewer::getTextureFetch()->createRequest(mUrl, getID(),getTargetHost(), getDecodePriority(),
-																		  w, h, c, desired_discard, needsAux());
-
-	if (fetch_request_created)
-	{				
-		mHasFetcher = TRUE;
-		mIsFetching = TRUE;
-		mRequestedDiscardLevel = desired_discard ;
-
-		mFetchState = LLAppViewer::getTextureFetch()->getFetchState(mID, mDownloadProgress, mRequestedDownloadPriority,
-																	mFetchPriority, mFetchDeltaTime, mRequestDeltaTime);
-	}	
-
-	return mIsFetching ? true : false;
-}
-
 void LLViewerFetchedTexture::setIsMissingAsset()
 {
 	if (mUrl.empty())
@@ -2037,6 +1964,10 @@ void LLViewerFetchedTexture::setLoadedCallback( loaded_callback_func loaded_call
 	LLLoadedCallbackEntry* entryp = new LLLoadedCallbackEntry(loaded_callback, discard_level, keep_imageraw, userdata);
 	mLoadedCallbackList.push_back(entryp);
 	mNeedsAux |= needs_aux;
+	if(keep_imageraw)
+	{
+		forceToSaveRawImage(discard_level) ;
+	}
 	if (mNeedsAux && mAuxRawImage.isNull() && getDiscardLevel() >= 0)
 	{
 		// We need aux data, but we've already loaded the image, and it didn't have any
@@ -2285,8 +2216,15 @@ LLImageRaw* LLViewerFetchedTexture::reloadRawImage(S8 discard_level)
 
 	if(mSavedRawDiscardLevel >= 0 && mSavedRawDiscardLevel <= discard_level)
 	{
-		mRawImage = new LLImageRaw(getWidth(discard_level), getHeight(discard_level), getComponents()) ;
-		mRawImage->copy(getSavedRawImage()) ;
+		if(mSavedRawDiscardLevel != discard_level)
+		{
+			mRawImage = new LLImageRaw(getWidth(discard_level), getHeight(discard_level), getComponents()) ;
+			mRawImage->copy(getSavedRawImage()) ;
+		}
+		else
+		{
+			mRawImage = getSavedRawImage() ;
+		}
 		mRawDiscardLevel = discard_level ;
 	}
 	else
@@ -2296,13 +2234,18 @@ LLImageRaw* LLViewerFetchedTexture::reloadRawImage(S8 discard_level)
 		{
 			mRawImage = mCachedRawImage ;
 			mRawDiscardLevel = mCachedRawDiscardLevel;
-
-			forceToSaveRawImage(discard_level) ;
 		}
 		else //cached raw image is good enough, copy it.
 		{
-			mRawImage = new LLImageRaw(getWidth(discard_level), getHeight(discard_level), getComponents()) ;
-			mRawImage->copy(mCachedRawImage) ;
+			if(mCachedRawDiscardLevel != discard_level)
+			{
+				mRawImage = new LLImageRaw(getWidth(discard_level), getHeight(discard_level), getComponents()) ;
+				mRawImage->copy(mCachedRawImage) ;
+			}
+			else
+			{
+				mRawImage = mCachedRawImage ;
+			}
 			mRawDiscardLevel = discard_level ;
 		}
 	}
@@ -2331,11 +2274,6 @@ void LLViewerFetchedTexture::destroyRawImage()
 	mAuxRawImage = NULL;
 	mIsRawImageValid = FALSE;
 	mRawDiscardLevel = INVALID_DISCARD_LEVEL;
-
-	if(mForceToSaveRawImage)
-	{
-		forceFetch() ;
-	}
 }
 
 //use the mCachedRawImage to (re)generate the gl texture.
@@ -2448,7 +2386,7 @@ void LLViewerFetchedTexture::checkCachedRawSculptImage()
 
 void LLViewerFetchedTexture::saveRawImage() 
 {
-	if(mRawImage.isNull() || mSavedRawDiscardLevel == mRawDiscardLevel)
+	if(mRawImage.isNull() || mRawImage == mSavedRawImage || (mSavedRawDiscardLevel >= 0 && mSavedRawDiscardLevel <= mRawDiscardLevel))
 	{
 		return ;
 	}
@@ -2466,12 +2404,22 @@ void LLViewerFetchedTexture::saveRawImage()
 
 void LLViewerFetchedTexture::forceToSaveRawImage(S32 desired_discard) 
 { 
-	if(!mForceToSaveRawImage && (mDesiredSavedRawDiscardLevel < 0 || mDesiredSavedRawDiscardLevel > desired_discard))
+	if(!mForceToSaveRawImage || mDesiredSavedRawDiscardLevel < 0 || mDesiredSavedRawDiscardLevel > desired_discard)
 	{
 		mForceToSaveRawImage = TRUE ;
 		mDesiredSavedRawDiscardLevel = desired_discard ;
 	
-		forceFetch() ;
+		//copy from the cached raw image if exists.
+		if(mCachedRawImage.notNull() && mRawImage.isNull() )
+		{
+			mRawImage = mCachedRawImage ;
+			mRawDiscardLevel = mCachedRawDiscardLevel ;
+
+			saveRawImage() ;
+
+			mRawImage = NULL ;
+			mRawDiscardLevel = INVALID_DISCARD_LEVEL ;
+		}
 	}
 }
 void LLViewerFetchedTexture::destroySavedRawImage()
@@ -2838,6 +2786,11 @@ void LLViewerLODTexture::processTextureStats()
 			}
 		}
 	}
+
+	if(mForceToSaveRawImage && mDesiredSavedRawDiscardLevel >= 0)
+	{
+		mDesiredDiscardLevel = llmin(mDesiredDiscardLevel, (S8)mDesiredSavedRawDiscardLevel) ;
+	}
 }
 
 void LLViewerLODTexture::scaleDown()
diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h
index 79db754072..84377198eb 100644
--- a/indra/newview/llviewertexture.h
+++ b/indra/newview/llviewertexture.h
@@ -424,7 +424,6 @@ public:
 
 	LLImageRaw* reloadRawImage(S8 discard_level) ;
 	void destroyRawImage();
-	/*virtual*/ void setCachedRawImage(S32 discard_level, LLImageRaw* imageraw) ;
 
 	const std::string& getUrl() const {return mUrl;}
 	//---------------
@@ -449,6 +448,7 @@ public:
 	BOOL        isCachedRawImageReady() const {return mCachedRawImageReady ;}
 	BOOL        isRawImageValid()const { return mIsRawImageValid ; }	
 	void        forceToSaveRawImage(S32 desired_discard = 0) ;
+	/*virtual*/ void setCachedRawImage(S32 discard_level, LLImageRaw* imageraw) ;
 	void        destroySavedRawImage() ;
 	LLImageRaw* getSavedRawImage() ;
 	BOOL        hasSavedRawImage() const ;
@@ -457,15 +457,14 @@ public:
 
 protected:
 	/*virtual*/ void switchToCachedImage();
+	S32 getCurrentDiscardLevelForFetching() ;
 
 private:
 	void init(bool firstinit) ;
 	void cleanup() ;
 
 	void saveRawImage() ;
-	BOOL forceFetch() ;
 	void setCachedRawImage() ;
-	BOOL keepReuestedDiscardLevel();
 
 	//for atlas
 	void resetFaceAtlas() ;
diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp
index ee934ab9c5..eaef93a81d 100644
--- a/indra/newview/llviewertexturelist.cpp
+++ b/indra/newview/llviewertexturelist.cpp
@@ -502,10 +502,8 @@ void LLViewerTextureList::addImageToList(LLViewerFetchedTexture *image)
 	{
 		llerrs << "LLViewerTextureList::addImageToList - Image already in list" << llendl;
 	}
-	if ((mImageList.insert(image)).second != true)
-	{
-		llwarns << "BAD STUFF!  (mImageList.insert(image)).second != true" << llendl;
-	}
+	llassert((mImageList.insert(image)).second == true) ;
+	
 	image->setInImageList(TRUE) ;
 }
 
@@ -522,10 +520,8 @@ void LLViewerTextureList::removeImageFromList(LLViewerFetchedTexture *image)
 		}
 		llerrs << "LLViewerTextureList::removeImageFromList - Image not in list" << llendl;
 	}
-	if (mImageList.erase(image) != 1)
-        {
-                llwarns << "BAD STUFF!  mImageList.erase(image) != 1" << llendl;
-        }
+	llassert(mImageList.erase(image) == 1) ;
+      
 	image->setInImageList(FALSE) ;
 }
 
-- 
cgit v1.2.3