diff options
-rw-r--r-- | indra/newview/app_settings/settings.xml | 16 | ||||
-rw-r--r-- | indra/newview/lltexlayer.cpp | 144 | ||||
-rw-r--r-- | indra/newview/lltexlayer.h | 78 | ||||
-rw-r--r-- | indra/newview/lltextureview.cpp | 4 | ||||
-rw-r--r-- | indra/newview/lltoolmorph.cpp | 2 | ||||
-rw-r--r-- | indra/newview/llvoavatar.h | 5 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/en/notifications.xml | 2 |
7 files changed, 182 insertions, 69 deletions
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index af296f918e..810b2d9a1d 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -585,7 +585,7 @@ <key>Value</key> <integer>2</integer> </map> - <key>AvatarBakedTextureTimeout</key> + <key>AvatarBakedTextureUploadTimeout</key> <map> <key>Comment</key> <string>Specifes the maximum time in seconds to wait before sending your baked textures for avatar appearance. Set to 0 to disable and wait until all baked textures are at highest resolution.</string> @@ -594,8 +594,20 @@ <key>Type</key> <string>U32</string> <key>Value</key> - <integer>120</integer> + <integer>60</integer> </map> + <key>AvatarBakedLocalTextureUpdateTimeout</key> + <map> + <key>Comment</key> + <string>Specifes the maximum time in seconds to wait before updating your appearance during appearance mode.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>U32</string> + <key>Value</key> + <integer>10</integer> + </map> + <key>AvatarSex</key> <map> <key>Comment</key> diff --git a/indra/newview/lltexlayer.cpp b/indra/newview/lltexlayer.cpp index 46bd55de43..355f46e290 100644 --- a/indra/newview/lltexlayer.cpp +++ b/indra/newview/lltexlayer.cpp @@ -119,14 +119,16 @@ LLTexLayerSetBuffer::LLTexLayerSetBuffer(LLTexLayerSet* const owner, S32 width, S32 height) : // ORDER_LAST => must render these after the hints are created. LLViewerDynamicTexture( width, height, 4, LLViewerDynamicTexture::ORDER_LAST, TRUE ), - mNeedsUpdate(TRUE), - mNeedsUpload(FALSE), mUploadPending(FALSE), // Not used for any logic here, just to sync sending of updates + mNeedsUpload(FALSE), mNumLowresUploads(0), + mNeedsUpdate(TRUE), + mNumLowresUpdates(0), mTexLayerSet(owner) { LLTexLayerSetBuffer::sGLByteCount += getSize(); mNeedsUploadTimer.start(); + mNeedsUpdateTimer.start(); } LLTexLayerSetBuffer::~LLTexLayerSetBuffer() @@ -165,8 +167,9 @@ void LLTexLayerSetBuffer::dumpTotalByteCount() void LLTexLayerSetBuffer::requestUpdate() { - conditionalRestartUploadTimer(); + 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(); @@ -196,6 +199,12 @@ void LLTexLayerSetBuffer::conditionalRestartUploadTimer() } } +void LLTexLayerSetBuffer::restartUpdateTimer() +{ + mNeedsUpdateTimer.reset(); + mNeedsUpdateTimer.start(); +} + void LLTexLayerSetBuffer::cancelUpload() { mNeedsUpload = FALSE; @@ -229,25 +238,31 @@ BOOL LLTexLayerSetBuffer::needsRender() llassert(mTexLayerSet->getAvatar() == gAgentAvatarp); if (!isAgentAvatarValid()) return FALSE; - const BOOL upload_now = isReadyToUpload(); - BOOL needs_update = (mNeedsUpdate || upload_now) && !gAgentAvatarp->mAppearanceAnimating; - if (needs_update) + 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)) { - BOOL invalid_skirt = gAgentAvatarp->getBakedTE(mTexLayerSet) == LLVOAvatarDefines::TEX_SKIRT_BAKED && !gAgentAvatarp->isWearingWearableType(LLWearableType::WT_SKIRT); - if (invalid_skirt) - { - // we were trying to create a skirt texture - // but we're no longer wearing a skirt... - needs_update = FALSE; - cancelUpload(); - } - else - { - needs_update &= mTexLayerSet->isLocalTextureDataAvailable(); - } + return FALSE; + } + + // Don't render if we're animating our appearance. + if (gAgentAvatarp->getIsAppearanceAnimating()) + { + return FALSE; } - return needs_update; + // Don't render if we are trying to create a shirt texture but aren't wearing a skirt. + if (gAgentAvatarp->getBakedTE(mTexLayerSet) == LLVOAvatarDefines::TEX_SKIRT_BAKED && + !gAgentAvatarp->isWearingWearableType(LLWearableType::WT_SKIRT)) + { + cancelUpload(); + return FALSE; + } + + // Render if we have at least minimal level of detail for each local texture. + return mTexLayerSet->isLocalTextureDataAvailable(); } void LLTexLayerSetBuffer::preRender(BOOL clear_depth) @@ -272,11 +287,12 @@ BOOL LLTexLayerSetBuffer::render() gGL.setColorMask(true, true); // 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? - const BOOL upload_now = isReadyToUpload(); + // 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(); + BOOL success = TRUE; - // Composite the color data LLGLSUIDefault gls_ui; success &= mTexLayerSet->render( mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight ); @@ -294,7 +310,7 @@ BOOL LLTexLayerSetBuffer::render() if (mTexLayerSet->isVisible()) { mTexLayerSet->getAvatar()->debugBakedTextureUpload(mTexLayerSet->getBakedTexIndex(), FALSE); // FALSE for start of upload, TRUE for finish. - readBackAndUpload(); + doUpload(); } else { @@ -305,6 +321,11 @@ BOOL LLTexLayerSetBuffer::render() } } } + + if (update_now) + { + doUpdate(); + } // reset GL state gGL.setColorMask(true, true); @@ -312,7 +333,6 @@ BOOL LLTexLayerSetBuffer::render() // we have valid texture data now mGLTexturep->setGLTextureCreated(true); - mNeedsUpdate = FALSE; return success; } @@ -339,16 +359,16 @@ BOOL LLTexLayerSetBuffer::uploadInProgress() const BOOL LLTexLayerSetBuffer::isReadyToUpload() const { - if (!mNeedsUpload) return FALSE; // Don't need to upload if we haven't requested one. if (!gAgentQueryManager.hasNoPendingQueries()) return FALSE; // Can't upload if there are pending queries. if (isAgentAvatarValid() && !gAgentAvatarp->isUsingBakedTextures()) return FALSE; // Don't upload if avatar is using composites. // If we requested an upload and have the final LOD ready, then upload. - const BOOL can_highest_lod = mTexLayerSet->isLocalTextureDataFinal(); - if (can_highest_lod) return TRUE; + if (mTexLayerSet->isLocalTextureDataFinal()) return TRUE; - const U32 texture_timeout = gSavedSettings.getU32("AvatarBakedTextureTimeout"); - if (texture_timeout) + // 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. @@ -359,10 +379,33 @@ BOOL LLTexLayerSetBuffer::isReadyToUpload() const const BOOL has_lower_lod = mTexLayerSet->isLocalTextureDataAvailable(); if (has_lower_lod && is_upload_textures_timeout) return TRUE; } + return FALSE; } -BOOL LLTexLayerSetBuffer::updateImmediate() +BOOL LLTexLayerSetBuffer::isReadyToUpdate() const +{ + // If we requested an update and have the final LOD ready, then update. + if (mTexLayerSet->isLocalTextureDataFinal()) return TRUE; + + // If we haven't done an update yet, then just do one now regardless of state of textures. + if (mNumLowresUpdates == 0) return TRUE; + + // Update if we've hit a timeout. Unlike for uploads, we can make this timeout fairly small + // since render unnecessarily doesn't cost much. + const U32 texture_timeout = gSavedSettings.getU32("AvatarBakedLocalTextureUpdateTimeout"); + if (texture_timeout != 0) + { + // If we hit our timeout and have textures available at even lower resolution, then update. + const BOOL is_update_textures_timeout = mNeedsUpdateTimer.getElapsedTimeF32() >= texture_timeout; + const BOOL has_lower_lod = mTexLayerSet->isLocalTextureDataAvailable(); + if (has_lower_lod && is_update_textures_timeout) return TRUE; + } + + return FALSE; +} + +BOOL LLTexLayerSetBuffer::requestUpdateImmediate() { mNeedsUpdate = TRUE; BOOL result = FALSE; @@ -377,7 +420,9 @@ BOOL LLTexLayerSetBuffer::updateImmediate() return result; } -void LLTexLayerSetBuffer::readBackAndUpload() +// 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 LLTexLayerSetBuffer::doUpload() { llinfos << "Uploading baked " << mTexLayerSet->getBodyRegionName() << llendl; LLViewerStats::getInstance()->incStat(LLViewerStats::ST_TEX_BAKES); @@ -447,6 +492,7 @@ void LLTexLayerSetBuffer::readBackAndUpload() LLBakedUploadData* baked_upload_data = new LLBakedUploadData(gAgentAvatarp, this->mTexLayerSet, asset_id); + // 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 @@ -493,9 +539,10 @@ void LLTexLayerSetBuffer::readBackAndUpload() std::string lod_str = highest_lod ? "HighRes" : "LowRes"; LLSD args; args["EXISTENCE"] = llformat("%d",(U32)mTexLayerSet->getAvatar()->debugGetExistenceTimeElapsedF32()); - args["TIME"] = llformat("%d",(U32)mNeedsUploadTimer.getElapsedTimeF32()); + args["TIME"] = llformat("%d",(U32)mNeedsUpdateTimer.getElapsedTimeF32()); args["BODYREGION"] = mTexLayerSet->getBodyRegionName(); args["RESOLUTION"] = lod_str; + args["ACTION"] = "uploaded"; LLNotificationsUtil::add("AvatarRezSelfBakeNotification",args); llinfos << "Uploading [ name: " << mTexLayerSet->getBodyRegionName() << " res:" << lod_str << " time:" << (U32)mNeedsUploadTimer.getElapsedTimeF32() << " ]" << llendl; } @@ -520,6 +567,37 @@ void LLTexLayerSetBuffer::readBackAndUpload() delete [] baked_color_data; } +// Mostly bookkeeping; don't need to actually "do" anything since +// render() will actually do the update. +void LLTexLayerSetBuffer::doUpdate() +{ + const BOOL highest_lod = mTexLayerSet->isLocalTextureDataFinal(); + if (highest_lod) + { + mNeedsUpdate = FALSE; + } + else + { + mNumLowresUpdates++; + } + + restartUpdateTimer(); + + // Print out notification that we uploaded this texture. + if (gSavedSettings.getBOOL("DebugAvatarRezTime")) + { + const BOOL highest_lod = mTexLayerSet->isLocalTextureDataFinal(); + std::string lod_str = highest_lod ? "HighRes" : "LowRes"; + LLSD args; + args["EXISTENCE"] = llformat("%d",(U32)mTexLayerSet->getAvatar()->debugGetExistenceTimeElapsedF32()); + args["TIME"] = llformat("%d",(U32)mNeedsUploadTimer.getElapsedTimeF32()); + args["BODYREGION"] = mTexLayerSet->getBodyRegionName(); + args["RESOLUTION"] = lod_str; + args["ACTION"] = "locally updated"; + LLNotificationsUtil::add("AvatarRezSelfBakeNotification",args); + llinfos << "Locally updating [ name: " << mTexLayerSet->getBodyRegionName() << " res:" << lod_str << " time:" << (U32)mNeedsUpdateTimer.getElapsedTimeF32() << " ]" << llendl; + } +} // static void LLTexLayerSetBuffer::onTextureUploadComplete(const LLUUID& uuid, @@ -931,7 +1009,7 @@ void LLTexLayerSet::setUpdatesEnabled( BOOL b ) void LLTexLayerSet::updateComposite() { createComposite(); - mComposite->updateImmediate(); + mComposite->requestUpdateImmediate(); } LLTexLayerSetBuffer* LLTexLayerSet::getComposite() diff --git a/indra/newview/lltexlayer.h b/indra/newview/lltexlayer.h index cb2e1faaa6..745cd88c47 100644 --- a/indra/newview/lltexlayer.h +++ b/indra/newview/lltexlayer.h @@ -270,47 +270,69 @@ class LLTexLayerSetBuffer : public LLViewerDynamicTexture public: LLTexLayerSetBuffer(LLTexLayerSet* const owner, S32 width, S32 height); virtual ~LLTexLayerSetBuffer(); - /*virtual*/ S8 getType() const; - virtual void preRender(BOOL clear_depth); - virtual void postRender(BOOL success); - virtual BOOL render(); - BOOL updateImmediate(); +public: + /*virtual*/ S8 getType() const; BOOL isInitialized(void) const; - BOOL uploadPending() const; // We are expecting a new texture to be uploaded at some point - BOOL uploadNeeded() const; // We need to upload a new texture - BOOL uploadInProgress() const; // We have started uploading a new texture and are awaiting the result + static void dumpTotalByteCount(); + const std::string dumpTextureInfo() const; + virtual void restoreGLTexture(); + virtual void destroyGLTexture(); +protected: + void pushProjection() const; + void popProjection() const; +private: + LLTexLayerSet* const mTexLayerSet; + static S32 sGLByteCount; + //-------------------------------------------------------------------- + // Render + //-------------------------------------------------------------------- +public: /*virtual*/ BOOL needsRender(); - void requestUpdate(); +protected: + BOOL render(S32 x, S32 y, S32 width, S32 height); + virtual void preRender(BOOL clear_depth); + virtual void postRender(BOOL success); + virtual BOOL render(); + + //-------------------------------------------------------------------- + // Uploads + //-------------------------------------------------------------------- +public: void requestUpload(); void cancelUpload(); - BOOL render(S32 x, S32 y, S32 width, S32 height); - void readBackAndUpload(); + BOOL uploadNeeded() const; // We need to upload a new texture + BOOL uploadInProgress() const; // We have started uploading a new texture and are awaiting the result + BOOL uploadPending() const; // We are expecting a new texture to be uploaded at some point static void onTextureUploadComplete(const LLUUID& uuid, void* userdata, S32 result, LLExtStat ext_status); - static void dumpTotalByteCount(); - const std::string dumpTextureInfo() const; - virtual void restoreGLTexture(); - virtual void destroyGLTexture(); - - protected: - void pushProjection() const; - void popProjection() const; BOOL isReadyToUpload() const; + void doUpload(); // Does a read back and upload. void conditionalRestartUploadTimer(); - private: - LLTexLayerSet* const mTexLayerSet; - BOOL mNeedsUpdate; // whether we need to update our baked textures - BOOL mNeedsUpload; // whether we need to send our baked textures to the server - U32 mNumLowresUploads; // number of times we've sent a lowres version of our baked textures to the server - BOOL mUploadPending; // whether we have received back the new baked textures - LLUUID mUploadID; // the current upload process (null if none). Used to avoid overlaps, e.g. when the user rapidly makes two changes outside of Face Edit. - static S32 sGLByteCount; - LLFrameTimer mNeedsUploadTimer; // Tracks time since upload was requested + BOOL mNeedsUpload; // Whether we need to send our baked textures to the server + U32 mNumLowresUploads; // Number of times we've sent a lowres version of our baked textures to the server + BOOL mUploadPending; // Whether we have received back the new baked textures + LLUUID mUploadID; // The current upload process (null if none). + LLFrameTimer mNeedsUploadTimer; // Tracks time since upload was requested and performed. + + //-------------------------------------------------------------------- + // Updates + //-------------------------------------------------------------------- +public: + void requestUpdate(); + BOOL requestUpdateImmediate(); +protected: + BOOL isReadyToUpdate() const; + void doUpdate(); + void restartUpdateTimer(); +private: + BOOL mNeedsUpdate; // Whether we need to locally update our baked textures + U32 mNumLowresUpdates; // Number of times we've locally updated with lowres version of our baked textures + LLFrameTimer mNeedsUpdateTimer; // Tracks time since update was requested and performed. }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/indra/newview/lltextureview.cpp b/indra/newview/lltextureview.cpp index 8ea4dbeb04..b588ff91d1 100644 --- a/indra/newview/lltextureview.cpp +++ b/indra/newview/lltextureview.cpp @@ -450,14 +450,14 @@ void LLAvatarTexBar::draw() text_color, LLFontGL::LEFT, LLFontGL::TOP); //, LLFontGL::BOLD, LLFontGL::DROP_SHADOW_SOFT); line_num++; } - const U32 texture_timeout = gSavedSettings.getU32("AvatarBakedTextureTimeout"); + const U32 texture_timeout = gSavedSettings.getU32("AvatarBakedTextureUploadTimeout"); const U32 override_tex_discard_level = gSavedSettings.getU32("TextureDiscardLevel"); LLColor4 header_color(1.f, 1.f, 1.f, 0.9f); const std::string texture_timeout_str = texture_timeout ? llformat("%d",texture_timeout) : "Disabled"; const std::string override_tex_discard_level_str = override_tex_discard_level ? llformat("%d",override_tex_discard_level) : "Disabled"; - std::string header_text = llformat("[ Timeout('AvatarBakedTextureTimeout'):%s ] [ LOD_Override('TextureDiscardLevel'):%s ]", texture_timeout_str.c_str(), override_tex_discard_level_str.c_str()); + std::string header_text = llformat("[ Timeout('AvatarBakedTextureUploadTimeout'):%s ] [ LOD_Override('TextureDiscardLevel'):%s ]", texture_timeout_str.c_str(), override_tex_discard_level_str.c_str()); LLFontGL::getFontMonospace()->renderUTF8(header_text, 0, l_offset, v_offset + line_height*line_num, header_color, LLFontGL::LEFT, LLFontGL::TOP); //, LLFontGL::BOLD, LLFontGL::DROP_SHADOW_SOFT); line_num++; diff --git a/indra/newview/lltoolmorph.cpp b/indra/newview/lltoolmorph.cpp index fa21b1a866..81559429b0 100644 --- a/indra/newview/lltoolmorph.cpp +++ b/indra/newview/lltoolmorph.cpp @@ -147,7 +147,7 @@ void LLVisualParamHint::requestHintUpdates( LLVisualParamHint* exception1, LLVis BOOL LLVisualParamHint::needsRender() { - return mNeedsUpdate && mDelayFrames-- <= 0 && !gAgentAvatarp->mAppearanceAnimating && mAllowsUpdates; + return mNeedsUpdate && mDelayFrames-- <= 0 && !gAgentAvatarp->getIsAppearanceAnimating() && mAllowsUpdates; } void LLVisualParamHint::preRender(BOOL clear_depth) diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 49b9fe1536..22fc595ea2 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -611,8 +611,9 @@ public: // Appearance morphing //-------------------------------------------------------------------- public: - BOOL mAppearanceAnimating; + BOOL getIsAppearanceAnimating() const { return mAppearanceAnimating; } private: + BOOL mAppearanceAnimating; LLFrameTimer mAppearanceMorphTimer; F32 mLastAppearanceBlendTime; @@ -622,7 +623,7 @@ private: public: void setClothesColor(LLVOAvatarDefines::ETextureIndex te, const LLColor4& new_color, BOOL upload_bake); LLColor4 getClothesColor(LLVOAvatarDefines::ETextureIndex te); - static BOOL teToColorParams(LLVOAvatarDefines::ETextureIndex te, U32 *param_name); + static BOOL teToColorParams(LLVOAvatarDefines::ETextureIndex te, U32 *param_name); //-------------------------------------------------------------------- // Global colors diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 04bdb4302c..4c241562e6 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -6343,7 +6343,7 @@ Avatar '[NAME]' left as fully loaded. name="AvatarRezSelfBakeNotification" type="notifytip"> ( [EXISTENCE] seconds alive ) -You uploaded a [RESOLUTION] baked texture for '[BODYREGION]' after [TIME] seconds. +You [ACTION] a [RESOLUTION] baked texture for '[BODYREGION]' after [TIME] seconds. </notification> <notification |