diff options
Diffstat (limited to 'indra/newview/lltexturefetch.cpp')
| -rw-r--r-- | indra/newview/lltexturefetch.cpp | 731 | 
1 files changed, 726 insertions, 5 deletions
| diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index f18aa8b4e6..e2af497a7d 100644 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -52,12 +52,20 @@  #include "llviewerstats.h"  #include "llviewerassetstats.h"  #include "llworld.h" +#include "llsdutil.h" +#include "llstartup.h" +#include "llviewerstats.h" + +bool LLTextureFetchDebugger::sDebuggerEnabled = false ; +LLStat LLTextureFetch::sCacheHitRate("texture_cache_hits", 128); +LLStat LLTextureFetch::sCacheReadLatency("texture_cache_read_latency", 128);  //////////////////////////////////////////////////////////////////////////////  class LLTextureFetchWorker : public LLWorkerClass  {  	friend class LLTextureFetch;  	friend class HTTPGetResponder; +	friend class LLTextureFetchDebugger;  private:  	class CacheReadResponder : public LLTextureCache::ReadResponder @@ -242,6 +250,8 @@ private:  	S32 mDecodedDiscard;  	LLFrameTimer mRequestedTimer;  	LLFrameTimer mFetchTimer; +	LLTimer			mCacheReadTimer; +	F32				mCacheReadTime;  	LLTextureCache::handle_t mCacheReadHandle;  	LLTextureCache::handle_t mCacheWriteHandle;  	U8* mBuffer; @@ -258,6 +268,7 @@ private:  	BOOL mNeedsAux;  	BOOL mHaveAllData;  	BOOL mInLocalCache; +	BOOL mInCache;  	bool mCanUseHTTP ;  	bool mCanUseNET ; //can get from asset server.  	S32 mHTTPFailCount; @@ -653,6 +664,7 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher,  	  mRequestedDiscard(-1),  	  mLoadedDiscard(-1),  	  mDecodedDiscard(-1), +	  mCacheReadTime(0.f),  	  mCacheReadHandle(LLTextureCache::nullHandle()),  	  mCacheWriteHandle(LLTextureCache::nullHandle()),  	  mBuffer(NULL), @@ -669,6 +681,7 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher,  	  mNeedsAux(FALSE),  	  mHaveAllData(FALSE),  	  mInLocalCache(FALSE), +	  mInCache(FALSE),  	  mCanUseHTTP(true),  	  mHTTPFailCount(0),  	  mRetryAttempt(0), @@ -838,6 +851,8 @@ void LLTextureFetchWorker::startWork(S32 param)  // Called from LLWorkerThread::processRequest()  bool LLTextureFetchWorker::doWork(S32 param)  { +	static const F32 FETCHING_TIMEOUT = 120.f;//seconds +  	LLMutexLock lock(&mWorkMutex);  	if ((mFetcher->isQuitting() || getFlags(LLWorkerClass::WCF_DELETE_REQUESTED))) @@ -896,6 +911,7 @@ bool LLTextureFetchWorker::doWork(S32 param)  		mCacheReadHandle = LLTextureCache::nullHandle();  		mCacheWriteHandle = LLTextureCache::nullHandle();  		mState = LOAD_FROM_TEXTURE_CACHE; +		mInCache = FALSE;  		mDesiredSize = llmax(mDesiredSize, TEXTURE_CACHE_ENTRY_SIZE); // min desired size is TEXTURE_CACHE_ENTRY_SIZE  		LL_DEBUGS("Texture") << mID << ": Priority: " << llformat("%8.0f",mImagePriority)  							 << " Desired Discard: " << mDesiredDiscard << " Desired Size: " << mDesiredSize << LL_ENDL; @@ -926,6 +942,7 @@ bool LLTextureFetchWorker::doWork(S32 param)  				CacheReadResponder* responder = new CacheReadResponder(mFetcher, mID, mFormattedImage);  				mCacheReadHandle = mFetcher->mTextureCache->readFromCache(filename, mID, cache_priority,  																		  offset, size, responder); +				mCacheReadTimer.reset();  			}  			else if (mUrl.empty())  			{ @@ -934,6 +951,7 @@ bool LLTextureFetchWorker::doWork(S32 param)  				CacheReadResponder* responder = new CacheReadResponder(mFetcher, mID, mFormattedImage);  				mCacheReadHandle = mFetcher->mTextureCache->readFromCache(mID, cache_priority,  																		  offset, size, responder); +				mCacheReadTimer.reset();  			}  			else if(mCanUseHTTP)  			{ @@ -982,11 +1000,12 @@ bool LLTextureFetchWorker::doWork(S32 param)  			llassert_always(mFormattedImage->getDataSize() > 0);  			mLoadedDiscard = mDesiredDiscard;  			mState = DECODE_IMAGE; +			mInCache = TRUE;  			mWriteToCacheState = NOT_WRITE ;  			LL_DEBUGS("Texture") << mID << ": Cached. Bytes: " << mFormattedImage->getDataSize()  								 << " Size: " << llformat("%dx%d",mFormattedImage->getWidth(),mFormattedImage->getHeight())  								 << " Desired Discard: " << mDesiredDiscard << " Desired Size: " << mDesiredSize << LL_ENDL; -			// fall through +			LLTextureFetch::sCacheHitRate.addValue(100.f);  		}  		else  		{ @@ -1002,6 +1021,7 @@ bool LLTextureFetchWorker::doWork(S32 param)  				mState = LOAD_FROM_NETWORK;  			}  			// fall through +			LLTextureFetch::sCacheHitRate.addValue(0.f);  		}  	} @@ -1177,6 +1197,8 @@ bool LLTextureFetchWorker::doWork(S32 param)  			bool res = false;  			if (!mUrl.empty())  			{ +				mRequestedTimer.reset(); +  				mLoaded = FALSE;  				mGetStatus = 0;  				mGetReason.clear(); @@ -1335,6 +1357,13 @@ bool LLTextureFetchWorker::doWork(S32 param)  		}  		else  		{ +			if(FETCHING_TIMEOUT < mRequestedTimer.getElapsedTimeF32()) +			{ +				//timeout, abort. +				mState = DONE; +				return true; +			} +  			setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority);  			return false;  		} @@ -1396,6 +1425,11 @@ bool LLTextureFetchWorker::doWork(S32 param)  	{  		if (mDecoded)  		{ +			if(mFetcher->getFetchDebugger() && !mInLocalCache) +			{ +				mFetcher->getFetchDebugger()->addHistoryEntry(this); +			} +  			if (mDecodedDiscard < 0)  			{  				LL_DEBUGS("Texture") << mID << ": Failed to Decode." << LL_ENDL; @@ -1780,6 +1814,7 @@ void LLTextureFetchWorker::callbackDecoded(bool success, LLImageRaw* raw, LLImag  	mDecoded = TRUE;  // 	llinfos << mID << " : DECODE COMPLETE " << llendl;  	setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); +	mCacheReadTime = mCacheReadTimer.getElapsedTimeF32();  }  ////////////////////////////////////////////////////////////////////////////// @@ -1824,11 +1859,18 @@ LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* image  	  mHTTPTextureBits(0),  	  mTotalHTTPRequests(0),  	  mCurlGetRequest(NULL), -	  mQAMode(qa_mode) +	  mQAMode(qa_mode), +	  mFetchDebugger(NULL)  {  	mCurlPOSTRequestCount = 0;  	mMaxBandwidth = gSavedSettings.getF32("ThrottleBandwidthKBPS");  	mTextureInfo.setUpLogging(gSavedSettings.getBOOL("LogTextureDownloadsToViewerLog"), gSavedSettings.getBOOL("LogTextureDownloadsToSimulator"), gSavedSettings.getU32("TextureLoggingThreshold")); + +	LLTextureFetchDebugger::sDebuggerEnabled = gSavedSettings.getBOOL("TextureFetchDebuggerEnabled"); +	if(LLTextureFetchDebugger::isEnabled()) +	{ +		mFetchDebugger = new LLTextureFetchDebugger(this, cache, imagedecodethread) ; +	}  }  LLTextureFetch::~LLTextureFetch() @@ -1843,11 +1885,17 @@ LLTextureFetch::~LLTextureFetch()  	}  	// ~LLQueuedThread() called here + +	delete mFetchDebugger;  }  bool LLTextureFetch::createRequest(const std::string& url, const LLUUID& id, const LLHost& host, F32 priority,  								   S32 w, S32 h, S32 c, S32 desired_discard, bool needs_aux, bool can_use_http)  { +	if(mFetcherLocked) +	{ +		return false; +	}  	if (mDebugPause)  	{  		return false; @@ -2092,6 +2140,11 @@ bool LLTextureFetch::getRequestFinished(const LLUUID& id, S32& discard_level,  			discard_level = worker->mDecodedDiscard;  			raw = worker->mRawImage;  			aux = worker->mAuxImage; +			F32 cache_read_time = worker->mCacheReadTime; +			if (cache_read_time != 0.f) +			{ +				sCacheReadLatency.addValue(cache_read_time * 1000.f); +			}  			res = true;  			LL_DEBUGS("Texture") << id << ": Request Finished. State: " << worker->mState << " Discard: " << discard_level << LL_ENDL;  			worker->unlockWorkMutex(); @@ -2222,7 +2275,13 @@ S32 LLTextureFetch::update(F32 max_time_ms)  	if (!mDebugPause)  	{ -		sendRequestListToSimulators(); +		// this is the startup state when send_complete_agent_movement() message is sent. +		// Before this, the RequestImages message sent by sendRequestListToSimulators  +		// won't work so don't bother trying +		if (LLStartUp::getStartupState() > STATE_AGENT_SEND) +		{ +			sendRequestListToSimulators(); +		}  	}  	if (!mThreaded) @@ -2258,6 +2317,11 @@ void LLTextureFetch::startThread()  {  	// Construct mCurlGetRequest from Worker Thread  	mCurlGetRequest = new LLCurlRequest(); +	 +	if(mFetchDebugger) +	{ +		mFetchDebugger->setCurlGetRequest(mCurlGetRequest); +	}  }  // WORKER THREAD @@ -2266,6 +2330,10 @@ void LLTextureFetch::endThread()  	// Destroy mCurlGetRequest from Worker Thread  	delete mCurlGetRequest;  	mCurlGetRequest = NULL; +	if(mFetchDebugger) +	{ +		mFetchDebugger->setCurlGetRequest(NULL); +	}  }  // WORKER THREAD @@ -2803,7 +2871,6 @@ void LLTextureFetch::cmdDoWork()  	}  } -  //////////////////////////////////////////////////////////////////////////////  // Private (anonymous) class methods implementing the command scheme. @@ -2959,7 +3026,7 @@ TFReqSendMetrics::doWork(LLTextureFetch * fetcher)  	// In QA mode, Metrics submode, log the result for ease of testing  	if (fetcher->isQAMode())  	{ -		LL_INFOS("Textures") << merged_llsd << LL_ENDL; +		LL_INFOS("Textures") << ll_pretty_print_sd(merged_llsd) << LL_ENDL;  	}  	gViewerAssetStatsThread1->reset(); @@ -3007,5 +3074,659 @@ truncate_viewer_metrics(int max_regions, LLSD & metrics)  } // end of anonymous namespace +/////////////////////////////////////////////////////////////////////////////////////////// +//Start LLTextureFetchDebugger +/////////////////////////////////////////////////////////////////////////////////////////// +//--------------------- +class LLDebuggerCacheReadResponder : public LLTextureCache::ReadResponder +{ +public: +	LLDebuggerCacheReadResponder(LLTextureFetchDebugger* debugger, S32 id, LLImageFormatted* image) +		: mDebugger(debugger), mID(id) +	{ +		setImage(image); +	} +	virtual void completed(bool success) +	{ +		mDebugger->callbackCacheRead(mID, success, mFormattedImage, mImageSize, mImageLocal); +	} +private: +	LLTextureFetchDebugger* mDebugger; +	S32 mID; +}; + +class LLDebuggerCacheWriteResponder : public LLTextureCache::WriteResponder +{ +public: +	LLDebuggerCacheWriteResponder(LLTextureFetchDebugger* debugger, S32 id) +		: mDebugger(debugger), mID(id) +	{ +	} +	virtual void completed(bool success) +	{ +		mDebugger->callbackCacheWrite(mID, success); +	} +private: +	LLTextureFetchDebugger* mDebugger; +	S32 mID; +}; + +class LLDebuggerDecodeResponder : public LLImageDecodeThread::Responder +{ +public: +	LLDebuggerDecodeResponder(LLTextureFetchDebugger* debugger, S32 id) +		: mDebugger(debugger), mID(id) +	{ +	} +	virtual void completed(bool success, LLImageRaw* raw, LLImageRaw* aux) +	{ +		mDebugger->callbackDecoded(mID, success, raw, aux); +	} +private: +	LLTextureFetchDebugger* mDebugger; +	S32 mID; +}; + +class LLDebuggerHTTPResponder : public LLCurl::Responder +{ +public: +	LLDebuggerHTTPResponder(LLTextureFetchDebugger* debugger, S32 index) +	: mDebugger(debugger), mIndex(index) +	{ +	} +	virtual void completedRaw(U32 status, const std::string& reason, +							  const LLChannelDescriptors& channels, +							  const LLIOPipe::buffer_ptr_t& buffer) +	{ +		bool success = false; +		bool partial = false; +		if (HTTP_OK <= status &&  status < HTTP_MULTIPLE_CHOICES) +		{ +			success = true; +			if (HTTP_PARTIAL_CONTENT == status) // partial information +			{ +				partial = true; +			} +		} +		if (!success) +		{ +			llinfos << "Fetch Debugger : CURL GET FAILED, index = " << mIndex << ", status:" << status << " reason:" << reason << llendl; +		} +		mDebugger->callbackHTTP(mIndex, channels, buffer, partial, success); +	} +	virtual bool followRedir() +	{ +		return true; +	} +private: +	LLTextureFetchDebugger* mDebugger; +	S32 mIndex; +}; + +LLTextureFetchDebugger::LLTextureFetchDebugger(LLTextureFetch* fetcher, LLTextureCache* cache, LLImageDecodeThread* imagedecodethread) : +	mFetcher(fetcher), +	mTextureCache(cache), +	mImageDecodeThread(imagedecodethread), +	mCurlGetRequest(NULL) +{ +	init(); +} +	 +LLTextureFetchDebugger::~LLTextureFetchDebugger() +{ +	mFetchingHistory.clear(); +	stopDebug(); +} + +void LLTextureFetchDebugger::init() +{ +	mState = IDLE; +	 +	mCacheReadTime = -1.f; +	mCacheWriteTime = -1.f; +	mDecodingTime = -1.f; +	mHTTPTime = -1.f; +	mGLCreationTime = -1.f; +	mTotalFetchingTime = 0.f; +	mRefetchVisCacheTime = -1.f; +	mRefetchVisHTTPTime = -1.f; + +	mNumFetchedTextures = 0; +	mNumCacheHits = 0; +	mNumVisibleFetchedTextures = 0; +	mNumVisibleFetchingRequests = 0; +	mFetchedData = 0; +	mDecodedData = 0; +	mVisibleFetchedData = 0; +	mVisibleDecodedData = 0; +	mRenderedData = 0; +	mRenderedDecodedData = 0; +	mFetchedPixels = 0; +	mRenderedPixels = 0; +	mRefetchedData = 0; +	mRefetchedPixels = 0; + +	mFreezeHistory = FALSE; +} + +void LLTextureFetchDebugger::startDebug() +{ +	//lock the fetcher +	mFetcher->lockFetcher(true); +	mFreezeHistory = TRUE; + +	//clear the current fetching queue +	gTextureList.clearFetchingRequests(); + +	//wait for all works to be done +	while(1) +	{ +		S32 pending = 0; +		pending += LLAppViewer::getTextureCache()->update(1);  +		pending += LLAppViewer::getImageDecodeThread()->update(1);  +		pending += LLAppViewer::getTextureFetch()->update(1);  +		if(!pending) +		{ +			break; +		} +	} + +	//collect statistics +	mTotalFetchingTime = gDebugTimers[0].getElapsedTimeF32() - mTotalFetchingTime; +	 +	std::set<LLUUID> fetched_textures; +	S32 size = mFetchingHistory.size(); +	for(S32 i = 0 ; i < size; i++) +	{ +		bool in_list = true; +		if(fetched_textures.find(mFetchingHistory[i].mID) == fetched_textures.end()) +		{ +			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(); +			} +		} +	} + +	mNumFetchedTextures = fetched_textures.size(); +} + +void LLTextureFetchDebugger::stopDebug() +{ +	//clear the current debug work +	S32 size = mFetchingHistory.size(); +	switch(mState) +	{ +	case READ_CACHE:		 +		for(S32 i = 0 ; i < size; i++) +		{ +			if (mFetchingHistory[i]. mCacheHandle != LLTextureCache::nullHandle()) +			{ +				mTextureCache->readComplete(mFetchingHistory[i].mCacheHandle, true); +			} +		}	 +		break; +	case WRITE_CACHE: +		for(S32 i = 0 ; i < size; i++) +		{ +			if (mFetchingHistory[i].mCacheHandle != LLTextureCache::nullHandle()) +			{ +				mTextureCache->writeComplete(mFetchingHistory[i].mCacheHandle, true); +			} +		} +		break; +	case DECODING: +		break; +	case HTTP_FETCHING: +		break; +	case GL_TEX: +		break; +	default: +		break; +	} + +	while(1) +	{ +		if(update()) +		{ +			break; +		} +	} + +	//unlock the fetcher +	mFetcher->lockFetcher(false); +	mFreezeHistory = FALSE; +	mTotalFetchingTime = gDebugTimers[0].getElapsedTimeF32(); //reset +} + +//called in the main thread and when the fetching queue is empty +void LLTextureFetchDebugger::clearHistory() +{ +	mFetchingHistory.clear(); +	init(); +} + +void LLTextureFetchDebugger::addHistoryEntry(LLTextureFetchWorker* worker) +{ +	if(mFreezeHistory) +	{ +		mRefetchedPixels += worker->mRawImage->getWidth() * worker->mRawImage->getHeight(); +		mRefetchedData += worker->mFormattedImage->getDataSize(); +		return; +	} + +	if(worker->mInCache) +	{ +		mNumCacheHits++; +	} +	mFetchedData += worker->mFormattedImage->getDataSize(); +	mDecodedData += worker->mRawImage->getDataSize(); +	mFetchedPixels += worker->mRawImage->getWidth() * worker->mRawImage->getHeight(); + +	mFetchingHistory.push_back(FetchEntry(worker->mID, worker->mDesiredSize, worker->mDecodedDiscard, worker->mFormattedImage->getDataSize(), worker->mRawImage->getDataSize())); +	//mFetchingHistory.push_back(FetchEntry(worker->mID, worker->mDesiredSize, worker->mHaveAllData ? 0 : worker->mLoadedDiscard, worker->mFormattedImage->getComponents(), +		//worker->mDecodedDiscard, worker->mFormattedImage->getDataSize(), worker->mRawImage->getDataSize())); +} + +void LLTextureFetchDebugger::lockCache() +{ +} +	 +void LLTextureFetchDebugger::unlockCache() +{ +} +	 +void LLTextureFetchDebugger::debugCacheRead() +{ +	lockCache(); +	llassert_always(mState == IDLE); +	mTimer.reset(); +	mState = READ_CACHE; + +	S32 size = mFetchingHistory.size(); +	for(S32 i = 0 ; i < size ; i++) +	{		 +		mFetchingHistory[i].mFormattedImage = NULL; +		mFetchingHistory[i].mCacheHandle = mTextureCache->readFromCache(mFetchingHistory[i].mID, LLWorkerThread::PRIORITY_NORMAL, 0, mFetchingHistory[i].mFetchedSize,  +			new LLDebuggerCacheReadResponder(this, i, mFetchingHistory[i].mFormattedImage)); +	} +} +	 +void LLTextureFetchDebugger::clearCache() +{ +	S32 size = mFetchingHistory.size(); +	{ +		std::set<LLUUID> deleted_list; +		for(S32 i = 0 ; i < size ; i++) +		{ +			if(deleted_list.find(mFetchingHistory[i].mID) == deleted_list.end()) +			{ +				deleted_list.insert(mFetchingHistory[i].mID); +				mTextureCache->removeFromCache(mFetchingHistory[i].mID); +			} +		} +	} +} + +void LLTextureFetchDebugger::debugCacheWrite() +{ +	//remove from cache +	clearCache(); + +	lockCache(); +	llassert_always(mState == IDLE); +	mTimer.reset(); +	mState = WRITE_CACHE; + +	S32 size = mFetchingHistory.size(); +	for(S32 i = 0 ; i < size ; i++) +	{		 +		if(mFetchingHistory[i].mFormattedImage.notNull()) +		{ +			mFetchingHistory[i].mCacheHandle = mTextureCache->writeToCache(mFetchingHistory[i].mID, LLWorkerThread::PRIORITY_NORMAL,  +				mFetchingHistory[i].mFormattedImage->getData(), mFetchingHistory[i].mFetchedSize, +				mFetchingHistory[i].mDecodedLevel == 0 ? mFetchingHistory[i].mFetchedSize : mFetchingHistory[i].mFetchedSize + 1,  +				new LLDebuggerCacheWriteResponder(this, i));					 +		} +	} +} + +void LLTextureFetchDebugger::lockDecoder() +{ +} +	 +void LLTextureFetchDebugger::unlockDecoder() +{ +} + +void LLTextureFetchDebugger::debugDecoder() +{ +	lockDecoder(); +	llassert_always(mState == IDLE); +	mTimer.reset(); +	mState = DECODING; + +	S32 size = mFetchingHistory.size(); +	for(S32 i = 0 ; i < size ; i++) +	{		 +		if(mFetchingHistory[i].mFormattedImage.isNull()) +		{ +			continue; +		} + +		mImageDecodeThread->decodeImage(mFetchingHistory[i].mFormattedImage, LLWorkerThread::PRIORITY_NORMAL,  +			mFetchingHistory[i].mDecodedLevel, mFetchingHistory[i].mNeedsAux, +			new LLDebuggerDecodeResponder(this, i)); +	} +} + +void LLTextureFetchDebugger::debugHTTP() +{ +	llassert_always(mState == IDLE); + +	LLViewerRegion* region = gAgent.getRegion(); +	if (!region) +	{ +		llinfos << "Fetch Debugger : Current region undefined. Cannot fetch textures through HTTP." << llendl; +		return; +	} +	 +	mHTTPUrl = region->getHttpUrl(); +	if (mHTTPUrl.empty()) +	{ +		llinfos << "Fetch Debugger : Current region URL undefined. Cannot fetch textures through HTTP." << llendl; +		return; +	} +	 +	mTimer.reset(); +	mState = HTTP_FETCHING; +	 +	S32 size = mFetchingHistory.size(); +	for (S32 i = 0 ; i < size ; i++) +	{ +		mFetchingHistory[i].mCurlState = FetchEntry::CURL_NOT_DONE; +		mFetchingHistory[i].mCurlReceivedSize = 0; +		mFetchingHistory[i].mHTTPFailCount = 0; +	} +	mNbCurlRequests = 0; +	mNbCurlCompleted = 0; +	 +	fillCurlQueue(); +} + +S32 LLTextureFetchDebugger::fillCurlQueue() +{ +	if (mNbCurlRequests == 24) +		return mNbCurlRequests; +	 +	S32 size = mFetchingHistory.size(); +	for (S32 i = 0 ; i < size ; i++) +	{		 +		if (mFetchingHistory[i].mCurlState != FetchEntry::CURL_NOT_DONE) +			continue; +		std::string texture_url = mHTTPUrl + "/?texture_id=" + mFetchingHistory[i].mID.asString().c_str(); +		S32 requestedSize = mFetchingHistory[i].mRequestedSize; +		// We request the whole file if the size was not set. +		requestedSize = llmax(0,requestedSize); +		// We request the whole file if the size was set to an absurdly high value (meaning all file) +		requestedSize = (requestedSize == 33554432 ? 0 : requestedSize); +		std::vector<std::string> headers; +		headers.push_back("Accept: image/x-j2c"); +		bool res = mCurlGetRequest->getByteRange(texture_url, headers, 0, requestedSize, new LLDebuggerHTTPResponder(this, i)); +		if (res) +		{ +			mFetchingHistory[i].mCurlState = FetchEntry::CURL_IN_PROGRESS; +			mNbCurlRequests++; +			// Hack +			if (mNbCurlRequests == 24) +				break; +		} +		else  +		{ +			break; +		} +	} +	//llinfos << "Fetch Debugger : Having " << mNbCurlRequests << " requests through the curl thread." << llendl; +	return mNbCurlRequests; +} + +void LLTextureFetchDebugger::debugGLTextureCreation() +{ +	llassert_always(mState == IDLE); +	mState = GL_TEX; +	std::vector<LLViewerFetchedTexture*> tex_list; + +	S32 size = mFetchingHistory.size(); +	for(S32 i = 0 ; i < size ; i++) +	{ +		if(mFetchingHistory[i].mRawImage.notNull()) +		{ +			LLViewerFetchedTexture* tex = gTextureList.findImage(mFetchingHistory[i].mID) ; +			if(tex && !tex->isForSculptOnly()) +			{ +				tex->destroyGLTexture() ; +				tex_list.push_back(tex); +			} +		} +	} + +	mTimer.reset(); +	S32 j = 0 ; +	S32 size1 = tex_list.size(); +	for(S32 i = 0 ; i < size && j < size1; i++) +	{ +		if(mFetchingHistory[i].mRawImage.notNull()) +		{ +			if(mFetchingHistory[i].mID == tex_list[j]->getID()) +			{ +				tex_list[j]->createGLTexture(mFetchingHistory[i].mDecodedLevel, mFetchingHistory[i].mRawImage, 0, TRUE, tex_list[j]->getBoostLevel()); +				j++; +			} +		} +	} + +	mGLCreationTime = mTimer.getElapsedTimeF32() ; +	return; +} + +//clear fetching results of all textures. +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() ; +		} +	} +} + +void LLTextureFetchDebugger::debugRefetchVisibleFromCache() +{ +	llassert_always(mState == IDLE); +	mState = REFETCH_VIS_CACHE; + +	clearTextures(); + +	mTimer.reset(); +	mFetcher->lockFetcher(false); +} + +void LLTextureFetchDebugger::debugRefetchVisibleFromHTTP() +{ +	llassert_always(mState == IDLE); +	mState = REFETCH_VIS_HTTP; + +	clearCache(); +	clearTextures(); + +	mTimer.reset(); +	mFetcher->lockFetcher(false); +} + +bool LLTextureFetchDebugger::update() +{ +	switch(mState) +	{ +	case READ_CACHE: +		if(!mTextureCache->update(1)) +		{ +			mCacheReadTime = mTimer.getElapsedTimeF32() ; +			mState = IDLE; +			unlockCache(); +		} +		break; +	case WRITE_CACHE: +		if(!mTextureCache->update(1)) +		{ +			mCacheWriteTime = mTimer.getElapsedTimeF32() ; +			mState = IDLE; +			unlockCache(); +		} +		break; +	case DECODING: +		if(!mImageDecodeThread->update(1)) +		{ +			mDecodingTime =  mTimer.getElapsedTimeF32() ; +			mState = IDLE; +			unlockDecoder(); +		} +		break; +	case HTTP_FETCHING: +		mCurlGetRequest->process(); +		LLCurl::getCurlThread()->update(1); +		if (!fillCurlQueue() && mNbCurlCompleted == mFetchingHistory.size()) +		{ +			mHTTPTime =  mTimer.getElapsedTimeF32() ; +			mState = IDLE; +		} +		break; +	case GL_TEX: +		mState = IDLE; +		break; +	case REFETCH_VIS_CACHE: +		if (LLAppViewer::getTextureFetch()->getNumRequests() == 0) +		{ +			mRefetchVisCacheTime = gDebugTimers[0].getElapsedTimeF32() - mTotalFetchingTime; +			mState = IDLE; +			mFetcher->lockFetcher(true); +		} +		break; +	case REFETCH_VIS_HTTP: +		if (LLAppViewer::getTextureFetch()->getNumRequests() == 0) +		{ +			mRefetchVisHTTPTime = gDebugTimers[0].getElapsedTimeF32() - mTotalFetchingTime; +			mState = IDLE; +			mFetcher->lockFetcher(true); +		} +		break; +	default: +		mState = IDLE; +		break; +	} + +	return mState == IDLE; +} + +void LLTextureFetchDebugger::callbackCacheRead(S32 id, bool success, LLImageFormatted* image, +						   S32 imagesize, BOOL islocal) +{ +	if (success) +	{ +		mFetchingHistory[id].mFormattedImage = image; +	} +	mTextureCache->readComplete(mFetchingHistory[id].mCacheHandle, false); +	mFetchingHistory[id].mCacheHandle = LLTextureCache::nullHandle(); +} + +void LLTextureFetchDebugger::callbackCacheWrite(S32 id, bool success) +{ +	mTextureCache->writeComplete(mFetchingHistory[id].mCacheHandle); +	mFetchingHistory[id].mCacheHandle = LLTextureCache::nullHandle(); +} + +void LLTextureFetchDebugger::callbackDecoded(S32 id, bool success, LLImageRaw* raw, LLImageRaw* aux) +{ +	if (success) +	{ +		llassert_always(raw); +		mFetchingHistory[id].mRawImage = raw; +	} +} + +void LLTextureFetchDebugger::callbackHTTP(S32 id, const LLChannelDescriptors& channels, +										  const LLIOPipe::buffer_ptr_t& buffer,  +										  bool partial, bool success) +{ +	mNbCurlRequests--; +	if (success) +	{ +		mFetchingHistory[id].mCurlState = FetchEntry::CURL_DONE; +		mNbCurlCompleted++; + +		S32 data_size = buffer->countAfter(channels.in(), NULL); +		mFetchingHistory[id].mCurlReceivedSize += data_size; +		//llinfos << "Fetch Debugger : got results for " << id << ", data_size = " << data_size << ", received = " << mFetchingHistory[id].mCurlReceivedSize << ", requested = " << mFetchingHistory[id].mRequestedSize << ", partial = " << partial << llendl; +		if ((mFetchingHistory[id].mCurlReceivedSize >= mFetchingHistory[id].mRequestedSize) || !partial || (mFetchingHistory[id].mRequestedSize == 600)) +		{ +			U8* d_buffer = (U8*)ALLOCATE_MEM(LLImageBase::getPrivatePool(), data_size); +			buffer->readAfter(channels.in(), NULL, d_buffer, data_size); +			 +			llassert_always(mFetchingHistory[id].mFormattedImage.isNull()); +			{ +				// For now, create formatted image based on extension +				std::string texture_url = mHTTPUrl + "/?texture_id=" + mFetchingHistory[id].mID.asString().c_str(); +				std::string extension = gDirUtilp->getExtension(texture_url); +				mFetchingHistory[id].mFormattedImage = LLImageFormatted::createFromType(LLImageBase::getCodecFromExtension(extension)); +				if (mFetchingHistory[id].mFormattedImage.isNull()) +				{ +					mFetchingHistory[id].mFormattedImage = new LLImageJ2C; // default +				} +			} +						 +			mFetchingHistory[id].mFormattedImage->setData(d_buffer, data_size);	 +		} +	} +	else //failed +	{ +		mFetchingHistory[id].mHTTPFailCount++; +		if(mFetchingHistory[id].mHTTPFailCount < 5) +		{ +			// Fetch will have to be redone +			mFetchingHistory[id].mCurlState = FetchEntry::CURL_NOT_DONE; +		} +		else //skip +		{ +			mFetchingHistory[id].mCurlState = FetchEntry::CURL_DONE; +			mNbCurlCompleted++; +		} +	} +} + + +//--------------------- +/////////////////////////////////////////////////////////////////////////////////////////// +//End LLTextureFetchDebugger +/////////////////////////////////////////////////////////////////////////////////////////// | 
