diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml
index 79f3eafac949033b65f6264a70f984abddef684a..ddb0f44150734357b39e70892d3bf72f5fc31c6d 100644
--- a/.github/workflows/build.yaml
+++ b/.github/workflows/build.yaml
@@ -65,7 +65,7 @@ jobs:
           ref: ${{ github.event.pull_request.head.sha || github.sha }}
 
       - name: Setup python
-        uses: actions/setup-python@v4
+        uses: actions/setup-python@v5
         with:
           python-version: ${{ matrix.python-version }}
 
@@ -86,7 +86,7 @@ jobs:
         run: pip3 install autobuild llsd
 
       - name: Cache autobuild packages
-        uses: actions/cache@v3
+        uses: actions/cache@v4
         id: cache-installables
         with:
           path: .autobuild-installables
@@ -101,7 +101,7 @@ jobs:
 
       - name: Determine source branch
         id: which-branch
-        uses: secondlife/viewer-build-util/which-branch@relnotes
+        uses: secondlife/viewer-build-util/which-branch@v1
         with:
           token: ${{ github.token }}
 
diff --git a/autobuild.xml b/autobuild.xml
index 0e51a0476c5b3ff8e7c141305bee42e8e578f0df..6209de299485147965a8d13496f0c4636cedb936 100644
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -1571,11 +1571,11 @@
               <key>creds</key>
               <string>github</string>
               <key>hash</key>
-              <string>48bca5d0233d1e724a59f649a2c6c7ac5f40ec3c</string>
+              <string>b037cc0b29ea70ee834cfae6dda5b7a25cd57174</string>
               <key>hash_algorithm</key>
               <string>sha1</string>
               <key>url</key>
-              <string>https://api.github.com/repos/secondlife/llphysicsextensions_source/releases/assets/117009335</string>
+              <string>https://api.github.com/repos/secondlife/llphysicsextensions_source/releases/assets/144851460</string>
             </map>
             <key>name</key>
             <string>darwin64</string>
@@ -1587,11 +1587,11 @@
               <key>creds</key>
               <string>github</string>
               <key>hash</key>
-              <string>39f52d0350e130f41c5c758f7cb94e87b962c223</string>
+              <string>bdea1fd5c4da9da5afde088d16188b45d0853e04</string>
               <key>hash_algorithm</key>
               <string>sha1</string>
               <key>url</key>
-              <string>https://api.github.com/repos/secondlife/llphysicsextensions_source/releases/assets/117009336</string>
+              <string>https://api.github.com/repos/secondlife/llphysicsextensions_source/releases/assets/144851461</string>
             </map>
             <key>name</key>
             <string>linux64</string>
@@ -1603,11 +1603,11 @@
               <key>creds</key>
               <string>github</string>
               <key>hash</key>
-              <string>7b5e645fb7eb399abbea63bd21e8063bbb32a911</string>
+              <string>f652ce0d6aef864689f0ed44255da4d9cd65a43f</string>
               <key>hash_algorithm</key>
               <string>sha1</string>
               <key>url</key>
-              <string>https://api.github.com/repos/secondlife/llphysicsextensions_source/releases/assets/117009339</string>
+              <string>https://api.github.com/repos/secondlife/llphysicsextensions_source/releases/assets/144851463</string>
             </map>
             <key>name</key>
             <string>windows64</string>
@@ -1620,7 +1620,7 @@
         <key>copyright</key>
         <string>Copyright (c) 2010, Linden Research, Inc.</string>
         <key>version</key>
-        <string>1.0.565768</string>
+        <string>1.0.479d20a</string>
         <key>name</key>
         <string>llphysicsextensions_source</string>
       </map>
@@ -1652,18 +1652,6 @@
             <key>name</key>
             <string>linux64</string>
           </map>
-          <key>windows</key>
-          <map>
-            <key>archive</key>
-            <map>
-              <key>hash</key>
-              <string>2e5f1f7046a49d8b0bc295aa878116bc</string>
-              <key>url</key>
-              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/60043/564063/llphysicsextensions_stub-1.0.542456-windows-542456.tar.bz2</string>
-            </map>
-            <key>name</key>
-            <string>windows</string>
-          </map>
         </map>
         <key>license</key>
         <string>internal</string>
@@ -1804,18 +1792,6 @@
       </map>
       <key>mikktspace</key>
       <map>
-        <key>canonical_repo</key>
-        <string>https://bitbucket.org/lindenlab/3p-mikktspace</string>
-        <key>copyright</key>
-        <string>Copyright (C) 2011 by Morten S. Mikkelsen</string>
-        <key>description</key>
-        <string>Mikktspace Tangent Generator</string>
-        <key>license</key>
-        <string>Copyright (C) 2011 by Morten S. Mikkelsen</string>
-        <key>license_file</key>
-        <string>mikktspace.txt</string>
-        <key>name</key>
-        <string>mikktspace</string>
         <key>platforms</key>
         <map>
           <key>darwin64</key>
@@ -1823,40 +1799,58 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>b48b7ac0792d3ea8f087d99d9e4a29d8</string>
+              <string>6cc1585dba85b0226a2e7033a7e2a2ceaae7c983</string>
+              <key>hash_algorithm</key>
+              <string>sha1</string>
               <key>url</key>
-              <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/104415/914944/mikktspace-1-darwin64-574859.tar.bz2</string>
+              <string>https://github.com/secondlife/3p-mikktspace/releases/download/v1-5cee1f4/mikktspace-1-darwin64-5cee1f4.tar.zst</string>
             </map>
             <key>name</key>
             <string>darwin64</string>
           </map>
-          <key>windows</key>
+          <key>windows64</key>
           <map>
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>0a016b9c0c1e2c0b557e0124094da6c5</string>
+              <string>6b7d01ad54e4a88a001f66840c32329cedb28202</string>
+              <key>hash_algorithm</key>
+              <string>sha1</string>
               <key>url</key>
-              <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/104407/914918/mikktspace-1-windows-574859.tar.bz2</string>
+              <string>https://github.com/secondlife/3p-mikktspace/releases/download/v1-5cee1f4/mikktspace-1-windows64-5cee1f4.tar.zst</string>
             </map>
             <key>name</key>
-            <string>windows</string>
+            <string>windows64</string>
           </map>
-          <key>windows64</key>
+          <key>linux64</key>
           <map>
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>02e9e5b6fe6788f4d2babb83ec544843</string>
+              <string>edc9782bf209e17ad1845498b42f16d733582082</string>
+              <key>hash_algorithm</key>
+              <string>sha1</string>
               <key>url</key>
-              <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/104406/914909/mikktspace-1-windows64-574859.tar.bz2</string>
+              <string>https://github.com/secondlife/3p-mikktspace/releases/download/v1-5cee1f4/mikktspace-1-linux64-5cee1f4.tar.zst</string>
             </map>
             <key>name</key>
-            <string>windows64</string>
+            <string>linux64</string>
           </map>
         </map>
+        <key>license</key>
+        <string>Copyright (C) 2011 by Morten S. Mikkelsen</string>
+        <key>license_file</key>
+        <string>mikktspace.txt</string>
+        <key>copyright</key>
+        <string>Copyright (C) 2011 by Morten S. Mikkelsen</string>
         <key>version</key>
         <string>1</string>
+        <key>name</key>
+        <string>mikktspace</string>
+        <key>canonical_repo</key>
+        <string>https://bitbucket.org/lindenlab/3p-mikktspace</string>
+        <key>description</key>
+        <string>Mikktspace Tangent Generator</string>
       </map>
       <key>minizip-ng</key>
       <map>
@@ -2502,18 +2496,6 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
       </map>
       <key>tinygltf</key>
       <map>
-        <key>canonical_repo</key>
-        <string>https://bitbucket.org/lindenlab/3p-tinygltf</string>
-        <key>copyright</key>
-        <string>// Copyright (c) 2015 - Present Syoyo Fujita, Aurélien Chatelain and many contributors.</string>
-        <key>description</key>
-        <string>tinygltf import library</string>
-        <key>license</key>
-        <string>MIT</string>
-        <key>license_file</key>
-        <string>LICENSES/tinygltf_license.txt</string>
-        <key>name</key>
-        <string>tinygltf</string>
         <key>platforms</key>
         <map>
           <key>common</key>
@@ -2521,20 +2503,34 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>4dad1c0948141e1667c01a3ee755e4dc</string>
+              <string>2c47ae2d0c38c86b8c2db8d9317f0ab15edfc74f</string>
+              <key>hash_algorithm</key>
+              <string>sha1</string>
               <key>url</key>
-              <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/105849/926137/tinygltf-v2.5.0-common-575729.tar.bz2</string>
+              <string>https://github.com/secondlife/3p-tinygltf/releases/download/v2.5.0-1ae57fd/tinygltf-v2.5.0-common-1ae57fd.tar.zst</string>
             </map>
             <key>name</key>
             <string>common</string>
           </map>
         </map>
+        <key>license</key>
+        <string>MIT</string>
+        <key>license_file</key>
+        <string>LICENSES/tinygltf_license.txt</string>
+        <key>copyright</key>
+        <string>// Copyright (c) 2015 - Present Syoyo Fujita, Aurélien Chatelain and many contributors.</string>
+        <key>version</key>
+        <string>v2.5.0</string>
+        <key>name</key>
+        <string>tinygltf</string>
+        <key>canonical_repo</key>
+        <string>https://bitbucket.org/lindenlab/3p-tinygltf</string>
+        <key>description</key>
+        <string>tinygltf import library</string>
         <key>source</key>
         <string>https://bitbucket.org/lindenlab/3p-tinygltf</string>
         <key>source_type</key>
         <string>git</string>
-        <key>version</key>
-        <string>v2.5.0</string>
       </map>
       <key>tracy</key>
       <map>
@@ -2545,9 +2541,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>9b6e1a1f4b0969d38a1ca8ee00aeb548</string>
+              <string>49650353442698c3e05102676fe427d0ebe02f0b</string>
+              <key>hash_algorithm</key>
+              <string>sha1</string>
               <key>url</key>
-              <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/110584/960613/tracy-v0.8.1.578241-darwin64-578241.tar.bz2</string>
+              <string>https://github.com/secondlife/3p-tracy/releases/download/v0.8.1-eecbf72/tracy-v0.8.1-eecbf72-darwin64-eecbf72.tar.zst</string>
             </map>
             <key>name</key>
             <string>darwin64</string>
@@ -2557,11 +2555,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>05b72ae5d733aed7d3bf142287601cc6</string>
+              <string>2b80e7407e4f3e82eff3879add0e9ad63e7fcace</string>
               <key>hash_algorithm</key>
-              <string>md5</string>
+              <string>sha1</string>
               <key>url</key>
-              <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/110586/960637/tracy-v0.8.1.578241-windows64-578241.tar.bz2</string>
+              <string>https://github.com/secondlife/3p-tracy/releases/download/v0.8.1-eecbf72/tracy-v0.8.1-eecbf72-windows64-eecbf72.tar.zst</string>
             </map>
             <key>name</key>
             <string>windows64</string>
@@ -2574,7 +2572,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
         <key>copyright</key>
         <string>Copyright (c) 2017-2022, Bartosz Taudul (wolf@nereid.pl)</string>
         <key>version</key>
-        <string>v0.8.1.235e98f</string>
+        <string>v0.8.1-eecbf72</string>
         <key>name</key>
         <string>tracy</string>
         <key>canonical_repo</key>
@@ -2585,8 +2583,6 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
         <string>https://bitbucket.org/lindenlab/3p-tracy</string>
         <key>source_type</key>
         <string>git</string>
-        <key>version</key>
-        <string>v0.8.1.578241</string>
       </map>
       <key>tut</key>
       <map>
@@ -2892,59 +2888,37 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
       </map>
       <key>vulkan_gltf</key>
       <map>
-        <key>canonical_repo</key>
-        <string>https://bitbucket.org/lindenlab/3p-vulkan-gltf-pbr</string>
-        <key>copyright</key>
-        <string>Copyright (c) 2018 Sascha Willems</string>
-        <key>description</key>
-        <string>Vulkan GLTF Sample Implementation</string>
-        <key>license</key>
-        <string>Copyright (c) 2018 Sascha Willems</string>
-        <key>license_file</key>
-        <string>LICENSES/vulkan_gltf.txt</string>
-        <key>name</key>
-        <string>vulkan_gltf</string>
         <key>platforms</key>
         <map>
-          <key>darwin64</key>
-          <map>
-            <key>archive</key>
-            <map>
-              <key>hash</key>
-              <string>8cff2060843db3db788511ee34a8e8cc</string>
-              <key>url</key>
-              <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/101316/891509/vulkan_gltf-1-darwin64-572743.tar.bz2</string>
-            </map>
-            <key>name</key>
-            <string>darwin64</string>
-          </map>
-          <key>windows</key>
-          <map>
-            <key>archive</key>
-            <map>
-              <key>hash</key>
-              <string>58eea384be49ba756ce9c5e66669540b</string>
-              <key>url</key>
-              <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/101318/891520/vulkan_gltf-1-windows-572743.tar.bz2</string>
-            </map>
-            <key>name</key>
-            <string>windows</string>
-          </map>
-          <key>windows64</key>
+          <key>common</key>
           <map>
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>79b6a11622c2f83cfc2b7cd1fafb867b</string>
+              <string>8e365eff8dcace48d91e2530f8b13e420849aefc</string>
+              <key>hash_algorithm</key>
+              <string>sha1</string>
               <key>url</key>
-              <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/101319/891521/vulkan_gltf-1-windows64-572743.tar.bz2</string>
+              <string>https://github.com/secondlife/3p-vulkan-gltf-pbr/releases/download/v1.0.0-d7c372f/vulkan_gltf-1.0.0-common-d7c372f.tar.zst</string>
             </map>
             <key>name</key>
-            <string>windows64</string>
+            <string>common</string>
           </map>
         </map>
+        <key>license</key>
+        <string>Copyright (c) 2018 Sascha Willems</string>
+        <key>license_file</key>
+        <string>vulkan_gltf.txt</string>
+        <key>copyright</key>
+        <string>Copyright (c) 2018 Sascha Willems</string>
         <key>version</key>
-        <string>1</string>
+        <string>1.0.0</string>
+        <key>name</key>
+        <string>vulkan_gltf</string>
+        <key>canonical_repo</key>
+        <string>https://bitbucket.org/lindenlab/3p-vulkan-gltf-pbr</string>
+        <key>description</key>
+        <string>Vulkan GLTF Sample Implementation</string>
       </map>
       <key>xxhash</key>
       <map>
@@ -2955,54 +2929,14 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>e4f77ba0a9b8ec3cc3fabc51c4da81d2</string>
-              <key>url</key>
-              <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/110070/956941/xxhash-0.8.1.578006-windows-578006.tar.bz2</string>
-            </map>
-            <key>name</key>
-            <string>common</string>
-          </map>
-          <key>darwin64</key>
-          <map>
-            <key>archive</key>
-            <map>
-              <key>hash</key>
-              <string>fdcc803a76a3359bb426db7dac161406676d51e7</string>
+              <string>1a73c476b371b62066d1c3eced249660e9467e53</string>
               <key>hash_algorithm</key>
               <string>sha1</string>
               <key>url</key>
-              <string>https://github.com/secondlife/3p-xxhash/releases/download/v0.8.1.7501c90/xxhash-0.8.1.7501c90-darwin64-7501c90.tar.zst</string>
+              <string>https://github.com/secondlife/3p-xxhash/releases/download/v0.8.1-69ff69a/xxhash-0.8.1-69ff69a-common-69ff69a.tar.zst</string>
             </map>
             <key>name</key>
-            <string>darwin64</string>
-          </map>
-          <key>linux64</key>
-          <map>
-            <key>archive</key>
-            <map>
-              <key>hash</key>
-              <string>7acb3f94a549fbb9bd7bc16604e34f33c5365a9b</string>
-              <key>hash_algorithm</key>
-              <string>sha1</string>
-              <key>url</key>
-              <string>https://github.com/secondlife/3p-xxhash/releases/download/v0.8.1.7501c90/xxhash-0.8.1.7501c90-linux64-7501c90.tar.zst</string>
-            </map>
-            <key>name</key>
-            <string>linux64</string>
-          </map>
-          <key>windows64</key>
-          <map>
-            <key>archive</key>
-            <map>
-              <key>hash</key>
-              <string>4522d075ea4703ef4b527c3039864ef735ea7953</string>
-              <key>hash_algorithm</key>
-              <string>sha1</string>
-              <key>url</key>
-              <string>https://github.com/secondlife/3p-xxhash/releases/download/v0.8.1.7501c90/xxhash-0.8.1.7501c90-windows64-7501c90.tar.zst</string>
-            </map>
-            <key>name</key>
-            <string>windows64</string>
+            <string>common</string>
           </map>
         </map>
         <key>license</key>
@@ -3012,7 +2946,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
         <key>copyright</key>
         <string>Copyright (c) 2012-2021 Yann Collet</string>
         <key>version</key>
-        <string>0.8.1.7501c90</string>
+        <string>0.8.1-69ff69a</string>
         <key>name</key>
         <string>xxhash</string>
         <key>description</key>
diff --git a/doc/testplans/optimize_away_alpha.md b/doc/testplans/optimize_away_alpha.md
new file mode 100644
index 0000000000000000000000000000000000000000..f0c8d1e8d634342c9bc1758a7574718a89f75cdc
--- /dev/null
+++ b/doc/testplans/optimize_away_alpha.md
@@ -0,0 +1,5 @@
+Textures imported via Build->Upload->Material that have an all opaque (255) alpha channel should have their alpha channel removed before upload.
+
+1. Make 4 images that have different colors but all 255 alpha channels
+2. Upload them all using Build->Upload->Material, with one in each of the material texture slots
+3. Verify that using the textures as a blinn-phong diffuse map does not make the corresponding face render in the alpha pass (face should stay visible after disabling alpha pass by unchecking Advanced->Render Types->Alpha).
diff --git a/indra/llcommon/indra_constants.cpp b/indra/llcommon/indra_constants.cpp
index 1b48e4daf3a911c94867d11a31587d79a7209083..9a0c565b06a134a595be2c4e10aa4197513d29cc 100644
--- a/indra/llcommon/indra_constants.cpp
+++ b/indra/llcommon/indra_constants.cpp
@@ -50,6 +50,7 @@ const LLUUID IMG_FIRE			("aca40aa8-44cf-44ca-a0fa-93e1a2986f82"); // dataserver
 const LLUUID IMG_FACE_SELECT    ("a85ac674-cb75-4af6-9499-df7c5aaf7a28"); // face selector
 const LLUUID IMG_DEFAULT_AVATAR ("c228d1cf-4b5d-4ba8-84f4-899a0796aa97"); // dataserver
 const LLUUID IMG_INVISIBLE		("3a367d1c-bef1-6d43-7595-e88c1e3aadb3"); // dataserver
+const LLUUID IMG_WHITE          ("5748decc-f629-461c-9a36-a35a221fe21f"); // dataserver
 
 const LLUUID IMG_EXPLOSION				("68edcf47-ccd7-45b8-9f90-1649d7f12806"); // On dataserver
 const LLUUID IMG_EXPLOSION_2			("21ce046c-83fe-430a-b629-c7660ac78d7c"); // On dataserver
@@ -71,6 +72,11 @@ const LLUUID TERRAIN_ROCK_DETAIL		("53a2f406-4895-1d13-d541-d2e3b86bc19c"); // V
 
 const LLUUID DEFAULT_WATER_NORMAL		("822ded49-9a6c-f61c-cb89-6df54f42cdf4"); // VIEWER
 
+const LLUUID DEFAULT_OBJECT_TEXTURE     ("89556747-24cb-43ed-920b-47caed15465f"); // On dataserver
+const LLUUID DEFAULT_OBJECT_SPECULAR    ("87e0e8f7-8729-1ea8-cfc9-8915773009db"); // On dataserver
+const LLUUID DEFAULT_OBJECT_NORMAL      ("85f28839-7a1c-b4e3-d71d-967792970a7b"); // On dataserver
+const LLUUID BLANK_OBJECT_NORMAL        ("5b53359e-59dd-d8a2-04c3-9e65134da47a"); // VIEWER (has a verion on dataserver, but with compression artifacts)
+
 const LLUUID IMG_USE_BAKED_HEAD  ("5a9f4a74-30f2-821c-b88d-70499d3e7183");
 const LLUUID IMG_USE_BAKED_UPPER ("ae2de45c-d252-50b8-5c6e-19f39ce79317");
 const LLUUID IMG_USE_BAKED_LOWER ("24daea5f-0539-cfcf-047f-fbc40b2786ba");
diff --git a/indra/llcommon/indra_constants.h b/indra/llcommon/indra_constants.h
index 679f79039bd9adec0b7866d94f79059ba5cf27e2..a16cfac2b9223017570e903856c4ca5b7f159151 100644
--- a/indra/llcommon/indra_constants.h
+++ b/indra/llcommon/indra_constants.h
@@ -197,6 +197,7 @@ LL_COMMON_API extern const LLUUID IMG_FIRE;
 LL_COMMON_API extern const LLUUID IMG_FACE_SELECT;
 LL_COMMON_API extern const LLUUID IMG_DEFAULT_AVATAR;
 LL_COMMON_API extern const LLUUID IMG_INVISIBLE;
+LL_COMMON_API extern const LLUUID IMG_WHITE;
 
 LL_COMMON_API extern const LLUUID IMG_EXPLOSION;
 LL_COMMON_API extern const LLUUID IMG_EXPLOSION_2;
@@ -230,6 +231,10 @@ LL_COMMON_API extern const LLUUID IMG_USE_BAKED_AUX3;
 
 LL_COMMON_API extern const LLUUID DEFAULT_WATER_NORMAL;
 
+LL_COMMON_API extern const LLUUID DEFAULT_OBJECT_TEXTURE;
+LL_COMMON_API extern const LLUUID DEFAULT_OBJECT_SPECULAR;
+LL_COMMON_API extern const LLUUID DEFAULT_OBJECT_NORMAL;
+LL_COMMON_API extern const LLUUID BLANK_OBJECT_NORMAL;
 
 // radius within which a chat message is fully audible
 const F32 CHAT_NORMAL_RADIUS = 20.f;
diff --git a/indra/llcommon/llcoros.cpp b/indra/llcommon/llcoros.cpp
index 3deed2e199efef7c7f2f83cbc4cb9c7b89f6b627..c13900f74a08804682bdd6b0f9082b3beca93f5c 100644
--- a/indra/llcommon/llcoros.cpp
+++ b/indra/llcommon/llcoros.cpp
@@ -278,6 +278,7 @@ std::string LLCoros::launch(const std::string& prefix, const callable_t& callabl
     catch (std::bad_alloc&)
     {
         // Out of memory on stack allocation?
+        LLError::LLUserWarningMsg::showOutOfMemory();
         printActiveCoroutines();
         LL_ERRS("LLCoros") << "Bad memory allocation in LLCoros::launch(" << prefix << ")!" << LL_ENDL;
     }
diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp
index 414515854a241be125a3d33ab5b662b6bb75b40d..3de641fcba6d2fc04d9d8637aa5176bb11f75d09 100644
--- a/indra/llcommon/llerror.cpp
+++ b/indra/llcommon/llerror.cpp
@@ -1601,6 +1601,48 @@ namespace LLError
     {
         return out << boost::stacktrace::stacktrace();
     }
+
+    // LLOutOfMemoryWarning
+    std::string LLUserWarningMsg::sLocalizedOutOfMemoryTitle;
+    std::string LLUserWarningMsg::sLocalizedOutOfMemoryWarning;
+    LLUserWarningMsg::Handler LLUserWarningMsg::sHandler;
+
+    void LLUserWarningMsg::show(const std::string& message)
+    {
+        if (sHandler)
+        {
+            sHandler(std::string(), message);
+        }
+    }
+
+    void LLUserWarningMsg::showOutOfMemory()
+    {
+        if (sHandler && !sLocalizedOutOfMemoryTitle.empty())
+        {
+            sHandler(sLocalizedOutOfMemoryTitle, sLocalizedOutOfMemoryWarning);
+        }
+    }
+
+    void LLUserWarningMsg::showMissingFiles()
+    {
+        // Files Are missing, likely can't localize.
+        const std::string error_string =
+            "Second Life viewer couldn't access some of the files it needs and will be closed."
+            "\n\nPlease reinstall viewer from  https://secondlife.com/support/downloads/ and "
+            "contact https://support.secondlife.com if issue persists after reinstall.";
+        sHandler("Missing Files", error_string);
+    }
+
+    void LLUserWarningMsg::setHandler(const LLUserWarningMsg::Handler &handler)
+    {
+        sHandler = handler;
+    }
+
+    void LLUserWarningMsg::setOutOfMemoryStrings(const std::string& title, const std::string& message)
+    {
+        sLocalizedOutOfMemoryTitle = title;
+        sLocalizedOutOfMemoryWarning = message;
+    }
 }
 
 void crashdriver(void (*callback)(int*))
diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h
index 05dd88ee514fc5a2097b7888d0744359e3699efd..6f6b349cf54c7b67043167c83fa68e86735a6658 100644
--- a/indra/llcommon/llerror.h
+++ b/indra/llcommon/llerror.h
@@ -39,6 +39,7 @@
 #include "llpreprocessor.h"
 
 #include <boost/static_assert.hpp>
+#include <functional> // std::function
 
 const int LL_ERR_NOERR = 0;
 
@@ -301,6 +302,28 @@ namespace LLError
     {
         friend std::ostream& operator<<(std::ostream& out, const LLStacktrace&);
     };
+
+    // Provides access to OS notification popup on error, since
+    // not everything has access to OS's messages
+    class LLUserWarningMsg
+    {
+    public:
+        typedef std::function<void(const std::string&, const std::string&)> Handler;
+        static void setHandler(const Handler&);
+        static void setOutOfMemoryStrings(const std::string& title, const std::string& message);
+
+        // When viewer encounters bad alloc or can't access files try warning user about reasons
+        static void showOutOfMemory();
+        static void showMissingFiles();
+        // Genering error
+        static void show(const std::string&);
+
+    private:
+        // needs to be preallocated before viewer runs out of memory
+        static std::string sLocalizedOutOfMemoryTitle;
+        static std::string sLocalizedOutOfMemoryWarning;
+        static Handler sHandler;
+    };
 }
 
 //this is cheaper than llcallstacks if no need to output other variables to call stacks. 
diff --git a/indra/llcommon/llexception.cpp b/indra/llcommon/llexception.cpp
index 46560b5e4ce39ac7c12dc45b7ae1d080448090d7..0787bde57f101b02253d89cd5889dc82032ef24a 100644
--- a/indra/llcommon/llexception.cpp
+++ b/indra/llcommon/llexception.cpp
@@ -37,6 +37,7 @@
 #include "llerror.h"
 #include "llerrorcontrol.h"
 
+
 // used to attach and extract stacktrace information to/from boost::exception,
 // see https://www.boost.org/doc/libs/release/doc/html/stacktrace/getting_started.html#stacktrace.getting_started.exceptions_with_stacktrace
 // apparently the struct passed as the first template param needs no definition?
diff --git a/indra/llcommon/llsingleton.h b/indra/llcommon/llsingleton.h
index cbe5ab6406b0eac442328707474231028c091af1..64027c16c76274a4c8550ab1138b6168d488a553 100644
--- a/indra/llcommon/llsingleton.h
+++ b/indra/llcommon/llsingleton.h
@@ -455,7 +455,7 @@ class LLSingleton : public LLSingletonBase
 
     static DERIVED_TYPE* getInstance()
     {
-        LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD;
+        //LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD; // TODO -- reenable this when we have a fix for using Tracy with coroutines
         // We know the viewer has LLSingleton dependency circularities. If you
         // feel strongly motivated to eliminate them, cheers and good luck.
         // (At that point we could consider a much simpler locking mechanism.)
diff --git a/indra/llcorehttp/_httpservice.cpp b/indra/llcorehttp/_httpservice.cpp
index 294acd7f638175501216323678e8d0cb59a9b929..517076804d2b40140d135b62018f8e0a772358a5 100644
--- a/indra/llcorehttp/_httpservice.cpp
+++ b/indra/llcorehttp/_httpservice.cpp
@@ -320,6 +320,7 @@ void HttpService::threadRun(LLCoreInt::HttpThread * thread)
             LLMemory::logMemoryInfo(TRUE);
 
             //output possible call stacks to log file.
+            LLError::LLUserWarningMsg::showOutOfMemory();
             LLError::LLCallStacks::print();
 
             LL_ERRS() << "Bad memory allocation in HttpService::threadRun()!" << LL_ENDL;
diff --git a/indra/llimage/llimagebmp.cpp b/indra/llimage/llimagebmp.cpp
index 90b7272efa78f17d4314f8b07a763b23f0ba3b23..cdea0da68ddad653d88f9439b7e2d60ae1786a86 100644
--- a/indra/llimage/llimagebmp.cpp
+++ b/indra/llimage/llimagebmp.cpp
@@ -321,6 +321,7 @@ bool LLImageBMP::updateData()
 		mColorPalette = new(std::nothrow) U8[color_palette_size];
 		if (!mColorPalette)
 		{
+            LLError::LLUserWarningMsg::showOutOfMemory();
 			LL_ERRS() << "Out of memory in LLImageBMP::updateData()" << LL_ENDL;
 			return false;
 		}
diff --git a/indra/llimage/llimagedxt.cpp b/indra/llimage/llimagedxt.cpp
index 36317a5ba883c39cd973549c308ba66a658e7f73..ae76c5243f0a4215f9563ab3a614294b0f05fac3 100644
--- a/indra/llimage/llimagedxt.cpp
+++ b/indra/llimage/llimagedxt.cpp
@@ -437,6 +437,7 @@ bool LLImageDXT::convertToDXR()
 	U8* newdata = (U8*)ll_aligned_malloc_16(total_bytes);
 	if (!newdata)
 	{
+        LLError::LLUserWarningMsg::showOutOfMemory();
 		LL_ERRS() << "Out of memory in LLImageDXT::convertToDXR()" << LL_ENDL;
 		return false;
 	}
diff --git a/indra/llimage/llimagetga.cpp b/indra/llimage/llimagetga.cpp
index 88bdae9b80f4fe3f1247759bb4a2f98a51a275ac..152a7f309c0417d9b91edf142937cea3a2e7307c 100644
--- a/indra/llimage/llimagetga.cpp
+++ b/indra/llimage/llimagetga.cpp
@@ -266,6 +266,7 @@ bool LLImageTGA::updateData()
 			mColorMap = new(std::nothrow) U8[ color_map_bytes ];  
 			if (!mColorMap)
 			{
+                LLError::LLUserWarningMsg::showOutOfMemory();
 				LL_ERRS() << "Out of Memory in bool LLImageTGA::updateData()" << LL_ENDL;
 				return false;
 			}
diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp
index c6fd824c4eed881c7aa05ff0f391a44267d60237..56a12b07b1dfc32f7801b502088e7d73458666b8 100644
--- a/indra/llrender/llimagegl.cpp
+++ b/indra/llrender/llimagegl.cpp
@@ -1353,6 +1353,7 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt
                 scratch = new(std::nothrow) U32[width * height];
                 if (!scratch)
                 {
+                    LLError::LLUserWarningMsg::showOutOfMemory();
                     LL_ERRS() << "Failed to allocate " << (U32)(width * height * sizeof(U32))
                               << " bytes for a manual image W" << width << " H" << height << LL_ENDL;
                 }
@@ -1378,6 +1379,7 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt
                 scratch = new(std::nothrow) U32[width * height];
                 if (!scratch)
                 {
+                    LLError::LLUserWarningMsg::showOutOfMemory();
                     LL_ERRS() << "Failed to allocate " << (U32)(width * height * sizeof(U32))
                         << " bytes for a manual image W" << width << " H" << height << LL_ENDL;
                 }
@@ -1406,6 +1408,7 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt
                 scratch = new(std::nothrow) U32[width * height];
                 if (!scratch)
                 {
+                    LLError::LLUserWarningMsg::showOutOfMemory();
                     LL_ERRS() << "Failed to allocate " << (U32)(width * height * sizeof(U32))
                         << " bytes for a manual image W" << width << " H" << height << LL_ENDL;
                 }
diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp
index ee66122774d0487d1ed9fe3a85aa7de615a801d2..4d64dc9e104ab729f488091a4afd6b2dc1fe9b02 100644
--- a/indra/llrender/llrender.cpp
+++ b/indra/llrender/llrender.cpp
@@ -857,7 +857,7 @@ LLRender::~LLRender()
 	shutdown();
 }
 
-void LLRender::init(bool needs_vertex_buffer)
+bool LLRender::init(bool needs_vertex_buffer)
 {
 #if LL_WINDOWS
     if (gGLManager.mHasDebugOutput && gDebugGL)
@@ -879,6 +879,13 @@ void LLRender::init(bool needs_vertex_buffer)
     // necessary for reflection maps
     glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
 
+#if LL_WINDOWS
+    if (glGenVertexArrays == nullptr)
+    {
+        return false;
+    }
+#endif
+
     { //bind a dummy vertex array object so we're core profile compliant
         U32 ret;
         glGenVertexArrays(1, &ret);
@@ -889,6 +896,7 @@ void LLRender::init(bool needs_vertex_buffer)
     {
         initVertexBuffer();
     }
+    return true;
 }
 
 void LLRender::initVertexBuffer()
diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h
index fd922affbabe219dfda2ca9713abce09e89b0407..716b52354dc4fb0c2061e17e05af358f1f1b1e10 100644
--- a/indra/llrender/llrender.h
+++ b/indra/llrender/llrender.h
@@ -375,7 +375,7 @@ class LLRender
 
 	LLRender();
 	~LLRender();
-    void init(bool needs_vertex_buffer);
+    bool init(bool needs_vertex_buffer);
     void initVertexBuffer();
     void resetVertexBuffer();
 	void shutdown();
diff --git a/indra/llrender/llrendernavprim.cpp b/indra/llrender/llrendernavprim.cpp
index d610a44bc680c4462179af1d723cad84385f708a..eea30776321fa06e6efd391e3c1bd432d87fbcf7 100644
--- a/indra/llrender/llrendernavprim.cpp
+++ b/indra/llrender/llrendernavprim.cpp
@@ -40,20 +40,20 @@ LLRenderNavPrim gRenderNav;
 //=============================================================================
 void LLRenderNavPrim::renderLLTri( const LLVector3& a, const LLVector3& b, const LLVector3& c, const LLColor4U& color ) const
 {
-	LLColor4 cV(color);
-	gGL.color4fv( cV.mV );
-	gGL.begin(LLRender::TRIANGLES);
+    gGL.color4ubv(color.mV);
+
+    gGL.begin(LLRender::TRIANGLES);
 	{
 		gGL.vertex3fv( a.mV );
 		gGL.vertex3fv( b.mV );
 		gGL.vertex3fv( c.mV );
 	}
-	gGL.end();		
+	gGL.end();
 }
 //=============================================================================
 void LLRenderNavPrim::renderNavMeshVB( U32 mode, LLVertexBuffer* pVBO, int vertCnt )
 {	
 	pVBO->setBuffer();
-	pVBO->drawArrays( mode, 0, vertCnt );	
+	pVBO->drawArrays( mode, 0, vertCnt );
 }
 //=============================================================================
diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp
index d736aa6634879ca33fc27023000f539c59db6a8f..2fe9ee18e3077b681ea060a3fa57aaa39479c8f1 100644
--- a/indra/llui/llnotifications.cpp
+++ b/indra/llui/llnotifications.cpp
@@ -1553,6 +1553,7 @@ bool LLNotifications::loadTemplates()
 
 	if (!success || root.isNull() || !root->hasName( "notifications" ))
 	{
+        LLError::LLUserWarningMsg::show(LLTrans::getString("MBMissingFile"));
 		LL_ERRS() << "Problem reading XML from UI Notifications file: " << base_filename << LL_ENDL;
 		return false;
 	}
@@ -1563,6 +1564,7 @@ bool LLNotifications::loadTemplates()
 
 	if(!params.validateBlock())
 	{
+        LLError::LLUserWarningMsg::show(LLTrans::getString("MBMissingFile"));
 		LL_ERRS() << "Problem reading XUI from UI Notifications file: " << base_filename << LL_ENDL;
 		return false;
 	}
@@ -1629,6 +1631,7 @@ bool LLNotifications::loadVisibilityRules()
 
 	if(!params.validateBlock())
 	{
+        LLError::LLUserWarningMsg::show(LLTrans::getString("MBMissingFile"));
 		LL_ERRS() << "Problem reading UI Notification Visibility Rules file: " << full_filename << LL_ENDL;
 		return false;
 	}
diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp
index 2c4f32b5cb04557309a126b1920cfa456034f545..7150052b65701e81f791660022793601dc4260c2 100644
--- a/indra/llui/lltexteditor.cpp
+++ b/indra/llui/lltexteditor.cpp
@@ -2695,6 +2695,7 @@ BOOL LLTextEditor::importBuffer(const char* buffer, S32 length )
 	char* text = new char[ text_len + 1];
 	if (text == NULL)
 	{
+        LLError::LLUserWarningMsg::showOutOfMemory();
 		LL_ERRS() << "Memory allocation failure." << LL_ENDL;			
 		return FALSE;
 	}
diff --git a/indra/llui/lltransutil.cpp b/indra/llui/lltransutil.cpp
index 5da722a72bb8fd1815c5ee3ddcdb4cb58926f765..6c486f29ba94ebae5d824bc89a4ae79a07a5b9f9 100644
--- a/indra/llui/lltransutil.cpp
+++ b/indra/llui/lltransutil.cpp
@@ -44,8 +44,13 @@ bool LLTransUtil::parseStrings(const std::string& xml_filename, const std::set<s
 	bool success = LLUICtrlFactory::getLayeredXMLNode(xml_filename, root, LLDir::ALL_SKINS);
 	if (!success)
 	{
+        const std::string error_string =
+            "Second Life viewer couldn't access some of the files it needs and will be closed."
+            "\n\nPlease reinstall viewer from  https://secondlife.com/support/downloads/ and "
+            "contact https://support.secondlife.com if issue persists after reinstall.";
+        LLError::LLUserWarningMsg::show(error_string);
 		gDirUtilp->dumpCurrentDirectories(LLError::LEVEL_WARN);
-		LL_ERRS() << "Couldn't load string table " << xml_filename << ". Please reinstall viewer from  https://secondlife.com/support/downloads/ and contact https://support.secondlife.com if issue persists after reinstall." << LL_ENDL;
+		LL_ERRS() << "Couldn't load string table " << xml_filename << " " << errno << LL_ENDL;
 		return false;
 	}
 
@@ -60,6 +65,7 @@ bool LLTransUtil::parseLanguageStrings(const std::string& xml_filename)
 	
 	if (!success)
 	{
+        LLError::LLUserWarningMsg::showMissingFiles();
 		LL_ERRS() << "Couldn't load localization table " << xml_filename << LL_ENDL;
 		return false;
 	}
diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt
index b7f8ee41e6934d953db404b5c91f4465bd1850cb..69adf3456f81f66dbf635e4241f9e57336f2bc01 100644
--- a/indra/newview/VIEWER_VERSION.txt
+++ b/indra/newview/VIEWER_VERSION.txt
@@ -1 +1 @@
-7.1.4
+7.1.5
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index dc21742c31fde3600669d1e1eb9d3bd98827d3f9..2f7c256b49feb43d5ca0c06ce00a7a980236b8c5 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -3244,17 +3244,6 @@
       <key>Value</key>
       <integer>0</integer>
     </map>
-  <key>DefaultBlankNormalTexture</key>
-  <map>
-    <key>Comment</key>
-    <string>Texture used as 'Blank' in texture picker for normal maps. (UUID texture reference)</string>
-    <key>Persist</key>
-    <integer>1</integer>
-    <key>Type</key>
-    <string>String</string>
-    <key>Value</key>
-    <string>5b53359e-59dd-d8a2-04c3-9e65134da47a</string>
-  </map>
 	<key>DefaultFemaleAvatar</key>
 	<map>
 	  <key>Comment</key>
@@ -3288,39 +3277,6 @@
 	  <key>Value</key>
 	  <string>Male Shape &amp; Outfit</string>
 	</map>
-  <key>DefaultObjectNormalTexture</key>
-  <map>
-    <key>Comment</key>
-    <string>Texture used as 'Default' in texture picker for normal map. (UUID texture reference)</string>
-    <key>Persist</key>
-    <integer>1</integer>
-    <key>Type</key>
-    <string>String</string>
-    <key>Value</key>
-    <string>85f28839-7a1c-b4e3-d71d-967792970a7b</string>
-  </map>
-  <key>DefaultObjectSpecularTexture</key>
-  <map>
-    <key>Comment</key>
-    <string>Texture used as 'Default' in texture picker for specular map. (UUID texture reference)</string>
-    <key>Persist</key>
-    <integer>1</integer>
-    <key>Type</key>
-    <string>String</string>
-    <key>Value</key>
-    <string>87e0e8f7-8729-1ea8-cfc9-8915773009db</string>
-  </map>
-  <key>DefaultObjectTexture</key>
-    <map>
-      <key>Comment</key>
-      <string>Texture used as 'Default' in texture picker. (UUID texture reference)</string>
-      <key>Persist</key>
-      <integer>1</integer>
-      <key>Type</key>
-      <string>String</string>
-      <key>Value</key>
-      <string>89556747-24cb-43ed-920b-47caed15465f</string>
-    </map>
     <key>DefaultUploadCost</key>
     <map>
       <key>Comment</key>
@@ -10709,7 +10665,7 @@
     <key>Type</key>
     <string>F32</string>
     <key>Value</key>
-    <real>2.0</real>
+    <real>1.0</real>
   </map>
   <key>RendeSkyAutoAdjustBlueHorizonScale</key>
   <map>
@@ -10753,7 +10709,7 @@
     <key>Type</key>
     <string>F32</string>
     <key>Value</key>
-    <real>0.001</real>
+    <real>0.01</real>
   </map>
   <key>RenderSkySunlightScale</key>
   <map>
@@ -13653,17 +13609,6 @@
       <key>Value</key>
       <string>F3E07BC8-A973-476D-8C7F-F3B7293975D1</string>
     </map>
-    <key>UIImgWhiteUUID</key>
-    <map>
-      <key>Comment</key>
-      <string />
-      <key>Persist</key>
-      <integer>0</integer>
-      <key>Type</key>
-      <string>String</string>
-      <key>Value</key>
-      <string>5748decc-f629-461c-9a36-a35a221fe21f</string>
-    </map>
     <key>UILineEditorCursorThickness</key>
     <map>
       <key>Comment</key>
diff --git a/indra/newview/llappcorehttp.cpp b/indra/newview/llappcorehttp.cpp
index debf93dccd740753599de90fdc3adf635176e3a7..51e259992d25bf238313d653600810eefe815727 100644
--- a/indra/newview/llappcorehttp.cpp
+++ b/indra/newview/llappcorehttp.cpp
@@ -168,6 +168,7 @@ void LLAppCoreHttp::init()
     }
     else
     {
+        LLError::LLUserWarningMsg::showMissingFiles();
         LL_ERRS("Init") << "Missing CA File; should be at " << ca_file << LL_ENDL;
     }
     
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index f094170ff5216460c6d7a4238f9f009ae1b7661b..6e176183d82fa0de21a98b19d980eeceb149cf67 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -362,7 +362,6 @@ BOOL gRandomizeFramerate = FALSE;
 BOOL gPeriodicSlowFrame = FALSE;
 
 BOOL gCrashOnStartup = FALSE;
-BOOL gLLErrorActivated = FALSE;
 BOOL gLogoutInProgress = FALSE;
 
 BOOL gSimulateMemLeak = FALSE;
@@ -2258,9 +2257,6 @@ void errorCallback(LLError::ELevel level, const std::string &error_string)
         OSMessageBox(error_string, LLTrans::getString("MBFatalError"), OSMB_OK);
 #endif
 
-        //Set the ErrorActivated global so we know to create a marker file
-        gLLErrorActivated = true;
-
         gDebugInfo["FatalMessage"] = error_string;
         // We're not already crashing -- we simply *intend* to crash. Since we
         // haven't actually trashed anything yet, we can afford to write the whole
@@ -2269,6 +2265,14 @@ void errorCallback(LLError::ELevel level, const std::string &error_string)
     }
 }
 
+void errorMSG(const std::string& title_string, const std::string& message_string)
+{
+    if (!message_string.empty())
+    {
+        OSMessageBox(message_string, title_string.empty() ? LLTrans::getString("MBFatalError") : title_string, OSMB_OK);
+    }
+}
+
 void LLAppViewer::initLoggingAndGetLastDuration()
 {
     //
@@ -2280,6 +2284,8 @@ void LLAppViewer::initLoggingAndGetLastDuration()
     LLError::addGenericRecorder(&errorCallback);
     //LLError::setTimeFunction(getRuntime);
 
+    LLError::LLUserWarningMsg::setHandler(errorMSG);
+
 
     if (mSecondInstance)
     {
@@ -2417,6 +2423,7 @@ bool LLAppViewer::loadSettingsFromDirectory(const std::string& location_key,
 			{	// failed to load
 				if(file.required)
 				{
+                    LLError::LLUserWarningMsg::showMissingFiles();
 					LL_ERRS() << "Error: Cannot load required settings file from: " << full_settings_path << LL_ENDL;
 					return false;
 				}
@@ -2515,6 +2522,7 @@ bool LLAppViewer::initConfiguration()
 	if (!success)
 	{
         LL_WARNS() << "Cannot load default configuration file " << settings_file_list << LL_ENDL;
+        LLError::LLUserWarningMsg::showMissingFiles();
         if (gDirUtilp->fileExists(settings_file_list))
         {
             LL_ERRS() << "Cannot load default configuration file settings_files.xml. "
@@ -2538,6 +2546,7 @@ bool LLAppViewer::initConfiguration()
 
 	if (!mSettingsLocationList->validateBlock())
 	{
+        LLError::LLUserWarningMsg::showMissingFiles();
         LL_ERRS() << "Invalid settings file list " << settings_file_list << LL_ENDL;
 	}
 
@@ -2973,6 +2982,8 @@ bool LLAppViewer::initConfiguration()
 		LLEventPumps::instance().obtain("LLControlGroup").post(LLSDMap("init", key));
 	}
 
+    LLError::LLUserWarningMsg::setOutOfMemoryStrings(LLTrans::getString("MBOutOfMemoryTitle"), LLTrans::getString("MBOutOfMemoryErr"));
+
 	return true; // Config was successful.
 }
 
@@ -3010,6 +3021,7 @@ void LLAppViewer::initStrings()
 
 		// initial check to make sure files are there failed
 		gDirUtilp->dumpCurrentDirectories(LLError::LEVEL_WARN);
+        LLError::LLUserWarningMsg::showMissingFiles();
 		LL_ERRS() << "Viewer failed to find localization and UI files."
 			<< " Please reinstall viewer from https://secondlife.com/support/downloads"
 			<< " and contact https://support.secondlife.com if issue persists after reinstall." << LL_ENDL;
@@ -3334,7 +3346,6 @@ LLSD LLAppViewer::getViewerInfo() const
     info["NET_BANDWITH"] = gSavedSettings.getF32("ThrottleBandwidthKBPS");
     info["LOD_FACTOR"] = gSavedSettings.getF32("RenderVolumeLODFactor");
     info["RENDER_QUALITY"] = (F32)gSavedSettings.getU32("RenderQualityPerformance");
-    info["GPU_SHADERS"] = gSavedSettings.getBOOL("RenderDeferred") ? "Enabled" : "Disabled";
     info["TEXTURE_MEMORY"] = gGLManager.mVRAM;
 
 #if LL_DARWIN
@@ -4316,6 +4327,7 @@ void LLAppViewer::loadKeyBindings()
 		key_bindings_file = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "key_bindings.xml");
 		if (!gViewerInput.loadBindingsXML(key_bindings_file))
 		{
+            LLError::LLUserWarningMsg::showMissingFiles();
 			LL_ERRS("InitInfo") << "Unable to open default key bindings from " << key_bindings_file << LL_ENDL;
 		}
 	}
@@ -5409,6 +5421,14 @@ void LLAppViewer::forceErrorLLError()
    	LL_ERRS() << "This is a deliberate llerror" << LL_ENDL;
 }
 
+void LLAppViewer::forceErrorLLErrorMsg()
+{
+    LLError::LLUserWarningMsg::show("Deliberate error");
+    // Note: under debug this will show a message as well,
+    // but release won't show anything and will quit silently
+    LL_ERRS() << "This is a deliberate llerror with a message" << LL_ENDL;
+}
+
 void LLAppViewer::forceErrorBreakpoint()
 {
    	LL_WARNS() << "Forcing a deliberate breakpoint" << LL_ENDL;
diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h
index c5faa67120d6730cefc60a92df9dbb2177b3ccf4..9352dba06d4bb157f1ce905e1dc99d612a431ea2 100644
--- a/indra/newview/llappviewer.h
+++ b/indra/newview/llappviewer.h
@@ -152,6 +152,7 @@ class LLAppViewer : public LLApp
     // LLAppViewer testing helpers.
     // *NOTE: These will potentially crash the viewer. Only for debugging.
     virtual void forceErrorLLError();
+    virtual void forceErrorLLErrorMsg();
     virtual void forceErrorBreakpoint();
     virtual void forceErrorBadMemoryAccess();
     virtual void forceErrorInfiniteLoop();
diff --git a/indra/newview/llavatarrenderinfoaccountant.cpp b/indra/newview/llavatarrenderinfoaccountant.cpp
index a6c9a41fa46e0bf8d0e85b28b9829b00c4072b36..b95b9718906c57373b3fabdb4fd0c79a73a6ec81 100644
--- a/indra/newview/llavatarrenderinfoaccountant.cpp
+++ b/indra/newview/llavatarrenderinfoaccountant.cpp
@@ -339,6 +339,7 @@ void LLAvatarRenderInfoAccountant::sendRenderInfoToRegion(LLViewerRegion * regio
         }
         catch (std::bad_alloc&)
         {
+            LLError::LLUserWarningMsg::showOutOfMemory();
             LL_ERRS() << "LLCoros::launch() allocation failure" << LL_ENDL;
         }
 	}
@@ -370,6 +371,7 @@ void LLAvatarRenderInfoAccountant::getRenderInfoFromRegion(LLViewerRegion * regi
         }
         catch (std::bad_alloc&)
         {
+            LLError::LLUserWarningMsg::showOutOfMemory();
             LL_ERRS() << "LLCoros::launch() allocation failure" << LL_ENDL;
         }
 	}
diff --git a/indra/newview/llenvironment.cpp b/indra/newview/llenvironment.cpp
index edc7bdef5f2ba17276be492428574afa8958c305..60c268207895d36cc468046fe5c9757465ce8201 100644
--- a/indra/newview/llenvironment.cpp
+++ b/indra/newview/llenvironment.cpp
@@ -815,7 +815,7 @@ const F64Seconds LLEnvironment::TRANSITION_SLOW(10.0f);
 const F64Seconds LLEnvironment::TRANSITION_ALTITUDE(5.0f);
 
 const LLUUID LLEnvironment::KNOWN_SKY_SUNRISE("01e41537-ff51-2f1f-8ef7-17e4df760bfb");
-const LLUUID LLEnvironment::KNOWN_SKY_MIDDAY("651510b8-5f4d-8991-1592-e7eeab2a5a06");
+const LLUUID LLEnvironment::KNOWN_SKY_MIDDAY("c46226b4-0e43-5a56-9708-d27ca1df3292");
 const LLUUID LLEnvironment::KNOWN_SKY_LEGACY_MIDDAY("cef49723-0292-af49-9b14-9598a616b8a3");
 const LLUUID LLEnvironment::KNOWN_SKY_SUNSET("084e26cd-a900-28e8-08d0-64a9de5c15e2");
 const LLUUID LLEnvironment::KNOWN_SKY_MIDNIGHT("8a01b97a-cb20-c1ea-ac63-f7ea84ad0090");
@@ -895,6 +895,14 @@ void LLEnvironment::initSingleton()
         gGenericDispatcher.addHandler(MESSAGE_PUSHENVIRONMENT, &environment_push_dispatch_handler);
     }
 
+    gSavedSettings.getControl("RenderSkyAutoAdjustProbeAmbiance")->getSignal()->connect(
+        [](LLControlVariable*, const LLSD& new_val, const LLSD& old_val)
+        {
+            LLSettingsSky::sAutoAdjustProbeAmbiance = new_val.asReal();
+        }
+    );
+    LLSettingsSky::sAutoAdjustProbeAmbiance = gSavedSettings.getF32("RenderSkyAutoAdjustProbeAmbiance");
+
     LLEventPumps::instance().obtain(PUMP_EXPERIENCE).stopListening(LISTENER_NAME);
     LLEventPumps::instance().obtain(PUMP_EXPERIENCE).listen(LISTENER_NAME, [this](LLSD message) { listenExperiencePump(message); return false; });
 }
diff --git a/indra/newview/llfloaterchangeitemthumbnail.cpp b/indra/newview/llfloaterchangeitemthumbnail.cpp
index 0301627c152eb4d07ca01adc88ef5bb714f89c44..776f8dc785254b5d81f369553e640b8959d391d9 100644
--- a/indra/newview/llfloaterchangeitemthumbnail.cpp
+++ b/indra/newview/llfloaterchangeitemthumbnail.cpp
@@ -751,7 +751,8 @@ void LLFloaterChangeItemThumbnail::showTexturePicker(const LLUUID &thumbnail_id)
             PERM_NONE,
             PERM_NONE,
             FALSE,
-            NULL);
+            NULL,
+            PICK_TEXTURE);
 
         mPickerHandle = floaterp->getHandle();
 
diff --git a/indra/newview/llfloatereditextdaycycle.cpp b/indra/newview/llfloatereditextdaycycle.cpp
index bb47feaa9565938ca9cecbbd17f423b64df047e4..4e764674e5fd741dbdbd0f0bcc516749685eda1a 100644
--- a/indra/newview/llfloatereditextdaycycle.cpp
+++ b/indra/newview/llfloatereditextdaycycle.cpp
@@ -1724,7 +1724,9 @@ void LLFloaterEditExtDayCycle::showHDRNotification(const LLSettingsDay::ptr_t &p
         while (iter != end)
         {
             LLSettingsSky::ptr_t sky = std::static_pointer_cast<LLSettingsSky>(iter->second);
-            if (sky && sky->canAutoAdjust()) 
+            if (sky
+                && sky->canAutoAdjust()
+                && sky->getReflectionProbeAmbiance(true) != 0.f) 
             {
                 LLNotificationsUtil::add("AutoAdjustHDRSky");
                 return;
diff --git a/indra/newview/llfloaterenvironmentadjust.cpp b/indra/newview/llfloaterenvironmentadjust.cpp
index c64ee5a69ceaa512ee51c9749e25542e7d4e44b5..c98afefa65fee5a18e10c41288622d1f1243f8a1 100644
--- a/indra/newview/llfloaterenvironmentadjust.cpp
+++ b/indra/newview/llfloaterenvironmentadjust.cpp
@@ -116,7 +116,7 @@ BOOL LLFloaterEnvironmentAdjust::postBuild()
     getChild<LLTextureCtrl>(FIELD_SKY_CLOUD_MAP)->setAllowNoTexture(TRUE);
 
     getChild<LLTextureCtrl>(FIELD_WATER_NORMAL_MAP)->setDefaultImageAssetID(LLSettingsWater::GetDefaultWaterNormalAssetId());
-    getChild<LLTextureCtrl>(FIELD_WATER_NORMAL_MAP)->setBlankImageAssetID(LLUUID(gSavedSettings.getString("DefaultBlankNormalTexture")));
+    getChild<LLTextureCtrl>(FIELD_WATER_NORMAL_MAP)->setBlankImageAssetID(BLANK_OBJECT_NORMAL);
     getChild<LLTextureCtrl>(FIELD_WATER_NORMAL_MAP)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onWaterMapChanged(); });
 
     getChild<LLUICtrl>(FIELD_REFLECTION_PROBE_AMBIANCE)->setCommitCallback([this](LLUICtrl*, const LLSD&) { onReflectionProbeAmbianceChanged(); });
diff --git a/indra/newview/llfloaterfixedenvironment.cpp b/indra/newview/llfloaterfixedenvironment.cpp
index 8e28fd6234afc271208fb80409052721e60ef334..3e8bad3ef58e92b197ede0a764b612011ad90dab 100644
--- a/indra/newview/llfloaterfixedenvironment.cpp
+++ b/indra/newview/llfloaterfixedenvironment.cpp
@@ -186,7 +186,8 @@ void LLFloaterFixedEnvironment::setEditSettingsAndUpdate(const LLSettingsBase::p
     // teach user about HDR settings
     if (mSettings
         && mSettings->getSettingsType() == "sky"
-        && ((LLSettingsSky*)mSettings.get())->canAutoAdjust())
+        && ((LLSettingsSky*)mSettings.get())->canAutoAdjust()
+        && ((LLSettingsSky*)mSettings.get())->getReflectionProbeAmbiance(true) != 0.f)
     {
         LLNotificationsUtil::add("AutoAdjustHDRSky");
     }
diff --git a/indra/newview/llgltfmateriallist.cpp b/indra/newview/llgltfmateriallist.cpp
index 8919229c78b9edaa6e436df75672bd00c4438144..92c58a2dbcc77e9170a8973bfe6871aa2d33fbdb 100644
--- a/indra/newview/llgltfmateriallist.cpp
+++ b/indra/newview/llgltfmateriallist.cpp
@@ -139,69 +139,18 @@ static bool is_valid_update(const LLSD& data)
 }
 #endif
 
-class LLGLTFMaterialOverrideDispatchHandler : public LLDispatchHandler
+class LLGLTFMaterialOverrideDispatchHandler
 {
     LOG_CLASS(LLGLTFMaterialOverrideDispatchHandler);
 public:
     LLGLTFMaterialOverrideDispatchHandler() = default;
-    ~LLGLTFMaterialOverrideDispatchHandler() override = default;
+    ~LLGLTFMaterialOverrideDispatchHandler() = default;
 
     void addCallback(void(*callback)(const LLUUID& object_id, S32 side))
     {
         mSelectionCallbacks.push_back(callback);
     }
 
-    bool operator()(const LLDispatcher* dispatcher, const std::string& key, const LLUUID& invoice, const sparam_t& strings) override
-    {
-        LL_PROFILE_ZONE_SCOPED;
-        // receive override data from simulator via LargeGenericMessage
-        // message should have:
-        //  object_id - UUID of LLViewerObject
-        //  sides - array of S32 indices of texture entries
-        //  gltf_json - array of corresponding Strings of GLTF json for override data
-
-        LLSD message;
-        bool success = true;
-#if 0 //deprecated
-        for(const std::string& llsdRaw : strings)
-        {
-            std::istringstream llsdData(llsdRaw);
-            if (!LLSDSerialize::deserialize(message, llsdData, llsdRaw.length()))
-            {
-                LL_WARNS() << "LLGLTFMaterialOverrideDispatchHandler: Attempted to read parameter data into LLSD but failed:" << llsdRaw << LL_ENDL;
-                success = false;
-                continue;
-            }
-
-            LLGLTFOverrideCacheEntry object_override;
-            if (!object_override.fromLLSD(message))
-            {
-                // malformed message, nothing we can do to handle it
-                LL_DEBUGS("GLTF") << "Message without id:" << message << LL_ENDL;
-                success = false;
-                continue;
-            }
-
-            // Cache the data
-            {
-                LLViewerRegion * region = LLWorld::instance().getRegionFromHandle(object_override.mRegionHandle);
-
-                if (region)
-                {
-                    region->cacheFullUpdateGLTFOverride(object_override);
-                }
-                else
-                {
-                    LL_WARNS("GLTF") << "could not access region for material overrides message cache, region_handle: " << LL_ENDL;
-                }
-            }
-            applyData(object_override);
-        }
-
-#endif
-        return success;
-    }
-
     void doSelectionCallbacks(const LLUUID& object_id, S32 side)
     {
         for (auto& callback : mSelectionCallbacks)
@@ -210,112 +159,6 @@ class LLGLTFMaterialOverrideDispatchHandler : public LLDispatchHandler
         }
     }
 
-    void applyData(const LLGLTFOverrideCacheEntry &object_override)
-    {
-        // Parse the data
-
-#if 0 // DEPRECATED
-        LL::WorkQueue::ptr_t main_queue = LL::WorkQueue::getInstance("mainloop");
-        LL::WorkQueue::ptr_t general_queue = LL::WorkQueue::getInstance("General");
-
-        struct ReturnData
-        {
-        public:
-            LLGLTFMaterial mMaterial;
-            S32 mSide;
-            bool mSuccess;
-        };
-
-        if (!object_override.mSides.empty())
-        {
-            // fromJson() is performance heavy offload to a thread.
-            main_queue->postTo(
-                general_queue,
-                [sides=object_override.mSides]() // Work done on general queue
-            {
-                std::vector<ReturnData> results;
-
-                results.reserve(sides.size());
-                // parse json
-                std::unordered_map<S32, LLSD>::const_iterator iter = sides.begin();
-                std::unordered_map<S32, LLSD>::const_iterator end = sides.end();
-                while (iter != end)
-                {
-                    ReturnData result;
-
-                    result.mMaterial.applyOverrideLLSD(iter->second);
-                    
-                    result.mSuccess = true;
-                    result.mSide = iter->first;
-
-                    results.push_back(result);
-                    iter++;
-                }
-                return results;
-            },
-            [object_id=object_override.mObjectId, this](std::vector<ReturnData> results) // Callback to main thread
-            {
-                LLViewerObject * obj = gObjectList.findObject(object_id);
-
-                if (results.size() > 0 )
-                {
-                    std::unordered_set<S32> side_set;
-
-                    for (auto const & result : results)
-                    {
-                        S32 side = result.mSide;
-                        if (result.mSuccess)
-                        {
-                            // copy to heap here because LLTextureEntry is going to take ownership with an LLPointer
-                            LLGLTFMaterial * material = new LLGLTFMaterial(result.mMaterial);
-
-                            // flag this side to not be nulled out later
-                            side_set.insert(side);
-
-                            if (obj)
-                            {
-                                obj->setTEGLTFMaterialOverride(side, material);
-                            }
-                        }
-
-                        // unblock material editor
-                        if (obj && obj->getTE(side) && obj->getTE(side)->isSelected())
-                        {
-                            doSelectionCallbacks(object_id, side);
-                        }
-                    }
-
-                    if (obj && side_set.size() != obj->getNumTEs())
-                    { // object exists and at least one texture entry needs to have its override data nulled out
-                        for (int i = 0; i < obj->getNumTEs(); ++i)
-                        {
-                            if (side_set.find(i) == side_set.end())
-                            {
-                                obj->setTEGLTFMaterialOverride(i, nullptr);
-                                if (obj->getTE(i) && obj->getTE(i)->isSelected())
-                                {
-                                    doSelectionCallbacks(object_id, i);
-                                }
-                            }
-                        }
-                    }
-                }
-                else if (obj)
-                { // override list was empty or an error occurred, null out all overrides for this object
-                    for (int i = 0; i < obj->getNumTEs(); ++i)
-                    {
-                        obj->setTEGLTFMaterialOverride(i, nullptr);
-                        if (obj->getTE(i) && obj->getTE(i)->isSelected())
-                        {
-                            doSelectionCallbacks(obj->getID(), i);
-                        }
-                    }
-                }
-            });
-        }
-#endif
-    }
-
 private:
 
     std::vector<void(*)(const LLUUID& object_id, S32 side)> mSelectionCallbacks;
@@ -821,12 +664,6 @@ void LLGLTFMaterialList::flushMaterials()
     }
 }
 
-// static
-void LLGLTFMaterialList::registerCallbacks()
-{
-    gGenericDispatcher.addHandler("GLTFMaterialOverride", &handle_gltf_override_message);
-}
-
 // static
 void LLGLTFMaterialList::modifyMaterialCoro(std::string cap_url, LLSD overrides, void(*done_callback)(bool) )
 {
@@ -864,7 +701,3 @@ void LLGLTFMaterialList::modifyMaterialCoro(std::string cap_url, LLSD overrides,
     }
 }
 
-void LLGLTFMaterialList::loadCacheOverrides(const LLGLTFOverrideCacheEntry& override)
-{
-    handle_gltf_override_message.applyData(override);
-}
diff --git a/indra/newview/llgltfmateriallist.h b/indra/newview/llgltfmateriallist.h
index 7317214019d52ec41e39f96f057ca747c39d4f34..f1c4ce20f91c5ace4afee9f452c88cfb03ec6993 100644
--- a/indra/newview/llgltfmateriallist.h
+++ b/indra/newview/llgltfmateriallist.h
@@ -52,8 +52,6 @@ class LLGLTFMaterialList
 
     void flushMaterials();
 
-    static void registerCallbacks();
-
     // Queue an modification of a material that we want to send to the simulator.  Call "flushUpdates" to flush pending updates.
     //  id - ID of object to modify
     //  side - TexureEntry index to modify, or -1 for all sides
@@ -99,8 +97,6 @@ class LLGLTFMaterialList
     // any override data that arrived before the object was ready to receive it
     void applyQueuedOverrides(LLViewerObject* obj);
 
-    static void loadCacheOverrides(const LLGLTFOverrideCacheEntry& override);
-
     // Apply an override update with the given data
     void applyOverrideMessage(LLMessageSystem* msg, const std::string& data);
 
diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp
index 8122f3bcf5935ad4d9f35b4db21c239fe69da9a8..7ddc0c18b2e50cb3420322a73b46239ccc23f08e 100644
--- a/indra/newview/llinventoryfunctions.cpp
+++ b/indra/newview/llinventoryfunctions.cpp
@@ -2572,6 +2572,12 @@ bool LLIsOfAssetType::operator()(LLInventoryCategory* cat, LLInventoryItem* item
 	return FALSE;
 }
 
+bool LLAssetIDAndTypeMatches::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
+{
+    if (!item) return false;
+    return (item->getActualType() == mType && item->getAssetUUID() == mAssetID);
+}
+
 bool LLIsValidItemLink::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
 {
 	LLViewerInventoryItem *vitem = dynamic_cast<LLViewerInventoryItem*>(item);
diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h
index fcbef57101400d846638997580600c3b365c1dcb..5a833eab8c5a0821ef1faae243ec4052ba594b07 100644
--- a/indra/newview/llinventoryfunctions.h
+++ b/indra/newview/llinventoryfunctions.h
@@ -279,6 +279,28 @@ class LLIsOfAssetType : public LLInventoryCollectFunctor
 	LLAssetType::EType mType;
 };
 
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Class LLAssetIDAndTypeMatches
+//
+// Implementation of a LLInventoryCollectFunctor which returns TRUE if
+// the item matches both asset type and asset id.
+// This is needed in case you are looking for a specific type with default id
+// (since null is default for multiple asset types)
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+class LLAssetIDAndTypeMatches: public LLInventoryCollectFunctor
+{
+public:
+    LLAssetIDAndTypeMatches(const LLUUID& asset_id, LLAssetType::EType type): mAssetID(asset_id), mType(type) {}
+    virtual ~LLAssetIDAndTypeMatches() {}
+    bool operator()(LLInventoryCategory* cat,
+                    LLInventoryItem* item);
+
+protected:
+    LLUUID mAssetID;
+    LLAssetType::EType mType;
+};
+
 class LLIsValidItemLink : public LLInventoryCollectFunctor
 {
 public:
diff --git a/indra/newview/llmaterialeditor.cpp b/indra/newview/llmaterialeditor.cpp
index 1f5974c74dd6801b6d506740d3393dc2b4251bc4..b7828db3a9b05ee33ca6ae6489563303d963155a 100644
--- a/indra/newview/llmaterialeditor.cpp
+++ b/indra/newview/llmaterialeditor.cpp
@@ -43,6 +43,7 @@
 #include "llnotificationsutil.h"
 #include "lltexturectrl.h"
 #include "lltrans.h"
+#include "llviewercontrol.h"
 #include "llviewermenufile.h"
 #include "llviewertexture.h"
 #include "llsdutil.h"
@@ -448,6 +449,8 @@ BOOL LLMaterialEditor::postBuild()
     mEmissiveTextureCtrl->setCommitCallback(boost::bind(&LLMaterialEditor::onCommitTexture, this, _1, _2, MATERIAL_EMISIVE_TEX_DIRTY));
     mNormalTextureCtrl->setCommitCallback(boost::bind(&LLMaterialEditor::onCommitTexture, this, _1, _2, MATERIAL_NORMAL_TEX_DIRTY));
 
+    mNormalTextureCtrl->setBlankImageAssetID(BLANK_OBJECT_NORMAL);
+
     if (mIsOverride)
     {
         // Live editing needs a recovery mechanism on cancel
@@ -1376,10 +1379,23 @@ bool LLMaterialEditor::saveIfNeeded()
         LLPermissions local_permissions;
         local_permissions.init(gAgent.getID(), gAgent.getID(), LLUUID::null, LLUUID::null);
 
-        U32 everyone_perm = LLFloaterPerms::getEveryonePerms("Materials");
-        U32 group_perm = LLFloaterPerms::getGroupPerms("Materials");
-        U32 next_owner_perm = LLFloaterPerms::getNextOwnerPerms("Materials");
-        local_permissions.initMasks(PERM_ALL, PERM_ALL, everyone_perm, group_perm, next_owner_perm);
+        if (mIsOverride)
+        {
+            // Shouldn't happen, but just in case it ever changes
+            U32 everyone_perm = LLFloaterPerms::getEveryonePerms("Materials");
+            U32 group_perm = LLFloaterPerms::getGroupPerms("Materials");
+            U32 next_owner_perm = LLFloaterPerms::getNextOwnerPerms("Materials");
+            local_permissions.initMasks(PERM_ALL, PERM_ALL, everyone_perm, group_perm, next_owner_perm);
+
+        }
+        else
+        {
+            // Uploads are supposed to use Upload permissions, not material permissions
+            U32 everyone_perm = LLFloaterPerms::getEveryonePerms("Uploads");
+            U32 group_perm = LLFloaterPerms::getGroupPerms("Uploads");
+            U32 next_owner_perm = LLFloaterPerms::getNextOwnerPerms("Uploads");
+            local_permissions.initMasks(PERM_ALL, PERM_ALL, everyone_perm, group_perm, next_owner_perm);
+        }
 
         std::string res_desc = buildMaterialDescription();
         createInventoryItem(buffer, mMaterialName, res_desc, local_permissions);
diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp
index 1398c1acdb0f99615febce1e316ebfe7a16d8d87..48fd946a21f4928305d610f1cb6b3b86f0167b8b 100644
--- a/indra/newview/llmeshrepository.cpp
+++ b/indra/newview/llmeshrepository.cpp
@@ -1360,7 +1360,7 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id, bool can_retry)
 				U8* buffer = new(std::nothrow) U8[size];
 				if (!buffer)
 				{
-					LL_WARNS_ONCE(LOG_MESH) << "Failed to allocate memory for skin info, size: " << size << LL_ENDL;
+					LL_WARNS(LOG_MESH) << "Failed to allocate memory for skin info, size: " << size << LL_ENDL;
 					return false;
 				}
 				LLMeshRepository::sCacheBytesRead += size;
@@ -1473,7 +1473,7 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id)
 				U8* buffer = new(std::nothrow) U8[size];
 				if (!buffer)
 				{
-					LL_WARNS_ONCE(LOG_MESH) << "Failed to allocate memory for mesh decomposition, size: " << size << LL_ENDL;
+					LL_WARNS(LOG_MESH) << "Failed to allocate memory for mesh decomposition, size: " << size << LL_ENDL;
 					return false;
 				}
 				LLMeshRepository::sCacheBytesRead += size;
@@ -1575,7 +1575,7 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id)
 				U8* buffer = new(std::nothrow) U8[size];
 				if (!buffer)
 				{
-					LL_WARNS_ONCE(LOG_MESH) << "Failed to allocate memory for physics shape, size: " << size << LL_ENDL;
+					LL_WARNS(LOG_MESH) << "Failed to allocate memory for physics shape, size: " << size << LL_ENDL;
 					return false;
 				}
 				file.read(buffer, size);
@@ -1770,7 +1770,7 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod,
 				U8* buffer = new(std::nothrow) U8[size];
 				if (!buffer)
 				{
-					LL_WARNS_ONCE(LOG_MESH) << "Can't allocate memory for mesh " << mesh_id << " LOD " << lod << ", size: " << size << LL_ENDL;
+					LL_WARNS(LOG_MESH) << "Can't allocate memory for mesh " << mesh_id << " LOD " << lod << ", size: " << size << LL_ENDL;
 					// todo: for now it will result in indefinite constant retries, should result in timeout
 					// or in retry-count and disabling mesh. (but usually viewer is beyond saving at this point)
 					return false;
diff --git a/indra/newview/llpaneleditwater.cpp b/indra/newview/llpaneleditwater.cpp
index a09964e17dcb0290f743eb0d4bc9588e783a4a7e..cf536dd87e3e2413457007a65d38632a27aac47d 100644
--- a/indra/newview/llpaneleditwater.cpp
+++ b/indra/newview/llpaneleditwater.cpp
@@ -89,7 +89,7 @@ BOOL LLPanelSettingsWaterMainTab::postBuild()
     getChild<LLUICtrl>(FIELD_WATER_UNDERWATER_MOD)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onFogUnderWaterChanged(); });
 
     mTxtNormalMap->setDefaultImageAssetID(LLSettingsWater::GetDefaultWaterNormalAssetId());
-    mTxtNormalMap->setBlankImageAssetID(LLUUID( gSavedSettings.getString( "DefaultBlankNormalTexture" )));
+    mTxtNormalMap->setBlankImageAssetID(BLANK_OBJECT_NORMAL);
     mTxtNormalMap->setCommitCallback([this](LLUICtrl *, const LLSD &) { onNormalMapChanged(); });
 
     getChild<LLUICtrl>(FIELD_WATER_WAVE2_XY)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onSmallWaveChanged(); });
diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp
index 5f8071d3ebf61e99accce1d477bdc30f71086500..a527ebe47fa07186f2afe844ab32324f304bf8ed 100644
--- a/indra/newview/llpanelface.cpp
+++ b/indra/newview/llpanelface.cpp
@@ -227,6 +227,17 @@ LLRender::eTexIndex LLPanelFace::getTextureDropChannel()
     return LLRender::eTexIndex(MATTYPE_DIFFUSE);
 }
 
+LLGLTFMaterial::TextureInfo LLPanelFace::getPBRDropChannel()
+{
+    if (mComboMatMedia && mComboMatMedia->getCurrentIndex() == MATMEDIA_PBR)
+    {
+        LLRadioGroup* radio_pbr_type = getChild<LLRadioGroup>("radio_pbr_type");
+        return texture_info_from_pbrtype(radio_pbr_type->getSelectedIndex());
+    }
+
+    return texture_info_from_pbrtype(PBRTYPE_BASE_COLOR);
+}
+
 // Things the UI provides...
 //
 LLUUID	LLPanelFace::getCurrentNormalMap()			{ return getChild<LLTextureCtrl>("bumpytexture control")->getImageAssetID();	}
@@ -330,13 +341,13 @@ BOOL	LLPanelFace::postBuild()
         pbr_ctrl->setImmediateFilterPermMask(PERM_NONE);
         pbr_ctrl->setDnDFilterPermMask(PERM_COPY | PERM_TRANSFER);
         pbr_ctrl->setBakeTextureEnabled(false);
-        pbr_ctrl->setInventoryPickType(LLTextureCtrl::PICK_MATERIAL);
+        pbr_ctrl->setInventoryPickType(PICK_MATERIAL);
     }
 
 	mTextureCtrl = getChild<LLTextureCtrl>("texture control");
 	if(mTextureCtrl)
 	{
-		mTextureCtrl->setDefaultImageAssetID(LLUUID( gSavedSettings.getString( "DefaultObjectTexture" )));
+		mTextureCtrl->setDefaultImageAssetID(DEFAULT_OBJECT_TEXTURE);
 		mTextureCtrl->setCommitCallback( boost::bind(&LLPanelFace::onCommitTexture, this, _2) );
 		mTextureCtrl->setOnCancelCallback( boost::bind(&LLPanelFace::onCancelTexture, this, _2) );
 		mTextureCtrl->setOnSelectCallback( boost::bind(&LLPanelFace::onSelectTexture, this, _2) );
@@ -353,7 +364,7 @@ BOOL	LLPanelFace::postBuild()
 	mShinyTextureCtrl = getChild<LLTextureCtrl>("shinytexture control");
 	if(mShinyTextureCtrl)
 	{
-		mShinyTextureCtrl->setDefaultImageAssetID(LLUUID( gSavedSettings.getString( "DefaultObjectSpecularTexture" )));
+		mShinyTextureCtrl->setDefaultImageAssetID(DEFAULT_OBJECT_SPECULAR);
 		mShinyTextureCtrl->setCommitCallback( boost::bind(&LLPanelFace::onCommitSpecularTexture, this, _2) );
 		mShinyTextureCtrl->setOnCancelCallback( boost::bind(&LLPanelFace::onCancelSpecularTexture, this, _2) );
 		mShinyTextureCtrl->setOnSelectCallback( boost::bind(&LLPanelFace::onSelectSpecularTexture, this, _2) );
@@ -370,8 +381,8 @@ BOOL	LLPanelFace::postBuild()
 	mBumpyTextureCtrl = getChild<LLTextureCtrl>("bumpytexture control");
 	if(mBumpyTextureCtrl)
 	{
-		mBumpyTextureCtrl->setDefaultImageAssetID(LLUUID( gSavedSettings.getString( "DefaultObjectNormalTexture" )));
-		mBumpyTextureCtrl->setBlankImageAssetID(LLUUID( gSavedSettings.getString( "DefaultBlankNormalTexture" )));
+		mBumpyTextureCtrl->setDefaultImageAssetID(DEFAULT_OBJECT_NORMAL);
+		mBumpyTextureCtrl->setBlankImageAssetID(BLANK_OBJECT_NORMAL);
 		mBumpyTextureCtrl->setCommitCallback( boost::bind(&LLPanelFace::onCommitNormalTexture, this, _2) );
 		mBumpyTextureCtrl->setOnCancelCallback( boost::bind(&LLPanelFace::onCancelNormalTexture, this, _2) );
 		mBumpyTextureCtrl->setOnSelectCallback( boost::bind(&LLPanelFace::onSelectNormalTexture, this, _2) );
@@ -4413,7 +4424,7 @@ void LLPanelFace::onCopyTexture()
                         LLUUID id = mat_data["NormMap"].asUUID();
                         if (id.notNull() && !get_can_copy_texture(id))
                         {
-                            mat_data["NormMap"] = LLUUID(gSavedSettings.getString("DefaultObjectTexture"));
+                            mat_data["NormMap"] = DEFAULT_OBJECT_TEXTURE;
                             mat_data["NormMapNoCopy"] = true;
                         }
 
@@ -4423,7 +4434,7 @@ void LLPanelFace::onCopyTexture()
                         LLUUID id = mat_data["SpecMap"].asUUID();
                         if (id.notNull() && !get_can_copy_texture(id))
                         {
-                            mat_data["SpecMap"] = LLUUID(gSavedSettings.getString("DefaultObjectTexture"));
+                            mat_data["SpecMap"] = DEFAULT_OBJECT_TEXTURE;
                             mat_data["SpecMapNoCopy"] = true;
                         }
 
@@ -4653,7 +4664,8 @@ void LLPanelFace::onPasteTexture(LLViewerObject* objectp, S32 te)
                         LLToolDragAndDrop::dropTextureAllFaces(objectp,
                             itemp_res,
                             from_library ? LLToolDragAndDrop::SOURCE_LIBRARY : LLToolDragAndDrop::SOURCE_AGENT,
-                            LLUUID::null);
+                            LLUUID::null,
+                            false);
                     }
                     else // one face
                     {
@@ -4662,6 +4674,7 @@ void LLPanelFace::onPasteTexture(LLViewerObject* objectp, S32 te)
                             itemp_res,
                             from_library ? LLToolDragAndDrop::SOURCE_LIBRARY : LLToolDragAndDrop::SOURCE_AGENT,
                             LLUUID::null,
+                            false,
                             0);
                     }
                 }
@@ -5176,8 +5189,9 @@ void LLPanelFace::onPbrSelectionChanged(LLInventoryItem* itemp)
         bool can_modify = itemp->getPermissions().allowOperationBy(PERM_MODIFY, gAgentID); // do we have perm to transfer this material?
         bool is_object_owner = gAgentID == obj_owner_id; // does object for which we are going to apply material belong to the agent?
         bool not_for_sale = !sale_info.isForSale(); // is object for which we are going to apply material not for sale?
+        bool from_library = ALEXANDRIA_LINDEN_ID == itemp->getPermissions().getOwner();
 
-        if (can_copy && can_transfer && can_modify)
+        if ((can_copy && can_transfer && can_modify) || from_library)
         {
             pbr_ctrl->setCanApply(true, true);
             return;
diff --git a/indra/newview/llpanelface.h b/indra/newview/llpanelface.h
index 5ca6a956994686fd6448fae33d240d25e02fbe76..a64b85815f7462b7f30f6e104289d6d99e8acc42 100644
--- a/indra/newview/llpanelface.h
+++ b/indra/newview/llpanelface.h
@@ -126,6 +126,7 @@ class LLPanelFace : public LLPanel
 
 	LLRender::eTexIndex getTextureChannelToEdit();
     LLRender::eTexIndex getTextureDropChannel();
+    LLGLTFMaterial::TextureInfo getPBRDropChannel();
 
 protected:
     void			navigateToTitleMedia(const std::string url);
diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp
index ffbed778c16d6ae4e26bf57c9b328e1e1592e6c0..8114e05a9465710c3388b368a7de3edd1f722ddf 100644
--- a/indra/newview/llpanelprofile.cpp
+++ b/indra/newview/llpanelprofile.cpp
@@ -1969,7 +1969,8 @@ void LLPanelProfileSecondLife::onShowTexturePicker()
                 PERM_NONE,
                 PERM_NONE,
                 FALSE,
-                NULL);
+                NULL,
+                PICK_TEXTURE);
 
             mFloaterTexturePickerHandle = texture_floaterp->getHandle();
 
@@ -2304,7 +2305,8 @@ void LLPanelProfileFirstLife::onChangePhoto()
                 PERM_NONE,
                 PERM_NONE,
                 FALSE,
-                NULL);
+                NULL,
+                PICK_TEXTURE);
 
             mFloaterTexturePickerHandle = texture_floaterp->getHandle();
 
diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp
index a887f9aa9e45b89d7709d8b884395768d7606c88..b50c0f60bdf0091cba35bc76a264f64f95c27aaf 100644
--- a/indra/newview/llselectmgr.cpp
+++ b/indra/newview/llselectmgr.cpp
@@ -1879,7 +1879,8 @@ bool LLSelectMgr::selectionSetImage(const LLUUID& imageid)
                                                       te,
                                                       mItem,
                                                       LLToolDragAndDrop::SOURCE_AGENT,
-                                                      LLUUID::null);
+                                                      LLUUID::null,
+                                                      false);
 			}
 			else // not an inventory item
 			{
@@ -1959,26 +1960,30 @@ bool LLSelectMgr::selectionSetGLTFMaterial(const LLUUID& mat_id)
             {
                 return false;
             }
-            if (mItem && objectp->isAttachment())
+            LLUUID asset_id = mMatId;
+            if (mItem)
             {
                 const LLPermissions& perm = mItem->getPermissions();
-                BOOL unrestricted = ((perm.getMaskBase() & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED) ? TRUE : FALSE;
-                if (!unrestricted)
+                bool from_library = perm.getOwner() == ALEXANDRIA_LINDEN_ID;
+                if (objectp->isAttachment())
                 {
-                    // Attachments are in world and in inventory simultaneously,
-                    // at the moment server doesn't support such a situation.
-                    return false;
+                    bool unrestricted = (perm.getMaskBase() & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED;
+
+                    if (!unrestricted && !from_library)
+                    {
+                        // Attachments are in world and in inventory simultaneously,
+                        // at the moment server doesn't support such a situation.
+                        return false;
+                    }
                 }
-            }
-            LLUUID asset_id = mMatId;
-            if (mItem)
-            {
-                // If success, the material may be copied into the object's inventory
-                BOOL success = LLToolDragAndDrop::handleDropMaterialProtections(objectp, mItem, LLToolDragAndDrop::SOURCE_AGENT, LLUUID::null);
-                if (!success)
+
+                if (!from_library
+                    // Check if item may be copied into the object's inventory
+                    && !LLToolDragAndDrop::handleDropMaterialProtections(objectp, mItem, LLToolDragAndDrop::SOURCE_AGENT, LLUUID::null))
                 {
                     return false;
                 }
+
                 asset_id = mItem->getAssetUUID();
                 if (asset_id.isNull())
                 {
@@ -1994,11 +1999,13 @@ bool LLSelectMgr::selectionSetGLTFMaterial(const LLUUID& mat_id)
     };
 
     bool success = true;
-    if (item &&
-            (!item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID()) ||
+    if (item
+        &&  (!item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID()) ||
              !item->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID()) ||
              !item->getPermissions().allowOperationBy(PERM_MODIFY, gAgent.getID())
-            ))
+            )
+        && item->getPermissions().getOwner() != ALEXANDRIA_LINDEN_ID
+        )
     {
         success = success && getSelection()->applyRestrictedPbrMaterialToTEs(item);
     }
diff --git a/indra/newview/llsettingsvo.cpp b/indra/newview/llsettingsvo.cpp
index 7009fb98ab6421e3503d646cedc84e50947fae5a..c07c939862e442878a5ce8075c092921deb8e46a 100644
--- a/indra/newview/llsettingsvo.cpp
+++ b/indra/newview/llsettingsvo.cpp
@@ -739,7 +739,6 @@ void LLSettingsVOSky::applySpecial(void *ptarget, bool force)
     static LLCachedControl<F32> auto_adjust_blue_horizon_scale(gSavedSettings, "RenderSkyAutoAdjustBlueHorizonScale", 1.f);
     static LLCachedControl<F32> auto_adjust_blue_density_scale(gSavedSettings, "RenderSkyAutoAdjustBlueDensityScale", 1.f);
     static LLCachedControl<F32> auto_adjust_sun_color_scale(gSavedSettings, "RenderSkyAutoAdjustSunColorScale", 1.f);
-    static LLCachedControl<F32> auto_adjust_probe_ambiance(gSavedSettings, "RenderSkyAutoAdjustProbeAmbiance", 1.f);
     static LLCachedControl<F32> sunlight_scale(gSavedSettings, "RenderSkySunlightScale", 1.5f);
     static LLCachedControl<F32> ambient_scale(gSavedSettings, "RenderSkyAmbientScale", 1.5f);
 
@@ -772,8 +771,7 @@ void LLSettingsVOSky::applySpecial(void *ptarget, bool force)
             shader->uniform3fv(LLShaderMgr::BLUE_DENSITY, blue_density.mV);
             shader->uniform3fv(LLShaderMgr::BLUE_HORIZON, blue_horizon.mV);
 
-            LLSettingsSky::sAutoAdjustProbeAmbiance = auto_adjust_probe_ambiance;
-            probe_ambiance = auto_adjust_probe_ambiance;  // NOTE -- must match LLSettingsSky::getReflectionProbeAmbiance value for "auto_adjust" true
+            probe_ambiance = sAutoAdjustProbeAmbiance;
         }
         else
         {
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 9161926f5288edb18fd61346119ebea80442f36c..a0324ca82aafa43a061d83a6280a74173228cd7d 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -1511,9 +1511,6 @@ bool idle_startup()
 		gXferManager->registerCallbacks(gMessageSystem);
 		display_startup();
 
-		LLGLTFMaterialList::registerCallbacks();
-		display_startup();
-
 		LLStartUp::initNameCache();
 		display_startup();
 
diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp
index 28e01c6c219234a8cd753bfbcef95fe9b95e57e1..62d3fa28bf13237a4ea35f7a5f536d97c343a461 100644
--- a/indra/newview/lltexturectrl.cpp
+++ b/indra/newview/lltexturectrl.cpp
@@ -82,9 +82,11 @@
 //static
 bool get_is_predefined_texture(LLUUID asset_id)
 {
-    if (asset_id == LLUUID(gSavedSettings.getString("DefaultObjectTexture"))
-        || asset_id == LLUUID(gSavedSettings.getString("UIImgWhiteUUID"))
-        || asset_id == LLUUID(gSavedSettings.getString("UIImgInvisibleUUID"))
+    if (asset_id == DEFAULT_OBJECT_TEXTURE
+        || asset_id == DEFAULT_OBJECT_SPECULAR
+        || asset_id == DEFAULT_OBJECT_NORMAL
+        || asset_id == BLANK_OBJECT_NORMAL
+        || asset_id == IMG_WHITE
         || asset_id == LLUUID(SCULPT_DEFAULT_TEXTURE))
     {
         return true;
@@ -151,7 +153,8 @@ LLFloaterTexturePicker::LLFloaterTexturePicker(
 	PermissionMask immediate_filter_perm_mask,
 	PermissionMask dnd_filter_perm_mask,
 	BOOL can_apply_immediately,
-	LLUIImagePtr fallback_image)
+	LLUIImagePtr fallback_image,
+    EPickInventoryType pick_type)
 :	LLFloater(LLSD()),
 	mOwner( owner ),
 	mImageAssetID( image_asset_id ),
@@ -181,7 +184,7 @@ LLFloaterTexturePicker::LLFloaterTexturePicker(
 	mSetImageAssetIDCallback(NULL),
 	mOnUpdateImageStatsCallback(NULL),
 	mBakeTextureEnabled(FALSE),
-    mInventoryPickType(LLTextureCtrl::PICK_TEXTURE)
+    mInventoryPickType(pick_type)
 {
 	mCanApplyImmediately = can_apply_immediately;
 	buildFromFile("floater_texture_ctrl.xml");
@@ -225,7 +228,7 @@ void LLFloaterTexturePicker::setImageID(const LLUUID& image_id, bool set_selecti
 
                 LLInventoryItem* itemp = gInventory.getItem(inv_view->getUUID());
 
-                if (mInventoryPickType == LLTextureCtrl::PICK_MATERIAL
+                if (mInventoryPickType == PICK_MATERIAL
                     && mImageAssetID == LLGLTFMaterialList::BLANK_MATERIAL_ASSET_ID
                     && itemp && itemp->getAssetUUID().isNull())
                 {
@@ -266,7 +269,7 @@ void LLFloaterTexturePicker::setImageID(const LLUUID& image_id, bool set_selecti
 void LLFloaterTexturePicker::setImageIDFromItem(const LLInventoryItem* itemp, bool set_selection)
 {
     LLUUID asset_id = itemp->getAssetUUID();
-    if (mInventoryPickType == LLTextureCtrl::PICK_MATERIAL && asset_id.isNull())
+    if (mInventoryPickType == PICK_MATERIAL && asset_id.isNull())
     {
         // If an inventory item has a null asset, consider it a valid blank material(gltf)
         asset_id = LLGLTFMaterialList::BLANK_MATERIAL_ASSET_ID;
@@ -425,11 +428,11 @@ BOOL LLFloaterTexturePicker::handleDragAndDrop(
     bool is_material = cargo_type == DAD_MATERIAL;
 
     bool allow_dnd = false;
-    if (mInventoryPickType == LLTextureCtrl::PICK_MATERIAL)
+    if (mInventoryPickType == PICK_MATERIAL)
     {
         allow_dnd = is_material;
     }
-    else if (mInventoryPickType == LLTextureCtrl::PICK_TEXTURE)
+    else if (mInventoryPickType == PICK_TEXTURE)
     {
         allow_dnd = is_texture || is_mesh;
     }
@@ -602,9 +605,7 @@ BOOL LLFloaterTexturePicker::postBuild()
 		// don't put keyboard focus on selected item, because the selection callback
 		// will assume that this was user input
 
-		
-
-		if(!mImageAssetID.isNull())
+		if(!mImageAssetID.isNull() || mInventoryPickType == PICK_MATERIAL)
 		{
 			mInventoryPanel->setSelection(findItemID(mImageAssetID, FALSE), TAKE_FOCUS_NO);
 		}
@@ -661,7 +662,7 @@ void LLFloaterTexturePicker::draw()
         mGLTFMaterial = NULL;
         if (mImageAssetID.notNull())
         {
-            if (mInventoryPickType == LLTextureCtrl::PICK_MATERIAL)
+            if (mInventoryPickType == PICK_MATERIAL)
             {
                 mGLTFMaterial = (LLFetchedGLTFMaterial*) gGLTFMaterialList.getMaterial(mImageAssetID);
                 llassert(mGLTFMaterial == nullptr || dynamic_cast<LLFetchedGLTFMaterial*>(gGLTFMaterialList.getMaterial(mImageAssetID)) != nullptr);
@@ -786,27 +787,43 @@ void LLFloaterTexturePicker::draw()
 
 const LLUUID& LLFloaterTexturePicker::findItemID(const LLUUID& asset_id, BOOL copyable_only, BOOL ignore_library)
 {
-    LLUUID loockup_id = asset_id;
-	if (loockup_id.isNull())
+	if (asset_id.isNull())
 	{
-        if (mInventoryPickType == LLTextureCtrl::PICK_MATERIAL)
-        {
-            loockup_id = LLGLTFMaterialList::BLANK_MATERIAL_ASSET_ID;
-        }
-        else
-        {
-            return LLUUID::null;
-        }
+        // null asset id means, no material or texture assigned
+        return LLUUID::null;
 	}
 
+    LLUUID loockup_id = asset_id;
+    if (mInventoryPickType == PICK_MATERIAL && loockup_id == LLGLTFMaterialList::BLANK_MATERIAL_ASSET_ID)
+    {
+        // default asset id means we are looking for an inventory item with a default asset UUID (null)
+        loockup_id = LLUUID::null;
+    }
+
 	LLViewerInventoryCategory::cat_array_t cats;
 	LLViewerInventoryItem::item_array_t items;
-	LLAssetIDMatches asset_id_matches(loockup_id);
-	gInventory.collectDescendentsIf(LLUUID::null,
-							cats,
-							items,
-							LLInventoryModel::INCLUDE_TRASH,
-							asset_id_matches);
+
+    if (loockup_id.isNull())
+    {
+        // looking for a material with a null id, null id is shared by a lot
+        // of objects as a default value, so have to filter by type as well
+        LLAssetIDAndTypeMatches matches(loockup_id, LLAssetType::AT_MATERIAL);
+        gInventory.collectDescendentsIf(LLUUID::null,
+                                        cats,
+                                        items,
+                                        LLInventoryModel::INCLUDE_TRASH,
+                                        matches);
+    }
+    else
+    {
+        LLAssetIDMatches asset_id_matches(loockup_id);
+        gInventory.collectDescendentsIf(LLUUID::null,
+                                        cats,
+                                        items,
+                                        LLInventoryModel::INCLUDE_TRASH,
+                                        asset_id_matches);
+    }
+
 
 	if (items.size())
 	{
@@ -871,7 +888,7 @@ void LLFloaterTexturePicker::commitCallback(LLTextureCtrl::ETexturePickOp op)
 
                     LLInventoryItem* itemp = gInventory.getItem(inv_view->getUUID());
 
-                    if (mInventoryPickType == LLTextureCtrl::PICK_MATERIAL
+                    if (mInventoryPickType == PICK_MATERIAL
                         && mImageAssetID == LLGLTFMaterialList::BLANK_MATERIAL_ASSET_ID
                         && itemp && itemp->getAssetUUID().isNull())
                     {
@@ -1064,15 +1081,15 @@ void LLFloaterTexturePicker::onBtnAdd(void* userdata)
 {
     LLFloaterTexturePicker* self = (LLFloaterTexturePicker*)userdata;
 
-    if (self->mInventoryPickType == LLTextureCtrl::PICK_TEXTURE_MATERIAL)
+    if (self->mInventoryPickType == PICK_TEXTURE_MATERIAL)
     {
         LLFilePickerReplyThread::startPicker(boost::bind(&onPickerCallback, _1, self->getHandle()), LLFilePicker::FFLOAD_MATERIAL_TEXTURE, true);
     }
-    else if (self->mInventoryPickType == LLTextureCtrl::PICK_TEXTURE)
+    else if (self->mInventoryPickType == PICK_TEXTURE)
     {
         LLFilePickerReplyThread::startPicker(boost::bind(&onPickerCallback, _1, self->getHandle()), LLFilePicker::FFLOAD_IMAGE, true);
     }
-    else if (self->mInventoryPickType == LLTextureCtrl::PICK_MATERIAL)
+    else if (self->mInventoryPickType == PICK_MATERIAL)
     {
         LLFilePickerReplyThread::startPicker(boost::bind(&onPickerCallback, _1, self->getHandle()), LLFilePicker::FFLOAD_MATERIAL, true);
     }
@@ -1351,7 +1368,7 @@ void LLFloaterTexturePicker::changeMode()
     getChild<LLCheckBoxCtrl>("hide_base_mesh_region")->setVisible(FALSE);// index == 2 ? TRUE : FALSE);
 
     bool pipette_visible = (index == PICKER_INVENTORY)
-        && (mInventoryPickType != LLTextureCtrl::PICK_MATERIAL);
+        && (mInventoryPickType != PICK_MATERIAL);
     mPipetteBtn->setVisible(pipette_visible);
 
     if (index == PICKER_BAKE)
@@ -1414,16 +1431,16 @@ void LLFloaterTexturePicker::refreshLocalList()
 {
     mLocalScrollCtrl->clearRows();
 
-    if (mInventoryPickType == LLTextureCtrl::PICK_TEXTURE_MATERIAL)
+    if (mInventoryPickType == PICK_TEXTURE_MATERIAL)
     {
         LLLocalBitmapMgr::getInstance()->feedScrollList(mLocalScrollCtrl);
         LLLocalGLTFMaterialMgr::getInstance()->feedScrollList(mLocalScrollCtrl);
     }
-    else if (mInventoryPickType == LLTextureCtrl::PICK_TEXTURE)
+    else if (mInventoryPickType == PICK_TEXTURE)
     {
         LLLocalBitmapMgr::getInstance()->feedScrollList(mLocalScrollCtrl);
     }
-    else if (mInventoryPickType == LLTextureCtrl::PICK_MATERIAL)
+    else if (mInventoryPickType == PICK_MATERIAL)
     {
         LLLocalGLTFMaterialMgr::getInstance()->feedScrollList(mLocalScrollCtrl);
     }
@@ -1433,18 +1450,18 @@ void LLFloaterTexturePicker::refreshInventoryFilter()
 {
     U32 filter_types = 0x0;
 
-    if (mInventoryPickType == LLTextureCtrl::PICK_TEXTURE_MATERIAL)
+    if (mInventoryPickType == PICK_TEXTURE_MATERIAL)
     {
         filter_types |= 0x1 << LLInventoryType::IT_TEXTURE;
         filter_types |= 0x1 << LLInventoryType::IT_SNAPSHOT;
         filter_types |= 0x1 << LLInventoryType::IT_MATERIAL;
     }
-    else if (mInventoryPickType == LLTextureCtrl::PICK_TEXTURE)
+    else if (mInventoryPickType == PICK_TEXTURE)
     {
         filter_types |= 0x1 << LLInventoryType::IT_TEXTURE;
         filter_types |= 0x1 << LLInventoryType::IT_SNAPSHOT;
     }
-    else if (mInventoryPickType == LLTextureCtrl::PICK_MATERIAL)
+    else if (mInventoryPickType == PICK_MATERIAL)
     {
         filter_types |= 0x1 << LLInventoryType::IT_MATERIAL;
     }
@@ -1479,13 +1496,13 @@ void LLFloaterTexturePicker::setBakeTextureEnabled(BOOL enabled)
 	onModeSelect(0, this);
 }
 
-void LLFloaterTexturePicker::setInventoryPickType(LLTextureCtrl::EPickInventoryType type)
+void LLFloaterTexturePicker::setInventoryPickType(EPickInventoryType type)
 {
     mInventoryPickType = type;
     refreshLocalList();
     refreshInventoryFilter();
 
-    if (mInventoryPickType == LLTextureCtrl::PICK_MATERIAL)
+    if (mInventoryPickType == PICK_MATERIAL)
     {
         getChild<LLButton>("Pipette")->setVisible(false);
     }
@@ -1501,7 +1518,7 @@ void LLFloaterTexturePicker::setInventoryPickType(LLTextureCtrl::EPickInventoryT
 
         setTitle(pick + mLabel);
     }
-    else if(mInventoryPickType == LLTextureCtrl::PICK_MATERIAL)
+    else if(mInventoryPickType == PICK_MATERIAL)
     {
         setTitle(getString("pick_material"));
     }
@@ -1509,6 +1526,12 @@ void LLFloaterTexturePicker::setInventoryPickType(LLTextureCtrl::EPickInventoryT
     {
         setTitle(getString("pick_texture"));
     }
+
+    // refresh selection
+    if (!mImageAssetID.isNull() || mInventoryPickType == PICK_MATERIAL)
+    {
+        mInventoryPanel->setSelection(findItemID(mImageAssetID, FALSE), TAKE_FOCUS_NO);
+    }
 }
 
 void LLFloaterTexturePicker::setImmediateFilterPermMask(PermissionMask mask)
@@ -1543,16 +1566,16 @@ void LLFloaterTexturePicker::onPickerCallback(const std::vector<std::string>& fi
         LLFloaterTexturePicker* self = (LLFloaterTexturePicker*)handle.get();
         self->mLocalScrollCtrl->clearRows();
 
-        if (self->mInventoryPickType == LLTextureCtrl::PICK_TEXTURE_MATERIAL)
+        if (self->mInventoryPickType == PICK_TEXTURE_MATERIAL)
         {
             LLLocalBitmapMgr::getInstance()->feedScrollList(self->mLocalScrollCtrl);
             LLLocalGLTFMaterialMgr::getInstance()->feedScrollList(self->mLocalScrollCtrl);
         }
-        else if (self->mInventoryPickType == LLTextureCtrl::PICK_TEXTURE)
+        else if (self->mInventoryPickType == PICK_TEXTURE)
         {
             LLLocalBitmapMgr::getInstance()->feedScrollList(self->mLocalScrollCtrl);
         }
-        else if (self->mInventoryPickType == LLTextureCtrl::PICK_MATERIAL)
+        else if (self->mInventoryPickType == PICK_MATERIAL)
         {
             LLLocalGLTFMaterialMgr::getInstance()->feedScrollList(self->mLocalScrollCtrl);
         }
@@ -1565,7 +1588,7 @@ void LLFloaterTexturePicker::onTextureSelect( const LLTextureEntry& te )
 	if (inventory_item_id.notNull())
 	{
 		LLToolPipette::getInstance()->setResult(TRUE, "");
-        if (mInventoryPickType == LLTextureCtrl::PICK_MATERIAL)
+        if (mInventoryPickType == PICK_MATERIAL)
         {
             // tes have no data about material ids
             // Plus gltf materials are layered with overrides,
@@ -1625,8 +1648,7 @@ LLTextureCtrl::LLTextureCtrl(const LLTextureCtrl::Params& p)
 
 	// Default of defaults is white image for diff tex
 	//
-	LLUUID whiteImage( gSavedSettings.getString( "UIImgWhiteUUID" ) );
-	setBlankImageAssetID( whiteImage );
+	setBlankImageAssetID(IMG_WHITE);
 
 	setAllowNoTexture(p.allow_no_texture);
 	setCanApplyImmediately(p.can_apply_immediately);
@@ -1807,7 +1829,8 @@ void LLTextureCtrl::showPicker(BOOL take_focus)
 			mImmediateFilterPermMask,
 			mDnDFilterPermMask,
 			mCanApplyImmediately,
-			mFallbackImage);
+			mFallbackImage,
+			mInventoryPickType);
 		mFloaterHandle = floaterp->getHandle();
 
 		LLFloaterTexturePicker* texture_floaterp = dynamic_cast<LLFloaterTexturePicker*>(floaterp);
@@ -1828,7 +1851,6 @@ void LLTextureCtrl::showPicker(BOOL take_focus)
 			texture_floaterp->setSetImageAssetIDCallback(boost::bind(&LLTextureCtrl::setImageAssetID, this, _1));
 
 			texture_floaterp->setBakeTextureEnabled(mBakeTextureEnabled);
-            texture_floaterp->setInventoryPickType(mInventoryPickType);
 		}
 
 		LLFloater* root_floater = gFloaterView->getParentFloater(this);
@@ -1891,7 +1913,7 @@ BOOL LLTextureCtrl::handleMouseDown(S32 x, S32 y, MASK mask)
 		if (!mOpenTexPreview)
 		{
 			showPicker(FALSE);
-            if (mInventoryPickType == LLTextureCtrl::PICK_MATERIAL)
+            if (mInventoryPickType == PICK_MATERIAL)
             {
                 //grab materials first...
                 LLInventoryModelBackgroundFetch::instance().start(gInventory.findCategoryUUIDForType(LLFolderType::FT_MATERIAL));
@@ -2089,11 +2111,11 @@ BOOL LLTextureCtrl::handleDragAndDrop(S32 x, S32 y, MASK mask,
     bool is_material = cargo_type == DAD_MATERIAL;
 
     bool allow_dnd = false;
-    if (mInventoryPickType == LLTextureCtrl::PICK_MATERIAL)
+    if (mInventoryPickType == PICK_MATERIAL)
     {
         allow_dnd = is_material;
     }
-    else if (mInventoryPickType == LLTextureCtrl::PICK_TEXTURE)
+    else if (mInventoryPickType == PICK_TEXTURE)
     {
         allow_dnd = is_texture || is_mesh;
     }
@@ -2156,7 +2178,7 @@ void LLTextureCtrl::draw()
 
 		if (texture.isNull())
 		{
-            if (mInventoryPickType == LLTextureCtrl::PICK_MATERIAL)
+            if (mInventoryPickType == PICK_MATERIAL)
             {
                 LLPointer<LLFetchedGLTFMaterial> material = gGLTFMaterialList.getMaterial(mImageAssetID);
                 if (material)
@@ -2313,7 +2335,7 @@ BOOL LLTextureCtrl::doDrop(LLInventoryItem* item)
     // no callback installed, so just set the image ids and carry on.
     LLUUID asset_id = item->getAssetUUID();
 
-    if (mInventoryPickType == LLTextureCtrl::PICK_MATERIAL && asset_id.isNull())
+    if (mInventoryPickType == PICK_MATERIAL && asset_id.isNull())
     {
         // If an inventory material has a null asset, consider it a valid blank material(gltf)
         asset_id = LLGLTFMaterialList::BLANK_MATERIAL_ASSET_ID;
diff --git a/indra/newview/lltexturectrl.h b/indra/newview/lltexturectrl.h
index 7a96eea60dccf2d69ba324756fedc21de6f3380e..cb6ce636e0be37c70ccdd0e071bf2305c97b1b70 100644
--- a/indra/newview/lltexturectrl.h
+++ b/indra/newview/lltexturectrl.h
@@ -72,6 +72,13 @@ enum LLPickerSource
     PICKER_UNKNOWN, // on cancel, default ids
 };
 
+typedef enum e_pick_inventory_type
+{
+    PICK_TEXTURE_MATERIAL = 0,
+    PICK_TEXTURE = 1,
+    PICK_MATERIAL = 2,
+} EPickInventoryType;
+
 //////////////////////////////////////////////////////////////////////////////////////////
 // LLTextureCtrl
 
@@ -87,13 +94,6 @@ class LLTextureCtrl
 		TEXTURE_CANCEL
 	} ETexturePickOp;
 
-    typedef enum e_pick_inventory_type
-    {
-        PICK_TEXTURE_MATERIAL = 0,
-        PICK_TEXTURE = 1,
-        PICK_MATERIAL = 2,
-    } EPickInventoryType;
-
 public:
 	struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>
 	{
@@ -276,7 +276,7 @@ class LLTextureCtrl
 	S32						 	mLabelWidth;
 	bool						mOpenTexPreview;
 	bool						mBakeTextureEnabled;
-    LLTextureCtrl::EPickInventoryType mInventoryPickType;
+    EPickInventoryType mInventoryPickType;
 };
 
 //////////////////////////////////////////////////////////////////////////////////////////
@@ -300,8 +300,8 @@ class LLFloaterTexturePicker : public LLFloater
 		PermissionMask immediate_filter_perm_mask,
 		PermissionMask dnd_filter_perm_mask,
 		BOOL can_apply_immediately,
-		LLUIImagePtr fallback_image_name
-		);
+		LLUIImagePtr fallback_image_name,
+		EPickInventoryType pick_type);
 
 	virtual ~LLFloaterTexturePicker();
 
@@ -369,7 +369,7 @@ class LLFloaterTexturePicker : public LLFloater
 	void 			setLocalTextureEnabled(BOOL enabled);
 	void 			setBakeTextureEnabled(BOOL enabled);
 
-    void setInventoryPickType(LLTextureCtrl::EPickInventoryType type);
+    void setInventoryPickType(EPickInventoryType type);
     void setImmediateFilterPermMask(PermissionMask mask);
 
     static void		onPickerCallback(const std::vector<std::string>& filenames, LLHandle<LLFloater> handle);
@@ -428,7 +428,7 @@ class LLFloaterTexturePicker : public LLFloater
     bool mLimitsSet;
     S32 mMaxDim;
     S32 mMinDim;
-    LLTextureCtrl::EPickInventoryType mInventoryPickType;
+    EPickInventoryType mInventoryPickType;
 
 
 	texture_selected_callback mTextureSelectedCallback;
diff --git a/indra/newview/lltinygltfhelper.cpp b/indra/newview/lltinygltfhelper.cpp
index 999be07dbafa4d261f5578db18e762361cb84b02..5b75db37d0814676b393129849f2af4cfd91c256 100644
--- a/indra/newview/lltinygltfhelper.cpp
+++ b/indra/newview/lltinygltfhelper.cpp
@@ -178,6 +178,7 @@ LLImageRaw * LLTinyGLTFHelper::getTexture(const std::string & folder, const tiny
     {
         rawImage = new LLImageRaw(&image->image[0], image->width, image->height, image->component);
         rawImage->verticalFlip();
+        rawImage->optimizeAwayAlpha();
     }
 
     return rawImage;
diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp
index e7f96239fdcc34aa181b558e9e9714fa917d4101..bfa9386cd4db7e41ea95e177daffe5acbf70ff76 100644
--- a/indra/newview/lltooldraganddrop.cpp
+++ b/indra/newview/lltooldraganddrop.cpp
@@ -1071,10 +1071,64 @@ BOOL LLToolDragAndDrop::handleDropMaterialProtections(LLViewerObject* hit_obj,
 	return TRUE;
 }
 
+void set_texture_to_material(LLViewerObject* hit_obj,
+                             S32 hit_face,
+                             const LLUUID& asset_id,
+                             LLGLTFMaterial::TextureInfo drop_channel)
+{
+    LLTextureEntry* te = hit_obj->getTE(hit_face);
+    if (te)
+    {
+        LLPointer<LLGLTFMaterial> material = te->getGLTFMaterialOverride();
+
+        // make a copy to not invalidate existing
+        // material for multiple objects
+        if (material.isNull())
+        {
+            // Start with a material override which does not make any changes
+            material = new LLGLTFMaterial();
+        }
+        else
+        {
+            material = new LLGLTFMaterial(*material);
+        }
+
+        switch (drop_channel)
+        {
+            case LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR:
+            default:
+                {
+                    material->setBaseColorId(asset_id);
+                }
+                break;
+
+            case LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS:
+                {
+                    material->setOcclusionRoughnessMetallicId(asset_id);
+                }
+                break;
+
+            case LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE:
+                {
+                    material->setEmissiveId(asset_id);
+                }
+                break;
+
+            case LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL:
+                {
+                    material->setNormalId(asset_id);
+                }
+                break;
+        }
+        LLGLTFMaterialList::queueModify(hit_obj, hit_face, material);
+    }
+}
+
 void LLToolDragAndDrop::dropTextureAllFaces(LLViewerObject* hit_obj,
 											LLInventoryItem* item,
 											LLToolDragAndDrop::ESource source,
-											const LLUUID& src_id)
+											const LLUUID& src_id,
+                                            bool remove_pbr)
 {
 	if (!item)
 	{
@@ -1091,28 +1145,46 @@ void LLToolDragAndDrop::dropTextureAllFaces(LLViewerObject* hit_obj,
             break;
         }
     }
-    if (!has_non_pbr_faces)
+
+    if (has_non_pbr_faces || remove_pbr)
     {
-        return;
+        BOOL res = handleDropMaterialProtections(hit_obj, item, source, src_id);
+        if (!res)
+        {
+            return;
+        }
     }
 	LLUUID asset_id = item->getAssetUUID();
-	BOOL success = handleDropMaterialProtections(hit_obj, item, source, src_id);
-	if (!success)
-	{
-		return;
-	}
+
+    // Overrides require textures to be copy and transfer free
+    LLPermissions item_permissions = item->getPermissions();
+    bool allow_adding_to_override = item_permissions.allowOperationBy(PERM_COPY, gAgent.getID());
+    allow_adding_to_override &= item_permissions.allowOperationBy(PERM_TRANSFER, gAgent.getID());
+
 	LLViewerTexture* image = LLViewerTextureManager::getFetchedTexture(asset_id);
 	add(LLStatViewer::EDIT_TEXTURE, 1);
 	for( S32 face = 0; face < num_faces; face++ )
 	{
-        if (hit_obj->getRenderMaterialID(face).isNull())
+        if (remove_pbr)
+        {
+            hit_obj->setRenderMaterialID(face, LLUUID::null);
+            hit_obj->setTEImage(face, image);
+            dialog_refresh_all();
+        }
+        else if (hit_obj->getRenderMaterialID(face).isNull())
         {
-            // update viewer side image in anticipation of update from simulator
+            // update viewer side
             hit_obj->setTEImage(face, image);
             dialog_refresh_all();
         }
+        else if (allow_adding_to_override)
+        {
+            set_texture_to_material(hit_obj, face, asset_id, LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR);
+        }
 	}
+
 	// send the update to the simulator
+    LLGLTFMaterialList::flushUpdates(nullptr);
 	hit_obj->sendTEUpdate();
 }
 
@@ -1260,21 +1332,13 @@ void LLToolDragAndDrop::dropMesh(LLViewerObject* hit_obj,
 	dialog_refresh_all();
 }
 
-/*
-void LLToolDragAndDrop::dropTextureOneFaceAvatar(LLVOAvatar* avatar, S32 hit_face, LLInventoryItem* item)
-{
-	if (hit_face == -1) return;
-	LLViewerTexture* image = LLViewerTextureManager::getFetchedTexture(item->getAssetUUID());
-	
-	avatar->userSetOptionalTE( hit_face, image);
-}
-*/
 void LLToolDragAndDrop::dropTexture(LLViewerObject* hit_obj,
                                     S32 hit_face,
                                     LLInventoryItem* item,
                                     ESource source,
                                     const LLUUID& src_id,
                                     bool all_faces,
+                                    bool remove_pbr,
                                     S32 tex_channel)
 {
     LLSelectNode* nodep = nullptr;
@@ -1286,13 +1350,15 @@ void LLToolDragAndDrop::dropTexture(LLViewerObject* hit_obj,
 
     if (all_faces)
     {
-        dropTextureAllFaces(hit_obj, item, source, src_id);
+        dropTextureAllFaces(hit_obj, item, source, src_id, remove_pbr);
 
         // If user dropped a texture onto face it implies
         // applying texture now without cancel, save to selection
         if (nodep)
         {
             uuid_vec_t texture_ids;
+            uuid_vec_t material_ids;
+            gltf_materials_vec_t override_materials;
             S32 num_faces = hit_obj->getNumTEs();
             for (S32 face = 0; face < num_faces; face++)
             {
@@ -1305,13 +1371,35 @@ void LLToolDragAndDrop::dropTexture(LLViewerObject* hit_obj,
                 {
                     texture_ids.push_back(LLUUID::null);
                 }
+
+                // either removed or modified materials
+                if (remove_pbr)
+                {
+                    material_ids.push_back(LLUUID::null);
+                }
+                else
+                {
+                    material_ids.push_back(hit_obj->getRenderMaterialID(face));
+                }
+
+                LLTextureEntry* te = hit_obj->getTE(hit_face);
+                if (te && !remove_pbr)
+                {
+                    override_materials.push_back(te->getGLTFMaterialOverride());
+                }
+                else
+                {
+                    override_materials.push_back(nullptr);
+                }
             }
+
             nodep->saveTextures(texture_ids);
+            nodep->saveGLTFMaterials(material_ids, override_materials);
         }
     }
     else
     {
-        dropTextureOneFace(hit_obj, hit_face, item, source, src_id);
+        dropTextureOneFace(hit_obj, hit_face, item, source, src_id, remove_pbr, tex_channel);
 
         // If user dropped a texture onto face it implies
         // applying texture now without cancel, save to selection
@@ -1331,6 +1419,16 @@ void LLToolDragAndDrop::dropTexture(LLViewerObject* hit_obj,
             {
                 nodep->mSavedTextures[hit_face] = LLUUID::null;
             }
+
+            LLTextureEntry* te = hit_obj->getTE(hit_face);
+            if (te && !remove_pbr)
+            {
+                nodep->mSavedGLTFOverrideMaterials[hit_face] = te->getGLTFMaterialOverride();
+            }
+            else
+            {
+                nodep->mSavedGLTFOverrideMaterials[hit_face] = nullptr;
+            }
         }
     }
 }
@@ -1340,6 +1438,7 @@ void LLToolDragAndDrop::dropTextureOneFace(LLViewerObject* hit_obj,
 										   LLInventoryItem* item,
 										   LLToolDragAndDrop::ESource source,
 										   const LLUUID& src_id,
+                                           bool remove_pbr,
                                            S32 tex_channel)
 {
 	if (hit_face == -1) return;
@@ -1348,21 +1447,44 @@ void LLToolDragAndDrop::dropTextureOneFace(LLViewerObject* hit_obj,
 		LL_WARNS() << "LLToolDragAndDrop::dropTextureOneFace no texture item." << LL_ENDL;
 		return;
 	}
-    if (hit_obj->getRenderMaterialID(hit_face).notNull())
+
+    LLUUID asset_id = item->getAssetUUID();
+
+    if (hit_obj->getRenderMaterialID(hit_face).notNull() && !remove_pbr)
     {
+        // Overrides require textures to be copy and transfer free
+        LLPermissions item_permissions = item->getPermissions();
+        bool allow_adding_to_override = item_permissions.allowOperationBy(PERM_COPY, gAgent.getID());
+        allow_adding_to_override &= item_permissions.allowOperationBy(PERM_TRANSFER, gAgent.getID());
+
+        if (allow_adding_to_override)
+        {
+            LLGLTFMaterial::TextureInfo drop_channel = LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR;
+            LLPanelFace* panel_face = gFloaterTools->getPanelFace();
+            if (gFloaterTools->getVisible() && panel_face)
+            {
+                drop_channel = panel_face->getPBRDropChannel();
+            }
+            set_texture_to_material(hit_obj, hit_face, asset_id, drop_channel);
+            LLGLTFMaterialList::flushUpdates(nullptr);
+        }
         return;
     }
-	LLUUID asset_id = item->getAssetUUID();
 	BOOL success = handleDropMaterialProtections(hit_obj, item, source, src_id);
 	if (!success)
 	{
 		return;
 	}
+    if (remove_pbr)
+    {
+        hit_obj->setRenderMaterialID(hit_face, LLUUID::null);
+    }
+
 	// update viewer side image in anticipation of update from simulator
 	LLViewerTexture* image = LLViewerTextureManager::getFetchedTexture(asset_id);
 	add(LLStatViewer::EDIT_TEXTURE, 1);
 
-	LLTextureEntry* tep = hit_obj ? (hit_obj->getTE(hit_face)) : NULL;
+	LLTextureEntry* tep = hit_obj->getTE(hit_face);
 
 	LLPanelFace* panel_face = gFloaterTools->getPanelFace();
 
@@ -1380,6 +1502,7 @@ void LLToolDragAndDrop::dropTextureOneFace(LLViewerObject* hit_obj,
 			break;
 
 		case 1:
+            if (tep)
 			{
 				LLMaterialPtr old_mat = tep->getMaterialParams();
 				LLMaterialPtr new_mat = panel_face->createDefaultMaterial(old_mat);
@@ -1391,6 +1514,7 @@ void LLToolDragAndDrop::dropTextureOneFace(LLViewerObject* hit_obj,
 			break;
 
 		case 2:
+            if (tep)
 			{
 				LLMaterialPtr old_mat = tep->getMaterialParams();
 				LLMaterialPtr new_mat = panel_face->createDefaultMaterial(old_mat);
@@ -2200,6 +2324,7 @@ EAcceptance LLToolDragAndDrop::dad3dApplyToObject(
 	LLViewerInventoryCategory* cat;
 	locateInventory(item, cat);
 	if (!item || !item->isFinished()) return ACCEPT_NO;
+    LLPermissions item_permissions = item->getPermissions();
 	EAcceptance rv = willObjectAcceptInventory(obj, item);
 	if((mask & MASK_CONTROL))
 	{
@@ -2214,12 +2339,12 @@ EAcceptance LLToolDragAndDrop::dad3dApplyToObject(
 		return ACCEPT_NO_LOCKED;
 	}
 
-    if (cargo_type == DAD_TEXTURE)
+    if (cargo_type == DAD_TEXTURE && (mask & MASK_ALT) == 0)
     {
+        bool has_non_pbr_faces = false;
         if ((mask & MASK_SHIFT))
         {
             S32 num_faces = obj->getNumTEs();
-            bool has_non_pbr_faces = false;
             for (S32 face = 0; face < num_faces; face++)
             {
                 if (obj->getRenderMaterialID(face).isNull())
@@ -2228,14 +2353,19 @@ EAcceptance LLToolDragAndDrop::dad3dApplyToObject(
                     break;
                 }
             }
-            if (!has_non_pbr_faces)
-            {
-                return ACCEPT_NO;
-            }
         }
-        else if (obj->getRenderMaterialID(face).notNull())
+        else
+        {
+            has_non_pbr_faces = obj->getRenderMaterialID(face).isNull();
+        }
+
+        if (!has_non_pbr_faces)
         {
-            return ACCEPT_NO;
+            // Only pbr faces selected, texture will be added to an override
+            // Overrides require textures to be copy and transfer free
+            bool allow_adding_to_override = item_permissions.allowOperationBy(PERM_COPY, gAgent.getID());
+            allow_adding_to_override &= item_permissions.allowOperationBy(PERM_TRANSFER, gAgent.getID());
+            if (!allow_adding_to_override) return ACCEPT_NO;
         }
     }
 
@@ -2244,15 +2374,16 @@ EAcceptance LLToolDragAndDrop::dad3dApplyToObject(
 		if (cargo_type == DAD_TEXTURE)
 		{
             bool all_faces = mask & MASK_SHIFT;
-            if (item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID()))
+            bool remove_pbr = mask & MASK_ALT;
+            if (item_permissions.allowOperationBy(PERM_COPY, gAgent.getID()))
             {
-                dropTexture(obj, face, item, mSource, mSourceID, all_faces);
+                dropTexture(obj, face, item, mSource, mSourceID, all_faces, remove_pbr);
             }
             else
             {
                 ESource source = mSource;
                 LLUUID source_id = mSourceID;
-                LLNotificationsUtil::add("ApplyInventoryToObject", LLSD(), LLSD(), [obj, face, item, source, source_id, all_faces](const LLSD& notification, const LLSD& response)
+                LLNotificationsUtil::add("ApplyInventoryToObject", LLSD(), LLSD(), [obj, face, item, source, source_id, all_faces, remove_pbr](const LLSD& notification, const LLSD& response)
                                          {
                                              S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
                                              // if Cancel pressed
@@ -2260,7 +2391,7 @@ EAcceptance LLToolDragAndDrop::dad3dApplyToObject(
                                              {
                                                  return;
                                              }
-                                             dropTexture(obj, face, item, source, source_id, all_faces);
+                                             dropTexture(obj, face, item, source, source_id, all_faces, remove_pbr);
                                          });
             }
 		}
@@ -2327,23 +2458,6 @@ EAcceptance LLToolDragAndDrop::dad3dMeshObject(
 	return dad3dApplyToObject(obj, face, mask, drop, DAD_MESH);
 }
 
-
-/*
-EAcceptance LLToolDragAndDrop::dad3dTextureSelf(
-	LLViewerObject* obj, S32 face, MASK mask, BOOL drop)
-{
-	LL_DEBUGS() << "LLToolDragAndDrop::dad3dTextureAvatar()" << LL_ENDL;
-	if(drop)
-	{
-		if( !(mask & MASK_SHIFT) )
-		{
-			dropTextureOneFaceAvatar( (LLVOAvatar*)obj, face, (LLInventoryItem*)mCargoData);
-		}
-	}
-	return (mask & MASK_SHIFT) ? ACCEPT_NO : ACCEPT_YES_SINGLE;
-}
-*/
-
 EAcceptance LLToolDragAndDrop::dad3dWearItem(
 	LLViewerObject* obj, S32 face, MASK mask, BOOL drop)
 {
diff --git a/indra/newview/lltooldraganddrop.h b/indra/newview/lltooldraganddrop.h
index f69774952c4c37034152c2aeb8b44879a0a27c7b..60a2f01107d7f42ba46d68409682a927ff02d6e7 100644
--- a/indra/newview/lltooldraganddrop.h
+++ b/indra/newview/lltooldraganddrop.h
@@ -249,17 +249,20 @@ class LLToolDragAndDrop : public LLTool, public LLSingleton<LLToolDragAndDrop>
                             ESource source,
                             const LLUUID& src_id,
                             bool all_faces,
+                            bool replace_pbr,
                             S32 tex_channel = -1);
 	static void dropTextureOneFace(LLViewerObject* hit_obj,
                                    S32 hit_face,
 								   LLInventoryItem* item,
 								   ESource source,
 								   const LLUUID& src_id,
+                                   bool remove_pbr,
                                    S32 tex_channel = -1);
 	static void dropTextureAllFaces(LLViewerObject* hit_obj,
 									LLInventoryItem* item,
 									ESource source,
-									const LLUUID& src_id);
+									const LLUUID& src_id,
+                                    bool remove_pbr);
     static void dropMaterial(LLViewerObject* hit_obj,
                              S32 hit_face,
                              LLInventoryItem* item,
diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp
index a936012781612b294c5f5aa0c4b6d62ee8ae089e..e1d6f71cce9b32f377146201161b171430dedf0e 100644
--- a/indra/newview/llviewerdisplay.cpp
+++ b/indra/newview/llviewerdisplay.cpp
@@ -730,8 +730,8 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
 			LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("display - 2")
 			if (gResizeScreenTexture)
 			{
-				gResizeScreenTexture = FALSE;
 				gPipeline.resizeScreenTexture();
+                gResizeScreenTexture = FALSE;
 			}
 
 			gGL.setColorMask(true, true);
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 3eb0d7e59d9ea3cffccc17b21fc5dccf73fc0779..94efab3f4ba991b13465fcf2d0b4aa54aff3c2b4 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -289,6 +289,7 @@ void handle_disconnect_viewer(void *);
 
 void force_error_breakpoint(void *);
 void force_error_llerror(void *);
+void force_error_llerror_msg(void*);
 void force_error_bad_memory_access(void *);
 void force_error_infinite_loop(void *);
 void force_error_software_exception(void *);
@@ -2401,6 +2402,15 @@ class LLAdvancedForceErrorLlerror : public view_listener_t
 	}
 };
 
+class LLAdvancedForceErrorLlerrorMsg: public view_listener_t
+{
+    bool handleEvent(const LLSD& userdata)
+    {
+        force_error_llerror_msg(NULL);
+        return true;
+    }
+};
+
 class LLAdvancedForceErrorBadMemoryAccess : public view_listener_t
 {
 	bool handleEvent(const LLSD& userdata)
@@ -8399,6 +8409,11 @@ void force_error_llerror(void *)
     LLAppViewer::instance()->forceErrorLLError();
 }
 
+void force_error_llerror_msg(void*)
+{
+    LLAppViewer::instance()->forceErrorLLErrorMsg();
+}
+
 void force_error_bad_memory_access(void *)
 {
     LLAppViewer::instance()->forceErrorBadMemoryAccess();
@@ -9629,6 +9644,7 @@ void initialize_menus()
 	// Advanced > Debugging
 	view_listener_t::addMenu(new LLAdvancedForceErrorBreakpoint(), "Advanced.ForceErrorBreakpoint");
 	view_listener_t::addMenu(new LLAdvancedForceErrorLlerror(), "Advanced.ForceErrorLlerror");
+    view_listener_t::addMenu(new LLAdvancedForceErrorLlerrorMsg(), "Advanced.ForceErrorLlerrorMsg");
 	view_listener_t::addMenu(new LLAdvancedForceErrorBadMemoryAccess(), "Advanced.ForceErrorBadMemoryAccess");
 	view_listener_t::addMenu(new LLAdvancedForceErrorBadMemoryAccessCoro(), "Advanced.ForceErrorBadMemoryAccessCoro");
 	view_listener_t::addMenu(new LLAdvancedForceErrorInfiniteLoop(), "Advanced.ForceErrorInfiniteLoop");
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index fc055a7303954c75e220cbccdbc62e6fc6c91594..f1fac106c7ba315dd6f6f11549886c76528617d8 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -5051,11 +5051,6 @@ void LLViewerObject::updateTEMaterialTextures(U8 te)
                     LLViewerObject* obj = gObjectList.findObject(id);
                     if (obj)
                     {
-                        LLViewerRegion* region = obj->getRegion();
-                        if(region)
-                        {
-                            region->loadCacheMiscExtras(obj->getLocalID());
-                        }
                         obj->markForUpdate();
                     }
                 });
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index ed5b80900360b6251a29cf77599fffd406588f2a..eba7189a8227e4f7bd6ec9a5da59af53b5752c30 100755
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -1886,8 +1886,6 @@ LLViewerObject* LLViewerRegion::addNewObject(LLVOCacheEntry* entry)
 		addActiveCacheEntry(entry);
 	}
 
-    loadCacheMiscExtras(entry->getLocalID());
-
 	return obj;
 }
 
@@ -3665,15 +3663,6 @@ std::string LLViewerRegion::getSimHostName()
 	return std::string("...");
 }
 
-void LLViewerRegion::loadCacheMiscExtras(U32 local_id)
-{
-    auto iter = mImpl->mGLTFOverridesLLSD.find(local_id);
-    if (iter != mImpl->mGLTFOverridesLLSD.end())
-    {
-        LLGLTFMaterialList::loadCacheOverrides(iter->second);
-    }
-}
-
 void LLViewerRegion::applyCacheMiscExtras(LLViewerObject* obj)
 {
     LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h
index a409d837a4da352c566e17eeacc2f2de4b4a6394..622490c88199cdc472623c248386bb7c3684b872 100644
--- a/indra/newview/llviewerregion.h
+++ b/indra/newview/llviewerregion.h
@@ -435,8 +435,6 @@ class LLViewerRegion: public LLCapabilityProvider // implements this interface
 	bool isNonCacheableObjectCreated(U32 local_id);	
 
 public:
-	void loadCacheMiscExtras(U32 local_id);
-
     void applyCacheMiscExtras(LLViewerObject* obj);
 
 	struct CompareDistance
diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp
index fee825d12103df8f2ef8aba7ce61b8ea1518a4a1..8731be6e976041204e95cabe80e1bc01abbfaaff 100644
--- a/indra/newview/llviewertexturelist.cpp
+++ b/indra/newview/llviewertexturelist.cpp
@@ -121,8 +121,17 @@ void LLViewerTextureList::doPreloadImages()
 	LLTexUnit::sWhiteTexture = LLViewerFetchedTexture::sWhiteImagep->getTexName();
 	LLUIImageList* image_list = LLUIImageList::getInstance();
 
-	// Set the default flat normal map
-	LLViewerFetchedTexture::sFlatNormalImagep = LLViewerTextureManager::getFetchedTextureFromFile("flatnormal.tga", FTT_LOCAL_FILE, MIPMAP_NO, LLViewerFetchedTexture::BOOST_BUMP);
+    // Set the default flat normal map
+    // BLANK_OBJECT_NORMAL has a version on dataserver, but it has compression artifacts
+    LLViewerFetchedTexture::sFlatNormalImagep =
+        LLViewerTextureManager::getFetchedTextureFromFile("flatnormal.tga",
+                                                          FTT_LOCAL_FILE,
+                                                          MIPMAP_NO,
+                                                          LLViewerFetchedTexture::BOOST_BUMP,
+                                                          LLViewerTexture::FETCHED_TEXTURE,
+                                                          0,
+                                                          0,
+                                                          BLANK_OBJECT_NORMAL);
 
 	// PBR: irradiance
 	LLViewerFetchedTexture::sDefaultIrradiancePBRp = LLViewerTextureManager::getFetchedTextureFromFile("default_irradiance.png", FTT_LOCAL_FILE, MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI);
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index 47c7eed872ab546af9040a9f1f1c80ff6e141288..37e64dfc17d4f2ed0ffe35435627ea49aea34240 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -1957,7 +1957,11 @@ LLViewerWindow::LLViewerWindow(const Params& p)
 	// Initialize OpenGL Renderer
 	LLVertexBuffer::initClass(mWindow);
 	LL_INFOS("RenderInit") << "LLVertexBuffer initialization done." << LL_ENDL ;
-	gGL.init(true);
+	if (!gGL.init(true))
+    {
+        LLError::LLUserWarningMsg::show(LLTrans::getString("MBVideoDrvErr"));
+        LL_ERRS() << "gGL not initialized" << LL_ENDL;
+    }
 
 	if (LLFeatureManager::getInstance()->isSafe()
 		|| (gSavedSettings.getS32("LastFeatureVersion") != LLFeatureManager::getInstance()->getVersion())
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 1e212250a360461c92126b51f0f2a3502bffcd33..57a7d6a90b38e2a1ab85d8b089af1509b0405372 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -5262,8 +5262,9 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
 
 	//drawable->getVObj()->setDebugText(llformat("%d", drawable->isState(LLDrawable::ANIMATED_CHILD)));
 
-	U8 bump = (type == LLRenderPass::PASS_BUMP || type == LLRenderPass::PASS_POST_BUMP) ? facep->getTextureEntry()->getBumpmap() : 0;
-	U8 shiny = facep->getTextureEntry()->getShiny();
+    const LLTextureEntry* te = facep->getTextureEntry();
+	U8 bump = (type == LLRenderPass::PASS_BUMP || type == LLRenderPass::PASS_POST_BUMP) ? te->getBumpmap() : 0;
+	U8 shiny = te->getShiny();
 	
 	LLViewerTexture* tex = facep->getTexture();
 
@@ -5273,22 +5274,22 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
     
     LLUUID mat_id;
 
-    auto* gltf_mat = (LLFetchedGLTFMaterial*) facep->getTextureEntry()->getGLTFRenderMaterial();
-    llassert(gltf_mat == nullptr || dynamic_cast<LLFetchedGLTFMaterial*>(facep->getTextureEntry()->getGLTFRenderMaterial()) != nullptr);
+    auto* gltf_mat = (LLFetchedGLTFMaterial*)te->getGLTFRenderMaterial();
+    llassert(gltf_mat == nullptr || dynamic_cast<LLFetchedGLTFMaterial*>(te->getGLTFRenderMaterial()) != nullptr);
     if (gltf_mat != nullptr)
     {
         mat_id = gltf_mat->getHash(); // TODO: cache this hash
-        if (!facep->hasMedia())
+        if (!facep->hasMedia() || (tex && tex->getType() != LLViewerTexture::MEDIA_TEXTURE))
         { // no media texture, face texture will be unused
             tex = nullptr;
         }
     }
     else
     {
-        mat = facep->getTextureEntry()->getMaterialParams().get();
+        mat = te->getMaterialParams().get();
         if (mat)
         {
-            mat_id = facep->getTextureEntry()->getMaterialParams()->getHash();
+            mat_id = te->getMaterialParams()->getHash();
         }
     }
 
@@ -5298,7 +5299,7 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
 
 	if (mat)
 	{
-		BOOL is_alpha = (facep->getPoolType() == LLDrawPool::POOL_ALPHA) || (facep->getTextureEntry()->getColor().mV[3] < 0.999f) ? TRUE : FALSE;
+		BOOL is_alpha = (facep->getPoolType() == LLDrawPool::POOL_ALPHA) || (te->getColor().mV[3] < 0.999f) ? TRUE : FALSE;
 		if (type == LLRenderPass::PASS_ALPHA)
 		{
 			shader_mask = mat->getShaderMask(LLMaterial::DIFFUSE_ALPHA_MODE_BLEND, is_alpha);
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index 8bdf9bbb8c4293b7eb1dfcc71ab22a7ee5b55a2f..f5f2ba52bfdb4c89a8e932bea10c778be92bdbbe 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -8365,7 +8365,7 @@ void LLPipeline::doWaterHaze()
         else
         {
             //render water patches like LLDrawPoolWater does
-            LLGLDepthTest depth(GL_FALSE);
+            LLGLDepthTest depth(GL_TRUE, GL_FALSE);
             LLGLDisable   cull(GL_CULL_FACE);
 
             gGLLastMatrix = NULL;
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index e78670126e6f6c4e88702696bbe250fff60c231e..d580369ab26826a72a15ffe71874b5092a618372 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -2724,6 +2724,12 @@ function="World.EnvPreset"
                 <menu_item_call.on_click
                  function="Advanced.ForceErrorLlerror" />
             </menu_item_call>
+            <menu_item_call
+             label="Force LLError, Message And Crash"
+             name="Force LLError And Crash">
+                <menu_item_call.on_click
+                 function="Advanced.ForceErrorLlerrorMsg" />
+            </menu_item_call>
             <menu_item_call
              label="Force Bad Memory Access"
              name="Force Bad Memory Access">
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 9fb29c772f6eed63fe97a6817e25bf56b005cae2..b1feb7368f07499d55204df29027cfb905fff1a0 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -53,7 +53,6 @@ Draw distance: [DRAW_DISTANCE]m
 Bandwidth: [NET_BANDWITH]kbit/s
 LOD factor: [LOD_FACTOR]
 Render quality: [RENDER_QUALITY]
-Advanced Lighting Model: [GPU_SHADERS]
 Texture memory: [TEXTURE_MEMORY]MB
 Disk cache: [DISK_CACHE_INFO]
 	</string>
@@ -3020,8 +3019,19 @@ Running in window.
 
 If you continue to receive this message, contact the [SUPPORT_SITE].
 	</string>
+    <string name="MBOutOfMemoryTitle">Out Of Memory</string>
+    <string name="MBOutOfMemoryErr">
+        [APP_NAME]'s request for memory failed. Application can't proceed and will be closed.
 
-	<!-- Avatar Shape Information -->
+If your computer's RAM is low, quit any heavy applications before runing Second Life, allocate a page file or reduce graphical settings like draw distance.
+    </string>
+    <string name="MBMissingFile">
+        [APP_NAME] couldn't access or find some of the files it needs and will be closed.
+
+Please reinstall viewer from  https://secondlife.com/support/downloads/ and contact https://support.secondlife.com if issue persists after reinstall.
+    </string>
+
+    <!-- Avatar Shape Information -->
 <string name="5 O'Clock Shadow">5 O'Clock Shadow</string>
 
 <string name="All White">All White</string>