diff --git a/.github/labeler.yaml b/.github/labeler.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..d31a361baf2212b092bc7dca01ccf0f0e0b20ce4
--- /dev/null
+++ b/.github/labeler.yaml
@@ -0,0 +1,78 @@
+llappearance:
+  - indra/llappearance/**/*
+  
+llaudio:
+  - indra/llaudio/**/*
+
+llcharacter:
+  - indra/llcharacter/**/*
+
+llcommon:
+  - indra/llcommon/**/*
+
+llcorehttp:
+  - indra/llcorehttp/**/*
+
+llcrashlogger:
+  - indra/llcrashlogger/**/*
+
+llfilesystem:
+  - indra/llfilesystem/**/*
+
+llimage:
+  - indra/llimage/**/*
+
+llimagej2coj:
+  - indra/llimagej2coj/**/*
+
+llinventory:
+  - indra/llinventory/**/*
+
+llkdu:
+  - indra/llkdu/**/*
+
+llmath:
+  - indra/llmath/**/*
+
+llmeshoptimizer:
+  - indra/llmeshoptimizer/**/*
+
+llmessage:
+  - indra/llmessage/**/*
+
+llplugin:
+  - indra/llplugin/**/*
+
+llprimitive:
+  - indra/llprimitive/**/*
+
+llrender:
+  - indra/llrender/**/*
+
+llui:
+  - indra/llui/**/*
+
+llwindow:
+  - indra/llwindow/**/*
+
+llxml:
+  - indra/llxml/**/*
+
+cmake:
+  - '**/*.cmake'
+  - '**/*/cmake/*'
+  - '**/CMakeLists.txt'
+
+python:
+  - '**/*.py'
+
+c/cpp:
+  - '**/*.c'
+  - '**/*.cpp'
+  - '**/*.cxx'
+  - '**/*.h'
+  - '**/*.hpp'
+  - '**/*.hxx'
+  - '**/*.i'
+  - '**/*.inl'
+  - '**/*.y'
diff --git a/.github/workflows/cla.yaml b/.github/workflows/cla.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..fa180c66c9763bfcc7bec83d4c901e7526790574
--- /dev/null
+++ b/.github/workflows/cla.yaml
@@ -0,0 +1,25 @@
+name: Check CLA
+
+on:
+  issue_comment:
+    types: [created]
+  pull_request_target:
+    types: [opened, closed, synchronize]
+
+jobs:
+  cla:
+    name: Check CLA
+    runs-on: ubuntu-latest
+    steps:
+      - name: CLA Assistant
+        if: (github.event.comment.body == 'recheck' || github.event.comment.body == 'I have read the CLA Document and I hereby sign the CLA') || github.event_name == 'pull_request_target'
+        uses: secondlife-3p/contributor-assistant@v2
+        env:
+          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+          PERSONAL_ACCESS_TOKEN: ${{ secrets.SHARED_CLA_TOKEN }}
+        with:
+          branch: main
+          path-to-document: https://github.com/secondlife/cla/blob/master/CLA.md
+          path-to-signatures: signatures.json
+          remote-organization-name: secondlife
+          remote-repository-name: cla-signatures
diff --git a/.github/workflows/label.yaml b/.github/workflows/label.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..6e41d8aa2d808e5edd3e99bc67067ba5353b7b69
--- /dev/null
+++ b/.github/workflows/label.yaml
@@ -0,0 +1,15 @@
+name: Pull Request Labeler
+on:
+  - pull_request_target
+
+jobs:
+  triage:
+    permissions:
+      contents: read
+      pull-requests: write
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/labeler@v4
+        with:
+          configuration-path: .github/labeler.yaml
+          repo-token: "${{ secrets.GITHUB_TOKEN }}"
diff --git a/doc/LGPL-licence.txt b/LICENSE
similarity index 100%
rename from doc/LGPL-licence.txt
rename to LICENSE
diff --git a/README.md b/README.md
index 8813c2522815c116a2f14a59cb52cf52278ef2d5..c57140af9cb65f04afacdb15db3963240929c6be 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,8 @@
-![Second Life Logo](doc/sl-logo.png)
+<picture>
+  <source media="(prefers-color-scheme: dark)" srcset="doc/sl-logo-dark.png">
+  <source media="(prefers-color-scheme: light)" srcset="doc/sl-logo.png">
+  <img alt="Second Life Logo" src="doc/sl-logo.png">
+</picture>
 
 **[Second Life][] is a free 3D virtual world where users can create, connect and chat with others from around the
 world.** This repository contains the source code for the official client.
diff --git a/autobuild.xml b/autobuild.xml
index 5a5ffa2898df4867c8ce2166708afafe4fc50551..81c47b3300e3f12864330ec4014161b74a18d7e3 100644
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -52,9 +52,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>b6357ef3a0ec37877a5831820f25094e</string>
+              <string>178b16ee9ff67986c8c14413ee68218e</string>
               <key>url</key>
-              <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/80557/759704/apr_suite-1.4.5.558565-darwin64-558565.tar.bz2</string>
+              <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/107593/938535/apr_suite-1.4.5.576669-darwin64-576669.tar.bz2</string>
             </map>
             <key>name</key>
             <string>darwin64</string>
@@ -76,9 +76,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>cb48ac069440f6dcd564cfa9fd02a4c2</string>
+              <string>d2997cad03dbd0d70a060276b5671480</string>
               <key>url</key>
-              <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/80556/759710/apr_suite-1.4.5.558565-windows-558565.tar.bz2</string>
+              <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/107594/938548/apr_suite-1.4.5.576669-windows-576669.tar.bz2</string>
             </map>
             <key>name</key>
             <string>windows</string>
@@ -88,16 +88,16 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>646dc3828d9c39fb1e77c4eec44ed739</string>
+              <string>ec24f5945faa8f13807b83eeaeb994f8</string>
               <key>url</key>
-              <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/80555/759709/apr_suite-1.4.5.558565-windows64-558565.tar.bz2</string>
+              <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/107592/938547/apr_suite-1.4.5.576669-windows64-576669.tar.bz2</string>
             </map>
             <key>name</key>
             <string>windows64</string>
           </map>
         </map>
         <key>version</key>
-        <string>1.4.5.558565</string>
+        <string>1.4.5.576669</string>
       </map>
       <key>boost</key>
       <map>
@@ -184,9 +184,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>ae90d19cdcddf539f6d0b41cab12f918</string>
+              <string>7b4aceaed511d44c4d1354b2162b59c7</string>
               <key>url</key>
-              <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/72773/702861/bugsplat-1.0.7.552580-darwin64-552580.tar.bz2</string>
+              <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/107398/936936/bugsplat-1.0.7.576560-darwin64-576560.tar.bz2</string>
             </map>
             <key>name</key>
             <string>darwin64</string>
@@ -196,9 +196,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>f5936eceb6a33ff0f1cc31996a40f29c</string>
+              <string>53918c7c74b943cdc0bb90caf9657a84</string>
               <key>url</key>
-              <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/72774/702905/bugsplat-3.6.0.8.552580-windows-552580.tar.bz2</string>
+              <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/107400/936949/bugsplat-4.0.3.0.576560-windows-576560.tar.bz2</string>
             </map>
             <key>name</key>
             <string>windows</string>
@@ -208,16 +208,16 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>9cd940754e53e0670030b3da5ba8f373</string>
+              <string>19d6a55db101f02e7eb531daf3e8cfd1</string>
               <key>url</key>
-              <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/72775/702906/bugsplat-3.6.0.8.552580-windows64-552580.tar.bz2</string>
+              <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/107401/936948/bugsplat-.576560-windows64-576560.tar.bz2</string>
             </map>
             <key>name</key>
             <string>windows64</string>
           </map>
         </map>
         <key>version</key>
-        <string>3.6.0.8.552580</string>
+        <string>4.0.3.0.576560</string>
       </map>
       <key>colladadom</key>
       <map>
@@ -602,9 +602,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>2c619c1bef969dc42b4f44a4651b314e</string>
+              <string>8de71c518c248d77f70f87ab5e9de732</string>
               <key>url</key>
-              <string>https://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/98369/869141/fmodstudio-2.02.06.570913-darwin64-570913.tar.bz2</string>
+              <string>https://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/105828/925920/fmodstudio-2.02.06.575716-darwin64-575716.tar.bz2</string>
             </map>
             <key>name</key>
             <string>darwin64</string>
@@ -626,9 +626,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>875ccd8c1feec8ff03438d453371044b</string>
+              <string>2eea946ee7a572b748cec0c623ade3ef</string>
               <key>url</key>
-              <string>https://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/98371/869153/fmodstudio-2.02.06.570913-windows-570913.tar.bz2</string>
+              <string>https://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/105830/925932/fmodstudio-2.02.06.575716-windows-575716.tar.bz2</string>
             </map>
             <key>name</key>
             <string>windows</string>
@@ -638,16 +638,16 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>5e402f4828741bce942e2ced318cd02a</string>
+              <string>483d6fd5d057b0a681bffef9b8b9d927</string>
               <key>url</key>
-              <string>https://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/98372/869154/fmodstudio-2.02.06.570913-windows64-570913.tar.bz2</string>
+              <string>https://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/105829/925931/fmodstudio-2.02.06.575716-windows64-575716.tar.bz2</string>
             </map>
             <key>name</key>
             <string>windows64</string>
           </map>
         </map>
         <key>version</key>
-        <string>2.02.06.570913</string>
+        <string>2.02.06.575716</string>
       </map>
       <key>fontconfig</key>
       <map>
@@ -1418,9 +1418,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>c1c9e32e21f3c34d91ed045b2ca91f24</string>
+              <string>7a0059748d0b8733f2f9ce434cf604b8</string>
               <key>url</key>
-              <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/87781/805801/libpng-1.6.8.563850-darwin64-563850.tar.bz2</string>
+              <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/107514/937867/libpng-1.6.38.576621-darwin64-576621.tar.bz2</string>
             </map>
             <key>name</key>
             <string>darwin64</string>
@@ -1442,9 +1442,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>642e9cf95c8ccd0eb34f6d7a40df585a</string>
+              <string>3112013186ad60b0fc270a398d4dd499</string>
               <key>url</key>
-              <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/87782/805831/libpng-1.6.8.563850-windows-563850.tar.bz2</string>
+              <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/107513/937823/libpng-1.6.38.576621-windows-576621.tar.bz2</string>
             </map>
             <key>name</key>
             <string>windows</string>
@@ -1454,16 +1454,16 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>ce46aa0f171d97626c4a3940347cecd7</string>
+              <string>7c6bfcdb0d6162587cdbc436f595dd02</string>
               <key>url</key>
-              <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/87780/805832/libpng-1.6.8.563850-windows64-563850.tar.bz2</string>
+              <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/107512/937822/libpng-1.6.38.576621-windows64-576621.tar.bz2</string>
             </map>
             <key>name</key>
             <string>windows64</string>
           </map>
         </map>
         <key>version</key>
-        <string>1.6.8.563850</string>
+        <string>1.6.38.576621</string>
       </map>
       <key>libuuid</key>
       <map>
@@ -2195,9 +2195,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>5abf2d9c0b250821c59cc60cd94fd8af</string>
+              <string>8114c6a7e499ea20d325db0de08ce30a</string>
               <key>url</key>
-              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/54840/510064/openjpeg-1.5.1.538970-darwin64-538970.tar.bz2</string>
+              <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/105469/923024/openjpeg-2.5.0.575496-darwin64-575496.tar.bz2</string>
             </map>
             <key>name</key>
             <string>darwin64</string>
@@ -2219,9 +2219,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>222a406ecb4071a9cc9635353afa337e</string>
+              <string>edc9388870d951632a6d595792293e05</string>
               <key>url</key>
-              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/54977/511775/openjpeg-1.5.1.538970-windows-538970.tar.bz2</string>
+              <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/105472/923036/openjpeg-2.5.0.575496-windows-575496.tar.bz2</string>
             </map>
             <key>name</key>
             <string>windows</string>
@@ -2231,16 +2231,16 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>5b5c80807fa8161f3480be3d89fe9516</string>
+              <string>b95f0732f2388ebb0ddf33d4a30e0ff1</string>
               <key>url</key>
-              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/54974/511767/openjpeg-1.5.1.538970-windows64-538970.tar.bz2</string>
+              <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/105471/923037/openjpeg-2.5.0.575496-windows64-575496.tar.bz2</string>
             </map>
             <key>name</key>
             <string>windows64</string>
           </map>
         </map>
         <key>version</key>
-        <string>1.5.1.538970</string>
+        <string>2.5.0.575496</string>
       </map>
       <key>openssl</key>
       <map>
@@ -2671,9 +2671,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>1dda5fb3bb649b0ab5a93f22df7cb11e</string>
+              <string>2e8d817e7837dd6f4284b13fa3f5c15e</string>
               <key>url</key>
-              <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/96998/862110/viewer_manager-3.0.569958-darwin64-569958.tar.bz2</string>
+              <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/104765/917714/viewer_manager-3.0.575083-darwin64-575083.tar.bz2</string>
             </map>
             <key>name</key>
             <string>darwin64</string>
@@ -2683,9 +2683,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>30d1386d0a6883d898fc56757a789b8b</string>
+              <string>3efa80faaf537e39a77218cd6efa9409</string>
               <key>url</key>
-              <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/97002/862130/viewer_manager-3.0.569958-windows-569958.tar.bz2</string>
+              <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/104766/917721/viewer_manager-3.0.575083-windows-575083.tar.bz2</string>
             </map>
             <key>name</key>
             <string>windows</string>
@@ -2696,7 +2696,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
         <key>source_type</key>
         <string>hg</string>
         <key>version</key>
-        <string>3.0.569958</string>
+        <string>3.0.575083</string>
       </map>
       <key>vlc-bin</key>
       <map>
@@ -2888,7 +2888,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
     <key>package_description</key>
     <map>
       <key>canonical_repo</key>
-      <string>https://bitbucket.org/lindenlab/viewer</string>
+      <string>https://github.com/secondlife/viewer</string>
       <key>copyright</key>
       <string>Copyright (c) 2020, Linden Research, Inc.</string>
       <key>description</key>
diff --git a/doc/LGPL-license.txt b/doc/LGPL-license.txt
new file mode 100755
index 0000000000000000000000000000000000000000..4362b49151d7b34ef83b3067a8f9c9f877d72a0e
--- /dev/null
+++ b/doc/LGPL-license.txt
@@ -0,0 +1,502 @@
+                  GNU LESSER GENERAL PUBLIC LICENSE
+                       Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL.  It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+                            Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it.  You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+  When we speak of free software, we are referring to freedom of use,
+not price.  Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+  To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights.  These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  To protect each distributor, we want to make it very clear that
+there is no warranty for the free library.  Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+  Finally, software patents pose a constant threat to the existence of
+any free program.  We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder.  Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+  Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License.  This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License.  We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+  When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library.  The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom.  The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+  We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License.  It also provides other free software developers Less
+of an advantage over competing non-free programs.  These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries.  However, the Lesser license provides advantages in certain
+special circumstances.
+
+  For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard.  To achieve this, non-free programs must be
+allowed to use the library.  A more frequent case is that a free
+library does the same job as widely used non-free libraries.  In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+  In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software.  For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+  Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+                  GNU LESSER GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+  6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Use a suitable shared library mechanism for linking with the
+    Library.  A suitable mechanism is one that (1) uses at run time a
+    copy of the library already present on the user's computer system,
+    rather than copying library functions into the executable, and (2)
+    will operate properly with a modified version of the library, if
+    the user installs one, as long as the modified version is
+    interface-compatible with the version that the work was made with.
+
+    c) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    d) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    e) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+                            NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+                     END OF TERMS AND CONDITIONS
+
+           How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    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; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    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
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/doc/contributions.txt b/doc/contributions.txt
index 9368781c9a6cc27e81d9a2a3b4830da743a261eb..4c56ef86dcab421c8c8ea89967292b0a313e79b2 100755
--- a/doc/contributions.txt
+++ b/doc/contributions.txt
@@ -282,6 +282,8 @@ Beq Janus
 	SL-11300
 	SL-15709
 	SL-16021
+	SL-18592
+	SL-18637
 Beth Walcher
 Bezilon Kasei
 Biancaluce Robbiani
@@ -372,6 +374,7 @@ Charlie Sazaland
 Chaser Zaks
     BUG-225599
     BUG-227485
+    SL-16874
 Cherry Cheevers
 ChickyBabes Zuzu
 Chorazin Allen
@@ -1380,6 +1383,7 @@ Sovereign Engineer
     OPEN-343
 	SL-11625
     BUG-229030
+	SL-14696
 	SL-14705
 	SL-14706
 	SL-14707
@@ -1387,6 +1391,12 @@ Sovereign Engineer
 	SL-14732
 	SL-15096
 	SL-16127
+	SL-18249
+    SL-18394
+    SL-18412
+    SL-18497
+    SL-18525
+    SL-18534
 SpacedOut Frye
 	VWR-34
 	VWR-45
@@ -1649,6 +1659,8 @@ Zi Ree
 	VWR-25588
 	STORM-1790
 	STORM-1842
+	SL-18348
+	SL-18593
 Zipherius Turas
 	VWR-76
 	VWR-77
diff --git a/doc/sl-logo-dark.png b/doc/sl-logo-dark.png
new file mode 100644
index 0000000000000000000000000000000000000000..fa9ef32aea03eef5d740df05964bb60ddd8b05fd
Binary files /dev/null and b/doc/sl-logo-dark.png differ
diff --git a/indra/cmake/Copy3rdPartyLibs.cmake b/indra/cmake/Copy3rdPartyLibs.cmake
index ff705101ded51485ee120cc69017823871d68899..04b4202ca3de688a2af9aaea9f41c4da30d4d240 100644
--- a/indra/cmake/Copy3rdPartyLibs.cmake
+++ b/indra/cmake/Copy3rdPartyLibs.cmake
@@ -52,7 +52,7 @@ if(WINDOWS)
 
     set(release_src_dir "${ARCH_PREBUILT_DIRS_RELEASE}")
     set(release_files
-        openjpeg.dll
+        openjp2.dll
         libapr-1.dll
         libaprutil-1.dll
         libapriconv-1.dll
@@ -220,7 +220,7 @@ elseif(LINUX)
         libgobject-2.0.so
         libhunspell-1.3.so.0.0.0
         libopenal.so
-        libopenjpeg.so
+        libopenjp2.so
         libuuid.so.16
         libuuid.so.16.0.22
         libfontconfig.so.1.8.0
diff --git a/indra/cmake/FindOpenJPEG.cmake b/indra/cmake/FindOpenJPEG.cmake
index 949384eec4e1d0d9d245883d8d821710ed39c539..2d4353b54f991881e9620da269c8a86aee1433d5 100644
--- a/indra/cmake/FindOpenJPEG.cmake
+++ b/indra/cmake/FindOpenJPEG.cmake
@@ -14,9 +14,10 @@ FIND_PATH(OPENJPEG_INCLUDE_DIR openjpeg.h
 /usr/local/include
 /usr/include/openjpeg
 /usr/include
+include/openjpeg
 )
 
-SET(OPENJPEG_NAMES ${OPENJPEG_NAMES} openjpeg)
+SET(OPENJPEG_NAMES ${OPENJPEG_NAMES} openjp2)
 FIND_LIBRARY(OPENJPEG_LIBRARY
   NAMES ${OPENJPEG_NAMES}
   PATHS /usr/lib /usr/local/lib
diff --git a/indra/cmake/OpenJPEG.cmake b/indra/cmake/OpenJPEG.cmake
index bf0bde2ba7b85084765c2e8bde21a24fb090be75..a078c97cb8fd209fc88bc9ff739d2eb4cabb841a 100644
--- a/indra/cmake/OpenJPEG.cmake
+++ b/indra/cmake/OpenJPEG.cmake
@@ -8,15 +8,7 @@ if (USESYSTEMLIBS)
   include(FindOpenJPEG)
 else (USESYSTEMLIBS)
   use_prebuilt_binary(openjpeg)
-  
-  if(WINDOWS)
-    # Windows has differently named release and debug openjpeg(d) libs.
-    set(OPENJPEG_LIBRARIES 
-        debug openjpegd
-        optimized openjpeg)
-  else(WINDOWS)
-    set(OPENJPEG_LIBRARIES openjpeg)
-  endif(WINDOWS)
-  
-    set(OPENJPEG_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/openjpeg)
+
+  set(OPENJPEG_LIBRARIES openjp2)
+  set(OPENJPEG_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/openjpeg)
 endif (USESYSTEMLIBS)
diff --git a/indra/integration_tests/llui_libtest/CMakeLists.txt b/indra/integration_tests/llui_libtest/CMakeLists.txt
index d7706e73b24ed6033609482a852323aaf077b04b..3957ede77f01d49af6eabc3cd7d389c223c4d8d8 100644
--- a/indra/integration_tests/llui_libtest/CMakeLists.txt
+++ b/indra/integration_tests/llui_libtest/CMakeLists.txt
@@ -99,14 +99,14 @@ if (WINDOWS)
     # Copy over OpenJPEG.dll
     # *NOTE: On Windows with VS2005, only the first comment prints
     set(OPENJPEG_RELEASE
-        "${ARCH_PREBUILT_DIRS_RELEASE}/openjpeg.dll")
+        "${ARCH_PREBUILT_DIRS_RELEASE}/openjp2.dll")
     add_custom_command( TARGET llui_libtest POST_BUILD
         COMMAND ${CMAKE_COMMAND} -E copy_if_different 
             ${OPENJPEG_RELEASE} ${CMAKE_CURRENT_BINARY_DIR}
         COMMENT "Copying OpenJPEG DLLs to binary directory"
         )
     set(OPENJPEG_DEBUG
-        "${ARCH_PREBUILT_DIRS_DEBUG}/openjpegd.dll")
+        "${ARCH_PREBUILT_DIRS_DEBUG}/openjp2.dll")
     add_custom_command( TARGET llui_libtest POST_BUILD
         COMMAND ${CMAKE_COMMAND} -E copy_if_different 
             ${OPENJPEG_DEBUG} ${CMAKE_CURRENT_BINARY_DIR}
diff --git a/indra/llappearance/llavatarappearance.cpp b/indra/llappearance/llavatarappearance.cpp
index f0df3e147489ae16b7752ae5a6892dd3a8db2cd3..c1336fd612294865492dc811c1f5e91f593eb079 100644
--- a/indra/llappearance/llavatarappearance.cpp
+++ b/indra/llappearance/llavatarappearance.cpp
@@ -305,7 +305,12 @@ LLAvatarAppearance::~LLAvatarAppearance()
 		}
 	}
 
-	if (mRoot) mRoot->removeAllChildren();
+	if (mRoot) 
+	{
+		mRoot->removeAllChildren();
+		delete mRoot;
+		mRoot = nullptr;
+	}
 	mJointMap.clear();
 
 	clearSkeleton();
diff --git a/indra/llappearance/lllocaltextureobject.cpp b/indra/llappearance/lllocaltextureobject.cpp
index 3f564ec3de305f7f77d4f2ea607bc3187b5c137c..0481326e9e9d2d46b68f22148b416305ffdc8776 100644
--- a/indra/llappearance/lllocaltextureobject.cpp
+++ b/indra/llappearance/lllocaltextureobject.cpp
@@ -76,6 +76,7 @@ LLLocalTextureObject::LLLocalTextureObject(const LLLocalTextureObject& lto) :
 
 LLLocalTextureObject::~LLLocalTextureObject()
 {
+	delete_and_clear(mTexLayers);
 }
 
 LLGLTexture* LLLocalTextureObject::getImage() const
diff --git a/indra/llcharacter/llkeyframemotion.cpp b/indra/llcharacter/llkeyframemotion.cpp
index ebf7454a6154cd148b8d5a0e6de1cd8ab196bb6f..403d5bcf490b7611cf57379d9dadf2f91841270a 100644
--- a/indra/llcharacter/llkeyframemotion.cpp
+++ b/indra/llcharacter/llkeyframemotion.cpp
@@ -1229,7 +1229,7 @@ void LLKeyframeMotion::applyConstraint(JointConstraint* constraint, F32 time, U8
 BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, bool allow_invalid_joints)
 {
 	BOOL old_version = FALSE;
-	mJointMotionList = new LLKeyframeMotion::JointMotionList;
+	std::unique_ptr<LLKeyframeMotion::JointMotionList> joint_motion_list(new LLKeyframeMotion::JointMotionList);
 
 	//-------------------------------------------------------------------------
 	// get base priority
@@ -1272,16 +1272,16 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
                    << " for animation " << asset_id << LL_ENDL;
 		return FALSE;
 	}
-	mJointMotionList->mBasePriority = (LLJoint::JointPriority) temp_priority;
+	joint_motion_list->mBasePriority = (LLJoint::JointPriority) temp_priority;
 
-	if (mJointMotionList->mBasePriority >= LLJoint::ADDITIVE_PRIORITY)
+	if (joint_motion_list->mBasePriority >= LLJoint::ADDITIVE_PRIORITY)
 	{
-		mJointMotionList->mBasePriority = (LLJoint::JointPriority)((S32)LLJoint::ADDITIVE_PRIORITY-1);
-		mJointMotionList->mMaxPriority = mJointMotionList->mBasePriority;
+		joint_motion_list->mBasePriority = (LLJoint::JointPriority)((S32)LLJoint::ADDITIVE_PRIORITY-1);
+		joint_motion_list->mMaxPriority = joint_motion_list->mBasePriority;
 	}
-	else if (mJointMotionList->mBasePriority < LLJoint::USE_MOTION_PRIORITY)
+	else if (joint_motion_list->mBasePriority < LLJoint::USE_MOTION_PRIORITY)
 	{
-		LL_WARNS() << "bad animation base_priority " << mJointMotionList->mBasePriority
+		LL_WARNS() << "bad animation base_priority " << joint_motion_list->mBasePriority
                    << " for animation " << asset_id << LL_ENDL;
 		return FALSE;
 	}
@@ -1289,15 +1289,15 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
 	//-------------------------------------------------------------------------
 	// get duration
 	//-------------------------------------------------------------------------
-	if (!dp.unpackF32(mJointMotionList->mDuration, "duration"))
+	if (!dp.unpackF32(joint_motion_list->mDuration, "duration"))
 	{
 		LL_WARNS() << "can't read duration"
                    << " for animation " << asset_id << LL_ENDL;
 		return FALSE;
 	}
 	
-	if (mJointMotionList->mDuration > MAX_ANIM_DURATION ||
-	    !llfinite(mJointMotionList->mDuration))
+	if (joint_motion_list->mDuration > MAX_ANIM_DURATION ||
+	    !llfinite(joint_motion_list->mDuration))
 	{
 		LL_WARNS() << "invalid animation duration"
                    << " for animation " << asset_id << LL_ENDL;
@@ -1307,14 +1307,14 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
 	//-------------------------------------------------------------------------
 	// get emote (optional)
 	//-------------------------------------------------------------------------
-	if (!dp.unpackString(mJointMotionList->mEmoteName, "emote_name"))
+	if (!dp.unpackString(joint_motion_list->mEmoteName, "emote_name"))
 	{
 		LL_WARNS() << "can't read optional_emote_animation"
                    << " for animation " << asset_id << LL_ENDL;
 		return FALSE;
 	}
 
-	if(mJointMotionList->mEmoteName==mID.asString())
+	if(joint_motion_list->mEmoteName==mID.asString())
 	{
 		LL_WARNS() << "Malformed animation mEmoteName==mID"
                    << " for animation " << asset_id << LL_ENDL;
@@ -1324,23 +1324,23 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
 	//-------------------------------------------------------------------------
 	// get loop
 	//-------------------------------------------------------------------------
-	if (!dp.unpackF32(mJointMotionList->mLoopInPoint, "loop_in_point") ||
-	    !llfinite(mJointMotionList->mLoopInPoint))
+	if (!dp.unpackF32(joint_motion_list->mLoopInPoint, "loop_in_point") ||
+	    !llfinite(joint_motion_list->mLoopInPoint))
 	{
 		LL_WARNS() << "can't read loop point"
                    << " for animation " << asset_id << LL_ENDL;
 		return FALSE;
 	}
 
-	if (!dp.unpackF32(mJointMotionList->mLoopOutPoint, "loop_out_point") ||
-	    !llfinite(mJointMotionList->mLoopOutPoint))
+	if (!dp.unpackF32(joint_motion_list->mLoopOutPoint, "loop_out_point") ||
+	    !llfinite(joint_motion_list->mLoopOutPoint))
 	{
 		LL_WARNS() << "can't read loop point"
                    << " for animation " << asset_id << LL_ENDL;
 		return FALSE;
 	}
 
-	if (!dp.unpackS32(mJointMotionList->mLoop, "loop"))
+	if (!dp.unpackS32(joint_motion_list->mLoop, "loop"))
 	{
 		LL_WARNS() << "can't read loop"
                    << " for animation " << asset_id << LL_ENDL;
@@ -1353,22 +1353,22 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
 	if (female_land_anim == asset_id || formal_female_land_anim == asset_id)
 	{
 		LL_WARNS() << "Animation(" << asset_id << ") won't be looped." << LL_ENDL;
-		mJointMotionList->mLoop = FALSE;
+		joint_motion_list->mLoop = FALSE;
 	}
 
 	//-------------------------------------------------------------------------
 	// get easeIn and easeOut
 	//-------------------------------------------------------------------------
-	if (!dp.unpackF32(mJointMotionList->mEaseInDuration, "ease_in_duration") ||
-	    !llfinite(mJointMotionList->mEaseInDuration))
+	if (!dp.unpackF32(joint_motion_list->mEaseInDuration, "ease_in_duration") ||
+	    !llfinite(joint_motion_list->mEaseInDuration))
 	{
 		LL_WARNS() << "can't read easeIn"
                    << " for animation " << asset_id << LL_ENDL;
 		return FALSE;
 	}
 
-	if (!dp.unpackF32(mJointMotionList->mEaseOutDuration, "ease_out_duration") ||
-	    !llfinite(mJointMotionList->mEaseOutDuration))
+	if (!dp.unpackF32(joint_motion_list->mEaseOutDuration, "ease_out_duration") ||
+	    !llfinite(joint_motion_list->mEaseOutDuration))
 	{
 		LL_WARNS() << "can't read easeOut"
                    << " for animation " << asset_id << LL_ENDL;
@@ -1393,7 +1393,7 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
 		return FALSE;
 	}
 	
-	mJointMotionList->mHandPose = (LLHandMotion::eHandPose)word;
+	joint_motion_list->mHandPose = (LLHandMotion::eHandPose)word;
 
 	//-------------------------------------------------------------------------
 	// get number of joint motions
@@ -1419,8 +1419,8 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
 		return FALSE;
 	}
 
-	mJointMotionList->mJointMotionArray.clear();
-	mJointMotionList->mJointMotionArray.reserve(num_motions);
+	joint_motion_list->mJointMotionArray.clear();
+	joint_motion_list->mJointMotionArray.reserve(num_motions);
 	mJointStates.clear();
 	mJointStates.reserve(num_motions);
 
@@ -1431,7 +1431,7 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
 	for(U32 i=0; i<num_motions; ++i)
 	{
 		JointMotion* joint_motion = new JointMotion;		
-		mJointMotionList->mJointMotionArray.push_back(joint_motion);
+		joint_motion_list->mJointMotionArray.push_back(joint_motion);
 		
 		std::string joint_name;
 		if (!dp.unpackString(joint_name, "joint_name"))
@@ -1503,9 +1503,9 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
 		
 		joint_motion->mPriority = (LLJoint::JointPriority)joint_priority;
 		if (joint_priority != LLJoint::USE_MOTION_PRIORITY &&
-		    joint_priority > mJointMotionList->mMaxPriority)
+		    joint_priority > joint_motion_list->mMaxPriority)
 		{
-			mJointMotionList->mMaxPriority = (LLJoint::JointPriority)joint_priority;
+			joint_motion_list->mMaxPriority = (LLJoint::JointPriority)joint_priority;
 		}
 
 		joint_state->setPriority((LLJoint::JointPriority)joint_priority);
@@ -1556,9 +1556,9 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
 					return FALSE;
 				}
 
-				time = U16_to_F32(time_short, 0.f, mJointMotionList->mDuration);
+				time = U16_to_F32(time_short, 0.f, joint_motion_list->mDuration);
 				
-				if (time < 0 || time > mJointMotionList->mDuration)
+				if (time < 0 || time > joint_motion_list->mDuration)
 				{
 					LL_WARNS() << "invalid frame time"
                                << " for animation " << asset_id << LL_ENDL;
@@ -1571,38 +1571,57 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
 			LLVector3 rot_angles;
 			U16 x, y, z;
 
-			BOOL success = TRUE;
-
 			if (old_version)
 			{
-				success = dp.unpackVector3(rot_angles, "rot_angles") && rot_angles.isFinite();
+				if (!dp.unpackVector3(rot_angles, "rot_angles"))
+				{
+					LL_WARNS() << "can't read rot_angles in rotation key (" << k << ")" << LL_ENDL;
+					return FALSE;
+				}
+				if (!rot_angles.isFinite())
+				{
+					LL_WARNS() << "non-finite angle in rotation key (" << k << ")" << LL_ENDL;
+					return FALSE;
+				}
 
 				LLQuaternion::Order ro = StringToOrder("ZYX");
 				rot_key.mRotation = mayaQ(rot_angles.mV[VX], rot_angles.mV[VY], rot_angles.mV[VZ], ro);
 			}
 			else
 			{
-				success &= dp.unpackU16(x, "rot_angle_x");
-				success &= dp.unpackU16(y, "rot_angle_y");
-				success &= dp.unpackU16(z, "rot_angle_z");
+				if (!dp.unpackU16(x, "rot_angle_x"))
+				{
+					LL_WARNS() << "can't read rot_angle_x in rotation key (" << k << ")" << LL_ENDL;
+					return FALSE;
+				}
+				if (!dp.unpackU16(y, "rot_angle_y"))
+				{
+					LL_WARNS() << "can't read rot_angle_y in rotation key (" << k << ")" << LL_ENDL;
+					return FALSE;
+				}
+				if (!dp.unpackU16(z, "rot_angle_z"))
+				{
+					LL_WARNS() << "can't read rot_angle_z in rotation key (" << k << ")" << LL_ENDL;
+					return FALSE;
+				}
 
 				LLVector3 rot_vec;
 				rot_vec.mV[VX] = U16_to_F32(x, -1.f, 1.f);
 				rot_vec.mV[VY] = U16_to_F32(y, -1.f, 1.f);
 				rot_vec.mV[VZ] = U16_to_F32(z, -1.f, 1.f);
+
+				if(!rot_vec.isFinite())
+				{
+					LL_WARNS() << "non-finite angle in rotation key (" << k << ")"
+						<< " for animation " << asset_id << LL_ENDL;
+					return FALSE;
+				}				
 				rot_key.mRotation.unpackFromVector3(rot_vec);
 			}
 
-			if( !(rot_key.mRotation.isFinite()) )
-			{
-				LL_WARNS() << "non-finite angle in rotation key"
-                           << " for animation " << asset_id << LL_ENDL;
-				success = FALSE;
-			}
-			
-			if (!success)
+			if(!rot_key.mRotation.isFinite())
 			{
-				LL_WARNS() << "can't read rotation key (" << k << ")"
+				LL_WARNS() << "non-finite angle in rotation key (" << k << ")"
                            << " for animation " << asset_id << LL_ENDL;
 				return FALSE;
 			}
@@ -1655,14 +1674,16 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
 					return FALSE;
 				}
 
-				pos_key.mTime = U16_to_F32(time_short, 0.f, mJointMotionList->mDuration);
+				pos_key.mTime = U16_to_F32(time_short, 0.f, joint_motion_list->mDuration);
 			}
 
-			BOOL success = TRUE;
-
 			if (old_version)
 			{
-				success = dp.unpackVector3(pos_key.mPosition, "pos");
+				if (!dp.unpackVector3(pos_key.mPosition, "pos"))
+				{
+					LL_WARNS() << "can't read pos in position key (" << k << ")" << LL_ENDL;
+					return FALSE;
+				}
                 
                 //MAINT-6162
                 pos_key.mPosition.mV[VX] = llclamp( pos_key.mPosition.mV[VX], -LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET);
@@ -1674,25 +1695,30 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
 			{
 				U16 x, y, z;
 
-				success &= dp.unpackU16(x, "pos_x");
-				success &= dp.unpackU16(y, "pos_y");
-				success &= dp.unpackU16(z, "pos_z");
+				if (!dp.unpackU16(x, "pos_x"))
+				{
+					LL_WARNS() << "can't read pos_x in position key (" << k << ")" << LL_ENDL;
+					return FALSE;
+				}
+				if (!dp.unpackU16(y, "pos_y"))
+				{
+					LL_WARNS() << "can't read pos_y in position key (" << k << ")" << LL_ENDL;
+					return FALSE;
+				}
+				if (!dp.unpackU16(z, "pos_z"))
+				{
+					LL_WARNS() << "can't read pos_z in position key (" << k << ")" << LL_ENDL;
+					return FALSE;
+				}
 
 				pos_key.mPosition.mV[VX] = U16_to_F32(x, -LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET);
 				pos_key.mPosition.mV[VY] = U16_to_F32(y, -LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET);
 				pos_key.mPosition.mV[VZ] = U16_to_F32(z, -LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET);
 			}
 			
-			if( !(pos_key.mPosition.isFinite()) )
+			if(!pos_key.mPosition.isFinite())
 			{
 				LL_WARNS() << "non-finite position in key"
-                           << " for animation " << asset_id << LL_ENDL;
-				success = FALSE;
-			}
-			
-			if (!success)
-			{
-				LL_WARNS() << "can't read position key (" << k << ")"
                            << " for animation " << asset_id << LL_ENDL;
 				return FALSE;
 			}
@@ -1701,7 +1727,7 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
 
 			if (is_pelvis)
 			{
-				mJointMotionList->mPelvisBBox.addPoint(pos_key.mPosition);
+				joint_motion_list->mPelvisBBox.addPoint(pos_key.mPosition);
 			}
 		}
 
@@ -1733,23 +1759,21 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
 		for(S32 i = 0; i < num_constraints; ++i)
 		{
 			// read in constraint data
-			JointConstraintSharedData* constraintp = new JointConstraintSharedData;
+			std::unique_ptr<JointConstraintSharedData> constraintp(new JointConstraintSharedData);
 			U8 byte = 0;
 
 			if (!dp.unpackU8(byte, "chain_length"))
 			{
 				LL_WARNS() << "can't read constraint chain length"
                            << " for animation " << asset_id << LL_ENDL;
-				delete constraintp;
 				return FALSE;
 			}
 			constraintp->mChainLength = (S32) byte;
 
-			if((U32)constraintp->mChainLength > mJointMotionList->getNumJointMotions())
+			if((U32)constraintp->mChainLength > joint_motion_list->getNumJointMotions())
 			{
 				LL_WARNS() << "invalid constraint chain length"
                            << " for animation " << asset_id << LL_ENDL;
-				delete constraintp;
 				return FALSE;
 			}
 
@@ -1757,7 +1781,6 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
 			{
 				LL_WARNS() << "can't read constraint type"
                            << " for animation " << asset_id << LL_ENDL;
-				delete constraintp;
 				return FALSE;
 			}
 			
@@ -1765,7 +1788,6 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
 			{
 				LL_WARNS() << "invalid constraint type"
                            << " for animation " << asset_id << LL_ENDL;
-				delete constraintp;
 				return FALSE;
 			}
 			constraintp->mConstraintType = (EConstraintType)byte;
@@ -1776,7 +1798,6 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
 			{
 				LL_WARNS() << "can't read source volume name"
                            << " for animation " << asset_id << LL_ENDL;
-				delete constraintp;
 				return FALSE;
 			}
 
@@ -1787,7 +1808,6 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
 			{
 				LL_WARNS() << "not a valid source constraint volume " << str
 						   << " for animation " << asset_id << LL_ENDL;
-				delete constraintp;
 				return FALSE;
 			}
 
@@ -1795,7 +1815,6 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
 			{
 				LL_WARNS() << "can't read constraint source offset"
                            << " for animation " << asset_id << LL_ENDL;
-				delete constraintp;
 				return FALSE;
 			}
 			
@@ -1803,7 +1822,6 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
 			{
 				LL_WARNS() << "non-finite constraint source offset"
                            << " for animation " << asset_id << LL_ENDL;
-				delete constraintp;
 				return FALSE;
 			}
 			
@@ -1811,7 +1829,6 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
 			{
 				LL_WARNS() << "can't read target volume name"
                            << " for animation " << asset_id << LL_ENDL;
-				delete constraintp;
 				return FALSE;
 			}
 
@@ -1830,7 +1847,6 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
 				{
 					LL_WARNS() << "not a valid target constraint volume " << str
 							   << " for animation " << asset_id << LL_ENDL;
-					delete constraintp;
 					return FALSE;
 				}
 			}
@@ -1839,7 +1855,6 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
 			{
 				LL_WARNS() << "can't read constraint target offset"
                            << " for animation " << asset_id << LL_ENDL;
-				delete constraintp;
 				return FALSE;
 			}
 
@@ -1847,7 +1862,6 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
 			{
 				LL_WARNS() << "non-finite constraint target offset"
                            << " for animation " << asset_id << LL_ENDL;
-				delete constraintp;
 				return FALSE;
 			}
 			
@@ -1855,7 +1869,6 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
 			{
 				LL_WARNS() << "can't read constraint target direction"
                            << " for animation " << asset_id << LL_ENDL;
-				delete constraintp;
 				return FALSE;
 			}
 
@@ -1863,7 +1876,6 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
 			{
 				LL_WARNS() << "non-finite constraint target direction"
                            << " for animation " << asset_id << LL_ENDL;
-				delete constraintp;
 				return FALSE;
 			}
 
@@ -1877,7 +1889,6 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
 			{
 				LL_WARNS() << "can't read constraint ease in start time"
                            << " for animation " << asset_id << LL_ENDL;
-				delete constraintp;
 				return FALSE;
 			}
 
@@ -1885,7 +1896,6 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
 			{
 				LL_WARNS() << "can't read constraint ease in stop time"
                            << " for animation " << asset_id << LL_ENDL;
-				delete constraintp;
 				return FALSE;
 			}
 
@@ -1893,7 +1903,6 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
 			{
 				LL_WARNS() << "can't read constraint ease out start time"
                            << " for animation " << asset_id << LL_ENDL;
-				delete constraintp;
 				return FALSE;
 			}
 
@@ -1901,33 +1910,31 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
 			{
 				LL_WARNS() << "can't read constraint ease out stop time"
                            << " for animation " << asset_id << LL_ENDL;
-				delete constraintp;
 				return FALSE;
 			}
 
-			mJointMotionList->mConstraints.push_front(constraintp);
-
-			constraintp->mJointStateIndices = new S32[constraintp->mChainLength + 1]; // note: mChainLength is size-limited - comes from a byte
-			
 			LLJoint* joint = mCharacter->findCollisionVolume(constraintp->mSourceConstraintVolume);
 			// get joint to which this collision volume is attached
 			if (!joint)
 			{
 				return FALSE;
 			}
+
+			constraintp->mJointStateIndices = new S32[constraintp->mChainLength + 1]; // note: mChainLength is size-limited - comes from a byte
+
 			for (S32 i = 0; i < constraintp->mChainLength + 1; i++)
 			{
 				LLJoint* parent = joint->getParent();
 				if (!parent)
 				{
 					LL_WARNS() << "Joint with no parent: " << joint->getName()
-                               << " Emote: " << mJointMotionList->mEmoteName
+                               << " Emote: " << joint_motion_list->mEmoteName
                                << " for animation " << asset_id << LL_ENDL;
 					return FALSE;
 				}
 				joint = parent;
 				constraintp->mJointStateIndices[i] = -1;
-				for (U32 j = 0; j < mJointMotionList->getNumJointMotions(); j++)
+				for (U32 j = 0; j < joint_motion_list->getNumJointMotions(); j++)
 				{
 					LLJoint* constraint_joint = getJoint(j);
 					
@@ -1948,14 +1955,16 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
 				{
 					LL_WARNS() << "No joint index for constraint " << i
                                << " for animation " << asset_id << LL_ENDL;
-					delete constraintp;
 					return FALSE;
 				}
 			}
+
+			joint_motion_list->mConstraints.push_front(constraintp.release());
 		}
 	}
 
 	// *FIX: support cleanup of old keyframe data
+    mJointMotionList = joint_motion_list.release(); // release from unique_ptr to member;
 	LLKeyframeDataCache::addKeyframeData(getID(),  mJointMotionList);
 	mAssetStatus = ASSET_LOADED;
 
diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index df65828d02ff6ffad43b8601e240f8fd6324f08f..108149b5f730295603c8a9525db6f65f25111a36 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -108,7 +108,6 @@ set(llcommon_SOURCE_FILES
     llsys.cpp
     lltempredirect.cpp
     llthread.cpp
-    llthreadlocalstorage.cpp
     llthreadsafequeue.cpp
     lltimer.cpp
     lltrace.cpp
diff --git a/indra/llcommon/llapr.cpp b/indra/llcommon/llapr.cpp
index db947658719b2aa453310bbb5700e563ad8621be..435531f86f37d088dd6129d63970649e368c150d 100644
--- a/indra/llcommon/llapr.cpp
+++ b/indra/llcommon/llapr.cpp
@@ -30,7 +30,6 @@
 #include "llapr.h"
 #include "llmutex.h"
 #include "apr_dso.h"
-#include "llthreadlocalstorage.h"
 
 apr_pool_t *gAPRPoolp = NULL; // Global APR memory pool
 LLVolatileAPRPool *LLAPRFile::sAPRFilePoolp = NULL ; //global volatile APR memory pool.
@@ -54,7 +53,6 @@ void ll_init_apr()
 		LLAPRFile::sAPRFilePoolp = new LLVolatileAPRPool(FALSE) ;
 	}
 
-	LLThreadLocalPointerBase::initAllThreadLocalStorage();
 	gAPRInitialized = true;
 }
 
@@ -70,8 +68,6 @@ void ll_cleanup_apr()
 
 	LL_DEBUGS("APR") << "Cleaning up APR" << LL_ENDL;
 
-	LLThreadLocalPointerBase::destroyAllThreadLocalStorage();
-
 	if (gAPRPoolp)
 	{
 		apr_pool_destroy(gAPRPoolp);
diff --git a/indra/llcommon/llcoros.cpp b/indra/llcommon/llcoros.cpp
index 14bfb98629d2e79bcd4b64a3ee0363489360e73d..70d8dfc8b932565668b5617ae4f51559660fadf5 100644
--- a/indra/llcommon/llcoros.cpp
+++ b/indra/llcommon/llcoros.cpp
@@ -288,25 +288,15 @@ std::string LLCoros::launch(const std::string& prefix, const callable_t& callabl
     return name;
 }
 
+namespace
+{
+
 #if LL_WINDOWS
 
 static const U32 STATUS_MSC_EXCEPTION = 0xE06D7363; // compiler specific
 
-U32 cpp_exception_filter(U32 code, struct _EXCEPTION_POINTERS *exception_infop, const std::string& name)
+U32 exception_filter(U32 code, struct _EXCEPTION_POINTERS *exception_infop)
 {
-    // C++ exceptions were logged in toplevelTryWrapper, but not SEH
-    // log SEH exceptions here, to make sure it gets into bugsplat's 
-    // report and because __try won't allow std::string operations
-    if (code != STATUS_MSC_EXCEPTION)
-    {
-        LL_WARNS() << "SEH crash in " << name << ", code: " << code << LL_ENDL;
-    }
-    // Handle bugsplat here, since GetExceptionInformation() can only be
-    // called from within filter for __except(filter), not from __except's {}
-    // Bugsplat should get all exceptions, C++ and SEH
-    LLApp::instance()->reportCrashToBugsplat(exception_infop);
-
-    // Only convert non C++ exceptions.
     if (code == STATUS_MSC_EXCEPTION)
     {
         // C++ exception, go on
@@ -319,28 +309,38 @@ U32 cpp_exception_filter(U32 code, struct _EXCEPTION_POINTERS *exception_infop,
     }
 }
 
-void LLCoros::sehHandle(const std::string& name, const LLCoros::callable_t& callable)
+void sehandle(const LLCoros::callable_t& callable)
 {
     __try
     {
-        LLCoros::toplevelTryWrapper(name, callable);
+        callable();
     }
-    __except (cpp_exception_filter(GetExceptionCode(), GetExceptionInformation(), name))
+    __except (exception_filter(GetExceptionCode(), GetExceptionInformation()))
     {
-        // convert to C++ styled exception for handlers other than bugsplat
+        // convert to C++ styled exception
         // Note: it might be better to use _se_set_translator
         // if you want exception to inherit full callstack
-        //
-        // in case of bugsplat this will get to exceptionTerminateHandler and
-        // looks like fiber will terminate application after that
         char integer_string[512];
-        sprintf(integer_string, "SEH crash in %s, code: %lu\n", name.c_str(), GetExceptionCode());
+        sprintf(integer_string, "SEH, code: %lu\n", GetExceptionCode());
         throw std::exception(integer_string);
     }
 }
-#endif
 
-void LLCoros::toplevelTryWrapper(const std::string& name, const callable_t& callable)
+#else  // ! LL_WINDOWS
+
+inline void sehandle(const LLCoros::callable_t& callable)
+{
+    callable();
+}
+
+#endif // ! LL_WINDOWS
+
+} // anonymous namespace
+
+// Top-level wrapper around caller's coroutine callable.
+// Normally we like to pass strings and such by const reference -- but in this
+// case, we WANT to copy both the name and the callable to our local stack!
+void LLCoros::toplevel(std::string name, callable_t callable)
 {
     // keep the CoroData on this top-level function's stack frame
     CoroData corodata(name);
@@ -350,12 +350,12 @@ void LLCoros::toplevelTryWrapper(const std::string& name, const callable_t& call
     // run the code the caller actually wants in the coroutine
     try
     {
-        callable();
+        sehandle(callable);
     }
     catch (const Stop& exc)
     {
         LL_INFOS("LLCoros") << "coroutine " << name << " terminating because "
-            << exc.what() << LL_ENDL;
+                            << exc.what() << LL_ENDL;
     }
     catch (const LLContinueError&)
     {
@@ -366,36 +366,14 @@ void LLCoros::toplevelTryWrapper(const std::string& name, const callable_t& call
     }
     catch (...)
     {
-#if LL_WINDOWS
-        // Any OTHER kind of uncaught exception will cause the viewer to
-        // crash, SEH handling should catch it and report to bugsplat.
-        LOG_UNHANDLED_EXCEPTION(STRINGIZE("coroutine " << name));
-        // to not modify callstack
-        throw;
-#else
         // Stash any OTHER kind of uncaught exception in the rethrow() queue
         // to be rethrown by the main fiber.
         LL_WARNS("LLCoros") << "Capturing uncaught exception in coroutine "
                             << name << LL_ENDL;
         LLCoros::instance().saveException(name, std::current_exception());
-#endif
     }
 }
 
-// Top-level wrapper around caller's coroutine callable.
-// Normally we like to pass strings and such by const reference -- but in this
-// case, we WANT to copy both the name and the callable to our local stack!
-void LLCoros::toplevel(std::string name, callable_t callable)
-{
-#if LL_WINDOWS
-    // Because SEH can's have unwinding, need to call a wrapper
-    // 'try' is inside SEH handling to not catch LLContinue
-    sehHandle(name, callable);
-#else
-    toplevelTryWrapper(name, callable);
-#endif
-}
-
 //static
 void LLCoros::checkStop()
 {
diff --git a/indra/llcommon/llcoros.h b/indra/llcommon/llcoros.h
index dbff921f167eb5f69262de816911c73e7c9e3845..966ce032965d6eb284cdfcfafd1d4dae3bf47949 100644
--- a/indra/llcommon/llcoros.h
+++ b/indra/llcommon/llcoros.h
@@ -307,11 +307,7 @@ class LL_COMMON_API LLCoros: public LLSingleton<LLCoros>
 
 private:
     std::string generateDistinctName(const std::string& prefix) const;
-    void toplevelTryWrapper(const std::string& name, const callable_t& callable);
-#if LL_WINDOWS
-    void sehHandle(const std::string& name, const callable_t& callable); // calls toplevelTryWrapper
-#endif
-    void toplevel(std::string name, callable_t callable); // calls sehHandle or toplevelTryWrapper
+    void toplevel(std::string name, callable_t callable);
     struct CoroData;
     static CoroData& get_CoroData(const std::string& caller);
     void saveException(const std::string& name, std::exception_ptr exc);
diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp
index 519426e9d180c88cc1300cb5e7f10d9ef02332f9..f9eda3cd4ebf26ff121bd40554d6f7465472f43e 100644
--- a/indra/llcommon/llerror.cpp
+++ b/indra/llcommon/llerror.cpp
@@ -943,7 +943,7 @@ namespace LLError
             for (a = sets.beginArray(), end = sets.endArray(); a != end; ++a)
             {
                 const LLSD& entry = *a;
-                if (entry.isMap() && !entry.emptyMap())
+                if (entry.isMap() && entry.size() != 0)
                 {
                     ELevel level = decodeLevel(entry["level"]);
 
diff --git a/indra/llcommon/llsdserialize.cpp b/indra/llcommon/llsdserialize.cpp
index af57f4ac5ec212c97ad3477cb9ed15572f0e6a48..b7e316da1002db395cdc56ba1459a53bc072bdc9 100644
--- a/indra/llcommon/llsdserialize.cpp
+++ b/indra/llcommon/llsdserialize.cpp
@@ -34,6 +34,9 @@
 #include <iostream>
 #include "apr_base64.h"
 
+#include <boost/iostreams/device/array.hpp>
+#include <boost/iostreams/stream.hpp>
+
 #ifdef LL_USESYSTEMLIBS
 # include <zlib.h>
 #else
@@ -2128,7 +2131,9 @@ std::string zip_llsd(LLSD& data)
 		{ //copy result into output
 			if (strm.avail_out >= CHUNK)
 			{
-				free(output);
+				deflateEnd(&strm);
+				if(output)
+					free(output);
 				LL_WARNS() << "Failed to compress LLSD block." << LL_ENDL;
 				return std::string();
 			}
@@ -2151,7 +2156,9 @@ std::string zip_llsd(LLSD& data)
 		}
 		else 
 		{
-			free(output);
+			deflateEnd(&strm);
+			if(output)
+				free(output);
 			LL_WARNS() << "Failed to compress LLSD block." << LL_ENDL;
 			return std::string();
 		}
@@ -2162,7 +2169,8 @@ std::string zip_llsd(LLSD& data)
 
 	std::string result((char*) output, size);
 	deflateEnd(&strm);
-	free(output);
+	if(output)
+		free(output);
 
 	return result;
 }
@@ -2171,54 +2179,67 @@ std::string zip_llsd(LLSD& data)
 // not very efficient -- creats a copy of decompressed LLSD block in memory
 // and deserializes from that copy using LLSDSerialize
 LLUZipHelper::EZipRresult LLUZipHelper::unzip_llsd(LLSD& data, std::istream& is, S32 size)
+{
+	std::unique_ptr<U8[]> in = std::unique_ptr<U8[]>(new(std::nothrow) U8[size]);
+	if (!in)
+	{
+		return ZR_MEM_ERROR;
+	}
+	is.read((char*) in.get(), size); 
+
+	return unzip_llsd(data, in.get(), size);
+}
+
+LLUZipHelper::EZipRresult LLUZipHelper::unzip_llsd(LLSD& data, const U8* in, S32 size)
 {
 	U8* result = NULL;
-	llssize cur_size = 0;
+	U32 cur_size = 0;
 	z_stream strm;
 		
-	const U32 CHUNK = 65536;
+	constexpr U32 CHUNK = 1024 * 512;
 
-	U8 *in = new(std::nothrow) U8[size];
-	if (!in)
+	static thread_local std::unique_ptr<U8[]> out;
+	if (!out)
 	{
-		return ZR_MEM_ERROR;
+		out = std::unique_ptr<U8[]>(new(std::nothrow) U8[CHUNK]);
 	}
-	is.read((char*) in, size); 
-
-	U8 out[CHUNK];
 		
 	strm.zalloc = Z_NULL;
 	strm.zfree = Z_NULL;
 	strm.opaque = Z_NULL;
 	strm.avail_in = size;
-	strm.next_in = in;
+	strm.next_in = const_cast<U8*>(in);
 
 	S32 ret = inflateInit(&strm);
 	
 	do
 	{
 		strm.avail_out = CHUNK;
-		strm.next_out = out;
+		strm.next_out = out.get();
 		ret = inflate(&strm, Z_NO_FLUSH);
-		if (ret == Z_STREAM_ERROR)
+		switch (ret)
+		{
+		case Z_NEED_DICT:
+		case Z_DATA_ERROR:
 		{
 			inflateEnd(&strm);
 			free(result);
-			delete [] in;
 			return ZR_DATA_ERROR;
 		}
-		
-		switch (ret)
+		case Z_STREAM_ERROR:
+		case Z_BUF_ERROR:
 		{
-		case Z_NEED_DICT:
-			ret = Z_DATA_ERROR;
-		case Z_DATA_ERROR:
+			inflateEnd(&strm);
+			free(result);
+			return ZR_BUFFER_ERROR;
+		}
+
 		case Z_MEM_ERROR:
+		{
 			inflateEnd(&strm);
 			free(result);
-			delete [] in;
 			return ZR_MEM_ERROR;
-			break;
+		}
 		}
 
 		U32 have = CHUNK-strm.avail_out;
@@ -2231,17 +2252,15 @@ LLUZipHelper::EZipRresult LLUZipHelper::unzip_llsd(LLSD& data, std::istream& is,
 			{
 				free(result);
 			}
-			delete[] in;
 			return ZR_MEM_ERROR;
 		}
 		result = new_result;
-		memcpy(result+cur_size, out, have);
+		memcpy(result+cur_size, out.get(), have);
 		cur_size += have;
 
-	} while (ret == Z_OK);
+	} while (ret == Z_OK && ret != Z_STREAM_END);
 
 	inflateEnd(&strm);
-	delete [] in;
 
 	if (ret != Z_STREAM_END)
 	{
@@ -2251,37 +2270,11 @@ LLUZipHelper::EZipRresult LLUZipHelper::unzip_llsd(LLSD& data, std::istream& is,
 
 	//result now points to the decompressed LLSD block
 	{
-		std::istringstream istr;
-		// Since we are using this for meshes, data we are dealing with tend to be large.
-		// So string can potentially fail to allocate, make sure this won't cause problems
-		try
-		{
-			std::string res_str((char*)result, cur_size);
+		char* result_ptr = strip_deprecated_header((char*)result, cur_size);
 
-			std::string deprecated_header("<? LLSD/Binary ?>");
-
-			if (res_str.substr(0, deprecated_header.size()) == deprecated_header)
-			{
-				res_str = res_str.substr(deprecated_header.size() + 1, cur_size);
-			}
-			cur_size = res_str.size();
-
-			istr.str(res_str);
-		}
-#ifdef LL_WINDOWS
-		catch (std::length_error)
-		{
-			free(result);
-			return ZR_SIZE_ERROR;
-		}
-#endif
-		catch (std::bad_alloc&)
-		{
-			free(result);
-			return ZR_MEM_ERROR;
-		}
-
-		if (!LLSDSerialize::fromBinary(data, istr, cur_size, UNZIP_LLSD_MAX_DEPTH))
+		boost::iostreams::stream<boost::iostreams::array_source> istrm(result_ptr, cur_size);
+		
+		if (!LLSDSerialize::fromBinary(data, istrm, cur_size, UNZIP_LLSD_MAX_DEPTH))
 		{
 			free(result);
 			return ZR_PARSE_ERROR;
@@ -2395,4 +2388,22 @@ U8* unzip_llsdNavMesh( bool& valid, size_t& outsize, std::istream& is, S32 size
 	return result;
 }
 
+char* strip_deprecated_header(char* in, U32& cur_size, U32* header_size)
+{
+	const char* deprecated_header = "<? LLSD/Binary ?>";
+	constexpr size_t deprecated_header_size = 17;
+
+	if (cur_size > deprecated_header_size
+		&& memcmp(in, deprecated_header, deprecated_header_size) == 0)
+	{
+		in = in + deprecated_header_size;
+		cur_size = cur_size - deprecated_header_size;
+		if (header_size)
+		{
+			*header_size = deprecated_header_size + 1;
+		}
+	}
+
+	return in;
+}
 
diff --git a/indra/llcommon/llsdserialize.h b/indra/llcommon/llsdserialize.h
index bd5ef668c0a8c80f284e21bd8d2015772154b4dc..cf6c1ab73a9903125f52c52baf70f4f8f5cf0b92 100644
--- a/indra/llcommon/llsdserialize.h
+++ b/indra/llcommon/llsdserialize.h
@@ -858,14 +858,20 @@ class LL_COMMON_API LLUZipHelper : public LLRefCount
         ZR_SIZE_ERROR,
         ZR_DATA_ERROR,
         ZR_PARSE_ERROR,
+		ZR_BUFFER_ERROR,
+		ZR_VERSION_ERROR
     } EZipRresult;
     // return OK or reason for failure
     static EZipRresult unzip_llsd(LLSD& data, std::istream& is, S32 size);
+	static EZipRresult unzip_llsd(LLSD& data, const U8* in, S32 size);
 };
 
 //dirty little zip functions -- yell at davep
 LL_COMMON_API std::string zip_llsd(LLSD& data);
 
 
-LL_COMMON_API U8* unzip_llsdNavMesh( bool& valid, size_t& outsize,std::istream& is, S32 size);
+LL_COMMON_API U8* unzip_llsdNavMesh( bool& valid, unsigned int& outsize,std::istream& is, S32 size);
+
+// returns a pointer to the array or past the array if the deprecated header exists
+LL_COMMON_API char* strip_deprecated_header(char* in, U32& cur_size, U32* header_size = nullptr);
 #endif // LL_LLSDSERIALIZE_H
diff --git a/indra/llcommon/llthreadlocalstorage.cpp b/indra/llcommon/llthreadlocalstorage.cpp
deleted file mode 100644
index d8a063e8d53551c06cfc0f55b101bdd30d3c37a1..0000000000000000000000000000000000000000
--- a/indra/llcommon/llthreadlocalstorage.cpp
+++ /dev/null
@@ -1,115 +0,0 @@
-/** 
- * @file llthreadlocalstorage.cpp
- * @author Richard
- * @date 2013-1-11
- * @brief implementation of thread local storage utility classes
- *
- * $LicenseInfo:firstyear=2013&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-#include "llthreadlocalstorage.h"
-#include "llapr.h"
-
-//
-//LLThreadLocalPointerBase
-//
-bool LLThreadLocalPointerBase::sInitialized = false;
-
-void LLThreadLocalPointerBase::set( void* value )
-{
-	llassert(sInitialized && mThreadKey);
-
-	apr_status_t result = apr_threadkey_private_set((void*)value, mThreadKey);
-	if (result != APR_SUCCESS)
-	{
-		ll_apr_warn_status(result);
-		LL_ERRS() << "Failed to set thread local data" << LL_ENDL;
-	}
-}
-
-void* LLThreadLocalPointerBase::get() const
-{
-	// llassert(sInitialized);
-	void* ptr;
-	apr_status_t result =
-		apr_threadkey_private_get(&ptr, mThreadKey);
-	if (result != APR_SUCCESS)
-	{
-		ll_apr_warn_status(result);
-		LL_ERRS() << "Failed to get thread local data" << LL_ENDL;
-	}
-	return ptr;
-}
-
-
-void LLThreadLocalPointerBase::initStorage( )
-{
-	apr_status_t result = apr_threadkey_private_create(&mThreadKey, NULL, gAPRPoolp);
-	if (result != APR_SUCCESS)
-	{
-		ll_apr_warn_status(result);
-		LL_ERRS() << "Failed to allocate thread local data" << LL_ENDL;
-	}
-}
-
-void LLThreadLocalPointerBase::destroyStorage()
-{
-	if (sInitialized)
-	{
-		if (mThreadKey)
-		{
-			apr_status_t result = apr_threadkey_private_delete(mThreadKey);
-			if (result != APR_SUCCESS)
-			{
-				ll_apr_warn_status(result);
-				LL_ERRS() << "Failed to delete thread local data" << LL_ENDL;
-			}
-		}
-	}
-}
-
-//static
-void LLThreadLocalPointerBase::initAllThreadLocalStorage()
-{
-	if (!sInitialized)
-	{
-		for (auto& base : instance_snapshot())
-		{
-			base.initStorage();
-		}
-		sInitialized = true;
-	}
-}
-
-//static
-void LLThreadLocalPointerBase::destroyAllThreadLocalStorage()
-{
-	if (sInitialized)
-	{
-		//for (auto& base : instance_snapshot())
-		//{
-		//	base.destroyStorage();
-		//}
-		sInitialized = false;
-	}
-}
diff --git a/indra/llcommon/llthreadlocalstorage.h b/indra/llcommon/llthreadlocalstorage.h
index 3b5786023f45fe9b8b36423da9fbfbf36869bac0..bdd28ec8653ee92feda114f991e04b118833b561 100644
--- a/indra/llcommon/llthreadlocalstorage.h
+++ b/indra/llcommon/llthreadlocalstorage.h
@@ -30,100 +30,6 @@
 
 #include "llinstancetracker.h"
 
-class LLThreadLocalPointerBase : public LLInstanceTracker<LLThreadLocalPointerBase>
-{
-public:
-	LLThreadLocalPointerBase()
-	:	mThreadKey(NULL)
-	{
-		if (sInitialized)
-		{
-			initStorage();
-		}
-	}
-
-	LLThreadLocalPointerBase( const LLThreadLocalPointerBase& other)
-	:	mThreadKey(NULL)
-	{
-		if (sInitialized)
-		{
-			initStorage();
-		}
-	}
-
-	~LLThreadLocalPointerBase()
-	{
-		destroyStorage();
-	}
-
-	static void initAllThreadLocalStorage();
-	static void destroyAllThreadLocalStorage();
-
-protected:
-	void set(void* value);
-
-	void* get() const;
-
-	void initStorage();
-	void destroyStorage();
-
-protected:
-	struct apr_threadkey_t*	mThreadKey;
-	static bool				sInitialized;
-};
-
-template <typename T>
-class LLThreadLocalPointer : public LLThreadLocalPointerBase
-{
-public:
-
-	LLThreadLocalPointer()
-	{}
-
-	explicit LLThreadLocalPointer(T* value)
-	{
-		set(value);
-	}
-
-
-	LLThreadLocalPointer(const LLThreadLocalPointer<T>& other)
-	:	LLThreadLocalPointerBase(other)
-	{
-		set(other.get());		
-	}
-
-	LL_FORCE_INLINE T* get() const
-	{
-		return (T*)LLThreadLocalPointerBase::get();
-	}
-
-	T* operator -> () const
-	{
-		return (T*)get();
-	}
-
-	T& operator*() const
-	{
-		return *(T*)get();
-	}
-
-	LLThreadLocalPointer<T>& operator = (T* value)
-	{
-		set((void*)value);
-		return *this;
-	}
-
-	bool operator ==(const T* other) const
-	{
-		if (!sInitialized) return false;
-		return get() == other;
-	}
-
-	bool isNull() const { return !sInitialized || get() == NULL; }
-
-	bool notNull() const { return sInitialized && get() != NULL; }
-};
-
 template<typename DERIVED_TYPE>
 class LLThreadLocalSingletonPointer
 {
@@ -139,10 +45,10 @@ class LLThreadLocalSingletonPointer
 	}
 
 private:
-	static LL_THREAD_LOCAL DERIVED_TYPE* sInstance;
+	static thread_local DERIVED_TYPE* sInstance;
 };
 
 template<typename DERIVED_TYPE>
-LL_THREAD_LOCAL DERIVED_TYPE* LLThreadLocalSingletonPointer<DERIVED_TYPE>::sInstance = NULL;
+thread_local DERIVED_TYPE* LLThreadLocalSingletonPointer<DERIVED_TYPE>::sInstance = NULL;
 
 #endif // LL_LLTHREADLOCALSTORAGE_H
diff --git a/indra/llcommon/lltrace.cpp b/indra/llcommon/lltrace.cpp
index 7ad50d128821fe94a8532c73f0dfbdf0ba2e4d2b..ff671a837089be312599ff7c9f010a8a61bd7e83 100644
--- a/indra/llcommon/lltrace.cpp
+++ b/indra/llcommon/lltrace.cpp
@@ -40,7 +40,7 @@ StatBase::StatBase( const char* name, const char* description )
 	mDescription(description ? description : "")
 {
 #ifndef LL_RELEASE_FOR_DOWNLOAD
-	if (LLTrace::get_thread_recorder().notNull())
+	if (LLTrace::get_thread_recorder() != NULL)
 	{
 		LL_ERRS() << "Attempting to declare trace object after program initialization.  Trace objects should be statically initialized." << LL_ENDL;
 	}
diff --git a/indra/llcommon/lltraceaccumulators.cpp b/indra/llcommon/lltraceaccumulators.cpp
index 7c38cdb7cd66413a529a755e0e103d8ac6933ceb..6bd886ae98aff6bf4e64b61412fbf7d88f9be05e 100644
--- a/indra/llcommon/lltraceaccumulators.cpp
+++ b/indra/llcommon/lltraceaccumulators.cpp
@@ -93,7 +93,7 @@ void AccumulatorBufferGroup::makeCurrent()
 	mStackTimers.makeCurrent();
 	mMemStats.makeCurrent();
 
-	ThreadRecorder* thread_recorder = get_thread_recorder().get();
+	ThreadRecorder* thread_recorder = get_thread_recorder();
 	AccumulatorBuffer<TimeBlockAccumulator>& timer_accumulator_buffer = mStackTimers;
 	// update stacktimer parent pointers
 	for (size_t i = 0, end_i = mStackTimers.size(); i < end_i; i++)
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index 8414b234e0d170c21d35c472bcbdfdcf37c9ab33..dd148dd08adef80ef96c0a4fadc5f211ca321f70 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -95,7 +95,7 @@ Recording::~Recording()
 	// allow recording destruction without thread recorder running, 
 	// otherwise thread shutdown could crash if a recording outlives the thread recorder
 	// besides, recording construction and destruction is fine without a recorder...just don't attempt to start one
-	if (isStarted() && LLTrace::get_thread_recorder().notNull())
+	if (isStarted() && LLTrace::get_thread_recorder() != NULL)
 	{
 		LLTrace::get_thread_recorder()->deactivate(mBuffers.write());
 	}
@@ -112,9 +112,9 @@ void Recording::update()
 
 		// must have 
 		llassert(mActiveBuffers != NULL 
-				&& LLTrace::get_thread_recorder().notNull());
+				&& LLTrace::get_thread_recorder() != NULL);
 
-		if(!mActiveBuffers->isCurrent())
+		if(!mActiveBuffers->isCurrent() && LLTrace::get_thread_recorder() != NULL)
 		{
 			AccumulatorBufferGroup* buffers = mBuffers.write();
 			LLTrace::get_thread_recorder()->deactivate(buffers);
@@ -144,7 +144,7 @@ void Recording::handleStart()
 	mSamplingTimer.reset();
 	mBuffers.setStayUnique(true);
 	// must have thread recorder running on this thread
-	llassert(LLTrace::get_thread_recorder().notNull());
+	llassert(LLTrace::get_thread_recorder() != NULL);
 	mActiveBuffers = LLTrace::get_thread_recorder()->activate(mBuffers.write());
 #endif
 }
@@ -155,7 +155,7 @@ void Recording::handleStop()
 #if LL_TRACE_ENABLED
 	mElapsedSeconds += mSamplingTimer.getElapsedTimeF64();
 	// must have thread recorder running on this thread
-	llassert(LLTrace::get_thread_recorder().notNull());
+	llassert(LLTrace::get_thread_recorder() != NULL);
 	LLTrace::get_thread_recorder()->deactivate(mBuffers.write());
 	mActiveBuffers = NULL;
 	mBuffers.setStayUnique(false);
@@ -1182,8 +1182,8 @@ void ExtendablePeriodicRecording::handleSplitTo(ExtendablePeriodicRecording& oth
 
 PeriodicRecording& get_frame_recording()
 {
-	static LLThreadLocalPointer<PeriodicRecording> sRecording(new PeriodicRecording(200, PeriodicRecording::STARTED));
-	return *sRecording;
+	static thread_local PeriodicRecording sRecording(200, PeriodicRecording::STARTED);
+	return sRecording;
 }
 
 }
diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp
index d10312e0ec949d796a6aca456e05797035cfa510..4028a5ce973593bdb432c5584e1c351dbb301b7e 100644
--- a/indra/llcommon/lltracethreadrecorder.cpp
+++ b/indra/llcommon/lltracethreadrecorder.cpp
@@ -308,13 +308,13 @@ ThreadRecorder* get_master_thread_recorder()
 	return sMasterThreadRecorder;
 }
 
-LLThreadLocalPointer<ThreadRecorder>& get_thread_recorder_ptr()
+ThreadRecorder*& get_thread_recorder_ptr()
 {
-	static LLThreadLocalPointer<ThreadRecorder> s_thread_recorder;
+	static thread_local ThreadRecorder* s_thread_recorder;
 	return s_thread_recorder;
 }
 
-const LLThreadLocalPointer<ThreadRecorder>& get_thread_recorder()
+ThreadRecorder* get_thread_recorder()
 {
 	return get_thread_recorder_ptr();
 }
diff --git a/indra/llcommon/lltracethreadrecorder.h b/indra/llcommon/lltracethreadrecorder.h
index 1294d4318f78e4434c41d9688de2d9432b750950..8ee6729ac6de0f1a3f26aa05f97fc4110aa7e08c 100644
--- a/indra/llcommon/lltracethreadrecorder.h
+++ b/indra/llcommon/lltracethreadrecorder.h
@@ -32,7 +32,6 @@
 
 #include "llmutex.h"
 #include "lltraceaccumulators.h"
-#include "llthreadlocalstorage.h"
 
 namespace LLTrace
 {
@@ -92,7 +91,7 @@ namespace LLTrace
 
 	};
 
-	const LLThreadLocalPointer<ThreadRecorder>& get_thread_recorder();
+	ThreadRecorder* get_thread_recorder();
 	void set_thread_recorder(ThreadRecorder*);
 
 	void set_master_thread_recorder(ThreadRecorder*);
diff --git a/indra/llcommon/lluuid.cpp b/indra/llcommon/lluuid.cpp
index acce8366eae1b0eac7080af3c9e1612d919dd739..6f9e09a5872fd634af17e4e4d73e23a38764ff12 100644
--- a/indra/llcommon/lluuid.cpp
+++ b/indra/llcommon/lluuid.cpp
@@ -1009,36 +1009,6 @@ LLUUID::LLUUID()
 	return !(word[0] | word[1] | word[2] | word[3]);
 }
 
-// Copy constructor
- LLUUID::LLUUID(const LLUUID& rhs)
-{
-	U32 *tmp = (U32 *)mData;
-	U32 *rhstmp = (U32 *)rhs.mData;
-	tmp[0] = rhstmp[0];
-	tmp[1] = rhstmp[1];
-	tmp[2] = rhstmp[2];
-	tmp[3] = rhstmp[3];
-}
-
- LLUUID::~LLUUID()
-{
-}
-
-// Assignment
- LLUUID& LLUUID::operator=(const LLUUID& rhs)
-{
-	// No need to check the case where this==&rhs.  The branch is slower than the write.
-	U32 *tmp = (U32 *)mData;
-	U32 *rhstmp = (U32 *)rhs.mData;
-	tmp[0] = rhstmp[0];
-	tmp[1] = rhstmp[1];
-	tmp[2] = rhstmp[2];
-	tmp[3] = rhstmp[3];
-	
-	return *this;
-}
-
-
  LLUUID::LLUUID(const char *in_string)
 {
 	if (!in_string || in_string[0] == 0)
diff --git a/indra/llcommon/lluuid.h b/indra/llcommon/lluuid.h
index 86a396ab06f8c1f4de367116c96eba87d8635133..c139c4eb4e1be11e08c7a14093dc76c9d0c592f9 100644
--- a/indra/llcommon/lluuid.h
+++ b/indra/llcommon/lluuid.h
@@ -55,10 +55,7 @@ class LL_COMMON_API LLUUID
 	LLUUID();
 	explicit LLUUID(const char *in_string); // Convert from string.
 	explicit LLUUID(const std::string& in_string); // Convert from string.
-	LLUUID(const LLUUID &in);
-	LLUUID &operator=(const LLUUID &rhs);
-
-	~LLUUID();
+	~LLUUID() = default;
 
 	//
 	// MANIPULATORS
@@ -131,6 +128,9 @@ class LL_COMMON_API LLUUID
 
 	U8 mData[UUID_BYTES];
 };
+static_assert(std::is_trivially_copyable<LLUUID>::value, "LLUUID must be trivial copy");
+static_assert(std::is_trivially_move_assignable<LLUUID>::value, "LLUUID must be trivial move");
+static_assert(std::is_standard_layout<LLUUID>::value, "LLUUID must be a standard layout type");
 
 typedef std::vector<LLUUID> uuid_vec_t;
 typedef std::set<LLUUID> uuid_set_t;
diff --git a/indra/llcommon/threadsafeschedule.h b/indra/llcommon/threadsafeschedule.h
index 2d82d6a15e1ae47e4767432f31394e96b5190fad..92bc7da940621e7a6f8b3773ec06e0312fe4e43f 100644
--- a/indra/llcommon/threadsafeschedule.h
+++ b/indra/llcommon/threadsafeschedule.h
@@ -248,7 +248,7 @@ namespace LL
                 TimePoint until = TimePoint::clock::now() + std::chrono::hours(24);
                 pop_result popped = tryPopUntil_(lock, until, tt);
                 if (popped == POPPED)
-                    return std::move(tt);
+                    return tt;
 
                 // DONE: throw, just as super::pop() does
                 if (popped == DONE)
diff --git a/indra/llfilesystem/lldir_mac.cpp b/indra/llfilesystem/lldir_mac.cpp
index 3bc4ee844e1de113dda495b2dd59c74e07bc00fd..9ad8e274b601704b23a60fc69e2fcf6424ecda93 100644
--- a/indra/llfilesystem/lldir_mac.cpp
+++ b/indra/llfilesystem/lldir_mac.cpp
@@ -66,16 +66,16 @@ LLDir_Mac::LLDir_Mac()
 
     const std::string     secondLifeString = "SecondLife";
     
-    std::string *executablepathstr = getSystemExecutableFolder();
+    std::string executablepathstr = getSystemExecutableFolder();
 
     //NOTE:  LLINFOS/LLERRS will not output to log here.  The streams are not initialized.
     
-	if (executablepathstr)
+	if (!executablepathstr.empty())
 	{
 		// mExecutablePathAndName
-		mExecutablePathAndName = *executablepathstr;
+		mExecutablePathAndName = executablepathstr;
         
-        boost::filesystem::path executablepath(*executablepathstr);
+        boost::filesystem::path executablepath(executablepathstr);
         
 # ifndef BOOST_SYSTEM_NO_DEPRECATED
 #endif
@@ -83,8 +83,8 @@ LLDir_Mac::LLDir_Mac()
         mExecutableDir = executablepath.parent_path().string();
 		
 		// mAppRODataDir
-        std::string *resourcepath = getSystemResourceFolder();
-        mAppRODataDir = *resourcepath;
+        std::string resourcepath = getSystemResourceFolder();
+        mAppRODataDir = resourcepath;
 		
 		// *NOTE: When running in a dev tree, use the copy of
 		// skins in indra/newview/ rather than in the application bundle.  This
@@ -110,11 +110,11 @@ LLDir_Mac::LLDir_Mac()
 		}
 		
 		// mOSUserDir
-        std::string *appdir = getSystemApplicationSupportFolder();
+        std::string appdir = getSystemApplicationSupportFolder();
         std::string rootdir;
 
         //Create root directory
-        if (CreateDirectory(*appdir, secondLifeString, &rootdir))
+        if (CreateDirectory(appdir, secondLifeString, &rootdir))
         {
             
             // Save the full path to the folder
@@ -128,12 +128,10 @@ LLDir_Mac::LLDir_Mac()
         }
     
 		//mOSCacheDir
-        std::string *cachedir =  getSystemCacheFolder();
-
-        if (cachedir)
-		
+        std::string cachedir =  getSystemCacheFolder();
+        if (!cachedir.empty())
 		{
-            mOSCacheDir = *cachedir;
+            mOSCacheDir = cachedir;
             //TODO:  This changes from ~/Library/Cache/Secondlife to ~/Library/Cache/com.app.secondlife/Secondlife.  Last dir level could go away.
             CreateDirectory(mOSCacheDir, secondLifeString, NULL);
 		}
@@ -143,12 +141,10 @@ LLDir_Mac::LLDir_Mac()
 		
 		// mTempDir
         //Aura 120920 boost::filesystem::temp_directory_path() not yet implemented on mac. :(
-        std::string *tmpdir = getSystemTempFolder();
-        if (tmpdir)
+        std::string tmpdir = getSystemTempFolder();
+        if (!tmpdir.empty())
         {
-            
-            CreateDirectory(*tmpdir, secondLifeString, &mTempDir);
-            if (tmpdir) delete tmpdir;
+            CreateDirectory(tmpdir, secondLifeString, &mTempDir);
         }
 		
 		mWorkingDir = getCurPath();
diff --git a/indra/llfilesystem/lldir_utils_objc.h b/indra/llfilesystem/lldir_utils_objc.h
index 12019c4284523629e4e6139c719af31144ee98af..59dbeb4aec26f525850d43be3af29a3fb6a40e30 100644
--- a/indra/llfilesystem/lldir_utils_objc.h
+++ b/indra/llfilesystem/lldir_utils_objc.h
@@ -33,11 +33,11 @@
 
 #include <iostream>
 
-std::string* getSystemTempFolder();
-std::string* getSystemCacheFolder();
-std::string* getSystemApplicationSupportFolder();
-std::string* getSystemResourceFolder();
-std::string* getSystemExecutableFolder();
+std::string getSystemTempFolder();
+std::string getSystemCacheFolder();
+std::string getSystemApplicationSupportFolder();
+std::string getSystemResourceFolder();
+std::string getSystemExecutableFolder();
 
 
 #endif // LL_LLDIR_UTILS_OBJC_H
diff --git a/indra/llfilesystem/lldir_utils_objc.mm b/indra/llfilesystem/lldir_utils_objc.mm
index da55a2f897a6be99720c17a36fd244960f7ab087..20540fb93cd2d85e1d4a554cb8c92d4c3ce09341 100644
--- a/indra/llfilesystem/lldir_utils_objc.mm
+++ b/indra/llfilesystem/lldir_utils_objc.mm
@@ -30,75 +30,75 @@
 #include "lldir_utils_objc.h"
 #import <Cocoa/Cocoa.h>
 
-std::string* getSystemTempFolder()
+std::string getSystemTempFolder()
 {
-    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-    NSString * tempDir = NSTemporaryDirectory();
-    if (tempDir == nil)
-        tempDir = @"/tmp";
-    std::string *result = ( new std::string([tempDir UTF8String]) );
-    [pool release];
+    std::string result;
+    @autoreleasepool {
+        NSString * tempDir = NSTemporaryDirectory();
+        if (tempDir == nil)
+            tempDir = @"/tmp";
+        result = std::string([tempDir UTF8String]);
+    }
     
     return result;
 }
 
 //findSystemDirectory scoped exclusively to this file. 
-std::string* findSystemDirectory(NSSearchPathDirectory searchPathDirectory,
+std::string findSystemDirectory(NSSearchPathDirectory searchPathDirectory,
                                    NSSearchPathDomainMask domainMask)
 {
-    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-    
-    std::string *result = nil;
-    NSString *path = nil;
-    
-    // Search for the path
-    NSArray* paths = NSSearchPathForDirectoriesInDomains(searchPathDirectory,
-                                                         domainMask,
-                                                         YES);
-    if ([paths count])
-    {
-        path = [paths objectAtIndex:0];
-        //HACK:  Always attempt to create directory, ignore errors.
-        NSError *error = nil;
-
-        [[NSFileManager defaultManager] createDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:&error];
-
+    std::string result;
+    @autoreleasepool {
+        NSString *path = nil;
         
-        result = new std::string([path UTF8String]);        
+        // Search for the path
+        NSArray* paths = NSSearchPathForDirectoriesInDomains(searchPathDirectory,
+                                                             domainMask,
+                                                             YES);
+        if ([paths count])
+        {
+            path = [paths objectAtIndex:0];
+            //HACK:  Always attempt to create directory, ignore errors.
+            NSError *error = nil;
+            
+            [[NSFileManager defaultManager] createDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:&error];
+            
+            
+            result = std::string([path UTF8String]);
+        }
     }
-    [pool release];
     return result;
 }
 
-std::string* getSystemExecutableFolder()
+std::string getSystemExecutableFolder()
 {
-    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-
-    NSString *bundlePath = [[NSBundle mainBundle] executablePath];
-    std::string *result = (new std::string([bundlePath UTF8String]));  
-    [pool release];
+    std::string result;
+    @autoreleasepool {
+        NSString *bundlePath = [[NSBundle mainBundle] executablePath];
+        result = std::string([bundlePath UTF8String]);
+    }
 
     return result;
 }
 
-std::string* getSystemResourceFolder()
+std::string getSystemResourceFolder()
 {
-    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-
-    NSString *bundlePath = [[NSBundle mainBundle] resourcePath];
-    std::string *result = (new std::string([bundlePath UTF8String]));
-    [pool release];
+    std::string result;
+    @autoreleasepool {
+        NSString *bundlePath = [[NSBundle mainBundle] resourcePath];
+        result = std::string([bundlePath UTF8String]);
+    }
     
     return result;
 }
 
-std::string* getSystemCacheFolder()
+std::string getSystemCacheFolder()
 {
     return findSystemDirectory (NSCachesDirectory,
                                 NSUserDomainMask);
 }
 
-std::string* getSystemApplicationSupportFolder()
+std::string getSystemApplicationSupportFolder()
 {
     return findSystemDirectory (NSApplicationSupportDirectory,
                                 NSUserDomainMask);
diff --git a/indra/llimage/llpngwrapper.cpp b/indra/llimage/llpngwrapper.cpp
index f7dc6272cf94cc7c5ad4319669781eb7f63f9080..cad7c00042bd33ca864fbba71a48bf9b8839659d 100644
--- a/indra/llimage/llpngwrapper.cpp
+++ b/indra/llimage/llpngwrapper.cpp
@@ -257,12 +257,7 @@ void LLPngWrapper::normalizeImage()
 		png_set_strip_16(mReadPngPtr);
 	}
 
-#if LL_DARWIN
-	const F64 SCREEN_GAMMA = 1.8;
-#else
 	const F64 SCREEN_GAMMA = 2.2;
-#endif
-
 	if (png_get_gAMA(mReadPngPtr, mReadInfoPtr, &mGamma))
 	{
 		png_set_gamma(mReadPngPtr, SCREEN_GAMMA, mGamma);
diff --git a/indra/llimagej2coj/llimagej2coj.cpp b/indra/llimagej2coj/llimagej2coj.cpp
index 925da5674bfc5591faa941221c035a4aea8da1da..12985c3c7f51247fd646653b3033e4304248ba83 100644
--- a/indra/llimagej2coj/llimagej2coj.cpp
+++ b/indra/llimagej2coj/llimagej2coj.cpp
@@ -29,40 +29,41 @@
 
 // this is defined so that we get static linking.
 #include "openjpeg.h"
+#include "event.h"
+#include "cio.h"
 
-#include "lltimer.h"
-//#include "llmemory.h"
+#define MAX_ENCODED_DISCARD_LEVELS 5
 
 // Factory function: see declaration in llimagej2c.cpp
 LLImageJ2CImpl* fallbackCreateLLImageJ2CImpl()
 {
-	return new LLImageJ2COJ();
+    return new LLImageJ2COJ();
 }
 
 std::string LLImageJ2COJ::getEngineInfo() const
 {
 #ifdef OPENJPEG_VERSION
-	return std::string("OpenJPEG: " OPENJPEG_VERSION ", Runtime: ")
-		+ opj_version();
+    return std::string("OpenJPEG: " OPENJPEG_VERSION ", Runtime: ")
+        + opj_version();
 #else
-	return std::string("OpenJPEG runtime: ") + opj_version();
+    return std::string("OpenJPEG runtime: ") + opj_version();
 #endif
 }
 
 // Return string from message, eliminating final \n if present
 static std::string chomp(const char* msg)
 {
-	// stomp trailing \n
-	std::string message = msg;
-	if (!message.empty())
-	{
-		size_t last = message.size() - 1;
-		if (message[last] == '\n')
-		{
-			message.resize( last );
-		}
-	}
-	return message;
+    // stomp trailing \n
+    std::string message = msg;
+    if (!message.empty())
+    {
+        size_t last = message.size() - 1;
+        if (message[last] == '\n')
+        {
+            message.resize(last);
+        }
+}
+    return message;
 }
 
 /**
@@ -70,419 +71,770 @@ sample error callback expecting a LLFILE* client object
 */
 void error_callback(const char* msg, void*)
 {
-	LL_DEBUGS() << "LLImageJ2COJ: " << chomp(msg) << LL_ENDL;
+    LL_DEBUGS() << "LLImageJ2COJ: " << chomp(msg) << LL_ENDL;
 }
 /**
 sample warning callback expecting a LLFILE* client object
 */
 void warning_callback(const char* msg, void*)
 {
-	LL_DEBUGS() << "LLImageJ2COJ: " << chomp(msg) << LL_ENDL;
+    LL_DEBUGS() << "LLImageJ2COJ: " << chomp(msg) << LL_ENDL;
 }
 /**
 sample debug callback expecting no client object
 */
 void info_callback(const char* msg, void*)
 {
-	LL_DEBUGS() << "LLImageJ2COJ: " << chomp(msg) << LL_ENDL;
+    LL_DEBUGS() << "LLImageJ2COJ: " << chomp(msg) << LL_ENDL;
 }
 
 // Divide a by 2 to the power of b and round upwards
 int ceildivpow2(int a, int b)
 {
-	return (a + (1 << b) - 1) >> b;
+    return (a + (1 << b) - 1) >> b;
 }
 
-
-LLImageJ2COJ::LLImageJ2COJ()
-	: LLImageJ2CImpl()
+class JPEG2KBase
 {
-}
+public:
+    JPEG2KBase() {}
 
+    U8*        buffer = nullptr;
+    OPJ_SIZE_T size = 0;
+    OPJ_OFF_T  offset = 0;
+};
 
-LLImageJ2COJ::~LLImageJ2COJ()
+#define WANT_VERBOSE_OPJ_SPAM LL_DEBUG
+
+static void opj_info(const char* msg, void* user_data)
 {
+    llassert(user_data);
+#if WANT_VERBOSE_OPJ_SPAM
+    LL_INFOS("OpenJPEG") << msg << LL_ENDL;
+#endif
 }
 
-bool LLImageJ2COJ::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, int discard_level, int* region)
+static void opj_warn(const char* msg, void* user_data)
 {
-	// No specific implementation for this method in the OpenJpeg case
-	return false;
+    llassert(user_data);
+#if WANT_VERBOSE_OPJ_SPAM
+    LL_WARNS("OpenJPEG") << msg << LL_ENDL;
+#endif
 }
 
-bool LLImageJ2COJ::initEncode(LLImageJ2C &base, LLImageRaw &raw_image, int blocks_size, int precincts_size, int levels)
+static void opj_error(const char* msg, void* user_data)
 {
-	// No specific implementation for this method in the OpenJpeg case
-	return false;
+    llassert(user_data);
+#if WANT_VERBOSE_OPJ_SPAM
+    LL_WARNS("OpenJPEG") << msg << LL_ENDL;
+#endif
 }
 
-bool LLImageJ2COJ::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, S32 first_channel, S32 max_channel_count)
+static OPJ_SIZE_T opj_read(void * buffer, OPJ_SIZE_T bytes, void* user_data)
 {
-	//
-	// FIXME: Get the comment field out of the texture
-	//
-
-	LLTimer decode_timer;
-
-	opj_dparameters_t parameters;	/* decompression parameters */
-	opj_event_mgr_t event_mgr;		/* event manager */
-	opj_image_t *image = NULL;
-
-	opj_dinfo_t* dinfo = NULL;	/* handle to a decompressor */
-	opj_cio_t *cio = NULL;
-
-
-	/* configure the event callbacks (not required) */
-	memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
-	event_mgr.error_handler = error_callback;
-	event_mgr.warning_handler = warning_callback;
-	event_mgr.info_handler = info_callback;
-
-	/* set decoding parameters to default values */
-	opj_set_default_decoder_parameters(&parameters);
-
-	parameters.cp_reduce = base.getRawDiscardLevel();
-
-	/* decode the code-stream */
-	/* ---------------------- */
-
-	/* JPEG-2000 codestream */
-
-	/* get a decoder handle */
-	dinfo = opj_create_decompress(CODEC_J2K);
-
-	/* catch events using our callbacks and give a local context */
-	opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, stderr);			
-
-	/* setup the decoder decoding parameters using user parameters */
-	opj_setup_decoder(dinfo, &parameters);
-
-	/* open a byte stream */
-	cio = opj_cio_open((opj_common_ptr)dinfo, base.getData(), base.getDataSize());
-
-	/* decode the stream and fill the image structure */
-	image = opj_decode(dinfo, cio);
-
-	/* close the byte stream */
-	opj_cio_close(cio);
-
-	/* free remaining structures */
-	if(dinfo)
-	{
-		opj_destroy_decompress(dinfo);
-	}
-
-	// The image decode failed if the return was NULL or the component
-	// count was zero.  The latter is just a sanity check before we
-	// dereference the array.
-	if(!image || !image->numcomps)
-	{
-		LL_DEBUGS("Texture") << "ERROR -> decodeImpl: failed to decode image!" << LL_ENDL;
-		if (image)
-		{
-			opj_image_destroy(image);
-		}
-
-		return true; // done
-	}
-
-	// sometimes we get bad data out of the cache - check to see if the decode succeeded
-	for (S32 i = 0; i < image->numcomps; i++)
-	{
-		if (image->comps[i].factor != base.getRawDiscardLevel())
-		{
-			// if we didn't get the discard level we're expecting, fail
-			opj_image_destroy(image);
-			base.mDecoding = false;
-			return true;
-		}
-	}
-	
-	if(image->numcomps <= first_channel)
-	{
-		LL_WARNS() << "trying to decode more channels than are present in image: numcomps: " << image->numcomps << " first_channel: " << first_channel << LL_ENDL;
-		if (image)
-		{
-			opj_image_destroy(image);
-		}
-			
-		return true;
-	}
-
-	// Copy image data into our raw image format (instead of the separate channel format
-
-	S32 img_components = image->numcomps;
-	S32 channels = img_components - first_channel;
-	if( channels > max_channel_count )
-		channels = max_channel_count;
-
-	// Component buffers are allocated in an image width by height buffer.
-	// The image placed in that buffer is ceil(width/2^factor) by
-	// ceil(height/2^factor) and if the factor isn't zero it will be at the
-	// top left of the buffer with black filled in the rest of the pixels.
-	// It is integer math so the formula is written in ceildivpo2.
-	// (Assuming all the components have the same width, height and
-	// factor.)
-	S32 comp_width = image->comps[0].w;
-	S32 f=image->comps[0].factor;
-	S32 width = ceildivpow2(image->x1 - image->x0, f);
-	S32 height = ceildivpow2(image->y1 - image->y0, f);
-	raw_image.resize(width, height, channels);
-	U8 *rawp = raw_image.getData();
-
-	// first_channel is what channel to start copying from
-	// dest is what channel to copy to.  first_channel comes from the
-	// argument, dest always starts writing at channel zero.
-	for (S32 comp = first_channel, dest=0; comp < first_channel + channels;
-		comp++, dest++)
-	{
-		if (image->comps[comp].data)
-		{
-			S32 offset = dest;
-			for (S32 y = (height - 1); y >= 0; y--)
-			{
-				for (S32 x = 0; x < width; x++)
-				{
-					rawp[offset] = image->comps[comp].data[y*comp_width + x];
-					offset += channels;
-				}
-			}
-		}
-		else // Some rare OpenJPEG versions have this bug.
-		{
-			LL_DEBUGS("Texture") << "ERROR -> decodeImpl: failed to decode image! (NULL comp data - OpenJPEG bug)" << LL_ENDL;
-			opj_image_destroy(image);
-
-			return true; // done
-		}
-	}
-
-	/* free image data structure */
-	opj_image_destroy(image);
-
-	return true; // done
+    llassert(user_data);
+    JPEG2KBase* jpeg_codec = static_cast<JPEG2KBase*>(user_data);
+    OPJ_SIZE_T remainder = (jpeg_codec->size - jpeg_codec->offset);
+    if (remainder <= 0)
+    {
+        jpeg_codec->offset = jpeg_codec->size;
+        // Indicate end of stream (hacky?)
+        return (OPJ_OFF_T)-1;
+    }
+    OPJ_SIZE_T to_read = llclamp(U32(bytes), U32(0), U32(remainder));
+    memcpy(buffer, jpeg_codec->buffer + jpeg_codec->offset, to_read);
+    jpeg_codec->offset += to_read;
+    return to_read;
 }
 
-
-bool LLImageJ2COJ::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, const char* comment_text, F32 encode_time, bool reversible)
+static OPJ_SIZE_T opj_write(void * buffer, OPJ_SIZE_T bytes, void* user_data)
 {
-	const S32 MAX_COMPS = 5;
-	opj_cparameters_t parameters;	/* compression parameters */
-	opj_event_mgr_t event_mgr;		/* event manager */
-
-
-	/* 
-	configure the event callbacks (not required)
-	setting of each callback is optional 
-	*/
-	memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
-	event_mgr.error_handler = error_callback;
-	event_mgr.warning_handler = warning_callback;
-	event_mgr.info_handler = info_callback;
-
-	/* set encoding parameters to default values */
-	opj_set_default_encoder_parameters(&parameters);
-	parameters.cod_format = 0;
-	parameters.cp_disto_alloc = 1;
-
-	if (reversible)
-	{
-		parameters.tcp_numlayers = 1;
-		parameters.tcp_rates[0] = 0.0f;
-	}
-	else
-	{
-		parameters.tcp_numlayers = 5;
-                parameters.tcp_rates[0] = 1920.0f;
-                parameters.tcp_rates[1] = 480.0f;
-                parameters.tcp_rates[2] = 120.0f;
-                parameters.tcp_rates[3] = 30.0f;
-		parameters.tcp_rates[4] = 10.0f;
-		parameters.irreversible = 1;
-		if (raw_image.getComponents() >= 3)
-		{
-			parameters.tcp_mct = 1;
-		}
-	}
-
-	if (!comment_text)
-	{
-		parameters.cp_comment = (char *) "";
-	}
-	else
-	{
-		// Awful hacky cast, too lazy to copy right now.
-		parameters.cp_comment = (char *) comment_text;
-	}
-
-	//
-	// Fill in the source image from our raw image
-	//
-	OPJ_COLOR_SPACE color_space = CLRSPC_SRGB;
-	opj_image_cmptparm_t cmptparm[MAX_COMPS];
-	opj_image_t * image = NULL;
-	S32 numcomps = raw_image.getComponents();
-	S32 width = raw_image.getWidth();
-	S32 height = raw_image.getHeight();
-
-	memset(&cmptparm[0], 0, MAX_COMPS * sizeof(opj_image_cmptparm_t));
-	for(S32 c = 0; c < numcomps; c++) {
-		cmptparm[c].prec = 8;
-		cmptparm[c].bpp = 8;
-		cmptparm[c].sgnd = 0;
-		cmptparm[c].dx = parameters.subsampling_dx;
-		cmptparm[c].dy = parameters.subsampling_dy;
-		cmptparm[c].w = width;
-		cmptparm[c].h = height;
-	}
-
-	/* create the image */
-	image = opj_image_create(numcomps, &cmptparm[0], color_space);
-
-	image->x1 = width;
-	image->y1 = height;
-
-	S32 i = 0;
-	const U8 *src_datap = raw_image.getData();
-	for (S32 y = height - 1; y >= 0; y--)
-	{
-		for (S32 x = 0; x < width; x++)
-		{
-			const U8 *pixel = src_datap + (y*width + x) * numcomps;
-			for (S32 c = 0; c < numcomps; c++)
-			{
-				image->comps[c].data[i] = *pixel;
-				pixel++;
-			}
-			i++;
-		}
-	}
-
-
-
-	/* encode the destination image */
-	/* ---------------------------- */
-
-	int codestream_length;
-	opj_cio_t *cio = NULL;
-
-	/* get a J2K compressor handle */
-	opj_cinfo_t* cinfo = opj_create_compress(CODEC_J2K);
-
-	/* catch events using our callbacks and give a local context */
-	opj_set_event_mgr((opj_common_ptr)cinfo, &event_mgr, stderr);			
-
-	/* setup the encoder parameters using the current image and using user parameters */
-	opj_setup_encoder(cinfo, &parameters, image);
-
-	/* open a byte stream for writing */
-	/* allocate memory for all tiles */
-	cio = opj_cio_open((opj_common_ptr)cinfo, NULL, 0);
-
-	/* encode the image */
-	bool bSuccess = opj_encode(cinfo, cio, image, NULL);
-	if (!bSuccess)
-	{
-		opj_cio_close(cio);
-		LL_DEBUGS("Texture") << "Failed to encode image." << LL_ENDL;
-		return false;
-	}
-	codestream_length = cio_tell(cio);
-
-	base.copyData(cio->buffer, codestream_length);
-	base.updateData(); // set width, height
-
-	/* close and free the byte stream */
-	opj_cio_close(cio);
-
-	/* free remaining compression structures */
-	opj_destroy_compress(cinfo);
-
-
-	/* free user parameters structure */
-	if(parameters.cp_matrice) free(parameters.cp_matrice);
-
-	/* free image data */
-	opj_image_destroy(image);
-	return true;
+    llassert(user_data);
+    JPEG2KBase* jpeg_codec = static_cast<JPEG2KBase*>(user_data);
+    OPJ_SIZE_T remainder = jpeg_codec->size - jpeg_codec->offset;
+    if (remainder < bytes)
+    {
+        OPJ_SIZE_T new_size = jpeg_codec->size + (bytes - remainder);
+        U8* new_buffer = (U8*)ll_aligned_malloc_16(new_size);
+        memcpy(new_buffer, jpeg_codec->buffer, jpeg_codec->offset);
+        U8* old_buffer = jpeg_codec->buffer;
+        jpeg_codec->buffer = new_buffer;
+        ll_aligned_free_16(old_buffer);
+        jpeg_codec->size = new_size;
+    }
+    memcpy(jpeg_codec->buffer + jpeg_codec->offset, buffer, bytes);
+    jpeg_codec->offset += bytes;
+    return bytes;
 }
 
-bool LLImageJ2COJ::getMetadata(LLImageJ2C &base)
+static OPJ_OFF_T opj_skip(OPJ_OFF_T bytes, void* user_data)
 {
-	//
-	// FIXME: We get metadata by decoding the ENTIRE image.
-	//
-
-	// Update the raw discard level
-	base.updateRawDiscardLevel();
-
-	opj_dparameters_t parameters;	/* decompression parameters */
-	opj_event_mgr_t event_mgr;		/* event manager */
-	opj_image_t *image = NULL;
-
-	opj_dinfo_t* dinfo = NULL;	/* handle to a decompressor */
-	opj_cio_t *cio = NULL;
-
-
-	/* configure the event callbacks (not required) */
-	memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
-	event_mgr.error_handler = error_callback;
-	event_mgr.warning_handler = warning_callback;
-	event_mgr.info_handler = info_callback;
-
-	/* set decoding parameters to default values */
-	opj_set_default_decoder_parameters(&parameters);
-
-	// Only decode what's required to get the size data.
-	parameters.cp_limit_decoding=LIMIT_TO_MAIN_HEADER;
+    JPEG2KBase* jpeg_codec = static_cast<JPEG2KBase*>(user_data);
+    jpeg_codec->offset += bytes;
+
+    if (jpeg_codec->offset > jpeg_codec->size)
+    {
+        jpeg_codec->offset = jpeg_codec->size;
+        // Indicate end of stream
+        return (OPJ_OFF_T)-1;
+    }
+
+    if (jpeg_codec->offset < 0)
+    {
+        // Shouldn't be possible?
+        jpeg_codec->offset = 0;
+        return (OPJ_OFF_T)-1;
+    }
+
+    return bytes;
+}
 
-	//parameters.cp_reduce = mRawDiscardLevel;
+static OPJ_BOOL opj_seek(OPJ_OFF_T bytes, void * user_data)
+{
+    JPEG2KBase* jpeg_codec = static_cast<JPEG2KBase*>(user_data);
+    jpeg_codec->offset = bytes;
+    jpeg_codec->offset = llclamp(U32(jpeg_codec->offset), U32(0), U32(jpeg_codec->size));
+    return OPJ_TRUE;
+}
 
-	/* decode the code-stream */
-	/* ---------------------- */
+static void opj_free_user_data(void * user_data)
+{
+    JPEG2KBase* jpeg_codec = static_cast<JPEG2KBase*>(user_data);
+    // Don't free, data is managed externally
+    jpeg_codec->buffer = nullptr;
+    jpeg_codec->size = 0;
+    jpeg_codec->offset = 0;
+}
 
-	/* JPEG-2000 codestream */
+static void opj_free_user_data_write(void * user_data)
+{
+    JPEG2KBase* jpeg_codec = static_cast<JPEG2KBase*>(user_data);
+    // Free, data was allocated here
+    ll_aligned_free_16(jpeg_codec->buffer);
+    jpeg_codec->buffer = nullptr;
+    jpeg_codec->size = 0;
+    jpeg_codec->offset = 0;
+}
 
-	/* get a decoder handle */
-	dinfo = opj_create_decompress(CODEC_J2K);
+class JPEG2KDecode : public JPEG2KBase
+{
+public:
+
+    JPEG2KDecode(S8 discardLevel)
+    {
+        memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
+        memset(&parameters, 0, sizeof(opj_dparameters_t));
+        event_mgr.error_handler = error_callback;
+        event_mgr.warning_handler = warning_callback;
+        event_mgr.info_handler = info_callback;
+        opj_set_default_decoder_parameters(&parameters);
+        parameters.cp_reduce = discardLevel;
+    }
+
+    ~JPEG2KDecode()
+    {
+        if (decoder)
+        {
+            opj_destroy_codec(decoder);
+        }
+        decoder = nullptr;
+
+        if (image)
+        {
+            opj_image_destroy(image);
+        }
+        image = nullptr;
+
+        if (stream)
+        {
+            opj_stream_destroy(stream);
+        }
+        stream = nullptr;
+
+        if (codestream_info)
+        {
+            opj_destroy_cstr_info(&codestream_info);
+        }
+        codestream_info = nullptr;
+    }
+
+    bool readHeader(
+        U8* data,
+        U32 dataSize,
+        S32& widthOut,
+        S32& heightOut,
+        S32& components,
+        S32& discard_level)
+    {
+        parameters.flags |= OPJ_DPARAMETERS_DUMP_FLAG;
+
+        decoder = opj_create_decompress(OPJ_CODEC_J2K);
+
+        if (!opj_setup_decoder(decoder, &parameters))
+        {
+            return false;
+        }
+
+        if (stream)
+        {
+            opj_stream_destroy(stream);
+        }
+
+        stream = opj_stream_create(dataSize, true);
+        if (!stream)
+        {
+            return false;
+        }
+
+        opj_stream_set_user_data(stream, this, opj_free_user_data);
+        opj_stream_set_user_data_length(stream, dataSize);
+        opj_stream_set_read_function(stream, opj_read);
+        opj_stream_set_write_function(stream, opj_write);
+        opj_stream_set_skip_function(stream, opj_skip);
+        opj_stream_set_seek_function(stream, opj_seek);
+
+        buffer = data;
+        size = dataSize;
+        offset = 0;
+
+        // enable decoding partially loaded images
+        opj_decoder_set_strict_mode(decoder, OPJ_FALSE);
+
+        /* Read the main header of the codestream and if necessary the JP2 boxes*/
+        if (!opj_read_header((opj_stream_t*)stream, decoder, &image))
+        {
+            return false;
+        }
+
+        codestream_info = opj_get_cstr_info(decoder);
+
+        if (!codestream_info)
+        {
+            return false;
+        }
+
+        U32 tileDimX = codestream_info->tdx;
+        U32 tileDimY = codestream_info->tdy;
+        U32 tilesW = codestream_info->tw;
+        U32 tilesH = codestream_info->th;
+
+        widthOut = S32(tilesW * tileDimX);
+        heightOut = S32(tilesH * tileDimY);
+        components = codestream_info->nbcomps;
+
+        discard_level = 0;
+        while (tilesW > 1 && tilesH > 1 && discard_level < MAX_DISCARD_LEVEL)
+        {
+            discard_level++;
+            tilesW >>= 1;
+            tilesH >>= 1;
+        }
+
+        return true;
+    }
+
+    bool decode(U8* data, U32 dataSize, U32* channels, U8 discard_level)
+    {
+        parameters.flags &= ~OPJ_DPARAMETERS_DUMP_FLAG;
+
+        decoder = opj_create_decompress(OPJ_CODEC_J2K);
+        opj_setup_decoder(decoder, &parameters);
+
+        opj_set_info_handler(decoder, opj_info, this);
+        opj_set_warning_handler(decoder, opj_warn, this);
+        opj_set_error_handler(decoder, opj_error, this);
+
+        if (stream)
+        {
+            opj_stream_destroy(stream);
+        }
+
+        stream = opj_stream_create(dataSize, true);
+        if (!stream)
+        {
+            return false;
+        }
+
+        opj_stream_set_user_data(stream, this, opj_free_user_data);
+        opj_stream_set_user_data_length(stream, dataSize);
+        opj_stream_set_read_function(stream, opj_read);
+        opj_stream_set_write_function(stream, opj_write);
+        opj_stream_set_skip_function(stream, opj_skip);
+        opj_stream_set_seek_function(stream, opj_seek);
+
+        buffer = data;
+        size = dataSize;
+        offset = 0;
+
+        if (image)
+        {
+            opj_image_destroy(image);
+            image = nullptr;
+        }
+
+        // needs to happen before opj_read_header and opj_decode...
+        opj_set_decoded_resolution_factor(decoder, discard_level);
+
+        // enable decoding partially loaded images
+        opj_decoder_set_strict_mode(decoder, OPJ_FALSE);
+
+        if (!opj_read_header(stream, decoder, &image))
+        {
+            return false;
+        }
+
+        // needs to happen before decode which may fail
+        if (channels)
+        {
+            *channels = image->numcomps;
+        }
+
+        OPJ_BOOL decoded = opj_decode(decoder, stream, image);
+
+        // count was zero.  The latter is just a sanity check before we
+        // dereference the array.
+        if (!decoded || !image || !image->numcomps)
+        {
+            opj_end_decompress(decoder, stream);
+            return false;
+        }
+
+        opj_end_decompress(decoder, stream);
+
+        return true;
+    }
+
+    opj_image_t* getImage() { return image; }
+
+private:
+    opj_dparameters_t         parameters;
+    opj_event_mgr_t           event_mgr;
+    opj_image_t*              image = nullptr;
+    opj_codec_t*              decoder = nullptr;
+    opj_stream_t*             stream = nullptr;
+    opj_codestream_info_v2_t* codestream_info = nullptr;
+};
+
+class JPEG2KEncode : public JPEG2KBase
+{
+public:
+    const OPJ_UINT32 TILE_SIZE = 64 * 64 * 3;
+
+    JPEG2KEncode(const char* comment_text_in, bool reversible)
+    {
+        memset(&parameters, 0, sizeof(opj_cparameters_t));
+        memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
+        event_mgr.error_handler = error_callback;
+        event_mgr.warning_handler = warning_callback;
+        event_mgr.info_handler = info_callback;
+
+        opj_set_default_encoder_parameters(&parameters);
+        parameters.cod_format = OPJ_CODEC_J2K;
+        parameters.cp_disto_alloc = 1;
+        parameters.max_cs_size = (1 << 15);
+
+        if (reversible)
+        {
+            parameters.tcp_numlayers = 1;
+            parameters.tcp_rates[0] = 1.0f;
+        }
+        else
+        {
+            parameters.tcp_numlayers = 5;
+            parameters.tcp_rates[0] = 1920.0f;
+            parameters.tcp_rates[1] = 960.0f;
+            parameters.tcp_rates[2] = 480.0f;
+            parameters.tcp_rates[3] = 120.0f;
+            parameters.tcp_rates[4] = 30.0f;
+            parameters.irreversible = 1;
+            parameters.tcp_mct = 1;
+        }
+
+        if (comment_text)
+        {
+            free(comment_text);
+        }
+        comment_text = comment_text_in ? strdup(comment_text_in) : nullptr;
+
+        parameters.cp_comment = comment_text ? comment_text : (char*)"no comment";
+        llassert(parameters.cp_comment);
+    }
+
+    ~JPEG2KEncode()
+    {
+        if (encoder)
+        {
+            opj_destroy_codec(encoder);
+        }
+        encoder = nullptr;
+
+        if (image)
+        {
+            opj_image_destroy(image);
+        }
+        image = nullptr;
+
+        if (stream)
+        {
+            opj_stream_destroy(stream);
+        }
+        stream = nullptr;
+
+        if (comment_text)
+        {
+            free(comment_text);
+        }
+        comment_text = nullptr;
+    }
+
+    bool encode(const LLImageRaw& rawImageIn, LLImageJ2C &compressedImageOut)
+    {
+        setImage(rawImageIn);
+
+        encoder = opj_create_compress(OPJ_CODEC_J2K);
+
+        parameters.tcp_mct = (image->numcomps >= 3) ? 1 : 0;
+        parameters.cod_format = OPJ_CODEC_J2K;
+        parameters.prog_order = OPJ_RLCP;
+        parameters.cp_disto_alloc = 1;
+
+        if (!opj_setup_encoder(encoder, &parameters, image))
+        {
+            return false;
+        }
+
+        opj_set_info_handler(encoder, opj_info, this);
+        opj_set_warning_handler(encoder, opj_warn, this);
+        opj_set_error_handler(encoder, opj_error, this);
+
+        U32 tile_count = (rawImageIn.getWidth() >> 6) * (rawImageIn.getHeight() >> 6);
+        U32 data_size_guess = tile_count * TILE_SIZE;
+
+        // will be freed in opj_free_user_data_write
+        buffer = (U8*)ll_aligned_malloc_16(data_size_guess);
+        size = data_size_guess;
+        offset = 0;
+
+        memset(buffer, 0, data_size_guess);
+
+        if (stream)
+        {
+            opj_stream_destroy(stream);
+        }
+
+        stream = opj_stream_create(data_size_guess, false);
+        if (!stream)
+        {
+            return false;
+        }
+
+        opj_stream_set_user_data(stream, this, opj_free_user_data_write);
+        opj_stream_set_user_data_length(stream, data_size_guess);
+        opj_stream_set_read_function(stream, opj_read);
+        opj_stream_set_write_function(stream, opj_write);
+        opj_stream_set_skip_function(stream, opj_skip);
+        opj_stream_set_seek_function(stream, opj_seek);
+
+        OPJ_BOOL started = opj_start_compress(encoder, image, stream);
+
+        if (!started)
+        {
+            return false;
+        }
+
+        if (!opj_encode(encoder, stream))
+        {
+            return false;
+        }
+
+        OPJ_BOOL encoded = opj_end_compress(encoder, stream);
+
+        // if we successfully encoded, then stream out the compressed data...
+        if (encoded)
+        {
+            // "append" (set) the data we "streamed" (memcopied) for writing to the formatted image
+            // with side-effect of setting the actually encoded size  to same
+            compressedImageOut.allocateData(offset);
+            memcpy(compressedImageOut.getData(), buffer, offset);
+            compressedImageOut.updateData(); // update width, height etc from header
+        }
+        return encoded;
+    }
+
+    void setImage(const LLImageRaw& raw)
+    {
+        opj_image_cmptparm_t cmptparm[MAX_ENCODED_DISCARD_LEVELS];
+        memset(&cmptparm[0], 0, MAX_ENCODED_DISCARD_LEVELS * sizeof(opj_image_cmptparm_t));
+
+        S32 numcomps = raw.getComponents();
+        S32 width = raw.getWidth();
+        S32 height = raw.getHeight();
+
+        for (S32 c = 0; c < numcomps; c++)
+        {
+            cmptparm[c].prec = 8;
+            cmptparm[c].bpp = 8;
+            cmptparm[c].sgnd = 0;
+            cmptparm[c].dx = parameters.subsampling_dx;
+            cmptparm[c].dy = parameters.subsampling_dy;
+            cmptparm[c].w = width;
+            cmptparm[c].h = height;
+        }
+
+        image = opj_image_create(numcomps, &cmptparm[0], OPJ_CLRSPC_SRGB);
+
+        image->x1 = width;
+        image->y1 = height;
+
+        const U8 *src_datap = raw.getData();
+
+        S32 i = 0;
+        for (S32 y = height - 1; y >= 0; y--)
+        {
+            for (S32 x = 0; x < width; x++)
+            {
+                const U8 *pixel = src_datap + (y*width + x) * numcomps;
+                for (S32 c = 0; c < numcomps; c++)
+                {
+                    image->comps[c].data[i] = *pixel;
+                    pixel++;
+                }
+                i++;
+            }
+        }
+
+        // This likely works, but there seems to be an issue openjpeg side
+        // check over after gixing that.
+
+        // De-interleave to component plane data
+        /*
+        switch (numcomps)
+        {
+        case 0:
+        default:
+            break;
+
+        case 1:
+        {
+            U32 rBitDepth = image->comps[0].bpp;
+            U32 bytesPerPixel = rBitDepth >> 3;
+            memcpy(image->comps[0].data, src, width * height * bytesPerPixel);
+        }
+        break;
+
+        case 2:
+        {
+            U32 rBitDepth = image->comps[0].bpp;
+            U32 gBitDepth = image->comps[1].bpp;
+            U32 totalBitDepth = rBitDepth + gBitDepth;
+            U32 bytesPerPixel = totalBitDepth >> 3;
+            U32 stride = width * bytesPerPixel;
+            U32 offset = 0;
+            for (S32 y = height - 1; y >= 0; y--)
+            {
+                const U8* component = src + (y * stride);
+                for (S32 x = 0; x < width; x++)
+                {
+                    image->comps[0].data[offset] = *component++;
+                    image->comps[1].data[offset] = *component++;
+                    offset++;
+                }
+            }
+        }
+        break;
+
+        case 3:
+        {
+            U32 rBitDepth = image->comps[0].bpp;
+            U32 gBitDepth = image->comps[1].bpp;
+            U32 bBitDepth = image->comps[2].bpp;
+            U32 totalBitDepth = rBitDepth + gBitDepth + bBitDepth;
+            U32 bytesPerPixel = totalBitDepth >> 3;
+            U32 stride = width * bytesPerPixel;
+            U32 offset = 0;
+            for (S32 y = height - 1; y >= 0; y--)
+            {
+                const U8* component = src + (y * stride);
+                for (S32 x = 0; x < width; x++)
+                {
+                    image->comps[0].data[offset] = *component++;
+                    image->comps[1].data[offset] = *component++;
+                    image->comps[2].data[offset] = *component++;
+                    offset++;
+                }
+            }
+        }
+        break;
+
+
+        case 4:
+        {
+            U32 rBitDepth = image->comps[0].bpp;
+            U32 gBitDepth = image->comps[1].bpp;
+            U32 bBitDepth = image->comps[2].bpp;
+            U32 aBitDepth = image->comps[3].bpp;
+
+            U32 totalBitDepth = rBitDepth + gBitDepth + bBitDepth + aBitDepth;
+            U32 bytesPerPixel = totalBitDepth >> 3;
+
+            U32 stride = width * bytesPerPixel;
+            U32 offset = 0;
+            for (S32 y = height - 1; y >= 0; y--)
+            {
+                const U8* component = src + (y * stride);
+                for (S32 x = 0; x < width; x++)
+                {
+                    image->comps[0].data[offset] = *component++;
+                    image->comps[1].data[offset] = *component++;
+                    image->comps[2].data[offset] = *component++;
+                    image->comps[3].data[offset] = *component++;
+                    offset++;
+                }
+            }
+        }
+        break;
+        }*/
+    }
+
+    opj_image_t* getImage() { return image; }
+
+private:
+    opj_cparameters_t   parameters;
+    opj_event_mgr_t     event_mgr;
+    opj_image_t*        image = nullptr;
+    opj_codec_t*        encoder = nullptr;
+    opj_stream_t*       stream = nullptr;
+    char*               comment_text = nullptr;
+};
 
-	/* catch events using our callbacks and give a local context */
-	opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, stderr);			
 
-	/* setup the decoder decoding parameters using user parameters */
-	opj_setup_decoder(dinfo, &parameters);
+LLImageJ2COJ::LLImageJ2COJ()
+	: LLImageJ2CImpl()
+{
+}
 
-	/* open a byte stream */
-	cio = opj_cio_open((opj_common_ptr)dinfo, base.getData(), base.getDataSize());
 
-	/* decode the stream and fill the image structure */
-	image = opj_decode(dinfo, cio);
+LLImageJ2COJ::~LLImageJ2COJ()
+{
+}
 
-	/* close the byte stream */
-	opj_cio_close(cio);
+bool LLImageJ2COJ::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, int discard_level, int* region)
+{
+    base.mDiscardLevel = discard_level;
+	return false;
+}
 
-	/* free remaining structures */
-	if(dinfo)
-	{
-		opj_destroy_decompress(dinfo);
-	}
+bool LLImageJ2COJ::initEncode(LLImageJ2C &base, LLImageRaw &raw_image, int blocks_size, int precincts_size, int levels)
+{
+	// No specific implementation for this method in the OpenJpeg case
+	return false;
+}
 
-	if(!image)
-	{
-		LL_WARNS() << "ERROR -> getMetadata: failed to decode image!" << LL_ENDL;
-		return false;
-	}
+bool LLImageJ2COJ::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, S32 first_channel, S32 max_channel_count)
+{
+    JPEG2KDecode decoder(0);
+
+    U32 image_channels = 0;
+    S32 data_size = base.getDataSize();
+    S32 max_bytes = (base.getMaxBytes() ? base.getMaxBytes() : data_size);
+    bool decoded = decoder.decode(base.getData(), max_bytes, &image_channels, base.mDiscardLevel);
+
+    // set correct channel count early so failed decodes don't miss it...
+    S32 channels = (S32)image_channels - first_channel;
+    channels = llmin(channels, max_channel_count);
+
+    if (!decoded)
+    {
+        // reset the channel count if necessary
+        if (raw_image.getComponents() != channels)
+        {
+            raw_image.resize(raw_image.getWidth(), raw_image.getHeight(), S8(channels));
+        }
+
+        LL_DEBUGS("Texture") << "ERROR -> decodeImpl: failed to decode image!" << LL_ENDL;
+        return true; // done
+    }
+
+    opj_image_t *image = decoder.getImage();
+
+    // Component buffers are allocated in an image width by height buffer.
+    // The image placed in that buffer is ceil(width/2^factor) by
+    // ceil(height/2^factor) and if the factor isn't zero it will be at the
+    // top left of the buffer with black filled in the rest of the pixels.
+    // It is integer math so the formula is written in ceildivpo2.
+    // (Assuming all the components have the same width, height and
+    // factor.)
+    U32 comp_width = image->comps[0].w; // leave this unshifted by 'f' discard factor, the strides are always for the full buffer width
+    U32 f = image->comps[0].factor;
+
+    // do size the texture to the mem we'll acrually use...
+    U32 width = image->comps[0].w;
+    U32 height = image->comps[0].h;
+
+    raw_image.resize(U16(width), U16(height), S8(channels));
+
+    U8 *rawp = raw_image.getData();
+
+    // first_channel is what channel to start copying from
+    // dest is what channel to copy to.  first_channel comes from the
+    // argument, dest always starts writing at channel zero.
+    for (S32 comp = first_channel, dest = 0; comp < first_channel + channels; comp++, dest++)
+    {
+        llassert(image->comps[comp].data);
+        if (image->comps[comp].data)
+        {
+            S32 offset = dest;
+            for (S32 y = (height - 1); y >= 0; y--)
+            {
+                for (S32 x = 0; x < width; x++)
+                {
+                    rawp[offset] = image->comps[comp].data[y*comp_width + x];
+                    offset += channels;
+                }
+            }
+        }
+        else // Some rare OpenJPEG versions have this bug.
+        {
+            LL_DEBUGS("Texture") << "ERROR -> decodeImpl: failed! (OpenJPEG bug)" << LL_ENDL;
+        }
+    }
+
+    base.setDiscardLevel(f);
+
+    return true; // done
+}
 
-	// Copy image data into our raw image format (instead of the separate channel format
-	S32 width = 0;
-	S32 height = 0;
 
-	S32 img_components = image->numcomps;
-	width = image->x1 - image->x0;
-	height = image->y1 - image->y0;
-	base.setSize(width, height, img_components);
+bool LLImageJ2COJ::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, const char* comment_text, F32 encode_time, bool reversible)
+{
+    JPEG2KEncode encode(comment_text, reversible);
+    bool encoded = encode.encode(raw_image, base);
+    if (encoded)
+    {
+        LL_WARNS() << "Openjpeg encoding implementation isn't complete, returning false" << LL_ENDL;
+    }
+    return encoded;
+    //return false;
+}
 
-	/* free image data structure */
-	opj_image_destroy(image);
-	return true;
+bool LLImageJ2COJ::getMetadata(LLImageJ2C &base)
+{
+    JPEG2KDecode decode(0);
+
+    S32 width = 0;
+    S32 height = 0;
+    S32 components = 0;
+    S32 discard_level = 0;
+
+    U32 dataSize = base.getDataSize();
+    U8* data = base.getData();
+    bool header_read = decode.readHeader(data, dataSize, width, height, components, discard_level);
+    if (!header_read)
+    {
+        return false;
+    }
+
+    base.mDiscardLevel = discard_level;
+    base.setSize(width, height, components);
+    return true;
 }
diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp
index bac630f626f3c9f80191d88d21b75e17674675f3..40f7b1e9fbc1edcbbab559b3b87a4d6f89725bc6 100644
--- a/indra/llmath/llvolume.cpp
+++ b/indra/llmath/llvolume.cpp
@@ -2386,7 +2386,25 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size)
 		LL_DEBUGS("MeshStreaming") << "Failed to unzip LLSD blob for LoD with code " << uzip_result << " , will probably fetch from sim again." << LL_ENDL;
 		return false;
 	}
-	
+	return unpackVolumeFacesInternal(mdl);
+}
+
+bool LLVolume::unpackVolumeFaces(U8* in_data, S32 size)
+{
+	//input data is now pointing at a zlib compressed block of LLSD
+	//decompress block
+	LLSD mdl;
+	U32 uzip_result = LLUZipHelper::unzip_llsd(mdl, in_data, size);
+	if (uzip_result != LLUZipHelper::ZR_OK)
+	{
+		LL_DEBUGS("MeshStreaming") << "Failed to unzip LLSD blob for LoD with code " << uzip_result << " , will probably fetch from sim again." << LL_ENDL;
+		return false;
+	}
+	return unpackVolumeFacesInternal(mdl);
+}
+
+bool LLVolume::unpackVolumeFacesInternal(const LLSD& mdl)
+{
 	{
 		U32 face_count = mdl.size();
 
@@ -5013,6 +5031,17 @@ void LLVolumeFace::optimize(F32 angle_cutoff)
 	{
 		U16 index = mIndices[i];
 
+        if (index >= mNumVertices)
+        {
+            // invalid index
+            // replace with a valid index to avoid crashes
+            index = mNumVertices - 1;
+            mIndices[i] = index;
+
+            // Needs better logging
+            LL_DEBUGS_ONCE("LLVOLUME") << "Invalid index, substituting" << LL_ENDL;
+        }
+
 		LLVolumeFace::VertexData cv;
 		getVertexData(index, cv);
 		
@@ -5385,6 +5414,17 @@ bool LLVolumeFace::cacheOptimize()
             U16 idx = mIndices[i];
             U32 tri_idx = i / 3;
 
+            if (idx >= mNumVertices)
+            {
+                // invalid index
+                // replace with a valid index to avoid crashes
+                idx = mNumVertices - 1;
+                mIndices[i] = idx;
+
+                // Needs better logging
+                LL_DEBUGS_ONCE("LLVOLUME") << "Invalid index, substituting" << LL_ENDL;
+            }
+
             vertex_data[idx].mTriangles.push_back(&(triangle_data[tri_idx]));
             vertex_data[idx].mIdx = idx;
             triangle_data[tri_idx].mVertex[i % 3] = &(vertex_data[idx]);
diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h
index 3ccaed47f13eabba83217368f503335157877f53..150924162353c8e5e7d529c092070c37926deadd 100644
--- a/indra/llmath/llvolume.h
+++ b/indra/llmath/llvolume.h
@@ -1101,8 +1101,12 @@ class LLVolume : public LLRefCount
 	BOOL generate();
 	void createVolumeFaces();
 public:
-	virtual bool unpackVolumeFaces(std::istream& is, S32 size);
+	bool unpackVolumeFaces(std::istream& is, S32 size);
+	bool unpackVolumeFaces(U8* in_data, S32 size);
+private:
+	bool unpackVolumeFacesInternal(const LLSD& mdl);
 
+public:
 	virtual void setMeshAssetLoaded(BOOL loaded);
 	virtual BOOL isMeshAssetLoaded();
 
diff --git a/indra/llmessage/lldatapacker.cpp b/indra/llmessage/lldatapacker.cpp
index b6adc102d2149d788a25e57f47a1c03025a359b9..9f7768f78ec6f13c7f4fdc75b389ac11f72f9ed8 100644
--- a/indra/llmessage/lldatapacker.cpp
+++ b/indra/llmessage/lldatapacker.cpp
@@ -116,9 +116,8 @@ BOOL LLDataPacker::packFixed(const F32 value, const char *name,
 BOOL LLDataPacker::unpackFixed(F32 &value, const char *name,
 							   const BOOL is_signed, const U32 int_bits, const U32 frac_bits)
 {
-	//BOOL success = TRUE;
+	BOOL success = TRUE;
 	//LL_INFOS() << "unpackFixed:" << name << " int:" << int_bits << " frac:" << frac_bits << LL_ENDL;
-	BOOL ok = FALSE;
 	S32 unsigned_bits = int_bits + frac_bits;
 	S32 total_bits = unsigned_bits;
 
@@ -134,19 +133,19 @@ BOOL LLDataPacker::unpackFixed(F32 &value, const char *name,
 	if (total_bits <= 8)
 	{
 		U8 fixed_8;
-		ok = unpackU8(fixed_8, name);
+		success = unpackU8(fixed_8, name);
 		fixed_val = (F32)fixed_8;
 	}
 	else if (total_bits <= 16)
 	{
 		U16 fixed_16;
-		ok = unpackU16(fixed_16, name);
+		success = unpackU16(fixed_16, name);
 		fixed_val = (F32)fixed_16;
 	}
 	else if (total_bits <= 31)
 	{
 		U32 fixed_32;
-		ok = unpackU32(fixed_32, name);
+		success = unpackU32(fixed_32, name);
 		fixed_val = (F32)fixed_32;
 	}
 	else
@@ -164,7 +163,7 @@ BOOL LLDataPacker::unpackFixed(F32 &value, const char *name,
 	}
 	value = fixed_val;
 	//LL_INFOS() << "Value: " << value << LL_ENDL;
-	return ok;
+	return success;
 }
 
 BOOL LLDataPacker::unpackU16s(U16 *values, S32 count, const char *name)
@@ -238,37 +237,43 @@ BOOL LLDataPacker::unpackUUIDs(LLUUID *values, S32 count, const char *name)
 
 BOOL LLDataPackerBinaryBuffer::packString(const std::string& value, const char *name)
 {
-	BOOL success = TRUE;
 	S32 length = value.length()+1;
 
-	success &= verifyLength(length, name);
+	if (!verifyLength(length, name))
+	{
+		return FALSE;
+	}
 
 	if (mWriteEnabled) 
 	{
 		htolememcpy(mCurBufferp, value.c_str(), MVT_VARIABLE, length);  
 	}
 	mCurBufferp += length;
-	return success;
+	return TRUE;
 }
 
 
 BOOL LLDataPackerBinaryBuffer::unpackString(std::string& value, const char *name)
 {
-	BOOL success = TRUE;
 	S32 length = (S32)strlen((char *)mCurBufferp) + 1; /*Flawfinder: ignore*/
 
-	success &= verifyLength(length, name);
+	if (!verifyLength(length, name))
+	{
+		return FALSE;
+	}
 
 	value = std::string((char*)mCurBufferp); // We already assume NULL termination calling strlen()
 	
 	mCurBufferp += length;
-	return success;
+	return TRUE;
 }
 
 BOOL LLDataPackerBinaryBuffer::packBinaryData(const U8 *value, S32 size, const char *name)
 {
-	BOOL success = TRUE;
-	success &= verifyLength(size + 4, name);
+	if (!verifyLength(size + 4, name))
+	{
+		return FALSE;
+	}
 
 	if (mWriteEnabled) 
 	{ 
@@ -280,102 +285,117 @@ BOOL LLDataPackerBinaryBuffer::packBinaryData(const U8 *value, S32 size, const c
 		htolememcpy(mCurBufferp, value, MVT_VARIABLE, size);  
 	}
 	mCurBufferp += size;
-	return success;
+	return TRUE;
 }
 
 
 BOOL LLDataPackerBinaryBuffer::unpackBinaryData(U8 *value, S32 &size, const char *name)
 {
-	BOOL success = TRUE;
-	success &= verifyLength(4, name);
-	htolememcpy(&size, mCurBufferp, MVT_S32, 4);
-	mCurBufferp += 4;
-	success &= verifyLength(size, name);
-	if (success)
+	if (!verifyLength(4, name))
 	{
-		htolememcpy(value, mCurBufferp, MVT_VARIABLE, size);
-		mCurBufferp += size;
+		LL_WARNS() << "LLDataPackerBinaryBuffer::unpackBinaryData would unpack invalid data, aborting!" << LL_ENDL;
+		return FALSE;
 	}
-	else
+
+	htolememcpy(&size, mCurBufferp, MVT_S32, 4);
+	mCurBufferp += 4;
+
+	if (!verifyLength(size, name))
 	{
 		LL_WARNS() << "LLDataPackerBinaryBuffer::unpackBinaryData would unpack invalid data, aborting!" << LL_ENDL;
-		success = FALSE;
+		return FALSE;
 	}
-	return success;
+
+	htolememcpy(value, mCurBufferp, MVT_VARIABLE, size);
+	mCurBufferp += size;
+
+	return TRUE;
 }
 
 
 BOOL LLDataPackerBinaryBuffer::packBinaryDataFixed(const U8 *value, S32 size, const char *name)
 {
-	BOOL success = TRUE;
-	success &= verifyLength(size, name);
+	if (!verifyLength(size, name))
+	{
+		return FALSE;
+	}
 
 	if (mWriteEnabled) 
 	{ 
 		htolememcpy(mCurBufferp, value, MVT_VARIABLE, size);  
 	}
 	mCurBufferp += size;
-	return success;
+	return TRUE;
 }
 
 
 BOOL LLDataPackerBinaryBuffer::unpackBinaryDataFixed(U8 *value, S32 size, const char *name)
 {
-	BOOL success = TRUE;
-	success &= verifyLength(size, name);
+	if (!verifyLength(size, name))
+	{
+		return FALSE;
+	}
 	htolememcpy(value, mCurBufferp, MVT_VARIABLE, size);
 	mCurBufferp += size;
-	return success;
+	return TRUE;
 }
 
 
 BOOL LLDataPackerBinaryBuffer::packU8(const U8 value, const char *name)
 {
-	BOOL success = TRUE;
-	success &= verifyLength(sizeof(U8), name);
+	if (!verifyLength(sizeof(U8), name))
+	{
+		return FALSE;
+	}
 
 	if (mWriteEnabled) 
 	{
 		*mCurBufferp = value;
 	}
 	mCurBufferp++;
-	return success;
+	return TRUE;
 }
 
 
 BOOL LLDataPackerBinaryBuffer::unpackU8(U8 &value, const char *name)
 {
-	BOOL success = TRUE;
-	success &= verifyLength(sizeof(U8), name);
+	if (!verifyLength(sizeof(U8), name))
+	{
+		return FALSE;
+	}
 
 	value = *mCurBufferp;
 	mCurBufferp++;
-	return success;
+	return TRUE;
 }
 
 
 BOOL LLDataPackerBinaryBuffer::packU16(const U16 value, const char *name)
 {
-	BOOL success = TRUE;
-	success &= verifyLength(sizeof(U16), name);
+	if (!verifyLength(sizeof(U16), name))
+	{
+		return FALSE;
+	}
 
 	if (mWriteEnabled) 
 	{ 
 		htolememcpy(mCurBufferp, &value, MVT_U16, 2);  
 	}
 	mCurBufferp += 2;
-	return success;
+	return TRUE;
 }
 
 
 BOOL LLDataPackerBinaryBuffer::unpackU16(U16 &value, const char *name)
 {
-	BOOL success = TRUE;
-	success &= verifyLength(sizeof(U16), name);
+	if (!verifyLength(sizeof(U16), name))
+	{
+		return FALSE;
+	}
 
 	htolememcpy(&value, mCurBufferp, MVT_U16, 2);
 	mCurBufferp += 2;
-	return success;
+	return TRUE;
 }
 
 BOOL LLDataPackerBinaryBuffer::packS16(const S16 value, const char *name)
@@ -404,134 +424,156 @@ BOOL LLDataPackerBinaryBuffer::unpackS16(S16 &value, const char *name)
 
 BOOL LLDataPackerBinaryBuffer::packU32(const U32 value, const char *name)
 {
-	BOOL success = TRUE;
-	success &= verifyLength(sizeof(U32), name);
+	if (!verifyLength(sizeof(U32), name))
+	{
+		return FALSE;
+	}
 
 	if (mWriteEnabled) 
 	{ 
 		htolememcpy(mCurBufferp, &value, MVT_U32, 4);  
 	}
 	mCurBufferp += 4;
-	return success;
+	return TRUE;
 }
 
 
 BOOL LLDataPackerBinaryBuffer::unpackU32(U32 &value, const char *name)
 {
-	BOOL success = TRUE;
-	success &= verifyLength(sizeof(U32), name);
+	if (!verifyLength(sizeof(U32), name))
+	{
+		return FALSE;
+	}
 
 	htolememcpy(&value, mCurBufferp, MVT_U32, 4);
 	mCurBufferp += 4;
-	return success;
+	return TRUE;
 }
 
 
 BOOL LLDataPackerBinaryBuffer::packS32(const S32 value, const char *name)
 {
-	BOOL success = TRUE;
-	success &= verifyLength(sizeof(S32), name);
+	if (!verifyLength(sizeof(S32), name))
+	{
+		return FALSE;
+	}
 
 	if (mWriteEnabled) 
 	{ 
 		htolememcpy(mCurBufferp, &value, MVT_S32, 4); 
 	}
 	mCurBufferp += 4;
-	return success;
+	return TRUE;
 }
 
 
 BOOL LLDataPackerBinaryBuffer::unpackS32(S32 &value, const char *name)
 {
-	BOOL success = TRUE;
-	success &= verifyLength(sizeof(S32), name);
+	if(!verifyLength(sizeof(S32), name))
+	{
+		return FALSE;
+	}
 
 	htolememcpy(&value, mCurBufferp, MVT_S32, 4);
 	mCurBufferp += 4;
-	return success;
+	return TRUE;
 }
 
 
 BOOL LLDataPackerBinaryBuffer::packF32(const F32 value, const char *name)
 {
-	BOOL success = TRUE;
-	success &= verifyLength(sizeof(F32), name);
+	if (!verifyLength(sizeof(F32), name))
+	{
+		return FALSE;
+	}
 
 	if (mWriteEnabled) 
 	{ 
 		htolememcpy(mCurBufferp, &value, MVT_F32, 4); 
 	}
 	mCurBufferp += 4;
-	return success;
+	return TRUE;
 }
 
 
 BOOL LLDataPackerBinaryBuffer::unpackF32(F32 &value, const char *name)
 {
-	BOOL success = TRUE;
-	success &= verifyLength(sizeof(F32), name);
+	if (!verifyLength(sizeof(F32), name))
+	{
+		return FALSE;
+	}
 
 	htolememcpy(&value, mCurBufferp, MVT_F32, 4);
 	mCurBufferp += 4;
-	return success;
+	return TRUE;
 }
 
 
 BOOL LLDataPackerBinaryBuffer::packColor4(const LLColor4 &value, const char *name)
 {
-	BOOL success = TRUE;
-	success &= verifyLength(16, name);
+	if (!verifyLength(16, name))
+	{
+		return FALSE;
+	}
 
 	if (mWriteEnabled) 
 	{ 
 		htolememcpy(mCurBufferp, value.mV, MVT_LLVector4, 16); 
 	}
 	mCurBufferp += 16;
-	return success;
+	return TRUE;
 }
 
 
 BOOL LLDataPackerBinaryBuffer::unpackColor4(LLColor4 &value, const char *name)
 {
-	BOOL success = TRUE;
-	success &= verifyLength(16, name);
+	if (!verifyLength(16, name))
+	{
+		return FALSE;
+	}
 
 	htolememcpy(value.mV, mCurBufferp, MVT_LLVector4, 16);
 	mCurBufferp += 16;
-	return success;
+	return TRUE;
 }
 
 
 BOOL LLDataPackerBinaryBuffer::packColor4U(const LLColor4U &value, const char *name)
 {
-	BOOL success = TRUE;
-	success &= verifyLength(4, name);
+	if (!verifyLength(4, name))
+	{
+		return FALSE;
+	}
 
 	if (mWriteEnabled) 
 	{ 
 		htolememcpy(mCurBufferp, value.mV, MVT_VARIABLE, 4);  
 	}
 	mCurBufferp += 4;
-	return success;
+	return TRUE;
 }
 
 
 BOOL LLDataPackerBinaryBuffer::unpackColor4U(LLColor4U &value, const char *name)
 {
-	BOOL success = TRUE;
-	success &= verifyLength(4, name);
+	if (!verifyLength(4, name))
+	{
+		return FALSE;
+	}
 
 	htolememcpy(value.mV, mCurBufferp, MVT_VARIABLE, 4);
 	mCurBufferp += 4;
-	return success;
+	return TRUE;
 }
 
 
 
 BOOL LLDataPackerBinaryBuffer::packVector2(const LLVector2 &value, const char *name)
 {
-	BOOL success = TRUE;
-	success &= verifyLength(8, name);
+	if (!verifyLength(8, name))
+	{
+		return FALSE;
+	}
 
 	if (mWriteEnabled) 
 	{ 
@@ -539,92 +581,106 @@ BOOL LLDataPackerBinaryBuffer::packVector2(const LLVector2 &value, const char *n
 		htolememcpy(mCurBufferp+4, &value.mV[1], MVT_F32, 4);  
 	}
 	mCurBufferp += 8;
-	return success;
+	return TRUE;
 }
 
 
 BOOL LLDataPackerBinaryBuffer::unpackVector2(LLVector2 &value, const char *name)
 {
-	BOOL success = TRUE;
-	success &= verifyLength(8, name);
+	if (!verifyLength(8, name))
+	{
+		return FALSE;
+	}
 
 	htolememcpy(&value.mV[0], mCurBufferp, MVT_F32, 4);
 	htolememcpy(&value.mV[1], mCurBufferp+4, MVT_F32, 4);
 	mCurBufferp += 8;
-	return success;
+	return TRUE;
 }
 
 
 BOOL LLDataPackerBinaryBuffer::packVector3(const LLVector3 &value, const char *name)
 {
-	BOOL success = TRUE;
-	success &= verifyLength(12, name);
+	if (!verifyLength(12, name))
+	{
+		return FALSE;
+	}
 
 	if (mWriteEnabled) 
 	{ 
 		htolememcpy(mCurBufferp, value.mV, MVT_LLVector3, 12);  
 	}
 	mCurBufferp += 12;
-	return success;
+	return TRUE;
 }
 
 
 BOOL LLDataPackerBinaryBuffer::unpackVector3(LLVector3 &value, const char *name)
 {
-	BOOL success = TRUE;
-	success &= verifyLength(12, name);
+	if (!verifyLength(12, name))
+	{
+		return FALSE;
+	}
 
 	htolememcpy(value.mV, mCurBufferp, MVT_LLVector3, 12);
 	mCurBufferp += 12;
-	return success;
+	return TRUE;
 }
 
 BOOL LLDataPackerBinaryBuffer::packVector4(const LLVector4 &value, const char *name)
 {
-	BOOL success = TRUE;
-	success &= verifyLength(16, name);
+	if (!verifyLength(16, name))
+	{
+		return FALSE;
+	}
 
 	if (mWriteEnabled) 
 	{ 
 		htolememcpy(mCurBufferp, value.mV, MVT_LLVector4, 16);  
 	}
 	mCurBufferp += 16;
-	return success;
+	return TRUE;
 }
 
 
 BOOL LLDataPackerBinaryBuffer::unpackVector4(LLVector4 &value, const char *name)
 {
-	BOOL success = TRUE;
-	success &= verifyLength(16, name);
+	if (!verifyLength(16, name))
+	{
+		return FALSE;
+	}
 
 	htolememcpy(value.mV, mCurBufferp, MVT_LLVector4, 16);
 	mCurBufferp += 16;
-	return success;
+	return TRUE;
 }
 
 BOOL LLDataPackerBinaryBuffer::packUUID(const LLUUID &value, const char *name)
 {
-	BOOL success = TRUE;
-	success &= verifyLength(16, name);
+	if (!verifyLength(16, name))
+	{
+		return FALSE;
+	}
 
 	if (mWriteEnabled) 
 	{ 
 		htolememcpy(mCurBufferp, value.mData, MVT_LLUUID, 16);  
 	}
 	mCurBufferp += 16;
-	return success;
+	return TRUE;
 }
 
 
 BOOL LLDataPackerBinaryBuffer::unpackUUID(LLUUID &value, const char *name)
 {
-	BOOL success = TRUE;
-	success &= verifyLength(16, name);
+	if (!verifyLength(16, name))
+	{
+		return FALSE;
+	}
 
 	htolememcpy(value.mData, mCurBufferp, MVT_LLUUID, 16);
 	mCurBufferp += 16;
-	return success;
+	return TRUE;
 }
 
 const LLDataPackerBinaryBuffer&	LLDataPackerBinaryBuffer::operator=(const LLDataPackerBinaryBuffer &a)
@@ -698,15 +754,13 @@ BOOL LLDataPackerAsciiBuffer::packString(const std::string& value, const char *n
 
 BOOL LLDataPackerAsciiBuffer::unpackString(std::string& value, const char *name)
 {
-	BOOL success = TRUE;
 	char valuestr[DP_BUFSIZE]; /*Flawfinder: ignore*/
-	BOOL res = getValueStr(name, valuestr, DP_BUFSIZE); // NULL terminated
-	if (!res) // 
+	if (!getValueStr(name, valuestr, DP_BUFSIZE))  // NULL terminated
 	{
 		return FALSE;
 	}
 	value = valuestr;
-	return success;
+	return TRUE;
 }
 
 
diff --git a/indra/llmessage/message_prehash.cpp b/indra/llmessage/message_prehash.cpp
index 35dcbe383682fbd9c3249234a06d0689339444c2..57ea954054bcfadfc20c95c3657918a6eb976a8e 100644
--- a/indra/llmessage/message_prehash.cpp
+++ b/indra/llmessage/message_prehash.cpp
@@ -666,7 +666,6 @@ char const* const _PREHASH_GroupRolesCount = LLMessageStringTable::getInstance()
 char const* const _PREHASH_SimulatorBlock = LLMessageStringTable::getInstance()->getString("SimulatorBlock");
 char const* const _PREHASH_GroupID = LLMessageStringTable::getInstance()->getString("GroupID");
 char const* const _PREHASH_AgentVel = LLMessageStringTable::getInstance()->getString("AgentVel");
-char const* const _PREHASH_RequestImage = LLMessageStringTable::getInstance()->getString("RequestImage");
 char const* const _PREHASH_NetStats = LLMessageStringTable::getInstance()->getString("NetStats");
 char const* const _PREHASH_AgentPos = LLMessageStringTable::getInstance()->getString("AgentPos");
 char const* const _PREHASH_AgentSit = LLMessageStringTable::getInstance()->getString("AgentSit");
@@ -1047,7 +1046,6 @@ char const* const _PREHASH_SortOrder = LLMessageStringTable::getInstance()->getS
 char const* const _PREHASH_Hunter = LLMessageStringTable::getInstance()->getString("Hunter");
 char const* const _PREHASH_SunAngVelocity = LLMessageStringTable::getInstance()->getString("SunAngVelocity");
 char const* const _PREHASH_BinaryBucket = LLMessageStringTable::getInstance()->getString("BinaryBucket");
-char const* const _PREHASH_ImagePacket = LLMessageStringTable::getInstance()->getString("ImagePacket");
 char const* const _PREHASH_StartGroupProposal = LLMessageStringTable::getInstance()->getString("StartGroupProposal");
 char const* const _PREHASH_EnergyLevel = LLMessageStringTable::getInstance()->getString("EnergyLevel");
 char const* const _PREHASH_PriceForListing = LLMessageStringTable::getInstance()->getString("PriceForListing");
@@ -1236,7 +1234,6 @@ char const* const _PREHASH_ForceScriptControlRelease = LLMessageStringTable::get
 char const* const _PREHASH_ParcelRelease = LLMessageStringTable::getInstance()->getString("ParcelRelease");
 char const* const _PREHASH_VFileType = LLMessageStringTable::getInstance()->getString("VFileType");
 char const* const _PREHASH_EjectGroupMemberReply = LLMessageStringTable::getInstance()->getString("EjectGroupMemberReply");
-char const* const _PREHASH_ImageData = LLMessageStringTable::getInstance()->getString("ImageData");
 char const* const _PREHASH_SimulatorViewerTimeMessage = LLMessageStringTable::getInstance()->getString("SimulatorViewerTimeMessage");
 char const* const _PREHASH_Rotation = LLMessageStringTable::getInstance()->getString("Rotation");
 char const* const _PREHASH_Selection = LLMessageStringTable::getInstance()->getString("Selection");
diff --git a/indra/llmessage/message_prehash.h b/indra/llmessage/message_prehash.h
index 3015f438b5e98a47e100f316b21bf9458b635051..572dadd40820447cc348a15320b95aa50de3d6d2 100644
--- a/indra/llmessage/message_prehash.h
+++ b/indra/llmessage/message_prehash.h
@@ -666,7 +666,6 @@ extern char const* const _PREHASH_GroupRolesCount;
 extern char const* const _PREHASH_SimulatorBlock;
 extern char const* const _PREHASH_GroupID;
 extern char const* const _PREHASH_AgentVel;
-extern char const* const _PREHASH_RequestImage;
 extern char const* const _PREHASH_NetStats;
 extern char const* const _PREHASH_AgentPos;
 extern char const* const _PREHASH_AgentSit;
@@ -1047,7 +1046,6 @@ extern char const* const _PREHASH_SortOrder;
 extern char const* const _PREHASH_Hunter;
 extern char const* const _PREHASH_SunAngVelocity;
 extern char const* const _PREHASH_BinaryBucket;
-extern char const* const _PREHASH_ImagePacket;
 extern char const* const _PREHASH_StartGroupProposal;
 extern char const* const _PREHASH_EnergyLevel;
 extern char const* const _PREHASH_PriceForListing;
diff --git a/indra/llmessage/tests/llcoproceduremanager_test.cpp b/indra/llmessage/tests/llcoproceduremanager_test.cpp
index 6424117ef321b32f959013ac955db9ed6d213ac7..a1a4ce05208fb6d014de798bc847e5a56917bb86 100644
--- a/indra/llmessage/tests/llcoproceduremanager_test.cpp
+++ b/indra/llmessage/tests/llcoproceduremanager_test.cpp
@@ -92,7 +92,7 @@ namespace tut
         Sync sync;
         int foo = 0;
         LLCoprocedureManager::instance().initializePool("PoolName");
-        LLUUID queueId = LLCoprocedureManager::instance().enqueueCoprocedure("PoolName", "ProcName",
+        LLCoprocedureManager::instance().enqueueCoprocedure("PoolName", "ProcName",
             [&foo, &sync] (LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t & ptr, const LLUUID & id) {
                 sync.bump();
                 foo = 1;
diff --git a/indra/llprimitive/lldaeloader.cpp b/indra/llprimitive/lldaeloader.cpp
index 68654486a4088fa07b24d13d97434ae3c63cf942..752a850d42b6c5b9e6443165cda84aad01db4778 100644
--- a/indra/llprimitive/lldaeloader.cpp
+++ b/indra/llprimitive/lldaeloader.cpp
@@ -330,7 +330,10 @@ LLModel::EModelStatus load_face_from_dom_triangles(
 			// VFExtents change
 			face.mExtents[0].set(v[0], v[1], v[2]);
 			face.mExtents[1].set(v[0], v[1], v[2]);
-			point_map.clear();
+
+            verts.clear();
+            indices.clear();
+            point_map.clear();
 		}
 	}
 
diff --git a/indra/llprimitive/llmodel.cpp b/indra/llprimitive/llmodel.cpp
index 805af552996e68f9418d90ab74491210378bfd1c..765a8cda22e96ba0c3baca831c5ce89cc3bdf73b 100644
--- a/indra/llprimitive/llmodel.cpp
+++ b/indra/llprimitive/llmodel.cpp
@@ -1386,6 +1386,16 @@ LLMeshSkinInfo::LLMeshSkinInfo(LLSD& skin):
 	fromLLSD(skin);
 }
 
+LLMeshSkinInfo::LLMeshSkinInfo(const LLUUID& mesh_id, LLSD& skin) :
+	mMeshID(mesh_id),
+	mPelvisOffset(0.0),
+	mLockScaleIfJointPosition(false),
+	mInvalidJointsScrubbed(false),
+	mJointNumsInitialized(false)
+{
+	fromLLSD(skin);
+}
+
 void LLMeshSkinInfo::fromLLSD(LLSD& skin)
 {
 	if (skin.has("joint_names"))
diff --git a/indra/llprimitive/llmodel.h b/indra/llprimitive/llmodel.h
index a6ab96ab18400dcfd57c02064a1bc1eb6bbbdcdf..4505d6b3b993b90cf6162bcbe943420e2fd28321 100644
--- a/indra/llprimitive/llmodel.h
+++ b/indra/llprimitive/llmodel.h
@@ -41,12 +41,13 @@ class domMesh;
 #define MAX_MODEL_FACES 8
 
 LL_ALIGN_PREFIX(16)
-class LLMeshSkinInfo 
+class LLMeshSkinInfo : public LLRefCount
 {
     LL_ALIGN_NEW
 public:
 	LLMeshSkinInfo();
 	LLMeshSkinInfo(LLSD& data);
+	LLMeshSkinInfo(const LLUUID& mesh_id, LLSD& data);
 	void fromLLSD(LLSD& data);
 	LLSD asLLSD(bool include_joints, bool lock_scale_if_joint_position) const;
     void updateHash();
@@ -57,6 +58,8 @@ class LLMeshSkinInfo
     mutable std::vector<S32> mJointNums;
     typedef std::vector<LLMatrix4a, boost::alignment::aligned_allocator<LLMatrix4a, 16>> matrix_list_t;
 	matrix_list_t mInvBindMatrix;
+
+    // bones/joints position overrides
 	matrix_list_t mAlternateBindMatrix;
 
 	LL_ALIGN_16(LLMatrix4a mBindShapeMatrix);
diff --git a/indra/llui/llchat.h b/indra/llui/llchat.h
index c39e44200ce1812742eeed07c89bfba78a7f258e..b4fd5f60aa718eda496feb1a93f5564222b3d302 100644
--- a/indra/llui/llchat.h
+++ b/indra/llui/llchat.h
@@ -38,7 +38,8 @@ typedef enum e_chat_source_type
 	CHAT_SOURCE_AGENT = 1,
 	CHAT_SOURCE_OBJECT = 2,
 	CHAT_SOURCE_TELEPORT = 3,
-	CHAT_SOURCE_UNKNOWN = 4
+	CHAT_SOURCE_UNKNOWN = 4,
+	CHAT_SOURCE_REGION = 5,
 } EChatSourceType;
 
 typedef enum e_chat_type
diff --git a/indra/llui/llcheckboxctrl.cpp b/indra/llui/llcheckboxctrl.cpp
index 08da599ef24c480aa94461e64e1361184540ccff..362fe0c19e1ab102b45c99e5b7816e487a0cd904 100644
--- a/indra/llui/llcheckboxctrl.cpp
+++ b/indra/llui/llcheckboxctrl.cpp
@@ -203,11 +203,9 @@ void LLCheckBoxCtrl::reshape(S32 width, S32 height, BOOL called_from_parent)
     // it will work fine in case of decrease of space, but if we get more space or text
     // becomes longer, label will fail to grow so reinit label's dimentions.
     
-    static LLUICachedControl<S32> llcheckboxctrl_hpad("UICheckboxctrlHPad", 0);
     LLRect label_rect = mLabel->getRect();
-    S32 new_width = getRect().getWidth() - label_rect.mLeft - llcheckboxctrl_hpad;
-    label_rect.mRight = label_rect.mLeft + new_width;
-    mLabel->setRect(label_rect);
+    S32 new_width = rect.getWidth() - label_rect.mLeft;
+    mLabel->reshape(new_width, label_rect.getHeight(), TRUE);
 
 	S32 label_top = label_rect.mTop;
 	mLabel->reshapeToFitText(TRUE);
diff --git a/indra/llui/llflatlistview.cpp b/indra/llui/llflatlistview.cpp
index 5e00bf7f4501bfa9389f2f722af0f53465da1f88..b13e7389cc11438bb85e66708f1b0ae14b0be59f 100644
--- a/indra/llui/llflatlistview.cpp
+++ b/indra/llui/llflatlistview.cpp
@@ -505,6 +505,17 @@ LLFlatListView::LLFlatListView(const LLFlatListView::Params& p)
 	}
 };
 
+LLFlatListView::~LLFlatListView()
+{
+	for (pairs_iterator_t it = mItemPairs.begin(); it != mItemPairs.end(); ++it)
+	{
+		mItemsPanel->removeChild((*it)->first);
+		(*it)->first->die();
+		delete *it;
+	}
+	mItemPairs.clear();
+}
+
 // virtual
 void LLFlatListView::draw()
 {
diff --git a/indra/llui/llflatlistview.h b/indra/llui/llflatlistview.h
index 230ea200d888545ecee96e0a52f30f1fa68e6487..d47c1cf3332204de198085efeeab357765e52ee8 100644
--- a/indra/llui/llflatlistview.h
+++ b/indra/llui/llflatlistview.h
@@ -299,6 +299,7 @@ class LLFlatListView : public LLScrollContainer, public LLEditMenuHandler
 
 	virtual S32	notify(const LLSD& info) ;
 
+	virtual ~LLFlatListView();
 protected:
 
 	/** Pairs LLpanel representing a single item LLPanel and LLSD associated with it */
diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp
index ea2ca68e47a7968f33c37da46bd767b335a4c2d2..e1869e8125da50b2b5b3f7153f5d34767f155914 100644
--- a/indra/llui/llfolderview.cpp
+++ b/indra/llui/llfolderview.cpp
@@ -163,6 +163,7 @@ LLFolderView::LLFolderView(const Params& p)
 :	LLFolderViewFolder(p),
 	mScrollContainer( NULL ),
 	mPopupMenuHandle(),
+	mMenuFileName(p.options_menu),
 	mAllowMultiSelect(p.allow_multiselect),
 	mAllowDrag(p.allow_drag),
 	mShowEmptyMessage(p.show_empty_message),
@@ -182,6 +183,7 @@ LLFolderView::LLFolderView(const Params& p)
 	mMinWidth(0),
 	mDragAndDropThisFrame(FALSE),
 	mCallbackRegistrar(NULL),
+	mEnableRegistrar(NULL),
 	mUseEllipses(p.use_ellipses),
 	mDraggingOverItem(NULL),
 	mStatusTextBox(NULL),
@@ -244,17 +246,6 @@ LLFolderView::LLFolderView(const Params& p)
 	mStatusTextBox->setFollowsTop();
 	addChild(mStatusTextBox);
 
-
-	// make the popup menu available
-	llassert(LLMenuGL::sMenuContainer != NULL);
-	LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>(p.options_menu, LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance());
-	if (!menu)
-	{
-		menu = LLUICtrlFactory::getDefaultWidget<LLMenuGL>("inventory_menu");
-	}
-	menu->setBackgroundColor(LLUIColorTable::instance().getColor("MenuPopupBgColor"));
-	mPopupMenuHandle = menu->getHandle();
-
 	mViewModelItem->openItem();
 
 	mAreChildrenInited = true; // root folder is a special case due to not being loaded normally, assume that it's inited.
@@ -276,6 +267,7 @@ LLFolderView::~LLFolderView( void )
 	mStatusTextBox = NULL;
 
 	if (mPopupMenuHandle.get()) mPopupMenuHandle.get()->die();
+	mPopupMenuHandle.markDead();
 
 	mAutoOpenItems.removeAllNodes();
 	clearSelection();
@@ -1438,22 +1430,56 @@ BOOL LLFolderView::handleRightMouseDown( S32 x, S32 y, MASK mask )
 	BOOL handled = childrenHandleRightMouseDown(x, y, mask) != NULL;
 	S32 count = mSelectedItems.size();
 
-	LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get();
+	LLMenuGL* menu = static_cast<LLMenuGL*>(mPopupMenuHandle.get());
+	if (!menu)
+	{
+		if (mCallbackRegistrar)
+		{
+			mCallbackRegistrar->pushScope();
+		}
+		if (mEnableRegistrar)
+		{
+			mEnableRegistrar->pushScope();
+		}
+		llassert(LLMenuGL::sMenuContainer != NULL);
+		menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>(mMenuFileName, LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance());
+		if (!menu)
+		{
+			menu = LLUICtrlFactory::getDefaultWidget<LLMenuGL>("inventory_menu");
+		}
+		menu->setBackgroundColor(LLUIColorTable::instance().getColor("MenuPopupBgColor"));
+		mPopupMenuHandle = menu->getHandle();
+		if (mEnableRegistrar)
+		{
+			mEnableRegistrar->popScope();
+		}
+		if (mCallbackRegistrar)
+		{
+			mCallbackRegistrar->popScope();
+		}
+	}
 	bool hide_folder_menu = mSuppressFolderMenu && isFolderSelected();
-	if ((handled
-		&& ( count > 0 && (hasVisibleChildren()) ) // show menu only if selected items are visible
-		&& menu ) &&
+	if (menu && (handled
+		&& ( count > 0 && (hasVisibleChildren()) )) && // show menu only if selected items are visible
 		!hide_folder_menu)
 	{
 		if (mCallbackRegistrar)
         {
 			mCallbackRegistrar->pushScope();
         }
+		if (mEnableRegistrar)
+		{
+			mEnableRegistrar->pushScope();
+		}
 
 		updateMenuOptions(menu);
 	   
 		menu->updateParent(LLMenuGL::sMenuContainer);
 		LLMenuGL::showPopup(this, menu, x, y);
+		if (mEnableRegistrar)
+		{
+			mEnableRegistrar->popScope();
+		}
 		if (mCallbackRegistrar)
         {
 			mCallbackRegistrar->popScope();
@@ -1531,7 +1557,7 @@ void LLFolderView::deleteAllChildren()
 {
 	closeRenamer();
 	if (mPopupMenuHandle.get()) mPopupMenuHandle.get()->die();
-	mPopupMenuHandle = LLHandle<LLView>();
+	mPopupMenuHandle.markDead();
 	mScrollContainer = NULL;
 	mRenameItem = NULL;
 	mRenamer = NULL;
diff --git a/indra/llui/llfolderview.h b/indra/llui/llfolderview.h
index 6bb5e6c02e0d4a46f3c4260fb2583a4c960deafe..7dfa04828a02d1f4658b62a80dc16df1733f4b0a 100644
--- a/indra/llui/llfolderview.h
+++ b/indra/llui/llfolderview.h
@@ -235,6 +235,7 @@ class LLFolderView : public LLFolderViewFolder, public LLEditMenuHandler
 	bool showItemLinkOverlays() { return mShowItemLinkOverlays; }
 
 	void setCallbackRegistrar(LLUICtrl::CommitCallbackRegistry::ScopedRegistrar* registrar) { mCallbackRegistrar = registrar; }
+	void setEnableRegistrar(LLUICtrl::EnableCallbackRegistry::ScopedRegistrar* registrar) { mEnableRegistrar = registrar; }
 
 	LLPanel* getParentPanel() { return mParentPanel.get(); }
 	// DEBUG only
@@ -272,6 +273,7 @@ class LLFolderView : public LLFolderViewFolder, public LLEditMenuHandler
 
 protected:
 	LLHandle<LLView>					mPopupMenuHandle;
+	std::string						mMenuFileName;
 	
 	selected_items_t				mSelectedItems;
 	bool							mKeyboardSelection,
@@ -327,6 +329,7 @@ class LLFolderView : public LLFolderViewFolder, public LLEditMenuHandler
 	LLFolderViewItem*				mDraggingOverItem; // See EXT-719
 
 	LLUICtrl::CommitCallbackRegistry::ScopedRegistrar* mCallbackRegistrar;
+	LLUICtrl::EnableCallbackRegistry::ScopedRegistrar* mEnableRegistrar;
 	
 public:
 	static F32 sAutoOpenTime;
diff --git a/indra/llui/llfolderviewmodel.h b/indra/llui/llfolderviewmodel.h
index 093e213be35038cb4850d7723a0c1d1112d60851..c5e027d314aef23a5217e9370ea407b7d0ef188e 100644
--- a/indra/llui/llfolderviewmodel.h
+++ b/indra/llui/llfolderviewmodel.h
@@ -172,7 +172,7 @@ class LLFolderViewModelItem : public LLRefCount
 	virtual BOOL removeItem() = 0;
 	virtual void removeBatch(std::vector<LLFolderViewModelItem*>& batch) = 0;
 
-	virtual BOOL isItemCopyable() const = 0;
+	virtual bool isItemCopyable(bool can_copy_as_link = true) const = 0;
 	virtual BOOL copyToClipboard() const = 0;
 	virtual BOOL cutToClipboard() = 0;
 	virtual bool isCutToClipboard() { return false; };
@@ -419,21 +419,15 @@ class LLFolderViewModel : public LLFolderViewModelCommon
 		mFilter(filter)
 	{}
 
-	virtual ~LLFolderViewModel() 
-	{
-		delete mSorter;
-		mSorter = NULL;
-		delete mFilter;
-		mFilter = NULL;
-	}
+	virtual ~LLFolderViewModel() {}
 
 	virtual SortType& getSorter()					 { return *mSorter; }
 	virtual const SortType& getSorter() const 		 { return *mSorter; }
-	virtual void setSorter(const SortType& sorter) 	 { mSorter = new SortType(sorter); requestSortAll(); }
+	virtual void setSorter(const SortType& sorter) 	 { mSorter.reset(new SortType(sorter)); requestSortAll(); }
 
 	virtual FilterType& getFilter() 				 { return *mFilter; }
 	virtual const FilterType& getFilter() const		 { return *mFilter; }
-	virtual void setFilter(const FilterType& filter) { mFilter = new FilterType(filter); }
+	virtual void setFilter(const FilterType& filter) { mFilter.reset(new FilterType(filter)); }
 
 	// By default, we assume the content is available. If a network fetch mechanism is implemented for the model,
 	// this method needs to be overloaded and return the relevant fetch status.
@@ -471,8 +465,8 @@ class LLFolderViewModel : public LLFolderViewModelCommon
 	}
 
 protected:
-	SortType*		mSorter;
-	FilterType*		mFilter;
+	std::unique_ptr<SortType>		mSorter;
+	std::unique_ptr<FilterType>		mFilter;
 };
 
 #endif // LLFOLDERVIEWMODEL_H
diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp
index 33037b500176e2eddb5bdbe8d8bb6439f586085a..940cf398c02f7bf1be223620022b43fea27e8bc8 100644
--- a/indra/llui/lllineeditor.cpp
+++ b/indra/llui/lllineeditor.cpp
@@ -209,13 +209,6 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p)
 
 	setPrevalidateInput(p.prevalidate_input_callback());
 	setPrevalidate(p.prevalidate_callback());
-
-	llassert(LLMenuGL::sMenuContainer != NULL);
-	LLContextMenu* menu = LLUICtrlFactory::instance().createFromFile<LLContextMenu>
-		("menu_text_editor.xml",
-		 LLMenuGL::sMenuContainer,
-		 LLMenuHolderGL::child_registry_t::instance());
-	setContextMenu(menu);
 }
  
 LLLineEditor::~LLLineEditor()
@@ -1567,7 +1560,7 @@ BOOL LLLineEditor::handleKeyHere(KEY key, MASK mask )
 				KEY_SHIFT != key &&
 				KEY_CONTROL != key &&
 				KEY_ALT != key &&
-				KEY_CAPSLOCK )
+				KEY_CAPSLOCK != key)
 			{
 				deselect();
 			}
@@ -2637,6 +2630,15 @@ LLWString LLLineEditor::getConvertedText() const
 void LLLineEditor::showContextMenu(S32 x, S32 y)
 {
 	LLContextMenu* menu = static_cast<LLContextMenu*>(mContextMenuHandle.get());
+	if (!menu)
+	{
+		llassert(LLMenuGL::sMenuContainer != NULL);
+		menu = LLUICtrlFactory::createFromFile<LLContextMenu>
+			("menu_text_editor.xml",
+				LLMenuGL::sMenuContainer,
+				LLMenuHolderGL::child_registry_t::instance());
+		setContextMenu(menu);
+	}
 
 	if (menu)
 	{
diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp
index 4264028338d6d40c3c17feceef38ecf5e016a7aa..5cb840fd613e9bf370295d54ad3620c54570f7b2 100644
--- a/indra/llui/llmenugl.cpp
+++ b/indra/llui/llmenugl.cpp
@@ -4087,25 +4087,39 @@ void LLTearOffMenu::closeTearOff()
 }
 
 LLContextMenuBranch::LLContextMenuBranch(const LLContextMenuBranch::Params& p) 
-:	LLMenuItemGL(p),
-	mBranch( p.branch()->getHandle() )
+:	LLMenuItemGL(p)
 {
-	mBranch.get()->hide();
-	mBranch.get()->setParentMenuItem(this);
+	LLContextMenu* branch = static_cast<LLContextMenu*>(p.branch);
+	if (branch)
+	{
+		mBranch = branch->getHandle();
+		branch->hide();
+		branch->setParentMenuItem(this);
+	}
+}
+
+LLContextMenuBranch::~LLContextMenuBranch()
+{
+	if (mBranch.get())
+	{
+		mBranch.get()->die();
+	}
 }
 
 // called to rebuild the draw label
 void LLContextMenuBranch::buildDrawLabel( void )
 {
+	auto menu = getBranch();
+	if (menu)
 	{
 		// default enablement is this -- if any of the subitems are
 		// enabled, this item is enabled. JC
-		U32 sub_count = mBranch.get()->getItemCount();
+		U32 sub_count = menu->getItemCount();
 		U32 i;
 		BOOL any_enabled = FALSE;
 		for (i = 0; i < sub_count; i++)
 		{
-			LLMenuItemGL* item = mBranch.get()->getItem(i);
+			LLMenuItemGL* item = menu->getItem(i);
 			item->buildDrawLabel();
 			if (item->getEnabled() && !item->getDrawTextDisabled() )
 			{
@@ -4127,13 +4141,17 @@ void LLContextMenuBranch::buildDrawLabel( void )
 
 void	LLContextMenuBranch::showSubMenu()
 {
-	LLMenuItemGL* menu_item = mBranch.get()->getParentMenuItem();
-	if (menu_item != NULL && menu_item->getVisible())
+	auto menu = getBranch();
+	if(menu)
 	{
-		S32 center_x;
-		S32 center_y;
-		localPointToScreen(getRect().getWidth(), getRect().getHeight() , &center_x, &center_y);
-		mBranch.get()->show(center_x, center_y);
+		LLMenuItemGL* menu_item = menu->getParentMenuItem();
+		if (menu_item != NULL && menu_item->getVisible())
+		{
+			S32 center_x;
+			S32 center_y;
+			localPointToScreen(getRect().getWidth(), getRect().getHeight(), &center_x, &center_y);
+			menu->show(center_x, center_y);
+		}
 	}
 }
 
@@ -4147,13 +4165,17 @@ void LLContextMenuBranch::setHighlight( BOOL highlight )
 {
 	if (highlight == getHighlight()) return;
 	LLMenuItemGL::setHighlight(highlight);
-	if( highlight )
-	{
-		showSubMenu();
-	}
-	else
+	auto menu = getBranch();
+	if (menu)
 	{
-		mBranch.get()->hide();
+		if (highlight)
+		{
+			showSubMenu();
+		}
+		else
+		{
+			menu->hide();
+		}
 	}
 }
 
diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h
index abbfd9a24a36c0597045f3f0b12584a68b6931a5..f84c4d41ebe59b51f094c95fd5d9eba2e35e3afb 100644
--- a/indra/llui/llmenugl.h
+++ b/indra/llui/llmenugl.h
@@ -745,8 +745,7 @@ class LLContextMenuBranch : public LLMenuItemGL
 
 	LLContextMenuBranch(const Params&);
 
-	virtual ~LLContextMenuBranch()
-	{}
+	virtual ~LLContextMenuBranch();
 
 	// called to rebuild the draw label
 	virtual void	buildDrawLabel( void );
diff --git a/indra/llui/llmultislider.cpp b/indra/llui/llmultislider.cpp
index f89064d59acb5230b11f72d6c4db63ec9ccf3827..604d246f12cb5f566fe5b281d24cbaa347ba545d 100644
--- a/indra/llui/llmultislider.cpp
+++ b/indra/llui/llmultislider.cpp
@@ -92,7 +92,7 @@ LLMultiSlider::LLMultiSlider(const LLMultiSlider::Params& p)
 	mMouseDownSignal(NULL),
 	mMouseUpSignal(NULL)
 {
-	mValue.emptyMap();
+	mValue = LLSD::emptyMap();
 	mCurSlider = LLStringUtil::null;
 
 	if (mOrientation == HORIZONTAL)
diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp
index 65c7b420ce725871710844a681ee63ebc8e4c19f..219667f7667741e36ad6fcb79cab15295d0aa9a9 100644
--- a/indra/llui/llscrolllistctrl.cpp
+++ b/indra/llui/llscrolllistctrl.cpp
@@ -196,7 +196,6 @@ LLScrollListCtrl::LLScrollListCtrl(const LLScrollListCtrl::Params& p)
 	mHighlightedItem(-1),
 	mBorder(NULL),
 	mSortCallback(NULL),
-	mPopupMenu(NULL),
 	mCommentTextView(NULL),
 	mNumDynamicWidthColumns(0),
 	mTotalStaticColumnWidth(0),
@@ -348,6 +347,13 @@ LLScrollListCtrl::~LLScrollListCtrl()
 	mItemList.clear();
     clearColumns(); //clears columns and deletes headers
 	delete mIsFriendSignal;
+
+	auto menu = mPopupMenuHandle.get();
+	if (menu)
+	{
+		menu->die();
+		mPopupMenuHandle.markDead();
+	}
 }
 
 
@@ -1307,14 +1313,14 @@ LLScrollListItem* LLScrollListCtrl::getItemByLabel(const std::string& label, BOO
 }
 
 
-BOOL LLScrollListCtrl::selectItemByPrefix(const std::string& target, BOOL case_sensitive)
+BOOL LLScrollListCtrl::selectItemByPrefix(const std::string& target, BOOL case_sensitive, S32 column)
 {
-	return selectItemByPrefix(utf8str_to_wstring(target), case_sensitive);
+	return selectItemByPrefix(utf8str_to_wstring(target), case_sensitive, column);
 }
 
 // Selects first enabled item that has a name where the name's first part matched the target string.
 // Returns false if item not found.
-BOOL LLScrollListCtrl::selectItemByPrefix(const LLWString& target, BOOL case_sensitive)
+BOOL LLScrollListCtrl::selectItemByPrefix(const LLWString& target, BOOL case_sensitive, S32 column)
 {
 	BOOL found = FALSE;
 
@@ -1329,7 +1335,7 @@ BOOL LLScrollListCtrl::selectItemByPrefix(const LLWString& target, BOOL case_sen
 		{
 			LLScrollListItem* item = *iter;
 			// Only select enabled items with matching names
-			LLScrollListCell* cellp = item->getColumn(getSearchColumn());
+			LLScrollListCell* cellp = item->getColumn(column == -1 ? getSearchColumn() : column);
 			BOOL select = cellp ? item->getEnabled() && ('\0' == cellp->getValue().asString()[0]) : FALSE;
 			if (select)
 			{
@@ -1352,7 +1358,7 @@ BOOL LLScrollListCtrl::selectItemByPrefix(const LLWString& target, BOOL case_sen
 			LLScrollListItem* item = *iter;
 
 			// Only select enabled items with matching names
-			LLScrollListCell* cellp = item->getColumn(getSearchColumn());
+			LLScrollListCell* cellp = item->getColumn(column == -1 ? getSearchColumn() : column);
 			if (!cellp)
 			{
 				continue;
@@ -1997,17 +2003,23 @@ BOOL LLScrollListCtrl::handleRightMouseDown(S32 x, S32 y, MASK mask)
 
 			// create the context menu from the XUI file and display it
 			std::string menu_name = is_group ? "menu_url_group.xml" : "menu_url_agent.xml";
-			delete mPopupMenu;
+			auto menu = mPopupMenuHandle.get();
+			if (menu)
+			{
+				menu->die();
+				mPopupMenuHandle.markDead();
+			}
 			llassert(LLMenuGL::sMenuContainer != NULL);
-			mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>(
+			menu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>(
 				menu_name, LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance());
-			if (mPopupMenu)
+			if (menu)
 			{
+				mPopupMenuHandle = menu->getHandle();
 				if (mIsFriendSignal)
 				{
 					bool isFriend = *(*mIsFriendSignal)(uuid);
-					LLView* addFriendButton = mPopupMenu->getChild<LLView>("add_friend");
-					LLView* removeFriendButton = mPopupMenu->getChild<LLView>("remove_friend");
+					LLView* addFriendButton = menu->getChild<LLView>("add_friend");
+					LLView* removeFriendButton = menu->getChild<LLView>("remove_friend");
 
 					if (addFriendButton && removeFriendButton)
 					{
@@ -2016,8 +2028,8 @@ BOOL LLScrollListCtrl::handleRightMouseDown(S32 x, S32 y, MASK mask)
 					}
 				}
 
-				mPopupMenu->show(x, y);
-				LLMenuGL::showPopup(this, mPopupMenu, x, y);
+				menu->show(x, y);
+				LLMenuGL::showPopup(this, menu, x, y);
 				return TRUE;
 			}
 		}
@@ -3395,3 +3407,42 @@ boost::signals2::connection LLScrollListCtrl::setIsFriendCallback(const is_frien
 	}
 	return mIsFriendSignal->connect(cb);
 }
+
+bool LLScrollListCtrl::highlightMatchingItems(const std::string& filter_str)
+{
+    if (filter_str == "" || filter_str == " ")
+    {
+        clearHighlightedItems();
+        return false;
+    }
+    
+    bool res = false;
+
+    setHighlightedColor(LLUIColorTable::instance().getColor("SearchableControlHighlightColor", LLColor4::red));
+
+    std::string filter_str_lc(filter_str);
+    LLStringUtil::toLower(filter_str_lc);
+
+    std::vector<LLScrollListItem*> data = getAllData();
+    std::vector<LLScrollListItem*>::iterator iter = data.begin();
+    while (iter != data.end())
+    {
+        LLScrollListCell* cell = (*iter)->getColumn(0);
+        if (cell)
+        {
+            std::string value = cell->getValue().asString();
+            LLStringUtil::toLower(value);
+            if (value.find(filter_str_lc) == std::string::npos)
+            {
+                (*iter)->setHighlighted(false);
+            }
+            else
+            {
+                (*iter)->setHighlighted(true);
+                res = true;
+            }
+        }
+        iter++;
+    }
+    return res;
+}
diff --git a/indra/llui/llscrolllistctrl.h b/indra/llui/llscrolllistctrl.h
index 77d10fdec7239b2ee3299642cec3f5f3cc176cb4..73b4fb036ab717df66a4c624313e55e331535bfb 100644
--- a/indra/llui/llscrolllistctrl.h
+++ b/indra/llui/llscrolllistctrl.h
@@ -261,8 +261,8 @@ class LLScrollListCtrl : public LLUICtrl, public LLEditMenuHandler,
 	virtual LLScrollListItem* addSimpleElement(const std::string& value, EAddPosition pos = ADD_BOTTOM, const LLSD& id = LLSD());
 
 	BOOL			selectItemByLabel( const std::string& item, BOOL case_sensitive = TRUE, S32 column = 0 );		// FALSE if item not found
-	BOOL			selectItemByPrefix(const std::string& target, BOOL case_sensitive = TRUE);
-	BOOL			selectItemByPrefix(const LLWString& target, BOOL case_sensitive = TRUE);
+	BOOL			selectItemByPrefix(const std::string& target, BOOL case_sensitive = TRUE, S32 column = -1);
+	BOOL			selectItemByPrefix(const LLWString& target, BOOL case_sensitive = TRUE, S32 column = -1);
 	LLScrollListItem*  getItemByLabel( const std::string& item, BOOL case_sensitive = TRUE, S32 column = 0 );
 	const std::string	getSelectedItemLabel(S32 column = 0) const;
 	LLSD			getSelectedValue();
@@ -419,6 +419,8 @@ class LLScrollListCtrl : public LLUICtrl, public LLEditMenuHandler,
 	void			setNeedsSort(bool val = true) { mSorted = !val; }
 	void			dirtyColumns(); // some operation has potentially affected column layout or ordering
 
+    bool highlightMatchingItems(const std::string& filter_str);
+
 	boost::signals2::connection setSortCallback(sort_signal_t::slot_type cb )
 	{
 		if (!mSortCallback) mSortCallback = new sort_signal_t();
@@ -526,7 +528,7 @@ class LLScrollListCtrl : public LLUICtrl, public LLEditMenuHandler,
 
 	S32				mHighlightedItem;
 	class LLViewBorder*	mBorder;
-	LLContextMenu	*mPopupMenu;
+	LLHandle<LLContextMenu>	mPopupMenuHandle;
 	
 	LLView			*mCommentTextView;
 
diff --git a/indra/llui/llspinctrl.cpp b/indra/llui/llspinctrl.cpp
index ef7c8ec0129fc4ba40cddc8a9d778055e81cc0de..c411aafb1a66231175a4fa6b87ac59c7e15dfe91 100644
--- a/indra/llui/llspinctrl.cpp
+++ b/indra/llui/llspinctrl.cpp
@@ -101,7 +101,10 @@ LLSpinCtrl::LLSpinCtrl(const LLSpinCtrl::Params& p)
 	// Spin buttons
 	LLButton::Params up_button_params(p.up_button);
 	up_button_params.rect = LLRect(btn_left, getRect().getHeight(), btn_right, getRect().getHeight() - spinctrl_btn_height);
-	up_button_params.click_callback.function(boost::bind(&LLSpinCtrl::onUpBtn, this, _2));
+    // Click callback starts within the button and ends within the button,
+    // but LLSpinCtrl handles the action continuosly so subsribers needs to
+    // be informed about click ending even if outside view, use 'up' instead
+	up_button_params.mouse_up_callback.function(boost::bind(&LLSpinCtrl::onUpBtn, this, _2));
 	up_button_params.mouse_held_callback.function(boost::bind(&LLSpinCtrl::onUpBtn, this, _2));
     up_button_params.commit_on_capture_lost = true;
 
@@ -110,7 +113,7 @@ LLSpinCtrl::LLSpinCtrl(const LLSpinCtrl::Params& p)
 
 	LLButton::Params down_button_params(p.down_button);
 	down_button_params.rect = LLRect(btn_left, getRect().getHeight() - spinctrl_btn_height, btn_right, getRect().getHeight() - 2 * spinctrl_btn_height);
-	down_button_params.click_callback.function(boost::bind(&LLSpinCtrl::onDownBtn, this, _2));
+	down_button_params.mouse_up_callback.function(boost::bind(&LLSpinCtrl::onDownBtn, this, _2));
 	down_button_params.mouse_held_callback.function(boost::bind(&LLSpinCtrl::onDownBtn, this, _2));
     down_button_params.commit_on_capture_lost = true;
 	mDownBtn = LLUICtrlFactory::create<LLButton>(down_button_params);
diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp
index 0aa7a2d2178fef7d56f48a74e36fc6ec364f7980..8c841540a5d8dc2da105def1be45fb264ad56cf6 100644
--- a/indra/llui/lltabcontainer.cpp
+++ b/indra/llui/lltabcontainer.cpp
@@ -1442,6 +1442,11 @@ void LLTabContainer::selectLastTab()
 
 void LLTabContainer::selectNextTab()
 {
+    if (mTabList.size() == 0)
+    {
+        return;
+    }
+
 	BOOL tab_has_focus = FALSE;
 	if (mCurrentTabIdx >= 0 && mTabList[mCurrentTabIdx]->mButton->hasFocus())
 	{
diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp
index 7e4aaa53bff730fa595b1a6f49ec3e93e61b2532..82a3c01c6d9b00967fcf366124b8da74e6bed18c 100644
--- a/indra/llui/lltextbase.cpp
+++ b/indra/llui/lltextbase.cpp
@@ -273,6 +273,12 @@ LLTextBase::LLTextBase(const LLTextBase::Params &p)
 LLTextBase::~LLTextBase()
 {
 	mSegments.clear();
+	LLContextMenu* menu = static_cast<LLContextMenu*>(mPopupMenuHandle.get());
+	if (menu)
+	{
+		menu->die();
+		mPopupMenuHandle.markDead();
+	}
 	delete mURLClickSignal;
 	delete mIsFriendSignal;
 	delete mIsObjectBlockedSignal;
@@ -355,95 +361,113 @@ void LLTextBase::onValueChange(S32 start, S32 end)
 {
 }
 
-
-// Draws the black box behind the selected text
-void LLTextBase::drawSelectionBackground()
+std::vector<LLRect> LLTextBase::getSelctionRects()
 {
-	// Draw selection even if we don't have keyboard focus for search/replace
-	if( hasSelection() && !mLineInfoList.empty())
-	{
-		std::vector<LLRect> selection_rects;
+    // Nor supposed to be called without selection
+    llassert(hasSelection());
+    llassert(!mLineInfoList.empty());
 
-		S32 selection_left		= llmin( mSelectionStart, mSelectionEnd );
-		S32 selection_right		= llmax( mSelectionStart, mSelectionEnd );
+    std::vector<LLRect> selection_rects;
 
-		// Skip through the lines we aren't drawing.
-		LLRect content_display_rect = getVisibleDocumentRect();
+    S32 selection_left = llmin(mSelectionStart, mSelectionEnd);
+    S32 selection_right = llmax(mSelectionStart, mSelectionEnd);
 
-		// binary search for line that starts before top of visible buffer
-		line_list_t::const_iterator line_iter = std::lower_bound(mLineInfoList.begin(), mLineInfoList.end(), content_display_rect.mTop, compare_bottom());
-		line_list_t::const_iterator end_iter = std::upper_bound(mLineInfoList.begin(), mLineInfoList.end(), content_display_rect.mBottom, compare_top());
+    // Skip through the lines we aren't drawing.
+    LLRect content_display_rect = getVisibleDocumentRect();
 
-		bool done = false;
+    // binary search for line that starts before top of visible buffer
+    line_list_t::const_iterator line_iter = std::lower_bound(mLineInfoList.begin(), mLineInfoList.end(), content_display_rect.mTop, compare_bottom());
+    line_list_t::const_iterator end_iter = std::upper_bound(mLineInfoList.begin(), mLineInfoList.end(), content_display_rect.mBottom, compare_top());
 
-		// Find the coordinates of the selected area
-		for (;line_iter != end_iter && !done; ++line_iter)
-		{
-			// is selection visible on this line?
-			if (line_iter->mDocIndexEnd > selection_left && line_iter->mDocIndexStart < selection_right)
-			{
-				segment_set_t::iterator segment_iter;
-				S32 segment_offset;
-				getSegmentAndOffset(line_iter->mDocIndexStart, &segment_iter, &segment_offset);
-				
-				LLRect selection_rect;
-				selection_rect.mLeft = line_iter->mRect.mLeft;
-				selection_rect.mRight = line_iter->mRect.mLeft;
-				selection_rect.mBottom = line_iter->mRect.mBottom;
-				selection_rect.mTop = line_iter->mRect.mTop;
-					
-				for(;segment_iter != mSegments.end(); ++segment_iter, segment_offset = 0)
-				{
-					LLTextSegmentPtr segmentp = *segment_iter;
+    bool done = false;
+
+    // Find the coordinates of the selected area
+    for (; line_iter != end_iter && !done; ++line_iter)
+    {
+        // is selection visible on this line?
+        if (line_iter->mDocIndexEnd > selection_left && line_iter->mDocIndexStart < selection_right)
+        {
+            segment_set_t::iterator segment_iter;
+            S32 segment_offset;
+            getSegmentAndOffset(line_iter->mDocIndexStart, &segment_iter, &segment_offset);
 
-					S32 segment_line_start = segmentp->getStart() + segment_offset;
-					S32 segment_line_end = llmin(segmentp->getEnd(), line_iter->mDocIndexEnd);
+            // Use F32 otherwise a string of multiple segments
+            // will accumulate a large error
+            F32 left_precise = line_iter->mRect.mLeft;
+            F32 right_precise = line_iter->mRect.mLeft;
 
-					if (segment_line_start > segment_line_end) break;
+            for (; segment_iter != mSegments.end(); ++segment_iter, segment_offset = 0)
+            {
+                LLTextSegmentPtr segmentp = *segment_iter;
 
-					S32 segment_width = 0;
-					S32 segment_height = 0;
+                S32 segment_line_start = segmentp->getStart() + segment_offset;
+                S32 segment_line_end = llmin(segmentp->getEnd(), line_iter->mDocIndexEnd);
 
-					// if selection after beginning of segment
-					if(selection_left >= segment_line_start)
-					{
-						S32 num_chars = llmin(selection_left, segment_line_end) - segment_line_start;
-						segmentp->getDimensions(segment_offset, num_chars, segment_width, segment_height);
-						selection_rect.mLeft += segment_width;
-					}
+                if (segment_line_start > segment_line_end) break;
 
-					// if selection_right == segment_line_end then that means we are the first character of the next segment
-					// or first character of the next line, in either case we want to add the length of the current segment
-					// to the selection rectangle and continue.
-					// if selection right > segment_line_end then selection spans end of current segment...
-					if (selection_right >= segment_line_end)
-					{
-						// extend selection slightly beyond end of line
-						// to indicate selection of newline character (use "n" character to determine width)
-						S32 num_chars = segment_line_end - segment_line_start;
-						segmentp->getDimensions(segment_offset, num_chars, segment_width, segment_height);
-						selection_rect.mRight += segment_width;
-					}
-					// else if selection ends on current segment...
-					else
-					{
-						S32 num_chars = selection_right - segment_line_start;
-						segmentp->getDimensions(segment_offset, num_chars, segment_width, segment_height);
-						selection_rect.mRight += segment_width;
+                F32 segment_width = 0;
+                S32 segment_height = 0;
 
-						break;
-					}
-				}
-				selection_rects.push_back(selection_rect);
-			}
-		}
+                // if selection after beginning of segment
+                if (selection_left >= segment_line_start)
+                {
+                    S32 num_chars = llmin(selection_left, segment_line_end) - segment_line_start;
+                    segmentp->getDimensionsF32(segment_offset, num_chars, segment_width, segment_height);
+                    left_precise += segment_width;
+                }
+
+                // if selection_right == segment_line_end then that means we are the first character of the next segment
+                // or first character of the next line, in either case we want to add the length of the current segment
+                // to the selection rectangle and continue.
+                // if selection right > segment_line_end then selection spans end of current segment...
+                if (selection_right >= segment_line_end)
+                {
+                    // extend selection slightly beyond end of line
+                    // to indicate selection of newline character (use "n" character to determine width)
+                    S32 num_chars = segment_line_end - segment_line_start;
+                    segmentp->getDimensionsF32(segment_offset, num_chars, segment_width, segment_height);
+                    right_precise += segment_width;
+                }
+                // else if selection ends on current segment...
+                else
+                {
+                    S32 num_chars = selection_right - segment_line_start;
+                    segmentp->getDimensionsF32(segment_offset, num_chars, segment_width, segment_height);
+                    right_precise += segment_width;
+
+                    break;
+                }
+            }
+
+            LLRect selection_rect;
+            selection_rect.mLeft = left_precise;
+            selection_rect.mRight = right_precise;
+            selection_rect.mBottom = line_iter->mRect.mBottom;
+            selection_rect.mTop = line_iter->mRect.mTop;
+
+            selection_rects.push_back(selection_rect);
+        }
+    }
+
+    return selection_rects;
+}
+
+// Draws the black box behind the selected text
+void LLTextBase::drawSelectionBackground()
+{
+    // Draw selection even if we don't have keyboard focus for search/replace
+    if (hasSelection() && !mLineInfoList.empty())
+    {
+        std::vector<LLRect> selection_rects = getSelctionRects();
 		
 		// Draw the selection box (we're using a box instead of reversing the colors on the selected text).
 		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
 		const LLColor4& color = mSelectedBGColor;
 		F32 alpha = hasFocus() ? 0.7f : 0.3f;
 		alpha *= getDrawContext().mAlpha;
+
 		LLColor4 selection_color(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE], alpha);
+        LLRect content_display_rect = getVisibleDocumentRect();
 
 		for (std::vector<LLRect>::iterator rect_it = selection_rects.begin();
 			rect_it != selection_rects.end();
@@ -2551,7 +2575,7 @@ S32 LLTextBase::getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round,
 	}
 	
 	S32 pos = getLength();
-	S32 start_x = line_iter->mRect.mLeft + doc_rect.mLeft;
+	F32 start_x = line_iter->mRect.mLeft + doc_rect.mLeft;
 
 	segment_set_t::iterator line_seg_iter;
 	S32 line_seg_offset;
@@ -2563,8 +2587,9 @@ S32 LLTextBase::getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round,
 
 		S32 segment_line_start = segmentp->getStart() + line_seg_offset;
 		S32 segment_line_length = llmin(segmentp->getEnd(), line_iter->mDocIndexEnd) - segment_line_start;
-		S32 text_width, text_height;
-		bool newline = segmentp->getDimensions(line_seg_offset, segment_line_length, text_width, text_height);
+        F32 text_width;
+        S32 text_height;
+		bool newline = segmentp->getDimensionsF32(line_seg_offset, segment_line_length, text_width, text_height);
 
 		if(newline)
 		{
@@ -2584,8 +2609,9 @@ S32 LLTextBase::getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round,
 			S32 offset;
 			if (!segmentp->canEdit())
 			{
-				S32 segment_width, segment_height;
-				segmentp->getDimensions(0, segmentp->getEnd() - segmentp->getStart(), segment_width, segment_height);
+                F32 segment_width;
+                S32 segment_height;
+				segmentp->getDimensionsF32(0, segmentp->getEnd() - segmentp->getStart(), segment_width, segment_height);
 				if (round && local_x - start_x > segment_width / 2)
 				{
 					offset = segment_line_length;
@@ -2632,17 +2658,11 @@ LLRect LLTextBase::getDocRectFromDocIndex(S32 pos) const
 		return LLRect();
 	}
 
-	LLRect doc_rect;
-
 	// clamp pos to valid values
 	pos = llclamp(pos, 0, mLineInfoList.back().mDocIndexEnd - 1);
 
 	line_list_t::const_iterator line_iter = std::upper_bound(mLineInfoList.begin(), mLineInfoList.end(), pos, line_end_compare());
 
-	doc_rect.mLeft = line_iter->mRect.mLeft; 
-	doc_rect.mBottom = line_iter->mRect.mBottom;
-	doc_rect.mTop = line_iter->mRect.mTop;
-
 	segment_set_t::iterator line_seg_iter;
 	S32 line_seg_offset;
 	segment_set_t::iterator cursor_seg_iter;
@@ -2650,6 +2670,8 @@ LLRect LLTextBase::getDocRectFromDocIndex(S32 pos) const
 	getSegmentAndOffset(line_iter->mDocIndexStart, &line_seg_iter, &line_seg_offset);
 	getSegmentAndOffset(pos, &cursor_seg_iter, &cursor_seg_offset);
 
+    F32 doc_left_precise = line_iter->mRect.mLeft;
+
 	while(line_seg_iter != mSegments.end())
 	{
 		const LLTextSegmentPtr segmentp = *line_seg_iter;
@@ -2657,18 +2679,20 @@ LLRect LLTextBase::getDocRectFromDocIndex(S32 pos) const
 		if (line_seg_iter == cursor_seg_iter)
 		{
 			// cursor advanced to right based on difference in offset of cursor to start of line
-			S32 segment_width, segment_height;
-			segmentp->getDimensions(line_seg_offset, cursor_seg_offset - line_seg_offset, segment_width, segment_height);
-			doc_rect.mLeft += segment_width;
+            F32 segment_width;
+            S32 segment_height;
+			segmentp->getDimensionsF32(line_seg_offset, cursor_seg_offset - line_seg_offset, segment_width, segment_height);
+            doc_left_precise += segment_width;
 
 			break;
 		}
 		else
 		{
 			// add remainder of current text segment to cursor position
-			S32 segment_width, segment_height;
-			segmentp->getDimensions(line_seg_offset, (segmentp->getEnd() - segmentp->getStart()) - line_seg_offset, segment_width, segment_height);
-			doc_rect.mLeft += segment_width;
+            F32 segment_width;
+            S32 segment_height;
+			segmentp->getDimensionsF32(line_seg_offset, (segmentp->getEnd() - segmentp->getStart()) - line_seg_offset, segment_width, segment_height);
+            doc_left_precise += segment_width;
 			// offset will be 0 for all segments after the first
 			line_seg_offset = 0;
 			// go to next text segment on this line
@@ -2676,6 +2700,11 @@ LLRect LLTextBase::getDocRectFromDocIndex(S32 pos) const
 		}
 	}
 
+    LLRect doc_rect;
+    doc_rect.mLeft = doc_left_precise;
+    doc_rect.mBottom = line_iter->mRect.mBottom;
+    doc_rect.mTop = line_iter->mRect.mTop;
+
 	// set rect to 0 width
 	doc_rect.mRight = doc_rect.mLeft; 
 
diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h
index 25f8fa1c2bb7c770dfbeaf31778ce381df35f8bb..e3cf56a5ee38cf979971efe35d86fcfd4db4ca18 100644
--- a/indra/llui/lltextbase.h
+++ b/indra/llui/lltextbase.h
@@ -638,6 +638,8 @@ class LLTextBase
 		return mLabel.getString() + getToolTip();
 	}
 
+    std::vector<LLRect> getSelctionRects();
+
 protected:
 	// text segmentation and flow
 	segment_set_t       		mSegments;
diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp
index b1f8b00cab18a9f09d7b634239bc87f6111c73c2..3d2a4269134facfd3fcaa70ee6cd11d0da12d4c0 100644
--- a/indra/llui/lltexteditor.cpp
+++ b/indra/llui/lltexteditor.cpp
@@ -257,7 +257,6 @@ LLTextEditor::LLTextEditor(const LLTextEditor::Params& p) :
 	mMouseDownY(0),
 	mTabsToNextField(p.ignore_tab),
 	mPrevalidateFunc(p.prevalidate_callback()),
-	mContextMenu(NULL),
 	mShowContextMenu(p.show_context_menu),
 	mEnableTooltipPaste(p.enable_tooltip_paste),
 	mPassDelete(FALSE),
@@ -301,8 +300,13 @@ LLTextEditor::~LLTextEditor()
 	// Scrollbar is deleted by LLView
 	std::for_each(mUndoStack.begin(), mUndoStack.end(), DeletePointer());
 	mUndoStack.clear();
-	// context menu is owned by menu holder, not us
-	//delete mContextMenu;
+	// Mark the menu as dead or its retained in memory till shutdown.
+	LLContextMenu* menu = static_cast<LLContextMenu*>(mContextMenuHandle.get());
+	if(menu)
+	{
+		menu->die();
+		mContextMenuHandle.markDead();
+	}
 }
 
 ////////////////////////////////////////////////////////////
@@ -2051,12 +2055,19 @@ void LLTextEditor::setEnabled(BOOL enabled)
 
 void LLTextEditor::showContextMenu(S32 x, S32 y)
 {
-	if (!mContextMenu)
+	LLContextMenu* menu = static_cast<LLContextMenu*>(mContextMenuHandle.get());
+	if (!menu)
 	{
 		llassert(LLMenuGL::sMenuContainer != NULL);
-		mContextMenu = LLUICtrlFactory::instance().createFromFile<LLContextMenu>("menu_text_editor.xml", 
+		menu = LLUICtrlFactory::createFromFile<LLContextMenu>("menu_text_editor.xml", 
 																				LLMenuGL::sMenuContainer, 
 																				LLMenuHolderGL::child_registry_t::instance());
+        if(!menu)
+        {
+            LL_WARNS() << "Failed to create menu for LLTextEditor: " << getName() << LL_ENDL;
+            return;
+        }
+		mContextMenuHandle = menu->getHandle();
 	}
 
 	// Route menu to this class
@@ -2102,11 +2113,11 @@ void LLTextEditor::showContextMenu(S32 x, S32 y)
 		}
 	}
 
-	mContextMenu->setItemVisible("Suggestion Separator", (use_spellcheck) && (!mSuggestionList.empty()));
-	mContextMenu->setItemVisible("Add to Dictionary", (use_spellcheck) && (is_misspelled));
-	mContextMenu->setItemVisible("Add to Ignore", (use_spellcheck) && (is_misspelled));
-	mContextMenu->setItemVisible("Spellcheck Separator", (use_spellcheck) && (is_misspelled));
-	mContextMenu->show(screen_x, screen_y, this);
+	menu->setItemVisible("Suggestion Separator", (use_spellcheck) && (!mSuggestionList.empty()));
+	menu->setItemVisible("Add to Dictionary", (use_spellcheck) && (is_misspelled));
+	menu->setItemVisible("Add to Ignore", (use_spellcheck) && (is_misspelled));
+	menu->setItemVisible("Spellcheck Separator", (use_spellcheck) && (is_misspelled));
+	menu->show(screen_x, screen_y, this);
 }
 
 
diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h
index 1a10d2fd1ee206167f843651b4c3e657a5206451..f3939248c2acf6413ea3241c5009ea0418853359 100644
--- a/indra/llui/lltexteditor.h
+++ b/indra/llui/lltexteditor.h
@@ -329,7 +329,7 @@ class LLTextEditor :
 	keystroke_signal_t mKeystrokeSignal;
 	LLTextValidate::validate_func_t mPrevalidateFunc;
 
-	LLContextMenu* mContextMenu;
+	LLHandle<LLContextMenu> mContextMenuHandle;
 }; // end class LLTextEditor
 
 // Build time optimization, generate once in .cpp file
diff --git a/indra/llui/lltoolbar.cpp b/indra/llui/lltoolbar.cpp
index 5150df25f21adf3512c7bdc832e47b6a69261eac..2707f7a15ca6bd8000b11a0e2da47f2418886711 100644
--- a/indra/llui/lltoolbar.cpp
+++ b/indra/llui/lltoolbar.cpp
@@ -127,7 +127,12 @@ LLToolBar::LLToolBar(const LLToolBar::Params& p)
 
 LLToolBar::~LLToolBar()
 {
-	delete mPopupMenuHandle.get();
+	auto menu = mPopupMenuHandle.get();
+	if (menu)
+	{
+		menu->die();
+		mPopupMenuHandle.markDead();
+	}
 	delete mButtonAddSignal;
 	delete mButtonEnterSignal;
 	delete mButtonLeaveSignal;
diff --git a/indra/llwindow/lldxhardware.cpp b/indra/llwindow/lldxhardware.cpp
index 81e938edbe787300138628382f4daf78e6d9cd48..391a37728064a49a21050177098c80fdacd4029d 100644
--- a/indra/llwindow/lldxhardware.cpp
+++ b/indra/llwindow/lldxhardware.cpp
@@ -1098,7 +1098,7 @@ LLSD LLDXHardware::getDisplayInfo()
     }
 
 LCleanup:
-    if (ret.emptyMap())
+    if (!ret.isMap() || (ret.size() == 0))
     {
         LL_INFOS() << "Failed to get data, cleaning up" << LL_ENDL;
     }
diff --git a/indra/llwindow/llopenglview-objc.mm b/indra/llwindow/llopenglview-objc.mm
index 049226db65b3ee64088b28a7e3207e10a49179ba..79362457448268059fa8c10226ac5d2a12e0d46d 100644
--- a/indra/llwindow/llopenglview-objc.mm
+++ b/indra/llwindow/llopenglview-objc.mm
@@ -495,7 +495,12 @@ attributedStringInfo getSegments(NSAttributedString *str)
     // e.g. OS Window for upload something or Input Window...
     // mModifiers instance variable is for insertText: or insertText:replacementRange:  (by Pell Smit)
 	mModifiers = [theEvent modifierFlags];
-    unichar ch = [[theEvent charactersIgnoringModifiers] characterAtIndex:0];
+    NSString *str_no_modifiers = [theEvent charactersIgnoringModifiers];
+    unichar ch = 0;
+    if (str_no_modifiers.length)
+    {
+        ch = [str_no_modifiers characterAtIndex:0];
+    }
     bool acceptsText = mHasMarkedText ? false : callKeyDown(&eventData, keycode, mModifiers, ch);
 
     if (acceptsText &&
diff --git a/indra/llwindow/llwindowmacosx-objc.h b/indra/llwindow/llwindowmacosx-objc.h
index 43edc0110d6a34d7831d78f66e8abf7eaf0c5fad..77024d3a9c8cb642a82ac3b3059196a9766b9675 100644
--- a/indra/llwindow/llwindowmacosx-objc.h
+++ b/indra/llwindow/llwindowmacosx-objc.h
@@ -83,7 +83,7 @@ int createNSApp(int argc, const char **argv);
 void setupCocoa();
 bool pasteBoardAvailable();
 bool copyToPBoard(const unsigned short *str, unsigned int len);
-const unsigned short *copyFromPBoard();
+unsigned short *copyFromPBoard();
 CursorRef createImageCursor(const char *fullpath, int hotspotX, int hotspotY);
 short releaseImageCursor(CursorRef ref);
 short setImageCursor(CursorRef ref);
diff --git a/indra/llwindow/llwindowmacosx-objc.mm b/indra/llwindow/llwindowmacosx-objc.mm
index 5ec9b017cf1db4144a3f370658e9cde0af271f00..57c3d862956ec5dd483ec06c66765270f08139b5 100644
--- a/indra/llwindow/llwindowmacosx-objc.mm
+++ b/indra/llwindow/llwindowmacosx-objc.mm
@@ -49,14 +49,12 @@ void setupCocoa()
 	
 	if(!inited)
 	{
-		NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-		
-		// The following prevents the Cocoa command line parser from trying to open 'unknown' arguements as documents.
-		// ie. running './secondlife -set Language fr' would cause a pop-up saying can't open document 'fr'
-		// when init'ing the Cocoa App window.
-		[[NSUserDefaults standardUserDefaults] setObject:@"NO" forKey:@"NSTreatUnknownArgumentsAsOpen"];
-		
-		[pool release];
+        @autoreleasepool {
+            // The following prevents the Cocoa command line parser from trying to open 'unknown' arguements as documents.
+            // ie. running './secondlife -set Language fr' would cause a pop-up saying can't open document 'fr'
+            // when init'ing the Cocoa App window.
+            [[NSUserDefaults standardUserDefaults] setObject:@"NO" forKey:@"NSTreatUnknownArgumentsAsOpen"];
+        }
 
 		inited = true;
 	}
@@ -64,13 +62,13 @@ void setupCocoa()
 
 bool copyToPBoard(const unsigned short *str, unsigned int len)
 {
-	NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
-	NSPasteboard *pboard = [NSPasteboard generalPasteboard];
-	[pboard clearContents];
-	
-	NSArray *contentsToPaste = [[NSArray alloc] initWithObjects:[NSString stringWithCharacters:str length:len], nil];
-	[pool release];
-	return [pboard writeObjects:contentsToPaste];
+    @autoreleasepool {
+        NSPasteboard *pboard = [NSPasteboard generalPasteboard];
+        [pboard clearContents];
+        
+        NSArray *contentsToPaste = [[[NSArray alloc] initWithObjects:[NSString stringWithCharacters:str length:len], nil] autorelease];
+        return [pboard writeObjects:contentsToPaste];
+    }
 }
 
 bool pasteBoardAvailable()
@@ -79,39 +77,39 @@ bool pasteBoardAvailable()
 	return [[NSPasteboard generalPasteboard] canReadObjectForClasses:classArray options:[NSDictionary dictionary]];
 }
 
-const unsigned short *copyFromPBoard()
+unsigned short *copyFromPBoard()
 {
-	NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
-	NSPasteboard *pboard = [NSPasteboard generalPasteboard];
-	NSArray *classArray = [NSArray arrayWithObject:[NSString class]];
-	NSString *str = NULL;
-	BOOL ok = [pboard canReadObjectForClasses:classArray options:[NSDictionary dictionary]];
-	if (ok)
-	{
-		NSArray *objToPaste = [pboard readObjectsForClasses:classArray options:[NSDictionary dictionary]];
-		str = [objToPaste objectAtIndex:0];
-	}
-	unichar* temp = (unichar*)calloc([str length]+1, sizeof(unichar));
-	[str getCharacters:temp];
-	[pool release];
-	return temp;
+    @autoreleasepool {
+        NSPasteboard *pboard = [NSPasteboard generalPasteboard];
+        NSArray *classArray = [NSArray arrayWithObject:[NSString class]];
+        NSString *str = NULL;
+        BOOL ok = [pboard canReadObjectForClasses:classArray options:[NSDictionary dictionary]];
+        if (ok)
+        {
+            NSArray *objToPaste = [pboard readObjectsForClasses:classArray options:[NSDictionary dictionary]];
+            str = [objToPaste objectAtIndex:0];
+        }
+        NSUInteger str_len = [str length];
+        unichar* temp = (unichar*)calloc(str_len+1, sizeof(unichar));
+        [str getCharacters:temp range:NSMakeRange(0, str_len)];
+        return temp;
+    }
 }
 
 CursorRef createImageCursor(const char *fullpath, int hotspotX, int hotspotY)
 {
-	NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-
-	// extra retain on the NSCursor since we want it to live for the lifetime of the app.
-	NSCursor *cursor =
-	[[[NSCursor alloc]
-	  initWithImage:
-	  [[[NSImage alloc] initWithContentsOfFile:
-		[NSString stringWithUTF8String:fullpath]
-		]autorelease]
-	  hotSpot:NSMakePoint(hotspotX, hotspotY)
-	  ]retain];
-	
-	[pool release];
+    NSCursor *cursor = nil;
+    @autoreleasepool {
+        // extra retain on the NSCursor since we want it to live for the lifetime of the app.
+        cursor =
+        [[[NSCursor alloc]
+          initWithImage:
+              [[[NSImage alloc] initWithContentsOfFile:
+                    [NSString stringWithUTF8String:fullpath]
+               ] autorelease]
+          hotSpot:NSMakePoint(hotspotX, hotspotY)
+         ] retain];
+    }
 	
 	return (CursorRef)cursor;
 }
@@ -178,10 +176,10 @@ OSErr releaseImageCursor(CursorRef ref)
 {
 	if( ref != NULL )
 	{
-		NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-		NSCursor *cursor = (NSCursor*)ref;
-		[cursor release];
-		[pool release];
+        @autoreleasepool {
+            NSCursor *cursor = (NSCursor*)ref;
+            [cursor autorelease];
+        }
 	}
 	else
 	{
@@ -195,10 +193,10 @@ OSErr setImageCursor(CursorRef ref)
 {
 	if( ref != NULL )
 	{
-		NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-		NSCursor *cursor = (NSCursor*)ref;
-		[cursor set];
-		[pool release];
+        @autoreleasepool {
+            NSCursor *cursor = (NSCursor*)ref;
+            [cursor set];
+        }
 	}
 	else
 	{
@@ -419,24 +417,26 @@ void requestUserAttention()
 
 long showAlert(std::string text, std::string title, int type)
 {
-    NSAlert *alert = [[NSAlert alloc] init];
-    
-    [alert setMessageText:[NSString stringWithCString:title.c_str() encoding:[NSString defaultCStringEncoding]]];
-    [alert setInformativeText:[NSString stringWithCString:text.c_str() encoding:[NSString defaultCStringEncoding]]];
-    if (type == 0)
-    {
-        [alert addButtonWithTitle:@"Okay"];
-    } else if (type == 1)
-    {
-        [alert addButtonWithTitle:@"Okay"];
-        [alert addButtonWithTitle:@"Cancel"];
-    } else if (type == 2)
-    {
-        [alert addButtonWithTitle:@"Yes"];
-        [alert addButtonWithTitle:@"No"];
+    long ret = 0;
+    @autoreleasepool {
+        NSAlert *alert = [[[NSAlert alloc] init] autorelease];
+        
+        [alert setMessageText:[NSString stringWithCString:title.c_str() encoding:[NSString defaultCStringEncoding]]];
+        [alert setInformativeText:[NSString stringWithCString:text.c_str() encoding:[NSString defaultCStringEncoding]]];
+        if (type == 0)
+        {
+            [alert addButtonWithTitle:@"Okay"];
+        } else if (type == 1)
+        {
+            [alert addButtonWithTitle:@"Okay"];
+            [alert addButtonWithTitle:@"Cancel"];
+        } else if (type == 2)
+        {
+            [alert addButtonWithTitle:@"Yes"];
+            [alert addButtonWithTitle:@"No"];
+        }
+        ret = [alert runModal];
     }
-    long ret = [alert runModal];
-    [alert dealloc];
     
     if (ret == NSAlertFirstButtonReturn)
     {
diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp
index c29131d60bc2566835e7680d59cc70ba48c65a6e..f924b17090e5a953f0a97a5178a18b51311822fc 100644
--- a/indra/llwindow/llwindowmacosx.cpp
+++ b/indra/llwindow/llwindowmacosx.cpp
@@ -668,11 +668,11 @@ BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits
 
 		if (cgl_err != kCGLNoError )
 		{
-			LL_DEBUGS("GLInit") << "Multi-threaded OpenGL not available." << LL_ENDL;
+			LL_INFOS("GLInit") << "Multi-threaded OpenGL not available." << LL_ENDL;
 		}
 		else
 		{
-			LL_DEBUGS("GLInit") << "Multi-threaded OpenGL enabled." << LL_ENDL;
+            LL_INFOS("GLInit") << "Multi-threaded OpenGL enabled." << LL_ENDL;
 		}
 	}
 	makeFirstResponder(mWindow, mGLView);
@@ -1246,8 +1246,11 @@ BOOL LLWindowMacOSX::isClipboardTextAvailable()
 }
 
 BOOL LLWindowMacOSX::pasteTextFromClipboard(LLWString &dst)
-{	
-	llutf16string str(copyFromPBoard());
+{
+    unsigned short* pboard_data = copyFromPBoard(); // must free returned data
+	llutf16string str(pboard_data);
+    free(pboard_data);
+
 	dst = utf16str_to_wstring(str);
 	if (dst != L"")
 	{
@@ -1280,7 +1283,7 @@ LLWindow::LLWindowResolution* LLWindowMacOSX::getSupportedResolutions(S32 &num_r
 {
 	if (!mSupportedResolutions)
 	{
-		CFArrayRef modes = CGDisplayAvailableModes(mDisplay);
+		CFArrayRef modes = CGDisplayCopyAllDisplayModes(mDisplay, nullptr);
 
 		if(modes != NULL)
 		{
@@ -1319,6 +1322,7 @@ LLWindow::LLWindowResolution* LLWindowMacOSX::getSupportedResolutions(S32 &num_r
 					}
 				}
 			}
+            CFRelease(modes);
 		}
 	}
 
diff --git a/indra/llwindow/llwindowmacosx.h b/indra/llwindow/llwindowmacosx.h
index b0f339e1db8282bef2feb84883b4d10018cb080e..851c860017fd8153fbc4fa029746119ba7c32d47 100644
--- a/indra/llwindow/llwindowmacosx.h
+++ b/indra/llwindow/llwindowmacosx.h
@@ -228,6 +228,7 @@ class LLWindowMacOSX : public LLWindow
 	BOOL		mLanguageTextInputAllowed;
 	LLPreeditor*	mPreeditor;
 	
+public:
 	static BOOL	sUseMultGL;
 
 	friend class LLWindowManager;
diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp
index c487877cafdff183543c43af6dd9a8ad1d6ef6ac..41f3042ace01102dfbeff1c11503910154f99fc7 100644
--- a/indra/llwindow/llwindowwin32.cpp
+++ b/indra/llwindow/llwindowwin32.cpp
@@ -3067,18 +3067,54 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
                 {
                     LLMutexLock lock(&window_imp->mRawMouseMutex);
 
-                    S32 speed;
-                    const S32 DEFAULT_SPEED(10);
-                    SystemParametersInfo(SPI_GETMOUSESPEED, 0, &speed, 0);
-                    if (speed == DEFAULT_SPEED)
+                    bool absolute_coordinates = (raw->data.mouse.usFlags & MOUSE_MOVE_ABSOLUTE);
+
+                    if (absolute_coordinates)
                     {
-                        window_imp->mRawMouseDelta.mX += raw->data.mouse.lLastX;
-                        window_imp->mRawMouseDelta.mY -= raw->data.mouse.lLastY;
+                        static S32 prev_absolute_x = 0;
+                        static S32 prev_absolute_y = 0;
+                        S32 absolute_x;
+                        S32 absolute_y;
+
+                        if ((raw->data.mouse.usFlags & 0x10) == 0x10) // touch screen? touch? Not defined in header
+                        {
+                            // touch screen spams (0,0) coordinates in a number of situations
+                            // (0,0) might need to be filtered
+                            absolute_x = raw->data.mouse.lLastX;
+                            absolute_y = raw->data.mouse.lLastY;
+                        }
+                        else
+                        {
+                            bool v_desktop = (raw->data.mouse.usFlags & MOUSE_VIRTUAL_DESKTOP) == MOUSE_VIRTUAL_DESKTOP;
+
+                            S32 width = GetSystemMetrics(v_desktop ? SM_CXVIRTUALSCREEN : SM_CXSCREEN);
+                            S32 height = GetSystemMetrics(v_desktop ? SM_CYVIRTUALSCREEN : SM_CYSCREEN);
+
+                            absolute_x = (raw->data.mouse.lLastX / 65535.0f) * width;
+                            absolute_y = (raw->data.mouse.lLastY / 65535.0f) * height;
+                        }
+
+                        window_imp->mRawMouseDelta.mX += absolute_x - prev_absolute_x;
+                        window_imp->mRawMouseDelta.mY -= absolute_y - prev_absolute_y;
+
+                        prev_absolute_x = absolute_x;
+                        prev_absolute_y = absolute_y;
                     }
                     else
                     {
-                        window_imp->mRawMouseDelta.mX += round((F32)raw->data.mouse.lLastX * (F32)speed / DEFAULT_SPEED);
-                        window_imp->mRawMouseDelta.mY -= round((F32)raw->data.mouse.lLastY * (F32)speed / DEFAULT_SPEED);
+                        S32 speed;
+                        const S32 DEFAULT_SPEED(10);
+                        SystemParametersInfo(SPI_GETMOUSESPEED, 0, &speed, 0);
+                        if (speed == DEFAULT_SPEED)
+                        {
+                            window_imp->mRawMouseDelta.mX += raw->data.mouse.lLastX;
+                            window_imp->mRawMouseDelta.mY -= raw->data.mouse.lLastY;
+                        }
+                        else
+                        {
+                            window_imp->mRawMouseDelta.mX += round((F32)raw->data.mouse.lLastX * (F32)speed / DEFAULT_SPEED);
+                            window_imp->mRawMouseDelta.mY -= round((F32)raw->data.mouse.lLastY * (F32)speed / DEFAULT_SPEED);
+                        }
                     }
                 }
             }
@@ -4215,7 +4251,10 @@ void LLWindowWin32::handleCompositionMessage(const U32 indexes)
 
 	if (needs_update)
 	{
-		mPreeditor->resetPreedit();
+        if (preedit_string.length() != 0 || result_string.length() != 0)
+        {
+            mPreeditor->resetPreedit();
+        }
 
 		if (result_string.length() > 0)
 		{
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 7d78ec9e3c80bb6f99d3a29379dc11acf68e4409..837efee7b1dbbb79116f650563345b4874e7205b 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -287,9 +287,9 @@ set(viewer_SOURCE_FILES
     llfloaternotificationsconsole.cpp
     llfloaternotificationstabbed.cpp
     llfloateroutfitphotopreview.cpp 
-    llfloateroutfitsnapshot.cpp
     llfloaterobjectweights.cpp
     llfloateropenobject.cpp
+    llfloatersimpleoutfitsnapshot.cpp
     llfloaterpathfindingcharacters.cpp
     llfloaterpathfindingconsole.cpp
     llfloaterpathfindinglinksets.cpp
@@ -929,9 +929,9 @@ set(viewer_HEADER_FILES
     llfloaternotificationsconsole.h
     llfloaternotificationstabbed.h
     llfloateroutfitphotopreview.h
-    llfloateroutfitsnapshot.h
     llfloaterobjectweights.h
     llfloateropenobject.h
+    llfloatersimpleoutfitsnapshot.h
     llfloaterpathfindingcharacters.h
     llfloaterpathfindingconsole.h
     llfloaterpathfindinglinksets.h
@@ -1825,9 +1825,9 @@ if (WINDOWS)
       ${SHARED_LIB_STAGING_DIR}/Release/libcollada14dom22.dll
       ${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/libcollada14dom22.dll
       ${SHARED_LIB_STAGING_DIR}/Debug/libcollada14dom22-d.dll
-      ${SHARED_LIB_STAGING_DIR}/Release/openjpeg.dll
-      ${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/openjpeg.dll
-      ${SHARED_LIB_STAGING_DIR}/Debug/openjpegd.dll
+      ${SHARED_LIB_STAGING_DIR}/Release/openjp2.dll
+      ${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/openjp2.dll
+      ${SHARED_LIB_STAGING_DIR}/Debug/openjp2.dll
       ${SHARED_LIB_STAGING_DIR}/Release/libhunspell.dll
       ${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/libhunspell.dll
       ${SHARED_LIB_STAGING_DIR}/Debug/libhunspell.dll
diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt
index 4aa5a3a58e8c27e16189402e6ab0e13712de35f8..0673dfa857a900ad047072c8e4d022791164d3aa 100644
--- a/indra/newview/VIEWER_VERSION.txt
+++ b/indra/newview/VIEWER_VERSION.txt
@@ -1 +1 @@
-6.6.8
+6.6.10
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 6861153d43798aca1899f5fa697942ce0be5e031..411f77e6a7b527f189a37300a1dcc1855ba50433 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -4747,7 +4747,7 @@
       <key>Type</key>
       <string>String</string>
       <key>Value</key>
-      <string>https://search.[GRID]/?query_term=[QUERY]&amp;search_type=[TYPE][COLLECTION]&amp;maturity=[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/?query_term=[QUERY]&amp;search_type=[TYPE][COLLECTION]&amp;maturity=[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>
@@ -14634,6 +14634,17 @@
       <key>Value</key>
       <integer>0</integer>
     </map>
+    <key>MediaSoundsEarLocation</key>
+    <map>
+      <key>Comment</key>
+      <string>Location of the virtual ear for media and sounds</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>S32</string>
+      <key>Value</key>
+      <integer>0</integer>
+    </map>
     <key>VoiceHost</key>
     <map>
       <key>Comment</key>
@@ -16876,5 +16887,16 @@
     <key>Value</key>
     <string></string>
   </map>
+  <key>DebugSettingsHideDefault</key>
+  <map>
+    <key>Comment</key>
+    <string>Show non-default settings only in Debug Settings list</string>
+    <key>Persist</key>
+    <integer>0</integer>
+    <key>Type</key>
+    <string>Boolean</string>
+    <key>Value</key>
+    <integer>0</integer>
+  </map>
 </map>
 </llsd>
diff --git a/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl b/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl
index b26194f278823da1da30ec16972e52f09e3ee60c..b30d7655dbe468f713b44f0f6795ade71e8149fb 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl
@@ -202,7 +202,7 @@ VARYING vec2 vary_texcoord2;
 uniform float env_intensity;
 uniform vec4 specular_color;  // specular color RGB and specular exponent (glossiness) in alpha
 
-#ifdef HAS_ALPHA_MASK
+#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_MASK)
 uniform float minimum_alpha;
 #endif
 
@@ -227,12 +227,11 @@ void main()
     vec4 diffcol = texture2D(diffuseMap, vary_texcoord0.xy);
 	diffcol.rgb *= vertex_color.rgb;
 
-#ifdef HAS_ALPHA_MASK
-#if DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND
-    if (diffcol.a*vertex_color.a < minimum_alpha)
-#else
-    if (diffcol.a < minimum_alpha)
-#endif
+#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_MASK)
+
+    // Comparing floats cast from 8-bit values, produces acne right at the 8-bit transition points
+    float bias = 0.001953125; // 1/512, or half an 8-bit quantization (SL-18637)
+    if (diffcol.a < minimum_alpha-bias)
     {
         discard;
     }
diff --git a/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl b/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl
index 331249dc33b509b52648944fa4363a81392a4f24..de22312d3ccc133b5f30e7e462077823575430af 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl
@@ -25,6 +25,17 @@
  
 /*[EXTRA_CODE_HERE]*/
 
+// Inputs
+VARYING vec4 vary_HazeColor;
+VARYING float vary_LightNormPosDot;
+
+uniform sampler2D rainbow_map;
+uniform sampler2D halo_map;
+
+uniform float moisture_level;
+uniform float droplet_radius;
+uniform float ice_level;
+
 #ifdef DEFINE_GL_FRAGCOLOR
 out vec4 frag_data[3];
 #else
@@ -35,11 +46,34 @@ out vec4 frag_data[3];
 // The fragment shader for the sky
 /////////////////////////////////////////////////////////////////////////
 
-VARYING vec4 vary_HazeColor;
+vec3 rainbow(float d)
+{
+    // 'Interesting' values of d are -0.75 .. -0.825, i.e. when view vec nearly opposite of sun vec
+    // Rainbox tex is mapped with REPEAT, so -.75 as tex coord is same as 0.25.  -0.825 -> 0.175. etc.
+    // SL-13629
+    // Unfortunately the texture is inverted, so we need to invert the y coord, but keep the 'interesting'
+    // part within the same 0.175..0.250 range, i.e. d = (1 - d) - 1.575
+    d         = clamp(-0.575 - d, 0.0, 1.0);
+
+    // With the colors in the lower 1/4 of the texture, inverting the coords leaves most of it inaccessible.
+    // So, we can stretch the texcoord above the colors (ie > 0.25) to fill the entire remaining coordinate
+    // space. This improves gradation, reduces banding within the rainbow interior. (1-0.25) / (0.425/0.25) = 4.2857
+    float interior_coord = max(0.0, d - 0.25) * 4.2857;
+    d = clamp(d, 0.0, 0.25) + interior_coord;
+
+    float rad = (droplet_radius - 5.0f) / 1024.0f;
+    return pow(texture2D(rainbow_map, vec2(rad+0.5, d)).rgb, vec3(1.8)) * moisture_level;
+}
+
+vec3 halo22(float d)
+{
+    d       = clamp(d, 0.1, 1.0);
+    float v = sqrt(clamp(1 - (d * d), 0, 1));
+    return texture2D(halo_map, vec2(0, v)).rgb * ice_level;
+}
 
 /// Soft clips the light with a gamma correction
 vec3 scaleSoftClip(vec3 light);
-vec3 srgb_to_linear(vec3 c);
 
 void main()
 {
@@ -48,14 +82,18 @@ void main()
     // the fragment) if the sky wouldn't show up because the clouds 
     // are fully opaque.
 
-    vec4 color;
-    color = vary_HazeColor;
+    vec4 color = vary_HazeColor;
 
+    float  rel_pos_lightnorm = vary_LightNormPosDot;
+    float optic_d = rel_pos_lightnorm;
+    vec3  halo_22 = halo22(optic_d);
+    color.rgb += rainbow(optic_d);
+    color.rgb += halo_22;
     color.rgb *= 2.;
     color.rgb = scaleSoftClip(color.rgb);
 
-    /// Gamma correct for WL (soft clip effect).
-    frag_data[0] = vec4(color.rgb, 0.0);
+    // Gamma correct for WL (soft clip effect).
+    frag_data[0] = vec4(color.rgb, 1.0);
     frag_data[1] = vec4(0.0,0.0,0.0,0.0);
     frag_data[2] = vec4(0.0,0.0,0.0,1.0); //1.0 in norm.w masks off fog
 
diff --git a/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl b/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl
index 28a1faf24f75c47a3991d47b7a2b7e1d83731bc4..6db4690bfffddd1de1a31e5f1527a12f75c6d51f 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl
@@ -33,6 +33,7 @@ ATTRIBUTE vec3 position;
 
 // Output parameters
 VARYING vec4 vary_HazeColor;
+VARYING float vary_LightNormPosDot;
 
 // Inputs
 uniform vec3 camPosLocal;
@@ -72,27 +73,29 @@ void main()
     vec3 rel_pos = position.xyz - camPosLocal.xyz + vec3(0, 50, 0);
 
     // Adj position vector to clamp altitude
-    if (rel_pos.y > 0)
+    if (rel_pos.y > 0.)
     {
         rel_pos *= (max_y / rel_pos.y);
     }
-    if (rel_pos.y < 0)
+    if (rel_pos.y < 0.)
     {
         rel_pos *= (-32000. / rel_pos.y);
     }
 
-    // Can normalize then
-    vec3 rel_pos_norm = normalize(rel_pos);
+    // Normalized
+    vec3  rel_pos_norm = normalize(rel_pos);
+    float rel_pos_len  = length(rel_pos);
 
-    float rel_pos_len = length(rel_pos);
+    // Grab this value and pass to frag shader for rainbows
+    float rel_pos_lightnorm_dot = dot(rel_pos_norm, lightnorm.xyz);
+    vary_LightNormPosDot = rel_pos_lightnorm_dot;
 
     // Initialize temp variables
     vec4 sunlight = (sun_up_factor == 1) ? sunlight_color : moonlight_color;
-    vec4 light_atten;
 
     // Sunlight attenuation effect (hue and brightness) due to atmosphere
     // this is used later for sunlight modulation at various altitudes
-    light_atten = (blue_density + vec4(haze_density * 0.25)) * (density_multiplier * max_y);
+    vec4 light_atten = (blue_density + vec4(haze_density * 0.25)) * (density_multiplier * max_y);
 
     // Calculate relative weights
     vec4 combined_haze = abs(blue_density) + vec4(abs(haze_density));
@@ -112,7 +115,7 @@ void main()
     combined_haze = exp(-combined_haze * density_dist);
 
     // Compute haze glow
-    float haze_glow = 1.0 - dot(rel_pos_norm, lightnorm.xyz);
+    float haze_glow = 1.0 - rel_pos_lightnorm_dot;
     // haze_glow is 0 at the sun and increases away from sun
     haze_glow = max(haze_glow, .001);
     // Set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot)
@@ -123,30 +126,30 @@ void main()
 
     // Add "minimum anti-solar illumination"
     // For sun, add to glow.  For moon, remove glow entirely. SL-13768
-    haze_glow = (sun_moon_glow_factor < 1.0) ? 0.0 : (haze_glow + 0.25);
+    haze_glow = (sun_moon_glow_factor < 1.0) ? 0.0 : (sun_moon_glow_factor * (haze_glow + 0.25));
 
-    vec4 color =
-        (blue_horizon * blue_weight * (sunlight + ambient_color) + (haze_horizon * haze_weight) * (sunlight * haze_glow + ambient_color));
+    // Haze color above cloud
+    vec4 color = (blue_horizon * blue_weight * (sunlight + ambient_color)
+               + (haze_horizon * haze_weight) * (sunlight * haze_glow + ambient_color));
 
     // Final atmosphere additive
     color *= (1. - combined_haze);
 
     // Increase ambient when there are more clouds
-    vec4 tmpAmbient = ambient_color;
-    tmpAmbient += max(vec4(0), (1. - ambient_color)) * cloud_shadow * 0.5;
+    vec4 ambient = ambient_color + max(vec4(0), (1. - ambient_color)) * cloud_shadow * 0.5;
 
     // Dim sunlight by cloud shadow percentage
     sunlight *= max(0.0, (1. - cloud_shadow));
 
     // Haze color below cloud
-    vec4 additiveColorBelowCloud =
-        (blue_horizon * blue_weight * (sunlight + tmpAmbient) + (haze_horizon * haze_weight) * (sunlight * haze_glow + tmpAmbient));
+    vec4 add_below_cloud = (blue_horizon * blue_weight * (sunlight + ambient) 
+                         + (haze_horizon * haze_weight) * (sunlight * haze_glow + ambient));
 
     // Attenuate cloud color by atmosphere
     combined_haze = sqrt(combined_haze);  // less atmos opacity (more transparency) below clouds
 
     // At horizon, blend high altitude sky color towards the darker color below the clouds
-    color += (additiveColorBelowCloud - color) * (1. - sqrt(combined_haze));
+    color += (add_below_cloud - color) * (1. - sqrt(combined_haze));
 
     // Haze color above cloud
     vary_HazeColor = color;
diff --git a/indra/newview/app_settings/shaders/class2/deferred/skyF.glsl b/indra/newview/app_settings/shaders/class2/deferred/skyF.glsl
deleted file mode 100644
index 6841a8194f6c27ebe4f84c48e82f9608d6e9e84d..0000000000000000000000000000000000000000
--- a/indra/newview/app_settings/shaders/class2/deferred/skyF.glsl
+++ /dev/null
@@ -1,199 +0,0 @@
-/**
- * @file class2/deferred/skyF.glsl
- *
- * $LicenseInfo:firstyear=2005&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2005, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-uniform mat4 modelview_projection_matrix;
-
-// SKY ////////////////////////////////////////////////////////////////////////
-// The vertex shader for creating the atmospheric sky
-///////////////////////////////////////////////////////////////////////////////
-
-// Inputs
-uniform vec3 camPosLocal;
-
-uniform vec4  lightnorm;
-uniform vec4  sunlight_color;
-uniform vec4  moonlight_color;
-uniform int   sun_up_factor;
-uniform vec4  ambient_color;
-uniform vec4  blue_horizon;
-uniform vec4  blue_density;
-uniform float haze_horizon;
-uniform float haze_density;
-
-uniform float cloud_shadow;
-uniform float density_multiplier;
-uniform float distance_multiplier;
-uniform float max_y;
-
-uniform vec4  glow;
-uniform float sun_moon_glow_factor;
-
-uniform vec4 cloud_color;
-
-#ifdef DEFINE_GL_FRAGCOLOR
-out vec4 frag_data[3];
-#else
-#define frag_data gl_FragData
-#endif
-
-VARYING vec3 pos;
-
-/////////////////////////////////////////////////////////////////////////
-// The fragment shader for the sky
-/////////////////////////////////////////////////////////////////////////
-
-uniform sampler2D rainbow_map;
-uniform sampler2D halo_map;
-
-uniform float moisture_level;
-uniform float droplet_radius;
-uniform float ice_level;
-
-vec3 rainbow(float d)
-{
-    // d is the dot product of view and sun directions, so ranging -1.0..1.0
-    // 'interesting' values of d are the range -0.75..-0.825, when view is nearly opposite of sun vec
-    // Rainbox texture mode is GL_REPEAT, so tc of -.75 is equiv to 0.25, -0.825 equiv to 0.175.
-
-    // SL-13629 Rainbow texture has colors within the correct .175...250 range, but order is inverted.
-    // Rather than replace the texture, we mirror and translate the y tc to keep the colors within the
-    // interesting range, but in reversed order:  i.e. d = (1 - d) - 1.575
-    d = clamp(-0.575 - d, 0.0, 1.0);
-
-    // With the colors in the lower 1/4 of the texture, inverting the coords leaves most of it inaccessible.
-    // So, we can stretch the texcoord above the colors (ie > 0.25) to fill the entire remaining coordinate
-    // space. This improves gradation, reduces banding within the rainbow interior. (1-0.25) / (0.425/0.25) = 4.2857
-    float interior_coord = max(0.0, d - 0.25) * 4.2857;
-    d = clamp(d, 0.0, 0.25) + interior_coord;
-
-    float rad = (droplet_radius - 5.0f) / 1024.0f;
-    return pow(texture2D(rainbow_map, vec2(rad, d)).rgb, vec3(1.8)) * moisture_level;
-}
-
-vec3 halo22(float d)
-{
-    d       = clamp(d, 0.1, 1.0);
-    float v = sqrt(clamp(1 - (d * d), 0, 1));
-    return texture2D(halo_map, vec2(0, v)).rgb * ice_level;
-}
-
-/// Soft clips the light with a gamma correction
-vec3 scaleSoftClip(vec3 light);
-
-void main()
-{
-    // World / view / projection
-    // Get relative position (offset why?)
-    vec3 rel_pos = pos.xyz - camPosLocal.xyz + vec3(0, 50, 0);
-
-    // Adj position vector to clamp altitude
-    if (rel_pos.y > 0.)
-    {
-        rel_pos *= (max_y / rel_pos.y);
-    }
-    if (rel_pos.y < 0.)
-    {
-        rel_pos *= (-32000. / rel_pos.y);
-    }
-
-    // Normalized
-    vec3  rel_pos_norm = normalize(rel_pos);
-    float rel_pos_len  = length(rel_pos);
-
-    // Initialize temp variables
-    vec4 sunlight = (sun_up_factor == 1) ? sunlight_color : moonlight_color;
-
-    // Sunlight attenuation effect (hue and brightness) due to atmosphere
-    // this is used later for sunlight modulation at various altitudes
-    vec4 light_atten = (blue_density + vec4(haze_density * 0.25)) * (density_multiplier * max_y);
-
-    // Calculate relative weights
-    vec4 combined_haze = abs(blue_density) + vec4(abs(haze_density));
-    vec4 blue_weight   = blue_density / combined_haze;
-    vec4 haze_weight   = haze_density / combined_haze;
-
-    // Compute sunlight from rel_pos & lightnorm (for long rays like sky)
-    float off_axis = 1.0 / max(1e-6, max(0, rel_pos_norm.y) + lightnorm.y);
-    sunlight *= exp(-light_atten * off_axis);
-
-    // Distance
-    float density_dist = rel_pos_len * density_multiplier;
-
-    // Transparency (-> combined_haze)
-    // ATI Bugfix -- can't store combined_haze*density_dist in a variable because the ati
-    // compiler gets confused.
-    combined_haze = exp(-combined_haze * density_dist);
-
-    // Compute haze glow
-    float haze_glow = dot(rel_pos_norm, lightnorm.xyz);
-    haze_glow       = 1. - haze_glow;
-    // haze_glow is 0 at the sun and increases away from sun
-    haze_glow = max(haze_glow, .001);
-    // Set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot)
-    haze_glow *= glow.x;
-    // Higher glow.x gives dimmer glow (because next step is 1 / "angle")
-    haze_glow = pow(haze_glow, glow.z);
-    // glow.z should be negative, so we're doing a sort of (1 / "angle") function
-
-    // Add "minimum anti-solar illumination"
-    // For sun, add to glow.  For moon, remove glow entirely. SL-13768
-    haze_glow = (sun_moon_glow_factor < 1.0) ? 0.0 : (sun_moon_glow_factor * (haze_glow + 0.25));
-
-    // Haze color above cloud
-    vec4 color = blue_horizon * blue_weight * (sunlight + ambient_color) 
-               + haze_horizon * haze_weight * (sunlight * haze_glow + ambient_color);
-
-    // Final atmosphere additive
-    color *= (1. - combined_haze);
-
-    // Increase ambient when there are more clouds
-    // TODO 9/20: DJH what does this do?  max(0,(1-ambient)) will change the color
-    vec4 ambient = ambient_color + max(vec4(0), (1. - ambient_color)) * cloud_shadow * 0.5;
-
-    // Dim sunlight by cloud shadow percentage
-    sunlight *= max(0.0, (1. - cloud_shadow));
-
-    // Haze color below cloud
-    vec4 add_below_cloud = blue_horizon * blue_weight * (sunlight + ambient) 
-                         + haze_horizon * haze_weight * (sunlight * haze_glow + ambient);
-
-    // Attenuate cloud color by atmosphere
-    combined_haze = sqrt(combined_haze);  // less atmos opacity (more transparency) below clouds
-
-    // At horizon, blend high altitude sky color towards the darker color below the clouds
-    color += (add_below_cloud - color) * (1. - sqrt(combined_haze));
-
-    float optic_d = dot(rel_pos_norm, lightnorm.xyz);
-    vec3  halo_22 = halo22(optic_d);
-    color.rgb += rainbow(optic_d);
-    color.rgb += halo_22;
-    color.rgb *= 2.;
-    color.rgb = scaleSoftClip(color.rgb);
-
-    // Gamma correct for WL (soft clip effect).
-    frag_data[0] = vec4(color.rgb, 1.0);
-    frag_data[1] = vec4(0.0, 0.0, 0.0, 0.0);
-    frag_data[2] = vec4(0.0, 0.0, 0.0, 1.0);  // 1.0 in norm.w masks off fog
-}
diff --git a/indra/newview/app_settings/shaders/class2/deferred/skyV.glsl b/indra/newview/app_settings/shaders/class2/deferred/skyV.glsl
deleted file mode 100644
index bcf775577ab2dc11bacd4f31bf230da392bf1b42..0000000000000000000000000000000000000000
--- a/indra/newview/app_settings/shaders/class2/deferred/skyV.glsl
+++ /dev/null
@@ -1,42 +0,0 @@
-/** 
- * @file WLSkyV.glsl
- *
- * $LicenseInfo:firstyear=2005&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2005, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-uniform mat4 modelview_projection_matrix;
-
-ATTRIBUTE vec3 position;
-
-// SKY ////////////////////////////////////////////////////////////////////////
-// The vertex shader for creating the atmospheric sky
-///////////////////////////////////////////////////////////////////////////////
-
-VARYING vec3 pos;
-
-void main()
-{
-
-	// World / view / projection
-    pos = position.xyz;
-	gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0);
-}
diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt
index 1ccde98283751309899d1b0241854ae8196ded7f..93dd5e7e70d741fc2a2096d5a83c5526f88e3acc 100644
--- a/indra/newview/featuretable.txt
+++ b/indra/newview/featuretable.txt
@@ -33,7 +33,6 @@ RenderAvatarLODFactor		1	1.0
 RenderAvatarPhysicsLODFactor 1	1.0
 RenderAvatarMaxNonImpostors 1   16
 RenderAvatarMaxComplexity          1	350000
-RenderAvatarVP				1	1
 RenderAutoMuteSurfaceAreaLimit     1	1000.0
 RenderCubeMap				1	1
 RenderDelayVBUpdate			1	0
diff --git a/indra/newview/featuretable_linux.txt b/indra/newview/featuretable_linux.txt
index 5542eee6ca7ddb275d3d18b70bf73b2e0d69f17d..66197e6484dc0bf034fc144821868a5f2790fb6b 100644
--- a/indra/newview/featuretable_linux.txt
+++ b/indra/newview/featuretable_linux.txt
@@ -33,7 +33,6 @@ RenderAvatarLODFactor		1	1.0
 RenderAvatarPhysicsLODFactor 1	1.0
 RenderAvatarMaxNonImpostors 1   16
 RenderAvatarMaxComplexity          1	350000
-RenderAvatarVP				1	1
 RenderAutoMuteSurfaceAreaLimit     1	1000.0
 RenderCubeMap				1	1
 RenderDelayVBUpdate			1	0
@@ -80,7 +79,6 @@ RenderAvatarLODFactor		1	0
 RenderAvatarPhysicsLODFactor 1	0
 RenderAvatarMaxNonImpostors 1   3
 RenderAvatarMaxComplexity          1	25000
-RenderAvatarVP				1	0
 RenderFarClip				1	64
 RenderFlexTimeFactor		1	0
 RenderGlowResolutionPow		1	8
@@ -111,7 +109,6 @@ RenderAvatarLODFactor		1	0
 RenderAvatarPhysicsLODFactor 1	0
 RenderAvatarMaxNonImpostors 1   3
 RenderAvatarMaxComplexity          1	35000
-RenderAvatarVP				1	0
 RenderFarClip				1	64
 RenderFlexTimeFactor		1	0
 RenderGlowResolutionPow		1	8
@@ -141,7 +138,6 @@ RenderAvatarCloth			1	0
 RenderAvatarLODFactor		1	0.5
 RenderAvatarMaxComplexity   1	100000
 RenderAvatarPhysicsLODFactor 1	0.75
-RenderAvatarVP				1	1
 RenderFarClip				1	96
 RenderFlexTimeFactor		1	1.0
 RenderGlowResolutionPow		1	8
@@ -171,7 +167,6 @@ RenderAvatarCloth			1	0
 RenderAvatarLODFactor		1	1.0
 RenderAvatarMaxComplexity   1	200000
 RenderAvatarPhysicsLODFactor 1	1.0
-RenderAvatarVP				1	1
 RenderFarClip				1	128
 RenderFlexTimeFactor		1	1.0
 RenderGlowResolutionPow		1	9
@@ -201,7 +196,6 @@ RenderAvatarCloth			1	0
 RenderAvatarLODFactor		1	1.0
 RenderAvatarMaxComplexity   1	250000
 RenderAvatarPhysicsLODFactor 1	1.0
-RenderAvatarVP				1	1
 RenderFarClip				1	128
 RenderFlexTimeFactor		1	1.0
 RenderGlowResolutionPow		1	9
@@ -231,7 +225,6 @@ RenderAvatarCloth			1	0
 RenderAvatarLODFactor		1	1.0
 RenderAvatarMaxComplexity   1	300000
 RenderAvatarPhysicsLODFactor 1	1.0
-RenderAvatarVP				1	1
 RenderFarClip				1	128
 RenderFlexTimeFactor		1	1.0
 RenderGlowResolutionPow		1	9
@@ -261,7 +254,6 @@ RenderAvatarCloth			1	0
 RenderAvatarLODFactor		1	1.0
 RenderAvatarMaxComplexity   1	350000
 RenderAvatarPhysicsLODFactor 1	1.0
-RenderAvatarVP				1	1
 RenderFarClip				1	128
 RenderFlexTimeFactor		1	1.0
 RenderGlowResolutionPow		1	9
@@ -290,7 +282,6 @@ RenderAnisotropic			1	1
 RenderAvatarCloth			1	1
 RenderAvatarLODFactor		1	1.0
 RenderAvatarPhysicsLODFactor 1	1.0
-RenderAvatarVP				1	1
 RenderFarClip				1	256
 RenderFlexTimeFactor		1	1.0
 RenderGlowResolutionPow		1	9
@@ -367,7 +358,6 @@ RenderCompressTextures		1	0
 // No Pixel Shaders available
 //
 list NoPixelShaders
-RenderAvatarVP				0	0
 RenderAvatarCloth			0	0
 RenderReflectionDetail		0	0
 WindLightUseAtmosShaders	0	0
@@ -380,7 +370,6 @@ RenderShadowDetail			0	0
 // No Vertex Shaders available
 //
 list NoVertexShaders
-RenderAvatarVP				0	0
 RenderAvatarCloth			0	0
 RenderReflectionDetail		0	0
 WindLightUseAtmosShaders	0	0
@@ -402,7 +391,6 @@ RenderVBOMappingDisable		1	1
 list safe
 RenderAnisotropic			1	0
 RenderAvatarCloth			0	0
-RenderAvatarVP				0	0
 RenderAvatarMaxNonImpostors 1	16
 RenderAvatarMaxComplexity          1	80000
 RenderObjectBump			0	0
@@ -597,7 +585,6 @@ Disregard128DefaultDrawDistance	1	0
 // on various ATI chipsets on drivers before 8.2
 
 list ATIOldDriver
-RenderAvatarVP				0	0
 RenderAvatarCloth			0	0
 // Avoid driver crashes with some features on Linux with old ATI drivers
 UseOcclusion				0	0
diff --git a/indra/newview/featuretable_mac.txt b/indra/newview/featuretable_mac.txt
index c9efd89cc87d7dc6802e35ea52ea0fdf19c9224b..fed035c7fa0436816aacb806a32f2ff052ac6632 100644
--- a/indra/newview/featuretable_mac.txt
+++ b/indra/newview/featuretable_mac.txt
@@ -33,7 +33,6 @@ RenderAvatarLODFactor			1	1.0
 RenderAvatarPhysicsLODFactor 1	1.0
 RenderAvatarMaxNonImpostors     1   16
 RenderAvatarMaxComplexity              1	350000
-RenderAvatarVP					1	1
 RenderAutoMuteSurfaceAreaLimit     1	1000.0
 RenderCubeMap				1	1
 RenderDelayVBUpdate			1	0
diff --git a/indra/newview/llaccountingcostmanager.cpp b/indra/newview/llaccountingcostmanager.cpp
index e09527a34b5802fcbed9128d168dc1c844ea5e0e..d3f988d715bef04b03634351ed2cc40b97cf5e77 100644
--- a/indra/newview/llaccountingcostmanager.cpp
+++ b/indra/newview/llaccountingcostmanager.cpp
@@ -96,11 +96,7 @@ void LLAccountingCostManager::accountingCostCoro(std::string url,
         LLSD dataToPost = LLSD::emptyMap();
         dataToPost[keystr.c_str()] = objectList;
 
-        LLAccountingCostObserver* observer = observerHandle.get();
-        LLUUID transactionId = observer->getTransactionID();
-        observer = NULL;
-
-
+        LLAccountingCostObserver* observer = NULL;
 
         LLSD results = httpAdapter->postAndSuspend(httpRequest, url, dataToPost);
 
diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index 5250369813de200833d39a9d3b9b7dfb7ca20b05..9018a5f168cd4f54415647fd695bc64db53b3bc2 100644
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -2912,9 +2912,11 @@ void LLAgent::processMaturityPreferenceFromServer(const LLSD &result, U8 perferr
 
 bool LLAgent::requestPostCapability(const std::string &capName, LLSD &postData, httpCallback_t cbSuccess, httpCallback_t cbFailure)
 {
-    std::string url;
-
-    url = getRegion()->getCapability(capName);
+    if (!getRegion())
+    {
+        return false;
+    }
+    std::string url = getRegion()->getCapability(capName);
 
     if (url.empty())
     {
diff --git a/indra/newview/llappdelegate-objc.mm b/indra/newview/llappdelegate-objc.mm
index 5214f4b838113830230a09b22486c1d8f60c5f68..1090888c1cdf9fc340133d616abe4589b754051a 100644
--- a/indra/newview/llappdelegate-objc.mm
+++ b/indra/newview/llappdelegate-objc.mm
@@ -46,6 +46,7 @@
 
 - (void)dealloc
 {
+    [currentInputLanguage release];
     [super dealloc];
 }
 
@@ -199,12 +200,14 @@
 
 - (bool) romanScript
 {
-	// How to add support for new languages with the input window:
-	// Simply append this array with the language code (ja for japanese, ko for korean, zh for chinese, etc.)
-	NSArray *nonRomanScript = [[NSArray alloc] initWithObjects:@"ja", @"ko", @"zh-Hant", @"zh-Hans", nil];
-	if ([nonRomanScript containsObject:currentInputLanguage])
-    {
-        return false;
+    @autoreleasepool {
+        // How to add support for new languages with the input window:
+        // Simply append this array with the language code (ja for japanese, ko for korean, zh for chinese, etc.)
+        NSArray* nonRomanScript = @[@"ja", @"ko", @"zh-Hant", @"zh-Hans"];
+        if ([nonRomanScript containsObject:currentInputLanguage])
+        {
+            return false;
+        }
     }
     
     return true;
diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 909f32cd21a637de4e8564aa471f7dad2c40bdbe..3c93a9df7ebaab026aee32c8a7a0dbb376fb9db5 100644
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -3987,7 +3987,7 @@ void LLAppearanceMgr::makeNewOutfitLinks(const std::string& new_folder_name, boo
 		// existence of AIS as an indicator the fix is present. Does
 		// not actually use AIS to create the category.
 		inventory_func_type func = boost::bind(&LLAppearanceMgr::onOutfitFolderCreated,this,_1,show_panel);
-		LLUUID folder_id = gInventory.createNewCategory(
+		gInventory.createNewCategory(
 			parent_id,
 			LLFolderType::FT_OUTFIT,
 			new_folder_name,
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index b31447a72b7d8fc14e50ad396caaacb92769c208..dc9f7bb4038f2f7e3d11ee04413756bb4fd7cd7e 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -135,6 +135,10 @@
 #include "vlc/libvlc_version.h"
 #endif // LL_LINUX
 
+#if LL_DARWIN
+#include "llwindowmacosx.h"
+#endif
+
 // Third party library includes
 #include <boost/bind.hpp>
 #include <boost/foreach.hpp>
@@ -209,7 +213,7 @@
 #include "llcommandlineparser.h"
 #include "llfloatermemleak.h"
 #include "llfloaterreg.h"
-#include "llfloateroutfitsnapshot.h"
+#include "llfloatersimpleoutfitsnapshot.h"
 #include "llfloatersnapshot.h"
 #include "llsidepanelinventory.h"
 #include "llatmosphere.h"
@@ -560,6 +564,7 @@ static void settings_to_globals()
     LLWorldMapView::setScaleSetting(gSavedSettings.getF32("MapScale"));
 	
 #if LL_DARWIN
+    LLWindowMacOSX::sUseMultGL = gSavedSettings.getBOOL("RenderAppleUseMultGL");
 	gHiDPISupport = gSavedSettings.getBOOL("RenderHiDPI");
 #endif
 }
@@ -1275,7 +1280,6 @@ bool LLAppViewer::init()
 
     //LLSimpleton creations
     LLEnvironment::createInstance();
-    LLEnvironment::getInstance()->initSingleton();
     LLWorld::createInstance();
     LLSelectMgr::createInstance();
     LLViewerCamera::createInstance();
@@ -1521,7 +1525,7 @@ bool LLAppViewer::doFrame()
 					LL_PROFILE_ZONE_NAMED_CATEGORY_APP( "df Snapshot" )
 				pingMainloopTimeout("Main:Snapshot");
 				LLFloaterSnapshot::update(); // take snapshots
-					LLFloaterOutfitSnapshot::update();
+                LLFloaterSimpleOutfitSnapshot::update();
 				gGLActive = FALSE;
 			}
 		}
@@ -1725,7 +1729,8 @@ bool LLAppViewer::cleanup()
 	{
 		if (!isSecondInstance())
 		{
-			LLSceneMonitor::instance().dumpToFile(gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "scene_monitor_results.csv"));
+            std::string dump_path = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "scene_monitor_results.csv");
+			LLSceneMonitor::instance().dumpToFile(dump_path);
 		}
 		LLSceneMonitor::deleteSingleton();
 	}
diff --git a/indra/newview/llaudiosourcevo.cpp b/indra/newview/llaudiosourcevo.cpp
index 1846238d93e35e50c93114d03ee12ae9160ef4d7..43abbb57eeb01ef575cd4e5a85ac6c9524953628 100644
--- a/indra/newview/llaudiosourcevo.cpp
+++ b/indra/newview/llaudiosourcevo.cpp
@@ -102,7 +102,7 @@ LLVector3d LLAudioSourceVO::getPosGlobal() const
 
 bool LLAudioSourceVO::isInCutOffRadius(const LLVector3d pos_global, const F32 cutoff) const
 {
-    static LLCachedControl<S32> ear_mode(gSavedSettings, "VoiceEarLocation", 0);
+    static LLCachedControl<S32> ear_mode(gSavedSettings, "MediaSoundsEarLocation", 0);
 
     LLVector3d pos_ear;
 
@@ -113,9 +113,6 @@ bool LLAudioSourceVO::isInCutOffRadius(const LLVector3d pos_global, const F32 cu
             break;
 
         case 1: // avatar
-        case 2:
-            // voice support 'mixed' in '2' case with agent's position and camera's rotations
-            // but it is not defined in settings and uses camera as default
             pos_ear = gAgent.getPositionGlobal();
             break;
 
diff --git a/indra/newview/llavatarrenderinfoaccountant.cpp b/indra/newview/llavatarrenderinfoaccountant.cpp
index 275f17b02ae23647bdedd8d95ea7759909a958a3..293c9d60a14dafec63feb992a0409b766cad55cb 100644
--- a/indra/newview/llavatarrenderinfoaccountant.cpp
+++ b/indra/newview/llavatarrenderinfoaccountant.cpp
@@ -364,11 +364,10 @@ void LLAvatarRenderInfoAccountant::getRenderInfoFromRegion(LLViewerRegion * regi
 	}
 }
 
-// static
 // Called every frame - send render weight requests to every region
 void LLAvatarRenderInfoAccountant::idle()
 {
-	if (mRenderInfoScanTimer.hasExpired())
+	if (mRenderInfoScanTimer.hasExpired() && !LLApp::isExiting())
 	{
 		LL_DEBUGS("AvatarRenderInfo") << "Scanning regions for render info updates"
 									  << LL_ENDL;
diff --git a/indra/newview/llbuycurrencyhtml.cpp b/indra/newview/llbuycurrencyhtml.cpp
index 1c69dadb1227041179d32bffe0b6ec6fd4999f5f..7ad06f8eaa41a089c6a54b7bc3ee4aac7a522f87 100644
--- a/indra/newview/llbuycurrencyhtml.cpp
+++ b/indra/newview/llbuycurrencyhtml.cpp
@@ -41,7 +41,7 @@ class LLBuyCurrencyHTMLHandler :
 {
 public:
 	// requests will be throttled from a non-trusted browser
-	LLBuyCurrencyHTMLHandler() : LLCommandHandler( "buycurrencyhtml", UNTRUSTED_ALLOW ) {}
+	LLBuyCurrencyHTMLHandler() : LLCommandHandler( "buycurrencyhtml", UNTRUSTED_THROTTLE) {}
 
 	bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web)
 	{
diff --git a/indra/newview/llcallingcard.cpp b/indra/newview/llcallingcard.cpp
index 1ad2157df04b13bdfa5a69ce13290c02778eb889..df79043b000350a7c03a2ce216275e58e415c0e1 100644
--- a/indra/newview/llcallingcard.cpp
+++ b/indra/newview/llcallingcard.cpp
@@ -650,8 +650,7 @@ void LLAvatarTracker::processChange(LLMessageSystem* msg)
 		{
 			if(mBuddyInfo.find(agent_id) != mBuddyInfo.end())
 			{
-                if (((mBuddyInfo[agent_id]->getRightsGrantedFrom() ^  new_rights) & LLRelationship::GRANT_MODIFY_OBJECTS)
-                    && !gAgent.isDoNotDisturb())
+                if (((mBuddyInfo[agent_id]->getRightsGrantedFrom() ^  new_rights) & LLRelationship::GRANT_MODIFY_OBJECTS))
 				{
 					LLSD args;
 					args["NAME"] = LLSLURL("agent", agent_id, "displayname").getSLURLString();
@@ -719,11 +718,12 @@ void LLAvatarTracker::processNotify(LLMessageSystem* msg, bool online)
 				// we were tracking someone who went offline
 				deleteTrackingData();
 			}
-		}
-		if(chat_notify)
-		{
-			// Look up the name of this agent for the notification
-			LLAvatarNameCache::get(agent_id,boost::bind(&on_avatar_name_cache_notify,_1, _2, online, payload));
+
+            if(chat_notify)
+            {
+                // Look up the name of this agent for the notification
+                LLAvatarNameCache::get(agent_id,boost::bind(&on_avatar_name_cache_notify,_1, _2, online, payload));
+            }
 		}
 
 		mModifyMask |= LLFriendObserver::ONLINE;
diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp
index 7ff24f64acf08513b4cfdae57401e35123766866..9a608fba8e4c24be15b1d4db9161f947bcfe3f58 100644
--- a/indra/newview/llchathistory.cpp
+++ b/indra/newview/llchathistory.cpp
@@ -141,6 +141,18 @@ class LLChatHistoryHeader: public LLPanel
 		{
 			mAvatarNameCacheConnection.disconnect();
 		}
+		auto menu = mPopupMenuHandleAvatar.get();
+		if (menu)
+		{
+			menu->die();
+			mPopupMenuHandleAvatar.markDead();
+		}
+		menu = mPopupMenuHandleObject.get();
+		if (menu)
+		{
+			menu->die();
+			mPopupMenuHandleObject.markDead();
+		}
 	}
 
 	BOOL handleMouseUp(S32 x, S32 y, MASK mask)
@@ -567,36 +579,6 @@ class LLChatHistoryHeader: public LLPanel
 
 	BOOL postBuild()
 	{
-		LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
-		LLUICtrl::EnableCallbackRegistry::ScopedRegistrar registrar_enable;
-
-		registrar.add("AvatarIcon.Action", boost::bind(&LLChatHistoryHeader::onAvatarIconContextMenuItemClicked, this, _2));
-		registrar_enable.add("AvatarIcon.Check", boost::bind(&LLChatHistoryHeader::onAvatarIconContextMenuItemChecked, this, _2));
-		registrar_enable.add("AvatarIcon.Enable", boost::bind(&LLChatHistoryHeader::onAvatarIconContextMenuItemEnabled, this, _2));
-		registrar_enable.add("AvatarIcon.Visible", boost::bind(&LLChatHistoryHeader::onAvatarIconContextMenuItemVisible, this, _2));
-		registrar.add("ObjectIcon.Action", boost::bind(&LLChatHistoryHeader::onObjectIconContextMenuItemClicked, this, _2));
-		registrar_enable.add("ObjectIcon.Visible", boost::bind(&LLChatHistoryHeader::onObjectIconContextMenuItemVisible, this, _2));
-
-		LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_avatar_icon.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
-		if (menu)
-		{
-			mPopupMenuHandleAvatar = menu->getHandle();
-		}
-		else
-		{
-			LL_WARNS() << " Failed to create menu_avatar_icon.xml" << LL_ENDL;
-		}
-
-		menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_object_icon.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
-		if (menu)
-		{
-			mPopupMenuHandleObject = menu->getHandle();
-		}
-		else
-		{
-			LL_WARNS() << " Failed to create menu_object_icon.xml" << LL_ENDL;
-		}
-
 		setDoubleClickCallback(boost::bind(&LLChatHistoryHeader::showInspector, this));
 
 		setMouseEnterCallback(boost::bind(&LLChatHistoryHeader::showInfoCtrl, this));
@@ -650,7 +632,7 @@ class LLChatHistoryHeader: public LLPanel
 
 	void showInspector()
 	{
-		if (mAvatarID.isNull() && CHAT_SOURCE_SYSTEM != mSourceType) return;
+		if (mAvatarID.isNull() && CHAT_SOURCE_SYSTEM != mSourceType && CHAT_SOURCE_REGION != mSourceType) return;
 		
 		if (mSourceType == CHAT_SOURCE_OBJECT)
 		{
@@ -798,6 +780,7 @@ class LLChatHistoryHeader: public LLPanel
 				icon->setValue(LLSD("OBJECT_Icon"));
 				break;
 			case CHAT_SOURCE_SYSTEM:
+			case CHAT_SOURCE_REGION:
 				icon->setValue(LLSD("SL_Logo"));
 				break;
 			case CHAT_SOURCE_TELEPORT:
@@ -883,13 +866,53 @@ class LLChatHistoryHeader: public LLPanel
 	void showObjectContextMenu(S32 x,S32 y)
 	{
 		LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandleObject.get();
-		if(menu)
+		if (!menu)
+		{
+			LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
+			LLUICtrl::EnableCallbackRegistry::ScopedRegistrar registrar_enable;
+			registrar.add("ObjectIcon.Action", boost::bind(&LLChatHistoryHeader::onObjectIconContextMenuItemClicked, this, _2));
+			registrar_enable.add("ObjectIcon.Visible", boost::bind(&LLChatHistoryHeader::onObjectIconContextMenuItemVisible, this, _2));
+
+			menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_object_icon.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+			if (menu)
+			{
+				mPopupMenuHandleObject = menu->getHandle();
+				menu->updateParent(LLMenuGL::sMenuContainer);
+				LLMenuGL::showPopup(this, menu, x, y);
+			}
+			else
+			{
+				LL_WARNS() << " Failed to create menu_object_icon.xml" << LL_ENDL;
+			}
+		}
+		else
+		{
 			LLMenuGL::showPopup(this, menu, x, y);
+		}
 	}
 	
 	void showAvatarContextMenu(S32 x,S32 y)
 	{
 		LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandleAvatar.get();
+		if (!menu)
+		{
+			LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
+			LLUICtrl::EnableCallbackRegistry::ScopedRegistrar registrar_enable;
+			registrar.add("AvatarIcon.Action", boost::bind(&LLChatHistoryHeader::onAvatarIconContextMenuItemClicked, this, _2));
+			registrar_enable.add("AvatarIcon.Check", boost::bind(&LLChatHistoryHeader::onAvatarIconContextMenuItemChecked, this, _2));
+			registrar_enable.add("AvatarIcon.Enable", boost::bind(&LLChatHistoryHeader::onAvatarIconContextMenuItemEnabled, this, _2));
+			registrar_enable.add("AvatarIcon.Visible", boost::bind(&LLChatHistoryHeader::onAvatarIconContextMenuItemVisible, this, _2));
+
+			menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_avatar_icon.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+			if (menu)
+			{
+				mPopupMenuHandleAvatar = menu->getHandle();
+			}
+			else
+			{
+				LL_WARNS() << " Failed to create menu_avatar_icon.xml" << LL_ENDL;
+			}
+		}
 
 		if(menu)
 		{
@@ -947,7 +970,7 @@ class LLChatHistoryHeader: public LLPanel
 
 	void showInfoCtrl()
 	{
-		const bool isVisible = !mAvatarID.isNull() && !mFrom.empty() && CHAT_SOURCE_SYSTEM != mSourceType;
+		const bool isVisible = !mAvatarID.isNull() && !mFrom.empty() && CHAT_SOURCE_SYSTEM != mSourceType && CHAT_SOURCE_REGION != mSourceType;
 		if (isVisible)
 		{
 			const LLRect sticky_rect = mUserNameTextBox->getRect();
@@ -1081,10 +1104,7 @@ LLChatHistory::LLChatHistory(const LLChatHistory::Params& p)
 
 LLSD LLChatHistory::getValue() const
 {
-  LLSD* text=new LLSD(); 
-  text->assign(mEditor->getText());
-  return *text;
-    
+	return LLSD(mEditor->getText());
 }
 
 LLChatHistory::~LLChatHistory()
@@ -1343,7 +1363,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL
 				mEditor->appendText(chat.mFromName + delimiter, prependNewLineState, link_params);
 				prependNewLineState = false;
 			}
-			else if ( chat.mFromName != SYSTEM_FROM && chat.mFromID.notNull() && !message_from_log)
+			else if ( chat.mFromName != SYSTEM_FROM && chat.mFromID.notNull() && !message_from_log && chat.mSourceType != CHAT_SOURCE_REGION)
 			{
 				LLStyle::Params link_params(body_message_params);
 				link_params.overwriteFrom(LLStyleMap::instance().lookupAgent(chat.mFromID));
diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp
index 0f187b0ecfb6713642448eae1cb670173c614e56..cc4f4536a4d3413ae4105aaaa4a1eac605f67b9a 100644
--- a/indra/newview/llchiclet.cpp
+++ b/indra/newview/llchiclet.cpp
@@ -67,7 +67,6 @@ LLSysWellChiclet::LLSysWellChiclet(const Params& p)
 	, mMaxDisplayedCount(p.max_displayed_count)
 	, mIsNewMessagesState(false)
 	, mFlashToLitTimer(NULL)
-	, mContextMenu(NULL)
 {
 	LLButton::Params button_params = p.button;
 	mButton = LLUICtrlFactory::create<LLButton>(button_params);
@@ -79,6 +78,12 @@ LLSysWellChiclet::LLSysWellChiclet(const Params& p)
 LLSysWellChiclet::~LLSysWellChiclet()
 {
 	mFlashToLitTimer->unset();
+	LLContextMenu* menu = static_cast<LLContextMenu*>(mContextMenuHandle.get());
+	if (menu)
+	{
+		menu->die();
+		mContextMenuHandle.markDead();
+	}
 }
 
 void LLSysWellChiclet::setCounter(S32 counter)
@@ -145,14 +150,16 @@ void LLSysWellChiclet::updateWidget(bool is_window_empty)
 // virtual
 BOOL LLSysWellChiclet::handleRightMouseDown(S32 x, S32 y, MASK mask)
 {
-	if(!mContextMenu)
+	LLContextMenu* menu_avatar = mContextMenuHandle.get();
+	if(!menu_avatar)
 	{
 		createMenu();
+		menu_avatar = mContextMenuHandle.get();
 	}
-	if (mContextMenu)
+	if (menu_avatar)
 	{
-		mContextMenu->show(x, y);
-		LLMenuGL::showPopup(this, mContextMenu, x, y);
+		menu_avatar->show(x, y);
+		LLMenuGL::showPopup(this, menu_avatar, x, y);
 	}
 	return TRUE;
 }
@@ -192,7 +199,7 @@ bool LLNotificationChiclet::enableMenuItem(const LLSD& user_data)
 
 void LLNotificationChiclet::createMenu()
 {
-	if(mContextMenu)
+	if(mContextMenuHandle.get())
 	{
 		LL_WARNS() << "Menu already exists" << LL_ENDL;
 		return;
@@ -207,10 +214,14 @@ void LLNotificationChiclet::createMenu()
 		boost::bind(&LLNotificationChiclet::enableMenuItem, this, _2));
 
 	llassert(LLMenuGL::sMenuContainer != NULL);
-	mContextMenu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>
+	LLContextMenu* menu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>
 		("menu_notification_well_button.xml",
 		 LLMenuGL::sMenuContainer,
 		 LLViewerMenuHolderGL::child_registry_t::instance());
+	if (menu)
+	{
+		mContextMenuHandle = menu->getHandle();
+	}
 }
 
 /*virtual*/
@@ -309,10 +320,19 @@ LLIMChiclet::LLIMChiclet(const LLIMChiclet::Params& p)
 , mDefaultWidth(p.rect().getWidth())
 , mNewMessagesIcon(NULL)
 , mChicletButton(NULL)
-, mPopupMenu(NULL)
 {
 }
 
+LLIMChiclet::~LLIMChiclet()
+{
+	auto menu = mPopupMenuHandle.get();
+	if (menu)
+	{
+		menu->die();
+		mPopupMenuHandle.markDead();
+	}
+}
+
 /* virtual*/
 BOOL LLIMChiclet::postBuild()
 {
@@ -364,16 +384,18 @@ void LLIMChiclet::setToggleState(bool toggle)
 
 BOOL LLIMChiclet::handleRightMouseDown(S32 x, S32 y, MASK mask)
 {
-	if(!mPopupMenu)
+	auto menu = static_cast<LLMenuGL*>(mPopupMenuHandle.get());
+	if(!menu)
 	{
 		createPopupMenu();
+		menu = static_cast<LLMenuGL*>(mPopupMenuHandle.get());
 	}
 
-	if (mPopupMenu)
+	if (menu)
 	{
 		updateMenuItems();
-		mPopupMenu->arrangeAndClear();
-		LLMenuGL::showPopup(this, mPopupMenu, x, y);
+		menu->arrangeAndClear();
+		LLMenuGL::showPopup(this, menu, x, y);
 	}
 
 	return TRUE;
@@ -381,15 +403,16 @@ BOOL LLIMChiclet::handleRightMouseDown(S32 x, S32 y, MASK mask)
 
 void LLIMChiclet::hidePopupMenu()
 {
-	if (mPopupMenu)
+	auto menu = mPopupMenuHandle.get();
+	if (menu)
 	{
-		mPopupMenu->setVisible(FALSE);
+		menu->setVisible(FALSE);
 	}
 }
 
 bool LLIMChiclet::canCreateMenu()
 {
-	if(mPopupMenu)
+	if(mPopupMenuHandle.get())
 	{
 		LL_WARNS() << "Menu already exists" << LL_ENDL;
 		return false;
@@ -1107,8 +1130,13 @@ void LLScriptChiclet::createPopupMenu()
 	LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
 	registrar.add("ScriptChiclet.Action", boost::bind(&LLScriptChiclet::onMenuItemClicked, this, _2));
 
-	mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>
+	LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>
 		("menu_script_chiclet.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+	if (menu)
+	{
+		mPopupMenuHandle = menu->getHandle();
+	}
+
 }
 
 //////////////////////////////////////////////////////////////////////////
@@ -1185,8 +1213,12 @@ void LLInvOfferChiclet::createPopupMenu()
 	LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
 	registrar.add("InvOfferChiclet.Action", boost::bind(&LLInvOfferChiclet::onMenuItemClicked, this, _2));
 
-	mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>
+	LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>
 		("menu_inv_offer_chiclet.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+	if (menu)
+	{
+		mPopupMenuHandle = menu->getHandle();
+	}
 }
 
 // EOF
diff --git a/indra/newview/llchiclet.h b/indra/newview/llchiclet.h
index aceedda07eb83c1ce5379308d2e4083b7239cf96..58a797218fd44760b5bcacf0577de8525eddab5b 100644
--- a/indra/newview/llchiclet.h
+++ b/indra/newview/llchiclet.h
@@ -252,7 +252,7 @@ class LLIMChiclet : public LLChiclet
 	{};
 
 	
-	virtual ~LLIMChiclet() {};
+	virtual ~LLIMChiclet();
 
 	/**
 	 * It is used for default setting up of chicklet:click handler, etc.  
@@ -325,7 +325,7 @@ class LLIMChiclet : public LLChiclet
 
 	bool canCreateMenu();
 
-	LLMenuGL* mPopupMenu;
+	LLHandle<LLUICtrl> mPopupMenuHandle;
 
 	bool mShowSpeaker;
 	bool mCounterEnabled;
@@ -519,7 +519,7 @@ class LLSysWellChiclet : public LLChiclet
 	bool mIsNewMessagesState;
 
 	LLFlashTimer* mFlashToLitTimer;
-	LLContextMenu* mContextMenu;
+	LLHandle<LLContextMenu> mContextMenuHandle;
 };
 
 class LLNotificationChiclet : public LLSysWellChiclet
diff --git a/indra/newview/llcommandhandler.cpp b/indra/newview/llcommandhandler.cpp
index 23e2271eae55381e4e42194b58aa8438fbb57764..74f37961c7420043b19edba9df9f6714b98a0225 100644
--- a/indra/newview/llcommandhandler.cpp
+++ b/indra/newview/llcommandhandler.cpp
@@ -39,6 +39,7 @@
 #define THROTTLE_PERIOD    5    // required seconds between throttled commands
 
 static LLCommandDispatcherListener sCommandDispatcherListener;
+const std::string LLCommandHandler::NAV_TYPE_CLICKED = "clicked";
 
 //---------------------------------------------------------------------------
 // Underlying registry for command handlers, not directly accessible.
@@ -64,6 +65,9 @@ class LLCommandHandlerRegistry
 				  bool trusted_browser);
 
 private:
+    void notifySlurlBlocked();
+    void notifySlurlThrottled();
+
 	friend LLSD LLCommandDispatcher::enumerate();
 	std::map<std::string, LLCommandHandlerInfo> mMap;
 };
@@ -96,8 +100,6 @@ bool LLCommandHandlerRegistry::dispatch(const std::string& cmd,
 										const std::string& nav_type,
 										bool trusted_browser)
 {
-	static bool slurl_blocked = false;
-	static bool slurl_throttled = false;
 	static F64 last_throttle_time = 0.0;
 	F64 cur_time = 0.0;
 	std::map<std::string, LLCommandHandlerInfo>::iterator it = mMap.find(cmd);
@@ -115,44 +117,45 @@ bool LLCommandHandlerRegistry::dispatch(const std::string& cmd,
 			// block request from external browser, but report as
 			// "handled" because it was well formatted.
 			LL_WARNS_ONCE("SLURL") << "Blocked SLURL command from untrusted browser" << LL_ENDL;
-			if (! slurl_blocked)
-			{
-				if (LLStartUp::getStartupState() >= STATE_BROWSER_INIT)
-				{
-					// Note: commands can arrive before we initialize everything we need for Notification.
-					LLNotificationsUtil::add("BlockedSLURL");
-				}
-				slurl_blocked = true;
-			}
+            notifySlurlBlocked();
 			return true;
 
+        case LLCommandHandler::UNTRUSTED_CLICK_ONLY:
+            if (nav_type == LLCommandHandler::NAV_TYPE_CLICKED
+                && info.mHandler->canHandleUntrusted(params, query_map, web, nav_type))
+            {
+                break;
+            }
+            LL_WARNS_ONCE("SLURL") << "Blocked SLURL click-only command " << cmd << " from untrusted browser" << LL_ENDL;
+            notifySlurlBlocked();
+            return true;
+
 		case LLCommandHandler::UNTRUSTED_THROTTLE:
+			//skip initial request from external browser before STATE_BROWSER_INIT
+			if (LLStartUp::getStartupState() == STATE_FIRST)
+			{
+				return true;
+			}
+            if (!info.mHandler->canHandleUntrusted(params, query_map, web, nav_type))
+            {
+                LL_WARNS_ONCE("SLURL") << "Blocked SLURL command from untrusted browser" << LL_ENDL;
+                notifySlurlBlocked();
+                return true;
+            }
 			// if users actually click on a link, we don't need to throttle it
 			// (throttling mechanism is used to prevent an avalanche of clicks via
 			// javascript
-			if ( nav_type == "clicked" )
+			if (nav_type == LLCommandHandler::NAV_TYPE_CLICKED)
 			{
 				break;
 			}
-			//skip initial request from external browser before STATE_BROWSER_INIT
-			if (LLStartUp::getStartupState() == STATE_FIRST)
-			{
-				return true;
-			}
 			cur_time = LLTimer::getElapsedSeconds();
 			if (cur_time < last_throttle_time + THROTTLE_PERIOD)
 			{
 				// block request from external browser if it happened
 				// within THROTTLE_PERIOD seconds of the last command
 				LL_WARNS_ONCE("SLURL") << "Throttled SLURL command from untrusted browser" << LL_ENDL;
-				if (! slurl_throttled)
-				{
-					if (LLStartUp::getStartupState() >= STATE_BROWSER_INIT)
-					{
-						LLNotificationsUtil::add("ThrottledSLURL");
-					}
-					slurl_throttled = true;
-				}
+                notifySlurlThrottled();
 				return true;
 			}
 			last_throttle_time = cur_time;
@@ -163,6 +166,34 @@ bool LLCommandHandlerRegistry::dispatch(const std::string& cmd,
 	return info.mHandler->handle(params, query_map, web);
 }
 
+void LLCommandHandlerRegistry::notifySlurlBlocked()
+{
+    static bool slurl_blocked = false;
+    if (!slurl_blocked)
+    {
+        if (LLStartUp::getStartupState() >= STATE_BROWSER_INIT)
+        {
+            // Note: commands can arrive before we initialize everything we need for Notification.
+            LLNotificationsUtil::add("BlockedSLURL");
+        }
+        slurl_blocked = true;
+    }
+}
+
+void LLCommandHandlerRegistry::notifySlurlThrottled()
+{
+    static bool slurl_throttled = false;
+    if (!slurl_throttled)
+    {
+        if (LLStartUp::getStartupState() >= STATE_BROWSER_INIT)
+        {
+            // Note: commands can arrive before we initialize everything we need for Notification.
+            LLNotificationsUtil::add("ThrottledSLURL");
+        }
+        slurl_throttled = true;
+    }
+}
+
 //---------------------------------------------------------------------------
 // Automatic registration of commands, runs before main()
 //---------------------------------------------------------------------------
@@ -230,6 +261,7 @@ symbol_info symbols[] =
 {
 	ent(LLCommandHandler::UNTRUSTED_ALLOW),		  // allow commands from untrusted browsers
 	ent(LLCommandHandler::UNTRUSTED_BLOCK),		  // ignore commands from untrusted browsers
+    ent(LLCommandHandler::UNTRUSTED_CLICK_ONLY),  // allow untrusted, but only if clicked
 	ent(LLCommandHandler::UNTRUSTED_THROTTLE)	  // allow untrusted, but only a few per min.
 };
 
diff --git a/indra/newview/llcommandhandler.h b/indra/newview/llcommandhandler.h
index 1e0895565afc13b94de1ac0db0fdfa7d12289b2a..763e3ee51f3658026305dcdce18e49a8bdf516d1 100644
--- a/indra/newview/llcommandhandler.h
+++ b/indra/newview/llcommandhandler.h
@@ -65,9 +65,12 @@ class LLCommandHandler
 	{
 		UNTRUSTED_ALLOW,       // allow commands from untrusted browsers
 		UNTRUSTED_BLOCK,       // ignore commands from untrusted browsers
+        UNTRUSTED_CLICK_ONLY,  // allow untrusted, but only if clicked
 		UNTRUSTED_THROTTLE     // allow untrusted, but only a few per min.
 	};
 
+    static const std::string NAV_TYPE_CLICKED;
+
 	LLCommandHandler(const char* command, EUntrustedAccess untrusted_access);
 		// Automatically registers object to get called when 
 		// command is executed.  All commands can be processed
@@ -76,6 +79,13 @@ class LLCommandHandler
 		
 	virtual ~LLCommandHandler();
 
+    virtual bool canHandleUntrusted(
+        const LLSD& params,
+        const LLSD& query_map,
+        LLMediaCtrl* web,
+        const std::string& nav_type)
+    { return true; }
+
 	virtual bool handle(const LLSD& params,
 						const LLSD& query_map,
 						LLMediaCtrl* web) = 0;
diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h
index 787deeb594036efa3043bc7564c871d3e63ac644..7c6980a7e659f15bf536197e8283113eae798cba 100644
--- a/indra/newview/llconversationmodel.h
+++ b/indra/newview/llconversationmodel.h
@@ -87,7 +87,7 @@ class LLConversationItem : public LLFolderViewModelItemCommon
 	virtual BOOL removeItem() { return FALSE; }
 	virtual void removeBatch(std::vector<LLFolderViewModelItem*>& batch) { }
 	virtual void move( LLFolderViewModelItem* parent_listener ) { }
-	virtual BOOL isItemCopyable() const { return FALSE; }
+    virtual bool isItemCopyable(bool can_copy_as_link = true) const { return false; }
 	virtual BOOL copyToClipboard() const { return FALSE; }
 	virtual BOOL cutToClipboard() { return FALSE; }
 	virtual BOOL isClipboardPasteable() const { return FALSE; }
diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp
index 8db6a10e2685a539369219ac4a0f241c64aad1fd..c4c88d304c09bf5e841f880f66de9d805a67b55d 100644
--- a/indra/newview/lldrawpoolbump.cpp
+++ b/indra/newview/lldrawpoolbump.cpp
@@ -41,6 +41,7 @@
 #include "lldrawable.h"
 #include "llface.h"
 #include "llsky.h"
+#include "llstartup.h"
 #include "lltextureentry.h"
 #include "llviewercamera.h"
 #include "llviewertexturelist.h"
@@ -79,11 +80,6 @@ static S32 bump_channel = -1;
 
 #define LL_BUMPLIST_MULTITHREADED 0 // TODO -- figure out why this doesn't work
 
-// static 
-void LLStandardBumpmap::init()
-{
-	LLStandardBumpmap::restoreGL();
-}
 
 // static 
 void LLStandardBumpmap::shutdown()
@@ -94,7 +90,7 @@ void LLStandardBumpmap::shutdown()
 // static 
 void LLStandardBumpmap::restoreGL()
 {
-	addstandard();
+    addstandard();
 }
 
 // static
@@ -107,6 +103,12 @@ void LLStandardBumpmap::addstandard()
 		return ;
 	}
 
+    if (LLStartUp::getStartupState() < STATE_SEED_CAP_GRANTED)
+    {
+        // Not ready, need caps for images
+        return;
+    }
+
 	// can't assert; we destroyGL and restoreGL a lot during *first* startup, which populates this list already, THEN we explicitly init the list as part of *normal* startup.  Sigh.  So clear the list every time before we (re-)add the standard bumpmaps.
 	//llassert( LLStandardBumpmap::sStandardBumpmapCount == 0 );
 	clear();
@@ -769,8 +771,6 @@ void LLBumpImageList::init()
 	llassert( mBrightnessEntries.size() == 0 );
 	llassert( mDarknessEntries.size() == 0 );
 
-	LLStandardBumpmap::init();
-
 	LLStandardBumpmap::restoreGL();
     sMainQueue = LL::WorkQueue::getInstance("mainloop");
     sTexUpdateQueue = LL::WorkQueue::getInstance("LLImageGL"); // Share work queue with tex loader.
diff --git a/indra/newview/lldrawpoolbump.h b/indra/newview/lldrawpoolbump.h
index e8a027967bcca922e44c560f2471874a1c22bed1..cf463f4458ecc48981628764271a63204d90cbbe 100644
--- a/indra/newview/lldrawpoolbump.h
+++ b/indra/newview/lldrawpoolbump.h
@@ -118,7 +118,6 @@ class LLStandardBumpmap
 	static void clear();
 	static void addstandard();
 
-	static void init();
 	static void shutdown();
 	static void restoreGL();
 	static void destroyGL();
diff --git a/indra/newview/llenvironment.cpp b/indra/newview/llenvironment.cpp
index 1300cf3658a8be5cee521b241bdf72f917712456..05c7decfbdaaa62e1aa08a752bd1734f0e4d38c4 100644
--- a/indra/newview/llenvironment.cpp
+++ b/indra/newview/llenvironment.cpp
@@ -684,7 +684,6 @@ namespace
             if (!injection->mBlendIn)
                 mix = 1.0 - mix;
             stringset_t dummy;
-            LLUUID cloud_noise_id = getCloudNoiseTextureId();
             F64 value = this->mSettings[injection->mKeyName].asReal();
             if (this->getCloudNoiseTextureId().isNull())
             {
@@ -874,26 +873,37 @@ void LLEnvironment::initSingleton()
 
     requestRegion();
 
-    gAgent.addParcelChangedCallback([this]() { onParcelChange(); });
+    if (!mParcelCallbackConnection.connected())
+    {
+        mParcelCallbackConnection = gAgent.addParcelChangedCallback([this]() { onParcelChange(); });
 
-    //TODO: This frequently results in one more request than we need.  It isn't breaking, but should be nicer.
-    // We need to know new env version to fix this, without it we can only do full re-request
-    // Happens: on updates, on opening LLFloaterRegionInfo, on region crossing if info floater is open
-    LLRegionInfoModel::instance().setUpdateCallback([this]() { requestRegion(); });
-    gAgent.addRegionChangedCallback([this]() { onRegionChange(); });
+        //TODO: This frequently results in one more request than we need.  It isn't breaking, but should be nicer.
+        // We need to know new env version to fix this, without it we can only do full re-request
+        // Happens: on updates, on opening LLFloaterRegionInfo, on region crossing if info floater is open
+        mRegionUpdateCallbackConnection = LLRegionInfoModel::instance().setUpdateCallback([this]() { requestRegion(); });
+        mRegionChangeCallbackConnection = gAgent.addRegionChangedCallback([this]() { onRegionChange(); });
 
-    gAgent.whenPositionChanged([this](const LLVector3 &localpos, const LLVector3d &) { onAgentPositionHasChanged(localpos); });
+        mPositionCallbackConnection = gAgent.whenPositionChanged([this](const LLVector3 &localpos, const LLVector3d &) { onAgentPositionHasChanged(localpos); });
+    }
 
     if (!gGenericDispatcher.isHandlerPresent(MESSAGE_PUSHENVIRONMENT))
     {
         gGenericDispatcher.addHandler(MESSAGE_PUSHENVIRONMENT, &environment_push_dispatch_handler);
     }
 
+    LLEventPumps::instance().obtain(PUMP_EXPERIENCE).stopListening(LISTENER_NAME);
     LLEventPumps::instance().obtain(PUMP_EXPERIENCE).listen(LISTENER_NAME, [this](LLSD message) { listenExperiencePump(message); return false; });
 }
 
 void LLEnvironment::cleanupSingleton()
 {
+    if (mParcelCallbackConnection.connected())
+    {
+        mParcelCallbackConnection.disconnect();
+        mRegionUpdateCallbackConnection.disconnect();
+        mRegionChangeCallbackConnection.disconnect();
+        mPositionCallbackConnection.disconnect();
+    }
     LLEventPumps::instance().obtain(PUMP_EXPERIENCE).stopListening(LISTENER_NAME);
 }
 
@@ -3086,7 +3096,7 @@ bool LLEnvironment::loadFromSettings()
         LL_INFOS("ENVIRONMENT") << "Unable to open previous session environment file " << user_filepath << LL_ENDL;
     }
 
-    if (!env_data.isMap() || env_data.emptyMap())
+    if (!env_data.isMap() || (env_data.size() == 0))
     {
         LL_DEBUGS("ENVIRONMENT") << "Empty map loaded from: " << user_filepath << LL_ENDL;
         return false;
diff --git a/indra/newview/llenvironment.h b/indra/newview/llenvironment.h
index 330de2bea87da56123b2164818e82dff3c237251..64fd170e43c51194ce187c0e8a1d5451f1328586 100644
--- a/indra/newview/llenvironment.h
+++ b/indra/newview/llenvironment.h
@@ -402,6 +402,11 @@ class LLEnvironment : public LLSimpleton<LLEnvironment>
     bool                        mShowMoonBeacon;
     S32                         mEditorCounter;
 
+    connection_t                mParcelCallbackConnection;
+    connection_t                mRegionUpdateCallbackConnection;
+    connection_t                mRegionChangeCallbackConnection;
+    connection_t                mPositionCallbackConnection;
+
     struct UpdateInfo
     {
         typedef std::shared_ptr<UpdateInfo> ptr_t;
diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp
index 3669fb1eeb000e103e5a2187ac829b901d39a810..e3a695fc79b8d091d2ce531dc53a3175fe32b78e 100644
--- a/indra/newview/llfilepicker.cpp
+++ b/indra/newview/llfilepicker.cpp
@@ -586,9 +586,9 @@ BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const std::string& filename,
 
 #elif LL_DARWIN
 
-std::vector<std::string>* LLFilePicker::navOpenFilterProc(ELoadFilter filter) //(AEDesc *theItem, void *info, void *callBackUD, NavFilterModes filterMode)
+std::unique_ptr<std::vector<std::string>> LLFilePicker::navOpenFilterProc(ELoadFilter filter) //(AEDesc *theItem, void *info, void *callBackUD, NavFilterModes filterMode)
 {
-    std::vector<std::string> *allowedv = new std::vector< std::string >;
+    std::unique_ptr<std::vector<std::string>> allowedv(new std::vector< std::string >);
     switch(filter)
     {
         case FFLOAD_ALL:
@@ -661,9 +661,9 @@ bool	LLFilePicker::doNavChooseDialog(ELoadFilter filter)
     
 	gViewerWindow->getWindow()->beforeDialog();
     
-    std::vector<std::string> *allowed_types=navOpenFilterProc(filter);
+    std::unique_ptr<std::vector<std::string>> allowed_types = navOpenFilterProc(filter);
     
-    std::vector<std::string> *filev  = doLoadDialog(allowed_types, 
+    std::unique_ptr<std::vector<std::string>> filev  = doLoadDialog(allowed_types.get(),
                                                     mPickOptions);
 
 	gViewerWindow->getWindow()->afterDialog();
@@ -780,7 +780,7 @@ bool	LLFilePicker::doNavSaveDialog(ESaveFilter filter, const std::string& filena
 	gViewerWindow->getWindow()->beforeDialog();
 
 	// Run the dialog
-    std::string* filev = doSaveDialog(&namestring, 
+    std::unique_ptr<std::string> filev = doSaveDialog(&namestring, 
                  &type,
                  &creator,
                  &extension,
diff --git a/indra/newview/llfilepicker.h b/indra/newview/llfilepicker.h
index 04ba4416d7ef2e379b0c40fa8749592bc6dd1e61..73baeca1c01c75b08e2c81a8101e23f179a768e8 100644
--- a/indra/newview/llfilepicker.h
+++ b/indra/newview/llfilepicker.h
@@ -167,7 +167,7 @@ class LLFilePicker
 	
 	bool doNavChooseDialog(ELoadFilter filter);
 	bool doNavSaveDialog(ESaveFilter filter, const std::string& filename);
-    std::vector<std::string>* navOpenFilterProc(ELoadFilter filter);
+    std::unique_ptr<std::vector<std::string>> navOpenFilterProc(ELoadFilter filter);
 #endif
 
 #if LL_GTK
diff --git a/indra/newview/llfilepicker_mac.h b/indra/newview/llfilepicker_mac.h
index e0b7e2e8ce01105c6004824087d46ffc944523d8..b2fb371afea595150aca1dee82e4a955d0e09724 100644
--- a/indra/newview/llfilepicker_mac.h
+++ b/indra/newview/llfilepicker_mac.h
@@ -39,9 +39,9 @@
 #include <vector>
 
 //void modelessPicker();
-std::vector<std::string>* doLoadDialog(const std::vector<std::string>* allowed_types, 
+std::unique_ptr<std::vector<std::string>> doLoadDialog(const std::vector<std::string>* allowed_types,
                  unsigned int flags);
-std::string* doSaveDialog(const std::string* file, 
+std::unique_ptr<std::string> doSaveDialog(const std::string* file, 
                   const std::string* type,
                   const std::string* creator,
                   const std::string* extension,
diff --git a/indra/newview/llfilepicker_mac.mm b/indra/newview/llfilepicker_mac.mm
index 1438e4dc0a993c69d23bae424a2b0363a0452bb2..0ae5fc3f774dc74a5f34b13e0de4012f21c9341b 100644
--- a/indra/newview/llfilepicker_mac.mm
+++ b/indra/newview/llfilepicker_mac.mm
@@ -29,104 +29,107 @@
 #include <iostream>
 #include "llfilepicker_mac.h"
 
-std::vector<std::string>* doLoadDialog(const std::vector<std::string>* allowed_types, 
+std::unique_ptr<std::vector<std::string>> doLoadDialog(const std::vector<std::string>* allowed_types,
                  unsigned int flags)
 {
-    int i, result;
-    
-    //Aura TODO:  We could init a small window and release it at the end of this routine
-    //for a modeless interface.
-    
-    NSOpenPanel *panel = [NSOpenPanel openPanel];
-    //NSString *fileName = nil;
-    NSMutableArray *fileTypes = nil;
-    
-    
-    if ( allowed_types && !allowed_types->empty()) 
-    {
-        fileTypes = [[NSMutableArray alloc] init];
+    std::unique_ptr<std::vector<std::string>> outfiles;
+
+    @autoreleasepool {
+        int i, result;
+        //Aura TODO:  We could init a small window and release it at the end of this routine
+        //for a modeless interface.
+        
+        NSOpenPanel *panel = [NSOpenPanel openPanel];
+        //NSString *fileName = nil;
+        NSMutableArray *fileTypes = nil;
         
-        for (i=0;i<allowed_types->size();++i)
+        if ( allowed_types && !allowed_types->empty())
         {
-            [fileTypes addObject: 
-             [NSString stringWithCString:(*allowed_types)[i].c_str() 
-                                encoding:[NSString defaultCStringEncoding]]];
+            fileTypes = [[[NSMutableArray alloc] init] autorelease];
+            
+            for (i=0;i<allowed_types->size();++i)
+            {
+                [fileTypes addObject:
+                 [NSString stringWithCString:(*allowed_types)[i].c_str()
+                                    encoding:[NSString defaultCStringEncoding]]];
+            }
         }
-    }
         
-    //[panel setMessage:@"Import one or more files or directories."];
-    [panel setAllowsMultipleSelection: ( (flags & F_MULTIPLE)?true:false ) ];
-    [panel setCanChooseDirectories: ( (flags & F_DIRECTORY)?true:false ) ];
-    [panel setCanCreateDirectories: true];
-    [panel setResolvesAliases: true];
-    [panel setCanChooseFiles: ( (flags & F_FILE)?true:false )];
-    [panel setTreatsFilePackagesAsDirectories: ( flags & F_NAV_SUPPORT ) ];
-    
-    std::vector<std::string>* outfiles = NULL; 
-    
-    if (fileTypes)
-    {
-        [panel setAllowedFileTypes:fileTypes];
-        result = [panel runModal];
-    }
-    else 
-    {
-        // I suggest it's better to open the last path and let this default to home dir as necessary
-        // for consistency with other OS X apps
-        //
-        //[panel setDirectoryURL: fileURLWithPath(NSHomeDirectory()) ];
-        result = [panel runModal];
-    }
-    
-    if (result == NSOKButton) 
-    {
-        NSArray *filesToOpen = [panel URLs];
-        int i, count = [filesToOpen count];
+        //[panel setMessage:@"Import one or more files or directories."];
+        [panel setAllowsMultipleSelection: ( (flags & F_MULTIPLE)?true:false ) ];
+        [panel setCanChooseDirectories: ( (flags & F_DIRECTORY)?true:false ) ];
+        [panel setCanCreateDirectories: true];
+        [panel setResolvesAliases: true];
+        [panel setCanChooseFiles: ( (flags & F_FILE)?true:false )];
+        [panel setTreatsFilePackagesAsDirectories: ( flags & F_NAV_SUPPORT ) ];
         
-        if (count > 0)
+        if (fileTypes)
+        {
+            [panel setAllowedFileTypes:fileTypes];
+            result = [panel runModal];
+        }
+        else
         {
-            outfiles = new std::vector<std::string>;
+            // I suggest it's better to open the last path and let this default to home dir as necessary
+            // for consistency with other OS X apps
+            //
+            //[panel setDirectoryURL: fileURLWithPath(NSHomeDirectory()) ];
+            result = [panel runModal];
         }
         
-        for (i=0; i<count; i++) {
-            NSString *aFile = [[filesToOpen objectAtIndex:i] path];
-            std::string *afilestr = new std::string([aFile UTF8String]);
-            outfiles->push_back(*afilestr);
+        if (result == NSOKButton)
+        {
+            NSArray *filesToOpen = [panel URLs];
+            int i, count = [filesToOpen count];
+            
+            if (count > 0)
+            {
+                outfiles.reset(new std::vector<std::string>);
+            }
+            
+            for (i=0; i<count; i++) {
+                NSString *aFile = [[filesToOpen objectAtIndex:i] path];
+                std::string afilestr = std::string([aFile UTF8String]);
+                outfiles->push_back(afilestr);
+            }
         }
     }
+
     return outfiles;
 }
 
 
-std::string* doSaveDialog(const std::string* file, 
+std::unique_ptr<std::string> doSaveDialog(const std::string* file,
                   const std::string* type,
                   const std::string* creator,
                   const std::string* extension,
                   unsigned int flags)
 {
-    NSSavePanel *panel = [NSSavePanel savePanel]; 
-    
-    NSString *extensionns = [NSString stringWithCString:extension->c_str() encoding:[NSString defaultCStringEncoding]];
-    NSArray *fileType = [extensionns componentsSeparatedByString:@","];
-    
-    //[panel setMessage:@"Save Image File"]; 
-    [panel setTreatsFilePackagesAsDirectories: ( flags & F_NAV_SUPPORT ) ];
-    [panel setCanSelectHiddenExtension:true]; 
-    [panel setAllowedFileTypes:fileType];
-    NSString *fileName = [NSString stringWithCString:file->c_str() encoding:[NSString defaultCStringEncoding]];
-    
-    std::string *outfile = NULL;
-    NSURL* url = [NSURL fileURLWithPath:fileName];
-    [panel setNameFieldStringValue: fileName];
-    [panel setDirectoryURL: url];
-    if([panel runModal] == 
-       NSFileHandlingPanelOKButton) 
-    {
-        NSURL* url = [panel URL];
-        NSString* p = [url path];
-        outfile = new std::string( [p UTF8String] );
-        // write the file 
-    } 
+    std::unique_ptr<std::string> outfile;
+    @autoreleasepool {
+        NSSavePanel *panel = [NSSavePanel savePanel];
+        
+        NSString *extensionns = [NSString stringWithCString:extension->c_str() encoding:[NSString defaultCStringEncoding]];
+        NSArray *fileType = [extensionns componentsSeparatedByString:@","];
+        
+        //[panel setMessage:@"Save Image File"];
+        [panel setTreatsFilePackagesAsDirectories: ( flags & F_NAV_SUPPORT ) ];
+        [panel setCanSelectHiddenExtension:true];
+        [panel setAllowedFileTypes:fileType];
+        NSString *fileName = [NSString stringWithCString:file->c_str() encoding:[NSString defaultCStringEncoding]];
+        
+        NSURL* url = [NSURL fileURLWithPath:fileName];
+        [panel setNameFieldStringValue: fileName];
+        [panel setDirectoryURL: url];
+        if([panel runModal] ==
+           NSFileHandlingPanelOKButton)
+        {
+            NSURL* url = [panel URL];
+            NSString* p = [url path];
+            outfile.reset(new std::string([p UTF8String]));
+            // write the file
+        }
+    }
     return outfile;
 }
 
diff --git a/indra/newview/llfloater360capture.cpp b/indra/newview/llfloater360capture.cpp
index c075f7e8bdd3f9be33733f96677bf866830bb0d5..eff94bd1951a0422e7e55da75bef1880c4e13d7f 100644
--- a/indra/newview/llfloater360capture.cpp
+++ b/indra/newview/llfloater360capture.cpp
@@ -84,7 +84,7 @@ LLFloater360Capture::~LLFloater360Capture()
     // Tell the Simulator not to send us everything anymore
     // and revert to the regular "keyhole" frustum of interest
     // list updates.
-    if (gSavedSettings.getBOOL("360CaptureUseInterestListCap"))
+    if (!LLApp::isExiting() && gSavedSettings.getBOOL("360CaptureUseInterestListCap"))
     {
         const bool send_everything = false;
         changeInterestListMode(send_everything);
@@ -537,7 +537,8 @@ void LLFloater360Capture::capture360Images()
     // We need to convert from the angle getYaw() gives us into something
     // the XMP data field wants (N=0, E=90, S=180, W= 270 etc.)
     mInitialHeadingDeg  = (360 + 90 - (int)(camera->getYaw() * RAD_TO_DEG)) % 360;
-    LL_INFOS("360Capture") << "Recording a heading of " << (int)(mInitialHeadingDeg) << LL_ENDL;
+    LL_INFOS("360Capture") << "Recording a heading of " << (int)(mInitialHeadingDeg)
+        << " Image size: " << (S32)mSourceImageSize << LL_ENDL;
 
     // camera constants for the square, cube map capture image
     camera->setAspect(1.0); // must set aspect ratio first to avoid undesirable clamping of vertical FoV
@@ -587,6 +588,9 @@ void LLFloater360Capture::capture360Images()
     // for each of the 6 directions we shoot...
     for (int i = 0; i < 6; i++)
     {
+        LLAppViewer::instance()->pauseMainloopTimeout();
+        LLViewerStats::instance().getRecording().stop();
+
         // these buffers are where the raw, captured pixels are stored and
         // the first time we use them, we have to make a new one
         if (mRawImages[i] == nullptr)
@@ -624,8 +628,10 @@ void LLFloater360Capture::capture360Images()
         auto duration = std::chrono::duration_cast<std::chrono::duration<double>>(t_end - t_start);
         encode_time_total += duration.count();
 
-        // ping the main loop in case the snapshot process takes a really long
-        // time and we get disconnected
+        LLViewerStats::instance().getRecording().resume();
+        LLAppViewer::instance()->resumeMainloopTimeout();
+        
+        // update main loop timeout state
         LLAppViewer::instance()->pingMainloopTimeout("LLFloater360Capture::capture360Images");
     }
 
diff --git a/indra/newview/llfloateravatar.cpp b/indra/newview/llfloateravatar.cpp
index 31adf5b61e23c86feef9f534dc203dcf61b46472..f888d032aec1f22576d02367facac8c01e934600 100644
--- a/indra/newview/llfloateravatar.cpp
+++ b/indra/newview/llfloateravatar.cpp
@@ -44,17 +44,21 @@ LLFloaterAvatar::LLFloaterAvatar(const LLSD& key)
 
 LLFloaterAvatar::~LLFloaterAvatar()
 {
-	LLMediaCtrl* avatar_picker = findChild<LLMediaCtrl>("avatar_picker_contents");
-	if (avatar_picker)
+	if (mAvatarPicker)
 	{
-		avatar_picker->navigateStop();
-		avatar_picker->clearCache();          //images are reloading each time already
-		avatar_picker->unloadMediaSource();
+		mAvatarPicker->navigateStop();
+        mAvatarPicker->clearCache();          //images are reloading each time already
+        mAvatarPicker->unloadMediaSource();
 	}
 }
 
 BOOL LLFloaterAvatar::postBuild()
 {
+    mAvatarPicker = findChild<LLMediaCtrl>("avatar_picker_contents");
+    if (mAvatarPicker)
+    {
+        mAvatarPicker->clearCache();
+    }
 	enableResizeCtrls(true, true, false);
 	return TRUE;
 }
diff --git a/indra/newview/llfloateravatar.h b/indra/newview/llfloateravatar.h
index cadc5e4028be24ed39f4bec922eaf4f3469bc81d..76e93727092a018e16f35b242d99f96b65ce19a2 100644
--- a/indra/newview/llfloateravatar.h
+++ b/indra/newview/llfloateravatar.h
@@ -29,6 +29,7 @@
 #define LL_FLOATER_AVATAR_H
 
 #include "llfloater.h"
+class LLMediaCtrl;
 
 class LLFloaterAvatar:
 	public LLFloater
@@ -38,6 +39,8 @@ class LLFloaterAvatar:
 	LLFloaterAvatar(const LLSD& key);
 	/*virtual*/	~LLFloaterAvatar();
 	/*virtual*/	BOOL postBuild();
+
+    LLMediaCtrl* mAvatarPicker;
 };
 
 #endif
diff --git a/indra/newview/llfloaterbump.cpp b/indra/newview/llfloaterbump.cpp
index 33e4c7cd5fded23519bdd09ae71354cab3e104c0..307ab8c4d1d68e0fc797ba749d89d3a967bbe39d 100644
--- a/indra/newview/llfloaterbump.cpp
+++ b/indra/newview/llfloaterbump.cpp
@@ -69,6 +69,12 @@ LLFloaterBump::LLFloaterBump(const LLSD& key)
 // Destroys the object
 LLFloaterBump::~LLFloaterBump()
 {
+	auto menu = mPopupMenuHandle.get();
+	if (menu)
+	{
+		menu->die();
+		mPopupMenuHandle.markDead();
+	}
 }
 
 BOOL LLFloaterBump::postBuild()
@@ -77,11 +83,15 @@ BOOL LLFloaterBump::postBuild()
 	mList->setAllowMultipleSelection(false);
 	mList->setRightMouseDownCallback(boost::bind(&LLFloaterBump::onScrollListRightClicked, this, _1, _2, _3));
 
-	mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>("menu_avatar_other.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
-	mPopupMenu->setItemVisible(std::string("Normal"), false);
-	mPopupMenu->setItemVisible(std::string("Always use impostor"), false);
-	mPopupMenu->setItemVisible(std::string("Never use impostor"), false);
-	mPopupMenu->setItemVisible(std::string("Impostor seperator"), false);
+	LLContextMenu* menu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>("menu_avatar_other.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+	if (menu)
+	{
+		mPopupMenuHandle = menu->getHandle();
+		menu->setItemVisible(std::string("Normal"), false);
+		menu->setItemVisible(std::string("Always use impostor"), false);
+		menu->setItemVisible(std::string("Never use impostor"), false);
+		menu->setItemVisible(std::string("Impostor seperator"), false);
+	}
 
 	return TRUE;
 }
@@ -176,18 +186,19 @@ void LLFloaterBump::onScrollListRightClicked(LLUICtrl* ctrl, S32 x, S32 y)
 	if (!gMeanCollisionList.empty())
 	{
 		LLScrollListItem* item = mList->hitItem(x, y);
-		if (item && mPopupMenu)
+		auto menu = mPopupMenuHandle.get();
+		if (item && menu)
 		{
 			mItemUUID = item->getUUID();
-			mPopupMenu->buildDrawLabels();
-			mPopupMenu->updateParent(LLMenuGL::sMenuContainer);
+			menu->buildDrawLabels();
+			menu->updateParent(LLMenuGL::sMenuContainer);
 
 			std::string mute_msg = (LLMuteList::getInstance()->isMuted(mItemUUID, mNames[mItemUUID])) ? "UnmuteAvatar" : "MuteAvatar";
-			mPopupMenu->getChild<LLUICtrl>("Avatar Mute")->setValue(LLTrans::getString(mute_msg));
-			mPopupMenu->setItemEnabled(std::string("Zoom In"), bool(gObjectList.findObject(mItemUUID)));
+			menu->getChild<LLUICtrl>("Avatar Mute")->setValue(LLTrans::getString(mute_msg));
+			menu->setItemEnabled(std::string("Zoom In"), bool(gObjectList.findObject(mItemUUID)));
 
-			((LLContextMenu*)mPopupMenu)->show(x, y);
-			LLMenuGL::showPopup(ctrl, mPopupMenu, x, y);
+			menu->show(x, y);
+			LLMenuGL::showPopup(ctrl, menu, x, y);
 		}
 	}
 }
diff --git a/indra/newview/llfloaterbump.h b/indra/newview/llfloaterbump.h
index ce52c75255fd42f447a560e1bfaa7a16047b854d..d2f9fabdd335d5ff261af301f25e7415421381ca 100644
--- a/indra/newview/llfloaterbump.h
+++ b/indra/newview/llfloaterbump.h
@@ -68,7 +68,7 @@ class LLFloaterBump
 	virtual ~LLFloaterBump();
 
 	LLScrollListCtrl* mList;
-	LLMenuGL* mPopupMenu;
+	LLHandle<LLContextMenu> mPopupMenuHandle;
 	LLUUID mItemUUID;
 
 	typedef std::map<LLUUID, std::string> uuid_map_t;
diff --git a/indra/newview/llfloatercreatelandmark.cpp b/indra/newview/llfloatercreatelandmark.cpp
index 7def855d83cd945d496c4f845becbbe066f2b894..b82d8a29ba4b266af195ca40c3656eb892c6f80d 100644
--- a/indra/newview/llfloatercreatelandmark.cpp
+++ b/indra/newview/llfloatercreatelandmark.cpp
@@ -316,7 +316,6 @@ void LLFloaterCreateLandmark::onSaveClicked()
 	LLStringUtil::trim(current_title_value);
 	LLStringUtil::trim(current_notes_value);
 
-	LLUUID item_id = mItem->getUUID();
 	LLUUID folder_id = mFolderCombo->getValue().asUUID();
 	bool change_parent = folder_id != mItem->getParentUUID();
 
diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp
index 703b5d0011b4098fac38052e603553367746cab4..2720b7fcf7756cf57c51642c72ed3e695218a254 100644
--- a/indra/newview/llfloaterimcontainer.cpp
+++ b/indra/newview/llfloaterimcontainer.cpp
@@ -211,6 +211,7 @@ BOOL LLFloaterIMContainer::postBuild()
     p.options_menu = "menu_conversation.xml";
 	mConversationsRoot = LLUICtrlFactory::create<LLFolderView>(p);
     mConversationsRoot->setCallbackRegistrar(&mCommitCallbackRegistrar);
+	mConversationsRoot->setEnableRegistrar(&mEnableCallbackRegistrar);
 
 	// Add listener to conversation model events
 	mConversationsEventStream.listen("ConversationsRefresh", boost::bind(&LLFloaterIMContainer::onConversationModelEvent, this, _1));
diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp
index 4cceddeefb455077dcefd7fd6e8f96cb6c607aa2..f1807f1c5bea465b1ce60e4cd19ea4424aed46c3 100644
--- a/indra/newview/llfloaterimnearbychat.cpp
+++ b/indra/newview/llfloaterimnearbychat.cpp
@@ -307,7 +307,6 @@ void LLFloaterIMNearbyChat::onOpen(const LLSD& key)
 		restoreFloater();
 		onCollapseToLine(this);
 	}
-	showTranslationCheckbox(LLTranslate::isTranslationConfigured());
 }
 
 // virtual
diff --git a/indra/newview/llfloaterimsession.cpp b/indra/newview/llfloaterimsession.cpp
index 48e2b8dc140f6d1d17043f4436c01e11d1b058e0..ee9dc35283242de6e6a52c7585dc2ff50d8cec20 100644
--- a/indra/newview/llfloaterimsession.cpp
+++ b/indra/newview/llfloaterimsession.cpp
@@ -842,6 +842,7 @@ void LLFloaterIMSession::updateMessages()
 			std::string from = msg["from"].asString();
 			std::string message = msg["message"].asString();
 			bool is_history = msg["is_history"].asBoolean();
+			bool is_region_msg = msg["is_region_msg"].asBoolean();
 
 			LLChat chat;
 			chat.mFromID = from_id;
@@ -849,6 +850,10 @@ void LLFloaterIMSession::updateMessages()
 			chat.mFromName = from;
 			chat.mTimeStr = time;
 			chat.mChatStyle = is_history ? CHAT_STYLE_HISTORY : chat.mChatStyle;
+            if (is_region_msg)
+            {
+                chat.mSourceType = CHAT_SOURCE_REGION;
+            }
 
 			// process offer notification
 			if (msg.has("notification_id"))
diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp
index 93a0b39e023189167cdd50b4279c923e27b9da81..78271369d217770545fec211f82aec26381fc64a 100644
--- a/indra/newview/llfloaterimsessiontab.cpp
+++ b/indra/newview/llfloaterimsessiontab.cpp
@@ -253,7 +253,6 @@ BOOL LLFloaterIMSessionTab::postBuild()
 	mGearBtn = getChild<LLButton>("gear_btn");
     mAddBtn = getChild<LLButton>("add_btn");
 	mVoiceButton = getChild<LLButton>("voice_call_btn");
-    mTranslationCheckBox = getChild<LLUICtrl>("translate_chat_checkbox_lp");
     
 	mParticipantListPanel = getChild<LLLayoutPanel>("speakers_list_panel");
 	mRightPartPanel = getChild<LLLayoutPanel>("right_part_holder");
@@ -317,6 +316,7 @@ BOOL LLFloaterIMSessionTab::postBuild()
     p.name = "root";
 	mConversationsRoot = LLUICtrlFactory::create<LLFolderView>(p);
     mConversationsRoot->setCallbackRegistrar(&mCommitCallbackRegistrar);
+	mConversationsRoot->setEnableRegistrar(&mEnableCallbackRegistrar);
 	// Attach that root to the scroller
 	mScroller->addChild(mConversationsRoot);
 	mConversationsRoot->setScrollContainer(mScroller);
@@ -811,8 +811,6 @@ void LLFloaterIMSessionTab::updateHeaderAndToolbar()
 	mCloseBtn->setVisible(is_not_torn_off && !mIsNearbyChat);
 
 	enableDisableCallBtn();
-
-	showTranslationCheckbox();
 }
  
 void LLFloaterIMSessionTab::forceReshape()
@@ -829,11 +827,6 @@ void LLFloaterIMSessionTab::reshapeChatLayoutPanel()
 	mChatLayoutPanel->reshape(mChatLayoutPanel->getRect().getWidth(), mInputEditor->getRect().getHeight() + mInputEditorPad, FALSE);
 }
 
-void LLFloaterIMSessionTab::showTranslationCheckbox(BOOL show)
-{
-	mTranslationCheckBox->setVisible(mIsNearbyChat && show);
-}
-
 // static
 void LLFloaterIMSessionTab::processChatHistoryStyleUpdate(bool clean_messages/* = false*/)
 {
diff --git a/indra/newview/llfloaterimsessiontab.h b/indra/newview/llfloaterimsessiontab.h
index 375461cfc173ce0190af1ef5a4844c59b997ab41..9f009176475585acf74972f6f4dcb7758688ee2e 100644
--- a/indra/newview/llfloaterimsessiontab.h
+++ b/indra/newview/llfloaterimsessiontab.h
@@ -71,8 +71,6 @@ class LLFloaterIMSessionTab
     static LLFloaterIMSessionTab* findConversation(const LLUUID& uuid);
     static LLFloaterIMSessionTab* getConversation(const LLUUID& uuid);
 
-	// show/hide the translation check box
-	void showTranslationCheckbox(const BOOL visible = FALSE);
 
 	bool isNearbyChat() {return mIsNearbyChat;}
 
@@ -187,7 +185,6 @@ class LLFloaterIMSessionTab
 	LLButton* mGearBtn;
 	LLButton* mAddBtn;
     LLButton* mVoiceButton;
-    LLUICtrl* mTranslationCheckBox;
 
 private:
 	// Handling selection and contextual menu
diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp
index 66a245b779598d2eff0d48a2999ed185df3a9d4f..6f8f73bca0f6a5348d665a4ae249c6bf1e0f4bca 100644
--- a/indra/newview/llfloatermodelpreview.cpp
+++ b/indra/newview/llfloatermodelpreview.cpp
@@ -1740,7 +1740,7 @@ void LLFloaterModelPreview::toggleCalculateButton(bool visible)
 		childSetTextArg("download_weight", "[ST]", tbd);
 		childSetTextArg("server_weight", "[SIM]", tbd);
 		childSetTextArg("physics_weight", "[PH]", tbd);
-		if (!mModelPhysicsFee.isMap() || mModelPhysicsFee.emptyMap())
+		if (!mModelPhysicsFee.isMap() || (mModelPhysicsFee.size() == 0))
 		{
 			childSetTextArg("upload_fee", "[FEE]", tbd);
 		}
diff --git a/indra/newview/llfloateropenobject.cpp b/indra/newview/llfloateropenobject.cpp
index 2a1749bd42bd872394a3bef23b48eb4bc9b82aa0..a682064dad498ad8dab48b8d2365ba8ae1c5282a 100644
--- a/indra/newview/llfloateropenobject.cpp
+++ b/indra/newview/llfloateropenobject.cpp
@@ -56,8 +56,6 @@ LLFloaterOpenObject::LLFloaterOpenObject(const LLSD& key)
 	mDirty(TRUE)
 {
 	mCommitCallbackRegistrar.add("OpenObject.MoveToInventory",	boost::bind(&LLFloaterOpenObject::onClickMoveToInventory, this));
-	mCommitCallbackRegistrar.add("OpenObject.MoveAndWear",		boost::bind(&LLFloaterOpenObject::onClickMoveAndWear, this));
-	mCommitCallbackRegistrar.add("OpenObject.ReplaceOutfit",	boost::bind(&LLFloaterOpenObject::onClickReplace, this));
 	mCommitCallbackRegistrar.add("OpenObject.Cancel",			boost::bind(&LLFloaterOpenObject::onClickCancel, this));
 }
 
@@ -243,18 +241,6 @@ void LLFloaterOpenObject::onClickMoveToInventory()
 	closeFloater();
 }
 
-void LLFloaterOpenObject::onClickMoveAndWear()
-{
-	moveToInventory(true, false);
-	closeFloater();
-}
-
-void LLFloaterOpenObject::onClickReplace()
-{
-	moveToInventory(true, true);
-	closeFloater();
-}
-
 void LLFloaterOpenObject::onClickCancel()
 {
 	closeFloater();
diff --git a/indra/newview/llfloateropenobject.h b/indra/newview/llfloateropenobject.h
index 2e761f99bfb241c6b8e87732defe356e4bdb47d3..745753316bed0cb5e53af42ec2cf0caa52c20cbc 100644
--- a/indra/newview/llfloateropenobject.h
+++ b/indra/newview/llfloateropenobject.h
@@ -63,8 +63,6 @@ class LLFloaterOpenObject
 	void moveToInventory(bool wear, bool replace = false);
 
 	void onClickMoveToInventory();
-	void onClickMoveAndWear();
-	void onClickReplace();
 	void onClickCancel();
 	static void callbackCreateInventoryCategory(const LLUUID& category_id, LLUUID object_id, bool wear, bool replace = false);
 	static void callbackMoveInventory(S32 result, void* data);
diff --git a/indra/newview/llfloateroutfitphotopreview.cpp b/indra/newview/llfloateroutfitphotopreview.cpp
index 6c39db730c33c40b0f86a3d0a2661d6a9c24368f..ade258aef74ee07ffbc8a95c8cfe811ee40139f5 100644
--- a/indra/newview/llfloateroutfitphotopreview.cpp
+++ b/indra/newview/llfloateroutfitphotopreview.cpp
@@ -234,7 +234,6 @@ void LLFloaterOutfitPhotoPreview::updateImageID()
 	if(item)
 	{
 		mImageID = item->getAssetUUID();
-		LLPermissions perm(item->getPermissions());
 	}
 	else
 	{
diff --git a/indra/newview/llfloateroutfitsnapshot.cpp b/indra/newview/llfloateroutfitsnapshot.cpp
deleted file mode 100644
index ad5e97e0677c7afea40fac8361fc727918b6ca0d..0000000000000000000000000000000000000000
--- a/indra/newview/llfloateroutfitsnapshot.cpp
+++ /dev/null
@@ -1,372 +0,0 @@
-/** 
- * @file llfloateroutfitsnapshot.cpp
- * @brief Snapshot preview window for saving as an outfit thumbnail in visual outfit gallery
- *
- * $LicenseInfo:firstyear=2004&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2016, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#include "llviewerprecompiledheaders.h"
-
-#include "llfloatersnapshot.h"
-#include "llfloateroutfitsnapshot.h"
-
-#include "llagent.h"
-#include "llfloaterreg.h"
-#include "llimagefiltersmanager.h"
-#include "llcheckboxctrl.h"
-#include "llcombobox.h"
-#include "llpostcard.h"
-#include "llresmgr.h"		// LLLocale
-#include "llsdserialize.h"
-#include "llsidetraypanelcontainer.h"
-#include "llspinctrl.h"
-#include "llviewercontrol.h"
-#include "lltoolfocus.h"
-#include "lltoolmgr.h"
-
-///----------------------------------------------------------------------------
-/// Local function declarations, constants, enums, and typedefs
-///----------------------------------------------------------------------------
-LLOutfitSnapshotFloaterView* gOutfitSnapshotFloaterView = NULL;
-
-const S32 OUTFIT_SNAPSHOT_WIDTH = 256;
-const S32 OUTFIT_SNAPSHOT_HEIGHT = 256;
-
-static LLDefaultChildRegistry::Register<LLOutfitSnapshotFloaterView> r("snapshot_outfit_floater_view");
-
-///----------------------------------------------------------------------------
-/// Class LLFloaterOutfitSnapshot::Impl
-///----------------------------------------------------------------------------
-
-// virtual
-LLPanelSnapshot* LLFloaterOutfitSnapshot::Impl::getActivePanel(LLFloaterSnapshotBase* floater, bool ok_if_not_found)
-{
-    LLPanel* panel = floater->getChild<LLPanel>("panel_outfit_snapshot_inventory");
-    LLPanelSnapshot* active_panel = dynamic_cast<LLPanelSnapshot*>(panel);
-    if (!ok_if_not_found)
-    {
-        llassert_always(active_panel != NULL);
-    }
-    return active_panel;
-}
-
-// virtual
-LLSnapshotModel::ESnapshotFormat LLFloaterOutfitSnapshot::Impl::getImageFormat(LLFloaterSnapshotBase* floater)
-{
-    return LLSnapshotModel::SNAPSHOT_FORMAT_PNG;
-}
-
-// virtual
-LLSnapshotModel::ESnapshotLayerType LLFloaterOutfitSnapshot::Impl::getLayerType(LLFloaterSnapshotBase* floater)
-{
-    return LLSnapshotModel::SNAPSHOT_TYPE_COLOR;
-}
-
-// This is the main function that keeps all the GUI controls in sync with the saved settings.
-// It should be called anytime a setting is changed that could affect the controls.
-// No other methods should be changing any of the controls directly except for helpers called by this method.
-// The basic pattern for programmatically changing the GUI settings is to first set the
-// appropriate saved settings and then call this method to sync the GUI with them.
-// FIXME: The above comment seems obsolete now.
-// virtual
-void LLFloaterOutfitSnapshot::Impl::updateControls(LLFloaterSnapshotBase* floater)
-{
-    LLSnapshotModel::ESnapshotType shot_type = getActiveSnapshotType(floater);
-    LLSnapshotModel::ESnapshotFormat shot_format = (LLSnapshotModel::ESnapshotFormat)gSavedSettings.getS32("SnapshotFormat");
-    LLSnapshotModel::ESnapshotLayerType layer_type = getLayerType(floater);
-
-    LLSnapshotLivePreview* previewp = getPreviewView();
-    BOOL got_snap = previewp && previewp->getSnapshotUpToDate();
-
-    // *TODO: Separate maximum size for Web images from postcards
-    LL_DEBUGS() << "Is snapshot up-to-date? " << got_snap << LL_ENDL;
-
-    LLLocale locale(LLLocale::USER_LOCALE);
-    std::string bytes_string;
-    if (got_snap)
-    {
-        LLResMgr::getInstance()->getIntegerString(bytes_string, (previewp->getDataSize()) >> 10);
-    }
-
-    // Update displayed image resolution.
-    LLTextBox* image_res_tb = floater->getChild<LLTextBox>("image_res_text");
-    image_res_tb->setVisible(got_snap);
-    if (got_snap)
-    {
-        image_res_tb->setTextArg("[WIDTH]", llformat("%d", previewp->getEncodedImageWidth()));
-        image_res_tb->setTextArg("[HEIGHT]", llformat("%d", previewp->getEncodedImageHeight()));
-    }
-
-    floater->getChild<LLUICtrl>("file_size_label")->setTextArg("[SIZE]", got_snap ? bytes_string : floater->getString("unknown"));
-    floater->getChild<LLUICtrl>("file_size_label")->setColor(LLUIColorTable::instance().getColor("LabelTextColor"));
-
-    updateResolution(floater);
-
-    if (previewp)
-    {
-        previewp->setSnapshotType(shot_type);
-        previewp->setSnapshotFormat(shot_format);
-        previewp->setSnapshotBufferType(layer_type);
-    }
-
-    LLPanelSnapshot* current_panel = Impl::getActivePanel(floater);
-    if (current_panel)
-    {
-        LLSD info;
-        info["have-snapshot"] = got_snap;
-        current_panel->updateControls(info);
-    }
-    LL_DEBUGS() << "finished updating controls" << LL_ENDL;
-}
-
-// virtual
-std::string LLFloaterOutfitSnapshot::Impl::getSnapshotPanelPrefix()
-{
-    return "panel_outfit_snapshot_";
-}
-
-// Show/hide upload status message.
-// virtual
-void LLFloaterOutfitSnapshot::Impl::setFinished(bool finished, bool ok, const std::string& msg)
-{
-    mFloater->setSuccessLabelPanelVisible(finished && ok);
-    mFloater->setFailureLabelPanelVisible(finished && !ok);
-
-    if (finished)
-    {
-        LLUICtrl* finished_lbl = mFloater->getChild<LLUICtrl>(ok ? "succeeded_lbl" : "failed_lbl");
-        std::string result_text = mFloater->getString(msg + "_" + (ok ? "succeeded_str" : "failed_str"));
-        finished_lbl->setValue(result_text);
-
-        LLPanel* snapshot_panel = mFloater->getChild<LLPanel>("panel_outfit_snapshot_inventory");
-        snapshot_panel->onOpen(LLSD());
-    }
-}
-
-void LLFloaterOutfitSnapshot::Impl::updateResolution(void* data)
-{
-    LLFloaterOutfitSnapshot *view = (LLFloaterOutfitSnapshot *)data;
-
-    if (!view)
-    {
-        llassert(view);
-        return;
-    }
-
-    S32 width = OUTFIT_SNAPSHOT_WIDTH;
-    S32 height = OUTFIT_SNAPSHOT_HEIGHT;
-
-    LLSnapshotLivePreview* previewp = getPreviewView();
-    if (previewp)
-    {
-        S32 original_width = 0, original_height = 0;
-        previewp->getSize(original_width, original_height);
-
-        if (gSavedSettings.getBOOL("RenderUIInSnapshot") || gSavedSettings.getBOOL("RenderHUDInSnapshot"))
-        { //clamp snapshot resolution to window size when showing UI or HUD in snapshot
-            width = llmin(width, gViewerWindow->getWindowWidthRaw());
-            height = llmin(height, gViewerWindow->getWindowHeightRaw());
-        }
-
-
-        llassert(width > 0 && height > 0);
-
-        // use the resolution from the selected pre-canned drop-down choice
-        LL_DEBUGS() << "Setting preview res selected from combo: " << width << "x" << height << LL_ENDL;
-        previewp->setSize(width, height);
-
-        if (original_width != width || original_height != height)
-        {
-            // hide old preview as the aspect ratio could be wrong
-            checkAutoSnapshot(previewp, FALSE);
-            LL_DEBUGS() << "updating thumbnail" << LL_ENDL;
-            previewp->updateSnapshot(TRUE);
-        }
-    }
-}
-
-///----------------------------------------------------------------------------
-/// Class LLFloaterOutfitSnapshot
-///----------------------------------------------------------------------------
-
-// Default constructor
-LLFloaterOutfitSnapshot::LLFloaterOutfitSnapshot(const LLSD& key)
-: LLFloaterSnapshotBase(key),
-mOutfitGallery(NULL)
-{
-    impl = new Impl(this);
-}
-
-LLFloaterOutfitSnapshot::~LLFloaterOutfitSnapshot()
-{
-}
-
-// virtual
-BOOL LLFloaterOutfitSnapshot::postBuild()
-{
-    mRefreshBtn = getChild<LLUICtrl>("new_snapshot_btn");
-    childSetAction("new_snapshot_btn", ImplBase::onClickNewSnapshot, this);
-    mRefreshLabel = getChild<LLUICtrl>("refresh_lbl");
-    mSucceessLblPanel = getChild<LLUICtrl>("succeeded_panel");
-    mFailureLblPanel = getChild<LLUICtrl>("failed_panel");
-
-    childSetCommitCallback("ui_check", ImplBase::onClickUICheck, this);
-    getChild<LLUICtrl>("ui_check")->setValue(gSavedSettings.getBOOL("RenderUIInSnapshot"));
-
-    childSetCommitCallback("hud_check", ImplBase::onClickHUDCheck, this);
-    getChild<LLUICtrl>("hud_check")->setValue(gSavedSettings.getBOOL("RenderHUDInSnapshot"));
-
-    getChild<LLUICtrl>("freeze_frame_check")->setValue(gSavedSettings.getBOOL("UseFreezeFrame"));
-    childSetCommitCallback("freeze_frame_check", ImplBase::onCommitFreezeFrame, this);
-
-    getChild<LLUICtrl>("auto_snapshot_check")->setValue(gSavedSettings.getBOOL("AutoSnapshot"));
-    childSetCommitCallback("auto_snapshot_check", ImplBase::onClickAutoSnap, this);
-
-    getChild<LLButton>("retract_btn")->setCommitCallback(boost::bind(&LLFloaterOutfitSnapshot::onExtendFloater, this));
-    getChild<LLButton>("extend_btn")->setCommitCallback(boost::bind(&LLFloaterOutfitSnapshot::onExtendFloater, this));
-
-    // Filters
-    LLComboBox* filterbox = getChild<LLComboBox>("filters_combobox");
-    std::vector<std::string> filter_list = LLImageFiltersManager::getInstance()->getFiltersList();
-    for (U32 i = 0; i < filter_list.size(); i++)
-    {
-        filterbox->add(filter_list[i]);
-    }
-    childSetCommitCallback("filters_combobox", ImplBase::onClickFilter, this);
-
-    mThumbnailPlaceholder = getChild<LLUICtrl>("thumbnail_placeholder");
-
-    // create preview window
-    LLRect full_screen_rect = getRootView()->getRect();
-    LLSnapshotLivePreview::Params p;
-    p.rect(full_screen_rect);
-    LLSnapshotLivePreview* previewp = new LLSnapshotLivePreview(p);
-    LLView* parent_view = gSnapshotFloaterView->getParent();
-
-    parent_view->removeChild(gSnapshotFloaterView);
-    // make sure preview is below snapshot floater
-    parent_view->addChild(previewp);
-    parent_view->addChild(gSnapshotFloaterView);
-
-    //move snapshot floater to special purpose snapshotfloaterview
-    gFloaterView->removeChild(this);
-    gSnapshotFloaterView->addChild(this);
-
-    impl->mPreviewHandle = previewp->getHandle();
-    previewp->setContainer(this);
-    impl->updateControls(this);
-    impl->setAdvanced(gSavedSettings.getBOOL("AdvanceOutfitSnapshot"));
-    impl->updateLayout(this);
-
-    previewp->mKeepAspectRatio = FALSE;
-    previewp->setThumbnailPlaceholderRect(getThumbnailPlaceholderRect());
-
-    return TRUE;
-}
-
-// virtual
-void LLFloaterOutfitSnapshot::onOpen(const LLSD& key)
-{
-    LLSnapshotLivePreview* preview = getPreviewView();
-    if (preview)
-    {
-        LL_DEBUGS() << "opened, updating snapshot" << LL_ENDL;
-        preview->updateSnapshot(TRUE);
-    }
-    focusFirstItem(FALSE);
-    gSnapshotFloaterView->setEnabled(TRUE);
-    gSnapshotFloaterView->setVisible(TRUE);
-    gSnapshotFloaterView->adjustToFitScreen(this, FALSE);
-
-    impl->updateControls(this);
-    impl->setAdvanced(gSavedSettings.getBOOL("AdvanceOutfitSnapshot"));
-    impl->updateLayout(this);
-
-    LLPanel* snapshot_panel = getChild<LLPanel>("panel_outfit_snapshot_inventory");
-    snapshot_panel->onOpen(LLSD());
-    postPanelSwitch();
-
-}
-
-void LLFloaterOutfitSnapshot::onExtendFloater()
-{
-	impl->setAdvanced(gSavedSettings.getBOOL("AdvanceOutfitSnapshot"));
-}
-
-// static 
-void LLFloaterOutfitSnapshot::update()
-{
-    LLFloaterOutfitSnapshot* inst = findInstance();
-    if (inst != NULL)
-    {
-        inst->impl->updateLivePreview();
-    }
-}
-
-
-// static
-LLFloaterOutfitSnapshot* LLFloaterOutfitSnapshot::findInstance()
-{
-    return LLFloaterReg::findTypedInstance<LLFloaterOutfitSnapshot>("outfit_snapshot");
-}
-
-// static
-LLFloaterOutfitSnapshot* LLFloaterOutfitSnapshot::getInstance()
-{
-    return LLFloaterReg::getTypedInstance<LLFloaterOutfitSnapshot>("outfit_snapshot");
-}
-
-// virtual
-void LLFloaterOutfitSnapshot::saveTexture()
-{
-    LL_DEBUGS() << "saveTexture" << LL_ENDL;
-
-    LLSnapshotLivePreview* previewp = getPreviewView();
-    if (!previewp)
-    {
-        llassert(previewp != NULL);
-        return;
-    }
-
-    if (mOutfitGallery)
-    {
-        mOutfitGallery->onBeforeOutfitSnapshotSave();
-    }
-    previewp->saveTexture(TRUE, getOutfitID().asString());
-    if (mOutfitGallery)
-    {
-        mOutfitGallery->onAfterOutfitSnapshotSave();
-    }
-    closeFloater();
-}
-
-///----------------------------------------------------------------------------
-/// Class LLOutfitSnapshotFloaterView
-///----------------------------------------------------------------------------
-
-LLOutfitSnapshotFloaterView::LLOutfitSnapshotFloaterView(const Params& p) : LLFloaterView(p)
-{
-}
-
-LLOutfitSnapshotFloaterView::~LLOutfitSnapshotFloaterView()
-{
-}
diff --git a/indra/newview/llfloateroutfitsnapshot.h b/indra/newview/llfloateroutfitsnapshot.h
deleted file mode 100644
index bee386ec63bb70ca29708b62375367e048880213..0000000000000000000000000000000000000000
--- a/indra/newview/llfloateroutfitsnapshot.h
+++ /dev/null
@@ -1,123 +0,0 @@
-/**
- * @file llfloateroutfitsnapshot.h
- * @brief Snapshot preview window for saving as an outfit thumbnail in visual outfit gallery
- *
- * $LicenseInfo:firstyear=2004&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2016, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLFLOATEROUTFITSNAPSHOT_H
-#define LL_LLFLOATEROUTFITSNAPSHOT_H
-
-#include "llfloater.h"
-#include "llfloatersnapshot.h"
-#include "lloutfitgallery.h"
-#include "llsnapshotlivepreview.h"
-
-///----------------------------------------------------------------------------
-/// Class LLFloaterOutfitSnapshot
-///----------------------------------------------------------------------------
-
-class LLFloaterOutfitSnapshot : public LLFloaterSnapshotBase
-{
-    LOG_CLASS(LLFloaterOutfitSnapshot);
-
-public:
-
-    LLFloaterOutfitSnapshot(const LLSD& key);
-    /*virtual*/ ~LLFloaterOutfitSnapshot();
-
-    /*virtual*/ BOOL postBuild();
-    /*virtual*/ void onOpen(const LLSD& key);
-
-    static void update();
-
-    void onExtendFloater();
-
-    static LLFloaterOutfitSnapshot* getInstance();
-    static LLFloaterOutfitSnapshot* findInstance();
-    /*virtual*/ void saveTexture();
-
-    const LLRect& getThumbnailPlaceholderRect() { return mThumbnailPlaceholder->getRect(); }
-
-    void setOutfitID(LLUUID id) { mOutfitID = id; }
-    LLUUID getOutfitID() { return mOutfitID; }
-    void setGallery(LLOutfitGallery* gallery) { mOutfitGallery = gallery; }
-
-    class Impl;
-    friend class Impl;
-private:
-
-    LLUUID mOutfitID;
-    LLOutfitGallery* mOutfitGallery;
-};
-
-///----------------------------------------------------------------------------
-/// Class LLFloaterOutfitSnapshot::Impl
-///----------------------------------------------------------------------------
-
-class LLFloaterOutfitSnapshot::Impl : public LLFloaterSnapshotBase::ImplBase
-{
-    LOG_CLASS(LLFloaterOutfitSnapshot::Impl);
-public:
-    Impl(LLFloaterSnapshotBase* floater)
-        : LLFloaterSnapshotBase::ImplBase(floater)
-    {}
-    ~Impl()
-    {}
-    void updateResolution(void* data);
-
-    static void onSnapshotUploadFinished(LLFloaterSnapshotBase* floater, bool status);
-
-    /*virtual*/ LLPanelSnapshot* getActivePanel(LLFloaterSnapshotBase* floater, bool ok_if_not_found = true);
-    /*virtual*/ LLSnapshotModel::ESnapshotFormat getImageFormat(LLFloaterSnapshotBase* floater);
-    /*virtual*/ std::string getSnapshotPanelPrefix();
-
-    /*virtual*/ void updateControls(LLFloaterSnapshotBase* floater);
-
-private:
-    /*virtual*/ LLSnapshotModel::ESnapshotLayerType getLayerType(LLFloaterSnapshotBase* floater);
-    /*virtual*/ void setFinished(bool finished, bool ok = true, const std::string& msg = LLStringUtil::null);
-};
-
-///----------------------------------------------------------------------------
-/// Class LLOutfitSnapshotFloaterView
-///----------------------------------------------------------------------------
-
-class LLOutfitSnapshotFloaterView : public LLFloaterView
-{
-public:
-    struct Params
-        : public LLInitParam::Block<Params, LLFloaterView::Params>
-    {
-    };
-
-protected:
-    LLOutfitSnapshotFloaterView(const Params& p);
-    friend class LLUICtrlFactory;
-
-public:
-    virtual ~LLOutfitSnapshotFloaterView();
-};
-
-extern LLOutfitSnapshotFloaterView* gOutfitSnapshotFloaterView;
-
-#endif // LL_LLFLOATEROUTFITSNAPSHOT_H
diff --git a/indra/newview/llfloaterpathfindinglinksets.cpp b/indra/newview/llfloaterpathfindinglinksets.cpp
index 1e46d7a402abf1f4ac1104f0ea1ecc733c79b0fd..03aede94c6718b07110e0b5fc88262ae2375c5a8 100644
--- a/indra/newview/llfloaterpathfindinglinksets.cpp
+++ b/indra/newview/llfloaterpathfindinglinksets.cpp
@@ -44,6 +44,7 @@
 #include "llpathfindinglinkset.h"
 #include "llpathfindinglinksetlist.h"
 #include "llpathfindingmanager.h"
+#include "llsearcheditor.h"
 #include "llscrolllistitem.h"
 #include "llsd.h"
 #include "lltextbase.h"
@@ -114,17 +115,13 @@ BOOL LLFloaterPathfindingLinksets::postBuild()
 {
 	mBeaconColor = LLUIColorTable::getInstance()->getColor("PathfindingLinksetBeaconColor");
 
-	mFilterByName = findChild<LLLineEditor>("filter_by_name");
-	llassert(mFilterByName != NULL);
-	mFilterByName->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onApplyAllFilters, this));
-	mFilterByName->setSelectAllonFocusReceived(true);
-	mFilterByName->setCommitOnFocusLost(true);
-
-	mFilterByDescription = findChild<LLLineEditor>("filter_by_description");
-	llassert(mFilterByDescription != NULL);
-	mFilterByDescription->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onApplyAllFilters, this));
-	mFilterByDescription->setSelectAllonFocusReceived(true);
-	mFilterByDescription->setCommitOnFocusLost(true);
+    mFilterByName = getChild<LLSearchEditor>("filter_by_name");
+    mFilterByName->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onApplyAllFilters, this));
+    mFilterByName->setCommitOnFocusLost(true);
+
+    mFilterByDescription = getChild<LLSearchEditor>("filter_by_description");
+    mFilterByDescription->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onApplyAllFilters, this));
+    mFilterByDescription->setCommitOnFocusLost(true);
 
 	mFilterByLinksetUse = findChild<LLComboBox>("filter_by_linkset_use");
 	llassert(mFilterByLinksetUse != NULL);
diff --git a/indra/newview/llfloaterpathfindinglinksets.h b/indra/newview/llfloaterpathfindinglinksets.h
index 7149da9215f9258a7c48492dce4650f4830f73d9..a954d8a8ec8dd0f8265415760997c3bd47ee21cb 100644
--- a/indra/newview/llfloaterpathfindinglinksets.h
+++ b/indra/newview/llfloaterpathfindinglinksets.h
@@ -42,6 +42,7 @@ class LLSD;
 class LLTextBase;
 class LLUICtrl;
 class LLVector3;
+class LLSearchEditor;
 
 class LLFloaterPathfindingLinksets : public LLFloaterPathfindingObjects
 {
@@ -105,8 +106,8 @@ class LLFloaterPathfindingLinksets : public LLFloaterPathfindingObjects
 	LLPathfindingLinkset::ELinksetUse convertToLinksetUse(LLSD pXuiValue) const;
 	LLSD                              convertToXuiValue(LLPathfindingLinkset::ELinksetUse pLinksetUse) const;
 
-	LLLineEditor     *mFilterByName;
-	LLLineEditor     *mFilterByDescription;
+    LLSearchEditor   *mFilterByName;
+    LLSearchEditor   *mFilterByDescription;
 	LLComboBox       *mFilterByLinksetUse;
 	LLComboBox       *mEditLinksetUse;
 	LLScrollListItem *mEditLinksetUseUnset;
diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp
index 273810e8d421c6a99bd3a1dac0d2735ec0b5508e..6909ad513d2df39e2d63be3334748d07abd96bd9 100644
--- a/indra/newview/llfloaterpreference.cpp
+++ b/indra/newview/llfloaterpreference.cpp
@@ -512,6 +512,7 @@ void LLFloaterPreference::saveSettings()
 		if (panel)
 			panel->saveSettings();
 	}
+    saveIgnoredNotifications();
 }	
 
 void LLFloaterPreference::apply()
@@ -628,6 +629,8 @@ void LLFloaterPreference::cancel()
 		gSavedSettings.setString("PresetGraphicActive", mSavedGraphicsPreset);
 		LLPresetsManager::getInstance()->triggerChangeSignal();
 	}
+
+    restoreIgnoredNotifications();
 }
 
 void LLFloaterPreference::onOpen(const LLSD& key)
@@ -1505,6 +1508,10 @@ void LLFloaterPreference::onClickEnablePopup()
 	}
 	
 	buildPopupLists();
+    if (!mFilterEdit->getText().empty())
+    {
+        filterIgnorableNotifications();
+    }
 }
 
 void LLFloaterPreference::onClickDisablePopup()
@@ -1520,6 +1527,10 @@ void LLFloaterPreference::onClickDisablePopup()
 	}
 	
 	buildPopupLists();
+    if (!mFilterEdit->getText().empty())
+    {
+        filterIgnorableNotifications();
+    }
 }
 
 void LLFloaterPreference::resetAllIgnored()
@@ -3545,11 +3556,24 @@ void LLFloaterPreference::onUpdateFilterTerm(bool force)
 		return;
 
 	mSearchData->mRootTab->hightlightAndHide( seachValue );
+    filterIgnorableNotifications();
+
 	LLTabContainer *pRoot = getChild< LLTabContainer >( "pref core" );
 	if( pRoot )
 		pRoot->selectFirstTab();
 }
 
+void LLFloaterPreference::filterIgnorableNotifications()
+{
+    bool visible = getChildRef<LLScrollListCtrl>("enabled_popups").highlightMatchingItems(mFilterEdit->getValue());
+    visible |= getChildRef<LLScrollListCtrl>("disabled_popups").highlightMatchingItems(mFilterEdit->getValue());
+
+    if (visible)
+    {
+        getChildRef<LLTabContainer>("pref core").setTabVisibility( getChild<LLPanel>("msgs"), true );
+    }
+}
+
 void collectChildren( LLView const *aView, ll::prefs::PanelDataPtr aParentPanel, ll::prefs::TabContainerDataPtr aParentTabContainer )
 {
 	if( !aView )
@@ -3638,3 +3662,28 @@ void LLFloaterPreference::collectSearchableItems()
 	}
 	mSearchDataDirty = false;
 }
+
+void LLFloaterPreference::saveIgnoredNotifications()
+{
+    for (LLNotifications::TemplateMap::const_iterator iter = LLNotifications::instance().templatesBegin();
+            iter != LLNotifications::instance().templatesEnd();
+            ++iter)
+    {
+        LLNotificationTemplatePtr templatep = iter->second;
+        LLNotificationFormPtr formp = templatep->mForm;
+
+        LLNotificationForm::EIgnoreType ignore = formp->getIgnoreType();
+        if (ignore <= LLNotificationForm::IGNORE_NO)
+            continue;
+
+        mIgnorableNotifs[templatep->mName] = !formp->getIgnored();
+    }
+}
+
+void LLFloaterPreference::restoreIgnoredNotifications()
+{
+    for (std::map<std::string, bool>::iterator it = mIgnorableNotifs.begin(); it != mIgnorableNotifs.end(); ++it)
+    {
+        LLUI::getInstance()->mSettingGroups["ignores"]->setBOOL(it->first, it->second);
+    }
+}
diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h
index 542df18ddba39f94107de156078dea33136dd72c..e312c35135fc8a1df5508f09169683ea1ea5fc07 100644
--- a/indra/newview/llfloaterpreference.h
+++ b/indra/newview/llfloaterpreference.h
@@ -143,6 +143,9 @@ class LLFloaterPreference : public LLFloater, public LLAvatarPropertiesObserver,
 	// cancel() can restore them.	
 	void saveSettings();
 
+	void saveIgnoredNotifications();
+	void restoreIgnoredNotifications();
+
 	void setCacheLocation(const LLStringExplicit& location);
 
 	void onClickSetCache();
@@ -223,6 +226,9 @@ class LLFloaterPreference : public LLFloater, public LLAvatarPropertiesObserver,
 
 	void onUpdateFilterTerm( bool force = false );
 	void collectSearchableItems();
+    void filterIgnorableNotifications();
+
+    std::map<std::string, bool> mIgnorableNotifs;
 };
 
 class LLPanelPreference : public LLPanel
diff --git a/indra/newview/llfloaterscriptlimits.cpp b/indra/newview/llfloaterscriptlimits.cpp
index 3746b9b6c286709032e4ecb4c7ac4706c6b3e3d9..40fe11b309304eb9982c5262de791913b083df75 100644
--- a/indra/newview/llfloaterscriptlimits.cpp
+++ b/indra/newview/llfloaterscriptlimits.cpp
@@ -421,7 +421,6 @@ void LLPanelScriptLimitsRegionMemory::setRegionDetails(LLSD content)
 	for(S32 i = 0; i < number_parcels; i++)
 	{
 		std::string parcel_name = content["parcels"][i]["name"].asString();
-		LLUUID parcel_id = content["parcels"][i]["id"].asUUID();
 		S32 number_objects = content["parcels"][i]["objects"].size();
 
 		S32 local_id = 0;
diff --git a/indra/newview/llfloatersearch.cpp b/indra/newview/llfloatersearch.cpp
index bb3ed77772c6e372baa54eec25a7fe17b0c8cd6d..7e6af45515ec53f7ec6a26bee3f74f7877b9902b 100644
--- a/indra/newview/llfloatersearch.cpp
+++ b/indra/newview/llfloatersearch.cpp
@@ -45,7 +45,7 @@ class LLSearchHandler : public LLCommandHandler
 {
 public:
 	// requires trusted browser to trigger
-	LLSearchHandler() : LLCommandHandler("search", UNTRUSTED_THROTTLE) { }
+	LLSearchHandler() : LLCommandHandler("search", UNTRUSTED_CLICK_ONLY) { }
 	bool handle(const LLSD& tokens, const LLSD& query_map, LLMediaCtrl* web)
 	{
 		if (!LLUI::getInstance()->mSettingGroups["config"]->getBOOL("EnableSearch"))
diff --git a/indra/newview/llfloatersettingsdebug.cpp b/indra/newview/llfloatersettingsdebug.cpp
index 186994c8571c118669aef4a2642e6cf55f4fd526..3c7f3416138c922636893f592672df83c3aaae55 100644
--- a/indra/newview/llfloatersettingsdebug.cpp
+++ b/indra/newview/llfloatersettingsdebug.cpp
@@ -2,9 +2,9 @@
  * @file llfloatersettingsdebug.cpp
  * @brief floater for debugging internal viewer settings
  *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * $LicenseInfo:firstyear=2022&license=viewerlgpl$
  * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
+ * 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
@@ -27,8 +27,8 @@
 #include "llviewerprecompiledheaders.h"
 #include "llfloatersettingsdebug.h"
 #include "llfloater.h"
+#include "llfiltereditor.h"
 #include "lluictrlfactory.h"
-//#include "llfirstuse.h"
 #include "llcombobox.h"
 #include "llspinctrl.h"
 #include "llcolorswatch.h"
@@ -37,12 +37,11 @@
 
 
 LLFloaterSettingsDebug::LLFloaterSettingsDebug(const LLSD& key) 
-:	LLFloater(key)
+:   LLFloater(key),
+    mSettingList(NULL)
 {
-	mCommitCallbackRegistrar.add("SettingSelect",	boost::bind(&LLFloaterSettingsDebug::onSettingSelect, this,_1));
 	mCommitCallbackRegistrar.add("CommitSettings",	boost::bind(&LLFloaterSettingsDebug::onCommitSettings, this));
 	mCommitCallbackRegistrar.add("ClickDefault",	boost::bind(&LLFloaterSettingsDebug::onClickDefault, this));
-
 }
 
 LLFloaterSettingsDebug::~LLFloaterSettingsDebug()
@@ -50,59 +49,43 @@ LLFloaterSettingsDebug::~LLFloaterSettingsDebug()
 
 BOOL LLFloaterSettingsDebug::postBuild()
 {
-	LLComboBox* settings_combo = getChild<LLComboBox>("settings_combo");
+    enableResizeCtrls(true, false, true);
 
-	struct f : public LLControlGroup::ApplyFunctor
-	{
-		LLComboBox* combo;
-		f(LLComboBox* c) : combo(c) {}
-		virtual void apply(const std::string& name, LLControlVariable* control)
-		{
-			if (!control->isHiddenFromSettingsEditor())
-			{
-				combo->add(name, (void*)control);
-			}
-		}
-	} func(settings_combo);
+    mComment = getChild<LLTextEditor>("comment_text");
 
-	std::string key = getKey().asString();
-	if (key == "all" || key == "base")
-	{
-		gSavedSettings.applyToAll(&func);
-	}
-	if (key == "all" || key == "account")
-	{
-		gSavedPerAccountSettings.applyToAll(&func);
-	}
+    getChild<LLFilterEditor>("filter_input")->setCommitCallback(boost::bind(&LLFloaterSettingsDebug::setSearchFilter, this, _2));
+
+    mSettingList = getChild<LLScrollListCtrl>("setting_list");
+    mSettingList->setCommitOnSelectionChange(TRUE);
+    mSettingList->setCommitCallback(boost::bind(&LLFloaterSettingsDebug::onSettingSelect, this));
+
+    updateList();
+
+    gSavedSettings.getControl("DebugSettingsHideDefault")->getCommitSignal()->connect(boost::bind(&LLFloaterSettingsDebug::updateList, this, false));
 
-	settings_combo->sortByName();
-	settings_combo->updateSelection();
-	mComment = getChild<LLTextEditor>("comment_text");
 	return TRUE;
 }
 
 void LLFloaterSettingsDebug::draw()
 {
-	LLComboBox* settings_combo = getChild<LLComboBox>("settings_combo");
-	LLControlVariable* controlp = (LLControlVariable*)settings_combo->getCurrentUserdata();
-	updateControl(controlp);
+    LLScrollListItem* first_selected = mSettingList->getFirstSelected();
+    if (first_selected)
+    {
+        LLControlVariable* controlp = (LLControlVariable*)first_selected->getUserdata();
+        updateControl(controlp);
+    }
 
 	LLFloater::draw();
 }
 
-//static 
-void LLFloaterSettingsDebug::onSettingSelect(LLUICtrl* ctrl)
-{
-	LLComboBox* combo_box = (LLComboBox*)ctrl;
-	LLControlVariable* controlp = (LLControlVariable*)combo_box->getCurrentUserdata();
-
-	updateControl(controlp);
-}
-
 void LLFloaterSettingsDebug::onCommitSettings()
 {
-	LLComboBox* settings_combo = getChild<LLComboBox>("settings_combo");
-	LLControlVariable* controlp = (LLControlVariable*)settings_combo->getCurrentUserdata();
+    LLScrollListItem* first_selected = mSettingList->getFirstSelected();
+    if (!first_selected)
+    {
+        return;
+    }
+    LLControlVariable* controlp = (LLControlVariable*)first_selected->getUserdata();
 
 	if (!controlp)
 	{
@@ -176,19 +159,23 @@ void LLFloaterSettingsDebug::onCommitSettings()
 	  default:
 		break;
 	}
+    updateDefaultColumn(controlp);
 }
 
 // static
 void LLFloaterSettingsDebug::onClickDefault()
 {
-	LLComboBox* settings_combo = getChild<LLComboBox>("settings_combo");
-	LLControlVariable* controlp = (LLControlVariable*)settings_combo->getCurrentUserdata();
-
-	if (controlp)
-	{
-		controlp->resetToDefault(true);
-		updateControl(controlp);
-	}
+    LLScrollListItem* first_selected = mSettingList->getFirstSelected();
+    if (first_selected)
+    {
+        LLControlVariable* controlp = (LLControlVariable*)first_selected->getUserdata();
+        if (controlp)
+        {
+            controlp->resetToDefault(true);
+            updateDefaultColumn(controlp);
+            updateControl(controlp);
+        }
+    }
 }
 
 // we've switched controls, or doing per-frame update, so update spinners, etc.
@@ -207,23 +194,30 @@ void LLFloaterSettingsDebug::updateControl(LLControlVariable* controlp)
 		return;
 	}
 
-	spinner1->setVisible(FALSE);
-	spinner2->setVisible(FALSE);
-	spinner3->setVisible(FALSE);
-	spinner4->setVisible(FALSE);
-	color_swatch->setVisible(FALSE);
-	getChildView("val_text")->setVisible( FALSE);
-	mComment->setText(LLStringUtil::null);
+    hideUIControls();
 
-	if (controlp)
+	if (controlp && !isSettingHidden(controlp))
 	{
 		eControlType type = controlp->type();
 
 		//hide combo box only for non booleans, otherwise this will result in the combo box closing every frame
 		getChildView("boolean_combo")->setVisible( type == TYPE_BOOLEAN);
-		
+        getChildView("default_btn")->setVisible(true);
+        getChildView("setting_name_txt")->setVisible(true);
+        getChild<LLTextBox>("setting_name_txt")->setText(controlp->getName());
+        getChild<LLTextBox>("setting_name_txt")->setToolTip(controlp->getName());
+        mComment->setVisible(true);
+
+        std::string old_text = mComment->getText();
+        std::string new_text = controlp->getComment();
+        // Don't setText if not nessesary, it will reset scroll
+        // This is a debug UI that reads from xml, there might
+        // be use cases where comment changes, but not the name
+        if (old_text != new_text)
+        {
+            mComment->setText(controlp->getComment());
+        }
 
-		mComment->setText(controlp->getComment());
 		spinner1->setMaxValue(F32_MAX);
 		spinner2->setMaxValue(F32_MAX);
 		spinner3->setMaxValue(F32_MAX);
@@ -479,3 +473,166 @@ void LLFloaterSettingsDebug::updateControl(LLControlVariable* controlp)
 	}
 
 }
+
+void LLFloaterSettingsDebug::updateList(bool skip_selection)
+{
+    std::string last_selected;
+    LLScrollListItem* item = mSettingList->getFirstSelected();
+    if (item)
+    {
+        LLScrollListCell* cell = item->getColumn(1);
+        if (cell)
+        {
+            last_selected = cell->getValue().asString();
+         }
+    }
+
+    mSettingList->deleteAllItems();
+    struct f : public LLControlGroup::ApplyFunctor
+    {
+        LLScrollListCtrl* setting_list;
+        LLFloaterSettingsDebug* floater;
+        std::string selected_setting;
+        bool skip_selection;
+        f(LLScrollListCtrl* list, LLFloaterSettingsDebug* floater, std::string setting, bool skip_selection) 
+            : setting_list(list), floater(floater), selected_setting(setting), skip_selection(skip_selection) {}
+        virtual void apply(const std::string& name, LLControlVariable* control)
+        {
+            if (!control->isHiddenFromSettingsEditor() && floater->matchesSearchFilter(name) && !floater->isSettingHidden(control))
+            {
+                LLSD row;
+
+                row["columns"][0]["column"] = "changed_setting";
+                row["columns"][0]["value"] = control->isDefault() ? "" : "*";
+
+                row["columns"][1]["column"] = "setting";
+                row["columns"][1]["value"] = name;
+
+                LLScrollListItem* item = setting_list->addElement(row, ADD_BOTTOM, (void*)control);
+                if (!floater->mSearchFilter.empty() && (selected_setting == name) && !skip_selection)
+                {
+                    std::string lower_name(name);
+                    LLStringUtil::toLower(lower_name);
+                    if (LLStringUtil::startsWith(lower_name, floater->mSearchFilter))
+                    {
+                        item->setSelected(true);
+                    }
+                }
+            }
+        }
+    } func(mSettingList, this, last_selected, skip_selection);
+
+    std::string key = getKey().asString();
+    if (key == "all" || key == "base")
+    {
+        gSavedSettings.applyToAll(&func);
+    }
+    if (key == "all" || key == "account")
+    {
+        gSavedPerAccountSettings.applyToAll(&func);
+    }
+
+
+    if (!mSettingList->isEmpty())
+    {
+        if (mSettingList->hasSelectedItem())
+        {
+            mSettingList->scrollToShowSelected();
+        }
+        else if (!mSettingList->hasSelectedItem() && !mSearchFilter.empty() && !skip_selection)
+        {
+            if (!mSettingList->selectItemByPrefix(mSearchFilter, false, 1))
+            {
+                mSettingList->selectFirstItem();
+            }
+            mSettingList->scrollToShowSelected();
+        }
+    }
+    else
+    {
+        LLSD row;
+
+        row["columns"][0]["column"] = "changed_setting";
+        row["columns"][0]["value"] = "";
+        row["columns"][1]["column"] = "setting";
+        row["columns"][1]["value"] = "No matching settings.";
+
+        mSettingList->addElement(row);
+        hideUIControls();
+    }
+}
+
+void LLFloaterSettingsDebug::onSettingSelect()
+{
+    LLScrollListItem* first_selected = mSettingList->getFirstSelected();
+    if (first_selected)
+    {
+        LLControlVariable* controlp = (LLControlVariable*)first_selected->getUserdata();
+        if (controlp)
+        {
+            updateControl(controlp);
+        }
+    }
+}
+
+void LLFloaterSettingsDebug::setSearchFilter(const std::string& filter)
+{
+    if(mSearchFilter == filter)
+        return;
+    mSearchFilter = filter;
+    LLStringUtil::toLower(mSearchFilter);
+    updateList();
+}
+
+bool LLFloaterSettingsDebug::matchesSearchFilter(std::string setting_name)
+{
+    // If the search filter is empty, everything passes.
+    if (mSearchFilter.empty()) return true;
+
+    LLStringUtil::toLower(setting_name);
+    std::string::size_type match_name = setting_name.find(mSearchFilter);
+
+    return (std::string::npos != match_name);
+}
+
+bool LLFloaterSettingsDebug::isSettingHidden(LLControlVariable* control)
+{
+    static LLCachedControl<bool> hide_default(gSavedSettings, "DebugSettingsHideDefault", false);
+    return hide_default && control->isDefault();
+}
+
+void LLFloaterSettingsDebug::updateDefaultColumn(LLControlVariable* control)
+{
+    if (isSettingHidden(control))
+    {
+        hideUIControls();
+        updateList(true);
+        return;
+    }
+
+    LLScrollListItem* item = mSettingList->getFirstSelected();
+    if (item)
+    {
+        LLScrollListCell* cell = item->getColumn(0);
+        if (cell)
+        {
+            std::string is_default = control->isDefault() ? "" : "*";
+            cell->setValue(is_default);
+        }
+    }
+}
+
+void LLFloaterSettingsDebug::hideUIControls()
+{
+    getChildView("val_spinner_1")->setVisible(false);
+    getChildView("val_spinner_2")->setVisible(false);
+    getChildView("val_spinner_3")->setVisible(false);
+    getChildView("val_spinner_4")->setVisible(false);
+    getChildView("val_color_swatch")->setVisible(false);
+    getChildView("val_text")->setVisible(false);
+    getChildView("default_btn")->setVisible(false);
+    getChildView("boolean_combo")->setVisible(false);
+    getChildView("setting_name_txt")->setVisible(false);
+    mComment->setVisible(false);
+}
+
diff --git a/indra/newview/llfloatersettingsdebug.h b/indra/newview/llfloatersettingsdebug.h
index f07e0557e3d7c8b5f413bfcd35920d9883a66f2d..888eaadcbdbf72c292ccd5d3ac00ae8f64679497 100644
--- a/indra/newview/llfloatersettingsdebug.h
+++ b/indra/newview/llfloatersettingsdebug.h
@@ -2,9 +2,9 @@
  * @file llfloatersettingsdebug.h
  * @brief floater for debugging internal viewer settings
  *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * $LicenseInfo:firstyear=2022&license=viewerlgpl$
  * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
+ * 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
@@ -30,6 +30,8 @@
 #include "llcontrol.h"
 #include "llfloater.h"
 
+class LLScrollListCtrl;
+
 class LLFloaterSettingsDebug 
 :	public LLFloater
 {
@@ -42,18 +44,31 @@ class LLFloaterSettingsDebug
 
 	void updateControl(LLControlVariable* control);
 
-	void onSettingSelect(LLUICtrl* ctrl);
 	void onCommitSettings();
 	void onClickDefault();
 
+    bool matchesSearchFilter(std::string setting_name);
+    bool isSettingHidden(LLControlVariable* control);
+
 private:
 	// key - selects which settings to show, one of:
 	// "all", "base", "account", "skin"
 	LLFloaterSettingsDebug(const LLSD& key);
 	virtual ~LLFloaterSettingsDebug();
+
+    void updateList(bool skip_selection = false);
+    void onSettingSelect();
+    void setSearchFilter(const std::string& filter);
+
+    void updateDefaultColumn(LLControlVariable* control);
+    void hideUIControls();
+
+    LLScrollListCtrl* mSettingList;
 	
 protected:
 	class LLTextEditor* mComment;
+
+    std::string mSearchFilter;
 };
 
 #endif //LLFLOATERDEBUGSETTINGS_H
diff --git a/indra/newview/llfloatersimpleoutfitsnapshot.cpp b/indra/newview/llfloatersimpleoutfitsnapshot.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..bab2efbbd56aa0fb59c516223b08922a49cef42d
--- /dev/null
+++ b/indra/newview/llfloatersimpleoutfitsnapshot.cpp
@@ -0,0 +1,333 @@
+/** 
+* @file llfloatersimpleoutfitsnapshot.cpp
+* @brief Snapshot preview window for saving as an outfit thumbnail in visual outfit gallery
+*
+* $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$
+*/
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llfloatersimpleoutfitsnapshot.h"
+
+#include "llfloaterreg.h"
+#include "llimagefiltersmanager.h"
+#include "llstatusbar.h" // can_afford_transaction()
+#include "llnotificationsutil.h"
+#include "llagentbenefits.h"
+#include "llviewercontrol.h"
+
+LLSimpleOutfitSnapshotFloaterView* gSimpleOutfitSnapshotFloaterView = NULL;
+
+const S32 OUTFIT_SNAPSHOT_WIDTH = 256;
+const S32 OUTFIT_SNAPSHOT_HEIGHT = 256;
+
+static LLDefaultChildRegistry::Register<LLSimpleOutfitSnapshotFloaterView> r("simple_snapshot_outfit_floater_view");
+
+///----------------------------------------------------------------------------
+/// Class LLFloaterSimpleOutfitSnapshot::Impl
+///----------------------------------------------------------------------------
+
+LLSnapshotModel::ESnapshotFormat LLFloaterSimpleOutfitSnapshot::Impl::getImageFormat(LLFloaterSnapshotBase* floater)
+{
+    return LLSnapshotModel::SNAPSHOT_FORMAT_PNG;
+}
+
+LLSnapshotModel::ESnapshotLayerType LLFloaterSimpleOutfitSnapshot::Impl::getLayerType(LLFloaterSnapshotBase* floater)
+{
+    return LLSnapshotModel::SNAPSHOT_TYPE_COLOR;
+}
+
+void LLFloaterSimpleOutfitSnapshot::Impl::updateControls(LLFloaterSnapshotBase* floater)
+{
+    LLSnapshotLivePreview* previewp = getPreviewView();
+    updateResolution(floater);
+    if (previewp)
+    {
+        previewp->setSnapshotType(LLSnapshotModel::ESnapshotType::SNAPSHOT_TEXTURE);
+        previewp->setSnapshotFormat(LLSnapshotModel::ESnapshotFormat::SNAPSHOT_FORMAT_PNG);
+        previewp->setSnapshotBufferType(LLSnapshotModel::ESnapshotLayerType::SNAPSHOT_TYPE_COLOR);
+    }
+}
+
+std::string LLFloaterSimpleOutfitSnapshot::Impl::getSnapshotPanelPrefix()
+{
+    return "panel_outfit_snapshot_";
+}
+
+void LLFloaterSimpleOutfitSnapshot::Impl::updateResolution(void* data)
+{
+    LLFloaterSimpleOutfitSnapshot *view = (LLFloaterSimpleOutfitSnapshot *)data;
+
+    if (!view)
+    {
+        llassert(view);
+        return;
+    }
+
+    S32 width = OUTFIT_SNAPSHOT_WIDTH;
+    S32 height = OUTFIT_SNAPSHOT_HEIGHT;
+
+    LLSnapshotLivePreview* previewp = getPreviewView();
+    if (previewp)
+    {
+        S32 original_width = 0, original_height = 0;
+        previewp->getSize(original_width, original_height);
+
+        if (gSavedSettings.getBOOL("RenderHUDInSnapshot"))
+        { //clamp snapshot resolution to window size when showing UI HUD in snapshot
+            width = llmin(width, gViewerWindow->getWindowWidthRaw());
+            height = llmin(height, gViewerWindow->getWindowHeightRaw());
+        }
+
+        llassert(width > 0 && height > 0);
+
+        previewp->setSize(width, height);
+
+        if (original_width != width || original_height != height)
+        {
+            // hide old preview as the aspect ratio could be wrong
+            checkAutoSnapshot(previewp, FALSE);
+            previewp->updateSnapshot(TRUE);
+        }
+    }
+}
+
+void LLFloaterSimpleOutfitSnapshot::Impl::setStatus(EStatus status, bool ok, const std::string& msg)
+{
+    switch (status)
+    {
+    case STATUS_READY:
+        mFloater->setCtrlsEnabled(true);
+        break;
+    case STATUS_WORKING:
+        mFloater->setCtrlsEnabled(false);
+        break;
+    case STATUS_FINISHED:
+        mFloater->setCtrlsEnabled(true);
+        break;
+    }
+
+    mStatus = status;
+}
+
+///----------------------------------------------------------------re------------
+/// Class LLFloaterSimpleOutfitSnapshot
+///----------------------------------------------------------------------------
+
+LLFloaterSimpleOutfitSnapshot::LLFloaterSimpleOutfitSnapshot(const LLSD& key)
+    : LLFloaterSnapshotBase(key),
+    mOutfitGallery(NULL)
+{
+    impl = new Impl(this);
+}
+
+LLFloaterSimpleOutfitSnapshot::~LLFloaterSimpleOutfitSnapshot()
+{
+}
+
+BOOL LLFloaterSimpleOutfitSnapshot::postBuild()
+{
+    getChild<LLUICtrl>("save_btn")->setLabelArg("[UPLOAD_COST]", std::to_string(LLAgentBenefitsMgr::current().getTextureUploadCost()));
+
+    childSetAction("new_snapshot_btn", ImplBase::onClickNewSnapshot, this);
+    childSetAction("save_btn", boost::bind(&LLFloaterSimpleOutfitSnapshot::onSend, this));
+    childSetAction("cancel_btn", boost::bind(&LLFloaterSimpleOutfitSnapshot::onCancel, this));
+
+    mThumbnailPlaceholder = getChild<LLUICtrl>("thumbnail_placeholder");
+
+    // create preview window
+    LLRect full_screen_rect = getRootView()->getRect();
+    LLSnapshotLivePreview::Params p;
+    p.rect(full_screen_rect);
+    LLSnapshotLivePreview* previewp = new LLSnapshotLivePreview(p);
+    LLView* parent_view = gSnapshotFloaterView->getParent();
+
+    parent_view->removeChild(gSnapshotFloaterView);
+    // make sure preview is below snapshot floater
+    parent_view->addChild(previewp);
+    parent_view->addChild(gSnapshotFloaterView);
+
+    //move snapshot floater to special purpose snapshotfloaterview
+    gFloaterView->removeChild(this);
+    gSnapshotFloaterView->addChild(this);
+
+    impl->mPreviewHandle = previewp->getHandle();
+    previewp->setContainer(this);
+    impl->updateControls(this);
+    impl->setAdvanced(true);
+    impl->setSkipReshaping(true);
+
+    previewp->mKeepAspectRatio = FALSE;
+    previewp->setThumbnailPlaceholderRect(getThumbnailPlaceholderRect());
+    previewp->setAllowRenderUI(false);
+
+    return TRUE;
+}
+const S32 PREVIEW_OFFSET_X = 12;
+const S32 PREVIEW_OFFSET_Y = 70;
+
+void LLFloaterSimpleOutfitSnapshot::draw()
+{
+    LLSnapshotLivePreview* previewp = getPreviewView();
+
+    if (previewp && (previewp->isSnapshotActive() || previewp->getThumbnailLock()))
+    {
+        // don't render snapshot window in snapshot, even if "show ui" is turned on
+        return;
+    }
+
+    LLFloater::draw();
+
+    if (previewp && !isMinimized() && mThumbnailPlaceholder->getVisible())
+    {		
+        if(previewp->getThumbnailImage())
+        {
+            bool working = impl->getStatus() == ImplBase::STATUS_WORKING;
+            const LLRect& thumbnail_rect = getThumbnailPlaceholderRect();
+            const S32 thumbnail_w = previewp->getThumbnailWidth();
+            const S32 thumbnail_h = previewp->getThumbnailHeight();
+
+            S32 offset_x = PREVIEW_OFFSET_X;
+            S32 offset_y = PREVIEW_OFFSET_Y;
+
+            gGL.matrixMode(LLRender::MM_MODELVIEW);
+            // Apply floater transparency to the texture unless the floater is focused.
+            F32 alpha = getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency();
+            LLColor4 color = working ? LLColor4::grey4 : LLColor4::white;
+            gl_draw_scaled_image(offset_x, offset_y, 
+                thumbnail_w, thumbnail_h,
+                previewp->getThumbnailImage(), color % alpha);
+#if LL_DARWIN
+            std::string alpha_color = getTransparencyType() == TT_ACTIVE ? "OutfitSnapshotMacMask" : "OutfitSnapshotMacMask2";
+#else
+            std::string alpha_color = getTransparencyType() == TT_ACTIVE ? "FloaterFocusBackgroundColor" : "DkGray";
+#endif
+
+            previewp->drawPreviewRect(offset_x, offset_y, LLUIColorTable::instance().getColor(alpha_color));
+
+            gGL.pushUIMatrix();
+            LLUI::translate((F32) thumbnail_rect.mLeft, (F32) thumbnail_rect.mBottom);
+            mThumbnailPlaceholder->draw();
+            gGL.popUIMatrix();
+        }
+    }
+    impl->updateLayout(this);
+}
+
+void LLFloaterSimpleOutfitSnapshot::onOpen(const LLSD& key)
+{
+    LLSnapshotLivePreview* preview = getPreviewView();
+    if (preview)
+    {
+        preview->updateSnapshot(TRUE);
+    }
+    focusFirstItem(FALSE);
+    gSnapshotFloaterView->setEnabled(TRUE);
+    gSnapshotFloaterView->setVisible(TRUE);
+    gSnapshotFloaterView->adjustToFitScreen(this, FALSE);
+
+    impl->updateControls(this);
+    impl->setStatus(ImplBase::STATUS_READY);
+}
+
+void LLFloaterSimpleOutfitSnapshot::onCancel()
+{
+    closeFloater();
+}
+
+void LLFloaterSimpleOutfitSnapshot::onSend()
+{
+    S32 expected_upload_cost = LLAgentBenefitsMgr::current().getTextureUploadCost();
+    if (can_afford_transaction(expected_upload_cost))
+    {
+        saveTexture();
+        postSave();
+    }
+    else
+    {
+        LLSD args;
+        args["COST"] = llformat("%d", expected_upload_cost);
+        LLNotificationsUtil::add("ErrorPhotoCannotAfford", args);
+        inventorySaveFailed();
+    }
+}
+
+void LLFloaterSimpleOutfitSnapshot::postSave()
+{
+    impl->setStatus(ImplBase::STATUS_WORKING);
+}
+
+// static 
+void LLFloaterSimpleOutfitSnapshot::update()
+{
+    LLFloaterSimpleOutfitSnapshot* inst = findInstance();
+    if (inst != NULL)
+    {
+        inst->impl->updateLivePreview();
+    }
+}
+
+
+// static
+LLFloaterSimpleOutfitSnapshot* LLFloaterSimpleOutfitSnapshot::findInstance()
+{
+    return LLFloaterReg::findTypedInstance<LLFloaterSimpleOutfitSnapshot>("simple_outfit_snapshot");
+}
+
+// static
+LLFloaterSimpleOutfitSnapshot* LLFloaterSimpleOutfitSnapshot::getInstance()
+{
+    return LLFloaterReg::getTypedInstance<LLFloaterSimpleOutfitSnapshot>("simple_outfit_snapshot");
+}
+
+void LLFloaterSimpleOutfitSnapshot::saveTexture()
+{
+     LLSnapshotLivePreview* previewp = getPreviewView();
+    if (!previewp)
+    {
+        llassert(previewp != NULL);
+        return;
+    }
+
+    if (mOutfitGallery)
+    {
+        mOutfitGallery->onBeforeOutfitSnapshotSave();
+    }
+    previewp->saveTexture(TRUE, getOutfitID().asString());
+    if (mOutfitGallery)
+    {
+        mOutfitGallery->onAfterOutfitSnapshotSave();
+    }
+    closeFloater();
+}
+
+///----------------------------------------------------------------------------
+/// Class LLSimpleOutfitSnapshotFloaterView
+///----------------------------------------------------------------------------
+
+LLSimpleOutfitSnapshotFloaterView::LLSimpleOutfitSnapshotFloaterView(const Params& p) : LLFloaterView(p)
+{
+}
+
+LLSimpleOutfitSnapshotFloaterView::~LLSimpleOutfitSnapshotFloaterView()
+{
+}
diff --git a/indra/newview/llfloatersimpleoutfitsnapshot.h b/indra/newview/llfloatersimpleoutfitsnapshot.h
new file mode 100644
index 0000000000000000000000000000000000000000..cc9a6c5d1e4016ef57382321ce743b09ddff1f96
--- /dev/null
+++ b/indra/newview/llfloatersimpleoutfitsnapshot.h
@@ -0,0 +1,129 @@
+/**
+* @file llfloatersimpleoutfitsnapshot.h
+* @brief Snapshot preview window for saving as an outfit thumbnail in visual outfit gallery
+*
+* $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$
+*/
+
+#ifndef LL_LLFLOATERSIMPLEOUTFITSNAPSHOT_H
+#define LL_LLFLOATERSIMPLEOUTFITSNAPSHOT_H
+
+#include "llfloater.h"
+#include "llfloatersnapshot.h"
+#include "lloutfitgallery.h"
+#include "llsnapshotlivepreview.h"
+
+///----------------------------------------------------------------------------
+/// Class LLFloaterSimpleOutfitSnapshot
+///----------------------------------------------------------------------------
+
+class LLFloaterSimpleOutfitSnapshot : public LLFloaterSnapshotBase
+{
+    LOG_CLASS(LLFloaterSimpleOutfitSnapshot);
+
+public:
+
+    LLFloaterSimpleOutfitSnapshot(const LLSD& key);
+    ~LLFloaterSimpleOutfitSnapshot();
+
+    BOOL postBuild();
+    void onOpen(const LLSD& key);
+    void draw();
+
+    static void update();
+
+    static LLFloaterSimpleOutfitSnapshot* getInstance();
+    static LLFloaterSimpleOutfitSnapshot* findInstance();
+    void saveTexture();
+
+    const LLRect& getThumbnailPlaceholderRect() { return mThumbnailPlaceholder->getRect(); }
+
+    void setOutfitID(LLUUID id) { mOutfitID = id; }
+    LLUUID getOutfitID() { return mOutfitID; }
+    void setGallery(LLOutfitGallery* gallery) { mOutfitGallery = gallery; }
+
+    void postSave();
+
+    class Impl;
+    friend class Impl;
+
+private:
+    void onSend();
+    void onCancel();
+
+    LLUUID mOutfitID;
+    LLOutfitGallery* mOutfitGallery;
+};
+
+///----------------------------------------------------------------------------
+/// Class LLFloaterSimpleOutfitSnapshot::Impl
+///----------------------------------------------------------------------------
+
+class LLFloaterSimpleOutfitSnapshot::Impl : public LLFloaterSnapshotBase::ImplBase
+{
+    LOG_CLASS(LLFloaterSimpleOutfitSnapshot::Impl);
+public:
+    Impl(LLFloaterSnapshotBase* floater)
+        : LLFloaterSnapshotBase::ImplBase(floater)
+    {}
+    ~Impl()
+    {}
+    void updateResolution(void* data);
+
+    static void onSnapshotUploadFinished(LLFloaterSnapshotBase* floater, bool status);
+
+    LLPanelSnapshot* getActivePanel(LLFloaterSnapshotBase* floater, bool ok_if_not_found = true) { return NULL; }
+    LLSnapshotModel::ESnapshotFormat getImageFormat(LLFloaterSnapshotBase* floater);
+    std::string getSnapshotPanelPrefix();
+
+    void updateControls(LLFloaterSnapshotBase* floater);
+
+    void setStatus(EStatus status, bool ok = true, const std::string& msg = LLStringUtil::null);
+
+private:
+    LLSnapshotModel::ESnapshotLayerType getLayerType(LLFloaterSnapshotBase* floater);
+    void setFinished(bool finished, bool ok = true, const std::string& msg = LLStringUtil::null) {};
+};
+
+///----------------------------------------------------------------------------
+/// Class LLSimpleOutfitSnapshotFloaterView
+///----------------------------------------------------------------------------
+
+class LLSimpleOutfitSnapshotFloaterView : public LLFloaterView
+{
+public:
+    struct Params
+        : public LLInitParam::Block<Params, LLFloaterView::Params>
+    {
+    };
+
+protected:
+    LLSimpleOutfitSnapshotFloaterView(const Params& p);
+    friend class LLUICtrlFactory;
+
+public:
+    virtual ~LLSimpleOutfitSnapshotFloaterView();
+};
+
+extern LLSimpleOutfitSnapshotFloaterView* gSimpleOutfitSnapshotFloaterView;
+
+#endif // LL_LLFLOATERSIMPLEOUTFITSNAPSHOT_H
diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp
index 83212230e52acafc59fdae2cf08414d48024b07c..6b9d4580dccdaf44da194bdbc0b80433c4eded78 100644
--- a/indra/newview/llfloatersnapshot.cpp
+++ b/indra/newview/llfloatersnapshot.cpp
@@ -176,16 +176,20 @@ void LLFloaterSnapshotBase::ImplBase::updateLayout(LLFloaterSnapshotBase* floate
 
 	LLUICtrl* thumbnail_placeholder = floaterp->getChild<LLUICtrl>("thumbnail_placeholder");
 	thumbnail_placeholder->setVisible(mAdvanced);
-	thumbnail_placeholder->reshape(panel_width, thumbnail_placeholder->getRect().getHeight());
+
 	floaterp->getChild<LLUICtrl>("image_res_text")->setVisible(mAdvanced);
 	floaterp->getChild<LLUICtrl>("file_size_label")->setVisible(mAdvanced);
     if (floaterp->hasChild("360_label", TRUE))
     { 
         floaterp->getChild<LLUICtrl>("360_label")->setVisible(mAdvanced);
     }
-	if(!floaterp->isMinimized())
+	if (!mSkipReshaping)
 	{
-		floaterp->reshape(floater_width, floaterp->getRect().getHeight());
+        thumbnail_placeholder->reshape(panel_width, thumbnail_placeholder->getRect().getHeight());
+        if (!floaterp->isMinimized())
+        {
+            floaterp->reshape(floater_width, floaterp->getRect().getHeight());
+        }
 	}
 
 	bool use_freeze_frame = floaterp->getChild<LLUICtrl>("freeze_frame_check")->getValue().asBoolean();
@@ -1193,7 +1197,7 @@ S32 LLFloaterSnapshotBase::notify(const LLSD& info)
 
 		// The refresh button is initially hidden. We show it after the first update,
 		// i.e. when preview appears.
-		if (!mRefreshBtn->getVisible())
+		if (mRefreshBtn && !mRefreshBtn->getVisible())
 		{
 			mRefreshBtn->setVisible(true);
 		}
diff --git a/indra/newview/llfloatersnapshot.h b/indra/newview/llfloatersnapshot.h
index 7ec133ff4585cfa2fd85300452b0ca135afd11c7..7fc62a27469bb91fd84e3216017e2c860b54b585 100644
--- a/indra/newview/llfloatersnapshot.h
+++ b/indra/newview/llfloatersnapshot.h
@@ -59,9 +59,9 @@ class LLFloaterSnapshotBase : public LLFloater
 
 	const LLRect& getThumbnailPlaceholderRect() { return mThumbnailPlaceholder->getRect(); }
 
-	void setRefreshLabelVisible(bool value) { mRefreshLabel->setVisible(value); }
-	void setSuccessLabelPanelVisible(bool value) { mSucceessLblPanel->setVisible(value); }
-	void setFailureLabelPanelVisible(bool value) { mFailureLblPanel->setVisible(value); }
+	void setRefreshLabelVisible(bool value) { if (mRefreshLabel) mRefreshLabel->setVisible(value); }
+	void setSuccessLabelPanelVisible(bool value) { if (mSucceessLblPanel) mSucceessLblPanel->setVisible(value); }
+	void setFailureLabelPanelVisible(bool value) { if (mFailureLblPanel) mFailureLblPanel->setVisible(value); }
 	void inventorySaveFailed();
 
 	class ImplBase;
@@ -88,6 +88,7 @@ class LLFloaterSnapshotBase::ImplBase
 		mLastToolset(NULL),
 		mAspectRatioCheckOff(false),
 		mNeedRefresh(false),
+        mSkipReshaping(false),
 		mStatus(STATUS_READY),
 		mFloater(floater)
 	{}
@@ -120,6 +121,7 @@ class LLFloaterSnapshotBase::ImplBase
 	static BOOL updatePreviewList(bool initialized);
 
 	void setAdvanced(bool advanced) { mAdvanced = advanced; }
+    void setSkipReshaping(bool skip) { mSkipReshaping = skip; }
 
 	virtual LLSnapshotModel::ESnapshotLayerType getLayerType(LLFloaterSnapshotBase* floater) = 0;
 	virtual void checkAutoSnapshot(LLSnapshotLivePreview* floater, BOOL update_thumbnail = FALSE);
@@ -135,6 +137,7 @@ class LLFloaterSnapshotBase::ImplBase
 	bool mAspectRatioCheckOff;
 	bool mNeedRefresh;
 	bool mAdvanced;
+    bool mSkipReshaping;
 	EStatus mStatus;
 };
 
diff --git a/indra/newview/llfloatertranslationsettings.cpp b/indra/newview/llfloatertranslationsettings.cpp
index b1316e386df0ccb4262ac30409560dff2297c644..082bb888b1fa444003fba5901002131bc84cba64 100644
--- a/indra/newview/llfloatertranslationsettings.cpp
+++ b/indra/newview/llfloatertranslationsettings.cpp
@@ -289,7 +289,6 @@ void LLFloaterTranslationSettings::onBtnOK()
 	gSavedSettings.setString("TranslationService", getSelectedService());
 	gSavedSettings.setString("BingTranslateAPIKey", getEnteredBingKey());
 	gSavedSettings.setString("GoogleTranslateAPIKey", getEnteredGoogleKey());
-	(LLFloaterReg::getTypedInstance<LLFloaterIMNearbyChat>("nearby_chat"))->
-			showTranslationCheckbox(LLTranslate::isTranslationConfigured());
+
 	closeFloater(false);
 }
diff --git a/indra/newview/llfloaterworldmap.cpp b/indra/newview/llfloaterworldmap.cpp
index 01bfae89346c5e33c055d6b4bd234e0c3dd37114..704abd269fa7e109214d6a305895a3c27fe7c2b9 100755
--- a/indra/newview/llfloaterworldmap.cpp
+++ b/indra/newview/llfloaterworldmap.cpp
@@ -122,7 +122,7 @@ class LLWorldMapHandler : public LLCommandHandler
 {
 public:
 	// requires trusted browser to trigger
-	LLWorldMapHandler() : LLCommandHandler("worldmap", UNTRUSTED_THROTTLE ) { }
+	LLWorldMapHandler() : LLCommandHandler("worldmap", UNTRUSTED_CLICK_ONLY ) { }
 	
 	bool handle(const LLSD& params, const LLSD& query_map,
 				LLMediaCtrl* web)
@@ -159,7 +159,7 @@ class LLMapTrackAvatarHandler : public LLCommandHandler
 {
 public:
 	// requires trusted browser to trigger
-	LLMapTrackAvatarHandler() : LLCommandHandler("maptrackavatar", UNTRUSTED_THROTTLE) 
+	LLMapTrackAvatarHandler() : LLCommandHandler("maptrackavatar", UNTRUSTED_CLICK_ONLY) 
 	{ 
 	}
 	
diff --git a/indra/newview/llgroupactions.cpp b/indra/newview/llgroupactions.cpp
index 84a12787679e0846b1804172972831a6de85be6d..be52e280e1935286666118a585c32c2282057e92 100644
--- a/indra/newview/llgroupactions.cpp
+++ b/indra/newview/llgroupactions.cpp
@@ -52,7 +52,32 @@ class LLGroupHandler : public LLCommandHandler
 {
 public:
 	// requires trusted browser to trigger
-	LLGroupHandler() : LLCommandHandler("group", UNTRUSTED_THROTTLE) { }
+	LLGroupHandler() : LLCommandHandler("group", UNTRUSTED_CLICK_ONLY) { }
+
+    virtual bool canHandleUntrusted(
+        const LLSD& params,
+        const LLSD& query_map,
+        LLMediaCtrl* web,
+        const std::string& nav_type)
+    {
+        if (params.size() < 1)
+        {
+            return true; // don't block, will fail later
+        }
+
+        if (nav_type == NAV_TYPE_CLICKED)
+        {
+            return true;
+        }
+
+        const std::string verb = params[0].asString();
+        if (verb == "create")
+        {
+            return false;
+        }
+        return true;
+    }
+
 	bool handle(const LLSD& tokens, const LLSD& query_map,
 				LLMediaCtrl* web)
 	{
@@ -175,8 +200,7 @@ class LLFetchGroupMemberData : public LLGroupMgrObserver
 	virtual void processGroupData() = 0;
 protected:
 	LLUUID mGroupId;
-private:
-	bool mRequestProcessed;
+    bool mRequestProcessed;
 };
 
 class LLFetchLeaveGroupData: public LLFetchGroupMemberData
@@ -189,6 +213,22 @@ class LLFetchLeaveGroupData: public LLFetchGroupMemberData
 	 {
 		 LLGroupActions::processLeaveGroupDataResponse(mGroupId);
 	 }
+     void changed(LLGroupChange gc)
+     {
+         if (gc == GC_PROPERTIES && !mRequestProcessed)
+         {
+             LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupId);
+             if (!gdatap)
+             {
+                 LL_WARNS() << "GroupData was NULL" << LL_ENDL;
+             } 
+             else
+             {
+                 processGroupData();
+                 mRequestProcessed = true;
+             }
+         }
+     }
 };
 
 LLFetchLeaveGroupData* gFetchLeaveGroupData = NULL;
diff --git a/indra/newview/llimprocessing.cpp b/indra/newview/llimprocessing.cpp
index 0524313a5cc678f2babda97e72b6e0ee0d1b45a6..af2d168aefef8211ef667cd3234a86241ce0934f 100644
--- a/indra/newview/llimprocessing.cpp
+++ b/indra/newview/llimprocessing.cpp
@@ -55,6 +55,7 @@
 #include "llviewerwindow.h"
 #include "llviewerregion.h"
 #include "llvoavatarself.h"
+#include "llworld.h"
 
 #include "boost/lexical_cast.hpp"
 #if LL_MSVC
@@ -520,8 +521,7 @@ void LLIMProcessing::processNewMessage(LLUUID from_id,
                     dialog,
                     parent_estate_id,
                     region_id,
-                    position,
-                    true);
+                    position);
 
                 if (!gIMMgr->isDNDMessageSend(session_id))
                 {
@@ -572,6 +572,15 @@ void LLIMProcessing::processNewMessage(LLUUID from_id,
                 }
                 if (!mute_im)
                 {
+                    bool region_message = false;
+                    if (region_id.isNull())
+                    {
+                        LLViewerRegion* regionp = LLWorld::instance().getRegionFromID(from_id);
+                        if (regionp)
+                        {
+                            region_message = true;
+                        }
+                    }
                     gIMMgr->addMessage(
                         session_id,
                         from_id,
@@ -583,7 +592,7 @@ void LLIMProcessing::processNewMessage(LLUUID from_id,
                         parent_estate_id,
                         region_id,
                         position,
-                        true);
+                        region_message);
                 }
                 else
                 {
@@ -1102,8 +1111,7 @@ void LLIMProcessing::processNewMessage(LLUUID from_id,
                     IM_SESSION_INVITE,
                     parent_estate_id,
                     region_id,
-                    position,
-                    true);
+                    position);
             }
             else
             {
@@ -1128,8 +1136,7 @@ void LLIMProcessing::processNewMessage(LLUUID from_id,
                     IM_SESSION_INVITE,
                     parent_estate_id,
                     region_id,
-                    position,
-                    true);
+                    position);
             }
             break;
 
@@ -1561,7 +1568,7 @@ void LLIMProcessing::requestOfflineMessagesCoro(std::string url)
         return;
     }
 
-    if (messages.emptyArray())
+    if (messages.size() == 0)
     {
         // Nothing to process
         return;
diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp
index 4d6ebf9cbb4bee8e8b1a1ef1af0ca6489cc9c50b..3607e49b4abbc8bf3dc573a981da8f227b95b830 100644
--- a/indra/newview/llimview.cpp
+++ b/indra/newview/llimview.cpp
@@ -760,7 +760,7 @@ void LLIMModel::LLIMSession::sessionInitReplyReceived(const LLUUID& new_session_
 	}
 }
 
-void LLIMModel::LLIMSession::addMessage(const std::string& from, const LLUUID& from_id, const std::string& utf8_text, const std::string& time, const bool is_history)
+void LLIMModel::LLIMSession::addMessage(const std::string& from, const LLUUID& from_id, const std::string& utf8_text, const std::string& time, const bool is_history, bool is_region_msg)
 {
 	LLSD message;
 	message["from"] = from;
@@ -769,6 +769,7 @@ void LLIMModel::LLIMSession::addMessage(const std::string& from, const LLUUID& f
 	message["time"] = time; 
 	message["index"] = (LLSD::Integer)mMsgs.size(); 
 	message["is_history"] = is_history;
+	message["is_region_msg"] = is_region_msg;
 
 	LL_DEBUGS("UIUsage") << "addMessage " << " from " << from << " from_id " << from_id << " utf8_text " << utf8_text << " time " << time << " is_history " << is_history << " session mType " << mType << LL_ENDL;
 	if (from_id == gAgent.getID())
@@ -1149,7 +1150,7 @@ void LLIMModel::sendNoUnreadMessages(const LLUUID& session_id)
 	mNoUnreadMsgsSignal(arg);
 }
 
-bool LLIMModel::addToHistory(const LLUUID& session_id, const std::string& from, const LLUUID& from_id, const std::string& utf8_text) {
+bool LLIMModel::addToHistory(const LLUUID& session_id, const std::string& from, const LLUUID& from_id, const std::string& utf8_text, bool is_region_msg) {
 	
 	LLIMSession* session = findIMSession(session_id);
 
@@ -1159,7 +1160,7 @@ bool LLIMModel::addToHistory(const LLUUID& session_id, const std::string& from,
 		return false;
 	}
 
-	session->addMessage(from, from_id, utf8_text, LLLogChat::timestamp(false)); //might want to add date separately
+	session->addMessage(from, from_id, utf8_text, LLLogChat::timestamp(false), false, is_region_msg); //might want to add date separately
 
 	return true;
 }
@@ -1197,9 +1198,9 @@ bool LLIMModel::proccessOnlineOfflineNotification(
 }
 
 bool LLIMModel::addMessage(const LLUUID& session_id, const std::string& from, const LLUUID& from_id, 
-						   const std::string& utf8_text, bool log2file /* = true */) { 
+						   const std::string& utf8_text, bool log2file, bool is_region_msg) { 
 
-	LLIMSession* session = addMessageSilently(session_id, from, from_id, utf8_text, log2file);
+	LLIMSession* session = addMessageSilently(session_id, from, from_id, utf8_text, log2file, is_region_msg);
 	if (!session) return false;
 
 	//good place to add some1 to recent list
@@ -1224,7 +1225,7 @@ bool LLIMModel::addMessage(const LLUUID& session_id, const std::string& from, co
 }
 
 LLIMModel::LLIMSession* LLIMModel::addMessageSilently(const LLUUID& session_id, const std::string& from, const LLUUID& from_id, 
-													 const std::string& utf8_text, bool log2file /* = true */)
+													 const std::string& utf8_text, bool log2file, bool is_region_msg)
 {
 	LLIMSession* session = findIMSession(session_id);
 
@@ -1240,7 +1241,7 @@ LLIMModel::LLIMSession* LLIMModel::addMessageSilently(const LLUUID& session_id,
 		from_name = SYSTEM_FROM;
 	}
 
-	addToHistory(session_id, from_name, from_id, utf8_text);
+	addToHistory(session_id, from_name, from_id, utf8_text, is_region_msg);
 	if (log2file)
 	{
 		logToFile(getHistoryFileName(session_id), from_name, from_id, utf8_text);
@@ -2114,8 +2115,6 @@ void LLOutgoingCallDialog::show(const LLSD& key)
 
 	std::string callee_name = mPayload["session_name"].asString();
 
-	LLUUID session_id = mPayload["session_id"].asUUID();
-
 	if (callee_name == "anonymous") // obsolete? Likely was part of avaline support
 	{
 		callee_name = getString("anonymous");
@@ -2499,7 +2498,7 @@ void LLIncomingCallDialog::processCallResponse(S32 response, const LLSD &payload
 				}
 			}
 			
-			LLUUID new_session_id = gIMMgr->addSession(correct_session_name, type, session_id, true);
+			gIMMgr->addSession(correct_session_name, type, session_id, true);
 
 			std::string url = gAgent.getRegion()->getCapability(
 				"ChatSessionRequest");
@@ -2585,7 +2584,7 @@ bool inviteUserResponse(const LLSD& notification, const LLSD& response)
 			}
 			else
 			{
-				LLUUID new_session_id = gIMMgr->addSession(
+				gIMMgr->addSession(
 					payload["session_name"].asString(),
 					type,
 					session_id, true);
@@ -2663,7 +2662,7 @@ void LLIMMgr::addMessage(
 	U32 parent_estate_id,
 	const LLUUID& region_id,
 	const LLVector3& position,
-	bool link_name) // If this is true, then we insert the name and link it to a profile
+	bool is_region_msg)
 {
 	LLUUID other_participant_id = target_id;
 
@@ -2735,7 +2734,7 @@ void LLIMMgr::addMessage(
 				//<< "*** region_id: " << region_id << std::endl
 				//<< "*** position: " << position << std::endl;
 
-				LLIMModel::instance().addMessage(new_session_id, from, other_participant_id, bonus_info.str());
+				LLIMModel::instance().addMessage(new_session_id, from, other_participant_id, bonus_info.str(), true, is_region_msg);
 			}
 
 			// Logically it would make more sense to reject the session sooner, in another area of the
@@ -2765,7 +2764,7 @@ void LLIMMgr::addMessage(
 
 	if (!LLMuteList::getInstance()->isMuted(other_participant_id, LLMute::flagTextChat) && !skip_message)
 	{
-		LLIMModel::instance().addMessage(new_session_id, from, other_participant_id, msg);
+		LLIMModel::instance().addMessage(new_session_id, from, other_participant_id, msg, true, is_region_msg);
 	}
 
 	// Open conversation floater if offline messages are present
@@ -3692,8 +3691,7 @@ class LLViewerChatterBoxInvitation : public LLHTTPNode
 				IM_SESSION_INVITE,
 				message_params["parent_estate_id"].asInteger(),
 				message_params["region_id"].asUUID(),
-				ll_vector3_from_sd(message_params["position"]),
-				true);
+				ll_vector3_from_sd(message_params["position"]));
 
 			if (LLMuteList::getInstance()->isMuted(from_id, name, LLMute::flagTextChat))
 			{
diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h
index fdf9806e2ec22f2421e4e6801dea9062359cc4cb..326e8f22e3061829ca0edddbaaf3200c5ed69a4c 100644
--- a/indra/newview/llimview.h
+++ b/indra/newview/llimview.h
@@ -81,7 +81,7 @@ class LLIMModel :  public LLSingleton<LLIMModel>
 
 		void sessionInitReplyReceived(const LLUUID& new_session_id);
 		void addMessagesFromHistory(const std::list<LLSD>& history);
-		void addMessage(const std::string& from, const LLUUID& from_id, const std::string& utf8_text, const std::string& time, const bool is_history = false);
+		void addMessage(const std::string& from, const LLUUID& from_id, const std::string& utf8_text, const std::string& time, const bool is_history = false, bool is_region_msg = false);
 		void onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state, const LLVoiceChannel::EDirection& direction);
 		
 		/** @deprecated */
@@ -208,13 +208,13 @@ class LLIMModel :  public LLSingleton<LLIMModel>
 	 * and also saved into a file if log2file is specified.
 	 * It sends new message signal for each added message.
 	 */
-	bool addMessage(const LLUUID& session_id, const std::string& from, const LLUUID& other_participant_id, const std::string& utf8_text, bool log2file = true);
+	bool addMessage(const LLUUID& session_id, const std::string& from, const LLUUID& other_participant_id, const std::string& utf8_text, bool log2file = true, bool is_region_msg = false);
 
 	/**
 	 * Similar to addMessage(...) above but won't send a signal about a new message added
 	 */
 	LLIMModel::LLIMSession* addMessageSilently(const LLUUID& session_id, const std::string& from, const LLUUID& from_id, 
-		const std::string& utf8_text, bool log2file = true);
+		const std::string& utf8_text, bool log2file = true, bool is_region_msg = false);
 
 	/**
 	 * Add a system message to an IM Model
@@ -292,7 +292,7 @@ class LLIMModel :  public LLSingleton<LLIMModel>
 	/**
 	 * Add message to a list of message associated with session specified by session_id
 	 */
-	bool addToHistory(const LLUUID& session_id, const std::string& from, const LLUUID& from_id, const std::string& utf8_text);
+	bool addToHistory(const LLUUID& session_id, const std::string& from, const LLUUID& from_id, const std::string& utf8_text, bool is_region_msg = false);
 
 };
 
@@ -334,7 +334,7 @@ class LLIMMgr : public LLSingleton<LLIMMgr>
 					U32 parent_estate_id = 0,
 					const LLUUID& region_id = LLUUID::null,
 					const LLVector3& position = LLVector3::zero,
-					bool link_name = false);
+					bool is_region_msg = false);
 
 	void addSystemMessage(const LLUUID& session_id, const std::string& message_name, const LLSD& args);
 
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index a0bc1035bfecbb0ac5650682dde81e54fb259810..db347f7096c2357ad4097ecf6f85caaf1997f235 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -614,7 +614,7 @@ BOOL LLInvFVBridge::isClipboardPasteable() const
 		if (cat)
 		{
 			LLFolderBridge cat_br(mInventoryPanel.get(), mRoot, item_id);
-			if (!cat_br.isItemCopyable())
+			if (!cat_br.isItemCopyable(false))
 			return FALSE;
 			// Skip to the next item in the clipboard
 			continue;
@@ -622,7 +622,7 @@ BOOL LLInvFVBridge::isClipboardPasteable() const
 
 		// Each item must be copyable to be pastable
 		LLItemBridge item_br(mInventoryPanel.get(), mRoot, item_id);
-		if (!item_br.isItemCopyable())
+		if (!item_br.isItemCopyable(false))
 		{
 			return FALSE;
 		}
@@ -654,6 +654,11 @@ BOOL LLInvFVBridge::isClipboardPasteableAsLink() const
 			{
 				return FALSE;
 			}
+
+            if (gInventory.isObjectDescendentOf(item->getUUID(), gInventory.getLibraryRootFolderID()))
+            {
+                return FALSE;
+            }
 		}
 		const LLViewerInventoryCategory *cat = model->getCategory(objects.at(i));
 		if (cat && LLFolderType::lookupIsProtectedType(cat->getPreferredType()))
@@ -729,15 +734,15 @@ void hide_context_entries(LLMenuGL& menu,
 		}
 
 		bool found = false;
-		menuentry_vec_t::const_iterator itor2;
-		for (itor2 = entries_to_show.begin(); itor2 != entries_to_show.end(); ++itor2)
-		{
-			if (*itor2 == name)
-			{
-				found = true;
-				break;
-			}
-		}
+
+        std::string myinput;
+        std::vector<std::string> mylist{ "a", "b", "c" };
+
+        menuentry_vec_t::const_iterator itor2 = std::find(entries_to_show.begin(), entries_to_show.end(), name);
+        if (itor2 != entries_to_show.end())
+        {
+            found = true;
+        }
 
 		// Don't allow multiple separators in a row (e.g. such as if there are no items
 		// between two separators).
@@ -755,7 +760,21 @@ void hide_context_entries(LLMenuGL& menu,
 				menu_item->setVisible(FALSE);
 			}
 
-			menu_item->setEnabled(FALSE);
+            if (menu_item->getEnabled())
+            {
+                // These should stay enabled unless specifically disabled
+                const menuentry_vec_t exceptions = {
+                    "Detach From Yourself",
+                    "Wearable And Object Wear",
+                    "Wearable Add",
+                };
+
+                menuentry_vec_t::const_iterator itor2 = std::find(exceptions.begin(), exceptions.end(), name);
+                if (itor2 == exceptions.end())
+                {
+                    menu_item->setEnabled(FALSE);
+                }
+            }
 		}
 		else
 		{
@@ -812,6 +831,12 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
 			{
 				disabled_items.push_back(std::string("Find Original"));
 			}
+
+            items.push_back(std::string("Cut"));
+            if (!isItemMovable() || !isItemRemovable())
+            {
+                disabled_items.push_back(std::string("Cut"));
+            }
 		}
 		else
 		{
@@ -882,7 +907,8 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
 		disabled_items.push_back(std::string("Paste"));
 	}
 
-	if (gSavedSettings.getBOOL("InventoryLinking"))
+    static LLCachedControl<bool> inventory_linking(gSavedSettings, "InventoryLinking", true);
+	if (inventory_linking)
 	{
 		items.push_back(std::string("Paste As Link"));
 		if (!isClipboardPasteableAsLink() || (flags & FIRST_SELECTED_ITEM) == 0)
@@ -2059,7 +2085,8 @@ BOOL LLItemBridge::removeItem()
 	// we can't do this check because we may have items in a folder somewhere that is
 	// not yet in memory, so we don't want false negatives.  (If disabled, then we 
 	// know we only have links in the Outfits folder which we explicitly fetch.)
-	if (!gSavedSettings.getBOOL("InventoryLinking"))
+    static LLCachedControl<bool> inventory_linking(gSavedSettings, "InventoryLinking", true);
+	if (!inventory_linking)
 	{
 		if (!item->getIsLinkType())
 		{
@@ -2102,22 +2129,25 @@ BOOL LLItemBridge::confirmRemoveItem(const LLSD& notification, const LLSD& respo
 	return FALSE;
 }
 
-BOOL LLItemBridge::isItemCopyable() const
+bool LLItemBridge::isItemCopyable(bool can_copy_as_link) const
 {
-	LLViewerInventoryItem* item = getItem();
-	if (item)
-	{
-		// Can't copy worn objects.
-		// Worn objects are tied to their inworld conterparts
-		// Copy of modified worn object will return object with obsolete asset and inventory
-		if(get_is_item_worn(mUUID))
-		{
-			return FALSE;
-		}
+    LLViewerInventoryItem* item = getItem();
+    if (!item)
+    {
+        return false;
+    }
+    // Can't copy worn objects.
+    // Worn objects are tied to their inworld conterparts
+    // Copy of modified worn object will return object with obsolete asset and inventory
+    if (get_is_item_worn(mUUID))
+    {
+        return false;
+    }
 
-		return item->getPermissions().allowCopyBy(gAgent.getID()) || gSavedSettings.getBOOL("InventoryLinking");
-	}
-	return FALSE;
+    static LLCachedControl<bool> inventory_linking(gSavedSettings, "InventoryLinking", true);
+    return (can_copy_as_link && inventory_linking)
+        || (mIsLink && inventory_linking)
+        || item->getPermissions().allowCopyBy(gAgent.getID());
 }
 
 LLViewerInventoryItem* LLItemBridge::getItem() const
@@ -2321,8 +2351,14 @@ BOOL LLFolderBridge::isUpToDate() const
 	return category->getVersion() != LLViewerInventoryCategory::VERSION_UNKNOWN;
 }
 
-BOOL LLFolderBridge::isItemCopyable() const
+bool LLFolderBridge::isItemCopyable(bool can_copy_as_link) const
 {
+    if (can_copy_as_link && !LLFolderType::lookupIsProtectedType(getPreferredType()))
+    {
+        // Can copy and paste unprotected folders as links
+        return true;
+    }
+
 	// Folders are copyable if items in them are, recursively, copyable.
 	
 	// Get the content of the folder
@@ -2336,22 +2372,26 @@ BOOL LLFolderBridge::isItemCopyable() const
 	{
 		LLInventoryItem* item = *iter;
 		LLItemBridge item_br(mInventoryPanel.get(), mRoot, item->getUUID());
-		if (!item_br.isItemCopyable())
-			return FALSE;
-}
+        if (!item_br.isItemCopyable(false))
+        {
+            return false;
+        }
+    }
 
 	// Check the folders
 	LLInventoryModel::cat_array_t cat_array_copy = *cat_array;
 	for (LLInventoryModel::cat_array_t::iterator iter = cat_array_copy.begin(); iter != cat_array_copy.end(); iter++)
-{
+    {
 		LLViewerInventoryCategory* category = *iter;
 		LLFolderBridge cat_br(mInventoryPanel.get(), mRoot, category->getUUID());
-		if (!cat_br.isItemCopyable())
-			return FALSE;
-	}
-	
-		return TRUE;
-	}
+        if (!cat_br.isItemCopyable(false))
+        {
+            return false;
+        }
+    }
+
+    return true;
+}
 
 BOOL LLFolderBridge::isClipboardPasteable() const
 {
@@ -3768,6 +3808,7 @@ void LLFolderBridge::perform_pasteFromClipboard()
 			LLInventoryObject *obj = model->getObject(item_id);
 			if (obj)
 			{
+
 				if (move_is_into_lost_and_found)
 				{
 					if (LLAssetType::AT_CATEGORY == obj->getType())
@@ -4296,7 +4337,7 @@ void LLFolderBridge::buildContextMenuFolderOptions(U32 flags,   menuentry_vec_t&
 			items.push_back(std::string("IM All Contacts In Folder"));
 		}
 
-        if (((flags & ITEM_IN_MULTI_SELECTION) == 0) && hasChildren())
+        if (((flags & ITEM_IN_MULTI_SELECTION) == 0) && hasChildren() && (type != LLFolderType::FT_OUTFIT))
         {
             items.push_back(std::string("Ungroup folder items"));
         }
diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h
index 0b0ef273e17438df0d8147ad20a5a1c47d3087c4..bdffecf1c6fcf0774131bb113bbf9374f55ba45f 100644
--- a/indra/newview/llinventorybridge.h
+++ b/indra/newview/llinventorybridge.h
@@ -119,7 +119,7 @@ class LLInvFVBridge : public LLFolderViewModelItemInventory
 	//virtual BOOL removeItem() = 0;
 	virtual void removeBatch(std::vector<LLFolderViewModelItem*>& batch);
 	virtual void move(LLFolderViewModelItem* new_parent_bridge) {}
-	virtual BOOL isItemCopyable() const { return FALSE; }
+    virtual bool isItemCopyable(bool can_copy_as_link = true) const { return false; }
 	virtual BOOL copyToClipboard() const;
 	virtual BOOL cutToClipboard();
 	virtual bool isCutToClipboard();
@@ -245,7 +245,7 @@ class LLItemBridge : public LLInvFVBridge
 	virtual BOOL isItemRenameable() const;
 	virtual BOOL renameItem(const std::string& new_name);
 	virtual BOOL removeItem();
-	virtual BOOL isItemCopyable() const;
+    virtual bool isItemCopyable(bool can_copy_as_link = true) const;
 	virtual bool hasChildren() const { return FALSE; }
 	virtual BOOL isUpToDate() const { return TRUE; }
 	virtual LLUIImagePtr getIconOverlay() const;
@@ -318,7 +318,7 @@ class LLFolderBridge : public LLInvFVBridge
 	virtual BOOL isItemRemovable() const;
 	virtual BOOL isItemMovable() const ;
 	virtual BOOL isUpToDate() const;
-	virtual BOOL isItemCopyable() const;
+    virtual bool isItemCopyable(bool can_copy_as_link = true) const;
 	virtual BOOL isClipboardPasteable() const;
 	virtual BOOL isClipboardPasteableAsLink() const;
 	
diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp
index 707ff2b7b6170ed66ec3ff69633bf9676a69beaa..e3a6b2dc855214262cc0f6cd9b7bf3e2f4dcfae9 100644
--- a/indra/newview/llinventoryfilter.cpp
+++ b/indra/newview/llinventoryfilter.cpp
@@ -437,7 +437,6 @@ bool LLInventoryFilter::checkAgainstFilterType(const LLFolderViewModelItemInvent
 bool LLInventoryFilter::checkAgainstFilterType(const LLInventoryItem* item) const
 {
 	LLInventoryType::EType object_type = item->getInventoryType();
-	const LLUUID object_id = item->getUUID();
 
 	const U32 filterTypes = mFilterOps.mFilterTypes;
 
diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp
index 27edc8148efc638062c5d43063048263b98f0c6c..af1c93f38379d2b38bc62dab4966c17f1589bdc1 100644
--- a/indra/newview/llinventoryfunctions.cpp
+++ b/indra/newview/llinventoryfunctions.cpp
@@ -862,6 +862,9 @@ LLUUID create_folder_for_item(LLInventoryItem* item, const LLUUID& destFolderId)
 S32 depth_nesting_in_marketplace(LLUUID cur_uuid)
 {
     // Get the marketplace listings root, exit with -1 (i.e. not under the marketplace listings root) if none
+    // Todo: findCategoryUUIDForType is somewhat expensive with large
+    // flat root folders yet we use depth_nesting_in_marketplace at
+    // every turn, find a way to correctly cache this id.
     const LLUUID marketplace_listings_uuid = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false);
     if (marketplace_listings_uuid.isNull())
     {
@@ -1403,9 +1406,6 @@ bool move_item_to_marketplacelistings(LLInventoryItem* inv_item, LLUUID dest_fol
                 LLNotificationsUtil::add("MerchantPasteFailed", subs);
                 return false;
             }
-            
-            // Get the parent folder of the moved item : we may have to update it
-            LLUUID src_folder = viewer_inv_item->getParentUUID();
 
             if (copy)
             {
@@ -1504,7 +1504,12 @@ void dump_trace(std::string& message, S32 depth, LLError::ELevel log_level)
 // This function does no deletion of listings but a mere audit and raises issues to the user (through the
 // optional callback cb). It also returns a boolean, true if things validate, false if issues are raised.
 // The only inventory changes that are done is to move and sort folders containing no-copy items to stock folders.
-bool validate_marketplacelistings(LLInventoryCategory* cat, validation_callback_t cb, bool fix_hierarchy, S32 depth)
+bool validate_marketplacelistings(
+    LLInventoryCategory* cat,
+    validation_callback_t cb,
+    bool fix_hierarchy,
+    S32 depth,
+    bool notify_observers)
 {
 #if 0
     // Used only for debug
@@ -1570,7 +1575,7 @@ bool validate_marketplacelistings(LLInventoryCategory* cat, validation_callback_
             LLUUID folder_uuid = gInventory.createNewCategory(parent_uuid, LLFolderType::FT_NONE, cat->getName());
             LLInventoryCategory* new_cat = gInventory.getCategory(folder_uuid);
             gInventory.changeCategoryParent(viewer_cat, folder_uuid, false);
-            result &= validate_marketplacelistings(new_cat, cb, fix_hierarchy, depth + 1);
+            result &= validate_marketplacelistings(new_cat, cb, fix_hierarchy, depth + 1, notify_observers);
             return result;
         }
         else
@@ -1740,7 +1745,10 @@ bool validate_marketplacelistings(LLInventoryCategory* cat, validation_callback_
                     // Next type
                     update_marketplace_category(parent_uuid);
                     update_marketplace_category(folder_uuid);
-                    gInventory.notifyObservers();
+                    if (notify_observers)
+                    {
+                        gInventory.notifyObservers();
+                    }
                     items_vector_it++;
                 }
             }
@@ -1754,7 +1762,7 @@ bool validate_marketplacelistings(LLInventoryCategory* cat, validation_callback_
                 {
                     LLViewerInventoryCategory * viewer_cat = (LLViewerInventoryCategory *) (*iter);
                     gInventory.changeCategoryParent(viewer_cat, parent_uuid, false);
-                    result &= validate_marketplacelistings(viewer_cat, cb, fix_hierarchy, depth);
+                    result &= validate_marketplacelistings(viewer_cat, cb, fix_hierarchy, depth, false);
                 }
             }
         }
@@ -1826,7 +1834,10 @@ bool validate_marketplacelistings(LLInventoryCategory* cat, validation_callback_
                 cb(message,depth,LLError::LEVEL_WARN);
             }
             gInventory.removeCategory(cat->getUUID());
-            gInventory.notifyObservers();
+            if (notify_observers)
+            {
+                gInventory.notifyObservers();
+            }
             return result && !has_bad_items;
         }
     }
@@ -1840,11 +1851,14 @@ bool validate_marketplacelistings(LLInventoryCategory* cat, validation_callback_
 	for (LLInventoryModel::cat_array_t::iterator iter = cat_array_copy.begin(); iter != cat_array_copy.end(); iter++)
 	{
 		LLInventoryCategory* category = *iter;
-		result &= validate_marketplacelistings(category, cb, fix_hierarchy, depth + 1);
+		result &= validate_marketplacelistings(category, cb, fix_hierarchy, depth + 1, false);
 	}
     
     update_marketplace_category(cat->getUUID(), true, true);
-    gInventory.notifyObservers();
+    if (notify_observers)
+    {
+        gInventory.notifyObservers();
+    }
     return result && !has_bad_items;
 }
 
@@ -2583,8 +2597,62 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root
 	}
 
 	std::set<LLUUID> selected_uuid_set = LLAvatarActions::getInventorySelectedUUIDs();
+
+    // copy list of applicable items into a vector for bulk handling
     uuid_vec_t ids;
-    std::copy(selected_uuid_set.begin(), selected_uuid_set.end(), std::back_inserter(ids));
+    if (action == "wear" || action == "wear_add")
+    {
+        const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
+        const LLUUID mp_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false);
+        std::copy_if(selected_uuid_set.begin(),
+            selected_uuid_set.end(),
+            std::back_inserter(ids),
+            [trash_id, mp_id](LLUUID id)
+        {
+            if (get_is_item_worn(id)
+                || LLAppearanceMgr::instance().getIsInCOF(id)
+                || gInventory.isObjectDescendentOf(id, trash_id))
+            {
+                return false;
+            }
+            if (mp_id.notNull() && gInventory.isObjectDescendentOf(id, mp_id))
+            {
+                return false;
+            }
+            LLInventoryObject* obj = (LLInventoryObject*)gInventory.getObject(id);
+            if (!obj)
+            {
+                return false;
+            }
+            if (obj->getIsLinkType() && gInventory.isObjectDescendentOf(obj->getLinkedUUID(), trash_id))
+            {
+                return false;
+            }
+            if (obj->getIsLinkType() && LLAssetType::lookupIsLinkType(obj->getType()))
+            {
+                // missing
+                return false;
+            }
+            return true;
+        }
+        );
+    }
+    else if (isRemoveAction(action))
+    {
+        std::copy_if(selected_uuid_set.begin(),
+            selected_uuid_set.end(),
+            std::back_inserter(ids),
+            [](LLUUID id)
+        {
+            return get_is_item_worn(id);
+        }
+        );
+    }
+    else
+    {
+        std::copy(selected_uuid_set.begin(), selected_uuid_set.end(), std::back_inserter(ids));
+    }
+
     // Check for actions that get handled in bulk
     if (action == "wear")
     {
diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h
index ba9f157e47ba97b389c9a51d14a49c87d3a5fc36..56ad6f6496cb67078ff62b6eee861fae6e43c3b8 100644
--- a/indra/newview/llinventoryfunctions.h
+++ b/indra/newview/llinventoryfunctions.h
@@ -87,7 +87,7 @@ bool can_move_item_to_marketplace(const LLInventoryCategory* root_folder, LLInve
 bool can_move_folder_to_marketplace(const LLInventoryCategory* root_folder, LLInventoryCategory* dest_folder, LLInventoryCategory* inv_cat, std::string& tooltip_msg, S32 bundle_size = 1, bool check_items = true, bool from_paste = false);
 bool move_item_to_marketplacelistings(LLInventoryItem* inv_item, LLUUID dest_folder, bool copy = false);
 bool move_folder_to_marketplacelistings(LLInventoryCategory* inv_cat, const LLUUID& dest_folder, bool copy = false, bool move_no_copy_items = false);
-bool validate_marketplacelistings(LLInventoryCategory* inv_cat, validation_callback_t cb = NULL, bool fix_hierarchy = true, S32 depth = -1);
+bool validate_marketplacelistings(LLInventoryCategory* inv_cat, validation_callback_t cb = NULL, bool fix_hierarchy = true, S32 depth = -1, bool notify_observers = true);
 S32  depth_nesting_in_marketplace(LLUUID cur_uuid);
 LLUUID nested_parent_id(LLUUID cur_uuid, S32 depth);
 S32 compute_stock_count(LLUUID cat_uuid, bool force_count = false);
diff --git a/indra/newview/llinventorylistitem.h b/indra/newview/llinventorylistitem.h
index d4dd212cc3e4e5fa60faff8049ca03f262f453aa..cf713a69306ec473211c80c2f3b07b5f3ae3f9a3 100644
--- a/indra/newview/llinventorylistitem.h
+++ b/indra/newview/llinventorylistitem.h
@@ -197,6 +197,7 @@ class LLPanelInventoryListItemBase : public LLPanel
 	virtual BOOL handleToolTip( S32 x, S32 y, MASK mask);
 
 	const LLUUID mInventoryItemUUID;
+    bool mHovered;
 
 private:
 
@@ -221,7 +222,6 @@ class LLPanelInventoryListItemBase : public LLPanel
 	LLUIImagePtr	mSelectedImage;
 	LLUIImagePtr	mSeparatorImage;
 
-	bool			mHovered;
 	bool			mSelected;
 	bool			mSeparatorVisible;
 
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index fab7ae8f1a3c2c821443f4daa8c1b1070697d72c..b0d6f9d9c3a580beef708b34097d87af5e733613 100644
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -1691,11 +1691,11 @@ void LLInventoryModel::deleteObject(const LLUUID& id, bool fix_broken_links, boo
 	// Can't have links to links, so there's no need for this update
 	// if the item removed is a link. Can also skip if source of the
 	// update is getting broken link info separately.
-	obj = NULL; // delete obj
 	if (fix_broken_links && !is_link_type)
 	{
 		updateLinkedObjectsFromPurge(id);
 	}
+	obj = nullptr; // delete obj
 	if (do_notify_observers)
 	{
 		notifyObservers();
@@ -1851,9 +1851,13 @@ void LLInventoryModel::addChangedMask(U32 mask, const LLUUID& referent)
             mChangedItemIDs.insert(referent);
         }
 
-        // Fix me: From DD-81, probably shouldn't be here, instead
-        // should be somewhere in an observer
-        update_marketplace_category(referent, false);
+        if (mask != LLInventoryObserver::LABEL)
+        {
+            // Fix me: From DD-81, probably shouldn't be here, instead
+            // should be somewhere in an observer or in
+            // LLMarketplaceInventoryObserver::onIdleProcessQueue
+            update_marketplace_category(referent, false);
+        }
 
         if (mask & LLInventoryObserver::ADD)
         {
@@ -2711,7 +2715,6 @@ void LLInventoryModel::buildParentChildMap()
 			// some accounts has pbroken inventory root folders
 			
 			std::string name = "My Inventory";
-			LLUUID prev_root_id = mRootFolderID;
 			for (parent_cat_map_t::const_iterator it = mParentChildCategoryTree.begin(),
 					 it_end = mParentChildCategoryTree.end(); it != it_end; ++it)
 			{
diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp
index 6b102c750063f91192ded91699f7af3212d954f4..c065c76dca247cf81a01acf6c1cbef594668f686 100644
--- a/indra/newview/llinventorypanel.cpp
+++ b/indra/newview/llinventorypanel.cpp
@@ -211,7 +211,11 @@ LLFolderView * LLInventoryPanel::createFolderRoot(LLUUID root_id )
     p.allow_drop = mParams.allow_drop_on_root;
     p.options_menu = "menu_inventory.xml";
 
-    return LLUICtrlFactory::create<LLFolderView>(p);
+	LLFolderView* fv = LLUICtrlFactory::create<LLFolderView>(p);
+	fv->setCallbackRegistrar(&mCommitCallbackRegistrar);
+	fv->setEnableRegistrar(&mEnableCallbackRegistrar);
+
+	return fv;
 }
 
 void LLInventoryPanel::clearFolderRoot()
@@ -264,6 +268,7 @@ void LLInventoryPanel::initFromParams(const LLInventoryPanel::Params& params)
 	}
 	mCommitCallbackRegistrar.popScope();
 	mFolderRoot.get()->setCallbackRegistrar(&mCommitCallbackRegistrar);
+	mFolderRoot.get()->setEnableRegistrar(&mEnableCallbackRegistrar);
 	
 	// Scroller
 		LLRect scroller_view_rect = getRect();
diff --git a/indra/newview/llkeyconflict.cpp b/indra/newview/llkeyconflict.cpp
index d3ba18525be1803413e773660660a2ffc2547d09..60f8aca94cce8d40923994da487a25b5aaf5d23c 100644
--- a/indra/newview/llkeyconflict.cpp
+++ b/indra/newview/llkeyconflict.cpp
@@ -171,8 +171,9 @@ bool LLKeyConflictHandler::isReservedByMenu(const KEY &key, const MASK &mask)
     {
         return false;
     }
-    return (gMenuBarView && gMenuBarView->hasAccelerator(key, mask))
-           || (gLoginMenuBarView && gLoginMenuBarView->hasAccelerator(key, mask));
+    // At the moment controls are only applicable inworld,
+    // ignore gLoginMenuBarView
+    return gMenuBarView && gMenuBarView->hasAccelerator(key, mask);
 }
 
 // static
@@ -182,8 +183,7 @@ bool LLKeyConflictHandler::isReservedByMenu(const LLKeyData &data)
     {
         return false;
     }
-    return (gMenuBarView && gMenuBarView->hasAccelerator(data.mKey, data.mMask))
-           || (gLoginMenuBarView && gLoginMenuBarView->hasAccelerator(data.mKey, data.mMask));
+    return gMenuBarView && gMenuBarView->hasAccelerator(data.mKey, data.mMask);
 }
 
 bool LLKeyConflictHandler::registerControl(const std::string &control_name, U32 index, EMouseClickType mouse, KEY key, MASK mask, bool ignore_mask)
diff --git a/indra/newview/lllistcontextmenu.cpp b/indra/newview/lllistcontextmenu.cpp
index 6bda8b1d0d90a556ff30e3c1160a3c3688e5a4f8..77185411c5e36d9122ce05fb9dce79522dddb66e 100644
--- a/indra/newview/lllistcontextmenu.cpp
+++ b/indra/newview/lllistcontextmenu.cpp
@@ -51,6 +51,7 @@ LLListContextMenu::~LLListContextMenu()
 	if (!mMenuHandle.isDead())
 	{
 		mMenuHandle.get()->die();
+		mMenuHandle.markDead();
 	}
 }
 
@@ -59,13 +60,8 @@ void LLListContextMenu::show(LLView* spawning_view, const uuid_vec_t& uuids, S32
 	LLContextMenu* menup = mMenuHandle.get();
 	if (menup)
 	{
-		//preventing parent (menu holder) from deleting already "dead" context menus on exit
-		LLView* parent = menup->getParent();
-		if (parent)
-		{
-			parent->removeChild(menup);
-		}
-		delete menup;
+		menup->die();
+		mMenuHandle.markDead();
 		mUUIDs.clear();
 	}
 
diff --git a/indra/newview/llmarketplacefunctions.cpp b/indra/newview/llmarketplacefunctions.cpp
index dd4ae4d201c11ddf03f139b5e89608e01c3e3c70..2d726409c6da24e67cb9e5282abdb90406934f35 100644
--- a/indra/newview/llmarketplacefunctions.cpp
+++ b/indra/newview/llmarketplacefunctions.cpp
@@ -30,6 +30,7 @@
 
 #include "llagent.h"
 #include "llbufferstream.h"
+#include "llcallbacklist.h"
 #include "llinventoryfunctions.h"
 #include "llinventoryobserver.h"
 #include "llnotificationsutil.h"
@@ -605,20 +606,67 @@ class LLMarketplaceInventoryObserver : public LLInventoryObserver
 	LLMarketplaceInventoryObserver() {}
 	virtual ~LLMarketplaceInventoryObserver() {}
 	virtual void changed(U32 mask);
+
+private:
+    static void onIdleProcessQueue(void *userdata);
+
+    // doesn't hold just marketplace related ids
+    static std::set<LLUUID> sAddQueue;
+    static std::set<LLUUID> sStructureQueue;
+    static bool sProcessingQueue;
 };
 
+std::set<LLUUID> LLMarketplaceInventoryObserver::sAddQueue;
+std::set<LLUUID> LLMarketplaceInventoryObserver::sStructureQueue;
+bool LLMarketplaceInventoryObserver::sProcessingQueue = false;
+
 void LLMarketplaceInventoryObserver::changed(U32 mask)
 {
-    // When things are added to the marketplace, we might need to re-validate and fix the containing listings
-	if (mask & LLInventoryObserver::ADD)
+	if (mask & LLInventoryObserver::ADD && LLMarketplaceData::instance().hasValidationWaiting())
 	{
+        // When things are added to the marketplace, we might need to re-validate and fix the containing listings
+        // just add whole list even if it contains items and non-marketplace folders
         const std::set<LLUUID>& changed_items = gInventory.getChangedIDs();
-        
-        std::set<LLUUID>::const_iterator id_it = changed_items.begin();
-        std::set<LLUUID>::const_iterator id_end = changed_items.end();
+        sAddQueue.insert(changed_items.begin(), changed_items.end());
+	}
+    
+	if (mask & (LLInventoryObserver::INTERNAL | LLInventoryObserver::STRUCTURE))
+	{
+        // When things are changed in the inventory, this can trigger a host of changes in the marketplace listings folder:
+        // * stock counts changing : no copy items coming in and out will change the stock count on folders
+        // * version and listing folders : moving those might invalidate the marketplace data itself
+        // Since we should cannot raise inventory change while the observer is called (the list will be cleared
+        // once observers are called) we need to raise a flag in the inventory to signal that things have been dirtied.
+        const std::set<LLUUID>& changed_items = gInventory.getChangedIDs();
+        sStructureQueue.insert(changed_items.begin(), changed_items.end());
+	}
+
+    if (!sProcessingQueue && (!sAddQueue.empty() || !sStructureQueue.empty()))
+    {
+        gIdleCallbacks.addFunction(onIdleProcessQueue, NULL);
+        // can do without sProcessingQueue, but it's usufull for simplicity and reliability
+        sProcessingQueue = true;
+    }
+}
+
+void LLMarketplaceInventoryObserver::onIdleProcessQueue(void *userdata)
+{
+    U64 start_time = LLTimer::getTotalTime(); // microseconds
+    const U64 MAX_PROCESSING_TIME = 1000;
+    U64 stop_time = start_time + MAX_PROCESSING_TIME;
+
+    if (!sAddQueue.empty())
+    {
+        // Make a copy of sAddQueue since decrementValidationWaiting
+        // can theoretically add more items
+        std::set<LLUUID> add_queue(sAddQueue);
+        sAddQueue.clear();
+
+        std::set<LLUUID>::const_iterator id_it = add_queue.begin();
+        std::set<LLUUID>::const_iterator id_end = add_queue.end();
         // First, count the number of items in this list...
         S32 count = 0;
-        for (;id_it != id_end; ++id_it)
+        for (; id_it != id_end; ++id_it)
         {
             LLInventoryObject* obj = gInventory.getObject(*id_it);
             if (obj && (LLAssetType::AT_CATEGORY != obj->getType()))
@@ -629,56 +677,58 @@ void LLMarketplaceInventoryObserver::changed(U32 mask)
         // Then, decrement the folders of that amount
         // Note that of all of those, only one folder will be a listing folder (if at all).
         // The other will be ignored by the decrement method.
-        id_it = changed_items.begin();
-        for (;id_it != id_end; ++id_it)
+        id_it = add_queue.begin();
+        for (; id_it != id_end; ++id_it)
         {
             LLInventoryObject* obj = gInventory.getObject(*id_it);
             if (obj && (LLAssetType::AT_CATEGORY == obj->getType()))
             {
-                LLMarketplaceData::instance().decrementValidationWaiting(obj->getUUID(),count);
+                // can trigger notifyObservers
+                LLMarketplaceData::instance().decrementValidationWaiting(obj->getUUID(), count);
             }
         }
-	}
-    
-    // When things are changed in the inventory, this can trigger a host of changes in the marketplace listings folder:
-    // * stock counts changing : no copy items coming in and out will change the stock count on folders
-    // * version and listing folders : moving those might invalidate the marketplace data itself
-    // Since we should cannot raise inventory change while the observer is called (the list will be cleared
-    // once observers are called) we need to raise a flag in the inventory to signal that things have been dirtied.
-    
-	if (mask & (LLInventoryObserver::INTERNAL | LLInventoryObserver::STRUCTURE))
-	{
-        const std::set<LLUUID>& changed_items = gInventory.getChangedIDs();
-    
-        std::set<LLUUID>::const_iterator id_it = changed_items.begin();
-        std::set<LLUUID>::const_iterator id_end = changed_items.end();
-        for (;id_it != id_end; ++id_it)
+    }
+
+    while (!sStructureQueue.empty() && LLTimer::getTotalTime() < stop_time)
+    {
+        std::set<LLUUID>::const_iterator id_it = sStructureQueue.begin();
+        LLInventoryObject* obj = gInventory.getObject(*id_it);
+        if (obj)
         {
-            LLInventoryObject* obj = gInventory.getObject(*id_it);
-            if (obj)
+            if (LLAssetType::AT_CATEGORY == obj->getType())
             {
-                if (LLAssetType::AT_CATEGORY == obj->getType())
+                // If it's a folder known to the marketplace, let's check it's in proper shape
+                if (LLMarketplaceData::instance().isListed(*id_it) || LLMarketplaceData::instance().isVersionFolder(*id_it))
                 {
-                    // If it's a folder known to the marketplace, let's check it's in proper shape
-                    if (LLMarketplaceData::instance().isListed(*id_it) || LLMarketplaceData::instance().isVersionFolder(*id_it))
-                    {
-                        LLInventoryCategory* cat = (LLInventoryCategory*)(obj);
-                        validate_marketplacelistings(cat);
-                    }
+                    LLInventoryCategory* cat = (LLInventoryCategory*)(obj);
+                    // can trigger notifyObservers
+                    // can cause more structural changes
+                    validate_marketplacelistings(cat);
                 }
-                else
+            }
+            else
+            {
+                // If it's not a category, it's an item...
+                LLInventoryItem* item = (LLInventoryItem*)(obj);
+                // If it's a no copy item, we may need to update the label count of marketplace listings
+                if (!item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID()))
                 {
-                    // If it's not a category, it's an item...
-                    LLInventoryItem* item = (LLInventoryItem*)(obj);
-                    // If it's a no copy item, we may need to update the label count of marketplace listings
-                    if (!item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID()))
-                    {
-                        LLMarketplaceData::instance().setDirtyCount();
-                    }
+                    LLMarketplaceData::instance().setDirtyCount();
                 }
             }
         }
-	}
+
+        // sStructureQueue could have been modified in validate_marketplacelistings
+        // adding items does not invalidate existing iterator
+        sStructureQueue.erase(id_it);
+    }
+
+    if (LLApp::isExiting() || (sAddQueue.empty() && sStructureQueue.empty()))
+    {
+        // Nothing to do anymore
+        gIdleCallbacks.deleteFunction(onIdleProcessQueue, NULL);
+        sProcessingQueue = false;
+    }
 }
 
 // Tuple == Item
diff --git a/indra/newview/llmarketplacefunctions.h b/indra/newview/llmarketplacefunctions.h
index 088507d85098d8ed0a8632b28ec43a2155d07d48..24fdc5e0ad5ef706edacbeb9c4ab045c18255b14 100644
--- a/indra/newview/llmarketplacefunctions.h
+++ b/indra/newview/llmarketplacefunctions.h
@@ -242,6 +242,7 @@ class LLMarketplaceData
     void setUpdating(const LLUUID& folder_id, bool isUpdating);
     
     // Used to decide when to run a validation on listing folders
+    bool hasValidationWaiting() { return mValidationWaitingList.size() > 0; }
     void setValidationWaiting(const LLUUID& folder_id, S32 count);
     void decrementValidationWaiting(const LLUUID& folder_id, S32 count = 1);
 
diff --git a/indra/newview/llmaterialmgr.cpp b/indra/newview/llmaterialmgr.cpp
index 11aa607393613149708b900950d7d6e6bdcb4fc1..a52f7244f3bd55b865183e2a2577f343667596c2 100644
--- a/indra/newview/llmaterialmgr.cpp
+++ b/indra/newview/llmaterialmgr.cpp
@@ -429,12 +429,10 @@ void LLMaterialMgr::onGetResponse(bool success, const LLSD& content, const LLUUI
 	llassert(content.has(MATERIALS_CAP_ZIP_FIELD));
 	llassert(content[MATERIALS_CAP_ZIP_FIELD].isBinary());
 
-	LLSD::Binary content_binary = content[MATERIALS_CAP_ZIP_FIELD].asBinary();
-	std::string content_string(reinterpret_cast<const char*>(content_binary.data()), content_binary.size());
-	std::istringstream content_stream(content_string);
+	const LLSD::Binary& content_binary = content[MATERIALS_CAP_ZIP_FIELD].asBinary();
 
 	LLSD response_data;
-	U32 uzip_result = LLUZipHelper::unzip_llsd(response_data, content_stream, content_binary.size());
+	U32 uzip_result = LLUZipHelper::unzip_llsd(response_data, content_binary.data(), content_binary.size());
 	if (uzip_result != LLUZipHelper::ZR_OK)
 	{
 		LL_WARNS("Materials") << "Cannot unzip LLSD binary content: " << uzip_result << LL_ENDL;
@@ -472,12 +470,10 @@ void LLMaterialMgr::onGetAllResponse(bool success, const LLSD& content, const LL
 	llassert(content.has(MATERIALS_CAP_ZIP_FIELD));
 	llassert(content[MATERIALS_CAP_ZIP_FIELD].isBinary());
 
-	LLSD::Binary content_binary = content[MATERIALS_CAP_ZIP_FIELD].asBinary();
-	std::string content_string(reinterpret_cast<const char*>(content_binary.data()), content_binary.size());
-	std::istringstream content_stream(content_string);
+	const LLSD::Binary& content_binary = content[MATERIALS_CAP_ZIP_FIELD].asBinary();
 
 	LLSD response_data;
-	U32 uzip_result = LLUZipHelper::unzip_llsd(response_data, content_stream, content_binary.size());
+	U32 uzip_result = LLUZipHelper::unzip_llsd(response_data, content_binary.data(), content_binary.size());
 	if (uzip_result != LLUZipHelper::ZR_OK)
 	{
 		LL_WARNS("Materials") << "Cannot unzip LLSD binary content: " << uzip_result << LL_ENDL;
@@ -541,12 +537,10 @@ void LLMaterialMgr::onPutResponse(bool success, const LLSD& content)
 	llassert(content.has(MATERIALS_CAP_ZIP_FIELD));
 	llassert(content[MATERIALS_CAP_ZIP_FIELD].isBinary());
 
-	LLSD::Binary content_binary = content[MATERIALS_CAP_ZIP_FIELD].asBinary();
-	std::string content_string(reinterpret_cast<const char*>(content_binary.data()), content_binary.size());
-	std::istringstream content_stream(content_string);
+	const LLSD::Binary& content_binary = content[MATERIALS_CAP_ZIP_FIELD].asBinary();
 
 	LLSD response_data;
-	U32 uzip_result = LLUZipHelper::unzip_llsd(response_data, content_stream, content_binary.size());
+	U32 uzip_result = LLUZipHelper::unzip_llsd(response_data, content_binary.data(), content_binary.size());
 	if (uzip_result != LLUZipHelper::ZR_OK)
 	{
 		LL_WARNS("Materials") << "Cannot unzip LLSD binary content: " << uzip_result << LL_ENDL;
@@ -666,8 +660,8 @@ void LLMaterialMgr::processGetQueue()
 		{
 			material_queue_t::iterator itMaterial = loopMaterial++;
 			materialsData.append((*itMaterial).asLLSD());
-			materials.erase(itMaterial);
 			markGetPending(region_id, *itMaterial);
+			materials.erase(itMaterial);
 		}
 		if (materials.empty())
 		{
diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp
index 9142aadab9ff71d78b42019927fb88b10d0d8c8e..36ac1bdf97db695e1526087dac1a9f36d9845dac 100644
--- a/indra/newview/llmediactrl.cpp
+++ b/indra/newview/llmediactrl.cpp
@@ -106,7 +106,6 @@ LLMediaCtrl::LLMediaCtrl( const Params& p) :
 	mTrusted(p.trusted_content),
 	mWindowShade(NULL),
 	mHoverTextChanged(false),
-	mContextMenu(NULL),
     mAllowFileDownload(false)
 {
 	{
@@ -151,6 +150,13 @@ LLMediaCtrl::LLMediaCtrl( const Params& p) :
 
 LLMediaCtrl::~LLMediaCtrl()
 {
+	auto menu = mContextMenuHandle.get();
+	if (menu)
+	{
+		menu->die();
+		mContextMenuHandle.markDead();
+	}
+
 	if (mMediaSource)
 	{
 		mMediaSource->remObserver( this );
@@ -336,15 +342,33 @@ BOOL LLMediaCtrl::handleRightMouseDown( S32 x, S32 y, MASK mask )
 		setFocus( TRUE );
 	}
 
-	if (mContextMenu)
+	auto menu = mContextMenuHandle.get();
+	if (!menu)
+	{
+		LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registar;
+		registar.add("Open.WebInspector", boost::bind(&LLMediaCtrl::onOpenWebInspector, this));
+
+		// stinson 05/05/2014 : use this as the parent of the context menu if the static menu
+		// container has yet to be created
+		LLPanel* menuParent = (LLMenuGL::sMenuContainer != NULL) ? dynamic_cast<LLPanel*>(LLMenuGL::sMenuContainer) : dynamic_cast<LLPanel*>(this);
+		llassert(menuParent != NULL);
+		menu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>(
+			"menu_media_ctrl.xml", menuParent, LLViewerMenuHolderGL::child_registry_t::instance());
+		if (menu)
+		{
+			mContextMenuHandle = menu->getHandle();
+		}
+	}
+
+	if (menu)
 	{
 		// hide/show debugging options
 		bool media_plugin_debugging_enabled = gSavedSettings.getBOOL("MediaPluginDebugging");
-		mContextMenu->setItemVisible("open_webinspector", media_plugin_debugging_enabled );
-		mContextMenu->setItemVisible("debug_separator", media_plugin_debugging_enabled );
+		menu->setItemVisible("open_webinspector", media_plugin_debugging_enabled );
+		menu->setItemVisible("debug_separator", media_plugin_debugging_enabled );
 
-		mContextMenu->show(x, y);
-		LLMenuGL::showPopup(this, mContextMenu, x, y);
+		menu->show(x, y);
+		LLMenuGL::showPopup(this, menu, x, y);
 	}
 
 	return TRUE;
@@ -409,15 +433,6 @@ void LLMediaCtrl::onFocusLost()
 //
 BOOL LLMediaCtrl::postBuild ()
 {
-	LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registar;
-	registar.add("Open.WebInspector", boost::bind(&LLMediaCtrl::onOpenWebInspector, this));
-
-	// stinson 05/05/2014 : use this as the parent of the context menu if the static menu
-	// container has yet to be created
-	LLPanel* menuParent = (LLMenuGL::sMenuContainer != NULL) ? dynamic_cast<LLPanel*>(LLMenuGL::sMenuContainer) : dynamic_cast<LLPanel*>(this);
-	llassert(menuParent != NULL);
-	mContextMenu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>(
-		"menu_media_ctrl.xml", menuParent, LLViewerMenuHolderGL::child_registry_t::instance());
 	setVisibleCallback(boost::bind(&LLMediaCtrl::onVisibilityChanged, this, _2));
 
 	return TRUE;
@@ -1230,11 +1245,6 @@ void LLMediaCtrl::setTrustedContent(bool trusted)
 	}
 }
 
-void LLMediaCtrl::updateContextMenuParent(LLView* pNewParent)
-{
-	mContextMenu->updateParent(pNewParent);
-}
-
 bool LLMediaCtrl::wantsKeyUpKeyDown() const
 {
     return true;
diff --git a/indra/newview/llmediactrl.h b/indra/newview/llmediactrl.h
index bc4cbaae6860307d05732f61a5a67a67fd6ebd5a..487c654adc41397ed93abf509752476b6086400e 100644
--- a/indra/newview/llmediactrl.h
+++ b/indra/newview/llmediactrl.h
@@ -174,8 +174,6 @@ class LLMediaCtrl :
 
 		LLUUID getTextureID() {return mMediaTextureID;}
 
-		void updateContextMenuParent(LLView* pNewParent);
-
         // The Browser windows want keyup and keydown events. Overridden from LLFocusableElement to return true.
         virtual bool    wantsKeyUpKeyDown() const;
         virtual bool    wantsReturnKey() const;
@@ -220,7 +218,7 @@ class LLMediaCtrl :
 			mTextureHeight;
 
 		class LLWindowShade* mWindowShade;
-		LLContextMenu* mContextMenu;
+		LLHandle<LLContextMenu> mContextMenuHandle;
 };
 
 #endif // LL_LLMediaCtrl_H
diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp
index a15a61429bf20a8fb17c1d71ed75e42a8aa3c32b..f9377543682bc8f96efb62d25b8b964ac4a58947 100644
--- a/indra/newview/llmeshrepository.cpp
+++ b/indra/newview/llmeshrepository.cpp
@@ -77,6 +77,8 @@
 #include "lluploaddialog.h"
 #include "llfloaterreg.h"
 
+#include "boost/iostreams/device/array.hpp"
+#include "boost/iostreams/stream.hpp"
 #include "boost/lexical_cast.hpp"
 
 #ifndef LL_WINDOWS
@@ -138,7 +140,7 @@
 //                               data copied
 //                               headerReceived() invoked
 //                                 LLSD parsed
-//                                 mMeshHeader, mMeshHeaderSize updated
+//                                 mMeshHeader updated
 //                                 scan mPendingLOD for LOD request
 //                                 push LODRequest to mLODReqQ
 //                             ...
@@ -246,7 +248,6 @@
 //     sActiveLODRequests       mMutex        rw.any.mMutex, ro.repo.none [1]
 //     sMaxConcurrentRequests   mMutex        wo.main.none, ro.repo.none, ro.main.mMutex
 //     mMeshHeader              mHeaderMutex  rw.repo.mHeaderMutex, ro.main.mHeaderMutex, ro.main.none [0]
-//     mMeshHeaderSize          mHeaderMutex  rw.repo.mHeaderMutex
 //     mSkinRequests            mMutex        rw.repo.mMutex, ro.repo.none [5]
 //     mSkinInfoQ               mMutex        rw.repo.mMutex, rw.main.mMutex [5] (was:  [0])
 //     mDecompositionRequests   mMutex        rw.repo.mMutex, ro.repo.none [5]
@@ -858,6 +859,12 @@ LLMeshRepoThread::~LLMeshRepoThread()
 	mHttpRequestSet.clear();
     mHttpHeaders.reset();
 
+	while (!mSkinInfoQ.empty())
+    {
+        delete mSkinInfoQ.front();
+        mSkinInfoQ.pop_front();
+    }
+
     while (!mDecompositionQ.empty())
     {
         delete mDecompositionQ.front();
@@ -947,7 +954,8 @@ void LLMeshRepoThread::run()
                     else
                     {
                         // too many fails
-                        mUnavailableQ.push(req);
+						LLMutexLock lock(mMutex);
+                        mUnavailableQ.push_back(req);
                         LL_WARNS() << "Failed to load " << req.mMeshParams << " , skip" << LL_ENDL;
                     }
                 }
@@ -1023,37 +1031,42 @@ void LLMeshRepoThread::run()
 
             if (!mSkinRequests.empty())
             {
-                std::set<UUIDBasedRequest> incomplete;
-                while (!mSkinRequests.empty() && mHttpRequestSet.size() < sRequestHighWater)
-                {
-                    mMutex->lock();
-                    std::set<UUIDBasedRequest>::iterator iter = mSkinRequests.begin();
-                    UUIDBasedRequest req = *iter;
-                    mSkinRequests.erase(iter);
-                    mMutex->unlock();
-                    if (req.isDelayed())
-                    {
-                        incomplete.insert(req);
-                    }
-                    else if (!fetchMeshSkinInfo(req.mId))
-                    {
-                        if (req.canRetry())
-                        {
-                            req.updateTime();
-                            incomplete.insert(req);
-                        }
-                        else
-                        {
-                            LL_DEBUGS() << "mSkinRequests failed: " << req.mId << LL_ENDL;
-                        }
-                    }
-                }
+				std::list<UUIDBasedRequest> incomplete;
+				while (!mSkinRequests.empty() && mHttpRequestSet.size() < sRequestHighWater)
+				{
 
-                if (!incomplete.empty())
-                {
-                    LLMutexLock locker(mMutex);
-                    mSkinRequests.insert(incomplete.begin(), incomplete.end());
-                }
+					mMutex->lock();
+					auto req = mSkinRequests.front();
+					mSkinRequests.pop_front();
+					mMutex->unlock();
+					if (req.isDelayed())
+					{
+						incomplete.emplace_back(req);
+					}
+					else if (!fetchMeshSkinInfo(req.mId, req.canRetry()))
+					{
+						if (req.canRetry())
+						{
+							req.updateTime();
+							incomplete.emplace_back(req);
+						}
+						else
+						{
+							LLMutexLock locker(mMutex);
+							mSkinUnavailableQ.push_back(req);
+							LL_DEBUGS() << "mSkinReqQ failed: " << req.mId << LL_ENDL;
+						}
+					}
+				}
+
+				if (!incomplete.empty())
+				{
+					LLMutexLock locker(mMutex);
+					for (const auto& req : incomplete)
+					{
+						mSkinRequests.push_back(req);
+					}
+				}
             }
 
             // holding lock, try next list
@@ -1152,7 +1165,7 @@ void LLMeshRepoThread::run()
 // Mutex:  LLMeshRepoThread::mMutex must be held on entry
 void LLMeshRepoThread::loadMeshSkinInfo(const LLUUID& mesh_id)
 {
-	mSkinRequests.insert(UUIDBasedRequest(mesh_id));
+	mSkinRequests.push_back(UUIDBasedRequest(mesh_id));
 }
 
 // Mutex:  LLMeshRepoThread::mMutex must be held on entry
@@ -1178,10 +1191,13 @@ void LLMeshRepoThread::lockAndLoadMeshLOD(const LLVolumeParams& mesh_params, S32
 
 void LLMeshRepoThread::loadMeshLOD(const LLVolumeParams& mesh_params, S32 lod)
 { //could be called from any thread
+	const LLUUID& mesh_id = mesh_params.getSculptID();
 	LLMutexLock lock(mMutex);
-	mesh_header_map::iterator iter = mMeshHeader.find(mesh_params.getSculptID());
+	LLMutexLock header_lock(mHeaderMutex);
+	mesh_header_map::iterator iter = mMeshHeader.find(mesh_id);
 	if (iter != mMeshHeader.end())
 	{ //if we have the header, request LOD byte range
+
 		LODRequest req(mesh_params, lod);
 		{
 			mLODReqQ.push(req);
@@ -1191,8 +1207,7 @@ void LLMeshRepoThread::loadMeshLOD(const LLVolumeParams& mesh_params, S32 lod)
 	else
 	{ 
 		HeaderRequest req(mesh_params);
-		
-		pending_lod_map::iterator pending = mPendingLOD.find(mesh_params);
+		pending_lod_map::iterator pending = mPendingLOD.find(mesh_id);
 
 		if (pending != mPendingLOD.end())
 		{ //append this lod request to existing header request
@@ -1202,7 +1217,7 @@ void LLMeshRepoThread::loadMeshLOD(const LLVolumeParams& mesh_params, S32 lod)
 		else
 		{ //if no header request is pending, fetch header
 			mHeaderReqQ.push(req);
-			mPendingLOD[mesh_params].push_back(lod);
+			mPendingLOD[mesh_id].push_back(lod);
 		}
 	}
 }
@@ -1307,7 +1322,7 @@ LLCore::HttpHandle LLMeshRepoThread::getByteRange(const std::string & url,
 }
 
 
-bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id)
+bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id, bool can_retry)
 {
 	
 	if (!mHeaderMutex)
@@ -1317,7 +1332,8 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id)
 
 	mHeaderMutex->lock();
 
-	if (mMeshHeader.find(mesh_id) == mMeshHeader.end())
+	auto header_it = mMeshHeader.find(mesh_id);
+	if (header_it == mMeshHeader.end())
 	{ //we have no header info for this mesh, do nothing
 		mHeaderMutex->unlock();
 		return false;
@@ -1325,13 +1341,14 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id)
 
 	++LLMeshRepository::sMeshRequestCount;
 	bool ret = true;
-	U32 header_size = mMeshHeaderSize[mesh_id];
+	U32 header_size = header_it->second.first;
 	
 	if (header_size > 0)
 	{
-		S32 version = mMeshHeader[mesh_id]["version"].asInteger();
-		S32 offset = header_size + mMeshHeader[mesh_id]["skin"]["offset"].asInteger();
-		S32 size = mMeshHeader[mesh_id]["skin"]["size"].asInteger();
+		const LLSD& header = header_it->second.second;
+		S32 version = header["version"].asInteger();
+		S32 offset = header_size + header["skin"]["offset"].asInteger();
+		S32 size = header["skin"]["size"].asInteger();
 
 		mHeaderMutex->unlock();
 
@@ -1387,12 +1404,27 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id)
 									   << LL_ENDL;
 					ret = false;
 				}
-				else
+				else if(can_retry)
 				{
 					handler->mHttpHandle = handle;
 					mHttpRequestSet.insert(handler);
 				}
+				else
+				{
+					LLMutexLock locker(mMutex);
+					mSkinUnavailableQ.emplace_back(mesh_id);
+				}
 			}
+			else
+			{
+				LLMutexLock locker(mMutex);
+				mSkinUnavailableQ.emplace_back(mesh_id);
+			}
+		}
+		else
+		{
+			LLMutexLock locker(mMutex);
+			mSkinUnavailableQ.emplace_back(mesh_id);
 		}
 	}
 	else
@@ -1413,21 +1445,23 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id)
 
 	mHeaderMutex->lock();
 
-	if (mMeshHeader.find(mesh_id) == mMeshHeader.end())
+	auto header_it = mMeshHeader.find(mesh_id);
+	if (header_it == mMeshHeader.end())
 	{ //we have no header info for this mesh, do nothing
 		mHeaderMutex->unlock();
 		return false;
 	}
 
 	++LLMeshRepository::sMeshRequestCount;
-	U32 header_size = mMeshHeaderSize[mesh_id];
+	U32 header_size = header_it->second.first;
 	bool ret = true;
 	
 	if (header_size > 0)
 	{
-		S32 version = mMeshHeader[mesh_id]["version"].asInteger();
-		S32 offset = header_size + mMeshHeader[mesh_id]["physics_convex"]["offset"].asInteger();
-		S32 size = mMeshHeader[mesh_id]["physics_convex"]["size"].asInteger();
+		const auto& header = header_it->second.second;
+		S32 version = header["version"].asInteger();
+		S32 offset = header_size + header["physics_convex"]["offset"].asInteger();
+		S32 size = header["physics_convex"]["size"].asInteger();
 
 		mHeaderMutex->unlock();
 
@@ -1510,21 +1544,23 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id)
 
 	mHeaderMutex->lock();
 
-	if (mMeshHeader.find(mesh_id) == mMeshHeader.end())
+	auto header_it = mMeshHeader.find(mesh_id);
+	if (header_it == mMeshHeader.end())
 	{ //we have no header info for this mesh, do nothing
 		mHeaderMutex->unlock();
 		return false;
 	}
 
 	++LLMeshRepository::sMeshRequestCount;
-	U32 header_size = mMeshHeaderSize[mesh_id];
+	U32 header_size = header_it->second.first;
 	bool ret = true;
 
 	if (header_size > 0)
 	{
-		S32 version = mMeshHeader[mesh_id]["version"].asInteger();
-		S32 offset = header_size + mMeshHeader[mesh_id]["physics_mesh"]["offset"].asInteger();
-		S32 size = mMeshHeader[mesh_id]["physics_mesh"]["size"].asInteger();
+		const auto& header = header_it->second.second;
+		S32 version = header["version"].asInteger();
+		S32 offset = header_size + header["physics_mesh"]["offset"].asInteger();
+		S32 size = header["physics_mesh"]["size"].asInteger();
 
 		mHeaderMutex->unlock();
 
@@ -1704,20 +1740,25 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod,
 		return false;
 	}
 
-	mHeaderMutex->lock();
+	const LLUUID& mesh_id = mesh_params.getSculptID();
 
+	mHeaderMutex->lock();
+	auto header_it = mMeshHeader.find(mesh_id);
+	if (header_it == mMeshHeader.end())
+	{ //we have no header info for this mesh, do nothing
+		mHeaderMutex->unlock();
+		return false;
+	}
 	++LLMeshRepository::sMeshRequestCount;
 	bool retval = true;
-
-	LLUUID mesh_id = mesh_params.getSculptID();
 	
-	U32 header_size = mMeshHeaderSize[mesh_id];
-
+	U32 header_size = header_it->second.first;
 	if (header_size > 0)
 	{
-		S32 version = mMeshHeader[mesh_id]["version"].asInteger();
-		S32 offset = header_size + mMeshHeader[mesh_id][header_lod[lod]]["offset"].asInteger();
-		S32 size = mMeshHeader[mesh_id][header_lod[lod]]["size"].asInteger();
+		const auto& header = header_it->second.second;
+		S32 version = header["version"].asInteger();
+		S32 offset = header_size + header[header_lod[lod]]["offset"].asInteger();
+		S32 size = header[header_lod[lod]]["size"].asInteger();
 		mHeaderMutex->unlock();
 				
 		if (version <= MAX_MESH_VERSION && offset >= 0 && size > 0)
@@ -1792,17 +1833,20 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod,
 				}
 				else
 				{
-					mUnavailableQ.push(LODRequest(mesh_params, lod));
+					LLMutexLock lock(mMutex);
+					mUnavailableQ.push_back(LODRequest(mesh_params, lod));
 				}
 			}
 			else
 			{
-				mUnavailableQ.push(LODRequest(mesh_params, lod));
+				LLMutexLock lock(mMutex);
+				mUnavailableQ.push_back(LODRequest(mesh_params, lod));
 			}
 		}
 		else
 		{
-			mUnavailableQ.push(LODRequest(mesh_params, lod));
+			LLMutexLock lock(mMutex);
+			mUnavailableQ.push_back(LODRequest(mesh_params, lod));
 		}
 	}
 	else
@@ -1821,27 +1865,12 @@ EMeshProcessingResult LLMeshRepoThread::headerReceived(const LLVolumeParams& mes
 	U32 header_size = 0;
 	if (data_size > 0)
 	{
-        std::istringstream stream;
-        try
-        {
-            std::string res_str((char*)data, data_size);
+		U32 dsize = data_size;
+		char* result_ptr = strip_deprecated_header((char*)data, dsize, &header_size);
 
-            std::string deprecated_header("<? LLSD/Binary ?>");
+		data_size = dsize;
 
-            if (res_str.substr(0, deprecated_header.size()) == deprecated_header)
-            {
-                res_str = res_str.substr(deprecated_header.size() + 1, data_size);
-                header_size = deprecated_header.size() + 1;
-            }
-            data_size = res_str.size();
-
-            stream.str(res_str);
-        }
-        catch (std::bad_alloc&)
-        {
-            // out of memory, we won't be able to process this mesh
-            return MESH_OUT_OF_MEMORY;
-        }
+		boost::iostreams::stream<boost::iostreams::array_source> stream(result_ptr, data_size);
 
 		if (!LLSDSerialize::fromBinary(header, stream, data_size))
 		{
@@ -1878,8 +1907,7 @@ EMeshProcessingResult LLMeshRepoThread::headerReceived(const LLVolumeParams& mes
 		
 		{
 			LLMutexLock lock(mHeaderMutex);
-			mMeshHeaderSize[mesh_id] = header_size;
-			mMeshHeader[mesh_id] = header;
+			mMeshHeader[mesh_id] = { header_size, header };
             LLMeshRepository::sCacheBytesHeaders += header_size;
 		}
 
@@ -1887,7 +1915,7 @@ EMeshProcessingResult LLMeshRepoThread::headerReceived(const LLVolumeParams& mes
 		LLMutexLock lock(mMutex); // make sure only one thread access mPendingLOD at the same time.
 
 		//check for pending requests
-		pending_lod_map::iterator iter = mPendingLOD.find(mesh_params);
+		pending_lod_map::iterator iter = mPendingLOD.find(mesh_id);
 		if (iter != mPendingLOD.end())
 		{
 			for (U32 i = 0; i < iter->second.size(); ++i)
@@ -1911,26 +1939,14 @@ EMeshProcessingResult LLMeshRepoThread::lodReceived(const LLVolumeParams& mesh_p
 	}
 
 	LLPointer<LLVolume> volume = new LLVolume(mesh_params, LLVolumeLODGroup::getVolumeScaleFromDetail(lod));
-	std::istringstream stream;
-	try
-	{
-		std::string mesh_string((char*)data, data_size);
-		stream.str(mesh_string);
-	}
-	catch (std::bad_alloc&)
-	{
-		// out of memory, we won't be able to process this mesh
-		return MESH_OUT_OF_MEMORY;
-	}
-
-	if (volume->unpackVolumeFaces(stream, data_size))
+	if (volume->unpackVolumeFaces(data, data_size))
 	{
 		if (volume->getNumFaces() > 0)
 		{
 			LoadedMesh mesh(volume, mesh_params, lod);
 			{
 				LLMutexLock lock(mMutex);
-				mLoadedQ.push(mesh);
+				mLoadedQ.push_back(mesh);
 				// LLPointer is not thread safe, since we added this pointer into
 				// threaded list, make sure counter gets decreased inside mutex lock
 				// and won't affect mLoadedQ processing
@@ -1953,10 +1969,7 @@ bool LLMeshRepoThread::skinInfoReceived(const LLUUID& mesh_id, U8* data, S32 dat
 	{
         try
         {
-            std::string res_str((char*)data, data_size);
-            std::istringstream stream(res_str);
-
-            U32 uzip_result = LLUZipHelper::unzip_llsd(skin, stream, data_size);
+            U32 uzip_result = LLUZipHelper::unzip_llsd(skin, data, data_size);
             if (uzip_result != LLUZipHelper::ZR_OK)
             {
                 LL_WARNS(LOG_MESH) << "Mesh skin info parse error.  Not a valid mesh asset!  ID:  " << mesh_id
@@ -1973,8 +1986,16 @@ bool LLMeshRepoThread::skinInfoReceived(const LLUUID& mesh_id, U8* data, S32 dat
 	}
 	
 	{
-		LLMeshSkinInfo info(skin);
-		info.mMeshID = mesh_id;
+		LLMeshSkinInfo* info = nullptr;
+		try
+		{
+			info = new LLMeshSkinInfo(mesh_id, skin);
+		}
+		catch (const std::bad_alloc& ex)
+		{
+			LL_WARNS() << "Failed to allocate skin info with exception: " << ex.what()  << LL_ENDL;
+			return false;
+		}
 
         // LL_DEBUGS(LOG_MESH) << "info pelvis offset" << info.mPelvisOffset << LL_ENDL;
 		{
@@ -1994,10 +2015,7 @@ bool LLMeshRepoThread::decompositionReceived(const LLUUID& mesh_id, U8* data, S3
     {
         try
         {
-            std::string res_str((char*)data, data_size);
-            std::istringstream stream(res_str);
-
-            U32 uzip_result = LLUZipHelper::unzip_llsd(decomp, stream, data_size);
+            U32 uzip_result = LLUZipHelper::unzip_llsd(decomp, data, data_size);
             if (uzip_result != LLUZipHelper::ZR_OK)
             {
                 LL_WARNS(LOG_MESH) << "Mesh decomposition parse error.  Not a valid mesh asset!  ID:  " << mesh_id
@@ -2006,7 +2024,7 @@ bool LLMeshRepoThread::decompositionReceived(const LLUUID& mesh_id, U8* data, S3
                 return false;
             }
         }
-        catch (std::bad_alloc&)
+        catch (const std::bad_alloc&)
         {
             LL_WARNS(LOG_MESH) << "Out of memory for mesh ID " << mesh_id << " of size: " << data_size << LL_ENDL;
             return false;
@@ -2043,20 +2061,7 @@ EMeshProcessingResult LLMeshRepoThread::physicsShapeReceived(const LLUUID& mesh_
 		volume_params.setSculptID(mesh_id, LL_SCULPT_TYPE_MESH);
 		LLPointer<LLVolume> volume = new LLVolume(volume_params,0);
 
-        std::istringstream stream;
-        try
-        {
-            std::string mesh_string((char*)data, data_size);
-            stream.str(mesh_string);
-        }
-        catch (std::bad_alloc&)
-        {
-            // out of memory, we won't be able to process this mesh
-            delete d;
-            return MESH_OUT_OF_MEMORY;
-        }
-
-		if (volume->unpackVolumeFaces(stream, data_size))
+		if (volume->unpackVolumeFaces(data, data_size))
 		{
 			d->mPhysicsShapeMesh.clear();
 
@@ -2870,58 +2875,72 @@ void LLMeshRepoThread::notifyLoadedMeshes()
 		return;
 	}
 
-	while (!mLoadedQ.empty())
+	if (!mLoadedQ.empty())
 	{
+		std::deque<LoadedMesh> loaded_queue;
+
 		mMutex->lock();
-		if (mLoadedQ.empty())
+		if (!mLoadedQ.empty())
 		{
+			loaded_queue.swap(mLoadedQ);
 			mMutex->unlock();
-			break;
-		}
-		LoadedMesh mesh = mLoadedQ.front(); // make sure nothing else owns volume pointer by this point
-		mLoadedQ.pop();
-		mMutex->unlock();
-		
-		update_metrics = true;
-		if (mesh.mVolume->getNumVolumeFaces() > 0)
-		{
-			gMeshRepo.notifyMeshLoaded(mesh.mMeshParams, mesh.mVolume);
-		}
-		else
-		{
-			gMeshRepo.notifyMeshUnavailable(mesh.mMeshParams, 
-				LLVolumeLODGroup::getVolumeDetailFromScale(mesh.mVolume->getDetail()));
+
+			update_metrics = true;
+
+			// Process the elements free of the lock
+			for (const auto& mesh : loaded_queue)
+			{
+				if (mesh.mVolume->getNumVolumeFaces() > 0)
+				{
+					gMeshRepo.notifyMeshLoaded(mesh.mMeshParams, mesh.mVolume);
+				}
+				else
+				{
+					gMeshRepo.notifyMeshUnavailable(mesh.mMeshParams,
+						LLVolumeLODGroup::getVolumeDetailFromScale(mesh.mVolume->getDetail()));
+				}
+			}
 		}
 	}
 
-	while (!mUnavailableQ.empty())
+	if (!mUnavailableQ.empty())
 	{
+		std::deque<LODRequest> unavil_queue;
+
 		mMutex->lock();
-		if (mUnavailableQ.empty())
+		if (!mUnavailableQ.empty())
 		{
+			unavil_queue.swap(mUnavailableQ);
 			mMutex->unlock();
-			break;
-		}
-		
-		LODRequest req = mUnavailableQ.front();
-		mUnavailableQ.pop();
-		mMutex->unlock();
 
-		update_metrics = true;
-		gMeshRepo.notifyMeshUnavailable(req.mMeshParams, req.mLOD);
+			update_metrics = true;
+
+			// Process the elements free of the lock
+			for (const auto& req : unavil_queue)
+			{
+				gMeshRepo.notifyMeshUnavailable(req.mMeshParams, req.mLOD);
+			}
+		}
 	}
 
-	if (! mSkinInfoQ.empty() || ! mDecompositionQ.empty())
+	if (!mSkinInfoQ.empty() || !mSkinUnavailableQ.empty() || ! mDecompositionQ.empty())
 	{
 		if (mMutex->trylock())
 		{
-			std::list<LLMeshSkinInfo> skin_info_q;
+			std::deque<LLMeshSkinInfo*> skin_info_q;
+			std::deque<UUIDBasedRequest> skin_info_unavail_q;
 			std::list<LLModel::Decomposition*> decomp_q;
 
 			if (! mSkinInfoQ.empty())
 			{
 				skin_info_q.swap(mSkinInfoQ);
 			}
+
+			if (! mSkinUnavailableQ.empty())
+			{
+				skin_info_unavail_q.swap(mSkinUnavailableQ);
+			}
+
 			if (! mDecompositionQ.empty())
 			{
 				decomp_q.swap(mDecompositionQ);
@@ -2935,6 +2954,11 @@ void LLMeshRepoThread::notifyLoadedMeshes()
 				gMeshRepo.notifySkinInfoReceived(skin_info_q.front());
 				skin_info_q.pop_front();
 			}
+			while (! skin_info_unavail_q.empty())
+			{
+				gMeshRepo.notifySkinInfoUnavailable(skin_info_unavail_q.front().mId);
+				skin_info_unavail_q.pop_front();
+			}
 
 			while (! decomp_q.empty())
 			{
@@ -2959,7 +2983,7 @@ S32 LLMeshRepoThread::getActualMeshLOD(const LLVolumeParams& mesh_params, S32 lo
 
 	if (iter != mMeshHeader.end())
 	{
-		LLSD& header = iter->second;
+		LLSD& header = iter->second.second;
 
 		return LLMeshRepository::getActualMeshLOD(header, lod);
 	}
@@ -3162,7 +3186,7 @@ void LLMeshHeaderHandler::processFailure(LLCore::HttpStatus status)
 	LLMutexLock lock(gMeshRepo.mThread->mMutex);
 	for (int i(0); i < 4; ++i)
 	{
-		gMeshRepo.mThread->mUnavailableQ.push(LLMeshRepoThread::LODRequest(mMeshParams, i));
+		gMeshRepo.mThread->mUnavailableQ.push_back(LLMeshRepoThread::LODRequest(mMeshParams, i));
 	}
 }
 
@@ -3191,7 +3215,7 @@ void LLMeshHeaderHandler::processData(LLCore::BufferArray * /* body */, S32 /* b
 		LLMutexLock lock(gMeshRepo.mThread->mMutex);
 		for (int i(0); i < 4; ++i)
 		{
-			gMeshRepo.mThread->mUnavailableQ.push(LLMeshRepoThread::LODRequest(mMeshParams, i));
+			gMeshRepo.mThread->mUnavailableQ.push_back(LLMeshRepoThread::LODRequest(mMeshParams, i));
 		}
 	}
 	else if (data && data_size > 0)
@@ -3204,8 +3228,8 @@ void LLMeshHeaderHandler::processData(LLCore::BufferArray * /* body */, S32 /* b
 		LLMeshRepoThread::mesh_header_map::iterator iter = gMeshRepo.mThread->mMeshHeader.find(mesh_id);
 		if (iter != gMeshRepo.mThread->mMeshHeader.end())
 		{
-			header_bytes = (S32)gMeshRepo.mThread->mMeshHeaderSize[mesh_id];
-			header = iter->second;
+			header_bytes = (S32)iter->second.first;
+			header = iter->second.second;
 		}
 
 		if (header_bytes > 0
@@ -3273,7 +3297,7 @@ void LLMeshHeaderHandler::processData(LLCore::BufferArray * /* body */, S32 /* b
 			LLMutexLock lock(gMeshRepo.mThread->mMutex);
 			for (int i(0); i < 4; ++i)
 			{
-				gMeshRepo.mThread->mUnavailableQ.push(LLMeshRepoThread::LODRequest(mMeshParams, i));
+				gMeshRepo.mThread->mUnavailableQ.push_back(LLMeshRepoThread::LODRequest(mMeshParams, i));
 			}
 		}
 	}
@@ -3300,7 +3324,7 @@ void LLMeshLODHandler::processFailure(LLCore::HttpStatus status)
 					   << LL_ENDL;
 
 	LLMutexLock lock(gMeshRepo.mThread->mMutex);
-	gMeshRepo.mThread->mUnavailableQ.push(LLMeshRepoThread::LODRequest(mMeshParams, mLOD));
+	gMeshRepo.mThread->mUnavailableQ.push_back(LLMeshRepoThread::LODRequest(mMeshParams, mLOD));
 }
 
 void LLMeshLODHandler::processData(LLCore::BufferArray * /* body */, S32 /* body_offset */,
@@ -3337,7 +3361,7 @@ void LLMeshLODHandler::processData(LLCore::BufferArray * /* body */, S32 /* body
 							   << " Not retrying."
 							   << LL_ENDL;
 			LLMutexLock lock(gMeshRepo.mThread->mMutex);
-			gMeshRepo.mThread->mUnavailableQ.push(LLMeshRepoThread::LODRequest(mMeshParams, mLOD));
+			gMeshRepo.mThread->mUnavailableQ.push_back(LLMeshRepoThread::LODRequest(mMeshParams, mLOD));
 		}
 	}
 	else
@@ -3348,7 +3372,7 @@ void LLMeshLODHandler::processData(LLCore::BufferArray * /* body */, S32 /* body
 						   << " Data size: " << data_size
 						   << LL_ENDL;
 		LLMutexLock lock(gMeshRepo.mThread->mMutex);
-		gMeshRepo.mThread->mUnavailableQ.push(LLMeshRepoThread::LODRequest(mMeshParams, mLOD));
+		gMeshRepo.mThread->mUnavailableQ.push_back(LLMeshRepoThread::LODRequest(mMeshParams, mLOD));
 	}
 }
 
@@ -3366,9 +3390,8 @@ void LLMeshSkinInfoHandler::processFailure(LLCore::HttpStatus status)
 					   << ", Reason:  " << status.toString()
 					   << " (" << status.toTerseString() << ").  Not retrying."
 					   << LL_ENDL;
-
-	// *TODO:  Mark mesh unavailable on error.  For now, simply leave
-	// request unfulfilled rather than retry forever.
+		LLMutexLock lock(gMeshRepo.mThread->mMutex);
+		gMeshRepo.mThread->mSkinUnavailableQ.emplace_back(mMeshID);
 }
 
 void LLMeshSkinInfoHandler::processData(LLCore::BufferArray * /* body */, S32 /* body_offset */,
@@ -3399,7 +3422,8 @@ void LLMeshSkinInfoHandler::processData(LLCore::BufferArray * /* body */, S32 /*
 		LL_WARNS(LOG_MESH) << "Error during mesh skin info processing.  ID:  " << mMeshID
 						   << ", Unknown reason.  Not retrying."
 						   << LL_ENDL;
-		// *TODO:  Mark mesh unavailable on error
+		LLMutexLock lock(gMeshRepo.mThread->mMutex);
+		gMeshRepo.mThread->mSkinUnavailableQ.emplace_back(mMeshID);
 	}
 }
 
@@ -3508,7 +3532,7 @@ LLMeshRepository::LLMeshRepository()
   mMeshThreadCount(0),
   mThread(NULL)
 {
-
+	mSkinInfoCullTimer.resetWithExpiry(10.f);
 }
 
 void LLMeshRepository::init()
@@ -3609,6 +3633,22 @@ S32 LLMeshRepository::update()
 	return size ;
 }
 
+void LLMeshRepository::unregisterMesh(LLVOVolume* vobj)
+{
+	for (auto& lod : mLoadingMeshes)
+	{
+		for (auto& param : lod)
+		{
+			vector_replace_with_last(param.second, vobj);
+		}
+	}
+
+	for (auto& skin_pair : mLoadingSkins)
+	{
+		vector_replace_with_last(skin_pair.second, vobj);
+	}
+}
+
 S32 LLMeshRepository::loadMesh(LLVOVolume* vobj, const LLVolumeParams& mesh_params, S32 detail, S32 last_lod)
 {
     LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; //LL_LL_RECORD_BLOCK_TIME(FTM_MESH_FETCH);
@@ -3624,15 +3664,19 @@ S32 LLMeshRepository::loadMesh(LLVOVolume* vobj, const LLVolumeParams& mesh_para
 	{
 		LLMutexLock lock(mMeshMutex);
 		//add volume to list of loading meshes
-		mesh_load_map::iterator iter = mLoadingMeshes[detail].find(mesh_params);
+		const auto& mesh_id = mesh_params.getSculptID();
+		mesh_load_map::iterator iter = mLoadingMeshes[detail].find(mesh_id);
 		if (iter != mLoadingMeshes[detail].end())
 		{ //request pending for this mesh, append volume id to list
-			iter->second.insert(vobj->getID());
+			auto it = std::find(iter->second.begin(), iter->second.end(), vobj);
+			if (it == iter->second.end()) {
+				iter->second.push_back(vobj);
+			}
 		}
 		else
 		{
 			//first request for this mesh
-			mLoadingMeshes[detail][mesh_params].insert(vobj->getID());
+			mLoadingMeshes[detail][mesh_id].push_back(vobj);
 			mPendingRequests.push_back(LLMeshRepoThread::LODRequest(mesh_params, detail));
 			LLMeshRepository::sLODPending++;
 		}
@@ -3789,6 +3833,28 @@ void LLMeshRepository::notifyLoadedMeshes()
 	//call completed callbacks on finished decompositions
 	mDecompThread->notifyCompleted();
 
+	if (mSkinInfoCullTimer.checkExpirationAndReset(10.f)) 
+	{
+		//// Clean up dead skin info
+		//U64Bytes skinbytes(0);
+		for (auto iter = mSkinMap.begin(), ender = mSkinMap.end(); iter != ender;)
+		{
+			auto copy_iter = iter++;
+
+			//skinbytes += U64Bytes(sizeof(LLMeshSkinInfo));
+			//skinbytes += U64Bytes(copy_iter->second->mJointNames.size() * sizeof(std::string));
+			//skinbytes += U64Bytes(copy_iter->second->mJointNums.size() * sizeof(S32));
+			//skinbytes += U64Bytes(copy_iter->second->mJointNames.size() * sizeof(LLMatrix4a));
+			//skinbytes += U64Bytes(copy_iter->second->mJointNames.size() * sizeof(LLMatrix4));
+
+			if (copy_iter->second->getNumRefs() == 1)
+			{
+				mSkinMap.erase(copy_iter);
+			}
+		}
+		//LL_INFOS() << "Skin info cache elements:" << mSkinMap.size() << " Memory: " << U64Kilobytes(skinbytes) << LL_ENDL;
+	}
+
 	// For major operations, attempt to get the required locks
 	// without blocking and punt if they're not available.  The
 	// longest run of holdoffs is kept in sMaxLockHoldoffs just
@@ -3859,10 +3925,9 @@ void LLMeshRepository::notifyLoadedMeshes()
 					for (mesh_load_map::iterator iter = mLoadingMeshes[i].begin();  iter != mLoadingMeshes[i].end(); ++iter)
 					{
 						F32 max_score = 0.f;
-						for (std::set<LLUUID>::iterator obj_iter = iter->second.begin(); obj_iter != iter->second.end(); ++obj_iter)
+						for (auto obj_iter = iter->second.begin(); obj_iter != iter->second.end(); ++obj_iter)
 						{
-							LLViewerObject* object = gObjectList.findObject(*obj_iter);
-							
+							LLVOVolume* object = *obj_iter;						
 							if (object)
 							{
 								LLDrawable* drawable = object->mDrawable;
@@ -3874,7 +3939,7 @@ void LLMeshRepository::notifyLoadedMeshes()
 							}
 						}
 				
-						score_map[iter->first.getSculptID()] = max_score;
+						score_map[iter->first] = max_score;
 					}
 				}
 
@@ -3926,24 +3991,39 @@ void LLMeshRepository::notifyLoadedMeshes()
 	mThread->mSignal->signal();
 }
 
-void LLMeshRepository::notifySkinInfoReceived(LLMeshSkinInfo& info)
+void LLMeshRepository::notifySkinInfoReceived(LLMeshSkinInfo* info)
 {
-	mSkinMap[info.mMeshID] = info;
+	mSkinMap[info->mMeshID] = info; // Cache into LLPointer
     // Alternative: We can get skin size from header
-    sCacheBytesSkins += info.sizeBytes();
+    sCacheBytesSkins += info->sizeBytes();
 
-	skin_load_map::iterator iter = mLoadingSkins.find(info.mMeshID);
+	skin_load_map::iterator iter = mLoadingSkins.find(info->mMeshID);
 	if (iter != mLoadingSkins.end())
 	{
-		for (std::set<LLUUID>::iterator obj_id = iter->second.begin(); obj_id != iter->second.end(); ++obj_id)
+		for (LLVOVolume* vobj : iter->second)
 		{
-			LLVOVolume* vobj = (LLVOVolume*) gObjectList.findObject(*obj_id);
 			if (vobj)
 			{
-				vobj->notifyMeshLoaded();
+				vobj->notifySkinInfoLoaded(info);
 			}
 		}
-		mLoadingSkins.erase(info.mMeshID);
+		mLoadingSkins.erase(iter);
+	}
+}
+
+void LLMeshRepository::notifySkinInfoUnavailable(const LLUUID& mesh_id)
+{
+	skin_load_map::iterator iter = mLoadingSkins.find(mesh_id);
+	if (iter != mLoadingSkins.end())
+	{
+		for (LLVOVolume* vobj : iter->second)
+		{
+			if (vobj)
+			{
+				vobj->notifySkinInfoUnavailable();
+			}
+		}
+		mLoadingSkins.erase(iter);
 	}
 }
 
@@ -3972,14 +4052,15 @@ void LLMeshRepository::notifyMeshLoaded(const LLVolumeParams& mesh_params, LLVol
 	S32 detail = LLVolumeLODGroup::getVolumeDetailFromScale(volume->getDetail());
 
 	//get list of objects waiting to be notified this mesh is loaded
-	mesh_load_map::iterator obj_iter = mLoadingMeshes[detail].find(mesh_params);
+	const auto& mesh_id = mesh_params.getSculptID();
+	mesh_load_map::iterator obj_iter = mLoadingMeshes[detail].find(mesh_id);
 
 	if (volume && obj_iter != mLoadingMeshes[detail].end())
 	{
 		//make sure target volume is still valid
 		if (volume->getNumVolumeFaces() <= 0)
 		{
-			LL_WARNS(LOG_MESH) << "Mesh loading returned empty volume.  ID:  " << mesh_params.getSculptID()
+			LL_WARNS(LOG_MESH) << "Mesh loading returned empty volume.  ID:  " << mesh_id
 							   << LL_ENDL;
 		}
 		
@@ -3993,37 +4074,35 @@ void LLMeshRepository::notifyMeshLoaded(const LLVolumeParams& mesh_params, LLVol
 			}
 			else
 			{
-				LL_WARNS(LOG_MESH) << "Couldn't find system volume for mesh " << mesh_params.getSculptID()
+				LL_WARNS(LOG_MESH) << "Couldn't find system volume for mesh " << mesh_id
 								   << LL_ENDL;
 			}
 		}
 
 		//notify waiting LLVOVolume instances that their requested mesh is available
-		for (std::set<LLUUID>::iterator vobj_iter = obj_iter->second.begin(); vobj_iter != obj_iter->second.end(); ++vobj_iter)
+		for (LLVOVolume* vobj : obj_iter->second)
 		{
-			LLVOVolume* vobj = (LLVOVolume*) gObjectList.findObject(*vobj_iter);
 			if (vobj)
 			{
 				vobj->notifyMeshLoaded();
 			}
 		}
 		
-		mLoadingMeshes[detail].erase(mesh_params);
+		mLoadingMeshes[detail].erase(obj_iter);
 	}
 }
 
 void LLMeshRepository::notifyMeshUnavailable(const LLVolumeParams& mesh_params, S32 lod)
 { //called from main thread
 	//get list of objects waiting to be notified this mesh is loaded
-	mesh_load_map::iterator obj_iter = mLoadingMeshes[lod].find(mesh_params);
-
-	F32 detail = LLVolumeLODGroup::getVolumeScaleFromDetail(lod);
-
+	const auto& mesh_id = mesh_params.getSculptID();
+	mesh_load_map::iterator obj_iter = mLoadingMeshes[lod].find(mesh_id);
 	if (obj_iter != mLoadingMeshes[lod].end())
 	{
-		for (std::set<LLUUID>::iterator vobj_iter = obj_iter->second.begin(); vobj_iter != obj_iter->second.end(); ++vobj_iter)
+		F32 detail = LLVolumeLODGroup::getVolumeScaleFromDetail(lod);
+
+		for (LLVOVolume* vobj : obj_iter->second)
 		{
-			LLVOVolume* vobj = (LLVOVolume*) gObjectList.findObject(*vobj_iter);
 			if (vobj)
 			{
 				LLVolume* obj_volume = vobj->getVolume();
@@ -4037,7 +4116,7 @@ void LLMeshRepository::notifyMeshUnavailable(const LLVolumeParams& mesh_params,
 			}
 		}
 		
-		mLoadingMeshes[lod].erase(mesh_params);
+		mLoadingMeshes[lod].erase(obj_iter);
 	}
 }
 
@@ -4046,7 +4125,7 @@ S32 LLMeshRepository::getActualMeshLOD(const LLVolumeParams& mesh_params, S32 lo
 	return mThread->getActualMeshLOD(mesh_params, lod);
 }
 
-const LLMeshSkinInfo* LLMeshRepository::getSkinInfo(const LLUUID& mesh_id, const LLVOVolume* requesting_obj)
+const LLMeshSkinInfo* LLMeshRepository::getSkinInfo(const LLUUID& mesh_id, LLVOVolume* requesting_obj)
 {
     LL_PROFILE_ZONE_SCOPED_CATEGORY_AVATAR;
     if (mesh_id.notNull())
@@ -4054,7 +4133,7 @@ const LLMeshSkinInfo* LLMeshRepository::getSkinInfo(const LLUUID& mesh_id, const
         skin_map::iterator iter = mSkinMap.find(mesh_id);
         if (iter != mSkinMap.end())
         {
-            return &(iter->second);
+            return iter->second;
         }
 
         //no skin info known about given mesh, try to fetch it
@@ -4063,14 +4142,22 @@ const LLMeshSkinInfo* LLMeshRepository::getSkinInfo(const LLUUID& mesh_id, const
             LLMutexLock lock(mMeshMutex);
             //add volume to list of loading meshes
             skin_load_map::iterator iter = mLoadingSkins.find(mesh_id);
-            if (iter == mLoadingSkins.end())
-            { //no request pending for this skin info
+			if (iter != mLoadingSkins.end())
+			{ //request pending for this mesh, append volume id to list
+				auto it = std::find(iter->second.begin(), iter->second.end(), requesting_obj);
+				if (it == iter->second.end()) {
+					iter->second.push_back(requesting_obj);
+				}
+			}
+			else
+			{
+				//first request for this mesh
+				mLoadingSkins[mesh_id].push_back(requesting_obj);
                 mPendingSkinRequests.push(mesh_id);
             }
-            mLoadingSkins[mesh_id].insert(requesting_obj->getID());
         }
     }
-	return NULL;
+	return nullptr;
 }
 
 void LLMeshRepository::fetchPhysicsShape(const LLUUID& mesh_id)
@@ -4173,16 +4260,13 @@ bool LLMeshRepository::hasPhysicsShape(const LLUUID& mesh_id)
 bool LLMeshRepoThread::hasPhysicsShapeInHeader(const LLUUID& mesh_id)
 {
     LLMutexLock lock(mHeaderMutex);
-    if (mMeshHeaderSize[mesh_id] > 0)
+    mesh_header_map::iterator iter = mMeshHeader.find(mesh_id);
+    if (iter != mMeshHeader.end() && iter->second.first > 0)
     {
-        mesh_header_map::iterator iter = mMeshHeader.find(mesh_id);
-        if (iter != mMeshHeader.end())
+        LLSD &mesh = iter->second.second;
+        if (mesh.has("physics_mesh") && mesh["physics_mesh"].has("size") && (mesh["physics_mesh"]["size"].asInteger() > 0))
         {
-            LLSD &mesh = iter->second;
-            if (mesh.has("physics_mesh") && mesh["physics_mesh"].has("size") && (mesh["physics_mesh"]["size"].asInteger() > 0))
-            {
-                return true;
-            }
+            return true;
         }
     }
 
@@ -4207,9 +4291,9 @@ S32 LLMeshRepository::getMeshSize(const LLUUID& mesh_id, S32 lod)
 	{
 		LLMutexLock lock(mThread->mHeaderMutex);
 		LLMeshRepoThread::mesh_header_map::iterator iter = mThread->mMeshHeader.find(mesh_id);
-		if (iter != mThread->mMeshHeader.end() && mThread->mMeshHeaderSize[mesh_id] > 0)
+		if (iter != mThread->mMeshHeader.end() && iter->second.first > 0)
 		{
-			LLSD& header = iter->second;
+			const LLSD& header = iter->second.second;
 
 			if (header.has("404"))
 			{
@@ -4313,9 +4397,9 @@ F32 LLMeshRepository::getStreamingCostLegacy(LLUUID mesh_id, F32 radius, S32* by
     {
         LLMutexLock lock(mThread->mHeaderMutex);
         LLMeshRepoThread::mesh_header_map::iterator iter = mThread->mMeshHeader.find(mesh_id);
-        if (iter != mThread->mMeshHeader.end() && mThread->mMeshHeaderSize[mesh_id] > 0)
+        if (iter != mThread->mMeshHeader.end() && iter->second.first > 0)
         {
-            result  = getStreamingCostLegacy(iter->second, radius, bytes, bytes_visible, lod, unscaled_value);
+            result  = getStreamingCostLegacy(iter->second.second, radius, bytes, bytes_visible, lod, unscaled_value);
         }
     }
     if (result > 0.f)
@@ -4628,9 +4712,9 @@ bool LLMeshRepository::getCostData(LLUUID mesh_id, LLMeshCostData& data)
     {
         LLMutexLock lock(mThread->mHeaderMutex);
         LLMeshRepoThread::mesh_header_map::iterator iter = mThread->mMeshHeader.find(mesh_id);
-        if (iter != mThread->mMeshHeader.end() && mThread->mMeshHeaderSize[mesh_id] > 0)
+        if (iter != mThread->mMeshHeader.end() && iter->second.first > 0)
         {
-            LLSD& header = iter->second;
+            LLSD& header = iter->second.second;
 
             bool header_invalid = (header.has("404")
                                    || !header.has("lowest_lod")
diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h
index f61da3e5715c98d9b369d80cbcd7017b3e184cc8..e3688ff243fb09e2ba9a3eacc10d1a24452b920b 100644
--- a/indra/newview/llmeshrepository.h
+++ b/indra/newview/llmeshrepository.h
@@ -210,10 +210,8 @@ class LLMeshRepoThread : public LLThread
 	LLCondition* mSignal;
 
 	//map of known mesh headers
-	typedef std::map<LLUUID, LLSD> mesh_header_map;
+	typedef boost::unordered_map<LLUUID, std::pair<U32, LLSD>> mesh_header_map; // pair is header_size and data
 	mesh_header_map mMeshHeader;
-	
-	std::map<LLUUID, U32> mMeshHeaderSize;
 
 	class HeaderRequest : public RequestStats
 	{ 
@@ -283,10 +281,13 @@ class LLMeshRepoThread : public LLThread
 	};
 
 	//set of requested skin info
-	std::set<UUIDBasedRequest> mSkinRequests;
+	std::deque<UUIDBasedRequest> mSkinRequests;
 	
 	// list of completed skin info requests
-	std::list<LLMeshSkinInfo> mSkinInfoQ;
+	std::deque<LLMeshSkinInfo*> mSkinInfoQ;
+
+	// list of skin info requests that have failed or are unavailaibe
+	std::deque<UUIDBasedRequest> mSkinUnavailableQ;
 
 	//set of requested decompositions
 	std::set<UUIDBasedRequest> mDecompositionRequests;
@@ -304,13 +305,13 @@ class LLMeshRepoThread : public LLThread
 	std::queue<LODRequest> mLODReqQ;
 
 	//queue of unavailable LODs (either asset doesn't exist or asset doesn't have desired LOD)
-	std::queue<LODRequest> mUnavailableQ;
+	std::deque<LODRequest> mUnavailableQ;
 
 	//queue of successfully loaded meshes
-	std::queue<LoadedMesh> mLoadedQ;
+	std::deque<LoadedMesh> mLoadedQ;
 
 	//map of pending header requests and currently desired LODs
-	typedef std::map<LLVolumeParams, std::vector<S32> > pending_lod_map;
+	typedef boost::unordered_map<LLUUID, std::vector<S32> > pending_lod_map;
 	pending_lod_map mPendingLOD;
 
 	// llcorehttp library interface objects.
@@ -354,7 +355,7 @@ class LLMeshRepoThread : public LLThread
 
 	//send request for skin info, returns true if header info exists 
 	//  (should hold onto mesh_id and try again later if header info does not exist)
-	bool fetchMeshSkinInfo(const LLUUID& mesh_id);
+	bool fetchMeshSkinInfo(const LLUUID& mesh_id, bool can_retry = true);
 
 	//send request for decomposition, returns true if header info exists 
 	//  (should hold onto mesh_id and try again later if header info does not exist)
@@ -577,18 +578,20 @@ class LLMeshRepository
 	void shutdown();
 	S32 update();
 
+	void unregisterMesh(LLVOVolume* volume);
 	//mesh management functions
 	S32 loadMesh(LLVOVolume* volume, const LLVolumeParams& mesh_params, S32 detail = 0, S32 last_lod = -1);
 	
 	void notifyLoadedMeshes();
 	void notifyMeshLoaded(const LLVolumeParams& mesh_params, LLVolume* volume);
 	void notifyMeshUnavailable(const LLVolumeParams& mesh_params, S32 lod);
-	void notifySkinInfoReceived(LLMeshSkinInfo& info);
+	void notifySkinInfoReceived(LLMeshSkinInfo* info);
+	void notifySkinInfoUnavailable(const LLUUID& info);
 	void notifyDecompositionReceived(LLModel::Decomposition* info);
 
 	S32 getActualMeshLOD(const LLVolumeParams& mesh_params, S32 lod);
 	static S32 getActualMeshLOD(LLSD& header, S32 lod);
-	const LLMeshSkinInfo* getSkinInfo(const LLUUID& mesh_id, const LLVOVolume* requesting_obj = nullptr);
+	const LLMeshSkinInfo* getSkinInfo(const LLUUID& mesh_id, LLVOVolume* requesting_obj = nullptr);
 	LLModel::Decomposition* getDecomposition(const LLUUID& mesh_id);
 	void fetchPhysicsShape(const LLUUID& mesh_id);
 	bool hasPhysicsShape(const LLUUID& mesh_id);
@@ -613,10 +616,10 @@ class LLMeshRepository
 	static void metricsProgress(unsigned int count);
 	static void metricsUpdate();
 	
-	typedef std::map<LLVolumeParams, std::set<LLUUID> > mesh_load_map;
+	typedef boost::unordered_map<LLUUID, std::vector<LLVOVolume*> > mesh_load_map;
 	mesh_load_map mLoadingMeshes[4];
 	
-	typedef std::unordered_map<LLUUID, LLMeshSkinInfo> skin_map;
+	typedef std::unordered_map<LLUUID, LLPointer<LLMeshSkinInfo>> skin_map;
 	skin_map mSkinMap;
 
 	typedef std::map<LLUUID, LLModel::Decomposition*> decomposition_map;
@@ -627,7 +630,7 @@ class LLMeshRepository
 	std::vector<LLMeshRepoThread::LODRequest> mPendingRequests;
 	
 	//list of mesh ids awaiting skin info
-	typedef std::map<LLUUID, std::set<LLUUID> > skin_load_map;
+	typedef boost::unordered_map<LLUUID, std::vector<LLVOVolume*> > skin_load_map;
 	skin_load_map mLoadingSkins;
 
 	//list of mesh ids that need to send skin info fetch requests
@@ -652,6 +655,8 @@ class LLMeshRepository
 	std::vector<LLMeshUploadThread*> mUploadWaitList;
 
 	LLPhysicsDecomp* mDecompThread;
+
+	LLFrameTimer     mSkinInfoCullTimer;
 	
 	class inventory_data
 	{
diff --git a/indra/newview/llmodelpreview.cpp b/indra/newview/llmodelpreview.cpp
index 642df7f931fb56762dfa373b5d2014011b4a821e..e1a5b224909846fa31b48a3e18b5c3794893c3bb 100644
--- a/indra/newview/llmodelpreview.cpp
+++ b/indra/newview/llmodelpreview.cpp
@@ -1926,32 +1926,16 @@ void LLModelPreview::genMeshOptimizerLODs(S32 which_lod, S32 meshopt_mode, U32 d
                     if (sloppy_ratio < 0)
                     {
                         // Sloppy method didn't work, try with smaller decimation values
-                        S32 size_vertices = 0;
-
-                        for (U32 face_idx = 0; face_idx < base->getNumVolumeFaces(); ++face_idx)
-                        {
-                            const LLVolumeFace &face = base->getVolumeFace(face_idx);
-                            size_vertices += face.mNumVertices;
-                        }
-
-                        // Complex models aren't supposed to get here, they are supposed
-                        // to work on a first try of sloppy due to having more viggle room.
-                        // If they didn't, something is likely wrong, no point locking the
-                        // thread in a long calculation that will fail.
-                        const U32 too_many_vertices = 27000;
-                        if (size_vertices > too_many_vertices)
-                        {
-                            LL_WARNS() << "Sloppy optimization method failed for a complex model " << target_model->getName() << LL_ENDL;
-                        }
-                        else
                         {
                             // Find a decimator that does work
                             F32 sloppy_decimation_step = sqrt((F32)decimation); // example: 27->15->9->5->3
                             F32 sloppy_decimator = indices_decimator / sloppy_decimation_step;
+                            U64Microseconds end_time = LLTimer::getTotalTime() + U64Seconds(5);
 
                             while (sloppy_ratio < 0
                                 && sloppy_decimator > precise_ratio
-                                && sloppy_decimator > 1)// precise_ratio isn't supposed to be below 1, but check just in case
+                                && sloppy_decimator > 1 // precise_ratio isn't supposed to be below 1, but check just in case
+                                && end_time > LLTimer::getTotalTime())
                             {
                                 sloppy_ratio = genMeshOptimizerPerModel(base, target_model, sloppy_decimator, lod_error_threshold, MESH_OPTIMIZER_NO_TOPOLOGY);
                                 sloppy_decimator = sloppy_decimator / sloppy_decimation_step;
diff --git a/indra/newview/llnetmap.cpp b/indra/newview/llnetmap.cpp
old mode 100755
new mode 100644
index b34be80b078ec0f279599593e22c235ca5982b84..0ba3c3d6914e7abded9cb3c2607d515e8b5f8e34
--- a/indra/newview/llnetmap.cpp
+++ b/indra/newview/llnetmap.cpp
@@ -102,8 +102,7 @@ LLNetMap::LLNetMap (const Params & p)
 	mObjectImagep(),
 	mClosestAgentToCursor(),
 	mClosestAgentAtLastRightClick(),
-	mToolTipMsg(),
-	mPopupMenu(NULL)
+	mToolTipMsg()
 {
 	mScale = gSavedSettings.getF32("MiniMapScale");
     if (gAgent.isFirstLogin())
@@ -119,6 +118,12 @@ LLNetMap::LLNetMap (const Params & p)
 
 LLNetMap::~LLNetMap()
 {
+    auto menu = static_cast<LLMenuGL*>(mPopupMenuHandle.get());
+    if (menu)
+    {
+        menu->die();
+        mPopupMenuHandle.markDead();
+    }
 }
 
 BOOL LLNetMap::postBuild()
@@ -134,11 +139,10 @@ BOOL LLNetMap::postBuild()
     commitRegistrar.add("Minimap.MapOrientation.Set", boost::bind(&LLNetMap::setMapOrientation, this, _2));
     commitRegistrar.add("Minimap.AboutLand", boost::bind(&LLNetMap::popupShowAboutLand, this, _2));
 
-    mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_mini_map.xml", gMenuHolder,
-                                                                          LLViewerMenuHolderGL::child_registry_t::instance());
-    mPopupMenu->setItemEnabled("Re-center map", false);
-
-    return true;
+    LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_mini_map.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+    mPopupMenuHandle = menu->getHandle();
+    menu->setItemEnabled("Re-center map", false);
+	return TRUE;
 }
 
 void LLNetMap::setScale( F32 scale )
@@ -206,8 +210,12 @@ void LLNetMap::draw()
         mCentering = false;
     }
 
-    bool can_recenter_map = !(centered || mCentering || auto_centering);
-    mPopupMenu->setItemEnabled("Re-center map", can_recenter_map);
+    auto menu = static_cast<LLMenuGL*>(mPopupMenuHandle.get());
+    if (menu)
+    {
+        bool can_recenter_map = !(centered || mCentering || auto_centering);
+        menu->setItemEnabled("Re-center map", can_recenter_map);
+    }
     updateAboutLandPopupButton();
 
 	// Prepare a scissor region
@@ -595,14 +603,15 @@ void LLNetMap::drawTracking(const LLVector3d& pos_global, const LLColor4& color,
 
 bool LLNetMap::isMouseOnPopupMenu()
 {
-    if (!mPopupMenu->isOpen())
+    auto menu = static_cast<LLMenuGL*>(mPopupMenuHandle.get());
+    if (!menu || !menu->isOpen())
     {
         return false;
     }
 
     S32 popup_x;
     S32 popup_y;
-    LLUI::getInstance()->getMousePositionLocal(mPopupMenu, &popup_x, &popup_y);
+    LLUI::getInstance()->getMousePositionLocal(menu, &popup_x, &popup_y);
     // *NOTE: Tolerance is larger than it needs to be because the context menu is offset from the mouse when the menu is opened from certain
     // directions. This may be a quirk of LLMenuGL::showPopup. -Cosmic,2022-03-22
     constexpr S32 tolerance = 10;
@@ -613,7 +622,7 @@ bool LLNetMap::isMouseOnPopupMenu()
     {
         for (S32 sign_y = -1; sign_y <= 1; sign_y += 2)
         {
-            if (mPopupMenu->pointInView(popup_x + (sign_x * tolerance), popup_y + (sign_y * tolerance)))
+            if (menu->pointInView(popup_x + (sign_x * tolerance), popup_y + (sign_y * tolerance)))
             {
                 return true;
             }
@@ -624,7 +633,8 @@ bool LLNetMap::isMouseOnPopupMenu()
 
 void LLNetMap::updateAboutLandPopupButton()
 {
-    if (!mPopupMenu->isOpen())
+    auto menu = static_cast<LLMenuGL*>(mPopupMenuHandle.get());
+    if (!menu || !menu->isOpen())
     {
         return;
     }
@@ -632,7 +642,7 @@ void LLNetMap::updateAboutLandPopupButton()
     LLViewerRegion *region = LLWorld::getInstance()->getRegionFromPosGlobal(mPopupWorldPos);
     if (!region)
     {
-        mPopupMenu->setItemEnabled("About Land", false);
+        menu->setItemEnabled("About Land", false);
     }
     else
     {
@@ -647,7 +657,7 @@ void LLNetMap::updateAboutLandPopupButton()
             {
                 valid_parcel = hover_parcel->getOwnerID().notNull();
             }
-            mPopupMenu->setItemEnabled("About Land", valid_parcel);
+            menu->setItemEnabled("About Land", valid_parcel);
         }
     }
 }
@@ -1043,13 +1053,14 @@ BOOL LLNetMap::handleMouseUp(S32 x, S32 y, MASK mask)
 
 BOOL LLNetMap::handleRightMouseDown(S32 x, S32 y, MASK mask)
 {
-	if (mPopupMenu)
+    auto menu = static_cast<LLMenuGL*>(mPopupMenuHandle.get());
+    if (menu)
 	{
-        mPopupWorldPos = viewPosToGlobal(x, y);
-		mPopupMenu->buildDrawLabels();
-		mPopupMenu->updateParent(LLMenuGL::sMenuContainer);
-		mPopupMenu->setItemEnabled("Stop tracking", LLTracker::isTracking(0));
-		LLMenuGL::showPopup(this, mPopupMenu, x, y);
+		mPopupWorldPos = viewPosToGlobal(x, y);
+        menu->buildDrawLabels();
+        menu->updateParent(LLMenuGL::sMenuContainer);
+        menu->setItemEnabled("Stop Tracking", LLTracker::isTracking(0));
+		LLMenuGL::showPopup(this, menu, x, y);
 	}
 	return TRUE;
 }
@@ -1182,9 +1193,10 @@ void LLNetMap::setZoom(const LLSD &userdata)
 
 void LLNetMap::handleStopTracking (const LLSD& userdata)
 {
-	if (mPopupMenu)
+    auto menu = static_cast<LLMenuGL*>(mPopupMenuHandle.get());
+    if (menu)
 	{
-		mPopupMenu->setItemEnabled ("Stop tracking", false);
+        menu->setItemEnabled ("Stop Tracking", false);
 		LLTracker::stopTracking (LLTracker::isTracking(NULL));
 	}
 }
diff --git a/indra/newview/llnetmap.h b/indra/newview/llnetmap.h
index fe1aca65a9b92220a5202e9639b2eccd8adc6977..75c1abc4ed886fb966cddb146bac6ff2decdea38 100644
--- a/indra/newview/llnetmap.h
+++ b/indra/newview/llnetmap.h
@@ -162,7 +162,7 @@ class LLNetMap : public LLUICtrl
     void setMapOrientation(const LLSD& userdata);
     void popupShowAboutLand(const LLSD& userdata);
 
-	LLMenuGL*		mPopupMenu;
+    LLHandle<LLView> mPopupMenuHandle;
 	uuid_vec_t		gmSelected;
 };
 
diff --git a/indra/newview/llnotificationlistitem.cpp b/indra/newview/llnotificationlistitem.cpp
index 6a79a0c68cf9224f873f5332187fda8a24e33443..f86edfd0cf5beb67f3fffd666f2823415c1e6bd3 100644
--- a/indra/newview/llnotificationlistitem.cpp
+++ b/indra/newview/llnotificationlistitem.cpp
@@ -521,8 +521,6 @@ void LLGroupNoticeNotificationListItem::close()
 void LLGroupNoticeNotificationListItem::onClickAttachment()
 {
     if (mInventoryOffer != NULL) {
-        mInventoryOffer->forceResponse(IOR_ACCEPT);
-
         static const LLUIColor textColor = LLUIColorTable::instance().getColor(
             "GroupNotifyDimmedTextColor");
         mAttachmentTextBox->setColor(textColor);
@@ -532,7 +530,7 @@ void LLGroupNoticeNotificationListItem::onClickAttachment()
         if (!isAttachmentOpenable(mInventoryOffer->mType)) {
             LLNotifications::instance().add("AttachmentSaved", LLSD(), LLSD());
         }
-
+        mInventoryOffer->forceResponse(IOR_ACCEPT);
         mInventoryOffer = NULL;
     }
 }
diff --git a/indra/newview/lloutfitgallery.cpp b/indra/newview/lloutfitgallery.cpp
index f419e2e06dd5eb56061cc21fd0706bddb33c03ea..602b7412a4192d623044047b834e140aa27b229f 100644
--- a/indra/newview/lloutfitgallery.cpp
+++ b/indra/newview/lloutfitgallery.cpp
@@ -41,7 +41,7 @@
 #include "llfilepicker.h"
 #include "llfloaterperms.h"
 #include "llfloaterreg.h"
-#include "llfloateroutfitsnapshot.h"
+#include "llfloatersimpleoutfitsnapshot.h"
 #include "llimagedimensionsinfo.h"
 #include "llinventoryfunctions.h"
 #include "llinventorymodel.h"
@@ -1226,7 +1226,7 @@ void LLOutfitGallery::uploadOutfitImage(const std::vector<std::string>& filename
         checkRemovePhoto(outfit_id);
         std::string upload_pending_name = outfit_id.asString();
         std::string upload_pending_desc = "";
-        LLUUID photo_id = upload_new_resource(filename, // file
+        upload_new_resource(filename, // file
             upload_pending_name,
             upload_pending_desc,
             0, LLFolderType::FT_NONE, LLInventoryType::IT_NONE,
@@ -1386,8 +1386,8 @@ void LLOutfitGallery::onSelectPhoto(LLUUID selected_outfit_id)
 
 void LLOutfitGallery::onTakeSnapshot(LLUUID selected_outfit_id)
 {
-    LLFloaterReg::toggleInstanceOrBringToFront("outfit_snapshot");
-    LLFloaterOutfitSnapshot* snapshot_floater = LLFloaterOutfitSnapshot::getInstance();
+    LLFloaterReg::toggleInstanceOrBringToFront("simple_outfit_snapshot");
+    LLFloaterSimpleOutfitSnapshot* snapshot_floater = LLFloaterSimpleOutfitSnapshot::getInstance();
     if (snapshot_floater)
     {
         snapshot_floater->setOutfitID(selected_outfit_id);
diff --git a/indra/newview/lloutfitslist.cpp b/indra/newview/lloutfitslist.cpp
index 72705800325ff2dbedd980f2c9798c3b5dbab460..4171fd8822dec507feafb607a5c04551bfa1c01d 100644
--- a/indra/newview/lloutfitslist.cpp
+++ b/indra/newview/lloutfitslist.cpp
@@ -823,8 +823,7 @@ void LLOutfitListBase::onOpen(const LLSD& info)
         mCategoriesObserver->addCategory(outfits,
             boost::bind(&LLOutfitListBase::refreshList, this, outfits));
 
-        const LLUUID cof = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT);
-
+        //const LLUUID cof = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT);
         // Start observing changes in Current Outfit category.
         //mCategoriesObserver->addCategory(cof, boost::bind(&LLOutfitsList::onCOFChanged, this));
 
diff --git a/indra/newview/llpaneleditwearable.cpp b/indra/newview/llpaneleditwearable.cpp
index ea10aa75ae011aa7b7ce0da16ead9677519f2b16..0103bf628a9d69aef9365b6ebcfbbaa581cf133a 100644
--- a/indra/newview/llpaneleditwearable.cpp
+++ b/indra/newview/llpaneleditwearable.cpp
@@ -1663,7 +1663,7 @@ void LLPanelEditWearable::initPreviousAlphaTextureEntry(LLAvatarAppearanceDefine
 class LLMetricSystemHandler : public LLCommandHandler
 {
 public:
-        LLMetricSystemHandler() : LLCommandHandler("metricsystem", UNTRUSTED_THROTTLE) { }
+        LLMetricSystemHandler() : LLCommandHandler("metricsystem", UNTRUSTED_CLICK_ONLY) { }
 
         bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web)
         {
diff --git a/indra/newview/llpanelexperiencelog.cpp b/indra/newview/llpanelexperiencelog.cpp
index 44b4728df779925cda2c905b31f513231c211290..e5c637938ff9edee0bda4a6630aa2b4b678000bf 100644
--- a/indra/newview/llpanelexperiencelog.cpp
+++ b/indra/newview/llpanelexperiencelog.cpp
@@ -112,7 +112,7 @@ void LLPanelExperienceLog::refresh()
 	int items = 0;
 	bool moreItems = false;
 	LLSD events_to_save = events;
-	if (!events.emptyMap())
+	if (events.isMap() && events.size() != 0)
 	{
 		LLSD::map_const_iterator day = events.endMap();
 		do
diff --git a/indra/newview/llpanellandmedia.cpp b/indra/newview/llpanellandmedia.cpp
index 26cd3ff1c19b509fe65cf726258b6bec772b6d96..e379d67e372bec8730091601e5c3774694426ea9 100644
--- a/indra/newview/llpanellandmedia.cpp
+++ b/indra/newview/llpanellandmedia.cpp
@@ -179,7 +179,6 @@ void LLPanelLandMedia::refresh()
 		// enable/disable for text label for completeness
 		mMediaSizeCtrlLabel->setEnabled( can_change_media && allow_resize );
 
-		LLUUID tmp = parcel->getMediaID();
 		mMediaTextureCtrl->setImageAssetID ( parcel->getMediaID() );
 		mMediaTextureCtrl->setEnabled( can_change_media );
 
diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp
index 89256b40c4c79f5406ec2b51b4310e595058b3bb..81acb1c8b4d7c47d71c876016416eb68462ffa15 100644
--- a/indra/newview/llpanelmaininventory.cpp
+++ b/indra/newview/llpanelmaininventory.cpp
@@ -307,6 +307,13 @@ LLPanelMainInventory::~LLPanelMainInventory( void )
     
 	gInventory.removeObserver(this);
 	delete mSavedFolderState;
+
+	auto menu = mMenuAddHandle.get();
+	if(menu)
+	{
+		menu->die();
+		mMenuAddHandle.markDead();
+	}
 }
 
 LLInventoryPanel* LLPanelMainInventory::getAllItemsPanel()
@@ -1177,13 +1184,12 @@ void LLPanelMainInventory::initListCommandsHandlers()
 	mEnableCallbackRegistrar.add("Inventory.GearDefault.Check", boost::bind(&LLPanelMainInventory::isActionChecked, this, _2));
 	mEnableCallbackRegistrar.add("Inventory.GearDefault.Enable", boost::bind(&LLPanelMainInventory::isActionEnabled, this, _2));
 	mMenuGearDefault = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_inventory_gear_default.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
-	mGearMenuButton->setMenu(mMenuGearDefault);
+	mGearMenuButton->setMenu(mMenuGearDefault, LLMenuButton::MP_TOP_LEFT, true);
 	LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_inventory_add.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
 	mMenuAddHandle = menu->getHandle();
 
 	mMenuVisibility = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_inventory_search_visibility.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
-	mVisibilityMenuButton->setMenu(mMenuVisibility);
-	mVisibilityMenuButton->setMenuPosition(LLMenuButton::MP_BOTTOM_LEFT);
+	mVisibilityMenuButton->setMenu(mMenuVisibility, LLMenuButton::MP_BOTTOM_LEFT, true);
 
 	// Update the trash button when selected item(s) get worn or taken off.
 	LLOutfitObserver::instance().addCOFChangedCallback(boost::bind(&LLPanelMainInventory::updateListCommands, this));
diff --git a/indra/newview/llpanelmediasettingsgeneral.cpp b/indra/newview/llpanelmediasettingsgeneral.cpp
index e1818cc68b3933c3d775e694690c958f6e6e823f..416857bd305f2b22567a03381c30065d14c2a65f 100644
--- a/indra/newview/llpanelmediasettingsgeneral.cpp
+++ b/indra/newview/llpanelmediasettingsgeneral.cpp
@@ -454,7 +454,8 @@ bool LLPanelMediaSettingsGeneral::navigateHomeSelectedFace(bool only_if_current_
 							LLViewerMedia::getInstance()->getMediaImplFromTextureID(object->getTE(face)->getMediaData()->getMediaID());
 						if(media_impl)
 						{
-							media_impl->navigateHome();
+                            media_impl->setPriority(LLPluginClassMedia::PRIORITY_NORMAL);
+                            media_impl->navigateHome();
 							return true;
 						}
 					}
diff --git a/indra/newview/llpanelobject.cpp b/indra/newview/llpanelobject.cpp
index 0bfc1297d35b0339d4b1a06dadd81d102e1fc66d..2da431955fc326c0094a9747131bd20a8ba666d3 100644
--- a/indra/newview/llpanelobject.cpp
+++ b/indra/newview/llpanelobject.cpp
@@ -93,6 +93,8 @@ enum {
 	MI_HOLE_COUNT
 };
 
+const F32 MAX_ATTACHMENT_DIST = 3.5f; // meters
+
 //static const std::string LEGACY_FULLBRIGHT_DESC =LLTrans::getString("Fullbright");
 
 BOOL	LLPanelObject::postBuild()
@@ -1685,6 +1687,16 @@ void LLPanelObject::sendPosition(BOOL btn_down)
 			mCtrlPosZ->set(LLWorld::getInstance()->resolveLandHeightAgent(newpos) + 1.f);
 		}
 	}
+    else
+    {
+        if (newpos.length() > MAX_ATTACHMENT_DIST)
+        {
+            newpos.clampLength(MAX_ATTACHMENT_DIST);
+            mCtrlPosX->set(newpos.mV[VX]);
+            mCtrlPosY->set(newpos.mV[VY]);
+            mCtrlPosZ->set(newpos.mV[VZ]);
+        }
+    }
 
 	// Make sure new position is in a valid region, so the object
 	// won't get dumped by the simulator.
@@ -2119,7 +2131,7 @@ bool LLPanelObject::menuEnableItem(const LLSD& userdata)
     }
     else if (command == "params_paste")
     {
-        return mClipboardParams.isMap() && !mClipboardParams.emptyMap();
+        return mClipboardParams.isMap() && (mClipboardParams.size() != 0);
     }
     // copy options
     else if (command == "psr_copy")
@@ -2191,6 +2203,10 @@ void LLPanelObject::onPastePos()
         mClipboardPos.mV[VY] = llclamp(mClipboardPos.mV[VY], 0.f, max_width);
         //height will get properly clamped by sendPosition
     }
+    else
+    {
+        mClipboardPos.clampLength(MAX_ATTACHMENT_DIST);
+    }
 
     mCtrlPosX->set( mClipboardPos.mV[VX] );
     mCtrlPosY->set( mClipboardPos.mV[VY] );
diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp
index cfaa9456be3f1242305981d5e0d477eaafdbcfc0..bd40c9dd2baac0f46749e6b37b184f6ea1f05d16 100644
--- a/indra/newview/llpanelobjectinventory.cpp
+++ b/indra/newview/llpanelobjectinventory.cpp
@@ -131,7 +131,7 @@ class LLTaskInvFVBridge : public LLFolderViewModelItemInventory
 	virtual BOOL removeItem();
 	virtual void removeBatch(std::vector<LLFolderViewModelItem*>& batch);
 	virtual void move(LLFolderViewModelItem* parent_listener);	
-	virtual BOOL isItemCopyable() const;
+    virtual bool isItemCopyable(bool can_copy_as_link = true) const;
 	virtual BOOL copyToClipboard() const;
 	virtual BOOL cutToClipboard();
 	virtual BOOL isClipboardPasteable() const;
@@ -439,10 +439,10 @@ void LLTaskInvFVBridge::move(LLFolderViewModelItem* parent_listener)
 {
 }
 
-BOOL LLTaskInvFVBridge::isItemCopyable() const
+bool LLTaskInvFVBridge::isItemCopyable(bool can_link) const
 {
 	LLInventoryItem* item = findItem();
-	if(!item) return FALSE;
+	if(!item) return false;
 	return gAgent.allowOperation(PERM_COPY, item->getPermissions(),
 								GP_OBJECT_MANIPULATE);
 }
@@ -1275,7 +1275,8 @@ LLPanelObjectInventory::LLPanelObjectInventory(const LLPanelObjectInventory::Par
 	mHaveInventory(FALSE),
 	mIsInventoryEmpty(TRUE),
 	mInventoryNeedsUpdate(FALSE),
-	mInventoryViewModel(p.name)
+	mInventoryViewModel(p.name),
+    mShowRootFolder(p.show_root_folder)
 {
 	// Setup context menu callbacks
 	mCommitCallbackRegistrar.add("Inventory.DoToSelected", boost::bind(&LLPanelObjectInventory::doToSelected, this, _2));
@@ -1360,6 +1361,7 @@ void LLPanelObjectInventory::reset()
 	mFolders = LLUICtrlFactory::create<LLFolderView>(p);
 
 	mFolders->setCallbackRegistrar(&mCommitCallbackRegistrar);
+	mFolders->setEnableRegistrar(&mEnableCallbackRegistrar);
 
 	if (hasFocus())
 	{
@@ -1526,15 +1528,23 @@ void LLPanelObjectInventory::createFolderViews(LLInventoryObject* inventory_root
 		p.font_highlight_color = item_color;
 
 		LLFolderViewFolder* new_folder = LLUICtrlFactory::create<LLFolderViewFolder>(p);
-		new_folder->addToFolder(mFolders);
-		new_folder->toggleOpen();
+
+        if (mShowRootFolder)
+        {
+            new_folder->addToFolder(mFolders);
+            new_folder->toggleOpen();
+        }
 
 		if (!contents.empty())
 		{
-			createViewsForCategory(&contents, inventory_root, new_folder);
+			createViewsForCategory(&contents, inventory_root, mShowRootFolder ? new_folder : mFolders);
 		}
-        // Refresh for label to add item count
-        new_folder->refresh();
+
+        if (mShowRootFolder)
+        {
+            // Refresh for label to add item count
+            new_folder->refresh();
+        }
 	}
 }
 
diff --git a/indra/newview/llpanelobjectinventory.h b/indra/newview/llpanelobjectinventory.h
index 7b9ecfb8f31d6914fc9c4b77f8fbe3f7cf138131..0e450d8ce9c6ec43fcc80b7dac9eccc510d73f77 100644
--- a/indra/newview/llpanelobjectinventory.h
+++ b/indra/newview/llpanelobjectinventory.h
@@ -48,8 +48,14 @@ class LLViewerObject;
 class LLPanelObjectInventory : public LLPanel, public LLVOInventoryListener
 {
 public:
-	// dummy param block for template registration purposes
-	struct Params : public LLPanel::Params {};
+    struct Params : public LLInitParam::Block<Params, LLPanel::Params>
+    {
+        Optional<bool> show_root_folder;
+
+        Params()
+            : show_root_folder("show_root_folder", true)
+        {}
+    };
 
 	LLPanelObjectInventory(const Params&);
 	virtual ~LLPanelObjectInventory();
@@ -110,6 +116,7 @@ class LLPanelObjectInventory : public LLPanel, public LLVOInventoryListener
 	BOOL mIsInventoryEmpty; // 'Empty' label
 	BOOL mInventoryNeedsUpdate; // for idle, set on changed callback
 	LLFolderViewModelInventory	mInventoryViewModel;	
+    bool mShowRootFolder;
 };
 
 #endif // LL_LLPANELOBJECTINVENTORY_H
diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp
index 74ec57655463038bc1e4e23bed79550d92a311a5..0f00231643c63dc3dad339e84469492568de347f 100644
--- a/indra/newview/llpanelplaces.cpp
+++ b/indra/newview/llpanelplaces.cpp
@@ -800,7 +800,6 @@ void LLPanelPlaces::onSaveButtonClicked()
 	LLStringUtil::trim(current_title_value);
 	LLStringUtil::trim(current_notes_value);
 
-	LLUUID item_id = mItem->getUUID();
 	LLUUID folder_id = mLandmarkInfo->getLandmarkFolder();
 	bool change_parent = folder_id != mItem->getParentUUID();
 
diff --git a/indra/newview/llpanelpresetscamerapulldown.cpp b/indra/newview/llpanelpresetscamerapulldown.cpp
index 183123e534e8a333472d94117ae9475e3d203c12..4c9c30160c4d362b96ea11a7c8d89c399ce1ea9c 100644
--- a/indra/newview/llpanelpresetscamerapulldown.cpp
+++ b/indra/newview/llpanelpresetscamerapulldown.cpp
@@ -127,7 +127,10 @@ void LLPanelPresetsCameraPulldown::onRowClick(const LLSD& user_data)
             LL_DEBUGS() << "selected '" << name << "'" << LL_ENDL;
 			LLFloaterCamera::switchToPreset(name);
 
-			setVisible(FALSE);
+            // Scroll grabbed focus, drop it to prevent selection of parent menu
+            setFocus(FALSE);
+
+            setVisible(FALSE);
 		}
         else
         {
diff --git a/indra/newview/llpanelpresetspulldown.cpp b/indra/newview/llpanelpresetspulldown.cpp
index d52ad8056fc75849b1d717dfe4572a32f9891b13..23e4fa8887dfde2bf53e868b322d76c5b78d452c 100644
--- a/indra/newview/llpanelpresetspulldown.cpp
+++ b/indra/newview/llpanelpresetspulldown.cpp
@@ -122,6 +122,9 @@ void LLPanelPresetsPulldown::onRowClick(const LLSD& user_data)
             LL_DEBUGS() << "selected '" << name << "'" << LL_ENDL;
 			LLPresetsManager::getInstance()->loadPreset(PRESETS_GRAPHIC, name);
 
+            // Scroll grabbed focus, drop it to prevent selection of parent menu
+            setFocus(FALSE);
+
 			setVisible(FALSE);
 		}
         else
diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp
index f4eaa78f11367404b4a06e5dccaf5adfea8b3816..708ff26ced83648091bc4d6dc37398bda9fd7fdc 100644
--- a/indra/newview/llpanelprofile.cpp
+++ b/indra/newview/llpanelprofile.cpp
@@ -484,6 +484,30 @@ class LLAgentHandler : public LLCommandHandler
 	// requires trusted browser to trigger
 	LLAgentHandler() : LLCommandHandler("agent", UNTRUSTED_THROTTLE) { }
 
+    virtual bool canHandleUntrusted(
+        const LLSD& params,
+        const LLSD& query_map,
+        LLMediaCtrl* web,
+        const std::string& nav_type)
+    {
+        if (params.size() < 2)
+        {
+            return true; // don't block, will fail later
+        }
+
+        if (nav_type == NAV_TYPE_CLICKED)
+        {
+            return true;
+        }
+
+        const std::string verb = params[1].asString();
+        if (verb == "about" || verb == "inspect" || verb == "reportAbuse")
+        {
+            return true;
+        }
+        return false;
+    }
+
 	bool handle(const LLSD& params, const LLSD& query_map,
 		LLMediaCtrl* web)
 	{
@@ -1031,7 +1055,6 @@ void LLPanelProfileSecondLife::resetData()
 
 void LLPanelProfileSecondLife::processProfileProperties(const LLAvatarData* avatar_data)
 {
-    LLUUID avatar_id = getAvatarId();
     const LLRelationship* relationship = LLAvatarTracker::instance().getBuddyInfo(getAvatarId());
     if ((relationship != NULL || gAgent.isGodlike()) && !getSelfProfile())
     {
@@ -1280,6 +1303,8 @@ void LLPanelProfileSecondLife::fillRightsData()
 
 void LLPanelProfileSecondLife::fillAgeData(const LLDate &born_on)
 {
+    // Date from server comes already converted to stl timezone,
+    // so display it as an UTC + 0
     std::string name_and_date = getString("date_format");
     LLSD args_name;
     args_name["datetime"] = (S32)born_on.secondsSinceEpoch();
diff --git a/indra/newview/llpanelprofileclassifieds.cpp b/indra/newview/llpanelprofileclassifieds.cpp
index a3913ddc49e49e6ef021670adf1f532a1761a977..1ff12b4f3781dfce2d61bfd0d0fffee2e62b434c 100644
--- a/indra/newview/llpanelprofileclassifieds.cpp
+++ b/indra/newview/llpanelprofileclassifieds.cpp
@@ -81,6 +81,30 @@ class LLClassifiedHandler : public LLCommandHandler, public LLAvatarPropertiesOb
 	
 	std::set<LLUUID> mClassifiedIds;
 	std::string mRequestVerb;
+
+    virtual bool canHandleUntrusted(
+        const LLSD& params,
+        const LLSD& query_map,
+        LLMediaCtrl* web,
+        const std::string& nav_type)
+    {
+        if (params.size() < 1)
+        {
+            return true; // don't block, will fail later
+        }
+
+        if (nav_type == NAV_TYPE_CLICKED)
+        {
+            return true;
+        }
+
+        const std::string verb = params[0].asString();
+        if (verb == "create")
+        {
+            return false;
+        }
+        return true;
+    }
     
 	bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web)
     {
diff --git a/indra/newview/llpanelprofilepicks.cpp b/indra/newview/llpanelprofilepicks.cpp
index 774119f16975e48fdb88ab6a84acf6b327bff26c..45d0252e4fef0d36ab3e4b01cc2c5ace18410aba 100644
--- a/indra/newview/llpanelprofilepicks.cpp
+++ b/indra/newview/llpanelprofilepicks.cpp
@@ -63,6 +63,30 @@ class LLPickHandler : public LLCommandHandler
     // requires trusted browser to trigger
     LLPickHandler() : LLCommandHandler("pick", UNTRUSTED_THROTTLE) { }
 
+    virtual bool canHandleUntrusted(
+        const LLSD& params,
+        const LLSD& query_map,
+        LLMediaCtrl* web,
+        const std::string& nav_type)
+    {
+        if (params.size() < 1)
+        {
+            return true; // don't block, will fail later
+        }
+
+        if (nav_type == NAV_TYPE_CLICKED)
+        {
+            return true;
+        }
+
+        const std::string verb = params[0].asString();
+        if (verb == "create")
+        {
+            return false;
+        }
+        return true;
+    }
+
     bool handle(const LLSD& params, const LLSD& query_map,
         LLMediaCtrl* web)
     {
diff --git a/indra/newview/llpanelpulldown.cpp b/indra/newview/llpanelpulldown.cpp
index 4de6ee81829eadd0910a13d049d02035a70bbbba..075278f44ccbb987ebc080fead3525ca36bd6b19 100644
--- a/indra/newview/llpanelpulldown.cpp
+++ b/indra/newview/llpanelpulldown.cpp
@@ -51,6 +51,7 @@ void LLPanelPulldown::onMouseEnter(S32 x, S32 y, MASK mask)
 /*virtual*/
 void LLPanelPulldown::onTopLost()
 {
+    setFocus(FALSE); // drop focus to prevent transfer to parent
     setVisible(FALSE);
 }
 
@@ -113,6 +114,7 @@ void LLPanelPulldown::draw()
 
     if (alpha == 0.f)
     {
+        setFocus(FALSE); // drop focus to prevent transfer to parent
         setVisible(FALSE);
     }
 }
diff --git a/indra/newview/llpreviewnotecard.cpp b/indra/newview/llpreviewnotecard.cpp
index 3fd4f51559e023af6be25256548f039e97e8b031..33656566d1f4f92d0412ecea7646aaa99c900355 100644
--- a/indra/newview/llpreviewnotecard.cpp
+++ b/indra/newview/llpreviewnotecard.cpp
@@ -255,7 +255,7 @@ void LLPreviewNotecard::loadAsset()
 			else
 			{
 				LLHost source_sim = LLHost();
-				LLSD* user_data = new LLSD();
+				LLSD* user_data = nullptr;
 				if (mObjectUUID.notNull())
 				{
 					LLViewerObject *objectp = gObjectList.findObject(mObjectUUID);
@@ -274,6 +274,7 @@ void LLPreviewNotecard::loadAsset()
 						mAssetStatus = PREVIEW_ASSET_LOADED;
 						return;
 					}
+					user_data = new LLSD();
 					user_data->with("taskid", mObjectUUID).with("itemid", mItemUUID);
 				}
 				else
diff --git a/indra/newview/llscenemonitor.cpp b/indra/newview/llscenemonitor.cpp
index 2e44dc1459259b69a0acc9d4019ad3275efcb55e..7089df677ec9bf8562e2290cd5691653a634db80 100644
--- a/indra/newview/llscenemonitor.cpp
+++ b/indra/newview/llscenemonitor.cpp
@@ -515,7 +515,7 @@ void LLSceneMonitor::fetchQueryResult()
 }
 
 //dump results to a file _scene_xmonitor_results.csv
-void LLSceneMonitor::dumpToFile(std::string file_name)
+void LLSceneMonitor::dumpToFile(const std::string &file_name)
 {
 	if (!hasResults()) return;
 
diff --git a/indra/newview/llscenemonitor.h b/indra/newview/llscenemonitor.h
index 7cd531bd34667c510e492f3d396ba63226e792b1..f2e1ef69b9274a934488216e696728eabc59fdb0 100644
--- a/indra/newview/llscenemonitor.h
+++ b/indra/newview/llscenemonitor.h
@@ -61,7 +61,7 @@ class LLSceneMonitor : public LLSingleton<LLSceneMonitor>
 	bool needsUpdate() const;
 	
 	const LLTrace::ExtendablePeriodicRecording* getRecording() const {return &mSceneLoadRecording;}
-	void dumpToFile(std::string file_name);
+	void dumpToFile(const std::string &file_name);
 	bool hasResults() const { return mSceneLoadRecording.getResults().getDuration() != S32Seconds(0);}
 
 	void reset();
diff --git a/indra/newview/llscripteditor.cpp b/indra/newview/llscripteditor.cpp
index c6bb2f19dd45a47b90394ae550ec79b0bcb3f3f7..140cbbedbecd027f4b7a0e38ecef50dacd363d7c 100644
--- a/indra/newview/llscripteditor.cpp
+++ b/indra/newview/llscripteditor.cpp
@@ -187,82 +187,8 @@ void LLScriptEditor::drawSelectionBackground()
 	// Draw selection even if we don't have keyboard focus for search/replace
 	if( hasSelection() && !mLineInfoList.empty())
 	{
-		std::vector<LLRect> selection_rects;
-		
-		S32 selection_left		= llmin( mSelectionStart, mSelectionEnd );
-		S32 selection_right		= llmax( mSelectionStart, mSelectionEnd );
-		
-		// Skip through the lines we aren't drawing.
-		LLRect content_display_rect = getVisibleDocumentRect();
-		
-		// binary search for line that starts before top of visible buffer
-		line_list_t::const_iterator line_iter = std::lower_bound(mLineInfoList.begin(), mLineInfoList.end(), content_display_rect.mTop, LLTextBase::compare_bottom());
-		line_list_t::const_iterator end_iter = std::upper_bound(mLineInfoList.begin(), mLineInfoList.end(), content_display_rect.mBottom, LLTextBase::compare_top());
-		
-		bool done = false;
-		
-		// Find the coordinates of the selected area
-		for (;line_iter != end_iter && !done; ++line_iter)
-		{
-			// is selection visible on this line?
-			if (line_iter->mDocIndexEnd > selection_left && line_iter->mDocIndexStart < selection_right)
-			{
-				segment_set_t::iterator segment_iter;
-				S32 segment_offset;
-				getSegmentAndOffset(line_iter->mDocIndexStart, &segment_iter, &segment_offset);
-				
-				LLRect selection_rect;
-				selection_rect.mLeft = line_iter->mRect.mLeft;
-				selection_rect.mRight = line_iter->mRect.mLeft;
-				selection_rect.mBottom = line_iter->mRect.mBottom;
-				selection_rect.mTop = line_iter->mRect.mTop;
-				
-				for(;segment_iter != mSegments.end(); ++segment_iter, segment_offset = 0)
-				{
-					LLTextSegmentPtr segmentp = *segment_iter;
-					
-					S32 segment_line_start = segmentp->getStart() + segment_offset;
-					S32 segment_line_end = llmin(segmentp->getEnd(), line_iter->mDocIndexEnd);
-					
-					if (segment_line_start > segment_line_end) break;
-					
-					S32 segment_width = 0;
-					S32 segment_height = 0;
-					
-					// if selection after beginning of segment
-					if(selection_left >= segment_line_start)
-					{
-						S32 num_chars = llmin(selection_left, segment_line_end) - segment_line_start;
-						segmentp->getDimensions(segment_offset, num_chars, segment_width, segment_height);
-						selection_rect.mLeft += segment_width;
-					}
-					
-					// if selection_right == segment_line_end then that means we are the first character of the next segment
-					// or first character of the next line, in either case we want to add the length of the current segment
-					// to the selection rectangle and continue.
-					// if selection right > segment_line_end then selection spans end of current segment...
-					if (selection_right >= segment_line_end)
-					{
-						// extend selection slightly beyond end of line
-						// to indicate selection of newline character (use "n" character to determine width)
-						S32 num_chars = segment_line_end - segment_line_start;
-						segmentp->getDimensions(segment_offset, num_chars, segment_width, segment_height);
-						selection_rect.mRight += segment_width;
-					}
-					// else if selection ends on current segment...
-					else
-					{
-						S32 num_chars = selection_right - segment_line_start;
-						segmentp->getDimensions(segment_offset, num_chars, segment_width, segment_height);
-						selection_rect.mRight += segment_width;
-						
-						break;
-					}
-				}
-				selection_rects.push_back(selection_rect);
-			}
-		}
-		
+        std::vector<LLRect> selection_rects = getSelctionRects();
+
 		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
 		const LLColor4& color = mReadOnly ? mReadOnlyFgColor : mFgColor;
 		F32 alpha = hasFocus() ? 0.7f : 0.3f;
@@ -272,6 +198,7 @@ void LLScriptEditor::drawSelectionBackground()
 								 (1.f + color.mV[VGREEN]) * 0.5f,
 								 (1.f + color.mV[VBLUE]) * 0.5f,
 								 alpha);
+        LLRect content_display_rect = getVisibleDocumentRect();
 		
 		for (std::vector<LLRect>::iterator rect_it = selection_rects.begin();
 			 rect_it != selection_rects.end();
diff --git a/indra/newview/llscriptfloater.cpp b/indra/newview/llscriptfloater.cpp
index da912ef3d48de17770c67dcf42f71ce168cdb2ba..6a27ff3047900e03352bd1707d29728e18353b70 100644
--- a/indra/newview/llscriptfloater.cpp
+++ b/indra/newview/llscriptfloater.cpp
@@ -460,10 +460,11 @@ void LLScriptFloaterManager::onAddNotification(const LLUUID& notification_id)
 
 		if(it != mNotifications.end())
 		{
+			LLUUID old_id = it->first; // copy LLUUID to prevent use after free when it is erased below
 			LLChicletPanel * chiclet_panelp = LLChicletBar::getInstance()->getChicletPanel();
 			if (NULL != chiclet_panelp)
 			{
-				LLIMChiclet * chicletp = chiclet_panelp->findChiclet<LLIMChiclet>(it->first);
+				LLIMChiclet * chicletp = chiclet_panelp->findChiclet<LLIMChiclet>(old_id);
 				if (NULL != chicletp)
 				{
 					// Pass the new_message icon state further.
@@ -472,14 +473,14 @@ void LLScriptFloaterManager::onAddNotification(const LLUUID& notification_id)
 				}
 			}
 
-			LLScriptFloater* floater = LLFloaterReg::findTypedInstance<LLScriptFloater>("script_floater", it->first);
+			LLScriptFloater* floater = LLFloaterReg::findTypedInstance<LLScriptFloater>("script_floater", old_id);
 			if (floater)
 			{
 				// Generate chiclet with a "new message" indicator if a docked window was opened but not in focus. See EXT-3142.
 				set_new_message |= !floater->hasFocus();
 			}
 
-			removeNotification(it->first);
+			removeNotification(old_id);
 		}
 	}
 
diff --git a/indra/newview/llsettingsvo.cpp b/indra/newview/llsettingsvo.cpp
index 1930faa1a00eefb5ba1e02e3f325ea673a8a2efd..b1eed81476a321993fecbe1885a17ef9852afb1b 100644
--- a/indra/newview/llsettingsvo.cpp
+++ b/indra/newview/llsettingsvo.cpp
@@ -694,8 +694,8 @@ void LLSettingsVOSky::applySpecial(void *ptarget, bool force)
 
         LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky();
 
-        LLVector4 sunDiffuse = LLVector4(psky->getSunlightColor().mV);
-        LLVector4 moonDiffuse = LLVector4(psky->getMoonlightColor().mV);
+        LLVector4 sunDiffuse = LLVector4(LLVector3(psky->getSunlightColor().mV));
+        LLVector4 moonDiffuse = LLVector4(LLVector3(psky->getMoonlightColor().mV));
 
         shader->uniform4fv(LLShaderMgr::SUNLIGHT_COLOR, sunDiffuse);
         shader->uniform4fv(LLShaderMgr::MOONLIGHT_COLOR, moonDiffuse);
diff --git a/indra/newview/llsky.h b/indra/newview/llsky.h
index 8c0d70c16c93d3b310febd87a3b4fb75748e8c8b..ec0de1fbfde636f59ea1996c65853def4adf6cc2 100644
--- a/indra/newview/llsky.h
+++ b/indra/newview/llsky.h
@@ -39,7 +39,6 @@
 class LLViewerCamera;
 
 class LLVOWLSky;
-class LLVOWLClouds;
 
 
 class LLSky  
diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp
index 8134187c21edb6348791877789fc413c5cb62423..ed7e18fadc99b9a26aeb1e1d059d2832166b2b8d 100644
--- a/indra/newview/llsnapshotlivepreview.cpp
+++ b/indra/newview/llsnapshotlivepreview.cpp
@@ -233,7 +233,7 @@ bool LLSnapshotLivePreview::setSnapshotQuality(S32 quality, bool set_by_user)
     return false;
 }
 
-void LLSnapshotLivePreview::drawPreviewRect(S32 offset_x, S32 offset_y)
+void LLSnapshotLivePreview::drawPreviewRect(S32 offset_x, S32 offset_y, LLColor4 alpha_color)
 {
 	F32 line_width ; 
 	glGetFloatv(GL_LINE_WIDTH, &line_width) ;
@@ -246,7 +246,6 @@ void LLSnapshotLivePreview::drawPreviewRect(S32 offset_x, S32 offset_y)
 	//draw four alpha rectangles to cover areas outside of the snapshot image
 	if(!mKeepAspectRatio)
 	{
-		LLColor4 alpha_color(0.5f, 0.5f, 0.5f, 0.8f) ;
 		S32 dwl = 0, dwr = 0 ;
 		if(mThumbnailWidth > mPreviewRect.getWidth())
 		{
diff --git a/indra/newview/llsnapshotlivepreview.h b/indra/newview/llsnapshotlivepreview.h
index 683cd016d8387d05ddd6652fc8f224bce1357f9b..1f81307976797f0ac52a2b3641b0515a0d35cbb0 100644
--- a/indra/newview/llsnapshotlivepreview.h
+++ b/indra/newview/llsnapshotlivepreview.h
@@ -112,7 +112,7 @@ class LLSnapshotLivePreview : public LLView
 	BOOL setThumbnailImageSize() ;
 	void generateThumbnailImage(BOOL force_update = FALSE) ;
 	void resetThumbnailImage() { mThumbnailImage = NULL ; }
-	void drawPreviewRect(S32 offset_x, S32 offset_y) ;
+	void drawPreviewRect(S32 offset_x, S32 offset_y, LLColor4 alpha_color = LLColor4(0.5f, 0.5f, 0.5f, 0.8f));
 	void prepareFreezeFrame();
     
 	LLViewerTexture* getBigThumbnailImage();
diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp
index ea671a130e1c41d6b3c2d2a6b31bc6cb12a25348..60bada8f58133ed64a34ab41ba07a3186df4b219 100644
--- a/indra/newview/llspeakers.cpp
+++ b/indra/newview/llspeakers.cpp
@@ -982,7 +982,6 @@ void LLActiveSpeakerMgr::updateSpeakerList()
 	// clean up text only speakers
 	for (speaker_map_t::iterator speaker_it = mSpeakers.begin(); speaker_it != mSpeakers.end(); ++speaker_it)
 	{
-		LLUUID speaker_id = speaker_it->first;
 		LLSpeaker* speakerp = speaker_it->second;
 		if (speakerp->mStatus == LLSpeaker::STATUS_TEXT_ONLY)
 		{
diff --git a/indra/newview/llspeakingindicatormanager.cpp b/indra/newview/llspeakingindicatormanager.cpp
index 5ca1d4b4a57d597c558f4594052f70ed31acacb3..0111d8869cf9fd5ac6610c6248f8e779efbd6f35 100644
--- a/indra/newview/llspeakingindicatormanager.cpp
+++ b/indra/newview/llspeakingindicatormanager.cpp
@@ -51,6 +51,10 @@ class SpeakingIndicatorManager : public LLSingleton<SpeakingIndicatorManager>, L
 	LLSINGLETON(SpeakingIndicatorManager);
 	~SpeakingIndicatorManager();
 	LOG_CLASS(SpeakingIndicatorManager);
+
+protected:
+    void                cleanupSingleton();
+
 public:
 
 	/**
@@ -183,12 +187,16 @@ SpeakingIndicatorManager::SpeakingIndicatorManager()
 
 SpeakingIndicatorManager::~SpeakingIndicatorManager()
 {
-	// Don't use LLVoiceClient::getInstance() here without check
-	// singleton MAY have already been destroyed.
-	if(LLVoiceClient::instanceExists())
-	{
-		LLVoiceClient::getInstance()->removeObserver(this);
-	}
+}
+
+void SpeakingIndicatorManager::cleanupSingleton()
+{
+    // Don't use LLVoiceClient::getInstance() here without a check,
+    // singleton MAY have already been destroyed.
+    if (LLVoiceClient::instanceExists())
+    {
+        LLVoiceClient::getInstance()->removeObserver(this);
+    }
 }
 
 void SpeakingIndicatorManager::sOnCurrentChannelChanged(const LLUUID& /*session_id*/)
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 054e9530d445ec116614d3326e5efbc5f02a8dc3..6883ead5ee08e34f44f77309238d0ac69025b749 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -272,12 +272,10 @@ void show_first_run_dialog();
 bool first_run_dialog_callback(const LLSD& notification, const LLSD& response);
 void set_startup_status(const F32 frac, const std::string& string, const std::string& msg);
 bool login_alert_status(const LLSD& notification, const LLSD& response);
-void login_packet_failed(void**, S32 result);
 void use_circuit_callback(void**, S32 result);
 void register_viewer_callbacks(LLMessageSystem* msg);
 void asset_callback_nothing(const LLUUID&, LLAssetType::EType, void*, S32);
 bool callback_choose_gender(const LLSD& notification, const LLSD& response);
-void init_start_screen(S32 location_id);
 void release_start_screen();
 void reset_login();
 LLSD transform_cert_args(LLPointer<LLCertificate> cert);
@@ -1285,9 +1283,6 @@ bool idle_startup()
 		// Initialize classes w/graphics stuff.
 		//
 		LLViewerStatsRecorder::instance(); // Since textures work in threads
-		gTextureList.doPrefetchImages();		
-		display_startup();
-
 		LLSurface::initClasses();
 		display_startup();
 
@@ -1432,6 +1427,15 @@ bool idle_startup()
 	if (STATE_SEED_CAP_GRANTED == LLStartUp::getStartupState())
 	{
 		display_startup();
+
+        // These textures are not warrantied to be cached, so needs
+        // to hapen with caps granted
+        gTextureList.doPrefetchImages();
+
+        // will init images, should be done with caps, but before gSky.init()
+        LLEnvironment::getInstance()->initSingleton();
+
+        display_startup();
 		update_texture_fetch();
 		display_startup();
 
@@ -2526,8 +2530,6 @@ void use_circuit_callback(void**, S32 result)
 void register_viewer_callbacks(LLMessageSystem* msg)
 {
 	msg->setHandlerFuncFast(_PREHASH_LayerData,				process_layer_data );
-	msg->setHandlerFuncFast(_PREHASH_ImageData,				LLViewerTextureList::receiveImageHeader );
-	msg->setHandlerFuncFast(_PREHASH_ImagePacket,				LLViewerTextureList::receiveImagePacket );
 	msg->setHandlerFuncFast(_PREHASH_ObjectUpdate,				process_object_update );
 	msg->setHandlerFunc("ObjectUpdateCompressed",				process_compressed_object_update );
 	msg->setHandlerFunc("ObjectUpdateCached",					process_cached_object_update );
@@ -2913,6 +2915,7 @@ void reset_login()
 	gAgentWearables.cleanup();
 	gAgentCamera.cleanup();
 	gAgent.cleanup();
+    gSky.cleanup(); // mVOSkyp is an inworld object.
 	LLWorld::getInstance()->resetClass();
 
 	if ( gViewerWindow )
diff --git a/indra/newview/llsurfacepatch.cpp b/indra/newview/llsurfacepatch.cpp
index aeefcd6fb829d7e2fa08ed604ad45578d970d33a..449d3d95c8a4a954f85452116684939ad624ade4 100644
--- a/indra/newview/llsurfacepatch.cpp
+++ b/indra/newview/llsurfacepatch.cpp
@@ -714,7 +714,7 @@ BOOL LLSurfacePatch::updateTexture()
 				{
 					mVObjp->dirtyGeom();
 					gPipeline.markGLRebuild(mVObjp);
-					return TRUE;
+					return !mSTexUpdate;
 				}
 			}
 		}
diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp
index 67da311493767439a432fbfdcf98c068149874bf..5c6f7254f22469d0691b9d42431e2222b622f2b4 100644
--- a/indra/newview/lltexturecache.cpp
+++ b/indra/newview/lltexturecache.cpp
@@ -1646,6 +1646,12 @@ void LLTextureCache::purgeAllTextures(bool purge_directories)
 			{
 				gDirUtilp->deleteFilesInDir(dirname, mask);
 			}
+#if LL_WINDOWS
+            // Texture cache can be large and can take a while to remove
+            // assure OS that processes is alive and not hanging
+            MSG msg;
+            PeekMessage(&msg, 0, 0, 0, PM_NOREMOVE | PM_NOYIELD);
+#endif
 		}
 		gDirUtilp->deleteFilesInDir(mTexturesDirName, mask); // headers, fast cache
 		if (purge_directories)
diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp
index 8923f53cf5efc4a7d1273d9c2ea32cd30edcf4f3..6f6ca2be9bac616e26c4d81da2870c1dd8b810a8 100644
--- a/indra/newview/lltexturefetch.cpp
+++ b/indra/newview/lltexturefetch.cpp
@@ -282,7 +282,6 @@ static const char* e_state_name[] =
 	"LOAD_FROM_TEXTURE_CACHE",
 	"CACHE_POST",
 	"LOAD_FROM_NETWORK",
-	"LOAD_FROM_SIMULATOR",
 	"WAIT_HTTP_RESOURCE",
 	"WAIT_HTTP_RESOURCE2",
 	"SEND_HTTP_REQ",
@@ -456,7 +455,6 @@ class LLTextureFetchWorker : public LLWorkerClass, public LLCore::HttpHandler
 		LOAD_FROM_TEXTURE_CACHE,
 		CACHE_POST,
 		LOAD_FROM_NETWORK,
-		LOAD_FROM_SIMULATOR,
 		WAIT_HTTP_RESOURCE,				// Waiting for HTTP resources
 		WAIT_HTTP_RESOURCE2,			// Waiting for HTTP resources
 		SEND_HTTP_REQ,					// Commit to sending as HTTP
@@ -497,8 +495,6 @@ class LLTextureFetchWorker : public LLWorkerClass, public LLCore::HttpHandler
 	// Locks:  Mw
 	void clearPackets();
 
-	// Locks:  Mw
-	void setupPacketData();
 
 	// Locks:  Mw (ctor invokes without lock)
 	U32 calcWorkPriority();
@@ -506,10 +502,6 @@ class LLTextureFetchWorker : public LLWorkerClass, public LLCore::HttpHandler
 	// Locks:  Mw
 	void removeFromCache();
 
-	// Threads:  Ttf
-	// Locks:  Mw
-	bool processSimulatorPackets();
-
 	// Threads:  Ttf
 	bool writeToCacheComplete();
 	
@@ -612,8 +604,7 @@ class LLTextureFetchWorker : public LLWorkerClass, public LLCore::HttpHandler
 	BOOL mHaveAllData;
 	BOOL mInLocalCache;
 	BOOL mInCache;
-	bool                        mCanUseHTTP,
-								mCanUseNET ; //can get from asset server.
+    bool                        mCanUseHTTP;
 	S32 mRetryAttempt;
 	S32 mActiveCount;
 	LLCore::HttpStatus mGetStatus;
@@ -885,7 +876,6 @@ const char* sStateDescs[] = {
 	"LOAD_FROM_TEXTURE_CACHE",
 	"CACHE_POST",
 	"LOAD_FROM_NETWORK",
-	"LOAD_FROM_SIMULATOR",
 	"WAIT_HTTP_RESOURCE",
 	"WAIT_HTTP_RESOURCE2",
 	"SEND_HTTP_REQ",
@@ -897,7 +887,7 @@ const char* sStateDescs[] = {
 	"DONE"
 };
 
-const std::set<S32> LOGGED_STATES = { LLTextureFetchWorker::LOAD_FROM_TEXTURE_CACHE, LLTextureFetchWorker::LOAD_FROM_NETWORK, LLTextureFetchWorker::LOAD_FROM_SIMULATOR, 
+const std::set<S32> LOGGED_STATES = { LLTextureFetchWorker::LOAD_FROM_TEXTURE_CACHE, LLTextureFetchWorker::LOAD_FROM_NETWORK,
 										LLTextureFetchWorker::WAIT_HTTP_REQ, LLTextureFetchWorker::DECODE_IMAGE_UPDATE, LLTextureFetchWorker::WAIT_ON_WRITE };
 
 // static
@@ -972,8 +962,6 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher,
 	  mResourceWaitCount(0U),
 	  mFetchRetryPolicy(10.0,3600.0,2.0,10)
 {
-	mCanUseNET = mUrl.empty() ;
-	
 	calcWorkPriority();
 	mType = host.isOk() ? LLImageBase::TYPE_AVATAR_BAKE : LLImageBase::TYPE_NORMAL;
 // 	LL_INFOS(LOG_TXT) << "Create: " << mID << " mHost:" << host << " Discard=" << discard << LL_ENDL;
@@ -1037,39 +1025,6 @@ void LLTextureFetchWorker::clearPackets()
 	mFirstPacket = 0;
 }
 
-// Locks:  Mw
-void LLTextureFetchWorker::setupPacketData()
-{
-	S32 data_size = 0;
-	if (mFormattedImage.notNull())
-	{
-		data_size = mFormattedImage->getDataSize();
-	}
-	if (data_size > 0)
-	{
-		// Only used for simulator requests
-		mFirstPacket = (data_size - FIRST_PACKET_SIZE) / MAX_IMG_PACKET_SIZE + 1;
-		if (FIRST_PACKET_SIZE + (mFirstPacket-1) * MAX_IMG_PACKET_SIZE != data_size)
-		{
-			LL_WARNS(LOG_TXT) << "Bad CACHED TEXTURE size: " << data_size << " removing." << LL_ENDL;
-			removeFromCache();
-			resetFormattedData();
-			clearPackets();
-		}
-		else if (mFileSize > 0)
-		{
-			mLastPacket = mFirstPacket-1;
-			mTotalPackets = (mFileSize - FIRST_PACKET_SIZE + MAX_IMG_PACKET_SIZE-1) / MAX_IMG_PACKET_SIZE + 1;
-		}
-		else
-		{
-			// This file was cached using HTTP so we have to refetch the first packet
-			resetFormattedData();
-			clearPackets();
-		}
-	}
-}
-
 // Locks:  Mw (ctor invokes without lock)
 U32 LLTextureFetchWorker::calcWorkPriority()
 {
@@ -1177,13 +1132,13 @@ bool LLTextureFetchWorker::doWork(S32 param)
 
 	if(mImagePriority < F_ALMOST_ZERO)
 	{
-		if (mState == INIT || mState == LOAD_FROM_NETWORK || mState == LOAD_FROM_SIMULATOR)
+		if (mState == INIT || mState == LOAD_FROM_NETWORK)
 		{
 			LL_DEBUGS(LOG_TXT) << mID << " abort: mImagePriority < F_ALMOST_ZERO" << LL_ENDL;
 			return true; // abort
 		}
 	}
-	if(mState > CACHE_POST && !mCanUseNET && !mCanUseHTTP)
+	if(mState > CACHE_POST && !mCanUseHTTP)
 	{
 		//nowhere to get data, abort.
 		LL_WARNS(LOG_TXT) << mID << " abort, nowhere to get data" << LL_ENDL;
@@ -1387,10 +1342,14 @@ bool LLTextureFetchWorker::doWork(S32 param)
 		if ( use_http && mCanUseHTTP && mUrl.empty())//get http url.
 		{
 			LLViewerRegion* region = NULL;
-			if (mHost.isInvalid())
-				region = gAgent.getRegion();
-			else
-				region = LLWorld::getInstance()->getRegion(mHost);
+            if (mHost.isInvalid())
+            {
+                region = gAgent.getRegion();
+            }
+            else if (LLWorld::instanceExists())
+            {
+                region = LLWorld::getInstance()->getRegion(mHost);
+            }
 
 			if (region)
 			{
@@ -1408,14 +1367,14 @@ bool LLTextureFetchWorker::doWork(S32 param)
 				else
 				{
 					mCanUseHTTP = false ;
-					LL_DEBUGS(LOG_TXT) << "Texture not available via HTTP: empty URL." << LL_ENDL;
+					LL_WARNS(LOG_TXT) << "Texture not available via HTTP: empty URL." << LL_ENDL;
 				}
 			}
 			else
 			{
 				// This will happen if not logged in or if a region deoes not have HTTP Texture enabled
 				//LL_WARNS(LOG_TXT) << "Region not found for host: " << mHost << LL_ENDL;
-				LL_DEBUGS(LOG_TXT) << "Texture not available via HTTP: no region " << mUrl << LL_ENDL;
+                LL_WARNS(LOG_TXT) << "Texture not available via HTTP: no region " << mUrl << LL_ENDL;
 				mCanUseHTTP = false;
 			}
 		}
@@ -1434,84 +1393,12 @@ bool LLTextureFetchWorker::doWork(S32 param)
 			}
 			// don't return, fall through to next state
 		}
-		else if (mSentRequest == UNSENT && mCanUseNET)
-		{
-			// Add this to the network queue and sit here.
-			// LLTextureFetch::update() will send off a request which will change our state
-			mWriteToCacheState = CAN_WRITE ;
-			mRequestedSize = mDesiredSize;
-			mRequestedDiscard = mDesiredDiscard;
-			mSentRequest = QUEUED;
-			mFetcher->addToNetworkQueue(this);
-			recordTextureStart(false);
-			setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority);
-			
-			return false;
-		}
 		else
 		{
-			// Shouldn't need to do anything here
-			//llassert_always(mFetcher->mNetworkQueue.find(mID) != mFetcher->mNetworkQueue.end());
-			// Make certain this is in the network queue
-			//mFetcher->addToNetworkQueue(this);
-			//recordTextureStart(false);
-			//setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority);
-
 			return false;
 		}
 	}
 	
-	if (mState == LOAD_FROM_SIMULATOR)
-	{
-		if (mFormattedImage.isNull())
-		{
-			mFormattedImage = new LLImageJ2C;
-		}
-		if (processSimulatorPackets())
-		{
-            // Capture some measure of total size for metrics
-            F64 byte_count = 0;
-            if (mLastPacket >= mFirstPacket)
-            {
-                for (S32 i=mFirstPacket; i<=mLastPacket; i++)
-                {
-                    llassert_always((i>=0) && (i<mPackets.size()));
-                    if (mPackets[i])
-                    {
-                        byte_count += mPackets[i]->mSize;
-                    }
-                }
-            }
-
-			LL_DEBUGS(LOG_TXT) << mID << ": Loaded from Sim. Bytes: " << mFormattedImage->getDataSize() << LL_ENDL;
-			mFetcher->removeFromNetworkQueue(this, false);
-			if (mFormattedImage.isNull() || !mFormattedImage->getDataSize())
-			{
-				// processSimulatorPackets() failed
-// 				LL_WARNS(LOG_TXT) << "processSimulatorPackets() failed to load buffer" << LL_ENDL;
-				LL_WARNS(LOG_TXT) << mID << " processSimulatorPackets() failed to load buffer" << LL_ENDL;
-				return true; // failed
-			}
-			setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);
-			if (mLoadedDiscard < 0)
-			{
-				LL_WARNS(LOG_TXT) << mID << " mLoadedDiscard is " << mLoadedDiscard
-								  << ", should be >=0" << LL_ENDL;
-			}
-			setState(DECODE_IMAGE);
-			mWriteToCacheState = SHOULD_WRITE;
-
-			recordTextureDone(false, byte_count);
-		}
-		else
-		{
-			mFetcher->addToNetworkQueue(this); // failsafe
-			setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority);
-			recordTextureStart(false);
-		}
-		return false;
-	}
-	
 	if (mState == WAIT_HTTP_RESOURCE)
 	{
 		// NOTE:
@@ -1553,8 +1440,6 @@ bool LLTextureFetchWorker::doWork(S32 param)
 			LL_WARNS(LOG_TXT) << mID << " abort: SEND_HTTP_REQ but !mCanUseHTTP" << LL_ENDL;
 			return true; // abort
 		}
-
-		mFetcher->removeFromNetworkQueue(this, false);
 			
 		S32 cur_size = 0;
 		if (mFormattedImage.notNull())
@@ -1701,17 +1586,6 @@ bool LLTextureFetchWorker::doWork(S32 param)
 						}
 						return true; 
 					}
-
-					// roll back to try UDP
-					if (mCanUseNET)
-					{
-						setState(INIT);
-						mCanUseHTTP = false;
-						mUrl.clear();
-						setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);
-						releaseHttpSemaphore();
-						return false;
-					}
 				}
 				else if (http_service_unavail == mGetStatus)
 				{
@@ -2280,69 +2154,6 @@ void LLTextureFetchWorker::removeFromCache()
 }
 
 
-//////////////////////////////////////////////////////////////////////////////
-
-// Threads:  Ttf
-// Locks:  Mw
-bool LLTextureFetchWorker::processSimulatorPackets()
-{
-	if (mFormattedImage.isNull() || mRequestedSize < 0)
-	{
-		// not sure how we got here, but not a valid state, abort!
-		llassert_always(mDecodeHandle == 0);
-		mFormattedImage = NULL;
-		return true;
-	}
-	
-	if (mLastPacket >= mFirstPacket)
-	{
-		S32 buffer_size = mFormattedImage->getDataSize();
-		for (S32 i = mFirstPacket; i<=mLastPacket; i++)
-		{
-            llassert_always((i>=0) && (i<mPackets.size()));
-			llassert_always(mPackets[i]);
-			buffer_size += mPackets[i]->mSize;
-		}
-		bool have_all_data = mLastPacket >= mTotalPackets-1;
-		if (mRequestedSize <= 0)
-		{
-			// We received a packed but haven't requested anything yet (edge case)
-			// Return true (we're "done") since we didn't request anything
-			return true;
-		}
-		if (buffer_size >= mRequestedSize || have_all_data)
-		{
-			/// We have enough (or all) data
-			if (have_all_data)
-			{
-				mHaveAllData = TRUE;
-			}
-			S32 cur_size = mFormattedImage->getDataSize();
-			if (buffer_size > cur_size)
-			{
-				/// We have new data
-				U8* buffer = (U8*)ll_aligned_malloc_16(buffer_size);
-				S32 offset = 0;
-				if (cur_size > 0 && mFirstPacket > 0)
-				{
-					memcpy(buffer, mFormattedImage->getData(), cur_size);
-					offset = cur_size;
-				}
-				for (S32 i=mFirstPacket; i<=mLastPacket; i++)
-				{
-					memcpy(buffer + offset, mPackets[i]->mData, mPackets[i]->mSize);
-					offset += mPackets[i]->mSize;
-				}
-				// NOTE: setData releases current data
-				mFormattedImage->setData(buffer, buffer_size);
-			}
-			mLoadedDiscard = mRequestedDiscard;
-			return true;
-		}
-	}
-	return false;
-}
-
 //////////////////////////////////////////////////////////////////////////////
 
 // Threads:  Ttf
@@ -2813,40 +2624,6 @@ bool LLTextureFetch::createRequest(FTType f_type, const std::string& url, const
 }
 
 
-// Threads:  T* (but Ttf in practice)
-
-// protected
-void LLTextureFetch::addToNetworkQueue(LLTextureFetchWorker* worker)
-{
-	lockQueue();														// +Mfq
-	bool in_request_map = (mRequestMap.find(worker->mID) != mRequestMap.end()) ;
-	unlockQueue();														// -Mfq
-
-	LLMutexLock lock(&mNetworkQueueMutex);								// +Mfnq		
-	if (in_request_map)
-	{
-		// only add to the queue if in the request map
-		// i.e. a delete has not been requested
-		mNetworkQueue.insert(worker->mID);
-	}
-	for (cancel_queue_t::iterator iter1 = mCancelQueue.begin();
-		 iter1 != mCancelQueue.end(); ++iter1)
-	{
-		iter1->second.erase(worker->mID);
-	}
-}																		// -Mfnq
-
-// Threads:  T*
-void LLTextureFetch::removeFromNetworkQueue(LLTextureFetchWorker* worker, bool cancel)
-{
-	LLMutexLock lock(&mNetworkQueueMutex);								// +Mfnq
-	size_t erased = mNetworkQueue.erase(worker->mID);
-	if (cancel && erased > 0)
-	{
-		mCancelQueue[worker->mHost].insert(worker->mID);
-	}
-}																		// -Mfnq
-
 // Threads:  T*
 //
 // protected
@@ -2880,7 +2657,6 @@ void LLTextureFetch::deleteRequest(const LLUUID& id, bool cancel)
 		unlockQueue();													// -Mfq
 
 		llassert_always(erased_1 > 0) ;
-		removeFromNetworkQueue(worker, cancel);
 		llassert_always(!(worker->getFlags(LLWorkerClass::WCF_DELETE_REQUESTED))) ;
 
 		worker->scheduleDelete();	
@@ -2908,7 +2684,6 @@ void LLTextureFetch::removeRequest(LLTextureFetchWorker* worker, bool cancel)
 	unlockQueue();														// -Mfq
 
 	llassert_always(erased_1 > 0) ;
-	removeFromNetworkQueue(worker, cancel);
 	llassert_always(!(worker->getFlags(LLWorkerClass::WCF_DELETE_REQUESTED))) ;
 
 	worker->scheduleDelete();	
@@ -3197,17 +2972,6 @@ size_t LLTextureFetch::update(F32 max_time_ms)
 
 	size_t res = LLWorkerThread::update(max_time_ms);
 	
-	if (!mDebugPause)
-	{
-		// this is the startup state when send_complete_agent_movement() message is sent.
-		// Before this, the RequestImages message sent by sendRequestListToSimulators 
-		// won't work so don't bother trying
-		if (LLStartUp::getStartupState() > STATE_AGENT_SEND)
-		{
-			sendRequestListToSimulators();			
-		}
-	}
-
 	if (!mThreaded)
 	{
 		commonUpdate();
@@ -3298,202 +3062,6 @@ void LLTextureFetch::threadedUpdate()
 
 //////////////////////////////////////////////////////////////////////////////
 
-// Threads:  Tmain
-void LLTextureFetch::sendRequestListToSimulators()
-{
-	// All requests
-	const F32 REQUEST_DELTA_TIME = 0.10f; // 10 fps
-	
-	// Sim requests
-	const S32 IMAGES_PER_REQUEST = 50;
-	const F32 SIM_LAZY_FLUSH_TIMEOUT = 10.0f; // temp
-	const F32 MIN_REQUEST_TIME = 1.0f;
-	const F32 MIN_DELTA_PRIORITY = 1000.f;
-
-	// Periodically, gather the list of textures that need data from the network
-	// And send the requests out to the simulators
-	static LLFrameTimer timer;
-	if (timer.getElapsedTimeF32() < REQUEST_DELTA_TIME)
-	{
-		return;
-	}
-	timer.reset();
-	
-	// Send requests
-	typedef std::set<LLTextureFetchWorker*,LLTextureFetchWorker::Compare> request_list_t;
-	typedef std::map< LLHost, request_list_t > work_request_map_t;
-	work_request_map_t requests;
-	{
-		LLMutexLock lock2(&mNetworkQueueMutex);							// +Mfnq
-		for (queue_t::iterator iter = mNetworkQueue.begin(); iter != mNetworkQueue.end(); )
-		{
-			queue_t::iterator curiter = iter++;
-			LLTextureFetchWorker* req = getWorker(*curiter);
-			if (!req)
-			{
-				mNetworkQueue.erase(curiter);
-				continue; // paranoia
-			}
-			if ((req->mState != LLTextureFetchWorker::LOAD_FROM_NETWORK) &&
-				(req->mState != LLTextureFetchWorker::LOAD_FROM_SIMULATOR))
-			{
-				// We already received our URL, remove from the queue
-				LL_WARNS(LOG_TXT) << "Worker: " << req->mID << " in mNetworkQueue but in wrong state: " << req->mState << LL_ENDL;
-				mNetworkQueue.erase(curiter);
-				continue;
-			}
-			if (req->mID == mDebugID)
-			{
-				mDebugCount++; // for setting breakpoints
-			}
-			if (req->mSentRequest == LLTextureFetchWorker::SENT_SIM &&
-				req->mTotalPackets > 0 &&
-				req->mLastPacket >= req->mTotalPackets-1)
-			{
-				// We have all the packets... make sure this is high priority
-// 			req->setPriority(LLWorkerThread::PRIORITY_HIGH | req->mWorkPriority);
-				continue;
-			}
-			F32 elapsed = req->mRequestedDeltaTimer.getElapsedTimeF32();
-			{
-				F32 delta_priority = llabs(req->mRequestedPriority - req->mImagePriority);
-				if ((req->mSimRequestedDiscard != req->mDesiredDiscard) ||
-					(delta_priority > MIN_DELTA_PRIORITY && elapsed >= MIN_REQUEST_TIME) ||
-					(elapsed >= SIM_LAZY_FLUSH_TIMEOUT))
-				{
-					requests[req->mHost].insert(req);
-				}
-			}
-		}
-	}																	// -Mfnq
-
-	for (work_request_map_t::iterator iter1 = requests.begin();
-		 iter1 != requests.end(); ++iter1)
-	{
-		LLHost host = iter1->first;
-		// invalid host = use agent host
-		if (host.isInvalid())
-		{
-			host = gAgent.getRegionHost();
-		}
-
-		S32 sim_request_count = 0;
-		
-		for (request_list_t::iterator iter2 = iter1->second.begin();
-			 iter2 != iter1->second.end(); ++iter2)
-		{
-			LLTextureFetchWorker* req = *iter2;
-			if (gMessageSystem)
-			{
-				if (req->mSentRequest != LLTextureFetchWorker::SENT_SIM)
-				{
-					// Initialize packet data based on data read from cache
-					req->lockWorkMutex();								// +Mw
-					req->setupPacketData();
-					req->unlockWorkMutex();								// -Mw		
-				}
-				if (0 == sim_request_count)
-				{
-					gMessageSystem->newMessageFast(_PREHASH_RequestImage);
-					gMessageSystem->nextBlockFast(_PREHASH_AgentData);
-					gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
-					gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
-				}
-				S32 packet = req->mLastPacket + 1;
-				gMessageSystem->nextBlockFast(_PREHASH_RequestImage);
-				gMessageSystem->addUUIDFast(_PREHASH_Image, req->mID);
-				gMessageSystem->addS8Fast(_PREHASH_DiscardLevel, (S8)req->mDesiredDiscard);
-				gMessageSystem->addF32Fast(_PREHASH_DownloadPriority, req->mImagePriority);
-				gMessageSystem->addU32Fast(_PREHASH_Packet, packet);
-				gMessageSystem->addU8Fast(_PREHASH_Type, req->mType);
-// 				LL_INFOS(LOG_TXT) << "IMAGE REQUEST: " << req->mID << " Discard: " << req->mDesiredDiscard
-// 						<< " Packet: " << packet << " Priority: " << req->mImagePriority << LL_ENDL;
-
-				static LLCachedControl<bool> log_to_viewer_log(gSavedSettings,"LogTextureDownloadsToViewerLog", false);
-				static LLCachedControl<bool> log_to_sim(gSavedSettings,"LogTextureDownloadsToSimulator", false);
-				if (log_to_viewer_log || log_to_sim)
-				{
-					mTextureInfo.setRequestStartTime(req->mID, LLTimer::getTotalTime());
-					mTextureInfo.setRequestOffset(req->mID, 0);
-					mTextureInfo.setRequestSize(req->mID, 0);
-					mTextureInfo.setRequestType(req->mID, LLTextureInfoDetails::REQUEST_TYPE_UDP);
-				}
-
-				req->lockWorkMutex();									// +Mw
-				req->mSentRequest = LLTextureFetchWorker::SENT_SIM;
-				req->mSimRequestedDiscard = req->mDesiredDiscard;
-				req->mRequestedPriority = req->mImagePriority;
-				req->mRequestedDeltaTimer.reset();
-				req->unlockWorkMutex();									// -Mw
-				sim_request_count++;
-				if (sim_request_count >= IMAGES_PER_REQUEST)
-				{
-// 					LL_INFOS(LOG_TXT) << "REQUESTING " << sim_request_count << " IMAGES FROM HOST: " << host.getIPString() << LL_ENDL;
-
-					gMessageSystem->sendSemiReliable(host, NULL, NULL);
-					sim_request_count = 0;
-				}
-			}
-		}
-		if (gMessageSystem && sim_request_count > 0 && sim_request_count < IMAGES_PER_REQUEST)
-		{
-// 			LL_INFOS(LOG_TXT) << "REQUESTING " << sim_request_count << " IMAGES FROM HOST: " << host.getIPString() << LL_ENDL;
-			gMessageSystem->sendSemiReliable(host, NULL, NULL);
-			sim_request_count = 0;
-		}
-	}
-	
-	// Send cancelations
-	{
-		LLMutexLock lock2(&mNetworkQueueMutex);							// +Mfnq
-		if (gMessageSystem && !mCancelQueue.empty())
-		{
-			for (cancel_queue_t::iterator iter1 = mCancelQueue.begin();
-				 iter1 != mCancelQueue.end(); ++iter1)
-			{
-				LLHost host = iter1->first;
-				if (host.isInvalid())
-				{
-					host = gAgent.getRegionHost();
-				}
-				S32 request_count = 0;
-				for (queue_t::iterator iter2 = iter1->second.begin();
-					 iter2 != iter1->second.end(); ++iter2)
-				{
-					if (0 == request_count)
-					{
-						gMessageSystem->newMessageFast(_PREHASH_RequestImage);
-						gMessageSystem->nextBlockFast(_PREHASH_AgentData);
-						gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
-						gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
-					}
-					gMessageSystem->nextBlockFast(_PREHASH_RequestImage);
-					gMessageSystem->addUUIDFast(_PREHASH_Image, *iter2);
-					gMessageSystem->addS8Fast(_PREHASH_DiscardLevel, -1);
-					gMessageSystem->addF32Fast(_PREHASH_DownloadPriority, 0);
-					gMessageSystem->addU32Fast(_PREHASH_Packet, 0);
-					gMessageSystem->addU8Fast(_PREHASH_Type, 0);
-// 				LL_INFOS(LOG_TXT) << "CANCELING IMAGE REQUEST: " << (*iter2) << LL_ENDL;
-
-					request_count++;
-					if (request_count >= IMAGES_PER_REQUEST)
-					{
-						gMessageSystem->sendSemiReliable(host, NULL, NULL);
-						request_count = 0;
-					}
-				}
-				if (request_count > 0 && request_count < IMAGES_PER_REQUEST)
-				{
-					gMessageSystem->sendSemiReliable(host, NULL, NULL);
-				}
-			}
-			mCancelQueue.clear();
-		}
-	}																	// -Mfnq
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
 // Threads:  T*
 // Locks:  Mw
 bool LLTextureFetchWorker::insertPacket(S32 index, U8* data, S32 size)
@@ -3556,138 +3124,6 @@ void LLTextureFetchWorker::setState(e_state new_state)
 	mState = new_state;
 }
 
-// Threads:  T*
-bool LLTextureFetch::receiveImageHeader(const LLHost& host, const LLUUID& id, U8 codec, U16 packets, U32 totalbytes,
-										U16 data_size, U8* data)
-{
-	LLTextureFetchWorker* worker = getWorker(id);
-	bool res = true;
-
-	++mPacketCount;
-	
-	if (!worker)
-	{
-// 		LL_WARNS(LOG_TXT) << "Received header for non active worker: " << id << LL_ENDL;
-		res = false;
-	}
-	else if (worker->mState != LLTextureFetchWorker::LOAD_FROM_NETWORK ||
-			 worker->mSentRequest != LLTextureFetchWorker::SENT_SIM)
-	{
-// 		LL_WARNS(LOG_TXT) << "receiveImageHeader for worker: " << id
-// 				<< " in state: " << LLTextureFetchWorker::sStateDescs[worker->mState]
-// 				<< " sent: " << worker->mSentRequest << LL_ENDL;
-		res = false;
-	}
-	else if (worker->mLastPacket != -1)
-	{
-		// check to see if we've gotten this packet before
-// 		LL_WARNS(LOG_TXT) << "Received duplicate header for: " << id << LL_ENDL;
-		res = false;
-	}
-	else if (!data_size)
-	{
-// 		LL_WARNS(LOG_TXT) << "Img: " << id << ":" << " Empty Image Header" << LL_ENDL;
-		res = false;
-	}
-	if (!res)
-	{
-		mNetworkQueueMutex.lock();										// +Mfnq
-		++mBadPacketCount;
-		mCancelQueue[host].insert(id);
-		mNetworkQueueMutex.unlock();									// -Mfnq 
-		return false;
-	}
-
-	LLViewerStatsRecorder::instance().textureFetch(data_size);
-	LLViewerStatsRecorder::instance().log(0.1f);
-
-	worker->lockWorkMutex();
-
-
-	//	Copy header data into image object
-	worker->mImageCodec = codec;
-	worker->mTotalPackets = packets;
-	worker->mFileSize = (S32)totalbytes;	
-	llassert_always(totalbytes > 0);
-	llassert_always(data_size == FIRST_PACKET_SIZE || data_size == worker->mFileSize);
-	res = worker->insertPacket(0, data, data_size);
-	worker->setPriority(LLWorkerThread::PRIORITY_HIGH | worker->mWorkPriority);
-	worker->setState(LLTextureFetchWorker::LOAD_FROM_SIMULATOR);
-	worker->unlockWorkMutex();											// -Mw
-	return res;
-}
-
-
-// Threads:  T*
-bool LLTextureFetch::receiveImagePacket(const LLHost& host, const LLUUID& id, U16 packet_num, U16 data_size, U8* data)
-{
-	LLTextureFetchWorker* worker = getWorker(id);
-	bool res = true;
-
-	++mPacketCount;
-	
-	if (!worker)
-	{
-// 		LL_WARNS(LOG_TXT) << "Received packet " << packet_num << " for non active worker: " << id << LL_ENDL;
-		res = false;
-	}
-	else if (worker->mLastPacket == -1)
-	{
-// 		LL_WARNS(LOG_TXT) << "Received packet " << packet_num << " before header for: " << id << LL_ENDL;
-		res = false;
-	}
-	else if (!data_size)
-	{
-// 		LL_WARNS(LOG_TXT) << "Img: " << id << ":" << " Empty Image Header" << LL_ENDL;
-		res = false;
-	}
-	if (!res)
-	{
-		mNetworkQueueMutex.lock();										// +Mfnq
-		++mBadPacketCount;
-		mCancelQueue[host].insert(id);
-		mNetworkQueueMutex.unlock();									// -Mfnq
-		return false;
-	}
-	
-	LLViewerStatsRecorder::instance().textureFetch(data_size);
-	LLViewerStatsRecorder::instance().log(0.1f);
-
-	worker->lockWorkMutex();
-
-	
-	res = worker->insertPacket(packet_num, data, data_size);
-	
-	if ((worker->mState == LLTextureFetchWorker::LOAD_FROM_SIMULATOR) ||
-		(worker->mState == LLTextureFetchWorker::LOAD_FROM_NETWORK))
-	{
-		worker->setPriority(LLWorkerThread::PRIORITY_HIGH | worker->mWorkPriority);
-		worker->setState(LLTextureFetchWorker::LOAD_FROM_SIMULATOR);
-	}
-	else
-	{
-// 		LL_WARNS(LOG_TXT) << "receiveImagePacket " << packet_num << "/" << worker->mLastPacket << " for worker: " << id
-// 				<< " in state: " << LLTextureFetchWorker::sStateDescs[worker->mState] << LL_ENDL;
-		removeFromNetworkQueue(worker, true); // failsafe
-	}
-
-	if (packet_num >= (worker->mTotalPackets - 1))
-	{
-		static LLCachedControl<bool> log_to_viewer_log(gSavedSettings,"LogTextureDownloadsToViewerLog", false);
-		static LLCachedControl<bool> log_to_sim(gSavedSettings,"LogTextureDownloadsToSimulator", false);
-
-		if (log_to_viewer_log || log_to_sim)
-		{
-			U64Microseconds timeNow = LLTimer::getTotalTime();
-			mTextureInfoMainThread.setRequestSize(id, worker->mFileSize);
-			mTextureInfoMainThread.setRequestCompleteTimeAndLog(id, timeNow);
-		}
-	}
-	worker->unlockWorkMutex();											// -Mw
-
-	return res;
-}
-
 //////////////////////////////////////////////////////////////////////////////
 
 // Threads:  T*
@@ -3726,13 +3162,7 @@ S32 LLTextureFetch::getFetchState(const LLUUID& id, F32& data_progress_p, F32& r
 		request_dtime = worker->mRequestedDeltaTimer.getElapsedTimeF32();
 		if (worker->mFileSize > 0)
 		{
-			if (state == LLTextureFetchWorker::LOAD_FROM_SIMULATOR)
-			{
-				S32 data_size = FIRST_PACKET_SIZE + (worker->mLastPacket-1) * MAX_IMG_PACKET_SIZE;
-				data_size = llmax(data_size, 0);
-				data_progress = (F32)data_size / (F32)worker->mFileSize;
-			}
-			else if (worker->mFormattedImage.notNull())
+			if (worker->mFormattedImage.notNull())
 			{
 				data_progress = (F32)worker->mFormattedImage->getDataSize() / (F32)worker->mFileSize;
 			}
diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h
index e2d2aa365c0921a5d2a940099912e225260d4ecf..611a7d641966c88653e293b116697b41c395ae5b 100644
--- a/indra/newview/lltexturefetch.h
+++ b/indra/newview/lltexturefetch.h
@@ -101,12 +101,6 @@ class LLTextureFetch : public LLWorkerThread
 	// Threads:  T*
 	bool updateRequestPriority(const LLUUID& id, F32 priority);
 
-    // Threads:  T*
-	bool receiveImageHeader(const LLHost& host, const LLUUID& id, U8 codec, U16 packets, U32 totalbytes, U16 data_size, U8* data);
-
-    // Threads:  T*
-	bool receiveImagePacket(const LLHost& host, const LLUUID& id, U16 packet_num, U16 data_size, U8* data);
-
     // Threads:  T* (but not safe)
 	void setTextureBandwidth(F32 bandwidth) { mTextureBandwidth = bandwidth; }
 	
@@ -227,12 +221,6 @@ class LLTextureFetch : public LLWorkerThread
 	// ----------------------------------
 	
 protected:
-	// Threads:  T* (but Ttf in practice)
-	void addToNetworkQueue(LLTextureFetchWorker* worker);
-
-	// Threads:  T*
-	void removeFromNetworkQueue(LLTextureFetchWorker* worker, bool cancel);
-
     // Threads:  T*
 	void addToHTTPQueue(const LLUUID& id);
 
@@ -251,9 +239,6 @@ class LLTextureFetch : public LLWorkerThread
 	bool runCondition();
 
 private:
-    // Threads:  Tmain
-	void sendRequestListToSimulators();
-	
 	// Threads:  Ttf
 	/*virtual*/ void startThread(void);
 	
@@ -319,7 +304,7 @@ class LLTextureFetch : public LLWorkerThread
 
 private:
 	LLMutex mQueueMutex;        //to protect mRequestMap and mCommands only
-	LLMutex mNetworkQueueMutex; //to protect mNetworkQueue, mHTTPTextureQueue and mCancelQueue.
+	LLMutex mNetworkQueueMutex; //to protect mHTTPTextureQueue
 
 	LLTextureCache* mTextureCache;
 	LLImageDecodeThread* mImageDecodeThread;
@@ -330,10 +315,8 @@ class LLTextureFetch : public LLWorkerThread
 
 	// Set of requests that require network data
 	typedef std::set<LLUUID> queue_t;
-	queue_t mNetworkQueue;												// Mfnq
 	queue_t mHTTPTextureQueue;											// Mfnq
 	typedef std::map<LLHost,std::set<LLUUID> > cancel_queue_t;
-	cancel_queue_t mCancelQueue;										// Mfnq
 	F32 mTextureBandwidth;												// <none>
 	F32 mMaxBandwidth;													// Mfnq
 	LLTextureInfo mTextureInfo;
diff --git a/indra/newview/lltextureview.cpp b/indra/newview/lltextureview.cpp
index b74577315e30f33970719889e3b2b691a65351ec..cf9211767e1ea50d9df264ab93f183e168686ebf 100644
--- a/indra/newview/lltextureview.cpp
+++ b/indra/newview/lltextureview.cpp
@@ -234,7 +234,6 @@ void LLTextureBar::draw()
 		{ "DSK", LLColor4::cyan },	// LOAD_FROM_TEXTURE_CACHE
 		{ "DSK", LLColor4::blue },	// CACHE_POST
 		{ "NET", LLColor4::green },	// LOAD_FROM_NETWORK
-		{ "SIM", LLColor4::green },	// LOAD_FROM_SIMULATOR
 		{ "HTW", LLColor4::green },	// WAIT_HTTP_RESOURCE
 		{ "HTW", LLColor4::green },	// WAIT_HTTP_RESOURCE2
 		{ "REQ", LLColor4::yellow },// SEND_HTTP_REQ
diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp
index 024f25bc98a2a7f1c8d1f2d30311e5c9fae386c6..bf3f4c1e8891b266d2de877eaa50b47e3ca19616 100644
--- a/indra/newview/lltoastnotifypanel.cpp
+++ b/indra/newview/lltoastnotifypanel.cpp
@@ -89,6 +89,7 @@ LLButton* LLToastNotifyPanel::createButton(const LLSD& form_element, BOOL is_opt
 	const LLFontGL* font = make_small_btn ? sFontSmall: sFont; // for block and ignore buttons in script dialog
 	p.name = form_element["name"].asString();
 	p.label = form_element["text"].asString();
+	p.tool_tip = form_element["text"].asString();
 	p.font = font;
 	p.rect.height = BTN_HEIGHT;
 	p.click_callback.function(boost::bind(&LLToastNotifyPanel::onClickButton, userdata));
diff --git a/indra/newview/llurldispatcher.cpp b/indra/newview/llurldispatcher.cpp
index a1670351f4005da600c0e90a9470dba1eadcd4b0..7c92e7ef98ac802a2a2772adc4c2427dce1609e2 100644
--- a/indra/newview/llurldispatcher.cpp
+++ b/indra/newview/llurldispatcher.cpp
@@ -263,7 +263,7 @@ class LLTeleportHandler : public LLCommandHandler, public LLEventAPI
 	// inside the app, otherwise a malicious web page could
 	// cause a constant teleport loop.  JC
 	LLTeleportHandler() :
-		LLCommandHandler("teleport", UNTRUSTED_THROTTLE),
+		LLCommandHandler("teleport", UNTRUSTED_CLICK_ONLY),
 		LLEventAPI("LLTeleportHandler", "Low-level teleport API")
 	{
 		LLEventAPI::add("teleport",
diff --git a/indra/newview/llviewerassetupload.cpp b/indra/newview/llviewerassetupload.cpp
index 14fae8d03553495b0555c6d88a1028ba8f21dbdd..232b52a3f9fb1a62ce72f54d8f881f9f19fdccda 100644
--- a/indra/newview/llviewerassetupload.cpp
+++ b/indra/newview/llviewerassetupload.cpp
@@ -868,11 +868,6 @@ void LLViewerAssetUpload::AssetInventoryUploadCoproc(LLCoreHttpUtil::HttpCorouti
     {
         floater_snapshot->notify(LLSD().with("set-finished", LLSD().with("ok", success).with("msg", "inventory")));
     }
-    LLFloater* floater_outfit_snapshot = LLFloaterReg::findInstance("outfit_snapshot");
-    if (uploadInfo->getAssetType() == LLAssetType::AT_TEXTURE && floater_outfit_snapshot && floater_outfit_snapshot->isShown())
-    {
-        floater_outfit_snapshot->notify(LLSD().with("set-finished", LLSD().with("ok", success).with("msg", "inventory")));
-    }
 }
 
 //=========================================================================
@@ -951,11 +946,5 @@ void LLViewerAssetUpload::HandleUploadError(LLCore::HttpStatus status, LLSD &res
             floater_snapshot->notify(LLSD().with("set-finished", LLSD().with("ok", false).with("msg", "inventory")));
         }
     }
-
-    LLFloater* floater_outfit_snapshot = LLFloaterReg::findInstance("outfit_snapshot");
-    if (uploadInfo->getAssetType() == LLAssetType::AT_TEXTURE && floater_outfit_snapshot && floater_outfit_snapshot->isShown())
-    {
-        floater_outfit_snapshot->notify(LLSD().with("set-finished", LLSD().with("ok", false).with("msg", "inventory")));
-    }
 }
 
diff --git a/indra/newview/llvieweraudio.cpp b/indra/newview/llvieweraudio.cpp
index f810e5f4ef6e8d2c66bfbc06fbf33963949c43db..cc73f7ca800185ed9fffb9fe9b8d80c1aac96b69 100644
--- a/indra/newview/llvieweraudio.cpp
+++ b/indra/newview/llvieweraudio.cpp
@@ -496,7 +496,20 @@ void audio_update_listener()
 	if (gAudiop)
 	{
 		// update listener position because agent has moved	
-		LLVector3d lpos_global = gAgentCamera.getCameraPositionGlobal();		
+        static LLUICachedControl<S32> mEarLocation("MediaSoundsEarLocation", 0);
+        LLVector3d ear_position;
+        switch(mEarLocation)
+        {
+        case 0:
+        default:
+            ear_position = gAgentCamera.getCameraPositionGlobal();
+            break;
+
+        case 1:
+            ear_position = gAgent.getPositionGlobal();
+            break;
+        }
+		LLVector3d lpos_global = ear_position;		
 		LLVector3 lpos_global_f;
 		lpos_global_f.setVec(lpos_global);
 	
diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp
index bc46a61fb0a8fe95da5dbf2490af065c0a61ea2e..34c9dae4bb9558914ee6319552484c2bc2f3c1ec 100644
--- a/indra/newview/llviewercontrol.cpp
+++ b/indra/newview/llviewercontrol.cpp
@@ -616,7 +616,7 @@ bool toggle_show_navigation_panel(const LLSD& newvalue)
 
 	LLNavigationBar::getInstance()->setVisible(value);
 	gSavedSettings.setBOOL("ShowMiniLocationPanel", !value);
-
+    gViewerWindow->reshapeStatusBarContainer();
 	return true;
 }
 
diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp
index 06a6c5e37347165d8ed33be1710ade65ad3196bc..c0398372b43e43ee53238c57c33987bc898df587 100644
--- a/indra/newview/llviewerfloaterreg.cpp
+++ b/indra/newview/llviewerfloaterreg.cpp
@@ -103,7 +103,7 @@
 #include "llfloaterobjectweights.h"
 #include "llfloateropenobject.h"
 #include "llfloateroutfitphotopreview.h"
-#include "llfloateroutfitsnapshot.h"
+#include "llfloatersimpleoutfitsnapshot.h"
 #include "llfloaterpathfindingcharacters.h"
 #include "llfloaterpathfindingconsole.h"
 #include "llfloaterpathfindinglinksets.h"
@@ -170,14 +170,107 @@
 // *NOTE: Please add files in alphabetical order to keep merges easy.
 
 // handle secondlife:///app/openfloater/{NAME} URLs
+const std::string FLOATER_PROFILE("profile");
 class LLFloaterOpenHandler : public LLCommandHandler
 {
 public:
-	// requires trusted browser to trigger
+	// requires trusted browser to trigger or an explicit click
 	LLFloaterOpenHandler() : LLCommandHandler("openfloater", UNTRUSTED_THROTTLE) { }
 
-	bool handle(const LLSD& params, const LLSD& query_map,
-				LLMediaCtrl* web)
+    bool canHandleUntrusted(
+        const LLSD& params,
+        const LLSD& query_map,
+        LLMediaCtrl* web,
+        const std::string& nav_type) override
+    {
+        if (params.size() != 1)
+        {
+            return true; // will fail silently
+        }
+        
+        std::string fl_name = params[0].asString();
+
+        if (nav_type == NAV_TYPE_CLICKED)
+        {
+            const std::list<std::string> blacklist_clicked = {
+                "camera_presets",
+                "delete_pref_preset",
+                "forget_username",
+                "god_tools",
+                "group_picker",
+                "hud",
+                "incoming_call",
+                "linkreplace",
+                "message_critical", // Modal!!! Login specific.
+                "message_tos", // Modal!!! Login specific.
+                "save_pref_preset",
+                "save_camera_preset",
+                "region_restarting",
+                "outfit_snapshot",
+                "upload_anim_bvh",
+                "upload_anim_anim",
+                "upload_image",
+                "upload_model",
+                "upload_script",
+                "upload_sound"
+            };
+            return std::find(blacklist_clicked.begin(), blacklist_clicked.end(), fl_name) == blacklist_clicked.end();
+        }
+        else
+        {
+            const std::list<std::string> blacklist_untrusted = {
+                "360capture",
+                "block_timers",
+                "add_payment_method",
+                "appearance",
+                "associate_listing",
+                "avatar_picker",
+                "camera",
+                "camera_presets",
+                "classified",
+                "add_landmark",
+                "delete_pref_preset",
+                "env_fixed_environmentent_water",
+                "env_fixed_environmentent_sky",
+                "env_edit_extdaycycle",
+                "font_test",
+                "forget_username",
+                "god_tools",
+                "group_picker",
+                "hud",
+                "incoming_call",
+                "linkreplace",
+                "mem_leaking",
+                "marketplace_validation",
+                "message_critical", // Modal!!! Login specific. If this is in use elsewhere, better to create a non modal variant
+                "message_tos", // Modal!!! Login specific.
+                "mute_object_by_name",
+                "publish_classified",
+                "save_pref_preset",
+                "save_camera_preset",
+                "region_restarting",
+                "script_debug",
+                "script_debug_output",
+                "sell_land",
+                "outfit_snapshot",
+                "upload_anim_bvh",
+                "upload_anim_anim",
+                "upload_image",
+                "upload_model",
+                "upload_script",
+                "upload_sound"
+            };
+            return std::find(blacklist_untrusted.begin(), blacklist_untrusted.end(), fl_name) == blacklist_untrusted.end();
+        }
+
+
+        return true;
+    }
+
+	bool handle(
+        const LLSD& params,
+        const LLSD& query_map,
+        LLMediaCtrl* web) override
 	{
 		if (params.size() != 1)
 		{
@@ -185,7 +278,12 @@ class LLFloaterOpenHandler : public LLCommandHandler
 		}
 
 		const std::string floater_name = LLURI::unescape(params[0].asString());
-		LLFloaterReg::showInstance(floater_name);
+        LLSD key;
+        if (floater_name == FLOATER_PROFILE)
+        {
+            key["id"] = gAgentID;
+        }
+		LLFloaterReg::showInstance(floater_name, key);
 
 		return true;
 	}
@@ -368,7 +466,7 @@ void LLViewerFloaterReg::registerFloaters()
 	LLFloaterReg::add("scene_load_stats", "floater_scene_load_stats.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSceneLoadStats>);
 	LLFloaterReg::add("stop_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterNotRunQueue>);
 	LLFloaterReg::add("snapshot", "floater_snapshot.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSnapshot>);
-    LLFloaterReg::add("outfit_snapshot", "floater_outfit_snapshot.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterOutfitSnapshot>);
+    LLFloaterReg::add("simple_outfit_snapshot", "floater_simple_outfit_snapshot.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSimpleOutfitSnapshot>);
     LLFloaterReg::add("search", "floater_search.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSearch>);
     LLFloaterReg::add("profile", "floater_profile.xml",(LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterProfile>);
 	LLFloaterReg::add("guidebook", "floater_how_to.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterHowTo>);
diff --git a/indra/newview/llviewerinput.cpp b/indra/newview/llviewerinput.cpp
index 43b9cd90bd6f90cdfb3917dff2acb79920ff2c90..6bab2c2100265108b0a799dc5eabac76e886475f 100644
--- a/indra/newview/llviewerinput.cpp
+++ b/indra/newview/llviewerinput.cpp
@@ -1614,12 +1614,22 @@ BOOL LLViewerInput::handleMouse(LLWindow *window_impl, LLCoordGL pos, MASK mask,
             clicktype = CLICK_DOUBLELEFT;
         }
 
+        // If the first LMB click is handled by the menu, skip the following double click
+        static bool skip_double_click = false;
+        if (clicktype == CLICK_LEFT && down )
+        {
+            skip_double_click = handled;
+        }
 
         if (double_click_sp && down)
         {
             // Consume click.
             // Due to handling, double click that is not handled will be immediately followed by LMB click
         }
+        else if (clicktype == CLICK_DOUBLELEFT && skip_double_click)
+        {
+            handled = true;
+        }
         // If UI handled 'down', it should handle 'up' as well
         // If we handle 'down' not by UI, then we should handle 'up'/'level' regardless of UI
         else if (handled)
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index 55ac817479170eafb35e1f1e88a0f5616c9d368a..50252556debd20f594704fa462c2ad5777d1dc48 100644
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -232,7 +232,7 @@ class LLInventoryHandler : public LLCommandHandler
 {
 public:
 	// requires trusted browser to trigger
-	LLInventoryHandler() : LLCommandHandler("inventory", UNTRUSTED_THROTTLE) { }
+	LLInventoryHandler() : LLCommandHandler("inventory", UNTRUSTED_CLICK_ONLY) { }
 	
 	bool handle(const LLSD& params, const LLSD& query_map,
 				LLMediaCtrl* web)
diff --git a/indra/newview/llviewerjointattachment.cpp b/indra/newview/llviewerjointattachment.cpp
index fd314ed3dcafe8c30aae48171c1d7d8f9cfbb7b3..b3bfb86b995255957c1124539aedbd070ec07115 100644
--- a/indra/newview/llviewerjointattachment.cpp
+++ b/indra/newview/llviewerjointattachment.cpp
@@ -45,7 +45,7 @@
 #include "llglheaders.h"
 
 extern LLPipeline gPipeline;
-const F32 MAX_ATTACHMENT_DIST = 3.5f; // meters?
+const F32 MAX_ATTACHMENT_DIST = 3.5f; // meters
 
 //-----------------------------------------------------------------------------
 // LLViewerJointAttachment()
diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp
index a1cb152e1e54c87d922d8853a4e932e6cc6fb0d9..8570c0cd5d49c71c20e21b1ef97d15292b99b73f 100644
--- a/indra/newview/llviewermedia.cpp
+++ b/indra/newview/llviewermedia.cpp
@@ -3581,7 +3581,20 @@ void LLViewerMediaImpl::calculateInterest()
 			LLVector3d global_delta = agent_global - obj_global ;
 			mProximityDistance = global_delta.magVecSquared();  // use distance-squared because it's cheaper and sorts the same.
 
-			LLVector3d camera_delta = gAgentCamera.getCameraPositionGlobal() - obj_global;
+            static LLUICachedControl<S32> mEarLocation("MediaSoundsEarLocation", 0);
+            LLVector3d ear_position;
+            switch(mEarLocation)
+            {
+            case 0:
+            default:
+                ear_position = gAgentCamera.getCameraPositionGlobal();
+                break;
+
+            case 1:
+                ear_position = agent_global;
+                break;
+            }
+            LLVector3d camera_delta = ear_position - obj_global;
 			mProximityCamera = camera_delta.magVec();
 		}
 	}
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 3573af40cb710dc75977fcc02b6dd918db6c59c4..a0223a5dbbd615ea2baabcd22b264bed685122e4 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -2803,14 +2803,15 @@ void handle_object_show_original()
 }
 
 
-static void init_default_item_label(const std::string& item_name)
+static void init_default_item_label(LLUICtrl* ctrl)
 {
+	const std::string& item_name = ctrl->getName();
 	boost::unordered_map<std::string, LLStringExplicit>::iterator it = sDefaultItemLabels.find(item_name);
 	if (it == sDefaultItemLabels.end())
 	{
 		// *NOTE: This will not work for items of type LLMenuItemCheckGL because they return boolean value
 		//       (doesn't seem to matter much ATM).
-		LLStringExplicit default_label = gMenuHolder->childGetValue(item_name).asString();
+		LLStringExplicit default_label = ctrl->getValue().asString();
 		if (!default_label.empty())
 		{
 			sDefaultItemLabels.insert(std::pair<std::string, LLStringExplicit>(item_name, default_label));
@@ -2841,18 +2842,17 @@ bool enable_object_touch(LLUICtrl* ctrl)
 		new_value = obj->flagHandleTouch() || (parent && parent->flagHandleTouch());
 	}
 
-	std::string item_name = ctrl->getName();
-	init_default_item_label(item_name);
+	init_default_item_label(ctrl);
 
 	// Update label based on the node touch name if available.
 	LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode();
 	if (node && node->mValid && !node->mTouchName.empty())
 	{
-		gMenuHolder->childSetValue(item_name, node->mTouchName);
+		ctrl->setValue(node->mTouchName);
 	}
 	else
 	{
-		gMenuHolder->childSetValue(item_name, get_default_item_label(item_name));
+		ctrl->setValue(get_default_item_label(ctrl->getName()));
 	}
 
 	return new_value;
@@ -4334,6 +4334,10 @@ class LLLandSit : public view_listener_t
 {
     bool handleEvent(const LLSD& userdata)
     {
+        if (gAgent.isSitting())
+        {
+            gAgent.standUp();
+        }
         LLVector3d posGlobal = LLToolPie::getInstance()->getPick().mPosGlobal;
 
         LLQuaternion target_rot;
@@ -5628,6 +5632,7 @@ class LLToolsSelectNextPartFace : public view_listener_t
                     }
                 }
                 LLSelectMgr::getInstance()->selectObjectOnly(to_select, new_te);
+                LLSelectMgr::getInstance()->addAsIndividual(to_select, new_te, false);
             }
             else
             {
@@ -6591,20 +6596,18 @@ bool enable_object_sit(LLUICtrl* ctrl)
 	bool sitting_on_sel = sitting_on_selection();
 	if (!sitting_on_sel)
 	{
-		std::string item_name = ctrl->getName();
-
 		// init default labels
-		init_default_item_label(item_name);
+		init_default_item_label(ctrl);
 
 		// Update label
 		LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode();
 		if (node && node->mValid && !node->mSitName.empty())
 		{
-			gMenuHolder->childSetValue(item_name, node->mSitName);
+			ctrl->setValue(node->mSitName);
 		}
 		else
 		{
-			gMenuHolder->childSetValue(item_name, get_default_item_label(item_name));
+			ctrl->setValue(get_default_item_label(ctrl->getName()));
 		}
 	}
 	return !sitting_on_sel && is_object_sittable();
@@ -7650,7 +7653,6 @@ void handle_selected_texture_info(void*)
    		map_t::iterator it;
    		for (it = faces_per_texture.begin(); it != faces_per_texture.end(); ++it)
    		{
-   			LLUUID image_id = it->first;
    			U8 te = it->second[0];
    			LLViewerTexture* img = node->getObject()->getTEImage(te);
    			S32 height = img->getHeight();
diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp
index f1e2c06e0c761cd08ecdc4da63c67e57ec4fdd0d..fdf1d04c0961369e12afd28e413c6f3ed3511c59 100644
--- a/indra/newview/llviewermenufile.cpp
+++ b/indra/newview/llviewermenufile.cpp
@@ -38,7 +38,7 @@
 #include "llfloatermap.h"
 #include "llfloatermodelpreview.h"
 #include "llfloatersnapshot.h"
-#include "llfloateroutfitsnapshot.h"
+#include "llfloatersimpleoutfitsnapshot.h"
 #include "llimage.h"
 #include "llimagebmp.h"
 #include "llimagepng.h"
@@ -664,7 +664,7 @@ class LLFileEnableCloseAllWindows : public view_listener_t
 	bool handleEvent(const LLSD& userdata)
 	{
 		LLFloaterSnapshot* floater_snapshot = LLFloaterSnapshot::findInstance();
-		LLFloaterOutfitSnapshot* floater_outfit_snapshot = LLFloaterOutfitSnapshot::findInstance();
+		LLFloaterSimpleOutfitSnapshot* floater_outfit_snapshot = LLFloaterSimpleOutfitSnapshot::findInstance();
 		bool is_floaters_snapshot_opened = (floater_snapshot && floater_snapshot->isInVisibleChain())
 			|| (floater_outfit_snapshot && floater_outfit_snapshot->isInVisibleChain());
 		bool open_children = gFloaterView->allChildrenClosed() && !is_floaters_snapshot_opened;
@@ -681,7 +681,7 @@ class LLFileCloseAllWindows : public view_listener_t
 		LLFloaterSnapshot* floater_snapshot = LLFloaterSnapshot::findInstance();
 		if (floater_snapshot)
 			floater_snapshot->closeFloater(app_quitting);
-		LLFloaterOutfitSnapshot* floater_outfit_snapshot = LLFloaterOutfitSnapshot::findInstance();
+        LLFloaterSimpleOutfitSnapshot* floater_outfit_snapshot = LLFloaterSimpleOutfitSnapshot::findInstance();
 		if (floater_outfit_snapshot)
 			floater_outfit_snapshot->closeFloater(app_quitting);
 		if (gMenuHolder) gMenuHolder->hideMenus();
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index aad6c14b4d2006f2e5101ff18f953241e8e2c467..f47f0b45727f4872666a3f760dd295886437d05b 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -316,7 +316,8 @@ LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRe
 	mLastUpdateType(OUT_UNKNOWN),
 	mLastUpdateCached(FALSE),
 	mCachedMuteListUpdateTime(0),
-	mCachedOwnerInMuteList(false)
+	mCachedOwnerInMuteList(false),
+	mRiggedAttachedWarned(false)
 {
 	if (!is_global)
 	{
@@ -3233,36 +3234,39 @@ void LLViewerObject::processTaskInv(LLMessageSystem* msg, void** user_data)
         return;
     }
 
-    LLFilenameAndTask* ft = new LLFilenameAndTask;
-    ft->mTaskID = task_id;
     // we can receive multiple task updates simultaneously, make sure we will not rewrite newer with older update
-    msg->getS16Fast(_PREHASH_InventoryData, _PREHASH_Serial, ft->mSerial);
+    S16 serial = 0;
+    msg->getS16Fast(_PREHASH_InventoryData, _PREHASH_Serial, serial);
 
-    if (ft->mSerial == object->mInventorySerialNum
-        && ft->mSerial < object->mExpectedInventorySerialNum)
+    if (serial == object->mInventorySerialNum
+        && serial < object->mExpectedInventorySerialNum)
     {
         // Loop Protection.
         // We received same serial twice.
         // Viewer did some changes to inventory that couldn't be saved server side
         // or something went wrong to cause serial to be out of sync.
         // Drop xfer and restart after some time, assign server's value as expected
-        LL_WARNS() << "Task inventory serial might be out of sync, server serial: " << ft->mSerial << " client expected serial: " << object->mExpectedInventorySerialNum << LL_ENDL;
-        object->mExpectedInventorySerialNum = ft->mSerial;
+        LL_WARNS() << "Task inventory serial might be out of sync, server serial: " << serial << " client expected serial: " << object->mExpectedInventorySerialNum << LL_ENDL;
+        object->mExpectedInventorySerialNum = serial;
         object->fetchInventoryDelayed(INVENTORY_UPDATE_WAIT_TIME_DESYNC);
     }
-    else if (ft->mSerial < object->mExpectedInventorySerialNum)
+    else if (serial < object->mExpectedInventorySerialNum)
     {
         // Out of date message, record to current serial for loop protection, but do not load it
         // Drop xfer and restart after some time
-        if (ft->mSerial < object->mInventorySerialNum)
+        if (serial < object->mInventorySerialNum)
         {
             LL_WARNS() << "Task serial decreased. Potentially out of order packet or desync." << LL_ENDL;
         }
-        object->mInventorySerialNum = ft->mSerial;
+        object->mInventorySerialNum = serial;
         object->fetchInventoryDelayed(INVENTORY_UPDATE_WAIT_TIME_OUTDATED);
     }
-    else if (ft->mSerial >= object->mExpectedInventorySerialNum)
+    else if (serial >= object->mExpectedInventorySerialNum)
     {
+        LLFilenameAndTask* ft = new LLFilenameAndTask;
+        ft->mTaskID = task_id;
+        ft->mSerial = serial;
+        
         // We received version we expected or newer. Load it.
         object->mInventorySerialNum = ft->mSerial;
         object->mExpectedInventorySerialNum = ft->mSerial;
@@ -3297,7 +3301,7 @@ void LLViewerObject::processTaskInv(LLMessageSystem* msg, void** user_data)
             object->mRegionp->getHost(),
             TRUE,
             &LLViewerObject::processTaskInvFile,
-            (void**)ft,
+            (void**)ft, // This takes ownership of ft
             LLXferManager::HIGH_PRIORITY);
         if (object->mInvRequestState == INVENTORY_XFER)
         {
diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h
index bef8e3e7e3c919517c5b5754a5be13d9aa0c178d..0005cdf14e10f23346131b14f694e8ec77e093d7 100644
--- a/indra/newview/llviewerobject.h
+++ b/indra/newview/llviewerobject.h
@@ -702,6 +702,8 @@ class LLViewerObject
 	// Replace textures with web pages on this object while drawing
 	BOOL mRenderMedia;
 
+    bool mRiggedAttachedWarned;
+
 	// In bits
 	S32				mBestUpdatePrecision;
 
diff --git a/indra/newview/llviewerparcelmgr.cpp b/indra/newview/llviewerparcelmgr.cpp
index 75eb16c085473905cbb9a4f51a4f993203cc946d..97dc916bfe8d920dd11a4150e3c25279612ab03c 100644
--- a/indra/newview/llviewerparcelmgr.cpp
+++ b/indra/newview/llviewerparcelmgr.cpp
@@ -1974,7 +1974,7 @@ void LLViewerParcelMgr::optionallyStartMusic(const std::string &music_url, const
 		static LLCachedControl<bool> tentative_autoplay(gSavedSettings, "MediaTentativeAutoPlay", true);
 		// only play music when you enter a new parcel if the UI control for this
 		// was not *explicitly* stopped by the user. (part of SL-4878)
-		LLPanelNearByMedia* nearby_media_panel = gStatusBar->getNearbyMediaPanel();
+		LLPanelNearByMedia* nearby_media_panel = gStatusBar ? gStatusBar->getNearbyMediaPanel() : NULL;
         LLViewerAudio* viewer_audio = LLViewerAudio::getInstance();
 
         // ask mode //todo constants
diff --git a/indra/newview/llviewerpartsource.cpp b/indra/newview/llviewerpartsource.cpp
index f042040e98a58cf19ccb334da10428b31c8a4615..1751ee1ebbe1b7a188c97631c4491abee3bed176 100644
--- a/indra/newview/llviewerpartsource.cpp
+++ b/indra/newview/llviewerpartsource.cpp
@@ -793,7 +793,7 @@ void LLViewerPartSourceBeam::update(const F32 dt)
 		}
 
 		LLViewerPart* part = new LLViewerPart();
-		part->init(this, mImagep, NULL);
+		part->init(this, mImagep, updatePart);
 
 		part->mFlags = LLPartData::LL_PART_INTERP_COLOR_MASK |
 						LLPartData::LL_PART_INTERP_SCALE_MASK |
diff --git a/indra/newview/llviewertexteditor.cpp b/indra/newview/llviewertexteditor.cpp
index e2de7ac825e7e5f76b2e4f1bf7097b7438a3f621..7abb42dd8a2f01be90414967da93bf414621a5f8 100644
--- a/indra/newview/llviewertexteditor.cpp
+++ b/indra/newview/llviewertexteditor.cpp
@@ -1252,7 +1252,6 @@ bool LLViewerTextEditor::onCopyToInvDialog(const LLSD& notification, const LLSD&
 	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
 	if( 0 == option )
 	{
-		LLUUID item_id = notification["payload"]["item_id"].asUUID();
 		llwchar wc = llwchar(notification["payload"]["item_wc"].asInteger());
 		LLInventoryItem* itemp = LLEmbeddedItems::getEmbeddedItemPtr(wc);
 		if (itemp)
diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp
index da3c860ddbc63fcc287d4a6e77e6a7185fe7fe84..93ae1670c8e9195265f773fc6d3d1fb97d2f0366 100644
--- a/indra/newview/llviewertexturelist.cpp
+++ b/indra/newview/llviewertexturelist.cpp
@@ -45,11 +45,13 @@
 #include "llxmltree.h"
 #include "message.h"
 
+#include "lldrawpoolbump.h" // to init bumpmap images
 #include "lltexturecache.h"
 #include "lltexturefetch.h"
 #include "llviewercontrol.h"
 #include "llviewertexture.h"
 #include "llviewermedia.h"
+#include "llviewernetwork.h"
 #include "llviewerregion.h"
 #include "llviewerstats.h"
 #include "pipeline.h"
@@ -139,9 +141,6 @@ void LLViewerTextureList::doPreloadImages()
 	//uv_test->setClamp(FALSE, FALSE);
 	//uv_test->setMipFilterNearest(TRUE, TRUE);
 
-	// prefetch specific UUIDs
-	LLViewerTextureManager::getFetchedTexture(IMG_SHOT);
-	LLViewerTextureManager::getFetchedTexture(IMG_SMOKE_POOF);
 	LLViewerFetchedTexture* image = LLViewerTextureManager::getFetchedTextureFromFile("silhouette.j2c", FTT_LOCAL_FILE, MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI);
 	if (image) 
 	{
@@ -160,12 +159,6 @@ void LLViewerTextureList::doPreloadImages()
 		image->setAddressMode(LLTexUnit::TAM_WRAP);
 		mImagePreloads.insert(image);
 	}
-	image = LLViewerTextureManager::getFetchedTexture(DEFAULT_WATER_NORMAL, FTT_DEFAULT, MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI);
-	if (image) 
-	{
-		image->setAddressMode(LLTexUnit::TAM_WRAP);	
-		mImagePreloads.insert(image);
-	}
 	image = LLViewerTextureManager::getFetchedTextureFromFile("transparent.j2c", FTT_LOCAL_FILE, MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI, LLViewerTexture::FETCHED_TEXTURE,
 		0, 0, IMG_TRANSPARENT);
 	if (image) 
@@ -198,7 +191,18 @@ void LLViewerTextureList::doPreloadImages()
 
 static std::string get_texture_list_name()
 {
-	return gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "texture_list_" + gSavedSettings.getString("LoginLocation") + "." + gDirUtilp->getUserName() + ".xml");
+    if (LLGridManager::getInstance()->isInProductionGrid())
+    {
+        return gDirUtilp->getExpandedFilename(LL_PATH_CACHE,
+            "texture_list_" + gSavedSettings.getString("LoginLocation") + "." + gDirUtilp->getUserName() + ".xml");
+    }
+    else
+    {
+        const std::string& grid_id_str = LLGridManager::getInstance()->getGridId();
+        const std::string& grid_id_lower = utf8str_tolower(grid_id_str);
+        return gDirUtilp->getExpandedFilename(LL_PATH_CACHE,
+            "texture_list_" + gSavedSettings.getString("LoginLocation") + "." + gDirUtilp->getUserName() + "." + grid_id_lower + ".xml");
+    }
 }
 
 void LLViewerTextureList::doPrefetchImages()
@@ -207,6 +211,26 @@ void LLViewerTextureList::doPrefetchImages()
 	gTextureTimer.start();
 	gTextureTimer.pause();
 
+    // todo: do not load without getViewerAssetUrl()
+    // either fail login without caps or provide this
+    // in some other way, textures won't load otherwise
+    LLViewerFetchedTexture *imagep = findImage(DEFAULT_WATER_NORMAL, TEX_LIST_STANDARD);
+    if (!imagep)
+    {
+        // add it to mImagePreloads only once
+        imagep = LLViewerTextureManager::getFetchedTexture(DEFAULT_WATER_NORMAL, FTT_DEFAULT, MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI);
+        if (imagep)
+        {
+            imagep->setAddressMode(LLTexUnit::TAM_WRAP);
+            mImagePreloads.insert(imagep);
+        }
+    }
+
+    LLViewerTextureManager::getFetchedTexture(IMG_SHOT);
+    LLViewerTextureManager::getFetchedTexture(IMG_SMOKE_POOF);
+
+    LLStandardBumpmap::addstandard();
+
 	if (LLAppViewer::instance()->getPurgeCache())
 	{
 		// cache was purged, no point
@@ -1501,152 +1525,6 @@ void LLViewerTextureList::updateMaxResidentTexMem(S32Megabytes mem)
 
 ///////////////////////////////////////////////////////////////////////////////
 
-// static
-void LLViewerTextureList::receiveImageHeader(LLMessageSystem *msg, void **user_data)
-{
-	static LLCachedControl<bool> log_texture_traffic(gSavedSettings,"LogTextureNetworkTraffic", false) ;
-
-    LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
-
-	// Receive image header, copy into image object and decompresses 
-	// if this is a one-packet image. 
-	
-	LLUUID id;
-	
-	char ip_string[256];
-	u32_to_ip_string(msg->getSenderIP(),ip_string);
-	
-	U32Bytes received_size ;
-	if (msg->getReceiveCompressedSize())
-	{
-		received_size = (U32Bytes)msg->getReceiveCompressedSize() ;		
-	}
-	else
-	{
-		received_size = (U32Bytes)msg->getReceiveSize() ;		
-	}
-	add(LLStatViewer::TEXTURE_NETWORK_DATA_RECEIVED, received_size);
-	add(LLStatViewer::TEXTURE_PACKETS, 1);
-	
-	U8 codec;
-	U16 packets;
-	U32 totalbytes;
-	msg->getUUIDFast(_PREHASH_ImageID, _PREHASH_ID, id);
-	msg->getU8Fast(_PREHASH_ImageID, _PREHASH_Codec, codec);
-	msg->getU16Fast(_PREHASH_ImageID, _PREHASH_Packets, packets);
-	msg->getU32Fast(_PREHASH_ImageID, _PREHASH_Size, totalbytes);
-	
-	S32 data_size = msg->getSizeFast(_PREHASH_ImageData, _PREHASH_Data); 
-	if (!data_size)
-	{
-		return;
-	}
-	if (data_size < 0)
-	{
-		// msg->getSizeFast() is probably trying to tell us there
-		// was an error.
-		LL_ERRS() << "image header chunk size was negative: "
-		<< data_size << LL_ENDL;
-		return;
-	}
-	
-	// this buffer gets saved off in the packet list
-	U8 *data = new U8[data_size];
-	msg->getBinaryDataFast(_PREHASH_ImageData, _PREHASH_Data, data, data_size);
-	
-	LLViewerFetchedTexture *image = LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
-	if (!image)
-	{
-		delete [] data;
-		return;
-	}
-	if(log_texture_traffic)
-	{
-		gTotalTextureBytesPerBoostLevel[image->getBoostLevel()] += received_size ;
-	}
-
-	//image->getLastPacketTimer()->reset();
-	bool res = LLAppViewer::getTextureFetch()->receiveImageHeader(msg->getSender(), id, codec, packets, totalbytes, data_size, data);
-	if (!res)
-	{
-		delete[] data;
-	}
-}
-
-// static
-void LLViewerTextureList::receiveImagePacket(LLMessageSystem *msg, void **user_data)
-{
-	static LLCachedControl<bool> log_texture_traffic(gSavedSettings,"LogTextureNetworkTraffic", false) ;
-
-    LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
-	
-	// Receives image packet, copy into image object,
-	// checks if all packets received, decompresses if so. 
-	
-	LLUUID id;
-	U16 packet_num;
-	
-	char ip_string[256];
-	u32_to_ip_string(msg->getSenderIP(),ip_string);
-	
-	U32Bytes received_size ;
-	if (msg->getReceiveCompressedSize())
-	{
-		received_size = (U32Bytes)msg->getReceiveCompressedSize() ;
-	}
-	else
-	{
-		received_size = (U32Bytes)msg->getReceiveSize() ;		
-	}
-
-	add(LLStatViewer::TEXTURE_NETWORK_DATA_RECEIVED, F64Bytes(received_size));
-	add(LLStatViewer::TEXTURE_PACKETS, 1);
-	
-	//llprintline("Start decode, image header...");
-	msg->getUUIDFast(_PREHASH_ImageID, _PREHASH_ID, id);
-	msg->getU16Fast(_PREHASH_ImageID, _PREHASH_Packet, packet_num);
-	S32 data_size = msg->getSizeFast(_PREHASH_ImageData, _PREHASH_Data); 
-	
-	if (!data_size)
-	{
-		return;
-	}
-	if (data_size < 0)
-	{
-		// msg->getSizeFast() is probably trying to tell us there
-		// was an error.
-		LL_ERRS() << "image data chunk size was negative: "
-		<< data_size << LL_ENDL;
-		return;
-	}
-	if (data_size > MTUBYTES)
-	{
-		LL_ERRS() << "image data chunk too large: " << data_size << " bytes" << LL_ENDL;
-		return;
-	}
-	U8 *data = new U8[data_size];
-	msg->getBinaryDataFast(_PREHASH_ImageData, _PREHASH_Data, data, data_size);
-	
-	LLViewerFetchedTexture *image = LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
-	if (!image)
-	{
-		delete [] data;
-		return;
-	}
-	if(log_texture_traffic)
-	{
-		gTotalTextureBytesPerBoostLevel[image->getBoostLevel()] += received_size ;
-	}
-
-	//image->getLastPacketTimer()->reset();
-	bool res = LLAppViewer::getTextureFetch()->receiveImagePacket(msg->getSender(), id, packet_num, data_size, data);
-	if (!res)
-	{
-		delete[] data;
-	}
-}
-
-
 // We've been that the asset server does not contain the requested image id.
 // static
 void LLViewerTextureList::processImageNotInDatabase(LLMessageSystem *msg,void **user_data)
diff --git a/indra/newview/llviewertexturelist.h b/indra/newview/llviewertexturelist.h
index 6fb0d3552e65a4d853c31a02c247c38de87bab71..0018e78d4567ab53f9c307fa6eb9b6347441011e 100644
--- a/indra/newview/llviewertexturelist.h
+++ b/indra/newview/llviewertexturelist.h
@@ -98,8 +98,6 @@ class LLViewerTextureList
                                  const S32 max_image_dimentions = LLViewerFetchedTexture::MAX_IMAGE_SIZE_DEFAULT);
 	static LLPointer<LLImageJ2C> convertToUploadFile(LLPointer<LLImageRaw> raw_image, const S32 max_image_dimentions = LLViewerFetchedTexture::MAX_IMAGE_SIZE_DEFAULT);
 	static void processImageNotInDatabase( LLMessageSystem *msg, void **user_data );
-	static void receiveImageHeader(LLMessageSystem *msg, void **user_data);
-	static void receiveImagePacket(LLMessageSystem *msg, void **user_data);
 
 public:
 	LLViewerTextureList();
@@ -133,7 +131,9 @@ class LLViewerTextureList
 
 	void updateMaxResidentTexMem(S32Megabytes mem);
 	
+    // Local UI images
 	void doPreloadImages();
+    // Network images. Needs caps and cache to work
 	void doPrefetchImages();
 
 	void clearFetchingRequests();
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index 8a7d5f12d0da13ecfe2446e4d4e53512a70901e2..ddc11ac0bd098dedd9eb49abe7a73f996769e4c0 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -262,6 +262,8 @@ static const F32 MIN_UI_SCALE = 0.75f;
 static const F32 MAX_UI_SCALE = 7.0f;
 static const F32 MIN_DISPLAY_SCALE = 0.75f;
 
+static const char KEY_MOUSELOOK = 'M';
+
 static LLCachedControl<std::string>	sSnapshotBaseName(LLCachedControl<std::string>(gSavedPerAccountSettings, "SnapshotBaseName", "Snapshot"));
 static LLCachedControl<std::string>	sSnapshotDir(LLCachedControl<std::string>(gSavedPerAccountSettings, "SnapshotBaseDir", ""));
 
@@ -1307,7 +1309,6 @@ LLWindowCallbacks::DragNDropResult LLViewerWindow::handleDragNDrop( LLWindow *wi
                                                           TRUE /* pick_transparent */, 
                                                           FALSE /* pick_rigged */);
 
-					LLUUID object_id = pick_info.getObjectID();
 					S32 object_face = pick_info.mObjectFace;
 					std::string url = data;
 
@@ -2232,31 +2233,36 @@ void LLViewerWindow::initWorldUI()
 	// Force gFloaterTools to initialize
 	LLFloaterReg::getInstance("build");
 
-
 	// Status bar
 	LLPanel* status_bar_container = getRootView()->getChild<LLPanel>("status_bar_container");
 	gStatusBar = new LLStatusBar(status_bar_container->getLocalRect());
-	gStatusBar->setFollowsAll();
+	gStatusBar->setFollows(FOLLOWS_LEFT | FOLLOWS_TOP | FOLLOWS_RIGHT);
 	gStatusBar->setShape(status_bar_container->getLocalRect());
 	// sync bg color with menu bar
 	gStatusBar->setBackgroundColor( gMenuBarView->getBackgroundColor().get() );
     // add InBack so that gStatusBar won't be drawn over menu
-	status_bar_container->addChildInBack(gStatusBar);
-	status_bar_container->setVisible(TRUE);
+    status_bar_container->addChildInBack(gStatusBar, 2/*tab order, after menu*/);
+    status_bar_container->setVisible(TRUE);
 
 	// Navigation bar
-	LLPanel* nav_bar_container = getRootView()->getChild<LLPanel>("nav_bar_container");
+	LLView* nav_bar_container = getRootView()->getChild<LLView>("nav_bar_container");
 
 	LLNavigationBar* navbar = LLNavigationBar::getInstance();
 	navbar->setShape(nav_bar_container->getLocalRect());
 	navbar->setBackgroundColor(gMenuBarView->getBackgroundColor().get());
 	nav_bar_container->addChild(navbar);
 	nav_bar_container->setVisible(TRUE);
-	
+
+
 	if (!gSavedSettings.getBOOL("ShowNavbarNavigationPanel"))
 	{
 		navbar->setVisible(FALSE);
 	}
+    else
+    {
+        reshapeStatusBarContainer();
+    }
+
 
 	// Top Info bar
 	LLPanel* topinfo_bar_container = getRootView()->getChild<LLPanel>("topinfo_bar_container");
@@ -2883,6 +2889,13 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask)
     if (keyboard_focus
         && !gFocusMgr.getKeystrokesOnly())
     {
+        //Most things should fall through, but mouselook is an exception,
+        //don't switch to mouselook if any floater has focus
+        if ((key == KEY_MOUSELOOK) && !(mask & (MASK_CONTROL | MASK_ALT)))
+        {
+            return TRUE;
+        }
+
         LLUICtrl* cur_focus = dynamic_cast<LLUICtrl*>(keyboard_focus);
         if (cur_focus && cur_focus->acceptsTextInput())
         {
@@ -3421,6 +3434,59 @@ void LLViewerWindow::updateUI()
 		root_view = mRootView;
 	}
 
+	static LLCachedControl<bool> dump_menu_holder(gSavedSettings, "DumpMenuHolderSize", false);
+	if (dump_menu_holder)
+	{
+		static bool init = false;
+		static LLFrameTimer child_count_timer;
+		static std::vector <std::string> child_vec;
+		if (!init)
+		{
+			child_count_timer.resetWithExpiry(5.f);
+			init = true;
+		}
+		if (child_count_timer.hasExpired())
+		{
+			LL_INFOS() << "gMenuHolder child count: " << gMenuHolder->getChildCount() << LL_ENDL;
+			std::vector<std::string> local_child_vec;
+			LLView::child_list_t child_list = *gMenuHolder->getChildList();
+			for (auto child : child_list)
+			{
+				local_child_vec.emplace_back(child->getName());
+			}
+			if (!local_child_vec.empty() && local_child_vec != child_vec)
+			{
+				std::vector<std::string> out_vec;
+				std::sort(local_child_vec.begin(), local_child_vec.end());
+				std::sort(child_vec.begin(), child_vec.end());
+				std::set_difference(child_vec.begin(), child_vec.end(), local_child_vec.begin(), local_child_vec.end(), std::inserter(out_vec, out_vec.begin()));
+				if (!out_vec.empty())
+				{
+					LL_INFOS() << "gMenuHolder removal diff size: '"<<out_vec.size() <<"' begin_child_diff";
+					for (auto str : out_vec)
+					{
+						LL_CONT << " : " << str;
+					}
+					LL_CONT << " : end_child_diff" << LL_ENDL;
+				}
+
+				out_vec.clear();
+				std::set_difference(local_child_vec.begin(), local_child_vec.end(), child_vec.begin(), child_vec.end(), std::inserter(out_vec, out_vec.begin()));
+				if (!out_vec.empty())
+				{
+					LL_INFOS() << "gMenuHolder addition diff size: '" << out_vec.size() << "' begin_child_diff";
+					for (auto str : out_vec)
+					{
+						LL_CONT << " : " << str;
+					}
+					LL_CONT << " : end_child_diff" << LL_ENDL;
+				}
+				child_vec.swap(local_child_vec);
+			}
+			child_count_timer.resetWithExpiry(5.f);
+		}
+	}
+
 	// only update mouse hover set when UI is visible (since we shouldn't send hover events to invisible UI
 	if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
 	{
@@ -5842,6 +5908,27 @@ LLRect LLViewerWindow::getChatConsoleRect()
 
 	return console_rect;
 }
+
+void LLViewerWindow::reshapeStatusBarContainer()
+{
+    LLPanel* status_bar_container = getRootView()->getChild<LLPanel>("status_bar_container");
+    LLView* nav_bar_container = getRootView()->getChild<LLView>("nav_bar_container");
+
+    S32 new_height = status_bar_container->getRect().getHeight();
+    S32 new_width = status_bar_container->getRect().getWidth();
+
+    if (gSavedSettings.getBOOL("ShowNavbarNavigationPanel"))
+    {
+        // Navigation bar is outside visible area, expand status_bar_container to show it
+        new_height += nav_bar_container->getRect().getHeight();
+    }
+    else
+    {
+        // collapse status_bar_container
+        new_height -= nav_bar_container->getRect().getHeight();
+    }
+    status_bar_container->reshape(new_width, new_height, TRUE);
+}
 //----------------------------------------------------------------------------
 
 
diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h
index 979a560508635d334d85ba137a4e1aa3e7169360..1927e01ddba4f8ccbed3c93c5161f699f76bf95a 100644
--- a/indra/newview/llviewerwindow.h
+++ b/indra/newview/llviewerwindow.h
@@ -177,6 +177,8 @@ class LLViewerWindow : public LLWindowCallbacks
 	bool			getUIVisibility();
 	void			handlePieMenu(S32 x, S32 y, MASK mask);
 
+    void            reshapeStatusBarContainer();
+
 	BOOL handleAnyMouseClick(LLWindow *window, LLCoordGL pos, MASK mask, EMouseClickType clicktype, BOOL down);
 
 	//
diff --git a/indra/newview/llvlcomposition.cpp b/indra/newview/llvlcomposition.cpp
index 46beac8255ce61fdcc84fe5203c8a908c5c5f0bd..0e6734f6e08833f49a5917514e317724039fcc74 100644
--- a/indra/newview/llvlcomposition.cpp
+++ b/indra/newview/llvlcomposition.cpp
@@ -287,6 +287,12 @@ BOOL LLVLComposition::generateTexture(const F32 x, const F32 y,
 			BOOL delete_raw = (mDetailTextures[i]->reloadRawImage(ddiscard) != NULL) ;
 			if(mDetailTextures[i]->getRawImageLevel() != ddiscard)//raw iamge is not ready, will enter here again later.
 			{
+                if (mDetailTextures[i]->getDecodePriority() <= 0.0f && !mDetailTextures[i]->hasSavedRawImage())
+                {
+                    mDetailTextures[i]->setBoostLevel(LLGLTexture::BOOST_MAP);
+                    mDetailTextures[i]->forceToRefetchTexture(ddiscard);
+                }
+
 				if(delete_raw)
 				{
 					mDetailTextures[i]->destroyRawImage() ;
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 42550ed48d2176cd0c626c38d8649f37acc9e4aa..176528cb5641afc2a707662c79a13e7d86a532d4 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -10636,7 +10636,7 @@ void LLVOAvatar::updateVisualComplexity()
 // with an avatar. This will be either an attached object or an animated
 // object.
 void LLVOAvatar::accountRenderComplexityForObject(
-    const LLViewerObject *attached_object,
+    LLViewerObject *attached_object,
     const F32 max_attachment_complexity,
     LLVOVolume::texture_cost_t& textures,
     U32& cost,
@@ -10708,7 +10708,7 @@ void LLVOAvatar::accountRenderComplexityForObject(
                     && attached_object->mDrawable)
                 {
                     textures.clear();
-
+                    BOOL is_rigged_mesh = attached_object->isRiggedMesh();
         mAttachmentSurfaceArea += attached_object->recursiveGetScaledSurfaceArea();
 
                     const LLVOVolume* volume = attached_object->mDrawable->getVOVolume();
@@ -10729,6 +10729,7 @@ void LLVOAvatar::accountRenderComplexityForObject(
                             iter != child_list.end(); ++iter)
                         {
                             LLViewerObject* childp = *iter;
+                            is_rigged_mesh |= childp->isRiggedMesh();
                             const LLVOVolume* chld_volume = dynamic_cast<LLVOVolume*>(childp);
                             if (chld_volume)
                             {
@@ -10737,6 +10738,16 @@ void LLVOAvatar::accountRenderComplexityForObject(
                                 hud_object_complexity.objectsCount++;
                             }
                         }
+                        if (is_rigged_mesh && !attached_object->mRiggedAttachedWarned)
+                        {
+                            LLSD args;                            
+                            LLViewerInventoryItem* itemp = gInventory.getItem(attached_object->getAttachmentItemID());
+                            args["NAME"] = itemp ? itemp->getName() : LLTrans::getString("Unknown");
+                            args["POINT"] = LLTrans::getString(getTargetAttachmentPoint(attached_object)->getName());
+                            LLNotificationsUtil::add("RiggedMeshAttachedToHUD", args);
+
+                            attached_object->mRiggedAttachedWarned = true;
+                        }
 
                         hud_object_complexity.texturesCount += textures.size();
 
@@ -10841,7 +10852,7 @@ void LLVOAvatar::calculateUpdateRenderComplexity()
 				 attachment_iter != attachment->mAttachedObjects.end();
 				 ++attachment_iter)
 			{
-                const LLViewerObject* attached_object = attachment_iter->get();
+                LLViewerObject* attached_object = attachment_iter->get();
                 accountRenderComplexityForObject(attached_object, max_attachment_complexity,
                                                  textures, cost, hud_complexity_list);
 			}
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index 8d1dcbcda2a1bc9025556131bb762567187ceaf9..56f2b73befa826be6a3b90f55062d8953939ba55 100644
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -293,7 +293,7 @@ class LLVOAvatar :
 	void			addNameTagLine(const std::string& line, const LLColor4& color, S32 style, const LLFontGL* font, const bool use_ellipses = false);
 	void 			idleUpdateRenderComplexity();
 	void 			idleUpdateDebugInfo();
-    void 			accountRenderComplexityForObject(const LLViewerObject *attached_object,
+    void 			accountRenderComplexityForObject(LLViewerObject *attached_object,
                                                      const F32 max_attachment_complexity,
                                                      LLVOVolume::texture_cost_t& textures,
                                                      U32& cost,
diff --git a/indra/newview/llvoground.h b/indra/newview/llvoground.h
index a53f309e468eefcdaf546a7f569273aa8c4eba97..e7033290c7f54bce5fe7d7782e8c528a63e0d316 100644
--- a/indra/newview/llvoground.h
+++ b/indra/newview/llvoground.h
@@ -49,7 +49,6 @@ class LLVOGround : public LLStaticViewerObject
 	/*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline);
 	/*virtual*/ BOOL		updateGeometry(LLDrawable *drawable);
 
-	void cleanupGL();
 };
 
 #endif // LL_LLVOGROUND_H
diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp
index 2ef2d66f1874b07aa2e591320d207302b7a61f5f..6bb987ede4e329f5dc2eb1f4fc447c3324a12da2 100644
--- a/indra/newview/llvoiceclient.cpp
+++ b/indra/newview/llvoiceclient.cpp
@@ -797,7 +797,10 @@ void LLVoiceClient::addObserver(LLVoiceClientStatusObserver* observer)
 
 void LLVoiceClient::removeObserver(LLVoiceClientStatusObserver* observer)
 {
-	if (mVoiceModule && mVoiceModule->singletoneInstanceExists()) mVoiceModule->removeObserver(observer);
+    if (mVoiceModule)
+    {
+        mVoiceModule->removeObserver(observer);
+    }
 }
 
 void LLVoiceClient::addObserver(LLFriendObserver* observer)
@@ -807,7 +810,10 @@ void LLVoiceClient::addObserver(LLFriendObserver* observer)
 
 void LLVoiceClient::removeObserver(LLFriendObserver* observer)
 {
-	if (mVoiceModule && mVoiceModule->singletoneInstanceExists()) mVoiceModule->removeObserver(observer);
+    if (mVoiceModule)
+    {
+        mVoiceModule->removeObserver(observer);
+    }
 }
 
 void LLVoiceClient::addObserver(LLVoiceClientParticipantObserver* observer)
@@ -817,7 +823,10 @@ void LLVoiceClient::addObserver(LLVoiceClientParticipantObserver* observer)
 
 void LLVoiceClient::removeObserver(LLVoiceClientParticipantObserver* observer)
 {
-	if (mVoiceModule && mVoiceModule->singletoneInstanceExists()) mVoiceModule->removeObserver(observer);
+    if (mVoiceModule)
+    {
+        mVoiceModule->removeObserver(observer);
+    }
 }
 
 std::string LLVoiceClient::sipURIFromID(const LLUUID &id)
diff --git a/indra/newview/llvoiceclient.h b/indra/newview/llvoiceclient.h
index 246883b6110f5a9e945a1a7b72a68f59cf1f9b25..aa67502908d201f973bd99c9de188ed2fb58e114 100644
--- a/indra/newview/llvoiceclient.h
+++ b/indra/newview/llvoiceclient.h
@@ -122,8 +122,6 @@ class LLVoiceModuleInterface
 
 	virtual const LLVoiceVersionInfo& getVersion()=0;
 	
-	virtual bool singletoneInstanceExists()=0;
-	
 	/////////////////////
 	/// @name Tuning
 	//@{
diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp
index ac6369e4e2ccc9d012a9cbb28e59f2cae50f945b..8f0938d01efda29dbfd6296d2211c42bf94a97b5 100644
--- a/indra/newview/llvoicevivox.cpp
+++ b/indra/newview/llvoicevivox.cpp
@@ -1247,8 +1247,8 @@ bool LLVivoxVoiceClient::establishVoiceConnection()
 
         if (result.has("connector"))
         {
-            LLVoiceVivoxStats::getInstance()->establishAttemptEnd(connected);
             connected = LLSD::Boolean(result["connector"]);
+            LLVoiceVivoxStats::getInstance()->establishAttemptEnd(connected);
             if (!connected)
             {
                 if (result.has("retry") && ++retries <= CONNECT_RETRY_MAX && !sShuttingDown)
@@ -4551,9 +4551,7 @@ void LLVivoxVoiceClient::messageEvent(
 						IM_NOTHING_SPECIAL,		// default arg
 						0,						// default arg
 						LLUUID::null,			// default arg
-						LLVector3::zero,		// default arg
-						true);					// prepend name and make it a link to the user's profile
-
+						LLVector3::zero);		// default arg
 			}
 		}		
 	}
@@ -5217,11 +5215,6 @@ void LLVivoxVoiceClient::declineInvite(std::string &sessionHandle)
 	}
 }
 
-bool LLVivoxVoiceClient::singletoneInstanceExists()
-{
-	return LLVivoxVoiceClient::instanceExists();
-}
-
 void LLVivoxVoiceClient::leaveNonSpatialChannel()
 {
     LL_DEBUGS("Voice") << "Request to leave spacial channel." << LL_ENDL;
@@ -6229,7 +6222,7 @@ void LLVivoxVoiceClient::clearSessionHandle(const sessionStatePtr_t &session)
 {
     if (session)
     {
-        if (session->mHandle.empty())
+        if (!session->mHandle.empty())
         {
             sessionMap::iterator iter = mSessionsByHandle.find(session->mHandle);
             if (iter != mSessionsByHandle.end())
diff --git a/indra/newview/llvoicevivox.h b/indra/newview/llvoicevivox.h
index ebc3a62c350428e666be6b25e01d82ba996cbea3..0a785401c11a4494dc36f5b1b38e8f8370a04dec 100644
--- a/indra/newview/llvoicevivox.h
+++ b/indra/newview/llvoicevivox.h
@@ -73,8 +73,6 @@ class LLVivoxVoiceClient :	public LLSingleton<LLVivoxVoiceClient>,
 
 	// Returns true if vivox has successfully logged in and is not in error state	
 	virtual bool isVoiceWorking() const;
-	
-	virtual bool singletoneInstanceExists();
 
 	/////////////////////
 	/// @name Tuning
diff --git a/indra/newview/llvosky.cpp b/indra/newview/llvosky.cpp
index 1aa00bc894c0bfc5b9356ab94b66ad2188af0b31..909588367b4d6157352320c67af03cd9df83419e 100644
--- a/indra/newview/llvosky.cpp
+++ b/indra/newview/llvosky.cpp
@@ -100,8 +100,8 @@ LLSkyTex::LLSkyTex() :
 void LLSkyTex::init(bool isShiny)
 {
     mIsShiny = isShiny;
-	mSkyData = new LLColor4[SKYTEX_RESOLUTION * SKYTEX_RESOLUTION];
-	mSkyDirs = new LLVector3[SKYTEX_RESOLUTION * SKYTEX_RESOLUTION];
+	mSkyData = new LLColor4[(U32)(SKYTEX_RESOLUTION * SKYTEX_RESOLUTION)];
+	mSkyDirs = new LLVector3[(U32)(SKYTEX_RESOLUTION * SKYTEX_RESOLUTION)];
 
 	for (S32 i = 0; i < 2; ++i)
 	{
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index a4e0d367c8bf793c003f16805897de8367f02fb1..2e7ccc83343864f884794e81bcbf322edcbaf1ba 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -228,6 +228,9 @@ LLVOVolume::LLVOVolume(const LLUUID &id, const LLPCode pcode, LLViewerRegion *re
     mColorChanged = FALSE;
 	mSpotLightPriority = 0.f;
 
+	mSkinInfoFailed = false;
+	mSkinInfo = NULL;
+
 	mMediaImplList.resize(getNumTEs());
 	mLastFetchedMediaVersion = -1;
     mServerDrawableUpdateCount = 0;
@@ -244,6 +247,8 @@ LLVOVolume::~LLVOVolume()
 	delete mVolumeImpl;
 	mVolumeImpl = NULL;
 
+	gMeshRepo.unregisterMesh(this);
+
 	if(!mMediaImplList.empty())
 	{
 		for(U32 i = 0 ; i < mMediaImplList.size() ; i++)
@@ -851,10 +856,7 @@ void LLVOVolume::updateTextureVirtualSize(bool forced)
 	
 	if (isSculpted())
 	{
-		LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT);
-		LLUUID id =  sculpt_params->getSculptTexture();
-		
-		updateSculptTexture();
+        updateSculptTexture();
 		
 		
 
@@ -1095,10 +1097,15 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams &params_in, const S32 detail, bo
 			// if it's a mesh
 			if ((volume_params.getSculptType() & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH)
 			{
+				if (mSkinInfo && mSkinInfo->mMeshID != volume_params.getSculptID())
+				{
+					mSkinInfo = NULL;
+					mSkinInfoFailed = false;
+				}
+
 				if (!getVolume()->isMeshAssetLoaded())
 				{ 
 					//load request not yet issued, request pipeline load this mesh
-					LLUUID asset_id = volume_params.getSculptID();
 					S32 available_lod = gMeshRepo.loadMesh(this, volume_params, lod, last_lod);
 					if (available_lod != lod)
 					{
@@ -1106,6 +1113,14 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams &params_in, const S32 detail, bo
 					}
 				}
 				
+				if (!mSkinInfo && !mSkinInfoFailed)
+				{
+					const LLMeshSkinInfo* skin_info = gMeshRepo.getSkinInfo(volume_params.getSculptID(), this);
+					if (skin_info)
+					{
+						notifySkinInfoLoaded(skin_info);
+					}
+				}
 			}
 			else // otherwise is sculptie
 			{
@@ -1158,6 +1173,9 @@ void LLVOVolume::updateSculptTexture()
 		{
 			mSculptTexture = LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
 		}
+
+		mSkinInfoFailed = false;
+		mSkinInfo = NULL;
 	}
 	else
 	{
@@ -1212,6 +1230,20 @@ void LLVOVolume::notifyMeshLoaded()
     updateVisualComplexity();
 }
 
+void LLVOVolume::notifySkinInfoLoaded(const LLMeshSkinInfo* skin)
+{
+	mSkinInfoFailed = false;
+	mSkinInfo = skin;
+
+	notifyMeshLoaded();
+}
+
+void LLVOVolume::notifySkinInfoUnavailable()
+{
+	mSkinInfoFailed = true;
+	mSkinInfo = nullptr;
+}
+
 // sculpt replaces generate() for sculpted surfaces
 void LLVOVolume::sculpt()
 {	
@@ -3645,7 +3677,7 @@ const LLMeshSkinInfo* LLVOVolume::getSkinInfo() const
 {
     if (getVolume())
     {
-        return gMeshRepo.getSkinInfo(getMeshID(), this);
+         return mSkinInfo;
     }
     else
     {
diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h
index 01ad40274b8e2b35840a3dabed83edb43bcfdbb5..59599ddc0c6364089d4e404567d3c7f788c54f0e 100644
--- a/indra/newview/llvovolume.h
+++ b/indra/newview/llvovolume.h
@@ -353,6 +353,8 @@ class LLVOVolume : public LLViewerObject
     void updateVisualComplexity();
     
 	void notifyMeshLoaded();
+	void notifySkinInfoLoaded(const LLMeshSkinInfo* skin);
+	void notifySkinInfoUnavailable();
 	
 	// Returns 'true' iff the media data for this object is in flight
 	bool isMediaDataBeingFetched() const;
@@ -437,6 +439,8 @@ class LLVOVolume : public LLViewerObject
 
 	LLPointer<LLRiggedVolume> mRiggedVolume;
 
+	bool mSkinInfoFailed;
+	LLConstPointer<LLMeshSkinInfo> mSkinInfo;
 	// statics
 public:
 	static F32 sLODSlopDistanceFactor;// Changing this to zero, effectively disables the LOD transition slop
diff --git a/indra/newview/llwearableitemslist.cpp b/indra/newview/llwearableitemslist.cpp
index bf4db8147525772ae80fafa177b195083be812d4..89b74ae96282c416293313d3ac0ae985340fa938 100644
--- a/indra/newview/llwearableitemslist.cpp
+++ b/indra/newview/llwearableitemslist.cpp
@@ -92,17 +92,77 @@ LLPanelWearableListItem::LLPanelWearableListItem(LLViewerInventoryItem* item, co
 //////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////
+static LLWidgetNameRegistry::StaticRegistrar sRegisterPanelWearableOutfitItem(&typeid(LLPanelWearableOutfitItem::Params), "wearable_outfit_list_item");
+
+LLPanelWearableOutfitItem::Params::Params()
+:   add_btn("add_btn"),
+    remove_btn("remove_btn")
+{
+}
+
+BOOL LLPanelWearableOutfitItem::postBuild()
+{
+    LLPanelWearableListItem::postBuild();
+    
+    LLViewerInventoryItem* inv_item = getItem();
+    mShowWidgets &= (inv_item->getType() != LLAssetType::AT_BODYPART);
+    if(mShowWidgets)
+    {
+        addWidgetToRightSide("add_wearable");
+        addWidgetToRightSide("remove_wearable");
+
+        childSetAction("add_wearable", boost::bind(&LLPanelWearableOutfitItem::onAddWearable, this));
+        childSetAction("remove_wearable", boost::bind(&LLPanelWearableOutfitItem::onRemoveWearable, this));
+
+        setWidgetsVisible(false);
+        reshapeWidgets();
+    }
+    return TRUE;
+}
+
+BOOL LLPanelWearableOutfitItem::handleDoubleClick(S32 x, S32 y, MASK mask)
+{
+    if(!mShowWidgets)
+    {
+        return LLPanelWearableListItem::handleDoubleClick(x, y, mask);
+    }
+
+    if(LLAppearanceMgr::instance().isLinkedInCOF(mInventoryItemUUID))
+    {
+        onRemoveWearable();
+    }
+    else
+    {
+        onAddWearable();
+    }
+    return TRUE;
+}
+
+void LLPanelWearableOutfitItem::onAddWearable()
+{
+    setWidgetsVisible(false);
+    reshapeWidgets();
+    LLAppearanceMgr::instance().wearItemOnAvatar(mInventoryItemUUID, true, false);
+}
+
+void LLPanelWearableOutfitItem::onRemoveWearable()
+{
+    setWidgetsVisible(false);
+    reshapeWidgets();
+    LLAppearanceMgr::instance().removeItemFromAvatar(mInventoryItemUUID);
+}
 
 // static
 LLPanelWearableOutfitItem* LLPanelWearableOutfitItem::create(LLViewerInventoryItem* item,
-															 bool worn_indication_enabled)
+															 bool worn_indication_enabled,
+                                                             bool show_widgets)
 {
 	LLPanelWearableOutfitItem* list_item = NULL;
 	if (item)
 	{
-		const LLPanelInventoryListItemBase::Params& params = LLUICtrlFactory::getDefaultParams<LLPanelInventoryListItemBase>();
+		const LLPanelWearableOutfitItem::Params& params = LLUICtrlFactory::getDefaultParams<LLPanelWearableOutfitItem>();
 
-		list_item = new LLPanelWearableOutfitItem(item, worn_indication_enabled, params);
+		list_item = new LLPanelWearableOutfitItem(item, worn_indication_enabled, params, show_widgets);
 		list_item->initFromParams(params);
 		list_item->postBuild();
 	}
@@ -110,11 +170,23 @@ LLPanelWearableOutfitItem* LLPanelWearableOutfitItem::create(LLViewerInventoryIt
 }
 
 LLPanelWearableOutfitItem::LLPanelWearableOutfitItem(LLViewerInventoryItem* item,
-													 bool worn_indication_enabled,
-													 const LLPanelWearableOutfitItem::Params& params)
-: LLPanelInventoryListItemBase(item, params)
+                                                     bool worn_indication_enabled,
+                                                     const LLPanelWearableOutfitItem::Params& params,
+                                                     bool show_widgets)
+: LLPanelWearableListItem(item, params)
 , mWornIndicationEnabled(worn_indication_enabled)
+, mShowWidgets(show_widgets)
 {
+    if(mShowWidgets)
+    {
+        LLButton::Params button_params = params.add_btn;
+        applyXUILayout(button_params, this);
+        addChild(LLUICtrlFactory::create<LLButton>(button_params));
+
+        button_params = params.remove_btn;
+        applyXUILayout(button_params, this);
+        addChild(LLUICtrlFactory::create<LLButton>(button_params));
+    }
 }
 
 // virtual
@@ -127,11 +199,22 @@ void LLPanelWearableOutfitItem::updateItem(const std::string& name,
 	// We don't use get_is_item_worn() here because this update is triggered by
 	// an inventory observer upon link in COF beind added or removed so actual
 	// worn status of a linked item may still remain unchanged.
-	if (mWornIndicationEnabled && LLAppearanceMgr::instance().isLinkedInCOF(mInventoryItemUUID))
+    bool is_worn = LLAppearanceMgr::instance().isLinkedInCOF(mInventoryItemUUID);
+	if (mWornIndicationEnabled && is_worn)
 	{
 		search_label += LLTrans::getString("worn");
 		item_state = IS_WORN;
 	}
+    if(mShowWidgets)
+    {
+        setShowWidget("add_wearable", !is_worn);
+        setShowWidget("remove_wearable", is_worn);
+        if(mHovered)
+        {
+            setWidgetsVisible(true);
+            reshapeWidgets();
+        }
+    }
 
 	LLPanelInventoryListItemBase::updateItem(search_label, item_state);
 }
@@ -634,6 +717,7 @@ static const LLDefaultChildRegistry::Register<LLWearableItemsList> r("wearable_i
 LLWearableItemsList::Params::Params()
 :	standalone("standalone", true)
 ,	worn_indication_enabled("worn_indication_enabled", true)
+,   show_item_widgets("show_item_widgets", false)
 {}
 
 LLWearableItemsList::LLWearableItemsList(const LLWearableItemsList::Params& p)
@@ -649,6 +733,7 @@ LLWearableItemsList::LLWearableItemsList(const LLWearableItemsList::Params& p)
 	}
 	mWornIndicationEnabled = p.worn_indication_enabled;
 	setNoItemsCommentText(LLTrans::getString("LoadingData"));
+    mShowItemWidgets = p.show_item_widgets;
 }
 
 // virtual
@@ -665,7 +750,7 @@ LLPanel* LLWearableItemsList::createNewItem(LLViewerInventoryItem* item)
         return NULL;
     }
 
-    return LLPanelWearableOutfitItem::create(item, mWornIndicationEnabled);
+    return LLPanelWearableOutfitItem::create(item, mWornIndicationEnabled, mShowItemWidgets);
 }
 
 void LLWearableItemsList::updateList(const LLUUID& category_id)
diff --git a/indra/newview/llwearableitemslist.h b/indra/newview/llwearableitemslist.h
index ba8488b23785d62e0cde5cede09c0e30fde51c00..f7774a708643aafbcfb2e847e985a9878aaeaf4c 100644
--- a/indra/newview/llwearableitemslist.h
+++ b/indra/newview/llwearableitemslist.h
@@ -72,12 +72,23 @@ class LLPanelWearableListItem : public LLPanelInventoryListItemBase
  * Extends LLPanelInventoryListItemBase with handling
  * double click to wear the item.
  */
-class LLPanelWearableOutfitItem : public LLPanelInventoryListItemBase
+class LLPanelWearableOutfitItem : public LLPanelWearableListItem
 {
 	LOG_CLASS(LLPanelWearableOutfitItem);
 public:
+    struct Params : public LLInitParam::Block<Params, LLPanelWearableListItem::Params>
+    {
+        Optional<LLButton::Params>   add_btn, remove_btn;
+
+        Params();
+    };
+
+    BOOL postBuild();
+    BOOL handleDoubleClick(S32 x, S32 y, MASK mask);
+
 	static LLPanelWearableOutfitItem* create(LLViewerInventoryItem* item,
-											 bool worn_indication_enabled);
+											 bool worn_indication_enabled,
+                                             bool show_widgets);
 
 	/**
 	 * Updates item name and (worn) suffix.
@@ -85,12 +96,16 @@ class LLPanelWearableOutfitItem : public LLPanelInventoryListItemBase
 	/*virtual*/ void updateItem(const std::string& name,
 								EItemState item_state = IS_DEFAULT);
 
+    void onAddWearable();
+    void onRemoveWearable();
+
 protected:
 	LLPanelWearableOutfitItem(LLViewerInventoryItem* item,
-							  bool worn_indication_enabled, const Params& params);
+							  bool worn_indication_enabled, const Params& params, bool show_widgets = false);
 
 private:
 	bool	mWornIndicationEnabled;
+    bool mShowWidgets;
 };
 
 class LLPanelDeletableWearableListItem : public LLPanelWearableListItem
@@ -442,6 +457,7 @@ class LLWearableItemsList : public LLInventoryItemsList
 	{
 		Optional<bool> standalone;
 		Optional<bool> worn_indication_enabled;
+        Optional<bool> show_item_widgets;
 
 		Params();
 	};
@@ -482,6 +498,7 @@ class LLWearableItemsList : public LLInventoryItemsList
 
 	bool mIsStandalone;
 	bool mWornIndicationEnabled;
+    bool mShowItemWidgets;
 
 	ESortOrder		mSortOrder;
 
diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp
index aa32ef04b289723e29c5a1077da0c95c058143bb..871583e071b59f2e89e556ed9a50010e5f593baf 100644
--- a/indra/newview/llworld.cpp
+++ b/indra/newview/llworld.cpp
@@ -93,7 +93,7 @@ LLWorld::LLWorld() :
 	mLastPacketsLost(0),
 	mSpaceTimeUSec(0)
 {
-	for (S32 i = 0; i < 8; i++)
+	for (S32 i = 0; i < EDGE_WATER_OBJECTS_COUNT; i++)
 	{
 		mEdgeWaterObjects[i] = NULL;
 	}
@@ -126,7 +126,7 @@ void LLWorld::resetClass()
 	LLViewerPartSim::getInstance()->destroyClass();
 
 	mDefaultWaterTexturep = NULL ;
-	for (S32 i = 0; i < 8; i++)
+	for (S32 i = 0; i < EDGE_WATER_OBJECTS_COUNT; i++)
 	{
 		mEdgeWaterObjects[i] = NULL;
 	}
@@ -293,13 +293,13 @@ void LLWorld::removeRegion(const LLHost &host)
 
 	mRegionRemovedSignal(regionp);
 
-	delete regionp;
-
 	updateWaterObjects();
 
 	//double check all objects of this region are removed.
 	gObjectList.clearAllMapObjectsInRegion(regionp) ;
 	//llassert_always(!gObjectList.hasMapObjectInRegion(regionp)) ;
+
+	delete regionp; // Delete last to prevent use after free
 }
 
 
@@ -753,6 +753,8 @@ void LLWorld::clearAllVisibleObjects()
 		//clear all cached visible objects.
 		(*iter)->clearCachedVisibleObjects();
 	}
+    clearHoleWaterObjects();
+    clearEdgeWaterObjects();
 }
 
 void LLWorld::updateParticles()
@@ -920,7 +922,7 @@ void LLWorld::precullWaterObjects(LLCamera& camera, LLCullResult* cull, bool inc
     }
 
 	S32 dir;
-	for (dir = 0; dir < 8; dir++)
+	for (dir = 0; dir < EDGE_WATER_OBJECTS_COUNT; dir++)
 	{
 		LLVOWater* waterp = mEdgeWaterObjects[dir];
 		if (waterp && waterp->mDrawable)
@@ -931,6 +933,26 @@ void LLWorld::precullWaterObjects(LLCamera& camera, LLCullResult* cull, bool inc
 	}
 }
 
+void LLWorld::clearHoleWaterObjects()
+{
+    for (std::list<LLPointer<LLVOWater> >::iterator iter = mHoleWaterObjects.begin();
+        iter != mHoleWaterObjects.end(); ++iter)
+    {
+        LLVOWater* waterp = (*iter).get();
+        gObjectList.killObject(waterp);
+    }
+    mHoleWaterObjects.clear();
+}
+
+void LLWorld::clearEdgeWaterObjects()
+{
+    for (S32 i = 0; i < EDGE_WATER_OBJECTS_COUNT; i++)
+    {
+        gObjectList.killObject(mEdgeWaterObjects[i]);
+        mEdgeWaterObjects[i] = NULL;
+    }
+}
+
 void LLWorld::updateWaterObjects()
 {
 	if (!gAgent.getRegion())
@@ -974,13 +996,7 @@ void LLWorld::updateWaterObjects()
 		}
 	}
 
-	for (std::list<LLPointer<LLVOWater> >::iterator iter = mHoleWaterObjects.begin();
-		 iter != mHoleWaterObjects.end(); ++ iter)
-	{
-		LLVOWater* waterp = (*iter).get();
-		gObjectList.killObject(waterp);
-	}
-	mHoleWaterObjects.clear();
+    clearHoleWaterObjects();
 
 	// Use the water height of the region we're on for areas where there is no region
 	F32 water_height = gAgent.getRegion()->getWaterHeight();
@@ -1021,7 +1037,7 @@ void LLWorld::updateWaterObjects()
 		(S32)(512 - (region_y - min_y)) };
 		
 	S32 dir;
-	for (dir = 0; dir < 8; dir++)
+	for (dir = 0; dir < EDGE_WATER_OBJECTS_COUNT; dir++)
 	{
 		S32 dim[2] = { 0 };
 		switch (gDirAxes[dir][0])
diff --git a/indra/newview/llworld.h b/indra/newview/llworld.h
index 5c43cdf4e274f932a5bce44fd11c1de7ff90f932..5dee8eea0fc767a4afbd1e20d9b502ede7bf9af2 100644
--- a/indra/newview/llworld.h
+++ b/indra/newview/llworld.h
@@ -122,12 +122,9 @@ class LLWorld : public LLSimpleton<LLWorld>
 	void					updateRegions(F32 max_update_time);
 	void					updateVisibilities();
 	void					updateParticles();
-	void					updateClouds(const F32 dt);
-	LLCloudGroup *			findCloudGroup(const LLCloudPuff &puff);
 
 	void					renderPropertyLines();
 
-	void resetStats();
 	void updateNetStats(); // Update network statistics for all the regions...
 
 	void printPacketsLost();
@@ -140,7 +137,7 @@ class LLWorld : public LLSimpleton<LLWorld>
 	void setLandFarClip(const F32 far_clip);
 
 	LLViewerTexture *getDefaultWaterTexture();
-	void updateWaterObjects();
+    void updateWaterObjects();
 
     void precullWaterObjects(LLCamera& camera, LLCullResult* cull, bool include_void_water);
 
@@ -175,6 +172,9 @@ class LLWorld : public LLSimpleton<LLWorld>
 	bool isRegionListed(const LLViewerRegion* region) const;
 
 private:
+    void clearHoleWaterObjects();
+    void clearEdgeWaterObjects();
+
 	region_list_t	mActiveRegionList;
 	region_list_t	mRegionList;
 	region_list_t	mVisibleRegionList;
@@ -198,15 +198,14 @@ class LLWorld : public LLSimpleton<LLWorld>
 	U32 mNumOfActiveCachedObjects;
 	U64MicrosecondsImplicit mSpaceTimeUSec;
 
-	BOOL mClassicCloudsEnabled;
-
 	////////////////////////////
 	//
 	// Data for "Fake" objects
 	//
 
 	std::list<LLPointer<LLVOWater> > mHoleWaterObjects;
-	LLPointer<LLVOWater> mEdgeWaterObjects[8];
+    static const S32 EDGE_WATER_OBJECTS_COUNT = 8;
+    LLPointer<LLVOWater> mEdgeWaterObjects[EDGE_WATER_OBJECTS_COUNT];
 
 	LLPointer<LLViewerTexture> mDefaultWaterTexturep;
 };
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index 96ba80dacc5a22ce8515d8e846c2f9324350a2c8..13d6966723640a9f3805e0f8de0cb3648dfdbaeb 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -685,7 +685,9 @@ void LLPipeline::cleanup()
 
 	mFaceSelectImagep = NULL;
 
-	mMovedBridge.clear();
+    mMovedList.clear();
+    mMovedBridge.clear();
+    mShiftList.clear();
 
 	mInitialized = false;
 
@@ -1773,15 +1775,20 @@ void LLPipeline::unlinkDrawable(LLDrawable *drawable)
 void LLPipeline::removeMutedAVsLights(LLVOAvatar* muted_avatar)
 {
     LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE;
-	for (light_set_t::iterator iter = gPipeline.mNearbyLights.begin();
-		 iter != gPipeline.mNearbyLights.end(); iter++)
-	{
-		if (iter->drawable->getVObj()->isAttachment() && iter->drawable->getVObj()->getAvatar() == muted_avatar)
-		{
-			gPipeline.mLights.erase(iter->drawable);
-			gPipeline.mNearbyLights.erase(iter);
-		}
-	}
+    light_set_t::iterator iter = gPipeline.mNearbyLights.begin();
+
+    while (iter != gPipeline.mNearbyLights.end())
+    {
+        if (iter->drawable->getVObj()->isAttachment() && iter->drawable->getVObj()->getAvatar() == muted_avatar)
+        {
+            gPipeline.mLights.erase(iter->drawable);
+            iter = gPipeline.mNearbyLights.erase(iter);
+        }
+        else
+        {
+            iter++;
+        }
+    }
 }
 
 U32 LLPipeline::addObject(LLViewerObject *vobj)
@@ -2817,6 +2824,14 @@ void LLPipeline::clearRebuildDrawables()
 		drawablep->clearState(LLDrawable::EARLY_MOVE | LLDrawable::MOVE_UNDAMPED | LLDrawable::ON_MOVE_LIST | LLDrawable::ANIMATED_CHILD);
 	}
 	mMovedList.clear();
+
+    for (LLDrawable::drawable_vector_t::iterator iter = mShiftList.begin();
+        iter != mShiftList.end(); ++iter)
+    {
+        LLDrawable *drawablep = *iter;
+        drawablep->clearState(LLDrawable::EARLY_MOVE | LLDrawable::MOVE_UNDAMPED | LLDrawable::ON_MOVE_LIST | LLDrawable::ANIMATED_CHILD | LLDrawable::ON_SHIFT_LIST);
+    }
+    mShiftList.clear();
 }
 
 void LLPipeline::rebuildPriorityGroups()
@@ -10906,6 +10921,8 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar, bool preview_avatar)
         if (preview_avatar)
         {
             // Only show rigged attachments for preview
+            // For the sake of performance and so that static
+            // objects won't obstruct previewing changes
             LLVOAvatar::attachment_map_t::iterator iter;
             for (iter = avatar->mAttachmentPoints.begin();
                 iter != avatar->mAttachmentPoints.end();
@@ -10917,9 +10934,27 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar, bool preview_avatar)
                     ++attachment_iter)
                 {
                     LLViewerObject* attached_object = attachment_iter->get();
-                    if (attached_object && attached_object->isRiggedMesh())
+                    if (attached_object)
                     {
-                        markVisible(attached_object->mDrawable->getSpatialBridge(), *viewer_camera);
+                        if (attached_object->isRiggedMesh())
+                        {
+                            markVisible(attached_object->mDrawable->getSpatialBridge(), *viewer_camera);
+                        }
+                        else
+                        {
+                            // sometimes object is a linkset and rigged mesh is a child
+                            LLViewerObject::const_child_list_t& child_list = attached_object->getChildren();
+                            for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
+                                iter != child_list.end(); iter++)
+                            {
+                                LLViewerObject* child = *iter;
+                                if (child->isRiggedMesh())
+                                {
+                                    markVisible(attached_object->mDrawable->getSpatialBridge(), *viewer_camera);
+                                    break;
+                                }
+                            }
+                        }
                     }
                 }
             }
diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h
index 62d3ae7a398884ffa2129f22892ca7258f6a73ea..0830d4a2ea0581fe2930443b5070fe7f7a8679a2 100644
--- a/indra/newview/pipeline.h
+++ b/indra/newview/pipeline.h
@@ -465,7 +465,7 @@ class LLPipeline
         RENDER_TYPE_PASS_SIMPLE_RIGGED = LLRenderPass::PASS_SIMPLE_RIGGED,
 		RENDER_TYPE_PASS_GRASS					= LLRenderPass::PASS_GRASS,
 		RENDER_TYPE_PASS_FULLBRIGHT				= LLRenderPass::PASS_FULLBRIGHT,
-        RENDER_TYPE_PASS_FULLBRIGHT_RIGGED = LLRenderPass::PASS_FULLBRIGHT,
+        RENDER_TYPE_PASS_FULLBRIGHT_RIGGED = LLRenderPass::PASS_FULLBRIGHT_RIGGED,
 		RENDER_TYPE_PASS_INVISIBLE				= LLRenderPass::PASS_INVISIBLE,
         RENDER_TYPE_PASS_INVISIBLE_RIGGED = LLRenderPass::PASS_INVISIBLE_RIGGED,
 		RENDER_TYPE_PASS_INVISI_SHINY			= LLRenderPass::PASS_INVISI_SHINY,
diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml
index c3ce83e834737203daa8e5c1459aad1041d6e76c..8bb3feaeb0df1d2fff093b8d57edf80e46951d3f 100644
--- a/indra/newview/skins/default/colors.xml
+++ b/indra/newview/skins/default/colors.xml
@@ -985,4 +985,10 @@
   <color
     name="AddPaymentPanel"
     value="0.27 0.27 0.27 1" />
+  <color
+    name="OutfitSnapshotMacMask"
+    value="0.115 0.115 0.115 1"/>
+ <color
+   name="OutfitSnapshotMacMask2"
+   value="0.1 0.1 0.1 1"/>
 </colors>
diff --git a/indra/newview/skins/default/textures/icons/add_icon.png b/indra/newview/skins/default/textures/icons/add_icon.png
new file mode 100644
index 0000000000000000000000000000000000000000..cb68ee8e16d59fc379949164be128432622f8cdf
Binary files /dev/null and b/indra/newview/skins/default/textures/icons/add_icon.png differ
diff --git a/indra/newview/skins/default/textures/icons/remove_icon.png b/indra/newview/skins/default/textures/icons/remove_icon.png
new file mode 100644
index 0000000000000000000000000000000000000000..6e62ee33f49f64c703bf0557cfc683ee5612219f
Binary files /dev/null and b/indra/newview/skins/default/textures/icons/remove_icon.png differ
diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml
index 4429a1677e7cc1e7a71de6fa7afa2638f9b00e69..1f2c0867c4d32e1f8b788b9c86bd9285c32f76b2 100644
--- a/indra/newview/skins/default/textures/textures.xml
+++ b/indra/newview/skins/default/textures/textures.xml
@@ -743,6 +743,9 @@ with the same filename but different name
   
   <texture name="Wearables_Divider" file_name="windows/Wearables_Divider.png" preload="false" />
 
+  <texture name="Add_Icon" file_name="icons/add_icon.png" preload="false" />
+  <texture name="Remove_Icon" file_name="icons/remove_icon.png" preload="false" />
+
   <texture name="Web_Profile_Off" file_name="icons/Web_Profile_Off.png" preload="false" />
 
   <texture name="WellButton_Lit" file_name="bottomtray/WellButton_Lit.png"  preload="true" scale.left="4" scale.top="19" scale.right="28" scale.bottom="4" />
diff --git a/indra/newview/skins/default/xui/en/floater_about_land.xml b/indra/newview/skins/default/xui/en/floater_about_land.xml
index 4678d65b85691db0426b52c0a1537e53f878dab6..c6776ad039d892856a476ac0a20436a10536c3c6 100644
--- a/indra/newview/skins/default/xui/en/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/en/floater_about_land.xml
@@ -1908,7 +1908,7 @@ Only large parcels can be listed in search.
             </text>
             <check_box
              height="16"
-             label="Obscure MOAP"
+             label="Restrict MOAP to this parcel"
              layout="topleft"
              left="110"
              left_pad="0"
diff --git a/indra/newview/skins/default/xui/en/floater_how_to.xml b/indra/newview/skins/default/xui/en/floater_how_to.xml
index baff8e1bc065ad3cdcb90d7be0c6965f131a5fd2..19e42798af7a65c1d9f3ebfe804474d08c37cb57 100644
--- a/indra/newview/skins/default/xui/en/floater_how_to.xml
+++ b/indra/newview/skins/default/xui/en/floater_how_to.xml
@@ -3,7 +3,6 @@
   legacy_header_height="18"
   can_resize="false"
   can_minimize="false"
-  can_close="false"
   height="525"
   layout="topleft"
   name="floater_how_to"
diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml
index 15f02ab9c35f3ab925a733185fc9d1a69b23b0f5..da84fbeea62449f6dda28ec0b43b44fc5fb38d17 100644
--- a/indra/newview/skins/default/xui/en/floater_im_session.xml
+++ b/indra/newview/skins/default/xui/en/floater_im_session.xml
@@ -220,20 +220,6 @@
                          left="1"
                          right="-1"
                          bottom="-1">
-                            <layout_panel
-                             auto_resize="false"
-                             height="26"
-                             name="translate_chat_checkbox_lp">
-                                <check_box
-                                 top="10"
-                                 control_name="TranslateChat"
-                                 enabled="true"
-                                 height="16"
-                                 label="Translate chat"
-                                 left="5"
-                                 name="translate_chat_checkbox"
-                                 width="230" />
-                            </layout_panel>
                             <layout_panel
                              name="chat_holder">
                                 <chat_history
diff --git a/indra/newview/skins/default/xui/en/floater_object_weights.xml b/indra/newview/skins/default/xui/en/floater_object_weights.xml
index eb283a1043d57dc1123ccfdd09efcfee6267606a..889efa061c1a3765a02866a63987bd3425d5b139 100644
--- a/indra/newview/skins/default/xui/en/floater_object_weights.xml
+++ b/indra/newview/skins/default/xui/en/floater_object_weights.xml
@@ -2,7 +2,7 @@
 <floater
  can_close="true"
  can_tear_off="false"
- height="315"
+ height="289"
  help_topic="object_weights"
  layout="topleft"
  name="object_weights"
@@ -320,23 +320,4 @@
      top_delta="0"
      value="Total capacity"
      width="130" />
-    <view_border
-     bevel_style="none"
-     follows="top|left"
-     height="0"
-     layout="topleft"
-     left="10"
-     name="land_impacts_text_border"
-     top_pad="5"
-     width="180"/>
-
-    <text
-     follows="left|top"
-     height="16"
-     layout="topleft"
-     left="10"
-     name="help_SLURL"
-     top_pad="10"
-     value="[secondlife:///app/help/object_weights What is all this?...]"
-     width="180" />
 </floater>
diff --git a/indra/newview/skins/default/xui/en/floater_openobject.xml b/indra/newview/skins/default/xui/en/floater_openobject.xml
index 912db80bccc00904990ba07335af9b98b829d288..ec03d7d32cd637d1a6827ce0a65e7f90d5782dd9 100644
--- a/indra/newview/skins/default/xui/en/floater_openobject.xml
+++ b/indra/newview/skins/default/xui/en/floater_openobject.xml
@@ -3,7 +3,7 @@
  legacy_header_height="18"
  can_resize="true"
  default_tab_group="1"
- height="370"
+ height="350"
  layout="topleft"
  min_height="190"
  min_width="285"
@@ -31,62 +31,18 @@
      background_visible="false"
      draw_border="false"
      follows="all"
-     height="240"
+     height="265"
      layout="topleft"
+     show_root_folder="false"
      left="10"
      name="object_contents"
      top_pad="0"
      width="284" />
-  	<view_border
-     bevel_style="none"
-     follows="bottom|left"
-     height="50"
-     highlight_light_color="0.6 0.6 0.6"
-     layout="topleft"
-     left="10"
-     name="border"
-     top_pad="5"
-     width="270"/> 
-  	<text
-  	 follows="bottom|left"
-  	 height="15"
-  	 layout="topleft"
-  	 left="15"
-  	 name="border_note"
-  	 text_color="White"
-  	 top_delta="5">
-  	 	Copy to inventory and wear
-    </text>  
- 	<button
-     follows="bottom|left"
-     height="23"
-     label="Add to outfit"
-     label_selected="Add to outfit"
-     layout="topleft"
- 	 left="15"    
-     name="copy_and_wear_button" 	
- 	 top_pad="3"	
-     width="135">
-        <button.commit_callback
-         function="OpenObject.MoveAndWear" />
-    </button>
-	<button
-     follows="bottom|left"
-     height="23"
-     label="Replace outfit"
-     label_selected="Replace outfit"
-     layout="topleft"
-     left_pad="5"
-     name="copy_and_replace_button"
-     width="120">
-        <button.commit_callback
-         function="OpenObject.ReplaceOutfit" />
-    </button>  
     <button
      follows="bottom|left"
      height="23"
      label="Only copy to inventory"
-     label_selected="Only copy to inventory"
+     label_selected="Copy to inventory"
      layout="topleft"
      left="15"
      name="copy_to_inventory_button"
diff --git a/indra/newview/skins/default/xui/en/floater_outfit_snapshot.xml b/indra/newview/skins/default/xui/en/floater_outfit_snapshot.xml
deleted file mode 100644
index 15c480f144777e18527f117714b0debd7fc1a2e7..0000000000000000000000000000000000000000
--- a/indra/newview/skins/default/xui/en/floater_outfit_snapshot.xml
+++ /dev/null
@@ -1,351 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater
- positioning="cascading"
- legacy_header_height="18"
- can_minimize="true"
- can_resize="false"
- can_close="true"
- height="455"
- layout="topleft"
- name="outfit_snapshot"
- single_instance="true"
- help_topic="snapshot"
- save_rect="true"
- save_visibility="false"
- title="OUTFIT SNAPSHOT"
- width="624"
- min_height="455">
-  <floater.string
-   name="unknown">
-    unknown
-  </floater.string>
-  <string
-   name="inventory_progress_str">
-    Saving to Inventory
-  </string>
-  <string
- 	 name="inventory_succeeded_str">
-    Saved to Inventory!
-  </string>
-  <string
- 	 name="inventory_failed_str">
-    Failed to save to inventory.
-  </string>
-  <button
-     follows="left|top"
-     height="25"
-     image_overlay="Refresh_Off"
-	 image_hover_unselected="Toolbar_Middle_Over"
-     image_selected="Toolbar_Middle_Selected"
-     image_unselected="Toolbar_Middle_Off"
-     image_overlay_alignment="left"
-     imgoverlay_label_space="5"
-	 pad_bottom="0"
-	 halign="left"
-     layout="topleft"
-     left="10"
-	 label="REFRESH"
-     name="new_snapshot_btn"
-     top_pad="26"
-     width="167" />
-	<button
-       follows="left|top"
-	   control_name="AdvanceOutfitSnapshot"
-	   invisibility_control="AdvanceOutfitSnapshot"
-       height="25"
-	   is_toggle="true"
-       layout="topleft"
-	   image_hover_unselected="Toolbar_Middle_Over"
-	   image_selected="Toolbar_Middle_Off"
-	   image_unselected="Toolbar_Middle_Off"
-	   image_overlay="Conv_toolbar_expand"
-       name="retract_btn"
-       left_pad="1"
-	   top_delta="0"
-       width="31" />
-   <button
-       follows="left|top"
-	   control_name="AdvanceOutfitSnapshot"
-	   visibility_control="AdvanceOutfitSnapshot"
-       height="25"
-	   is_toggle="true"
-       layout="topleft"
-	   image_overlay="Conv_toolbar_collapse"
-	   image_hover_unselected="Toolbar_Middle_Over"
-	   image_selected="Toolbar_Middle_Off"
-	   image_unselected="Toolbar_Middle_Off"
-       name="extend_btn"
-       left_delta="0"
-	   top_delta="0"
-       width="31" />
-	<panel
-     height="154"
-     layout="topleft"
-	 follows="top|left"
-     left="0"
-     name="advanced_options_panel"
-     top_pad="-6"
-     width="210">
-        <view_border 
-         bevel_style="in"
-         follows="left|top|right" 
-         height="1"
-         left="10"
-         layout="topleft"
-         name="advanced_options_hr"
-         right="-1"
-         top_pad="5"
-         />
-        <text
-         type="string"
-         length="1"
-         follows="left|top"
-         height="13"
-         layout="topleft"
-         left="10"
-         name="layer_type_label"
-         top_pad="10"
-         width="100">
-            Capture:
-        </text>
-        <check_box
-         label="Interface"
-         layout="topleft"
-         left="30"
-		 height="16"
-         top_pad="8"
-         width="180"
-         name="ui_check" />
-        <check_box
-         label="HUDs"
-         layout="topleft"
-		 height="16"
-         left="30"
-         top_pad="1"
-         width="180"
-         name="hud_check" />
-        <check_box
-         label="Freeze frame (fullscreen)"
-         layout="topleft"
-		 height="16"
-         left="10"
-         top_pad="1"
-         width="180"
-         name="freeze_frame_check" />
-        <check_box
-         label="Auto-refresh"
-         layout="topleft"
-		 height="16"
-         left="10"
-         top_pad="1"
-         width="180"
-         name="auto_snapshot_check" />
-        <text
-         type="string"
-         length="1"
-         follows="left|top"
-         height="13"
-         layout="topleft"
-         left="10"
-         name="filter_list_label"
-         top_pad="10"
-         width="50">
-            Filter:
-        </text>
-        <combo_box
-            control_name="PhotoFilters"
-            follows="left|right|top"
-            name="filters_combobox"
-            tool_tip="Image filters"
-            top_delta="-3"
-            left="50"
-			right="-1"
-            height="21"
-            width="135">
-            <combo_box.item
-            label="No Filter"
-            name="NoFilter"
-            value="NoFilter" />
-        </combo_box>
-		 <view_border 
-         bevel_style="in"
-         follows="left|top|right" 
-         height="1"
-         left="10"
-         layout="topleft"
-         name="advanced_options_hr"
-         right="-1"
-         top_pad="7"
-         />
-    </panel>
-      <panel
-        class="llpaneloutfitsnapshotinventory"
-        follows="left|top"
-        height="230"
-        layout="topleft"
-        left="0"
-        name="panel_outfit_snapshot_inventory"
-        filename="panel_outfit_snapshot_inventory.xml"
-        top_pad="10"
-        width="215"
-      />
-	<view_border 
-         bevel_style="in"
-         follows="left|top" 
-         height="1"
-         left="10"
-         layout="topleft"
-         name="status_hr"
-         width="199"
-         top_pad="-16"/>
-	<panel
-       background_visible="false"
-       follows="left|top"
-       font="SansSerifLarge"
-       halign="center"
-       height="20"
-       layout="topleft"
-       left="10"
-       length="1"
-       name="succeeded_panel"
-	   width="198"
-       top_pad="1"
-       type="string"
-       visible="false">
-          <text
-           follows="all"
-           font="SansSerif"
-           halign="center"
-           height="18"
-           layout="topleft"
-           left="1"
-           length="1"
-           name="succeeded_lbl"
-           right="-1"
-           text_color="0.2 0.85 0.2 1"
-           top="4"
-           translate="false"
-           type="string">
-              Succeeded
-          </text>
-      </panel>
-      <panel
-       background_visible="false"
-       follows="left|top"
-       font="SansSerifLarge"
-       halign="center"
-       height="20"
-       layout="topleft"
-       left="10"
-       length="1"
-       name="failed_panel"
-	   width="198"
-       top_delta="0"
-       type="string"
-       visible="false">
-          <text
-           follows="all"
-           font="SansSerif"
-           halign="center"
-           height="18"
-           layout="topleft"
-           left="1"
-           length="1"
-           name="failed_lbl"
-           right="-1"
-           text_color="0.95 0.4 0.4 1"
-           top="4"
-           translate="false"
-           type="string">
-              Failed
-          </text>
-      </panel>
-      <loading_indicator
-       follows="left|top"
-       height="24"
-       layout="topleft"
-       name="working_indicator"
-       left="10"
-       top_delta="0"
-       visible="false"
-       width="24" />
-      <text
-       follows="left|top"
-       font="SansSerifBold"
-       height="14"
-       layout="topleft"
-       left_pad="3"
-       length="1"
-       halign="left"
-       name="working_lbl"
-       top_delta="5"
-       translate="false"
-       type="string"
-       visible="false"
-       width="162">
-          Working
-      </text>
-      <text
-       follows="left|top"
-       font="SansSerifBold"
-       halign="left"
-       height="18"
-       layout="topleft"
-       left="10"
-       length="1"
-       name="refresh_lbl"
-       text_color="0.95 0.4 0.4 1"
-       top_delta="0"
-       translate="false"
-       type="string"
-       visible="false"
-       width="130">
-          Refresh to save.
-      </text>
-  <ui_ctrl 
-    layout="topleft"
-    name="thumbnail_placeholder"
-    top="23"
-	left="215"
-	width="400"
-	height="400"
-    follows="top|left"/>
-  <view_border 
-   bevel_style="in" 
-   height="21"
-   layout="topleft"
-   name="img_info_border"
-   top_pad="0"
-   right="-10"
-   follows="left|top|right"
-   left_delta="0"/>
-   <text
-    type="string"
-    font="SansSerifSmall"
-    length="1"
-    follows="left|top|right"
-    height="14"
-    layout="topleft"
-    left="220"
-	right="-20"
-    halign="left"
-    name="image_res_text"
-    top_delta="5"
-    width="200">
-       [WIDTH]px (width) x [HEIGHT]px (height)
-   </text>
-   <text
-    follows="right|top"
-    font="SansSerifSmall"
-    height="14"
-    layout="topleft"
-    left="-65"
-    length="1"
-    halign="right"
-    name="file_size_label"
-    top_delta="0"
-    type="string"
-    width="50">
-       [SIZE] KB
-   </text>
-</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_pathfinding_linksets.xml b/indra/newview/skins/default/xui/en/floater_pathfinding_linksets.xml
index 41384a77b835b259cf37ebac3e9f0be55ca954d8..59117c01782d85513fa74987116c651adc5b1adf 100644
--- a/indra/newview/skins/default/xui/en/floater_pathfinding_linksets.xml
+++ b/indra/newview/skins/default/xui/en/floater_pathfinding_linksets.xml
@@ -82,17 +82,20 @@
         width="62">
       Name
     </text>
-    <line_editor
-        border_style="line"
-        border_thickness="1"
-        follows="left|top"
-        height="20"
-        layout="topleft"
-        left_pad="0"
-        top_pad="-18"
-        max_length_chars="255"
-        name="filter_by_name"
-        width="161" />
+
+    <search_editor
+       follows="left|top"
+       search_button_visible="false"
+       height="20"
+       text_readonly_color="DkGray"
+       label="Objects by Name"
+       layout="topleft"
+       left_pad="0"
+       top_pad="-18"
+       name="filter_by_name"
+       select_on_focus="true"
+       width="161">
+    </search_editor>
     <text
         name="linksets_desc_label"
         height="13"
@@ -108,17 +111,19 @@
         width="88">
       Description
     </text>
-    <line_editor
-        border_style="line"
-        border_thickness="1"
-        follows="left|top"
-        height="20"
-        layout="topleft"
-        left_pad="0"
-        top_pad="-17"
-        max_length_chars="255"
-        name="filter_by_description"
-        width="162" />
+    <search_editor
+       follows="left|top"
+       search_button_visible="false"
+       height="20"
+       text_readonly_color="DkGray"
+       label="Objects by Description"
+       layout="topleft"
+       left_pad="0"
+       top_pad="-17"
+       name="filter_by_description"
+       select_on_focus="true"
+       width="162">
+    </search_editor>
     <combo_box
         height="20"
         layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/floater_settings_debug.xml b/indra/newview/skins/default/xui/en/floater_settings_debug.xml
index 3ed2bd72061c4e27a4e506c3b6969d58336bd986..e4fda5cd108320022ef3be55fb44b29f5f72ecbb 100644
--- a/indra/newview/skins/default/xui/en/floater_settings_debug.xml
+++ b/indra/newview/skins/default/xui/en/floater_settings_debug.xml
@@ -2,41 +2,79 @@
 <floater
  legacy_header_height="18"
  can_minimize="false"
- height="215"
+ height="360"
+ min_height="367"
  layout="topleft"
  name="settings_debug"
  help_topic="settings_debug"
  title="DEBUG SETTINGS"
- width="350">
-    <combo_box
-     allow_text_entry="true"
-     follows="top|left"
-     height="22"
-     layout="topleft"
-     left="15"
-     max_chars="255"
-     name="settings_combo"
-     top="30"
-     width="320">
-      <combo_box.commit_callback
-       function="SettingSelect" />
-    </combo_box>
-    <text_editor
-     enabled="false"
-     height="60"
-     layout="topleft"
-     left_delta="0"
-     name="comment_text"
-     top_pad="10"
-     width="320"
-     word_wrap="true" />
+ reuse_instance="true"
+ can_resize="true"
+ min_width="550"
+ width="570">
+  <filter_editor
+   follows="left|top|right"
+   height="23"
+   layout="topleft"
+   left="10"
+   right="-10"
+   label="Enter search text"
+   max_length_chars="300"
+   name="filter_input"
+   text_pad_left="10"
+   top="30" />
+  <scroll_list
+   column_padding="0"
+   draw_heading="true"
+   draw_stripes="false"
+   heading_height="23"
+   height="266"
+   layout="topleft"
+   search_column="1"
+   left="10"
+   follows="left|top|bottom"
+   name="setting_list"
+   top_pad="2"
+   width="300">
+    <scroll_list.columns
+     name="changed_setting"
+     relative_width="0.05"  />
+    <scroll_list.columns
+     label="Setting"
+     name="setting" />
+  </scroll_list>
+  <text
+   type="string"
+   length="1"
+   follows="left|top"
+   height="16"
+   layout="topleft"
+   name="setting_name_txt"
+   font="SansSerifSmallBold"
+   top_delta="8"
+   left_pad="10"
+   visible="false"
+   use_ellipses="true"
+   text_color="White"
+   width="240">
+    Debug setting name
+  </text>
+  <text_editor
+   enabled="false"
+   height="75"
+   layout="topleft"
+   visible="false"
+   name="comment_text"
+   follows="left|top"
+   width="240"
+   top_delta="20"
+   word_wrap="true" />
   <radio_group
    follows="top|left"
    height="30"
    layout="topleft"
-   left_delta="0"
    name="boolean_combo"
-   top_pad="10"
+   top_pad="15"
    visible="false"
    tab_stop="true" 
    width="100">
@@ -55,21 +93,25 @@
   </radio_group>
     <line_editor
      height="20"
+     follows="top|left"
      layout="topleft"
      left_delta="0"
      name="val_text"
      top_delta="0"
      visible="false"
-     width="300" >
+     width="220" >
       <line_editor.commit_callback
        function="CommitSettings" />
     </line_editor>
     <color_swatch
-     bottom="185"
+     top_delta="0"
+     left_delta="0"
+     follows="top|left"
      can_apply_immediately="true"
      height="55"
      name="val_color_swatch"
      label="Color"
+     visible="false"
      layout="topleft"
      width="37" >
       <color_swatch.commit_callback
@@ -79,10 +121,11 @@
      height="20"
      label="x"
      layout="topleft"
+     follows="top|left"
      left_delta="0"
      max_val="1e+007"
      name="val_spinner_1"
-     top_delta="10"
+     top_delta="5"
      visible="false"
      width="120" >
       <spinner.commit_callback
@@ -92,10 +135,11 @@
      height="20"
      label="x"
      layout="topleft"
-     left_pad="15"
+     follows="top|left"
+     left_delta="0"
      max_val="1e+007"
      name="val_spinner_2"
-     top_delta="0"
+     top_pad="10"
      visible="false"
      width="120">
       <spinner.commit_callback
@@ -105,10 +149,11 @@
      height="20"
      label="x"
      layout="topleft"
-     left="15"
+     follows="top|left"
+     left_delta="0"
      max_val="1e+007"
      name="val_spinner_3"
-     top="160"
+     top_pad="10"
      visible="false"
      width="120">
       <spinner.commit_callback
@@ -118,10 +163,11 @@
      height="20"
      label="x"
      layout="topleft"
-     left_pad="15"
+     follows="top|left"
+     left_delta="0"
      max_val="1e+007"
      name="val_spinner_4"
-     top_delta="0"
+     top_pad="10"
      visible="false"
      width="120" >
       <spinner.commit_callback
@@ -130,12 +176,26 @@
     <button
      height="22"
      label="Reset to default"
+     follows="left|top"
      layout="topleft"
-     left="15"
+     left_delta="0"
      name="default_btn"
-     top="186"
+     visible="false"
+     top_pad="10"
      width="150" >
       <button.commit_callback
        function="ClickDefault" />
     </button>
+    <check_box
+      control_name="DebugSettingsHideDefault"
+      height="16"
+      initial_value="true"
+      label="Show changed settings only"
+      layout="topleft"
+      top_pad="10"
+      left="10"
+      follows="left|bottom"
+      name="hide_default"
+      width="330">
+    </check_box>
 </floater>
diff --git a/indra/newview/skins/default/xui/en/floater_simple_outfit_snapshot.xml b/indra/newview/skins/default/xui/en/floater_simple_outfit_snapshot.xml
new file mode 100644
index 0000000000000000000000000000000000000000..5ece7b85d583842c84d35f68701e05d7efd602e2
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_simple_outfit_snapshot.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ positioning="cascading"
+ legacy_header_height="18"
+ can_minimize="true"
+ can_resize="false"
+ can_close="true"
+ height="305"
+ layout="topleft"
+ name="simple_outfit_snapshot"
+ single_instance="true"
+ help_topic="snapshot"
+ save_rect="true"
+ save_visibility="false"
+ title="OUTFIT SNAPSHOT"
+ width="351">
+  <ui_ctrl
+   layout="topleft"
+   name="thumbnail_placeholder"
+   top="18"
+   left="22"
+   width="335"
+   height="200"
+   follows="top|left"/>
+  <button
+   follows="left|bottom"
+   height="22"
+   layout="topleft"
+   left="29"
+   label="Take photo"
+   name="new_snapshot_btn"
+   bottom="-15"
+   width="90" />
+  <button
+   follows="left|bottom"
+   height="22"
+   layout="topleft"
+   left_pad="10"
+   label="Save (L$[UPLOAD_COST])"
+   name="save_btn"
+   width="90" />
+  <button
+   follows="left|bottom"
+   height="22"
+   layout="topleft"
+   left_pad="10"
+   label="Cancel"
+   name="cancel_btn"
+   width="90" />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_tos.xml b/indra/newview/skins/default/xui/en/floater_tos.xml
index a8db0aca4ed43a3a56217f4dc9cf28fd592c47a5..7e172e138a100d4326263df9d64ecf39f2f08bee 100644
--- a/indra/newview/skins/default/xui/en/floater_tos.xml
+++ b/indra/newview/skins/default/xui/en/floater_tos.xml
@@ -76,7 +76,7 @@
      word_wrap="true"
      text_readonly_color="LabelDisabledColor"
      width="552">
-      I have read and agree to the Second Life Terms and Conditions, Privacy Policy, and Terms of Service, including the dispute resolution requirements.
+      I consent to the Linden Lab Terms of Service, Second Life Terms and Conditions, and acknowledge receipt of the Privacy Policy.
     </text>
     <button
      enabled="false"
diff --git a/indra/newview/skins/default/xui/en/main_view.xml b/indra/newview/skins/default/xui/en/main_view.xml
index 842184de883cea353f714d0ebc0f86c4eee72980..bab37c625898f459b966d12280f6a4a96c17ee78 100644
--- a/indra/newview/skins/default/xui/en/main_view.xml
+++ b/indra/newview/skins/default/xui/en/main_view.xml
@@ -8,16 +8,6 @@
  tab_stop="false" 
  name="main_view"
  width="1024">
-
-  <!-- At the moment layout_stack is not an LLUICtrl,
-  but Tab requires focus_root to function and focus_root
-  functionality is implemented in LLUICtrl -->
-  <panel follows="all"
-         height="768"
-         name="menu_tab_wrapper"
-         mouse_opaque="false"
-         focus_root="true"
-         top="0">
   <layout_stack border_size="0"
                 follows="all"
                 mouse_opaque="false"
@@ -25,31 +15,35 @@
                 name="menu_stack"
                 orientation="vertical"
                 top="0">
+    <!-- Menu, nav bar and status bar need common focus_root-->
     <layout_panel mouse_opaque="true"
               follows="left|right|top"
               name="status_bar_container"
+              focus_root="true"
               height="19"
               left="0"
               top="0"
               width="1024"
               auto_resize="false"
-              default_tab_group="1"
               visible="true">
       <view mouse_opaque="false"
-            follows="all"
+            follows="top|left|right"
             name="menu_bar_holder"
+            tab_group="1"
             left="0"
             top="0"
             width="1024"
-            tab_group="1"
             height="19"/>
+      <view mouse_opaque="false"
+            follows="top|left|right"
+            name="nav_bar_container"
+            tab_group="3"
+            left="0"
+            top="19"
+            width="1024"
+            height="34"
+            visible="false"/>
     </layout_panel>
-    <layout_panel auto_resize="false"
-                  height="34"
-                  mouse_opaque="false"
-                  name="nav_bar_container"
-                  width="1024"
-                  visible="false"/>
     <layout_panel auto_resize="true"  
                   follows="all"
                   height="500"
@@ -109,7 +103,6 @@
              tab_stop="false"/>
     </layout_panel>
   </layout_stack>
-  </panel> <!--menu_tab_wrapper-->
  
   <panel top="0"
         follows="all"
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 1ddec936688ae21a5c372703b56b6d38eddd5ae3..d1a99133f07a8469947d4447cb0930a393b1359c 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -9689,7 +9689,7 @@ Do you wish to continue?
     The selected object affects the navmesh.  Changing it to a Flexible Path will remove it from the navmesh.
     <tag>confirm</tag>
     <usetemplate
-     ignoretext="The selected object affects the navmesh.  Changing it to a Flexible Path will remove it from the navmesh."
+     ignoretext="The selected object affects the navmesh. Changing it to a Flexible Path will remove it from the navmesh."
      name="okcancelignore"
      notext="Cancel"
      yestext="OK"/>
@@ -11914,4 +11914,20 @@ Unpacking: [UNPACK_TIME]s [USIZE]KB
       yestext="OK"/>
   </notification>
 
+  <notification
+    icon="alertmodal.tga"
+    name="RiggedMeshAttachedToHUD"
+    type="alertmodal">
+    An object "[NAME]" attached to HUD point "[POINT]" contains rigged mesh.
+
+Rigged mesh objects are designed for attachment to the avatar. You will see this object but no one else will.
+
+If you want others to see this object, remove it and re-attach it to an avatar attachment point.
+    <tag>confirm</tag>
+    <usetemplate
+        ignoretext="Warn me when rigged mesh is attached to HUD point."
+        name="okignore"
+        yestext="OK"/>
+  </notification>
+
 </notifications>
diff --git a/indra/newview/skins/default/xui/en/outfit_accordion_tab.xml b/indra/newview/skins/default/xui/en/outfit_accordion_tab.xml
index 2a24c74febd824fa81d29e31faea390b998f90b8..d74dca8b95cd804bc128720ae889d81caf3643e9 100644
--- a/indra/newview/skins/default/xui/en/outfit_accordion_tab.xml
+++ b/indra/newview/skins/default/xui/en/outfit_accordion_tab.xml
@@ -18,6 +18,7 @@
      follows="all"
      keep_one_selected="true"
      multi_select="true"
+     show_item_widgets="true"
      name="wearable_items_list"
      translate="false"
      standalone="false"
diff --git a/indra/newview/skins/default/xui/en/panel_nearby_chat.xml b/indra/newview/skins/default/xui/en/panel_nearby_chat.xml
index 4de56b424e15b1a5d411c5477e7ff5aad9a7325a..edc1fb21e79602078e8d53e6681d04f8c58c2ea4 100644
--- a/indra/newview/skins/default/xui/en/panel_nearby_chat.xml
+++ b/indra/newview/skins/default/xui/en/panel_nearby_chat.xml
@@ -17,26 +17,6 @@
    top="5"
    orientation="vertical"
    width="242">
-    <layout_panel
-     auto_resize="false"
-     height="26"
-     layout="topleft"
-     left_delta="0"
-     name="translate_chat_checkbox_lp"
-     top_delta="0"
-     visible="true"
-     width="230">
-      <check_box
-       top="10"
-       control_name="TranslateChat"
-       enabled="true"
-       height="16"
-       label="Translate chat"
-       layout="topleft"
-       left="5"
-       name="translate_chat_checkbox"
-       width="230" />
-    </layout_panel>
     <layout_panel
      auto_resize="true"
      height="138"
diff --git a/indra/newview/skins/default/xui/en/panel_outfits_wearing.xml b/indra/newview/skins/default/xui/en/panel_outfits_wearing.xml
index 42a79743169aba8c1364624ea0ea42173ba4ee7c..b2dc975c6ec2ccf9820d4d1a28dbd89d8b40f292 100644
--- a/indra/newview/skins/default/xui/en/panel_outfits_wearing.xml
+++ b/indra/newview/skins/default/xui/en/panel_outfits_wearing.xml
@@ -36,6 +36,7 @@
      left="3"
      multi_select="true"
      name="cof_items_list"
+     show_item_widgets="true"
      standalone="false"
      top="0"
      width="309"
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml b/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml
index 2ec5cef640373c1d03989f28e89b2067fb2169ae..ef08fdf7c46c37cdf7c9d09b74d7793570dd4e33 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml
@@ -19,7 +19,7 @@
       follows="left|top"
       height="23"
       label="Clear History"
-      tool_tip="Clear login image, last location, teleport history, web and texture cache"
+      tool_tip="Clear search and teleport history, web and texture cache"
       layout="topleft"
       left="30"
       name="clear_cache"
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 42a34d171aa352179d3c04aad6e6b5ca0bc7ebc6..ab2e9c72f31aad10f5eb304e37166731a3d6ab91 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_sound.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_sound.xml
@@ -322,154 +322,161 @@
 		name="enable_voice_check"
 		width="110"/>
 	<!-- -->
-    <text
-        follows="left|top"
-        layout="topleft"
-        height="15"
-        left="0"
-        top_pad="3"
-        width="120"
-        halign="right"
-        name="media_autoplay_label">
-         Media auto-play
-    </text>
-    <combo_box
+  <text
+   type="string"
+   length="1"
+   follows="left|top"
+   layout="topleft"
+   left="23"
+   top_delta="22"
+   name="Listen media from"
+   height="15"
+   word_wrap="true"
+   width="112">
+      Hear media and sounds from:
+  </text>
+  <radio_group
+   control_name="MediaSoundsEarLocation"
+   follows="left|top"
+   top_delta="-6"
+   layout="topleft"
+   left_pad="20"
+   width="360"
+   height="40"
+   name="media_ear_location">
+      <radio_item
+       height="19"
+       label="Camera position"
+       follows="left|top"
+       layout="topleft"
+       name="0"
+       width="200"/>
+      <radio_item
+       height="19"
+       follows="left|top"
+       label="Avatar position"
+       layout="topleft"
+       left_delta="0"
+       name="1"
+       top_delta ="18"
+       width="200" />
+  </radio_group>  
+ 	<check_box
+    name="media_show_on_others_btn"
+    control_name="MediaShowOnOthers"
+    value="true"
+    follows="left|top"
+    layout="topleft" 
+    height="15"
+    top_pad="8"
+    tool_tip="Uncheck this to hide media attached to other avatars nearby"
+    label="Play media attached to other avatars"
+    left="20"
+    width="230"/>
+  <text
+   follows="left|top"
+   layout="topleft"
+   height="15"
+   left="23"
+   top_pad="8"
+   width="120"
+   name="media_autoplay_label">
+    Auto-play media
+  </text>
+  <combo_box
         control_name="ParcelMediaAutoPlayEnable"
         enabled_control="AudioStreamingMedia"
         follows="left|top"
         layout="topleft"
         height="23"
-        left_pad="7"
+        left_pad="-15"
         top_delta="-4"
         name="media_auto_play_combo"
-        width="100">
-      <item
-          label="No"
-          name="autoplay_disabled"
-          value="0"/>      
-      <item
-          label="Yes"
-          name="autoplay_enabled"
-          value="1"/>
-      <item
-          label="Ask"
-          name="autoplay_ask"
-          value="2"/>
-    </combo_box>
- 	<check_box
-		name="media_show_on_others_btn"
-		control_name="MediaShowOnOthers"
-		value="true"
-		follows="left|bottom|right"
-		height="15"
-		tool_tip="Uncheck this to hide media attached to other avatars nearby"
-		label="Play media attached to other avatars"
-		left="25"
-    width="230"/>
-	<check_box
-		name="gesture_audio_play_btn"
-		control_name="EnableGestureSounds"
-        disabled_control="MuteAudio"
-		value="true"
-		follows="left|bottom|right"
-		height="15"
-		tool_tip="Check this to hear sounds from gestures"
-		label="Play sounds from gestures"
-		top_pad="1"
-		left="25"/>
-    <text
-     type="string"
-     length="1"
-     follows="left|top"
-     height="20"
-     layout="topleft"
-     left="25"
-     name="voice_chat_settings"
-     width="200"
-     top_pad="16">
-	  Voice Chat Settings
-    </text>
-    <text
-     type="string"
-     length="1"
-     follows="left|top"
-     layout="topleft"
-	   left="46"
-	   top_delta="16"
-     name="Listen from"
-     width="112">
-        Listen from:
-    </text>
-	<icon
-		follows="left|top"
-		height="18"
-		image_name="Cam_FreeCam_Off"
-		layout="topleft"
-		name="camera_icon"
-		mouse_opaque="false"
-		visible="true"
-		width="18"
-		left_pad="-4"
-		top_delta="-5"/>
-	<icon
-		follows="left|top"
-		height="18"
-		image_name="Move_Walk_Off"
-		layout="topleft"
-		left_pad="170" 
-		name="avatar_icon"
-		mouse_opaque="false"
-		visible="true"
-		width="18"
-		top_delta="0" />
-   <radio_group
-     enabled_control="EnableVoiceChat"
-     control_name="VoiceEarLocation"
-     follows="left|top"
-     layout="topleft"
-     left_delta="-168"
-     width="360"
-     height="20"
-     name="ear_location">
-    <radio_item
-     height="19"
-     label="Camera position"
-     follows="left|top"
-     layout="topleft"
-     name="0"
-     width="200"/>
-    <radio_item
-     height="19"
-     follows="left|top"
-     label="Avatar position"
-     layout="topleft"
-     left_pad="-16"
-     name="1"
-     top_delta ="0" 
-     width="200" />
-   </radio_group>
+        width="115">
+    <item
+        label="Never"
+        name="autoplay_disabled"
+        value="0"/>
+    <item
+        label="Always"
+        name="autoplay_enabled"
+        value="1"/>
+    <item
+        label="Ask"
+        name="autoplay_ask"
+        value="2"/>
+  </combo_box>
+  <text
+   type="string"
+   length="1"
+   follows="left|top"
+   layout="topleft"
+   left="23"
+   top_delta="30"
+   name="Listen from"
+   width="112">
+     Hear voice from:
+  </text>
+  <radio_group
+   enabled_control="EnableVoiceChat"
+   control_name="VoiceEarLocation"
+   follows="left|top"
+   layout="topleft"
+   left_pad="20"
+   top_delta="-6"
+   width="360"
+   height="40"
+   name="ear_location">
+   <radio_item
+    height="19"
+    label="Camera position"
+    follows="left|top"
+    layout="topleft"
+    name="0"
+    width="200"/>
+   <radio_item
+    height="19"
+    follows="left|top"
+    label="Avatar position"
+    layout="topleft"
+    left_delta="0"
+    name="1"
+    top_delta ="18" 
+    width="200" />
+  </radio_group>
   <check_box
    control_name="LipSyncEnabled"
    follows="left|top"
    height="15"
    label="Move avatar lips when speaking"
    layout="topleft"
-   left="44"
+   left="20"
    name="enable_lip_sync"
-   top_pad="5" 
+   top_pad="10" 
    width="237"/>
- <check_box
-  follows="top|left"
-  enabled_control="EnableVoiceChat"
-  control_name="PushToTalkToggle"
-  height="15"
-  label="Toggle speak on/off when I press button in toolbar"
-  layout="topleft"
-  left="44"
-  name="push_to_talk_toggle_check"
-  width="237"
-  tool_tip="When in toggle mode, press and release the trigger key ONCE to switch your microphone on or off. When not in toggle mode, the microphone broadcasts your voice only while the trigger is being held down."
-  top_pad="3"/>
+  <check_box
+   follows="top|left"
+   enabled_control="EnableVoiceChat"
+   control_name="PushToTalkToggle"
+   height="15"
+   label="Toggle speak on/off when I press button in toolbar"
+   layout="topleft"
+   left="20"
+   name="push_to_talk_toggle_check"
+   width="237"
+   tool_tip="When in toggle mode, press and release the trigger key ONCE to switch your microphone on or off. When not in toggle mode, the microphone broadcasts your voice only while the trigger is being held down."
+   top_pad="5"/>
+  <check_box
+   name="gesture_audio_play_btn"
+   control_name="EnableGestureSounds"
+   disabled_control="MuteAudio"
+   value="true"
+   follows="left|bottom|right"
+   height="15"
+   tool_tip="Check this to hear sounds from gestures"
+   label="Play sounds from gestures"
+   top_pad="5"
+   left="20"/>
   <button
    control_name="ShowDeviceSettings"
    follows="left|top"
@@ -478,7 +485,7 @@
    label="Voice Input/Output devices"
    layout="topleft"
    left="20"
-   top_pad="6"
+   top_pad="9"
    name="device_settings_btn"
    width="230">
   </button>
diff --git a/indra/newview/skins/default/xui/en/panel_profile_secondlife.xml b/indra/newview/skins/default/xui/en/panel_profile_secondlife.xml
index 551b4778762a98af802aab0183462caf5684a1be..777b37d66675dcae63d5b23bd6906c3a43574810 100644
--- a/indra/newview/skins/default/xui/en/panel_profile_secondlife.xml
+++ b/indra/newview/skins/default/xui/en/panel_profile_secondlife.xml
@@ -9,9 +9,13 @@
  follows="all"
  layout="topleft"
 >
+  <!--
+  Date from server comes already converted to stl timezone,
+  so display it as an UTC+0
+  -->
    <string 
     name="date_format"
-    value="SL birthdate: [mth,datetime,slt] [day,datetime,slt], [year,datetime,slt]" />
+    value="SL birthdate: [mth,datetime,utc] [day,datetime,utc], [year,datetime,utc]" />
    <string
     name="age_format"
     value="[AGE]" />
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 6f95e282ca1019a654bd5ea320ad8a5626c405a8..42a10e8c56cf3931311ee39e70e4346542e60ed0 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -3983,7 +3983,7 @@ Please check http://status.secondlifegrid.net to see if there is a known problem
   <string name="Premium_PlusMembership">Premium Plus</string>
   <string name="InternalMembership">Internal</string> <!-- No need to translate -->
 
-  <string name="MembershipUpgradeText">Upgrade to Premium</string>
+  <string name="MembershipUpgradeText">Change membership plan...</string>
   <string name="MembershipPremiumText">My Premium membership</string>
 
   <!-- Question strings for delete items notifications -->
@@ -4300,6 +4300,10 @@ name="Command_360_Capture_Tooltip">Capture a 360 equirectangular image</string>
   <string name="Mav_Details_MAV_CONFIRMATION_DATA_MISMATCH">
       The physics shape contains bad confirmation data. Try to correct the physics model.
   </string>
+  <!-- MAV_BLOCK_MISSING means server didn't get and couldn't substitute physics_convex, high_lod or BoundingVerts-->
+  <string name="Mav_Details_MAV_BLOCK_MISSING">
+    Missing data. Make sure high lod is present and valid. Set the physics model if not set.
+  </string>
   <string name="Mav_Details_MAV_UNKNOWN_VERSION">
       The physics shape does not have correct version. Set the correct version for the physics model.
   </string>
diff --git a/indra/newview/skins/default/xui/en/widgets/filter_editor.xml b/indra/newview/skins/default/xui/en/widgets/filter_editor.xml
index 1c4822b8d5be373e15eedf18e32c9ca677c2953e..9c80deeafc242e20ed8c496e27f2299406917505 100644
--- a/indra/newview/skins/default/xui/en/widgets/filter_editor.xml
+++ b/indra/newview/skins/default/xui/en/widgets/filter_editor.xml
@@ -6,7 +6,7 @@
   text_pad_left="7"
   select_on_focus="true"
   text_tentative_color="TextFgTentativeColor"
-  highlight_text_field="false"
+  highlight_text_field="true"
   background_image="TextField_Search_Off"
   background_image_disabled="TextField_Search_Disabled"
   background_image_focused="TextField_Search_Active"
diff --git a/indra/newview/skins/default/xui/en/widgets/search_editor.xml b/indra/newview/skins/default/xui/en/widgets/search_editor.xml
index dc5a07bf4f40bed427dc297869ef542a5ddd13f0..18d99f1ed15151abd29a72cef687838926c2955a 100644
--- a/indra/newview/skins/default/xui/en/widgets/search_editor.xml
+++ b/indra/newview/skins/default/xui/en/widgets/search_editor.xml
@@ -7,7 +7,7 @@
   text_pad_right="6" 
   select_on_focus="true"
   text_tentative_color="TextFgTentativeColor"
-  highlight_text_field="false"
+  highlight_text_field="true"
   background_image="TextField_Search_Off"
   background_image_disabled="TextField_Search_Disabled"
   background_image_focused="TextField_Search_Active"
diff --git a/indra/newview/skins/default/xui/en/widgets/wearable_outfit_list_item.xml b/indra/newview/skins/default/xui/en/widgets/wearable_outfit_list_item.xml
new file mode 100644
index 0000000000000000000000000000000000000000..cd84b91b1fd07088322a6740d5623531f4692248
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/wearable_outfit_list_item.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<inventory_list_item
+  follows="top|right|left"
+  height="20"
+  name="inventory_item"
+  tab_stop="false" 
+  hover_image="ListItem_Over"
+  selected_image="ListItem_Select"
+  separator_image="Wearables_Divider" 
+  width="380">
+  <!-- DEFAULT style for inventory list item -->
+  <default_style
+   font="SansSerifSmall"
+   font.style="NORMAL" />
+
+  <!-- style for inventory list item WORN on avatar -->
+  <worn_style
+   font="SansSerifSmall"
+   font.style="BOLD"
+   color="EmphasisColor" />
+  <item_icon
+    height="16"
+    follows="top|left"
+    image_name="Inv_Object"
+    layout="topleft"
+    left="0"
+    name="item_icon"
+    top="0"
+    width="16" />
+  <item_name
+    follows="left|right"
+    height="20"
+    layout="topleft"
+    left="21"
+    parse_urls="false"
+    use_ellipses="true"
+    name="item_name"
+    text_color="white"
+    top="4"
+    value="..."
+    width="359" />
+    <add_btn
+     name="add_wearable"
+     layout="topleft"
+     follows="top|right"
+     image_unselected="Add_Icon"
+     image_selected="Add_Icon"
+     top="1"
+     left="0"
+     height="16"
+     width="16"
+     tab_stop="false" />
+    <remove_btn
+     name="remove_wearable"
+     layout="topleft"
+     follows="top|right"
+     image_unselected="Remove_Icon"
+     image_selected="Remove_Icon"
+     top="1"
+     left="26"
+     height="16"
+     width="16"
+     tab_stop="false" />
+</inventory_list_item>
diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py
index 59eb18b7347eeed24de2fa3f252330b32547885f..6d68fd545303d15d750444762ba1fe338cc6face 100755
--- a/indra/newview/viewer_manifest.py
+++ b/indra/newview/viewer_manifest.py
@@ -518,7 +518,7 @@ def construct(self):
                 self.path("alut.dll")
 
             # For textures
-            self.path("openjpeg.dll")
+            self.path("openjp2.dll")
 
             # Uriparser
             self.path("uriparser.dll")
@@ -1501,7 +1501,7 @@ def construct(self):
             self.path("libdirectfb-1.*.so.*")
             self.path("libfusion-1.*.so.*")
             self.path("libdirect-1.*.so.*")
-            self.path("libopenjpeg.so*")
+            self.path("libopenjp2.so*")
             self.path("libdirectfb-1.4.so.5")
             self.path("libfusion-1.4.so.5")
             self.path("libdirect-1.4.so.5*")