diff --git a/.hgtags b/.hgtags
index 539f4a700c4bb64815d95f4050ebdec9bce7e9cb..066f705b9e3058ed4ca47eb4533313e0c3cc5cfa 100755
--- a/.hgtags
+++ b/.hgtags
@@ -458,6 +458,6 @@ a314f1c94374ab1f6633dd2983f7090a68663eb2 3.5.2-beta4
 9b1b6f33aa5394b27bb652b31b5cb81ef6060370 3.5.2-release
 a277b841729f2a62ba1e34acacc964bc13c1ad6f 3.5.3-release
 fb1630153bac5552046ea914af3f14deabc1def8 3.6.0-materials-beta1
-69429d81ae4dd321eda2607901ef0a0fde71b54c 3.6.0-release
-69429d81ae4dd321eda2607901ef0a0fde71b54c 3.6.0-release
 0a56f33ad6aa112032b14a41dad759ad377bdde9 3.6.0-release
+83357f31d8dbf048a8bfdc323f363bf4d588aca1 CHOP-951-a
+75cf8e855ae1af6895a35da475314c2b5acf1850 3.6.1-release
diff --git a/BuildParams b/BuildParams
index 84d30f651bad54782baf50b8fb0f3dcb4e8c4900..5ee1bd11eaa97583815b1d6ec67220804a12567d 100755
--- a/BuildParams
+++ b/BuildParams
@@ -26,6 +26,9 @@ codeticket_since = 3.3.0-release
 Linux.gcc_version = /usr/bin/gcc-4.6
 Linux.cxx_version = /usr/bin/g++-4.6
 
+# Setup default sourceid so Windows can pick up the TeamCity override
+sourceid = ""
+
 ################################################################
 ####      Examples of how to set the viewer_channel         ####
 #
diff --git a/indra/lib/python/indra/util/llmanifest.py b/indra/lib/python/indra/util/llmanifest.py
index 9cb830a2dbd1956424cbfb3063f2f6dfcf569ef2..54049b5545bf8ef9dae8321b5ded922b7240228a 100755
--- a/indra/lib/python/indra/util/llmanifest.py
+++ b/indra/lib/python/indra/util/llmanifest.py
@@ -392,11 +392,21 @@ def created_path(self, path):
             raise ManifestError, "Should be something at path " + path
         self.created_paths.append(path)
 
-    def put_in_file(self, contents, dst):
+    def put_in_file(self, contents, dst, src=None):
         # write contents as dst
-        f = open(self.dst_path_of(dst), "wb")
-        f.write(contents)
-        f.close()
+        dst_path = self.dst_path_of(dst)
+        f = open(dst_path, "wb")
+        try:
+            f.write(contents)
+        finally:
+            f.close()
+
+        # Why would we create a file in the destination tree if not to include
+        # it in the installer? The default src=None (plus the fact that the
+        # src param is last) is to preserve backwards compatibility.
+        if src:
+            self.file_list.append([src, dst_path])
+        return dst_path
 
     def replace_in(self, src, dst=None, searchdict={}):
         if dst == None:
diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp
index c4e1f0c84c37a991e6378a06f8b78bc2a5859612..14cebfe5aa7d85c7ff10b6edf92cdaeee91f3e69 100755
--- a/indra/llmath/llvolume.cpp
+++ b/indra/llmath/llvolume.cpp
@@ -7277,9 +7277,6 @@ void CalculateTangentArray(U32 vertexCount, const LLVector4a *vertex, const LLVe
 
 		const LLVector4a& t = tan1[a];
 
-		llassert(tan1[a].getLength3().getF32() >= 0.f);
-		llassert(tan2[a].getLength3().getF32() >= 0.f);
-
 		LLVector4a ncrosst;
 		ncrosst.setCross3(n,t);
 
@@ -7299,16 +7296,6 @@ void CalculateTangentArray(U32 vertexCount, const LLVector4a *vertex, const LLVe
 			tsubn.getF32ptr()[3] = handedness;
 
 			tangent[a] = tsubn;
-
-			/*
-			These are going off on invalid input and hindering other debugging.
-			llassert(llfinite(tangent[a].getF32ptr()[0]));
-			llassert(llfinite(tangent[a].getF32ptr()[1]));
-			llassert(llfinite(tangent[a].getF32ptr()[2]));
-
-			llassert(!llisnan(tangent[a].getF32ptr()[0]));
-			llassert(!llisnan(tangent[a].getF32ptr()[1]));
-			llassert(!llisnan(tangent[a].getF32ptr()[2]));*/
 		}
 		else
 		{ //degenerate, make up a value
diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp
index 62191b4c1aacb0013c945d6c5ee6a54755faf725..ac16e30796a96d4e27190151a7344f2a92a0afc7 100755
--- a/indra/llrender/llglslshader.cpp
+++ b/indra/llrender/llglslshader.cpp
@@ -149,6 +149,9 @@ void LLGLSLShader::clearStats()
 	mTimeElapsed = 0;
 	mSamplesDrawn = 0;
 	mDrawCalls = 0;
+	mTextureStateFetched = false;
+	mTextureMagFilter.clear();
+	mTextureMinFilter.clear();
 }
 
 void LLGLSLShader::dumpStats()
@@ -161,6 +164,16 @@ void LLGLSLShader::dumpStats()
 		{
 			llinfos << mShaderFiles[i].first << llendl;
 		}
+		for (U32 i = 0; i < mTexture.size(); ++i)
+		{
+			GLint idx = mTexture[i];
+			
+			if (idx >= 0)
+			{
+				GLint uniform_idx = getUniformLocation(i);
+				llinfos << mUniformNameMap[uniform_idx] << " - " << std::hex << mTextureMagFilter[i] << "/" << mTextureMinFilter[i] << std::dec << llendl;
+			}
+		}
 		llinfos << "=============================================" << llendl;
 
 		F32 ms = mTimeElapsed/1000000.f;
@@ -211,6 +224,39 @@ void LLGLSLShader::placeProfileQuery()
 		glGenQueriesARB(1, &mTimerQuery);
 	}
 
+	if (!mTextureStateFetched)
+	{
+		mTextureStateFetched = true;
+		mTextureMagFilter.resize(mTexture.size());
+		mTextureMinFilter.resize(mTexture.size());
+
+		U32 cur_active = gGL.getCurrentTexUnitIndex();
+
+		for (U32 i = 0; i < mTexture.size(); ++i)
+		{
+			GLint idx = mTexture[i];
+
+			if (idx >= 0)
+			{
+				gGL.getTexUnit(idx)->activate();
+
+				U32 mag = 0xFFFFFFFF;
+				U32 min = 0xFFFFFFFF;
+
+				U32 type = LLTexUnit::getInternalType(gGL.getTexUnit(idx)->getCurrType());
+
+				glGetTexParameteriv(type, GL_TEXTURE_MAG_FILTER, (GLint*) &mag);
+				glGetTexParameteriv(type, GL_TEXTURE_MIN_FILTER, (GLint*) &min);
+
+				mTextureMagFilter[i] = mag;
+				mTextureMinFilter[i] = min;
+			}
+		}
+
+		gGL.getTexUnit(cur_active)->activate();
+	}
+
+
 	glBeginQueryARB(GL_SAMPLES_PASSED, 1);
 	glBeginQueryARB(GL_TIME_ELAPSED, mTimerQuery);
 #endif
@@ -573,6 +619,7 @@ void LLGLSLShader::mapUniform(GLint index, const vector<string> * uniforms)
 		}
 
 		mUniformMap[name] = location;
+		mUniformNameMap[location] = name;
 		LL_DEBUGS("ShaderLoading") << "Uniform " << name << " is at location " << location << LL_ENDL;
 	
 		//find the index of this uniform
@@ -635,6 +682,7 @@ BOOL LLGLSLShader::mapUniforms(const vector<string> * uniforms)
 	mActiveTextureChannels = 0;
 	mUniform.clear();
 	mUniformMap.clear();
+	mUniformNameMap.clear();
 	mTexture.clear();
 	mValue.clear();
 	//initialize arrays
@@ -1152,6 +1200,23 @@ void LLGLSLShader::uniform1i(const string& uniform, GLint v)
 	}
 }
 
+void LLGLSLShader::uniform2i(const string& uniform, GLint i, GLint j)
+{
+	GLint location = getUniformLocation(uniform);
+				
+	if (location >= 0)
+	{
+		std::map<GLint, LLVector4>::iterator iter = mValue.find(location);
+		LLVector4 vec(i,j,0.f,0.f);
+		if (iter == mValue.end() || shouldChange(iter->second,vec))
+		{
+			glUniform2iARB(location, i, j);
+			mValue[location] = vec;
+		}
+	}
+}
+
+
 void LLGLSLShader::uniform1f(const string& uniform, GLfloat v)
 {
 	GLint location = getUniformLocation(uniform);
diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h
index 3c775cde27946e03e24aa78699d08ee3cf431d0d..eabdb9fc927c8a24680303b55a5b0704566480b1 100755
--- a/indra/llrender/llglslshader.h
+++ b/indra/llrender/llglslshader.h
@@ -111,6 +111,7 @@ class LLGLSLShader
 	void uniform3fv(U32 index, U32 count, const GLfloat* v);
 	void uniform4fv(U32 index, U32 count, const GLfloat* v);
 	void uniform1i(const std::string& uniform, GLint i);
+	void uniform2i(const std::string& uniform, GLint i, GLint j);
 	void uniform1f(const std::string& uniform, GLfloat v);
 	void uniform2f(const std::string& uniform, GLfloat x, GLfloat y);
 	void uniform3f(const std::string& uniform, GLfloat x, GLfloat y, GLfloat z);
@@ -170,6 +171,7 @@ class LLGLSLShader
 	U32 mAttributeMask;  //mask of which reserved attributes are set (lines up with LLVertexBuffer::getTypeMask())
 	std::vector<GLint> mUniform;   //lookup table of uniform enum to uniform location
 	std::map<std::string, GLint> mUniformMap;  //lookup map of uniform name to uniform location
+	std::map<GLint, std::string> mUniformNameMap; //lookup map of uniform location to uniform name
 	std::map<GLint, LLVector4> mValue; //lookup map of uniform location to last known value
 	std::vector<GLint> mTexture;
 	S32 mTotalUniformSize;
@@ -192,6 +194,11 @@ class LLGLSLShader
 	static U64 sTotalSamplesDrawn;
 	U32 mDrawCalls;
 	static U32 sTotalDrawCalls;
+
+	bool mTextureStateFetched;
+	std::vector<U32> mTextureMagFilter;
+	std::vector<U32> mTextureMinFilter;
+	
 };
 
 //UI shader (declared here so llui_libtest will link properly)
diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp
index 5fb4fc8e520b3b26bf549c62d4e8351c734eb9f4..6e22712b94f8158b3d099c627ba71337156f42b9 100755
--- a/indra/llrender/llrendertarget.cpp
+++ b/indra/llrender/llrendertarget.cpp
@@ -53,11 +53,19 @@ void check_framebuffer_status()
 bool LLRenderTarget::sUseFBO = false;
 U32 LLRenderTarget::sCurFBO = 0;
 
+
+extern S32 gGLViewport[4];
+
+U32 LLRenderTarget::sCurResX = 0;
+U32 LLRenderTarget::sCurResY = 0;
+
 LLRenderTarget::LLRenderTarget() :
 	mResX(0),
 	mResY(0),
 	mFBO(0),
 	mPreviousFBO(0),
+	mPreviousResX(0),
+	mPreviousResY(0),
 	mDepth(0),
 	mStencil(0),
 	mUseDepth(false),
@@ -390,13 +398,12 @@ void LLRenderTarget::bindTarget()
 {
 	if (mFBO)
 	{
-		mPreviousFBO = sCurFBO;
-
 		stop_glerror();
 		
+		mPreviousFBO = sCurFBO;
 		glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
 		sCurFBO = mFBO;
-
+		
 		stop_glerror();
 		if (gGLManager.mHasDrawBuffers)
 		{ //setup multiple render targets
@@ -418,7 +425,12 @@ void LLRenderTarget::bindTarget()
 		stop_glerror();
 	}
 
+	mPreviousResX = sCurResX;
+	mPreviousResY = sCurResY;
 	glViewport(0, 0, mResX, mResY);
+	sCurResX = mResX;
+	sCurResY = mResY;
+
 	sBoundTarget = this;
 }
 
@@ -489,6 +501,20 @@ void LLRenderTarget::flush(bool fetch_depth)
 		stop_glerror();
 		glBindFramebuffer(GL_FRAMEBUFFER, mPreviousFBO);
 		sCurFBO = mPreviousFBO;
+
+		if (mPreviousFBO)
+		{
+			glViewport(0, 0, mPreviousResX, mPreviousResY);
+			sCurResX = mPreviousResX;
+			sCurResY = mPreviousResY;
+		}
+		else
+		{
+			glViewport(gGLViewport[0],gGLViewport[1],gGLViewport[2],gGLViewport[3]);
+			sCurResX = gGLViewport[2];
+			sCurResY = gGLViewport[3];
+		}
+						
 		stop_glerror();
 	}
 }
diff --git a/indra/llrender/llrendertarget.h b/indra/llrender/llrendertarget.h
index 765a727b5b9ea358403491e9ac6bebec8e185fc3..66a9874a6b20ddd5ba41964b07e436a8c8e3f3ca 100755
--- a/indra/llrender/llrendertarget.h
+++ b/indra/llrender/llrendertarget.h
@@ -63,6 +63,9 @@ class LLRenderTarget
 	static bool sUseFBO; 
 	static U32 sBytesAllocated;
 	static U32 sCurFBO;
+	static U32 sCurResX;
+	static U32 sCurResY;
+
 
 	LLRenderTarget();
 	~LLRenderTarget();
@@ -146,6 +149,9 @@ class LLRenderTarget
 	std::vector<U32> mInternalFormat;
 	U32 mFBO;
 	U32 mPreviousFBO;
+	U32 mPreviousResX;
+	U32 mPreviousResY;
+
 	U32 mDepth;
 	bool mStencil;
 	bool mUseDepth;
diff --git a/indra/llui/llfloaterreg.cpp b/indra/llui/llfloaterreg.cpp
index 1cdddf0d5b93e830eabc4776cabcfb26bf3dd6e0..b1b75776a7b43bc56a4dca5d419103b6faced0cb 100755
--- a/indra/llui/llfloaterreg.cpp
+++ b/indra/llui/llfloaterreg.cpp
@@ -356,8 +356,8 @@ std::string LLFloaterReg::declareRectControl(const std::string& name)
 {
 	std::string controlname = getRectControlName(name);
 	LLFloater::getControlGroup()->declareRect(controlname, LLRect(),
-												 llformat("Window Size for %s", name.c_str()),
-												 TRUE);
+											  llformat("Window Size for %s", name.c_str()),
+											  LLControlVariable::PERSIST_NONDFT);
 	return controlname;
 }
 
@@ -367,7 +367,7 @@ std::string LLFloaterReg::declarePosXControl(const std::string& name)
 	LLFloater::getControlGroup()->declareF32(controlname, 
 											10.f,
 											llformat("Window X Position for %s", name.c_str()),
-											TRUE);
+											LLControlVariable::PERSIST_NONDFT);
 	return controlname;
 }
 
@@ -377,7 +377,7 @@ std::string LLFloaterReg::declarePosYControl(const std::string& name)
 	LLFloater::getControlGroup()->declareF32(controlname,
 											10.f,
 											llformat("Window Y Position for %s", name.c_str()),
-											TRUE);
+											LLControlVariable::PERSIST_NONDFT);
 
 	return controlname;
 }
@@ -404,7 +404,7 @@ std::string LLFloaterReg::declareVisibilityControl(const std::string& name)
 	std::string controlname = getVisibilityControlName(name);
 	LLFloater::getControlGroup()->declareBOOL(controlname, FALSE,
 												 llformat("Window Visibility for %s", name.c_str()),
-												 TRUE);
+												 LLControlVariable::PERSIST_NONDFT);
 	return controlname;
 }
 
@@ -414,7 +414,7 @@ std::string LLFloaterReg::declareDockStateControl(const std::string& name)
 	std::string controlname = getDockStateControlName(name);
 	LLFloater::getControlGroup()->declareBOOL(controlname, TRUE,
 												 llformat("Window Docking state for %s", name.c_str()),
-												 TRUE);
+												 LLControlVariable::PERSIST_NONDFT);
 	return controlname;
 
 }
diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp
index 1789f003b91ecd843aba930d724b22e4184e4f48..a1853ca1f787de02aec6216015af041244c3d0d2 100755
--- a/indra/llui/llnotifications.cpp
+++ b/indra/llui/llnotifications.cpp
@@ -214,7 +214,7 @@ LLNotificationForm::LLNotificationForm(const std::string& name, const LLNotifica
 		}
 		else
 		{
-			LLUI::sSettingGroups["ignores"]->declareBOOL(name, show_notification, "Show notification with this name", TRUE);
+			LLUI::sSettingGroups["ignores"]->declareBOOL(name, show_notification, "Show notification with this name", LLControlVariable::PERSIST_NONDFT);
 			mIgnoreSetting = LLUI::sSettingGroups["ignores"]->getControl(name);
 		}
 	}
diff --git a/indra/llxml/llcontrol.cpp b/indra/llxml/llcontrol.cpp
index 666c03e9fffc89295d0549544d0c3c18e9382104..16f22907872f01a7b3fbedc454716285145ee665 100755
--- a/indra/llxml/llcontrol.cpp
+++ b/indra/llxml/llcontrol.cpp
@@ -132,14 +132,14 @@ bool LLControlVariable::llsd_compare(const LLSD& a, const LLSD & b)
 
 LLControlVariable::LLControlVariable(const std::string& name, eControlType type,
 							 LLSD initial, const std::string& comment,
-							 bool persist, bool hidefromsettingseditor)
+							 ePersist persist, bool hidefromsettingseditor)
 	: mName(name),
 	  mComment(comment),
 	  mType(type),
 	  mPersist(persist),
 	  mHideFromSettingsEditor(hidefromsettingseditor)
 {
-	if (mPersist && mComment.empty())
+	if ((persist != PERSIST_NO) && mComment.empty())
 	{
 		llerrs << "Must supply a comment for control " << mName << llendl;
 	}
@@ -260,7 +260,7 @@ void LLControlVariable::setDefaultValue(const LLSD& value)
 	}
 }
 
-void LLControlVariable::setPersist(bool state)
+void LLControlVariable::setPersist(ePersist state)
 {
 	mPersist = state;
 }
@@ -292,10 +292,29 @@ void LLControlVariable::resetToDefault(bool fire_signal)
 	}
 }
 
-bool LLControlVariable::isSaveValueDefault()
-{ 
-    return (mValues.size() ==  1) 
-        || ((mValues.size() > 1) && llsd_compare(mValues[1], mValues[0]));
+bool LLControlVariable::shouldSave(bool nondefault_only)
+{
+	// This method is used to decide whether we should save a given
+	// variable. Two of the three values of mPersist are easy.
+	if (mPersist == PERSIST_NO)
+		return false;
+
+	if (mPersist == PERSIST_ALWAYS)
+		return true;
+
+	// PERSIST_NONDFT
+	// If caller doesn't need us to filter, just save.
+	if (! nondefault_only)
+		return true;
+
+	// PERSIST_NONDFT: caller only wants us to save this variable if its value
+	// differs from default.
+	if (isDefault())                // never been altered
+		return false;
+
+	// We've set at least one other value: compare it to default. Save only if
+	// they differ.
+	return ! llsd_compare(getSaveValue(), getDefault());
 }
 
 LLSD LLControlVariable::getSaveValue() const
@@ -355,12 +374,12 @@ std::string LLControlGroup::typeEnumToString(eControlType typeenum)
 	return mTypeString[typeenum];
 }
 
-BOOL LLControlGroup::declareControl(const std::string& name, eControlType type, const LLSD initial_val, const std::string& comment, BOOL persist, BOOL hidefromsettingseditor)
+LLControlVariable* LLControlGroup::declareControl(const std::string& name, eControlType type, const LLSD initial_val, const std::string& comment, LLControlVariable::ePersist persist, BOOL hidefromsettingseditor)
 {
 	LLControlVariable* existing_control = getControl(name);
 	if (existing_control)
  	{
-		if (persist && existing_control->isType(type))
+		if ((persist != LLControlVariable::PERSIST_NO) && existing_control->isType(type))
 		{
 			if (!existing_control->llsd_compare(existing_control->getDefault(), initial_val))
 			{
@@ -374,66 +393,66 @@ BOOL LLControlGroup::declareControl(const std::string& name, eControlType type,
 		{
 			llwarns << "Control named " << name << " already exists, ignoring new declaration." << llendl;
 		}
- 		return TRUE;
+ 		return existing_control;
 	}
 
 	// if not, create the control and add it to the name table
 	LLControlVariable* control = new LLControlVariable(name, type, initial_val, comment, persist, hidefromsettingseditor);
 	mNameTable[name] = control;	
-	return TRUE;
+	return control;
 }
 
-BOOL LLControlGroup::declareU32(const std::string& name, const U32 initial_val, const std::string& comment, BOOL persist)
+LLControlVariable* LLControlGroup::declareU32(const std::string& name, const U32 initial_val, const std::string& comment, LLControlVariable::ePersist persist)
 {
 	return declareControl(name, TYPE_U32, (LLSD::Integer) initial_val, comment, persist);
 }
 
-BOOL LLControlGroup::declareS32(const std::string& name, const S32 initial_val, const std::string& comment, BOOL persist)
+LLControlVariable* LLControlGroup::declareS32(const std::string& name, const S32 initial_val, const std::string& comment, LLControlVariable::ePersist persist)
 {
 	return declareControl(name, TYPE_S32, initial_val, comment, persist);
 }
 
-BOOL LLControlGroup::declareF32(const std::string& name, const F32 initial_val, const std::string& comment, BOOL persist)
+LLControlVariable* LLControlGroup::declareF32(const std::string& name, const F32 initial_val, const std::string& comment, LLControlVariable::ePersist persist)
 {
 	return declareControl(name, TYPE_F32, initial_val, comment, persist);
 }
 
-BOOL LLControlGroup::declareBOOL(const std::string& name, const BOOL initial_val, const std::string& comment, BOOL persist)
+LLControlVariable* LLControlGroup::declareBOOL(const std::string& name, const BOOL initial_val, const std::string& comment, LLControlVariable::ePersist persist)
 {
 	return declareControl(name, TYPE_BOOLEAN, initial_val, comment, persist);
 }
 
-BOOL LLControlGroup::declareString(const std::string& name, const std::string& initial_val, const std::string& comment, BOOL persist)
+LLControlVariable* LLControlGroup::declareString(const std::string& name, const std::string& initial_val, const std::string& comment, LLControlVariable::ePersist persist)
 {
 	return declareControl(name, TYPE_STRING, initial_val, comment, persist);
 }
 
-BOOL LLControlGroup::declareVec3(const std::string& name, const LLVector3 &initial_val, const std::string& comment, BOOL persist)
+LLControlVariable* LLControlGroup::declareVec3(const std::string& name, const LLVector3 &initial_val, const std::string& comment, LLControlVariable::ePersist persist)
 {
 	return declareControl(name, TYPE_VEC3, initial_val.getValue(), comment, persist);
 }
 
-BOOL LLControlGroup::declareVec3d(const std::string& name, const LLVector3d &initial_val, const std::string& comment, BOOL persist)
+LLControlVariable* LLControlGroup::declareVec3d(const std::string& name, const LLVector3d &initial_val, const std::string& comment, LLControlVariable::ePersist persist)
 {
 	return declareControl(name, TYPE_VEC3D, initial_val.getValue(), comment, persist);
 }
 
-BOOL LLControlGroup::declareRect(const std::string& name, const LLRect &initial_val, const std::string& comment, BOOL persist)
+LLControlVariable* LLControlGroup::declareRect(const std::string& name, const LLRect &initial_val, const std::string& comment, LLControlVariable::ePersist persist)
 {
 	return declareControl(name, TYPE_RECT, initial_val.getValue(), comment, persist);
 }
 
-BOOL LLControlGroup::declareColor4(const std::string& name, const LLColor4 &initial_val, const std::string& comment, BOOL persist )
+LLControlVariable* LLControlGroup::declareColor4(const std::string& name, const LLColor4 &initial_val, const std::string& comment, LLControlVariable::ePersist persist )
 {
 	return declareControl(name, TYPE_COL4, initial_val.getValue(), comment, persist);
 }
 
-BOOL LLControlGroup::declareColor3(const std::string& name, const LLColor3 &initial_val, const std::string& comment, BOOL persist )
+LLControlVariable* LLControlGroup::declareColor3(const std::string& name, const LLColor3 &initial_val, const std::string& comment, LLControlVariable::ePersist persist )
 {
 	return declareControl(name, TYPE_COL3, initial_val.getValue(), comment, persist);
 }
 
-BOOL LLControlGroup::declareLLSD(const std::string& name, const LLSD &initial_val, const std::string& comment, BOOL persist )
+LLControlVariable* LLControlGroup::declareLLSD(const std::string& name, const LLSD &initial_val, const std::string& comment, LLControlVariable::ePersist persist )
 {
 	return declareControl(name, TYPE_LLSD, initial_val, comment, persist);
 }
@@ -664,11 +683,11 @@ U32 LLControlGroup::loadFromFileLegacy(const std::string& filename, BOOL require
 			switch(declare_as)
 			{
 			case TYPE_COL4:
-				declareColor4(name, LLColor4::white, LLStringUtil::null, NO_PERSIST);
+				declareColor4(name, LLColor4::white, LLStringUtil::null, LLControlVariable::PERSIST_NO);
 				break;
 			case TYPE_STRING:
 			default:
-				declareString(name, LLStringUtil::null, LLStringUtil::null, NO_PERSIST);
+				declareString(name, LLStringUtil::null, LLStringUtil::null, LLControlVariable::PERSIST_NO);
 				break;
 			}
 		}
@@ -805,21 +824,12 @@ U32 LLControlGroup::saveToFile(const std::string& filename, BOOL nondefault_only
 		{
 			llwarns << "Tried to save invalid control: " << iter->first << llendl;
 		}
-
-		if( control && control->isPersisted() )
+		else if( control->shouldSave(nondefault_only) )
 		{
-			if (!(nondefault_only && (control->isSaveValueDefault())))
-			{
-				settings[iter->first]["Type"] = typeEnumToString(control->type());
-				settings[iter->first]["Comment"] = control->getComment();
-				settings[iter->first]["Value"] = control->getSaveValue();
-				++num_saved;
-			}
-			else
-			{
-				// Debug spam
-				// llinfos << "Skipping " << control->getName() << llendl;
-			}
+			settings[iter->first]["Type"] = typeEnumToString(control->type());
+			settings[iter->first]["Comment"] = control->getComment();
+			settings[iter->first]["Value"] = control->getSaveValue();
+			++num_saved;
 		}
 	}
 	llofstream file;
@@ -862,13 +872,14 @@ U32 LLControlGroup::loadFromFile(const std::string& filename, bool set_default_v
 	
 	for(LLSD::map_const_iterator itr = settings.beginMap(); itr != settings.endMap(); ++itr)
 	{
-		bool persist = true;
+		LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT;
 		std::string const & name = itr->first;
 		LLSD const & control_map = itr->second;
 		
 		if(control_map.has("Persist")) 
 		{
-			persist = control_map["Persist"].asInteger();
+			persist = control_map["Persist"].asInteger()?
+					  LLControlVariable::PERSIST_NONDFT : LLControlVariable::PERSIST_NO;
 		}
 		
 		// Sometimes we want to use the settings system to provide cheap persistence, but we
@@ -887,6 +898,8 @@ U32 LLControlGroup::loadFromFile(const std::string& filename, bool set_default_v
 		LLControlVariable* existing_control = getControl(name);
 		if(existing_control)
 		{
+			// set_default_values is true when we're loading the initial,
+			// immutable files from app_settings, e.g. settings.xml.
 			if(set_default_values)
 			{
 				// Override all previously set properties of this control.
@@ -908,6 +921,9 @@ U32 LLControlGroup::loadFromFile(const std::string& filename, bool set_default_v
 			}
 			else if(existing_control->isPersisted())
 			{
+				// save_values is specifically false for (e.g.)
+				// SessionSettingsFile and UserSessionSettingsFile -- in other
+				// words, for a file that's supposed to be transient.
 				existing_control->setValue(control_map["Value"], save_values);
 			}
 			// *NOTE: If not persisted and not setting defaults, 
@@ -915,6 +931,39 @@ U32 LLControlGroup::loadFromFile(const std::string& filename, bool set_default_v
 		}
 		else
 		{
+			// We've never seen this control before. Either we're loading up
+			// the initial set of default settings files (set_default_values)
+			// -- or we're loading user settings last saved by a viewer that
+			// supports a superset of the variables we know.
+			// CHOP-962: if we're loading an unrecognized user setting, make
+			// sure we save it later. If you try an experimental viewer, tweak
+			// a new setting, briefly revert to an old viewer, then return to
+			// the new one, we don't want the old viewer to discard the
+			// setting you changed.
+			if (! set_default_values)
+			{
+				// Using PERSIST_ALWAYS insists that saveToFile() (which calls
+				// LLControlVariable::shouldSave()) must save this control
+				// variable regardless of its value. We can safely set this
+				// LLControlVariable persistent because the 'persistent' flag
+				// is not itself persisted!
+				persist = LLControlVariable::PERSIST_ALWAYS;
+				// We want to mention unrecognized user settings variables
+				// (e.g. from a newer version of the viewer) in the log. But
+				// we also arrive here for Boolean variables generated by
+				// the notifications subsystem when the user checks "Don't
+				// show me this again." These aren't declared in settings.xml;
+				// they're actually named for the notification they suppress.
+				// We don't want to mention those. Apologies, this is a bit of
+				// a hack: we happen to know that user settings go into an
+				// LLControlGroup whose name is "Global".
+				if (getKey() == "Global")
+				{
+					LL_INFOS("LLControlGroup") << "preserving unrecognized " << getKey()
+											   << " settings variable " << name << LL_ENDL;
+				}
+			}
+
 			declareControl(name, 
 						   typeStringToEnum(control_map["Type"].asString()), 
 						   control_map["Value"], 
@@ -923,7 +972,7 @@ U32 LLControlGroup::loadFromFile(const std::string& filename, bool set_default_v
 						   hidefromsettingseditor
 						   );
 		}
-		
+
 		++validitems;
 	}
 
diff --git a/indra/llxml/llcontrol.h b/indra/llxml/llcontrol.h
index ee7d1d50b7e1de8cb81e372330c9de128fda49ec..e1f9be80ddad26d909449b0a6300f4d50c08b553 100755
--- a/indra/llxml/llcontrol.h
+++ b/indra/llxml/llcontrol.h
@@ -72,8 +72,6 @@ class LLVector3d;
 class LLColor4;
 class LLColor3;
 
-const BOOL NO_PERSIST = FALSE;
-
 typedef enum e_control_type
 {
 	TYPE_U32 = 0,
@@ -100,21 +98,28 @@ class LLControlVariable : public LLRefCount
 	typedef boost::signals2::signal<bool(LLControlVariable* control, const LLSD&), boost_boolean_combiner> validate_signal_t;
 	typedef boost::signals2::signal<void(LLControlVariable* control, const LLSD&, const LLSD&)> commit_signal_t;
 
+	enum ePersist
+	{
+		PERSIST_NO,                 // don't save this var
+		PERSIST_NONDFT,             // save this var if differs from default
+		PERSIST_ALWAYS              // save this var even if has default value
+	};
+
 private:
 	std::string		mName;
 	std::string		mComment;
 	eControlType	mType;
-	bool			mPersist;
+	ePersist		mPersist;
 	bool			mHideFromSettingsEditor;
 	std::vector<LLSD> mValues;
-	
+
 	commit_signal_t mCommitSignal;
 	validate_signal_t mValidateSignal;
 	
 public:
 	LLControlVariable(const std::string& name, eControlType type,
 					  LLSD initial, const std::string& comment,
-					  bool persist = true, bool hidefromsettingseditor = false);
+					  ePersist persist = PERSIST_NONDFT, bool hidefromsettingseditor = false);
 
 	virtual ~LLControlVariable();
 	
@@ -131,8 +136,8 @@ class LLControlVariable : public LLRefCount
 	validate_signal_t* getValidateSignal() { return &mValidateSignal; }
 
 	bool isDefault() { return (mValues.size() == 1); }
-	bool isSaveValueDefault();
-	bool isPersisted() { return mPersist; }
+	bool shouldSave(bool nondefault_only);
+	bool isPersisted() { return mPersist != PERSIST_NO; }
 	bool isHiddenFromSettingsEditor() { return mHideFromSettingsEditor; }
 	LLSD get()			const	{ return getValue(); }
 	LLSD getValue()		const	{ return mValues.back(); }
@@ -142,7 +147,7 @@ class LLControlVariable : public LLRefCount
 	void set(const LLSD& val)	{ setValue(val); }
 	void setValue(const LLSD& value, bool saved_value = TRUE);
 	void setDefaultValue(const LLSD& value);
-	void setPersist(bool state);
+	void setPersist(ePersist);
 	void setHiddenFromSettingsEditor(bool hide);
 	void setComment(const std::string& comment);
 
@@ -207,19 +212,19 @@ class LLControlGroup : public LLInstanceTracker<LLControlGroup, std::string>
 		virtual void apply(const std::string& name, LLControlVariable* control) = 0;
 	};
 	void applyToAll(ApplyFunctor* func);
-	
-	BOOL declareControl(const std::string& name, eControlType type, const LLSD initial_val, const std::string& comment, BOOL persist, BOOL hidefromsettingseditor = FALSE);
-	BOOL declareU32(const std::string& name, U32 initial_val, const std::string& comment, BOOL persist = TRUE);
-	BOOL declareS32(const std::string& name, S32 initial_val, const std::string& comment, BOOL persist = TRUE);
-	BOOL declareF32(const std::string& name, F32 initial_val, const std::string& comment, BOOL persist = TRUE);
-	BOOL declareBOOL(const std::string& name, BOOL initial_val, const std::string& comment, BOOL persist = TRUE);
-	BOOL declareString(const std::string& name, const std::string &initial_val, const std::string& comment, BOOL persist = TRUE);
-	BOOL declareVec3(const std::string& name, const LLVector3 &initial_val,const std::string& comment,  BOOL persist = TRUE);
-	BOOL declareVec3d(const std::string& name, const LLVector3d &initial_val, const std::string& comment, BOOL persist = TRUE);
-	BOOL declareRect(const std::string& name, const LLRect &initial_val, const std::string& comment, BOOL persist = TRUE);
-	BOOL declareColor4(const std::string& name, const LLColor4 &initial_val, const std::string& comment, BOOL persist = TRUE);
-	BOOL declareColor3(const std::string& name, const LLColor3 &initial_val, const std::string& comment, BOOL persist = TRUE);
-	BOOL declareLLSD(const std::string& name, const LLSD &initial_val, const std::string& comment, BOOL persist = TRUE);
+
+	LLControlVariable* declareControl(const std::string& name, eControlType type, const LLSD initial_val, const std::string& comment, LLControlVariable::ePersist persist, BOOL hidefromsettingseditor = FALSE);
+	LLControlVariable* declareU32(const std::string& name, U32 initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT);
+	LLControlVariable* declareS32(const std::string& name, S32 initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT);
+	LLControlVariable* declareF32(const std::string& name, F32 initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT);
+	LLControlVariable* declareBOOL(const std::string& name, BOOL initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT);
+	LLControlVariable* declareString(const std::string& name, const std::string &initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT);
+	LLControlVariable* declareVec3(const std::string& name, const LLVector3 &initial_val,const std::string& comment,  LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT);
+	LLControlVariable* declareVec3d(const std::string& name, const LLVector3d &initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT);
+	LLControlVariable* declareRect(const std::string& name, const LLRect &initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT);
+	LLControlVariable* declareColor4(const std::string& name, const LLColor4 &initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT);
+	LLControlVariable* declareColor3(const std::string& name, const LLColor3 &initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT);
+	LLControlVariable* declareLLSD(const std::string& name, const LLSD &initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT);
 
 	std::string getString(const std::string& name);
 	std::string getText(const std::string& name);
@@ -368,7 +373,7 @@ class LLControlCache : public LLRefCount, public LLInstanceTracker<LLControlCach
 		init_value = convert_to_llsd(default_value);
 		if(type < TYPE_COUNT)
 		{
-			group.declareControl(name, type, init_value, comment, FALSE);
+			group.declareControl(name, type, init_value, comment, LLControlVariable::PERSIST_NO);
 			return true;
 		}
 		return false;
diff --git a/indra/llxml/tests/llcontrol_test.cpp b/indra/llxml/tests/llcontrol_test.cpp
index ede81956ec6879b896ba09be308211f1b002fc67..c273773c9b43a9223dfc43fc7dba44bb76f67934 100755
--- a/indra/llxml/tests/llcontrol_test.cpp
+++ b/indra/llxml/tests/llcontrol_test.cpp
@@ -128,7 +128,11 @@ namespace tut
 	template<> template<>
 	void control_group_t::test<3>()
 	{
-		int results = mCG->loadFromFile(mTestConfigFile.c_str());
+		// Pass default_values = true. This tells loadFromFile() we're loading
+		// a default settings file that declares variables, rather than a user
+		// settings file. When loadFromFile() encounters an unrecognized user
+		// settings variable, it forcibly preserves it (CHOP-962).
+		int results = mCG->loadFromFile(mTestConfigFile.c_str(), true);
 		LLControlVariable* control = mCG->getControl("TestSetting");
 		LLSD new_value = 13;
 		control->setValue(new_value, FALSE);
diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt
index 9575d51bad249b78b01fa517932882eb917cb750..b72762837ea636398fece3c5651f664c2ee82ffb 100644
--- a/indra/newview/VIEWER_VERSION.txt
+++ b/indra/newview/VIEWER_VERSION.txt
@@ -1 +1 @@
-3.6.1
+3.6.2
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 6f50a72016f70f7217f670b77a114924383cceef..4c8860ffe73999544cfc9728ceb3b77c2740fcc2 100755
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -7831,7 +7831,7 @@
     <key>Type</key>
     <string>S32</string>
     <key>Value</key>
-    <integer>4</integer>
+    <integer>3</integer>
   </map>
 
   <key>OctreeAlphaDistanceFactor</key>
@@ -8603,7 +8603,6 @@
     <key>Value</key>
     <real>1.0</real>
   </map>
-
   <key>RenderDeferredTreeShadowBias</key>
   <map>
     <key>Comment</key>
diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl
index 77a53a71aac611f9511064f514cdcbd9ade38498..0899caa2af6e84884ce371daa0caba5f8f5a0db9 100755
--- a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl
@@ -78,6 +78,7 @@ uniform vec2 screen_res;
 vec3 calcDirectionalLight(vec3 n, vec3 l)
 {
 	float a = max(dot(n,l),0.0);
+	a = pow(a, 1.0/1.3);
 	return vec3(a,a,a);
 }
 
@@ -87,7 +88,7 @@ vec3 calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float
 	vec3 lv = lp.xyz-v;
 	
 	//get distance
-	float d = dot(lv,lv);
+	float d = length(lv);
 	
 	float da = 0.0;
 
@@ -97,9 +98,11 @@ vec3 calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float
 		lv = normalize(lv);
 	
 		//distance attenuation
-		float dist2 = d/la;
-		da = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0);
-		da = pow(da, 2.2) * 2.2;
+		float dist = d/la;
+		da = clamp(1.0-(dist-1.0*(1.0-fa))/fa, 0.0, 1.0);
+		da *= da;
+		da *= 1.4;
+	
 
 		// spotlight coefficient.
 		float spot = max(dot(-ln, lv), is_pointlight);
@@ -212,6 +215,7 @@ void main()
 #else
 	vec4 diff = texture2D(diffuseMap,vary_texcoord0.xy);
 #endif
+	vec4 gamma_diff = diff;
 
 	diff.rgb = pow(diff.rgb, vec3(2.2f, 2.2f, 2.2f));
 
@@ -224,7 +228,7 @@ void main()
 	vec3 normal = vary_norm; 
 	
 	vec3 l = light_position[0].xyz;
-	vec3 dlight = calcDirectionalLight(normal, l) * 2.6;
+	vec3 dlight = calcDirectionalLight(normal, l);
 	dlight = dlight * vary_directional.rgb * vary_pointlight_col;
 
 #if HAS_SHADOW
@@ -233,13 +237,16 @@ void main()
 	vec4 col = vec4(vary_ambient + dlight, vertex_color_alpha);
 #endif
 
-	vec4 color = diff * col;
+	vec4 color = gamma_diff * col;
 	
 	color.rgb = atmosLighting(color.rgb);
 
 	color.rgb = scaleSoftClip(color.rgb);
+
+	color.rgb = pow(color.rgb, vec3(2.2));
 	col = vec4(0,0,0,0);
 
+	
    #define LIGHT_LOOP(i) col.rgb += light_diffuse[i].rgb * calcPointLightOrSpotLight(pos.xyz, normal, light_position[i], light_direction[i].xyz, light_attenuation[i].x, light_attenuation[i].y, light_attenuation[i].z);
 
 	LIGHT_LOOP(1)
@@ -250,7 +257,7 @@ void main()
 	LIGHT_LOOP(6)
 	LIGHT_LOOP(7)
 
-	color.rgb += diff.rgb * vary_pointlight_col * col.rgb;
+	color.rgb += diff.rgb * pow(vary_pointlight_col, vec3(2.2)) * col.rgb;
 
 	color.rgb = pow(color.rgb, vec3(1.0/2.2));
 
diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl
index 247ee0a34f32cb48519db0784ae8f30bd766672a..9d3ba564cdc4556f18e3ef4a3eed801b48032168 100755
--- a/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl
@@ -58,8 +58,6 @@ mat4 getSkinnedTransform();
 vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol);
 void calcAtmospherics(vec3 inPositionEye);
 
-vec3 calcDirectionalLight(vec3 n, vec3 l);
-
 vec3 atmosAmbient(vec3 light);
 vec3 atmosAffectDirectionalLight(float lightIntensity);
 vec3 scaleDownLight(vec3 light);
@@ -88,12 +86,6 @@ uniform vec3 light_diffuse[8];
 
 uniform vec3 sun_dir;
 
-vec3 calcDirectionalLight(vec3 n, vec3 l)
-{
-        float a = max(dot(n,l),0.0);
-        return vec3(a,a,a);
-}
-
 vec3 calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight)
 {
 	//get light vector
@@ -184,7 +176,7 @@ void main()
 	//vec4 color = calcLighting(pos.xyz, norm, diffuse_color, vec4(0.));
 	vec4 col = vec4(0.0, 0.0, 0.0, diffuse_color.a);
 	
-	vec3 diff = pow(diffuse_color.rgb, vec3(2.2));
+	vec3 diff = diffuse_color.rgb;
 
 	
 
diff --git a/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl
index eebeb91bf834c20c4a4759099bc55be56cb55277..968a5f6b3df7fa57f19ca85c8f82eaed96bfb71c 100755
--- a/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl
@@ -46,11 +46,6 @@ VARYING vec2 vary_fragcoord;
 uniform mat4 inv_proj;
 uniform vec2 screen_res;
 
-vec3 getKern(int i)
-{
-	return kern[i];
-}
-
 vec4 getPosition(vec2 pos_screen)
 {
 	float depth = texture2DRect(depthMap, pos_screen.xy).r;
@@ -110,7 +105,7 @@ void main()
 	vec2 dlt = kern_scale * delta / (1.0+norm.xy*norm.xy);
 	dlt /= max(-pos.z*dist_factor, 1.0);
 	
-	vec2 defined_weight = getKern(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'
+	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
@@ -120,28 +115,33 @@ void main()
 	float tc_mod = 0.5*(tc.x + tc.y); // mod(tc.x+tc.y,2)
 	tc_mod -= floor(tc_mod);
 	tc_mod *= 2.0;
-	tc += ( (tc_mod - 0.5) * getKern(1).z * dlt * 0.5 );
+	tc += ( (tc_mod - 0.5) * kern[1].z * dlt * 0.5 );
 
 	for (int i = 1; i < 4; i++)
 	{
-		vec2 samptc = tc + getKern(i).z*dlt;
-	        vec3 samppos = getPosition(samptc).xyz; 
+		vec2 samptc = tc + kern[i].z*dlt;
+	    vec3 samppos = getPosition(samptc).xyz; 
+
 		float d = dot(norm.xyz, samppos.xyz-pos.xyz);// dist from plane
+		
 		if (d*d <= pointplanedist_tolerance_pow2)
 		{
-			col += texture2DRect(lightMap, samptc)*getKern(i).xyxx;
-			defined_weight += getKern(i).xy;
+			col += texture2DRect(lightMap, samptc)*kern[i].xyxx;
+			defined_weight += kern[i].xy;
 		}
 	}
+
 	for (int i = 1; i < 4; i++)
 	{
-		vec2 samptc = tc - getKern(i).z*dlt;
-	        vec3 samppos = getPosition(samptc).xyz; 
+		vec2 samptc = tc - kern[i].z*dlt;
+	    vec3 samppos = getPosition(samptc).xyz; 
+
 		float d = dot(norm.xyz, samppos.xyz-pos.xyz);// dist from plane
+		
 		if (d*d <= pointplanedist_tolerance_pow2)
 		{
-			col += texture2DRect(lightMap, samptc)*getKern(i).xyxx;
-			defined_weight += getKern(i).xy;
+			col += texture2DRect(lightMap, samptc)*kern[i].xyxx;
+			defined_weight += kern[i].xy;
 		}
 	}
 
diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl
index a2c3ec3355ce16d531995a2aea881ba92c870332..adc361d7a2b1409863450df01437c9598ba3652e 100755
--- a/indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl
@@ -43,10 +43,12 @@ vec2 encode_normal(vec3 n)
 void main() 
 {
 	vec3 col = vertex_color.rgb * diffuseLookup(vary_texcoord0.xy).rgb;
+	
+	vec3 spec;
+	spec.rgb = vec3(vertex_color.a);
 
 	frag_data[0] = vec4(col, 0.0);
-	frag_data[1] = vertex_color.aaaa; // spec
-	frag_data[1] = vec4(vec3(vertex_color.a), vertex_color.a+(1.0-vertex_color.a)*vertex_color.a); // spec - from former class3 - maybe better, but not so well tested
+	frag_data[1] = vec4(spec, vertex_color.a); // spec
 	vec3 nvn = normalize(vary_normal);
 	frag_data[2] = vec4(encode_normal(nvn.xyz), vertex_color.a, 0.0);
 }
diff --git a/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl b/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl
index de2f74b68101f5b49c52fbe066ebfdecf4e8e270..618ea747f58c87d8b724b3da3593decb7222dd96 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl
@@ -127,7 +127,7 @@ vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 npos, vec3 diffuse, vec4 spe
 	vec3 lv = lp.xyz-v;
 	
 	//get distance
-	float d = dot(lv,lv);
+	float d = length(lv);
 	
 	float da = 1.0;
 
@@ -139,8 +139,10 @@ vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 npos, vec3 diffuse, vec4 spe
 		lv = normalize(lv);
 	
 		//distance attenuation
-		float dist2 = d/la;
-		float dist_atten = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0);
+		float dist = d/la;
+		float dist_atten = clamp(1.0-(dist-1.0*(1.0-fa))/fa, 0.0, 1.0);
+		dist_atten *= dist_atten;
+		dist_atten *= 1.4;
 
 		// spotlight coefficient.
 		float spot = max(dot(-ln, lv), is_pointlight);
@@ -321,9 +323,9 @@ void calcAtmospherics(vec3 inPositionEye, float ambFactor) {
 		  + tmpAmbient)));
 
 	//brightness of surface both sunlight and ambient
-	setSunlitColor(pow(vec3(sunlight * .5), vec3(2.2)) * 2.2);
-	setAmblitColor(pow(vec3(tmpAmbient * .25), vec3(2.2)) * 2.2);
-	setAdditiveColor(pow(getAdditiveColor() * vec3(1.0 - temp1), vec3(2.2)) * 2.2);
+	setSunlitColor(vec3(sunlight * .5));
+	setAmblitColor(vec3(tmpAmbient * .25));
+	setAdditiveColor(getAdditiveColor() * vec3(1.0 - temp1));
 }
 
 vec3 atmosLighting(vec3 light)
@@ -617,8 +619,8 @@ void main()
 
 	col.rgb *= ambient;
 
-	col.rgb = col.rgb + atmosAffectDirectionalLight(final_da * 2.6);
-	col.rgb *= diffuse.rgb;
+	col.rgb = col.rgb + atmosAffectDirectionalLight(pow(final_da, 1.0/1.3));
+	col.rgb *= old_diffcol.rgb;
 	
 
 	float glare = 0.0;
@@ -647,9 +649,8 @@ void main()
 	{
 		//add environmentmap
 		vec3 env_vec = env_mat * refnormpersp;
-		float exponent = mix(2.2, 1.0, diffuse.a);
-
-		vec3 refcol = pow(textureCube(environmentMap, env_vec).rgb, vec3(exponent))*exponent;
+		
+		vec3 refcol = textureCube(environmentMap, env_vec).rgb;
 
 		col = mix(col.rgb, refcol, 
 			envIntensity);  
@@ -660,13 +661,12 @@ void main()
 		glare += cur_glare;
 	}
 
-	float exponent = mix(1.0, 2.2, diffuse.a);
-	col = pow(col, vec3(exponent));
-				
-	
 	col = mix(atmosLighting(col), fullbrightAtmosTransport(col), diffuse.a);
 	col = mix(scaleSoftClip(col), fullbrightScaleSoftClip(col), diffuse.a);
 
+	//convert to linear space before adding local lights
+	col = pow(col, vec3(2.2));
+
 			
 	vec3 npos = normalize(-pos.xyz);
 
@@ -681,6 +681,7 @@ void main()
 		LIGHT_LOOP(7)
 
 
+	//convert to gamma space for display on screen
 	col.rgb = pow(col.rgb, vec3(1.0/2.2));
 
 	frag_color.rgb = col.rgb;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl
index b35ba549f65ecfabfddb62a166fe4bdfa8bd3b3f..868526d457eb61e9b22106aec75525ed58b115d5 100755
--- a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl
@@ -127,9 +127,9 @@ void main()
 		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)
+		float dist = length(lv);
+		dist /= light[i].w;
+		if (dist > 1.0)
 		{
 			light_contrib = false;
 		}
@@ -146,10 +146,10 @@ void main()
 			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);
+			float dist_atten = clamp(1.0-(dist-1.0*(1.0-fa))/fa, 0.0, 1.0);
+			dist_atten *= dist_atten;
+			dist_atten *= 2.0;
 			
-			dist_atten = pow(dist_atten, 2.2) * 2.2;
-
 			dist_atten *= noise;
 
 			float lit = da * dist_atten;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl
index 36fb4afa520bd829103c0d2bfeef0eacbb23796a..97bf49a605b0e5346cdca1736a275d0d4a3113ec 100755
--- a/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl
@@ -177,9 +177,9 @@ void main()
 	
 	vec3 pos = getPosition(frag.xy).xyz;
 	vec3 lv = center.xyz-pos.xyz;
-	float dist2 = dot(lv,lv);
-	dist2 /= size;
-	if (dist2 > 1.0)
+	float dist = length(lv);
+	dist /= size;
+	if (dist > 1.0)
 	{
 		discard;
 	}
@@ -201,8 +201,10 @@ void main()
 	proj_tc.xyz /= proj_tc.w;
 	
 	float fa = falloff+1.0;
-	float dist_atten = min(1.0-(dist2-1.0*(1.0-fa))/fa, 1.0);
-	dist_atten = pow(dist_atten, 2.2) * 2.2;
+	float dist_atten = min(1.0-(dist-1.0*(1.0-fa))/fa, 1.0);
+	dist_atten *= dist_atten;
+	dist_atten *= 2.0;
+
 	if (dist_atten <= 0.0)
 	{
 		discard;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl
index c6b1eb7c8d57326b1f4e4e832174cce6867349af..caf20ce707e6b45f5d01f1a1c034e6d3308be014 100755
--- a/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl
@@ -110,9 +110,9 @@ void main()
 	
 	vec3 pos = getPosition(frag.xy).xyz;
 	vec3 lv = trans_center.xyz-pos;
-	float dist2 = dot(lv,lv);
-	dist2 /= size;
-	if (dist2 > 1.0)
+	float dist = length(lv);
+	dist /= size;
+	if (dist > 1.0)
 	{
 		discard;
 	}
@@ -133,8 +133,10 @@ void main()
 	
 	vec3 col = texture2DRect(diffuseRect, frag.xy).rgb;
 	float fa = falloff+1.0;
-	float dist_atten = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0);
-	dist_atten = pow(dist_atten, 2.2) * 2.2;
+	float dist_atten = clamp(1.0-(dist-1.0*(1.0-fa))/fa, 0.0, 1.0);
+	dist_atten *= dist_atten;
+	dist_atten *= 2.0;
+	
 	float lit = da * dist_atten * noise;
 
 	col = color.rgb*lit*col;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl b/indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl
index 9491421236d49d0ad05f8220274498c75809a54e..a5625fbc16e1f567a41ff5f806ab187481a039ee 100755
--- a/indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl
@@ -37,7 +37,7 @@ VARYING vec3 trans_center;
 void main()
 {
 	//transform vertex
-	vec3 p = position*sqrt(size)+center;
+	vec3 p = position*size+center;
 	vec4 pos = modelview_projection_matrix * vec4(p.xyz, 1.0);
 	vary_fragcoord = pos;
 	trans_center = (modelview_matrix*vec4(center.xyz, 1.0)).xyz;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl
index b40850e76962e2f6ca577d2b5cb126c73b916c87..08583ad0f2f7804c7fbf943288381fb7f925efdb 100755
--- a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl
@@ -248,9 +248,9 @@ void calcAtmospherics(vec3 inPositionEye, float ambFactor) {
 		  + tmpAmbient)));
 
 	//brightness of surface both sunlight and ambient
-	setSunlitColor(pow(vec3(sunlight * .5), vec3(global_gamma)) * global_gamma);
-	setAmblitColor(pow(vec3(tmpAmbient * .25), vec3(global_gamma)) * global_gamma);
-	setAdditiveColor(pow(getAdditiveColor() * vec3(1.0 - temp1), vec3(global_gamma)) * global_gamma);
+	setSunlitColor(vec3(sunlight * .5));
+	setAmblitColor(vec3(tmpAmbient * .25));
+	setAdditiveColor(getAdditiveColor() * vec3(1.0 - temp1));
 }
 
 vec3 atmosLighting(vec3 light)
@@ -325,8 +325,13 @@ void main()
 	norm.xyz = decode_normal(norm.xy); // unpack norm
 		
 	float da = max(dot(norm.xyz, sun_dir.xyz), 0.0);
+	da = pow(da, 1.0/1.3);
 
 	vec4 diffuse = texture2DRect(diffuseRect, tc);
+
+	//convert to gamma space
+	diffuse.rgb = pow(diffuse.rgb, vec3(1.0/2.2));
+
 	vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy);
 	vec3 col;
 	float bloom = 0.0;
@@ -341,7 +346,7 @@ void main()
 
 		col.rgb *= ambient;
 
-		col += atmosAffectDirectionalLight(max(min(da, 1.0) * 2.6, 0.0));
+		col += atmosAffectDirectionalLight(max(min(da, 1.0), 0.0));
 	
 		col *= diffuse.rgb;
 	
@@ -362,23 +367,18 @@ void main()
 		}
 		
 		
-		col = mix(col.rgb, pow(diffuse.rgb, vec3(1.0/2.2)), diffuse.a);
-		
-		
+		col = mix(col.rgb, diffuse.rgb, diffuse.a);
+				
 		if (envIntensity > 0.0)
 		{ //add environmentmap
 			vec3 env_vec = env_mat * refnormpersp;
 			
-			float exponent = mix(2.2, 1.0, diffuse.a);
-			vec3 refcol = pow(textureCube(environmentMap, env_vec).rgb, vec3(exponent))*exponent;
+			
+			vec3 refcol = textureCube(environmentMap, env_vec).rgb;
 
 			col = mix(col.rgb, refcol, 
 				envIntensity);  
-
 		}
-
-		float exponent = mix(1.0, 2.2, diffuse.a);
-		col = pow(col, vec3(exponent));
 				
 		if (norm.w < 0.5)
 		{
@@ -386,10 +386,12 @@ void main()
 			col = mix(scaleSoftClip(col), fullbrightScaleSoftClip(col), diffuse.a);
 		}
 
+		col = pow(col, vec3(2.2));
+
 		//col = vec3(1,0,1);
 		//col.g = envIntensity;
 	}
-	
+
 	frag_color.rgb = col;
 
 	frag_color.a = bloom;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl
index 3539c8d2b27b450727efb6148c46620b7d5512c4..1975b18652d29a6c92576b4ceb189e7fc63c33a0 100755
--- a/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl
@@ -175,9 +175,9 @@ void main()
 	
 	vec3 pos = getPosition(frag.xy).xyz;
 	vec3 lv = trans_center.xyz-pos.xyz;
-	float dist2 = dot(lv,lv);
-	dist2 /= size;
-	if (dist2 > 1.0)
+	float dist = length(lv);
+	dist /= size;
+	if (dist > 1.0)
 	{
 		discard;
 	}
@@ -199,8 +199,10 @@ void main()
 	proj_tc.xyz /= proj_tc.w;
 	
 	float fa = falloff+1.0;
-	float dist_atten = min(1.0-(dist2-1.0*(1.0-fa))/fa, 1.0);
-	dist_atten = pow(dist_atten, 2.2) * 2.2;
+	float dist_atten = min(1.0-(dist-1.0*(1.0-fa))/fa, 1.0);
+	dist_atten *= dist_atten;
+	dist_atten *= 2.0;
+
 	if (dist_atten <= 0.0)
 	{
 		discard;
@@ -279,10 +281,7 @@ void main()
 			//col += spec.rgb;
 		}
 	}	
-	
-	
-	
-	
+
 
 	if (envIntensity > 0.0)
 	{
diff --git a/indra/newview/app_settings/shaders/class1/interface/downsampleDepthF.glsl b/indra/newview/app_settings/shaders/class1/interface/downsampleDepthF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..6523a06d22b6259945e24251c7c8b73fecfba192
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/interface/downsampleDepthF.glsl
@@ -0,0 +1,67 @@
+/** 
+ * @file debugF.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2011, 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$
+ */
+
+#ifdef DEFINE_GL_FRAGCOLOR
+out vec4 frag_color;
+#else
+#define frag_color gl_FragColor
+#endif
+
+uniform sampler2D depthMap;
+
+uniform float delta;
+
+VARYING vec2 tc0;
+VARYING vec2 tc1;
+VARYING vec2 tc2;
+VARYING vec2 tc3;
+VARYING vec2 tc4;
+VARYING vec2 tc5;
+VARYING vec2 tc6;
+VARYING vec2 tc7;
+VARYING vec2 tc8;
+
+void main() 
+{
+	vec4 depth1 = 
+		vec4(texture2D(depthMap, tc0).r,
+			texture2D(depthMap, tc1).r,
+			texture2D(depthMap, tc2).r,
+			texture2D(depthMap, tc3).r);
+
+	vec4 depth2 = 
+		vec4(texture2D(depthMap, tc4).r,
+			texture2D(depthMap, tc5).r,
+			texture2D(depthMap, tc6).r,
+			texture2D(depthMap, tc7).r);
+
+	depth1 = min(depth1, depth2);
+	float depth = min(depth1.x, depth1.y);
+	depth = min(depth, depth1.z);
+	depth = min(depth, depth1.w);
+	depth = min(depth, texture2D(depthMap, tc8).r);
+
+	gl_FragDepth = depth;
+}
diff --git a/indra/newview/app_settings/shaders/class1/interface/downsampleDepthRectF.glsl b/indra/newview/app_settings/shaders/class1/interface/downsampleDepthRectF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..0e5dc0818363afffa65038762f0ca726ce3d7069
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/interface/downsampleDepthRectF.glsl
@@ -0,0 +1,69 @@
+/** 
+ * @file debugF.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2011, 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$
+ */
+
+#extension GL_ARB_texture_rectangle : enable
+
+#ifdef DEFINE_GL_FRAGCOLOR
+out vec4 frag_color;
+#else
+#define frag_color gl_FragColor
+#endif
+
+uniform sampler2DRect depthMap;
+
+uniform float delta;
+
+VARYING vec2 tc0;
+VARYING vec2 tc1;
+VARYING vec2 tc2;
+VARYING vec2 tc3;
+VARYING vec2 tc4;
+VARYING vec2 tc5;
+VARYING vec2 tc6;
+VARYING vec2 tc7;
+VARYING vec2 tc8;
+
+void main() 
+{
+	vec4 depth1 = 
+		vec4(texture2DRect(depthMap, tc0).r,
+			texture2DRect(depthMap, tc1).r,
+			texture2DRect(depthMap, tc2).r,
+			texture2DRect(depthMap, tc3).r);
+
+	vec4 depth2 = 
+		vec4(texture2DRect(depthMap, tc4).r,
+			texture2DRect(depthMap, tc5).r,
+			texture2DRect(depthMap, tc6).r,
+			texture2DRect(depthMap, tc7).r);
+
+	depth1 = min(depth1, depth2);
+	float depth = min(depth1.x, depth1.y);
+	depth = min(depth, depth1.z);
+	depth = min(depth, depth1.w);
+	depth = min(depth, texture2DRect(depthMap, tc8).r);
+
+	gl_FragDepth = depth;
+}
diff --git a/indra/newview/app_settings/shaders/class1/interface/downsampleDepthV.glsl b/indra/newview/app_settings/shaders/class1/interface/downsampleDepthV.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..71d80911d62635c28e5996fd174800fc476a4c8d
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/interface/downsampleDepthV.glsl
@@ -0,0 +1,59 @@
+/** 
+ * @file debugV.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2011, 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$
+ */
+
+uniform mat4 modelview_projection_matrix;
+
+ATTRIBUTE vec3 position;
+
+uniform vec2 screen_res;
+
+uniform vec2 delta;
+
+VARYING vec2 tc0;
+VARYING vec2 tc1;
+VARYING vec2 tc2;
+VARYING vec2 tc3;
+VARYING vec2 tc4;
+VARYING vec2 tc5;
+VARYING vec2 tc6;
+VARYING vec2 tc7;
+VARYING vec2 tc8;
+
+void main()
+{
+	gl_Position = vec4(position, 1.0); 
+	
+	vec2 tc = (position.xy*0.5+0.5)*screen_res;
+	tc0 = tc+vec2(-delta.x,-delta.y);
+	tc1 = tc+vec2(0,-delta.y);
+	tc2 = tc+vec2(delta.x,-delta.y);
+	tc3 = tc+vec2(-delta.x,0);
+	tc4 = tc+vec2(0,0);
+	tc5 = tc+vec2(delta.x,0);
+	tc6 = tc+vec2(-delta.x,delta.y);
+	tc7 = tc+vec2(0,delta.y);
+	tc8 = tc+vec2(delta.x,delta.y);
+}
+
diff --git a/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl
index eaacb93cb979aafa963ec144319ae63a20673b3b..780df9ed1ac8c0a40ff9231b32af7f39bf09d988 100755
--- a/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl
@@ -179,9 +179,9 @@ void main()
 	
 	vec3 pos = getPosition(frag.xy).xyz;
 	vec3 lv = center.xyz-pos.xyz;
-	float dist2 = dot(lv,lv);
-	dist2 /= size;
-	if (dist2 > 1.0)
+	float dist = length(lv);
+	dist /= size;
+	if (dist > 1.0)
 	{
 		discard;
 	}
@@ -215,8 +215,9 @@ void main()
 	proj_tc.xyz /= proj_tc.w;
 	
 	float fa = falloff+1.0;
-	float dist_atten = min(1.0-(dist2-1.0*(1.0-fa))/fa, 1.0);
-	dist_atten = pow(dist_atten, 2.2) * 2.2;
+	float dist_atten = min(1.0-(dist-1.0*(1.0-fa))/fa, 1.0);
+	dist_atten *= dist_atten;
+	dist_atten *= 2.0;
 	if (dist_atten <= 0.0)
 	{
 		discard;
diff --git a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl
index 4fe2f1551e61443da2dfb6b6746ebf703f646a9e..67bac1f7c2e42079d9ddfa9a5bc932bf20d3fa6a 100755
--- a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl
@@ -254,9 +254,13 @@ void calcAtmospherics(vec3 inPositionEye, float ambFactor) {
 		  + tmpAmbient)));
 
 	//brightness of surface both sunlight and ambient
-	setSunlitColor(pow(vec3(sunlight * .5), vec3(global_gamma)) * global_gamma);
+	/*setSunlitColor(pow(vec3(sunlight * .5), vec3(global_gamma)) * global_gamma);
 	setAmblitColor(pow(vec3(tmpAmbient * .25), vec3(global_gamma)) * global_gamma);
-	setAdditiveColor(pow(getAdditiveColor() * vec3(1.0 - temp1), vec3(global_gamma)) * global_gamma);
+	setAdditiveColor(pow(getAdditiveColor() * vec3(1.0 - temp1), vec3(global_gamma)) * global_gamma);*/
+
+	setSunlitColor(vec3(sunlight * .5));
+	setAmblitColor(vec3(tmpAmbient * .25));
+	setAdditiveColor(getAdditiveColor() * vec3(1.0 - temp1));
 }
 
 vec3 atmosLighting(vec3 light)
@@ -332,7 +336,14 @@ void main()
 		
 	float da = max(dot(norm.xyz, sun_dir.xyz), 0.0);
 
+	float light_gamma = 1.0/1.3;
+	da = pow(da, light_gamma);
+
+
 	vec4 diffuse = texture2DRect(diffuseRect, tc);
+
+	//convert to gamma space
+	diffuse.rgb = pow(diffuse.rgb, vec3(1.0/2.2));
 	
 	vec3 col;
 	float bloom = 0.0;
@@ -340,7 +351,12 @@ void main()
 		vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy);
 		
 		vec2 scol_ambocc = texture2DRect(lightMap, vary_fragcoord.xy).rg;
+		scol_ambocc = pow(scol_ambocc, vec2(light_gamma));
+
 		float scol = max(scol_ambocc.r, diffuse.a); 
+
+		
+
 		float ambocc = scol_ambocc.g;
 	
 		calcAtmospherics(pos.xyz, ambocc);
@@ -353,7 +369,7 @@ void main()
 
 		col.rgb *= ambient;
 
-		col += atmosAffectDirectionalLight(max(min(da, scol) * 2.6, 0.0));
+		col += atmosAffectDirectionalLight(max(min(da, scol), 0.0));
 	
 		col *= diffuse.rgb;
 	
@@ -374,30 +390,27 @@ void main()
 		}
 	
 		
-		col = mix(col.rgb, pow(diffuse.rgb, vec3(1.0/2.2)), diffuse.a);
-		
-		
+		col = mix(col, diffuse.rgb, diffuse.a);
+
 		if (envIntensity > 0.0)
 		{ //add environmentmap
 			vec3 env_vec = env_mat * refnormpersp;
 			
-			float exponent = mix(2.2, 1.0, diffuse.a);
-			vec3 refcol = pow(textureCube(environmentMap, env_vec).rgb, vec3(exponent))*exponent;
+			vec3 refcol = textureCube(environmentMap, env_vec).rgb;
 
 			col = mix(col.rgb, refcol, 
 				envIntensity);  
 
 		}
-
-		float exponent = mix(1.0, 2.2, diffuse.a);
-		col = pow(col, vec3(exponent));
-				
+						
 		if (norm.w < 0.5)
 		{
 			col = mix(atmosLighting(col), fullbrightAtmosTransport(col), diffuse.a);
 			col = mix(scaleSoftClip(col), fullbrightScaleSoftClip(col), diffuse.a);
 		}
 
+		col = pow(col, vec3(2.2));
+
 		//col = vec3(1,0,1);
 		//col.g = envIntensity;
 	}
diff --git a/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl
index bdb713d682cdbc41601c319f9eeca4858153d5e7..fc0e6b2388991e5297073fafac187290ce002561 100755
--- a/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl
@@ -178,9 +178,9 @@ void main()
 	
 	vec3 pos = getPosition(frag.xy).xyz;
 	vec3 lv = trans_center.xyz-pos.xyz;
-	float dist2 = dot(lv,lv);
-	dist2 /= size;
-	if (dist2 > 1.0)
+	float dist = length(lv);
+	dist /= size;
+	if (dist > 1.0)
 	{
 		discard;
 	}
@@ -212,8 +212,10 @@ void main()
 	proj_tc.xyz /= proj_tc.w;
 	
 	float fa = falloff+1.0;
-	float dist_atten = min(1.0-(dist2-1.0*(1.0-fa))/fa, 1.0);
-	dist_atten = pow(dist_atten, 2.2) * 2.2;
+	float dist_atten = min(1.0-(dist-1.0*(1.0-fa))/fa, 1.0);
+	dist_atten *= dist_atten;
+	dist_atten *= 2.0;
+
 	if (dist_atten <= 0.0)
 	{
 		discard;
diff --git a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsV.glsl b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsV.glsl
index 8fd06c7e2f89d82107f4a4ff42c67f76fcd8683b..d174805cc08c739c70b2255b4aafbdc096547dc9 100755
--- a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsV.glsl
+++ b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsV.glsl
@@ -54,7 +54,6 @@ uniform float density_multiplier;
 uniform float distance_multiplier;
 uniform float max_y;
 uniform vec4 glow;
-uniform float global_gamma;
 
 void calcAtmospherics(vec3 inPositionEye) {
 
@@ -132,9 +131,9 @@ void calcAtmospherics(vec3 inPositionEye) {
 		  + tmpAmbient)));
 	
 	//brightness of surface both sunlight and ambient
-	setSunlitColor(pow(vec3(sunlight * .5), vec3(global_gamma)) * global_gamma);
-	setAmblitColor(pow(vec3(tmpAmbient * .25), vec3(global_gamma)) * global_gamma);
-	setAdditiveColor(pow(getAdditiveColor() * vec3(1.0 - temp1), vec3(global_gamma)) * global_gamma);
+	setSunlitColor(vec3(sunlight * .5));
+	setAmblitColor(vec3(tmpAmbient * .25));
+	setAdditiveColor(getAdditiveColor() * vec3(1.0 - temp1));
 
 	// vary_SunlitColor = vec3(0);
 	// vary_AmblitColor = vec3(0);
diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index 3e94c5edf758ade2e383e3f2bf00aea8ddfbb541..05f38244854742a3d76ca0f1be09963d3c61b4d2 100755
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -433,7 +433,7 @@ void LLAgent::init()
 {
 	mMoveTimer.start();
 
-	gSavedSettings.declareBOOL("SlowMotionAnimation", FALSE, "Declared in code", FALSE);
+	gSavedSettings.declareBOOL("SlowMotionAnimation", FALSE, "Declared in code", LLControlVariable::PERSIST_NO);
 	gSavedSettings.getControl("SlowMotionAnimation")->getSignal()->connect(boost::bind(&handleSlowMotionAnimation, _2));
 	
 	// *Note: this is where LLViewerCamera::getInstance() used to be constructed.
diff --git a/indra/newview/llcommandlineparser.cpp b/indra/newview/llcommandlineparser.cpp
index 17d403bbe1040b492658123af45a8e606e99037a..7adc6b8c5ec33c1a1753789c6277ef2cbe6c351f 100755
--- a/indra/newview/llcommandlineparser.cpp
+++ b/indra/newview/llcommandlineparser.cpp
@@ -39,13 +39,17 @@
 
 #include <boost/program_options.hpp>
 #include <boost/bind.hpp>
-#include<boost/tokenizer.hpp>
+#include <boost/tokenizer.hpp>
+#include <boost/assign/list_of.hpp>
 
 #if _MSC_VER
 #   pragma warning(pop)
 #endif
 
 #include "llsdserialize.h"
+#include "llerror.h"
+#include <string>
+#include <set>
 #include <iostream>
 #include <sstream>
 
@@ -63,6 +67,18 @@ namespace po = boost::program_options;
 // This could be good or bad, and probably won't matter for most use cases.
 namespace 
 {
+    // List of command-line switches that can't map-to settings variables.
+    // Going forward, we want every new command-line switch to map-to some
+    // settings variable. This list is used to validate that.
+    const std::set<std::string> unmapped_options = boost::assign::list_of
+        ("help")
+        ("set")
+        ("setdefault")
+        ("settings")
+        ("sessionsettings")
+        ("usersessionsettings")
+    ;
+
     po::options_description gOptionsDesc;
     po::positional_options_description gPositionalOptions;
 	po::variables_map gVariableMap;
@@ -561,9 +577,35 @@ void LLControlGroupCLP::configure(const std::string& config_filename, LLControlG
             }
 
             boost::function1<void, const token_vector_t&> callback;
-            if(option_params.has("map-to") && (NULL != controlGroup))
+            if (! option_params.has("map-to"))
+            {
+                // If this option isn't mapped to a settings variable, is it
+                // one of the ones for which that's unreasonable, or did
+                // someone carelessly add a new option? (Make all these
+                // configuration errors fatal so a maintainer will catch them
+                // right away.)
+                std::set<std::string>::const_iterator found = unmapped_options.find(long_name);
+                if (found == unmapped_options.end())
+                {
+                    llerrs << "New command-line option " << long_name
+                           << " should map-to a variable in settings.xml" << llendl;
+                }
+            }
+            else                    // option specifies map-to
             {
                 std::string controlName = option_params["map-to"].asString();
+                if (! controlGroup)
+                {
+                    llerrs << "Must pass gSavedSettings to LLControlGroupCLP::configure() for "
+                           << long_name << " (map-to " << controlName << ")" << llendl;
+                }
+
+                if (! controlGroup->getControl(controlName))
+                {
+                    llerrs << "Option " << long_name << " specifies map-to " << controlName
+                           << " which does not exist" << llendl;
+                }
+
                 callback = boost::bind(setControlValueCB, _1, 
                                        controlName, controlGroup);
             }
diff --git a/indra/newview/llfloaterabout.cpp b/indra/newview/llfloaterabout.cpp
index 318a03f755caabb2e76ed5e480dbc286d408a175..163f294d2a13bc7e1c7ef47cd8af3dc23f16cfab 100755
--- a/indra/newview/llfloaterabout.cpp
+++ b/indra/newview/llfloaterabout.cpp
@@ -33,8 +33,10 @@
 
 // Viewer includes
 #include "llagent.h"
+#include "llagentui.h"
 #include "llappviewer.h" 
 #include "llsecondlifeurls.h"
+#include "llslurl.h"
 #include "llvoiceclient.h"
 #include "lluictrlfactory.h"
 #include "llviewertexteditor.h"
@@ -257,6 +259,9 @@ LLSD LLFloaterAbout::getInfo()
 		info["HOSTNAME"] = gAgent.getRegion()->getHost().getHostName();
 		info["HOSTIP"] = gAgent.getRegion()->getHost().getString();
 		info["SERVER_VERSION"] = gLastVersionChannel;
+		LLSLURL slurl;
+		LLAgentUI::buildSLURL(slurl);
+		info["SLURL"] = slurl.getSLURLString();
 	}
 
 	// CPU
diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp
index 56b0c15cb9e8ec03157270f9ef3e45ec0d04b085..38592b3f6583c280f1ebb1a6eca70ce142f7c650 100755
--- a/indra/newview/llfloaterimnearbychat.cpp
+++ b/indra/newview/llfloaterimnearbychat.cpp
@@ -125,7 +125,7 @@ BOOL LLFloaterIMNearbyChat::postBuild()
 	setTitle(LLTrans::getString("NearbyChatTitle"));
 
 	// obsolete, but may be needed for backward compatibility?
-	gSavedSettings.declareS32("nearbychat_showicons_and_names", 2, "NearByChat header settings", true);
+	gSavedSettings.declareS32("nearbychat_showicons_and_names", 2, "NearByChat header settings", LLControlVariable::PERSIST_NONDFT);
 
 	if (gSavedPerAccountSettings.getBOOL("LogShowHistory"))
 	{
diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp
index b47fe9d4b123e2331cbf9a94c564d69c69a2c30d..8d3539d297e8d4b6b91d88c3bbcedd27a25de9db 100755
--- a/indra/newview/llmeshrepository.cpp
+++ b/indra/newview/llmeshrepository.cpp
@@ -1,3 +1,4 @@
+
 /** 
  * @file llmeshrepository.cpp
  * @brief Mesh repository implementation.
diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp
index 78401020a6f9f76f5dbd34e3e2f69788c24e0831..941c5787835c61a42d80a9ca2488a357e321423e 100755
--- a/indra/newview/llspatialpartition.cpp
+++ b/indra/newview/llspatialpartition.cpp
@@ -1498,6 +1498,8 @@ BOOL LLSpatialGroup::rebound()
 	if (mOctreeNode->getChildCount() == 1 && mOctreeNode->getElementCount() == 0)
 	{
 		LLSpatialGroup* group = (LLSpatialGroup*) mOctreeNode->getChild(0)->getListener(0);
+
+		//rebound single child
 		group->rebound();
 		
 		//copy single child's bounding box
@@ -1506,10 +1508,11 @@ BOOL LLSpatialGroup::rebound()
 		mExtents[0] = group->mExtents[0];
 		mExtents[1] = group->mExtents[1];
 		
+		//treat this node as a "chute" to a deeper level of the tree
 		group->setState(SKIP_FRUSTUM_CHECK);
 	}
 	else if (mOctreeNode->isLeaf())
-	{ //copy object bounding box if this is a leaf
+	{ //copy object bounding box if this is a leaf 
 		boundObjects(TRUE, mExtents[0], mExtents[1]);
 		mBounds[0] = mObjectBounds[0];
 		mBounds[1] = mObjectBounds[1];
@@ -1518,14 +1521,17 @@ BOOL LLSpatialGroup::rebound()
 	{
 		LLVector4a& newMin = mExtents[0];
 		LLVector4a& newMax = mExtents[1];
+		
+		//get bounding box of first child
 		LLSpatialGroup* group = (LLSpatialGroup*) mOctreeNode->getChild(0)->getListener(0);
 		group->clearState(SKIP_FRUSTUM_CHECK);
 		group->rebound();
+
 		//initialize to first child
 		newMin = group->mExtents[0];
 		newMax = group->mExtents[1];
 
-		//first, rebound children
+		//rebound remaining children, expanding bounding box to encompass children
 		for (U32 i = 1; i < mOctreeNode->getChildCount(); i++)
 		{
 			group = (LLSpatialGroup*) mOctreeNode->getChild(i)->getListener(0);
@@ -2506,7 +2512,7 @@ void pushBufferVerts(LLVertexBuffer* buffer, U32 mask)
 	}
 }
 
-void pushBufferVerts(LLSpatialGroup* group, U32 mask)
+void pushBufferVerts(LLSpatialGroup* group, U32 mask, bool push_alpha = true)
 {
 	if (group->mSpatialPartition->mRenderByGroup)
 	{
@@ -2515,7 +2521,10 @@ void pushBufferVerts(LLSpatialGroup* group, U32 mask)
 			LLDrawInfo* params = *(group->mDrawMap.begin()->second.begin());
 			LLRenderPass::applyModelMatrix(*params);
 		
-			pushBufferVerts(group->mVertexBuffer, mask);
+			if (push_alpha)
+			{
+				pushBufferVerts(group->mVertexBuffer, mask);
+			}
 
 			for (LLSpatialGroup::buffer_map_t::iterator i = group->mBufferMap.begin(); i != group->mBufferMap.end(); ++i)
 			{
@@ -2529,10 +2538,10 @@ void pushBufferVerts(LLSpatialGroup* group, U32 mask)
 			}
 		}
 	}
-	else
+	/*else
 	{
-		drawBox(group->mBounds[0], group->mBounds[1]);
-	}
+		//drawBox(group->mBounds[0], group->mBounds[1]);
+	}*/
 }
 
 void pushVertsColorCoded(LLSpatialGroup* group, U32 mask)
@@ -2705,17 +2714,53 @@ void renderOctree(LLSpatialGroup* group)
 //	drawBoxOutline(LLVector3(node->getCenter()), LLVector3(node->getSize()));
 }
 
+std::set<LLSpatialGroup*> visible_selected_groups;
+
 void renderVisibility(LLSpatialGroup* group, LLCamera* camera)
 {
-	LLGLEnable blend(GL_BLEND);
+	/*LLGLEnable blend(GL_BLEND);
 	gGL.setSceneBlendType(LLRender::BT_ALPHA);
 	LLGLEnable cull(GL_CULL_FACE);
-	glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+	glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);*/
 
-	BOOL render_objects = (!LLPipeline::sUseOcclusion || !group->isOcclusionState(LLSpatialGroup::OCCLUDED)) && group->isVisible() &&
+	/*BOOL render_objects = (!LLPipeline::sUseOcclusion || !group->isOcclusionState(LLSpatialGroup::OCCLUDED)) && group->isVisible() &&
 							!group->isEmpty();
 
+
 	if (render_objects)
+	{
+		LLGLDepthTest depth(GL_TRUE, GL_FALSE);
+
+		LLGLDisable blend(GL_BLEND);
+		gGL.diffuseColor4f(0.f, 0.75f, 0.f,0.5f);
+		pushBufferVerts(group, LLVertexBuffer::MAP_VERTEX, false);
+		
+		glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+		glLineWidth(4.f);
+		gGL.diffuseColor4f(0.f, 0.5f, 0.f, 1.f);
+		pushBufferVerts(group, LLVertexBuffer::MAP_VERTEX, false);
+		glLineWidth(1.f);
+		glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+
+		bool selected = false;
+		
+		for (LLSpatialGroup::element_iter iter = group->getDataBegin(); iter != group->getDataEnd(); ++iter)
+		{
+			LLDrawable* drawable = *iter;
+			if (drawable->getVObj().notNull() && drawable->getVObj()->isSelected())
+			{
+				selected = true;
+				break;
+			}
+		}
+		
+		if (selected)
+		{ //store for rendering occlusion volume as overlay
+			visible_selected_groups.insert(group);
+		}
+	}*/		
+
+	/*if (render_objects)
 	{
 		LLGLDepthTest depth_under(GL_TRUE, GL_FALSE, GL_GREATER);
 		gGL.diffuseColor4f(0, 0.5f, 0, 0.5f);
@@ -2740,6 +2785,59 @@ void renderVisibility(LLSpatialGroup* group, LLCamera* camera)
 			gGL.diffuseColor4f(0.f, 0.75f, 0.f,0.5f);
 			gGL.diffuseColor4f(0.f, 0.75f, 0.f, 0.5f);
 			pushBufferVerts(group, LLVertexBuffer::MAP_VERTEX);
+		
+			bool selected = false;
+		
+			for (LLSpatialGroup::element_iter iter = group->getDataBegin(); iter != group->getDataEnd(); ++iter)
+			{
+				LLDrawable* drawable = *iter;
+				if (drawable->getVObj().notNull() && drawable->getVObj()->isSelected())
+				{
+					selected = true;
+					break;
+				}
+			}
+		
+			if (selected)
+			{ //store for rendering occlusion volume as overlay
+				visible_selected_groups.insert(group);
+			}
+		}		
+	}*/
+}
+
+void renderXRay(LLSpatialGroup* group, LLCamera* camera)
+{
+	BOOL render_objects = (!LLPipeline::sUseOcclusion || !group->isOcclusionState(LLSpatialGroup::OCCLUDED)) && group->isVisible() &&
+							!group->isEmpty();
+	
+	if (render_objects)
+	{
+		pushBufferVerts(group, LLVertexBuffer::MAP_VERTEX, false);
+
+		bool selected = false;
+
+		for (LLSpatialGroup::element_iter iter = group->getDataBegin(); iter != group->getDataEnd(); ++iter)
+		{
+			LLDrawable* drawable = *iter;
+			if (drawable->getVObj().notNull() && drawable->getVObj()->isSelected())
+			{
+				selected = true;
+				break;
+			}
+		}
+
+		if (selected)
+		{ //store for rendering occlusion volume as overlay
+
+			if (!group->mSpatialPartition->isBridge())
+			{
+				visible_selected_groups.insert(group);
+			}
+			else
+			{
+				visible_selected_groups.insert(group->mSpatialPartition->asBridge()->getSpatialGroup());
+			}
 		}
 	}
 }
@@ -4210,6 +4308,48 @@ class LLOctreeRenderNonOccluded : public LLOctreeTraveler<LLDrawable>
 	}
 };
 
+class LLOctreeRenderXRay : public LLOctreeTraveler<LLDrawable>
+{
+public:
+	LLCamera* mCamera;
+	LLOctreeRenderXRay(LLCamera* camera): mCamera(camera) {}
+	
+	virtual void traverse(const LLSpatialGroup::OctreeNode* node)
+	{
+		LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0);
+		
+		if (!mCamera || mCamera->AABBInFrustumNoFarClip(group->mBounds[0], group->mBounds[1]))
+		{
+			node->accept(this);
+			stop_glerror();
+
+			for (U32 i = 0; i < node->getChildCount(); i++)
+			{
+				traverse(node->getChild(i));
+				stop_glerror();
+			}
+			
+			//render visibility wireframe
+			if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCCLUSION))
+			{
+				group->rebuildGeom();
+				group->rebuildMesh();
+
+				gGL.flush();
+				gGL.pushMatrix();
+				gGLLastMatrix = NULL;
+				gGL.loadMatrix(gGLModelView);
+				renderXRay(group, mCamera);
+				stop_glerror();
+				gGLLastMatrix = NULL;
+				gGL.popMatrix();
+			}
+		}
+	}
+
+	virtual void visit(const LLSpatialGroup::OctreeNode* node) {}
+
+};
 
 class LLOctreeRenderPhysicsShapes : public LLOctreeTraveler<LLDrawable>
 {
@@ -4437,6 +4577,26 @@ void LLSpatialPartition::renderDebug()
 	LLOctreeRenderNonOccluded render_debug(camera);
 	render_debug.traverse(mOctree);
 
+
+	if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCCLUSION))
+	{
+		{
+			LLGLEnable cull(GL_CULL_FACE);
+			
+			LLGLEnable blend(GL_BLEND);
+			LLGLDepthTest depth_under(GL_TRUE, GL_FALSE, GL_GREATER);
+			glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+			gGL.diffuseColor4f(0.5f, 0.0f, 0, 0.25f);
+
+			LLGLEnable offset(GL_POLYGON_OFFSET_LINE);
+			glPolygonOffset(-1.f, -1.f);
+
+			LLOctreeRenderXRay xray(camera);
+			xray.traverse(mOctree);
+
+			glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+		}
+	}
 	if (LLGLSLShader::sNoFixedFunction)
 	{
 		gDebugProgram.unbind();
diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp
index afbb59e72343e2ea05404adc93d9f097d432e790..744ec4de2b02705f5605ff792df317d58dee2a03 100755
--- a/indra/newview/llviewercontrol.cpp
+++ b/indra/newview/llviewercontrol.cpp
@@ -83,7 +83,9 @@
 BOOL 				gHackGodmode = FALSE;
 #endif
 
-
+// Should you contemplate changing the name "Global", please first grep for
+// that string literal. There are at least a couple other places in the C++
+// code that assume the LLControlGroup named "Global" is gSavedSettings.
 LLControlGroup gSavedSettings("Global");	// saved at end of session
 LLControlGroup gSavedPerAccountSettings("PerAccount"); // saved at end of session
 LLControlGroup gCrashSettings("CrashSettings");	// saved at end of session
diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp
index b07fe39e37e69202c096bd37a3c1fe1d961d58c1..f90b35a7bddbf65cbe7897110678c795c1262c53 100755
--- a/indra/newview/llviewerdisplay.cpp
+++ b/indra/newview/llviewerdisplay.cpp
@@ -673,6 +673,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
 
 		static LLCullResult result;
 		LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
+		LLPipeline::sUnderWaterRender = LLViewerCamera::getInstance()->cameraUnderWater() ? TRUE : FALSE;
 		gPipeline.updateCull(*LLViewerCamera::getInstance(), result, water_clip);
 		stop_glerror();
 
@@ -879,7 +880,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
 		//}
 
 		LLPipeline::sUnderWaterRender = LLViewerCamera::getInstance()->cameraUnderWater() ? TRUE : FALSE;
-		
+
 		LLGLState::checkStates();
 		LLGLState::checkClientArrays();
 
diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp
index b9e08479353826edf78eed3569ac16356460b165..e24237522a1adf4301325a79b56049ec8771a84e 100755
--- a/indra/newview/llviewershadermgr.cpp
+++ b/indra/newview/llviewershadermgr.cpp
@@ -93,6 +93,8 @@ LLGLSLShader	gTwoTextureAddProgram;
 LLGLSLShader	gOneTextureNoColorProgram;
 LLGLSLShader	gDebugProgram;
 LLGLSLShader	gClipProgram;
+LLGLSLShader	gDownsampleDepthProgram;
+LLGLSLShader	gDownsampleDepthRectProgram;
 LLGLSLShader	gAlphaMaskProgram;
 
 //object shaders
@@ -702,6 +704,8 @@ void LLViewerShaderMgr::unloadShaders()
 	gOcclusionCubeProgram.unload();
 	gDebugProgram.unload();
 	gClipProgram.unload();
+	gDownsampleDepthProgram.unload();
+	gDownsampleDepthRectProgram.unload();
 	gAlphaMaskProgram.unload();
 	gUIProgram.unload();
 	gPathfindingProgram.unload();
@@ -3001,6 +3005,26 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
 		success = gClipProgram.createShader(NULL, NULL);
 	}
 
+	if (success)
+	{
+		gDownsampleDepthProgram.mName = "DownsampleDepth Shader";
+		gDownsampleDepthProgram.mShaderFiles.clear();
+		gDownsampleDepthProgram.mShaderFiles.push_back(make_pair("interface/downsampleDepthV.glsl", GL_VERTEX_SHADER_ARB));
+		gDownsampleDepthProgram.mShaderFiles.push_back(make_pair("interface/downsampleDepthF.glsl", GL_FRAGMENT_SHADER_ARB));
+		gDownsampleDepthProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE];
+		success = gDownsampleDepthProgram.createShader(NULL, NULL);
+	}
+
+	if (success)
+	{
+		gDownsampleDepthRectProgram.mName = "DownsampleDepthRect Shader";
+		gDownsampleDepthRectProgram.mShaderFiles.clear();
+		gDownsampleDepthRectProgram.mShaderFiles.push_back(make_pair("interface/downsampleDepthV.glsl", GL_VERTEX_SHADER_ARB));
+		gDownsampleDepthRectProgram.mShaderFiles.push_back(make_pair("interface/downsampleDepthRectF.glsl", GL_FRAGMENT_SHADER_ARB));
+		gDownsampleDepthRectProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE];
+		success = gDownsampleDepthRectProgram.createShader(NULL, NULL);
+	}
+
 	if (success)
 	{
 		gAlphaMaskProgram.mName = "Alpha Mask Shader";
diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h
index 8c7de05062025823875b185a7cd27b7734425bb0..438853cd6f7ef46117c5014842945789958e924e 100755
--- a/indra/newview/llviewershadermgr.h
+++ b/indra/newview/llviewershadermgr.h
@@ -230,6 +230,8 @@ extern LLGLSLShader			gSplatTextureRectProgram;
 extern LLGLSLShader			gGlowCombineFXAAProgram;
 extern LLGLSLShader			gDebugProgram;
 extern LLGLSLShader			gClipProgram;
+extern LLGLSLShader			gDownsampleDepthProgram;
+extern LLGLSLShader			gDownsampleDepthRectProgram;
 
 //output tex0[tc0] + tex1[tc1]
 extern LLGLSLShader			gTwoTextureAddProgram;
@@ -322,6 +324,7 @@ extern LLGLSLShader			gWLCloudProgram;
 extern LLGLSLShader			gPostColorFilterProgram;
 extern LLGLSLShader			gPostNightVisionProgram;
 
+
 // Deferred rendering shaders
 extern LLGLSLShader			gDeferredImpostorProgram;
 extern LLGLSLShader			gDeferredWaterProgram;
@@ -369,7 +372,6 @@ extern LLGLSLShader			gDeferredSkinnedFullbrightShinyProgram;
 extern LLGLSLShader			gDeferredSkinnedFullbrightProgram;
 extern LLGLSLShader			gNormalMapGenProgram;
 
-
 // Deferred materials shaders
 extern LLGLSLShader			gDeferredMaterialProgram[LLMaterial::SHADER_COUNT*2];
 
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 007c2b9003e0af10f636124451b318fa68911823..3be1f523529c78adbe6f42692a8a044fe53e4c93 100755
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -3517,7 +3517,12 @@ F32 LLVOVolume::getBinRadius()
 	}
 	else if (mDrawable->isStatic())
 	{
-		radius = llmax((S32) mDrawable->getRadius(), 1)*size_factor;
+		F32 szf = size_factor;
+
+		radius = llmax(mDrawable->getRadius(), szf);
+		
+		radius = powf(radius, 1.f+szf/radius);
+
 		radius *= 1.f + mDrawable->mDistanceWRTCamera * distance_factor[1];
 		radius += mDrawable->mDistanceWRTCamera * distance_factor[0];
 	}
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index ebf6be4e369ee71db80625aa48a08874d942c6fd..c25d22bbdf77f0b77072eecd5c88df9de6bb2981 100755
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -279,7 +279,7 @@ std::string gPoolNames[] =
 	"POOL_ALPHA"
 };
 
-void drawBox(const LLVector3& c, const LLVector3& r);
+void drawBox(const LLVector4a& c, const LLVector4a& r);
 void drawBoxOutline(const LLVector3& pos, const LLVector3& size);
 U32 nhpo2(U32 v);
 LLVertexBuffer* ll_create_cube_vb(U32 type_mask, U32 usage);
@@ -929,9 +929,12 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)
 		S32 shadow_detail = RenderShadowDetail;
 		BOOL ssao = RenderDeferredSSAO;
 		
+		const U32 occlusion_divisor = 3;
+
 		//allocate deferred rendering color buffers
 		if (!mDeferredScreen.allocate(resX, resY, GL_SRGB8_ALPHA8, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false;
 		if (!mDeferredDepth.allocate(resX, resY, 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false;
+		if (!mOcclusionDepth.allocate(resX/occlusion_divisor, resY/occlusion_divisor, 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false;
 		if (!addDeferredAttachments(mDeferredScreen)) return false;
 		
 		GLuint screenFormat = GL_RGBA16;
@@ -972,6 +975,7 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)
 			for (U32 i = 0; i < 4; i++)
 			{
 				if (!mShadow[i].allocate(sun_shadow_map_width,U32(resY*scale), 0, TRUE, FALSE, LLTexUnit::TT_TEXTURE)) return false;
+				if (!mShadowOcclusion[i].allocate(mShadow[i].getWidth()/occlusion_divisor, mShadow[i].getHeight()/occlusion_divisor, 0, TRUE, FALSE, LLTexUnit::TT_TEXTURE)) return false;
 			}
 		}
 		else
@@ -979,6 +983,7 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)
 			for (U32 i = 0; i < 4; i++)
 			{
 				mShadow[i].release();
+				mShadowOcclusion[i].release();
 			}
 		}
 
@@ -991,6 +996,7 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)
 			for (U32 i = 4; i < 6; i++)
 			{
 				if (!mShadow[i].allocate(spot_shadow_map_width, height, 0, TRUE, FALSE)) return false;
+				if (!mShadowOcclusion[i].allocate(mShadow[i].getWidth()/occlusion_divisor, mShadow[i].getHeight()/occlusion_divisor, 0, TRUE, FALSE)) return false;
 			}
 		}
 		else
@@ -998,6 +1004,7 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)
 			for (U32 i = 4; i < 6; i++)
 			{
 				mShadow[i].release();
+				mShadowOcclusion[i].release();
 			}
 		}
 
@@ -1014,11 +1021,13 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)
 		for (U32 i = 0; i < 6; i++)
 		{
 			mShadow[i].release();
+			mShadowOcclusion[i].release();
 		}
 		mFXAABuffer.release();
 		mScreen.release();
 		mDeferredScreen.release(); //make sure to release any render targets that share a depth buffer with mDeferredScreen first
 		mDeferredDepth.release();
+		mOcclusionDepth.release();
 						
 		if (!mScreen.allocate(resX, resY, GL_RGBA, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE)) return false;		
 	}
@@ -1396,6 +1405,8 @@ void LLPipeline::createLUTBuffers()
 			//LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_UNSIGNED_BYTE, lightResX, lightResY, GL_RED, GL_UNSIGNED_BYTE, ls, false);
 			gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
 			gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_TRILINEAR);
+			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
 			
 			delete [] ls;
 		}
@@ -2429,7 +2440,14 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl
 
 	if (to_texture)
 	{
-		mScreen.bindTarget();
+		if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender)
+		{
+			mOcclusionDepth.bindTarget();
+		}
+		else
+		{
+			mScreen.bindTarget();
+		}
 	}
 
 	if (sUseOcclusion > 1)
@@ -2567,7 +2585,14 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl
 
 	if (to_texture)
 	{
-		mScreen.flush();
+		if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender)
+		{
+			mOcclusionDepth.flush();
+		}
+		else
+		{
+			mScreen.flush();
+		}
 	}
 }
 
@@ -2635,6 +2660,73 @@ void LLPipeline::markOccluder(LLSpatialGroup* group)
 	}
 }
 
+void LLPipeline::downsampleDepthBuffer(LLRenderTarget& source, LLRenderTarget& dest, LLRenderTarget* scratch_space)
+{
+	LLGLSLShader* last_shader = LLGLSLShader::sCurBoundShaderPtr;
+
+	LLGLSLShader* shader = NULL;
+
+	if (scratch_space)
+	{
+		scratch_space->copyContents(source, 
+									0, 0, source.getWidth(), source.getHeight(), 
+									0, 0, scratch_space->getWidth(), scratch_space->getHeight(), GL_DEPTH_BUFFER_BIT, GL_NEAREST);
+	}
+
+	dest.bindTarget();
+	dest.clear(GL_DEPTH_BUFFER_BIT);
+
+	LLStrider<LLVector3> vert; 
+	mDeferredVB->getVertexStrider(vert);
+	LLStrider<LLVector2> tc0;
+		
+	vert[0].set(-1,1,0);
+	vert[1].set(-1,-3,0);
+	vert[2].set(3,1,0);
+	
+	if (source.getUsage() == LLTexUnit::TT_RECT_TEXTURE)
+	{
+		shader = &gDownsampleDepthRectProgram;
+		shader->bind();
+		shader->uniform2f("delta", 1.f, 1.f);
+		shader->uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, source.getWidth(), source.getHeight());
+	}
+	else
+	{
+		shader = &gDownsampleDepthProgram;
+		shader->bind();
+		shader->uniform2f("delta", 1.f/source.getWidth(), 1.f/source.getHeight());
+		shader->uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, 1.f, 1.f);
+	}
+
+	gGL.getTexUnit(0)->bind(scratch_space ? scratch_space : &source, TRUE);
+
+	{
+		LLGLDepthTest depth(GL_TRUE, GL_TRUE, GL_ALWAYS);
+		mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
+		mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
+	}
+	
+	dest.flush();
+	
+	if (last_shader)
+	{
+		last_shader->bind();
+	}
+	else
+	{
+		shader->unbind();
+	}
+}
+
+void LLPipeline::doOcclusion(LLCamera& camera, LLRenderTarget& source, LLRenderTarget& dest, LLRenderTarget* scratch_space)
+{
+	downsampleDepthBuffer(source, dest, scratch_space);
+	dest.bindTarget();
+	doOcclusion(camera);
+	dest.flush();
+}
+
 void LLPipeline::doOcclusion(LLCamera& camera)
 {
 	if (LLPipeline::sUseOcclusion > 1 && sCull->hasOcclusionGroups())
@@ -4547,7 +4639,7 @@ void LLPipeline::renderGeomDeferred(LLCamera& camera)
 	gGL.setColorMask(true, false);
 }
 
-void LLPipeline::renderGeomPostDeferred(LLCamera& camera)
+void LLPipeline::renderGeomPostDeferred(LLCamera& camera, bool do_occlusion)
 {
 	LLFastTimer t(FTM_POST_DEFERRED_POOLS);
 	U32 cur_type = 0;
@@ -4562,7 +4654,7 @@ void LLPipeline::renderGeomPostDeferred(LLCamera& camera)
 	gGL.setColorMask(true, false);
 
 	pool_set_t::iterator iter1 = mPools.begin();
-	BOOL occlude = LLPipeline::sUseOcclusion > 1;
+	BOOL occlude = LLPipeline::sUseOcclusion > 1 && do_occlusion;
 
 	while ( iter1 != mPools.end() )
 	{
@@ -4576,7 +4668,7 @@ void LLPipeline::renderGeomPostDeferred(LLCamera& camera)
 			gGLLastMatrix = NULL;
 			gGL.loadMatrix(gGLModelView);
 			LLGLSLShader::bindNoShader();
-			doOcclusion(camera);
+			doOcclusion(camera, mScreen, mOcclusionDepth, &mDeferredDepth);
 			gGL.setColorMask(true, false);
 		}
 
@@ -4794,6 +4886,7 @@ void LLPipeline::renderPhysicsDisplay()
 	mPhysicsDisplay.flush();
 }
 
+extern std::set<LLSpatialGroup*> visible_selected_groups;
 
 void LLPipeline::renderDebug()
 {
@@ -5204,6 +5297,27 @@ void LLPipeline::renderDebug()
 		}
 	}
 
+	if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCCLUSION) && LLGLSLShader::sNoFixedFunction)
+	{ //render visible selected group occlusion geometry
+		gDebugProgram.bind();
+		LLGLDepthTest depth(GL_TRUE, GL_FALSE);
+		gGL.diffuseColor3f(1,0,1);
+		for (std::set<LLSpatialGroup*>::iterator iter = visible_selected_groups.begin(); iter != visible_selected_groups.end(); ++iter)
+		{
+			LLSpatialGroup* group = *iter;
+
+			LLVector4a fudge;
+			fudge.splat(0.25f); //SG_OCCLUSION_FUDGE
+
+			LLVector4a size;
+			size.setAdd(fudge, group->mBounds[1]);
+
+			drawBox(group->mBounds[0], size);
+		}
+	}
+
+	visible_selected_groups.clear();
+
 	if (LLGLSLShader::sNoFixedFunction)
 	{
 		gUIProgram.bind();
@@ -5822,9 +5936,9 @@ void LLPipeline::setupAvatarLights(BOOL for_edit)
 
 		if (LLPipeline::sRenderDeferred)
 		{
-			diffuse.mV[0] = powf(diffuse.mV[0], 2.2f);
+			/*diffuse.mV[0] = powf(diffuse.mV[0], 2.2f);
 			diffuse.mV[1] = powf(diffuse.mV[1], 2.2f);
-			diffuse.mV[2] = powf(diffuse.mV[2], 2.2f);
+			diffuse.mV[2] = powf(diffuse.mV[2], 2.2f);*/
 		}
 
 		mHWLightColors[1] = diffuse;
@@ -5869,9 +5983,9 @@ void LLPipeline::setupAvatarLights(BOOL for_edit)
 
 		if (LLPipeline::sRenderDeferred)
 		{
-			backlight_diffuse.mV[0] = powf(backlight_diffuse.mV[0], 2.2f);
+			/*backlight_diffuse.mV[0] = powf(backlight_diffuse.mV[0], 2.2f);
 			backlight_diffuse.mV[1] = powf(backlight_diffuse.mV[1], 2.2f);
-			backlight_diffuse.mV[2] = powf(backlight_diffuse.mV[2], 2.2f);
+			backlight_diffuse.mV[2] = powf(backlight_diffuse.mV[2], 2.2f);*/
 		}
 
 		mHWLightColors[1] = backlight_diffuse;
@@ -6083,9 +6197,9 @@ void LLPipeline::setupHWLights(LLDrawPool* pool)
 
 		if (LLPipeline::sRenderDeferred)
 		{
-			light_diffuse.mV[0] = powf(light_diffuse.mV[0], 2.2f);
+			/*light_diffuse.mV[0] = powf(light_diffuse.mV[0], 2.2f);
 			light_diffuse.mV[1] = powf(light_diffuse.mV[1], 2.2f);
-			light_diffuse.mV[2] = powf(light_diffuse.mV[2], 2.2f);
+			light_diffuse.mV[2] = powf(light_diffuse.mV[2], 2.2f);*/
 		}
 
 		mHWLightColors[0] = light_diffuse;
@@ -6158,9 +6272,9 @@ void LLPipeline::setupHWLights(LLDrawPool* pool)
 
 			if (LLPipeline::sRenderDeferred)
 			{
-				light_color.mV[0] = powf(light_color.mV[0], 2.2f);
+				/*light_color.mV[0] = powf(light_color.mV[0], 2.2f);
 				light_color.mV[1] = powf(light_color.mV[1], 2.2f);
-				light_color.mV[2] = powf(light_color.mV[2], 2.2f);
+				light_color.mV[2] = powf(light_color.mV[2], 2.2f);*/
 			}
 
 			mHWLightColors[cur_light] = light_color;
@@ -6173,7 +6287,7 @@ void LLPipeline::setupHWLights(LLDrawPool* pool)
 			if (sRenderDeferred)
 			{
 				F32 size = light_radius*1.5f;
-				light_state->setLinearAttenuation(size*size);
+				light_state->setLinearAttenuation(size);
 				light_state->setQuadraticAttenuation(light->getLightFalloff()*0.5f+1.f);
 			}
 			else
@@ -6238,9 +6352,9 @@ void LLPipeline::setupHWLights(LLDrawPool* pool)
 
 		if (LLPipeline::sRenderDeferred)
 		{
-			light_color.mV[0] = powf(light_color.mV[0], 2.2f);
+			/*light_color.mV[0] = powf(light_color.mV[0], 2.2f);
 			light_color.mV[1] = powf(light_color.mV[1], 2.2f);
-			light_color.mV[2] = powf(light_color.mV[2], 2.2f);
+			light_color.mV[2] = powf(light_color.mV[2], 2.2f);*/
 		}
 
 		mHWLightColors[2] = light_color;
@@ -8201,11 +8315,7 @@ void LLPipeline::renderDeferredLighting()
 
 		LLStrider<LLVector3> vert; 
 		mDeferredVB->getVertexStrider(vert);
-		LLStrider<LLVector2> tc0;
-		LLStrider<LLVector2> tc1;
-		mDeferredVB->getTexCoord0Strider(tc0);
-		mDeferredVB->getTexCoord1Strider(tc1);
-
+		
 		vert[0].set(-1,1,0);
 		vert[1].set(-1,-3,0);
 		vert[2].set(3,1,0);
@@ -8386,7 +8496,7 @@ void LLPipeline::renderDeferredLighting()
 										LLPipeline::END_RENDER_TYPES);
 								
 			
-			renderGeomPostDeferred(*LLViewerCamera::getInstance());
+			renderGeomPostDeferred(*LLViewerCamera::getInstance(), false);
 			gPipeline.popRenderTypeMask();
 		}
 
@@ -8480,13 +8590,13 @@ void LLPipeline::renderDeferredLighting()
 								continue;
 							}
 							
-							col.mV[0] = powf(col.mV[0], 2.2f);
+							/*col.mV[0] = powf(col.mV[0], 2.2f);
 							col.mV[1] = powf(col.mV[1], 2.2f);
-							col.mV[2] = powf(col.mV[2], 2.2f);
+							col.mV[2] = powf(col.mV[2], 2.2f);*/
 							
 							LLFastTimer ftm(FTM_LOCAL_LIGHTS);
 							gDeferredLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, c);
-							gDeferredLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s*s);
+							gDeferredLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s);
 							gDeferredLightProgram.uniform3fv(LLShaderMgr::DIFFUSE_COLOR, 1, col.mV);
 							gDeferredLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, volume->getLightFalloff()*0.5f);
 							gGL.syncMatrices();
@@ -8507,7 +8617,7 @@ void LLPipeline::renderDeferredLighting()
 						glh::vec3f tc(c);
 						mat.mult_matrix_vec(tc);
 					
-						fullscreen_lights.push_back(LLVector4(tc.v[0], tc.v[1], tc.v[2], s*s));
+						fullscreen_lights.push_back(LLVector4(tc.v[0], tc.v[1], tc.v[2], s));
 						light_colors.push_back(LLVector4(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff()*0.5f));
 					}
 				}
@@ -8540,12 +8650,12 @@ void LLPipeline::renderDeferredLighting()
 					setupSpotLight(gDeferredSpotLightProgram, drawablep);
 					
 					LLColor3 col = volume->getLightColor();
-					col.mV[0] = powf(col.mV[0], 2.2f);
+					/*col.mV[0] = powf(col.mV[0], 2.2f);
 					col.mV[1] = powf(col.mV[1], 2.2f);
-					col.mV[2] = powf(col.mV[2], 2.2f);
+					col.mV[2] = powf(col.mV[2], 2.2f);*/
 					
 					gDeferredSpotLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, c);
-					gDeferredSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s*s);
+					gDeferredSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s);
 					gDeferredSpotLightProgram.uniform3fv(LLShaderMgr::DIFFUSE_COLOR, 1, col.mV);
 					gDeferredSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, volume->getLightFalloff()*0.5f);
 					gGL.syncMatrices();
@@ -8592,11 +8702,11 @@ void LLPipeline::renderDeferredLighting()
 					col[count] = light_colors.front();
 					light_colors.pop_front();
 					
-					col[count].mV[0] = powf(col[count].mV[0], 2.2f);
+					/*col[count].mV[0] = powf(col[count].mV[0], 2.2f);
 					col[count].mV[1] = powf(col[count].mV[1], 2.2f);
-					col[count].mV[2] = powf(col[count].mV[2], 2.2f);
+					col[count].mV[2] = powf(col[count].mV[2], 2.2f);*/
 					
-					far_z = llmin(light[count].mV[2]-sqrtf(light[count].mV[3]), far_z);
+					far_z = llmin(light[count].mV[2]-light[count].mV[3], far_z);
 					//col[count] = pow4fsrgb(col[count], 2.2f);
 					count++;
 					if (count == max_count || fullscreen_lights.empty())
@@ -8639,12 +8749,12 @@ void LLPipeline::renderDeferredLighting()
 
 					LLColor3 col = volume->getLightColor();
 					
-					col.mV[0] = powf(col.mV[0], 2.2f);
+					/*col.mV[0] = powf(col.mV[0], 2.2f);
 					col.mV[1] = powf(col.mV[1], 2.2f);
-					col.mV[2] = powf(col.mV[2], 2.2f);
+					col.mV[2] = powf(col.mV[2], 2.2f);*/
 					
 					gDeferredMultiSpotLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, tc.v);
-					gDeferredMultiSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s*s);
+					gDeferredMultiSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s);
 					gDeferredMultiSpotLightProgram.uniform3fv(LLShaderMgr::DIFFUSE_COLOR, 1, col.mV);
 					gDeferredMultiSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, volume->getLightFalloff()*0.5f);
 					mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
@@ -9320,9 +9430,15 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera
 		gDeferredShadowCubeProgram.bind();
 	}
 
+	LLRenderTarget& occlusion_target = mShadowOcclusion[LLViewerCamera::sCurCameraID-1];
+
+	occlusion_target.bindTarget();
 	updateCull(shadow_cam, result);
+	occlusion_target.flush();
+
 	stateSort(shadow_cam, result);
 	
+	
 	//generate shadow map
 	gGL.matrixMode(LLRender::MM_PROJECTION);
 	gGL.pushMatrix();
@@ -9410,7 +9526,10 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera
 	gDeferredShadowCubeProgram.bind();
 	gGLLastMatrix = NULL;
 	gGL.loadMatrix(gGLModelView);
-	doOcclusion(shadow_cam);
+
+	LLRenderTarget& occlusion_source = mShadow[LLViewerCamera::sCurCameraID-1];
+
+	doOcclusion(shadow_cam, occlusion_source, occlusion_target);
 
 	if (use_shader)
 	{
diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h
index 2c023a6f70b755d010c25a0261dca53c81f22d50..70dcf8040708568ae3c576bb686a814a137c635c 100755
--- a/indra/newview/pipeline.h
+++ b/indra/newview/pipeline.h
@@ -176,6 +176,12 @@ class LLPipeline
 	// Object related methods
 	void        markVisible(LLDrawable *drawablep, LLCamera& camera);
 	void		markOccluder(LLSpatialGroup* group);
+
+	//downsample source to dest, taking the maximum depth value per pixel in source and writing to dest
+	// if source's depth buffer cannot be bound for reading, a scratch space depth buffer must be provided
+	void		downsampleDepthBuffer(LLRenderTarget& source, LLRenderTarget& dest, LLRenderTarget* scratch_space = NULL);
+
+	void		doOcclusion(LLCamera& camera, LLRenderTarget& source, LLRenderTarget& dest, LLRenderTarget* scratch_space = NULL);
 	void		doOcclusion(LLCamera& camera);
 	void		markNotCulled(LLSpatialGroup* group, LLCamera &camera);
 	void        markMoved(LLDrawable *drawablep, BOOL damped_motion = FALSE);
@@ -275,7 +281,7 @@ class LLPipeline
 
 	void renderGeom(LLCamera& camera, BOOL forceVBOUpdate = FALSE);
 	void renderGeomDeferred(LLCamera& camera);
-	void renderGeomPostDeferred(LLCamera& camera);
+	void renderGeomPostDeferred(LLCamera& camera, bool do_occlusion=true);
 	void renderGeomShadow(LLCamera& camera);
 	void bindDeferredShader(LLGLSLShader& shader, U32 light_index = 0, U32 noise_map = 0xFFFFFFFF);
 	void setupSpotLight(LLGLSLShader& shader, LLDrawable* drawablep);
@@ -603,6 +609,7 @@ class LLPipeline
 	LLRenderTarget			mFXAABuffer;
 	LLRenderTarget			mEdgeMap;
 	LLRenderTarget			mDeferredDepth;
+	LLRenderTarget			mOcclusionDepth;
 	LLRenderTarget			mDeferredLight;
 	LLRenderTarget			mHighlight;
 	LLRenderTarget			mPhysicsDisplay;
@@ -615,6 +622,7 @@ class LLPipeline
 
 	//sun shadow map
 	LLRenderTarget			mShadow[6];
+	LLRenderTarget			mShadowOcclusion[6];
 	std::vector<LLVector3>	mShadowFrustPoints[4];
 	LLVector4				mShadowError;
 	LLVector4				mShadowFOV;
diff --git a/indra/newview/skins/default/xui/da/floater_about.xml b/indra/newview/skins/default/xui/da/floater_about.xml
index fc8bc33096d17eb5a96f689fb1511afe9ef87da1..9206690c8f27a5b44a4effe44932dd4a11b4f28f 100755
--- a/indra/newview/skins/default/xui/da/floater_about.xml
+++ b/indra/newview/skins/default/xui/da/floater_about.xml
@@ -8,7 +8,7 @@
 		Bygget med [COMPILER] version [COMPILER_VERSION]
 	</floater.string>
 	<floater.string name="AboutPosition">
-		Du er ved [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1] i regionen [REGION] lokaliseret ved &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; ([HOSTIP])
+		Du er ved [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] i regionen [REGION] lokaliseret ved &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; ([HOSTIP])
 [SERVER_VERSION]
 [SERVER_RELEASE_NOTES_URL]
 	</floater.string>
diff --git a/indra/newview/skins/default/xui/de/floater_about.xml b/indra/newview/skins/default/xui/de/floater_about.xml
index 4387a619634bab5fd4f2b23cc7044ac666a632d7..524546718327f201848959feadbe37e16b616dbb 100755
--- a/indra/newview/skins/default/xui/de/floater_about.xml
+++ b/indra/newview/skins/default/xui/de/floater_about.xml
@@ -8,7 +8,7 @@
 		Kompiliert mit [COMPILER] version [COMPILER_VERSION]
 	</floater.string>
 	<floater.string name="AboutPosition">
-		Sie befinden sich in [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1] in [REGION] auf &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; ([HOSTIP])
+		Sie befinden sich in [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] in [REGION] auf &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; ([HOSTIP])
 [SERVER_VERSION]
 [SERVER_RELEASE_NOTES_URL]
 	</floater.string>
diff --git a/indra/newview/skins/default/xui/en/floater_about.xml b/indra/newview/skins/default/xui/en/floater_about.xml
index 63eb87f27a17531b618229d8883eaeb11119c0c1..703015af20081678693a8f0d72ad20312f1dd2e4 100755
--- a/indra/newview/skins/default/xui/en/floater_about.xml
+++ b/indra/newview/skins/default/xui/en/floater_about.xml
@@ -22,7 +22,9 @@ Built with [COMPILER] version [COMPILER_VERSION]
 </floater.string>
   <floater.string
      name="AboutPosition">
-You are at [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1] in [REGION] located at &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; ([HOSTIP])
+You are at [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] in [REGION] located at &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; ([HOSTIP])
+SLURL: &lt;nolink&gt;[SLURL]&lt;/nolink&gt;
+(global coordinates [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1])
 [SERVER_VERSION]
 [SERVER_RELEASE_NOTES_URL]
 
diff --git a/indra/newview/skins/default/xui/es/floater_about.xml b/indra/newview/skins/default/xui/es/floater_about.xml
index 3696c7e12cfe6bc4ea349126b2612f28ebf70e41..7ca1e3721f48952bafa9d73296033b08219c2e77 100755
--- a/indra/newview/skins/default/xui/es/floater_about.xml
+++ b/indra/newview/skins/default/xui/es/floater_about.xml
@@ -8,7 +8,7 @@
 		Compilado con [COMPILER], versión [COMPILER_VERSION]
 	</floater.string>
 	<floater.string name="AboutPosition">
-		Estás en la posición [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1], de [REGION], alojada en &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; ([HOSTIP])
+		Estás en la posición [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1], de [REGION], alojada en &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; ([HOSTIP])
 [SERVER_VERSION]
 [SERVER_RELEASE_NOTES_URL]
 	</floater.string>
diff --git a/indra/newview/skins/default/xui/fr/floater_about.xml b/indra/newview/skins/default/xui/fr/floater_about.xml
index a659cb4245825c358dec94a8d3bc056fdafaa191..d45bdccf3e8f3e75f75fc2f0eb73ec6abe69017a 100755
--- a/indra/newview/skins/default/xui/fr/floater_about.xml
+++ b/indra/newview/skins/default/xui/fr/floater_about.xml
@@ -8,7 +8,7 @@
 		Compilé avec [COMPILER] version [COMPILER_VERSION]
 	</floater.string>
 	<floater.string name="AboutPosition">
-		Vous êtes à [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1] dans [REGION], se trouvant à &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; ([HOSTIP])
+		Vous êtes à [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] dans [REGION], se trouvant à &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; ([HOSTIP])
 [SERVER_VERSION]
 [SERVER_RELEASE_NOTES_URL]
 	</floater.string>
diff --git a/indra/newview/skins/default/xui/it/floater_about.xml b/indra/newview/skins/default/xui/it/floater_about.xml
index c672511fc5a675edcc2515a8a22f2922677b59db..b0fb585fa252f9a118db2282639e6fa26b5a7afe 100755
--- a/indra/newview/skins/default/xui/it/floater_about.xml
+++ b/indra/newview/skins/default/xui/it/floater_about.xml
@@ -8,7 +8,7 @@
 		Generato con [COMPILER] versione [COMPILER_VERSION]
 	</floater.string>
 	<floater.string name="AboutPosition">
-		Tu sei  [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1] in [REGION] che si trova a &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; ([HOSTIP])
+		Tu sei  [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] in [REGION] che si trova a &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; ([HOSTIP])
 [SERVER_VERSION]
 [SERVER_RELEASE_NOTES_URL]
 	</floater.string>
diff --git a/indra/newview/skins/default/xui/ja/floater_about.xml b/indra/newview/skins/default/xui/ja/floater_about.xml
index 6d5df7564521497710b87166d5e4922f0b123d49..eae52c98ec2375af9c3aecadfb7a9fb1b6a1c37d 100755
--- a/indra/newview/skins/default/xui/ja/floater_about.xml
+++ b/indra/newview/skins/default/xui/ja/floater_about.xml
@@ -8,7 +8,7 @@
 		コンパイラー [COMPILER] [COMPILER_VERSION] バージョン
 	</floater.string>
 	<floater.string name="AboutPosition">
-		あなたの現在地は、[POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1] の [REGION] です。位置は &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; です。([HOSTIP])
+		あなたの現在地は、[POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] の [REGION] です。位置は &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; です。([HOSTIP])
 [SERVER_VERSION]
 [SERVER_RELEASE_NOTES_URL]
 	</floater.string>
diff --git a/indra/newview/skins/default/xui/pl/floater_about.xml b/indra/newview/skins/default/xui/pl/floater_about.xml
index 409429ffaa64b2f5584ed937ebbce14fac9dc3fb..61a72ff27de35ec7a4870df323b5e882d4afaf6c 100755
--- a/indra/newview/skins/default/xui/pl/floater_about.xml
+++ b/indra/newview/skins/default/xui/pl/floater_about.xml
@@ -8,7 +8,7 @@
 		Buduj z [COMPILER] wersjÄ… [COMPILER_VERSION]
 	</floater.string>
 	<floater.string name="AboutPosition">
-		Położenie [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1] w [REGION] zlokalizowanym w &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; ([HOSTIP])
+		Położenie [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] w [REGION] zlokalizowanym w &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; ([HOSTIP])
 [SERVER_VERSION]
 [SERVER_RELEASE_NOTES_URL]
 	</floater.string>
diff --git a/indra/newview/skins/default/xui/pt/floater_about.xml b/indra/newview/skins/default/xui/pt/floater_about.xml
index 299f88b22a14211393417e5d8e0520cae587d399..d08926634208f1442c31cf58c7d69f83f8993413 100755
--- a/indra/newview/skins/default/xui/pt/floater_about.xml
+++ b/indra/newview/skins/default/xui/pt/floater_about.xml
@@ -7,7 +7,7 @@
 		Construído com [COMPILER] versão [COMPILER_VERSION]
 	</floater.string>
 	<floater.string name="AboutPosition">
-		Você está em [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1] em [REGION] localizado em [HOSTNAME]&lt;/nolink&gt;([HOSTIP])
+		Você está em [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] em [REGION] localizado em [HOSTNAME]&lt;/nolink&gt;([HOSTIP])
 [SERVER_VERSION]
 [SERVER_RELEASE_NOTES_URL]
 	</floater.string>
diff --git a/indra/newview/skins/default/xui/ru/floater_about.xml b/indra/newview/skins/default/xui/ru/floater_about.xml
index bb6266ac9ae4196f593c2cef75cd74262fbd3f83..2b2b3cf453385abf54408b2fb5c3df30fe525ab2 100755
--- a/indra/newview/skins/default/xui/ru/floater_about.xml
+++ b/indra/newview/skins/default/xui/ru/floater_about.xml
@@ -8,7 +8,7 @@
 		Использован компилятор [COMPILER], версия [COMPILER_VERSION]
 	</floater.string>
 	<floater.string name="AboutPosition">
-		Вы в точке [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1] в регионе «[REGION]», расположенном на &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; ([HOSTIP])
+		Вы в точке [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] в регионе «[REGION]», расположенном на &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; ([HOSTIP])
 [SERVER_VERSION]
 [SERVER_RELEASE_NOTES_URL]
 	</floater.string>
diff --git a/indra/newview/skins/default/xui/tr/floater_about.xml b/indra/newview/skins/default/xui/tr/floater_about.xml
index 9cc9c7a2201ae01263d0ecd8a0ac53c07ce30a6e..4dcf6200c6377d7606f117da9062ee0a6449efed 100755
--- a/indra/newview/skins/default/xui/tr/floater_about.xml
+++ b/indra/newview/skins/default/xui/tr/floater_about.xml
@@ -8,7 +8,7 @@
 		[COMPILER] [COMPILER_VERSION] sürümü ile oluşturuldu
 	</floater.string>
 	<floater.string name="AboutPosition">
-		&lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; ([HOSTIP]) üzerinde bulunan [REGION] içerisinde [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1] konumundasınız
+		&lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; ([HOSTIP]) üzerinde bulunan [REGION] içerisinde [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] konumundasınız
 [SERVER_VERSION]
 [SERVER_RELEASE_NOTES_URL]
 	</floater.string>
diff --git a/indra/newview/skins/default/xui/zh/floater_about.xml b/indra/newview/skins/default/xui/zh/floater_about.xml
index 643881e416e06e5fa9924085ccb4e01f152fc5e6..1193243c7ecbfeb4776c3099ff0a5ee74e1709f7 100755
--- a/indra/newview/skins/default/xui/zh/floater_about.xml
+++ b/indra/newview/skins/default/xui/zh/floater_about.xml
@@ -8,7 +8,7 @@
 		以 [COMPILER_VERSION] 版本 [COMPILER] 建置
 	</floater.string>
 	<floater.string name="AboutPosition">
-		你的方位是 [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1],地區名:[REGION],主機:&lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; ([HOSTIP])
+		你的方位是 [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1],地區名:[REGION],主機:&lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; ([HOSTIP])
 [SERVER_VERSION]
 [SERVER_RELEASE_NOTES_URL]
 	</floater.string>
diff --git a/indra/newview/tests/llagentaccess_test.cpp b/indra/newview/tests/llagentaccess_test.cpp
index 3ba25f3c10963b160bfd1dc6a824b341d39cc1d2..a40b5c9a3d1836691d7ca0f2adeb1e77ad58158e 100755
--- a/indra/newview/tests/llagentaccess_test.cpp
+++ b/indra/newview/tests/llagentaccess_test.cpp
@@ -49,10 +49,10 @@ LLControlGroup::~LLControlGroup()
 }
 
 // Implementation of just the LLControlGroup methods we requre
-BOOL LLControlGroup::declareU32(const std::string& name, U32 initial_val, const std::string& comment, BOOL persist)
+LLControlVariable* LLControlGroup::declareU32(const std::string& name, U32 initial_val, const std::string& comment, LLControlVariable::ePersist persist)
 {
 	test_preferred_maturity = initial_val;
-	return true;
+	return NULL;
 }
 
 void LLControlGroup::setU32(const std::string& name, U32 val)
@@ -80,7 +80,7 @@ namespace tut
 	void agentaccess_object_t::test<1>()
 	{
 		LLControlGroup cgr("test");
-		cgr.declareU32("PreferredMaturity", SIM_ACCESS_PG, "declared_for_test", FALSE);
+		cgr.declareU32("PreferredMaturity", SIM_ACCESS_PG, "declared_for_test", LLControlVariable::PERSIST_NO);
 		LLAgentAccess aa(cgr);
 		
 		cgr.setU32("PreferredMaturity", SIM_ACCESS_PG);
@@ -109,7 +109,7 @@ namespace tut
 	void agentaccess_object_t::test<2>()
 	{
 		LLControlGroup cgr("test");
-		cgr.declareU32("PreferredMaturity", SIM_ACCESS_PG, "declared_for_test", FALSE);
+		cgr.declareU32("PreferredMaturity", SIM_ACCESS_PG, "declared_for_test", LLControlVariable::PERSIST_NO);
 		LLAgentAccess aa(cgr);
 		
 		// make sure default is PG
@@ -157,7 +157,7 @@ namespace tut
 	void agentaccess_object_t::test<3>()
 	{
 		LLControlGroup cgr("test");
-		cgr.declareU32("PreferredMaturity", SIM_ACCESS_PG, "declared_for_test", FALSE);
+		cgr.declareU32("PreferredMaturity", SIM_ACCESS_PG, "declared_for_test", LLControlVariable::PERSIST_NO);
 		LLAgentAccess aa(cgr);
 		
 #ifndef HACKED_GODLIKE_VIEWER
@@ -195,7 +195,7 @@ namespace tut
 	void agentaccess_object_t::test<4>()
 	{
 		LLControlGroup cgr("test");
-		cgr.declareU32("PreferredMaturity", SIM_ACCESS_PG, "declared_for_test", FALSE);
+		cgr.declareU32("PreferredMaturity", SIM_ACCESS_PG, "declared_for_test", LLControlVariable::PERSIST_NO);
 		LLAgentAccess aa(cgr);
 		
 #ifndef HACKED_GODLIKE_VIEWER
@@ -272,7 +272,7 @@ namespace tut
 	void agentaccess_object_t::test<5>()
 	{
 		LLControlGroup cgr("test");
-		cgr.declareU32("PreferredMaturity", SIM_ACCESS_PG, "declared_for_test", FALSE);
+		cgr.declareU32("PreferredMaturity", SIM_ACCESS_PG, "declared_for_test", LLControlVariable::PERSIST_NO);
 		LLAgentAccess aa(cgr);
 		
 		cgr.setU32("PreferredMaturity", SIM_ACCESS_ADULT);
diff --git a/indra/newview/tests/lllogininstance_test.cpp b/indra/newview/tests/lllogininstance_test.cpp
index f038112fd07ccf4ccea9bf7e6d78bea82450c343..272a46aa8dc66cb6bb2317e37823018ff80a1f12 100755
--- a/indra/newview/tests/lllogininstance_test.cpp
+++ b/indra/newview/tests/lllogininstance_test.cpp
@@ -175,8 +175,8 @@ F32 LLControlGroup::getF32(const std::string& name) { return 0.0f; }
 U32 LLControlGroup::saveToFile(const std::string& filename, BOOL nondefault_only) { return 1; }
 void LLControlGroup::setString(const std::string& name, const std::string& val) {}
 std::string LLControlGroup::getString(const std::string& name) { return "test_string"; }
-BOOL LLControlGroup::declareBOOL(const std::string& name, BOOL initial_val, const std::string& comment, BOOL persist) { return TRUE; }
-BOOL LLControlGroup::declareString(const std::string& name, const std::string &initial_val, const std::string& comment, BOOL persist) { return TRUE; }
+LLControlVariable* LLControlGroup::declareBOOL(const std::string& name, BOOL initial_val, const std::string& comment, LLControlVariable::ePersist persist) { return NULL; }
+LLControlVariable* LLControlGroup::declareString(const std::string& name, const std::string &initial_val, const std::string& comment, LLControlVariable::ePersist persist) { return NULL; }
 
 #include "lluicolortable.h"
 void LLUIColorTable::saveUserSettings(void)const {}
@@ -344,13 +344,13 @@ namespace tut
 			gTOSReplyPump = 0; // clear the callback.
 
 
-			gSavedSettings.declareBOOL("NoInventoryLibrary", FALSE, "", FALSE);
-			gSavedSettings.declareBOOL("ConnectAsGod", FALSE, "", FALSE);
-			gSavedSettings.declareBOOL("UseDebugMenus", FALSE, "", FALSE);
-			gSavedSettings.declareBOOL("ForceMandatoryUpdate", FALSE, "", FALSE);
-			gSavedSettings.declareString("ClientSettingsFile", "test_settings.xml", "", FALSE);
-			gSavedSettings.declareString("NextLoginLocation", "", "", FALSE);
-			gSavedSettings.declareBOOL("LoginLastLocation", FALSE, "", FALSE);
+			gSavedSettings.declareBOOL("NoInventoryLibrary", FALSE, "", LLControlVariable::PERSIST_NO);
+			gSavedSettings.declareBOOL("ConnectAsGod", FALSE, "", LLControlVariable::PERSIST_NO);
+			gSavedSettings.declareBOOL("UseDebugMenus", FALSE, "", LLControlVariable::PERSIST_NO);
+			gSavedSettings.declareBOOL("ForceMandatoryUpdate", FALSE, "", LLControlVariable::PERSIST_NO);
+			gSavedSettings.declareString("ClientSettingsFile", "test_settings.xml", "", LLControlVariable::PERSIST_NO);
+			gSavedSettings.declareString("NextLoginLocation", "", "", LLControlVariable::PERSIST_NO);
+			gSavedSettings.declareBOOL("LoginLastLocation", FALSE, "", LLControlVariable::PERSIST_NO);
 
 			LLSD authenticator = LLSD::emptyMap();
 			LLSD identifier = LLSD::emptyMap();
diff --git a/indra/newview/tests/llsecapi_test.cpp b/indra/newview/tests/llsecapi_test.cpp
index 703603e2dbff8911f91ad9bebff4ada5728149ee..d7e87ed52ea5dc0c1a8d9c9853a358774c1fd180 100755
--- a/indra/newview/tests/llsecapi_test.cpp
+++ b/indra/newview/tests/llsecapi_test.cpp
@@ -39,10 +39,10 @@
 LLControlGroup::LLControlGroup(const std::string& name)
 : LLInstanceTracker<LLControlGroup, std::string>(name) {}
 LLControlGroup::~LLControlGroup() {}
-BOOL LLControlGroup::declareString(const std::string& name,
+LLControlVariable* LLControlGroup::declareString(const std::string& name,
                                    const std::string& initial_val,
                                    const std::string& comment,
-                                   BOOL persist) {return TRUE;}
+                                   LLControlVariable::ePersist persist) {return NULL;}
 void LLControlGroup::setString(const std::string& name, const std::string& val){}
 std::string LLControlGroup::getString(const std::string& name)
 {
diff --git a/indra/newview/tests/llsechandler_basic_test.cpp b/indra/newview/tests/llsechandler_basic_test.cpp
index 02354009760348c40dd7bc1b294d250a9ed0a449..2a8dc153466a7ee12efe56f815d7f027c9774855 100755
--- a/indra/newview/tests/llsechandler_basic_test.cpp
+++ b/indra/newview/tests/llsechandler_basic_test.cpp
@@ -71,10 +71,10 @@ std::string gLastName;
 LLControlGroup::LLControlGroup(const std::string& name)
 : LLInstanceTracker<LLControlGroup, std::string>(name) {}
 LLControlGroup::~LLControlGroup() {}
-BOOL LLControlGroup::declareString(const std::string& name,
+LLControlVariable* LLControlGroup::declareString(const std::string& name,
                                    const std::string& initial_val,
                                    const std::string& comment,
-                                   BOOL persist) {return TRUE;}
+                                   LLControlVariable::ePersist persist) {return NULL;}
 void LLControlGroup::setString(const std::string& name, const std::string& val){}
 std::string LLControlGroup::getString(const std::string& name)
 {
diff --git a/indra/newview/tests/llslurl_test.cpp b/indra/newview/tests/llslurl_test.cpp
index 09343ef227b209efdc0ecc8ce7522dddc7dcd5f4..86229ad636b1b7ced88daed66d231177e6a23257 100755
--- a/indra/newview/tests/llslurl_test.cpp
+++ b/indra/newview/tests/llslurl_test.cpp
@@ -37,10 +37,10 @@
 LLControlGroup::LLControlGroup(const std::string& name)
 : LLInstanceTracker<LLControlGroup, std::string>(name) {}
 LLControlGroup::~LLControlGroup() {}
-BOOL LLControlGroup::declareString(const std::string& name,
+LLControlVariable* LLControlGroup::declareString(const std::string& name,
                                    const std::string& initial_val,
                                    const std::string& comment,
-                                   BOOL persist) {return TRUE;}
+                                   LLControlVariable::ePersist persist) {return NULL;}
 void LLControlGroup::setString(const std::string& name, const std::string& val){}
 
 std::string gCmdLineLoginURI;
diff --git a/indra/newview/tests/llviewerhelputil_test.cpp b/indra/newview/tests/llviewerhelputil_test.cpp
index 710881d81124587d8dcb5512a030732880b87c8b..f6456a28392b5af902743800117c0c60203f4127 100755
--- a/indra/newview/tests/llviewerhelputil_test.cpp
+++ b/indra/newview/tests/llviewerhelputil_test.cpp
@@ -49,10 +49,10 @@ static std::string gOS;
 LLControlGroup::LLControlGroup(const std::string& name)
 	: LLInstanceTracker<LLControlGroup, std::string>(name) {}
 LLControlGroup::~LLControlGroup() {}
-BOOL LLControlGroup::declareString(const std::string& name,
+LLControlVariable* LLControlGroup::declareString(const std::string& name,
 				   const std::string& initial_val,
 				   const std::string& comment,
-				   BOOL persist) {return TRUE;}
+				   LLControlVariable::ePersist persist) {return NULL;}
 void LLControlGroup::setString(const std::string& name, const std::string& val){}
 std::string LLControlGroup::getString(const std::string& name)
 {
diff --git a/indra/newview/tests/llviewernetwork_test.cpp b/indra/newview/tests/llviewernetwork_test.cpp
index a1e97ea17eac6641eb0788d97b0fa1a1aac1e595..06de1cbfa27a5d10bb826939824d8fe8cfba8d64 100755
--- a/indra/newview/tests/llviewernetwork_test.cpp
+++ b/indra/newview/tests/llviewernetwork_test.cpp
@@ -37,10 +37,10 @@
 LLControlGroup::LLControlGroup(const std::string& name)
 : LLInstanceTracker<LLControlGroup, std::string>(name) {}
 LLControlGroup::~LLControlGroup() {}
-BOOL LLControlGroup::declareString(const std::string& name,
+LLControlVariable* LLControlGroup::declareString(const std::string& name,
                                    const std::string& initial_val,
                                    const std::string& comment,
-                                   BOOL persist) {return TRUE;}
+                                   LLControlVariable::ePersist persist) {return NULL;}
 void LLControlGroup::setString(const std::string& name, const std::string& val){}
 
 std::string gCmdLineLoginURI;
diff --git a/indra/newview/tests/llxmlrpclistener_test.cpp b/indra/newview/tests/llxmlrpclistener_test.cpp
index 711c2a3d51a908ba9a18316556c49f643d1c1960..20f913b67083be6aeef3635428f8dbb9b2a35d90 100755
--- a/indra/newview/tests/llxmlrpclistener_test.cpp
+++ b/indra/newview/tests/llxmlrpclistener_test.cpp
@@ -62,8 +62,8 @@ namespace tut
             // These variables are required by machinery used by
             // LLXMLRPCTransaction. The values reflect reality for this test
             // executable; hopefully these values are correct.
-            gSavedSettings.declareBOOL("BrowserProxyEnabled", FALSE, "", FALSE); // don't persist
-            gSavedSettings.declareBOOL("NoVerifySSLCert", TRUE, "", FALSE); // don't persist
+            gSavedSettings.declareBOOL("BrowserProxyEnabled", FALSE, "", LLControlVariable::PERSIST_NO); // don't persist
+            gSavedSettings.declareBOOL("NoVerifySSLCert", TRUE, "", LLControlVariable::PERSIST_NO); // don't persist
         }
 
         // LLEventPump listener signature
diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py
index 1429fe4c7aa1eb702139b88cf62df616dbd58362..b9da6c92807c270dbcce65fd65e06bc3119ac23f 100755
--- a/indra/newview/viewer_manifest.py
+++ b/indra/newview/viewer_manifest.py
@@ -71,13 +71,13 @@ def construct(self):
                 # include the entire shaders directory recursively
                 self.path("shaders")
                 # include the extracted list of contributors
-                contributor_names = self.extract_names("../../doc/contributions.txt")
-                self.put_in_file(contributor_names, "contributors.txt")
-                self.file_list.append(["../../doc/contributions.txt",self.dst_path_of("contributors.txt")])
+                contributions_path = "../../doc/contributions.txt"
+                contributor_names = self.extract_names(contributions_path)
+                self.put_in_file(contributor_names, "contributors.txt", src=contributions_path)
                 # include the extracted list of translators
-                translator_names = self.extract_names("../../doc/translations.txt")
-                self.put_in_file(translator_names, "translators.txt")
-                self.file_list.append(["../../doc/translations.txt",self.dst_path_of("translators.txt")])
+                translations_path = "../../doc/translations.txt"
+                translator_names = self.extract_names(translations_path)
+                self.put_in_file(translator_names, "translators.txt", src=translations_path)
                 # include the list of Lindens (if any)
                 #   see https://wiki.lindenlab.com/wiki/Generated_Linden_Credits
                 linden_names_path = os.getenv("LINDEN_CREDITS")
@@ -91,10 +91,9 @@ def construct(self):
                     else:
                          # all names should be one line, but the join below also converts to a string
                         linden_names = ', '.join(linden_file.readlines())
-                        self.put_in_file(linden_names, "lindens.txt")
+                        self.put_in_file(linden_names, "lindens.txt", src=linden_names_path)
                         linden_file.close()
                         print "Linden names extracted from '%s'" % linden_names_path
-                        self.file_list.append([linden_names_path,self.dst_path_of("lindens.txt")])
 
                 # ... and the entire windlight directory
                 self.path("windlight")
@@ -113,12 +112,18 @@ def construct(self):
                     # no sourceid, no settings_install.xml file
                     pass
                 else:
-                    # Single-entry subset of the LLSD content of settings.xml
-                    content = dict(sourceid=dict(Comment='Identify referring agency to Linden web servers',
-                                                 Persist=1,
-                                                 Type='String',
-                                                 Value=sourceid))
-                    self.put_in_file(llsd.format_pretty_xml(content), "settings_install.xml")
+                    if sourceid:
+                        # Single-entry subset of the LLSD content of settings.xml
+                        content = dict(sourceid=dict(Comment='Identify referring agency to Linden web servers',
+                                                     Persist=1,
+                                                     Type='String',
+                                                     Value=sourceid))
+                        # put_in_file(src=) need not be an actual pathname; it
+                        # only needs to be non-empty
+                        settings_install = self.put_in_file(llsd.format_pretty_xml(content),
+                                                            "settings_install.xml",
+                                                            src="environment")
+                        print "Put sourceid '%s' in %s" % (sourceid, settings_install)
 
                 self.end_prefix("app_settings")
 
@@ -193,7 +198,7 @@ def channel_lowerword(self):
     def app_name(self):
         app_suffix='Test'
         channel_type=self.channel_lowerword()
-        if channel_type == 'release' :
+        if channel_type.startswith('release') :
             app_suffix='Viewer'
         elif re.match('^(beta|project).*',channel_type) :
             app_suffix=self.channel_unique()
@@ -203,8 +208,8 @@ def icon_path(self):
         icon_path="icons/"
         channel_type=self.channel_lowerword()
         print "Icon channel type '%s'" % channel_type
-        if channel_type == 'release' :
-            icon_path += channel_type
+        if channel_type.startswith('release') :
+            icon_path += 'release'
         elif re.match('^beta.*',channel_type) :
             icon_path += 'beta'
         elif re.match('^project.*',channel_type) :
@@ -265,7 +270,7 @@ class WindowsManifest(ViewerManifest):
     def final_exe(self):
         app_suffix="Test"
         channel_type=self.channel_lowerword()
-        if channel_type == 'release' :
+        if channel_type.startswith('release') :
             app_suffix=''
         elif re.match('^(beta|project).*',channel_type) :
             app_suffix=''.join(self.channel_unique().split())