diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp
index df4c618ac10e187cad7aee71b970e880b970baae..ae5c9bc8cf0643c8df96b6d7e496aff056640ce0 100644
--- a/indra/llmath/llvolume.cpp
+++ b/indra/llmath/llvolume.cpp
@@ -4520,15 +4520,65 @@ BOOL LLVolumeFace::createUnCutCubeCap(LLVolume* volume, BOOL partial_build)
 
 	if (!partial_build)
 	{
-		int idxs[] = {0,1,(grid_size+1)+1,(grid_size+1)+1,(grid_size+1),0};
-		for(int gx = 0;gx<grid_size;gx++){
-			for(int gy = 0;gy<grid_size;gy++){
-				if (mTypeMask & TOP_MASK){
-					for(int i=5;i>=0;i--)mIndices.push_back(vtop+(gy*(grid_size+1))+gx+idxs[i]);
-				}else{
-					for(int i=0;i<6;i++)mIndices.push_back(vtop+(gy*(grid_size+1))+gx+idxs[i]);
+		mTriStrip.clear();
+		S32 idxs[] = {0,1,(grid_size+1)+1,(grid_size+1)+1,(grid_size+1),0};
+		for(S32 gx = 0;gx<grid_size;gx++)
+		{
+			
+			for(S32 gy = 0;gy<grid_size;gy++)
+			{
+				if (mTypeMask & TOP_MASK)
+				{
+					for(S32 i=5;i>=0;i--)
+					{
+						mIndices.push_back(vtop+(gy*(grid_size+1))+gx+idxs[i]);
+					}
+					
+					if (gy == 0)
+					{
+						mTriStrip.push_back((gx+1)*(grid_size+1));
+						mTriStrip.push_back((gx+1)*(grid_size+1));
+						mTriStrip.push_back(gx*(grid_size+1));
+					}
+
+					mTriStrip.push_back(gy+1+(gx+1)*(grid_size+1));
+					mTriStrip.push_back(gy+1+gx*(grid_size+1));
+					
+					
+					if (gy == grid_size-1)
+					{
+						mTriStrip.push_back(gy+1+gx*(grid_size+1));
+					}
+				}
+				else
+				{
+					for(S32 i=0;i<6;i++)
+					{
+						mIndices.push_back(vtop+(gy*(grid_size+1))+gx+idxs[i]);
+					}
+
+					if (gy == 0)
+					{
+						mTriStrip.push_back(gx*(grid_size+1));
+						mTriStrip.push_back(gx*(grid_size+1));
+						mTriStrip.push_back((gx+1)*(grid_size+1));
+					}
+
+					mTriStrip.push_back(gy+1+gx*(grid_size+1));
+					mTriStrip.push_back(gy+1+(gx+1)*(grid_size+1));
+					
+					if (gy == grid_size-1)
+					{
+						mTriStrip.push_back(gy+1+(gx+1)*(grid_size+1));
+					}
 				}
 			}
+			
+		}
+
+		if (mTriStrip.size()%2 == 1)
+		{
+			mTriStrip.push_back(mTriStrip[mTriStrip.size()-1]);
 		}
 	}
 		
@@ -4770,6 +4820,8 @@ BOOL LLVolumeFace::createCap(LLVolume* volume, BOOL partial_build)
 					pt2--;
 				}
 			}
+
+			makeTriStrip();
 		}
 		else
 		{
@@ -4874,67 +4926,108 @@ BOOL LLVolumeFace::createCap(LLVolume* volume, BOOL partial_build)
 					pt2--;
 				}
 			}
+
+			makeTriStrip();
 		}
 	}
 	else
 	{
 		// Not hollow, generate the triangle fan.
+		U16 v1 = 2;
+		U16 v2 = 1;
+
 		if (mTypeMask & TOP_MASK)
 		{
-			if (mTypeMask & OPEN_MASK)
-			{
-				// SOLID OPEN TOP
-				// Generate indices
-				// This is a tri-fan, so we reuse the same first point for all triangles.
-				for (S32 i = 0; i < (num_vertices - 2); i++)
-				{
-					mIndices[3*i] = num_vertices - 1;
-					mIndices[3*i+1] = i;
-					mIndices[3*i+2] = i + 1;
-				}
-			}
-			else
-			{
-				// SOLID CLOSED TOP
-				for (S32 i = 0; i < (num_vertices - 2); i++)
-				{				
-					//MSMSM fix these caps but only for the un-cut case
-					mIndices[3*i] = num_vertices - 1;
-					mIndices[3*i+1] = i;
-					mIndices[3*i+2] = i + 1;
-				}
-			}
+			v1 = 1;
+			v2 = 2;
+		}
+
+		for (S32 i = 0; i < (num_vertices - 2); i++)
+		{
+			mIndices[3*i] = num_vertices - 1;
+			mIndices[3*i+v1] = i;
+			mIndices[3*i+v2] = i + 1;
+		}
+
+		//make tri strip
+		if (mTypeMask & OPEN_MASK)
+		{
+			makeTriStrip();
 		}
 		else
 		{
-			if (mTypeMask & OPEN_MASK)
+			S32 j = num_vertices-2;
+			if (mTypeMask & TOP_MASK)
 			{
-				// SOLID OPEN BOTTOM
-				// Generate indices
-				// This is a tri-fan, so we reuse the same first point for all triangles.
-				for (S32 i = 0; i < (num_vertices - 2); i++)
+				mTriStrip.push_back(0);
+				for (S32 i = 0; i <= j; ++i)
 				{
-					mIndices[3*i] = num_vertices - 1;
-					mIndices[3*i+1] = i + 1;
-					mIndices[3*i+2] = i;
+					mTriStrip.push_back(i);
+					if (i != j)
+					{
+						mTriStrip.push_back(j);
+					}
+					--j;
 				}
 			}
 			else
 			{
-				// SOLID CLOSED BOTTOM
-				for (S32 i = 0; i < (num_vertices - 2); i++)
+				mTriStrip.push_back(j);
+				for (S32 i = 0; i <= j; ++i)
 				{
-					//MSMSM fix these caps but only for the un-cut case
-					mIndices[3*i] = num_vertices - 1;
-					mIndices[3*i+1] = i + 1;
-					mIndices[3*i+2] = i;
+					if (i != j)
+					{
+						mTriStrip.push_back(j);
+					}
+					mTriStrip.push_back(i);
+					--j;
 				}
 			}
+			
+			mTriStrip.push_back(mTriStrip[mTriStrip.size()-1]);
+
+			if (mTriStrip.size()%2 == 1)
+			{
+				mTriStrip.push_back(mTriStrip[mTriStrip.size()-1]);
+			}
 		}
 	}
+		
 	return TRUE;
 }
 
+void LLVolumeFace::makeTriStrip()
+{
+	for (U32 i = 0; i < mIndices.size(); i+=3)
+	{
+		U16 i0 = mIndices[i];
+		U16 i1 = mIndices[i+1];
+		U16 i2 = mIndices[i+2];
+
+		if ((i/3)%2 == 1)
+		{
+			mTriStrip.push_back(i0);
+			mTriStrip.push_back(i0);
+			mTriStrip.push_back(i1);
+			mTriStrip.push_back(i2);
+			mTriStrip.push_back(i2);
+		}
+		else
+		{
+			mTriStrip.push_back(i2);
+			mTriStrip.push_back(i2);
+			mTriStrip.push_back(i1);
+			mTriStrip.push_back(i0);
+			mTriStrip.push_back(i0);
+		}
+	}
+
+	if (mTriStrip.size()%2 == 1)
+	{
+		mTriStrip.push_back(mTriStrip[mTriStrip.size()-1]);
+	}
+}
+
 void LLVolumeFace::createBinormals()
 {
 	LLMemType m1(LLMemType::MTYPE_VOLUME);
@@ -5135,9 +5228,14 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build)
 
 	if (!partial_build)
 	{
+		mTriStrip.clear();
+
 		// Now we generate the indices.
 		for (t = 0; t < (mNumT-1); t++)
 		{
+			//prepend terminating index to strip
+			mTriStrip.push_back(mNumS*t);
+
 			for (s = 0; s < (mNumS-1); s++)
 			{	
 				mIndices[cur_index++] = s   + mNumS*t;			//bottom left
@@ -5147,6 +5245,14 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build)
 				mIndices[cur_index++] = s+1 + mNumS*t;			//bottom right
 				mIndices[cur_index++] = s+1 + mNumS*(t+1);		//top right
 
+				if (s == 0)
+				{
+					mTriStrip.push_back(s+mNumS*t);
+					mTriStrip.push_back(s+mNumS*(t+1));
+				}
+				mTriStrip.push_back(s+1+mNumS*t);
+				mTriStrip.push_back(s+1+mNumS*(t+1));
+				
 				mEdge[cur_edge++] = (mNumS-1)*2*t+s*2+1;						//bottom left/top right neighbor face 
 				if (t < mNumT-2) {												//top right/top left neighbor face 
 					mEdge[cur_edge++] = (mNumS-1)*2*(t+1)+s*2+1;
@@ -5187,6 +5293,13 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build)
 				}
 				mEdge[cur_edge++] = (mNumS-1)*2*t+s*2;							//top right/bottom left neighbor face	
 			}
+			//append terminating vertex to strip
+			mTriStrip.push_back(mNumS-1+mNumS*(t+1));
+		}
+
+		if (mTriStrip.size()%2 == 1)
+		{
+			mTriStrip.push_back(mTriStrip[mTriStrip.size()-1]);
 		}
 	}
 
diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h
index 871b334452180ca76160900b6961b015eb4874dd..d9f80f0e30e5d099294b0862aa187d94409e1446 100644
--- a/indra/llmath/llvolume.h
+++ b/indra/llmath/llvolume.h
@@ -798,7 +798,8 @@ class LLVolumeFace
 
 	BOOL create(LLVolume* volume, BOOL partial_build = FALSE);
 	void createBinormals();
-
+	void makeTriStrip();
+	
 	class VertexData
 	{
 	public:
@@ -839,6 +840,7 @@ class LLVolumeFace
 
 	std::vector<VertexData> mVertices;
 	std::vector<U16>	mIndices;
+	std::vector<U16>	mTriStrip;
 	std::vector<S32>	mEdge;
 
 private:
diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp
index b6a6b448eee7cbe9c13f022104366dac07618d3e..25f8320b028d7efc527ebad944e6f5830792caf8 100644
--- a/indra/llrender/llfontgl.cpp
+++ b/indra/llrender/llfontgl.cpp
@@ -151,14 +151,16 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
 		}
 	}
 
-	gGL.pushMatrix();
-	glLoadIdentity();
-	gGL.translatef(floorf(sCurOrigin.mX*sScaleX), floorf(sCurOrigin.mY*sScaleY), sCurOrigin.mZ);
+	gGL.pushUIMatrix();
+
+	gGL.loadUIIdentity();
+	
+	gGL.translateUI(floorf(sCurOrigin.mX*sScaleX), floorf(sCurOrigin.mY*sScaleY), sCurOrigin.mZ);
 
 	// this code snaps the text origin to a pixel grid to start with
 	F32 pixel_offset_x = llround((F32)sCurOrigin.mX) - (sCurOrigin.mX);
 	F32 pixel_offset_y = llround((F32)sCurOrigin.mY) - (sCurOrigin.mY);
-	gGL.translatef(-pixel_offset_x, -pixel_offset_y, 0.f);
+	gGL.translateUI(-pixel_offset_x, -pixel_offset_y, 0.f);
 
 	LLFastTimer t(FTM_RENDER_FONTS);
 
@@ -246,9 +248,6 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
 	}
 
 
-	// Remember last-used texture to avoid unnecesssary bind calls.
-	LLImageGL *last_bound_texture = NULL;
-
 	for (i = begin_offset; i < begin_offset + length; i++)
 	{
 		llwchar wch = wstr[i];
@@ -261,12 +260,8 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
 		}
 		// Per-glyph bitmap texture.
 		LLImageGL *image_gl = mFontFreetype->getFontBitmapCache()->getImageGL(fgi->mBitmapNum);
-		if (last_bound_texture != image_gl)
-		{
-			gGL.getTexUnit(0)->bind(image_gl);
-			last_bound_texture = image_gl;
-		}
-
+		gGL.getTexUnit(0)->bind(image_gl);
+	
 		if ((start_x + scaled_max_pixels) < (cur_x + fgi->mXBearing + fgi->mWidth))
 		{
 			// Not enough room for this character.
@@ -330,10 +325,7 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
 		
 		// recursively render ellipses at end of string
 		// we've already reserved enough room
-		gGL.pushMatrix();
-		//glLoadIdentity();
-		//gGL.translatef(sCurOrigin.mX, sCurOrigin.mY, 0.0f);
-		//glScalef(sScaleX, sScaleY, 1.f);
+		gGL.pushUIMatrix();
 		renderUTF8(std::string("..."), 
 				0,
 				cur_x / sScaleX, (F32)y,
@@ -344,10 +336,10 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
 				S32_MAX, max_pixels,
 				right_x,
 				FALSE); 
-		gGL.popMatrix();
+		gGL.popUIMatrix();
 	}
 
-	gGL.popMatrix();
+	gGL.popUIMatrix();
 
 	return chars_drawn;
 }
diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp
index 595b8577ffee4008372f36e292310bce635aced1..c11675fa48cf226eb8c18a60bb4d9e1759799039 100644
--- a/indra/llrender/llrender.cpp
+++ b/indra/llrender/llrender.cpp
@@ -49,6 +49,9 @@ F64 gGLLastProjection[16];
 F64 gGLProjection[16];
 S32	gGLViewport[4];
 
+U32 LLRender::sUICalls = 0;
+U32 LLRender::sUIVerts = 0;
+
 static const U32 LL_NUM_TEXTURE_LAYERS = 16; 
 
 static GLenum sGLTextureType[] =
@@ -255,10 +258,9 @@ bool LLTexUnit::bind(LLImageGL* texture, bool for_rendering, bool forceBind)
 		return false ;
 	}
 
-	gGL.flush();
-
 	if ((mCurrTexture != texture->getTexName()) || forceBind)
 	{
+		gGL.flush();
 		activate();
 		enable(texture->getTarget());
 		mCurrTexture = texture->getTexName();
@@ -445,6 +447,8 @@ void LLTexUnit::setTextureBlendType(eTextureBlendType type)
 		return;
 	}
 
+	gGL.flush();
+
 	activate();
 	mCurrBlendType = type;
 	S32 scale_amount = 1;
@@ -759,6 +763,8 @@ LLRender::LLRender()
 
 	mCurrAlphaFunc = CF_DEFAULT;
 	mCurrAlphaFuncVal = 0.01f;
+	mCurrBlendSFactor = BF_SOURCE_ALPHA;
+	mCurrBlendDFactor = BF_ONE_MINUS_SOURCE_ALPHA;
 }
 
 LLRender::~LLRender()
@@ -821,6 +827,80 @@ void LLRender::popMatrix()
 	glPopMatrix();
 }
 
+void LLRender::translateUI(F32 x, F32 y, F32 z)
+{
+	if (mUIOffset.empty())
+	{
+		llerrs << "Need to push a UI translation frame before offsetting" << llendl;
+	}
+
+	mUIOffset.front().mV[0] += x;
+	mUIOffset.front().mV[1] += y;
+	mUIOffset.front().mV[2] += z;
+}
+
+void LLRender::scaleUI(F32 x, F32 y, F32 z)
+{
+	if (mUIScale.empty())
+	{
+		llerrs << "Need to push a UI transformation frame before scaling." << llendl;
+	}
+
+	mUIScale.front().scaleVec(LLVector3(x,y,z));
+}
+
+void LLRender::pushUIMatrix()
+{
+	mUIOffset.push_front(mUIOffset.front());
+	if (mUIScale.empty())
+	{
+		mUIScale.push_front(LLVector3(1,1,1));
+	}
+	else
+	{
+		mUIScale.push_front(mUIScale.front());
+	}
+}
+
+void LLRender::popUIMatrix()
+{
+	if (mUIOffset.empty())
+	{
+		llerrs << "UI offset stack blown." << llendl;
+	}
+	mUIOffset.pop_front();
+	mUIScale.pop_front();
+}
+
+LLVector3 LLRender::getUITranslation()
+{
+	if (mUIOffset.empty())
+	{
+		llerrs << "UI offset stack empty." << llendl;
+	}
+	return mUIOffset.front();
+}
+
+LLVector3 LLRender::getUIScale()
+{
+	if (mUIScale.empty())
+	{
+		llerrs << "UI scale stack empty." << llendl;
+	}
+	return mUIScale.front();
+}
+
+
+void LLRender::loadUIIdentity()
+{
+	if (mUIOffset.empty())
+	{
+		llerrs << "Need to push UI translation frame before clearing offset." << llendl;
+	}
+	mUIOffset.front().setVec(0,0,0);
+	mUIScale.front().setVec(1,1,1);
+}
+
 void LLRender::setColorMask(bool writeColor, bool writeAlpha)
 {
 	setColorMask(writeColor, writeColor, writeColor, writeAlpha);
@@ -843,29 +923,28 @@ void LLRender::setColorMask(bool writeColorR, bool writeColorG, bool writeColorB
 
 void LLRender::setSceneBlendType(eBlendType type)
 {
-	flush();
 	switch (type) 
 	{
 		case BT_ALPHA:
-			glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+			blendFunc(BF_SOURCE_ALPHA, BF_ONE_MINUS_SOURCE_ALPHA);
 			break;
 		case BT_ADD:
-			glBlendFunc(GL_ONE, GL_ONE);
+			blendFunc(BF_ONE, BF_ONE);
 			break;
 		case BT_ADD_WITH_ALPHA:
-			glBlendFunc(GL_SRC_ALPHA, GL_ONE);
+			blendFunc(BF_SOURCE_ALPHA, BF_ONE);
 			break;
 		case BT_MULT:
-			glBlendFunc(GL_DST_COLOR, GL_ZERO);
+			blendFunc(BF_DEST_COLOR, BF_ZERO);
 			break;
 		case BT_MULT_ALPHA:
-			glBlendFunc(GL_DST_ALPHA, GL_ZERO);
+			blendFunc(BF_DEST_ALPHA, BF_ZERO);
 			break;
 		case BT_MULT_X2:
-			glBlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
+			blendFunc(BF_DEST_COLOR, BF_SOURCE_COLOR);
 			break;
 		case BT_REPLACE:
-			glBlendFunc(GL_ONE, GL_ZERO);
+			blendFunc(BF_ONE, BF_ZERO);
 			break;
 		default:
 			llerrs << "Unknown Scene Blend Type: " << type << llendl;
@@ -891,8 +970,13 @@ void LLRender::setAlphaRejectSettings(eCompareFunc func, F32 value)
 
 void LLRender::blendFunc(eBlendFactor sfactor, eBlendFactor dfactor)
 {
-	flush();
-	glBlendFunc(sGLBlendFactor[sfactor], sGLBlendFactor[dfactor]);
+	if (mCurrBlendSFactor != sfactor || mCurrBlendDFactor != dfactor)
+	{
+		mCurrBlendSFactor = sfactor;
+		mCurrBlendDFactor = dfactor;
+		flush();
+		glBlendFunc(sGLBlendFactor[sfactor], sGLBlendFactor[dfactor]);
+	}
 }
 
 LLTexUnit* LLRender::getTexUnit(U32 index)
@@ -1012,6 +1096,12 @@ void LLRender::flush()
 		}
 #endif
 				
+		if (!mUIOffset.empty())
+		{
+			sUICalls++;
+			sUIVerts += mCount;
+		}
+
 		mBuffer->setBuffer(immediate_mask);
 		mBuffer->drawArrays(mMode, 0, mCount);
 		
@@ -1031,7 +1121,16 @@ void LLRender::vertex3f(const GLfloat& x, const GLfloat& y, const GLfloat& z)
 		return;
 	}
 
-	mVerticesp[mCount] = LLVector3(x,y,z);
+	if (mUIOffset.empty())
+	{
+		mVerticesp[mCount] = LLVector3(x,y,z);
+	}
+	else
+	{
+		LLVector3 vert = (LLVector3(x,y,z)+mUIOffset.front()).scaledVec(mUIScale.front());
+		mVerticesp[mCount] = vert;
+	}
+
 	mCount++;
 	if (mCount < 4096)
 	{
diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h
index 0121a190ee5d052b5ae3d6fe2d412c75eb56a15d..a70ccf4d80560b1953a1eb9a63896c67eebc90fb 100644
--- a/indra/llrender/llrender.h
+++ b/indra/llrender/llrender.h
@@ -286,6 +286,14 @@ class LLRender
 	void pushMatrix();
 	void popMatrix();
 
+	void translateUI(F32 x, F32 y, F32 z);
+	void scaleUI(F32 x, F32 y, F32 z);
+	void pushUIMatrix();
+	void popUIMatrix();
+	void loadUIIdentity();
+	LLVector3 getUITranslation();
+	LLVector3 getUIScale();
+
 	void flush();
 
 	void begin(const GLuint& mode);
@@ -333,7 +341,9 @@ class LLRender
 	};
 
 public:
-
+	static U32 sUICalls;
+	static U32 sUIVerts;
+	
 private:
 	bool				mDirty;
 	U32				mCount;
@@ -350,7 +360,14 @@ class LLRender
 	std::vector<LLTexUnit*>		mTexUnits;
 	LLTexUnit*			mDummyTexUnit;
 
+	U32				mCurrBlendSFactor;
+	U32				mCurrBlendDFactor;
+
 	F32				mMaxAnisotropy;
+
+	std::list<LLVector3> mUIOffset;
+	std::list<LLVector3> mUIScale;
+
 };
 
 extern F64 gGLModelView[16];
diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp
index d9520b3bf63c1f226bb65244bb50904b4a51ee2f..3f2558f1f5e2d1af1d9816dd1e06fb1ade95433a 100644
--- a/indra/llrender/llrendertarget.cpp
+++ b/indra/llrender/llrendertarget.cpp
@@ -390,8 +390,6 @@ void LLRenderTarget::flush(BOOL fetch_depth)
 	}
 	else
 	{
-#if !LL_DARWIN
-
 		stop_glerror();
 
 		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
@@ -435,7 +433,6 @@ void LLRenderTarget::flush(BOOL fetch_depth)
 				}
 			}
 		}
-#endif
 
 		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
 	}
@@ -444,7 +441,6 @@ void LLRenderTarget::flush(BOOL fetch_depth)
 void LLRenderTarget::copyContents(LLRenderTarget& source, S32 srcX0, S32 srcY0, S32 srcX1, S32 srcY1,
 						S32 dstX0, S32 dstY0, S32 dstX1, S32 dstY1, U32 mask, U32 filter)
 {
-#if !LL_DARWIN
 	gGL.flush();
 	if (!source.mFBO || !mFBO)
 	{
@@ -483,14 +479,12 @@ void LLRenderTarget::copyContents(LLRenderTarget& source, S32 srcX0, S32 srcY0,
 			stop_glerror();
 		}
 	}
-#endif
 }
 
 //static
 void LLRenderTarget::copyContentsToFramebuffer(LLRenderTarget& source, S32 srcX0, S32 srcY0, S32 srcX1, S32 srcY1,
 						S32 dstX0, S32 dstY0, S32 dstX1, S32 dstY1, U32 mask, U32 filter)
 {
-#if !LL_DARWIN
 	if (!source.mFBO)
 	{
 		llerrs << "Cannot copy framebuffer contents for non FBO render targets." << llendl;
@@ -507,7 +501,6 @@ void LLRenderTarget::copyContentsToFramebuffer(LLRenderTarget& source, S32 srcX0
 		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
 		stop_glerror();
 	}
-#endif
 }
 
 BOOL LLRenderTarget::isComplete() const
@@ -652,7 +645,6 @@ void LLMultisampleBuffer::allocate(U32 resx, U32 resy, U32 color_fmt, BOOL depth
 
 void LLMultisampleBuffer::addColorAttachment(U32 color_fmt)
 {
-#if !LL_DARWIN
 	if (color_fmt == 0)
 	{
 		return;
@@ -693,12 +685,10 @@ void LLMultisampleBuffer::addColorAttachment(U32 color_fmt)
 	}
 
 	mTex.push_back(tex);
-#endif
 }
 
 void LLMultisampleBuffer::allocateDepth()
 {
-#if !LL_DARWIN
 	glGenRenderbuffersEXT(1, (GLuint* ) &mDepth);
 	glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, mDepth);
 	if (mStencil)
@@ -709,6 +699,5 @@ void LLMultisampleBuffer::allocateDepth()
 	{
 		glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, mSamples, GL_DEPTH_COMPONENT16_ARB, mResX, mResY);	
 	}
-#endif
 }
 
diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp
index 19408989a535a6e0f60ef82cab3ae4b0f810b94f..74043ad8839f494bb984c030bbf0327c515f96ba 100644
--- a/indra/llui/lltabcontainer.cpp
+++ b/indra/llui/lltabcontainer.cpp
@@ -489,15 +489,15 @@ void LLTabContainer::draw()
 		if( mIsVertical && has_scroll_arrows )
 		{
 			// Redraw the arrows so that they appears on top.
-			gGL.pushMatrix();
-			gGL.translatef((F32)mPrevArrowBtn->getRect().mLeft, (F32)mPrevArrowBtn->getRect().mBottom, 0.f);
+			gGL.pushUIMatrix();
+			gGL.translateUI((F32)mPrevArrowBtn->getRect().mLeft, (F32)mPrevArrowBtn->getRect().mBottom, 0.f);
 			mPrevArrowBtn->draw();
-			gGL.popMatrix();
+			gGL.popUIMatrix();
 
-			gGL.pushMatrix();
-			gGL.translatef((F32)mNextArrowBtn->getRect().mLeft, (F32)mNextArrowBtn->getRect().mBottom, 0.f);
+			gGL.pushUIMatrix();
+			gGL.translateUI((F32)mNextArrowBtn->getRect().mLeft, (F32)mNextArrowBtn->getRect().mBottom, 0.f);
 			mNextArrowBtn->draw();
-			gGL.popMatrix();
+			gGL.popUIMatrix();
 		}
 	}
 
diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp
index 76f07373b4413261fb0ce35c89b4bfa33428c6b2..852a19660a09c2bc4a2484f41ca357cc28db6d8e 100644
--- a/indra/llui/llui.cpp
+++ b/indra/llui/llui.cpp
@@ -39,6 +39,7 @@
 
 // Linden library includes
 #include "v2math.h"
+#include "m3math.h"
 #include "v4color.h"
 #include "llrender.h"
 #include "llrect.h"
@@ -180,19 +181,19 @@ void gl_rect_2d_offset_local( S32 left, S32 top, S32 right, S32 bottom, const LL
 
 void gl_rect_2d_offset_local( S32 left, S32 top, S32 right, S32 bottom, S32 pixel_offset, BOOL filled)
 {
-	gGL.pushMatrix();
+	gGL.pushUIMatrix();
 	left += LLFontGL::sCurOrigin.mX;
 	right += LLFontGL::sCurOrigin.mX;
 	bottom += LLFontGL::sCurOrigin.mY;
 	top += LLFontGL::sCurOrigin.mY;
 
-	glLoadIdentity();
+	gGL.loadUIIdentity();
 	gl_rect_2d(llfloor((F32)left * LLUI::sGLScaleFactor.mV[VX]) - pixel_offset,
 				llfloor((F32)top * LLUI::sGLScaleFactor.mV[VY]) + pixel_offset,
 				llfloor((F32)right * LLUI::sGLScaleFactor.mV[VX]) + pixel_offset,
 				llfloor((F32)bottom * LLUI::sGLScaleFactor.mV[VY]) - pixel_offset,
 				filled);
-	gGL.popMatrix();
+	gGL.popUIMatrix();
 }
 
 
@@ -508,9 +509,9 @@ void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTex
 		gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_MULT, LLTexUnit::TBS_TEX_ALPHA, LLTexUnit::TBS_VERT_ALPHA);
 	}
 
-	gGL.pushMatrix();
+	gGL.pushUIMatrix();
 	{
-		gGL.translatef((F32)x, (F32)y, 0.f);
+		gGL.translateUI((F32)x, (F32)y, 0.f);
 
 		gGL.getTexUnit(0)->bind(image);
 
@@ -637,7 +638,7 @@ void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTex
 		}
 		gGL.end();
 	}
-	gGL.popMatrix();
+	gGL.popUIMatrix();
 
 	if (solid_color)
 	{
@@ -660,39 +661,72 @@ void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degre
 
 	LLGLSUIDefault gls_ui;
 
-	gGL.pushMatrix();
+
+	gGL.getTexUnit(0)->bind(image);
+
+	gGL.color4fv(color.mV);
+
+	if (degrees == 0.f)
 	{
-		gGL.translatef((F32)x, (F32)y, 0.f);
-		if( degrees )
+		gGL.pushUIMatrix();
+		gGL.translateUI((F32)x, (F32)y, 0.f);
+			
+		gGL.begin(LLRender::QUADS);
 		{
-			F32 offset_x = F32(width/2);
-			F32 offset_y = F32(height/2);
-			gGL.translatef( offset_x, offset_y, 0.f);
-			glRotatef( degrees, 0.f, 0.f, 1.f );
-			gGL.translatef( -offset_x, -offset_y, 0.f );
+			gGL.texCoord2f(uv_rect.mRight, uv_rect.mTop);
+			gGL.vertex2i(width, height );
+
+			gGL.texCoord2f(uv_rect.mLeft, uv_rect.mTop);
+			gGL.vertex2i(0, height );
+
+			gGL.texCoord2f(uv_rect.mLeft, uv_rect.mBottom);
+			gGL.vertex2i(0, 0);
+
+			gGL.texCoord2f(uv_rect.mRight, uv_rect.mBottom);
+			gGL.vertex2i(width, 0);
 		}
+		gGL.end();
+		gGL.popUIMatrix();
+	}
+	else
+	{
+		gGL.pushUIMatrix();
+		gGL.translateUI((F32)x, (F32)y, 0.f);
+	
+		F32 offset_x = F32(width/2);
+		F32 offset_y = F32(height/2);
+
+		gGL.translateUI(offset_x, offset_y, 0.f);
 
+		LLMatrix3 quat(0.f, 0.f, degrees*DEG_TO_RAD);
+		
 		gGL.getTexUnit(0)->bind(image);
 
 		gGL.color4fv(color.mV);
 		
 		gGL.begin(LLRender::QUADS);
 		{
+			LLVector3 v;
+
+			v = LLVector3(offset_x, offset_y, 0.f) * quat;
 			gGL.texCoord2f(uv_rect.mRight, uv_rect.mTop);
-			gGL.vertex2i(width, height );
+			gGL.vertex2i(v.mV[0], v.mV[1] );
 
+			v = LLVector3(-offset_x, offset_y, 0.f) * quat;
 			gGL.texCoord2f(uv_rect.mLeft, uv_rect.mTop);
-			gGL.vertex2i(0, height );
+			gGL.vertex2i(v.mV[0], v.mV[1] );
 
+			v = LLVector3(-offset_x, -offset_y, 0.f) * quat;
 			gGL.texCoord2f(uv_rect.mLeft, uv_rect.mBottom);
-			gGL.vertex2i(0, 0);
+			gGL.vertex2i(v.mV[0], v.mV[1] );
 
+			v = LLVector3(offset_x, -offset_y, 0.f) * quat;
 			gGL.texCoord2f(uv_rect.mRight, uv_rect.mBottom);
-			gGL.vertex2i(width, 0);
+			gGL.vertex2i(v.mV[0], v.mV[1] );
 		}
 		gGL.end();
+		gGL.popUIMatrix();
 	}
-	gGL.popMatrix();
 }
 
 
@@ -747,9 +781,9 @@ void gl_arc_2d(F32 center_x, F32 center_y, F32 radius, S32 steps, BOOL filled, F
 		end_angle += F_TWO_PI;
 	}
 
-	gGL.pushMatrix();
+	gGL.pushUIMatrix();
 	{
-		gGL.translatef(center_x, center_y, 0.f);
+		gGL.translateUI(center_x, center_y, 0.f);
 
 		// Inexact, but reasonably fast.
 		F32 delta = (end_angle - start_angle) / steps;
@@ -780,15 +814,15 @@ void gl_arc_2d(F32 center_x, F32 center_y, F32 radius, S32 steps, BOOL filled, F
 		}
 		gGL.end();
 	}
-	gGL.popMatrix();
+	gGL.popUIMatrix();
 }
 
 void gl_circle_2d(F32 center_x, F32 center_y, F32 radius, S32 steps, BOOL filled)
 {
-	gGL.pushMatrix();
+	gGL.pushUIMatrix();
 	{
 		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-		gGL.translatef(center_x, center_y, 0.f);
+		gGL.translateUI(center_x, center_y, 0.f);
 
 		// Inexact, but reasonably fast.
 		F32 delta = F_TWO_PI / steps;
@@ -819,7 +853,7 @@ void gl_circle_2d(F32 center_x, F32 center_y, F32 radius, S32 steps, BOOL filled
 		}
 		gGL.end();
 	}
-	gGL.popMatrix();
+	gGL.popUIMatrix();
 }
 
 // Renders a ring with sides (tube shape)
@@ -846,9 +880,9 @@ void gl_deep_circle( F32 radius, F32 depth, S32 steps )
 
 void gl_ring( F32 radius, F32 width, const LLColor4& center_color, const LLColor4& side_color, S32 steps, BOOL render_center )
 {
-	gGL.pushMatrix();
+	gGL.pushUIMatrix();
 	{
-		gGL.translatef(0.f, 0.f, -width / 2);
+		gGL.translateUI(0.f, 0.f, -width / 2);
 		if( render_center )
 		{
 			gGL.color4fv(center_color.mV);
@@ -857,11 +891,11 @@ void gl_ring( F32 radius, F32 width, const LLColor4& center_color, const LLColor
 		else
 		{
 			gl_washer_2d(radius, radius - width, steps, side_color, side_color);
-			gGL.translatef(0.f, 0.f, width);
+			gGL.translateUI(0.f, 0.f, width);
 			gl_washer_2d(radius - width, radius, steps, side_color, side_color);
 		}
 	}
-	gGL.popMatrix();
+	gGL.popUIMatrix();
 }
 
 // Draw gray and white checkerboard with black border
@@ -1050,9 +1084,9 @@ void gl_segmented_rect_2d_tex(const S32 left,
 	S32 width = llabs(right - left);
 	S32 height = llabs(top - bottom);
 
-	gGL.pushMatrix();
+	gGL.pushUIMatrix();
 
-	gGL.translatef((F32)left, (F32)bottom, 0.f);
+	gGL.translateUI((F32)left, (F32)bottom, 0.f);
 	LLVector2 border_uv_scale((F32)border_size / (F32)texture_width, (F32)border_size / (F32)texture_height);
 
 	if (border_uv_scale.mV[VX] > 0.5f)
@@ -1193,7 +1227,7 @@ void gl_segmented_rect_2d_tex(const S32 left,
 	}
 	gGL.end();
 
-	gGL.popMatrix();
+	gGL.popUIMatrix();
 }
 
 void gl_segmented_rect_2d_fragment_tex(const S32 left, 
@@ -1210,9 +1244,9 @@ void gl_segmented_rect_2d_fragment_tex(const S32 left,
 	S32 width = llabs(right - left);
 	S32 height = llabs(top - bottom);
 
-	gGL.pushMatrix();
+	gGL.pushUIMatrix();
 
-	gGL.translatef((F32)left, (F32)bottom, 0.f);
+	gGL.translateUI((F32)left, (F32)bottom, 0.f);
 	LLVector2 border_uv_scale((F32)border_size / (F32)texture_width, (F32)border_size / (F32)texture_height);
 
 	if (border_uv_scale.mV[VX] > 0.5f)
@@ -1383,7 +1417,7 @@ void gl_segmented_rect_2d_fragment_tex(const S32 left,
 	}
 	gGL.end();
 
-	gGL.popMatrix();
+	gGL.popUIMatrix();
 }
 
 void gl_segmented_rect_3d_tex(const LLVector2& border_scale, const LLVector3& border_width, 
@@ -1591,7 +1625,7 @@ void LLUI::dirtyRect(LLRect rect)
 //static
 void LLUI::translate(F32 x, F32 y, F32 z)
 {
-	gGL.translatef(x,y,z);
+	gGL.translateUI(x,y,z);
 	LLFontGL::sCurOrigin.mX += (S32) x;
 	LLFontGL::sCurOrigin.mY += (S32) y;
 	LLFontGL::sCurOrigin.mZ += z;
@@ -1600,14 +1634,14 @@ void LLUI::translate(F32 x, F32 y, F32 z)
 //static
 void LLUI::pushMatrix()
 {
-	gGL.pushMatrix();
+	gGL.pushUIMatrix();
 	LLFontGL::sOriginStack.push_back(LLFontGL::sCurOrigin);
 }
 
 //static
 void LLUI::popMatrix()
 {
-	gGL.popMatrix();
+	gGL.popUIMatrix();
 	LLFontGL::sCurOrigin = *LLFontGL::sOriginStack.rbegin();
 	LLFontGL::sOriginStack.pop_back();
 }
@@ -1615,7 +1649,7 @@ void LLUI::popMatrix()
 //static 
 void LLUI::loadIdentity()
 {
-	glLoadIdentity();
+	gGL.loadUIIdentity(); 
 	LLFontGL::sCurOrigin.mX = 0;
 	LLFontGL::sCurOrigin.mY = 0;
 	LLFontGL::sCurOrigin.mZ = 0;
diff --git a/indra/llui/llviewborder.cpp b/indra/llui/llviewborder.cpp
index 30717f87def3caf41ff1ed4605bc479857b5a134..bd9c43c97f0a488d8ca308b6ce36edc040417f07 100644
--- a/indra/llui/llviewborder.cpp
+++ b/indra/llui/llviewborder.cpp
@@ -125,14 +125,6 @@ void LLViewBorder::draw()
 			llassert( FALSE );  // not implemented
 		}
 	}
-	else
-	if( STYLE_TEXTURE == mStyle )
-	{
-		if( mTexture )
-		{
-			drawTextures();
-		}
-	}
 
 	LLView::draw();
 }
@@ -255,56 +247,6 @@ void LLViewBorder::drawTwoPixelLines()
 	gl_line_2d(left+1, bottom+1, right-1, bottom+1);
 }
 
-void LLViewBorder::drawTextures()
-{
-	//LLGLSUIDefault gls_ui;
-
-	//llassert( FALSE );  // TODO: finish implementing
-
-	//gGL.color4fv(UI_VERTEX_COLOR.mV);
-
-	//gGL.getTexUnit(0)->bind(mTexture);
-	//gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_WRAP);
-
-	//drawTextureTrapezoid(   0.f, mBorderWidth, getRect().getWidth(),  0,					0 );
-	//drawTextureTrapezoid(  90.f, mBorderWidth, getRect().getHeight(), (F32)getRect().getWidth(),0 );
-	//drawTextureTrapezoid( 180.f, mBorderWidth, getRect().getWidth(),  (F32)getRect().getWidth(),(F32)getRect().getHeight() );
-	//drawTextureTrapezoid( 270.f, mBorderWidth, getRect().getHeight(), 0,					(F32)getRect().getHeight() );
-}
-
-
-void LLViewBorder::drawTextureTrapezoid( F32 degrees, S32 width, S32 length, F32 start_x, F32 start_y )
-{
-	gGL.pushMatrix();
-	{
-		gGL.translatef(start_x, start_y, 0.f);
-		glRotatef( degrees, 0, 0, 1 );
-
-		gGL.begin(LLRender::QUADS);
-		{
-			//      width, width   /---------\ length-width, width		//
-			//	   			      /           \							//
-			//				     /			   \						//
-			//				    /---------------\						//
-			//    			0,0					  length, 0				//
-
-			gGL.texCoord2f( 0, 0 );
-			gGL.vertex2i( 0, 0 );
-
-			gGL.texCoord2f( (GLfloat)length, 0 );
-			gGL.vertex2i( length, 0 );
-
-			gGL.texCoord2f( (GLfloat)(length - width), (GLfloat)width );
-			gGL.vertex2i( length - width, width );
-
-			gGL.texCoord2f( (GLfloat)width, (GLfloat)width );
-			gGL.vertex2i( width, width );
-		}
-		gGL.end();
-	}
-	gGL.popMatrix();
-}
-
 BOOL LLViewBorder::getBevelFromAttribute(LLXMLNodePtr node, LLViewBorder::EBevel& bevel_style)
 {
 	if (node->hasAttribute("bevel_style"))
diff --git a/indra/llui/llviewborder.h b/indra/llui/llviewborder.h
index 92fd5693250a9d82df65bf52adb0d5d40e6bd05f..342e84fd93e65e473377d10f31079be337b1c965 100644
--- a/indra/llui/llviewborder.h
+++ b/indra/llui/llviewborder.h
@@ -99,8 +99,7 @@ class LLViewBorder : public LLView
 	void		drawOnePixelLines();
 	void		drawTwoPixelLines();
 	void		drawTextures();
-	void		drawTextureTrapezoid( F32 degrees, S32 width, S32 length, F32 start_x, F32 start_y );
-
+	
 	EBevel		mBevel;
 	EStyle		mStyle;
 	LLUIColor	mHighlightLight;
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 923ba44906d60f1344e0ccdbfbbcb50b8e6918aa..5e5917add9dbb56c6045a9cd2cd33e257b1da785 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -7384,8 +7384,19 @@
       <key>Type</key>
       <string>Boolean</string>
       <key>Value</key>
-      <integer>0</integer>
+      <integer>1</integer>
     </map>
+  <key>RenderUseTriStrips</key>
+  <map>
+    <key>Comment</key>
+    <string>Use triangle strips for rendering prims.</string>
+    <key>Persist</key>
+    <integer>1</integer>
+    <key>Type</key>
+    <string>Boolean</string>
+    <key>Value</key>
+    <integer>1</integer>
+  </map>
     <key>RenderUseFarClip</key>
     <map>
       <key>Comment</key>
diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index 2354323a66d82006316ee8c8738d2146c1acf4bc..9f2186f7f7c40363d140703245b36d1f13e14b56 100644
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -3017,6 +3017,9 @@ void LLAgent::endAnimationUpdateUI()
 //-----------------------------------------------------------------------------
 void LLAgent::updateCamera()
 {
+	static LLFastTimer::DeclareTimer ftm("Camera");
+	LLFastTimer t(ftm);
+
 	//Ventrella - changed camera_skyward to the new global "mCameraUpVector"
 	mCameraUpVector = LLVector3::z_axis;
 	//LLVector3	camera_skyward(0.f, 0.f, 1.f);
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 98ec9078863ed13d3e59f2cab98840f579c975cc..ff4587021b5afaacc06a7be8d0ea9206bff9924e 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -3594,13 +3594,15 @@ void LLAppViewer::idle()
 
 	{
 		// Handle pending gesture processing
+		static LLFastTimer::DeclareTimer ftm("Agent Position");
+		LLFastTimer t(ftm);
 		LLGestureManager::instance().update();
 
 		gAgent.updateAgentPosition(gFrameDTClamped, yaw, current_mouse.mX, current_mouse.mY);
 	}
 
 	{
-		LLFastTimer t(FTM_OBJECTLIST_UPDATE); // Actually "object update"
+		LLFastTimer t(FTM_OBJECTLIST_UPDATE); 
 		
         if (!(logoutRequestSent() && hasSavedFinalSnapshot()))
 		{
@@ -3634,6 +3636,8 @@ void LLAppViewer::idle()
 	//
 
 	{
+		static LLFastTimer::DeclareTimer ftm("HUD Effects");
+		LLFastTimer t(ftm);
 		LLSelectMgr::getInstance()->updateEffects();
 		LLHUDManager::getInstance()->cleanupEffects();
 		LLHUDManager::getInstance()->sendEffects();
@@ -3890,7 +3894,7 @@ void LLAppViewer::sendLogoutRequest()
 static F32 CheckMessagesMaxTime = CHECK_MESSAGES_DEFAULT_MAX_TIME;
 #endif
 
-static LLFastTimer::DeclareTimer FTM_IDLE_NETWORK("Network");
+static LLFastTimer::DeclareTimer FTM_IDLE_NETWORK("Idle Network");
 
 void LLAppViewer::idleNetwork()
 {
diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp
index d60330024afedf42cb35e2dd6e08c7a19c141c29..244fed791f3e874c26eda44fd765da6eef026c21 100644
--- a/indra/newview/lldrawable.cpp
+++ b/indra/newview/lldrawable.cpp
@@ -386,8 +386,6 @@ void LLDrawable::makeActive()
 			mParent->makeActive();
 		}
 
-		gPipeline.setActive(this, TRUE);
-
 		//all child objects must also be active
 		llassert_always(mVObjp);
 		
@@ -434,7 +432,6 @@ void LLDrawable::makeStatic(BOOL warning_enabled)
 	if (isState(ACTIVE))
 	{
 		clearState(ACTIVE);
-		gPipeline.setActive(this, FALSE);
 
 		if (mParent.notNull() && mParent->isActive() && warning_enabled)
 		{
diff --git a/indra/newview/lldrawpool.cpp b/indra/newview/lldrawpool.cpp
index 95ddacb722a5e0d39e3b1d6f0a8bb6416886c809..ef946ac49e5cfe99ff3fc99ddf682a20e3ce4433 100644
--- a/indra/newview/lldrawpool.cpp
+++ b/indra/newview/lldrawpool.cpp
@@ -496,8 +496,8 @@ void LLRenderPass::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture)
 			params.mGroup->rebuildMesh();
 		}
 		params.mVertexBuffer->setBuffer(mask);
-		params.mVertexBuffer->drawRange(LLRender::TRIANGLES, params.mStart, params.mEnd, params.mCount, params.mOffset);
-		gPipeline.addTrianglesDrawn(params.mCount/3);
+		params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset);
+		gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode);
 	}
 
 	if (params.mTextureMatrix && texture && params.mTexture.notNull())
diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp
index 6d7736141494967cfee8e6aa2aab8f54e5aad250..0e02bc4b01c94a2f8b4e752002428745dacbf18f 100644
--- a/indra/newview/lldrawpoolalpha.cpp
+++ b/indra/newview/lldrawpoolalpha.cpp
@@ -250,8 +250,8 @@ void LLDrawPoolAlpha::renderAlphaHighlight(U32 mask)
 					params.mGroup->rebuildMesh();
 				}
 				params.mVertexBuffer->setBuffer(mask);
-				params.mVertexBuffer->drawRange(LLRender::TRIANGLES, params.mStart, params.mEnd, params.mCount, params.mOffset);
-				gPipeline.addTrianglesDrawn(params.mCount/3);
+				params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset);
+				gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode);
 			}
 		}
 	}
@@ -380,8 +380,8 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask)
 				}
 
 				params.mVertexBuffer->setBuffer(mask);
-				params.mVertexBuffer->drawRange(LLRender::TRIANGLES, params.mStart, params.mEnd, params.mCount, params.mOffset);
-				gPipeline.addTrianglesDrawn(params.mCount/3);
+				params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset);
+				gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode);
 
 				if (params.mTextureMatrix && params.mTexture.notNull())
 				{
diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp
index 03a8b108e299077e3e29961a2ca4d9c0087ab4d7..d09d4a412fa13e0924268f4a38bdcf2d8679f429 100644
--- a/indra/newview/lldrawpoolbump.cpp
+++ b/indra/newview/lldrawpoolbump.cpp
@@ -560,8 +560,8 @@ void LLDrawPoolBump::renderGroup(LLSpatialGroup* group, U32 type, U32 mask, BOOL
 			params.mGroup->rebuildMesh();
 		}
 		params.mVertexBuffer->setBuffer(mask);
-		params.mVertexBuffer->drawRange(LLRender::TRIANGLES, params.mStart, params.mEnd, params.mCount, params.mOffset);
-		gPipeline.addTrianglesDrawn(params.mCount/3);
+		params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset);
+		gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode);
 	}
 }
 
@@ -1231,8 +1231,8 @@ void LLDrawPoolBump::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture)
 		params.mGroup->rebuildMesh();
 	}
 	params.mVertexBuffer->setBuffer(mask);
-	params.mVertexBuffer->drawRange(LLRender::TRIANGLES, params.mStart, params.mEnd, params.mCount, params.mOffset);
-	gPipeline.addTrianglesDrawn(params.mCount/3);
+	params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset);
+	gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode);
 	if (params.mTextureMatrix)
 	{
 		if (mShiny)
diff --git a/indra/newview/lldrawpooltree.cpp b/indra/newview/lldrawpooltree.cpp
index 5521fb05a82fcf7b87ae500afca251e2b7105bb7..1a5d55d793b1f7011e140e903dc04bd484443bd3 100644
--- a/indra/newview/lldrawpooltree.cpp
+++ b/indra/newview/lldrawpooltree.cpp
@@ -115,7 +115,7 @@ void LLDrawPoolTree::render(S32 pass)
 			LLFace *face = *iter;
 			face->mVertexBuffer->setBuffer(LLDrawPoolTree::VERTEX_DATA_MASK);
 			face->mVertexBuffer->drawRange(LLRender::TRIANGLES, 0, face->mVertexBuffer->getRequestedVerts()-1, face->mVertexBuffer->getRequestedIndices(), 0); 
-			gPipeline.addTrianglesDrawn(face->mVertexBuffer->getRequestedIndices()/3);
+			gPipeline.addTrianglesDrawn(face->mVertexBuffer->getRequestedIndices());
 		}
 	}
 }
@@ -237,7 +237,7 @@ void LLDrawPoolTree::renderForSelect()
 				
 				face->mVertexBuffer->setBuffer(LLDrawPoolTree::VERTEX_DATA_MASK);
 				face->mVertexBuffer->drawRange(LLRender::TRIANGLES, 0, face->mVertexBuffer->getRequestedVerts()-1, face->mVertexBuffer->getRequestedIndices(), 0); 
-				gPipeline.addTrianglesDrawn(face->mVertexBuffer->getRequestedIndices()/3);
+				gPipeline.addTrianglesDrawn(face->mVertexBuffer->getRequestedIndices());
 			}
 		}
 	}
diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp
index 965ac1cad0b11cf40ca5833be8446d0ac57e6f8a..93840e077c67fa13f36dd76c6645b7a791e786c6 100644
--- a/indra/newview/llface.cpp
+++ b/indra/newview/llface.cpp
@@ -868,7 +868,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 	llpushcallstacks ;
 	const LLVolumeFace &vf = volume.getVolumeFace(f);
 	S32 num_vertices = (S32)vf.mVertices.size();
-	S32 num_indices = (S32)vf.mIndices.size();
+	S32 num_indices = LLPipeline::sUseTriStrips ? (S32)vf.mTriStrip.size() : (S32) vf.mIndices.size();
 	
 	if (mVertexBuffer.notNull())
 	{
@@ -1058,9 +1058,19 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 	if (full_rebuild)
 	{
 		mVertexBuffer->getIndexStrider(indicesp, mIndicesIndex);
-		for (U16 i = 0; i < num_indices; i++)
+		if (LLPipeline::sUseTriStrips)
 		{
-			*indicesp++ = vf.mIndices[i] + index_offset;
+			for (U16 i = 0; i < num_indices; i++)
+			{
+				*indicesp++ = vf.mTriStrip[i] + index_offset;
+			}
+		}
+		else
+		{
+			for (U16 i = 0; i < num_indices; i++)
+			{
+				*indicesp++ = vf.mIndices[i] + index_offset;
+			}
 		}
 	}
 	
@@ -1572,8 +1582,13 @@ S32 LLFace::pushVertices(const U16* index_array) const
 {
 	if (mIndicesCount)
 	{
-		mVertexBuffer->drawRange(LLRender::TRIANGLES, mGeomIndex, mGeomIndex+mGeomCount-1, mIndicesCount, mIndicesIndex);
-		gPipeline.addTrianglesDrawn(mIndicesCount/3);
+		U32 render_type = LLRender::TRIANGLES;
+		if (mDrawInfo)
+		{
+			render_type = mDrawInfo->mDrawMode;
+		}
+		mVertexBuffer->drawRange(render_type, mGeomIndex, mGeomIndex+mGeomCount-1, mIndicesCount, mIndicesIndex);
+		gPipeline.addTrianglesDrawn(mIndicesCount, render_type);
 	}
 
 	return mIndicesCount;
diff --git a/indra/newview/llflexibleobject.cpp b/indra/newview/llflexibleobject.cpp
index aea2de8e92f110366dbc94bccb59b83d2a68630d..561965d0214f4991e78177f7e3e9c1884404005d 100644
--- a/indra/newview/llflexibleobject.cpp
+++ b/indra/newview/llflexibleobject.cpp
@@ -51,6 +51,9 @@
 
 /*static*/ F32 LLVolumeImplFlexible::sUpdateFactor = 1.0f;
 
+static LLFastTimer::DeclareTimer FTM_FLEXIBLE_REBUILD("Rebuild");
+static LLFastTimer::DeclareTimer FTM_DO_FLEXIBLE_UPDATE("Update");
+
 // LLFlexibleObjectData::pack/unpack now in llprimitive.cpp
 
 //-----------------------------------------------
@@ -194,7 +197,6 @@ void LLVolumeImplFlexible::remapSections(LLFlexibleObjectSection *source, S32 so
 	}
 }
 
-
 //-----------------------------------------------------------------------------
 void LLVolumeImplFlexible::setAttributesOfAllSections(LLVector3* inScale)
 {
@@ -363,6 +365,7 @@ inline S32 log2(S32 x)
 
 void LLVolumeImplFlexible::doFlexibleUpdate()
 {
+	LLFastTimer ftm(FTM_DO_FLEXIBLE_UPDATE);
 	LLVolume* volume = mVO->getVolume();
 	LLPath *path = &volume->getPath();
 	if (mSimulateRes == 0)
@@ -693,7 +696,10 @@ BOOL LLVolumeImplFlexible::doUpdateGeometry(LLDrawable *drawable)
 	}
 
 	volume->updateRelativeXform();
-	doFlexibleUpdate();
+	{
+		LLFastTimer t(FTM_DO_FLEXIBLE_UPDATE);
+		doFlexibleUpdate();
+	}
 	
 	// Object may have been rotated, which means it needs a rebuild.  See SL-47220
 	BOOL	rotated = FALSE;
@@ -710,7 +716,10 @@ BOOL LLVolumeImplFlexible::doUpdateGeometry(LLDrawable *drawable)
 		volume->regenFaces();
 		volume->mDrawable->setState(LLDrawable::REBUILD_VOLUME);
 		volume->dirtySpatialGroup();
-		doFlexibleRebuild();
+		{
+			LLFastTimer t(FTM_FLEXIBLE_REBUILD);
+			doFlexibleRebuild();
+		}
 		volume->genBBoxes(isVolumeGlobal());
 	}
 	else if (!mUpdated || rotated)
diff --git a/indra/newview/llglsandbox.cpp b/indra/newview/llglsandbox.cpp
index 750a9d478fe5c1ee023716fc3885697bece3c345..8569e208eb9b0e82f8e0c1ff3328a0061bea9684 100644
--- a/indra/newview/llglsandbox.cpp
+++ b/indra/newview/llglsandbox.cpp
@@ -897,19 +897,21 @@ void LLViewerObjectList::renderObjectBeacons()
 		S32 last_line_width = -1;
 		// gGL.begin(LLRender::LINES); // Always happens in (line_width != last_line_width)
 		
-		for (S32 i = 0; i < mDebugBeacons.count(); i++)
+		BOOL flush = FALSE;
+		for (std::vector<LLDebugBeacon>::iterator iter = mDebugBeacons.begin(); iter != mDebugBeacons.end(); ++iter)
 		{
-			const LLDebugBeacon &debug_beacon = mDebugBeacons[i];
+			const LLDebugBeacon &debug_beacon = *iter;
 			LLColor4 color = debug_beacon.mColor;
 			color.mV[3] *= 0.25f;
 			S32 line_width = debug_beacon.mLineWidth;
 			if (line_width != last_line_width)
 			{
-				if (i > 0)
+				if (flush)
 				{
 					gGL.end();
-					gGL.flush();
 				}
+				flush = TRUE;
+				gGL.flush();
 				glLineWidth( (F32)line_width );
 				last_line_width = line_width;
 				gGL.begin(LLRender::LINES);
@@ -936,18 +938,20 @@ void LLViewerObjectList::renderObjectBeacons()
 		S32 last_line_width = -1;
 		// gGL.begin(LLRender::LINES); // Always happens in (line_width != last_line_width)
 		
-		for (S32 i = 0; i < mDebugBeacons.count(); i++)
+		BOOL flush = FALSE;
+		for (std::vector<LLDebugBeacon>::iterator iter = mDebugBeacons.begin(); iter != mDebugBeacons.end(); ++iter)
 		{
-			const LLDebugBeacon &debug_beacon = mDebugBeacons[i];
+			const LLDebugBeacon &debug_beacon = *iter;
 
 			S32 line_width = debug_beacon.mLineWidth;
 			if (line_width != last_line_width)
 			{
-				if (i > 0)
+				if (flush)
 				{
 					gGL.end();
-					gGL.flush();
 				}
+				flush = TRUE;
+				gGL.flush();
 				glLineWidth( (F32)line_width );
 				last_line_width = line_width;
 				gGL.begin(LLRender::LINES);
@@ -969,9 +973,9 @@ void LLViewerObjectList::renderObjectBeacons()
 		gGL.flush();
 		glLineWidth(1.f);
 
-		for (S32 i = 0; i < mDebugBeacons.count(); i++)
+		for (std::vector<LLDebugBeacon>::iterator iter = mDebugBeacons.begin(); iter != mDebugBeacons.end(); ++iter)
 		{
-			LLDebugBeacon &debug_beacon = mDebugBeacons[i];
+			LLDebugBeacon &debug_beacon = *iter;
 			if (debug_beacon.mString == "")
 			{
 				continue;
diff --git a/indra/newview/llhudrender.cpp b/indra/newview/llhudrender.cpp
index a02dc3355b12c197b1ae38ef9bee785b698774e7..325c9c260ca47927efa793af9efdfec4420c6be8 100644
--- a/indra/newview/llhudrender.cpp
+++ b/indra/newview/llhudrender.cpp
@@ -121,24 +121,24 @@ void hud_render_text(const LLWString &wstr, const LLVector3 &pos_agent,
 	glMatrixMode(GL_PROJECTION);
 	glPushMatrix();
 	glMatrixMode(GL_MODELVIEW);
-	
+	gGL.pushMatrix();
 	LLUI::pushMatrix();
 		
 	gl_state_for_2d(world_view_rect.getWidth(), world_view_rect.getHeight());
 	gViewerWindow->setup3DViewport();
-	//gViewerWindow->setup2DRender();
-
+	
 	winX -= world_view_rect.mLeft;
 	winY -= world_view_rect.mBottom;
 	LLUI::loadIdentity();
+	glLoadIdentity();
 	LLUI::translate((F32) winX*1.0f/LLFontGL::sScaleX, (F32) winY*1.0f/(LLFontGL::sScaleY), -(((F32) winZ*2.f)-1.f));
-	//glRotatef(angle * RAD_TO_DEG, axis.mV[VX], axis.mV[VY], axis.mV[VZ]);
-	//glScalef(right_scale, up_scale, 1.f);
 	F32 right_x;
 	
 	font.render(wstr, 0, 0, 0, color, LLFontGL::LEFT, LLFontGL::BASELINE, style, shadow, wstr.length(), 1000, &right_x);
+
 	LLUI::popMatrix();
-	
+	gGL.popMatrix();
+
 	glMatrixMode(GL_PROJECTION);
 	glPopMatrix();
 	glMatrixMode(GL_MODELVIEW);
diff --git a/indra/newview/llhudtext.cpp b/indra/newview/llhudtext.cpp
index 8ad94b957d78ac5525bd58e0607d8d12a710e9d4..8d1d27444b900fecb8222dc41ce7c93621f3a8b7 100644
--- a/indra/newview/llhudtext.cpp
+++ b/indra/newview/llhudtext.cpp
@@ -555,7 +555,7 @@ void LLHUDText::renderText(BOOL for_select)
 		}
 	}
 	/// Reset the default color to white.  The renderer expects this to be the default. 
-	glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
+	gGL.color4f(1.0f, 1.0f, 1.0f, 1.0f);
 	if (for_select)
 	{
 		gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp
index 501a137b4253ac49f8397a2460864371f2fa9b5b..bf33d8527e3c8c55f100521eaae79182b94d2d59 100644
--- a/indra/newview/llmediactrl.cpp
+++ b/indra/newview/llmediactrl.cpp
@@ -724,14 +724,14 @@ void LLMediaCtrl::draw()
 		LLGLSUIDefault gls_ui;
 		LLGLDisable gls_alphaTest( GL_ALPHA_TEST );
 
-		gGL.pushMatrix();
+		gGL.pushUIMatrix();
 		{
 			if (mIgnoreUIScale)
 			{
-				glLoadIdentity();
+				gGL.loadUIIdentity();
 				// font system stores true screen origin, need to scale this by UI scale factor
 				// to get render origin for this view (with unit scale)
-				gGL.translatef(floorf(LLFontGL::sCurOrigin.mX * LLUI::sGLScaleFactor.mV[VX]), 
+				gGL.translateUI(floorf(LLFontGL::sCurOrigin.mX * LLUI::sGLScaleFactor.mV[VX]), 
 							floorf(LLFontGL::sCurOrigin.mY * LLUI::sGLScaleFactor.mV[VY]), 
 							LLFontGL::sCurOrigin.mZ);
 			}
@@ -825,7 +825,7 @@ void LLMediaCtrl::draw()
 			gGL.end();
 			gGL.setSceneBlendType(LLRender::BT_ALPHA);
 		}
-		gGL.popMatrix();
+		gGL.popUIMatrix();
 	
 	}
 	else
diff --git a/indra/newview/llnetmap.cpp b/indra/newview/llnetmap.cpp
index 234fe13217f935efba7c0151a149d326418aed4e..05623198ab626dac11165cd113291ee6977d0ad4 100644
--- a/indra/newview/llnetmap.cpp
+++ b/indra/newview/llnetmap.cpp
@@ -153,6 +153,18 @@ void LLNetMap::draw()
 	// Prepare a scissor region
 	F32 rotation = 0;
 
+	gGL.pushMatrix();
+	gGL.pushUIMatrix();
+	
+	LLVector3 offset = gGL.getUITranslation();
+	LLVector3 scale = gGL.getUIScale();
+
+	glLoadIdentity();
+	gGL.loadUIIdentity();
+
+	glScalef(scale.mV[0], scale.mV[1], scale.mV[2]);
+	gGL.translatef(offset.mV[0], offset.mV[1], offset.mV[2]);
+	
 	{
 		LLLocalClipRect clip(getLocalRect());
 		{
@@ -435,6 +447,9 @@ void LLNetMap::draw()
 		}
 	}
 	
+	gGL.popMatrix();
+	gGL.popUIMatrix();
+
 	LLUICtrl::draw();
 }
 
diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp
index 95408946468c8520b0398782287f276f72846234..d733574a9dfc068bfc569d318a914f7f11baf696 100644
--- a/indra/newview/llselectmgr.cpp
+++ b/indra/newview/llselectmgr.cpp
@@ -4919,13 +4919,15 @@ void LLSelectMgr::renderSilhouettes(BOOL for_hud)
 
 		// set up transform to encompass bounding box of HUD
 		glMatrixMode(GL_PROJECTION);
-		glPushMatrix();
+		gGL.pushMatrix();
 		glLoadIdentity();
 		F32 depth = llmax(1.f, hud_bbox.getExtentLocal().mV[VX] * 1.1f);
 		glOrtho(-0.5f * LLViewerCamera::getInstance()->getAspect(), 0.5f * LLViewerCamera::getInstance()->getAspect(), -0.5f, 0.5f, 0.f, depth);
 
 		glMatrixMode(GL_MODELVIEW);
-		glPushMatrix();
+		gGL.pushMatrix();
+		gGL.pushUIMatrix();
+		gGL.loadUIIdentity();
 		glLoadIdentity();
 		glLoadMatrixf(OGL_TO_CFR_ROTATION);		// Load Cory's favorite reference frame
 		glTranslatef(-hud_bbox.getCenterLocal().mV[VX] + (depth *0.5f), 0.f, 0.f);
@@ -5022,10 +5024,11 @@ void LLSelectMgr::renderSilhouettes(BOOL for_hud)
 	if (for_hud && avatar)
 	{
 		glMatrixMode(GL_PROJECTION);
-		glPopMatrix();
+		gGL.popMatrix();
 
 		glMatrixMode(GL_MODELVIEW);
-		glPopMatrix();
+		gGL.popMatrix();
+		gGL.popUIMatrix();
 		stop_glerror();
 	}
 
@@ -5374,7 +5377,10 @@ void LLSelectNode::renderOneSilhouette(const LLColor4 &color)
 	}
 
 	glMatrixMode(GL_MODELVIEW);
-	glPushMatrix();
+	gGL.pushMatrix();
+	gGL.pushUIMatrix();
+	gGL.loadUIIdentity();
+
 	if (!is_hud_object)
 	{
 		glLoadIdentity();
@@ -5493,7 +5499,8 @@ void LLSelectNode::renderOneSilhouette(const LLColor4 &color)
 		gGL.end();
 		gGL.flush();
 	}
-	glPopMatrix();
+	gGL.popMatrix();
+	gGL.popUIMatrix();
 }
 
 //
diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp
index 2a57d48f16bd45e722d0b0b9fc6d7fa6b55cf46a..d6e9256feea2af8ad1461e46505e914117135fb2 100644
--- a/indra/newview/llspatialpartition.cpp
+++ b/indra/newview/llspatialpartition.cpp
@@ -3380,7 +3380,8 @@ LLDrawInfo::LLDrawInfo(U16 start, U16 end, U32 count, U32 offset,
 	mVSize(0.f),
 	mGroup(NULL),
 	mFace(NULL),
-	mDistance(0.f)
+	mDistance(0.f),
+	mDrawMode(LLRender::TRIANGLES)
 {
 	mDebugColor = (rand() << 16) + rand();
 	if (mStart >= mVertexBuffer->getRequestedVerts() ||
diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h
index 64c2a9acbc7d94d7da76ad693d94b5e7217a1803..7896488379e0d80dc8aa7f1b808032648117787f 100644
--- a/indra/newview/llspatialpartition.h
+++ b/indra/newview/llspatialpartition.h
@@ -93,6 +93,7 @@ class LLDrawInfo : public LLRefCount
 	LLFace* mFace; //associated face
 	F32 mDistance;
 	LLVector3 mExtents[2];
+	U32 mDrawMode;
 
 	struct CompareTexture
 	{
diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp
index 64eabe65cfebefa2889aa58731d2aa4ab1e9d6db..0b7f6900ed8775828390ce5b7ff1f5494982a723 100644
--- a/indra/newview/llviewercontrol.cpp
+++ b/indra/newview/llviewercontrol.cpp
@@ -510,10 +510,12 @@ void settings_setup_listeners()
 	gSavedSettings.getControl("FirstPersonAvatarVisible")->getSignal()->connect(boost::bind(&handleRenderAvatarMouselookChanged, _2));
 	gSavedSettings.getControl("RenderFarClip")->getSignal()->connect(boost::bind(&handleRenderFarClipChanged, _2));
 	gSavedSettings.getControl("RenderTerrainDetail")->getSignal()->connect(boost::bind(&handleTerrainDetailChanged, _2));
+	gSavedSettings.getControl("RenderUseTriStrips")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2));
 	gSavedSettings.getControl("RenderAnimateTrees")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2));
 	gSavedSettings.getControl("RenderAvatarVP")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2));
 	gSavedSettings.getControl("VertexShaderEnable")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2));
 	gSavedSettings.getControl("RenderUIBuffer")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2));
+	gSavedSettings.getControl("RenderFSAASamples")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2));
 	gSavedSettings.getControl("RenderShadowResolutionScale")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2));
 	gSavedSettings.getControl("RenderGlow")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2));
 	gSavedSettings.getControl("RenderGlow")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2));
diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp
index ba256d70e80423c7c08f759360c2e2434bbf8b1a..64b3bccd4c4362039e9728515ddf9965991049a0 100644
--- a/indra/newview/llviewerdisplay.cpp
+++ b/indra/newview/llviewerdisplay.cpp
@@ -862,10 +862,14 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
 			if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender)
 			{
 				gPipeline.mDeferredScreen.flush();
+				LLRenderTarget::copyContentsToFramebuffer(gPipeline.mDeferredScreen, 0, 0, gPipeline.mDeferredScreen.getWidth(), gPipeline.mDeferredScreen.getHeight(),
+									0, 0, gPipeline.mDeferredScreen.getWidth(), gPipeline.mDeferredScreen.getHeight(), GL_DEPTH_BUFFER_BIT, GL_NEAREST);
 			}
 			else
 			{
 				gPipeline.mScreen.flush();
+				LLRenderTarget::copyContentsToFramebuffer(gPipeline.mScreen, 0, 0, gPipeline.mScreen.getWidth(), gPipeline.mScreen.getHeight(),
+									0, 0, gPipeline.mScreen.getWidth(), gPipeline.mScreen.getHeight(), GL_DEPTH_BUFFER_BIT, GL_NEAREST);
 			}
 		}
 
diff --git a/indra/newview/llviewerjointmesh.cpp b/indra/newview/llviewerjointmesh.cpp
index 1a67fc09664de606e6ce747f514df615b49274d1..7225aa15238fc5c3cec5a12328fb65c35a435460 100644
--- a/indra/newview/llviewerjointmesh.cpp
+++ b/indra/newview/llviewerjointmesh.cpp
@@ -626,7 +626,7 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy)
 		mFace->mVertexBuffer->drawRange(LLRender::TRIANGLES, start, end, count, offset);
 		glPopMatrix();
 	}
-	gPipeline.addTrianglesDrawn(count/3);
+	gPipeline.addTrianglesDrawn(count);
 
 	triangle_count += count;
 	
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index d0afa9d9de4015e3615187469f543090f28ce419..b5642d07a520c47228059148fe2f4515e784d76a 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -2001,6 +2001,9 @@ BOOL LLViewerObject::isActive() const
 
 BOOL LLViewerObject::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
 {
+	static LLFastTimer::DeclareTimer ftm("Viewer Object");
+	LLFastTimer t(ftm);
+
 	if (mDead)
 	{
 		// It's dead.  Don't update it.
diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp
index 96828ee1b6088baad4c3ef16e92c81c7a38438fb..6347090f7166d050c0ac0a9b58f9d6d97b7a2541 100644
--- a/indra/newview/llviewerobjectlist.cpp
+++ b/indra/newview/llviewerobjectlist.cpp
@@ -93,7 +93,7 @@ extern LLPipeline	gPipeline;
 
 // Statics for object lookup tables.
 U32						LLViewerObjectList::sSimulatorMachineIndex = 1; // Not zero deliberately, to speed up index check.
-LLMap<U64, U32>			LLViewerObjectList::sIPAndPortToIndex;
+std::map<U64, U32>			LLViewerObjectList::sIPAndPortToIndex;
 std::map<U64, LLUUID>	LLViewerObjectList::sIndexAndLocalIDToUUID;
 
 LLViewerObjectList::LLViewerObjectList()
@@ -571,10 +571,9 @@ void LLViewerObjectList::processCachedObjectUpdate(LLMessageSystem *mesgsys,
 
 void LLViewerObjectList::dirtyAllObjectInventory()
 {
-	S32 count = mObjects.count();
-	for(S32 i = 0; i < count; ++i)
+	for (vobj_list_t::iterator iter = mObjects.begin(); iter != mObjects.end(); ++iter)
 	{
-		mObjects[i]->dirtyInventory();
+		(*iter)->dirtyInventory();
 	}
 }
 
@@ -587,14 +586,14 @@ void LLViewerObjectList::updateApparentAngles(LLAgent &agent)
 	S32 num_updates, max_value;
 	if (NUM_BINS - 1 == mCurBin)
 	{
-		num_updates = mObjects.count() - mCurLazyUpdateIndex;
-		max_value = mObjects.count();
+		num_updates = (S32) mObjects.size() - mCurLazyUpdateIndex;
+		max_value = (S32) mObjects.size();
 		gTextureList.setUpdateStats(TRUE);
 	}
 	else
 	{
-		num_updates = (mObjects.count() / NUM_BINS) + 1;
-		max_value = llmin(mObjects.count(), mCurLazyUpdateIndex + num_updates);
+		num_updates = ((S32) mObjects.size() / NUM_BINS) + 1;
+		max_value = llmin((S32) mObjects.size(), mCurLazyUpdateIndex + num_updates);
 	}
 
 
@@ -647,7 +646,7 @@ void LLViewerObjectList::updateApparentAngles(LLAgent &agent)
 	}
 
 	mCurLazyUpdateIndex = max_value;
-	if (mCurLazyUpdateIndex == mObjects.count())
+	if (mCurLazyUpdateIndex == mObjects.size())
 	{
 		mCurLazyUpdateIndex = 0;
 	}
@@ -694,20 +693,26 @@ void LLViewerObjectList::update(LLAgent &agent, LLWorld &world)
 	
 	// Make a copy of the list in case something in idleUpdate() messes with it
 	std::vector<LLViewerObject*> idle_list;
-	idle_list.reserve( mActiveObjects.size() );
+	
+	static LLFastTimer::DeclareTimer idle_copy("Idle Copy");
 
- 	for (std::set<LLPointer<LLViewerObject> >::iterator active_iter = mActiveObjects.begin();
-		active_iter != mActiveObjects.end(); active_iter++)
 	{
-		objectp = *active_iter;
-		if (objectp)
+		LLFastTimer t(idle_copy);
+		idle_list.reserve( mActiveObjects.size() );
+
+ 		for (std::set<LLPointer<LLViewerObject> >::iterator active_iter = mActiveObjects.begin();
+			active_iter != mActiveObjects.end(); active_iter++)
 		{
-			idle_list.push_back( objectp );
-		}
-		else
-		{	// There shouldn't be any NULL pointers in the list, but they have caused
-			// crashes before.  This may be idleUpdate() messing with the list.
-			llwarns << "LLViewerObjectList::update has a NULL objectp" << llendl;
+			objectp = *active_iter;
+			if (objectp)
+			{
+				idle_list.push_back( objectp );
+			}
+			else
+			{	// There shouldn't be any NULL pointers in the list, but they have caused
+				// crashes before.  This may be idleUpdate() messing with the list.
+				llwarns << "LLViewerObjectList::update has a NULL objectp" << llendl;
+			}
 		}
 	}
 
@@ -807,7 +812,7 @@ void LLViewerObjectList::update(LLAgent &agent, LLWorld &world)
 	}
 	*/
 
-	LLViewerStats::getInstance()->mNumObjectsStat.addValue(mObjects.count());
+	LLViewerStats::getInstance()->mNumObjectsStat.addValue((S32) mObjects.size());
 	LLViewerStats::getInstance()->mNumActiveObjectsStat.addValue(num_active_objects);
 	LLViewerStats::getInstance()->mNumSizeCulledStat.addValue(mNumSizeCulled);
 	LLViewerStats::getInstance()->mNumVisCulledStat.addValue(mNumVisCulled);
@@ -815,9 +820,9 @@ void LLViewerObjectList::update(LLAgent &agent, LLWorld &world)
 
 void LLViewerObjectList::clearDebugText()
 {
-	for (S32 i = 0; i < mObjects.count(); i++)
+	for (vobj_list_t::iterator iter = mObjects.begin(); iter != mObjects.end(); ++iter)
 	{
-		mObjects[i]->setDebugText("");
+		(*iter)->setDebugText("");
 	}
 }
 
@@ -856,7 +861,7 @@ void LLViewerObjectList::cleanupReferences(LLViewerObject *objectp)
 
 	if (objectp->isOnMap())
 	{
-		mMapObjects.removeObj(objectp);
+		removeFromMap(objectp);
 	}
 
 	// Don't clean up mObject references, these will be cleaned up more efficiently later!
@@ -913,10 +918,10 @@ void LLViewerObjectList::killObjects(LLViewerRegion *regionp)
 {
 	LLViewerObject *objectp;
 
-	S32 i;
-	for (i = 0; i < mObjects.count(); i++)
+	
+	for (vobj_list_t::iterator iter = mObjects.begin(); iter != mObjects.end(); ++iter)
 	{
-		objectp = mObjects[i];
+		objectp = *iter;
 		
 		if (objectp->mRegionp == regionp)
 		{
@@ -933,10 +938,9 @@ void LLViewerObjectList::killAllObjects()
 	// Used only on global destruction.
 	LLViewerObject *objectp;
 
-	for (S32 i = 0; i < mObjects.count(); i++)
+	for (vobj_list_t::iterator iter = mObjects.begin(); iter != mObjects.end(); ++iter)
 	{
-		objectp = mObjects[i];
-		
+		objectp = *iter;
 		killObject(objectp);
 		llassert(objectp->isDead());
 	}
@@ -945,7 +949,7 @@ void LLViewerObjectList::killAllObjects()
 
 	if(!mObjects.empty())
 	{
-		llwarns << "LLViewerObjectList::killAllObjects still has entries in mObjects: " << mObjects.count() << llendl;
+		llwarns << "LLViewerObjectList::killAllObjects still has entries in mObjects: " << mObjects.size() << llendl;
 		mObjects.clear();
 	}
 
@@ -970,16 +974,15 @@ void LLViewerObjectList::cleanDeadObjects(BOOL use_timer)
 		return;
 	}
 
-	S32 i = 0;
 	S32 num_removed = 0;
 	LLViewerObject *objectp;
-	while (i < mObjects.count())
+	for (vobj_list_t::iterator iter = mObjects.begin(); iter != mObjects.end(); )
 	{
 		// Scan for all of the dead objects and remove any "global" references to them.
-		objectp = mObjects[i];
+		objectp = *iter;
 		if (objectp->isDead())
 		{
-			mObjects.remove(i);
+			iter = mObjects.erase(iter);
 			num_removed++;
 
 			if (num_removed == mNumDeadObjects)
@@ -990,8 +993,7 @@ void LLViewerObjectList::cleanDeadObjects(BOOL use_timer)
 		}
 		else
 		{
-			// iterate, this isn't a dead object.
-			i++;
+			++iter;
 		}
 	}
 
@@ -1041,12 +1043,11 @@ void LLViewerObjectList::shiftObjects(const LLVector3 &offset)
 	}
 
 	LLViewerObject *objectp;
-	S32 i;
-	for (i = 0; i < mObjects.count(); i++)
+	for (vobj_list_t::iterator iter = mObjects.begin(); iter != mObjects.end(); ++iter)
 	{
-		objectp = getObject(i);
+		objectp = *iter;
 		// There could be dead objects on the object list, so don't update stuff if the object is dead.
-		if (objectp)
+		if (!objectp->isDead())
 		{
 			objectp->updatePositionCaches();
 
@@ -1076,9 +1077,9 @@ void LLViewerObjectList::renderObjectsForMap(LLNetMap &netmap)
 
 	F32 max_radius = gSavedSettings.getF32("MiniMapPrimMaxRadius");
 
-	for (S32 i = 0; i < mMapObjects.count(); i++)
+	for (vobj_list_t::iterator iter = mMapObjects.begin(); iter != mMapObjects.end(); ++iter)
 	{
-		LLViewerObject* objectp = mMapObjects[i];
+		LLViewerObject* objectp = *iter;
 		if (!objectp->getRegion() || objectp->isOrphaned() || objectp->isAttachment())
 		{
 			continue;
@@ -1144,21 +1145,14 @@ void LLViewerObjectList::renderObjectBounds(const LLVector3 &center)
 {
 }
 
-void LLViewerObjectList::renderObjectsForSelect(LLCamera &camera, const LLRect& screen_rect, BOOL pick_parcel_wall, BOOL render_transparent)
-{
-	generatePickList(camera);
-	renderPickList(screen_rect, pick_parcel_wall, render_transparent);
-}
-
 void LLViewerObjectList::generatePickList(LLCamera &camera)
 {
 		LLViewerObject *objectp;
 		S32 i;
 		// Reset all of the GL names to zero.
-		for (i = 0; i < mObjects.count(); i++)
+		for (vobj_list_t::iterator iter = mObjects.begin(); iter != mObjects.end(); ++iter)
 		{
-			objectp = mObjects[i];
-			objectp->mGLName = 0;
+			(*iter)->mGLName = 0;
 		}
 
 		mSelectPickList.clear();
@@ -1321,17 +1315,19 @@ void LLViewerObjectList::addDebugBeacon(const LLVector3 &pos_agent,
 										const LLColor4 &text_color,
 										S32 line_width)
 {
-	LLDebugBeacon *beaconp = mDebugBeacons.reserve_block(1);
-	beaconp->mPositionAgent = pos_agent;
-	beaconp->mString = string;
-	beaconp->mColor = color;
-	beaconp->mTextColor = text_color;
-	beaconp->mLineWidth = line_width;
+	LLDebugBeacon beacon;
+	beacon.mPositionAgent = pos_agent;
+	beacon.mString = string;
+	beacon.mColor = color;
+	beacon.mTextColor = text_color;
+	beacon.mLineWidth = line_width;
+
+	mDebugBeacons.push_back(beacon);
 }
 
 void LLViewerObjectList::resetObjectBeacons()
 {
-	mDebugBeacons.reset();
+	mDebugBeacons.clear();
 }
 
 LLViewerObject *LLViewerObjectList::createObjectViewer(const LLPCode pcode, LLViewerRegion *regionp)
@@ -1349,7 +1345,7 @@ LLViewerObject *LLViewerObjectList::createObjectViewer(const LLPCode pcode, LLVi
 
 	mUUIDObjectMap[fullid] = objectp;
 
-	mObjects.put(objectp);
+	mObjects.push_back(objectp);
 
 	updateActive(objectp);
 
@@ -1388,7 +1384,7 @@ LLViewerObject *LLViewerObjectList::createObject(const LLPCode pcode, LLViewerRe
 					gMessageSystem->getSenderIP(),
 					gMessageSystem->getSenderPort());
 
-	mObjects.put(objectp);
+	mObjects.push_back(objectp);
 
 	updateActive(objectp);
 
@@ -1411,11 +1407,11 @@ LLViewerObject *LLViewerObjectList::replaceObject(const LLUUID &id, const LLPCod
 S32 LLViewerObjectList::findReferences(LLDrawable *drawablep) const
 {
 	LLViewerObject *objectp;
-	S32 i;
 	S32 num_refs = 0;
-	for (i = 0; i < mObjects.count(); i++)
+	
+	for (vobj_list_t::const_iterator iter = mObjects.begin(); iter != mObjects.end(); ++iter)
 	{
-		objectp = mObjects[i];
+		objectp = *iter;
 		if (objectp->mDrawable.notNull())
 		{
 			num_refs += objectp->mDrawable->findReferences(drawablep);
@@ -1460,15 +1456,15 @@ void LLViewerObjectList::orphanize(LLViewerObject *childp, U32 parent_id, U32 ip
 	// Unknown parent, add to orpaned child list
 	U64 parent_info = getIndex(parent_id, ip, port);
 
-	if (-1 == mOrphanParents.find(parent_info))
+	if (std::find(mOrphanParents.begin(), mOrphanParents.end(), parent_info) == mOrphanParents.end())
 	{
-		mOrphanParents.put(parent_info);
+		mOrphanParents.push_back(parent_info);
 	}
 
 	LLViewerObjectList::OrphanInfo oi(parent_info, childp->mID);
-	if (-1 == mOrphanChildren.find(oi))
+	if (std::find(mOrphanChildren.begin(), mOrphanChildren.end(), oi) == mOrphanChildren.end())
 	{
-		mOrphanChildren.put(oi);
+		mOrphanChildren.push_back(oi);
 		mNumOrphans++;
 	}
 }
@@ -1491,28 +1487,29 @@ void LLViewerObjectList::findOrphans(LLViewerObject* objectp, U32 ip, U32 port)
 	// 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...
-	if (0 == mOrphanParents.count())
+	if (mOrphanParents.empty())
 	{
 		// no known orphan parents
 		return;
 	}
-	if (-1 == mOrphanParents.find(getIndex(objectp->mLocalID, ip, port)))
+	if (std::find(mOrphanParents.begin(), mOrphanParents.end(), getIndex(objectp->mLocalID, ip, port)) == mOrphanParents.end())
 	{
 		// did not find objectp in OrphanParent list
 		return;
 	}
 
-	S32 i;
 	U64 parent_info = getIndex(objectp->mLocalID, ip, port);
 	BOOL orphans_found = FALSE;
 	// Iterate through the orphan list, and set parents of matching children.
-	for (i = 0; i < mOrphanChildren.count(); i++)
-	{
-		if (mOrphanChildren[i].mParentInfo != parent_info)
+
+	for (std::vector<OrphanInfo>::iterator iter = mOrphanChildren.begin(); iter != mOrphanChildren.end(); )
+	{	
+		if (iter->mParentInfo != parent_info)
 		{
+			++iter;
 			continue;
 		}
-		LLViewerObject *childp = findObject(mOrphanChildren[i].mChildInfo);
+		LLViewerObject *childp = findObject(iter->mChildInfo);
 		if (childp)
 		{
 			if (childp == objectp)
@@ -1546,29 +1543,35 @@ void LLViewerObjectList::findOrphans(LLViewerObject* objectp, U32 ip, U32 port)
 
 			objectp->addChild(childp);
 			orphans_found = TRUE;
+			++iter;
 		}
 		else
 		{
 			llinfos << "Missing orphan child, removing from list" << llendl;
-			mOrphanChildren.remove(i);
-			i--;
+
+			iter = mOrphanChildren.erase(iter);
 		}
 	}
 
 	// Remove orphan parent and children from lists now that they've been found
-	mOrphanParents.remove(mOrphanParents.find(parent_info));
-
-	i = 0;
-	while (i < mOrphanChildren.count())
 	{
-		if (mOrphanChildren[i].mParentInfo == parent_info)
+		std::vector<U64>::iterator iter = std::find(mOrphanParents.begin(), mOrphanParents.end(), parent_info);
+		if (iter != mOrphanParents.end())
+		{
+			mOrphanParents.erase(iter);
+		}
+	}
+	
+	for (std::vector<OrphanInfo>::iterator iter = mOrphanChildren.begin(); iter != mOrphanChildren.end(); )
+	{
+		if (iter->mParentInfo == parent_info)
 		{
-			mOrphanChildren.remove(i);
+			iter = mOrphanChildren.erase(iter);
 			mNumOrphans--;
 		}
 		else
 		{
-			i++;
+			++iter;
 		}
 	}
 
diff --git a/indra/newview/llviewerobjectlist.h b/indra/newview/llviewerobjectlist.h
index ace5c5038e7d39d16d32f0b137eaaf86dd3391f7..8d3d2c4b44a4209728c387d48ac87efb82b1f571 100644
--- a/indra/newview/llviewerobjectlist.h
+++ b/indra/newview/llviewerobjectlist.h
@@ -38,8 +38,6 @@
 
 // common includes
 #include "llstat.h"
-#include "lldarrayptr.h"
-#include "llmap.h"			// *TODO: switch to std::map
 #include "llstring.h"
 
 // project includes
@@ -50,7 +48,7 @@ class LLNetMap;
 class LLDebugBeacon;
 
 const U32 CLOSE_BIN_SIZE = 10;
-const U32 NUM_BINS = 16;
+const U32 NUM_BINS = 128;
 
 // GL name = position in object list + GL_NAME_INDEX_OFFSET so that
 // we can have special numbers like zero.
@@ -111,13 +109,12 @@ class LLViewerObjectList
 	void updateAvatarVisibility();
 
 	// Selection related stuff
-	void renderObjectsForSelect(LLCamera &camera, const LLRect& screen_rect, BOOL pick_parcel_wall = FALSE, BOOL render_transparent = TRUE);
 	void generatePickList(LLCamera &camera);
 	void renderPickList(const LLRect& screen_rect, BOOL pick_parcel_wall, BOOL render_transparent);
 
 	LLViewerObject *getSelectedObject(const U32 object_id);
 
-	inline S32 getNumObjects() { return mObjects.count(); }
+	inline S32 getNumObjects() { return (S32) mObjects.size(); }
 
 	void addToMap(LLViewerObject *objectp);
 	void removeFromMap(LLViewerObject *objectp);
@@ -131,7 +128,7 @@ class LLViewerObjectList
 
 	S32 findReferences(LLDrawable *drawablep) const; // Find references to drawable in all objects, and return value.
 
-	S32 getOrphanParentCount() const { return mOrphanParents.count(); }
+	S32 getOrphanParentCount() const { return (S32) mOrphanParents.size(); }
 	S32 getOrphanCount() const { return mNumOrphans; }
 	void orphanize(LLViewerObject *childp, U32 parent_id, U32 ip, U32 port);
 	void findOrphans(LLViewerObject* objectp, U32 ip, U32 port);
@@ -179,26 +176,28 @@ class LLViewerObjectList
 	S32 mNumUnknownKills;
 	S32 mNumDeadObjects;
 protected:
-	LLDynamicArray<U64>	mOrphanParents;	// LocalID/ip,port of orphaned objects
-	LLDynamicArray<OrphanInfo> mOrphanChildren;	// UUID's of orphaned objects
+	std::vector<U64>	mOrphanParents;	// LocalID/ip,port of orphaned objects
+	std::vector<OrphanInfo> mOrphanChildren;	// UUID's of orphaned objects
 	S32 mNumOrphans;
 
-	LLDynamicArrayPtr<LLPointer<LLViewerObject>, 256> mObjects;
+	typedef std::vector<LLPointer<LLViewerObject> > vobj_list_t;
+
+	vobj_list_t mObjects;
 	std::set<LLPointer<LLViewerObject> > mActiveObjects;
 
-	LLDynamicArrayPtr<LLPointer<LLViewerObject> > mMapObjects;
+	vobj_list_t mMapObjects;
 
 	typedef std::map<LLUUID, LLPointer<LLViewerObject> > vo_map;
 	vo_map mDeadObjects;	// Need to keep multiple entries per UUID
 
 	std::map<LLUUID, LLPointer<LLViewerObject> > mUUIDObjectMap;
 
-	LLDynamicArray<LLDebugBeacon> mDebugBeacons;
+	std::vector<LLDebugBeacon> mDebugBeacons;
 
 	S32 mCurLazyUpdateIndex;
 
 	static U32 sSimulatorMachineIndex;
-	static LLMap<U64, U32> sIPAndPortToIndex;
+	static std::map<U64, U32> sIPAndPortToIndex;
 
 	static std::map<U64, LLUUID> sIndexAndLocalIDToUUID;
 
@@ -260,12 +259,16 @@ inline LLViewerObject *LLViewerObjectList::getObject(const S32 index)
 
 inline void LLViewerObjectList::addToMap(LLViewerObject *objectp)
 {
-	mMapObjects.put(objectp);
+	mMapObjects.push_back(objectp);
 }
 
 inline void LLViewerObjectList::removeFromMap(LLViewerObject *objectp)
 {
-	mMapObjects.removeObj(objectp);
+	std::vector<LLPointer<LLViewerObject> >::iterator iter = std::find(mMapObjects.begin(), mMapObjects.end(), objectp);
+	if (iter != mMapObjects.end())
+	{
+		mMapObjects.erase(iter);
+	}
 }
 
 
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index 0ad269392d178f2c31c72271c9ec4759c768e3d0..06fdb2a3b2c0d429a8c25fca0771b073f6c1cd27 100644
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -496,7 +496,9 @@ void LLViewerTexture::init(bool firstinit)
 	mAdditionalDecodePriority = 0.f ;	
 	mParcelMedia = NULL ;
 	mNumFaces = 0 ;
+	mNumVolumes = 0;
 	mFaceList.clear() ;
+	mVolumeList.clear();
 }
 
 //virtual 
@@ -508,7 +510,7 @@ S8 LLViewerTexture::getType() const
 void LLViewerTexture::cleanup()
 {
 	mFaceList.clear() ;
-	
+	mVolumeList.clear();
 	if(mGLTexturep)
 	{
 		mGLTexturep->cleanup();
@@ -661,6 +663,42 @@ S32 LLViewerTexture::getNumFaces() const
 	return mNumFaces ;
 }
 
+
+//virtual
+void LLViewerTexture::addVolume(LLVOVolume* volumep) 
+{
+	if( mNumVolumes >= mVolumeList.size())
+	{
+		mVolumeList.resize(2 * mNumVolumes + 1) ;		
+	}
+	mVolumeList[mNumVolumes] = volumep ;
+	volumep->setIndexInTex(mNumVolumes) ;
+	mNumVolumes++ ;
+	mLastVolumeListUpdateTimer.reset() ;
+}
+
+//virtual
+void LLViewerTexture::removeVolume(LLVOVolume* volumep) 
+{
+	if(mNumVolumes > 1)
+	{
+		S32 index = volumep->getIndexInTex() ; 
+		mVolumeList[index] = mVolumeList[--mNumVolumes] ;
+		mVolumeList[index]->setIndexInTex(index) ;
+	}
+	else 
+	{
+		mVolumeList.clear() ;
+		mNumVolumes = 0 ;
+	}
+	mLastVolumeListUpdateTimer.reset() ;
+}
+
+S32 LLViewerTexture::getNumVolumes() const
+{
+	return mNumVolumes ;
+}
+
 void LLViewerTexture::reorganizeFaceList()
 {
 	static const F32 MAX_WAIT_TIME = 20.f; // seconds
@@ -680,6 +718,27 @@ void LLViewerTexture::reorganizeFaceList()
 	mFaceList.erase(mFaceList.begin() + mNumFaces, mFaceList.end());
 }
 
+void LLViewerTexture::reorganizeVolumeList()
+{
+	static const F32 MAX_WAIT_TIME = 20.f; // seconds
+	static const U32 MAX_EXTRA_BUFFER_SIZE = 4 ;
+
+	if(mNumVolumes + MAX_EXTRA_BUFFER_SIZE > mVolumeList.size())
+	{
+		return ;
+	}
+
+	if(mLastVolumeListUpdateTimer.getElapsedTimeF32() < MAX_WAIT_TIME)
+	{
+		return ;
+	}
+
+	mLastVolumeListUpdateTimer.reset() ;
+	mVolumeList.erase(mVolumeList.begin() + mNumVolumes, mVolumeList.end());
+}
+
+
+
 //virtual
 void LLViewerTexture::switchToCachedImage()
 {
@@ -1598,6 +1657,7 @@ void LLViewerFetchedTexture::updateVirtualSize()
 	}
 	mNeedsResetMaxVirtualSize = TRUE ;
 	reorganizeFaceList() ;
+	reorganizeVolumeList();
 }
 
 bool LLViewerFetchedTexture::updateFetch()
@@ -3252,6 +3312,7 @@ F32 LLViewerMediaTexture::getMaxVirtualSize()
 
 	mNeedsResetMaxVirtualSize = TRUE ;
 	reorganizeFaceList() ;
+	reorganizeVolumeList();
 
 	return mMaxVirtualSize ;
 }
diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h
index 79d9c4e7bb71207a93a74821f492644d08d97763..85f03b583938ff05c32c8d66b7c955a552264602 100644
--- a/indra/newview/llviewertexture.h
+++ b/indra/newview/llviewertexture.h
@@ -134,7 +134,9 @@ class LLViewerTexture : public LLTexture
 	static S32 getIndexFromCategory(S32 category) ;
 	static S32 getCategoryFromIndex(S32 index) ;
 
-	typedef std::vector<LLFace*> ll_face_list_t ;
+	typedef std::vector<LLFace*> ll_face_list_t;
+	typedef std::vector<LLVOVolume*> ll_volume_list_t;
+
 
 protected:
 	virtual ~LLViewerTexture();
@@ -178,6 +180,11 @@ class LLViewerTexture : public LLTexture
 	S32 getNumFaces() const;
 	const ll_face_list_t* getFaceList() const {return &mFaceList;}
 
+	virtual void addVolume(LLVOVolume* volumep);
+	virtual void removeVolume(LLVOVolume* volumep);
+	S32 getNumVolumes() const;
+	const ll_volume_list_t* getVolumeList() const { return &mVolumeList; }
+
 	void generateGLTexture() ;
 	void destroyGLTexture() ;
 	
@@ -242,7 +249,7 @@ class LLViewerTexture : public LLTexture
 	void cleanup() ;
 	void init(bool firstinit) ;	
 	void reorganizeFaceList() ;
-
+	void reorganizeVolumeList() ;
 private:
 	//note: do not make this function public.
 	/*virtual*/ LLImageGL* getGLTexture() const ;
@@ -269,6 +276,10 @@ class LLViewerTexture : public LLTexture
 	U32               mNumFaces ;
 	LLFrameTimer      mLastFaceListUpdateTimer ;
 
+	ll_volume_list_t  mVolumeList;
+	U32					mNumVolumes;
+	LLFrameTimer	  mLastVolumeListUpdateTimer;
+
 	//do not use LLPointer here.
 	LLViewerMediaTexture* mParcelMedia ;
 
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index 4a86e1ca412d0ff104dcc078e4b9b32996dbefe5..5d1a328b8be88fdf2602f0c1092a668de712ffb5 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -486,6 +486,10 @@ class LLDebugText
 			}
             ypos += y_inc;
 
+			addText(xpos, ypos, llformat("UI Verts/Calls: %d/%d", LLRender::sUIVerts, LLRender::sUICalls));
+			LLRender::sUICalls = LLRender::sUIVerts = 0;
+			ypos += y_inc;
+
 			addText(xpos,ypos, llformat("%d/%d Nodes visible", gPipeline.mNumVisibleNodes, LLSpatialGroup::sNodeCount));
 			
 			ypos += y_inc;
@@ -1358,7 +1362,7 @@ LLViewerWindow::LLViewerWindow(
 		gSavedSettings.getBOOL("DisableVerticalSync"),
 		!gNoRender,
 		ignore_pixel_depth,
-		gSavedSettings.getU32("RenderFSAASamples"));
+		0); //gSavedSettings.getU32("RenderFSAASamples"));
 
 	if (!LLAppViewer::instance()->restoreErrorTrap())
 	{
@@ -1988,12 +1992,15 @@ void LLViewerWindow::drawDebugText()
 {
 	gGL.color4f(1,1,1,1);
 	gGL.pushMatrix();
+	gGL.pushUIMatrix();
 	{
 		// scale view by UI global scale factor and aspect ratio correction factor
-		glScalef(mDisplayScale.mV[VX], mDisplayScale.mV[VY], 1.f);
+		gGL.scaleUI(mDisplayScale.mV[VX], mDisplayScale.mV[VY], 1.f);
 		mDebugText->draw();
 	}
+	gGL.popUIMatrix();
 	gGL.popMatrix();
+
 	gGL.flush();
 }
 
@@ -2041,9 +2048,11 @@ void LLViewerWindow::draw()
 	// No translation needed, this view is glued to 0,0
 
 	gGL.pushMatrix();
+	LLUI::pushMatrix();
 	{
+		
 		// scale view by UI global scale factor and aspect ratio correction factor
-		glScalef(mDisplayScale.mV[VX], mDisplayScale.mV[VY], 1.f);
+		gGL.scaleUI(mDisplayScale.mV[VX], mDisplayScale.mV[VY], 1.f);
 
 		LLVector2 old_scale_factor = LLUI::sGLScaleFactor;
 		// apply camera zoom transform (for high res screenshots)
@@ -2109,6 +2118,7 @@ void LLViewerWindow::draw()
 
 		LLUI::sGLScaleFactor = old_scale_factor;
 	}
+	LLUI::popMatrix();
 	gGL.popMatrix();
 
 #if LL_DEBUG
@@ -2461,6 +2471,9 @@ void append_xui_tooltip(LLView* viewp, LLToolTip::Params& params)
 // event processing.
 void LLViewerWindow::updateUI()
 {
+	static LLFastTimer::DeclareTimer ftm("Update UI");
+	LLFastTimer t(ftm);
+
 	static std::string last_handle_msg;
 
 	// animate layout stacks so we have up to date rect for world view
@@ -3040,7 +3053,6 @@ void LLViewerWindow::saveLastMouse(const LLCoordGL &point)
 // Must be called after displayObjects is called, which sets the mGLName parameter
 // NOTE: This function gets called 3 times:
 //  render_ui_3d: 			FALSE, FALSE, TRUE
-//  renderObjectsForSelect:	TRUE, pick_parcel_wall, FALSE
 //  render_hud_elements:	FALSE, FALSE, FALSE
 void LLViewerWindow::renderSelections( BOOL for_gl_pick, BOOL pick_parcel_walls, BOOL for_hud )
 {
@@ -4705,8 +4717,9 @@ BOOL LLViewerWindow::changeDisplaySettings(BOOL fullscreen, LLCoordScreen size,
 		return TRUE;
 	}
 
-	U32 fsaa = gSavedSettings.getU32("RenderFSAASamples");
-	U32 old_fsaa = mWindow->getFSAASamples();
+	//U32 fsaa = gSavedSettings.getU32("RenderFSAASamples");
+	//U32 old_fsaa = mWindow->getFSAASamples();
+
 	// going from windowed to windowed
 	if (!old_fullscreen && !fullscreen)
 	{
@@ -4716,7 +4729,7 @@ BOOL LLViewerWindow::changeDisplaySettings(BOOL fullscreen, LLCoordScreen size,
 			mWindow->setSize(size);
 		}
 
-		if (fsaa == old_fsaa)
+		//if (fsaa == old_fsaa)
 		{
 			return TRUE;
 		}
@@ -4745,13 +4758,13 @@ BOOL LLViewerWindow::changeDisplaySettings(BOOL fullscreen, LLCoordScreen size,
 		gSavedSettings.setS32("WindowY", old_pos.mY);
 	}
 	
-	mWindow->setFSAASamples(fsaa);
+	//mWindow->setFSAASamples(fsaa);
 
 	result_first_try = mWindow->switchContext(fullscreen, size, disable_vsync);
 	if (!result_first_try)
 	{
 		// try to switch back
-		mWindow->setFSAASamples(old_fsaa);
+		//mWindow->setFSAASamples(old_fsaa);
 		result_second_try = mWindow->switchContext(old_fullscreen, old_size, disable_vsync);
 
 		if (!result_second_try)
diff --git a/indra/newview/llvoclouds.cpp b/indra/newview/llvoclouds.cpp
index 177cb16c50802a5e17ab62533a0c7459ffd220af..5153cef7094960a93c07461af935657b6765568f 100644
--- a/indra/newview/llvoclouds.cpp
+++ b/indra/newview/llvoclouds.cpp
@@ -77,9 +77,11 @@ BOOL LLVOClouds::isActive() const
 	return TRUE;
 }
 
-
 BOOL LLVOClouds::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
 {
+	static LLFastTimer::DeclareTimer ftm("Idle Clouds");
+	LLFastTimer t(ftm);
+
 	if (!(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_CLOUDS)))
 	{
 		return TRUE;
diff --git a/indra/newview/llvotextbubble.cpp b/indra/newview/llvotextbubble.cpp
index 75beab519e0c5406704ced2b2d4ec72a265b9fec..428ef2000648c59e85734a580b6f14ae84f35512 100644
--- a/indra/newview/llvotextbubble.cpp
+++ b/indra/newview/llvotextbubble.cpp
@@ -84,6 +84,9 @@ BOOL LLVOTextBubble::isActive() const
 
 BOOL LLVOTextBubble::idleUpdate(LLAgent &agent, LLWorld	&world, const F64 &time)
 {
+	static LLFastTimer::DeclareTimer ftm("Text Bubble");
+	LLFastTimer t(ftm);
+
 	F32 dt = mUpdateTimer.getElapsedTimeF32();
 	// Die after a few seconds.
 	if (dt > 1.5f)
diff --git a/indra/newview/llvotree.cpp b/indra/newview/llvotree.cpp
index 24f1c4bd246717d25b0840422439fcf7daf8a56e..55e2c58a520fb86b215dd5d2a0fbfc8255c72709 100644
--- a/indra/newview/llvotree.cpp
+++ b/indra/newview/llvotree.cpp
@@ -1141,7 +1141,7 @@ U32 LLVOTree::drawBranchPipeline(LLMatrix4& matrix, U16* indicesp, S32 trunk_LOD
 
 				glLoadMatrixf((F32*) scale_mat.mMatrix);
  				glDrawElements(GL_TRIANGLES, sLODIndexCount[trunk_LOD], GL_UNSIGNED_SHORT, indicesp + sLODIndexOffset[trunk_LOD]);
-				gPipeline.addTrianglesDrawn(LEAF_INDICES/3);
+				gPipeline.addTrianglesDrawn(LEAF_INDICES);
 				stop_glerror();
 				ret += sLODIndexCount[trunk_LOD];
 			}
@@ -1191,7 +1191,7 @@ U32 LLVOTree::drawBranchPipeline(LLMatrix4& matrix, U16* indicesp, S32 trunk_LOD
 			
 				glLoadMatrixf((F32*) scale_mat.mMatrix);
 				glDrawElements(GL_TRIANGLES, LEAF_INDICES, GL_UNSIGNED_SHORT, indicesp);
-				gPipeline.addTrianglesDrawn(LEAF_INDICES/3);							
+				gPipeline.addTrianglesDrawn(LEAF_INDICES);							
 				stop_glerror();
 				ret += LEAF_INDICES;
 			}
@@ -1216,7 +1216,7 @@ U32 LLVOTree::drawBranchPipeline(LLMatrix4& matrix, U16* indicesp, S32 trunk_LOD
 					
 		glLoadMatrixf((F32*) scale_mat.mMatrix);
 		glDrawElements(GL_TRIANGLES, LEAF_INDICES, GL_UNSIGNED_SHORT, indicesp);
-		gPipeline.addTrianglesDrawn(LEAF_INDICES/3);
+		gPipeline.addTrianglesDrawn(LEAF_INDICES);
 		stop_glerror();
 		ret += LEAF_INDICES;
 
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index bfe38c14ba952530b90837f16a02b577dd59e5e3..b87ad7fc478128ac3758cd01ad4bfd0151bf2095 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -192,6 +192,7 @@ LLVOVolume::LLVOVolume(const LLUUID &id, const LLPCode pcode, LLViewerRegion *re
 
 	mMediaImplList.resize(getNumTEs());
 	mLastFetchedMediaVersion = -1;
+	mIndexInTex = 0;
 }
 
 LLVOVolume::~LLVOVolume()
@@ -226,6 +227,11 @@ void LLVOVolume::markDead()
 		{
 			removeMediaImpl(i);
 		}
+
+		if (mSculptTexture.notNull())
+		{
+			mSculptTexture->removeVolume(this);
+		}
 	}
 	
 	LLViewerObject::markDead();
@@ -597,6 +603,9 @@ BOOL LLVOVolume::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
 {
 	LLViewerObject::idleUpdate(agent, world, time);
 
+	static LLFastTimer::DeclareTimer ftm("Volume");
+	LLFastTimer t(ftm);
+
 	if (mDead || mDrawable.isNull())
 	{
 		return TRUE;
@@ -618,6 +627,18 @@ BOOL LLVOVolume::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
 		mVolumeImpl->doIdleUpdate(agent, world, time);
 	}
 
+	const S32 MAX_ACTIVE_OBJECT_QUIET_FRAMES = 40;
+
+	if (mDrawable->isActive())
+	{
+		if (mDrawable->isRoot() && 
+			mDrawable->mQuietCount++ > MAX_ACTIVE_OBJECT_QUIET_FRAMES && 
+			(!mDrawable->getParent() || !mDrawable->getParent()->isActive()))
+		{
+			mDrawable->makeStatic();
+		}
+	}
+
 	return TRUE;
 }
 
@@ -725,7 +746,9 @@ void LLVOVolume::updateTextureVirtualSize()
 	{
 		LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT);
 		LLUUID id =  sculpt_params->getSculptTexture(); 
-		mSculptTexture = LLViewerTextureManager::getFetchedTexture(id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
+		
+		updateSculptTexture();
+		
 		if (mSculptTexture.notNull())
 		{
 			mSculptTexture->setBoostLevel(llmax((S32)mSculptTexture->getBoostLevel(),
@@ -914,35 +937,53 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams &volume_params, const S32 detail
 		{
 			mVolumeImpl->onSetVolume(volume_params, detail);
 		}
-		
+	
+		updateSculptTexture();
+
 		if (isSculpted())
 		{
-			mSculptTexture = LLViewerTextureManager::getFetchedTexture(volume_params.getSculptID(), TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
+			updateSculptTexture();
+
 			if (mSculptTexture.notNull())
 			{
-				//ignore sculpt GL usage since bao fixed this in a separate branch
-				if (!gGLActive)
-				{
-					gGLActive = TRUE;
-					sculpt();
-					gGLActive = FALSE;
-				}
-				else
-				{
-					sculpt();
-				}
+				sculpt();
 			}
 		}
-		else
-		{
-			mSculptTexture = NULL;
-		}
 
 		return TRUE;
 	}
 	return FALSE;
 }
 
+void LLVOVolume::updateSculptTexture()
+{
+	LLPointer<LLViewerFetchedTexture> old_sculpt = mSculptTexture;
+
+	if (isSculpted())
+	{
+		LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT);
+		LLUUID id =  sculpt_params->getSculptTexture(); 
+		mSculptTexture = LLViewerTextureManager::getFetchedTexture(id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
+	}
+	else
+	{
+		mSculptTexture = NULL;
+	}
+
+	if (mSculptTexture != old_sculpt)
+	{
+		if (old_sculpt.notNull())
+		{
+			old_sculpt->removeVolume(this);
+		}
+		if (mSculptTexture.notNull())
+		{
+			mSculptTexture->addVolume(this);
+		}
+	}
+	
+}
+
 // sculpt replaces generate() for sculpted surfaces
 void LLVOVolume::sculpt()
 {	
@@ -1006,6 +1047,17 @@ void LLVOVolume::sculpt()
 			}
 		}
 		getVolume()->sculpt(sculpt_width, sculpt_height, sculpt_components, sculpt_data, discard_level);
+
+		//notify rebuild any other VOVolumes that reference this sculpty volume
+		for (S32 i = 0; i < mSculptTexture->getNumVolumes(); ++i)
+		{
+			LLVOVolume* volume = (*(mSculptTexture->getVolumeList()))[i];
+			if (volume != this && volume->getVolume() == getVolume())
+			{
+				gPipeline.markRebuild(volume->mDrawable, LLDrawable::REBUILD_GEOMETRY, FALSE);
+				volume->mSculptChanged = TRUE;
+			}
+		}
 	}
 }
 
@@ -1035,7 +1087,7 @@ BOOL LLVOVolume::calcLOD()
 	S32 cur_detail = 0;
 	
 	F32 radius = getVolume()->mLODScaleBias.scaledVec(getScale()).length();
-	F32 distance = llmin(mDrawable->mDistanceWRTCamera, MAX_LOD_DISTANCE);
+	F32 distance = mDrawable->mDistanceWRTCamera; //llmin(mDrawable->mDistanceWRTCamera, MAX_LOD_DISTANCE);
 	distance *= sDistanceFactor;
 			
 	F32 rampDist = LLVOVolume::sLODFactor * 2;
@@ -1462,7 +1514,14 @@ void LLVOVolume::updateFaceSize(S32 idx)
 	else
 	{
 		const LLVolumeFace& vol_face = getVolume()->getVolumeFace(idx);
-		facep->setSize(vol_face.mVertices.size(), vol_face.mIndices.size());
+		if (LLPipeline::sUseTriStrips)
+		{
+			facep->setSize(vol_face.mVertices.size(), vol_face.mTriStrip.size());
+		}
+		else
+		{
+			facep->setSize(vol_face.mVertices.size(), vol_face.mIndices.size());
+		}
 	}
 }
 
@@ -3212,6 +3271,11 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
 		draw_info->mExtents[0] = facep->mExtents[0];
 		draw_info->mExtents[1] = facep->mExtents[1];
 		validate_draw_info(*draw_info);
+
+		if (LLPipeline::sUseTriStrips)
+		{
+			draw_info->mDrawMode = LLRender::TRIANGLE_STRIP;
+		}
 	}
 }
 
@@ -3296,7 +3360,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 			drawablep->updateFaceSize(i);
 			LLFace* facep = drawablep->getFace(i);
 
-			if (cur_total > max_total)
+			if (cur_total > max_total || facep->getIndicesCount() <= 0 || facep->getGeomCount() <= 0)
 			{
 				facep->mVertexBuffer = NULL;
 				facep->mLastVertexBuffer = NULL;
diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h
index a287d34402f03cad061218a061f044a96c79962f..a8bb597f93a2cf50203c98f3a030fe509b864055 100644
--- a/indra/newview/llvovolume.h
+++ b/indra/newview/llvovolume.h
@@ -179,8 +179,10 @@ class LLVOVolume : public LLViewerObject
 	/*virtual*/ BOOL 	setMaterial(const U8 material);
 
 				void	setTexture(const S32 face);
-
+				S32     getIndexInTex() const {return mIndexInTex ;}
 	/*virtual*/ BOOL	setVolume(const LLVolumeParams &volume_params, const S32 detail, bool unique_volume = false);
+				void	updateSculptTexture();
+				void    setIndexInTex(S32 index) { mIndexInTex = index ;}
 				void	sculpt();
 				void	updateRelativeXform();
 	/*virtual*/ BOOL	updateGeometry(LLDrawable *drawable);
@@ -303,7 +305,7 @@ class LLVOVolume : public LLViewerObject
 	LLPointer<LLViewerFetchedTexture> mLightTexture;
 	media_list_t mMediaImplList;
 	S32			mLastFetchedMediaVersion; // as fetched from the server, starts as -1
-	
+	S32 mIndexInTex;
 	// statics
 public:
 	static F32 sLODSlopDistanceFactor;// Changing this to zero, effectively disables the LOD transition slop 
diff --git a/indra/newview/llvowlsky.cpp b/indra/newview/llvowlsky.cpp
index 0272a2ab342186523c0846759b57cc0feabbca15..1749ccef94b18918683c6382f54105f44951d9e6 100644
--- a/indra/newview/llvowlsky.cpp
+++ b/indra/newview/llvowlsky.cpp
@@ -519,7 +519,7 @@ void LLVOWLSky::drawDome(void)
 			LLRender::TRIANGLE_STRIP, 
 			0, strips_segment->getRequestedVerts()-1, strips_segment->getRequestedIndices(), 
 			0);
-		gPipeline.addTrianglesDrawn(strips_segment->getRequestedIndices() - 2);
+		gPipeline.addTrianglesDrawn(strips_segment->getRequestedIndices(), LLRender::TRIANGLE_STRIP);
 	}
 
 #else
diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp
index 118d7f8d08d603809a4bee3a4844f07735f49f1e..d7e5b464a65dbeba861aa8b94970b0fa49264835 100644
--- a/indra/newview/llworld.cpp
+++ b/indra/newview/llworld.cpp
@@ -657,6 +657,9 @@ void LLWorld::updateParticles()
 
 void LLWorld::updateClouds(const F32 dt)
 {
+	static LLFastTimer::DeclareTimer ftm("World Clouds");
+	LLFastTimer t(ftm);
+
 	if (gSavedSettings.getBOOL("FreezeTime") ||
 		!gSavedSettings.getBOOL("SkyUseClassicClouds"))
 	{
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index 4f4fc838191bb0fe9922e6e8931b3a931001ba58..91da9e39e07f71abfde2e1a7e95d11ce758d1b1d 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -116,7 +116,6 @@ const F32 BACKLIGHT_DAY_MAGNITUDE_AVATAR = 0.2f;
 const F32 BACKLIGHT_NIGHT_MAGNITUDE_AVATAR = 0.1f;
 const F32 BACKLIGHT_DAY_MAGNITUDE_OBJECT = 0.1f;
 const F32 BACKLIGHT_NIGHT_MAGNITUDE_OBJECT = 0.08f;
-const S32 MAX_ACTIVE_OBJECT_QUIET_FRAMES = 40;
 const S32 MAX_OFFSCREEN_GEOMETRY_CHANGES_PER_FRAME = 10;
 const U32 REFLECTION_MAP_RES = 128;
 
@@ -271,6 +270,7 @@ BOOL	LLPipeline::sDelayVBUpdate = TRUE;
 BOOL	LLPipeline::sFastAlpha = TRUE;
 BOOL	LLPipeline::sDisableShaders = FALSE;
 BOOL	LLPipeline::sRenderBump = TRUE;
+BOOL	LLPipeline::sUseTriStrips = TRUE;
 BOOL	LLPipeline::sUseFarClip = TRUE;
 BOOL	LLPipeline::sShadowRender = FALSE;
 BOOL	LLPipeline::sWaterReflections = FALSE;
@@ -359,6 +359,7 @@ void LLPipeline::init()
 
 	sDynamicLOD = gSavedSettings.getBOOL("RenderDynamicLOD");
 	sRenderBump = gSavedSettings.getBOOL("RenderObjectBump");
+	sUseTriStrips = gSavedSettings.getBOOL("RenderUseTriStrips");
 	sRenderAttachedLights = gSavedSettings.getBOOL("RenderAttachedLights");
 	sRenderAttachedParticles = gSavedSettings.getBOOL("RenderAttachedParticles");
 
@@ -1411,38 +1412,26 @@ void LLPipeline::updateMove()
 
 	assertInitialized();
 
-	for (LLDrawable::drawable_set_t::iterator iter = mRetexturedList.begin();
-		 iter != mRetexturedList.end(); ++iter)
 	{
-		LLDrawable* drawablep = *iter;
-		if (drawablep && !drawablep->isDead())
-		{
-			drawablep->updateTexture();
-		}
-	}
-	mRetexturedList.clear();
-
-	updateMovedList(mMovedList);
+		static LLFastTimer::DeclareTimer ftm("Retexture");
+		LLFastTimer t(ftm);
 
-	for (LLDrawable::drawable_set_t::iterator iter = mActiveQ.begin();
-		 iter != mActiveQ.end(); )
-	{
-		LLDrawable::drawable_set_t::iterator curiter = iter++;
-		LLDrawable* drawablep = *curiter;
-		if (drawablep && !drawablep->isDead()) 
+		for (LLDrawable::drawable_set_t::iterator iter = mRetexturedList.begin();
+			 iter != mRetexturedList.end(); ++iter)
 		{
-			if (drawablep->isRoot() && 
-				drawablep->mQuietCount++ > MAX_ACTIVE_OBJECT_QUIET_FRAMES && 
-				(!drawablep->getParent() || !drawablep->getParent()->isActive()))
+			LLDrawable* drawablep = *iter;
+			if (drawablep && !drawablep->isDead())
 			{
-				drawablep->makeStatic(); // removes drawable and its children from mActiveQ
-				iter = mActiveQ.upper_bound(drawablep); // next valid entry
+				drawablep->updateTexture();
 			}
 		}
-		else
-		{
-			mActiveQ.erase(curiter);
-		}
+		mRetexturedList.clear();
+	}
+
+	{
+		static LLFastTimer::DeclareTimer ftm("Moved List");
+		LLFastTimer t(ftm);
+		updateMovedList(mMovedList);
 	}
 
 	//balance octrees
@@ -3058,12 +3047,6 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate)
 		}
 	}
 
-	if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PICKING))
-	{
-		LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderForSelect");
-		gObjectList.renderObjectsForSelect(camera, gViewerWindow->getWindowRectScaled());
-	}
-	else
 	{
 		LLFastTimer t(FTM_POOLS);
 		
@@ -3514,9 +3497,19 @@ void LLPipeline::renderGeomShadow(LLCamera& camera)
 }
 
 
-void LLPipeline::addTrianglesDrawn(S32 count)
+void LLPipeline::addTrianglesDrawn(S32 index_count, U32 render_type)
 {
 	assertInitialized();
+	S32 count = 0;
+	if (render_type == LLRender::TRIANGLE_STRIP)
+	{
+		count = index_count-2;
+	}
+	else
+	{
+		count = index_count/3;
+	}
+
 	mTrianglesDrawn += count;
 	mBatchCount++;
 	mMaxBatchSize = llmax(mMaxBatchSize, count);
@@ -4797,10 +4790,6 @@ void LLPipeline::findReferences(LLDrawable *drawablep)
 		llinfos << "In mRetexturedList" << llendl;
 	}
 	
-	if (mActiveQ.find(drawablep) != mActiveQ.end())
-	{
-		llinfos << "In mActiveQ" << llendl;
-	}
 	if (std::find(mBuildQ1.begin(), mBuildQ1.end(), drawablep) != mBuildQ1.end())
 	{
 		llinfos << "In mBuildQ1" << llendl;
@@ -4957,19 +4946,6 @@ void LLPipeline::setLight(LLDrawable *drawablep, BOOL is_light)
 	}
 }
 
-void LLPipeline::setActive(LLDrawable *drawablep, BOOL active)
-{
-	assertInitialized();
-	if (active)
-	{
-		mActiveQ.insert(drawablep);
-	}
-	else
-	{
-		mActiveQ.erase(drawablep);
-	}
-}
-
 //static
 void LLPipeline::toggleRenderType(U32 type)
 {
@@ -5385,6 +5361,7 @@ void LLPipeline::resetVertexBuffers(LLDrawable* drawable)
 void LLPipeline::resetVertexBuffers()
 {
 	sRenderBump = gSavedSettings.getBOOL("RenderObjectBump");
+	sUseTriStrips = gSavedSettings.getBOOL("RenderUseTriStrips");
 
 	for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
 			iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h
index 67004a5f2d921cba497d8961dfde0eedc9190620..1bf2ee941b49226168e6cffc53fb4d6439701c26 100644
--- a/indra/newview/pipeline.h
+++ b/indra/newview/pipeline.h
@@ -270,15 +270,14 @@ class LLPipeline
 	void shiftObjects(const LLVector3 &offset);
 
 	void setLight(LLDrawable *drawablep, BOOL is_light);
-	void setActive(LLDrawable *drawablep, BOOL active);
-
+	
 	BOOL hasRenderBatches(const U32 type) const;
 	LLCullResult::drawinfo_list_t::iterator beginRenderMap(U32 type);
 	LLCullResult::drawinfo_list_t::iterator endRenderMap(U32 type);
 	LLCullResult::sg_list_t::iterator beginAlphaGroups();
 	LLCullResult::sg_list_t::iterator endAlphaGroups();
 	
-	void addTrianglesDrawn(S32 count);
+	void addTrianglesDrawn(S32 index_count, U32 render_type = LLRender::TRIANGLES);
 	BOOL hasRenderType(const U32 type) const				{ return (type && (mRenderTypeMask & (1<<type))) ? TRUE : FALSE; }
 	BOOL hasRenderDebugFeatureMask(const U32 mask) const	{ return (mRenderDebugFeatureMask & mask) ? TRUE : FALSE; }
 	BOOL hasRenderDebugMask(const U32 mask) const			{ return (mRenderDebugMask & mask) ? TRUE : FALSE; }
@@ -448,7 +447,7 @@ class LLPipeline
 	static BOOL				sFastAlpha;
 	static BOOL				sDisableShaders; // if TRUE, rendering will be done without shaders
 	static BOOL				sRenderBump;
-	static BOOL				sUseFBO;
+	static BOOL				sUseTriStrips;
 	static BOOL				sUseFarClip;
 	static BOOL				sShadowRender;
 	static BOOL				sWaterReflections;
@@ -589,8 +588,6 @@ class LLPipeline
 
 	LLViewerObject::vobj_list_t		mCreateQ;
 		
-	LLDrawable::drawable_set_t		mActiveQ;
-	
 	LLDrawable::drawable_set_t		mRetexturedList;
 
 	class HighlightItem