summaryrefslogtreecommitdiff
path: root/indra/newview/llviewerobjectlist.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llviewerobjectlist.cpp')
-rwxr-xr-xindra/newview/llviewerobjectlist.cpp306
1 files changed, 228 insertions, 78 deletions
diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp
index caacf26cb3..b215869a3e 100755
--- a/indra/newview/llviewerobjectlist.cpp
+++ b/indra/newview/llviewerobjectlist.cpp
@@ -47,6 +47,7 @@
#include "lltooltip.h"
#include "llworld.h"
#include "llstring.h"
+#include "llhudicon.h"
#include "llhudnametag.h"
#include "lldrawable.h"
#include "llflexibleobject.h"
@@ -76,6 +77,7 @@
#include "object_flags.h"
#include "llappviewer.h"
+#include "llvocache.h"
extern F32 gMinObjectDistance;
extern BOOL gAnimateTextures;
@@ -93,7 +95,7 @@ extern LLPipeline gPipeline;
U32 LLViewerObjectList::sSimulatorMachineIndex = 1; // Not zero deliberately, to speed up index check.
std::map<U64, U32> LLViewerObjectList::sIPAndPortToIndex;
std::map<U64, LLUUID> LLViewerObjectList::sIndexAndLocalIDToUUID;
-LLStat LLViewerObjectList::sCacheHitRate("object_cache_hits", 128);
+LLTrace::SampleStatHandle<> LLViewerObjectList::sCacheHitRate("object_cache_hits");
LLViewerObjectList::LLViewerObjectList()
{
@@ -106,7 +108,6 @@ LLViewerObjectList::LLViewerObjectList()
mNumNewObjects = 0;
mWasPaused = FALSE;
mNumDeadObjectUpdates = 0;
- mNumUnknownKills = 0;
mNumUnknownUpdates = 0;
}
@@ -228,9 +229,15 @@ void LLViewerObjectList::processUpdateCore(LLViewerObject* objectp,
U32 i,
const EObjectUpdateType update_type,
LLDataPacker* dpp,
- BOOL just_created)
+ bool just_created,
+ bool from_cache)
{
- LLMessageSystem* msg = gMessageSystem;
+ LLMessageSystem* msg = NULL;
+
+ if(!from_cache)
+ {
+ msg = gMessageSystem;
+ }
// ignore returned flags
objectp->processUpdateMessage(msg, user_data, i, update_type, dpp);
@@ -254,7 +261,18 @@ void LLViewerObjectList::processUpdateCore(LLViewerObject* objectp,
// RN: this must be called after we have a drawable
// (from gPipeline.addObject)
// so that the drawable parent is set properly
+ if(msg != NULL)
+ {
findOrphans(objectp, msg->getSenderIP(), msg->getSenderPort());
+ }
+ else
+ {
+ LLViewerRegion* regionp = objectp->getRegion();
+ if(regionp != NULL)
+ {
+ findOrphans(objectp, regionp->getHost().getAddress(), regionp->getHost().getPort());
+ }
+ }
// If we're just wandering around, don't create new objects selected.
if (just_created
@@ -277,10 +295,90 @@ void LLViewerObjectList::processUpdateCore(LLViewerObject* objectp,
static LLFastTimer::DeclareTimer FTM_PROCESS_OBJECTS("Process Objects");
+LLViewerObject* LLViewerObjectList::processObjectUpdateFromCache(LLVOCacheEntry* entry, LLViewerRegion* regionp)
+{
+ LLDataPacker *cached_dpp = entry->getDP();
+
+ if (!cached_dpp)
+ {
+ return NULL; //nothing cached.
+ }
+
+ LLViewerObject *objectp;
+ U32 local_id;
+ LLPCode pcode = 0;
+ LLUUID fullid;
+ LLViewerStatsRecorder& recorder = LLViewerStatsRecorder::instance();
+
+ // Cache Hit.
+ cached_dpp->reset();
+ cached_dpp->unpackUUID(fullid, "ID");
+ cached_dpp->unpackU32(local_id, "LocalID");
+ cached_dpp->unpackU8(pcode, "PCode");
+
+ objectp = findObject(fullid);
+
+ if (objectp)
+ {
+ if(!objectp->isDead() && (objectp->mLocalID != entry->getLocalID() ||
+ objectp->getRegion() != regionp))
+ {
+ removeFromLocalIDTable(objectp);
+ setUUIDAndLocal(fullid, entry->getLocalID(),
+ regionp->getHost().getAddress(),
+ regionp->getHost().getPort());
+
+ if (objectp->mLocalID != entry->getLocalID())
+ { // Update local ID in object with the one sent from the region
+ objectp->mLocalID = entry->getLocalID();
+ }
+
+ if (objectp->getRegion() != regionp)
+ { // Object changed region, so update it
+ objectp->updateRegion(regionp); // for LLVOAvatar
+ }
+ }
+ else
+ {
+ //should fall through if already loaded because may need to update the object.
+ //return objectp; //already loaded.
+ }
+ }
+
+ bool justCreated = false;
+ if (!objectp)
+ {
+ objectp = createObjectFromCache(pcode, regionp, fullid, entry->getLocalID());
+
+ if (!objectp)
+ {
+ llinfos << "createObject failure for object: " << fullid << llendl;
+ recorder.objectUpdateFailure(entry->getLocalID(), OUT_FULL_CACHED, 0);
+ return NULL;
+ }
+ justCreated = true;
+ mNumNewObjects++;
+ sample(sCacheHitRate, 100.f);
+ }
+
+ if (objectp->isDead())
+ {
+ llwarns << "Dead object " << objectp->mID << " in UUID map 1!" << llendl;
+ }
+
+ processUpdateCore(objectp, NULL, 0, OUT_FULL_CACHED, cached_dpp, justCreated, true);
+ objectp->loadFlags(entry->getUpdateFlags()); //just in case, reload update flags from cache.
+
+ recorder.log(0.2f);
+ LLVOAvatar::cullAvatarsByPixelArea();
+
+ return objectp;
+}
+
void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
void **user_data,
const EObjectUpdateType update_type,
- bool cached, bool compressed)
+ bool compressed)
{
LLFastTimer t(FTM_PROCESS_OBJECTS);
@@ -298,7 +396,7 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
num_objects = mesgsys->getNumberOfBlocksFast(_PREHASH_ObjectData);
// I don't think this case is ever hit. TODO* Test this.
- if (!cached && !compressed && update_type != OUT_FULL)
+ if (!compressed && update_type != OUT_FULL)
{
//llinfos << "TEST: !cached && !compressed && update_type != OUT_FULL" << llendl;
gTerseObjectUpdates += num_objects;
@@ -346,7 +444,6 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
U8 compressed_dpbuffer[2048];
LLDataPackerBinaryBuffer compressed_dp(compressed_dpbuffer, 2048);
- LLDataPacker *cached_dpp = NULL;
LLViewerStatsRecorder& recorder = LLViewerStatsRecorder::instance();
for (i = 0; i < num_objects; i++)
@@ -355,57 +452,37 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
LLTimer update_timer;
BOOL justCreated = FALSE;
S32 msg_size = 0;
+ bool remove_from_cache = false; //remove from object cache if it is a full-update or terse update
- if (cached)
- {
- U32 id;
- U32 crc;
- mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_ID, id, i);
- mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_CRC, crc, i);
- msg_size += sizeof(U32) * 2;
-
- // Lookup data packer and add this id to cache miss lists if necessary.
- U8 cache_miss_type = LLViewerRegion::CACHE_MISS_TYPE_NONE;
- cached_dpp = regionp->getDP(id, crc, cache_miss_type);
- if (cached_dpp)
- {
- // Cache Hit.
- cached_dpp->reset();
- cached_dpp->unpackUUID(fullid, "ID");
- cached_dpp->unpackU32(local_id, "LocalID");
- cached_dpp->unpackU8(pcode, "PCode");
- }
- else
- {
- // Cache Miss.
- recorder.cacheMissEvent(id, update_type, cache_miss_type, msg_size);
-
- continue; // no data packer, skip this object
- }
- }
- else if (compressed)
+ if (compressed)
{
S32 uncompressed_length = 2048;
compressed_dp.reset();
- U32 flags = 0;
- if (update_type != OUT_TERSE_IMPROVED) // OUT_FULL_COMPRESSED only?
- {
- mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_UpdateFlags, flags, i);
- }
-
uncompressed_length = mesgsys->getSizeFast(_PREHASH_ObjectData, i, _PREHASH_Data);
mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_Data, compressed_dpbuffer, 0, i);
compressed_dp.assignBuffer(compressed_dpbuffer, uncompressed_length);
if (update_type != OUT_TERSE_IMPROVED) // OUT_FULL_COMPRESSED only?
{
+ U32 flags = 0;
+ mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_UpdateFlags, flags, i);
+
+ if(flags & FLAGS_TEMPORARY_ON_REZ)
+ {
compressed_dp.unpackUUID(fullid, "ID");
compressed_dp.unpackU32(local_id, "LocalID");
compressed_dp.unpackU8(pcode, "PCode");
}
+ else //send to object cache
+ {
+ regionp->cacheFullUpdate(compressed_dp, flags);
+ continue;
+ }
+ }
else
{
+ remove_from_cache = true;
compressed_dp.unpackU32(local_id, "LocalID");
getUUIDFromLocal(fullid,
local_id,
@@ -435,6 +512,7 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
}
else // OUT_FULL only?
{
+ remove_from_cache = true;
mesgsys->getUUIDFast(_PREHASH_ObjectData, _PREHASH_FullID, fullid, i);
mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_ID, local_id, i);
msg_size += sizeof(LLUUID);
@@ -443,6 +521,11 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
}
objectp = findObject(fullid);
+ if(remove_from_cache)
+ {
+ objectp = regionp->forceToRemoveFromCache(local_id, objectp);
+ }
+
// This looks like it will break if the local_id of the object doesn't change
// upon boundary crossing, but we check for region id matching later...
// Reset object local id and region pointer if things have changed
@@ -488,9 +571,6 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
continue;
}
}
- else if (cached) // Cache hit only?
- {
- }
else
{
if (update_type != OUT_FULL)
@@ -521,13 +601,11 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
recorder.objectUpdateFailure(local_id, update_type, msg_size);
continue;
}
+
justCreated = TRUE;
mNumNewObjects++;
- sCacheHitRate.addValue(cached ? 100.f : 0.f);
-
}
-
if (objectp->isDead())
{
llwarns << "Dead object " << objectp->mID << " in UUID map 1!" << llendl;
@@ -541,17 +619,21 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
objectp->mLocalID = local_id;
}
processUpdateCore(objectp, user_data, i, update_type, &compressed_dp, justCreated);
+
+#if 0
if (update_type != OUT_TERSE_IMPROVED) // OUT_FULL_COMPRESSED only?
{
+ U32 flags = 0;
+ mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_UpdateFlags, flags, i);
+
+ if(!(flags & FLAGS_TEMPORARY_ON_REZ))
+ {
bCached = true;
- LLViewerRegion::eCacheUpdateResult result = objectp->mRegionp->cacheFullUpdate(objectp, compressed_dp);
+ LLViewerRegion::eCacheUpdateResult result = objectp->mRegionp->cacheFullUpdate(objectp, compressed_dp, flags);
recorder.cacheFullUpdate(local_id, update_type, result, objectp, msg_size);
}
}
- else if (cached) // Cache hit only?
- {
- objectp->mLocalID = local_id;
- processUpdateCore(objectp, user_data, i, update_type, cached_dpp, justCreated);
+#endif
}
else
{
@@ -575,14 +657,53 @@ void LLViewerObjectList::processCompressedObjectUpdate(LLMessageSystem *mesgsys,
void **user_data,
const EObjectUpdateType update_type)
{
- processObjectUpdate(mesgsys, user_data, update_type, false, true);
+ processObjectUpdate(mesgsys, user_data, update_type, true);
}
void LLViewerObjectList::processCachedObjectUpdate(LLMessageSystem *mesgsys,
void **user_data,
const EObjectUpdateType update_type)
{
- processObjectUpdate(mesgsys, user_data, update_type, true, false);
+ //processObjectUpdate(mesgsys, user_data, update_type, true, false);
+
+ S32 num_objects = mesgsys->getNumberOfBlocksFast(_PREHASH_ObjectData);
+ gFullObjectUpdates += num_objects;
+
+ U64 region_handle;
+ mesgsys->getU64Fast(_PREHASH_RegionData, _PREHASH_RegionHandle, region_handle);
+ LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(region_handle);
+ if (!regionp)
+ {
+ llwarns << "Object update from unknown region! " << region_handle << llendl;
+ return;
+ }
+
+ LLViewerStatsRecorder& recorder = LLViewerStatsRecorder::instance();
+
+ for (S32 i = 0; i < num_objects; i++)
+ {
+ S32 msg_size = 0;
+ U32 id;
+ U32 crc;
+ U32 flags;
+ mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_ID, id, i);
+ mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_CRC, crc, i);
+ mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_UpdateFlags, flags, i);
+ msg_size += sizeof(U32) * 2;
+
+ // Lookup data packer and add this id to cache miss lists if necessary.
+ U8 cache_miss_type = LLViewerRegion::CACHE_MISS_TYPE_NONE;
+ if(!regionp->probeCache(id, crc, flags, cache_miss_type))
+ {
+ // Cache Miss.
+ recorder.cacheMissEvent(id, update_type, cache_miss_type, msg_size);
+
+ continue; // no data packer, skip this object
+ }
+ sample(sCacheHitRate, 100.f);
+ }
+
+ return;
}
void LLViewerObjectList::dirtyAllObjectInventory()
@@ -853,6 +974,8 @@ private:
LLSD mObjectIDs;
};
+static LLFastTimer::DeclareTimer FTM_IDLE_COPY("Idle Copy");
+
void LLViewerObjectList::update(LLAgent &agent, LLWorld &world)
{
// Update globals
@@ -903,10 +1026,8 @@ void LLViewerObjectList::update(LLAgent &agent, LLWorld &world)
U32 idle_count = 0;
- static LLFastTimer::DeclareTimer idle_copy("Idle Copy");
-
{
- LLFastTimer t(idle_copy);
+ LLFastTimer t(FTM_IDLE_COPY);
for (std::vector<LLPointer<LLViewerObject> >::iterator active_iter = mActiveObjects.begin();
active_iter != mActiveObjects.end(); active_iter++)
@@ -1032,10 +1153,10 @@ void LLViewerObjectList::update(LLAgent &agent, LLWorld &world)
}
*/
- LLViewerStats::getInstance()->mNumObjectsStat.addValue((S32) mObjects.size());
- LLViewerStats::getInstance()->mNumActiveObjectsStat.addValue(idle_count);
- LLViewerStats::getInstance()->mNumSizeCulledStat.addValue(mNumSizeCulled);
- LLViewerStats::getInstance()->mNumVisCulledStat.addValue(mNumVisCulled);
+ sample(LLStatViewer::NUM_OBJECTS, mObjects.size());
+ sample(LLStatViewer::NUM_ACTIVE_OBJECTS, idle_count);
+ sample(LLStatViewer::NUM_SIZE_CULLED, mNumSizeCulled);
+ sample(LLStatViewer::NUM_VIS_CULLED, mNumVisCulled);
}
void LLViewerObjectList::fetchObjectCosts()
@@ -1248,16 +1369,7 @@ BOOL LLViewerObjectList::killObject(LLViewerObject *objectp)
if (objectp)
{
- if (objectp->isDead())
- {
- // This object is already dead. Don't need to do more.
- return TRUE;
- }
- else
- {
- objectp->markDead();
- }
-
+ objectp->markDead(); // does the right thing if object already dead
return TRUE;
}
@@ -1893,6 +2005,29 @@ LLViewerObject *LLViewerObjectList::createObjectViewer(const LLPCode pcode, LLVi
return objectp;
}
+LLViewerObject *LLViewerObjectList::createObjectFromCache(const LLPCode pcode, LLViewerRegion *regionp, const LLUUID &uuid, const U32 local_id)
+{
+ llassert_always(uuid.notNull());
+
+ LLViewerObject *objectp = LLViewerObject::createObject(uuid, pcode, regionp);
+ if (!objectp)
+ {
+// llwarns << "Couldn't create object of type " << LLPrimitive::pCodeToString(pcode) << " id:" << fullid << llendl;
+ return NULL;
+ }
+
+ objectp->mLocalID = local_id;
+ mUUIDObjectMap[uuid] = objectp;
+ setUUIDAndLocal(uuid,
+ local_id,
+ regionp->getHost().getAddress(),
+ regionp->getHost().getPort());
+ mObjects.push_back(objectp);
+
+ updateActive(objectp);
+
+ return objectp;
+}
LLViewerObject *LLViewerObjectList::createObject(const LLPCode pcode, LLViewerRegion *regionp,
const LLUUID &uuid, const U32 local_id, const LLHost &sender)
@@ -1914,6 +2049,10 @@ LLViewerObject *LLViewerObjectList::createObject(const LLPCode pcode, LLViewerRe
// llwarns << "Couldn't create object of type " << LLPrimitive::pCodeToString(pcode) << " id:" << fullid << llendl;
return NULL;
}
+ if(regionp)
+ {
+ regionp->addToCreatedList(local_id);
+ }
mUUIDObjectMap[fullid] = objectp;
setUUIDAndLocal(fullid,
@@ -1960,9 +2099,7 @@ S32 LLViewerObjectList::findReferences(LLDrawable *drawablep) const
void LLViewerObjectList::orphanize(LLViewerObject *childp, U32 parent_id, U32 ip, U32 port)
{
-#ifdef ORPHAN_SPAM
- llinfos << "Orphaning object " << childp->getID() << " with parent " << parent_id << llendl;
-#endif
+ LL_DEBUGS("ORPHANS") << "Orphaning object " << childp->getID() << " with parent " << parent_id << LL_ENDL;
// We're an orphan, flag things appropriately.
childp->mOrphaned = TRUE;
@@ -2015,6 +2152,12 @@ void LLViewerObjectList::findOrphans(LLViewerObject* objectp, U32 ip, U32 port)
return;
}
+ //search object cache to get orphans
+ if(objectp->getRegion())
+ {
+ objectp->getRegion()->findOrphans(objectp->getLocalID());
+ }
+
// See if we are a parent of an orphan.
// Note: This code is fairly inefficient but it should happen very rarely.
// It can be sped up if this is somehow a performance issue...
@@ -2050,11 +2193,11 @@ void LLViewerObjectList::findOrphans(LLViewerObject* objectp, U32 ip, U32 port)
continue;
}
+ LL_DEBUGS("ORPHANS") << "Reunited parent " << objectp->mID
+ << " with child " << childp->mID << LL_ENDL;
+ LL_DEBUGS("ORPHANS") << "Glob: " << objectp->getPositionGlobal() << LL_ENDL;
+ LL_DEBUGS("ORPHANS") << "Agent: " << objectp->getPositionAgent() << LL_ENDL;
#ifdef ORPHAN_SPAM
- llinfos << "Reunited parent " << objectp->mID
- << " with child " << childp->mID << llendl;
- llinfos << "Glob: " << objectp->getPositionGlobal() << llendl;
- llinfos << "Agent: " << objectp->getPositionAgent() << llendl;
addDebugBeacon(objectp->getPositionAgent(),"");
#endif
gPipeline.markMoved(objectp->mDrawable);
@@ -2142,3 +2285,10 @@ bool LLViewerObjectList::OrphanInfo::operator!=(const OrphanInfo &rhs) const
}
+LLDebugBeacon::~LLDebugBeacon()
+{
+ if (mHUDObject.notNull())
+ {
+ mHUDObject->markDead();
+ }
+}