Conflicts:
	indra/newview/lldrawpoolavatar.cpp
	indra/newview/llviewertexturelist.cpp
	indra/newview/llworldmap.cpp
	indra/newview/pipeline.cpp
This commit is contained in:
Shyotl
2012-11-29 11:54:41 -06:00
358 changed files with 27109 additions and 8865 deletions

View File

@@ -1,4 +1,4 @@
/**
/**
* @file lltexturefetch.cpp
* @brief Object which fetches textures from the cache and/or network
*
@@ -28,6 +28,9 @@
#include <iostream>
#include <boost/regex.hpp>
#include <boost/lexical_cast.hpp>
#include "llstl.h"
#include "message.h"
@@ -52,6 +55,11 @@
#include "llviewerstats.h"
#include "llworld.h"
#include "llstartup.h"
#include "llbuffer.h"
class AIHTTPTimeoutPolicy;
extern AIHTTPTimeoutPolicy HTTPGetResponder_timeout;
extern AIHTTPTimeoutPolicy lcl_responder_timeout;
//////////////////////////////////////////////////////////////////////////////
class LLTextureFetchWorker : public LLWorkerClass
@@ -148,7 +156,7 @@ public:
// void relese() { --mActiveCount; }
S32 callbackHttpGet(const LLChannelDescriptors& channels,
const LLIOPipe::buffer_ptr_t& buffer,
const LLHTTPClient::ResponderBase::buffer_ptr_t& buffer,
bool partial, bool success);
void callbackCacheRead(bool success, LLImageFormatted* image,
S32 imagesize, BOOL islocal);
@@ -244,9 +252,9 @@ private:
LLFrameTimer mFetchTimer;
LLTextureCache::handle_t mCacheReadHandle;
LLTextureCache::handle_t mCacheWriteHandle;
U8* mBuffer;
S32 mBufferSize;
std::vector<U8> mHttpBuffer;
S32 mRequestedSize;
S32 mRequestedOffset;
S32 mDesiredSize;
S32 mFileSize;
S32 mCachedSize;
@@ -287,22 +295,51 @@ private:
};
//////////////////////////////////////////////////////////////////////////////
class HTTPGetResponder : public LLCurl::Responder
class HTTPGetResponder : public LLHTTPClient::ResponderWithCompleted
{
LOG_CLASS(HTTPGetResponder);
public:
HTTPGetResponder(LLTextureFetch* fetcher, const LLUUID& id, U64 startTime, S32 requestedSize, U32 offset, bool redir)
: mFetcher(fetcher), mID(id), mStartTime(startTime), mRequestedSize(requestedSize), mOffset(offset), mFollowRedir(redir)
: mFetcher(fetcher)
, mID(id)
, mStartTime(startTime)
, mRequestedSize(requestedSize)
, mRequestedOffset(offset)
, mFollowRedir(redir)
{
}
~HTTPGetResponder()
{
}
virtual void completedRaw(U32 status, const std::string& reason,
/*virtual*/ AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return HTTPGetResponder_timeout; }
#if 0 //Apparently, SL never sends content-range and instead sends transfer-encoding: chunked, so disabling for now
/*virtual*/ bool needsHeaders(void) const { return true; }
/*virtual*/ void completedHeaders(U32 status, std::string const& reason, AIHTTPReceivedHeaders const& headers) {
llinfos << "Texture fetch HTTP status: " << status << llendl;
llinfos << "Texture fetch headers: " << headers << llendl;
//example: Content-Range: 1000-3979/3980 Content-Length: 2980
static const boost::regex pattern("\\w*bytes\\w+(\\d+)-(\\d+)/(\\d+)");
std::string rangehdr;
if (headers.getFirstValue("content-range", rangehdr)){
llinfos << "Have content-range header" <<llendl;
boost::smatch match;
llassert_always(boost::regex_match(rangehdr, match, pattern));
llassert(match.length() == 3);
std::string lengthhdr;
if(headers.getFirstValue("content-length",lengthhdr)) {
//insert length checking
}
}
}
#endif
/*virtual*/ void completedRaw(U32 status, const std::string& reason,
const LLChannelDescriptors& channels,
const LLIOPipe::buffer_ptr_t& buffer)
const buffer_ptr_t& buffer)
{
static LLCachedControl<bool> log_to_viewer_log(gSavedSettings,"LogTextureDownloadsToViewerLog");
static LLCachedControl<bool> log_to_sim(gSavedSettings,"LogTextureDownloadsToSimulator");
@@ -314,7 +351,7 @@ public:
U64 timeNow = LLTimer::getTotalTime();
mFetcher->mTextureInfo.setRequestType(mID, LLTextureInfoDetails::REQUEST_TYPE_HTTP);
mFetcher->mTextureInfo.setRequestSize(mID, mRequestedSize);
mFetcher->mTextureInfo.setRequestOffset(mID, mOffset);
mFetcher->mTextureInfo.setRequestOffset(mID, mRequestedOffset);
mFetcher->mTextureInfo.setRequestCompleteTimeAndLog(mID, timeNow);
}
@@ -381,7 +418,7 @@ private:
LLUUID mID;
U64 mStartTime;
S32 mRequestedSize;
U32 mOffset;
U32 mRequestedOffset;
bool mFollowRedir;
};
@@ -748,9 +785,8 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher,
mDecodedDiscard(-1),
mCacheReadHandle(LLTextureCache::nullHandle()),
mCacheWriteHandle(LLTextureCache::nullHandle()),
mBuffer(NULL),
mBufferSize(0),
mRequestedSize(0),
mRequestedOffset(0),
mDesiredSize(TEXTURE_CACHE_ENTRY_SIZE),
mFileSize(0),
mCachedSize(0),
@@ -779,7 +815,7 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher,
calcWorkPriority();
mType = host.isOk() ? LLImageBase::TYPE_AVATAR_BAKE : LLImageBase::TYPE_NORMAL;
llinfos << "Create: " << mID << " mHost:" << host << " Discard=" << discard << " URL:"<< mUrl << llendl;
//llinfos << "Create: " << mID << " mHost:" << host << " Discard=" << discard << " URL:"<< mUrl << llendl;
if (!mFetcher->mDebugPause)
{
U32 work_priority = mWorkPriority | LLWorkerThread::PRIORITY_HIGH;
@@ -910,9 +946,7 @@ void LLTextureFetchWorker::setImagePriority(F32 priority)
void LLTextureFetchWorker::resetFormattedData()
{
FREE_MEM(LLImageBase::getPrivatePool(), mBuffer);
mBuffer = NULL;
mBufferSize = 0;
std::vector<U8>().swap(mHttpBuffer);
if (mFormattedImage.notNull())
{
mFormattedImage->deleteData();
@@ -984,15 +1018,14 @@ bool LLTextureFetchWorker::doWork(S32 param)
mLoadedDiscard = -1;
mDecodedDiscard = -1;
mRequestedSize = 0;
mRequestedOffset = 0;
mFileSize = 0;
mCachedSize = 0;
mLoaded = FALSE;
mSentRequest = UNSENT;
mDecoded = FALSE;
mWritten = FALSE;
FREE_MEM(LLImageBase::getPrivatePool(), mBuffer);
mBuffer = NULL;
mBufferSize = 0;
std::vector<U8>().swap(mHttpBuffer);
mHaveAllData = FALSE;
clearPackets(); // TODO: Shouldn't be necessary
mCacheReadHandle = LLTextureCache::nullHandle();
@@ -1282,14 +1315,10 @@ bool LLTextureFetchWorker::doWork(S32 param)
return true ; //abort.
}
}
resetFormattedData();
cur_size = 0;
}
mRequestedSize = mDesiredSize;
mRequestedSize = mDesiredSize - cur_size;
mRequestedDiscard = mDesiredDiscard;
mRequestedSize -= cur_size;
S32 offset = cur_size;
mBufferSize = cur_size; // This will get modified by callbackHttpGet()
mRequestedOffset = cur_size;
bool res = false;
if (!mUrl.empty())
@@ -1299,7 +1328,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
mLoaded = FALSE;
mGetStatus = 0;
mGetReason.clear();
LL_DEBUGS("Texture") << "HTTP GET: " << mID << " Offset: " << offset
LL_DEBUGS("Texture") << "HTTP GET: " << mID << " Offset: " << mRequestedOffset
<< " Bytes: " << mRequestedSize
<< " Bandwidth(kbps): " << mFetcher->getTextureBandwidth() << "/" << mFetcher->mMaxBandwidth
<< LL_ENDL;
@@ -1317,13 +1346,28 @@ bool LLTextureFetchWorker::doWork(S32 param)
LLImageBase::TYPE_AVATAR_BAKE == mType);
#endif
// Will call callbackHttpGet when curl request completes
std::vector<std::string> headers;
headers.push_back("Accept: image/x-j2c");
if(mRequestedOffset>0)
{
// Texture fetching often issues 'speculative' loads that
// start beyond the end of the actual asset. Some cache/web
// systems, e.g. Varnish, will respond to this not with a
// 416 but with a 200 and the entire asset in the response
// body. By ensuring that we always have a partially
// satisfiable Range request, we avoid that hit to the network.
// We just have to deal with the overlapping data which is made
// somewhat harder by the fact that grid services don't necessarily
// return the Content-Range header on 206 responses. *Sigh*
mRequestedSize++;
mRequestedOffset--;
}
try
{
res = mFetcher->mCurlGetRequest->getByteRange(mUrl, headers, offset, mRequestedSize,
new HTTPGetResponder(mFetcher, mID, LLTimer::getTotalTime(), mRequestedSize, offset, true));
// Will call callbackHttpGet when curl request completes
AIHTTPHeaders headers("Accept", "image/x-j2c");
LLHTTPClient::getByteRange(mUrl, mRequestedOffset, mRequestedSize,
new HTTPGetResponder(mFetcher, mID, LLTimer::getTotalTime(), mRequestedSize, mRequestedOffset, true), headers);
res = true;
}
catch(AICurlNoEasyHandle const& error)
{
@@ -1435,18 +1479,37 @@ bool LLTextureFetchWorker::doWork(S32 param)
return false; // retry
}
}
llassert_always(mBufferSize == cur_size + mRequestedSize);
if(!mBufferSize)//no data received.
{
FREE_MEM(LLImageBase::getPrivatePool(), mBuffer);
mBuffer = NULL;
if(mHttpBuffer.empty())//no data received.
{
//abort.
mState = DONE;
return true;
}
S32 total_size(cur_size + mRequestedSize);
S32 src_offset(0);
if(mRequestedOffset && mRequestedOffset != cur_size)
{
// In case of a partial response, our offset may
// not be trivially contiguous with the data we have.
// Get back into alignment.
if (mRequestedOffset > cur_size)
{
LL_WARNS("Texture") << "Partial HTTP response produces break in image data for texture "
<< mID << ". Aborting load." << LL_ENDL;
mState = DONE;
return true;
}
src_offset = cur_size - mRequestedOffset;
total_size -= src_offset;
mRequestedSize -= src_offset; // Make requested values reflect useful part
mRequestedOffset += src_offset;
}
llassert(total_size == cur_size + mRequestedSize);
if (mFormattedImage.isNull())
{
// For now, create formatted image based on extension
@@ -1460,25 +1523,26 @@ bool LLTextureFetchWorker::doWork(S32 param)
if (mHaveAllData && mRequestedDiscard == 0) //the image file is fully loaded.
{
mFileSize = mBufferSize;
mFileSize = total_size;
}
else //the file size is unknown.
{
mFileSize = mBufferSize + 1 ; //flag the file is not fully loaded.
mFileSize = total_size + 1 ; //flag the file is not fully loaded.
}
U8* buffer = (U8*)ALLOCATE_MEM(LLImageBase::getPrivatePool(), mBufferSize);
U8* buffer = (U8*)ALLOCATE_MEM(LLImageBase::getPrivatePool(), total_size);
if (cur_size > 0)
{
memcpy(buffer, mFormattedImage->getData(), cur_size);
}
memcpy(buffer + cur_size, mBuffer, mRequestedSize); // append
if (mRequestedSize > 0)
{
memcpy(buffer + mRequestedOffset, &mHttpBuffer[src_offset], mRequestedSize); // append
}
// NOTE: setData releases current data and owns new data (buffer)
mFormattedImage->setData(buffer, mBufferSize);
mFormattedImage->setData(buffer, total_size);
// delete temp data
FREE_MEM(LLImageBase::getPrivatePool(), mBuffer); // Note: not 'buffer' (assigned in setData())
mBuffer = NULL;
mBufferSize = 0;
std::vector<U8>().swap(mHttpBuffer);
mLoadedDiscard = mRequestedDiscard;
mState = DECODE_IMAGE;
if(mWriteToCacheState != NOT_WRITE)
@@ -1805,7 +1869,7 @@ bool LLTextureFetchWorker::processSimulatorPackets()
//////////////////////////////////////////////////////////////////////////////
S32 LLTextureFetchWorker::callbackHttpGet(const LLChannelDescriptors& channels,
const LLIOPipe::buffer_ptr_t& buffer,
const LLHTTPClient::ResponderBase::buffer_ptr_t& buffer,
bool partial, bool success)
{
S32 data_size = 0 ;
@@ -1832,9 +1896,9 @@ S32 LLTextureFetchWorker::callbackHttpGet(const LLChannelDescriptors& channels,
if (data_size > 0)
{
// *TODO: set the formatted image data here directly to avoid the copy
mBuffer = (U8*)ALLOCATE_MEM(LLImageBase::getPrivatePool(), data_size);
buffer->readAfter(channels.in(), NULL, mBuffer, data_size);
mBufferSize += data_size;
llassert(mHttpBuffer.empty());
mHttpBuffer.resize(data_size);
buffer->readAfter(channels.in(), NULL, &mHttpBuffer[0], data_size);
if (data_size < mRequestedSize && mRequestedDiscard == 0)
{
mHaveAllData = TRUE;
@@ -1844,9 +1908,9 @@ S32 LLTextureFetchWorker::callbackHttpGet(const LLChannelDescriptors& channels,
// *TODO: This shouldn't be happening any more
llwarns << "data_size = " << data_size << " > requested: " << mRequestedSize << llendl;
mHaveAllData = TRUE;
mRequestedOffset = 0;
llassert_always(mDecodeHandle == 0);
mFormattedImage = NULL; // discard any previous data we had
mBufferSize = data_size;
}
}
else
@@ -1989,8 +2053,7 @@ LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* image
mImageDecodeThread(imagedecodethread),
mTextureBandwidth(0),
mHTTPTextureBits(0),
mTotalHTTPRequests(0),
mCurlGetRequest(NULL)
mTotalHTTPRequests(0)
#if HTTP_METRICS
,mQAMode(qa_mode)
#endif
@@ -2107,7 +2170,7 @@ bool LLTextureFetch::createRequest(const std::string& url, const LLUUID& id, con
worker->unlockWorkMutex();
}
llinfos << "REQUESTED: " << id << " Discard: " << desired_discard << llendl;
//llinfos << "REQUESTED: " << id << " Discard: " << desired_discard << llendl;
return true;
}
@@ -2435,26 +2498,9 @@ void LLTextureFetch::shutDownImageDecodeThread()
}
}
// WORKER THREAD
void LLTextureFetch::startThread()
{
// Construct mCurlGetRequest from Worker Thread
mCurlGetRequest = new AICurlInterface::Request;
}
// WORKER THREAD
void LLTextureFetch::endThread()
{
// Destroy mCurlGetRequest from Worker Thread
delete mCurlGetRequest;
mCurlGetRequest = NULL;
}
// WORKER THREAD
void LLTextureFetch::threadedUpdate()
{
llassert_always(mCurlGetRequest);
// Limit update frequency
const F32 PROCESS_TIME = 0.05f;
static LLFrameTimer process_timer;
@@ -3039,7 +3085,7 @@ TFReqSendMetrics::doWork(LLTextureFetch * fetcher)
* refactoring of the LLQueuedThread usage, these POSTs
* could be put in a request object and made more reliable.
*/
class lcl_responder : public LLCurl::Responder
class lcl_responder : public LLHTTPClient::ResponderWithResult
{
public:
lcl_responder(LLTextureFetch * fetcher,
@@ -3047,8 +3093,7 @@ TFReqSendMetrics::doWork(LLTextureFetch * fetcher)
volatile const S32 & live_sequence,
volatile bool & reporting_break,
volatile bool & reporting_started)
: LLCurl::Responder(),
mFetcher(fetcher),
: mFetcher(fetcher),
mExpectedSequence(expected_sequence),
mLiveSequence(live_sequence),
mReportingBreak(reporting_break),
@@ -3082,6 +3127,7 @@ TFReqSendMetrics::doWork(LLTextureFetch * fetcher)
mReportingStarted = true;
}
}
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return lcl_responder_timeout; }
private:
LLTextureFetch * mFetcher;
@@ -3124,9 +3170,7 @@ TFReqSendMetrics::doWork(LLTextureFetch * fetcher)
if (! mCapsURL.empty())
{
LLCurlRequest::headers_t headers;
fetcher->getCurlRequest().post(mCapsURL,
headers,
LLHTTPClient::post(mCapsURL,
merged_llsd,
new lcl_responder(fetcher,
report_sequence,