Stinson Linden avatar Stinson Linden committed 2e47566 Merge

Pull and merge from ssh://hg@bitbucket.org/oz_linden/viewer-beta-drtvwr-179.

Comments (0)

Files changed (63)

indra/cmake/00-Common.cmake

       /Oy-
       /Zc:wchar_t-
       /arch:SSE2
+      /fp:fast
       )
      
   # Are we using the crummy Visual Studio KDU build workaround?

indra/llcharacter/llcharacter.cpp

 //-----------------------------------------------------------------------------
 static LLFastTimer::DeclareTimer FTM_UPDATE_ANIMATION("Update Animation");
 static LLFastTimer::DeclareTimer FTM_UPDATE_HIDDEN_ANIMATION("Update Hidden Anim");
+static LLFastTimer::DeclareTimer FTM_UPDATE_MOTIONS("Update Motions");
 
 void LLCharacter::updateMotions(e_update_t update_type)
 {
 			mMotionController.unpauseAllMotions();
 		}
 		bool force_update = (update_type == FORCE_UPDATE);
-		mMotionController.updateMotions(force_update);
+		{
+			LLFastTimer t(FTM_UPDATE_MOTIONS);
+			mMotionController.updateMotions(force_update);
+		}
 	}
 }
 
Add a comment to this file

indra/llcharacter/lleditingmotion.cpp

File contents unchanged.

Add a comment to this file

indra/llcharacter/llkeyframewalkmotion.cpp

File contents unchanged.

indra/llcharacter/llmotioncontroller.cpp

 //-----------------------------------------------------------------------------
 // updateMotionsByType()
 //-----------------------------------------------------------------------------
+static LLFastTimer::DeclareTimer FTM_MOTION_ON_UPDATE("Motion onUpdate");
+
 void LLMotionController::updateMotionsByType(LLMotion::LLMotionBlendType anim_type)
 {
 	BOOL update_result = TRUE;
 			}
 
 			// perform motion update
-			update_result = motionp->onUpdate(mAnimTime - motionp->mActivationTimestamp, last_joint_signature);
+			{
+				LLFastTimer t(FTM_MOTION_ON_UPDATE);
+				update_result = motionp->onUpdate(mAnimTime - motionp->mActivationTimestamp, last_joint_signature);
+			}
 		}
 
 		//**********************
 
 	// Always cap the number of loaded motions
 	purgeExcessMotions();
-	
+		
 	// Update timing info for this time step.
 	if (!mPaused)
 	{
 				}
 
 				updateLoadingMotions();
+				
 				return;
 			}
 			
 	}
 
 	updateLoadingMotions();
-
+	
 	resetJointSignatures();
 
 	if (mPaused && !force_update)
 	{
 		// update additive motions
 		updateAdditiveMotions();
+				
 		resetJointSignatures();
-
+		
 		// update all regular motions
 		updateRegularMotions();
-
+		
 		if (use_quantum)
 		{
 			mPoseBlender.blendAndCache(TRUE);

indra/llmath/lloctree.h

 #include "v3math.h"
 #include "llvector4a.h"
 #include <vector>
-#include <set>
 
 #define OCT_ERRS LL_WARNS("OctreeErrors")
 
 
 	typedef LLOctreeTraveler<T>									oct_traveler;
 	typedef LLTreeTraveler<T>									tree_traveler;
-	typedef typename std::set<LLPointer<T> >					element_list;
-	typedef typename element_list::iterator						element_iter;
-	typedef typename element_list::const_iterator	const_element_iter;
+	typedef LLPointer<T>*										element_list;
+	typedef LLPointer<T>*										element_iter;
+	typedef const LLPointer<T>*									const_element_iter;
 	typedef typename std::vector<LLTreeListener<T>*>::iterator	tree_listener_iter;
-	typedef typename std::vector<LLOctreeNode<T>* >				child_list;
+	typedef LLOctreeNode<T>**									child_list;
+	typedef LLOctreeNode<T>**									child_iter;
+
 	typedef LLTreeNode<T>		BaseType;
 	typedef LLOctreeNode<T>		oct_node;
 	typedef LLOctreeListener<T>	oct_listener;
 	:	mParent((oct_node*)parent), 
 		mOctant(octant) 
 	{ 
+		mData = NULL;
+		mDataEnd = NULL;
+
 		mCenter = center;
 		mSize = size;
 
 	{ 
 		BaseType::destroyListeners(); 
 		
+		for (U32 i = 0; i < mElementCount; ++i)
+		{
+			mData[i]->setBinIndex(-1);
+			mData[i] = NULL;
+		}
+
+		free(mData);
+		mData = NULL;
+		mDataEnd = NULL;
+
 		for (U32 i = 0; i < getChildCount(); i++)
 		{
 			delete getChild(i);
 	}
 
 	void accept(oct_traveler* visitor)				{ visitor->visit(this); }
-	virtual bool isLeaf() const						{ return mChild.empty(); }
+	virtual bool isLeaf() const						{ return mChildCount == 0; }
 	
 	U32 getElementCount() const						{ return mElementCount; }
+	bool isEmpty() const							{ return mElementCount == 0; }
 	element_list& getData()							{ return mData; }
 	const element_list& getData() const				{ return mData; }
-	
+	element_iter getDataBegin()						{ return mData; }
+	element_iter getDataEnd()						{ return mDataEnd; }
+	const_element_iter getDataBegin() const			{ return mData; }
+	const_element_iter getDataEnd() const			{ return mDataEnd; }
+		
 	U32 getChildCount()	const						{ return mChildCount; }
 	oct_node* getChild(U32 index)					{ return mChild[index]; }
 	const oct_node* getChild(U32 index) const		{ return mChild[index]; }
 	
 	virtual bool insert(T* data)
 	{
-		if (data == NULL)
+		if (data == NULL || data->getBinIndex() != -1)
 		{
 			OCT_ERRS << "!!! INVALID ELEMENT ADDED TO OCTREE BRANCH !!!" << llendl;
 			return false;
 			if ((getElementCount() < gOctreeMaxCapacity && contains(data->getBinRadius()) ||
 				(data->getBinRadius() > getSize()[0] &&	parent && parent->getElementCount() >= gOctreeMaxCapacity))) 
 			{ //it belongs here
-				//if this is a redundant insertion, error out (should never happen)
-				llassert(mData.find(data) == mData.end());
+				mElementCount++;
+				mData = (element_list) realloc(mData, sizeof(LLPointer<T>)*mElementCount);
 
-				mData.insert(data);
+				//avoid unref on uninitialized memory
+				memset(mData+mElementCount-1, 0, sizeof(LLPointer<T>));
+
+				mData[mElementCount-1] = data;
+				mDataEnd = mData + mElementCount;
+				data->setBinIndex(mElementCount-1);
 				BaseType::insert(data);
-
-				mElementCount = mData.size();
 				return true;
 			}
 			else
 
 				if( lt == 0x7 )
 				{
-					mData.insert(data);
+					mElementCount++;
+					mData = (element_list) realloc(mData, sizeof(LLPointer<T>)*mElementCount);
+
+					//avoid unref on uninitialized memory
+					memset(mData+mElementCount-1, 0, sizeof(LLPointer<T>));
+
+					mData[mElementCount-1] = data;
+					mDataEnd = mData + mElementCount;
+					data->setBinIndex(mElementCount-1);
 					BaseType::insert(data);
-
-					mElementCount = mData.size();
 					return true;
 				}
 
 		return false;
 	}
 
+	void _remove(T* data, S32 i)
+	{ //precondition -- mElementCount > 0, idx is in range [0, mElementCount)
+
+		mElementCount--;
+		data->setBinIndex(-1); 
+		
+		if (mElementCount > 0)
+		{
+			if (mElementCount != i)
+			{
+				mData[i] = mData[mElementCount]; //might unref data, do not access data after this point
+				mData[i]->setBinIndex(i);
+			}
+
+			mData[mElementCount] = NULL; //needed for unref
+			mData = (element_list) realloc(mData, sizeof(LLPointer<T>)*mElementCount);
+			mDataEnd = mData+mElementCount;
+		}
+		else
+		{
+			mData[0] = NULL; //needed for unref
+			free(mData);
+			mData = NULL;
+			mDataEnd = NULL;
+		}
+
+		notifyRemoval(data);
+		checkAlive();
+	}
+
 	bool remove(T* data)
 	{
-		if (mData.find(data) != mData.end())
-		{	//we have data
-			mData.erase(data);
-			mElementCount = mData.size();
-			notifyRemoval(data);
-			checkAlive();
-			return true;
+		S32 i = data->getBinIndex();
+
+		if (i >= 0 && i < mElementCount)
+		{
+			if (mData[i] == data)
+			{ //found it
+				_remove(data, i);
+				llassert(data->getBinIndex() == -1);
+				return true;
+			}
 		}
-		else if (isInside(data))
+		
+		if (isInside(data))
 		{
 			oct_node* dest = getNodeAt(data);
 
 			if (dest != this)
 			{
-				return dest->remove(data);
+				bool ret = dest->remove(data);
+				llassert(data->getBinIndex() == -1);
+				return ret;
 			}
 		}
 
 		//node is now root
 		llwarns << "!!! OCTREE REMOVING FACE BY ADDRESS, SEVERE PERFORMANCE PENALTY |||" << llendl;
 		node->removeByAddress(data);
+		llassert(data->getBinIndex() == -1);
 		return true;
 	}
 
 	void removeByAddress(T* data)
 	{
-        if (mData.find(data) != mData.end())
+        for (U32 i = 0; i < mElementCount; ++i)
 		{
-			mData.erase(data);
-			mElementCount = mData.size();
-			notifyRemoval(data);
-			llwarns << "FOUND!" << llendl;
-			checkAlive();
-			return;
+			if (mData[i] == data)
+			{ //we have data
+				_remove(data, i);
+				llwarns << "FOUND!" << llendl;
+				return;
+			}
 		}
 		
 		for (U32 i = 0; i < getChildCount(); i++)
 
 	void clearChildren()
 	{
-		mChild.clear();
 		mChildCount = 0;
+
 		U32* foo = (U32*) mChildMap;
 		foo[0] = foo[1] = 0xFFFFFFFF;
 	}
 
 		mChildMap[child->getOctant()] = mChildCount;
 
-		mChild.push_back(child);
+		mChild[mChildCount] = child;
 		++mChildCount;
 		child->setParent(this);
 
 			mChild[index]->destroy();
 			delete mChild[index];
 		}
-		mChild.erase(mChild.begin() + index);
+
 		--mChildCount;
 
+		mChild[index] = mChild[mChildCount];
+		
+
 		//rebuild child map
 		U32* foo = (U32*) mChildMap;
 		foo[0] = foo[1] = 0xFFFFFFFF;
 	oct_node* mParent;
 	U8 mOctant;
 
-	child_list mChild;
+	LLOctreeNode<T>* mChild[8];
 	U8 mChildMap[8];
 	U32 mChildCount;
 
 	element_list mData;
+	element_iter mDataEnd;
 	U32 mElementCount;
 		
 }; 

indra/llmath/llvolume.cpp

 		LLVector4a& min = node->mExtents[0];
 		LLVector4a& max = node->mExtents[1];
 
-		if (!branch->getData().empty())
+		if (!branch->isEmpty())
 		{ //node has data, find AABB that binds data set
-			const LLVolumeTriangle* tri = *(branch->getData().begin());
+			const LLVolumeTriangle* tri = *(branch->getDataBegin());
 			
 			//initialize min/max to first available vertex
 			min = *(tri->mV[0]);
 			max = *(tri->mV[0]);
 			
 			for (LLOctreeNode<LLVolumeTriangle>::const_element_iter iter = 
-				branch->getData().begin(); iter != branch->getData().end(); ++iter)
+				branch->getDataBegin(); iter != branch->getDataEnd(); ++iter)
 			{ //for each triangle in node
 
 				//stretch by triangles in node
 				max.setMax(max, *tri->mV[2]);
 			}
 		}
-		else if (!branch->getChildren().empty())
+		else if (!branch->isLeaf())
 		{ //no data, but child nodes exist
 			LLVolumeOctreeListener* child = (LLVolumeOctreeListener*) branch->getChild(0)->getListener(0);
 

indra/llmath/llvolumeoctree.cpp

 void LLOctreeTriangleRayIntersect::visit(const LLOctreeNode<LLVolumeTriangle>* node)
 {
 	for (LLOctreeNode<LLVolumeTriangle>::const_element_iter iter = 
-			node->getData().begin(); iter != node->getData().end(); ++iter)
+			node->getDataBegin(); iter != node->getDataEnd(); ++iter)
 	{
 		const LLVolumeTriangle* tri = *iter;
 
 	}
 
 	//children fit, check data
-	for (LLOctreeNode<LLVolumeTriangle>::const_element_iter iter = branch->getData().begin(); 
-			iter != branch->getData().end(); ++iter)
+	for (LLOctreeNode<LLVolumeTriangle>::const_element_iter iter = branch->getDataBegin(); 
+			iter != branch->getDataEnd(); ++iter)
 	{
 		const LLVolumeTriangle* tri = *iter;
 

indra/llmath/llvolumeoctree.h

 
 	LLVolumeTriangle()
 	{
-		
+		mBinIndex = -1;	
 	}
 
 	LLVolumeTriangle(const LLVolumeTriangle& rhs)
 	U16 mIndex[3];
 
 	F32 mRadius;
+	mutable S32 mBinIndex;
+
 
 	virtual const LLVector4a& getPositionGroup() const;
 	virtual const F32& getBinRadius() const;
+	
+	S32 getBinIndex() const { return mBinIndex; }
+	void setBinIndex(S32 idx) const { mBinIndex = idx; }
+
+
 };
 
 class LLVolumeOctreeListener : public LLOctreeListener<LLVolumeTriangle>

indra/llmessage/llurlrequest.cpp

 }
 
 static LLFastTimer::DeclareTimer FTM_PROCESS_URL_REQUEST("URL Request");
+static LLFastTimer::DeclareTimer FTM_PROCESS_URL_REQUEST_GET_RESULT("Get Result");
+static LLFastTimer::DeclareTimer FTM_URL_PERFORM("Perform");
 
 // virtual
 LLIOPipe::EStatus LLURLRequest::process_impl(
 	{
 		PUMP_DEBUG;
 		LLIOPipe::EStatus status = STATUS_BREAK;
-		static LLFastTimer::DeclareTimer FTM_URL_PERFORM("Perform");
 		{
 			LLFastTimer t(FTM_URL_PERFORM);
 			if(!mDetail->mCurlRequest->wait())
 		{
 			CURLcode result;
 
-			static LLFastTimer::DeclareTimer FTM_PROCESS_URL_REQUEST_GET_RESULT("Get Result");
-
 			bool newmsg = false;
 			{
 				LLFastTimer t(FTM_PROCESS_URL_REQUEST_GET_RESULT);

indra/llrender/llimagegl.cpp

 
 //----------------------------------------------------------------------------
 
+static LLFastTimer::DeclareTimer FTM_IMAGE_UPDATE_STATS("Image Stats");
 // static
 void LLImageGL::updateStats(F32 current_time)
 {
+	LLFastTimer t(FTM_IMAGE_UPDATE_STATS);
 	sLastFrameTime = current_time;
 	sBoundTextureMemoryInBytes = sCurBoundTextureMemory;
 	sCurBoundTextureMemory = 0;

indra/llrender/llrendertarget.cpp

 	release();
 }
 
+void LLRenderTarget::resize(U32 resx, U32 resy, U32 color_fmt)
+{ 
+	//for accounting, get the number of pixels added/subtracted
+	S32 pix_diff = (resx*resy)-(mResX*mResY);
+		
+	mResX = resx;
+	mResY = resy;
+
+	for (U32 i = 0; i < mTex.size(); ++i)
+	{ //resize color attachments
+		gGL.getTexUnit(0)->bindManual(mUsage, mTex[i]);
+		LLImageGL::setManualImage(LLTexUnit::getInternalType(mUsage), 0, color_fmt, mResX, mResY, GL_RGBA, GL_UNSIGNED_BYTE, NULL, false);
+		sBytesAllocated += pix_diff*4;
+	}
+
+	if (mDepth)
+	{ //resize depth attachment
+		if (mStencil)
+		{
+			//use render buffers where stencil buffers are in play
+			glBindRenderbuffer(GL_RENDERBUFFER, mDepth);
+			glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, mResX, mResY);
+			glBindRenderbuffer(GL_RENDERBUFFER, 0);
+		}
+		else
+		{
+			gGL.getTexUnit(0)->bindManual(mUsage, mDepth);
+			U32 internal_type = LLTexUnit::getInternalType(mUsage);
+			LLImageGL::setManualImage(internal_type, 0, GL_DEPTH_COMPONENT24, mResX, mResY, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL, false);
+		}
+
+		sBytesAllocated += pix_diff*4;
+	}
+}
+	
+
 bool LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo, S32 samples)
 {
 	stop_glerror();

indra/llrender/llrendertarget.h

 
 */
 
-class LLMultisampleBuffer;
-
 class LLRenderTarget
 {
 public:
 	//multiple calls will release previously allocated resources
 	bool allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage = LLTexUnit::TT_TEXTURE, bool use_fbo = false, S32 samples = 0);
 
+	//resize existing attachments to use new resolution and color format
+	// CAUTION: if the GL runs out of memory attempting to resize, this render target will be undefined
+	// DO NOT use for screen space buffers or for scratch space for an image that might be uploaded
+	// DO use for render targets that resize often and aren't likely to ruin someone's day if they break
+	void resize(U32 resx, U32 resy, U32 color_fmt);
+
 	//add color buffer attachment
 	//limit of 4 color attachments per render target
 	bool addColorAttachment(U32 color_fmt);

indra/newview/llappviewer.cpp

 #include "lllogininstance.h"
 #include "llprogressview.h"
 #include "llvocache.h"
+#include "llvopartgroup.h"
 #include "llweb.h"
 #include "llsecondlifeurls.h"
 #include "llupdaterservice.h"
 	// initialize SSE options
 	LLVector4a::initClass();
 
+	//initialize particle index pool
+	LLVOPartGroup::initClass();
+
 	// Need to do this initialization before we do anything else, since anything
 	// that touches files should really go through the lldir API
 	gDirUtilp->initAppDirs("SecondLife");

indra/newview/lldrawable.cpp

 
 static LLFastTimer::DeclareTimer FTM_CULL_REBOUND("Cull Rebound");
 
+extern bool gShiftFrame;
+
 
 ////////////////////////
 //
 	
 	mGeneration = -1;
 	mBinRadius = 1.f;
+	mBinIndex = -1;
+
 	mSpatialBridge = NULL;
 }
 
 		return;
 	}
 
+	if (gShiftFrame)
+	{
+		return;
+	}
+
 	//switch LOD with the spatial group to avoid artifacts
 	//LLSpatialGroup* sg = getSpatialGroup();
 
 		mXform.setPosition(mVObjp->getPositionAgent());
 	}
 
-	mXform.setRotation(mVObjp->getRotation());
-	mXform.setScale(1,1,1);
 	mXform.updateMatrix();
 
 	if (isStatic())
 	{
 		LLVOVolume* volume = getVOVolume();
-		if (!volume)
+
+		bool rebuild = (!volume && 
+						getRenderType() != LLPipeline::RENDER_TYPE_TREE &&
+						getRenderType() != LLPipeline::RENDER_TYPE_TERRAIN &&
+						getRenderType() != LLPipeline::RENDER_TYPE_SKY &&
+						getRenderType() != LLPipeline::RENDER_TYPE_GROUND);
+
+		if (rebuild)
 		{
 			gPipeline.markRebuild(this, LLDrawable::REBUILD_ALL, TRUE);
 		}
 				facep->mExtents[0].add(shift_vector);
 				facep->mExtents[1].add(shift_vector);
 			
-				if (!volume && facep->hasGeometry())
+				if (rebuild && facep->hasGeometry())
 				{
 					facep->clearVertexBuffer();
 				}
 {
 }
 
+LLSpatialGroup* LLDrawable::getSpatialGroup() const
+{ 
+	llassert((mSpatialGroupp == NULL) ? getBinIndex() == -1 : getBinIndex() != -1);
+	return mSpatialGroupp; 
+}
+
 void LLDrawable::setSpatialGroup(LLSpatialGroup *groupp)
 {
 	//precondition: mSpatialGroupp MUST be null or DEAD or mSpatialGroupp MUST NOT contain this
 	}
 
 	mSpatialGroupp = groupp;
+
+	llassert((mSpatialGroupp == NULL) ? getBinIndex() == -1 : getBinIndex() != -1);
 }
 
 LLSpatialPartition* LLDrawable::getSpatialPartition()
 	mDrawable = root;
 	root->setSpatialBridge(this);
 	
+	mBinIndex = -1;
+
 	mRenderType = mDrawable->mRenderType;
 	mDrawableType = mDrawable->mRenderType;
 	
 		return;
 	}
 
+	if (gShiftFrame)
+	{
+		return;
+	}
+
 	if (mDrawable->getVObj())
 	{
 		if (mDrawable->getVObj()->isAttachment())

indra/newview/lldrawable.h

 	F32			          getIntensity() const			{ return llmin(mXform.getScale().mV[0], 4.f); }
 	S32					  getLOD() const				{ return mVObjp ? mVObjp->getLOD() : 1; }
 	F32					  getBinRadius() const			{ return mBinRadius; }
+	S32					  getBinIndex() const			{ return mBinIndex; }
+	void				  setBinIndex(S32 index) const	{ mBinIndex = index; }
+
 	void  getMinMax(LLVector3& min,LLVector3& max) const { mXform.getMinMax(min,max); }
 	LLXformMatrix*		getXform() { return &mXform; }
 
 	S32 findReferences(LLDrawable *drawablep); // Not const because of @#$! iterators...
 
 	void setSpatialGroup(LLSpatialGroup *groupp);
-	LLSpatialGroup *getSpatialGroup() const			{ return mSpatialGroupp; }
+	LLSpatialGroup *getSpatialGroup() const;
 	LLSpatialPartition* getSpatialPartition();
 	
 	// Statics
 	mutable U32		mVisible;
 	F32				mRadius;
 	F32				mBinRadius;
+	mutable S32		mBinIndex;
 	S32				mGeneration;
 	
 	LLVector3		mCurrentScale;

indra/newview/lldrawpool.cpp

 {
 }
 
-// static
-S32 LLFacePool::drawLoop(face_array_t& face_list)
-{
-	S32 res = 0;
-	if (!face_list.empty())
-	{
-		for (std::vector<LLFace*>::iterator iter = face_list.begin();
-			 iter != face_list.end(); iter++)
-		{
-			LLFace *facep = *iter;
-			res += facep->renderIndexed();
-		}
-	}
-	return res;
-}
-
-// static
-S32 LLFacePool::drawLoopSetTex(face_array_t& face_list, S32 stage)
-{
-	S32 res = 0;
-	if (!face_list.empty())
-	{
-		for (std::vector<LLFace*>::iterator iter = face_list.begin();
-			 iter != face_list.end(); iter++)
-		{
-			LLFace *facep = *iter;
-			gGL.getTexUnit(stage)->bind(facep->getTexture(), TRUE) ;
-			gGL.getTexUnit(0)->activate();
-			res += facep->renderIndexed();
-		}
-	}
-	return res;
-}
-
-void LLFacePool::drawLoop()
-{
-	if (!mDrawFace.empty())
-	{
-		drawLoop(mDrawFace);
-	}
-}
-
 void LLFacePool::enqueue(LLFace* facep)
 {
 	mDrawFace.push_back(facep);
 
 void LLRenderPass::pushBatches(U32 type, U32 mask, BOOL texture, BOOL batch_textures)
 {
-	for (LLCullResult::drawinfo_list_t::iterator i = gPipeline.beginRenderMap(type); i != gPipeline.endRenderMap(type); ++i)	
+	for (LLCullResult::drawinfo_iterator i = gPipeline.beginRenderMap(type); i != gPipeline.endRenderMap(type); ++i)	
 	{
 		LLDrawInfo* pparams = *i;
 		if (pparams) 

indra/newview/lldrawpool.h

 
 	void buildEdges();
 
-	static S32 drawLoop(face_array_t& face_list);
-	static S32 drawLoopSetTex(face_array_t& face_list, S32 stage);
-	void drawLoop();
-
 	void addFaceReference(LLFace *facep);
 	void removeFaceReference(LLFace *facep);
 

indra/newview/lldrawpoolalpha.cpp

 
 void LLDrawPoolAlpha::renderAlphaHighlight(U32 mask)
 {
-	for (LLCullResult::sg_list_t::iterator i = gPipeline.beginAlphaGroups(); i != gPipeline.endAlphaGroups(); ++i)
+	for (LLCullResult::sg_iterator i = gPipeline.beginAlphaGroups(); i != gPipeline.endAlphaGroups(); ++i)
 	{
 		LLSpatialGroup* group = *i;
 		if (group->mSpatialPartition->mRenderByGroup &&
 	
 	BOOL use_shaders = gPipeline.canUseVertexShaders();
 		
-	for (LLCullResult::sg_list_t::iterator i = gPipeline.beginAlphaGroups(); i != gPipeline.endAlphaGroups(); ++i)
+	for (LLCullResult::sg_iterator i = gPipeline.beginAlphaGroups(); i != gPipeline.endAlphaGroups(); ++i)
 	{
 		LLSpatialGroup* group = *i;
 		llassert(group);

indra/newview/lldrawpoolavatar.cpp

 	gGL.getTexUnit(0)->activate();
 }
 
+static LLFastTimer::DeclareTimer FTM_RENDER_AVATARS("renderAvatars");
+
 
 void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
 {
+	LLFastTimer t(FTM_RENDER_AVATARS);
+
 	if (pass == -1)
 	{
 		for (S32 i = 1; i < getNumPasses(); i++)
 
 	if (pass >= 7 && pass < 9)
 	{
-		LLGLEnable blend(GL_BLEND);
-
-		gGL.setColorMask(true, true);
-		gGL.blendFunc(LLRender::BF_SOURCE_ALPHA,
-					  LLRender::BF_ONE_MINUS_SOURCE_ALPHA,
-					  LLRender::BF_ZERO,
-					  LLRender::BF_ONE_MINUS_SOURCE_ALPHA);
-
-		
 		if (pass == 7)
 		{
 			renderRiggedAlpha(avatarp);
 
 	if (pass == 9)
 	{
-		LLGLEnable blend(GL_BLEND);
-		LLGLDisable test(GL_ALPHA_TEST);
-		gGL.flush();
-
-		LLGLEnable polyOffset(GL_POLYGON_OFFSET_FILL);
-		glPolygonOffset(-1.0f, -1.0f);
-		gGL.setSceneBlendType(LLRender::BT_ADD);
-
-		LLGLDepthTest depth(GL_TRUE, GL_FALSE);
-		gGL.setColorMask(false, true);
-
 		renderRiggedGlow(avatarp);
-		gGL.setColorMask(true, false);
-		gGL.setSceneBlendType(LLRender::BT_ALPHA);
+		
 		return;
 	}
 	
 
 void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow)
 {
-	if (avatar->isSelf() && !gAgent.needsRenderAvatar() || !gMeshRepo.meshRezEnabled())
+	if (avatar->isSelf() && !gAgent.needsRenderAvatar())
 	{
 		return;
 	}
 	renderRigged(avatar, RIGGED_DEFERRED_BUMP);
 }
 
+static LLFastTimer::DeclareTimer FTM_RIGGED_VBO("Rigged VBO");
+
 void LLDrawPoolAvatar::updateRiggedVertexBuffers(LLVOAvatar* avatar)
 {
+	LLFastTimer t(FTM_RIGGED_VBO);
+
 	//update rigged vertex buffers
 	for (U32 type = 0; type < NUM_RIGGED_PASSES; ++type)
 	{
 
 void LLDrawPoolAvatar::renderRiggedAlpha(LLVOAvatar* avatar)
 {
-	renderRigged(avatar, RIGGED_ALPHA);
+	if (!mRiggedFace[RIGGED_ALPHA].empty())
+	{
+		LLGLEnable blend(GL_BLEND);
+
+		gGL.setColorMask(true, true);
+		gGL.blendFunc(LLRender::BF_SOURCE_ALPHA,
+						LLRender::BF_ONE_MINUS_SOURCE_ALPHA,
+						LLRender::BF_ZERO,
+						LLRender::BF_ONE_MINUS_SOURCE_ALPHA);
+
+		renderRigged(avatar, RIGGED_ALPHA);
+	}
 }
 
 void LLDrawPoolAvatar::renderRiggedFullbrightAlpha(LLVOAvatar* avatar)
 {
-	renderRigged(avatar, RIGGED_FULLBRIGHT_ALPHA);
+	if (!mRiggedFace[RIGGED_FULLBRIGHT_ALPHA].empty())
+	{
+		LLGLEnable blend(GL_BLEND);
+
+		gGL.setColorMask(true, true);
+		gGL.blendFunc(LLRender::BF_SOURCE_ALPHA,
+						LLRender::BF_ONE_MINUS_SOURCE_ALPHA,
+						LLRender::BF_ZERO,
+						LLRender::BF_ONE_MINUS_SOURCE_ALPHA);
+
+		renderRigged(avatar, RIGGED_FULLBRIGHT_ALPHA);
+	}
 }
 
 void LLDrawPoolAvatar::renderRiggedGlow(LLVOAvatar* avatar)
 {
-	renderRigged(avatar, RIGGED_GLOW, true);
+	if (!mRiggedFace[RIGGED_GLOW].empty())
+	{
+		LLGLEnable blend(GL_BLEND);
+		LLGLDisable test(GL_ALPHA_TEST);
+		gGL.flush();
+
+		LLGLEnable polyOffset(GL_POLYGON_OFFSET_FILL);
+		glPolygonOffset(-1.0f, -1.0f);
+		gGL.setSceneBlendType(LLRender::BT_ADD);
+
+		LLGLDepthTest depth(GL_TRUE, GL_FALSE);
+		gGL.setColorMask(false, true);
+
+		renderRigged(avatar, RIGGED_GLOW, true);
+
+		gGL.setColorMask(true, false);
+		gGL.setSceneBlendType(LLRender::BT_ALPHA);
+	}
 }
 
 

indra/newview/lldrawpoolbump.cpp

 	LLFastTimer ftm(FTM_RENDER_BUMP);
 
 	U32 type = LLRenderPass::PASS_BUMP;
-	LLCullResult::drawinfo_list_t::iterator begin = gPipeline.beginRenderMap(type);
-	LLCullResult::drawinfo_list_t::iterator end = gPipeline.endRenderMap(type);
+	LLCullResult::drawinfo_iterator begin = gPipeline.beginRenderMap(type);
+	LLCullResult::drawinfo_iterator end = gPipeline.endRenderMap(type);
 
 	U32 mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_BINORMAL | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_COLOR;
 	
-	for (LLCullResult::drawinfo_list_t::iterator i = begin; i != end; ++i)	
+	for (LLCullResult::drawinfo_iterator i = begin; i != end; ++i)	
 	{
 		LLDrawInfo& params = **i;
 
 
 void LLDrawPoolBump::renderBump(U32 type, U32 mask)
 {	
-	LLCullResult::drawinfo_list_t::iterator begin = gPipeline.beginRenderMap(type);
-	LLCullResult::drawinfo_list_t::iterator end = gPipeline.endRenderMap(type);
+	LLCullResult::drawinfo_iterator begin = gPipeline.beginRenderMap(type);
+	LLCullResult::drawinfo_iterator end = gPipeline.endRenderMap(type);
 
-	for (LLCullResult::drawinfo_list_t::iterator i = begin; i != end; ++i)	
+	for (LLCullResult::drawinfo_iterator i = begin; i != end; ++i)	
 	{
 		LLDrawInfo& params = **i;
 

indra/newview/lldrawpoolterrain.cpp

 	//glCullFace(GL_BACK);
 }
 
+
+void LLDrawPoolTerrain::drawLoop()
+{
+	if (!mDrawFace.empty())
+	{
+		for (std::vector<LLFace*>::iterator iter = mDrawFace.begin();
+			 iter != mDrawFace.end(); iter++)
+		{
+			LLFace *facep = *iter;
+
+			LLMatrix4* model_matrix = &(facep->getDrawable()->getRegion()->mRenderMatrix);
+
+			if (model_matrix != gGLLastMatrix)
+			{
+				gGLLastMatrix = model_matrix;
+				gGL.loadMatrix(gGLModelView);
+				if (model_matrix)
+				{
+					gGL.multMatrix((GLfloat*) model_matrix->mMatrix);
+				}
+				gPipeline.mMatrixOpCount++;
+			}
+
+			facep->renderIndexed();
+		}
+	}
+}
+
 void LLDrawPoolTerrain::renderFullShader()
 {
 	// Hack! Get the region that this draw pool is rendering from!

indra/newview/lldrawpoolterrain.h

 	void renderFull2TU();
 	void renderFull4TU();
 	void renderFullShader();
+	void drawLoop();
 };
 
 #endif // LL_LLDRAWPOOLSIMPLE_H

indra/newview/lldrawpooltree.cpp

 #include "llviewershadermgr.h"
 #include "llrender.h"
 #include "llviewercontrol.h"
+#include "llviewerregion.h"
 
 S32 LLDrawPoolTree::sDiffTex = 0;
 static LLGLSLShader* shader = NULL;
 	{
 		LLFace *face = *iter;
 		LLVertexBuffer* buff = face->getVertexBuffer();
+
 		if(buff)
 		{
+			LLMatrix4* model_matrix = &(face->getDrawable()->getRegion()->mRenderMatrix);
+
+			if (model_matrix != gGLLastMatrix)
+			{
+				gGLLastMatrix = model_matrix;
+				gGL.loadMatrix(gGLModelView);
+				if (model_matrix)
+				{
+					gGL.multMatrix((GLfloat*) model_matrix->mMatrix);
+				}
+				gPipeline.mMatrixOpCount++;
+			}
+
 			buff->setBuffer(LLDrawPoolTree::VERTEX_DATA_MASK);
 			buff->drawRange(LLRender::TRIANGLES, 0, buff->getNumVerts()-1, buff->getNumIndices(), 0); 
 			gPipeline.addTrianglesDrawn(buff->getNumIndices());

indra/newview/lldriverparam.cpp

 	mAvatarp(avatarp), 
 	mWearablep(NULL)
 {
+	mDefaultVec.clear();
 }
 
 LLDriverParam::LLDriverParam(LLWearable *wearablep) : 
 	mAvatarp(NULL), 
 	mWearablep(wearablep)
 {
+	mDefaultVec.clear();
 }
 
 LLDriverParam::~LLDriverParam()
 	return sum; 
 }
 
-const LLVector3	&LLDriverParam::getAvgDistortion()	
+const LLVector4a	&LLDriverParam::getAvgDistortion()	
 {
 	// It's not actually correct to take the average of averages, but it good enough here.
-	LLVector3 sum;
+	LLVector4a sum;
+	sum.clear();
 	S32 count = 0;
 	for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); iter++ )
 	{
 		LLDrivenEntry* driven = &(*iter);
-		sum += driven->mParam->getAvgDistortion();
+		sum.add(driven->mParam->getAvgDistortion());
 		count++;
 	}
-	sum /= (F32)count;
+	sum.mul( 1.f/(F32)count);
 
 	mDefaultVec = sum;
 	return mDefaultVec; 
 }
 
 
-LLVector3	LLDriverParam::getVertexDistortion(S32 index, LLPolyMesh *poly_mesh)
+LLVector4a	LLDriverParam::getVertexDistortion(S32 index, LLPolyMesh *poly_mesh)
 {
-	LLVector3 sum;
+	LLVector4a sum;
+	sum.clear();
 	for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); iter++ )
 	{
 		LLDrivenEntry* driven = &(*iter);
-		sum += driven->mParam->getVertexDistortion( index, poly_mesh );
+		sum.add(driven->mParam->getVertexDistortion( index, poly_mesh ));
 	}
 	return sum;
 }
 
-const LLVector3*	LLDriverParam::getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh)
+const LLVector4a*	LLDriverParam::getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh)
 {
 	mCurrentDistortionParam = NULL;
-	const LLVector3* v = NULL;
+	const LLVector4a* v = NULL;
 	for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); iter++ )
 	{
 		LLDrivenEntry* driven = &(*iter);
 	return v;
 };
 
-const LLVector3*	LLDriverParam::getNextDistortion(U32 *index, LLPolyMesh **poly_mesh)
+const LLVector4a*	LLDriverParam::getNextDistortion(U32 *index, LLPolyMesh **poly_mesh)
 {
 	llassert( mCurrentDistortionParam );
 	if( !mCurrentDistortionParam )
 	}
 
 	// We're already in the middle of a param's distortions, so get the next one.
-	const LLVector3* v = driven->mParam->getNextDistortion( index, poly_mesh );
+	const LLVector4a* v = driven->mParam->getNextDistortion( index, poly_mesh );
 	if( (!v) && (iter != mDriven.end()) )
 	{
 		// This param is finished, so start the next param.  It might not have any

indra/newview/lldriverparam.h

 	LLDriverParam(LLWearable *wearablep);
 	~LLDriverParam();
 
+	void* operator new(size_t size)
+	{
+		return ll_aligned_malloc_16(size);
+	}
+
+	void operator delete(void* ptr)
+	{
+		ll_aligned_free_16(ptr);
+	}
+
 	// Special: These functions are overridden by child classes
 	LLDriverParamInfo*		getInfo() const { return (LLDriverParamInfo*)mInfo; }
 	//   This sets mInfo and calls initialization functions
 	
 	// LLViewerVisualParam Virtual functions
 	/*virtual*/ F32					getTotalDistortion();
-	/*virtual*/ const LLVector3&	getAvgDistortion();
+	/*virtual*/ const LLVector4a&	getAvgDistortion();
 	/*virtual*/ F32					getMaxDistortion();
-	/*virtual*/ LLVector3			getVertexDistortion(S32 index, LLPolyMesh *poly_mesh);
-	/*virtual*/ const LLVector3*	getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh);
-	/*virtual*/ const LLVector3*	getNextDistortion(U32 *index, LLPolyMesh **poly_mesh);
+	/*virtual*/ LLVector4a			getVertexDistortion(S32 index, LLPolyMesh *poly_mesh);
+	/*virtual*/ const LLVector4a*	getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh);
+	/*virtual*/ const LLVector4a*	getNextDistortion(U32 *index, LLPolyMesh **poly_mesh);
 
 protected:
 	F32 getDrivenWeight(const LLDrivenEntry* driven, F32 input_weight);
 	void setDrivenWeight(LLDrivenEntry *driven, F32 driven_weight, bool upload_bake);
 
 
-	LLVector3	mDefaultVec; // temp holder
+	LLVector4a	mDefaultVec; // temp holder
 	typedef std::vector<LLDrivenEntry> entry_list_t;
 	entry_list_t mDriven;
 	LLViewerVisualParam* mCurrentDistortionParam;

indra/newview/llface.cpp

 	mGeomCount		= 0;
 	mGeomIndex		= 0;
 	mIndicesCount	= 0;
-	if (drawablep->getRenderType() == LLPipeline::RENDER_TYPE_PARTICLES ||
-		drawablep->getRenderType() == LLPipeline::RENDER_TYPE_HUD_PARTICLES)
-	{ //indicate to LLParticlePartition that this particle is uninitialized
-		mIndicesIndex = 0xFFFFFFFF;
-	}
-	else
-	{
-		mIndicesIndex	= 0;
-	}
+
+	//special value to indicate uninitialized position
+	mIndicesIndex	= 0xFFFFFFFF;
+	
 	mIndexInTex = 0;
 	mTexture		= NULL;
 	mTEOffset		= -1;
 		mTexture->removeFace(this) ;
 	}
 	
-	if (mDrawablep.notNull() &&
-		(mDrawablep->getRenderType() == LLPipeline::RENDER_TYPE_PARTICLES ||
-		mDrawablep->getRenderType() == LLPipeline::RENDER_TYPE_HUD_PARTICLES) &&
-		mIndicesIndex != 0xFFFFFFFF)
+	if (isState(LLFace::PARTICLE))
 	{
 		LLVOPartGroup::freeVBSlot(getGeomIndex()/4);
-		mIndicesIndex = 0xFFFFFFFF;
+		clearState(LLFace::PARTICLE);
 	}
 
 	if (mDrawPoolp)
 	{
 		if (num_indices + (S32) mIndicesIndex > mVertexBuffer->getNumIndices())
 		{
-			llwarns	<< "Index buffer overflow!" << llendl;
-			llwarns << "Indices Count: " << mIndicesCount
-					<< " VF Num Indices: " << num_indices
-					<< " Indices Index: " << mIndicesIndex
-					<< " VB Num Indices: " << mVertexBuffer->getNumIndices() << llendl;
-			llwarns	<< " Face Index: " << f
-					<< " Pool Type: " << mPoolType << llendl;
+			if (gDebugGL)
+			{
+				llwarns	<< "Index buffer overflow!" << llendl;
+				llwarns << "Indices Count: " << mIndicesCount
+						<< " VF Num Indices: " << num_indices
+						<< " Indices Index: " << mIndicesIndex
+						<< " VB Num Indices: " << mVertexBuffer->getNumIndices() << llendl;
+				llwarns	<< " Face Index: " << f
+						<< " Pool Type: " << mPoolType << llendl;
+			}
 			return FALSE;
 		}
 
 		if (num_vertices + mGeomIndex > mVertexBuffer->getNumVerts())
 		{
-			llwarns << "Vertex buffer overflow!" << llendl;
+			if (gDebugGL)
+			{
+				llwarns << "Vertex buffer overflow!" << llendl;
+			}
 			return FALSE;
 		}
 	}

indra/newview/llface.h

 		USE_FACE_COLOR	= 0x0010,
 		TEXTURE_ANIM	= 0x0020, 
 		RIGGED			= 0x0040,
+		PARTICLE		= 0x0080,
 	};
 
 	static void initClass();

indra/newview/llflexibleobject.cpp

 	mFrameNum = 0;
 	mCollisionSphereRadius = 0.f;
 	mRenderRes = 1;
-
+	
 	if(mVO->mDrawable.notNull())
 	{
 		mVO->mDrawable->makeActive() ;
 {
 }
 
-//---------------------------------------------------------------------------------
-// This calculates the physics of the flexible object. Note that it has to be 0
-// updated every time step. In the future, perhaps there could be an 
-// optimization similar to what Havok does for objects that are stationary. 
-//---------------------------------------------------------------------------------
-static LLFastTimer::DeclareTimer FTM_FLEXIBLE_UPDATE("Update Flexies");
-BOOL LLVolumeImplFlexible::doIdleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
+
+void LLVolumeImplFlexible::updateRenderRes()
 {
-	if (mVO->mDrawable.isNull())
-	{
-		// Don't do anything until we have a drawable
-		return FALSE; // (we are not initialized or updated)
-	}
+	LLDrawable* drawablep = mVO->mDrawable;
 
-	BOOL force_update = mSimulateRes == 0 ? TRUE : FALSE;
-
-	//flexible objects never go static
-	mVO->mDrawable->mQuietCount = 0;
-	if (!mVO->mDrawable->isRoot())
-	{
-		LLViewerObject* parent = (LLViewerObject*) mVO->getParent();
-		parent->mDrawable->mQuietCount = 0;
-	}
-
-	LLFastTimer ftm(FTM_FLEXIBLE_UPDATE);
-		
 	S32 new_res = mAttributes->getSimulateLOD();
 
-	//number of segments only cares about z axis
-	F32 app_angle = llround((F32) atan2( mVO->getScale().mV[2]*2.f, mVO->mDrawable->mDistanceWRTCamera) * RAD_TO_DEG, 0.01f);
+#if 1 //optimal approximation of previous behavior that doesn't rely on atan2
+	F32 app_angle = mVO->getScale().mV[2]/drawablep->mDistanceWRTCamera;
 
 	// Rendering sections increases with visible angle on the screen
+	mRenderRes = (S32) (12.f*app_angle);
+#else //legacy behavior
+	//number of segments only cares about z axis
+	F32 app_angle = llround((F32) atan2( mVO->getScale().mV[2]*2.f, drawablep->mDistanceWRTCamera) * RAD_TO_DEG, 0.01f);
+
+ 	// Rendering sections increases with visible angle on the screen
 	mRenderRes = (S32)(FLEXIBLE_OBJECT_MAX_SECTIONS*4*app_angle*DEG_TO_RAD/LLViewerCamera::getInstance()->getView());
-	if (mRenderRes > FLEXIBLE_OBJECT_MAX_SECTIONS)
-	{
-		mRenderRes = FLEXIBLE_OBJECT_MAX_SECTIONS;
-	}
-
-
-	// Bottom cap at 1/4 the original number of sections
-	if (mRenderRes < mAttributes->getSimulateLOD()-1)
-	{
-		mRenderRes = mAttributes->getSimulateLOD()-1;
-	}
+#endif
+		
+	mRenderRes = llclamp(mRenderRes, new_res-1, (S32) FLEXIBLE_OBJECT_MAX_SECTIONS);
+		
 	// Throttle back simulation of segments we're not rendering
 	if (mRenderRes < new_res)
 	{
 		setAttributesOfAllSections();
 		mInitialized = TRUE;
 	}
-	if (!gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_FLEXIBLE))
+}
+//---------------------------------------------------------------------------------
+// This calculates the physics of the flexible object. Note that it has to be 0
+// updated every time step. In the future, perhaps there could be an 
+// optimization similar to what Havok does for objects that are stationary. 
+//---------------------------------------------------------------------------------
+static LLFastTimer::DeclareTimer FTM_FLEXIBLE_UPDATE("Update Flexies");
+void LLVolumeImplFlexible::doIdleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
+{
+	LLDrawable* drawablep = mVO->mDrawable;
+
+	if (drawablep)
 	{
-		return FALSE; // (we are not initialized or updated)
-	}
+		//LLFastTimer ftm(FTM_FLEXIBLE_UPDATE);
 
-	bool visible = mVO->mDrawable->isVisible();
-
-	if (force_update && visible)
-	{
-		gPipeline.markRebuild(mVO->mDrawable, LLDrawable::REBUILD_POSITION, FALSE);
-	}
-	else if	(visible &&
-		!mVO->mDrawable->isState(LLDrawable::IN_REBUILD_Q1) &&
-		mVO->getPixelArea() > 256.f)
-	{
-		U32 id;
-		F32 pixel_area = mVO->getPixelArea();
-
-		if (mVO->isRootEdit())
+		//flexible objects never go static
+		drawablep->mQuietCount = 0;
+		if (!drawablep->isRoot())
 		{
-			id = mID;
-		}
-		else
-		{
-			LLVOVolume* parent = (LLVOVolume*) mVO->getParent();
-			id = parent->getVolumeInterfaceID();
+			LLViewerObject* parent = (LLViewerObject*) mVO->getParent();
+			parent->mDrawable->mQuietCount = 0;
 		}
 
-		U32 update_period = (U32) (LLViewerCamera::getInstance()->getScreenPixelArea()*0.01f/(pixel_area*(sUpdateFactor+1.f)))+1;
+		if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_FLEXIBLE))
+		{
+			bool visible = drawablep->isVisible();
 
-		if ((LLDrawable::getCurrentFrame()+id)%update_period == 0)
-		{
-			gPipeline.markRebuild(mVO->mDrawable, LLDrawable::REBUILD_POSITION, FALSE);
+			if ((mSimulateRes == 0) && visible)
+			{
+				updateRenderRes();
+				gPipeline.markRebuild(drawablep, LLDrawable::REBUILD_POSITION, FALSE);
+			}
+			else if	(visible &&
+				!drawablep->isState(LLDrawable::IN_REBUILD_Q1) &&
+				mVO->getPixelArea() > 256.f)
+			{
+				U32 id;
+				F32 pixel_area = mVO->getPixelArea();
+
+				if (mVO->isRootEdit())
+				{
+					id = mID;
+				}
+				else
+				{
+					LLVOVolume* parent = (LLVOVolume*) mVO->getParent();
+					id = parent->getVolumeInterfaceID();
+				}
+
+				U32 update_period = (U32) (LLViewerCamera::getInstance()->getScreenPixelArea()*0.01f/(pixel_area*(sUpdateFactor+1.f)))+1;
+
+				if ((LLDrawable::getCurrentFrame()+id)%update_period == 0)
+				{
+					updateRenderRes();
+					gPipeline.markRebuild(drawablep, LLDrawable::REBUILD_POSITION, FALSE);
+				}
+			}
 		}
 	}
-	
-	return force_update;
 }
 
 inline S32 log2(S32 x)

indra/newview/llflexibleobject.h

 		LLVector3 getFramePosition() const;
 		LLQuaternion getFrameRotation() const;
 		LLVolumeInterfaceType getInterfaceType() const		{ return INTERFACE_FLEXIBLE; }
-		BOOL doIdleUpdate(LLAgent &agent, LLWorld &world, const F64 &time);
+		void updateRenderRes();
+		void doIdleUpdate(LLAgent &agent, LLWorld &world, const F64 &time);
 		BOOL doUpdateGeometry(LLDrawable *drawable);
 		LLVector3 getPivotPosition() const;
 		void onSetVolume(const LLVolumeParams &volume_params, const S32 detail);
 		LLVector3					mCollisionSpherePosition;
 		F32							mCollisionSphereRadius;
 		U32							mID;
-
+		
 		//--------------------------------------
 		// private methods
 		//--------------------------------------

indra/newview/llfloaterland.cpp

 	BOOL allow_damage		= !self->mCheckSafe->get();
 	BOOL allow_fly			= self->mCheckFly->get();
 	BOOL allow_landmark		= TRUE; // cannot restrict landmark creation
-	BOOL allow_group_scripts	= self->mCheckGroupScripts->get() || self->mCheckOtherScripts->get();
 	BOOL allow_other_scripts	= self->mCheckOtherScripts->get();
+	BOOL allow_group_scripts	= self->mCheckGroupScripts->get() || allow_other_scripts;
 	BOOL allow_publish		= FALSE;
 	BOOL mature_publish		= self->mMatureCtrl->get();
 	BOOL push_restriction	= self->mPushRestrictionCtrl->get();
 	LLViewerRegion* region;
 	region = LLViewerParcelMgr::getInstance()->getSelectionRegion();
 
-	if (!allow_other_scripts && region && region->getAllowDamage())
-	{
-
-		LLNotificationsUtil::add("UnableToDisableOutsideScripts");
-		return;
+	if (region && region->getAllowDamage())
+	{	// Damage is allowed on the region - server will always allow scripts
+		if ( (!allow_other_scripts && parcel->getParcelFlag(PF_ALLOW_OTHER_SCRIPTS)) ||
+			 (!allow_group_scripts && parcel->getParcelFlag(PF_ALLOW_GROUP_SCRIPTS)) )
+		{	// Don't allow turning off "Run Scripts" if damage is allowed in the region
+			self->mCheckOtherScripts->set(parcel->getParcelFlag(PF_ALLOW_OTHER_SCRIPTS));	// Restore UI to actual settings
+			self->mCheckGroupScripts->set(parcel->getParcelFlag(PF_ALLOW_GROUP_SCRIPTS));
+			LLNotificationsUtil::add("UnableToDisableOutsideScripts");
+			return;
+		}
 	}
 
 	// Push data into current parcel

indra/newview/llphysicsmotion.cpp

 class LLPhysicsMotion
 {
 public:
+	typedef enum
+	{
+		SMOOTHING = 0,
+		MASS,
+		GRAVITY,
+		SPRING,
+		GAIN,
+		DAMPING,
+		DRAG,
+		MAX_EFFECT,
+		NUM_PARAMS
+	} eParamName;
+
         /*
           param_driver_name: The param that controls the params that are being affected by the physics.
           joint_name: The joint that the body part is attached to.  The joint is
                 mPositionLastUpdate_local(0)
         {
                 mJointState = new LLJointState;
+
+				for (U32 i = 0; i < NUM_PARAMS; ++i)
+				{
+					mParamCache[i] = NULL;
+				}
         }
 
         BOOL initialize();
                 return mJointState;
         }
 protected:
-        F32 getParamValue(const std::string& controller_key)
-        {
-                const controller_map_t::const_iterator& entry = mParamControllers.find(controller_key);
+
+		F32 getParamValue(eParamName param)
+		{
+			static std::string controller_key[] = 
+			{
+				"Smoothing",
+				"Mass",
+				"Gravity",
+				"Spring",
+				"Gain",
+				"Damping",
+				"Drag",
+				"MaxEffect"
+			};
+
+			if (!mParamCache[param])
+			{
+				const controller_map_t::const_iterator& entry = mParamControllers.find(controller_key[param]);
                 if (entry == mParamControllers.end())
                 {
-                        return sDefaultController[controller_key];
+                        return sDefaultController[controller_key[param]];
                 }
                 const std::string& param_name = (*entry).second.c_str();
-                return mCharacter->getVisualParamWeight(param_name.c_str());
-        }
+                mParamCache[param] = mCharacter->getVisualParam(param_name.c_str());
+			}
+				
+			if (mParamCache[param])
+			{
+				return mParamCache[param]->getWeight();
+			}
+			else
+			{
+				return sDefaultController[controller_key[param]];
+			}
+		}
+
+        
         void setParamValue(LLViewerVisualParam *param,
                            const F32 new_value_local,
                                                    F32 behavior_maxeffect);
 
         F32 mLastTime;
         
+		LLVisualParam* mParamCache[NUM_PARAMS];
+
         static default_controller_map_t sDefaultController;
 };
 
         return TRUE;
 }
 
-
 // Return TRUE if character has to update visual params.
 BOOL LLPhysicsMotion::onUpdate(F32 time)
 {
 
         LLJoint *joint = mJointState->getJoint();
 
-        const F32 behavior_mass = getParamValue("Mass");
-        const F32 behavior_gravity = getParamValue("Gravity");
-        const F32 behavior_spring = getParamValue("Spring");
-        const F32 behavior_gain = getParamValue("Gain");
-        const F32 behavior_damping = getParamValue("Damping");
-        const F32 behavior_drag = getParamValue("Drag");
-        const BOOL physics_test = FALSE; // Enable this to simulate bouncing on all parts.
+		const F32 behavior_mass = getParamValue(MASS);
+		const F32 behavior_gravity = getParamValue(GRAVITY);
+		const F32 behavior_spring = getParamValue(SPRING);
+		const F32 behavior_gain = getParamValue(GAIN);
+		const F32 behavior_damping = getParamValue(DAMPING);
+		const F32 behavior_drag = getParamValue(DRAG);
+		F32 behavior_maxeffect = getParamValue(MAX_EFFECT);
+		
+		const BOOL physics_test = FALSE; // Enable this to simulate bouncing on all parts.
         
-        F32 behavior_maxeffect = getParamValue("MaxEffect");
         if (physics_test)
                 behavior_maxeffect = 1.0f;
 

indra/newview/llpolymesh.cpp

 BOOL LLPolyMeshSharedData::allocateVertexData( U32 numVertices )
 {
         U32 i;
-        mBaseCoords = (LLVector3*) ll_aligned_malloc_16(numVertices*sizeof(LLVector3));
-        mBaseNormals = (LLVector3*) ll_aligned_malloc_16(numVertices*sizeof(LLVector3));
-        mBaseBinormals = (LLVector3*) ll_aligned_malloc_16(numVertices*sizeof(LLVector3));
+        mBaseCoords = (LLVector4a*) ll_aligned_malloc_16(numVertices*sizeof(LLVector4a));
+        mBaseNormals = (LLVector4a*) ll_aligned_malloc_16(numVertices*sizeof(LLVector4a));
+        mBaseBinormals = (LLVector4a*) ll_aligned_malloc_16(numVertices*sizeof(LLVector4a));
         mTexCoords = (LLVector2*) ll_aligned_malloc_16(numVertices*sizeof(LLVector2));
         mDetailTexCoords = (LLVector2*) ll_aligned_malloc_16(numVertices*sizeof(LLVector2));
         mWeights = (F32*) ll_aligned_malloc_16(numVertices*sizeof(F32));
         for (i = 0; i < numVertices; i++)
         {
-                mWeights[i] = 0.f;
+			mBaseCoords[i].clear();
+			mBaseNormals[i].clear();
+			mBaseBinormals[i].clear();
+			mWeights[i] = 0.f;
         }
         mNumVertices = numVertices;
         return TRUE;
 
                         allocateVertexData( numVertices );      
 
-                        //----------------------------------------------------------------
-                        // Coords
-                        //----------------------------------------------------------------
-                        numRead = fread(mBaseCoords, 3*sizeof(float), numVertices, fp);
-                        llendianswizzle(mBaseCoords, sizeof(float), 3*numVertices);
-                        if (numRead != numVertices)
-                        {
-                                llerrs << "can't read Coordinates from " << fileName << llendl;
-                                return FALSE;
-                        }
+						for (U16 i = 0; i < numVertices; ++i)
+						{
+							//----------------------------------------------------------------
+							// Coords
+							//----------------------------------------------------------------
+							numRead = fread(&mBaseCoords[i], sizeof(float), 3, fp);
+							llendianswizzle(&mBaseCoords[i], sizeof(float), 3);
+							if (numRead != 3)
+							{
+									llerrs << "can't read Coordinates from " << fileName << llendl;
+									return FALSE;
+							}
+						}
 
-                        //----------------------------------------------------------------
-                        // Normals
-                        //----------------------------------------------------------------
-                        numRead = fread(mBaseNormals, 3*sizeof(float), numVertices, fp);
-                        llendianswizzle(mBaseNormals, sizeof(float), 3*numVertices);
-                        if (numRead != numVertices)
-                        {
-                                llerrs << " can't read Normals from " << fileName << llendl;
-                                return FALSE;
-                        }
+						for (U16 i = 0; i < numVertices; ++i)
+						{
+							//----------------------------------------------------------------
+							// Normals
+							//----------------------------------------------------------------
+							numRead = fread(&mBaseNormals[i], sizeof(float), 3, fp);
+							llendianswizzle(&mBaseNormals[i], sizeof(float), 3);
+							if (numRead != 3)
+							{
+									llerrs << " can't read Normals from " << fileName << llendl;
+									return FALSE;
+							}
+						}
 
-                        //----------------------------------------------------------------
-                        // Binormals
-                        //----------------------------------------------------------------
-                        numRead = fread(mBaseBinormals, 3*sizeof(float), numVertices, fp);
-                        llendianswizzle(mBaseBinormals, sizeof(float), 3*numVertices);
-                        if (numRead != numVertices)
-                        {
-                                llerrs << " can't read Binormals from " << fileName << llendl;
-                                return FALSE;
-                        }
-
+						for (U16 i = 0; i < numVertices; ++i)
+						{
+							//----------------------------------------------------------------
+							// Binormals
+							//----------------------------------------------------------------
+							numRead = fread(&mBaseBinormals[i], sizeof(float), 3, fp);
+							llendianswizzle(&mBaseBinormals[i], sizeof(float), 3);
+							if (numRead != 3)
+							{
+									llerrs << " can't read Binormals from " << fileName << llendl;
+									return FALSE;
+							}
+						}
 
                         //----------------------------------------------------------------
                         // TexCoords
 	{
 		// Allocate memory without initializing every vector
 		// NOTE: This makes asusmptions about the size of LLVector[234]
-		int nverts = mSharedData->mNumVertices;
-		int nfloats = nverts * (2*4 + 3*3 + 2 + 4);
+		S32 nverts = mSharedData->mNumVertices;
+		//make sure it's an even number of verts for alignment
+		nverts += nverts%2;
+		S32 nfloats = nverts * (
+					4 + //coords
+					4 + //normals
+					4 + //weights
+					2 + //coords
+					4 + //scaled normals
+					4 + //binormals
+					4); //scaled binormals
+
 		//use 16 byte aligned vertex data to make LLPolyMesh SSE friendly
 		mVertexData = (F32*) ll_aligned_malloc_16(nfloats*4);
-		int offset = 0;
-		mCoords				= 	(LLVector4*)(mVertexData + offset); offset += 4*nverts;
-		mNormals			=	(LLVector4*)(mVertexData + offset); offset += 4*nverts;
-		mClothingWeights	= 	(LLVector4*)(mVertexData + offset); offset += 4*nverts;
-		mTexCoords			= 	(LLVector2*)(mVertexData + offset); offset += 2*nverts;
-
-		// these members don't need to be 16-byte aligned, but the first one might be
-		// read during an aligned memcpy of mTexCoords
-		mScaledNormals =                (LLVector3*)(mVertexData + offset); offset += 3*nverts;
-		mBinormals =                    (LLVector3*)(mVertexData + offset); offset += 3*nverts;
-		mScaledBinormals =              (LLVector3*)(mVertexData + offset); offset += 3*nverts; 
+		S32 offset = 0;
+		mCoords				= 	(LLVector4a*)(mVertexData + offset); offset += 4*nverts;
+		mNormals			=	(LLVector4a*)(mVertexData + offset); offset += 4*nverts;
+		mClothingWeights	= 	(LLVector4a*)(mVertexData + offset); offset += 4*nverts;
+		mTexCoords			= 	(LLVector2*)(mVertexData + offset);  offset += 2*nverts;
+		mScaledNormals		=   (LLVector4a*)(mVertexData + offset); offset += 4*nverts;
+		mBinormals			=   (LLVector4a*)(mVertexData + offset); offset += 4*nverts;
+		mScaledBinormals	=   (LLVector4a*)(mVertexData + offset); offset += 4*nverts; 
 		initializeForMorph();
 	}
 }
 //-----------------------------------------------------------------------------
 // getWritableCoords()
 //-----------------------------------------------------------------------------
-LLVector4 *LLPolyMesh::getWritableCoords()
+LLVector4a *LLPolyMesh::getWritableCoords()
 {
         return mCoords;
 }
 //-----------------------------------------------------------------------------
 // getWritableNormals()
 //-----------------------------------------------------------------------------
-LLVector4 *LLPolyMesh::getWritableNormals()
+LLVector4a *LLPolyMesh::getWritableNormals()
 {
         return mNormals;
 }
 //-----------------------------------------------------------------------------
 // getWritableBinormals()
 //-----------------------------------------------------------------------------
-LLVector3 *LLPolyMesh::getWritableBinormals()
+LLVector4a *LLPolyMesh::getWritableBinormals()
 {
         return mBinormals;
 }
 //-----------------------------------------------------------------------------
 // getWritableClothingWeights()
 //-----------------------------------------------------------------------------
-LLVector4       *LLPolyMesh::getWritableClothingWeights()
+LLVector4a       *LLPolyMesh::getWritableClothingWeights()
 {
         return mClothingWeights;
 }
 //-----------------------------------------------------------------------------
 // getScaledNormals()
 //-----------------------------------------------------------------------------
-LLVector3 *LLPolyMesh::getScaledNormals()
+LLVector4a *LLPolyMesh::getScaledNormals()
 {
         return mScaledNormals;
 }
 //-----------------------------------------------------------------------------
 // getScaledBinormals()
 //-----------------------------------------------------------------------------
-LLVector3 *LLPolyMesh::getScaledBinormals()
+LLVector4a *LLPolyMesh::getScaledBinormals()
 {
         return mScaledBinormals;
 }
 //-----------------------------------------------------------------------------
 void LLPolyMesh::initializeForMorph()
 {
-    for (U32 i = 0; i < mSharedData->mNumVertices; ++i)
+    LLVector4a::memcpyNonAliased16((F32*) mCoords, (F32*) mSharedData->mBaseCoords, sizeof(LLVector4a) * mSharedData->mNumVertices);
+	LLVector4a::memcpyNonAliased16((F32*) mNormals, (F32*) mSharedData->mBaseNormals, sizeof(LLVector4a) * mSharedData->mNumVertices);
+	LLVector4a::memcpyNonAliased16((F32*) mScaledNormals, (F32*) mSharedData->mBaseNormals, sizeof(LLVector4a) * mSharedData->mNumVertices);
+	LLVector4a::memcpyNonAliased16((F32*) mBinormals, (F32*) mSharedData->mBaseNormals, sizeof(LLVector4a) * mSharedData->mNumVertices);
+	LLVector4a::memcpyNonAliased16((F32*) mScaledBinormals, (F32*) mSharedData->mBaseNormals, sizeof(LLVector4a) * mSharedData->mNumVertices);
+	LLVector4a::memcpyNonAliased16((F32*) mTexCoords, (F32*) mSharedData->mTexCoords, sizeof(LLVector2) * (mSharedData->mNumVertices + mSharedData->mNumVertices%2));
+
+	for (U32 i = 0; i < mSharedData->mNumVertices; ++i)
 	{
-		mCoords[i] = LLVector4(mSharedData->mBaseCoords[i]);
-		mNormals[i] = LLVector4(mSharedData->mBaseNormals[i]);
+		mClothingWeights[i].clear();
 	}
-
-	memcpy(mScaledNormals, mSharedData->mBaseNormals, sizeof(LLVector3) * mSharedData->mNumVertices);	/*Flawfinder: ignore*/
-	memcpy(mBinormals, mSharedData->mBaseBinormals, sizeof(LLVector3) * mSharedData->mNumVertices);	/*Flawfinder: ignore*/
-	memcpy(mScaledBinormals, mSharedData->mBaseBinormals, sizeof(LLVector3) * mSharedData->mNumVertices);		/*Flawfinder: ignore*/
-	memcpy(mTexCoords, mSharedData->mTexCoords, sizeof(LLVector2) * mSharedData->mNumVertices);		/*Flawfinder: ignore*/
-	memset(mClothingWeights, 0, sizeof(LLVector4) * mSharedData->mNumVertices);
 }
 
 //-----------------------------------------------------------------------------
 LLPolySkeletalDistortion::LLPolySkeletalDistortion(LLVOAvatar *avatarp)
 {
         mAvatar = avatarp;
-        mDefaultVec.setVec(0.001f, 0.001f, 0.001f);
+        mDefaultVec.splat(0.001f);
 }
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 // apply()
 //-----------------------------------------------------------------------------
+static LLFastTimer::DeclareTimer FTM_POLYSKELETAL_DISTORTION_APPLY("Skeletal Distortion");
+
 void LLPolySkeletalDistortion::apply( ESex avatar_sex )
 {
+	LLFastTimer t(FTM_POLYSKELETAL_DISTORTION_APPLY);
+
         F32 effective_weight = ( getSex() & avatar_sex ) ? mCurWeight : getDefaultWeight();
 
         LLJoint* joint;
 {
         LLPolyMorphData* cloned_morph_data = new LLPolyMorphData(*src_data);
         cloned_morph_data->mName = name;
+		LLVector4a dir;
+		dir.load3(direction.mV);
+
         for (U32 v=0; v < cloned_morph_data->mNumIndices; v++)
         {
-                cloned_morph_data->mCoords[v] = direction;
-                cloned_morph_data->mNormals[v] = LLVector3(0,0,0);
-                cloned_morph_data->mBinormals[v] = LLVector3(0,0,0);
+                cloned_morph_data->mCoords[v] = dir;
+                cloned_morph_data->mNormals[v].clear();
+                cloned_morph_data->mBinormals[v].clear();
         }
         return cloned_morph_data;
 }
 {
         LLPolyMorphData* cloned_morph_data = new LLPolyMorphData(*src_data);
         cloned_morph_data->mName = name;
+
+		LLVector4a sc;
+		sc.splat(scale);
+
+		LLVector4a nsc;
+		nsc.set(scale, -scale, scale, scale);
+
         for (U32 v=0; v < cloned_morph_data->mNumIndices; v++)
         {
-                cloned_morph_data->mCoords[v] = src_data->mCoords[v]*scale;
-                cloned_morph_data->mNormals[v] = src_data->mNormals[v]*scale;
-                cloned_morph_data->mBinormals[v] = src_data->mBinormals[v]*scale;
-                if (cloned_morph_data->mCoords[v][1] < 0)
-                {
-                        cloned_morph_data->mCoords[v][1] *= -1;
-                        cloned_morph_data->mNormals[v][1] *= -1;
-                        cloned_morph_data->mBinormals[v][1] *= -1;
-                }
+            if (cloned_morph_data->mCoords[v][1] < 0)
+            {
+                cloned_morph_data->mCoords[v].setMul(src_data->mCoords[v],nsc);
+				cloned_morph_data->mNormals[v].setMul(src_data->mNormals[v],nsc);
+				cloned_morph_data->mBinormals[v].setMul(src_data->mBinormals[v],nsc);
+			}
+			else
+			{
+				cloned_morph_data->mCoords[v].setMul(src_data->mCoords[v],sc);
+				cloned_morph_data->mNormals[v].setMul(src_data->mNormals[v], sc);
+				cloned_morph_data->mBinormals[v].setMul(src_data->mBinormals[v],sc);
+			}
         }
         return cloned_morph_data;
 }

indra/newview/llpolymesh.h

 							
 	// vertex data			
 	S32						mNumVertices;
-	LLVector3				*mBaseCoords;
-	LLVector3				*mBaseNormals;
-	LLVector3				*mBaseBinormals;
+	LLVector4a				*mBaseCoords;
+	LLVector4a				*mBaseNormals;
+	LLVector4a				*mBaseBinormals;
 	LLVector2				*mTexCoords;
 	LLVector2				*mDetailTexCoords;
 	F32						*mWeights;
 	}
 
 	// Get coords
-	const LLVector4	*getCoords() const{
+	const LLVector4a	*getCoords() const{
 		return mCoords;
 	}
 
 	// non const version
-	LLVector4 *getWritableCoords();
+	LLVector4a *getWritableCoords();
 
 	// Get normals
-	const LLVector4	*getNormals() const{ 
+	const LLVector4a	*getNormals() const{ 
 		return mNormals; 
 	}
 
 	// Get normals
-	const LLVector3	*getBinormals() const{ 
+	const LLVector4a	*getBinormals() const{ 
 		return mBinormals; 
 	}
 
 	// Get base mesh normals
-	const LLVector3 *getBaseNormals() const{
+	const LLVector4a *getBaseNormals() const{
 		llassert(mSharedData);
 		return mSharedData->mBaseNormals;
 	}
 
 	// Get base mesh normals
-	const LLVector3 *getBaseBinormals() const{
+	const LLVector4a *getBaseBinormals() const{
 		llassert(mSharedData);
 		return mSharedData->mBaseBinormals;
 	}
 
 	// intermediate morphed normals and output normals
-	LLVector4 *getWritableNormals();
-	LLVector3 *getScaledNormals();
+	LLVector4a *getWritableNormals();
+	LLVector4a *getScaledNormals();
 
-	LLVector3 *getWritableBinormals();
-	LLVector3 *getScaledBinormals();
+	LLVector4a *getWritableBinormals();
+	LLVector4a *getScaledBinormals();
 
 	// Get texCoords
 	const LLVector2	*getTexCoords() const { 
 
 	F32			*getWritableWeights() const;
 
-	LLVector4	*getWritableClothingWeights();
+	LLVector4a	*getWritableClothingWeights();
 
-	const LLVector4		*getClothingWeights()
+	const LLVector4a		*getClothingWeights()
 	{
 		return mClothingWeights;	
 	}
 	// Single array of floats for allocation / deletion
 	F32						*mVertexData;
 	// deformed vertices (resulting from application of morph targets)
-	LLVector4				*mCoords;
+	LLVector4a				*mCoords;
 	// deformed normals (resulting from application of morph targets)
-	LLVector3				*mScaledNormals;
+	LLVector4a				*mScaledNormals;
 	// output normals (after normalization)
-	LLVector4				*mNormals;
+	LLVector4a				*mNormals;
 	// deformed binormals (resulting from application of morph targets)
-	LLVector3				*mScaledBinormals;
+	LLVector4a				*mScaledBinormals;
 	// output binormals (after normalization)