From 45a7fe901aa4cd7af14fa1cb894da46a988e3aa2 Mon Sep 17 00:00:00 2001
From: Xiaohong Bao <bao@lindenlab.com>
Date: Tue, 15 Jan 2013 23:01:40 -0700
Subject: for SH-3653: Can we repurpose
 ObjectUpdateCached:ObjectData:UpdateFlags field to carry spatial+size data?

---
 indra/newview/llviewerobjectlist.cpp |  4 +-
 indra/newview/llviewerregion.cpp     | 81 ++++++++++++++++--------------------
 indra/newview/llviewerregion.h       | 35 ++++++++++++++--
 3 files changed, 70 insertions(+), 50 deletions(-)

(limited to 'indra/newview')

diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp
index 0335cd769b..dce963c5c5 100644
--- a/indra/newview/llviewerobjectlist.cpp
+++ b/indra/newview/llviewerobjectlist.cpp
@@ -657,13 +657,15 @@ void LLViewerObjectList::processCachedObjectUpdate(LLMessageSystem *mesgsys,
 		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, cache_miss_type))
+		if(!regionp->probeCache(id, crc, flags, cache_miss_type))
 		{
 			// Cache Miss.
 			recorder.cacheMissEvent(id, update_type, cache_miss_type, msg_size);
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index 7d2e08c1c6..f44c8ffe46 100644
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -1718,9 +1718,26 @@ LLVOCacheEntry* LLViewerRegion::getCacheEntry(U32 local_id)
 	return NULL;
 }
 
+//estimate weight of cache missed object
+F32 LLViewerRegion::calcObjectWeight(U32 flags)
+{
+	LLVector3 pos((F32)(flags & 0xff), (F32)((flags >> 8) & 0xff), (F32)((flags >> 16) & 0xff) * 16.f);
+	F32 rad = (F32)((flags >> 24) & 0xff);
+
+	pos += getOriginAgent();
+	pos -= LLViewerCamera::getInstance()->getOrigin();
+
+	return rad * rad / pos.lengthSquared();
+}
+
+void LLViewerRegion::addCacheMiss(U32 id, LLViewerRegion::eCacheMissType miss_type, F32 weight)
+{
+	mCacheMissList.insert(CacheMissItem(id, miss_type, weight));
+}
+
 // Get data packer for this object, if we have cached data
 // AND the CRC matches. JC
-bool LLViewerRegion::probeCache(U32 local_id, U32 crc, U8 &cache_miss_type)
+bool LLViewerRegion::probeCache(U32 local_id, U32 crc, U32 flags, U8 &cache_miss_type)
 {
 	//llassert(mCacheLoaded);  This assert failes often, changing to early-out -- davep, 2010/10/18
 
@@ -1746,15 +1763,14 @@ bool LLViewerRegion::probeCache(U32 local_id, U32 crc, U8 &cache_miss_type)
 		else
 		{
 			// llinfos << "CRC miss for " << local_id << llendl;
-			cache_miss_type = CACHE_MISS_TYPE_CRC;
-			mCacheMissCRC.put(local_id);
+
+			addCacheMiss(local_id, CACHE_MISS_TYPE_CRC, calcObjectWeight(flags));
 		}
 	}
 	else
 	{
 		// llinfos << "Cache miss for " << local_id << llendl;
-		cache_miss_type = CACHE_MISS_TYPE_FULL;
-		mCacheMissFull.put(local_id);
+		addCacheMiss(local_id, CACHE_MISS_TYPE_FULL, calcObjectWeight(flags));
 	}
 
 	return false;
@@ -1762,49 +1778,22 @@ bool LLViewerRegion::probeCache(U32 local_id, U32 crc, U8 &cache_miss_type)
 
 void LLViewerRegion::addCacheMissFull(const U32 local_id)
 {
-	mCacheMissFull.put(local_id);
+	addCacheMiss(local_id, CACHE_MISS_TYPE_FULL, 100.f);
 }
 
 void LLViewerRegion::requestCacheMisses()
 {
-	S32 full_count = mCacheMissFull.count();
-	S32 crc_count = mCacheMissCRC.count();
-	if (full_count == 0 && crc_count == 0) return;
+	if (!mCacheMissList.size()) 
+	{
+		return;
+	}
 
 	LLMessageSystem* msg = gMessageSystem;
 	BOOL start_new_message = TRUE;
 	S32 blocks = 0;
-	S32 i;
-
-	// Send full cache miss updates.  For these, we KNOW we don't
-	// have a viewer object.
-	for (i = 0; i < full_count; i++)
-	{
-		if (start_new_message)
-		{
-			msg->newMessageFast(_PREHASH_RequestMultipleObjects);
-			msg->nextBlockFast(_PREHASH_AgentData);
-			msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
-			msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
-			start_new_message = FALSE;
-		}
-
-		msg->nextBlockFast(_PREHASH_ObjectData);
-		msg->addU8Fast(_PREHASH_CacheMissType, CACHE_MISS_TYPE_FULL);
-		msg->addU32Fast(_PREHASH_ID, mCacheMissFull[i]);
-		blocks++;
-
-		if (blocks >= 255)
-		{
-			sendReliableMessage();
-			start_new_message = TRUE;
-			blocks = 0;
-		}
-	}
-
-	// Send CRC miss updates.  For these, we _might_ have a viewer object,
-	// but probably not.
-	for (i = 0; i < crc_count; i++)
+	
+	//send requests for all cache-missed objects
+	for (CacheMissItem::cache_miss_list_t::iterator iter = mCacheMissList.begin(); iter != mCacheMissList.end(); ++iter)
 	{
 		if (start_new_message)
 		{
@@ -1816,8 +1805,8 @@ void LLViewerRegion::requestCacheMisses()
 		}
 
 		msg->nextBlockFast(_PREHASH_ObjectData);
-		msg->addU8Fast(_PREHASH_CacheMissType, CACHE_MISS_TYPE_CRC);
-		msg->addU32Fast(_PREHASH_ID, mCacheMissCRC[i]);
+		msg->addU8Fast(_PREHASH_CacheMissType, (*iter).mType);
+		msg->addU32Fast(_PREHASH_ID, (*iter).mID);
 		blocks++;
 
 		if (blocks >= 255)
@@ -1832,14 +1821,14 @@ void LLViewerRegion::requestCacheMisses()
 	if (!start_new_message)
 	{
 		sendReliableMessage();
-	}
-	mCacheMissFull.reset();
-	mCacheMissCRC.reset();
+	}	
 
 	mCacheDirty = TRUE ;
 	// llinfos << "KILLDEBUG Sent cache miss full " << full_count << " crc " << crc_count << llendl;
-	LLViewerStatsRecorder::instance().requestCacheMissesEvent(full_count + crc_count);
+	LLViewerStatsRecorder::instance().requestCacheMissesEvent(mCacheMissList.size());
 	LLViewerStatsRecorder::instance().log(0.2f);
+
+	mCacheMissList.clear();
 }
 
 void LLViewerRegion::dumpCache()
diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h
index 9252923aa3..4f0087ba7c 100644
--- a/indra/newview/llviewerregion.h
+++ b/indra/newview/llviewerregion.h
@@ -169,6 +169,9 @@ public:
 	const LLVector3d &getOriginGlobal() const;
 	LLVector3 getOriginAgent() const;
 
+	//estimate weight of cache missed object
+	F32 calcObjectWeight(U32 flags);
+
 	// Center is at the height of the water table.
 	const LLVector3d &getCenterGlobal() const;
 	LLVector3 getCenterAgent() const;
@@ -316,7 +319,7 @@ public:
 	// handle a full update message
 	eCacheUpdateResult cacheFullUpdate(LLViewerObject* objectp, LLDataPackerBinaryBuffer &dp);	
 	LLVOCacheEntry* getCacheEntryForOctree(U32 local_id);
-	bool probeCache(U32 local_id, U32 crc, U8 &cache_miss_type);
+	bool probeCache(U32 local_id, U32 crc, U32 flags, U8 &cache_miss_type);
 	void requestCacheMisses();
 	void addCacheMissFull(const U32 local_id);
 
@@ -356,6 +359,7 @@ private:
 	F32 createVisibleObjects(F32 max_time);
 	F32 updateVisibleEntries(F32 max_time); //update visible entries
 
+	void addCacheMiss(U32 id, LLViewerRegion::eCacheMissType miss_type, F32 weight);
 public:
 	struct CompareDistance
 	{
@@ -441,8 +445,33 @@ private:
 	BOOL    mReleaseNotesRequested;
 	BOOL    mDead;  //if true, this region is in the process of deleting.
 
-	LLDynamicArray<U32>						mCacheMissFull;
-	LLDynamicArray<U32>						mCacheMissCRC;
+	class CacheMissItem
+	{
+	public:
+		CacheMissItem(U32 id, LLViewerRegion::eCacheMissType miss_type, F32 weight) : mID(id), mType(miss_type), mWeight(weight){}
+
+		U32                            mID;     //local object id
+		LLViewerRegion::eCacheMissType mType;   //cache miss type
+		F32                            mWeight; //importance of this object to the current camera.
+	
+		struct Compare
+		{
+			bool operator()(const CacheMissItem& lhs, const CacheMissItem& rhs)
+			{
+				if(lhs.mWeight == rhs.mWeight) //larger weight first
+				{
+					return &lhs < &rhs;
+				}
+				else 
+				{
+					return lhs.mWeight > rhs.mWeight; //larger weight first
+				}
+			}
+		};
+
+		typedef std::set<CacheMissItem, Compare> cache_miss_list_t;
+	};
+	CacheMissItem::cache_miss_list_t        mCacheMissList;
 	
 	caps_received_signal_t mCapabilitiesReceivedSignal;		
 	LLSD mSimulatorFeatures;
-- 
cgit v1.2.3