diff options
Diffstat (limited to 'indra/newview/llvoavatar.cpp')
-rw-r--r-- | indra/newview/llvoavatar.cpp | 158 |
1 files changed, 99 insertions, 59 deletions
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 3b51d07f96..d567623ac0 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -38,6 +38,7 @@ #include "raytrace.h" #include "llagent.h" // Get state values from here +#include "llagentbenefits.h" #include "llagentcamera.h" #include "llagentwearables.h" #include "llanimationstates.h" @@ -197,6 +198,8 @@ const F32 NAMETAG_VERT_OFFSET_WEIGHT = 0.17f; const U32 LLVOAvatar::VISUAL_COMPLEXITY_UNKNOWN = 0; const F64 HUD_OVERSIZED_TEXTURE_DATA_SIZE = 1024 * 1024; +const F32 MAX_TEXTURE_WAIT_TIME_SEC = 60; + enum ERenderName { RENDER_NAME_NEVER, @@ -663,6 +666,7 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, mFullyLoadedInitialized(FALSE), mVisualComplexity(VISUAL_COMPLEXITY_UNKNOWN), mLoadedCallbacksPaused(FALSE), + mLoadedCallbackTextures(0), mRenderUnloadedAvatar(LLCachedControl<bool>(gSavedSettings, "RenderUnloadedAvatar", false)), mLastRezzedStatus(-1), mIsEditingAppearance(FALSE), @@ -883,8 +887,9 @@ BOOL LLVOAvatar::hasGray() const S32 LLVOAvatar::getRezzedStatus() const { if (getIsCloud()) return 0; - if (isFullyTextured() && allBakedTexturesCompletelyDownloaded()) return 3; - if (isFullyTextured()) return 2; + bool textured = isFullyTextured(); + if (textured && allBakedTexturesCompletelyDownloaded()) return 3; + if (textured) return 2; llassert(hasGray()); return 1; // gray } @@ -2045,8 +2050,10 @@ void LLVOAvatar::resetSkeleton(bool reset_animations) LL_ERRS() << "Error resetting skeleton" << LL_ENDL; } - // Reset attachment points (buildSkeleton only does bones and CVs) - bool ignore_hud_joints = true; + // Reset attachment points + // BuildSkeleton only does bones and CVs but we still need to reinit huds + // since huds can be animated. + bool ignore_hud_joints = !isSelf(); initAttachmentPoints(ignore_hud_joints); // Fix up collision volumes @@ -2953,7 +2960,7 @@ void LLVOAvatar::idleUpdateLoadingEffect() void LLVOAvatar::idleUpdateWindEffect() { // update wind effect - if ((LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) >= LLDrawPoolAvatar::SHADER_LEVEL_CLOTH)) + if ((LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) >= LLDrawPoolAvatar::SHADER_LEVEL_CLOTH)) { F32 hover_strength = 0.f; F32 time_delta = mRippleTimer.getElapsedTimeF32() - mRippleTimeLast; @@ -4655,7 +4662,7 @@ U32 LLVOAvatar::renderSkinned() } } - if (LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) <= 0) + if (LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) <= 0) { if (mNeedsSkin) { @@ -4804,6 +4811,15 @@ U32 LLVOAvatar::renderSkinned() BOOL first_pass = TRUE; if (!LLDrawPoolAvatar::sSkipOpaque) { + if (isUIAvatar() && mIsDummy) + { + LLViewerJoint* hair_mesh = getViewerJoint(MESH_ID_HAIR); + if (hair_mesh) + { + num_indices += hair_mesh->render(mAdjustedPixelArea, first_pass, mIsDummy); + } + first_pass = FALSE; + } if (!isSelf() || gAgent.needsRenderHead() || LLPipeline::sShadowRender) { if (isTextureVisible(TEX_HEAD_BAKED) || isUIAvatar()) @@ -4811,7 +4827,7 @@ U32 LLVOAvatar::renderSkinned() LLViewerJoint* head_mesh = getViewerJoint(MESH_ID_HEAD); if (head_mesh) { - num_indices += head_mesh->render(mAdjustedPixelArea, TRUE, mIsDummy); + num_indices += head_mesh->render(mAdjustedPixelArea, first_pass, mIsDummy); } first_pass = FALSE; } @@ -5318,12 +5334,28 @@ void LLVOAvatar::checkTextureLoading() } if(mLoadedCallbacksPaused == pause) { + if (!pause && mFirstFullyVisible && mLoadedCallbackTextures < mCallbackTextureList.size()) + { + // We still need to update 'loaded' textures count to decide on 'cloud' visibility + // Alternatively this can be done on TextureLoaded callbacks, but is harder to properly track + mLoadedCallbackTextures = 0; + for (LLLoadedCallbackEntry::source_callback_list_t::iterator iter = mCallbackTextureList.begin(); + iter != mCallbackTextureList.end(); ++iter) + { + LLViewerFetchedTexture* tex = gTextureList.findImage(*iter); + if (tex && (tex->getDiscardLevel() >= 0 || tex->isMissingAsset())) + { + mLoadedCallbackTextures++; + } + } + } return ; } if(mCallbackTextureList.empty()) //when is self or no callbacks. Note: this list for self is always empty. { mLoadedCallbacksPaused = pause ; + mLoadedCallbackTextures = 0; return ; //nothing to check. } @@ -5331,7 +5363,9 @@ void LLVOAvatar::checkTextureLoading() { return ; //have not been invisible for enough time. } - + + mLoadedCallbackTextures = pause ? mCallbackTextureList.size() : 0; + for(LLLoadedCallbackEntry::source_callback_list_t::iterator iter = mCallbackTextureList.begin(); iter != mCallbackTextureList.end(); ++iter) { @@ -5352,9 +5386,15 @@ void LLVOAvatar::checkTextureLoading() tex->unpauseLoadedCallbacks(&mCallbackTextureList) ; tex->addTextureStats(START_AREA); //jump start the fetching again + + // technically shouldn't need to account for missing, but callback might not have happened yet + if (tex->getDiscardLevel() >= 0 || tex->isMissingAsset()) + { + mLoadedCallbackTextures++; // consider it loaded (we have at least some data) + } } - } - } + } + } if(!pause) { @@ -6576,7 +6616,7 @@ void LLVOAvatar::initAttachmentPoints(bool ignore_hud_joints) LLAvatarXmlInfo::LLAvatarAttachmentInfo *info = *iter; if (info->mIsHUDAttachment && (!isSelf() || ignore_hud_joints)) { - //don't process hud joint for other avatars, or when doing a skeleton reset. + //don't process hud joint for other avatars. continue; } @@ -7061,20 +7101,7 @@ U32 LLVOAvatar::getNumAttachments() const //----------------------------------------------------------------------------- S32 LLVOAvatar::getMaxAttachments() const { - const S32 MAX_AGENT_ATTACHMENTS = 38; - - S32 max_attach = MAX_AGENT_ATTACHMENTS; - - if (gAgent.getRegion()) - { - LLSD features; - gAgent.getRegion()->getSimulatorFeatures(features); - if (features.has("MaxAgentAttachments")) - { - max_attach = features["MaxAgentAttachments"].asInteger(); - } - } - return max_attach; + return LLAgentBenefitsMgr::current().getAttachmentLimit(); } //----------------------------------------------------------------------------- @@ -7108,24 +7135,7 @@ U32 LLVOAvatar::getNumAnimatedObjectAttachments() const //----------------------------------------------------------------------------- S32 LLVOAvatar::getMaxAnimatedObjectAttachments() const { - S32 max_attach = 0; - if (gSavedSettings.getBOOL("AnimatedObjectsIgnoreLimits")) - { - max_attach = getMaxAttachments(); - } - else - { - if (gAgent.getRegion()) - { - LLSD features; - gAgent.getRegion()->getSimulatorFeatures(features); - if (features.has("AnimatedObjects")) - { - max_attach = features["AnimatedObjects"]["MaxAgentAnimatedObjectAttachments"].asInteger(); - } - } - } - return max_attach; + return LLAgentBenefitsMgr::current().getAnimatedObjectLimit(); } //----------------------------------------------------------------------------- @@ -7363,7 +7373,8 @@ void LLVOAvatar::sitOnObject(LLViewerObject *sit_object) mRoot->updateWorldMatrixChildren(); stopMotion(ANIM_AGENT_BODY_NOISE); - + + gAgentCamera.setInitSitRot(gAgent.getFrameAgent().getQuaternion()); } //----------------------------------------------------------------------------- @@ -7618,14 +7629,13 @@ bool LLVOAvatar::getIsCloud() const ); } -void LLVOAvatar::updateRezzedStatusTimers() +void LLVOAvatar::updateRezzedStatusTimers(S32 rez_status) { // State machine for rezzed status. Statuses are -1 on startup, 0 // = cloud, 1 = gray, 2 = downloading, 3 = full. // Purpose is to collect time data for each it takes avatar to reach // various loading landmarks: gray, textured (partial), textured fully. - S32 rez_status = getRezzedStatus(); if (rez_status != mLastRezzedStatus) { LL_DEBUGS("Avatar") << avString() << "rez state change: " << mLastRezzedStatus << " -> " << rez_status << LL_ENDL; @@ -7795,8 +7805,21 @@ void LLVOAvatar::logMetricsTimerRecord(const std::string& phase_name, F32 elapse // returns true if the value has changed. BOOL LLVOAvatar::updateIsFullyLoaded() { - const bool loading = getIsCloud(); - updateRezzedStatusTimers(); + S32 rez_status = getRezzedStatus(); + bool loading = getIsCloud(); + if (mFirstFullyVisible && !mIsControlAvatar) + { + loading = ((rez_status < 2) + // Wait at least 60s for unfinished textures to finish on first load, + // don't wait forever, it might fail. Even if it will eventually load by + // itself and update mLoadedCallbackTextures (or fail and clean the list), + // avatars are more time-sensitive than textures and can't wait that long. + || (mLoadedCallbackTextures < mCallbackTextureList.size() && mLastTexCallbackAddedTime.getElapsedTimeF32() < MAX_TEXTURE_WAIT_TIME_SEC) + || !mPendingAttachment.empty() + || (rez_status < 3 && !isFullyBaked()) + ); + } + updateRezzedStatusTimers(rez_status); updateRuthTimer(loading); return processFullyLoadedChange(loading); } @@ -7832,13 +7855,22 @@ void LLVOAvatar::updateRuthTimer(bool loading) BOOL LLVOAvatar::processFullyLoadedChange(bool loading) { - // we wait a little bit before giving the all clear, - // to let textures settle down - const F32 PAUSE = 1.f; + // We wait a little bit before giving the 'all clear', to let things to + // settle down (models to snap into place, textures to get first packets) + const F32 LOADED_DELAY = 1.f; + const F32 FIRST_USE_DELAY = 3.f; + if (loading) mFullyLoadedTimer.reset(); - - mFullyLoaded = (mFullyLoadedTimer.getElapsedTimeF32() > PAUSE); + + if (mFirstFullyVisible) + { + mFullyLoaded = (mFullyLoadedTimer.getElapsedTimeF32() > FIRST_USE_DELAY); + } + else + { + mFullyLoaded = (mFullyLoadedTimer.getElapsedTimeF32() > LOADED_DELAY); + } if (!mPreviousFullyLoaded && !loading && mFullyLoaded) { @@ -8128,6 +8160,7 @@ void LLVOAvatar::updateMeshTextures() LLViewerTexLayerSet* layerset = getTexLayerSet(i); if (use_lkg_baked_layer[i] && !isUsingLocalAppearance() ) { + // use last known good layer (no new one) LLViewerFetchedTexture* baked_img = LLViewerTextureManager::getFetchedTexture(mBakedTextureDatas[i].mLastTextureID); mBakedTextureDatas[i].mIsUsed = TRUE; @@ -8146,6 +8179,7 @@ void LLVOAvatar::updateMeshTextures() } else if (!isUsingLocalAppearance() && is_layer_baked[i]) { + // use new layer LLViewerFetchedTexture* baked_img = LLViewerTextureManager::staticCastToFetchedTexture( getImage( mBakedTextureDatas[i].mTextureIndex, 0 ), TRUE) ; @@ -8165,10 +8199,15 @@ void LLVOAvatar::updateMeshTextures() ((i == BAKED_HEAD) || (i == BAKED_UPPER) || (i == BAKED_LOWER)) ) { baked_img->setLoadedCallback(onBakedTextureMasksLoaded, MORPH_MASK_REQUESTED_DISCARD, TRUE, TRUE, new LLTextureMaskData( mID ), - src_callback_list, paused); + src_callback_list, paused); } baked_img->setLoadedCallback(onBakedTextureLoaded, SWITCH_TO_BAKED_DISCARD, FALSE, FALSE, new LLUUID( mID ), src_callback_list, paused ); + if (baked_img->getDiscardLevel() < 0 && !paused) + { + // mLoadedCallbackTextures will be updated by checkTextureLoading() below + mLastTexCallbackAddedTime.reset(); + } // this could add paused texture callbacks mLoadedCallbacksPaused |= paused; @@ -8562,13 +8601,16 @@ void LLVOAvatar::onFirstTEMessageReceived() LL_DEBUGS("Avatar") << avString() << "layer_baked, setting onInitialBakedTextureLoaded as callback" << LL_ENDL; image->setLoadedCallback( onInitialBakedTextureLoaded, MAX_DISCARD_LEVEL, FALSE, FALSE, new LLUUID( mID ), src_callback_list, paused ); - + if (image->getDiscardLevel() < 0 && !paused) + { + mLastTexCallbackAddedTime.reset(); + } // this could add paused texture callbacks mLoadedCallbacksPaused |= paused; } } - mMeshTexturesDirty = TRUE; + mMeshTexturesDirty = TRUE; gPipeline.markGLRebuild(this); } } @@ -9215,8 +9257,6 @@ void LLVOAvatar::onBakedTextureMasksLoaded( BOOL success, LLViewerFetchedTexture // static void LLVOAvatar::onInitialBakedTextureLoaded( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata ) { - - LLUUID *avatar_idp = (LLUUID *)userdata; LLVOAvatar *selfp = (LLVOAvatar *)gObjectList.findObject(*avatar_idp); @@ -10335,7 +10375,7 @@ void LLVOAvatar::calculateUpdateRenderComplexity() // Diagnostic list of all textures on our avatar static std::set<LLUUID> all_textures; - if (mVisualComplexityStale) + if (mVisualComplexityStale) { U32 cost = VISUAL_COMPLEXITY_UNKNOWN; LLVOVolume::texture_cost_t textures; |