summaryrefslogtreecommitdiff
path: root/indra/newview/lltexturefetch.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/lltexturefetch.cpp')
-rwxr-xr-xindra/newview/lltexturefetch.cpp605
1 files changed, 451 insertions, 154 deletions
diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp
index 7e6dfbc9d9..b148b8b76d 100755
--- a/indra/newview/lltexturefetch.cpp
+++ b/indra/newview/lltexturefetch.cpp
@@ -151,7 +151,7 @@ public:
/*virtual*/ bool doWork(S32 param); // Called from LLWorkerThread::processRequest()
/*virtual*/ void finishWork(S32 param, bool completed); // called from finishRequest() (WORK THREAD)
/*virtual*/ bool deleteOK(); // called from update() (WORK THREAD)
-
+
~LLTextureFetchWorker();
// void relese() { --mActiveCount; }
@@ -196,6 +196,8 @@ private:
bool processSimulatorPackets();
bool writeToCacheComplete();
+ void removeFromHTTPQueue();
+
void lockWorkMutex() { mWorkMutex.lock(); }
void unlockWorkMutex() { mWorkMutex.unlock(); }
@@ -275,6 +277,8 @@ private:
S32 mRetryAttempt;
S32 mActiveCount;
U32 mGetStatus;
+ U32 mHTTPHandle;
+ F32 mDelay;
std::string mGetReason;
// Work Data
@@ -328,6 +332,7 @@ public:
mFetcher->mTextureInfo.setRequestCompleteTimeAndLog(mID, timeNow);
}
+ S32 data_size = 0;
lldebugs << "HTTP COMPLETE: " << mID << llendl;
LLTextureFetchWorker* worker = mFetcher->getWorker(mID);
if (worker)
@@ -349,7 +354,7 @@ public:
// llwarns << "CURL GET FAILED, status:" << status << " reason:" << reason << llendl;
}
- S32 data_size = worker->callbackHttpGet(channels, buffer, partial, success);
+ data_size = worker->callbackHttpGet(channels, buffer, partial, success);
if(log_texture_traffic && data_size > 0)
{
@@ -359,9 +364,7 @@ public:
gTotalTextureBytesPerBoostLevel[tex->getBoostLevel()] += data_size ;
}
}
-
- mFetcher->removeFromHTTPQueue(mID, data_size);
-
+
if (worker->mMetricsStartTime)
{
LLViewerAssetStatsFF::record_response_thread1(LLViewerAssetType::AT_TEXTURE,
@@ -376,9 +379,10 @@ public:
}
else
{
- mFetcher->removeFromHTTPQueue(mID);
- llwarns << "Worker not found: " << mID << llendl;
+ llwarns << "Worker not found: " << mID << llendl;
}
+
+ mFetcher->getCurlRequest().completeRequest(data_size);
}
virtual bool followRedir()
@@ -692,10 +696,12 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher,
mLastPacket(-1),
mTotalPackets(0),
mImageCodec(IMG_CODEC_INVALID),
- mMetricsStartTime(0)
+ mMetricsStartTime(0),
+ mHTTPHandle(0),
+ mDelay(-1.f)
{
mCanUseNET = mUrl.empty() ;
-
+
calcWorkPriority();
mType = host.isOk() ? LLImageBase::TYPE_AVATAR_BAKE : LLImageBase::TYPE_NORMAL;
// llinfos << "Create: " << mID << " mHost:" << host << " Discard=" << discard << llendl;
@@ -726,7 +732,19 @@ LLTextureFetchWorker::~LLTextureFetchWorker()
mFormattedImage = NULL;
clearPackets();
unlockWorkMutex();
- mFetcher->removeFromHTTPQueue(mID);
+
+ removeFromHTTPQueue();
+}
+
+void LLTextureFetchWorker::removeFromHTTPQueue()
+{
+ if(mHTTPHandle > 0)
+ {
+ llassert_always(mState == WAIT_HTTP_REQ);
+
+ mFetcher->getCurlRequest().removeRequest(mHTTPHandle);
+ mHTTPHandle = 0;
+ }
}
void LLTextureFetchWorker::clearPackets()
@@ -824,6 +842,7 @@ void LLTextureFetchWorker::setImagePriority(F32 priority)
mImagePriority = priority;
calcWorkPriority();
U32 work_priority = mWorkPriority | (getPriority() & LLWorkerThread::PRIORITY_HIGHBITS);
+ mFetcher->getCurlRequest().updatePriority(mHTTPHandle, mWorkPriority);
setPriority(work_priority);
}
}
@@ -851,8 +870,6 @@ 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)))
@@ -912,6 +929,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
mCacheWriteHandle = LLTextureCache::nullHandle();
mState = LOAD_FROM_TEXTURE_CACHE;
mInCache = FALSE;
+ mDelay = -1.f;
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;
@@ -927,7 +945,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
S32 size = mDesiredSize - offset;
if (size <= 0)
{
- mState = CACHE_POST;
+ mState = CACHE_POST; //have enough data, will fall to decode
return false;
}
mFileSize = 0;
@@ -944,7 +962,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
offset, size, responder);
mCacheReadTimer.reset();
}
- else if (mUrl.empty())
+ else if (mUrl.empty() && mFetcher->canLoadFromCache())
{
setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); // Set priority first since Responder may change it
@@ -953,7 +971,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
offset, size, responder);
mCacheReadTimer.reset();
}
- else if(mCanUseHTTP)
+ else if(!mUrl.empty() && mCanUseHTTP)
{
if (!(mUrl.compare(0, 7, "http://") == 0))
{
@@ -981,6 +999,9 @@ bool LLTextureFetchWorker::doWork(S32 param)
}
else
{
+ //
+ //This should never happen
+ //
return false;
}
}
@@ -1020,6 +1041,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
LL_DEBUGS("Texture") << mID << ": Not in Cache" << LL_ENDL;
mState = LOAD_FROM_NETWORK;
}
+
// fall through
LLTextureFetch::sCacheHitRate.addValue(0.f);
}
@@ -1060,7 +1082,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
}
if (mCanUseHTTP && !mUrl.empty())
{
- mState = LLTextureFetchWorker::SEND_HTTP_REQ;
+ mState = SEND_HTTP_REQ;
setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);
if(mWriteToCacheState != NOT_WRITE)
{
@@ -1156,17 +1178,6 @@ bool LLTextureFetchWorker::doWork(S32 param)
{
if(mCanUseHTTP)
{
- //NOTE:
- //control the number of the http requests issued for:
- //1, not openning too many file descriptors at the same time;
- //2, control the traffic of http so udp gets bandwidth.
- //
- static const S32 MAX_NUM_OF_HTTP_REQUESTS_IN_QUEUE = 8 ;
- if(mFetcher->getNumHTTPRequests() > MAX_NUM_OF_HTTP_REQUESTS_IN_QUEUE)
- {
- return false ; //wait.
- }
-
mFetcher->removeFromNetworkQueue(this, false);
S32 cur_size = 0;
@@ -1179,6 +1190,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
{
// We already have all the data, just decode it
mLoadedDiscard = mFormattedImage->getDiscardLevel();
+ setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);
mState = DECODE_IMAGE;
return false;
}
@@ -1209,7 +1221,6 @@ bool LLTextureFetchWorker::doWork(S32 param)
setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority);
mState = WAIT_HTTP_REQ;
- mFetcher->addToHTTPQueue(mID);
if (! mMetricsStartTime)
{
mMetricsStartTime = LLViewerAssetStatsFF::get_timestamp();
@@ -1221,8 +1232,16 @@ bool LLTextureFetchWorker::doWork(S32 param)
// Will call callbackHttpGet when curl request completes
std::vector<std::string> headers;
headers.push_back("Accept: image/x-j2c");
- res = mFetcher->mCurlGetRequest->getByteRange(mUrl, headers, offset, mRequestedSize,
- new HTTPGetResponder(mFetcher, mID, LLTimer::getTotalTime(), mRequestedSize, offset, true));
+ // If we try to fetch the whole file, we set the size to 0 so that we generate the correct curl range request
+ // Note: it looks a bit hacky but we need to limit this (size==0) to mean "whole file" to HTTP only as it messes up UDP fetching
+ if ((offset+mRequestedSize) == MAX_IMAGE_DATA_SIZE)
+ {
+ mRequestedSize = 0;
+ }
+ mHTTPHandle = mFetcher->mCurlGetRequest->getByteRange(mUrl, headers, offset, mRequestedSize, mWorkPriority,
+ new HTTPGetResponder(mFetcher, mID, LLTimer::getTotalTime(), mRequestedSize, offset, true), mDelay);
+ mDelay = -1.f; //reset
+ res = true;
}
if (!res)
{
@@ -1257,6 +1276,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
{
mState = INIT ;
mCanUseHTTP = false ;
+ mUrl.clear();
setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);
return false ;
}
@@ -1269,12 +1289,15 @@ bool LLTextureFetchWorker::doWork(S32 param)
++mHTTPFailCount;
max_attempts = mHTTPFailCount+1; // Keep retrying
LL_INFOS_ONCE("Texture") << "Texture server busy (503): " << mUrl << LL_ENDL;
+ mDelay = 2.0f; //delay 2 second to re-issue the http request
}
else
{
const S32 HTTP_MAX_RETRY_COUNT = 3;
max_attempts = HTTP_MAX_RETRY_COUNT + 1;
++mHTTPFailCount;
+ mDelay = 2.0f; //delay 2 second to re-issue the http request
+
llinfos << "HTTP GET failed for: " << mUrl
<< " Status: " << mGetStatus << " Reason: '" << mGetReason << "'"
<< " Attempt:" << mHTTPFailCount+1 << "/" << max_attempts << llendl;
@@ -1282,10 +1305,12 @@ bool LLTextureFetchWorker::doWork(S32 param)
if (mHTTPFailCount >= max_attempts)
{
+ mUrl.clear();
if (cur_size > 0)
{
// Use available data
mLoadedDiscard = mFormattedImage->getDiscardLevel();
+ setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);
mState = DECODE_IMAGE;
return false;
}
@@ -1298,11 +1323,20 @@ bool LLTextureFetchWorker::doWork(S32 param)
}
else
{
+ setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);
mState = SEND_HTTP_REQ;
return false; // retry
}
}
+ // Clear the url since we're done with the fetch
+ // Note: mUrl is used to check is fetching is required so failure to clear it will force an http fetch
+ // next time the texture is requested, even if the data have already been fetched.
+ if(mWriteToCacheState != NOT_WRITE)
+ {
+ mUrl.clear();
+ }
+
llassert_always(mBufferSize == cur_size + mRequestedSize);
if(!mBufferSize)//no data received.
{
@@ -1357,13 +1391,9 @@ bool LLTextureFetchWorker::doWork(S32 param)
}
else
{
- if(FETCHING_TIMEOUT < mRequestedTimer.getElapsedTimeF32())
- {
- //timeout, abort.
- mState = DONE;
- return true;
- }
-
+ //
+ //No need to timeout, the responder should be triggered automatically.
+ //
setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority);
return false;
}
@@ -1495,7 +1525,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
CacheWriteResponder* responder = new CacheWriteResponder(mFetcher, mID);
mCacheWriteHandle = mFetcher->mTextureCache->writeToCache(mID, cache_priority,
mFormattedImage->getData(), datasize,
- mFileSize, responder);
+ mFileSize, mRawImage, mDecodedDiscard, responder);
// fall through
}
@@ -1683,7 +1713,7 @@ S32 LLTextureFetchWorker::callbackHttpGet(const LLChannelDescriptors& channels,
S32 data_size = 0 ;
LLMutexLock lock(&mWorkMutex);
-
+ mHTTPHandle = 0;
if (mState != WAIT_HTTP_REQ)
{
llwarns << "callbackHttpGet for unrequested fetch worker: " << mID
@@ -1707,7 +1737,7 @@ S32 LLTextureFetchWorker::callbackHttpGet(const LLChannelDescriptors& channels,
mBuffer = (U8*)ALLOCATE_MEM(LLImageBase::getPrivatePool(), data_size);
buffer->readAfter(channels.in(), NULL, mBuffer, data_size);
mBufferSize += data_size;
- if (data_size < mRequestedSize && mRequestedDiscard == 0)
+ if (mRequestedSize == 0)
{
mHaveAllData = TRUE;
}
@@ -1733,6 +1763,7 @@ S32 LLTextureFetchWorker::callbackHttpGet(const LLChannelDescriptors& channels,
{
mRequestedSize = -1; // error
}
+
mLoaded = TRUE;
setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);
@@ -1856,11 +1887,11 @@ LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* image
mTextureCache(cache),
mImageDecodeThread(imagedecodethread),
mTextureBandwidth(0),
- mHTTPTextureBits(0),
- mTotalHTTPRequests(0),
mCurlGetRequest(NULL),
mQAMode(qa_mode),
mFetchDebugger(NULL),
+ mFetchSource(LLTextureFetch::FROM_ALL),
+ mOriginFetchSource(LLTextureFetch::FROM_ALL),
mFetcherLocked(FALSE)
{
mCurlPOSTRequestCount = 0;
@@ -1871,6 +1902,13 @@ LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* image
if(LLTextureFetchDebugger::isEnabled())
{
mFetchDebugger = new LLTextureFetchDebugger(this, cache, imagedecodethread) ;
+ mFetchSource = (e_tex_source)gSavedSettings.getS32("TextureFetchSource");
+ if(mFetchSource < 0 && mFetchSource >= INVALID_SOURCE)
+ {
+ mFetchSource = LLTextureFetch::FROM_ALL;
+ gSavedSettings.setS32("TextureFetchSource", 0);
+ }
+ mOriginFetchSource = mFetchSource;
}
}
@@ -1940,6 +1978,8 @@ bool LLTextureFetch::createRequest(const std::string& url, const LLUUID& id, con
}
else
{
+ // If the requester knows nothing about the file, we fetch the smallest
+ // amount of data at the lowest resolution (highest discard level) possible.
desired_size = TEXTURE_CACHE_ENTRY_SIZE;
desired_discard = MAX_DISCARD_LEVEL;
}
@@ -2018,45 +2058,22 @@ void LLTextureFetch::removeFromNetworkQueue(LLTextureFetchWorker* worker, bool c
}
}
-// protected
-void LLTextureFetch::addToHTTPQueue(const LLUUID& id)
-{
- LLMutexLock lock(&mNetworkQueueMutex);
- mHTTPTextureQueue.insert(id);
- mTotalHTTPRequests++;
-}
-
-void LLTextureFetch::removeFromHTTPQueue(const LLUUID& id, S32 received_size)
-{
- LLMutexLock lock(&mNetworkQueueMutex);
- mHTTPTextureQueue.erase(id);
- mHTTPTextureBits += received_size * 8; // Approximate - does not include header bits
-}
-
void LLTextureFetch::deleteRequest(const LLUUID& id, bool cancel)
{
lockQueue() ;
LLTextureFetchWorker* worker = getWorkerAfterLock(id);
- if (worker)
- {
- size_t erased_1 = mRequestMap.erase(worker->mID);
- unlockQueue() ;
-
- llassert_always(erased_1 > 0) ;
-
- removeFromNetworkQueue(worker, cancel);
- llassert_always(!(worker->getFlags(LLWorkerClass::WCF_DELETE_REQUESTED))) ;
+ unlockQueue() ;
- worker->scheduleDelete();
- }
- else
- {
- unlockQueue() ;
- }
+ removeRequest(worker, cancel);
}
void LLTextureFetch::removeRequest(LLTextureFetchWorker* worker, bool cancel)
{
+ if(!worker)
+ {
+ return;
+ }
+
lockQueue() ;
size_t erased_1 = mRequestMap.erase(worker->mID);
unlockQueue() ;
@@ -2065,9 +2082,28 @@ void LLTextureFetch::removeRequest(LLTextureFetchWorker* worker, bool cancel)
removeFromNetworkQueue(worker, cancel);
llassert_always(!(worker->getFlags(LLWorkerClass::WCF_DELETE_REQUESTED))) ;
+ worker->removeFromHTTPQueue();
worker->scheduleDelete();
}
+void LLTextureFetch::deleteAllRequests()
+{
+ while(1)
+ {
+ lockQueue();
+ if(mRequestMap.empty())
+ {
+ unlockQueue() ;
+ break;
+ }
+
+ LLTextureFetchWorker* worker = mRequestMap.begin()->second;
+ unlockQueue() ;
+
+ removeRequest(worker, true);
+ }
+}
+
S32 LLTextureFetch::getNumRequests()
{
lockQueue() ;
@@ -2077,24 +2113,6 @@ S32 LLTextureFetch::getNumRequests()
return size ;
}
-S32 LLTextureFetch::getNumHTTPRequests()
-{
- mNetworkQueueMutex.lock() ;
- S32 size = (S32)mHTTPTextureQueue.size();
- mNetworkQueueMutex.unlock() ;
-
- return size ;
-}
-
-U32 LLTextureFetch::getTotalNumHTTPRequests()
-{
- mNetworkQueueMutex.lock() ;
- U32 size = mTotalHTTPRequests ;
- mNetworkQueueMutex.unlock() ;
-
- return size ;
-}
-
// call lockQueue() first!
LLTextureFetchWorker* LLTextureFetch::getWorkerAfterLock(const LLUUID& id)
{
@@ -2180,7 +2198,7 @@ bool LLTextureFetch::updateRequestPriority(const LLUUID& id, F32 priority)
{
worker->lockWorkMutex();
worker->setImagePriority(priority);
- worker->unlockWorkMutex();
+ worker->unlockWorkMutex();
res = true;
}
return res;
@@ -2262,15 +2280,7 @@ S32 LLTextureFetch::update(F32 max_time_ms)
{
static LLCachedControl<F32> band_width(gSavedSettings,"ThrottleBandwidthKBPS");
- {
- mNetworkQueueMutex.lock() ;
- mMaxBandwidth = band_width ;
-
- gTextureList.sTextureBits += mHTTPTextureBits ;
- mHTTPTextureBits = 0 ;
-
- mNetworkQueueMutex.unlock() ;
- }
+ mMaxBandwidth = band_width ;
S32 res = LLWorkerThread::update(max_time_ms);
@@ -2281,13 +2291,28 @@ S32 LLTextureFetch::update(F32 max_time_ms)
// won't work so don't bother trying
if (LLStartUp::getStartupState() > STATE_AGENT_SEND)
{
- sendRequestListToSimulators();
+ sendRequestListToSimulators();
}
}
if (!mThreaded)
{
commonUpdate();
+
+ if(mCurlGetRequest)
+ {
+ mCurlGetRequest->nextRequests();
+ }
+ }
+
+ if(mCurlGetRequest)
+ {
+ gTextureList.sTextureBits += mCurlGetRequest->getTotalReceivedBits();
+ }
+
+ if(mFetchDebugger)
+ {
+ mFetchDebugger->tryToStopDebug(); //check if need to stop debugger.
}
return res;
@@ -2317,7 +2342,7 @@ void LLTextureFetch::shutDownImageDecodeThread()
void LLTextureFetch::startThread()
{
// Construct mCurlGetRequest from Worker Thread
- mCurlGetRequest = new LLCurlRequest();
+ mCurlGetRequest = new LLCurlTextureRequest(8);
if(mFetchDebugger)
{
@@ -2342,6 +2367,8 @@ void LLTextureFetch::threadedUpdate()
{
llassert_always(mCurlGetRequest);
+ mCurlGetRequest->nextRequests();
+
// Limit update frequency
const F32 PROCESS_TIME = 0.05f;
static LLFrameTimer process_timer;
@@ -3154,6 +3181,7 @@ public:
llinfos << "Fetch Debugger : CURL GET FAILED, index = " << mIndex << ", status:" << status << " reason:" << reason << llendl;
}
mDebugger->callbackHTTP(mIndex, channels, buffer, partial, success);
+ mDebugger->getCurlGetRequest()->completeRequest(0);
}
virtual bool followRedir()
{
@@ -3176,7 +3204,8 @@ LLTextureFetchDebugger::LLTextureFetchDebugger(LLTextureFetch* fetcher, LLTextur
LLTextureFetchDebugger::~LLTextureFetchDebugger()
{
mFetchingHistory.clear();
- stopDebug();
+ mStopDebug = TRUE;
+ tryToStopDebug();
}
void LLTextureFetchDebugger::init()
@@ -3191,6 +3220,8 @@ void LLTextureFetchDebugger::init()
mTotalFetchingTime = 0.f;
mRefetchVisCacheTime = -1.f;
mRefetchVisHTTPTime = -1.f;
+ mRefetchAllCacheTime = -1.f;
+ mRefetchAllHTTPTime = -1.f;
mNumFetchedTextures = 0;
mNumCacheHits = 0;
@@ -3204,10 +3235,56 @@ void LLTextureFetchDebugger::init()
mRenderedDecodedData = 0;
mFetchedPixels = 0;
mRenderedPixels = 0;
- mRefetchedData = 0;
- mRefetchedPixels = 0;
+ mRefetchedVisData = 0;
+ mRefetchedVisPixels = 0;
+ mRefetchedAllData = 0;
+ mRefetchedAllPixels = 0;
mFreezeHistory = FALSE;
+ mStopDebug = FALSE;
+ mClearHistory = FALSE;
+}
+
+void LLTextureFetchDebugger::startWork(e_debug_state state)
+{
+ switch(state)
+ {
+ case IDLE:
+ break;
+ case START_DEBUG:
+ startDebug();
+ break;
+ case READ_CACHE:
+ debugCacheRead();
+ break;
+ case WRITE_CACHE:
+ debugCacheWrite();
+ break;
+ case DECODING:
+ debugDecoder();
+ break;
+ case HTTP_FETCHING:
+ debugHTTP();
+ break;
+ case GL_TEX:
+ debugGLTextureCreation();
+ break;
+ case REFETCH_VIS_CACHE:
+ debugRefetchVisibleFromCache();
+ break;
+ case REFETCH_VIS_HTTP:
+ debugRefetchVisibleFromHTTP();
+ break;
+ case REFETCH_ALL_CACHE:
+ debugRefetchAllFromCache();
+ break;
+ case REFETCH_ALL_HTTP:
+ debugRefetchAllFromHTTP();
+ break;
+ default:
+ break;
+ }
+ return;
}
void LLTextureFetchDebugger::startDebug()
@@ -3215,10 +3292,18 @@ void LLTextureFetchDebugger::startDebug()
//lock the fetcher
mFetcher->lockFetcher(true);
mFreezeHistory = TRUE;
+ mFetcher->resetLoadSource();
//clear the current fetching queue
gTextureList.clearFetchingRequests();
+ mState = START_DEBUG;
+}
+
+bool LLTextureFetchDebugger::processStartDebug(F32 max_time)
+{
+ mTimer.reset();
+
//wait for all works to be done
while(1)
{
@@ -3230,6 +3315,11 @@ void LLTextureFetchDebugger::startDebug()
{
break;
}
+
+ if(mTimer.getElapsedTimeF32() > max_time)
+ {
+ return false;
+ }
}
//collect statistics
@@ -3268,10 +3358,17 @@ void LLTextureFetchDebugger::startDebug()
}
mNumFetchedTextures = fetched_textures.size();
+
+ return true;
}
-void LLTextureFetchDebugger::stopDebug()
+void LLTextureFetchDebugger::tryToStopDebug()
{
+ if(!mStopDebug)
+ {
+ return;
+ }
+
//clear the current debug work
S32 size = mFetchingHistory.size();
switch(mState)
@@ -3300,37 +3397,71 @@ void LLTextureFetchDebugger::stopDebug()
break;
case GL_TEX:
break;
+ case REFETCH_VIS_CACHE:
+ break;
+ case REFETCH_VIS_HTTP:
+ break;
+ case REFETCH_ALL_CACHE:
+ mRefetchList.clear();
+ break;
+ case REFETCH_ALL_HTTP:
+ mRefetchList.clear();
+ break;
default:
break;
}
- while(1)
+ if(update(0.005f))
{
- if(update())
+ //unlock the fetcher
+ mFetcher->lockFetcher(false);
+ mFetcher->resetLoadSource();
+ mFreezeHistory = FALSE;
+ mStopDebug = FALSE;
+
+ if(mClearHistory)
{
- break;
+ mFetchingHistory.clear();
+ init();
+ mTotalFetchingTime = gDebugTimers[0].getElapsedTimeF32(); //reset
}
}
-
- //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();
+ mClearHistory = TRUE;
}
void LLTextureFetchDebugger::addHistoryEntry(LLTextureFetchWorker* worker)
{
+ if(worker->mRawImage.isNull() || worker->mFormattedImage.isNull())
+ {
+ return;
+ }
+
if(mFreezeHistory)
{
- mRefetchedPixels += worker->mRawImage->getWidth() * worker->mRawImage->getHeight();
- mRefetchedData += worker->mFormattedImage->getDataSize();
+ if(mState == REFETCH_VIS_CACHE || mState == REFETCH_VIS_HTTP)
+ {
+ mRefetchedVisPixels += worker->mRawImage->getWidth() * worker->mRawImage->getHeight();
+ mRefetchedVisData += worker->mFormattedImage->getDataSize();
+ }
+ else
+ {
+ mRefetchedAllPixels += worker->mRawImage->getWidth() * worker->mRawImage->getHeight();
+ mRefetchedAllData += worker->mFormattedImage->getDataSize();
+
+ LLViewerFetchedTexture* tex = LLViewerTextureManager::findFetchedTexture(worker->mID);
+ if(tex && mRefetchList[tex].begin() != mRefetchList[tex].end())
+ {
+ if(worker->mDecodedDiscard == mFetchingHistory[mRefetchList[tex][0]].mDecodedLevel)
+ {
+ mRefetchList[tex].erase(mRefetchList[tex].begin());
+ }
+ }
+ }
return;
}
@@ -3342,9 +3473,8 @@ void LLTextureFetchDebugger::addHistoryEntry(LLTextureFetchWorker* worker)
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()));
+ mFetchingHistory.push_back(FetchEntry(worker->mID, worker->mDesiredSize, worker->mDecodedDiscard,
+ worker->mFormattedImage->getDataSize(), worker->mRawImage->getDataSize()));
}
void LLTextureFetchDebugger::lockCache()
@@ -3361,6 +3491,7 @@ void LLTextureFetchDebugger::debugCacheRead()
llassert_always(mState == IDLE);
mTimer.reset();
mState = READ_CACHE;
+ mCacheReadTime = -1.f;
S32 size = mFetchingHistory.size();
for(S32 i = 0 ; i < size ; i++)
@@ -3396,6 +3527,7 @@ void LLTextureFetchDebugger::debugCacheWrite()
llassert_always(mState == IDLE);
mTimer.reset();
mState = WRITE_CACHE;
+ mCacheWriteTime = -1.f;
S32 size = mFetchingHistory.size();
for(S32 i = 0 ; i < size ; i++)
@@ -3405,7 +3537,7 @@ void LLTextureFetchDebugger::debugCacheWrite()
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));
+ NULL, 0, new LLDebuggerCacheWriteResponder(this, i));
}
}
}
@@ -3424,6 +3556,7 @@ void LLTextureFetchDebugger::debugDecoder()
llassert_always(mState == IDLE);
mTimer.reset();
mState = DECODING;
+ mDecodingTime = -1.f;
S32 size = mFetchingHistory.size();
for(S32 i = 0 ; i < size ; i++)
@@ -3459,6 +3592,7 @@ void LLTextureFetchDebugger::debugHTTP()
mTimer.reset();
mState = HTTP_FETCHING;
+ mHTTPTime = -1.f;
S32 size = mFetchingHistory.size();
for (S32 i = 0 ; i < size ; i++)
@@ -3475,14 +3609,28 @@ void LLTextureFetchDebugger::debugHTTP()
S32 LLTextureFetchDebugger::fillCurlQueue()
{
- if (mNbCurlRequests == 24)
- return mNbCurlRequests;
-
+ if(mStopDebug) //stop
+ {
+ mNbCurlCompleted = mFetchingHistory.size();
+ return 0;
+ }
S32 size = mFetchingHistory.size();
+
+ if (mNbCurlRequests == size) //all issued
+ {
+ return 0;
+ }
+
+ S32 counter = 8;
+ mNbCurlRequests = 0;
for (S32 i = 0 ; i < size ; i++)
{
+ mNbCurlRequests++;
+
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.
@@ -3491,16 +3639,11 @@ S32 LLTextureFetchDebugger::fillCurlQueue()
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
+ mCurlGetRequest->getByteRange(texture_url, headers, 0, requestedSize, 0x10000, new LLDebuggerHTTPResponder(this, i));
+
+ mFetchingHistory[i].mCurlState = FetchEntry::CURL_IN_PROGRESS;
+ counter--;
+ if(counter < 1)
{
break;
}
@@ -3513,7 +3656,7 @@ void LLTextureFetchDebugger::debugGLTextureCreation()
{
llassert_always(mState == IDLE);
mState = GL_TEX;
- std::vector<LLViewerFetchedTexture*> tex_list;
+ mTempTexList.clear();
S32 size = mFetchingHistory.size();
for(S32 i = 0 ; i < size ; i++)
@@ -3524,28 +3667,54 @@ void LLTextureFetchDebugger::debugGLTextureCreation()
if(tex && !tex->isForSculptOnly())
{
tex->destroyGLTexture() ;
- tex_list.push_back(tex);
+ mTempTexList.push_back(tex);
}
}
}
+
+ mGLCreationTime = -1.f;
+ mTempIndex = 0;
+ mHistoryListIndex = 0;
+
+ return;
+}
+bool LLTextureFetchDebugger::processGLCreation(F32 max_time)
+{
mTimer.reset();
- S32 j = 0 ;
- S32 size1 = tex_list.size();
- for(S32 i = 0 ; i < size && j < size1; i++)
+
+ bool done = true;
+ S32 size = mFetchingHistory.size();
+ S32 size1 = mTempTexList.size();
+ for(; mHistoryListIndex < size && mTempIndex < size1; mHistoryListIndex++)
{
- if(mFetchingHistory[i].mRawImage.notNull())
+ if(mFetchingHistory[mHistoryListIndex].mRawImage.notNull())
{
- if(mFetchingHistory[i].mID == tex_list[j]->getID())
+ if(mFetchingHistory[mHistoryListIndex].mID == mTempTexList[mTempIndex]->getID())
{
- tex_list[j]->createGLTexture(mFetchingHistory[i].mDecodedLevel, mFetchingHistory[i].mRawImage, 0, TRUE, tex_list[j]->getBoostLevel());
- j++;
+ mTempTexList[mTempIndex]->createGLTexture(mFetchingHistory[mHistoryListIndex].mDecodedLevel,
+ mFetchingHistory[mHistoryListIndex].mRawImage, 0, TRUE, mTempTexList[mTempIndex]->getBoostLevel());
+ mTempIndex++;
}
}
+
+ if(mTimer.getElapsedTimeF32() > max_time)
+ {
+ done = false;
+ break;
+ }
}
- mGLCreationTime = mTimer.getElapsedTimeF32() ;
- return;
+ if(mGLCreationTime < 0.f)
+ {
+ mGLCreationTime = mTimer.getElapsedTimeF32() ;
+ }
+ else
+ {
+ mGLCreationTime += mTimer.getElapsedTimeF32() ;
+ }
+
+ return done;
}
//clear fetching results of all textures.
@@ -3562,15 +3731,62 @@ void LLTextureFetchDebugger::clearTextures()
}
}
+void LLTextureFetchDebugger::makeRefetchList()
+{
+ mRefetchList.clear();
+ S32 size = mFetchingHistory.size();
+ for(S32 i = 0 ; i < size; i++)
+ {
+ LLViewerFetchedTexture* tex = LLViewerTextureManager::getFetchedTexture(mFetchingHistory[i].mID);
+ if(tex && tex->isJustBound()) //visible
+ {
+ continue; //the texture fetch pipeline will take care of visible textures.
+ }
+
+ mRefetchList[tex].push_back(i);
+ }
+}
+
+void LLTextureFetchDebugger::scanRefetchList()
+{
+ if(mStopDebug)
+ {
+ return;
+ }
+ if(!mRefetchNonVis)
+ {
+ return;
+ }
+
+ for(std::map< LLPointer<LLViewerFetchedTexture>, std::vector<S32> >::iterator iter = mRefetchList.begin();
+ iter != mRefetchList.end(); )
+ {
+ if(iter->second.empty())
+ {
+ gTextureList.setDebugFetching(iter->first, -1);
+ mRefetchList.erase(iter++); // This is the correct method to "erase and move on" in an std::map
+ }
+ else
+ {
+ gTextureList.setDebugFetching(iter->first, mFetchingHistory[iter->second[0]].mDecodedLevel);
+ ++iter;
+ }
+ }
+}
+
void LLTextureFetchDebugger::debugRefetchVisibleFromCache()
{
llassert_always(mState == IDLE);
mState = REFETCH_VIS_CACHE;
clearTextures();
-
+ mFetcher->setLoadSource(LLTextureFetch::FROM_ALL);
+
mTimer.reset();
mFetcher->lockFetcher(false);
+ mRefetchVisCacheTime = -1.f;
+ mRefetchedVisData = 0;
+ mRefetchedVisPixels = 0;
}
void LLTextureFetchDebugger::debugRefetchVisibleFromHTTP()
@@ -3578,17 +3794,60 @@ void LLTextureFetchDebugger::debugRefetchVisibleFromHTTP()
llassert_always(mState == IDLE);
mState = REFETCH_VIS_HTTP;
- clearCache();
clearTextures();
+ mFetcher->setLoadSource(LLTextureFetch::FROM_HTTP_ONLY);
+
+ mTimer.reset();
+ mFetcher->lockFetcher(false);
+ mRefetchVisHTTPTime = -1.f;
+ mRefetchedVisData = 0;
+ mRefetchedVisPixels = 0;
+}
+
+void LLTextureFetchDebugger::debugRefetchAllFromCache()
+{
+ llassert_always(mState == IDLE);
+ mState = REFETCH_ALL_CACHE;
+
+ clearTextures();
+ makeRefetchList();
+ mFetcher->setLoadSource(LLTextureFetch::FROM_ALL);
+
+ mTimer.reset();
+ mFetcher->lockFetcher(false);
+ mRefetchAllCacheTime = -1.f;
+ mRefetchedAllData = 0;
+ mRefetchedAllPixels = 0;
+ mRefetchNonVis = FALSE;
+}
+
+void LLTextureFetchDebugger::debugRefetchAllFromHTTP()
+{
+ llassert_always(mState == IDLE);
+ mState = REFETCH_ALL_HTTP;
+
+ clearTextures();
+ makeRefetchList();
+ mFetcher->setLoadSource(LLTextureFetch::FROM_HTTP_ONLY);
mTimer.reset();
mFetcher->lockFetcher(false);
+ mRefetchAllHTTPTime = -1.f;
+ mRefetchedAllData = 0;
+ mRefetchedAllPixels = 0;
+ mRefetchNonVis = TRUE;
}
-bool LLTextureFetchDebugger::update()
+bool LLTextureFetchDebugger::update(F32 max_time)
{
switch(mState)
{
+ case START_DEBUG:
+ if(processStartDebug(max_time))
+ {
+ mState = IDLE;
+ }
+ break;
case READ_CACHE:
if(!mTextureCache->update(1))
{
@@ -3615,6 +3874,7 @@ bool LLTextureFetchDebugger::update()
break;
case HTTP_FETCHING:
mCurlGetRequest->process();
+ mCurlGetRequest->nextRequests();
LLCurl::getCurlThread()->update(1);
if (!fillCurlQueue() && mNbCurlCompleted == mFetchingHistory.size())
{
@@ -3623,22 +3883,59 @@ bool LLTextureFetchDebugger::update()
}
break;
case GL_TEX:
- mState = IDLE;
+ if(processGLCreation(max_time))
+ {
+ mState = IDLE;
+ mTempTexList.clear();
+ }
break;
case REFETCH_VIS_CACHE:
if (LLAppViewer::getTextureFetch()->getNumRequests() == 0)
{
- mRefetchVisCacheTime = gDebugTimers[0].getElapsedTimeF32() - mTotalFetchingTime;
+ mRefetchVisCacheTime = mTimer.getElapsedTimeF32() ;
mState = IDLE;
mFetcher->lockFetcher(true);
+ mFetcher->resetLoadSource();
}
break;
case REFETCH_VIS_HTTP:
if (LLAppViewer::getTextureFetch()->getNumRequests() == 0)
{
- mRefetchVisHTTPTime = gDebugTimers[0].getElapsedTimeF32() - mTotalFetchingTime;
+ mRefetchVisHTTPTime = mTimer.getElapsedTimeF32() ;
+ mState = IDLE;
+ mFetcher->lockFetcher(true);
+ mFetcher->resetLoadSource();
+ }
+ break;
+ case REFETCH_ALL_CACHE:
+ scanRefetchList();
+ if (LLAppViewer::getTextureFetch()->getNumRequests() == 0)
+ {
+ if(!mRefetchNonVis)
+ {
+ mRefetchNonVis = TRUE; //start to fetch non-vis
+ scanRefetchList();
+ break;
+ }
+
+ mRefetchAllCacheTime = mTimer.getElapsedTimeF32() ;
+ mState = IDLE;
+ mFetcher->lockFetcher(true);
+ mFetcher->resetLoadSource();
+ mRefetchList.clear();
+ mRefetchNonVis = FALSE;
+ }
+ break;
+ case REFETCH_ALL_HTTP:
+ scanRefetchList();
+ if (LLAppViewer::getTextureFetch()->getNumRequests() == 0)
+ {
+ mRefetchAllHTTPTime = mTimer.getElapsedTimeF32() ;
mState = IDLE;
mFetcher->lockFetcher(true);
+ mFetcher->resetLoadSource();
+ mRefetchList.clear();
+ mRefetchNonVis = FALSE;
}
break;
default:
@@ -3679,7 +3976,6 @@ void LLTextureFetchDebugger::callbackHTTP(S32 id, const LLChannelDescriptors& ch
const LLIOPipe::buffer_ptr_t& buffer,
bool partial, bool success)
{
- mNbCurlRequests--;
if (success)
{
mFetchingHistory[id].mCurlState = FetchEntry::CURL_DONE;
@@ -3693,7 +3989,7 @@ void LLTextureFetchDebugger::callbackHTTP(S32 id, const LLChannelDescriptors& ch
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());
+ mFetchingHistory[id].mFormattedImage = NULL;
{
// For now, create formatted image based on extension
std::string texture_url = mHTTPUrl + "/?texture_id=" + mFetchingHistory[id].mID.asString().c_str();
@@ -3715,6 +4011,7 @@ void LLTextureFetchDebugger::callbackHTTP(S32 id, const LLChannelDescriptors& ch
{
// Fetch will have to be redone
mFetchingHistory[id].mCurlState = FetchEntry::CURL_NOT_DONE;
+ mNbCurlRequests--;
}
else //skip
{