fix for SH-4656: crash at LLVOCacheEntry::updateParentBoundingInfo() line 510

master
Xiaohong Bao 2014-01-06 12:28:36 -07:00
parent 5e55cfd49e
commit 10ae6a779e
6 changed files with 239 additions and 245 deletions

View File

@ -330,6 +330,8 @@ LLViewerOctreeEntryData::LLViewerOctreeEntryData(LLViewerOctreeEntry::eEntryData
//virtual
void LLViewerOctreeEntryData::setOctreeEntry(LLViewerOctreeEntry* entry)
{
llassert_always(mEntry.isNull());
if(mEntry.notNull())
{
return;
@ -346,6 +348,15 @@ void LLViewerOctreeEntryData::setOctreeEntry(LLViewerOctreeEntry* entry)
mEntry->addData(this);
}
void LLViewerOctreeEntryData::removeOctreeEntry()
{
if(mEntry)
{
mEntry->removeData(this);
mEntry = NULL;
}
}
void LLViewerOctreeEntryData::setSpatialExtents(const LLVector3& min, const LLVector3& max)
{
mEntry->mExtents[0].load3(min.mV);

View File

@ -140,6 +140,7 @@ public:
LLViewerOctreeEntry* getEntry() {return mEntry;}
virtual void setOctreeEntry(LLViewerOctreeEntry* entry);
void removeOctreeEntry();
F32 getBinRadius() const {return mEntry->getBinRadius();}
const LLVector4a* getSpatialExtents() const;

View File

@ -806,50 +806,10 @@ void LLViewerRegion::dirtyHeights()
}
}
void LLViewerRegion::replaceVisibleCacheEntry(LLVOCacheEntry* old_entry, LLVOCacheEntry* new_entry)
{
//save old entry
old_entry->moveTo(new_entry);
U32 state = old_entry->getState();
U32 old_parent_id = old_entry->getParentID();
//kill old entry
killCacheEntry(old_entry);
//parse new entry
U32 new_parent_id = 0;
LLViewerObject::unpackParentID(new_entry->getDP(), new_parent_id);
//store new entry
mImpl->mCacheMap[new_entry->getLocalID()] = new_entry;
//process entry state
new_entry->setState(state);
if(state == LLVOCacheEntry::ACTIVE)
{
llassert(new_entry->getEntry()->hasDrawable());
mImpl->mActiveSet.insert(new_entry);
}
else if(state == LLVOCacheEntry::WAITING)
{
mImpl->mWaitingSet.insert(new_entry);
}
//process parent info
if(!old_parent_id && new_parent_id > 0) //becomes a child
{
new_entry->clearChildrenList();
}
new_entry->setParentID(new_parent_id);
//update the object
gObjectList.processObjectUpdateFromCache(new_entry, this);
}
//physically delete the cache entry
void LLViewerRegion::killCacheEntry(LLVOCacheEntry* entry, bool for_rendering)
{
if(!entry)
if(!entry || !entry->isValid())
{
return;
}
@ -889,22 +849,18 @@ void LLViewerRegion::killCacheEntry(LLVOCacheEntry* entry, bool for_rendering)
}
else if(entry->getNumOfChildren() > 0)//remove children from cache if has any
{
S32 num_child = entry->getNumOfChildren();
LLVOCacheEntry* child;
for(S32 i = 0; i < num_child; i++)
LLVOCacheEntry* child = entry->getChild();
while(child != NULL)
{
child = entry->getChild(i);
if(child)
{
child->setParentID(0); //disconnect from parent
killCacheEntry(child, for_rendering);
}
killCacheEntry(child, for_rendering);
child = entry->getChild();
}
}
//remove from mCacheMap, real deletion
mImpl->mCacheMap.erase(entry->getLocalID());
//will remove it from the object cache, real deletion
entry->setState(LLVOCacheEntry::INACTIVE);
entry->removeOctreeEntry();
entry->setValid(FALSE);
}
//physically delete the cache entry
@ -924,6 +880,10 @@ void LLViewerRegion::addActiveCacheEntry(LLVOCacheEntry* entry)
{
return;
}
if(entry->isState(LLVOCacheEntry::ACTIVE))
{
return; //already inserted.
}
if(entry->isState(LLVOCacheEntry::WAITING))
{
@ -939,10 +899,14 @@ void LLViewerRegion::addActiveCacheEntry(LLVOCacheEntry* entry)
void LLViewerRegion::removeActiveCacheEntry(LLVOCacheEntry* entry, LLDrawable* drawablep)
{
if(mDead || !entry)
if(mDead || !entry || !entry->isValid())
{
return;
}
if(!entry->isState(LLVOCacheEntry::ACTIVE))
{
return; //not an active entry.
}
//shift to the local regional space from agent space
if(drawablep != NULL && drawablep->getVObj().notNull())
@ -1004,11 +968,7 @@ void LLViewerRegion::addToVOCacheTree(LLVOCacheEntry* entry)
return;
}
if(mDead || !entry || !entry->getEntry())
{
return;
}
if(entry->getGroup()) //already in octree.
if(mDead || !entry || !entry->getEntry() || !entry->isValid())
{
return;
}
@ -1017,7 +977,14 @@ void LLViewerRegion::addToVOCacheTree(LLVOCacheEntry* entry)
return; //no child prim in cache octree.
}
llassert(!entry->getEntry()->hasDrawable());
if(entry->hasState(LLVOCacheEntry::IN_VO_TREE))
{
return; //already in the tree.
}
entry->setState(LLVOCacheEntry::IN_VO_TREE);
llassert_always(!entry->getGroup()); //not in octree.
llassert(!entry->getEntry()->hasDrawable()); //not have drawables
mImpl->mVOCachePartition->addEntry(entry->getEntry());
}
@ -1028,10 +995,12 @@ void LLViewerRegion::removeFromVOCacheTree(LLVOCacheEntry* entry)
{
return;
}
if(!entry->getGroup())
if(!entry->hasState(LLVOCacheEntry::IN_VO_TREE))
{
return;
return; //not in the tree.
}
entry->clearState(LLVOCacheEntry::IN_VO_TREE);
mImpl->mVOCachePartition->removeEntry(entry->getEntry());
}
@ -1039,7 +1008,7 @@ void LLViewerRegion::removeFromVOCacheTree(LLVOCacheEntry* entry)
//add the visible entries
void LLViewerRegion::addVisibleCacheEntry(LLVOCacheEntry* entry)
{
if(mDead || !entry || !entry->getEntry())
if(mDead || !entry || !entry->getEntry() || !entry->isValid())
{
return;
}
@ -1053,7 +1022,22 @@ void LLViewerRegion::addVisibleCacheEntry(LLVOCacheEntry* entry)
{
entry->setState(LLVOCacheEntry::IN_QUEUE);
}
mImpl->mVisibleEntries.insert(entry);
if(!entry->isState(LLVOCacheEntry::ACTIVE))
{
mImpl->mVisibleEntries.insert(entry);
}
//add all children
if(entry->getNumOfChildren() > 0)
{
LLVOCacheEntry* child = entry->getChild();
while(child != NULL)
{
addVisibleCacheEntry(child);
child = entry->getChild();
}
}
}
void LLViewerRegion::updateVisibleEntries(F32 max_time)
@ -1085,53 +1069,18 @@ void LLViewerRegion::updateVisibleEntries(F32 max_time)
for(LLVOCacheEntry::vocache_entry_set_t::iterator iter = mImpl->mVisibleEntries.begin(); iter != mImpl->mVisibleEntries.end();)
{
LLVOCacheEntry* vo_entry = *iter;
//set a large number to force to load this object.
vo_entry->setSceneContribution(LARGE_SCENE_CONTRIBUTION);
if(vo_entry->getState() < LLVOCacheEntry::WAITING)
{
if(vo_entry->isValid() && vo_entry->getState() < LLVOCacheEntry::WAITING)
{
//set a large number to force to load this object.
vo_entry->setSceneContribution(LARGE_SCENE_CONTRIBUTION);
mImpl->mWaitingList.insert(vo_entry);
}
LLVOCacheEntry* child;
S32 num_child = vo_entry->getNumOfChildren();
S32 num_done = 0;
for(S32 i = 0; i < num_child; i++)
{
child = vo_entry->getChild(i);
if(child->getState() < LLVOCacheEntry::WAITING)
{
child->setSceneContribution(LARGE_SCENE_CONTRIBUTION); //a large number to force to load the child.
mImpl->mWaitingList.insert(child);
}
else
{
num_done++;
}
}
if(num_done == num_child)
{
vo_entry->clearChildrenList();
}
if(!vo_entry->getNumOfChildren())
{
if(vo_entry->getState() >= LLVOCacheEntry::WAITING)
{
LLVOCacheEntry::vocache_entry_set_t::iterator next_iter = iter;
++next_iter;
mImpl->mVisibleEntries.erase(iter);
iter = next_iter;
}
else
{
++iter;
}
++iter;
}
else
{
++iter;
iter = mImpl->mVisibleEntries.erase(iter);
}
}
@ -1163,6 +1112,10 @@ void LLViewerRegion::updateVisibleEntries(F32 max_time)
//child visibility depends on its parent.
continue;
}
if(!vo_entry->isValid())
{
continue; //skip invalid entry.
}
vo_entry->calcSceneContribution(local_origin, needs_update, last_update, dist_threshold);
if(vo_entry->getSceneContribution() > projection_threshold)
@ -1240,10 +1193,7 @@ void LLViewerRegion::clearCachedVisibleObjects()
parent->addChild(entry);
}
LLVOCacheEntry::vocache_entry_set_t::iterator next_iter = iter;
++next_iter;
mImpl->mVisibleEntries.erase(iter);
iter = next_iter;
iter = mImpl->mVisibleEntries.erase(iter);
}
else //parent is not cache-able, leave it.
{
@ -2044,8 +1994,7 @@ void LLViewerRegion::findOrphans(U32 parent_id)
for(S32 i = 0; i < children->size(); i++)
{
//parent is visible, so is the child.
LLVOCacheEntry* child = getCacheEntry((*children)[i]);
addVisibleCacheEntry(child);
addVisibleCacheEntry(getCacheEntry((*children)[i]));
}
children->clear();
mOrphanMap.erase(parent_id);
@ -2059,46 +2008,50 @@ void LLViewerRegion::decodeBoundingInfo(LLVOCacheEntry* entry)
gObjectList.processObjectUpdateFromCache(entry, this);
return;
}
if(!entry || !entry->isValid())
{
return;
}
if(entry != NULL && !entry->getEntry())
if(!entry->getEntry())
{
entry->setOctreeEntry(NULL);
if(entry->getEntry()->hasDrawable()) //already in the rendering pipeline
{
LLViewerRegion* old_regionp = ((LLDrawable*)entry->getEntry()->getDrawable())->getRegion();
if(old_regionp != this && old_regionp)
{
LLViewerObject* obj = ((LLDrawable*)entry->getEntry()->getDrawable())->getVObj();
if(obj)
{
//remove from old region
old_regionp->killCacheEntry(obj->getLocalID());
//change region
obj->setRegion(this);
}
}
addActiveCacheEntry(entry);
//set parent id
U32 parent_id = 0;
LLViewerObject::unpackParentID(entry->getDP(), parent_id);
if(parent_id > 0)
{
entry->setParentID(parent_id);
}
//update the object
gObjectList.processObjectUpdateFromCache(entry, this);
return; //done
}
}
else if(entry->getGroup() != NULL)
if(entry->getEntry()->hasDrawable()) //already in the rendering pipeline
{
return; //already in octree, no post processing.
}
LLViewerRegion* old_regionp = ((LLDrawable*)entry->getEntry()->getDrawable())->getRegion();
if(old_regionp != this && old_regionp)
{
LLViewerObject* obj = ((LLDrawable*)entry->getEntry()->getDrawable())->getVObj();
if(obj)
{
//remove from old region
old_regionp->killCacheEntry(obj->getLocalID());
//change region
obj->setRegion(this);
}
}
addActiveCacheEntry(entry);
//set parent id
U32 parent_id = 0;
LLViewerObject::unpackParentID(entry->getDP(), parent_id);
if(parent_id != entry->getParentID())
{
entry->setParentID(parent_id);
}
//update the object
gObjectList.processObjectUpdateFromCache(entry, this);
return; //done
}
//must not be active.
llassert_always(!entry->isState(LLVOCacheEntry::ACTIVE));
removeFromVOCacheTree(entry); //remove from cache octree if it is in.
LLVector3 pos;
LLVector3 scale;
@ -2107,27 +2060,56 @@ void LLViewerRegion::decodeBoundingInfo(LLVOCacheEntry* entry)
//decode spatial info and parent info
U32 parent_id = LLViewerObject::extractSpatialExtents(entry->getDP(), pos, scale, rot);
if(parent_id > 0) //has parent
U32 old_parent_id = entry->getParentID();
bool same_old_parent = false;
if(parent_id != old_parent_id) //parent changed.
{
if(old_parent_id > 0) //has an old parent, disconnect it
{
LLVOCacheEntry* old_parent = getCacheEntry(old_parent_id);
if(old_parent)
{
old_parent->removeChild(entry);
if(!old_parent->isState(LLVOCacheEntry::INACTIVE))
{
mImpl->mVisibleEntries.erase(entry);
entry->setState(LLVOCacheEntry::INACTIVE);
}
}
}
entry->setParentID(parent_id);
}
else
{
same_old_parent = true;
}
if(parent_id > 0) //has a new parent
{
//1, find the parent in cache
LLVOCacheEntry* parent = getCacheEntry(parent_id);
//2, parent is not in the cache, put into the orphan list.
if(!parent)
{
//check if parent is non-cacheable and already created
if(isNonCacheableObjectCreated(parent_id))
if(!same_old_parent)
{
//parent is visible, so is the child.
addVisibleCacheEntry(entry);
//check if parent is non-cacheable and already created
if(isNonCacheableObjectCreated(parent_id))
{
//parent is visible, so is the child.
addVisibleCacheEntry(entry);
}
else
{
entry->setBoundingInfo(pos, scale);
mOrphanMap[parent_id].push_back(entry->getLocalID());
}
}
else
{
entry->setBoundingInfo(pos, scale);
mOrphanMap[parent_id].push_back(entry->getLocalID());
}
}
}
else //parent in cache.
{
@ -2194,10 +2176,12 @@ LLViewerRegion::eCacheUpdateResult LLViewerRegion::cacheFullUpdate(LLDataPackerB
LLViewerObject::unpackU32(&dp, local_id, "LocalID");
LLViewerObject::unpackU32(&dp, crc, "CRC");
LLVOCacheEntry* entry = getCacheEntry(local_id);
LLVOCacheEntry* entry = getCacheEntry(local_id, false);
if (entry)
{
entry->setValid();
// we've seen this object before
if (entry->getCRC() == crc)
{
@ -2205,31 +2189,15 @@ LLViewerRegion::eCacheUpdateResult LLViewerRegion::cacheFullUpdate(LLDataPackerB
entry->recordDupe();
result = CACHE_UPDATE_DUPE;
}
else
else //CRC changed
{
// Update the cache entry
LLPointer<LLVOCacheEntry> new_entry = new LLVOCacheEntry(local_id, crc, dp);
//if visible, update it
if(!entry->isState(LLVOCacheEntry::INACTIVE))
{
replaceVisibleCacheEntry(entry, new_entry);
}
else //invisible
{
//copy some contents from old entry
entry->moveTo(new_entry, true);
entry->updateEntry(crc, dp);
//remove old entry
killCacheEntry(entry);
entry = new_entry;
mImpl->mCacheMap[local_id] = entry;
decodeBoundingInfo(entry);
}
decodeBoundingInfo(entry);
result = CACHE_UPDATE_CHANGED;
}
}
}
else
{
@ -2268,12 +2236,15 @@ LLVOCacheEntry* LLViewerRegion::getCacheEntryForOctree(U32 local_id)
return entry;
}
LLVOCacheEntry* LLViewerRegion::getCacheEntry(U32 local_id)
LLVOCacheEntry* LLViewerRegion::getCacheEntry(U32 local_id, bool valid)
{
LLVOCacheEntry::vocache_entry_map_t::iterator iter = mImpl->mCacheMap.find(local_id);
if(iter != mImpl->mCacheMap.end())
{
return iter->second;
if(!valid || iter->second->isValid())
{
return iter->second;
}
}
return NULL;
}
@ -2323,7 +2294,7 @@ bool LLViewerRegion::probeCache(U32 local_id, U32 crc, U32 flags, U8 &cache_miss
{
//llassert(mCacheLoaded); This assert failes often, changing to early-out -- davep, 2010/10/18
LLVOCacheEntry* entry = getCacheEntry(local_id);
LLVOCacheEntry* entry = getCacheEntry(local_id, false);
if (entry)
{
@ -2341,15 +2312,12 @@ bool LLViewerRegion::probeCache(U32 local_id, U32 crc, U32 flags, U8 &cache_miss
return true;
}
if(entry->getGroup() || !entry->isState(LLVOCacheEntry::INACTIVE)) //already probed
if(entry->isValid())
{
return true;
}
if(entry->getParentID() > 0) //already probed
{
return true;
return true; //already probed
}
entry->setValid();
decodeBoundingInfo(entry);
return true;
}

View File

@ -331,7 +331,7 @@ public:
eCacheUpdateResult cacheFullUpdate(LLDataPackerBinaryBuffer &dp, U32 flags);
eCacheUpdateResult cacheFullUpdate(LLViewerObject* objectp, LLDataPackerBinaryBuffer &dp, U32 flags);
LLVOCacheEntry* getCacheEntryForOctree(U32 local_id);
LLVOCacheEntry* getCacheEntry(U32 local_id);
LLVOCacheEntry* getCacheEntry(U32 local_id, bool valid = true);
bool probeCache(U32 local_id, U32 crc, U32 flags, U8 &cache_miss_type);
void requestCacheMisses();
void addCacheMissFull(const U32 local_id);
@ -384,7 +384,6 @@ private:
LLViewerObject* addNewObject(LLVOCacheEntry* entry);
void killObject(LLVOCacheEntry* entry, std::vector<LLDrawable*>& delete_list);
void removeFromVOCacheTree(LLVOCacheEntry* entry);
void replaceVisibleCacheEntry(LLVOCacheEntry* old_entry, LLVOCacheEntry* new_entry);
void killCacheEntry(LLVOCacheEntry* entry, bool for_rendering = false); //physically delete the cache entry
void killInvisibleObjects(F32 max_time);
void createVisibleObjects(F32 max_time);

View File

@ -69,7 +69,7 @@ LLVOCacheEntry::LLVOCacheEntry(U32 local_id, U32 crc, LLDataPackerBinaryBuffer &
mCRCChangeCount(0),
mState(INACTIVE),
mSceneContrib(0.f),
mTouched(TRUE),
mValid(TRUE),
mParentID(0),
mBSphereRadius(-1.0f)
{
@ -90,7 +90,7 @@ LLVOCacheEntry::LLVOCacheEntry()
mBuffer(NULL),
mState(INACTIVE),
mSceneContrib(0.f),
mTouched(TRUE),
mValid(TRUE),
mParentID(0),
mBSphereRadius(-1.0f)
{
@ -104,7 +104,7 @@ LLVOCacheEntry::LLVOCacheEntry(LLAPRFile* apr_file)
mUpdateFlags(-1),
mState(INACTIVE),
mSceneContrib(0.f),
mTouched(FALSE),
mValid(FALSE),
mParentID(0),
mBSphereRadius(-1.0f)
{
@ -169,14 +169,29 @@ LLVOCacheEntry::LLVOCacheEntry(LLAPRFile* apr_file)
mCRCChangeCount = 0;
mBuffer = NULL;
mEntry = NULL;
mState = 0;
mState = INACTIVE;
}
}
LLVOCacheEntry::~LLVOCacheEntry()
{
mDP.freeBuffer();
//llassert(mState == INACTIVE);
}
void LLVOCacheEntry::updateEntry(U32 crc, LLDataPackerBinaryBuffer &dp)
{
if(mCRC != crc)
{
mCRC = crc;
mCRCChangeCount++;
}
mDP.freeBuffer();
llassert_always(dp.getBufferSize() > 0);
mBuffer = new U8[dp.getBufferSize()];
mDP.assignBuffer(mBuffer, dp.getBufferSize());
mDP = dp;
}
//virtual
@ -197,27 +212,19 @@ void LLVOCacheEntry::setOctreeEntry(LLViewerOctreeEntry* entry)
LLViewerOctreeEntryData::setOctreeEntry(entry);
}
void LLVOCacheEntry::moveTo(LLVOCacheEntry* new_entry, bool no_entry_move)
{
//copy LLViewerOctreeEntry
if(mEntry.notNull() && !no_entry_move)
{
new_entry->setOctreeEntry(mEntry);
mEntry = NULL;
}
//copy children
S32 num_children = getNumOfChildren();
for(S32 i = 0; i < num_children; i++)
{
new_entry->addChild(getChild(i));
}
mChildrenList.clear();
}
void LLVOCacheEntry::setState(U32 state)
{
mState = state;
if(state > LOW_BITS) //special states
{
mState |= (HIGH_BITS & state);
return;
}
//
//otherwise LOW_BITS states
//
clearState(LOW_BITS);
mState |= (LOW_BITS & state);
if(getState() == ACTIVE)
{
@ -249,8 +256,8 @@ void LLVOCacheEntry::addChild(LLVOCacheEntry* entry)
{
return;
}
mChildrenList.push_back(entry);
mChildrenList.insert(entry);
//update parent bbox
if(getEntry() != NULL && isState(INACTIVE))
@ -262,24 +269,27 @@ void LLVOCacheEntry::addChild(LLVOCacheEntry* entry)
void LLVOCacheEntry::removeChild(LLVOCacheEntry* entry)
{
for(S32 i = 0; i < mChildrenList.size(); i++)
entry->setParentID(0);
vocache_entry_set_t::iterator iter = mChildrenList.find(entry);
if(iter != mChildrenList.end())
{
if(mChildrenList[i] == entry)
{
entry->setParentID(0);
mChildrenList[i] = mChildrenList[mChildrenList.size() - 1];
mChildrenList.pop_back();
}
mChildrenList.erase(iter);
}
}
void LLVOCacheEntry::removeAllChildren()
//remove the first child, and return it.
LLVOCacheEntry* LLVOCacheEntry::getChild()
{
for(S32 i = 0; i < mChildrenList.size(); i++)
LLVOCacheEntry* child = NULL;
vocache_entry_set_t::iterator iter = mChildrenList.begin();
if(iter != mChildrenList.end())
{
mChildrenList[i]->setParentID(0);
child = *iter;
mChildrenList.erase(iter);
}
mChildrenList.clear();
return child;
}
LLDataPackerBinaryBuffer *LLVOCacheEntry::getDP()
@ -295,7 +305,6 @@ LLDataPackerBinaryBuffer *LLVOCacheEntry::getDP()
void LLVOCacheEntry::recordHit()
{
setTouched();
mHitCount++;
}
@ -505,9 +514,9 @@ void LLVOCacheEntry::updateParentBoundingInfo()
return;
}
for(S32 i = 0; i < mChildrenList.size(); i++)
for(vocache_entry_set_t::iterator iter = mChildrenList.begin(); iter != mChildrenList.end(); ++iter)
{
updateParentBoundingInfo(mChildrenList[i]);
updateParentBoundingInfo(*iter);
}
resetVisible();
}
@ -1463,7 +1472,7 @@ void LLVOCache::writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry:
for (LLVOCacheEntry::vocache_entry_map_t::const_iterator iter = cache_entry_map.begin(); success && iter != cache_entry_map.end(); ++iter)
{
if(!removal_enabled || iter->second->isTouched())
if(!removal_enabled || iter->second->isValid())
{
success = iter->second->writeToFile(&apr_file) ;
if(!success)

View File

@ -42,12 +42,19 @@ class LLVOCacheEntry
public LLTrace::MemTrackable<LLVOCacheEntry, 16>
{
public:
enum //low 16-bit state
enum
{
//low 16-bit state
INACTIVE = 0x00000000, //not visible
IN_QUEUE = 0x00000001, //in visible queue, object to be created
WAITING = 0x00000002, //object creation request sent
ACTIVE = 0x00000004 //object created, and in rendering pipeline.
ACTIVE = 0x00000004, //object created, and in rendering pipeline.
//high 16-bit state
IN_VO_TREE = 0x00010000, //the entry is in the object cache tree.
LOW_BITS = 0x0000ffff,
HIGH_BITS = 0xffff0000
};
struct CompareVOCacheEntry
@ -79,11 +86,13 @@ public:
LLVOCacheEntry(LLAPRFile* apr_file);
LLVOCacheEntry();
void setState(U32 state);
//void clearState(U32 state) {mState &= ~state;}
bool isState(U32 state) {return mState == state;}
bool hasState(U32 state) {return mState & state;}
U32 getState() const {return mState;}
void updateEntry(U32 crc, LLDataPackerBinaryBuffer &dp);
void clearState(U32 state) {mState &= ~state;}
bool hasState(U32 state) {return mState & state;}
void setState(U32 state);
bool isState(U32 state) {return (mState & LOW_BITS) == state;}
U32 getState() const {return mState & LOW_BITS;}
bool isAnyVisible(const LLVector4a& camera_origin, const LLVector4a& local_camera_origin, F32 dist_threshold);
@ -102,7 +111,6 @@ public:
void recordHit();
void recordDupe() { mDupeCount++; }
void moveTo(LLVOCacheEntry* new_entry, bool no_entry_move = false); //copy variables
/*virtual*/ void setOctreeEntry(LLViewerOctreeEntry* entry);
void setParentID(U32 id) {mParentID = id;}
@ -110,17 +118,15 @@ public:
void addChild(LLVOCacheEntry* entry);
void removeChild(LLVOCacheEntry* entry);
void removeAllChildren();
LLVOCacheEntry* getChild(S32 i) {return mChildrenList[i];}
S32 getNumOfChildren() {return mChildrenList.size();}
void clearChildrenList() {mChildrenList.clear();}
LLVOCacheEntry* getChild(); //remove the first child, and return it.
S32 getNumOfChildren() const {return mChildrenList.size();}
void setBoundingInfo(const LLVector3& pos, const LLVector3& scale); //called from processing object update message
void updateParentBoundingInfo();
void saveBoundingSphere();
void setTouched(BOOL touched = TRUE) {mTouched = touched;}
BOOL isTouched() const {return mTouched;}
void setValid(BOOL valid = TRUE) {mValid = valid;}
BOOL isValid() const {return mValid;}
void setUpdateFlags(U32 flags) {mUpdateFlags = flags;}
U32 getUpdateFlags() const {return mUpdateFlags;}
@ -150,9 +156,9 @@ protected:
F32 mSceneContrib; //projected scene contributuion of this object.
U32 mState; //high 16 bits reserved for special use.
std::vector<LLVOCacheEntry*> mChildrenList; //children entries in a linked set.
vocache_entry_set_t mChildrenList; //children entries in a linked set.
BOOL mTouched; //if set, this entry is valid, otherwise it is invalid.
BOOL mValid; //if set, this entry is valid, otherwise it is invalid and will be removed.
LLVector4a mBSphereCenter; //bounding sphere center
F32 mBSphereRadius; //bounding sphere radius