diff options
Diffstat (limited to 'indra/newview/lltexturefetch.cpp')
-rw-r--r-- | indra/newview/lltexturefetch.cpp | 732 |
1 files changed, 727 insertions, 5 deletions
diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index f18aa8b4e6..7e6dfbc9d9 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,19 @@ LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* image mHTTPTextureBits(0), mTotalHTTPRequests(0), mCurlGetRequest(NULL), - mQAMode(qa_mode) + mQAMode(qa_mode), + mFetchDebugger(NULL), + mFetcherLocked(FALSE) { 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 +1886,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 +2141,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 +2276,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 +2318,11 @@ void LLTextureFetch::startThread() { // Construct mCurlGetRequest from Worker Thread mCurlGetRequest = new LLCurlRequest(); + + if(mFetchDebugger) + { + mFetchDebugger->setCurlGetRequest(mCurlGetRequest); + } } // WORKER THREAD @@ -2266,6 +2331,10 @@ void LLTextureFetch::endThread() // Destroy mCurlGetRequest from Worker Thread delete mCurlGetRequest; mCurlGetRequest = NULL; + if(mFetchDebugger) + { + mFetchDebugger->setCurlGetRequest(NULL); + } } // WORKER THREAD @@ -2803,7 +2872,6 @@ void LLTextureFetch::cmdDoWork() } } - ////////////////////////////////////////////////////////////////////////////// // Private (anonymous) class methods implementing the command scheme. @@ -2959,7 +3027,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 +3075,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 +/////////////////////////////////////////////////////////////////////////////////////////// |