diff --git a/indra/llcommon/llmemtype.h b/indra/llcommon/llmemtype.h
index 9bf6cad9f7ca5626b1cdfe4be8cececbb48a173c..2e275bd523dfd36fbaf8b937ec4fab1c9d5a015c 100644
--- a/indra/llcommon/llmemtype.h
+++ b/indra/llcommon/llmemtype.h
@@ -84,6 +84,9 @@ class LLMemType
 		MTYPE_REGIONS,
 		MTYPE_INVENTORY,
 		MTYPE_ANIMATION,
+		MTYPE_VOLUME,
+		MTYPE_PRIMITIVE,
+
 		MTYPE_NETWORK,
 		MTYPE_PHYSICS,
 		MTYPE_INTERESTLIST,
diff --git a/indra/llcommon/llversionviewer.h b/indra/llcommon/llversionviewer.h
index a1fd0ff509cbeccc891eb2fb0cdd4f51470f9df2..dbf1d3154b1982862a763887fe7e3e4de51656c7 100644
--- a/indra/llcommon/llversionviewer.h
+++ b/indra/llcommon/llversionviewer.h
@@ -34,7 +34,7 @@
 
 const S32 LL_VERSION_MAJOR = 1;
 const S32 LL_VERSION_MINOR = 20;
-const S32 LL_VERSION_PATCH = 2;
+const S32 LL_VERSION_PATCH = 4;
 const S32 LL_VERSION_BUILD = 0;
 
 const char * const LL_CHANNEL = "Second Life Release";
diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp
index c8cfad84f687597de79cb8c5b76de4d39caa09a7..29486753966aedabd662a6cf9065e341155a5500 100644
--- a/indra/llimage/llimage.cpp
+++ b/indra/llimage/llimage.cpp
@@ -768,8 +768,8 @@ void LLImageRaw::copyScaled( LLImageRaw* src )
 	LLMemType mt1((LLMemType::EMemType)mMemType);
 	LLImageRaw* dst = this;  // Just for clarity.
 
-	llassert( (1 == src->getComponents()) || (3 == src->getComponents()) || (4 == src->getComponents()) );
-	llassert( src->getComponents() == dst->getComponents() );
+	llassert_always( (1 == src->getComponents()) || (3 == src->getComponents()) || (4 == src->getComponents()) );
+	llassert_always( src->getComponents() == dst->getComponents() );
 
 	if( (src->getWidth() == dst->getWidth()) && (src->getHeight() == dst->getHeight()) )
 	{
@@ -779,6 +779,7 @@ void LLImageRaw::copyScaled( LLImageRaw* src )
 
 	// Vertical
 	S32 temp_data_size = src->getWidth() * dst->getHeight() * getComponents();
+	llassert_always(temp_data_size > 0);
 	U8* temp_buffer = new U8[ temp_data_size ];
 	for( S32 col = 0; col < src->getWidth(); col++ )
 	{
diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp
index a0990c5fc1929d061c351f998e859f14b5eef910..f4052f336f509eb72a8f3b0be278494e40ffe33f 100644
--- a/indra/llmath/llvolume.cpp
+++ b/indra/llmath/llvolume.cpp
@@ -34,6 +34,7 @@
 #include <set>
 
 #include "llerror.h"
+#include "llmemtype.h"
 
 #include "llvolumemgr.h"
 #include "v2math.h"
@@ -155,6 +156,8 @@ BOOL LLTriangleLineSegmentIntersect( const LLVector3& pt1, const LLVector3& pt2,
 
 LLProfile::Face* LLProfile::addCap(S16 faceID)
 {
+	LLMemType m1(LLMemType::MTYPE_VOLUME);
+	
 	Face *face   = vector_append(mFaces, 1);
 	
 	face->mIndex = 0;
@@ -167,6 +170,8 @@ LLProfile::Face* LLProfile::addCap(S16 faceID)
 
 LLProfile::Face* LLProfile::addFace(S32 i, S32 count, F32 scaleU, S16 faceID, BOOL flat)
 {
+	LLMemType m1(LLMemType::MTYPE_VOLUME);
+	
 	Face *face   = vector_append(mFaces, 1);
 	
 	face->mIndex = i;
@@ -182,8 +187,10 @@ LLProfile::Face* LLProfile::addFace(S32 i, S32 count, F32 scaleU, S16 faceID, BO
 // What is the bevel parameter used for? - DJS 04/05/02
 // Bevel parameter is currently unused but presumedly would support
 // filleted and chamfered corners
-void LLProfile::genNGon(S32 sides, F32 offset, F32 bevel, F32 ang_scale, S32 split)
+void LLProfile::genNGon(const LLProfileParams& params, S32 sides, F32 offset, F32 bevel, F32 ang_scale, S32 split)
 {
+	LLMemType m1(LLMemType::MTYPE_VOLUME);
+	
 	// Generate an n-sided "circular" path.
 	// 0 is (1,0), and we go counter-clockwise along a circular path from there.
 	const F32 tableScale[] = { 1, 1, 1, 0.5f, 0.707107f, 0.53f, 0.525f, 0.5f };
@@ -194,8 +201,8 @@ void LLProfile::genNGon(S32 sides, F32 offset, F32 bevel, F32 ang_scale, S32 spl
 	mMaxX = 0.f;
 	mMinX = 0.f;
 
-	F32 begin  = mParams.getBegin();
-	F32 end    = mParams.getEnd();
+	F32 begin  = params.getBegin();
+	F32 end    = params.getEnd();
 
 	t_step = 1.0f / sides;
 	ang_step = 2.0f*F_PI*t_step*ang_scale;
@@ -311,7 +318,7 @@ void LLProfile::genNGon(S32 sides, F32 offset, F32 bevel, F32 ang_scale, S32 spl
 			mConcave = FALSE;
 		}
 		mOpen = TRUE;
-		if (!isHollow())
+		if (params.getHollow() <= 0)
 		{
 			// put center point if not hollow.
 			mProfile.push_back(LLVector3(0,0,0));
@@ -327,7 +334,7 @@ void LLProfile::genNGon(S32 sides, F32 offset, F32 bevel, F32 ang_scale, S32 spl
 	mTotal = mProfile.size();
 }
 
-void LLProfile::genNormals()
+void LLProfile::genNormals(const LLProfileParams& params)
 {
 	S32 count = mProfile.size();
 
@@ -347,8 +354,7 @@ void LLProfile::genNormals()
 
 	LLVector2 pt0,pt1;
 
-	BOOL hollow;
-	hollow = isHollow();
+	BOOL hollow = (params.getHollow() > 0);
 
 	S32 i0, i1, i2, i3, i4;
 
@@ -428,7 +434,7 @@ void LLProfile::genNormals()
 // Hollow is percent of the original bounding box, not of this particular
 // profile's geometry.  Thus, a swept triangle needs lower hollow values than
 // a swept square.
-LLProfile::Face* LLProfile::addHole(BOOL flat, F32 sides, F32 offset, F32 box_hollow, F32 ang_scale, S32 split)
+LLProfile::Face* LLProfile::addHole(const LLProfileParams& params, BOOL flat, F32 sides, F32 offset, F32 box_hollow, F32 ang_scale, S32 split)
 {
 	// Note that addHole will NOT work for non-"circular" profiles, if we ever decide to use them.
 
@@ -436,11 +442,12 @@ LLProfile::Face* LLProfile::addHole(BOOL flat, F32 sides, F32 offset, F32 box_ho
 	mTotalOut = mTotal;
 
 	// Why is the "bevel" parameter -1? DJS 04/05/02
-	genNGon(llfloor(sides),offset,-1, ang_scale, split);
+	genNGon(params, llfloor(sides),offset,-1, ang_scale, split);
 
 	Face *face = addFace(mTotalOut, mTotal-mTotalOut,0,LL_FACE_INNER_SIDE, flat);
 
-	LLVector3 pt[128];
+	std::vector<LLVector3> pt;
+	pt.resize(mTotal) ;
 
 	for (S32 i=mTotalOut;i<mTotal;i++)
 	{
@@ -489,8 +496,10 @@ S32 sculpt_sides(F32 detail)
 }
 
 
-BOOL LLProfile::generate(BOOL path_open,F32 detail, S32 split, BOOL is_sculpted)
+BOOL LLProfile::generate(const LLProfileParams& params, BOOL path_open,F32 detail, S32 split, BOOL is_sculpted)
 {
+	LLMemType m1(LLMemType::MTYPE_VOLUME);
+	
 	if ((!mDirty) && (!is_sculpted))
 	{
 		return FALSE;
@@ -508,9 +517,9 @@ BOOL LLProfile::generate(BOOL path_open,F32 detail, S32 split, BOOL is_sculpted)
 
 	// Generate the face data
 	S32 i;
-	F32 begin = mParams.getBegin();
-	F32 end = mParams.getEnd();
-	F32 hollow = mParams.getHollow();
+	F32 begin = params.getBegin();
+	F32 end = params.getEnd();
+	F32 hollow = params.getHollow();
 
 	// Quick validation to eliminate some server crashes.
 	if (begin > end - 0.01f)
@@ -521,11 +530,11 @@ BOOL LLProfile::generate(BOOL path_open,F32 detail, S32 split, BOOL is_sculpted)
 
 	S32 face_num = 0;
 
-	switch (mParams.getCurveType() & LL_PCODE_PROFILE_MASK)
+	switch (params.getCurveType() & LL_PCODE_PROFILE_MASK)
 	{
 	case LL_PCODE_PROFILE_SQUARE:
 		{
-			genNGon(4,-0.375, 0, 1, split);
+			genNGon(params, 4,-0.375, 0, 1, split);
 			if (path_open)
 			{
 				addCap (LL_FACE_PATH_BEGIN);
@@ -544,20 +553,20 @@ BOOL LLProfile::generate(BOOL path_open,F32 detail, S32 split, BOOL is_sculpted)
 
 			if (hollow)
 			{
-				switch (mParams.getCurveType() & LL_PCODE_HOLE_MASK)
+				switch (params.getCurveType() & LL_PCODE_HOLE_MASK)
 				{
 				case LL_PCODE_HOLE_TRIANGLE:
 					// This offset is not correct, but we can't change it now... DK 11/17/04
-					addHole(TRUE, 3, -0.375f, hollow, 1.f, split);
+				  	addHole(params, TRUE, 3, -0.375f, hollow, 1.f, split);
 					break;
 				case LL_PCODE_HOLE_CIRCLE:
 					// TODO: Compute actual detail levels for cubes
-					addHole(FALSE, MIN_DETAIL_FACES * detail, -0.375f, hollow, 1.f);
+				  	addHole(params, FALSE, MIN_DETAIL_FACES * detail, -0.375f, hollow, 1.f);
 					break;
 				case LL_PCODE_HOLE_SAME:
 				case LL_PCODE_HOLE_SQUARE:
 				default:
-					addHole(TRUE, 4, -0.375f, hollow, 1.f, split);
+					addHole(params, TRUE, 4, -0.375f, hollow, 1.f, split);
 					break;
 				}
 			}
@@ -571,7 +580,7 @@ BOOL LLProfile::generate(BOOL path_open,F32 detail, S32 split, BOOL is_sculpted)
 	case  LL_PCODE_PROFILE_RIGHTTRI:
 	case  LL_PCODE_PROFILE_EQUALTRI:
 		{
-			genNGon(3,0, 0, 1, split);
+			genNGon(params, 3,0, 0, 1, split);
 			for (i = 0; i <(S32) mProfile.size(); i++)
 			{
 				// Scale by 3 to generate proper tex coords.
@@ -593,19 +602,19 @@ BOOL LLProfile::generate(BOOL path_open,F32 detail, S32 split, BOOL is_sculpted)
 				// because the triangle doesn't fill the bounding box.
 				F32 triangle_hollow = hollow / 2.f;
 
-				switch (mParams.getCurveType() & LL_PCODE_HOLE_MASK)
+				switch (params.getCurveType() & LL_PCODE_HOLE_MASK)
 				{
 				case LL_PCODE_HOLE_CIRCLE:
 					// TODO: Actually generate level of detail for triangles
-					addHole(FALSE, MIN_DETAIL_FACES * detail, 0, triangle_hollow, 1.f);
+					addHole(params, FALSE, MIN_DETAIL_FACES * detail, 0, triangle_hollow, 1.f);
 					break;
 				case LL_PCODE_HOLE_SQUARE:
-					addHole(TRUE, 4, 0, triangle_hollow, 1.f, split);
+					addHole(params, TRUE, 4, 0, triangle_hollow, 1.f, split);
 					break;
 				case LL_PCODE_HOLE_SAME:
 				case LL_PCODE_HOLE_TRIANGLE:
 				default:
-					addHole(TRUE, 3, 0, triangle_hollow, 1.f, split);
+					addHole(params, TRUE, 3, 0, triangle_hollow, 1.f, split);
 					break;
 				}
 			}
@@ -619,7 +628,7 @@ BOOL LLProfile::generate(BOOL path_open,F32 detail, S32 split, BOOL is_sculpted)
 			F32 circle_detail = MIN_DETAIL_FACES * detail;
 			if (hollow)
 			{
-				hole_type = mParams.getCurveType() & LL_PCODE_HOLE_MASK;
+				hole_type = params.getCurveType() & LL_PCODE_HOLE_MASK;
 				if (hole_type == LL_PCODE_HOLE_SQUARE)
 				{
 					// Snap to the next multiple of four sides,
@@ -633,7 +642,7 @@ BOOL LLProfile::generate(BOOL path_open,F32 detail, S32 split, BOOL is_sculpted)
 			if (is_sculpted)
 				sides = sculpt_sides(detail);
 			
-			genNGon(sides);
+			genNGon(params, sides);
 			
 			if (path_open)
 			{
@@ -654,15 +663,15 @@ BOOL LLProfile::generate(BOOL path_open,F32 detail, S32 split, BOOL is_sculpted)
 				switch (hole_type)
 				{
 				case LL_PCODE_HOLE_SQUARE:
-					addHole(TRUE, 4, 0, hollow, 1.f, split);
+					addHole(params, TRUE, 4, 0, hollow, 1.f, split);
 					break;
 				case LL_PCODE_HOLE_TRIANGLE:
-					addHole(TRUE, 3, 0, hollow, 1.f, split);
+					addHole(params, TRUE, 3, 0, hollow, 1.f, split);
 					break;
 				case LL_PCODE_HOLE_CIRCLE:
 				case LL_PCODE_HOLE_SAME:
 				default:
-					addHole(FALSE, circle_detail, 0, hollow, 1.f);
+					addHole(params, FALSE, circle_detail, 0, hollow, 1.f);
 					break;
 				}
 			}
@@ -677,7 +686,7 @@ BOOL LLProfile::generate(BOOL path_open,F32 detail, S32 split, BOOL is_sculpted)
 			F32 circle_detail = MIN_DETAIL_FACES * detail * 0.5f;
 			if (hollow)
 			{
-				hole_type = mParams.getCurveType() & LL_PCODE_HOLE_MASK;
+				hole_type = params.getCurveType() & LL_PCODE_HOLE_MASK;
 				if (hole_type == LL_PCODE_HOLE_SQUARE)
 				{
 					// Snap to the next multiple of four sides (div 2),
@@ -685,12 +694,12 @@ BOOL LLProfile::generate(BOOL path_open,F32 detail, S32 split, BOOL is_sculpted)
 					circle_detail = llceil(circle_detail / 2.0f) * 2.0f;
 				}
 			}
-			genNGon(llfloor(circle_detail), 0.5f, 0.f, 0.5f);
+			genNGon(params, llfloor(circle_detail), 0.5f, 0.f, 0.5f);
 			if (path_open)
 			{
 				addCap(LL_FACE_PATH_BEGIN);
 			}
-			if (mOpen && !mParams.getHollow())
+			if (mOpen && !params.getHollow())
 			{
 				addFace(0,mTotal-1,0,LL_FACE_OUTER_SIDE_0, FALSE);
 			}
@@ -704,21 +713,21 @@ BOOL LLProfile::generate(BOOL path_open,F32 detail, S32 split, BOOL is_sculpted)
 				switch (hole_type)
 				{
 				case LL_PCODE_HOLE_SQUARE:
-					addHole(TRUE, 2, 0.5f, hollow, 0.5f, split);
+					addHole(params, TRUE, 2, 0.5f, hollow, 0.5f, split);
 					break;
 				case LL_PCODE_HOLE_TRIANGLE:
-					addHole(TRUE, 3,  0.5f, hollow, 0.5f, split);
+					addHole(params, TRUE, 3,  0.5f, hollow, 0.5f, split);
 					break;
 				case LL_PCODE_HOLE_CIRCLE:
 				case LL_PCODE_HOLE_SAME:
 				default:
-					addHole(FALSE, circle_detail,  0.5f, hollow, 0.5f);
+					addHole(params, FALSE, circle_detail,  0.5f, hollow, 0.5f);
 					break;
 				}
 			}
 
 			// Special case for openness of sphere
-			if ((mParams.getEnd() - mParams.getBegin()) < 1.f)
+			if ((params.getEnd() - params.getBegin()) < 1.f)
 			{
 				mOpen = TRUE;
 			}
@@ -731,7 +740,7 @@ BOOL LLProfile::generate(BOOL path_open,F32 detail, S32 split, BOOL is_sculpted)
 		}
 		break;
 	default:
-	    llerrs << "Unknown profile: getCurveType()=" << mParams.getCurveType() << llendl;
+	    llerrs << "Unknown profile: getCurveType()=" << params.getCurveType() << llendl;
 		break;
 	};
 
@@ -754,7 +763,7 @@ BOOL LLProfile::generate(BOOL path_open,F32 detail, S32 split, BOOL is_sculpted)
 		}
 	}
 	
-	//genNormals();
+	//genNormals(params);
 
 	return TRUE;
 }
@@ -763,6 +772,8 @@ BOOL LLProfile::generate(BOOL path_open,F32 detail, S32 split, BOOL is_sculpted)
 
 BOOL LLProfileParams::importFile(FILE *fp)
 {
+	LLMemType m1(LLMemType::MTYPE_VOLUME);
+	
 	const S32 BUFSIZE = 16384;
 	char buffer[BUFSIZE];	/* Flawfinder: ignore */
 	// *NOTE: changing the size or type of these buffers will require
@@ -838,6 +849,8 @@ BOOL LLProfileParams::exportFile(FILE *fp) const
 
 BOOL LLProfileParams::importLegacyStream(std::istream& input_stream)
 {
+	LLMemType m1(LLMemType::MTYPE_VOLUME);
+	
 	const S32 BUFSIZE = 16384;
 	char buffer[BUFSIZE];	/* Flawfinder: ignore */
 	// *NOTE: changing the size or type of these buffers will require
@@ -929,6 +942,7 @@ bool LLProfileParams::fromLLSD(LLSD& sd)
 
 void LLProfileParams::copyParams(const LLProfileParams &params)
 {
+	LLMemType m1(LLMemType::MTYPE_VOLUME);
 	setCurveType(params.getCurveType());
 	setBegin(params.getBegin());
 	setEnd(params.getEnd());
@@ -940,22 +954,22 @@ LLPath::~LLPath()
 {
 }
 
-void LLPath::genNGon(S32 sides, F32 startOff, F32 end_scale, F32 twist_scale)
+void LLPath::genNGon(const LLPathParams& params, S32 sides, F32 startOff, F32 end_scale, F32 twist_scale)
 {
 	// Generates a circular path, starting at (1, 0, 0), counterclockwise along the xz plane.
 	const F32 tableScale[] = { 1, 1, 1, 0.5f, 0.707107f, 0.53f, 0.525f, 0.5f };
 
-	F32 revolutions = mParams.getRevolutions();
-	F32 skew		= mParams.getSkew();
+	F32 revolutions = params.getRevolutions();
+	F32 skew		= params.getSkew();
 	F32 skew_mag	= fabs(skew);
-	F32 hole_x		= mParams.getScaleX() * (1.0f - skew_mag);
-	F32 hole_y		= mParams.getScaleY();
+	F32 hole_x		= params.getScaleX() * (1.0f - skew_mag);
+	F32 hole_y		= params.getScaleY();
 
 	// Calculate taper begin/end for x,y (Negative means taper the beginning)
 	F32 taper_x_begin	= 1.0f;
-	F32 taper_x_end		= 1.0f - mParams.getTaperX();
+	F32 taper_x_end		= 1.0f - params.getTaperX();
 	F32	taper_y_begin	= 1.0f;
-	F32	taper_y_end		= 1.0f - mParams.getTaperY();
+	F32	taper_y_end		= 1.0f - params.getTaperY();
 
 	if ( taper_x_end > 1.0f )
 	{
@@ -983,7 +997,7 @@ void LLPath::genNGon(S32 sides, F32 startOff, F32 end_scale, F32 twist_scale)
 	// Now check the radius offset to calculate the start,end radius.  (Negative means
 	// decrease the start radius instead).
 	F32 radius_end    = radius_start;
-	F32 radius_offset = mParams.getRadiusOffset();
+	F32 radius_offset = params.getRadiusOffset();
 	if (radius_offset < 0.f)
 	{
 		radius_start *= 1.f + radius_offset;
@@ -994,7 +1008,7 @@ void LLPath::genNGon(S32 sides, F32 startOff, F32 end_scale, F32 twist_scale)
 	}	
 
 	// Is the path NOT a closed loop?
-	mOpen = ( (mParams.getEnd()*end_scale - mParams.getBegin() < 1.0f) ||
+	mOpen = ( (params.getEnd()*end_scale - params.getBegin() < 1.0f) ||
 		      (skew_mag > 0.001f) ||
 			  (fabs(taper_x_end - taper_x_begin) > 0.001f) ||
 			  (fabs(taper_y_end - taper_y_begin) > 0.001f) ||
@@ -1005,22 +1019,22 @@ void LLPath::genNGon(S32 sides, F32 startOff, F32 end_scale, F32 twist_scale)
 	PathPt *pt;
 	LLVector3 path_axis (1.f, 0.f, 0.f);
 	//LLVector3 twist_axis(0.f, 0.f, 1.f);
-	F32 twist_begin = mParams.getTwistBegin() * twist_scale;
-	F32 twist_end	= mParams.getTwist() * twist_scale;
+	F32 twist_begin = params.getTwistBegin() * twist_scale;
+	F32 twist_end	= params.getTwist() * twist_scale;
 
 	// We run through this once before the main loop, to make sure
 	// the path begins at the correct cut.
 	F32 step= 1.0f / sides;
-	F32 t	= mParams.getBegin();
+	F32 t	= params.getBegin();
 	pt		= vector_append(mPath, 1);
 	ang		= 2.0f*F_PI*revolutions * t;
 	s		= sin(ang)*lerp(radius_start, radius_end, t);	
 	c		= cos(ang)*lerp(radius_start, radius_end, t);
 
 
-	pt->mPos.setVec(0 + lerp(0,mParams.getShear().mV[0],s)
+	pt->mPos.setVec(0 + lerp(0,params.getShear().mV[0],s)
 					  + lerp(-skew ,skew, t) * 0.5f,
-					c + lerp(0,mParams.getShear().mV[1],s), 
+					c + lerp(0,params.getShear().mV[1],s), 
 					s);
 	pt->mScale.mV[VX] = hole_x * lerp(taper_x_begin, taper_x_end, t);
 	pt->mScale.mV[VY] = hole_y * lerp(taper_y_begin, taper_y_end, t);
@@ -1039,7 +1053,7 @@ void LLPath::genNGon(S32 sides, F32 startOff, F32 end_scale, F32 twist_scale)
 	t = ((S32)(t * sides)) / (F32)sides;
 
 	// Run through the non-cut dependent points.
-	while (t < mParams.getEnd())
+	while (t < params.getEnd())
 	{
 		pt		= vector_append(mPath, 1);
 
@@ -1047,9 +1061,9 @@ void LLPath::genNGon(S32 sides, F32 startOff, F32 end_scale, F32 twist_scale)
 		c   = cos(ang)*lerp(radius_start, radius_end, t);
 		s   = sin(ang)*lerp(radius_start, radius_end, t);
 
-		pt->mPos.setVec(0 + lerp(0,mParams.getShear().mV[0],s)
+		pt->mPos.setVec(0 + lerp(0,params.getShear().mV[0],s)
 					      + lerp(-skew ,skew, t) * 0.5f,
-						c + lerp(0,mParams.getShear().mV[1],s), 
+						c + lerp(0,params.getShear().mV[1],s), 
 						s);
 
 		pt->mScale.mV[VX] = hole_x * lerp(taper_x_begin, taper_x_end, t);
@@ -1066,15 +1080,15 @@ void LLPath::genNGon(S32 sides, F32 startOff, F32 end_scale, F32 twist_scale)
 	}
 
 	// Make one final pass for the end cut.
-	t = mParams.getEnd();
+	t = params.getEnd();
 	pt		= vector_append(mPath, 1);
 	ang = 2.0f*F_PI*revolutions * t;
 	c   = cos(ang)*lerp(radius_start, radius_end, t);
 	s   = sin(ang)*lerp(radius_start, radius_end, t);
 
-	pt->mPos.setVec(0 + lerp(0,mParams.getShear().mV[0],s)
+	pt->mPos.setVec(0 + lerp(0,params.getShear().mV[0],s)
 					  + lerp(-skew ,skew, t) * 0.5f,
-					c + lerp(0,mParams.getShear().mV[1],s), 
+					c + lerp(0,params.getShear().mV[1],s), 
 					s);
 	pt->mScale.mV[VX] = hole_x * lerp(taper_x_begin, taper_x_end, t);
 	pt->mScale.mV[VY] = hole_y * lerp(taper_y_begin, taper_y_end, t);
@@ -1117,8 +1131,10 @@ const LLVector2 LLPathParams::getEndScale() const
 	return end_scale;
 }
 
-BOOL LLPath::generate(F32 detail, S32 split, BOOL is_sculpted)
+BOOL LLPath::generate(const LLPathParams& params, F32 detail, S32 split, BOOL is_sculpted)
 {
+	LLMemType m1(LLMemType::MTYPE_VOLUME);
+	
 	if ((!mDirty) && (!is_sculpted))
 	{
 		return FALSE;
@@ -1137,13 +1153,13 @@ BOOL LLPath::generate(F32 detail, S32 split, BOOL is_sculpted)
 	mOpen = TRUE;
 
 	// Is this 0xf0 mask really necessary?  DK 03/02/05
-	switch (mParams.getCurveType() & 0xf0)
+	switch (params.getCurveType() & 0xf0)
 	{
 	default:
 	case LL_PCODE_PATH_LINE:
 		{
 			// Take the begin/end twist into account for detail.
-			np    = llfloor(fabs(mParams.getTwistBegin() - mParams.getTwist()) * 3.5f * (detail-0.5f)) + 2;
+			np    = llfloor(fabs(params.getTwistBegin() - params.getTwist()) * 3.5f * (detail-0.5f)) + 2;
 			if (np < split+2)
 			{
 				np = split+2;
@@ -1153,16 +1169,16 @@ BOOL LLPath::generate(F32 detail, S32 split, BOOL is_sculpted)
 			
 			mPath.resize(np);
 
-			LLVector2 start_scale = mParams.getBeginScale();
-			LLVector2 end_scale = mParams.getEndScale();
+			LLVector2 start_scale = params.getBeginScale();
+			LLVector2 end_scale = params.getEndScale();
 
 			for (S32 i=0;i<np;i++)
 			{
-				F32 t = lerp(mParams.getBegin(),mParams.getEnd(),(F32)i * mStep);
-				mPath[i].mPos.setVec(lerp(0,mParams.getShear().mV[0],t),
-									 lerp(0,mParams.getShear().mV[1],t),
+				F32 t = lerp(params.getBegin(),params.getEnd(),(F32)i * mStep);
+				mPath[i].mPos.setVec(lerp(0,params.getShear().mV[0],t),
+									 lerp(0,params.getShear().mV[1],t),
 									 t - 0.5f);
-				mPath[i].mRot.setQuat(lerp(F_PI * mParams.getTwistBegin(),F_PI * mParams.getTwist(),t),0,0,1);
+				mPath[i].mRot.setQuat(lerp(F_PI * params.getTwistBegin(),F_PI * params.getTwist(),t),0,0,1);
 				mPath[i].mScale.mV[0] = lerp(start_scale.mV[0],end_scale.mV[0],t);
 				mPath[i].mScale.mV[1] = lerp(start_scale.mV[1],end_scale.mV[1],t);
 				mPath[i].mTexT        = t;
@@ -1173,27 +1189,27 @@ BOOL LLPath::generate(F32 detail, S32 split, BOOL is_sculpted)
 	case LL_PCODE_PATH_CIRCLE:
 		{
 			// Increase the detail as the revolutions and twist increase.
-			F32 twist_mag = fabs(mParams.getTwistBegin() - mParams.getTwist());
+			F32 twist_mag = fabs(params.getTwistBegin() - params.getTwist());
 
-			S32 sides = (S32)llfloor(llfloor((MIN_DETAIL_FACES * detail + twist_mag * 3.5f * (detail-0.5f))) * mParams.getRevolutions());
+			S32 sides = (S32)llfloor(llfloor((MIN_DETAIL_FACES * detail + twist_mag * 3.5f * (detail-0.5f))) * params.getRevolutions());
 
 			if (is_sculpted)
 				sides = sculpt_sides(detail);
 			
-			genNGon(sides);
+			genNGon(params, sides);
 		}
 		break;
 
 	case LL_PCODE_PATH_CIRCLE2:
 		{
-			if (mParams.getEnd() - mParams.getBegin() >= 0.99f &&
-				mParams.getScaleX() >= .99f)
+			if (params.getEnd() - params.getBegin() >= 0.99f &&
+				params.getScaleX() >= .99f)
 			{
 				mOpen = FALSE;
 			}
 
-			//genNGon(llfloor(MIN_DETAIL_FACES * detail), 4.f, 0.f);
-			genNGon(llfloor(MIN_DETAIL_FACES * detail));
+			//genNGon(params, llfloor(MIN_DETAIL_FACES * detail), 4.f, 0.f);
+			genNGon(params, llfloor(MIN_DETAIL_FACES * detail));
 
 			F32 t     = 0.f;
 			F32 tStep = 1.0f / mPath.size();
@@ -1223,28 +1239,30 @@ BOOL LLPath::generate(F32 detail, S32 split, BOOL is_sculpted)
 		{
 			F32 t = (F32)i * mStep;
 			mPath[i].mPos.setVec(0,
-								lerp(0,   -sin(F_PI*mParams.getTwist()*t)*0.5f,t),
-								lerp(-0.5, cos(F_PI*mParams.getTwist()*t)*0.5f,t));
-			mPath[i].mScale.mV[0] = lerp(1,mParams.getScale().mV[0],t);
-			mPath[i].mScale.mV[1] = lerp(1,mParams.getScale().mV[1],t);
+								lerp(0,   -sin(F_PI*params.getTwist()*t)*0.5f,t),
+								lerp(-0.5, cos(F_PI*params.getTwist()*t)*0.5f,t));
+			mPath[i].mScale.mV[0] = lerp(1,params.getScale().mV[0],t);
+			mPath[i].mScale.mV[1] = lerp(1,params.getScale().mV[1],t);
 			mPath[i].mTexT  = t;
-			mPath[i].mRot.setQuat(F_PI * mParams.getTwist() * t,1,0,0);
+			mPath[i].mRot.setQuat(F_PI * params.getTwist() * t,1,0,0);
 		}
 
 		break;
 	};
 
-	if (mParams.getTwist() != mParams.getTwistBegin()) mOpen = TRUE;
+	if (params.getTwist() != params.getTwistBegin()) mOpen = TRUE;
 
-	//if ((int(fabsf(mParams.getTwist() - mParams.getTwistBegin())*100))%100 != 0) {
+	//if ((int(fabsf(params.getTwist() - params.getTwistBegin())*100))%100 != 0) {
 	//	mOpen = TRUE;
 	//}
 	
 	return TRUE;
 }
 
-BOOL LLDynamicPath::generate(F32 detail, S32 split, BOOL is_sculpted)
+BOOL LLDynamicPath::generate(const LLPathParams& params, F32 detail, S32 split, BOOL is_sculpted)
 {
+	LLMemType m1(LLMemType::MTYPE_VOLUME);
+	
 	mOpen = TRUE; // Draw end caps
 	if (getPathLength() == 0)
 	{
@@ -1266,6 +1284,8 @@ BOOL LLDynamicPath::generate(F32 detail, S32 split, BOOL is_sculpted)
 
 BOOL LLPathParams::importFile(FILE *fp)
 {
+	LLMemType m1(LLMemType::MTYPE_VOLUME);
+	
 	const S32 BUFSIZE = 16384;
 	char buffer[BUFSIZE];	/* Flawfinder: ignore */
 	// *NOTE: changing the size or type of these buffers will require
@@ -1410,6 +1430,8 @@ BOOL LLPathParams::exportFile(FILE *fp) const
 
 BOOL LLPathParams::importLegacyStream(std::istream& input_stream)
 {
+	LLMemType m1(LLMemType::MTYPE_VOLUME);
+	
 	const S32 BUFSIZE = 16384;
 	char buffer[BUFSIZE];	/* Flawfinder: ignore */
 	// *NOTE: changing the size or type of these buffers will require
@@ -1610,8 +1632,11 @@ LLProfile::~LLProfile()
 
 S32 LLVolume::sNumMeshPoints = 0;
 
-LLVolume::LLVolume(const LLVolumeParams &params, const F32 detail, const BOOL generate_single_face, const BOOL is_unique) : mParams(params)
+LLVolume::LLVolume(const LLVolumeParams &params, const F32 detail, const BOOL generate_single_face, const BOOL is_unique)
+	: mParams(params)
 {
+	LLMemType m1(LLMemType::MTYPE_VOLUME);
+	
 	mUnique = is_unique;
 	mFaceMask = 0x0;
 	mDetail = detail;
@@ -1620,16 +1645,14 @@ LLVolume::LLVolume(const LLVolumeParams &params, const F32 detail, const BOOL ge
 	// set defaults
 	if (mParams.getPathParams().getCurveType() == LL_PCODE_PATH_FLEXIBLE)
 	{
-		mPathp = new LLDynamicPath(mParams.getPathParams());
+		mPathp = new LLDynamicPath();
 	}
 	else
 	{
-		mPathp    = new LLPath(mParams.getPathParams());
+		mPathp = new LLPath();
 	}
-	mProfilep = new LLProfile(mParams.getProfileParams());
+	mProfilep = new LLProfile();
 
-	mNumVolumeFaces = 0;
-	mVolumeFaces = NULL;
 	mGenerateSingleFace = generate_single_face;
 
 	generate();
@@ -1642,11 +1665,7 @@ LLVolume::LLVolume(const LLVolumeParams &params, const F32 detail, const BOOL ge
 void LLVolume::resizePath(S32 length)
 {
 	mPathp->resizePath(length);
-	if (mVolumeFaces != NULL)
-	{
-		delete[] mVolumeFaces;
-		mVolumeFaces = NULL;
-	}
+	mVolumeFaces.clear();
 }
 
 void LLVolume::regen()
@@ -1665,15 +1684,14 @@ LLVolume::~LLVolume()
 	sNumMeshPoints -= mMesh.size();
 	delete mPathp;
 	delete mProfilep;
-	delete[] mVolumeFaces;
-
 	mPathp = NULL;
 	mProfilep = NULL;
-	mVolumeFaces = NULL;
+	mVolumeFaces.clear();
 }
 
 BOOL LLVolume::generate()
 {
+	LLMemType m1(LLMemType::MTYPE_VOLUME);
 	llassert_always(mProfilep);
 	
 	//Added 10.03.05 Dave Parks
@@ -1682,13 +1700,13 @@ BOOL LLVolume::generate()
 	// stretched due to twisting or scaling on the path.  
 	S32 split = (S32) ((mDetail)*0.66f);
 	
-	if (mPathp->mParams.getCurveType() == LL_PCODE_PATH_LINE &&
-		(mPathp->mParams.getScale().mV[0] != 1.0f ||
-		 mPathp->mParams.getScale().mV[1] != 1.0f) &&
-		(mProfilep->mParams.getCurveType() == LL_PCODE_PROFILE_SQUARE ||
-		 mProfilep->mParams.getCurveType() == LL_PCODE_PROFILE_ISOTRI ||
-		 mProfilep->mParams.getCurveType() == LL_PCODE_PROFILE_EQUALTRI ||
-		 mProfilep->mParams.getCurveType() == LL_PCODE_PROFILE_RIGHTTRI))
+	if (mParams.getPathParams().getCurveType() == LL_PCODE_PATH_LINE &&
+		(mParams.getPathParams().getScale().mV[0] != 1.0f ||
+		 mParams.getPathParams().getScale().mV[1] != 1.0f) &&
+		(mParams.getProfileParams().getCurveType() == LL_PCODE_PROFILE_SQUARE ||
+		 mParams.getProfileParams().getCurveType() == LL_PCODE_PROFILE_ISOTRI ||
+		 mParams.getProfileParams().getCurveType() == LL_PCODE_PROFILE_EQUALTRI ||
+		 mParams.getProfileParams().getCurveType() == LL_PCODE_PROFILE_RIGHTTRI))
 	{
 		split = 0;
 	}
@@ -1698,8 +1716,8 @@ BOOL LLVolume::generate()
 	F32 profile_detail = mDetail;
 	F32 path_detail = mDetail;
 	
-	U8 path_type = mPathp->mParams.getCurveType();
-	U8 profile_type = mProfilep->mParams.getCurveType();
+	U8 path_type = mParams.getPathParams().getCurveType();
+	U8 profile_type = mParams.getProfileParams().getCurveType();
 	
 	if (path_type == LL_PCODE_PATH_LINE && profile_type == LL_PCODE_PROFILE_CIRCLE)
 	{ //cylinders don't care about Z-Axis
@@ -1710,8 +1728,8 @@ BOOL LLVolume::generate()
 		mLODScaleBias.setVec(0.6f, 0.6f, 0.6f);
 	}
 	
-	BOOL regenPath = mPathp->generate(path_detail, split);
-	BOOL regenProf = mProfilep->generate(mPathp->isOpen(),profile_detail, split);
+	BOOL regenPath = mPathp->generate(mParams.getPathParams(), path_detail, split);
+	BOOL regenProf = mProfilep->generate(mParams.getProfileParams(), mPathp->isOpen(),profile_detail, split);
 
 	if (regenPath || regenProf ) 
 	{
@@ -1759,28 +1777,26 @@ BOOL LLVolume::generate()
 
 void LLVolume::createVolumeFaces()
 {
-	S32 i;
+	LLMemType m1(LLMemType::MTYPE_VOLUME);
 
 	if (mGenerateSingleFace)
 	{
-		mNumVolumeFaces = 0;
+		// do nothing
 	}
 	else
 	{
 		S32 num_faces = getNumFaces();
-		mNumVolumeFaces = num_faces;
 		BOOL partial_build = TRUE;
-		if (!mVolumeFaces)
+		if (num_faces != mVolumeFaces.size())
 		{
 			partial_build = FALSE;
-			mVolumeFaces = new LLVolumeFace[num_faces];
+			mVolumeFaces.resize(num_faces);
 		}
 		// Initialize volume faces with parameter data
-		for (i = 0; i < num_faces; i++)
+		for (S32 i = 0; i < (S32)mVolumeFaces.size(); i++)
 		{
-			LLVolumeFace &vf = mVolumeFaces[i];
-			LLProfile::Face &face = mProfilep->mFaces[i];
-			vf.mVolumep = this;
+			LLVolumeFace& vf = mVolumeFaces[i];
+			LLProfile::Face& face = mProfilep->mFaces[i];
 			vf.mBeginS = face.mIndex;
 			vf.mNumS = face.mCount;
 			vf.mBeginT = 0;
@@ -1788,7 +1804,7 @@ void LLVolume::createVolumeFaces()
 			vf.mID = i;
 
 			// Set the type mask bits correctly
-			if (mProfilep->isHollow())
+			if (mParams.getProfileParams().getHollow() > 0)
 			{
 				vf.mTypeMask |= LLVolumeFace::HOLLOW_MASK;
 			}
@@ -1835,9 +1851,10 @@ void LLVolume::createVolumeFaces()
 			}
 		}
 
-		for (i = 0; i < mNumVolumeFaces; i++)
+		for (face_list_t::iterator iter = mVolumeFaces.begin();
+			 iter != mVolumeFaces.end(); ++iter)
 		{
-			mVolumeFaces[i].create(partial_build);
+			(*iter).create(this, partial_build);
 		}
 	}
 }
@@ -1929,6 +1946,8 @@ F32 LLVolume::sculptGetSurfaceArea(U16 sculpt_width, U16 sculpt_height, S8 sculp
 // create placeholder shape
 void LLVolume::sculptGeneratePlaceholder()
 {
+	LLMemType m1(LLMemType::MTYPE_VOLUME);
+	
 	S32 sizeS = mPathp->mPath.size();
 	S32 sizeT = mProfilep->mProfile.size();
 	
@@ -1960,6 +1979,8 @@ void LLVolume::sculptGeneratePlaceholder()
 // create the vertices from the map
 void LLVolume::sculptGenerateMapVertices(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, U8 sculpt_type)
 {
+	LLMemType m1(LLMemType::MTYPE_VOLUME);
+	
 	S32 sizeS = mPathp->mPath.size();
 	S32 sizeT = mProfilep->mProfile.size();
 	
@@ -2029,18 +2050,19 @@ void LLVolume::sculptGenerateMapVertices(U16 sculpt_width, U16 sculpt_height, S8
 // sculpt replaces generate() for sculpted surfaces
 void LLVolume::sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, S32 sculpt_level)
 {
+	LLMemType m1(LLMemType::MTYPE_VOLUME);
     U8 sculpt_type = mParams.getSculptType();
 
 	BOOL data_is_empty = FALSE;
 
-	if (sculpt_width == 0 || sculpt_height == 0 || sculpt_components == 0 || sculpt_data == NULL)
+	if (sculpt_width == 0 || sculpt_height == 0 || sculpt_components < 3 || sculpt_data == NULL)
 	{
 		sculpt_level = -1;
 		data_is_empty = TRUE;
 	}
 
-	mPathp->generate(mDetail, 0, TRUE);
-	mProfilep->generate(mPathp->isOpen(), mDetail, 0, TRUE);
+	mPathp->generate(mParams.getPathParams(), mDetail, 0, TRUE);
+	mProfilep->generate(mParams.getProfileParams(), mPathp->isOpen(), mDetail, 0, TRUE);
 
 	S32 sizeS = mPathp->mPath.size();
 	S32 sizeT = mProfilep->mProfile.size();
@@ -2055,7 +2077,7 @@ void LLVolume::sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components,
 	mMesh.resize(sizeS * sizeT);
 	sNumMeshPoints += mMesh.size();
 	
-	if (sculptGetSurfaceArea(sculpt_width, sculpt_height, sculpt_components, sculpt_data) < SCULPT_MIN_AREA)
+	if (!data_is_empty && sculptGetSurfaceArea(sculpt_width, sculpt_height, sculpt_components, sculpt_data) < SCULPT_MIN_AREA)
 		data_is_empty = TRUE;
 
 	//generate vertex positions
@@ -2076,11 +2098,7 @@ void LLVolume::sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components,
 	mSculptLevel = sculpt_level;
 
 	// Delete any existing faces so that they get regenerated
-	if (mVolumeFaces)
-	{
-		delete[] mVolumeFaces;
-		mVolumeFaces = NULL;
-	}
+	mVolumeFaces.clear();
 	
 	createVolumeFaces();
 }
@@ -2140,6 +2158,7 @@ bool LLVolumeParams::operator<(const LLVolumeParams &params) const
 
 void LLVolumeParams::copyParams(const LLVolumeParams &params)
 {
+	LLMemType m1(LLMemType::MTYPE_VOLUME);
 	mProfileParams.copyParams(params.mProfileParams);
 	mPathParams.copyParams(params.mPathParams);
 	mSculptID = params.getSculptID();
@@ -2511,6 +2530,8 @@ bool LLVolumeParams::validate(U8 prof_curve, F32 prof_begin, F32 prof_end, F32 h
 
 S32 *LLVolume::getTriangleIndices(U32 &num_indices) const
 {
+	LLMemType m1(LLMemType::MTYPE_VOLUME);
+	
 	S32 expected_num_triangle_indices = getNumTriangleIndices();
 	if (expected_num_triangle_indices > MAX_VOLUME_TRIANGLE_INDICES)
 	{
@@ -2527,7 +2548,7 @@ S32 *LLVolume::getTriangleIndices(U32 &num_indices) const
 	// Counter-clockwise triangles are forward facing...
 
 	BOOL open = getProfile().isOpen();
-	BOOL hollow = getProfile().isHollow();
+	BOOL hollow = (mParams.getProfileParams().getHollow() > 0);
 	BOOL path_open = getPath().isOpen();
 	S32 size_s, size_s_out, size_t;
 	S32 s, t, i;
@@ -3133,7 +3154,7 @@ S32 *LLVolume::getTriangleIndices(U32 &num_indices) const
 S32 LLVolume::getNumTriangleIndices() const
 {
 	BOOL profile_open = getProfile().isOpen();
-	BOOL hollow = getProfile().isHollow();
+	BOOL hollow = (mParams.getProfileParams().getHollow() > 0);
 	BOOL path_open = getPath().isOpen();
 
 	S32 size_s, size_s_out, size_t;
@@ -3197,13 +3218,17 @@ void LLVolume::generateSilhouetteVertices(std::vector<LLVector3> &vertices,
 										  const LLMatrix4& mat,
 										  const LLMatrix3& norm_mat)
 {
+	LLMemType m1(LLMemType::MTYPE_VOLUME);
+	
 	vertices.clear();
 	normals.clear();
 	segments.clear();
 
 	//for each face
-	for (S32 i = 0; i < getNumVolumeFaces(); i++) {
-		LLVolumeFace face = this->getVolumeFace(i);
+	for (face_list_t::iterator iter = mVolumeFaces.begin();
+		 iter != mVolumeFaces.end(); ++iter)
+	{
+		const LLVolumeFace& face = *iter;
 	
 		if (face.mTypeMask & (LLVolumeFace::CAP_MASK)) {
 	
@@ -3386,9 +3411,9 @@ S32 LLVolume::lineSegmentIntersect(const LLVector3& start, LLVector3& end) const
 	
 	LLVector3 vec = end - start;
 	
-	for (U32 i = 0; i < (U32)getNumFaces(); i++)
+	for (S32 i = 0; i < getNumFaces(); i++)
 	{
-		LLVolumeFace face = getVolumeFace(i);
+		const LLVolumeFace& face = getVolumeFace(i);
 
 		for (U32 j = 0; j < face.mIndices.size()/3; j++) 
 		{
@@ -3531,6 +3556,8 @@ BOOL LLVolume::cleanupTriangleData( const S32 num_input_vertices,
 									S32 &num_output_triangles,
 									S32 **output_triangles)
 {
+	LLMemType m1(LLMemType::MTYPE_VOLUME);
+	
 	/* Testing: avoid any cleanup
 	static BOOL skip_cleanup = TRUE;
 	if ( skip_cleanup )
@@ -3752,6 +3779,8 @@ BOOL LLVolume::cleanupTriangleData( const S32 num_input_vertices,
 
 BOOL LLVolumeParams::importFile(FILE *fp)
 {
+	LLMemType m1(LLMemType::MTYPE_VOLUME);
+	
 	//llinfos << "importing volume" << llendl;
 	const S32 BUFSIZE = 16384;
 	char buffer[BUFSIZE];	/* Flawfinder: ignore */
@@ -3806,6 +3835,8 @@ BOOL LLVolumeParams::exportFile(FILE *fp) const
 
 BOOL LLVolumeParams::importLegacyStream(std::istream& input_stream)
 {
+	LLMemType m1(LLMemType::MTYPE_VOLUME);
+	
 	//llinfos << "importing volume" << llendl;
 	const S32 BUFSIZE = 16384;
 	// *NOTE: changing the size or type of this buffer will require
@@ -3845,6 +3876,8 @@ BOOL LLVolumeParams::importLegacyStream(std::istream& input_stream)
 
 BOOL LLVolumeParams::exportLegacyStream(std::ostream& output_stream) const
 {
+	LLMemType m1(LLMemType::MTYPE_VOLUME);
+	
 	output_stream <<"\tshape 0\n";
 	output_stream <<"\t{\n";
 	mPathParams.exportLegacyStream(output_stream);
@@ -3998,7 +4031,7 @@ LLFaceID LLVolume::generateFaceMask()
 {
 	LLFaceID new_mask = 0x0000;
 
-	switch(mProfilep->mParams.getCurveType() & LL_PCODE_PROFILE_MASK)
+	switch(mParams.getProfileParams().getCurveType() & LL_PCODE_PROFILE_MASK)
 	{
 	case LL_PCODE_PROFILE_CIRCLE:
 	case LL_PCODE_PROFILE_CIRCLE_HALF:
@@ -4006,7 +4039,7 @@ LLFaceID LLVolume::generateFaceMask()
 		break;
 	case LL_PCODE_PROFILE_SQUARE:
 		{
-			for(S32 side = (S32)(mProfilep->mParams.getBegin() * 4.f); side < llceil(mProfilep->mParams.getEnd() * 4.f); side++)
+			for(S32 side = (S32)(mParams.getProfileParams().getBegin() * 4.f); side < llceil(mParams.getProfileParams().getEnd() * 4.f); side++)
 			{
 				new_mask |= LL_FACE_OUTER_SIDE_0 << side;
 			}
@@ -4016,7 +4049,7 @@ LLFaceID LLVolume::generateFaceMask()
 	case LL_PCODE_PROFILE_EQUALTRI:
 	case LL_PCODE_PROFILE_RIGHTTRI:
 		{
-			for(S32 side = (S32)(mProfilep->mParams.getBegin() * 3.f); side < llceil(mProfilep->mParams.getEnd() * 3.f); side++)
+			for(S32 side = (S32)(mParams.getProfileParams().getBegin() * 3.f); side < llceil(mParams.getProfileParams().getEnd() * 3.f); side++)
 			{
 				new_mask |= LL_FACE_OUTER_SIDE_0 << side;
 			}
@@ -4028,7 +4061,7 @@ LLFaceID LLVolume::generateFaceMask()
 	}
 
 	// handle hollow objects
-	if (mProfilep->isHollow())
+	if (mParams.getProfileParams().getHollow() > 0)
 	{
 		new_mask |= LL_FACE_INNER_SIDE;
 	}
@@ -4130,7 +4163,7 @@ std::ostream& operator<<(std::ostream &s, const LLPath &path)
 
 std::ostream& operator<<(std::ostream &s, const LLVolume &volume)
 {
-	s << "{params = " << volume.mParams;
+	s << "{params = " << volume.getParams();
 	s << ", path = " << *volume.mPathp;
 	s << ", profile = " << *volume.mProfilep;
 	s << "}";
@@ -4140,7 +4173,7 @@ std::ostream& operator<<(std::ostream &s, const LLVolume &volume)
 
 std::ostream& operator<<(std::ostream &s, const LLVolume *volumep)
 {
-	s << "{params = " << volumep->mParams;
+	s << "{params = " << volumep->getParams();
 	s << ", path = " << *(volumep->mPathp);
 	s << ", profile = " << *(volumep->mProfilep);
 	s << "}";
@@ -4160,15 +4193,15 @@ LLVolumeFace::LLVolumeFace()
 }
 
 
-BOOL LLVolumeFace::create(BOOL partial_build)
+BOOL LLVolumeFace::create(LLVolume* volume, BOOL partial_build)
 {
 	if (mTypeMask & CAP_MASK)
 	{
-		return createCap(partial_build);
+		return createCap(volume, partial_build);
 	}
 	else if ((mTypeMask & END_MASK) || (mTypeMask & SIDE_MASK))
 	{
-		return createSide(partial_build);
+		return createSide(volume, partial_build);
 	}
 	else
 	{
@@ -4190,12 +4223,14 @@ void	LerpPlanarVertex(LLVolumeFace::VertexData& v0,
 	vout.mBinormal = v0.mBinormal;
 }
 
-BOOL LLVolumeFace::createUnCutCubeCap(BOOL partial_build)
+BOOL LLVolumeFace::createUnCutCubeCap(LLVolume* volume, BOOL partial_build)
 {
-	const std::vector<LLVolume::Point>& mesh = mVolumep->getMesh();
-	const std::vector<LLVector3>& profile = mVolumep->getProfile().mProfile;
-	S32 max_s = mVolumep->getProfile().getTotal();
-	S32 max_t = mVolumep->getPath().mPath.size();
+	LLMemType m1(LLMemType::MTYPE_VOLUME);
+	
+	const std::vector<LLVolume::Point>& mesh = volume->getMesh();
+	const std::vector<LLVector3>& profile = volume->getProfile().mProfile;
+	S32 max_s = volume->getProfile().getTotal();
+	S32 max_t = volume->getPath().mPath.size();
 
 	// S32 i;
 	S32 num_vertices = 0, num_indices = 0;
@@ -4296,23 +4331,24 @@ BOOL LLVolumeFace::createUnCutCubeCap(BOOL partial_build)
 }
 
 
-BOOL LLVolumeFace::createCap(BOOL partial_build)
+BOOL LLVolumeFace::createCap(LLVolume* volume, BOOL partial_build)
 {
+	LLMemType m1(LLMemType::MTYPE_VOLUME);
+	
 	if (!(mTypeMask & HOLLOW_MASK) && 
 		!(mTypeMask & OPEN_MASK) && 
-		((this->mVolumep->getParams().getPathParams().getBegin()==0.0f)&&
-		(this->mVolumep->getParams().getPathParams().getEnd()==1.0f))&&
-		(mVolumep->getProfile().mParams.getCurveType()==LL_PCODE_PROFILE_SQUARE &&
-			mVolumep->getPath().mParams.getCurveType()==LL_PCODE_PATH_LINE)	
+		((volume->getParams().getPathParams().getBegin()==0.0f)&&
+		(volume->getParams().getPathParams().getEnd()==1.0f))&&
+		(volume->getParams().getProfileParams().getCurveType()==LL_PCODE_PROFILE_SQUARE &&
+		 volume->getParams().getPathParams().getCurveType()==LL_PCODE_PATH_LINE)	
 		){
-		return createUnCutCubeCap(partial_build);
+		return createUnCutCubeCap(volume, partial_build);
 	}
 
-	S32 i;
 	S32 num_vertices = 0, num_indices = 0;
 
-	const std::vector<LLVolume::Point>& mesh = mVolumep->getMesh();
-	const std::vector<LLVector3>& profile = mVolumep->getProfile().mProfile;
+	const std::vector<LLVolume::Point>& mesh = volume->getMesh();
+	const std::vector<LLVector3>& profile = volume->getProfile().mProfile;
 
 	// All types of caps have the same number of vertices and indices
 	num_vertices = profile.size();
@@ -4325,8 +4361,8 @@ BOOL LLVolumeFace::createCap(BOOL partial_build)
 		mIndices.resize(num_indices);
 	}
 
-	S32 max_s = mVolumep->getProfile().getTotal();
-	S32 max_t = mVolumep->getPath().mPath.size();
+	S32 max_s = volume->getProfile().getTotal();
+	S32 max_t = volume->getPath().mPath.size();
 
 	mCenter.clearVec();
 
@@ -4350,7 +4386,7 @@ BOOL LLVolumeFace::createCap(BOOL partial_build)
 	LLVector3& max = mExtents[1];
 
 	// Copy the vertices into the array
-	for (i = 0; i < num_vertices; i++)
+	for (S32 i = 0; i < num_vertices; i++)
 	{
 		if (mTypeMask & TOP_MASK)
 		{
@@ -4414,7 +4450,7 @@ BOOL LLVolumeFace::createCap(BOOL partial_build)
 	}
 		
 	
-	for (i = 0; i < num_vertices; i++)
+	for (S32 i = 0; i < num_vertices; i++)
 	{
 		mVertices[i].mBinormal = binormal;
 		mVertices[i].mNormal = normal;
@@ -4435,7 +4471,7 @@ BOOL LLVolumeFace::createCap(BOOL partial_build)
 			// Does it matter if it's open or closed? - djs
 
 			S32 pt1 = 0, pt2 = num_vertices - 1;
-			i = 0;
+			S32 i = 0;
 			while (pt2 - pt1 > 1)
 			{
 				// Use the profile points instead of the mesh, since you want
@@ -4538,7 +4574,7 @@ BOOL LLVolumeFace::createCap(BOOL partial_build)
 			llassert(mTypeMask & BOTTOM_MASK);
 			S32 pt1 = 0, pt2 = num_vertices - 1;
 
-			i = 0;
+			S32 i = 0;
 			while (pt2 - pt1 > 1)
 			{
 				// Use the profile points instead of the mesh, since you want
@@ -4645,7 +4681,7 @@ BOOL LLVolumeFace::createCap(BOOL partial_build)
 				// SOLID OPEN TOP
 				// Generate indices
 				// This is a tri-fan, so we reuse the same first point for all triangles.
-				for (i = 0; i < (num_vertices - 2); i++)
+				for (S32 i = 0; i < (num_vertices - 2); i++)
 				{
 					mIndices[3*i] = num_vertices - 1;
 					mIndices[3*i+1] = i;
@@ -4655,7 +4691,7 @@ BOOL LLVolumeFace::createCap(BOOL partial_build)
 			else
 			{
 				// SOLID CLOSED TOP
-				for (i = 0; i < (num_vertices - 2); i++)
+				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;
@@ -4671,7 +4707,7 @@ BOOL LLVolumeFace::createCap(BOOL partial_build)
 				// SOLID OPEN BOTTOM
 				// Generate indices
 				// This is a tri-fan, so we reuse the same first point for all triangles.
-				for (i = 0; i < (num_vertices - 2); i++)
+				for (S32 i = 0; i < (num_vertices - 2); i++)
 				{
 					mIndices[3*i] = num_vertices - 1;
 					mIndices[3*i+1] = i + 1;
@@ -4681,7 +4717,7 @@ BOOL LLVolumeFace::createCap(BOOL partial_build)
 			else
 			{
 				// SOLID CLOSED BOTTOM
-				for (i = 0; i < (num_vertices - 2); i++)
+				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;
@@ -4696,6 +4732,8 @@ BOOL LLVolumeFace::createCap(BOOL partial_build)
 
 void LLVolumeFace::createBinormals()
 {
+	LLMemType m1(LLMemType::MTYPE_VOLUME);
+	
 	if (!mHasBinormals)
 	{
 		//generate binormals
@@ -4737,16 +4775,18 @@ void LLVolumeFace::createBinormals()
 	}
 }
 
-BOOL LLVolumeFace::createSide(BOOL partial_build)
+BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build)
 {
+	LLMemType m1(LLMemType::MTYPE_VOLUME);
+	
 	BOOL flat = mTypeMask & FLAT_MASK;
 	S32 num_vertices, num_indices;
 
-	const std::vector<LLVolume::Point>& mesh = mVolumep->getMesh();
-	const std::vector<LLVector3>& profile = mVolumep->getProfile().mProfile;
-	const std::vector<LLPath::PathPt>& path_data = mVolumep->getPath().mPath;
+	const std::vector<LLVolume::Point>& mesh = volume->getMesh();
+	const std::vector<LLVector3>& profile = volume->getProfile().mProfile;
+	const std::vector<LLPath::PathPt>& path_data = volume->getPath().mPath;
 
-	S32 max_s = mVolumep->getProfile().getTotal();
+	S32 max_s = volume->getProfile().getTotal();
 
 	S32 s, t, i;
 	F32 ss, tt;
@@ -4889,7 +4929,7 @@ BOOL LLVolumeFace::createSide(BOOL partial_build)
 				if (t < mNumT-2) {												//top right/top left neighbor face 
 					mEdge[cur_edge++] = (mNumS-1)*2*(t+1)+s*2+1;
 				}
-				else if (mNumT <= 3 || mVolumep->getPath().isOpen() == TRUE) { //no neighbor
+				else if (mNumT <= 3 || volume->getPath().isOpen() == TRUE) { //no neighbor
 					mEdge[cur_edge++] = -1;
 				}
 				else { //wrap on T
@@ -4898,7 +4938,7 @@ BOOL LLVolumeFace::createSide(BOOL partial_build)
 				if (s > 0) {													//top left/bottom left neighbor face
 					mEdge[cur_edge++] = (mNumS-1)*2*t+s*2-1;
 				}
-				else if (flat_face ||  mVolumep->getProfile().isOpen() == TRUE) { //no neighbor
+				else if (flat_face ||  volume->getProfile().isOpen() == TRUE) { //no neighbor
 					mEdge[cur_edge++] = -1;
 				}
 				else {	//wrap on S
@@ -4908,7 +4948,7 @@ BOOL LLVolumeFace::createSide(BOOL partial_build)
 				if (t > 0) {													//bottom left/bottom right neighbor face
 					mEdge[cur_edge++] = (mNumS-1)*2*(t-1)+s*2;
 				}
-				else if (mNumT <= 3 || mVolumep->getPath().isOpen() == TRUE) { //no neighbor
+				else if (mNumT <= 3 || volume->getPath().isOpen() == TRUE) { //no neighbor
 					mEdge[cur_edge++] = -1;
 				}
 				else { //wrap on T
@@ -4917,7 +4957,7 @@ BOOL LLVolumeFace::createSide(BOOL partial_build)
 				if (s < mNumS-2) {												//bottom right/top right neighbor face
 					mEdge[cur_edge++] = (mNumS-1)*2*t+(s+1)*2;
 				}
-				else if (flat_face || mVolumep->getProfile().isOpen() == TRUE) { //no neighbor
+				else if (flat_face || volume->getProfile().isOpen() == TRUE) { //no neighbor
 					mEdge[cur_edge++] = -1;
 				}
 				else { //wrap on S
@@ -4962,11 +5002,11 @@ BOOL LLVolumeFace::createSide(BOOL partial_build)
 	
 	BOOL s_bottom_converges = ((mVertices[0].mPosition - mVertices[mNumS*(mNumT-2)].mPosition).magVecSquared() < 0.000001f);
 	BOOL s_top_converges = ((mVertices[mNumS-1].mPosition - mVertices[mNumS*(mNumT-2)+mNumS-1].mPosition).magVecSquared() < 0.000001f);
-	U8 sculpt_type = mVolumep->getParams().getSculptType();
+	U8 sculpt_type = volume->getParams().getSculptType();
 
 	if (sculpt_type == LL_SCULPT_TYPE_NONE)  // logic for non-sculpt volumes
 	{
-		if (mVolumep->getPath().isOpen() == FALSE)
+		if (volume->getPath().isOpen() == FALSE)
 		{ //wrap normals on T
 			for (S32 i = 0; i < mNumS; i++)
 			{
@@ -4976,7 +5016,7 @@ BOOL LLVolumeFace::createSide(BOOL partial_build)
 			}
 		}
 
-		if ((mVolumep->getProfile().isOpen() == FALSE) && !(s_bottom_converges))
+		if ((volume->getProfile().isOpen() == FALSE) && !(s_bottom_converges))
 		{ //wrap normals on S
 			for (S32 i = 0; i < mNumT; i++)
 			{
@@ -4986,8 +5026,8 @@ BOOL LLVolumeFace::createSide(BOOL partial_build)
 			}
 		}
 	
-		if (mVolumep->getPathType() == LL_PCODE_PATH_CIRCLE &&
-			((mVolumep->getProfileType() & LL_PCODE_PROFILE_MASK) == LL_PCODE_PROFILE_CIRCLE_HALF))
+		if (volume->getPathType() == LL_PCODE_PATH_CIRCLE &&
+			((volume->getProfileType() & LL_PCODE_PROFILE_MASK) == LL_PCODE_PROFILE_CIRCLE_HALF))
 		{
 			if (s_bottom_converges)
 			{ //all lower S have same normal
@@ -5086,69 +5126,6 @@ BOOL LLVolumeFace::createSide(BOOL partial_build)
 	return TRUE;
 }
 
-// Static			
-BOOL LLVolumeFace::updateColors(LLColor4U *old_colors, const S32 num_old, const LLVolumeFace &old_vf,
-								LLStrider<LLColor4U> &new_colors, const S32 num_new, const LLVolumeFace &new_vf)
-{
-	if (new_vf.mTypeMask & CAP_MASK)
-	{
-		// These aren't interpolated correctly.  Need to fix when shadows go in...
-		F32 ratio = (F32)num_old / (F32)num_new;
-		S32 v = 0;
-		for (v = 0; v < num_new; v++)
-		{
-			new_colors[v] = old_colors[(S32)(v*ratio)];
-		}
-		return FALSE;
-	}
-	else if (new_vf.mTypeMask & END_MASK)
-	{
-		// These aren't interpolated correctly.  Need to fix when shadows go in...
-		F32 ratio = (F32)num_old / (F32)num_new;
-		S32 v = 0;
-		for (v = 0; v < num_new; v++)
-		{
-			new_colors[v] = old_colors[(S32)(v*ratio)];
-		}
-		return FALSE;
-	}
-	else if (new_vf.mTypeMask & SIDE_MASK)
-	{
-		S32 s, t;
-		F32 s_ratio = (F32)old_vf.mNumS / (F32)new_vf.mNumS;
-		F32 t_ratio = (F32)old_vf.mNumT / (F32)new_vf.mNumT;
-
-		S32 v = 0;
-		for (t = 0; t < new_vf.mNumT; t++)
-		{
-			F32 t_frac = t * t_ratio;
-			S32 old_t = (S32)t_frac;
-			S32 t_target = llmin(old_t + 1, (old_vf.mNumT - 1));
-			t_frac -= old_t;
-			for (s = 0; s < new_vf.mNumS; s++)
-			{
-				F32 s_frac = s * s_ratio;
-				S32 old_s = (S32)s_frac;
-				S32 s_target = llmin(old_s + 1, (old_vf.mNumS - 1));
-				s_frac -= old_s;
-
-				// Interpolate along s, then along t.
-				LLColor4U s_interp0 = old_colors[old_t *  old_vf.mNumS + old_s].multAll(1.f - s_frac).addClampMax(old_colors[old_t * old_vf.mNumS + s_target].multAll(s_frac));
-				LLColor4U s_interp1 = old_colors[t_target *  old_vf.mNumS + old_s].multAll(1.f - s_frac).addClampMax(old_colors[t_target * old_vf.mNumS + s_target].multAll(s_frac));
-				new_colors[v] = s_interp0.multAll(1.f - t_frac).addClampMax(s_interp1.multAll(t_frac));
-				v++;
-			}
-		}
-	}
-	else
-	{
-		llerrs << "Unknown/uninitialized face type!" << llendl;
-		return FALSE;
-	}
-	return TRUE;
-}
-
-
 // Finds binormal based on three vertices with texture coordinates.
 // Fills in dummy values if the triangle has degenerate texture coordinates.
 LLVector3 calc_binormal_from_triangle( 
diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h
index a1eba9de389e13089117c82ed0031578b87a1626..11a7c2f1c60491f67fb9e846424aa6d18b9fe4db 100644
--- a/indra/llmath/llvolume.h
+++ b/indra/llmath/llvolume.h
@@ -643,9 +643,8 @@ class LLVolumeParams
 class LLProfile
 {
 public:
-	LLProfile(const LLProfileParams &params)
-		: mParams(params),
-		  mOpen(FALSE),
+	LLProfile()
+		: mOpen(FALSE),
 		  mConcave(FALSE),
 		  mDirty(TRUE),
 		  mTotalOut(0),
@@ -657,15 +656,12 @@ class LLProfile
 
 	S32	 getTotal() const								{ return mTotal; }
 	S32	 getTotalOut() const							{ return mTotalOut; }	// Total number of outside points
-	BOOL isHollow() const								{ return (mParams.getHollow() > 0); }
 	BOOL isFlat(S32 face) const							{ return (mFaces[face].mCount == 2); }
 	BOOL isOpen() const									{ return mOpen; }
 	void setDirty()										{ mDirty     = TRUE; }
-	BOOL generate(BOOL path_open, F32 detail = 1.0f, S32 split = 0, BOOL is_sculpted = FALSE);
+	BOOL generate(const LLProfileParams& params, BOOL path_open, F32 detail = 1.0f, S32 split = 0, BOOL is_sculpted = FALSE);
 	BOOL isConcave() const								{ return mConcave; }
 public:
-	const LLProfileParams &mParams;
-
 	struct Face
 	{
 		S32       mIndex;
@@ -687,10 +683,10 @@ class LLProfile
 	friend std::ostream& operator<<(std::ostream &s, const LLProfile &profile);
 
 protected:
-	void genNormals();
-	void genNGon(S32 sides, F32 offset=0.0f, F32 bevel = 0.0f, F32 ang_scale = 1.f, S32 split = 0);
+	void genNormals(const LLProfileParams& params);
+	void genNGon(const LLProfileParams& params, S32 sides, F32 offset=0.0f, F32 bevel = 0.0f, F32 ang_scale = 1.f, S32 split = 0);
 
-	Face* addHole(BOOL flat, F32 sides, F32 offset, F32 box_hollow, F32 ang_scale, S32 split = 0);
+	Face* addHole(const LLProfileParams& params, BOOL flat, F32 sides, F32 offset, F32 box_hollow, F32 ang_scale, S32 split = 0);
 	Face* addCap (S16 faceID);
 	Face* addFace(S32 index, S32 count, F32 scaleU, S16 faceID, BOOL flat);
 
@@ -720,9 +716,8 @@ class LLPath
 	};
 
 public:
-	LLPath(const LLPathParams &params)
-		: mParams(params),
-		  mOpen(FALSE),
+	LLPath()
+		: mOpen(FALSE),
 		  mTotal(0),
 		  mDirty(TRUE),
 		  mStep(1)
@@ -731,8 +726,8 @@ class LLPath
 
 	virtual ~LLPath();
 
-	void genNGon(S32 sides, F32 offset=0.0f, F32 end_scale = 1.f, F32 twist_scale = 1.f);
-	virtual BOOL generate(F32 detail=1.0f, S32 split = 0, BOOL is_sculpted = FALSE);
+	void genNGon(const LLPathParams& params, S32 sides, F32 offset=0.0f, F32 end_scale = 1.f, F32 twist_scale = 1.f);
+	virtual BOOL generate(const LLPathParams& params, F32 detail=1.0f, S32 split = 0, BOOL is_sculpted = FALSE);
 
 	BOOL isOpen() const						{ return mOpen; }
 	F32 getStep() const						{ return mStep; }
@@ -745,7 +740,6 @@ class LLPath
 	friend std::ostream& operator<<(std::ostream &s, const LLPath &path);
 
 public:
-	const LLPathParams &mParams;
 	std::vector<PathPt> mPath;
 
 protected:
@@ -758,8 +752,8 @@ class LLPath
 class LLDynamicPath : public LLPath
 {
 public:
-	LLDynamicPath(const LLPathParams &params) : LLPath(params) { }
-	BOOL generate(F32 detail=1.0f, S32 split = 0, BOOL is_sculpted = FALSE);
+	LLDynamicPath() : LLPath() { }
+	/*virtual*/ BOOL generate(const LLPathParams& params, F32 detail=1.0f, S32 split = 0, BOOL is_sculpted = FALSE);
 };
 
 // Yet another "face" class - caches volume-specific, but not instance-specific data for faces)
@@ -767,7 +761,7 @@ class LLVolumeFace
 {
 public:
 	LLVolumeFace();
-	BOOL create(BOOL partial_build = FALSE);
+	BOOL create(LLVolume* volume, BOOL partial_build = FALSE);
 	void createBinormals();
 
 	class VertexData
@@ -811,16 +805,11 @@ class LLVolumeFace
 	std::vector<VertexData> mVertices;
 	std::vector<U16>	mIndices;
 	std::vector<S32>	mEdge;
-	LLVolume *mVolumep; // Deliberately NOT reference counted - djs 11/20/03 - otherwise would make an annoying circular reference
 
-	// Shouldn't need num_old and num_new, really - djs
-	static BOOL updateColors(LLColor4U *old_colors, const S32 num_old, const LLVolumeFace &old_face,
-							 LLStrider<LLColor4U> &new_colors, const S32 num_new, const LLVolumeFace &new_face);
-	
-protected:
-	BOOL createUnCutCubeCap(BOOL partial_build = FALSE);
-	BOOL createCap(BOOL partial_build = FALSE);
-	BOOL createSide(BOOL partial_build = FALSE);
+private:
+	BOOL createUnCutCubeCap(LLVolume* volume, BOOL partial_build = FALSE);
+	BOOL createCap(LLVolume* volume, BOOL partial_build = FALSE);
+	BOOL createSide(LLVolume* volume, BOOL partial_build = FALSE);
 };
 
 class LLVolume : public LLRefCount
@@ -848,12 +837,12 @@ class LLVolume : public LLRefCount
 
 	LLVolume(const LLVolumeParams &params, const F32 detail, const BOOL generate_single_face = FALSE, const BOOL is_unique = FALSE);
 	
-	U8 getProfileType()	const								{ return mProfilep->mParams.getCurveType(); }
-	U8 getPathType() const									{ return mPathp->mParams.getCurveType(); }
+	U8 getProfileType()	const								{ return mParams.getProfileParams().getCurveType(); }
+	U8 getPathType() const									{ return mParams.getPathParams().getCurveType(); }
 	S32	getNumFaces() const									{ return (S32)mProfilep->mFaces.size(); }
-	S32 getNumVolumeFaces() const							{ return mNumVolumeFaces; }
-	F32 getDetail() const								{ return mDetail; }
-	const LLVolumeParams & getParams() const				{ return mParams; }
+	S32 getNumVolumeFaces() const							{ return mVolumeFaces.size(); }
+	F32 getDetail() const									{ return mDetail; }
+	const LLVolumeParams& getParams() const					{ return mParams; }
 	LLVolumeParams getCopyOfParams() const					{ return mParams; }
 	const LLProfile& getProfile() const						{ return *mProfilep; }
 	LLPath& getPath() const									{ return *mPathp; }
@@ -932,8 +921,8 @@ class LLVolume : public LLRefCount
 	std::vector<Point> mMesh;
 
 	BOOL mGenerateSingleFace;
-	S32 mNumVolumeFaces;
-	LLVolumeFace *mVolumeFaces;
+	typedef std::vector<LLVolumeFace> face_list_t;
+	face_list_t mVolumeFaces;
 };
 
 std::ostream& operator<<(std::ostream &s, const LLVolumeParams &volume_params);
diff --git a/indra/llmath/llvolumemgr.cpp b/indra/llmath/llvolumemgr.cpp
index f3a6b7d157aef24ba9ed6ba801f8ca9a28582537..23ed0183b880bbf7c55472e7ccbf648f30dbd75b 100644
--- a/indra/llmath/llvolumemgr.cpp
+++ b/indra/llmath/llvolumemgr.cpp
@@ -31,13 +31,10 @@
 #include "linden_common.h"
 
 #include "llvolumemgr.h"
+#include "llmemtype.h"
 #include "llvolume.h"
 
 
-//#define DEBUG_VOLUME
-
-//LLVolumeMgr* gVolumeMgr = 0;
-
 const F32 BASE_THRESHOLD = 0.03f;
 
 //static
@@ -70,11 +67,6 @@ LLVolumeMgr::~LLVolumeMgr()
 
 BOOL LLVolumeMgr::cleanup()
 {
-	#ifdef DEBUG_VOLUME
-	{
-		lldebugs << "LLVolumeMgr::cleanup()" << llendl;
-	}
-	#endif
 	BOOL no_refs = TRUE;
 	if (mDataMutex)
 	{
@@ -85,14 +77,11 @@ BOOL LLVolumeMgr::cleanup()
 		 iter != end; iter++)
 	{
 		LLVolumeLODGroup *volgroupp = iter->second;
-		if (volgroupp->getNumRefs() != 1)
+		if (volgroupp->cleanupRefs() == false)
 		{
-			llwarns << "Volume group " << volgroupp << " has " 
-					<< volgroupp->getNumRefs() << " remaining refs" << llendl;
-			llwarns << volgroupp->getParams() << llendl;
 			no_refs = FALSE;
 		}
- 		volgroupp->unref();// this );
+ 		delete volgroupp;
 	}
 	mVolumeLODGroups.clear();
 	if (mDataMutex)
@@ -102,10 +91,11 @@ BOOL LLVolumeMgr::cleanup()
 	return no_refs;
 }
 
-// whatever calls getVolume() never owns the LLVolume* and
-// cannot keep references for long since it may be deleted
-// later.  For best results hold it in an LLPointer<LLVolume>.
-LLVolume *LLVolumeMgr::getVolume(const LLVolumeParams &volume_params, const S32 detail)
+// Always only ever store the results of refVolume in a LLPointer
+// Note however that LLVolumeLODGroup that contains the volume
+//  also holds a LLPointer so the volume will only go away after
+//  anything holding the volume and the LODGroup are destroyed
+LLVolume* LLVolumeMgr::refVolume(const LLVolumeParams &volume_params, const S32 detail)
 {
 	LLVolumeLODGroup* volgroupp;
 	if (mDataMutex)
@@ -121,17 +111,11 @@ LLVolume *LLVolumeMgr::getVolume(const LLVolumeParams &volume_params, const S32
 	{
 		volgroupp = iter->second;
 	}
-	volgroupp->ref();
 	if (mDataMutex)
 	{
 		mDataMutex->unlock();
 	}
-	#ifdef DEBUG_VOLUME
-	{
-		lldebugs << "LLVolumeMgr::getVolume() " << (*this) << llendl;
-	}
-	#endif
-	return volgroupp->getLOD(detail);
+	return volgroupp->getLODVolume(detail);
 }
 
 // virtual
@@ -154,15 +138,14 @@ LLVolumeLODGroup* LLVolumeMgr::getGroup( const LLVolumeParams& volume_params ) c
 	return volgroupp;
 }
 
-// virtual
-void LLVolumeMgr::cleanupVolume(LLVolume *volumep)
+void LLVolumeMgr::unrefVolume(LLVolume *volumep)
 {
 	if (volumep->isUnique())
 	{
 		// TomY: Don't need to manage this volume. It is a unique instance.
 		return;
 	}
-	LLVolumeParams* params = (LLVolumeParams*) &(volumep->getParams());
+	const LLVolumeParams* params = &(volumep->getParams());
 	if (mDataMutex)
 	{
 		mDataMutex->lock();
@@ -182,11 +165,10 @@ void LLVolumeMgr::cleanupVolume(LLVolume *volumep)
 		LLVolumeLODGroup* volgroupp = iter->second;
 
 		volgroupp->derefLOD(volumep);
-		volgroupp->unref();// this );
-		if (volgroupp->getNumRefs() == 1)
+		if (volgroupp->getNumRefs() == 0)
 		{
 			mVolumeLODGroups.erase(params);
-			volgroupp->unref();// this );
+			delete volgroupp;
 		}
 	}
 	if (mDataMutex)
@@ -194,40 +176,21 @@ void LLVolumeMgr::cleanupVolume(LLVolume *volumep)
 		mDataMutex->unlock();
 	}
 
-	#ifdef DEBUG_VOLUME
-	{
-		lldebugs << "LLVolumeMgr::cleanupVolume() " << (*this) << llendl;
-	}
-	#endif
-}
-
-#ifdef DEBUG_VOLUME
-S32 LLVolumeMgr::getTotalRefCount() const
-{
-	S32 total_ref_count = 0;
-	for ( volume_lod_group_map_t::const_iterator iter = mVolumeLODGroups.begin(),
-			 end = mVolumeLODGroups.end();
-		 iter != end; iter++)
-	{
-		total_ref_count += iter->second->getTotalVolumeRefCount();
-	}
-	return total_ref_count;
 }
 
-S32 LLVolumeMgr::getGroupCount() const
+// protected
+void LLVolumeMgr::insertGroup(LLVolumeLODGroup* volgroup)
 {
-	return mVolumeLODGroups.size();
+	mVolumeLODGroups[volgroup->getVolumeParams()] = volgroup;
 }
-#endif
 
 // protected
 LLVolumeLODGroup* LLVolumeMgr::createNewGroup(const LLVolumeParams& volume_params)
 {
-	LLVolumeLODGroup* group = new LLVolumeLODGroup(volume_params);
-	const LLVolumeParams* params = &(group->getParams());
-	mVolumeLODGroups[params] = group;
- 	group->ref(); // initial reference
-	return group;
+	LLMemType m1(LLMemType::MTYPE_VOLUME);
+	LLVolumeLODGroup* volgroup = new LLVolumeLODGroup(volume_params);
+	insertGroup(volgroup);
+	return volgroup;
 }
 
 // virtual
@@ -272,9 +235,8 @@ std::ostream& operator<<(std::ostream& s, const LLVolumeMgr& volume_mgr)
 		volume_mgr.mDataMutex->lock();
 	}
 
-	LLVolumeMgr::volume_lod_group_map_iter iter = volume_mgr.mVolumeLODGroups.begin();
-	LLVolumeMgr::volume_lod_group_map_iter end  = volume_mgr.mVolumeLODGroups.end();
-	for ( ; iter != end; ++iter)
+	for (LLVolumeMgr::volume_lod_group_map_t::const_iterator iter = volume_mgr.mVolumeLODGroups.begin();
+		 iter != volume_mgr.mVolumeLODGroups.end(); ++iter)
 	{
 		LLVolumeLODGroup *volgroupp = iter->second;
 		total_refs += volgroupp->getNumRefs();
@@ -291,72 +253,78 @@ std::ostream& operator<<(std::ostream& s, const LLVolumeMgr& volume_mgr)
 }
 
 LLVolumeLODGroup::LLVolumeLODGroup(const LLVolumeParams &params)
+	: mVolumeParams(params),
+	  mRefs(0)
 {
-	S32 i;
-	mParams = params;
-
-	for (i = 0; i < NUM_LODS; i++)
+	for (S32 i = 0; i < NUM_LODS; i++)
 	{
 		mLODRefs[i] = 0;
-		// no need to initialize mVolumeLODs, they are smart pointers
-		//mVolumeLODs[i] = NULL;
 		mAccessCount[i] = 0;
 	}
 }
 
-#ifdef DEBUG_VOLUME
-S32 LLVolumeLODGroup::getTotalVolumeRefCount() const
+LLVolumeLODGroup::~LLVolumeLODGroup()
 {
-	S32 total_ref_count = 0;
 	for (S32 i = 0; i < NUM_LODS; i++)
 	{
-		total_ref_count += mLODRefs[i];
+		llassert_always(mLODRefs[i] == 0);
 	}
-	return total_ref_count;
-}
-#endif
-
-// protected
-LLVolumeLODGroup::~LLVolumeLODGroup()
-{
-	destroy();
 }
 
-// protected
-void LLVolumeLODGroup::destroy()
+// Called from LLVolumeMgr::cleanup
+bool LLVolumeLODGroup::cleanupRefs()
 {
-	for (S32 i = 0; i < NUM_LODS; i++)
+	bool res = true;
+	if (mRefs != 0)
 	{
-		// remember that mVolumeLODs are smart pointers!
-		mVolumeLODs[i] = NULL;
+		llwarns << "Volume group has remaining refs:" << getNumRefs() << llendl;
+		mRefs = 0;
+		for (S32 i = 0; i < NUM_LODS; i++)
+		{
+			if (mLODRefs[i] > 0)
+			{
+				llwarns << " LOD " << i << " refs = " << mLODRefs[i] << llendl;
+				mLODRefs[i] = 0;
+				mVolumeLODs[i] = NULL;
+			}
+		}
+		llwarns << *getVolumeParams() << llendl;
+		res = false;
 	}
+	return res;
 }
 
-LLVolume * LLVolumeLODGroup::getLOD(const S32 detail)
+LLVolume* LLVolumeLODGroup::getLODVolume(const S32 detail)
 {
 	llassert(detail >=0 && detail < NUM_LODS);
 	mAccessCount[detail]++;
 	
-	if (!mLODRefs[detail])
+	mRefs++;
+	if (mVolumeLODs[detail].isNull())
 	{
-		mVolumeLODs[detail] = new LLVolume(mParams, mDetailScales[detail]);
+		LLMemType m1(LLMemType::MTYPE_VOLUME);
+		mVolumeLODs[detail] = new LLVolume(mVolumeParams, mDetailScales[detail]);
 	}
 	mLODRefs[detail]++;
-	return mVolumeLODs[detail].get();
+	return mVolumeLODs[detail];
 }
 
 BOOL LLVolumeLODGroup::derefLOD(LLVolume *volumep)
 {
-	S32 i;
-	for (i = 0; i < NUM_LODS; i++)
+	llassert_always(mRefs > 0);
+	mRefs--;
+	for (S32 i = 0; i < NUM_LODS; i++)
 	{
 		if (mVolumeLODs[i] == volumep)
 		{
+			llassert_always(mLODRefs[i] > 0);
 			mLODRefs[i]--;
+#if 1 // SJB: Possible opt: keep other lods around
 			if (!mLODRefs[i])
 			{
 				mVolumeLODs[i] = NULL;
 			}
+#endif
 			return TRUE;
 		}
 	}
@@ -428,7 +396,7 @@ F32 LLVolumeLODGroup::dump()
 std::ostream& operator<<(std::ostream& s, const LLVolumeLODGroup& volgroup)
 {
 	s << "{ numRefs=" << volgroup.getNumRefs();
-	s << ", mParams=" << volgroup.mParams;
+	s << ", mParams=" << volgroup.getVolumeParams();
 	s << " }";
 	 
 	return s;
diff --git a/indra/llmath/llvolumemgr.h b/indra/llmath/llvolumemgr.h
index c28ffce6311e50506edcaaf9ec847114d907eda5..fac194165be09f738d43c7d8806dc58064a99e77 100644
--- a/indra/llmath/llvolumemgr.h
+++ b/indra/llmath/llvolumemgr.h
@@ -41,8 +41,10 @@
 class LLVolumeParams;
 class LLVolumeLODGroup;
 
-class LLVolumeLODGroup : public LLThreadSafeRefCount
+class LLVolumeLODGroup
 {
+	LOG_CLASS(LLVolumeLODGroup);
+	
 public:
 	enum
 	{
@@ -50,29 +52,26 @@ class LLVolumeLODGroup : public LLThreadSafeRefCount
 	};
 
 	LLVolumeLODGroup(const LLVolumeParams &params);
+	~LLVolumeLODGroup();
+	bool cleanupRefs();
 
-	BOOL derefLOD(LLVolume *volumep);
 	static S32 getDetailFromTan(const F32 tan_angle);
 	static void getDetailProximity(const F32 tan_angle, F32 &to_lower, F32& to_higher);
 	static F32 getVolumeScaleFromDetail(const S32 detail);
 
-	LLVolume *getLOD(const S32 detail);
-	const LLVolumeParams& getParams() const { return mParams; };
+	LLVolume* getLODVolume(const S32 detail);
+	BOOL derefLOD(LLVolume *volumep);
+	S32 getNumRefs() const { return mRefs; }
+	
+	const LLVolumeParams* getVolumeParams() const { return &mVolumeParams; };
 
 	F32	dump();
 	friend std::ostream& operator<<(std::ostream& s, const LLVolumeLODGroup& volgroup);
 
-#ifdef DEBUG_VOLUME
-	S32 getTotalVolumeRefCount() const;
-#endif
-
 protected:
-	virtual ~LLVolumeLODGroup();
-	void destroy();
-	
-protected:
-	LLVolumeParams mParams;
+	LLVolumeParams mVolumeParams;
 
+	S32 mRefs;
 	S32 mLODRefs[NUM_LODS];
 	LLPointer<LLVolume> mVolumeLODs[NUM_LODS];
 	static F32 mDetailThresholds[NUM_LODS];
@@ -82,10 +81,6 @@ class LLVolumeLODGroup : public LLThreadSafeRefCount
 
 class LLVolumeMgr
 {
-//public:
-//	static void initClass();
-//	static BOOL cleanupClass();
-	
 public:
 	LLVolumeMgr();
 	virtual ~LLVolumeMgr();
@@ -96,36 +91,26 @@ class LLVolumeMgr
 	// whatever calls getVolume() never owns the LLVolume* and
 	// cannot keep references for long since it may be deleted
 	// later.  For best results hold it in an LLPointer<LLVolume>.
-	LLVolume *getVolume(const LLVolumeParams &volume_params, const S32 detail);
-
-	void cleanupVolume(LLVolume *volumep);
+	LLVolume *refVolume(const LLVolumeParams &volume_params, const S32 detail);
+	void unrefVolume(LLVolume *volumep);
 
 	void dump();
 
 	// manually call this for mutex magic
 	void useMutex();
 
-#ifdef DEBUG_VOLUME
-	S32 getTotalRefCount() const;
-	S32 getGroupCount() const;
-#endif
 	friend std::ostream& operator<<(std::ostream& s, const LLVolumeMgr& volume_mgr);
 
 protected:
+	void insertGroup(LLVolumeLODGroup* volgroup);
+	// Overridden in llphysics/abstract/utils/llphysicsvolumemanager.h
 	virtual LLVolumeLODGroup* createNewGroup(const LLVolumeParams& volume_params);
 
 protected:
 	typedef std::map<const LLVolumeParams*, LLVolumeLODGroup*, LLVolumeParams::compare> volume_lod_group_map_t;
-	typedef volume_lod_group_map_t::const_iterator volume_lod_group_map_iter;
 	volume_lod_group_map_t mVolumeLODGroups;
 
 	LLMutex* mDataMutex;
-
-	// We need to be able to disable threadsafe checks to prevent 
-	// some unit_tests from blocking on failure
-	bool mThreadSafe;
 };
 
-//extern LLVolumeMgr* gVolumeMgr;
-
 #endif // LL_LLVOLUMEMGR_H
diff --git a/indra/llprimitive/llprimitive.cpp b/indra/llprimitive/llprimitive.cpp
index cc676f73f18bb694d7d0e345f3fee6fd1ed91fc8..ff69cacf0f465850bf3c6eaa3d1c58298dcb7053 100644
--- a/indra/llprimitive/llprimitive.cpp
+++ b/indra/llprimitive/llprimitive.cpp
@@ -32,6 +32,7 @@
 #include "linden_common.h"
 
 #include "material_codes.h"
+#include "llmemtype.h"
 #include "llerror.h"
 #include "message.h"
 #include "llprimitive.h"
@@ -178,7 +179,7 @@ LLPrimitive::~LLPrimitive()
 	// Cleanup handled by volume manager
 	if (mVolumep)
 	{
-		sVolumeManager->cleanupVolume(mVolumep);
+		sVolumeManager->unrefVolume(mVolumep);
 	}
 	mVolumep = NULL;
 }
@@ -187,6 +188,7 @@ LLPrimitive::~LLPrimitive()
 // static
 LLPrimitive *LLPrimitive::createPrimitive(LLPCode p_code)
 {
+	LLMemType m1(LLMemType::MTYPE_PRIMITIVE);
 	LLPrimitive *retval = new LLPrimitive();
 	
 	if (retval)
@@ -204,6 +206,7 @@ LLPrimitive *LLPrimitive::createPrimitive(LLPCode p_code)
 //===============================================================
 void LLPrimitive::init_primitive(LLPCode p_code)
 {
+	LLMemType m1(LLMemType::MTYPE_PRIMITIVE);
 	if (mNumTEs)
 	{
 		if (mTextureList)
@@ -246,6 +249,7 @@ void LLPrimitive::setNumTEs(const U8 num_tes)
 	// Right now, we don't try and preserve entries when the number of faces
 	// changes.
 
+	LLMemType m1(LLMemType::MTYPE_PRIMITIVE);
 	if (num_tes)
 	{
 		LLTextureEntry *new_tes;
@@ -914,6 +918,7 @@ S32	face_index_from_id(LLFaceID face_ID, const std::vector<LLProfile::Face>& fac
 
 BOOL LLPrimitive::setVolume(const LLVolumeParams &volume_params, const S32 detail, bool unique_volume)
 {
+	LLMemType m1(LLMemType::MTYPE_VOLUME);
 	LLVolume *volumep;
 	if (unique_volume)
 	{
@@ -935,10 +940,10 @@ BOOL LLPrimitive::setVolume(const LLVolumeParams &volume_params, const S32 detai
 			}
 		}
 
-		volumep = sVolumeManager->getVolume(volume_params, detail);
+		volumep = sVolumeManager->refVolume(volume_params, detail);
 		if (volumep == mVolumep)
 		{
-			sVolumeManager->cleanupVolume( volumep );  // LLVolumeMgr::getVolume() creates a reference, but we don't need a second one.
+			sVolumeManager->unrefVolume( volumep );  // LLVolumeMgr::refVolume() creates a reference, but we don't need a second one.
 			return TRUE;
 		}
 	}
@@ -981,7 +986,7 @@ BOOL LLPrimitive::setVolume(const LLVolumeParams &volume_params, const S32 detai
 
 
 	// build the new object
-	sVolumeManager->cleanupVolume(mVolumep);
+	sVolumeManager->unrefVolume(mVolumep);
 	mVolumep = volumep;
 	
 	U32 new_face_mask = mVolumep->mFaceMask;
diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp
index 2a8424a09b4c7bc051032ba6538880f3b58fe327..d5ad38dff3725e3686806773ab74a043e05c05b0 100644
--- a/indra/llrender/llimagegl.cpp
+++ b/indra/llrender/llimagegl.cpp
@@ -128,10 +128,16 @@ S32 LLImageGL::dataFormatComponents(S32 dataformat)
 void LLImageGL::bindExternalTexture(LLGLuint gl_name, S32 stage, LLGLenum bind_target )
 {
 	gGL.flush();
-	glActiveTextureARB(GL_TEXTURE0_ARB + stage);
-	glClientActiveTextureARB(GL_TEXTURE0_ARB + stage);
+	if (stage > 0)
+	{
+		glActiveTextureARB(GL_TEXTURE0_ARB + stage);
+	}
 	glBindTexture(bind_target, gl_name);
 	sCurrentBoundTextures[stage] = gl_name;
+	if (stage > 0)
+	{
+		glActiveTextureARB(GL_TEXTURE0_ARB);
+	}
 }
 
 // static
@@ -141,9 +147,16 @@ void LLImageGL::unbindTexture(S32 stage, LLGLenum bind_target)
 	if (stage >= 0)
 	{
 		gGL.flush();
-		glActiveTextureARB(GL_TEXTURE0_ARB + stage);
-		glClientActiveTextureARB(GL_TEXTURE0_ARB + stage);
-		glBindTexture(bind_target, 0);
+		if (stage > 0)
+		{
+			glActiveTextureARB(GL_TEXTURE0_ARB + stage);
+			glBindTexture(GL_TEXTURE_2D, 0);
+			glActiveTextureARB(GL_TEXTURE0_ARB);
+		}
+		else
+		{
+			glBindTexture(GL_TEXTURE_2D, 0);
+		}
 		sCurrentBoundTextures[stage] = 0;
 	}
 }
@@ -151,15 +164,7 @@ void LLImageGL::unbindTexture(S32 stage, LLGLenum bind_target)
 // static (duplicated for speed and to avoid GL_TEXTURE_2D default argument which requires GL header dependency)
 void LLImageGL::unbindTexture(S32 stage)
 {
-	// LLGLSLShader can return -1
-	if (stage >= 0)
-	{
-		gGL.flush();
-		glActiveTextureARB(GL_TEXTURE0_ARB + stage);
-		glClientActiveTextureARB(GL_TEXTURE0_ARB + stage);
-		glBindTexture(GL_TEXTURE_2D, 0);
-		sCurrentBoundTextures[stage] = 0;
-	}
+	unbindTexture(stage, GL_TEXTURE_2D);
 }
 
 // static
@@ -419,8 +424,6 @@ BOOL LLImageGL::bindTextureInternal(const S32 stage) const
 	}
 
 
-	glActiveTextureARB(GL_TEXTURE0_ARB + stage);
-		
 	if (sCurrentBoundTextures[stage] && sCurrentBoundTextures[stage] == mTexName)
 	{
 		// already set!
@@ -434,10 +437,20 @@ BOOL LLImageGL::bindTextureInternal(const S32 stage) const
 #endif
 
 		gGL.flush();
+		if (stage > 0)
+		{
+			glActiveTextureARB(GL_TEXTURE0_ARB + stage);
+		}
+	
 		glBindTexture(mBindTarget, mTexName);
 		sCurrentBoundTextures[stage] = mTexName;
 		sBindCount++;
 
+		if (stage > 0)
+		{
+			glActiveTextureARB(GL_TEXTURE0_ARB);
+		}
+		
 		if (mLastBindTime != sLastFrameTime)
 		{
 			// we haven't accounted for this texture yet this frame
@@ -451,7 +464,15 @@ BOOL LLImageGL::bindTextureInternal(const S32 stage) const
 	else
 	{
 		gGL.flush();
+		if (stage > 0)
+		{
+			glActiveTextureARB(GL_TEXTURE0_ARB+stage);
+		}
 		glBindTexture(mBindTarget, 0);
+		if (stage > 0)
+		{
+			glActiveTextureARB(GL_TEXTURE0_ARB+stage);
+		}
 		sCurrentBoundTextures[stage] = 0;
 		return FALSE;
 	}
@@ -594,18 +615,25 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)
 				S32 w = width, h = height;
 				const U8* prev_mip_data = 0;
 				const U8* cur_mip_data = 0;
+				S32 prev_mip_size = 0;
+				S32 cur_mip_size = 0;
 				for (int m=0; m<nummips; m++)
 				{
 					if (m==0)
 					{
 						cur_mip_data = data_in;
+						cur_mip_size = width * height * mComponents; 
 					}
 					else
 					{
 						S32 bytes = w * h * mComponents;
+						llassert(prev_mip_data);
+						llassert(prev_mip_size == bytes);
 						U8* new_data = new U8[bytes];
+						llassert_always(new_data);
 						LLImageBase::generateMip(prev_mip_data, new_data, w, h, mComponents);
 						cur_mip_data = new_data;
+						cur_mip_size = bytes; 
 					}
 					llassert(w > 0 && h > 0 && cur_mip_data);
 					{
@@ -630,12 +658,14 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)
 						delete[] prev_mip_data;
 					}
 					prev_mip_data = cur_mip_data;
+					prev_mip_size = cur_mip_size;
 					w >>= 1;
 					h >>= 1;
 				}
 				if (prev_mip_data && prev_mip_data != data_in)
 				{
 					delete[] prev_mip_data;
+					prev_mip_data = NULL;
 				}
 			}
 		}
@@ -985,6 +1015,21 @@ BOOL LLImageGL::setDiscardLevel(S32 discard_level)
 	}
 }
 
+BOOL LLImageGL::isValidForSculpt(S32 discard_level, S32 image_width, S32 image_height, S32 ncomponents)
+{
+	assert_glerror();
+	S32 gl_discard = discard_level - mCurrentDiscardLevel;
+	LLGLint glwidth = 0;
+	glGetTexLevelParameteriv(mTarget, gl_discard, GL_TEXTURE_WIDTH, (GLint*)&glwidth);
+	LLGLint glheight = 0;
+	glGetTexLevelParameteriv(mTarget, gl_discard, GL_TEXTURE_HEIGHT, (GLint*)&glheight);
+	LLGLint glcomponents = 0 ;
+	glGetTexLevelParameteriv(mTarget, gl_discard, GL_TEXTURE_INTERNAL_FORMAT, (GLint*)&glcomponents);
+	assert_glerror();
+
+	return glwidth >= image_width && glheight >= image_height && (GL_RGB8 == glcomponents || GL_RGBA8 == glcomponents) ;
+}
+
 BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compressed_ok)
 {
 	if (discard_level < 0)
@@ -1022,6 +1067,7 @@ BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compre
 		llerrs << llformat("LLImageGL::readBackRaw: bogus params: %d x %d x %d",width,height,ncomponents) << llendl;
 	}
 	
+	BOOL return_result = TRUE ;
 	LLGLint is_compressed = 0;
 	if (compressed_ok)
 	{
@@ -1033,16 +1079,28 @@ BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compre
 		glGetTexLevelParameteriv(mTarget, gl_discard, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, (GLint*)&glbytes);
 		imageraw->allocateDataSize(width, height, ncomponents, glbytes);
 		glGetCompressedTexImageARB(mTarget, gl_discard, (GLvoid*)(imageraw->getData()));
+		if(glGetError() != GL_NO_ERROR)
+		{
+			llwarns << "Error happens when reading back the compressed texture image." << llendl ;
+			imageraw->deleteData() ;
+			return_result = FALSE ;
+		}
 		stop_glerror();
 	}
 	else
 	{
 		imageraw->allocateDataSize(width, height, ncomponents);
 		glGetTexImage(GL_TEXTURE_2D, gl_discard, mFormatPrimary, mFormatType, (GLvoid*)(imageraw->getData()));
+		if(glGetError() != GL_NO_ERROR)
+		{
+			llwarns << "Error happens when reading back the texture image." << llendl ;
+			imageraw->deleteData() ;
+			return_result = FALSE ;
+		}
 		stop_glerror();
 	}
 		
-	return TRUE;
+	return return_result ;
 }
 
 void LLImageGL::destroyGLTexture()
@@ -1057,7 +1115,6 @@ void LLImageGL::destroyGLTexture()
 			{
 				unbindTexture(i, GL_TEXTURE_2D);
 				stop_glerror();
-				glActiveTextureARB(GL_TEXTURE0_ARB);
 			}
 		}
 
diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h
index 20cf4ae10f09f8563df8778e4987f9e99e6153a1..82ea147d6ecca69fd0a677619f07cf0cfa41f866 100644
--- a/indra/llrender/llimagegl.h
+++ b/indra/llrender/llimagegl.h
@@ -131,6 +131,8 @@ class LLImageGL : public LLRefCount
 	BOOL getUseDiscard() const { return mUseMipMaps && !mDontDiscard; }
 	BOOL getDontDiscard() const { return mDontDiscard; }
 
+	BOOL isValidForSculpt(S32 discard_level, S32 image_width, S32 image_height, S32 ncomponents) ;
+
 protected:
 	void init(BOOL usemipmaps);
 	virtual void cleanup(); // Clean up the LLImageGL so it can be reinitialized.  Be careful when using this in derived class destructors
diff --git a/indra/llrender/llrendertarget.h b/indra/llrender/llrendertarget.h
index 7f9c611c69ba03083dfabf296ca55b5157a42c7c..27c40fcfcf3d01e409f12365d7f68f6d2a05c1fd 100644
--- a/indra/llrender/llrendertarget.h
+++ b/indra/llrender/llrendertarget.h
@@ -71,7 +71,7 @@ class LLRenderTarget
 	//allocate resources for rendering
 	//must be called before use
 	//multiple calls will release previously allocated resources
-	void allocate(U32 resx, U32 resy, U32 color_fmt, BOOL depth, U32 usage = GL_TEXTURE_2D, BOOL use_fbo = TRUE);
+	void allocate(U32 resx, U32 resy, U32 color_fmt, BOOL depth, U32 usage = GL_TEXTURE_2D, BOOL use_fbo = FALSE);
 
 	//allocate a depth texture
 	void allocateDepth();
diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp
index 9303e00228bdf173b2e9c2a439d771f03981eb6f..b646a02cae429ae7b73015b61218872616090104 100644
--- a/indra/llrender/llvertexbuffer.cpp
+++ b/indra/llrender/llvertexbuffer.cpp
@@ -38,6 +38,7 @@
 #include "llglheaders.h"
 #include "llmemory.h"
 #include "llmemtype.h"
+#include "llglimmediate.h"
 
 //============================================================================
 
@@ -76,6 +77,141 @@ S32 LLVertexBuffer::sTypeOffsets[LLVertexBuffer::TYPE_MAX] =
 	sizeof(LLVector4), // TYPE_CLOTHWEIGHT,
 };
 
+U32 LLVertexBuffer::sGLMode[LLVertexBuffer::NUM_MODES] = 
+{
+	GL_TRIANGLES,
+	GL_TRIANGLE_STRIP,
+	GL_TRIANGLE_FAN,
+	GL_POINTS,
+	GL_LINES,
+	GL_LINE_STRIP
+};
+
+//static
+void LLVertexBuffer::setupClientArrays(U32 data_mask)
+{
+	if (LLGLImmediate::sStarted)
+	{
+		llerrs << "Cannot use LLGLImmediate and LLVertexBuffer simultaneously!" << llendl;
+	}
+
+	if (sLastMask != data_mask)
+	{
+		U32 mask[] =
+		{
+			MAP_VERTEX,
+			MAP_NORMAL,
+			MAP_TEXCOORD,
+			MAP_COLOR
+		};
+		
+		GLenum array[] =
+		{
+			GL_VERTEX_ARRAY,
+			GL_NORMAL_ARRAY,
+			GL_TEXTURE_COORD_ARRAY,
+			GL_COLOR_ARRAY
+		};
+
+		for (U32 i = 0; i < 4; ++i)
+		{
+			if (sLastMask & mask[i])
+			{ //was enabled
+				if (!(data_mask & mask[i]) && i > 0)
+				{ //needs to be disabled
+					glDisableClientState(array[i]);
+				}
+				else
+				{ //needs to be enabled, make sure it was (DEBUG TEMPORARY)
+					if (i > 0 && !glIsEnabled(array[i]))
+					{
+						llerrs << "Bad client state! " << array[i] << " disabled." << llendl;
+					}
+				}
+			}
+			else 
+			{	//was disabled
+				if (data_mask & mask[i])
+				{ //needs to be enabled
+					glEnableClientState(array[i]);
+				}
+				else if (glIsEnabled(array[i]))
+				{ //needs to be disabled, make sure it was (DEBUG TEMPORARY)
+					llerrs << "Bad client state! " << array[i] << " enabled." << llendl;
+				}
+			}
+		}
+
+		if (sLastMask & MAP_TEXCOORD2)
+		{
+			if (!(data_mask & MAP_TEXCOORD2))
+			{
+				glClientActiveTextureARB(GL_TEXTURE1_ARB);
+				glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+				glClientActiveTextureARB(GL_TEXTURE0_ARB);
+			}
+		}
+		else if (data_mask & MAP_TEXCOORD2)
+		{
+			glClientActiveTextureARB(GL_TEXTURE1_ARB);
+			glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+			glClientActiveTextureARB(GL_TEXTURE0_ARB);
+		}
+
+		sLastMask = data_mask;
+	}
+}
+
+void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indices_offset) const
+{
+	if (start >= (U32) mRequestedNumVerts ||
+		end >= (U32) mRequestedNumVerts)
+	{
+		llerrs << "Bad vertex buffer draw range: [" << start << ", " << end << "]" << llendl;
+	}
+
+	if (indices_offset >= (U32) mRequestedNumIndices ||
+		indices_offset + count > (U32) mRequestedNumIndices)
+	{
+		llerrs << "Bad index buffer draw range: [" << indices_offset << ", " << indices_offset+count << "]" << llendl;
+	}
+
+	if (mGLIndices != sGLRenderIndices)
+	{
+		llerrs << "Wrong index buffer bound." << llendl;
+	}
+
+	if (mGLBuffer != sGLRenderBuffer)
+	{
+		llerrs << "Wrong vertex buffer bound." << llendl;
+	}
+
+	glDrawRangeElements(sGLMode[mode], start, end, count, GL_UNSIGNED_SHORT, 
+		((U16*) getIndicesPointer()) + indices_offset);
+}
+
+void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const
+{
+	if (indices_offset >= (U32) mRequestedNumIndices ||
+		indices_offset + count > (U32) mRequestedNumIndices)
+	{
+		llerrs << "Bad index buffer draw range: [" << indices_offset << ", " << indices_offset+count << "]" << llendl;
+	}
+
+	if (mGLIndices != sGLRenderIndices)
+	{
+		llerrs << "Wrong index buffer bound." << llendl;
+	}
+
+	if (mGLBuffer != sGLRenderBuffer)
+	{
+		llerrs << "Wrong vertex buffer bound." << llendl;
+	}
+
+	glDrawElements(sGLMode[mode], count, GL_UNSIGNED_SHORT,
+		((U16*) getIndicesPointer()) + indices_offset);
+}
+
 //static
 void LLVertexBuffer::initClass(bool use_vbo)
 {
@@ -102,7 +238,8 @@ void LLVertexBuffer::unbind()
 
 	sGLRenderBuffer = 0;
 	sGLRenderIndices = 0;
-	sLastMask = 0;
+
+	setupClientArrays(0);
 }
 
 //static
@@ -118,22 +255,14 @@ void LLVertexBuffer::cleanupClass()
 void LLVertexBuffer::startRender()
 {		
 	LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
-	if (sEnableVBOs)
-	{
-		glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
-		glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
-		sVBOActive = FALSE;
-		sIBOActive = FALSE;
-	}
-	
+
+	unbind();
 	sRenderActive = TRUE;
-	sGLRenderBuffer = 0;
-	sGLRenderIndices = 0;
-	sLastMask = 0;
 }
 
 void LLVertexBuffer::stopRender()
 {
+	unbind();
 	sRenderActive = FALSE;
 }
 
@@ -615,6 +744,16 @@ U8* LLVertexBuffer::mapBuffer(S32 access)
 			llerrs << "Mapped two VBOs at the same time!" << llendl;
 		}
 		sMapped = TRUE;*/
+		if (!mMappedData)
+		{
+			llerrs << "glMapBuffer returned NULL (no vertex data)" << llendl;
+		}
+
+		if (!mMappedIndexData)
+		{
+			llerrs << "glMapBuffer returned NULL (no index data)" << llendl;
+		}
+
 		sMappedCount++;
 	}
 	
@@ -666,7 +805,12 @@ template <class T,S32 type> struct VertexBufferStrider
 					strider_t& strider, 
 					S32 index)
 	{
-		vbo.mapBuffer();
+		if (vbo.mapBuffer() == NULL)
+		{
+			llwarns << "mapBuffer failed!" << llendl;
+			return FALSE;
+		}
+
 		if (type == LLVertexBuffer::TYPE_INDEX)
 		{
 			S32 stride = sizeof(T);
@@ -828,6 +972,8 @@ void LLVertexBuffer::setBuffer(U32 data_mask)
 			sIBOActive = FALSE;
 		}
 	}
+
+	setupClientArrays(data_mask);
 	
 	if (mGLIndices)
 	{
@@ -846,8 +992,6 @@ void LLVertexBuffer::setBuffer(U32 data_mask)
 			sSetCount++;
 		}
 	}
-
-	sLastMask = data_mask;
 }
 
 // virtual (default)
@@ -871,10 +1015,10 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask) const
 	{
 		glClientActiveTextureARB(GL_TEXTURE1_ARB);
 		glTexCoordPointer(2,GL_FLOAT, stride, (void*)(base + mOffsets[TYPE_TEXCOORD2]));
+		glClientActiveTextureARB(GL_TEXTURE0_ARB);
 	}
 	if (data_mask & MAP_TEXCOORD)
 	{
-		glClientActiveTextureARB(GL_TEXTURE0_ARB);
 		glTexCoordPointer(2,GL_FLOAT, stride, (void*)(base + mOffsets[TYPE_TEXCOORD]));
 	}
 	if (data_mask & MAP_COLOR)
diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h
index e2a4196b0e341d4f57ce8128eb9edfcfe07fb05d..50f79cfc9dd5614ddda064c364ea2c3863614193 100644
--- a/indra/llrender/llvertexbuffer.h
+++ b/indra/llrender/llvertexbuffer.h
@@ -84,6 +84,7 @@ class LLVertexBuffer : public LLRefCount
 
 	static void initClass(bool use_vbo);
 	static void cleanupClass();
+	static void setupClientArrays(U32 data_mask);
  	static void startRender(); //between start and stop render, no client copies will occur
 	static void stopRender(); //any buffer not copied to GL will be rendered from client memory
 	static void clientCopy(F64 max_time = 0.005); //copy data from client to GL
@@ -123,6 +124,15 @@ class LLVertexBuffer : public LLRefCount
 		MAP_UNMAPPED = 0x8000 // Indicates that buffer has been logically un-mapped
 	};
 	
+	enum {
+		TRIANGLES = 0,
+		TRIANGLE_STRIP,
+		TRIANGLE_FAN,
+		POINTS,
+		LINES,
+		LINE_STRIP,
+		NUM_MODES
+	};
 protected:
 	friend class LLGLImmediate;
 
@@ -194,6 +204,9 @@ class LLVertexBuffer : public LLRefCount
 	
 	void markDirty(U32 vert_index, U32 vert_count, U32 indices_index, U32 indices_count);
 
+	void draw(U32 mode, U32 count, U32 indices_offset) const;
+	void drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indices_offset) const;
+
 protected:	
 	S32		mNumVerts;		// Number of vertices allocated
 	S32		mNumIndices;	// Number of indices allocated
@@ -241,6 +254,7 @@ class LLVertexBuffer : public LLRefCount
 		
 	static BOOL sEnableVBOs;
 	static S32 sTypeOffsets[TYPE_MAX];
+	static U32 sGLMode[NUM_MODES];
 	static U32 sGLRenderBuffer;
 	static U32 sGLRenderIndices;
 	static BOOL sVBOActive;
diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index 4829d5b893a26d82e1b1d508e88a82c5fef24d3b..f80028656e0ed4b990d85de1457a6210af4859cf 100644
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -923,6 +923,7 @@ void LLFloater::setFocus( BOOL b )
 	}
 }
 
+// virtual
 void LLFloater::setIsChrome(BOOL is_chrome)
 {
 	// chrome floaters don't take focus at all
@@ -941,6 +942,12 @@ void LLFloater::setIsChrome(BOOL is_chrome)
 	LLPanel::setIsChrome(is_chrome);
 }
 
+void LLFloater::setTitleVisible(bool visible)
+{
+	if (mDragHandle)
+		mDragHandle->setTitleVisible(visible);
+}
+
 // Change the draw style to account for the foreground state.
 void LLFloater::setForeground(BOOL front)
 {
diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h
index 280789d64c952c7991d9e4dd564373673bcf73c8..4e8b86d2de76ce94cfc16403c2b72a8996634dec 100644
--- a/indra/llui/llfloater.h
+++ b/indra/llui/llfloater.h
@@ -146,6 +146,7 @@ friend class LLFloaterView;
 	const LLString&	getTitle() const;
 	void			setShortTitle( const LLString& short_title );
 	LLString		getShortTitle();
+	void			setTitleVisible(bool visible);
 	virtual void	setMinimized(BOOL b);
 	void			moveResizeHandlesToFront();
 	void			addDependentFloater(LLFloater* dependent, BOOL reposition = TRUE);
diff --git a/indra/llui/llscrollbar.cpp b/indra/llui/llscrollbar.cpp
index 90659cdc70977028b7cb1dc8c28973448c4865f5..2c4a5cbc581450728c59dccec349830e1e7c7564 100644
--- a/indra/llui/llscrollbar.cpp
+++ b/indra/llui/llscrollbar.cpp
@@ -501,6 +501,13 @@ void LLScrollbar::draw()
 	}
 	else
 	{
+		// Background
+		rounded_rect_imagep->drawSolid(mOrientation == HORIZONTAL ? SCROLLBAR_SIZE : 0, 
+			mOrientation == VERTICAL ? SCROLLBAR_SIZE : 0,
+			mOrientation == HORIZONTAL ? getRect().getWidth() - 2 * SCROLLBAR_SIZE : getRect().getWidth(), 
+			mOrientation == VERTICAL ? getRect().getHeight() - 2 * SCROLLBAR_SIZE : getRect().getHeight(),
+			mTrackColor);
+
 		// Thumb
 		LLRect outline_rect = mThumbRect;
 		outline_rect.stretch(2);
diff --git a/indra/llui/llscrollcontainer.cpp b/indra/llui/llscrollcontainer.cpp
index d8df636abdb14775311113655909e96067bc79bd..edad4c4d6bdf945f531914739dd9dfb84c23dea4 100644
--- a/indra/llui/llscrollcontainer.cpp
+++ b/indra/llui/llscrollcontainer.cpp
@@ -430,7 +430,7 @@ void LLScrollableContainerView::draw()
 	if( mIsOpaque )
 	{
 		LLGLSNoTexture no_texture;
-		glColor4fv( mBackgroundColor.mV );
+		gGL.color4fv( mBackgroundColor.mV );
 		gl_rect_2d( mInnerRect );
 	}
 	
diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp
index eb244a6f824a1c5fc953e4936b10344bda73d694..4e640eac2aa258c983383bd0e85491acd3c24e83 100644
--- a/indra/llui/llscrolllistctrl.cpp
+++ b/indra/llui/llscrolllistctrl.cpp
@@ -1759,7 +1759,7 @@ void LLScrollListCtrl::draw()
 	if (mBackgroundVisible)
 	{
 		LLGLSNoTexture no_texture;
-		glColor4fv( getEnabled() ? mBgWriteableColor.mV : mBgReadOnlyColor.mV );
+		gGL.color4fv( getEnabled() ? mBgWriteableColor.mV : mBgReadOnlyColor.mV );
 		gl_rect_2d(background);
 	}
 
diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp
index e6e999bac402334c0048e22ba46491e69c970e2e..06b4fbde59f7417021227c6cceba864f9e96499d 100644
--- a/indra/llwindow/llwindowwin32.cpp
+++ b/indra/llwindow/llwindowwin32.cpp
@@ -1326,8 +1326,9 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BO
 		close();
 		OSMessageBox(
 					 "Second Life is unable to run because your video card drivers\n"
-					 "are out of date or unsupported. Please make sure you have\n"
-					 "the latest video card drivers installed.\n\n"
+					 "did not install properly, are out of date, or are for unsupported\n" 
+					 "hardware. Please make sure you have the latest video card drivers\n"
+					 "and even if you do have the latest, try reinstalling them.\n\n"
 					 "If you continue to receive this message, contact customer service.",
 					 "Error",
 					 OSMB_OK);
@@ -1836,6 +1837,10 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
 			break;
 		}
 		case WM_IME_SETCONTEXT:
+			if (gDebugWindowProc)
+			{
+				llinfos << "WM_IME_SETCONTEXT" << llendl;
+			}
 			if (LLWinImm::isAvailable() && window_imp->mPreeditor)
 			{
 				l_param &= ~ISC_SHOWUICOMPOSITIONWINDOW;
@@ -1844,6 +1849,10 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
 			break;
 
 		case WM_IME_STARTCOMPOSITION:
+			if (gDebugWindowProc)
+			{
+				llinfos << "WM_IME_STARTCOMPOSITION" << llendl;
+			}
 			if (LLWinImm::isAvailable() && window_imp->mPreeditor)
 			{
 				window_imp->handleStartCompositionMessage();
@@ -1852,6 +1861,10 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
 			break;
 
 		case WM_IME_ENDCOMPOSITION:
+			if (gDebugWindowProc)
+			{
+				llinfos << "WM_IME_ENDCOMPOSITION" << llendl;
+			}
 			if (LLWinImm::isAvailable() && window_imp->mPreeditor)
 			{
 				return 0;
@@ -1859,6 +1872,10 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
 			break;
 
 		case WM_IME_COMPOSITION:
+			if (gDebugWindowProc)
+			{
+				llinfos << "WM_IME_COMPOSITION" << llendl;
+			}
 			if (LLWinImm::isAvailable() && window_imp->mPreeditor)
 			{
 				window_imp->handleCompositionMessage(l_param);
@@ -1867,6 +1884,10 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
 			break;
 
 		case WM_IME_REQUEST:
+			if (gDebugWindowProc)
+			{
+				llinfos << "WM_IME_REQUEST" << llendl;
+			}
 			if (LLWinImm::isAvailable() && window_imp->mPreeditor)
 			{
 				LRESULT result = 0;
diff --git a/indra/llxml/llcontrol.cpp b/indra/llxml/llcontrol.cpp
index a1d2620a6fd5371e6adb9ad54bce5c079fd4fcd3..2c4fb3bcccd13e0f2b6ed0e7d08ca89aea0e4b05 100644
--- a/indra/llxml/llcontrol.cpp
+++ b/indra/llxml/llcontrol.cpp
@@ -953,7 +953,7 @@ U32 LLControlGroup::saveToFile(const LLString& filename, BOOL nondefault_only)
 	return num_saved;
 }
 
-U32 LLControlGroup::loadFromFile(const LLString& filename, BOOL require_declaration, eControlType declare_as)
+U32 LLControlGroup::loadFromFile(const LLString& filename)
 {
 	LLString name;
 	LLSD settings;
@@ -965,24 +965,47 @@ U32 LLControlGroup::loadFromFile(const LLString& filename, BOOL require_declarat
 		llwarns << "Cannot find file " << filename << " to load." << llendl;
 		return 0;
 	}
+
 	S32 ret = LLSDSerialize::fromXML(settings, infile);
+
 	if (ret <= 0)
 	{
 		infile.close();
 		llwarns << "Unable to open LLSD control file " << filename << ". Trying Legacy Method." << llendl;		
-		return loadFromFileLegacy(filename, require_declaration, declare_as);
+		return loadFromFileLegacy(filename, TRUE, TYPE_STRING);
 	}
 
-	U32		validitems = 0;
+	U32	validitems = 0;
 	int persist = 1;
 	for(LLSD::map_const_iterator itr = settings.beginMap(); itr != settings.endMap(); ++itr)
 	{
 		name = (*itr).first;
 		control_map = (*itr).second;
 		
-		if(control_map.has("Persist")) persist = control_map["Persist"].asInteger();
+		if(control_map.has("Persist")) 
+		{
+			persist = control_map["Persist"].asInteger();
+		}
 		
-		declareControl(name, typeStringToEnum(control_map["Type"].asString()), control_map["Value"], control_map["Comment"].asString(), persist);
+		// If the control exists just set the value from the input file.
+		LLControlVariable* existing_control = getControl(name);
+		if(existing_control)
+		{
+			// Check persistence. If not persisted, we shouldn't be loading.
+			if(existing_control->isPersisted())
+			{
+				existing_control->setValue(control_map["Value"]);
+			}
+		}
+		else
+		{
+			declareControl(name, 
+						   typeStringToEnum(control_map["Type"].asString()), 
+						   control_map["Value"], 
+						   control_map["Comment"].asString(), 
+						   persist
+						   );
+		}
 		
 		++validitems;
 	}
diff --git a/indra/llxml/llcontrol.h b/indra/llxml/llcontrol.h
index 7a638a7b73c1078c66e3faa2ef2ae250e24f1b70..7287731cfaa3c03db6d6e9c8104351d7cd846049 100644
--- a/indra/llxml/llcontrol.h
+++ b/indra/llxml/llcontrol.h
@@ -213,7 +213,7 @@ class LLControlGroup
 	// as the given type.
 	U32	loadFromFileLegacy(const LLString& filename, BOOL require_declaration = TRUE, eControlType declare_as = TYPE_STRING);
  	U32 saveToFile(const LLString& filename, BOOL nondefault_only);
- 	U32	loadFromFile(const LLString& filename, BOOL require_declaration = TRUE, eControlType declare_as = TYPE_STRING);
+ 	U32	loadFromFile(const LLString& filename);
 	void	resetToDefaults();
 
 	
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 41566d68d01aa1370c1fb0c07dd02de4129c46df..73a832ead7e0b95360d9e25386af2c96eeac4ced 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -5829,7 +5829,7 @@
     <key>RenderUseCleverUI</key>
         <map>
         <key>Comment</key>
-            <string>Turns on the \"clever\" UI rendering optimization.  It's a known performace gain (and enabled by default) on apple.</string>
+            <string>Turns on the \"clever\" UI rendering optimization. It's a known performace gain on apple.</string>
         <key>Persist</key>
             <integer>1</integer>
         <key>Type</key>
@@ -9825,17 +9825,6 @@
                 <integer>0</integer>
             </array>
 	    </map>
-    <key>AlertedUnsupportedHardware</key>
-		<map>
-		<key>Comment</key>
-			<string>Toggle that lets us tell the user he's on old hardware only once</string>
-		<key>Persist</key>
-			<integer>1</integer>
-		<key>Type</key>
-			<string>Boolean</string>
-		<key>Value</key>
-			<integer>0</integer>
-		</map>
     <key>RenderFastAlpha</key>
 		<map>
 		<key>Comment</key>
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 572927f9181d189e3b053b9aad7452b24351939d..ee471d21ac8725ab88521c7a62ee31ebc54086ea 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -64,6 +64,7 @@
 #include "llurldispatcher.h"
 #include "llurlhistory.h"
 #include "llfirstuse.h"
+#include "llglimmediate.h"
 
 #include "llweb.h"
 #include "llsecondlifeurls.h"
@@ -416,10 +417,11 @@ static void settings_to_globals()
 static void settings_modify()
 {
 	LLRenderTarget::sUseFBO				= gSavedSettings.getBOOL("RenderUseFBO");
-	LLVOAvatar::sUseImpostors			= FALSE; //gSavedSettings.getBOOL("RenderUseImpostors");
+	LLVOAvatar::sUseImpostors			= gSavedSettings.getBOOL("RenderUseImpostors");
 	LLVOSurfacePatch::sLODFactor		= gSavedSettings.getF32("RenderTerrainLODFactor");
 	LLVOSurfacePatch::sLODFactor *= LLVOSurfacePatch::sLODFactor; //sqaure lod factor to get exponential range of [1,4]
-
+	gGL.setClever(gSavedSettings.getBOOL("RenderUseCleverUI"));
+	
 #if LL_VECTORIZE
 	if (gSysCPU.hasAltivec())
 	{
@@ -774,15 +776,6 @@ bool LLAppViewer::init()
 		return 1;
 	}
 	
-#if LL_DARWIN
-	// Display the release notes for the current version
-	if(!gHideLinks && gCurrentVersion != gLastRunVersion)
-	{
-		// Current version and last run version don't match exactly.  Display the release notes.
-		DisplayReleaseNotes();
-	}
-#endif
-
 	//
 	// Initialize the window
 	//
@@ -821,51 +814,55 @@ bool LLAppViewer::init()
 		return 0;
 	}
 
-	// alert the user if they are using unsupported hardware
-	if(!gSavedSettings.getBOOL("AlertedUnsupportedHardware"))
-	{
-		bool unsupported = false;
-		LLString::format_map_t args;
-		LLString minSpecs;
+
+	bool unsupported = false;
+	LLString::format_map_t args;
+	LLString minSpecs;
 		
-		// get cpu data from xml
-		std::stringstream minCPUString(LLAlertDialog::getTemplateMessage("UnsupportedCPUAmount"));
-		S32 minCPU = 0;
-		minCPUString >> minCPU;
-
-		// get RAM data from XML
-		std::stringstream minRAMString(LLAlertDialog::getTemplateMessage("UnsupportedRAMAmount"));
-		U64 minRAM = 0;
-		minRAMString >> minRAM;
-		minRAM = minRAM * 1024 * 1024;
-
-		if(!LLFeatureManager::getInstance()->isGPUSupported())
-		{
-			minSpecs += LLAlertDialog::getTemplateMessage("UnsupportedGPU");
-			minSpecs += "\n";
-			unsupported = true;
-		}
-		if(gSysCPU.getMhz() < minCPU)
-		{
-			minSpecs += LLAlertDialog::getTemplateMessage("UnsupportedCPU");
-			minSpecs += "\n";
-			unsupported = true;
-		}
-		if(gSysMemory.getPhysicalMemoryClamped() < minRAM)
-		{
-			minSpecs += LLAlertDialog::getTemplateMessage("UnsupportedRAM");
-			minSpecs += "\n";
-			unsupported = true;
-		}
+	// get cpu data from xml
+	std::stringstream minCPUString(LLAlertDialog::getTemplateMessage("UnsupportedCPUAmount"));
+	S32 minCPU = 0;
+	minCPUString >> minCPU;
+
+	// get RAM data from XML
+	std::stringstream minRAMString(LLAlertDialog::getTemplateMessage("UnsupportedRAMAmount"));
+	U64 minRAM = 0;
+	minRAMString >> minRAM;
+	minRAM = minRAM * 1024 * 1024;
+
+	if(!LLFeatureManager::getInstance()->isGPUSupported() && LLFeatureManager::getInstance()->getGPUClass() != GPU_CLASS_UNKNOWN)
+	{
+		minSpecs += LLAlertDialog::getTemplateMessage("UnsupportedGPU");
+		minSpecs += "\n";
+		unsupported = true;
+	}
+	if(gSysCPU.getMhz() < minCPU)
+	{
+		minSpecs += LLAlertDialog::getTemplateMessage("UnsupportedCPU");
+		minSpecs += "\n";
+		unsupported = true;
+	}
+	if(gSysMemory.getPhysicalMemoryClamped() < minRAM)
+	{
+		minSpecs += LLAlertDialog::getTemplateMessage("UnsupportedRAM");
+		minSpecs += "\n";
+		unsupported = true;
+	}
 
-		if(unsupported)
+	if (LLFeatureManager::getInstance()->getGPUClass() == GPU_CLASS_UNKNOWN)
+	{
+		gViewerWindow->alertXml("UnknownGPU");
+	} 
+		
+	if(unsupported)
+	{
+		if(!gSavedSettings.controlExists("WarnUnsupportedHardware") 
+			|| gSavedSettings.getBOOL("WarnUnsupportedHardware"))
 		{
 			args["MINSPECS"] = minSpecs;
 			gViewerWindow->alertXml("UnsupportedHardware", args );
-			
-			// turn off flag
-			gSavedSettings.setBOOL("AlertedUnsupportedHardware", TRUE);
 		}
+
 	}
 	
 	// Save the current version to the prefs file
@@ -1452,10 +1449,13 @@ void LLAppViewer::loadSettingsFromDirectory(ELLPath path_index)
 
 		LLString full_settings_path = gDirUtilp->getExpandedFilename(path_index, settings_file);
 
-		if(settings_name == sGlobalSettingsName)
+		if(settings_name == sGlobalSettingsName 
+			&& path_index == LL_PATH_USER_SETTINGS)
 		{
 			// The non-persistent setting, ClientSettingsFile, specifies a 
 			// custom name to use for the global settings file.
+			// Only apply this setting if this method is setting the 'Global' 
+			// settings from the user_settings path.
 			std::string custom_path;
 			if(gSettings[sGlobalSettingsName]->controlExists("ClientSettingsFile"))
 			{
diff --git a/indra/newview/llcylinder.cpp b/indra/newview/llcylinder.cpp
index 58a80c21e4757dc869bb130cd88023821e422810..82db7788d648f4ff036cbd5393811a2b3fa5007f 100644
--- a/indra/newview/llcylinder.cpp
+++ b/indra/newview/llcylinder.cpp
@@ -255,7 +255,6 @@ void LLCone::render(S32 level_of_detail)
 	// center object at 0
 	glTranslatef(0.f, 0.f, - height / 2.0f);
 
-	LLVertexBuffer::unbind();
 	drawSide(level_of_detail);
 	drawBottom(level_of_detail);
 
diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp
index 198c235a1e0b1b76f1532e98ef920745c606f891..06536660e2abae0cf243fc5210ed29ffeffc706c 100644
--- a/indra/newview/lldrawable.cpp
+++ b/indra/newview/lldrawable.cpp
@@ -1188,10 +1188,11 @@ void LLSpatialBridge::setVisible(LLCamera& camera_in, std::vector<LLDrawable*>*
 	LLVector3 center = (mExtents[0] + mExtents[1]) * 0.5f;
 	LLVector3 size = (mExtents[1]-mExtents[0]) * 0.5f;
 
-	if (camera_in.AABBInFrustumNoFarClip(center, size) && 
-		AABBSphereIntersect(mExtents[0], mExtents[1], camera_in.getOrigin(), camera_in.mFrustumCornerDist))
+	if (LLPipeline::sImpostorRender ||
+		(camera_in.AABBInFrustumNoFarClip(center, size) && 
+		AABBSphereIntersect(mExtents[0], mExtents[1], camera_in.getOrigin(), camera_in.mFrustumCornerDist)))
 	{
-		if (LLPipeline::calcPixelArea(center, size, camera_in) < FORCE_INVISIBLE_AREA)
+		if (!LLPipeline::sImpostorRender && LLPipeline::calcPixelArea(center, size, camera_in) < FORCE_INVISIBLE_AREA)
 		{
 			return;
 		}
diff --git a/indra/newview/lldrawpool.cpp b/indra/newview/lldrawpool.cpp
index c987f3e03597cef821a123e96fbd1dad47a77cc5..6cd2152a287d81acdba5d86906839664c68cc5d6 100644
--- a/indra/newview/lldrawpool.cpp
+++ b/indra/newview/lldrawpool.cpp
@@ -115,7 +115,6 @@ LLDrawPool::LLDrawPool(const U32 type)
 	sNumDrawPools++;
 	mId = sNumDrawPools;
 	mVertexShaderLevel = 0;
-	mIndicesDrawn = 0;
 }
 
 LLDrawPool::~LLDrawPool()
@@ -136,24 +135,6 @@ void LLDrawPool::beginRenderPass( S32 pass )
 //virtual
 void LLDrawPool::endRenderPass( S32 pass )
 {
-	glDisableClientState ( GL_TEXTURE_COORD_ARRAY );
-	glDisableClientState ( GL_COLOR_ARRAY );
-	glDisableClientState ( GL_NORMAL_ARRAY );
-}
-
-U32 LLDrawPool::getTrianglesDrawn() const
-{
-	return mIndicesDrawn / 3;
-}
-
-void LLDrawPool::resetTrianglesDrawn()
-{
-	mIndicesDrawn = 0;
-}
-
-void LLDrawPool::addIndicesDrawn(const U32 indices)
-{
-	mIndicesDrawn += indices;
 }
 
 //=============================
@@ -224,7 +205,7 @@ void LLFacePool::drawLoop()
 {
 	if (!mDrawFace.empty())
 	{
-		mIndicesDrawn += drawLoop(mDrawFace);
+		drawLoop(mDrawFace);
 	}
 }
 
@@ -382,10 +363,6 @@ void LLRenderPass::renderTexture(U32 type, U32 mask)
 
 void LLRenderPass::pushBatches(U32 type, U32 mask, BOOL texture)
 {
-#if !LL_RELEASE_FOR_DOWNLOAD
-	LLGLState::checkClientArrays(mask);
-#endif
-
 	for (LLCullResult::drawinfo_list_t::iterator i = gPipeline.beginRenderMap(type); i != gPipeline.endRenderMap(type); ++i)	
 	{
 		LLDrawInfo* pparams = *i;
@@ -436,9 +413,7 @@ void LLRenderPass::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture)
 	if (params.mVertexBuffer.notNull())
 	{
 		params.mVertexBuffer->setBuffer(mask);
-		U16* indices_pointer = (U16*) params.mVertexBuffer->getIndicesPointer();
-		glDrawRangeElements(GL_TRIANGLES, params.mStart, params.mEnd, params.mCount,
-							GL_UNSIGNED_SHORT, indices_pointer+params.mOffset);
+		params.mVertexBuffer->drawRange(LLVertexBuffer::TRIANGLES, params.mStart, params.mEnd, params.mCount, params.mOffset);
 		gPipeline.addTrianglesDrawn(params.mCount/3);
 	}
 
diff --git a/indra/newview/lldrawpool.h b/indra/newview/lldrawpool.h
index 30a16a24ba63a54cfec5c3d999b1dae42d72e5ab..3bd1f686d162dc99b5f908f22986da204251a27d 100644
--- a/indra/newview/lldrawpool.h
+++ b/indra/newview/lldrawpool.h
@@ -90,15 +90,10 @@ class LLDrawPool
 	virtual BOOL isFacePool() { return FALSE; }
 	virtual void resetDrawOrders() = 0;
 
-	U32	getTrianglesDrawn() const;
-	void resetTrianglesDrawn();
-	void addIndicesDrawn(const U32 indices);
-
 protected:
 	S32 mVertexShaderLevel;
 	S32	mId;
 	U32 mType;				// Type of draw pool
-	S32	mIndicesDrawn;
 };
 
 class LLRenderPass : public LLDrawPool
diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp
index d22c4592786d41643df925efc18fb412b91785ee..795f6bc39657ee3c026bf8c2b994525b00967ee5 100644
--- a/indra/newview/lldrawpoolalpha.cpp
+++ b/indra/newview/lldrawpoolalpha.cpp
@@ -77,9 +77,6 @@ void LLDrawPoolAlpha::prerender()
 void LLDrawPoolAlpha::beginRenderPass(S32 pass)
 {
 	LLFastTimer t(LLFastTimer::FTM_RENDER_ALPHA);
-	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
-	glEnableClientState(GL_NORMAL_ARRAY);
-	glEnableClientState(GL_COLOR_ARRAY);
 	
 	if (LLPipeline::sUnderWaterRender)
 	{
@@ -128,8 +125,6 @@ void LLDrawPoolAlpha::render(S32 pass)
 		{
 			glUseProgramObjectARB(0);
 		}
-		glDisableClientState(GL_NORMAL_ARRAY);
-		glDisableClientState(GL_COLOR_ARRAY);
 		gPipeline.enableLightsFullbright(LLColor4(1,1,1,1));
 		glColor4f(1,0,0,1);
 		LLViewerImage::sSmokeImagep->addTextureStats(1024.f*1024.f);
@@ -141,10 +136,6 @@ void LLDrawPoolAlpha::render(S32 pass)
 
 void LLDrawPoolAlpha::renderAlpha(U32 mask)
 {
-#if !LL_RELEASE_FOR_DOWNLOAD
-	LLGLState::checkClientArrays(mask);
-#endif
-	
 	for (LLCullResult::sg_list_t::iterator i = gPipeline.beginAlphaGroups(); i != gPipeline.endAlphaGroups(); ++i)
 	{
 		LLSpatialGroup* group = *i;
@@ -182,9 +173,7 @@ void LLDrawPoolAlpha::renderAlphaHighlight(U32 mask)
 				LLRenderPass::applyModelMatrix(params);
 
 				params.mVertexBuffer->setBuffer(mask);
-				U16* indices_pointer = (U16*) params.mVertexBuffer->getIndicesPointer();
-				glDrawRangeElements(GL_TRIANGLES, params.mStart, params.mEnd, params.mCount,
-									GL_UNSIGNED_SHORT, indices_pointer+params.mOffset);
+				params.mVertexBuffer->drawRange(LLVertexBuffer::TRIANGLES, params.mStart, params.mEnd, params.mCount, params.mOffset);
 				gPipeline.addTrianglesDrawn(params.mCount/3);
 			}
 		}
@@ -303,9 +292,7 @@ void LLDrawPoolAlpha::renderGroupAlpha(LLSpatialGroup* group, U32 type, U32 mask
 		}
 
 		params.mVertexBuffer->setBuffer(mask);
-		U16* indices_pointer = (U16*) params.mVertexBuffer->getIndicesPointer();
-		glDrawRangeElements(GL_TRIANGLES, params.mStart, params.mEnd, params.mCount,
-							GL_UNSIGNED_SHORT, indices_pointer+params.mOffset);
+		params.mVertexBuffer->drawRange(LLVertexBuffer::TRIANGLES, params.mStart, params.mEnd, params.mCount, params.mOffset);
 		gPipeline.addTrianglesDrawn(params.mCount/3);
 
 		if (params.mTextureMatrix && texture && params.mTexture.notNull())
diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp
index 6db67fb269ae0f41e584b28bc62478e4999902de..99bb2049b5a580b38042c6b5439ad9b33e48fc9d 100644
--- a/indra/newview/lldrawpoolavatar.cpp
+++ b/indra/newview/lldrawpoolavatar.cpp
@@ -216,13 +216,11 @@ void LLDrawPoolAvatar::beginFootShadow()
 	}
 
 	gPipeline.enableLightsFullbright(LLColor4(1,1,1,1));
-	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
 }
 
 void LLDrawPoolAvatar::endFootShadow()
 {
 	gPipeline.enableLightsDynamic();
-	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
 }
 
 void LLDrawPoolAvatar::beginRigid()
@@ -247,16 +245,11 @@ void LLDrawPoolAvatar::beginRigid()
 	{
 		sVertexProgram = NULL;
 	}
-
-	glEnableClientState(GL_NORMAL_ARRAY);
-	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
 }
 
 void LLDrawPoolAvatar::endRigid()
 {
 	sShaderLevel = mVertexShaderLevel;
-	glDisableClientState(GL_NORMAL_ARRAY);
-	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
 	if (sVertexProgram != NULL)
 	{
 		sVertexProgram->unbind();
@@ -265,9 +258,6 @@ void LLDrawPoolAvatar::endRigid()
 
 void LLDrawPoolAvatar::beginSkinned()
 {
-	glEnableClientState(GL_NORMAL_ARRAY);
-	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
-
 	if (sShaderLevel > 0)
 	{
 		if (LLPipeline::sUnderWaterRender)
@@ -295,8 +285,7 @@ void LLDrawPoolAvatar::beginSkinned()
 	if (sShaderLevel > 0)  // for hardware blending
 	{
 		sRenderingSkinned = TRUE;
-		glClientActiveTextureARB(GL_TEXTURE1_ARB);
-
+		
 		sVertexProgram->bind();
 		if (sShaderLevel >= SHADER_LEVEL_CLOTH)
 		{
@@ -331,7 +320,6 @@ void LLDrawPoolAvatar::endSkinned()
 		sRenderingSkinned = FALSE;
 		sVertexProgram->disableTexture(LLShaderMgr::BUMP_MAP);
 		glActiveTextureARB(GL_TEXTURE0_ARB);
-		glClientActiveTextureARB(GL_TEXTURE0_ARB);
 		disable_vertex_weighting(sVertexProgram->mAttribute[LLShaderMgr::AVATAR_WEIGHT]);
 		if (sShaderLevel >= SHADER_LEVEL_BUMP)
 		{
@@ -356,10 +344,6 @@ void LLDrawPoolAvatar::endSkinned()
 	}
 
 	glActiveTextureARB(GL_TEXTURE0_ARB);
-	glClientActiveTextureARB(GL_TEXTURE0_ARB);
-
-	glDisableClientState(GL_NORMAL_ARRAY);
-	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
 }
 
 
@@ -438,7 +422,7 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
 		}
 		else if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_FOOT_SHADOWS))
 		{
-			mIndicesDrawn += avatarp->renderFootShadows();	
+			avatarp->renderFootShadows();	
 		}
 		return;
 	}
@@ -451,7 +435,7 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
 	if (pass == 1)
 	{
 		// render rigid meshes (eyeballs) first
-		mIndicesDrawn += avatarp->renderRigid();
+		avatarp->renderRigid();
 		return;
 	}
 	
@@ -548,7 +532,7 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
 			color.setColor(1.0f, 1.0f, 1.0f, 1.0f);
 		}
 
-		mIndicesDrawn += avatarp->renderSkinned(AVATAR_RENDER_PASS_SINGLE);
+		avatarp->renderSkinned(AVATAR_RENDER_PASS_SINGLE);
 	}
 }
 
@@ -609,9 +593,6 @@ void LLDrawPoolAvatar::renderForSelect()
 		return;
 	}
 
-	glEnableClientState(GL_VERTEX_ARRAY);
-	glEnableClientState(GL_NORMAL_ARRAY);
-	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
 	sVertexProgram = &gAvatarPickProgram;
 	if (sShaderLevel > 0)
 	{
@@ -624,13 +605,12 @@ void LLDrawPoolAvatar::renderForSelect()
 
 	if ((sShaderLevel > 0) && !gUseGLPick)  // for hardware blending
 	{
-		glClientActiveTextureARB(GL_TEXTURE0_ARB);
 		sRenderingSkinned = TRUE;
 		sVertexProgram->bind();
 		enable_vertex_weighting(sVertexProgram->mAttribute[LLShaderMgr::AVATAR_WEIGHT]);
 	}
 	
-	mIndicesDrawn += avatarp->renderSkinned(AVATAR_RENDER_PASS_SINGLE);
+	avatarp->renderSkinned(AVATAR_RENDER_PASS_SINGLE);
 
 	// if we're in software-blending, remember to set the fence _after_ we draw so we wait till this rendering is done
 	if ((sShaderLevel > 0) && !gUseGLPick)
@@ -645,8 +625,6 @@ void LLDrawPoolAvatar::renderForSelect()
 
 	// restore texture mode
 	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
-	glDisableClientState(GL_NORMAL_ARRAY);
-	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
 }
 
 //-----------------------------------------------------------------------------
diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp
index b35ef818030e056ef61dd24692bc7f0a6ca983b3..e5c9200cad38b97b4ba95342106096887c01392b 100644
--- a/indra/newview/lldrawpoolbump.cpp
+++ b/indra/newview/lldrawpoolbump.cpp
@@ -316,12 +316,8 @@ void LLDrawPoolBump::beginShiny(bool invisible)
 	mShiny = TRUE;
 	sVertexMask = VERTEX_MASK_SHINY;
 	// Second pass: environment map
-	glEnableClientState(GL_VERTEX_ARRAY);
-	glEnableClientState(GL_NORMAL_ARRAY);
-	glEnableClientState(GL_COLOR_ARRAY);
 	if (!invisible && mVertexShaderLevel > 1)
 	{
-		glEnableClientState(GL_TEXTURE_COORD_ARRAY);
 		sVertexMask = VERTEX_MASK_SHINY | LLVertexBuffer::MAP_TEXCOORD;
 	}
 	
@@ -456,13 +452,7 @@ void LLDrawPoolBump::endShiny(bool invisible)
 	
 	LLImageGL::unbindTexture(0, GL_TEXTURE_2D);
 	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
-	glDisableClientState(GL_NORMAL_ARRAY);
-	glDisableClientState(GL_COLOR_ARRAY);
-	if (!invisible && mVertexShaderLevel > 1)
-	{
-		glDisableClientState(GL_TEXTURE_COORD_ARRAY);
-	}
-
+	
 	diffuse_channel = -1;
 	cube_channel = 0;
 	mShiny = FALSE;
@@ -479,10 +469,6 @@ void LLDrawPoolBump::beginFullbrightShiny()
 	sVertexMask = VERTEX_MASK_SHINY | LLVertexBuffer::MAP_TEXCOORD;
 
 	// Second pass: environment map
-	glEnableClientState(GL_VERTEX_ARRAY);
-	glEnableClientState(GL_NORMAL_ARRAY);
-	glEnableClientState(GL_COLOR_ARRAY);
-	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
 	
 	if (LLPipeline::sUnderWaterRender)
 	{
@@ -564,9 +550,6 @@ void LLDrawPoolBump::endFullbrightShiny()
 	
 	LLImageGL::unbindTexture(0, GL_TEXTURE_2D);
 	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
-	glDisableClientState(GL_NORMAL_ARRAY);
-	glDisableClientState(GL_COLOR_ARRAY);
-	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
 
 	diffuse_channel = -1;
 	cube_channel = 0;
@@ -607,9 +590,7 @@ void LLDrawPoolBump::renderGroup(LLSpatialGroup* group, U32 type, U32 mask, BOOL
 		applyModelMatrix(params);
 
 		params.mVertexBuffer->setBuffer(mask);
-		U16* indices_pointer = (U16*) params.mVertexBuffer->getIndicesPointer();
-		glDrawRangeElements(GL_TRIANGLES, params.mStart, params.mEnd, params.mCount,
-							GL_UNSIGNED_SHORT, indices_pointer+params.mOffset);
+		params.mVertexBuffer->drawRange(LLVertexBuffer::TRIANGLES, params.mStart, params.mEnd, params.mCount, params.mOffset);
 		gPipeline.addTrianglesDrawn(params.mCount/3);
 	}
 }
@@ -670,8 +651,6 @@ void LLDrawPoolBump::beginBump()
 	// TEXTURE UNIT 0
 	// Output.rgb = texture at texture coord 0
 	glActiveTextureARB(GL_TEXTURE0_ARB);
-	glClientActiveTextureARB(GL_TEXTURE0_ARB);
-	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
 
 	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,	GL_COMBINE_ARB);
 	glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB,	GL_REPLACE);
@@ -686,8 +665,6 @@ void LLDrawPoolBump::beginBump()
 
 	// TEXTURE UNIT 1
 	glActiveTextureARB(GL_TEXTURE1_ARB);
-	glClientActiveTextureARB(GL_TEXTURE1_ARB);
-	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
 
 	glEnable(GL_TEXTURE_2D); // Texture unit 1
 
@@ -752,15 +729,11 @@ void LLDrawPoolBump::endBump()
 
 	// Disable texture unit 1
 	glActiveTextureARB(GL_TEXTURE1_ARB);
-	glClientActiveTextureARB(GL_TEXTURE1_ARB);
 	glDisable(GL_TEXTURE_2D); // Texture unit 1
-	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
 	glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
 
 	// Disable texture unit 0
 	glActiveTextureARB(GL_TEXTURE0_ARB);
-	glClientActiveTextureARB(GL_TEXTURE0_ARB);
-	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
 	glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
 	
 	gGL.blendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
@@ -1091,10 +1064,6 @@ void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerImage *src_vi, LLIma
 
 void LLDrawPoolBump::renderBump(U32 type, U32 mask)
 {	
-#if !LL_RELEASE_FOR_DOWNLOAD
-	LLGLState::checkClientArrays(mask);
-#endif
-
 	LLCullResult::drawinfo_list_t::iterator begin = gPipeline.beginRenderMap(type);
 	LLCullResult::drawinfo_list_t::iterator end = gPipeline.endRenderMap(type);
 
@@ -1178,11 +1147,8 @@ void LLDrawPoolBump::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture)
 	}
 	
 	params.mVertexBuffer->setBuffer(mask);
-	U16* indices_pointer = (U16*) params.mVertexBuffer->getIndicesPointer();
-	glDrawRangeElements(GL_TRIANGLES, params.mStart, params.mEnd, params.mCount,
-						GL_UNSIGNED_SHORT, indices_pointer+params.mOffset);
+	params.mVertexBuffer->drawRange(LLVertexBuffer::TRIANGLES, params.mStart, params.mEnd, params.mCount, params.mOffset);
 	gPipeline.addTrianglesDrawn(params.mCount/3);
-
 	if (params.mTextureMatrix)
 	{
 		if (mShiny)
diff --git a/indra/newview/lldrawpoolground.cpp b/indra/newview/lldrawpoolground.cpp
index d71c6de9cd4714057c666cda657da35d9aed2b4d..3500d9471f9d3f3101bc64c3ac34da61f694f4b3 100644
--- a/indra/newview/lldrawpoolground.cpp
+++ b/indra/newview/lldrawpoolground.cpp
@@ -68,9 +68,6 @@ void LLDrawPoolGround::render(S32 pass)
 		return;
 	}	
 	
-	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
-	glEnableClientState(GL_VERTEX_ARRAY);
-
 	LLGLSPipelineSkyBox gls_skybox;
 	LLImageGL::unbindTexture(0, GL_TEXTURE_2D);
 	LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
diff --git a/indra/newview/lldrawpoolsimple.cpp b/indra/newview/lldrawpoolsimple.cpp
index 174a9ac427e28b4ac5701b777f0de120fbc67f63..a2a82eada5ec63438e68f6da1927aa99748a9a78 100644
--- a/indra/newview/lldrawpoolsimple.cpp
+++ b/indra/newview/lldrawpoolsimple.cpp
@@ -65,13 +65,10 @@ void LLDrawPoolGlow::render(S32 pass)
 		gPipeline.enableLightsFullbright(LLColor4(1,1,1,1));
 	}
 
-	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
 	LLGLDepthTest depth(GL_TRUE, GL_FALSE);
 	glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
 	renderTexture(LLRenderPass::PASS_GLOW, getVertexDataMask());
-
-	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
-
+	
 	glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
 	gGL.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 	
@@ -101,10 +98,6 @@ void LLDrawPoolSimple::prerender()
 void LLDrawPoolSimple::beginRenderPass(S32 pass)
 {
 	LLFastTimer t(LLFastTimer::FTM_RENDER_SIMPLE);
-	glEnableClientState(GL_VERTEX_ARRAY);
-	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
-	glEnableClientState(GL_NORMAL_ARRAY);
-	glEnableClientState(GL_COLOR_ARRAY);
 
 	if (LLPipeline::sUnderWaterRender)
 	{
@@ -136,7 +129,6 @@ void LLDrawPoolSimple::endRenderPass(S32 pass)
 {
 	LLFastTimer t(LLFastTimer::FTM_RENDER_SIMPLE);
 	LLRenderPass::endRenderPass(pass);
-	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
 
 	if (mVertexShaderLevel > 0){
 
@@ -177,7 +169,6 @@ void LLDrawPoolSimple::render(S32 pass)
 		}
 		LLFastTimer t(LLFastTimer::FTM_RENDER_FULLBRIGHT);
 		U32 fullbright_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD | LLVertexBuffer::MAP_COLOR;
-		glDisableClientState(GL_NORMAL_ARRAY);
 		renderTexture(LLRenderPass::PASS_FULLBRIGHT, fullbright_mask);
 	}
 
diff --git a/indra/newview/lldrawpoolsky.cpp b/indra/newview/lldrawpoolsky.cpp
index d3273f2eebe14bd96c435d0aefd4c1f7a66448c2..828c9b0848930dafa6d7356dafdad6997aec9be6 100644
--- a/indra/newview/lldrawpoolsky.cpp
+++ b/indra/newview/lldrawpoolsky.cpp
@@ -113,10 +113,6 @@ void LLDrawPoolSky::render(S32 pass)
 	LLVector3 origin = LLViewerCamera::getInstance()->getOrigin();
 	glTranslatef(origin.mV[0], origin.mV[1], origin.mV[2]);
 
-	glEnableClientState(GL_VERTEX_ARRAY);
-	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
-	glDisableClientState(GL_NORMAL_ARRAY);
-
 	S32 face_count = (S32)mDrawFace.size();
 
 	for (S32 i = 0; i < llmin(6, face_count); ++i)
@@ -160,8 +156,6 @@ void LLDrawPoolSky::render(S32 pass)
 		// renderHeavenlyBody(1, hbfaces[1]);
 	}
 
-	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
-
 	glPopMatrix();
 }
 
@@ -184,8 +178,6 @@ void LLDrawPoolSky::renderSkyCubeFace(U8 side)
 		glColor4f(1, 1, 1, LLSkyTex::getInterpVal()); // lighting is disabled
 		face.renderIndexed();
 	}
-
-	mIndicesDrawn += face.getIndicesCount();
 }
 
 void LLDrawPoolSky::renderHeavenlyBody(U8 hb, LLFace* face)
@@ -198,7 +190,6 @@ void LLDrawPoolSky::renderHeavenlyBody(U8 hb, LLFace* face)
 	LLColor4 color(mHB[hb]->getInterpColor());
 	LLOverrideFaceColor override(this, color);
 	face->renderIndexed();
-	mIndicesDrawn += face->getIndicesCount();
 }
 
 
@@ -215,7 +206,6 @@ void LLDrawPoolSky::renderSunHalo(LLFace* face)
 
 	LLOverrideFaceColor override(this, color);
 	face->renderIndexed();
-	mIndicesDrawn += face->getIndicesCount();
 }
 
 
diff --git a/indra/newview/lldrawpoolterrain.cpp b/indra/newview/lldrawpoolterrain.cpp
index 634b502057727068e2953b61209ce3c9daf6f043..4747043c78bd933ee399aa500cc4b8a85762f832 100644
--- a/indra/newview/lldrawpoolterrain.cpp
+++ b/indra/newview/lldrawpoolterrain.cpp
@@ -217,14 +217,6 @@ void LLDrawPoolTerrain::render(S32 pass)
 
 void LLDrawPoolTerrain::renderFullShader()
 {
-	glEnableClientState(GL_VERTEX_ARRAY);
-	glEnableClientState(GL_NORMAL_ARRAY);
-
-	if (gPipeline.getLightingDetail() >= 2)
-	{
-		glEnableClientState(GL_COLOR_ARRAY);
-	}
-
 	// Hack! Get the region that this draw pool is rendering from!
 	LLViewerRegion *regionp = mDrawFace[0]->getDrawable()->getVObj()->getRegion();
 	LLVLComposition *compp = regionp->getComposition();
@@ -247,10 +239,8 @@ void LLDrawPoolTerrain::renderFullShader()
 	//
 	S32 detail0 = sShader->enableTexture(LLShaderMgr::TERRAIN_DETAIL0);
 	LLViewerImage::bindTexture(detail_texture0p,detail0);
-	glClientActiveTextureARB(GL_TEXTURE0_ARB);
 	glActiveTextureARB(GL_TEXTURE0_ARB);
 
-	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
 	glEnable(GL_TEXTURE_GEN_S);
 	glEnable(GL_TEXTURE_GEN_T);
 	glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
@@ -269,9 +259,7 @@ void LLDrawPoolTerrain::renderFullShader()
 	LLViewerImage::bindTexture(detail_texture1p,detail1);
 	
 	/// ALPHA TEXTURE COORDS 0:
-	glClientActiveTextureARB(GL_TEXTURE1_ARB);
 	glActiveTextureARB(GL_TEXTURE1_ARB);
-	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
 	glMatrixMode(GL_TEXTURE);
 	glLoadIdentity();
 	glMatrixMode(GL_MODELVIEW);
@@ -283,9 +271,7 @@ void LLDrawPoolTerrain::renderFullShader()
 	glEnable(GL_TEXTURE_2D);
 	
 	/// ALPHA TEXTURE COORDS 1:
-	glClientActiveTextureARB(GL_TEXTURE2_ARB);
 	glActiveTextureARB(GL_TEXTURE2_ARB);
-	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
 	glMatrixMode(GL_TEXTURE);
 	glLoadIdentity();
 	glTranslatef(-2.f, 0.f, 0.f);
@@ -298,9 +284,7 @@ void LLDrawPoolTerrain::renderFullShader()
 	LLViewerImage::bindTexture(detail_texture3p,detail3);
 	
 	/// ALPHA TEXTURE COORDS 2:
-	glClientActiveTextureARB(GL_TEXTURE3_ARB);
 	glActiveTextureARB(GL_TEXTURE3_ARB);
-	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
 	glMatrixMode(GL_TEXTURE);
 	glLoadIdentity();
 	glTranslatef(-1.f, 0.f, 0.f);
@@ -323,7 +307,6 @@ void LLDrawPoolTerrain::renderFullShader()
 	sShader->disableTexture(LLShaderMgr::TERRAIN_DETAIL3);
 
 	LLImageGL::unbindTexture(alpha_ramp, GL_TEXTURE_2D);
-	glClientActiveTextureARB(GL_TEXTURE4_ARB);
 	glActiveTextureARB(GL_TEXTURE4_ARB);	
 	glDisable(GL_TEXTURE_2D); // Texture unit 4
 	glDisable(GL_TEXTURE_GEN_S);
@@ -333,10 +316,8 @@ void LLDrawPoolTerrain::renderFullShader()
 	glMatrixMode(GL_MODELVIEW);
 
 	LLImageGL::unbindTexture(detail3, GL_TEXTURE_2D);
-	glClientActiveTextureARB(GL_TEXTURE3_ARB);
 	glActiveTextureARB(GL_TEXTURE3_ARB);
 	glDisable(GL_TEXTURE_2D);	
-	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
 	glDisable(GL_TEXTURE_GEN_S);
 	glDisable(GL_TEXTURE_GEN_T);
 	glMatrixMode(GL_TEXTURE);
@@ -344,10 +325,8 @@ void LLDrawPoolTerrain::renderFullShader()
 	glMatrixMode(GL_MODELVIEW);
 
 	LLImageGL::unbindTexture(detail2, GL_TEXTURE_2D);
-	glClientActiveTextureARB(GL_TEXTURE2_ARB);
 	glActiveTextureARB(GL_TEXTURE2_ARB);
 	glDisable(GL_TEXTURE_2D);		
-	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
 	glDisable(GL_TEXTURE_GEN_S);
 	glDisable(GL_TEXTURE_GEN_T);
 	glMatrixMode(GL_TEXTURE);
@@ -355,10 +334,8 @@ void LLDrawPoolTerrain::renderFullShader()
 	glMatrixMode(GL_MODELVIEW);
 
 	LLImageGL::unbindTexture(detail1, GL_TEXTURE_2D);
-	glClientActiveTextureARB(GL_TEXTURE1_ARB);
 	glActiveTextureARB(GL_TEXTURE1_ARB);
 	glDisable(GL_TEXTURE_2D);		
-	glDisableClientState(GL_TEXTURE_COORD_ARRAY);	
 	glDisable(GL_TEXTURE_GEN_S);
 	glDisable(GL_TEXTURE_GEN_T);
 	glMatrixMode(GL_TEXTURE);
@@ -369,7 +346,6 @@ void LLDrawPoolTerrain::renderFullShader()
 	// Restore Texture Unit 0 defaults
 	
 	LLImageGL::unbindTexture(detail0, GL_TEXTURE_2D);
-	glClientActiveTextureARB(GL_TEXTURE0_ARB);
 	glActiveTextureARB(GL_TEXTURE0_ARB);
 	glEnable(GL_TEXTURE_2D);
 	glDisable(GL_TEXTURE_GEN_S);
@@ -377,14 +353,11 @@ void LLDrawPoolTerrain::renderFullShader()
 	glMatrixMode(GL_TEXTURE);
 	glLoadIdentity();
 	glMatrixMode(GL_MODELVIEW);
-
-	// Restore non Texture Unit specific defaults
-	glDisableClientState(GL_NORMAL_ARRAY);
 }
 
 void LLDrawPoolTerrain::renderFull4TU()
 {
-	glEnableClientState(GL_VERTEX_ARRAY);
+		glEnableClientState(GL_VERTEX_ARRAY);
 	glEnableClientState(GL_NORMAL_ARRAY);
 
 	// Hack! Get the region that this draw pool is rendering from!
@@ -434,9 +407,8 @@ void LLDrawPoolTerrain::renderFull4TU()
 	//
 	// Stage 1: Generate alpha ramp for detail0/detail1 transition
 	//
-	glActiveTextureARB(GL_TEXTURE1_ARB);
 	LLViewerImage::bindTexture(m2DAlphaRampImagep,1);
-
+	glActiveTextureARB(GL_TEXTURE1_ARB);
 	glEnable(GL_TEXTURE_2D); // Texture unit 1
 	glClientActiveTextureARB(GL_TEXTURE1_ARB);
 	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
@@ -454,8 +426,8 @@ void LLDrawPoolTerrain::renderFull4TU()
 	//
 	// Stage 2: Interpolate detail1 with existing based on ramp
 	//
-	glActiveTextureARB(GL_TEXTURE2_ARB);
 	LLViewerImage::bindTexture(detail_texture1p,2);
+	glActiveTextureARB(GL_TEXTURE2_ARB);
 	glEnable(GL_TEXTURE_2D); // Texture unit 2
 	glClientActiveTextureARB(GL_TEXTURE2_ARB);
 
@@ -480,8 +452,8 @@ void LLDrawPoolTerrain::renderFull4TU()
 	//
 	// Stage 3: Modulate with primary (vertex) color for lighting
 	//
-	glActiveTextureARB(GL_TEXTURE3_ARB);
 	LLViewerImage::bindTexture(detail_texture1p,3); // bind any texture
+	glActiveTextureARB(GL_TEXTURE3_ARB);
 	glEnable(GL_TEXTURE_2D); // Texture unit 3
 	glClientActiveTextureARB(GL_TEXTURE3_ARB);
 
@@ -494,6 +466,7 @@ void LLDrawPoolTerrain::renderFull4TU()
 	glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB,		GL_PRIMARY_COLOR_ARB);
 	glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB,		GL_SRC_COLOR);
 
+	glActiveTextureARB(GL_TEXTURE0_ARB);
 	// GL_BLEND disabled by default
 	drawLoop();
 
@@ -524,9 +497,8 @@ void LLDrawPoolTerrain::renderFull4TU()
 	//
 	// Stage 1: Generate alpha ramp for detail2/detail3 transition
 	//
-	glActiveTextureARB(GL_TEXTURE1_ARB);
 	LLViewerImage::bindTexture(m2DAlphaRampImagep,1);
-
+	glActiveTextureARB(GL_TEXTURE1_ARB);
 	glEnable(GL_TEXTURE_2D); // Texture unit 1
 	glClientActiveTextureARB(GL_TEXTURE1_ARB);
 
@@ -551,8 +523,8 @@ void LLDrawPoolTerrain::renderFull4TU()
 	//
 	// Stage 2: Interpolate detail2 with existing based on ramp
 	//
-	glActiveTextureARB(GL_TEXTURE2_ARB);
 	LLViewerImage::bindTexture(detail_texture2p,2);
+	glActiveTextureARB(GL_TEXTURE2_ARB);
 	glEnable(GL_TEXTURE_2D); // Texture unit 2
 	glClientActiveTextureARB(GL_TEXTURE2_ARB);
 
@@ -578,9 +550,9 @@ void LLDrawPoolTerrain::renderFull4TU()
 	//
 	// Stage 3: Generate alpha ramp for detail1/detail2 transition
 	//
-	glActiveTextureARB(GL_TEXTURE3_ARB);
 	LLViewerImage::bindTexture(m2DAlphaRampImagep,3);
-
+	glActiveTextureARB(GL_TEXTURE3_ARB);
+	
 	glEnable(GL_TEXTURE_2D); // Texture unit 3
 	glClientActiveTextureARB(GL_TEXTURE3_ARB);
 
@@ -603,7 +575,7 @@ void LLDrawPoolTerrain::renderFull4TU()
 	glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB,		GL_TEXTURE);
 	glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB,	GL_SRC_ALPHA);
 
-
+	glActiveTextureARB(GL_TEXTURE0_ARB);
 	{
 		LLGLEnable blend(GL_BLEND);
 		drawLoop();
@@ -611,6 +583,7 @@ void LLDrawPoolTerrain::renderFull4TU()
 
 	// Disable multitexture
 	LLImageGL::unbindTexture(3, GL_TEXTURE_2D);
+	glActiveTextureARB(GL_TEXTURE3_ARB);
 	glClientActiveTextureARB(GL_TEXTURE3_ARB);
 	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
 	glDisable(GL_TEXTURE_2D); // Texture unit 3
@@ -619,6 +592,7 @@ void LLDrawPoolTerrain::renderFull4TU()
 	glMatrixMode(GL_MODELVIEW);
 
 	LLImageGL::unbindTexture(2, GL_TEXTURE_2D);
+	glActiveTextureARB(GL_TEXTURE2_ARB);
 	glClientActiveTextureARB(GL_TEXTURE2_ARB);
 	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
 	glDisable(GL_TEXTURE_2D); // Texture unit 2
@@ -629,6 +603,7 @@ void LLDrawPoolTerrain::renderFull4TU()
 	glMatrixMode(GL_MODELVIEW);
 
 	LLImageGL::unbindTexture(1, GL_TEXTURE_2D);
+	glActiveTextureARB(GL_TEXTURE1_ARB);
 	glClientActiveTextureARB(GL_TEXTURE1_ARB);
 	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
 	glDisable(GL_TEXTURE_2D); // Texture unit 1
@@ -642,6 +617,7 @@ void LLDrawPoolTerrain::renderFull4TU()
 	//----------------------------------------------------------------------------
 	// Restore Texture Unit 0 defaults
 	
+	glActiveTextureARB(GL_TEXTURE0_ARB);
 	LLImageGL::unbindTexture(0, GL_TEXTURE_2D);
 	glClientActiveTextureARB(GL_TEXTURE0_ARB);
 	glActiveTextureARB(GL_TEXTURE0_ARB);
@@ -658,9 +634,6 @@ void LLDrawPoolTerrain::renderFull4TU()
 
 void LLDrawPoolTerrain::renderFull2TU()
 {
-	glEnableClientState(GL_VERTEX_ARRAY);
-	glEnableClientState(GL_NORMAL_ARRAY);
-
 	// Hack! Get the region that this draw pool is rendering from!
 	LLViewerRegion *regionp = mDrawFace[0]->getDrawable()->getVObj()->getRegion();
 	LLVLComposition *compp = regionp->getComposition();
@@ -687,9 +660,6 @@ void LLDrawPoolTerrain::renderFull2TU()
 	// Stage 0: Render detail 0 into base
 	//
 	LLViewerImage::bindTexture(detail_texture0p,0);
-	glClientActiveTextureARB(GL_TEXTURE0_ARB);
-
-	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
 	glEnable(GL_TEXTURE_GEN_S);
 	glEnable(GL_TEXTURE_GEN_T);
 	glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
@@ -715,12 +685,10 @@ void LLDrawPoolTerrain::renderFull2TU()
 	// Stage 0: Generate alpha ramp for detail0/detail1 transition
 	//
 	LLViewerImage::bindTexture(m2DAlphaRampImagep,0);
-	glClientActiveTextureARB(GL_TEXTURE0_ARB);
-
+	
 	glDisable(GL_TEXTURE_GEN_S);
 	glDisable(GL_TEXTURE_GEN_T);
-	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
-
+	
 	// Care about alpha only
 	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,		GL_COMBINE_ARB);
 	glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB,		GL_REPLACE);
@@ -736,10 +704,8 @@ void LLDrawPoolTerrain::renderFull2TU()
 	// Stage 1: Write detail1
 	//
 	LLViewerImage::bindTexture(detail_texture1p,1); // Texture unit 1
+	glActiveTextureARB(GL_TEXTURE1_ARB);
 	glEnable(GL_TEXTURE_2D);		// Texture unit 1
-	glClientActiveTextureARB(GL_TEXTURE1_ARB);
-
-	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
 	glEnable(GL_TEXTURE_GEN_S);
 	glEnable(GL_TEXTURE_GEN_T);
 	glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
@@ -758,6 +724,7 @@ void LLDrawPoolTerrain::renderFull2TU()
 	glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB,		GL_PREVIOUS);
 	glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB,	GL_SRC_ALPHA);
 
+	glActiveTextureARB(GL_TEXTURE0_ARB);
 	{
 		LLGLEnable blend(GL_BLEND);
 		drawLoop();
@@ -769,14 +736,11 @@ void LLDrawPoolTerrain::renderFull2TU()
 	// Stage 0: Generate alpha ramp for detail1/detail2 transition
 	//
 	LLViewerImage::bindTexture(m2DAlphaRampImagep,0);
-	glClientActiveTextureARB(GL_TEXTURE0_ARB);
 	// Set the texture matrix
 	glMatrixMode(GL_TEXTURE);
 	glLoadIdentity();
 	glTranslatef(-1.f, 0.f, 0.f);
 
-	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
-
 	// Care about alpha only
 	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,		GL_COMBINE_ARB);
 	glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB,		GL_REPLACE);
@@ -793,9 +757,7 @@ void LLDrawPoolTerrain::renderFull2TU()
 	
 	LLViewerImage::bindTexture(detail_texture2p,1);
 	glEnable(GL_TEXTURE_2D); // Texture unit 1
-	glClientActiveTextureARB(GL_TEXTURE1_ARB);
-
-	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+	
 	glEnable(GL_TEXTURE_GEN_S);
 	glEnable(GL_TEXTURE_GEN_T);
 	glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
@@ -826,14 +788,11 @@ void LLDrawPoolTerrain::renderFull2TU()
 	// Stage 0: Generate alpha ramp for detail2/detail3 transition
 	//
 	LLViewerImage::bindTexture(m2DAlphaRampImagep,0);
-	glClientActiveTextureARB(GL_TEXTURE0_ARB);
 	// Set the texture matrix
 	glMatrixMode(GL_TEXTURE);
 	glLoadIdentity();
 	glTranslatef(-2.f, 0.f, 0.f);
 
-	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
-
 	// Care about alpha only
 	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,		GL_COMBINE_ARB);
 	glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB,		GL_REPLACE);
@@ -847,10 +806,8 @@ void LLDrawPoolTerrain::renderFull2TU()
 	// Stage 1: Write detail3
 
 	LLViewerImage::bindTexture(detail_texture3p,1);
+	glActiveTextureARB(GL_TEXTURE1_ARB);
 	glEnable(GL_TEXTURE_2D); // Texture unit 1
-	glClientActiveTextureARB(GL_TEXTURE1_ARB);
-
-	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
 	glEnable(GL_TEXTURE_GEN_S);
 	glEnable(GL_TEXTURE_GEN_T);
 	glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
@@ -869,6 +826,7 @@ void LLDrawPoolTerrain::renderFull2TU()
 	glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB,		GL_PREVIOUS);
 	glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB,	GL_SRC_ALPHA);
 
+	glActiveTextureARB(GL_TEXTURE0_ARB);
 	{
 		LLGLEnable blend(GL_BLEND);
 		drawLoop();
@@ -879,8 +837,7 @@ void LLDrawPoolTerrain::renderFull2TU()
 	
 	// Disable multitexture
 	LLImageGL::unbindTexture(1, GL_TEXTURE_2D);
-	glClientActiveTextureARB(GL_TEXTURE1_ARB);
-	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+	glActiveTextureARB(GL_TEXTURE1_ARB);
 	glDisable(GL_TEXTURE_2D); // Texture unit 1
 	glDisable(GL_TEXTURE_GEN_S);
 	glDisable(GL_TEXTURE_GEN_T);
@@ -891,9 +848,9 @@ void LLDrawPoolTerrain::renderFull2TU()
 	//----------------------------------------------------------------------------
 	// Restore Texture Unit 0 defaults
 	
+	glActiveTextureARB(GL_TEXTURE0_ARB);
 	LLImageGL::unbindTexture(0, GL_TEXTURE_2D);
 
-	glClientActiveTextureARB(GL_TEXTURE0_ARB);
 	glActiveTextureARB(GL_TEXTURE0_ARB);
 	glDisable(GL_TEXTURE_GEN_S);
 	glDisable(GL_TEXTURE_GEN_T);
@@ -902,16 +859,12 @@ void LLDrawPoolTerrain::renderFull2TU()
 	glMatrixMode(GL_MODELVIEW);
 
 	// Restore non Texture Unit specific defaults
-	glDisableClientState(GL_NORMAL_ARRAY);
 	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
 }
 
 
 void LLDrawPoolTerrain::renderSimple()
 {
-	glEnableClientState(GL_VERTEX_ARRAY);
-	glEnableClientState(GL_NORMAL_ARRAY);
-
 	LLVector4 tp0, tp1;
 
 	//----------------------------------------------------------------------------
@@ -923,14 +876,12 @@ void LLDrawPoolTerrain::renderSimple()
 
 	glActiveTextureARB(GL_TEXTURE0_ARB);
 	glEnable(GL_TEXTURE_2D); // Texture unit 2
-	glClientActiveTextureARB(GL_TEXTURE0_ARB);
-
+	
 	LLVector3 origin_agent = mDrawFace[0]->getDrawable()->getVObj()->getRegion()->getOriginAgent();
 	F32 tscale = 1.f/256.f;
 	tp0.setVec(tscale, 0.f, 0.0f, -1.f*(origin_agent.mV[0]/256.f));
 	tp1.setVec(0.f, tscale, 0.0f, -1.f*(origin_agent.mV[1]/256.f));
 	
-	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
 	glEnable(GL_TEXTURE_GEN_S);
 	glEnable(GL_TEXTURE_GEN_T);
 	glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
@@ -952,7 +903,6 @@ void LLDrawPoolTerrain::renderSimple()
 	// Restore Texture Unit 0 defaults
 	
 	LLImageGL::unbindTexture(0, GL_TEXTURE_2D);
-	glClientActiveTextureARB(GL_TEXTURE0_ARB);
 	glActiveTextureARB(GL_TEXTURE0_ARB);
 	glDisable(GL_TEXTURE_GEN_S);
 	glDisable(GL_TEXTURE_GEN_T);
@@ -961,7 +911,6 @@ void LLDrawPoolTerrain::renderSimple()
 	glMatrixMode(GL_MODELVIEW);
 
 	// Restore non Texture Unit specific defaults
-	glDisableClientState(GL_NORMAL_ARRAY);
 	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
 }
 
@@ -986,14 +935,8 @@ void LLDrawPoolTerrain::renderOwnership()
 	LLViewerParcelOverlay	*overlayp			= regionp->getParcelOverlay();
 	LLImageGL				*texturep			= overlayp->getTexture();
 
-	glEnableClientState(GL_VERTEX_ARRAY);
-	glDisableClientState(GL_NORMAL_ARRAY);
-
 	LLViewerImage::bindTexture(texturep);
 
-	glClientActiveTextureARB(GL_TEXTURE0_ARB);
-	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
-	
 	// *NOTE: Because the region is 256 meters wide, but has 257 pixels, the 
 	// texture coordinates for pixel 256x256 is not 1,1. This makes the
 	// ownership map not line up with the selection. We address this with
@@ -1014,9 +957,6 @@ void LLDrawPoolTerrain::renderOwnership()
 	glMatrixMode(GL_TEXTURE);
 	glPopMatrix();
 	glMatrixMode(GL_MODELVIEW);
-
-	// Restore non Texture Unit specific defaults
-	glDisableClientState(GL_NORMAL_ARRAY);
 }
 
 
diff --git a/indra/newview/lldrawpooltree.cpp b/indra/newview/lldrawpooltree.cpp
index f70904eba4785f2db39c7022dadffee0fef2bff8..eabc0f1268db3337daa021fc077f011355b6c406 100644
--- a/indra/newview/lldrawpooltree.cpp
+++ b/indra/newview/lldrawpooltree.cpp
@@ -67,9 +67,6 @@ void LLDrawPoolTree::prerender()
 void LLDrawPoolTree::beginRenderPass(S32 pass)
 {
 	LLFastTimer t(LLFastTimer::FTM_RENDER_TREES);
-	glEnableClientState(GL_VERTEX_ARRAY);
-	glEnableClientState(GL_NORMAL_ARRAY);
-	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
 	glAlphaFunc(GL_GREATER, 0.5f);
 	
 	if (LLPipeline::sUnderWaterRender)
@@ -110,9 +107,7 @@ void LLDrawPoolTree::endRenderPass(S32 pass)
 {
 	LLFastTimer t(LLFastTimer::FTM_RENDER_TREES);
 	glAlphaFunc(GL_GREATER, 0.01f);
-	glDisableClientState(GL_NORMAL_ARRAY);
-	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
-
+	
 	if (gPipeline.canUseWindLightShadersOnObjects())
 	{
 		shader->unbind();
@@ -126,9 +121,6 @@ void LLDrawPoolTree::renderForSelect()
 		return;
 	}
 
-	glEnableClientState (GL_VERTEX_ARRAY);
-	glEnableClientState (GL_TEXTURE_COORD_ARRAY);
-	
 	LLOverrideFaceColor color(this, 1.f, 1.f, 1.f, 1.f);
 
 	LLGLSObjectSelectAlpha gls_alpha;
@@ -155,7 +147,6 @@ void LLDrawPoolTree::renderForSelect()
 	gGL.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 
 	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
-	glDisableClientState (GL_TEXTURE_COORD_ARRAY);
 }
 
 void LLDrawPoolTree::renderTree(BOOL selecting)
@@ -278,8 +269,6 @@ void LLDrawPoolTree::renderTree(BOOL selecting)
 			//glPopMatrix();
 		}
 	}
-
-	addIndicesDrawn(indices_drawn);
 }
 
 BOOL LLDrawPoolTree::verify() const
diff --git a/indra/newview/lldrawpoolwater.cpp b/indra/newview/lldrawpoolwater.cpp
index f4e22a57f6857bf0f61ae47da0a33fd3dc16b00a..9ffa552895f507a6d8111ada3cb7a4fb7dda3b14 100644
--- a/indra/newview/lldrawpoolwater.cpp
+++ b/indra/newview/lldrawpoolwater.cpp
@@ -163,17 +163,11 @@ void LLDrawPoolWater::render(S32 pass)
 
 	LLGLDisable cullFace(GL_CULL_FACE);
 	
-	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
-	glEnableClientState(GL_VERTEX_ARRAY);
-	glEnableClientState(GL_NORMAL_ARRAY);
-	
 	// Set up second pass first
-	glActiveTextureARB(GL_TEXTURE1_ARB);
 	mWaterImagep->addTextureStats(1024.f*1024.f);
 	mWaterImagep->bind(1);
-
-	glClientActiveTextureARB(GL_TEXTURE1_ARB);
-	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+	glActiveTextureARB(GL_TEXTURE1_ARB);
+	
 	glEnable(GL_TEXTURE_2D); // Texture unit 1
 
 	LLVector3 camera_up = LLViewerCamera::getInstance()->getUpAxis();
@@ -215,7 +209,6 @@ void LLDrawPoolWater::render(S32 pass)
 	glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB,		GL_PREVIOUS_ARB);
 	glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB,	GL_SRC_ALPHA);
 
-	glClientActiveTextureARB(GL_TEXTURE0_ARB);
 	glActiveTextureARB(GL_TEXTURE0_ARB);
 	
 	glClearStencil(1);
@@ -234,11 +227,9 @@ void LLDrawPoolWater::render(S32 pass)
 		}
 		face->bindTexture();
 		face->renderIndexed();
-		mIndicesDrawn += face->getIndicesCount();
 	}
 
 	// Now, disable texture coord generation on texture state 1
-	glClientActiveTextureARB(GL_TEXTURE1_ARB);
 	glActiveTextureARB(GL_TEXTURE1_ARB);
 	glDisable(GL_TEXTURE_2D); // Texture unit 1
 	glDisable(GL_TEXTURE_GEN_S); //texture unit 1
@@ -246,11 +237,9 @@ void LLDrawPoolWater::render(S32 pass)
 	LLImageGL::unbindTexture(1, GL_TEXTURE_2D);
 
 	// Disable texture coordinate and color arrays
-	glClientActiveTextureARB(GL_TEXTURE0_ARB);
 	glActiveTextureARB(GL_TEXTURE0_ARB);
 	LLImageGL::unbindTexture(0, GL_TEXTURE_2D);
 
-	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
 	stop_glerror();
 	
 	if (gSky.mVOSkyp->getCubeMap())
@@ -284,7 +273,6 @@ void LLDrawPoolWater::render(S32 pass)
 			if (face->getGeomCount() > 0)
 			{					
 				face->renderIndexed();
-				mIndicesDrawn += face->getIndicesCount();
 			}
 		}
 
@@ -310,9 +298,6 @@ void LLDrawPoolWater::render(S32 pass)
 		renderReflection(refl_face);
 	}
 
-	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
-	glDisableClientState(GL_NORMAL_ARRAY);
-	
 	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
 }
 
@@ -338,16 +323,10 @@ void LLDrawPoolWater::renderReflection(LLFace* face)
 
 	LLGLSNoFog noFog;
 
-	glEnableClientState(GL_VERTEX_ARRAY);
-	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
-
 	LLViewerImage::bindTexture(mHBTex[dr]);
 
 	LLOverrideFaceColor override(this, face->getFaceColor().mV);
 	face->renderIndexed();
-	mIndicesDrawn += face->getIndicesCount();
-
-	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
 }
 
 void LLDrawPoolWater::shade()
@@ -361,10 +340,6 @@ void LLDrawPoolWater::shade()
 		return;
 	}
 
-	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
-	glEnableClientState(GL_VERTEX_ARRAY);
-	glEnableClientState(GL_NORMAL_ARRAY);
-	
 	LLGLDisable blend(GL_BLEND);
 
 	LLColor3 light_diffuse(0,0,0);
@@ -562,8 +537,6 @@ void LLDrawPoolWater::shade()
 					face->renderIndexed();
 				}
 			}
-						
-			mIndicesDrawn += face->getIndicesCount();
 		}
 	}
 	
@@ -576,8 +549,6 @@ void LLDrawPoolWater::shade()
 	shader->unbind();
 
 	glActiveTextureARB(GL_TEXTURE0_ARB);
-	glClientActiveTextureARB(GL_TEXTURE0_ARB);
-	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
 	glEnable(GL_TEXTURE_2D);
 	glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_FALSE);
 
diff --git a/indra/newview/lldrawpoolwlsky.cpp b/indra/newview/lldrawpoolwlsky.cpp
index 63d13d61d924d92f024470a7209cebd891016fe3..e2d0c6088ada3b922c546d1ce3051a59f6a40f91 100644
--- a/indra/newview/lldrawpoolwlsky.cpp
+++ b/indra/newview/lldrawpoolwlsky.cpp
@@ -159,9 +159,7 @@ void LLDrawPoolWLSky::renderStars(void) const
 	// combiners blending below requires something to be bound
 	// and we might as well only bind once.
 	//LLGLEnable gl_texture_2d(GL_TEXTURE_2D);
-	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
-	glDisableClientState(GL_NORMAL_ARRAY);
-
+	
 	gPipeline.disableLights();
 
 	if (!LLPipeline::sReflectionRender)
@@ -224,9 +222,6 @@ void LLDrawPoolWLSky::renderSkyClouds(F32 camHeightLocal) const
 
 void LLDrawPoolWLSky::renderHeavenlyBodies()
 {
-	glEnableClientState(GL_VERTEX_ARRAY);
-	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
-	glDisableClientState(GL_NORMAL_ARRAY);
 	LLGLSPipelineSkyBox gls_skybox;
 	LLGLEnable blend_on(GL_BLEND);
 	gPipeline.disableLights();
@@ -240,7 +235,6 @@ void LLDrawPoolWLSky::renderHeavenlyBodies()
 		LLColor4 color(gSky.mVOSkyp->getSun().getInterpColor());
 		LLFacePool::LLOverrideFaceColor color_override(this, color);
 		face->renderIndexed();
-		mIndicesDrawn += face->getIndicesCount();
 	}
 #endif
 
@@ -264,10 +258,7 @@ void LLDrawPoolWLSky::renderHeavenlyBodies()
 		
 		LLFacePool::LLOverrideFaceColor color_override(this, color);
 		face->renderIndexed();
-		mIndicesDrawn += face->getIndicesCount();
 	}
-
-	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
 }
 
 void LLDrawPoolWLSky::render(S32 pass)
diff --git a/indra/newview/lldynamictexture.cpp b/indra/newview/lldynamictexture.cpp
index 24ee701ff2b3ffc2473bc9587ede36b297e7d367..cdb7531341a03aaa69ccf3025b539b0456f9103e 100644
--- a/indra/newview/lldynamictexture.cpp
+++ b/indra/newview/lldynamictexture.cpp
@@ -223,17 +223,15 @@ BOOL LLDynamicTexture::updateAllInstances()
 				glClear(GL_DEPTH_BUFFER_BIT);
 				gDisplaySwapBuffers = FALSE;
 				
-				LLVertexBuffer::startRender();
-				gGL.start();
-								
 				dynamicTexture->preRender();	// Must be called outside of startRender()
 
+				LLVertexBuffer::startRender();
+								
 				if (dynamicTexture->render())
 				{
 					result = TRUE;
 					sNumRenders++;
 				}
-				gGL.stop();
 				LLVertexBuffer::stopRender();
 		
 				dynamicTexture->postRender(result);
diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp
index 2157b50eb50c63ba8e6460703b6417c46c2d5168..5a683c4c2e5effcc878c60fe630e93482af9226d 100644
--- a/indra/newview/llface.cpp
+++ b/indra/newview/llface.cpp
@@ -263,8 +263,14 @@ void LLFace::setDrawable(LLDrawable *drawable)
 
 void LLFace::setSize(const S32 num_vertices, const S32 num_indices)
 {
-	mGeomCount    = num_vertices;
-	mIndicesCount = num_indices;
+	if (mGeomCount != num_vertices ||
+		mIndicesCount != num_indices)
+	{
+		mGeomCount    = num_vertices;
+		mIndicesCount = num_indices;
+		mVertexBuffer = NULL;
+		mLastVertexBuffer = NULL;
+	}
 }
 
 //============================================================================
@@ -368,8 +374,6 @@ void LLFace::renderForSelect(U32 data_mask)
 #if !LL_RELEASE_FOR_DOWNLOAD
 		LLGLState::checkClientArrays(data_mask);
 #endif
-		U16* indicesp = (U16*) mVertexBuffer->getIndicesPointer() + mIndicesIndex;
-
 		if (gPickFaces && mTEOffset != -1)
 		{
 			// mask off high 4 bits (16 total possible faces)
@@ -386,40 +390,26 @@ void LLFace::renderForSelect(U32 data_mask)
 				{
 					glPushMatrix();
 					glMultMatrixf((float*) mDrawablep->getRegion()->mRenderMatrix.mMatrix);
-					glDrawElements(GL_TRIANGLES, mIndicesCount, GL_UNSIGNED_SHORT, indicesp); 
+					mVertexBuffer->draw(LLVertexBuffer::TRIANGLES, mIndicesCount, mIndicesIndex);
 					glPopMatrix();
 				}
 				else
 				{
-					glDrawElements(GL_TRIANGLES, mIndicesCount, GL_UNSIGNED_SHORT, indicesp); 
+					mVertexBuffer->draw(LLVertexBuffer::TRIANGLES, mIndicesCount, mIndicesIndex);
 				}
 			}
 			else
 			{
 				glPushMatrix();
 				glMultMatrixf((float*)getRenderMatrix().mMatrix);
-				glDrawElements(GL_TRIANGLES, mIndicesCount, GL_UNSIGNED_SHORT, indicesp); 
-				glPopMatrix();
-			}
-		}
-		else if (mGeomCount > 0)
-		{
-			if (isState(GLOBAL))
-			{
-				glDrawArrays(GL_TRIANGLES, mGeomIndex, mGeomCount); 
-			}
-			else
-			{
-				glPushMatrix();
-				glMultMatrixf((float*)getRenderMatrix().mMatrix);
-				glDrawArrays(GL_TRIANGLES, mGeomIndex, mGeomCount); 
+				mVertexBuffer->draw(LLVertexBuffer::TRIANGLES, mIndicesCount, mIndicesIndex);
 				glPopMatrix();
 			}
 		}
 	}
 }
 
-void LLFace::renderSelected(LLImageGL *imagep, const LLColor4& color, const S32 offset, const S32 count)
+void LLFace::renderSelected(LLImageGL *imagep, const LLColor4& color)
 {
 	if(mDrawablep.isNull() || mVertexBuffer.isNull())
 	{
@@ -443,27 +433,12 @@ void LLFace::renderSelected(LLImageGL *imagep, const LLColor4& color, const S32
 			glMultMatrixf((GLfloat*)mDrawablep->getRegion()->mRenderMatrix.mMatrix);
 		}
 
-		glEnableClientState(GL_TEXTURE_COORD_ARRAY);
-		glEnableClientState(GL_VERTEX_ARRAY);
-		glEnableClientState(GL_NORMAL_ARRAY);
-
 		mVertexBuffer->setBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD);
 #if !LL_RELEASE_FOR_DOWNLOAD
 		LLGLState::checkClientArrays(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD);
 #endif
-		U16* indicesp = ((U16*) mVertexBuffer->getIndicesPointer()) + mIndicesIndex;
-
-		if (count)
-		{
-			glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_SHORT, indicesp + offset); 
-		}
-		else
-		{
-			glDrawElements(GL_TRIANGLES, mIndicesCount, GL_UNSIGNED_SHORT, indicesp); 
-		}
-		glDisableClientState(GL_TEXTURE_COORD_ARRAY);
-		glDisableClientState(GL_NORMAL_ARRAY);
-		
+		mVertexBuffer->draw(LLVertexBuffer::TRIANGLES, mIndicesCount, mIndicesIndex);
+				
 		glPopMatrix();
 	}
 }
@@ -542,8 +517,6 @@ void LLFace::renderSelectedUV(const S32 offset, const S32 count)
 			}
 			else
 			{
-				glEnableClientState(GL_TEXTURE_COORD_ARRAY);
-				glEnableClientState(GL_VERTEX_ARRAY);
 				llassert(mGeomIndex >= 0);
 				if (count)
 				{
@@ -568,7 +541,6 @@ void LLFace::renderSelectedUV(const S32 offset, const S32 count)
 						glDrawArrays(GL_TRIANGLES, mGeomIndex, mGeomCount); 
 					}
 				}
-				glDisableClientState(GL_TEXTURE_COORD_ARRAY);
 			}
 
 			glDisable(GL_POLYGON_OFFSET_FILL);
@@ -1251,16 +1223,7 @@ S32 LLFace::pushVertices(const U16* index_array) const
 {
 	if (mIndicesCount)
 	{
-		if (mGeomCount <= gGLManager.mGLMaxVertexRange && 
-			mIndicesCount <= (U32) gGLManager.mGLMaxIndexRange)
-		{
-			glDrawRangeElements(GL_TRIANGLES, mGeomIndex, mGeomIndex + mGeomCount-1, mIndicesCount, 
-									GL_UNSIGNED_SHORT, index_array + mIndicesIndex); 
-		}
-		else
-		{
-			glDrawElements(GL_TRIANGLES, mIndicesCount, GL_UNSIGNED_SHORT, index_array+mIndicesIndex);
-		}
+		mVertexBuffer->drawRange(LLVertexBuffer::TRIANGLES, mGeomIndex, mGeomIndex+mGeomCount-1, mIndicesCount, mIndicesIndex);
 		gPipeline.addTrianglesDrawn(mIndicesCount/3);
 	}
 
diff --git a/indra/newview/llface.h b/indra/newview/llface.h
index 6142ba6672d9a19b8636c062680f2359063d1159..070283ecd2692037e9158befb77b8d95a98d288e 100644
--- a/indra/newview/llface.h
+++ b/indra/newview/llface.h
@@ -167,7 +167,7 @@ class LLFace
 	void		renderSelectedUV(const S32 offset = 0, const S32 count = 0);
 
 	void		renderForSelect(U32 data_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD);
-	void		renderSelected(LLImageGL *image, const LLColor4 &color, const S32 offset = 0, const S32 count = 0);
+	void		renderSelected(LLImageGL *image, const LLColor4 &color);
 
 	F32			getKey()					const	{ return mDistance; }
 
diff --git a/indra/newview/llflexibleobject.cpp b/indra/newview/llflexibleobject.cpp
index c18dc069a47c74fe438822e969e34911900e60cc..248e680c1b70f2e06dd8fac5ead4e0e2ffc5a0bb 100644
--- a/indra/newview/llflexibleobject.cpp
+++ b/indra/newview/llflexibleobject.cpp
@@ -195,7 +195,7 @@ void LLVolumeImplFlexible::remapSections(LLFlexibleObjectSection *source, S32 so
 
 
 //-----------------------------------------------------------------------------
-void LLVolumeImplFlexible::setAttributesOfAllSections()
+void LLVolumeImplFlexible::setAttributesOfAllSections(LLVector3* inScale)
 {
 	LLVector2 bottom_scale, top_scale;
 	F32 begin_rot = 0, end_rot = 0;
@@ -215,8 +215,16 @@ void LLVolumeImplFlexible::setAttributesOfAllSections()
 	
 	S32 num_sections = 1 << mSimulateRes;
 
-	LLVector3 scale = mVO->mDrawable->getScale();
-									
+	LLVector3 scale;
+	if (inScale == (LLVector3*)NULL)
+	{
+		scale = mVO->mDrawable->getScale();
+	}
+	else
+	{
+		scale = *inScale;
+	}
+
 	mSection[0].mPosition = getAnchorPosition();
 	mSection[0].mDirection = LLVector3::z_axis * getFrameRotation();
 	mSection[0].mdPosition = mSection[0].mDirection;
@@ -297,7 +305,7 @@ BOOL LLVolumeImplFlexible::doIdleUpdate(LLAgent &agent, LLWorld &world, const F6
 		new_res = mRenderRes;
 	}
 
-	if (!mInitialized || (mSimulateRes != new_res))
+	if (!mInitialized)
 	{
 		mSimulateRes = new_res;
 		setAttributesOfAllSections();
@@ -644,7 +652,7 @@ void LLVolumeImplFlexible::doFlexibleRebuild()
 
 void LLVolumeImplFlexible::onSetScale(const LLVector3& scale, BOOL damped)
 {
-	setAttributesOfAllSections();
+	setAttributesOfAllSections((LLVector3*) &scale);
 }
 
 BOOL LLVolumeImplFlexible::doUpdateGeometry(LLDrawable *drawable)
diff --git a/indra/newview/llflexibleobject.h b/indra/newview/llflexibleobject.h
index d4b79fb536b2b14ab3812cc4a5c30f5edcb24112..f711d0a57d1ea50071af08a2656b394437a43c2e 100644
--- a/indra/newview/llflexibleobject.h
+++ b/indra/newview/llflexibleobject.h
@@ -138,7 +138,7 @@ class LLVolumeImplFlexible : public LLVolumeInterface
 		//--------------------------------------
 		// private methods
 		//--------------------------------------
-		void setAttributesOfAllSections	();
+		void setAttributesOfAllSections	(LLVector3* inScale = NULL);
 
 		void remapSections(LLFlexibleObjectSection *source, S32 source_sections,
 										 LLFlexibleObjectSection *dest, S32 dest_sections);
diff --git a/indra/newview/llfloateranimpreview.cpp b/indra/newview/llfloateranimpreview.cpp
index afa3fcddbe3a4102688d3983786f1c39a4cc3541..aba92791e057d15e1262e87c50c63ea3933d10ec 100644
--- a/indra/newview/llfloateranimpreview.cpp
+++ b/indra/newview/llfloateranimpreview.cpp
@@ -293,7 +293,6 @@ BOOL LLFloaterAnimPreview::postBuild()
 			mAnimPreview = NULL;
 			mMotionID.setNull();
 			childSetValue("bad_animation_text", getString("failed_to_initialize"));
-			setEnabled(FALSE);
 		}
 	}
 	else
@@ -1039,6 +1038,8 @@ BOOL	LLPreviewAnimation::render()
 {
 	mNeedsUpdate = FALSE;
 	LLVOAvatar* avatarp = mDummyAvatar;
+
+	gGL.start();
 	
 	glMatrixMode(GL_PROJECTION);
 	gGL.pushMatrix();
@@ -1109,7 +1110,6 @@ BOOL	LLPreviewAnimation::render()
 		avatarPoolp->renderAvatars(avatarp);  // renders only one avatar
 	}
 
-	gGL.start();
 	return TRUE;
 }
 
diff --git a/indra/newview/llfloaterauction.cpp b/indra/newview/llfloaterauction.cpp
index 25b275c8cb03e7184419accea3bc16f8461163ed..2e971a8324c1a70ffb24b83f48ac3bd78fdc56f3 100644
--- a/indra/newview/llfloaterauction.cpp
+++ b/indra/newview/llfloaterauction.cpp
@@ -53,6 +53,7 @@
 #include "llviewerdisplay.h"
 #include "llviewercontrol.h"
 #include "llui.h"
+#include "llglimmediate.h"
 
 ///----------------------------------------------------------------------------
 /// Local function declarations, constants, enums, and typedefs
@@ -153,7 +154,7 @@ void LLFloaterAuction::draw()
 			}
 			{
 				LLGLSUIDefault gls_ui;
-				glColor3f(1.f, 1.f, 1.f);
+				gGL.color3f(1.f, 1.f, 1.f);
 				gl_draw_scaled_image(rect.mLeft,
 									 rect.mBottom,
 									 rect.getWidth(),
diff --git a/indra/newview/llfloaterhud.cpp b/indra/newview/llfloaterhud.cpp
index 7f311be9fd9503749685d102f1eee5a87d9047e6..12b1f0b4f1c6ab9306fa959aef09bc22f883e29a 100644
--- a/indra/newview/llfloaterhud.cpp
+++ b/indra/newview/llfloaterhud.cpp
@@ -29,16 +29,20 @@ LLFloaterHUD::LLFloaterHUD()
 :	LLFloater("floater_hud"),
 	mWebBrowser(0)
 {
+	// Create floater from its XML definition
+	LLUICtrlFactory::getInstance()->buildFloater(this, "floater_hud.xml");
+	
 	// Don't grab the focus as it will impede performing in-world actions
 	// while using the HUD
-	setAutoFocus(FALSE);
+	setIsChrome(TRUE);
+
+	// Chrome doesn't show the window title by default, but here we
+	// want to show it.
+	setTitleVisible(true);
 	
 	// Opaque background since we never get the focus
 	setBackgroundOpaque(TRUE);
 
-	// Create floater from its XML definition
-	LLUICtrlFactory::getInstance()->buildFloater(this, "floater_hud.xml");
-	
 	// Position floater based on saved location
 	LLRect saved_position_rect = gSavedSettings.getRect("FloaterHUDRect");
 	reshape(saved_position_rect.getWidth(), saved_position_rect.getHeight(), FALSE);
@@ -47,12 +51,14 @@ LLFloaterHUD::LLFloaterHUD()
 	mWebBrowser = getChild<LLWebBrowserCtrl>("floater_hud_browser" );
 	if (mWebBrowser)
 	{
-		// Always refresh the browser
-		mWebBrowser->setAlwaysRefresh(true);
-
 		// Open links in internal browser
 		mWebBrowser->setOpenInExternalBrowser(false);
 
+		// This is a "chrome" floater, so we don't want anything to
+		// take focus (as the user needs to be able to walk with 
+		// arrow keys during tutorial).
+		mWebBrowser->setTakeFocusOnClick(false);
+
 		LLString language(gSavedSettings.getString("Language"));
 		if(language == "default")
 		{
@@ -110,9 +116,3 @@ void LLFloaterHUD::close()
 {
 	if (sInstance) sInstance->close();
 }
-
-void LLFloaterHUD::onFocusReceived()
-{
-	// Never get the focus
-	setFocus(FALSE);
-}
diff --git a/indra/newview/llfloaterhud.h b/indra/newview/llfloaterhud.h
index 9c1140986e68458a01d690b3eea1e0ca781b1443..06da9fb44ef4e41a70adb513c73e51af0335bceb 100644
--- a/indra/newview/llfloaterhud.h
+++ b/indra/newview/llfloaterhud.h
@@ -36,7 +36,7 @@ class LLFloaterHUD : public LLFloater
 	LLWebBrowserCtrl* mWebBrowser; ///< the actual web browser control
 
 	LLFloaterHUD(); ///< default constructor
-	virtual void onFocusReceived(); ///< called when we get the focus
+
 private:
 	static LLFloaterHUD* sInstance;
 };
diff --git a/indra/newview/llfloaterimagepreview.cpp b/indra/newview/llfloaterimagepreview.cpp
index 51e67dcf2b481abae227f8d3b34555ee2db68672..67f9ebe6b414dfe1f73d542404f8cc267f596d60 100644
--- a/indra/newview/llfloaterimagepreview.cpp
+++ b/indra/newview/llfloaterimagepreview.cpp
@@ -667,6 +667,8 @@ void LLImagePreviewAvatar::setPreviewTarget(const char* joint_name, const char*
 //-----------------------------------------------------------------------------
 BOOL LLImagePreviewAvatar::render()
 {
+	gGL.start();
+	
 	mNeedsUpdate = FALSE;
 	LLVOAvatar* avatarp = mDummyAvatar;
 
@@ -723,8 +725,6 @@ BOOL LLImagePreviewAvatar::render()
 		avatarPoolp->renderAvatars(avatarp);  // renders only one avatar
 	}
 
-	gGL.start();
-
 	return TRUE;
 }
 
@@ -823,6 +823,8 @@ void LLImagePreviewSculpted::setPreviewTarget(LLImageRaw* imagep, F32 distance)
 //-----------------------------------------------------------------------------
 BOOL LLImagePreviewSculpted::render()
 {
+	gGL.start();
+	
 	mNeedsUpdate = FALSE;
 
 	LLGLSUIDefault def;
@@ -917,6 +919,8 @@ BOOL LLImagePreviewSculpted::render()
 		delete [] normals;
 	}
 
+	gGL.stop();
+	
 	return TRUE;
 }
 
diff --git a/indra/newview/llglsandbox.cpp b/indra/newview/llglsandbox.cpp
index 493b69f99e15a0edab392d2da1954f91fdec00df..f6d9ee97615ab008a88be625b477d2fd625c57df 100644
--- a/indra/newview/llglsandbox.cpp
+++ b/indra/newview/llglsandbox.cpp
@@ -1006,17 +1006,17 @@ void LLViewerObjectList::renderObjectBeacons()
 		return;
 	}
 
-	S32 i;
 	//const LLFontGL *font = LLResMgr::getInstance()->getRes(LLFONT_SANSSERIF);
 
 	LLGLSUIDefault gls_ui;
 
-	S32 last_line_width = -1;
-	
 	{
 		LLGLSNoTexture gls_ui_no_texture;
-		gGL.begin(GL_LINES);
-		for (i = 0; i < mDebugBeacons.count(); i++)
+
+		S32 last_line_width = -1;
+		// gGL.begin(GL_LINES); // Always happens in (line_width != last_line_width)
+		
+		for (S32 i = 0; i < mDebugBeacons.count(); i++)
 		{
 			const LLDebugBeacon &debug_beacon = mDebugBeacons[i];
 			LLColor4 color = debug_beacon.mColor;
@@ -1024,8 +1024,11 @@ void LLViewerObjectList::renderObjectBeacons()
 			S32 line_width = debug_beacon.mLineWidth;
 			if (line_width != last_line_width)
 			{
-				gGL.end();
-				gGL.flush();
+				if (i > 0)
+				{
+					gGL.end();
+					gGL.flush();
+				}
 				glLineWidth( (F32)line_width );
 				last_line_width = line_width;
 				gGL.begin(GL_LINES);
@@ -1049,17 +1052,21 @@ void LLViewerObjectList::renderObjectBeacons()
 		LLGLSNoTexture gls_ui_no_texture;
 		LLGLDepthTest gls_depth(GL_TRUE);
 		
-		gGL.begin(GL_LINES);
-		last_line_width = -1;
-		for (i = 0; i < mDebugBeacons.count(); i++)
+		S32 last_line_width = -1;
+		// gGL.begin(GL_LINES); // Always happens in (line_width != last_line_width)
+		
+		for (S32 i = 0; i < mDebugBeacons.count(); i++)
 		{
 			const LLDebugBeacon &debug_beacon = mDebugBeacons[i];
 
 			S32 line_width = debug_beacon.mLineWidth;
 			if (line_width != last_line_width)
 			{
-				gGL.end();
-				gGL.flush();
+				if (i > 0)
+				{
+					gGL.end();
+					gGL.flush();
+				}
 				glLineWidth( (F32)line_width );
 				last_line_width = line_width;
 				gGL.begin(GL_LINES);
@@ -1076,12 +1083,12 @@ void LLViewerObjectList::renderObjectBeacons()
 
 			draw_line_cube(0.10f, thisline);
 		}
+		
 		gGL.end();
-	
 		gGL.flush();
 		glLineWidth(1.f);
 
-		for (i = 0; i < mDebugBeacons.count(); i++)
+		for (S32 i = 0; i < mDebugBeacons.count(); i++)
 		{
 			LLDebugBeacon &debug_beacon = mDebugBeacons[i];
 			if (debug_beacon.mString == "")
diff --git a/indra/newview/llimpanel.cpp b/indra/newview/llimpanel.cpp
index 7eac7eb5987b06830aca2f91913e710476f75116..35cf36bd07b68a659d4820cb2917d9e303f51941 100644
--- a/indra/newview/llimpanel.cpp
+++ b/indra/newview/llimpanel.cpp
@@ -1061,7 +1061,7 @@ LLFloaterIMPanel::LLFloaterIMPanel(
 	mSessionUUID(session_id),
 	mVoiceChannel(NULL),
 	mSessionInitialized(FALSE),
-
+	mSessionStartMsgPos(0),
 	mOtherParticipantUUID(other_participant_id),
 	mDialog(dialog),
 	mTyping(FALSE),
@@ -1090,6 +1090,7 @@ LLFloaterIMPanel::LLFloaterIMPanel(
 	mSessionUUID(session_id),
 	mVoiceChannel(NULL),
 	mSessionInitialized(FALSE),
+	mSessionStartMsgPos(0),
 	mOtherParticipantUUID(other_participant_id),
 	mDialog(dialog),
 	mTyping(FALSE),
@@ -1182,6 +1183,7 @@ void LLFloaterIMPanel::init(const LLString& session_label)
 			//we don't need to need to wait for any responses
 			//so we're already initialized
 			mSessionInitialized = TRUE;
+			mSessionStartMsgPos = 0;
 		}
 		else
 		{
diff --git a/indra/newview/llmemoryview.cpp b/indra/newview/llmemoryview.cpp
index 4b4b0a36dc18471ef37338ae5b5f6a142e2e472a..e124af1427e65d62bf9010c43773846663c9243f 100644
--- a/indra/newview/llmemoryview.cpp
+++ b/indra/newview/llmemoryview.cpp
@@ -121,6 +121,8 @@ static const struct mtv_display_info mtv_display_table[] =
 	{ LLMemType::MTYPE_VERTEX_DATA,		"Vertex Buffer",	&LLColor4::blue3 },
 	{ LLMemType::MTYPE_AVATAR,			"Avatar",			&LLColor4::purple1 },
 	{ LLMemType::MTYPE_REGIONS,			"Regions",			&LLColor4::blue1 },
+	{ LLMemType::MTYPE_VOLUME,			"Volume",			&LLColor4::pink1 },
+	{ LLMemType::MTYPE_PRIMITIVE,		"Profile",			&LLColor4::pink2 },
  	{ LLMemType::MTYPE_TEMP1,			"Temp1",			&LLColor4::red1 },
  	{ LLMemType::MTYPE_TEMP2,			"Temp2",			&LLColor4::magenta1 },
  	{ LLMemType::MTYPE_TEMP3,			"Temp3",			&LLColor4::red2 },
diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp
index b6805f42fa5a184f6bdd80afc1fa0ac81100a636..a94fcf7bc265534b0cb417b5e97b34ce1997abb2 100644
--- a/indra/newview/llpanellogin.cpp
+++ b/indra/newview/llpanellogin.cpp
@@ -951,6 +951,7 @@ void LLPanelLogin::loadLoginPage()
 	{
 		LLAppViewer::instance()->resetURIs();
 		gGridChoice = (EGridInfo)grid_index;
+		gSavedSettings.setString("GridChoice", gGridInfo[gGridChoice].mLabel);
 		gViewerWindow->setMenuBackgroundColor(false, 
 			!LLAppViewer::instance()->isInProductionGrid());
 		gLoginMenuBarView->setBackgroundColor(gMenuBarView->getBackgroundColor());
diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp
index 331505166e7d658b76ac483a8fba298e8cf2179b..59fa2c4bcc88058dcdc043956558438e74406383 100644
--- a/indra/newview/llspatialpartition.cpp
+++ b/indra/newview/llspatialpartition.cpp
@@ -1906,9 +1906,8 @@ void pushVerts(LLDrawInfo* params, U32 mask)
 {
 	LLRenderPass::applyModelMatrix(*params);
 	params->mVertexBuffer->setBuffer(mask);
-	U16* indicesp = (U16*) params->mVertexBuffer->getIndicesPointer();
-	glDrawRangeElements(params->mParticle ? GL_POINTS : GL_TRIANGLES, params->mStart, params->mEnd, params->mCount,
-					GL_UNSIGNED_SHORT, indicesp+params->mOffset);
+	params->mVertexBuffer->drawRange(params->mParticle ? LLVertexBuffer::POINTS : LLVertexBuffer::TRIANGLES,
+								params->mStart, params->mEnd, params->mCount, params->mOffset);
 }
 
 void pushVerts(LLSpatialGroup* group, U32 mask)
@@ -1932,13 +1931,11 @@ void pushVerts(LLFace* face, U32 mask)
 	if (buffer)
 	{
 		buffer->setBuffer(mask);
-		U16* indicesp = (U16*) buffer->getIndicesPointer();
 		U16 start = face->getGeomStart();
 		U16 end = start + face->getGeomCount()-1;
 		U32 count = face->getIndicesCount();
 		U16 offset = face->getIndicesStart();
-
-		glDrawRangeElements(GL_TRIANGLES, start, end, count, GL_UNSIGNED_SHORT, indicesp + offset);
+		buffer->drawRange(LLVertexBuffer::TRIANGLES, start, end, count, offset);
 	}
 
 }
@@ -1948,9 +1945,7 @@ void pushBufferVerts(LLVertexBuffer* buffer, U32 mask)
 	if (buffer)
 	{
 		buffer->setBuffer(mask);
-		U16* indicesp = (U16*) buffer->getIndicesPointer();
-		glDrawRangeElements(GL_TRIANGLES, 0, buffer->getRequestedVerts(), buffer->getRequestedIndices(),
-							GL_UNSIGNED_SHORT, indicesp);
+		buffer->drawRange(LLVertexBuffer::TRIANGLES, 0, buffer->getRequestedVerts()-1, buffer->getRequestedIndices(), 0);
 	}
 }
 
@@ -1999,9 +1994,8 @@ void pushVertsColorCoded(LLSpatialGroup* group, U32 mask)
 			LLRenderPass::applyModelMatrix(*params);
 			glColor4f(colors[col].mV[0], colors[col].mV[1], colors[col].mV[2], 0.5f);
 			params->mVertexBuffer->setBuffer(mask);
-			U16* indicesp = (U16*) params->mVertexBuffer->getIndicesPointer();
-			glDrawRangeElements(params->mParticle ? GL_POINTS : GL_TRIANGLES, params->mStart, params->mEnd, params->mCount,
-							GL_UNSIGNED_SHORT, indicesp+params->mOffset);
+			params->mVertexBuffer->drawRange(params->mParticle ? LLVertexBuffer::POINTS : LLVertexBuffer::TRIANGLES,
+				params->mStart, params->mEnd, params->mCount, params->mOffset);
 			col = (col+1)%col_count;
 		}
 	}
@@ -2070,8 +2064,7 @@ void renderOctree(LLSpatialGroup* group)
 						face->mVertexBuffer->setBuffer(LLVertexBuffer::MAP_VERTEX);
 						//drawBox((face->mExtents[0] + face->mExtents[1])*0.5f,
 						//		(face->mExtents[1]-face->mExtents[0])*0.5f);
-						glDrawElements(GL_TRIANGLES, face->getIndicesCount(), GL_UNSIGNED_SHORT, 
-							((U16*) face->mVertexBuffer->getIndicesPointer())+face->getIndicesStart());
+						face->mVertexBuffer->draw(LLVertexBuffer::TRIANGLES, face->getIndicesCount(), face->getIndicesStart());
 					}
 				}
 
diff --git a/indra/newview/lltexlayer.cpp b/indra/newview/lltexlayer.cpp
index 7a2d232de61d8c5d9d44af819b578e2d7f610976..f8931cb18b3d2f22c0b27e1c5fa0322b6773e996 100644
--- a/indra/newview/lltexlayer.cpp
+++ b/indra/newview/lltexlayer.cpp
@@ -244,6 +244,8 @@ BOOL LLTexLayerSetBuffer::render()
 	BOOL upload_now = (gAgent.mNumPendingQueries == 0 && mNeedsUpload && mTexLayerSet->isLocalTextureDataFinal());
 	BOOL success = TRUE;
 
+	gGL.start();
+	
 	// Composite bump
 	if( mBumpTexName )
 	{
@@ -295,6 +297,8 @@ BOOL LLTexLayerSetBuffer::render()
 	glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
 	gGL.blendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );  
 
+	gGL.stop();
+	
 	// we have valid texture data now
 	mInitialized = TRUE;
 	mNeedsUpdate = FALSE;
diff --git a/indra/newview/lltoolmorph.cpp b/indra/newview/lltoolmorph.cpp
index 265d1082d16982a4606a933336b46150e28f71d6..85ea2046458c2ee57b7398b753fc4c3d59a3b845 100644
--- a/indra/newview/lltoolmorph.cpp
+++ b/indra/newview/lltoolmorph.cpp
@@ -163,6 +163,8 @@ void LLVisualParamHint::preRender(BOOL clear_depth)
 //-----------------------------------------------------------------------------
 BOOL LLVisualParamHint::render()
 {
+	gGL.start();
+	
 	LLVisualParamReset::sDirty = TRUE;
 	LLVOAvatar* avatarp = gAgent.getAvatarObject();
 
@@ -223,6 +225,7 @@ BOOL LLVisualParamHint::render()
 	LLVector3 camera_pos = target_joint_pos + (camera_snapshot_offset * avatar_rotation);
 	
 	gGL.stop();
+	
 	LLViewerCamera::getInstance()->setAspect((F32)mWidth / (F32)mHeight);
 	LLViewerCamera::getInstance()->setOriginAndLookAt(
 		camera_pos,		// camera
@@ -238,7 +241,7 @@ BOOL LLVisualParamHint::render()
 		avatarPoolp->renderAvatars(avatarp);  // renders only one avatar
 	}
 	avatarp->setVisualParamWeight(mVisualParam, mLastParamWeight);
-	gGL.start();
+
 	return TRUE;
 }
 
diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp
index 3d0daa73a20b0c84554bfaaa6a04f95629a61c82..583139298ffcd7a11e51e859bbad496a7dc67249 100644
--- a/indra/newview/llviewerdisplay.cpp
+++ b/indra/newview/llviewerdisplay.cpp
@@ -886,6 +886,11 @@ void render_ui_and_swap()
 	LLGLState::checkStates();
 #endif
 	
+	glPushMatrix();
+	glLoadMatrixd(gGLLastModelView);
+	glh::matrix4f saved_view = glh_get_current_modelview();
+	glh_set_current_modelview(glh_copy_matrix(gGLLastModelView));
+	
 	{
 		BOOL to_texture = gPipeline.canUseVertexShaders() &&
 							LLPipeline::sRenderGlow &&
@@ -936,6 +941,9 @@ void render_ui_and_swap()
 
 		LLVertexBuffer::stopRender();
 	}
+
+	glh_set_current_modelview(saved_view);
+	glPopMatrix();
 }
 
 void render_ui_and_swap_if_needed()
@@ -1030,11 +1038,6 @@ void render_ui_3d()
 	//		 so 3d elements requiring Z buffer are moved to LLDrawPoolHUD
 	//
 
-	// Render selections
-	//glDisableClientState(GL_COLOR_ARRAY);
-	//glDisableClientState(GL_TEXTURE_COORD_ARRAY);
-	//glDisableClientState(GL_NORMAL_ARRAY);
-
 	/////////////////////////////////////////////////////////////
 	//
 	// Render 2.5D elements (2D elements in the world)
diff --git a/indra/newview/llviewerjointmesh.cpp b/indra/newview/llviewerjointmesh.cpp
index fe00c25c638eb5bc8d8d577cbf84cc5fbf73487c..ce23efe2f01bec5f0e6aa952b777e3abe3e3762d 100644
--- a/indra/newview/llviewerjointmesh.cpp
+++ b/indra/newview/llviewerjointmesh.cpp
@@ -501,21 +501,6 @@ int compare_int(const void *a, const void *b)
 	else return 0;
 }
 
-void llDrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices)
-{
-	if (end-start+1 > (U32) gGLManager.mGLMaxVertexRange ||
-		count > gGLManager.mGLMaxIndexRange)
-	{
-		glDrawElements(mode,count,type,indices);
-	}
-	else
-	{
-		glDrawRangeElements(mode,start,end,count,type,indices);
-	}
-
-	gPipeline.addTrianglesDrawn(count/3);
-}
-
 //--------------------------------------------------------------------
 // LLViewerJointMesh::drawShape()
 //--------------------------------------------------------------------
@@ -626,7 +611,7 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass)
 	U32 start = mMesh->mFaceVertexOffset;
 	U32 end = start + mMesh->mFaceVertexCount - 1;
 	U32 count = mMesh->mFaceIndexCount;
-	U16* indicesp = ((U16*) mFace->mVertexBuffer->getIndicesPointer()) + mMesh->mFaceIndexOffset;
+	U32 offset = mMesh->mFaceIndexOffset;
 
 	if (mMesh->hasWeights())
 	{
@@ -636,23 +621,21 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass)
 			{
 				uploadJointMatrices();
 			}
-			llDrawRangeElements(GL_TRIANGLES, start, end, count, GL_UNSIGNED_SHORT, indicesp);
-		}
-		else
-		{
-			llDrawRangeElements(GL_TRIANGLES, start, end, count, GL_UNSIGNED_SHORT, indicesp);
 		}
+		
+		mFace->mVertexBuffer->drawRange(LLVertexBuffer::TRIANGLES, start, end, count, offset);
 	}
 	else
 	{
 		glPushMatrix();
 		LLMatrix4 jointToWorld = getWorldMatrix();
 		glMultMatrixf((GLfloat*)jointToWorld.mMatrix);
-		llDrawRangeElements(GL_TRIANGLES, start, end, count, GL_UNSIGNED_SHORT, indicesp);
+		mFace->mVertexBuffer->drawRange(LLVertexBuffer::TRIANGLES, start, end, count, offset);
 		glPopMatrix();
 	}
+	gPipeline.addTrianglesDrawn(count/3);
 
-	triangle_count += mMesh->mFaceIndexCount;
+	triangle_count += count;
 	
 	if (mTestImageName)
 	{
diff --git a/indra/newview/llviewerkeyboard.cpp b/indra/newview/llviewerkeyboard.cpp
index bea4b910b6b29ac6babf956c016e376f19081295..e21c14637b961a9dce3d879834052da499e0a57a 100644
--- a/indra/newview/llviewerkeyboard.cpp
+++ b/indra/newview/llviewerkeyboard.cpp
@@ -88,8 +88,6 @@ static void agent_handle_doubletap_run(EKeystate s, LLAgent::EDoubleTapRunMode m
 {
 	if (KEYSTATE_UP == s)
 	{
-		// Releasing a walk-key resets the double-tap timer
-		gAgent.mDoubleTapRunTimer.reset();
 		if (gAgent.mDoubleTapRunMode == mode &&
 		    gAgent.getRunning() &&
 		    !gAgent.getAlwaysRun())
@@ -98,17 +96,23 @@ static void agent_handle_doubletap_run(EKeystate s, LLAgent::EDoubleTapRunMode m
 			gAgent.clearRunning();
 			gAgent.sendWalkRun(gAgent.getRunning());
 		}
-		gAgent.mDoubleTapRunMode = mode;
 	}
 	else if (gAllowTapTapHoldRun &&
 		 KEYSTATE_DOWN == s &&
-		 gAgent.mDoubleTapRunMode == mode &&
-		 gAgent.mDoubleTapRunTimer.getElapsedTimeF32() < NUDGE_TIME)
+		 !gAgent.getRunning())
 	{
-		// Same walk-key was pushed again quickly; this is a double-tap
-		// so engage temporary running.
-		gAgent.setRunning();
-		gAgent.sendWalkRun(gAgent.getRunning());
+		if (gAgent.mDoubleTapRunMode == mode &&
+		    gAgent.mDoubleTapRunTimer.getElapsedTimeF32() < NUDGE_TIME)
+		{
+			// Same walk-key was pushed again quickly; this is a
+			// double-tap so engage temporary running.
+			gAgent.setRunning();
+			gAgent.sendWalkRun(gAgent.getRunning());
+		}
+
+		// Pressing any walk-key resets the double-tap timer
+		gAgent.mDoubleTapRunTimer.reset();
+		gAgent.mDoubleTapRunMode = mode;
 	}
 }
 
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index cfcd446b5598941027f1bd8a57f6a3fb9143b090..2cb60785d3ed830ad69134bf0eedfe7195fc9c9f 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -4897,12 +4897,12 @@ BOOL menu_check_build_tool( void* user_data )
 void handle_reload_settings(void*)
 {
 	gSavedSettings.resetToDefaults();
-	gSavedSettings.loadFromFile(gSavedSettings.getString("ClientSettingsFile"), TRUE);
+	gSavedSettings.loadFromFile(gSavedSettings.getString("ClientSettingsFile"));
 
 	llinfos << "Loading colors from colors.xml" << llendl;
 	std::string color_file = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,"colors.xml");
 	gColors.resetToDefaults();
-	gColors.loadFromFile(color_file, FALSE, TYPE_COL4U);
+	gColors.loadFromFileLegacy(color_file, FALSE, TYPE_COL4U);
 }
 
 class LLWorldSetHomeLocation : public view_listener_t
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index 99f1af61e5e8ce4c9c8bf90e77091bc9693ecf15..8afb0879a37a5138c8566e52535ca56c50d97354 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -5063,7 +5063,7 @@ void callback_load_url(S32 option, void* data)
 
 	if (0 == option)
 	{
-		LLWeb::loadURL(infop->mUrl);
+		LLWeb::loadURLExternal(infop->mUrl);
 	}
 
 	delete infop;
diff --git a/indra/newview/llvotree.cpp b/indra/newview/llvotree.cpp
index 16555fdc9a268ac26ff4da953697785b8d15b94e..5f83dd4b06f8385a4af92ef4bccc86f2a5ae3eb5 100644
--- a/indra/newview/llvotree.cpp
+++ b/indra/newview/llvotree.cpp
@@ -821,7 +821,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);
 				stop_glerror();
 				ret += sLODIndexCount[trunk_LOD];
 			}
@@ -871,7 +871,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);							
 				stop_glerror();
 				ret += LEAF_INDICES;
 			}
@@ -896,7 +896,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);
 		stop_glerror();
 		ret += LEAF_INDICES;
 
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index e7dbf0bfb81302cbeb1d8a186a3f5da0328b630a..a440ae2957b0a73a36ad24ce29537e7c8eca22da 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -762,16 +762,30 @@ void LLVOVolume::sculpt()
 			return;
 		
 		LLPointer<LLImageRaw> raw_image = new LLImageRaw();
-		mSculptTexture->readBackRaw(discard_level, raw_image, FALSE);
+		BOOL is_valid = mSculptTexture->readBackRaw(discard_level, raw_image, FALSE);
 
 		sculpt_height = raw_image->getHeight();
 		sculpt_width = raw_image->getWidth();
+		sculpt_components = raw_image->getComponents();		
 
-		sculpt_components = raw_image->getComponents();
-		sculpt_data = raw_image->getData();
-
-		llassert_always(raw_image->getDataSize() >= sculpt_height * sculpt_width * sculpt_components);
-
+		if(is_valid)
+		{
+			is_valid = mSculptTexture->isValidForSculpt(discard_level, sculpt_width, sculpt_height, sculpt_components) ;
+		}
+		if(!is_valid)
+		{
+			sculpt_width = 0;
+			sculpt_height = 0;
+			sculpt_data = NULL ;
+		}
+		else
+		{
+			if (raw_image->getDataSize() < sculpt_height * sculpt_width * sculpt_components)
+				llerrs << "Sculpt: image data size = " << raw_image->getDataSize()
+					   << " < " << sculpt_height << " x " << sculpt_width << " x " <<sculpt_components << llendl;
+					   
+			sculpt_data = raw_image->getData();
+		}
 		getVolume()->sculpt(sculpt_width, sculpt_height, sculpt_components, sculpt_data, discard_level);
 	}
 }
diff --git a/indra/newview/llvowlsky.cpp b/indra/newview/llvowlsky.cpp
index ca9f328e482dda578da1cc676a1e4ecca53e496a..18c03d870f17068b7f3267daf6083a34e662a925 100644
--- a/indra/newview/llvowlsky.cpp
+++ b/indra/newview/llvowlsky.cpp
@@ -484,17 +484,12 @@ BOOL LLVOWLSky::updateGeometry(LLDrawable * drawable)
 
 void LLVOWLSky::drawStars(void)
 {
-	glEnableClientState(GL_COLOR_ARRAY);
-	
 	//  render the stars as a sphere centered at viewer camera 
 	if (mStarsVerts.notNull())
 	{
 		mStarsVerts->setBuffer(LLDrawPoolWLSky::STAR_VERTEX_DATA_MASK);
-		U16* indicesp = (U16*) mStarsVerts->getIndicesPointer();
-		glDrawElements(GL_POINTS, getStarsNumIndices(), GL_UNSIGNED_SHORT, indicesp);
+		mStarsVerts->draw(LLVertexBuffer::POINTS, getStarsNumIndices(), 0);
 	}
-
-	glDisableClientState(GL_COLOR_ARRAY);
 }
 
 void LLVOWLSky::drawDome(void)
@@ -507,19 +502,8 @@ void LLVOWLSky::drawDome(void)
 	LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
 
 	const U32 data_mask = LLDrawPoolWLSky::SKY_VERTEX_DATA_MASK;
-
-	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
-
+	
 #if DOME_SLICES
-	//mFanVerts->setBuffer(data_mask);
-	//glDrawRangeElements(
-	//	GL_TRIANGLES,
-	//	0, getFanNumVerts()-1, getFanNumIndices(),
-	//	GL_UNSIGNED_SHORT,
-	//	mFanVerts->getIndicesPointer());
-
-	//gPipeline.addTrianglesDrawn(getFanNumIndices()/3);
-
 	std::vector< LLPointer<LLVertexBuffer> >::const_iterator strips_vbo_iter, end_strips;
 	end_strips = mStripsVerts.end();
 	for(strips_vbo_iter = mStripsVerts.begin(); strips_vbo_iter != end_strips; ++strips_vbo_iter)
@@ -528,13 +512,10 @@ void LLVOWLSky::drawDome(void)
 
 		strips_segment->setBuffer(data_mask);
 
-		glDrawRangeElements(
-			//GL_TRIANGLES,
-			GL_TRIANGLE_STRIP,
-			0, strips_segment->getRequestedVerts()-1, strips_segment->getRequestedIndices(),
-			GL_UNSIGNED_SHORT,
-			strips_segment->getIndicesPointer());
-		
+		strips_segment->drawRange(
+			LLVertexBuffer::TRIANGLE_STRIP, 
+			0, strips_segment->getRequestedVerts()-1, strips_segment->getRequestedIndices(), 
+			0);
 		gPipeline.addTrianglesDrawn(strips_segment->getRequestedIndices() - 2);
 	}
 
@@ -547,8 +528,6 @@ void LLVOWLSky::drawDome(void)
 		mStripsVerts->getIndicesPointer());
 #endif
 
-	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
-
 	LLVertexBuffer::unbind();
 }
 
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index 4e679d28d5d4f174283f8e0c4a75d68c92801008..69f2a4c4b7ae8060c35b632a26047764fddedaf6 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -168,7 +168,7 @@ glh::matrix4f glh_get_current_projection()
 	return glh_copy_matrix(gGLProjection);
 }
 
-void glh_copy_matrix(glh::matrix4f& src, GLdouble* dst)
+void glh_copy_matrix(const glh::matrix4f& src, GLdouble* dst)
 {
 	for (U32 i = 0; i < 16; i++)
 	{
@@ -176,7 +176,7 @@ void glh_copy_matrix(glh::matrix4f& src, GLdouble* dst)
 	}
 }
 
-void glh_set_current_modelview(glh::matrix4f& mat)
+void glh_set_current_modelview(const glh::matrix4f& mat)
 {
 	glh_copy_matrix(mat, gGLModelView);
 }
@@ -2144,9 +2144,9 @@ void render_hud_elements()
 		LLViewerParcelMgr::getInstance()->renderParcelCollision();
 	
 		// Render debugging beacons.
-		gObjectList.renderObjectBeacons();
-		LLHUDObject::renderAll();
-		gObjectList.resetObjectBeacons();
+		//gObjectList.renderObjectBeacons();
+		//LLHUDObject::renderAll();
+		//gObjectList.resetObjectBeacons();
 	}
 	else if (gForceRenderLandFence)
 	{
@@ -2253,11 +2253,11 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate)
 	//
 	//
 
-	glEnableClientState(GL_VERTEX_ARRAY);
-
 	stop_glerror();
 	gFrameStats.start(LLFrameStats::RENDER_SYNC);
 
+	glEnableClientState(GL_VERTEX_ARRAY);
+
 	// Do verification of GL state
 #ifndef LL_RELEASE_FOR_DOWNLOAD
 	LLGLState::checkStates();
@@ -2377,10 +2377,10 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate)
 							break;
 						}
 						
-						p->resetTrianglesDrawn();
 						p->render(i);
 					}
 					poolp->endRenderPass(i);
+					LLVertexBuffer::unbind();
 #ifndef LL_RELEASE_FOR_DOWNLOAD
 #	if LL_DEBUG_GL
 					GLint depth;
@@ -2413,6 +2413,7 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate)
 		}
 	}
 
+	LLVertexBuffer::unbind();
 #ifndef LL_RELEASE_FOR_DOWNLOAD
 	LLGLState::checkStates();
 	LLGLState::checkTextureChannels();
@@ -2452,6 +2453,15 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate)
 	LLVertexBuffer::stopRender();
 	LLVertexBuffer::unbind();
 	
+	if (!LLPipeline::sReflectionRender && gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
+	{
+		gGL.start();
+		// Render debugging beacons.
+		gObjectList.renderObjectBeacons();
+		LLHUDObject::renderAll();
+		gObjectList.resetObjectBeacons();
+		gGL.stop();
+	}
 
 	//HACK: preserve/restore matrices around HUD render
 	if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD))
@@ -2472,15 +2482,9 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate)
 
 void LLPipeline::renderGeomDeferred()
 {
-	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
-	glEnableClientState(GL_NORMAL_ARRAY);
-	glEnableClientState(GL_COLOR_ARRAY);
 	gDeferredDiffuseProgram.bind();
 	gPipeline.renderObjects(LLRenderPass::PASS_SIMPLE, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD | LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_NORMAL, TRUE);
 	gDeferredDiffuseProgram.unbind();
-	glDisableClientState(GL_COLOR_ARRAY);
-	glDisableClientState(GL_NORMAL_ARRAY);
-	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
 }
 
 void LLPipeline::addTrianglesDrawn(S32 count)
@@ -2506,11 +2510,6 @@ void LLPipeline::renderDebug()
 
 	gGL.start();
 
-	// Disable all client state
-    //glDisableClientState(GL_TEXTURE_COORD_ARRAY);
-    //glDisableClientState(GL_NORMAL_ARRAY);
-	//glDisableClientState(GL_COLOR_ARRAY);
-
 	gGLLastMatrix = NULL;
 	glLoadMatrixd(gGLModelView);
 	glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
@@ -2603,8 +2602,6 @@ void LLPipeline::renderForSelect(std::set<LLViewerObject*>& objects)
 	LLGLDepthTest gls_depth(GL_TRUE,GL_TRUE);
 	disableLights();
 	
-    glEnableClientState ( GL_VERTEX_ARRAY );
-
 	//for each drawpool
 #ifndef LL_RELEASE_FOR_DOWNLOAD
 	LLGLState::checkStates();
@@ -2619,7 +2616,7 @@ void LLPipeline::renderForSelect(std::set<LLViewerObject*>& objects)
 		{
 			LLFacePool* face_pool = (LLFacePool*) poolp;
 			face_pool->renderForSelect();
-	
+			LLVertexBuffer::unbind();
 			gGLLastMatrix = NULL;
 			glLoadMatrixd(gGLModelView);
 
@@ -2635,7 +2632,6 @@ void LLPipeline::renderForSelect(std::set<LLViewerObject*>& objects)
 		}
 	}	
 
-	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
 	LLGLEnable alpha_test(GL_ALPHA_TEST);
 	if (gPickTransparent)
 	{
@@ -2759,10 +2755,10 @@ void LLPipeline::renderForSelect(std::set<LLViewerObject*>& objects)
 	}
 
 	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
-	glDisableClientState( GL_TEXTURE_COORD_ARRAY );
 	
+	LLVertexBuffer::unbind();
 	LLVertexBuffer::stopRender();
-
+	
 	glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
 }
 
@@ -4866,6 +4862,12 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
 {
 	if (LLPipeline::sWaterReflections && assertInitialized() && LLDrawPoolWater::sNeedsReflectionUpdate)
 	{
+#ifndef LL_RELEASE_FOR_DOWNLOAD
+		LLGLState::checkStates();
+		LLGLState::checkTextureChannels();
+		LLGLState::checkClientArrays();
+#endif
+
 		LLCamera camera = camera_in;
 		camera.setFar(camera.getFar()*0.87654321f);
 		LLPipeline::sReflectionRender = TRUE;
@@ -5052,6 +5054,12 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
 		LLDrawPoolWater::sNeedsDistortionUpdate = FALSE;
 		LLViewerCamera::getInstance()->setUserClipPlane(LLPlane(-pnorm, -pd));
 		LLPipeline::sUseOcclusion = occlusion;
+		
+#ifndef LL_RELEASE_FOR_DOWNLOAD
+		LLGLState::checkStates();
+		LLGLState::checkTextureChannels();
+		LLGLState::checkClientArrays();
+#endif
 	}
 }
 
diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h
index 6e02b55daf42368bcda7a627b33456ff092567fb..7e38628d879da18ae0f9d5073bceeca7b857cbec 100644
--- a/indra/newview/pipeline.h
+++ b/indra/newview/pipeline.h
@@ -67,8 +67,9 @@ BOOL compute_min_max(LLMatrix4& box, LLVector2& min, LLVector2& max); // Shouldn
 bool LLRayAABB(const LLVector3 &center, const LLVector3 &size, const LLVector3& origin, const LLVector3& dir, LLVector3 &coord, F32 epsilon = 0);
 BOOL LLLineSegmentAABB(const LLVector3& start, const LLVector3& end, const LLVector3& center, const LLVector3& size);
 BOOL setup_hud_matrices(BOOL for_select);
+glh::matrix4f glh_copy_matrix(GLdouble* src);
 glh::matrix4f glh_get_current_modelview();
-void glh_set_current_modelview(glh::matrix4f& mat);
+void glh_set_current_modelview(const glh::matrix4f& mat);
 glh::matrix4f glh_get_current_projection();
 void glh_set_current_projection(glh::matrix4f& mat);
 glh::matrix4f gl_ortho(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat znear, GLfloat zfar);