diff --git a/.hgtags b/.hgtags
index 0519522468c3b813b058c32bcf3bc39d4bb50a67..a81e5fa806f5732389fe34937e0cdb1341b9a558 100755
--- a/.hgtags
+++ b/.hgtags
@@ -536,3 +536,4 @@ ad0e15543836d64d6399d28b32852510435e344a 5.1.0-release
 2eb917875efdfe920680b9049302d0f03721245d 5.1.2-release
 7c00e5b6cb3d95712e9d8e29277c805bca2bda90 5.1.3-release
 7b6b020fd5ad9a8dc3670c5c92d1ca92e55fc485 5.1.4-release
+2ea47f358b171178eb9a95503a1670d519c2886f 5.1.5-release
diff --git a/autobuild.xml b/autobuild.xml
index cea8b51ec5e4c6c8642e72ecf23da0968d20394e..7e49b9f4586efc18830d3ed967ba581b40c6c412 100644
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -1692,11 +1692,11 @@
           <key>darwin</key>
           <map>
             <key>archive</key>
-            <map>
+            <map>              
               <key>hash</key>
-              <string>7b769c4284bdbd5fce536395d1eab695</string>
+              <string>3855bd40f950e3c22739ae8f3ee2afc9</string>
               <key>url</key>
-              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/4054/11304/kdu-7.9.1.504041-darwin-504041.tar.bz2</string>
+              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/15258/98444/kdu-7.10.4.513518-darwin-513518.tar.bz2</string>
             </map>
             <key>name</key>
             <string>darwin</string>
@@ -1705,10 +1705,10 @@
           <map>
             <key>archive</key>
             <map>
-              <key>hash</key>
-              <string>a48db5cf79a4631090bfc968572d9953</string>
+              <key>hash</key>              
+              <string>d1521becaf21bf7233173722af63f57d</string>
               <key>url</key>
-              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/4052/11292/kdu-7.9.1.504041-darwin64-504041.tar.bz2</string>
+              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/15257/98440/kdu-7.10.4.513518-darwin64-513518.tar.bz2</string>              
             </map>
             <key>name</key>
             <string>darwin64</string>
@@ -1717,10 +1717,10 @@
           <map>
             <key>archive</key>
             <map>
-              <key>hash</key>
-              <string>ed952c0cb86329e63a8db190953962d8</string>
+              <key>hash</key>              
+              <string>43d7a6a69a54534a736f132e9c81795b</string>
               <key>url</key>
-              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/kdu_3p-update-kdu/rev/296932/arch/Linux/installer/kdu-7.2.296932-linux-296932.tar.bz2</string>
+              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/15255/98451/kdu-7.10.4.513518-linux-513518.tar.bz2</string>              
             </map>
             <key>name</key>
             <string>linux</string>
@@ -1730,9 +1730,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>99b0b22f87cebdd02c4cc954a7b3b465</string>
+              <string>a705a665810a71e7b0114a97ae9a2224</string>
               <key>url</key>
-              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/4053/11298/kdu-7.9.1.504041-linux64-504041.tar.bz2</string>
+              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/15256/98457/kdu-7.10.4.513518-linux64-513518.tar.bz2</string>
             </map>
             <key>name</key>
             <string>linux64</string>
@@ -1742,9 +1742,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>f3ff5982b3b5f02738044432dd77a2c1</string>
+              <string>0e5b37a03a3f873d15142473b193ec5f</string>
               <key>url</key>
-              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/4055/11310/kdu-7.9.1.504041-windows-504041.tar.bz2</string>
+              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/15259/98463/kdu-7.10.4.513518-windows-513518.tar.bz2</string>
             </map>
             <key>name</key>
             <string>windows</string>
@@ -1752,18 +1752,18 @@
           <key>windows64</key>
           <map>
             <key>archive</key>
-            <map>
+            <map>              
               <key>hash</key>
-              <string>3010fa35f412b36296342b07de06f1ca</string>
+              <string>da3b1ea90797b189d80ab5d50fdf05d4</string>
               <key>url</key>
-              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/4056/11316/kdu-7.9.1.504041-windows64-504041.tar.bz2</string>
+              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/15260/98469/kdu-7.10.4.513518-windows64-513518.tar.bz2</string>              
             </map>
             <key>name</key>
             <string>windows64</string>
           </map>
         </map>
         <key>version</key>
-        <string>7.9.1.504041</string>
+        <string>7.A.4.513518</string>
       </map>
       <key>libhunspell</key>
       <map>
diff --git a/doc/contributions.txt b/doc/contributions.txt
index e67df2453e678e5e3f5dc18a8ca700fd14ff36f6..90bbb1c2c6b60944192ab93ed97d127ea7c8620d 100755
--- a/doc/contributions.txt
+++ b/doc/contributions.txt
@@ -218,6 +218,7 @@ Ansariel Hiller
 	MAINT-7899
 	STORM-2105
 	STORM-2151
+	MAINT-6917
 	MAINT-8085
 Aralara Rajal
 Arare Chantilly
diff --git a/indra/llkdu/tests/llimagej2ckdu_test.cpp b/indra/llkdu/tests/llimagej2ckdu_test.cpp
index e386a9f71b4ac5bc53144f944a10ada914f839fb..79ed566d00ddaa0466e6e5a93169f610d64c8e55 100644
--- a/indra/llkdu/tests/llimagej2ckdu_test.cpp
+++ b/indra/llkdu/tests/llimagej2ckdu_test.cpp
@@ -119,6 +119,10 @@ bool LLKDUMemIn::get(int, kdu_core::kdu_line_buf&, int) { return false; }
 
 // Stub Kakadu Library calls
 // they're all namespaced now
+namespace kdu_core_local
+{
+    class kd_coremem;
+}
 namespace kdu_core {
 kdu_tile_comp kdu_tile::access_component(int ) { kdu_tile_comp a; return a; }
 kdu_block_encoder::kdu_block_encoder() { }
@@ -140,7 +144,8 @@ void kdu_resolution::get_dims(kdu_dims& ) { }
 int kdu_resolution::which() { return 0; }
 int kdu_resolution::get_valid_band_indices(int &) { return 1; }
 kdu_synthesis::kdu_synthesis(kdu_resolution, kdu_sample_allocator*, bool, float, kdu_thread_env*, kdu_thread_queue*) { }
-kdu_params::kdu_params(const char*, bool, bool, bool, bool, bool) { }
+//kdu_params::kdu_params(const char*, bool, bool, bool, bool, bool) { }
+kdu_params::kdu_params(const char*, bool, bool, bool, bool, bool, kd_core_local::kd_coremem*) {}
 kdu_params::~kdu_params() { }
 void kdu_params::set(const char* , int , int , bool ) { }
 void kdu_params::set(const char* , int , int , int ) { }
@@ -164,39 +169,61 @@ void kdu_codestream::destroy() { }
 void kdu_codestream::collect_timing_stats(int ) { }
 void kdu_codestream::set_max_bytes(kdu_long, bool, bool ) { }
 void kdu_codestream::get_valid_tiles(kdu_dims& ) { }
-void kdu_codestream::create(kdu_compressed_source*, kdu_thread_env*) { }
+void kdu_codestream::create(
+    siz_params*,
+    kdu_compressed_target*,
+    kdu_dims*,
+    int,
+    kdu_long,
+    kdu_thread_env*,
+    kdu_membroker*) {}
+void kdu_codestream::create(kdu_compressed_source *,kdu_thread_env *, kdu_membroker *) {}
 void kdu_codestream::apply_input_restrictions(int, int, int, int, kdu_dims const *, kdu_component_access_mode, kdu_thread_env *, kdu_quality_limiter const *) {}
 void kdu_codestream::get_subsampling(int , kdu_coords&, bool ) { }
 void kdu_codestream::flush(kdu_long *, int, kdu_uint16 *, bool, bool, double, kdu_thread_env*, int) { }
 void kdu_codestream::set_resilient(bool ) { }
 int kdu_codestream::get_num_components(bool ) { return 0; }
 kdu_long kdu_codestream::get_total_bytes(bool ) { return 0; }
-kdu_long kdu_codestream::get_compressed_data_memory(bool ) {return 0; }
+kdu_long kdu_codestream::get_compressed_data_memory(bool ) const {return 0; }
 void kdu_codestream::share_buffering(kdu_codestream ) { }
 int kdu_codestream::get_num_tparts() { return 0; }
 int kdu_codestream::trans_out(kdu_long, kdu_long*, int, bool, kdu_thread_env* ) { return 0; }
 bool kdu_codestream::ready_for_flush(kdu_thread_env*) { return false; }
 siz_params* kdu_codestream::access_siz() { return NULL; }
 kdu_tile kdu_codestream::open_tile(kdu_coords , kdu_thread_env* ) { kdu_tile a; return a; }
-kdu_codestream_comment kdu_codestream::add_comment() { kdu_codestream_comment a; return a; }
+kdu_codestream_comment kdu_codestream::add_comment(kdu_thread_env*) { kdu_codestream_comment a; return a; }
 void kdu_subband::close_block(kdu_block*, kdu_thread_env*) { }
 void kdu_subband::get_valid_blocks(kdu_dims &indices) const { }
 kdu_block * kdu_subband::open_block(kdu_coords, int *, kdu_thread_env *, int, bool) { return NULL; }
 bool kdu_codestream_comment::put_text(const char*) { return false; }
 void kdu_customize_warnings(kdu_message*) { }
 void kdu_customize_errors(kdu_message*) { }
-kdu_long kdu_multi_analysis::create(kdu_codestream, kdu_tile, kdu_thread_env *,kdu_thread_queue *, int, kdu_roi_image *, int, kdu_sample_allocator *, kdu_push_pull_params const *) { return kdu_long(0); }
+kdu_long kdu_multi_analysis::create(
+    kdu_codestream,
+    kdu_tile,
+    kdu_thread_env*,
+    kdu_thread_queue*,
+    int,
+    kdu_roi_image*,
+    int,
+    kdu_sample_allocator*,
+    const kdu_push_pull_params*,
+    kdu_membroker*) { return kdu_long(0); }
 void kdu_multi_analysis::destroy(kdu_thread_env *) {}
-siz_params::siz_params() : kdu_params(NULL, false, false, false, false, false) { }
+siz_params::siz_params(kd_core_local::kd_coremem*) : kdu_params(NULL, false, false, false, false, false) { }
 siz_params::~siz_params() {}
 void siz_params::finalize(bool ) { }
 void siz_params::copy_with_xforms(kdu_params*, int, int, bool, bool, bool) { }
 int siz_params::write_marker_segment(kdu_output*, kdu_params*, int) { return 0; }
 bool siz_params::check_marker_segment(kdu_uint16, int, kdu_byte a[], int&) { return false; }
 bool siz_params::read_marker_segment(kdu_uint16, int, kdu_byte a[], int) { return false; }
-
-kdu_decoder::kdu_decoder(kdu_subband , kdu_sample_allocator*, bool , float, int, kdu_thread_env*, kdu_thread_queue*, int) { }
-void kdu_codestream::create(siz_params*, kdu_compressed_target*, kdu_dims*, int, kdu_long, kdu_thread_env* ) { }
+kdu_decoder::kdu_decoder(
+    kdu_subband subband,
+    kdu_sample_allocator*,
+    bool, float, int,
+    kdu_thread_env*,
+    kdu_thread_queue*,
+    int, float*) {}
 kdu_sample_allocator::~kdu_sample_allocator() {}
 void kdu_sample_allocator::do_finalize(kdu_codestream) {}
 void (*kdu_convert_ycc_to_rgb_rev16)(kdu_int16*,kdu_int16*,kdu_int16*,int);
@@ -205,6 +232,8 @@ void (*kdu_convert_ycc_to_rgb_rev32)(kdu_int32*,kdu_int32*,kdu_int32*,int);
 void (*kdu_convert_ycc_to_rgb_irrev32)(float*,float*,float*,int);
 bool kdu_core_sample_alignment_checker(int, int, int, int, bool, bool) { return false; }
 void kdu_pull_ifc::destroy() {}
+void kdu_sample_allocator::advance_pre_frag() {}
+void kdu_params::operator delete(void *) {}
 } // namespace kdu_core
 
 // -------------------------------------------------------------------------------------------
diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp
index 5aa1f6b44bee9e655c833623d777e4ae9840cd0c..8f08394ce939226537b04c017eb50b1bcaf5b782 100644
--- a/indra/llmath/llvolume.cpp
+++ b/indra/llmath/llvolume.cpp
@@ -544,7 +544,7 @@ void LLProfile::genNGon(const LLProfileParams& params, S32 sides, F32 offset, F3
 {
 	// Generate an n-sided "circular" path.
 	// 0 is (1,0), and we go counter-clockwise along a circular path from there.
-	const F32 tableScale[] = { 1, 1, 1, 0.5f, 0.707107f, 0.53f, 0.525f, 0.5f };
+	static const F32 tableScale[] = { 1, 1, 1, 0.5f, 0.707107f, 0.53f, 0.525f, 0.5f };
 	F32 scale = 0.5f;
 	F32 t, t_step, t_first, t_fraction, ang, ang_step;
 	LLVector4a pt1,pt2;
@@ -1303,7 +1303,7 @@ S32 LLPath::getNumNGonPoints(const LLPathParams& params, S32 sides, F32 startOff
 void LLPath::genNGon(const LLPathParams& params, S32 sides, F32 startOff, F32 end_scale, F32 twist_scale)
 {
 	// Generates a circular path, starting at (1, 0, 0), counterclockwise along the xz plane.
-	const F32 tableScale[] = { 1, 1, 1, 0.5f, 0.707107f, 0.53f, 0.525f, 0.5f };
+	static const F32 tableScale[] = { 1, 1, 1, 0.5f, 0.707107f, 0.53f, 0.525f, 0.5f };
 
 	F32 revolutions = params.getRevolutions();
 	F32 skew		= params.getSkew();
@@ -1601,7 +1601,8 @@ BOOL LLPath::generate(const LLPathParams& params, F32 detail, S32 split,
 			if (is_sculpted)
 				sides = llmax(sculpt_size, 1);
 			
-			genNGon(params, sides);
+			if (0 < sides)
+				genNGon(params, sides);
 		}
 		break;
 
diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h
index e92cf0b21f28ba6c8da426252d9c90b815385761..d518bcf3efe830058f340cf7016c1946e00156c1 100644
--- a/indra/llmath/llvolume.h
+++ b/indra/llmath/llvolume.h
@@ -1094,7 +1094,7 @@ class LLVolume : public LLRefCount
 	F32 mSurfaceArea; //unscaled surface area
 	BOOL mIsMeshAssetLoaded;
 	
-	LLVolumeParams mParams;
+	const LLVolumeParams mParams;
 	LLPath *mPathp;
 	LLProfile *mProfilep;
 	LLAlignedArray<LLVector4a,64> mMesh;
diff --git a/indra/llprimitive/llmaterialid.cpp b/indra/llprimitive/llmaterialid.cpp
index 820f62c43ce04941c51f5ab28b208d99f1fcdec0..f88a607c4f9b167fd73f022166351f2f905e5dbd 100644
--- a/indra/llprimitive/llmaterialid.cpp
+++ b/indra/llprimitive/llmaterialid.cpp
@@ -61,6 +61,11 @@ LLMaterialID::LLMaterialID(const LLMaterialID& pOtherMaterialID)
 	copyFromOtherMaterialID(pOtherMaterialID);
 }
 
+LLMaterialID::LLMaterialID(const LLUUID& lluid)
+{
+	set(lluid.mData);
+}
+
 LLMaterialID::~LLMaterialID()
 {
 }
diff --git a/indra/llprimitive/llmaterialid.h b/indra/llprimitive/llmaterialid.h
index b4c82d3b7b7fc0c21d0a8f9d1f265539c7852877..ee663f8f99f41c6926102f0cb14bff7220ec098d 100644
--- a/indra/llprimitive/llmaterialid.h
+++ b/indra/llprimitive/llmaterialid.h
@@ -40,6 +40,7 @@ class LLMaterialID
 	LLMaterialID(const LLSD::Binary& pMaterialID);
 	LLMaterialID(const void* pMemory);
 	LLMaterialID(const LLMaterialID& pOtherMaterialID);
+	LLMaterialID(const LLUUID& lluid);
 	~LLMaterialID();
 
 	bool          operator == (const LLMaterialID& pOtherMaterialID) const;
diff --git a/indra/llprimitive/llprimitive.cpp b/indra/llprimitive/llprimitive.cpp
index c847cf653f46c7009d262132efa3837577619cb4..c69c059880cb2b4534c26d9d2aae95b2f87eed8b 100644
--- a/indra/llprimitive/llprimitive.cpp
+++ b/indra/llprimitive/llprimitive.cpp
@@ -732,6 +732,16 @@ S32	face_index_from_id(LLFaceID face_ID, const std::vector<LLProfile::Face>& fac
 
 BOOL LLPrimitive::setVolume(const LLVolumeParams &volume_params, const S32 detail, bool unique_volume)
 {
+	if (NO_LOD == detail)
+	{
+		// build the new object
+		setChanged(GEOMETRY);
+		sVolumeManager->unrefVolume(mVolumep);
+		mVolumep = new LLVolume(volume_params, 1, TRUE, TRUE);
+		setNumTEs(mVolumep->getNumFaces());
+		return FALSE;
+	}
+
 	LLVolume *volumep;
 	if (unique_volume)
 	{
diff --git a/indra/llprimitive/llprimitive.h b/indra/llprimitive/llprimitive.h
index 9216c0422968692cd61af6f6a1b812792eb521b2..c138c2ac2b0552037e7ee1380db052d7f9856245 100644
--- a/indra/llprimitive/llprimitive.h
+++ b/indra/llprimitive/llprimitive.h
@@ -511,6 +511,11 @@ class LLPrimitive : public LLXform
 
 public:
 	static LLVolumeMgr* sVolumeManager;
+
+	enum
+	{
+		NO_LOD = -1
+	};
 };
 
 inline BOOL LLPrimitive::isAvatar() const
diff --git a/indra/llrender/CMakeLists.txt b/indra/llrender/CMakeLists.txt
index 331f988382a3476edb77981d890c20dbb97b1279..07a0d8c402d0906338d9ee87dfc23974211dae83 100644
--- a/indra/llrender/CMakeLists.txt
+++ b/indra/llrender/CMakeLists.txt
@@ -51,6 +51,7 @@ set(llrender_SOURCE_FILES
     lltexture.cpp
     lluiimage.cpp
     llvertexbuffer.cpp
+    llglcommonfunc.cpp
     )
     
 set(llrender_HEADER_FILES
@@ -78,6 +79,7 @@ set(llrender_HEADER_FILES
     lltexture.h
     lluiimage.h
     llvertexbuffer.h
+    llglcommonfunc.h
     )
 
 set_source_files_properties(${llrender_HEADER_FILES}
diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h
index aa98b3f6bc635992f59132175486c58b59506bec..4c4302d05ba3e101c2cc6081ebe69b6fc428648a 100644
--- a/indra/llrender/llgl.h
+++ b/indra/llrender/llgl.h
@@ -256,6 +256,9 @@ void clear_glerror();
 	if the existing GL state does not match the expected GL state.
 
 */
+
+#include "boost/function.hpp"
+
 class LLGLState
 {
 public:
@@ -297,6 +300,20 @@ class LLGLEnableAlphaReject : public LLGLState
 	LLGLEnableAlphaReject(bool enable);
 };
 
+// Enable with functor
+class LLGLEnableFunc : LLGLState
+{
+public:
+	LLGLEnableFunc(LLGLenum state, bool enable, boost::function<void()> func)
+		: LLGLState(state, enable)
+	{
+		if (enable)
+		{
+			func();
+		}
+	}
+};
+
 /// TODO: Being deprecated.
 class LLGLEnable : public LLGLState
 {
diff --git a/indra/llrender/llglcommonfunc.cpp b/indra/llrender/llglcommonfunc.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e9ec28927fad6dc3ffed63df355c940f5b23d8cc
--- /dev/null
+++ b/indra/llrender/llglcommonfunc.cpp
@@ -0,0 +1,37 @@
+/**
+* @file llglcommonfunc.cpp
+* @brief Implementation of the LLGLCommonFunc.
+*
+* $LicenseInfo:firstyear=2001&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2010, Linden Research, Inc.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+* $/LicenseInfo$
+*/
+
+#include "llglheaders.h"
+#include "llglcommonfunc.h"
+
+namespace LLGLCommonFunc 
+{
+	void selected_stencil_test()
+	{
+		glStencilFunc(GL_ALWAYS, 2, 0xffff);
+		glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
+	}
+}
diff --git a/indra/llrender/llglcommonfunc.h b/indra/llrender/llglcommonfunc.h
new file mode 100644
index 0000000000000000000000000000000000000000..f1f8ff7bc40300c9ec33f3d106bdb2a98dc96ac1
--- /dev/null
+++ b/indra/llrender/llglcommonfunc.h
@@ -0,0 +1,30 @@
+/**
+* @file llphoenixfunc.h
+* @brief File include common opengl code snippets
+*
+* $LicenseInfo:firstyear=2003&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2010, Linden Research, Inc.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+* $/LicenseInfo$
+*/
+
+namespace LLGLCommonFunc
+{
+	void selected_stencil_test();
+}
diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp
index 970502f2d6f9f39060b9499f2d433051adbf6e22..4702042ab9e9fa95751f4cbada914c69b35d64ff 100644
--- a/indra/llrender/llglslshader.cpp
+++ b/indra/llrender/llglslshader.cpp
@@ -537,7 +537,11 @@ BOOL LLGLSLShader::mapAttributes(const std::vector<LLStaticHashedString> * attri
 
     mAttribute.clear();
     U32 numAttributes = (attributes == NULL) ? 0 : attributes->size();
+#if LL_RELEASE_WITH_DEBUG_INFO
+    mAttribute.resize(LLShaderMgr::instance()->mReservedAttribs.size() + numAttributes, { -1, NULL });
+#else
     mAttribute.resize(LLShaderMgr::instance()->mReservedAttribs.size() + numAttributes, -1);
+#endif
     
     if (res)
     { //read back channel locations
@@ -551,7 +555,11 @@ BOOL LLGLSLShader::mapAttributes(const std::vector<LLStaticHashedString> * attri
             S32 index = glGetAttribLocationARB(mProgramObject, (const GLcharARB *)name);
             if (index != -1)
             {
+#if LL_RELEASE_WITH_DEBUG_INFO
+                mAttribute[i] = { index, name };
+#else
                 mAttribute[i] = index;
+#endif
                 mAttributeMask |= 1 << i;
                 LL_DEBUGS("ShaderLoading") << "Attribute " << name << " assigned to channel " << index << LL_ENDL;
             }
@@ -744,24 +752,25 @@ BOOL LLGLSLShader::mapUniforms(const vector<LLStaticHashedString> * uniforms)
 	, even if the "diffuseMap" will be appear and use first in shader code.
 
 	As example where this situation appear see: "Deferred Material Shader 28/29/30/31"
-	And tickets: MAINT-4165, MAINT-4839, MAINT-3568
+	And tickets: MAINT-4165, MAINT-4839, MAINT-3568, MAINT-6437
 	*/
 
 
 	S32 diffuseMap = glGetUniformLocationARB(mProgramObject, "diffuseMap");
+	S32 specularMap = glGetUniformLocationARB(mProgramObject, "specularMap");
 	S32 bumpMap = glGetUniformLocationARB(mProgramObject, "bumpMap");
 	S32 environmentMap = glGetUniformLocationARB(mProgramObject, "environmentMap");
 
 	std::set<S32> skip_index;
 
-	if (-1 != diffuseMap && (-1 != bumpMap || -1 != environmentMap))
+	if (-1 != diffuseMap && (-1 != specularMap || -1 != bumpMap || -1 != environmentMap))
 	{
 		GLenum type;
 		GLsizei length;
 		GLint size = -1;
 		char name[1024];
 
-		diffuseMap = bumpMap = environmentMap = -1;
+		diffuseMap = specularMap = bumpMap = environmentMap = -1;
 
 		for (S32 i = 0; i < activeCount; i++)
 		{
@@ -775,6 +784,18 @@ BOOL LLGLSLShader::mapUniforms(const vector<LLStaticHashedString> * uniforms)
 				continue;
 			}
 
+			if (-1 == specularMap && std::string(name) == "specularMap")
+			{
+				specularMap = i;
+				continue;
+			}
+
+			if (-1 == specularMap && std::string(name) == "specularMap")
+			{
+				specularMap = i;
+				continue;
+			}
+
 			if (-1 == bumpMap && std::string(name) == "bumpMap")
 			{
 				bumpMap = i;
@@ -788,34 +809,29 @@ BOOL LLGLSLShader::mapUniforms(const vector<LLStaticHashedString> * uniforms)
 			}
 		}
 
+		bool specularDiff = specularMap < diffuseMap && -1 != specularMap;
 		bool bumpLessDiff = bumpMap < diffuseMap && -1 != bumpMap;
 		bool envLessDiff = environmentMap < diffuseMap && -1 != environmentMap;
 
-		if (bumpLessDiff && envLessDiff)
+		if (specularDiff || bumpLessDiff || envLessDiff)
 		{
 			mapUniform(diffuseMap, uniforms);
-			mapUniform(bumpMap, uniforms);
-			mapUniform(environmentMap, uniforms);
-
 			skip_index.insert(diffuseMap);
-			skip_index.insert(bumpMap);
-			skip_index.insert(environmentMap);
-		}
-		else if (bumpLessDiff)
-		{
-			mapUniform(diffuseMap, uniforms);
-			mapUniform(bumpMap, uniforms);
 
-			skip_index.insert(diffuseMap);
-			skip_index.insert(bumpMap);
-		}
-		else if (envLessDiff)
-		{
-			mapUniform(diffuseMap, uniforms);
-			mapUniform(environmentMap, uniforms);
+			if (-1 != specularMap) {
+				mapUniform(specularMap, uniforms);
+				skip_index.insert(specularMap);
+			}
 
-			skip_index.insert(diffuseMap);
-			skip_index.insert(environmentMap);
+			if (-1 != bumpMap) {
+				mapUniform(bumpMap, uniforms);
+				skip_index.insert(bumpMap);
+			}
+
+			if (-1 != environmentMap) {
+				mapUniform(environmentMap, uniforms);
+				skip_index.insert(environmentMap);
+			}
 		}
 	}
 
diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h
index 6f10d122cb1d19ffcdf6664b38ba667218876b43..b56b91401323cde25fe0317dccce11bbda2e4182 100644
--- a/indra/llrender/llglslshader.h
+++ b/indra/llrender/llglslshader.h
@@ -167,7 +167,18 @@ class LLGLSLShader
 	U32 mLightHash;
 
 	GLhandleARB mProgramObject;
+#if LL_RELEASE_WITH_DEBUG_INFO
+	struct attr_name
+	{
+		GLint loc;
+		const char *name;
+		void operator = (GLint _loc) { loc = _loc; }
+		operator GLint () { return loc; }
+	};
+	std::vector<attr_name> mAttribute; //lookup table of attribute enum to attribute channel
+#else
 	std::vector<GLint> mAttribute; //lookup table of attribute enum to attribute channel
+#endif
 	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
 	LLStaticStringTable<GLint> mUniformMap; //lookup map of uniform name to uniform location
diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp
index a55ca5ed9c3cef21a19cb99c1f48329403029b43..e3e605d040aae7aa7ed8bc808520e5bfe3ede00c 100644
--- a/indra/llrender/llvertexbuffer.cpp
+++ b/indra/llrender/llvertexbuffer.cpp
@@ -327,7 +327,7 @@ void LLVBOPool::cleanup()
 
 
 //NOTE: each component must be AT LEAST 4 bytes in size to avoid a performance penalty on AMD hardware
-S32 LLVertexBuffer::sTypeSize[LLVertexBuffer::TYPE_MAX] =
+const S32 LLVertexBuffer::sTypeSize[LLVertexBuffer::TYPE_MAX] =
 {
 	sizeof(LLVector4), // TYPE_VERTEX,
 	sizeof(LLVector4), // TYPE_NORMAL,
@@ -344,7 +344,7 @@ S32 LLVertexBuffer::sTypeSize[LLVertexBuffer::TYPE_MAX] =
 	sizeof(LLVector4), // TYPE_TEXTURE_INDEX (actually exists as position.w), no extra data, but stride is 16 bytes
 };
 
-static std::string vb_type_name[] =
+static const std::string vb_type_name[] =
 {
 	"TYPE_VERTEX",
 	"TYPE_NORMAL",
@@ -363,7 +363,7 @@ static std::string vb_type_name[] =
 	"TYPE_INDEX",	
 };
 
-U32 LLVertexBuffer::sGLMode[LLRender::NUM_MODES] = 
+const U32 LLVertexBuffer::sGLMode[LLRender::NUM_MODES] =
 {
 	GL_TRIANGLES,
 	GL_TRIANGLE_STRIP,
@@ -512,7 +512,7 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask)
 				}
 			}
 		
-			U32 map_tc[] = 
+			static const U32 map_tc[] = 
 			{
 				MAP_TEXCOORD1,
 				MAP_TEXCOORD2,
@@ -1382,7 +1382,7 @@ void LLVertexBuffer::setupVertexArray()
 #endif
 	sGLRenderArray = mGLArray;
 
-	U32 attrib_size[] = 
+	static const U32 attrib_size[] = 
 	{
 		3, //TYPE_VERTEX,
 		3, //TYPE_NORMAL,
@@ -1399,7 +1399,7 @@ void LLVertexBuffer::setupVertexArray()
 		1, //TYPE_TEXTURE_INDEX
 	};
 
-	U32 attrib_type[] =
+	static const U32 attrib_type[] =
 	{
 		GL_FLOAT, //TYPE_VERTEX,
 		GL_FLOAT, //TYPE_NORMAL,
@@ -1416,7 +1416,7 @@ void LLVertexBuffer::setupVertexArray()
 		GL_UNSIGNED_INT, //TYPE_TEXTURE_INDEX
 	};
 
-	bool attrib_integer[] = 
+	static const bool attrib_integer[] =
 	{
 		false, //TYPE_VERTEX,
 		false, //TYPE_NORMAL,
@@ -1433,7 +1433,7 @@ void LLVertexBuffer::setupVertexArray()
 		true, //TYPE_TEXTURE_INDEX
 	};
 
-	U32 attrib_normalized[] =
+	static const U32 attrib_normalized[] =
 	{
 		GL_FALSE, //TYPE_VERTEX,
 		GL_FALSE, //TYPE_NORMAL,
diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h
index bd27296eb66b70401c14cad1587f287d6e2d5320..c89d7e39580712809e80f5e56e57c4594277af8a 100644
--- a/indra/llrender/llvertexbuffer.h
+++ b/indra/llrender/llvertexbuffer.h
@@ -341,8 +341,8 @@ class LLVertexBuffer : public LLRefCount, public LLTrace::MemTrackable<LLVertexB
 		
 	static bool sDisableVBOMapping; //disable glMapBufferARB
 	static bool sEnableVBOs;
-	static S32 sTypeSize[TYPE_MAX];
-	static U32 sGLMode[LLRender::NUM_MODES];
+	static const S32 sTypeSize[TYPE_MAX];
+	static const U32 sGLMode[LLRender::NUM_MODES];
 	static U32 sGLRenderBuffer;
 	static U32 sGLRenderArray;
 	static U32 sGLRenderIndices;
diff --git a/indra/llxml/llcontrol.h b/indra/llxml/llcontrol.h
index 77065dcf8d330fe2412c5ac0da02f1a6a01fa152..8136a3e88a0e48ea5a9025c6fc8e9b3cf76fc60c 100644
--- a/indra/llxml/llcontrol.h
+++ b/indra/llxml/llcontrol.h
@@ -357,7 +357,8 @@ class LLControlCache : public LLRefCount, public LLInstanceTracker<LLControlCach
 		mCachedValue = convert_from_llsd<T>(controlp->get(), mType, name);
 
 		// Add a listener to the controls signal...
-		mConnection = controlp->getSignal()->connect(
+		// NOTE: All listeners connected to 0 group, for guaranty that variable handlers (gSavedSettings) call last
+		mConnection = controlp->getSignal()->connect(0,
 			boost::bind(&LLControlCache<T>::handleValueChange, this, _2)
 			);
 		mType = controlp->type();
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index ff3ca3055e66ab449c1b0098ec365e7df866d80e..e9774f3bdf61713c61bf1f841472804cda54ff2a 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -531,6 +531,7 @@ set(viewer_SOURCE_FILES
     llscriptfloater.cpp
     llscrollingpanelparam.cpp
     llscrollingpanelparambase.cpp
+    llsculptidsize.cpp
     llsearchcombobox.cpp
     llsearchhistory.cpp
     llsecapi.cpp
@@ -1146,6 +1147,7 @@ set(viewer_HEADER_FILES
     llscriptruntimeperms.h
     llscrollingpanelparam.h
     llscrollingpanelparambase.h
+    llsculptidsize.h
     llsearchcombobox.h
     llsearchhistory.h
     llsecapi.h
diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt
index 220d8e0a4606aafd961b0d52fd07971ffcc980e2..8710cfdff2f3f9113c1acf83ea340faa96523427 100644
--- a/indra/newview/VIEWER_VERSION.txt
+++ b/indra/newview/VIEWER_VERSION.txt
@@ -1 +1 @@
-5.1.5
+5.1.6
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index ac46106721175a8b02d324071b824b6d5df6c3f6..2e297c92cdb240853f37ab00598f49f0f590fedc 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -4690,6 +4690,17 @@
       <key>Value</key>
       <integer>1</integer>
     </map>
+    <key>IgnoreFOVZoomForLODs</key>
+    <map>
+      <key>Comment</key>
+      <string>Ignore zoom effect(CTRL+0) when calculating lods.</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>Boolean</string>
+      <key>Value</key>
+      <integer>0</integer>
+    </map>
     <key>IgnoreAllNotifications</key>
     <map>
       <key>Comment</key>
@@ -10214,9 +10225,9 @@
   <key>RenderAutoMuteByteLimit</key>
   <map>
     <key>Comment</key>
-    <string>OBSOLETE and UNUSED.</string>
+    <string>If avatar attachment size exceed this value (in bytes) attachment will not be rendered. Excludes attachments worn by own avatar.</string>
     <key>Persist</key>
-    <integer>0</integer>
+    <integer>1</integer>
     <key>Type</key>
     <string>U32</string>
     <key>Value</key>
diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp
index 7e513896551b1bd7ada9d6786bd92e9bfb92afc5..22ed54913a69e0e2d878cd399394addb3300beb0 100644
--- a/indra/newview/lldrawable.cpp
+++ b/indra/newview/lldrawable.cpp
@@ -52,6 +52,7 @@
 #include "llvocache.h"
 #include "llcontrolavatar.h"
 #include "llcallstack.h"
+#include "lldrawpoolavatar.h"
 
 const F32 MIN_INTERPOLATE_DISTANCE_SQUARED = 0.001f * 0.001f;
 const F32 MAX_INTERPOLATE_DISTANCE_SQUARED = 10.f * 10.f;
@@ -145,6 +146,28 @@ void LLDrawable::init(bool new_entry)
 	initVisible(sCurVisible - 2);//invisible for the current frame and the last frame.
 }
 
+void LLDrawable::unload()
+{
+	LLVOVolume *pVVol = getVOVolume();
+	pVVol->setNoLOD();
+
+	for (S32 i = 0; i < getNumFaces(); i++)
+	{
+		LLFace* facep = getFace(i);
+		if (facep->isState(LLFace::RIGGED))
+		{
+			LLDrawPoolAvatar* pool = (LLDrawPoolAvatar*)facep->getPool();
+			if (pool) {
+				pool->removeRiggedFace(facep);
+			}
+			facep->setVertexBuffer(NULL);
+		}
+		facep->clearState(LLFace::RIGGED);
+	}
+
+	pVVol->markForUpdate(TRUE);
+}
+
 // static
 void LLDrawable::initClass()
 {
@@ -598,7 +621,7 @@ F32 LLDrawable::updateXform(BOOL undamped)
 	BOOL damped = !undamped;
 
 	// Position
-	LLVector3 old_pos(mXform.getPosition());
+	const LLVector3 old_pos(mXform.getPosition());
 	LLVector3 target_pos;
 	if (mXform.isRoot())
 	{
@@ -612,7 +635,7 @@ F32 LLDrawable::updateXform(BOOL undamped)
 	}
 	
 	// Rotation
-	LLQuaternion old_rot(mXform.getRotation());
+	const LLQuaternion old_rot(mXform.getRotation());
 	LLQuaternion target_rot = mVObjp->getRotation();
 	//scaling
 	LLVector3 target_scale = mVObjp->getScale();
@@ -647,6 +670,9 @@ F32 LLDrawable::updateXform(BOOL undamped)
 		{
 			// snap to final position (only if no target omega is applied)
 			dist_squared = 0.0f;
+			//set target scale here, because of dist_squared = 0.0f remove object from move list
+			mCurrentScale = target_scale;
+
 			if (getVOVolume() && !isRoot())
 			{ //child prim snapping to some position, needs a rebuild
 				gPipeline.markRebuild(this, LLDrawable::REBUILD_POSITION, TRUE);
@@ -663,11 +689,16 @@ F32 LLDrawable::updateXform(BOOL undamped)
 		//dist_squared += dist_vec_squared(old_scale, target_scale);
 	}
 
-	LLVector3 vec = mCurrentScale-target_scale;
+	const LLVector3 vec = mCurrentScale-target_scale;
+	
+	//It's a very important on each cycle on Drawable::update form(), when object remained in move
+	//, list update the CurrentScale member, because if do not do that, it remained in this list forever 
+	//or when the delta time between two frames a become a sufficiently large (due to interpolation) 
+	//for overcome the MIN_INTERPOLATE_DISTANCE_SQUARED.
+	mCurrentScale = target_scale;
 	
 	if (vec*vec > MIN_INTERPOLATE_DISTANCE_SQUARED)
 	{ //scale change requires immediate rebuild
-		mCurrentScale = target_scale;
 		gPipeline.markRebuild(this, LLDrawable::REBUILD_POSITION, TRUE);
 	}
 	else if (!isRoot() && 
@@ -982,9 +1013,7 @@ void LLDrawable::updateSpatialExtents()
 	if (mVObjp)
 	{
 		const LLVector4a* exts = getSpatialExtents();
-		LLVector4a extents[2];
-		extents[0] = exts[0];
-		extents[1] = exts[1];
+		LLVector4a extents[2] = { exts[0], exts[1] };
 
 		mVObjp->updateSpatialExtents(extents[0], extents[1]);
 		setSpatialExtents(extents[0], extents[1]);
diff --git a/indra/newview/lldrawable.h b/indra/newview/lldrawable.h
index a3461d4c01141327750be99f5551aea3055bb732..14d782d6f2683ff1bddb72aaf71994f4833ad142 100644
--- a/indra/newview/lldrawable.h
+++ b/indra/newview/lldrawable.h
@@ -84,6 +84,7 @@ class LLDrawable
 	void markDead();			// Mark this drawable as dead
 	BOOL isDead() const			{ return isState(DEAD); }
 	BOOL isNew() const			{ return !isState(BUILT); }
+	BOOL isUnload() const		{ return isState(FOR_UNLOAD); }
 
 	BOOL isLight() const;
 
@@ -141,6 +142,7 @@ class LLDrawable
 	void				mergeFaces(LLDrawable* src);
 
 	void init(bool new_entry);
+	void unload();
 	void destroy();
 
 	void update();
@@ -282,6 +284,7 @@ class LLDrawable
 		PARTITION_MOVE	= 0x10000000,
 		ANIMATED_CHILD  = 0x20000000,
 		ACTIVE_CHILD	= 0x40000000,
+		FOR_UNLOAD		= 0x80000000, //should be unload from memory
 	} EDrawableFlags;
 
 public:
diff --git a/indra/newview/lldrawpool.cpp b/indra/newview/lldrawpool.cpp
index 1ec8d97f36d69383af8fe98fb78416d8f6af07de..82888b2df6d83325ed52230d50fadf6fa99a3d17 100644
--- a/indra/newview/lldrawpool.cpp
+++ b/indra/newview/lldrawpool.cpp
@@ -49,6 +49,7 @@
 #include "llviewercamera.h"
 #include "lldrawpoolwlsky.h"
 #include "llglslshader.h"
+#include "llglcommonfunc.h"
 
 S32 LLDrawPool::sNumDrawPools = 0;
 
@@ -504,7 +505,9 @@ void LLRenderPass::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL ba
 		{
 			params.mGroup->rebuildMesh();
 		}
-		
+
+		LLGLEnableFunc stencil_test(GL_STENCIL_TEST, params.mSelected, &LLGLCommonFunc::selected_stencil_test);
+	
 		params.mVertexBuffer->setBuffer(mask);
 		params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset);
 		gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode);
diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp
index 60056ac21dd4dc9dacf4e7bffb008122fd724388..32630237cebb73e5285c487d76368f52a3b309bf 100644
--- a/indra/newview/lldrawpoolalpha.cpp
+++ b/indra/newview/lldrawpoolalpha.cpp
@@ -47,6 +47,7 @@
 #include "llviewerregion.h"
 #include "lldrawpoolwater.h"
 #include "llspatialpartition.h"
+#include "llglcommonfunc.h"
 
 BOOL LLDrawPoolAlpha::sShowDebugAlpha = FALSE;
 
@@ -583,11 +584,14 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass)
 
 				{
 					LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_PUSH);
-    gGL.blendFunc((LLRender::eBlendFactor) params.mBlendFuncSrc, (LLRender::eBlendFactor) params.mBlendFuncDst, mAlphaSFactor, mAlphaDFactor);					
-				params.mVertexBuffer->setBuffer(mask & ~(params.mFullbright ? (LLVertexBuffer::MAP_TANGENT | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_TEXCOORD2) : 0));
-                
-				params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset);
-				gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode);
+
+					LLGLEnableFunc stencil_test(GL_STENCIL_TEST, params.mSelected, &LLGLCommonFunc::selected_stencil_test);
+
+					gGL.blendFunc((LLRender::eBlendFactor) params.mBlendFuncSrc, (LLRender::eBlendFactor) params.mBlendFuncDst, mAlphaSFactor, mAlphaDFactor);
+					params.mVertexBuffer->setBuffer(mask & ~(params.mFullbright ? (LLVertexBuffer::MAP_TANGENT | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_TEXCOORD2) : 0));
+
+					params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset);
+					gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode);
 				}
 				
 				// If this alpha mesh has glow, then draw it a second time to add the destination-alpha (=glow).  Interleaving these state-changing calls could be expensive, but glow must be drawn Z-sorted with alpha.
@@ -597,7 +601,7 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass)
 				{
 					// install glow-accumulating blend mode
 					gGL.blendFunc(LLRender::BF_ZERO, LLRender::BF_ONE, // don't touch color
-						      LLRender::BF_ONE, LLRender::BF_ONE); // add to alpha (glow)
+					LLRender::BF_ONE, LLRender::BF_ONE); // add to alpha (glow)
 
 					emissive_shader->bind();
 					
diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp
index 375704adff734a31f0d0cec93e74f74108bed120..905428b090482268ea8b975bcb0d1c49d1e69bef 100644
--- a/indra/newview/lldrawpoolavatar.cpp
+++ b/indra/newview/lldrawpoolavatar.cpp
@@ -1600,6 +1600,11 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(
 	LLPointer<LLVertexBuffer> buffer = face->getVertexBuffer();
 	LLDrawable* drawable = face->getDrawable();
 
+	if (drawable->getVOVolume() && drawable->getVOVolume()->isNoLOD())
+	{
+		return;
+	}
+
 	U32 data_mask = face->getRiggedVertexBufferDataMask();
 
     if (!vol_face.mWeightsScrubbed)
@@ -1647,7 +1652,9 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(
 		return;
 	}
 
-	if (sShaderLevel <= 0 && face->mLastSkinTime < avatar->getLastSkinTime())
+	if (!buffer.isNull() && 
+		sShaderLevel <= 0 && 
+		face->mLastSkinTime < avatar->getLastSkinTime())
 	{
 		//perform software vertex skinning for this face
 		LLStrider<LLVector3> position;
@@ -1934,7 +1941,7 @@ void LLDrawPoolAvatar::updateRiggedVertexBuffers(LLVOAvatar* avatar)
 
 			LLVOVolume* vobj = drawable->getVOVolume();
 
-			if (!vobj)
+			if (!vobj || vobj->isNoLOD())
 			{
 				continue;
 			}
diff --git a/indra/newview/lldrawpoolmaterials.cpp b/indra/newview/lldrawpoolmaterials.cpp
index f92320490ab62a2c85d34b6421f6a12de1380a98..63e96a93b53e530d5a5fec93b6a767a2b3938d2f 100644
--- a/indra/newview/lldrawpoolmaterials.cpp
+++ b/indra/newview/lldrawpoolmaterials.cpp
@@ -30,6 +30,7 @@
 #include "lldrawpoolmaterials.h"
 #include "llviewershadermgr.h"
 #include "pipeline.h"
+#include "llglcommonfunc.h"
 
 S32 diffuse_channel = -1;
 
@@ -211,6 +212,9 @@ void LLDrawPoolMaterials::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture,
 	{
 		params.mGroup->rebuildMesh();
 	}
+
+	LLGLEnableFunc stencil_test(GL_STENCIL_TEST, params.mSelected, &LLGLCommonFunc::selected_stencil_test);
+
 	params.mVertexBuffer->setBuffer(mask);
 	params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset);
 	gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode);
diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp
index 7bc78143926b87ffc368d514285070424687f62a..e1691324f43ce272bc9d48f10666411855aec928 100644
--- a/indra/newview/llface.cpp
+++ b/indra/newview/llface.cpp
@@ -53,6 +53,7 @@
 #include "llviewershadermgr.h"
 #include "llviewertexture.h"
 #include "llvoavatar.h"
+#include "llsculptidsize.h"
 
 #if LL_LINUX
 // Work-around spurious used before init warning on Vector4a
@@ -2615,12 +2616,27 @@ LLViewerTexture* LLFace::getTexture(U32 ch) const
 
 void LLFace::setVertexBuffer(LLVertexBuffer* buffer)
 {
+	if (buffer)
+	{
+		LLSculptIDSize::instance().inc(mDrawablep, buffer->getSize() + buffer->getIndicesSize());
+	}
+
+	if (mVertexBuffer)
+	{
+		LLSculptIDSize::instance().dec(mDrawablep);
+	}
+
 	mVertexBuffer = buffer;
 	llassert(verify());
 }
 
 void LLFace::clearVertexBuffer()
 {
+	if (mVertexBuffer)
+	{
+		LLSculptIDSize::instance().dec(mDrawablep);
+	}
+
 	mVertexBuffer = NULL;
 }
 
diff --git a/indra/newview/llmaniprotate.cpp b/indra/newview/llmaniprotate.cpp
index 7bd5e4cba2105302fa157d41e4ca931ce88a2f68..f158aae3d2a5fe1922cee511ac39c2712e67b59c 100644
--- a/indra/newview/llmaniprotate.cpp
+++ b/indra/newview/llmaniprotate.cpp
@@ -283,6 +283,7 @@ void LLManipRotate::render()
 			LLGLEnable cull_face(GL_CULL_FACE);
 			LLGLEnable clip_plane0(GL_CLIP_PLANE0);
 			LLGLDepthTest gls_depth(GL_FALSE);
+			LLGLDisable gls_stencil(GL_STENCIL_TEST);
 
 			// First pass: centers. Second pass: sides.
 			for( S32 i=0; i<2; i++ )
diff --git a/indra/newview/llmanipscale.cpp b/indra/newview/llmanipscale.cpp
index 8b2ac4f303eaed9f7879e9afeda0be9d726bb2d0..9a8222d9412eb36b9e72f9f3e1827303138bb88d 100644
--- a/indra/newview/llmanipscale.cpp
+++ b/indra/newview/llmanipscale.cpp
@@ -754,6 +754,7 @@ void LLManipScale::renderBoxHandle( F32 x, F32 y, F32 z )
 {
 	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
 	LLGLDepthTest gls_depth(GL_FALSE);
+	LLGLDisable gls_stencil(GL_STENCIL_TEST);
 
 	gGL.pushMatrix();
 	{
diff --git a/indra/newview/llmaniptranslate.cpp b/indra/newview/llmaniptranslate.cpp
index 785022792bb68d76ba9e7108fd2deba87d6fcfd0..92a09357c8fa5adc77405f2118df0aceb10915db 100644
--- a/indra/newview/llmaniptranslate.cpp
+++ b/indra/newview/llmaniptranslate.cpp
@@ -1060,6 +1060,7 @@ void LLManipTranslate::render()
 		renderGuidelines();
 	}
 	{
+		LLGLDisable gls_stencil(GL_STENCIL_TEST);
 		renderTranslationHandles();
 		renderSnapGuides();
 	}
@@ -1638,8 +1639,8 @@ void LLManipTranslate::highlightIntersection(LLVector3 normal,
 	LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;
 
 	
-	U32 types[] = { LLRenderPass::PASS_SIMPLE, LLRenderPass::PASS_ALPHA, LLRenderPass::PASS_FULLBRIGHT, LLRenderPass::PASS_SHINY };
-	U32 num_types = LL_ARRAY_SIZE(types);
+	static const U32 types[] = { LLRenderPass::PASS_SIMPLE, LLRenderPass::PASS_ALPHA, LLRenderPass::PASS_FULLBRIGHT, LLRenderPass::PASS_SHINY };
+	static const U32 num_types = LL_ARRAY_SIZE(types);
 
 	GLuint stencil_mask = 0xFFFFFFFF;
 	//stencil in volumes
diff --git a/indra/newview/llmaterialmgr.cpp b/indra/newview/llmaterialmgr.cpp
index d9fc489b4ee071bc26bd686d067f6eb403dd89d8..52b9fb40ae6233500f4389cc0f7038f6d36ebcba 100644
--- a/indra/newview/llmaterialmgr.cpp
+++ b/indra/newview/llmaterialmgr.cpp
@@ -350,6 +350,25 @@ void LLMaterialMgr::remove(const LLUUID& object_id, const U8 te)
 	put(object_id, te, LLMaterial::null);
 }
 
+void LLMaterialMgr::setLocalMaterial(const LLUUID& region_id, LLMaterialPtr material_ptr)
+{
+	LLUUID uuid;
+	uuid.generate();
+	LLMaterialID material_id(uuid);
+	while (mMaterials.end() != mMaterials.find(material_id)) 
+	{ //probability that this loop will executed is very, very low (one in a billion chance)
+		uuid.generate();
+		material_id.set(uuid.mData);
+	}	
+
+	LL_DEBUGS("Materials") << "region " << region_id << "new local material id " << material_id << LL_ENDL;
+	mMaterials.insert(std::pair<LLMaterialID, LLMaterialPtr>(material_id, material_ptr));
+
+	setMaterialCallbacks(material_id, material_ptr);
+
+	mGetPending.erase(pending_material_t(region_id, material_id));
+}
+
 const LLMaterialPtr LLMaterialMgr::setMaterial(const LLUUID& region_id, const LLMaterialID& material_id, const LLSD& material_data)
 {
 	LL_DEBUGS("Materials") << "region " << region_id << " material id " << material_id << LL_ENDL;
@@ -362,17 +381,26 @@ const LLMaterialPtr LLMaterialMgr::setMaterial(const LLUUID& region_id, const LL
 		itMaterial = ret.first;
 	}
 
+	setMaterialCallbacks(material_id, itMaterial->second);
+
+	mGetPending.erase(pending_material_t(region_id, material_id));
+
+	return itMaterial->second;
+}
+
+void LLMaterialMgr::setMaterialCallbacks(const LLMaterialID& material_id, const LLMaterialPtr material_ptr)
+{
 	TEMaterialPair te_mat_pair;
 	te_mat_pair.materialID = material_id;
 
 	U32 i = 0;
-	while (i < LLTEContents::MAX_TES)
+	while (i < LLTEContents::MAX_TES && !mGetTECallbacks.empty())
 	{
 		te_mat_pair.te = i++;
 		get_callback_te_map_t::iterator itCallbackTE = mGetTECallbacks.find(te_mat_pair);
 		if (itCallbackTE != mGetTECallbacks.end())
 		{
-			(*itCallbackTE->second)(material_id, itMaterial->second, te_mat_pair.te);
+			(*itCallbackTE->second)(material_id, material_ptr, te_mat_pair.te);
 			delete itCallbackTE->second;
 			mGetTECallbacks.erase(itCallbackTE);
 		}
@@ -381,15 +409,11 @@ const LLMaterialPtr LLMaterialMgr::setMaterial(const LLUUID& region_id, const LL
 	get_callback_map_t::iterator itCallback = mGetCallbacks.find(material_id);
 	if (itCallback != mGetCallbacks.end())
 	{
-		(*itCallback->second)(material_id, itMaterial->second);
+		(*itCallback->second)(material_id, material_ptr);
 
 		delete itCallback->second;
 		mGetCallbacks.erase(itCallback);
 	}
-
-	mGetPending.erase(pending_material_t(region_id, material_id));
-
-	return itMaterial->second;
 }
 
 void LLMaterialMgr::onGetResponse(bool success, const LLSD& content, const LLUUID& region_id)
diff --git a/indra/newview/llmaterialmgr.h b/indra/newview/llmaterialmgr.h
index 60b58d17de7156d0234e6a5a39e4fd33e7e0ee7b..843dc66fbcaefe7ca64df53c814d347672493108 100644
--- a/indra/newview/llmaterialmgr.h
+++ b/indra/newview/llmaterialmgr.h
@@ -56,6 +56,9 @@ class LLMaterialMgr : public LLSingleton<LLMaterialMgr>
 	boost::signals2::connection getAll(const LLUUID& region_id, getall_callback_t::slot_type cb);
 	void put(const LLUUID& object_id, const U8 te, const LLMaterial& material);
 	void remove(const LLUUID& object_id, const U8 te);
+	
+	//explicitly add new material to material manager
+	void setLocalMaterial(const LLUUID& region_id, LLMaterialPtr material_ptr);
 
 private:
 	void clearGetQueues(const LLUUID& region_id);
@@ -63,7 +66,8 @@ class LLMaterialMgr : public LLSingleton<LLMaterialMgr>
 	bool isGetAllPending(const LLUUID& region_id) const;
 	void markGetPending(const LLUUID& region_id, const LLMaterialID& material_id);
 	const LLMaterialPtr setMaterial(const LLUUID& region_id, const LLMaterialID& material_id, const LLSD& material_data);
-
+	void setMaterialCallbacks(const LLMaterialID& material_id, const LLMaterialPtr material_ptr);
+	
 	static void onIdle(void*);
 
     static void CapsRecvForRegion(const LLUUID& regionId, LLUUID regionTest, std::string pumpname);
diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp
index e2df30c034e2a11702baf39fd10bb148119e58f7..4561920c4c49a38013007c0d0ee4e7d37a584b79 100644
--- a/indra/newview/llmeshrepository.cpp
+++ b/indra/newview/llmeshrepository.cpp
@@ -4027,7 +4027,7 @@ void LLMeshRepository::uploadModel(std::vector<LLModelInstance>& data, LLVector3
 
 S32 LLMeshRepository::getMeshSize(const LLUUID& mesh_id, S32 lod)
 {
-	if (mThread && mesh_id.notNull())
+	if (mThread && mesh_id.notNull() && LLPrimitive::NO_LOD != lod)
 	{
 		LLMutexLock lock(mThread->mHeaderMutex);
 		LLMeshRepoThread::mesh_header_map::iterator iter = mThread->mMeshHeader.find(mesh_id);
diff --git a/indra/newview/llsculptidsize.cpp b/indra/newview/llsculptidsize.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..9edd78bff03b33c14cf6acc425aeaeb8f5f20559
--- /dev/null
+++ b/indra/newview/llsculptidsize.cpp
@@ -0,0 +1,154 @@
+/**
+* @file llsculptidsize.cpp
+* @brief LLSculptIDSize class implementation
+*
+* $LicenseInfo:firstyear=2002&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2010, Linden Research, Inc.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+* $/LicenseInfo$
+*/
+
+#include "llviewerprecompiledheaders.h"
+#include "llsculptidsize.h"
+#include "llvovolume.h"
+#include "lldrawable.h"
+#include "llvoavatar.h"
+//boost
+#include "boost/make_shared.hpp"
+
+//...........
+
+extern LLControlGroup gSavedSettings;
+
+//...........
+
+typedef std::pair<LLSculptIDSize::container_BY_SCULPT_ID_view::iterator, LLSculptIDSize::container_BY_SCULPT_ID_view::iterator> pair_iter_iter_BY_SCULPT_ID_t;
+
+//...........
+
+void _nothing_to_do_func(int) { /*nothing todo here because of the size it's a shared member*/ }
+
+void LLSculptIDSize::inc(const LLDrawable *pdrawable, int sz)
+{
+	llassert(sz >= 0);
+
+	if (!pdrawable) return;
+	LLVOVolume* vvol = pdrawable->getVOVolume();
+	if (!vvol) return;
+	if (!vvol->isAttachment()) return;
+	if (!vvol->getAvatar()) return;
+	if (vvol->getAvatar()->isSelf()) return;
+	LLVolume *vol = vvol->getVolume();
+	if (!vol) return;
+
+	const LLUUID &sculptId = vol->getParams().getSculptID();
+	if (sculptId.isNull()) return;
+
+	unsigned int total_size = 0;
+
+	pair_iter_iter_BY_SCULPT_ID_t itLU = mSizeInfo.get<tag_BY_SCULPT_ID>().equal_range(sculptId);
+	if (itLU.first == itLU.second)
+	{ //register
+		llassert(mSizeInfo.get<tag_BY_DRAWABLE>().end() == mSizeInfo.get<tag_BY_DRAWABLE>().find(pdrawable));
+		mSizeInfo.get<tag_BY_DRAWABLE>().insert(Info(pdrawable, sz, boost::make_shared<SizeSum>(sz), sculptId));
+		total_size = sz;
+	}
+	else
+	{ //update + register
+		Info &nfo = const_cast<Info &>(*itLU.first);
+		//calc new size
+		total_size = nfo.getSizeSum() + sz;
+		nfo.mSharedSizeSum->mSizeSum = total_size;
+		nfo.mSize = sz;
+		//update size for all LLDrwable in range of sculptId
+		for (pair_iter_iter_BY_SCULPT_ID_t::first_type it = itLU.first; it != itLU.second; ++it)
+		{
+			mSizeInfo.get<tag_BY_SIZE>().modify_key(mSizeInfo.project<tag_BY_SIZE>(it), boost::bind(&_nothing_to_do_func, _1));
+		}
+
+		//trying insert the LLDrawable
+		mSizeInfo.get<tag_BY_DRAWABLE>().insert(Info(pdrawable, sz, nfo.mSharedSizeSum, sculptId));
+	}
+
+	static LLCachedControl<U32> render_auto_mute_byte_limit(gSavedSettings, "RenderAutoMuteByteLimit", 0U);
+
+	if (0 != render_auto_mute_byte_limit && total_size > render_auto_mute_byte_limit)
+	{
+		pair_iter_iter_BY_SCULPT_ID_t it_eqr = mSizeInfo.get<tag_BY_SCULPT_ID>().equal_range(sculptId);
+		for (; it_eqr.first != it_eqr.second; ++it_eqr.first)
+		{
+			const Info &i = *it_eqr.first;
+			LLVOVolume *pVVol = i.mDrawable->getVOVolume();
+			if (pVVol
+				&& !pVVol->isDead()
+				&& pVVol->isAttachment()
+				&& !pVVol->getAvatar()->isSelf()
+				&& LLVOVolume::NO_LOD != pVVol->getLOD()
+				)
+			{
+				addToUnloaded(sculptId);
+				//immediately
+				const_cast<LLDrawable*>(i.mDrawable)->unload();
+			}
+		}
+	}
+}
+
+void LLSculptIDSize::dec(const LLDrawable *pdrawable)
+{
+	container_BY_DRAWABLE_view::iterator it = mSizeInfo.get<tag_BY_DRAWABLE>().find(pdrawable);
+	if (mSizeInfo.get<tag_BY_DRAWABLE>().end() == it) return;
+
+	unsigned int size = it->getSizeSum() - it->getSize();
+
+	if (0 == size)
+	{
+		mSizeInfo.get<tag_BY_SCULPT_ID>().erase(it->getSculptId());
+	}
+	else
+	{
+		Info &nfo = const_cast<Info &>(*it);
+		nfo.mSize = 0;
+		pair_iter_iter_BY_SCULPT_ID_t itLU = mSizeInfo.get<tag_BY_SCULPT_ID>().equal_range(it->getSculptId());
+		it->mSharedSizeSum->mSizeSum = size;
+		for (pair_iter_iter_BY_SCULPT_ID_t::first_type it = itLU.first; it != itLU.second; ++it)
+		{
+			mSizeInfo.get<tag_BY_SIZE>().modify_key(mSizeInfo.project<tag_BY_SIZE>(it), boost::bind(&_nothing_to_do_func, _1));
+		}
+	}
+}
+
+void LLSculptIDSize::rem(const LLUUID &sculptId)
+{
+	mSizeInfo.get<tag_BY_SCULPT_ID>().erase(sculptId);
+}
+
+void LLSculptIDSize::resetSizeSum(const LLUUID &sculptId)
+{
+	const pair_iter_iter_BY_SCULPT_ID_t itLU = mSizeInfo.get<tag_BY_SCULPT_ID>().equal_range(sculptId);
+
+	if (itLU.first != itLU.second) {
+		itLU.first->mSharedSizeSum->mSizeSum = 0;
+	}
+
+	for (pair_iter_iter_BY_SCULPT_ID_t::first_type it = itLU.first, itE = itLU.second; it != itE; ++it)
+	{
+		mSizeInfo.get<tag_BY_SIZE>().modify_key(mSizeInfo.project<tag_BY_SIZE>(it), boost::bind(&_nothing_to_do_func, _1));
+	}
+}
diff --git a/indra/newview/llsculptidsize.h b/indra/newview/llsculptidsize.h
new file mode 100644
index 0000000000000000000000000000000000000000..87ee417b867317e15bb91bcf1e2ff569cc7a8ca8
--- /dev/null
+++ b/indra/newview/llsculptidsize.h
@@ -0,0 +1,134 @@
+/**
+* @file llsculptidsize.h
+* @brief LLSculptIDSize class definition
+*
+* $LicenseInfo:firstyear=2009&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2010, Linden Research, Inc.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+* $/LicenseInfo$
+*/
+
+#ifndef LL_LLSCULPTIDSIZE_H
+#define LL_LLSCULPTIDSIZE_H
+
+#include "lluuid.h"
+
+//std
+#include <set>
+//boost
+#include "boost/multi_index_container.hpp"
+#include "boost/multi_index/ordered_index.hpp"
+#include "boost/multi_index/mem_fun.hpp"
+
+class LLDrawable;
+
+
+class LLSculptIDSize
+{
+public:
+	struct SizeSum
+	{
+		SizeSum(int size) 
+			: mSizeSum(size)
+		{}
+		unsigned int mSizeSum;
+	};
+
+	struct Info
+	{
+		typedef boost::shared_ptr<SizeSum> PtrSizeSum;
+
+		Info(const LLDrawable *drawable, int size, PtrSizeSum sizeInfo, LLUUID sculptId)
+			: mDrawable(drawable)
+			, mSize(size)
+			, mSharedSizeSum(sizeInfo)
+			, mSculptId(sculptId)
+		{}
+
+		const LLDrawable *mDrawable;
+		unsigned int mSize;
+		PtrSizeSum	mSharedSizeSum;
+		LLUUID mSculptId;
+
+		inline const LLDrawable*	getPtrLLDrawable() const { return mDrawable; }
+		inline unsigned int			getSize() const { return mSize; }
+		inline unsigned int			getSizeSum() const { return mSharedSizeSum->mSizeSum; }
+		inline LLUUID				getSculptId() const { return mSculptId; }
+		PtrSizeSum					getSizeInfo() { return mSharedSizeSum; }
+	};
+
+public:
+	//tags
+	struct tag_BY_DRAWABLE {};
+	struct tag_BY_SCULPT_ID {};
+	struct tag_BY_SIZE {};
+
+	//container
+	typedef boost::multi_index_container <
+		Info,
+		boost::multi_index::indexed_by <
+		boost::multi_index::ordered_unique< boost::multi_index::tag<tag_BY_DRAWABLE>
+		, boost::multi_index::const_mem_fun<Info, const LLDrawable*, &Info::getPtrLLDrawable>
+		>
+		, boost::multi_index::ordered_non_unique<boost::multi_index::tag<tag_BY_SCULPT_ID>
+		, boost::multi_index::const_mem_fun<Info, LLUUID, &Info::getSculptId>
+		>
+		, boost::multi_index::ordered_non_unique < boost::multi_index::tag<tag_BY_SIZE>
+		, boost::multi_index::const_mem_fun < Info, unsigned int, &Info::getSizeSum >
+		>
+		>
+	> container;
+
+	//views
+	typedef container::index<tag_BY_DRAWABLE>::type			container_BY_DRAWABLE_view;
+	typedef container::index<tag_BY_SCULPT_ID>::type		container_BY_SCULPT_ID_view;
+	typedef container::index<tag_BY_SIZE>::type				container_BY_SIZE_view;
+
+private:
+	LLSculptIDSize()
+	{}
+
+public:
+	static LLSculptIDSize & instance() 
+	{
+		static LLSculptIDSize inst;
+		return inst;
+	}
+
+public:
+	void inc(const LLDrawable *pdrawable, int sz);
+	void dec(const LLDrawable *pdrawable);
+	void rem(const LLUUID &sculptId);
+
+	inline void addToUnloaded(const LLUUID &sculptId) { mMarkAsUnloaded.insert(sculptId); }
+	inline void remFromUnloaded(const LLUUID &sculptId) { mMarkAsUnloaded.erase(sculptId); }
+	inline bool isUnloaded(const LLUUID &sculptId) const { return mMarkAsUnloaded.end() != mMarkAsUnloaded.find(sculptId); }
+	inline void clearUnloaded() { mMarkAsUnloaded.clear(); }
+	
+	void resetSizeSum(const LLUUID &sculptId);
+
+	inline const container & getSizeInfo() const { return mSizeInfo; }
+
+private:
+	container mSizeInfo;
+	typedef std::set<LLUUID> std_LLUUID;
+	std_LLUUID mMarkAsUnloaded;
+};
+
+#endif
diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp
index ce5fc7a71ec1372e8a73902a09dd3012aa14c916..983606a604f21305df0b25db6852fcce1f1deb12 100644
--- a/indra/newview/llselectmgr.cpp
+++ b/indra/newview/llselectmgr.cpp
@@ -6280,92 +6280,107 @@ void pushWireframe(LLDrawable* drawable)
 
 void LLSelectNode::renderOneWireframe(const LLColor4& color)
 {
-	//Need to because crash on ATI 3800 (and similar cards) MAINT-5018 
-	LLGLDisable multisample(LLPipeline::RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0);
+    //Need to because crash on ATI 3800 (and similar cards) MAINT-5018 
+    LLGLDisable multisample(LLPipeline::RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0);
 
-	LLViewerObject* objectp = getObject();
-	if (!objectp)
-	{
-		return;
-	}
+    LLViewerObject* objectp = getObject();
+    if (!objectp)
+    {
+        return;
+    }
 
-	LLDrawable* drawable = objectp->mDrawable;
-	if(!drawable)
-	{
-		return;
-	}
+    LLDrawable* drawable = objectp->mDrawable;
+    if (!drawable)
+    {
+        return;
+    }
 
-	LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;
+    LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;
 
-	if (shader)
-	{
-		gDebugProgram.bind();
-	}
+    if (shader)
+    {
+        gDebugProgram.bind();
+    }
 
-	gGL.matrixMode(LLRender::MM_MODELVIEW);
-	gGL.pushMatrix();
-	
-	BOOL is_hud_object = objectp->isHUDAttachment();
+    gGL.matrixMode(LLRender::MM_MODELVIEW);
+    gGL.pushMatrix();
 
-	if (drawable->isActive())
-	{
-		gGL.loadMatrix(gGLModelView);
-		gGL.multMatrix((F32*) objectp->getRenderMatrix().mMatrix);
-	}
-	else if (!is_hud_object)
-	{
-		gGL.loadIdentity();
-		gGL.multMatrix(gGLModelView);
-		LLVector3 trans = objectp->getRegion()->getOriginAgent();		
-		gGL.translatef(trans.mV[0], trans.mV[1], trans.mV[2]);		
-	}
-	
-	glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
-	
-	if (LLSelectMgr::sRenderHiddenSelections) // && gFloaterTools && gFloaterTools->getVisible())
-	{
-		gGL.blendFunc(LLRender::BF_SOURCE_COLOR, LLRender::BF_ONE);
-		LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE, GL_GEQUAL);
-		if (shader)
-		{
-			gGL.diffuseColor4f(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE], 0.4f);
-			pushWireframe(drawable);
-		}
-		else
-		{
-			LLGLEnable fog(GL_FOG);
-			glFogi(GL_FOG_MODE, GL_LINEAR);
-			float d = (LLViewerCamera::getInstance()->getPointOfInterest()-LLViewerCamera::getInstance()->getOrigin()).magVec();
-			LLColor4 fogCol = color * (F32)llclamp((LLSelectMgr::getInstance()->getSelectionCenterGlobal()-gAgentCamera.getCameraPositionGlobal()).magVec()/(LLSelectMgr::getInstance()->getBBoxOfSelection().getExtentLocal().magVec()*4), 0.0, 1.0);
-			glFogf(GL_FOG_START, d);
-			glFogf(GL_FOG_END, d*(1 + (LLViewerCamera::getInstance()->getView() / LLViewerCamera::getInstance()->getDefaultFOV())));
-			glFogfv(GL_FOG_COLOR, fogCol.mV);
+    BOOL is_hud_object = objectp->isHUDAttachment();
 
-			gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT);
-			{
-				gGL.diffuseColor4f(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE], 0.4f);
-				pushWireframe(drawable);
-			}
-		}
-	}
+    if (drawable->isActive())
+    {
+        gGL.loadMatrix(gGLModelView);
+        gGL.multMatrix((F32*)objectp->getRenderMatrix().mMatrix);
+    }
+    else if (!is_hud_object)
+    {
+        gGL.loadIdentity();
+        gGL.multMatrix(gGLModelView);
+        LLVector3 trans = objectp->getRegion()->getOriginAgent();
+        gGL.translatef(trans.mV[0], trans.mV[1], trans.mV[2]);
+    }
 
-	gGL.flush();
-	gGL.setSceneBlendType(LLRender::BT_ALPHA);
+    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
 
-	gGL.diffuseColor4f(color.mV[VRED]*2, color.mV[VGREEN]*2, color.mV[VBLUE]*2, LLSelectMgr::sHighlightAlpha*2);
-	
-	LLGLEnable offset(GL_POLYGON_OFFSET_LINE);
-	glPolygonOffset(3.f, 3.f);
-	glLineWidth(3.f);
-	pushWireframe(drawable);
-	glLineWidth(1.f);
-	glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
-	gGL.popMatrix();
+    if (LLSelectMgr::sRenderHiddenSelections) // && gFloaterTools && gFloaterTools->getVisible())
+    {
+        gGL.blendFunc(LLRender::BF_SOURCE_COLOR, LLRender::BF_ONE);
+        LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE, GL_GEQUAL);
+        if (shader)
+        {
+            gGL.diffuseColor4f(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE], 0.4f);
+            pushWireframe(drawable);
+        }
+        else
+        {
+            LLGLEnable fog(GL_FOG);
+            glFogi(GL_FOG_MODE, GL_LINEAR);
+            float d = (LLViewerCamera::getInstance()->getPointOfInterest() - LLViewerCamera::getInstance()->getOrigin()).magVec();
+            LLColor4 fogCol = color * (F32)llclamp((LLSelectMgr::getInstance()->getSelectionCenterGlobal() - gAgentCamera.getCameraPositionGlobal()).magVec() / (LLSelectMgr::getInstance()->getBBoxOfSelection().getExtentLocal().magVec() * 4), 0.0, 1.0);
+            glFogf(GL_FOG_START, d);
+            glFogf(GL_FOG_END, d*(1 + (LLViewerCamera::getInstance()->getView() / LLViewerCamera::getInstance()->getDefaultFOV())));
+            glFogfv(GL_FOG_COLOR, fogCol.mV);
+
+            gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT);
+            {
+                gGL.diffuseColor4f(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE], 0.4f);
+                pushWireframe(drawable);
+            }
+        }
+    }
 
-	if (shader)
-	{
-		shader->bind();
-	}
+    gGL.flush();
+    gGL.setSceneBlendType(LLRender::BT_ALPHA);
+
+    gGL.diffuseColor4f(color.mV[VRED] * 2, color.mV[VGREEN] * 2, color.mV[VBLUE] * 2, LLSelectMgr::sHighlightAlpha * 2);
+
+    {
+        bool wireframe_selection = gFloaterTools && gFloaterTools->getVisible();
+
+        LLGLDisable depth(wireframe_selection ? 0 : GL_BLEND);
+        LLGLEnable stencil(wireframe_selection ? 0 : GL_STENCIL_TEST);
+
+        if (!wireframe_selection)
+        { //modify wireframe into outline selection mode
+            glStencilFunc(GL_NOTEQUAL, 2, 0xffff);
+            glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
+        }
+
+        LLGLEnable offset(GL_POLYGON_OFFSET_LINE);
+        glPolygonOffset(3.f, 3.f);
+        glLineWidth(5.f);
+        glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+        pushWireframe(drawable);
+    }
+
+    glLineWidth(1.f);
+    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+    gGL.popMatrix();
+
+    if (shader)
+    {
+        shader->bind();
+    }
 }
 
 //-----------------------------------------------------------------------------
diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp
index 8b1a23fe89c566e3dbb4b0729972e599ea4874c4..ee77556047c627cec572310c718efa2147701127 100644
--- a/indra/newview/llspatialpartition.cpp
+++ b/indra/newview/llspatialpartition.cpp
@@ -3957,6 +3957,7 @@ LLDrawable* LLSpatialPartition::lineSegmentIntersect(const LLVector4a& start, co
 
 LLDrawInfo::LLDrawInfo(U16 start, U16 end, U32 count, U32 offset, 
 					   LLViewerTexture* texture, LLVertexBuffer* buffer,
+					   bool selected,
 					   BOOL fullbright, U8 bump, BOOL particle, F32 part_size)
 :	LLTrace::MemTrackableNonVirtual<LLDrawInfo, 16>("LLDrawInfo"),
 	mVertexBuffer(buffer),
@@ -3984,7 +3985,8 @@ LLDrawInfo::LLDrawInfo(U16 start, U16 end, U32 count, U32 offset,
 	mHasGlow(FALSE),
 	mEnvIntensity(0.0f),
 	mAlphaMaskCutoff(0.5f),
-	mDiffuseAlphaMode(0)
+	mDiffuseAlphaMode(0),
+	mSelected(selected)
 {
 	mVertexBuffer->validateRange(mStart, mEnd, mCount, mOffset);
 	
diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h
index 2594e3397cc1ec09e0a4e40d41e46eb0d9ce3395..7e65da42f7e471d9760d6920529d254b8834d676 100644
--- a/indra/newview/llspatialpartition.h
+++ b/indra/newview/llspatialpartition.h
@@ -75,6 +75,7 @@ class LLDrawInfo : public LLRefCount, public LLTrace::MemTrackableNonVirtual<LLD
 
 	LLDrawInfo(U16 start, U16 end, U32 count, U32 offset, 
 				LLViewerTexture* image, LLVertexBuffer* buffer, 
+				bool selected,
 				BOOL fullbright = FALSE, U8 bump = 0, BOOL particle = FALSE, F32 part_size = 0);
 	
 
@@ -117,6 +118,7 @@ class LLDrawInfo : public LLRefCount, public LLTrace::MemTrackableNonVirtual<LLD
 	F32  mEnvIntensity;
 	F32  mAlphaMaskCutoff;
 	U8   mDiffuseAlphaMode;
+	bool mSelected;
 
 
 	struct CompareTexture
@@ -644,7 +646,7 @@ class LLVolumeGeometryManager: public LLGeometryManager
 	virtual void rebuildGeom(LLSpatialGroup* group);
 	virtual void rebuildMesh(LLSpatialGroup* group);
 	virtual void getGeometry(LLSpatialGroup* group);
-	void genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace** faces, U32 face_count, BOOL distance_sort = FALSE, BOOL batch_textures = FALSE, BOOL no_materials = FALSE);
+	U32 genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace** faces, U32 face_count, BOOL distance_sort = FALSE, BOOL batch_textures = FALSE, BOOL no_materials = FALSE);
 	void registerFace(LLSpatialGroup* group, LLFace* facep, U32 type);
 
 private:
diff --git a/indra/newview/llviewercamera.cpp b/indra/newview/llviewercamera.cpp
index 57a0195d23ea41ed3074e0bbb4595422460b5146..778e27572728557f3269cdf06642c56f25398ee6 100644
--- a/indra/newview/llviewercamera.cpp
+++ b/indra/newview/llviewercamera.cpp
@@ -113,6 +113,7 @@ LLViewerCamera::LLViewerCamera() : LLCamera()
 {
 	calcProjection(getFar());
 	mCameraFOVDefault = DEFAULT_FIELD_OF_VIEW;
+	mPrevCameraFOVDefault = DEFAULT_FIELD_OF_VIEW;
 	mCosHalfCameraFOV = cosf(mCameraFOVDefault * 0.5f);
 	mPixelMeterRatio = 0.f;
 	mScreenPixelArea = 0;
@@ -882,6 +883,15 @@ void LLViewerCamera::setDefaultFOV(F32 vertical_fov_rads)
 	mCosHalfCameraFOV = cosf(mCameraFOVDefault * 0.5f);
 }
 
+BOOL LLViewerCamera::isDefaultFOVChanged()
+{
+	if(mPrevCameraFOVDefault != mCameraFOVDefault)
+	{
+		mPrevCameraFOVDefault = mCameraFOVDefault;
+		return !gSavedSettings.getBOOL("IgnoreFOVZoomForLODs");
+	}
+	return FALSE;
+}
 
 // static
 void LLViewerCamera::updateCameraAngle( void* user_data, const LLSD& value)
diff --git a/indra/newview/llviewercamera.h b/indra/newview/llviewercamera.h
index f8c973690a08aff2a3d26111348da4a931beb3ba..5901de289f02315a2d3a34dd94e9222e65679025 100644
--- a/indra/newview/llviewercamera.h
+++ b/indra/newview/llviewercamera.h
@@ -115,6 +115,8 @@ class LLViewerCamera : public LLCamera, public LLSingleton<LLViewerCamera>
 	void setDefaultFOV(F32 fov) ;
 	F32 getDefaultFOV() { return mCameraFOVDefault; }
 
+	BOOL isDefaultFOVChanged();
+
 	BOOL cameraUnderWater() const;
 	BOOL areVertsVisible(LLViewerObject* volumep, BOOL all_verts);
 
@@ -138,6 +140,7 @@ class LLViewerCamera : public LLCamera, public LLSingleton<LLViewerCamera>
 	mutable LLMatrix4	mProjectionMatrix;	// Cache of perspective matrix
 	mutable LLMatrix4	mModelviewMatrix;
 	F32					mCameraFOVDefault;
+	F32					mPrevCameraFOVDefault;
 	F32					mCosHalfCameraFOV;
 	LLVector3			mLastPointOfInterest;
 	F32					mPixelMeterRatio; // Divide by distance from camera to get pixels per meter at that distance.
diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp
index 63c62fc99072cd3bc7d740dc0b9eac52e46375df..88984d518ab5fe18ae9eef12b5768574d86eea2e 100644
--- a/indra/newview/llviewercontrol.cpp
+++ b/indra/newview/llviewercontrol.cpp
@@ -592,6 +592,7 @@ bool toggle_show_object_render_cost(const LLSD& newvalue)
 	return true;
 }
 
+void handleRenderAutoMuteByteLimitChanged(const LLSD& new_value);
 ////////////////////////////////////////////////////////////////////////////
 
 void settings_setup_listeners()
@@ -745,6 +746,7 @@ void settings_setup_listeners()
 	gSavedSettings.getControl("SpellCheckDictionary")->getSignal()->connect(boost::bind(&handleSpellCheckChanged));
 	gSavedSettings.getControl("LoginLocation")->getSignal()->connect(boost::bind(&handleLoginLocationChanged));
 	gSavedSettings.getControl("DebugAvatarJoints")->getCommitSignal()->connect(boost::bind(&handleDebugAvatarJointsChanged, _2));
+	gSavedSettings.getControl("RenderAutoMuteByteLimit")->getSignal()->connect(boost::bind(&handleRenderAutoMuteByteLimitChanged, _2));
 	gSavedPerAccountSettings.getControl("AvatarHoverOffsetZ")->getCommitSignal()->connect(boost::bind(&handleAvatarHoverOffsetChanged, _2));
 }
 
diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp
index 96ef160c7262cbc06d8214bf0343569560df13a1..86a9e7e2ad848bea176db901e34a483167aa33f4 100644
--- a/indra/newview/llviewerdisplay.cpp
+++ b/indra/newview/llviewerdisplay.cpp
@@ -1005,7 +1005,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
 															  gPipeline.mDeferredScreen.getHeight(), 0, 0, 
 															  gPipeline.mDeferredScreen.getWidth(), 
 															  gPipeline.mDeferredScreen.getHeight(), 
-															  GL_DEPTH_BUFFER_BIT, GL_NEAREST);
+															  GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
 				}
 			}
 			else
@@ -1017,7 +1017,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
 															  gPipeline.mScreen.getHeight(), 0, 0, 
 															  gPipeline.mScreen.getWidth(), 
 															  gPipeline.mScreen.getHeight(), 
-															  GL_DEPTH_BUFFER_BIT, GL_NEAREST);
+															  GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
 				}
 			}
 		}
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index f33bafa03c588075605f7c8ac4ff37c9cf48a70a..5ca6b25a189311b256ad60c64ac1437be06b30fd 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -6193,6 +6193,14 @@ void LLViewerObject::markForUpdate(BOOL priority)
 	}
 }
 
+void LLViewerObject::markForUnload(BOOL priority)
+{
+	if (mDrawable.notNull())
+	{
+		gPipeline.markRebuild(mDrawable, LLDrawable::FOR_UNLOAD, priority);
+	}
+}
+
 bool LLViewerObject::isPermanentEnforced() const
 {
 	return flagObjectPermanent() && (mRegionp != gAgent.getRegion()) && !gAgent.isGodlike();
diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h
index b9840f629b7b61cc079e5cb37dd16e41a14b6a15..eac3f1bbe83a440ce0a1489345a004f22bf85b4f 100644
--- a/indra/newview/llviewerobject.h
+++ b/indra/newview/llviewerobject.h
@@ -430,6 +430,7 @@ class LLViewerObject
 
     void recursiveMarkForUpdate(BOOL priority);
 	virtual void markForUpdate(BOOL priority);
+	void markForUnload(BOOL priority);
 	void updateVolume(const LLVolumeParams& volume_params);
 	virtual	void updateSpatialExtents(LLVector4a& min, LLVector4a& max);
 	virtual F32 getBinRadius();
diff --git a/indra/newview/llvieweroctree.cpp b/indra/newview/llvieweroctree.cpp
index e7916ebd3b67f7a8a26f8bd49a5e3968afb4eefe..00a652384c189c66fa79f49a20a4be990f838d4c 100644
--- a/indra/newview/llvieweroctree.cpp
+++ b/indra/newview/llvieweroctree.cpp
@@ -465,7 +465,7 @@ LLViewerOctreeGroup::LLViewerOctreeGroup(OctreeNode* node)
 {
 	LLVector4a tmp;
 	tmp.splat(0.f);
-	mExtents[0] = mExtents[1] = mObjectBounds[0] = mObjectBounds[0] = mObjectBounds[1] = 
+	mExtents[0] = mExtents[1] = mObjectBounds[0] = mObjectBounds[1] =
 		mObjectExtents[0] = mObjectExtents[1] = tmp;
 	
 	mBounds[0] = node->getCenter();
diff --git a/indra/newview/llviewerpartsim.cpp b/indra/newview/llviewerpartsim.cpp
index 25cf082751fd02ce4a84fa2b0ef2aefd2d9fd24b..e5265f1dcd50f029c3d710206b3fe17b4e1bdab8 100644
--- a/indra/newview/llviewerpartsim.cpp
+++ b/indra/newview/llviewerpartsim.cpp
@@ -662,9 +662,6 @@ void LLViewerPartSim::updateSimulation()
 {
 	static LLFrameTimer update_timer;
 
-	//reset VBO cursor
-	LLVOPartGroup::sVBSlotCursor = 0;
-
 	const F32 dt = llmin(update_timer.getElapsedTimeAndResetF32(), 0.1f);
 
  	if (!(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES)))
diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp
index 3e0cec0f0999e7fb19b05ae4141f28bd03789070..ff7647a7e46917fea43545b3e9ebe60ebc3cdae6 100644
--- a/indra/newview/llviewershadermgr.cpp
+++ b/indra/newview/llviewershadermgr.cpp
@@ -2811,6 +2811,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 			gSkinnedObjectSimpleWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
 			gSkinnedObjectSimpleWaterProgram.mFeatures.hasObjectSkinning = true;
 			gSkinnedObjectSimpleWaterProgram.mFeatures.disableTextureIndex = true;
+			gSkinnedObjectSimpleWaterProgram.mFeatures.hasAlphaMask = true;
 			gSkinnedObjectSimpleWaterProgram.mShaderFiles.clear();
 			gSkinnedObjectSimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleSkinnedV.glsl", GL_VERTEX_SHADER_ARB));
 			gSkinnedObjectSimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
diff --git a/indra/newview/llvograss.cpp b/indra/newview/llvograss.cpp
index 5def0f0c0fd303ec03653e078cf77424cf409b2b..d651d540b9cd89c7fa601303ca4785512ef681c2 100644
--- a/indra/newview/llvograss.cpp
+++ b/indra/newview/llvograss.cpp
@@ -741,7 +741,7 @@ void LLGrassPartition::getGeometry(LLSpatialGroup* group)
 			U32 count = facep->getIndicesCount();
 			LLDrawInfo* info = new LLDrawInfo(start,end,count,offset,facep->getTexture(), 
 				//facep->getTexture(),
-				buffer, fullbright); 
+				buffer, object->isSelected(), fullbright);
 
 			const LLVector4a* exts = group->getObjectExtents();
 			info->mExtents[0] = exts[0];
diff --git a/indra/newview/llvopartgroup.cpp b/indra/newview/llvopartgroup.cpp
index f7b21338f8a37e350c8e7fd171674f2449504ef2..b31afca61da82e4dc202ca84587af4c1cfb55435 100644
--- a/indra/newview/llvopartgroup.cpp
+++ b/indra/newview/llvopartgroup.cpp
@@ -47,11 +47,17 @@
 extern U64MicrosecondsImplicit gFrameTime;
 
 LLPointer<LLVertexBuffer> LLVOPartGroup::sVB = NULL;
-S32 LLVOPartGroup::sVBSlotCursor = 0;
+S32 LLVOPartGroup::sVBSlotFree[];
+S32* LLVOPartGroup::sVBSlotCursor = NULL;
 
 void LLVOPartGroup::initClass()
 {
+	for (S32 i = 0; i < LL_MAX_PARTICLE_COUNT; ++i)
+	{
+		sVBSlotFree[i] = i;
+	}
 	
+	sVBSlotCursor = sVBSlotFree;
 }
 
 //static
@@ -124,12 +130,14 @@ void LLVOPartGroup::destroyGL()
 //static
 S32 LLVOPartGroup::findAvailableVBSlot()
 {
-	if (sVBSlotCursor >= LL_MAX_PARTICLE_COUNT)
+	if (sVBSlotCursor >= sVBSlotFree + LL_MAX_PARTICLE_COUNT)
 	{ //no more available slots
 		return -1;
 	}
 
-	return sVBSlotCursor++;
+	S32 ret = *sVBSlotCursor;
+	sVBSlotCursor++;
+	return ret;
 }
 
 bool ll_is_part_idx_allocated(S32 idx, S32* start, S32* end)
@@ -150,7 +158,7 @@ bool ll_is_part_idx_allocated(S32 idx, S32* start, S32* end)
 //static
 void LLVOPartGroup::freeVBSlot(S32 idx)
 {
-	/*llassert(idx < LL_MAX_PARTICLE_COUNT && idx >= 0);
+	llassert(idx < LL_MAX_PARTICLE_COUNT && idx >= 0);
 	//llassert(sVBSlotCursor > sVBSlotFree);
 	//llassert(ll_is_part_idx_allocated(idx, sVBSlotCursor, sVBSlotFree+LL_MAX_PARTICLE_COUNT));
 
@@ -158,7 +166,7 @@ void LLVOPartGroup::freeVBSlot(S32 idx)
 	{
 		sVBSlotCursor--;
 		*sVBSlotCursor = idx;
-	}*/
+	}
 }
 
 LLVOPartGroup::LLVOPartGroup(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp)
@@ -870,7 +878,7 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group)
 		LLFace* facep = *i;
 		LLAlphaObject* object = (LLAlphaObject*) facep->getViewerObject();
 
-		//if (!facep->isState(LLFace::PARTICLE))
+		if (!facep->isState(LLFace::PARTICLE))
 		{ //set the indices of this face
 			S32 idx = LLVOPartGroup::findAvailableVBSlot();
 			if (idx >= 0)
@@ -879,7 +887,7 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group)
 				facep->setIndicesIndex(idx*6);
 				facep->setVertexBuffer(LLVOPartGroup::sVB);
 				facep->setPoolType(LLDrawPool::POOL_ALPHA);
-				//facep->setState(LLFace::PARTICLE);
+				facep->setState(LLFace::PARTICLE);
 			}
 			else
 			{
@@ -964,7 +972,7 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group)
 			U32 count = facep->getIndicesCount();
 			LLDrawInfo* info = new LLDrawInfo(start,end,count,offset,facep->getTexture(), 
 				//facep->getTexture(),
-				buffer, fullbright); 
+				buffer, object->isSelected(), fullbright);
 
 			const LLVector4a* exts = group->getObjectExtents();
 			info->mExtents[0] = exts[0];
diff --git a/indra/newview/llvopartgroup.h b/indra/newview/llvopartgroup.h
index 2ef8b1c84801659be4c9e9489b42a67c0d0351fe..4e4d6e609dbc486c9b6e657fc9399f72ce7615d0 100644
--- a/indra/newview/llvopartgroup.h
+++ b/indra/newview/llvopartgroup.h
@@ -42,7 +42,8 @@ class LLVOPartGroup : public LLAlphaObject
 
 	//vertex buffer for holding all particles
 	static LLPointer<LLVertexBuffer> sVB;
-	static S32 sVBSlotCursor;
+	static S32 sVBSlotFree[LL_MAX_PARTICLE_COUNT];
+	static S32 *sVBSlotCursor;
 
 	static void initClass();
 	static void restoreGL();
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 3f442051095cc61006bf74cbc67c80e78ae13526..2f2a28daff703a221e104f36e944578f9b92b9c1 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -84,6 +84,7 @@
 #include "llinventorytype.h"
 #include "llviewerinventory.h"
 #include "llcallstack.h"
+#include "llsculptidsize.h"
 
 const F32 FORCE_SIMPLE_RENDER_AREA = 512.f;
 const F32 FORCE_CULL_AREA = 8.f;
@@ -256,6 +257,8 @@ void LLVOVolume::markDead()
 {
 	if (!mDead)
 	{
+		LLSculptIDSize::instance().rem(getVolume()->getParams().getSculptID());
+
 		if(getMDCImplCount() > 0)
 		{
 			LLMediaDataClientObject::ptr_t obj = new LLMediaDataClientObjectImpl(const_cast<LLVOVolume*>(this), false);
@@ -967,13 +970,14 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams &params_in, const S32 detail, bo
 		// if it's a mesh
 		if ((volume_params.getSculptType() & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH)
 		{ //meshes might not have all LODs, get the force detail to best existing LOD
-			LLUUID mesh_id = volume_params.getSculptID();
-
-			lod = gMeshRepo.getActualMeshLOD(volume_params, lod);
-			if (lod == -1)
+			if (NO_LOD != lod)
 			{
-				is404 = TRUE;
-				lod = 0;
+				lod = gMeshRepo.getActualMeshLOD(volume_params, lod);
+				if (lod == -1)
+				{
+					is404 = TRUE;
+					lod = 0;
+				}
 			}
 		}
 	}
@@ -1070,12 +1074,13 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams &params_in, const S32 detail, bo
 				LLFace::cacheFaceInVRAM(face);
 			}
 		}
-		
 
 		return TRUE;
 	}
-
-
+	else if (NO_LOD == lod) 
+	{
+		LLSculptIDSize::instance().resetSizeSum(volume_params.getSculptID());
+	}
 
 	return FALSE;
 }
@@ -1248,19 +1253,19 @@ void LLVOVolume::sculpt()
 	}
 }
 
-S32	LLVOVolume::computeLODDetail(F32 distance, F32 radius)
+S32	LLVOVolume::computeLODDetail(F32 distance, F32 radius, F32 lod_factor)
 {
 	S32	cur_detail;
-    if (LLPipeline::sDynamicLOD)
-    {
-        // We've got LOD in the profile, and in the twist.  Use radius.
-        F32 tan_angle = (LLVOVolume::sLODFactor*radius)/distance;
-        cur_detail = LLVolumeLODGroup::getDetailFromTan(ll_round(tan_angle, 0.01f));
-    }
-    else
-    {
-        cur_detail = llclamp((S32) (sqrtf(radius)*LLVOVolume::sLODFactor*4.f), 0, 3);		
-    }
+	if (LLPipeline::sDynamicLOD)
+	{
+		// We've got LOD in the profile, and in the twist.  Use radius.
+		F32 tan_angle = (lod_factor*radius)/distance;
+		cur_detail = LLVolumeLODGroup::getDetailFromTan(ll_round(tan_angle, 0.01f));
+	}
+	else
+	{
+		cur_detail = llclamp((S32) (sqrtf(radius)*lod_factor*4.f), 0, 3);
+	}
 	return cur_detail;
 }
 
@@ -1275,6 +1280,7 @@ BOOL LLVOVolume::calcLOD()
 	
 	F32 radius;
 	F32 distance;
+	F32 lod_factor = LLVOVolume::sLODFactor;
 
 	if (mDrawable->isState(LLDrawable::RIGGED))
 	{
@@ -1320,11 +1326,16 @@ BOOL LLVOVolume::calcLOD()
 		distance *= rampDist;
 	}
 	
-	// DON'T Compensate for field of view changing on FOV zoom.
+
 	distance *= F_PI/3.f;
 
-	cur_detail = computeLODDetail(ll_round(distance, 0.01f), 
-                                  ll_round(radius, 0.01f));
+	static LLCachedControl<bool> ignore_fov_zoom(gSavedSettings,"IgnoreFOVZoomForLODs");
+	if(!ignore_fov_zoom)
+	{
+		lod_factor *= DEFAULT_FIELD_OF_VIEW / LLViewerCamera::getInstance()->getDefaultFOV();
+	}
+
+	cur_detail = computeLODDetail(ll_round(distance, 0.01f), ll_round(radius, 0.01f), lod_factor);
 
     if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TRIANGLE_COUNT) && mDrawable->getFace(0))
     {
@@ -1367,7 +1378,16 @@ BOOL LLVOVolume::updateLOD()
 		return FALSE;
 	}
 	
-	BOOL lod_changed = calcLOD();
+	BOOL lod_changed = FALSE;
+
+	if (!LLSculptIDSize::instance().isUnloaded(getVolume()->getParams().getSculptID())) 
+	{
+		lod_changed = calcLOD();
+	}
+	else
+	{
+		return FALSE;
+	}
 
 	if (lod_changed)
 	{
@@ -1868,6 +1888,11 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable)
 		dirtySpatialGroup(drawable->isState(LLDrawable::IN_REBUILD_Q1));
 		compiled = TRUE;
 		lodOrSculptChanged(drawable, compiled);
+		
+		if(drawable->isState(LLDrawable::REBUILD_RIGGED | LLDrawable::RIGGED)) 
+		{
+			updateRiggedVolume(false);
+		}
 		genBBoxes(FALSE);
 	}
 	// it has its own drawable (it's moved) or it has changed UVs or it has changed xforms from global<->local
@@ -2286,7 +2311,7 @@ bool LLVOVolume::notifyAboutMissingAsset(LLViewerTexture *texture)
 	//setup new materials
 	for(map_te_material::const_iterator it = new_material.begin(), end = new_material.end(); it != end; ++it)
 	{
-		LLMaterialMgr::getInstance()->put(getID(), it->first, *it->second);
+		LLMaterialMgr::getInstance()->setLocalMaterial(getRegion()->getRegionID(), it->second);
 		LLViewerObject::setTEMaterialParams(it->first, it->second);
 	}
 
@@ -2389,7 +2414,7 @@ S32 LLVOVolume::setTEMaterialParams(const U8 te, const LLMaterialPtr pMaterialPa
 
 		if(new_material) {
 			pMaterial = new_material;
-			LLMaterialMgr::getInstance()->put(getID(),te,*pMaterial);
+			LLMaterialMgr::getInstance()->setLocalMaterial(getRegion()->getRegionID(), pMaterial);
 		}
 	}
 
@@ -4651,7 +4676,7 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons
 
 			LLVector4a* pos = dst_face.mPositions;
 
-			if( pos && weight && dst_face.mExtents )
+			if (pos && dst_face.mExtents)
 			{
 				LL_RECORD_BLOCK_TIME(FTM_SKIN_RIGGED);
 
@@ -4852,7 +4877,9 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
 		LL_WARNS_ONCE("RenderMaterials") << "Oh no! No binormals for this alpha blended face!" << LL_ENDL;
 	}
 
-	if (facep->getViewerObject()->isSelected() && LLSelectMgr::getInstance()->mHideSelectedObjects)
+	bool selected = facep->getViewerObject()->isSelected();
+
+	if (selected && LLSelectMgr::getInstance()->mHideSelectedObjects)
 	{
 		return;
 	}
@@ -4949,7 +4976,7 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
 			batchable = true;
 		}
 	}
-	
+
 	if (idx >= 0 && 
 		draw_vec[idx]->mVertexBuffer == facep->getVertexBuffer() &&
 		draw_vec[idx]->mEnd == facep->getGeomIndex()-1 &&
@@ -4965,7 +4992,8 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
 		(!mat || (draw_vec[idx]->mShiny == shiny)) && // need to break batches when a material is shared, but legacy settings are different
 		draw_vec[idx]->mTextureMatrix == tex_mat &&
 		draw_vec[idx]->mModelMatrix == model_mat &&
-		draw_vec[idx]->mShaderMask == shader_mask)
+		draw_vec[idx]->mShaderMask == shader_mask &&
+		draw_vec[idx]->mSelected == selected)
 	{
 		draw_vec[idx]->mCount += facep->getIndicesCount();
 		draw_vec[idx]->mEnd += facep->getGeomCount();
@@ -4987,7 +5015,7 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
 		U32 offset = facep->getIndicesStart();
 		U32 count = facep->getIndicesCount();
 		LLPointer<LLDrawInfo> draw_info = new LLDrawInfo(start,end,count,offset, tex, 
-			facep->getVertexBuffer(), fullbright, bump); 
+			facep->getVertexBuffer(), selected, fullbright, bump);
 		draw_info->mGroup = group;
 		draw_info->mVSize = facep->getVirtualSize();
 		draw_vec.push_back(draw_info);
@@ -5014,26 +5042,25 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
 
 		if (mat)
 		{
-				draw_info->mMaterialID = mat_id;
+			draw_info->mMaterialID = mat_id;
 
-				// We have a material.  Update our draw info accordingly.
+			// We have a material.  Update our draw info accordingly.
 				
-				if (!mat->getSpecularID().isNull())
-				{
-					LLVector4 specColor;
-					specColor.mV[0] = mat->getSpecularLightColor().mV[0] * (1.f / 255.f);
-					specColor.mV[1] = mat->getSpecularLightColor().mV[1] * (1.f / 255.f);
-					specColor.mV[2] = mat->getSpecularLightColor().mV[2] * (1.f / 255.f);
-					specColor.mV[3] = mat->getSpecularLightExponent() * (1.f / 255.f);
-					draw_info->mSpecColor = specColor;
-					draw_info->mEnvIntensity = mat->getEnvironmentIntensity() * (1.f / 255.f);
-					draw_info->mSpecularMap = facep->getViewerObject()->getTESpecularMap(facep->getTEOffset());
-				}
+			if (!mat->getSpecularID().isNull())
+			{
+				LLVector4 specColor;
+				specColor.mV[0] = mat->getSpecularLightColor().mV[0] * (1.f / 255.f);
+				specColor.mV[1] = mat->getSpecularLightColor().mV[1] * (1.f / 255.f);
+				specColor.mV[2] = mat->getSpecularLightColor().mV[2] * (1.f / 255.f);
+				specColor.mV[3] = mat->getSpecularLightExponent() * (1.f / 255.f);
+				draw_info->mSpecColor = specColor;
+				draw_info->mEnvIntensity = mat->getEnvironmentIntensity() * (1.f / 255.f);
+				draw_info->mSpecularMap = facep->getViewerObject()->getTESpecularMap(facep->getTEOffset());
+			}
 
-				draw_info->mAlphaMaskCutoff = mat->getAlphaMaskCutoff() * (1.f / 255.f);
-				draw_info->mDiffuseAlphaMode = mat->getDiffuseAlphaMode();
-				draw_info->mNormalMap = facep->getViewerObject()->getTENormalMap(facep->getTEOffset());
-				
+			draw_info->mAlphaMaskCutoff = mat->getAlphaMaskCutoff() * (1.f / 255.f);
+			draw_info->mDiffuseAlphaMode = mat->getDiffuseAlphaMode();
+			draw_info->mNormalMap = facep->getViewerObject()->getTENormalMap(facep->getTEOffset());
 		}
 		else 
 		{
@@ -5104,6 +5131,81 @@ static LLDrawPoolAvatar* get_avatar_drawpool(LLViewerObject* vobj)
 	return NULL;
 }
 
+void handleRenderAutoMuteByteLimitChanged(const LLSD& new_value)
+{
+	static LLCachedControl<U32> render_auto_mute_byte_limit(gSavedSettings, "RenderAutoMuteByteLimit", 0U);
+
+	if (0 != render_auto_mute_byte_limit)
+	{
+		//for unload
+		LLSculptIDSize::container_BY_SIZE_view::iterator
+			itL = LLSculptIDSize::instance().getSizeInfo().get<LLSculptIDSize::tag_BY_SIZE>().lower_bound(render_auto_mute_byte_limit),
+			itU = LLSculptIDSize::instance().getSizeInfo().get<LLSculptIDSize::tag_BY_SIZE>().end();
+
+		for (; itL != itU; ++itL)
+		{
+			const LLSculptIDSize::Info &nfo = *itL;
+			LLVOVolume *pVVol = nfo.getPtrLLDrawable()->getVOVolume();
+			if (pVVol
+				&& !pVVol->isDead()
+				&& pVVol->isAttachment()
+				&& !pVVol->getAvatar()->isSelf()
+				&& LLVOVolume::NO_LOD != pVVol->getLOD()
+				)
+			{
+				//postponed
+				pVVol->markForUnload();
+				LLSculptIDSize::instance().addToUnloaded(nfo.getSculptId());
+			}
+		}
+
+		//for load if it was unload
+		itL = LLSculptIDSize::instance().getSizeInfo().get<LLSculptIDSize::tag_BY_SIZE>().begin();
+		itU = LLSculptIDSize::instance().getSizeInfo().get<LLSculptIDSize::tag_BY_SIZE>().upper_bound(render_auto_mute_byte_limit);
+
+		for (; itL != itU; ++itL)
+		{
+			const LLSculptIDSize::Info &nfo = *itL;
+			LLVOVolume *pVVol = nfo.getPtrLLDrawable()->getVOVolume();
+			if (pVVol
+				&& !pVVol->isDead()
+				&& pVVol->isAttachment()
+				&& !pVVol->getAvatar()->isSelf()
+				&& LLVOVolume::NO_LOD == pVVol->getLOD()
+				)
+			{
+				LLSculptIDSize::instance().remFromUnloaded(nfo.getSculptId());
+				pVVol->updateLOD();
+				pVVol->markForUpdate(TRUE);
+			}
+		}
+	}
+	else
+	{
+		LLSculptIDSize::instance().clearUnloaded();
+
+		LLSculptIDSize::container_BY_SIZE_view::iterator
+			itL = LLSculptIDSize::instance().getSizeInfo().get<LLSculptIDSize::tag_BY_SIZE>().begin(),
+			itU = LLSculptIDSize::instance().getSizeInfo().get<LLSculptIDSize::tag_BY_SIZE>().end();
+
+		for (; itL != itU; ++itL)
+		{
+			const LLSculptIDSize::Info &nfo = *itL;
+			LLVOVolume *pVVol = nfo.getPtrLLDrawable()->getVOVolume();
+			if (pVVol
+				&& !pVVol->isDead()
+				&& pVVol->isAttachment()
+				&& !pVVol->getAvatar()->isSelf()
+				&& LLVOVolume::NO_LOD == pVVol->getLOD()
+				) 
+			{
+				pVVol->updateLOD();
+				pVVol->markForUpdate(TRUE);
+			}
+		}
+	}
+}
+
 void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 {
 	if (group->changeLOD())
@@ -5679,13 +5781,19 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 		fullbright_mask = fullbright_mask | LLVertexBuffer::MAP_TEXTURE_INDEX;
 	}
 
-	genDrawInfo(group, simple_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sSimpleFaces, simple_count, FALSE, batch_textures, FALSE);
-	genDrawInfo(group, fullbright_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sFullbrightFaces, fullbright_count, FALSE, batch_textures);
-	genDrawInfo(group, alpha_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sAlphaFaces, alpha_count, TRUE, batch_textures);
-	genDrawInfo(group, bump_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sBumpFaces, bump_count, FALSE, FALSE);
-	genDrawInfo(group, norm_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sNormFaces, norm_count, FALSE, FALSE);
-	genDrawInfo(group, spec_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sSpecFaces, spec_count, FALSE, FALSE);
-	genDrawInfo(group, normspec_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sNormSpecFaces, normspec_count, FALSE, FALSE);
+	group->mGeometryBytes = 0;
+
+	U32 geometryBytes = 0;
+
+	geometryBytes += genDrawInfo(group, simple_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sSimpleFaces, simple_count, FALSE, batch_textures, FALSE);
+	geometryBytes += genDrawInfo(group, fullbright_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sFullbrightFaces, fullbright_count, FALSE, batch_textures);
+	geometryBytes += genDrawInfo(group, alpha_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sAlphaFaces, alpha_count, TRUE, batch_textures);
+	geometryBytes += genDrawInfo(group, bump_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sBumpFaces, bump_count, FALSE, FALSE);
+	geometryBytes += genDrawInfo(group, norm_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sNormFaces, norm_count, FALSE, FALSE);
+	geometryBytes += genDrawInfo(group, spec_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sSpecFaces, spec_count, FALSE, FALSE);
+	geometryBytes += genDrawInfo(group, normspec_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sNormSpecFaces, normspec_count, FALSE, FALSE);
+
+	group->mGeometryBytes = geometryBytes;
 
 	if (!LLPipeline::sDelayVBUpdate)
 	{
@@ -5738,7 +5846,6 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group)
 			if (drawablep && !drawablep->isDead() && drawablep->isState(LLDrawable::REBUILD_ALL) && !drawablep->isState(LLDrawable::RIGGED) )
 			{
 				LLVOVolume* vobj = drawablep->getVOVolume();
-
                 if (debugLoggingEnabled("AnimatedObjectsLinkset"))
                 {
                     if (vobj->isAnimatedObject() && vobj->isRiggedMesh())
@@ -5748,6 +5855,7 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group)
                         LL_DEBUGS("AnimatedObjectsLinkset") << vobj_name << " rebuildMesh, tris " << est_tris << LL_ENDL; 
                     }
                 }
+				if (vobj->isNoLOD()) continue;
 
 				vobj->preRebuild();
 
@@ -5881,10 +5989,11 @@ static LLTrace::BlockTimerStatHandle FTM_GEN_DRAW_INFO_RESIZE_VB("Resize VB");
 
 
 
-void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace** faces, U32 face_count, BOOL distance_sort, BOOL batch_textures, BOOL no_materials)
+U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace** faces, U32 face_count, BOOL distance_sort, BOOL batch_textures, BOOL no_materials)
 {
 	LL_RECORD_BLOCK_TIME(FTM_REBUILD_VOLUME_GEN_DRAW_INFO);
 
+	U32 geometryBytes = 0;
 	U32 buffer_usage = group->mBufferUsage;
 	
 	static LLCachedControl<bool> use_transform_feedback(gSavedSettings, "RenderUseTransformFeedback", false);
@@ -6134,7 +6243,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFac
 
 		if (buffer)
 		{
-			group->mGeometryBytes += buffer->getSize() + buffer->getIndicesSize();
+			geometryBytes += buffer->getSize() + buffer->getIndicesSize();
 			buffer_map[mask][*face_iter].push_back(buffer);
 		}
 
@@ -6422,7 +6531,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFac
 					}
 					else
 					{
-					registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT);
+						registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT);
 					}
 					if (LLPipeline::sRenderDeferred && !hud_group && LLPipeline::sRenderBump && use_legacy_bump)
 					{ //if this is the deferred render and a bump map is present, register in post deferred bump
@@ -6444,8 +6553,8 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFac
 						}
 						else
 						{
-						registerFace(group, facep, LLRenderPass::PASS_SIMPLE);
-					}
+							registerFace(group, facep, LLRenderPass::PASS_SIMPLE);
+						}
 				}
 				}
 				
@@ -6490,6 +6599,8 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFac
 	{
 		group->mBufferMap[mask][i->first] = i->second;
 	}
+
+	return geometryBytes;
 }
 
 void LLGeometryManager::addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32 &index_count)
@@ -6556,4 +6667,3 @@ void LLHUDPartition::shift(const LLVector4a &offset)
 {
 	//HUD objects don't shift with region crossing.  That would be silly.
 }
-
diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h
index 2ba73b9d860ca4bc60cad796b3dfa912a66eaa44..446d4a3d37e07ff6b4d78d69f062eb78ac593ca4 100644
--- a/indra/newview/llvovolume.h
+++ b/indra/newview/llvovolume.h
@@ -35,6 +35,8 @@
 #include "m3math.h"		// LLMatrix3
 #include "m4math.h"		// LLMatrix4
 #include <map>
+#include <set>
+
 
 class LLViewerTextureAnim;
 class LLDrawPool;
@@ -127,7 +129,9 @@ class LLVOVolume : public LLViewerObject
 
 				void	generateSilhouette(LLSelectNode* nodep, const LLVector3& view_point);
 	/*virtual*/	BOOL	setParent(LLViewerObject* parent);
-				S32		getLOD() const							{ return mLOD; }
+				S32		getLOD() const						{ return mLOD; }
+				void	setNoLOD()							{ mLOD = NO_LOD; mLODChanged = TRUE; }
+				bool	isNoLOD() const						{ return NO_LOD == mLOD; }
 	const LLVector3		getPivotPositionAgent() const;
 	const LLMatrix4&	getRelativeXform() const				{ return mRelativeXform; }
 	const LLMatrix3&	getRelativeXformInvTrans() const		{ return mRelativeXformInvTrans; }
@@ -164,6 +168,7 @@ class LLVOVolume : public LLViewerObject
 				const LLMatrix4& getWorldMatrix(LLXformMatrix* xform) const;
 
 				void	markForUpdate(BOOL priority);
+				void	markForUnload()							{ LLViewerObject::markForUnload(TRUE); mVolumeChanged = TRUE; }
 				void    faceMappingChanged()                    { mFaceMappingChanged=TRUE; };
 
 	/*virtual*/ void	onShift(const LLVector4a &shift_vector); // Called when the drawable shifts
@@ -351,7 +356,7 @@ class LLVOVolume : public LLViewerObject
 	void clearRiggedVolume();
 
 protected:
-	S32	computeLODDetail(F32	distance, F32 radius);
+	S32	computeLODDetail(F32 distance, F32 radius, F32 lod_factor);
 	BOOL calcLOD();
 	LLFace* addFace(S32 face_index);
 	void updateTEData();
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index 740da863af059838c18be82b91e2478228b0f7ec..4bfa749d9fe918dce4df62c115af078789aad8e3 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -2656,7 +2656,7 @@ void LLPipeline::downsampleDepthBuffer(LLRenderTarget& source, LLRenderTarget& d
 	{
 		scratch_space->copyContents(source, 
 									0, 0, source.getWidth(), source.getHeight(), 
-									0, 0, scratch_space->getWidth(), scratch_space->getHeight(), GL_DEPTH_BUFFER_BIT, GL_NEAREST);
+									0, 0, scratch_space->getWidth(), scratch_space->getHeight(), GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
 	}
 
 	dest.bindTarget();
@@ -3031,6 +3031,12 @@ void LLPipeline::updateGeom(F32 max_dtime)
 				}
 			}
 
+			if (drawablep->isUnload())
+			{
+				drawablep->unload();
+				drawablep->clearState(LLDrawable::FOR_UNLOAD);
+			}
+
 			if (updateDrawableGeom(drawablep, TRUE))
 			{
 				drawablep->clearState(LLDrawable::IN_REBUILD_Q1);
@@ -3436,6 +3442,7 @@ void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result)
 	if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD)
 	{
 		LLSpatialGroup* last_group = NULL;
+		BOOL fov_changed = LLViewerCamera::getInstance()->isDefaultFOVChanged();
 		for (LLCullResult::bridge_iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i)
 		{
 			LLCullResult::bridge_iterator cur_iter = i;
@@ -3449,7 +3456,7 @@ void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result)
 
 			if (!bridge->isDead() && group && !group->isOcclusionState(LLSpatialGroup::OCCLUDED))
 			{
-				stateSort(bridge, camera);
+				stateSort(bridge, camera, fov_changed);
 			}
 
 			if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD &&
@@ -3521,9 +3528,9 @@ void LLPipeline::stateSort(LLSpatialGroup* group, LLCamera& camera)
 
 }
 
-void LLPipeline::stateSort(LLSpatialBridge* bridge, LLCamera& camera)
+void LLPipeline::stateSort(LLSpatialBridge* bridge, LLCamera& camera, BOOL fov_changed)
 {
-	if (bridge->getSpatialGroup()->changeLOD())
+	if (bridge->getSpatialGroup()->changeLOD() || fov_changed)
 	{
 		bool force_update = false;
 		bridge->updateDistance(camera, force_update);
@@ -4589,12 +4596,6 @@ void LLPipeline::renderGeomDeferred(LLCamera& camera)
 
 	LLGLEnable cull(GL_CULL_FACE);
 
-	LLGLEnable stencil(GL_STENCIL_TEST);
-	glStencilFunc(GL_ALWAYS, 1, 0xFFFFFFFF);
-	stop_glerror();
-	glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
-	stop_glerror();
-
 	for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
 	{
 		LLDrawPool *poolp = *iter;
@@ -8150,7 +8151,7 @@ void LLPipeline::renderBloom(bool for_snapshot, F32 zoom_factor, int subfield)
 	if (LLRenderTarget::sUseFBO)
 	{ //copy depth buffer from mScreen to framebuffer
 		LLRenderTarget::copyContentsToFramebuffer(mScreen, 0, 0, mScreen.getWidth(), mScreen.getHeight(), 
-			0, 0, mScreen.getWidth(), mScreen.getHeight(), GL_DEPTH_BUFFER_BIT, GL_NEAREST);
+			0, 0, mScreen.getWidth(), mScreen.getHeight(), GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
 	}
 	
 
@@ -9031,7 +9032,7 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target)
 		{
 			LLGLDepthTest depth(GL_TRUE);
 			mDeferredDepth.copyContents(mDeferredScreen, 0, 0, mDeferredScreen.getWidth(), mDeferredScreen.getHeight(),
-							0, 0, mDeferredDepth.getWidth(), mDeferredDepth.getHeight(), GL_DEPTH_BUFFER_BIT, GL_NEAREST);	
+							0, 0, mDeferredDepth.getWidth(), mDeferredDepth.getHeight(), GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);	
 		}
 
 		LLGLEnable multisample(RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0);
@@ -10006,7 +10007,19 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
 				}
 				else
 				{
-				renderGeom(camera);
+					renderGeom(camera);
+
+					if (LLGLSLShader::sNoFixedFunction)
+					{
+						gUIProgram.bind();
+					}
+					
+					LLWorld::getInstance()->renderPropertyLines();
+					
+					if (LLGLSLShader::sNoFixedFunction)
+					{
+						gUIProgram.unbind();
+					}
 				}
 
 				if (LLPipeline::sRenderDeferred && materials_in_water)
@@ -10129,7 +10142,7 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera
 	}
 	LLPipeline::sShadowRender = true;
 	
-	U32 types[] = { 
+	static const U32 types[] = { 
 		LLRenderPass::PASS_SIMPLE, 
 		LLRenderPass::PASS_FULLBRIGHT, 
 		LLRenderPass::PASS_SHINY, 
@@ -11634,7 +11647,7 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
 
 	avatar->setImpostorDim(tdim);
 
-	LLVOAvatar::sUseImpostors = true; // @TODO ???
+	LLVOAvatar::sUseImpostors = (0 != LLVOAvatar::sMaxNonImpostors);
 	sUseOcclusion = occlusion;
 	sReflectionRender = false;
 	sImpostorRender = false;
diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h
index d7fbbdafb6bbfe0d417180d34e1e7c0912907736..85c13487ee39c40340cc0ae3e0fea7b380420fdb 100644
--- a/indra/newview/pipeline.h
+++ b/indra/newview/pipeline.h
@@ -254,7 +254,7 @@ class LLPipeline
 
 	void stateSort(LLCamera& camera, LLCullResult& result);
 	void stateSort(LLSpatialGroup* group, LLCamera& camera);
-	void stateSort(LLSpatialBridge* bridge, LLCamera& camera);
+	void stateSort(LLSpatialBridge* bridge, LLCamera& camera, BOOL fov_changed = FALSE);
 	void stateSort(LLDrawable* drawablep, LLCamera& camera);
 	void postSort(LLCamera& camera);
 	void forAllVisibleDrawables(void (*func)(LLDrawable*));