summaryrefslogtreecommitdiff
path: root/indra/newview/llviewertexlayer.cpp
diff options
context:
space:
mode:
authordolphin <dolphin@lindenlab.com>2014-06-17 13:09:15 -0700
committerdolphin <dolphin@lindenlab.com>2014-06-17 13:09:15 -0700
commit299921de323eb9b6844cd7b6f6b8da3490ee3747 (patch)
treedcb4c5c257622c20014a0b986dc8e2d1c25a10c7 /indra/newview/llviewertexlayer.cpp
parent89ea1cbc7acee8878c36a5795dd3df12a913c513 (diff)
parent977476171ddcc057d7c28b6c14ae988b8189ed75 (diff)
Merge with 3.7.9-release
Diffstat (limited to 'indra/newview/llviewertexlayer.cpp')
-rwxr-xr-xindra/newview/llviewertexlayer.cpp404
1 files changed, 6 insertions, 398 deletions
diff --git a/indra/newview/llviewertexlayer.cpp b/indra/newview/llviewertexlayer.cpp
index 62e8da81ec..65ba3fb6e5 100755
--- a/indra/newview/llviewertexlayer.cpp
+++ b/indra/newview/llviewertexlayer.cpp
@@ -37,7 +37,6 @@
#include "llglslshader.h"
#include "llvoavatarself.h"
#include "pipeline.h"
-#include "llassetuploadresponders.h"
#include "llviewercontrol.h"
static const S32 BAKE_UPLOAD_ATTEMPTS = 7;
@@ -46,22 +45,6 @@ static const F32 BAKE_UPLOAD_RETRY_DELAY = 2.f; // actual delay grows by power o
// runway consolidate
extern std::string self_av_string();
-
-//-----------------------------------------------------------------------------
-// LLBakedUploadData()
-//-----------------------------------------------------------------------------
-LLBakedUploadData::LLBakedUploadData(const LLVOAvatarSelf* avatar,
- LLViewerTexLayerSet* layerset,
- const LLUUID& id,
- bool highest_res) :
- mAvatar(avatar),
- mTexLayerSet(layerset),
- mID(id),
- mStartTime(LLFrameTimer::getTotalTime()), // Record starting time
- mIsHighestRes(highest_res)
-{
-}
-
//-----------------------------------------------------------------------------
// LLViewerTexLayerSetBuffer
// The composite image that a LLViewerTexLayerSet writes to. Each LLViewerTexLayerSet has one.
@@ -75,15 +58,10 @@ LLViewerTexLayerSetBuffer::LLViewerTexLayerSetBuffer(LLTexLayerSet* const owner,
// ORDER_LAST => must render these after the hints are created.
LLTexLayerSetBuffer(owner),
LLViewerDynamicTexture( width, height, 4, LLViewerDynamicTexture::ORDER_LAST, TRUE ),
- mUploadPending(FALSE), // Not used for any logic here, just to sync sending of updates
- mNeedsUpload(FALSE),
- mNumLowresUploads(0),
- mUploadFailCount(0),
mNeedsUpdate(TRUE),
mNumLowresUpdates(0)
{
LLViewerTexLayerSetBuffer::sGLByteCount += getSize();
- mNeedsUploadTimer.start();
mNeedsUpdateTimer.start();
}
@@ -126,33 +104,6 @@ void LLViewerTexLayerSetBuffer::requestUpdate()
restartUpdateTimer();
mNeedsUpdate = TRUE;
mNumLowresUpdates = 0;
- // If we're in the middle of uploading a baked texture, we don't care about it any more.
- // When it's downloaded, ignore it.
- mUploadID.setNull();
-}
-
-void LLViewerTexLayerSetBuffer::requestUpload()
-{
- conditionalRestartUploadTimer();
- mNeedsUpload = TRUE;
- mNumLowresUploads = 0;
- mUploadPending = TRUE;
-}
-
-void LLViewerTexLayerSetBuffer::conditionalRestartUploadTimer()
-{
- // If we requested a new upload but haven't even uploaded
- // a low res version of our last upload request, then
- // keep the timer ticking instead of resetting it.
- if (mNeedsUpload && (mNumLowresUploads == 0))
- {
- mNeedsUploadTimer.unpause();
- }
- else
- {
- mNeedsUploadTimer.reset();
- mNeedsUploadTimer.start();
- }
}
void LLViewerTexLayerSetBuffer::restartUpdateTimer()
@@ -161,25 +112,16 @@ void LLViewerTexLayerSetBuffer::restartUpdateTimer()
mNeedsUpdateTimer.start();
}
-void LLViewerTexLayerSetBuffer::cancelUpload()
-{
- mNeedsUpload = FALSE;
- mUploadPending = FALSE;
- mNeedsUploadTimer.pause();
- mUploadRetryTimer.reset();
-}
-
// virtual
BOOL LLViewerTexLayerSetBuffer::needsRender()
{
llassert(mTexLayerSet->getAvatarAppearance() == gAgentAvatarp);
if (!isAgentAvatarValid()) return FALSE;
- const BOOL upload_now = mNeedsUpload && isReadyToUpload();
const BOOL update_now = mNeedsUpdate && isReadyToUpdate();
- // Don't render if we don't want to (or aren't ready to) upload or update.
- if (!(update_now || upload_now))
+ // Don't render if we don't want to (or aren't ready to) update.
+ if (!update_now)
{
return FALSE;
}
@@ -190,11 +132,10 @@ BOOL LLViewerTexLayerSetBuffer::needsRender()
return FALSE;
}
- // Don't render if we are trying to create a shirt texture but aren't wearing a skirt.
+ // Don't render if we are trying to create a skirt texture but aren't wearing a skirt.
if (gAgentAvatarp->getBakedTE(getViewerTexLayerSet()) == LLAvatarAppearanceDefines::TEX_SKIRT_BAKED &&
!gAgentAvatarp->isWearingWearableType(LLWearableType::WT_SKIRT))
{
- cancelUpload();
return FALSE;
}
@@ -222,36 +163,7 @@ void LLViewerTexLayerSetBuffer::postRenderTexLayerSet(BOOL success)
// virtual
void LLViewerTexLayerSetBuffer::midRenderTexLayerSet(BOOL success)
{
- // do we need to upload, and do we have sufficient data to create an uploadable composite?
- // TODO: When do we upload the texture if gAgent.mNumPendingQueries is non-zero?
- const BOOL upload_now = mNeedsUpload && isReadyToUpload();
const BOOL update_now = mNeedsUpdate && isReadyToUpdate();
-
- if(upload_now)
- {
- if (!success)
- {
- LL_INFOS() << "Failed attempt to bake " << mTexLayerSet->getBodyRegionName() << LL_ENDL;
- mUploadPending = FALSE;
- }
- else
- {
- LLViewerTexLayerSet* layer_set = getViewerTexLayerSet();
- if (layer_set->isVisible())
- {
- layer_set->getAvatar()->debugBakedTextureUpload(layer_set->getBakedTexIndex(), FALSE); // FALSE for start of upload, TRUE for finish.
- doUpload();
- }
- else
- {
- mUploadPending = FALSE;
- mNeedsUpload = FALSE;
- mNeedsUploadTimer.pause();
- layer_set->getAvatar()->setNewBakedTexture(layer_set->getBakedTexIndex(),IMG_INVISIBLE);
- }
- }
- }
-
if (update_now)
{
doUpdate();
@@ -267,60 +179,6 @@ BOOL LLViewerTexLayerSetBuffer::isInitialized(void) const
return mGLTexturep.notNull() && mGLTexturep->isGLTextureCreated();
}
-BOOL LLViewerTexLayerSetBuffer::uploadPending() const
-{
- return mUploadPending;
-}
-
-BOOL LLViewerTexLayerSetBuffer::uploadNeeded() const
-{
- return mNeedsUpload;
-}
-
-BOOL LLViewerTexLayerSetBuffer::uploadInProgress() const
-{
- return !mUploadID.isNull();
-}
-
-BOOL LLViewerTexLayerSetBuffer::isReadyToUpload() const
-{
- if (!gAgentQueryManager.hasNoPendingQueries()) return FALSE; // Can't upload if there are pending queries.
- if (isAgentAvatarValid() && gAgentAvatarp->isEditingAppearance()) return FALSE; // Don't upload if avatar is being edited.
-
- BOOL ready = FALSE;
- if (getViewerTexLayerSet()->isLocalTextureDataFinal())
- {
- // If we requested an upload and have the final LOD ready, upload (or wait a while if this is a retry)
- if (mUploadFailCount == 0)
- {
- ready = TRUE;
- }
- else
- {
- ready = mUploadRetryTimer.getElapsedTimeF32() >= BAKE_UPLOAD_RETRY_DELAY * (1 << (mUploadFailCount - 1));
- }
- }
- else
- {
- // Upload if we've hit a timeout. Upload is a pretty expensive process so we need to make sure
- // we aren't doing uploads too frequently.
- const U32 texture_timeout = gSavedSettings.getU32("AvatarBakedTextureUploadTimeout");
- if (texture_timeout != 0)
- {
- // The timeout period increases exponentially between every lowres upload in order to prevent
- // spamming the server with frequent uploads.
- const U32 texture_timeout_threshold = texture_timeout*(1 << mNumLowresUploads);
-
- // If we hit our timeout and have textures available at even lower resolution, then upload.
- const BOOL is_upload_textures_timeout = mNeedsUploadTimer.getElapsedTimeF32() >= texture_timeout_threshold;
- const BOOL has_lower_lod = getViewerTexLayerSet()->isLocalTextureDataAvailable();
- ready = has_lower_lod && is_upload_textures_timeout;
- }
- }
-
- return ready;
-}
-
BOOL LLViewerTexLayerSetBuffer::isReadyToUpdate() const
{
// If we requested an update and have the final LOD ready, then update.
@@ -358,159 +216,6 @@ BOOL LLViewerTexLayerSetBuffer::requestUpdateImmediate()
return result;
}
-// Create the baked texture, send it out to the server, then wait for it to come
-// back so we can switch to using it.
-void LLViewerTexLayerSetBuffer::doUpload()
-{
- LLViewerTexLayerSet* layer_set = getViewerTexLayerSet();
- LL_DEBUGS("Avatar") << "Uploading baked " << layer_set->getBodyRegionName() << LL_ENDL;
- add(LLStatViewer::TEX_BAKES, 1);
-
- // Don't need caches since we're baked now. (note: we won't *really* be baked
- // until this image is sent to the server and the Avatar Appearance message is received.)
- layer_set->deleteCaches();
-
- // Get the COLOR information from our texture
- U8* baked_color_data = new U8[ mFullWidth * mFullHeight * 4 ];
- glReadPixels(mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight, GL_RGBA, GL_UNSIGNED_BYTE, baked_color_data );
- stop_glerror();
-
- // Get the MASK information from our texture
- LLGLSUIDefault gls_ui;
- LLPointer<LLImageRaw> baked_mask_image = new LLImageRaw(mFullWidth, mFullHeight, 1 );
- U8* baked_mask_data = baked_mask_image->getData();
- layer_set->gatherMorphMaskAlpha(baked_mask_data,
- mOrigin.mX, mOrigin.mY,
- mFullWidth, mFullHeight);
-
-
- // Create the baked image from our color and mask information
- const S32 baked_image_components = 5; // red green blue [bump] clothing
- LLPointer<LLImageRaw> baked_image = new LLImageRaw( mFullWidth, mFullHeight, baked_image_components );
- U8* baked_image_data = baked_image->getData();
- S32 i = 0;
- for (S32 u=0; u < mFullWidth; u++)
- {
- for (S32 v=0; v < mFullHeight; v++)
- {
- baked_image_data[5*i + 0] = baked_color_data[4*i + 0];
- baked_image_data[5*i + 1] = baked_color_data[4*i + 1];
- baked_image_data[5*i + 2] = baked_color_data[4*i + 2];
- baked_image_data[5*i + 3] = baked_color_data[4*i + 3]; // alpha should be correct for eyelashes.
- baked_image_data[5*i + 4] = baked_mask_data[i];
- i++;
- }
- }
-
- LLPointer<LLImageJ2C> compressedImage = new LLImageJ2C;
- const char* comment_text = LINDEN_J2C_COMMENT_PREFIX "RGBHM"; // writes into baked_color_data. 5 channels (rgb, heightfield/alpha, mask)
- if (compressedImage->encode(baked_image, comment_text))
- {
- LLTransactionID tid;
- tid.generate();
- const LLAssetID asset_id = tid.makeAssetID(gAgent.getSecureSessionID());
- if (LLVFile::writeFile(compressedImage->getData(), compressedImage->getDataSize(),
- gVFS, asset_id, LLAssetType::AT_TEXTURE))
- {
- // Read back the file and validate.
- BOOL valid = FALSE;
- LLPointer<LLImageJ2C> integrity_test = new LLImageJ2C;
- S32 file_size = 0;
- LLVFile file(gVFS, asset_id, LLAssetType::AT_TEXTURE);
- file_size = file.getSize();
- U8* data = integrity_test->allocateData(file_size);
- file.read(data, file_size);
- if (data)
- {
- valid = integrity_test->validate(data, file_size); // integrity_test will delete 'data'
- }
- else
- {
- integrity_test->setLastError("Unable to read entire file");
- }
-
- if (valid)
- {
- const bool highest_lod = layer_set->isLocalTextureDataFinal();
- // Baked_upload_data is owned by the responder and deleted after the request completes.
- LLBakedUploadData* baked_upload_data = new LLBakedUploadData(gAgentAvatarp,
- layer_set,
- asset_id,
- highest_lod);
- // upload ID is used to avoid overlaps, e.g. when the user rapidly makes two changes outside of Face Edit.
- mUploadID = asset_id;
-
- // Upload the image
- const std::string url = gAgent.getRegion()->getCapability("UploadBakedTexture");
- if(!url.empty()
- && !LLPipeline::sForceOldBakedUpload // toggle debug setting UploadBakedTexOld to change between the new caps method and old method
- && (mUploadFailCount < (BAKE_UPLOAD_ATTEMPTS - 1))) // Try last ditch attempt via asset store if cap upload is failing.
- {
- LLSD body = LLSD::emptyMap();
- // The responder will call LLViewerTexLayerSetBuffer::onTextureUploadComplete()
- LLHTTPClient::post(url, body, new LLSendTexLayerResponder(body, mUploadID, LLAssetType::AT_TEXTURE, baked_upload_data));
- LL_INFOS() << "Baked texture upload via capability of " << mUploadID << " to " << url << LL_ENDL;
- }
- else
- {
- gAssetStorage->storeAssetData(tid,
- LLAssetType::AT_TEXTURE,
- LLViewerTexLayerSetBuffer::onTextureUploadComplete,
- baked_upload_data,
- TRUE, // temp_file
- TRUE, // is_priority
- TRUE); // store_local
- LL_INFOS() << "Baked texture upload via Asset Store." << LL_ENDL;
- }
-
- if (highest_lod)
- {
- // Sending the final LOD for the baked texture. All done, pause
- // the upload timer so we know how long it took.
- mNeedsUpload = FALSE;
- mNeedsUploadTimer.pause();
- }
- else
- {
- // Sending a lower level LOD for the baked texture. Restart the upload timer.
- mNumLowresUploads++;
- mNeedsUploadTimer.unpause();
- mNeedsUploadTimer.reset();
- }
-
- // Print out notification that we uploaded this texture.
- if (gSavedSettings.getBOOL("DebugAvatarRezTime"))
- {
- const std::string lod_str = highest_lod ? "HighRes" : "LowRes";
- LLSD args;
- args["EXISTENCE"] = llformat("%d",(U32)layer_set->getAvatar()->debugGetExistenceTimeElapsedF32());
- args["TIME"] = llformat("%d",(U32)mNeedsUploadTimer.getElapsedTimeF32());
- args["BODYREGION"] = layer_set->getBodyRegionName();
- args["RESOLUTION"] = lod_str;
- LLNotificationsUtil::add("AvatarRezSelfBakedTextureUploadNotification",args);
- LL_DEBUGS("Avatar") << self_av_string() << "Uploading [ name: " << layer_set->getBodyRegionName() << " res:" << lod_str << " time:" << (U32)mNeedsUploadTimer.getElapsedTimeF32() << " ]" << LL_ENDL;
- }
- }
- else
- {
- // The read back and validate operation failed. Remove the uploaded file.
- mUploadPending = FALSE;
- LLVFile file(gVFS, asset_id, LLAssetType::AT_TEXTURE, LLVFile::WRITE);
- file.remove();
- LL_INFOS() << "Unable to create baked upload file (reason: corrupted)." << LL_ENDL;
- }
- }
- }
- else
- {
- // The VFS write file operation failed.
- mUploadPending = FALSE;
- LL_INFOS() << "Unable to create baked upload file (reason: failed to write file)" << LL_ENDL;
- }
-
- delete [] baked_color_data;
-}
-
// Mostly bookkeeping; don't need to actually "do" anything since
// render() will actually do the update.
void LLViewerTexLayerSetBuffer::doUpdate()
@@ -547,82 +252,6 @@ void LLViewerTexLayerSetBuffer::doUpdate()
}
}
-// static
-void LLViewerTexLayerSetBuffer::onTextureUploadComplete(const LLUUID& uuid,
- void* userdata,
- S32 result,
- LLExtStat ext_status) // StoreAssetData callback (not fixed)
-{
- LLBakedUploadData* baked_upload_data = (LLBakedUploadData*)userdata;
-
- if (isAgentAvatarValid() &&
- !gAgentAvatarp->isDead() &&
- (baked_upload_data->mAvatar == gAgentAvatarp) && // Sanity check: only the user's avatar should be uploading textures.
- (baked_upload_data->mTexLayerSet->hasComposite()))
- {
- LLViewerTexLayerSetBuffer* layerset_buffer = baked_upload_data->mTexLayerSet->getViewerComposite();
- S32 failures = layerset_buffer->mUploadFailCount;
- layerset_buffer->mUploadFailCount = 0;
-
- if (layerset_buffer->mUploadID.isNull())
- {
- // The upload got canceled, we should be in the
- // process of baking a new texture so request an
- // upload with the new data
-
- // BAP: does this really belong in this callback, as
- // opposed to where the cancellation takes place?
- // suspect this does nothing.
- layerset_buffer->requestUpload();
- }
- else if (baked_upload_data->mID == layerset_buffer->mUploadID)
- {
- // This is the upload we're currently waiting for.
- layerset_buffer->mUploadID.setNull();
- const std::string name(baked_upload_data->mTexLayerSet->getBodyRegionName());
- const std::string resolution = baked_upload_data->mIsHighestRes ? " full res " : " low res ";
- if (result >= 0)
- {
- layerset_buffer->mUploadPending = FALSE; // Allows sending of AgentSetAppearance later
- LLAvatarAppearanceDefines::ETextureIndex baked_te = gAgentAvatarp->getBakedTE(layerset_buffer->getViewerTexLayerSet());
- // Update baked texture info with the new UUID
- U64 now = LLFrameTimer::getTotalTime(); // Record starting time
- LL_INFOS() << "Baked" << resolution << "texture upload for " << name << " took " << (S32)((now - baked_upload_data->mStartTime) / 1000) << " ms" << LL_ENDL;
- gAgentAvatarp->setNewBakedTexture(baked_te, uuid);
- }
- else
- {
- ++failures;
- S32 max_attempts = baked_upload_data->mIsHighestRes ? BAKE_UPLOAD_ATTEMPTS : 1; // only retry final bakes
- LL_WARNS() << "Baked" << resolution << "texture upload for " << name << " failed (attempt " << failures << "/" << max_attempts << ")" << LL_ENDL;
- if (failures < max_attempts)
- {
- layerset_buffer->mUploadFailCount = failures;
- layerset_buffer->mUploadRetryTimer.start();
- layerset_buffer->requestUpload();
- }
- }
- }
- else
- {
- LL_INFOS() << "Received baked texture out of date, ignored." << LL_ENDL;
- }
-
- gAgentAvatarp->dirtyMesh();
- }
- else
- {
- // Baked texture failed to upload (in which case since we
- // didn't set the new baked texture, it means that they'll try
- // and rebake it at some point in the future (after login?)),
- // or this response to upload is out of date, in which case a
- // current response should be on the way or already processed.
- LL_WARNS() << "Baked upload failed" << LL_ENDL;
- }
-
- delete baked_upload_data;
-}
-
//-----------------------------------------------------------------------------
// LLViewerTexLayerSet
// An ordered set of texture layers that get composited into a single texture.
@@ -664,20 +293,6 @@ void LLViewerTexLayerSet::requestUpdate()
}
}
-void LLViewerTexLayerSet::requestUpload()
-{
- createComposite();
- getViewerComposite()->requestUpload();
-}
-
-void LLViewerTexLayerSet::cancelUpload()
-{
- if(mComposite)
- {
- getViewerComposite()->cancelUpload();
- }
-}
-
void LLViewerTexLayerSet::updateComposite()
{
createComposite();
@@ -730,19 +345,12 @@ const std::string LLViewerTexLayerSetBuffer::dumpTextureInfo() const
{
if (!isAgentAvatarValid()) return "";
- const BOOL is_high_res = !mNeedsUpload;
- const U32 num_low_res = mNumLowresUploads;
- const U32 upload_time = (U32)mNeedsUploadTimer.getElapsedTimeF32();
+ const BOOL is_high_res = TRUE;
+ const U32 num_low_res = 0;
const std::string local_texture_info = gAgentAvatarp->debugDumpLocalTextureDataInfo(getViewerTexLayerSet());
- std::string status = "CREATING ";
- if (!uploadNeeded()) status = "DONE ";
- if (uploadInProgress()) status = "UPLOADING";
-
- std::string text = llformat("[%s] [HiRes:%d LoRes:%d] [Elapsed:%d] %s",
- status.c_str(),
+ std::string text = llformat("[HiRes:%d LoRes:%d] %s",
is_high_res, num_low_res,
- upload_time,
local_texture_info.c_str());
return text;
}