diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..6d296d7a24cd416f33970eca5d76f0cdbdcf18ce
--- /dev/null
+++ b/.pre-commit-config.yaml
@@ -0,0 +1,17 @@
+repos:
+  - repo: https://bitbucket.org/lindenlab/git-hooks.git 
+    rev: v1.0.0-beta2
+    hooks:
+      - id: opensource-license
+      - id: jira-issue 
+      - id: llsd
+      - id: no-trigraphs
+      - id: copyright
+      - id: end-of-file
+        files: \.(cpp|c|h|py|glsl|cmake|txt)$
+        exclude: language.txt
+  - repo: https://github.com/pre-commit/pre-commit-hooks
+    rev: v2.5.0
+    hooks:
+      - id: check-xml
+      - id: mixed-line-ending
diff --git a/autobuild.xml b/autobuild.xml
index a8c35f48833d293c6be7b0762edb0d8ca295b1c7..45141cae5321bb8f000408b27af65596ecb05775 100644
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -2107,18 +2107,18 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>95cb09a712b7b61e992fe68ab7bf8c72</string>
+              <string>d6e7ab8483c348f223fd24028e27a52f</string>
               <key>hash_algorithm</key>
               <string>md5</string>
               <key>url</key>
-              <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/92744/837149/llca-202201010217.567162-common-567162.tar.bz2</string>
+              <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/93933/844890/llca-202202010217.567974-common-567974.tar.bz2</string>
             </map>
             <key>name</key>
             <string>common</string>
           </map>
         </map>
         <key>version</key>
-        <string>202201010217.567162</string>
+        <string>202202010217.567974</string>
       </map>
       <key>llphysicsextensions_source</key>
       <map>
@@ -3298,9 +3298,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>33ed1bb3e24fbd3462da04fb3e917e94</string>
+              <string>1dda5fb3bb649b0ab5a93f22df7cb11e</string>
               <key>url</key>
-              <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/94814/850320/viewer_manager-3.0.568552-darwin64-568552.tar.bz2</string>
+              <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/96998/862110/viewer_manager-3.0.569958-darwin64-569958.tar.bz2</string>
             </map>
             <key>name</key>
             <string>darwin64</string>
@@ -3322,9 +3322,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>2ad8e04965ac8bddb7d351abe09bee07</string>
+              <string>30d1386d0a6883d898fc56757a789b8b</string>
               <key>url</key>
-              <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/94813/850316/viewer_manager-3.0.568552-windows-568552.tar.bz2</string>
+              <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/97002/862130/viewer_manager-3.0.569958-windows-569958.tar.bz2</string>
             </map>
             <key>name</key>
             <string>windows</string>
@@ -3335,7 +3335,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
         <key>source_type</key>
         <string>hg</string>
         <key>version</key>
-        <string>3.0.568552</string>
+        <string>3.0.569958</string>
       </map>
       <key>vlc-bin</key>
       <map>
diff --git a/indra/llaudio/llaudioengine.cpp b/indra/llaudio/llaudioengine.cpp
index d35f2499730a14a2ed159388e697d78f9db89e62..e0ebbb76bd30770759ba12c201e4b29549aa74d0 100644
--- a/indra/llaudio/llaudioengine.cpp
+++ b/indra/llaudio/llaudioengine.cpp
@@ -1402,6 +1402,15 @@ bool LLAudioSource::setupChannel()
 	return true;
 }
 
+void LLAudioSource::stop()
+{
+    play(LLUUID::null);
+    if (mCurrentDatap)
+    {
+        // always reset data if something wants us to stop
+        mCurrentDatap = nullptr;
+    }
+}
 
 bool LLAudioSource::play(const LLUUID &audio_uuid)
 {
diff --git a/indra/llaudio/llaudioengine.h b/indra/llaudio/llaudioengine.h
index 577b36d667f895fe2535a6750ed46b14a31f156f..b5fd4c27a19d9954ec85d47233e96eba247baa6d 100644
--- a/indra/llaudio/llaudioengine.h
+++ b/indra/llaudio/llaudioengine.h
@@ -304,7 +304,13 @@ class LLAudioSource
 	LLAudioBuffer *getCurrentBuffer();
 
 	bool setupChannel();
-	bool play(const LLUUID &audio_id);	// Start the audio source playing
+
+    // Stop the audio source, reset audio id even if muted
+    void stop();
+
+    // Start the audio source playing,
+    // takes mute into account to preserve previous id if nessesary
+    bool play(const LLUUID &audio_id);
 
 	bool hasPendingPreloads() const;	// Has preloads that haven't been done yet
 
diff --git a/indra/llcommon/llcoros.cpp b/indra/llcommon/llcoros.cpp
index 75fc0fec99d19942c8859130c6f29b7160d1da4e..c2d353b0fc9b89ee44bfb43335bb4fdabf936851 100644
--- a/indra/llcommon/llcoros.cpp
+++ b/indra/llcommon/llcoros.cpp
@@ -249,14 +249,25 @@ std::string LLCoros::launch(const std::string& prefix, const callable_t& callabl
     // protected_fixedsize_stack sets a guard page past the end of the new
     // stack so that stack underflow will result in an access violation
     // instead of weird, subtle, possibly undiagnosed memory stomps.
-    boost::fibers::fiber newCoro(boost::fibers::launch::dispatch,
-                                 std::allocator_arg,
-                                 boost::fibers::protected_fixedsize_stack(mStackSize),
-                                 [this, &name, &callable](){ toplevel(name, callable); });
-    // You have two choices with a fiber instance: you can join() it or you
-    // can detach() it. If you try to destroy the instance before doing
-    // either, the program silently terminates. We don't need this handle.
-    newCoro.detach();
+
+    try
+    {
+        boost::fibers::fiber newCoro(boost::fibers::launch::dispatch,
+            std::allocator_arg,
+            boost::fibers::protected_fixedsize_stack(mStackSize),
+            [this, &name, &callable]() { toplevel(name, callable); });
+
+        // You have two choices with a fiber instance: you can join() it or you
+        // can detach() it. If you try to destroy the instance before doing
+        // either, the program silently terminates. We don't need this handle.
+        newCoro.detach();
+    }
+    catch (std::bad_alloc&)
+    {
+        // Out of memory on stack allocation?
+        LL_ERRS("LLCoros") << "Bad memory allocation in LLCoros::launch(" << prefix << ")!" << LL_ENDL;
+    }
+
     return name;
 }
 
diff --git a/indra/llcommon/lleventcoro.cpp b/indra/llcommon/lleventcoro.cpp
index 995356dc520197e4e5d8a3fad20f13229621a42f..067b5e6fbc9737f88d655268d051cd42107d9bfa 100644
--- a/indra/llcommon/lleventcoro.cpp
+++ b/indra/llcommon/lleventcoro.cpp
@@ -101,7 +101,7 @@ void storeToLLSDPath(LLSD& dest, const LLSD& path, const LLSD& value)
     }
 
     // Drill down to where we should store 'value'.
-    llsd::drill(dest, path) = value;
+    llsd::drill_ref(dest, path) = value;
 }
 
 } // anonymous
diff --git a/indra/llcommon/llexception.cpp b/indra/llcommon/llexception.cpp
index b584b0ff8b53c2a4efb58e40f4d4aef210fb1466..46560b5e4ce39ac7c12dc45b7ae1d080448090d7 100644
--- a/indra/llcommon/llexception.cpp
+++ b/indra/llcommon/llexception.cpp
@@ -97,6 +97,11 @@ static const U32 STATUS_MSC_EXCEPTION = 0xE06D7363; // compiler specific
 
 U32 msc_exception_filter(U32 code, struct _EXCEPTION_POINTERS *exception_infop)
 {
+    const auto stack = to_string(boost::stacktrace::stacktrace());
+    LL_WARNS() << "SEH Exception handled (that probably shouldn't be): Code " << code 
+        << "\n Stack trace: \n" 
+        << stack << LL_ENDL;
+
     if (code == STATUS_MSC_EXCEPTION)
     {
         // C++ exception, go on
diff --git a/indra/llcommon/llprocessor.cpp b/indra/llcommon/llprocessor.cpp
index 5d16a4b74d3b5ad306ec13f2a90ba57dd01de2e8..818df07bb2f45237f884f6632f9a770faf5d2d51 100644
--- a/indra/llcommon/llprocessor.cpp
+++ b/indra/llcommon/llprocessor.cpp
@@ -44,20 +44,6 @@
 
 #include "llsd.h"
 
-#if LL_MSVC && _M_X64
-#      define LL_X86_64 1
-#      define LL_X86 1
-#elif LL_MSVC && _M_IX86
-#      define LL_X86 1
-#elif LL_GNUC && ( defined(__amd64__) || defined(__x86_64__) )
-#      define LL_X86_64 1
-#      define LL_X86 1
-#elif LL_GNUC && ( defined(__i386__) )
-#      define LL_X86 1
-#elif LL_GNUC && ( defined(__powerpc__) || defined(__ppc__) )
-#      define LL_PPC 1
-#endif
-
 class LLProcessorInfoImpl; // foward declaration for the mImpl;
 
 namespace 
diff --git a/indra/llcommon/llprocessor.h b/indra/llcommon/llprocessor.h
index 90e5bc59ee24638243342e814de4a761006f13c1..b77eb22c3ab97bdefa13264919d6e4ec33047661 100644
--- a/indra/llcommon/llprocessor.h
+++ b/indra/llcommon/llprocessor.h
@@ -29,6 +29,20 @@
 #define LLPROCESSOR_H
 #include "llunits.h"
 
+#if LL_MSVC && _M_X64
+#      define LL_X86_64 1
+#      define LL_X86 1
+#elif LL_MSVC && _M_IX86
+#      define LL_X86 1
+#elif LL_GNUC && ( defined(__amd64__) || defined(__x86_64__) )
+#      define LL_X86_64 1
+#      define LL_X86 1
+#elif LL_GNUC && ( defined(__i386__) )
+#      define LL_X86 1
+#elif LL_GNUC && ( defined(__powerpc__) || defined(__ppc__) )
+#      define LL_PPC 1
+#endif
+
 class LLProcessorInfoImpl;
 
 class LL_COMMON_API LLProcessorInfo
diff --git a/indra/llcommon/llsdutil.cpp b/indra/llcommon/llsdutil.cpp
index c2fe15e9b76dc345ac32e2817e79b366acf03eea..8e90d1e8b89f76dafba377d1efaa9f538bc9da5c 100644
--- a/indra/llcommon/llsdutil.cpp
+++ b/indra/llcommon/llsdutil.cpp
@@ -29,6 +29,7 @@
 #include "linden_common.h"
 
 #include "llsdutil.h"
+#include <sstream>
 
 #if LL_WINDOWS
 #	define WIN32_LEAN_AND_MEAN
@@ -876,7 +877,7 @@ bool llsd_equals(const LLSD& lhs, const LLSD& rhs, int bits)
 namespace llsd
 {
 
-LLSD& drill(LLSD& blob, const LLSD& rawPath)
+LLSD& drill_ref(LLSD& blob, const LLSD& rawPath)
 {
     LL_PROFILE_ZONE_SCOPED
 
@@ -937,9 +938,9 @@ LLSD drill(const LLSD& blob, const LLSD& path)
 {
     LL_PROFILE_ZONE_SCOPED
 
-    // non-const drill() does exactly what we want. Temporarily cast away
+    // drill_ref() does exactly what we want. Temporarily cast away
     // const-ness and use that.
-    return drill(const_cast<LLSD&>(blob), path);
+    return drill_ref(const_cast<LLSD&>(blob), path);
 }
 
 } // namespace llsd
diff --git a/indra/llcommon/llsdutil.h b/indra/llcommon/llsdutil.h
index 8678ca97f2e9ac7b75c0f468af9bf5c90b44f8cc..1321615805bfec449bedcd91b464962a67ce1fef 100644
--- a/indra/llcommon/llsdutil.h
+++ b/indra/llcommon/llsdutil.h
@@ -184,10 +184,10 @@ namespace llsd
  *   - Anything else is an error.
  *
  * By implication, if path.isUndefined() or otherwise equivalent to an empty
- * LLSD::Array, drill() returns 'blob' as is.
+ * LLSD::Array, drill[_ref]() returns 'blob' as is.
  */
 LLSD  drill(const LLSD& blob, const LLSD& path);
-LLSD& drill(      LLSD& blob, const LLSD& path);
+LLSD& drill_ref(  LLSD& blob, const LLSD& path);
 
 }
 
diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp
index 4f57daf9ec9741e7a3a139f7a16fed285d8068eb..f717b2cf34155228aabe465b98e8ec1dd1885ebe 100644
--- a/indra/llcommon/llsys.cpp
+++ b/indra/llcommon/llsys.cpp
@@ -195,18 +195,6 @@ LLOSInfo::LLOSInfo() :
 		GetSystemInfo(&si); //if it fails get regular system info 
 	//(Warning: If GetSystemInfo it may result in incorrect information in a WOW64 machine, if the kernel fails to load)
 
-	//msdn microsoft finds 32 bit and 64 bit flavors this way..
-	//http://msdn.microsoft.com/en-us/library/ms724429(VS.85).aspx (example code that contains quite a few more flavors
-	//of windows than this code does (in case it is needed for the future)
-	if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) //check for 64 bit
-	{
-		mOSStringSimple += "64-bit ";
-	}
-	else if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
-	{
-		mOSStringSimple += "32-bit ";
-	}
-
 	// Try calling GetVersionEx using the OSVERSIONINFOEX structure.
 	OSVERSIONINFOEX osvi;
 	ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
@@ -253,9 +241,21 @@ LLOSInfo::LLOSInfo() :
             // Query WMI's Win32_OperatingSystem for OS string. Slow
             // and likely to return 'compatibility' string.
             // Check presence of dlls/libs or may be their version.
-            mOSStringSimple = "Microsoft Windows 10/11";
+            mOSStringSimple = "Microsoft Windows 10/11 ";
         }
-	}
+    }
+
+    //msdn microsoft finds 32 bit and 64 bit flavors this way..
+    //http://msdn.microsoft.com/en-us/library/ms724429(VS.85).aspx (example code that contains quite a few more flavors
+    //of windows than this code does (in case it is needed for the future)
+    if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) //check for 64 bit
+    {
+        mOSStringSimple += "64-bit ";
+    }
+    else if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
+    {
+        mOSStringSimple += "32-bit ";
+    }
 
 	mOSString = mOSStringSimple;
 	if (mBuild > 0)
diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp
index 5fa19ce9c6f4dc2b3123751dbebcecda321a9ccf..0fa027c9c30314302b82e475255e7d75949631a6 100644
--- a/indra/llimage/llimage.cpp
+++ b/indra/llimage/llimage.cpp
@@ -884,8 +884,6 @@ void LLImageRaw::setDataAndSize(U8 *data, S32 width, S32 height, S8 components)
 
 	LLImageBase::setSize(width, height, components) ;
 	LLImageBase::setDataAndSize(data, width * height * components) ;
-	
-	sGlobalRawMemory += getDataSize();
 }
 
 bool LLImageRaw::resize(U16 width, U16 height, S8 components)
diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp
index efa1a4076b1e7f4e38398957af19bb427e52f0b1..3727ce85afab9d1ab2b99b8ec29eb57d8822829c 100644
--- a/indra/llmath/llvolume.cpp
+++ b/indra/llmath/llvolume.cpp
@@ -5764,7 +5764,16 @@ BOOL LLVolumeFace::createUnCutCubeCap(LLVolume* volume, BOOL partial_build)
 		resizeIndices(grid_size*grid_size*6);
 		if (!volume->isMeshAssetLoaded())
 		{
-			mEdge.resize(grid_size*grid_size * 6);
+            S32 size = grid_size * grid_size * 6;
+            try
+            {
+                mEdge.resize(size);
+            }
+            catch (std::bad_alloc&)
+            {
+                LL_WARNS("LLVOLUME") << "Resize of mEdge to " << size << " failed" << LL_ENDL;
+                return false;
+            }
 		}
 
 		U16* out = mIndices;
@@ -6577,7 +6586,15 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build)
 
 		if (!volume->isMeshAssetLoaded())
 		{
-			mEdge.resize(num_indices);
+            try
+            {
+                mEdge.resize(num_indices);
+            }
+            catch (std::bad_alloc&)
+            {
+                LL_WARNS("LLVOLUME") << "Resize of mEdge to " << num_indices << " failed" << LL_ENDL;
+                return false;
+            }
 		}
 	}
 
@@ -6805,7 +6822,15 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build)
 	LLVector4a* norm = mNormals;
 
 	static LLAlignedArray<LLVector4a, 64> triangle_normals;
-	triangle_normals.resize(count);
+    try
+    {
+        triangle_normals.resize(count);
+    }
+    catch (std::bad_alloc&)
+    {
+        LL_WARNS("LLVOLUME") << "Resize of triangle_normals to " << count << " failed" << LL_ENDL;
+        return false;
+    }
 	LLVector4a* output = triangle_normals.mArray;
 	LLVector4a* end_output = output+count;
 
diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp
index f43671dee5c23cb53937442fd2c3eef3244ce0de..9bd3a0a6b0a1c93007883a3838780043ac34e9ed 100644
--- a/indra/llrender/llimagegl.cpp
+++ b/indra/llrender/llimagegl.cpp
@@ -211,6 +211,7 @@ S32 LLImageGL::dataFormatBits(S32 dataformat)
     case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:    return 8;
     case GL_LUMINANCE:						        return 8;
     case GL_ALPHA:							        return 8;
+    case GL_RED:                                    return 8;
     case GL_COLOR_INDEX:						    return 8;
     case GL_LUMINANCE_ALPHA:					    return 16;
     case GL_RGB:								    return 24;
@@ -260,6 +261,7 @@ S32 LLImageGL::dataFormatComponents(S32 dataformat)
 	  case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: return 4;
 	  case GL_LUMINANCE:						return 1;
 	  case GL_ALPHA:							return 1;
+      case GL_RED:                              return 1;
 	  case GL_COLOR_INDEX:						return 1;
 	  case GL_LUMINANCE_ALPHA:					return 2;
 	  case GL_RGB:								return 3;
@@ -1199,7 +1201,29 @@ BOOL LLImageGL::setSubImageFromFrameBuffer(S32 fb_x, S32 fb_y, S32 x_pos, S32 y_
 void LLImageGL::generateTextures(S32 numTextures, U32 *textures)
 {
     LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
-	glGenTextures(numTextures, textures);
+    static constexpr U32 pool_size = 1024;
+    static thread_local U32 name_pool[pool_size]; // pool of texture names
+    static thread_local U32 name_count = 0; // number of available names in the pool
+
+    if (name_count == 0)
+    {
+        LL_PROFILE_ZONE_NAMED("iglgt - reup pool");
+        // pool is emtpy, refill it
+        glGenTextures(pool_size, name_pool);
+        name_count = pool_size;
+    }
+
+    if (numTextures <= name_count)
+    {
+        //copy teture names off the end of the pool
+        memcpy(textures, name_pool + name_count - numTextures, sizeof(U32) * numTextures);
+        name_count -= numTextures;
+    }
+    else
+    {
+        LL_PROFILE_ZONE_NAMED("iglgt - pool miss");
+        glGenTextures(numTextures, textures);
+    }
 }
 
 // static
@@ -1221,15 +1245,18 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt
     {
         if (pixformat == GL_ALPHA && pixtype == GL_UNSIGNED_BYTE)
         { //GL_ALPHA is deprecated, convert to RGBA
-            use_scratch = true;
-            scratch = new U32[width * height];
-
-            U32 pixel_count = (U32)(width * height);
-            for (U32 i = 0; i < pixel_count; i++)
+            if (pixels != nullptr)
             {
-                U8* pix = (U8*)&scratch[i];
-                pix[0] = pix[1] = pix[2] = 0;
-                pix[3] = ((U8*)pixels)[i];
+                use_scratch = true;
+                scratch = new U32[width * height];
+
+                U32 pixel_count = (U32)(width * height);
+                for (U32 i = 0; i < pixel_count; i++)
+                {
+                    U8* pix = (U8*)&scratch[i];
+                    pix[0] = pix[1] = pix[2] = 0;
+                    pix[3] = ((U8*)pixels)[i];
+                }
             }
 
             pixformat = GL_RGBA;
@@ -1238,18 +1265,21 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt
 
         if (pixformat == GL_LUMINANCE_ALPHA && pixtype == GL_UNSIGNED_BYTE)
         { //GL_LUMINANCE_ALPHA is deprecated, convert to RGBA
-            use_scratch = true;
-            scratch = new U32[width * height];
-
-            U32 pixel_count = (U32)(width * height);
-            for (U32 i = 0; i < pixel_count; i++)
+            if (pixels != nullptr)
             {
-                U8 lum = ((U8*)pixels)[i * 2 + 0];
-                U8 alpha = ((U8*)pixels)[i * 2 + 1];
+                use_scratch = true;
+                scratch = new U32[width * height];
+
+                U32 pixel_count = (U32)(width * height);
+                for (U32 i = 0; i < pixel_count; i++)
+                {
+                    U8 lum = ((U8*)pixels)[i * 2 + 0];
+                    U8 alpha = ((U8*)pixels)[i * 2 + 1];
 
-                U8* pix = (U8*)&scratch[i];
-                pix[0] = pix[1] = pix[2] = lum;
-                pix[3] = alpha;
+                    U8* pix = (U8*)&scratch[i];
+                    pix[0] = pix[1] = pix[2] = lum;
+                    pix[3] = alpha;
+                }
             }
 
             pixformat = GL_RGBA;
@@ -1258,19 +1288,21 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt
 
         if (pixformat == GL_LUMINANCE && pixtype == GL_UNSIGNED_BYTE)
         { //GL_LUMINANCE_ALPHA is deprecated, convert to RGB
-            use_scratch = true;
-            scratch = new U32[width * height];
-
-            U32 pixel_count = (U32)(width * height);
-            for (U32 i = 0; i < pixel_count; i++)
+            if (pixels != nullptr)
             {
-                U8 lum = ((U8*)pixels)[i];
+                use_scratch = true;
+                scratch = new U32[width * height];
 
-                U8* pix = (U8*)&scratch[i];
-                pix[0] = pix[1] = pix[2] = lum;
-                pix[3] = 255;
-            }
+                U32 pixel_count = (U32)(width * height);
+                for (U32 i = 0; i < pixel_count; i++)
+                {
+                    U8 lum = ((U8*)pixels)[i];
 
+                    U8* pix = (U8*)&scratch[i];
+                    pix[0] = pix[1] = pix[2] = lum;
+                    pix[3] = 255;
+                }
+            }
             pixformat = GL_RGBA;
             intformat = GL_RGB8;
         }
@@ -1308,6 +1340,10 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt
         case GL_ALPHA8:
             intformat = GL_COMPRESSED_ALPHA;
             break;
+        case GL_RED:
+        case GL_R8:
+            intformat = GL_COMPRESSED_RED;
+            break;
         default:
             LL_WARNS() << "Could not compress format: " << std::hex << intformat << LL_ENDL;
             break;
@@ -2010,6 +2046,7 @@ void LLImageGL::calcAlphaChannelOffsetAndStride()
     case GL_LUMINANCE_ALPHA:
         mAlphaStride = 2;
         break;
+    case GL_RED:
     case GL_RGB:
     case GL_SRGB:
         mNeedsAlphaAndPickMask = FALSE;
diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp
index 401085a00bc9dc767762a1a5e9d219c06599b91a..04080105131c63a73bdb6e6b0c90820ac0d65611 100644
--- a/indra/llrender/llrendertarget.cpp
+++ b/indra/llrender/llrendertarget.cpp
@@ -170,6 +170,53 @@ bool LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, boo
 	return addColorAttachment(color_fmt);
 }
 
+void LLRenderTarget::setColorAttachment(LLImageGL* img, LLGLuint use_name)
+{
+    LL_PROFILE_ZONE_SCOPED;
+    llassert(img != nullptr); // img must not be null
+    llassert(sUseFBO); // FBO support must be enabled
+    llassert(mDepth == 0); // depth buffers not supported with this mode
+    llassert(mTex.empty()); // mTex must be empty with this mode (binding target should be done via LLImageGL)
+
+    if (mFBO == 0)
+    {
+        glGenFramebuffers(1, (GLuint*)&mFBO);
+    }
+
+    mResX = img->getWidth();
+    mResY = img->getHeight();
+    mUsage = img->getTarget();
+
+    if (use_name == 0)
+    {
+        use_name = img->getTexName();
+    }
+
+    mTex.push_back(use_name);
+
+    glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+            LLTexUnit::getInternalType(mUsage), use_name, 0);
+        stop_glerror();
+
+    check_framebuffer_status();
+
+    glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);
+}
+
+void LLRenderTarget::releaseColorAttachment()
+{
+    LL_PROFILE_ZONE_SCOPED;
+    llassert(mTex.size() == 1); //cannot use releaseColorAttachment with LLRenderTarget managed color targets
+    llassert(mFBO != 0);  // mFBO must be valid
+    
+    glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, LLTexUnit::getInternalType(mUsage), 0, 0);
+    glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);
+
+    mTex.clear();
+}
+
 bool LLRenderTarget::addColorAttachment(U32 color_fmt)
 {
 	if (color_fmt == 0)
diff --git a/indra/llrender/llrendertarget.h b/indra/llrender/llrendertarget.h
index 6c07ac5b1c7c8645af7e04c45fc731bdc97f3dc7..584f224dcaccc3893e1fb15954cfd171fce19a4f 100644
--- a/indra/llrender/llrendertarget.h
+++ b/indra/llrender/llrendertarget.h
@@ -81,6 +81,24 @@ class LLRenderTarget
 	// DO use for render targets that resize often and aren't likely to ruin someone's day if they break
 	void resize(U32 resx, U32 resy);
 
+    //point this render target at a particular LLImageGL
+    //   Intended usage:
+    //      LLRenderTarget target;
+    //      target.addColorAttachment(image);
+    //      target.bindTarget();
+    //      < issue GL calls>
+    //      target.flush();
+    //      target.releaseColorAttachment();
+    // 
+    // attachment -- LLImageGL to render into
+    // use_name -- optional texture name to target instead of attachment->getTexName()
+    // NOTE: setColorAttachment and releaseColorAttachment cannot be used in conjuction with
+    // addColorAttachment, allocateDepth, resize, etc.
+    void setColorAttachment(LLImageGL* attachment, LLGLuint use_name = 0);
+
+    // detach from current color attachment
+    void releaseColorAttachment();
+
 	//add color buffer attachment
 	//limit of 4 color attachments per render target
 	bool addColorAttachment(U32 color_fmt);
diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp
index 1badd54fca5df6af7b8ab85b69abb5b9b81884ae..33037b500176e2eddb5bdbe8d8bb6439f586085a 100644
--- a/indra/llui/lllineeditor.cpp
+++ b/indra/llui/lllineeditor.cpp
@@ -175,6 +175,14 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p)
 	mTripleClickTimer.reset();
 	setText(p.default_text());
 
+    if (p.initial_value.isProvided()
+        && !p.control_name.isProvided())
+    {
+        // Initial value often is descriptive, like "Type some ID here"
+        // and can be longer than size limitation, ignore size
+        setText(p.initial_value.getValue().asString(), false);
+    }
+
 	// Initialize current history line iterator
 	mCurrentHistoryLine = mLineHistory.begin();
 
@@ -389,6 +397,11 @@ void LLLineEditor::updateTextPadding()
 
 
 void LLLineEditor::setText(const LLStringExplicit &new_text)
+{
+    setText(new_text, true);
+}
+
+void LLLineEditor::setText(const LLStringExplicit &new_text, bool use_size_limit)
 {
 	// If new text is identical, don't copy and don't move insertion point
 	if (mText.getString() == new_text)
@@ -407,13 +420,13 @@ void LLLineEditor::setText(const LLStringExplicit &new_text)
 	all_selected = all_selected || (len == 0 && hasFocus() && mSelectAllonFocusReceived);
 
 	std::string truncated_utf8 = new_text;
-	if (truncated_utf8.size() > (U32)mMaxLengthBytes)
+	if (use_size_limit && truncated_utf8.size() > (U32)mMaxLengthBytes)
 	{	
 		truncated_utf8 = utf8str_truncate(new_text, mMaxLengthBytes);
 	}
 	mText.assign(truncated_utf8);
 
-	if (mMaxLengthChars)
+	if (use_size_limit && mMaxLengthChars)
 	{
 		mText.assign(utf8str_symbol_truncate(truncated_utf8, mMaxLengthChars));
 	}
diff --git a/indra/llui/lllineeditor.h b/indra/llui/lllineeditor.h
index f84625bea7a680467dbe2cce4e0d2f86499221bf..ae4e05c065f7430e651ab88c60080661c0bfb9bc 100644
--- a/indra/llui/lllineeditor.h
+++ b/indra/llui/lllineeditor.h
@@ -320,6 +320,8 @@ class LLLineEditor
 	virtual S32		getPreeditFontSize() const;
 	virtual LLWString getPreeditString() const { return getWText(); }
 
+    void			setText(const LLStringExplicit &new_text, bool use_size_limit);
+
 	void			setContextMenu(LLContextMenu* new_context_menu);
 
 protected:
diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp
index cdaf03ebde411a0d48bd896f4368bb36dfa7b65b..76fd789becebe6ff33f41496be5023b58b33c9b5 100644
--- a/indra/llui/llmenugl.cpp
+++ b/indra/llui/llmenugl.cpp
@@ -2362,6 +2362,16 @@ void LLMenuGL::arrange( void )
 				(*item_iter)->setRect( rect );
 			}
 		}
+
+
+        if (getTornOff())
+        {
+            LLTearOffMenu * torn_off_menu = dynamic_cast<LLTearOffMenu*>(getParent());
+            if (torn_off_menu)
+            {
+                torn_off_menu->updateSize();
+            }
+        }
 	}
 	if (mKeepFixedSize)
 	{
@@ -3879,7 +3889,8 @@ void LLMenuHolderGL::setActivatedItem(LLMenuItemGL* item)
 /// Class LLTearOffMenu
 ///============================================================================
 LLTearOffMenu::LLTearOffMenu(LLMenuGL* menup) : 
-	LLFloater(LLSD())
+	LLFloater(LLSD()),
+    mQuitRequested(false)
 {
 	S32 floater_header_size = getHeaderHeight();
 
@@ -3894,7 +3905,7 @@ LLTearOffMenu::LLTearOffMenu(LLMenuGL* menup) :
 	LLRect rect;
 	menup->localRectToOtherView(LLRect(-1, menup->getRect().getHeight(), menup->getRect().getWidth() + 3, 0), &rect, gFloaterView);
 	// make sure this floater is big enough for menu
-	mTargetHeight = (F32)(rect.getHeight() + floater_header_size);
+	mTargetHeight = rect.getHeight() + floater_header_size;
 	reshape(rect.getWidth(), rect.getHeight());
 	setRect(rect);
 
@@ -3926,19 +3937,24 @@ LLTearOffMenu::~LLTearOffMenu()
 void LLTearOffMenu::draw()
 {
 	mMenu->setBackgroundVisible(isBackgroundOpaque());
-	mMenu->needsArrange();
 
 	if (getRect().getHeight() != mTargetHeight)
 	{
 		// animate towards target height
-		reshape(getRect().getWidth(), llceil(lerp((F32)getRect().getHeight(), mTargetHeight, LLSmoothInterpolation::getInterpolant(0.05f))));
+        reshape(getRect().getWidth(), llceil(lerp((F32)getRect().getHeight(), (F32)mTargetHeight, LLSmoothInterpolation::getInterpolant(0.05f))));
+        mMenu->needsArrange();
 	}
 	LLFloater::draw();
 }
 
 void LLTearOffMenu::onFocusReceived()
 {
-	// if nothing is highlighted, just highlight first item
+    if (mQuitRequested)
+    {
+        return;
+    }
+ 
+    // if nothing is highlighted, just highlight first item
 	if (!mMenu->getHighlightedItem())
 	{
 		mMenu->highlightNextItem(NULL);
@@ -4014,6 +4030,31 @@ LLTearOffMenu* LLTearOffMenu::create(LLMenuGL* menup)
 	return tearoffp;
 }
 
+void LLTearOffMenu::updateSize()
+{
+    if (mMenu)
+    {
+        S32 floater_header_size = getHeaderHeight();
+        const LLRect &floater_rect = getRect();
+        LLRect new_rect;
+        mMenu->localRectToOtherView(LLRect(-1, mMenu->getRect().getHeight() + floater_header_size, mMenu->getRect().getWidth() + 3, 0), &new_rect, gFloaterView);
+
+        if (floater_rect.getWidth() != new_rect.getWidth()
+            || mTargetHeight != new_rect.getHeight())
+        {
+            // make sure this floater is big enough for menu
+            mTargetHeight = new_rect.getHeight();
+            reshape(new_rect.getWidth(), mTargetHeight);
+
+            // Restore menu position
+            LLRect menu_rect = mMenu->getRect();
+            menu_rect.setOriginAndSize(1, 1,
+                menu_rect.getWidth(), menu_rect.getHeight());
+            mMenu->setRect(menu_rect);
+        }
+    }
+}
+
 void LLTearOffMenu::closeTearOff()
 {
 	removeChild(mMenu);
@@ -4024,6 +4065,7 @@ void LLTearOffMenu::closeTearOff()
 	mMenu->setVisible(FALSE);
 	mMenu->setTornOff(FALSE);
 	mMenu->setDropShadowed(TRUE);
+    mQuitRequested = true;
 }
 
 LLContextMenuBranch::LLContextMenuBranch(const LLContextMenuBranch::Params& p) 
diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h
index 273bd789c44796b1a76740b2a5c6b002ffb7e0b1..abbfd9a24a36c0597045f3f0b12584a68b6931a5 100644
--- a/indra/llui/llmenugl.h
+++ b/indra/llui/llmenugl.h
@@ -873,6 +873,8 @@ class LLTearOffMenu : public LLFloater
 	virtual BOOL handleKeyHere(KEY key, MASK mask);
 	virtual void translate(S32 x, S32 y);
 
+	void updateSize();
+
 private:
 	LLTearOffMenu(LLMenuGL* menup);
 	
@@ -880,7 +882,8 @@ class LLTearOffMenu : public LLFloater
 	
 	LLView*		mOldParent;
 	LLMenuGL*	mMenu;
-	F32			mTargetHeight;
+	S32			mTargetHeight;
+    bool        mQuitRequested;
 };
 
 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp
index 38495e1e0b023fbfa5df2c1df942e6c4a0df229d..1547a4ba5c89aa0c0df716e48720989f5e08451f 100644
--- a/indra/llui/llurlentry.cpp
+++ b/indra/llui/llurlentry.cpp
@@ -1017,6 +1017,24 @@ std::string LLUrlEntryObjectIM::getLocation(const std::string &url) const
 	return LLUrlEntryBase::getLocation(url);
 }
 
+//
+// LLUrlEntryChat Describes a Second Life chat Url, e.g.,
+// secondlife:///app/chat/42/This%20Is%20a%20test
+//
+
+LLUrlEntryChat::LLUrlEntryChat()
+{
+    mPattern = boost::regex("secondlife:///app/chat/\\d+/\\S+",
+        boost::regex::perl|boost::regex::icase);
+    mMenuName = "menu_url_slapp.xml";
+    mTooltip = LLTrans::getString("TooltipSLAPP");
+}
+
+std::string LLUrlEntryChat::getLabel(const std::string &url, const LLUrlLabelCallback &cb)
+{
+    return unescapeUrl(url);
+}
+
 // LLUrlEntryParcel statics.
 LLUUID	LLUrlEntryParcel::sAgentID(LLUUID::null);
 LLUUID	LLUrlEntryParcel::sSessionID(LLUUID::null);
diff --git a/indra/llui/llurlentry.h b/indra/llui/llurlentry.h
index 102e0a4fd98d7e2537ab2df0cd6f0f427fb49552..63a1506731f73100f97fda9fa27b105e8ebaa175 100644
--- a/indra/llui/llurlentry.h
+++ b/indra/llui/llurlentry.h
@@ -370,6 +370,17 @@ class LLUrlEntryObjectIM : public LLUrlEntryBase
 private:
 };
 
+//
+// LLUrlEntryChat Describes a Second Life chat Url, e.g.,
+// secondlife:///app/chat/42/This%20Is%20a%20test
+//
+class LLUrlEntryChat : public LLUrlEntryBase
+{
+public:
+    LLUrlEntryChat();
+    /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
+};
+
 ///
 /// LLUrlEntryParcel Describes a Second Life parcel Url, e.g.,
 /// secondlife:///app/parcel/0000060e-4b39-e00b-d0c3-d98b1934e3a8/about
diff --git a/indra/llui/llurlregistry.cpp b/indra/llui/llurlregistry.cpp
index bfcd970529454c89aa2f09d981f38008144b02b7..c9d7013a11ac5dba1887d0d66cbc9f64c17ca1e4 100644
--- a/indra/llui/llurlregistry.cpp
+++ b/indra/llui/llurlregistry.cpp
@@ -63,6 +63,7 @@ LLUrlRegistry::LLUrlRegistry()
 	// LLUrlEntryAgent*Name must appear before LLUrlEntryAgent since 
 	// LLUrlEntryAgent is a less specific (catchall for agent urls)
 	registerUrl(new LLUrlEntryAgent());
+    registerUrl(new LLUrlEntryChat());
 	registerUrl(new LLUrlEntryGroup());
 	registerUrl(new LLUrlEntryParcel());
 	registerUrl(new LLUrlEntryTeleport());
@@ -71,7 +72,6 @@ LLUrlRegistry::LLUrlRegistry()
 	registerUrl(new LLUrlEntryObjectIM());
 	registerUrl(new LLUrlEntryPlace());
 	registerUrl(new LLUrlEntryInventory());
-	registerUrl(new LLUrlEntryObjectIM());
     registerUrl(new LLUrlEntryExperienceProfile());
 	//LLUrlEntrySL and LLUrlEntrySLLabel have more common pattern, 
 	//so it should be registered in the end of list
diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp
index f26e3a84d2e327233af061d4e28ea7a890880814..33b42577064aaa4fcd8142a85ab91654a0f3c283 100644
--- a/indra/llwindow/llwindowwin32.cpp
+++ b/indra/llwindow/llwindowwin32.cpp
@@ -2426,6 +2426,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
             LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_SYSKEYDOWN");
             // allow system keys, such as ALT-F4 to be processed by Windows
             eat_keystroke = FALSE;
+            // intentional fall-through here
         }
         case WM_KEYDOWN:
         {
@@ -2450,10 +2451,12 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
                         gKeyboard->handleKeyDown(w_param, mask);
                     }
                 });
-                return eat_keystroke;
+            if (eat_keystroke) return 0;    // skip DefWindowProc() handling if we're consuming the keypress 
+            break;
         }
         case WM_SYSKEYUP:
             eat_keystroke = FALSE;
+            // intentional fall-through here
         case WM_KEYUP:
         {
             LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_KEYUP");
@@ -2477,7 +2480,8 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
                     gKeyboard->handleKeyUp(w_param, mask);
                 }
             });
-            return eat_keystroke;
+            if (eat_keystroke) return 0;    // skip DefWindowProc() handling if we're consuming the keypress 
+            break;
         }
         case WM_IME_SETCONTEXT:
         {
@@ -4365,7 +4369,8 @@ BOOL LLWindowWin32::handleImeRequests(WPARAM request, LPARAM param, LRESULT *res
 				S32 context_offset;
 				LLWString context = find_context(wtext, preedit, preedit_length, &context_offset);
 				preedit -= context_offset;
-				if (preedit_length)
+				preedit_length = llmin(preedit_length, (S32)context.length() - preedit);
+				if (preedit_length && preedit >= 0)
 				{
 					// IMR_DOCUMENTFEED may be called when we have an active preedit.
 					// We should pass the context string *excluding* the preedit string.
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index e7f0af84ef0e408b5f2f3966f27e8adecdb497f1..539b4f7b34c27566665b009ed6b35e969e710bf5 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -1917,9 +1917,7 @@ if (WINDOWS)
       add_dependencies(${VIEWER_BINARY_NAME} copy_win_scripts)
     endif (EXISTS ${CMAKE_SOURCE_DIR}/copy_win_scripts)
 
-    add_dependencies(${VIEWER_BINARY_NAME}
-      SLPlugin
-    )
+    add_dependencies(${VIEWER_BINARY_NAME} SLPlugin)
 
     # sets the 'working directory' for debugging from visual studio.
     # Condition for version can be moved to requirements once build agents will be updated (see TOOL-3865)
@@ -2270,7 +2268,7 @@ endif (INSTALL)
 
 # Note that the conventional VIEWER_SYMBOL_FILE is set by ../../build.sh
 if (PACKAGE AND (RELEASE_CRASH_REPORTING OR NON_RELEASE_CRASH_REPORTING) AND VIEWER_SYMBOL_FILE)
-  if (BUGSPLAT_DB)
+  if (USE_BUGSPLAT)
     # BugSplat symbol-file generation
     if (WINDOWS)
       # Just pack up a tarball containing only the .pdb file for the
@@ -2354,7 +2352,7 @@ if (PACKAGE AND (RELEASE_CRASH_REPORTING OR NON_RELEASE_CRASH_REPORTING) AND VIE
     if (LINUX)
       # TBD
     endif (LINUX)
-  endif (BUGSPLAT_DB)
+  endif (USE_BUGSPLAT)
 
   # for both Bugsplat and Breakpad
   add_dependencies(llpackage generate_symbols)
diff --git a/indra/newview/app_settings/cmd_line.xml b/indra/newview/app_settings/cmd_line.xml
index 7514913d13165b2bbf862f5ae454806ad66889c7..dd2b656ce3e4fc052566ad2e75c22e89edf2995a 100644
--- a/indra/newview/app_settings/cmd_line.xml
+++ b/indra/newview/app_settings/cmd_line.xml
@@ -207,14 +207,6 @@
     <map>
       <key>map-to</key>
       <string>NoAudio</string>
-    </map>    
-
-    <key>noinvlib</key>
-    <map>
-      <key>desc</key>
-      <string>Do not request the inventory library.</string>
-      <key>map-to</key>
-      <string>NoInventoryLibrary</string>
     </map>
 
     <key>noninteractive</key>
diff --git a/indra/newview/app_settings/key_bindings.xml b/indra/newview/app_settings/key_bindings.xml
index 1a5157838cd7a2f0d5858e5b6ce59af32853091b..55babc88bceaa5acd97ffebcbf00fe598fdeb1f7 100644
--- a/indra/newview/app_settings/key_bindings.xml
+++ b/indra/newview/app_settings/key_bindings.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<keys>
+<keys xml_version="1">
   <first_person>
     <binding key="A" mask="NONE" command="slide_left"/>
     <binding key="D" mask="NONE" command="slide_right"/>
@@ -17,22 +17,13 @@
     <binding key="PGDN" mask="NONE" command="push_down"/>
     <binding key="HOME" mask="NONE" command="toggle_fly"/>
 
-    <binding key="PAD_LEFT" mask="NONE" command="slide_left"/>
-    <binding key="PAD_RIGHT" mask="NONE" command="slide_right"/>
-    <binding key="PAD_UP" mask="NONE" command="push_forward"/>
-    <binding key="PAD_DOWN" mask="NONE" command="push_backward"/>
-    <binding key="PAD_PGUP" mask="NONE" command="jump"/>
-    <binding key="PAD_PGDN" mask="NONE" command="push_down"/>
-    <binding key="PAD_HOME" mask="NONE" command="toggle_fly"/>
-    <binding key="PAD_CENTER" mask="NONE" command="stop_moving"/>
-    <binding key="PAD_ENTER" mask="NONE" command="start_chat"/>
-    <binding key="PAD_DIVIDE" mask="NONE" command="start_gesture"/>
-
     <binding key="SPACE" mask="NONE" command="stop_moving"/>
     <binding key="ENTER" mask="NONE" command="start_chat"/>
     <binding key="DIVIDE" mask="NONE" command="start_gesture"/>
 
     <binding key="" mask="NONE" mouse="MMB" command="toggle_voice"/>
+
+    <binding key="" mask="NONE" mouse="LMB" command="script_trigger_lbutton"/>
   </first_person>
   <third_person>
     <binding key="A" mask="NONE" command="turn_left"/>
@@ -60,19 +51,6 @@
     <binding key="PGDN" mask="NONE" command="push_down"/>
     <binding key="HOME" mask="NONE" command="toggle_fly"/>
 
-    <binding key="PAD_LEFT" mask="NONE" command="turn_left"/>
-    <binding key="PAD_LEFT" mask="SHIFT" command="slide_left"/>
-    <binding key="PAD_RIGHT" mask="NONE" command="turn_right"/>
-    <binding key="PAD_RIGHT" mask="SHIFT" command="slide_right"/>
-    <binding key="PAD_UP" mask="NONE" command="push_forward"/>
-    <binding key="PAD_DOWN" mask="NONE" command="push_backward"/>
-    <binding key="PAD_PGUP" mask="NONE" command="jump"/>
-    <binding key="PAD_PGDN" mask="NONE" command="push_down"/>
-    <binding key="PAD_HOME" mask="NONE" command="toggle_fly"/>
-    <binding key="PAD_CENTER" mask="NONE" command="stop_moving"/>
-    <binding key="PAD_ENTER" mask="NONE" command="start_chat"/>
-    <binding key="PAD_DIVIDE" mask="NONE" command="start_gesture"/>
-
     <!--Camera controls in third person on Alt-->
     <binding key="LEFT" mask="ALT" command="spin_around_cw"/>
     <binding key="RIGHT" mask="ALT" command="spin_around_ccw"/>
@@ -88,15 +66,6 @@
     <binding key="E" mask="ALT" command="spin_over"/>
     <binding key="C" mask="ALT" command="spin_under"/>
 
-    <binding key="PAD_LEFT" mask="ALT" command="spin_around_cw"/>
-    <binding key="PAD_RIGHT" mask="ALT" command="spin_around_ccw"/>
-    <binding key="PAD_UP" mask="ALT" command="move_forward"/>
-    <binding key="PAD_DOWN" mask="ALT" command="move_backward"/>
-    <binding key="PAD_PGUP" mask="ALT" command="spin_over"/>
-    <binding key="PAD_PGDN" mask="ALT" command="spin_under"/>
-    <binding key="PAD_ENTER" mask="ALT" command="start_chat"/>
-    <binding key="PAD_DIVIDE" mask="ALT" command="start_gesture"/>
-
     <!--mimic alt zoom behavior with keyboard only-->
     <binding key="W" mask="CTL_ALT" command="spin_over"/>
     <binding key="S" mask="CTL_ALT" command="spin_under"/>
@@ -104,9 +73,6 @@
     <binding key="UP" mask="CTL_ALT" command="spin_over"/>
     <binding key="DOWN" mask="CTL_ALT" command="spin_under"/>
 
-    <binding key="PAD_UP" mask="CTL_ALT" command="spin_over"/>
-    <binding key="PAD_DOWN" mask="CTL_ALT" command="spin_under"/>
-
     <!--Therefore pan on Alt-Shift-->
     <binding key="A" mask="CTL_ALT_SHIFT" command="pan_left"/>
     <binding key="D" mask="CTL_ALT_SHIFT" command="pan_right"/>
@@ -118,14 +84,10 @@
     <binding key="UP" mask="CTL_ALT_SHIFT" command="pan_up"/>
     <binding key="DOWN" mask="CTL_ALT_SHIFT" command="pan_down"/>
 
-    <binding key="PAD_LEFT" mask="CTL_ALT_SHIFT" command="pan_left"/>
-    <binding key="PAD_RIGHT" mask="CTL_ALT_SHIFT" command="pan_right"/>
-    <binding key="PAD_UP" mask="CTL_ALT_SHIFT" command="pan_up"/>
-    <binding key="PAD_DOWN" mask="CTL_ALT_SHIFT" command="pan_down"/>
-    <binding key="PAD_ENTER" mask="CTL_ALT_SHIFT" command="start_chat"/>
-    <binding key="PAD_DIVIDE" mask="CTL_ALT_SHIFT" command="start_gesture"/>
-
     <binding key="" mask="NONE" mouse="MMB" command="toggle_voice"/>
+    <binding key="" mask="NONE" mouse="LMB" command="walk_to"/>
+
+    <binding key="" mask="NONE" mouse="LMB" command="script_trigger_lbutton"/>
   </third_person>
   <sitting>
     <binding key="A" mask="ALT" command="spin_around_cw"/>
@@ -167,16 +129,6 @@
     <binding key="PGUP" mask="NONE" command="spin_over_sitting"/>
     <binding key="PGDN" mask="NONE" command="spin_under_sitting"/>
 
-    <binding key="PAD_LEFT" mask="NONE" command="spin_around_cw_sitting"/>
-    <binding key="PAD_RIGHT" mask="NONE" command="spin_around_ccw_sitting"/>
-    <binding key="PAD_UP" mask="NONE" command="move_forward_sitting"/>
-    <binding key="PAD_DOWN" mask="NONE" command="move_backward_sitting"/>
-    <binding key="PAD_PGUP" mask="NONE" command="spin_over_sitting"/>
-    <binding key="PAD_PGDN" mask="NONE" command="spin_under_sitting"/>
-    <binding key="PAD_CENTER" mask="NONE" command="stop_moving"/>
-    <binding key="PAD_ENTER" mask="NONE" command="start_chat"/>
-    <binding key="PAD_DIVIDE" mask="NONE" command="start_gesture"/>
-
     <!--these are for passing controls when sitting on vehicles-->
     <binding key="A" mask="SHIFT" command="slide_left"/>
     <binding key="D" mask="SHIFT" command="slide_right"/>
@@ -192,15 +144,6 @@
     <binding key="PGUP" mask="SHIFT" command="spin_over_sitting"/>
     <binding key="PGDN" mask="SHIFT" command="spin_under_sitting"/>
 
-    <binding key="PAD_LEFT" mask="SHIFT" command="slide_left"/>
-    <binding key="PAD_RIGHT" mask="SHIFT" command="slide_right"/>
-    <binding key="PAD_UP" mask="SHIFT" command="move_forward_sitting"/>
-    <binding key="PAD_DOWN" mask="SHIFT" command="move_backward_sitting"/>
-    <binding key="PAD_PGUP" mask="SHIFT" command="spin_over_sitting"/>
-    <binding key="PAD_PGDN" mask="SHIFT" command="spin_under_sitting"/> 
-    <binding key="PAD_ENTER" mask="SHIFT" command="start_chat"/>
-    <binding key="PAD_DIVIDE" mask="SHIFT" command="start_gesture"/>
-
     <!--pan on Alt-Shift-->
     <binding key="A" mask="CTL_ALT_SHIFT" command="pan_left"/>
     <binding key="D" mask="CTL_ALT_SHIFT" command="pan_right"/>
@@ -212,17 +155,12 @@
     <binding key="UP" mask="CTL_ALT_SHIFT" command="pan_up"/>
     <binding key="DOWN" mask="CTL_ALT_SHIFT" command="pan_down"/>
 
-    <binding key="PAD_LEFT" mask="CTL_ALT_SHIFT" command="pan_left"/>
-    <binding key="PAD_RIGHT" mask="CTL_ALT_SHIFT" command="pan_right"/>
-    <binding key="PAD_UP" mask="CTL_ALT_SHIFT" command="pan_up"/>
-    <binding key="PAD_DOWN" mask="CTL_ALT_SHIFT" command="pan_down"/>
-    <binding key="PAD_ENTER" mask="CTL_ALT_SHIFT" command="start_chat"/>
-    <binding key="PAD_DIVIDE" mask="CTL_ALT_SHIFT" command="start_gesture"/>
-
     <binding key="ENTER" mask="NONE" command="start_chat"/>
     <binding key="DIVIDE" mask="NONE" command="start_gesture"/>
 
     <binding key="" mask="NONE" mouse="MMB" command="toggle_voice"/>
+
+    <binding key="" mask="NONE" mouse="LMB" command="script_trigger_lbutton"/>
   </sitting>
   <edit_avatar>
     <!--Avatar editing camera controls-->
@@ -240,15 +178,9 @@
     <binding key="PGDN" mask="NONE" command="edit_avatar_spin_under"/>
     <binding key="ENTER" mask="NONE" command="start_chat"/>
     <binding key="DIVIDE" mask="NONE" command="start_gesture"/>
-    <binding key="PAD_LEFT" mask="NONE" command="edit_avatar_spin_cw"/>
-    <binding key="PAD_RIGHT" mask="NONE" command="edit_avatar_spin_ccw"/>
-    <binding key="PAD_UP" mask="NONE" command="edit_avatar_move_forward"/>
-    <binding key="PAD_DOWN" mask="NONE" command="edit_avatar_move_backward"/>
-    <binding key="PAD_PGUP" mask="NONE" command="edit_avatar_spin_over"/>
-    <binding key="PAD_PGDN" mask="NONE" command="edit_avatar_spin_under"/>
-    <binding key="PAD_ENTER" mask="NONE" command="start_chat"/>
-    <binding key="PAD_DIVIDE" mask="NONE" command="start_gesture"/>
 
     <binding key="" mask="NONE" mouse="MMB" command="toggle_voice"/>
+
+    <binding key="" mask="NONE" mouse="LMB" command="script_trigger_lbutton"/>
   </edit_avatar>
 </keys>
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index bfc47d2c65225c2e8b613f9cca367a26a094f9f7..5d775622a018d46b316b385aa906697632d5010a 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -4758,7 +4758,7 @@
       <key>Type</key>
       <string>String</string>
       <key>Value</key>
-      <string>https://search.[GRID]/viewer/[CATEGORY]/?q=[QUERY]&amp;p=[AUTH_TOKEN]&amp;r=[MATURITY]&amp;lang=[LANGUAGE]&amp;g=[GODLIKE]&amp;sid=[SESSION_ID]&amp;rid=[REGION_ID]&amp;pid=[PARCEL_ID]&amp;channel=[CHANNEL]&amp;version=[VERSION]&amp;major=[VERSION_MAJOR]&amp;minor=[VERSION_MINOR]&amp;patch=[VERSION_PATCH]&amp;build=[VERSION_BUILD]</string>
+      <string>https://search.[GRID]/viewer/[CATEGORY]/?q=[QUERY]&amp;r=[MATURITY]&amp;lang=[LANGUAGE]&amp;g=[GODLIKE]&amp;sid=[SESSION_ID]&amp;rid=[REGION_ID]&amp;pid=[PARCEL_ID]&amp;channel=[CHANNEL]&amp;version=[VERSION]&amp;major=[VERSION_MAJOR]&amp;minor=[VERSION_MINOR]&amp;patch=[VERSION_PATCH]&amp;build=[VERSION_BUILD]</string>
     </map>
     <key>GuidebookURL</key>
     <map>
@@ -5895,17 +5895,6 @@
       <key>Value</key>
       <integer>0</integer>
     </map>
-    <key>LoginAsGod</key>
-    <map>
-      <key>Comment</key>
-      <string>Attempt to login with god powers (Linden accounts only)</string>
-      <key>Persist</key>
-      <integer>1</integer>
-      <key>Type</key>
-      <string>Boolean</string>
-      <key>Value</key>
-      <integer>0</integer>
-    </map>
     <key>LoginLocation</key>
     <map>
       <key>Comment</key>
@@ -6481,7 +6470,7 @@
     <key>MaxHeapSize</key>
     <map>
       <key>Comment</key>
-      <string>Maximum heap size (GB)</string>
+      <string>Maximum heap size on 32-bit builds (GB)</string>
       <key>Persist</key>
       <integer>1</integer>
       <key>Type</key>
@@ -6489,6 +6478,17 @@
       <key>Value</key>
       <real>1.6</real>
     </map>
+    <key>MaxHeapSize64</key>
+    <map>
+      <key>Comment</key>
+      <string>Maximum heap size on 64-bit builds (GB)</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>F32</string>
+      <key>Value</key>
+      <real>16.0</real>
+    </map>
     <key>MaxPersistentNotifications</key>
     <map>
       <key>Comment</key>
@@ -6964,6 +6964,17 @@
       <key>Value</key>
       <integer>1000</integer>
     </map>
+	<key>FakeInitialOutfitName</key>
+	<map>
+		<key>Comment</key>
+		<string>Pretend that this is first time login and specified name was chosen</string>
+		<key>Persist</key>
+		<integer>1</integer>
+		<key>Type</key>
+        <string>String</string>
+        <key>Value</key>
+        <string />
+	</map>
 	<key>MyOutfitsAutofill</key>
 	<map>
 		<key>Comment</key>
@@ -7066,7 +7077,7 @@
     <key>NoInventoryLibrary</key>
     <map>
       <key>Comment</key>
-      <string>Do not request inventory library.</string>
+      <string>(Deprecated) Do not request inventory library.</string>
       <key>Persist</key>
       <integer>1</integer>
       <key>Type</key>
diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl
index d3a05c34c0fe51184c63160848547d312a114ab8..02b2daf0ac547622b27a56aa97e6c2f98328e1f9 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl
@@ -56,6 +56,10 @@ VARYING vec3 vary_norm;
 VARYING vec4 vertex_color; //vertex color should be treated as sRGB
 #endif
 
+#ifdef HAS_ALPHA_MASK
+uniform float minimum_alpha;
+#endif
+
 uniform mat4 proj_mat;
 uniform mat4 inv_proj;
 uniform vec2 screen_res;
@@ -191,7 +195,6 @@ void main()
 #endif
 
     vec4 diffuse_srgb = diffuse_tap;
-    vec4 diffuse_linear = vec4(srgb_to_linear(diffuse_srgb.rgb), diffuse_srgb.a);
 
 #ifdef FOR_IMPOSTOR
     vec4 color;
@@ -200,25 +203,37 @@ void main()
 
     float final_alpha = diffuse_srgb.a * vertex_color.a;
     diffuse_srgb.rgb *= vertex_color.rgb;
-    diffuse_linear.rgb = srgb_to_linear(diffuse_srgb.rgb); 
     
     // Insure we don't pollute depth with invis pixels in impostor rendering
     //
-    if (final_alpha < 0.01)
+    if (final_alpha < minimum_alpha)
     {
         discard;
     }
-#else
-    
+
+    color.rgb = diffuse_srgb.rgb;
+    color.a = final_alpha;
+
+#else // FOR_IMPOSTOR
+
+    vec4 diffuse_linear = vec4(srgb_to_linear(diffuse_srgb.rgb), diffuse_srgb.a);
+
     vec3 light_dir = (sun_up_factor == 1) ? sun_dir: moon_dir;
 
     float final_alpha = diffuse_linear.a;
 
 #ifdef USE_VERTEX_COLOR
     final_alpha *= vertex_color.a;
+
+    if (final_alpha < minimum_alpha)
+    { // TODO: figure out how to get invisible faces out of 
+        // render batches without breaking glow
+        discard;
+    }
+
     diffuse_srgb.rgb *= vertex_color.rgb;
     diffuse_linear.rgb = srgb_to_linear(diffuse_srgb.rgb);
-#endif
+#endif // USE_VERTEX_COLOR
 
     vec3 sunlit;
     vec3 amblit;
@@ -250,13 +265,13 @@ void main()
 #if !defined(AMBIENT_KILL)
     color.rgb = amblit;
     color.rgb *= ambient;
-#endif
+#endif // !defined(AMBIENT_KILL)
 
 vec3 post_ambient = color.rgb;
 
 #if !defined(SUNLIGHT_KILL)
     color.rgb += sun_contrib;
-#endif
+#endif // !defined(SUNLIGHT_KILL)
 
 vec3 post_sunlight = color.rgb;
 
@@ -288,7 +303,7 @@ vec3 post_atmo = color.rgb;
     // sum local light contrib in linear colorspace
 #if !defined(LOCAL_LIGHT_KILL)
     color.rgb += light.rgb;
-#endif
+#endif // !defined(LOCAL_LIGHT_KILL)
     // back to sRGB as we're going directly to the final RT post-deferred gamma correction
     color.rgb = linear_to_srgb(color.rgb);
 
@@ -307,8 +322,8 @@ vec3 post_atmo = color.rgb;
     color = applyWaterFogView(pos.xyz, color);
 #endif // WATER_FOG
 
-#endif
-    
+#endif // #else // FOR_IMPOSTOR
+
     frag_color = color;
 }
 
diff --git a/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl b/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl
index eb6e56e718cf3da79584bcc5792b972e25f2e2e8..a58cc3d12df4213d1d65976df3811a4f7c8bb1d6 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl
@@ -54,8 +54,7 @@ void main()
 	vec4 norm = texture2D(normalMap,   vary_texcoord0.xy);
 	vec4 spec = texture2D(specularMap, vary_texcoord0.xy);
 
-	col.rgb = linear_to_srgb(col.rgb);
 	frag_data[0] = vec4(col.rgb, 0.0);
 	frag_data[1] = spec;
-	frag_data[2] = vec4(norm.xy,0,0);
+	frag_data[2] = norm;
 }
diff --git a/indra/newview/app_settings/shaders/class1/deferred/normgenF.glsl b/indra/newview/app_settings/shaders/class1/deferred/normgenF.glsl
index d0c06cd51f6e7a9341742e346ccb341afa7a239d..7a941674b87363f6ceeb7dc635cab45e55b37aa7 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/normgenF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/normgenF.glsl
@@ -43,18 +43,18 @@ uniform float norm_scale;
 
 void main()
 {
-	float alpha = texture2D(alphaMap, vary_texcoord0).a;
+	float c = texture2D(alphaMap, vary_texcoord0).r;
 
-	vec3 right = vec3(norm_scale, 0, (texture2D(alphaMap, vary_texcoord0+vec2(stepX, 0)).a-alpha)*255);
-	vec3 left = vec3(-norm_scale, 0, (texture2D(alphaMap, vary_texcoord0-vec2(stepX, 0)).a-alpha)*255);
-	vec3 up = vec3(0, -norm_scale, (texture2D(alphaMap, vary_texcoord0-vec2(0, stepY)).a-alpha)*255);
-	vec3 down = vec3(0, norm_scale, (texture2D(alphaMap, vary_texcoord0+vec2(0, stepY)).a-alpha)*255);
+	vec3 right = vec3(norm_scale, 0, (texture2D(alphaMap, vary_texcoord0+vec2(stepX, 0)).r-c)*255);
+	vec3 left = vec3(-norm_scale, 0, (texture2D(alphaMap, vary_texcoord0-vec2(stepX, 0)).r-c)*255);
+	vec3 up = vec3(0, -norm_scale, (texture2D(alphaMap, vary_texcoord0-vec2(0, stepY)).r-c)*255);
+	vec3 down = vec3(0, norm_scale, (texture2D(alphaMap, vary_texcoord0+vec2(0, stepY)).r-c)*255);
 	
 	vec3 norm = cross(right, down) + cross(down, left) + cross(left,up) + cross(up, right);
 	
 	norm = normalize(norm);
 	norm *= 0.5;
 	norm += 0.5;	
-	
-	frag_color = vec4(norm, alpha);
+
+	frag_color = vec4(norm, c);
 }
diff --git a/indra/newview/app_settings/shaders/class1/objects/previewPhysicsF.glsl b/indra/newview/app_settings/shaders/class1/objects/previewPhysicsF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..3a5e6fdf7c440e14e541af9553c1824b502ec1b6
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/objects/previewPhysicsF.glsl
@@ -0,0 +1,42 @@
+/** 
+ * @file previewPhysicsF.glsl
+ *
+ * $LicenseInfo:firstyear=2022&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2022, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#ifdef DEFINE_GL_FRAGCOLOR
+out vec4 frag_color;
+#else
+#define frag_color gl_FragColor
+#endif
+
+uniform sampler2D diffuseMap;
+uniform vec4 color;
+
+VARYING vec2 vary_texcoord0;
+
+//====================================================================================================
+
+void main()
+{
+    frag_color = texture2D(diffuseMap,vary_texcoord0.xy) * color;
+}
diff --git a/indra/newview/app_settings/shaders/class1/objects/previewPhysicsV.glsl b/indra/newview/app_settings/shaders/class1/objects/previewPhysicsV.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..913dec83bd711f9419cb77369df3865a69a308bd
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/objects/previewPhysicsV.glsl
@@ -0,0 +1,42 @@
+/** 
+ * @file previewPhysicsV.glsl
+ *
+ * $LicenseInfo:firstyear=2022&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2022, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+uniform mat4 texture_matrix0;
+uniform mat4 modelview_matrix;
+uniform mat4 modelview_projection_matrix;
+
+ATTRIBUTE vec3 position;
+ATTRIBUTE vec2 texcoord0;
+
+VARYING vec2 vary_texcoord0;
+
+//====================================================================================================
+
+void main()
+{
+	//transform vertex
+	gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0);
+	vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
+}
diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index d3a490f51f02614d606c02dd0a24ca79f5f6f698..d9c7d8b42e769d55f935fbde05776c3956a89d4f 100644
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -1988,7 +1988,8 @@ void LLAgent::propagate(const F32 dt)
 //-----------------------------------------------------------------------------
 void LLAgent::updateAgentPosition(const F32 dt, const F32 yaw_radians, const S32 mouse_x, const S32 mouse_y)
 {
-	if (mMoveTimer.getStarted() && mMoveTimer.getElapsedTimeF32() > gSavedSettings.getF32("NotMovingHintTimeout"))
+    static LLCachedControl<F32> hint_timeout(gSavedSettings, "NotMovingHintTimeout");
+	if (mMoveTimer.getStarted() && mMoveTimer.getElapsedTimeF32() > hint_timeout)
 	{
 		LLFirstUse::notMoving();
 	}
@@ -2159,7 +2160,8 @@ void LLAgent::endAnimationUpdateUI()
 		LLNavigationBar::getInstance()->setVisible(TRUE && gSavedSettings.getBOOL("ShowNavbarNavigationPanel"));
 		gStatusBar->setVisibleForMouselook(true);
 
-		if (gSavedSettings.getBOOL("ShowMiniLocationPanel"))
+        static LLCachedControl<bool> show_mini_location_panel(gSavedSettings, "ShowMiniLocationPanel");
+		if (show_mini_location_panel)
 		{
 			LLPanelTopInfoBar::getInstance()->setVisible(TRUE);
 		}
@@ -3901,10 +3903,6 @@ bool LLAgent::teleportCore(bool is_local)
 	// yet if the teleport will succeed.  Look in 
 	// process_teleport_location_reply
 
-	// close the map panel so we can see our destination.
-	// we don't close search floater, see EXT-5840.
-	LLFloaterReg::hideInstance("world_map");
-
 	// hide land floater too - it'll be out of date
 	LLFloaterReg::hideInstance("about_land");
 
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 66c44ef6a622225acb00d23fa60d3117446ee9c3..a63203f3cba5d2f2fdf6c68392dc5d1c749592be 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -637,6 +637,7 @@ LLAppViewer::LLAppViewer()
 	mLogoutMarkerFile(),
 	mReportedCrash(false),
 	mNumSessions(0),
+    mGeneralThreadPool(nullptr),
 	mPurgeCache(false),
 	mPurgeCacheOnExit(false),
 	mPurgeUserDataOnExit(false),
@@ -1309,10 +1310,13 @@ void LLAppViewer::initMaxHeapSize()
 	//------------------------------------------------------------------------------------------
 	//currently SL is built under 32-bit setting, we set its max heap size no more than 1.6 GB.
 
-	//F32 max_heap_size_gb = llmin(1.6f, (F32)gSavedSettings.getF32("MaxHeapSize")) ;
-	F32Gigabytes max_heap_size_gb = (F32Gigabytes)gSavedSettings.getF32("MaxHeapSize") ;
+ #ifndef LL_X86_64
+    F32Gigabytes max_heap_size_gb = (F32Gigabytes)gSavedSettings.getF32("MaxHeapSize") ;
+#else
+    F32Gigabytes max_heap_size_gb = (F32Gigabytes)gSavedSettings.getF32("MaxHeapSize64");
+#endif
 
-	LLMemory::initMaxHeapSizeGB(max_heap_size_gb);
+    LLMemory::initMaxHeapSizeGB(max_heap_size_gb);
 }
 
 static LLTrace::BlockTimerStatHandle FTM_MESSAGES("System Messages");
@@ -1709,11 +1713,6 @@ void LLAppViewer::flushLFSIO()
 
 bool LLAppViewer::cleanup()
 {
-	// Since we don't know what functions are going to be queued by
-	// onCleanup(), we have to assume they might rely on some of the things
-	// we're about to destroy below. Run them first.
-	mOnCleanup();
-
     LLAtmosphere::cleanupClass();
 
 	//ditch LLVOAvatarSelf instance
@@ -2067,6 +2066,10 @@ bool LLAppViewer::cleanup()
 	sTextureCache->shutdown();
 	sImageDecodeThread->shutdown();
 	sPurgeDiskCacheThread->shutdown();
+    if (mGeneralThreadPool)
+    {
+        mGeneralThreadPool->close();
+    }
 
 	sTextureFetch->shutDownTextureCacheThread() ;
 	sTextureFetch->shutDownImageDecodeThread() ;
@@ -2091,6 +2094,8 @@ bool LLAppViewer::cleanup()
 	mFastTimerLogThread = NULL;
 	delete sPurgeDiskCacheThread;
 	sPurgeDiskCacheThread = NULL;
+    delete mGeneralThreadPool;
+    mGeneralThreadPool = NULL;
 
 	if (LLFastTimerView::sAnalyzePerformance)
 	{
@@ -2156,6 +2161,7 @@ bool LLAppViewer::cleanup()
 	LLEnvironment::deleteSingleton();
 	LLSelectMgr::deleteSingleton();
 	LLViewerEventRecorder::deleteSingleton();
+    LLWorld::deleteSingleton();
 
 	// It's not at first obvious where, in this long sequence, a generic cleanup
 	// call OUGHT to go. So let's say this: as we migrate cleanup from
@@ -2176,6 +2182,24 @@ bool LLAppViewer::cleanup()
 	return true;
 }
 
+void LLAppViewer::initGeneralThread()
+{
+    if (mGeneralThreadPool)
+    {
+        return;
+    }
+
+    LLSD poolSizes{ gSavedSettings.getLLSD("ThreadPoolSizes") };
+    LLSD sizeSpec{ poolSizes["General"] };
+    LLSD::Integer poolSize{ sizeSpec.isInteger() ? sizeSpec.asInteger() : 3 };
+    LL_DEBUGS("ThreadPool") << "Instantiating General pool with "
+        << poolSize << " threads" << LL_ENDL;
+    // We don't want anyone, especially the main thread, to have to block
+    // due to this ThreadPool being full.
+    mGeneralThreadPool = new LL::ThreadPool("General", poolSize, 1024 * 1024);
+    mGeneralThreadPool->start();
+}
+
 bool LLAppViewer::initThreads()
 {
 	static const bool enable_threads = true;
@@ -5365,14 +5389,18 @@ void LLAppViewer::disconnectViewer()
 	}
 
 	// save inventory if appropriate
-	gInventory.cache(gInventory.getRootFolderID(), gAgent.getID());
-	if (gInventory.getLibraryRootFolderID().notNull()
-		&& gInventory.getLibraryOwnerID().notNull())
-	{
-		gInventory.cache(
-			gInventory.getLibraryRootFolderID(),
-			gInventory.getLibraryOwnerID());
-	}
+    if (gInventory.isInventoryUsable()
+        && gAgent.getID().notNull()) // Shouldn't be null at this stage
+    {
+        gInventory.cache(gInventory.getRootFolderID(), gAgent.getID());
+        if (gInventory.getLibraryRootFolderID().notNull()
+            && gInventory.getLibraryOwnerID().notNull())
+        {
+            gInventory.cache(
+                gInventory.getLibraryRootFolderID(),
+                gInventory.getLibraryOwnerID());
+        }
+    }
 
 	saveNameCache();
 	if (LLExperienceCache::instanceExists())
@@ -5394,7 +5422,7 @@ void LLAppViewer::disconnectViewer()
 	// Now we just ask the LLWorld singleton to cleanly shut down.
 	if(LLWorld::instanceExists())
 	{
-		LLWorld::getInstance()->destroyClass();
+		LLWorld::getInstance()->resetClass();
 	}
 	LLVOCache::deleteSingleton();
 
diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h
index d807cf9765e0f60dfe568ca48c0c3af454d1179a..a86fa7d8733de1e5b2347db24b78d772e3378025 100644
--- a/indra/newview/llappviewer.h
+++ b/indra/newview/llappviewer.h
@@ -63,6 +63,11 @@ class LLViewerJoystick;
 class LLPurgeDiskCacheThread;
 class LLViewerRegion;
 
+namespace LL
+{
+    class ThreadPool;
+}
+
 extern LLTrace::BlockTimerStatHandle FTM_FRAME;
 
 class LLAppViewer : public LLApp
@@ -201,13 +206,7 @@ class LLAppViewer : public LLApp
 
 	void addOnIdleCallback(const boost::function<void()>& cb); // add a callback to fire (once) when idle
 
-	typedef boost::signals2::signal<void()> cleanup_signal_t;
-	cleanup_signal_t mOnCleanup;
-	boost::signals2::connection onCleanup(const cleanup_signal_t::slot_type& cb)
-	{
-		return mOnCleanup.connect(cb);
-	}
-
+    void initGeneralThread();
 	void purgeUserDataOnExit() { mPurgeUserDataOnExit = true; }
 	void purgeCache(); // Clear the local cache. 
 	void purgeCacheImmediate(); //clear local cache immediately.
@@ -269,7 +268,6 @@ class LLAppViewer : public LLApp
 	void idle(); 
 	void idleShutdown();
 	// update avatar SLID and display name caches
-	void idleExperienceCache();
 	void idleNameCache();
 	void idleNetwork();
 
@@ -298,6 +296,7 @@ class LLAppViewer : public LLApp
 	static LLImageDecodeThread* sImageDecodeThread; 
 	static LLTextureFetch* sTextureFetch;
 	static LLPurgeDiskCacheThread* sPurgeDiskCacheThread;
+    LL::ThreadPool* mGeneralThreadPool;
 
 	S32 mNumSessions;
 
diff --git a/indra/newview/llappviewerwin32.h b/indra/newview/llappviewerwin32.h
index 82b6b0c77c8089fa8ad911a481984f8b1df43273..ab52bf15f9e7d7fa51643dff8e526244c68b4fe4 100644
--- a/indra/newview/llappviewerwin32.h
+++ b/indra/newview/llappviewerwin32.h
@@ -51,8 +51,8 @@ class LLAppViewerWin32 : public LLAppViewer
 	bool initHardwareTest() override; // Win32 uses DX9 to test hardware.
 	bool initParseCommandLine(LLCommandLineParser& clp) override;
 
-	virtual bool beingDebugged();
-	virtual bool restoreErrorTrap();
+	bool beingDebugged() override;
+	bool restoreErrorTrap() override;
 
 	bool sendURLToOtherInstance(const std::string& url) override;
 
diff --git a/indra/newview/llavatarrenderinfoaccountant.cpp b/indra/newview/llavatarrenderinfoaccountant.cpp
index ca83afb5ab070e69d40ae80bc457fdb4e911a4b6..fe94cd27b6d5dfb0e9d938f37965d3bf7658cb9d 100644
--- a/indra/newview/llavatarrenderinfoaccountant.cpp
+++ b/indra/newview/llavatarrenderinfoaccountant.cpp
@@ -82,7 +82,15 @@ void LLAvatarRenderInfoAccountant::avatarRenderInfoGetCoro(std::string url, U64
 
     LLSD result = httpAdapter->getAndSuspend(httpRequest, url);
 
-    LLViewerRegion * regionp = LLWorld::getInstance()->getRegionFromHandle(regionHandle);
+    LLWorld *world_inst = LLWorld::getInstance();
+    if (!world_inst)
+    {
+        LL_WARNS("AvatarRenderInfoAccountant") << "Avatar render weight info received but world no longer exists "
+            << regionHandle << LL_ENDL;
+        return;
+    }
+
+    LLViewerRegion * regionp = world_inst->getRegionFromHandle(regionHandle);
     if (!regionp)
     {
         LL_WARNS("AvatarRenderInfoAccountant") << "Avatar render weight info received but region not found for " 
@@ -183,7 +191,15 @@ void LLAvatarRenderInfoAccountant::avatarRenderInfoReportCoro(std::string url, U
         httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("AvatarRenderInfoAccountant", httpPolicy));
     LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
 
-    LLViewerRegion * regionp = LLWorld::getInstance()->getRegionFromHandle(regionHandle);
+    LLWorld *world_inst = LLWorld::getInstance();
+    if (!world_inst)
+    {
+        LL_WARNS("AvatarRenderInfoAccountant") << "Avatar render weight calculation but world no longer exists "
+            << regionHandle << LL_ENDL;
+        return;
+    }
+
+    LLViewerRegion * regionp = world_inst->getRegionFromHandle(regionHandle);
     if (!regionp)
     {
         LL_WARNS("AvatarRenderInfoAccountant") << "Avatar render weight calculation but region not found for "
@@ -239,9 +255,18 @@ void LLAvatarRenderInfoAccountant::avatarRenderInfoReportCoro(std::string url, U
     report[KEY_AGENTS] = agents;
 
     regionp = NULL;
+    world_inst = NULL;
     LLSD result = httpAdapter->postAndSuspend(httpRequest, url, report);
 
-    regionp = LLWorld::getInstance()->getRegionFromHandle(regionHandle);
+    world_inst = LLWorld::getInstance();
+    if (!world_inst)
+    {
+        LL_WARNS("AvatarRenderInfoAccountant") << "Avatar render weight POST result but world no longer exists "
+            << regionHandle << LL_ENDL;
+        return;
+    }
+
+    regionp = world_inst->getRegionFromHandle(regionHandle);
     if (!regionp)
     {
         LL_INFOS("AvatarRenderInfoAccountant") << "Avatar render weight POST result received but region not found for "
@@ -345,6 +370,8 @@ void LLAvatarRenderInfoAccountant::idle()
 				&& regionp->capabilitiesReceived())
 			{
 				// each of these is further governed by and resets its own timer
+                // Note: We can have multiple regions, each launches up to two coroutines,
+                // it likely is expensive
 				sendRenderInfoToRegion(regionp);
 				getRenderInfoFromRegion(regionp);
 			}
diff --git a/indra/newview/llcallingcard.cpp b/indra/newview/llcallingcard.cpp
index 9ee9900ebad998261678b9cd6a77844adca1f193..bddbc79df4f71207e51a68dbde4b13c2c4702577 100644
--- a/indra/newview/llcallingcard.cpp
+++ b/indra/newview/llcallingcard.cpp
@@ -645,7 +645,8 @@ void LLAvatarTracker::processChange(LLMessageSystem* msg)
 		{
 			if(mBuddyInfo.find(agent_id) != mBuddyInfo.end())
 			{
-				if((mBuddyInfo[agent_id]->getRightsGrantedFrom() ^  new_rights) & LLRelationship::GRANT_MODIFY_OBJECTS)
+                if (((mBuddyInfo[agent_id]->getRightsGrantedFrom() ^  new_rights) & LLRelationship::GRANT_MODIFY_OBJECTS)
+                    && !gAgent.isDoNotDisturb())
 				{
 					LLSD args;
 					args["NAME"] = LLSLURL("agent", agent_id, "displayname").getSLURLString();
diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp
index c110e0d815f11ed48c47d6b1946220bb879427a0..cdf82c77c1bd2f65c70f7ce58e0043495702a1d2 100644
--- a/indra/newview/llchathistory.cpp
+++ b/indra/newview/llchathistory.cpp
@@ -752,7 +752,7 @@ class LLChatHistoryHeader: public LLPanel
 		if ( chat.mSourceType == CHAT_SOURCE_OBJECT)
 		{
 			std::string slurl = args["slurl"].asString();
-			if (slurl.empty())
+			if (slurl.empty() && LLWorld::instanceExists())
 			{
 				LLViewerRegion *region = LLWorld::getInstance()->getRegionFromPosAgent(chat.mPosAgent);
 				if(region)
diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp
index fee85d50bd4305521109f995fcb8088ba1147687..20fa6d490b4562c24c3bf13349103130b07d61af 100644
--- a/indra/newview/llconversationview.cpp
+++ b/indra/newview/llconversationview.cpp
@@ -96,10 +96,14 @@ LLConversationViewSession::~LLConversationViewSession()
 {
 	mActiveVoiceChannelConnection.disconnect();
 
-	if(LLVoiceClient::instanceExists() && mVoiceClientObserver)
-	{
-		LLVoiceClient::getInstance()->removeObserver(mVoiceClientObserver);
-	}
+    if (mVoiceClientObserver)
+    {
+        if (LLVoiceClient::instanceExists())
+        {
+            LLVoiceClient::getInstance()->removeObserver(mVoiceClientObserver);
+        }
+        delete mVoiceClientObserver;
+    }
 
 	mFlashTimer->unset();
 }
@@ -255,7 +259,12 @@ BOOL LLConversationViewSession::postBuild()
 			mIsInActiveVoiceChannel = true;
 			if(LLVoiceClient::instanceExists())
 			{
-				LLNearbyVoiceClientStatusObserver* mVoiceClientObserver = new LLNearbyVoiceClientStatusObserver(this);
+                if (mVoiceClientObserver)
+                {
+                    LLVoiceClient::getInstance()->removeObserver(mVoiceClientObserver);
+                    delete mVoiceClientObserver;
+                }
+				mVoiceClientObserver = new LLNearbyVoiceClientStatusObserver(this);
 				LLVoiceClient::getInstance()->addObserver(mVoiceClientObserver);
 			}
 			break;
diff --git a/indra/newview/lldrawpool.cpp b/indra/newview/lldrawpool.cpp
index faa5f71da42ff533f28b4a409cbcd783493a1df9..a3837fe10c68d3758bfbdada979edbe4402d7f84 100644
--- a/indra/newview/lldrawpool.cpp
+++ b/indra/newview/lldrawpool.cpp
@@ -451,7 +451,7 @@ void LLRenderPass::pushRiggedBatches(U32 type, U32 mask, BOOL texture, BOOL batc
         LLDrawInfo* pparams = *i;
         if (pparams)
         {
-            if (lastAvatar != pparams->mAvatar || lastMeshId != pparams->mSkinInfo->mHash)
+            if (pparams->mAvatar.notNull() && (lastAvatar != pparams->mAvatar || lastMeshId != pparams->mSkinInfo->mHash))
             {
                 uploadMatrixPalette(*pparams);
                 lastAvatar = pparams->mAvatar;
@@ -596,6 +596,10 @@ bool LLRenderPass::uploadMatrixPalette(LLDrawInfo& params)
 //static
 bool LLRenderPass::uploadMatrixPalette(LLVOAvatar* avatar, LLMeshSkinInfo* skinInfo)
 {
+    if (!avatar)
+    {
+        return false;
+    }
     const LLVOAvatar::MatrixPaletteCache& mpc = avatar->updateSkinInfoMatrixPalette(skinInfo);
     U32 count = mpc.mMatrixPalette.size();
 
diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp
index 2bf8e9b9112d0798aed014436f31d2fc6e4691ff..eebd89f77fd39eadd5386c34aff34e74cf20c97a 100644
--- a/indra/newview/lldrawpoolalpha.cpp
+++ b/indra/newview/lldrawpoolalpha.cpp
@@ -56,6 +56,11 @@ BOOL LLDrawPoolAlpha::sShowDebugAlpha = FALSE;
 
 static BOOL deferred_render = FALSE;
 
+// minimum alpha before discarding a fragment
+static const F32 MINIMUM_ALPHA = 0.004f; // ~ 1/255
+// minimum alpha before discarding a fragment when rendering impostors
+static const F32 MINIMUM_IMPOSTOR_ALPHA = 0.1f;
+
 LLDrawPoolAlpha::LLDrawPoolAlpha(U32 type) :
 		LLRenderPass(type), target_shader(NULL),
 		mColorSFactor(LLRender::BF_UNDEF), mColorDFactor(LLRender::BF_UNDEF),
@@ -106,11 +111,11 @@ static void prepare_alpha_shader(LLGLSLShader* shader, bool textureGamma, bool d
 
     if (LLPipeline::sImpostorRender)
     {
-        shader->setMinimumAlpha(0.5f);
+        shader->setMinimumAlpha(MINIMUM_IMPOSTOR_ALPHA);
     }
     else
     {
-        shader->setMinimumAlpha(0.f);
+        shader->setMinimumAlpha(MINIMUM_ALPHA);
     }
     if (textureGamma)
     {
@@ -130,14 +135,15 @@ void LLDrawPoolAlpha::renderPostDeferred(S32 pass)
     deferred_render = TRUE;
 
     // prepare shaders
-    emissive_shader = (LLPipeline::sUnderWaterRender) ? &gObjectEmissiveWaterProgram : &gObjectEmissiveProgram;
+    emissive_shader = (LLPipeline::sRenderDeferred)   ? &gDeferredEmissiveProgram    :
+                      (LLPipeline::sUnderWaterRender) ? &gObjectEmissiveWaterProgram : &gObjectEmissiveProgram;
     prepare_alpha_shader(emissive_shader, true, false);
 
-    fullbright_shader = (LLPipeline::sImpostorRender) ? &gDeferredFullbrightProgram :
-        (LLPipeline::sUnderWaterRender) ? &gDeferredFullbrightWaterProgram : &gDeferredFullbrightProgram;
+    fullbright_shader   = (LLPipeline::sImpostorRender) ? &gDeferredFullbrightAlphaMaskProgram :
+        (LLPipeline::sUnderWaterRender) ? &gDeferredFullbrightWaterProgram : &gDeferredFullbrightAlphaMaskProgram;
     prepare_alpha_shader(fullbright_shader, true, false);
 
-    simple_shader = (LLPipeline::sImpostorRender) ? &gDeferredAlphaImpostorProgram :
+    simple_shader   = (LLPipeline::sImpostorRender) ? &gDeferredAlphaImpostorProgram :
         (LLPipeline::sUnderWaterRender) ? &gDeferredAlphaWaterProgram : &gDeferredAlphaProgram;
     prepare_alpha_shader(simple_shader, false, true); //prime simple shader (loads shadow relevant uniforms)
 
@@ -196,18 +202,18 @@ void LLDrawPoolAlpha::render(S32 pass)
     LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL;
 
     simple_shader = (LLPipeline::sImpostorRender) ? &gObjectSimpleImpostorProgram :
-        (LLPipeline::sUnderWaterRender) ? &gObjectSimpleWaterProgram : &gObjectSimpleProgram;
+        (LLPipeline::sUnderWaterRender) ? &gObjectSimpleWaterProgram : &gObjectSimpleAlphaMaskProgram;
 
-    fullbright_shader = (LLPipeline::sImpostorRender) ? &gObjectFullbrightProgram :
-        (LLPipeline::sUnderWaterRender) ? &gObjectFullbrightWaterProgram : &gObjectFullbrightProgram;
+    fullbright_shader = (LLPipeline::sImpostorRender) ? &gObjectFullbrightAlphaMaskProgram :
+        (LLPipeline::sUnderWaterRender) ? &gObjectFullbrightWaterProgram : &gObjectFullbrightAlphaMaskProgram;
 
     emissive_shader = (LLPipeline::sImpostorRender) ? &gObjectEmissiveProgram :
         (LLPipeline::sUnderWaterRender) ? &gObjectEmissiveWaterProgram : &gObjectEmissiveProgram;
 
-    F32 minimum_alpha = 0.f;
+    F32 minimum_alpha = MINIMUM_ALPHA;
     if (LLPipeline::sImpostorRender)
     {
-        minimum_alpha = 0.5f;
+        minimum_alpha = MINIMUM_IMPOSTOR_ALPHA;
     }
     prepare_forward_shader(fullbright_shader, minimum_alpha);
     prepare_forward_shader(simple_shader, minimum_alpha);
@@ -228,8 +234,8 @@ void LLDrawPoolAlpha::forwardRender(bool rigged)
     //enable writing to alpha for emissive effects
     gGL.setColorMask(true, true);
 
-    bool write_depth = rigged
-        || LLDrawPoolWater::sSkipScreenCopy
+    bool write_depth = rigged || 
+        LLDrawPoolWater::sSkipScreenCopy
         // we want depth written so that rendered alpha will
         // contribute to the alpha mask used for impostors
         || LLPipeline::sImpostorRenderAlphaDepthPass;
@@ -484,6 +490,7 @@ void LLDrawPoolAlpha::renderEmissives(U32 mask, std::vector<LLDrawInfo*>& emissi
 
 void LLDrawPoolAlpha::renderRiggedEmissives(U32 mask, std::vector<LLDrawInfo*>& emissives)
 {
+    LLGLDepthTest depth(GL_TRUE, GL_FALSE); //disable depth writes since "emissive" is additive so sorting doesn't matter
     LLGLSLShader* shader = emissive_shader->mRiggedVariant;
     shader->bind();
     shader->uniform1f(LLShaderMgr::EMISSIVE_BRIGHTNESS, 1.f);
@@ -587,7 +594,7 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, bool depth_only, bool rigged)
 						const LLTextureEntry* tep = face->getTextureEntry();
 						if(tep)
 						{ // don't render faces that are more than 90% transparent
-							if(tep->getColor().mV[3] < 0.1f)
+							if(tep->getColor().mV[3] < MINIMUM_IMPOSTOR_ALPHA)
 								continue;
 						}
 					}
@@ -795,6 +802,10 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, bool depth_only, bool rigged)
 
 bool LLDrawPoolAlpha::uploadMatrixPalette(const LLDrawInfo& params)
 {
+    if (params.mAvatar.isNull())
+    {
+        return false;
+    }
     const LLVOAvatar::MatrixPaletteCache& mpc = params.mAvatar.get()->updateSkinInfoMatrixPalette(params.mSkinInfo);
     U32 count = mpc.mMatrixPalette.size();
 
diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp
index 1d5419b515a1c6e3974a8108c0308c6d295439ac..2892fc6f9f533c3bf2270e48016ad085d7bfdb03 100644
--- a/indra/newview/lldrawpoolbump.cpp
+++ b/indra/newview/lldrawpoolbump.cpp
@@ -56,6 +56,7 @@
 LLStandardBumpmap gStandardBumpmapList[TEM_BUMPMAP_COUNT]; 
 LL::WorkQueue::weak_t LLBumpImageList::sMainQueue;
 LL::WorkQueue::weak_t LLBumpImageList::sTexUpdateQueue;
+LLRenderTarget LLBumpImageList::sRenderTarget;
 
 // static
 U32 LLStandardBumpmap::sStandardBumpmapCount = 0;
@@ -76,7 +77,7 @@ static S32 cube_channel = -1;
 static S32 diffuse_channel = -1;
 static S32 bump_channel = -1;
 
-#define LL_BUMPLIST_MULTITHREADED 0
+#define LL_BUMPLIST_MULTITHREADED 0 // TODO -- figure out why this doesn't work
 
 // static 
 void LLStandardBumpmap::init()
@@ -776,6 +777,8 @@ void LLBumpImageList::clear()
 	mBrightnessEntries.clear();
 	mDarknessEntries.clear();
 
+    sRenderTarget.release();
+
 	LLStandardBumpmap::clear();
 }
 
@@ -1032,6 +1035,8 @@ void LLBumpImageList::generateNormalMapFromAlpha(LLImageRaw* src, LLImageRaw* nr
 // static
 void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerTexture *src_vi, LLImageRaw* src, LLUUID& source_asset_id, EBumpEffect bump_code )
 {
+    LL_PROFILE_ZONE_SCOPED;
+
 	if( success )
 	{
         LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL;
@@ -1201,145 +1206,111 @@ void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerTexture *src_vi, LLI
 			}
 			else 
 			{ //convert to normal map
-				
-				//disable compression on normal maps to prevent errors below
-				bump->getGLTexture()->setAllowCompression(false);
-                bump->getGLTexture()->setUseMipMaps(TRUE);
-
-                auto* bump_ptr = bump.get();
-                auto* dst_ptr = dst_image.get();
+                LL_PROFILE_ZONE_NAMED("bil - create normal map");
+                LLImageGL* img = bump->getGLTexture();
+                LLImageRaw* dst_ptr = dst_image.get();
+                LLGLTexture* bump_ptr = bump.get();
 
-#if LL_BUMPLIST_MULTITHREADED
-                bump_ptr->ref();
                 dst_ptr->ref();
-#endif
-
-                bump_ptr->setExplicitFormat(GL_RGBA8, GL_ALPHA);
-
-                auto create_texture = [=]()
+                img->ref();
+                bump_ptr->ref();
+                auto create_func = [=]()
                 {
-#if LL_IMAGEGL_THREAD_CHECK
-                    bump_ptr->getGLTexture()->mActiveThread = LLThread::currentID();
-#endif
-                    LL_PROFILE_ZONE_NAMED("bil - create texture deferred");
+                    img->setUseMipMaps(TRUE);
+                    // upload dst_image to GPU (greyscale in red channel)
+                    img->setExplicitFormat(GL_RED, GL_RED);
+
                     bump_ptr->createGLTexture(0, dst_ptr);
+                    dst_ptr->unref();
                 };
 
-                auto gen_normal_map = [=]()
+                auto generate_func = [=]()
                 {
-#if LL_IMAGEGL_THREAD_CHECK
-                    bump_ptr->getGLTexture()->mActiveThread = LLThread::currentID();
-#endif
-                    LL_PROFILE_ZONE_NAMED("bil - generate normal map");
-                    if (gNormalMapGenProgram.mProgramObject == 0)
-                    {
-#if LL_BUMPLIST_MULTITHREADED
-                        bump_ptr->unref();
-                        dst_ptr->unref();
-#endif
-                        return;
-                    }
-                    gPipeline.mScreen.bindTarget();
-
-                    LLGLDepthTest depth(GL_FALSE);
-                    LLGLDisable cull(GL_CULL_FACE);
-                    LLGLDisable blend(GL_BLEND);
-                    gGL.setColorMask(TRUE, TRUE);
-                    gNormalMapGenProgram.bind();
-
-                    static LLStaticHashedString sNormScale("norm_scale");
-                    static LLStaticHashedString sStepX("stepX");
-                    static LLStaticHashedString sStepY("stepY");
-
-                    gNormalMapGenProgram.uniform1f(sNormScale, gSavedSettings.getF32("RenderNormalMapScale"));
-                    gNormalMapGenProgram.uniform1f(sStepX, 1.f / bump_ptr->getWidth());
-                    gNormalMapGenProgram.uniform1f(sStepY, 1.f / bump_ptr->getHeight());
+                    // Allocate an empty RGBA texture at "tex_name" the same size as bump
+                    //  Note: bump will still point at GPU copy of dst_image
+                    bump_ptr->setExplicitFormat(GL_RGBA, GL_RGBA);
+                    LLGLuint tex_name;
+                    img->createGLTexture(0, nullptr, 0, 0, true, &tex_name);
 
-                    LLVector2 v((F32)bump_ptr->getWidth() / gPipeline.mScreen.getWidth(),
-                        (F32)bump_ptr->getHeight() / gPipeline.mScreen.getHeight());
+                    // point render target at empty buffer
+                    sRenderTarget.setColorAttachment(img, tex_name);
 
-                    gGL.getTexUnit(0)->bind(bump_ptr);
-
-                    S32 width = bump_ptr->getWidth();
-                    S32 height = bump_ptr->getHeight();
-
-                    S32 screen_width = gPipeline.mScreen.getWidth();
-                    S32 screen_height = gPipeline.mScreen.getHeight();
-
-                    glViewport(0, 0, screen_width, screen_height);
-
-                    for (S32 left = 0; left < width; left += screen_width)
+                    // generate normal map in empty texture
                     {
-                        S32 right = left + screen_width;
-                        right = llmin(right, width);
+                        sRenderTarget.bindTarget();
 
-                        F32 left_tc = (F32)left / width;
-                        F32 right_tc = (F32)right / width;
+                        LLGLDepthTest depth(GL_FALSE);
+                        LLGLDisable cull(GL_CULL_FACE);
+                        LLGLDisable blend(GL_BLEND);
+                        gGL.setColorMask(TRUE, TRUE);
 
-                        for (S32 bottom = 0; bottom < height; bottom += screen_height)
-                        {
-                            S32 top = bottom + screen_height;
-                            top = llmin(top, height);
+                        gNormalMapGenProgram.bind();
 
-                            F32 bottom_tc = (F32)bottom / height;
-                            F32 top_tc = (F32)(bottom + screen_height) / height;
-                            top_tc = llmin(top_tc, 1.f);
+                        static LLStaticHashedString sNormScale("norm_scale");
+                        static LLStaticHashedString sStepX("stepX");
+                        static LLStaticHashedString sStepY("stepY");
 
-                            F32 screen_right = (F32)(right - left) / screen_width;
-                            F32 screen_top = (F32)(top - bottom) / screen_height;
+                        gNormalMapGenProgram.uniform1f(sNormScale, gSavedSettings.getF32("RenderNormalMapScale"));
+                        gNormalMapGenProgram.uniform1f(sStepX, 1.f / bump_ptr->getWidth());
+                        gNormalMapGenProgram.uniform1f(sStepY, 1.f / bump_ptr->getHeight());
 
-                            gGL.begin(LLRender::TRIANGLE_STRIP);
-                            gGL.texCoord2f(left_tc, bottom_tc);
-                            gGL.vertex2f(0, 0);
+                        gGL.getTexUnit(0)->bind(bump_ptr);
 
-                            gGL.texCoord2f(left_tc, top_tc);
-                            gGL.vertex2f(0, screen_top);
+                        gGL.begin(LLRender::TRIANGLE_STRIP);
+                        gGL.texCoord2f(0, 0);
+                        gGL.vertex2f(0, 0);
 
-                            gGL.texCoord2f(right_tc, bottom_tc);
-                            gGL.vertex2f(screen_right, 0);
+                        gGL.texCoord2f(0, 1);
+                        gGL.vertex2f(0, 1);
 
-                            gGL.texCoord2f(right_tc, top_tc);
-                            gGL.vertex2f(screen_right, screen_top);
+                        gGL.texCoord2f(1, 0);
+                        gGL.vertex2f(1, 0);
 
-                            gGL.end();
+                        gGL.texCoord2f(1, 1);
+                        gGL.vertex2f(1, 1);
 
-                            gGL.flush();
+                        gGL.end();
 
-                            S32 w = right - left;
-                            S32 h = top - bottom;
+                        gGL.flush();
 
-                            glCopyTexSubImage2D(GL_TEXTURE_2D, 0, left, bottom, 0, 0, w, h);
-                        }
-                    }
+                        gNormalMapGenProgram.unbind();
 
-                    glGenerateMipmap(GL_TEXTURE_2D);
+                        sRenderTarget.flush();
+                        sRenderTarget.releaseColorAttachment();
+                    }
 
-                    gPipeline.mScreen.flush();
+                    // point bump at normal map and free gpu copy of dst_image
+                    img->syncTexName(tex_name);
 
-                    gNormalMapGenProgram.unbind();
+                    // generate mipmap
+                    gGL.getTexUnit(0)->bind(img);
+                    glGenerateMipmap(GL_TEXTURE_2D);
+                    gGL.getTexUnit(0)->disable();
 
-                    //generateNormalMapFromAlpha(dst_image, nrm_image);
-#if LL_BUMPLIST_MULTITHREADED
                     bump_ptr->unref();
-                    dst_ptr->unref();
-#endif
+                    img->unref();
                 };
 
 #if LL_BUMPLIST_MULTITHREADED
-                auto main_queue = sMainQueue.lock();
-
-                if (LLImageGLThread::sEnabled)
-                { //dispatch creation to background thread
-                    main_queue->postTo(sTexUpdateQueue, create_texture, gen_normal_map);
+                auto main_queue = LLImageGLThread::sEnabled ? sMainQueue.lock() : nullptr;
+
+                if (main_queue)
+                { //dispatch texture upload to background thread, issue GPU commands to generate normal map on main thread
+                    main_queue->postTo(
+                        sTexUpdateQueue,
+                        create_func,
+                        generate_func);
                 }
                 else
 #endif
-                {
-                    create_texture();
-                    gen_normal_map();
+                { // immediate upload texture and generate normal map
+                    create_func();
+                    generate_func();
                 }
+
+
 			}
-		
+
 			iter->second = bump; // derefs (and deletes) old image
 			//---------------------------------------------------
 		}
diff --git a/indra/newview/lldrawpoolbump.h b/indra/newview/lldrawpoolbump.h
index 6e218597387188f560d96d1e55f773b7f6b373dc..e8a027967bcca922e44c560f2471874a1c22bed1 100644
--- a/indra/newview/lldrawpoolbump.h
+++ b/indra/newview/lldrawpoolbump.h
@@ -163,6 +163,7 @@ class LLBumpImageList
 	bump_image_map_t mDarknessEntries;
     static LL::WorkQueue::weak_t sMainQueue;
     static LL::WorkQueue::weak_t sTexUpdateQueue;
+    static LLRenderTarget sRenderTarget;
 };
 
 extern LLBumpImageList gBumpImageList;
diff --git a/indra/newview/lldrawpoolmaterials.cpp b/indra/newview/lldrawpoolmaterials.cpp
index 135770c99cbadeeae0391392311569e97f0f4bc3..2b05f4c4532ae77301a51ae2a5061a7d0a941ef8 100644
--- a/indra/newview/lldrawpoolmaterials.cpp
+++ b/indra/newview/lldrawpoolmaterials.cpp
@@ -243,7 +243,7 @@ void LLDrawPoolMaterials::pushMaterialsBatch(LLDrawInfo& params, U32 mask, bool
 	}
 
     // upload matrix palette to shader
-    if (rigged)
+    if (rigged && params.mAvatar.notNull())
     {
         const LLVOAvatar::MatrixPaletteCache& mpc = params.mAvatar->updateSkinInfoMatrixPalette(params.mSkinInfo);
         U32 count = mpc.mMatrixPalette.size();
diff --git a/indra/newview/lldrawpoolwater.cpp b/indra/newview/lldrawpoolwater.cpp
index 6762b38c3957a64204062552a658dee52556581c..a84f62036e45c9739d4b0f60b5f4ec9e85405711 100644
--- a/indra/newview/lldrawpoolwater.cpp
+++ b/indra/newview/lldrawpoolwater.cpp
@@ -624,18 +624,10 @@ void LLDrawPoolWater::renderWater()
 
         shader->uniform3fv(LLShaderMgr::WATER_SPECULAR, 1, light_diffuse.mV);
         shader->uniform1f(LLShaderMgr::WATER_SPECULAR_EXP, light_exp);
-        if (LLEnvironment::instance().isCloudScrollPaused())
-        {
-            static const std::array<F32, 2> zerowave {{0.0f, 0.0f}};
 
-            shader->uniform2fv(LLShaderMgr::WATER_WAVE_DIR1, 1, zerowave.data());
-            shader->uniform2fv(LLShaderMgr::WATER_WAVE_DIR2, 1, zerowave.data());
-        }
-        else
-        {
-            shader->uniform2fv(LLShaderMgr::WATER_WAVE_DIR1, 1, pwater->getWave1Dir().mV);
-            shader->uniform2fv(LLShaderMgr::WATER_WAVE_DIR2, 1, pwater->getWave2Dir().mV);
-        }
+        shader->uniform2fv(LLShaderMgr::WATER_WAVE_DIR1, 1, pwater->getWave1Dir().mV);
+        shader->uniform2fv(LLShaderMgr::WATER_WAVE_DIR2, 1, pwater->getWave2Dir().mV);
+
         shader->uniform3fv(LLShaderMgr::WATER_LIGHT_DIR, 1, light_dir.mV);
 
         shader->uniform3fv(LLShaderMgr::WATER_NORM_SCALE, 1, pwater->getNormalScale().mV);
diff --git a/indra/newview/llenvironment.cpp b/indra/newview/llenvironment.cpp
index 42f3d15a1c1536f3886f6823727836dedfb36733..b76dc6a96142487fcc6b82373aaeb8798585b207 100644
--- a/indra/newview/llenvironment.cpp
+++ b/indra/newview/llenvironment.cpp
@@ -1155,6 +1155,10 @@ void LLEnvironment::setEnvironment(LLEnvironment::EnvSelection_t env, const LLSe
         mSignalEnvChanged(env, env_version);
 }
 
+void LLEnvironment::setCurrentEnvironmentSelection(LLEnvironment::EnvSelection_t env)
+{
+    mCurrentEnvironment->setEnvironmentSelection(env);
+}
 
 void LLEnvironment::setEnvironment(LLEnvironment::EnvSelection_t env, LLEnvironment::fixedEnvironment_t fixed, S32 env_version)
 {
@@ -1761,8 +1765,22 @@ void LLEnvironment::updateShaderUniforms(LLGLSLShader* shader)
 
 void LLEnvironment::updateSettingsUniforms()
 {
-    updateGLVariablesForSettings(mWaterUniforms, mCurrentEnvironment->getWater());
-    updateGLVariablesForSettings(mSkyUniforms, mCurrentEnvironment->getSky());
+    if (mCurrentEnvironment->getWater())
+    {
+        updateGLVariablesForSettings(mWaterUniforms, mCurrentEnvironment->getWater());
+    }
+    else
+    {
+        LL_WARNS("ENVIRONMENT") << "Failed to update GL variable for water settings, environment is not properly set" << LL_ENDL;
+    }
+    if (mCurrentEnvironment->getSky())
+    {
+        updateGLVariablesForSettings(mSkyUniforms, mCurrentEnvironment->getSky());
+    }
+    else
+    {
+        LL_WARNS("ENVIRONMENT") << "Failed to update GL variable for sky settings, environment is not properly set" << LL_ENDL;
+    }
 }
 
 void LLEnvironment::recordEnvironment(S32 parcel_id, LLEnvironment::EnvironmentInfo::ptr_t envinfo, LLSettingsBase::Seconds transition)
diff --git a/indra/newview/llenvironment.h b/indra/newview/llenvironment.h
index 0ec06402f869c44015867f175a48f65eedbe8312..330de2bea87da56123b2164818e82dff3c237251 100644
--- a/indra/newview/llenvironment.h
+++ b/indra/newview/llenvironment.h
@@ -158,6 +158,8 @@ class LLEnvironment : public LLSimpleton<LLEnvironment>
 
     static void                 logEnvironment(EnvSelection_t env, const LLSettingsBase::ptr_t &settings, S32 env_version = NO_VERSION);
 
+    void                        setCurrentEnvironmentSelection(LLEnvironment::EnvSelection_t env);
+
 
     LLSettingsDay::ptr_t        getEnvironmentDay(EnvSelection_t env);
     LLSettingsDay::Seconds      getEnvironmentDayLength(EnvSelection_t env);
diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp
index b328dd2962c1aa6274d615cae927018fb338a2c8..d1e2b8b93d01deb35e0a7c76d1afd4a2143f610b 100644
--- a/indra/newview/llface.cpp
+++ b/indra/newview/llface.cpp
@@ -1172,6 +1172,11 @@ bool LLFace::canRenderAsMask()
 		return true;
 	}
 
+    if (isState(LLFace::RIGGED))
+    { // never auto alpha-mask rigged faces
+        return false;
+    }
+
 	const LLTextureEntry* te = getTextureEntry();
 	if( !te || !getViewerObject() || !getTexture() )
 	{
@@ -2359,14 +2364,35 @@ F32 LLFace::getTextureVirtualSize()
 
 BOOL LLFace::calcPixelArea(F32& cos_angle_to_view_dir, F32& radius)
 {
-	LL_PROFILE_ZONE_SCOPED_CATEGORY_FACE
+    LL_PROFILE_ZONE_SCOPED_CATEGORY_FACE;
 
 	//VECTORIZE THIS
 	//get area of circle around face
-	LLVector4a center;
-	center.load3(getPositionAgent().mV);
-	LLVector4a size;
-	size.setSub(mExtents[1], mExtents[0]);
+
+    LLVector4a center;
+    LLVector4a size;
+
+
+    if (isState(LLFace::RIGGED))
+    {
+        //override with avatar bounding box
+        LLVOAvatar* avatar = mVObjp->getAvatar();
+        if (avatar)
+        {
+            center.load3(avatar->getPositionAgent().mV);
+            const LLVector4a* exts = avatar->mDrawable->getSpatialExtents();
+            size.setSub(exts[1], exts[0]);
+        }
+        else
+        {
+            return false;
+        }
+    }
+    else
+    {
+        center.load3(getPositionAgent().mV);
+        size.setSub(mExtents[1], mExtents[0]);
+    }
 	size.mul(0.5f);
 
 	LLViewerCamera* camera = LLViewerCamera::getInstance();
diff --git a/indra/newview/llface.h b/indra/newview/llface.h
index 79f50f22736907a440b5b04abbfd8336358fecc8..aa00c9d052630c73c84ba55fffd9516301647468 100644
--- a/indra/newview/llface.h
+++ b/indra/newview/llface.h
@@ -143,7 +143,7 @@ class alignas(16) LLFace
 	LLViewerObject*	getViewerObject()	const	{ return mVObjp; }
 	S32				getLOD()			const	{ return mVObjp.notNull() ? mVObjp->getLOD() : 0; }
 	void			setPoolType(U32 type)		{ mPoolType = type; }
-	S32				getTEOffset()				{ return mTEOffset; }
+	S32				getTEOffset()       const   { return mTEOffset; }
 	LLViewerTexture*	getTexture(U32 ch = LLRender::DIFFUSE_MAP) const;
 
 	void			setViewerObject(LLViewerObject* object);
@@ -233,6 +233,12 @@ class alignas(16) LLFace
 	void	notifyAboutCreatingTexture(LLViewerTexture *texture);
 	void	notifyAboutMissingAsset(LLViewerTexture *texture);
 
+    // used to preserve draw order of faces that are batched together. 
+    // Allows content creators to manipulate linked sets and face ordering 
+    // for consistent alpha sorting results, particularly for rigged attachments
+    void setDrawOrderIndex(U32 index) { mDrawOrderIndex = index; }
+    U32 getDrawOrderIndex() const { return mDrawOrderIndex; }
+
 public: //aligned members
 	LLVector4a		mExtents[2];
 
@@ -305,6 +311,7 @@ class alignas(16) LLFace
 	bool        mHasMedia ;
 	bool        mIsMediaAllowed;
 
+    U32 mDrawOrderIndex = 0; // see setDrawOrderIndex
 	
 protected:
 	static BOOL	sSafeRenderSelect;
diff --git a/indra/newview/llfeaturemanager.cpp b/indra/newview/llfeaturemanager.cpp
index 08130577145c0b5d2482b74f5c6653ebf368abbe..329af264ebbdc1727ab3ecb7c4f873a9d4f56784 100644
--- a/indra/newview/llfeaturemanager.cpp
+++ b/indra/newview/llfeaturemanager.cpp
@@ -381,7 +381,10 @@ F32 gpu_benchmark();
 
 F32 logExceptionBenchmark()
 {
-    // Todo: make a wrapper/class for SEH exceptions
+    // FIXME: gpu_benchmark uses many C++ classes on the stack to control state.
+    //  SEH exceptions with our current exception handling options do not call 
+    //  destructors for these classes, resulting in an undefined state should
+    //  this handler be invoked.  
     F32 gbps = -1;
     __try
     {
@@ -389,6 +392,9 @@ F32 logExceptionBenchmark()
     }
     __except (msc_exception_filter(GetExceptionCode(), GetExceptionInformation()))
     {
+        // HACK - ensure that profiling is disabled
+        LLGLSLShader::finishProfile(false);
+
         // convert to C++ styled exception
         char integer_string[32];
         sprintf(integer_string, "SEH, code: %lu\n", GetExceptionCode());
diff --git a/indra/newview/llfloatercamera.cpp b/indra/newview/llfloatercamera.cpp
index 3b192ff81b00c0ba6cdb1742ed94f78f570b4050..1c69b9d60baa026ba66c90e94c5b325658cc75b8 100644
--- a/indra/newview/llfloatercamera.cpp
+++ b/indra/newview/llfloatercamera.cpp
@@ -453,18 +453,18 @@ void LLFloaterCamera::setMode(ECameraControlMode mode)
 
 void LLFloaterCamera::switchMode(ECameraControlMode mode)
 {
-	setMode(mode);
-
 	switch (mode)
 	{
 	case CAMERA_CTRL_MODE_PRESETS:
 	case CAMERA_CTRL_MODE_PAN:
 		sFreeCamera = false;
+		setMode(mode); // depends onto sFreeCamera
 		clear_camera_tool();
 		break;
 
 	case CAMERA_CTRL_MODE_FREE_CAMERA:
 		sFreeCamera = true;
+		setMode(mode);
 		activate_camera_tool();
 		break;
 
diff --git a/indra/newview/llfloaterfixedenvironment.cpp b/indra/newview/llfloaterfixedenvironment.cpp
index 4f2c36f45b6217ae609cd8ef2b3dc5f190191add..fec218ca3b4b905cb575daea7998fffdceacf7b5 100644
--- a/indra/newview/llfloaterfixedenvironment.cpp
+++ b/indra/newview/llfloaterfixedenvironment.cpp
@@ -137,6 +137,7 @@ void LLFloaterFixedEnvironment::onClose(bool app_quitting)
     doCloseInventoryFloater(app_quitting);
 
     LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL);
+    LLEnvironment::instance().setCurrentEnvironmentSelection(LLEnvironment::ENV_LOCAL);
     LLEnvironment::instance().clearEnvironment(LLEnvironment::ENV_EDIT);
 
     mSettings.reset();
diff --git a/indra/newview/llfloatergesture.cpp b/indra/newview/llfloatergesture.cpp
index c4e0dd483fa04521c72899959804f4f42927517c..6e326ff3cf041cc0c11ce86a23010f2eac9d509e 100644
--- a/indra/newview/llfloatergesture.cpp
+++ b/indra/newview/llfloatergesture.cpp
@@ -582,8 +582,7 @@ void LLFloaterGesture::onCopyPasteAction(const LLSD& command)
 			LLInventoryItem* item = gInventory.getItem(*it);
 			if(item  && item->getInventoryType() == LLInventoryType::IT_GESTURE)
 			{
-				LLWString item_name = utf8str_to_wstring(item->getName());
-				LLClipboard::instance().addToClipboard(item_name, 0, item_name.size());
+				LLClipboard::instance().addToClipboard(*it);
 			}
 		}
 	}
diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp
index 43dc304c1076039d180468a37dbd0d6dbab15372..34499ac170e1ecf02a81ac952c33b009ecc7ddea 100644
--- a/indra/newview/llfloaterimsessiontab.cpp
+++ b/indra/newview/llfloaterimsessiontab.cpp
@@ -384,7 +384,7 @@ void LLFloaterIMSessionTab::draw()
 
 void LLFloaterIMSessionTab::enableDisableCallBtn()
 {
-    if (LLVoiceClient::instanceExists())
+    if (LLVoiceClient::instanceExists() && mVoiceButton)
     {
         mVoiceButton->setEnabled(
             mSessionID.notNull()
diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp
index a57705fe50321e1f0c46d15bc1cb0b312d1b75c2..0e94d31d90bb28a1142e50d30dd6b8bb18b78d1d 100644
--- a/indra/newview/llfloaterpreference.cpp
+++ b/indra/newview/llfloaterpreference.cpp
@@ -2056,7 +2056,16 @@ void LLPanelPreference::saveSettings()
 		{
 			view_stack.push_back(*iter);
 		}
-	}	
+	}
+
+    if (LLStartUp::getStartupState() == STATE_STARTED)
+    {
+        LLControlVariable* control = gSavedPerAccountSettings.getControl("VoiceCallsFriendsOnly");
+        if (control)
+        {
+            mSavedValues[control] = control->getValue();
+        }
+    }
 }
 
 void LLPanelPreference::showMultipleViewersWarning(LLUICtrl* checkbox, const LLSD& value)
diff --git a/indra/newview/llfloatersearch.cpp b/indra/newview/llfloatersearch.cpp
index 779542cfcc8821d83232b693f5f02ae7663f1b72..2e1fbb09e0e398a3bac23a5875b3c3d52fb54528 100644
--- a/indra/newview/llfloatersearch.cpp
+++ b/indra/newview/llfloatersearch.cpp
@@ -169,15 +169,6 @@ void LLFloaterSearch::search(const SearchQuery &p)
 	// add the search query string
 	subs["QUERY"] = LLURI::escape(p.query);
 
-	// add the permissions token that login.cgi gave us
-	// We use "search_token", and fallback to "auth_token" if not present.
-	LLSD search_token = LLLoginInstance::getInstance()->getResponse("search_token");
-	if (search_token.asString().empty())
-	{
-		search_token = LLLoginInstance::getInstance()->getResponse("auth_token");
-	}
-	subs["AUTH_TOKEN"] = search_token.asString();
-
 	// add the user's preferred maturity (can be changed via prefs)
 	std::string maturity;
 	if (gAgent.prefersAdult())
diff --git a/indra/newview/llfloaterworldmap.cpp b/indra/newview/llfloaterworldmap.cpp
index 27197f0b065075055cef8c772c0a6f82247027a1..2c84cd1f93ddd84eb092d8655e5ceef70f8bd275 100644
--- a/indra/newview/llfloaterworldmap.cpp
+++ b/indra/newview/llfloaterworldmap.cpp
@@ -56,10 +56,12 @@
 #include "llscrolllistctrl.h"
 #include "llslurl.h"
 #include "lltextbox.h"
+#include "lltoolbarview.h"
 #include "lltracker.h"
 #include "lltrans.h"
 #include "llviewerinventory.h"	// LLViewerInventoryItem
 #include "llviewermenu.h"
+#include "llviewerparcelmgr.h"
 #include "llviewerregion.h"
 #include "llviewerstats.h"
 #include "llviewertexture.h"
@@ -87,6 +89,9 @@ static const F32 MAP_ZOOM_TIME = 0.2f;
 // Currently (01/26/09), this value allows the whole grid to be visible in a 1024x1024 window.
 static const S32 MAX_VISIBLE_REGIONS = 512;
 
+
+const S32 HIDE_BEACON_PAD = 133;
+
 // It would be more logical to have this inside the method where it is used but to compile under gcc this
 // struct has to be here.
 struct SortRegionNames
@@ -326,6 +331,8 @@ LLFloaterWorldMap::~LLFloaterWorldMap()
 	mFriendObserver = NULL;
 	
 	gFloaterWorldMap = NULL;
+
+    mTeleportFinishConnection.disconnect();
 }
 
 //static
@@ -339,12 +346,16 @@ void LLFloaterWorldMap::onClose(bool app_quitting)
 {
 	// While we're not visible, discard the overlay images we're using
 	LLWorldMap::getInstance()->clearImageRefs();
+    mTeleportFinishConnection.disconnect();
 }
 
 // virtual
 void LLFloaterWorldMap::onOpen(const LLSD& key)
 {
-	bool center_on_target = (key.asString() == "center");
+    mTeleportFinishConnection = LLViewerParcelMgr::getInstance()->
+        setTeleportFinishedCallback(boost::bind(&LLFloaterWorldMap::onTeleportFinished, this));
+ 
+    bool center_on_target = (key.asString() == "center");
 	
 	mIsClosing = FALSE;
 	
@@ -1566,6 +1577,13 @@ void LLFloaterWorldMap::updateSims(bool found_null_sim)
 	}
 }
 
+void LLFloaterWorldMap::onTeleportFinished()
+{
+    if(isInVisibleChain())
+    {
+        LLWorldMapView::setPan(0, 0, TRUE);
+    }
+}
 
 void LLFloaterWorldMap::onCommitSearchResult()
 {
@@ -1642,3 +1660,103 @@ void LLFloaterWorldMap::onFocusLost()
 	LLWorldMapView* map_panel = (LLWorldMapView*)gFloaterWorldMap->mPanel;
 	map_panel->mPanning = FALSE;
 }
+
+LLPanelHideBeacon::LLPanelHideBeacon() :
+	mHideButton(NULL)
+{
+}
+
+// static
+LLPanelHideBeacon* LLPanelHideBeacon::getInstance()
+{
+	static LLPanelHideBeacon* panel = getPanelHideBeacon();
+	return panel;
+}
+
+
+BOOL LLPanelHideBeacon::postBuild()
+{
+	mHideButton = getChild<LLButton>("hide_beacon_btn");
+	mHideButton->setCommitCallback(boost::bind(&LLPanelHideBeacon::onHideButtonClick, this));
+
+	gViewerWindow->setOnWorldViewRectUpdated(boost::bind(&LLPanelHideBeacon::updatePosition, this));
+
+	return TRUE;
+}
+
+//virtual
+void LLPanelHideBeacon::draw()
+{
+	if (!LLTracker::isTracking(NULL))
+	{
+        mHideButton->setVisible(false);
+        return;
+	}
+    mHideButton->setVisible(true);
+	updatePosition(); 
+	LLPanel::draw();
+}
+
+//virtual
+void LLPanelHideBeacon::setVisible(BOOL visible)
+{
+	if (gAgentCamera.getCameraMode() == CAMERA_MODE_MOUSELOOK) visible = false;
+
+	if (visible)
+	{
+		updatePosition();
+	}
+
+	LLPanel::setVisible(visible);
+}
+
+
+//static
+LLPanelHideBeacon* LLPanelHideBeacon::getPanelHideBeacon()
+{
+	LLPanelHideBeacon* panel = new LLPanelHideBeacon();
+	panel->buildFromFile("panel_hide_beacon.xml");
+
+	LL_INFOS() << "Build LLPanelHideBeacon panel" << LL_ENDL;
+
+	panel->updatePosition();
+	return panel;
+}
+
+void LLPanelHideBeacon::onHideButtonClick()
+{
+	LLFloaterWorldMap* instance = LLFloaterWorldMap::getInstance();
+	if (instance)
+	{
+		instance->onClearBtn();
+	}
+}
+
+/**
+* Updates position of the panel (similar to Stand & Stop Flying panel).
+*/
+void LLPanelHideBeacon::updatePosition()
+{
+	S32 bottom_tb_center = 0;
+	if (LLToolBar* toolbar_bottom = gToolBarView->getToolbar(LLToolBarEnums::TOOLBAR_BOTTOM))
+	{
+		bottom_tb_center = toolbar_bottom->getRect().getCenterX();
+	}
+
+	S32 left_tb_width = 0;
+	if (LLToolBar* toolbar_left = gToolBarView->getToolbar(LLToolBarEnums::TOOLBAR_LEFT))
+	{
+		left_tb_width = toolbar_left->getRect().getWidth();
+	}
+
+	if (gToolBarView != NULL && gToolBarView->getToolbar(LLToolBarEnums::TOOLBAR_LEFT)->hasButtons())
+	{
+		S32 x_pos = bottom_tb_center - getRect().getWidth() / 2 - left_tb_width;
+		setOrigin( x_pos + HIDE_BEACON_PAD, 0);
+	}
+	else 
+	{
+		S32 x_pos = bottom_tb_center - getRect().getWidth() / 2;
+		setOrigin( x_pos + HIDE_BEACON_PAD, 0);
+	}
+}
diff --git a/indra/newview/llfloaterworldmap.h b/indra/newview/llfloaterworldmap.h
index 97e99297cfe60e11ee9f5b51d0c61c7075e18369..14a9c26fb97fe7687eb540e06c154ade3fb26621 100644
--- a/indra/newview/llfloaterworldmap.h
+++ b/indra/newview/llfloaterworldmap.h
@@ -107,7 +107,8 @@ class LLFloaterWorldMap : public LLFloater
 	// teleport to the tracked item, if there is one
 	void			teleport();
 	void			onChangeMaturity();
-	
+
+	void			onClearBtn();
 	
 	//Slapp instigated avatar tracking
 	void			avatarTrackFromSlapp( const LLUUID& id ); 
@@ -124,7 +125,6 @@ class LLFloaterWorldMap : public LLFloater
 	void			onComboTextEntry( );
 	void			onSearchTextEntry( );
 
-	void			onClearBtn();
 	void			onClickTeleportBtn();
 	void			onShowTargetBtn();
 	void			onShowAgentBtn();
@@ -151,7 +151,7 @@ class LLFloaterWorldMap : public LLFloater
 	void			onCoordinatesCommit();
 	void		    onCommitSearchResult();
 
-	void			cacheLandmarkPosition();
+    void            onTeleportFinished();
 
 private:
 	LLPanel*			mPanel;		// Panel displaying the map
@@ -195,9 +195,31 @@ class LLFloaterWorldMap : public LLFloater
 	LLCtrlListInterface *	mListFriendCombo;
 	LLCtrlListInterface *	mListLandmarkCombo;
 	LLCtrlListInterface *	mListSearchResults;
+
+    boost::signals2::connection mTeleportFinishConnection;
 };
 
 extern LLFloaterWorldMap* gFloaterWorldMap;
 
+
+class LLPanelHideBeacon : public LLPanel
+{
+public:
+	static LLPanelHideBeacon* getInstance();
+
+	LLPanelHideBeacon();
+	/*virtual*/ BOOL postBuild();
+	/*virtual*/ void setVisible(BOOL visible);
+	/*virtual*/ void draw();
+
+private:
+	static LLPanelHideBeacon* getPanelHideBeacon();
+	void onHideButtonClick();
+	void updatePosition();
+
+	LLButton* mHideButton;
+
+};
+
 #endif
 
diff --git a/indra/newview/llgesturemgr.cpp b/indra/newview/llgesturemgr.cpp
index 9f2119281d367d418d2b68f47479da252c3c6d22..489d34edca403173a755b0e3479a911c678f6223 100644
--- a/indra/newview/llgesturemgr.cpp
+++ b/indra/newview/llgesturemgr.cpp
@@ -483,8 +483,13 @@ void LLGestureMgr::replaceGesture(const LLUUID& item_id, LLMultiGesture* new_ges
 
 	mActive[base_item_id] = new_gesture;
 
-	delete old_gesture;
-	old_gesture = NULL;
+    // replaceGesture(const LLUUID& item_id, const LLUUID& new_asset_id)
+    // replaces ids without repalcing gesture
+    if (old_gesture != new_gesture)
+    {
+        delete old_gesture;
+        old_gesture = NULL;
+    }
 
 	if (asset_id.notNull())
 	{
@@ -910,7 +915,7 @@ void LLGestureMgr::stepGesture(LLMultiGesture* gesture)
 			else if (gesture->mWaitTimer.getElapsedTimeF32() > MAX_WAIT_ANIM_SECS)
 			{
 				// we've waited too long for an animation
-				LL_INFOS() << "Waited too long for animations to stop, continuing gesture."
+				LL_INFOS("GestureMgr") << "Waited too long for animations to stop, continuing gesture."
 					<< LL_ENDL;
 				gesture->mWaitingAnimations = FALSE;
 				gesture->mCurrentStep++;
@@ -1097,6 +1102,34 @@ void LLGestureMgr::onLoadComplete(const LLUUID& asset_uuid,
 				self.setFetchID(item_id);
 				self.startFetch();
 			}
+
+            item_map_t::iterator it = self.mActive.find(item_id);
+            if (it == self.mActive.end())
+            {
+                // Gesture is supposed to be present, active, but NULL
+                LL_DEBUGS("GestureMgr") << "Gesture " << item_id << " not found in active list" << LL_ENDL;
+            }
+            else
+            {
+                LLMultiGesture* old_gesture = (*it).second;
+                if (old_gesture && old_gesture != gesture)
+                {
+                    LL_DEBUGS("GestureMgr") << "Received dupplicate " << item_id << " callback" << LL_ENDL;
+                    // In case somebody managest to activate, deactivate and
+                    // then activate gesture again, before asset finishes loading.
+                    // LLLoadInfo will have a different pointer, asset storage will
+                    // see it as a different request, resulting in two callbacks.
+
+                    // deactivateSimilarGestures() did not turn this one off
+                    // because of matching item_id
+                    self.stopGesture(old_gesture);
+
+                    self.mActive.erase(item_id);
+                    delete old_gesture;
+                    old_gesture = NULL;
+                }
+            }
+
 			self.mActive[item_id] = gesture;
 
 			// Everything has been successful.  Add to the active list.
@@ -1131,9 +1164,23 @@ void LLGestureMgr::onLoadComplete(const LLUUID& asset_uuid,
 		}
 		else
 		{
-			LL_WARNS() << "Unable to load gesture" << LL_ENDL;
-
-			self.mActive.erase(item_id);
+			LL_WARNS("GestureMgr") << "Unable to load gesture" << LL_ENDL;
+
+            item_map_t::iterator it = self.mActive.find(item_id);
+            if (it != self.mActive.end())
+            {
+                LLMultiGesture* old_gesture = (*it).second;
+                if (old_gesture)
+                {
+                    // Shouldn't happen, just in case
+                    LL_WARNS("GestureMgr") << "Gesture " << item_id << " existed when it shouldn't" << LL_ENDL;
+
+                    self.stopGesture(old_gesture);
+                    delete old_gesture;
+                    old_gesture = NULL;
+                }
+                self.mActive.erase(item_id);
+            }
 			
 			delete gesture;
 			gesture = NULL;
@@ -1151,9 +1198,23 @@ void LLGestureMgr::onLoadComplete(const LLUUID& asset_uuid,
 			LLDelayedGestureError::gestureFailedToLoad( item_id );
 		}
 
-		LL_WARNS() << "Problem loading gesture: " << status << LL_ENDL;
-		
-		LLGestureMgr::instance().mActive.erase(item_id);			
+		LL_WARNS("GestureMgr") << "Problem loading gesture: " << status << LL_ENDL;
+        
+        item_map_t::iterator it = self.mActive.find(item_id);
+        if (it != self.mActive.end())
+        {
+            LLMultiGesture* old_gesture = (*it).second;
+            if (old_gesture)
+            {
+                // Shouldn't happen, just in case
+                LL_WARNS("GestureMgr") << "Gesture " << item_id << " existed when it shouldn't" << LL_ENDL;
+
+                self.stopGesture(old_gesture);
+                delete old_gesture;
+                old_gesture = NULL;
+            }
+            self.mActive.erase(item_id);
+        }
 	}
 }
 
diff --git a/indra/newview/llgroupactions.cpp b/indra/newview/llgroupactions.cpp
index 9dca50926299a0a9e04ac27b0af1de9f0510759d..e7bc2a926852104ce4d70d75f4ca22a750669098 100644
--- a/indra/newview/llgroupactions.cpp
+++ b/indra/newview/llgroupactions.cpp
@@ -196,7 +196,7 @@ LLFetchLeaveGroupData* gFetchLeaveGroupData = NULL;
 // static
 void LLGroupActions::search()
 {
-	LLFloaterReg::showInstance("search", LLSD().with("category", "groups"));
+	LLFloaterReg::showInstance("search");
 }
 
 // static
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index b4fc83259659ae69cce18a63db83552e4dc5c190..37500176ea5f5b280c9aa4e02215ca8fef2fb1e6 100644
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -138,6 +138,8 @@ bool LLCanCache::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
 LLInventoryValidationInfo::LLInventoryValidationInfo():
 	mFatalErrorCount(0),
 	mWarningCount(0),
+    mLoopCount(0),
+    mOrphanedCount(0),
 	mInitialized(false),
 	mFatalNoRootFolder(false),
 	mFatalNoLibraryRootFolder(false),
@@ -147,7 +149,10 @@ LLInventoryValidationInfo::LLInventoryValidationInfo():
 
 void LLInventoryValidationInfo::toOstream(std::ostream& os) const
 {
-	os << "mFatalErrorCount " << mFatalErrorCount << " mWarningCount " << mWarningCount;
+	os << "mFatalErrorCount " << mFatalErrorCount
+       << " mWarningCount " << mWarningCount
+       << " mLoopCount " << mLoopCount
+       << " mOrphanedCount " << mOrphanedCount;
 }
 
 
@@ -161,6 +166,8 @@ void LLInventoryValidationInfo::asLLSD(LLSD& sd) const
 {
 	sd["fatal_error_count"] = mFatalErrorCount;
 	sd["warning_count"] = mWarningCount;
+    sd["loop_count"] = mLoopCount;
+    sd["orphaned_count"] = mOrphanedCount;
 	sd["initialized"] = mInitialized;
 	sd["missing_system_folders_count"] = LLSD::Integer(mMissingRequiredSystemFolders.size());
 	sd["fatal_no_root_folder"] = mFatalNoRootFolder;
@@ -337,21 +344,35 @@ const LLViewerInventoryCategory* LLInventoryModel::getFirstDescendantOf(const LL
 	return NULL;
 }
 
-bool LLInventoryModel::getObjectTopmostAncestor(const LLUUID& object_id, LLUUID& result) const
+LLInventoryModel::EAnscestorResult LLInventoryModel::getObjectTopmostAncestor(const LLUUID& object_id, LLUUID& result) const
 {
 	LLInventoryObject *object = getObject(object_id);
-	while (object && object->getParentUUID().notNull())
-	{
-		LLInventoryObject *parent_object = getObject(object->getParentUUID());
+    if (!object)
+    {
+        LL_WARNS(LOG_INV) << "Unable to trace topmost ancestor, initial object " << object_id << " does not exist" << LL_ENDL;
+        return ANSCESTOR_MISSING;
+    }
+
+    std::set<LLUUID> object_ids{ object_id }; // loop protection
+    while (object->getParentUUID().notNull())
+    {
+        LLUUID parent_id = object->getParentUUID();
+        if (object_ids.find(parent_id) != object_ids.end())
+        {
+            LL_WARNS(LOG_INV) << "Detected a loop on an object " << parent_id << " when searching for ancestor of " << object_id << LL_ENDL;
+            return ANSCESTOR_LOOP;
+        }
+        object_ids.insert(parent_id);
+        LLInventoryObject *parent_object = getObject(parent_id);
 		if (!parent_object)
 		{
-			LL_WARNS(LOG_INV) << "unable to trace topmost ancestor, missing item for uuid " << object->getParentUUID() << LL_ENDL;
-			return false;
+			LL_WARNS(LOG_INV) << "unable to trace topmost ancestor of " << object_id << ", missing item for uuid " << parent_id << LL_ENDL;
+			return ANSCESTOR_MISSING;
 		}
 		object = parent_object;
 	}
 	result = object->getUUID();
-	return true;
+	return ANSCESTOR_OK;
 }
 
 // Get the object by id. Returns NULL if not found.
@@ -2947,42 +2968,69 @@ bool LLInventoryModel::saveToFile(const std::string& filename,
 
 	LL_INFOS(LOG_INV) << "saving inventory to: (" << filename << ")" << LL_ENDL;
 
-	llofstream fileXML(filename.c_str());
-	if (!fileXML.is_open())
-	{
-		LL_WARNS(LOG_INV) << "unable to save inventory to: " << filename << LL_ENDL;
-		return false;
-	}
+    try
+    {
+        llofstream fileXML(filename.c_str());
+        if (!fileXML.is_open())
+        {
+            LL_WARNS(LOG_INV) << "Failed to open file. Unable to save inventory to: " << filename << LL_ENDL;
+            return false;
+        }
 
-	LLSD cache_ver;
-	cache_ver["inv_cache_version"] = sCurrentInvCacheVersion;
+        LLSD cache_ver;
+        cache_ver["inv_cache_version"] = sCurrentInvCacheVersion;
 
-	fileXML << LLSDOStreamer<LLSDNotationFormatter>(cache_ver) << std::endl;
+        if (fileXML.fail())
+        {
+            LL_WARNS(LOG_INV) << "Failed to write cache version to file. Unable to save inventory to: " << filename << LL_ENDL;
+            return false;
+        }
 
-	S32 count = categories.size();
-	S32 cat_count = 0;
-	S32 i;
-	for(i = 0; i < count; ++i)
-	{
-		LLViewerInventoryCategory* cat = categories[i];
-		if(cat->getVersion() != LLViewerInventoryCategory::VERSION_UNKNOWN)
-		{
-			fileXML << LLSDOStreamer<LLSDNotationFormatter>(cat->exportLLSD()) << std::endl;
-			cat_count++;
-		}
-	}
+        fileXML << LLSDOStreamer<LLSDNotationFormatter>(cache_ver) << std::endl;
 
-	S32 it_count = items.size();
-	for(i = 0; i < it_count; ++i)
-	{
-		fileXML << LLSDOStreamer<LLSDNotationFormatter>(items[i]->asLLSD()) << std::endl;
-	}
+        S32 count = categories.size();
+        S32 cat_count = 0;
+        S32 i;
+        for (i = 0; i < count; ++i)
+        {
+            LLViewerInventoryCategory* cat = categories[i];
+            if (cat->getVersion() != LLViewerInventoryCategory::VERSION_UNKNOWN)
+            {
+                fileXML << LLSDOStreamer<LLSDNotationFormatter>(cat->exportLLSD()) << std::endl;
+                cat_count++;
+            }
 
-	fileXML.close();
+            if (fileXML.fail())
+            {
+                LL_WARNS(LOG_INV) << "Failed to write a folder to file. Unable to save inventory to: " << filename << LL_ENDL;
+                return false;
+            }
+        }
 
-	LL_INFOS(LOG_INV) << "Inventory saved: " << cat_count << " categories, " << it_count << " items." << LL_ENDL;
+        S32 it_count = items.size();
+        for (i = 0; i < it_count; ++i)
+        {
+            fileXML << LLSDOStreamer<LLSDNotationFormatter>(items[i]->asLLSD()) << std::endl;
 
-	return true;
+            if (fileXML.fail())
+            {
+                LL_WARNS(LOG_INV) << "Failed to write an item to file. Unable to save inventory to: " << filename << LL_ENDL;
+                return false;
+            }
+        }
+
+        fileXML.close();
+
+        LL_INFOS(LOG_INV) << "Inventory saved: " << cat_count << " categories, " << it_count << " items." << LL_ENDL;
+    }
+    catch (...)
+    {
+        LOG_UNHANDLED_EXCEPTION("");
+        LL_INFOS(LOG_INV) << "Failed to save inventory to: (" << filename << ")" << LL_ENDL;
+        return false;
+    }
+
+    return true;
 }
 
 // message handling functionality
@@ -3850,20 +3898,23 @@ void LLInventoryModel::dumpInventory() const
 LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const
 {
 	LLPointer<LLInventoryValidationInfo> validation_info = new LLInventoryValidationInfo;
-	S32 fatalities = 0;
+	S32 fatal_errs = 0;
 	S32 warnings = 0;
+    S32 loops = 0;
+    S32 orphaned = 0;
 
 	if (getRootFolderID().isNull())
 	{
 		LL_WARNS("Inventory") << "Fatal inventory corruption: no root folder id" << LL_ENDL;
 		validation_info->mFatalNoRootFolder = true;
-		fatalities++;
+        fatal_errs++;
 	}
 	if (getLibraryRootFolderID().isNull())
 	{
+        // Probably shouldn't be a fatality, inventory can function without a library 
 		LL_WARNS("Inventory") << "Fatal inventory corruption: no library root folder id" << LL_ENDL;
 		validation_info->mFatalNoLibraryRootFolder = true;
-		fatalities++;
+        fatal_errs++;
 	}
 
 	if (mCategoryMap.size() + 1 != mParentChildCategoryTree.size())
@@ -3895,7 +3946,23 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const
 		}
 		LLUUID topmost_ancestor_id;
 		// Will leave as null uuid on failure
-		getObjectTopmostAncestor(cat_id, topmost_ancestor_id);
+        EAnscestorResult res = getObjectTopmostAncestor(cat_id, topmost_ancestor_id);
+        switch (res)
+        {
+        case ANSCESTOR_MISSING:
+            orphaned++;
+            break;
+        case ANSCESTOR_LOOP:
+            loops++;
+            break;
+        case ANSCESTOR_OK:
+            break;
+        default:
+            LL_WARNS("Inventory") << "Unknown ancestor error for " << cat_id << LL_ENDL;
+            warnings++;
+            break;
+        }
+
 		if (cat_id != cat->getUUID())
 		{
 			LL_WARNS("Inventory") << "cat id/index mismatch " << cat_id << " " << cat->getUUID() << LL_ENDL;
@@ -3995,8 +4062,8 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const
 
 			// Topmost ancestor should be root or library.
 			LLUUID topmost_ancestor_id;
-			bool found = getObjectTopmostAncestor(item_id, topmost_ancestor_id);
-			if (!found)
+            EAnscestorResult found = getObjectTopmostAncestor(item_id, topmost_ancestor_id);
+			if (found != ANSCESTOR_OK)
 			{
 				LL_WARNS("Inventory") << "unable to find topmost ancestor for " << item_id << LL_ENDL;
 				warnings++;
@@ -4026,7 +4093,7 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const
 			{
 				LL_WARNS("Inventory") << "cat " << cat_id << " name [" << cat->getName()
 									  << "] orphaned - no child cat array for alleged parent " << parent_id << LL_ENDL;
-				warnings++;
+                orphaned++;
 			}
 			else
 			{
@@ -4044,6 +4111,7 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const
 				{
 					LL_WARNS("Inventory") << "cat " << cat_id << " name [" << cat->getName()
 										  << "] orphaned - not found in child cat array of alleged parent " << parent_id << LL_ENDL;
+                    orphaned++;
 				}
 			}
 		}
@@ -4052,7 +4120,7 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const
 		LLFolderType::EType folder_type = cat->getPreferredType();
 		bool cat_is_in_library = false;
 		LLUUID topmost_id;
-		if (getObjectTopmostAncestor(cat->getUUID(),topmost_id) && topmost_id == getLibraryRootFolderID())
+		if (getObjectTopmostAncestor(cat->getUUID(),topmost_id) == ANSCESTOR_OK && topmost_id == getLibraryRootFolderID())
 		{
 			cat_is_in_library = true;
 		}
@@ -4092,6 +4160,7 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const
 		if (parent_id.isNull())
 		{
 			LL_WARNS("Inventory") << "item " << item_id << " name [" << item->getName() << "] has null parent id!" << LL_ENDL;
+            orphaned++;
 		}
 		else
 		{
@@ -4102,6 +4171,7 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const
 			{
 				LL_WARNS("Inventory") << "item " << item_id << " name [" << item->getName()
 									  << "] orphaned - alleged parent has no child items list " << parent_id << LL_ENDL;
+                orphaned++;
 			}
 			else
 			{
@@ -4118,6 +4188,7 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const
 				{
 					LL_WARNS("Inventory") << "item " << item_id << " name [" << item->getName()
 										  << "] orphaned - not found as child of alleged parent " << parent_id << LL_ENDL;
+                    orphaned++;
 				}
 			}
 				
@@ -4135,15 +4206,18 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const
 				LL_WARNS("Inventory") << "link " << item->getUUID() << " type " << item->getActualType()
 									  << " missing backlink info at target_id " << target_id
 									  << LL_ENDL;
+                orphaned++;
 			}
 			// Links should have referents.
 			if (item->getActualType() == LLAssetType::AT_LINK && !target_item)
 			{
 				LL_WARNS("Inventory") << "broken item link " << item->getName() << " id " << item->getUUID() << LL_ENDL;
+                orphaned++;
 			}
 			else if (item->getActualType() == LLAssetType::AT_LINK_FOLDER && !target_cat)
 			{
 				LL_WARNS("Inventory") << "broken folder link " << item->getName() << " id " << item->getUUID() << LL_ENDL;
+                orphaned++;
 			}
 			if (target_item && target_item->getIsLinkType())
 			{
@@ -4215,8 +4289,8 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const
 				if (is_automatic)
 				{
 					LL_WARNS("Inventory") << "Fatal inventory corruption: cannot create system folder of type " << ft << LL_ENDL;
-					fatalities++;
-					validation_info->mMissingRequiredSystemFolders.insert(LLFolderType::EType(ft));
+                    fatal_errs++;
+					validation_info->mMissingRequiredSystemFolders.insert(folder_type);
 				}
 				else
 				{
@@ -4227,8 +4301,20 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const
 			else if (count_under_root > 1)
 			{
 				LL_WARNS("Inventory") << "Fatal inventory corruption: system folder type has excess copies under root, type " << ft << " count " << count_under_root << LL_ENDL;
-				validation_info->mDuplicateRequiredSystemFolders.insert(LLFolderType::EType(ft));
-				fatalities++;
+				validation_info->mDuplicateRequiredSystemFolders.insert(folder_type);
+                if (!is_automatic && folder_type != LLFolderType::FT_SETTINGS)
+                {
+                    // It is a fatal problem or can lead to fatal problems for COF,
+                    // outfits, trash and other non-automatic folders.
+                    fatal_errs++;
+                }
+                else
+                {
+                    // For automatic folders it's not a fatal issue and shouldn't
+                    // break inventory or other functionality further
+                    // Exception: FT_SETTINGS is not automatic, but only deserves a warning.
+                    warnings++;
+                }
 			}
 			if (count_elsewhere > 0)
 			{
@@ -4254,11 +4340,13 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const
 	}
 
 	// FIXME need to fail login and tell user to retry, contact support if problem persists.
-	bool valid = (fatalities == 0);
-	LL_INFOS("Inventory") << "Validate done, fatal errors: " << fatalities << ", warnings: " << warnings << ", valid: " << valid << LL_ENDL;
+	bool valid = (fatal_errs == 0);
+	LL_INFOS("Inventory") << "Validate done, fatal errors: " << fatal_errs << ", warnings: " << warnings << ", valid: " << valid << LL_ENDL;
 
-	validation_info->mFatalErrorCount = fatalities;
+	validation_info->mFatalErrorCount = fatal_errs;
 	validation_info->mWarningCount = warnings;
+    validation_info->mLoopCount = loops;
+    validation_info->mOrphanedCount = orphaned;
 
 	return validation_info; 
 }
diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h
index e81652820f5bc54fdcab0acc1b21a4fb0f796737..eeec89bfb0332197da234f1e1985b671d9cce1f1 100644
--- a/indra/newview/llinventorymodel.h
+++ b/indra/newview/llinventorymodel.h
@@ -68,6 +68,8 @@ class LLInventoryValidationInfo: public LLRefCount
 
 	S32 mFatalErrorCount;
 	S32 mWarningCount;
+    S32 mLoopCount; // Presence of folders whose ansestors loop onto themselves
+    S32 mOrphanedCount; // Missing or orphaned items, links and folders
 	bool mInitialized;
 	bool mFatalNoRootFolder;
 	bool mFatalNoLibraryRootFolder;
@@ -283,9 +285,14 @@ class LLInventoryModel
 
 	// Check if one object has a parent chain up to the category specified by UUID.
 	BOOL isObjectDescendentOf(const LLUUID& obj_id, const LLUUID& cat_id) const;
-
+    
+    enum EAnscestorResult{
+        ANSCESTOR_OK = 0,
+        ANSCESTOR_MISSING = 1,
+        ANSCESTOR_LOOP = 2,
+    };
 	// Follow parent chain to the top.
-	bool getObjectTopmostAncestor(const LLUUID& object_id, LLUUID& result) const;
+    EAnscestorResult getObjectTopmostAncestor(const LLUUID& object_id, LLUUID& result) const;
 
 	//--------------------------------------------------------------------
 	// Find
diff --git a/indra/newview/llkeyconflict.cpp b/indra/newview/llkeyconflict.cpp
index c1e5e5faed3e1d15a891c04c6642e084d2179e67..d3ba18525be1803413e773660660a2ffc2547d09 100644
--- a/indra/newview/llkeyconflict.cpp
+++ b/indra/newview/llkeyconflict.cpp
@@ -411,8 +411,16 @@ void LLKeyConflictHandler::loadFromSettings(ESourceMode load_mode)
         filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, filename_default);
         if (!gDirUtilp->fileExists(filename) || !loadFromSettings(load_mode, filename, &mControlsMap))
         {
-            // mind placeholders
-            mControlsMap.insert(mDefaultsMap.begin(), mDefaultsMap.end());
+            // Mind placeholders
+            // Do not use mControlsMap.insert(mDefaultsMap) since mControlsMap has
+            // placeholders that won't be added over(to) by insert.
+            // Or instead move generatePlaceholders call to be after copying
+            control_map_t::iterator iter = mDefaultsMap.begin();
+            while (iter != mDefaultsMap.end())
+            {
+                mControlsMap[iter->first].mKeyBind = iter->second.mKeyBind;
+                iter++;
+            }
         }
     }
     mLoadMode = load_mode;
@@ -575,6 +583,8 @@ void LLKeyConflictHandler::saveToSettings(bool temporary)
                 break;
             }
 
+            keys.xml_version.set(keybindings_xml_version, true);
+
             if (temporary)
             {
                 // write to temporary xml and use it for gViewerInput
@@ -736,9 +746,9 @@ void LLKeyConflictHandler::resetToDefault(const std::string &control_name)
     resetToDefaultAndResolve(control_name, false);
 }
 
-void LLKeyConflictHandler::resetToDefaults(ESourceMode mode)
+void LLKeyConflictHandler::resetToDefaultsAndResolve()
 {
-    if (mode == MODE_SAVED_SETTINGS)
+    if (mLoadMode == MODE_SAVED_SETTINGS)
     {
         control_map_t::iterator iter = mControlsMap.begin();
         control_map_t::iterator end = mControlsMap.end();
@@ -751,8 +761,16 @@ void LLKeyConflictHandler::resetToDefaults(ESourceMode mode)
     else
     {
         mControlsMap.clear();
-        generatePlaceholders(mode);
+
+        // Set key combinations.
+        // Copy from mDefaultsMap before doing generatePlaceholders, otherwise
+        // insert() will fail to add some keys into pre-existing values from
+        // generatePlaceholders()
         mControlsMap.insert(mDefaultsMap.begin(), mDefaultsMap.end());
+
+        // Set conflict masks and mark functions (un)assignable
+        generatePlaceholders(mLoadMode);
+
     }
 
     mHasUnsavedChanges = true;
@@ -762,7 +780,7 @@ void LLKeyConflictHandler::resetToDefaults()
 {
     if (!empty())
     {
-        resetToDefaults(mLoadMode);
+        resetToDefaultsAndResolve();
     }
     else
     {
@@ -772,7 +790,7 @@ void LLKeyConflictHandler::resetToDefaults()
         // 3. We are loading 'current' only to replace it
         // but it is reliable and works Todo: consider optimizing.
         loadFromSettings(mLoadMode);
-        resetToDefaults(mLoadMode);
+        resetToDefaultsAndResolve();
     }
 }
 
@@ -805,7 +823,7 @@ void LLKeyConflictHandler::resetKeyboardBindings()
 
 void LLKeyConflictHandler::generatePlaceholders(ESourceMode load_mode)
 {
-    // These controls are meant to cause conflicts when user tries to assign same control somewhere else
+    // These placeholders are meant to cause conflict resolution when user tries to assign same control somewhere else
     // also this can be used to pre-record controls that should not conflict or to assign conflict groups/masks
 
     if (load_mode == MODE_FIRST_PERSON)
@@ -865,24 +883,60 @@ void LLKeyConflictHandler::generatePlaceholders(ESourceMode load_mode)
         registerTemporaryControl("spin_around_ccw_sitting");
         registerTemporaryControl("spin_around_cw_sitting");
     }
+
+
+    // Special case, mouse clicks passed to scripts have 'lowest' piority
+    // thus do not conflict, everything else has a chance before them
+    // also in ML they have highest priority, but only when script-grabbed,
+    // thus do not conflict
+    // (see AGENT_CONTROL_ML_LBUTTON_DOWN and CONTROL_LBUTTON_DOWN_INDEX)
+    LLKeyConflict *type_data = &mControlsMap[script_mouse_handler_name];
+    type_data->mAssignable = true;
+    type_data->mConflictMask = U32_MAX - CONFLICT_LMOUSE;
 }
 
-bool LLKeyConflictHandler::removeConflicts(const LLKeyData &data, const U32 &conlict_mask)
+bool LLKeyConflictHandler::removeConflicts(const LLKeyData &data, U32 conlict_mask)
 {
     if (conlict_mask == CONFLICT_NOTHING)
     {
         // Can't conflict
         return true;
     }
+
+    if (data.mMouse == CLICK_LEFT
+        && data.mMask == MASK_NONE
+        && data.mKey == KEY_NONE)
+    {
+        if ((conlict_mask & CONFLICT_LMOUSE) == 0)
+        {
+            // Can't conflict
+            return true;
+        }
+        else
+        {
+            // simplify conflict mask
+            conlict_mask = CONFLICT_LMOUSE;
+        }
+    }
+    else
+    {
+        // simplify conflict mask
+        conlict_mask &= ~CONFLICT_LMOUSE;
+    }
+
     std::map<std::string, S32> conflict_list;
     control_map_t::iterator cntrl_iter = mControlsMap.begin();
     control_map_t::iterator cntrl_end = mControlsMap.end();
     for (; cntrl_iter != cntrl_end; ++cntrl_iter)
     {
+        const U32 cmp_mask = cntrl_iter->second.mConflictMask;
+        if ((cmp_mask & conlict_mask) == 0)
+        {
+            // can't conflict
+            continue;
+        }
         S32 index = cntrl_iter->second.mKeyBind.findKeyData(data);
-        if (index >= 0
-            && cntrl_iter->second.mConflictMask != CONFLICT_NOTHING
-            && (cntrl_iter->second.mConflictMask & conlict_mask) != 0)
+        if (index >= 0)
         {
             if (cntrl_iter->second.mAssignable)
             {
diff --git a/indra/newview/llkeyconflict.h b/indra/newview/llkeyconflict.h
index 2926ca3aeb10f33f9ed3b7aaed53e78bf596579b..23c1adf1e4b16dab2ea423f1eeb03ff6f49ca661 100644
--- a/indra/newview/llkeyconflict.h
+++ b/indra/newview/llkeyconflict.h
@@ -66,6 +66,7 @@ class LLKeyConflictHandler
     };
 
     const U32 CONFLICT_NOTHING = 0;
+    const U32 CONFLICT_LMOUSE = 0x1 << 1;
     // at the moment this just means that key will conflict with everything that is identical
     const U32 CONFLICT_ANY = U32_MAX;
 
@@ -128,23 +129,24 @@ class LLKeyConflictHandler
     // resets current mode to defaults
     void resetToDefaults();
 
-    bool empty() { return mControlsMap.empty(); }
+    bool empty() const { return mControlsMap.empty(); }
     void clear();
 
     // reloads bindings from last valid user's xml or from default xml
     // to keyboard's handler
     static void resetKeyboardBindings();
 
-    bool hasUnsavedChanges() { return mHasUnsavedChanges; }
+    bool hasUnsavedChanges() const { return mHasUnsavedChanges; }
     void setLoadMode(ESourceMode mode) { mLoadMode = mode; }
-    ESourceMode getLoadMode() { return mLoadMode; }
+    ESourceMode getLoadMode() const { return mLoadMode; }
 
 private:
     void resetToDefaultAndResolve(const std::string &control_name, bool ignore_conflicts);
-    void resetToDefaults(ESourceMode mode);
+    void resetToDefaultsAndResolve();
 
     // at the moment these kind of control is not savable, but takes part in conflict resolution
     void registerTemporaryControl(const std::string &control_name, EMouseClickType mouse_ind, KEY key, MASK mask, U32 conflict_mask);
+    // conflict mask 0 means that any conflicts will be ignored
     void registerTemporaryControl(const std::string &control_name, U32 conflict_mask = 0);
 
     typedef std::map<std::string, LLKeyConflict> control_map_t;
@@ -152,7 +154,7 @@ class LLKeyConflictHandler
     bool loadFromSettings(const ESourceMode &load_mode, const std::string &filename, control_map_t *destination);
     void generatePlaceholders(ESourceMode load_mode); //E.x. non-assignable values
     // returns false in case user is trying to reuse control that can't be reassigned
-    bool removeConflicts(const LLKeyData &data, const U32 &conlict_mask);
+    bool removeConflicts(const LLKeyData &data, U32 conlict_mask);
 
     // removes flags and removes temporary file, returns 'true' if file was removed
     bool clearUnsavedChanges();
diff --git a/indra/newview/lllogininstance.cpp b/indra/newview/lllogininstance.cpp
index e81d2cc0826e83e8b4ff0c4709722590f19d125b..531f0b172d126c9234281c18fea9b13ac7f59430 100644
--- a/indra/newview/lllogininstance.cpp
+++ b/indra/newview/lllogininstance.cpp
@@ -165,13 +165,12 @@ void LLLoginInstance::constructAuthParams(LLPointer<LLCredential> user_credentia
 	//requested_options.append("inventory-meat");
 	//requested_options.append("inventory-skel-targets");
 #if (!defined LL_MINIMIAL_REQUESTED_OPTIONS)
-	if(FALSE == gSavedSettings.getBOOL("NoInventoryLibrary"))
-	{
-		requested_options.append("inventory-lib-root");
-		requested_options.append("inventory-lib-owner");
-		requested_options.append("inventory-skel-lib");
+
+    // Not requesting library will trigger mFatalNoLibraryRootFolder
+	requested_options.append("inventory-lib-root");
+	requested_options.append("inventory-lib-owner");
+	requested_options.append("inventory-skel-lib");
 	//	requested_options.append("inventory-meat-lib");
-	}
 
 	requested_options.append("initial-outfit");
 	requested_options.append("gestures");
diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp
index 5393d0b0b782f3fbf1c66ed2003982b26fb077b4..9142aadab9ff71d78b42019927fb88b10d0d8c8e 100644
--- a/indra/newview/llmediactrl.cpp
+++ b/indra/newview/llmediactrl.cpp
@@ -1146,6 +1146,11 @@ void LLMediaCtrl::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event)
             }
             else
             {
+                // Media might be blocked, waiting for a file,
+                // send an empty response to unblock it
+                const std::vector<std::string> empty_response;
+                self->sendPickFileResponse(empty_response);
+
                 LLNotificationsUtil::add("MediaFileDownloadUnsupported");
             }
 		};
diff --git a/indra/newview/llmodelpreview.cpp b/indra/newview/llmodelpreview.cpp
index d3eb2dd4d45aa8aca413e7ca680cc9f51159c7d5..859d987fc3d30d922848c7d673154e579bc5a98e 100644
--- a/indra/newview/llmodelpreview.cpp
+++ b/indra/newview/llmodelpreview.cpp
@@ -180,7 +180,6 @@ LLModelPreview::LLModelPreview(S32 width, S32 height, LLFloater* fmp)
     mPreviewLOD = 0;
     mModelLoader = NULL;
     mMaxTriangleLimit = 0;
-    mMinTriangleLimit = 0;
     mDirty = false;
     mGenLOD = false;
     mLoading = false;
@@ -1287,7 +1286,14 @@ F32 LLModelPreview::genMeshOptimizerPerModel(LLModel *base_model, LLModel *targe
     F32 result_error = 0; // how far from original the model is, 1 == 100%
     S32 new_indices = 0;
 
-    target_indices = llclamp(llfloor(size_indices / indices_decimator), 3, (S32)size_indices); // leave at least one triangle
+    if (indices_decimator > 0)
+    {
+        target_indices = llclamp(llfloor(size_indices / indices_decimator), 3, (S32)size_indices); // leave at least one triangle
+    }
+    else // indices_decimator can be zero for error_threshold based calculations
+    {
+        target_indices = 3;
+    }
     new_indices = LLMeshOptimizer::simplifyU32(
         output_indices,
         combined_indices,
@@ -1377,7 +1383,28 @@ F32 LLModelPreview::genMeshOptimizerPerModel(LLModel *base_model, LLModel *targe
                             << " original count: " << size_indices
                             << " error treshold: " << error_threshold
                             << LL_ENDL;
-                        return -1;
+
+                        // U16 vertices overflow shouldn't happen, but just in case
+                        new_indices = 0;
+                        valid_faces = 0;
+                        for (U32 face_idx = 0; face_idx < base_model->getNumVolumeFaces(); ++face_idx)
+                        {
+                            genMeshOptimizerPerFace(base_model, target_model, face_idx, indices_decimator, error_threshold, false);
+                            const LLVolumeFace &face = target_model->getVolumeFace(face_idx);
+                            new_indices += face.mNumIndices;
+                            if (face.mNumIndices >= 3)
+                            {
+                                valid_faces++;
+                            }
+                        }
+                        if (valid_faces)
+                        {
+                            return (F32)size_indices / (F32)new_indices;
+                        }
+                        else
+                        {
+                            return -1;
+                        }
                     }
 
                     // Copy vertice, normals, tcs
@@ -1447,20 +1474,6 @@ F32 LLModelPreview::genMeshOptimizerPerModel(LLModel *base_model, LLModel *targe
     if (new_indices < 3 || valid_faces == 0)
     {
         // Model should have at least one visible triangle
-
-        if (!sloppy)
-        {
-            // Should only happen with sloppy
-            // non sloppy shouldn't be capable of optimizing mesh away
-            LL_WARNS() << "Failed to generate triangles"
-                << " model " << target_model->mLabel
-                << " target Indices: " << target_indices
-                << " new Indices: " << new_indices
-                << " original count: " << size_indices
-                << " error treshold: " << error_threshold
-                << LL_ENDL;
-        }
-
         return -1;
     }
 
@@ -1484,7 +1497,14 @@ F32 LLModelPreview::genMeshOptimizerPerFace(LLModel *base_model, LLModel *target
     F32 result_error = 0; // how far from original the model is, 1 == 100%
     S32 new_indices = 0;
 
-    target_indices = llclamp(llfloor(size_indices / indices_decimator), 3, (S32)size_indices); // leave at least one triangle
+    if (indices_decimator > 0)
+    {
+        target_indices = llclamp(llfloor(size_indices / indices_decimator), 3, (S32)size_indices); // leave at least one triangle
+    }
+    else
+    {
+        target_indices = 3;
+    }
     new_indices = LLMeshOptimizer::simplify(
         output,
         face.mIndices,
@@ -1621,11 +1641,13 @@ void LLModelPreview::genMeshOptimizerLODs(S32 which_lod, S32 meshopt_mode, U32 d
 
             }
             // meshoptimizer doesn't use triangle limit, it uses indices limit, so convert it to aproximate ratio
-            indices_decimator = (F32)base_triangle_count / triangle_limit;
+            // triangle_limit can be 0.
+            indices_decimator = (F32)base_triangle_count / llmax(triangle_limit, 1.f);
         }
         else
         {
-            lod_error_threshold = mFMP->childGetValue("lod_error_threshold_" + lod_name[which_lod]).asReal();
+            // UI shows 0 to 100%, but meshoptimizer works with 0 to 1
+            lod_error_threshold = mFMP->childGetValue("lod_error_threshold_" + lod_name[which_lod]).asReal() / 100.f;
         }
     }
     else
@@ -1636,7 +1658,6 @@ void LLModelPreview::genMeshOptimizerLODs(S32 which_lod, S32 meshopt_mode, U32 d
     }
 
     mMaxTriangleLimit = base_triangle_count;
-    mMinTriangleLimit = mBaseModel.size();
 
     // Build models
 
@@ -1661,8 +1682,8 @@ void LLModelPreview::genMeshOptimizerLODs(S32 which_lod, S32 meshopt_mode, U32 d
             }
         }
 
-        mRequestedTriangleCount[lod] = llmax(mMinTriangleLimit, (S32)triangle_limit);
-        mRequestedErrorThreshold[lod] = lod_error_threshold;
+        mRequestedTriangleCount[lod] = triangle_limit;
+        mRequestedErrorThreshold[lod] = lod_error_threshold * 100;
         mRequestedLoDMode[lod] = lod_mode;
 
         mModel[lod].clear();
@@ -1699,11 +1720,7 @@ void LLModelPreview::genMeshOptimizerLODs(S32 which_lod, S32 meshopt_mode, U32 d
                 F32 res = genMeshOptimizerPerModel(base, target_model, indices_decimator, lod_error_threshold, false);
                 if (res < 0)
                 {
-                    // U16 vertices overflow, shouldn't happen, but just in case
-                    for (U32 face_idx = 0; face_idx < base->getNumVolumeFaces(); ++face_idx)
-                    {
-                        genMeshOptimizerPerFace(base, target_model, face_idx, indices_decimator, lod_error_threshold, false);
-                    }
+                    target_model->copyVolumeFaces(base);
                 }
             }
 
@@ -1726,15 +1743,7 @@ void LLModelPreview::genMeshOptimizerLODs(S32 which_lod, S32 meshopt_mode, U32 d
                 F32 allowed_ratio_drift = 2.f;
                 F32 precise_ratio = genMeshOptimizerPerModel(base, target_model, indices_decimator, lod_error_threshold, false);
                 
-                if (precise_ratio < 0)
-                {
-                    // U16 vertices overflow, shouldn't happen, but just in case
-                    for (U32 face_idx = 0; face_idx < base->getNumVolumeFaces(); ++face_idx)
-                    {
-                        genMeshOptimizerPerFace(base, target_model, face_idx, indices_decimator, lod_error_threshold, false);
-                    }
-                }
-                else if (precise_ratio * allowed_ratio_drift < indices_decimator)
+                if (precise_ratio < 0 || (precise_ratio * allowed_ratio_drift < indices_decimator))
                 {
                     // Try sloppy variant if normal one failed to simplify model enough.
                     // Sloppy variant can fail entirely and has issues with precision,
@@ -1815,9 +1824,18 @@ void LLModelPreview::genMeshOptimizerLODs(S32 which_lod, S32 meshopt_mode, U32 d
                     {
                         // Sloppy variant failed to generate triangles or is worse.
                         // Can happen with models that are too simple as is.
-                        // Fallback to normal method
 
-                        precise_ratio = genMeshOptimizerPerModel(base, target_model, indices_decimator, lod_error_threshold, false);
+                        if (precise_ratio < 0)
+                        {
+                            // Precise method failed as well, just copy face over
+                            target_model->copyVolumeFaces(base);
+                            precise_ratio = 1.f;
+                        }
+                        else
+                        {
+                            // Fallback to normal method
+                            precise_ratio = genMeshOptimizerPerModel(base, target_model, indices_decimator, lod_error_threshold, false);
+                        }
 
                         LL_INFOS() << "Model " << target_model->getName()
                             << " lod " << which_lod
@@ -1999,7 +2017,6 @@ void LLModelPreview::updateStatusMessages()
     if (mMaxTriangleLimit == 0)
     {
         mMaxTriangleLimit = total_tris[LLModel::LOD_HIGH];
-        mMinTriangleLimit = mUploadData.size();
     }
 
     mHasDegenerate = false;
@@ -2502,7 +2519,6 @@ void LLModelPreview::updateLodControls(S32 lod)
         LLSpinCtrl* limit = mFMP->getChild<LLSpinCtrl>("lod_triangle_limit_" + lod_name[lod]);
 
         limit->setMaxValue(mMaxTriangleLimit);
-        limit->setMinValue(mMinTriangleLimit);
         limit->forceSetValue(mRequestedTriangleCount[lod]);
 
         threshold->forceSetValue(mRequestedErrorThreshold[lod]);
@@ -2515,7 +2531,6 @@ void LLModelPreview::updateLodControls(S32 lod)
             threshold->setVisible(false);
 
             limit->setMaxValue(mMaxTriangleLimit);
-            limit->setMinValue(mMinTriangleLimit);
             limit->setIncrement(llmax((U32)1, mMaxTriangleLimit / 32));
         }
         else
@@ -2798,7 +2813,9 @@ void LLModelPreview::lookupLODModelFiles(S32 lod)
 
     std::string lod_filename = mLODFile[LLModel::LOD_HIGH];
     std::string ext = ".dae";
-    std::string::size_type i = lod_filename.rfind(ext);
+    std::string lod_filename_lower(lod_filename);
+    LLStringUtil::toLower(lod_filename_lower);
+    std::string::size_type i = lod_filename_lower.rfind(ext);
     if (i != std::string::npos)
     {
         lod_filename.replace(i, lod_filename.size() - ext.size(), getLodSuffix(next_lod) + ext);
@@ -3281,6 +3298,14 @@ BOOL LLModelPreview::render()
 
                                 if (!physics.mMesh.empty())
                                 { //render hull instead of mesh
+                                    // SL-16993 physics.mMesh[i].mNormals were being used to light the exploded
+                                    // analyzed physics shape but the drawArrays() interface changed
+                                    //  causing normal data <0,0,0> to be passed to the shader.
+                                    // The Phyics Preview shader uses plain vertex coloring so the physics hull is full lit.
+                                    // We could also use interface/ui shaders.
+                                    gObjectPreviewProgram.unbind();
+                                    gPhysicsPreviewProgram.bind();
+
                                     for (U32 i = 0; i < physics.mMesh.size(); ++i)
                                     {
                                         if (explode > 0.f)
@@ -3308,6 +3333,9 @@ BOOL LLModelPreview::render()
                                             gGL.popMatrix();
                                         }
                                     }
+
+                                    gPhysicsPreviewProgram.unbind();
+                                    gObjectPreviewProgram.bind();
                                 }
                             }
                         }
@@ -3730,6 +3758,7 @@ void LLModelPreview::onLODMeshOptimizerParamCommit(S32 requested_lod, bool enfor
     {
         genMeshOptimizerLODs(requested_lod, mode, 3, enforce_tri_limit);
         refresh();
+        mDirty = true;
     }
 }
 
diff --git a/indra/newview/llmodelpreview.h b/indra/newview/llmodelpreview.h
index f78f476810771b7e8e49951ddff1cf7cba6725d2..9e32215e6ac9d3f271ce0308c9c81f0ea0fa04f4 100644
--- a/indra/newview/llmodelpreview.h
+++ b/indra/newview/llmodelpreview.h
@@ -290,10 +290,6 @@ class LLModelPreview : public LLViewerDynamicTexture, public LLMutex
     // Amount of triangles in original(base) model
     U32 mMaxTriangleLimit;
 
-    // Minimum amount of allowed triangles in lod for spin cntrl.
-    // Leave at least one triangle per model.
-    S32 mMinTriangleLimit;
-
     LLMeshUploadThread::instance_list mUploadData;
     std::set<LLViewerFetchedTexture * > mTextureSet;
 
diff --git a/indra/newview/llpathfindingmanager.cpp b/indra/newview/llpathfindingmanager.cpp
index cb4c07a417bb3d9ab012f8d9a54f9f7975431443..852b39f4429ceb806c69b7ec6878e771320a2b50 100644
--- a/indra/newview/llpathfindingmanager.cpp
+++ b/indra/newview/llpathfindingmanager.cpp
@@ -61,7 +61,7 @@
 
 #define CAP_SERVICE_NAVMESH_STATUS          "NavMeshGenerationStatus"
 
-#define CAP_SERVICE_OBJECT_LINKSETS         "ObjectNavMeshProperties"
+#define CAP_SERVICE_OBJECT_LINKSETS         "RegionObjects"
 #define CAP_SERVICE_TERRAIN_LINKSETS        "TerrainNavMeshProperties"
 
 #define CAP_SERVICE_CHARACTERS              "CharacterProperties"
diff --git a/indra/newview/llpreviewgesture.cpp b/indra/newview/llpreviewgesture.cpp
index 061ecad099af5eda3d235b6964624f51486c47a8..39cdb6fb04fbdf355ae79ef54516cde07d09ec2d 100644
--- a/indra/newview/llpreviewgesture.cpp
+++ b/indra/newview/llpreviewgesture.cpp
@@ -1029,7 +1029,6 @@ void LLPreviewGesture::finishInventoryUpload(LLUUID itemId, LLUUID newAssetId)
     // active map with the new pointer.				
     if (LLGestureMgr::instance().isGestureActive(itemId))
     {
-        //*TODO: This is crashing for some reason.  Fix it.
         // Active gesture edited from menu.
         LLGestureMgr::instance().replaceGesture(itemId, newAssetId);
         gInventory.notifyObservers();
diff --git a/indra/newview/llsearchableui.cpp b/indra/newview/llsearchableui.cpp
index 1119e80005ecaee81ff95099a46f9f3d493b4063..620bbdfcdf91ba60d4d4dbd82d43b1f8088b2c05 100644
--- a/indra/newview/llsearchableui.cpp
+++ b/indra/newview/llsearchableui.cpp
@@ -132,8 +132,11 @@ void ll::statusbar::SearchableItem::setNotHighlighted( )
 	{
 		mCtrl->setHighlighted( false );
 
-		if( mWasHiddenBySearch )
-			mMenu->setVisible( TRUE );
+        if (mWasHiddenBySearch)
+        {
+            mMenu->setVisible(TRUE);
+            mWasHiddenBySearch = false;
+        }
 	}
 }
 
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 537b431ea2fc764fbf5f2471b918bdd5328495dd..a42b6562b8e335a17a205522a04a70132c5b6313 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -310,6 +310,12 @@ void update_texture_fetch()
 	LLAppViewer::getImageDecodeThread()->update(1); // unpauses the image thread
 	LLAppViewer::getTextureFetch()->update(1); // unpauses the texture fetch thread
 	gTextureList.updateImages(0.10f);
+
+    if (LLImageGLThread::sEnabled)
+    {
+        std::shared_ptr<LL::WorkQueue> main_queue = LL::WorkQueue::getInstance("mainloop");
+        main_queue->runFor(std::chrono::milliseconds(1));
+    }
 }
 
 void set_flags_and_update_appearance()
@@ -1490,19 +1496,7 @@ bool idle_startup()
 		display_startup();
 
 		// start up the ThreadPool we'll use for textures et al.
-		{
-			LLSD poolSizes{ gSavedSettings.getLLSD("ThreadPoolSizes") };
-			LLSD sizeSpec{ poolSizes["General"] };
-			LLSD::Integer poolSize{ sizeSpec.isInteger()? sizeSpec.asInteger() : 3 };
-			LL_DEBUGS("ThreadPool") << "Instantiating General pool with "
-									<< poolSize << " threads" << LL_ENDL;
-			// We don't want anyone, especially the main thread, to have to block
-			// due to this ThreadPool being full.
-			auto pool = new LL::ThreadPool("General", poolSize, 1024*1024);
-			pool->start();
-			// Once we start shutting down, destroy this ThreadPool.
-			LLAppViewer::instance()->onCleanup([pool](){ delete pool; });
-		}
+        LLAppViewer::instance()->initGeneralThread();
 
 		// Initialize global class data needed for surfaces (i.e. textures)
 		LL_DEBUGS("AppInit") << "Initializing sky..." << LL_ENDL;
@@ -1518,7 +1512,11 @@ bool idle_startup()
 		display_startup();
 
 		LL_DEBUGS("AppInit") << "Decoding images..." << LL_ENDL;
-		// For all images pre-loaded into viewer cache, decode them.
+		// For all images pre-loaded into viewer cache, init
+        // priorities and fetching using decodeAllImages.
+        // Most of the fetching and decoding likely to be done
+        // by update_texture_fetch() later, while viewer waits.
+        //
 		// Need to do this AFTER we init the sky
 		const S32 DECODE_TIME_SEC = 2;
 		for (int i = 0; i < DECODE_TIME_SEC; i++)
@@ -2242,10 +2240,6 @@ bool idle_startup()
 
 		// Have the agent start watching the friends list so we can update proxies
 		gAgent.observeFriends();
-		if (gSavedSettings.getBOOL("LoginAsGod"))
-		{
-			gAgent.requestEnterGodMode();
-		}
 		
 		// Start automatic replay if the flag is set.
 		if (gSavedSettings.getBOOL("StatsAutoRun") || gAgentPilot.getReplaySession())
@@ -2726,19 +2720,34 @@ void LLStartUp::loadInitialOutfit( const std::string& outfit_folder_name,
 
 	gAgentAvatarp->setSex(gender);
 
-	// try to find the outfit - if not there, create some default
-	// wearables.
+	// try to find the requested outfit or folder
+
+	// -- check for existing outfit in My Outfits
+	bool do_copy = false;
 	LLUUID cat_id = findDescendentCategoryIDByName(
-		gInventory.getLibraryRootFolderID(),
+		gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS),
 		outfit_folder_name);
+
+	// -- check for existing folder in Library
 	if (cat_id.isNull())
 	{
+		cat_id = findDescendentCategoryIDByName(
+			gInventory.getLibraryRootFolderID(),
+			outfit_folder_name);
+		if (!cat_id.isNull())
+		{
+			do_copy = true;
+		}
+	}
+
+	if (cat_id.isNull())
+	{
+		// -- final fallback: create standard wearables
 		LL_DEBUGS() << "standard wearables" << LL_ENDL;
 		gAgentWearables.createStandardWearables();
 	}
 	else
 	{
-		bool do_copy = true;
 		bool do_append = false;
 		LLViewerInventoryCategory *cat = gInventory.getCategory(cat_id);
 		// Need to fetch cof contents before we can wear.
@@ -2836,7 +2845,7 @@ void reset_login()
 	gAgentWearables.cleanup();
 	gAgentCamera.cleanup();
 	gAgent.cleanup();
-	LLWorld::getInstance()->destroyClass();
+	LLWorld::getInstance()->resetClass();
 
 	if ( gViewerWindow )
 	{	// Hide menus and normal buttons
@@ -3613,6 +3622,19 @@ bool process_login_success_response()
 		}
 	}
 
+	std::string fake_initial_outfit_name = gSavedSettings.getString("FakeInitialOutfitName");
+	if (!fake_initial_outfit_name.empty())
+	{
+		gAgent.setFirstLogin(TRUE);
+		sInitialOutfit = fake_initial_outfit_name;
+		if (sInitialOutfitGender.empty())
+		{
+			sInitialOutfitGender = "female"; // just guess, will get overridden when outfit is worn anyway.
+		}
+
+		LL_WARNS() << "Faking first-time login with initial outfit " << sInitialOutfit << LL_ENDL;
+	}
+
 	// set the location of the Agent Appearance service, from which we can request
 	// avatar baked textures if they are supported by the current region
 	std::string agent_appearance_url = response["agent_appearance_service"];
diff --git a/indra/newview/lltextureview.cpp b/indra/newview/lltextureview.cpp
index 7a0f69fed565cec8f025e24c68f6a45157cb0cba..b74577315e30f33970719889e3b2b691a65351ec 100644
--- a/indra/newview/lltextureview.cpp
+++ b/indra/newview/lltextureview.cpp
@@ -549,9 +549,11 @@ void LLGLTexMemBar::draw()
     U32 texFetchLatMed = U32(recording.getMean(LLTextureFetch::sTexFetchLatency).value() * 1000.0f);
     U32 texFetchLatMax = U32(recording.getMax(LLTextureFetch::sTexFetchLatency).value() * 1000.0f);
 
-	text = llformat("GL Tot: %d/%d MB Bound: %4d/%4d MB FBO: %d MB Raw Tot: %d MB Bias: %.2f Cache: %.1f/%.1f MB",
+	text = llformat("GL Tot: %d/%d MB GL Free: %d Sys Free: %d MB Bound: %4d/%4d MB FBO: %d MB Raw Tot: %d MB Bias: %.2f Cache: %.1f/%.1f MB",
 					total_mem.value(),
 					max_total_mem.value(),
+                    LLImageGLThread::getFreeVRAMMegabytes(),
+                    LLMemory::getAvailableMemKB()/1024,
 					bound_mem.value(),
 					max_bound_mem.value(),
 					LLRenderTarget::sBytesAllocated/(1024*1024),
diff --git a/indra/newview/lltoolcomp.cpp b/indra/newview/lltoolcomp.cpp
index ba328f27c4cf81640f781bda2e4935e26ebd010c..6d54a3770ce425aabf22a95133b7fecb954a6828 100644
--- a/indra/newview/lltoolcomp.cpp
+++ b/indra/newview/lltoolcomp.cpp
@@ -44,6 +44,7 @@
 #include "lltoolmgr.h"
 #include "lltoolselectrect.h"
 #include "lltoolplacer.h"
+#include "llviewerinput.h"
 #include "llviewermenu.h"
 #include "llviewerobject.h"
 #include "llviewerwindow.h"
@@ -745,7 +746,7 @@ BOOL LLToolCompGun::handleHover(S32 x, S32 y, MASK mask)
 BOOL LLToolCompGun::handleMouseDown(S32 x, S32 y, MASK mask)
 { 
 	// if the left button is grabbed, don't put up the pie menu
-	if (gAgent.leftButtonGrabbed())
+	if (gAgent.leftButtonGrabbed() && gViewerInput.isLMouseHandlingDefault(MODE_FIRST_PERSON))
 	{
 		gAgent.setControlFlags(AGENT_CONTROL_ML_LBUTTON_DOWN);
 		return FALSE;
@@ -762,7 +763,7 @@ BOOL LLToolCompGun::handleMouseDown(S32 x, S32 y, MASK mask)
 BOOL LLToolCompGun::handleDoubleClick(S32 x, S32 y, MASK mask)
 {
 	// if the left button is grabbed, don't put up the pie menu
-	if (gAgent.leftButtonGrabbed())
+	if (gAgent.leftButtonGrabbed() && gViewerInput.isLMouseHandlingDefault(MODE_FIRST_PERSON))
 	{
 		gAgent.setControlFlags(AGENT_CONTROL_ML_LBUTTON_DOWN);
 		return FALSE;
@@ -796,7 +797,10 @@ BOOL LLToolCompGun::handleRightMouseDown(S32 x, S32 y, MASK mask)
 
 BOOL LLToolCompGun::handleMouseUp(S32 x, S32 y, MASK mask)
 {
-	gAgent.setControlFlags(AGENT_CONTROL_ML_LBUTTON_UP);
+    if (gViewerInput.isLMouseHandlingDefault(MODE_FIRST_PERSON))
+    {
+        gAgent.setControlFlags(AGENT_CONTROL_ML_LBUTTON_UP);
+    }
 	setCurrentTool( (LLTool*) mGun );
 	return TRUE;
 }
diff --git a/indra/newview/lltoolgrab.cpp b/indra/newview/lltoolgrab.cpp
index 6216899dc66eee9fc7dca3bafedd270c0ae121be..897f8c1e5fe5c49b5ab974845fcc48e892e324ba 100644
--- a/indra/newview/lltoolgrab.cpp
+++ b/indra/newview/lltoolgrab.cpp
@@ -51,6 +51,7 @@
 #include "lltoolmgr.h"
 #include "lltoolpie.h"
 #include "llviewercamera.h"
+#include "llviewerinput.h"
 #include "llviewerobject.h"
 #include "llviewerobjectlist.h" 
 #include "llviewerregion.h"
@@ -140,7 +141,6 @@ BOOL LLToolGrabBase::handleMouseDown(S32 x, S32 y, MASK mask)
 		LL_INFOS() << "LLToolGrab handleMouseDown" << LL_ENDL;
 	}
 
-	// call the base class to propogate info to sim
 	LLTool::handleMouseDown(x, y, mask);
 
 	// leftButtonGrabbed() checks if controls are reserved by scripts, but does not take masks into account
@@ -150,6 +150,19 @@ BOOL LLToolGrabBase::handleMouseDown(S32 x, S32 y, MASK mask)
 		gViewerWindow->pickAsync(x, y, mask, pickCallback, /*BOOL pick_transparent*/ TRUE);
 	}
 	mClickedInMouselook = gAgentCamera.cameraMouselook();
+
+    if (mClickedInMouselook && gViewerInput.isLMouseHandlingDefault(MODE_FIRST_PERSON))
+    {
+        // LLToolCompGun::handleMouseDown handles the event if ML controls are grabed,
+        // but LLToolGrabBase is often the end point for mouselook clicks if ML controls
+        // are not grabbed and LLToolGrabBase::handleMouseDown consumes the event,
+        // so send clicks from here.
+        // We are sending specifically CONTROL_LBUTTON_DOWN instead of _ML_ version.
+        gAgent.setControlFlags(AGENT_CONTROL_LBUTTON_DOWN);
+
+        // Todo: LLToolGrabBase probably shouldn't consume the event if there is nothing
+        // to grab in Mouselook, it intercepts handling in scanMouse
+    }
 	return TRUE;
 }
 
@@ -953,9 +966,18 @@ void LLToolGrabBase::handleHoverFailed(S32 x, S32 y, MASK mask)
 
 BOOL LLToolGrabBase::handleMouseUp(S32 x, S32 y, MASK mask)
 {
-	// call the base class to propogate info to sim
 	LLTool::handleMouseUp(x, y, mask);
 
+    if (gAgentCamera.cameraMouselook() && gViewerInput.isLMouseHandlingDefault(MODE_FIRST_PERSON))
+    {
+        // LLToolCompGun::handleMouseUp handles the event if ML controls are grabed,
+        // but LLToolGrabBase is often the end point for mouselook clicks if ML controls
+        // are not grabbed and LToolGrabBase::handleMouseUp consumes the event,
+        // so send clicks from here.
+        // We are sending specifically CONTROL_LBUTTON_UP instead of _ML_ version.
+        gAgent.setControlFlags(AGENT_CONTROL_LBUTTON_UP);
+    }
+
 	if( hasMouseCapture() )
 	{
 		setMouseCapture( FALSE );
diff --git a/indra/newview/lltoolmorph.cpp b/indra/newview/lltoolmorph.cpp
index b5eb2880aee21b58c6077d6e4e7cb51e0aae41ba..d99c0ba2a6ae2508534dad913eb23346ec933642 100644
--- a/indra/newview/lltoolmorph.cpp
+++ b/indra/newview/lltoolmorph.cpp
@@ -239,7 +239,15 @@ BOOL LLVisualParamHint::render()
 
 	LLViewerCamera::getInstance()->setPerspective(FALSE, mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight, FALSE);
 
-    gPipeline.previewAvatar(gAgentAvatarp);
+    if (gAgentAvatarp->mDrawable.notNull())
+    {
+        LLGLDepthTest gls_depth(GL_TRUE, GL_TRUE);
+        gGL.flush();
+        gGL.setSceneBlendType(LLRender::BT_REPLACE);
+        gPipeline.generateImpostor(gAgentAvatarp, true);
+        gGL.setSceneBlendType(LLRender::BT_ALPHA);
+        gGL.flush();
+    }
 
 	gAgentAvatarp->setVisualParamWeight(mVisualParam->getID(), mLastParamWeight);
 	mWearablePtr->setVisualParamWeight(mVisualParam->getID(), mLastParamWeight);
diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp
index b4736841d639ed2287bf690ef4f89831dbf3b742..43deac60d92188f1bc5a0017b43aa416593084a4 100644
--- a/indra/newview/lltoolpie.cpp
+++ b/indra/newview/lltoolpie.cpp
@@ -394,8 +394,9 @@ BOOL LLToolPie::handleLeftClickPick()
 		gFocusMgr.setKeyboardFocus(NULL);
 	}
 
-	BOOL touchable = (object && object->flagHandleTouch()) 
-					 || (parent && parent->flagHandleTouch());
+    bool touchable = object
+                     && (object->getClickAction() != CLICK_ACTION_DISABLED)
+                     && (object->flagHandleTouch() || (parent && parent->flagHandleTouch()));
 
 	// Switch to grab tool if physical or triggerable
 	if (object && 
@@ -656,6 +657,12 @@ bool LLToolPie::teleportToClickedLocation()
     LLViewerObject* objp = mHoverPick.getObject();
     LLViewerObject* parentp = objp ? objp->getRootEdit() : NULL;
 
+    if (objp && (objp->getAvatar() == gAgentAvatarp || objp == gAgentAvatarp)) // ex: nametag
+    {
+        // Don't teleport to self, teleporting to other avatars is fine
+        return false;
+    }
+
     bool is_in_world = mHoverPick.mObjectID.notNull() && objp && !objp->isHUDAttachment();
     bool is_land = mHoverPick.mPickType == LLPickInfo::PICK_LAND;
     bool pos_non_zero = !mHoverPick.mPosGlobal.isExactlyZero();
@@ -750,7 +757,7 @@ BOOL LLToolPie::handleHover(S32 x, S32 y, MASK mask)
 	else if (!mMouseOutsideSlop 
 		&& mMouseButtonDown
 		// disable camera steering if click on land is not used for moving
-		&& gViewerInput.isMouseBindUsed(CLICK_LEFT))
+		&& gViewerInput.isMouseBindUsed(CLICK_LEFT, MASK_NONE, MODE_THIRD_PERSON))
 	{
 		S32 delta_x = x - mMouseDownX;
 		S32 delta_y = y - mMouseDownY;
diff --git a/indra/newview/llviewerassetstorage.cpp b/indra/newview/llviewerassetstorage.cpp
index 6aa12731749fcd90ddd84d93d467a95e5bf9b9bb..70065cb5a049698ba081585cd3cdf9076711d33a 100644
--- a/indra/newview/llviewerassetstorage.cpp
+++ b/indra/newview/llviewerassetstorage.cpp
@@ -353,7 +353,7 @@ void LLViewerAssetStorage::checkForTimeouts()
     // Restore requests
     LLCoprocedureManager* manager = LLCoprocedureManager::getInstance();
     while (mCoroWaitList.size() > 0
-           && manager->count(VIEWER_ASSET_STORAGE_CORO_POOL) < LLCoprocedureManager::DEFAULT_QUEUE_SIZE)
+           && manager->count(VIEWER_ASSET_STORAGE_CORO_POOL) < (LLCoprocedureManager::DEFAULT_QUEUE_SIZE - 1))
     {
         CoroWaitList &request = mCoroWaitList.front();
         
@@ -425,13 +425,14 @@ void LLViewerAssetStorage::queueRequestHttp(
     if (!duplicate)
     {
         // Coroutine buffer has fixed size (synchronization buffer, so we have no alternatives), so buffer any request above limit
-        if (LLCoprocedureManager::instance().count(VIEWER_ASSET_STORAGE_CORO_POOL) < LLCoprocedureManager::DEFAULT_QUEUE_SIZE)
+        LLCoprocedureManager* manager = LLCoprocedureManager::getInstance();
+        if (manager->count(VIEWER_ASSET_STORAGE_CORO_POOL) < (LLCoprocedureManager::DEFAULT_QUEUE_SIZE - 1))
         {
             bool with_http = true;
             bool is_temp = false;
             LLViewerAssetStatsFF::record_enqueue(atype, with_http, is_temp);
 
-            LLCoprocedureManager::instance().enqueueCoprocedure(VIEWER_ASSET_STORAGE_CORO_POOL, "LLViewerAssetStorage::assetRequestCoro",
+            manager->enqueueCoprocedure(VIEWER_ASSET_STORAGE_CORO_POOL, "LLViewerAssetStorage::assetRequestCoro",
                 boost::bind(&LLViewerAssetStorage::assetRequestCoro, this, req, uuid, atype, callback, user_data));
         }
         else
diff --git a/indra/newview/llviewerinput.cpp b/indra/newview/llviewerinput.cpp
index 94ec5347322c17e5dab24db59509d9f248c28170..43b9cd90bd6f90cdfb3917dff2acb79920ff2c90 100644
--- a/indra/newview/llviewerinput.cpp
+++ b/indra/newview/llviewerinput.cpp
@@ -816,13 +816,20 @@ bool toggle_enable_media(EKeystate s)
 
 bool walk_to(EKeystate s)
 {
-    if (KEYSTATE_DOWN != s) return true;
+    if (KEYSTATE_DOWN != s)
+    {
+        // teleport/walk is usually on mouseclick, mouseclick needs
+        // to let AGENT_CONTROL_LBUTTON_UP happen if teleport didn't,
+        // so return false, but if it causes issues, do some kind of
+        // "return !has_teleported"
+        return false;
+    }
     return LLToolPie::getInstance()->walkToClickedLocation();
 }
 
 bool teleport_to(EKeystate s)
 {
-    if (KEYSTATE_DOWN != s) return true;
+    if (KEYSTATE_DOWN != s) return false;
     return LLToolPie::getInstance()->teleportToClickedLocation();
 }
 
@@ -850,7 +857,47 @@ bool voice_follow_key(EKeystate s)
     return false;
 }
 
-bool agen_control_lbutton_handle(EKeystate s)
+bool script_trigger_lbutton(EKeystate s)
+{
+    // Check for script overriding/expecting left mouse button.
+    // Note that this does not pass event further and depends onto mouselook.
+    // Checks CONTROL_ML_LBUTTON_DOWN_INDEX for mouselook,
+    // CONTROL_LBUTTON_DOWN_INDEX for normal camera
+    if (gAgent.leftButtonGrabbed())
+    {
+        bool mouselook = gAgentCamera.cameraMouselook();
+        switch (s)
+        {
+        case KEYSTATE_DOWN:
+            if (mouselook)
+            {
+                gAgent.setControlFlags(AGENT_CONTROL_ML_LBUTTON_DOWN);
+            }
+            else
+            {
+                gAgent.setControlFlags(AGENT_CONTROL_LBUTTON_DOWN);
+            }
+            return true;
+        case KEYSTATE_UP:
+            if (mouselook)
+            {
+                gAgent.setControlFlags(AGENT_CONTROL_ML_LBUTTON_UP);
+            }
+            else
+            {
+                gAgent.setControlFlags(AGENT_CONTROL_LBUTTON_UP);
+            }
+            return true;
+        default:
+            break;
+        }
+    }
+    return false;
+}
+
+// Used by scripts, for overriding/handling left mouse button
+// see mControlsTakenCount
+bool agent_control_lbutton_handle(EKeystate s)
 {
     switch (s)
     {
@@ -922,6 +969,7 @@ REGISTER_KEYBOARD_ACTION("teleport_to", teleport_to);
 REGISTER_KEYBOARD_ACTION("walk_to", walk_to);
 REGISTER_KEYBOARD_GLOBAL_ACTION("toggle_voice", toggle_voice);
 REGISTER_KEYBOARD_GLOBAL_ACTION("voice_follow_key", voice_follow_key);
+REGISTER_KEYBOARD_ACTION(script_mouse_handler_name, script_trigger_lbutton);
 #undef REGISTER_KEYBOARD_ACTION
 
 LLViewerInput::LLViewerInput()
@@ -1193,6 +1241,20 @@ BOOL LLViewerInput::bindMouse(const S32 mode, const EMouseClickType mouse, const
     typedef boost::function<bool(EKeystate)> function_t;
     function_t function = NULL;
 
+    if (mouse == CLICK_LEFT
+        && mask == MASK_NONE
+        && function_name == script_mouse_handler_name)
+    {
+        // Special case
+        // Left click has script overrides and by default
+        // is handled via agent_control_lbutton as last option
+        // In case of mouselook and present overrides it has highest
+        // priority even over UI and is handled in LLToolCompGun::handleMouseDown
+        // so just mark it as having default handler
+        mLMouseDefaultHandling[mode] = true;
+        return TRUE;
+    }
+
     LLKeybindFunctionData* result = LLKeyboardActionRegistry::getValue(function_name);
     if (result)
     {
@@ -1269,7 +1331,8 @@ LLViewerInput::Keys::Keys()
 :	first_person("first_person"),
 	third_person("third_person"),
 	sitting("sitting"),
-	edit_avatar("edit_avatar")
+	edit_avatar("edit_avatar"),
+	xml_version("xml_version", 0)
 {}
 
 void LLViewerInput::resetBindings()
@@ -1280,6 +1343,7 @@ void LLViewerInput::resetBindings()
         mGlobalMouseBindings[i].clear();
         mKeyBindings[i].clear();
         mMouseBindings[i].clear();
+        mLMouseDefaultHandling[i] = false;
     }
 }
 
@@ -1298,6 +1362,65 @@ S32 LLViewerInput::loadBindingsXML(const std::string& filename)
 		binding_count += loadBindingMode(keys.third_person, MODE_THIRD_PERSON);
 		binding_count += loadBindingMode(keys.sitting, MODE_SITTING);
 		binding_count += loadBindingMode(keys.edit_avatar, MODE_EDIT_AVATAR);
+
+        // verify version
+        if (keys.xml_version < 1)
+        {
+            // updating from a version that was not aware of LMouse bindings
+            for (S32 i = 0; i < MODE_COUNT; i++)
+            {
+                mLMouseDefaultHandling[i] = true;
+            }
+
+            // fix missing values
+            KeyBinding mouse_binding;
+            mouse_binding.key = "";
+            mouse_binding.mask = "NONE";
+            mouse_binding.mouse = "LMB";
+            mouse_binding.command = script_mouse_handler_name;
+
+            if (keys.third_person.isProvided())
+            {
+                keys.third_person.bindings.add(mouse_binding);
+            }
+
+            if (keys.first_person.isProvided())
+            {
+                keys.first_person.bindings.add(mouse_binding);
+            }
+
+            if (keys.sitting.isProvided())
+            {
+                keys.sitting.bindings.add(mouse_binding);
+            }
+
+            if (keys.edit_avatar.isProvided())
+            {
+                keys.edit_avatar.bindings.add(mouse_binding);
+            }
+
+            // fix version
+            keys.xml_version.set(keybindings_xml_version, true);
+
+            // Write the resulting XML to file
+            LLXMLNodePtr output_node = new LLXMLNode("keys", false);
+            LLXUIParser write_parser;
+            write_parser.writeXUI(output_node, keys);
+
+            if (!output_node->isNull())
+            {
+                // file in app_settings is supposed to be up to date
+                // this is only for the file from user_settings
+                LL_INFOS("ViewerInput") << "Updating file " << filename << " to a newer version" << LL_ENDL;
+                LLFILE *fp = LLFile::fopen(filename, "w");
+                if (fp != NULL)
+                {
+                    LLXMLNode::writeHeaderToFile(fp);
+                    output_node->writeToFile(fp);
+                    fclose(fp);
+                }
+            }
+        }
 	}
 	return binding_count;
 }
@@ -1469,17 +1592,6 @@ bool LLViewerInput::scanKey(KEY key, BOOL key_down, BOOL key_up, BOOL key_level)
 
     bool res = scanKey(mKeyBindings[mode], mKeyBindings[mode].size(), key, mask, key_down, key_up, key_level, repeat);
 
-    if (!res && agent_control_lbutton.canHandle(CLICK_NONE, key, mask))
-    {
-        if (key_down && !repeat)
-        {
-            res = agen_control_lbutton_handle(KEYSTATE_DOWN);
-        }
-        if (key_up)
-        {
-            res = agen_control_lbutton_handle(KEYSTATE_UP);
-        }
-    }
     return res;
 }
 
@@ -1603,29 +1715,36 @@ bool LLViewerInput::scanMouse(EMouseClickType click, EMouseState state) const
     bool res = false;
     S32 mode = getMode();
     MASK mask = gKeyboard->currentMask(TRUE);
-
-    // By default mouse clicks require exact mask
-    // Todo: support for mIgnoreMasks because some functions like teleports
-    // expect to be canceled, but for voice it's prefered to ignore mask.
     res = scanMouse(mMouseBindings[mode], mMouseBindings[mode].size(), click, mask, state, false);
-    // no user defined actions found or those actions can't handle the key/button, handle control if nessesary
-    if (!res && agent_control_lbutton.canHandle(click, KEY_NONE, mask))
+
+    // No user defined actions found or those actions can't handle the key/button,
+    // so handle CONTROL_LBUTTON if nessesary.
+    //
+    // Default handling for MODE_FIRST_PERSON is in LLToolCompGun::handleMouseDown,
+    // and sends AGENT_CONTROL_ML_LBUTTON_DOWN, but it only applies if ML controls
+    // are leftButtonGrabbed(), send a normal click otherwise.
+
+    if (!res
+        && mLMouseDefaultHandling[mode]
+        && (mode != MODE_FIRST_PERSON || !gAgent.leftButtonGrabbed())
+        && (click == CLICK_LEFT || click == CLICK_DOUBLELEFT)
+        )
     {
         switch (state)
         {
         case MOUSE_STATE_DOWN:
-            agen_control_lbutton_handle(KEYSTATE_DOWN);
+            agent_control_lbutton_handle(KEYSTATE_DOWN);
             res = true;
             break;
         case MOUSE_STATE_CLICK:
             // might not work best with some functions,
             // but some function need specific states too specifically
-            agen_control_lbutton_handle(KEYSTATE_DOWN);
-            agen_control_lbutton_handle(KEYSTATE_UP);
+            agent_control_lbutton_handle(KEYSTATE_DOWN);
+            agent_control_lbutton_handle(KEYSTATE_UP);
             res = true;
             break;
         case MOUSE_STATE_UP:
-            agen_control_lbutton_handle(KEYSTATE_UP);
+            agent_control_lbutton_handle(KEYSTATE_UP);
             res = true;
             break;
         default:
@@ -1655,7 +1774,7 @@ void LLViewerInput::scanMouse()
     }
 }
 
-bool LLViewerInput::isMouseBindUsed(const EMouseClickType mouse, const MASK mask, const S32 mode)
+bool LLViewerInput::isMouseBindUsed(const EMouseClickType mouse, const MASK mask, const S32 mode) const
 {
     S32 size = mMouseBindings[mode].size();
     for (S32 index = 0; index < size; index++)
diff --git a/indra/newview/llviewerinput.h b/indra/newview/llviewerinput.h
index ca70ac76bf0f294c8655850efd94e3f07b879171..52e95e2168ba4103891e58ae9a9e6267cc328ebd 100644
--- a/indra/newview/llviewerinput.h
+++ b/indra/newview/llviewerinput.h
@@ -31,6 +31,8 @@
 #include "llinitparam.h"
 
 const S32 MAX_KEY_BINDINGS = 128; // was 60
+const S32 keybindings_xml_version = 1;
+const std::string script_mouse_handler_name = "script_trigger_lbutton";
 
 class LLNamedFunction
 {
@@ -100,7 +102,7 @@ class LLViewerInput
 							third_person,
 							sitting,
 							edit_avatar;
-
+		Optional<S32> xml_version; // 'xml', because 'version' appears to be reserved
 		Keys();
 	};
 
@@ -131,7 +133,8 @@ class LLViewerInput
     BOOL            handleMouse(LLWindow *window_impl, LLCoordGL pos, MASK mask, EMouseClickType clicktype, BOOL down);
     void            scanMouse();
 
-    bool            isMouseBindUsed(const EMouseClickType mouse, const MASK mask = MASK_NONE, const S32 mode = MODE_THIRD_PERSON);
+    bool            isMouseBindUsed(const EMouseClickType mouse, const MASK mask, const S32 mode) const;
+    bool            isLMouseHandlingDefault(const S32 mode) const { return mLMouseDefaultHandling[mode]; }
 
 private:
     bool            scanKey(const std::vector<LLKeyboardBinding> &binding,
@@ -171,6 +174,7 @@ class LLViewerInput
     // to send what we think function wants based on collection of bools (mKeyRepeated, mKeyLevel, mKeyDown)
     std::vector<LLKeyboardBinding>	mKeyBindings[MODE_COUNT];
     std::vector<LLMouseBinding>		mMouseBindings[MODE_COUNT];
+    bool							mLMouseDefaultHandling[MODE_COUNT]; // Due to having special priority
 
     // keybindings that do not consume event and are handled earlier, before floaters
     std::vector<LLKeyboardBinding>	mGlobalKeyBindings[MODE_COUNT];
diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp
index 27d8df28c34892abee0dea1cf9316baf13ef2516..812f804ea93d1c90f03ba25bc23c2231af48f761 100644
--- a/indra/newview/llviewermedia.cpp
+++ b/indra/newview/llviewermedia.cpp
@@ -3289,10 +3289,6 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginCla
 		case LLViewerMediaObserver::MEDIA_EVENT_FILE_DOWNLOAD:
 		{
 			LL_DEBUGS("Media") << "Media event - file download requested - filename is " << plugin->getFileDownloadFilename() << LL_ENDL;
-
-            //unblock media plugin
-            const std::vector<std::string> empty_response;
-            plugin->sendPickFileResponse(empty_response);
 		}
 		break;
 
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index a2d3f2c0cf24ed7e6e5f64f7b32081365fef59b1..a95636ff238fcc4e00cc54094726985ba514fac2 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -1278,6 +1278,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
 				mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_ObjectData, data, length, block_num, MAX_OBJECT_BINARY_DATA_SIZE);
 
 				mTotalCRC = crc;
+                // Might need to update mSourceMuted here to properly pick up new radius
 				mSoundCutOffRadius = cutoff;
 
 				// Owner ID used for sound muting or particle system muting
@@ -5884,7 +5885,7 @@ void LLViewerObject::setAttachedSound(const LLUUID &audio_uuid, const LLUUID& ow
 		else if (flags & LL_SOUND_FLAG_STOP)
         {
 			// Just shut off the sound
-			mAudioSourcep->play(LLUUID::null);
+			mAudioSourcep->stop();
 		}
 		return;
 	}
@@ -5923,7 +5924,7 @@ void LLViewerObject::setAttachedSound(const LLUUID &audio_uuid, const LLUUID& ow
 		mAudioSourcep->setQueueSounds(queue);
 		if(!queue) // stop any current sound first to avoid "farts of doom" (SL-1541) -MG
 		{
-			mAudioSourcep->play(LLUUID::null);
+			mAudioSourcep->stop();
 		}
 		
 		// Play this sound if region maturity permits
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index 27fbf39673a044c5b311c8a762f4269aa2aa6b95..67ad72e997b4f2e0a1b0901f1eb0152f90a9c8c1 100644
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -266,7 +266,14 @@ void LLViewerRegionImpl::requestBaseCapabilitiesCoro(U64 regionHandle)
             return;
         }
 
-        regionp = LLWorld::getInstance()->getRegionFromHandle(regionHandle);
+        LLWorld *world_inst = LLWorld::getInstance(); // Not a singleton!
+        if (!world_inst)
+        {
+            LL_WARNS("AppInit", "Capabilities") << "Attempting to get capabilities, but world no longer exists!" << LL_ENDL;
+            return;
+        }
+
+        regionp = world_inst->getRegionFromHandle(regionHandle);
         if (!regionp) //region was removed
         {
             LL_WARNS("AppInit", "Capabilities") << "Attempting to get capabilities for region that no longer exists!" << LL_ENDL;
@@ -314,6 +321,7 @@ void LLViewerRegionImpl::requestBaseCapabilitiesCoro(U64 regionHandle)
 
         regionp = NULL;
         impl = NULL;
+        world_inst = NULL;
         result = httpAdapter->postAndSuspend(httpRequest, url, capabilityNames);
 
         if (STATE_WORLD_INIT > LLStartUp::getStartupState())
@@ -327,7 +335,14 @@ void LLViewerRegionImpl::requestBaseCapabilitiesCoro(U64 regionHandle)
             return;
         }
 
-        regionp = LLWorld::getInstance()->getRegionFromHandle(regionHandle);
+        world_inst = LLWorld::getInstance();
+        if (!world_inst)
+        {
+            LL_WARNS("AppInit", "Capabilities") << "Received capabilities, but world no longer exists!" << LL_ENDL;
+            return;
+        }
+
+        regionp = world_inst->getRegionFromHandle(regionHandle);
         if (!regionp) //region was removed
         {
             LL_WARNS("AppInit", "Capabilities") << "Received capabilities for region that no longer exists!" << LL_ENDL;
@@ -411,7 +426,14 @@ void LLViewerRegionImpl::requestBaseCapabilitiesCompleteCoro(U64 regionHandle)
     // This loop is used for retrying a capabilities request.
     do
     {
-        regionp = LLWorld::getInstance()->getRegionFromHandle(regionHandle);
+        LLWorld *world_inst = LLWorld::getInstance(); // Not a singleton!
+        if (!world_inst)
+        {
+            LL_WARNS("AppInit", "Capabilities") << "Attempting to get capabilities, but world no longer exists!" << LL_ENDL;
+            return;
+        }
+
+        regionp = world_inst->getRegionFromHandle(regionHandle);
         if (!regionp) //region was removed
         {
             LL_WARNS("AppInit", "Capabilities") << "Attempting to get capabilities for region that no longer exists!" << LL_ENDL;
@@ -434,6 +456,7 @@ void LLViewerRegionImpl::requestBaseCapabilitiesCompleteCoro(U64 regionHandle)
         LL_INFOS("AppInit", "Capabilities") << "Requesting second Seed from " << url << " for region " << regionp->getRegionID() << LL_ENDL;
 
         regionp = NULL;
+        world_inst = NULL;
         result = httpAdapter->postAndSuspend(httpRequest, url, capabilityNames);
 
         LLSD httpResults = result["http_result"];
@@ -449,7 +472,14 @@ void LLViewerRegionImpl::requestBaseCapabilitiesCompleteCoro(U64 regionHandle)
             break;
         }
 
-        regionp = LLWorld::getInstance()->getRegionFromHandle(regionHandle);
+        world_inst = LLWorld::getInstance();
+        if (!world_inst)
+        {
+            LL_WARNS("AppInit", "Capabilities") << "Received capabilities, but world no longer exists!" << LL_ENDL;
+            return;
+        }
+
+        regionp = world_inst->getRegionFromHandle(regionHandle);
         if (!regionp) //region was removed
         {
             LL_WARNS("AppInit", "Capabilities") << "Received capabilities for region that no longer exists!" << LL_ENDL;
@@ -533,7 +563,14 @@ void LLViewerRegionImpl::requestSimulatorFeatureCoro(std::string url, U64 region
             break;
         }
 
-        regionp = LLWorld::getInstance()->getRegionFromHandle(regionHandle);
+        LLWorld *world_inst = LLWorld::getInstance(); // Not a singleton!
+        if (!world_inst)
+        {
+            LL_WARNS("AppInit", "Capabilities") << "Attempting to request Sim Feature, but world no longer exists!" << LL_ENDL;
+            return;
+        }
+
+        regionp = world_inst->getRegionFromHandle(regionHandle);
         if (!regionp) //region was removed
         {
             LL_WARNS("AppInit", "SimulatorFeatures") << "Attempting to request Sim Feature for region that no longer exists!" << LL_ENDL;
@@ -541,6 +578,7 @@ void LLViewerRegionImpl::requestSimulatorFeatureCoro(std::string url, U64 region
         }
 
         regionp = NULL;
+        world_inst = NULL;
         LLSD result = httpAdapter->getAndSuspend(httpRequest, url);
 
         LLSD httpResults = result["http_result"];
@@ -559,7 +597,14 @@ void LLViewerRegionImpl::requestSimulatorFeatureCoro(std::string url, U64 region
         // remove the http_result from the llsd
         result.erase("http_result");
 
-        regionp = LLWorld::getInstance()->getRegionFromHandle(regionHandle);
+        world_inst = LLWorld::getInstance();
+        if (!world_inst)
+        {
+            LL_WARNS("AppInit", "Capabilities") << "Attempting to request Sim Feature, but world no longer exists!" << LL_ENDL;
+            return;
+        }
+
+        regionp = world_inst->getRegionFromHandle(regionHandle);
         if (!regionp) //region was removed
         {
             LL_WARNS("AppInit", "SimulatorFeatures") << "Attempting to set Sim Feature for region that no longer exists!" << LL_ENDL;
@@ -2092,7 +2137,14 @@ class CoarseLocationUpdate : public LLHTTPNode
 		const LLSD& input) const
 	{
 		LLHost host(input["sender"].asString());
-		LLViewerRegion* region = LLWorld::getInstance()->getRegion(host);
+
+        LLWorld *world_inst = LLWorld::getInstance(); // Not a singleton!
+        if (!world_inst)
+        {
+            return;
+        }
+
+		LLViewerRegion* region = world_inst->getRegion(host);
 		if( !region )
 		{
 			return;
@@ -3008,12 +3060,12 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames)
 	capabilityNames.append("ObjectAnimation");
 	capabilityNames.append("ObjectMedia");
 	capabilityNames.append("ObjectMediaNavigate");
-	capabilityNames.append("ObjectNavMeshProperties");
 	capabilityNames.append("ParcelPropertiesUpdate");
 	capabilityNames.append("ParcelVoiceInfoRequest");
 	capabilityNames.append("ProductInfoRequest");
 	capabilityNames.append("ProvisionVoiceAccountRequest");
 	capabilityNames.append("ReadOfflineMsgs"); // Requires to respond reliably: AcceptFriendship, AcceptGroupInvite, DeclineFriendship, DeclineGroupInvite
+	capabilityNames.append("RegionObjects");
 	capabilityNames.append("RemoteParcelRequest");
 	capabilityNames.append("RenderMaterials");
 	capabilityNames.append("RequestTextureDownload");
diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp
index c97b1d914b9f1b0a9feb2a1f50202678dd4d61b3..1cb2c6b9eee1b88c7b83ab47b1a67329d2c88a25 100644
--- a/indra/newview/llviewershadermgr.cpp
+++ b/indra/newview/llviewershadermgr.cpp
@@ -102,6 +102,7 @@ LLGLSLShader        gSkinnedObjectSimpleProgram;
 LLGLSLShader		gObjectSimpleImpostorProgram;
 LLGLSLShader        gSkinnedObjectSimpleImpostorProgram;
 LLGLSLShader		gObjectPreviewProgram;
+LLGLSLShader        gPhysicsPreviewProgram;
 LLGLSLShader		gObjectSimpleWaterProgram;
 LLGLSLShader        gSkinnedObjectSimpleWaterProgram;
 LLGLSLShader		gObjectSimpleAlphaMaskProgram;
@@ -758,6 +759,7 @@ void LLViewerShaderMgr::unloadShaders()
 	gObjectSimpleImpostorProgram.unload();
     gSkinnedObjectSimpleImpostorProgram.unload();
 	gObjectPreviewProgram.unload();
+    gPhysicsPreviewProgram.unload();
 	gImpostorProgram.unload();
 	gObjectSimpleAlphaMaskProgram.unload();
     gSkinnedObjectSimpleAlphaMaskProgram.unload();
@@ -1874,6 +1876,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 
             shader->clearPermutations();
             shader->addPermutation("USE_VERTEX_COLOR", "1");
+            shader->addPermutation("HAS_ALPHA_MASK", "1");
             shader->addPermutation("USE_INDEXED_TEX", "1");
             if (use_sun_shadow)
             {
@@ -1950,6 +1953,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
             shader->clearPermutations();
             shader->addPermutation("USE_INDEXED_TEX", "1");
             shader->addPermutation("FOR_IMPOSTOR", "1");
+            shader->addPermutation("HAS_ALPHA_MASK", "1");
             shader->addPermutation("USE_VERTEX_COLOR", "1");
             if (rigged)
             {
@@ -2021,6 +2025,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
             shader[i]->addPermutation("USE_INDEXED_TEX", "1");
             shader[i]->addPermutation("WATER_FOG", "1");
             shader[i]->addPermutation("USE_VERTEX_COLOR", "1");
+            shader[i]->addPermutation("HAS_ALPHA_MASK", "1");
             if (use_sun_shadow)
             {
                 shader[i]->addPermutation("HAS_SHADOW", "1");
@@ -3021,6 +3026,24 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectPreviewProgram.mFeatures.hasLighting = true;
 	}
 
+	if (success)
+	{
+		gPhysicsPreviewProgram.mName = "Preview Physics Shader";
+		gPhysicsPreviewProgram.mFeatures.calculatesLighting = false;
+		gPhysicsPreviewProgram.mFeatures.calculatesAtmospherics = false;
+		gPhysicsPreviewProgram.mFeatures.hasGamma = false;
+		gPhysicsPreviewProgram.mFeatures.hasAtmospherics = false;
+		gPhysicsPreviewProgram.mFeatures.hasLighting = false;
+		gPhysicsPreviewProgram.mFeatures.mIndexedTextureChannels = 0;
+		gPhysicsPreviewProgram.mFeatures.disableTextureIndex = true;
+		gPhysicsPreviewProgram.mShaderFiles.clear();
+		gPhysicsPreviewProgram.mShaderFiles.push_back(make_pair("objects/previewPhysicsV.glsl", GL_VERTEX_SHADER_ARB));
+		gPhysicsPreviewProgram.mShaderFiles.push_back(make_pair("objects/previewPhysicsF.glsl", GL_FRAGMENT_SHADER_ARB));
+		gPhysicsPreviewProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
+		success = gPhysicsPreviewProgram.createShader(NULL, NULL);
+		gPhysicsPreviewProgram.mFeatures.hasLighting = false;
+	}
+
 	if (success)
 	{
 		gObjectSimpleProgram.mName = "Simple Shader";
diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h
index 297cfb6e68bae2b3aecc80a6e1cd64a2fbd3dc89..93bb29a355b1609a16d7fdcd71ad5732f3364e10 100644
--- a/indra/newview/llviewershadermgr.h
+++ b/indra/newview/llviewershadermgr.h
@@ -181,6 +181,7 @@ extern LLGLSLShader			gOneTextureNoColorProgram;
 extern LLGLSLShader			gObjectSimpleProgram;
 extern LLGLSLShader			gObjectSimpleImpostorProgram;
 extern LLGLSLShader			gObjectPreviewProgram;
+extern LLGLSLShader			gPhysicsPreviewProgram;
 extern LLGLSLShader			gObjectSimpleAlphaMaskProgram;
 extern LLGLSLShader			gObjectSimpleWaterProgram;
 extern LLGLSLShader			gObjectSimpleWaterAlphaMaskProgram;
diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp
index 5484d43b8da593e7b7efedb6941fb4c3188c7eb3..3befac73b389f2b2699cb274b581412a8c51420e 100644
--- a/indra/newview/llviewerstats.cpp
+++ b/indra/newview/llviewerstats.cpp
@@ -392,8 +392,12 @@ void update_statistics()
 	gTransferManager.resetTransferBitsIn(LLTCT_ASSET);
 
 	sample(LLStatViewer::VISIBLE_AVATARS, LLVOAvatar::sNumVisibleAvatars);
-	LLWorld::getInstance()->updateNetStats();
-	LLWorld::getInstance()->requestCacheMisses();
+    LLWorld *world = LLWorld::getInstance(); // not LLSingleton
+    if (world)
+    {
+        world->updateNetStats();
+        world->requestCacheMisses();
+    }
 	
 	// Reset all of these values.
 	gVLManager.resetBitCounts();
diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp
index f9fd0f85e3e870324b689920f40c43d9c8927e01..19797a2f543d008fc084b8127f7c96b44d96a5d0 100644
--- a/indra/newview/llviewertexturelist.cpp
+++ b/indra/newview/llviewertexturelist.cpp
@@ -1222,6 +1222,7 @@ void LLViewerTextureList::decodeAllImages(F32 max_time)
 		LLViewerFetchedTexture* imagep = *iter++;
 		imagep->updateFetch();
 	}
+    std::shared_ptr<LL::WorkQueue> main_queue = LLImageGLThread::sEnabled ? LL::WorkQueue::getInstance("mainloop") : NULL;
 	// Run threads
 	S32 fetch_pending = 0;
 	while (1)
@@ -1229,6 +1230,13 @@ void LLViewerTextureList::decodeAllImages(F32 max_time)
 		LLAppViewer::instance()->getTextureCache()->update(1); // unpauses the texture cache thread
 		LLAppViewer::instance()->getImageDecodeThread()->update(1); // unpauses the image thread
 		fetch_pending = LLAppViewer::instance()->getTextureFetch()->update(1); // unpauses the texture fetch thread
+
+        if (LLImageGLThread::sEnabled)
+        {
+            main_queue->runFor(std::chrono::milliseconds(1));
+            fetch_pending += main_queue->size();
+        }
+
 		if (fetch_pending == 0 || timer.getElapsedTimeF32() > max_time)
 		{
 			break;
@@ -1968,9 +1976,18 @@ bool LLUIImageList::initFromFile()
 			preloadUIImage(image.name, file_name, image.use_mips, image.scale, image.clip, image.scale_type);
 		}
 
-		if (cur_pass == PASS_DECODE_NOW && !gSavedSettings.getBOOL("NoPreload"))
+		if (!gSavedSettings.getBOOL("NoPreload"))
 		{
-			gTextureList.decodeAllImages(10.f); // decode preloaded images
+            if (cur_pass == PASS_DECODE_NOW)
+            {
+                // init fetching and decoding of preloaded images
+                gTextureList.decodeAllImages(9.f);
+            }
+            else
+            {
+                // decodeAllImages needs two passes to refresh stats and priorities on second pass
+                gTextureList.decodeAllImages(1.f);
+            }
 		}
 	}
 	return true;
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index a54c29a404197dd1511b3b7a143cccaf4c1f341f..42e21f7130457987d9679947ae56fb691f3fc523 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -2282,6 +2282,9 @@ void LLViewerWindow::initWorldUI()
 	LLPanelStandStopFlying* panel_stand_stop_flying	= LLPanelStandStopFlying::getInstance();
 	panel_ssf_container->addChild(panel_stand_stop_flying);
 
+	LLPanelHideBeacon* panel_hide_beacon = LLPanelHideBeacon::getInstance();
+	panel_ssf_container->addChild(panel_hide_beacon);
+
 	panel_ssf_container->setVisible(TRUE);
 
 	LLMenuOptionPathfindingRebakeNavmesh::getInstance()->initialize();
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 6a5cd6eabcf2f1b784a7afbc4b1549c05726d0e4..87aff6ca981b60b8c5bb9b8b67afd66c914b8e81 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -1334,7 +1334,8 @@ void LLVOAvatar::calculateSpatialExtents(LLVector4a& newMin, LLVector4a& newMax)
 {
     LL_PROFILE_ZONE_SCOPED_CATEGORY_AVATAR;
 
-    S32 box_detail = gSavedSettings.getS32("AvatarBoundingBoxComplexity");
+    static LLCachedControl<S32> box_detail_cache(gSavedSettings, "AvatarBoundingBoxComplexity");
+    S32 box_detail = box_detail_cache;
     if (getOverallAppearance() != AOA_NORMAL)
     {
         if (isControlAvatar())
@@ -2539,16 +2540,13 @@ void LLVOAvatar::idleUpdate(LLAgent &agent, const F64 &time)
 	{
 		LL_INFOS() << "Warning!  Idle on dead avatar" << LL_ENDL;
 		return;
-	}	
+	}
 
+	static LLCachedControl<bool> disable_all_render_types(gSavedSettings, "DisableAllRenderTypes");
 	if (!(gPipeline.hasRenderType(mIsControlAvatar ? LLPipeline::RENDER_TYPE_CONTROL_AV : LLPipeline::RENDER_TYPE_AVATAR))
-		&& !(gSavedSettings.getBOOL("DisableAllRenderTypes")) && !isSelf())
+		&& !disable_all_render_types && !isSelf())
 	{
-        if (!mIsControlAvatar)
-        {
-            idleUpdateNameTag( mLastRootPos );
-        }
-        return;
+		return;
 	}
 
     // Update should be happening max once per frame.
@@ -2684,7 +2682,8 @@ void LLVOAvatar::idleUpdateVoiceVisualizer(bool voice_enabled)
 	// Don't render the user's own voice visualizer when in mouselook, or when opening the mic is disabled.
 	if(isSelf())
 	{
-		if(gAgentCamera.cameraMouselook() || gSavedSettings.getBOOL("VoiceDisableMic"))
+        static LLCachedControl<bool> voice_disable_mic(gSavedSettings, "VoiceDisableMic");
+		if(gAgentCamera.cameraMouselook() || voice_disable_mic)
 		{
 			render_visualizer = false;
 		}
@@ -2821,11 +2820,15 @@ void LLVOAvatar::idleUpdateMisc(bool detailed_update)
 				 ++attachment_iter)
 			{
 				LLViewerObject* attached_object = attachment_iter->get();
-				BOOL visibleAttachment = visible || (attached_object && 
+				BOOL visibleAttachment = visible || (attached_object && attached_object->mDrawable.notNull() &&
 													 !(attached_object->mDrawable->getSpatialBridge() &&
 													   attached_object->mDrawable->getSpatialBridge()->getRadius() < 2.0));
 				
-				if (visibleAttachment && attached_object && !attached_object->isDead() && attachment->getValid())
+				if (visibleAttachment
+                    && attached_object
+                    && !attached_object->isDead()
+                    && attachment->getValid()
+                    && attached_object->mDrawable.notNull())
 				{
 
                     //override rigged attachments' octree spatial extents with this avatar's bounding box
@@ -3181,20 +3184,26 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
 	}
 	
 	const F32 time_visible = mTimeVisible.getElapsedTimeF32();
-	const F32 NAME_SHOW_TIME = gSavedSettings.getF32("RenderNameShowTime");	// seconds
-	const F32 FADE_DURATION = gSavedSettings.getF32("RenderNameFadeDuration"); // seconds
-	BOOL visible_chat = gSavedSettings.getBOOL("UseChatBubbles") && (mChats.size() || mTyping);
-	BOOL render_name =	visible_chat ||
-		(((sRenderName == RENDER_NAME_ALWAYS) ||
+
+    static LLCachedControl<F32> NAME_SHOW_TIME(gSavedSettings, "RenderNameShowTime"); // seconds
+    static LLCachedControl<F32> FADE_DURATION(gSavedSettings, "RenderNameFadeDuration"); // seconds
+    static LLCachedControl<bool> use_chat_bubbles(gSavedSettings, "UseChatBubbles");
+
+	bool visible_avatar = isVisible() || mNeedsAnimUpdate;
+	bool visible_chat = use_chat_bubbles && (mChats.size() || mTyping);
+	bool render_name =	visible_chat ||
+		(visible_avatar &&
+		 ((sRenderName == RENDER_NAME_ALWAYS) ||
 		  (sRenderName == RENDER_NAME_FADE && time_visible < NAME_SHOW_TIME)));
 	// If it's your own avatar, don't draw in mouselook, and don't
 	// draw if we're specifically hiding our own name.
 	if (isSelf())
 	{
+        static LLCachedControl<bool> render_name_show_self(gSavedSettings, "RenderNameShowSelf");
+        static LLCachedControl<S32> name_tag_mode(gSavedSettings, "AvatarNameTagMode");
 		render_name = render_name
 			&& !gAgentCamera.cameraMouselook()
-			&& (visible_chat || (gSavedSettings.getBOOL("RenderNameShowSelf") 
-								 && gSavedSettings.getS32("AvatarNameTagMode") ));
+			&& (visible_chat || (render_name_show_self && name_tag_mode));
 	}
 
 	if ( !render_name )
@@ -3209,7 +3218,7 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
 		return;
 	}
 
-	BOOL new_name = FALSE;
+	bool new_name = FALSE;
 	if (visible_chat != mVisibleChat)
 	{
 		mVisibleChat = visible_chat;
@@ -3274,7 +3283,7 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
 	idleUpdateNameTagAlpha(new_name, alpha);
 }
 
-void LLVOAvatar::idleUpdateNameTagText(BOOL new_name)
+void LLVOAvatar::idleUpdateNameTagText(bool new_name)
 {
 	LLNameValue *title = getNVPair("Title");
 	LLNameValue* firstname = getNVPair("FirstName");
@@ -3584,7 +3593,7 @@ void LLVOAvatar::idleUpdateNameTagPosition(const LLVector3& root_pos_last)
 	mNameText->setPositionAgent(name_position);				
 }
 
-void LLVOAvatar::idleUpdateNameTagAlpha(BOOL new_name, F32 alpha)
+void LLVOAvatar::idleUpdateNameTagAlpha(bool new_name, F32 alpha)
 {
 	llassert(mNameText);
 
@@ -3727,7 +3736,8 @@ void LLVOAvatar::updateAppearanceMessageDebugText()
 		{
 			debug_line += llformat(" - cof: %d req: %d rcv:%d",
 								   curr_cof_version, last_request_cof_version, last_received_cof_version);
-			if (gSavedSettings.getBOOL("DebugForceAppearanceRequestFailure"))
+			static LLCachedControl<bool> debug_force_failure(gSavedSettings, "DebugForceAppearanceRequestFailure");
+			if (debug_force_failure)
 			{
 				debug_line += " FORCING ERRS";
 			}
@@ -5943,7 +5953,8 @@ BOOL LLVOAvatar::processSingleAnimationStateChange( const LLUUID& anim_id, BOOL
 					//}
 					//else
 					{
-						LLUUID sound_id = LLUUID(gSavedSettings.getString("UISndTyping"));
+                        static LLCachedControl<std::string> ui_snd_string(gSavedSettings, "UISndTyping");
+						LLUUID sound_id = LLUUID(ui_snd_string);
 						gAudiop->triggerSound(sound_id, getID(), 1.0f, LLAudioEngine::AUDIO_TYPE_SFX, char_pos_global);
 					}
 				}
@@ -6011,7 +6022,7 @@ void LLVOAvatar::resetAnimations()
 // animations.
 LLUUID LLVOAvatar::remapMotionID(const LLUUID& id)
 {
-	BOOL use_new_walk_run = gSavedSettings.getBOOL("UseNewWalkRun");
+    static LLCachedControl<bool> use_new_walk_run(gSavedSettings, "UseNewWalkRun");
 	LLUUID result = id;
 
 	// start special case female walk for female avatars
@@ -8232,7 +8243,8 @@ BOOL LLVOAvatar::isFullyLoaded() const
 bool LLVOAvatar::isTooComplex() const
 {
 	bool too_complex;
-	bool render_friend =  (LLAvatarTracker::instance().isBuddy(getID()) && gSavedSettings.getBOOL("AlwaysRenderFriends"));
+    static LLCachedControl<bool> always_render_friends(gSavedSettings, "AlwaysRenderFriends");
+	bool render_friend =  (LLAvatarTracker::instance().isBuddy(getID()) && always_render_friends);
 
 	if (isSelf() || render_friend || mVisuallyMuteSetting == AV_ALWAYS_RENDER)
 	{
@@ -9089,7 +9101,8 @@ void LLVOAvatar::parseAppearanceMessage(LLMessageSystem* mesgsys, LLAppearanceMe
 	
 	// Parse visual params, if any.
 	S32 num_blocks = mesgsys->getNumberOfBlocksFast(_PREHASH_VisualParam);
-	bool drop_visual_params_debug = gSavedSettings.getBOOL("BlockSomeAvatarAppearanceVisualParams") && (ll_rand(2) == 0); // pretend that ~12% of AvatarAppearance messages arrived without a VisualParam block, for testing
+    static LLCachedControl<bool> block_some_avatars(gSavedSettings, "BlockSomeAvatarAppearanceVisualParams");
+	bool drop_visual_params_debug = block_some_avatars && (ll_rand(2) == 0); // pretend that ~12% of AvatarAppearance messages arrived without a VisualParam block, for testing
 	if( num_blocks > 1 && !drop_visual_params_debug)
 	{
 		//LL_DEBUGS("Avatar") << avString() << " handle visual params, num_blocks " << num_blocks << LL_ENDL;
@@ -9194,10 +9207,12 @@ bool resolve_appearance_version(const LLAppearanceMessageContents& contents, S32
 void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
 {
 	LL_DEBUGS("Avatar") << "starts" << LL_ENDL;
-	
-	bool enable_verbose_dumps = gSavedSettings.getBOOL("DebugAvatarAppearanceMessage");
+
+    static LLCachedControl<bool> enable_verbose_dumps(gSavedSettings, "DebugAvatarAppearanceMessage");
+    static LLCachedControl<bool> block_avatar_appearance_messages(gSavedSettings, "BlockAvatarAppearanceMessages");
+
 	std::string dump_prefix = getFullname() + "_" + (isSelf()?"s":"o") + "_";
-	if (gSavedSettings.getBOOL("BlockAvatarAppearanceMessages"))
+	if (block_avatar_appearance_messages)
 	{
 		LL_WARNS() << "Blocking AvatarAppearance message" << LL_ENDL;
 		return;
@@ -10648,12 +10663,12 @@ void LLVOAvatar::accountRenderComplexityForObject(
                             F32 attachment_volume_cost = 0;
                             F32 attachment_texture_cost = 0;
                             F32 attachment_children_cost = 0;
-                            const F32 animated_object_attachment_surcharge = 1000;
+                const F32 animated_object_attachment_surcharge = 1000;
 
-                            if (attached_object->isAnimatedObject())
-                            {
-                                attachment_volume_cost += animated_object_attachment_surcharge;
-                            }
+                if (attached_object->isAnimatedObject())
+                {
+                    attachment_volume_cost += animated_object_attachment_surcharge;
+                }
 							attachment_volume_cost += volume->getRenderCost(textures);
 
 							const_child_list_t children = volume->getChildren();
@@ -10901,13 +10916,13 @@ void LLVOAvatar::calculateUpdateRenderComplexity()
 		mVisualComplexity = cost;
 		mVisualComplexityStale = false;
 
-        if (isSelf())
+        static LLCachedControl<U32> show_my_complexity_changes(gSavedSettings, "ShowMyComplexityChanges", 20);
+
+        if (isSelf() && show_my_complexity_changes)
         {
             // Avatar complexity
             LLAvatarRenderNotifier::getInstance()->updateNotificationAgent(mVisualComplexity);
-
             LLAvatarRenderNotifier::getInstance()->setObjectComplexityList(object_complexity_list);
-
             // HUD complexity
             LLHUDRenderNotifier::getInstance()->updateNotificationHUD(hud_complexity_list);
         }
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index acebbc10743469f42bb32371d34940b2a97a3979..8a47895cf7e41fb854c1122fef07fb2c343b6bd0 100644
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -282,9 +282,9 @@ class LLVOAvatar :
 	void 			idleUpdateLoadingEffect();
 	void 			idleUpdateWindEffect();
 	void 			idleUpdateNameTag(const LLVector3& root_pos_last);
-	void			idleUpdateNameTagText(BOOL new_name);
+	void			idleUpdateNameTagText(bool new_name);
 	void			idleUpdateNameTagPosition(const LLVector3& root_pos_last);
-	void			idleUpdateNameTagAlpha(BOOL new_name, F32 alpha);
+	void			idleUpdateNameTagAlpha(bool new_name, F32 alpha);
 	LLColor4		getNameTagColor(bool is_friend);
 	void			clearNameTag();
 	static void		invalidateNameTag(const LLUUID& agent_id);
@@ -939,7 +939,7 @@ class LLVOAvatar :
 	void	   		startTyping() { mTyping = TRUE; mTypingTimer.reset(); }
 	void			stopTyping() { mTyping = FALSE; }
 private:
-	BOOL			mVisibleChat;
+	bool			mVisibleChat;
 
 	//--------------------------------------------------------------------
 	// Lip synch morphs
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 1625dd527632e13bca1243ae3373ba688c97d85e..126a25115d64707d3b6702186c7a3e184198115d 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -71,6 +71,8 @@
 #include "llmediaentry.h"
 #include "llmediadataclient.h"
 #include "llmeshrepository.h"
+#include "llnotifications.h"
+#include "llnotificationsutil.h"
 #include "llagent.h"
 #include "llviewermediafocus.h"
 #include "lldatapacker.h"
@@ -2993,6 +2995,17 @@ void LLVOVolume::mediaEvent(LLViewerMediaImpl *impl, LLPluginClassMedia* plugin,
 			}
 		}
 		break;
+
+        case LLViewerMediaObserver::MEDIA_EVENT_FILE_DOWNLOAD:
+        {
+            // Media might be blocked, waiting for a file,
+            // send an empty response to unblock it
+            const std::vector<std::string> empty_response;
+            plugin->sendPickFileResponse(empty_response);
+
+            LLNotificationsUtil::add("MediaFileDownloadUnsupported");
+        }
+        break;
 		
 		default:
 		break;
@@ -5467,6 +5480,7 @@ static inline void add_face(T*** list, U32* count, T* face)
     {
         if (count[1] < MAX_FACE_COUNT)
         {
+            face->setDrawOrderIndex(count[1]);
             list[1][count[1]++] = face;
         }
     }
@@ -5474,6 +5488,7 @@ static inline void add_face(T*** list, U32* count, T* face)
     {
         if (count[0] < MAX_FACE_COUNT)
         {
+            face->setDrawOrderIndex(count[0]);
             list[0][count[0]++] = face;
         }
     }
@@ -5689,6 +5704,8 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
                             pool->removeFace(facep);
                         }
                         facep->clearState(LLFace::RIGGED);
+                        facep->mAvatar = NULL;
+                        facep->mSkinInfo = NULL;
                     }
                 }
 
@@ -5926,7 +5943,6 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 
         // for rigged set, add weights and disable alpha sorting (rigged items use depth buffer)
         extra_mask |= LLVertexBuffer::MAP_WEIGHT4;
-        alpha_sort = FALSE;
         rigged = TRUE;
     }
 
@@ -6086,7 +6102,7 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group)
 	} 
 }
 
-struct CompareBatchBreakerModified
+struct CompareBatchBreaker
 {
 	bool operator()(const LLFace* const& lhs, const LLFace* const& rhs)
 	{
@@ -6101,18 +6117,23 @@ struct CompareBatchBreakerModified
 		{
 			return lte->getFullbright() < rte->getFullbright();
 		}
-		else if (LLPipeline::sRenderDeferred && lte->getMaterialParams() != rte->getMaterialParams())
-		{
-			return lte->getMaterialParams() < rte->getMaterialParams();
-		}
-		else if (LLPipeline::sRenderDeferred && (lte->getMaterialParams() == rte->getMaterialParams()) && (lte->getShiny() != rte->getShiny()))
+        else if (LLPipeline::sRenderDeferred && lte->getMaterialID() != rte->getMaterialID())
+        {
+            return lte->getMaterialID() < rte->getMaterialID();
+        }
+		else if (lte->getShiny() != rte->getShiny())
 		{
 			return lte->getShiny() < rte->getShiny();
 		}
-		else
+        else if (lhs->getTexture() != rhs->getTexture())
 		{
 			return lhs->getTexture() < rhs->getTexture();
 		}
+        else 
+        {
+            // all else being equal, maintain consistent draw order
+            return lhs->getDrawOrderIndex() < rhs->getDrawOrderIndex();
+        }
 	}
 };
 
@@ -6120,9 +6141,6 @@ struct CompareBatchBreakerRigged
 {
     bool operator()(const LLFace* const& lhs, const LLFace* const& rhs)
     {
-        const LLTextureEntry* lte = lhs->getTextureEntry();
-        const LLTextureEntry* rte = rhs->getTextureEntry();
-
         if (lhs->mAvatar != rhs->mAvatar)
         {
             return lhs->mAvatar < rhs->mAvatar;
@@ -6131,23 +6149,12 @@ struct CompareBatchBreakerRigged
         {
             return lhs->mSkinInfo->mHash < rhs->mSkinInfo->mHash;
         }
-        else if (lhs->getTexture() != rhs->getTexture())
-        {
-            return lhs->getTexture() < rhs->getTexture();
-        }
-        else if (lte->getBumpmap() != rte->getBumpmap())
-        {
-            return lte->getBumpmap() < rte->getBumpmap();
-        }
-        else if (LLPipeline::sRenderDeferred && lte->getMaterialID() != rte->getMaterialID())
-        {
-            return lte->getMaterialID() < rte->getMaterialID();
-        }
-        else // if (LLPipeline::sRenderDeferred && (lte->getMaterialParams() == rte->getMaterialParams()) && (lte->getShiny() != rte->getShiny()))
+        else
         {
-            return lte->getShiny() < rte->getShiny();
+            // "inherit" non-rigged behavior
+            CompareBatchBreaker comp;
+            return comp(lhs, rhs);
         }
-        
     }
 };
 
@@ -6190,13 +6197,16 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace
         
         if (rigged)
         {
-            //sort faces by things that break batches, including avatar and mesh id
-            std::sort(faces, faces + face_count, CompareBatchBreakerRigged());
+            if (!distance_sort) // <--- alpha "sort" rigged faces by maintaining original draw order
+            {
+                //sort faces by things that break batches, including avatar and mesh id
+                std::sort(faces, faces + face_count, CompareBatchBreakerRigged());
+            }
         }
         else if (!distance_sort)
         {
             //sort faces by things that break batches, not including avatar and mesh id
-            std::sort(faces, faces + face_count, CompareBatchBreakerModified());
+            std::sort(faces, faces + face_count, CompareBatchBreaker());
         }
 		else
 		{
@@ -6226,11 +6236,6 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace
 		texture_index_channels = gDeferredAlphaProgram.mFeatures.mIndexedTextureChannels;
 	}
     
-    if (rigged)
-    { //don't attempt distance sorting on rigged meshes, not likely to succeed and breaks batches
-        distance_sort = FALSE;
-    }
-
     if (distance_sort)
     {
         buffer_index = -1;
diff --git a/indra/newview/llweb.cpp b/indra/newview/llweb.cpp
index b8f1ec35f6dd707a296fd31dda90a554dcafa987..c4d873dd22bc42c2ec140567f070ae9c5cdc3a65 100644
--- a/indra/newview/llweb.cpp
+++ b/indra/newview/llweb.cpp
@@ -199,19 +199,16 @@ std::string LLWeb::expandURLSubstitutions(const std::string &url,
 	// find the grid
 	std::string current_grid = LLGridManager::getInstance()->getGridId();
 	std::transform(current_grid.begin(), current_grid.end(), current_grid.begin(), ::tolower);
-	if (current_grid == "agni")
+    if (current_grid == "damballah")
 	{
-		substitution["GRID"] = "secondlife.com";
-	}
-	else if (current_grid == "damballah")
-	{
-		// Staging grid has its own naming scheme.
-		substitution["GRID"] = "secondlife-staging.com";
-	}
-	else
-	{
-		substitution["GRID"] = llformat("%s.lindenlab.com", current_grid.c_str());
-	}
+      // Staging grid has its own naming scheme.
+      substitution["GRID"] = "secondlife-staging.com";
+    }
+    else
+    {
+        substitution["GRID"] = "secondlife.com";
+    }
+
 	// expand all of the substitution strings and escape the url
 	std::string expanded_url = url;
 	LLStringUtil::format(expanded_url, substitution);
diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp
index 0a2ad8235404a20981c4540060fc2546e12c265e..d79a25c1adcef7057ba0de15b861716c6441a0f7 100644
--- a/indra/newview/llworld.cpp
+++ b/indra/newview/llworld.cpp
@@ -114,7 +114,7 @@ LLWorld::LLWorld() :
 }
 
 
-void LLWorld::destroyClass()
+void LLWorld::resetClass()
 {
 	mHoleWaterObjects.clear();
 	gObjectList.destroy();
@@ -136,7 +136,6 @@ void LLWorld::destroyClass()
 	LLDrawable::incrementVisible();
 
 	LLSceneMonitor::deleteSingleton();
-    LLWorld::deleteSingleton();
 }
 
 
@@ -1197,6 +1196,16 @@ class LLEstablishAgentCommunication : public LLHTTPNode
 	virtual void post(ResponsePtr response, const LLSD& context, const LLSD& input) const
 	{
         if (LLApp::isExiting())
+        {
+            return;
+        }
+
+        if (gDisconnected)
+        {
+            return;
+        }
+
+        if (!LLWorld::instanceExists())
         {
             return;
         }
@@ -1209,8 +1218,13 @@ class LLEstablishAgentCommunication : public LLHTTPNode
             return;
 		}
 
-		LLHost sim(input["body"]["sim-ip-and-port"].asString());
-	
+        LLHost sim(input["body"]["sim-ip-and-port"].asString());
+        if (sim.isInvalid())
+        {
+            LL_WARNS() << "Got EstablishAgentCommunication with invalid host" << LL_ENDL;
+            return;
+        }
+
 		LLViewerRegion* regionp = LLWorld::getInstance()->getRegion(sim);
 		if (!regionp)
 		{
@@ -1219,7 +1233,7 @@ class LLEstablishAgentCommunication : public LLHTTPNode
 			return;
 		}
 		LL_DEBUGS("CrossingCaps") << "Calling setSeedCapability from LLEstablishAgentCommunication::post. Seed cap == "
-				<< input["body"]["seed-capability"] << LL_ENDL;
+				<< input["body"]["seed-capability"] << " for region " << regionp->getRegionID() << LL_ENDL;
 		regionp->setSeedCapability(input["body"]["seed-capability"]);
 	}
 };
diff --git a/indra/newview/llworld.h b/indra/newview/llworld.h
index 1c12ad0e2c666035676e1235c10fc81ac71ace28..68db2b8ccfc6f02c550b66c5dab11e8cbd467ec0 100644
--- a/indra/newview/llworld.h
+++ b/indra/newview/llworld.h
@@ -65,7 +65,9 @@ class LLWorld : public LLSimpleton<LLWorld>
 public:
     LLWorld();
 
-    void destroyClass();
+    // Clear any objects, regions
+    // Prepares class to be reused or destroyed
+    void resetClass();
 
 	LLViewerRegion*	addRegion(const U64 &region_handle, const LLHost &host);
 		// safe to call if already present, does the "right thing" if
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index a3c971153c81c0c49c487d25433bdb3e1a2aad16..545fe9642ad3f51aca6c9d538127e71abd2e044a 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -363,10 +363,12 @@ static LLCullResult* sCull = NULL;
 
 void validate_framebuffer_object();
 
-
-bool addDeferredAttachments(LLRenderTarget& target)
+// Add color attachments for deferred rendering
+// target -- RenderTarget to add attachments to
+// for_impostor -- whether or not these render targets are for an impostor (if true, avoids implicit sRGB conversions)
+bool addDeferredAttachments(LLRenderTarget& target, bool for_impostor = false)
 {
-	return target.addColorAttachment(GL_SRGB8_ALPHA8) && //specular
+	return target.addColorAttachment(for_impostor ? GL_RGBA : GL_SRGB8_ALPHA8) && //specular
 			target.addColorAttachment(GL_RGB10_A2); //normal+z
 }
 
@@ -10818,7 +10820,7 @@ void LLPipeline::renderRiggedGroups(LLRenderPass* pass, U32 type, U32 mask, bool
 
 static LLTrace::BlockTimerStatHandle FTM_GENERATE_IMPOSTOR("Generate Impostor");
 
-void LLPipeline::generateImpostor(LLVOAvatar* avatar)
+void LLPipeline::generateImpostor(LLVOAvatar* avatar, bool preview_avatar)
 {
     LL_RECORD_BLOCK_TIME(FTM_GENERATE_IMPOSTOR);
 	LLGLState::checkStates();
@@ -10837,11 +10839,12 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
 
 	assertInitialized();
 
-	bool visually_muted = avatar->isVisuallyMuted();		
+    // previews can't be muted or impostered
+	bool visually_muted = !preview_avatar && avatar->isVisuallyMuted();
     LL_DEBUGS_ONCE("AvatarRenderPipeline") << "Avatar " << avatar->getID()
                               << " is " << ( visually_muted ? "" : "not ") << "visually muted"
                               << LL_ENDL;
-	bool too_complex = avatar->isTooComplex();		
+	bool too_complex = !preview_avatar && avatar->isTooComplex();
     LL_DEBUGS_ONCE("AvatarRenderPipeline") << "Avatar " << avatar->getID()
                               << " is " << ( too_complex ? "" : "not ") << "too complex"
                               << LL_ENDL;
@@ -10915,6 +10918,7 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
 	U32 resY = 0;
 	U32 resX = 0;
 
+    if (!preview_avatar)
 	{
 		const LLVector4a* ext = avatar->mDrawable->getSpatialExtents();
 		LLVector3 pos(avatar->getRenderPosition()+avatar->getImpostorOffset());
@@ -10972,14 +10976,11 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
 
 		if (!avatar->mImpostor.isComplete())
 		{
+            avatar->mImpostor.allocate(resX, resY, GL_RGBA, TRUE, FALSE);
+
 			if (LLPipeline::sRenderDeferred)
 			{
-				avatar->mImpostor.allocate(resX,resY,GL_SRGB8_ALPHA8,TRUE,FALSE);
-				addDeferredAttachments(avatar->mImpostor);
-			}
-			else
-			{
-				avatar->mImpostor.allocate(resX,resY,GL_RGBA,TRUE,FALSE);
+				addDeferredAttachments(avatar->mImpostor, true);
 			}
 		
 			gGL.getTexUnit(0)->bind(&avatar->mImpostor);
@@ -11001,7 +11002,20 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
 		LLDrawPoolAvatar::sMinimumAlpha = 0.f;
 	}
 
-	if (LLPipeline::sRenderDeferred)
+    if (preview_avatar)
+    {
+        // previews don't care about imposters
+        if (LLPipeline::sRenderDeferred)
+        {
+            renderGeomDeferred(camera);
+            renderGeomPostDeferred(camera);
+        }
+        else
+        {
+            renderGeom(camera);
+        }
+    }
+    else if (LLPipeline::sRenderDeferred)
 	{
 		avatar->mImpostor.clear();
 		renderGeomDeferred(camera);
@@ -11089,7 +11103,7 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
             LL_DEBUGS_ONCE("AvatarRenderPipeline") << "Avatar " << avatar->getID() << " MUTED set solid color " << muted_color << LL_ENDL;
 			gGL.diffuseColor4fv( muted_color.mV );
 		}
-		else
+		else if (!preview_avatar)
 		{ //grey muted avatar
             LL_DEBUGS_ONCE("AvatarRenderPipeline") << "Avatar " << avatar->getID() << " MUTED set grey" << LL_ENDL;
 			gGL.diffuseColor4fv(LLColor4::pink.mV );
@@ -11110,9 +11124,11 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
 		gGL.popMatrix();
 	}
 
-	avatar->mImpostor.flush();
-
-	avatar->setImpostorDim(tdim);
+    if (!preview_avatar)
+    {
+        avatar->mImpostor.flush();
+        avatar->setImpostorDim(tdim);
+    }
 
 	sUseOcclusion = occlusion;
 	sReflectionRender = false;
@@ -11125,176 +11141,18 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
 	gGL.matrixMode(LLRender::MM_MODELVIEW);
 	gGL.popMatrix();
 
-	avatar->mNeedsImpostorUpdate = FALSE;
-	avatar->cacheImpostorValues();
-	avatar->mLastImpostorUpdateFrameTime = gFrameTimeSeconds;
+    if (!preview_avatar)
+    {
+        avatar->mNeedsImpostorUpdate = FALSE;
+        avatar->cacheImpostorValues();
+        avatar->mLastImpostorUpdateFrameTime = gFrameTimeSeconds;
+    }
 
 	LLVertexBuffer::unbind();
 	LLGLState::checkStates();
 	LLGLState::checkTextureChannels();
 }
 
-static LLTrace::BlockTimerStatHandle FTM_PREVIEW_AVATAR("Preview Avatar");
-
-void LLPipeline::previewAvatar(LLVOAvatar* avatar)
-{
-    LL_RECORD_BLOCK_TIME(FTM_PREVIEW_AVATAR);
-
-    LLGLDepthTest gls_depth(GL_TRUE, GL_TRUE);
-    gGL.flush();
-    gGL.setSceneBlendType(LLRender::BT_REPLACE);
-
-    LLGLState::checkStates();
-    LLGLState::checkTextureChannels();
-
-    static LLCullResult result;
-    result.clear();
-    grabReferences(result);
-
-    if (!avatar || !avatar->mDrawable)
-    {
-        LL_WARNS_ONCE("AvatarRenderPipeline") << "Avatar is " << (avatar ? "not drawable" : "null") << LL_ENDL;
-        return;
-    }
-    LL_DEBUGS_ONCE("AvatarRenderPipeline") << "Avatar " << avatar->getID() << " is drawable" << LL_ENDL;
-
-    assertInitialized();
-
-    pushRenderTypeMask();
-
-    {
-        //hide world geometry
-        clearRenderTypeMask(
-            RENDER_TYPE_SKY,
-            RENDER_TYPE_WL_SKY,
-            RENDER_TYPE_GROUND,
-            RENDER_TYPE_TERRAIN,
-            RENDER_TYPE_GRASS,
-            RENDER_TYPE_CONTROL_AV, // Animesh
-            RENDER_TYPE_TREE,
-            RENDER_TYPE_VOIDWATER,
-            RENDER_TYPE_WATER,
-            RENDER_TYPE_PASS_GRASS,
-            RENDER_TYPE_HUD,
-            RENDER_TYPE_PARTICLES,
-            RENDER_TYPE_CLOUDS,
-            RENDER_TYPE_HUD_PARTICLES,
-            END_RENDER_TYPES
-        );
-    }
-
-    S32 occlusion = sUseOcclusion;
-    sUseOcclusion = 0;
-
-    sReflectionRender = !sRenderDeferred;
-
-    sShadowRender = true;
-    sImpostorRender = true; // Likely not needed for previews
-
-    LLViewerCamera* viewer_camera = LLViewerCamera::getInstance();
-
-    {
-        markVisible(avatar->mDrawable, *viewer_camera);
-
-        LLVOAvatar::attachment_map_t::iterator iter;
-        for (iter = avatar->mAttachmentPoints.begin();
-            iter != avatar->mAttachmentPoints.end();
-            ++iter)
-        {
-            LLViewerJointAttachment *attachment = iter->second;
-            for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
-                attachment_iter != attachment->mAttachedObjects.end();
-                ++attachment_iter)
-            {
-                if (LLViewerObject* attached_object = attachment_iter->get())
-                {
-                    markVisible(attached_object->mDrawable->getSpatialBridge(), *viewer_camera);
-                }
-            }
-        }
-    }
-
-    stateSort(*LLViewerCamera::getInstance(), result);
-
-    LLCamera camera = *viewer_camera;
-
-    F32 old_alpha = LLDrawPoolAvatar::sMinimumAlpha;
-
-    if (LLPipeline::sRenderDeferred)
-    {
-        renderGeomDeferred(camera);
-
-        renderGeomPostDeferred(camera);
-    }
-    else
-    {
-        renderGeom(camera);
-    }
-
-    LLDrawPoolAvatar::sMinimumAlpha = old_alpha;
-
-    { //create alpha mask based on depth buffer
-        if (LLPipeline::sRenderDeferred)
-        {
-            GLuint buff = GL_COLOR_ATTACHMENT0;
-            LL_PROFILER_GPU_ZONEC("gl.DrawBuffersARB", 0x8000FF);
-            glDrawBuffersARB(1, &buff);
-        }
-
-        LLGLDisable blend(GL_BLEND);
-
-        gGL.setColorMask(false, true);
-
-        gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-
-        LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_GREATER);
-
-        gGL.flush();
-
-        gGL.pushMatrix();
-        gGL.loadIdentity();
-        gGL.matrixMode(LLRender::MM_PROJECTION);
-        gGL.pushMatrix();
-        gGL.loadIdentity();
-
-        static const F32 clip_plane = 0.99999f;
-
-        gDebugProgram.bind();
-
-        gGL.begin(LLRender::QUADS);
-        gGL.vertex3f(-1, -1, clip_plane);
-        gGL.vertex3f(1, -1, clip_plane);
-        gGL.vertex3f(1, 1, clip_plane);
-        gGL.vertex3f(-1, 1, clip_plane);
-        gGL.end();
-        gGL.flush();
-
-        gDebugProgram.unbind();
-
-        gGL.popMatrix();
-        gGL.matrixMode(LLRender::MM_MODELVIEW);
-        gGL.popMatrix();
-    }
-
-    sUseOcclusion = occlusion;
-    sReflectionRender = false;
-    sImpostorRender = false;
-    sShadowRender = false;
-    popRenderTypeMask();
-
-    gGL.matrixMode(LLRender::MM_PROJECTION);
-    gGL.popMatrix();
-    gGL.matrixMode(LLRender::MM_MODELVIEW);
-    gGL.popMatrix();
-
-    LLVertexBuffer::unbind();
-    LLGLState::checkStates();
-    LLGLState::checkTextureChannels();
-
-    gGL.setSceneBlendType(LLRender::BT_ALPHA);
-    gGL.flush();
-}
-
 bool LLPipeline::hasRenderBatches(const U32 type) const
 {
 	return sCull->getRenderMapSize(type) > 0;
diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h
index 4946bac7013c392e832422e26228a506b878de91..bdd498abff972ae1f1c7312791807f98d6b13978 100644
--- a/indra/newview/pipeline.h
+++ b/indra/newview/pipeline.h
@@ -134,8 +134,7 @@ class LLPipeline
 	void allocatePhysicsBuffer();
 	
 	void resetVertexBuffers(LLDrawable* drawable);
-	void generateImpostor(LLVOAvatar* avatar);
-    void previewAvatar(LLVOAvatar* avatar);
+	void generateImpostor(LLVOAvatar* avatar, bool preview_avatar = false);
 	void bindScreenToTexture();
 	void renderFinalize();
 
diff --git a/indra/newview/skins/default/xui/en/control_table_contents_media.xml b/indra/newview/skins/default/xui/en/control_table_contents_media.xml
index ce5d3556b612988e32fab8aa341b334b7e06d132..43e8d730cd9679460d8bf6eeb9277c0d46b3a71e 100644
--- a/indra/newview/skins/default/xui/en/control_table_contents_media.xml
+++ b/indra/newview/skins/default/xui/en/control_table_contents_media.xml
@@ -73,4 +73,14 @@
          name="lst_action"
          value="Start Gesture" />
     </rows>
+    <rows
+     name="script_trigger_lbutton"
+     value="script_trigger_lbutton">
+        <columns
+         column="lst_action"
+         font="SansSerif"
+         halign="left"
+         name="lst_action"
+         value="Interact (Script LMB)" />
+    </rows>
 </contents>
diff --git a/indra/newview/skins/default/xui/en/floater_associate_listing.xml b/indra/newview/skins/default/xui/en/floater_associate_listing.xml
index e019ed58ddbd9aa955f65d7e918384246154f24a..0f7ed241034e3aee0c1e1263b564be35deb3fcd5 100644
--- a/indra/newview/skins/default/xui/en/floater_associate_listing.xml
+++ b/indra/newview/skins/default/xui/en/floater_associate_listing.xml
@@ -20,9 +20,10 @@
      name="message">
         Listing ID:
     </text>
+    <!--listing_id is a positive S32-->
     <line_editor
      type="string"
-     length="1"
+     max_length_bytes="10"
      follows="top|right"
      font="SansSerif"
      height="20"
diff --git a/indra/newview/skins/default/xui/en/floater_model_preview.xml b/indra/newview/skins/default/xui/en/floater_model_preview.xml
index ca3e40465c92b74bdef9156303b26c20a444f6fc..e499ddbc2f396f3ea6789c060c29fc775cad031d 100644
--- a/indra/newview/skins/default/xui/en/floater_model_preview.xml
+++ b/indra/newview/skins/default/xui/en/floater_model_preview.xml
@@ -34,7 +34,7 @@
   <string name="mesh_status_missing_lod">Missing required level of detail.</string>
   <string name="mesh_status_invalid_material_list">LOD materials are not a subset of reference model.</string>
   <string name="phys_status_vertex_limit_exceeded">Some physical hulls exceed vertex limitations.</string>
-  <string name="phys_status_degenerate_triangles">The physics mesh too dense remove the small thin triangles (see preview)</string>
+  <string name="phys_status_degenerate_triangles">The physics mesh is too dense or contains degenerate triangles. Use Analyze/Simplify to resolve.</string>
   <string name="layer_all">All</string> <!-- Text to display in physics layer combo box for "all layers" -->
   <string name="decomposing">Analyzing...</string>
   <string name="simplifying">Simplifying...</string>
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 1b9df53ad2834869c23dac1ee6a647ad6f1c4de8..ed6683ce2aaac367563080f99fb9ea76c8aab225 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -2344,6 +2344,7 @@ Please try again later.
   <notification
    icon="notifytip.tga"
    name="LandmarkCreated"
+   log_to_chat="false"
    type="notifytip">
 You have added "[LANDMARK_NAME]" to your [FOLDER_NAME] folder.
   </notification>
diff --git a/indra/newview/skins/default/xui/en/panel_hide_beacon.xml b/indra/newview/skins/default/xui/en/panel_hide_beacon.xml
new file mode 100644
index 0000000000000000000000000000000000000000..7cab285f77dc37e1cba722b0ad44a6652fe3b6bc
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_hide_beacon.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ height="25"
+ layout="topleft"
+ name="panel_hide_beacon"
+ mouse_opaque="false"
+ visible="true"
+ width="133">
+    <button
+     follows="left|bottom"
+     height="19"
+     label="Hide beacon"
+     layout="topleft"
+     left="10"
+     name="hide_beacon_btn"
+     tool_tip="Stop tracking and hide beacon"
+     top="2"
+     visible="false"
+     width="113" />
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_sound.xml b/indra/newview/skins/default/xui/en/panel_preferences_sound.xml
index 2ea20570b18e39da29a3e874ffc58667c90b5fac..42a34d171aa352179d3c04aad6e6b5ca0bc7ebc6 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_sound.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_sound.xml
@@ -28,7 +28,7 @@
      height="15"
      increment="0.025"
      initial_value="0.5"
-     label="Master volume"
+     label="All volume"
 	   label_width="120"
      layout="topleft"
      left="0"
@@ -386,7 +386,7 @@
      left="25"
      name="voice_chat_settings"
      width="200"
-     top_pad="7">
+     top_pad="16">
 	  Voice Chat Settings
     </text>
     <text
diff --git a/indra/newview/skins/default/xui/en/panel_toolbar_view.xml b/indra/newview/skins/default/xui/en/panel_toolbar_view.xml
index f5c559fe1dda158c06c33f4439980e9067918200..a3348f28c7317adf250d1de172f3a67174bd7e11 100644
--- a/indra/newview/skins/default/xui/en/panel_toolbar_view.xml
+++ b/indra/newview/skins/default/xui/en/panel_toolbar_view.xml
@@ -95,7 +95,7 @@
                tab_stop="false"
                name="state_management_buttons_container"
                visible="false"
-               width="200"/>
+               width="350"/>
       </layout_panel>
        <layout_panel name="right_toolbar_panel"
                     auto_resize="false"
diff --git a/indra/newview/skins/default/xui/en/panel_volume_pulldown.xml b/indra/newview/skins/default/xui/en/panel_volume_pulldown.xml
index 2034409111990c1550be42693801162092cb9c37..b4eb1ade9476c79fb2b551087810c1e454c0e3ae 100644
--- a/indra/newview/skins/default/xui/en/panel_volume_pulldown.xml
+++ b/indra/newview/skins/default/xui/en/panel_volume_pulldown.xml
@@ -19,7 +19,7 @@
      height="15"
      increment="0.025"
      initial_value="0.5"
-     label="Master"
+     label="All"
      label_width="60"
      left="10"
      width="160"
diff --git a/indra/test/sync.h b/indra/test/sync.h
index ca8b7262d692612c7a7f9c656ee67d9e98e59213..bd837cb73054aa1659727288dee80bd6036e0a74 100644
--- a/indra/test/sync.h
+++ b/indra/test/sync.h
@@ -89,25 +89,26 @@ class Sync
     /// suspend until "somebody else" has bumped mCond by n steps
     void yield(int n=1)
     {
-        return yield_until(STRINGIZE("Sync::yield_for(" << n << ") timed out after "
-                                     << int(mTimeout.value()) << "ms"),
-                           mCond.get() + n);
+        return yield_until("Sync::yield_for", n, mCond.get() + n);
     }
 
     /// suspend until "somebody else" has bumped mCond to a specific value
     void yield_until(int until)
     {
-        return yield_until(STRINGIZE("Sync::yield_until(" << until << ") timed out after "
-                                     << int(mTimeout.value()) << "ms"),
-                           until);
+        return yield_until("Sync::yield_until", until, until);
     }
 
 private:
-    void yield_until(const std::string& desc, int until)
+    void yield_until(const char* func, int arg, int until)
     {
         std::string name(llcoro::logname());
         LL_DEBUGS() << name << " yield_until(" << until << ") suspending" << LL_ENDL;
-        tut::ensure(name + ' ' + desc, mCond.wait_for_equal(mTimeout, until));
+        if (! mCond.wait_for_equal(mTimeout, until))
+        {
+            tut::fail(STRINGIZE(name << ' ' << func << '(' << arg << ") timed out after "
+                                << int(mTimeout.value()) << "ms (expected " << until
+                                << ", actual " << mCond.get() << ')'));
+        }
         // each time we wake up, bump mCond
         bump();
     }