diff --git a/BuildParams b/BuildParams
index c303bd2e5ef364e5147821aad537de508266ee6f..f34b262913ef32bae9cca22f817cad3f2b24c973 100644
--- a/BuildParams
+++ b/BuildParams
@@ -102,6 +102,16 @@ mesh-development.build_debug_release_separately = true
 mesh-development.build_CYGWIN_Debug = false
 mesh-development.build_viewer_update_version_manager = false
 
+# ========================================
+# mesh-asset-deprecation
+# ========================================
+mesh-asset-deprecation.viewer_channel = "Project Viewer - Mesh Asset Deprecation"
+mesh-asset-deprecation.login_channel = "Project Viewer - Mesh Asset Deprecation"
+mesh-asset-deprecation.viewer_grid = aditi
+mesh-asset-deprecation.build_debug_release_separately = true
+mesh-asset-deprecation.build_CYGWIN_Debug = false
+mesh-asset-deprecation.build_viewer_update_version_manager = false
+
 # ========================================
 # viewer-mesh
 # ========================================
diff --git a/autobuild.xml b/autobuild.xml
index ec52d6e33156d7670b496f52df4aa0884e064937..3cccddf861c9408c84194e66c8f5fcab492ee04d 100644
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -18,9 +18,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>930bdd987a321eda1838caba8cd6098f</string>
+              <string>b2fe1c860613a68e74d4384be418ffee</string>
               <key>url</key>
-              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-glod/rev/230348/arch/Darwin/installer/glod-1.0pre4-darwin-20110519.tar.bz2</string>
+              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-glod/rev/232684/arch/Darwin/installer/glod-1.0pre4-darwin-20110610.tar.bz2</string>
             </map>
             <key>name</key>
             <string>darwin</string>
@@ -30,9 +30,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>fb33b6cac2e6b98f93c5efa2af2e5a00</string>
+              <string>c0c64dae149d0892343e2ff300fd06b9</string>
               <key>url</key>
-              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-glod/rev/230348/arch/Linux/installer/glod-1.0pre4-linux-20110519.tar.bz2</string>
+              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-glod/rev/232684/arch/Linux/installer/glod-1.0pre4-linux-20110611.tar.bz2</string>
             </map>
             <key>name</key>
             <string>linux</string>
@@ -42,9 +42,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>388cf0e292f756b4bb37696622f0bbc5</string>
+              <string>842208365f5b108dac4c7c733b99da9c</string>
               <key>url</key>
-              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-glod/rev/230348/arch/CYGWIN/installer/glod-1.0pre4-windows-20110519.tar.bz2</string>
+              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-glod/rev/232684/arch/CYGWIN/installer/glod-1.0pre4-windows-20110610.tar.bz2</string>
             </map>
             <key>name</key>
             <string>windows</string>
diff --git a/indra/llcommon/llaccountingquota.h b/indra/llcommon/llaccountingquota.h
index 3401cb57b636d3cef36e3c04e4dbe8bb11c5282a..140333de07535a12d5fbe667ed1833b6cb055dd4 100644
--- a/indra/llcommon/llaccountingquota.h
+++ b/indra/llcommon/llaccountingquota.h
@@ -29,30 +29,38 @@
 
 struct ParcelQuota
 {
-	ParcelQuota( F32 ownerRenderCost, F32 ownerPhysicsCost, F32 ownerNetworkCost, F32 ownerSimulationCost,
-				F32 groupRenderCost, F32 groupPhysicsCost, F32 groupNetworkCost, F32 groupSimulationCost,
-				F32 otherRenderCost, F32 otherPhysicsCost, F32 otherNetworkCost, F32 otherSimulationCost,
-				F32 totalRenderCost, F32 totalPhysicsCost, F32 totalNetworkCost, F32 totalSimulationCost)
+	ParcelQuota( F32 ownerRenderCost,	 F32 ownerPhysicsCost,	  F32 ownerNetworkCost,	   F32 ownerSimulationCost,
+				 F32 groupRenderCost,	 F32 groupPhysicsCost,	  F32 groupNetworkCost,	   F32 groupSimulationCost,
+				 F32 otherRenderCost,	 F32 otherPhysicsCost,	  F32 otherNetworkCost,	   F32 otherSimulationCost,
+				 F32 tempRenderCost,	 F32 tempPhysicsCost,	  F32 tempNetworkCost,	   F32 tempSimulationCost,
+				 F32 selectedRenderCost, F32 selectedPhysicsCost, F32 selectedNetworkCost, F32 selectedSimulationCost,
+				 F32 parcelCapacity )
 	: mOwnerRenderCost( ownerRenderCost ), mOwnerPhysicsCost( ownerPhysicsCost ) 
 	, mOwnerNetworkCost( ownerNetworkCost ), mOwnerSimulationCost( ownerSimulationCost )
 	, mGroupRenderCost( groupRenderCost ), mGroupPhysicsCost( groupPhysicsCost )
 	, mGroupNetworkCost( groupNetworkCost ), mGroupSimulationCost( groupSimulationCost )
 	, mOtherRenderCost( otherRenderCost ), mOtherPhysicsCost( otherPhysicsCost )
 	, mOtherNetworkCost( otherNetworkCost ), mOtherSimulationCost( otherSimulationCost )
-	, mTotalRenderCost( totalRenderCost ), mTotalPhysicsCost( totalPhysicsCost ) 
-	, mTotalNetworkCost( totalNetworkCost ), mTotalSimulationCost( totalSimulationCost )
+	, mTempRenderCost( tempRenderCost ), mTempPhysicsCost( tempPhysicsCost ) 
+	, mTempNetworkCost( tempNetworkCost ), mTempSimulationCost( tempSimulationCost )
+	, mSelectedRenderCost( tempRenderCost ), mSelectedPhysicsCost( tempPhysicsCost ) 
+	, mSelectedNetworkCost( tempNetworkCost ), mSelectedSimulationCost( selectedSimulationCost )
+	, mParcelCapacity( parcelCapacity )
 	{
 	}
+
 	ParcelQuota(){}			
 	F32 mOwnerRenderCost, mOwnerPhysicsCost, mOwnerNetworkCost, mOwnerSimulationCost;
 	F32 mGroupRenderCost, mGroupPhysicsCost, mGroupNetworkCost, mGroupSimulationCost;
 	F32 mOtherRenderCost, mOtherPhysicsCost, mOtherNetworkCost, mOtherSimulationCost;
-	F32 mTotalRenderCost, mTotalPhysicsCost, mTotalNetworkCost, mTotalSimulationCost;
+	F32 mTempRenderCost,  mTempPhysicsCost,  mTempNetworkCost,  mTempSimulationCost;
+	F32 mSelectedRenderCost, mSelectedPhysicsCost, mSelectedNetworkCost, mSelectedSimulationCost;
+	F32 mParcelCapacity;
 };
 
 struct SelectionQuota
 {
-	SelectionQuota( S32 localId, F32 renderCost, F32 physicsCost, F32 networkCost, F32 simulationCost )
+	SelectionQuota( LLUUID localId, F32 renderCost, F32 physicsCost, F32 networkCost, F32 simulationCost )
 	: mLocalId( localId)
 	, mRenderCost( renderCost )
 	, mPhysicsCost( physicsCost )
@@ -63,7 +71,7 @@ struct SelectionQuota
 	SelectionQuota() {}
 	
 	F32 mRenderCost, mPhysicsCost, mNetworkCost, mSimulationCost;	
-	S32 mLocalId;
+	LLUUID mLocalId;
 };
 
 #endif
diff --git a/indra/llcommon/llsdserialize.cpp b/indra/llcommon/llsdserialize.cpp
index 5be5ecc492f6795e91e13660f49f677232e0110e..bf626005143565b67d42fdf45ddec516cc743067 100644
--- a/indra/llcommon/llsdserialize.cpp
+++ b/indra/llcommon/llsdserialize.cpp
@@ -2036,7 +2036,9 @@ std::string zip_llsd(LLSD& data)
 		{ //copy result into output
 			if (strm.avail_out >= CHUNK)
 			{
-				llerrs << "WTF?" << llendl;
+				free(output);
+				llwarns << "Failed to compress LLSD block." << llendl;
+				return std::string();
 			}
 
 			have = CHUNK-strm.avail_out;
diff --git a/indra/llcommon/llstat.cpp b/indra/llcommon/llstat.cpp
index 8ba97d7730e9ed29856a94d74788ee5255125dc3..b2c495d093ebdbcb3fab98262f91ad0fd4114761 100644
--- a/indra/llcommon/llstat.cpp
+++ b/indra/llcommon/llstat.cpp
@@ -737,7 +737,7 @@ void LLPerfBlock::addStatsToLLSDandReset( LLSD & stats,
             }
 		}
 		else
-		{	// WTF?  Shouldn't have a NULL pointer in the map.
+		{	// Shouldn't have a NULL pointer in the map.
             llwarns << "Unexpected NULL dynamic stat at '" << stats_full_path << "'" << llendl;
 		}
 	}	
diff --git a/indra/llmath/lloctree.h b/indra/llmath/lloctree.h
index fdfc24f8b7fbe14c676904d914652f4acb03d213..e5ca47da698efca948d96cc28998790c0b6e9185 100644
--- a/indra/llmath/lloctree.h
+++ b/indra/llmath/lloctree.h
@@ -35,12 +35,14 @@
 
 #define OCT_ERRS LL_WARNS("OctreeErrors")
 
-#define LL_OCTREE_PARANOIA_CHECK 0
+
+extern U32 gOctreeMaxCapacity;
+/*#define LL_OCTREE_PARANOIA_CHECK 0
 #if LL_DARWIN
 #define LL_OCTREE_MAX_CAPACITY 32
 #else
 #define LL_OCTREE_MAX_CAPACITY 128
-#endif
+#endif*/
 
 template <class T> class LLOctreeNode;
 
@@ -74,6 +76,7 @@ template <class T>
 class LLOctreeNode : public LLTreeNode<T>
 {
 public:
+
 	typedef LLOctreeTraveler<T>									oct_traveler;
 	typedef LLTreeTraveler<T>									tree_traveler;
 	typedef typename std::set<LLPointer<T> >					element_list;
@@ -294,8 +297,8 @@ class LLOctreeNode : public LLTreeNode<T>
 		//is it here?
 		if (isInside(data->getPositionGroup()))
 		{
-			if ((getElementCount() < LL_OCTREE_MAX_CAPACITY && contains(data->getBinRadius()) ||
-				(data->getBinRadius() > getSize()[0] &&	parent && parent->getElementCount() >= LL_OCTREE_MAX_CAPACITY))) 
+			if ((getElementCount() < gOctreeMaxCapacity && contains(data->getBinRadius()) ||
+				(data->getBinRadius() > getSize()[0] &&	parent && parent->getElementCount() >= gOctreeMaxCapacity))) 
 			{ //it belongs here
 #if LL_OCTREE_PARANOIA_CHECK
 				//if this is a redundant insertion, error out (should never happen)
diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp
index c504215ee5252f9c7ccf315395e4b721ef5b1bbe..8c81f2778495e12a2a6fd3e7e7a329a407c981a1 100644
--- a/indra/llmath/llvolume.cpp
+++ b/indra/llmath/llvolume.cpp
@@ -100,7 +100,7 @@ void assert_aligned(void* ptr, uintptr_t alignment)
 	uintptr_t t = (uintptr_t) ptr;
 	if (t%alignment != 0)
 	{
-		llerrs << "WTF?" << llendl;
+		llerrs << "Alignment check failed." << llendl;
 	}
 #endif
 }
@@ -361,7 +361,7 @@ class LLVolumeOctreeRebound : public LLOctreeTravelerDepthFirst<LLVolumeTriangle
 		}
 		else
 		{
-			llerrs << "WTF? Empty leaf" << llendl;
+			llerrs << "Empty leaf" << llendl;
 		}
 
 		for (S32 i = 0; i < branch->getChildCount(); ++i)
@@ -416,6 +416,70 @@ LLProfile::Face* LLProfile::addFace(S32 i, S32 count, F32 scaleU, S16 faceID, BO
 	return face;
 }
 
+//static
+S32 LLProfile::getNumNGonPoints(const LLProfileParams& params, S32 sides, F32 offset, F32 bevel, F32 ang_scale, S32 split)
+{ // this is basically LLProfile::genNGon stripped down to only the operations that influence the number of points
+	LLMemType m1(LLMemType::MTYPE_VOLUME);
+	S32 np = 0;
+
+	// Generate an n-sided "circular" path.
+	// 0 is (1,0), and we go counter-clockwise along a circular path from there.
+	F32 t, t_step, t_first, t_fraction;
+	
+	F32 begin  = params.getBegin();
+	F32 end    = params.getEnd();
+
+	t_step = 1.0f / sides;
+	
+	t_first = floor(begin * sides) / (F32)sides;
+
+	// pt1 is the first point on the fractional face.
+	// Starting t and ang values for the first face
+	t = t_first;
+	
+	// Increment to the next point.
+	// pt2 is the end point on the fractional face
+	t += t_step;
+	
+	t_fraction = (begin - t_first)*sides;
+
+	// Only use if it's not almost exactly on an edge.
+	if (t_fraction < 0.9999f)
+	{
+		np++;
+	}
+
+	// There's lots of potential here for floating point error to generate unneeded extra points - DJS 04/05/02
+	while (t < end)
+	{
+		// Iterate through all the integer steps of t.
+		np++;
+
+		t += t_step;
+	}
+
+	t_fraction = (end - (t - t_step))*sides;
+
+	// Find the fraction that we need to add to the end point.
+	t_fraction = (end - (t - t_step))*sides;
+	if (t_fraction > 0.0001f)
+	{
+		np++;
+	}
+
+	// If we're sliced, the profile is open.
+	if ((end - begin)*ang_scale < 0.99f)
+	{
+		if (params.getHollow() <= 0)
+		{
+			// put center point if not hollow.
+			np++;
+		}
+	}
+	
+	return np;
+}
+
 // What is the bevel parameter used for? - DJS 04/05/02
 // Bevel parameter is currently unused but presumedly would support
 // filleted and chamfered corners
@@ -672,6 +736,117 @@ LLProfile::Face* LLProfile::addHole(const LLProfileParams& params, BOOL flat, F3
 	return face;
 }
 
+//static
+S32 LLProfile::getNumPoints(const LLProfileParams& params, BOOL path_open,F32 detail, S32 split,
+						 BOOL is_sculpted, S32 sculpt_size)
+{ // this is basically LLProfile::generate stripped down to only operations that influence the number of points
+	LLMemType m1(LLMemType::MTYPE_VOLUME);
+	
+	if (detail < MIN_LOD)
+	{
+		detail = MIN_LOD;
+	}
+
+	// Generate the face data
+	F32 hollow = params.getHollow();
+
+	S32 np = 0;
+
+	switch (params.getCurveType() & LL_PCODE_PROFILE_MASK)
+	{
+	case LL_PCODE_PROFILE_SQUARE:
+		{
+			np = getNumNGonPoints(params, 4,-0.375, 0, 1, split);
+		
+			if (hollow)
+			{
+				np *= 2;
+			}
+		}
+		break;
+	case  LL_PCODE_PROFILE_ISOTRI:
+	case  LL_PCODE_PROFILE_RIGHTTRI:
+	case  LL_PCODE_PROFILE_EQUALTRI:
+		{
+			np = getNumNGonPoints(params, 3,0, 0, 1, split);
+						
+			if (hollow)
+			{
+				np *= 2;
+			}
+		}
+		break;
+	case LL_PCODE_PROFILE_CIRCLE:
+		{
+			// If this has a square hollow, we should adjust the
+			// number of faces a bit so that the geometry lines up.
+			U8 hole_type=0;
+			F32 circle_detail = MIN_DETAIL_FACES * detail;
+			if (hollow)
+			{
+				hole_type = params.getCurveType() & LL_PCODE_HOLE_MASK;
+				if (hole_type == LL_PCODE_HOLE_SQUARE)
+				{
+					// Snap to the next multiple of four sides,
+					// so that corners line up.
+					circle_detail = llceil(circle_detail / 4.0f) * 4.0f;
+				}
+			}
+
+			S32 sides = (S32)circle_detail;
+
+			if (is_sculpted)
+				sides = sculpt_size;
+			
+			np = getNumNGonPoints(params, sides);
+			
+			if (hollow)
+			{
+				np *= 2;
+			}
+		}
+		break;
+	case LL_PCODE_PROFILE_CIRCLE_HALF:
+		{
+			// If this has a square hollow, we should adjust the
+			// number of faces a bit so that the geometry lines up.
+			U8 hole_type=0;
+			// Number of faces is cut in half because it's only a half-circle.
+			F32 circle_detail = MIN_DETAIL_FACES * detail * 0.5f;
+			if (hollow)
+			{
+				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),
+					// so that corners line up.
+					circle_detail = llceil(circle_detail / 2.0f) * 2.0f;
+				}
+			}
+			np = getNumNGonPoints(params, llfloor(circle_detail), 0.5f, 0.f, 0.5f);
+			
+			if (hollow)
+			{
+				np *= 2;
+			}
+
+			// Special case for openness of sphere
+			if ((params.getEnd() - params.getBegin()) < 1.f)
+			{
+			}
+			else if (!hollow)
+			{
+				np++;
+			}
+		}
+		break;
+	default:
+	   break;
+	};
+
+	
+	return np;
+}
 
 
 BOOL LLProfile::generate(const LLProfileParams& params, BOOL path_open,F32 detail, S32 split,
@@ -1133,6 +1308,32 @@ LLPath::~LLPath()
 {
 }
 
+S32 LLPath::getNumNGonPoints(const LLPathParams& params, S32 sides, F32 startOff, F32 end_scale, F32 twist_scale)
+{ //this is basically LLPath::genNGon stripped down to only operations that influence the number of points added
+	S32 ret = 0;
+
+	F32 step= 1.0f / sides;
+	F32 t	= params.getBegin();
+	ret = 1;
+	
+	t+=step;
+
+	// Snap to a quantized parameter, so that cut does not
+	// affect most sample points.
+	t = ((S32)(t * sides)) / (F32)sides;
+
+	// Run through the non-cut dependent points.
+	while (t < params.getEnd())
+	{
+		ret++;
+		t+=step;
+	}
+
+	ret++;
+
+	return ret;
+}
+
 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.
@@ -1310,6 +1511,56 @@ const LLVector2 LLPathParams::getEndScale() const
 	return end_scale;
 }
 
+S32 LLPath::getNumPoints(const LLPathParams& params, F32 detail)
+{ // this is basically LLPath::generate stripped down to only the operations that influence the number of points
+	LLMemType m1(LLMemType::MTYPE_VOLUME);
+	
+	if (detail < MIN_LOD)
+	{
+		detail = MIN_LOD;
+	}
+
+	S32 np = 2; // hardcode for line
+
+	// Is this 0xf0 mask really necessary?  DK 03/02/05
+
+	switch (params.getCurveType() & 0xf0)
+	{
+	default:
+	case LL_PCODE_PATH_LINE:
+		{
+			// Take the begin/end twist into account for detail.
+			np    = llfloor(fabs(params.getTwistBegin() - params.getTwist()) * 3.5f * (detail-0.5f)) + 2;
+		}
+		break;
+
+	case LL_PCODE_PATH_CIRCLE:
+		{
+			// Increase the detail as the revolutions and twist increase.
+			F32 twist_mag = fabs(params.getTwistBegin() - params.getTwist());
+
+			S32 sides = (S32)llfloor(llfloor((MIN_DETAIL_FACES * detail + twist_mag * 3.5f * (detail-0.5f))) * params.getRevolutions());
+
+			np = sides;
+		}
+		break;
+
+	case LL_PCODE_PATH_CIRCLE2:
+		{
+			//genNGon(params, llfloor(MIN_DETAIL_FACES * detail), 4.f, 0.f);
+			np = getNumNGonPoints(params, llfloor(MIN_DETAIL_FACES * detail));
+		}
+		break;
+
+	case LL_PCODE_PATH_TEST:
+
+		np     = 5;
+		break;
+	};
+
+	return np;
+}
+
 BOOL LLPath::generate(const LLPathParams& params, F32 detail, S32 split,
 					  BOOL is_sculpted, S32 sculpt_size)
 {
@@ -2159,27 +2410,41 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size)
 		U32 face_count = mdl.size();
 
 		if (face_count == 0)
-		{
-			llerrs << "WTF?" << llendl;
+		{ //no faces unpacked, treat as failed decode
+			llwarns << "found no faces!" << llendl;
+			return false;
 		}
 
 		mVolumeFaces.resize(face_count);
 
 		for (U32 i = 0; i < face_count; ++i)
 		{
+			LLVolumeFace& face = mVolumeFaces[i];
+
+			if (mdl[i].has("NoGeometry"))
+			{ //face has no geometry, continue
+				face.resizeIndices(3);
+				face.resizeVertices(1);
+				memset(face.mPositions, 0, sizeof(LLVector4a));
+				memset(face.mNormals, 0, sizeof(LLVector4a));
+				memset(face.mTexCoords, 0, sizeof(LLVector2));
+				memset(face.mIndices, 0, sizeof(U16)*3);
+				continue;
+			}
+
 			LLSD::Binary pos = mdl[i]["Position"];
 			LLSD::Binary norm = mdl[i]["Normal"];
 			LLSD::Binary tc = mdl[i]["TexCoord0"];
 			LLSD::Binary idx = mdl[i]["TriangleList"];
 
-			LLVolumeFace& face = mVolumeFaces[i];
+			
 
 			//copy out indices
 			face.resizeIndices(idx.size()/2);
 			
 			if (idx.empty() || face.mNumIndices < 3)
 			{ //why is there an empty index list?
-				llerrs <<"WTF?" << llendl;
+				llwarns <<"Empty face present!" << llendl;
 				continue;
 			}
 
@@ -2377,14 +2642,20 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size)
 			LLVector4a& min = face.mExtents[0];
 			LLVector4a& max = face.mExtents[1];
 
-			min.clear();
-			max.clear();
-			min = max = face.mPositions[0];
-
-			for (S32 i = 1; i < face.mNumVertices; ++i)
+			if (face.mNumVertices < 3)
+			{ //empty face, use a dummy 1cm (at 1m scale) bounding box
+				min.splat(-0.005f);
+				max.splat(0.005f);
+			}
+			else
 			{
-				min.setMin(min, face.mPositions[i]);
-				max.setMax(max, face.mPositions[i]);
+				min = max = face.mPositions[0];
+
+				for (S32 i = 1; i < face.mNumVertices; ++i)
+				{
+					min.setMin(min, face.mPositions[i]);
+					max.setMax(max, face.mPositions[i]);
+				}
 			}
 		}
 	}
@@ -2980,7 +3251,11 @@ void LLVolume::sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components,
 		// don't test lowest LOD to support legacy content DEV-33670
 		if (mDetail > SCULPT_MIN_AREA_DETAIL)
 		{
-			if (sculptGetSurfaceArea() < SCULPT_MIN_AREA)
+			F32 area = sculptGetSurfaceArea();
+
+			const F32 SCULPT_MAX_AREA = 32.f;
+
+			if (area < SCULPT_MIN_AREA || area > SCULPT_MAX_AREA)
 			{
 				data_is_empty = TRUE;
 			}
@@ -4064,6 +4339,23 @@ S32 *LLVolume::getTriangleIndices(U32 &num_indices) const
 	return index;
 }
 
+void LLVolume::getLoDTriangleCounts(const LLVolumeParams& params, S32* counts)
+{ //attempt to approximate the number of triangles that will result from generating a volume LoD set for the 
+	//supplied LLVolumeParams -- inaccurate, but a close enough approximation for determining streaming cost
+	F32 detail[] = {1.f, 1.5f, 2.5f, 4.f};	
+	for (S32 i = 0; i < 4; i++)
+	{
+		S32 count = 0;
+		S32 path_points = LLPath::getNumPoints(params.getPathParams(), detail[i]);
+		S32 profile_points = LLProfile::getNumPoints(params.getProfileParams(), false, detail[i]);
+
+		count = (profile_points-1)*2*(path_points-1);
+		count += profile_points*2;
+
+		counts[i] = count;
+	}
+}
+
 S32 LLVolume::getNumTriangleIndices() const
 {
 	BOOL profile_open = getProfile().isOpen();
@@ -5220,6 +5512,8 @@ LLVolumeFace::LLVolumeFace() :
 	mOctree(NULL)
 {
 	mExtents = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*3);
+	mExtents[0].splat(-0.5f);
+	mExtents[1].splat(0.5f);
 	mCenter = mExtents+2;
 }
 
@@ -5741,6 +6035,11 @@ void LLVolumeFace::cacheOptimize()
 	
 	LLVCacheLRU cache;
 	
+	if (mNumVertices < 3)
+	{ //nothing to do
+		return;
+	}
+
 	//mapping of vertices to triangles and indices
 	std::vector<LLVCacheVertexData> vertex_data;
 
diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h
index 01bfbd858be72fd6badd82b8e0e335f68b682eba..f67f8f644dfa44185df04ee40361e681f3b15e37 100644
--- a/indra/llmath/llvolume.h
+++ b/indra/llmath/llvolume.h
@@ -690,6 +690,9 @@ class LLProfile
 	BOOL isFlat(S32 face) const							{ return (mFaces[face].mCount == 2); }
 	BOOL isOpen() const									{ return mOpen; }
 	void setDirty()										{ mDirty     = TRUE; }
+
+	static S32 getNumPoints(const LLProfileParams& params, BOOL path_open, F32 detail = 1.0f, S32 split = 0,
+				  BOOL is_sculpted = FALSE, S32 sculpt_size = 0);
 	BOOL generate(const LLProfileParams& params, BOOL path_open, F32 detail = 1.0f, S32 split = 0,
 				  BOOL is_sculpted = FALSE, S32 sculpt_size = 0);
 	BOOL isConcave() const								{ return mConcave; }
@@ -714,6 +717,7 @@ class LLProfile
 
 protected:
 	void genNormals(const LLProfileParams& params);
+	static S32 getNumNGonPoints(const LLProfileParams& params, S32 sides, F32 offset=0.0f, F32 bevel = 0.0f, F32 ang_scale = 1.f, S32 split = 0);
 	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(const LLProfileParams& params, BOOL flat, F32 sides, F32 offset, F32 box_hollow, F32 ang_scale, S32 split = 0);
@@ -756,6 +760,9 @@ class LLPath
 
 	virtual ~LLPath();
 
+	static S32 getNumPoints(const LLPathParams& params, F32 detail);
+	static S32 getNumNGonPoints(const LLPathParams& params, S32 sides, F32 offset=0.0f, F32 end_scale = 1.f, F32 twist_scale = 1.f);
+
 	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, S32 sculpt_size = 0);
@@ -981,6 +988,7 @@ class LLVolume : public LLRefCount
 
 	// returns number of triangle indeces required for path/profile mesh
 	S32 getNumTriangleIndices() const;
+	static void getLoDTriangleCounts(const LLVolumeParams& params, S32* counts);
 
 	S32 getNumTriangles() const;
 
diff --git a/indra/llmessage/message_prehash.cpp b/indra/llmessage/message_prehash.cpp
index 5d03615e5333bdef27d8873ea92b6e48c872e0ec..6133f506376224648965b7e404139a74195aa118 100644
--- a/indra/llmessage/message_prehash.cpp
+++ b/indra/llmessage/message_prehash.cpp
@@ -742,6 +742,7 @@ char const* const _PREHASH_MoneyData = LLMessageStringTable::getInstance()->getS
 char const* const _PREHASH_ObjectDeselect = LLMessageStringTable::getInstance()->getString("ObjectDeselect");
 char const* const _PREHASH_NewAssetID = LLMessageStringTable::getInstance()->getString("NewAssetID");
 char const* const _PREHASH_ObjectAdd = LLMessageStringTable::getInstance()->getString("ObjectAdd");
+char const* const _PREHASH_SimulatorFeatures = LLMessageStringTable::getInstance()->getString("SimulatorFeatures");
 char const* const _PREHASH_RayEndIsIntersection = LLMessageStringTable::getInstance()->getString("RayEndIsIntersection");
 char const* const _PREHASH_CompleteAuction = LLMessageStringTable::getInstance()->getString("CompleteAuction");
 char const* const _PREHASH_CircuitCode = LLMessageStringTable::getInstance()->getString("CircuitCode");
diff --git a/indra/llmessage/message_prehash.h b/indra/llmessage/message_prehash.h
index 8dc86601e6815093a99ea0ffb008f134187ebf42..f94ee1ed22bc7dadb42dc537ed63d2a4fb28950c 100644
--- a/indra/llmessage/message_prehash.h
+++ b/indra/llmessage/message_prehash.h
@@ -742,6 +742,7 @@ extern char const* const _PREHASH_MoneyData;
 extern char const* const _PREHASH_ObjectDeselect;
 extern char const* const _PREHASH_NewAssetID;
 extern char const* const _PREHASH_ObjectAdd;
+extern char const* const _PREHASH_SimulatorFeatures;
 extern char const* const _PREHASH_RayEndIsIntersection;
 extern char const* const _PREHASH_CompleteAuction;
 extern char const* const _PREHASH_CircuitCode;
diff --git a/indra/llprimitive/llmodel.cpp b/indra/llprimitive/llmodel.cpp
index 57ac7a143f3f6206e192f264378b580d4cc0aaad..0463d5364bd6af6490e4751bb1995315a75b35dc 100644
--- a/indra/llprimitive/llmodel.cpp
+++ b/indra/llprimitive/llmodel.cpp
@@ -50,7 +50,7 @@ std::string model_names[] =
 	"low_lod",
 	"medium_lod",
 	"high_lod",
-	"physics_shape"
+	"physics_mesh"
 };
 
 const int MODEL_NAMES_LENGTH = sizeof(model_names) / sizeof(std::string);
@@ -84,7 +84,7 @@ void load_face_from_dom_inputs(LLVolumeFace& face, const domInputLocalOffset_Arr
 			domInputLocal_Array& v_inp = vertices->getInput_array();
 			if (inputs[j]->getOffset() != 0)
 			{
-				llerrs << "WTF?" << llendl;
+				llerrs << "Vertex array offset MUST be zero." << llendl;
 			}
 
 			for (U32 k = 0; k < v_inp.getCount(); ++k)
@@ -98,7 +98,7 @@ void load_face_from_dom_inputs(LLVolumeFace& face, const domInputLocalOffset_Arr
 
 					if (src->getTechnique_common()->getAccessor()->getStride() != 3)
 					{
-						llerrs << "WTF?" << llendl;
+						llerrs << "Vertex array stride MUST be three." << llendl;
 					}
 
 					domListOfFloats& v = src->getFloat_array()->getValue();
@@ -149,9 +149,10 @@ void load_face_from_dom_inputs(LLVolumeFace& face, const domInputLocalOffset_Arr
 	}
 }
 
-void get_dom_sources(const domInputLocalOffset_Array& inputs, S32& pos_offset, S32& tc_offset, S32& norm_offset, S32 &idx_stride,
+bool get_dom_sources(const domInputLocalOffset_Array& inputs, S32& pos_offset, S32& tc_offset, S32& norm_offset, S32 &idx_stride,
 					 domSource* &pos_source, domSource* &tc_source, domSource* &norm_source)
 {
+	
 	idx_stride = 0;
 
 	for (U32 j = 0; j < inputs.getCount(); ++j)
@@ -163,7 +164,11 @@ void get_dom_sources(const domInputLocalOffset_Array& inputs, S32& pos_offset, S
 			const domURIFragmentType& uri = inputs[j]->getSource();
 			daeElementRef elem = uri.getElement();
 			domVertices* vertices = (domVertices*) elem.cast();
-
+			if ( !vertices )
+			{
+				return false;
+			}
+				
 			domInputLocal_Array& v_inp = vertices->getInput_array();
 			
 			
@@ -207,6 +212,8 @@ void get_dom_sources(const domInputLocalOffset_Array& inputs, S32& pos_offset, S
 	}
 
 	idx_stride += 1;
+	
+	return true;
 }
 
 LLModel::EModelStatus load_face_from_dom_triangles(std::vector<LLVolumeFace>& face_list, std::vector<std::string>& materials, domTrianglesRef& tri)
@@ -227,8 +234,12 @@ LLModel::EModelStatus load_face_from_dom_triangles(std::vector<LLVolumeFace>& fa
 
 	S32 idx_stride = 0;
 
-	get_dom_sources(inputs, pos_offset, tc_offset, norm_offset, idx_stride, pos_source, tc_source, norm_source);
+	if ( !get_dom_sources(inputs, pos_offset, tc_offset, norm_offset, idx_stride, pos_source, tc_source, norm_source) || !pos_source )
+	{
+		return LLModel::BAD_ELEMENT;
+	}
 
+	
 	domPRef p = tri->getP();
 	domListOfUInts& idx = p->getValue();
 	
@@ -367,7 +378,10 @@ LLModel::EModelStatus load_face_from_dom_polylist(std::vector<LLVolumeFace>& fac
 
 	S32 idx_stride = 0;
 
-	get_dom_sources(inputs, pos_offset, tc_offset, norm_offset, idx_stride, pos_source, tc_source, norm_source);
+	if (!get_dom_sources(inputs, pos_offset, tc_offset, norm_offset, idx_stride, pos_source, tc_source, norm_source))
+	{
+		return LLModel::BAD_ELEMENT;
+	}
 
 	LLVolumeFace face;
 
@@ -564,7 +578,10 @@ LLModel::EModelStatus load_face_from_dom_polygons(std::vector<LLVolumeFace>& fac
 			const domURIFragmentType& uri = inputs[i]->getSource();
 			daeElementRef elem = uri.getElement();
 			domVertices* vertices = (domVertices*) elem.cast();
-
+			if (!vertices)
+			{
+				return LLModel::BAD_ELEMENT;
+			}
 			domInputLocal_Array& v_inp = vertices->getInput_array();
 
 			for (U32 k = 0; k < v_inp.getCount(); ++k)
@@ -574,6 +591,10 @@ LLModel::EModelStatus load_face_from_dom_polygons(std::vector<LLVolumeFace>& fac
 					const domURIFragmentType& uri = v_inp[k]->getSource();
 					daeElementRef elem = uri.getElement();
 					domSource* src = (domSource*) elem.cast();
+					if (!src)
+					{
+						return LLModel::BAD_ELEMENT;
+					}
 					v = &(src->getFloat_array()->getValue());
 				}
 			}
@@ -585,6 +606,10 @@ LLModel::EModelStatus load_face_from_dom_polygons(std::vector<LLVolumeFace>& fac
 			const domURIFragmentType& uri = inputs[i]->getSource();
 			daeElementRef elem = uri.getElement();
 			domSource* src = (domSource*) elem.cast();
+			if (!src)
+			{
+				return LLModel::BAD_ELEMENT;
+			}
 			n = &(src->getFloat_array()->getValue());
 		}
 		else if (strcmp(COMMON_PROFILE_INPUT_TEXCOORD, inputs[i]->getSemantic()) == 0 && inputs[i]->getSet() == 0)
@@ -593,6 +618,10 @@ LLModel::EModelStatus load_face_from_dom_polygons(std::vector<LLVolumeFace>& fac
 			const domURIFragmentType& uri = inputs[i]->getSource();
 			daeElementRef elem = uri.getElement();
 			domSource* src = (domSource*) elem.cast();
+			if (!src)
+			{
+				return LLModel::BAD_ELEMENT;
+			}
 			t = &(src->getFloat_array()->getValue());
 		}
 	}
@@ -667,11 +696,6 @@ LLModel::EModelStatus load_face_from_dom_polygons(std::vector<LLVolumeFace>& fac
 		}
 	}
 
-	if (cur_idx != vert_idx.size())
-	{
-		llerrs << "WTF?" << llendl;
-	}
-
 	//build vertex array from map
 	std::vector<LLVolumeFace::VertexData> new_verts;
 	new_verts.resize(vert_idx.size());
@@ -717,7 +741,7 @@ LLModel::EModelStatus load_face_from_dom_polygons(std::vector<LLVolumeFace>& fac
 //static
 std::string LLModel::getStatusString(U32 status)
 {
-	const static std::string status_strings[(S32)INVALID_STATUS] = {"status_no_error", "status_vertex_number_overflow"};
+	const static std::string status_strings[(S32)INVALID_STATUS] = {"status_no_error", "status_vertex_number_overflow","bad_element"};
 
 	if(status < INVALID_STATUS)
 	{
@@ -755,7 +779,6 @@ void LLModel::addVolumeFacesFromDomMesh(domMesh* mesh)
 	for (U32 i = 0; i < polys.getCount(); ++i)
 	{
 		domPolylistRef& poly = polys.get(i);
-
 		mStatus = load_face_from_dom_polylist(mVolumeFaces, mMaterialList, poly);
 
 		if(mStatus != NO_ERRORS)
@@ -765,12 +788,12 @@ void LLModel::addVolumeFacesFromDomMesh(domMesh* mesh)
 			return ; //abort
 		}
 	}
-
+	
 	domPolygons_Array& polygons = mesh->getPolygons_array();
+	
 	for (U32 i = 0; i < polygons.getCount(); ++i)
 	{
 		domPolygonsRef& poly = polygons.get(i);
-
 		mStatus = load_face_from_dom_polygons(mVolumeFaces, mMaterialList, poly);
 
 		if(mStatus != NO_ERRORS)
@@ -780,7 +803,7 @@ void LLModel::addVolumeFacesFromDomMesh(domMesh* mesh)
 			return ; //abort
 		}
 	}
-
+ 
 }
 
 BOOL LLModel::createVolumeFacesFromDomMesh(domMesh* mesh)
@@ -926,11 +949,6 @@ void LLModel::normalizeVolumeFaces()
 	{
 		LLVector4a min, max;
 		
-		if (mVolumeFaces[0].mNumVertices <= 0)
-		{
-			llerrs << "WTF?" << llendl;
-		}
-
 		// For all of the volume faces
 		// in the model, loop over
 		// them and see what the extents
@@ -942,11 +960,6 @@ void LLModel::normalizeVolumeFaces()
 		{
 			LLVolumeFace& face = mVolumeFaces[i];
 
-			if (face.mNumVertices <= 0)
-			{
-				llerrs << "WTF?" << llendl;
-			}
-
 			update_min_max(min, max, face.mExtents[0]);
 			update_min_max(min, max, face.mExtents[1]);
 		}
@@ -1289,11 +1302,6 @@ void LLModel::generateNormals(F32 angle_cutoff)
 				{
 					LLVector4a& n = iter->second[k].getNormal();
 
-					if (!iter->second[k].getPosition().equals3(new_face.mPositions[i]))
-					{
-						llerrs << "WTF?" << llendl;
-					}
-
 					F32 cur = n.dot3(ref_norm).getF32();
 
 					if (cur > best)
@@ -1410,7 +1418,11 @@ LLSD LLModel::writeModel(
 	if (!decomp.mBaseHull.empty() ||
 		!decomp.mHull.empty())		
 	{
-		mdl["decomposition"] = decomp.asLLSD();
+		mdl["physics_convex"] = decomp.asLLSD();
+		if (!decomp.mHull.empty())
+		{ //convex decomposition exists, physics mesh will not be used
+			model[LLModel::LOD_PHYSICS] = NULL;
+		}
 	}
 
 	for (U32 idx = 0; idx < MODEL_NAMES_LENGTH; ++idx)
@@ -1435,8 +1447,9 @@ LLSD LLModel::writeModel(
 			for (S32 i = 0; i < model[idx]->getNumVolumeFaces(); ++i)
 			{ //for each face
 				const LLVolumeFace& face = model[idx]->getVolumeFace(i);
-				if (!face.mNumVertices)
+				if (face.mNumVertices < 3)
 				{ //don't export an empty face
+					mdl[model_names[idx]][i]["NoGeometry"] = true;
 					continue;
 				}
 				LLSD::Binary verts(face.mNumVertices*3*2);
@@ -1469,7 +1482,6 @@ LLSD LLModel::writeModel(
 					//position + normal
 					for (U32 k = 0; k < 3; ++k)
 					{ //for each component
-
 						//convert to 16-bit normalized across domain
 						U16 val = (U16) (((pos[k]-min_pos.mV[k])/pos_range.mV[k])*65535);
 
@@ -1513,7 +1525,6 @@ LLSD LLModel::writeModel(
 				//write out face data
 				mdl[model_names[idx]][i]["PositionDomain"]["Min"] = min_pos.getValue();
 				mdl[model_names[idx]][i]["PositionDomain"]["Max"] = max_pos.getValue();
-
 				mdl[model_names[idx]][i]["TexCoord0Domain"]["Min"] = min_tc.getValue();
 				mdl[model_names[idx]][i]["TexCoord0Domain"]["Max"] = max_tc.getValue();
 
@@ -1539,11 +1550,6 @@ LLSD LLModel::writeModel(
 
 						weight_list& weights = high->getJointInfluences(pos);
 
-						if (weights.size() > 4)
-						{
-							llerrs << "WTF?" << llendl;
-						}
-
 						S32 count = 0;
 						for (weight_list::iterator iter = weights.begin(); iter != weights.end(); ++iter)
 						{
@@ -1607,23 +1613,19 @@ LLSD LLModel::writeModelToStream(std::ostream& ostr, LLSD& mdl, BOOL nowrite)
 			cur_offset += size;
 			bytes += size;
 		}
-		else
-		{
-			llerrs << "WTF?" << llendl;
-		}
 	}
 
 	std::string decomposition;
 
-	if (mdl.has("decomposition"))
+	if (mdl.has("physics_convex"))
 	{ //write out convex decomposition
-		decomposition = zip_llsd(mdl["decomposition"]);
+		decomposition = zip_llsd(mdl["physics_convex"]);
 
 		U32 size = decomposition.size();
 		if (size > 0)
 		{
-			header["decomposition"]["offset"] = (LLSD::Integer) cur_offset;
-			header["decomposition"]["size"] = (LLSD::Integer) size;
+			header["physics_convex"]["offset"] = (LLSD::Integer) cur_offset;
+			header["physics_convex"]["size"] = (LLSD::Integer) size;
 			cur_offset += size;
 			bytes += size;
 		}
@@ -1644,11 +1646,6 @@ LLSD LLModel::writeModelToStream(std::ostream& ostr, LLSD& mdl, BOOL nowrite)
 			cur_offset += size;
 			bytes += size;
 		}
-		else
-		{
-			header[model_names[i]]["offset"] = -1;
-			header[model_names[i]]["size"] = 0;
-		}
 	}
 
 	if (!nowrite)
@@ -1662,7 +1659,7 @@ LLSD LLModel::writeModelToStream(std::ostream& ostr, LLSD& mdl, BOOL nowrite)
 
 		if (!decomposition.empty())
 		{ //write decomposition block
-			ostr.write((const char*) decomposition.data(), header["decomposition"]["size"].asInteger());
+			ostr.write((const char*) decomposition.data(), header["physics_convex"]["size"].asInteger());
 		}
 
 		for (S32 i = 0; i < MODEL_NAMES_LENGTH; i++)
@@ -1685,7 +1682,7 @@ LLModel::weight_list& LLModel::getJointInfluences(const LLVector3& pos)
 	{
 		if ((iter->first - pos).magVec() > 0.1f)
 		{
-			llerrs << "WTF?" << llendl;
+			llerrs << "Couldn't find weight list." << llendl;
 		}
 
 		return iter->second;
@@ -1778,7 +1775,7 @@ void LLModel::updateHullCenters()
 	if (mHullPoints > 0)
 	{
 		mCenterOfHullCenters *= 1.f / mHullPoints;
-		llassert(mPhysics.asLLSD().has("HullList"));
+		llassert(mPhysics.hasHullList());
 	}
 }
 
@@ -1801,7 +1798,7 @@ bool LLModel::loadModel(std::istream& is)
 		"low_lod",
 		"medium_lod",
 		"high_lod",
-		"physics_shape",
+		"physics_mesh",
 	};
 
 	const S32 MODEL_LODS = 5;
@@ -1900,8 +1897,8 @@ bool LLModel::loadSkinInfo(LLSD& header, std::istream &is)
 
 bool LLModel::loadDecomposition(LLSD& header, std::istream& is)
 {
-	S32 offset = header["decomposition"]["offset"].asInteger();
-	S32 size = header["decomposition"]["size"].asInteger();
+	S32 offset = header["physics_convex"]["offset"].asInteger();
+	S32 size = header["physics_convex"]["size"].asInteger();
 
 	if (offset >= 0 && size > 0)
 	{
@@ -2041,7 +2038,7 @@ void LLModel::Decomposition::fromLLSD(LLSD& decomp)
 	{
 		// updated for const-correctness. gcc is picky about this type of thing - Nyx
 		const LLSD::Binary& hulls = decomp["HullList"].asBinary();
-		const LLSD::Binary& position = decomp["Position"].asBinary();
+		const LLSD::Binary& position = decomp["Positions"].asBinary();
 
 		U16* p = (U16*) &position[0];
 
@@ -2051,11 +2048,19 @@ void LLModel::Decomposition::fromLLSD(LLSD& decomp)
 		LLVector3 max;
 		LLVector3 range;
 
-		min.setValue(decomp["Min"]);
-		max.setValue(decomp["Max"]);
+		if (decomp.has("Min"))
+		{
+			min.setValue(decomp["Min"]);
+			max.setValue(decomp["Max"]);
+		}
+		else
+		{
+			min.set(-0.5f, -0.5f, -0.5f);
+			max.set(0.5f, 0.5f, 0.5f);
+		}
+
 		range = max-min;
 
-		
 		for (U32 i = 0; i < hulls.size(); ++i)
 		{
 			U16 count = (hulls[i] == 0) ? 256 : hulls[i];
@@ -2071,6 +2076,7 @@ void LLModel::Decomposition::fromLLSD(LLSD& decomp)
 				//point must be unique
 				//llassert(valid.find(test) == valid.end());
 				valid.insert(test);
+
 				mHull[i].push_back(LLVector3(
 					(F32) p[0]/65535.f*range.mV[0]+min.mV[0],
 					(F32) p[1]/65535.f*range.mV[1]+min.mV[1],
@@ -2085,9 +2091,9 @@ void LLModel::Decomposition::fromLLSD(LLSD& decomp)
 		}
 	}
 
-	if (decomp.has("Hull"))
+	if (decomp.has("BoundingVerts"))
 	{
-		const LLSD::Binary& position = decomp["Hull"].asBinary();
+		const LLSD::Binary& position = decomp["BoundingVerts"].asBinary();
 
 		U16* p = (U16*) &position[0];
 
@@ -2123,10 +2129,15 @@ void LLModel::Decomposition::fromLLSD(LLSD& decomp)
 	{
 		//empty base hull mesh to indicate decomposition has been loaded
 		//but contains no base hull
-		mBaseHullMesh.clear();;
+		mBaseHullMesh.clear();
 	}
 }
 
+bool LLModel::Decomposition::hasHullList() const
+{
+	return !mHull.empty() ;
+}
+
 LLSD LLModel::Decomposition::asLLSD() const
 {
 	LLSD ret;
@@ -2137,11 +2148,9 @@ LLSD LLModel::Decomposition::asLLSD() const
 	}
 
 	//write decomposition block
-	// ["decomposition"]["HullList"] -- list of 8 bit integers, each entry represents a hull with specified number of points
-	// ["decomposition"]["PositionDomain"]["Min"/"Max"]
-	// ["decomposition"]["Position"] -- list of 16-bit integers to be decoded to given domain, encoded 3D points
-	// ["decomposition"]["Hull"] -- list of 16-bit integers to be decoded to given domain, encoded 3D points representing a single hull approximation of given shape
-	
+	// ["physics_convex"]["HullList"] -- list of 8 bit integers, each entry represents a hull with specified number of points
+	// ["physics_convex"]["Position"] -- list of 16-bit integers to be decoded to given domain, encoded 3D points
+	// ["physics_convex"]["BoundingVerts"] -- list of 16-bit integers to be decoded to given domain, encoded 3D points representing a single hull approximation of given shape
 	
 	//get minimum and maximum
 	LLVector3 min;
@@ -2190,6 +2199,8 @@ LLSD LLModel::Decomposition::asLLSD() const
 	{
 		LLSD::Binary p(total*3*2);
 
+		LLVector3 min(-0.5f, -0.5f, -0.5f);
+		LLVector3 max(0.5f, 0.5f, 0.5f);
 		LLVector3 range = max-min;
 
 		U32 vert_idx = 0;
@@ -2205,17 +2216,24 @@ LLSD LLModel::Decomposition::asLLSD() const
 				U64 test = 0;
 				for (U32 k = 0; k < 3; k++)
 				{
+					F32* src = (F32*) (mHull[i][j].mV);
+
+					llassert(src[k] <= 0.501f && src[k] >= -0.501f);
+
 					//convert to 16-bit normalized across domain
-					U16 val = (U16) (((mHull[i][j].mV[k]-min.mV[k])/range.mV[k])*65535);
+					U16 val = (U16) (((src[k]-min.mV[k])/range.mV[k])*65535);
 
-					switch (k)
+					if(valid.size() < 3)
 					{
-						case 0: test = test | (U64) val; break;
-						case 1: test = test | ((U64) val << 16); break;
-						case 2: test = test | ((U64) val << 32); break;
-					};
+						switch (k)
+						{
+							case 0: test = test | (U64) val; break;
+							case 1: test = test | ((U64) val << 16); break;
+							case 2: test = test | ((U64) val << 32); break;
+						};
 
-					valid.insert(test);
+						valid.insert(test);
+					}
 					
 					U8* buff = (U8*) &val;
 					//write to binary buffer
@@ -2227,17 +2245,21 @@ LLSD LLModel::Decomposition::asLLSD() const
 				}
 			}
 
-			//must have at least 4 unique points
-			llassert(valid.size() > 3);
+			//must have at least 3 unique points
+			llassert(valid.size() > 2);
 		}
 
-		ret["Position"] = p;
+		ret["Positions"] = p;
 	}
 
+	//llassert(!mBaseHull.empty());
+
 	if (!mBaseHull.empty())
 	{
 		LLSD::Binary p(mBaseHull.size()*3*2);
 
+		LLVector3 min(-0.5f, -0.5f, -0.5f);
+		LLVector3 max(0.5f, 0.5f, 0.5f);
 		LLVector3 range = max-min;
 
 		U32 vert_idx = 0;
@@ -2245,6 +2267,8 @@ LLSD LLModel::Decomposition::asLLSD() const
 		{
 			for (U32 k = 0; k < 3; k++)
 			{
+				llassert(mBaseHull[j].mV[k] <= 0.51f && mBaseHull[j].mV[k] >= -0.51f);
+
 				//convert to 16-bit normalized across domain
 				U16 val = (U16) (((mBaseHull[j].mV[k]-min.mV[k])/range.mV[k])*65535);
 
@@ -2255,12 +2279,12 @@ LLSD LLModel::Decomposition::asLLSD() const
 
 				if (vert_idx > p.size())
 				{
-					llerrs << "WTF?" << llendl;
+					llerrs << "Index out of bounds" << llendl;
 				}
 			}
 		}
 		
-		ret["Hull"] = p;
+		ret["BoundingVerts"] = p;
 	}
 
 	return ret;
@@ -2290,10 +2314,5 @@ void LLModel::Decomposition::merge(const LLModel::Decomposition* rhs)
 	{ //take physics shape mesh from rhs
 		mPhysicsShapeMesh = rhs->mPhysicsShapeMesh;
 	}
-
-	if (!mHull.empty())
-	{ //verify
-		llassert(asLLSD().has("HullList"));
-	}
 }
 
diff --git a/indra/llprimitive/llmodel.h b/indra/llprimitive/llmodel.h
index 23f4b5cb42733a0565fc4d15d19f9976266d4595..cd9f76fcb740026fd1239bc73f904ac3a4eeed9b 100644
--- a/indra/llprimitive/llmodel.h
+++ b/indra/llprimitive/llmodel.h
@@ -73,6 +73,7 @@ class LLModel : public LLVolume
 	{
 		NO_ERRORS = 0,
 		VERTEX_NUMBER_OVERFLOW, //vertex number is >= 65535.
+		BAD_ELEMENT,
 		INVALID_STATUS
 	} ;
 
@@ -106,6 +107,7 @@ class LLModel : public LLVolume
 		Decomposition(LLSD& data);
 		void fromLLSD(LLSD& data);
 		LLSD asLLSD() const;
+		bool hasHullList() const;
 
 		void merge(const Decomposition* rhs);
 
diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp
index a460912e70d080b98d97416f9ce308d3aebd2f61..a3aed4dd8abba758d7247fcbe436ed77b4f3faad 100644
--- a/indra/llrender/llgl.cpp
+++ b/indra/llrender/llgl.cpp
@@ -127,6 +127,11 @@ PFNGLUNMAPBUFFERARBPROC				glUnmapBufferARB = NULL;
 PFNGLGETBUFFERPARAMETERIVARBPROC	glGetBufferParameterivARB = NULL;
 PFNGLGETBUFFERPOINTERVARBPROC		glGetBufferPointervARB = NULL;
 
+// GL_ARB_map_buffer_range
+PFNGLMAPBUFFERRANGEPROC			glMapBufferRange;
+PFNGLFLUSHMAPPEDBUFFERRANGEPROC	glFlushMappedBufferRange;
+
+
 // vertex object prototypes
 PFNGLNEWOBJECTBUFFERATIPROC			glNewObjectBufferATI = NULL;
 PFNGLISOBJECTBUFFERATIPROC			glIsObjectBufferATI = NULL;
@@ -178,6 +183,12 @@ PFNGLBLITFRAMEBUFFERPROC glBlitFramebuffer = NULL;
 PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC glRenderbufferStorageMultisample = NULL;
 PFNGLFRAMEBUFFERTEXTURELAYERPROC glFramebufferTextureLayer = NULL;
 
+//GL_ARB_texture_multisample
+PFNGLTEXIMAGE2DMULTISAMPLEPROC glTexImage2DMultisample;
+PFNGLTEXIMAGE3DMULTISAMPLEPROC glTexImage3DMultisample;
+PFNGLGETMULTISAMPLEFVPROC glGetMultisamplefv;
+PFNGLSAMPLEMASKIPROC glSampleMaski;
+
 // GL_EXT_blend_func_separate
 PFNGLBLENDFUNCSEPARATEEXTPROC glBlendFuncSeparateEXT = NULL;
 
@@ -321,9 +332,11 @@ LLGLManager::LLGLManager() :
 	mHasMipMapGeneration(FALSE),
 	mHasCompressedTextures(FALSE),
 	mHasFramebufferObject(FALSE),
+	mMaxSamples(0),
 	mHasBlendFuncSeparate(FALSE),
 
 	mHasVertexBufferObject(FALSE),
+	mHasMapBufferRange(FALSE),
 	mHasPBuffer(FALSE),
 	mHasShaderObjects(FALSE),
 	mHasVertexShader(FALSE),
@@ -334,6 +347,11 @@ LLGLManager::LLGLManager() :
 	mHasPointParameters(FALSE),
 	mHasDrawBuffers(FALSE),
 	mHasTextureRectangle(FALSE),
+	mHasTextureMultisample(FALSE),
+	mMaxSampleMaskWords(0),
+	mMaxColorTextureSamples(0),
+	mMaxDepthTextureSamples(0),
+	mMaxIntegerSamples(0),
 
 	mHasAnisotropic(FALSE),
 	mHasARBEnvCombine(FALSE),
@@ -539,7 +557,20 @@ bool LLGLManager::initGL()
 	{
 		GLint num_tex_image_units;
 		glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &num_tex_image_units);
-		mNumTextureImageUnits = num_tex_image_units;
+		mNumTextureImageUnits = llmin(num_tex_image_units, 32);
+	}
+
+	if (mHasTextureMultisample)
+	{
+		glGetIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &mMaxColorTextureSamples);
+		glGetIntegerv(GL_MAX_DEPTH_TEXTURE_SAMPLES, &mMaxDepthTextureSamples);
+		glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &mMaxIntegerSamples);
+		glGetIntegerv(GL_MAX_SAMPLE_MASK_WORDS, &mMaxSampleMaskWords);
+	}
+
+	if (mHasFramebufferObject)
+	{
+		glGetIntegerv(GL_MAX_SAMPLES, &mMaxSamples);
 	}
 	
 	setToDebugGPU();
@@ -648,6 +679,14 @@ std::string LLGLManager::getRawGLString()
 	return gl_string;
 }
 
+U32 LLGLManager::getNumFBOFSAASamples(U32 samples)
+{
+	samples = llmin(samples, (U32) mMaxColorTextureSamples);
+	samples = llmin(samples, (U32) mMaxDepthTextureSamples);
+	samples = llmin(samples, (U32) 4);
+	return samples;
+}
+
 void LLGLManager::shutdownGL()
 {
 	if (mInited)
@@ -728,6 +767,7 @@ void LLGLManager::initExtensions()
 	mHasOcclusionQuery = ExtensionExists("GL_ARB_occlusion_query", gGLHExts.mSysExts);
 	mHasOcclusionQuery2 = ExtensionExists("GL_ARB_occlusion_query2", gGLHExts.mSysExts);
 	mHasVertexBufferObject = ExtensionExists("GL_ARB_vertex_buffer_object", gGLHExts.mSysExts);
+	mHasMapBufferRange = ExtensionExists("GL_ARB_map_buffer_range", gGLHExts.mSysExts);
 	mHasDepthClamp = ExtensionExists("GL_ARB_depth_clamp", gGLHExts.mSysExts) || ExtensionExists("GL_NV_depth_clamp", gGLHExts.mSysExts);
 	// mask out FBO support when packed_depth_stencil isn't there 'cause we need it for LLRenderTarget -Brad
 #ifdef GL_ARB_framebuffer_object
@@ -742,6 +782,7 @@ void LLGLManager::initExtensions()
 	mHasDrawBuffers = ExtensionExists("GL_ARB_draw_buffers", gGLHExts.mSysExts);
 	mHasBlendFuncSeparate = ExtensionExists("GL_EXT_blend_func_separate", gGLHExts.mSysExts);
 	mHasTextureRectangle = ExtensionExists("GL_ARB_texture_rectangle", gGLHExts.mSysExts);
+	mHasTextureMultisample = ExtensionExists("GL_ARB_texture_multisample", gGLHExts.mSysExts);
 #if !LL_DARWIN
 	mHasPointParameters = !mIsATI && ExtensionExists("GL_ARB_point_parameters", gGLHExts.mSysExts);
 #endif
@@ -921,6 +962,11 @@ void LLGLManager::initExtensions()
 			mHasVertexBufferObject = FALSE;
 		}
 	}
+	if (mHasMapBufferRange)
+	{
+		glMapBufferRange = (PFNGLMAPBUFFERRANGEPROC) GLH_EXT_GET_PROC_ADDRESS("glMapBufferRange");
+		glFlushMappedBufferRange = (PFNGLFLUSHMAPPEDBUFFERRANGEPROC) GLH_EXT_GET_PROC_ADDRESS("glFlushMappedBufferRange");
+	}
 	if (mHasFramebufferObject)
 	{
 		llinfos << "initExtensions() FramebufferObject-related procs..." << llendl;
@@ -953,6 +999,13 @@ void LLGLManager::initExtensions()
 	{
 		glBlendFuncSeparateEXT = (PFNGLBLENDFUNCSEPARATEEXTPROC) GLH_EXT_GET_PROC_ADDRESS("glBlendFuncSeparateEXT");
 	}
+	if (mHasTextureMultisample)
+	{
+		glTexImage2DMultisample = (PFNGLTEXIMAGE2DMULTISAMPLEPROC) GLH_EXT_GET_PROC_ADDRESS("glTexImage2DMultisample");
+		glTexImage3DMultisample = (PFNGLTEXIMAGE3DMULTISAMPLEPROC) GLH_EXT_GET_PROC_ADDRESS("glTexImage3DMultisample");
+		glGetMultisamplefv = (PFNGLGETMULTISAMPLEFVPROC) GLH_EXT_GET_PROC_ADDRESS("glGetMultisamplefv");
+		glSampleMaski = (PFNGLSAMPLEMASKIPROC) GLH_EXT_GET_PROC_ADDRESS("glSampleMaski");
+	}	
 #if (!LL_LINUX && !LL_SOLARIS) || LL_LINUX_NV_GL_HEADERS
 	// This is expected to be a static symbol on Linux GL implementations, except if we use the nvidia headers - bah
 	glDrawRangeElements = (PFNGLDRAWRANGEELEMENTSPROC)GLH_EXT_GET_PROC_ADDRESS("glDrawRangeElements");
@@ -1370,10 +1423,6 @@ void LLGLState::checkTextureChannels(const std::string& msg)
 		}
 	}
 
-	GLint maxTextureUnits = 0;
-	glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &maxTextureUnits);
-	stop_glerror();
-
 	static const char* label[] =
 	{
 		"GL_TEXTURE_2D",
@@ -1384,7 +1433,8 @@ void LLGLState::checkTextureChannels(const std::string& msg)
 		"GL_TEXTURE_GEN_T",
 		"GL_TEXTURE_GEN_Q",
 		"GL_TEXTURE_GEN_R",
-		"GL_TEXTURE_RECTANGLE_ARB"
+		"GL_TEXTURE_RECTANGLE_ARB",
+		"GL_TEXTURE_2D_MULTISAMPLE"
 	};
 
 	static GLint value[] =
@@ -1397,7 +1447,8 @@ void LLGLState::checkTextureChannels(const std::string& msg)
 		GL_TEXTURE_GEN_T,
 		GL_TEXTURE_GEN_Q,
 		GL_TEXTURE_GEN_R,
-		GL_TEXTURE_RECTANGLE_ARB
+		GL_TEXTURE_RECTANGLE_ARB,
+		GL_TEXTURE_2D_MULTISAMPLE
 	};
 
 	GLint stackDepth = 0;
@@ -1406,68 +1457,96 @@ void LLGLState::checkTextureChannels(const std::string& msg)
 	glh::matrix4f identity;
 	identity.identity();
 
-	for (GLint i = 1; i < maxTextureUnits; i++)
+	for (GLint i = 1; i < gGLManager.mNumTextureUnits; i++)
 	{
 		gGL.getTexUnit(i)->activate();
-		glClientActiveTextureARB(GL_TEXTURE0_ARB+i);
-		stop_glerror();
-		glGetIntegerv(GL_TEXTURE_STACK_DEPTH, &stackDepth);
-		stop_glerror();
 
-		if (stackDepth != 1)
+		if (i < gGLManager.mNumTextureUnits)
 		{
-			error = TRUE;
-			LL_WARNS("RenderState") << "Texture matrix stack corrupted." << LL_ENDL;
+			glClientActiveTextureARB(GL_TEXTURE0_ARB+i);
+			stop_glerror();
+			glGetIntegerv(GL_TEXTURE_STACK_DEPTH, &stackDepth);
+			stop_glerror();
 
-			if (gDebugSession)
+			if (stackDepth != 1)
 			{
-				gFailLog << "Texture matrix stack corrupted." << std::endl;
+				error = TRUE;
+				LL_WARNS("RenderState") << "Texture matrix stack corrupted." << LL_ENDL;
+
+				if (gDebugSession)
+				{
+					gFailLog << "Texture matrix stack corrupted." << std::endl;
+				}
 			}
-		}
 
-		glGetFloatv(GL_TEXTURE_MATRIX, (GLfloat*) mat.m);
-		stop_glerror();
+			glGetFloatv(GL_TEXTURE_MATRIX, (GLfloat*) mat.m);
+			stop_glerror();
 
-		if (mat != identity)
-		{
-			error = TRUE;
-			LL_WARNS("RenderState") << "Texture matrix in channel " << i << " corrupt." << LL_ENDL;
-			if (gDebugSession)
+			if (mat != identity)
 			{
-				gFailLog << "Texture matrix in channel " << i << " corrupt." << std::endl;
+				error = TRUE;
+				LL_WARNS("RenderState") << "Texture matrix in channel " << i << " corrupt." << LL_ENDL;
+				if (gDebugSession)
+				{
+					gFailLog << "Texture matrix in channel " << i << " corrupt." << std::endl;
+				}
+			}
+				
+			for (S32 j = (i == 0 ? 1 : 0); 
+				j < 9; j++)
+			{
+				if (j == 8 && !gGLManager.mHasTextureRectangle ||
+					j == 9 && !gGLManager.mHasTextureMultisample)
+				{
+					continue;
+				}
+				
+				if (glIsEnabled(value[j]))
+				{
+					error = TRUE;
+					LL_WARNS("RenderState") << "Texture channel " << i << " still has " << label[j] << " enabled." << LL_ENDL;
+					if (gDebugSession)
+					{
+						gFailLog << "Texture channel " << i << " still has " << label[j] << " enabled." << std::endl;
+					}
+				}
+				stop_glerror();
 			}
-		}
 
-		
-		for (S32 j = (i == 0 ? 1 : 0); 
-			j < (gGLManager.mHasTextureRectangle ? 9 : 8); j++)
-		{
-			if (glIsEnabled(value[j]))
+			glGetFloatv(GL_TEXTURE_MATRIX, mat.m);
+			stop_glerror();
+
+			if (mat != identity)
 			{
 				error = TRUE;
-				LL_WARNS("RenderState") << "Texture channel " << i << " still has " << label[j] << " enabled." << LL_ENDL;
+				LL_WARNS("RenderState") << "Texture matrix " << i << " is not identity." << LL_ENDL;
 				if (gDebugSession)
 				{
-					gFailLog << "Texture channel " << i << " still has " << label[j] << " enabled." << std::endl;
+					gFailLog << "Texture matrix " << i << " is not identity." << std::endl;
 				}
 			}
-			stop_glerror();
 		}
 
-		glGetFloatv(GL_TEXTURE_MATRIX, mat.m);
-		stop_glerror();
-
-		if (mat != identity)
 		{
-			error = TRUE;
-			LL_WARNS("RenderState") << "Texture matrix " << i << " is not identity." << LL_ENDL;
-			if (gDebugSession)
+			GLint tex = 0;
+			stop_glerror();
+			glGetIntegerv(GL_TEXTURE_BINDING_2D, &tex);
+			stop_glerror();
+
+			if (tex != 0)
 			{
-				gFailLog << "Texture matrix " << i << " is not identity." << std::endl;
+				error = TRUE;
+				LL_WARNS("RenderState") << "Texture channel " << i << " still has texture " << tex << " bound." << llendl;
+
+				if (gDebugSession)
+				{
+					gFailLog << "Texture channel " << i << " still has texture " << tex << " bound." << std::endl;
+				}
 			}
 		}
 	}
 
+	stop_glerror();
 	gGL.getTexUnit(0)->activate();
 	glClientActiveTextureARB(GL_TEXTURE0_ARB);
 	stop_glerror();
diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h
index 1d7ab188fcef1991a22e8e38342cdd20041433d7..d1bee001617b33f0c3447b6571c50cefeff5949b 100644
--- a/indra/llrender/llgl.h
+++ b/indra/llrender/llgl.h
@@ -83,10 +83,12 @@ class LLGLManager
 	BOOL mHasMipMapGeneration;
 	BOOL mHasCompressedTextures;
 	BOOL mHasFramebufferObject;
+	S32 mMaxSamples;
 	BOOL mHasBlendFuncSeparate;
-	
+		
 	// ARB Extensions
 	BOOL mHasVertexBufferObject;
+	BOOL mHasMapBufferRange;
 	BOOL mHasPBuffer;
 	BOOL mHasShaderObjects;
 	BOOL mHasVertexShader;
@@ -98,6 +100,11 @@ class LLGLManager
 	BOOL mHasDrawBuffers;
 	BOOL mHasDepthClamp;
 	BOOL mHasTextureRectangle;
+	BOOL mHasTextureMultisample;
+	S32 mMaxSampleMaskWords;
+	S32 mMaxColorTextureSamples;
+	S32 mMaxDepthTextureSamples;
+	S32 mMaxIntegerSamples;
 
 	// Other extensions.
 	BOOL mHasAnisotropic;
@@ -139,6 +146,7 @@ class LLGLManager
 	void printGLInfoString();
 	void getGLInfo(LLSD& info);
 
+	U32 getNumFBOFSAASamples(U32 desired_samples = 32);
 	// In ALL CAPS
 	std::string mGLVendor;
 	std::string mGLVendorShort;
diff --git a/indra/llrender/llglheaders.h b/indra/llrender/llglheaders.h
index d8140a124db1d5a02b3cf07518d07031ce2896ff..f35f329f002488b8b8ce61cd2149f462b253be47 100644
--- a/indra/llrender/llglheaders.h
+++ b/indra/llrender/llglheaders.h
@@ -68,6 +68,10 @@ extern PFNGLUNMAPBUFFERARBPROC		glUnmapBufferARB;
 extern PFNGLGETBUFFERPARAMETERIVARBPROC	glGetBufferParameterivARB;
 extern PFNGLGETBUFFERPOINTERVARBPROC	glGetBufferPointervARB;
 
+// GL_ARB_map_buffer_range
+extern PFNGLMAPBUFFERRANGEPROC			glMapBufferRange;
+extern PFNGLFLUSHMAPPEDBUFFERRANGEPROC	glFlushMappedBufferRange;
+
 // GL_ATI_vertex_array_object
 extern PFNGLNEWOBJECTBUFFERATIPROC			glNewObjectBufferATI;
 extern PFNGLISOBJECTBUFFERATIPROC			glIsObjectBufferATI;
@@ -306,6 +310,10 @@ extern PFNGLUNMAPBUFFERARBPROC		glUnmapBufferARB;
 extern PFNGLGETBUFFERPARAMETERIVARBPROC	glGetBufferParameterivARB;
 extern PFNGLGETBUFFERPOINTERVARBPROC	glGetBufferPointervARB;
 
+// GL_ARB_map_buffer_range
+extern PFNGLMAPBUFFERRANGEPROC			glMapBufferRange;
+extern PFNGLFLUSHMAPPEDBUFFERRANGEPROC	glFlushMappedBufferRange;
+
 // GL_ATI_vertex_array_object
 extern PFNGLNEWOBJECTBUFFERATIPROC			glNewObjectBufferATI;
 extern PFNGLISOBJECTBUFFERATIPROC			glIsObjectBufferATI;
@@ -474,6 +482,11 @@ extern PFNGLFRAMEBUFFERTEXTURELAYERPROC glFramebufferTextureLayer;
 //GL_ARB_draw_buffers
 extern PFNGLDRAWBUFFERSARBPROC glDrawBuffersARB;
 
+//GL_ARB_texture_multisample
+extern PFNGLTEXIMAGE2DMULTISAMPLEPROC glTexImage2DMultisample;
+extern PFNGLTEXIMAGE3DMULTISAMPLEPROC glTexImage3DMultisample;
+extern PFNGLGETMULTISAMPLEFVPROC glGetMultisamplefv;
+extern PFNGLSAMPLEMASKIPROC glSampleMaski;
 
 #elif LL_WINDOWS
 //----------------------------------------------------------------------------
@@ -506,6 +519,10 @@ extern PFNGLUNMAPBUFFERARBPROC		glUnmapBufferARB;
 extern PFNGLGETBUFFERPARAMETERIVARBPROC	glGetBufferParameterivARB;
 extern PFNGLGETBUFFERPOINTERVARBPROC	glGetBufferPointervARB;
 
+// GL_ARB_map_buffer_range
+extern PFNGLMAPBUFFERRANGEPROC			glMapBufferRange;
+extern PFNGLFLUSHMAPPEDBUFFERRANGEPROC	glFlushMappedBufferRange;
+
 // GL_ATI_vertex_array_object
 extern PFNGLNEWOBJECTBUFFERATIPROC			glNewObjectBufferATI;
 extern PFNGLISOBJECTBUFFERATIPROC			glIsObjectBufferATI;
@@ -673,6 +690,11 @@ extern PFNGLFRAMEBUFFERTEXTURELAYERPROC glFramebufferTextureLayer;
 //GL_ARB_draw_buffers
 extern PFNGLDRAWBUFFERSARBPROC glDrawBuffersARB;
 
+//GL_ARB_texture_multisample
+extern PFNGLTEXIMAGE2DMULTISAMPLEPROC glTexImage2DMultisample;
+extern PFNGLTEXIMAGE3DMULTISAMPLEPROC glTexImage3DMultisample;
+extern PFNGLGETMULTISAMPLEFVPROC glGetMultisamplefv;
+extern PFNGLSAMPLEMASKIPROC glSampleMaski;
 
 #elif LL_DARWIN
 //----------------------------------------------------------------------------
@@ -714,13 +736,55 @@ extern void glGenerateMipmapEXT(GLenum target) AVAILABLE_MAC_OS_X_VERSION_10_4_A
 
 #ifndef GL_ARB_framebuffer_object
 #define glGenerateMipmap glGenerateMipmapEXT
+#define GL_MAX_SAMPLES	0x8D57
 #endif
+
 // GL_ARB_draw_buffers
 extern void glDrawBuffersARB(GLsizei n, const GLenum* bufs) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
 
 #ifdef __cplusplus
 extern "C" {
 #endif
+
+//
+// Define map buffer range headers on Mac
+//
+#ifndef GL_ARB_map_buffer_range
+#define GL_MAP_READ_BIT                   0x0001
+#define GL_MAP_WRITE_BIT                  0x0002
+#define GL_MAP_INVALIDATE_RANGE_BIT       0x0004
+#define GL_MAP_INVALIDATE_BUFFER_BIT      0x0008
+#define GL_MAP_FLUSH_EXPLICIT_BIT         0x0010
+#define GL_MAP_UNSYNCHRONIZED_BIT         0x0020
+#endif
+
+//
+// Define multisample headers on Mac
+//
+#ifndef GL_ARB_texture_multisample
+#define GL_SAMPLE_POSITION                0x8E50
+#define GL_SAMPLE_MASK                    0x8E51
+#define GL_SAMPLE_MASK_VALUE              0x8E52
+#define GL_MAX_SAMPLE_MASK_WORDS          0x8E59
+#define GL_TEXTURE_2D_MULTISAMPLE         0x9100
+#define GL_PROXY_TEXTURE_2D_MULTISAMPLE   0x9101
+#define GL_TEXTURE_2D_MULTISAMPLE_ARRAY   0x9102
+#define GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9103
+#define GL_TEXTURE_BINDING_2D_MULTISAMPLE 0x9104
+#define GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY 0x9105
+#define GL_TEXTURE_SAMPLES                0x9106
+#define GL_TEXTURE_FIXED_SAMPLE_LOCATIONS 0x9107
+#define GL_SAMPLER_2D_MULTISAMPLE         0x9108
+#define GL_INT_SAMPLER_2D_MULTISAMPLE     0x9109
+#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE 0x910A
+#define GL_SAMPLER_2D_MULTISAMPLE_ARRAY   0x910B
+#define GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910C
+#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910D
+#define GL_MAX_COLOR_TEXTURE_SAMPLES      0x910E
+#define GL_MAX_DEPTH_TEXTURE_SAMPLES      0x910F
+#define GL_MAX_INTEGER_SAMPLES            0x9110
+#endif
+
 //
 // Define vertex buffer object headers on Mac
 //
@@ -757,7 +821,7 @@ extern "C" {
 #define GL_DYNAMIC_READ_ARB               0x88E9
 #define GL_DYNAMIC_COPY_ARB               0x88EA
 #endif
-
+	
 
 
 #ifndef GL_ARB_vertex_buffer_object
diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp
index 257bcd93802883dec2c2ca149a89fb7008ad110a..8e99f62de680ead157709bd7a895724d2b995153 100644
--- a/indra/llrender/llglslshader.cpp
+++ b/indra/llrender/llglslshader.cpp
@@ -48,6 +48,8 @@ using std::pair;
 using std::make_pair;
 using std::string;
 
+GLhandleARB LLGLSLShader::sCurBoundShader = 0;
+
 BOOL shouldChange(const LLVector4& v1, const LLVector4& v2)
 {
 	return v1 != v2;
@@ -56,7 +58,7 @@ BOOL shouldChange(const LLVector4& v1, const LLVector4& v2)
 LLShaderFeatures::LLShaderFeatures()
 : calculatesLighting(false), isShiny(false), isFullbright(false), hasWaterFog(false),
 hasTransport(false), hasSkinning(false), hasObjectSkinning(false), hasAtmospherics(false), isSpecular(false),
-hasGamma(false), hasLighting(false), calculatesAtmospherics(false)
+hasGamma(false), hasLighting(false), calculatesAtmospherics(false), mIndexedTextureChannels(0), disableTextureIndex(false)
 {
 }
 
@@ -107,16 +109,11 @@ BOOL LLGLSLShader::createShader(vector<string> * attributes,
 	// Create program
 	mProgramObject = glCreateProgramObjectARB();
 	
-	// Attach existing objects
-	if (!LLShaderMgr::instance()->attachShaderFeatures(this))
-	{
-		return FALSE;
-	}
-
+	//compile new source
 	vector< pair<string,GLenum> >::iterator fileIter = mShaderFiles.begin();
 	for ( ; fileIter != mShaderFiles.end(); fileIter++ )
 	{
-		GLhandleARB shaderhandle = LLShaderMgr::instance()->loadShaderFile((*fileIter).first, mShaderLevel, (*fileIter).second);
+		GLhandleARB shaderhandle = LLShaderMgr::instance()->loadShaderFile((*fileIter).first, mShaderLevel, (*fileIter).second, mFeatures.mIndexedTextureChannels);
 		LL_DEBUGS("ShaderLoading") << "SHADER FILE: " << (*fileIter).first << " mShaderLevel=" << mShaderLevel << LL_ENDL;
 		if (shaderhandle > 0)
 		{
@@ -128,6 +125,12 @@ BOOL LLGLSLShader::createShader(vector<string> * attributes,
 		}
 	}
 
+	// Attach existing objects
+	if (!LLShaderMgr::instance()->attachShaderFeatures(this))
+	{
+		return FALSE;
+	}
+
 	// Map attributes and uniforms
 	if (success)
 	{
@@ -149,6 +152,29 @@ BOOL LLGLSLShader::createShader(vector<string> * attributes,
 			return createShader(attributes,uniforms);
 		}
 	}
+	else if (mFeatures.mIndexedTextureChannels > 0)
+	{ //override texture channels for indexed texture rendering
+		bind();
+		S32 channel_count = mFeatures.mIndexedTextureChannels;
+
+		for (S32 i = 0; i < channel_count; i++)
+		{
+			uniform1i(llformat("tex%d", i), i);
+		}
+
+		S32 cur_tex = channel_count; //adjust any texture channels that might have been overwritten
+		for (U32 i = 0; i < mTexture.size(); i++)
+		{
+			if (mTexture[i] > -1 && mTexture[i] < channel_count)
+			{
+				llassert(cur_tex < gGLManager.mNumTextureImageUnits);
+				uniform1i(i, cur_tex);
+				mTexture[i] = cur_tex++;
+			}
+		}
+		unbind();
+	}
+
 	return success;
 }
 
@@ -293,7 +319,8 @@ void LLGLSLShader::mapUniform(GLint index, const vector<string> * uniforms)
 
 GLint LLGLSLShader::mapUniformTextureChannel(GLint location, GLenum type)
 {
-	if (type >= GL_SAMPLER_1D_ARB && type <= GL_SAMPLER_2D_RECT_SHADOW_ARB)
+	if (type >= GL_SAMPLER_1D_ARB && type <= GL_SAMPLER_2D_RECT_SHADOW_ARB ||
+		type == GL_SAMPLER_2D_MULTISAMPLE)
 	{	//this here is a texture
 		glUniform1iARB(location, mActiveTextureChannels);
 		LL_DEBUGS("ShaderLoading") << "Assigned to texture channel " << mActiveTextureChannels << LL_ENDL;
@@ -342,7 +369,7 @@ void LLGLSLShader::bind()
 	if (gGLManager.mHasShaderObjects)
 	{
 		glUseProgramObjectARB(mProgramObject);
-
+		sCurBoundShader = mProgramObject;
 		if (mUniformsDirty)
 		{
 			LLShaderMgr::instance()->updateShaderUniforms(this);
@@ -365,6 +392,7 @@ void LLGLSLShader::unbind()
 			}
 		}
 		glUseProgramObjectARB(0);
+		sCurBoundShader = 0;
 		stop_glerror();
 	}
 }
@@ -372,6 +400,7 @@ void LLGLSLShader::unbind()
 void LLGLSLShader::bindNoShader(void)
 {
 	glUseProgramObjectARB(0);
+	sCurBoundShader = 0;
 }
 
 S32 LLGLSLShader::enableTexture(S32 uniform, LLTexUnit::eTextureType mode)
diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h
index d46ddbbe183992ab791626a227e8792b67c82912..4922eb6d6725bd0eee38177a2d776231c9e27ed1 100644
--- a/indra/llrender/llglslshader.h
+++ b/indra/llrender/llglslshader.h
@@ -45,6 +45,8 @@ class LLShaderFeatures
 	bool hasObjectSkinning;
 	bool hasAtmospherics;
 	bool hasGamma;
+	S32 mIndexedTextureChannels;
+	bool disableTextureIndex;
 
 	// char numLights;
 	
@@ -64,6 +66,8 @@ class LLGLSLShader
 	
 	LLGLSLShader();
 
+	static GLhandleARB sCurBoundShader;
+
 	void unload();
 	BOOL createShader(std::vector<std::string> * attributes,
 						std::vector<std::string> * uniforms);
diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp
index d408077c683d48f97cd042b8bb366061ebacd432..60a5962234054aa34b64ea9d543759f54113beb6 100644
--- a/indra/llrender/llimagegl.cpp
+++ b/indra/llrender/llimagegl.cpp
@@ -1083,12 +1083,17 @@ void LLImageGL::generateTextures(S32 numTextures, U32 *textures)
 }
 
 // static
-void LLImageGL::deleteTextures(S32 numTextures, U32 *textures)
+void LLImageGL::deleteTextures(S32 numTextures, U32 *textures, bool immediate)
 {
 	for (S32 i = 0; i < numTextures; i++)
 	{
 		sDeadTextureList.push_back(textures[i]);
 	}
+
+	if (immediate)
+	{
+		LLImageGL::deleteDeadTextures();
+	}
 }
 
 // static
@@ -1413,11 +1418,13 @@ void LLImageGL::deleteDeadTextures()
 	{
 		GLuint tex = sDeadTextureList.front();
 		sDeadTextureList.pop_front();
-		for (int i = 0; i < gGLManager.mNumTextureUnits; i++)
+		for (int i = 0; i < gGLManager.mNumTextureImageUnits; i++)
 		{
-			if (sCurrentBoundTextures[i] == tex)
+			LLTexUnit* tex_unit = gGL.getTexUnit(i);
+
+			if (tex_unit->getCurrTexture() == tex)
 			{
-				gGL.getTexUnit(i)->unbind(LLTexUnit::TT_TEXTURE);
+				tex_unit->unbind(tex_unit->getCurrType());
 				stop_glerror();
 			}
 		}
diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h
index 6c980984c0a5facb3433480f363b3414d10b257f..2cfb15b0d9d4d03c30efa2e8de9f1be2fcafedf4 100644
--- a/indra/llrender/llimagegl.h
+++ b/indra/llrender/llimagegl.h
@@ -98,7 +98,7 @@ class LLImageGL : public LLRefCount
 	// These 3 functions currently wrap glGenTextures(), glDeleteTextures(), and glTexImage2D() 
 	// for tracking purposes and will be deprecated in the future
 	static void generateTextures(S32 numTextures, U32 *textures);
-	static void deleteTextures(S32 numTextures, U32 *textures);
+	static void deleteTextures(S32 numTextures, U32 *textures, bool immediate = false);
 	static void setManualImage(U32 target, S32 miplevel, S32 intformat, S32 width, S32 height, U32 pixformat, U32 pixtype, const void *pixels);
 
 	BOOL createGLTexture() ;
diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp
index c37139ac4c41a32da4ea4aaf364ac7a3bb40edfa..6a3f1865316fc5992809049e348e91b242e60c94 100644
--- a/indra/llrender/llrender.cpp
+++ b/indra/llrender/llrender.cpp
@@ -30,6 +30,7 @@
 
 #include "llvertexbuffer.h"
 #include "llcubemap.h"
+#include "llglslshader.h"
 #include "llimagegl.h"
 #include "llrendertarget.h"
 #include "lltexture.h"
@@ -46,14 +47,15 @@ S32	gGLViewport[4];
 U32 LLRender::sUICalls = 0;
 U32 LLRender::sUIVerts = 0;
 
-static const U32 LL_NUM_TEXTURE_LAYERS = 16; 
+static const U32 LL_NUM_TEXTURE_LAYERS = 32; 
 static const U32 LL_NUM_LIGHT_UNITS = 8;
 
 static GLenum sGLTextureType[] =
 {
 	GL_TEXTURE_2D,
 	GL_TEXTURE_RECTANGLE_ARB,
-	GL_TEXTURE_CUBE_MAP_ARB
+	GL_TEXTURE_CUBE_MAP_ARB,
+	GL_TEXTURE_2D_MULTISAMPLE
 };
 
 static GLint sGLAddressMode[] =
@@ -124,7 +126,7 @@ void LLTexUnit::refreshState(void)
 	// Per apple spec, don't call glEnable/glDisable when index exceeds max texture units
 	// http://www.mailinglistarchive.com/html/mac-opengl@lists.apple.com/2008-07/msg00653.html
 	//
-	bool enableDisable = (mIndex < gGLManager.mNumTextureUnits);
+	bool enableDisable = (mIndex < gGLManager.mNumTextureUnits) && mCurrTexType != LLTexUnit::TT_MULTISAMPLE_TEXTURE;
 		
 	if (mCurrTexType != TT_NONE)
 	{
@@ -182,8 +184,8 @@ void LLTexUnit::enable(eTextureType type)
 		mCurrTexType = type;
 
 		gGL.flush();
-		
-		if (mIndex < gGLManager.mNumTextureUnits)
+		if (type != LLTexUnit::TT_MULTISAMPLE_TEXTURE &&
+			mIndex < gGLManager.mNumTextureUnits)
 		{
 			glEnable(sGLTextureType[type]);
 		}
@@ -199,8 +201,8 @@ void LLTexUnit::disable(void)
 		activate();
 		unbind(mCurrTexType);
 		gGL.flush();
-		
-		if (mIndex < gGLManager.mNumTextureUnits)
+		if (mCurrTexType != LLTexUnit::TT_MULTISAMPLE_TEXTURE &&
+			mIndex < gGLManager.mNumTextureUnits)
 		{
 			glDisable(sGLTextureType[mCurrTexType]);
 		}
@@ -292,7 +294,7 @@ bool LLTexUnit::bind(LLImageGL* texture, bool for_rendering, bool forceBind)
 		glBindTexture(sGLTextureType[texture->getTarget()], mCurrTexture);
 		texture->updateBindStats(texture->mTextureMemory);		
 		mHasMipMaps = texture->mHasMipMaps;
-		if (texture->mTexOptionsDirty)
+		if (mIndex == 0 && texture->mTexOptionsDirty)
 		{
 			texture->mTexOptionsDirty = false;
 			setTextureAddressMode(texture->mAddressMode);
@@ -402,6 +404,7 @@ void LLTexUnit::unbind(eTextureType type)
 		activate();
 		mCurrTexture = 0;
 		glBindTexture(sGLTextureType[type], 0);
+		stop_glerror();
 	}
 }
 
@@ -423,7 +426,7 @@ void LLTexUnit::setTextureAddressMode(eTextureAddressMode mode)
 
 void LLTexUnit::setTextureFilteringOption(LLTexUnit::eTextureFilterOptions option)
 {
-	if (mIndex < 0 || mCurrTexture == 0) return;
+	if (mIndex < 0 || mCurrTexture == 0 || mCurrTexType == LLTexUnit::TT_MULTISAMPLE_TEXTURE) return;
 
 	gGL.flush();
 
diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h
index 7ba14f7b405376f77060bfb331ca18b0bb31b27a..41e7b35341d17f27b77ccd761d44bca95463e399 100644
--- a/indra/llrender/llrender.h
+++ b/indra/llrender/llrender.h
@@ -57,6 +57,7 @@ class LLTexUnit
 		TT_TEXTURE = 0,			// Standard 2D Texture
 		TT_RECT_TEXTURE,	// Non power of 2 texture
 		TT_CUBE_MAP,		// 6-sided cube map texture
+		TT_MULTISAMPLE_TEXTURE, // see GL_ARB_texture_multisample
 		TT_NONE 		// No texture type is currently enabled
 	} eTextureType;
 
diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp
index da1e94df64e5e0546a1f9fec67b8272bc67a1c5f..b6463309e111f81db4805915fe472577ec435f20 100644
--- a/indra/llrender/llrendertarget.cpp
+++ b/indra/llrender/llrendertarget.cpp
@@ -63,8 +63,7 @@ LLRenderTarget::LLRenderTarget() :
 	mUseDepth(false),
 	mRenderDepth(false),
 	mUsage(LLTexUnit::TT_TEXTURE),
-	mSamples(0),
-	mSampleBuffer(NULL)
+	mSamples(0)
 {
 }
 
@@ -73,23 +72,32 @@ LLRenderTarget::~LLRenderTarget()
 	release();
 }
 
-
-void LLRenderTarget::setSampleBuffer(LLMultisampleBuffer* buffer)
-{
-	mSampleBuffer = buffer;
-}
-
-void LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo)
+void LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo, S32 samples)
 {
 	stop_glerror();
+	
+	release();
+
 	mResX = resx;
 	mResY = resy;
 
 	mStencil = stencil;
 	mUsage = usage;
 	mUseDepth = depth;
+	mSamples = samples;
 
-	release();
+	mSamples = gGLManager.getNumFBOFSAASamples(mSamples);
+	
+	if (mSamples > 1 && gGLManager.mHasTextureMultisample)
+	{
+		mUsage = LLTexUnit::TT_MULTISAMPLE_TEXTURE;
+		//no support for multisampled stencil targets yet
+		mStencil = false;
+	}
+	else
+	{
+		mSamples = 0;
+	}
 
 	if ((sUseFBO || use_fbo) && gGLManager.mHasFramebufferObject)
 	{
@@ -146,29 +154,51 @@ void LLRenderTarget::addColorAttachment(U32 color_fmt)
 
 	stop_glerror();
 
-	LLImageGL::setManualImage(LLTexUnit::getInternalType(mUsage), 0, color_fmt, mResX, mResY, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
-
-	stop_glerror();
 
-	if (offset == 0)
+#ifdef GL_ARB_texture_multisample
+	if (mSamples > 1)
 	{
-		gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
+		glTexImage2DMultisample(LLTexUnit::getInternalType(mUsage), mSamples, color_fmt, mResX, mResY, GL_TRUE);
 	}
 	else
-	{ //don't filter data attachments
-		gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
-	}
-	if (mUsage != LLTexUnit::TT_RECT_TEXTURE)
+#else
+	llassert_always(mSamples <= 1);
+#endif
 	{
-		gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_MIRROR);
+		LLImageGL::setManualImage(LLTexUnit::getInternalType(mUsage), 0, color_fmt, mResX, mResY, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
 	}
-	else
-	{
-		// ATI doesn't support mirrored repeat for rectangular textures.
-		gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
+	
+	stop_glerror();
+
+	if (mSamples == 0)
+	{ 
+		if (offset == 0)
+		{ //use bilinear filtering on single texture render targets that aren't multisampled
+			gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
+			stop_glerror();
+		}
+		else
+		{ //don't filter data attachments
+			gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
+			stop_glerror();
+		}
+
+		if (mUsage != LLTexUnit::TT_RECT_TEXTURE)
+		{
+			gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_MIRROR);
+			stop_glerror();
+		}
+		else
+		{
+			// ATI doesn't support mirrored repeat for rectangular textures.
+			gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
+			stop_glerror();
+		}
 	}
+		
 	if (mFBO)
 	{
+		stop_glerror();
 		glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
 		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+offset,
 			LLTexUnit::getInternalType(mUsage), tex, 0);
@@ -181,6 +211,12 @@ void LLRenderTarget::addColorAttachment(U32 color_fmt)
 
 	mTex.push_back(tex);
 
+	if (gDebugGL)
+	{ //bind and unbind to validate target
+		bindTarget();
+		flush();
+	}
+
 }
 
 void LLRenderTarget::allocateDepth()
@@ -197,9 +233,20 @@ void LLRenderTarget::allocateDepth()
 	{
 		LLImageGL::generateTextures(1, &mDepth);
 		gGL.getTexUnit(0)->bindManual(mUsage, mDepth);
-		U32 internal_type = LLTexUnit::getInternalType(mUsage);
-		gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
-		LLImageGL::setManualImage(internal_type, 0, GL_DEPTH_COMPONENT32, mResX, mResY, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
+		if (mSamples == 0)
+		{
+			U32 internal_type = LLTexUnit::getInternalType(mUsage);
+			gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
+			LLImageGL::setManualImage(internal_type, 0, GL_DEPTH_COMPONENT32, mResX, mResY, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
+		}
+#ifdef GL_ARB_texture_multisample
+		else
+		{
+			glTexImage2DMultisample(LLTexUnit::getInternalType(mUsage), mSamples, GL_DEPTH_COMPONENT32, mResX, mResY, GL_TRUE);
+		}
+#else
+		llassert_always(mSamples <= 1);
+#endif
 	}
 }
 
@@ -239,6 +286,9 @@ void LLRenderTarget::shareDepthBuffer(LLRenderTarget& target)
 			glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, LLTexUnit::getInternalType(mUsage), mDepth, 0);
 			stop_glerror();
 		}
+
+		check_framebuffer_status();
+
 		glBindFramebuffer(GL_FRAMEBUFFER, 0);
 
 		target.mUseDepth = true;
@@ -256,7 +306,7 @@ void LLRenderTarget::release()
 		}
 		else
 		{
-			LLImageGL::deleteTextures(1, &mDepth);
+			LLImageGL::deleteTextures(1, &mDepth, true);
 			stop_glerror();
 		}
 		mDepth = 0;
@@ -285,11 +335,12 @@ void LLRenderTarget::release()
 
 	if (mTex.size() > 0)
 	{
-		LLImageGL::deleteTextures(mTex.size(), &mTex[0]);
+		LLImageGL::deleteTextures(mTex.size(), &mTex[0], true);
 		mTex.clear();
 	}
+	
+	mResX = mResY = 0;
 
-	mSampleBuffer = NULL;
 	sBoundTarget = NULL;
 }
 
@@ -298,34 +349,27 @@ void LLRenderTarget::bindTarget()
 	if (mFBO)
 	{
 		stop_glerror();
-		if (mSampleBuffer)
-		{
-			mSampleBuffer->bindTarget(this);
-			stop_glerror();
+		
+		glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
+		stop_glerror();
+		if (gGLManager.mHasDrawBuffers)
+		{ //setup multiple render targets
+			GLenum drawbuffers[] = {GL_COLOR_ATTACHMENT0,
+									GL_COLOR_ATTACHMENT1,
+									GL_COLOR_ATTACHMENT2,
+									GL_COLOR_ATTACHMENT3};
+			glDrawBuffersARB(mTex.size(), drawbuffers);
 		}
-		else
-		{
-			glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
-			stop_glerror();
-			if (gGLManager.mHasDrawBuffers)
-			{ //setup multiple render targets
-				GLenum drawbuffers[] = {GL_COLOR_ATTACHMENT0,
-										GL_COLOR_ATTACHMENT1,
-										GL_COLOR_ATTACHMENT2,
-										GL_COLOR_ATTACHMENT3};
-				glDrawBuffersARB(mTex.size(), drawbuffers);
-			}
 			
-			if (mTex.empty())
-			{ //no color buffer to draw to
-				glDrawBuffer(GL_NONE);
-				glReadBuffer(GL_NONE);
-			}
+		if (mTex.empty())
+		{ //no color buffer to draw to
+			glDrawBuffer(GL_NONE);
+			glReadBuffer(GL_NONE);
+		}
 
-			check_framebuffer_status();
+		check_framebuffer_status();
 
-			stop_glerror();
-		}
+		stop_glerror();
 	}
 
 	glViewport(0, 0, mResX, mResY);
@@ -407,50 +451,8 @@ void LLRenderTarget::flush(bool fetch_depth)
 	else
 	{
 		stop_glerror();
-
 		glBindFramebuffer(GL_FRAMEBUFFER, 0);
-
 		stop_glerror();
-	
-		if (mSampleBuffer)
-		{
-			LLGLEnable multisample(GL_MULTISAMPLE);
-			stop_glerror();
-			glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
-			stop_glerror();
-			check_framebuffer_status();
-			glBindFramebuffer(GL_READ_FRAMEBUFFER, mSampleBuffer->mFBO);
-			check_framebuffer_status();
-			
-			stop_glerror();
-			glBlitFramebuffer(0, 0, mResX, mResY, 0, 0, mResX, mResY, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
-			stop_glerror();		
-
-			if (mTex.size() > 1)
-			{		
-				for (U32 i = 1; i < mTex.size(); ++i)
-				{
-					glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
-										LLTexUnit::getInternalType(mUsage), mTex[i], 0);
-					stop_glerror();
-					glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, mSampleBuffer->mTex[i]);
-					stop_glerror();
-					glBlitFramebuffer(0, 0, mResX, mResY, 0, 0, mResX, mResY, GL_COLOR_BUFFER_BIT, GL_NEAREST);		
-					stop_glerror();
-				}
-
-				for (U32 i = 0; i < mTex.size(); ++i)
-				{
-					glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+i,
-										LLTexUnit::getInternalType(mUsage), mTex[i], 0);
-					stop_glerror();
-					glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+i, GL_RENDERBUFFER, mSampleBuffer->mTex[i]);
-					stop_glerror();
-				}
-			}
-		}
-
-		glBindFramebuffer(GL_FRAMEBUFFER, 0);
 	}
 }
 
@@ -467,37 +469,36 @@ void LLRenderTarget::copyContents(LLRenderTarget& source, S32 srcX0, S32 srcY0,
 		llerrs << "Cannot copy framebuffer contents for non FBO render targets." << llendl;
 	}
 
-	if (mSampleBuffer)
+	
+	if (mask == GL_DEPTH_BUFFER_BIT && source.mStencil != mStencil)
 	{
-		mSampleBuffer->copyContents(source, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
+		stop_glerror();
+		
+		glBindFramebuffer(GL_FRAMEBUFFER, source.mFBO);
+		check_framebuffer_status();
+		gGL.getTexUnit(0)->bind(this, true);
+		stop_glerror();
+		glCopyTexSubImage2D(LLTexUnit::getInternalType(mUsage), 0, srcX0, srcY0, dstX0, dstY0, dstX1, dstY1);
+		stop_glerror();
+		glBindFramebuffer(GL_FRAMEBUFFER, 0);
+		stop_glerror();
 	}
 	else
 	{
-		if (mask == GL_DEPTH_BUFFER_BIT && source.mStencil != mStencil)
-		{
-			stop_glerror();
-		
-			glBindFramebuffer(GL_FRAMEBUFFER, source.mFBO);
-			gGL.getTexUnit(0)->bind(this, true);
-			stop_glerror();
-			glCopyTexSubImage2D(LLTexUnit::getInternalType(mUsage), 0, srcX0, srcY0, dstX0, dstY0, dstX1, dstY1);
-			stop_glerror();
-			glBindFramebuffer(GL_FRAMEBUFFER, 0);
-			stop_glerror();
-		}
-		else
-		{
-			glBindFramebuffer(GL_READ_FRAMEBUFFER, source.mFBO);
-			stop_glerror();
-			glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mFBO);
-			stop_glerror();
-			check_framebuffer_status();
-			stop_glerror();
-			glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
-			stop_glerror();
-			glBindFramebuffer(GL_FRAMEBUFFER, 0);
-			stop_glerror();
-		}
+		glBindFramebuffer(GL_READ_FRAMEBUFFER, source.mFBO);
+		stop_glerror();
+		glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mFBO);
+		stop_glerror();
+		check_framebuffer_status();
+		stop_glerror();
+		glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
+		stop_glerror();
+		glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
+		stop_glerror();
+		glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
+		stop_glerror();
+		glBindFramebuffer(GL_FRAMEBUFFER, 0);
+		stop_glerror();
 	}
 }
 
@@ -540,179 +541,3 @@ void LLRenderTarget::getViewport(S32* viewport)
 	viewport[3] = mResY;
 }
 
-//==================================================
-// LLMultisampleBuffer implementation
-//==================================================
-LLMultisampleBuffer::LLMultisampleBuffer()
-{
-
-}
-
-LLMultisampleBuffer::~LLMultisampleBuffer()
-{
-	release();
-}
-
-void LLMultisampleBuffer::release()
-{
-	if (mFBO)
-	{
-		glDeleteFramebuffers(1, (GLuint *) &mFBO);
-		mFBO = 0;
-	}
-
-	if (mTex.size() > 0)
-	{
-		glDeleteRenderbuffers(mTex.size(), (GLuint *) &mTex[0]);
-		mTex.clear();
-	}
-
-	if (mDepth)
-	{
-		glDeleteRenderbuffers(1, (GLuint *) &mDepth);
-		mDepth = 0;
-	}
-}
-
-void LLMultisampleBuffer::bindTarget()
-{
-	bindTarget(this);
-}
-
-void LLMultisampleBuffer::bindTarget(LLRenderTarget* ref)
-{
-	if (!ref)
-	{
-		ref = this;
-	}
-
-	glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
-	if (gGLManager.mHasDrawBuffers)
-	{ //setup multiple render targets
-		GLenum drawbuffers[] = {GL_COLOR_ATTACHMENT0,
-								GL_COLOR_ATTACHMENT1,
-								GL_COLOR_ATTACHMENT2,
-								GL_COLOR_ATTACHMENT3};
-		glDrawBuffersARB(ref->mTex.size(), drawbuffers);
-	}
-
-	check_framebuffer_status();
-
-	glViewport(0, 0, mResX, mResY);
-
-	sBoundTarget = this;
-}
-
-void LLMultisampleBuffer::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil,  LLTexUnit::eTextureType usage, bool use_fbo )
-{
-	allocate(resx,resy,color_fmt,depth,stencil,usage,use_fbo,2);
-}
-
-void LLMultisampleBuffer::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil,  LLTexUnit::eTextureType usage, bool use_fbo, U32 samples )
-{
-	stop_glerror();
-	mResX = resx;
-	mResY = resy;
-
-	mUsage = usage;
-	mUseDepth = depth;
-	mStencil = stencil;
-
-	release();
-
-	mSamples = samples;
-	
-	if (mSamples <= 1)
-	{
-		llerrs << "Cannot create a multisample buffer with less than 2 samples." << llendl;
-	}
-
-	stop_glerror();
-
-	if ((sUseFBO || use_fbo) && gGLManager.mHasFramebufferObject)
-	{
-
-		if (depth)
-		{
-			stop_glerror();
-			allocateDepth();
-			stop_glerror();
-		}
-
-		glGenFramebuffers(1, (GLuint *) &mFBO);
-
-		glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
-
-		if (mDepth)
-		{
-			glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mDepth);
-			if (mStencil)
-			{
-				glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, mDepth);			
-			}
-		}
-	
-		stop_glerror();
-		glBindFramebuffer(GL_FRAMEBUFFER, 0);
-		stop_glerror();
-	}
-
-	addColorAttachment(color_fmt);
-}
-
-void LLMultisampleBuffer::addColorAttachment(U32 color_fmt)
-{
-	if (color_fmt == 0)
-	{
-		return;
-	}
-
-	U32 offset = mTex.size();
-	if (offset >= 4 ||
-		(offset > 0 && (mFBO == 0 || !gGLManager.mHasDrawBuffers)))
-	{
-		llerrs << "Too many color attachments!" << llendl;
-	}
-
-	U32 tex;
-	glGenRenderbuffers(1, &tex);
-	
-	glBindRenderbuffer(GL_RENDERBUFFER, tex);
-	glRenderbufferStorageMultisample(GL_RENDERBUFFER, mSamples, color_fmt, mResX, mResY);
-	stop_glerror();
-
-	if (mFBO)
-	{
-		glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
-		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+offset, GL_RENDERBUFFER, tex);
-		stop_glerror();
-		GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
-		switch (status)
-		{
-		case GL_FRAMEBUFFER_COMPLETE:
-			break;
-		default:
-			llerrs << "WTF? " << std::hex << status << llendl;
-			break;
-		}
-
-		glBindFramebuffer(GL_FRAMEBUFFER, 0);
-	}
-
-	mTex.push_back(tex);
-}
-
-void LLMultisampleBuffer::allocateDepth()
-{
-	glGenRenderbuffers(1, (GLuint* ) &mDepth);
-	glBindRenderbuffer(GL_RENDERBUFFER, mDepth);
-	if (mStencil)
-	{
-		glRenderbufferStorageMultisample(GL_RENDERBUFFER, mSamples, GL_DEPTH24_STENCIL8, mResX, mResY);	
-	}
-	else
-	{
-		glRenderbufferStorageMultisample(GL_RENDERBUFFER, mSamples, GL_DEPTH_COMPONENT16, mResX, mResY);	
-	}
-}
-
diff --git a/indra/llrender/llrendertarget.h b/indra/llrender/llrendertarget.h
index 12dd1c8b90f85a734e9a108226a4e85552588798..094b58b562cabcab805cbfc7415c7805714d9940 100644
--- a/indra/llrender/llrendertarget.h
+++ b/indra/llrender/llrendertarget.h
@@ -71,10 +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, bool stencil, LLTexUnit::eTextureType usage = LLTexUnit::TT_TEXTURE, bool use_fbo = FALSE);
-
-	//provide this render target with a multisample resource.
-	void setSampleBuffer(LLMultisampleBuffer* buffer);
+	void allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage = LLTexUnit::TT_TEXTURE, bool use_fbo = false, S32 samples = 0);
 
 	//add color buffer attachment
 	//limit of 4 color attachments per render target
@@ -141,7 +138,6 @@ class LLRenderTarget
 	static LLRenderTarget* getCurrentBoundTarget() { return sBoundTarget; }
 
 protected:
-	friend class LLMultisampleBuffer;
 	U32 mResX;
 	U32 mResY;
 	std::vector<U32> mTex;
@@ -152,26 +148,8 @@ class LLRenderTarget
 	bool mRenderDepth;
 	LLTexUnit::eTextureType mUsage;
 	U32 mSamples;
-	LLMultisampleBuffer* mSampleBuffer;
-
-	static LLRenderTarget* sBoundTarget;
 	
-};
-
-class LLMultisampleBuffer : public LLRenderTarget
-{
-public:
-	LLMultisampleBuffer();
-	virtual ~LLMultisampleBuffer();
-
-	virtual void release();
-
-	virtual void bindTarget();
-	void bindTarget(LLRenderTarget* ref);
-	virtual void allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo);
-	void allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo, U32 samples);
-	virtual void addColorAttachment(U32 color_fmt);
-	virtual void allocateDepth();
+	static LLRenderTarget* sBoundTarget;
 };
 
 #endif //!LL_MESA_HEADLESS
diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp
index 98a0a93084e1762281ba02da11ec5daff2490b6e..e51ef8cfe7f5e0d9e9017a2baab1fa8412af4c2c 100644
--- a/indra/llrender/llshadermgr.cpp
+++ b/indra/llrender/llshadermgr.cpp
@@ -209,17 +209,39 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
 	
 		if (features->hasWaterFog)
 		{
-			if (!shader->attachObject("lighting/lightWaterF.glsl"))
+			if (features->disableTextureIndex)
 			{
-				return FALSE;
+				if (!shader->attachObject("lighting/lightWaterNonIndexedF.glsl"))
+				{
+					return FALSE;
+				}
+			}
+			else 
+			{
+				if (!shader->attachObject("lighting/lightWaterF.glsl"))
+				{
+					return FALSE;
+				}
+				shader->mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits-1;
 			}
 		}
 		
 		else
 		{
-			if (!shader->attachObject("lighting/lightF.glsl"))
+			if (features->disableTextureIndex)
 			{
-				return FALSE;
+				if (!shader->attachObject("lighting/lightNonIndexedF.glsl"))
+				{
+					return FALSE;
+				}
+			}
+			else 
+			{
+				if (!shader->attachObject("lighting/lightF.glsl"))
+				{
+					return FALSE;
+				}
+				shader->mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits-1;
 			}
 		}		
 	}
@@ -230,32 +252,76 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
 	
 		if (features->isShiny && features->hasWaterFog)
 		{
-			if (!shader->attachObject("lighting/lightFullbrightShinyWaterF.glsl"))
+			if (features->disableTextureIndex)
 			{
-				return FALSE;
+				if (!shader->attachObject("lighting/lightFullbrightShinyWaterNonIndexedF.glsl"))
+				{
+					return FALSE;
+				}
+			}
+			else 
+			{
+				if (!shader->attachObject("lighting/lightFullbrightShinyWaterF.glsl"))
+				{
+					return FALSE;
+				}
+				shader->mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits-1;
 			}
 		}
 		else if (features->hasWaterFog)
 		{
-			if (!shader->attachObject("lighting/lightFullbrightWaterF.glsl"))
+			if (features->disableTextureIndex)
 			{
-				return FALSE;
+				if (!shader->attachObject("lighting/lightFullbrightWaterNonIndexedF.glsl"))
+				{
+					return FALSE;
+				}
+			}
+			else 
+			{
+				if (!shader->attachObject("lighting/lightFullbrightWaterF.glsl"))
+				{
+					return FALSE;
+				}
+				shader->mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits-1;
 			}
 		}
 		
 		else if (features->isShiny)
 		{
-			if (!shader->attachObject("lighting/lightFullbrightShinyF.glsl"))
+			if (features->disableTextureIndex)
 			{
-				return FALSE;
+				if (!shader->attachObject("lighting/lightFullbrightShinyNonIndexedF.glsl"))
+				{
+					return FALSE;
+				}
+			}
+			else 
+			{
+				if (!shader->attachObject("lighting/lightFullbrightShinyF.glsl"))
+				{
+					return FALSE;
+				}
+				shader->mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits-1;
 			}
 		}
 		
 		else
 		{
-			if (!shader->attachObject("lighting/lightFullbrightF.glsl"))
+			if (features->disableTextureIndex)
 			{
-				return FALSE;
+				if (!shader->attachObject("lighting/lightFullbrightNonIndexedF.glsl"))
+				{
+					return FALSE;
+				}
+			}
+			else 
+			{
+				if (!shader->attachObject("lighting/lightFullbrightF.glsl"))
+				{
+					return FALSE;
+				}
+				shader->mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits-1;
 			}
 		}
 	}
@@ -266,17 +332,39 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
 	
 		if (features->hasWaterFog)
 		{
-			if (!shader->attachObject("lighting/lightShinyWaterF.glsl"))
+			if (features->disableTextureIndex)
 			{
-				return FALSE;
+				if (!shader->attachObject("lighting/lightShinyWaterNonIndexedF.glsl"))
+				{
+					return FALSE;
+				}
+			}
+			else 
+			{
+				if (!shader->attachObject("lighting/lightShinyWaterF.glsl"))
+				{
+					return FALSE;
+				}
+				shader->mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits-1;
 			}
 		}
 		
 		else 
 		{
-			if (!shader->attachObject("lighting/lightShinyF.glsl"))
+			if (features->disableTextureIndex)
 			{
-				return FALSE;
+				if (!shader->attachObject("lighting/lightShinyNonIndexedF.glsl"))
+				{
+					return FALSE;
+				}
+			}
+			else 
+			{
+				if (!shader->attachObject("lighting/lightShinyF.glsl"))
+				{
+					return FALSE;
+				}
+				shader->mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits-1;
 			}
 		}
 	}
@@ -320,7 +408,7 @@ void LLShaderMgr::dumpObjectLog(GLhandleARB ret, BOOL warns)
 	}
 }
 
-GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type)
+GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, S32 texture_index_channels)
 {
 	GLenum error = GL_NO_ERROR;
 	if (gDebugGL)
@@ -374,6 +462,73 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
 	GLcharARB* text[1024];
 	GLuint count = 0;
 
+	//set version to 1.20
+	text[count++] = strdup("#version 120\n");
+
+	//copy preprocessor definitions into buffer
+	for (std::map<std::string,std::string>::iterator iter = mDefinitions.begin(); iter != mDefinitions.end(); ++iter)
+	{
+		std::string define = "#define " + iter->first + " " + iter->second + "\n";
+		text[count++] = (GLcharARB *) strdup(define.c_str());
+	}
+
+	if (texture_index_channels > 0 && type == GL_FRAGMENT_SHADER_ARB)
+	{
+		//use specified number of texture channels for indexed texture rendering
+
+		/* prepend shader code that looks like this:
+
+		uniform sampler2D tex0;
+		uniform sampler2D tex1;
+		uniform sampler2D tex2;
+		.
+		.
+		.
+		uniform sampler2D texN;
+		
+		varying float vary_texture_index;
+
+		vec4 diffuseLookup(vec2 texcoord)
+		{
+			switch (int(vary_texture_index+0.25))
+			{
+				case 0: return texture2D(tex0, texcoord);
+				case 1: return texture2D(tex1, texcoord);
+				case 2: return texture2D(tex2, texcoord);
+				.
+				.
+				.
+				case N: return texture2D(texN, texcoord);
+			}
+
+			return vec4(0,0,0,0);
+		}
+		*/
+
+		//uniform declartion
+		for (S32 i = 0; i < texture_index_channels; ++i)
+		{
+			std::string decl = llformat("uniform sampler2D tex%d;\n", i);
+			text[count++] = strdup(decl.c_str());
+		}
+
+		text[count++] = strdup("varying float vary_texture_index;\n");
+		text[count++] = strdup("vec4 diffuseLookup(vec2 texcoord)\n");
+		text[count++] = strdup("{\n");
+		text[count++] = strdup("\tswitch (int(vary_texture_index+0.25))\n");
+		text[count++] = strdup("\t{\n");
+		
+		//switch body
+		for (S32 i = 0; i < texture_index_channels; ++i)
+		{
+			std::string case_str = llformat("\t\tcase %d: return texture2D(tex%d, texcoord);\n", i, i);
+			text[count++] = strdup(case_str.c_str());
+		}
+
+		text[count++] = strdup("\t}\n");
+		text[count++] = strdup("\treturn vec4(0,0,0,0);\n");
+		text[count++] = strdup("}\n");
+	}
 
 	//copy file into memory
 	while( fgets((char *)buff, 1024, file) != NULL && count < LL_ARRAY_SIZE(buff) ) 
@@ -457,7 +612,7 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
 		if (shader_level > 1)
 		{
 			shader_level--;
-			return loadShaderFile(filename,shader_level,type);
+			return loadShaderFile(filename,shader_level,type,texture_index_channels);
 		}
 		LL_WARNS("ShaderLoading") << "Failed to load " << filename << LL_ENDL;	
 	}
diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h
index c54c4608d7f043a9822b35272291d294569ffe15..2f3010381127f281d78f3bdf5c2739865a9ba65c 100644
--- a/indra/llrender/llshadermgr.h
+++ b/indra/llrender/llshadermgr.h
@@ -43,7 +43,7 @@ class LLShaderMgr
 	void dumpObjectLog(GLhandleARB ret, BOOL warns = TRUE);
 	BOOL	linkProgramObject(GLhandleARB obj, BOOL suppress_errors = FALSE);
 	BOOL	validateProgramObject(GLhandleARB obj);
-	GLhandleARB loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type);
+	GLhandleARB loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, S32 texture_index_channels = -1);
 
 	// Implemented in the application to actually point to the shader directory.
 	virtual std::string getShaderDirPrefix(void) = 0; // Pure Virtual
@@ -60,6 +60,9 @@ class LLShaderMgr
 
 	std::vector<std::string> mReservedUniforms;
 
+	//preprocessor definitions (name/value)
+	std::map<std::string, std::string> mDefinitions;
+
 protected:
 
 	// our parameter manager singleton instance
diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp
index 8c9171ccf45cedbb24fe1cb3890948f17093f190..4a0b964e616bb06644ed4bbe6b5f011ca2fdb021 100644
--- a/indra/llrender/llvertexbuffer.cpp
+++ b/indra/llrender/llvertexbuffer.cpp
@@ -934,8 +934,26 @@ void LLVertexBuffer::allocateClientIndexBuffer()
 	}
 }
 
+bool expand_region(LLVertexBuffer::MappedRegion& region, S32 index, S32 count)
+{
+	S32 end = index+count;
+	S32 region_end = region.mIndex+region.mCount;
+	
+	if (end < region.mIndex ||
+		index > region_end)
+	{ //gap exists, do not merge
+		return false;
+	}
+
+	S32 new_end = llmax(end, region_end);
+	S32 new_index = llmin(index, region.mIndex);
+	region.mIndex = new_index;
+	region.mCount = new_end-new_index;
+	return true;
+}
+
 // Map for data access
-U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 access)
+U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_range)
 {
 	LLMemType mt2(LLMemType::MTYPE_VERTEX_MAP_BUFFER);
 	if (mFinal)
@@ -947,8 +965,45 @@ U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 access)
 		llerrs << "LLVertexBuffer::mapVertexBuffer() called on unallocated buffer." << llendl;
 	}
 		
-	if (!mVertexLocked && useVBOs())
+	if (useVBOs())
 	{
+
+		if (sDisableVBOMapping || gGLManager.mHasMapBufferRange)
+		{
+			if (count == -1)
+			{
+				count = mNumVerts-index;
+			}
+
+			bool mapped = false;
+			//see if range is already mapped
+			for (U32 i = 0; i < mMappedVertexRegions.size(); ++i)
+			{
+				MappedRegion& region = mMappedVertexRegions[i];
+				if (region.mType == type)
+				{
+					if (expand_region(region, index, count))
+					{
+						mapped = true;
+						break;
+					}
+				}
+			}
+
+			if (!mapped)
+			{
+				//not already mapped, map new region
+				MappedRegion region(type, !sDisableVBOMapping && map_range ? -1 : index, count);
+				mMappedVertexRegions.push_back(region);
+			}
+		}
+
+		if (mVertexLocked && map_range)
+		{
+			llerrs << "Attempted to map a specific range of a buffer that was already mapped." << llendl;
+		}
+
+		if (!mVertexLocked)
 		{
 			LLMemType mt_v(LLMemType::MTYPE_VERTEX_MAP_BUFFER_VERTICES);
 			setBuffer(0, type);
@@ -957,61 +1012,95 @@ U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 access)
 
 			if(sDisableVBOMapping)
 			{
+				map_range = false;
 				allocateClientVertexBuffer() ;
 			}
 			else
 			{
-				U8* src = (U8*) glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
+				U8* src = NULL;
+#ifdef GL_ARB_map_buffer_range
+				if (gGLManager.mHasMapBufferRange)
+				{
+					if (map_range)
+					{
+						S32 offset = mOffsets[type] + sTypeSize[type]*index;
+						S32 length = (sTypeSize[type]*count+0xF) & ~0xF;
+						src = (U8*) glMapBufferRange(GL_ARRAY_BUFFER_ARB, offset, length, GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT | GL_MAP_INVALIDATE_RANGE_BIT);
+					}
+					else
+					{
+						src = (U8*) glMapBufferRange(GL_ARRAY_BUFFER_ARB, 0, mSize, GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT);
+					}
+				}
+				else
+#else
+				llassert_always(!gGLManager.mHasMapBufferRange);
+#endif
+				{
+					map_range = false;
+					src = (U8*) glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
+				}
+
 				mMappedData = LL_NEXT_ALIGNED_ADDRESS<U8>(src);
 				mAlignedOffset = mMappedData - src;
 			
 				stop_glerror();
 			}
-		}
-		
-		
-		if (!mMappedData)
-		{
-			log_glerror();
-
-			//check the availability of memory
-			U32 avail_phy_mem, avail_vir_mem;
-			LLMemoryInfo::getAvailableMemoryKB(avail_phy_mem, avail_vir_mem) ;
-			llinfos << "Available physical mwmory(KB): " << avail_phy_mem << llendl ; 
-			llinfos << "Available virtual memory(KB): " << avail_vir_mem << llendl;
-
-			if(!sDisableVBOMapping)
-			{			
-				//--------------------
-				//print out more debug info before crash
-				llinfos << "vertex buffer size: (num verts : num indices) = " << getNumVerts() << " : " << getNumIndices() << llendl ;
-				GLint size ;
-				glGetBufferParameterivARB(GL_ARRAY_BUFFER_ARB, GL_BUFFER_SIZE_ARB, &size) ;
-				llinfos << "GL_ARRAY_BUFFER_ARB size is " << size << llendl ;
-				//--------------------
+				
+			if (!mMappedData)
+			{
+				log_glerror();
+
+				//check the availability of memory
+				U32 avail_phy_mem, avail_vir_mem;
+				LLMemoryInfo::getAvailableMemoryKB(avail_phy_mem, avail_vir_mem) ;
+				llinfos << "Available physical mwmory(KB): " << avail_phy_mem << llendl ; 
+				llinfos << "Available virtual memory(KB): " << avail_vir_mem << llendl;
+
+				if(!sDisableVBOMapping)
+				{			
+					//--------------------
+					//print out more debug info before crash
+					llinfos << "vertex buffer size: (num verts : num indices) = " << getNumVerts() << " : " << getNumIndices() << llendl ;
+					GLint size ;
+					glGetBufferParameterivARB(GL_ARRAY_BUFFER_ARB, GL_BUFFER_SIZE_ARB, &size) ;
+					llinfos << "GL_ARRAY_BUFFER_ARB size is " << size << llendl ;
+					//--------------------
+
+					GLint buff;
+					glGetIntegerv(GL_ARRAY_BUFFER_BINDING_ARB, &buff);
+					if ((GLuint)buff != mGLBuffer)
+					{
+						llerrs << "Invalid GL vertex buffer bound: " << buff << llendl;
+					}
 
-				GLint buff;
-				glGetIntegerv(GL_ARRAY_BUFFER_BINDING_ARB, &buff);
-				if ((GLuint)buff != mGLBuffer)
+							
+					llerrs << "glMapBuffer returned NULL (no vertex data)" << llendl;
+				}
+				else
 				{
-					llerrs << "Invalid GL vertex buffer bound: " << buff << llendl;
+					llerrs << "memory allocation for vertex data failed." << llendl ;
 				}
-
-							
-				llerrs << "glMapBuffer returned NULL (no vertex data)" << llendl;
-			}
-			else
-			{
-				llerrs << "memory allocation for vertex data failed." << llendl ;
 			}
+			sMappedCount++;
 		}
-		sMappedCount++;
+	}
+	else
+	{
+		map_range = false;
 	}
 	
-	return mMappedData;
+	if (map_range && !sDisableVBOMapping)
+	{
+		return mMappedData;
+	}
+	else
+	{
+		return mMappedData+mOffsets[type]+sTypeSize[type]*index;
+	}
 }
 
-U8* LLVertexBuffer::mapIndexBuffer(S32 access)
+U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range)
 {
 	LLMemType mt2(LLMemType::MTYPE_VERTEX_MAP_BUFFER);
 	if (mFinal)
@@ -1023,8 +1112,41 @@ U8* LLVertexBuffer::mapIndexBuffer(S32 access)
 		llerrs << "LLVertexBuffer::mapIndexBuffer() called on unallocated buffer." << llendl;
 	}
 
-	if (!mIndexLocked && useVBOs())
+	if (useVBOs())
 	{
+		if (sDisableVBOMapping || gGLManager.mHasMapBufferRange)
+		{
+			if (count == -1)
+			{
+				count = mNumIndices-index;
+			}
+
+			bool mapped = false;
+			//see if range is already mapped
+			for (U32 i = 0; i < mMappedIndexRegions.size(); ++i)
+			{
+				MappedRegion& region = mMappedIndexRegions[i];
+				if (expand_region(region, index, count))
+				{
+					mapped = true;
+					break;
+				}
+			}
+
+			if (!mapped)
+			{
+				//not already mapped, map new region
+				MappedRegion region(TYPE_INDEX, !sDisableVBOMapping && map_range ? -1 : index, count);
+				mMappedIndexRegions.push_back(region);
+			}
+		}
+
+		if (mIndexLocked && map_range)
+		{
+			llerrs << "Attempted to map a specific range of a buffer that was already mapped." << llendl;
+		}
+
+		if (!mIndexLocked)
 		{
 			LLMemType mt_v(LLMemType::MTYPE_VERTEX_MAP_BUFFER_INDICES);
 
@@ -1034,12 +1156,36 @@ U8* LLVertexBuffer::mapIndexBuffer(S32 access)
 
 			if(sDisableVBOMapping)
 			{
+				map_range = false;
 				allocateClientIndexBuffer() ;
 			}
 			else
 			{
-				U8* src = (U8*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
-				mMappedIndexData = LL_NEXT_ALIGNED_ADDRESS<U8>(src);
+				U8* src = NULL;
+#ifdef GL_ARB_map_buffer_range
+				if (gGLManager.mHasMapBufferRange)
+				{
+					if (map_range)
+					{
+						S32 offset = sizeof(U16)*index;
+						S32 length = sizeof(U16)*count;
+						src = (U8*) glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER_ARB, offset, length, GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT | GL_MAP_INVALIDATE_RANGE_BIT);
+					}
+					else
+					{
+						src = (U8*) glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, sizeof(U16)*mNumIndices, GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT);
+					}
+				}
+				else
+#else
+				llassert_always(!gGLManager.mHasMapBufferRange);
+#endif
+				{
+					map_range = false;
+					src = (U8*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
+				}
+
+				mMappedIndexData = src; //LL_NEXT_ALIGNED_ADDRESS<U8>(src);
 				mAlignedIndexOffset = mMappedIndexData - src;
 				stop_glerror();
 			}
@@ -1068,31 +1214,81 @@ U8* LLVertexBuffer::mapIndexBuffer(S32 access)
 
 		sMappedCount++;
 	}
+	else
+	{
+		map_range = false;
+	}
 
-	return mMappedIndexData ;
+	if (map_range && !sDisableVBOMapping)
+	{
+		return mMappedIndexData;
+	}
+	else
+	{
+		return mMappedIndexData + sizeof(U16)*index;
+	}
 }
 
 void LLVertexBuffer::unmapBuffer(S32 type)
 {
 	LLMemType mt2(LLMemType::MTYPE_VERTEX_UNMAP_BUFFER);
-	if (!useVBOs())
+	if (!useVBOs() || type == -2)
 	{
 		return ; //nothing to unmap
 	}
 
 	bool updated_all = false ;
+
 	if (mMappedData && mVertexLocked && type != TYPE_INDEX)
 	{
 		updated_all = (mIndexLocked && type < 0) ; //both vertex and index buffers done updating
 
 		if(sDisableVBOMapping)
 		{
-			stop_glerror();
-			glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, getSize(), mMappedData);
-			stop_glerror();
+			if (!mMappedVertexRegions.empty())
+			{
+				stop_glerror();
+				for (U32 i = 0; i < mMappedVertexRegions.size(); ++i)
+				{
+					const MappedRegion& region = mMappedVertexRegions[i];
+					S32 offset = region.mIndex >= 0 ? mOffsets[region.mType]+sTypeSize[region.mType]*region.mIndex : 0;
+					S32 length = sTypeSize[region.mType]*region.mCount;
+					glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, offset, length, mMappedData+offset);
+					stop_glerror();
+				}
+
+				mMappedVertexRegions.clear();
+			}
+			else
+			{
+				stop_glerror();
+				glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, getSize(), mMappedData);
+				stop_glerror();
+			}
 		}
 		else
 		{
+#ifdef GL_ARB_map_buffer_range
+			if (gGLManager.mHasMapBufferRange)
+			{
+				if (!mMappedVertexRegions.empty())
+				{
+					stop_glerror();
+					for (U32 i = 0; i < mMappedVertexRegions.size(); ++i)
+					{
+						const MappedRegion& region = mMappedVertexRegions[i];
+						S32 offset = region.mIndex >= 0 ? mOffsets[region.mType]+sTypeSize[region.mType]*region.mIndex : 0;
+						S32 length = sTypeSize[region.mType]*region.mCount;
+						glFlushMappedBufferRange(GL_ARRAY_BUFFER_ARB, offset, length);
+						stop_glerror();
+					}
+
+					mMappedVertexRegions.clear();
+				}
+			}
+#else
+			llassert_always(!gGLManager.mHasMapBufferRange);
+#endif
 			stop_glerror();
 			glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
 			stop_glerror();
@@ -1103,17 +1299,53 @@ void LLVertexBuffer::unmapBuffer(S32 type)
 		mVertexLocked = FALSE ;
 		sMappedCount--;
 	}
-
-	if(mMappedIndexData && mIndexLocked && (type < 0 || type == TYPE_INDEX))
+	
+	if (mMappedIndexData && mIndexLocked && (type < 0 || type == TYPE_INDEX))
 	{
 		if(sDisableVBOMapping)
 		{
-			stop_glerror();
-			glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, getIndicesSize(), mMappedIndexData);
-			stop_glerror();
+			if (!mMappedIndexRegions.empty())
+			{
+				for (U32 i = 0; i < mMappedIndexRegions.size(); ++i)
+				{
+					const MappedRegion& region = mMappedIndexRegions[i];
+					S32 offset = region.mIndex >= 0 ? sizeof(U16)*region.mIndex : 0;
+					S32 length = sizeof(U16)*region.mCount;
+					glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, offset, length, mMappedIndexData+offset);
+					stop_glerror();
+				}
+
+				mMappedIndexRegions.clear();
+			}
+			else
+			{
+				stop_glerror();
+				glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, getIndicesSize(), mMappedIndexData);
+				stop_glerror();
+			}
 		}
 		else
 		{
+#ifdef GL_ARB_map_buffer_range
+			if (gGLManager.mHasMapBufferRange)
+			{
+				if (!mMappedIndexRegions.empty())
+				{
+					for (U32 i = 0; i < mMappedIndexRegions.size(); ++i)
+					{
+						const MappedRegion& region = mMappedIndexRegions[i];
+						S32 offset = region.mIndex >= 0 ? sizeof(U16)*region.mIndex : 0;
+						S32 length = sizeof(U16)*region.mCount;
+						glFlushMappedBufferRange(GL_ELEMENT_ARRAY_BUFFER_ARB, offset, length);
+						stop_glerror();
+					}
+
+					mMappedIndexRegions.clear();
+				}
+			}
+#else
+			llassert_always(!gGLManager.mHasMapBufferRange);
+#endif
 			stop_glerror();
 			glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB);
 			stop_glerror();
@@ -1152,19 +1384,19 @@ template <class T,S32 type> struct VertexBufferStrider
 	typedef LLStrider<T> strider_t;
 	static bool get(LLVertexBuffer& vbo, 
 					strider_t& strider, 
-					S32 index)
+					S32 index, S32 count, bool map_range)
 	{
 		if (type == LLVertexBuffer::TYPE_INDEX)
 		{
-			S32 stride = sizeof(T);
+			U8* ptr = vbo.mapIndexBuffer(index, count, map_range);
 
-			if (vbo.mapIndexBuffer() == NULL)
+			if (ptr == NULL)
 			{
 				llwarns << "mapIndexBuffer failed!" << llendl;
 				return FALSE;
 			}
 
-			strider = (T*)(vbo.getMappedIndices() + index*stride);
+			strider = (T*)ptr;
 			strider.setStride(0);
 			return TRUE;
 		}
@@ -1172,13 +1404,15 @@ template <class T,S32 type> struct VertexBufferStrider
 		{
 			S32 stride = LLVertexBuffer::sTypeSize[type];
 
-			if (vbo.mapVertexBuffer(type) == NULL)
+			U8* ptr = vbo.mapVertexBuffer(type, index, count, map_range);
+
+			if (ptr == NULL)
 			{
 				llwarns << "mapVertexBuffer failed!" << llendl;
 				return FALSE;
 			}
 
-			strider = (T*)(vbo.getMappedData() + vbo.getOffset(type)+index*stride);
+			strider = (T*)ptr;
 			strider.setStride(stride);
 			return TRUE;
 		}
@@ -1190,55 +1424,48 @@ template <class T,S32 type> struct VertexBufferStrider
 	}
 };
 
-bool LLVertexBuffer::getVertexStrider(LLStrider<LLVector3>& strider, S32 index)
-{
-	return VertexBufferStrider<LLVector3,TYPE_VERTEX>::get(*this, strider, index);
-}
-bool LLVertexBuffer::getIndexStrider(LLStrider<U16>& strider, S32 index)
+bool LLVertexBuffer::getVertexStrider(LLStrider<LLVector3>& strider, S32 index, S32 count, bool map_range)
 {
-	return VertexBufferStrider<U16,TYPE_INDEX>::get(*this, strider, index);
+	return VertexBufferStrider<LLVector3,TYPE_VERTEX>::get(*this, strider, index, count, map_range);
 }
-bool LLVertexBuffer::getTexCoord0Strider(LLStrider<LLVector2>& strider, S32 index)
+bool LLVertexBuffer::getIndexStrider(LLStrider<U16>& strider, S32 index, S32 count, bool map_range)
 {
-	return VertexBufferStrider<LLVector2,TYPE_TEXCOORD0>::get(*this, strider, index);
+	return VertexBufferStrider<U16,TYPE_INDEX>::get(*this, strider, index, count, map_range);
 }
-bool LLVertexBuffer::getTexCoord1Strider(LLStrider<LLVector2>& strider, S32 index)
+bool LLVertexBuffer::getTexCoord0Strider(LLStrider<LLVector2>& strider, S32 index, S32 count, bool map_range)
 {
-	return VertexBufferStrider<LLVector2,TYPE_TEXCOORD1>::get(*this, strider, index);
+	return VertexBufferStrider<LLVector2,TYPE_TEXCOORD0>::get(*this, strider, index, count, map_range);
 }
-/*bool LLVertexBuffer::getTexCoord2Strider(LLStrider<LLVector2>& strider, S32 index)
+bool LLVertexBuffer::getTexCoord1Strider(LLStrider<LLVector2>& strider, S32 index, S32 count, bool map_range)
 {
-	return VertexBufferStrider<LLVector2,TYPE_TEXCOORD2>::get(*this, strider, index);
+	return VertexBufferStrider<LLVector2,TYPE_TEXCOORD1>::get(*this, strider, index, count, map_range);
 }
-bool LLVertexBuffer::getTexCoord3Strider(LLStrider<LLVector2>& strider, S32 index)
-{
-	return VertexBufferStrider<LLVector2,TYPE_TEXCOORD3>::get(*this, strider, index);
-}*/
-bool LLVertexBuffer::getNormalStrider(LLStrider<LLVector3>& strider, S32 index)
+
+bool LLVertexBuffer::getNormalStrider(LLStrider<LLVector3>& strider, S32 index, S32 count, bool map_range)
 {
-	return VertexBufferStrider<LLVector3,TYPE_NORMAL>::get(*this, strider, index);
+	return VertexBufferStrider<LLVector3,TYPE_NORMAL>::get(*this, strider, index, count, map_range);
 }
-bool LLVertexBuffer::getBinormalStrider(LLStrider<LLVector3>& strider, S32 index)
+bool LLVertexBuffer::getBinormalStrider(LLStrider<LLVector3>& strider, S32 index, S32 count, bool map_range)
 {
-	return VertexBufferStrider<LLVector3,TYPE_BINORMAL>::get(*this, strider, index);
+	return VertexBufferStrider<LLVector3,TYPE_BINORMAL>::get(*this, strider, index, count, map_range);
 }
-bool LLVertexBuffer::getColorStrider(LLStrider<LLColor4U>& strider, S32 index)
+bool LLVertexBuffer::getColorStrider(LLStrider<LLColor4U>& strider, S32 index, S32 count, bool map_range)
 {
-	return VertexBufferStrider<LLColor4U,TYPE_COLOR>::get(*this, strider, index);
+	return VertexBufferStrider<LLColor4U,TYPE_COLOR>::get(*this, strider, index, count, map_range);
 }
-bool LLVertexBuffer::getWeightStrider(LLStrider<F32>& strider, S32 index)
+bool LLVertexBuffer::getWeightStrider(LLStrider<F32>& strider, S32 index, S32 count, bool map_range)
 {
-	return VertexBufferStrider<F32,TYPE_WEIGHT>::get(*this, strider, index);
+	return VertexBufferStrider<F32,TYPE_WEIGHT>::get(*this, strider, index, count, map_range);
 }
 
-bool LLVertexBuffer::getWeight4Strider(LLStrider<LLVector4>& strider, S32 index)
+bool LLVertexBuffer::getWeight4Strider(LLStrider<LLVector4>& strider, S32 index, S32 count, bool map_range)
 {
-	return VertexBufferStrider<LLVector4,TYPE_WEIGHT4>::get(*this, strider, index);
+	return VertexBufferStrider<LLVector4,TYPE_WEIGHT4>::get(*this, strider, index, count, map_range);
 }
 
-bool LLVertexBuffer::getClothWeightStrider(LLStrider<LLVector4>& strider, S32 index)
+bool LLVertexBuffer::getClothWeightStrider(LLStrider<LLVector4>& strider, S32 index, S32 count, bool map_range)
 {
-	return VertexBufferStrider<LLVector4,TYPE_CLOTHWEIGHT>::get(*this, strider, index);
+	return VertexBufferStrider<LLVector4,TYPE_CLOTHWEIGHT>::get(*this, strider, index, count, map_range);
 }
 
 //----------------------------------------------------------------------------
@@ -1497,17 +1724,16 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask) const
 	}
 	if (data_mask & MAP_VERTEX)
 	{
-		glVertexPointer(3,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_VERTEX], (void*)(base + 0));
+		if (data_mask & MAP_TEXTURE_INDEX)
+		{
+			glVertexPointer(4,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_VERTEX], (void*)(base + 0));
+		}
+		else
+		{
+			glVertexPointer(3,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_VERTEX], (void*)(base + 0));
+		}
 	}
 
 	llglassertok();
 }
 
-void LLVertexBuffer::markDirty(U32 vert_index, U32 vert_count, U32 indices_index, U32 indices_count)
-{
-	// TODO: use GL_APPLE_flush_buffer_range here
-	/*if (useVBOs() && !mFilthy)
-	{
-	
-	}*/
-}
diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h
index a9f22193f87a4601aa25b94da85ad4fdb7ded85b..aa5df305a66f0eda5bf8b31caa304311f454e4d1 100644
--- a/indra/llrender/llvertexbuffer.h
+++ b/indra/llrender/llvertexbuffer.h
@@ -77,6 +77,18 @@ class LLVBOPool : public LLGLNamePool
 class LLVertexBuffer : public LLRefCount
 {
 public:
+	class MappedRegion
+	{
+	public:
+		S32 mType;
+		S32 mIndex;
+		S32 mCount;
+		
+		MappedRegion(S32 type, S32 index, S32 count)
+			: mType(type), mIndex(index), mCount(count)
+		{ }	
+	};
+
 	LLVertexBuffer(const LLVertexBuffer& rhs)
 	{
 		*this = rhs;
@@ -130,6 +142,9 @@ class LLVertexBuffer : public LLRefCount
 		TYPE_CLOTHWEIGHT,
 		TYPE_MAX,
 		TYPE_INDEX,
+		
+		//no actual additional data, but indicates position.w is texture index
+		TYPE_TEXTURE_INDEX,
 	};
 	enum {
 		MAP_VERTEX = (1<<TYPE_VERTEX),
@@ -144,6 +159,7 @@ class LLVertexBuffer : public LLRefCount
 		MAP_WEIGHT = (1<<TYPE_WEIGHT),
 		MAP_WEIGHT4 = (1<<TYPE_WEIGHT4),
 		MAP_CLOTHWEIGHT = (1<<TYPE_CLOTHWEIGHT),
+		MAP_TEXTURE_INDEX = (1<<TYPE_TEXTURE_INDEX),
 	};
 	
 protected:
@@ -173,8 +189,8 @@ class LLVertexBuffer : public LLRefCount
 	LLVertexBuffer(U32 typemask, S32 usage);
 	
 	// map for data access
-	U8*		mapVertexBuffer(S32 type = -1, S32 access = -1);
-	U8*		mapIndexBuffer(S32 access = -1);
+	U8*		mapVertexBuffer(S32 type, S32 index, S32 count, bool map_range);
+	U8*		mapIndexBuffer(S32 index, S32 count, bool map_range);
 
 	// set for rendering
 	virtual void	setBuffer(U32 data_mask, S32 type = -1); 	// calls  setupVertexBuffer() if data_mask is not 0
@@ -189,16 +205,16 @@ class LLVertexBuffer : public LLRefCount
 	//   vb->getNormalStrider(norms);
 	//   setVertsNorms(verts, norms);
 	//   vb->unmapBuffer();
-	bool getVertexStrider(LLStrider<LLVector3>& strider, S32 index=0);
-	bool getIndexStrider(LLStrider<U16>& strider, S32 index=0);
-	bool getTexCoord0Strider(LLStrider<LLVector2>& strider, S32 index=0);
-	bool getTexCoord1Strider(LLStrider<LLVector2>& strider, S32 index=0);
-	bool getNormalStrider(LLStrider<LLVector3>& strider, S32 index=0);
-	bool getBinormalStrider(LLStrider<LLVector3>& strider, S32 index=0);
-	bool getColorStrider(LLStrider<LLColor4U>& strider, S32 index=0);
-	bool getWeightStrider(LLStrider<F32>& strider, S32 index=0);
-	bool getWeight4Strider(LLStrider<LLVector4>& strider, S32 index=0);
-	bool getClothWeightStrider(LLStrider<LLVector4>& strider, S32 index=0);
+	bool getVertexStrider(LLStrider<LLVector3>& strider, S32 index=0, S32 count = -1, bool map_range = false);
+	bool getIndexStrider(LLStrider<U16>& strider, S32 index=0, S32 count = -1, bool map_range = false);
+	bool getTexCoord0Strider(LLStrider<LLVector2>& strider, S32 index=0, S32 count = -1, bool map_range = false);
+	bool getTexCoord1Strider(LLStrider<LLVector2>& strider, S32 index=0, S32 count = -1, bool map_range = false);
+	bool getNormalStrider(LLStrider<LLVector3>& strider, S32 index=0, S32 count = -1, bool map_range = false);
+	bool getBinormalStrider(LLStrider<LLVector3>& strider, S32 index=0, S32 count = -1, bool map_range = false);
+	bool getColorStrider(LLStrider<LLColor4U>& strider, S32 index=0, S32 count = -1, bool map_range = false);
+	bool getWeightStrider(LLStrider<F32>& strider, S32 index=0, S32 count = -1, bool map_range = false);
+	bool getWeight4Strider(LLStrider<LLVector4>& strider, S32 index=0, S32 count = -1, bool map_range = false);
+	bool getClothWeightStrider(LLStrider<LLVector4>& strider, S32 index=0, S32 count = -1, bool map_range = false);
 	
 	BOOL isEmpty() const					{ return mEmpty; }
 	BOOL isLocked() const					{ return mVertexLocked || mIndexLocked; }
@@ -218,8 +234,6 @@ class LLVertexBuffer : public LLRefCount
 	S32 getOffset(S32 type) const			{ return mOffsets[type]; }
 	S32 getUsage() const					{ return mUsage; }
 
-	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 drawArrays(U32 mode, U32 offset, U32 count) const;
 	void drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indices_offset) const;
@@ -253,20 +267,8 @@ class LLVertexBuffer : public LLRefCount
 	BOOL	mDynamicSize;	// if TRUE, buffer has been resized at least once (and should be padded)
 	S32		mOffsets[TYPE_MAX];
 
-	class DirtyRegion
-	{
-	public:
-		U32 mIndex;
-		U32 mCount;
-		U32 mIndicesIndex;
-		U32 mIndicesCount;
-
-		DirtyRegion(U32 vi, U32 vc, U32 ii, U32 ic)
-			: mIndex(vi), mCount(vc), mIndicesIndex(ii), mIndicesCount(ic)
-		{ }	
-	};
-
-	std::vector<DirtyRegion> mDirtyRegions; //vector of dirty regions to rebuild
+	std::vector<MappedRegion> mMappedVertexRegions;
+	std::vector<MappedRegion> mMappedIndexRegions;
 
 public:
 	static S32 sCount;
diff --git a/indra/llui/llresmgr.cpp b/indra/llui/llresmgr.cpp
index 39385786bc826ee2f7552d8086794dda6767fa62..820e7cb26af36021a92d63c11645700fab644a1c 100644
--- a/indra/llui/llresmgr.cpp
+++ b/indra/llui/llresmgr.cpp
@@ -337,7 +337,7 @@ LLLocale::LLLocale(const std::string& locale_string)
 	char* new_locale_string = setlocale( LC_ALL, locale_string.c_str());
 	if ( new_locale_string == NULL)
 	{
-		llwarns << "Failed to set locale " << locale_string << llendl;
+		LL_WARNS_ONCE("LLLocale") << "Failed to set locale " << locale_string << LL_ENDL;
 		setlocale(LC_ALL, SYSTEM_LOCALE.c_str());
 	}
 	//else
diff --git a/indra/llui/llspinctrl.cpp b/indra/llui/llspinctrl.cpp
index 6b4e9cf923f86c94fc805274144087775dc6e19b..15a7438ec956796567cfcbcfe427c6e8e009d70d 100644
--- a/indra/llui/llspinctrl.cpp
+++ b/indra/llui/llspinctrl.cpp
@@ -52,6 +52,7 @@ LLSpinCtrl::Params::Params()
 :	label_width("label_width"),
 	decimal_digits("decimal_digits"),
 	allow_text_entry("allow_text_entry", true),
+	label_wrap("label_wrap", false),
 	text_enabled_color("text_enabled_color"),
 	text_disabled_color("text_disabled_color"),
 	up_button("up_button"),
@@ -80,6 +81,7 @@ LLSpinCtrl::LLSpinCtrl(const LLSpinCtrl::Params& p)
 	{
 		LLRect label_rect( 0, centered_top, label_width, centered_bottom );
 		LLTextBox::Params params;
+		params.wrap(p.label_wrap);
 		params.name("SpinCtrl Label");
 		params.rect(label_rect);
 		params.initial_value(p.label());
diff --git a/indra/llui/llspinctrl.h b/indra/llui/llspinctrl.h
index 8960971594d84b737bda01d907057584d09eba6e..d197084e38fac9c3c572a012d8577daf6e64e333 100644
--- a/indra/llui/llspinctrl.h
+++ b/indra/llui/llspinctrl.h
@@ -44,6 +44,7 @@ class LLSpinCtrl
 		Optional<S32> label_width;
 		Optional<U32> decimal_digits;
 		Optional<bool> allow_text_entry;
+		Optional<bool> label_wrap;
 
 		Optional<LLUIColor> text_enabled_color;
 		Optional<LLUIColor> text_disabled_color;
diff --git a/indra/newview/app_settings/logcontrol.xml b/indra/newview/app_settings/logcontrol.xml
index 937c4e4c6a02e8bb764527a8e2ea407c6f3b7631..9f4e89691f1ba3dc5628c63dcbce4a028983d77c 100644
--- a/indra/newview/app_settings/logcontrol.xml
+++ b/indra/newview/app_settings/logcontrol.xml
@@ -20,6 +20,7 @@
 					<key>tags</key>
 						<array>
 							<string>AppInit</string>
+              <string>Capabilities</string>
 							<string>SystemInfo</string>
 							<string>TextureCache</string>
 							<string>AppCache</string>
@@ -43,6 +44,7 @@
 						<array>
 							<!-- sample entry for debugging a specific item	-->
 <!--						<string>Voice</string>							-->
+              <string>Capabilities</string>
 						</array>
 				</map>
 			</array>
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
old mode 100644
new mode 100755
index ac6ea0f86006e70e7c90df1aec2f3c12d5213a40..76fecdf05edfd7d313d64d4abad9b1165999f53b
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -5589,10 +5589,10 @@
     <key>Value</key>
     <real>0</real>
   </map>
-  <key>MeshUseWholeModelUpload</key>
+  <key>MeshUploadLogXML</key>
   <map>
     <key>Comment</key>
-    <string>Upload model in its entirety instead of mesh-by-mesh (new caps)</string>
+    <string>Verbose XML logging on mesh upload</string>
     <key>Persist</key>
     <integer>1</integer>
     <key>Type</key>
@@ -5600,6 +5600,17 @@
     <key>Value</key>
     <real>0</real>
   </map>
+  <key>MeshUploadFakeErrors</key>
+  <map>
+    <key>Comment</key>
+    <string>Force upload errors (for testing)</string>
+    <key>Persist</key>
+    <integer>1</integer>
+    <key>Type</key>
+    <string>S32</string>
+    <key>Value</key>
+    <real>0</real>
+  </map>
   <key>MigrateCacheDirectory</key>
     <map>
       <key>Comment</key>
@@ -7102,7 +7113,76 @@
       <key>Value</key>
       <integer>1</integer>
     </map>
-    <key>RenderAnisotropic</key>
+
+  <key>OctreeMaxNodeCapacity</key>
+  <map>
+    <key>Comment</key>
+    <string>Maximum number of elements to store in a single octree node</string>
+    <key>Persist</key>
+    <integer>1</integer>
+    <key>Type</key>
+    <string>U32</string>
+    <key>Value</key>
+    <integer>128</integer>
+  </map>
+
+  <key>OctreeStaticObjectSizeFactor</key>
+  <map>
+    <key>Comment</key>
+    <string>Multiplier on static object size for determining octree node size </string>
+    <key>Persist</key>
+    <integer>1</integer>
+    <key>Type</key>
+    <string>S32</string>
+    <key>Value</key>
+    <integer>4</integer>
+  </map>
+
+  <key>OctreeAlphaDistanceFactor</key>
+  <map>
+    <key>Comment</key>
+    <string>Multiplier on alpha object distance for determining octree node size </string>
+    <key>Persist</key>
+    <integer>1</integer>
+    <key>Type</key>
+    <string>Vector3</string>
+    <key>Value</key>
+    <array>
+      <real>0.1</real>
+      <real>0.0</real>
+      <real>0.0</real>
+    </array>
+  </map>
+
+  <key>OctreeAttachmentSizeFactor</key>
+  <map>
+    <key>Comment</key>
+    <string>Multiplier on attachment size for determining octree node size </string>
+    <key>Persist</key>
+    <integer>1</integer>
+    <key>Type</key>
+    <string>S32</string>
+    <key>Value</key>
+    <integer>4</integer>
+  </map>
+
+  <key>OctreeDistanceFactor</key>
+  <map>
+    <key>Comment</key>
+    <string>Multiplier on distance for determining octree node size </string>
+    <key>Persist</key>
+    <integer>1</integer>
+    <key>Type</key>
+    <string>Vector3</string>
+    <key>Value</key>
+    <array>
+      <real>0.01</real>
+      <real>0.0</real>
+      <real>0.0</real>
+    </array>
+  </map>
+
+  <key>RenderAnisotropic</key>
     <map>
       <key>Comment</key>
       <string>Render textures using anisotropic filtering</string>
@@ -7199,7 +7279,7 @@
       <key>Type</key>
       <string>F32</string>
       <key>Value</key>
-      <integer>1.0</integer>
+      <real>1.0</real>
     </map>
     <key>RenderAvatarVP</key>
     <map>
@@ -7455,6 +7535,17 @@
       <key>Value</key>
       <integer>0</integer>
     </map>
+  <key>RenderMaxTextureIndex</key>
+  <map>
+    <key>Comment</key>
+    <string>Maximum texture index to use for indexed texture rendering.</string>
+    <key>Persist</key>
+    <integer>1</integer>
+    <key>Type</key>
+    <string>U32</string>
+    <key>Value</key>
+    <integer>6</integer>
+  </map>
     <key>RenderDebugTextureBind</key>
     <map>
       <key>Comment</key>
@@ -8600,7 +8691,7 @@
     <key>Type</key>
     <string>S32</string>
     <key>Value</key>
-    <integer>8192</integer>
+    <integer>65536</integer>
   </map>
     <key>RenderMaxVBOSize</key>
     <map>
@@ -8942,7 +9033,7 @@
       <key>Type</key>
       <string>Boolean</string>
       <key>Value</key>
-      <integer>1</integer>
+      <integer>0</integer>
     </map>
   <key>RenderUseStreamVBO</key>
   <map>
@@ -9052,7 +9143,7 @@
     <key>Type</key>
     <string>F32</string>
     <key>Value</key>
-    <real>3.0</real>
+    <real>2.0</real>
   </map>
   <key>MeshThreadCount</key>
   <map>
diff --git a/indra/newview/app_settings/shaders/class1/avatar/avatarF.glsl b/indra/newview/app_settings/shaders/class1/avatar/avatarF.glsl
index 3f6b8b33238fc1fd4b228575109fdd4eac825552..b0fa0ddd3ed7b3fc2f5a1a7a81d49b413c924e2d 100644
--- a/indra/newview/app_settings/shaders/class1/avatar/avatarF.glsl
+++ b/indra/newview/app_settings/shaders/class1/avatar/avatarF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 void default_lighting();
 
diff --git a/indra/newview/app_settings/shaders/class1/avatar/avatarSkinV.glsl b/indra/newview/app_settings/shaders/class1/avatar/avatarSkinV.glsl
index 1ad87badfe17dfe8b21a8beecdbbe25a9d911c9d..d9f29ced4fd1a90b66f5b1775bce85ae036c74b5 100644
--- a/indra/newview/app_settings/shaders/class1/avatar/avatarSkinV.glsl
+++ b/indra/newview/app_settings/shaders/class1/avatar/avatarSkinV.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 attribute vec4 weight;  //1
 
diff --git a/indra/newview/app_settings/shaders/class1/avatar/avatarV.glsl b/indra/newview/app_settings/shaders/class1/avatar/avatarV.glsl
index a15846f192f66b5356bec88cc4f3a38bf6100eb4..2796222c68d74e577ba584fb93068e6cb1474476 100644
--- a/indra/newview/app_settings/shaders/class1/avatar/avatarV.glsl
+++ b/indra/newview/app_settings/shaders/class1/avatar/avatarV.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol);
 mat4 getSkinnedTransform();
diff --git a/indra/newview/app_settings/shaders/class1/avatar/eyeballF.glsl b/indra/newview/app_settings/shaders/class1/avatar/eyeballF.glsl
index 05fe10037227c1826e430b14ec3af7cbb877ee7d..d86ef19a0466e90f9f50dcaac93d50599dfafef6 100644
--- a/indra/newview/app_settings/shaders/class1/avatar/eyeballF.glsl
+++ b/indra/newview/app_settings/shaders/class1/avatar/eyeballF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 void default_lighting();
 
diff --git a/indra/newview/app_settings/shaders/class1/avatar/eyeballV.glsl b/indra/newview/app_settings/shaders/class1/avatar/eyeballV.glsl
index 4b8a7604a1b6ffdaa45b6077fc20b14bab0ad861..2eb814bd91e1bb4a8fd603e9085ef8b26a2156c2 100644
--- a/indra/newview/app_settings/shaders/class1/avatar/eyeballV.glsl
+++ b/indra/newview/app_settings/shaders/class1/avatar/eyeballV.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 vec4 calcLightingSpecular(vec3 pos, vec3 norm, vec4 color, inout vec4 specularColor, vec4 baseCol);
 void calcAtmospherics(vec3 inPositionEye);
diff --git a/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl b/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl
index ef823c28b1c48693e7e8151fefe8baade88988cf..7613e50dca936c87195d4cc5bc8101737ef70dad 100644
--- a/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl
+++ b/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl
@@ -5,7 +5,7 @@
  * $License$
  */
 
-#version 120
+
 
 attribute vec4 object_weight;  
 
diff --git a/indra/newview/app_settings/shaders/class1/avatar/pickAvatarF.glsl b/indra/newview/app_settings/shaders/class1/avatar/pickAvatarF.glsl
index 27ac59a840f53adf2bb805c9c324f2a5afd097b9..2638351e962adfcb7ade3f413959e97c22dd569f 100644
--- a/indra/newview/app_settings/shaders/class1/avatar/pickAvatarF.glsl
+++ b/indra/newview/app_settings/shaders/class1/avatar/pickAvatarF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 uniform sampler2D diffuseMap;
 
diff --git a/indra/newview/app_settings/shaders/class1/avatar/pickAvatarV.glsl b/indra/newview/app_settings/shaders/class1/avatar/pickAvatarV.glsl
index f1aa549a478c7798b99ae7088db26840ff07c232..86b189b282cd9997bc3f65f76d5d133d1011ce06 100644
--- a/indra/newview/app_settings/shaders/class1/avatar/pickAvatarV.glsl
+++ b/indra/newview/app_settings/shaders/class1/avatar/pickAvatarV.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 mat4 getSkinnedTransform();
 
diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl
index 3b12a07a27df958a59de4e0dcc10e488b9bdb9ce..4a0815a163867fe5482b5d412bc15287970e5774 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl
@@ -5,13 +5,14 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 #extension GL_ARB_texture_rectangle : enable
 
-uniform sampler2D diffuseMap;
 uniform sampler2DRect depthMap;
 
+vec4 diffuseLookup(vec2 texcoord);
+
 uniform mat4 shadow_matrix[6];
 uniform vec4 shadow_clip;
 uniform vec2 screen_res;
@@ -47,7 +48,7 @@ void main()
 	
 	vec4 pos = vec4(vary_position, 1.0);
 	
-	vec4 diff= texture2D(diffuseMap, gl_TexCoord[0].xy);
+	vec4 diff= diffuseLookup(gl_TexCoord[0].xy);
 
 	vec4 col = vec4(vary_ambient + vary_directional.rgb, gl_Color.a);
 	vec4 color = diff * col;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaNonIndexedF.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaNonIndexedF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..b0d029dbf41b129df3b62f310683c7ddc7465ffc
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/alphaNonIndexedF.glsl
@@ -0,0 +1,67 @@
+/** 
+ * @file alphaF.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+ 
+
+
+#extension GL_ARB_texture_rectangle : enable
+
+uniform sampler2DRect depthMap;
+uniform sampler2D diffuseMap;
+
+
+uniform mat4 shadow_matrix[6];
+uniform vec4 shadow_clip;
+uniform vec2 screen_res;
+
+vec3 atmosLighting(vec3 light);
+vec3 scaleSoftClip(vec3 light);
+
+varying vec3 vary_ambient;
+varying vec3 vary_directional;
+varying vec3 vary_fragcoord;
+varying vec3 vary_position;
+varying vec3 vary_pointlight_col;
+
+uniform mat4 inv_proj;
+
+vec4 getPosition(vec2 pos_screen)
+{
+	float depth = texture2DRect(depthMap, pos_screen.xy).a;
+	vec2 sc = pos_screen.xy*2.0;
+	sc /= screen_res;
+	sc -= vec2(1.0,1.0);
+	vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+	vec4 pos = inv_proj * ndc;
+	pos /= pos.w;
+	pos.w = 1.0;
+	return pos;
+}
+
+void main() 
+{
+	vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5;
+	frag *= screen_res;
+	
+	vec4 pos = vec4(vary_position, 1.0);
+	
+	vec4 diff= texture2D(diffuseMap,gl_TexCoord[0].xy);
+
+	vec4 col = vec4(vary_ambient + vary_directional.rgb, gl_Color.a);
+	vec4 color = diff * col;
+	
+	color.rgb = atmosLighting(color.rgb);
+
+	color.rgb = scaleSoftClip(color.rgb);
+
+	color.rgb += diff.rgb * vary_pointlight_col.rgb;
+
+	gl_FragColor = color;
+	//gl_FragColor = vec4(1,0,1,1);
+	//gl_FragColor = vec4(1,0,1,1)*shadow;
+	
+}
+
diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaSkinnedV.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaSkinnedV.glsl
index 65d9209983e74e5ea677ede25935b472b4484cf2..ac3f7189c2f79b0f4f3629e980682f3c22465a67 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/alphaSkinnedV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/alphaSkinnedV.glsl
@@ -5,7 +5,7 @@
  * $License$
  */
  
-#version 120
+
 
 vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol);
 mat4 getObjectSkinnedTransform();
diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl
index 2691fc8dedb64b85a8cc3ecac5660e3c842fc23b..44cb78e9147dcd50df06f50799f4d0ef17b284ae 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
 
-#version 120
+
 
 vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol);
 void calcAtmospherics(vec3 inPositionEye);
@@ -23,6 +23,7 @@ varying vec3 vary_fragcoord;
 varying vec3 vary_position;
 varying vec3 vary_light;
 varying vec3 vary_pointlight_col;
+varying float vary_texture_index;
 
 uniform float near_clip;
 uniform float shadow_offset;
@@ -61,11 +62,13 @@ float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, floa
 void main()
 {
 	//transform vertex
-	gl_Position = ftransform(); 
+	vec4 vert = vec4(gl_Vertex.xyz, 1.0);
+	vary_texture_index = gl_Vertex.w;
+	gl_Position = gl_ModelViewProjectionMatrix * vert; 
 	
 	gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
 	
-	vec4 pos = (gl_ModelViewMatrix * gl_Vertex);
+	vec4 pos = (gl_ModelViewMatrix * vert);
 	vec3 norm = normalize(gl_NormalMatrix * gl_Normal);
 	
 	float dp_directional_light = max(0.0, dot(norm, gl_LightSource[0].position.xyz));
@@ -102,7 +105,7 @@ void main()
 
 	gl_FogFragCoord = pos.z;
 	
-	pos = gl_ModelViewProjectionMatrix * gl_Vertex;
+	pos = gl_ModelViewProjectionMatrix * vert;
 	vary_fragcoord.xyz = pos.xyz + vec3(0,0,near_clip);
 	
 }
diff --git a/indra/newview/app_settings/shaders/class1/deferred/attachmentShadowF.glsl b/indra/newview/app_settings/shaders/class1/deferred/attachmentShadowF.glsl
index 164322c3a732a87e16d84edd104876370e095931..870d593311f5a34d66bff7aedd3583f2252eaecc 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/attachmentShadowF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/attachmentShadowF.glsl
@@ -5,7 +5,7 @@
  * $License$
  */
 
-#version 120
+
 
 uniform sampler2D diffuseMap;
 
diff --git a/indra/newview/app_settings/shaders/class1/deferred/attachmentShadowV.glsl b/indra/newview/app_settings/shaders/class1/deferred/attachmentShadowV.glsl
index 5ae41cb73093d99f0e6c5ba60f3c109729057c6d..c7a4f86727178f55ff1b66bc4e0ef20eac070887 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/attachmentShadowV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/attachmentShadowV.glsl
@@ -5,7 +5,7 @@
  * $License$
  */
 
-#version 120
+
 
 mat4 getObjectSkinnedTransform();
 
diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl
index a012cb50304c7283716ca09638d5c3ef6bda7b23..68e4055cf228188145d6519e273d93990e7cc387 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol);
 mat4 getSkinnedTransform();
diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarEyesV.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarEyesV.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..7bc78fe407408575b036c1e4bb235c9de19fb654
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/avatarEyesV.glsl
@@ -0,0 +1,21 @@
+/** 
+ * @file avatarEyesV.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+ 
+
+
+varying vec3 vary_normal;
+
+void main()
+{
+	//transform vertex
+	gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; 
+	gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
+	
+	vary_normal = normalize(gl_NormalMatrix * gl_Normal);
+
+	gl_FrontColor = gl_Color;
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl
index 9748727147d62107ee9ed3f708852446d785cacc..326861809313b7e2d7fd9c21b5a15b241a5dcffa 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 uniform sampler2D diffuseMap;
 
diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarShadowF.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarShadowF.glsl
index 1b7ae0688841b60691e279a18efd5f6d3baa9ec8..78986ab12efd65784a256b0fcf3406388e60e0ea 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/avatarShadowF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/avatarShadowF.glsl
@@ -5,14 +5,17 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 uniform sampler2D diffuseMap;
 
+varying vec4 post_pos;
 
 void main() 
 {
 	//gl_FragColor = vec4(1,1,1,gl_Color.a * texture2D(diffuseMap, gl_TexCoord[0].xy).a);
 	gl_FragColor = vec4(1,1,1,1);
+
+	gl_FragDepth = max(post_pos.z/post_pos.w*0.5+0.5, 0.0);
 }
 
diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarShadowV.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarShadowV.glsl
index cf6579a40d4c608193da404644ad33ba1594fa9c..f177fcd8f11b6fc0d9463126c6dd54641c5b277c 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/avatarShadowV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/avatarShadowV.glsl
@@ -5,12 +5,14 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 mat4 getSkinnedTransform();
 
 attribute vec4 weight;
 
+varying vec4 post_pos;
+
 void main()
 {
 	gl_TexCoord[0] = gl_MultiTexCoord0;
@@ -30,8 +32,9 @@ void main()
 	norm = normalize(norm);
 	
 	pos = gl_ProjectionMatrix * pos;
-	pos.z = max(pos.z, -pos.w+0.01);
-	gl_Position = pos;
+	post_pos = pos;
+
+	gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w);
 	
 	gl_FrontColor = gl_Color;
 }
diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarV.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarV.glsl
index 69c93799b5d358b612c5be0a18150c6b193fb777..7eac11287a2b7e2f7666f90b10a5a137cfdeb8f7 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/avatarV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/avatarV.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 mat4 getSkinnedTransform();
 
diff --git a/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl
index d9f021b114f4919327c70f62c967750f98887d22..8c75c8045af71835637efb9be7fff0db707ad34f 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 #extension GL_ARB_texture_rectangle : enable
 
@@ -26,7 +26,7 @@ uniform vec2 screen_res;
 
 vec4 getPosition(vec2 pos_screen)
 {
-	float depth = texture2DRect(depthMap, pos_screen.xy).a;
+	float depth = texture2DRect(depthMap, pos_screen.xy).r;
 	vec2 sc = pos_screen.xy*2.0;
 	sc /= screen_res;
 	sc -= vec2(1.0,1.0);
@@ -39,7 +39,7 @@ vec4 getPosition(vec2 pos_screen)
 
 void main() 
 {
-        vec2 tc = vary_fragcoord.xy;
+    vec2 tc = vary_fragcoord.xy;
 	vec3 norm = texture2DRect(normalMap, tc).xyz;
 	norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm
 	vec3 pos = getPosition(tc).xyz;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/blurLightMSF.glsl b/indra/newview/app_settings/shaders/class1/deferred/blurLightMSF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..6ca51377c167fade71505ece7e3f9729a5e70557
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/blurLightMSF.glsl
@@ -0,0 +1,113 @@
+/** 
+ * @file blurLightF.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+ 
+
+
+#extension GL_ARB_texture_rectangle : enable
+#extension GL_ARB_texture_multisample : enable
+
+uniform sampler2DMS depthMap;
+uniform sampler2DMS normalMap;
+uniform sampler2DRect lightMap;
+
+uniform float dist_factor;
+uniform float blur_size;
+uniform vec2 delta;
+uniform vec3 kern[4];
+uniform float kern_scale;
+
+varying vec2 vary_fragcoord;
+
+uniform mat4 inv_proj;
+uniform vec2 screen_res;
+
+vec3 texture2DMS3(sampler2DMS tex, ivec2 tc)
+{
+	vec3 ret = vec3(0,0,0);
+	for (int i = 0; i < samples; i++)
+	{
+		ret += texelFetch(tex, tc, i).rgb;
+	}
+
+	return ret/samples;
+}
+
+float texture2DMS1(sampler2DMS tex, ivec2 tc)
+{
+	float ret = 0;
+	for (int i = 0; i < samples; i++)
+	{
+		ret += texelFetch(tex, tc, i).r;
+	}
+
+	return ret/samples;
+}
+
+vec4 getPosition(ivec2 pos_screen)
+{
+	float depth = texture2DMS1(depthMap, pos_screen.xy);
+	vec2 sc = pos_screen.xy*2.0;
+	sc /= screen_res;
+	sc -= vec2(1.0,1.0);
+	vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+	vec4 pos = inv_proj * ndc;
+	pos /= pos.w;
+	pos.w = 1.0;
+	return pos;
+}
+
+void main() 
+{
+    vec2 tc = vary_fragcoord.xy;
+	ivec2 itc = ivec2(tc);
+
+	vec3 norm = texture2DMS3(normalMap, itc).xyz;
+	norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm
+	vec3 pos = getPosition(itc).xyz;
+	vec4 ccol = texture2DRect(lightMap, tc).rgba;
+	
+	vec2 dlt = kern_scale * delta / (1.0+norm.xy*norm.xy);
+	dlt /= max(-pos.z*dist_factor, 1.0);
+	
+	vec2 defined_weight = kern[0].xy; // special case the first (centre) sample's weight in the blur; we have to sample it anyway so we get it for 'free'
+	vec4 col = defined_weight.xyxx * ccol;
+
+	// relax tolerance according to distance to avoid speckling artifacts, as angles and distances are a lot more abrupt within a small screen area at larger distances
+	float pointplanedist_tolerance_pow2 = pos.z*pos.z*0.00005;
+
+	// perturb sampling origin slightly in screen-space to hide edge-ghosting artifacts where smoothing radius is quite large
+	tc += ( (mod(tc.x+tc.y,2) - 0.5) * kern[1].z * dlt * 0.5 );
+
+	for (int i = 1; i < 4; i++)
+	{
+		vec2 samptc = tc + kern[i].z*dlt;
+		vec3 samppos = getPosition(ivec2(samptc)).xyz; 
+		float d = dot(norm.xyz, samppos.xyz-pos.xyz);// dist from plane
+		if (d*d <= pointplanedist_tolerance_pow2)
+		{
+			col += texture2DRect(lightMap, samptc)*kern[i].xyxx;
+			defined_weight += kern[i].xy;
+		}
+	}
+	for (int i = 1; i < 4; i++)
+	{
+		vec2 samptc = vec2(tc - kern[i].z*dlt);
+		vec3 samppos = getPosition(ivec2(samptc)).xyz; 
+		float d = dot(norm.xyz, samppos.xyz-pos.xyz);// dist from plane
+		if (d*d <= pointplanedist_tolerance_pow2)
+		{
+			col += texture2DRect(lightMap, samptc)*kern[i].xyxx;
+			defined_weight += kern[i].xy;
+		}
+	}
+
+	col /= defined_weight.xyxx;
+	col.y *= col.y;
+
+	gl_FragColor = col;
+}
+
diff --git a/indra/newview/app_settings/shaders/class1/deferred/blurLightV.glsl b/indra/newview/app_settings/shaders/class1/deferred/blurLightV.glsl
index c2d05c601a8cf9b760c5c0d4bdbc302619000055..862f809de5387f197ae38d5dd4ad02a8078d02d0 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/blurLightV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/blurLightV.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 varying vec2 vary_fragcoord;
 uniform vec2 screen_res;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl b/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl
index 37bfaac32cbf49f49aec497f0aee6d689010f5ff..75b4dc624a9f33035a971ac68260d3dd62cf3144 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 uniform sampler2D diffuseMap;
 uniform sampler2D bumpMap;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/bumpSkinnedV.glsl b/indra/newview/app_settings/shaders/class1/deferred/bumpSkinnedV.glsl
index d884f2e4a5de3b066518ddba72758c0bd05b912a..dc69519a8596c41468a96523f5514c9dc5a160bc 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/bumpSkinnedV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/bumpSkinnedV.glsl
@@ -5,7 +5,7 @@
  * $License$
  */
 
-#version 120
+
 
 varying vec3 vary_mat0;
 varying vec3 vary_mat1;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/bumpV.glsl b/indra/newview/app_settings/shaders/class1/deferred/bumpV.glsl
index 9b109b2db67ec589d752f18cd8c3103e67df2138..5b6726488bdce1ee127b9c9da5c4e237eb892f40 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/bumpV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/bumpV.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 varying vec3 vary_mat0;
 varying vec3 vary_mat1;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/cloudsF.glsl b/indra/newview/app_settings/shaders/class1/deferred/cloudsF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..ef300d5631da9be354f6f9ec0d7dbd813235f126
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/cloudsF.glsl
@@ -0,0 +1,79 @@
+/** 
+ * @file WLCloudsF.glsl
+ *
+ * $LicenseInfo:firstyear=2005&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+ 
+
+
+/////////////////////////////////////////////////////////////////////////
+// The fragment shader for the sky
+/////////////////////////////////////////////////////////////////////////
+
+varying vec4 vary_CloudColorSun;
+varying vec4 vary_CloudColorAmbient;
+varying float vary_CloudDensity;
+
+uniform sampler2D cloud_noise_texture;
+uniform vec4 cloud_pos_density1;
+uniform vec4 cloud_pos_density2;
+uniform vec4 gamma;
+
+/// Soft clips the light with a gamma correction
+vec3 scaleSoftClip(vec3 light) {
+	//soft clip effect:
+	light = 1. - clamp(light, vec3(0.), vec3(1.));
+	light = 1. - pow(light, gamma.xxx);
+
+	return light;
+}
+
+void main()
+{
+	// Set variables
+	vec2 uv1 = gl_TexCoord[0].xy;
+	vec2 uv2 = gl_TexCoord[1].xy;
+
+	vec4 cloudColorSun = vary_CloudColorSun;
+	vec4 cloudColorAmbient = vary_CloudColorAmbient;
+	float cloudDensity = vary_CloudDensity;
+	vec2 uv3 = gl_TexCoord[2].xy;
+	vec2 uv4 = gl_TexCoord[3].xy;
+
+	// Offset texture coords
+	uv1 += cloud_pos_density1.xy;	//large texture, visible density
+	uv2 += cloud_pos_density1.xy;	//large texture, self shadow
+	uv3 += cloud_pos_density2.xy;	//small texture, visible density
+	uv4 += cloud_pos_density2.xy;	//small texture, self shadow
+
+
+	// Compute alpha1, the main cloud opacity
+	float alpha1 = (texture2D(cloud_noise_texture, uv1).x - 0.5) + (texture2D(cloud_noise_texture, uv3).x - 0.5) * cloud_pos_density2.z;
+	alpha1 = min(max(alpha1 + cloudDensity, 0.) * 10. * cloud_pos_density1.z, 1.);
+
+	// And smooth
+	alpha1 = 1. - alpha1 * alpha1;
+	alpha1 = 1. - alpha1 * alpha1;	
+
+
+	// Compute alpha2, for self shadowing effect
+	// (1 - alpha2) will later be used as percentage of incoming sunlight
+	float alpha2 = (texture2D(cloud_noise_texture, uv2).x - 0.5);
+	alpha2 = min(max(alpha2 + cloudDensity, 0.) * 2.5 * cloud_pos_density1.z, 1.);
+
+	// And smooth
+	alpha2 = 1. - alpha2;
+	alpha2 = 1. - alpha2 * alpha2;	
+
+	// Combine
+	vec4 color;
+	color = (cloudColorSun*(1.-alpha2) + cloudColorAmbient);
+	color *= 2.;
+
+	/// Gamma correct for WL (soft clip effect).
+	gl_FragData[0] = vec4(scaleSoftClip(color.rgb), alpha1);
+	gl_FragData[1] = vec4(0.0,0.0,0.0,0.0);
+	gl_FragData[2] = vec4(0,0,1,0);
+}
+
diff --git a/indra/newview/app_settings/shaders/class1/deferred/cloudsV.glsl b/indra/newview/app_settings/shaders/class1/deferred/cloudsV.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..3eac63076c19119a7e0f78e4c0d68f20e2dcf26e
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/cloudsV.glsl
@@ -0,0 +1,165 @@
+/** 
+ * @file WLCloudsV.glsl
+ *
+ * $LicenseInfo:firstyear=2005&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+ 
+
+
+//////////////////////////////////////////////////////////////////////////
+// The vertex shader for creating the atmospheric sky
+///////////////////////////////////////////////////////////////////////////////
+
+// Output parameters
+varying vec4 vary_CloudColorSun;
+varying vec4 vary_CloudColorAmbient;
+varying float vary_CloudDensity;
+
+// Inputs
+uniform vec3 camPosLocal;
+
+uniform vec4 lightnorm;
+uniform vec4 sunlight_color;
+uniform vec4 ambient;
+uniform vec4 blue_horizon;
+uniform vec4 blue_density;
+uniform vec4 haze_horizon;
+uniform vec4 haze_density;
+
+uniform vec4 cloud_shadow;
+uniform vec4 density_multiplier;
+uniform vec4 max_y;
+
+uniform vec4 glow;
+
+uniform vec4 cloud_color;
+
+uniform vec4 cloud_scale;
+
+void main()
+{
+
+	// World / view / projection
+	gl_Position = ftransform();
+
+	gl_TexCoord[0] = gl_MultiTexCoord0;
+
+	// Get relative position
+	vec3 P = gl_Vertex.xyz - camPosLocal.xyz + vec3(0,50,0);
+
+	// Set altitude
+	if (P.y > 0.)
+	{
+		P *= (max_y.x / P.y);
+	}
+	else
+	{
+		P *= (-32000. / P.y);
+	}
+
+	// Can normalize then
+	vec3 Pn = normalize(P);
+	float  Plen = length(P);
+
+	// Initialize temp variables
+	vec4 temp1 = vec4(0.);
+	vec4 temp2 = vec4(0.);
+	vec4 blue_weight;
+	vec4 haze_weight;
+	vec4 sunlight = sunlight_color;
+	vec4 light_atten;
+
+
+	// Sunlight attenuation effect (hue and brightness) due to atmosphere
+	// this is used later for sunlight modulation at various altitudes
+	light_atten = (blue_density * 1.0 + haze_density.x * 0.25) * (density_multiplier.x * max_y.x);
+
+	// Calculate relative weights
+	temp1 = blue_density + haze_density.x;
+	blue_weight = blue_density / temp1;
+	haze_weight = haze_density.x / temp1;
+
+	// Compute sunlight from P & lightnorm (for long rays like sky)
+	temp2.y = max(0., max(0., Pn.y) * 1.0 + lightnorm.y );
+	temp2.y = 1. / temp2.y;
+	sunlight *= exp( - light_atten * temp2.y);
+
+	// Distance
+	temp2.z = Plen * density_multiplier.x;
+
+	// Transparency (-> temp1)
+	// ATI Bugfix -- can't store temp1*temp2.z in a variable because the ati
+	// compiler gets confused.
+	temp1 = exp(-temp1 * temp2.z);
+
+
+	// Compute haze glow
+	temp2.x = dot(Pn, lightnorm.xyz);
+	temp2.x = 1. - temp2.x;
+		// temp2.x is 0 at the sun and increases away from sun
+	temp2.x = max(temp2.x, .001);	
+		// Set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot)
+	temp2.x *= glow.x;
+		// Higher glow.x gives dimmer glow (because next step is 1 / "angle")
+	temp2.x = pow(temp2.x, glow.z);
+		// glow.z should be negative, so we're doing a sort of (1 / "angle") function
+
+	// Add "minimum anti-solar illumination"
+	temp2.x += .25;
+
+	// Increase ambient when there are more clouds
+	vec4 tmpAmbient = ambient;
+	tmpAmbient += (1. - tmpAmbient) * cloud_shadow.x * 0.5; 
+
+	// Dim sunlight by cloud shadow percentage
+	sunlight *= (1. - cloud_shadow.x);
+
+	// Haze color below cloud
+	vec4 additiveColorBelowCloud = (	  blue_horizon * blue_weight * (sunlight + tmpAmbient)
+				+ (haze_horizon.r * haze_weight) * (sunlight * temp2.x + tmpAmbient)
+			 );	
+
+	// CLOUDS
+
+	sunlight = sunlight_color;
+	temp2.y = max(0., lightnorm.y * 2.);
+	temp2.y = 1. / temp2.y;
+	sunlight *= exp( - light_atten * temp2.y);
+
+	// Cloud color out
+	vary_CloudColorSun = (sunlight * temp2.x) * cloud_color;
+	vary_CloudColorAmbient = tmpAmbient * cloud_color;
+	
+	// Attenuate cloud color by atmosphere
+	temp1 = sqrt(temp1);	//less atmos opacity (more transparency) below clouds
+	vary_CloudColorSun *= temp1;
+	vary_CloudColorAmbient *= temp1;
+	vec4 oHazeColorBelowCloud = additiveColorBelowCloud * (1. - temp1);
+
+	// Make a nice cloud density based on the cloud_shadow value that was passed in.
+	vary_CloudDensity = 2. * (cloud_shadow.x - 0.25);
+
+
+	// Texture coords
+	gl_TexCoord[0] = gl_MultiTexCoord0;
+	gl_TexCoord[0].xy -= 0.5;
+	gl_TexCoord[0].xy /= cloud_scale.x;
+	gl_TexCoord[0].xy += 0.5;
+
+	gl_TexCoord[1] = gl_TexCoord[0];
+	gl_TexCoord[1].x += lightnorm.x * 0.0125;
+	gl_TexCoord[1].y += lightnorm.z * 0.0125;
+
+	gl_TexCoord[2] = gl_TexCoord[0] * 16.;
+	gl_TexCoord[3] = gl_TexCoord[1] * 16.;
+
+	// Combine these to minimize register use
+	vary_CloudColorAmbient += oHazeColorBelowCloud;
+
+	// needs this to compile on mac
+	//vary_AtmosAttenuation = vec3(0.0,0.0,0.0);
+
+	// END CLOUDS
+}
+
diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl
index 35cfb80c93882795211bd29c2834427513ac0a2b..43af480c5046aae8576c01844cd8ef1a033bdf93 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 uniform sampler2D diffuseMap;
 
@@ -20,3 +20,4 @@ void main()
 	vec3 nvn = normalize(vary_normal);
 	gl_FragData[2] = vec4(nvn.xy * 0.5 + 0.5, nvn.z, 0.0);
 }
+
diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..e7b5dcce7f95bc643bf16c50068789af1743d154
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl
@@ -0,0 +1,19 @@
+/** 
+ * @file diffuseIndexedF.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+ 
+varying vec3 vary_normal;
+
+void main() 
+{
+	vec3 col = gl_Color.rgb * diffuseLookup(gl_TexCoord[0].xy).rgb;
+
+	gl_FragData[0] = vec4(col, 0.0);
+	gl_FragData[1] = gl_Color.aaaa; // spec
+	//gl_FragData[1] = vec4(vec3(gl_Color.a), gl_Color.a+(1.0-gl_Color.a)*gl_Color.a); // spec - from former class3 - maybe better, but not so well tested
+	vec3 nvn = normalize(vary_normal);
+	gl_FragData[2] = vec4(nvn.xy * 0.5 + 0.5, nvn.z, 0.0);
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseSkinnedV.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseSkinnedV.glsl
index 9a45c03237a885a54958c239dafbc473f9ec56e9..2c4caea1090dddb78cb0c236370e50d1682abc7e 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/diffuseSkinnedV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseSkinnedV.glsl
@@ -5,7 +5,7 @@
  * $License$
  */
 
-#version 120
+
 
 varying vec3 vary_normal;
 
diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl
index 03d3322cb68855adfc5a7c9fe0de09b73ae96a19..b56d1493c3a84d3f61e7c457406f7b3e4922d23c 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl
@@ -5,16 +5,18 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 varying vec3 vary_normal;
+varying float vary_texture_index;
 
 void main()
 {
 	//transform vertex
-	gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; 
+	gl_Position = gl_ModelViewProjectionMatrix * vec4(gl_Vertex.xyz, 1.0); 
 	gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
 	
+	vary_texture_index = gl_Vertex.w;
 	vary_normal = normalize(gl_NormalMatrix * gl_Normal);
 
 	gl_FrontColor = gl_Color;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl
index 34298773974b2d35ea7396dceaebf3b7e1d363b9..d781e08548ccf229e331c74d8ac1889816db7d0d 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl
@@ -5,60 +5,24 @@
  * $/LicenseInfo$
  */
  
-#version 120
 
-#extension GL_ARB_texture_rectangle : enable
-
-uniform sampler2D diffuseMap;
-uniform sampler2DRect depthMap;
-uniform sampler2D noiseMap;
 
-uniform vec4 shadow_clip;
-uniform vec2 screen_res;
+#extension GL_ARB_texture_rectangle : enable
 
 vec3 fullbrightAtmosTransport(vec3 light);
 vec3 fullbrightScaleSoftClip(vec3 light);
 
-varying vec3 vary_ambient;
-varying vec3 vary_directional;
-varying vec4 vary_position;
-varying vec3 vary_normal;
-varying vec3 vary_fragcoord;
-
-uniform mat4 inv_proj;
-
-vec4 getPosition(vec2 pos_screen)
-{
-	float depth = texture2DRect(depthMap, pos_screen.xy).a;
-	vec2 sc = pos_screen.xy*2.0;
-	sc /= screen_res;
-	sc -= vec2(1.0,1.0);
-	vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
-	vec4 pos = inv_proj * ndc;
-	pos /= pos.w;
-	pos.w = 1.0;
-	return pos;
-}
 
 void main() 
 {
-	vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5;
-	frag *= screen_res;
-	
-	vec3 samp_pos = getPosition(frag).xyz; 
-	
 	float shadow = 1.0;
-	vec4 pos = vary_position;
 
-	vec4 color = texture2D(diffuseMap, gl_TexCoord[0].xy)*gl_Color;
+	vec4 color = diffuseLookup(gl_TexCoord[0].xy)*gl_Color;
 	
 	color.rgb = fullbrightAtmosTransport(color.rgb);
 
 	color.rgb = fullbrightScaleSoftClip(color.rgb);
 
-	//gl_FragColor = gl_Color;
 	gl_FragColor = color;
-	//gl_FragColor = vec4(1,0,1,1);
-	
 }
 
diff --git a/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl b/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl
index 6c38d220e26962bf7ad251ca51fcc3f7e456c0d0..2eed044b7cc7db24521f785f70cce0fbae16fb92 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 void calcAtmospherics(vec3 inPositionEye);
 
@@ -14,30 +14,23 @@ vec3 atmosAffectDirectionalLight(float lightIntensity);
 vec3 scaleDownLight(vec3 light);
 vec3 scaleUpLight(vec3 light);
 
-varying vec3 vary_ambient;
-varying vec3 vary_directional;
-varying vec3 vary_normal;
-varying vec3 vary_fragcoord;
-uniform float near_clip;
-varying vec4 vary_position;
+varying float vary_texture_index;
 
 void main()
 {
 	//transform vertex
-	gl_Position = ftransform(); 
+	vec4 vert = vec4(gl_Vertex.xyz, 1.0);
+	vary_texture_index = gl_Vertex.w;
+
+	gl_Position = gl_ModelViewProjectionMatrix*vert; 
 	
 	gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
 	
-	vec4 pos = (gl_ModelViewMatrix * gl_Vertex);
-	vary_position = pos;
-		
+	vec4 pos = (gl_ModelViewMatrix * vert);
+				
 	calcAtmospherics(pos.xyz);
 	
 	gl_FrontColor = gl_Color;
 
 	gl_FogFragCoord = pos.z;
-	
-	pos = gl_ModelViewProjectionMatrix * gl_Vertex;
-	vary_fragcoord.xyz = pos.xyz + vec3(0,0,near_clip);
-	
 }
diff --git a/indra/newview/app_settings/shaders/class1/deferred/giF.glsl b/indra/newview/app_settings/shaders/class1/deferred/giF.glsl
index 75b555e8ae35eb709428304f60e9a16836938f6d..41c149e7744775d182ffb67a01330c25da722bef 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/giF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/giF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 #extension GL_ARB_texture_rectangle : enable
 
diff --git a/indra/newview/app_settings/shaders/class1/deferred/giV.glsl b/indra/newview/app_settings/shaders/class1/deferred/giV.glsl
index 8dc1410ea5ad90d05d8bad4c485238550fd4cdd7..e86f2896da5fbc006f817a4f03a256599a7a69e3 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/giV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/giV.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 varying vec2 vary_fragcoord;
 
diff --git a/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl b/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl
index e3c15a2ab2d668bc15bdc2649c0f98ae1d585222..fa811f0d559e0510adea7eb4be98df4235032488 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 uniform sampler2D diffuseMap;
 uniform sampler2D normalMap;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/impostorV.glsl b/indra/newview/app_settings/shaders/class1/deferred/impostorV.glsl
index 37148b3f1a8c48c036290a9b2edc431ab5e61a9e..723777bd3a3329a69af2fa8d2012672115ba7df3 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/impostorV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/impostorV.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 void main()
 {
diff --git a/indra/newview/app_settings/shaders/class1/deferred/luminanceF.glsl b/indra/newview/app_settings/shaders/class1/deferred/luminanceF.glsl
index 78df54d5dc2b3726ad28daa881f3ceb1b9eebc8f..25e93ae266e99d1794c7f16dfd80e0c3aea010f2 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/luminanceF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/luminanceF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
 
-#version 120
+
 
 uniform sampler2DRect diffuseMap;
 
diff --git a/indra/newview/app_settings/shaders/class1/deferred/luminanceV.glsl b/indra/newview/app_settings/shaders/class1/deferred/luminanceV.glsl
index 0c820bfc6cf314aed20c9049b255953aac8b7f4f..4baf1fc65aa7836a423f60b869dbfdc9870a5773 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/luminanceV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/luminanceV.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
 
-#version 120
+
 
 
 varying vec2 vary_fragcoord;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl
index 609fc4f14ffa68aa634e0356d88891d022131ed7..3c5c780d944238b2add8962d7e20e4f200a92053 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
 
-#version 120
+
 
 #extension GL_ARB_texture_rectangle : enable
 
@@ -36,7 +36,7 @@ uniform mat4 inv_proj;
 
 vec4 getPosition(vec2 pos_screen)
 {
-	float depth = texture2DRect(depthMap, pos_screen.xy).a;
+	float depth = texture2DRect(depthMap, pos_screen.xy).r;
 	vec2 sc = pos_screen.xy*2.0;
 	sc /= screen_res;
 	sc -= vec2(1.0,1.0);
diff --git a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightMSF.glsl b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightMSF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..6c43679acf281c28485f9802d0a2a9bf16bb21d0
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightMSF.glsl
@@ -0,0 +1,137 @@
+/** 
+ * @file multiPointLightF.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+
+
+
+#extension GL_ARB_texture_rectangle : enable
+#extension GL_ARB_texture_multisample : enable
+
+uniform sampler2DMS depthMap;
+uniform sampler2DMS diffuseRect;
+uniform sampler2DMS specularRect;
+uniform sampler2DMS normalMap;
+uniform sampler2D noiseMap;
+uniform sampler2D lightFunc;
+
+
+uniform vec3 env_mat[3];
+uniform float sun_wash;
+
+uniform int light_count;
+
+#define MAX_LIGHT_COUNT		16
+uniform vec4 light[MAX_LIGHT_COUNT];
+uniform vec4 light_col[MAX_LIGHT_COUNT];
+
+varying vec4 vary_fragcoord;
+uniform vec2 screen_res;
+
+uniform float far_z;
+
+uniform mat4 inv_proj;
+
+vec4 getPosition(ivec2 pos_screen, int sample)
+{
+	float depth = texelFetch(depthMap, pos_screen, sample).r;
+	vec2 sc = vec2(pos_screen.xy)*2.0;
+	sc /= screen_res;
+	sc -= vec2(1.0,1.0);
+	vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+	vec4 pos = inv_proj * ndc;
+	pos /= pos.w;
+	pos.w = 1.0;
+	return pos;
+}
+
+void main() 
+{
+	vec2 frag = (vary_fragcoord.xy*0.5+0.5)*screen_res;
+	ivec2 itc = ivec2(frag);
+
+	int wght = 0;
+	vec3 fcol = vec3(0,0,0);
+
+	for (int s = 0; s < samples; ++s)
+	{
+		vec3 pos = getPosition(itc, s).xyz;
+		if (pos.z >= far_z)
+		{
+			vec3 norm = texelFetch(normalMap, itc, s).xyz;
+			norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm
+			norm = normalize(norm);
+			vec4 spec = texelFetch(specularRect, itc, s);
+			vec3 diff = texelFetch(diffuseRect, itc, s).rgb;
+			float noise = texture2D(noiseMap, frag.xy/128.0).b;
+			vec3 out_col = vec3(0,0,0);
+			vec3 npos = normalize(-pos);
+
+			// As of OSX 10.6.7 ATI Apple's crash when using a variable size loop
+			for (int i = 0; i < MAX_LIGHT_COUNT; ++i)
+			{
+				bool light_contrib = (i < light_count);
+		
+				vec3 lv = light[i].xyz-pos;
+				float dist2 = dot(lv,lv);
+				dist2 /= light[i].w;
+				if (dist2 > 1.0)
+				{
+					light_contrib = false;
+				}
+		
+				float da = dot(norm, lv);
+				if (da < 0.0)
+				{
+					light_contrib = false;
+				}
+		
+				if (light_contrib)
+				{
+					lv = normalize(lv);
+					da = dot(norm, lv);
+					
+					float fa = light_col[i].a+1.0;
+					float dist_atten = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0);
+					dist_atten *= noise;
+
+					float lit = da * dist_atten;
+			
+					vec3 col = light_col[i].rgb*lit*diff;
+					//vec3 col = vec3(dist2, light_col[i].a, lit);
+			
+					if (spec.a > 0.0)
+					{
+						//vec3 ref = dot(pos+lv, norm);
+				
+						float sa = dot(normalize(lv+npos),norm);
+				
+						if (sa > 0.0)
+						{
+							sa = texture2D(lightFunc,vec2(sa, spec.a)).a * min(dist_atten*4.0, 1.0);
+							sa *= noise;
+							col += da*sa*light_col[i].rgb*spec.rgb;
+						}
+					}
+			
+					out_col += col;
+				}
+			}
+	
+			fcol += out_col;
+			++wght;
+		}
+	}
+
+	if (wght <= 0)
+	{
+		discard;
+	}
+
+	gl_FragColor.rgb = fcol/samples;
+	gl_FragColor.a = 0.0;
+
+	
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightV.glsl b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightV.glsl
index 2e3e84dd156fd62563fbd241cd02d38f9236fb50..434fb6f53462bbb23a585f2ae339f12efb907c85 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightV.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
 
-#version 120
+
 
 varying vec4 vary_fragcoord;
 
diff --git a/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl
index a9f03f76151d014db77e7b46d4f5a20e805f8eaf..0d25d7792da169da6a9e9917543c00622b6b2df7 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
 
-#version 120
+
 
 //class 1 -- no shadows
 
diff --git a/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightMSF.glsl b/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightMSF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..c80a54346e4cb78cdb5c666327d8d32524e23784
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightMSF.glsl
@@ -0,0 +1,232 @@
+/** 
+ * @file multiSpotLightF.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+
+
+
+//class 1 -- no shadows
+
+#extension GL_ARB_texture_rectangle : enable
+#extension GL_ARB_texture_multisample : enable
+
+uniform sampler2DMS diffuseRect;
+uniform sampler2DMS specularRect;
+uniform sampler2DMS depthMap;
+uniform sampler2DMS normalMap;
+uniform sampler2D noiseMap;
+uniform sampler2D lightFunc;
+uniform sampler2D projectionMap;
+
+uniform mat4 proj_mat; //screen space to light space
+uniform float proj_near; //near clip for projection
+uniform vec3 proj_p; //plane projection is emitting from (in screen space)
+uniform vec3 proj_n;
+uniform float proj_focus; //distance from plane to begin blurring
+uniform float proj_lod;  //(number of mips in proj map)
+uniform float proj_range; //range between near clip and far clip plane of projection
+uniform float proj_ambient_lod;
+uniform float proj_ambiance;
+uniform float near_clip;
+uniform float far_clip;
+
+uniform vec3 proj_origin; //origin of projection to be used for angular attenuation
+uniform float sun_wash;
+uniform float shadow_fade;
+
+varying vec4 vary_light;
+
+varying vec4 vary_fragcoord;
+uniform vec2 screen_res;
+
+uniform mat4 inv_proj;
+
+vec4 texture2DLodSpecular(sampler2D projectionMap, vec2 tc, float lod)
+{
+	vec4 ret = texture2DLod(projectionMap, tc, lod);
+	
+	vec2 dist = tc-vec2(0.5);
+	
+	float det = max(1.0-lod/(proj_lod*0.5), 0.0);
+	
+	float d = dot(dist,dist);
+		
+	ret *= min(clamp((0.25-d)/0.25, 0.0, 1.0)+det, 1.0);
+	
+	return ret;
+}
+
+vec4 texture2DLodDiffuse(sampler2D projectionMap, vec2 tc, float lod)
+{
+	vec4 ret = texture2DLod(projectionMap, tc, lod);
+	
+	vec2 dist = vec2(0.5) - abs(tc-vec2(0.5));
+	
+	float det = min(lod/(proj_lod*0.5), 1.0);
+	
+	float d = min(dist.x, dist.y);
+	
+	float edge = 0.25*det;
+		
+	ret *= clamp(d/edge, 0.0, 1.0);
+	
+	return ret;
+}
+
+vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod)
+{
+	vec4 ret = texture2DLod(projectionMap, tc, lod);
+	
+	vec2 dist = tc-vec2(0.5);
+	
+	float d = dot(dist,dist);
+		
+	ret *= min(clamp((0.25-d)/0.25, 0.0, 1.0), 1.0);
+	
+	return ret;
+}
+
+
+vec4 getPosition(ivec2 pos_screen, int sample)
+{
+	float depth = texelFetch(depthMap, pos_screen, sample).r;
+	vec2 sc = vec2(pos_screen.xy)*2.0;
+	sc /= screen_res;
+	sc -= vec2(1.0,1.0);
+	vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+	vec4 pos = inv_proj * ndc;
+	pos /= pos.w;
+	pos.w = 1.0;
+	return pos;
+}
+
+void main() 
+{
+	int wght = 0;
+
+	vec3 fcol = vec3(0,0,0);
+
+	vec2 frag = (vary_fragcoord.xy*0.5+0.5)*screen_res;
+	
+	ivec2 itc = ivec2(frag.xy);
+
+	for (int i = 0; i < samples; ++i)
+	{
+		vec3 pos = getPosition(itc, i).xyz;
+		vec3 lv = vary_light.xyz-pos.xyz;
+		float dist2 = dot(lv,lv);
+		dist2 /= vary_light.w;
+		if (dist2 <= 1.0)
+		{
+			vec3 norm = texelFetch(normalMap, itc, i).xyz*2.0-1.0;
+	
+			norm = normalize(norm);
+			float l_dist = -dot(lv, proj_n);
+	
+			vec4 proj_tc = (proj_mat * vec4(pos.xyz, 1.0));
+			if (proj_tc.z >= 0.0)
+			{
+				proj_tc.xyz /= proj_tc.w;
+	
+				float fa = gl_Color.a+1.0;
+				float dist_atten = min(1.0-(dist2-1.0*(1.0-fa))/fa, 1.0);
+				if (dist_atten > 0.0)
+				{
+					lv = proj_origin-pos.xyz;
+					lv = normalize(lv);
+					float da = dot(norm, lv);
+		
+					vec3 col = vec3(0,0,0);
+		
+					vec3 diff_tex = texelFetch(diffuseRect, itc, i).rgb;
+		
+					float noise = texture2D(noiseMap, frag.xy/128.0).b;
+					if (proj_tc.z > 0.0 &&
+						proj_tc.x < 1.0 &&
+						proj_tc.y < 1.0 &&
+						proj_tc.x > 0.0 &&
+						proj_tc.y > 0.0)
+					{
+						float lit = 0.0;
+						float amb_da = proj_ambiance;
+		
+						if (da > 0.0)
+						{
+							float diff = clamp((l_dist-proj_focus)/proj_range, 0.0, 1.0);
+							float lod = diff * proj_lod;
+			
+							vec4 plcol = texture2DLodDiffuse(projectionMap, proj_tc.xy, lod);
+		
+							vec3 lcol = gl_Color.rgb * plcol.rgb * plcol.a;
+			
+							lit = da * dist_atten * noise;
+			
+							col = lcol*lit*diff_tex;
+							amb_da += (da*0.5)*proj_ambiance;
+						}
+		
+						//float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0);
+						vec4 amb_plcol = texture2DLodAmbient(projectionMap, proj_tc.xy, proj_lod);
+							
+						amb_da += (da*da*0.5+0.5)*proj_ambiance;
+				
+						amb_da *= dist_atten * noise;
+			
+						amb_da = min(amb_da, 1.0-lit);
+			
+						col += amb_da*gl_Color.rgb*diff_tex.rgb*amb_plcol.rgb*amb_plcol.a;
+					}
+	
+	
+					vec4 spec = texelFetch(specularRect, itc, i);
+					if (spec.a > 0.0)
+					{
+						vec3 ref = reflect(normalize(pos), norm);
+		
+						//project from point pos in direction ref to plane proj_p, proj_n
+						vec3 pdelta = proj_p-pos;
+						float ds = dot(ref, proj_n);
+		
+						if (ds < 0.0)
+						{
+							vec3 pfinal = pos + ref * dot(pdelta, proj_n)/ds;
+			
+							vec4 stc = (proj_mat * vec4(pfinal.xyz, 1.0));
+
+							if (stc.z > 0.0)
+							{
+								stc.xy /= stc.w;
+
+								float fatten = clamp(spec.a*spec.a+spec.a*0.5, 0.25, 1.0);
+				
+								stc.xy = (stc.xy - vec2(0.5)) * fatten + vec2(0.5);
+								
+								if (stc.x < 1.0 &&
+									stc.y < 1.0 &&
+									stc.x > 0.0 &&
+									stc.y > 0.0)
+								{
+									vec4 scol = texture2DLodSpecular(projectionMap, stc.xy, proj_lod-spec.a*proj_lod);
+									col += dist_atten*scol.rgb*gl_Color.rgb*scol.a*spec.rgb;
+								}
+							}
+						}
+					}
+	
+					fcol += col;
+					++wght;
+				}
+			}
+		}
+	}
+
+	if (wght <= 0)
+	{
+		discard;
+	}
+
+	gl_FragColor.rgb = fcol/samples;	
+	gl_FragColor.a = 0.0;
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl
index 22ed9dcd40ec25f456f91c5dc0e92333e41dfb27..5efa3200d4ab93057ab80c3fecbe17d87e391d69 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
- #version 120
+ 
 
 #extension GL_ARB_texture_rectangle : enable
 
@@ -30,7 +30,7 @@ uniform vec4 viewport;
 
 vec4 getPosition(vec2 pos_screen)
 {
-	float depth = texture2DRect(depthMap, pos_screen.xy).a;
+	float depth = texture2DRect(depthMap, pos_screen.xy).r;
 	vec2 sc = (pos_screen.xy-viewport.xy)*2.0;
 	sc /= viewport.zw;
 	sc -= vec2(1.0,1.0);
diff --git a/indra/newview/app_settings/shaders/class1/deferred/pointLightMSF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pointLightMSF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..feaf38115d1c3904249eeb6028c5b25169fce6ed
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/pointLightMSF.glsl
@@ -0,0 +1,108 @@
+/** 
+ * @file pointLightF.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+ 
+ 
+
+#extension GL_ARB_texture_rectangle : enable
+#extension GL_ARB_texture_multisample : enable
+
+uniform sampler2DMS depthMap;
+uniform sampler2DMS diffuseRect;
+uniform sampler2DMS specularRect;
+uniform sampler2DMS normalMap;
+uniform sampler2D noiseMap;
+uniform sampler2D lightFunc;
+
+
+uniform vec3 env_mat[3];
+uniform float sun_wash;
+
+varying vec4 vary_light;
+
+varying vec4 vary_fragcoord;
+uniform vec2 screen_res;
+
+uniform mat4 inv_proj;
+uniform vec4 viewport;
+
+vec4 getPosition(ivec2 pos_screen, int sample)
+{
+	float depth = texelFetch(depthMap, pos_screen, sample).r;
+	vec2 sc = (vec2(pos_screen.xy)-viewport.xy)*2.0;
+	sc /= viewport.zw;
+	sc -= vec2(1.0,1.0);
+	vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+	vec4 pos = inv_proj * ndc;
+	pos /= pos.w;
+	pos.w = 1.0;
+	return pos;
+}
+
+void main() 
+{
+	vec4 frag = vary_fragcoord;
+	frag.xyz /= frag.w;
+	frag.xyz = frag.xyz*0.5+0.5;
+	frag.xy *= screen_res;
+	
+	ivec2 itc = ivec2(frag.xy);
+
+	int wght = 0;
+	vec3 fcol = vec3(0,0,0);
+
+	for (int s = 0; s < samples; ++s)
+	{
+		vec3 pos = getPosition(itc, s).xyz;
+		vec3 lv = vary_light.xyz-pos;
+		float dist2 = dot(lv,lv);
+		dist2 /= vary_light.w;
+		if (dist2 <= 1.0)
+		{
+			vec3 norm = texelFetch(normalMap, itc, s).xyz;
+			norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm
+			float da = dot(norm, lv);
+			if (da >= 0.0)
+			{
+				norm = normalize(norm);
+				lv = normalize(lv);
+				da = dot(norm, lv);
+	
+				float noise = texture2D(noiseMap, frag.xy/128.0).b;
+	
+				vec3 col = texelFetch(diffuseRect, itc, s).rgb;
+				float fa = gl_Color.a+1.0;
+				float dist_atten = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0);
+				float lit = da * dist_atten * noise;
+	
+				col = gl_Color.rgb*lit*col;
+
+				vec4 spec = texelFetch(specularRect, itc, s);
+				if (spec.a > 0.0)
+				{
+					float sa = dot(normalize(lv-normalize(pos)),norm);
+					if (sa > 0.0)
+					{
+						sa = texture2D(lightFunc, vec2(sa, spec.a)).a * min(dist_atten*4.0, 1.0);
+						sa *= noise;
+						col += da*sa*gl_Color.rgb*spec.rgb;
+					}
+				}
+
+				fcol += col;
+				++wght;
+			}
+		}
+	}
+	
+	if (wght <= 0)
+	{
+		discard;
+	}
+		
+	gl_FragColor.rgb = fcol/samples;	
+	gl_FragColor.a = 0.0;
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl b/indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl
index 8e74feb61565cac9f6d4736bc04c72909a293867..c510d8ad7794f040a107416ef400c01458b3bcf6 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl
@@ -5,19 +5,14 @@
  * $/LicenseInfo$
  */
 
-#version 120
+
 
 varying vec4 vary_light;
 varying vec4 vary_fragcoord;
 
-uniform vec2 screen_res;
-uniform float near_clip;
-
 void main()
 {
 	//transform vertex
-	gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; 
-
 	vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex;
 	vary_fragcoord = pos;
 		
@@ -25,6 +20,8 @@ void main()
 	tex.w = 1.0;
 	
 	vary_light = gl_MultiTexCoord0;
+	
+	gl_Position = pos;
 		
 	gl_FrontColor = gl_Color;
 }
diff --git a/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl
index 77f1b2224c20f04f66b79b948fc5be3a3844f6ea..f6b0402bb9c532e7def229313671079828281f3a 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 #extension GL_ARB_texture_rectangle : enable
 
@@ -29,7 +29,7 @@ varying vec2 vary_fragcoord;
 
 float getDepth(vec2 pos_screen)
 {
-	float z = texture2DRect(depthMap, pos_screen.xy).a;
+	float z = texture2DRect(depthMap, pos_screen.xy).r;
 	z = z*2.0-1.0;
 	vec4 ndc = vec4(0.0, 0.0, z, 1.0);
 	vec4 p = inv_proj*ndc;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/postDeferredMSF.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredMSF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..62ae5f917a2f5645f323a58a621178ebe1019525
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/postDeferredMSF.glsl
@@ -0,0 +1,133 @@
+/** 
+ * @file postDeferredF.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+ 
+
+
+#extension GL_ARB_texture_rectangle : enable
+#extension GL_ARB_texture_multisample : enable
+
+uniform sampler2DMS diffuseRect;
+uniform sampler2DMS edgeMap;
+uniform sampler2DMS depthMap;
+uniform sampler2DMS normalMap;
+uniform sampler2D bloomMap;
+
+uniform float depth_cutoff;
+uniform float norm_cutoff;
+uniform float focal_distance;
+uniform float blur_constant;
+uniform float tan_pixel_angle;
+uniform float magnification;
+
+uniform mat4 inv_proj;
+uniform vec2 screen_res;
+
+varying vec2 vary_fragcoord;
+
+vec4 texture2DMS(sampler2DMS tex, ivec2 tc)
+{
+	vec4 ret = vec4(0,0,0,0);
+	for (int i = 0; i < samples; ++i)
+	{
+		ret += texelFetch(tex, tc, i);
+	}
+
+	return ret/samples;
+}
+
+float getDepth(ivec2 pos_screen)
+{
+	float z = texture2DMS(depthMap, pos_screen.xy).r;
+	z = z*2.0-1.0;
+	vec4 ndc = vec4(0.0, 0.0, z, 1.0);
+	vec4 p = inv_proj*ndc;
+	return p.z/p.w;
+}
+
+float calc_cof(float depth)
+{
+	float sc = abs(depth-focal_distance)/-depth*blur_constant;
+		
+	sc /= magnification;
+	
+	// tan_pixel_angle = pixel_length/-depth;
+	float pixel_length =  tan_pixel_angle*-focal_distance;
+	
+	sc = sc/pixel_length;
+	sc *= 1.414;
+	
+	return sc;
+}
+
+void dofSample(inout vec4 diff, inout float w, float min_sc, float cur_depth, ivec2 tc)
+{
+	float d = getDepth(tc);
+	
+	float sc = calc_cof(d);
+	
+	if (sc > min_sc //sampled pixel is more "out of focus" than current sample radius
+	   || d < cur_depth) //sampled pixel is further away than current pixel
+	{
+		float wg = 0.25;
+		
+		vec4 s = texture2DMS(diffuseRect, tc);
+		// de-weight dull areas to make highlights 'pop'
+		wg += s.r+s.g+s.b;
+	
+		diff += wg*s;
+		
+		w += wg;
+	}
+}
+
+
+void main() 
+{
+	ivec2 itc = ivec2(vary_fragcoord.xy);
+
+	vec3 norm = texture2DMS(normalMap, itc).xyz;
+	norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm
+		
+	float depth = getDepth(itc);
+	
+	vec4 diff = texture2DMS(diffuseRect, itc);
+	
+	{ 
+		float w = 1.0;
+		
+		float sc = calc_cof(depth);
+		sc = min(abs(sc), 10.0);
+		
+		float fd = depth*0.5f;
+		
+		float PI = 3.14159265358979323846264;
+
+		int isc = int(sc);
+		
+		// sample quite uniformly spaced points within a circle, for a circular 'bokeh'		
+		//if (depth < focal_distance)
+		{
+			for (int x = -isc; x <= isc; x+=2)
+			{
+				for (int y = -isc; y <= isc; y+=2)
+				{
+					ivec2 cur_samp = ivec2(x,y);
+					float cur_sc = length(vec2(cur_samp));
+					if (cur_sc < sc)
+					{
+						dofSample(diff, w, cur_sc, depth, itc+cur_samp);
+					}
+				}
+			}
+		}
+		
+		diff /= w;
+	}
+		
+	vec4 bloom = texture2D(bloomMap, vary_fragcoord.xy/screen_res);
+	gl_FragColor = diff + bloom;
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/postDeferredNoDoFF.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredNoDoFF.glsl
index ab48d08bbb070342a2f48402b32859c8aaedf01a..bf829bfc560e94ca413183588fc71382a1100634 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/postDeferredNoDoFF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/postDeferredNoDoFF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 #extension GL_ARB_texture_rectangle : enable
 
diff --git a/indra/newview/app_settings/shaders/class1/deferred/postDeferredNoDoFMSF.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredNoDoFMSF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..bf35dfe11cb928c7a874504689dded0ed1e2a08d
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/postDeferredNoDoFMSF.glsl
@@ -0,0 +1,37 @@
+/** 
+ * @file postDeferredF.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+ 
+
+
+#extension GL_ARB_texture_rectangle : enable
+#extension GL_ARB_texture_multisample : enable
+
+uniform sampler2DMS diffuseRect;
+uniform sampler2D bloomMap;
+
+uniform vec2 screen_res;
+varying vec2 vary_fragcoord;
+
+vec4 texture2DMS(sampler2DMS tex, ivec2 tc)
+{
+	vec4 ret = vec4(0,0,0,0);
+
+	for (int i = 0; i < samples; ++i)
+	{
+		 ret += texelFetch(tex,tc,i);
+	}
+
+	return ret/samples;
+}
+
+void main() 
+{
+	vec4 diff = texture2DMS(diffuseRect, ivec2(vary_fragcoord.xy));
+
+	vec4 bloom = texture2D(bloomMap, vary_fragcoord.xy/screen_res);
+	gl_FragColor = diff + bloom;
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/postDeferredV.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredV.glsl
index 12983baa94882bfc3f58349847dd7bec1b3aadca..876f65ee3adc86302c81426f8ce576b67ae96a95 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/postDeferredV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/postDeferredV.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 varying vec2 vary_fragcoord;
 uniform vec2 screen_res;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/postgiF.glsl b/indra/newview/app_settings/shaders/class1/deferred/postgiF.glsl
index 63b3c9f20527dae3364ede4002f395aedf798ae4..fa3f04bcc81b9912fd7a0dcf094cab4f7c893649 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/postgiF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/postgiF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 uniform sampler2DRect depthMap;
 uniform sampler2DRect normalMap;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/postgiV.glsl b/indra/newview/app_settings/shaders/class1/deferred/postgiV.glsl
index ae57227fe528b03b5e2a0d216c9a8b97a5ddfb39..eebe930666a60742bb73b063f384b32d99d4f726 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/postgiV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/postgiV.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 varying vec2 vary_fragcoord;
 uniform vec2 screen_res;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/shadowF.glsl b/indra/newview/app_settings/shaders/class1/deferred/shadowF.glsl
index 6674c4a5aa275a379c2bab374801a9b38ebe51f9..e0c540648307f784156647f5a1463d740e96c8de 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/shadowF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/shadowF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 uniform sampler2D diffuseMap;
 
diff --git a/indra/newview/app_settings/shaders/class1/deferred/shadowV.glsl b/indra/newview/app_settings/shaders/class1/deferred/shadowV.glsl
index db3bddc6bea4b635bb834b2a59b29f00001ba503..9271a5115c5277925f61e0c9fa3ec61c79082a92 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/shadowV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/shadowV.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 varying vec4 post_pos;
 
diff --git a/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl b/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..820c82ffd7f964318e467c579840411de836aaec
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl
@@ -0,0 +1,44 @@
+/** 
+ * @file WLSkyF.glsl
+ *
+ * $LicenseInfo:firstyear=2005&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+ 
+
+
+/////////////////////////////////////////////////////////////////////////
+// The fragment shader for the sky
+/////////////////////////////////////////////////////////////////////////
+
+varying vec4 vary_HazeColor;
+
+uniform sampler2D cloud_noise_texture;
+uniform vec4 gamma;
+
+/// Soft clips the light with a gamma correction
+vec3 scaleSoftClip(vec3 light) {
+	//soft clip effect:
+	light = 1. - clamp(light, vec3(0.), vec3(1.));
+	light = 1. - pow(light, gamma.xxx);
+
+	return light;
+}
+
+void main()
+{
+	// Potential Fill-rate optimization.  Add cloud calculation 
+	// back in and output alpha of 0 (so that alpha culling kills 
+	// the fragment) if the sky wouldn't show up because the clouds 
+	// are fully opaque.
+
+	vec4 color;
+	color = vary_HazeColor;
+	color *= 2.;
+
+	/// Gamma correct for WL (soft clip effect).
+	gl_FragData[0] = vec4(scaleSoftClip(color.rgb), 1.0);
+	gl_FragData[1] = vec4(0.0,0.0,0.0,0.0);
+	gl_FragData[2] = vec4(0,0,1,0);
+}
+
diff --git a/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl b/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..1ea00f723afcab0ed9f5f746f194f1ab2e5e7dde
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl
@@ -0,0 +1,140 @@
+/** 
+ * @file WLSkyV.glsl
+ *
+ * $LicenseInfo:firstyear=2005&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+ 
+
+
+// SKY ////////////////////////////////////////////////////////////////////////
+// The vertex shader for creating the atmospheric sky
+///////////////////////////////////////////////////////////////////////////////
+
+// Output parameters
+varying vec4 vary_HazeColor;
+
+// Inputs
+uniform vec3 camPosLocal;
+
+uniform vec4 lightnorm;
+uniform vec4 sunlight_color;
+uniform vec4 ambient;
+uniform vec4 blue_horizon;
+uniform vec4 blue_density;
+uniform vec4 haze_horizon;
+uniform vec4 haze_density;
+
+uniform vec4 cloud_shadow;
+uniform vec4 density_multiplier;
+uniform vec4 max_y;
+
+uniform vec4 glow;
+
+uniform vec4 cloud_color;
+
+uniform vec4 cloud_scale;
+
+void main()
+{
+
+	// World / view / projection
+	gl_Position = ftransform();
+	gl_TexCoord[0] = gl_MultiTexCoord0;
+
+	// Get relative position
+	vec3 P = gl_Vertex.xyz - camPosLocal.xyz + vec3(0,50,0);
+	//vec3 P = gl_Vertex.xyz + vec3(0,50,0);
+
+	// Set altitude
+	if (P.y > 0.)
+	{
+		P *= (max_y.x / P.y);
+	}
+	else
+	{
+		P *= (-32000. / P.y);
+	}
+
+	// Can normalize then
+	vec3 Pn = normalize(P);
+	float  Plen = length(P);
+
+	// Initialize temp variables
+	vec4 temp1 = vec4(0.);
+	vec4 temp2 = vec4(0.);
+	vec4 blue_weight;
+	vec4 haze_weight;
+	vec4 sunlight = sunlight_color;
+	vec4 light_atten;
+
+
+	// Sunlight attenuation effect (hue and brightness) due to atmosphere
+	// this is used later for sunlight modulation at various altitudes
+	light_atten = (blue_density * 1.0 + haze_density.x * 0.25) * (density_multiplier.x * max_y.x);
+
+	// Calculate relative weights
+	temp1 = blue_density + haze_density.x;
+	blue_weight = blue_density / temp1;
+	haze_weight = haze_density.x / temp1;
+
+	// Compute sunlight from P & lightnorm (for long rays like sky)
+	temp2.y = max(0., max(0., Pn.y) * 1.0 + lightnorm.y );
+	temp2.y = 1. / temp2.y;
+	sunlight *= exp( - light_atten * temp2.y);
+
+	// Distance
+	temp2.z = Plen * density_multiplier.x;
+
+	// Transparency (-> temp1)
+	// ATI Bugfix -- can't store temp1*temp2.z in a variable because the ati
+	// compiler gets confused.
+	temp1 = exp(-temp1 * temp2.z);
+
+
+	// Compute haze glow
+	temp2.x = dot(Pn, lightnorm.xyz);
+	temp2.x = 1. - temp2.x;
+		// temp2.x is 0 at the sun and increases away from sun
+	temp2.x = max(temp2.x, .001);	
+		// Set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot)
+	temp2.x *= glow.x;
+		// Higher glow.x gives dimmer glow (because next step is 1 / "angle")
+	temp2.x = pow(temp2.x, glow.z);
+		// glow.z should be negative, so we're doing a sort of (1 / "angle") function
+
+	// Add "minimum anti-solar illumination"
+	temp2.x += .25;
+
+
+	// Haze color above cloud
+	vary_HazeColor = (	  blue_horizon * blue_weight * (sunlight + ambient)
+				+ (haze_horizon.r * haze_weight) * (sunlight * temp2.x + ambient)
+			 );	
+
+
+	// Increase ambient when there are more clouds
+	vec4 tmpAmbient = ambient;
+	tmpAmbient += (1. - tmpAmbient) * cloud_shadow.x * 0.5; 
+
+	// Dim sunlight by cloud shadow percentage
+	sunlight *= (1. - cloud_shadow.x);
+
+	// Haze color below cloud
+	vec4 additiveColorBelowCloud = (	  blue_horizon * blue_weight * (sunlight + tmpAmbient)
+				+ (haze_horizon.r * haze_weight) * (sunlight * temp2.x + tmpAmbient)
+			 );	
+
+	// Final atmosphere additive
+	vary_HazeColor *= (1. - temp1);
+	
+	// Attenuate cloud color by atmosphere
+	temp1 = sqrt(temp1);	//less atmos opacity (more transparency) below clouds
+
+	// At horizon, blend high altitude sky color towards the darker color below the clouds
+	vary_HazeColor += (additiveColorBelowCloud - vary_HazeColor) * (1. - sqrt(temp1));
+	
+	// won't compile on mac without this being set
+	//vary_AtmosAttenuation = vec3(0.0,0.0,0.0);
+}
+
diff --git a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl
index 29340c7e9f01bc8d44ad910fe56c4d0e243a6a4d..60082f40d691feee85946a50b180123a28c6b45a 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 #extension GL_ARB_texture_rectangle : enable
 
@@ -259,7 +259,7 @@ vec3 scaleSoftClip(vec3 light)
 void main() 
 {
 	vec2 tc = vary_fragcoord.xy;
-	float depth = texture2DRect(depthMap, tc.xy).a;
+	float depth = texture2DRect(depthMap, tc.xy).r;
 	vec3 pos = getPosition_d(tc, depth).xyz;
 	vec3 norm = texture2DRect(normalMap, tc).xyz;
 	norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm
diff --git a/indra/newview/app_settings/shaders/class1/deferred/softenLightMSF.glsl b/indra/newview/app_settings/shaders/class1/deferred/softenLightMSF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..9dfacfb520cd8638b252a2845d3560f5806a4a7e
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/softenLightMSF.glsl
@@ -0,0 +1,318 @@
+/** 
+ * @file softenLightF.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+ 
+
+
+#extension GL_ARB_texture_rectangle : enable
+#extension GL_ARB_texture_multisample : enable
+
+uniform sampler2DMS diffuseRect;
+uniform sampler2DMS specularRect;
+uniform sampler2DMS normalMap;
+uniform sampler2DMS depthMap;
+uniform sampler2D	  noiseMap;
+uniform samplerCube environmentMap;
+uniform sampler2D	  lightFunc;
+
+uniform float blur_size;
+uniform float blur_fidelity;
+
+// Inputs
+uniform vec4 morphFactor;
+uniform vec3 camPosLocal;
+//uniform vec4 camPosWorld;
+uniform vec4 gamma;
+uniform vec4 lightnorm;
+uniform vec4 sunlight_color;
+uniform vec4 ambient;
+uniform vec4 blue_horizon;
+uniform vec4 blue_density;
+uniform vec4 haze_horizon;
+uniform vec4 haze_density;
+uniform vec4 cloud_shadow;
+uniform vec4 density_multiplier;
+uniform vec4 distance_multiplier;
+uniform vec4 max_y;
+uniform vec4 glow;
+uniform float scene_light_strength;
+uniform vec3 env_mat[3];
+//uniform mat4 shadow_matrix[3];
+//uniform vec4 shadow_clip;
+uniform mat3 ssao_effect_mat;
+
+varying vec4 vary_light;
+varying vec2 vary_fragcoord;
+
+vec3 vary_PositionEye;
+
+vec3 vary_SunlitColor;
+vec3 vary_AmblitColor;
+vec3 vary_AdditiveColor;
+vec3 vary_AtmosAttenuation;
+
+uniform mat4 inv_proj;
+uniform vec2 screen_res;
+
+vec4 getPosition_d(vec2 pos_screen, float depth)
+{
+	vec2 sc = pos_screen.xy*2.0;
+	sc /= screen_res;
+	sc -= vec2(1.0,1.0);
+	vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+	vec4 pos = inv_proj * ndc;
+	pos /= pos.w;
+	pos.w = 1.0;
+	return pos;
+}
+
+vec3 getPositionEye()
+{
+	return vary_PositionEye;
+}
+vec3 getSunlitColor()
+{
+	return vary_SunlitColor;
+}
+vec3 getAmblitColor()
+{
+	return vary_AmblitColor;
+}
+vec3 getAdditiveColor()
+{
+	return vary_AdditiveColor;
+}
+vec3 getAtmosAttenuation()
+{
+	return vary_AtmosAttenuation;
+}
+
+
+void setPositionEye(vec3 v)
+{
+	vary_PositionEye = v;
+}
+
+void setSunlitColor(vec3 v)
+{
+	vary_SunlitColor = v;
+}
+
+void setAmblitColor(vec3 v)
+{
+	vary_AmblitColor = v;
+}
+
+void setAdditiveColor(vec3 v)
+{
+	vary_AdditiveColor = v;
+}
+
+void setAtmosAttenuation(vec3 v)
+{
+	vary_AtmosAttenuation = v;
+}
+
+void calcAtmospherics(vec3 inPositionEye, float ambFactor) {
+
+	vec3 P = inPositionEye;
+	setPositionEye(P);
+	
+	//(TERRAIN) limit altitude
+	if (P.y > max_y.x) P *= (max_y.x / P.y);
+	if (P.y < -max_y.x) P *= (-max_y.x / P.y);
+
+	vec3 tmpLightnorm = lightnorm.xyz;
+
+	vec3 Pn = normalize(P);
+	float Plen = length(P);
+
+	vec4 temp1 = vec4(0);
+	vec3 temp2 = vec3(0);
+	vec4 blue_weight;
+	vec4 haze_weight;
+	vec4 sunlight = sunlight_color;
+	vec4 light_atten;
+
+	//sunlight attenuation effect (hue and brightness) due to atmosphere
+	//this is used later for sunlight modulation at various altitudes
+	light_atten = (blue_density * 1.0 + vec4(haze_density.r) * 0.25) * (density_multiplier.x * max_y.x);
+		//I had thought blue_density and haze_density should have equal weighting,
+		//but attenuation due to haze_density tends to seem too strong
+
+	temp1 = blue_density + vec4(haze_density.r);
+	blue_weight = blue_density / temp1;
+	haze_weight = vec4(haze_density.r) / temp1;
+
+	//(TERRAIN) compute sunlight from lightnorm only (for short rays like terrain)
+	temp2.y = max(0.0, tmpLightnorm.y);
+	temp2.y = 1. / temp2.y;
+	sunlight *= exp( - light_atten * temp2.y);
+
+	// main atmospheric scattering line integral
+	temp2.z = Plen * density_multiplier.x;
+
+	// Transparency (-> temp1)
+	// ATI Bugfix -- can't store temp1*temp2.z*distance_multiplier.x in a variable because the ati
+	// compiler gets confused.
+	temp1 = exp(-temp1 * temp2.z * distance_multiplier.x);
+
+	//final atmosphere attenuation factor
+	setAtmosAttenuation(temp1.rgb);
+	
+	//compute haze glow
+	//(can use temp2.x as temp because we haven't used it yet)
+	temp2.x = dot(Pn, tmpLightnorm.xyz);
+	temp2.x = 1. - temp2.x;
+		//temp2.x is 0 at the sun and increases away from sun
+	temp2.x = max(temp2.x, .03);	//was glow.y
+		//set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot)
+	temp2.x *= glow.x;
+		//higher glow.x gives dimmer glow (because next step is 1 / "angle")
+	temp2.x = pow(temp2.x, glow.z);
+		//glow.z should be negative, so we're doing a sort of (1 / "angle") function
+
+	//add "minimum anti-solar illumination"
+	temp2.x += .25;
+	
+	//increase ambient when there are more clouds
+	vec4 tmpAmbient = ambient + (vec4(1.) - ambient) * cloud_shadow.x * 0.5;
+	
+	/*  decrease value and saturation (that in HSV, not HSL) for occluded areas
+	 * // for HSV color/geometry used here, see http://gimp-savvy.com/BOOK/index.html?node52.html
+	 * // The following line of code performs the equivalent of:
+	 * float ambAlpha = tmpAmbient.a;
+	 * float ambValue = dot(vec3(tmpAmbient), vec3(0.577)); // projection onto <1/rt(3), 1/rt(3), 1/rt(3)>, the neutral white-black axis
+	 * vec3 ambHueSat = vec3(tmpAmbient) - vec3(ambValue);
+	 * tmpAmbient = vec4(RenderSSAOEffect.valueFactor * vec3(ambValue) + RenderSSAOEffect.saturationFactor *(1.0 - ambFactor) * ambHueSat, ambAlpha);
+	 */
+	tmpAmbient = vec4(mix(ssao_effect_mat * tmpAmbient.rgb, tmpAmbient.rgb, ambFactor), tmpAmbient.a);
+
+	//haze color
+	setAdditiveColor(
+		vec3(blue_horizon * blue_weight * (sunlight*(1.-cloud_shadow.x) + tmpAmbient)
+	  + (haze_horizon.r * haze_weight) * (sunlight*(1.-cloud_shadow.x) * temp2.x
+		  + tmpAmbient)));
+
+	//brightness of surface both sunlight and ambient
+	setSunlitColor(vec3(sunlight * .5));
+	setAmblitColor(vec3(tmpAmbient * .25));
+	setAdditiveColor(getAdditiveColor() * vec3(1.0 - temp1));
+}
+
+vec3 atmosLighting(vec3 light)
+{
+	light *= getAtmosAttenuation().r;
+	light += getAdditiveColor();
+	return (2.0 * light);
+}
+
+vec3 atmosTransport(vec3 light) {
+	light *= getAtmosAttenuation().r;
+	light += getAdditiveColor() * 2.0;
+	return light;
+}
+vec3 atmosGetDiffuseSunlightColor()
+{
+	return getSunlitColor();
+}
+
+vec3 scaleDownLight(vec3 light)
+{
+	return (light / scene_light_strength );
+}
+
+vec3 scaleUpLight(vec3 light)
+{
+	return (light * scene_light_strength);
+}
+
+vec3 atmosAmbient(vec3 light)
+{
+	return getAmblitColor() + light / 2.0;
+}
+
+vec3 atmosAffectDirectionalLight(float lightIntensity)
+{
+	return getSunlitColor() * lightIntensity;
+}
+
+vec3 scaleSoftClip(vec3 light)
+{
+	//soft clip effect:
+	light = 1. - clamp(light, vec3(0.), vec3(1.));
+	light = 1. - pow(light, gamma.xxx);
+
+	return light;
+}
+
+vec4 texture2DMS(sampler2DMS tex, ivec2 tc)
+{
+	vec4 ret = vec4(0,0,0,0);
+
+	for (int i = 0; i < samples; ++i)
+	{
+		 ret += texelFetch(tex,tc,i);
+	}
+
+	return ret/samples;
+}
+
+void main() 
+{
+	vec2 tc = vary_fragcoord.xy;
+	ivec2 itc = ivec2(tc);
+
+	vec3 fcol = vec3(0,0,0);
+
+	for (int i = 0; i < samples; ++i)
+	{
+		float depth = texelFetch(depthMap, itc, i).r;
+		vec3 pos = getPosition_d(tc, depth).xyz;
+		vec3 norm = texelFetch(normalMap, itc, i).xyz;
+
+		norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm
+		//vec3 nz = texture2D(noiseMap, vary_fragcoord.xy/128.0).xyz;
+	
+		float da = max(dot(norm.xyz, vary_light.xyz), 0.0);
+	
+		vec4 diffuse = texelFetch(diffuseRect, itc, i);
+		if (diffuse.a >= 1.0)
+		{
+			fcol += diffuse.rgb;
+		}
+		else
+		{
+			vec4 spec = texelFetch(specularRect, itc, i);
+	
+			calcAtmospherics(pos.xyz, 1.0);
+	
+			vec3 col = atmosAmbient(vec3(0));
+			col += atmosAffectDirectionalLight(max(min(da, 1.0), diffuse.a));
+	
+			col *= diffuse.rgb;
+	
+			if (spec.a > 0.0) // specular reflection
+			{
+				// the old infinite-sky shiny reflection
+				//
+				vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz));
+				float sa = dot(refnormpersp, vary_light.xyz);
+				vec3 dumbshiny = vary_SunlitColor*texture2D(lightFunc, vec2(sa, spec.a)).a;
+
+				// add the two types of shiny together
+				col += dumbshiny * spec.rgb;
+			}
+
+			col = atmosLighting(col);
+			col = scaleSoftClip(col);
+			fcol += col;
+		}
+	}
+				
+	gl_FragColor.rgb = fcol.rgb/samples;
+	gl_FragColor.a = 0.0;
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/softenLightV.glsl b/indra/newview/app_settings/shaders/class1/deferred/softenLightV.glsl
index 8f0bcca76b86a22f32101d0c81b3631110fff0c9..745cc0199236aeff1ade125a59f78bd48b15d382 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/softenLightV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/softenLightV.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 uniform vec2 screen_res;
 
diff --git a/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl
index 29fac46bfe2dc022fb812455d3d7b072a9155c4d..9aaffc15bf3acbeb7ba94cd120d819742a00ce83 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
 
-#version 120
+
 
 #extension GL_ARB_texture_rectangle : enable
 
diff --git a/indra/newview/app_settings/shaders/class1/deferred/spotLightMSF.glsl b/indra/newview/app_settings/shaders/class1/deferred/spotLightMSF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..4bb9bad2751bfc9c1da2352464aef5ba92c93245
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/spotLightMSF.glsl
@@ -0,0 +1,234 @@
+/** 
+ * @file multiSpotLightF.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+
+
+
+//class 1 -- no shadows
+
+#extension GL_ARB_texture_rectangle : enable
+#extension GL_ARB_texture_multisample : enable
+
+uniform sampler2DMS diffuseRect;
+uniform sampler2DMS specularRect;
+uniform sampler2DMS depthMap;
+uniform sampler2DMS normalMap;
+uniform sampler2D noiseMap;
+uniform sampler2D lightFunc;
+uniform sampler2D projectionMap;
+
+uniform mat4 proj_mat; //screen space to light space
+uniform float proj_near; //near clip for projection
+uniform vec3 proj_p; //plane projection is emitting from (in screen space)
+uniform vec3 proj_n;
+uniform float proj_focus; //distance from plane to begin blurring
+uniform float proj_lod;  //(number of mips in proj map)
+uniform float proj_range; //range between near clip and far clip plane of projection
+uniform float proj_ambient_lod;
+uniform float proj_ambiance;
+uniform float near_clip;
+uniform float far_clip;
+
+uniform vec3 proj_origin; //origin of projection to be used for angular attenuation
+uniform float sun_wash;
+uniform int proj_shadow_idx;
+uniform float shadow_fade;
+
+varying vec4 vary_light;
+
+varying vec4 vary_fragcoord;
+uniform vec2 screen_res;
+
+uniform mat4 inv_proj;
+
+vec4 texture2DLodSpecular(sampler2D projectionMap, vec2 tc, float lod)
+{
+	vec4 ret = texture2DLod(projectionMap, tc, lod);
+	
+	vec2 dist = tc-vec2(0.5);
+	
+	float det = max(1.0-lod/(proj_lod*0.5), 0.0);
+	
+	float d = dot(dist,dist);
+		
+	ret *= min(clamp((0.25-d)/0.25, 0.0, 1.0)+det, 1.0);
+	
+	return ret;
+}
+
+vec4 texture2DLodDiffuse(sampler2D projectionMap, vec2 tc, float lod)
+{
+	vec4 ret = texture2DLod(projectionMap, tc, lod);
+	
+	vec2 dist = vec2(0.5) - abs(tc-vec2(0.5));
+	
+	float det = min(lod/(proj_lod*0.5), 1.0);
+	
+	float d = min(dist.x, dist.y);
+	
+	float edge = 0.25*det;
+		
+	ret *= clamp(d/edge, 0.0, 1.0);
+	
+	return ret;
+}
+
+vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod)
+{
+	vec4 ret = texture2DLod(projectionMap, tc, lod);
+	
+	vec2 dist = tc-vec2(0.5);
+	
+	float d = dot(dist,dist);
+		
+	ret *= min(clamp((0.25-d)/0.25, 0.0, 1.0), 1.0);
+	
+	return ret;
+}
+
+
+vec4 getPosition(ivec2 pos_screen, int sample)
+{
+	float depth = texelFetch(depthMap, pos_screen, sample).r;
+	vec2 sc = vec2(pos_screen.xy)*2.0;
+	sc /= screen_res;
+	sc -= vec2(1.0,1.0);
+	vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+	vec4 pos = inv_proj * ndc;
+	pos /= pos.w;
+	pos.w = 1.0;
+	return pos;
+}
+
+void main() 
+{
+	vec4 frag = vary_fragcoord;
+	frag.xyz /= frag.w;
+	frag.xyz = frag.xyz*0.5+0.5;
+	frag.xy *= screen_res;
+	ivec2 itc = ivec2(frag.xy);
+
+	vec3 fcol = vec3(0,0,0);
+	int wght = 0;
+	
+	for (int i = 0; i < samples; ++i)
+	{
+		vec3 pos = getPosition(itc, i).xyz;
+		vec3 lv = vary_light.xyz-pos.xyz;
+		float dist2 = dot(lv,lv);
+		dist2 /= vary_light.w;
+		if (dist2 <= 1.0)
+		{
+			vec3 norm = texelFetch(normalMap, itc, i).xyz*2.0-1.0;
+	
+			norm = normalize(norm);
+			float l_dist = -dot(lv, proj_n);
+	
+			vec4 proj_tc = (proj_mat * vec4(pos.xyz, 1.0));
+			if (proj_tc.z >= 0.0)
+			{
+				proj_tc.xyz /= proj_tc.w;
+	
+				float fa = gl_Color.a+1.0;
+				float dist_atten = min(1.0-(dist2-1.0*(1.0-fa))/fa, 1.0);
+				if (dist_atten > 0.0)
+				{
+					lv = proj_origin-pos.xyz;
+					lv = normalize(lv);
+					float da = dot(norm, lv);
+		
+					vec3 col = vec3(0,0,0);
+		
+					vec3 diff_tex = texelFetch(diffuseRect, itc, i).rgb;
+		
+					float noise = texture2D(noiseMap, frag.xy/128.0).b;
+					if (proj_tc.z > 0.0 &&
+						proj_tc.x < 1.0 &&
+						proj_tc.y < 1.0 &&
+						proj_tc.x > 0.0 &&
+						proj_tc.y > 0.0)
+					{
+						float lit = 0.0;
+						float amb_da = proj_ambiance;
+		
+						if (da > 0.0)
+						{
+							float diff = clamp((l_dist-proj_focus)/proj_range, 0.0, 1.0);
+							float lod = diff * proj_lod;
+			
+							vec4 plcol = texture2DLodDiffuse(projectionMap, proj_tc.xy, lod);
+		
+							vec3 lcol = gl_Color.rgb * plcol.rgb * plcol.a;
+			
+							lit = da * dist_atten * noise;
+			
+							col = lcol*lit*diff_tex;
+							amb_da += (da*0.5)*proj_ambiance;
+						}
+		
+						//float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0);
+						vec4 amb_plcol = texture2DLodAmbient(projectionMap, proj_tc.xy, proj_lod);
+							
+						amb_da += (da*da*0.5+0.5)*proj_ambiance;
+				
+						amb_da *= dist_atten * noise;
+			
+						amb_da = min(amb_da, 1.0-lit);
+			
+						col += amb_da*gl_Color.rgb*diff_tex.rgb*amb_plcol.rgb*amb_plcol.a;
+					}
+	
+	
+					vec4 spec = texelFetch(specularRect, itc, i);
+					if (spec.a > 0.0)
+					{
+						vec3 ref = reflect(normalize(pos), norm);
+		
+						//project from point pos in direction ref to plane proj_p, proj_n
+						vec3 pdelta = proj_p-pos;
+						float ds = dot(ref, proj_n);
+		
+						if (ds < 0.0)
+						{
+							vec3 pfinal = pos + ref * dot(pdelta, proj_n)/ds;
+			
+							vec4 stc = (proj_mat * vec4(pfinal.xyz, 1.0));
+
+							if (stc.z > 0.0)
+							{
+								stc.xy /= stc.w;
+
+								float fatten = clamp(spec.a*spec.a+spec.a*0.5, 0.25, 1.0);
+				
+								stc.xy = (stc.xy - vec2(0.5)) * fatten + vec2(0.5);
+								
+								if (stc.x < 1.0 &&
+									stc.y < 1.0 &&
+									stc.x > 0.0 &&
+									stc.y > 0.0)
+								{
+									vec4 scol = texture2DLodSpecular(projectionMap, stc.xy, proj_lod-spec.a*proj_lod);
+									col += dist_atten*scol.rgb*gl_Color.rgb*scol.a*spec.rgb;
+								}
+							}
+						}
+					}
+	
+					fcol += col;
+					++wght;
+				}
+			}
+		}
+	}
+
+	if (wght <= 0)
+	{
+		discard;
+	}
+
+	gl_FragColor.rgb = fcol/samples;	
+	gl_FragColor.a = 0.0;
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/starsF.glsl b/indra/newview/app_settings/shaders/class1/deferred/starsF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..2cf7d194cc7926a2f6a2de96a6b1ccb5367733af
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/starsF.glsl
@@ -0,0 +1,19 @@
+/** 
+ * @file starsF.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+ 
+
+
+uniform sampler2D diffuseMap;
+
+void main() 
+{
+	vec4 col = gl_Color * texture2D(diffuseMap, gl_TexCoord[0].xy);
+	
+	gl_FragData[0] = col;
+	gl_FragData[1] = vec4(0,0,0,0);
+	gl_FragData[2] = vec4(0,0,1,0);	
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/starsV.glsl b/indra/newview/app_settings/shaders/class1/deferred/starsV.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..c43125dad9c4ccc76d324eca14e4572e405fce20
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/starsV.glsl
@@ -0,0 +1,17 @@
+/** 
+ * @file starsV.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+ 
+
+
+
+void main()
+{
+	//transform vertex
+	gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; 
+	gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
+	gl_FrontColor = gl_Color;
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/sunLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/sunLightF.glsl
index 00093836a25472d9a1fa6ee545d04451d37c6e73..f20886565a196be01bbc88e5b2fedbbc4eb42a87 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/sunLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/sunLightF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 //class 1, no shadow, no SSAO, should never be called
 
diff --git a/indra/newview/app_settings/shaders/class1/deferred/sunLightMSF.glsl b/indra/newview/app_settings/shaders/class1/deferred/sunLightMSF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..f20886565a196be01bbc88e5b2fedbbc4eb42a87
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/sunLightMSF.glsl
@@ -0,0 +1,17 @@
+/** 
+ * @file sunLightF.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+ 
+
+
+//class 1, no shadow, no SSAO, should never be called
+
+#extension GL_ARB_texture_rectangle : enable
+
+void main() 
+{
+	gl_FragColor = vec4(0,0,0,0);
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl b/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl
index cd91351ad411e91b425f478e65f6123f583ea01b..665d8126a07683c7aa4c156a99341ead53a930b7 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl
@@ -5,7 +5,7 @@
  * $License$
  */
  
-#version 120
+
 
 #extension GL_ARB_texture_rectangle : enable
 
@@ -35,7 +35,7 @@ uniform float shadow_offset;
 
 vec4 getPosition(vec2 pos_screen)
 {
-	float depth = texture2DRect(depthMap, pos_screen.xy).a;
+	float depth = texture2DRect(depthMap, pos_screen.xy).r;
 	vec2 sc = pos_screen.xy*2.0;
 	sc /= screen_res;
 	sc -= vec2(1.0,1.0);
diff --git a/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOMSF.glsl b/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOMSF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..32d1b2149a4ce5a1ef002592c4b4c7fda38f9d6d
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOMSF.glsl
@@ -0,0 +1,123 @@
+/** 
+ * @file sunLightSSAOF.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+ 
+
+
+#extension GL_ARB_texture_rectangle : enable
+#extension GL_ARB_texture_multisample : enable
+
+//class 1 -- no shadow, SSAO only
+
+uniform sampler2DMS depthMap;
+uniform sampler2DMS normalMap;
+uniform sampler2D noiseMap;
+
+
+// Inputs
+uniform mat4 shadow_matrix[6];
+uniform vec4 shadow_clip;
+uniform float ssao_radius;
+uniform float ssao_max_radius;
+uniform float ssao_factor;
+uniform float ssao_factor_inv;
+
+varying vec2 vary_fragcoord;
+varying vec4 vary_light;
+
+uniform mat4 inv_proj;
+uniform vec2 screen_res;
+
+uniform float shadow_bias;
+uniform float shadow_offset;
+
+vec4 getPosition(ivec2 pos_screen, int sample)
+{
+	float depth = texelFetch(depthMap, pos_screen, sample).r;
+	vec2 sc = pos_screen.xy*2.0;
+	sc /= screen_res;
+	sc -= vec2(1.0,1.0);
+	vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+	vec4 pos = inv_proj * ndc;
+	pos /= pos.w;
+	pos.w = 1.0;
+	return pos;
+}
+
+//calculate decreases in ambient lighting when crowded out (SSAO)
+float calcAmbientOcclusion(vec4 pos, vec3 norm, int sample)
+{
+	float ret = 1.0;
+	
+	vec2 kern[8];
+	// exponentially (^2) distant occlusion samples spread around origin
+	kern[0] = vec2(-1.0, 0.0) * 0.125*0.125;
+	kern[1] = vec2(1.0, 0.0) * 0.250*0.250;
+	kern[2] = vec2(0.0, 1.0) * 0.375*0.375;
+	kern[3] = vec2(0.0, -1.0) * 0.500*0.500;
+	kern[4] = vec2(0.7071, 0.7071) * 0.625*0.625;
+	kern[5] = vec2(-0.7071, -0.7071) * 0.750*0.750;
+	kern[6] = vec2(-0.7071, 0.7071) * 0.875*0.875;
+	kern[7] = vec2(0.7071, -0.7071) * 1.000*1.000;
+
+	vec2 pos_screen = vary_fragcoord.xy;
+	vec3 pos_world = pos.xyz;
+	vec2 noise_reflect = texture2D(noiseMap, vary_fragcoord.xy/128.0).xy;
+		
+	float angle_hidden = 0.0;
+	int points = 0;
+		
+	float scale = min(ssao_radius / -pos_world.z, ssao_max_radius);
+		
+	// it was found that keeping # of samples a constant was the fastest, probably due to compiler optimizations unrolling?)
+	for (int i = 0; i < 8; i++)
+	{
+		ivec2 samppos_screen = ivec2(pos_screen + scale * reflect(kern[i], noise_reflect));
+		vec3 samppos_world = getPosition(samppos_screen, sample).xyz; 
+			
+		vec3 diff = pos_world - samppos_world;
+		float dist2 = dot(diff, diff);
+			
+		// assume each sample corresponds to an occluding sphere with constant radius, constant x-sectional area
+		// --> solid angle shrinking by the square of distance
+		//radius is somewhat arbitrary, can approx with just some constant k * 1 / dist^2
+		//(k should vary inversely with # of samples, but this is taken care of later)
+			
+		angle_hidden = angle_hidden + float(dot((samppos_world - 0.05*norm - pos_world), norm) > 0.0) * min(1.0/dist2, ssao_factor_inv);
+			
+		// 'blocked' samples (significantly closer to camera relative to pos_world) are "no data", not "no occlusion" 
+		points = points + int(diff.z > -1.0);
+	}
+		
+	angle_hidden = min(ssao_factor*angle_hidden/float(points), 1.0);
+		
+	ret = (1.0 - (float(points != 0) * angle_hidden));
+	
+	return min(ret, 1.0);
+}
+
+void main() 
+{
+	vec2 pos_screen = vary_fragcoord.xy;
+	ivec2 itc = ivec2(pos_screen);
+		
+	float col = 0;
+
+	for (int i = 0; i < samples; i++)
+	{
+		vec4 pos = getPosition(itc, i);
+		vec3 norm = texelFetch(normalMap, itc, i).xyz;
+		norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm
+		col += calcAmbientOcclusion(pos,norm,i);
+	}
+
+	col /= samples;
+
+	gl_FragColor[0] = 1.0;
+	gl_FragColor[1] = col;
+	gl_FragColor[2] = 1.0; 
+	gl_FragColor[3] = 1.0;
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/sunLightV.glsl b/indra/newview/app_settings/shaders/class1/deferred/sunLightV.glsl
index 9beb513ad8a63a129b231381cb010e69c58b9510..814deb3677ab6489c305175878b9b905911996b5 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/sunLightV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/sunLightV.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 varying vec4 vary_light;
 varying vec2 vary_fragcoord;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl b/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl
index 0edae4791826e05939f027c54e6e2d64f05b6a7f..d005f67bf6c96c22f7d32b6a06e64a1fba0fca25 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 uniform sampler2D detail_0;
 uniform sampler2D detail_1;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl b/indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl
index a6163063bebecc5c23d812122b66c7b6b7ef52e8..3038fd296681900d004e67754beadfc18eeaccfd 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 varying vec3 vary_normal;
 
diff --git a/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl b/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl
index c54d9a1e3e80dcf0bc9ba20d70c92b346d4fa3dc..de7e038402235d2a6044aa200d102923b210ed78 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 uniform sampler2D diffuseMap;
 
diff --git a/indra/newview/app_settings/shaders/class1/deferred/treeV.glsl b/indra/newview/app_settings/shaders/class1/deferred/treeV.glsl
index 29689ecbafea503e78ef8c2413ed027c1e357885..a9bef4292de33cf182268663562bd8372d587cdd 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/treeV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/treeV.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 varying vec3 vary_normal;
 
diff --git a/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl b/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl
index e76f598d09de4cd973e867dd439901954cc4475b..2710422d32bad10dd52eb1e52263886dd534af84 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 #extension GL_ARB_texture_rectangle : enable
 
diff --git a/indra/newview/app_settings/shaders/class1/deferred/waterV.glsl b/indra/newview/app_settings/shaders/class1/deferred/waterV.glsl
index 649e3926300d27cf2a547230910f5a8dfba0c172..5397290b116b76b017854c3c37c84658a6931c90 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/waterV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/waterV.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 void calcAtmospherics(vec3 inPositionEye);
 
diff --git a/indra/newview/app_settings/shaders/class1/effects/glowExtractF.glsl b/indra/newview/app_settings/shaders/class1/effects/glowExtractF.glsl
index f2023fa5ea1a76d510ffdaaa19e70acfa63078e8..32f5f5f236043bd6f40fb5cff98d7b1a0de5dabd 100644
--- a/indra/newview/app_settings/shaders/class1/effects/glowExtractF.glsl
+++ b/indra/newview/app_settings/shaders/class1/effects/glowExtractF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 #extension GL_ARB_texture_rectangle : enable
 
diff --git a/indra/newview/app_settings/shaders/class1/effects/glowExtractMSF.glsl b/indra/newview/app_settings/shaders/class1/effects/glowExtractMSF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..9267a8585dadcc7ea88ea753dad066da2cd8a905
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/effects/glowExtractMSF.glsl
@@ -0,0 +1,38 @@
+/** 
+ * @file glowExtractF.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+ 
+
+
+#extension GL_ARB_texture_rectangle : enable
+#extension GL_ARB_texture_multisample : enable
+
+uniform sampler2DMS diffuseMap;
+uniform float minLuminance;
+uniform float maxExtractAlpha;
+uniform vec3 lumWeights;
+uniform vec3 warmthWeights;
+uniform float warmthAmount;
+
+void main()
+{
+	ivec2 itc = ivec2(gl_TexCoord[0].xy);
+	vec4 fcol = vec4(0,0,0,0);
+
+	for (int i = 0; i < samples; i++)
+	{
+		vec4 col = texelFetch(diffuseMap, itc, i);	
+
+		/// CALCULATING LUMINANCE (Using NTSC lum weights)
+		/// http://en.wikipedia.org/wiki/Luma_%28video%29
+		float lum = smoothstep(minLuminance, minLuminance+1.0, dot(col.rgb, lumWeights ) );
+		float warmth = smoothstep(minLuminance, minLuminance+1.0, max(col.r * warmthWeights.r, max(col.g * warmthWeights.g, col.b * warmthWeights.b)) ); 
+	
+		fcol += vec4(col.rgb, max(col.a, mix(lum, warmth, warmthAmount) * maxExtractAlpha));
+	}
+
+	gl_FragColor = fcol/samples;
+}
diff --git a/indra/newview/app_settings/shaders/class1/effects/glowExtractV.glsl b/indra/newview/app_settings/shaders/class1/effects/glowExtractV.glsl
index 0ca0608b45aefebae7f54ce1016af2ead16223a5..76736fed53be470fc93969babe3cdc41516474d6 100644
--- a/indra/newview/app_settings/shaders/class1/effects/glowExtractV.glsl
+++ b/indra/newview/app_settings/shaders/class1/effects/glowExtractV.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
 
-#version 120
+
 
 void main() 
 {
diff --git a/indra/newview/app_settings/shaders/class1/effects/glowF.glsl b/indra/newview/app_settings/shaders/class1/effects/glowF.glsl
index 65fc2e9f99bc9b3bc9036c3658dfb93a51498467..d3225546b3041d2d5a7e68f2c417e06af37c17f0 100644
--- a/indra/newview/app_settings/shaders/class1/effects/glowF.glsl
+++ b/indra/newview/app_settings/shaders/class1/effects/glowF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 uniform sampler2D diffuseMap;
 uniform float glowStrength;
diff --git a/indra/newview/app_settings/shaders/class1/effects/glowV.glsl b/indra/newview/app_settings/shaders/class1/effects/glowV.glsl
index 0bd44cec903643cb7715b843524663886912e073..9bb41626ae6183ab6d1cd524697151cae7101d82 100644
--- a/indra/newview/app_settings/shaders/class1/effects/glowV.glsl
+++ b/indra/newview/app_settings/shaders/class1/effects/glowV.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 uniform vec2 glowDelta;
 
diff --git a/indra/newview/app_settings/shaders/class1/environment/terrainF.glsl b/indra/newview/app_settings/shaders/class1/environment/terrainF.glsl
index ac00f15b35b830f63cf6f11975994f261a08461d..cdc2ca3da2f832b2ef53666ef442f5febd7f27cd 100644
--- a/indra/newview/app_settings/shaders/class1/environment/terrainF.glsl
+++ b/indra/newview/app_settings/shaders/class1/environment/terrainF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 uniform sampler2D detail0;
 uniform sampler2D detail1;
diff --git a/indra/newview/app_settings/shaders/class1/environment/terrainV.glsl b/indra/newview/app_settings/shaders/class1/environment/terrainV.glsl
index 1e19ee7699f4e97fa046b6092ea1e700f582b53b..8af981915bceea719f62cda3153a9ae3368befbf 100644
--- a/indra/newview/app_settings/shaders/class1/environment/terrainV.glsl
+++ b/indra/newview/app_settings/shaders/class1/environment/terrainV.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol);
 
diff --git a/indra/newview/app_settings/shaders/class1/environment/terrainWaterF.glsl b/indra/newview/app_settings/shaders/class1/environment/terrainWaterF.glsl
index 34f78565a5c3746d5de909709da4b918249d46a3..d94d986581bbbbb8044e0e8391cfc72ac95deed8 100644
--- a/indra/newview/app_settings/shaders/class1/environment/terrainWaterF.glsl
+++ b/indra/newview/app_settings/shaders/class1/environment/terrainWaterF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 // this class1 shader is just a copy of terrainF
 
diff --git a/indra/newview/app_settings/shaders/class1/environment/underWaterF.glsl b/indra/newview/app_settings/shaders/class1/environment/underWaterF.glsl
index 0dfac84a6e1928590de0cb72dc218f877c8ebb7f..06854fcc0a0a874d1e4aafed94697b07242d3a63 100644
--- a/indra/newview/app_settings/shaders/class1/environment/underWaterF.glsl
+++ b/indra/newview/app_settings/shaders/class1/environment/underWaterF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 uniform sampler2D diffuseMap;
 uniform sampler2D bumpMap;   
diff --git a/indra/newview/app_settings/shaders/class1/environment/waterF.glsl b/indra/newview/app_settings/shaders/class1/environment/waterF.glsl
index 4e9c09b1ea7a6dcf13fe07d22e24bb4311329dd5..0f24e3c35afff6d019ce8b1f425d02c40027aae1 100644
--- a/indra/newview/app_settings/shaders/class1/environment/waterF.glsl
+++ b/indra/newview/app_settings/shaders/class1/environment/waterF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 vec3 scaleSoftClip(vec3 inColor);
 vec3 atmosTransport(vec3 inColor);
diff --git a/indra/newview/app_settings/shaders/class1/environment/waterFogF.glsl b/indra/newview/app_settings/shaders/class1/environment/waterFogF.glsl
index a34cf23790d5bf57abdfa2c1ecaa64cc5d1ee8be..630459b3245b1880d44d48e6d924c5d05ebd9f7b 100644
--- a/indra/newview/app_settings/shaders/class1/environment/waterFogF.glsl
+++ b/indra/newview/app_settings/shaders/class1/environment/waterFogF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 vec4 applyWaterFog(vec4 color)
 {
diff --git a/indra/newview/app_settings/shaders/class1/environment/waterV.glsl b/indra/newview/app_settings/shaders/class1/environment/waterV.glsl
index 161c794c68f7883207ae8227d43179e21b28ce8f..831d6a761c75dec5b9fbfb2072adac0e68a7320c 100644
--- a/indra/newview/app_settings/shaders/class1/environment/waterV.glsl
+++ b/indra/newview/app_settings/shaders/class1/environment/waterV.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 void calcAtmospherics(vec3 inPositionEye);
 
diff --git a/indra/newview/app_settings/shaders/class1/interface/highlightF.glsl b/indra/newview/app_settings/shaders/class1/interface/highlightF.glsl
index 6f821f893d6faab36e2d78c2ce054574aee3c3a6..f6c6d945de38d72189664b29b34b4252cbac5d39 100644
--- a/indra/newview/app_settings/shaders/class1/interface/highlightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/interface/highlightF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 uniform sampler2D diffuseMap;
 
diff --git a/indra/newview/app_settings/shaders/class1/interface/highlightV.glsl b/indra/newview/app_settings/shaders/class1/interface/highlightV.glsl
index d1c98bf70cbfc39b54e6e28e96e266de3828a4a0..f114f766bf66bb82d9d959ea9718dc4f21250aeb 100644
--- a/indra/newview/app_settings/shaders/class1/interface/highlightV.glsl
+++ b/indra/newview/app_settings/shaders/class1/interface/highlightV.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 void main()
 {
diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightF.glsl
index 9c59e8c3ad719d3f9d298c849354098b0b1d619d..1796730c923d907aac4a9ac14eb1ca43f1ab6057 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/lightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/lightF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 uniform sampler2D diffuseMap;
 
diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightF.glsl
index 1fee99c446f214a9237d1225b86cd5906613a46f..bfe0be9fdf5c29f97aaa5852e96ac12f35e89d40 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 
 uniform sampler2D diffuseMap;
diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyF.glsl
index fb5da21c72227b8ce91e757fa23a39d6904d1a61..6f1fe9100707f7a4af9e019ce57d1826f2e207be 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyF.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 
 uniform sampler2D diffuseMap;
diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyWaterF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyWaterF.glsl
index 1bdaccf9b8f2598666b19a1780626949ea71cf2b..19072cd052198bcd76719ea233279a6bf18db0e3 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyWaterF.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyWaterF.glsl
@@ -6,7 +6,7 @@
  */
 
  
-#version 120
+
 
 uniform sampler2D diffuseMap;
 uniform samplerCube environmentMap;
diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterF.glsl
index 2e94d3bbf1955bea23c80c08691f7de8af140150..0ae6dc89e25a4c5ecb4bdcb557f1651b4717a4eb 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterF.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterF.glsl
@@ -6,7 +6,7 @@
  */
 
  
-#version 120
+
 
 uniform sampler2D diffuseMap;
 
diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFuncSpecularV.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFuncSpecularV.glsl
index 714f9a2551005f78c2a88bdd869b8163299236f8..5d4bf2c33e8a0095007f818ac719078df14a8e0d 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/lightFuncSpecularV.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/lightFuncSpecularV.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 float calcDirectionalLight(vec3 n, vec3 l)
 {
diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFuncV.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFuncV.glsl
index 65b45f80818c376fe9d8ca1fd16fb73a1189e327..574252af12f4464161ea4d16f3aeffb068a98a2d 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/lightFuncV.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/lightFuncV.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 
 float calcDirectionalLight(vec3 n, vec3 l)
diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightShinyF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightShinyF.glsl
index 7f65ea76f71c156fbbfc3119e3f791c69b782bfe..29f575b7e5d29ceef8af80f2d35fca62c0a2074e 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/lightShinyF.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/lightShinyF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 
 uniform sampler2D diffuseMap;
diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightShinyWaterF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightShinyWaterF.glsl
index 8f13e6dc0447138b2d4cf8afa8008b07e3a91e0f..65da5a68255311dcb0184e7847e0d573ef76e09f 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/lightShinyWaterF.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/lightShinyWaterF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 
 uniform sampler2D diffuseMap;
diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightSpecularV.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightSpecularV.glsl
index 56f31f6a79b2f7c8ae0feb748178e31efd771caf..d491f1102ea7cec45fe88cf74987c765e1d7ac34 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/lightSpecularV.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/lightSpecularV.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 float calcDirectionalLight(vec3 n, vec3 l);
 
diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightV.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightV.glsl
index 64d549ff5299d898a385ec6c6062227a65c38f38..ef38ee9699faca4b47b5d8615b7e3256f78e52af 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/lightV.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/lightV.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 float calcDirectionalLight(vec3 n, vec3 l);
 
diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightWaterF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightWaterF.glsl
index c5d084c1323509ced287ea0bae5a2e4ce8f782da..286c92326b965074212497634f35524fa4f021e7 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/lightWaterF.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/lightWaterF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 uniform sampler2D diffuseMap;
 
diff --git a/indra/newview/app_settings/shaders/class1/lighting/sumLightsSpecularV.glsl b/indra/newview/app_settings/shaders/class1/lighting/sumLightsSpecularV.glsl
index 732d2464719fa82dee191028f128d9668297f8bd..772a420e33335fd683ab053e8b59c3dac092fd50 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/sumLightsSpecularV.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/sumLightsSpecularV.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
   
-#version 120
+
 
 float calcDirectionalLightSpecular(inout vec4 specular, vec3 view, vec3 n, vec3 l, vec3 lightCol, float da);
 vec3 atmosAmbient(vec3 light);
diff --git a/indra/newview/app_settings/shaders/class1/lighting/sumLightsV.glsl b/indra/newview/app_settings/shaders/class1/lighting/sumLightsV.glsl
index 73e1a1ec26eaa41c3b1adfbd625b23707e0fced5..da60a3ddf51e3cde2d691ba0d55442b483a4acc4 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/sumLightsV.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/sumLightsV.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 float calcDirectionalLight(vec3 n, vec3 l);
 
diff --git a/indra/newview/app_settings/shaders/class1/objects/fullbrightF.glsl b/indra/newview/app_settings/shaders/class1/objects/fullbrightF.glsl
index afc3dc89bf457484f050ff0771bedc3af5a202a7..c0b72115dd08974aa5dd550712255ac3bf5317ae 100644
--- a/indra/newview/app_settings/shaders/class1/objects/fullbrightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/objects/fullbrightF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 void fullbright_lighting();
 
diff --git a/indra/newview/app_settings/shaders/class1/objects/fullbrightShinyF.glsl b/indra/newview/app_settings/shaders/class1/objects/fullbrightShinyF.glsl
index 3dc4294f6781d11bf7a86ead0232a3a2430b0451..391c06edc87bd6d4a77d0c2d866d2f8f8def21d1 100644
--- a/indra/newview/app_settings/shaders/class1/objects/fullbrightShinyF.glsl
+++ b/indra/newview/app_settings/shaders/class1/objects/fullbrightShinyF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 void fullbright_shiny_lighting();
 
diff --git a/indra/newview/app_settings/shaders/class1/objects/fullbrightShinySkinnedV.glsl b/indra/newview/app_settings/shaders/class1/objects/fullbrightShinySkinnedV.glsl
index f0baeeeee58c787e65ec53f65d4cd4ffe4fb0de1..f44a5ce32e5ab4760f27269a464b65a7ee5f9121 100644
--- a/indra/newview/app_settings/shaders/class1/objects/fullbrightShinySkinnedV.glsl
+++ b/indra/newview/app_settings/shaders/class1/objects/fullbrightShinySkinnedV.glsl
@@ -5,7 +5,7 @@
  * $License$
  */
 
-#version 120
+
 
 void calcAtmospherics(vec3 inPositionEye);
 mat4 getObjectSkinnedTransform();
diff --git a/indra/newview/app_settings/shaders/class1/objects/fullbrightShinyV.glsl b/indra/newview/app_settings/shaders/class1/objects/fullbrightShinyV.glsl
index 02367b94393739692337d0740827c8246924ee80..31e0f0a429a6eb300b53ebb5d5c5416aa10d6638 100644
--- a/indra/newview/app_settings/shaders/class1/objects/fullbrightShinyV.glsl
+++ b/indra/newview/app_settings/shaders/class1/objects/fullbrightShinyV.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 void calcAtmospherics(vec3 inPositionEye);
 
diff --git a/indra/newview/app_settings/shaders/class1/objects/fullbrightShinyWaterF.glsl b/indra/newview/app_settings/shaders/class1/objects/fullbrightShinyWaterF.glsl
index 5daf66fb3108400b3613858b3c2f2139f14f0acd..8ffb252f57a86bc452853ce800f0a65561999053 100644
--- a/indra/newview/app_settings/shaders/class1/objects/fullbrightShinyWaterF.glsl
+++ b/indra/newview/app_settings/shaders/class1/objects/fullbrightShinyWaterF.glsl
@@ -5,7 +5,7 @@
  * $License$
  */
  
-#version 120
+
 
 void fullbright_shiny_lighting_water();
 
diff --git a/indra/newview/app_settings/shaders/class1/objects/fullbrightSkinnedV.glsl b/indra/newview/app_settings/shaders/class1/objects/fullbrightSkinnedV.glsl
index 02ff3cc2a96382d969bc020b3f87604cc9e462e7..e5dafa8c789e07ee9069ba1ae34ec30718888004 100644
--- a/indra/newview/app_settings/shaders/class1/objects/fullbrightSkinnedV.glsl
+++ b/indra/newview/app_settings/shaders/class1/objects/fullbrightSkinnedV.glsl
@@ -5,7 +5,7 @@
  * $License$
  */
 
-#version 120
+
 
 void calcAtmospherics(vec3 inPositionEye);
 mat4 getObjectSkinnedTransform();
diff --git a/indra/newview/app_settings/shaders/class1/objects/fullbrightV.glsl b/indra/newview/app_settings/shaders/class1/objects/fullbrightV.glsl
index 38e07dbd80c545f3413f3ca3c5913ebd9a6bc040..3382384c995bf3a33792b19755b33115bd649895 100644
--- a/indra/newview/app_settings/shaders/class1/objects/fullbrightV.glsl
+++ b/indra/newview/app_settings/shaders/class1/objects/fullbrightV.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 void calcAtmospherics(vec3 inPositionEye);
 
diff --git a/indra/newview/app_settings/shaders/class1/objects/fullbrightWaterF.glsl b/indra/newview/app_settings/shaders/class1/objects/fullbrightWaterF.glsl
index afaac4f69c524555118bb5029a45e8dcf914161e..220f26614f3259e6b173e6abf798018e7d5054b0 100644
--- a/indra/newview/app_settings/shaders/class1/objects/fullbrightWaterF.glsl
+++ b/indra/newview/app_settings/shaders/class1/objects/fullbrightWaterF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 void fullbright_lighting_water();
 
diff --git a/indra/newview/app_settings/shaders/class1/objects/shinyF.glsl b/indra/newview/app_settings/shaders/class1/objects/shinyF.glsl
index 2cf7a69baac7ae157088045d51fb6fe19bc886d1..d079de53773baac4981fa9e016c758c8b4bf0310 100644
--- a/indra/newview/app_settings/shaders/class1/objects/shinyF.glsl
+++ b/indra/newview/app_settings/shaders/class1/objects/shinyF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 void shiny_lighting();
 
diff --git a/indra/newview/app_settings/shaders/class1/objects/shinySimpleSkinnedV.glsl b/indra/newview/app_settings/shaders/class1/objects/shinySimpleSkinnedV.glsl
index 4146646058de4abbfb34a057243967421f838f7b..cd655f3bb51cde3cf018f6cfa20cef2f5efa5416 100644
--- a/indra/newview/app_settings/shaders/class1/objects/shinySimpleSkinnedV.glsl
+++ b/indra/newview/app_settings/shaders/class1/objects/shinySimpleSkinnedV.glsl
@@ -5,7 +5,7 @@
  * $License$
  */
 
-#version 120
+
 
 vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol);
 void calcAtmospherics(vec3 inPositionEye);
diff --git a/indra/newview/app_settings/shaders/class1/objects/shinyV.glsl b/indra/newview/app_settings/shaders/class1/objects/shinyV.glsl
index 6ea83b721defd91a9cf7cf46d665f5eed8ce517a..68a086dbc1a5da2c567e7e0ddc6fb63186858f21 100644
--- a/indra/newview/app_settings/shaders/class1/objects/shinyV.glsl
+++ b/indra/newview/app_settings/shaders/class1/objects/shinyV.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 void calcAtmospherics(vec3 inPositionEye);
 
diff --git a/indra/newview/app_settings/shaders/class1/objects/shinyWaterF.glsl b/indra/newview/app_settings/shaders/class1/objects/shinyWaterF.glsl
index e3babe2210f6c10fcb7f5347448893d409cefb16..4649d1c47c10175c9fc26516bdda4edace36a91a 100644
--- a/indra/newview/app_settings/shaders/class1/objects/shinyWaterF.glsl
+++ b/indra/newview/app_settings/shaders/class1/objects/shinyWaterF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 void shiny_lighting_water();
 
diff --git a/indra/newview/app_settings/shaders/class1/objects/simpleF.glsl b/indra/newview/app_settings/shaders/class1/objects/simpleF.glsl
index d449d37c0c7f499b1ccce65b25d0d39af2c20060..b4e4dcfbbf14fa7a59f49add2de3521a31a919ee 100644
--- a/indra/newview/app_settings/shaders/class1/objects/simpleF.glsl
+++ b/indra/newview/app_settings/shaders/class1/objects/simpleF.glsl
@@ -5,8 +5,6 @@
  * $/LicenseInfo$
  */
  
-#version 120
-
 void default_lighting();
 
 void main() 
diff --git a/indra/newview/app_settings/shaders/class1/objects/simpleSkinnedV.glsl b/indra/newview/app_settings/shaders/class1/objects/simpleSkinnedV.glsl
index be38a14d527c7eb5d588a6d3780e3dd3b4e14aab..900448035c44a78a29fde95f33dff7b05852efe8 100644
--- a/indra/newview/app_settings/shaders/class1/objects/simpleSkinnedV.glsl
+++ b/indra/newview/app_settings/shaders/class1/objects/simpleSkinnedV.glsl
@@ -5,7 +5,7 @@
  * $License$
  */
 
-#version 120
+
 
 vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol);
 void calcAtmospherics(vec3 inPositionEye);
diff --git a/indra/newview/app_settings/shaders/class1/objects/simpleV.glsl b/indra/newview/app_settings/shaders/class1/objects/simpleV.glsl
index 0d8e14e2e38ee1f3eafd858b2db37a208680c227..b493f76fcc60ce17619dbb09a46fbde93e2fa63d 100644
--- a/indra/newview/app_settings/shaders/class1/objects/simpleV.glsl
+++ b/indra/newview/app_settings/shaders/class1/objects/simpleV.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol);
 void calcAtmospherics(vec3 inPositionEye);
diff --git a/indra/newview/app_settings/shaders/class1/objects/simpleWaterF.glsl b/indra/newview/app_settings/shaders/class1/objects/simpleWaterF.glsl
index 68bd81e029328495ea7350222507de43257b9fdc..4ec5ee43b416d95b8937d398c2c3abfbc4ced9dd 100644
--- a/indra/newview/app_settings/shaders/class1/objects/simpleWaterF.glsl
+++ b/indra/newview/app_settings/shaders/class1/objects/simpleWaterF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 void default_lighting_water();
 
diff --git a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsF.glsl b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsF.glsl
index f337bde32922bf4b183ec7a8288f10830c0f4d3a..3d05850ab3d0e3da1b5e99c3f5489cad3adcbf92 100644
--- a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsF.glsl
+++ b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 vec3 atmosLighting(vec3 light)
 {
diff --git a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsHelpersV.glsl b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsHelpersV.glsl
index 4b402a70287c6fe1580983b0d39a599fbe783346..f1a0af21afe7315a6dc9175b35df48ab4b5c8410 100644
--- a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsHelpersV.glsl
+++ b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsHelpersV.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 vec3 atmosAmbient(vec3 light)
 {
diff --git a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsV.glsl b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsV.glsl
index 20948b1e468d07d6a6bd402c09cdf9a5623cde59..73bbd57315af369b277d5303652540829935c5a2 100644
--- a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsV.glsl
+++ b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsV.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 void setPositionEye(vec3 v);
 
diff --git a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsF.glsl b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsF.glsl
index 8a2c2a71862fb7402c313f95af0e03248262e8c4..e0eb7b37672e3c9dd242feb3195231ab3103568e 100644
--- a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsF.glsl
+++ b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 varying vec3 vary_PositionEye;
 
diff --git a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsV.glsl b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsV.glsl
index a1dd4ed5fedefd11993c77b5fa129a1815093d98..a251213ff535eaa4121ec9926ebbb83387aefecb 100644
--- a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsV.glsl
+++ b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsV.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 varying vec3 vary_PositionEye;
 
diff --git a/indra/newview/app_settings/shaders/class1/windlight/gammaF.glsl b/indra/newview/app_settings/shaders/class1/windlight/gammaF.glsl
index 7aed1fd3b5cd52c82194cc5b751d832e9259bb99..4958cb2f72a4ce2b421096e64f4f0e1facf8951c 100644
--- a/indra/newview/app_settings/shaders/class1/windlight/gammaF.glsl
+++ b/indra/newview/app_settings/shaders/class1/windlight/gammaF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 uniform vec4 gamma;
 
diff --git a/indra/newview/app_settings/shaders/class1/windlight/transportF.glsl b/indra/newview/app_settings/shaders/class1/windlight/transportF.glsl
index 6780dc4d3e1249c3eca244acc7e5fe4ced295851..75929bc6090ba10fc69e3f2765c70a946e7f6ac0 100644
--- a/indra/newview/app_settings/shaders/class1/windlight/transportF.glsl
+++ b/indra/newview/app_settings/shaders/class1/windlight/transportF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 vec3 atmosTransport(vec3 light)
 {
diff --git a/indra/newview/app_settings/shaders/class2/avatar/eyeballV.glsl b/indra/newview/app_settings/shaders/class2/avatar/eyeballV.glsl
index 172c2ca078ad4a7f5402a8b882d4f18877c23013..3e8b719f9392bc800651c762621924063e6392b9 100644
--- a/indra/newview/app_settings/shaders/class2/avatar/eyeballV.glsl
+++ b/indra/newview/app_settings/shaders/class2/avatar/eyeballV.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 vec4 calcLightingSpecular(vec3 pos, vec3 norm, vec4 color, inout vec4 specularColor, vec4 baseCol);
 void calcAtmospherics(vec3 inPositionEye);
diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl
index 6dfc1b952c1fc52bb82e8d690228c57d65d13457..681e52de2ab7ac45578dd229cf43c6e1f6a463aa 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl
@@ -5,11 +5,10 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 #extension GL_ARB_texture_rectangle : enable
 
-uniform sampler2D diffuseMap;
 uniform sampler2DRectShadow shadowMap0;
 uniform sampler2DRectShadow shadowMap1;
 uniform sampler2DRectShadow shadowMap2;
@@ -105,7 +104,7 @@ void main()
 		}
 	}
 	
-	vec4 diff= texture2D(diffuseMap, gl_TexCoord[0].xy);
+	vec4 diff = diffuseLookup(gl_TexCoord[0].xy);
 
 	vec4 col = vec4(vary_ambient + vary_directional.rgb*shadow, gl_Color.a);
 	vec4 color = diff * col;
diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaNonIndexedF.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaNonIndexedF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..5350359f750676b104cc741f9b3ad00cd2c2f589
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/deferred/alphaNonIndexedF.glsl
@@ -0,0 +1,125 @@
+/** 
+ * @file alphaF.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+ 
+
+
+#extension GL_ARB_texture_rectangle : enable
+
+uniform sampler2DRectShadow shadowMap0;
+uniform sampler2DRectShadow shadowMap1;
+uniform sampler2DRectShadow shadowMap2;
+uniform sampler2DRectShadow shadowMap3;
+uniform sampler2DRect depthMap;
+uniform sampler2D diffuseMap;
+
+uniform mat4 shadow_matrix[6];
+uniform vec4 shadow_clip;
+uniform vec2 screen_res;
+uniform vec2 shadow_res;
+
+vec3 atmosLighting(vec3 light);
+vec3 scaleSoftClip(vec3 light);
+
+varying vec3 vary_ambient;
+varying vec3 vary_directional;
+varying vec3 vary_fragcoord;
+varying vec3 vary_position;
+varying vec3 vary_pointlight_col;
+
+uniform float shadow_bias;
+
+uniform mat4 inv_proj;
+
+vec4 getPosition(vec2 pos_screen)
+{
+	float depth = texture2DRect(depthMap, pos_screen.xy).a;
+	vec2 sc = pos_screen.xy*2.0;
+	sc /= screen_res;
+	sc -= vec2(1.0,1.0);
+	vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+	vec4 pos = inv_proj * ndc;
+	pos.xyz /= pos.w;
+	pos.w = 1.0;
+	return pos;
+}
+
+float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc, float scl)
+{
+	stc.xyz /= stc.w;
+	stc.z += shadow_bias;
+	
+	float cs = shadow2DRect(shadowMap, stc.xyz).x;
+	float shadow = cs;
+
+	shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(scl, scl, 0.0)).x, cs);
+	shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(scl, -scl, 0.0)).x, cs);
+	shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-scl, scl, 0.0)).x, cs);
+	shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-scl, -scl, 0.0)).x, cs);
+			
+	return shadow/5.0;
+}
+
+
+void main() 
+{
+	vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5;
+	frag *= screen_res;
+	
+	float shadow = 1.0;
+	vec4 pos = vec4(vary_position, 1.0);
+	
+	vec4 spos = pos;
+		
+	if (spos.z > -shadow_clip.w)
+	{	
+		vec4 lpos;
+		
+		if (spos.z < -shadow_clip.z)
+		{
+			lpos = shadow_matrix[3]*spos;
+			lpos.xy *= shadow_res;
+			shadow = pcfShadow(shadowMap3, lpos, 1.5);
+			shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0);
+		}
+		else if (spos.z < -shadow_clip.y)
+		{
+			lpos = shadow_matrix[2]*spos;
+			lpos.xy *= shadow_res;
+			shadow = pcfShadow(shadowMap2, lpos, 1.5);
+		}
+		else if (spos.z < -shadow_clip.x)
+		{
+			lpos = shadow_matrix[1]*spos;
+			lpos.xy *= shadow_res;
+			shadow = pcfShadow(shadowMap1, lpos, 1.5);
+		}
+		else
+		{
+			lpos = shadow_matrix[0]*spos;
+			lpos.xy *= shadow_res;
+			shadow = pcfShadow(shadowMap0, lpos, 1.5);
+		}
+	}
+	
+	vec4 diff = texture2D(diffuseMap,gl_TexCoord[0].xy);
+
+	vec4 col = vec4(vary_ambient + vary_directional.rgb*shadow, gl_Color.a);
+	vec4 color = diff * col;
+	
+	color.rgb = atmosLighting(color.rgb);
+
+	color.rgb = scaleSoftClip(color.rgb);
+
+	color.rgb += diff.rgb * vary_pointlight_col.rgb;
+
+	//gl_FragColor = gl_Color;
+	gl_FragColor = color;
+	//gl_FragColor.r = 0.0;
+	//gl_FragColor = vec4(1,shadow,1,1);
+	
+}
+
diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaSkinnedV.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaSkinnedV.glsl
index dfb36980b006cb6b56ceda38ee0540fbf584e0c3..948a52da5b83f96d9ffe1878dd99154a1bc31fee 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/alphaSkinnedV.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/alphaSkinnedV.glsl
@@ -5,7 +5,7 @@
  * $License$
  */
  
-#version 120
+
 
 vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol);
 void calcAtmospherics(vec3 inPositionEye);
diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl
index f6160815ebb51b5afa5b3720d8cc2702bd041150..f616ecc872389ba7a816d2b0c3fb3ae688b7f368 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol);
 void calcAtmospherics(vec3 inPositionEye);
@@ -22,6 +22,7 @@ varying vec3 vary_directional;
 varying vec3 vary_fragcoord;
 varying vec3 vary_position;
 varying vec3 vary_pointlight_col;
+varying float vary_texture_index;
 
 uniform float near_clip;
 uniform float shadow_offset;
@@ -60,11 +61,13 @@ float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, floa
 void main()
 {
 	//transform vertex
-	gl_Position = ftransform(); 
+	vec4 vert = vec4(gl_Vertex.xyz, 1.0);
+	vary_texture_index = gl_Vertex.w;
+	gl_Position = gl_ModelViewProjectionMatrix * vert; 
 	
 	gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
 	
-	vec4 pos = (gl_ModelViewMatrix * gl_Vertex);
+	vec4 pos = (gl_ModelViewMatrix * vert);
 	vec3 norm = normalize(gl_NormalMatrix * gl_Normal);
 	
 	float dp_directional_light = max(0.0, dot(norm, gl_LightSource[0].position.xyz));
@@ -99,7 +102,7 @@ void main()
 
 	gl_FogFragCoord = pos.z;
 	
-	pos = gl_ModelViewProjectionMatrix * gl_Vertex;
+	pos = gl_ModelViewProjectionMatrix * vert;
 	vary_fragcoord.xyz = pos.xyz + vec3(0,0,near_clip);
 	
 }
diff --git a/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl b/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl
index 0ae09df0c6d1262e6e475f2e3ef6b566bb2f2fdd..01e40afc4f22150c2f488fcbfac7856b6815a583 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol);
 mat4 getSkinnedTransform();
diff --git a/indra/newview/app_settings/shaders/class2/deferred/edgeF.glsl b/indra/newview/app_settings/shaders/class2/deferred/edgeF.glsl
index 3155f3f9295a3602e8eaa1915910fd58226a48d8..729e4b55435068b2f58ec5e8a41f6f99382bc429 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/edgeF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/edgeF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 #extension GL_ARB_texture_rectangle : enable
 
@@ -22,7 +22,7 @@ uniform vec2 screen_res;
 
 float getDepth(vec2 pos_screen)
 {
-	float z = texture2DRect(depthMap, pos_screen.xy).a;
+	float z = texture2DRect(depthMap, pos_screen.xy).r;
 	z = z*2.0-1.0;
 	vec4 ndc = vec4(0.0, 0.0, z, 1.0);
 	vec4 p = inv_proj*ndc;
diff --git a/indra/newview/app_settings/shaders/class2/deferred/edgeMSF.glsl b/indra/newview/app_settings/shaders/class2/deferred/edgeMSF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..b22bc5b28828f2b7db99f79076cf65a2553af0bc
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/deferred/edgeMSF.glsl
@@ -0,0 +1,74 @@
+/** 
+ * @file edgeF.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+ 
+
+
+#extension GL_ARB_texture_rectangle : enable
+#extension GL_ARB_texture_multisample : enable
+
+uniform sampler2DMS depthMap;
+uniform sampler2DMS normalMap;
+
+varying vec2 vary_fragcoord;
+
+uniform float depth_cutoff;
+uniform float norm_cutoff;
+
+uniform mat4 inv_proj;
+uniform vec2 screen_res;
+
+float getDepth(ivec2 pos_screen, int sample)
+{
+	float z = texelFetch(depthMap, pos_screen, sample).r;
+	z = z*2.0-1.0;
+	vec4 ndc = vec4(0.0, 0.0, z, 1.0);
+	vec4 p = inv_proj*ndc;
+	return p.z/p.w;
+}
+
+void main() 
+{
+	float e = 0;
+	
+	ivec2 itc = ivec2(vary_fragcoord.xy);
+
+	for (int i = 0; i < samples; i++)
+	{	
+		vec3 norm = texelFetch(normalMap, itc, i).xyz;
+		norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm
+		float depth = getDepth(itc, i);
+	
+		vec2 tc = vary_fragcoord.xy;
+	
+		int sc = 1;
+	
+		vec2 de;
+		de.x = (depth-getDepth(itc+ivec2(sc, sc),i)) + (depth-getDepth(itc+ivec2(-sc, -sc), i));
+		de.y = (depth-getDepth(itc+ivec2(-sc, sc),i)) + (depth-getDepth(itc+ivec2(sc, -sc), i));
+		de /= depth;
+		de *= de;
+		de = step(depth_cutoff, de);
+	
+		vec2 ne;
+		vec3 nexnorm = texelFetch(normalMap, itc+ivec2(-sc,-sc), i).rgb;
+		nexnorm = vec3((nexnorm.xy-0.5)*2.0,nexnorm.z); // unpack norm
+		ne.x = dot(nexnorm, norm);
+		vec3 neynorm = texelFetch(normalMap, itc+ivec2(sc,sc), i).rgb;
+		neynorm = vec3((neynorm.xy-0.5)*2.0,neynorm.z); // unpack norm
+		ne.y = dot(neynorm, norm);
+	
+		ne = 1.0-ne;
+	
+		ne = step(norm_cutoff, ne);
+
+		e += dot(de,de)+dot(ne,ne);
+	}
+
+	e /= samples;
+	
+	gl_FragColor.a = e;
+}
diff --git a/indra/newview/app_settings/shaders/class2/deferred/edgeV.glsl b/indra/newview/app_settings/shaders/class2/deferred/edgeV.glsl
index b3413c301fc442633173347773d2f1c761d489ad..393084a3db72d9535d533e2bbe5090cbad351aa4 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/edgeV.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/edgeV.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 varying vec2 vary_fragcoord;
 uniform vec2 screen_res;
diff --git a/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl
index d6cd984ebe1bfa037c4a20740c21a4087fc87cf9..f54186ffca369052f2a30023179f65502ab79baa 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
 
-#version 120
+
 
 #extension GL_ARB_texture_rectangle : enable
 
@@ -91,7 +91,7 @@ vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod)
 
 vec4 getPosition(vec2 pos_screen)
 {
-	float depth = texture2DRect(depthMap, pos_screen.xy).a;
+	float depth = texture2DRect(depthMap, pos_screen.xy).r;
 	vec2 sc = pos_screen.xy*2.0;
 	sc /= screen_res;
 	sc -= vec2(1.0,1.0);
diff --git a/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightMSF.glsl b/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightMSF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..fee32be3e353c660853b648cef66c377c8baee62
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightMSF.glsl
@@ -0,0 +1,244 @@
+/** 
+ * @file multiSpotLightF.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+
+
+
+#extension GL_ARB_texture_rectangle : enable
+#extension GL_ARB_texture_multisample : enable
+
+uniform sampler2DMS diffuseRect;
+uniform sampler2DMS specularRect;
+uniform sampler2DMS depthMap;
+uniform sampler2DMS normalMap;
+uniform sampler2DRect lightMap;
+uniform sampler2D noiseMap;
+uniform sampler2D lightFunc;
+uniform sampler2D projectionMap;
+
+uniform mat4 proj_mat; //screen space to light space
+uniform float proj_near; //near clip for projection
+uniform vec3 proj_p; //plane projection is emitting from (in screen space)
+uniform vec3 proj_n;
+uniform float proj_focus; //distance from plane to begin blurring
+uniform float proj_lod;  //(number of mips in proj map)
+uniform float proj_range; //range between near clip and far clip plane of projection
+uniform float proj_ambient_lod;
+uniform float proj_ambiance;
+uniform float near_clip;
+uniform float far_clip;
+
+uniform vec3 proj_origin; //origin of projection to be used for angular attenuation
+uniform float sun_wash;
+uniform int proj_shadow_idx;
+uniform float shadow_fade;
+
+varying vec4 vary_light;
+
+varying vec4 vary_fragcoord;
+uniform vec2 screen_res;
+
+uniform mat4 inv_proj;
+
+vec4 texture2DLodSpecular(sampler2D projectionMap, vec2 tc, float lod)
+{
+	vec4 ret = texture2DLod(projectionMap, tc, lod);
+	
+	vec2 dist = tc-vec2(0.5);
+	
+	float det = max(1.0-lod/(proj_lod*0.5), 0.0);
+	
+	float d = dot(dist,dist);
+		
+	ret *= min(clamp((0.25-d)/0.25, 0.0, 1.0)+det, 1.0);
+	
+	return ret;
+}
+
+vec4 texture2DLodDiffuse(sampler2D projectionMap, vec2 tc, float lod)
+{
+	vec4 ret = texture2DLod(projectionMap, tc, lod);
+	
+	vec2 dist = vec2(0.5) - abs(tc-vec2(0.5));
+	
+	float det = min(lod/(proj_lod*0.5), 1.0);
+	
+	float d = min(dist.x, dist.y);
+	
+	float edge = 0.25*det;
+		
+	ret *= clamp(d/edge, 0.0, 1.0);
+	
+	return ret;
+}
+
+vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod)
+{
+	vec4 ret = texture2DLod(projectionMap, tc, lod);
+	
+	vec2 dist = tc-vec2(0.5);
+	
+	float d = dot(dist,dist);
+		
+	ret *= min(clamp((0.25-d)/0.25, 0.0, 1.0), 1.0);
+	
+	return ret;
+}
+
+
+vec4 getPosition(ivec2 pos_screen, int sample)
+{
+	float depth = texelFetch(depthMap, pos_screen, sample).r;
+	vec2 sc = vec2(pos_screen.xy)*2.0;
+	sc /= screen_res;
+	sc -= vec2(1.0,1.0);
+	vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+	vec4 pos = inv_proj * ndc;
+	pos /= pos.w;
+	pos.w = 1.0;
+	return pos;
+}
+
+void main() 
+{
+	int wght = 0;
+
+	vec3 fcol = vec3(0,0,0);
+
+	vec2 frag = (vary_fragcoord.xy*0.5+0.5)*screen_res;
+	
+	ivec2 itc = ivec2(frag.xy);
+
+	float shadow = 1.0;
+
+	if (proj_shadow_idx >= 0)
+	{
+		vec4 shd = texture2DRect(lightMap, frag);
+		float sh[2];
+		sh[0] = shd.b;
+		sh[1] = shd.a;
+		shadow = min(sh[proj_shadow_idx]+shadow_fade, 1.0);
+	}
+		
+	for (int i = 0; i < samples; i++)
+	{
+		vec3 pos = getPosition(itc, i).xyz;
+		vec3 lv = vary_light.xyz-pos.xyz;
+		float dist2 = dot(lv,lv);
+		dist2 /= vary_light.w;
+		if (dist2 <= 1.0)
+		{
+			vec3 norm = texelFetch(normalMap, itc, i).xyz;
+			norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm
+	
+			norm = normalize(norm);
+			float l_dist = -dot(lv, proj_n);
+	
+			vec4 proj_tc = (proj_mat * vec4(pos.xyz, 1.0));
+			if (proj_tc.z >= 0.0)
+			{
+				proj_tc.xyz /= proj_tc.w;
+	
+				float fa = gl_Color.a+1.0;
+				float dist_atten = min(1.0-(dist2-1.0*(1.0-fa))/fa, 1.0);
+				if (dist_atten > 0.0)
+				{
+					lv = proj_origin-pos.xyz;
+					lv = normalize(lv);
+					float da = dot(norm, lv);
+		
+					vec3 col = vec3(0,0,0);
+		
+					vec3 diff_tex = texelFetch(diffuseRect, itc, i).rgb;
+		
+					float noise = texture2D(noiseMap, frag.xy/128.0).b;
+					if (proj_tc.z > 0.0 &&
+						proj_tc.x < 1.0 &&
+						proj_tc.y < 1.0 &&
+						proj_tc.x > 0.0 &&
+						proj_tc.y > 0.0)
+					{
+						float lit = 0.0;
+						float amb_da = proj_ambiance;
+		
+						if (da > 0.0)
+						{
+							float diff = clamp((l_dist-proj_focus)/proj_range, 0.0, 1.0);
+							float lod = diff * proj_lod;
+			
+							vec4 plcol = texture2DLodDiffuse(projectionMap, proj_tc.xy, lod);
+		
+							vec3 lcol = gl_Color.rgb * plcol.rgb * plcol.a;
+			
+							lit = da * dist_atten * noise;
+			
+							col = lcol*lit*diff_tex*shadow;
+							amb_da += (da*0.5)*(1.0-shadow)*proj_ambiance;
+						}
+		
+						//float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0);
+						vec4 amb_plcol = texture2DLodAmbient(projectionMap, proj_tc.xy, proj_lod);
+							
+						amb_da += (da*da*0.5+0.5)*proj_ambiance;
+				
+						amb_da *= dist_atten * noise;
+			
+						amb_da = min(amb_da, 1.0-lit);
+			
+						col += amb_da*gl_Color.rgb*diff_tex.rgb*amb_plcol.rgb*amb_plcol.a;
+					}
+	
+	
+					vec4 spec = texelFetch(specularRect, itc, i);
+					if (spec.a > 0.0)
+					{
+						vec3 ref = reflect(normalize(pos), norm);
+		
+						//project from point pos in direction ref to plane proj_p, proj_n
+						vec3 pdelta = proj_p-pos;
+						float ds = dot(ref, proj_n);
+		
+						if (ds < 0.0)
+						{
+							vec3 pfinal = pos + ref * dot(pdelta, proj_n)/ds;
+			
+							vec4 stc = (proj_mat * vec4(pfinal.xyz, 1.0));
+
+							if (stc.z > 0.0)
+							{
+								stc.xy /= stc.w;
+
+								float fatten = clamp(spec.a*spec.a+spec.a*0.5, 0.25, 1.0);
+				
+								stc.xy = (stc.xy - vec2(0.5)) * fatten + vec2(0.5);
+								
+								if (stc.x < 1.0 &&
+									stc.y < 1.0 &&
+									stc.x > 0.0 &&
+									stc.y > 0.0)
+								{
+									vec4 scol = texture2DLodSpecular(projectionMap, stc.xy, proj_lod-spec.a*proj_lod);
+									col += dist_atten*scol.rgb*gl_Color.rgb*scol.a*spec.rgb*shadow;
+								}
+							}
+						}
+					}
+
+					fcol += col;
+					wght++;
+				}
+			}
+		}
+	}
+	
+	if (wght <= 0)
+	{
+		discard;
+	}
+
+	gl_FragColor.rgb = fcol/samples;	
+	gl_FragColor.a = 0.0;
+}
diff --git a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl
index 0160e84278fc665f06adde57cda481a1b9d39f52..66a1a8515f257bf4fc7fa610edb12afe455d20cb 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 #extension GL_ARB_texture_rectangle : enable
 
@@ -71,7 +71,7 @@ vec4 getPosition_d(vec2 pos_screen, float depth)
 
 vec4 getPosition(vec2 pos_screen)
 { //get position in screen space (world units) given window coordinate and depth map
-	float depth = texture2DRect(depthMap, pos_screen.xy).a;
+	float depth = texture2DRect(depthMap, pos_screen.xy).r;
 	return getPosition_d(pos_screen, depth);
 }
 
@@ -258,7 +258,7 @@ vec3 scaleSoftClip(vec3 light)
 void main() 
 {
 	vec2 tc = vary_fragcoord.xy;
-	float depth = texture2DRect(depthMap, tc.xy).a;
+	float depth = texture2DRect(depthMap, tc.xy).r;
 	vec3 pos = getPosition_d(tc, depth).xyz;
 	vec3 norm = texture2DRect(normalMap, tc).xyz;
 	norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm
@@ -288,54 +288,8 @@ void main()
 		float sa = dot(refnormpersp, vary_light.xyz);
 		vec3 dumbshiny = vary_SunlitColor*scol_ambocc.r*texture2D(lightFunc, vec2(sa, spec.a)).a;
 
-		/*
-		// screen-space cheap fakey reflection map
-		//
-		vec3 refnorm = normalize(reflect(vec3(0,0,-1), norm.xyz));
-		depth -= 0.5; // unbias depth
-		// first figure out where we'll make our 2D guess from
-		vec2 ref2d = (0.25 * screen_res.y) * (refnorm.xy) * abs(refnorm.z) / depth;
-		// Offset the guess source a little according to a trivial
-		// checkerboard dither function and spec.a.
-		// This is meant to be similar to sampling a blurred version
-		// of the diffuse map.  LOD would be better in that regard.
-		// The goal of the blur is to soften reflections in surfaces
-		// with low shinyness, and also to disguise our lameness.
-		float checkerboard = floor(mod(tc.x+tc.y, 2.0)); // 0.0, 1.0
-		float checkoffset = (3.0 + (7.0*(1.0-spec.a)))*(checkerboard-0.5);
-		ref2d += vec2(checkoffset, checkoffset);
-		ref2d += tc.xy; // use as offset from destination
-		// Get attributes from the 2D guess point.
-		// We average two samples of diffuse (not of anything else) per
-		// pixel to try to reduce aliasing some more.
-		vec3 refcol = 0.5 * (texture2DRect(diffuseRect, ref2d + vec2(0.0, -checkoffset)).rgb +
-				     texture2DRect(diffuseRect, ref2d + vec2(-checkoffset, 0.0)).rgb);
-		float refdepth = texture2DRect(depthMap, ref2d).a;
-		vec3 refpos = getPosition_d(ref2d, refdepth).xyz;
-		float refshad = texture2DRect(lightMap, ref2d).r;
-		vec3 refn = texture2DRect(normalMap, ref2d).rgb;
-		refn = vec3((refn.xy-0.5)*2.0,refn.z); // unpack norm
-		refn = normalize(refn);
-		// figure out how appropriate our guess actually was
-		float refapprop = max(0.0, dot(-refnorm, normalize(pos - refpos)));
-		// darken reflections from points which face away from the reflected ray - our guess was a back-face
-		//refapprop *= step(dot(refnorm, refn), 0.0);
-		refapprop = min(refapprop, max(0.0, -dot(refnorm, refn))); // more conservative variant
-		// get appropriate light strength for guess-point
-		// reflect light direction to increase the illusion that
-		// these are reflections.
-		vec3 reflight = reflect(lightnorm.xyz, norm.xyz);
-		float reflit = min(max(dot(refn, reflight.xyz), 0.0), refshad);
-		// apply sun color to guess-point, dampen according to inappropriateness of guess
-		float refmod = min(refapprop, reflit);
-		vec3 refprod = vary_SunlitColor * refcol.rgb * refmod;
-		vec3 ssshiny = (refprod * spec.a);
-		ssshiny *= 0.3; // dampen it even more
-		*/
-		vec3 ssshiny = vec3(0,0,0);
-
 		// add the two types of shiny together
-		col += (ssshiny + dumbshiny) * spec.rgb;
+		col += dumbshiny * spec.rgb;
 	}
 	
 	col = atmosLighting(col);
diff --git a/indra/newview/app_settings/shaders/class2/deferred/softenLightMSF.glsl b/indra/newview/app_settings/shaders/class2/deferred/softenLightMSF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..0bae10ca7d218a844f7fd4562548a6cb9881fb0d
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/deferred/softenLightMSF.glsl
@@ -0,0 +1,307 @@
+/** 
+ * @file softenLightMSF.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+ 
+
+
+#extension GL_ARB_texture_rectangle : enable
+#extension GL_ARB_texture_multisample : enable
+
+uniform sampler2DMS diffuseRect;
+uniform sampler2DMS specularRect;
+uniform sampler2DMS normalMap;
+uniform sampler2DRect lightMap;
+uniform sampler2DMS depthMap;
+uniform sampler2D	  noiseMap;
+uniform samplerCube environmentMap;
+uniform sampler2D	  lightFunc;
+uniform vec3 gi_quad;
+
+uniform float blur_size;
+uniform float blur_fidelity;
+
+// Inputs
+uniform vec4 morphFactor;
+uniform vec3 camPosLocal;
+//uniform vec4 camPosWorld;
+uniform vec4 gamma;
+uniform vec4 lightnorm;
+uniform vec4 sunlight_color;
+uniform vec4 ambient;
+uniform vec4 blue_horizon;
+uniform vec4 blue_density;
+uniform vec4 haze_horizon;
+uniform vec4 haze_density;
+uniform vec4 cloud_shadow;
+uniform vec4 density_multiplier;
+uniform vec4 distance_multiplier;
+uniform vec4 max_y;
+uniform vec4 glow;
+uniform float scene_light_strength;
+uniform vec3 env_mat[3];
+uniform vec4 shadow_clip;
+uniform mat3 ssao_effect_mat;
+
+uniform mat4 inv_proj;
+uniform vec2 screen_res;
+
+varying vec4 vary_light;
+varying vec2 vary_fragcoord;
+
+vec3 vary_PositionEye;
+
+vec3 vary_SunlitColor;
+vec3 vary_AmblitColor;
+vec3 vary_AdditiveColor;
+vec3 vary_AtmosAttenuation;
+
+vec4 getPosition_d(vec2 pos_screen, float depth)
+{
+	vec2 sc = pos_screen.xy*2.0;
+	sc /= screen_res;
+	sc -= vec2(1.0,1.0);
+	vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+	vec4 pos = inv_proj * ndc;
+	pos /= pos.w;
+	pos.w = 1.0;
+	return pos;
+}
+
+vec3 getPositionEye()
+{
+	return vary_PositionEye;
+}
+vec3 getSunlitColor()
+{
+	return vary_SunlitColor;
+}
+vec3 getAmblitColor()
+{
+	return vary_AmblitColor;
+}
+vec3 getAdditiveColor()
+{
+	return vary_AdditiveColor;
+}
+vec3 getAtmosAttenuation()
+{
+	return vary_AtmosAttenuation;
+}
+
+
+void setPositionEye(vec3 v)
+{
+	vary_PositionEye = v;
+}
+
+void setSunlitColor(vec3 v)
+{
+	vary_SunlitColor = v;
+}
+
+void setAmblitColor(vec3 v)
+{
+	vary_AmblitColor = v;
+}
+
+void setAdditiveColor(vec3 v)
+{
+	vary_AdditiveColor = v;
+}
+
+void setAtmosAttenuation(vec3 v)
+{
+	vary_AtmosAttenuation = v;
+}
+
+void calcAtmospherics(vec3 inPositionEye, float ambFactor) {
+
+	vec3 P = inPositionEye;
+	setPositionEye(P);
+	
+	//(TERRAIN) limit altitude
+	if (P.y > max_y.x) P *= (max_y.x / P.y);
+	if (P.y < -max_y.x) P *= (-max_y.x / P.y);
+
+	vec3 tmpLightnorm = lightnorm.xyz;
+
+	vec3 Pn = normalize(P);
+	float Plen = length(P);
+
+	vec4 temp1 = vec4(0);
+	vec3 temp2 = vec3(0);
+	vec4 blue_weight;
+	vec4 haze_weight;
+	vec4 sunlight = sunlight_color;
+	vec4 light_atten;
+
+	//sunlight attenuation effect (hue and brightness) due to atmosphere
+	//this is used later for sunlight modulation at various altitudes
+	light_atten = (blue_density * 1.0 + vec4(haze_density.r) * 0.25) * (density_multiplier.x * max_y.x);
+		//I had thought blue_density and haze_density should have equal weighting,
+		//but attenuation due to haze_density tends to seem too strong
+
+	temp1 = blue_density + vec4(haze_density.r);
+	blue_weight = blue_density / temp1;
+	haze_weight = vec4(haze_density.r) / temp1;
+
+	//(TERRAIN) compute sunlight from lightnorm only (for short rays like terrain)
+	temp2.y = max(0.0, tmpLightnorm.y);
+	temp2.y = 1. / temp2.y;
+	sunlight *= exp( - light_atten * temp2.y);
+
+	// main atmospheric scattering line integral
+	temp2.z = Plen * density_multiplier.x;
+
+	// Transparency (-> temp1)
+	// ATI Bugfix -- can't store temp1*temp2.z*distance_multiplier.x in a variable because the ati
+	// compiler gets confused.
+	temp1 = exp(-temp1 * temp2.z * distance_multiplier.x);
+
+	//final atmosphere attenuation factor
+	setAtmosAttenuation(temp1.rgb);
+	
+	//compute haze glow
+	//(can use temp2.x as temp because we haven't used it yet)
+	temp2.x = dot(Pn, tmpLightnorm.xyz);
+	temp2.x = 1. - temp2.x;
+		//temp2.x is 0 at the sun and increases away from sun
+	temp2.x = max(temp2.x, .03);	//was glow.y
+		//set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot)
+	temp2.x *= glow.x;
+		//higher glow.x gives dimmer glow (because next step is 1 / "angle")
+	temp2.x = pow(temp2.x, glow.z);
+		//glow.z should be negative, so we're doing a sort of (1 / "angle") function
+
+	//add "minimum anti-solar illumination"
+	temp2.x += .25;
+	
+	//increase ambient when there are more clouds
+	vec4 tmpAmbient = ambient + (vec4(1.) - ambient) * cloud_shadow.x * 0.5;
+	
+	/*  decrease value and saturation (that in HSV, not HSL) for occluded areas
+	 * // for HSV color/geometry used here, see http://gimp-savvy.com/BOOK/index.html?node52.html
+	 * // The following line of code performs the equivalent of:
+	 * float ambAlpha = tmpAmbient.a;
+	 * float ambValue = dot(vec3(tmpAmbient), vec3(0.577)); // projection onto <1/rt(3), 1/rt(3), 1/rt(3)>, the neutral white-black axis
+	 * vec3 ambHueSat = vec3(tmpAmbient) - vec3(ambValue);
+	 * tmpAmbient = vec4(RenderSSAOEffect.valueFactor * vec3(ambValue) + RenderSSAOEffect.saturationFactor *(1.0 - ambFactor) * ambHueSat, ambAlpha);
+	 */
+	tmpAmbient = vec4(mix(ssao_effect_mat * tmpAmbient.rgb, tmpAmbient.rgb, ambFactor), tmpAmbient.a);
+
+	//haze color
+	setAdditiveColor(
+		vec3(blue_horizon * blue_weight * (sunlight*(1.-cloud_shadow.x) + tmpAmbient)
+	  + (haze_horizon.r * haze_weight) * (sunlight*(1.-cloud_shadow.x) * temp2.x
+		  + tmpAmbient)));
+
+	//brightness of surface both sunlight and ambient
+	setSunlitColor(vec3(sunlight * .5));
+	setAmblitColor(vec3(tmpAmbient * .25));
+	setAdditiveColor(getAdditiveColor() * vec3(1.0 - temp1));
+}
+
+vec3 atmosLighting(vec3 light)
+{
+	light *= getAtmosAttenuation().r;
+	light += getAdditiveColor();
+	return (2.0 * light);
+}
+
+vec3 atmosTransport(vec3 light) {
+	light *= getAtmosAttenuation().r;
+	light += getAdditiveColor() * 2.0;
+	return light;
+}
+vec3 atmosGetDiffuseSunlightColor()
+{
+	return getSunlitColor();
+}
+
+vec3 scaleDownLight(vec3 light)
+{
+	return (light / scene_light_strength );
+}
+
+vec3 scaleUpLight(vec3 light)
+{
+	return (light * scene_light_strength);
+}
+
+vec3 atmosAmbient(vec3 light)
+{
+	return getAmblitColor() + light / 2.0;
+}
+
+vec3 atmosAffectDirectionalLight(float lightIntensity)
+{
+	return getSunlitColor() * lightIntensity;
+}
+
+vec3 scaleSoftClip(vec3 light)
+{
+	//soft clip effect:
+	light = 1. - clamp(light, vec3(0.), vec3(1.));
+	light = 1. - pow(light, gamma.xxx);
+
+	return light;
+}
+
+void main() 
+{
+	vec2 tc = vary_fragcoord.xy;
+	ivec2 itc = ivec2(tc);
+
+	vec3 fcol = vec3(0,0,0);
+
+	vec2 scol_ambocc = texture2DRect(lightMap, tc).rg;
+	float ambocc = scol_ambocc.g;
+
+	for (int i = 0; i < samples; ++i)
+	{
+		float depth = texelFetch(depthMap, itc.xy, i).r;
+		vec3 pos = getPosition_d(tc, depth).xyz;
+		vec3 norm = texelFetch(normalMap, itc, i).xyz;
+		norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm
+			
+		float da = max(dot(norm.xyz, vary_light.xyz), 0.0);
+	
+		vec4 diffuse = texelFetch(diffuseRect, itc, i);
+		vec4 spec = texelFetch(specularRect, itc, i);
+	
+		float amb = 0;
+
+		float scol = max(scol_ambocc.r, diffuse.a); 
+		amb += ambocc;
+
+		calcAtmospherics(pos.xyz, ambocc);
+	
+		vec3 col = atmosAmbient(vec3(0));
+		col += atmosAffectDirectionalLight(max(min(da, scol), diffuse.a));
+	
+		col *= diffuse.rgb;
+	
+		if (spec.a > 0.0) // specular reflection
+		{
+			// the old infinite-sky shiny reflection
+			//
+			vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz));
+			float sa = dot(refnormpersp, vary_light.xyz);
+			vec3 dumbshiny = vary_SunlitColor*scol_ambocc.r*texture2D(lightFunc, vec2(sa, spec.a)).a;
+
+			// add the two types of shiny together
+			col += dumbshiny * spec.rgb;
+		}
+	
+		col = atmosLighting(col);
+		col = scaleSoftClip(col);
+
+		fcol += col;
+	}
+		
+	gl_FragColor.rgb = fcol/samples; 
+	gl_FragColor.a = 0.0;
+}
diff --git a/indra/newview/app_settings/shaders/class2/deferred/softenLightV.glsl b/indra/newview/app_settings/shaders/class2/deferred/softenLightV.glsl
index 8f0bcca76b86a22f32101d0c81b3631110fff0c9..745cc0199236aeff1ade125a59f78bd48b15d382 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/softenLightV.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/softenLightV.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 uniform vec2 screen_res;
 
diff --git a/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl
index 50b9ef276e6ab7bb98a51eb5a00dff4ce9afa0d7..cd3828fbd4084d0fd980e65ce8dae2ecca4f9c1b 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 #extension GL_ARB_texture_rectangle : enable
 
diff --git a/indra/newview/app_settings/shaders/class2/deferred/spotLightMSF.glsl b/indra/newview/app_settings/shaders/class2/deferred/spotLightMSF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..ec9b547a47210ff1d032e9859bc9004de583a55f
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/deferred/spotLightMSF.glsl
@@ -0,0 +1,245 @@
+/** 
+ * @file multiSpotLightF.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+
+
+
+#extension GL_ARB_texture_rectangle : enable
+#extension GL_ARB_texture_multisample : enable
+
+uniform sampler2DMS diffuseRect;
+uniform sampler2DMS specularRect;
+uniform sampler2DMS depthMap;
+uniform sampler2DMS normalMap;
+uniform sampler2DRect lightMap;
+uniform sampler2D noiseMap;
+uniform sampler2D lightFunc;
+uniform sampler2D projectionMap;
+
+uniform mat4 proj_mat; //screen space to light space
+uniform float proj_near; //near clip for projection
+uniform vec3 proj_p; //plane projection is emitting from (in screen space)
+uniform vec3 proj_n;
+uniform float proj_focus; //distance from plane to begin blurring
+uniform float proj_lod;  //(number of mips in proj map)
+uniform float proj_range; //range between near clip and far clip plane of projection
+uniform float proj_ambient_lod;
+uniform float proj_ambiance;
+uniform float near_clip;
+uniform float far_clip;
+
+uniform vec3 proj_origin; //origin of projection to be used for angular attenuation
+uniform float sun_wash;
+uniform int proj_shadow_idx;
+uniform float shadow_fade;
+
+varying vec4 vary_light;
+
+varying vec4 vary_fragcoord;
+uniform vec2 screen_res;
+
+uniform mat4 inv_proj;
+
+vec4 texture2DLodSpecular(sampler2D projectionMap, vec2 tc, float lod)
+{
+	vec4 ret = texture2DLod(projectionMap, tc, lod);
+	
+	vec2 dist = tc-vec2(0.5);
+	
+	float det = max(1.0-lod/(proj_lod*0.5), 0.0);
+	
+	float d = dot(dist,dist);
+		
+	ret *= min(clamp((0.25-d)/0.25, 0.0, 1.0)+det, 1.0);
+	
+	return ret;
+}
+
+vec4 texture2DLodDiffuse(sampler2D projectionMap, vec2 tc, float lod)
+{
+	vec4 ret = texture2DLod(projectionMap, tc, lod);
+	
+	vec2 dist = vec2(0.5) - abs(tc-vec2(0.5));
+	
+	float det = min(lod/(proj_lod*0.5), 1.0);
+	
+	float d = min(dist.x, dist.y);
+	
+	float edge = 0.25*det;
+		
+	ret *= clamp(d/edge, 0.0, 1.0);
+	
+	return ret;
+}
+
+vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod)
+{
+	vec4 ret = texture2DLod(projectionMap, tc, lod);
+	
+	vec2 dist = tc-vec2(0.5);
+	
+	float d = dot(dist,dist);
+		
+	ret *= min(clamp((0.25-d)/0.25, 0.0, 1.0), 1.0);
+	
+	return ret;
+}
+
+
+vec4 getPosition(ivec2 pos_screen, int sample)
+{
+	float depth = texelFetch(depthMap, pos_screen, sample).r;
+	vec2 sc = vec2(pos_screen.xy)*2.0;
+	sc /= screen_res;
+	sc -= vec2(1.0,1.0);
+	vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+	vec4 pos = inv_proj * ndc;
+	pos /= pos.w;
+	pos.w = 1.0;
+	return pos;
+}
+
+void main() 
+{
+	vec4 frag = vary_fragcoord;
+	frag.xyz /= frag.w;
+	frag.xyz = frag.xyz*0.5+0.5;
+	frag.xy *= screen_res;
+	ivec2 itc = ivec2(frag.xy);
+	
+	vec3 fcol = vec3(0,0,0);
+	int wght = 0;
+
+	float shadow = 1.0;
+	
+	if (proj_shadow_idx >= 0)
+	{
+		vec4 shd = texture2DRect(lightMap, frag.xy);
+		float sh[2];
+		sh[0] = shd.b;
+		sh[1] = shd.a;
+		shadow = min(sh[proj_shadow_idx]+shadow_fade, 1.0);
+	}
+	
+	for (int i = 0; i < samples; i++)
+	{
+		vec3 pos = getPosition(itc, i).xyz;
+		vec3 lv = vary_light.xyz-pos.xyz;
+		float dist2 = dot(lv,lv);
+		dist2 /= vary_light.w;
+		if (dist2 <= 1.0)
+		{
+			vec3 norm = texelFetch(normalMap, itc, i).xyz;
+			norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm
+	
+			norm = normalize(norm);
+			float l_dist = -dot(lv, proj_n);
+	
+			vec4 proj_tc = (proj_mat * vec4(pos.xyz, 1.0));
+			if (proj_tc.z >= 0.0)
+			{
+				proj_tc.xyz /= proj_tc.w;
+	
+				float fa = gl_Color.a+1.0;
+				float dist_atten = min(1.0-(dist2-1.0*(1.0-fa))/fa, 1.0);
+				if (dist_atten > 0.0)
+				{
+					lv = proj_origin-pos.xyz;
+					lv = normalize(lv);
+					float da = dot(norm, lv);
+		
+					vec3 col = vec3(0,0,0);
+		
+					vec3 diff_tex = texelFetch(diffuseRect, itc, i).rgb;
+		
+					float noise = texture2D(noiseMap, frag.xy/128.0).b;
+					if (proj_tc.z > 0.0 &&
+						proj_tc.x < 1.0 &&
+						proj_tc.y < 1.0 &&
+						proj_tc.x > 0.0 &&
+						proj_tc.y > 0.0)
+					{
+						float lit = 0.0;
+						float amb_da = proj_ambiance;
+		
+						if (da > 0.0)
+						{
+							float diff = clamp((l_dist-proj_focus)/proj_range, 0.0, 1.0);
+							float lod = diff * proj_lod;
+			
+							vec4 plcol = texture2DLodDiffuse(projectionMap, proj_tc.xy, lod);
+		
+							vec3 lcol = gl_Color.rgb * plcol.rgb * plcol.a;
+			
+							lit = da * dist_atten * noise;
+			
+							col = lcol*lit*diff_tex*shadow;
+							amb_da += (da*0.5)*(1.0-shadow)*proj_ambiance;
+						}
+		
+						//float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0);
+						vec4 amb_plcol = texture2DLodAmbient(projectionMap, proj_tc.xy, proj_lod);
+							
+						amb_da += (da*da*0.5+0.5)*proj_ambiance;
+				
+						amb_da *= dist_atten * noise;
+			
+						amb_da = min(amb_da, 1.0-lit);
+			
+						col += amb_da*gl_Color.rgb*diff_tex.rgb*amb_plcol.rgb*amb_plcol.a;
+					}
+	
+	
+					vec4 spec = texelFetch(specularRect, itc, i);
+					if (spec.a > 0.0)
+					{
+						vec3 ref = reflect(normalize(pos), norm);
+		
+						//project from point pos in direction ref to plane proj_p, proj_n
+						vec3 pdelta = proj_p-pos;
+						float ds = dot(ref, proj_n);
+		
+						if (ds < 0.0)
+						{
+							vec3 pfinal = pos + ref * dot(pdelta, proj_n)/ds;
+			
+							vec4 stc = (proj_mat * vec4(pfinal.xyz, 1.0));
+
+							if (stc.z > 0.0)
+							{
+								stc.xy /= stc.w;
+
+								float fatten = clamp(spec.a*spec.a+spec.a*0.5, 0.25, 1.0);
+				
+								stc.xy = (stc.xy - vec2(0.5)) * fatten + vec2(0.5);
+								
+								if (stc.x < 1.0 &&
+									stc.y < 1.0 &&
+									stc.x > 0.0 &&
+									stc.y > 0.0)
+								{
+									vec4 scol = texture2DLodSpecular(projectionMap, stc.xy, proj_lod-spec.a*proj_lod);
+									col += dist_atten*scol.rgb*gl_Color.rgb*scol.a*spec.rgb*shadow;
+								}
+							}
+						}
+					}
+
+					fcol += col;
+					wght++;
+				}
+			}
+		}
+	}
+	
+	if (wght <= 0)
+	{
+		discard;
+	}
+
+	gl_FragColor.rgb = fcol/wght;	
+	gl_FragColor.a = 0.0;
+}
diff --git a/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl
index 4369b3b34ff8da6af4aabcf4b57e58b02024dd2b..315139b4151e3b5bb260af68e1fac61060b11029 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 #extension GL_ARB_texture_rectangle : enable
 
@@ -45,7 +45,7 @@ uniform float spot_shadow_offset;
 
 vec4 getPosition(vec2 pos_screen)
 {
-	float depth = texture2DRect(depthMap, pos_screen.xy).a;
+	float depth = texture2DRect(depthMap, pos_screen.xy).r;
 	vec2 sc = pos_screen.xy*2.0;
 	sc /= screen_res;
 	sc -= vec2(1.0,1.0);
diff --git a/indra/newview/app_settings/shaders/class2/deferred/sunLightMSF.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightMSF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..63d13c996d4107ffebededace3462370cf5d4fff
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/deferred/sunLightMSF.glsl
@@ -0,0 +1,202 @@
+/** 
+ * @file sunLightMSF.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+ 
+
+
+#extension GL_ARB_texture_rectangle : enable
+#extension GL_ARB_texture_multisample : enable
+
+//class 2, shadows, no SSAO
+
+uniform sampler2DMS depthMap;
+uniform sampler2DMS normalMap;
+uniform sampler2DRectShadow shadowMap0;
+uniform sampler2DRectShadow shadowMap1;
+uniform sampler2DRectShadow shadowMap2;
+uniform sampler2DRectShadow shadowMap3;
+uniform sampler2DShadow shadowMap4;
+uniform sampler2DShadow shadowMap5;
+
+
+// Inputs
+uniform mat4 shadow_matrix[6];
+uniform vec4 shadow_clip;
+uniform float ssao_radius;
+uniform float ssao_max_radius;
+uniform float ssao_factor;
+uniform float ssao_factor_inv;
+
+varying vec2 vary_fragcoord;
+varying vec4 vary_light;
+
+uniform mat4 inv_proj;
+uniform vec2 screen_res;
+uniform vec2 shadow_res;
+uniform vec2 proj_shadow_res;
+
+uniform float shadow_bias;
+uniform float shadow_offset;
+
+uniform float spot_shadow_bias;
+uniform float spot_shadow_offset;
+
+vec4 getPosition(ivec2 pos_screen, int sample)
+{
+	float depth = texelFetch(depthMap, pos_screen.xy, sample).r;
+	vec2 sc = vec2(pos_screen.xy)*2.0;
+	sc /= screen_res;
+	sc -= vec2(1.0,1.0);
+	vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+	vec4 pos = inv_proj * ndc;
+	pos /= pos.w;
+	pos.w = 1.0;
+	return pos;
+}
+
+float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc, float scl)
+{
+	stc.xyz /= stc.w;
+	stc.z += shadow_bias*scl;
+	
+	float cs = shadow2DRect(shadowMap, stc.xyz).x;
+	float shadow = cs;
+
+	shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(1.5, 1.5, 0.0)).x, cs);
+	shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(1.5, -1.5, 0.0)).x, cs);
+	shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-1.5, 1.5, 0.0)).x, cs);
+	shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-1.5, -1.5, 0.0)).x, cs);
+			
+	return shadow/5.0;
+	
+	//return shadow;
+}
+
+float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl)
+{
+	stc.xyz /= stc.w;
+	stc.z += spot_shadow_bias*scl;
+	
+	float cs = shadow2D(shadowMap, stc.xyz).x;
+	float shadow = cs;
+
+	vec2 off = 1.5/proj_shadow_res;
+	
+	shadow += max(shadow2D(shadowMap, stc.xyz+vec3(off.x, off.y, 0.0)).x, cs);
+	shadow += max(shadow2D(shadowMap, stc.xyz+vec3(off.x, -off.y, 0.0)).x, cs);
+	shadow += max(shadow2D(shadowMap, stc.xyz+vec3(-off.x, off.y, 0.0)).x, cs);
+	shadow += max(shadow2D(shadowMap, stc.xyz+vec3(-off.x, -off.y, 0.0)).x, cs);
+				
+	return shadow/5.0;
+	
+	//return shadow;
+}
+
+void main() 
+{
+	vec2 pos_screen = vary_fragcoord.xy;
+	ivec2 itc = ivec2(pos_screen);
+
+	//try doing an unproject here
+	
+	vec4 fcol = vec4(0,0,0,0);
+
+	for (int i = 0; i < samples; i++)
+	{
+		vec4 pos = getPosition(itc, i);
+	
+		vec4 nmap4 = texelFetch(normalMap, itc, i);
+		nmap4 = vec4((nmap4.xy-0.5)*2.0,nmap4.z,nmap4.w); // unpack norm
+		float displace = nmap4.w;
+		vec3 norm = nmap4.xyz;
+	
+		/*if (pos.z == 0.0) // do nothing for sky *FIX: REMOVE THIS IF/WHEN THE POSITION MAP IS BEING USED AS A STENCIL
+		{
+			gl_FragColor = vec4(0.0); // doesn't matter
+			return;
+		}*/
+	
+		float shadow = 1.0;
+		float dp_directional_light = max(0.0, dot(norm, vary_light.xyz));
+
+		vec3 shadow_pos = pos.xyz + displace*norm;
+		vec3 offset = vary_light.xyz * (1.0-dp_directional_light);
+	
+		vec4 spos = vec4(shadow_pos+offset*shadow_offset, 1.0);
+	
+		if (spos.z > -shadow_clip.w)
+		{	
+			if (dp_directional_light == 0.0)
+			{
+				// if we know this point is facing away from the sun then we know it's in shadow without having to do a squirrelly shadow-map lookup
+				shadow = 0.0;
+			}
+			else
+			{
+				vec4 lpos;
+			
+				if (spos.z < -shadow_clip.z)
+				{
+					lpos = shadow_matrix[3]*spos;
+					lpos.xy *= shadow_res;
+					shadow = pcfShadow(shadowMap3, lpos, 0.25);
+					shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0);
+				}
+				else if (spos.z < -shadow_clip.y)
+				{
+					lpos = shadow_matrix[2]*spos;
+					lpos.xy *= shadow_res;
+					shadow = pcfShadow(shadowMap2, lpos, 0.5);
+				}
+				else if (spos.z < -shadow_clip.x)
+				{
+					lpos = shadow_matrix[1]*spos;
+					lpos.xy *= shadow_res;
+					shadow = pcfShadow(shadowMap1, lpos, 0.75);
+				}
+				else
+				{
+					lpos = shadow_matrix[0]*spos;
+					lpos.xy *= shadow_res;
+					shadow = pcfShadow(shadowMap0, lpos, 1.0);
+				}
+		
+				// take the most-shadowed value out of these two:
+				//  * the blurred sun shadow in the light (shadow) map
+				//  * an unblurred dot product between the sun and this norm
+				// the goal is to err on the side of most-shadow to fill-in shadow holes and reduce artifacting
+				shadow = min(shadow, dp_directional_light);
+			
+				//lpos.xy /= lpos.w*32.0;
+				//if (fract(lpos.x) < 0.1 || fract(lpos.y) < 0.1)
+				//{
+				//	shadow = 0.0;
+				//}
+			
+			}
+		}
+		else
+		{
+			// more distant than the shadow map covers
+			shadow = 1.0;
+		}
+	
+		fcol[0] += shadow;
+		fcol[1] += 1.0;
+
+		spos = vec4(shadow_pos+norm*spot_shadow_offset, 1.0);
+	
+		//spotlight shadow 1
+		vec4 lpos = shadow_matrix[4]*spos;
+		fcol[2] += pcfShadow(shadowMap4, lpos, 0.8); 
+	
+		//spotlight shadow 2
+		lpos = shadow_matrix[5]*spos;
+		fcol[3] += pcfShadow(shadowMap5, lpos, 0.8); 
+	}
+
+	gl_FragColor = fcol/samples;
+}
diff --git a/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl
index 847b36b1ace5722cf0a4cdec723bc75b2549c177..d53850b489ca0c18763f0a7b839e46964085f1dd 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl
@@ -5,7 +5,7 @@
  * $License$
  */
  
-#version 120
+
 
 #extension GL_ARB_texture_rectangle : enable
 
@@ -45,7 +45,7 @@ uniform float spot_shadow_offset;
 
 vec4 getPosition(vec2 pos_screen)
 {
-	float depth = texture2DRect(depthMap, pos_screen.xy).a;
+	float depth = texture2DRect(depthMap, pos_screen.xy).r;
 	vec2 sc = pos_screen.xy*2.0;
 	sc /= screen_res;
 	sc -= vec2(1.0,1.0);
@@ -234,7 +234,7 @@ void main()
 	gl_FragColor[0] = shadow;
 	gl_FragColor[1] = calcAmbientOcclusion(pos, norm);
 	
-	spos.xyz = shadow_pos+offset*spot_shadow_offset;
+	spos.xyz = shadow_pos+norm*spot_shadow_offset;
 	
 	//spotlight shadow 1
 	vec4 lpos = shadow_matrix[4]*spos;
diff --git a/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOMSF.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOMSF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..a2a76eed9fdd22ee8fa79178fd21ec8e7969fd49
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOMSF.glsl
@@ -0,0 +1,241 @@
+/** 
+ * @file sunLightSSAOF.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+ 
+
+
+#extension GL_ARB_texture_rectangle : enable
+#extension GL_ARB_texture_multisample : enable
+
+//class 2 -- shadows and SSAO
+
+uniform sampler2DMS depthMap;
+uniform sampler2DMS normalMap;
+uniform sampler2DRectShadow shadowMap0;
+uniform sampler2DRectShadow shadowMap1;
+uniform sampler2DRectShadow shadowMap2;
+uniform sampler2DRectShadow shadowMap3;
+uniform sampler2DShadow shadowMap4;
+uniform sampler2DShadow shadowMap5;
+uniform sampler2D noiseMap;
+
+// Inputs
+uniform mat4 shadow_matrix[6];
+uniform vec4 shadow_clip;
+uniform float ssao_radius;
+uniform float ssao_max_radius;
+uniform float ssao_factor;
+uniform float ssao_factor_inv;
+
+varying vec2 vary_fragcoord;
+varying vec4 vary_light;
+
+uniform mat4 inv_proj;
+uniform vec2 screen_res;
+uniform vec2 shadow_res;
+uniform vec2 proj_shadow_res;
+
+uniform float shadow_bias;
+uniform float shadow_offset;
+
+uniform float spot_shadow_bias;
+uniform float spot_shadow_offset;
+
+vec4 getPosition(ivec2 pos_screen, int sample)
+{
+	float depth = texelFetch(depthMap, pos_screen, sample).r;
+	vec2 sc = vec2(pos_screen.xy)*2.0;
+	sc /= screen_res;
+	sc -= vec2(1.0,1.0);
+	vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+	vec4 pos = inv_proj * ndc;
+	pos /= pos.w;
+	pos.w = 1.0;
+	return pos;
+}
+
+//calculate decreases in ambient lighting when crowded out (SSAO)
+float calcAmbientOcclusion(vec4 pos, vec3 norm, int sample)
+{
+	float ret = 1.0;
+
+	vec2 kern[8];
+	// exponentially (^2) distant occlusion samples spread around origin
+	kern[0] = vec2(-1.0, 0.0) * 0.125*0.125;
+	kern[1] = vec2(1.0, 0.0) * 0.250*0.250;
+	kern[2] = vec2(0.0, 1.0) * 0.375*0.375;
+	kern[3] = vec2(0.0, -1.0) * 0.500*0.500;
+	kern[4] = vec2(0.7071, 0.7071) * 0.625*0.625;
+	kern[5] = vec2(-0.7071, -0.7071) * 0.750*0.750;
+	kern[6] = vec2(-0.7071, 0.7071) * 0.875*0.875;
+	kern[7] = vec2(0.7071, -0.7071) * 1.000*1.000;
+
+	vec2 pos_screen = vary_fragcoord.xy;
+	vec3 pos_world = pos.xyz;
+	vec2 noise_reflect = texture2D(noiseMap, vary_fragcoord.xy/128.0).xy;
+		
+	float angle_hidden = 0.0;
+	int points = 0;
+		
+	float scale = min(ssao_radius / -pos_world.z, ssao_max_radius);
+		
+	// it was found that keeping # of samples a constant was the fastest, probably due to compiler optimizations (unrolling?)
+	for (int i = 0; i < 8; i++)
+	{
+		ivec2 samppos_screen = ivec2(pos_screen + scale * reflect(kern[i], noise_reflect));
+		vec3 samppos_world = getPosition(samppos_screen, sample).xyz; 
+			
+		vec3 diff = pos_world - samppos_world;
+		float dist2 = dot(diff, diff);
+			
+		// assume each sample corresponds to an occluding sphere with constant radius, constant x-sectional area
+		// --> solid angle shrinking by the square of distance
+		//radius is somewhat arbitrary, can approx with just some constant k * 1 / dist^2
+		//(k should vary inversely with # of samples, but this is taken care of later)
+			
+		angle_hidden = angle_hidden + float(dot((samppos_world - 0.05*norm - pos_world), norm) > 0.0) * min(1.0/dist2, ssao_factor_inv);
+			
+		// 'blocked' samples (significantly closer to camera relative to pos_world) are "no data", not "no occlusion" 
+		points = points + int(diff.z > -1.0);
+	}
+		
+	angle_hidden = min(ssao_factor*angle_hidden/float(points), 1.0);
+		
+	ret = (1.0 - (float(points != 0) * angle_hidden));
+	
+	return min(ret, 1.0);
+}
+
+float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc, float scl)
+{
+	stc.xyz /= stc.w;
+	stc.z += shadow_bias*scl;
+	
+	float cs = shadow2DRect(shadowMap, stc.xyz).x;
+	float shadow = cs;
+
+	shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(1.5, 1.5, 0.0)).x, cs);
+	shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(1.5, -1.5, 0.0)).x, cs);
+	shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-1.5, 1.5, 0.0)).x, cs);
+	shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-1.5, -1.5, 0.0)).x, cs);
+			
+	return shadow/5.0;
+	
+	//return shadow;
+}
+
+float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl)
+{
+	stc.xyz /= stc.w;
+	stc.z += spot_shadow_bias*scl;
+	
+	float cs = shadow2D(shadowMap, stc.xyz).x;
+	float shadow = cs;
+
+	vec2 off = 1.5/proj_shadow_res;
+	
+	shadow += max(shadow2D(shadowMap, stc.xyz+vec3(off.x, off.y, 0.0)).x, cs);
+	shadow += max(shadow2D(shadowMap, stc.xyz+vec3(off.x, -off.y, 0.0)).x, cs);
+	shadow += max(shadow2D(shadowMap, stc.xyz+vec3(-off.x, off.y, 0.0)).x, cs);
+	shadow += max(shadow2D(shadowMap, stc.xyz+vec3(-off.x, -off.y, 0.0)).x, cs);
+	
+			
+	return shadow/5.0;
+	
+	//return shadow;
+}
+
+void main() 
+{
+	vec2 pos_screen = vary_fragcoord.xy;
+	ivec2 itc = ivec2(pos_screen);
+	vec4 fcol = vec4(0,0,0,0);
+
+	for (int i = 0; i < samples; i++)
+	{
+		vec4 pos = getPosition(itc, i);
+	
+		vec4 nmap4 = texelFetch(normalMap, itc, i);
+		nmap4 = vec4((nmap4.xy-0.5)*2.0,nmap4.z,nmap4.w); // unpack norm
+		float displace = nmap4.w;
+		vec3 norm = nmap4.xyz;
+	
+		float shadow = 1.0;
+		float dp_directional_light = max(0.0, dot(norm, vary_light.xyz));
+
+		vec3 shadow_pos = pos.xyz + displace*norm;
+		vec3 offset = vary_light.xyz * (1.0-dp_directional_light);
+	
+		vec4 spos = vec4(shadow_pos+offset*shadow_offset, 1.0);
+	
+		if (spos.z > -shadow_clip.w)
+		{	
+			if (dp_directional_light == 0.0)
+			{
+				// if we know this point is facing away from the sun then we know it's in shadow without having to do a squirrelly shadow-map lookup
+				shadow = 0.0;
+			}
+			else
+			{
+				vec4 lpos;
+			
+				if (spos.z < -shadow_clip.z)
+				{
+					lpos = shadow_matrix[3]*spos;
+					lpos.xy *= shadow_res;
+					shadow = pcfShadow(shadowMap3, lpos, 0.25);
+					shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0);
+				}
+				else if (spos.z < -shadow_clip.y)
+				{
+					lpos = shadow_matrix[2]*spos;
+					lpos.xy *= shadow_res;
+					shadow = pcfShadow(shadowMap2, lpos, 0.5);
+				}
+				else if (spos.z < -shadow_clip.x)
+				{
+					lpos = shadow_matrix[1]*spos;
+					lpos.xy *= shadow_res;
+					shadow = pcfShadow(shadowMap1, lpos, 0.75);
+				}
+				else
+				{
+					lpos = shadow_matrix[0]*spos;
+					lpos.xy *= shadow_res;
+					shadow = pcfShadow(shadowMap0, lpos, 1.0);
+				}
+		
+				// take the most-shadowed value out of these two:
+				//  * the blurred sun shadow in the light (shadow) map
+				//  * an unblurred dot product between the sun and this norm
+				// the goal is to err on the side of most-shadow to fill-in shadow holes and reduce artifacting
+				shadow = min(shadow, dp_directional_light);
+			
+			}
+		}
+		else
+		{
+			// more distant than the shadow map covers
+			shadow = 1.0;
+		}
+	
+		
+		fcol[0] += shadow;
+		fcol[1] += calcAmbientOcclusion(pos, norm, i);
+
+		spos.xyz = shadow_pos+offset*spot_shadow_offset;
+	
+		//spotlight shadow 1
+		vec4 lpos = shadow_matrix[4]*spos;
+		fcol[2] += pcfShadow(shadowMap4, lpos, 0.8); 
+	
+		//spotlight shadow 2
+		lpos = shadow_matrix[5]*spos;
+		fcol[3] += pcfShadow(shadowMap5, lpos, 0.8); 
+	}
+		
+	gl_FragColor = fcol / samples;
+}
diff --git a/indra/newview/app_settings/shaders/class2/deferred/sunLightV.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightV.glsl
index 9beb513ad8a63a129b231381cb010e69c58b9510..814deb3677ab6489c305175878b9b905911996b5 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/sunLightV.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/sunLightV.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 varying vec4 vary_light;
 varying vec2 vary_fragcoord;
diff --git a/indra/newview/app_settings/shaders/class2/effects/blurF.glsl b/indra/newview/app_settings/shaders/class2/effects/blurF.glsl
index a4ad0bfa15f1053bc0b8292cfb9c8eb26644ac0a..dff4d4a68f928986d7134688c019de3750db0185 100644
--- a/indra/newview/app_settings/shaders/class2/effects/blurF.glsl
+++ b/indra/newview/app_settings/shaders/class2/effects/blurF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 uniform sampler2DRect RenderTexture;
 uniform float bloomStrength;
diff --git a/indra/newview/app_settings/shaders/class2/effects/blurV.glsl b/indra/newview/app_settings/shaders/class2/effects/blurV.glsl
index d471a6c5e59582d536ad1d591462f7c683f3ad11..de469542f98cfec18c6332b5ee82fa75ec4c8ef6 100644
--- a/indra/newview/app_settings/shaders/class2/effects/blurV.glsl
+++ b/indra/newview/app_settings/shaders/class2/effects/blurV.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 uniform vec2 texelSize;
 uniform vec2 blurDirection;
diff --git a/indra/newview/app_settings/shaders/class2/effects/colorFilterF.glsl b/indra/newview/app_settings/shaders/class2/effects/colorFilterF.glsl
index 66880b958e0c9b1d9e12f59a06b4225ab0d65e8c..8871bb3fc7da685c41206176ae0259443e124e85 100644
--- a/indra/newview/app_settings/shaders/class2/effects/colorFilterF.glsl
+++ b/indra/newview/app_settings/shaders/class2/effects/colorFilterF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 uniform sampler2DRect RenderTexture;
 uniform float brightness;
diff --git a/indra/newview/app_settings/shaders/class2/effects/drawQuadV.glsl b/indra/newview/app_settings/shaders/class2/effects/drawQuadV.glsl
index c35c500d62374029b3123963f81185bf44253c10..9c52b8dd5d45f6a926379fe8c0f8b5c04e544f0f 100644
--- a/indra/newview/app_settings/shaders/class2/effects/drawQuadV.glsl
+++ b/indra/newview/app_settings/shaders/class2/effects/drawQuadV.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 void main(void)
 {
diff --git a/indra/newview/app_settings/shaders/class2/effects/extractF.glsl b/indra/newview/app_settings/shaders/class2/effects/extractF.glsl
index e77baa5bee115ea038138883aacb1c546ddea94a..713f8021de0c636f800e38fec0d8bacc8fc856b4 100644
--- a/indra/newview/app_settings/shaders/class2/effects/extractF.glsl
+++ b/indra/newview/app_settings/shaders/class2/effects/extractF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 uniform sampler2DRect RenderTexture;
 uniform float extractLow;
diff --git a/indra/newview/app_settings/shaders/class2/effects/nightVisionF.glsl b/indra/newview/app_settings/shaders/class2/effects/nightVisionF.glsl
index 8e0eec6f5e9a98c5727f73aa929832db345489d5..fd94b2e95f97a6b0d702ec3730d93bc5cef0bacf 100644
--- a/indra/newview/app_settings/shaders/class2/effects/nightVisionF.glsl
+++ b/indra/newview/app_settings/shaders/class2/effects/nightVisionF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 uniform sampler2DRect RenderTexture;
 uniform sampler2D NoiseTexture;
diff --git a/indra/newview/app_settings/shaders/class2/effects/simpleF.glsl b/indra/newview/app_settings/shaders/class2/effects/simpleF.glsl
index 98a50e22fc441d72aff3a2e87a77470bc1acc70b..a1a9c9716cc792b2e0f53b41896d16880f7bc613 100644
--- a/indra/newview/app_settings/shaders/class2/effects/simpleF.glsl
+++ b/indra/newview/app_settings/shaders/class2/effects/simpleF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 uniform sampler2DRect RenderTexture;
 
diff --git a/indra/newview/app_settings/shaders/class2/environment/terrainF.glsl b/indra/newview/app_settings/shaders/class2/environment/terrainF.glsl
index bbb8951f3a3e9d4cab7c98637195735f196421a3..9527dc469bab812a31ad26a74d7df4b86d52ebac 100644
--- a/indra/newview/app_settings/shaders/class2/environment/terrainF.glsl
+++ b/indra/newview/app_settings/shaders/class2/environment/terrainF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 uniform sampler2D detail_0;
 uniform sampler2D detail_1;
diff --git a/indra/newview/app_settings/shaders/class2/environment/terrainV.glsl b/indra/newview/app_settings/shaders/class2/environment/terrainV.glsl
index 84906c16bffd638afc6024c84d4c1bc2c43299c2..2658bee88da1296f48d0c607be49f4493f212d98 100644
--- a/indra/newview/app_settings/shaders/class2/environment/terrainV.glsl
+++ b/indra/newview/app_settings/shaders/class2/environment/terrainV.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 void calcAtmospherics(vec3 inPositionEye);
 
diff --git a/indra/newview/app_settings/shaders/class2/environment/terrainWaterF.glsl b/indra/newview/app_settings/shaders/class2/environment/terrainWaterF.glsl
index 7590c542ef46cea4a5f3d901ab7809c4b5ebbd4d..974e227b77f1bfb7fd2a03ae560a4119e24543c0 100644
--- a/indra/newview/app_settings/shaders/class2/environment/terrainWaterF.glsl
+++ b/indra/newview/app_settings/shaders/class2/environment/terrainWaterF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 uniform sampler2D detail_0;
 uniform sampler2D detail_1;
diff --git a/indra/newview/app_settings/shaders/class2/environment/underWaterF.glsl b/indra/newview/app_settings/shaders/class2/environment/underWaterF.glsl
index 900f1a6cb83668b0ae79622e49861bfd969ae4e0..702e0881acd0d6bcc56cfacc8815e93f381389e1 100644
--- a/indra/newview/app_settings/shaders/class2/environment/underWaterF.glsl
+++ b/indra/newview/app_settings/shaders/class2/environment/underWaterF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 uniform sampler2D diffuseMap;
 uniform sampler2D bumpMap;   
diff --git a/indra/newview/app_settings/shaders/class2/environment/waterF.glsl b/indra/newview/app_settings/shaders/class2/environment/waterF.glsl
index f4f6b6e90fa0bd80dd494a0482e14b25c7beffc8..c4e4bc08c5138c8cc4fc21687c57da95ddf3fa9e 100644
--- a/indra/newview/app_settings/shaders/class2/environment/waterF.glsl
+++ b/indra/newview/app_settings/shaders/class2/environment/waterF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 vec3 scaleSoftClip(vec3 inColor);
 vec3 atmosTransport(vec3 inColor);
diff --git a/indra/newview/app_settings/shaders/class2/environment/waterFogF.glsl b/indra/newview/app_settings/shaders/class2/environment/waterFogF.glsl
index 9f3328cbf0cfe9bb6d019fe20edb90fd899ee91b..b66b72b4015b3e6ce3e679686553c91289df3d2d 100644
--- a/indra/newview/app_settings/shaders/class2/environment/waterFogF.glsl
+++ b/indra/newview/app_settings/shaders/class2/environment/waterFogF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 uniform vec4 lightnorm;
 uniform vec4 waterPlane;
diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightF.glsl
index 342bc2ab6673aaea1d76832502645140401d874e..4c31602736ca019e230c0b17f40b4d56ffe4e47e 100644
--- a/indra/newview/app_settings/shaders/class2/lighting/lightF.glsl
+++ b/indra/newview/app_settings/shaders/class2/lighting/lightF.glsl
@@ -5,16 +5,14 @@
  * $/LicenseInfo$
  */
  
-#version 120
 
-uniform sampler2D diffuseMap;
 
 vec3 atmosLighting(vec3 light);
 vec3 scaleSoftClip(vec3 light);
 
 void default_lighting() 
 {
-	vec4 color = texture2D(diffuseMap, gl_TexCoord[0].xy) * gl_Color;
+	vec4 color = diffuseLookup(gl_TexCoord[0].xy) * gl_Color;
 	
 	color.rgb = atmosLighting(color.rgb);
 
diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightF.glsl
index dad18b588383139379889a453e207972cc1be2e2..95bd052b5d4e2810b7e7871adf9c48fba44d8b57 100644
--- a/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightF.glsl
+++ b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightF.glsl
@@ -5,16 +5,14 @@
  * $/LicenseInfo$
  */
  
-#version 120
 
-uniform sampler2D diffuseMap;
 
 vec3 fullbrightAtmosTransport(vec3 light);
 vec3 fullbrightScaleSoftClip(vec3 light);
 
 void fullbright_lighting()
 {
-	vec4 color = texture2D(diffuseMap, gl_TexCoord[0].xy) * gl_Color;
+	vec4 color = diffuseLookup(gl_TexCoord[0].xy) * gl_Color;
 	
 	color.rgb = fullbrightAtmosTransport(color.rgb);
 	
diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightNonIndexedF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightNonIndexedF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..b1e61e1a33afdac4da5f633dc15405489d87e3d7
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightNonIndexedF.glsl
@@ -0,0 +1,25 @@
+/** 
+ * @file lightFullbrightF.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+ 
+
+
+vec3 fullbrightAtmosTransport(vec3 light);
+vec3 fullbrightScaleSoftClip(vec3 light);
+
+uniform sampler2D diffuseMap;
+
+void fullbright_lighting()
+{
+	vec4 color = texture2D(diffuseMap,gl_TexCoord[0].xy) * gl_Color;
+	
+	color.rgb = fullbrightAtmosTransport(color.rgb);
+	
+	color.rgb = fullbrightScaleSoftClip(color.rgb);
+
+	gl_FragColor = color;
+}
+
diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightShinyF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightShinyF.glsl
index 73ff81e03a6ffdb2865356b48efde11a54136ae4..26f0ea84e06286e48c6f57f5b7326e0485887722 100644
--- a/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightShinyF.glsl
+++ b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightShinyF.glsl
@@ -5,9 +5,8 @@
  * $/LicenseInfo$
  */
  
-#version 120
 
-uniform sampler2D diffuseMap;
+
 uniform samplerCube environmentMap;
 
 vec3 fullbrightShinyAtmosTransport(vec3 light);
@@ -15,7 +14,7 @@ vec3 fullbrightScaleSoftClip(vec3 light);
 
 void fullbright_shiny_lighting()
 {
-	vec4 color = texture2D(diffuseMap, gl_TexCoord[0].xy);
+	vec4 color = diffuseLookup(gl_TexCoord[0].xy);
 	color.rgb *= gl_Color.rgb;
 	
 	vec3 envColor = textureCube(environmentMap, gl_TexCoord[1].xyz).rgb;	
diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightShinyNonIndexedF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightShinyNonIndexedF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..953298da0dae05b25b27971bae4783b02e3d80ab
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightShinyNonIndexedF.glsl
@@ -0,0 +1,32 @@
+/** 
+ * @file lightFullbrightShinyF.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+ 
+
+
+uniform samplerCube environmentMap;
+uniform sampler2D diffuseMap;
+
+vec3 fullbrightShinyAtmosTransport(vec3 light);
+vec3 fullbrightScaleSoftClip(vec3 light);
+
+void fullbright_shiny_lighting()
+{
+	vec4 color = texture2D(diffuseMap, gl_TexCoord[0].xy);
+	color.rgb *= gl_Color.rgb;
+	
+	vec3 envColor = textureCube(environmentMap, gl_TexCoord[1].xyz).rgb;	
+	color.rgb = mix(color.rgb, envColor.rgb, gl_Color.a);
+
+	color.rgb = fullbrightShinyAtmosTransport(color.rgb);
+
+	color.rgb = fullbrightScaleSoftClip(color.rgb);
+
+	color.a = max(color.a, gl_Color.a);
+
+	gl_FragColor = color;
+}
+
diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightShinyWaterF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightShinyWaterF.glsl
index 9b4b58436990b10e00a82b031fbcdbc0c061e7f1..a6e10a249d677109dc468ac3139cb88f94acb8cf 100644
--- a/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightShinyWaterF.glsl
+++ b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightShinyWaterF.glsl
@@ -5,9 +5,9 @@
  * $License$
  */
  
-#version 120
 
-uniform sampler2D diffuseMap;
+
+
 uniform samplerCube environmentMap;
 
 vec3 fullbrightShinyAtmosTransport(vec3 light);
@@ -16,7 +16,7 @@ vec4 applyWaterFog(vec4 color);
 
 void fullbright_shiny_lighting_water()
 {
-	vec4 color = texture2D(diffuseMap, gl_TexCoord[0].xy);
+	vec4 color = diffuseLookup(gl_TexCoord[0].xy);
 	color.rgb *= gl_Color.rgb;
 	
 	vec3 envColor = textureCube(environmentMap, gl_TexCoord[1].xyz).rgb;	
diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightShinyWaterNonIndexedF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightShinyWaterNonIndexedF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..b4bb665a2b1b3f3ba4fdad8c920193c4138b9656
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightShinyWaterNonIndexedF.glsl
@@ -0,0 +1,32 @@
+/** 
+ * @file lightFullbrightShinyWaterF.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+ 
+
+
+
+uniform samplerCube environmentMap;
+uniform sampler2D diffuseMap;
+
+vec3 fullbrightShinyAtmosTransport(vec3 light);
+vec3 fullbrightScaleSoftClip(vec3 light);
+vec4 applyWaterFog(vec4 color);
+
+void fullbright_shiny_lighting_water()
+{
+	vec4 color = texture2D(diffuseMap,gl_TexCoord[0].xy);
+	color.rgb *= gl_Color.rgb;
+	
+	vec3 envColor = textureCube(environmentMap, gl_TexCoord[1].xyz).rgb;	
+	color.rgb = mix(color.rgb, envColor.rgb, gl_Color.a);
+
+	color.rgb = fullbrightShinyAtmosTransport(color.rgb);
+	color.rgb = fullbrightScaleSoftClip(color.rgb);
+	color.a = max(color.a, gl_Color.a);
+
+	gl_FragColor = applyWaterFog(color);
+}
+
diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightWaterF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightWaterF.glsl
index 3d46c8d8744271a0a07e9ebfa2bc01a8a1f0bb5e..887d4130e70cd64962e64f7753c653e1a0f706c6 100644
--- a/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightWaterF.glsl
+++ b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightWaterF.glsl
@@ -5,16 +5,16 @@
  * $/LicenseInfo$
  */
  
-#version 120
 
-uniform sampler2D diffuseMap;
+
+vec4 diffuseLookup(vec2 texcoord);
 
 vec3 fullbrightAtmosTransport(vec3 light);
 vec4 applyWaterFog(vec4 color);
 
 void fullbright_lighting_water()
 {
-	vec4 color = texture2D(diffuseMap, gl_TexCoord[0].xy) * gl_Color;
+	vec4 color = diffuseLookup(gl_TexCoord[0].xy) * gl_Color;
 
 	color.rgb = fullbrightAtmosTransport(color.rgb);
 	
diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightWaterNonIndexedF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightWaterNonIndexedF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..1234682ae978b9d29e6b1d682af2d69e77810da7
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightWaterNonIndexedF.glsl
@@ -0,0 +1,23 @@
+/** 
+ * @file lightFullbrightWaterF.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+ 
+
+
+uniform sampler2D diffuseMap;
+
+vec3 fullbrightAtmosTransport(vec3 light);
+vec4 applyWaterFog(vec4 color);
+
+void fullbright_lighting_water()
+{
+	vec4 color = texture2D(diffuseMap, gl_TexCoord[0].xy) * gl_Color;
+
+	color.rgb = fullbrightAtmosTransport(color.rgb);
+	
+	gl_FragColor = applyWaterFog(color);
+}
+
diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightNonIndexedF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightNonIndexedF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..149cf791f57f0a6c2e81529e19b12386afd3609c
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/lighting/lightNonIndexedF.glsl
@@ -0,0 +1,25 @@
+/** 
+ * @file lightF.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+ 
+
+
+uniform sampler2D diffuseMap;
+
+vec3 atmosLighting(vec3 light);
+vec3 scaleSoftClip(vec3 light);
+
+void default_lighting() 
+{
+	vec4 color = texture2D(diffuseMap,gl_TexCoord[0].xy) * gl_Color;
+	
+	color.rgb = atmosLighting(color.rgb);
+
+	color.rgb = scaleSoftClip(color.rgb);
+
+	gl_FragColor = color;
+}
+
diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightShinyF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightShinyF.glsl
index ebe21320b43f8a8118623dae5bd7ba8f2fb5e9e9..300fcac0924251f8b30cc7313c205b6211430bc3 100644
--- a/indra/newview/app_settings/shaders/class2/lighting/lightShinyF.glsl
+++ b/indra/newview/app_settings/shaders/class2/lighting/lightShinyF.glsl
@@ -5,9 +5,9 @@
  * $/LicenseInfo$
  */
  
-#version 120
 
-uniform sampler2D diffuseMap;
+
+
 uniform samplerCube environmentMap;
 
 vec3 scaleSoftClip(vec3 light);
@@ -16,7 +16,7 @@ vec4 applyWaterFog(vec4 color);
 
 void shiny_lighting()
 {
-	vec4 color = texture2D(diffuseMap, gl_TexCoord[0].xy);
+	vec4 color = diffuseLookup(gl_TexCoord[0].xy);
 	color.rgb *= gl_Color.rgb;
 	
 	vec3 envColor = textureCube(environmentMap, gl_TexCoord[1].xyz).rgb;	
diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightShinyNonIndexedF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightShinyNonIndexedF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..e877c0abb122744c2e161c60a2a65ed1fc7dfa8b
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/lighting/lightShinyNonIndexedF.glsl
@@ -0,0 +1,32 @@
+/** 
+ * @file lightShinyF.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+ 
+
+
+
+uniform samplerCube environmentMap;
+uniform sampler2D diffuseMap;
+
+vec3 scaleSoftClip(vec3 light);
+vec3 atmosLighting(vec3 light);
+vec4 applyWaterFog(vec4 color);
+
+void shiny_lighting()
+{
+	vec4 color = texture2D(diffuseMap,gl_TexCoord[0].xy);
+	color.rgb *= gl_Color.rgb;
+	
+	vec3 envColor = textureCube(environmentMap, gl_TexCoord[1].xyz).rgb;	
+	color.rgb = mix(color.rgb, envColor.rgb, gl_Color.a);
+
+	color.rgb = atmosLighting(color.rgb);
+
+	color.rgb = scaleSoftClip(color.rgb);
+	color.a = max(color.a, gl_Color.a);
+	gl_FragColor = color;
+}
+
diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightShinyWaterF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightShinyWaterF.glsl
index 7f48e2cf1d5ec1c5ed586b4101fb5b385545e451..07572fa91542e66acbbb95ba95aa3fd06ab68269 100644
--- a/indra/newview/app_settings/shaders/class2/lighting/lightShinyWaterF.glsl
+++ b/indra/newview/app_settings/shaders/class2/lighting/lightShinyWaterF.glsl
@@ -5,10 +5,9 @@
  * $/LicenseInfo$
  */
  
-#version 120
 
 
-uniform sampler2D diffuseMap;
+
 uniform samplerCube environmentMap;
 
 vec3 atmosLighting(vec3 light);
@@ -16,7 +15,7 @@ vec4 applyWaterFog(vec4 color);
 
 void shiny_lighting_water()
 {
-	vec4 color = texture2D(diffuseMap, gl_TexCoord[0].xy);
+	vec4 color = diffuseLookup(gl_TexCoord[0].xy);
 	color.rgb *= gl_Color.rgb;
 	
 	vec3 envColor = textureCube(environmentMap, gl_TexCoord[1].xyz).rgb;	
diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightShinyWaterNonIndexedF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightShinyWaterNonIndexedF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..39041794272c65914cc1b587584a09abc4839aef
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/lighting/lightShinyWaterNonIndexedF.glsl
@@ -0,0 +1,29 @@
+/** 
+ * @file lightShinyWaterF.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+ 
+
+
+
+uniform sampler2D diffuseMap;
+uniform samplerCube environmentMap;
+
+vec3 atmosLighting(vec3 light);
+vec4 applyWaterFog(vec4 color);
+
+void shiny_lighting_water()
+{
+	vec4 color = texture2D(diffuseMap,gl_TexCoord[0].xy);
+	color.rgb *= gl_Color.rgb;
+	
+	vec3 envColor = textureCube(environmentMap, gl_TexCoord[1].xyz).rgb;	
+	color.rgb = mix(color.rgb, envColor.rgb, gl_Color.a);
+
+	color.rgb = atmosLighting(color.rgb);
+	color.a = max(color.a, gl_Color.a);
+	gl_FragColor = applyWaterFog(color);
+}
+
diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightSpecularV.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightSpecularV.glsl
index ad1dc4da77e17a34c9830f60566770f31cac6a64..3384f64d07a4d293f27e927d251a73e2f04188ec 100644
--- a/indra/newview/app_settings/shaders/class2/lighting/lightSpecularV.glsl
+++ b/indra/newview/app_settings/shaders/class2/lighting/lightSpecularV.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 // All lights, no specular highlights
 
diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightV.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightV.glsl
index a0f6e019ef12c4779a770c65553db3b44e2a0799..10c770fcc240abc6dd2780fa777e6f67a5f10f66 100644
--- a/indra/newview/app_settings/shaders/class2/lighting/lightV.glsl
+++ b/indra/newview/app_settings/shaders/class2/lighting/lightV.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 // All lights, no specular highlights
 
diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightWaterF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightWaterF.glsl
index 97eba92d7b51f463f0e6cd877eb3ed6950855fad..61341a9f1fb08adbf05cbdcd49ff023625898a70 100644
--- a/indra/newview/app_settings/shaders/class2/lighting/lightWaterF.glsl
+++ b/indra/newview/app_settings/shaders/class2/lighting/lightWaterF.glsl
@@ -5,16 +5,14 @@
  * $/LicenseInfo$
  */
  
-#version 120
 
-uniform sampler2D diffuseMap;
 
 vec3 atmosLighting(vec3 light);
 vec4 applyWaterFog(vec4 color);
 
 void default_lighting_water()
 {
-	vec4 color = texture2D(diffuseMap, gl_TexCoord[0].xy) * gl_Color;
+	vec4 color = diffuseLookup(gl_TexCoord[0].xy) * gl_Color;
 
 	color.rgb = atmosLighting(color.rgb);
 
diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightWaterNonIndexedF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightWaterNonIndexedF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..ba850b61d0b0bd5b6e05dc52bc14fe32756844f9
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/lighting/lightWaterNonIndexedF.glsl
@@ -0,0 +1,23 @@
+/** 
+ * @file lightWaterF.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+ 
+
+
+uniform sampler2D diffuseMap;
+
+vec3 atmosLighting(vec3 light);
+vec4 applyWaterFog(vec4 color);
+
+void default_lighting_water()
+{
+	vec4 color = texture2D(diffuseMap,gl_TexCoord[0].xy) * gl_Color;
+
+	color.rgb = atmosLighting(color.rgb);
+
+	gl_FragColor = applyWaterFog(color);
+}
+
diff --git a/indra/newview/app_settings/shaders/class2/lighting/sumLightsSpecularV.glsl b/indra/newview/app_settings/shaders/class2/lighting/sumLightsSpecularV.glsl
index fde32ed0358f55c07f8124454c3086f775bb5cd8..8df2e6f222baab4182815ca31545350f60f3d6cc 100644
--- a/indra/newview/app_settings/shaders/class2/lighting/sumLightsSpecularV.glsl
+++ b/indra/newview/app_settings/shaders/class2/lighting/sumLightsSpecularV.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 float calcDirectionalLightSpecular(inout vec4 specular, vec3 view, vec3 n, vec3 l, vec3 lightCol, float da);
 vec3 calcPointLightSpecular(inout vec4 specular, vec3 view, vec3 v, vec3 n, vec3 l, float r, float pw, vec3 lightCol);
diff --git a/indra/newview/app_settings/shaders/class2/lighting/sumLightsV.glsl b/indra/newview/app_settings/shaders/class2/lighting/sumLightsV.glsl
index 8fe49e3be026cebf056e9d6968361346abdd1465..3d43a1813a53f4329751bc760b0305f93e024d6e 100644
--- a/indra/newview/app_settings/shaders/class2/lighting/sumLightsV.glsl
+++ b/indra/newview/app_settings/shaders/class2/lighting/sumLightsV.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 float calcDirectionalLight(vec3 n, vec3 l);
 float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float is_pointlight);
diff --git a/indra/newview/app_settings/shaders/class2/objects/fullbrightShinyV.glsl b/indra/newview/app_settings/shaders/class2/objects/fullbrightShinyV.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..f49e74406fd19c5490849e7b3f731acfdd04df36
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/objects/fullbrightShinyV.glsl
@@ -0,0 +1,35 @@
+/**
+ * @file fullbrightShinyV.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+ 
+
+
+void calcAtmospherics(vec3 inPositionEye);
+
+uniform vec4 origin;
+
+varying float vary_texture_index;
+
+void main()
+{
+	//transform vertex
+	vec4 vert = vec4(gl_Vertex.xyz,1.0);
+	vary_texture_index = gl_Vertex.w;
+	gl_Position = gl_ModelViewProjectionMatrix*vert;
+	
+	vec4 pos = (gl_ModelViewMatrix * vert);
+	vec3 norm = normalize(gl_NormalMatrix * gl_Normal);
+	vec3 ref = reflect(pos.xyz, -norm);
+
+	gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
+	gl_TexCoord[1] = gl_TextureMatrix[1]*vec4(ref,1.0);
+
+	calcAtmospherics(pos.xyz);
+
+	gl_FrontColor = gl_Color;
+
+	gl_FogFragCoord = pos.z;
+}
diff --git a/indra/newview/app_settings/shaders/class2/objects/fullbrightV.glsl b/indra/newview/app_settings/shaders/class2/objects/fullbrightV.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..3076fa3260035ddd247467927c02fbfe9af19794
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/objects/fullbrightV.glsl
@@ -0,0 +1,29 @@
+/**
+ * @file fullbrightV.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+ 
+
+
+void calcAtmospherics(vec3 inPositionEye);
+
+varying float vary_texture_index;
+
+void main()
+{
+	//transform vertex
+	vec4 vert = vec4(gl_Vertex.xyz,1.0);
+	vary_texture_index = gl_Vertex.w;
+	gl_Position = gl_ModelViewProjectionMatrix*vert;
+	gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
+	
+	vec4 pos = (gl_ModelViewMatrix * vert);
+
+	calcAtmospherics(pos.xyz);
+
+	gl_FrontColor = gl_Color;
+
+	gl_FogFragCoord = pos.z;
+}
diff --git a/indra/newview/app_settings/shaders/class2/objects/shinyV.glsl b/indra/newview/app_settings/shaders/class2/objects/shinyV.glsl
index 4cebb06df080e8b289cccaee534789d54d7177aa..49992d353555757efe783be2a3f641dd0b078e17 100644
--- a/indra/newview/app_settings/shaders/class2/objects/shinyV.glsl
+++ b/indra/newview/app_settings/shaders/class2/objects/shinyV.glsl
@@ -5,20 +5,24 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol);
 
 void calcAtmospherics(vec3 inPositionEye);
 
+varying float vary_texture_index;
+
 uniform vec4 origin;
 
 void main()
 {
 	//transform vertex
-	gl_Position = ftransform();
+	vec4 vert = vec4(gl_Vertex.xyz,1.0);
+	vary_texture_index = gl_Vertex.w;
+	gl_Position = gl_ModelViewProjectionMatrix*vert;
 	
-	vec4 pos = (gl_ModelViewMatrix * gl_Vertex);
+	vec4 pos = (gl_ModelViewMatrix * vert);
 	vec3 norm = normalize(gl_NormalMatrix * gl_Normal);
 	vec3 ref = reflect(pos.xyz, -norm);
 
diff --git a/indra/newview/app_settings/shaders/class2/objects/simpleV.glsl b/indra/newview/app_settings/shaders/class2/objects/simpleV.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..5e02391767fefedd416b6fb0a0cd69ae0aaedb68
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/objects/simpleV.glsl
@@ -0,0 +1,33 @@
+/** 
+ * @file simpleV.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+ 
+
+
+vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol);
+void calcAtmospherics(vec3 inPositionEye);
+
+varying float vary_texture_index;
+
+void main()
+{
+	//transform vertex
+	vec4 vert = vec4(gl_Vertex.xyz,1.0);
+	vary_texture_index = gl_Vertex.w;
+	gl_Position = gl_ModelViewProjectionMatrix*vert;
+	gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
+	
+	vec4 pos = (gl_ModelViewMatrix * vert);
+	
+	vec3 norm = normalize(gl_NormalMatrix * gl_Normal);
+
+	calcAtmospherics(pos.xyz);
+
+	vec4 color = calcLighting(pos.xyz, norm, gl_Color, vec4(0.));
+	gl_FrontColor = color;
+
+	gl_FogFragCoord = pos.z;
+}
diff --git a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsF.glsl b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsF.glsl
index 77d15fba9a938989469fcbbf151e0b5f76203f61..21a0812c1b5ce1bd269bf8701c81ccd26ad9351e 100644
--- a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsF.glsl
+++ b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 //////////////////////////////////////////////////////////
 // The fragment shader for the terrain atmospherics
diff --git a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsHelpersV.glsl b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsHelpersV.glsl
index 8c5b864cbef69e49d0e0c71571ebcbcedbd0ac3c..ab4cf4806d36397ba9ebf6d5935f10f635915620 100644
--- a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsHelpersV.glsl
+++ b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsHelpersV.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 // Output variables
 vec3 getSunlitColor();
diff --git a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsV.glsl b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsV.glsl
index 8d365c15caf4fedb58ee369ee58a83462703995d..b61b0bb3966db2dd191aec85c47f54254327f2b1 100644
--- a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsV.glsl
+++ b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsV.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 // varying param funcs
 void setSunlitColor(vec3 v);
diff --git a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsVarsF.glsl b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsVarsF.glsl
index cf9ef306324b1565d17e61496bce1b0da47e7f2c..3a6585bb330bb6c1c8d0c99f960adb1b4c2f7a24 100644
--- a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsVarsF.glsl
+++ b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsVarsF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 varying vec3 vary_PositionEye;
 
diff --git a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsVarsV.glsl b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsVarsV.glsl
index 398f1556a06925a21a2e18e15ad8a120af7573ca..0f6e231ca6988c85d0bec99f3cab73242cc4e35a 100644
--- a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsVarsV.glsl
+++ b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsVarsV.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 varying vec3 vary_PositionEye;
 
diff --git a/indra/newview/app_settings/shaders/class2/windlight/cloudsF.glsl b/indra/newview/app_settings/shaders/class2/windlight/cloudsF.glsl
index 13207997b2f88b2f91842bec4a15a98ddb115804..20f907a006215a630ce250a039974dcda03a6f7d 100644
--- a/indra/newview/app_settings/shaders/class2/windlight/cloudsF.glsl
+++ b/indra/newview/app_settings/shaders/class2/windlight/cloudsF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 /////////////////////////////////////////////////////////////////////////
 // The fragment shader for the sky
diff --git a/indra/newview/app_settings/shaders/class2/windlight/cloudsV.glsl b/indra/newview/app_settings/shaders/class2/windlight/cloudsV.glsl
index 267ef36d4db63e6666d8cbf17a561546497d3eec..3eac63076c19119a7e0f78e4c0d68f20e2dcf26e 100644
--- a/indra/newview/app_settings/shaders/class2/windlight/cloudsV.glsl
+++ b/indra/newview/app_settings/shaders/class2/windlight/cloudsV.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 //////////////////////////////////////////////////////////////////////////
 // The vertex shader for creating the atmospheric sky
diff --git a/indra/newview/app_settings/shaders/class2/windlight/gammaF.glsl b/indra/newview/app_settings/shaders/class2/windlight/gammaF.glsl
index a658edd21f82d539bf9235fa27ddd41dc5275459..6570dcb6081d0f95fd6f2f107d01842cd39ce56b 100644
--- a/indra/newview/app_settings/shaders/class2/windlight/gammaF.glsl
+++ b/indra/newview/app_settings/shaders/class2/windlight/gammaF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 uniform vec4 gamma;
 
diff --git a/indra/newview/app_settings/shaders/class2/windlight/skyF.glsl b/indra/newview/app_settings/shaders/class2/windlight/skyF.glsl
index 77ca4868a68a81eeeee79cece7cddddfe2cfd004..d14c638130172c95807e6821a5691170f3277ced 100644
--- a/indra/newview/app_settings/shaders/class2/windlight/skyF.glsl
+++ b/indra/newview/app_settings/shaders/class2/windlight/skyF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 /////////////////////////////////////////////////////////////////////////
 // The fragment shader for the sky
diff --git a/indra/newview/app_settings/shaders/class2/windlight/skyV.glsl b/indra/newview/app_settings/shaders/class2/windlight/skyV.glsl
index 03bca8f27e2e2ec9c45cbb4386be0ee70fefc416..1ea00f723afcab0ed9f5f746f194f1ab2e5e7dde 100644
--- a/indra/newview/app_settings/shaders/class2/windlight/skyV.glsl
+++ b/indra/newview/app_settings/shaders/class2/windlight/skyV.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 // SKY ////////////////////////////////////////////////////////////////////////
 // The vertex shader for creating the atmospheric sky
diff --git a/indra/newview/app_settings/shaders/class2/windlight/transportF.glsl b/indra/newview/app_settings/shaders/class2/windlight/transportF.glsl
index 7f1ad4d5b4d31efb498056e130b7b6aacf6ead14..28381482c135df9b91875775191f2279a1dae708 100644
--- a/indra/newview/app_settings/shaders/class2/windlight/transportF.glsl
+++ b/indra/newview/app_settings/shaders/class2/windlight/transportF.glsl
@@ -5,8 +5,6 @@
  * $/LicenseInfo$
  */
  
-#version 120
-
 //////////////////////////////////////////////////////////
 // The fragment shader for the terrain atmospherics
 //////////////////////////////////////////////////////////
diff --git a/indra/newview/app_settings/shaders/class3/avatar/avatarV.glsl b/indra/newview/app_settings/shaders/class3/avatar/avatarV.glsl
index a003e2a1f10e521eaee6a9188bf5a0a69cc61ddc..3d970d252c6e581b9fbe879fcd8f434df8077337 100644
--- a/indra/newview/app_settings/shaders/class3/avatar/avatarV.glsl
+++ b/indra/newview/app_settings/shaders/class3/avatar/avatarV.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol);
 mat4 getSkinnedTransform();
diff --git a/indra/newview/app_settings/shaders/class3/deferred/giDownsampleF.glsl b/indra/newview/app_settings/shaders/class3/deferred/giDownsampleF.glsl
index fc370ef367c3f60319f84c0027c5ecb4bf6cf77b..498fee7c66ba3ab9495afb273425a84cc1ac43e6 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/giDownsampleF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/giDownsampleF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 uniform sampler2DRect giLightMap;
 
diff --git a/indra/newview/app_settings/shaders/class3/deferred/giDownsampleV.glsl b/indra/newview/app_settings/shaders/class3/deferred/giDownsampleV.glsl
index ae57227fe528b03b5e2a0d216c9a8b97a5ddfb39..eebe930666a60742bb73b063f384b32d99d4f726 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/giDownsampleV.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/giDownsampleV.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 varying vec2 vary_fragcoord;
 uniform vec2 screen_res;
diff --git a/indra/newview/app_settings/shaders/class3/deferred/giF.glsl b/indra/newview/app_settings/shaders/class3/deferred/giF.glsl
index 951e3e97aefc88dee9408e01aad35d701c24d2d5..9896f8dafecbe6438ffc12486fcbdb0a57222477 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/giF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/giF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 #extension GL_ARB_texture_rectangle : enable
 
diff --git a/indra/newview/app_settings/shaders/class3/deferred/giFinalF.glsl b/indra/newview/app_settings/shaders/class3/deferred/giFinalF.glsl
index b2f8b2c6338b207c23270e896d50a87f58f6a619..df4c6b3e0a4af0488db7fc977b767b11930a28b8 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/giFinalF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/giFinalF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 #extension GL_ARB_texture_rectangle : enable
 
diff --git a/indra/newview/app_settings/shaders/class3/deferred/giFinalV.glsl b/indra/newview/app_settings/shaders/class3/deferred/giFinalV.glsl
index 19c4e07b8b8dffa2791280efcf370e0940e5e306..7e20d71529ea52671fd1a19d10134e93f15adde0 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/giFinalV.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/giFinalV.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 varying vec2 vary_fragcoord;
 uniform vec2 screen_res;
diff --git a/indra/newview/app_settings/shaders/class3/deferred/giV.glsl b/indra/newview/app_settings/shaders/class3/deferred/giV.glsl
index 8dc1410ea5ad90d05d8bad4c485238550fd4cdd7..e86f2896da5fbc006f817a4f03a256599a7a69e3 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/giV.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/giV.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 varying vec2 vary_fragcoord;
 
diff --git a/indra/newview/app_settings/shaders/class3/deferred/luminanceF.glsl b/indra/newview/app_settings/shaders/class3/deferred/luminanceF.glsl
index 5f3bf68b240132fbe301d529805a06c9fa9e7b93..980def6443aba0136bd876eac59877c4acd288a0 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/luminanceF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/luminanceF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 #extension GL_ARB_texture_rectangle : enable
 
diff --git a/indra/newview/app_settings/shaders/class3/deferred/luminanceV.glsl b/indra/newview/app_settings/shaders/class3/deferred/luminanceV.glsl
index a24eda35dce7e099240dfc47dd37de2e5a1cb06b..9afeac6ddfa76c4ce00d63f57325d8defc09f166 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/luminanceV.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/luminanceV.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 varying vec2 vary_fragcoord;
 
diff --git a/indra/newview/app_settings/shaders/class3/deferred/postDeferredF.glsl b/indra/newview/app_settings/shaders/class3/deferred/postDeferredF.glsl
index ab99a889718571b597a502d811b8c30551d440ef..6d4c20f68c01e535fb1f62a78c04aa9ba16b1065 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/postDeferredF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/postDeferredF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
   
-#version 120
+
 
 #extension GL_ARB_texture_rectangle : enable
 
diff --git a/indra/newview/app_settings/shaders/class3/deferred/postDeferredV.glsl b/indra/newview/app_settings/shaders/class3/deferred/postDeferredV.glsl
index 12983baa94882bfc3f58349847dd7bec1b3aadca..876f65ee3adc86302c81426f8ce576b67ae96a95 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/postDeferredV.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/postDeferredV.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 varying vec2 vary_fragcoord;
 uniform vec2 screen_res;
diff --git a/indra/newview/app_settings/shaders/class3/deferred/postgiF.glsl b/indra/newview/app_settings/shaders/class3/deferred/postgiF.glsl
index f037754708726c727f9cff7a43598c3eb4d9e562..fc658816805ccf6236f4b7b93f7909c2513c40c2 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/postgiF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/postgiF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 #extension GL_ARB_texture_rectangle : enable
 
diff --git a/indra/newview/app_settings/shaders/class3/deferred/postgiV.glsl b/indra/newview/app_settings/shaders/class3/deferred/postgiV.glsl
index ae57227fe528b03b5e2a0d216c9a8b97a5ddfb39..eebe930666a60742bb73b063f384b32d99d4f726 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/postgiV.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/postgiV.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 varying vec2 vary_fragcoord;
 uniform vec2 screen_res;
diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl
index ce32f66000f91fa0b67400b931f3da6464d669c7..d38d33cc2193cd64280e863bdd958d8beb595954 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 #extension GL_ARB_texture_rectangle : enable
 
diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightV.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightV.glsl
index 8f0bcca76b86a22f32101d0c81b3631110fff0c9..745cc0199236aeff1ade125a59f78bd48b15d382 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/softenLightV.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightV.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 uniform vec2 screen_res;
 
diff --git a/indra/newview/app_settings/shaders/class3/deferred/treeF.glsl b/indra/newview/app_settings/shaders/class3/deferred/treeF.glsl
index c54d9a1e3e80dcf0bc9ba20d70c92b346d4fa3dc..de7e038402235d2a6044aa200d102923b210ed78 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/treeF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/treeF.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 uniform sampler2D diffuseMap;
 
diff --git a/indra/newview/app_settings/shaders/class3/lighting/sumLightsSpecularV.glsl b/indra/newview/app_settings/shaders/class3/lighting/sumLightsSpecularV.glsl
index 04533fdce1ac78d75e8d724802d07a4aba5e2d3e..92347a5b4a4fb2172c3679f86035e890bc3669da 100644
--- a/indra/newview/app_settings/shaders/class3/lighting/sumLightsSpecularV.glsl
+++ b/indra/newview/app_settings/shaders/class3/lighting/sumLightsSpecularV.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 float calcDirectionalLightSpecular(inout vec4 specular, vec3 view, vec3 n, vec3 l, vec3 lightCol, float da);
 vec3 calcPointLightSpecular(inout vec4 specular, vec3 view, vec3 v, vec3 n, vec3 l, float r, float pw, vec3 lightCol);
diff --git a/indra/newview/app_settings/shaders/class3/lighting/sumLightsV.glsl b/indra/newview/app_settings/shaders/class3/lighting/sumLightsV.glsl
index 73bc18b8663aa6de17e17800558da1d7d5e0a50f..24bbc0a1a115c6267ab5948ebc3b23f51de38b88 100644
--- a/indra/newview/app_settings/shaders/class3/lighting/sumLightsV.glsl
+++ b/indra/newview/app_settings/shaders/class3/lighting/sumLightsV.glsl
@@ -5,7 +5,7 @@
  * $/LicenseInfo$
  */
  
-#version 120
+
 
 float calcDirectionalLight(vec3 n, vec3 l);
 float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float is_pointlight);
diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt
index dd8a88e5586036e14b46bf6ffbeca97485cd83eb..4da155efdab1c5f9fa7396a4762ba7b4418d27a2 100644
--- a/indra/newview/featuretable.txt
+++ b/indra/newview/featuretable.txt
@@ -1,4 +1,4 @@
-version 27
+version 29
 
 // NOTE: This is mostly identical to featuretable_mac.txt with a few differences
 // Should be combined into one table
@@ -48,6 +48,7 @@ RenderTransparentWater		1	1
 RenderTreeLODFactor			1	1.0
 RenderUseImpostors			1	1
 RenderVBOEnable				1	1
+RenderVBOMappingDisable		1	1
 RenderVolumeLODFactor		1	2.0
 UseStartScreen				1	1
 UseOcclusion				1	1
@@ -64,6 +65,7 @@ RenderDeferredSSAO			1	1
 RenderShadowDetail			1	2
 WatchdogDisabled				1	1
 RenderUseStreamVBO			1	1
+RenderFSAASamples			1	16
 
 //
 // Low Graphics Settings
@@ -95,6 +97,7 @@ SkyUseClassicClouds			1	0
 RenderDeferred				1	0
 RenderDeferredSSAO			1	0
 RenderShadowDetail			1	0
+RenderFSAASamples			1	0
 
 //
 // Mid Graphics Settings
@@ -124,6 +127,7 @@ WLSkyDetail					1	48
 RenderDeferred				1	0
 RenderDeferredSSAO			1	0
 RenderShadowDetail			1	0
+RenderFSAASamples			1	0
 
 //
 // High Graphics Settings (purty)
@@ -153,6 +157,7 @@ WLSkyDetail					1	48
 RenderDeferred				1	0
 RenderDeferredSSAO			1	0
 RenderShadowDetail			1	0
+RenderFSAASamples			1	4
 
 //
 // Ultra graphics (REALLY PURTY!)
@@ -181,6 +186,8 @@ WLSkyDetail					1	128
 RenderDeferred				1	1
 RenderDeferredSSAO			1	1
 RenderShadowDetail			1	2
+RenderFSAASamples			1	8
+
 
 //
 // Class Unknown Hardware (unknown)
@@ -238,6 +245,12 @@ RenderDeferred				0	0
 RenderDeferredSSAO			0	0
 RenderShadowDetail			0	0
 
+//
+// No GL_ARB_map_buffer_range
+//
+list NoMapBufferRange
+RenderVBOMappingDisable		1	0
+
 
 //
 // "Default" setups for safe, low, medium, high
@@ -467,7 +480,6 @@ RenderAvatarCloth			0	0
 
 list ATI
 RenderUseStreamVBO			1	0
-RenderAvatarVP				1	0
 
 // Disable vertex buffer objects by default for ATI cards with little video memory
 list ATIVramLT256
diff --git a/indra/newview/featuretable_linux.txt b/indra/newview/featuretable_linux.txt
index 058bdcc7308bf9a35709c3304afb724491a06852..dab73dc3d18fd3d5f70d4b45ed26664189d40f76 100644
--- a/indra/newview/featuretable_linux.txt
+++ b/indra/newview/featuretable_linux.txt
@@ -1,4 +1,4 @@
-version 23
+version 25
 
 // NOTE: This is mostly identical to featuretable_mac.txt with a few differences
 // Should be combined into one table
@@ -48,6 +48,7 @@ RenderTransparentWater		1	1
 RenderTreeLODFactor			1	1.0
 RenderUseImpostors			1	1
 RenderVBOEnable				1	1
+RenderVBOMappingDisable		1	1
 RenderVolumeLODFactor		1	2.0
 UseStartScreen				1	1
 UseOcclusion				1	1
@@ -62,6 +63,7 @@ RenderShaderLightingMaxLevel		1	3
 RenderDeferred				1	1
 RenderDeferredSSAO			1	1
 RenderShadowDetail			1	2
+RenderFSAASamples			1	16
 
 //
 // Low Graphics Settings
@@ -93,6 +95,7 @@ SkyUseClassicClouds			1	0
 RenderDeferred				1	0
 RenderDeferredSSAO			1	0
 RenderShadowDetail			1	0
+RenderFSAASamples			1	0
 
 //
 // Mid Graphics Settings
@@ -122,6 +125,7 @@ WLSkyDetail					1	48
 RenderDeferred				1	0
 RenderDeferredSSAO			1	0
 RenderShadowDetail			1	0
+RenderFSAASamples			1	0
 
 //
 // High Graphics Settings (purty)
@@ -151,6 +155,7 @@ WLSkyDetail					1	48
 RenderDeferred				1	0
 RenderDeferredSSAO			1	0
 RenderShadowDetail			1	0
+RenderFSAASamples			1	4
 
 //
 // Ultra graphics (REALLY PURTY!)
@@ -180,6 +185,7 @@ WLSkyDetail					1	128
 RenderDeferred				1	1
 RenderDeferredSSAO			1	1
 RenderShadowDetail			1	2
+RenderFSAASamples			1	8
 
 //
 // Class Unknown Hardware (unknown)
@@ -237,6 +243,13 @@ RenderDeferred				0	0
 RenderDeferredSSAO			0	0
 RenderShadowDetail			0	0
 
+//
+// No GL_ARB_map_buffer_range
+//
+list NoMapBufferRange
+RenderVBOMappingDisable		1	0
+
+
 
 // "Default" setups for safe, low, medium, high
 //
diff --git a/indra/newview/featuretable_mac.txt b/indra/newview/featuretable_mac.txt
index e2b979d9e9c235e84bc3e14694e2a86c2eb5748f..a1e25aae0884f7162c78cdb023f3122b77ffe115 100644
--- a/indra/newview/featuretable_mac.txt
+++ b/indra/newview/featuretable_mac.txt
@@ -1,4 +1,4 @@
-version 23
+version 26
 
 // NOTE: This is mostly identical to featuretable_mac.txt with a few differences
 // Should be combined into one table
@@ -48,6 +48,7 @@ RenderTransparentWater			1	1
 RenderTreeLODFactor				1	1.0
 RenderUseImpostors				1	1
 RenderVBOEnable					1	1
+RenderVBOMappingDisable		1	1
 RenderVolumeLODFactor			1	2.0
 UseStartScreen				1	1
 UseOcclusion					1	1
@@ -64,6 +65,7 @@ RenderDeferredSSAO			1	1
 RenderShadowDetail			1	2
 WatchdogDisabled				1	1
 RenderUseStreamVBO			1	1
+RenderFSAASamples			1	16
 
 //
 // Low Graphics Settings
@@ -95,6 +97,7 @@ SkyUseClassicClouds			1	0
 RenderDeferred				1	0
 RenderDeferredSSAO			1	0
 RenderShadowDetail			1	0
+RenderFSAASamples			1	0
 
 //
 // Mid Graphics Settings
@@ -124,6 +127,7 @@ WLSkyDetail					1	48
 RenderDeferred				1	0
 RenderDeferredSSAO			1	0
 RenderShadowDetail			1	0
+RenderFSAASamples			1	0
 
 //
 // High Graphics Settings (purty)
@@ -153,6 +157,7 @@ WLSkyDetail					1	48
 RenderDeferred				1	0
 RenderDeferredSSAO			1	0
 RenderShadowDetail			1	2
+RenderFSAASamples			1	4
 
 //
 // Ultra graphics (REALLY PURTY!)
@@ -182,6 +187,7 @@ WLSkyDetail					1	128
 RenderDeferred				1	0
 RenderDeferredSSAO			1	0
 RenderShadowDetail			1	2
+RenderFSAASamples			1	8
 
 //
 // Class Unknown Hardware (unknown)
@@ -239,6 +245,13 @@ RenderDeferred				0	0
 RenderDeferredSSAO			0	0
 RenderShadowDetail			0	0
 
+//
+// No GL_ARB_map_buffer_range
+//
+list NoMapBufferRange
+RenderVBOMappingDisable		1	0
+
+
 //
 // "Default" setups for safe, low, medium, high
 //
@@ -412,31 +425,6 @@ Disregard128DefaultDrawDistance	1	0
 list ATI_Mobility_Radeon_X1xxx
 Disregard128DefaultDrawDistance	1	0
 
-
-
-
-// Avatar hardware skinning causes
-// invisible avatars on HD 2600... so I masked
-// out other possible bad ones till it's fixed
-
-list ATI_Radeon_HD_2300
-RenderAvatarVP				0	0
-RenderAvatarCloth			0	0
-Disregard128DefaultDrawDistance	1	0
-list ATI_Radeon_HD_2400
-RenderAvatarVP				0	0
-RenderAvatarCloth			0	0
-Disregard128DefaultDrawDistance	1	0
-list ATI_Radeon_HD_2600
-RenderAvatarVP				0	0
-RenderAvatarCloth			0	0
-list ATI_Radeon_HD_2900
-RenderAvatarVP				0	0
-RenderAvatarCloth			0	0
-list ATI_Radeon_HD_3800
-RenderAvatarVP				0	0
-RenderAvatarCloth			0	0
-
 /// Tweaked NVIDIA
 
 list NVIDIA_GeForce_FX_5100
diff --git a/indra/newview/featuretable_xp.txt b/indra/newview/featuretable_xp.txt
index 3339172a1a3d49ead0f4562b06c10af0974e05b6..abe4ec99285d9aa3dc4774d963ba90fa3e46ad28 100644
--- a/indra/newview/featuretable_xp.txt
+++ b/indra/newview/featuretable_xp.txt
@@ -1,4 +1,4 @@
-version 27
+version 29
 
 // NOTE: This is mostly identical to featuretable_mac.txt with a few differences
 // Should be combined into one table
@@ -48,6 +48,7 @@ RenderTransparentWater		1	1
 RenderTreeLODFactor			1	1.0
 RenderUseImpostors			1	1
 RenderVBOEnable				1	1
+RenderVBOMappingDisable		1	1
 RenderVolumeLODFactor		1	2.0
 UseStartScreen				1	1
 UseOcclusion				1	1
@@ -64,6 +65,7 @@ RenderDeferredSSAO			1	0
 RenderShadowDetail			1	0
 WatchdogDisabled				1	1
 RenderUseStreamVBO			1	1
+RenderFSAASamples			1	16
 
 //
 // Low Graphics Settings
@@ -95,6 +97,7 @@ SkyUseClassicClouds			1	0
 RenderDeferred				1	0
 RenderDeferredSSAO			1	0
 RenderShadowDetail			1	0
+RenderFSAASamples			1	0
 
 //
 // Mid Graphics Settings
@@ -124,6 +127,7 @@ WLSkyDetail					1	48
 RenderDeferred				1	0
 RenderDeferredSSAO			1	0
 RenderShadowDetail			1	0
+RenderFSAASamples			1	0
 
 //
 // High Graphics Settings (purty)
@@ -153,6 +157,7 @@ WLSkyDetail					1	48
 RenderDeferred				1	0
 RenderDeferredSSAO			1	0
 RenderShadowDetail			1	2
+RenderFSAASamples			1	4
 
 //
 // Ultra graphics (REALLY PURTY!)
@@ -182,6 +187,7 @@ WLSkyDetail					1	128
 RenderDeferred				1	0
 RenderDeferredSSAO			1	0
 RenderShadowDetail			1	2
+RenderFSAASamples			1	8
 
 //
 // Class Unknown Hardware (unknown)
@@ -239,6 +245,13 @@ RenderDeferred				0	0
 RenderDeferredSSAO			0	0
 RenderShadowDetail			0	0
 
+//
+// No GL_ARB_map_buffer_range
+//
+list NoMapBufferRange
+RenderVBOMappingDisable		1	0
+
+
 //
 // "Default" setups for safe, low, medium, high
 //
@@ -466,7 +479,6 @@ RenderAvatarCloth			0	0
 
 list ATI
 RenderUseStreamVBO			1	0
-RenderAvatarVP				1	0
 
 // Disable vertex buffer objects by default for ATI cards with little video memory
 list ATIVramLT256
diff --git a/indra/newview/llaccountingquotamanager.cpp b/indra/newview/llaccountingquotamanager.cpp
index 0a171959e7a69e8fe5d0feaed9f4a0eb550c6ed1..a4f5de5632fb0e8d54f777235595e8a7bc3543ca 100644
--- a/indra/newview/llaccountingquotamanager.cpp
+++ b/indra/newview/llaccountingquotamanager.cpp
@@ -71,12 +71,10 @@ class LLAccountingQuotaResponder : public LLCurl::Responder
 			return;
 		}
 		
-		//Differentiate what the incoming caps could be from the data
-		//bool VOContent  = content.has("Objects");
+		//Differentiate what the incoming caps could be from the data	
 		bool containsParcel    = content.has("parcel");
 		bool containsSelection = content.has("selected");
-		//bool VORegion   = content.has("region");
-				
+					
 		//Loop over the stored object ids checking against the incoming data
 		for ( LLSD::array_iterator iter = mObjectIDs.beginArray(); iter != mObjectIDs.endArray(); ++iter )
 		{
@@ -91,16 +89,17 @@ class LLAccountingQuotaResponder : public LLCurl::Responder
 					for(S32 i = 0; i < dataCount; i++)
 					{
 						//prep#todo verify that this is safe, otherwise just add a bool
-						S32 parcelId = 0;
-						S32 parcelOwner = 0;
+						LLUUID parcelId;
+						//S32 parcelOwner = 0;
 						if ( content["parcel"][i].has("parcel_id") )
 						{
-							parcelId = content["parcel"][i]["parcel_id"].asInteger();
-						}
-						if ( content["parcel"][i].has("parcel_owner") )
-						{
-							parcelOwner = content["parcel"][i]["parcel_owner"].asInteger();
+							parcelId = content["parcel"][i]["parcel_id"].asUUID();
 						}
+						
+						//if ( content["parcel"][i].has("parcel_owner") )
+						//{
+						//	parcelOwner = content["parcel"][i]["parcel_owner"].asInteger();
+						//}
 											
 						F32 ownerRenderCost		= 0;
 						F32 ownerPhysicsCost	= 0;
@@ -117,48 +116,69 @@ class LLAccountingQuotaResponder : public LLCurl::Responder
 						F32 otherNetworkCost	= 0;
 						F32 otherSimulationCost = 0;
 						
-						F32 totalRenderCost		= 0;
-						F32 totalPhysicsCost	= 0;
-						F32 totalNetworkCost	= 0;
-						F32 totalSimulationCost = 0;
+						F32 tempRenderCost		= 0;
+						F32 tempPhysicsCost		= 0;
+						F32 tempNetworkCost		= 0;
+						F32 tempSimulationCost  = 0;
+						
+						F32 selectedRenderCost		= 0;
+						F32 selectedPhysicsCost		= 0;
+						F32 selectedNetworkCost		= 0;
+						F32 selectedSimulationCost  = 0;
 						
+						F32 parcelCapacity			= 0;
+
+						if ( content["parcel"][i].has("capacity") )
+						{
+							parcelCapacity =  content["parcel"][i].has("capacity");
+						}
+
 						if ( content["parcel"][i].has("owner") )
 						{
-							ownerRenderCost		= content["parcel"][i]["owner"]["render"].asReal();
+							ownerRenderCost		= content["parcel"][i]["owner"]["rendering"].asReal();
 							ownerPhysicsCost	= content["parcel"][i]["owner"]["physics"].asReal();
-							ownerNetworkCost	= content["parcel"][i]["owner"]["network"].asReal();
-							ownerSimulationCost = content["parcel"][i]["owner"]["simulation"].asReal();
-							
+							ownerNetworkCost	= content["parcel"][i]["owner"]["streaming"].asReal();
+							ownerSimulationCost = content["parcel"][i]["owner"]["simulation"].asReal();							
 						}
+
 						if ( content["parcel"][i].has("group") )
 						{
-							groupRenderCost		= content["parcel"][i]["group"]["render"].asReal();
+							groupRenderCost		= content["parcel"][i]["group"]["rendering"].asReal();
 							groupPhysicsCost	= content["parcel"][i]["group"]["physics"].asReal();
-							groupNetworkCost	= content["parcel"][i]["group"]["network"].asReal();
+							groupNetworkCost	= content["parcel"][i]["group"]["streaming"].asReal();
 							groupSimulationCost = content["parcel"][i]["group"]["simulation"].asReal();
 							
 						}
 						if ( content["parcel"][i].has("other") )
 						{
-							otherRenderCost		= content["parcel"][i]["other"]["render"].asReal();
+							otherRenderCost		= content["parcel"][i]["other"]["rendering"].asReal();
 							otherPhysicsCost	= content["parcel"][i]["other"]["physics"].asReal();
-							otherNetworkCost	= content["parcel"][i]["other"]["network"].asReal();
+							otherNetworkCost	= content["parcel"][i]["other"]["streaming"].asReal();
 							otherSimulationCost = content["parcel"][i]["other"]["simulation"].asReal();
 						}
 						
-						if ( content["parcel"][i].has("total") )
+						if ( content["parcel"][i].has("temp") )
 						{
-							totalRenderCost		= content["parcel"][i]["total"]["render"].asReal();
-							totalPhysicsCost	= content["parcel"][i]["total"]["physics"].asReal();
-							totalNetworkCost	= content["parcel"][i]["total"]["network"].asReal();
-							totalSimulationCost = content["parcel"][i]["total"]["simulation"].asReal();
-							
+							tempRenderCost		= content["parcel"][i]["total"]["rendering"].asReal();
+							tempPhysicsCost		= content["parcel"][i]["total"]["physics"].asReal();
+							tempNetworkCost		= content["parcel"][i]["total"]["streaming"].asReal();
+							tempSimulationCost  = content["parcel"][i]["total"]["simulation"].asReal();							
+						}
+
+						if ( content["parcel"][i].has("selected") )
+						{
+							selectedRenderCost		= content["parcel"][i]["total"]["rendering"].asReal();
+							selectedPhysicsCost		= content["parcel"][i]["total"]["physics"].asReal();
+							selectedNetworkCost		= content["parcel"][i]["total"]["streaming"].asReal();
+							selectedSimulationCost  = content["parcel"][i]["total"]["simulation"].asReal();							
 						}
 						
-						ParcelQuota parcelQuota( ownerRenderCost, ownerPhysicsCost, ownerNetworkCost, ownerSimulationCost,
-												 groupRenderCost, groupPhysicsCost, groupNetworkCost, groupSimulationCost,
-												 otherRenderCost, otherPhysicsCost, otherNetworkCost, otherSimulationCost,
-												 totalRenderCost, totalPhysicsCost, totalNetworkCost, totalSimulationCost );
+						ParcelQuota parcelQuota( ownerRenderCost,	 ownerPhysicsCost,	  ownerNetworkCost,    ownerSimulationCost,
+												 groupRenderCost,	 groupPhysicsCost,	  groupNetworkCost,    groupSimulationCost,
+												 otherRenderCost,	 otherPhysicsCost,	  otherNetworkCost,    otherSimulationCost,
+												 tempRenderCost,	 tempPhysicsCost,	  tempNetworkCost,	   tempSimulationCost,
+												 selectedRenderCost, selectedPhysicsCost, selectedNetworkCost, selectedSimulationCost,
+												 parcelCapacity );
 						//Update the Parcel						
 						LLParcel* pParcel = LLViewerParcelMgr::getInstance()->getParcelSelection()->getParcel();
 						if ( pParcel )
@@ -179,18 +199,18 @@ class LLAccountingQuotaResponder : public LLCurl::Responder
 					F32 networkCost		= 0;
 					F32 simulationCost	= 0;
 					
-					S32 localId = 0;
+					LLUUID objectId;
 					
-					localId			= content["selected"][i]["local_id"].asInteger();
-					renderCost		= content["selected"][i]["render"].asReal();
+					objectId		= content["selected"][i]["local_id"].asUUID();
+					renderCost		= content["selected"][i]["rendering"].asReal();
 					physicsCost		= content["selected"][i]["physics"].asReal();
-					networkCost		= content["selected"][i]["network"].asReal();
+					networkCost		= content["selected"][i]["streaming"].asReal();
 					simulationCost	= content["selected"][i]["simulation"].asReal();
 					
-					SelectionQuota selectionQuota( localId, renderCost, physicsCost, networkCost, simulationCost );
+					SelectionQuota selectionQuota( objectId, renderCost, physicsCost, networkCost, simulationCost );
 					
 					//Update the objects					
-					//gObjectList.updateQuota( localId, selectionQuota ); 
+					gObjectList.updateQuota( objectId, selectionQuota ); 
 					
 				}
 			}
diff --git a/indra/newview/llagentcamera.cpp b/indra/newview/llagentcamera.cpp
index 80085dad9d2609d53f12cfdc6c7226ca76dec9e3..c30d3b9aa3e5e92a2376176c2d3e48d8ef985342 100644
--- a/indra/newview/llagentcamera.cpp
+++ b/indra/newview/llagentcamera.cpp
@@ -392,11 +392,9 @@ LLVector3 LLAgentCamera::calcFocusOffset(LLViewerObject *object, LLVector3 origi
 	}
 	
 	LLQuaternion inv_obj_rot = ~obj_rot; // get inverse of rotation
-	LLVector3 object_extents;	
+	LLVector3 object_extents = object->getScale();	
 	const LLVector4a* oe4 = object->mDrawable->getSpatialExtents();
-	LLVector4a size;
-	size.setSub(oe4[1], oe4[0]);
-	object_extents.set( size[0], size[1], size[2] );
+	object_extents.set( oe4[1][0], oe4[1][1], oe4[1][2] );
 	
 	// make sure they object extents are non-zero
 	object_extents.clamp(0.001f, F32_MAX);
diff --git a/indra/newview/llassetuploadresponders.cpp b/indra/newview/llassetuploadresponders.cpp
index c08771c5e7d2352049fa4c56004e6432d182d272..d7ba4ea4706b89604fdbe19faa44acd5d8fb0d17 100644
--- a/indra/newview/llassetuploadresponders.cpp
+++ b/indra/newview/llassetuploadresponders.cpp
@@ -384,18 +384,18 @@ void LLNewAgentInventoryResponder::uploadComplete(const LLSD& content)
 		// Continuing the horrible hack above, we need to extract the originally requested permissions data, if any,
 		// and use them for each next file to be uploaded. Note the requested perms are not the same as the
 		U32 everyone_perms =
-			content.has("everyone_mask") ?
-			content["everyone_mask"].asInteger() :
+			content.has("new_everyone_mask") ?
+			content["new_everyone_mask"].asInteger() :
 			PERM_NONE;
 
 		U32 group_perms =
-			content.has("group_mask") ?
-			content["group_mask"].asInteger() :
+			content.has("new_group_mask") ?
+			content["new_group_mask"].asInteger() :
 			PERM_NONE;
 
 		U32 next_owner_perms =
-			content.has("next_owner_mask") ?
-			content["next_owner_mask"].asInteger() :
+			content.has("new_next_owner_mask") ?
+			content["new_next_owner_mask"].asInteger() :
 			PERM_NONE;
 
 		std::string display_name = LLStringUtil::null;
diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp
index bdc12ec0e3c384ca6003dde4477a62c00bf64ba1..ad3710843c60b4f8c821cad0dabc2ac73e84ffdd 100644
--- a/indra/newview/lldrawable.cpp
+++ b/indra/newview/lldrawable.cpp
@@ -94,7 +94,9 @@ void LLDrawable::init()
 	mRenderType = 0;
 	mCurrentScale = LLVector3(1,1,1);
 	mDistanceWRTCamera = 0.0f;
-
+	mPositionGroup.clear();
+	mExtents[0].clear();
+	mExtents[1].clear();
 	mQuietCount = 0;
 
 	mState     = 0;
@@ -587,7 +589,10 @@ void LLDrawable::setRadius(F32 radius)
 
 void LLDrawable::moveUpdatePipeline(BOOL moved)
 {
-	makeActive();
+	if (moved)
+	{
+		makeActive();
+	}
 	
 	// Update the face centers.
 	for (S32 i = 0; i < getNumFaces(); i++)
@@ -695,7 +700,8 @@ void LLDrawable::updateDistance(LLCamera& camera, bool force_update)
 {
 	if (LLViewerCamera::sCurCameraID != LLViewerCamera::CAMERA_WORLD)
 	{
-		llerrs << "WTF?" << llendl;
+		llwarns << "Attempted to update distance for non-world camera." << llendl;
+		return;
 	}
 
 	//switch LOD with the spatial group to avoid artifacts
diff --git a/indra/newview/lldrawable.h b/indra/newview/lldrawable.h
index 9ebe1a45b44a12654a9c1ca8afb66da7941d735f..e268640a21cdf806415bd68bea90e9f719da88df 100644
--- a/indra/newview/lldrawable.h
+++ b/indra/newview/lldrawable.h
@@ -276,6 +276,7 @@ class LLDrawable : public LLRefCount
 		REBUILD_SHADOW =  0x02000000,
 		HAS_ALPHA		= 0x04000000,
 		RIGGED			= 0x08000000,
+		PARTITION_MOVE	= 0x10000000,
 	} EDrawableFlags;
 
 private: //aligned members
diff --git a/indra/newview/lldrawpool.cpp b/indra/newview/lldrawpool.cpp
index 25e4bc847c253dcfd41423ef3575751c21c073c5..f5483d969d196ce1095d2c54da32a4a6e326ac9e 100644
--- a/indra/newview/lldrawpool.cpp
+++ b/indra/newview/lldrawpool.cpp
@@ -191,6 +191,16 @@ void LLDrawPool::renderPostDeferred(S32 pass)
 //virtual
 void LLDrawPool::endRenderPass( S32 pass )
 {
+	for (U32 i = 0; i < gGLManager.mNumTextureImageUnits; i++)
+	{ //dummy cleanup of any currently bound textures
+		if (gGL.getTexUnit(i)->getCurrType() != LLTexUnit::TT_NONE)
+		{
+			gGL.getTexUnit(i)->unbind(gGL.getTexUnit(i)->getCurrType());
+			gGL.getTexUnit(i)->disable();
+		}
+	}
+
+	gGL.getTexUnit(0)->activate();
 }
 
 //virtual 
@@ -430,14 +440,14 @@ void LLRenderPass::renderTexture(U32 type, U32 mask)
 	pushBatches(type, mask, TRUE);
 }
 
-void LLRenderPass::pushBatches(U32 type, U32 mask, BOOL texture)
+void LLRenderPass::pushBatches(U32 type, U32 mask, BOOL texture, BOOL batch_textures)
 {
 	for (LLCullResult::drawinfo_list_t::iterator i = gPipeline.beginRenderMap(type); i != gPipeline.endRenderMap(type); ++i)	
 	{
 		LLDrawInfo* pparams = *i;
 		if (pparams) 
 		{
-			pushBatch(*pparams, mask, texture);
+			pushBatch(*pparams, mask, texture, batch_textures);
 		}
 	}
 }
@@ -456,26 +466,43 @@ void LLRenderPass::applyModelMatrix(LLDrawInfo& params)
 	}
 }
 
-void LLRenderPass::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture)
+void LLRenderPass::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL batch_textures)
 {
 	applyModelMatrix(params);
 
+	bool tex_setup = false;
+
 	if (texture)
 	{
-		if (params.mTexture.notNull())
+		if (batch_textures && params.mTextureList.size() > 1)
 		{
-			params.mTexture->addTextureStats(params.mVSize);
-			gGL.getTexUnit(0)->bind(params.mTexture, TRUE) ;
-			if (params.mTextureMatrix)
+			for (U32 i = 0; i < params.mTextureList.size(); ++i)
 			{
-				glMatrixMode(GL_TEXTURE);
-				glLoadMatrixf((GLfloat*) params.mTextureMatrix->mMatrix);
-				gPipeline.mTextureMatrixOps++;
+				if (params.mTextureList[i].notNull())
+				{
+					gGL.getTexUnit(i)->bind(params.mTextureList[i], TRUE);
+				}
 			}
 		}
 		else
-		{
-			gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+		{ //not batching textures or batch has only 1 texture -- might need a texture matrix
+			if (params.mTexture.notNull())
+			{
+				params.mTexture->addTextureStats(params.mVSize);
+				gGL.getTexUnit(0)->bind(params.mTexture, TRUE) ;
+				if (params.mTextureMatrix)
+				{
+					tex_setup = true;
+					gGL.getTexUnit(0)->activate();
+					glMatrixMode(GL_TEXTURE);
+					glLoadMatrixf((GLfloat*) params.mTextureMatrix->mMatrix);
+					gPipeline.mTextureMatrixOps++;
+				}
+			}
+			else
+			{
+				gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+			}
 		}
 	}
 	
@@ -490,7 +517,7 @@ void LLRenderPass::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture)
 		gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode);
 	}
 
-	if (params.mTextureMatrix && texture && params.mTexture.notNull())
+	if (tex_setup)
 	{
 		glLoadIdentity();
 		glMatrixMode(GL_MODELVIEW);
diff --git a/indra/newview/lldrawpool.h b/indra/newview/lldrawpool.h
index d3fd9ead0d4ef42a88f3a0d0230ffc03d8586b2b..c7acbb42c62da2c8aa5a471e7c8f5a5aaddfd536 100644
--- a/indra/newview/lldrawpool.h
+++ b/indra/newview/lldrawpool.h
@@ -146,8 +146,8 @@ class LLRenderPass : public LLDrawPool
 	void resetDrawOrders() { }
 
 	static void applyModelMatrix(LLDrawInfo& params);
-	virtual void pushBatches(U32 type, U32 mask, BOOL texture = TRUE);
-	virtual void pushBatch(LLDrawInfo& params, U32 mask, BOOL texture);
+	virtual void pushBatches(U32 type, U32 mask, BOOL texture = TRUE, BOOL batch_textures = FALSE);
+	virtual void pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL batch_textures = FALSE);
 	virtual void renderGroup(LLSpatialGroup* group, U32 type, U32 mask, BOOL texture = TRUE);
 	virtual void renderGroups(U32 type, U32 mask, BOOL texture = TRUE);
 	virtual void renderTexture(U32 type, U32 mask);
diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp
index 8b5a2ce78182d6e4147c73cb09430aaae7453f88..8d46133912e61fd7b0840ef7822041cc46f4375a 100644
--- a/indra/newview/lldrawpoolalpha.cpp
+++ b/indra/newview/lldrawpoolalpha.cpp
@@ -124,7 +124,10 @@ void LLDrawPoolAlpha::beginPostDeferredPass(S32 pass)
 	if (pass == 0)
 	{
 		simple_shader = &gDeferredAlphaProgram;
-		fullbright_shader = &gDeferredFullbrightProgram;
+		fullbright_shader = &gObjectFullbrightProgram;
+
+		//prime simple shader (loads shadow relevant uniforms)
+		gPipeline.bindDeferredShader(*simple_shader);
 	}
 	else
 	{
@@ -228,13 +231,13 @@ void LLDrawPoolAlpha::render(S32 pass)
 			if (!LLPipeline::sRenderDeferred)
 			{
 				simple_shader->bind();
-				pushBatches(LLRenderPass::PASS_ALPHA_MASK, getVertexDataMask());
+				pushBatches(LLRenderPass::PASS_ALPHA_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
 			}
 			if (fullbright_shader)
 			{
 				fullbright_shader->bind();
 			}
-			pushBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, getVertexDataMask());
+			pushBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
 			LLGLSLShader::bindNoShader();
 		}
 		else
@@ -273,7 +276,14 @@ void LLDrawPoolAlpha::render(S32 pass)
 		}
 	}
 
-	renderAlpha(getVertexDataMask());
+	if (mVertexShaderLevel > 0)
+	{
+		renderAlpha(getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX);
+	}
+	else
+	{
+		renderAlpha(getVertexDataMask());
+	}
 
 	gGL.setColorMask(true, false);
 
@@ -283,11 +293,6 @@ void LLDrawPoolAlpha::render(S32 pass)
 		gGL.setSceneBlendType(LLRender::BT_ALPHA);
 	}
 
-	if (deferred_render && current_shader != NULL)
-	{
-		gPipeline.unbindDeferredShader(*current_shader);
-	}
-
 	if (sShowDebugAlpha)
 	{
 		if(gPipeline.canUseWindLightShaders()) 
@@ -339,12 +344,9 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask)
 {
 	BOOL initialized_lighting = FALSE;
 	BOOL light_enabled = TRUE;
-	S32 diffuse_channel = 0;
-
-	BOOL use_shaders = (LLPipeline::sUnderWaterRender && gPipeline.canUseVertexShaders())
-		|| gPipeline.canUseWindLightShadersOnObjects();
-	
 	
+	BOOL use_shaders = gPipeline.canUseVertexShaders();
+		
 	for (LLCullResult::sg_list_t::iterator i = gPipeline.beginAlphaGroups(); i != gPipeline.endAlphaGroups(); ++i)
 	{
 		LLSpatialGroup* group = *i;
@@ -368,92 +370,89 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask)
 
 				LLRenderPass::applyModelMatrix(params);
 
+				
+				if (params.mFullbright)
 				{
-					if (params.mFullbright)
-					{
-						// Turn off lighting if it hasn't already been so.
-						if (light_enabled || !initialized_lighting)
-						{
-							initialized_lighting = TRUE;
-							if (use_shaders) 
-							{
-								target_shader = fullbright_shader;
-							}
-							else
-							{
-								gPipeline.enableLightsFullbright(LLColor4(1,1,1,1));
-							}
-							light_enabled = FALSE;
-						}
-					}
-					// Turn on lighting if it isn't already.
-					else if (!light_enabled || !initialized_lighting)
+					// Turn off lighting if it hasn't already been so.
+					if (light_enabled || !initialized_lighting)
 					{
 						initialized_lighting = TRUE;
 						if (use_shaders) 
 						{
-							target_shader = simple_shader;
+							target_shader = fullbright_shader;
 						}
 						else
 						{
-							gPipeline.enableLightsDynamic();
+							gPipeline.enableLightsFullbright(LLColor4(1,1,1,1));
 						}
-						light_enabled = TRUE;
+						light_enabled = FALSE;
 					}
-
-					// If we need shaders, and we're not ALREADY using the proper shader, then bind it
-					// (this way we won't rebind shaders unnecessarily).
-					if(use_shaders && (current_shader != target_shader))
+				}
+				// Turn on lighting if it isn't already.
+				else if (!light_enabled || !initialized_lighting)
+				{
+					initialized_lighting = TRUE;
+					if (use_shaders) 
 					{
-						llassert(target_shader != NULL);
-						if (deferred_render && current_shader != NULL)
-						{
-							gPipeline.unbindDeferredShader(*current_shader);
-							diffuse_channel = 0;
-						}
-						current_shader = target_shader;
-						if (deferred_render)
-						{
-							gPipeline.bindDeferredShader(*current_shader);
-							diffuse_channel = current_shader->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
-						}
-						else
-						{
-							current_shader->bind();
-						}
+						target_shader = simple_shader;
 					}
-					else if (!use_shaders && current_shader != NULL)
+					else
 					{
-						if (deferred_render)
-						{
-							gPipeline.unbindDeferredShader(*current_shader);
-							diffuse_channel = 0;
-						}
-						LLGLSLShader::bindNoShader();
-						current_shader = NULL;
+						gPipeline.enableLightsDynamic();
 					}
+					light_enabled = TRUE;
+				}
 
-					if (params.mGroup)
-					{
-						params.mGroup->rebuildMesh();
-					}
+				// If we need shaders, and we're not ALREADY using the proper shader, then bind it
+				// (this way we won't rebind shaders unnecessarily).
+				if(use_shaders && (current_shader != target_shader))
+				{
+					llassert(target_shader != NULL);
+					current_shader = target_shader;
+					current_shader->bind();
+				}
+				else if (!use_shaders && current_shader != NULL)
+				{
+					LLGLSLShader::bindNoShader();
+					current_shader = NULL;
+				}
 
-					
-					if (params.mTexture.notNull())
+				if (params.mGroup)
+				{
+					params.mGroup->rebuildMesh();
+				}
+
+				bool tex_setup = false;
+
+				if (use_shaders && params.mTextureList.size() > 1)
+				{
+					for (U32 i = 0; i < params.mTextureList.size(); ++i)
 					{
-						gGL.getTexUnit(diffuse_channel)->bind(params.mTexture.get());
-						if(params.mTexture.notNull())
+						if (params.mTextureList[i].notNull())
 						{
-							params.mTexture->addTextureStats(params.mVSize);
+							gGL.getTexUnit(i)->bind(params.mTextureList[i], TRUE);
 						}
+					}
+				}
+				else
+				{ //not batching textures or batch has only 1 texture -- might need a texture matrix
+					if (params.mTexture.notNull())
+					{
+						params.mTexture->addTextureStats(params.mVSize);
+						gGL.getTexUnit(0)->bind(params.mTexture, TRUE) ;
 						if (params.mTextureMatrix)
 						{
+							tex_setup = true;
 							gGL.getTexUnit(0)->activate();
 							glMatrixMode(GL_TEXTURE);
 							glLoadMatrixf((GLfloat*) params.mTextureMatrix->mMatrix);
 							gPipeline.mTextureMatrixOps++;
 						}
 					}
+					else
+					{
+						gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+					}
 				}
 
 				params.mVertexBuffer->setBuffer(mask);
@@ -480,7 +479,7 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask)
 					gGL.blendFunc(mColorSFactor, mColorDFactor, mAlphaSFactor, mAlphaDFactor);
 				}
 			
-				if (params.mTextureMatrix && params.mTexture.notNull())
+				if (tex_setup)
 				{
 					gGL.getTexUnit(0)->activate();
 					glLoadIdentity();
@@ -490,15 +489,8 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask)
 		}
 	}
 
-	if (deferred_render && current_shader != NULL)
-	{
-		gPipeline.unbindDeferredShader(*current_shader);
-		LLVertexBuffer::unbind();	
-		LLGLState::checkStates();
-		LLGLState::checkTextureChannels();
-		LLGLState::checkClientArrays();
-	}
-	
+	LLVertexBuffer::unbind();	
+		
 	if (!light_enabled)
 	{
 		gPipeline.enableLightsDynamic();
diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp
index 645c7ebcaeb933d586074da457beb80c55518d3d..9f790d03fe05a3d47ac1728b428a2ba457b7c9cc 100644
--- a/indra/newview/lldrawpoolavatar.cpp
+++ b/indra/newview/lldrawpoolavatar.cpp
@@ -459,14 +459,6 @@ S32 LLDrawPoolAvatar::getNumPasses()
 	{
 		return 10;
 	}
-	if (LLPipeline::sImpostorRender)
-	{
-		return 1;
-	}
-	else 
-	{
-		return 3;
-	}
 }
 
 
@@ -613,11 +605,11 @@ void LLDrawPoolAvatar::beginRigid()
 	{
 		if (LLPipeline::sUnderWaterRender)
 		{
-			sVertexProgram = &gObjectSimpleWaterProgram;
+			sVertexProgram = &gObjectSimpleNonIndexedWaterProgram;
 		}
 		else
 		{
-			sVertexProgram = &gObjectSimpleProgram;
+			sVertexProgram = &gObjectSimpleNonIndexedProgram;
 		}
 		
 		if (sVertexProgram != NULL)
@@ -669,7 +661,7 @@ void LLDrawPoolAvatar::endDeferredImpostor()
 
 void LLDrawPoolAvatar::beginDeferredRigid()
 {
-	sVertexProgram = &gDeferredDiffuseProgram;
+	sVertexProgram = &gDeferredNonIndexedDiffuseProgram;
 				
 	sVertexProgram->bind();
 }
@@ -700,11 +692,11 @@ void LLDrawPoolAvatar::beginSkinned()
 	{
 		if (LLPipeline::sUnderWaterRender)
 		{
-			sVertexProgram = &gObjectSimpleWaterProgram;
+			sVertexProgram = &gObjectSimpleNonIndexedWaterProgram;
 		}
 		else
 		{
-			sVertexProgram = &gObjectSimpleProgram;
+			sVertexProgram = &gObjectSimpleNonIndexedProgram;
 		}
 	}
 	
@@ -789,11 +781,11 @@ void LLDrawPoolAvatar::beginRiggedSimple()
 	{
 		if (LLPipeline::sUnderWaterRender)
 		{
-			sVertexProgram = &gObjectSimpleWaterProgram;
+			sVertexProgram = &gObjectSimpleNonIndexedWaterProgram;
 		}
 		else
 		{
-			sVertexProgram = &gObjectSimpleProgram;
+			sVertexProgram = &gObjectSimpleNonIndexedProgram;
 		}
 	}
 
@@ -864,11 +856,11 @@ void LLDrawPoolAvatar::beginRiggedFullbright()
 	{
 		if (LLPipeline::sUnderWaterRender)
 		{
-			sVertexProgram = &gObjectFullbrightWaterProgram;
+			sVertexProgram = &gObjectFullbrightNonIndexedWaterProgram;
 		}
 		else
 		{
-			sVertexProgram = &gObjectFullbrightProgram;
+			sVertexProgram = &gObjectFullbrightNonIndexedProgram;
 		}
 	}
 
@@ -908,11 +900,11 @@ void LLDrawPoolAvatar::beginRiggedShinySimple()
 	{
 		if (LLPipeline::sUnderWaterRender)
 		{
-			sVertexProgram = &gObjectShinyWaterProgram;
+			sVertexProgram = &gObjectShinyNonIndexedWaterProgram;
 		}
 		else
 		{
-			sVertexProgram = &gObjectShinyProgram;
+			sVertexProgram = &gObjectShinyNonIndexedProgram;
 		}
 	}
 
@@ -953,11 +945,11 @@ void LLDrawPoolAvatar::beginRiggedFullbrightShiny()
 	{
 		if (LLPipeline::sUnderWaterRender)
 		{
-			sVertexProgram = &gObjectFullbrightShinyWaterProgram;
+			sVertexProgram = &gObjectFullbrightShinyNonIndexedWaterProgram;
 		}
 		else
 		{
-			sVertexProgram = &gObjectFullbrightShinyProgram;
+			sVertexProgram = &gObjectFullbrightShinyNonIndexedProgram;
 		}
 	}
 
@@ -1419,7 +1411,7 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace*
 
 void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow)
 {
-	if (avatar->isSelf() && !gAgent.needsRenderAvatar())
+	if (avatar->isSelf() && !gAgent.needsRenderAvatar() || !gMeshRepo.meshRezEnabled())
 	{
 		return;
 	}
@@ -1456,7 +1448,7 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow)
 			continue;
 		}
 
-		const LLMeshSkinInfo* skin = gMeshRepo.getSkinInfo(mesh_id);
+		const LLMeshSkinInfo* skin = gMeshRepo.getSkinInfo(mesh_id, vobj);
 		if (!skin)
 		{
 			continue;
diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp
index 2f76baaaf7eb7f3d6b61aab63db61752df14a62f..813b3820ee8948c05e566754853c8531af581281 100644
--- a/indra/newview/lldrawpoolbump.cpp
+++ b/indra/newview/lldrawpoolbump.cpp
@@ -316,6 +316,9 @@ void LLDrawPoolBump::endRenderPass(S32 pass)
 			llassert(0);
 			break;
 	}
+
+	//to cleanup texture channels
+	LLRenderPass::endRenderPass(pass);
 }
 
 //static
@@ -354,6 +357,11 @@ void LLDrawPoolBump::beginShiny(bool invisible)
 	}
 
 	bindCubeMap(shader, mVertexShaderLevel, diffuse_channel, cube_channel, invisible);
+
+	if (mVertexShaderLevel > 1)
+	{ //indexed texture rendering, channel 0 is always diffuse
+		diffuse_channel = 0;
+	}
 }
 
 //static
@@ -421,16 +429,16 @@ void LLDrawPoolBump::renderShiny(bool invisible)
 		LLGLEnable blend_enable(GL_BLEND);
 		if (!invisible && mVertexShaderLevel > 1)
 		{
-			LLRenderPass::renderTexture(LLRenderPass::PASS_SHINY, sVertexMask);
+			LLRenderPass::pushBatches(LLRenderPass::PASS_SHINY, sVertexMask | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
 		}
 		else if (!invisible)
 		{
 			renderGroups(LLRenderPass::PASS_SHINY, sVertexMask);
 		}
-		else // invisible
-		{
-			renderGroups(LLRenderPass::PASS_INVISI_SHINY, sVertexMask);
-		}
+		//else // invisible (deprecated)
+		//{
+			//renderGroups(LLRenderPass::PASS_INVISI_SHINY, sVertexMask);
+		//}
 	}
 }
 
@@ -529,6 +537,12 @@ void LLDrawPoolBump::beginFullbrightShiny()
 		gGL.getTexUnit(cube_channel)->bind(cube_map);
 		gGL.getTexUnit(0)->activate();
 	}
+
+	if (mVertexShaderLevel > 1)
+	{ //indexed texture rendering, channel 0 is always diffuse
+		diffuse_channel = 0;
+	}
+
 	mShiny = TRUE;
 }
 
@@ -543,7 +557,15 @@ void LLDrawPoolBump::renderFullbrightShiny()
 	if( gSky.mVOSkyp->getCubeMap() )
 	{
 		LLGLEnable blend_enable(GL_BLEND);
-		LLRenderPass::renderTexture(LLRenderPass::PASS_FULLBRIGHT_SHINY, sVertexMask);
+
+		if (mVertexShaderLevel > 1)
+		{
+			LLRenderPass::pushBatches(LLRenderPass::PASS_FULLBRIGHT_SHINY, sVertexMask | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
+		}
+		else
+		{
+			LLRenderPass::renderTexture(LLRenderPass::PASS_FULLBRIGHT_SHINY, sVertexMask);
+		}
 	}
 }
 
@@ -843,6 +865,9 @@ void LLDrawPoolBump::endPostDeferredPass(S32 pass)
 		endBump(LLRenderPass::PASS_POST_BUMP);
 		break;
 	}
+
+	//to disable texture channels
+	LLRenderPass::endRenderPass(pass);
 }
 
 void LLDrawPoolBump::renderPostDeferred(S32 pass)
@@ -1300,43 +1325,60 @@ void LLDrawPoolBump::renderBump(U32 type, U32 mask)
 	}
 }
 
-void LLDrawPoolBump::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture)
+void LLDrawPoolBump::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL batch_textures)
 {
 	applyModelMatrix(params);
 
-	if (params.mTextureMatrix)
+	bool tex_setup = false;
+
+	if (batch_textures && params.mTextureList.size() > 1)
 	{
-		if (mShiny)
+		for (U32 i = 0; i < params.mTextureList.size(); ++i)
 		{
-			gGL.getTexUnit(0)->activate();
-			glMatrixMode(GL_TEXTURE);
+			if (params.mTextureList[i].notNull())
+			{
+				gGL.getTexUnit(i)->bind(params.mTextureList[i], TRUE);
+			}
 		}
-		else
+	}
+	else
+	{ //not batching textures or batch has only 1 texture -- might need a texture matrix
+		if (params.mTextureMatrix)
 		{
-			gGL.getTexUnit(1)->activate();
-			glMatrixMode(GL_TEXTURE);
+			if (mShiny)
+			{
+				gGL.getTexUnit(0)->activate();
+				glMatrixMode(GL_TEXTURE);
+			}
+			else
+			{
+				gGL.getTexUnit(1)->activate();
+				glMatrixMode(GL_TEXTURE);
+				glLoadMatrixf((GLfloat*) params.mTextureMatrix->mMatrix);
+				gPipeline.mTextureMatrixOps++;
+				gGL.getTexUnit(0)->activate();
+			}
+
 			glLoadMatrixf((GLfloat*) params.mTextureMatrix->mMatrix);
 			gPipeline.mTextureMatrixOps++;
-			gGL.getTexUnit(0)->activate();
-		}
-
-		glLoadMatrixf((GLfloat*) params.mTextureMatrix->mMatrix);
-		gPipeline.mTextureMatrixOps++;
-	}
 
-	if (mShiny && mVertexShaderLevel > 1 && texture)
-	{
-		if (params.mTexture.notNull())
-		{
-			gGL.getTexUnit(diffuse_channel)->bind(params.mTexture) ;
-			params.mTexture->addTextureStats(params.mVSize);		
+			tex_setup = true;
 		}
-		else
+
+		if (mShiny && mVertexShaderLevel > 1 && texture)
 		{
-			gGL.getTexUnit(diffuse_channel)->unbind(LLTexUnit::TT_TEXTURE);
+			if (params.mTexture.notNull())
+			{
+				gGL.getTexUnit(diffuse_channel)->bind(params.mTexture) ;
+				params.mTexture->addTextureStats(params.mVSize);		
+			}
+			else
+			{
+				gGL.getTexUnit(diffuse_channel)->unbind(LLTexUnit::TT_TEXTURE);
+			}
 		}
 	}
-	
+
 	if (params.mGroup)
 	{
 		params.mGroup->rebuildMesh();
@@ -1344,7 +1386,7 @@ void LLDrawPoolBump::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture)
 	params.mVertexBuffer->setBuffer(mask);
 	params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset);
 	gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode);
-	if (params.mTextureMatrix)
+	if (tex_setup)
 	{
 		if (mShiny)
 		{
diff --git a/indra/newview/lldrawpoolbump.h b/indra/newview/lldrawpoolbump.h
index f4702bf61d4ed3ed8d8a2c6545cc36f0fcdaf64a..476b1d41b7d40d85ac08d6fb353cabe18d4773b3 100644
--- a/indra/newview/lldrawpoolbump.h
+++ b/indra/newview/lldrawpoolbump.h
@@ -55,7 +55,7 @@ protected :
 	virtual void endRenderPass( S32 pass );
 	virtual S32	 getNumPasses();
 	/*virtual*/ void prerender();
-	/*virtual*/ void pushBatch(LLDrawInfo& params, U32 mask, BOOL texture);
+	/*virtual*/ void pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL batch_textures = FALSE);
 
 	void renderBump(U32 type, U32 mask);
 	void renderGroup(LLSpatialGroup* group, U32 type, U32 mask, BOOL texture);
diff --git a/indra/newview/lldrawpoolsimple.cpp b/indra/newview/lldrawpoolsimple.cpp
index 2e83167851d7abd61941c00da7889d5a386dc7c7..5dbb27cabb84e174b0dcb0b9a7f4c82daa266ec6 100644
--- a/indra/newview/lldrawpoolsimple.cpp
+++ b/indra/newview/lldrawpoolsimple.cpp
@@ -44,6 +44,36 @@ static LLGLSLShader* fullbright_shader = NULL;
 static LLFastTimer::DeclareTimer FTM_RENDER_SIMPLE_DEFERRED("Deferred Simple");
 static LLFastTimer::DeclareTimer FTM_RENDER_GRASS_DEFERRED("Deferred Grass");
 
+void LLDrawPoolGlow::beginPostDeferredPass(S32 pass)
+{
+	gDeferredFullbrightProgram.bind();
+}
+
+void LLDrawPoolGlow::renderPostDeferred(S32 pass)
+{
+	LLFastTimer t(FTM_RENDER_GLOW);
+	LLGLEnable blend(GL_BLEND);
+	LLGLDisable test(GL_ALPHA_TEST);
+	gGL.flush();
+	/// Get rid of z-fighting with non-glow pass.
+	LLGLEnable polyOffset(GL_POLYGON_OFFSET_FILL);
+	glPolygonOffset(-1.0f, -1.0f);
+	gGL.setSceneBlendType(LLRender::BT_ADD);
+	
+	LLGLDepthTest depth(GL_TRUE, GL_FALSE);
+	gGL.setColorMask(false, true);
+	pushBatches(LLRenderPass::PASS_GLOW, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
+	
+	gGL.setColorMask(true, false);
+	gGL.setSceneBlendType(LLRender::BT_ALPHA);	
+}
+
+void LLDrawPoolGlow::endPostDeferredPass(S32 pass)
+{
+	gDeferredFullbrightProgram.unbind();
+	LLRenderPass::endRenderPass(pass);
+}
+
 void LLDrawPoolGlow::render(S32 pass)
 {
 	LLFastTimer t(FTM_RENDER_GLOW);
@@ -68,7 +98,15 @@ void LLDrawPoolGlow::render(S32 pass)
 
 	LLGLDepthTest depth(GL_TRUE, GL_FALSE);
 	gGL.setColorMask(false, true);
-	renderTexture(LLRenderPass::PASS_GLOW, getVertexDataMask());
+
+	if (shader_level > 1)
+	{
+		pushBatches(LLRenderPass::PASS_GLOW, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
+	}
+	else
+	{
+		renderTexture(LLRenderPass::PASS_GLOW, getVertexDataMask());
+	}
 	
 	gGL.setColorMask(true, false);
 	gGL.setSceneBlendType(LLRender::BT_ALPHA);
@@ -79,10 +117,10 @@ void LLDrawPoolGlow::render(S32 pass)
 	}
 }
 
-void LLDrawPoolGlow::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture)
+void LLDrawPoolGlow::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL batch_textures)
 {
 	glColor4ubv(params.mGlowColor.mV);
-	LLRenderPass::pushBatch(params, mask, texture);
+	LLRenderPass::pushBatch(params, mask, texture, batch_textures);
 }
 
 
@@ -126,10 +164,11 @@ void LLDrawPoolSimple::beginRenderPass(S32 pass)
 void LLDrawPoolSimple::endRenderPass(S32 pass)
 {
 	LLFastTimer t(FTM_RENDER_SIMPLE);
+	stop_glerror();
 	LLRenderPass::endRenderPass(pass);
-
-	if (mVertexShaderLevel > 0){
-
+	stop_glerror();
+	if (mVertexShaderLevel > 0)
+	{
 		simple_shader->unbind();
 	}
 }
@@ -142,13 +181,24 @@ void LLDrawPoolSimple::render(S32 pass)
 	{ //render simple
 		LLFastTimer t(FTM_RENDER_SIMPLE);
 		gPipeline.enableLightsDynamic();
-		renderTexture(LLRenderPass::PASS_SIMPLE, getVertexDataMask());
 
-		if (LLPipeline::sRenderDeferred)
-		{ //if deferred rendering is enabled, bump faces aren't registered as simple
-			//render bump faces here as simple so bump faces will appear under water
-			renderTexture(LLRenderPass::PASS_BUMP, getVertexDataMask());
+		if (mVertexShaderLevel > 0)
+		{
+			U32 mask = getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX;
+
+			pushBatches(LLRenderPass::PASS_SIMPLE, mask, TRUE, TRUE);
+
+			if (LLPipeline::sRenderDeferred)
+			{ //if deferred rendering is enabled, bump faces aren't registered as simple
+				//render bump faces here as simple so bump faces will appear under water
+				pushBatches(LLRenderPass::PASS_BUMP, mask, TRUE, TRUE);
+			}
+		}
+		else
+		{
+			renderTexture(LLRenderPass::PASS_SIMPLE, getVertexDataMask());
 		}
+		
 	}
 }
 
@@ -177,7 +227,7 @@ void LLDrawPoolSimple::renderDeferred(S32 pass)
 
 	{ //render simple
 		LLFastTimer t(FTM_RENDER_SIMPLE_DEFERRED);
-		renderTexture(LLRenderPass::PASS_SIMPLE, getVertexDataMask());
+		pushBatches(LLRenderPass::PASS_SIMPLE, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
 	}
 }
 
@@ -200,11 +250,11 @@ void LLDrawPoolGrass::beginRenderPass(S32 pass)
 
 	if (LLPipeline::sUnderWaterRender)
 	{
-		simple_shader = &gObjectSimpleWaterProgram;
+		simple_shader = &gObjectSimpleNonIndexedWaterProgram;
 	}
 	else
 	{
-		simple_shader = &gObjectSimpleProgram;
+		simple_shader = &gObjectSimpleNonIndexedProgram;
 	}
 
 	if (mVertexShaderLevel > 0)
@@ -285,6 +335,26 @@ void LLDrawPoolFullbright::prerender()
 	mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT);
 }
 
+void LLDrawPoolFullbright::beginPostDeferredPass(S32 pass)
+{
+	gDeferredFullbrightProgram.bind();
+}
+
+void LLDrawPoolFullbright::renderPostDeferred(S32 pass)
+{
+	LLFastTimer t(FTM_RENDER_FULLBRIGHT);
+	
+	gGL.setSceneBlendType(LLRender::BT_ALPHA);
+	U32 fullbright_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_TEXTURE_INDEX;
+	pushBatches(LLRenderPass::PASS_FULLBRIGHT, fullbright_mask, TRUE, TRUE);
+}
+
+void LLDrawPoolFullbright::endPostDeferredPass(S32 pass)
+{
+	gDeferredFullbrightProgram.unbind();
+	LLRenderPass::endRenderPass(pass);
+}
+
 void LLDrawPoolFullbright::beginRenderPass(S32 pass)
 {
 	LLFastTimer t(FTM_RENDER_FULLBRIGHT);
@@ -313,25 +383,21 @@ void LLDrawPoolFullbright::endRenderPass(S32 pass)
 void LLDrawPoolFullbright::render(S32 pass)
 { //render fullbright
 	LLFastTimer t(FTM_RENDER_FULLBRIGHT);
+	gGL.setSceneBlendType(LLRender::BT_ALPHA);
+
 	if (mVertexShaderLevel > 0)
 	{
 		fullbright_shader->bind();
 		fullbright_shader->uniform1f(LLViewerShaderMgr::FULLBRIGHT, 1.f);
+		U32 fullbright_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_TEXTURE_INDEX;
+		pushBatches(LLRenderPass::PASS_FULLBRIGHT, fullbright_mask, TRUE, TRUE);
 	}
 	else
 	{
 		gPipeline.enableLightsFullbright(LLColor4(1,1,1,1));
+		U32 fullbright_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR;
+		renderTexture(LLRenderPass::PASS_FULLBRIGHT, fullbright_mask);
 	}
-	
-	//gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.25f);
-	
-	//LLGLEnable test(GL_ALPHA_TEST);
-	//LLGLEnable blend(GL_BLEND);
-	gGL.setSceneBlendType(LLRender::BT_ALPHA);
-	U32 fullbright_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR;
-	renderTexture(LLRenderPass::PASS_FULLBRIGHT, fullbright_mask);
-
-	//gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT);
 }
 
 S32 LLDrawPoolFullbright::getNumPasses()
diff --git a/indra/newview/lldrawpoolsimple.h b/indra/newview/lldrawpoolsimple.h
index 5f3bbebbdad5e6df941150e3f387c61ddfc72880..3811b3d398f872193cb6861e63c053f6f926e263 100644
--- a/indra/newview/lldrawpoolsimple.h
+++ b/indra/newview/lldrawpoolsimple.h
@@ -98,9 +98,9 @@ class LLDrawPoolFullbright : public LLRenderPass
 	LLDrawPoolFullbright();
 	
 	/*virtual*/ S32 getNumPostDeferredPasses() { return 1; }
-	/*virtual*/ void beginPostDeferredPass(S32 pass) { beginRenderPass(pass); }
-	/*virtual*/ void endPostDeferredPass(S32 pass) { endRenderPass(pass); }
-	/*virtual*/ void renderPostDeferred(S32 pass) { render(pass); }
+	/*virtual*/ void beginPostDeferredPass(S32 pass);
+	/*virtual*/ void endPostDeferredPass(S32 pass);
+	/*virtual*/ void renderPostDeferred(S32 pass);
 
 	/*virtual*/ void beginRenderPass(S32 pass);
 	/*virtual*/ void endRenderPass(S32 pass);
@@ -126,12 +126,12 @@ class LLDrawPoolGlow : public LLRenderPass
 	virtual void prerender() { }
 
 	/*virtual*/ S32 getNumPostDeferredPasses() { return 1; }
-	/*virtual*/ void beginPostDeferredPass(S32 pass) { beginRenderPass(pass); }
-	/*virtual*/ void endPostDeferredPass(S32 pass) { endRenderPass(pass); }
-	/*virtual*/ void renderPostDeferred(S32 pass) { render(pass); }
+	/*virtual*/ void beginPostDeferredPass(S32 pass); 
+	/*virtual*/ void endPostDeferredPass(S32 pass);
+	/*virtual*/ void renderPostDeferred(S32 pass);
 
 	void render(S32 pass = 0);
-	void pushBatch(LLDrawInfo& params, U32 mask, BOOL texture = TRUE);
+	void pushBatch(LLDrawInfo& params, U32 mask, BOOL texture = TRUE, BOOL batch_textures = FALSE);
 
 };
 
diff --git a/indra/newview/lldrawpooltree.cpp b/indra/newview/lldrawpooltree.cpp
index 195ee60a2ef164019287c4ccc860d209e0f3a9a7..81c796b14630f19aea34b1fcdaac174baf95688b 100644
--- a/indra/newview/lldrawpooltree.cpp
+++ b/indra/newview/lldrawpooltree.cpp
@@ -66,11 +66,11 @@ void LLDrawPoolTree::beginRenderPass(S32 pass)
 	
 	if (LLPipeline::sUnderWaterRender)
 	{
-		shader = &gObjectSimpleWaterProgram;
+		shader = &gObjectSimpleNonIndexedWaterProgram;
 	}
 	else
 	{
-		shader = &gObjectSimpleProgram;
+		shader = &gObjectSimpleNonIndexedProgram;
 	}
 
 	if (gPipeline.canUseWindLightShadersOnObjects())
diff --git a/indra/newview/lldrawpoolwlsky.cpp b/indra/newview/lldrawpoolwlsky.cpp
index 696c2d1abdcf3533f291c2193fdbaa4921d222b6..409b18d5229cb6c2c0cccd8620ce9dad9873f938 100644
--- a/indra/newview/lldrawpoolwlsky.cpp
+++ b/indra/newview/lldrawpoolwlsky.cpp
@@ -44,6 +44,8 @@ LLPointer<LLViewerTexture> LLDrawPoolWLSky::sCloudNoiseTexture = NULL;
 
 LLPointer<LLImageRaw> LLDrawPoolWLSky::sCloudNoiseRawImage = NULL;
 
+static LLGLSLShader* cloud_shader = NULL;
+static LLGLSLShader* sky_shader = NULL;
 
 
 LLDrawPoolWLSky::LLDrawPoolWLSky(void) :
@@ -83,12 +85,32 @@ LLViewerTexture *LLDrawPoolWLSky::getDebugTexture()
 
 void LLDrawPoolWLSky::beginRenderPass( S32 pass )
 {
+	sky_shader =
+		LLPipeline::sUnderWaterRender ?
+			&gObjectSimpleWaterProgram :
+			&gWLSkyProgram;
+
+	cloud_shader =
+			LLPipeline::sUnderWaterRender ?
+				&gObjectSimpleWaterProgram :
+				&gWLCloudProgram;
 }
 
 void LLDrawPoolWLSky::endRenderPass( S32 pass )
 {
 }
 
+void LLDrawPoolWLSky::beginDeferredPass(S32 pass)
+{
+	sky_shader = &gDeferredWLSkyProgram;
+	cloud_shader = &gDeferredWLCloudProgram;
+}
+
+void LLDrawPoolWLSky::endDeferredPass(S32 pass)
+{
+
+}
+
 void LLDrawPoolWLSky::renderDome(F32 camHeightLocal, LLGLSLShader * shader) const
 {
 	LLVector3 const & origin = LLViewerCamera::getInstance()->getOrigin();
@@ -128,19 +150,14 @@ void LLDrawPoolWLSky::renderSkyHaze(F32 camHeightLocal) const
 {
 	if (gPipeline.canUseWindLightShaders() && gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_SKY))
 	{
-		LLGLSLShader* shader =
-			LLPipeline::sUnderWaterRender ?
-				&gObjectSimpleWaterProgram :
-				&gWLSkyProgram;
-
 		LLGLDisable blend(GL_BLEND);
 
-		shader->bind();
+		sky_shader->bind();
 
 		/// Render the skydome
-		renderDome(camHeightLocal, shader);	
+		renderDome(camHeightLocal, sky_shader);	
 
-		shader->unbind();
+		sky_shader->unbind();
 	}
 }
 
@@ -186,23 +203,18 @@ void LLDrawPoolWLSky::renderSkyClouds(F32 camHeightLocal) const
 {
 	if (gPipeline.canUseWindLightShaders() && gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_CLOUDS))
 	{
-		LLGLSLShader* shader =
-			LLPipeline::sUnderWaterRender ?
-				&gObjectSimpleWaterProgram :
-				&gWLCloudProgram;
-
 		LLGLEnable blend(GL_BLEND);
 		gGL.setSceneBlendType(LLRender::BT_ALPHA);
 		gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT);
 
 		gGL.getTexUnit(0)->bind(sCloudNoiseTexture);
 
-		shader->bind();
+		cloud_shader->bind();
 
 		/// Render the skydome
-		renderDome(camHeightLocal, shader);
+		renderDome(camHeightLocal, cloud_shader);
 
-		shader->unbind();
+		cloud_shader->unbind();
 	}
 }
 
@@ -246,6 +258,53 @@ void LLDrawPoolWLSky::renderHeavenlyBodies()
 	}
 }
 
+void LLDrawPoolWLSky::renderDeferred(S32 pass)
+{
+	if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_SKY))
+	{
+		return;
+	}
+	LLFastTimer ftm(FTM_RENDER_WL_SKY);
+
+	const F32 camHeightLocal = LLWLParamManager::instance()->getDomeOffset() * LLWLParamManager::instance()->getDomeRadius();
+
+	LLGLSNoFog disableFog;
+	LLGLDepthTest depth(GL_TRUE, GL_FALSE);
+	LLGLDisable clip(GL_CLIP_PLANE0);
+
+	gGL.setColorMask(true, false);
+
+	LLGLSquashToFarClip far_clip(glh_get_current_projection());
+
+	renderSkyHaze(camHeightLocal);
+
+	LLVector3 const & origin = LLViewerCamera::getInstance()->getOrigin();
+	glPushMatrix();
+
+		
+		glTranslatef(origin.mV[0], origin.mV[1], origin.mV[2]);
+
+		gDeferredStarProgram.bind();
+		// *NOTE: have to bind a texture here since register combiners blending in
+		// renderStars() requires something to be bound and we might as well only
+		// bind the moon's texture once.		
+		gGL.getTexUnit(0)->bind(gSky.mVOSkyp->mFace[LLVOSky::FACE_MOON]->getTexture());
+
+		renderHeavenlyBodies();
+
+		renderStars();
+		
+		gDeferredStarProgram.unbind();
+
+	glPopMatrix();
+
+	renderSkyClouds(camHeightLocal);
+
+	gGL.setColorMask(true, true);
+	//gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+
+}
+
 void LLDrawPoolWLSky::render(S32 pass)
 {
 	if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_SKY))
diff --git a/indra/newview/lldrawpoolwlsky.h b/indra/newview/lldrawpoolwlsky.h
index 8ca1ebb94273994f01e72d5c3558ae4394082c35..cd15c991ee091fefb8e4f3f6a7ab452fa77364bb 100644
--- a/indra/newview/lldrawpoolwlsky.h
+++ b/indra/newview/lldrawpoolwlsky.h
@@ -44,10 +44,10 @@ class LLDrawPoolWLSky : public LLDrawPool {
 
 	/*virtual*/ BOOL isDead() { return FALSE; }
 
-	/*virtual*/ S32 getNumPostDeferredPasses() { return getNumPasses(); }
-	/*virtual*/ void beginPostDeferredPass(S32 pass) { beginRenderPass(pass); }
-	/*virtual*/ void endPostDeferredPass(S32 pass) { endRenderPass(pass); }
-	/*virtual*/ void renderPostDeferred(S32 pass) { render(pass); }
+	/*virtual*/ S32 getNumDeferredPasses() { return 1; }
+	/*virtual*/ void beginDeferredPass(S32 pass);
+	/*virtual*/ void endDeferredPass(S32 pass);
+	/*virtual*/ void renderDeferred(S32 pass);
 
 	/*virtual*/ LLViewerTexture *getDebugTexture();
 	/*virtual*/ void beginRenderPass( S32 pass );
diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp
index 5398c13c44086aca667eabfac288df518b749807..b6566fcbd094da1b4c887f89ac667fafd942b1ba 100644
--- a/indra/newview/llface.cpp
+++ b/indra/newview/llface.cpp
@@ -165,6 +165,7 @@ void LLFace::init(LLDrawable* drawablep, LLViewerObject* objp)
 	mIndexInTex = 0;
 	mTexture		= NULL;
 	mTEOffset		= -1;
+	mTextureIndex = 255;
 
 	setDrawable(drawablep);
 	mVObjp = objp;
@@ -364,14 +365,7 @@ void LLFace::setSize(S32 num_vertices, S32 num_indices, bool align)
 		//allocate vertices in blocks of 4 for alignment
 		num_vertices = (num_vertices + 0x3) & ~0x3;
 	}
-	else
-	{
-		if (mDrawablep->getVOVolume())
-		{
-			llerrs << "WTF?" << llendl;
-		}
-	}
-
+	
 	if (mGeomCount != num_vertices ||
 		mIndicesCount != num_indices)
 	{
@@ -393,6 +387,26 @@ void LLFace::setGeomIndex(U16 idx)
 	}
 }
 
+void LLFace::setTextureIndex(U8 index)
+{
+	if (index != mTextureIndex)
+	{
+		mTextureIndex = index;
+
+		if (mTextureIndex != 255)
+		{
+			mDrawablep->setState(LLDrawable::REBUILD_POSITION);
+		}
+		else
+		{
+			if (mDrawInfo && !mDrawInfo->mTextureList.empty())
+			{
+				llerrs << "Face with no texture index references indexed texture draw info." << llendl;
+			}
+		}
+	}
+}
+
 void LLFace::setIndicesIndex(S32 idx) 
 { 
 	if (mIndicesIndex != idx)
@@ -415,11 +429,11 @@ U16 LLFace::getGeometryAvatar(
 
 	if (mVertexBuffer.notNull())
 	{
-		mVertexBuffer->getVertexStrider      (vertices, mGeomIndex);
-		mVertexBuffer->getNormalStrider      (normals, mGeomIndex);
-		mVertexBuffer->getTexCoord0Strider    (tex_coords, mGeomIndex);
-		mVertexBuffer->getWeightStrider(vertex_weights, mGeomIndex);
-		mVertexBuffer->getClothWeightStrider(clothing_weights, mGeomIndex);
+		mVertexBuffer->getVertexStrider      (vertices, mGeomIndex, mGeomCount);
+		mVertexBuffer->getNormalStrider      (normals, mGeomIndex, mGeomCount);
+		mVertexBuffer->getTexCoord0Strider    (tex_coords, mGeomIndex, mGeomCount);
+		mVertexBuffer->getWeightStrider(vertex_weights, mGeomIndex, mGeomCount);
+		mVertexBuffer->getClothWeightStrider(clothing_weights, mGeomIndex, mGeomCount);
 	}
 
 	return mGeomIndex;
@@ -432,17 +446,17 @@ U16 LLFace::getGeometry(LLStrider<LLVector3> &vertices, LLStrider<LLVector3> &no
 	
 	if (mVertexBuffer.notNull())
 	{
-		mVertexBuffer->getVertexStrider(vertices,   mGeomIndex);
+		mVertexBuffer->getVertexStrider(vertices,   mGeomIndex, mGeomCount);
 		if (mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_NORMAL))
 		{
-			mVertexBuffer->getNormalStrider(normals,    mGeomIndex);
+			mVertexBuffer->getNormalStrider(normals,    mGeomIndex, mGeomCount);
 		}
 		if (mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD0))
 		{
-			mVertexBuffer->getTexCoord0Strider(tex_coords, mGeomIndex);
+			mVertexBuffer->getTexCoord0Strider(tex_coords, mGeomIndex, mGeomCount);
 		}
 
-		mVertexBuffer->getIndexStrider(indicesp, mIndicesIndex);
+		mVertexBuffer->getIndexStrider(indicesp, mIndicesIndex, mIndicesCount);
 	}
 	
 	return mGeomIndex;
@@ -679,6 +693,19 @@ static void xform(LLVector2 &tex_coord, F32 cosAng, F32 sinAng, F32 offS, F32 of
 }
 
 
+bool less_than_max_mag(const LLVector4a& vec)
+{
+	LLVector4a MAX_MAG;
+	MAX_MAG.splat(1024.f*1024.f);
+
+	LLVector4a val;
+	val.setAbs(vec);
+
+	S32 lt = val.lessThan(MAX_MAG).getGatheredBits() & 0x7;
+	
+	return lt == 0x7;
+}
+
 BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f,
 								const LLMatrix4& mat_vert_in, const LLMatrix3& mat_normal_in, BOOL global_volume)
 {
@@ -713,6 +740,8 @@ BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f,
 		min = face.mExtents[0];
 		max = face.mExtents[1];
 		
+		llassert(less_than_max_mag(min));
+		llassert(less_than_max_mag(max));
 
 		//min, max are in volume space, convert to drawable render space
 		LLVector4a center;
@@ -724,6 +753,9 @@ BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f,
 		size.setSub(max, min);
 		size.mul(0.5f);
 
+		llassert(less_than_max_mag(min));
+		llassert(less_than_max_mag(max));
+
 		if (!global_volume)
 		{
 			//VECTORIZE THIS
@@ -761,6 +793,8 @@ BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f,
 		
 		newMin = newMax = center;
 		
+		llassert(less_than_max_mag(center));
+		
 		for (U32 i = 0; i < 4; i++)
 		{
 			LLVector4a delta;
@@ -772,6 +806,9 @@ BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f,
 
 			newMin.setMin(newMin,min);
 			newMax.setMax(newMax,max);
+
+			llassert(less_than_max_mag(newMin));
+			llassert(less_than_max_mag(newMax));
 		}
 
 		if (!mDrawablep->isActive())
@@ -780,14 +817,22 @@ BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f,
 			offset.load3(mDrawablep->getRegion()->getOriginAgent().mV);
 			newMin.add(offset);
 			newMax.add(offset);
+			
+			llassert(less_than_max_mag(newMin));
+			llassert(less_than_max_mag(newMax));
 		}
 
 		t.setAdd(newMin, newMax);
 		t.mul(0.5f);
 
+		llassert(less_than_max_mag(t));
+		
 		//VECTORIZE THIS
 		mCenterLocal.set(t.getF32ptr());
 		
+		llassert(less_than_max_mag(newMin));
+		llassert(less_than_max_mag(newMax));
+
 		t.setSub(newMax,newMin);
 		mBoundingSphereRadius = t.getLength3().getF32()*0.5f;
 
@@ -1078,27 +1123,6 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 	const LLTextureEntry *tep = mVObjp->getTE(f);
 	const U8 bump_code = tep ? tep->getBumpmap() : 0;
 
-	if (rebuild_pos)
-	{
-		mVertexBuffer->getVertexStrider(vert, mGeomIndex);
-		vertices = (LLVector4a*) vert.get();
-	}
-	if (rebuild_normal)
-	{
-		mVertexBuffer->getNormalStrider(norm, mGeomIndex);
-		normals = (LLVector4a*) norm.get();
-	}
-	if (rebuild_binormal)
-	{
-		mVertexBuffer->getBinormalStrider(binorm, mGeomIndex);
-		binormals = (LLVector4a*) binorm.get();
-	}
-	if (rebuild_weights)
-	{
-		mVertexBuffer->getWeight4Strider(wght, mGeomIndex);
-		weights = (LLVector4a*) wght.get();
-	}
-	
 	F32 tcoord_xoffset = 0.f ;
 	F32 tcoord_yoffset = 0.f ;
 	F32 tcoord_xscale = 1.f ;
@@ -1107,12 +1131,6 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 
 	if (rebuild_tcoord)
 	{
-		mVertexBuffer->getTexCoord0Strider(tex_coords, mGeomIndex);
-		if (bump_code && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD1))
-		{
-			mVertexBuffer->getTexCoord1Strider(tex_coords2, mGeomIndex);
-		}
-
 		in_atlas = isAtlasInUse() ;
 		if(in_atlas)
 		{
@@ -1125,11 +1143,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 			tcoord_yscale = tmp->mV[1] ;	
 		}
 	}
-	if (rebuild_color)
-	{	
-		mVertexBuffer->getColorStrider(colors, mGeomIndex);
-	}
-
+	
 	BOOL is_static = mDrawablep->isStatic();
 	BOOL is_global = is_static;
 
@@ -1168,7 +1182,8 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 	// INDICES
 	if (full_rebuild)
 	{
-		mVertexBuffer->getIndexStrider(indicesp, mIndicesIndex);
+		mVertexBuffer->getIndexStrider(indicesp, mIndicesIndex, mIndicesCount, true);
+
 		__m128i* dst = (__m128i*) indicesp.get();
 		__m128i* src = (__m128i*) vf.mIndices;
 		__m128i offset = _mm_set1_epi16(index_offset);
@@ -1185,6 +1200,8 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 		{
 			indicesp[i] = vf.mIndices[i]+index_offset;
 		}
+
+		mVertexBuffer->setBuffer(0);
 	}
 	
 	LLMatrix4a mat_normal;
@@ -1330,6 +1347,8 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 
 		if (!in_atlas && !do_bump)
 		{ //not in atlas or not bump mapped, might be able to do a cheap update
+			mVertexBuffer->getTexCoord0Strider(tex_coords, mGeomIndex, mGeomCount);
+
 			if (texgen != LLTextureEntry::TEX_GEN_PLANAR)
 			{
 				if (!do_tex_mat)
@@ -1402,9 +1421,15 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 					}
 				}
 			}
+
+			mVertexBuffer->setBuffer(0);
 		}
 		else
 		{ //either bump mapped or in atlas, just do the whole expensive loop
+			mVertexBuffer->getTexCoord0Strider(tex_coords, mGeomIndex, mGeomCount, true);
+
+			std::vector<LLVector2> bump_tc;
+		
 			for (S32 i = 0; i < num_vertices; i++)
 			{	
 				LLVector2 tc(vf.mTexCoords[i]);
@@ -1535,8 +1560,20 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 				
 
 				*tex_coords++ = tc;
-				
-				if (bump_code && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD1))
+				if (do_bump)
+				{
+					bump_tc.push_back(tc);
+				}
+			}
+
+			mVertexBuffer->setBuffer(0);
+
+
+			if (do_bump)
+			{
+				mVertexBuffer->getTexCoord1Strider(tex_coords2, mGeomIndex, mGeomCount, true);
+		
+				for (S32 i = 0; i < num_vertices; i++)
 				{
 					LLVector4a tangent;
 					tangent.setCross3(vf.mBinormals[i], vf.mNormals[i]);
@@ -1558,16 +1595,22 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 					}
 
 					binormal.normalize3fast();
+					LLVector2 tc = bump_tc[i];
 					tc += LLVector2( bump_s_primary_light_ray.dot3(tangent).getF32(), bump_t_primary_light_ray.dot3(binormal).getF32() );
 					
 					*tex_coords2++ = tc;
-				}	
+				}
+
+				mVertexBuffer->setBuffer(0);
 			}
 		}
 	}
 
 	if (rebuild_pos)
 	{
+		mVertexBuffer->getVertexStrider(vert, mGeomIndex, mGeomCount, true);
+		vertices = (LLVector4a*) vert.get();
+	
 		LLMatrix4a mat_vert;
 		mat_vert.loadu(mat_vert_in);
 
@@ -1580,10 +1623,28 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 			mat_vert.affineTransform(*src++, *dst++);
 		}
 		while(dst < end);
+
+		F32 index = (F32) (mTextureIndex < 255 ? mTextureIndex : 0);
+		F32 *index_dst = (F32*) vertices;
+		F32 *index_end = (F32*) end;
+
+		index_dst += 3;
+		index_end += 3;
+		do
+		{
+			*index_dst = index;
+			index_dst += 4;
+		}
+		while (index_dst < index_end);
+
+		mVertexBuffer->setBuffer(0);
 	}
 		
 	if (rebuild_normal)
 	{
+		mVertexBuffer->getNormalStrider(norm, mGeomIndex, mGeomCount, true);
+		normals = (LLVector4a*) norm.get();
+	
 		for (S32 i = 0; i < num_vertices; i++)
 		{	
 			LLVector4a normal;
@@ -1591,10 +1652,15 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 			normal.normalize3fast();
 			normals[i] = normal;
 		}
+
+		mVertexBuffer->setBuffer(0);
 	}
 		
 	if (rebuild_binormal)
 	{
+		mVertexBuffer->getBinormalStrider(binorm, mGeomIndex, mGeomCount, true);
+		binormals = (LLVector4a*) binorm.get();
+		
 		for (S32 i = 0; i < num_vertices; i++)
 		{	
 			LLVector4a binormal;
@@ -1602,15 +1668,22 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 			binormal.normalize3fast();
 			binormals[i] = binormal;
 		}
+
+		mVertexBuffer->setBuffer(0);
 	}
 	
 	if (rebuild_weights && vf.mWeights)
 	{
+		mVertexBuffer->getWeight4Strider(wght, mGeomIndex, mGeomCount, true);
+		weights = (LLVector4a*) wght.get();
 		LLVector4a::memcpyNonAliased16((F32*) weights, (F32*) vf.mWeights, num_vertices*4*sizeof(F32));
+		mVertexBuffer->setBuffer(0);
 	}
 
 	if (rebuild_color)
 	{
+		mVertexBuffer->getColorStrider(colors, mGeomIndex, mGeomCount, true);
+
 		LLVector4a src;
 
 		U32 vec[4];
@@ -1629,6 +1702,8 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 		{	
 			dst[i] = src;
 		}
+
+		mVertexBuffer->setBuffer(0);
 	}
 
 	if (rebuild_tcoord)
@@ -2045,13 +2120,13 @@ S32 LLFace::getColors(LLStrider<LLColor4U> &colors)
 	}
 	
 	// llassert(mGeomIndex >= 0);
-	mVertexBuffer->getColorStrider(colors, mGeomIndex);
+	mVertexBuffer->getColorStrider(colors, mGeomIndex, mGeomCount);
 	return mGeomIndex;
 }
 
 S32	LLFace::getIndices(LLStrider<U16> &indicesp)
 {
-	mVertexBuffer->getIndexStrider(indicesp, mIndicesIndex);
+	mVertexBuffer->getIndexStrider(indicesp, mIndicesIndex, mIndicesCount);
 	llassert(indicesp[0] != indicesp[1]);
 	return mIndicesIndex;
 }
diff --git a/indra/newview/llface.h b/indra/newview/llface.h
index b2170c4cf3fd271c7cfd63ab7006d752892c0c3b..b5eaeecd60ea18c533f441e7c9b04c51386ef85f 100644
--- a/indra/newview/llface.h
+++ b/indra/newview/llface.h
@@ -94,6 +94,8 @@ class LLFace
 	U16				getGeomCount()		const	{ return mGeomCount; }		// vertex count for this face
 	U16				getGeomIndex()		const	{ return mGeomIndex; }		// index into draw pool
 	U16				getGeomStart()		const	{ return mGeomIndex; }		// index into draw pool
+	void			setTextureIndex(U8 index);
+	U8				getTextureIndex() const		{ return mTextureIndex; }
 	void			setTexture(LLViewerTexture* tex) ;
 	void            switchTexture(LLViewerTexture* new_texture);
 	void            dirtyTexture();
@@ -262,6 +264,7 @@ class LLFace
 	
 	U16			mGeomCount;			// vertex count for this face
 	U16			mGeomIndex;			// index into draw pool
+	U8			mTextureIndex;		// index of texture channel to use for pseudo-atlasing
 	U32			mIndicesCount;
 	U32			mIndicesIndex;		// index into draw pool for indices (yeah, I know!)
 	S32         mIndexInTex ;
diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp
index 9dd5269a6b4811519a3558bc73d966e2d797a6f6..ab6753b4be31b9f4ea0ab1cfc4c98170f2f7f671 100644
--- a/indra/newview/llfloatermodelpreview.cpp
+++ b/indra/newview/llfloatermodelpreview.cpp
@@ -178,6 +178,80 @@ std::string lod_label_name[NUM_LOD+1] =
 	"I went off the end of the lod_label_name array.  Me so smart."
 };
 
+
+#define LL_DEGENERACY_TOLERANCE  1e-7f
+
+inline F32 dot3fpu(const LLVector4a& a, const LLVector4a& b)
+{
+    volatile F32 p0 = a[0] * b[0];
+    volatile F32 p1 = a[1] * b[1];
+    volatile F32 p2 = a[2] * b[2];
+    return p0 + p1 + p2;
+}
+
+bool ll_is_degenerate(const LLVector4a& a, const LLVector4a& b, const LLVector4a& c, F32 tolerance = LL_DEGENERACY_TOLERANCE)
+{
+        // small area check
+        {
+                LLVector4a edge1; edge1.setSub( a, b );
+                LLVector4a edge2; edge2.setSub( a, c );
+                //////////////////////////////////////////////////////////////////////////
+                /// Linden Modified
+                //////////////////////////////////////////////////////////////////////////
+
+                // If no one edge is more than 10x longer than any other edge, we weaken
+                // the tolerance by a factor of 1e-4f.
+
+                LLVector4a edge3; edge3.setSub( c, b );
+				const F32 len1sq = edge1.dot3(edge1).getF32();
+                const F32 len2sq = edge2.dot3(edge2).getF32();
+                const F32 len3sq = edge3.dot3(edge3).getF32();
+                bool abOK = (len1sq <= 100.f * len2sq) && (len1sq <= 100.f * len3sq);
+                bool acOK = (len2sq <= 100.f * len1sq) && (len1sq <= 100.f * len3sq);
+                bool cbOK = (len3sq <= 100.f * len1sq) && (len1sq <= 100.f * len2sq);
+                if ( abOK && acOK && cbOK )
+                {
+                        tolerance *= 1e-4f;
+                }
+
+                //////////////////////////////////////////////////////////////////////////
+                /// End Modified
+                //////////////////////////////////////////////////////////////////////////
+
+                LLVector4a cross; cross.setCross3( edge1, edge2 );
+
+                LLVector4a edge1b; edge1b.setSub( b, a );
+                LLVector4a edge2b; edge2b.setSub( b, c );
+                LLVector4a crossb; crossb.setCross3( edge1b, edge2b );
+
+                if ( ( cross.dot3(cross).getF32() < tolerance ) || ( crossb.dot3(crossb).getF32() < tolerance ))
+                {
+                        return true;
+                }
+        }
+
+        // point triangle distance check
+        {
+                LLVector4a Q; Q.setSub(a, b);
+                LLVector4a R; R.setSub(c, b);
+
+                const F32 QQ = dot3fpu(Q, Q);
+                const F32 RR = dot3fpu(R, R);
+                const F32 QR = dot3fpu(R, Q);
+
+                volatile F32 QQRR = QQ * RR;
+                volatile F32 QRQR = QR * QR;
+                F32 Det = (QQRR - QRQR);
+
+                if( Det == 0.0f )
+                {
+                        return true;
+                }
+        }
+
+        return false;
+}
+
 bool validate_face(const LLVolumeFace& face)
 {
 	for (U32 i = 0; i < face.mNumIndices; ++i)
@@ -189,6 +263,31 @@ bool validate_face(const LLVolumeFace& face)
 		}
 	}
 
+	if (face.mNumIndices % 3 != 0 || face.mNumIndices == 0)
+	{
+		llwarns << "Face has invalid number of indices." << llendl;
+		return false;
+	}
+
+	/*const LLVector4a scale(0.5f);
+
+	for (U32 i = 0; i < face.mNumIndices; i+=3)
+	{
+		U16 idx1 = face.mIndices[i];
+		U16 idx2 = face.mIndices[i+1];
+		U16 idx3 = face.mIndices[i+2];
+
+		LLVector4a v1; v1.setMul(face.mPositions[idx1], scale);
+		LLVector4a v2; v2.setMul(face.mPositions[idx2], scale);
+		LLVector4a v3; v3.setMul(face.mPositions[idx3], scale);
+
+		if (ll_is_degenerate(v1,v2,v3))
+		{
+			llwarns << "Degenerate face found!" << llendl;
+			return false;
+		}
+	}*/
+
 	return true;
 }
 
@@ -314,15 +413,17 @@ BOOL LLFloaterModelPreview::postBuild()
 	childSetCommitCallback("pelvis_offset", onPelvisOffsetCommit, this);
 
 	childSetCommitCallback("lod_file_or_limit", refresh, this);
-	childSetCommitCallback("physics_load_radio", refresh, this);
+	childSetCommitCallback("physics_load_radio", onPhysicsLoadRadioCommit, this);
 	//childSetCommitCallback("physics_optimize", refresh, this);
 	//childSetCommitCallback("physics_use_hull", refresh, this);
 
 	childDisable("upload_skin");
 	childDisable("upload_joints");
-
+	
 	childDisable("ok_btn");
 
+	childSetCommitCallback("confirm_checkbox", refresh, this);
+
 	mViewOptionMenuButton = getChild<LLMenuButton>("options_gear_btn");
 
 	mCommitCallbackRegistrar.add("ModelImport.ViewOption.Action", boost::bind(&LLFloaterModelPreview::onViewOptionChecked, this, _2));
@@ -469,6 +570,29 @@ void LLFloaterModelPreview::onPelvisOffsetCommit( LLUICtrl*, void* userdata )
 	fp->mModelPreview->refresh();
 }
 
+//static
+void LLFloaterModelPreview::onPhysicsLoadRadioCommit( LLUICtrl*, void *userdata)
+{
+	LLFloaterModelPreview* fmp = LLFloaterModelPreview::sInstance;
+	if (fmp)
+	{
+		if (fmp->childGetValue("physics_use_lod").asBoolean())
+		{
+			onPhysicsUseLOD(NULL,NULL);
+		}
+		if (fmp->childGetValue("physics_load_from_file").asBoolean())
+		{
+			
+		}
+		LLModelPreview *model_preview = fmp->mModelPreview;
+		if (model_preview)
+		{
+			model_preview->refresh();
+			model_preview->updateStatusMessages();
+		}
+	}
+}
+
 //static
 void LLFloaterModelPreview::onUploadJointsCommit(LLUICtrl*,void* userdata)
 {
@@ -573,6 +697,11 @@ void LLFloaterModelPreview::draw()
 			childSetTextArg("status", "[STATUS]", getString(LLModel::getStatusString(mModelPreview->getLoadState() - LLModelLoader::ERROR_PARSING)));
 		}
 		else
+		if ( mModelPreview->getLoadState() == LLModelLoader::ERROR_PARSING )
+		{
+			childSetTextArg("status", "[STATUS]", getString("status_parse_error"));
+		}
+		else
 		{
 			childSetTextArg("status", "[STATUS]", getString("status_idle"));
 		}
@@ -992,7 +1121,7 @@ LLModelLoader::LLModelLoader( std::string filename, S32 lod, LLModelPreview* pre
 							  std::deque<std::string>& jointsFromNodes )
 : mJointList( jointMap )
 , mJointsFromNode( jointsFromNodes )
-, LLThread("Model Loader"), mFilename(filename), mLod(lod), mPreview(preview), mFirstTransform(TRUE)
+, LLThread("Model Loader"), mFilename(filename), mLod(lod), mPreview(preview), mFirstTransform(TRUE), mNumOfFetchingTextures(0)
 {
 	mJointMap["mPelvis"] = "mPelvis";
 	mJointMap["mTorso"] = "mTorso";
@@ -1157,11 +1286,7 @@ void stretch_extents(LLModel* model, LLMatrix4& mat, LLVector3& min, LLVector3&
 
 void LLModelLoader::run()
 {
-	if (!doLoadModel())
-	{
-		mPreview = NULL;
-	}
-
+	doLoadModel();
 	doOnIdleOneTime(boost::bind(&LLModelLoader::loadModelCallback,this));
 }
 
@@ -1225,6 +1350,23 @@ bool LLModelLoader::doLoadModel()
 		return false;
 	}
 	
+	//Verify some basic properties of the dae
+	//1. Basic validity check on controller 
+	U32 controllerCount = (int) db->getElementCount( NULL, "controller" );
+	bool result = false;
+	for ( int i=0; i<controllerCount; ++i )
+	{
+		domController* pController = NULL;
+		db->getElement( (daeElement**) &pController, i , NULL, "controller" );
+		result = mPreview->verifyController( pController );
+		if (!result)
+		{
+			setLoadState( ERROR_PARSING );
+			return true;
+		}
+	}
+
+
 	//get unit scale
 	mTransform.setIdentity();
 	
@@ -1275,7 +1417,7 @@ bool LLModelLoader::doLoadModel()
 			if(model->getStatus() != LLModel::NO_ERRORS)
 			{
 				setLoadState(ERROR_PARSING + model->getStatus()) ;
-				return true ; //abort
+				return false; //abort
 			}
 
 			if (model.notNull() && validate_model(model))
@@ -1634,7 +1776,7 @@ bool LLModelLoader::doLoadModel()
 											{
 												if (pos.getCount() <= j+2)
 												{
-													llerrs << "WTF?" << llendl;
+													llerrs << "Invalid position array size." << llendl;
 												}
 												
 												LLVector3 v(pos[j], pos[j+1], pos[j+2]);
@@ -1759,11 +1901,19 @@ bool LLModelLoader::doLoadModel()
 	{
 		llwarns << "document has no visual_scene" << llendl;
 		setLoadState( ERROR_PARSING );
-		return false;
+		return true;
 	}
+	
 	setLoadState( DONE );
 
-	processElement(scene);
+	bool badElement = false;
+	
+	processElement( scene, badElement );
+	
+	if ( badElement )
+	{
+		setLoadState( ERROR_PARSING );
+	}
 	
 	return true;
 }
@@ -2124,7 +2274,8 @@ void LLModelLoader::loadTextures()
 					iter->second[i].mMaterial[j].mDiffuseMap = 
 						LLViewerTextureManager::getFetchedTextureFromUrl("file://" + iter->second[i].mMaterial[j].mDiffuseMapFilename, TRUE, LLViewerTexture::BOOST_PREVIEW);
 					iter->second[i].mMaterial[j].mDiffuseMap->setLoadedCallback(LLModelPreview::textureLoadedCallback, 0, TRUE, FALSE, mPreview, NULL, FALSE);
-					iter->second[i].mMaterial[j].mDiffuseMap->forceToSaveRawImage();
+					iter->second[i].mMaterial[j].mDiffuseMap->forceToSaveRawImage(0, F32_MAX);
+					mNumOfFetchingTextures++ ;
 				}
 			}
 		}
@@ -2153,6 +2304,90 @@ bool LLModelLoader::isNodeAJoint( domNode* pNode )
 
 	return false;
 }
+//-----------------------------------------------------------------------------
+// verifyCount
+//-----------------------------------------------------------------------------
+bool LLModelPreview::verifyCount( int expected, int result )
+{
+	if ( expected != result )
+	{
+		llinfos<< "Error: (expected/got)"<<expected<<"/"<<result<<"verts"<<llendl;
+		return false;
+	}
+	return true;
+}
+//-----------------------------------------------------------------------------
+// verifyController
+//-----------------------------------------------------------------------------
+bool LLModelPreview::verifyController( domController* pController )
+{	
+
+	bool result = true;
+
+	domSkin* pSkin = pController->getSkin();
+
+	if ( pSkin )
+	{
+		xsAnyURI & uri = pSkin->getSource();
+		domElement* pElement = uri.getElement();
+
+		if ( !pElement )
+		{
+			llinfos<<"Can't resolve skin source"<<llendl;
+			return false;
+		}
+
+		daeString type_str = pElement->getTypeName();
+		if ( stricmp(type_str, "geometry") == 0 )
+		{	
+			//Skin is reference directly by geometry and get the vertex count from skin
+			domSkin::domVertex_weights* pVertexWeights = pSkin->getVertex_weights();
+			U32 vertexWeightsCount = pVertexWeights->getCount();
+			domGeometry* pGeometry = (domGeometry*) (domElement*) uri.getElement();
+			domMesh* pMesh = pGeometry->getMesh();				
+			
+			if ( pMesh )
+			{
+				//Get vertex count from geometry
+				domVertices* pVertices = pMesh->getVertices();
+				if ( !pVertices )
+				{ 
+					llinfos<<"No vertices!"<<llendl;
+					return false;
+				}
+
+				if ( pVertices )
+				{
+					xsAnyURI src = pVertices->getInput_array()[0]->getSource();
+					domSource* pSource = (domSource*) (domElement*) src.getElement();
+					U32 verticesCount = pSource->getTechnique_common()->getAccessor()->getCount();
+					result = verifyCount( verticesCount, vertexWeightsCount );
+					if ( !result )
+					{
+						return result;
+					}
+				}
+			}	
+
+			U32 vcountCount = (U32) pVertexWeights->getVcount()->getValue().getCount();
+			result = verifyCount( vcountCount, vertexWeightsCount );	
+			if ( !result )
+			{
+				return result;
+			}
+
+			domInputLocalOffset_Array& inputs = pVertexWeights->getInput_array();
+			U32 sum = 0;
+			for (size_t i=0; i<vcountCount; i++)
+			{
+				sum += pVertexWeights->getVcount()->getValue()[i];
+			}
+			result = verifyCount( sum * inputs.getCount(), (domInt) pVertexWeights->getV()->getValue().getCount() );
+		}
+	}
+	
+	return result;
+}
 
 //-----------------------------------------------------------------------------
 // extractTranslation()
@@ -2263,7 +2498,7 @@ daeElement* LLModelLoader::getChildFromElement( daeElement* pElement, std::strin
     return NULL;
 }
 
-void LLModelLoader::processElement(daeElement* element)
+void LLModelLoader::processElement( daeElement* element, bool& badElement )
 {
 	LLMatrix4 saved_transform = mTransform;
 
@@ -2296,8 +2531,11 @@ void LLModelLoader::processElement(daeElement* element)
 	{
 		domFloat3 dom_value = scale->getValue();
 
+
+		LLVector3 scale_vector = LLVector3(dom_value[0], dom_value[1], dom_value[2]);
+		scale_vector.abs(); // Set all values positive, since we don't currently support mirrored meshes
 		LLMatrix4 scaling;
-		scaling.initScale(LLVector3(dom_value[0], dom_value[1], dom_value[2]));
+		scaling.initScale(scale_vector);
 
 		scaling *= mTransform;
 		mTransform = scaling;
@@ -2360,6 +2598,12 @@ void LLModelLoader::processElement(daeElement* element)
 				}
 			}
 		}
+		else 
+		{
+			llinfos<<"Unable to resolve geometry URL."<<llendl;
+			badElement = true;			
+		}
+
 	}
 
 	domInstance_node* instance_node = daeSafeCast<domInstance_node>(element);
@@ -2368,7 +2612,7 @@ void LLModelLoader::processElement(daeElement* element)
 		daeElement* instance = instance_node->getUrl().getElement();
 		if (instance)
 		{
-			processElement(instance);
+			processElement(instance,badElement);
 		}
 	}
 
@@ -2376,7 +2620,7 @@ void LLModelLoader::processElement(daeElement* element)
 	daeTArray< daeSmartRef<daeElement> > children = element->getChildren();
 	for (S32 i = 0; i < children.getCount(); i++)
 	{
-		processElement(children[i]);
+		processElement(children[i],badElement);
 	}
 
 	domNode* node = daeSafeCast<domNode>(element);
@@ -2660,7 +2904,7 @@ LLModelPreview::~LLModelPreview()
 {
 	if (mModelLoader)
 	{
-		delete mModelLoader;
+		mModelLoader->mPreview = NULL;
 		mModelLoader = NULL;
 	}
 	//*HACK : *TODO : turn this back on when we understand why this crashes
@@ -2675,7 +2919,8 @@ U32 LLModelPreview::calcResourceCost()
 
 	if (mFMP && mModelLoader)
 	{
-		if ( getLoadState() < LLModelLoader::ERROR_PARSING )
+		const BOOL confirmed_checkbox = mFMP->getChild<LLCheckBoxCtrl>("confirm_checkbox")->getValue().asBoolean();
+		if ( getLoadState() < LLModelLoader::ERROR_PARSING && confirmed_checkbox )
 		{
 			mFMP->childEnable("ok_btn");
 		}
@@ -2817,7 +3062,8 @@ void LLModelPreview::rebuildUploadData()
 
 	F32 max_scale = 0.f;
 
-	if ( mBaseScene.size() > 0 )
+	const BOOL confirmed_checkbox = mFMP->getChild<LLCheckBoxCtrl>("confirm_checkbox")->getValue().asBoolean();
+	if ( mBaseScene.size() > 0 && confirmed_checkbox )
 	{
 		mFMP->childEnable("ok_btn");
 	}
@@ -3221,6 +3467,8 @@ void LLModelPreview::loadModelCallback(S32 lod)
 	}
 
 	mLoading = false;
+	if (mFMP)
+		mFMP->getChild<LLCheckBoxCtrl>("confirm_checkbox")->set(FALSE);
 	refresh();
 
 	mModelLoadedSignal();
@@ -3234,7 +3482,7 @@ void LLModelPreview::resetPreviewTarget()
 		mPreviewScale = (mModelLoader->mExtents[1] - mModelLoader->mExtents[0]) * 0.5f;
 	}
 
-	setPreviewTarget(mPreviewScale.magVec()*2.f);
+	setPreviewTarget(mPreviewScale.magVec()*10.f);
 }
 
 void LLModelPreview::generateNormals()
@@ -3752,7 +4000,35 @@ void LLModelPreview::updateStatusMessages()
 		mMaxTriangleLimit = total_tris[LLModel::LOD_HIGH];
 	}
 
+	bool has_degenerate = false;
+
+	{//check for degenerate triangles in physics mesh
+		U32 lod = LLModel::LOD_PHYSICS;
+		const LLVector4a scale(0.5f);
+		for (U32 i = 0; i < mModel[lod].size() && !has_degenerate; ++i)
+		{ //for each model in the lod
+			if (mModel[lod][i]->mPhysics.mHull.empty())
+			{ //no decomp exists
+				S32 cur_submeshes = mModel[lod][i]->getNumVolumeFaces();
+				for (S32 j = 0; j < cur_submeshes && !has_degenerate; ++j)
+				{ //for each submesh (face), add triangles and vertices to current total
+					const LLVolumeFace& face = mModel[lod][i]->getVolumeFace(j);
+					for (S32 k = 0; k < face.mNumIndices && !has_degenerate; )
+					{
+						LLVector4a v1; v1.setMul(face.mPositions[face.mIndices[k++]], scale);
+						LLVector4a v2; v2.setMul(face.mPositions[face.mIndices[k++]], scale);
+						LLVector4a v3; v3.setMul(face.mPositions[face.mIndices[k++]], scale);
 
+						if (ll_is_degenerate(v1,v2,v3))
+						{
+							has_degenerate = true;
+						}
+					}
+				}
+			}
+		}
+	}
+	
 	mFMP->childSetTextArg("submeshes_info", "[SUBMESHES]", llformat("%d", total_submeshes[LLModel::LOD_HIGH]));
 
 	std::string mesh_status_na = mFMP->getString("mesh_status_na");
@@ -3853,7 +4129,10 @@ void LLModelPreview::updateStatusMessages()
 
 		for (U32 j = 0; upload_ok && j < mdl->mPhysics.mHull.size(); ++j)
 		{
-			upload_ok = upload_ok && mdl->mPhysics.mHull[i].size() <= 256;
+			if (mdl->mPhysics.mHull[j].size() > 256)
+			{
+				upload_ok = false;
+			}
 		}
 	}
 
@@ -3876,7 +4155,16 @@ void LLModelPreview::updateStatusMessages()
 		}
 	}
 	
-	if ( upload_ok && !errorStateFromLoader && skinAndRigOk )
+	if(upload_ok && mModelLoader)
+	{
+		if(!mModelLoader->areTexturesReady() && mFMP->childGetValue("upload_textures").asBoolean())
+		{
+			upload_ok = false ;
+		}
+	}
+
+	const BOOL confirmed_checkbox = mFMP->getChild<LLCheckBoxCtrl>("confirm_checkbox")->getValue().asBoolean();
+	if ( upload_ok && !errorStateFromLoader && skinAndRigOk && !has_degenerate && confirmed_checkbox)
 	{
 		mFMP->childEnable("ok_btn");
 	}
@@ -4238,11 +4526,7 @@ void LLModelPreview::genBuffers(S32 lod, bool include_skin_weights)
 					const LLModel::weight_list& weight_list = base_mdl->getJointInfluences(pos);
 
 					LLVector4 w(0,0,0,0);
-					if (weight_list.size() > 4)
-					{
-						llerrs << "WTF?" << llendl;
-					}
-
+					
 					for (U32 i = 0; i < weight_list.size(); ++i)
 					{
 						F32 wght = llmin(weight_list[i].mWeight, 0.999999f);
@@ -4455,7 +4739,7 @@ BOOL LLModelPreview::render()
 	LLVector3 target_pos = mPreviewTarget+offset;
 
 	F32 z_near = 0.001f;
-	F32 z_far = mCameraDistance+mPreviewScale.magVec()+mCameraOffset.magVec();
+	F32 z_far = mCameraDistance*10.0f+mPreviewScale.magVec()+mCameraOffset.magVec();
 
 	if (skin_weight)
 	{
@@ -4605,39 +4889,43 @@ BOOL LLModelPreview::render()
 
 						LLModel::Decomposition& physics = model->mPhysics;
 
-						if (physics.mMesh.empty())
-						{ //build vertex buffer for physics mesh
-							gMeshRepo.buildPhysicsMesh(physics);
-						}
-							
-						if (!physics.mMesh.empty())
-						{ //render hull instead of mesh
+						if (!physics.mHull.empty())
+						{
 							render_mesh = false;
-							for (U32 i = 0; i < physics.mMesh.size(); ++i)
-							{
-								if (explode > 0.f)
+
+							if (physics.mMesh.empty())
+							{ //build vertex buffer for physics mesh
+								gMeshRepo.buildPhysicsMesh(physics);
+							}
+						
+							if (!physics.mMesh.empty())
+							{ //render hull instead of mesh
+								for (U32 i = 0; i < physics.mMesh.size(); ++i)
 								{
-									gGL.pushMatrix();
+									if (explode > 0.f)
+									{
+										gGL.pushMatrix();
 
-									LLVector3 offset = model->mHullCenter[i]-model->mCenterOfHullCenters;
-									offset *= explode;
+										LLVector3 offset = model->mHullCenter[i]-model->mCenterOfHullCenters;
+										offset *= explode;
 
-									gGL.translatef(offset.mV[0], offset.mV[1], offset.mV[2]);
-								}
+										gGL.translatef(offset.mV[0], offset.mV[1], offset.mV[2]);
+									}
 
-								static std::vector<LLColor4U> hull_colors;
+									static std::vector<LLColor4U> hull_colors;
 
-								if (i+1 >= hull_colors.size())
-								{
-									hull_colors.push_back(LLColor4U(rand()%128+127, rand()%128+127, rand()%128+127, 255));
-								}
+									if (i+1 >= hull_colors.size())
+									{
+										hull_colors.push_back(LLColor4U(rand()%128+127, rand()%128+127, rand()%128+127, 255));
+									}
 
-									glColor4ubv(hull_colors[i].mV);
-								LLVertexBuffer::drawArrays(LLRender::TRIANGLES, physics.mMesh[i].mPositions, physics.mMesh[i].mNormals);
+										glColor4ubv(hull_colors[i].mV);
+									LLVertexBuffer::drawArrays(LLRender::TRIANGLES, physics.mMesh[i].mPositions, physics.mMesh[i].mNormals);
 
-								if (explode > 0.f)
-								{
-									gGL.popMatrix();
+									if (explode > 0.f)
+									{
+										gGL.popMatrix();
+									}
 								}
 							}
 						}
@@ -4663,9 +4951,10 @@ BOOL LLModelPreview::render()
 
 							glColor3f(1.f, 1.f, 0.f);
 
-							glLineWidth(3.f);
+							glLineWidth(2.f);
 							glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
 							buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts()-1, buffer->getNumIndices(), 0);
+
 							glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
 							glLineWidth(1.f);
 						}
@@ -4674,6 +4963,80 @@ BOOL LLModelPreview::render()
 					gGL.popMatrix();
 				}
 
+				glLineWidth(3.f);
+				glPointSize(8.f);
+				gPipeline.enableLightsFullbright(LLColor4::white);
+				//show degenerate triangles
+				LLGLDepthTest depth(GL_TRUE, GL_TRUE, GL_ALWAYS);
+				LLGLDisable cull(GL_CULL_FACE);
+				glColor4f(1.f,0.f,0.f,1.f);
+				const LLVector4a scale(0.5f);
+
+				for (LLMeshUploadThread::instance_list::iterator iter = mUploadData.begin(); iter != mUploadData.end(); ++iter)
+				{
+					LLModelInstance& instance = *iter;
+
+					LLModel* model = instance.mLOD[LLModel::LOD_PHYSICS];
+
+					if (!model)
+					{
+						continue;
+					}
+
+					gGL.pushMatrix();
+					LLMatrix4 mat = instance.mTransform;
+
+					glMultMatrixf((GLfloat*) mat.mMatrix);
+
+
+					LLPhysicsDecomp* decomp = gMeshRepo.mDecompThread;
+					if (decomp)
+					{
+						LLMutexLock(decomp->mMutex);
+
+						LLModel::Decomposition& physics = model->mPhysics;
+
+						if (physics.mHull.empty())
+						{
+							if (mVertexBuffer[LLModel::LOD_PHYSICS].empty())
+							{
+								genBuffers(LLModel::LOD_PHYSICS, false);
+							}
+							
+							for (U32 i = 0; i < mVertexBuffer[LLModel::LOD_PHYSICS][model].size(); ++i)
+							{
+								LLVertexBuffer* buffer = mVertexBuffer[LLModel::LOD_PHYSICS][model][i];
+
+								buffer->setBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0);
+
+								LLStrider<LLVector3> pos_strider; 
+								buffer->getVertexStrider(pos_strider, 0);
+								LLVector4a* pos = (LLVector4a*) pos_strider.get();
+							
+								LLStrider<U16> idx;
+								buffer->getIndexStrider(idx, 0);
+
+								for (U32 i = 0; i < buffer->getNumIndices(); i += 3)
+								{
+									LLVector4a v1; v1.setMul(pos[*idx++], scale);
+									LLVector4a v2; v2.setMul(pos[*idx++], scale);
+									LLVector4a v3; v3.setMul(pos[*idx++], scale);
+
+									if (ll_is_degenerate(v1,v2,v3))
+									{
+										buffer->draw(LLRender::LINE_LOOP, 3, i);
+										buffer->draw(LLRender::POINTS, 3, i);
+									}
+								}
+							}
+						}
+					}
+
+					gGL.popMatrix();
+				}
+				glLineWidth(1.f);
+				glPointSize(1.f);
+				gPipeline.enableLightsPreview();
 				gGL.setSceneBlendType(LLRender::BT_ALPHA);
 			}
 		}
@@ -4938,6 +5301,14 @@ void LLModelPreview::textureLoadedCallback( BOOL success, LLViewerFetchedTexture
 {
 	LLModelPreview* preview = (LLModelPreview*) userdata;
 	preview->refresh();
+
+	if(final && preview->mModelLoader)
+	{
+		if(preview->mModelLoader->mNumOfFetchingTextures > 0)
+		{
+			preview->mModelLoader->mNumOfFetchingTextures-- ;
+		}
+	}
 }
 
 void LLModelPreview::onLODParamCommit(bool enforce_tri_limit)
@@ -4959,35 +5330,7 @@ LLFloaterModelPreview::DecompRequest::DecompRequest(const std::string& stage, LL
 	mParams = sInstance->mDecompParams;
 
 	//copy out positions and indices
-	if (mdl)
-	{
-		U16 index_offset = 0;
-
-		mPositions.clear();
-		mIndices.clear();
-
-		//queue up vertex positions and indices
-		for (S32 i = 0; i < mdl->getNumVolumeFaces(); ++i)
-		{
-			const LLVolumeFace& face = mdl->getVolumeFace(i);
-			if (mPositions.size() + face.mNumVertices > 65535)
-			{
-				continue;
-			}
-
-			for (U32 j = 0; j < face.mNumVertices; ++j)
-			{
-				mPositions.push_back(LLVector3(face.mPositions[j].getF32ptr()));
-			}
-
-			for (U32 j = 0; j < face.mNumIndices; ++j)
-			{
-				mIndices.push_back(face.mIndices[j]+index_offset);
-			}
-
-			index_offset += face.mNumVertices;
-		}
-	}
+	assignData(mdl) ;	
 }
 
 void LLFloaterModelPreview::setStatusMessage(const std::string& msg)
diff --git a/indra/newview/llfloatermodelpreview.h b/indra/newview/llfloatermodelpreview.h
index f6d4a08d1f2af2cb53f5e28b680c7544db2bbf5e..ccd6fef95333f796553272fa72e28795f4471780 100644
--- a/indra/newview/llfloatermodelpreview.h
+++ b/indra/newview/llfloatermodelpreview.h
@@ -1,431 +1,441 @@
-/**
- * @file llfloatermodelpreview.h
- * @brief LLFloaterModelPreview class definition
- *
- * $LicenseInfo:firstyear=2004&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLFLOATERMODELPREVIEW_H
-#define LL_LLFLOATERMODELPREVIEW_H
-
-#include "llfloaternamedesc.h"
-
-#include "lldynamictexture.h"
-#include "llfloatermodelwizard.h"
-#include "llquaternion.h"
-#include "llmeshrepository.h"
-#include "llmodel.h"
-#include "llthread.h"
-#include "llviewermenufile.h"
-
-class LLComboBox;
-class LLJoint;
-class LLViewerJointMesh;
-class LLVOAvatar;
-class LLTextBox;
-class LLVertexBuffer;
-class LLModelPreview;
-class LLFloaterModelPreview;
-class daeElement;
-class domProfile_COMMON;
-class domInstance_geometry;
-class domNode;
-class domTranslate;
-class LLMenuButton;
-class LLToggleableMenu;
-
-typedef std::map<std::string, LLMatrix4> JointTransformMap;
-typedef std::map<std::string, LLMatrix4>:: iterator JointTransformMapIt;
-
-const S32 NUM_LOD = 4;
-
-class LLModelLoader : public LLThread
-{
-public:
-	typedef enum
-	{
-		STARTING = 0,
-		READING_FILE,
-		CREATING_FACES,
-		GENERATING_VERTEX_BUFFERS,
-		GENERATING_LOD,
-		DONE,
-		ERROR_PARSING //basically loading failed
-	} eLoadState;
-
-	U32 mState;
-	std::string mFilename;
-	S32 mLod;
-	LLModelPreview* mPreview;
-	LLMatrix4 mTransform;
-	BOOL mFirstTransform;
-	LLVector3 mExtents[2];
-	bool mTrySLM;
-	
-	std::map<daeElement*, LLPointer<LLModel> > mModel;
-	
-	typedef std::vector<LLPointer<LLModel> > model_list;
-	model_list mModelList;
-
-	typedef std::vector<LLModelInstance> model_instance_list;
-	
-	typedef std::map<LLMatrix4, model_instance_list > scene;
-
-	scene mScene;
-
-	typedef std::queue<LLPointer<LLModel> > model_queue;
-
-	//queue of models that need a physics rep
-	model_queue mPhysicsQ;
-
-	LLModelLoader( std::string filename, S32 lod, LLModelPreview* preview, JointTransformMap& jointMap, 
-				   std::deque<std::string>& jointsFromNodes );
-	~LLModelLoader() ;
-
-	virtual void run();
-	bool doLoadModel();
-	bool loadFromSLM(const std::string& filename);
-	void loadModelCallback();
-
-	void loadTextures() ; //called in the main thread.
-	void processElement(daeElement* element);
-	std::vector<LLImportMaterial> getMaterials(LLModel* model, domInstance_geometry* instance_geo);
-	LLImportMaterial profileToMaterial(domProfile_COMMON* material);
-	std::string getElementLabel(daeElement *element);
-	LLColor4 getDaeColor(daeElement* element);
-	
-	daeElement* getChildFromElement( daeElement* pElement, std::string const & name );
-	
-	bool isNodeAJoint( domNode* pNode );
-	void processJointNode( domNode* pNode, std::map<std::string,LLMatrix4>& jointTransforms );
-	void extractTranslation( domTranslate* pTranslate, LLMatrix4& transform );
-	void extractTranslationViaElement( daeElement* pTranslateElement, LLMatrix4& transform );
-	
-	void setLoadState(U32 state);
-
-	void buildJointToNodeMappingFromScene( daeElement* pRoot );
-	void processJointToNodeMapping( domNode* pNode );
-
-
-	//map of avatar joints as named in COLLADA assets to internal joint names
-	std::map<std::string, std::string> mJointMap;
-	JointTransformMap& mJointList;	
-	std::deque<std::string>& mJointsFromNode;
-
-private:
-	static std::list<LLModelLoader*> sActiveLoaderList;
-	static bool isAlive(LLModelLoader* loader) ;
-};
-
-class LLFloaterModelPreview : public LLFloater
-{
-public:
-	
-	class DecompRequest : public LLPhysicsDecomp::Request
-	{
-	public:
-		S32 mContinue;
-		LLPointer<LLModel> mModel;
-		
-		DecompRequest(const std::string& stage, LLModel* mdl);
-		virtual S32 statusCallback(const char* status, S32 p1, S32 p2);
-		virtual void completed();
-		
-	};
-	static LLFloaterModelPreview* sInstance;
-	
-	LLFloaterModelPreview(const LLSD& key);
-	virtual ~LLFloaterModelPreview();
-	
-	virtual BOOL postBuild();
-	
-	BOOL handleMouseDown(S32 x, S32 y, MASK mask);
-	BOOL handleMouseUp(S32 x, S32 y, MASK mask);
-	BOOL handleHover(S32 x, S32 y, MASK mask);
-	BOOL handleScrollWheel(S32 x, S32 y, S32 clicks); 
-	
-	static void onMouseCaptureLostModelPreview(LLMouseHandler*);
-	static void setUploadAmount(S32 amount) { sUploadAmount = amount; }
-
-	void setDetails(F32 x, F32 y, F32 z, F32 streaming_cost, F32 physics_cost);
-	
-	static void onBrowseLOD(void* data);
-	
-	static void onReset(void* data);
-
-	static void onUpload(void* data);
-	
-	static void onClearMaterials(void* data);
-	
-	static void refresh(LLUICtrl* ctrl, void* data);
-	
-	void updateResourceCost();
-	
-	void			loadModel(S32 lod);
-	
-	void onViewOptionChecked(const LLSD& userdata);
-	bool isViewOptionChecked(const LLSD& userdata);
-	bool isViewOptionEnabled(const LLSD& userdata);
-	void setViewOptionEnabled(const std::string& option, bool enabled);
-	void enableViewOption(const std::string& option);
-	void disableViewOption(const std::string& option);
-
-protected:
-	friend class LLModelPreview;
-	friend class LLMeshFilePicker;
-	friend class LLPhysicsDecomp;
-	
-	static void		onImportScaleCommit(LLUICtrl*, void*);
-	static void		onPelvisOffsetCommit(LLUICtrl*, void*);
-	static void		onUploadJointsCommit(LLUICtrl*,void*);
-	static void		onUploadSkinCommit(LLUICtrl*,void*);
-	
-	static void		onPreviewLODCommit(LLUICtrl*,void*);
-	
-	static void		onGenerateNormalsCommit(LLUICtrl*,void*);
-	
-	static void		onAutoFillCommit(LLUICtrl*,void*);
-	static void		onLODParamCommit(LLUICtrl*,void*);
-	static void		onLODParamCommitTriangleLimit(LLUICtrl*,void*);
-	
-	static void		onExplodeCommit(LLUICtrl*, void*);
-	
-	static void onPhysicsParamCommit(LLUICtrl* ctrl, void* userdata);
-	static void onPhysicsStageExecute(LLUICtrl* ctrl, void* userdata);
-	static void onCancel(LLUICtrl* ctrl, void* userdata);
-	static void onPhysicsStageCancel(LLUICtrl* ctrl, void* userdata);
-	
-	static void onPhysicsBrowse(LLUICtrl* ctrl, void* userdata);
-	static void onPhysicsUseLOD(LLUICtrl* ctrl, void* userdata);
-	static void onPhysicsOptimize(LLUICtrl* ctrl, void* userdata);
-	static void onPhysicsDecomposeBack(LLUICtrl* ctrl, void* userdata);
-	static void onPhysicsSimplifyBack(LLUICtrl* ctrl, void* userdata);
-		
-	void			draw();
-	
-	void initDecompControls();
-	
-	void setStatusMessage(const std::string& msg);
-
-	LLModelPreview*	mModelPreview;
-	
-	LLPhysicsDecomp::decomp_params mDecompParams;
-	
-	S32				mLastMouseX;
-	S32				mLastMouseY;
-	LLRect			mPreviewRect;
-	U32				mGLName;
-	static S32		sUploadAmount;
-	
-	std::set<LLPointer<DecompRequest> > mCurRequest;
-	std::string mStatusMessage;
-
-	//use "disabled" as false by default
-	std::map<std::string, bool> mViewOptionDisabled;
-	
-	//store which lod mode each LOD is using
-	// 0 - load from file
-	// 1 - auto generate
-	// 2 - None
-	S32 mLODMode[4];
-
-	LLMenuButton* mViewOptionMenuButton;
-	LLToggleableMenu* mViewOptionMenu;
-	LLMutex* mStatusLock;
-
-};
-
-class LLMeshFilePicker : public LLFilePickerThread
-{
-public:
-	LLMeshFilePicker(LLModelPreview* mp, S32 lod);
-	virtual void notify(const std::string& filename);
-
-private:
-	LLModelPreview* mMP;
-	S32 mLOD;
-};
-
-
-class LLModelPreview : public LLViewerDynamicTexture, public LLMutex
-{	
-	typedef boost::signals2::signal<void (F32 x, F32 y, F32 z, F32 streaming_cost, F32 physics_cost)> details_signal_t;
-	typedef boost::signals2::signal<void (void)> model_loaded_signal_t;
-
-public:
-	LLModelPreview(S32 width, S32 height, LLFloater* fmp);
-	virtual ~LLModelPreview();
-
-	void resetPreviewTarget();
-	void setPreviewTarget(F32 distance);
-	void setTexture(U32 name) { mTextureName = name; }
-
-	void setPhysicsFromLOD(S32 lod);
-	BOOL render();
-	void update();
-	void genBuffers(S32 lod, bool skinned);
-	void clearBuffers();
-	void refresh();
-	void rotate(F32 yaw_radians, F32 pitch_radians);
-	void zoom(F32 zoom_amt);
-	void pan(F32 right, F32 up);
-	virtual BOOL needsRender() { return mNeedsUpdate; }
-	void setPreviewLOD(S32 lod);
-	void clearModel(S32 lod);
-	void loadModel(std::string filename, S32 lod);
-	void loadModelCallback(S32 lod);
-	void genLODs(S32 which_lod = -1, U32 decimation = 3, bool enforce_tri_limit = false);
-	void generateNormals();
-	void clearMaterials();
-	U32 calcResourceCost();
-	void rebuildUploadData();
-	void saveUploadData(bool save_skinweights, bool save_joint_poisitions);
-	void saveUploadData(const std::string& filename, bool save_skinweights, bool save_joint_poisitions);
-	void clearIncompatible(S32 lod);
-	void updateStatusMessages();
-	void clearGLODGroup();
-	void onLODParamCommit(bool enforce_tri_limit);
-
-	const bool getModelPivot( void ) const { return mHasPivot; }
-	void setHasPivot( bool val ) { mHasPivot = val; }
-	void setModelPivot( const LLVector3& pivot ) { mModelPivot = pivot; }
-
-	//Sets the current avatars joints to new positions
-	//Makes in world go to shit, however
-	void changeAvatarsJointPositions( LLModel* pModel );
-	//Determines the viability of an asset to be used as an avatar rig (w or w/o joint upload caps)
-	void critiqueRigForUploadApplicability( const std::vector<std::string> &jointListFromAsset );
-	void critiqueJointToNodeMappingFromScene( void  );
-	//Is a rig valid so that it can be used as a criteria for allowing for uploading of joint positions
-	//Accessors for joint position upload friendly rigs
-	const bool isRigValidForJointPositionUpload( void ) const { return mRigValidJointUpload; }
-	void setRigValidForJointPositionUpload( bool rigValid ) { mRigValidJointUpload = rigValid; }
-	bool isRigSuitableForJointPositionUpload( const std::vector<std::string> &jointListFromAsset );
-	//Determines if a rig is a legacy from the joint list
-	bool isRigLegacy( const std::vector<std::string> &jointListFromAsset );	
-	//Accessors for the legacy rigs
-	const bool isLegacyRigValid( void ) const { return mLegacyRigValid; }
-	void setLegacyRigValid( bool rigValid ) { mLegacyRigValid = rigValid; }	
-
-	static void	textureLoadedCallback( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* src_aux, S32 discard_level, BOOL final, void* userdata );
-	
-	boost::signals2::connection setDetailsCallback( const details_signal_t::slot_type& cb ){  return mDetailsSignal.connect(cb);  }
-	boost::signals2::connection setModelLoadedCallback( const model_loaded_signal_t::slot_type& cb ){  return mModelLoadedSignal.connect(cb);  }
-	
-	void setLoadState( U32 state ) { mLoadState = state; }
-	U32 getLoadState() { return mLoadState; }
-	//setRestJointFlag: If an asset comes through that changes the joints, we want the reset to persist
-	void setResetJointFlag( bool state ) { if ( !mResetJoints ) mResetJoints = state; }
-	const bool getResetJointFlag( void ) const { return mResetJoints; }
-	void setRigWithSceneParity( bool state ) { mRigParityWithScene = state; }
-	const bool getRigWithSceneParity( void ) const { return mRigParityWithScene; }
-	
-	LLVector3 getTranslationForJointOffset( std::string joint );
-
-	void		createPreviewAvatar( void );
-	LLVOAvatar* getPreviewAvatar( void ) { return mPreviewAvatar; }
-
- protected:
-	friend class LLModelLoader;
-	friend class LLFloaterModelPreview;
-	friend class LLFloaterModelWizard;
-	friend class LLFloaterModelPreview::DecompRequest;
-	friend class LLFloaterModelWizard::DecompRequest;
-	friend class LLPhysicsDecomp;
-
-	LLFloater*  mFMP;
-
-	BOOL        mNeedsUpdate;
-	bool		mDirty;
-	bool		mGenLOD;
-	U32         mTextureName;
-	F32			mCameraDistance;
-	F32			mCameraYaw;
-	F32			mCameraPitch;
-	F32			mCameraZoom;
-	LLVector3	mCameraOffset;
-	LLVector3	mPreviewTarget;
-	LLVector3	mPreviewScale;
-	S32			mPreviewLOD;
-	U32			mResourceCost;
-	std::string mLODFile[LLModel::NUM_LODS];
-	bool		mLoading;
-	U32			mLoadState;
-	bool		mResetJoints;
-	bool		mRigParityWithScene;
-	
-	std::map<std::string, bool> mViewOption;
-
-	//GLOD object parameters (must rebuild object if these change)
-	bool mLODFrozen;
-	F32 mBuildShareTolerance;
-	U32 mBuildQueueMode;
-	U32 mBuildOperator;
-	U32 mBuildBorderMode;
-	U32 mRequestedLoDMode[LLModel::NUM_LODS];
-	S32 mRequestedTriangleCount[LLModel::NUM_LODS];
-	F32 mRequestedErrorThreshold[LLModel::NUM_LODS];
-	U32 mRequestedBuildOperator[LLModel::NUM_LODS];
-	U32 mRequestedQueueMode[LLModel::NUM_LODS];
-	U32 mRequestedBorderMode[LLModel::NUM_LODS];
-	F32 mRequestedShareTolerance[LLModel::NUM_LODS];
-	F32 mRequestedCreaseAngle[LLModel::NUM_LODS];
-
-	LLModelLoader* mModelLoader;
-
-	LLModelLoader::scene mScene[LLModel::NUM_LODS];
-	LLModelLoader::scene mBaseScene;
-
-	LLModelLoader::model_list mModel[LLModel::NUM_LODS];
-	LLModelLoader::model_list mBaseModel;
-
-	U32 mGroup;
-	std::map<LLPointer<LLModel>, U32> mObject;
-	U32 mMaxTriangleLimit;
-	
-	LLMeshUploadThread::instance_list mUploadData;
-	std::set<LLViewerFetchedTexture* > mTextureSet;
-
-	//map of vertex buffers to models (one vertex buffer in vector per face in model
-	std::map<LLModel*, std::vector<LLPointer<LLVertexBuffer> > > mVertexBuffer[LLModel::NUM_LODS+1];
-
-	details_signal_t mDetailsSignal;
-	model_loaded_signal_t mModelLoadedSignal;
-	
-	LLVector3	mModelPivot;
-	bool		mHasPivot;
-	
-	float		mPelvisZOffset;
-	
-	bool		mRigValidJointUpload;
-	bool		mLegacyRigValid;
-
-	bool		mLastJointUpdate;
-
-	std::deque<std::string> mMasterJointList;
-	std::deque<std::string> mMasterLegacyJointList;
-	std::deque<std::string> mJointsFromNode;
-	JointTransformMap		mJointTransformMap;
-	LLPointer<LLVOAvatar>	mPreviewAvatar;
-};
-
-#endif  // LL_LLFLOATERMODELPREVIEW_H
+/**
+ * @file llfloatermodelpreview.h
+ * @brief LLFloaterModelPreview class definition
+ *
+ * $LicenseInfo:firstyear=2004&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLFLOATERMODELPREVIEW_H
+#define LL_LLFLOATERMODELPREVIEW_H
+
+#include "llfloaternamedesc.h"
+
+#include "lldynamictexture.h"
+#include "llfloatermodelwizard.h"
+#include "llquaternion.h"
+#include "llmeshrepository.h"
+#include "llmodel.h"
+#include "llthread.h"
+#include "llviewermenufile.h"
+
+class LLComboBox;
+class LLJoint;
+class LLViewerJointMesh;
+class LLVOAvatar;
+class LLTextBox;
+class LLVertexBuffer;
+class LLModelPreview;
+class LLFloaterModelPreview;
+class daeElement;
+class domProfile_COMMON;
+class domInstance_geometry;
+class domNode;
+class domTranslate;
+class domController;
+class LLMenuButton;
+class LLToggleableMenu;
+
+typedef std::map<std::string, LLMatrix4> JointTransformMap;
+typedef std::map<std::string, LLMatrix4>:: iterator JointTransformMapIt;
+
+const S32 NUM_LOD = 4;
+
+class LLModelLoader : public LLThread
+{
+public:
+	typedef enum
+	{
+		STARTING = 0,
+		READING_FILE,
+		CREATING_FACES,
+		GENERATING_VERTEX_BUFFERS,
+		GENERATING_LOD,
+		DONE,
+		ERROR_PARSING //basically loading failed
+	} eLoadState;
+
+	U32 mState;
+	std::string mFilename;
+	S32 mLod;
+	LLModelPreview* mPreview;
+	LLMatrix4 mTransform;
+	BOOL mFirstTransform;
+	LLVector3 mExtents[2];
+	bool mTrySLM;
+	
+	std::map<daeElement*, LLPointer<LLModel> > mModel;
+	
+	typedef std::vector<LLPointer<LLModel> > model_list;
+	model_list mModelList;
+
+	typedef std::vector<LLModelInstance> model_instance_list;
+	
+	typedef std::map<LLMatrix4, model_instance_list > scene;
+
+	scene mScene;
+
+	typedef std::queue<LLPointer<LLModel> > model_queue;
+
+	//queue of models that need a physics rep
+	model_queue mPhysicsQ;
+
+	LLModelLoader( std::string filename, S32 lod, LLModelPreview* preview, JointTransformMap& jointMap, 
+				   std::deque<std::string>& jointsFromNodes );
+	~LLModelLoader() ;
+
+	virtual void run();
+	bool doLoadModel();
+	bool loadFromSLM(const std::string& filename);
+	void loadModelCallback();
+
+	void loadTextures() ; //called in the main thread.
+	void processElement(daeElement* element, bool& badElement);
+	std::vector<LLImportMaterial> getMaterials(LLModel* model, domInstance_geometry* instance_geo);
+	LLImportMaterial profileToMaterial(domProfile_COMMON* material);
+	std::string getElementLabel(daeElement *element);
+	LLColor4 getDaeColor(daeElement* element);
+	
+	daeElement* getChildFromElement( daeElement* pElement, std::string const & name );
+	
+	bool isNodeAJoint( domNode* pNode );
+	void processJointNode( domNode* pNode, std::map<std::string,LLMatrix4>& jointTransforms );
+	void extractTranslation( domTranslate* pTranslate, LLMatrix4& transform );
+	void extractTranslationViaElement( daeElement* pTranslateElement, LLMatrix4& transform );
+	
+	void setLoadState(U32 state);
+
+	void buildJointToNodeMappingFromScene( daeElement* pRoot );
+	void processJointToNodeMapping( domNode* pNode );
+
+
+	//map of avatar joints as named in COLLADA assets to internal joint names
+	std::map<std::string, std::string> mJointMap;
+	JointTransformMap& mJointList;	
+	std::deque<std::string>& mJointsFromNode;
+
+	S32 mNumOfFetchingTextures ; //updated in the main thread
+	bool areTexturesReady() { return !mNumOfFetchingTextures; } //called in the main thread.
+
+private:
+	static std::list<LLModelLoader*> sActiveLoaderList;
+	static bool isAlive(LLModelLoader* loader) ;
+};
+
+class LLFloaterModelPreview : public LLFloater
+{
+public:
+	
+	class DecompRequest : public LLPhysicsDecomp::Request
+	{
+	public:
+		S32 mContinue;
+		LLPointer<LLModel> mModel;
+		
+		DecompRequest(const std::string& stage, LLModel* mdl);
+		virtual S32 statusCallback(const char* status, S32 p1, S32 p2);
+		virtual void completed();
+		
+	};
+	static LLFloaterModelPreview* sInstance;
+	
+	LLFloaterModelPreview(const LLSD& key);
+	virtual ~LLFloaterModelPreview();
+	
+	virtual BOOL postBuild();
+	
+	BOOL handleMouseDown(S32 x, S32 y, MASK mask);
+	BOOL handleMouseUp(S32 x, S32 y, MASK mask);
+	BOOL handleHover(S32 x, S32 y, MASK mask);
+	BOOL handleScrollWheel(S32 x, S32 y, S32 clicks); 
+	
+	static void onMouseCaptureLostModelPreview(LLMouseHandler*);
+	static void setUploadAmount(S32 amount) { sUploadAmount = amount; }
+
+	void setDetails(F32 x, F32 y, F32 z, F32 streaming_cost, F32 physics_cost);
+	
+	static void onBrowseLOD(void* data);
+	
+	static void onReset(void* data);
+
+	static void onUpload(void* data);
+	
+	static void onClearMaterials(void* data);
+	
+	static void refresh(LLUICtrl* ctrl, void* data);
+	
+	void updateResourceCost();
+	
+	void			loadModel(S32 lod);
+	
+	void onViewOptionChecked(const LLSD& userdata);
+	bool isViewOptionChecked(const LLSD& userdata);
+	bool isViewOptionEnabled(const LLSD& userdata);
+	void setViewOptionEnabled(const std::string& option, bool enabled);
+	void enableViewOption(const std::string& option);
+	void disableViewOption(const std::string& option);
+
+protected:
+	friend class LLModelPreview;
+	friend class LLMeshFilePicker;
+	friend class LLPhysicsDecomp;
+	
+	static void		onImportScaleCommit(LLUICtrl*, void*);
+	static void		onPelvisOffsetCommit(LLUICtrl*, void*);
+	static void		onUploadJointsCommit(LLUICtrl*,void*);
+	static void		onUploadSkinCommit(LLUICtrl*,void*);
+	
+	static void		onPhysicsLoadRadioCommit(LLUICtrl*,void *data);
+
+	static void		onPreviewLODCommit(LLUICtrl*,void*);
+	
+	static void		onGenerateNormalsCommit(LLUICtrl*,void*);
+	
+	static void		onAutoFillCommit(LLUICtrl*,void*);
+	static void		onLODParamCommit(LLUICtrl*,void*);
+	static void		onLODParamCommitTriangleLimit(LLUICtrl*,void*);
+	
+	static void		onExplodeCommit(LLUICtrl*, void*);
+	
+	static void onPhysicsParamCommit(LLUICtrl* ctrl, void* userdata);
+	static void onPhysicsStageExecute(LLUICtrl* ctrl, void* userdata);
+	static void onCancel(LLUICtrl* ctrl, void* userdata);
+	static void onPhysicsStageCancel(LLUICtrl* ctrl, void* userdata);
+	
+	static void onPhysicsBrowse(LLUICtrl* ctrl, void* userdata);
+	static void onPhysicsUseLOD(LLUICtrl* ctrl, void* userdata);
+	static void onPhysicsOptimize(LLUICtrl* ctrl, void* userdata);
+	static void onPhysicsDecomposeBack(LLUICtrl* ctrl, void* userdata);
+	static void onPhysicsSimplifyBack(LLUICtrl* ctrl, void* userdata);
+		
+	void			draw();
+	
+	void initDecompControls();
+	
+	void setStatusMessage(const std::string& msg);
+
+	LLModelPreview*	mModelPreview;
+	
+	LLPhysicsDecomp::decomp_params mDecompParams;
+	
+	S32				mLastMouseX;
+	S32				mLastMouseY;
+	LLRect			mPreviewRect;
+	U32				mGLName;
+	static S32		sUploadAmount;
+	
+	std::set<LLPointer<DecompRequest> > mCurRequest;
+	std::string mStatusMessage;
+
+	//use "disabled" as false by default
+	std::map<std::string, bool> mViewOptionDisabled;
+	
+	//store which lod mode each LOD is using
+	// 0 - load from file
+	// 1 - auto generate
+	// 2 - None
+	S32 mLODMode[4];
+
+	LLMenuButton* mViewOptionMenuButton;
+	LLToggleableMenu* mViewOptionMenu;
+	LLMutex* mStatusLock;
+
+};
+
+class LLMeshFilePicker : public LLFilePickerThread
+{
+public:
+	LLMeshFilePicker(LLModelPreview* mp, S32 lod);
+	virtual void notify(const std::string& filename);
+
+private:
+	LLModelPreview* mMP;
+	S32 mLOD;
+};
+
+
+class LLModelPreview : public LLViewerDynamicTexture, public LLMutex
+{	
+	typedef boost::signals2::signal<void (F32 x, F32 y, F32 z, F32 streaming_cost, F32 physics_cost)> details_signal_t;
+	typedef boost::signals2::signal<void (void)> model_loaded_signal_t;
+
+public:
+	LLModelPreview(S32 width, S32 height, LLFloater* fmp);
+	virtual ~LLModelPreview();
+
+	void resetPreviewTarget();
+	void setPreviewTarget(F32 distance);
+	void setTexture(U32 name) { mTextureName = name; }
+
+	void setPhysicsFromLOD(S32 lod);
+	BOOL render();
+	void update();
+	void genBuffers(S32 lod, bool skinned);
+	void clearBuffers();
+	void refresh();
+	void rotate(F32 yaw_radians, F32 pitch_radians);
+	void zoom(F32 zoom_amt);
+	void pan(F32 right, F32 up);
+	virtual BOOL needsRender() { return mNeedsUpdate; }
+	void setPreviewLOD(S32 lod);
+	void clearModel(S32 lod);
+	void loadModel(std::string filename, S32 lod);
+	void loadModelCallback(S32 lod);
+	void genLODs(S32 which_lod = -1, U32 decimation = 3, bool enforce_tri_limit = false);
+	void generateNormals();
+	void clearMaterials();
+	U32 calcResourceCost();
+	void rebuildUploadData();
+	void saveUploadData(bool save_skinweights, bool save_joint_poisitions);
+	void saveUploadData(const std::string& filename, bool save_skinweights, bool save_joint_poisitions);
+	void clearIncompatible(S32 lod);
+	void updateStatusMessages();
+	void clearGLODGroup();
+	void onLODParamCommit(bool enforce_tri_limit);
+
+	const bool getModelPivot( void ) const { return mHasPivot; }
+	void setHasPivot( bool val ) { mHasPivot = val; }
+	void setModelPivot( const LLVector3& pivot ) { mModelPivot = pivot; }
+
+	//Determines the viability of an asset to be used as an avatar rig (w or w/o joint upload caps)
+	void critiqueRigForUploadApplicability( const std::vector<std::string> &jointListFromAsset );
+	void critiqueJointToNodeMappingFromScene( void  );
+	//Is a rig valid so that it can be used as a criteria for allowing for uploading of joint positions
+	//Accessors for joint position upload friendly rigs
+	const bool isRigValidForJointPositionUpload( void ) const { return mRigValidJointUpload; }
+	void setRigValidForJointPositionUpload( bool rigValid ) { mRigValidJointUpload = rigValid; }
+	bool isRigSuitableForJointPositionUpload( const std::vector<std::string> &jointListFromAsset );
+	//Determines if a rig is a legacy from the joint list
+	bool isRigLegacy( const std::vector<std::string> &jointListFromAsset );	
+	//Accessors for the legacy rigs
+	const bool isLegacyRigValid( void ) const { return mLegacyRigValid; }
+	void setLegacyRigValid( bool rigValid ) { mLegacyRigValid = rigValid; }	
+	//Verify that a controller matches vertex counts
+	bool verifyController( domController* pController );
+
+	static void	textureLoadedCallback( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* src_aux, S32 discard_level, BOOL final, void* userdata );
+	
+	boost::signals2::connection setDetailsCallback( const details_signal_t::slot_type& cb ){  return mDetailsSignal.connect(cb);  }
+	boost::signals2::connection setModelLoadedCallback( const model_loaded_signal_t::slot_type& cb ){  return mModelLoadedSignal.connect(cb);  }
+	
+	void setLoadState( U32 state ) { mLoadState = state; }
+	U32 getLoadState() { return mLoadState; }
+	//setRestJointFlag: If an asset comes through that changes the joints, we want the reset to persist
+	void setResetJointFlag( bool state ) { if ( !mResetJoints ) mResetJoints = state; }
+	const bool getResetJointFlag( void ) const { return mResetJoints; }
+	void setRigWithSceneParity( bool state ) { mRigParityWithScene = state; }
+	const bool getRigWithSceneParity( void ) const { return mRigParityWithScene; }
+	
+	LLVector3 getTranslationForJointOffset( std::string joint );
+
+private:
+	//Utility function for controller vertex compare
+	bool verifyCount( int expected, int result );
+	//Creates the dummy avatar for the preview window
+	void		createPreviewAvatar( void );
+	//Accessor for the dummy avatar
+	LLVOAvatar* getPreviewAvatar( void ) { return mPreviewAvatar; }
+
+ protected:
+	friend class LLModelLoader;
+	friend class LLFloaterModelPreview;
+	friend class LLFloaterModelWizard;
+	friend class LLFloaterModelPreview::DecompRequest;
+	friend class LLFloaterModelWizard::DecompRequest;
+	friend class LLPhysicsDecomp;
+
+	LLFloater*  mFMP;
+
+	BOOL        mNeedsUpdate;
+	bool		mDirty;
+	bool		mGenLOD;
+	U32         mTextureName;
+	F32			mCameraDistance;
+	F32			mCameraYaw;
+	F32			mCameraPitch;
+	F32			mCameraZoom;
+	LLVector3	mCameraOffset;
+	LLVector3	mPreviewTarget;
+	LLVector3	mPreviewScale;
+	S32			mPreviewLOD;
+	U32			mResourceCost;
+	std::string mLODFile[LLModel::NUM_LODS];
+	bool		mLoading;
+	U32			mLoadState;
+	bool		mResetJoints;
+	bool		mRigParityWithScene;
+	
+	std::map<std::string, bool> mViewOption;
+
+	//GLOD object parameters (must rebuild object if these change)
+	bool mLODFrozen;
+	F32 mBuildShareTolerance;
+	U32 mBuildQueueMode;
+	U32 mBuildOperator;
+	U32 mBuildBorderMode;
+	U32 mRequestedLoDMode[LLModel::NUM_LODS];
+	S32 mRequestedTriangleCount[LLModel::NUM_LODS];
+	F32 mRequestedErrorThreshold[LLModel::NUM_LODS];
+	U32 mRequestedBuildOperator[LLModel::NUM_LODS];
+	U32 mRequestedQueueMode[LLModel::NUM_LODS];
+	U32 mRequestedBorderMode[LLModel::NUM_LODS];
+	F32 mRequestedShareTolerance[LLModel::NUM_LODS];
+	F32 mRequestedCreaseAngle[LLModel::NUM_LODS];
+
+	LLModelLoader* mModelLoader;
+
+	LLModelLoader::scene mScene[LLModel::NUM_LODS];
+	LLModelLoader::scene mBaseScene;
+
+	LLModelLoader::model_list mModel[LLModel::NUM_LODS];
+	LLModelLoader::model_list mBaseModel;
+
+	U32 mGroup;
+	std::map<LLPointer<LLModel>, U32> mObject;
+	U32 mMaxTriangleLimit;
+	
+	LLMeshUploadThread::instance_list mUploadData;
+	std::set<LLViewerFetchedTexture* > mTextureSet;
+
+	//map of vertex buffers to models (one vertex buffer in vector per face in model
+	std::map<LLModel*, std::vector<LLPointer<LLVertexBuffer> > > mVertexBuffer[LLModel::NUM_LODS+1];
+
+	details_signal_t mDetailsSignal;
+	model_loaded_signal_t mModelLoadedSignal;
+	
+	LLVector3	mModelPivot;
+	bool		mHasPivot;
+	
+	float		mPelvisZOffset;
+	
+	bool		mRigValidJointUpload;
+	bool		mLegacyRigValid;
+
+	bool		mLastJointUpdate;
+
+	std::deque<std::string> mMasterJointList;
+	std::deque<std::string> mMasterLegacyJointList;
+	std::deque<std::string> mJointsFromNode;
+	JointTransformMap		mJointTransformMap;
+	LLPointer<LLVOAvatar>	mPreviewAvatar;
+};
+
+#endif  // LL_LLFLOATERMODELPREVIEW_H
diff --git a/indra/newview/llfloatermodelwizard.cpp b/indra/newview/llfloatermodelwizard.cpp
index faf81dbc5c3cef62fb519439de92b04c2c101c41..707c8288dfe5dd43b22b39139d5a03b415b8594f 100644
--- a/indra/newview/llfloatermodelwizard.cpp
+++ b/indra/newview/llfloatermodelwizard.cpp
@@ -422,8 +422,11 @@ void LLFloaterModelWizard::executePhysicsStage(std::string stage_name)
 			{
 				LLModel* mdl = sInstance->mModelPreview->mModel[LLModel::LOD_PHYSICS][i];
 				DecompRequest* request = new DecompRequest(stage_name, mdl);
-				sInstance->mCurRequest.insert(request);
-				gMeshRepo.mDecompThread->submitRequest(request);
+				if(request->isValid())
+				{
+					sInstance->mCurRequest.insert(request);
+					gMeshRepo.mDecompThread->submitRequest(request);
+				}				
 			}
 		}
 	}
@@ -438,35 +441,7 @@ LLFloaterModelWizard::DecompRequest::DecompRequest(const std::string& stage, LLM
 	mParams = sInstance->mDecompParams;
 
 	//copy out positions and indices
-	if (mdl)
-	{
-		U16 index_offset = 0;
-
-		mPositions.clear();
-		mIndices.clear();
-
-		//queue up vertex positions and indices
-		for (S32 i = 0; i < mdl->getNumVolumeFaces(); ++i)
-		{
-			const LLVolumeFace& face = mdl->getVolumeFace(i);
-			if (mPositions.size() + face.mNumVertices > 65535)
-			{
-				continue;
-			}
-
-			for (U32 j = 0; j < face.mNumVertices; ++j)
-			{
-				mPositions.push_back(LLVector3(face.mPositions[j].getF32ptr()));
-			}
-
-			for (U32 j = 0; j < face.mNumIndices; ++j)
-			{
-				mIndices.push_back(face.mIndices[j]+index_offset);
-			}
-
-			index_offset += face.mNumVertices;
-		}
-	}
+	assignData(mdl) ;	
 }
 
 
diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp
index 232b8e9096bdae4b68e004a4df9dba8352d883a1..6b3e3088d5b6aed5727f1f8e55dbbac2b3c1cec7 100644
--- a/indra/newview/llfloaterregioninfo.cpp
+++ b/indra/newview/llfloaterregioninfo.cpp
@@ -82,6 +82,7 @@
 #include "llvlcomposition.h"
 #include "lltrans.h"
 #include "llagentui.h"
+#include "llmeshrepository.h"
 
 const S32 TERRAIN_TEXTURE_COUNT = 4;
 const S32 CORNER_COUNT = 4;
@@ -590,10 +591,7 @@ bool LLPanelRegionGeneralInfo::refreshFromRegion(LLViewerRegion* region)
 	getChildView("im_btn")->setEnabled(allow_modify);
 	getChildView("manage_telehub_btn")->setEnabled(allow_modify);
 
-	const bool enable_mesh = gSavedSettings.getBOOL("MeshEnabled") && 
-		gAgent.getRegion() &&
-		!gAgent.getRegion()->getCapability("GetMesh").empty() &&
-		!gAgent.getRegion()->getCapability("ObjectAdd").empty();
+	const bool enable_mesh = gMeshRepo.meshRezEnabled();
 	getChildView("mesh_rez_enabled_check")->setVisible(enable_mesh);
 	getChildView("mesh_rez_enabled_check")->setEnabled(getChildView("mesh_rez_enabled_check")->getEnabled() && enable_mesh);
 	// Data gets filled in by processRegionInfo
diff --git a/indra/newview/llfloatertools.cpp b/indra/newview/llfloatertools.cpp
index edcb96314b238f46a65e183cd085ac62539f2f8b..0d798afdcc759fbf200d3543b7e4a3f7623ee506 100644
--- a/indra/newview/llfloatertools.cpp
+++ b/indra/newview/llfloatertools.cpp
@@ -86,6 +86,7 @@
 #include "llvovolume.h"
 #include "lluictrlfactory.h"
 #include "llaccountingquotamanager.h"
+#include "llmeshrepository.h"
 
 // Globals
 LLFloaterTools *gFloaterTools = NULL;
@@ -423,7 +424,8 @@ void LLFloaterTools::refresh()
 	// Refresh object and prim count labels
 	LLLocale locale(LLLocale::USER_LOCALE);
 
-	if ((gAgent.getRegion() && (gAgent.getRegion()->getCapability("GetMesh").empty() || gAgent.getRegion()->getCapability("ObjectAdd").empty())) || !gSavedSettings.getBOOL("MeshEnabled"))
+#if 0
+	if (gMeshRepo.meshRezEnabled())
 	{		
 		std::string obj_count_string;
 		LLResMgr::getInstance()->getIntegerString(obj_count_string, LLSelectMgr::getInstance()->getSelection()->getRootObjectCount());
@@ -447,6 +449,7 @@ void LLFloaterTools::refresh()
 		getChildView("RenderingCost")->setEnabled(have_selection && sShowObjectCost);
 	}
 	else
+#endif
 	{
 		// Get the number of objects selected
 		std::string root_object_count_string;
@@ -788,10 +791,7 @@ void LLFloaterTools::updatePopup(LLCoordGL center, MASK mask)
 		getChildView("Strength:")->setVisible( land_visible);
 	}
 
-	bool show_mesh_cost = gAgent.getRegion() && 
-		                  !gAgent.getRegion()->getCapability("GetMesh").empty() && 
-						  gSavedSettings.getBOOL("MeshEnabled") &&
-						  !gAgent.getRegion()->getCapability("ObjectAdd").empty();
+	bool show_mesh_cost = gMeshRepo.meshRezEnabled();
 
 	getChildView("obj_count")->setVisible( !land_visible && !show_mesh_cost);
 	getChildView("prim_count")->setVisible( !land_visible && !show_mesh_cost);
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index b5180854efbe73340b71dd627ba5023b850e0c58..318beafe657a97e1e029c98036468d353a9267f4 100644
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -632,10 +632,12 @@ U32 LLInventoryModel::updateItem(const LLViewerInventoryItem* item)
 	}
 
 	// We're hiding mesh types
+#if 0
 	if (item->getType() == LLAssetType::AT_MESH)
 	{
 		return mask;
 	}
+#endif
 
 	LLViewerInventoryItem* old_item = getItem(item->getUUID());
 	LLPointer<LLViewerInventoryItem> new_item;
diff --git a/indra/newview/llmanipscale.cpp b/indra/newview/llmanipscale.cpp
index 673f28e01fafa9f125b90da9babe73b0000f1f7b..4eb94dfb8e805997665212b06761bd929675cc30 100644
--- a/indra/newview/llmanipscale.cpp
+++ b/indra/newview/llmanipscale.cpp
@@ -58,6 +58,7 @@
 #include "llworld.h"
 #include "v2math.h"
 #include "llvoavatar.h"
+#include "llmeshrepository.h"
 
 
 const F32 MAX_MANIP_SELECT_DISTANCE_SQUARED = 11.f * 11.f;
@@ -90,10 +91,7 @@ F32 get_default_max_prim_scale(bool is_flora)
 {
 	// a bit of a hack, but if it's foilage, we don't want to use the
 	// new larger scale which would result in giant trees and grass
-	if (gSavedSettings.getBOOL("MeshEnabled") && 
-		gAgent.getRegion() && 
-		!gAgent.getRegion()->getCapability("GetMesh").empty() &&
-		!gAgent.getRegion()->getCapability("ObjectAdd").empty() &&
+	if (gMeshRepo.meshRezEnabled() &&
 		!is_flora)
 	{
 		return DEFAULT_MAX_PRIM_SCALE;
diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp
old mode 100644
new mode 100755
index 55145c6ad7734aa4a95f6763acbbc9591c1587fa..6e0722bcf99fa46771bbbd90fd2c738c654a6c6a
--- a/indra/newview/llmeshrepository.cpp
+++ b/indra/newview/llmeshrepository.cpp
@@ -61,6 +61,9 @@
 #include "pipeline.h"
 #include "llinventorymodel.h"
 #include "llfoldertype.h"
+#include "llviewerparcelmgr.h"
+
+#include "boost/lexical_cast.hpp"
 
 #ifndef LL_WINDOWS
 #include "netdb.h"
@@ -85,7 +88,14 @@ U32 LLMeshRepository::sPeakKbps = 0;
 
 const U32 MAX_TEXTURE_UPLOAD_RETRIES = 5;
 
-void dumpLLSDToFile(const LLSD& content, std::string filename);
+static S32 dump_num = 0;
+std::string make_dump_name(std::string prefix, S32 num)
+{
+	return prefix + boost::lexical_cast<std::string>(num) + std::string(".xml");
+	
+}
+void dump_llsd_to_file(const LLSD& content, std::string filename);
+LLSD llsd_from_file(std::string filename);
 
 std::string header_lod[] = 
 {
@@ -459,6 +469,55 @@ class LLMeshPhysicsShapeResponder : public LLCurl::Responder
 
 };
 
+void log_upload_error(S32 status, const LLSD& content, std::string stage, std::string model_name)
+{
+	// Add notification popup.
+	LLSD args;
+	std::string message = content["error"]["message"];
+	std::string identifier = content["error"]["identifier"];
+	args["MESSAGE"] = message;
+	args["IDENTIFIER"] = identifier;
+	args["LABEL"] = model_name;
+	gMeshRepo.uploadError(args);
+
+	// Log details.
+	llwarns << "stage: " << stage << " http status: " << status << llendl;
+	if (content.has("error"))
+	{
+		const LLSD& err = content["error"];
+		llwarns << "err: " << err << llendl;
+		llwarns << "mesh upload failed, stage '" << stage
+				<< "' error '" << err["error"].asString()
+				<< "', message '" << err["message"].asString()
+				<< "', id '" << err["identifier"].asString()
+				<< "'" << llendl;
+		if (err.has("errors"))
+		{
+			S32 error_num = 0;
+			const LLSD& err_list = err["errors"];
+			for (LLSD::array_const_iterator it = err_list.beginArray();
+				 it != err_list.endArray();
+				 ++it)
+			{
+				const LLSD& err_entry = *it;
+				llwarns << "error[" << error_num << "]:" << llendl;
+				for (LLSD::map_const_iterator map_it = err_entry.beginMap();
+					 map_it != err_entry.endMap();
+					 ++map_it)
+				{
+					llwarns << "\t" << map_it->first << ": "
+							<< map_it->second << llendl;
+				}
+				error_num++;
+			}
+		}
+	}
+	else
+	{
+		llwarns << "bad mesh, no error information available" << llendl;
+	}
+}
+
 class LLModelObjectUploadResponder: public LLCurl::Responder
 {
 	LLSD mObjectAsset;
@@ -486,40 +545,82 @@ class LLModelObjectUploadResponder: public LLCurl::Responder
 class LLWholeModelFeeResponder: public LLCurl::Responder
 {
 	LLMeshUploadThread* mThread;
+	LLSD mModelData;
 public:
-	LLWholeModelFeeResponder(LLMeshUploadThread* thread):
-		mThread(thread)
+	LLWholeModelFeeResponder(LLMeshUploadThread* thread, LLSD& model_data):
+		mThread(thread),
+		mModelData(model_data)
 	{
 	}
 	virtual void completed(U32 status,
 						   const std::string& reason,
 						   const LLSD& content)
 	{
-		//assert_main_thread();
+		LLSD cc = content;
+		if (gSavedSettings.getS32("MeshUploadFakeErrors")&1)
+		{
+			cc = llsd_from_file("fake_upload_error.xml");
+		}
+			
 		llinfos << "completed" << llendl;
 		mThread->mPendingUploads--;
-		dumpLLSDToFile(content,"whole_model_response.xml");
-
-		mThread->mWholeModelUploadURL = content["uploader"].asString(); 
+		dump_llsd_to_file(cc,make_dump_name("whole_model_fee_response_",dump_num));
+		if (isGoodStatus(status) &&
+			cc["state"].asString() == "upload")
+		{
+			llinfos << "fee request succeeded" << llendl;
+			mThread->mWholeModelUploadURL = cc["uploader"].asString(); 
+		}
+		else
+		{
+			llwarns << "fee request failed" << llendl;
+			log_upload_error(status,cc,"fee",mModelData["name"]);
+			mThread->mWholeModelUploadURL = "";
+		}
 	}
+
 };
 
 class LLWholeModelUploadResponder: public LLCurl::Responder
 {
 	LLMeshUploadThread* mThread;
+	LLSD mModelData;
+	
 public:
-	LLWholeModelUploadResponder(LLMeshUploadThread* thread):
-		mThread(thread)
+	LLWholeModelUploadResponder(LLMeshUploadThread* thread, LLSD& model_data):
+		mThread(thread),
+		mModelData(model_data)
 	{
 	}
 	virtual void completed(U32 status,
 						   const std::string& reason,
 						   const LLSD& content)
 	{
+		LLSD cc = content;
+		if (gSavedSettings.getS32("MeshUploadFakeErrors")&2)
+		{
+			cc = llsd_from_file("fake_upload_error.xml");
+		}
+
 		//assert_main_thread();
-		llinfos << "upload completed" << llendl;
 		mThread->mPendingUploads--;
-		dumpLLSDToFile(content,"whole_model_upload_response.xml");
+		dump_llsd_to_file(cc,make_dump_name("whole_model_upload_response_",dump_num));
+		llinfos << "LLWholeModelUploadResponder content: " << cc << llendl;
+		// requested "mesh" asset type isn't actually the type
+		// of the resultant object, fix it up here.
+		if (isGoodStatus(status) &&
+			cc["state"].asString() == "complete")
+		{
+			llinfos << "upload succeeded" << llendl;
+			mModelData["asset_type"] = "object";
+			gMeshRepo.updateInventory(LLMeshRepository::inventory_data(mModelData,cc));
+		}
+		else
+		{
+			llwarns << "upload failed" << llendl;
+			std::string model_name = mModelData["name"].asString();
+			log_upload_error(status,cc,"upload",model_name);
+		}
 	}
 };
 
@@ -694,10 +795,7 @@ void LLMeshRepoThread::loadMeshLOD(const LLVolumeParams& mesh_params, S32 lod)
 		if (pending != mPendingLOD.end())
 		{ //append this lod request to existing header request
 			pending->second.push_back(lod);
-			if (pending->second.size() > 4)
-			{
-				llerrs << "WTF?" << llendl;
-			} 
+			llassert(pending->second.size() <= LLModel::NUM_LODS)
 		}
 		else
 		{ //if no header request is pending, fetch header
@@ -817,8 +915,8 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id)
 
 	if (header_size > 0)
 	{
-		S32 offset = header_size + mMeshHeader[mesh_id]["decomposition"]["offset"].asInteger();
-		S32 size = mMeshHeader[mesh_id]["decomposition"]["size"].asInteger();
+		S32 offset = header_size + mMeshHeader[mesh_id]["physics_convex"]["offset"].asInteger();
+		S32 size = mMeshHeader[mesh_id]["physics_convex"]["size"].asInteger();
 
 		mHeaderMutex->unlock();
 
@@ -889,8 +987,8 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id)
 
 	if (header_size > 0)
 	{
-		S32 offset = header_size + mMeshHeader[mesh_id]["physics_shape"]["offset"].asInteger();
-		S32 size = mMeshHeader[mesh_id]["physics_shape"]["size"].asInteger();
+		S32 offset = header_size + mMeshHeader[mesh_id]["physics_mesh"]["offset"].asInteger();
+		S32 size = mMeshHeader[mesh_id]["physics_mesh"]["size"].asInteger();
 
 		mHeaderMutex->unlock();
 
@@ -1282,8 +1380,6 @@ LLMeshUploadThread::LLMeshUploadThread(LLMeshUploadThread::instance_list& data,
 	mOrigin = gAgent.getPositionAgent();
 	mHost = gAgent.getRegionHost();
 	
-	mUploadObjectAssetCapability = gAgent.getRegion()->getCapability("UploadObjectAsset");
-	mNewInventoryCapability = gAgent.getRegion()->getCapability("NewFileAgentInventoryVariablePrice");
 	mWholeModelFeeCapability = gAgent.getRegion()->getCapability("NewFileAgentInventory");
 
 	mOrigin += gAgent.getAtAxis() * scale.magVec();
@@ -1303,35 +1399,7 @@ LLMeshUploadThread::DecompRequest::DecompRequest(LLModel* mdl, LLModel* base_mod
 	mThread = thread;
 	
 	//copy out positions and indices
-	if (mdl)
-	{
-		U16 index_offset = 0;
-
-		mPositions.clear();
-		mIndices.clear();
-			
-		//queue up vertex positions and indices
-		for (S32 i = 0; i < mdl->getNumVolumeFaces(); ++i)
-		{
-			const LLVolumeFace& face = mdl->getVolumeFace(i);
-			if (mPositions.size() + face.mNumVertices > 65535)
-			{
-				continue;
-			}
-
-			for (U32 j = 0; j < face.mNumVertices; ++j)
-			{
-				mPositions.push_back(LLVector3(face.mPositions[j].getF32ptr()));
-			}
-
-			for (U32 j = 0; j < face.mNumIndices; ++j)
-			{
-				mIndices.push_back(face.mIndices[j]+index_offset);
-			}
-
-			index_offset += face.mNumVertices;
-		}
-	}
+	assignData(mdl) ;	
 
 	mThread->mFinalDecomp = this;
 	mThread->mPhysicsComplete = false;
@@ -1344,11 +1412,8 @@ void LLMeshUploadThread::DecompRequest::completed()
 		mThread->mPhysicsComplete = true;
 	}
 
-	if (mHull.size() != 1)
-	{
-		llerrs << "WTF?" << llendl;
-	}
-
+	llassert(mHull.size() == 1);
+	
 	mThread->mHullMap[mBaseModel] = mHull[0];
 }
 
@@ -1376,148 +1441,199 @@ BOOL LLMeshUploadThread::isDiscarded()
 
 void LLMeshUploadThread::run()
 {
-	if (gSavedSettings.getBOOL("MeshUseWholeModelUpload"))
-	{
-		doWholeModelUpload();
-	}
-	else
+	doWholeModelUpload();
+}
+
+void dump_llsd_to_file(const LLSD& content, std::string filename)
+{
+	if (gSavedSettings.getBOOL("MeshUploadLogXML"))
 	{
-		doIterativeUpload();
+		std::ofstream of(filename.c_str());
+		LLSDSerialize::toPrettyXML(content,of);
 	}
 }
 
-#if 1
-void dumpLLSDToFile(const LLSD& content, std::string filename)
+LLSD llsd_from_file(std::string filename)
 {
-	std::ofstream of(filename.c_str());
-	LLSDSerialize::toPrettyXML(content,of);
+	std::ifstream ifs(filename.c_str());
+	LLSD result;
+	LLSDSerialize::fromXML(result,ifs);
+	return result;
 }
-#endif
 
 void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures)
 {
-	// TODO where do textures go?
-
 	LLSD result;
 
 	LLSD res;
 	result["folder_id"] = gInventory.findCategoryUUIDForType(LLFolderType::FT_OBJECT);
 	result["asset_type"] = "mesh";
 	result["inventory_type"] = "object";
-	result["name"] = "your name here";
+	result["name"] = "mesh model";
 	result["description"] = "your description here";
 
-	// TODO "optional" fields from the spec
-	
 	res["mesh_list"] = LLSD::emptyArray();
-// TODO Textures
-	//res["texture_list"] = LLSD::emptyArray();
+	res["texture_list"] = LLSD::emptyArray();
+	res["instance_list"] = LLSD::emptyArray();
 	S32 mesh_num = 0;
 	S32 texture_num = 0;
 	
 	std::set<LLViewerTexture* > textures;
+	std::map<LLViewerTexture*,S32> texture_index;
+
+	std::map<LLModel*,S32> mesh_index;
 
+	S32 instance_num = 0;
+	
 	for (instance_map::iterator iter = mInstance.begin(); iter != mInstance.end(); ++iter)
 	{
 		LLMeshUploadData data;
 		data.mBaseModel = iter->first;
-
-		LLModelInstance& instance = *(iter->second.begin());
-
+		LLModelInstance& first_instance = *(iter->second.begin());
 		for (S32 i = 0; i < 5; i++)
 		{
-			data.mModel[i] = instance.mLOD[i];
+			data.mModel[i] = first_instance.mLOD[i];
 		}
 
-		std::stringstream ostr;
-
-		LLModel::Decomposition& decomp =
-			data.mModel[LLModel::LOD_PHYSICS].notNull() ? 
-			data.mModel[LLModel::LOD_PHYSICS]->mPhysics : 
-			data.mBaseModel->mPhysics;
-
-		decomp.mBaseHull = mHullMap[data.mBaseModel];
-
-		LLSD mesh_header = LLModel::writeModel(
-			ostr,  
-			data.mModel[LLModel::LOD_PHYSICS],
-			data.mModel[LLModel::LOD_HIGH],
-			data.mModel[LLModel::LOD_MEDIUM],
-			data.mModel[LLModel::LOD_LOW],
-			data.mModel[LLModel::LOD_IMPOSTOR], 
-			decomp,
-			mUploadSkin,
-			mUploadJoints);
-
-		data.mAssetData = ostr.str();
+		if (mesh_index.find(data.mBaseModel) == mesh_index.end())
+		{
+			// Have not seen this model before - create a new mesh_list entry for it.
+			std::string model_name = data.mBaseModel->getName();
+			if (!model_name.empty())
+			{
+				result["name"] = model_name;
+			}
 
-		LLSD mesh_entry;
+			std::stringstream ostr;
+			
+			LLModel::Decomposition& decomp =
+				data.mModel[LLModel::LOD_PHYSICS].notNull() ? 
+				data.mModel[LLModel::LOD_PHYSICS]->mPhysics : 
+				data.mBaseModel->mPhysics;
 
-		LLVector3 pos, scale;
-		LLQuaternion rot;
-		LLMatrix4 transformation = instance.mTransform;
-		decomposeMeshMatrix(transformation,pos,rot,scale);
+			decomp.mBaseHull = mHullMap[data.mBaseModel];
 
-#if 0
-		mesh_entry["childpos"] = ll_sd_from_vector3(pos);
-		mesh_entry["childrot"] = ll_sd_from_quaternion(rot);
-		mesh_entry["scale"] = ll_sd_from_vector3(scale);
-#endif
-		mesh_entry["position"] = ll_sd_from_vector3(LLVector3());
-		mesh_entry["rotation"] = ll_sd_from_quaternion(rot);
-		mesh_entry["scale"] = ll_sd_from_vector3(scale);
+			LLSD mesh_header = LLModel::writeModel(
+				ostr,  
+				data.mModel[LLModel::LOD_PHYSICS],
+				data.mModel[LLModel::LOD_HIGH],
+				data.mModel[LLModel::LOD_MEDIUM],
+				data.mModel[LLModel::LOD_LOW],
+				data.mModel[LLModel::LOD_IMPOSTOR], 
+				decomp,
+				mUploadSkin,
+				mUploadJoints);
 
-		// TODO should be binary.
-		std::string str = ostr.str();
-		mesh_entry["mesh_data"] = LLSD::Binary(str.begin(),str.end()); 
+			data.mAssetData = ostr.str();
+			std::string str = ostr.str();
 
-		res["mesh_list"][mesh_num] = mesh_entry;
+			res["mesh_list"][mesh_num] = LLSD::Binary(str.begin(),str.end()); 
+			mesh_index[data.mBaseModel] = mesh_num;
+			mesh_num++;
+		}
 
-		// TODO how do textures in the list map to textures in the meshes?
-		if (mUploadTextures)
+		// For all instances that use this model
+		for (instance_list::iterator instance_iter = iter->second.begin();
+			 instance_iter != iter->second.end();
+			 ++instance_iter)
 		{
-			for (std::vector<LLImportMaterial>::iterator material_iter = instance.mMaterial.begin();
-				material_iter != instance.mMaterial.end(); ++material_iter)
-			{
 
-				if (textures.find(material_iter->mDiffuseMap.get()) == textures.end())
+			LLModelInstance& instance = *instance_iter;
+		
+			LLSD instance_entry;
+		
+			for (S32 i = 0; i < 5; i++)
+			{
+				data.mModel[i] = instance.mLOD[i];
+			}
+		
+			LLVector3 pos, scale;
+			LLQuaternion rot;
+			LLMatrix4 transformation = instance.mTransform;
+			decomposeMeshMatrix(transformation,pos,rot,scale);
+			instance_entry["position"] = ll_sd_from_vector3(pos);
+			instance_entry["rotation"] = ll_sd_from_quaternion(rot);
+			instance_entry["scale"] = ll_sd_from_vector3(scale);
+		
+			instance_entry["material"] = LL_MCODE_WOOD;
+			LLPermissions perm;
+			perm.setOwnerAndGroup(gAgent.getID(), gAgent.getID(), LLUUID::null, false);
+			perm.setCreator(gAgent.getID());
+		
+			perm.initMasks(PERM_ITEM_UNRESTRICTED | PERM_MOVE, //base
+						   PERM_ITEM_UNRESTRICTED | PERM_MOVE, //owner
+						   LLFloaterPerms::getEveryonePerms(),
+						   LLFloaterPerms::getGroupPerms(),
+						   LLFloaterPerms::getNextOwnerPerms());
+			instance_entry["permissions"] = ll_create_sd_from_permissions(perm);
+			instance_entry["physics_shape_type"] = (U8)(LLViewerObject::PHYSICS_SHAPE_CONVEX_HULL);
+			instance_entry["mesh"] = mesh_index[data.mBaseModel];
+
+			instance_entry["face_list"] = LLSD::emptyArray();
+
+			for (S32 face_num = 0; face_num < data.mBaseModel->getNumVolumeFaces(); face_num++)
+			{
+				LLImportMaterial& material = instance.mMaterial[face_num];
+				LLSD face_entry = LLSD::emptyMap();
+				LLViewerFetchedTexture *texture = material.mDiffuseMap.get();
+				
+				if ((texture != NULL) &&
+					(textures.find(texture) == textures.end()))
 				{
-					textures.insert(material_iter->mDiffuseMap.get());
+					textures.insert(texture);
+				}
 
-					std::stringstream ostr;
-					if (include_textures) // otherwise data is blank.
-					{
-						LLTextureUploadData data(material_iter->mDiffuseMap.get(), material_iter->mDiffuseMapLabel);
-						if (!data.mTexture->isRawImageValid())
-						{
-							data.mTexture->reloadRawImage(data.mTexture->getDiscardLevel());
-						}
-						
+				std::stringstream texture_str;
+				if (texture != NULL && include_textures && mUploadTextures)
+				{
+					if(texture->hasSavedRawImage())
+					{											
 						LLPointer<LLImageJ2C> upload_file =
-							LLViewerTextureList::convertToUploadFile(data.mTexture->getRawImage());
-						ostr.write((const char*) upload_file->getData(), upload_file->getDataSize());
+							LLViewerTextureList::convertToUploadFile(texture->getSavedRawImage());
+						texture_str.write((const char*) upload_file->getData(), upload_file->getDataSize());
 					}
-					LLSD texture_entry;
-					texture_entry["texture_data"] = ostr.str();
-					res["texture_list"][texture_num] = texture_entry;
+				}
+
+				if (texture != NULL &&
+					mUploadTextures &&
+					texture_index.find(texture) == texture_index.end())
+				{
+					texture_index[texture] = texture_num;
+					std::string str = texture_str.str();
+					res["texture_list"][texture_num] = LLSD::Binary(str.begin(),str.end());
 					texture_num++;
 				}
-			}
-		}
 
-		mesh_num++;
+				// Subset of TextureEntry fields.
+				if (texture != NULL && mUploadTextures)
+				{
+					face_entry["image"] = texture_index[texture];
+					face_entry["scales"] = 1.0;
+					face_entry["scalet"] = 1.0;
+					face_entry["offsets"] = 0.0;
+					face_entry["offsett"] = 0.0;
+					face_entry["imagerot"] = 0.0;
+				}
+				face_entry["diffuse_color"] = ll_sd_from_color4(material.mDiffuseColor);
+				face_entry["fullbright"] = material.mFullbright;
+				instance_entry["face_list"][face_num] = face_entry;
+		    }
+
+			res["instance_list"][instance_num] = instance_entry;
+			instance_num++;
+		}
 	}
 
 	result["asset_resources"] = res;
-#if 1	
-	dumpLLSDToFile(result,"whole_model.xml");
-#endif
+	dump_llsd_to_file(result,make_dump_name("whole_model_",dump_num));
 
 	dest = result;
 }
 
 void LLMeshUploadThread::doWholeModelUpload()
 {
+	dump_num++;
+	
 	mCurlRequest = new LLCurlRequest();	
 
 	// Queue up models for hull generation (viewer-side)
@@ -1549,13 +1665,13 @@ void LLMeshUploadThread::doWholeModelUpload()
 			physics = data.mModel[LLModel::LOD_HIGH];
 		}
 
-		if (!physics)
-		{
-			llerrs << "WTF?" << llendl;
-		}
-
+		llassert(physics != NULL);
+		
 		DecompRequest* request = new DecompRequest(physics, data.mBaseModel, this);
-		gMeshRepo.mDecompThread->submitRequest(request);
+		if(request->isValid())
+		{
+			gMeshRepo.mDecompThread->submitRequest(request);
+		}		
 	}
 
 	while (!mPhysicsComplete)
@@ -1563,183 +1679,44 @@ void LLMeshUploadThread::doWholeModelUpload()
 		apr_sleep(100);
 	}
 
-	bool do_include_textures = false; // not needed for initial cost/validation check.
 	LLSD model_data;
-	wholeModelToLLSD(model_data, do_include_textures);
+	wholeModelToLLSD(model_data,false);
+	dump_llsd_to_file(model_data,make_dump_name("whole_model_fee_request_",dump_num));
 
 	mPendingUploads++;
 	LLCurlRequest::headers_t headers;
 	mCurlRequest->post(mWholeModelFeeCapability, headers, model_data,
-					   new LLWholeModelFeeResponder(this));
+					   new LLWholeModelFeeResponder(this,model_data));
 
 	do
 	{
 		mCurlRequest->process();
 	} while (mCurlRequest->getQueued() > 0);
 
-	mCurlRequest->post(mWholeModelUploadURL, headers, model_data["asset_resources"], new LLWholeModelUploadResponder(this));
-	
-	do
-	{
-		mCurlRequest->process();
-	} while (mCurlRequest->getQueued() > 0);
-
-	delete mCurlRequest;
-	mCurlRequest = NULL;
-
-	// Currently a no-op.
-	mFinished = true;
-}
-
-void LLMeshUploadThread::doIterativeUpload()
-{
-	if(isDiscarded())
-	{
-		mFinished = true;
-		return ;
-	}
-	
-	mCurlRequest = new LLCurlRequest();	
-
-	std::set<LLViewerTexture* > textures;
-
-	//populate upload queue with relevant models
-	for (instance_map::iterator iter = mInstance.begin(); iter != mInstance.end(); ++iter)
-	{
-		LLMeshUploadData data;
-		data.mBaseModel = iter->first;
-
-		LLModelInstance& instance = *(iter->second.begin());
-
-		for (S32 i = 0; i < 5; i++)
-		{
-			data.mModel[i] = instance.mLOD[i];
-		}
-
-		uploadModel(data);
-
-		if (mUploadTextures)
-		{
-			for (std::vector<LLImportMaterial>::iterator material_iter = instance.mMaterial.begin();
-				material_iter != instance.mMaterial.end(); ++material_iter)
-			{
-
-				if (textures.find(material_iter->mDiffuseMap.get()) == textures.end())
-				{
-					textures.insert(material_iter->mDiffuseMap.get());
-					
-					LLTextureUploadData data(material_iter->mDiffuseMap.get(), material_iter->mDiffuseMapLabel);
-					uploadTexture(data);
-				}
-			}
-		}
-
-		//queue up models for hull generation
-		DecompRequest* request = new DecompRequest(data.mModel[LLModel::LOD_HIGH], data.mBaseModel, this);
-		gMeshRepo.mDecompThread->submitRequest(request);
-	}
 
-	while (!mPhysicsComplete)
+	if (mWholeModelUploadURL.empty())
 	{
-		apr_sleep(100);
-	}
-
-	//upload textures
-	bool done = false;
-	do
-	{
-		if (!mTextureQ.empty())
-		{
-			sendCostRequest(mTextureQ.front());
-			mTextureQ.pop();
-		}
-
-		if (!mConfirmedTextureQ.empty())
-		{
-			doUploadTexture(mConfirmedTextureQ.front());
-			mConfirmedTextureQ.pop();
-		}
-
-		mCurlRequest->process();
-
-		done = mTextureQ.empty() && mConfirmedTextureQ.empty();
+		llinfos << "unable to upload, fee request failed" << llendl;
 	}
-	while (!done || mCurlRequest->getQueued() > 0);
-
-	LLSD object_asset;
-	object_asset["objects"] = LLSD::emptyArray();
-
-	done = false;
-	do 
+	else
 	{
-		static S32 count = 0;
-		static F32 last_hundred = gFrameTimeSeconds;
-		if (gFrameTimeSeconds - last_hundred > 1.f)
+		LLSD full_model_data;
+		wholeModelToLLSD(full_model_data, true);
+		LLSD body = full_model_data["asset_resources"];
+		dump_llsd_to_file(body,make_dump_name("whole_model_body_",dump_num));
+		mCurlRequest->post(mWholeModelUploadURL, headers, body,
+						   new LLWholeModelUploadResponder(this, model_data));
+		do
 		{
-			last_hundred = gFrameTimeSeconds;
-			count = 0;
-		}
-
-		//how many requests to push before calling process
-		const S32 PUSH_PER_PROCESS = 32;
-
-		S32 tcount = llmin(count+PUSH_PER_PROCESS, 100);
-
-		while (!mUploadQ.empty() && count < tcount)
-		{ //send any pending upload requests
-			mMutex->lock();
-			LLMeshUploadData data = mUploadQ.front();
-			mUploadQ.pop();
-			mMutex->unlock();
-			sendCostRequest(data);
-			count++;
-		}
-
-		tcount = llmin(count+PUSH_PER_PROCESS, 100);
-		
-		while (!mConfirmedQ.empty() && count < tcount)
-		{ //process any meshes that have been confirmed for upload
-			LLMeshUploadData& data = mConfirmedQ.front();
-			doUploadModel(data);
-			mConfirmedQ.pop();
-			count++;
-		}
-	
-		tcount = llmin(count+PUSH_PER_PROCESS, 100);
-
-		while (!mInstanceQ.empty() && count < tcount && !isDiscarded())
-		{ //create any objects waiting for upload
-			count++;
-			object_asset["objects"].append(createObject(mInstanceQ.front()));
-			mInstanceQ.pop();
-		}
-			
-		mCurlRequest->process();
-			
-		done = isDiscarded() || (mInstanceQ.empty() && mConfirmedQ.empty() && mUploadQ.empty());
+			mCurlRequest->process();
+		} while (mCurlRequest->getQueued() > 0);
 	}
-	while (!done || mCurlRequest->getQueued() > 0);
 
 	delete mCurlRequest;
 	mCurlRequest = NULL;
 
-	// now upload the object asset
-	std::string url = mUploadObjectAssetCapability;
-
-	if (object_asset["objects"][0].has("permissions"))
-	{ //copy permissions from first available object to be used for coalesced object
-		object_asset["permissions"] = object_asset["objects"][0]["permissions"];
-	}
-
-	if(!isDiscarded())
-	{
-		mPendingUploads++;
-		LLHTTPClient::post(url, object_asset, new LLModelObjectUploadResponder(this,object_asset));
-	}
-	else
-	{
-		mFinished = true;
-	}
+	// Currently a no-op.
+	mFinished = true;
 }
 
 void LLMeshUploadThread::uploadModel(LLMeshUploadData& data)
@@ -2170,7 +2147,7 @@ void LLMeshHeaderResponder::completedRaw(U32 status, const std::string& reason,
 		
 		//just in case skin info or decomposition is at the end of the file (which it shouldn't be)
 		lod_bytes = llmax(lod_bytes, header["skin"]["offset"].asInteger() + header["skin"]["size"].asInteger());
-		lod_bytes = llmax(lod_bytes, header["decomposition"]["offset"].asInteger() + header["decomposition"]["size"].asInteger());
+		lod_bytes = llmax(lod_bytes, header["physics_convex"]["offset"].asInteger() + header["physics_convex"]["size"].asInteger());
 
 		S32 header_bytes = (S32) gMeshRepo.mThread->mMeshHeaderSize[mesh_id];
 		S32 bytes = lod_bytes + header_bytes; 
@@ -2387,10 +2364,6 @@ S32 LLMeshRepository::loadMesh(LLVOVolume* vobj, const LLVolumeParams& mesh_para
 				group->derefLOD(lod);
 			}
 		}
-		else
-		{
-			llerrs << "WTF?" << llendl;
-		}
 	}
 
 	return detail;
@@ -2462,7 +2435,6 @@ void LLMeshRepository::notifyLoadedMeshes()
 		if (gAgent.getRegion()->getName() != region_name && gAgent.getRegion()->capabilitiesReceived())
 		{
 			region_name = gAgent.getRegion()->getName();
-		
 			mGetMeshCapability = gAgent.getRegion()->getCapability("GetMesh");
 		}
 	}
@@ -2570,6 +2542,20 @@ void LLMeshRepository::notifyLoadedMeshes()
 void LLMeshRepository::notifySkinInfoReceived(LLMeshSkinInfo& info)
 {
 	mSkinMap[info.mMeshID] = info;
+
+	skin_load_map::iterator iter = mLoadingSkins.find(info.mMeshID);
+	if (iter != mLoadingSkins.end())
+	{
+		for (std::set<LLUUID>::iterator obj_id = iter->second.begin(); obj_id != iter->second.end(); ++obj_id)
+		{
+			LLVOVolume* vobj = (LLVOVolume*) gObjectList.findObject(*obj_id);
+			if (vobj)
+			{
+				vobj->notifyMeshLoaded();
+			}
+		}
+	}
+
 	mLoadingSkins.erase(info.mMeshID);
 }
 
@@ -2685,7 +2671,7 @@ U32 LLMeshRepository::getResourceCost(const LLUUID& mesh_id)
 	return mThread->getResourceCost(mesh_id);
 }
 
-const LLMeshSkinInfo* LLMeshRepository::getSkinInfo(const LLUUID& mesh_id)
+const LLMeshSkinInfo* LLMeshRepository::getSkinInfo(const LLUUID& mesh_id, LLVOVolume* requesting_obj)
 {
 	if (mesh_id.notNull())
 	{
@@ -2699,12 +2685,12 @@ const LLMeshSkinInfo* LLMeshRepository::getSkinInfo(const LLUUID& mesh_id)
 		{
 			LLMutexLock lock(mMeshMutex);
 			//add volume to list of loading meshes
-			std::set<LLUUID>::iterator iter = mLoadingSkins.find(mesh_id);
+			skin_load_map::iterator iter = mLoadingSkins.find(mesh_id);
 			if (iter == mLoadingSkins.end())
 			{ //no request pending for this skin info
-				mLoadingSkins.insert(mesh_id);
 				mPendingSkinRequests.push(mesh_id);
 			}
+			mLoadingSkins[mesh_id].insert(requesting_obj->getID());
 		}
 	}
 
@@ -2786,7 +2772,18 @@ void LLMeshRepository::buildHull(const LLVolumeParams& params, S32 detail)
 bool LLMeshRepository::hasPhysicsShape(const LLUUID& mesh_id)
 {
 	LLSD mesh = mThread->getMeshHeader(mesh_id);
-	return mesh.has("physics_shape") && mesh["physics_shape"].has("size") && (mesh["physics_shape"]["size"].asInteger() > 0);
+	if (mesh.has("physics_mesh") && mesh["physics_mesh"].has("size") && (mesh["physics_mesh"]["size"].asInteger() > 0))
+	{
+		return true;
+	}
+
+	LLModel::Decomposition* decomp = getDecomposition(mesh_id);
+	if (decomp && !decomp->mHull.empty())
+	{
+		return true;
+	}
+
+	return false;
 }
 
 LLSD& LLMeshRepository::getMeshHeader(const LLUUID& mesh_id)
@@ -2842,102 +2839,6 @@ S32 LLMeshRepository::getMeshSize(const LLUUID& mesh_id, S32 lod)
 
 }
 
-void LLMeshUploadThread::sendCostRequest(LLMeshUploadData& data)
-{
-	if(isDiscarded())
-	{
-		return ;
-	}
-
-	//write model file to memory buffer
-	std::stringstream ostr;
-
-	LLModel::Decomposition& decomp =
-		data.mModel[LLModel::LOD_PHYSICS].notNull() ? 
-		data.mModel[LLModel::LOD_PHYSICS]->mPhysics : 
-		data.mBaseModel->mPhysics;
-
-	LLSD header = LLModel::writeModel(
-		ostr,
-		data.mModel[LLModel::LOD_PHYSICS],
-		data.mModel[LLModel::LOD_HIGH],
-		data.mModel[LLModel::LOD_MEDIUM],
-		data.mModel[LLModel::LOD_LOW],
-		data.mModel[LLModel::LOD_IMPOSTOR], 
-		decomp,
-		mUploadSkin,
-		mUploadJoints,
-		true);
-
-	std::string desc = data.mBaseModel->mLabel;
-	
-	// Grab the total vertex count of the model
-	// along with other information for the "asset_resources" map
-	// to send to the server.
-	LLSD asset_resources = LLSD::emptyMap();
-
-
-	std::string url = mNewInventoryCapability; 
-
-	if (!url.empty())
-	{
-		LLSD body = generate_new_resource_upload_capability_body(
-			LLAssetType::AT_MESH,
-			desc,
-			desc,
-			LLFolderType::FT_MESH,
-			LLInventoryType::IT_MESH,
-			LLFloaterPerms::getNextOwnerPerms(),
-			LLFloaterPerms::getGroupPerms(),
-			LLFloaterPerms::getEveryonePerms());
-
-		body["asset_resources"] = asset_resources;
-
-		mPendingConfirmations++;
-		LLCurlRequest::headers_t headers;
-
-		data.mPostData = body;
-
-		mCurlRequest->post(url, headers, body, new LLMeshCostResponder(data, this));
-	}	
-}
-
-void LLMeshUploadThread::sendCostRequest(LLTextureUploadData& data)
-{
-	if(isDiscarded())
-	{
-		return ;
-	}
-
-	if (data.mTexture && data.mTexture->getDiscardLevel() >= 0)
-	{
-		LLSD asset_resources = LLSD::emptyMap();
-
-		std::string url = mNewInventoryCapability; 
-
-		if (!url.empty())
-		{
-			LLSD body = generate_new_resource_upload_capability_body(
-				LLAssetType::AT_TEXTURE,
-				data.mLabel,
-				data.mLabel,
-				LLFolderType::FT_TEXTURE,
-				LLInventoryType::IT_TEXTURE,
-				LLFloaterPerms::getNextOwnerPerms(),
-				LLFloaterPerms::getGroupPerms(),
-				LLFloaterPerms::getEveryonePerms());
-
-			body["asset_resources"] = asset_resources;
-
-			mPendingConfirmations++;
-			LLCurlRequest::headers_t headers;
-			
-			data.mPostData = body;
-			mCurlRequest->post(url, headers, body, new LLTextureCostResponder(data, this));
-		}	
-	}
-}
-
 
 void LLMeshUploadThread::doUploadModel(LLMeshUploadData& data)
 {
@@ -2993,9 +2894,12 @@ void LLMeshUploadThread::doUploadTexture(LLTextureUploadData& data)
 			data.mTexture->reloadRawImage(data.mTexture->getDiscardLevel());
 		}
 
-		LLPointer<LLImageJ2C> upload_file = LLViewerTextureList::convertToUploadFile(data.mTexture->getRawImage());
+		if(data.mTexture->hasSavedRawImage())
+		{
+			LLPointer<LLImageJ2C> upload_file = LLViewerTextureList::convertToUploadFile(data.mTexture->getSavedRawImage());
 		
-		ostr.write((const char*) upload_file->getData(), upload_file->getDataSize());
+			ostr.write((const char*) upload_file->getData(), upload_file->getDataSize());
+		}
 
 		data.mAssetData = ostr.str();
 
@@ -3075,11 +2979,8 @@ LLSD LLMeshUploadThread::createObject(LLModelInstance& instance)
 {
 	LLMatrix4 transformation = instance.mTransform;
 
-	if (instance.mMeshID.isNull())
-	{
-		llerrs << "WTF?" << llendl;
-	}
-
+	llassert(instance.mMeshID.notNull());
+	
 	// check for reflection
 	BOOL reflected = (transformation.determinant() < 0);
 
@@ -3243,6 +3144,8 @@ bool LLImportMaterial::operator<(const LLImportMaterial &rhs) const
 void LLMeshRepository::updateInventory(inventory_data data)
 {
 	LLMutexLock lock(mMeshMutex);
+	dump_llsd_to_file(data.mPostData,make_dump_name("update_inventory_post_data_",dump_num));
+	dump_llsd_to_file(data.mResponse,make_dump_name("update_inventory_response_",dump_num));
 	mInventoryQ.push(data);
 }
 
@@ -3400,15 +3303,18 @@ void LLPhysicsDecomp::setMeshData(LLCDMeshData& mesh)
 	
 	mesh.mNumTriangles = mCurRequest->mIndices.size()/3;
 
-	LLCDResult ret = LLCD_OK;
-	if (LLConvexDecomposition::getInstance() != NULL)
+	if (mesh.mNumTriangles > 0 && mesh.mNumVertices > 2)
 	{
-		ret  = LLConvexDecomposition::getInstance()->setMeshData(&mesh);
-	}
+		LLCDResult ret = LLCD_OK;
+		if (LLConvexDecomposition::getInstance() != NULL)
+		{
+			ret  = LLConvexDecomposition::getInstance()->setMeshData(&mesh);
+		}
 
-	if (ret)
-	{
-		llerrs << "Convex Decomposition thread valid but could not set mesh data" << llendl;
+		if (ret)
+		{
+			llerrs << "Convex Decomposition thread valid but could not set mesh data" << llendl;
+		}
 	}
 }
 
@@ -3472,11 +3378,6 @@ void LLPhysicsDecomp::doDecomposition()
 		{
 			ret = LLConvexDecomposition::getInstance()->setParam(param->mName, value.asBoolean());
 		}
-
-		if (ret)
-		{
-			llerrs << "WTF?" << llendl;
-		}
 	}
 
 	mCurRequest->setStatusMessage("Executing.");
@@ -3771,6 +3672,81 @@ void LLPhysicsDecomp::run()
 	mDone = true;
 }
 
+void LLPhysicsDecomp::Request::assignData(LLModel* mdl) 
+{
+	if (!mdl)
+	{
+		return ;
+	}
+
+	U16 index_offset = 0;
+	U16 tri[3] ;
+
+	mPositions.clear();
+	mIndices.clear();
+	mBBox[1] = LLVector3(F32_MIN, F32_MIN, F32_MIN) ;
+	mBBox[0] = LLVector3(F32_MAX, F32_MAX, F32_MAX) ;
+		
+	//queue up vertex positions and indices
+	for (S32 i = 0; i < mdl->getNumVolumeFaces(); ++i)
+	{
+		const LLVolumeFace& face = mdl->getVolumeFace(i);
+		if (mPositions.size() + face.mNumVertices > 65535)
+		{
+			continue;
+		}
+
+		for (U32 j = 0; j < face.mNumVertices; ++j)
+		{
+			mPositions.push_back(LLVector3(face.mPositions[j].getF32ptr()));
+			for(U32 k = 0 ; k < 3 ; k++)
+			{
+				mBBox[0].mV[k] = llmin(mBBox[0].mV[k], mPositions[j].mV[k]) ;
+				mBBox[1].mV[k] = llmax(mBBox[1].mV[k], mPositions[j].mV[k]) ;
+			}
+		}
+
+		updateTriangleAreaThreshold() ;
+
+		for (U32 j = 0; j+2 < face.mNumIndices; j += 3)
+		{
+			tri[0] = face.mIndices[j] + index_offset ;
+			tri[1] = face.mIndices[j + 1] + index_offset ;
+			tri[2] = face.mIndices[j + 2] + index_offset ;
+				
+			if(isValidTriangle(tri[0], tri[1], tri[2]))
+			{
+				mIndices.push_back(tri[0]);
+				mIndices.push_back(tri[1]);
+				mIndices.push_back(tri[2]);
+			}
+		}
+
+		index_offset += face.mNumVertices;
+	}
+
+	return ;
+}
+
+void LLPhysicsDecomp::Request::updateTriangleAreaThreshold() 
+{
+	F32 range = mBBox[1].mV[0] - mBBox[0].mV[0] ;
+	range = llmin(range, mBBox[1].mV[1] - mBBox[0].mV[1]) ;
+	range = llmin(range, mBBox[1].mV[2] - mBBox[0].mV[2]) ;
+
+	mTriangleAreaThreshold = llmin(0.0002f, range * 0.000002f) ;
+}
+
+//check if the triangle area is large enough to qualify for a valid triangle
+bool LLPhysicsDecomp::Request::isValidTriangle(U16 idx1, U16 idx2, U16 idx3) 
+{
+	LLVector3 a = mPositions[idx2] - mPositions[idx1] ;
+	LLVector3 b = mPositions[idx3] - mPositions[idx1] ;
+	F32 c = a * b ;
+
+	return ((a*a) * (b*b) - c * c) > mTriangleAreaThreshold ;
+}
+
 void LLPhysicsDecomp::Request::setStatusMessage(const std::string& msg)
 {
 	mStatusMessage = msg;
@@ -3868,3 +3844,27 @@ void LLMeshRepository::buildPhysicsMesh(LLModel::Decomposition& decomp)
 		}
 	}
 }
+
+
+bool LLMeshRepository::meshUploadEnabled()
+{
+	LLViewerRegion *region = gAgent.getRegion();
+	if(gSavedSettings.getBOOL("MeshEnabled") && 
+	   LLViewerParcelMgr::getInstance()->allowAgentBuild() &&
+	   region)
+	{
+		return region->meshUploadEnabled();
+	}
+	return false;
+}
+
+bool LLMeshRepository::meshRezEnabled()
+{
+	LLViewerRegion *region = gAgent.getRegion();
+	if(gSavedSettings.getBOOL("MeshEnabled") && 
+	   region)
+	{
+		return region->meshRezEnabled();
+	}
+	return false;
+}
diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h
index f859e29c0789778440fdb1158324024348dad163..f237c3a60e6cbdc9ad8134aad4b1c2966ac9b6b6 100644
--- a/indra/newview/llmeshrepository.h
+++ b/indra/newview/llmeshrepository.h
@@ -152,7 +152,7 @@ class LLPhysicsDecomp : public LLThread
 		std::string mStatusMessage;
 		std::vector<LLModel::PhysicsMesh> mHullMesh;
 		LLModel::convex_hull_decomposition mHull;
-		
+			
 		//status message callback, called from decomposition thread
 		virtual S32 statusCallback(const char* status, S32 p1, S32 p2) = 0;
 
@@ -160,6 +160,17 @@ class LLPhysicsDecomp : public LLThread
 		virtual void completed() = 0;
 
 		virtual void setStatusMessage(const std::string& msg);
+
+		bool isValid() const {return mPositions.size() > 2 && mIndices.size() > 2 ;}
+
+	protected:
+		//internal use
+		LLVector3 mBBox[2] ;
+		F32 mTriangleAreaThreshold ;
+
+		void assignData(LLModel* mdl) ;
+		void updateTriangleAreaThreshold() ;
+		bool isValidTriangle(U16 idx1, U16 idx2, U16 idx3) ;
 	};
 
 	LLCondition* mSignal;
@@ -385,8 +396,6 @@ class LLMeshUploadThread : public LLThread
 	BOOL            mDiscarded ;
 
 	LLHost			mHost;
-	std::string		mUploadObjectAssetCapability;
-	std::string		mNewInventoryCapability;
 	std::string		mWholeModelFeeCapability;
 	std::string		mWholeModelUploadURL;
 
@@ -405,12 +414,10 @@ class LLMeshUploadThread : public LLThread
 
 	void uploadTexture(LLTextureUploadData& data);
 	void doUploadTexture(LLTextureUploadData& data);
-	void sendCostRequest(LLTextureUploadData& data);
 	void priceResult(LLTextureUploadData& data, const LLSD& content);
 	void onTextureUploaded(LLTextureUploadData& data);
 
 	void uploadModel(LLMeshUploadData& data);
-	void sendCostRequest(LLMeshUploadData& data);
 	void doUploadModel(LLMeshUploadData& data);
 	void onModelUploaded(LLMeshUploadData& data);
 	void createObjects(LLMeshUploadData& data);
@@ -424,7 +431,6 @@ class LLMeshUploadThread : public LLThread
 	BOOL isDiscarded();
 
 	void doWholeModelUpload();
-	void doIterativeUpload();
 
 	void wholeModelToLLSD(LLSD& dest, bool include_textures);
 
@@ -467,13 +473,17 @@ class LLMeshRepository
 	static S32 getActualMeshLOD(LLSD& header, S32 lod);
 	U32 calcResourceCost(LLSD& header);
 	U32 getResourceCost(const LLUUID& mesh_params);
-	const LLMeshSkinInfo* getSkinInfo(const LLUUID& mesh_id);
+	const LLMeshSkinInfo* getSkinInfo(const LLUUID& mesh_id, LLVOVolume* requesting_obj);
 	LLModel::Decomposition* getDecomposition(const LLUUID& mesh_id);
 	void fetchPhysicsShape(const LLUUID& mesh_id);
 	bool hasPhysicsShape(const LLUUID& mesh_id);
 	
 	void buildHull(const LLVolumeParams& params, S32 detail);
 	void buildPhysicsMesh(LLModel::Decomposition& decomp);
+	
+	bool meshUploadEnabled();
+	bool meshRezEnabled();
+	
 
 	LLSD& getMeshHeader(const LLUUID& mesh_id);
 
@@ -496,7 +506,8 @@ class LLMeshRepository
 	std::vector<LLMeshRepoThread::LODRequest> mPendingRequests;
 	
 	//list of mesh ids awaiting skin info
-	std::set<LLUUID> mLoadingSkins;
+	typedef std::map<LLUUID, std::set<LLUUID> > skin_load_map;
+	skin_load_map mLoadingSkins;
 
 	//list of mesh ids that need to send skin info fetch requests
 	std::queue<LLUUID> mPendingSkinRequests;
diff --git a/indra/newview/llpanelobject.cpp b/indra/newview/llpanelobject.cpp
index b4d0ada19655a25b5f45ddbf1b9bc435edb13be1..52917ff20b3dfbe5e30fca4c53c52a47cf8496be 100644
--- a/indra/newview/llpanelobject.cpp
+++ b/indra/newview/llpanelobject.cpp
@@ -1740,26 +1740,11 @@ void LLPanelObject::refresh()
 		mRootObject = NULL;
 	}
 	
-	bool enable_mesh = gSavedSettings.getBOOL("MeshEnabled") && 
-					   gAgent.getRegion() &&
-					   !gAgent.getRegion()->getCapability("GetMesh").empty() &&
-					   !gAgent.getRegion()->getCapability("ObjectAdd").empty();
-
 	F32 max_scale = get_default_max_prim_scale(LLPickInfo::isFlora(mObject));
 
 	getChild<LLSpinCtrl>("Scale X")->setMaxValue(max_scale);
 	getChild<LLSpinCtrl>("Scale Y")->setMaxValue(max_scale);
 	getChild<LLSpinCtrl>("Scale Z")->setMaxValue(max_scale);
-
-	BOOL found = mCtrlSculptType->itemExists("Mesh");
-	if (enable_mesh && !found)
-	{
-		mCtrlSculptType->add("Mesh");
-	}
-	else if (!enable_mesh && found)
-	{
-		mCtrlSculptType->remove("Mesh");
-	}
 }
 
 
diff --git a/indra/newview/llpanelvolume.cpp b/indra/newview/llpanelvolume.cpp
index 7839cdd811141bd20924dea1cd43f409f38359b5..bb87601d2017fd6ef22bcd828d757d2057bc766e 100644
--- a/indra/newview/llpanelvolume.cpp
+++ b/indra/newview/llpanelvolume.cpp
@@ -530,17 +530,24 @@ void LLPanelVolume::refresh()
 	getChildView("Light Ambiance")->setVisible( visible);
 	getChildView("light texture control")->setVisible( visible);
 
-	bool enable_mesh = gSavedSettings.getBOOL("MeshEnabled") && 
-					   gAgent.getRegion() &&
-					   !gAgent.getRegion()->getCapability("GetMesh").empty() &&
-					   !gAgent.getRegion()->getCapability("ObjectAdd").empty();
+	bool enable_mesh = false;
 
+	LLSD sim_features;
+	LLViewerRegion *region = gAgent.getRegion();
+	if(region)
+	{
+		LLSD sim_features;
+		region->getSimulatorFeatures(sim_features);		 
+		enable_mesh = sim_features.has("PhysicsShapeTypes");
+	}
 	getChildView("label physicsshapetype")->setVisible(enable_mesh);
 	getChildView("Physics Shape Type Combo Ctrl")->setVisible(enable_mesh);
 	getChildView("Physics Gravity")->setVisible(enable_mesh);
 	getChildView("Physics Friction")->setVisible(enable_mesh);
 	getChildView("Physics Density")->setVisible(enable_mesh);
 	getChildView("Physics Restitution")->setVisible(enable_mesh);
+	
+    /* TODO: add/remove individual physics shape types as per the PhysicsShapeTypes simulator features */
 }
 
 
diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp
index fa329eb0ae0271807132e0a46f576214dd5ebbd3..a5b91729e856f1dbb018b8ec53e5917c95c15081 100644
--- a/indra/newview/llspatialpartition.cpp
+++ b/indra/newview/llspatialpartition.cpp
@@ -35,6 +35,7 @@
 #include "llvolumeoctree.h"
 #include "llviewercamera.h"
 #include "llface.h"
+#include "llfloatertools.h"
 #include "llviewercontrol.h"
 #include "llviewerregion.h"
 #include "llcamera.h"
@@ -69,6 +70,7 @@ U32 LLSpatialGroup::sNodeCount = 0;
 
 std::set<GLuint> LLSpatialGroup::sPendingQueries;
 
+U32 gOctreeMaxCapacity;
 
 BOOL LLSpatialGroup::sNoDelete = FALSE;
 
@@ -630,7 +632,7 @@ BOOL LLSpatialGroup::updateInGroup(LLDrawable *drawablep, BOOL immediate)
 	if (mOctreeNode->isInside(drawablep->getPositionGroup()) && 
 		(mOctreeNode->contains(drawablep) ||
 		 (drawablep->getBinRadius() > mOctreeNode->getSize()[0] &&
-				parent && parent->getElementCount() >= LL_OCTREE_MAX_CAPACITY)))
+				parent && parent->getElementCount() >= gOctreeMaxCapacity)))
 	{
 		unbound();
 		setState(OBJECT_DIRTY);
@@ -689,17 +691,8 @@ static LLFastTimer::DeclareTimer FTM_REBUILD_VBO("VBO Rebuilt");
 
 void LLSpatialPartition::rebuildGeom(LLSpatialGroup* group)
 {
-	/*if (!gPipeline.hasRenderType(mDrawableType))
-	{
-		return;
-	}*/
-
 	if (group->isDead() || !group->isState(LLSpatialGroup::GEOM_DIRTY))
 	{
-		/*if (!group->isState(LLSpatialGroup::GEOM_DIRTY) && mRenderByGroup)
-		{
-			llerrs << "WTF?" << llendl;
-		}*/
 		return;
 	}
 
@@ -961,21 +954,15 @@ void LLSpatialGroup::setState(U32 state)
 { 
 	mState |= state; 
 	
-	if (state > LLSpatialGroup::STATE_MASK)
-	{
-		llerrs << "WTF?" << llendl;
-	}
+	llassert(state <= LLSpatialGroup::STATE_MASK);
 }	
 
 void LLSpatialGroup::setState(U32 state, S32 mode) 
 {
 	LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
 
-	if (state > LLSpatialGroup::STATE_MASK)
-	{
-		llerrs << "WTF?" << llendl;
-	}
-
+	llassert(state <= LLSpatialGroup::STATE_MASK);
+	
 	if (mode > STATE_MODE_SINGLE)
 	{
 		if (mode == STATE_MODE_DIFF)
@@ -1021,20 +1008,14 @@ class LLSpatialClearStateDiff : public LLSpatialClearState
 
 void LLSpatialGroup::clearState(U32 state)
 {
-	if (state > LLSpatialGroup::STATE_MASK)
-	{
-		llerrs << "WTF?" << llendl;
-	}
+	llassert(state <= LLSpatialGroup::STATE_MASK);
 
 	mState &= ~state; 
 }
 
 void LLSpatialGroup::clearState(U32 state, S32 mode)
 {
-	if (state > LLSpatialGroup::STATE_MASK)
-	{
-		llerrs << "WTF?" << llendl;
-	}
+	llassert(state <= LLSpatialGroup::STATE_MASK);
 
 	LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
 	
@@ -1059,10 +1040,7 @@ void LLSpatialGroup::clearState(U32 state, S32 mode)
 
 BOOL LLSpatialGroup::isState(U32 state) const
 { 
-	if (state > LLSpatialGroup::STATE_MASK)
-	{
-		llerrs << "WTF?" << llendl;
-	}
+	llassert(state <= LLSpatialGroup::STATE_MASK);
 
 	return mState & state ? TRUE : FALSE; 
 }
@@ -1250,7 +1228,8 @@ void LLSpatialGroup::updateDistance(LLCamera &camera)
 {
 	if (LLViewerCamera::sCurCameraID != LLViewerCamera::CAMERA_WORLD)
 	{
-		llerrs << "WTF?" << llendl;
+		llwarns << "Attempted to update distance for camera other than world camera!" << llendl;
+		return;
 	}
 
 #if !LL_RELEASE_FOR_DOWNLOAD
@@ -2064,11 +2043,8 @@ class LLOctreeCullVisExtents: public LLOctreeCullShadow
 
 	virtual void processGroup(LLSpatialGroup* group)
 	{
-		if (group->isState(LLSpatialGroup::DIRTY) || group->getData().empty())
-		{
-			llerrs << "WTF?" << llendl;
-		}
-
+		llassert(!group->isState(LLSpatialGroup::DIRTY) && !group->getData().empty())
+		
 		if (mRes < 2)
 		{
 			if (mCamera->AABBInFrustum(group->mObjectBounds[0], group->mObjectBounds[1]) > 0)
@@ -2541,7 +2517,7 @@ void renderOctree(LLSpatialGroup* group)
 	//coded by buffer usage and activity
 	gGL.setSceneBlendType(LLRender::BT_ADD_WITH_ALPHA);
 	LLVector4 col;
-	if (group->mBuilt > 0.f)
+	/*if (group->mBuilt > 0.f)
 	{
 		group->mBuilt -= 2.f * gFrameIntervalSeconds;
 		if (group->mBufferUsage == GL_STATIC_DRAW_ARB)
@@ -2610,7 +2586,7 @@ void renderOctree(LLSpatialGroup* group)
 			gGL.color4f(1,1,1,1);
 		}
 	}
-	else
+	else*/
 	{
 		if (group->mBufferUsage == GL_STATIC_DRAW_ARB && !group->getData().empty() 
 			&& group->mSpatialPartition->mRenderByGroup)
@@ -2630,33 +2606,24 @@ void renderOctree(LLSpatialGroup* group)
 	size.mul(1.01f);
 	size.add(fudge);
 
-	{
-		LLGLDepthTest depth(GL_TRUE, GL_FALSE);
-		drawBox(group->mObjectBounds[0], fudge);
-	}
+	//{
+	//	LLGLDepthTest depth(GL_TRUE, GL_FALSE);
+	//	drawBox(group->mObjectBounds[0], fudge);
+	//}
 	
 	gGL.setSceneBlendType(LLRender::BT_ALPHA);
 
-	if (group->mBuilt <= 0.f)
+	//if (group->mBuilt <= 0.f)
 	{
 		//draw opaque outline
-		gGL.color4f(col.mV[0], col.mV[1], col.mV[2], 1.f);
-		drawBoxOutline(group->mObjectBounds[0], group->mObjectBounds[1]);
+		//gGL.color4f(col.mV[0], col.mV[1], col.mV[2], 1.f);
+		//drawBoxOutline(group->mObjectBounds[0], group->mObjectBounds[1]);
 
-		if (group->mOctreeNode->isLeaf())
-		{
-			gGL.color4f(1,1,1,1);
-		}
-		else
-		{
-			gGL.color4f(0,1,1,1);
-		}
-						
+		gGL.color4f(0,1,1,1);
 		drawBoxOutline(group->mBounds[0],group->mBounds[1]);
-
-
+		
 		//draw bounding box for draw info
-		if (group->mSpatialPartition->mRenderByGroup)
+		/*if (group->mSpatialPartition->mRenderByGroup)
 		{
 			gGL.color4f(1.0f, 0.75f, 0.25f, 0.6f);
 			for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i)
@@ -2673,7 +2640,7 @@ void renderOctree(LLSpatialGroup* group)
 					drawBoxOutline(center, size);
 				}
 			}
-		}
+		}*/
 	}
 	
 //	LLSpatialGroup::OctreeNode* node = group->mOctreeNode;
@@ -2716,7 +2683,7 @@ void renderVisibility(LLSpatialGroup* group, LLCamera* camera)
 			gGL.color4f(0.f, 0.75f, 0.f, 0.5f);
 			pushBufferVerts(group, LLVertexBuffer::MAP_VERTEX);
 		}
-		else if (camera && group->mOcclusionVerts.notNull())
+		/*else if (camera && group->mOcclusionVerts.notNull())
 		{
 			LLVertexBuffer::unbind();
 			group->mOcclusionVerts->setBuffer(LLVertexBuffer::MAP_VERTEX);
@@ -2728,7 +2695,7 @@ void renderVisibility(LLSpatialGroup* group, LLCamera* camera)
 			glColor4f(1.0f, 1.f, 1.f, 1.0f);
 			group->mOcclusionVerts->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, group->mBounds[0]));
 			glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
-		}
+		}*/
 	}
 }
 
@@ -3002,13 +2969,6 @@ void render_hull(LLModel::PhysicsMesh& mesh, const LLColor4& color, const LLColo
 
 void renderPhysicsShape(LLDrawable* drawable, LLVOVolume* volume)
 {
-	if (volume->isSelected())
-	{
-		LLVector3 construct_me(5,5,5);
-		construct_me.normalize();
-	}
-
-	
 	U8 physics_type = volume->getPhysicsShapeType();
 
 	if (physics_type == LLViewerObject::PHYSICS_SHAPE_NONE || volume->isFlexible())
@@ -3473,6 +3433,8 @@ void renderTextureAnim(LLDrawInfo* params)
 
 void renderBatchSize(LLDrawInfo* params)
 {
+	LLGLEnable offset(GL_POLYGON_OFFSET_FILL);
+	glPolygonOffset(-1.f, 1.f);
 	glColor3ubv((GLubyte*) &(params->mDebugColor));
 	pushVerts(params, LLVertexBuffer::MAP_VERTEX);
 }
@@ -3910,6 +3872,28 @@ class LLOctreeRenderNonOccluded : public LLOctreeTraveler<LLDrawable>
 				renderAgentTarget(avatar);
 			}
 			
+			if (gDebugGL)
+			{
+				for (U32 i = 0; i < drawable->getNumFaces(); ++i)
+				{
+					LLFace* facep = drawable->getFace(i);
+					U8 index = facep->getTextureIndex();
+					if (facep->mDrawInfo)
+					{
+						if (index < 255)
+						{
+							if (facep->mDrawInfo->mTextureList.size() <= index)
+							{
+								llerrs << "Face texture index out of bounds." << llendl;
+							}
+							else if (facep->mDrawInfo->mTextureList[index] != facep->getTexture())
+							{
+								llerrs << "Face texture index incorrect." << llendl;
+							}
+						}
+					}
+				}
+			}
 		}
 		
 		for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i)
@@ -4282,7 +4266,29 @@ class LLOctreeIntersect : public LLSpatialGroup::OctreeTraveler
 			if (vobj)
 			{
 				LLVector3 intersection;
-				if (vobj->lineSegmentIntersect(mStart, mEnd, -1, mPickTransparent, mFaceHit, &intersection, mTexCoord, mNormal, mBinormal))
+				bool skip_check = false;
+				if (vobj->isAvatar())
+				{
+					LLVOAvatar* avatar = (LLVOAvatar*) vobj;
+					if (avatar->isSelf() && LLFloater::isVisible(gFloaterTools))
+					{
+						LLViewerObject* hit = avatar->lineSegmentIntersectRiggedAttachments(mStart, mEnd, -1, mPickTransparent, mFaceHit, &intersection, mTexCoord, mNormal, mBinormal);
+						if (hit)
+						{
+							mEnd = intersection;
+							if (mIntersection)
+							{
+								*mIntersection = intersection;
+							}
+							
+							mHit = hit->mDrawable;
+							skip_check = true;
+						}
+
+					}
+				}
+
+				if (!skip_check && vobj->lineSegmentIntersect(mStart, mEnd, -1, mPickTransparent, mFaceHit, &intersection, mTexCoord, mNormal, mBinormal))
 				{
 					mEnd = intersection;  // shorten ray so we only find CLOSER hits
 					if (mIntersection)
diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h
index 0d9cad914a55755344cc062719da89ec364a05d7..db8a0c29926a6b7d4356b5813c7c48c163175766 100644
--- a/indra/newview/llspatialpartition.h
+++ b/indra/newview/llspatialpartition.h
@@ -91,6 +91,8 @@ class LLDrawInfo : public LLRefCount
 	
 	LLPointer<LLVertexBuffer> mVertexBuffer;
 	LLPointer<LLViewerTexture>     mTexture;
+	std::vector<LLPointer<LLViewerTexture> > mTextureList;
+
 	LLColor4U mGlowColor;
 	S32 mDebugColor;
 	const LLMatrix4* mTextureMatrix;
@@ -207,7 +209,7 @@ class LLSpatialGroup : public LLOctreeListener<LLDrawable>
 	typedef std::vector<LLPointer<LLDrawInfo> > drawmap_elem_t; 
 	typedef std::map<U32, drawmap_elem_t > draw_map_t;	
 	typedef std::vector<LLPointer<LLVertexBuffer> > buffer_list_t;
-	typedef std::map<LLPointer<LLViewerTexture>, buffer_list_t> buffer_texture_map_t;
+	typedef std::map<LLFace*, buffer_list_t> buffer_texture_map_t;
 	typedef std::map<U32, buffer_texture_map_t> buffer_map_t;
 
 	typedef LLOctreeListener<LLDrawable>	BaseType;
@@ -399,7 +401,7 @@ class LLSpatialGroup : public LLOctreeListener<LLDrawable>
 
 public:
 	bridge_list_t mBridgeList;
-	buffer_map_t mBufferMap; //used by volume buffers to store unique buffers per texture
+	buffer_map_t mBufferMap; //used by volume buffers to attempt to reuse vertex buffers
 
 	F32 mBuilt;
 	OctreeNode* mOctreeNode;
@@ -684,7 +686,7 @@ class LLVolumeGeometryManager: public LLGeometryManager
 	virtual void rebuildGeom(LLSpatialGroup* group);
 	virtual void rebuildMesh(LLSpatialGroup* group);
 	virtual void getGeometry(LLSpatialGroup* group);
-	void genDrawInfo(LLSpatialGroup* group, U32 mask, std::vector<LLFace*>& faces, BOOL distance_sort = FALSE);
+	void genDrawInfo(LLSpatialGroup* group, U32 mask, std::vector<LLFace*>& faces, BOOL distance_sort = FALSE, BOOL batch_textures = FALSE);
 	void registerFace(LLSpatialGroup* group, LLFace* facep, U32 type);
 };
 
diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp
index 379bbe614d62161a5d83a0cabd4cca2830c4db84..87ca80260f4337a52e6dc54bceb31c2708651525 100644
--- a/indra/newview/llviewercontrol.cpp
+++ b/indra/newview/llviewercontrol.cpp
@@ -57,6 +57,7 @@
 #include "llworld.h"
 #include "pipeline.h"
 #include "llviewerjoystick.h"
+#include "llviewerobjectlist.h"
 #include "llviewerparcelmgr.h"
 #include "llparcel.h"
 #include "llkeyboard.h"
@@ -183,6 +184,21 @@ static bool handleReleaseGLBufferChanged(const LLSD& newvalue)
 	return true;
 }
 
+static bool handleFSAASamplesChanged(const LLSD& newvalue)
+{
+	if (gPipeline.isInit())
+	{
+		gPipeline.releaseGLBuffers();
+		gPipeline.createGLBuffers();
+
+		if (LLPipeline::sRenderDeferred)
+		{
+			LLViewerShaderMgr::instance()->setShaders();
+		}
+	}
+	return true;
+}
+
 static bool handleAnisotropicChanged(const LLSD& newvalue)
 {
 	LLImageGL::sGlobalUseAnisotropic = newvalue.asBoolean();
@@ -357,6 +373,16 @@ static bool handleResetVertexBuffersChanged(const LLSD&)
 	return true;
 }
 
+static bool handleRepartition(const LLSD&)
+{
+	if (gPipeline.isInit())
+	{
+		gOctreeMaxCapacity = gSavedSettings.getU32("OctreeMaxNodeCapacity");
+		gObjectList.repartitionObjects();
+	}
+	return true;
+}
+
 static bool handleRenderDynamicLODChanged(const LLSD& newvalue)
 {
 	LLPipeline::sDynamicLOD = newvalue.asBoolean();
@@ -560,6 +586,12 @@ void settings_setup_listeners()
 	gSavedSettings.getControl("FirstPersonAvatarVisible")->getSignal()->connect(boost::bind(&handleRenderAvatarMouselookChanged, _2));
 	gSavedSettings.getControl("RenderFarClip")->getSignal()->connect(boost::bind(&handleRenderFarClipChanged, _2));
 	gSavedSettings.getControl("RenderTerrainDetail")->getSignal()->connect(boost::bind(&handleTerrainDetailChanged, _2));
+	gSavedSettings.getControl("OctreeStaticObjectSizeFactor")->getSignal()->connect(boost::bind(&handleRepartition, _2));
+	gSavedSettings.getControl("OctreeDistanceFactor")->getSignal()->connect(boost::bind(&handleRepartition, _2));
+	gSavedSettings.getControl("OctreeMaxNodeCapacity")->getSignal()->connect(boost::bind(&handleRepartition, _2));
+	gSavedSettings.getControl("OctreeAlphaDistanceFactor")->getSignal()->connect(boost::bind(&handleRepartition, _2));
+	gSavedSettings.getControl("OctreeAttachmentSizeFactor")->getSignal()->connect(boost::bind(&handleRepartition, _2));
+	gSavedSettings.getControl("RenderMaxTextureIndex")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2));
 	gSavedSettings.getControl("RenderUseTriStrips")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2));
 	gSavedSettings.getControl("RenderAnimateTrees")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2));
 	gSavedSettings.getControl("RenderAvatarVP")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2));
@@ -568,7 +600,7 @@ void settings_setup_listeners()
 	gSavedSettings.getControl("RenderSpecularResX")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2));
 	gSavedSettings.getControl("RenderSpecularResY")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2));
 	gSavedSettings.getControl("RenderSpecularExponent")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2));
-	gSavedSettings.getControl("RenderFSAASamples")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2));
+	gSavedSettings.getControl("RenderFSAASamples")->getSignal()->connect(boost::bind(&handleFSAASamplesChanged, _2));
 	gSavedSettings.getControl("RenderAnisotropic")->getSignal()->connect(boost::bind(&handleAnisotropicChanged, _2));
 	gSavedSettings.getControl("RenderShadowResolutionScale")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2));
 	gSavedSettings.getControl("RenderGlow")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2));
diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp
index e41773d27365d3d986fcd7bdb7d805b6adc90d37..f725f0fe86d4e45c19172775b909c186eb474ec2 100644
--- a/indra/newview/llviewerdisplay.cpp
+++ b/indra/newview/llviewerdisplay.cpp
@@ -582,6 +582,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
 			LLMemType mt_ug(LLMemType::MTYPE_DISPLAY_UPDATE_GEOM);
 			const F32 max_geom_update_time = 0.005f*10.f*gFrameIntervalSeconds; // 50 ms/second update time
 			gPipeline.createObjects(max_geom_update_time);
+			gPipeline.processPartitionQ();
 			gPipeline.updateGeom(max_geom_update_time);
 			stop_glerror();
 		}
@@ -836,7 +837,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
 			if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender)
 			{
 				gPipeline.mDeferredScreen.bindTarget();
-				glClearColor(0,0,0,0);
+				glClearColor(1,0,1,1);
 				gPipeline.mDeferredScreen.clear();
 			}
 			else
@@ -995,8 +996,7 @@ void render_hud_attachments()
 
 		S32 use_occlusion = LLPipeline::sUseOcclusion;
 		LLPipeline::sUseOcclusion = 0;
-		LLPipeline::sDisableShaders = TRUE;
-		
+				
 		//cull, sort, and render hud objects
 		static LLCullResult result;
 		LLSpatialGroup::sNoDelete = TRUE;
@@ -1036,7 +1036,6 @@ void render_hud_attachments()
 			gPipeline.toggleRenderDebugFeature((void*) LLPipeline::RENDER_DEBUG_FEATURE_UI);
 		}
 		LLPipeline::sUseOcclusion = use_occlusion;
-		LLPipeline::sDisableShaders = FALSE;
 	}
 	glMatrixMode(GL_PROJECTION);
 	glPopMatrix();
diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp
index 37640ad0d45ea7cd4a62de1b5ecd2b29e3e394e4..b9293b3b3105f8c9a1ebaef7e2752b97df21728a 100644
--- a/indra/newview/llviewermenufile.cpp
+++ b/indra/newview/llviewermenufile.cpp
@@ -107,9 +107,7 @@ class LLMeshUploadVisible : public view_listener_t
 {
 	bool handleEvent(const LLSD& userdata)
 	{
-		return gSavedSettings.getBOOL("MeshEnabled") && 
-			   LLViewerParcelMgr::getInstance()->allowAgentBuild() && 
-			   !gAgent.getRegion()->getCapability("ObjectAdd").empty();
+		return gMeshRepo.meshUploadEnabled();
 	}
 };
 
@@ -1203,78 +1201,6 @@ void upload_new_resource(
 	}
 }
 
-BOOL upload_new_variable_price_resource(
-	const LLTransactionID &tid, 
-	LLAssetType::EType asset_type,
-	std::string name,
-	std::string desc, 
-	LLFolderType::EType destination_folder_type,
-	LLInventoryType::EType inv_type,
-	U32 next_owner_perms,
-	U32 group_perms,
-	U32 everyone_perms,
-	const std::string& display_name,
-	const LLSD& asset_resources)
-{
-	LLAssetID uuid = 
-		upload_new_resource_prep(
-			tid,
-			asset_type,
-			inv_type,
-			name,
-			display_name,
-			desc);
-
-	llinfos << "*** Uploading: " << llendl;
-	llinfos << "Type: " << LLAssetType::lookup(asset_type) << llendl;
-	llinfos << "UUID: " << uuid << llendl;
-	llinfos << "Name: " << name << llendl;
-	llinfos << "Desc: " << desc << llendl;
-	lldebugs << "Folder: "
-		<< gInventory.findCategoryUUIDForType((destination_folder_type == LLFolderType::FT_NONE) ? (LLFolderType::EType)asset_type : destination_folder_type) << llendl;
-	lldebugs << "Asset Type: " << LLAssetType::lookup(asset_type) << llendl;
-
-	std::string url = gAgent.getRegion()->getCapability(
-		"NewFileAgentInventoryVariablePrice");
-
-	if ( !url.empty() )
-	{
-		lldebugs
-			<< "New Agent Inventory variable price upload" << llendl;
-		
-		// Each of the two capabilities has similar data, so
-		// let's reuse that code
-
-		LLSD body;
-
-		body = generate_new_resource_upload_capability_body(
-			asset_type,
-			name,
-			desc,
-			destination_folder_type,
-			inv_type,
-			next_owner_perms,
-			group_perms,
-			everyone_perms);
-
-		body["asset_resources"] = asset_resources;
-
-		LLHTTPClient::post(
-			url,
-			body,
-			new LLNewAgentInventoryVariablePriceResponder(
-				uuid,
-				asset_type,
-				body));
-
-		return TRUE;
-	}
-	else
-	{
-		return FALSE;
-	}
-}
-
 LLAssetID generate_asset_id_for_new_upload(const LLTransactionID& tid)
 {
 	if ( gDisconnected )
diff --git a/indra/newview/llviewermenufile.h b/indra/newview/llviewermenufile.h
index 1597821504269e9d752e5621bed2765f2cbf0ab3..3136358b83653e8c1d4d3b6d36482895f73f2729 100644
--- a/indra/newview/llviewermenufile.h
+++ b/indra/newview/llviewermenufile.h
@@ -68,23 +68,6 @@ void upload_new_resource(
 	S32 expected_upload_cost,
 	void *userdata);
 
-// TODO* : Move all uploads to use this new function
-// since at some point, that upload path will be deprecated and no longer
-// used
-
-// We make a new function here to ensure that previous code is not broken
-BOOL upload_new_variable_price_resource(
-	const LLTransactionID& tid, 
-	LLAssetType::EType type,
-	std::string name,
-	std::string desc, 
-	LLFolderType::EType destination_folder_type,
-	LLInventoryType::EType inv_type,
-	U32 next_owner_perms,
-	U32 group_perms,
-	U32 everyone_perms,
-	const std::string& display_name,
-	const LLSD& asset_resources);
 
 LLAssetID generate_asset_id_for_new_upload(const LLTransactionID& tid);
 void increase_new_upload_stats(LLAssetType::EType asset_type);
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index 01a5cb18dbaf5c418e439cc290acb7c964b97074..7ab335314a213f6a5a2f0c14b414e7ba9002770d 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -96,7 +96,6 @@
 #include "llviewerwindow.h"
 #include "llvlmanager.h"
 #include "llvoavatarself.h"
-#include "llvotextbubble.h"
 #include "llworld.h"
 #include "pipeline.h"
 #include "llfloaterworldmap.h"
@@ -4228,15 +4227,8 @@ void process_kill_object(LLMessageSystem *mesgsys, void **user_data)
 				// Display green bubble on kill
 				if ( gShowObjectUpdates )
 				{
-					LLViewerObject* newobject;
-					newobject = gObjectList.createObjectViewer(LL_PCODE_LEGACY_TEXT_BUBBLE, objectp->getRegion());
-
-					LLVOTextBubble* bubble = (LLVOTextBubble*) newobject;
-
-					bubble->mColor.setVec(0.f, 1.f, 0.f, 1.f);
-					bubble->setScale( 2.0f * bubble->getScale() );
-					bubble->setPositionGlobal(objectp->getPositionGlobal());
-					gPipeline.addObject(bubble);
+					LLColor4 color(0.f,1.f,0.f,1.f);
+					gPipeline.addDebugBlip(objectp->getPositionAgent(), color);
 				}
 
 				// Do the kill
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index e7878d8adfd785dda95ba01d3c8c1be4b5ecc9b3..be9ff872c06d0456f37aa5a6bc42d45bb41c8de2 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -89,7 +89,6 @@
 #include "llvopartgroup.h"
 #include "llvosky.h"
 #include "llvosurfacepatch.h"
-#include "llvotextbubble.h"
 #include "llvotree.h"
 #include "llvovolume.h"
 #include "llvowater.h"
@@ -168,8 +167,6 @@ LLViewerObject *LLViewerObject::createObject(const LLUUID &id, const LLPCode pco
 // 	  llwarns << "Creating new tree!" << llendl;
 // 	  res = new LLVOTree(id, pcode, regionp); break;
 	  res = NULL; break;
-	case LL_PCODE_LEGACY_TEXT_BUBBLE:
-	  res = new LLVOTextBubble(id, pcode, regionp); break;
 	case LL_VO_CLOUDS:
 	  res = new LLVOClouds(id, pcode, regionp); break;
 	case LL_VO_SURFACE_PATCH:
@@ -1894,7 +1891,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
 	//
 	//
 
-	// WTF?   If we're going to skip this message, why are we 
+	// If we're going to skip this message, why are we 
 	// doing all the parenting, etc above?
 	U32 packet_id = mesgsys->getCurrentRecvPacketID(); 
 	if (packet_id < mLatestRecvPacketID && 
@@ -1973,23 +1970,16 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
 
 	if ( gShowObjectUpdates )
 	{
-		if (!((mPrimitiveCode == LL_PCODE_LEGACY_AVATAR) && (((LLVOAvatar *) this)->isSelf()))
-			&& mRegionp)
+		LLColor4 color;
+		if (update_type == OUT_TERSE_IMPROVED)
 		{
-			LLViewerObject* object = gObjectList.createObjectViewer(LL_PCODE_LEGACY_TEXT_BUBBLE, mRegionp);
-			LLVOTextBubble* bubble = (LLVOTextBubble*) object;
-
-			if (update_type == OUT_TERSE_IMPROVED)
-			{
-				bubble->mColor.setVec(0.f, 0.f, 1.f, 1.f);
-			}
-			else
-			{
-				bubble->mColor.setVec(1.f, 0.f, 0.f, 1.f);
-			}
-			object->setPositionGlobal(getPositionGlobal());
-			gPipeline.addObject(object);
+			color.setVec(0.f, 0.f, 1.f, 1.f);
+		}
+		else
+		{
+			color.setVec(1.f, 0.f, 0.f, 1.f);
 		}
+		gPipeline.addDebugBlip(getPositionAgent(), color);
 	}
 
 	if ((0.0f == vel_mag_sq) && 
diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp
index 007b3416f17a28b04fa67f34e36d8c025b74a0e9..45c6777ae87eaafa6be96cb27d09108d8f0561d7 100644
--- a/indra/newview/llviewerobjectlist.cpp
+++ b/indra/newview/llviewerobjectlist.cpp
@@ -1418,12 +1418,12 @@ void LLViewerObjectList::onObjectCostFetchFailure(const LLUUID& object_id)
 	mPendingObjectCost.erase(object_id);
 }
 
-void LLViewerObjectList::updateQuotaCost( const LLUUID& objectId, const SelectionQuota& quota  )
+void LLViewerObjectList::updateQuota( const LLUUID& objectId, const SelectionQuota& quota  )
 {
 	LLViewerObject* pVO = findObject( objectId );
 	if ( pVO )
 	{
-		//pVO->updateQuota( quota );
+		pVO->updateQuota( quota );
 	}
 }
 
@@ -1497,6 +1497,24 @@ void LLViewerObjectList::shiftObjects(const LLVector3 &offset)
 	LLWorld::getInstance()->shiftRegions(offset);
 }
 
+void LLViewerObjectList::repartitionObjects()
+{
+	for (vobj_list_t::iterator iter = mObjects.begin(); iter != mObjects.end(); ++iter)
+	{
+		LLViewerObject* objectp = *iter;
+		if (!objectp->isDead())
+		{
+			LLDrawable* drawable = objectp->mDrawable;
+			if (drawable && !drawable->isDead())
+			{
+				drawable->updateBinRadius();
+				drawable->updateSpatialExtents();
+				drawable->movePartition();
+			}
+		}
+	}
+}
+
 //debug code
 bool LLViewerObjectList::hasMapObjectInRegion(LLViewerRegion* regionp) 
 {
diff --git a/indra/newview/llviewerobjectlist.h b/indra/newview/llviewerobjectlist.h
index 8e211eaf7380cbab38ccd48f60319a91f4a71dce..9d1b5cb56ff76e13d110e7fb34cf5994c6723fe1 100644
--- a/indra/newview/llviewerobjectlist.h
+++ b/indra/newview/llviewerobjectlist.h
@@ -102,9 +102,10 @@ class LLViewerObjectList
 									F32 restitution,
 									F32 gravity_multiplier);
 
-	void updateQuotaCost( const LLUUID& objectId, const SelectionQuota& costs );
+	void updateQuota( const LLUUID& objectId, const SelectionQuota& costs );
 	
 	void shiftObjects(const LLVector3 &offset);
+	void repartitionObjects();
 
 	bool hasMapObjectInRegion(LLViewerRegion* regionp) ;
 	void clearAllMapObjectsInRegion(LLViewerRegion* regionp) ;
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index 590c82856dcbc647da26dafeabb23fcde520a2fc..002e0567e4ec7b391e72f91307dc56530953b93c 100644
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -69,6 +69,7 @@
 #include "llspatialpartition.h"
 #include "stringize.h"
 #include "llviewercontrol.h"
+#include "llsdserialize.h"
 
 #ifdef LL_WINDOWS
 	#pragma warning(disable:4355)
@@ -1140,6 +1141,20 @@ void LLViewerRegion::getInfo(LLSD& info)
 	info["Region"]["Handle"]["y"] = (LLSD::Integer)y;
 }
 
+void LLViewerRegion::getSimulatorFeatures(LLSD& sim_features)
+{
+	sim_features = mSimulatorFeatures;
+}
+
+void LLViewerRegion::setSimulatorFeatures(const LLSD& sim_features)
+{
+	std::stringstream str;
+	
+	LLSDSerialize::toPrettyXML(sim_features, str);
+	llinfos << str.str() << llendl;
+	mSimulatorFeatures = sim_features;
+}
+
 LLViewerRegion::eCacheUpdateResult LLViewerRegion::cacheFullUpdate(LLViewerObject* objectp, LLDataPackerBinaryBuffer &dp)
 {
 	U32 local_id = objectp->getLocalID();
@@ -1480,6 +1495,8 @@ void LLViewerRegion::setSeedCapability(const std::string& url)
 
 	LLSD capabilityNames = LLSD::emptyArray();
 	
+	capabilityNames.append("AccountingParcel");
+	capabilityNames.append("AccountingSelection");
 	capabilityNames.append("AttachmentResources");
 	capabilityNames.append("AvatarPickerSearch");
 	capabilityNames.append("ChatSessionRequest");
@@ -1509,8 +1526,6 @@ void LLViewerRegion::setSeedCapability(const std::string& url)
 	capabilityNames.append("MapLayer");
 	capabilityNames.append("MapLayerGod");
 	capabilityNames.append("NewFileAgentInventory");
-	capabilityNames.append("NewFileAgentInventoryVariablePrice");
-	capabilityNames.append("ObjectAdd");
 	capabilityNames.append("ParcelPropertiesUpdate");
 	capabilityNames.append("ParcelMediaURLFilterList");
 	capabilityNames.append("ParcelNavigateMedia");
@@ -1541,7 +1556,6 @@ void LLViewerRegion::setSeedCapability(const std::string& url)
 	capabilityNames.append("UpdateNotecardTaskInventory");
 	capabilityNames.append("UpdateScriptTask");
 	capabilityNames.append("UploadBakedTexture");
-	capabilityNames.append("UploadObjectAsset");
 	capabilityNames.append("ViewerMetrics");
 	capabilityNames.append("ViewerStartAuction");
 	capabilityNames.append("ViewerStats");
@@ -1559,6 +1573,42 @@ void LLViewerRegion::setSeedCapability(const std::string& url)
 	LLHTTPClient::post(url, capabilityNames, mImpl->mHttpResponderPtr);
 }
 
+class SimulatorFeaturesReceived : public LLHTTPClient::Responder
+{
+	LOG_CLASS(SimulatorFeaturesReceived);
+public:
+    SimulatorFeaturesReceived(LLViewerRegion* region)
+	: mRegion(region)
+    { }
+	
+	
+    void error(U32 statusNum, const std::string& reason)
+    {
+		LL_WARNS2("AppInit", "SimulatorFeatures") << statusNum << ": " << reason << LL_ENDL;
+    }
+	
+    void result(const LLSD& content)
+    {
+		if(!mRegion) //region is removed or responder is not created.
+		{
+			return ;
+		}
+		
+		mRegion->setSimulatorFeatures(content);
+	}
+	
+    static boost::intrusive_ptr<SimulatorFeaturesReceived> build(
+																 LLViewerRegion* region)
+    {
+		return boost::intrusive_ptr<SimulatorFeaturesReceived>(
+															   new SimulatorFeaturesReceived(region));
+    }
+	
+private:
+	LLViewerRegion* mRegion;
+};
+
+
 void LLViewerRegion::setCapability(const std::string& name, const std::string& url)
 {
 	if(name == "EventQueueGet")
@@ -1571,6 +1621,11 @@ void LLViewerRegion::setCapability(const std::string& name, const std::string& u
 	{
 		LLHTTPSender::setSender(mImpl->mHost, new LLCapHTTPSender(url));
 	}
+	else if (name == "SimulatorFeatures")
+	{
+		// kick off a request for simulator features
+		LLHTTPClient::get(url, new SimulatorFeaturesReceived(this));
+	}
 	else
 	{
 		mImpl->mCapabilities[name] = url;
@@ -1664,3 +1719,16 @@ std::string LLViewerRegion::getDescription() const
     return stringize(*this);
 }
 
+bool LLViewerRegion::meshUploadEnabled() const
+{
+	return (mSimulatorFeatures.has("MeshUploadEnabled") &&
+		mSimulatorFeatures["MeshUploadEnabled"].asBoolean());
+}
+
+bool LLViewerRegion::meshRezEnabled() const
+{
+	return (mSimulatorFeatures.has("MeshRezEnabled") &&
+				mSimulatorFeatures["MeshRezEnabled"].asBoolean());
+}
+
+
diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h
index a6e5c47b866af8ba36e67eea701e3cd30e3813d1..3811b989e7c88cbdc98bc9ee1a0bce0c6de34713 100644
--- a/indra/newview/llviewerregion.h
+++ b/indra/newview/llviewerregion.h
@@ -276,6 +276,11 @@ class LLViewerRegion: public LLCapabilityProvider // implements this interface
 
 	void getInfo(LLSD& info);
 	
+	bool meshRezEnabled() const;
+	bool meshUploadEnabled() const;
+
+	void getSimulatorFeatures(LLSD& info);	
+	void setSimulatorFeatures(const LLSD& info);
 
 	typedef enum
 	{
@@ -401,6 +406,8 @@ class LLViewerRegion: public LLCapabilityProvider // implements this interface
 	bool	mCapabilitiesReceived;
 
 	BOOL mReleaseNotesRequested;
+	
+	LLSD mSimulatorFeatures;
 };
 
 inline BOOL LLViewerRegion::getAllowDamage() const
diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp
index 3e85802ba6c630780e6e4cab4676e482e9caa27d..e3ed2d064985680852e0623f884ee8cb931a1e60 100644
--- a/indra/newview/llviewershadermgr.cpp
+++ b/indra/newview/llviewershadermgr.cpp
@@ -66,12 +66,20 @@ LLGLSLShader		gObjectSimpleProgram;
 LLGLSLShader		gObjectSimpleWaterProgram;
 LLGLSLShader		gObjectFullbrightProgram;
 LLGLSLShader		gObjectFullbrightWaterProgram;
-
 LLGLSLShader		gObjectFullbrightShinyProgram;
 LLGLSLShader		gObjectFullbrightShinyWaterProgram;
 LLGLSLShader		gObjectShinyProgram;
 LLGLSLShader		gObjectShinyWaterProgram;
 
+LLGLSLShader		gObjectSimpleNonIndexedProgram;
+LLGLSLShader		gObjectSimpleNonIndexedWaterProgram;
+LLGLSLShader		gObjectFullbrightNonIndexedProgram;
+LLGLSLShader		gObjectFullbrightNonIndexedWaterProgram;
+LLGLSLShader		gObjectFullbrightShinyNonIndexedProgram;
+LLGLSLShader		gObjectFullbrightShinyNonIndexedWaterProgram;
+LLGLSLShader		gObjectShinyNonIndexedProgram;
+LLGLSLShader		gObjectShinyNonIndexedWaterProgram;
+
 //object hardware skinning shaders
 LLGLSLShader		gSkinnedObjectSimpleProgram;
 LLGLSLShader		gSkinnedObjectFullbrightProgram;
@@ -113,6 +121,7 @@ LLGLSLShader			gDeferredImpostorProgram;
 LLGLSLShader			gDeferredEdgeProgram;
 LLGLSLShader			gDeferredWaterProgram;
 LLGLSLShader			gDeferredDiffuseProgram;
+LLGLSLShader			gDeferredNonIndexedDiffuseProgram;
 LLGLSLShader			gDeferredSkinnedDiffuseProgram;
 LLGLSLShader			gDeferredSkinnedBumpProgram;
 LLGLSLShader			gDeferredSkinnedAlphaProgram;
@@ -132,13 +141,16 @@ LLGLSLShader			gDeferredShadowProgram;
 LLGLSLShader			gDeferredAvatarShadowProgram;
 LLGLSLShader			gDeferredAttachmentShadowProgram;
 LLGLSLShader			gDeferredAlphaProgram;
+LLGLSLShader			gDeferredAvatarEyesProgram;
 LLGLSLShader			gDeferredFullbrightProgram;
 LLGLSLShader			gDeferredGIProgram;
 LLGLSLShader			gDeferredGIFinalProgram;
 LLGLSLShader			gDeferredPostGIProgram;
 LLGLSLShader			gDeferredPostProgram;
 LLGLSLShader			gDeferredPostNoDoFProgram;
-
+LLGLSLShader			gDeferredWLSkyProgram;
+LLGLSLShader			gDeferredWLCloudProgram;
+LLGLSLShader			gDeferredStarProgram;
 LLGLSLShader			gLuminanceGatherProgram;
 
 
@@ -160,6 +172,10 @@ LLViewerShaderMgr::LLViewerShaderMgr() :
 	mShaderList.push_back(&gObjectFullbrightProgram);
 	mShaderList.push_back(&gObjectFullbrightShinyProgram);
 	mShaderList.push_back(&gObjectFullbrightShinyWaterProgram);
+	mShaderList.push_back(&gObjectSimpleNonIndexedProgram);
+	mShaderList.push_back(&gObjectFullbrightNonIndexedProgram);
+	mShaderList.push_back(&gObjectFullbrightShinyNonIndexedProgram);
+	mShaderList.push_back(&gObjectFullbrightShinyNonIndexedWaterProgram);
 	mShaderList.push_back(&gSkinnedObjectSimpleProgram);
 	mShaderList.push_back(&gSkinnedObjectFullbrightProgram);
 	mShaderList.push_back(&gSkinnedObjectFullbrightShinyProgram);
@@ -183,6 +199,7 @@ LLViewerShaderMgr::LLViewerShaderMgr() :
 	mShaderList.push_back(&gDeferredAlphaProgram);
 	mShaderList.push_back(&gDeferredSkinnedAlphaProgram);
 	mShaderList.push_back(&gDeferredFullbrightProgram);
+	mShaderList.push_back(&gDeferredAvatarEyesProgram);
 	mShaderList.push_back(&gDeferredPostGIProgram);
 	mShaderList.push_back(&gDeferredEdgeProgram);
 	mShaderList.push_back(&gDeferredPostProgram);
@@ -190,6 +207,9 @@ LLViewerShaderMgr::LLViewerShaderMgr() :
 	mShaderList.push_back(&gDeferredGIFinalProgram);
 	mShaderList.push_back(&gDeferredWaterProgram);
 	mShaderList.push_back(&gDeferredAvatarAlphaProgram);
+	mShaderList.push_back(&gDeferredWLSkyProgram);
+	mShaderList.push_back(&gDeferredWLCloudProgram);
+	mShaderList.push_back(&gDeferredStarProgram);
 }
 
 LLViewerShaderMgr::~LLViewerShaderMgr()
@@ -347,6 +367,10 @@ void LLViewerShaderMgr::setShaders()
 		return;
 	}
 
+	//setup preprocessor definitions
+	LLShaderMgr::instance()->mDefinitions["samples"] = llformat("%d", gGLManager.getNumFBOFSAASamples(gSavedSettings.getU32("RenderFSAASamples")));
+	LLShaderMgr::instance()->mDefinitions["NUM_TEX_UNITS"] = llformat("%d", gGLManager.mNumTextureImageUnits);
+
 	reentrance = true;
 
 	// Make sure the compiled shader map is cleared before we recompile shaders.
@@ -577,6 +601,16 @@ void LLViewerShaderMgr::unloadShaders()
 	gObjectFullbrightShinyWaterProgram.unload();
 	gObjectShinyWaterProgram.unload();
 
+	gObjectSimpleNonIndexedProgram.unload();
+	gObjectSimpleNonIndexedWaterProgram.unload();
+	gObjectFullbrightNonIndexedProgram.unload();
+	gObjectFullbrightNonIndexedWaterProgram.unload();
+
+	gObjectShinyNonIndexedProgram.unload();
+	gObjectFullbrightShinyNonIndexedProgram.unload();
+	gObjectFullbrightShinyNonIndexedWaterProgram.unload();
+	gObjectShinyNonIndexedWaterProgram.unload();
+
 	gSkinnedObjectSimpleProgram.unload();
 	gSkinnedObjectFullbrightProgram.unload();
 	gSkinnedObjectFullbrightShinyProgram.unload();
@@ -607,6 +641,7 @@ void LLViewerShaderMgr::unloadShaders()
 	gPostNightVisionProgram.unload();
 
 	gDeferredDiffuseProgram.unload();
+	gDeferredNonIndexedDiffuseProgram.unload();
 	gDeferredSkinnedDiffuseProgram.unload();
 	gDeferredSkinnedBumpProgram.unload();
 	gDeferredSkinnedAlphaProgram.unload();
@@ -685,24 +720,35 @@ BOOL LLViewerShaderMgr::loadBasicShaders()
 
 	shaders.clear();
 	shaders.reserve(13);
-	shaders.push_back( make_pair( "windlight/atmosphericsVarsF.glsl",		mVertexShaderLevel[SHADER_WINDLIGHT] ) );
-	shaders.push_back( make_pair( "windlight/gammaF.glsl",					mVertexShaderLevel[SHADER_WINDLIGHT]) );
-	shaders.push_back( make_pair( "windlight/atmosphericsF.glsl",			mVertexShaderLevel[SHADER_WINDLIGHT] ) );
-	shaders.push_back( make_pair( "windlight/transportF.glsl",				mVertexShaderLevel[SHADER_WINDLIGHT] ) );	
-	shaders.push_back( make_pair( "environment/waterFogF.glsl",				mVertexShaderLevel[SHADER_WATER] ) );
-	shaders.push_back( make_pair( "lighting/lightF.glsl",					mVertexShaderLevel[SHADER_LIGHTING] ) );
-	shaders.push_back( make_pair( "lighting/lightFullbrightF.glsl",			mVertexShaderLevel[SHADER_LIGHTING] ) );
-	shaders.push_back( make_pair( "lighting/lightWaterF.glsl",				mVertexShaderLevel[SHADER_LIGHTING] ) );
-	shaders.push_back( make_pair( "lighting/lightFullbrightWaterF.glsl",	mVertexShaderLevel[SHADER_LIGHTING] ) );
-	shaders.push_back( make_pair( "lighting/lightShinyF.glsl",				mVertexShaderLevel[SHADER_LIGHTING] ) );
-	shaders.push_back( make_pair( "lighting/lightFullbrightShinyF.glsl",	mVertexShaderLevel[SHADER_LIGHTING] ) );
-	shaders.push_back( make_pair( "lighting/lightShinyWaterF.glsl",			mVertexShaderLevel[SHADER_LIGHTING] ) );
-	shaders.push_back( make_pair( "lighting/lightFullbrightShinyWaterF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) );
+	S32 ch = gGLManager.mNumTextureImageUnits-1;
+
+	std::vector<S32> index_channels;
+	index_channels.push_back(-1);	 shaders.push_back( make_pair( "windlight/atmosphericsVarsF.glsl",		mVertexShaderLevel[SHADER_WINDLIGHT] ) );
+	index_channels.push_back(-1);	 shaders.push_back( make_pair( "windlight/gammaF.glsl",					mVertexShaderLevel[SHADER_WINDLIGHT]) );
+	index_channels.push_back(-1);	 shaders.push_back( make_pair( "windlight/atmosphericsF.glsl",			mVertexShaderLevel[SHADER_WINDLIGHT] ) );
+	index_channels.push_back(-1);	 shaders.push_back( make_pair( "windlight/transportF.glsl",				mVertexShaderLevel[SHADER_WINDLIGHT] ) );	
+	index_channels.push_back(-1);	 shaders.push_back( make_pair( "environment/waterFogF.glsl",				mVertexShaderLevel[SHADER_WATER] ) );
+	index_channels.push_back(-1);	 shaders.push_back( make_pair( "lighting/lightNonIndexedF.glsl",					mVertexShaderLevel[SHADER_LIGHTING] ) );
+	index_channels.push_back(-1);	 shaders.push_back( make_pair( "lighting/lightFullbrightNonIndexedF.glsl",			mVertexShaderLevel[SHADER_LIGHTING] ) );
+	index_channels.push_back(-1);	 shaders.push_back( make_pair( "lighting/lightWaterNonIndexedF.glsl",				mVertexShaderLevel[SHADER_LIGHTING] ) );
+	index_channels.push_back(-1);	 shaders.push_back( make_pair( "lighting/lightFullbrightWaterNonIndexedF.glsl",	mVertexShaderLevel[SHADER_LIGHTING] ) );
+	index_channels.push_back(-1);	 shaders.push_back( make_pair( "lighting/lightShinyNonIndexedF.glsl",				mVertexShaderLevel[SHADER_LIGHTING] ) );
+	index_channels.push_back(-1);	 shaders.push_back( make_pair( "lighting/lightFullbrightShinyNonIndexedF.glsl",	mVertexShaderLevel[SHADER_LIGHTING] ) );
+	index_channels.push_back(-1);	 shaders.push_back( make_pair( "lighting/lightShinyWaterNonIndexedF.glsl",			mVertexShaderLevel[SHADER_LIGHTING] ) );
+	index_channels.push_back(-1);	 shaders.push_back( make_pair( "lighting/lightFullbrightShinyWaterNonIndexedF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) );
+	index_channels.push_back(ch);	 shaders.push_back( make_pair( "lighting/lightF.glsl",					mVertexShaderLevel[SHADER_LIGHTING] ) );
+	index_channels.push_back(ch);	 shaders.push_back( make_pair( "lighting/lightFullbrightF.glsl",			mVertexShaderLevel[SHADER_LIGHTING] ) );
+	index_channels.push_back(ch);	 shaders.push_back( make_pair( "lighting/lightWaterF.glsl",				mVertexShaderLevel[SHADER_LIGHTING] ) );
+	index_channels.push_back(ch);	 shaders.push_back( make_pair( "lighting/lightFullbrightWaterF.glsl",	mVertexShaderLevel[SHADER_LIGHTING] ) );
+	index_channels.push_back(ch);	 shaders.push_back( make_pair( "lighting/lightShinyF.glsl",				mVertexShaderLevel[SHADER_LIGHTING] ) );
+	index_channels.push_back(ch);	 shaders.push_back( make_pair( "lighting/lightFullbrightShinyF.glsl",	mVertexShaderLevel[SHADER_LIGHTING] ) );
+	index_channels.push_back(ch);	 shaders.push_back( make_pair( "lighting/lightShinyWaterF.glsl",			mVertexShaderLevel[SHADER_LIGHTING] ) );
+	index_channels.push_back(ch);	 shaders.push_back( make_pair( "lighting/lightFullbrightShinyWaterF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) );
 	
 	for (U32 i = 0; i < shaders.size(); i++)
 	{
 		// Note usage of GL_FRAGMENT_SHADER_ARB
-		if (loadShaderFile(shaders[i].first, shaders[i].second, GL_FRAGMENT_SHADER_ARB) == 0)
+		if (loadShaderFile(shaders[i].first, shaders[i].second, GL_FRAGMENT_SHADER_ARB, index_channels[i]) == 0)
 		{
 			return FALSE;
 		}
@@ -833,6 +879,9 @@ BOOL LLViewerShaderMgr::loadShadersEffects()
 {
 	BOOL success = TRUE;
 
+	U32 samples = gGLManager.getNumFBOFSAASamples(gSavedSettings.getU32("RenderFSAASamples"));
+	bool multisample = samples > 1 && LLPipeline::sRenderDeferred && gGLManager.mHasTextureMultisample;
+
 	if (mVertexShaderLevel[SHADER_EFFECT] == 0)
 	{
 		gGlowProgram.unload();
@@ -858,10 +907,21 @@ BOOL LLViewerShaderMgr::loadShadersEffects()
 	
 	if (success)
 	{
+		std::string fragment;
+
+		if (multisample)
+		{
+			fragment = "effects/glowExtractMSF.glsl";
+		}
+		else
+		{
+			fragment = "effects/glowExtractF.glsl";
+		}
+
 		gGlowExtractProgram.mName = "Glow Extract Shader (Post)";
 		gGlowExtractProgram.mShaderFiles.clear();
 		gGlowExtractProgram.mShaderFiles.push_back(make_pair("effects/glowExtractV.glsl", GL_VERTEX_SHADER_ARB));
-		gGlowExtractProgram.mShaderFiles.push_back(make_pair("effects/glowExtractF.glsl", GL_FRAGMENT_SHADER_ARB));
+		gGlowExtractProgram.mShaderFiles.push_back(make_pair(fragment, GL_FRAGMENT_SHADER_ARB));
 		gGlowExtractProgram.mShaderLevel = mVertexShaderLevel[SHADER_EFFECT];
 		success = gGlowExtractProgram.createShader(NULL, &mGlowExtractUniforms);
 		if (!success)
@@ -925,6 +985,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 	{
 		gDeferredTreeProgram.unload();
 		gDeferredDiffuseProgram.unload();
+		gDeferredNonIndexedDiffuseProgram.unload();
 		gDeferredSkinnedDiffuseProgram.unload();
 		gDeferredSkinnedBumpProgram.unload();
 		gDeferredSkinnedAlphaProgram.unload();
@@ -945,6 +1006,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredAvatarAlphaProgram.unload();
 		gDeferredAlphaProgram.unload();
 		gDeferredFullbrightProgram.unload();
+		gDeferredAvatarEyesProgram.unload();
 		gDeferredPostGIProgram.unload();		
 		gDeferredEdgeProgram.unload();		
 		gDeferredPostProgram.unload();		
@@ -952,6 +1014,9 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredGIProgram.unload();
 		gDeferredGIFinalProgram.unload();
 		gDeferredWaterProgram.unload();
+		gDeferredWLSkyProgram.unload();
+		gDeferredWLCloudProgram.unload();
+		gDeferredStarProgram.unload();
 		return TRUE;
 	}
 
@@ -959,16 +1024,31 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 
 	BOOL success = TRUE;
 
+	U32 samples = gGLManager.getNumFBOFSAASamples(gSavedSettings.getU32("RenderFSAASamples"));
+	bool multisample = samples > 1 && gGLManager.mHasTextureMultisample;
+
 	if (success)
 	{
 		gDeferredDiffuseProgram.mName = "Deferred Diffuse Shader";
 		gDeferredDiffuseProgram.mShaderFiles.clear();
 		gDeferredDiffuseProgram.mShaderFiles.push_back(make_pair("deferred/diffuseV.glsl", GL_VERTEX_SHADER_ARB));
-		gDeferredDiffuseProgram.mShaderFiles.push_back(make_pair("deferred/diffuseF.glsl", GL_FRAGMENT_SHADER_ARB));
+		gDeferredDiffuseProgram.mShaderFiles.push_back(make_pair("deferred/diffuseIndexedF.glsl", GL_FRAGMENT_SHADER_ARB));
+		gDeferredDiffuseProgram.mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits;
 		gDeferredDiffuseProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
 		success = gDeferredDiffuseProgram.createShader(NULL, NULL);
 	}
 
+	if (success)
+	{
+		gDeferredNonIndexedDiffuseProgram.mName = "Non Indexed Deferred Diffuse Shader";
+		gDeferredNonIndexedDiffuseProgram.mShaderFiles.clear();
+		gDeferredNonIndexedDiffuseProgram.mShaderFiles.push_back(make_pair("deferred/diffuseV.glsl", GL_VERTEX_SHADER_ARB));
+		gDeferredNonIndexedDiffuseProgram.mShaderFiles.push_back(make_pair("deferred/diffuseF.glsl", GL_FRAGMENT_SHADER_ARB));
+		gDeferredNonIndexedDiffuseProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		success = gDeferredNonIndexedDiffuseProgram.createShader(NULL, NULL);
+	}
+		
+
 	if (success)
 	{
 		gDeferredSkinnedDiffuseProgram.mName = "Deferred Skinned Diffuse Shader";
@@ -1000,9 +1080,10 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredSkinnedAlphaProgram.mFeatures.hasGamma = true;
 		gDeferredSkinnedAlphaProgram.mFeatures.hasAtmospherics = true;
 		gDeferredSkinnedAlphaProgram.mFeatures.hasLighting = true;
+		gDeferredSkinnedAlphaProgram.mFeatures.disableTextureIndex = true;
 		gDeferredSkinnedAlphaProgram.mShaderFiles.clear();
 		gDeferredSkinnedAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaSkinnedV.glsl", GL_VERTEX_SHADER_ARB));
-		gDeferredSkinnedAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaF.glsl", GL_FRAGMENT_SHADER_ARB));
+		gDeferredSkinnedAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaNonIndexedF.glsl", GL_FRAGMENT_SHADER_ARB));
 		gDeferredSkinnedAlphaProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
 		success = gDeferredSkinnedAlphaProgram.createShader(NULL, NULL);
 	}
@@ -1039,40 +1120,83 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 
 	if (success)
 	{
+		std::string fragment;
+
+		if (multisample)
+		{
+			fragment = "deferred/pointLightMSF.glsl";
+		}
+		else
+		{
+			fragment = "deferred/pointLightF.glsl";
+		}
+
 		gDeferredLightProgram.mName = "Deferred Light Shader";
 		gDeferredLightProgram.mShaderFiles.clear();
 		gDeferredLightProgram.mShaderFiles.push_back(make_pair("deferred/pointLightV.glsl", GL_VERTEX_SHADER_ARB));
-		gDeferredLightProgram.mShaderFiles.push_back(make_pair("deferred/pointLightF.glsl", GL_FRAGMENT_SHADER_ARB));
+		gDeferredLightProgram.mShaderFiles.push_back(make_pair(fragment, GL_FRAGMENT_SHADER_ARB));
 		gDeferredLightProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
 		success = gDeferredLightProgram.createShader(NULL, NULL);
 	}
 
 	if (success)
 	{
+		std::string fragment;
+		if (multisample)
+		{
+			fragment = "deferred/multiPointLightMSF.glsl";
+		}
+		else
+		{
+			fragment = "deferred/multiPointLightF.glsl";
+		}
+
 		gDeferredMultiLightProgram.mName = "Deferred MultiLight Shader";
 		gDeferredMultiLightProgram.mShaderFiles.clear();
 		gDeferredMultiLightProgram.mShaderFiles.push_back(make_pair("deferred/multiPointLightV.glsl", GL_VERTEX_SHADER_ARB));
-		gDeferredMultiLightProgram.mShaderFiles.push_back(make_pair("deferred/multiPointLightF.glsl", GL_FRAGMENT_SHADER_ARB));
+		gDeferredMultiLightProgram.mShaderFiles.push_back(make_pair(fragment, GL_FRAGMENT_SHADER_ARB));
 		gDeferredMultiLightProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
 		success = gDeferredMultiLightProgram.createShader(NULL, NULL);
 	}
 
 	if (success)
 	{
+		std::string fragment;
+
+		if (multisample)
+		{
+			fragment = "deferred/spotLightMSF.glsl";
+		}
+		else
+		{
+			fragment = "deferred/multiSpotLightF.glsl";
+		}
+
 		gDeferredSpotLightProgram.mName = "Deferred SpotLight Shader";
 		gDeferredSpotLightProgram.mShaderFiles.clear();
 		gDeferredSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/pointLightV.glsl", GL_VERTEX_SHADER_ARB));
-		gDeferredSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/multiSpotLightF.glsl", GL_FRAGMENT_SHADER_ARB));
+		gDeferredSpotLightProgram.mShaderFiles.push_back(make_pair(fragment, GL_FRAGMENT_SHADER_ARB));
 		gDeferredSpotLightProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
 		success = gDeferredSpotLightProgram.createShader(NULL, NULL);
 	}
 
 	if (success)
 	{
+		std::string fragment;
+
+		if (multisample)
+		{
+			fragment = "deferred/multiSpotLightMSF.glsl";
+		}
+		else
+		{
+			fragment = "deferred/multiSpotLightF.glsl";
+		}
+
 		gDeferredMultiSpotLightProgram.mName = "Deferred MultiSpotLight Shader";
 		gDeferredMultiSpotLightProgram.mShaderFiles.clear();
 		gDeferredMultiSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/pointLightV.glsl", GL_VERTEX_SHADER_ARB));
-		gDeferredMultiSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/multiSpotLightF.glsl", GL_FRAGMENT_SHADER_ARB));
+		gDeferredMultiSpotLightProgram.mShaderFiles.push_back(make_pair(fragment, GL_FRAGMENT_SHADER_ARB));
 		gDeferredMultiSpotLightProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
 		success = gDeferredMultiSpotLightProgram.createShader(NULL, NULL);
 	}
@@ -1083,11 +1207,25 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 
 		if (gSavedSettings.getBOOL("RenderDeferredSSAO"))
 		{
-			fragment = "deferred/sunLightSSAOF.glsl";
+			if (multisample)
+			{
+				fragment = "deferred/sunlightSSAOMSF.glsl";
+			}
+			else
+			{
+				fragment = "deferred/sunLightSSAOF.glsl";
+			}
 		}
 		else
 		{
-			fragment = "deferred/sunLightF.glsl";
+			if (multisample)
+			{
+				fragment = "deferred/sunlightMSF.glsl";
+			}
+			else
+			{
+				fragment = "deferred/sunLightF.glsl";
+			}
 		}
 
 		gDeferredSunProgram.mName = "Deferred Sun Shader";
@@ -1100,10 +1238,21 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 
 	if (success)
 	{
+		std::string fragment;
+
+		if (multisample)
+		{
+			fragment = "deferred/blurLightMSF.glsl";
+		}
+		else
+		{
+			fragment = "deferred/blurLightF.glsl";
+		}
+
 		gDeferredBlurLightProgram.mName = "Deferred Blur Light Shader";
 		gDeferredBlurLightProgram.mShaderFiles.clear();
 		gDeferredBlurLightProgram.mShaderFiles.push_back(make_pair("deferred/blurLightV.glsl", GL_VERTEX_SHADER_ARB));
-		gDeferredBlurLightProgram.mShaderFiles.push_back(make_pair("deferred/blurLightF.glsl", GL_FRAGMENT_SHADER_ARB));
+		gDeferredBlurLightProgram.mShaderFiles.push_back(make_pair(fragment, GL_FRAGMENT_SHADER_ARB));
 		gDeferredBlurLightProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
 		success = gDeferredBlurLightProgram.createShader(NULL, NULL);
 	}
@@ -1116,6 +1265,16 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredAlphaProgram.mFeatures.hasGamma = true;
 		gDeferredAlphaProgram.mFeatures.hasAtmospherics = true;
 		gDeferredAlphaProgram.mFeatures.hasLighting = true;
+		gDeferredAlphaProgram.mFeatures.disableTextureIndex = true; //hack to disable auto-setup of texture channels
+		if (mVertexShaderLevel[SHADER_DEFERRED] < 1)
+		{
+			gDeferredAlphaProgram.mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits;
+		}
+		else
+		{ //shave off some texture units for shadow maps
+			gDeferredAlphaProgram.mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits - 6;
+		}
+			
 		gDeferredAlphaProgram.mShaderFiles.clear();
 		gDeferredAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaF.glsl", GL_FRAGMENT_SHADER_ARB));
@@ -1123,13 +1282,28 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		success = gDeferredAlphaProgram.createShader(NULL, NULL);
 	}
 
+	if (success)
+	{
+		gDeferredAvatarEyesProgram.mName = "Deferred Avatar Eyes Shader";
+		gDeferredAvatarEyesProgram.mFeatures.calculatesAtmospherics = true;
+		gDeferredAvatarEyesProgram.mFeatures.hasGamma = true;
+		gDeferredAvatarEyesProgram.mFeatures.hasTransport = true;
+		gDeferredAvatarEyesProgram.mFeatures.isFullbright = true;
+		gDeferredAvatarEyesProgram.mFeatures.disableTextureIndex = true;
+		gDeferredAvatarEyesProgram.mShaderFiles.clear();
+		gDeferredAvatarEyesProgram.mShaderFiles.push_back(make_pair("deferred/avatarEyesV.glsl", GL_VERTEX_SHADER_ARB));
+		gDeferredAvatarEyesProgram.mShaderFiles.push_back(make_pair("deferred/diffuseF.glsl", GL_FRAGMENT_SHADER_ARB));
+		gDeferredAvatarEyesProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		success = gDeferredAvatarEyesProgram.createShader(NULL, NULL);
+	}
+
 	if (success)
 	{
 		gDeferredFullbrightProgram.mName = "Deferred Fullbright Shader";
 		gDeferredFullbrightProgram.mFeatures.calculatesAtmospherics = true;
 		gDeferredFullbrightProgram.mFeatures.hasGamma = true;
 		gDeferredFullbrightProgram.mFeatures.hasTransport = true;
-		gDeferredFullbrightProgram.mFeatures.isFullbright = true;
+		gDeferredFullbrightProgram.mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits;
 		gDeferredFullbrightProgram.mShaderFiles.clear();
 		gDeferredFullbrightProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredFullbrightProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB));
@@ -1153,10 +1327,21 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 
 	if (success)
 	{
+		std::string fragment;
+
+		if (multisample)
+		{
+			fragment = "deferred/softenLightMSF.glsl";
+		}
+		else
+		{
+			fragment = "deferred/softenLightF.glsl";
+		}
+
 		gDeferredSoftenProgram.mName = "Deferred Soften Shader";
 		gDeferredSoftenProgram.mShaderFiles.clear();
 		gDeferredSoftenProgram.mShaderFiles.push_back(make_pair("deferred/softenLightV.glsl", GL_VERTEX_SHADER_ARB));
-		gDeferredSoftenProgram.mShaderFiles.push_back(make_pair("deferred/softenLightF.glsl", GL_FRAGMENT_SHADER_ARB));
+		gDeferredSoftenProgram.mShaderFiles.push_back(make_pair(fragment, GL_FRAGMENT_SHADER_ARB));
 
 		gDeferredSoftenProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
 
@@ -1230,41 +1415,106 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredAvatarAlphaProgram.mFeatures.hasGamma = true;
 		gDeferredAvatarAlphaProgram.mFeatures.hasAtmospherics = true;
 		gDeferredAvatarAlphaProgram.mFeatures.hasLighting = true;
+		gDeferredAvatarAlphaProgram.mFeatures.disableTextureIndex = true;
 		gDeferredAvatarAlphaProgram.mShaderFiles.clear();
 		gDeferredAvatarAlphaProgram.mShaderFiles.push_back(make_pair("deferred/avatarAlphaV.glsl", GL_VERTEX_SHADER_ARB));
-		gDeferredAvatarAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaF.glsl", GL_FRAGMENT_SHADER_ARB));
+		gDeferredAvatarAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaNonIndexedF.glsl", GL_FRAGMENT_SHADER_ARB));
 		gDeferredAvatarAlphaProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
 		success = gDeferredAvatarAlphaProgram.createShader(&mAvatarAttribs, &mAvatarUniforms);
 	}
 
 	if (success)
 	{
+		std::string fragment;
+		if (multisample)
+		{
+			fragment = "deferred/postDeferredMSF.glsl";
+		}
+		else
+		{
+			fragment = "deferred/postDeferredF.glsl";
+		}
+
 		gDeferredPostProgram.mName = "Deferred Post Shader";
 		gDeferredPostProgram.mShaderFiles.clear();
 		gDeferredPostProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredV.glsl", GL_VERTEX_SHADER_ARB));
-		gDeferredPostProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredF.glsl", GL_FRAGMENT_SHADER_ARB));
+		gDeferredPostProgram.mShaderFiles.push_back(make_pair(fragment, GL_FRAGMENT_SHADER_ARB));
 		gDeferredPostProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
 		success = gDeferredPostProgram.createShader(NULL, NULL);
 	}
 
 	if (success)
 	{
+		std::string fragment;
+		if (multisample)
+		{
+			fragment = "deferred/postDeferredNoDoFMSF.glsl";
+		}
+		else
+		{
+			fragment = "deferred/postDeferredNoDoFF.glsl";
+		}
+
 		gDeferredPostNoDoFProgram.mName = "Deferred Post Shader";
 		gDeferredPostNoDoFProgram.mShaderFiles.clear();
 		gDeferredPostNoDoFProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredV.glsl", GL_VERTEX_SHADER_ARB));
-		gDeferredPostNoDoFProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoDoFF.glsl", GL_FRAGMENT_SHADER_ARB));
+		gDeferredPostNoDoFProgram.mShaderFiles.push_back(make_pair(fragment, GL_FRAGMENT_SHADER_ARB));
 		gDeferredPostNoDoFProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
 		success = gDeferredPostNoDoFProgram.createShader(NULL, NULL);
 	}
 
+	if (success)
+	{
+		gDeferredWLSkyProgram.mName = "Deferred Windlight Sky Shader";
+		//gWLSkyProgram.mFeatures.hasGamma = true;
+		gDeferredWLSkyProgram.mShaderFiles.clear();
+		gDeferredWLSkyProgram.mShaderFiles.push_back(make_pair("deferred/skyV.glsl", GL_VERTEX_SHADER_ARB));
+		gDeferredWLSkyProgram.mShaderFiles.push_back(make_pair("deferred/skyF.glsl", GL_FRAGMENT_SHADER_ARB));
+		gDeferredWLSkyProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredWLSkyProgram.mShaderGroup = LLGLSLShader::SG_SKY;
+		success = gDeferredWLSkyProgram.createShader(NULL, &mWLUniforms);
+	}
+
+	if (success)
+	{
+		gDeferredWLCloudProgram.mName = "Deferred Windlight Cloud Program";
+		gDeferredWLCloudProgram.mShaderFiles.clear();
+		gDeferredWLCloudProgram.mShaderFiles.push_back(make_pair("deferred/cloudsV.glsl", GL_VERTEX_SHADER_ARB));
+		gDeferredWLCloudProgram.mShaderFiles.push_back(make_pair("deferred/cloudsF.glsl", GL_FRAGMENT_SHADER_ARB));
+		gDeferredWLCloudProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredWLCloudProgram.mShaderGroup = LLGLSLShader::SG_SKY;
+		success = gDeferredWLCloudProgram.createShader(NULL, &mWLUniforms);
+	}
+
+	if (success)
+	{
+		gDeferredStarProgram.mName = "Deferred Star Program";
+		gDeferredStarProgram.mShaderFiles.clear();
+		gDeferredStarProgram.mShaderFiles.push_back(make_pair("deferred/starsV.glsl", GL_VERTEX_SHADER_ARB));
+		gDeferredStarProgram.mShaderFiles.push_back(make_pair("deferred/starsF.glsl", GL_FRAGMENT_SHADER_ARB));
+		gDeferredStarProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredStarProgram.mShaderGroup = LLGLSLShader::SG_SKY;
+		success = gDeferredStarProgram.createShader(NULL, &mWLUniforms);
+	}
+
 	if (mVertexShaderLevel[SHADER_DEFERRED] > 1)
 	{
 		if (success)
 		{
+			std::string fragment;
+			if (multisample)
+			{
+				fragment = "deferred/edgeMSF.glsl";
+			}
+			else
+			{
+				fragment = "deferred/edgeF.glsl";
+			}
+
 			gDeferredEdgeProgram.mName = "Deferred Edge Shader";
 			gDeferredEdgeProgram.mShaderFiles.clear();
 			gDeferredEdgeProgram.mShaderFiles.push_back(make_pair("deferred/edgeV.glsl", GL_VERTEX_SHADER_ARB));
-			gDeferredEdgeProgram.mShaderFiles.push_back(make_pair("deferred/edgeF.glsl", GL_FRAGMENT_SHADER_ARB));
+			gDeferredEdgeProgram.mShaderFiles.push_back(make_pair(fragment, GL_FRAGMENT_SHADER_ARB));
 			gDeferredEdgeProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
 			success = gDeferredEdgeProgram.createShader(NULL, NULL);
 		}
@@ -1272,8 +1522,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 
 	if (mVertexShaderLevel[SHADER_DEFERRED] > 2)
 	{
-		
-
 		if (success)
 		{
 			gDeferredPostGIProgram.mName = "Deferred Post GI Shader";
@@ -1321,7 +1569,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 BOOL LLViewerShaderMgr::loadShadersObject()
 {
 	BOOL success = TRUE;
-
+	
 	if (mVertexShaderLevel[SHADER_OBJECT] == 0)
 	{
 		gObjectShinyProgram.unload();
@@ -1332,6 +1580,14 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectSimpleWaterProgram.unload();
 		gObjectFullbrightProgram.unload();
 		gObjectFullbrightWaterProgram.unload();
+		gObjectShinyNonIndexedProgram.unload();
+		gObjectFullbrightShinyNonIndexedProgram.unload();
+		gObjectFullbrightShinyNonIndexedWaterProgram.unload();
+		gObjectShinyNonIndexedWaterProgram.unload();
+		gObjectSimpleNonIndexedProgram.unload();
+		gObjectSimpleNonIndexedWaterProgram.unload();
+		gObjectFullbrightNonIndexedProgram.unload();
+		gObjectFullbrightNonIndexedWaterProgram.unload();
 		gSkinnedObjectSimpleProgram.unload();
 		gSkinnedObjectFullbrightProgram.unload();
 		gSkinnedObjectFullbrightShinyProgram.unload();
@@ -1344,6 +1600,137 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		return TRUE;
 	}
 
+	if (success)
+	{
+		gObjectSimpleNonIndexedProgram.mName = "Non indexed Shader";
+		gObjectSimpleNonIndexedProgram.mFeatures.calculatesLighting = true;
+		gObjectSimpleNonIndexedProgram.mFeatures.calculatesAtmospherics = true;
+		gObjectSimpleNonIndexedProgram.mFeatures.hasGamma = true;
+		gObjectSimpleNonIndexedProgram.mFeatures.hasAtmospherics = true;
+		gObjectSimpleNonIndexedProgram.mFeatures.hasLighting = true;
+		gObjectSimpleNonIndexedProgram.mFeatures.disableTextureIndex = true;
+		gObjectSimpleNonIndexedProgram.mShaderFiles.clear();
+		gObjectSimpleNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER_ARB));
+		gObjectSimpleNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB));
+		gObjectSimpleNonIndexedProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		success = gObjectSimpleNonIndexedProgram.createShader(NULL, NULL);
+	}
+	
+	if (success)
+	{
+		gObjectSimpleNonIndexedWaterProgram.mName = "Non indexed Water Shader";
+		gObjectSimpleNonIndexedWaterProgram.mFeatures.calculatesLighting = true;
+		gObjectSimpleNonIndexedWaterProgram.mFeatures.calculatesAtmospherics = true;
+		gObjectSimpleNonIndexedWaterProgram.mFeatures.hasWaterFog = true;
+		gObjectSimpleNonIndexedWaterProgram.mFeatures.hasAtmospherics = true;
+		gObjectSimpleNonIndexedWaterProgram.mFeatures.hasLighting = true;
+		gObjectSimpleNonIndexedWaterProgram.mFeatures.disableTextureIndex = true;
+		gObjectSimpleNonIndexedWaterProgram.mShaderFiles.clear();
+		gObjectSimpleNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER_ARB));
+		gObjectSimpleNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
+		gObjectSimpleNonIndexedWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectSimpleNonIndexedWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
+		success = gObjectSimpleNonIndexedWaterProgram.createShader(NULL, NULL);
+	}
+
+	if (success)
+	{
+		gObjectFullbrightNonIndexedProgram.mName = "Non Indexed Fullbright Shader";
+		gObjectFullbrightNonIndexedProgram.mFeatures.calculatesAtmospherics = true;
+		gObjectFullbrightNonIndexedProgram.mFeatures.hasGamma = true;
+		gObjectFullbrightNonIndexedProgram.mFeatures.hasTransport = true;
+		gObjectFullbrightNonIndexedProgram.mFeatures.isFullbright = true;
+		gObjectFullbrightNonIndexedProgram.mFeatures.disableTextureIndex = true;
+		gObjectFullbrightNonIndexedProgram.mShaderFiles.clear();
+		gObjectFullbrightNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/fullbrightV.glsl", GL_VERTEX_SHADER_ARB));
+		gObjectFullbrightNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB));
+		gObjectFullbrightNonIndexedProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		success = gObjectFullbrightNonIndexedProgram.createShader(NULL, NULL);
+	}
+
+	if (success)
+	{
+		gObjectFullbrightNonIndexedWaterProgram.mName = "Non Indexed Fullbright Water Shader";
+		gObjectFullbrightNonIndexedWaterProgram.mFeatures.calculatesAtmospherics = true;
+		gObjectFullbrightNonIndexedWaterProgram.mFeatures.isFullbright = true;
+		gObjectFullbrightNonIndexedWaterProgram.mFeatures.hasWaterFog = true;		
+		gObjectFullbrightNonIndexedWaterProgram.mFeatures.hasTransport = true;
+		gObjectFullbrightNonIndexedWaterProgram.mFeatures.disableTextureIndex = true;
+		gObjectFullbrightNonIndexedWaterProgram.mShaderFiles.clear();
+		gObjectFullbrightNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightV.glsl", GL_VERTEX_SHADER_ARB));
+		gObjectFullbrightNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
+		gObjectFullbrightNonIndexedWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectFullbrightNonIndexedWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
+		success = gObjectFullbrightNonIndexedWaterProgram.createShader(NULL, NULL);
+	}
+
+	if (success)
+	{
+		gObjectShinyNonIndexedProgram.mName = "Non Indexed Shiny Shader";
+		gObjectShinyNonIndexedProgram.mFeatures.calculatesAtmospherics = true;
+		gObjectShinyNonIndexedProgram.mFeatures.calculatesLighting = true;
+		gObjectShinyNonIndexedProgram.mFeatures.hasGamma = true;
+		gObjectShinyNonIndexedProgram.mFeatures.hasAtmospherics = true;
+		gObjectShinyNonIndexedProgram.mFeatures.isShiny = true;
+		gObjectShinyNonIndexedProgram.mFeatures.disableTextureIndex = true;
+		gObjectShinyNonIndexedProgram.mShaderFiles.clear();
+		gObjectShinyNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/shinyV.glsl", GL_VERTEX_SHADER_ARB));
+		gObjectShinyNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/shinyF.glsl", GL_FRAGMENT_SHADER_ARB));		
+		gObjectShinyNonIndexedProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		success = gObjectShinyNonIndexedProgram.createShader(NULL, &mShinyUniforms);
+	}
+
+	if (success)
+	{
+		gObjectShinyNonIndexedWaterProgram.mName = "Non Indexed Shiny Water Shader";
+		gObjectShinyNonIndexedWaterProgram.mFeatures.calculatesAtmospherics = true;
+		gObjectShinyNonIndexedWaterProgram.mFeatures.calculatesLighting = true;
+		gObjectShinyNonIndexedWaterProgram.mFeatures.isShiny = true;
+		gObjectShinyNonIndexedWaterProgram.mFeatures.hasWaterFog = true;
+		gObjectShinyNonIndexedWaterProgram.mFeatures.hasAtmospherics = true;
+		gObjectShinyNonIndexedWaterProgram.mFeatures.disableTextureIndex = true;
+		gObjectShinyNonIndexedWaterProgram.mShaderFiles.clear();
+		gObjectShinyNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/shinyWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
+		gObjectShinyNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/shinyV.glsl", GL_VERTEX_SHADER_ARB));
+		gObjectShinyNonIndexedWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectShinyNonIndexedWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
+		success = gObjectShinyNonIndexedWaterProgram.createShader(NULL, &mShinyUniforms);
+	}
+	
+	if (success)
+	{
+		gObjectFullbrightShinyNonIndexedProgram.mName = "Non Indexed Fullbright Shiny Shader";
+		gObjectFullbrightShinyNonIndexedProgram.mFeatures.calculatesAtmospherics = true;
+		gObjectFullbrightShinyNonIndexedProgram.mFeatures.isFullbright = true;
+		gObjectFullbrightShinyNonIndexedProgram.mFeatures.isShiny = true;
+		gObjectFullbrightShinyNonIndexedProgram.mFeatures.hasGamma = true;
+		gObjectFullbrightShinyNonIndexedProgram.mFeatures.hasTransport = true;
+		gObjectFullbrightShinyNonIndexedProgram.mFeatures.disableTextureIndex = true;
+		gObjectFullbrightShinyNonIndexedProgram.mShaderFiles.clear();
+		gObjectFullbrightShinyNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyV.glsl", GL_VERTEX_SHADER_ARB));
+		gObjectFullbrightShinyNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyF.glsl", GL_FRAGMENT_SHADER_ARB));
+		gObjectFullbrightShinyNonIndexedProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		success = gObjectFullbrightShinyNonIndexedProgram.createShader(NULL, &mShinyUniforms);
+	}
+
+	if (success)
+	{
+		gObjectFullbrightShinyNonIndexedWaterProgram.mName = "Non Indexed Fullbright Shiny Water Shader";
+		gObjectFullbrightShinyNonIndexedWaterProgram.mFeatures.calculatesAtmospherics = true;
+		gObjectFullbrightShinyNonIndexedWaterProgram.mFeatures.isFullbright = true;
+		gObjectFullbrightShinyNonIndexedWaterProgram.mFeatures.isShiny = true;
+		gObjectFullbrightShinyNonIndexedWaterProgram.mFeatures.hasGamma = true;
+		gObjectFullbrightShinyNonIndexedWaterProgram.mFeatures.hasTransport = true;
+		gObjectFullbrightShinyNonIndexedWaterProgram.mFeatures.hasWaterFog = true;
+		gObjectFullbrightShinyNonIndexedWaterProgram.mFeatures.disableTextureIndex = true;
+		gObjectFullbrightShinyNonIndexedWaterProgram.mShaderFiles.clear();
+		gObjectFullbrightShinyNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyV.glsl", GL_VERTEX_SHADER_ARB));
+		gObjectFullbrightShinyNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
+		gObjectFullbrightShinyNonIndexedWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectFullbrightShinyNonIndexedWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
+		success = gObjectFullbrightShinyNonIndexedWaterProgram.createShader(NULL, &mShinyUniforms);
+	}
+
 	if (success)
 	{
 		gObjectSimpleProgram.mName = "Simple Shader";
@@ -1352,6 +1739,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectSimpleProgram.mFeatures.hasGamma = true;
 		gObjectSimpleProgram.mFeatures.hasAtmospherics = true;
 		gObjectSimpleProgram.mFeatures.hasLighting = true;
+		gObjectSimpleProgram.mFeatures.mIndexedTextureChannels = 0;
 		gObjectSimpleProgram.mShaderFiles.clear();
 		gObjectSimpleProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectSimpleProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB));
@@ -1367,6 +1755,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectSimpleWaterProgram.mFeatures.hasWaterFog = true;
 		gObjectSimpleWaterProgram.mFeatures.hasAtmospherics = true;
 		gObjectSimpleWaterProgram.mFeatures.hasLighting = true;
+		gObjectSimpleWaterProgram.mFeatures.mIndexedTextureChannels = 0;
 		gObjectSimpleWaterProgram.mShaderFiles.clear();
 		gObjectSimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectSimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
@@ -1382,6 +1771,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectFullbrightProgram.mFeatures.hasGamma = true;
 		gObjectFullbrightProgram.mFeatures.hasTransport = true;
 		gObjectFullbrightProgram.mFeatures.isFullbright = true;
+		gObjectFullbrightProgram.mFeatures.mIndexedTextureChannels = 0;
 		gObjectFullbrightProgram.mShaderFiles.clear();
 		gObjectFullbrightProgram.mShaderFiles.push_back(make_pair("objects/fullbrightV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectFullbrightProgram.mShaderFiles.push_back(make_pair("objects/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB));
@@ -1396,6 +1786,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectFullbrightWaterProgram.mFeatures.isFullbright = true;
 		gObjectFullbrightWaterProgram.mFeatures.hasWaterFog = true;		
 		gObjectFullbrightWaterProgram.mFeatures.hasTransport = true;
+		gObjectFullbrightWaterProgram.mFeatures.mIndexedTextureChannels = 0;
 		gObjectFullbrightWaterProgram.mShaderFiles.clear();
 		gObjectFullbrightWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectFullbrightWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
@@ -1412,6 +1803,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectShinyProgram.mFeatures.hasGamma = true;
 		gObjectShinyProgram.mFeatures.hasAtmospherics = true;
 		gObjectShinyProgram.mFeatures.isShiny = true;
+		gObjectShinyProgram.mFeatures.mIndexedTextureChannels = 0;
 		gObjectShinyProgram.mShaderFiles.clear();
 		gObjectShinyProgram.mShaderFiles.push_back(make_pair("objects/shinyV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectShinyProgram.mShaderFiles.push_back(make_pair("objects/shinyF.glsl", GL_FRAGMENT_SHADER_ARB));		
@@ -1427,6 +1819,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectShinyWaterProgram.mFeatures.isShiny = true;
 		gObjectShinyWaterProgram.mFeatures.hasWaterFog = true;
 		gObjectShinyWaterProgram.mFeatures.hasAtmospherics = true;
+		gObjectShinyWaterProgram.mFeatures.mIndexedTextureChannels = 0;
 		gObjectShinyWaterProgram.mShaderFiles.clear();
 		gObjectShinyWaterProgram.mShaderFiles.push_back(make_pair("objects/shinyWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
 		gObjectShinyWaterProgram.mShaderFiles.push_back(make_pair("objects/shinyV.glsl", GL_VERTEX_SHADER_ARB));
@@ -1443,6 +1836,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectFullbrightShinyProgram.mFeatures.isShiny = true;
 		gObjectFullbrightShinyProgram.mFeatures.hasGamma = true;
 		gObjectFullbrightShinyProgram.mFeatures.hasTransport = true;
+		gObjectFullbrightShinyProgram.mFeatures.mIndexedTextureChannels = 0;
 		gObjectFullbrightShinyProgram.mShaderFiles.clear();
 		gObjectFullbrightShinyProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectFullbrightShinyProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyF.glsl", GL_FRAGMENT_SHADER_ARB));
@@ -1459,6 +1853,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectFullbrightShinyWaterProgram.mFeatures.hasGamma = true;
 		gObjectFullbrightShinyWaterProgram.mFeatures.hasTransport = true;
 		gObjectFullbrightShinyWaterProgram.mFeatures.hasWaterFog = true;
+		gObjectFullbrightShinyWaterProgram.mFeatures.mIndexedTextureChannels = 0;
 		gObjectFullbrightShinyWaterProgram.mShaderFiles.clear();
 		gObjectFullbrightShinyWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectFullbrightShinyWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
@@ -1478,6 +1873,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 			gSkinnedObjectSimpleProgram.mFeatures.hasAtmospherics = true;
 			gSkinnedObjectSimpleProgram.mFeatures.hasLighting = true;
 			gSkinnedObjectSimpleProgram.mFeatures.hasObjectSkinning = true;
+			gSkinnedObjectSimpleProgram.mFeatures.disableTextureIndex = true;
 			gSkinnedObjectSimpleProgram.mShaderFiles.clear();
 			gSkinnedObjectSimpleProgram.mShaderFiles.push_back(make_pair("objects/simpleSkinnedV.glsl", GL_VERTEX_SHADER_ARB));
 			gSkinnedObjectSimpleProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB));
@@ -1493,6 +1889,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 			gSkinnedObjectFullbrightProgram.mFeatures.hasTransport = true;
 			gSkinnedObjectFullbrightProgram.mFeatures.isFullbright = true;
 			gSkinnedObjectFullbrightProgram.mFeatures.hasObjectSkinning = true;
+			gSkinnedObjectFullbrightProgram.mFeatures.disableTextureIndex = true;
 			gSkinnedObjectFullbrightProgram.mShaderFiles.clear();
 			gSkinnedObjectFullbrightProgram.mShaderFiles.push_back(make_pair("objects/fullbrightSkinnedV.glsl", GL_VERTEX_SHADER_ARB));
 			gSkinnedObjectFullbrightProgram.mShaderFiles.push_back(make_pair("objects/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB));
@@ -1509,6 +1906,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 			gSkinnedObjectFullbrightShinyProgram.mFeatures.isShiny = true;
 			gSkinnedObjectFullbrightShinyProgram.mFeatures.isFullbright = true;
 			gSkinnedObjectFullbrightShinyProgram.mFeatures.hasObjectSkinning = true;
+			gSkinnedObjectFullbrightShinyProgram.mFeatures.disableTextureIndex = true;
 			gSkinnedObjectFullbrightShinyProgram.mShaderFiles.clear();
 			gSkinnedObjectFullbrightShinyProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinySkinnedV.glsl", GL_VERTEX_SHADER_ARB));
 			gSkinnedObjectFullbrightShinyProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyF.glsl", GL_FRAGMENT_SHADER_ARB));
@@ -1525,6 +1923,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 			gSkinnedObjectShinySimpleProgram.mFeatures.hasAtmospherics = true;
 			gSkinnedObjectShinySimpleProgram.mFeatures.hasObjectSkinning = true;
 			gSkinnedObjectShinySimpleProgram.mFeatures.isShiny = true;
+			gSkinnedObjectShinySimpleProgram.mFeatures.disableTextureIndex = true;
 			gSkinnedObjectShinySimpleProgram.mShaderFiles.clear();
 			gSkinnedObjectShinySimpleProgram.mShaderFiles.push_back(make_pair("objects/shinySimpleSkinnedV.glsl", GL_VERTEX_SHADER_ARB));
 			gSkinnedObjectShinySimpleProgram.mShaderFiles.push_back(make_pair("objects/shinyF.glsl", GL_FRAGMENT_SHADER_ARB));
@@ -1540,9 +1939,11 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 			gSkinnedObjectSimpleWaterProgram.mFeatures.hasGamma = true;
 			gSkinnedObjectSimpleWaterProgram.mFeatures.hasAtmospherics = true;
 			gSkinnedObjectSimpleWaterProgram.mFeatures.hasLighting = true;
+			gSkinnedObjectSimpleWaterProgram.mFeatures.disableTextureIndex = true;
 			gSkinnedObjectSimpleWaterProgram.mFeatures.hasWaterFog = true;
 			gSkinnedObjectSimpleWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
 			gSkinnedObjectSimpleWaterProgram.mFeatures.hasObjectSkinning = true;
+			gSkinnedObjectSimpleWaterProgram.mFeatures.disableTextureIndex = true;
 			gSkinnedObjectSimpleWaterProgram.mShaderFiles.clear();
 			gSkinnedObjectSimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleSkinnedV.glsl", GL_VERTEX_SHADER_ARB));
 			gSkinnedObjectSimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
@@ -1559,6 +1960,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 			gSkinnedObjectFullbrightWaterProgram.mFeatures.isFullbright = true;
 			gSkinnedObjectFullbrightWaterProgram.mFeatures.hasObjectSkinning = true;
 			gSkinnedObjectFullbrightWaterProgram.mFeatures.hasWaterFog = true;
+			gSkinnedObjectFullbrightWaterProgram.mFeatures.disableTextureIndex = true;
 			gSkinnedObjectFullbrightWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
 			gSkinnedObjectFullbrightWaterProgram.mShaderFiles.clear();
 			gSkinnedObjectFullbrightWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightSkinnedV.glsl", GL_VERTEX_SHADER_ARB));
@@ -1577,6 +1979,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 			gSkinnedObjectFullbrightShinyWaterProgram.mFeatures.isFullbright = true;
 			gSkinnedObjectFullbrightShinyWaterProgram.mFeatures.hasObjectSkinning = true;
 			gSkinnedObjectFullbrightShinyWaterProgram.mFeatures.hasWaterFog = true;
+			gSkinnedObjectFullbrightShinyWaterProgram.mFeatures.disableTextureIndex = true;
 			gSkinnedObjectFullbrightShinyWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
 			gSkinnedObjectFullbrightShinyWaterProgram.mShaderFiles.clear();
 			gSkinnedObjectFullbrightShinyWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinySkinnedV.glsl", GL_VERTEX_SHADER_ARB));
@@ -1595,6 +1998,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 			gSkinnedObjectShinySimpleWaterProgram.mFeatures.hasObjectSkinning = true;
 			gSkinnedObjectShinySimpleWaterProgram.mFeatures.isShiny = true;
 			gSkinnedObjectShinySimpleWaterProgram.mFeatures.hasWaterFog = true;
+			gSkinnedObjectShinySimpleWaterProgram.mFeatures.disableTextureIndex = true;
 			gSkinnedObjectShinySimpleWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
 			gSkinnedObjectShinySimpleWaterProgram.mShaderFiles.clear();
 			gSkinnedObjectShinySimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/shinySimpleSkinnedV.glsl", GL_VERTEX_SHADER_ARB));
@@ -1635,6 +2039,7 @@ BOOL LLViewerShaderMgr::loadShadersAvatar()
 		gAvatarProgram.mFeatures.hasGamma = true;
 		gAvatarProgram.mFeatures.hasAtmospherics = true;
 		gAvatarProgram.mFeatures.hasLighting = true;
+		gAvatarProgram.mFeatures.disableTextureIndex = true;
 		gAvatarProgram.mShaderFiles.clear();
 		gAvatarProgram.mShaderFiles.push_back(make_pair("avatar/avatarV.glsl", GL_VERTEX_SHADER_ARB));
 		gAvatarProgram.mShaderFiles.push_back(make_pair("avatar/avatarF.glsl", GL_FRAGMENT_SHADER_ARB));
@@ -1650,6 +2055,7 @@ BOOL LLViewerShaderMgr::loadShadersAvatar()
 			gAvatarWaterProgram.mFeatures.hasWaterFog = true;
 			gAvatarWaterProgram.mFeatures.hasAtmospherics = true;
 			gAvatarWaterProgram.mFeatures.hasLighting = true;
+			gAvatarWaterProgram.mFeatures.disableTextureIndex = true;
 			gAvatarWaterProgram.mShaderFiles.clear();
 			gAvatarWaterProgram.mShaderFiles.push_back(make_pair("avatar/avatarV.glsl", GL_VERTEX_SHADER_ARB));
 			gAvatarWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
@@ -1670,6 +2076,7 @@ BOOL LLViewerShaderMgr::loadShadersAvatar()
 	{
 		gAvatarPickProgram.mName = "Avatar Pick Shader";
 		gAvatarPickProgram.mFeatures.hasSkinning = true;
+		gAvatarPickProgram.mFeatures.disableTextureIndex = true;
 		gAvatarPickProgram.mShaderFiles.clear();
 		gAvatarPickProgram.mShaderFiles.push_back(make_pair("avatar/pickAvatarV.glsl", GL_VERTEX_SHADER_ARB));
 		gAvatarPickProgram.mShaderFiles.push_back(make_pair("avatar/pickAvatarF.glsl", GL_FRAGMENT_SHADER_ARB));
@@ -1686,6 +2093,7 @@ BOOL LLViewerShaderMgr::loadShadersAvatar()
 		gAvatarEyeballProgram.mFeatures.hasGamma = true;
 		gAvatarEyeballProgram.mFeatures.hasAtmospherics = true;
 		gAvatarEyeballProgram.mFeatures.hasLighting = true;
+		gAvatarEyeballProgram.mFeatures.disableTextureIndex = true;
 		gAvatarEyeballProgram.mShaderFiles.clear();
 		gAvatarEyeballProgram.mShaderFiles.push_back(make_pair("avatar/eyeballV.glsl", GL_VERTEX_SHADER_ARB));
 		gAvatarEyeballProgram.mShaderFiles.push_back(make_pair("avatar/eyeballF.glsl", GL_FRAGMENT_SHADER_ARB));
diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h
index 72ac5e02ee50d0931bfd595128732d201103f5d2..6ecba65470c8705de9424ec8cea924c306c8160d 100644
--- a/indra/newview/llviewershadermgr.h
+++ b/indra/newview/llviewershadermgr.h
@@ -298,16 +298,25 @@ extern LLVector4			gShinyOrigin;
 //object shaders
 extern LLGLSLShader			gObjectSimpleProgram;
 extern LLGLSLShader			gObjectSimpleWaterProgram;
+extern LLGLSLShader			gObjectSimpleNonIndexedProgram;
+extern LLGLSLShader			gObjectSimpleNonIndexedWaterProgram;
 extern LLGLSLShader			gObjectFullbrightProgram;
 extern LLGLSLShader			gObjectFullbrightWaterProgram;
+extern LLGLSLShader			gObjectFullbrightNonIndexedProgram;
+extern LLGLSLShader			gObjectFullbrightNonIndexedWaterProgram;
 
 extern LLGLSLShader			gObjectSimpleLODProgram;
 extern LLGLSLShader			gObjectFullbrightLODProgram;
 
 extern LLGLSLShader			gObjectFullbrightShinyProgram;
 extern LLGLSLShader			gObjectFullbrightShinyWaterProgram;
+extern LLGLSLShader			gObjectFullbrightShinyNonIndexedProgram;
+extern LLGLSLShader			gObjectFullbrightShinyNonIndexedWaterProgram;
+
 extern LLGLSLShader			gObjectShinyProgram;
 extern LLGLSLShader			gObjectShinyWaterProgram;
+extern LLGLSLShader			gObjectShinyNonIndexedProgram;
+extern LLGLSLShader			gObjectShinyNonIndexedWaterProgram;
 
 extern LLGLSLShader			gSkinnedObjectSimpleProgram;
 extern LLGLSLShader			gSkinnedObjectFullbrightProgram;
@@ -349,6 +358,7 @@ extern LLGLSLShader			gDeferredImpostorProgram;
 extern LLGLSLShader			gDeferredEdgeProgram;
 extern LLGLSLShader			gDeferredWaterProgram;
 extern LLGLSLShader			gDeferredDiffuseProgram;
+extern LLGLSLShader			gDeferredNonIndexedDiffuseProgram;
 extern LLGLSLShader			gDeferredSkinnedDiffuseProgram;
 extern LLGLSLShader			gDeferredSkinnedBumpProgram;
 extern LLGLSLShader			gDeferredSkinnedAlphaProgram;
@@ -373,8 +383,11 @@ extern LLGLSLShader			gDeferredAvatarShadowProgram;
 extern LLGLSLShader			gDeferredAttachmentShadowProgram;
 extern LLGLSLShader			gDeferredAlphaProgram;
 extern LLGLSLShader			gDeferredFullbrightProgram;
+extern LLGLSLShader			gDeferredAvatarEyesProgram;
 extern LLGLSLShader			gDeferredAvatarAlphaProgram;
-
+extern LLGLSLShader			gDeferredWLSkyProgram;
+extern LLGLSLShader			gDeferredWLCloudProgram;
+extern LLGLSLShader			gDeferredStarProgram;
 extern LLGLSLShader			gLuminanceGatherProgram;
 
 //current avatar shader parameter pointer
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index af06421bf9db7c1d4686d739fc8df6d9879cc2c6..4da0f80a00281beff887a3fd191d8ebf6cb14942 100644
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -1168,6 +1168,7 @@ void LLViewerFetchedTexture::init(bool firstinit)
 	mSavedRawDiscardLevel = -1 ;
 	mDesiredSavedRawDiscardLevel = -1 ;
 	mLastReferencedSavedRawImageTime = 0.0f ;
+	mKeptSavedRawImageTime = 0.f ;
 	mLastCallBackActiveTime = 0.f;
 }
 
@@ -2696,8 +2697,16 @@ void LLViewerFetchedTexture::saveRawImage()
 	mLastReferencedSavedRawImageTime = sCurrentTime ;
 }
 
-void LLViewerFetchedTexture::forceToSaveRawImage(S32 desired_discard) 
+void LLViewerFetchedTexture::forceToSaveRawImage(S32 desired_discard, F32 kept_time) 
 { 
+	mKeptSavedRawImageTime = kept_time ;
+	mLastReferencedSavedRawImageTime = sCurrentTime ;
+
+	if(mSavedRawDiscardLevel > -1 && mSavedRawDiscardLevel <= desired_discard)
+	{
+		return ; //raw imge is ready.
+	}
+
 	if(!mForceToSaveRawImage || mDesiredSavedRawDiscardLevel < 0 || mDesiredSavedRawDiscardLevel > desired_discard)
 	{
 		mForceToSaveRawImage = TRUE ;
@@ -2713,11 +2722,16 @@ void LLViewerFetchedTexture::forceToSaveRawImage(S32 desired_discard)
 
 			mRawImage = NULL ;
 			mRawDiscardLevel = INVALID_DISCARD_LEVEL ;
-		}
+		}		
 	}
 }
 void LLViewerFetchedTexture::destroySavedRawImage()
 {
+	if(mLastReferencedSavedRawImageTime < mKeptSavedRawImageTime)
+	{
+		return ; //keep the saved raw image.
+	}
+
 	mForceToSaveRawImage  = FALSE ;
 	mSaveRawImage = FALSE ;
 
@@ -2729,6 +2743,7 @@ void LLViewerFetchedTexture::destroySavedRawImage()
 	mSavedRawDiscardLevel = -1 ;
 	mDesiredSavedRawDiscardLevel = -1 ;
 	mLastReferencedSavedRawImageTime = 0.0f ;
+	mKeptSavedRawImageTime = 0.f ;
 }
 
 LLImageRaw* LLViewerFetchedTexture::getSavedRawImage() 
diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h
index d512f8ec3abc4f03a34a20aa4fbc8e4e5f28baf7..c5b8c8923ad52bf6b4eb16b363778221ee106e07 100644
--- a/indra/newview/llviewertexture.h
+++ b/indra/newview/llviewertexture.h
@@ -465,7 +465,7 @@ class LLViewerFetchedTexture : public LLViewerTexture
 	S32         getCachedRawImageLevel() const {return mCachedRawDiscardLevel;}
 	BOOL        isCachedRawImageReady() const {return mCachedRawImageReady ;}
 	BOOL        isRawImageValid()const { return mIsRawImageValid ; }	
-	void        forceToSaveRawImage(S32 desired_discard = 0) ;
+	void        forceToSaveRawImage(S32 desired_discard = 0, F32 kept_time = 0.f) ;
 	/*virtual*/ void setCachedRawImage(S32 discard_level, LLImageRaw* imageraw) ;
 	void        destroySavedRawImage() ;
 	LLImageRaw* getSavedRawImage() ;
@@ -550,6 +550,7 @@ class LLViewerFetchedTexture : public LLViewerTexture
 	S32 mSavedRawDiscardLevel;
 	S32 mDesiredSavedRawDiscardLevel;
 	F32 mLastReferencedSavedRawImageTime ;
+	F32 mKeptSavedRawImageTime ;
 
 	//a small version of the copy of the raw image (<= 64 * 64)
 	LLPointer<LLImageRaw> mCachedRawImage;
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index 34d15a597e99466b91d77678c2fd7635384ebd2b..b1441cc2812341abf558e3d92395b53f0b3bfc52 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -601,7 +601,7 @@ class LLDebugText
 			
 			ypos += y_inc;
 
-			if (gSavedSettings.getBOOL("MeshEnabled"))
+			if (gMeshRepo.meshRezEnabled())
 			{
 				addText(xpos, ypos, llformat("%.3f MB Mesh Data Received", LLMeshRepository::sBytesReceived/(1024.f*1024.f)));
 				
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index ec2b5a4c9800cc7ac7bd3711bc7984971d04151a..1b53348b43b46836c050c16c1caa84ddbd297253 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -56,6 +56,7 @@
 #include "lleditingmotion.h"
 #include "llemote.h"
 //#include "llfirstuse.h"
+#include "llfloatertools.h"
 #include "llheadrotmotion.h"
 #include "llhudeffecttrail.h"
 #include "llhudmanager.h"
@@ -1541,7 +1542,35 @@ BOOL LLVOAvatar::lineSegmentIntersect(const LLVector3& start, const LLVector3& e
 				return TRUE;
 			}
 		}
+
+		if (isSelf())
+		{
+			for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); 
+			 iter != mAttachmentPoints.end();
+			 ++iter)
+			{
+				LLViewerJointAttachment* attachment = iter->second;
+
+				for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
+					 attachment_iter != attachment->mAttachedObjects.end();
+					 ++attachment_iter)
+				{
+					LLViewerObject* attached_object = (*attachment_iter);
+					
+					if (attached_object && !attached_object->isDead() && attachment->getValid())
+					{
+						LLDrawable* drawable = attached_object->mDrawable;
+						if (drawable->isState(LLDrawable::RIGGED))
+						{ //regenerate octree for rigged attachment
+							gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_RIGGED, TRUE);
+						}
+					}
+				}
+			}
+		}
 	}
+
+	
 	
 	LLVector3 position;
 	if (mNameText.notNull() && mNameText->lineSegmentIntersect(start, end, position))
@@ -1557,6 +1586,56 @@ BOOL LLVOAvatar::lineSegmentIntersect(const LLVector3& start, const LLVector3& e
 	return FALSE;
 }
 
+LLViewerObject* LLVOAvatar::lineSegmentIntersectRiggedAttachments(const LLVector3& start, const LLVector3& end,
+									  S32 face,
+									  BOOL pick_transparent,
+									  S32* face_hit,
+									  LLVector3* intersection,
+									  LLVector2* tex_coord,
+									  LLVector3* normal,
+									  LLVector3* bi_normal)
+{
+	if (isSelf() && !gAgent.needsRenderAvatar())
+	{
+		return NULL;
+	}
+
+	LLViewerObject* hit = NULL;
+
+	if (lineSegmentBoundingBox(start, end))
+	{
+		LLVector3 local_end = end;
+		LLVector3 local_intersection;
+
+		for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); 
+			iter != mAttachmentPoints.end();
+			++iter)
+		{
+			LLViewerJointAttachment* attachment = iter->second;
+
+			for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
+					attachment_iter != attachment->mAttachedObjects.end();
+					++attachment_iter)
+			{
+				LLViewerObject* attached_object = (*attachment_iter);
+					
+				if (attached_object->lineSegmentIntersect(start, local_end, face, pick_transparent, face_hit, &local_intersection, tex_coord, normal, bi_normal))
+				{
+					local_end = local_intersection;
+					if (intersection)
+					{
+						*intersection = local_intersection;
+					}
+					
+					hit = attached_object;
+				}
+			}
+		}
+	}
+		
+	return hit;
+}
+
 //-----------------------------------------------------------------------------
 // parseSkeletonFile()
 //-----------------------------------------------------------------------------
@@ -4968,19 +5047,6 @@ void LLVOAvatar::resetSpecificJointPosition( const std::string& name )
 //-----------------------------------------------------------------------------
 void LLVOAvatar::resetJointPositionsToDefault( void )
 {
-	const LLVector3& avPos = getCharacterPosition();
-	
-	//Reposition the pelvis
-	LLJoint* pPelvis = mRoot.findJoint("mPelvis");
-	if ( pPelvis )
-	{
-		pPelvis->setPosition( avPos + pPelvis->getPosition() );
-	}
-	else 
-	{
-		llwarns<<"Can't get pelvis joint."<<llendl;	
-		return;
-	}
 
 	//Subsequent joints are relative to pelvis
 	for( S32 i = 0; i < (S32)mNumJoints; ++i )
@@ -4991,7 +5057,7 @@ void LLVOAvatar::resetJointPositionsToDefault( void )
 
 			pJoint->setId( LLUUID::null );
 			//restore joints to default positions, however skip over the pelvis
-			if ( pJoint && pPelvis != pJoint )
+			if ( pJoint )
 			{
 				pJoint->restoreOldXform();
 			}
@@ -6017,7 +6083,7 @@ void LLVOAvatar::cleanupAttachedMesh( LLViewerObject* pVO )
 		LLVOVolume* pVObj = pVO->mDrawable->getVOVolume();
 		if ( pVObj )
 		{
-			const LLMeshSkinInfo* pSkinData = gMeshRepo.getSkinInfo( pVObj->getVolume()->getParams().getSculptID() );
+			const LLMeshSkinInfo* pSkinData = gMeshRepo.getSkinInfo( pVObj->getVolume()->getParams().getSculptID(), pVObj );
 			if ( pSkinData )
 			{
 				const int jointCnt = pSkinData->mJointNames.size();
@@ -6028,6 +6094,14 @@ void LLVOAvatar::cleanupAttachedMesh( LLViewerObject* pVO )
 					if ( bindCnt > 0 )
 					{
 						LLVOAvatar::resetJointPositionsToDefault();
+						//Need to handle the repositioning of the cam, updating rig data etc during outfit editing 
+						//This handles the case where we detach a replacement rig.
+						if ( gAgentCamera.cameraCustomizeAvatar() )
+						{
+							gAgent.unpauseAnimation();
+							//Still want to refocus on head bone
+							gAgentCamera.changeCameraToCustomizeAvatar();
+						}
 					}
 				}
 			}				
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index 295799fd247bf95a2c86f3bb999484ce2be9d799..03c0498a2ac94c5147e7dc89570b56e6ae9b3eae 100644
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -145,6 +145,14 @@ class LLVOAvatar :
 												 LLVector2* tex_coord = NULL,      // return the texture coordinates of the intersection point
 												 LLVector3* normal = NULL,         // return the surface normal at the intersection point
 												 LLVector3* bi_normal = NULL);     // return the surface bi-normal at the intersection point
+	LLViewerObject*	lineSegmentIntersectRiggedAttachments(const LLVector3& start, const LLVector3& end,
+												 S32 face = -1,                    // which face to check, -1 = ALL_SIDES
+												 BOOL pick_transparent = FALSE,
+												 S32* face_hit = NULL,             // which face was hit
+												 LLVector3* intersection = NULL,   // return the intersection point
+												 LLVector2* tex_coord = NULL,      // return the texture coordinates of the intersection point
+												 LLVector3* normal = NULL,         // return the surface normal at the intersection point
+												 LLVector3* bi_normal = NULL);     // return the surface bi-normal at the intersection point
 
 	//--------------------------------------------------------------------
 	// LLCharacter interface and related
diff --git a/indra/newview/llvoclouds.cpp b/indra/newview/llvoclouds.cpp
index 78aa6e6ab8a5fa6b4365a5a7b96f98b5a67e9cb5..478708cd7832f522ee4f027e297470f8343e4bd2 100644
--- a/indra/newview/llvoclouds.cpp
+++ b/indra/newview/llvoclouds.cpp
@@ -244,9 +244,13 @@ void LLVOClouds::getGeometry(S32 te,
 	vtx[2] = puff_pos_agent + right + up;
 	vtx[3] = puff_pos_agent + right - up;
 
+	verticesp->mV[3] = 0.f;
 	*verticesp++  = vtx[0];
+	verticesp->mV[3] = 0.f;
 	*verticesp++  = vtx[1];
+	verticesp->mV[3] = 0.f;
 	*verticesp++  = vtx[2];
+	verticesp->mV[3] = 0.f;
 	*verticesp++  = vtx[3];
 
 	*texcoordsp++ = uvs[0];
diff --git a/indra/newview/llvopartgroup.cpp b/indra/newview/llvopartgroup.cpp
index 6f354b78b1e1fa953e105dc98fd1e6330cd9e3d7..a4b0910c926c0abb839fcc7f4d097e43077cfccf 100644
--- a/indra/newview/llvopartgroup.cpp
+++ b/indra/newview/llvopartgroup.cpp
@@ -324,10 +324,18 @@ void LLVOPartGroup::getGeometry(S32 idx,
 
 
 	LLVector3 normal = -LLViewerCamera::getInstance()->getXAxis();
-		
+
+	//HACK -- the verticesp->mV[3] = 0.f here are to set the texture index to 0 (particles don't use texture batching, maybe they should)
+	// this works because there is actually a 4th float stored after the vertex position which is used as a texture index
+	// also, somebody please VECTORIZE THIS
+
+	verticesp->mV[3] = 0.f;
 	*verticesp++ = part_pos_agent + up - right;
+	verticesp->mV[3] = 0.f;
 	*verticesp++ = part_pos_agent - up - right;
+	verticesp->mV[3] = 0.f;
 	*verticesp++ = part_pos_agent + up + right;
+	verticesp->mV[3] = 0.f;
 	*verticesp++ = part_pos_agent - up + right;
 
 	*colorsp++ = part.mColor;
@@ -360,7 +368,7 @@ U32 LLVOPartGroup::getPartitionType() const
 }
 
 LLParticlePartition::LLParticlePartition()
-: LLSpatialPartition(LLDrawPoolAlpha::VERTEX_DATA_MASK, TRUE, GL_STREAM_DRAW_ARB)
+: LLSpatialPartition(LLDrawPoolAlpha::VERTEX_DATA_MASK | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, GL_STREAM_DRAW_ARB)
 {
 	mRenderPass = LLRenderPass::PASS_ALPHA;
 	mDrawableType = LLPipeline::RENDER_TYPE_PARTICLES;
@@ -418,6 +426,7 @@ void LLParticlePartition::addGeometryCount(LLSpatialGroup* group, U32& vertex_co
 			mFaceList.push_back(facep);
 			vertex_count += facep->getGeomCount();
 			index_count += facep->getIndicesCount();
+			llassert(facep->getIndicesCount() < 65536);
 		}
 		
 		obj->mDepth /= count;
diff --git a/indra/newview/llvosky.cpp b/indra/newview/llvosky.cpp
index 6396bc042dba7fc9f4b01559b83adfb9fc25ae99..800af26b698c966f71926005ac293673a62f64fe 100644
--- a/indra/newview/llvosky.cpp
+++ b/indra/newview/llvosky.cpp
@@ -1483,6 +1483,8 @@ BOOL LLVOSky::updateHeavenlyBodyGeometry(LLDrawable *drawable, const S32 f, cons
 		facep->setVertexBuffer(buff);
 	}
 
+	llassert(facep->getVertexBuffer()->getNumIndices() == 6);
+
 	index_offset = facep->getGeometry(verticesp,normalsp,texCoordsp, indicesp);
 
 	if (-1 == index_offset)
diff --git a/indra/newview/llvosurfacepatch.cpp b/indra/newview/llvosurfacepatch.cpp
index dbcd4f50cadf6549509afcd1aee89ee4dd79601d..510525259f4c9a6f64fee619aafb1785880adf12 100644
--- a/indra/newview/llvosurfacepatch.cpp
+++ b/indra/newview/llvosurfacepatch.cpp
@@ -375,6 +375,8 @@ void LLVOSurfacePatch::updateMainGeometry(LLFace *facep,
 	S32 num_vertices, num_indices;
 	U32 index;
 
+	llassert(mLastStride > 0);
+
 	render_stride = mLastStride;
 	patch_size = mPatchp->getSurface()->getGridsPerPatchEdge();
 	S32 vert_size = patch_size / render_stride;
diff --git a/indra/newview/llvotree.cpp b/indra/newview/llvotree.cpp
index 8946d4e0b60c2f0f0ba91aa1a827ff5b573f712e..3c7fe708e61e5537d342c72f269567777e426914 100644
--- a/indra/newview/llvotree.cpp
+++ b/indra/newview/llvotree.cpp
@@ -980,11 +980,6 @@ void LLVOTree::appendMesh(LLStrider<LLVector3>& vertices,
 	for (S32 i = 0; i < index_count; i++)
 	{
 		U16 index = index_offset + i;
-		if (idx[index] >= vert_start + vert_count ||
-			idx[index] < vert_start)
-		{
-			llerrs << "WTF?" << llendl;
-		}
 		*indices++ = idx[index]-vert_start+cur_idx;
 	}
 
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index e9a8c9b80aab16c5feccf7f1834cb8fd97b0d68b..c5e2c56e4b298a8de20d4a09a0c0f525c33160de 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -73,6 +73,7 @@
 #include "llagent.h"
 #include "llviewermediafocus.h"
 #include "lldatapacker.h"
+#include "llviewershadermgr.h"
 #include "llvoavatar.h"
 #include "llvocache.h"
 
@@ -1095,8 +1096,6 @@ void LLVOVolume::updateSculptTexture()
 	
 }
 
-
-
 void LLVOVolume::notifyMeshLoaded()
 { 
 	mSculptChanged = TRUE;
@@ -1222,7 +1221,7 @@ BOOL LLVOVolume::calcLOD()
 	}
 	
 	//hold onto unmodified distance for debugging
-	F32 debug_distance = distance;
+	//F32 debug_distance = distance;
 	
 	distance *= sDistanceFactor;
 
@@ -1245,7 +1244,9 @@ BOOL LLVOVolume::calcLOD()
 
 	if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_LOD_INFO))
 	{
-		setDebugText(llformat("%.2f:%.2f, %d", debug_distance, radius, cur_detail));
+		//setDebugText(llformat("%.2f:%.2f, %d", debug_distance, radius, cur_detail));
+
+		setDebugText(llformat("%d", mDrawable->getFace(0)->getTextureIndex()));
 	}
 
 	if (cur_detail != mLOD)
@@ -1274,6 +1275,15 @@ BOOL LLVOVolume::updateLOD()
 		gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, FALSE);
 		mLODChanged = TRUE;
 	}
+	else
+	{
+		F32 new_radius = getBinRadius();
+		F32 old_radius = mDrawable->getBinRadius();
+		if (new_radius < old_radius * 0.9f || new_radius > old_radius*1.1f)
+		{
+			gPipeline.markPartitionMove(mDrawable);
+		}
+	}
 
 	lod_changed = lod_changed || LLViewerObject::updateLOD();
 	
@@ -3086,16 +3096,28 @@ U32 LLVOVolume::getRenderCost(std::set<LLUUID> &textures) const
 
 F32 LLVOVolume::getStreamingCost(S32* bytes, S32* visible_bytes)
 {
+	F32 radius = getScale().length();
+
 	if (isMesh())
 	{	
 		LLSD& header = gMeshRepo.getMeshHeader(getVolume()->getParams().getSculptID());
 
-		F32 radius = getScale().length();
-		
 		return LLMeshRepository::getStreamingCost(header, radius, bytes, visible_bytes, mLOD);
 	}
-		
-	return 0.f;
+	else
+	{
+		LLVolume* volume = getVolume();
+		S32 counts[4];
+		LLVolume::getLoDTriangleCounts(volume->getParams(), counts);
+
+		LLSD header;
+		header["lowest_lod"]["size"] = counts[0] * 10;
+		header["low_lod"]["size"] = counts[1] * 10;
+		header["medium_lod"]["size"] = counts[2] * 10;
+		header["high_lod"]["size"] = counts[3] * 10;
+
+		return LLMeshRepository::getStreamingCost(header, radius);
+	}	
 }
 
 U32 LLVOVolume::getTriangleCount()
@@ -3187,6 +3209,10 @@ F32 LLVOVolume::getBinRadius()
 	
 	F32 scale = 1.f;
 
+	S32 size_factor = llmax(gSavedSettings.getS32("OctreeStaticObjectSizeFactor"), 1);
+	S32 attachment_size_factor = llmax(gSavedSettings.getS32("OctreeAttachmentSizeFactor"), 1);
+	LLVector3 distance_factor = gSavedSettings.getVector3("OctreeDistanceFactor");
+	LLVector3 alpha_distance_factor = gSavedSettings.getVector3("OctreeAlphaDistanceFactor");
 	const LLVector4a* ext = mDrawable->getSpatialExtents();
 	
 	BOOL shrink_wrap = mDrawable->isAnimating();
@@ -3216,6 +3242,8 @@ F32 LLVOVolume::getBinRadius()
 		radius = llmin(bounds.mV[1], bounds.mV[2]);
 		radius = llmin(radius, bounds.mV[0]);
 		radius *= 0.5f;
+		radius *= 1.f+mDrawable->mDistanceWRTCamera*alpha_distance_factor[1];
+		radius += mDrawable->mDistanceWRTCamera*alpha_distance_factor[0];
 	}
 	else if (shrink_wrap)
 	{
@@ -3226,24 +3254,19 @@ F32 LLVOVolume::getBinRadius()
 	}
 	else if (mDrawable->isStatic())
 	{
-		/*if (mDrawable->getRadius() < 2.0f)
-		{
-			radius = 16.f;
-		}
-		else
-		{
-			radius = llmax(mDrawable->getRadius(), 32.f);
-		}*/
-
-		radius = (((S32) mDrawable->getRadius())/2+1)*8;
+		radius = llmax((S32) mDrawable->getRadius(), 1)*size_factor;
+		radius *= 1.f + mDrawable->mDistanceWRTCamera * distance_factor[1];
+		radius += mDrawable->mDistanceWRTCamera * distance_factor[0];
 	}
 	else if (mDrawable->getVObj()->isAttachment())
 	{
-		radius = (((S32) (mDrawable->getRadius()*4)+1))*2;
+		radius = llmax((S32) mDrawable->getRadius(),1)*attachment_size_factor;
 	}
 	else
 	{
-		radius = 8.f;
+		radius = mDrawable->getRadius();
+		radius *= 1.f + mDrawable->mDistanceWRTCamera * distance_factor[1];
+		radius += mDrawable->mDistanceWRTCamera * distance_factor[0];
 	}
 
 	return llclamp(radius*scale, 0.5f, 256.f);
@@ -3342,7 +3365,8 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& e
 	{
 		if (LLFloater::isVisible(gFloaterTools) && getAvatar()->isSelf())
 		{
-			gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_RIGGED, TRUE);
+			updateRiggedVolume();
+			genBBoxes(FALSE);
 			volume = mRiggedVolume;
 			transform = false;
 		}
@@ -3521,7 +3545,7 @@ void LLVOVolume::updateRiggedVolume()
 
 	LLVolume* volume = getVolume();
 
-	const LLMeshSkinInfo* skin = gMeshRepo.getSkinInfo(volume->getParams().getSculptID());
+	const LLMeshSkinInfo* skin = gMeshRepo.getSkinInfo(volume->getParams().getSculptID(), this);
 
 	if (!skin)
 	{
@@ -3712,6 +3736,21 @@ LLVolumeBridge::LLVolumeBridge(LLDrawable* drawablep)
 	mSlopRatio = 0.25f;
 }
 
+bool can_batch_texture(LLFace* facep)
+{
+	if (facep->getTextureEntry()->getBumpmap())
+	{ //bump maps aren't worked into texture batching yet
+		return false;
+	}
+
+	if (facep->isState(LLFace::TEXTURE_ANIM) && facep->getVirtualSize() > MIN_TEX_ANIM_SIZE)
+	{ //texture animation breaks batches
+		return false;
+	}
+	
+	return true;
+}
+
 void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, U32 type)
 {
 	LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
@@ -3762,12 +3801,36 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
 	
 	LLViewerTexture* tex = facep->getTexture();
 
+	U8 index = facep->getTextureIndex();
+
+	bool batchable = false;
+
+	if (index < 255 && idx >= 0)
+	{
+		if (index < draw_vec[idx]->mTextureList.size())
+		{
+			if (draw_vec[idx]->mTextureList[index].isNull())
+			{
+				batchable = true;
+				draw_vec[idx]->mTextureList[index] = tex;
+			}
+			else if (draw_vec[idx]->mTextureList[index] == tex)
+			{ //this face's texture index can be used with this batch
+				batchable = true;
+			}
+		}
+		else
+		{ //texture list can be expanded to fit this texture index
+			batchable = true;
+		}
+	}
+	
 	U8 glow = (U8) (facep->getTextureEntry()->getGlow() * 255);
 
 	if (idx >= 0 && 
 		draw_vec[idx]->mVertexBuffer == facep->getVertexBuffer() &&
 		draw_vec[idx]->mEnd == facep->getGeomIndex()-1 &&
-		(LLPipeline::sTextureBindTest || draw_vec[idx]->mTexture == tex) &&
+		(LLPipeline::sTextureBindTest || draw_vec[idx]->mTexture == tex || batchable) &&
 #if LL_DARWIN
 		draw_vec[idx]->mEnd - draw_vec[idx]->mStart + facep->getGeomCount() <= (U32) gGLManager.mGLMaxVertexRange &&
 		draw_vec[idx]->mCount + facep->getIndicesCount() <= (U32) gGLManager.mGLMaxIndexRange &&
@@ -3781,6 +3844,12 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
 		draw_vec[idx]->mCount += facep->getIndicesCount();
 		draw_vec[idx]->mEnd += facep->getGeomCount();
 		draw_vec[idx]->mVSize = llmax(draw_vec[idx]->mVSize, facep->getVirtualSize());
+
+		if (index >= draw_vec[idx]->mTextureList.size())
+		{
+			draw_vec[idx]->mTextureList.resize(index+1);
+			draw_vec[idx]->mTextureList[index] = tex;
+		}
 		draw_vec[idx]->validate();
 		update_min_max(draw_vec[idx]->mExtents[0], draw_vec[idx]->mExtents[1], facep->mExtents[0]);
 		update_min_max(draw_vec[idx]->mExtents[0], draw_vec[idx]->mExtents[1], facep->mExtents[1]);
@@ -3811,6 +3880,11 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
 			draw_info->mDrawMode = LLRender::TRIANGLE_STRIP;
 		}
 
+		if (index < 255)
+		{ //initialize texture list for texture batching
+			draw_info->mTextureList.resize(index+1);
+			draw_info->mTextureList[index] = tex;
+		}
 		draw_info->validate();
 	}
 }
@@ -3910,7 +3984,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 
 		LLVOVolume* vobj = drawablep->getVOVolume();
 
-		if (vobj->getVolume() && vobj->getVolume()->isTetrahedron())
+		if (vobj->getVolume() && vobj->getVolume()->isTetrahedron() || (vobj->isMesh() && !gMeshRepo.meshRezEnabled()))
 		{
 			continue;
 		}
@@ -3923,7 +3997,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 
 		bool rigged = vobj->isAttachment() && 
 					vobj->isMesh() && 
-					gMeshRepo.getSkinInfo(vobj->getVolume()->getParams().getSculptID());
+					gMeshRepo.getSkinInfo(vobj->getVolume()->getParams().getSculptID(), vobj);
 
 		bool bake_sunlight = LLPipeline::sBakeSunlight && drawablep->isStatic();
 
@@ -3965,7 +4039,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 				if ( pAvatarVO )
 				{
 					LLUUID currentId = vobj->getVolume()->getParams().getSculptID();
-					const LLMeshSkinInfo*  pSkinData = gMeshRepo.getSkinInfo( currentId );
+					const LLMeshSkinInfo*  pSkinData = gMeshRepo.getSkinInfo( currentId, vobj );
 					
 					if ( pSkinData )
 					{
@@ -4233,15 +4307,24 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 	U32 bump_mask = LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_COLOR;
 	U32 fullbright_mask = LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_COLOR;
 
-	if (LLPipeline::sRenderDeferred)
+	bool batch_textures = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 1;
+
+	if (batch_textures)
 	{
 		bump_mask |= LLVertexBuffer::MAP_BINORMAL;
+		genDrawInfo(group, simple_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, simple_faces, FALSE, TRUE);
+		genDrawInfo(group, fullbright_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, fullbright_faces, FALSE, TRUE);
+		genDrawInfo(group, bump_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, bump_faces, FALSE, TRUE);
+		genDrawInfo(group, alpha_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, alpha_faces, TRUE, TRUE);
+	}
+	else
+	{
+		genDrawInfo(group, simple_mask, simple_faces);
+		genDrawInfo(group, fullbright_mask, fullbright_faces);
+		genDrawInfo(group, bump_mask, bump_faces, FALSE, TRUE);
+		genDrawInfo(group, alpha_mask, alpha_faces, TRUE);
 	}
 	
-	genDrawInfo(group, simple_mask, simple_faces);
-	genDrawInfo(group, bump_mask, bump_faces);
-	genDrawInfo(group, fullbright_mask, fullbright_faces);
-	genDrawInfo(group, alpha_mask, alpha_faces, TRUE);
 
 	if (!LLPipeline::sDelayVBUpdate)
 	{
@@ -4297,11 +4380,6 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group)
 						face->getGeometryVolume(*volume, face->getTEOffset(), 
 							vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), face->getGeomIndex());
 					}
-
-					if (!face)
-					{
-						llerrs << "WTF?" << llendl;
-					}
 				}
 
 				drawablep->clearState(LLDrawable::REBUILD_ALL);
@@ -4356,13 +4434,37 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group)
 		group->clearState(LLSpatialGroup::MESH_DIRTY | LLSpatialGroup::NEW_DRAWINFO);
 	}
 
-	if (group && group->isState(LLSpatialGroup::NEW_DRAWINFO))
+	llassert(!group || !group->isState(LLSpatialGroup::NEW_DRAWINFO));
+}
+
+struct CompareBatchBreakerModified
+{
+	bool operator()(const LLFace* const& lhs, const LLFace* const& rhs)
 	{
-		llerrs << "WTF?" << llendl;
+		const LLTextureEntry* lte = lhs->getTextureEntry();
+		const LLTextureEntry* rte = rhs->getTextureEntry();
+
+		if (lte->getBumpmap() != rte->getBumpmap())
+		{
+			return lte->getBumpmap() < rte->getBumpmap();
+		}
+		else if (lte->getFullbright() != rte->getFullbright())
+		{
+			return lte->getFullbright() < rte->getFullbright();
+		}
+		else  if (lte->getGlow() != rte->getGlow())
+		{
+			return lte->getGlow() < rte->getGlow();
+		}
+		else
+		{
+			return lhs->getTexture() < rhs->getTexture();
+		}
+		
 	}
-}
+};
 
-void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::vector<LLFace*>& faces, BOOL distance_sort)
+void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::vector<LLFace*>& faces, BOOL distance_sort, BOOL batch_textures)
 {
 	//calculate maximum number of vertices to store in a single buffer
 	U32 max_vertices = (gSavedSettings.getS32("RenderMaxVBOSize")*1024)/LLVertexBuffer::calcVertexSize(group->mSpatialPartition->mVertexDataMask);
@@ -4371,7 +4473,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::
 	if (!distance_sort)
 	{
 		//sort faces by things that break batches
-		std::sort(faces.begin(), faces.end(), LLFace::CompareBatchBreaker());
+		std::sort(faces.begin(), faces.end(), CompareBatchBreakerModified());
 	}
 	else
 	{
@@ -4391,6 +4493,16 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::
 		buffer_index = -1;
 	}
 
+	S32 texture_index_channels = gGLManager.mNumTextureImageUnits-1; //always reserve one for shiny for now just for simplicity
+	
+	if (LLPipeline::sRenderDeferred && distance_sort)
+	{
+		texture_index_channels = gDeferredAlphaProgram.mFeatures.mIndexedTextureChannels;
+	}
+
+	texture_index_channels = llmin(texture_index_channels, (S32) gSavedSettings.getU32("RenderMaxTextureIndex"));
+	
+
 	while (face_iter != faces.end())
 	{
 		//pull off next face
@@ -4421,24 +4533,101 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::
 		std::vector<LLFace*>::iterator i = face_iter;
 		++i;
 		
-		while (i != faces.end() && 
-			(LLPipeline::sTextureBindTest || (distance_sort || (*i)->getTexture() == tex)))
+		std::vector<LLViewerTexture*> texture_list;
+
+		if (batch_textures)
 		{
-			facep = *i;
-			
-			if (geom_count + facep->getGeomCount() > max_vertices)
-			{ //cut batches on geom count too big
-				break;
+			U8 cur_tex = 0;
+			facep->setTextureIndex(cur_tex);
+			texture_list.push_back(tex);
+
+			//if (can_batch_texture(facep))
+			{
+				while (i != faces.end())
+				{
+					facep = *i;
+					if (facep->getTexture() != tex)
+					{
+						if (distance_sort)
+						{ //textures might be out of order, see if texture exists in current batch
+							bool found = false;
+							for (U32 tex_idx = 0; tex_idx < texture_list.size(); ++tex_idx)
+							{
+								if (facep->getTexture() == texture_list[tex_idx])
+								{
+									cur_tex = tex_idx;
+									found = true;
+									break;
+								}
+							}
+
+							if (!found)
+							{
+								cur_tex = texture_list.size();
+							}
+						}
+						else
+						{
+							cur_tex++;
+						}
+
+						if (!can_batch_texture(facep))
+						{ //face is bump mapped or has an animated texture matrix -- can't 
+							//batch more than 1 texture at a time
+							break;
+						}
+
+						if (cur_tex >= texture_index_channels)
+						{ //cut batches when index channels are depleted
+							break;
+						}
+
+						tex = facep->getTexture();
+
+						texture_list.push_back(tex);
+					}
+
+					if (geom_count + facep->getGeomCount() > max_vertices)
+					{ //cut batches on geom count too big
+						break;
+					}
+
+					++i;
+					index_count += facep->getIndicesCount();
+					geom_count += facep->getGeomCount();
+
+					facep->setTextureIndex(cur_tex);
+				}
 			}
 
-			++i;
-			index_count += facep->getIndicesCount();
-			geom_count += facep->getGeomCount();
+			tex = texture_list[0];
+		}
+		else
+		{
+			while (i != faces.end() && 
+				(LLPipeline::sTextureBindTest || (distance_sort || (*i)->getTexture() == tex)))
+			{
+				facep = *i;
+			
+
+				//face has no texture index
+				facep->mDrawInfo = NULL;
+				facep->setTextureIndex(255);
+
+				if (geom_count + facep->getGeomCount() > max_vertices)
+				{ //cut batches on geom count too big
+					break;
+				}
+
+				++i;
+				index_count += facep->getIndicesCount();
+				geom_count += facep->getGeomCount();
+			}
 		}
 	
 		//create/delete/resize vertex buffer if needed
 		LLVertexBuffer* buffer = NULL;
-		LLSpatialGroup::buffer_texture_map_t::iterator found_iter = group->mBufferMap[mask].find(tex);
+		LLSpatialGroup::buffer_texture_map_t::iterator found_iter = group->mBufferMap[mask].find(*face_iter);
 		
 		if (found_iter != group->mBufferMap[mask].end())
 		{
@@ -4469,7 +4658,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::
 			}
 		}
 
-		buffer_map[mask][tex].push_back(buffer);
+		buffer_map[mask][*face_iter].push_back(buffer);
 
 		//add face geometry
 
@@ -4483,6 +4672,11 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::
 			facep->setGeomIndex(index_offset);
 			facep->setVertexBuffer(buffer);	
 			
+			if (batch_textures && facep->getTextureIndex() == 255)
+			{
+				llerrs << "Invalid texture index." << llendl;
+			}
+			
 			{
 				//for debugging, set last time face was updated vs moved
 				facep->updateRebuildFlags();
@@ -4495,12 +4689,8 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::
 
 					U32 te_idx = facep->getTEOffset();
 
-					if (facep->getGeometryVolume(*volume, te_idx, 
-						vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), index_offset))
-					{
-						buffer->markDirty(facep->getGeomIndex(), facep->getGeomCount(), 
-							facep->getIndicesStart(), facep->getIndicesCount());
-					}
+					facep->getGeometryVolume(*volume, te_idx, 
+						vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), index_offset);
 				}
 			}
 
@@ -4681,7 +4871,7 @@ void LLGeometryManager::addGeometryCount(LLSpatialGroup* group, U32 &vertex_coun
 			{
 				vertex_count += facep->getGeomCount();
 				index_count += facep->getIndicesCount();
-
+				llassert(facep->getIndicesCount() < 65536);
 				//remember face (for sorting)
 				mFaceList.push_back(facep);
 			}
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index 845a87b8cff49fa020a6f7bcc00f14183c293b0d..e74bf2a6203d46a7ab7470744806d761902e2d47 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -392,6 +392,7 @@ void LLPipeline::init()
 {
 	LLMemType mt(LLMemType::MTYPE_PIPELINE_INIT);
 
+	gOctreeMaxCapacity = gSavedSettings.getU32("OctreeMaxNodeCapacity");
 	sDynamicLOD = gSavedSettings.getBOOL("RenderDynamicLOD");
 	sRenderBump = gSavedSettings.getBOOL("RenderObjectBump");
 	sUseTriStrips = gSavedSettings.getBOOL("RenderUseTriStrips");
@@ -580,11 +581,6 @@ void LLPipeline::allocatePhysicsBuffer()
 	if (mPhysicsDisplay.getWidth() != resX || mPhysicsDisplay.getHeight() != resY)
 	{
 		mPhysicsDisplay.allocate(resX, resY, GL_RGBA, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE);
-		if (mSampleBuffer.getWidth() == mPhysicsDisplay.getWidth() && 
-			mSampleBuffer.getHeight() == mPhysicsDisplay.getHeight())
-		{
-			mPhysicsDisplay.setSampleBuffer(&mSampleBuffer);
-		}
 	}
 }
 
@@ -594,8 +590,9 @@ void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY)
 	mScreenWidth = resX;
 	mScreenHeight = resY;
 	
-	//never use more than 4 samples for render targets
-	U32 samples = llmin(gSavedSettings.getU32("RenderFSAASamples"), (U32) 4);
+	//cap samples at 4 for render targets to avoid out of memory errors
+	U32 samples = gGLManager.getNumFBOFSAASamples(gSavedSettings.getU32("RenderFSAASamples"));
+
 	if (gGLManager.mIsATI)
 	{ //disable multisampling of render targets where ATI is involved
 		samples = 0;
@@ -621,11 +618,11 @@ void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY)
 		bool gi = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_DEFERRED);
 
 		//allocate deferred rendering color buffers
-		mDeferredScreen.allocate(resX, resY, GL_RGBA, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE);
-		mDeferredDepth.allocate(resX, resY, 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE);
+		mDeferredScreen.allocate(resX, resY, GL_RGBA, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples);
+		mDeferredDepth.allocate(resX, resY, 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples);
 		addDeferredAttachments(mDeferredScreen);
 	
-		mScreen.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE);
+		mScreen.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples);		
 		
 #if LL_DARWIN
 		// As of OS X 10.6.7, Apple doesn't support multiple color formats in a single FBO
@@ -636,7 +633,7 @@ void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY)
 
 		if (shadow_detail > 0 || ssao)
 		{ //only need mDeferredLight[0] for shadows OR ssao
-			mDeferredLight[0].allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE);
+			mDeferredLight[0].allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE);
 		}
 		else
 		{
@@ -645,7 +642,7 @@ void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY)
 
 		if (ssao)
 		{ //only need mDeferredLight[1] for ssao
-			mDeferredLight[1].allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE);
+			mDeferredLight[1].allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, false);
 		}
 		else
 		{
@@ -654,7 +651,7 @@ void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY)
 
 		if (gi)
 		{ //only need mDeferredLight[2] and mGIMapPost for gi
-			mDeferredLight[2].allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE);
+			mDeferredLight[2].allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, false);
 			for (U32 i = 0; i < 2; i++)
 			{
 #if LL_DARWIN
@@ -744,35 +741,9 @@ void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY)
 		mScreen.allocate(resX, resY, GL_RGBA, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE);		
 	}
 	
-	if (LLRenderTarget::sUseFBO && samples > 1)
-	{ 
-		mSampleBuffer.allocate(resX,resY,GL_RGBA,TRUE,TRUE,LLTexUnit::TT_RECT_TEXTURE,FALSE,samples);
-		if (LLPipeline::sRenderDeferred)
-		{
-			addDeferredAttachments(mSampleBuffer);
-			mDeferredScreen.setSampleBuffer(&mSampleBuffer);
-			mEdgeMap.setSampleBuffer(&mSampleBuffer);
-		}
-
-		mScreen.setSampleBuffer(&mSampleBuffer);
-
-		stop_glerror();
-	}
-	else
-	{
-		mSampleBuffer.release();
-	}
-	
 	if (LLPipeline::sRenderDeferred)
 	{ //share depth buffer between deferred targets
 		mDeferredScreen.shareDepthBuffer(mScreen);
-		for (U32 i = 0; i < 3; i++)
-		{ //share stencil buffer with screen space lightmap to stencil out sky
-			if (mDeferredLight[i].getTexture(0))
-			{
-				mDeferredScreen.shareDepthBuffer(mDeferredLight[i]);
-			}
-		}
 	}
 
 	gGL.getTexUnit(0)->disable();
@@ -802,16 +773,7 @@ void LLPipeline::updateRenderDeferred()
 //static
 void LLPipeline::refreshRenderDeferred()
 {
-	if(gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PHYSICS_SHAPES))
-	{
-		//turn the deferred rendering and glow off when draw physics shapes.
-		sRenderDeferred = FALSE ;
-		sRenderGlow = FALSE ;
-	}
-	else
-	{
-		updateRenderDeferred() ;
-	}
+	updateRenderDeferred();
 }
 
 void LLPipeline::releaseGLBuffers()
@@ -841,7 +803,6 @@ void LLPipeline::releaseGLBuffers()
 	mScreen.release();
 	mPhysicsDisplay.release();
 	mUIScreen.release();
-	mSampleBuffer.release();
 	mDeferredScreen.release();
 	mDeferredDepth.release();
 	for (U32 i = 0; i < 3; i++)
@@ -2550,6 +2511,32 @@ void LLPipeline::markGLRebuild(LLGLUpdate* glu)
 	}
 }
 
+void LLPipeline::markPartitionMove(LLDrawable* drawable)
+{
+	if (!drawable->isState(LLDrawable::PARTITION_MOVE) && 
+		!drawable->getPositionGroup().equals3(LLVector4a::getZero()))
+	{
+		drawable->setState(LLDrawable::PARTITION_MOVE);
+		mPartitionQ.push_back(drawable);
+	}
+}
+
+void LLPipeline::processPartitionQ()
+{
+	for (LLDrawable::drawable_list_t::iterator iter = mPartitionQ.begin(); iter != mPartitionQ.end(); ++iter)
+	{
+		LLDrawable* drawable = *iter;
+		if (!drawable->isDead())
+		{
+			drawable->updateBinRadius();
+			drawable->movePartition();
+		}
+		drawable->clearState(LLDrawable::PARTITION_MOVE);
+	}
+
+	mPartitionQ.clear();
+}
+
 void LLPipeline::markRebuild(LLSpatialGroup* group, BOOL priority)
 {
 	LLMemType mt(LLMemType::MTYPE_PIPELINE);
@@ -3610,7 +3597,7 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate)
 					if (gDebugGL)
 					{
 						check_stack_depth(stack_depth);
-						std::string msg = llformat("%s pass %d", gPoolNames[cur_type].c_str(), i);
+						std::string msg = llformat("pass %d", i);
 						LLGLState::checkStates(msg);
 						LLGLState::checkTextureChannels(msg);
 						LLGLState::checkClientArrays(msg);
@@ -4085,6 +4072,37 @@ void LLPipeline::renderDebug()
 
 	bool hud_only = hasRenderType(LLPipeline::RENDER_TYPE_HUD);
 
+	if (!hud_only && !mDebugBlips.empty())
+	{ //render debug blips
+		glPointSize(8.f);
+		LLGLDepthTest depth(GL_TRUE, GL_TRUE, GL_ALWAYS);
+
+		gGL.begin(LLRender::POINTS);
+		for (std::list<DebugBlip>::iterator iter = mDebugBlips.begin(); iter != mDebugBlips.end(); )
+		{
+			DebugBlip& blip = *iter;
+
+			blip.mAge += gFrameIntervalSeconds;
+			if (blip.mAge > 2.f)
+			{
+				mDebugBlips.erase(iter++);
+			}
+			else
+			{
+				iter++;
+			}
+
+			blip.mPosition.mV[2] += gFrameIntervalSeconds*2.f;
+
+			gGL.color4fv(blip.mColor.mV);
+			gGL.vertex3fv(blip.mPosition.mV);
+		}
+		gGL.end();
+		gGL.flush();
+		glPointSize(1.f);
+	}
+
+
 	// Debug stuff.
 	for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
 			iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
@@ -5919,7 +5937,6 @@ LLSpatialPartition* LLPipeline::getSpatialPartition(LLViewerObject* vobj)
 	return NULL;
 }
 
-
 void LLPipeline::resetVertexBuffers(LLDrawable* drawable)
 {
 	if (!drawable || drawable->isDead())
@@ -6065,7 +6082,8 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield)
 {
 	LLMemType mt_ru(LLMemType::MTYPE_PIPELINE_RENDER_BLOOM);
 	if (!(gPipeline.canUseVertexShaders() &&
-		sRenderGlow))
+		sRenderGlow) ||
+		(!sRenderDeferred && hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PHYSICS_SHAPES)))
 	{
 		return;
 	}
@@ -6111,67 +6129,7 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield)
 
 	gGL.setColorMask(true, true);
 	glClearColor(0,0,0,0);
-
-	/*if (for_snapshot)
-	{
-		gGL.getTexUnit(0)->bind(&mGlow[1]);
-		{
-			//LLGLEnable stencil(GL_STENCIL_TEST);
-			//glStencilFunc(GL_NOTEQUAL, 255, 0xFFFFFFFF);
-			//glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
-			//LLGLDisable blend(GL_BLEND);
-
-			// If the snapshot is constructed from tiles, calculate which
-			// tile we're in.
-
-			//from LLViewerCamera::setPerpsective
-			if (zoom_factor > 1.f)
-			{
-				int pos_y = subfield / llceil(zoom_factor);
-				int pos_x = subfield - (pos_y*llceil(zoom_factor));
-				F32 size = 1.f/zoom_factor;
-
-				tc1.set(pos_x*size, pos_y*size);
-				tc2 = tc1 + LLVector2(size,size);
-			}
-			else
-			{
-				tc2.set(1,1);
-			}
-			
-			LLGLEnable blend(GL_BLEND);
-			gGL.setSceneBlendType(LLRender::BT_ADD);
-			
-				
-			gGL.begin(LLRender::TRIANGLE_STRIP);
-			gGL.color4f(1,1,1,1);
-			gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
-			gGL.vertex2f(-1,-1);
-			
-			gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
-			gGL.vertex2f(-1,1);
-			
-			gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
-			gGL.vertex2f(1,-1);
-			
-			gGL.texCoord2f(tc2.mV[0], tc2.mV[1]);
-			gGL.vertex2f(1,1);
-
-			gGL.end();
-
-			gGL.flush();
-			gGL.setSceneBlendType(LLRender::BT_ALPHA);
-		}
-
-		gGL.flush();
-		glMatrixMode(GL_PROJECTION);
-		glPopMatrix();
-		glMatrixMode(GL_MODELVIEW);
-		glPopMatrix();
-
-		return;
-	}*/
-	
+		
 	{
 		{
 			LLFastTimer ftm(FTM_RENDER_BLOOM_FBO);
@@ -6195,11 +6153,8 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield)
 		gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT);
 		gGL.setSceneBlendType(LLRender::BT_ADD_WITH_ALPHA);
 		
-		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);		
-		gGL.getTexUnit(0)->disable();
-		gGL.getTexUnit(0)->enable(LLTexUnit::TT_RECT_TEXTURE);
-		gGL.getTexUnit(0)->bind(&mScreen);
-
+		mScreen.bindTexture(0, 0);
+		
 		gGL.color4f(1,1,1,1);
 		gPipeline.enableLightsFullbright(LLColor4(1,1,1,1));
 		gGL.begin(LLRender::TRIANGLE_STRIP);
@@ -6214,7 +6169,7 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield)
 		
 		gGL.end();
 		
-		gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
+		gGL.getTexUnit(0)->unbind(mScreen.getUsage());
 
 		mGlow[2].flush();
 	}
@@ -6242,7 +6197,6 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield)
 
 	for (S32 i = 0; i < kernel; i++)
 	{
-		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
 		{
 			LLFastTimer ftm(FTM_RENDER_BLOOM_FBO);
 			mGlow[i%2].bindTarget();
@@ -6303,9 +6257,9 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield)
 	
 	LLVertexBuffer::unbind();
 
-	if (LLPipeline::sRenderDeferred && !LLViewerCamera::getInstance()->cameraUnderWater())
+	if (LLPipeline::sRenderDeferred)
 	{
-		bool dof_enabled = true;
+		bool dof_enabled = !LLViewerCamera::getInstance()->cameraUnderWater();
 
 		LLGLSLShader* shader = &gDeferredPostProgram;
 		if (LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_DEFERRED) > 2)
@@ -6313,7 +6267,7 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield)
 			shader = &gDeferredGIFinalProgram;
 			dof_enabled = false;
 		}
-		else if (LLToolMgr::getInstance()->inBuildMode() || !gSavedSettings.getBOOL("RenderDepthOfField"))
+		else if (!dof_enabled || LLToolMgr::getInstance()->inBuildMode() || !gSavedSettings.getBOOL("RenderDepthOfField"))
 		{ //squish focal length when in build mode (or if DoF is disabled) so DoF doesn't make editing objects difficult
 			shader = &gDeferredPostNoDoFProgram;
 			dof_enabled = false;
@@ -6435,11 +6389,10 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield)
 			shader->uniform1f("magnification", magnification);
 		}
 
-		S32 channel = shader->enableTexture(LLViewerShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_RECT_TEXTURE);
+		S32 channel = shader->enableTexture(LLViewerShaderMgr::DEFERRED_DIFFUSE, mScreen.getUsage());
 		if (channel > -1)
 		{
 			mScreen.bindTexture(0, channel);
-			gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
 		}
 		//channel = shader->enableTexture(LLViewerShaderMgr::DEFERRED_DEPTH, LLTexUnit::TT_RECT_TEXTURE);
 		//if (channel > -1)
@@ -6532,6 +6485,8 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield)
 
 	if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PHYSICS_SHAPES))
 	{
+		gGL.setColorMask(true, false);
+
 		LLVector2 tc1(0,0);
 		LLVector2 tc2((F32) gViewerWindow->getWorldViewWidthRaw()*2,
 				  (F32) gViewerWindow->getWorldViewHeightRaw()*2);
@@ -6578,25 +6533,23 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, LLRen
 		noise_map = mNoiseMap;
 	}
 
-	LLGLState::checkTextureChannels();
-
 	shader.bind();
 	S32 channel = 0;
-	channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_RECT_TEXTURE);
+	channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_DIFFUSE, mDeferredScreen.getUsage());
 	if (channel > -1)
 	{
 		mDeferredScreen.bindTexture(0,channel);
 		gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
 	}
 
-	channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_SPECULAR, LLTexUnit::TT_RECT_TEXTURE);
+	channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_SPECULAR, mDeferredScreen.getUsage());
 	if (channel > -1)
 	{
 		mDeferredScreen.bindTexture(1, channel);
 		gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
 	}
 
-	channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_NORMAL, LLTexUnit::TT_RECT_TEXTURE);
+	channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_NORMAL, mDeferredScreen.getUsage());
 	if (channel > -1)
 	{
 		mDeferredScreen.bindTexture(2, channel);
@@ -6719,22 +6672,16 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, LLRen
 			shader.uniformMatrix4fv("gi_norm_mat", 1, FALSE, mGINormalMatrix.m);
 		}
 	}
-	
-	/*channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_POSITION, LLTexUnit::TT_RECT_TEXTURE);
-	if (channel > -1)
-	{
-		mDeferredScreen.bindTexture(3, channel);
-	}*/
+	stop_glerror();
 
-	channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_DEPTH, LLTexUnit::TT_RECT_TEXTURE);
+	channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_DEPTH, mDeferredDepth.getUsage());
 	if (channel > -1)
 	{
 		gGL.getTexUnit(channel)->bind(&mDeferredDepth, TRUE);
-		gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
 		stop_glerror();
 		
-		glTexParameteri(LLTexUnit::getInternalType(mDeferredDepth.getUsage()), GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE);		
-		glTexParameteri(LLTexUnit::getInternalType(mDeferredDepth.getUsage()), GL_DEPTH_TEXTURE_MODE_ARB, GL_ALPHA);		
+		//glTexParameteri(LLTexUnit::getInternalType(mDeferredDepth.getUsage()), GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE);		
+		//glTexParameteri(LLTexUnit::getInternalType(mDeferredDepth.getUsage()), GL_DEPTH_TEXTURE_MODE_ARB, GL_ALPHA);		
 
 		stop_glerror();
 
@@ -6763,7 +6710,7 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, LLRen
 
 	stop_glerror();
 
-	channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_LIGHT, LLTexUnit::TT_RECT_TEXTURE);
+	channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_LIGHT, mDeferredLight[light_index].getUsage());
 	if (channel > -1)
 	{
 		mDeferredLight[light_index].bindTexture(0, channel);
@@ -6983,9 +6930,9 @@ void LLPipeline::renderDeferredLighting()
 		}
 
 		//ati doesn't seem to love actually using the stencil buffer on FBO's
-		LLGLEnable stencil(GL_STENCIL_TEST);
-		glStencilFunc(GL_EQUAL, 1, 0xFFFFFFFF);
-		glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
+		LLGLDisable stencil(GL_STENCIL_TEST);
+		//glStencilFunc(GL_EQUAL, 1, 0xFFFFFFFF);
+		//glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
 
 		gGL.setColorMask(true, true);
 		
@@ -7787,33 +7734,41 @@ void LLPipeline::setupSpotLight(LLGLSLShader& shader, LLDrawable* drawablep)
 
 	LLViewerTexture* img = volume->getLightTexture();
 
+	if (img == NULL)
+	{
+		img = LLViewerFetchedTexture::sWhiteImagep;
+	}
+
 	S32 channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_PROJECTION);
 
-	if (channel > -1 && img)
+	if (channel > -1)
 	{
-		gGL.getTexUnit(channel)->bind(img);
+		if (img)
+		{
+			gGL.getTexUnit(channel)->bind(img);
 
-		F32 lod_range = logf(img->getWidth())/logf(2.f);
+			F32 lod_range = logf(img->getWidth())/logf(2.f);
 
-		shader.uniform1f("proj_focus", focus);
-		shader.uniform1f("proj_lod", lod_range);
-		shader.uniform1f("proj_ambient_lod", llclamp((proj_range-focus)/proj_range*lod_range, 0.f, 1.f));
+			shader.uniform1f("proj_focus", focus);
+			shader.uniform1f("proj_lod", lod_range);
+			shader.uniform1f("proj_ambient_lod", llclamp((proj_range-focus)/proj_range*lod_range, 0.f, 1.f));
+		}
 	}
+		
 }
 
 void LLPipeline::unbindDeferredShader(LLGLSLShader &shader)
 {
 	stop_glerror();
-	shader.disableTexture(LLViewerShaderMgr::DEFERRED_POSITION, LLTexUnit::TT_RECT_TEXTURE);
-	shader.disableTexture(LLViewerShaderMgr::DEFERRED_NORMAL, LLTexUnit::TT_RECT_TEXTURE);
-	shader.disableTexture(LLViewerShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_RECT_TEXTURE);
-	shader.disableTexture(LLViewerShaderMgr::DEFERRED_SPECULAR, LLTexUnit::TT_RECT_TEXTURE);
-	shader.disableTexture(LLViewerShaderMgr::DEFERRED_DEPTH, LLTexUnit::TT_RECT_TEXTURE);
-	shader.disableTexture(LLViewerShaderMgr::DEFERRED_LIGHT, LLTexUnit::TT_RECT_TEXTURE);
+	shader.disableTexture(LLViewerShaderMgr::DEFERRED_NORMAL, mDeferredScreen.getUsage());
+	shader.disableTexture(LLViewerShaderMgr::DEFERRED_DIFFUSE, mDeferredScreen.getUsage());
+	shader.disableTexture(LLViewerShaderMgr::DEFERRED_SPECULAR, mDeferredScreen.getUsage());
+	shader.disableTexture(LLViewerShaderMgr::DEFERRED_DEPTH, mDeferredScreen.getUsage());
+	shader.disableTexture(LLViewerShaderMgr::DEFERRED_LIGHT, mDeferredLight[0].getUsage());
 	shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_LIGHT, LLTexUnit::TT_RECT_TEXTURE);
-	shader.disableTexture(LLViewerShaderMgr::DEFERRED_EDGE, LLTexUnit::TT_RECT_TEXTURE);
-	shader.disableTexture(LLViewerShaderMgr::DEFERRED_SUN_LIGHT, LLTexUnit::TT_RECT_TEXTURE);
-	shader.disableTexture(LLViewerShaderMgr::DEFERRED_LOCAL_LIGHT, LLTexUnit::TT_RECT_TEXTURE);
+	shader.disableTexture(LLViewerShaderMgr::DEFERRED_EDGE, mEdgeMap.getUsage());
+	shader.disableTexture(LLViewerShaderMgr::DEFERRED_SUN_LIGHT, mDeferredLight[1].getUsage());
+	shader.disableTexture(LLViewerShaderMgr::DEFERRED_LOCAL_LIGHT, mDeferredLight[2].getUsage());
 	shader.disableTexture(LLViewerShaderMgr::DEFERRED_LUMINANCE);
 	shader.disableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
 	shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_MIP);
@@ -7860,8 +7815,6 @@ void LLPipeline::unbindDeferredShader(LLGLSLShader &shader)
 	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
 	gGL.getTexUnit(0)->activate();
 	shader.unbind();
-
-	LLGLState::checkTextureChannels();
 }
 
 inline float sgn(float a)
@@ -9409,6 +9362,11 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
 			mShadow[i+4].flush();
  		}
 	}
+	else
+	{ //no spotlight shadows
+		mShadowSpotLight[0] = mShadowSpotLight[1] = NULL;
+	}
+
 
 	if (!gSavedSettings.getBOOL("CameraOffset"))
 	{
@@ -9831,4 +9789,9 @@ void LLPipeline::clearRenderTypeMask(U32 type, ...)
 	}
 }
 
+void LLPipeline::addDebugBlip(const LLVector3& position, const LLColor4& color)
+{
+	DebugBlip blip(position, color);
+	mDebugBlips.push_back(blip);
+}
 
diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h
index e9a250cd6d7ba3c7a53d81922e1b25ccd61c7557..e9da25e544b93e9d686e5c90300be610b6021a83 100644
--- a/indra/newview/pipeline.h
+++ b/indra/newview/pipeline.h
@@ -157,7 +157,8 @@ class LLPipeline
 	void		markGLRebuild(LLGLUpdate* glu);
 	void		markRebuild(LLSpatialGroup* group, BOOL priority = FALSE);
 	void        markRebuild(LLDrawable *drawablep, LLDrawable::EDrawableFlags flag = LLDrawable::REBUILD_ALL, BOOL priority = FALSE);
-		
+	void		markPartitionMove(LLDrawable* drawablep);
+
 	//get the object between start and end that's closest to start.
 	LLViewerObject* lineSegmentIntersectInWorld(const LLVector3& start, const LLVector3& end,
 												BOOL pick_transparent,
@@ -211,6 +212,7 @@ class LLPipeline
 	void updateCull(LLCamera& camera, LLCullResult& result, S32 water_clip = 0, LLPlane* plane = NULL);  //if water_clip is 0, ignore water plane, 1, cull to above plane, -1, cull to below plane
 	void createObjects(F32 max_dtime);
 	void createObject(LLViewerObject* vobj);
+	void processPartitionQ();
 	void updateGeom(F32 max_dtime);
 	void updateGL();
 	void rebuildPriorityGroups();
@@ -358,6 +360,8 @@ class LLPipeline
 	static void updateRenderDeferred();
 	static void refreshRenderDeferred();
 
+	void addDebugBlip(const LLVector3& position, const LLColor4& color);
+
 private:
 	void unloadShaders();
 	void addToQuickLookup( LLDrawPool* new_poolp );
@@ -524,7 +528,6 @@ class LLPipeline
 	LLRenderTarget			mEdgeMap;
 	LLRenderTarget			mDeferredDepth;
 	LLRenderTarget			mDeferredLight[3];
-	LLMultisampleBuffer		mSampleBuffer;
 	LLRenderTarget			mGIMap;
 	LLRenderTarget			mGIMapPost[2];
 	LLRenderTarget			mLuminanceMap;
@@ -637,6 +640,9 @@ class LLPipeline
 	LLDrawable::drawable_list_t 	mBuildQ2; // non-priority
 	LLSpatialGroup::sg_vector_t		mGroupQ1; //priority
 	LLSpatialGroup::sg_vector_t		mGroupQ2; // non-priority
+
+	LLDrawable::drawable_list_t		mPartitionQ; //drawables that need to update their spatial partition radius 
+
 	bool mGroupQ2Locked;
 	bool mGroupQ1Locked;
 
@@ -726,6 +732,20 @@ class LLPipeline
 protected:
 	std::vector<LLFace*>		mSelectedFaces;
 
+	class DebugBlip
+	{
+	public:
+		LLColor4 mColor;
+		LLVector3 mPosition;
+		F32 mAge;
+
+		DebugBlip(const LLVector3& position, const LLColor4& color)
+			: mColor(color), mPosition(position), mAge(0.f)
+		{ }
+	};
+
+	std::list<DebugBlip> mDebugBlips;
+
 	LLPointer<LLViewerFetchedTexture>	mFaceSelectImagep;
 	
 	U32						mLightMask;
diff --git a/indra/newview/skins/default/xui/en/floater_model_preview.xml b/indra/newview/skins/default/xui/en/floater_model_preview.xml
index dce55dae128654190cb8b7d343def0d9f80f59f3..f58595b3c57246ce86a918f1f1b570477b9bc2f3 100644
--- a/indra/newview/skins/default/xui/en/floater_model_preview.xml
+++ b/indra/newview/skins/default/xui/en/floater_model_preview.xml
@@ -4,9 +4,11 @@
      name="Model Preview" title="Upload Model" width="620">
 
   <string name="status_idle">Idle</string>
+  <string name="status_parse_error">Dae parsing issue - see log for details.</string>
   <string name="status_reading_file">Loading...</string>
   <string name="status_generating_meshes">Generating Meshes...</string>
   <string name="status_vertex_number_overflow">Error: Vertex number is more than 65534, aborted!</string>
+  <string name="bad_element">Error: element is invalid</string>
   <string name="high">High</string>
   <string name="medium">Medium</string>
   <string name="low">Low</string>
@@ -83,6 +85,20 @@
     </text>
   </panel>
 
+  <check_box
+	height="16"
+	left_delta="0"
+	name="confirm_checkbox"
+	top_pad="15"
+	follows="bottom|left"
+	width="16" />
+
+  <text
+	height="30"
+	width="570"
+	word_wrap="true" 
+	left_delta="25"
+	top_delta="0">I confirm that I have the appropriate rights to the material contained in this model. [secondlife:///app/floater/learn_more Learn more]</text>
   <text left="10" bottom="540" width="290" height="15" follows="bottom|left|right" name="status">[STATUS]</text>
 
   
diff --git a/indra/newview/skins/default/xui/en/floater_model_wizard.xml b/indra/newview/skins/default/xui/en/floater_model_wizard.xml
index 47b2e5fd79e468da3acc016ab02fb3c7c61ce6e2..8603682e3ab3129124513131c3d4bd0f2621325d 100644
--- a/indra/newview/skins/default/xui/en/floater_model_wizard.xml
+++ b/indra/newview/skins/default/xui/en/floater_model_wizard.xml
@@ -1019,9 +1019,11 @@ Advanced users familiar with 3d content creation tools may prefer to use the [se
 	<spinner visible="false" left="10" height="20" follows="top|left" width="80" top_pad="-50" value="1.0" min_val="0.01" max_val="64.0" name="import_scale"/>
 
 	<string name="status_idle">Idle</string>
+  <string name="status_parse_error">Dae parsing issue - see log for details.</string>
 	<string name="status_reading_file">Loading...</string>
 	<string name="status_generating_meshes">Generating Meshes...</string>
-  <string name="status_vertex_number_overflow">Error: Vertex number is more than 65534, aborted!</string>
+	<string name="status_vertex_number_overflow">Error: Vertex number is more than 65534, aborted!</string>
+	<string name="bad_element">Error: element is invalid</string>
 	<string name="high">High</string>
 	<string name="medium">Medium</string>
 	<string name="low">Low</string>
diff --git a/indra/newview/skins/default/xui/en/floater_tools.xml b/indra/newview/skins/default/xui/en/floater_tools.xml
index 40bf7bfed75608d4530c6cceabfd1d709f9f4eef..7441b2cd9caabe8f020483b1789a6ce0b273b235 100644
--- a/indra/newview/skins/default/xui/en/floater_tools.xml
+++ b/indra/newview/skins/default/xui/en/floater_tools.xml
@@ -2098,11 +2098,7 @@ even though the user gets a free copy.
                  label="Cylinder"
                  name="Cylinder"
                  value="Cylinder" />
-              <combo_box.item
-                 label="Mesh"
-                 name="Mesh"
-                 value="Mesh" />
-            </combo_box>
+              </combo_box>
         </panel>
         <panel
          border="false"
@@ -2461,8 +2457,9 @@ even though the user gets a free copy.
              height="19"
              increment="0.1"
              initial_value="0"
-             label="Density"
+             label="Density in 100 kg/m^3"
              label_width="70"
+             label_wrap="true"
              layout="topleft"
              left_delta="0"
              max_val="22587"
@@ -2483,7 +2480,7 @@ even though the user gets a free copy.
              max_val="1"
              min_val="0"
              name="Physics Restitution"
-             top_pad="4"
+             top_pad="8"
              width="132" />
         </panel>
          <panel
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
old mode 100644
new mode 100755
index ce96c488b482063cba823331dcc2895d657f97a2..09105c1d287129f95ab51e7142c152b26336d9a0
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -6823,7 +6823,9 @@ Select residents to share with.
     name="MeshUploadError"
     icon="alert.tga"
     type="alert">
-    [LABEL] failed to upload: [MESSAGE] [IDENTIFIER] [INVALIDITY_IDENTIFIER]
+    [LABEL] failed to upload: [MESSAGE] [IDENTIFIER] 
+
+See the log file for details.
   </notification>
    
   <notification