Moar Thickbrick!

This commit is contained in:
Siana Gearz
2010-11-18 22:43:00 +01:00
parent e9296374cf
commit 923c18bc0a
3 changed files with 132 additions and 37 deletions

View File

@@ -61,6 +61,8 @@
using namespace LLVOAvatarDefines;
const S32 MAX_BAKE_UPLOAD_ATTEMPTS = 4;
// static
S32 LLTexLayerSetBuffer::sGLByteCount = 0;
@@ -98,6 +100,8 @@ LLTexLayerSetBuffer::LLTexLayerSetBuffer(LLTexLayerSet* owner, S32 width, S32 he
mNeedsUpdate( TRUE ),
mNeedsUpload( FALSE ),
mUploadPending( FALSE ), // Not used for any logic here, just to sync sending of updates
mUploadFailCount( 0 ),
mUploadAfter( 0 ),
mTexLayerSet( owner )
{
LLTexLayerSetBuffer::sGLByteCount += getSize();
@@ -151,6 +155,18 @@ void LLTexLayerSetBuffer::requestUpload()
{
mNeedsUpload = TRUE;
mUploadPending = TRUE;
mUploadAfter = 0;
}
}
// request an upload to start delay_usec microseconds from now
void LLTexLayerSetBuffer::requestDelayedUpload(U64 delay_usec)
{
if (!mNeedsUpload)
{
mNeedsUpload = TRUE;
mUploadPending = TRUE;
mUploadAfter = LLFrameTimer::getTotalTime() + delay_usec;
}
}
@@ -161,6 +177,14 @@ void LLTexLayerSetBuffer::cancelUpload()
mNeedsUpload = FALSE;
}
mUploadPending = FALSE;
mUploadAfter = 0;
}
// do we need to upload, and do we have sufficient data to create an uploadable composite?
BOOL LLTexLayerSetBuffer::needsUploadNow() const
{
BOOL upload = mNeedsUpload && mTexLayerSet->isLocalTextureDataFinal() && (gAgent.mNumPendingQueries == 0);
return (upload && (LLFrameTimer::getTotalTime() > mUploadAfter));
}
void LLTexLayerSetBuffer::pushProjection()
@@ -187,7 +211,7 @@ void LLTexLayerSetBuffer::popProjection()
BOOL LLTexLayerSetBuffer::needsRender()
{
LLVOAvatar* avatar = mTexLayerSet->getAvatar();
BOOL upload_now = mNeedsUpload && mTexLayerSet->isLocalTextureDataFinal() && gAgent.mNumPendingQueries == 0;
BOOL upload_now = needsUploadNow();
BOOL needs_update = (mNeedsUpdate || upload_now) && !avatar->mAppearanceAnimating;
if (needs_update)
{
@@ -231,7 +255,7 @@ BOOL LLTexLayerSetBuffer::render()
// do we need to upload, and do we have sufficient data to create an uploadable composite?
// When do we upload the texture if gAgent.mNumPendingQueries is non-zero?
BOOL upload_now = (gAgent.mNumPendingQueries == 0 && mNeedsUpload && mTexLayerSet->isLocalTextureDataFinal());
BOOL upload_now = needsUploadNow();
BOOL success = TRUE;
// Composite the color data
@@ -434,12 +458,13 @@ void LLTexLayerSetBuffer::onTextureUploadComplete(const LLUUID& uuid, void* user
LLVOAvatar* avatar = gAgent.getAvatarObject();
if (0 == result &&
avatar && !avatar->isDead() &&
if (avatar && !avatar->isDead() && baked_upload_data &&
baked_upload_data->mAvatar == avatar && // Sanity check: only the user's avatar should be uploading textures.
baked_upload_data->mLayerSet->hasComposite())
{
LLTexLayerSetBuffer* layerset_buffer = baked_upload_data->mLayerSet->getComposite();
S32 failures = layerset_buffer->mUploadFailCount;
layerset_buffer->mUploadFailCount = 0;
if (layerset_buffer->mUploadID.isNull())
{
@@ -467,9 +492,20 @@ void LLTexLayerSetBuffer::onTextureUploadComplete(const LLUUID& uuid, void* user
}
else
{
// Avatar appearance is changing, ignore the upload results
llinfos << "Baked upload failed. Reason: " << result << llendl;
// *FIX: retry upload after n seconds, asset server could be busy
++failures;
llinfos << "Baked upload failed (attempt " << failures << "/" << MAX_BAKE_UPLOAD_ATTEMPTS << "), ";
if (failures >= MAX_BAKE_UPLOAD_ATTEMPTS)
{
llcont << "giving up.";
}
else
{
const F32 delay = 5.f;
llcont << llformat("retrying in %.2f seconds.", delay);
layerset_buffer->mUploadFailCount = failures;
layerset_buffer->requestDelayedUpload((U64)(delay * 1000000));
}
llcont << llendl;
}
}
else

View File

@@ -218,6 +218,7 @@ public:
BOOL needsRender();
void requestUpdate();
void requestUpload();
void requestDelayedUpload(U64 delay_usec);
void cancelUpload();
BOOL uploadPending() { return mUploadPending; }
BOOL render( S32 x, S32 y, S32 width, S32 height );
@@ -234,12 +235,15 @@ public:
private:
void pushProjection();
void popProjection();
BOOL needsUploadNow() const;
private:
BOOL mNeedsUpdate;
BOOL mNeedsUpload;
BOOL mUploadPending;
LLUUID mUploadID; // Identifys the current upload process (null if none). Used to avoid overlaps (eg, when the user rapidly makes two changes outside of Face Edit)
S32 mUploadFailCount;
U64 mUploadAfter; // delay upload until after this time (in microseconds)
LLTexLayerSet* mTexLayerSet;
static S32 sGLByteCount;

View File

@@ -156,7 +156,7 @@ public:
void callbackHttpGet(const LLChannelDescriptors& channels,
const LLIOPipe::buffer_ptr_t& buffer,
bool last_block, bool success);
bool partial, bool unsatisfiable, bool success);
void callbackCacheRead(bool success, LLImageFormatted* image,
S32 imagesize, BOOL islocal);
void callbackCacheWrite(bool success);
@@ -175,7 +175,7 @@ protected:
LLTextureFetchWorker(LLTextureFetch* fetcher, const LLUUID& id, const LLHost& host,
F32 priority, S32 discard, S32 size);
LLTextureFetchWorker(LLTextureFetch* fetcher, const std::string& url, const LLUUID& id, const LLHost& host,
F32 priority, S32 discard, S32 size);
F32 priority, S32 discard, S32 size, bool can_use_http);
private:
/*virtual*/ void startWork(S32 param); // called from addWork() (MAIN THREAD)
@@ -323,6 +323,7 @@ public:
{
bool success = false;
bool partial = false;
bool unsatisfiable = false;
if (200 <= status && status < 300)
{
success = true;
@@ -331,10 +332,10 @@ public:
partial = true;
}
}
else
else if (status == HTTP_REQUESTED_RANGE_NOT_SATISFIABLE)
{
worker->setGetStatus(status, reason);
// llwarns << status << ": " << reason << llendl;
llwarns << "TextureFetch: Request was an unsatisfiable range: mRequestedSize=" << mRequestedSize << " mOffset=" << mOffset << " for: " << mID << LL_ENDL;
unsatisfiable = true;
}
if (!success)
{
@@ -342,7 +343,7 @@ public:
// llwarns << "CURL GET FAILED, status:" << status << " reason:" << reason << llendl;
}
mFetcher->removeFromHTTPQueue(mID);
worker->callbackHttpGet(channels, buffer, partial, success);
worker->callbackHttpGet(channels, buffer, partial, unsatisfiable, success);
}
else
{
@@ -387,7 +388,8 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher,
const LLHost& host, // Simulator host
F32 priority, // Priority
S32 discard, // Desired discard
S32 size) // Desired size
S32 size, // Desired size
bool can_use_http) // Try HTTP first
: LLWorkerClass(fetcher, "TextureFetch"),
mState(INIT),
mWriteToCacheState(NOT_WRITE),
@@ -419,7 +421,7 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher,
mNeedsAux(FALSE),
mHaveAllData(FALSE),
mInLocalCache(FALSE),
mCanUseHTTP(true),
mCanUseHTTP(can_use_http),
mHTTPFailCount(0),
mRetryAttempt(0),
mActiveCount(0),
@@ -869,6 +871,13 @@ bool LLTextureFetchWorker::doWork(S32 param)
if (mFormattedImage.notNull())
{
cur_size = mFormattedImage->getDataSize(); // amount of data we already have
if (mFormattedImage->getDiscardLevel() == 0)
{
// We already have all the data, just decode it
mLoadedDiscard = mFormattedImage->getDiscardLevel();
mState = DECODE_IMAGE;
return false;
}
}
mRequestedSize = mDesiredSize;
mRequestedDiscard = mDesiredDiscard;
@@ -885,6 +894,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
mGetReason.clear();
lldebugs << "HTTP GET: " << mID << " Offset: " << offset
<< " Bytes: " << mRequestedSize
<< " Range: " << offset << "-" << offset+mRequestedSize-1
<< " Bandwidth(kbps): " << mFetcher->getTextureBandwidth() << "/" << max_bandwidth
<< llendl;
setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority);
@@ -1152,8 +1162,8 @@ bool LLTextureFetchWorker::doWork(S32 param)
if(mDecodedDiscard<=0)
{
return true;
}
return true;
}
else
{
return false;
@@ -1305,7 +1315,9 @@ bool LLTextureFetchWorker::processSimulatorPackets()
void LLTextureFetchWorker::callbackHttpGet(const LLChannelDescriptors& channels,
const LLIOPipe::buffer_ptr_t& buffer,
bool last_block, bool success)
bool partial,
bool unsatisfiable,
bool success)
{
LLMutexLock lock(&mWorkMutex);
@@ -1320,46 +1332,89 @@ void LLTextureFetchWorker::callbackHttpGet(const LLChannelDescriptors& channels,
llwarns << "Duplicate callback for " << mID.asString() << llendl;
return; // ignore duplicate callback
}
S32 data_size = 0;
if (success)
{
// get length of stream:
S32 data_size = buffer->countAfter(channels.in(), NULL);
data_size = buffer->countAfter(channels.in(), NULL);
gImageList.sTextureBits += data_size * 8; // Approximate - does not include header bits
//llinfos << "HTTP RECEIVED: " << mID.asString() << " Bytes: " << data_size << llendl;
if (data_size > 0)
{
// *TODO: set the formatted image data here directly to avoid the copy
mBuffer = new U8[data_size];
buffer->readAfter(channels.in(), NULL, mBuffer, data_size);
mBufferSize += data_size;
if (data_size < mRequestedSize || last_block == true)
bool clean_data = false;
bool done = false;
if (!partial)
{
// we got the whole image in one go
done = true;
clean_data = true;
}
else if (data_size < mRequestedSize)
{
mHaveAllData = TRUE;
// we have the whole image
done = true;
}
else if (data_size == mRequestedSize)
{
if (mRequestedDiscard <= 0)
{
done = true;
}
else
{
// this is the normal case where we get the data we requested,
// but still need to request more data.
}
}
else if (data_size > mRequestedSize)
{
// *TODO: This shouldn't be happening any more
llwarns << "data_size = " << data_size << " > requested: " << mRequestedSize << llendl;
mHaveAllData = TRUE;
done = true;
clean_data = true;
llassert_always(mDecodeHandle == 0);
mFormattedImage = NULL; // discard any previous data we had
mBufferSize = data_size;
}
if (clean_data)
{
resetFormattedData(); // discard any previous data we had
llassert(mBufferSize == 0);
}
if (done)
{
mHaveAllData = TRUE;
mRequestedDiscard = 0;
}
// *TODO: set the formatted image data here directly to avoid the copy
mBuffer = new U8[data_size];
buffer->readAfter(channels.in(), NULL, mBuffer, data_size);
mBufferSize += data_size;
mRequestedSize = data_size;
}
else
{
// We requested data but received none (and no error),
// so presumably we have all of it
mHaveAllData = TRUE;
}
mRequestedSize = data_size;
}
else
{
mRequestedSize = -1; // error
}
if ((success && (data_size == 0)) || unsatisfiable)
{
if (mFormattedImage.notNull() && mFormattedImage->getDataSize() > 0)
{
// we already have some data, so we'll assume we have it all
mRequestedSize = 0;
mRequestedDiscard = 0;
mHaveAllData = TRUE;
}
else
{
mRequestedSize = -1; // treat this fetch as if it failed.
}
}
mLoaded = TRUE;
setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);
}
@@ -1563,7 +1618,7 @@ bool LLTextureFetch::createRequest(const std::string& url, const LLUUID& id, con
worker->lockWorkMutex();
worker->setImagePriority(priority);
worker->setDesiredDiscard(desired_discard, desired_size);
worker->setCanUseHTTP(can_use_http) ;
worker->setCanUseHTTP(can_use_http);
worker->unlockWorkMutex();
if (!worker->haveWork())
{
@@ -1579,7 +1634,7 @@ bool LLTextureFetch::createRequest(const std::string& url, const LLUUID& id, con
}
else
{
worker = new LLTextureFetchWorker(this, url, id, host, priority, desired_discard, desired_size);
worker = new LLTextureFetchWorker(this, url, id, host, priority, desired_discard, desired_size, can_use_http);
mRequestMap[id] = worker;
}
worker->mActiveCount++;