diff options
Diffstat (limited to 'indra/newview/llavatarrendernotifier.cpp')
-rw-r--r-- | indra/newview/llavatarrendernotifier.cpp | 223 |
1 files changed, 223 insertions, 0 deletions
diff --git a/indra/newview/llavatarrendernotifier.cpp b/indra/newview/llavatarrendernotifier.cpp index 24934fdb73..94584a623b 100644 --- a/indra/newview/llavatarrendernotifier.cpp +++ b/indra/newview/llavatarrendernotifier.cpp @@ -38,6 +38,7 @@ #include "llnotifications.h" #include "llnotificationsutil.h" #include "llnotificationtemplate.h" +#include "llslurl.h" #include "lltimer.h" #include "llvoavatarself.h" #include "llviewercontrol.h" @@ -51,6 +52,11 @@ static const F32 RENDER_ALLOWED_CHANGE_PCT = 0.1; // wait seconds before processing over limit updates after last complexity change static const U32 OVER_LIMIT_UPDATE_DELAY = 70; +static const U32 WARN_HUD_OBJECTS_LIMIT = 1000; +static const U32 WARN_HUD_TEXTURES_LIMIT = 200; +static const U32 WARN_HUD_OVERSIZED_TEXTURES_LIMIT = 6; +static const U32 WARN_HUD_TEXTURE_MEMORY_LIMIT = 32000000; // in bytes + LLAvatarRenderNotifier::LLAvatarRenderNotifier() : mAgentsCount(0), @@ -264,3 +270,220 @@ void LLAvatarRenderNotifier::updateNotificationAgent(U32 agentComplexity) } } +// LLHUDRenderNotifier + +static const char* e_hud_messages[] = +{ + "hud_render_textures_warning", + "hud_render_cramped_warning", + "hud_render_heavy_textures_warning", + "hud_render_cost_warning", + "hud_render_memory_warning", +}; + +LLHUDRenderNotifier::LLHUDRenderNotifier() : +mReportedHUDWarning(WARN_NONE) +{ +} + +LLHUDRenderNotifier::~LLHUDRenderNotifier() +{ +} + +void LLHUDRenderNotifier::updateNotificationHUD(hud_complexity_list_t complexity) +{ + if (!isAgentAvatarValid() || !gAgentWearables.areWearablesLoaded()) + { + // data not ready. + return; + } + + // TODO: + // Find a way to show message with list of issues, but without making it too large + // and intrusive. + + LLHUDComplexity new_total_complexity; + LLHUDComplexity report_complexity; + + hud_complexity_list_t::iterator iter = complexity.begin(); + hud_complexity_list_t::iterator end = complexity.end(); + EWarnLevel warning_level = WARN_NONE; + for (; iter != end; ++iter) + { + LLHUDComplexity object_complexity = *iter; + EWarnLevel object_level = getWarningType(object_complexity, report_complexity); + if (object_level >= 0) + { + warning_level = object_level; + report_complexity = object_complexity; + } + new_total_complexity.objectsCost += object_complexity.objectsCost; + new_total_complexity.objectsCount += object_complexity.objectsCount; + new_total_complexity.texturesCost += object_complexity.texturesCost; + new_total_complexity.texturesCount += object_complexity.texturesCount; + new_total_complexity.largeTexturesCount += object_complexity.largeTexturesCount; + new_total_complexity.texturesMemoryTotal += object_complexity.texturesMemoryTotal; + } + + if (mHUDPopUpDelayTimer.hasExpired() || isNotificationVisible()) + { + if (warning_level >= 0) + { + // Display info about most complex HUD object + // make sure it shown only once unless object's complexity or object itself changed + if (mReportedHUDComplexity.objectId != report_complexity.objectId + || mReportedHUDWarning != warning_level) + { + displayHUDNotification(warning_level, report_complexity.objectId, report_complexity.objectName, report_complexity.jointName); + mReportedHUDComplexity = report_complexity; + mReportedHUDWarning = warning_level; + } + } + else + { + // Check if total complexity is above threshold and above previous warning + // Show warning with highest importance (5m delay between warnings by default) + if (!mReportedHUDComplexity.objectId.isNull()) + { + mReportedHUDComplexity.reset(); + mReportedHUDWarning = WARN_NONE; + } + + warning_level = getWarningType(new_total_complexity, mReportedHUDComplexity); + if (warning_level >= 0 && mReportedHUDWarning != warning_level) + { + displayHUDNotification(warning_level); + } + mReportedHUDComplexity = new_total_complexity; + mReportedHUDWarning = warning_level; + } + } + else if (warning_level >= 0) + { + LL_DEBUGS("HUDdetail") << "HUD individual warning postponed" << LL_ENDL; + } + + if (mLatestHUDComplexity.objectsCost != new_total_complexity.objectsCost + || mLatestHUDComplexity.objectsCount != new_total_complexity.objectsCount + || mLatestHUDComplexity.texturesCost != new_total_complexity.texturesCost + || mLatestHUDComplexity.texturesCount != new_total_complexity.texturesCount + || mLatestHUDComplexity.largeTexturesCount != new_total_complexity.largeTexturesCount + || mLatestHUDComplexity.texturesMemoryTotal != new_total_complexity.texturesMemoryTotal) + { + LL_INFOS("HUDdetail") << "HUD textures count: " << new_total_complexity.texturesCount + << " HUD textures cost: " << new_total_complexity.texturesCost + << " Large textures: " << new_total_complexity.largeTexturesCount + << " HUD objects cost: " << new_total_complexity.objectsCost + << " HUD objects count: " << new_total_complexity.objectsCount << LL_ENDL; + + mLatestHUDComplexity = new_total_complexity; + } +} + +bool LLHUDRenderNotifier::isNotificationVisible() +{ + return mHUDNotificationPtr != NULL && mHUDNotificationPtr->isActive(); +} + +// private static +LLHUDRenderNotifier::EWarnLevel LLHUDRenderNotifier::getWarningType(LLHUDComplexity object_complexity, LLHUDComplexity cmp_complexity) +{ + static LLCachedControl<U32> max_render_cost(gSavedSettings, "RenderAvatarMaxComplexity", 0U); // ties max HUD cost to avatar cost + static LLCachedControl<U32> max_objects_count(gSavedSettings, "RenderHUDObjectsWarning", WARN_HUD_OBJECTS_LIMIT); + static LLCachedControl<U32> max_textures_count(gSavedSettings, "RenderHUDTexturesWarning", WARN_HUD_TEXTURES_LIMIT); + static LLCachedControl<U32> max_oversized_count(gSavedSettings, "RenderHUDOversizedTexturesWarning", WARN_HUD_OVERSIZED_TEXTURES_LIMIT); + static LLCachedControl<U32> max_texture_memory(gSavedSettings, "RenderHUDTexturesMemoryWarning", WARN_HUD_TEXTURE_MEMORY_LIMIT); + + if (cmp_complexity.texturesMemoryTotal < object_complexity.texturesMemoryTotal + && object_complexity.texturesMemoryTotal > (F64Bytes)max_texture_memory) + { + // Note: Memory might not be accurate since texture is still loading or discard level changes + + LL_DEBUGS("HUDdetail") << "HUD " << object_complexity.objectName << " memory usage over limit, " + << " was " << cmp_complexity.texturesMemoryTotal + << " is " << object_complexity.texturesMemoryTotal << LL_ENDL; + + return WARN_MEMORY; + } + else if ((cmp_complexity.objectsCost < object_complexity.objectsCost + || cmp_complexity.texturesCost < object_complexity.texturesCost) + && max_render_cost > 0 + && object_complexity.objectsCost + object_complexity.texturesCost > max_render_cost) + { + LL_DEBUGS("HUDdetail") << "HUD " << object_complexity.objectName << " complexity over limit," + << " HUD textures cost: " << object_complexity.texturesCost + << " HUD objects cost: " << object_complexity.objectsCost << LL_ENDL; + + return WARN_COST; + } + else if (cmp_complexity.largeTexturesCount < object_complexity.largeTexturesCount + && object_complexity.largeTexturesCount > max_oversized_count) + { + LL_DEBUGS("HUDdetail") << "HUD " << object_complexity.objectName << " contains to many large textures: " + << object_complexity.largeTexturesCount << LL_ENDL; + + return WARN_HEAVY; + } + else if (cmp_complexity.texturesCount < object_complexity.texturesCount + && object_complexity.texturesCount > max_textures_count) + { + LL_DEBUGS("HUDdetail") << "HUD " << object_complexity.objectName << " contains too many textures: " + << object_complexity.texturesCount << LL_ENDL; + + return WARN_CRAMPED; + } + else if (cmp_complexity.objectsCount < object_complexity.objectsCount + && object_complexity.objectsCount > max_objects_count) + { + LL_DEBUGS("HUDdetail") << "HUD " << object_complexity.objectName << " contains too many objects: " + << object_complexity.objectsCount << LL_ENDL; + + return WARN_TEXTURES; + } + return WARN_NONE; +} + +void LLHUDRenderNotifier::displayHUDNotification(EWarnLevel warn_type, LLUUID obj_id, std::string obj_name, std::string joint_name) +{ + static LLCachedControl<U32> pop_up_delay(gSavedSettings, "ComplexityChangesPopUpDelay", 300); + static LLCachedControl<U32> expire_delay(gSavedSettings, "ShowMyComplexityChanges", 20); + LLDate expire_date(LLDate::now().secondsSinceEpoch() + expire_delay); + + // Since we need working "ignoretext" there is no other way but to + // use single notification while constructing it from multiple pieces + LLSD reason_args; + if (obj_id.isNull()) + { + reason_args["HUD_DETAILS"] = LLTrans::getString("hud_description_total"); + } + else + { + if (obj_name.empty()) + { + LL_WARNS("HUDdetail") << "Object name not assigned" << LL_ENDL; + } + if (joint_name.empty()) + { + std::string verb = "select?name=" + LLURI::escape(obj_name); + reason_args["HUD_DETAILS"] = LLSLURL("inventory", obj_id, verb.c_str()).getSLURLString(); + } + else + { + LLSD object_args; + std::string verb = "select?name=" + LLURI::escape(obj_name); + object_args["OBJ_NAME"] = LLSLURL("inventory", obj_id, verb.c_str()).getSLURLString(); + object_args["JNT_NAME"] = LLTrans::getString(joint_name); + reason_args["HUD_DETAILS"] = LLTrans::getString("hud_name_with_joint", object_args); + } + } + + LLSD msg_args; + msg_args["HUD_REASON"] = LLTrans::getString(e_hud_messages[warn_type], reason_args); + + mHUDNotificationPtr = LLNotifications::instance().add(LLNotification::Params() + .name("HUDComplexityWarning") + .expiry(expire_date) + .substitutions(msg_args)); + mHUDPopUpDelayTimer.resetWithExpiry(pop_up_delay); +} + |