Merge branch 'master' of https://github.com/AlericInglewood/SingularityViewer.git into testpit
Conflicts: indra/newview/lldrawpoolavatar.cpp indra/newview/llviewertexturelist.cpp indra/newview/llworldmap.cpp indra/newview/pipeline.cpp
This commit is contained in:
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user