diff --git a/indra/newview/llreflectionmapmanager.cpp b/indra/newview/llreflectionmapmanager.cpp
index c0e166676d5f9b4ffa1a91718f60b7d0b7808c64..e49cdc8ada4451bfbd16cab5751ef5983fddf005 100644
--- a/indra/newview/llreflectionmapmanager.cpp
+++ b/indra/newview/llreflectionmapmanager.cpp
@@ -39,6 +39,8 @@
 extern BOOL gCubeSnapshot;
 extern BOOL gTeleportDisplay;
 
+static U32 sUpdateCount = 0;
+
 // get the next highest power of two of v (or v if v is already a power of two)
 //defined in llvertexbuffer.cpp
 extern U32 nhpo2(U32 v);
@@ -91,7 +93,7 @@ static bool check_priority(LLReflectionMap* a, LLReflectionMap* b)
         return false;
     }
     else if (b->mCubeIndex == -1)
-    { // certainly higher priority than b
+    { // b is not a candidate for updating, a is higher priority by default
         return true;
     }
     else if (!a->mComplete && !b->mComplete)
@@ -103,7 +105,13 @@ static bool check_priority(LLReflectionMap* a, LLReflectionMap* b)
         return update_score(a) > update_score(b);
     }
 
-    // one of these probes is not complete, if b is complete, a is higher priority
+    // a or b is not complete,
+    if (sUpdateCount % 3 == 0)
+    { // every third update, allow complete probes to cut in line in front of non-complete probes to avoid spammy probe generators from deadlocking scheduler (SL-20258))
+        return !b->mComplete;
+    }
+
+    // prioritize incomplete probe
     return b->mComplete;
 }
 
@@ -331,6 +339,7 @@ void LLReflectionMapManager::update()
         
         probe->autoAdjustOrigin();
 
+        sUpdateCount++;
         mUpdatingProbe = probe;
         doProbeUpdate();
     }
@@ -516,8 +525,14 @@ void LLReflectionMapManager::doProbeUpdate()
 
     updateProbeFace(mUpdatingProbe, mUpdatingFace);
     
+    bool debug_updates = gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PROBE_UPDATES) && mUpdatingProbe->mViewerObject;
+
     if (++mUpdatingFace == 6)
     {
+        if (debug_updates)
+        {
+            mUpdatingProbe->mViewerObject->setDebugText(llformat("%.1f", (F32)gFrameTimeSeconds), LLColor4(1, 1, 1, 1));
+        }
         updateNeighbors(mUpdatingProbe);
         mUpdatingFace = 0;
         if (isRadiancePass())
@@ -531,6 +546,10 @@ void LLReflectionMapManager::doProbeUpdate()
             mRadiancePass = true;
         }
     }
+    else if (debug_updates)
+    {
+        mUpdatingProbe->mViewerObject->setDebugText(llformat("%.1f", (F32)gFrameTimeSeconds), LLColor4(1, 1, 0, 1));
+    }
 }
 
 // Do the reflection map update render passes.
diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp
index 51af23bae96c953327022f28567dc729990fa264..df968f5ce9a7053f4b16089b6287e51cb8719394 100644
--- a/indra/newview/lltooldraganddrop.cpp
+++ b/indra/newview/lltooldraganddrop.cpp
@@ -1120,6 +1120,54 @@ void LLToolDragAndDrop::dropTextureAllFaces(LLViewerObject* hit_obj,
 	hit_obj->sendTEUpdate();
 }
 
+void LLToolDragAndDrop::dropMaterial(LLViewerObject* hit_obj,
+                                     S32 hit_face,
+                                     LLInventoryItem* item,
+                                     LLToolDragAndDrop::ESource source,
+                                     const LLUUID& src_id,
+                                     bool all_faces)
+{
+    LLSelectNode* nodep = nullptr;
+    if (hit_obj->isSelected())
+    {
+        // update object's saved materials
+        nodep = LLSelectMgr::getInstance()->getSelection()->findNode(hit_obj);
+    }
+
+    // If user dropped a material onto face it implies
+    // applying texture now without cancel, save to selection
+    if (all_faces)
+    {
+        dropMaterialAllFaces(hit_obj, item, source, src_id);
+
+        if (nodep)
+        {
+            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++)
+            {
+                material_ids.push_back(hit_obj->getRenderMaterialID(face));
+                override_materials.push_back(nullptr);
+            }
+            nodep->saveGLTFMaterials(material_ids, override_materials);
+        }
+    }
+    else
+    {
+        dropMaterialOneFace(hit_obj, hit_face, item, source, src_id);
+
+        // If user dropped a material onto face it implies
+        // applying texture now without cancel, save to selection
+        if (nodep
+            && gFloaterTools->getVisible()
+            && nodep->mSavedGLTFMaterialIds.size() > hit_face)
+        {
+            nodep->mSavedGLTFMaterialIds[hit_face] = hit_obj->getRenderMaterialID(hit_face);
+            nodep->mSavedGLTFOverrideMaterials[hit_face] = nullptr;
+        }
+    }
+}
 
 void LLToolDragAndDrop::dropMaterialOneFace(LLViewerObject* hit_obj,
     S32 hit_face,
@@ -1225,6 +1273,71 @@ void LLToolDragAndDrop::dropTextureOneFaceAvatar(LLVOAvatar* avatar, S32 hit_fac
 	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,
+                                    S32 tex_channel)
+{
+    LLSelectNode* nodep = nullptr;
+    if (hit_obj->isSelected())
+    {
+        // update object's saved textures
+        nodep = LLSelectMgr::getInstance()->getSelection()->findNode(hit_obj);
+    }
+
+    if (all_faces)
+    {
+        dropTextureAllFaces(hit_obj, item, source, src_id);
+
+        // If user dropped a texture onto face it implies
+        // applying texture now without cancel, save to selection
+        if (nodep)
+        {
+            uuid_vec_t texture_ids;
+            S32 num_faces = hit_obj->getNumTEs();
+            for (S32 face = 0; face < num_faces; face++)
+            {
+                LLViewerTexture* tex = hit_obj->getTEImage(face);
+                if (tex != nullptr)
+                {
+                    texture_ids.push_back(tex->getID());
+                }
+                else
+                {
+                    texture_ids.push_back(LLUUID::null);
+                }
+            }
+            nodep->saveTextures(texture_ids);
+        }
+    }
+    else
+    {
+        dropTextureOneFace(hit_obj, hit_face, item, source, src_id);
+
+        // If user dropped a texture onto face it implies
+        // applying texture now without cancel, save to selection
+        LLPanelFace* panel_face = gFloaterTools->getPanelFace();
+        if (nodep
+            && gFloaterTools->getVisible()
+            && panel_face
+            && panel_face->getTextureDropChannel() == 0 /*texture*/
+            && nodep->mSavedTextures.size() > hit_face)
+        {
+            LLViewerTexture* tex = hit_obj->getTEImage(hit_face);
+            if (tex != nullptr)
+            {
+                nodep->mSavedTextures[hit_face] = tex->getID();
+            }
+            else
+            {
+                nodep->mSavedTextures[hit_face] = LLUUID::null;
+            }
+        }
+    }
+}
 
 void LLToolDragAndDrop::dropTextureOneFace(LLViewerObject* hit_obj,
 										   S32 hit_face,
@@ -2211,104 +2324,48 @@ EAcceptance LLToolDragAndDrop::dad3dApplyToObject(
 	{
 		if (cargo_type == DAD_TEXTURE)
 		{
-            LLSelectNode *nodep = nullptr;
-            if (obj->isSelected())
+            bool all_faces = mask & MASK_SHIFT;
+            if (item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID()))
             {
-                // update object's saved textures
-                nodep = LLSelectMgr::getInstance()->getSelection()->findNode(obj);
+                dropTexture(obj, face, item, mSource, mSourceID, all_faces);
+            }
+            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)
+                                         {
+                                             S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+                                             // if Cancel pressed
+                                             if (option == 1)
+                                             {
+                                                 return;
+                                             }
+                                             dropTexture(obj, face, item, source, source_id, all_faces);
+                                         });
             }
-
-			if((mask & MASK_SHIFT))
-			{
-				dropTextureAllFaces(obj, item, mSource, mSourceID);
-
-                // If user dropped a texture onto face it implies
-                // applying texture now without cancel, save to selection
-                if (nodep)
-                {
-                    uuid_vec_t texture_ids;
-                    S32 num_faces = obj->getNumTEs();
-                    for (S32 face = 0; face < num_faces; face++)
-                    {
-                        LLViewerTexture *tex = obj->getTEImage(face);
-                        if (tex != nullptr)
-                        {
-                            texture_ids.push_back(tex->getID());
-                        }
-                        else
-                        {
-                            texture_ids.push_back(LLUUID::null);
-                        }
-                    }
-                    nodep->saveTextures(texture_ids);
-                }
-			}
-			else
-			{
-				dropTextureOneFace(obj, face, item, mSource, mSourceID);
-
-                // If user dropped a texture onto face it implies
-                // applying texture now without cancel, save to selection
-                LLPanelFace* panel_face = gFloaterTools->getPanelFace();
-                if (nodep
-                    && gFloaterTools->getVisible()
-                    && panel_face
-                    && panel_face->getTextureDropChannel() == 0 /*texture*/
-                    && nodep->mSavedGLTFMaterialIds.size() > face)
-                {
-                    LLViewerTexture *tex = obj->getTEImage(face);
-                    if (tex != nullptr)
-                    {
-                        nodep->mSavedTextures[face] = tex->getID();
-                    }
-                    else
-                    {
-                        nodep->mSavedTextures[face] = LLUUID::null;
-                    }
-                }
-			}
 		}
         else if (cargo_type == DAD_MATERIAL)
         {
-            LLSelectNode *nodep = nullptr;
-            if (obj->isSelected())
-            {
-                // update object's saved materials
-                nodep = LLSelectMgr::getInstance()->getSelection()->findNode(obj);
-            }
-
-            // If user dropped a material onto face it implies
-            // applying texture now without cancel, save to selection
-            if ((mask & MASK_SHIFT))
+            bool all_faces = mask & MASK_SHIFT;
+            if (item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID()))
             {
-                dropMaterialAllFaces(obj, item, mSource, mSourceID);
-
-                if (nodep)
-                {
-                    uuid_vec_t material_ids;
-                    gltf_materials_vec_t override_materials;
-                    S32 num_faces = obj->getNumTEs();
-                    for (S32 face = 0; face < num_faces; face++)
-                    {
-                        material_ids.push_back(obj->getRenderMaterialID(face));
-                        override_materials.push_back(nullptr);
-                    }
-                    nodep->saveGLTFMaterials(material_ids, override_materials);
-                }
+                dropMaterial(obj, face, item, mSource, mSourceID, all_faces);
             }
             else
             {
-                dropMaterialOneFace(obj, face, item, mSource, mSourceID);
-
-                // If user dropped a material onto face it implies
-                // applying texture now without cancel, save to selection
-                if (nodep
-                    && gFloaterTools->getVisible()
-                    && nodep->mSavedGLTFMaterialIds.size() > face)
-                {
-                    nodep->mSavedGLTFMaterialIds[face] = obj->getRenderMaterialID(face);
-                    nodep->mSavedGLTFOverrideMaterials[face] = nullptr;
-                }
+                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)
+                                         {
+                                             S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+                                             // if Cancel pressed
+                                             if (option == 1)
+                                             {
+                                                 return;
+                                             }
+                                             dropMaterial(obj, face, item, source, source_id, all_faces);
+                                         });
             }
         }
 		else if (cargo_type == DAD_MESH)
diff --git a/indra/newview/lltooldraganddrop.h b/indra/newview/lltooldraganddrop.h
index 49c0ba1650aeb2212046d9539b0e9751a624f7f9..2397970de53146a743954648539cd562ad4b47bf 100644
--- a/indra/newview/lltooldraganddrop.h
+++ b/indra/newview/lltooldraganddrop.h
@@ -243,7 +243,15 @@ class LLToolDragAndDrop final : public LLTool, public LLSingleton<LLToolDragAndD
 						   BOOL active,
 						   ESource source,
 						   const LLUUID& src_id);
-	static void dropTextureOneFace(LLViewerObject* hit_obj, S32 hit_face,
+    static void dropTexture(LLViewerObject* hit_obj,
+                            S32 hit_face,
+                            LLInventoryItem* item,
+                            ESource source,
+                            const LLUUID& src_id,
+                            bool all_faces,
+                            S32 tex_channel = -1);
+	static void dropTextureOneFace(LLViewerObject* hit_obj,
+                                   S32 hit_face,
 								   LLInventoryItem* item,
 								   ESource source,
 								   const LLUUID& src_id,
@@ -252,7 +260,14 @@ class LLToolDragAndDrop final : public LLTool, public LLSingleton<LLToolDragAndD
 									LLInventoryItem* item,
 									ESource source,
 									const LLUUID& src_id);
-    static void dropMaterialOneFace(LLViewerObject* hit_obj, S32 hit_face,
+    static void dropMaterial(LLViewerObject* hit_obj,
+                             S32 hit_face,
+                             LLInventoryItem* item,
+                             ESource source,
+                             const LLUUID& src_id,
+                             bool all_faces);
+    static void dropMaterialOneFace(LLViewerObject* hit_obj,
+                                    S32 hit_face,
                                     LLInventoryItem* item,
                                     ESource source,
                                     const LLUUID& src_id);
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 7a99fe79f3b684476d90d2e7f8e5d96009cd739a..e7fbbf16888d0edd790c3a7c6eda2884d83279c5 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -1151,7 +1151,11 @@ U64 info_display_from_string(std::string info_display)
 	}
     else if ("reflection probes" == info_display)
     {
-    return LLPipeline::RENDER_DEBUG_REFLECTION_PROBES;
+        return LLPipeline::RENDER_DEBUG_REFLECTION_PROBES;
+    }
+    else if ("probe updates" == info_display)
+    {
+        return LLPipeline::RENDER_DEBUG_PROBE_UPDATES;
     }
 	else
 	{
diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h
index 010159f2fc28a7082e8585c32743d07e5822f291..34ef37b6cca48a95f5133d6143d3cff71b80e455 100644
--- a/indra/newview/pipeline.h
+++ b/indra/newview/pipeline.h
@@ -584,7 +584,8 @@ class LLPipeline
 		RENDER_DEBUG_TEXEL_DENSITY		=  0x40000000,
 		RENDER_DEBUG_TRIANGLE_COUNT		=  0x80000000,
 		RENDER_DEBUG_IMPOSTORS			= 0x100000000,
-        RENDER_DEBUG_REFLECTION_PROBES  = 0x200000000
+        RENDER_DEBUG_REFLECTION_PROBES  = 0x200000000,
+        RENDER_DEBUG_PROBE_UPDATES      = 0x400000000
 	};
 
 public:
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index afd25414dff932f5fd45858ea44265288b829f6c..0ac1cbd07cc29c55a294b9281747a34e117e0060 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -3384,6 +3384,16 @@ function="World.EnvPreset"
            function="Advanced.ToggleInfoDisplay"
            parameter="reflection probes" />
         </menu_item_check>
+        <menu_item_check
+         label="Probe Updates"
+         name="Probe Updates">
+          <menu_item_check.on_check
+           function="Advanced.CheckInfoDisplay"
+           parameter="probe updates" />
+          <menu_item_check.on_click
+           function="Advanced.ToggleInfoDisplay"
+           parameter="probe updates" />
+        </menu_item_check>
         <menu_item_check
          label="Particles"
          name="Particles">
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index aa9e74df935a354e94011dda815a91421e6ceae4..b6a7070e658c205a9f46ea700af117cca0babed8 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -6115,6 +6115,22 @@ You have updated the location of this pick but the other details will retain the
      yestext="OK"/>
   </notification>
 
+  <notification
+   icon="alertmodal.tga"
+   name="ApplyInventoryToObject"
+   type="alertmodal">
+You are applying &apos;no copy&apos; inventory item.
+This item will be moved to object's inventory, not copied.
+
+Move the inventory item?
+    <tag>confirm</tag>
+    <usetemplate
+     ignoretext="Warn me before I apply &apos;no-copy&apos; items to an object"
+     name="okcancelignore"
+     notext="Cancel"
+     yestext="OK"/>
+  </notification>
+
   <notification
    icon="alertmodal.tga"
    name="MoveInventoryFromObject"