summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
Diffstat (limited to 'indra')
-rwxr-xr-x[-rw-r--r--]indra/llimage/llimagej2c.cpp2
-rwxr-xr-x[-rw-r--r--]indra/newview/llagent.cpp10
-rwxr-xr-x[-rw-r--r--]indra/newview/llagentwearables.cpp18
-rwxr-xr-x[-rw-r--r--]indra/newview/llagentwearables.h1
-rw-r--r--indra/newview/llappviewer.cpp3
-rw-r--r--indra/newview/llavatarpropertiesprocessor.cpp9
-rw-r--r--indra/newview/lldrawpool.h1
-rw-r--r--indra/newview/lldrawpoolalpha.cpp1
-rw-r--r--indra/newview/lldriverparam.cpp2
-rw-r--r--indra/newview/llinventorybridge.cpp2
-rwxr-xr-x[-rw-r--r--]indra/newview/llinventorymodel.cpp49
-rw-r--r--indra/newview/llmarketplacefunctions.cpp15
-rwxr-xr-xindra/newview/lltexturefetch.cpp9
-rwxr-xr-xindra/newview/llviewerassetstats.cpp26
-rwxr-xr-xindra/newview/llviewerassetstats.h9
-rwxr-xr-x[-rw-r--r--]indra/newview/llviewerstats.h2
-rw-r--r--indra/newview/llviewerwindow.cpp10
-rwxr-xr-xindra/newview/llvoavatar.cpp428
-rwxr-xr-xindra/newview/llvoavatar.h13
-rwxr-xr-xindra/newview/llvoavatarself.cpp102
-rwxr-xr-xindra/newview/llvoavatarself.h15
-rw-r--r--indra/newview/llvovolume.cpp10
-rw-r--r--indra/newview/llwearable.cpp2
-rw-r--r--indra/newview/skins/default/xui/en/floater_merchant_outbox.xml10
-rw-r--r--indra/newview/skins/default/xui/en/menu_viewer.xml7
-rw-r--r--indra/newview/skins/default/xui/en/sidepanel_inventory.xml2
-rw-r--r--indra/newview/skins/default/xui/en/strings.xml2
-rwxr-xr-xindra/newview/tests/llviewerassetstats_test.cpp44
28 files changed, 560 insertions, 244 deletions
diff --git a/indra/llimage/llimagej2c.cpp b/indra/llimage/llimagej2c.cpp
index a76734e550..a0e90b6b08 100644..100755
--- a/indra/llimage/llimagej2c.cpp
+++ b/indra/llimage/llimagej2c.cpp
@@ -287,7 +287,7 @@ S32 LLImageJ2C::calcDataSizeJ2C(S32 w, S32 h, S32 comp, S32 discard_level, F32 r
// Temporary: compute both new and old range and pick one according to the settings TextureNewByteRange
// *TODO: Take the old code out once we have enough tests done
S32 bytes;
- S32 new_bytes = sqrt((F32)(w*h))*(F32)(comp)*rate*1000.f/layer_factor;
+ S32 new_bytes = (S32) (sqrt((F32)(w*h))*(F32)(comp)*rate*1000.f/layer_factor);
S32 old_bytes = (S32)((F32)(w*h*comp)*rate);
bytes = (LLImage::useNewByteRange() && (new_bytes < old_bytes) ? new_bytes : old_bytes);
bytes = llmax(bytes, calcHeaderSizeJ2C());
diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index 8aba2e76a2..b1ece51439 100644..100755
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -3310,13 +3310,12 @@ void LLAgent::processAgentCachedTextureResponse(LLMessageSystem *mesgsys, void *
else
{
// no cache of this bake. request upload.
- gAgentAvatarp->requestLayerSetUpload(baked_index);
+ gAgentAvatarp->invalidateComposite(gAgentAvatarp->getLayerSet(baked_index),TRUE);
}
}
}
}
}
-
llinfos << "Received cached texture response for " << num_results << " textures." << llendl;
gAgentAvatarp->outputRezTiming("Fetched agent wearables textures from cache. Will now load them");
@@ -3783,6 +3782,13 @@ void LLAgent::sendAgentSetAppearance()
return;
}
+ if (!gAgentWearables.changeInProgress())
+ {
+ // Change is fully resolved, can close some open phases.
+ gAgentAvatarp->stopPhase("process_initial_wearables_update");
+ gAgentAvatarp->stopPhase("wear_inventory_category");
+ }
+
gAgentAvatarp->sendAppearanceChangeMetrics();
LL_DEBUGS("Avatar") << gAgentAvatarp->avString() << "TAT: Sent AgentSetAppearance: " << gAgentAvatarp->getBakedStatusForPrintout() << LL_ENDL;
//dumpAvatarTEs( "sendAgentSetAppearance()" );
diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp
index bd418ca2b3..5bfcace707 100644..100755
--- a/indra/newview/llagentwearables.cpp
+++ b/indra/newview/llagentwearables.cpp
@@ -952,7 +952,7 @@ void LLAgentWearables::processAgentInitialWearablesUpdate(LLMessageSystem* mesgs
if (isAgentAvatarValid())
{
- gAgentAvatarp->clearPhases(); // reset phase timers for outfit loading.
+ //gAgentAvatarp->clearPhases(); // reset phase timers for outfit loading.
gAgentAvatarp->startPhase("process_initial_wearables_update");
gAgentAvatarp->outputRezTiming("Received initial wearables update");
}
@@ -1447,7 +1447,16 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it
{
gAgentAvatarp->setCompositeUpdatesEnabled(TRUE);
gAgentAvatarp->updateVisualParams();
- gAgentAvatarp->invalidateAll();
+
+ // If we have not yet declouded, we may want to use
+ // baked texture UUIDs sent from the first objectUpdate message
+ // don't overwrite these. If we have already declouded, we've saved
+ // these ids as the last known good textures and can invalidate without
+ // re-clouding.
+ if (!gAgentAvatarp->getIsCloud())
+ {
+ gAgentAvatarp->invalidateAll();
+ }
}
// Start rendering & update the server
@@ -2081,6 +2090,11 @@ boost::signals2::connection LLAgentWearables::addLoadedCallback(loaded_callback_
return mLoadedSignal.connect(cb);
}
+bool LLAgentWearables::changeInProgress() const
+{
+ return mCOFChangeInProgress;
+}
+
void LLAgentWearables::notifyLoadingStarted()
{
mCOFChangeInProgress = true;
diff --git a/indra/newview/llagentwearables.h b/indra/newview/llagentwearables.h
index 01cae3ffd8..5932be21c6 100644..100755
--- a/indra/newview/llagentwearables.h
+++ b/indra/newview/llagentwearables.h
@@ -233,6 +233,7 @@ public:
typedef boost::signals2::signal<void()> loaded_signal_t;
boost::signals2::connection addLoadedCallback(loaded_callback_t cb);
+ bool changeInProgress() const;
void notifyLoadingStarted();
void notifyLoadingFinished();
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 23c7b47860..a627f3868b 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -1484,6 +1484,9 @@ void LLAppViewer::flushVFSIO()
bool LLAppViewer::cleanup()
{
+ //ditch LLVOAvatarSelf instance
+ gAgentAvatarp = NULL;
+
// workaround for DEV-35406 crash on shutdown
LLEventPumps::instance().reset();
diff --git a/indra/newview/llavatarpropertiesprocessor.cpp b/indra/newview/llavatarpropertiesprocessor.cpp
index b1cd83a1fb..706bc42ea0 100644
--- a/indra/newview/llavatarpropertiesprocessor.cpp
+++ b/indra/newview/llavatarpropertiesprocessor.cpp
@@ -33,6 +33,7 @@
#include "llagentpicksinfo.h"
#include "lldateutil.h"
#include "llviewergenericmessage.h"
+#include "llstartup.h"
// Linden library includes
#include "llavatarconstants.h" // AVATAR_TRANSACTED, etc.
@@ -113,6 +114,14 @@ void LLAvatarPropertiesProcessor::sendGenericRequest(const LLUUID& avatar_id, EA
void LLAvatarPropertiesProcessor::sendAvatarPropertiesRequest(const LLUUID& avatar_id)
{
+ // this is the startup state when send_complete_agent_movement() message is sent.
+ // Before this, the AvatarPropertiesRequest message
+ // won't work so don't bother trying
+ if (LLStartUp::getStartupState() <= STATE_AGENT_SEND)
+ {
+ return;
+ }
+
if (isPendingRequest(avatar_id, APT_PROPERTIES))
{
// waiting for a response, don't re-request
diff --git a/indra/newview/lldrawpool.h b/indra/newview/lldrawpool.h
index 5a2981e749..64774d06df 100644
--- a/indra/newview/lldrawpool.h
+++ b/indra/newview/lldrawpool.h
@@ -133,6 +133,7 @@ public:
PASS_ALPHA,
PASS_ALPHA_MASK,
PASS_FULLBRIGHT_ALPHA_MASK,
+ PASS_ALPHA_INVISIBLE,
NUM_RENDER_TYPES,
};
diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp
index ddb7d3ceeb..5b62dbc560 100644
--- a/indra/newview/lldrawpoolalpha.cpp
+++ b/indra/newview/lldrawpoolalpha.cpp
@@ -337,6 +337,7 @@ void LLDrawPoolAlpha::render(S32 pass)
pushBatches(LLRenderPass::PASS_ALPHA_MASK, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, FALSE);
pushBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, FALSE);
+ pushBatches(LLRenderPass::PASS_ALPHA_INVISIBLE, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, FALSE);
if(shaders)
{
diff --git a/indra/newview/lldriverparam.cpp b/indra/newview/lldriverparam.cpp
index 8f47d3c5e5..64eb11fc9b 100644
--- a/indra/newview/lldriverparam.cpp
+++ b/indra/newview/lldriverparam.cpp
@@ -139,7 +139,7 @@ void LLDriverParamInfo::toStream(std::ostream &out)
}
else
{
- llwarns << "could not get parameter " << driven.mDrivenID << " from avatar " << gAgentAvatarp << " for driver parameter " << getID() << llendl;
+ llwarns << "could not get parameter " << driven.mDrivenID << " from avatar " << gAgentAvatarp.get() << " for driver parameter " << getID() << llendl;
}
out << std::endl;
}
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index cebe93f042..c0065a94e6 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -73,7 +73,7 @@
#include "llwearablelist.h"
// Marketplace outbox current disabled
-#define ENABLE_MERCHANT_OUTBOX_CONTEXT_MENU 0
+#define ENABLE_MERCHANT_OUTBOX_CONTEXT_MENU 1
#define ENABLE_MERCHANT_SEND_TO_MARKETPLACE_CONTEXT_MENU 0
#define BLOCK_WORN_ITEMS_IN_OUTBOX 1
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index a71b699fdd..ba64447c1d 100644..100755
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -1664,6 +1664,7 @@ bool LLInventoryModel::loadSkeleton(
update_map_t child_counts;
cat_array_t categories;
item_array_t items;
+ item_array_t possible_broken_links;
cat_set_t invalid_categories; // Used to mark categories that weren't successfully loaded.
std::string owner_id_str;
owner_id.toString(owner_id_str);
@@ -1712,7 +1713,7 @@ bool LLInventoryModel::loadSkeleton(
LLViewerInventoryCategory* tcat = *cit;
// we can safely ignore anything loaded from file, but
- // not sent down in the skeleton.
+ // not sent down in the skeleton. Must have been removed from inventory.
if(cit == not_cached)
{
continue;
@@ -1750,6 +1751,8 @@ bool LLInventoryModel::loadSkeleton(
// Add all the items loaded which are parented to a
// category with a correctly cached parent
S32 bad_link_count = 0;
+ S32 good_link_count = 0;
+ S32 recovered_link_count = 0;
cat_map_t::iterator unparented = mCategoryMap.end();
for(item_array_t::const_iterator item_iter = items.begin();
item_iter != items.end();
@@ -1766,26 +1769,56 @@ bool LLInventoryModel::loadSkeleton(
// This can happen if the linked object's baseobj is removed from the cache but the linked object is still in the cache.
if (item->getIsBrokenLink())
{
- bad_link_count++;
+ //bad_link_count++;
lldebugs << "Attempted to add cached link item without baseobj present ( name: "
<< item->getName() << " itemID: " << item->getUUID()
<< " assetID: " << item->getAssetUUID()
<< " ). Ignoring and invalidating " << cat->getName() << " . " << llendl;
- invalid_categories.insert(cit->second);
+ possible_broken_links.push_back(item);
continue;
}
+ else if (item->getIsLinkType())
+ {
+ good_link_count++;
+ }
addItem(item);
cached_item_count += 1;
++child_counts[cat->getUUID()];
}
}
}
- if (bad_link_count > 0)
+ if (possible_broken_links.size() > 0)
{
- llinfos << "Attempted to add " << bad_link_count
- << " cached link items without baseobj present. "
- << "The corresponding categories were invalidated." << llendl;
+ for(item_array_t::const_iterator item_iter = possible_broken_links.begin();
+ item_iter != possible_broken_links.end();
+ ++item_iter)
+ {
+ LLViewerInventoryItem *item = (*item_iter).get();
+ const cat_map_t::iterator cit = mCategoryMap.find(item->getParentUUID());
+ const LLViewerInventoryCategory* cat = cit->second.get();
+ if (item->getIsBrokenLink())
+ {
+ bad_link_count++;
+ invalid_categories.insert(cit->second);
+ //llinfos << "link still broken: " << item->getName() << " in folder " << cat->getName() << llendl;
+ }
+ else
+ {
+ // was marked as broken because of loading order, its actually fine to load
+ addItem(item);
+ cached_item_count += 1;
+ ++child_counts[cat->getUUID()];
+ recovered_link_count++;
+ }
+ }
+
+ llinfos << "Attempted to add " << bad_link_count
+ << " cached link items without baseobj present. "
+ << good_link_count << " link items were successfully added. "
+ << recovered_link_count << " links added in recovery. "
+ << "The corresponding categories were invalidated." << llendl;
}
+
}
else
{
@@ -2683,7 +2716,7 @@ void LLInventoryModel::processBulkUpdateInventory(LLMessageSystem* msg, void**)
{
LLPointer<LLViewerInventoryItem> titem = new LLViewerInventoryItem;
titem->unpackMessage(msg, _PREHASH_ItemData, i);
- llinfos << "unpaked item '" << titem->getName() << "' in "
+ llinfos << "unpacked item '" << titem->getName() << "' in "
<< titem->getParentUUID() << llendl;
U32 callback_id;
msg->getU32Fast(_PREHASH_ItemData, _PREHASH_CallbackID, callback_id);
diff --git a/indra/newview/llmarketplacefunctions.cpp b/indra/newview/llmarketplacefunctions.cpp
index a3f0a6062c..93dd82957f 100644
--- a/indra/newview/llmarketplacefunctions.cpp
+++ b/indra/newview/llmarketplacefunctions.cpp
@@ -30,6 +30,7 @@
#include "llagent.h"
#include "llhttpclient.h"
+#include "lltimer.h"
#include "lltrans.h"
#include "llviewercontrol.h"
#include "llviewermedia.h"
@@ -115,6 +116,9 @@ namespace LLMarketplaceImport
static U32 sImportResultStatus = 0;
static LLSD sImportResults = LLSD::emptyMap();
+ static LLTimer slmGetTimer;
+ static LLTimer slmPostTimer;
+
// Responders
class LLImportPostResponder : public LLHTTPClient::Responder
@@ -124,11 +128,15 @@ namespace LLMarketplaceImport
void completed(U32 status, const std::string& reason, const LLSD& content)
{
+ slmPostTimer.stop();
+
if (gSavedSettings.getBOOL("InventoryOutboxLogging"))
{
llinfos << " SLM POST status: " << status << llendl;
llinfos << " SLM POST reason: " << reason << llendl;
llinfos << " SLM POST content: " << content.asString() << llendl;
+
+ llinfos << " SLM POST timer: " << slmPostTimer.getElapsedTimeF32() << llendl;
}
if ((status == MarketplaceErrorCodes::IMPORT_REDIRECT) ||
@@ -167,11 +175,15 @@ namespace LLMarketplaceImport
void completed(U32 status, const std::string& reason, const LLSD& content)
{
+ slmGetTimer.stop();
+
if (gSavedSettings.getBOOL("InventoryOutboxLogging"))
{
llinfos << " SLM GET status: " << status << llendl;
llinfos << " SLM GET reason: " << reason << llendl;
llinfos << " SLM GET content: " << content.asString() << llendl;
+
+ llinfos << " SLM GET timer: " << slmGetTimer.getElapsedTimeF32() << llendl;
}
if ((status == MarketplaceErrorCodes::IMPORT_AUTHENTICATION_ERROR) ||
@@ -247,6 +259,7 @@ namespace LLMarketplaceImport
llinfos << " SLM GET: " << url << llendl;
}
+ slmGetTimer.start();
LLHTTPClient::get(url, new LLImportGetResponder(), LLViewerMedia::getHeaders());
return true;
@@ -277,6 +290,7 @@ namespace LLMarketplaceImport
llinfos << " SLM GET: " << url << llendl;
}
+ slmGetTimer.start();
LLHTTPClient::get(url, new LLImportGetResponder(), headers);
return true;
@@ -310,6 +324,7 @@ namespace LLMarketplaceImport
llinfos << " SLM POST: " << url << llendl;
}
+ slmPostTimer.start();
LLHTTPClient::post(url, LLSD(), new LLImportPostResponder(), headers);
return true;
diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp
index 3d8424e274..2e1b409fa7 100755
--- a/indra/newview/lltexturefetch.cpp
+++ b/indra/newview/lltexturefetch.cpp
@@ -53,6 +53,7 @@
#include "llviewerassetstats.h"
#include "llworld.h"
#include "llsdutil.h"
+#include "llstartup.h"
LLStat LLTextureFetch::sCacheHitRate("texture_cache_hits", 128);
LLStat LLTextureFetch::sCacheReadLatency("texture_cache_read_latency", 128);
@@ -2249,7 +2250,13 @@ S32 LLTextureFetch::update(F32 max_time_ms)
if (!mDebugPause)
{
- sendRequestListToSimulators();
+ // this is the startup state when send_complete_agent_movement() message is sent.
+ // Before this, the RequestImages message sent by sendRequestListToSimulators
+ // won't work so don't bother trying
+ if (LLStartUp::getStartupState() > STATE_AGENT_SEND)
+ {
+ sendRequestListToSimulators();
+ }
}
if (!mThreaded)
diff --git a/indra/newview/llviewerassetstats.cpp b/indra/newview/llviewerassetstats.cpp
index 4928f93a51..f408d06f4c 100755
--- a/indra/newview/llviewerassetstats.cpp
+++ b/indra/newview/llviewerassetstats.cpp
@@ -160,7 +160,9 @@ LLViewerAssetStats::LLViewerAssetStats()
LLViewerAssetStats::LLViewerAssetStats(const LLViewerAssetStats & src)
: mRegionHandle(src.mRegionHandle),
- mResetTimestamp(src.mResetTimestamp)
+ mResetTimestamp(src.mResetTimestamp),
+ mPhaseStats(src.mPhaseStats),
+ mAvatarRezStates(src.mAvatarRezStates)
{
const PerRegionContainer::const_iterator it_end(src.mRegionStats.end());
for (PerRegionContainer::const_iterator it(src.mRegionStats.begin()); it_end != it; ++it)
@@ -261,7 +263,10 @@ LLViewerAssetStats::recordAvatarStats()
{
std::vector<S32> rez_counts;
LLVOAvatar::getNearbyRezzedStats(rez_counts);
- mCurRegionStats->mAvatarRezStates = rez_counts;
+ mAvatarRezStates = rez_counts;
+ mPhaseStats.clear();
+ mPhaseStats["cloud"] = LLVOAvatar::getPhaseStats("cloud");
+ mPhaseStats["cloud-or-gray"] = LLVOAvatar::getPhaseStats("cloud-or-gray");
}
LLSD
@@ -297,6 +302,7 @@ LLViewerAssetStats::asLLSD(bool compact_output)
// Avatar sub-tags
static const LLSD::String avatar_tag("avatar");
static const LLSD::String avatar_nearby_tag("nearby");
+ static const LLSD::String avatar_phase_stats_tag("phase_stats");
const duration_t now = LLViewerAssetStatsFF::get_timestamp();
mCurRegionStats->accumulateTime(now);
@@ -345,12 +351,6 @@ LLViewerAssetStats::asLLSD(bool compact_output)
slot[max_tag] = LLSD(F64(stats.mFPS.getMax()));
slot[mean_tag] = LLSD(F64(stats.mFPS.getMean()));
}
- reg_stat[avatar_tag][avatar_nearby_tag] = LLSD::emptyArray();
- for (S32 j = 0; j < stats.mAvatarRezStates.size(); ++j)
- {
- reg_stat[avatar_tag][avatar_nearby_tag].append(stats.mAvatarRezStates[j]);
- }
-
U32 grid_x(0), grid_y(0);
grid_from_region_handle(it->first, &grid_x, &grid_y);
reg_stat["grid_x"] = LLSD::Integer(grid_x);
@@ -362,6 +362,16 @@ LLViewerAssetStats::asLLSD(bool compact_output)
LLSD ret = LLSD::emptyMap();
ret["regions"] = regions;
ret["duration"] = LLSD::Real((now - mResetTimestamp) * 1.0e-6);
+ LLSD avatar_info;
+ avatar_info[avatar_nearby_tag] = LLSD::emptyArray();
+ for (S32 rez_stat=0; rez_stat < mAvatarRezStates.size(); ++rez_stat)
+ {
+ std::string rez_status_name = LLVOAvatar::rezStatusToString(rez_stat);
+ avatar_info[avatar_nearby_tag][rez_status_name] = mAvatarRezStates[rez_stat];
+ }
+ avatar_info[avatar_phase_stats_tag]["cloud"] = mPhaseStats["cloud"].getData();
+ avatar_info[avatar_phase_stats_tag]["cloud-or-gray"] = mPhaseStats["cloud-or-gray"].getData();
+ ret[avatar_tag] = avatar_info;
return ret;
}
diff --git a/indra/newview/llviewerassetstats.h b/indra/newview/llviewerassetstats.h
index 6cb0cc4060..4b278bc2a2 100755
--- a/indra/newview/llviewerassetstats.h
+++ b/indra/newview/llviewerassetstats.h
@@ -36,6 +36,7 @@
#include "llviewerassetstorage.h"
#include "llsimplestat.h"
#include "llsd.h"
+#include "llvoavatar.h"
/**
* @class LLViewerAssetStats
@@ -125,8 +126,7 @@ public:
mRegionHandle(src.mRegionHandle),
mTotalTime(src.mTotalTime),
mStartTimestamp(src.mStartTimestamp),
- mFPS(src.mFPS),
- mAvatarRezStates(src.mAvatarRezStates)
+ mFPS(src.mFPS)
{
for (int i = 0; i < LL_ARRAY_SIZE(mRequests); ++i)
{
@@ -149,7 +149,6 @@ public:
duration_t mTotalTime;
duration_t mStartTimestamp;
LLSimpleStatMMM<> mFPS;
- std::vector<S32> mAvatarRezStates;
struct prs_group
{
@@ -257,6 +256,10 @@ protected:
// Time of last reset
duration_t mResetTimestamp;
+
+ // Nearby avatar stats
+ std::vector<S32> mAvatarRezStates;
+ LLVOAvatar::phase_stats_t mPhaseStats;
};
diff --git a/indra/newview/llviewerstats.h b/indra/newview/llviewerstats.h
index f91a1241fe..718fabc75a 100644..100755
--- a/indra/newview/llviewerstats.h
+++ b/indra/newview/llviewerstats.h
@@ -244,7 +244,7 @@ public:
inline F32 getStdDev() const
{
const F32 mean = getMean();
- return (mCount == 0) ? 0.f : sqrt( mSumOfSquares/mCount - (mean * mean) );
+ return (mCount < 2) ? 0.f : sqrt(llmax(0.f,mSumOfSquares/mCount - (mean * mean)));
}
inline U32 getCount() const
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index 8a713ae22c..e0653fec30 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -2021,6 +2021,12 @@ void LLViewerWindow::shutdownGL()
gSky.cleanup();
stop_glerror();
+ llinfos << "Cleaning up pipeline" << llendl;
+ gPipeline.cleanup();
+ stop_glerror();
+
+ //MUST clean up pipeline before cleaning up wearables
+ llinfos << "Cleaning up wearables" << llendl;
LLWearableList::instance().cleanup() ;
gTextureList.shutdown();
@@ -2031,10 +2037,6 @@ void LLViewerWindow::shutdownGL()
LLWorldMapView::cleanupTextures();
- llinfos << "Cleaning up pipeline" << llendl;
- gPipeline.cleanup();
- stop_glerror();
-
LLViewerTextureManager::cleanup() ;
LLImageGL::cleanupClass() ;
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index ea771b6d68..46805ec0c6 100755
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -633,11 +633,11 @@ F32 LLVOAvatar::sLODFactor = 1.f;
F32 LLVOAvatar::sPhysicsLODFactor = 1.f;
BOOL LLVOAvatar::sUseImpostors = FALSE;
BOOL LLVOAvatar::sJointDebug = FALSE;
-
F32 LLVOAvatar::sUnbakedTime = 0.f;
F32 LLVOAvatar::sUnbakedUpdateTime = 0.f;
F32 LLVOAvatar::sGreyTime = 0.f;
F32 LLVOAvatar::sGreyUpdateTime = 0.f;
+LLVOAvatar::phase_stats_t LLVOAvatar::sPhaseStats;
//-----------------------------------------------------------------------------
// Helper functions
@@ -696,7 +696,9 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
mSupportsAlphaLayers(FALSE),
mLoadedCallbacksPaused(FALSE),
mHasPelvisOffset( FALSE ),
- mRenderUnloadedAvatar(LLCachedControl<bool>(gSavedSettings, "RenderUnloadedAvatar"))
+ mRenderUnloadedAvatar(LLCachedControl<bool>(gSavedSettings, "RenderUnloadedAvatar")),
+ mLastRezzedStatus(-1)
+
{
LLMemType mt(LLMemType::MTYPE_AVATAR);
//VTResume(); // VTune
@@ -779,13 +781,7 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
std::string LLVOAvatar::avString() const
{
- std::string viz_string;
- if (getIsCloud())
- viz_string = "cloud";
- else if (isFullyTextured())
- viz_string = "textured";
- else
- viz_string = "gray";
+ std::string viz_string = LLVOAvatar::rezStatusToString(getRezzedStatus());
return " Avatar '" + getFullname() + "' " + viz_string + " ";
}
@@ -799,12 +795,6 @@ void LLVOAvatar::debugAvatarRezTime(std::string notification_name, std::string c
<< " : " << comment
<< llendl;
- if (gAgentAvatarp && !gAgentAvatarp->isDead()) // not safe to call during ~LLVOAvatarself
- {
- LLSD metrics = gAgentAvatarp->metricsData();
- LL_DEBUGS("Avatar") << gAgentAvatarp->avString() << " metrics " << ll_pretty_print_sd(metrics) << LL_ENDL;
- }
-
if (gSavedSettings.getBOOL("DebugAvatarRezTime"))
{
LLSD args;
@@ -976,13 +966,27 @@ LLFrameTimer& LLVOAvatar::getPhaseTimer(const std::string& phase_name)
void LLVOAvatar::startPhase(const std::string& phase_name)
{
LLFrameTimer& timer = getPhaseTimer(phase_name);
+ lldebugs << "startPhase " << phase_name << llendl;
timer.unpause();
}
void LLVOAvatar::stopPhase(const std::string& phase_name)
{
- LLFrameTimer& timer = getPhaseTimer(phase_name);
- timer.pause();
+ phase_map_t::iterator iter = mPhases.find(phase_name);
+ if (iter != mPhases.end())
+ {
+ if (iter->second.getStarted())
+ {
+ // Going from started to paused state - record stats.
+ recordPhaseStat(phase_name,iter->second.getElapsedTimeF32());
+ }
+ lldebugs << "stopPhase " << phase_name << llendl;
+ iter->second.pause();
+ }
+ else
+ {
+ lldebugs << "stopPhase " << phase_name << " is not started, no-op" << llendl;
+ }
}
void LLVOAvatar::stopAllPhases()
@@ -990,13 +994,23 @@ void LLVOAvatar::stopAllPhases()
for (phase_map_t::iterator iter = mPhases.begin();
iter != mPhases.end(); ++iter)
{
+ const std::string& phase_name = iter->first;
+ if (iter->second.getStarted())
+ {
+ // Going from started to paused state - record stats.
+ recordPhaseStat(phase_name,iter->second.getElapsedTimeF32());
+ }
+ lldebugs << "stopPhase (all) " << phase_name << llendl;
iter->second.pause();
}
}
void LLVOAvatar::clearPhases()
{
+ lldebugs << "clearPhases" << llendl;
+
mPhases.clear();
+ mLastRezzedStatus = -1;
}
LLSD LLVOAvatar::dumpPhases()
@@ -1004,12 +1018,39 @@ LLSD LLVOAvatar::dumpPhases()
LLSD result;
for (phase_map_t::iterator iter = mPhases.begin(); iter != mPhases.end(); ++iter)
{
- result[iter->first]["completed"] = !(iter->second.getStarted());
- result[iter->first]["elapsed"] = iter->second.getElapsedTimeF32();
+ const std::string& phase_name = iter->first;
+ result[phase_name]["completed"] = !(iter->second.getStarted());
+ result[phase_name]["elapsed"] = iter->second.getElapsedTimeF32();
+#if 0 // global stats for each phase seem like overkill here
+ phase_stats_t::iterator stats_iter = sPhaseStats.find(phase_name);
+ if (stats_iter != sPhaseStats.end())
+ {
+ result[phase_name]["stats"] = stats_iter->second.getData();
+ }
+#endif
}
return result;
}
+// static
+LLViewerStats::StatsAccumulator& LLVOAvatar::getPhaseStats(const std::string& phase_name)
+{
+ phase_stats_t::iterator it = sPhaseStats.find(phase_name);
+ if (it == sPhaseStats.end())
+ {
+ LLViewerStats::StatsAccumulator new_stats;
+ sPhaseStats[phase_name] = new_stats;
+ }
+ return sPhaseStats[phase_name];
+}
+
+// static
+void LLVOAvatar::recordPhaseStat(const std::string& phase_name, F32 value)
+{
+ LLViewerStats::StatsAccumulator& stats = getPhaseStats(phase_name);
+ stats.push(value);
+}
+
void LLVOAvatar::deleteLayerSetCaches(bool clearAll)
{
for (U32 i = 0; i < mBakedTextureDatas.size(); i++)
@@ -1073,6 +1114,15 @@ void LLVOAvatar::getNearbyRezzedStats(std::vector<S32>& counts)
}
// static
+std::string LLVOAvatar::rezStatusToString(S32 rez_status)
+{
+ if (rez_status==0) return "cloud";
+ if (rez_status==1) return "gray";
+ if (rez_status==2) return "textured";
+ return "unknown";
+}
+
+// static
void LLVOAvatar::dumpBakedStatus()
{
LLVector3d camera_pos_global = gAgentCamera.getCameraPositionGlobal();
@@ -3061,43 +3111,43 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
return;
}
- BOOL new_name = FALSE;
- if (visible_chat != mVisibleChat)
+ BOOL new_name = FALSE;
+ if (visible_chat != mVisibleChat)
+ {
+ mVisibleChat = visible_chat;
+ new_name = TRUE;
+ }
+
+ if (sRenderGroupTitles != mRenderGroupTitles)
+ {
+ mRenderGroupTitles = sRenderGroupTitles;
+ new_name = TRUE;
+ }
+
+ // First Calculate Alpha
+ // If alpha > 0, create mNameText if necessary, otherwise delete it
+ F32 alpha = 0.f;
+ if (mAppAngle > 5.f)
+ {
+ const F32 START_FADE_TIME = NAME_SHOW_TIME - FADE_DURATION;
+ if (!visible_chat && sRenderName == RENDER_NAME_FADE && time_visible > START_FADE_TIME)
{
- mVisibleChat = visible_chat;
- new_name = TRUE;
+ alpha = 1.f - (time_visible - START_FADE_TIME) / FADE_DURATION;
}
-
- if (sRenderGroupTitles != mRenderGroupTitles)
+ else
{
- mRenderGroupTitles = sRenderGroupTitles;
- new_name = TRUE;
+ // ...not fading, full alpha
+ alpha = 1.f;
}
-
- // First Calculate Alpha
- // If alpha > 0, create mNameText if necessary, otherwise delete it
- F32 alpha = 0.f;
- if (mAppAngle > 5.f)
- {
- const F32 START_FADE_TIME = NAME_SHOW_TIME - FADE_DURATION;
- if (!visible_chat && sRenderName == RENDER_NAME_FADE && time_visible > START_FADE_TIME)
- {
- alpha = 1.f - (time_visible - START_FADE_TIME) / FADE_DURATION;
- }
- else
- {
- // ...not fading, full alpha
- alpha = 1.f;
- }
- }
- else if (mAppAngle > 2.f)
- {
- // far away is faded out also
- alpha = (mAppAngle-2.f)/3.f;
- }
+ }
+ else if (mAppAngle > 2.f)
+ {
+ // far away is faded out also
+ alpha = (mAppAngle-2.f)/3.f;
+ }
if (alpha <= 0.f)
- {
+ {
if (mNameText)
{
mNameText->markDead();
@@ -3107,19 +3157,19 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
return;
}
- if (!mNameText)
- {
+ if (!mNameText)
+ {
mNameText = static_cast<LLHUDNameTag*>( LLHUDObject::addHUDObject(
- LLHUDObject::LL_HUD_NAME_TAG) );
+ LLHUDObject::LL_HUD_NAME_TAG) );
//mNameText->setMass(10.f);
- mNameText->setSourceObject(this);
+ mNameText->setSourceObject(this);
mNameText->setVertAlignment(LLHUDNameTag::ALIGN_VERT_TOP);
- mNameText->setVisibleOffScreen(TRUE);
- mNameText->setMaxLines(11);
- mNameText->setFadeDistance(CHAT_NORMAL_RADIUS, 5.f);
- sNumVisibleChatBubbles++;
- new_name = TRUE;
- }
+ mNameText->setVisibleOffScreen(TRUE);
+ mNameText->setMaxLines(11);
+ mNameText->setFadeDistance(CHAT_NORMAL_RADIUS, 5.f);
+ sNumVisibleChatBubbles++;
+ new_name = TRUE;
+ }
LLVector3 name_position = idleUpdateNameTagPosition(root_pos_last);
mNameText->setPositionAgent(name_position);
@@ -3171,56 +3221,56 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name)
|| is_away != mNameAway
|| is_busy != mNameBusy
|| is_muted != mNameMute
- || is_appearance != mNameAppearance
+ || is_appearance != mNameAppearance
|| is_friend != mNameFriend
|| is_cloud != mNameCloud)
- {
+ {
LLColor4 name_tag_color = getNameTagColor(is_friend);
clearNameTag();
if (is_away || is_muted || is_busy || is_appearance)
- {
+ {
std::string line;
- if (is_away)
- {
- line += LLTrans::getString("AvatarAway");
+ if (is_away)
+ {
+ line += LLTrans::getString("AvatarAway");
line += ", ";
- }
- if (is_busy)
- {
+ }
+ if (is_busy)
+ {
line += LLTrans::getString("AvatarBusy");
line += ", ";
}
if (is_muted)
- {
+ {
line += LLTrans::getString("AvatarMuted");
- line += ", ";
- }
+ line += ", ";
+ }
if (is_appearance)
{
line += LLTrans::getString("AvatarEditingAppearance");
line += ", ";
- }
+ }
if (is_cloud)
- {
+ {
line += LLTrans::getString("LoadingData");
line += ", ";
}
// trim last ", "
line.resize( line.length() - 2 );
addNameTagLine(line, name_tag_color, LLFontGL::NORMAL,
- LLFontGL::getFontSansSerifSmall());
+ LLFontGL::getFontSansSerifSmall());
}
if (sRenderGroupTitles
&& title && title->getString() && title->getString()[0] != '\0')
- {
+ {
std::string title_str = title->getString();
LLStringFn::replace_ascii_controlchars(title_str,LL_UNKNOWN_CHAR);
addNameTagLine(title_str, name_tag_color, LLFontGL::NORMAL,
- LLFontGL::getFontSansSerifSmall());
- }
+ LLFontGL::getFontSansSerifSmall());
+ }
static LLUICachedControl<bool> show_display_names("NameTagShowDisplayNames");
static LLUICachedControl<bool> show_usernames("NameTagShowUsernames");
@@ -3233,120 +3283,120 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name)
// ...call this function back when the name arrives
// and force a rebuild
LLAvatarNameCache::get(getID(),
- boost::bind(&LLVOAvatar::clearNameTag, this));
- }
+ boost::bind(&LLVOAvatar::clearNameTag, this));
+ }
// Might be blank if name not available yet, that's OK
if (show_display_names)
{
addNameTagLine(av_name.mDisplayName, name_tag_color, LLFontGL::NORMAL,
- LLFontGL::getFontSansSerif());
- }
+ LLFontGL::getFontSansSerif());
+ }
// Suppress SLID display if display name matches exactly (ugh)
if (show_usernames && !av_name.mIsDisplayNameDefault)
- {
+ {
// *HACK: Desaturate the color
LLColor4 username_color = name_tag_color * 0.83f;
addNameTagLine(av_name.mUsername, username_color, LLFontGL::NORMAL,
- LLFontGL::getFontSansSerifSmall());
+ LLFontGL::getFontSansSerifSmall());
}
- }
+ }
else
- {
+ {
const LLFontGL* font = LLFontGL::getFontSansSerif();
std::string full_name =
LLCacheName::buildFullName( firstname->getString(), lastname->getString() );
addNameTagLine(full_name, name_tag_color, LLFontGL::NORMAL, font);
- }
+ }
- mNameAway = is_away;
- mNameBusy = is_busy;
- mNameMute = is_muted;
- mNameAppearance = is_appearance;
+ mNameAway = is_away;
+ mNameBusy = is_busy;
+ mNameMute = is_muted;
+ mNameAppearance = is_appearance;
mNameFriend = is_friend;
- mNameCloud = is_cloud;
- mTitle = title ? title->getString() : "";
- LLStringFn::replace_ascii_controlchars(mTitle,LL_UNKNOWN_CHAR);
- new_name = TRUE;
- }
+ mNameCloud = is_cloud;
+ mTitle = title ? title->getString() : "";
+ LLStringFn::replace_ascii_controlchars(mTitle,LL_UNKNOWN_CHAR);
+ new_name = TRUE;
+ }
if (mVisibleChat)
- {
- mNameText->setFont(LLFontGL::getFontSansSerif());
+ {
+ mNameText->setFont(LLFontGL::getFontSansSerif());
mNameText->setTextAlignment(LLHUDNameTag::ALIGN_TEXT_LEFT);
- mNameText->setFadeDistance(CHAT_NORMAL_RADIUS * 2.f, 5.f);
+ mNameText->setFadeDistance(CHAT_NORMAL_RADIUS * 2.f, 5.f);
- char line[MAX_STRING]; /* Flawfinder: ignore */
- line[0] = '\0';
- std::deque<LLChat>::iterator chat_iter = mChats.begin();
- mNameText->clearString();
-
- LLColor4 new_chat = LLUIColorTable::instance().getColor( isSelf() ? "UserChatColor" : "AgentChatColor" );
- LLColor4 normal_chat = lerp(new_chat, LLColor4(0.8f, 0.8f, 0.8f, 1.f), 0.7f);
- LLColor4 old_chat = lerp(normal_chat, LLColor4(0.6f, 0.6f, 0.6f, 1.f), 0.7f);
- if (mTyping && mChats.size() >= MAX_BUBBLE_CHAT_UTTERANCES)
- {
- ++chat_iter;
- }
-
- for(; chat_iter != mChats.end(); ++chat_iter)
- {
- F32 chat_fade_amt = llclamp((F32)((LLFrameTimer::getElapsedSeconds() - chat_iter->mTime) / CHAT_FADE_TIME), 0.f, 4.f);
- LLFontGL::StyleFlags style;
- switch(chat_iter->mChatType)
- {
- case CHAT_TYPE_WHISPER:
- style = LLFontGL::ITALIC;
- break;
- case CHAT_TYPE_SHOUT:
- style = LLFontGL::BOLD;
- break;
- default:
- style = LLFontGL::NORMAL;
- break;
- }
- if (chat_fade_amt < 1.f)
- {
- F32 u = clamp_rescale(chat_fade_amt, 0.9f, 1.f, 0.f, 1.f);
- mNameText->addLine(chat_iter->mText, lerp(new_chat, normal_chat, u), style);
- }
- else if (chat_fade_amt < 2.f)
- {
- F32 u = clamp_rescale(chat_fade_amt, 1.9f, 2.f, 0.f, 1.f);
- mNameText->addLine(chat_iter->mText, lerp(normal_chat, old_chat, u), style);
- }
- else if (chat_fade_amt < 3.f)
- {
- // *NOTE: only remove lines down to minimum number
- mNameText->addLine(chat_iter->mText, old_chat, style);
- }
- }
- mNameText->setVisibleOffScreen(TRUE);
+ char line[MAX_STRING]; /* Flawfinder: ignore */
+ line[0] = '\0';
+ std::deque<LLChat>::iterator chat_iter = mChats.begin();
+ mNameText->clearString();
- if (mTyping)
- {
- S32 dot_count = (llfloor(mTypingTimer.getElapsedTimeF32() * 3.f) + 2) % 3 + 1;
- switch(dot_count)
- {
- case 1:
- mNameText->addLine(".", new_chat);
- break;
- case 2:
- mNameText->addLine("..", new_chat);
- break;
- case 3:
- mNameText->addLine("...", new_chat);
- break;
- }
+ LLColor4 new_chat = LLUIColorTable::instance().getColor( isSelf() ? "UserChatColor" : "AgentChatColor" );
+ LLColor4 normal_chat = lerp(new_chat, LLColor4(0.8f, 0.8f, 0.8f, 1.f), 0.7f);
+ LLColor4 old_chat = lerp(normal_chat, LLColor4(0.6f, 0.6f, 0.6f, 1.f), 0.7f);
+ if (mTyping && mChats.size() >= MAX_BUBBLE_CHAT_UTTERANCES)
+ {
+ ++chat_iter;
+ }
- }
+ for(; chat_iter != mChats.end(); ++chat_iter)
+ {
+ F32 chat_fade_amt = llclamp((F32)((LLFrameTimer::getElapsedSeconds() - chat_iter->mTime) / CHAT_FADE_TIME), 0.f, 4.f);
+ LLFontGL::StyleFlags style;
+ switch(chat_iter->mChatType)
+ {
+ case CHAT_TYPE_WHISPER:
+ style = LLFontGL::ITALIC;
+ break;
+ case CHAT_TYPE_SHOUT:
+ style = LLFontGL::BOLD;
+ break;
+ default:
+ style = LLFontGL::NORMAL;
+ break;
}
- else
+ if (chat_fade_amt < 1.f)
+ {
+ F32 u = clamp_rescale(chat_fade_amt, 0.9f, 1.f, 0.f, 1.f);
+ mNameText->addLine(chat_iter->mText, lerp(new_chat, normal_chat, u), style);
+ }
+ else if (chat_fade_amt < 2.f)
+ {
+ F32 u = clamp_rescale(chat_fade_amt, 1.9f, 2.f, 0.f, 1.f);
+ mNameText->addLine(chat_iter->mText, lerp(normal_chat, old_chat, u), style);
+ }
+ else if (chat_fade_amt < 3.f)
+ {
+ // *NOTE: only remove lines down to minimum number
+ mNameText->addLine(chat_iter->mText, old_chat, style);
+ }
+ }
+ mNameText->setVisibleOffScreen(TRUE);
+
+ if (mTyping)
+ {
+ S32 dot_count = (llfloor(mTypingTimer.getElapsedTimeF32() * 3.f) + 2) % 3 + 1;
+ switch(dot_count)
{
+ case 1:
+ mNameText->addLine(".", new_chat);
+ break;
+ case 2:
+ mNameText->addLine("..", new_chat);
+ break;
+ case 3:
+ mNameText->addLine("...", new_chat);
+ break;
+ }
+
+ }
+ }
+ else
+ {
// ...not using chat bubbles, just names
mNameText->setTextAlignment(LLHUDNameTag::ALIGN_TEXT_CENTER);
- mNameText->setFadeDistance(CHAT_NORMAL_RADIUS, 5.f);
- mNameText->setVisibleOffScreen(FALSE);
+ mNameText->setFadeDistance(CHAT_NORMAL_RADIUS, 5.f);
+ mNameText->setVisibleOffScreen(FALSE);
}
}
@@ -6538,11 +6588,53 @@ BOOL LLVOAvatar::getIsCloud() const
return FALSE;
}
+void LLVOAvatar::updateRezzedStatusTimers()
+{
+ // State machine for rezzed status. Statuses are 0 = cloud, 1 = gray, 2 = textured.
+ // Purpose is to collect time data for each period of cloud or cloud+gray.
+ S32 rez_status = getRezzedStatus();
+ if (rez_status != mLastRezzedStatus)
+ {
+ llinfos << avString() << "rez state change: " << mLastRezzedStatus << " -> " << rez_status << llendl;
+ bool is_cloud_or_gray = (rez_status==0 || rez_status==1);
+ bool was_cloud_or_gray = (mLastRezzedStatus==0 || mLastRezzedStatus==1);
+ bool is_cloud = (rez_status==0);
+ bool was_cloud = (mLastRezzedStatus==0);
+
+ // Non-cloud to cloud
+ if (is_cloud && !was_cloud)
+ {
+ // start cloud timer.
+ startPhase("cloud");
+ }
+ else if (was_cloud && !is_cloud)
+ {
+ // stop cloud timer, which will capture stats.
+ stopPhase("cloud");
+ }
+
+ // Non-cloud-or-gray to cloud-or-gray
+ if (is_cloud_or_gray && !was_cloud_or_gray)
+ {
+ // start cloud-or-gray timer.
+ startPhase("cloud-or-gray");
+ }
+ else if (was_cloud_or_gray && !is_cloud_or_gray)
+ {
+ // stop cloud-or-gray timer, which will capture stats.
+ stopPhase("cloud-or-gray");
+ }
+
+ mLastRezzedStatus = rez_status;
+ }
+}
+
// call periodically to keep isFullyLoaded up to date.
// returns true if the value has changed.
BOOL LLVOAvatar::updateIsFullyLoaded()
{
const BOOL loading = getIsCloud();
+ updateRezzedStatusTimers();
updateRuthTimer(loading);
return processFullyLoadedChange(loading);
}
@@ -8604,13 +8696,7 @@ void LLVOAvatar::idleUpdateRenderCost()
}
- std::string viz_string;
- if (getIsCloud())
- viz_string = "cloud";
- else if (isFullyTextured())
- viz_string = "textured";
- else
- viz_string = "gray";
+ std::string viz_string = LLVOAvatar::rezStatusToString(getRezzedStatus());
setDebugText(llformat("%s %d", viz_string.c_str(), cost));
mVisualComplexity = cost;
F32 green = 1.f-llclamp(((F32) cost-(F32)ARC_LIMIT)/(F32)ARC_LIMIT, 0.f, 1.f);
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index 76261c0dc8..8b72682040 100755
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -48,6 +48,7 @@
#include "lltexglobalcolor.h"
#include "lldriverparam.h"
#include "material_codes.h" // LL_MCODE_END
+#include "llviewerstats.h"
extern const LLUUID ANIM_AGENT_BODY_NOISE;
extern const LLUUID ANIM_AGENT_BREATHE_ROT;
@@ -282,6 +283,9 @@ public:
BOOL isFullyTextured() const;
BOOL hasGray() const;
S32 getRezzedStatus() const; // 0 = cloud, 1 = gray, 2 = fully textured.
+ void updateRezzedStatusTimers();
+
+ S32 mLastRezzedStatus;
// Tracking progress of active/completed phases for activities like outfit changing.
LLFrameTimer& getPhaseTimer(const std::string& phase_name);
@@ -290,6 +294,8 @@ public:
void stopAllPhases();
void clearPhases();
LLSD dumpPhases();
+ static LLViewerStats::StatsAccumulator& getPhaseStats(const std::string& phase_name);
+ static void recordPhaseStat(const std::string& phase_name, F32 value);
class ScopedPhaseSetter
{
@@ -323,8 +329,14 @@ private:
LLFrameTimer mFullyLoadedTimer;
LLFrameTimer mRuthTimer;
+ // TODO move all the phase stuff to its down data structure.
+public:
+ typedef std::map<std::string,LLViewerStats::StatsAccumulator> phase_stats_t;
typedef std::map<std::string,LLFrameTimer> phase_map_t;
+
+private:
phase_map_t mPhases;
+ static phase_stats_t sPhaseStats;
protected:
LLFrameTimer mInvisibleTimer;
@@ -555,6 +567,7 @@ public:
BOOL isFullyBaked();
static BOOL areAllNearbyInstancesBaked(S32& grey_avatars);
static void getNearbyRezzedStats(std::vector<S32>& counts);
+ static std::string rezStatusToString(S32 status);
//--------------------------------------------------------------------
// Baked textures
diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp
index a39b1cf4bc..66cc107a87 100755
--- a/indra/newview/llvoavatarself.cpp
+++ b/indra/newview/llvoavatarself.cpp
@@ -67,10 +67,11 @@
#include <boost/lexical_cast.hpp>
-LLVOAvatarSelf *gAgentAvatarp = NULL;
+LLPointer<LLVOAvatarSelf> gAgentAvatarp = NULL;
+
BOOL isAgentAvatarValid()
{
- return (gAgentAvatarp &&
+ return (gAgentAvatarp.notNull() &&
(gAgentAvatarp->getRegion() != NULL) &&
(!gAgentAvatarp->isDead()));
}
@@ -163,7 +164,8 @@ LLVOAvatarSelf::LLVOAvatarSelf(const LLUUID& id,
LLVOAvatar(id, pcode, regionp),
mScreenp(NULL),
mLastRegionHandle(0),
- mRegionCrossingCount(0)
+ mRegionCrossingCount(0),
+ mInitialBakesLoaded(false)
{
gAgentWearables.setAvatarObject(this);
@@ -196,6 +198,7 @@ void LLVOAvatarSelf::initInstance()
{
mDebugBakedTextureTimes[i][0] = -1.0f;
mDebugBakedTextureTimes[i][1] = -1.0f;
+ mInitialBakeIDs[i] = LLUUID::null;
}
status &= buildMenus();
@@ -794,6 +797,41 @@ void LLVOAvatarSelf::stopMotionFromSource(const LLUUID& source_id)
}
}
+//virtual
+U32 LLVOAvatarSelf::processUpdateMessage(LLMessageSystem *mesgsys,
+ void **user_data,
+ U32 block_num,
+ const EObjectUpdateType update_type,
+ LLDataPacker *dp)
+{
+ U32 retval = LLVOAvatar::processUpdateMessage(mesgsys,user_data,block_num,update_type,dp);
+
+ if (mInitialBakesLoaded == false && retval == 0x0)
+ {
+ // call update textures to force the images to be created
+ updateMeshTextures();
+
+ // unpack the texture UUIDs to the texture slots
+ retval = unpackTEMessage(mesgsys, _PREHASH_ObjectData, block_num);
+
+ // need to trigger a few operations to get the avatar to use the new bakes
+ for (U32 i = 0; i < mBakedTextureDatas.size(); i++)
+ {
+ const LLVOAvatarDefines::ETextureIndex te = mBakedTextureDatas[i].mTextureIndex;
+ LLUUID texture_id = getTEImage(te)->getID();
+ setNewBakedTexture(te, texture_id);
+ mInitialBakeIDs[i] = texture_id;
+ }
+
+ onFirstTEMessageReceived();
+
+ mInitialBakesLoaded = true;
+ }
+
+ return retval;
+}
+
+
void LLVOAvatarSelf::setLocalTextureTE(U8 te, LLViewerTexture* image, U32 index)
{
if (te >= TEX_NUM_INDICES)
@@ -2093,14 +2131,16 @@ LLSD LLVOAvatarSelf::metricsData()
// runway - add region info
LLSD result;
result["id"] = getID();
- result["rez_status"] = getRezzedStatus();
+ result["rez_status"] = LLVOAvatar::rezStatusToString(getRezzedStatus());
result["is_self"] = isSelf();
std::vector<S32> rez_counts;
LLVOAvatar::getNearbyRezzedStats(rez_counts);
- result["nearby"] = LLSD::emptyArray();
- result["nearby"][0] = rez_counts[0];
- result["nearby"][1] = rez_counts[1];
- result["nearby"][2] = rez_counts[2];
+ result["nearby"] = LLSD::emptyMap();
+ for (S32 i=0; i<rez_counts.size(); ++i)
+ {
+ std::string rez_status_name = LLVOAvatar::rezStatusToString(i);
+ result["nearby"][rez_status_name] = rez_counts[i];
+ }
result["timers"]["debug_existence"] = mDebugExistenceTimer.getElapsedTimeF32();
result["timers"]["ruth_debug"] = mRuthDebugTimer.getElapsedTimeF32();
result["timers"]["ruth"] = mRuthTimer.getElapsedTimeF32();
@@ -2147,7 +2187,7 @@ void LLVOAvatarSelf::sendAppearanceChangeMetrics()
if (getRegion())
{
// runway - change here to activate.
- caps_url = "";//getRegion()->getCapability("ViewerMetrics");
+ caps_url = getRegion()->getCapability("ViewerMetrics");
}
if (!caps_url.empty())
{
@@ -2391,11 +2431,11 @@ void LLVOAvatarSelf::outputRezDiagnostics() const
}
const F32 final_time = mDebugSelfLoadTimer.getElapsedTimeF32();
- llinfos << "REZTIME: Myself rez stats:" << llendl;
- llinfos << "\t Time from avatar creation to load wearables: " << (S32)mDebugTimeWearablesLoaded << llendl;
- llinfos << "\t Time from avatar creation to de-cloud: " << (S32)mDebugTimeAvatarVisible << llendl;
- llinfos << "\t Time from avatar creation to de-cloud for others: " << (S32)final_time << llendl;
- llinfos << "\t Load time for each texture: " << llendl;
+ LL_DEBUGS("Avatar") << "REZTIME: Myself rez stats:" << llendl;
+ LL_DEBUGS("Avatar") << "\t Time from avatar creation to load wearables: " << (S32)mDebugTimeWearablesLoaded << llendl;
+ LL_DEBUGS("Avatar") << "\t Time from avatar creation to de-cloud: " << (S32)mDebugTimeAvatarVisible << llendl;
+ LL_DEBUGS("Avatar") << "\t Time from avatar creation to de-cloud for others: " << (S32)final_time << llendl;
+ LL_DEBUGS("Avatar") << "\t Load time for each texture: " << llendl;
for (U32 i = 0; i < LLVOAvatarDefines::TEX_NUM_INDICES; ++i)
{
std::stringstream out;
@@ -2419,12 +2459,12 @@ void LLVOAvatarSelf::outputRezDiagnostics() const
// Don't print out non-existent textures.
if (j != 0)
- llinfos << out.str() << llendl;
+ LL_DEBUGS("Avatar") << out.str() << llendl;
}
- llinfos << "\t Time points for each upload (start / finish)" << llendl;
+ LL_DEBUGS("Avatar") << "\t Time points for each upload (start / finish)" << llendl;
for (U32 i = 0; i < LLVOAvatarDefines::BAKED_NUM_INDICES; ++i)
{
- llinfos << "\t\t (" << i << ") \t" << (S32)mDebugBakedTextureTimes[i][0] << " / " << (S32)mDebugBakedTextureTimes[i][1] << llendl;
+ LL_DEBUGS("Avatar") << "\t\t (" << i << ") \t" << (S32)mDebugBakedTextureTimes[i][0] << " / " << (S32)mDebugBakedTextureTimes[i][1] << llendl;
}
for (LLVOAvatarDefines::LLVOAvatarDictionary::BakedTextures::const_iterator baked_iter = LLVOAvatarDefines::LLVOAvatarDictionary::getInstance()->getBakedTextures().begin();
@@ -2436,7 +2476,7 @@ void LLVOAvatarSelf::outputRezDiagnostics() const
if (!layerset) continue;
const LLTexLayerSetBuffer *layerset_buffer = layerset->getComposite();
if (!layerset_buffer) continue;
- llinfos << layerset_buffer->dumpTextureInfo() << llendl;
+ LL_DEBUGS("Avatar") << layerset_buffer->dumpTextureInfo() << llendl;
}
}
@@ -2469,6 +2509,18 @@ void LLVOAvatarSelf::setCachedBakedTexture( ETextureIndex te, const LLUUID& uuid
{
if ( mBakedTextureDatas[i].mTextureIndex == te && mBakedTextureDatas[i].mTexLayerSet)
{
+ if (mInitialBakeIDs[i] != LLUUID::null)
+ {
+ if (mInitialBakeIDs[i] == uuid)
+ {
+ llinfos << "baked texture correctly loaded at login! " << i << llendl;
+ }
+ else
+ {
+ llwarns << "baked texture does not match id loaded at login!" << i << llendl;
+ }
+ mInitialBakeIDs[i] = LLUUID::null;
+ }
mBakedTextureDatas[i].mTexLayerSet->cancelUpload();
}
}
@@ -2596,6 +2648,20 @@ LLTexLayerSet* LLVOAvatarSelf::getLayerSet(ETextureIndex index) const
return NULL;
}
+LLTexLayerSet* LLVOAvatarSelf::getLayerSet(EBakedTextureIndex baked_index) const
+{
+ /* switch(index)
+ case TEX_HEAD_BAKED:
+ case TEX_HEAD_BODYPAINT:
+ return mHeadLayerSet; */
+ if (baked_index >= 0 && baked_index < BAKED_NUM_INDICES)
+ {
+ return mBakedTextureDatas[baked_index].mTexLayerSet;
+ }
+ return NULL;
+}
+
+
// static
void LLVOAvatarSelf::onCustomizeStart()
{
diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h
index fc1b602764..543891ca63 100755
--- a/indra/newview/llvoavatarself.h
+++ b/indra/newview/llvoavatarself.h
@@ -93,15 +93,27 @@ public:
/*virtual*/ void updateVisualParams();
/*virtual*/ void idleUpdateAppearanceAnimation();
+ /*virtual*/ U32 processUpdateMessage(LLMessageSystem *mesgsys,
+ void **user_data,
+ U32 block_num,
+ const EObjectUpdateType update_type,
+ LLDataPacker *dp);
+
private:
// helper function. Passed in param is assumed to be in avatar's parameter list.
BOOL setParamWeight(LLViewerVisualParam *param, F32 weight, BOOL upload_bake = FALSE );
+
/** Initialization
** **
*******************************************************************************/
+private:
+ LLUUID mInitialBakeIDs[6];
+ bool mInitialBakesLoaded;
+
+
/********************************************************************************
** **
** STATE
@@ -229,6 +241,7 @@ public:
void requestLayerSetUpload(LLVOAvatarDefines::EBakedTextureIndex i);
void requestLayerSetUpdate(LLVOAvatarDefines::ETextureIndex i);
LLTexLayerSet* getLayerSet(LLVOAvatarDefines::ETextureIndex index) const;
+ LLTexLayerSet* getLayerSet(LLVOAvatarDefines::EBakedTextureIndex baked_index) const;
//--------------------------------------------------------------------
// Composites
@@ -385,7 +398,7 @@ private:
};
-extern LLVOAvatarSelf *gAgentAvatarp;
+extern LLPointer<LLVOAvatarSelf> gAgentAvatarp;
BOOL isAgentAvatarValid();
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 7492a06784..03d4c51aff 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -4433,10 +4433,10 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
else
{
if (te->getColor().mV[3] > 0.f)
- {
+ { //only treat as alpha in the pipeline if < 100% transparent
drawablep->setState(LLDrawable::HAS_ALPHA);
- alpha_faces.push_back(facep);
}
+ alpha_faces.push_back(facep);
}
}
else
@@ -4947,7 +4947,11 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::
if (is_alpha)
{
// can we safely treat this as an alpha mask?
- if (facep->canRenderAsMask())
+ if (facep->getFaceColor().mV[3] <= 0.f)
+ { //100% transparent, don't render unless we're highlighting transparent
+ registerFace(group, facep, LLRenderPass::PASS_ALPHA_INVISIBLE);
+ }
+ else if (facep->canRenderAsMask())
{
if (te->getFullbright() || LLPipeline::sNoAlpha)
{
diff --git a/indra/newview/llwearable.cpp b/indra/newview/llwearable.cpp
index d8aa0b7d5c..0f7f63061b 100644
--- a/indra/newview/llwearable.cpp
+++ b/indra/newview/llwearable.cpp
@@ -221,7 +221,7 @@ void LLWearable::createVisualParams()
param->resetDrivenParams();
if(!param->linkDrivenParams(boost::bind(wearable_function,(LLWearable*)this, _1), false))
{
- if( !param->linkDrivenParams(boost::bind(avatar_function,gAgentAvatarp,_1 ), true))
+ if( !param->linkDrivenParams(boost::bind(avatar_function,gAgentAvatarp.get(),_1 ), true))
{
llwarns << "could not link driven params for wearable " << getName() << " id: " << param->getID() << llendl;
continue;
diff --git a/indra/newview/skins/default/xui/en/floater_merchant_outbox.xml b/indra/newview/skins/default/xui/en/floater_merchant_outbox.xml
index 498a9b6ce0..6f387f4800 100644
--- a/indra/newview/skins/default/xui/en/floater_merchant_outbox.xml
+++ b/indra/newview/skins/default/xui/en/floater_merchant_outbox.xml
@@ -132,16 +132,16 @@
</panel>
<layout_stack name="import_progress_indicator" orientation="vertical" left="0" height="440" top="0" width="333" follows="all" visible="false">
<layout_panel />
- <layout_panel height="45" auto_resize="false">
- <layout_stack orientation="horizontal" left="0" height="45" top="0" width="333" follows="all">
+ <layout_panel height="24" auto_resize="false">
+ <layout_stack orientation="horizontal" left="0" height="24" top="0" width="333" follows="all">
<layout_panel width="0" />
- <layout_panel width="45" auto_resize="false">
+ <layout_panel width="24" auto_resize="false">
<loading_indicator
- height="45"
+ height="24"
layout="topleft"
left="0"
top="0"
- width="45" />
+ width="24" />
</layout_panel>
<layout_panel width="0" />
</layout_stack>
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index 54b4e59a54..8b0152b1a2 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -153,6 +153,13 @@
function="BuyCurrency" />
</menu_item_call>
<menu_item_call
+ label="Merchant Outbox..."
+ name="MerchantOutbox">
+ <menu_item_call.on_click
+ function="Floater.ToggleOrBringToFront"
+ parameter="outbox" />
+ </menu_item_call>
+ <menu_item_call
label="Account dashboard..."
name="Manage My Account">
<menu_item_call.on_click
diff --git a/indra/newview/skins/default/xui/en/sidepanel_inventory.xml b/indra/newview/skins/default/xui/en/sidepanel_inventory.xml
index fcba937bdb..29aa6d1039 100644
--- a/indra/newview/skins/default/xui/en/sidepanel_inventory.xml
+++ b/indra/newview/skins/default/xui/en/sidepanel_inventory.xml
@@ -112,7 +112,7 @@
bg_opaque_color="InventoryBackgroundColor"
background_visible="true"
background_opaque="true"
- tool_tip="Drag and drop items to your inventory to manage and use them"
+ tool_tip="Drag and drop items to your inventory to use them"
>
<text
name="inbox_inventory_placeholder"
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 3351ffe00f..4bc72be49b 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -2037,7 +2037,7 @@ Returns a string with the requested data about the region
<string name="PlacesNoMatchingItems">Didn't find what you're looking for? Try [secondlife:///app/search/places/[SEARCH_TERM] Search].</string>
<string name="FavoritesNoMatchingItems">Drag a landmark here to add it to your favorites.</string>
<string name="InventoryNoTexture">You do not have a copy of this texture in your inventory</string>
- <string name="InventoryInboxNoItems">Certain items you receive, such as premium gifts, will appear here. You may then drag them into your inventory.</string>
+ <string name="InventoryInboxNoItems">Your Marketplace purchases will appear here. You may then drag them into your inventory to use them.</string>
<string name="MarketplaceURL">https://marketplace.[MARKETPLACE_DOMAIN_NAME]/</string>
<string name="MarketplaceURL_CreateStore">http://community.secondlife.com/t5/English-Knowledge-Base/Selling-in-the-Marketplace/ta-p/700193#Section_.4</string>
<string name="MarketplaceURL_Dashboard">https://marketplace.[MARKETPLACE_DOMAIN_NAME]/merchants/store/dashboard</string>
diff --git a/indra/newview/tests/llviewerassetstats_test.cpp b/indra/newview/tests/llviewerassetstats_test.cpp
index 5e18f91b23..952f0f1a6e 100755
--- a/indra/newview/tests/llviewerassetstats_test.cpp
+++ b/indra/newview/tests/llviewerassetstats_test.cpp
@@ -45,6 +45,21 @@ void LLVOAvatar::getNearbyRezzedStats(std::vector<S32>& counts)
counts[2] = 1;
}
+LLViewerStats::StatsAccumulator& LLVOAvatar::getPhaseStats(const std::string& phase_name)
+{
+ static std::map<std::string,LLViewerStats::StatsAccumulator> stats_map;
+ return stats_map[phase_name];
+}
+
+// static
+std::string LLVOAvatar::rezStatusToString(S32 rez_status)
+{
+ if (rez_status==0) return "cloud";
+ if (rez_status==1) return "gray";
+ if (rez_status==2) return "textured";
+ return "unknown";
+}
+
static const char * all_keys[] =
{
"duration",
@@ -113,18 +128,25 @@ is_single_key_map(const LLSD & sd, const std::string & key)
{
return sd.isMap() && 1 == sd.size() && sd.has(key);
}
-#endif
static bool
is_double_key_map(const LLSD & sd, const std::string & key1, const std::string & key2)
{
return sd.isMap() && 2 == sd.size() && sd.has(key1) && sd.has(key2);
}
+#endif
+
+static bool
+is_triple_key_map(const LLSD & sd, const std::string & key1, const std::string & key2, const std::string& key3)
+{
+ return sd.isMap() && 3 == sd.size() && sd.has(key1) && sd.has(key2) && sd.has(key3);
+}
+
static bool
is_no_stats_map(const LLSD & sd)
{
- return is_double_key_map(sd, "duration", "regions");
+ return is_triple_key_map(sd, "duration", "regions", "avatar");
}
static bool
@@ -235,7 +257,7 @@ namespace tut
// Once the region is set, we will get a response even with no data collection
it->setRegion(region1_handle);
sd_full = it->asLLSD(false);
- ensure("Correct single-key LLSD map root", is_double_key_map(sd_full, "duration", "regions"));
+ ensure("Correct single-key LLSD map root", is_triple_key_map(sd_full, "duration", "regions", "avatar"));
ensure("Correct single-slot LLSD array regions", is_single_slot_array(sd_full["regions"], region1_handle));
LLSD sd = sd_full["regions"][0];
@@ -276,7 +298,7 @@ namespace tut
it->setRegion(region1_handle);
LLSD sd = it->asLLSD(false);
- ensure("Correct single-key LLSD map root", is_double_key_map(sd, "regions", "duration"));
+ ensure("Correct single-key LLSD map root", is_triple_key_map(sd, "regions", "duration", "avatar"));
ensure("Correct single-slot LLSD array regions", is_single_slot_array(sd["regions"], region1_handle));
sd = sd[0];
@@ -301,7 +323,7 @@ namespace tut
LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_BODYPART, false, false);
LLSD sd = gViewerAssetStatsMain->asLLSD(false);
- ensure("Correct single-key LLSD map root", is_double_key_map(sd, "regions", "duration"));
+ ensure("Correct single-key LLSD map root", is_triple_key_map(sd, "regions", "duration", "avatar"));
ensure("Correct single-slot LLSD array regions", is_single_slot_array(sd["regions"], region1_handle));
sd = sd["regions"][0];
@@ -341,7 +363,7 @@ namespace tut
LLSD sd = gViewerAssetStatsThread1->asLLSD(false);
ensure("Other collector is empty", is_no_stats_map(sd));
sd = gViewerAssetStatsMain->asLLSD(false);
- ensure("Correct single-key LLSD map root", is_double_key_map(sd, "regions", "duration"));
+ ensure("Correct single-key LLSD map root", is_triple_key_map(sd, "regions", "duration", "avatar"));
ensure("Correct single-slot LLSD array regions", is_single_slot_array(sd["regions"], region1_handle));
sd = sd["regions"][0];
@@ -391,7 +413,7 @@ namespace tut
// std::cout << sd << std::endl;
- ensure("Correct double-key LLSD map root", is_double_key_map(sd, "duration", "regions"));
+ ensure("Correct double-key LLSD map root", is_triple_key_map(sd, "duration", "regions", "avatar"));
ensure("Correct double-slot LLSD array regions", is_double_slot_array(sd["regions"], region1_handle, region2_handle));
LLSD sd1 = get_region(sd, region1_handle);
LLSD sd2 = get_region(sd, region2_handle);
@@ -414,7 +436,7 @@ namespace tut
// Reset leaves current region in place
gViewerAssetStatsMain->reset();
sd = gViewerAssetStatsMain->asLLSD(false);
- ensure("Correct single-key LLSD map root", is_double_key_map(sd, "regions", "duration"));
+ ensure("Correct single-key LLSD map root", is_triple_key_map(sd, "regions", "duration", "avatar"));
ensure("Correct single-slot LLSD array regions (p2)", is_single_slot_array(sd["regions"], region2_handle));
sd2 = sd["regions"][0];
@@ -463,7 +485,7 @@ namespace tut
LLSD sd = gViewerAssetStatsMain->asLLSD(false);
- ensure("Correct double-key LLSD map root", is_double_key_map(sd, "duration", "regions"));
+ ensure("Correct double-key LLSD map root", is_triple_key_map(sd, "duration", "regions", "avatar"));
ensure("Correct double-slot LLSD array regions", is_double_slot_array(sd["regions"], region1_handle, region2_handle));
LLSD sd1 = get_region(sd, region1_handle);
LLSD sd2 = get_region(sd, region2_handle);
@@ -486,7 +508,7 @@ namespace tut
// Reset leaves current region in place
gViewerAssetStatsMain->reset();
sd = gViewerAssetStatsMain->asLLSD(false);
- ensure("Correct single-key LLSD map root", is_double_key_map(sd, "duration", "regions"));
+ ensure("Correct single-key LLSD map root", is_triple_key_map(sd, "duration", "regions", "avatar"));
ensure("Correct single-slot LLSD array regions (p2)", is_single_slot_array(sd["regions"], region2_handle));
sd2 = get_region(sd, region2_handle);
ensure("Region2 is present in results", sd2.isMap());
@@ -532,7 +554,7 @@ namespace tut
LLSD sd = gViewerAssetStatsThread1->asLLSD(false);
ensure("Other collector is empty", is_no_stats_map(sd));
sd = gViewerAssetStatsMain->asLLSD(false);
- ensure("Correct single-key LLSD map root", is_double_key_map(sd, "regions", "duration"));
+ ensure("Correct single-key LLSD map root", is_triple_key_map(sd, "regions", "duration", "avatar"));
ensure("Correct single-slot LLSD array regions", is_single_slot_array(sd["regions"], region1_handle));
sd = get_region(sd, region1_handle);
ensure("Region1 is present in results", sd.isMap());