From 32d766cb3af0b79a722b838dcebffef29a755cfe Mon Sep 17 00:00:00 2001
From: Brad Linden <brad@lindenlab.com>
Date: Tue, 15 Oct 2024 15:20:16 -0700
Subject: Provide affordances to disable automatic downrezing of textures when
 SL is in background

secondlife/viewer#2549
---
 indra/newview/app_settings/settings.xml            | 11 ++++++++++
 indra/newview/llviewertexture.cpp                  | 24 +++++++++++++++++++---
 .../newview/skins/default/xui/en/notifications.xml | 15 ++++++++++++++
 3 files changed, 47 insertions(+), 3 deletions(-)

(limited to 'indra/newview')

diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 0d194288e8..25e6fac0ad 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -11413,6 +11413,17 @@
       <key>Value</key>
       <integer>0</integer>
     </map>
+    <key>TextureDiscardBackgroundedTime</key>
+    <map>
+        <key>Comment</key>
+        <string>Specify how long to wait before discarding texture data after viewer is backgrounded.  (zero or negative to disable)</string>
+        <key>Persist</key>
+        <integer>1</integer>
+        <key>Type</key>
+        <string>F32</string>
+        <key>Value</key>
+        <real>60.0</real>
+    </map>
     <key>TextureFetchConcurrency</key>
     <map>
       <key>Comment</key>
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index 99f8db00f2..ab0ea1ec93 100644
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -43,6 +43,7 @@
 #include "message.h"
 #include "lltimer.h"
 #include "v4coloru.h"
+#include "llnotificationsutil.h"
 
 // viewer includes
 #include "llimagegl.h"
@@ -111,6 +112,18 @@ const U32 DESIRED_NORMAL_TEXTURE_SIZE = (U32)LLViewerFetchedTexture::MAX_IMAGE_S
 const U32 DESIRED_NORMAL_TEXTURE_SIZE = (U32)LLViewerFetchedTexture::MAX_IMAGE_SIZE_DEFAULT;
 #endif
 
+namespace
+{
+void onClickDisableDiscard(const LLSD& notification, const LLSD& response)
+{
+    if (response["Cancel_okcancelignore"].asBoolean())
+    {
+        LL_INFOS() << "User chose to disable texture discard on backgrounding." << LL_ENDL;
+        gSavedSettings.setF32("TextureDiscardBackgroundedTime", -1.f);
+    }
+}
+}  // namespace
+
 //----------------------------------------------------------------------------------------------
 //namespace: LLViewerTextureAccess
 //----------------------------------------------------------------------------------------------
@@ -560,16 +573,21 @@ void LLViewerTexture::updateClass()
     // set to max discard bias if the window has been backgrounded for a while
     static bool was_backgrounded = false;
     static LLFrameTimer backgrounded_timer;
+    static F32 last_desired_discard_bias = 1.f;
+    static LLCachedControl<F32> backgrounded_discard_time(gSavedSettings, "TextureDiscardBackgroundedTime", 60.f);
 
     bool in_background = (gViewerWindow && !gViewerWindow->getWindow()->getVisible()) || !gFocusMgr.getAppHasFocus();
 
     if (in_background)
     {
-        if (backgrounded_timer.getElapsedTimeF32() > 10.f)
+        F32 background_elapsed = backgrounded_timer.getElapsedTimeF32();
+        if (backgrounded_discard_time > 0.f && background_elapsed > backgrounded_discard_time)
         {
             if (!was_backgrounded)
             {
-                LL_INFOS() << "Viewer is backgrounded, freeing up video memory." << LL_ENDL;
+                LL_INFOS() << "Viewer is backgrounded for " <<  backgrounded_discard_time << "s, freeing up video memory." << LL_ENDL;
+                LLNotificationsUtil::add("TextureDiscardBackgrounded", llsd::map("DELAY", backgrounded_discard_time), LLSD(), &onClickDisableDiscard);
+                last_desired_discard_bias = sDesiredDiscardBias;
             }
             was_backgrounded = true;
             sDesiredDiscardBias = 4.f;
@@ -582,7 +600,7 @@ void LLViewerTexture::updateClass()
         { // if the viewer was backgrounded
             LL_INFOS() << "Viewer is no longer backgrounded, resuming normal texture usage." << LL_ENDL;
             was_backgrounded = false;
-            sDesiredDiscardBias = 1.f;
+            sDesiredDiscardBias = last_desired_discard_bias;
         }
     }
 
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 5ce73b2cfa..40a8557bb8 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -12583,4 +12583,19 @@ are wearing now.
        yestext="OK"/>
   </notification>
 
+  <notification
+   icon="notify.tga"
+   name="TextureDiscardBackgrounded"
+   type="notify">
+      <unique>
+          <context>DELAY</context>
+      </unique>
+      To improve system performance, [SECOND_LIFE] has reduced texture memory usage after being in the background for [DELAY] seconds.  It may take some time for texture image quality to return to normal.
+     <usetemplate
+       ignoretext="Ask me about background texture memory usage and recovery"
+       name="okcancelignore"
+       yestext="OK"
+       notext="Disable"/>
+  </notification>
+
 </notifications>
-- 
cgit v1.2.3


From ed6ebed0816ed82a51c770ed047e79affb40cefb Mon Sep 17 00:00:00 2001
From: Roxie Linden <roxie@lindenlab.com>
Date: Sun, 20 Oct 2024 22:52:35 -0700
Subject: Don't double-add data channel observer

---
 indra/newview/llvoicewebrtc.cpp | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

(limited to 'indra/newview')

diff --git a/indra/newview/llvoicewebrtc.cpp b/indra/newview/llvoicewebrtc.cpp
index dbeccb51d8..2a3f633858 100644
--- a/indra/newview/llvoicewebrtc.cpp
+++ b/indra/newview/llvoicewebrtc.cpp
@@ -3045,7 +3045,9 @@ void LLVoiceWebRTCConnection::OnDataChannelReady(llwebrtc::LLWebRTCDataInterface
                 return;
             }
 
-            if (data_interface)
+            // OnDataChannelReady may be called multiple times in a single connection attempt
+            // so don't double-set the observer.
+            if (!mWebRTCDataInterface && data_interface)
             {
                 mWebRTCDataInterface = data_interface;
                 mWebRTCDataInterface->setDataObserver(this);
-- 
cgit v1.2.3


From 850bdf4ce335049a75e1c4f6400b627bf328a264 Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Tue, 22 Oct 2024 15:03:19 +0300
Subject: #2245 Allow Lua scripts to be run from the Conversations floater

---
 indra/newview/llfloaterimnearbychat.cpp | 9 +++++++++
 1 file changed, 9 insertions(+)

(limited to 'indra/newview')

diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp
index 6c3e8391cd..b580b19b19 100644
--- a/indra/newview/llfloaterimnearbychat.cpp
+++ b/indra/newview/llfloaterimnearbychat.cpp
@@ -55,6 +55,7 @@
 #include "llfloaterimnearbychatlistener.h"
 #include "llagent.h" // gAgent
 #include "llgesturemgr.h"
+#include "llluamanager.h"
 #include "llmultigesture.h"
 #include "llkeyboard.h"
 #include "llanimationstates.h"
@@ -69,6 +70,7 @@
 #include "lltranslate.h"
 #include "llautoreplace.h"
 #include "lluiusage.h"
+#include <boost/regex.hpp>
 
 S32 LLFloaterIMNearbyChat::sLastSpecialChatChannel = 0;
 
@@ -606,6 +608,13 @@ void LLFloaterIMNearbyChat::sendChat( EChatType type )
                 if(!LLGestureMgr::instance().triggerAndReviseString(utf8text, &utf8_revised_text))
                 {
                     utf8_revised_text = utf8text;
+                    // check if the message is /filename.lua and execute the Lua script
+                    static const boost::regex is_lua_script("^/.*\\.luau?$");
+                    if (boost::regex_match(utf8text, is_lua_script))
+                    {
+                        LLLUAmanager::runScriptFile(utf8text.substr(1));
+                        utf8_revised_text.clear();
+                    }
                 }
             }
             else
-- 
cgit v1.2.3


From cbd594a663fee2099c938e12f6839446a0aaf341 Mon Sep 17 00:00:00 2001
From: Alexander Gavriliuk <alexandrgproductengine@lindenlab.com>
Date: Tue, 22 Oct 2024 18:25:49 +0200
Subject: #2736 The 'Day Offset' makes a rebound back to 0,5 or 1 value

---
 indra/newview/llpanelenvironment.cpp | 23 +++++++++++++++++------
 1 file changed, 17 insertions(+), 6 deletions(-)

(limited to 'indra/newview')

diff --git a/indra/newview/llpanelenvironment.cpp b/indra/newview/llpanelenvironment.cpp
index be61c44b7c..d3df88b65e 100644
--- a/indra/newview/llpanelenvironment.cpp
+++ b/indra/newview/llpanelenvironment.cpp
@@ -48,6 +48,7 @@
 
 #include "llappviewer.h"
 #include "llcallbacklist.h"
+#include "llviewercontrol.h"
 #include "llviewerparcelmgr.h"
 
 #include "llinventorymodel.h"
@@ -939,19 +940,29 @@ void LLPanelEnvironmentInfo::udpateApparentTimeOfDay()
     S32Hours    hourofday(secondofday);
     S32Seconds  secondofhour(secondofday - hourofday);
     S32Minutes  minutesofhour(secondofhour);
+    static bool use_24h = gSavedSettings.getBOOL("Use24HourClock");
     bool        am_pm(hourofday.value() >= 12);
 
-    if (hourofday.value() < 1)
-        hourofday = S32Hours(12);
-    if (hourofday.value() > 12)
-        hourofday -= S32Hours(12);
+    if (!use_24h)
+    {
+        if (hourofday.value() < 1)
+            hourofday = S32Hours(12);
+        if (hourofday.value() > 12)
+            hourofday -= S32Hours(12);
+    }
 
     std::string lblminute(((minutesofhour.value() < 10) ? "0" : "") + LLSD(minutesofhour.value()).asString());
 
-
     mLabelApparentTime->setTextArg("[HH]", LLSD(hourofday.value()).asString());
     mLabelApparentTime->setTextArg("[MM]", lblminute);
-    mLabelApparentTime->setTextArg("[AP]", std::string(am_pm ? "PM" : "AM"));
+    if (use_24h)
+    {
+        mLabelApparentTime->setTextArg("[AP]", std::string());
+    }
+    else
+    {
+        mLabelApparentTime->setTextArg("[AP]", std::string(am_pm ? "PM" : "AM"));
+    }
     mLabelApparentTime->setTextArg("[PRC]", LLSD((S32)(100 * perc)).asString());
 
 }
-- 
cgit v1.2.3


From 12ea8e4f7252029d97b0dfdd9e67d4e744ad375f Mon Sep 17 00:00:00 2001
From: Roxie Linden <roxie@lindenlab.com>
Date: Thu, 24 Oct 2024 10:37:40 -0700
Subject: Fix issue where some connections were restarting instead of closing.

There was an issue where, when a connection close is requested,
a new connection is created.  Specifically, if the caps are not yet
available, a new connection would start.
---
 indra/newview/llvoicewebrtc.cpp | 36 ++++++++++++++++++++----------------
 indra/newview/llvoicewebrtc.h   |  2 +-
 2 files changed, 21 insertions(+), 17 deletions(-)

(limited to 'indra/newview')

diff --git a/indra/newview/llvoicewebrtc.cpp b/indra/newview/llvoicewebrtc.cpp
index 2a3f633858..a725bcf034 100644
--- a/indra/newview/llvoicewebrtc.cpp
+++ b/indra/newview/llvoicewebrtc.cpp
@@ -2478,7 +2478,7 @@ void LLVoiceWebRTCConnection::sendData(const std::string &data)
 
 // Tell the simulator that we're shutting down a voice connection.
 // The simulator will pass this on to the Secondlife WebRTC server.
-void LLVoiceWebRTCConnection::breakVoiceConnectionCoro(connectionPtr_t connection)
+void LLVoiceWebRTCConnection::breakVoiceConnection(connectionPtr_t connection)
 {
     LL_PROFILE_ZONE_SCOPED_CATEGORY_VOICE;
 
@@ -2493,7 +2493,9 @@ void LLVoiceWebRTCConnection::breakVoiceConnectionCoro(connectionPtr_t connectio
     if (!regionp || !regionp->capabilitiesReceived())
     {
         LL_DEBUGS("Voice") << "no capabilities for voice provisioning; waiting " << LL_ENDL;
-        connection->setVoiceConnectionState(VOICE_STATE_SESSION_RETRY);
+        // fine, don't be polite and ask the janus server to break the connection.
+        // just fall through and drop the connection.
+        connection->setVoiceConnectionState(VOICE_STATE_SESSION_EXIT);
         connection->mOutstandingRequests--;
         return;
     }
@@ -2501,7 +2503,8 @@ void LLVoiceWebRTCConnection::breakVoiceConnectionCoro(connectionPtr_t connectio
     std::string url = regionp->getCapability("ProvisionVoiceAccountRequest");
     if (url.empty())
     {
-        connection->setVoiceConnectionState(VOICE_STATE_SESSION_RETRY);
+        // and go on to drop the connection here, too.
+        connection->setVoiceConnectionState(VOICE_STATE_SESSION_EXIT);
         connection->mOutstandingRequests--;
         return;
     }
@@ -2529,8 +2532,11 @@ void LLVoiceWebRTCConnection::breakVoiceConnectionCoro(connectionPtr_t connectio
 
     connection->mOutstandingRequests--;
 
-    if (connection->getVoiceConnectionState() == VOICE_STATE_WAIT_FOR_EXIT)
+    if (connection->getVoiceConnectionState() == VOICE_STATE_WAIT_FOR_EXIT ||
+        !(connection->getVoiceConnectionState() & VOICE_STATE_SESSION_STOPPING))
     {
+        // drop the connection if we either somehow got set back to a running/starting state
+        // or we completed the call in the wait-for-exit state
         connection->setVoiceConnectionState(VOICE_STATE_SESSION_EXIT);
     }
 }
@@ -2814,9 +2820,7 @@ bool LLVoiceWebRTCConnection::connectionStateMachine()
             if (!LLWebRTCVoiceClient::isShuttingDown())
             {
                 mOutstandingRequests++;
-                setVoiceConnectionState(VOICE_STATE_WAIT_FOR_EXIT);
-                LLCoros::instance().launch("LLVoiceWebRTCConnection::breakVoiceConnectionCoro",
-                                           boost::bind(&LLVoiceWebRTCConnection::breakVoiceConnectionCoro, this->shared_from_this()));
+                breakVoiceConnection(this->shared_from_this());
             }
             else
             {
@@ -2829,17 +2833,18 @@ bool LLVoiceWebRTCConnection::connectionStateMachine()
             break;
 
         case VOICE_STATE_SESSION_EXIT:
+        setVoiceConnectionState(VOICE_STATE_WAIT_FOR_CLOSE);
+        mOutstandingRequests++;
+        if (!LLWebRTCVoiceClient::isShuttingDown())
         {
-            setVoiceConnectionState(VOICE_STATE_WAIT_FOR_CLOSE);
-            mOutstandingRequests++;
-            if (!LLWebRTCVoiceClient::isShuttingDown())
-            {
-                mWebRTCPeerConnectionInterface->shutdownConnection();
-            }
-            // else was already posted by llwebrtc::terminate().
-            break;
+            mWebRTCPeerConnectionInterface->shutdownConnection();
+        }
+        // else was already posted by llwebrtc::terminate().
+        break;
+
         case VOICE_STATE_WAIT_FOR_CLOSE:
             break;
+
         case VOICE_STATE_CLOSED:
             if (!mShutDown)
             {
@@ -2856,7 +2861,6 @@ bool LLVoiceWebRTCConnection::connectionStateMachine()
                 }
             }
             break;
-        }
 
         default:
         {
diff --git a/indra/newview/llvoicewebrtc.h b/indra/newview/llvoicewebrtc.h
index 930018b123..b765126af3 100644
--- a/indra/newview/llvoicewebrtc.h
+++ b/indra/newview/llvoicewebrtc.h
@@ -691,7 +691,7 @@ class LLVoiceWebRTCConnection :
     virtual void requestVoiceConnection() = 0;
     static void requestVoiceConnectionCoro(connectionPtr_t connection) { connection->requestVoiceConnection(); }
 
-    static void breakVoiceConnectionCoro(connectionPtr_t connection);
+    static void breakVoiceConnection(connectionPtr_t connection);
 
     LLVoiceClientStatusObserver::EStatusType mCurrentStatus;
 
-- 
cgit v1.2.3


From 541b44b873738a6b954125b31bca5f18c328bade Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Thu, 24 Oct 2024 15:17:01 -0400
Subject: Add LL::ResultSet subclass VectorResultSet for the simple case.

Update existing simple LL::ResultSet subclasses.
---
 indra/newview/llagentlistener.cpp     | 24 +++++++--------------
 indra/newview/llinventorylistener.cpp | 40 +++++++++++------------------------
 2 files changed, 20 insertions(+), 44 deletions(-)

(limited to 'indra/newview')

diff --git a/indra/newview/llagentlistener.cpp b/indra/newview/llagentlistener.cpp
index 2810cd6706..3d07ead95d 100644
--- a/indra/newview/llagentlistener.cpp
+++ b/indra/newview/llagentlistener.cpp
@@ -729,15 +729,11 @@ void LLAgentListener::getID(LLSD const& event_data)
     Response response(llsd::map("id", gAgentID), event_data);
 }
 
-struct AvResultSet : public LL::ResultSet
+struct AvResultSet : public LL::VectorResultSet<LLVOAvatar*>
 {
-    AvResultSet() : LL::ResultSet("nearby_avatars") {}
-    std::vector<LLVOAvatar*> mAvatars;
-
-    int getLength() const override { return narrow(mAvatars.size()); }
-    LLSD getSingle(int index) const override
+    AvResultSet() : super("nearby_avatars") {}
+    LLSD getSingleFrom(LLVOAvatar* const& av) const override
     {
-        auto av = mAvatars[index];
         LLAvatarName av_name;
         LLAvatarNameCache::get(av->getID(), &av_name);
         LLVector3 region_pos = av->getCharacterPosition();
@@ -749,15 +745,11 @@ struct AvResultSet : public LL::ResultSet
     }
 };
 
-struct ObjResultSet : public LL::ResultSet
+struct ObjResultSet : public LL::VectorResultSet<LLViewerObject*>
 {
-    ObjResultSet() : LL::ResultSet("nearby_objects") {}
-    std::vector<LLViewerObject*> mObjects;
-
-    int getLength() const override { return narrow(mObjects.size()); }
-    LLSD getSingle(int index) const override
+    ObjResultSet() : super("nearby_objects") {}
+    LLSD getSingleFrom(LLViewerObject* const& obj) const override
     {
-        auto obj = mObjects[index];
         return llsd::map("id", obj->getID(),
                          "global_pos", ll_sd_from_vector3d(obj->getPositionGlobal()),
                          "region_pos", ll_sd_from_vector3(obj->getPositionRegion()),
@@ -791,7 +783,7 @@ void LLAgentListener::getNearbyAvatarsList(LLSD const& event_data)
         {
             if ((dist_vec_squared(avatar->getPositionGlobal(), agent_pos) <= radius))
             {
-                avresult->mAvatars.push_back(avatar);
+                avresult->mVector.push_back(avatar);
             }
         }
     }
@@ -813,7 +805,7 @@ void LLAgentListener::getNearbyObjectsList(LLSD const& event_data)
         {
             if ((dist_vec_squared(object->getPositionGlobal(), agent_pos) <= radius))
             {
-                objresult->mObjects.push_back(object);
+                objresult->mVector.push_back(object);
             }
         }
     }
diff --git a/indra/newview/llinventorylistener.cpp b/indra/newview/llinventorylistener.cpp
index 88b07c0b0b..13ca12a69a 100644
--- a/indra/newview/llinventorylistener.cpp
+++ b/indra/newview/llinventorylistener.cpp
@@ -107,15 +107,11 @@ LLInventoryListener::LLInventoryListener()
 
 // This struct captures (possibly large) category results from
 // getDirectDescendants() and collectDescendantsIf().
-struct CatResultSet: public LL::ResultSet
+struct CatResultSet: public LL::VectorResultSet<LLInventoryModel::cat_array_t::value_type>
 {
-    CatResultSet(): LL::ResultSet("categories") {}
-    LLInventoryModel::cat_array_t mCategories;
-
-    int getLength() const override { return narrow(mCategories.size()); }
-    LLSD getSingle(int index) const override
+    CatResultSet(): super("categories") {}
+    LLSD getSingleFrom(const LLPointer<LLViewerInventoryCategory>& cat) const override
     {
-        auto cat = mCategories[index];
         return llsd::map("id", cat->getUUID(),
                          "name", cat->getName(),
                          "parent_id", cat->getParentUUID(),
@@ -125,15 +121,11 @@ struct CatResultSet: public LL::ResultSet
 
 // This struct captures (possibly large) item results from
 // getDirectDescendants() and collectDescendantsIf().
-struct ItemResultSet: public LL::ResultSet
+struct ItemResultSet: public LL::VectorResultSet<LLInventoryModel::item_array_t::value_type>
 {
-    ItemResultSet(): LL::ResultSet("items") {}
-    LLInventoryModel::item_array_t mItems;
-
-    int getLength() const override { return narrow(mItems.size()); }
-    LLSD getSingle(int index) const override
+    ItemResultSet(): super("items") {}
+    LLSD getSingleFrom(const LLPointer<LLViewerInventoryItem>& item) const override
     {
-        auto item = mItems[index];
         return llsd::map("id", item->getUUID(),
                          "name", item->getName(),
                          "parent_id", item->getParentUUID(),
@@ -160,14 +152,14 @@ void LLInventoryListener::getItemsInfo(LLSD const &data)
         LLViewerInventoryItem* item = gInventory.getItem(it);
         if (item)
         {
-            itemresult->mItems.push_back(item);
+            itemresult->mVector.push_back(item);
         }
         else
         {
             LLViewerInventoryCategory *cat = gInventory.getCategory(it);
             if (cat)
             {
-                catresult->mCategories.push_back(cat);
+                catresult->mVector.push_back(cat);
             }
         }
     }
@@ -202,8 +194,8 @@ void LLInventoryListener::getDirectDescendants(LLSD const &data)
     auto catresult = new CatResultSet;
     auto itemresult = new ItemResultSet;
 
-    catresult->mCategories = *cats;
-    itemresult->mItems = *items;
+    catresult->mVector = *cats;
+    itemresult->mVector = *items;
 
     response["categories"] = catresult->getKeyLength();
     response["items"] = itemresult->getKeyLength();
@@ -260,8 +252,8 @@ void LLInventoryListener::collectDescendantsIf(LLSD const &data)
     // collectDescendentsIf() method so it doesn't steal too many cycles.
     gInventory.collectDescendentsIf(
         folder_id,
-        catresult->mCategories,
-        itemresult->mItems,
+        catresult->mVector,
+        itemresult->mVector,
         LLInventoryModel::EXCLUDE_TRASH,
         collector);
 
@@ -269,14 +261,6 @@ void LLInventoryListener::collectDescendantsIf(LLSD const &data)
     response["items"] = itemresult->getKeyLength();
 }
 
-/*==========================================================================*|
-void LLInventoryListener::getSingle(LLSD const& data)
-{
-    auto result = LL::ResultSet::getInstance(data["result"]);
-    sendReply(llsd::map("single", result->getSingle(data["index"])), data);
-}
-|*==========================================================================*/
-
 void LLInventoryListener::getSlice(LLSD const& data)
 {
     auto result = LL::ResultSet::getInstance(data["result"]);
-- 
cgit v1.2.3


From 72ce0248f1669e3e172e38beeab96147d7eaea3b Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Thu, 24 Oct 2024 20:45:29 +0300
Subject: viewer#2753 "Animation to play" drop-down box stuck at None

Restore selection after regenerating list
---
 indra/newview/llpreviewgesture.cpp | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

(limited to 'indra/newview')

diff --git a/indra/newview/llpreviewgesture.cpp b/indra/newview/llpreviewgesture.cpp
index 7cbbb89313..66dcd2f7ba 100644
--- a/indra/newview/llpreviewgesture.cpp
+++ b/indra/newview/llpreviewgesture.cpp
@@ -517,6 +517,7 @@ void LLPreviewGesture::addKeys()
 void LLPreviewGesture::addAnimations()
 {
     LLComboBox* combo = mAnimationCombo;
+    LLUUID old_value = combo->getCurrentID();
 
     combo->removeall();
 
@@ -565,6 +566,8 @@ void LLPreviewGesture::addAnimations()
 
         combo->add(item->getName(), item->getAssetUUID(), ADD_BOTTOM);
     }
+
+    combo->setCurrentByID(old_value);
 }
 
 
@@ -1410,7 +1413,7 @@ void LLPreviewGesture::onCommitAnimation(LLUICtrl* ctrl, void* data)
         {
             // Assign the animation name
             LLGestureStepAnimation* anim_step = (LLGestureStepAnimation*)step;
-            if (self->mAnimationCombo->getCurrentIndex() == 0)
+            if (self->mAnimationCombo->getCurrentIndex() <= 0)
             {
                 anim_step->mAnimName.clear();
                 anim_step->mAnimAssetID.setNull();
-- 
cgit v1.2.3


From e0a76080b52df77af0c09c3eeb20fff7ddb064c3 Mon Sep 17 00:00:00 2001
From: Roxie Linden <roxie@lindenlab.com>
Date: Thu, 24 Oct 2024 15:59:00 -0700
Subject: Have to use a coro for now, due to a http call.

---
 indra/newview/llvoicewebrtc.cpp | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

(limited to 'indra/newview')

diff --git a/indra/newview/llvoicewebrtc.cpp b/indra/newview/llvoicewebrtc.cpp
index a725bcf034..52ed393da9 100644
--- a/indra/newview/llvoicewebrtc.cpp
+++ b/indra/newview/llvoicewebrtc.cpp
@@ -257,6 +257,7 @@ void LLWebRTCVoiceClient::cleanupSingleton()
         mNextSession->shutdownAllConnections();
     }
     cleanUp();
+    stopTimer();
     sessionState::clearSessions();
 }
 
@@ -295,7 +296,6 @@ void LLWebRTCVoiceClient::cleanUp()
     mNeighboringRegions.clear();
     sessionState::for_each(boost::bind(predShutdownSession, _1));
     LL_DEBUGS("Voice") << "Exiting" << LL_ENDL;
-    stopTimer();
 }
 
 void LLWebRTCVoiceClient::stopTimer()
@@ -2478,7 +2478,7 @@ void LLVoiceWebRTCConnection::sendData(const std::string &data)
 
 // Tell the simulator that we're shutting down a voice connection.
 // The simulator will pass this on to the Secondlife WebRTC server.
-void LLVoiceWebRTCConnection::breakVoiceConnection(connectionPtr_t connection)
+void LLVoiceWebRTCConnection::breakVoiceConnectionCoro(connectionPtr_t connection)
 {
     LL_PROFILE_ZONE_SCOPED_CATEGORY_VOICE;
 
@@ -2518,7 +2518,7 @@ void LLVoiceWebRTCConnection::breakVoiceConnection(connectionPtr_t connection)
     body["voice_server_type"] = WEBRTC_VOICE_SERVER_TYPE;
 
     LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter(
-        new LLCoreHttpUtil::HttpCoroutineAdapter("LLVoiceWebRTCAdHocConnection::breakVoiceConnection",
+        new LLCoreHttpUtil::HttpCoroutineAdapter("LLVoiceWebRTCAdHocConnection::breakVoiceConnectionCoro",
                                                  LLCore::HttpRequest::DEFAULT_POLICY_ID));
     LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
     LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
@@ -2820,7 +2820,9 @@ bool LLVoiceWebRTCConnection::connectionStateMachine()
             if (!LLWebRTCVoiceClient::isShuttingDown())
             {
                 mOutstandingRequests++;
-                breakVoiceConnection(this->shared_from_this());
+                setVoiceConnectionState(VOICE_STATE_WAIT_FOR_EXIT);
+                LLCoros::getInstance()->launch("LLVoiceWebRTCConnection::breakVoiceConnectionCoro",
+                                               boost::bind(&LLVoiceWebRTCConnection::breakVoiceConnectionCoro, this->shared_from_this()));
             }
             else
             {
-- 
cgit v1.2.3


From c167018e6aae45e18b5b2b255dab035f10b71a83 Mon Sep 17 00:00:00 2001
From: Roxie Linden <roxie@lindenlab.com>
Date: Thu, 24 Oct 2024 16:28:10 -0700
Subject: missing file

---
 indra/newview/llvoicewebrtc.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'indra/newview')

diff --git a/indra/newview/llvoicewebrtc.h b/indra/newview/llvoicewebrtc.h
index b765126af3..930018b123 100644
--- a/indra/newview/llvoicewebrtc.h
+++ b/indra/newview/llvoicewebrtc.h
@@ -691,7 +691,7 @@ class LLVoiceWebRTCConnection :
     virtual void requestVoiceConnection() = 0;
     static void requestVoiceConnectionCoro(connectionPtr_t connection) { connection->requestVoiceConnection(); }
 
-    static void breakVoiceConnection(connectionPtr_t connection);
+    static void breakVoiceConnectionCoro(connectionPtr_t connection);
 
     LLVoiceClientStatusObserver::EStatusType mCurrentStatus;
 
-- 
cgit v1.2.3


From c9c662440055cf8160ca22583b7998122d0b8851 Mon Sep 17 00:00:00 2001
From: Rye <rye@lindenlab.com>
Date: Thu, 24 Oct 2024 16:44:45 -0700
Subject: Restore default exposure to 1 and add exposure and tonemapping
 featuretable entries (#2913) (#2916)

---
 indra/newview/app_settings/settings.xml |  2 +-
 indra/newview/featuretable.txt          | 27 +++++++++++++++++++++++++--
 indra/newview/featuretable_linux.txt    | 27 +++++++++++++++++++++++++--
 indra/newview/featuretable_mac.txt      | 26 +++++++++++++++++++++++++-
 4 files changed, 76 insertions(+), 6 deletions(-)

(limited to 'indra/newview')

diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 4f7b866d5b..e5d48f1652 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -9063,7 +9063,7 @@
     <key>Type</key>
     <string>F32</string>
     <key>Value</key>
-    <real>1.5</real>
+    <real>1.0</real>
   </map>
   
   <key>RenderReflectionProbeDrawDistance</key>
diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt
index 553d6c1d32..6390e43b7a 100644
--- a/indra/newview/featuretable.txt
+++ b/indra/newview/featuretable.txt
@@ -1,4 +1,4 @@
-version 63
+version 64
 // The version number above should be incremented IF AND ONLY IF some
 // change has been made that is sufficiently important to justify
 // resetting the graphics preferences of all users to the recommended
@@ -81,7 +81,9 @@ RenderHeroProbeUpdateRate	1	6
 RenderHeroProbeConservativeUpdateMultiplier 1 16
 RenderDownScaleMethod       1   1
 RenderCASSharpness          1   1
-
+RenderExposure				1   4
+RenderTonemapType			1   1
+RenderTonemapMix			1   1
 
 //
 // Low Graphics Settings
@@ -119,6 +121,9 @@ RenderHeroProbeDistance		1	4
 RenderHeroProbeUpdateRate	1	6
 RenderHeroProbeConservativeUpdateMultiplier 1 16
 RenderCASSharpness          1   0
+RenderExposure				1   1
+RenderTonemapType			1   1
+RenderTonemapMix			1   0.7
 
 //
 // Medium Low Graphics Settings
@@ -156,6 +161,9 @@ RenderHeroProbeDistance		1	6
 RenderHeroProbeUpdateRate	1	3
 RenderHeroProbeConservativeUpdateMultiplier 1 16
 RenderCASSharpness          1   0
+RenderExposure				1   1
+RenderTonemapType			1   1
+RenderTonemapMix			1   0.7
 
 //
 // Medium Graphics Settings (standard)
@@ -193,6 +201,9 @@ RenderHeroProbeDistance		1	6
 RenderHeroProbeUpdateRate	1	3
 RenderHeroProbeConservativeUpdateMultiplier 1 16
 RenderCASSharpness          1   0
+RenderExposure				1   1
+RenderTonemapType			1   1
+RenderTonemapMix			1   0.7
 
 //
 // Medium High Graphics Settings
@@ -230,6 +241,9 @@ RenderHeroProbeDistance		1	6
 RenderHeroProbeUpdateRate	1	2
 RenderHeroProbeConservativeUpdateMultiplier 1 8
 RenderCASSharpness          1   0
+RenderExposure				1   1
+RenderTonemapType			1   1
+RenderTonemapMix			1   0.7
 
 //
 // High Graphics Settings (SSAO + sun shadows)
@@ -267,6 +281,9 @@ RenderHeroProbeDistance		1	8
 RenderHeroProbeUpdateRate	1	2
 RenderHeroProbeConservativeUpdateMultiplier 1 8
 RenderCASSharpness          1   0.4
+RenderExposure				1   1
+RenderTonemapType			1   1
+RenderTonemapMix			1   0.7
 
 //
 // High Ultra Graphics Settings (deferred + SSAO + all shadows)
@@ -304,6 +321,9 @@ RenderHeroProbeDistance		1	16
 RenderHeroProbeUpdateRate	1	1
 RenderHeroProbeConservativeUpdateMultiplier 1 4
 RenderCASSharpness          1   0.4
+RenderExposure				1   1
+RenderTonemapType			1   1
+RenderTonemapMix			1   0.7
 
 //
 // Ultra graphics (REALLY PURTY!)
@@ -341,6 +361,9 @@ RenderHeroProbeDistance		1	16
 RenderHeroProbeUpdateRate	1	1
 RenderHeroProbeConservativeUpdateMultiplier 1 4
 RenderCASSharpness          1   0.4
+RenderExposure				1   1
+RenderTonemapType			1   1
+RenderTonemapMix			1   0.7
 
 //
 // Class Unknown Hardware (unknown)
diff --git a/indra/newview/featuretable_linux.txt b/indra/newview/featuretable_linux.txt
index 6f7f553cec..d8d4f08429 100644
--- a/indra/newview/featuretable_linux.txt
+++ b/indra/newview/featuretable_linux.txt
@@ -1,4 +1,4 @@
-version 29
+version 30
 // The version number above should be incremented IF AND ONLY IF some
 // change has been made that is sufficiently important to justify
 // resetting the graphics preferences of all users to the recommended
@@ -103,7 +103,9 @@ RenderHeroProbeResolution	1	256
 RenderHeroProbeDistance		1	4
 RenderHeroProbeUpdateRate	1   6
 RenderHeroProbeConservativeUpdateMultiplier 1 16
-
+RenderExposure				1   4
+RenderTonemapType			1   1
+RenderTonemapMix			1   1
 
 //
 // Low Graphics Settings
@@ -139,6 +141,9 @@ RenderHeroProbeResolution	1	256
 RenderHeroProbeDistance		1	4
 RenderHeroProbeUpdateRate	1   6
 RenderHeroProbeConservativeUpdateMultiplier 1 16
+RenderExposure				1   1
+RenderTonemapType			1   1
+RenderTonemapMix			1   0.7
 
 //
 // Medium Low Graphics Settings
@@ -173,6 +178,9 @@ RenderHeroProbeResolution	1	256
 RenderHeroProbeDistance		1	6
 RenderHeroProbeUpdateRate	1	3
 RenderHeroProbeConservativeUpdateMultiplier 1 16
+RenderExposure				1   1
+RenderTonemapType			1   1
+RenderTonemapMix			1   0.7
 
 //
 // Medium Graphics Settings (standard)
@@ -207,6 +215,9 @@ RenderHeroProbeResolution	1	512
 RenderHeroProbeDistance		1	6
 RenderHeroProbeUpdateRate	1	3
 RenderHeroProbeConservativeUpdateMultiplier 1 16
+RenderExposure				1   1
+RenderTonemapType			1   1
+RenderTonemapMix			1   0.7
 
 //
 // Medium High Graphics Settings (deferred enabled)
@@ -241,6 +252,9 @@ RenderHeroProbeResolution	1	512
 RenderHeroProbeDistance		1	6
 RenderHeroProbeUpdateRate	1	2
 RenderHeroProbeConservativeUpdateMultiplier 1 8
+RenderExposure				1   1
+RenderTonemapType			1   1
+RenderTonemapMix			1   0.7
 
 //
 // High Graphics Settings (deferred + SSAO)
@@ -275,6 +289,9 @@ RenderHeroProbeResolution	1	512
 RenderHeroProbeDistance		1	8
 RenderHeroProbeUpdateRate	1	2
 RenderHeroProbeConservativeUpdateMultiplier 1 8
+RenderExposure				1   1
+RenderTonemapType			1   1
+RenderTonemapMix			1   0.7
 
 //
 // High Ultra Graphics Settings (deferred + SSAO + shadows)
@@ -309,6 +326,9 @@ RenderHeroProbeResolution	1	512
 RenderHeroProbeDistance		1	16
 RenderHeroProbeUpdateRate	1	1
 RenderHeroProbeConservativeUpdateMultiplier 1 4
+RenderExposure				1   1
+RenderTonemapType			1   1
+RenderTonemapMix			1   0.7
 
 //
 // Ultra graphics (REALLY PURTY!)
@@ -342,6 +362,9 @@ RenderHeroProbeResolution	1	1024
 RenderHeroProbeDistance		1	16
 RenderHeroProbeUpdateRate	1	1
 RenderHeroProbeConservativeUpdateMultiplier 1 4
+RenderExposure				1   1
+RenderTonemapType			1   1
+RenderTonemapMix			1   0.7
 
 //
 // Class Unknown Hardware (unknown)
diff --git a/indra/newview/featuretable_mac.txt b/indra/newview/featuretable_mac.txt
index b1359f8b91..9ba922c3ce 100644
--- a/indra/newview/featuretable_mac.txt
+++ b/indra/newview/featuretable_mac.txt
@@ -1,4 +1,4 @@
-version 61
+version 62
 // The version number above should be incremented IF AND ONLY IF some
 // change has been made that is sufficiently important to justify
 // resetting the graphics preferences of all users to the recommended
@@ -80,6 +80,9 @@ RenderHeroProbeDistance		1	16
 RenderHeroProbeUpdateRate	1	6
 RenderHeroProbeConservativeUpdateMultiplier 1 16
 RenderCASSharpness          1   1
+RenderExposure				1   1
+RenderTonemapType			1   1
+RenderTonemapMix			1   1
 
 //
 // Low Graphics Settings
@@ -117,6 +120,9 @@ RenderHeroProbeDistance		1	4
 RenderHeroProbeUpdateRate	1   6
 RenderHeroProbeConservativeUpdateMultiplier 1 16
 RenderCASSharpness          1   0
+RenderExposure				1   1
+RenderTonemapType			1   1
+RenderTonemapMix			1   0.7
 
 //
 // Medium Low Graphics Settings
@@ -154,6 +160,9 @@ RenderHeroProbeDistance		1	6
 RenderHeroProbeUpdateRate	1	3
 RenderHeroProbeConservativeUpdateMultiplier 1 16
 RenderCASSharpness          1   0
+RenderExposure				1   1
+RenderTonemapType			1   1
+RenderTonemapMix			1   0.7
 
 //
 // Medium Graphics Settings (standard)
@@ -191,6 +200,9 @@ RenderHeroProbeDistance		1	6
 RenderHeroProbeUpdateRate	1	3
 RenderHeroProbeConservativeUpdateMultiplier 1 16
 RenderCASSharpness          1   0
+RenderExposure				1   1
+RenderTonemapType			1   1
+RenderTonemapMix			1   0.7
 
 //
 // Medium High Graphics Settings
@@ -228,6 +240,9 @@ RenderHeroProbeDistance		1	6
 RenderHeroProbeUpdateRate	1	2
 RenderHeroProbeConservativeUpdateMultiplier 1 8
 RenderCASSharpness          1   0
+RenderExposure				1   1
+RenderTonemapType			1   1
+RenderTonemapMix			1   0.7
 
 //
 // High Graphics Settings (SSAO + sun shadows)
@@ -265,6 +280,9 @@ RenderHeroProbeDistance		1	8
 RenderHeroProbeUpdateRate	1	2
 RenderHeroProbeConservativeUpdateMultiplier 1 8
 RenderCASSharpness          1   0
+RenderExposure				1   1
+RenderTonemapType			1   1
+RenderTonemapMix			1   0.7
 
 //
 // High Ultra Graphics Settings (SSAO + all shadows)
@@ -302,6 +320,9 @@ RenderHeroProbeDistance		1	16
 RenderHeroProbeUpdateRate	1	1
 RenderHeroProbeConservativeUpdateMultiplier 1 4
 RenderCASSharpness          1   0.4
+RenderExposure				1   1
+RenderTonemapType			1   1
+RenderTonemapMix			1   0.7
 
 //
 // Ultra graphics (REALLY PURTY!)
@@ -339,6 +360,9 @@ RenderHeroProbeDistance		1	16
 RenderHeroProbeUpdateRate	1	1
 RenderHeroProbeConservativeUpdateMultiplier 1 4
 RenderCASSharpness          1   0.4
+RenderExposure				1   1
+RenderTonemapType			1   1
+RenderTonemapMix			1   0.7
 
 //
 // Class Unknown Hardware (unknown)
-- 
cgit v1.2.3


From fa5aba2b67a029c7415c48270c8c84cd35e73a24 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Sun, 20 Oct 2024 23:20:58 +0300
Subject: viewer#2875 Proportionally agressive vram cleanup

---
 indra/newview/llviewertexture.cpp     | 10 +++++++---
 indra/newview/llviewertexturelist.cpp |  5 +++++
 2 files changed, 12 insertions(+), 3 deletions(-)

(limited to 'indra/newview')

diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index 0f9c65893d..f1c0a4f0fc 100644
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -505,8 +505,12 @@ void LLViewerTexture::updateClass()
 
     F32 budget = max_vram_budget == 0 ? (F32)gGLManager.mVRAM : (F32)max_vram_budget;
 
-    // try to leave half a GB for everyone else, but keep at least 768MB for ourselves
-    F32 target = llmax(budget - 512.f, MIN_VRAM_BUDGET);
+    // Try to leave at least half a GB for everyone else and for bias,
+    // but keep at least 768MB for ourselves
+    // Viewer can 'overshoot' target when scene changes, if viewer goes over budget it
+    // can negatively impact performance, so leave 20% of a breathing room for
+    // 'bias' calculation to kick in.
+    F32 target = llmax(llmin(budget - 512.f, budget * 0.8f), MIN_VRAM_BUDGET);
     sFreeVRAMMegabytes = target - used;
 
     F32 over_pct = (used - target) / target;
@@ -522,7 +526,7 @@ void LLViewerTexture::updateClass()
         // slam to 1.5 bias the moment we hit low memory (discards off screen textures immediately)
         sDesiredDiscardBias = llmax(sDesiredDiscardBias, 1.5f);
 
-        if (is_sys_low)
+        if (is_sys_low || over_pct > 2.f)
         { // if we're low on system memory, emergency purge off screen textures to avoid a death spiral
             LL_WARNS() << "Low system memory detected, emergency downrezzing off screen textures" << LL_ENDL;
             for (auto& image : gTextureList)
diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp
index 08e9151940..0d609b8084 100644
--- a/indra/newview/llviewertexturelist.cpp
+++ b/indra/newview/llviewertexturelist.cpp
@@ -1169,6 +1169,11 @@ F32 LLViewerTextureList::updateImagesFetchTextures(F32 max_time)
 
     //update MIN_UPDATE_COUNT or 5% of other textures, whichever is greater
     update_count = llmax((U32) MIN_UPDATE_COUNT, (U32) mUUIDMap.size()/20);
+    if (LLViewerTexture::sDesiredDiscardBias > 1.f)
+    {
+        // we are over memory target, update more agresively
+        update_count = (S32)(update_count * LLViewerTexture::sDesiredDiscardBias);
+    }
     update_count = llmin(update_count, (U32) mUUIDMap.size());
 
     { // copy entries out of UUID map to avoid iterator invalidation from deletion inside updateImageDecodeProiroty or updateFetch below
-- 
cgit v1.2.3


From 05858ee68bc9bc3fd04c5f593c37f21b1c68a7ac Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Fri, 25 Oct 2024 00:10:35 +0300
Subject: viewer#2653 Failure logging

---
 indra/newview/llpreviewtexture.cpp | 10 ++++++++++
 1 file changed, 10 insertions(+)

(limited to 'indra/newview')

diff --git a/indra/newview/llpreviewtexture.cpp b/indra/newview/llpreviewtexture.cpp
index 1b657d9ea1..800fc7ec0c 100644
--- a/indra/newview/llpreviewtexture.cpp
+++ b/indra/newview/llpreviewtexture.cpp
@@ -441,6 +441,16 @@ void LLPreviewTexture::onFileLoadedForSave(bool success,
             self->getWindow()->decBusyCount();
             self->mLoadingFullImage = false;
         }
+        if (!success)
+        {
+            LL_WARNS("FileSaveAs") << "Failed to download file " << *item_uuid << " for saving."
+                << " Is missing: " << (src_vi->isMissingAsset() ? "true" : "false")
+                << " Discard: " << src_vi->getDiscardLevel()
+                << " Raw discard: " << discard_level
+                << " Size: " << src_vi->getWidth() << "x" << src_vi->getHeight()
+                << " Has GL texture: " << (src_vi->hasGLTexture() ? "true" : "false")
+                << " Has saved raw image: " << (src_vi->hasSavedRawImage() ? "true" : "false") << LL_ENDL;
+        }
     }
 
     if( self && final && success )
-- 
cgit v1.2.3


From 5484f34f9945a6f0060dd74d07ff2701d393f37b Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Fri, 25 Oct 2024 16:56:58 +0300
Subject: #2245 allow passing command-line arguments

---
 indra/newview/llfloaterimnearbychat.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

(limited to 'indra/newview')

diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp
index b580b19b19..f108b5198e 100644
--- a/indra/newview/llfloaterimnearbychat.cpp
+++ b/indra/newview/llfloaterimnearbychat.cpp
@@ -37,6 +37,7 @@
 #include "llfloatersidepanelcontainer.h"
 #include "llfocusmgr.h"
 #include "lllogchat.h"
+#include "llregex.h"
 #include "llresizebar.h"
 #include "llresizehandle.h"
 #include "lldraghandle.h"
@@ -70,7 +71,6 @@
 #include "lltranslate.h"
 #include "llautoreplace.h"
 #include "lluiusage.h"
-#include <boost/regex.hpp>
 
 S32 LLFloaterIMNearbyChat::sLastSpecialChatChannel = 0;
 
@@ -609,8 +609,8 @@ void LLFloaterIMNearbyChat::sendChat( EChatType type )
                 {
                     utf8_revised_text = utf8text;
                     // check if the message is /filename.lua and execute the Lua script
-                    static const boost::regex is_lua_script("^/.*\\.luau?$");
-                    if (boost::regex_match(utf8text, is_lua_script))
+                    static const boost::regex is_lua_script("^/.*\\.luau?(?:\\s+\\S+)*$");
+                    if (ll_regex_match(utf8text, is_lua_script))
                     {
                         LLLUAmanager::runScriptFile(utf8text.substr(1));
                         utf8_revised_text.clear();
-- 
cgit v1.2.3


From c5b499f3345bda4f97099793a5b9b4bcfffa0176 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Mon, 28 Oct 2024 21:15:19 +0200
Subject: viewer#2863 Notify of a missing material cap instead of applying
 locally

---
 indra/newview/llmaterialeditor.cpp | 9 +--------
 1 file changed, 1 insertion(+), 8 deletions(-)

(limited to 'indra/newview')

diff --git a/indra/newview/llmaterialeditor.cpp b/indra/newview/llmaterialeditor.cpp
index b5e494379d..dc7511b642 100644
--- a/indra/newview/llmaterialeditor.cpp
+++ b/indra/newview/llmaterialeditor.cpp
@@ -3177,14 +3177,7 @@ void LLMaterialEditor::applyToSelection()
     {
         LL_WARNS("MaterialEditor") << "Not connected to materials capable region, missing ModifyMaterialParams cap" << LL_ENDL;
 
-        // Fallback local preview. Will be removed once override systems is finished and new cap is deployed everywhere.
-        LLPointer<LLFetchedGLTFMaterial> mat = new LLFetchedGLTFMaterial();
-        getGLTFMaterial(mat);
-        static const LLUUID placeholder("984e183e-7811-4b05-a502-d79c6f978a98");
-        gGLTFMaterialList.addMaterial(placeholder, mat);
-        LLRenderMaterialFunctor mat_func(placeholder);
-        LLObjectSelectionHandle selected_objects = LLSelectMgr::getInstance()->getSelection();
-        selected_objects->applyToTEs(&mat_func);
+        LLNotificationsUtil::add("MissingMaterialCaps");
     }
 }
 
-- 
cgit v1.2.3


From 7827f66caefe358f050caf4d1215d5e956192114 Mon Sep 17 00:00:00 2001
From: Rye <rye@lindenlab.com>
Date: Tue, 29 Oct 2024 02:30:52 -0700
Subject: Add handling for downrezzing textures when viewer is minimized, fix
 downrezzing textures when minimized due to texture system not processesing

---
 indra/newview/app_settings/settings.xml            | 11 +++++
 indra/newview/llviewerdisplay.cpp                  | 29 ++++++++++++
 indra/newview/llviewertexture.cpp                  | 52 +++++++++++++---------
 .../newview/skins/default/xui/en/notifications.xml | 15 +++++++
 4 files changed, 87 insertions(+), 20 deletions(-)

(limited to 'indra/newview')

diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 25e6fac0ad..01df915af3 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -11424,6 +11424,17 @@
         <key>Value</key>
         <real>60.0</real>
     </map>
+    <key>TextureDiscardMinimizedTime</key>
+    <map>
+        <key>Comment</key>
+        <string>Specify how long to wait before discarding texture data after viewer is minimized.  (zero or negative to disable)</string>
+        <key>Persist</key>
+        <integer>1</integer>
+        <key>Type</key>
+        <string>F32</string>
+        <key>Value</key>
+        <real>1.0</real>
+    </map>
     <key>TextureFetchConcurrency</key>
     <map>
       <key>Comment</key>
diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp
index 8c6a38876a..3642c2a339 100644
--- a/indra/newview/llviewerdisplay.cpp
+++ b/indra/newview/llviewerdisplay.cpp
@@ -455,6 +455,35 @@ void display(bool rebuild, F32 zoom_factor, int subfield, bool for_snapshot)
             // true = minimized, do not show/update the TP screen. HB
             update_tp_display(true);
         }
+
+        // Run texture subsystem to discard memory while backgrounded
+        if (!gNonInteractive)
+        {
+            LL_PROFILE_ZONE_NAMED("Update Images");
+
+            {
+                LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("Class");
+                LLViewerTexture::updateClass();
+            }
+
+            {
+                LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("Image Update Bump");
+                gBumpImageList.updateImages();  // must be called before gTextureList version so that it's textures are thrown out first.
+            }
+
+            {
+                LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("List");
+                F32 max_image_decode_time = 0.050f * gFrameIntervalSeconds.value();          // 50 ms/second decode time
+                max_image_decode_time     = llclamp(max_image_decode_time, 0.002f, 0.005f);  // min 2ms/frame, max 5ms/frame)
+                gTextureList.updateImages(max_image_decode_time);
+            }
+
+            {
+                LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("GLTF Materials Cleanup");
+                // remove dead gltf materials
+                gGLTFMaterialList.flushMaterials();
+            }
+        }
         return;
     }
 
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index ab0ea1ec93..a4b76d0ae9 100644
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -112,18 +112,6 @@ const U32 DESIRED_NORMAL_TEXTURE_SIZE = (U32)LLViewerFetchedTexture::MAX_IMAGE_S
 const U32 DESIRED_NORMAL_TEXTURE_SIZE = (U32)LLViewerFetchedTexture::MAX_IMAGE_SIZE_DEFAULT;
 #endif
 
-namespace
-{
-void onClickDisableDiscard(const LLSD& notification, const LLSD& response)
-{
-    if (response["Cancel_okcancelignore"].asBoolean())
-    {
-        LL_INFOS() << "User chose to disable texture discard on backgrounding." << LL_ENDL;
-        gSavedSettings.setF32("TextureDiscardBackgroundedTime", -1.f);
-    }
-}
-}  // namespace
-
 //----------------------------------------------------------------------------------------------
 //namespace: LLViewerTextureAccess
 //----------------------------------------------------------------------------------------------
@@ -571,25 +559,49 @@ void LLViewerTexture::updateClass()
     }
 
     // set to max discard bias if the window has been backgrounded for a while
+    static F32 last_desired_discard_bias = 1.f;
     static bool was_backgrounded = false;
     static LLFrameTimer backgrounded_timer;
-    static F32 last_desired_discard_bias = 1.f;
+    static LLCachedControl<F32> minimized_discard_time(gSavedSettings, "TextureDiscardMinimizedTime", 1.f);
     static LLCachedControl<F32> backgrounded_discard_time(gSavedSettings, "TextureDiscardBackgroundedTime", 60.f);
 
     bool in_background = (gViewerWindow && !gViewerWindow->getWindow()->getVisible()) || !gFocusMgr.getAppHasFocus();
-
+    bool is_minimized  = gViewerWindow && gViewerWindow->getWindow()->getMinimized() && in_background;
     if (in_background)
     {
-        F32 background_elapsed = backgrounded_timer.getElapsedTimeF32();
-        if (backgrounded_discard_time > 0.f && background_elapsed > backgrounded_discard_time)
+        F32 discard_time = is_minimized ? minimized_discard_time : backgrounded_discard_time;
+        if (discard_time > 0.f && backgrounded_timer.getElapsedTimeF32() > discard_time)
         {
             if (!was_backgrounded)
             {
-                LL_INFOS() << "Viewer is backgrounded for " <<  backgrounded_discard_time << "s, freeing up video memory." << LL_ENDL;
-                LLNotificationsUtil::add("TextureDiscardBackgrounded", llsd::map("DELAY", backgrounded_discard_time), LLSD(), &onClickDisableDiscard);
+                std::string notification_name;
+                std::string setting;
+                if (is_minimized)
+                {
+                    notification_name = "TextureDiscardMinimized";
+                    setting           = "TextureDiscardMinimizedTime";
+                }
+                else
+                {
+                    notification_name = "TextureDiscardBackgrounded";
+                    setting           = "TextureDiscardBackgroundedTime";
+                }
+
+                LL_INFOS() << "Viewer was " << (is_minimized ? "minimized" : "backgrounded") << " for " << discard_time
+                           << "s, freeing up video memory." << LL_ENDL;
+
+                LLNotificationsUtil::add(notification_name, llsd::map("DELAY", discard_time), LLSD(),
+                                         [=](const LLSD& notification, const LLSD& response)
+                                         {
+                                             if (response["Cancel_okcancelignore"].asBoolean())
+                                             {
+                                                 LL_INFOS() << "User chose to disable texture discard on " <<  (is_minimized ? "minimizing." : "backgrounding.") << LL_ENDL;
+                                                 gSavedSettings.setF32(setting, -1.f);
+                                             }
+                                         });
                 last_desired_discard_bias = sDesiredDiscardBias;
+                was_backgrounded = true;
             }
-            was_backgrounded = true;
             sDesiredDiscardBias = 4.f;
         }
     }
@@ -598,7 +610,7 @@ void LLViewerTexture::updateClass()
         backgrounded_timer.reset();
         if (was_backgrounded)
         { // if the viewer was backgrounded
-            LL_INFOS() << "Viewer is no longer backgrounded, resuming normal texture usage." << LL_ENDL;
+            LL_INFOS() << "Viewer is no longer backgrounded or minimized, resuming normal texture usage." << LL_ENDL;
             was_backgrounded = false;
             sDesiredDiscardBias = last_desired_discard_bias;
         }
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 40a8557bb8..509e6e9766 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -12598,4 +12598,19 @@ are wearing now.
        notext="Disable"/>
   </notification>
 
+  <notification
+   icon="notify.tga"
+   name="TextureDiscardMinimized"
+   type="notify">
+      <unique>
+          <context>DELAY</context>
+      </unique>
+      To improve system performance, [SECOND_LIFE] has reduced texture memory usage after being minimized for [DELAY] seconds.  It may take some time for texture image quality to return to normal.
+     <usetemplate
+       ignoretext="Ask me about minimized texture memory usage and recovery"
+       name="okcancelignore"
+       yestext="OK"
+       notext="Disable"/>
+  </notification>
+    
 </notifications>
-- 
cgit v1.2.3


From 9598e2f4cedd3dc36d447086273e0ed97967bbf9 Mon Sep 17 00:00:00 2001
From: Rye <rye@lindenlab.com>
Date: Tue, 29 Oct 2024 10:16:53 -0700
Subject: Fix texture discard bias not incrementing correctly due to being
 limited by frame interval and a timer at the same time

---
 indra/newview/llviewertexture.cpp | 1 -
 1 file changed, 1 deletion(-)

(limited to 'indra/newview')

diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index a4b76d0ae9..5b4efc9ecc 100644
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -543,7 +543,6 @@ void LLViewerTexture::updateClass()
         {
             static LLCachedControl<F32> low_mem_min_discard_increment(gSavedSettings, "RenderLowMemMinDiscardIncrement", .1f);
             sDesiredDiscardBias += (F32)low_mem_min_discard_increment * (F32)gFrameIntervalSeconds;
-            sEvaluationTimer.reset();
         }
     }
     else
-- 
cgit v1.2.3


From 9c2a4aad3025ada41e3ff39fb40375245613a14d Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Tue, 29 Oct 2024 00:54:13 +0200
Subject: viewer#2894 Make PBR scale like Blinn Phong does

---
 indra/newview/llselectmgr.cpp | 27 +++++++++++++++++++++++++++
 indra/newview/llselectmgr.h   |  2 ++
 2 files changed, 29 insertions(+)

(limited to 'indra/newview')

diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp
index 51da051340..d0347c7abf 100644
--- a/indra/newview/llselectmgr.cpp
+++ b/indra/newview/llselectmgr.cpp
@@ -3133,6 +3133,8 @@ void LLSelectMgr::adjustTexturesByScale(bool send_to_sim, bool stretch)
 
                     F32 scale_x = 1;
                     F32 scale_y = 1;
+                    F32 offset_x = 0;
+                    F32 offset_y = 0;
 
                     for (U32 i = 0; i < LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT; ++i)
                     {
@@ -3149,6 +3151,21 @@ void LLSelectMgr::adjustTexturesByScale(bool send_to_sim, bool stretch)
                             scale_y = scale_ratio.mV[t_axis] * object_scale.mV[t_axis];
                         }
                         material->mTextureTransform[i].mScale.set(scale_x, scale_y);
+
+                        LLVector2 scales = selectNode->mGLTFScales[te_num][i];
+                        LLVector2 offsets = selectNode->mGLTFOffsets[te_num][i];
+                        F64 int_part = 0;
+                        offset_x = (F32)modf((offsets[VX] + (scales[VX] - scale_x)) / 2, &int_part);
+                        if (offset_x < 0)
+                        {
+                            offset_x++;
+                        }
+                        offset_y = (F32)modf((offsets[VY] + (scales[VY] - scale_y)) / 2, &int_part);
+                        if (offset_y < 0)
+                        {
+                            offset_y++;
+                        }
+                        material->mTextureTransform[i].mOffset.set(offset_x, offset_y);
                     }
 
                     LLFetchedGLTFMaterial* render_mat = (LLFetchedGLTFMaterial*)tep->getGLTFRenderMaterial();
@@ -6888,6 +6905,8 @@ void LLSelectNode::saveTextureScaleRatios(LLRender::eTexIndex index_to_query)
 {
     mTextureScaleRatios.clear();
     mGLTFScaleRatios.clear();
+    mGLTFScales.clear();
+    mGLTFOffsets.clear();
 
     if (mObject.notNull())
     {
@@ -6928,6 +6947,8 @@ void LLSelectNode::saveTextureScaleRatios(LLRender::eTexIndex index_to_query)
             F32 scale_x = 1;
             F32 scale_y = 1;
             std::vector<LLVector3> material_v_vec;
+            std::vector<LLVector2> material_scales_vec;
+            std::vector<LLVector2> material_offset_vec;
             for (U32 i = 0; i < LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT; ++i)
             {
                 if (material)
@@ -6935,12 +6956,16 @@ void LLSelectNode::saveTextureScaleRatios(LLRender::eTexIndex index_to_query)
                     LLGLTFMaterial::TextureTransform& transform = material->mTextureTransform[i];
                     scale_x = transform.mScale[VX];
                     scale_y = transform.mScale[VY];
+                    material_scales_vec.push_back(transform.mScale);
+                    material_offset_vec.push_back(transform.mOffset);
                 }
                 else
                 {
                     // Not having an override doesn't mean that there is no material
                     scale_x = 1;
                     scale_y = 1;
+                    material_scales_vec.emplace_back(scale_x, scale_y);
+                    material_offset_vec.emplace_back(0.f, 0.f);
                 }
 
                 if (tep->getTexGen() == LLTextureEntry::TEX_GEN_PLANAR)
@@ -6956,6 +6981,8 @@ void LLSelectNode::saveTextureScaleRatios(LLRender::eTexIndex index_to_query)
                 material_v_vec.push_back(material_v);
             }
             mGLTFScaleRatios.push_back(material_v_vec);
+            mGLTFScales.push_back(material_scales_vec);
+            mGLTFOffsets.push_back(material_offset_vec);
         }
     }
 }
diff --git a/indra/newview/llselectmgr.h b/indra/newview/llselectmgr.h
index f8242675dc..f2b1e691b5 100644
--- a/indra/newview/llselectmgr.h
+++ b/indra/newview/llselectmgr.h
@@ -240,6 +240,8 @@ public:
     gltf_materials_vec_t mSavedGLTFOverrideMaterials;
     std::vector<LLVector3>  mTextureScaleRatios;
     std::vector< std::vector<LLVector3> >  mGLTFScaleRatios;
+    std::vector< std::vector<LLVector2> >  mGLTFScales;
+    std::vector< std::vector<LLVector2> >  mGLTFOffsets;
     std::vector<LLVector3>  mSilhouetteVertices;    // array of vertices to render silhouette of object
     std::vector<LLVector3>  mSilhouetteNormals; // array of normals to render silhouette of object
     bool                    mSilhouetteExists;  // need to generate silhouette?
-- 
cgit v1.2.3


From a2c86616360fe51e8d766796bed80e73444823d5 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Tue, 29 Oct 2024 23:02:46 +0200
Subject: viewer#2972 Fix viewer stripping quotes off folder names

---
 indra/newview/llxmlrpctransaction.cpp | 3 +++
 1 file changed, 3 insertions(+)

(limited to 'indra/newview')

diff --git a/indra/newview/llxmlrpctransaction.cpp b/indra/newview/llxmlrpctransaction.cpp
index 07e2b118d3..7fbcb5fc04 100644
--- a/indra/newview/llxmlrpctransaction.cpp
+++ b/indra/newview/llxmlrpctransaction.cpp
@@ -313,6 +313,8 @@ bool LLXMLRPCTransaction::Impl::process()
     if (mHasResponse && !mResponseParsed)
     {
         LLXMLNodePtr root;
+        bool strip_escaped_strings = LLXMLNode::sStripEscapedStrings;
+        LLXMLNode::sStripEscapedStrings = false;
         if (!LLXMLNode::parseBuffer(mResponseText.data(), mResponseText.size(),
                                     root, nullptr))
         {
@@ -329,6 +331,7 @@ bool LLXMLRPCTransaction::Impl::process()
             LL_WARNS() << "XMLRPC response parsing failed; request URI: "
                        << mURI << LL_ENDL;
         }
+        LLXMLNode::sStripEscapedStrings = strip_escaped_strings;
         mResponseParsed = true;
     }
 
-- 
cgit v1.2.3


From 4b5fa5349e06ce3471875e0c401f9119831ed887 Mon Sep 17 00:00:00 2001
From: Rye <rye@lindenlab.com>
Date: Wed, 30 Oct 2024 17:25:16 -0400
Subject: Fix exposure in advanced graphics preferences being limited to 1.5
 instead of 4 (#2978)

(secondlife/viewer#2916)
---
 .../skins/default/xui/en/floater_preferences_graphics_advanced.xml      | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'indra/newview')

diff --git a/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml b/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml
index 8bb15d1d3a..23516c938a 100644
--- a/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml
+++ b/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml
@@ -821,7 +821,7 @@
     layout="topleft"
     left="420"
     min_val="0.5"
-    max_val="1.5"
+    max_val="4.0"
     name="RenderExposure"
     show_text="true"
     top_delta="24"
-- 
cgit v1.2.3


From 2039009f6c5aac15e85a41bd35ad38763d25ad5f Mon Sep 17 00:00:00 2001
From: Rye <rye@lindenlab.com>
Date: Tue, 29 Oct 2024 20:24:03 -0700
Subject: Fix LLMutexLock usage in LLModelPreview

---
 indra/newview/llmodelpreview.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'indra/newview')

diff --git a/indra/newview/llmodelpreview.cpp b/indra/newview/llmodelpreview.cpp
index 1e7da126b0..ecca593d51 100644
--- a/indra/newview/llmodelpreview.cpp
+++ b/indra/newview/llmodelpreview.cpp
@@ -3565,7 +3565,7 @@ bool LLModelPreview::render()
                         LLPhysicsDecomp* decomp = gMeshRepo.mDecompThread;
                         if (decomp)
                         {
-                            LLMutexLock(decomp->mMutex);
+                            LLMutexLock lock(decomp->mMutex);
 
                             LLModel::Decomposition& physics = model->mPhysics;
 
@@ -3686,7 +3686,7 @@ bool LLModelPreview::render()
                             LLPhysicsDecomp* decomp = gMeshRepo.mDecompThread;
                             if (decomp)
                             {
-                                LLMutexLock(decomp->mMutex);
+                                LLMutexLock lock(decomp->mMutex);
 
                                 LLModel::Decomposition& physics = model->mPhysics;
 
-- 
cgit v1.2.3


From d1a4cbb8fa9058c4d3a8fc3ebe3a543626aac77e Mon Sep 17 00:00:00 2001
From: Rye <rye@lindenlab.com>
Date: Tue, 29 Oct 2024 20:24:40 -0700
Subject: Fixes to LLCachedControl usage in windowing and avatars

---
 indra/newview/llviewerwindow.cpp | 14 ++++++++------
 indra/newview/llvoavatar.cpp     |  4 ++--
 indra/newview/llvoavatar.h       |  2 --
 3 files changed, 10 insertions(+), 10 deletions(-)

(limited to 'indra/newview')

diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index cc3e916270..d339d0c37c 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -268,9 +268,6 @@ static const F32 MIN_DISPLAY_SCALE = 0.75f;
 
 static const char KEY_MOUSELOOK = 'M';
 
-static LLCachedControl<std::string> sSnapshotBaseName(LLCachedControl<std::string>(gSavedPerAccountSettings, "SnapshotBaseName", "Snapshot"));
-static LLCachedControl<std::string> sSnapshotDir(LLCachedControl<std::string>(gSavedPerAccountSettings, "SnapshotBaseDir", ""));
-
 LLTrace::SampleStatHandle<> LLViewerWindow::sMouseVelocityStat("Mouse Velocity");
 
 
@@ -2012,6 +2009,7 @@ LLViewerWindow::LLViewerWindow(const Params& p)
 
 std::string LLViewerWindow::getLastSnapshotDir()
 {
+    static LLCachedControl<std::string> sSnapshotDir(gSavedPerAccountSettings, "SnapshotBaseDir", "");
     return sSnapshotDir;
 }
 
@@ -3782,7 +3780,7 @@ void LLViewerWindow::updateLayout()
 {
     LLToolMgr* tool_mgr = LLToolMgr::getInstance();
     LLTool* tool = tool_mgr->getCurrentTool();
-    LLCachedControl<bool> freeze_time(gSavedSettings, "FreezeTime");
+    static LLCachedControl<bool> freeze_time(gSavedSettings, "FreezeTime");
     if (gFloaterTools != NULL
         && tool != NULL
         && tool != gToolNull
@@ -4711,6 +4709,7 @@ void LLViewerWindow::saveImageNumbered(LLImageFormatted *image, bool force_picke
     // Get a base file location if needed.
     if (force_picker || !isSnapshotLocSet())
     {
+        static LLCachedControl<std::string> sSnapshotBaseName(gSavedPerAccountSettings, "SnapshotBaseName", "Snapshot");
         std::string proposed_name(sSnapshotBaseName);
 
         // getSaveFile will append an appropriate extension to the proposed name, based on the ESaveFilter constant passed in.
@@ -4756,6 +4755,9 @@ void LLViewerWindow::onSelectionFailure(const snapshot_saved_signal_t::slot_type
 
 void LLViewerWindow::saveImageLocal(LLImageFormatted *image, const snapshot_saved_signal_t::slot_type& success_cb, const snapshot_saved_signal_t::slot_type& failure_cb)
 {
+    static LLCachedControl<std::string> sSnapshotBaseName(gSavedPerAccountSettings, "SnapshotBaseName", "Snapshot");
+    static LLCachedControl<std::string> sSnapshotDir(gSavedPerAccountSettings, "SnapshotBaseDir", "");
+
     std::string lastSnapshotDir = LLViewerWindow::getLastSnapshotDir();
     if (lastSnapshotDir.empty())
     {
@@ -4907,8 +4909,8 @@ void LLViewerWindow::playSnapshotAnimAndSound()
 
 bool LLViewerWindow::isSnapshotLocSet() const
 {
-    std::string snapshot_dir = sSnapshotDir;
-    return !snapshot_dir.empty();
+    static LLCachedControl<std::string> sSnapshotDir(gSavedPerAccountSettings, "SnapshotBaseDir", "");
+    return !sSnapshotDir().empty();
 }
 
 void LLViewerWindow::resetSnapshotLoc() const
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 690cfaa677..bfed8b9d39 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -687,7 +687,6 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
     mVisualComplexity(VISUAL_COMPLEXITY_UNKNOWN),
     mLoadedCallbacksPaused(false),
     mLoadedCallbackTextures(0),
-    mRenderUnloadedAvatar(LLCachedControl<bool>(gSavedSettings, "RenderUnloadedAvatar", false)),
     mLastRezzedStatus(-1),
     mIsEditingAppearance(false),
     mUseLocalAppearance(false),
@@ -8523,7 +8522,8 @@ bool LLVOAvatar::processFullyLoadedChange(bool loading)
 
 bool LLVOAvatar::isFullyLoaded() const
 {
-    return (mRenderUnloadedAvatar || mFullyLoaded);
+    static LLCachedControl<bool> render_unloaded_avatars(gSavedSettings, "RenderUnloadedAvatar", false);
+    return (render_unloaded_avatars || mFullyLoaded);
 }
 
 bool LLVOAvatar::isTooComplex() const
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index dd1725c322..557ccddf99 100644
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -668,8 +668,6 @@ private:
     LLVector3   mLastAnimExtents[2];
     LLVector3   mLastAnimBasePos;
 
-    LLCachedControl<bool> mRenderUnloadedAvatar;
-
     //--------------------------------------------------------------------
     // Wind rippling in clothes
     //--------------------------------------------------------------------
-- 
cgit v1.2.3


From b44158591b06704de6506d4ec03314e93c800adb Mon Sep 17 00:00:00 2001
From: Rye Cogtail <rye@lindenlab.com>
Date: Wed, 30 Oct 2024 15:29:59 -0400
Subject: Fix potential null pointer deref during image upload

---
 indra/newview/llviewertexturelist.cpp | 11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)

(limited to 'indra/newview')

diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp
index 752cfb3884..bc9732a9ef 100644
--- a/indra/newview/llviewertexturelist.cpp
+++ b/indra/newview/llviewertexturelist.cpp
@@ -1422,6 +1422,11 @@ bool LLViewerTextureList::createUploadFile(LLPointer<LLImageRaw> raw_image,
         raw_image->getComponents());
 
     LLPointer<LLImageJ2C> compressedImage = LLViewerTextureList::convertToUploadFile(scale_image, max_image_dimentions);
+    if (compressedImage.isNull())
+    {
+        LL_INFOS() << "Couldn't convert to j2c, file : " << out_filename << LL_ENDL;
+        return false;
+    }
     if (compressedImage->getWidth() < min_image_dimentions || compressedImage->getHeight() < min_image_dimentions)
     {
         std::string reason = llformat("Images below %d x %d pixels are not allowed. Actual size: %d x %dpx",
@@ -1432,12 +1437,6 @@ bool LLViewerTextureList::createUploadFile(LLPointer<LLImageRaw> raw_image,
         compressedImage->setLastError(reason);
         return false;
     }
-    if (compressedImage.isNull())
-    {
-        compressedImage->setLastError("Couldn't convert the image to jpeg2000.");
-        LL_INFOS() << "Couldn't convert to j2c, file : " << out_filename << LL_ENDL;
-        return false;
-    }
     if (!compressedImage->save(out_filename))
     {
         compressedImage->setLastError("Couldn't create the jpeg2000 image for upload.");
-- 
cgit v1.2.3


From ae5e4c30468f0712c0f8b28b7b36ada41c198c14 Mon Sep 17 00:00:00 2001
From: Rye Cogtail <rye@lindenlab.com>
Date: Wed, 30 Oct 2024 16:03:53 -0400
Subject: Fix various member variables being access before initialization

---
 indra/newview/llinventorygallery.cpp  | 1 +
 indra/newview/lllocationinputctrl.h   | 2 +-
 indra/newview/llmediactrl.cpp         | 4 ----
 indra/newview/llmediactrl.h           | 1 -
 indra/newview/llnetmap.cpp            | 1 +
 indra/newview/llscrollingpanelparam.h | 1 -
 indra/newview/llvoavatar.h            | 4 ++--
 7 files changed, 5 insertions(+), 9 deletions(-)

(limited to 'indra/newview')

diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp
index 03bafa48bd..c7f2b0cb72 100644
--- a/indra/newview/llinventorygallery.cpp
+++ b/indra/newview/llinventorygallery.cpp
@@ -2777,6 +2777,7 @@ static LLDefaultChildRegistry::Register<LLInventoryGalleryItem> r("inventory_gal
 LLInventoryGalleryItem::LLInventoryGalleryItem(const Params& p)
     : LLPanel(p),
     mSelected(false),
+    mWorn(false),
     mDefaultImage(true),
     mItemName(""),
     mWornSuffix(""),
diff --git a/indra/newview/lllocationinputctrl.h b/indra/newview/lllocationinputctrl.h
index 56e5555ba5..c048b028f5 100644
--- a/indra/newview/lllocationinputctrl.h
+++ b/indra/newview/lllocationinputctrl.h
@@ -206,7 +206,7 @@ private:
     std::string mEditLandmarkTooltip;
     // this field holds a human-readable form of the location string, it is needed to be able to compare copy-pated value and real location
     std::string mHumanReadableLocation;
-    bool isHumanReadableLocationVisible;
+    bool isHumanReadableLocationVisible = true;
     std::string mMaturityHelpTopic;
 };
 
diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp
index 49260d5c50..ef9e8d7dac 100644
--- a/indra/newview/llmediactrl.cpp
+++ b/indra/newview/llmediactrl.cpp
@@ -1022,10 +1022,6 @@ void LLMediaCtrl::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event)
         case MEDIA_EVENT_NAVIGATE_COMPLETE:
         {
             LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_NAVIGATE_COMPLETE, result string is: " << self->getNavigateResultString() << LL_ENDL;
-            if(mHidingInitialLoad)
-            {
-                mHidingInitialLoad = false;
-            }
         };
         break;
 
diff --git a/indra/newview/llmediactrl.h b/indra/newview/llmediactrl.h
index 9f9564af46..5d3d8f3ba2 100644
--- a/indra/newview/llmediactrl.h
+++ b/indra/newview/llmediactrl.h
@@ -201,7 +201,6 @@ public:
                 mStretchToFill,
                 mMaintainAspectRatio,
                 mHideLoading,
-                mHidingInitialLoad,
                 mClearCache,
                 mHoverTextChanged,
                 mDecoupleTextureSize,
diff --git a/indra/newview/llnetmap.cpp b/indra/newview/llnetmap.cpp
index 483ddcdd63..bf9aa66094 100644
--- a/indra/newview/llnetmap.cpp
+++ b/indra/newview/llnetmap.cpp
@@ -96,6 +96,7 @@ LLNetMap::LLNetMap (const Params & p)
     mPopupWorldPos(0.f, 0.f, 0.f),
     mMouseDown(0, 0),
     mPanning(false),
+    mCentering(false),
     mUpdateNow(false),
     mObjectImageCenterGlobal( gAgentCamera.getCameraPositionGlobal() ),
     mObjectRawImagep(),
diff --git a/indra/newview/llscrollingpanelparam.h b/indra/newview/llscrollingpanelparam.h
index 3aba4e4e40..93daf22e76 100644
--- a/indra/newview/llscrollingpanelparam.h
+++ b/indra/newview/llscrollingpanelparam.h
@@ -81,7 +81,6 @@ public:
 protected:
     LLTimer             mMouseDownTimer;    // timer for how long mouse has been held down on a hint.
     F32                 mLastHeldTime;
-    bool mAllowModify;
 
     LLButton* mLessBtn;
     LLButton* mMoreBtn;
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index 557ccddf99..a9dea1f1e3 100644
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -1012,7 +1012,7 @@ public:
     void            startTyping() { mTyping = true; mTypingTimer.reset(); }
     void            stopTyping() { mTyping = false; }
 private:
-    bool            mVisibleChat;
+    bool            mVisibleChat = false;
 
     //--------------------------------------------------------------------
     // Lip synch morphs
@@ -1194,7 +1194,7 @@ public:
     static F32          sGreyUpdateTime; // Last time stats were updated (to prevent multiple updates per frame)
 protected:
     S32                 getUnbakedPixelAreaRank();
-    bool                mHasGrey;
+    bool                mHasGrey = false;
 private:
     F32                 mMinPixelArea;
     F32                 mMaxPixelArea;
-- 
cgit v1.2.3


From 067d568721ab65e5c806385a8c98d7a843ddf907 Mon Sep 17 00:00:00 2001
From: Rye Cogtail <rye@lindenlab.com>
Date: Wed, 30 Oct 2024 16:05:36 -0400
Subject: Fix potential crash from LLWorld being called before singleton
 creation during early init

---
 indra/newview/llviewershadermgr.cpp | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

(limited to 'indra/newview')

diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp
index a6d397c039..c219b0575e 100644
--- a/indra/newview/llviewershadermgr.cpp
+++ b/indra/newview/llviewershadermgr.cpp
@@ -985,7 +985,10 @@ bool LLViewerShaderMgr::loadShadersWater()
         return loadShadersWater();
     }
 
-    LLWorld::getInstance()->updateWaterObjects();
+    if (LLWorld::instanceExists())
+    {
+        LLWorld::getInstance()->updateWaterObjects();
+    }
 
     return true;
 }
-- 
cgit v1.2.3


From 914a955ea2c32e574af64d01d8c8be8ce9d23504 Mon Sep 17 00:00:00 2001
From: Rye Cogtail <rye@lindenlab.com>
Date: Wed, 30 Oct 2024 16:06:32 -0400
Subject: Fix potential shift by -1 exponent in flexi object update

---
 indra/newview/llflexibleobject.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'indra/newview')

diff --git a/indra/newview/llflexibleobject.cpp b/indra/newview/llflexibleobject.cpp
index 7d098b2676..8897ad55e0 100644
--- a/indra/newview/llflexibleobject.cpp
+++ b/indra/newview/llflexibleobject.cpp
@@ -151,7 +151,6 @@ void LLVolumeImplFlexible::remapSections(LLFlexibleObjectSection *source, S32 so
 {
     S32 num_output_sections = 1<<dest_sections;
     LLVector3 scale = mVO->mDrawable->getScale();
-    F32 source_section_length = scale.mV[VZ] / (F32)(1<<source_sections);
     F32 section_length = scale.mV[VZ] / (F32)num_output_sections;
     if (source_sections == -1)
     {
@@ -183,6 +182,7 @@ void LLVolumeImplFlexible::remapSections(LLFlexibleObjectSection *source, S32 so
         // Iterate from right to left since it may be an in-place computation
         S32 step_shift = dest_sections-source_sections;
         S32 num_steps = 1<<step_shift;
+        F32 source_section_length = scale.mV[VZ] / (F32)(1<<source_sections);
         for (S32 section=num_output_sections-num_steps; section>=0; section -= num_steps)
         {
             LLFlexibleObjectSection *last_source_section = &source[section>>step_shift];
-- 
cgit v1.2.3


From d425c0a28ec05fe655d91e34e5ea0ca9f2c26dd7 Mon Sep 17 00:00:00 2001
From: Rye Cogtail <rye@lindenlab.com>
Date: Tue, 22 Oct 2024 17:22:27 -0400
Subject: Introduce NFDE file picker support for linux and SDL

---
 indra/newview/CMakeLists.txt   |   2 +
 indra/newview/lldirpicker.cpp  |  99 ++++++++-
 indra/newview/llfilepicker.cpp | 484 +++++++++++++++++++++++++++++++++++++++++
 indra/newview/llfilepicker.h   |   8 +
 4 files changed, 590 insertions(+), 3 deletions(-)

(limited to 'indra/newview')

diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 3bf01d252d..4d79138aaf 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -30,6 +30,7 @@ include(LLPrimitive)
 include(LLWindow)
 include(SDL2)
 include(NDOF)
+include(NFDE)
 include(NVAPI)
 include(OPENAL)
 include(OpenGL)
@@ -1944,6 +1945,7 @@ target_link_libraries(${VIEWER_BINARY_NAME}
         ll::ndof
         ll::tracy
         ll::openxr
+        ll::nfde
         )
 
 if( TARGET ll::intel_memops )
diff --git a/indra/newview/lldirpicker.cpp b/indra/newview/lldirpicker.cpp
index 17edca7ccb..0799d90ce8 100644
--- a/indra/newview/lldirpicker.cpp
+++ b/indra/newview/lldirpicker.cpp
@@ -45,6 +45,13 @@
 #include <shlobj.h>
 #endif
 
+#if LL_NFD
+#include "nfd.hpp"
+#if LL_USE_SDL_WINDOW
+#include "nfd_sdl2.h"
+#endif
+#endif
+
 //
 // Implementation
 //
@@ -65,7 +72,93 @@ bool LLDirPicker::check_local_file_access_enabled()
     return true;
 }
 
-#if LL_WINDOWS
+#if LL_NFD
+
+LLDirPicker::LLDirPicker() :
+    mFileName(nullptr),
+    mLocked(false)
+{
+    reset();
+}
+
+LLDirPicker::~LLDirPicker()
+{
+}
+
+
+void LLDirPicker::reset()
+{
+    mDir.clear();
+}
+
+bool LLDirPicker::getDir(std::string* filename, bool blocking)
+{
+    if( mLocked )
+    {
+        return false;
+    }
+
+    // if local file browsing is turned off, return without opening dialog
+    if ( check_local_file_access_enabled() == false )
+    {
+        return false;
+    }
+
+    bool success = false;
+
+    if (blocking)
+    {
+        // Modal, so pause agent
+        send_agent_pause();
+    }
+
+    // initialize NFD
+    NFD::Guard nfdGuard;
+
+    // auto-freeing memory
+    NFD::UniquePath outPath;
+
+    nfdwindowhandle_t windowHandle = nfdwindowhandle_t();
+#if LL_USE_SDL_WINDOW
+    if(!NFD_GetNativeWindowFromSDLWindow((SDL_Window*)gViewerWindow->getPlatformWindow(), &windowHandle))
+    {
+        windowHandle = nfdwindowhandle_t();
+    }
+#endif
+
+    // show the dialog
+    nfdresult_t result = NFD::PickFolder(outPath, nullptr, windowHandle);
+    if (result == NFD_OKAY)
+    {
+        mDir = std::string(outPath.get());
+        success = true;
+    }
+    else if (result == NFD_CANCEL)
+    {
+        LL_INFOS() << "User pressed cancel." << LL_ENDL;
+    }
+    else
+    {
+        LL_INFOS() << "DirPicker Error: " << NFD::GetError() << LL_ENDL;
+    }
+
+    if (blocking)
+    {
+        send_agent_resume();
+
+        // Account for the fact that the app has been stalled.
+        LLFrameTimer::updateFrameTime();
+    }
+
+    return success;
+}
+
+std::string LLDirPicker::getDirName()
+{
+    return mDir;
+}
+
+#elif LL_WINDOWS
 
 LLDirPicker::LLDirPicker() :
     mFileName(NULL),
@@ -286,7 +379,7 @@ std::queue<LLDirPickerThread*> LLDirPickerThread::sDeadQ;
 
 void LLDirPickerThread::getFile()
 {
-#if LL_WINDOWS
+#if (LL_WINDOWS && !LL_NFD) || (LL_LINUX && LL_NFD)
     start();
 #else
     run();
@@ -296,7 +389,7 @@ void LLDirPickerThread::getFile()
 //virtual
 void LLDirPickerThread::run()
 {
-#if LL_WINDOWS
+#if (LL_WINDOWS && !LL_NFD) || (LL_LINUX && LL_NFD)
     bool blocking = false;
 #else
     bool blocking = true; // modal
diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp
index 3639064cc4..5c356abc11 100644
--- a/indra/newview/llfilepicker.cpp
+++ b/indra/newview/llfilepicker.cpp
@@ -41,6 +41,13 @@
 #include "llhttpconstants.h"    // file picker uses some of thes constants on Linux
 #endif
 
+#if LL_NFD
+#include "nfd.hpp"
+#if LL_USE_SDL_WINDOW
+#include "nfd_sdl2.h"
+#endif
+#endif
+
 //
 // Globals
 //
@@ -165,7 +172,484 @@ void LLFilePicker::reset()
     mCurrentFile = 0;
 }
 
+#if LL_NFD
+std::vector<nfdfilteritem_t> LLFilePicker::setupFilter(ELoadFilter filter)
+{
+    std::vector<nfdfilteritem_t> filter_vec;
+    switch (filter)
+    {
+    case FFLOAD_EXE:
 #if LL_WINDOWS
+        filter_vec.emplace_back(nfdfilteritem_t{"Executables", "exe"});
+#endif
+        break;
+    case FFLOAD_ALL:
+        filter_vec.emplace_back(nfdfilteritem_t{"Executables", "exe"});
+        filter_vec.emplace_back(nfdfilteritem_t{"Sounds", "wav"});
+        filter_vec.emplace_back(nfdfilteritem_t{"Animations", "bvh,anim"});
+        filter_vec.emplace_back(nfdfilteritem_t{"Model files", "dae"});
+        filter_vec.emplace_back(nfdfilteritem_t{"RAW files", "raw"});
+        filter_vec.emplace_back(nfdfilteritem_t{"Script files (lsl)", "lsl"});
+        filter_vec.emplace_back(nfdfilteritem_t{"Dictionary files", "dic,xcu"});
+        filter_vec.emplace_back(nfdfilteritem_t{"GLTF Files", "gltf,glb"});
+        filter_vec.emplace_back(nfdfilteritem_t{"Script files (lua)", "lua"});
+        break;
+    case FFLOAD_WAV:
+        filter_vec.emplace_back(nfdfilteritem_t{"Sounds", "wav"});
+        break;
+    case FFLOAD_IMAGE:
+        filter_vec.emplace_back(nfdfilteritem_t{"Images", "tga,bmp,jpg,jpeg,png"});
+        break;
+    case FFLOAD_ANIM:
+        filter_vec.emplace_back(nfdfilteritem_t{"Animations", "bvh,anim"});
+        break;
+    case FFLOAD_GLTF:
+    case FFLOAD_MATERIAL:
+        filter_vec.emplace_back(nfdfilteritem_t{"GLTF Files", "gltf,glb"});
+        break;
+    case FFLOAD_COLLADA:
+        filter_vec.emplace_back(nfdfilteritem_t{"Scene", "dae"});
+        break;
+    case FFLOAD_XML:
+        filter_vec.emplace_back(nfdfilteritem_t{"XML files", "xml"});
+        break;
+    case FFLOAD_SLOBJECT:
+        filter_vec.emplace_back(nfdfilteritem_t{"Objects", "slobject"});
+        break;
+    case FFLOAD_RAW:
+        filter_vec.emplace_back(nfdfilteritem_t{"RAW files", "raw"});
+        break;
+    case FFLOAD_MODEL:
+        filter_vec.emplace_back(nfdfilteritem_t{"Model files", "dae"});
+        break;
+    case FFLOAD_HDRI:
+        filter_vec.emplace_back(nfdfilteritem_t{"EXR files", "exr"});
+    case FFLOAD_MATERIAL_TEXTURE:
+        filter_vec.emplace_back(nfdfilteritem_t{"GLTF Import", "gltf,glb,tga,bmp,jpg,jpeg,png"});
+        filter_vec.emplace_back(nfdfilteritem_t{"GLTF Files", "gltf,glb"});
+        filter_vec.emplace_back(nfdfilteritem_t{"Images", "tga,bmp,jpg,jpeg,png"});
+        break;
+    case FFLOAD_SCRIPT:
+        filter_vec.emplace_back(nfdfilteritem_t{"Script files", "lsl"});
+        break;
+    case FFLOAD_DICTIONARY:
+        filter_vec.emplace_back(nfdfilteritem_t{"Dictionary files", "dic,xcu"});
+        break;
+    case FFLOAD_LUA:
+        filter_vec.emplace_back(nfdfilteritem_t{"Script files", "lua"});
+        break;
+    default:
+        break;
+    }
+    return filter_vec;
+}
+
+bool LLFilePicker::getOpenFile(ELoadFilter filter, bool blocking)
+{
+    if( mLocked )
+    {
+        return false;
+    }
+    bool success = false;
+
+    // if local file browsing is turned off, return without opening dialog
+    if ( check_local_file_access_enabled() == false )
+    {
+        return false;
+    }
+
+    // initialize NFD
+    NFD::Guard nfdGuard;
+
+    // auto-freeing memory
+    NFD::UniquePath outPath;
+
+    // prepare filters for the dialog
+    auto filterItem = setupFilter(filter);
+    
+    nfdwindowhandle_t windowHandle = nfdwindowhandle_t();
+#if LL_USE_SDL_WINDOW
+    if(!NFD_GetNativeWindowFromSDLWindow((SDL_Window*)gViewerWindow->getPlatformWindow(), &windowHandle))
+    {
+        windowHandle = nfdwindowhandle_t();
+    }
+#endif
+
+    if (blocking)
+    {
+        // Modal, so pause agent
+        send_agent_pause();
+    }
+
+    reset();
+
+    // show the dialog
+    nfdresult_t result = NFD::OpenDialog(outPath, filterItem.data(), filterItem.size(), nullptr, windowHandle);
+    if (result == NFD_OKAY)
+    {
+        mFiles.push_back(outPath.get());
+        success = true;
+    }
+
+    if (blocking)
+    {
+        send_agent_resume();
+        // Account for the fact that the app has been stalled.
+        LLFrameTimer::updateFrameTime();
+    }
+
+    return success;
+}
+
+bool LLFilePicker::getOpenFileModeless(ELoadFilter filter,
+                                       void (*callback)(bool, std::vector<std::string> &, void*),
+                                       void *userdata)
+{
+    if( mLocked )
+        return false;
+
+    // if local file browsing is turned off, return without opening dialog
+    if ( check_local_file_access_enabled() == false )
+    {
+        return false;
+    }
+
+    reset();
+    LL_WARNS() << "NOT IMPLEMENTED" << LL_ENDL;
+    return false;
+}
+
+bool LLFilePicker::getMultipleOpenFiles(ELoadFilter filter, bool blocking)
+{
+    if( mLocked )
+    {
+        return false;
+    }
+    bool success = false;
+
+    // if local file browsing is turned off, return without opening dialog
+    if ( check_local_file_access_enabled() == false )
+    {
+        return false;
+    }
+
+    // initialize NFD
+    NFD::Guard nfdGuard;
+
+    auto filterItem = setupFilter(filter);
+
+    reset();
+
+    if (blocking)
+    {
+        // Modal, so pause agent
+        send_agent_pause();
+    }
+
+    nfdwindowhandle_t windowHandle = nfdwindowhandle_t();
+#if LL_USE_SDL_WINDOW
+    if(!NFD_GetNativeWindowFromSDLWindow((SDL_Window*)gViewerWindow->getPlatformWindow(), &windowHandle))
+    {
+        windowHandle = nfdwindowhandle_t();
+    }
+#endif
+
+    // auto-freeing memory
+    NFD::UniquePathSet outPaths;
+
+    // show the dialog
+    nfdresult_t result = NFD::OpenDialogMultiple(outPaths, filterItem.data(), filterItem.size(), nullptr, windowHandle);
+    if (result == NFD_OKAY)
+    {
+        LL_INFOS() << "Success!" << LL_ENDL;
+
+        nfdpathsetsize_t numPaths;
+        NFD::PathSet::Count(outPaths, numPaths);
+
+        nfdpathsetsize_t i;
+        for (i = 0; i < numPaths; ++i)
+        {
+            NFD::UniquePathSetPath path;
+            NFD::PathSet::GetPath(outPaths, i, path);
+            mFiles.push_back(path.get());
+            LL_INFOS() << "Path " << i << ": " << path.get() << LL_ENDL;
+        }
+        success = true;
+    }
+    else if (result == NFD_CANCEL)
+    {
+        LL_INFOS() << "User pressed cancel." << LL_ENDL;
+    }
+    else
+    {
+        LL_INFOS() << "Error: " << NFD::GetError() << LL_ENDL;
+    }
+
+    if (blocking)
+    {
+        send_agent_resume();
+
+        // Account for the fact that the app has been stalled.
+        LLFrameTimer::updateFrameTime();
+    }
+
+    return success;
+}
+
+bool LLFilePicker::getMultipleOpenFilesModeless(ELoadFilter filter,
+                                                void (*callback)(bool, std::vector<std::string> &, void*),
+                                                void *userdata )
+{
+    if( mLocked )
+        return false;
+
+    // if local file browsing is turned off, return without opening dialog
+    if ( check_local_file_access_enabled() == false )
+    {
+        return false;
+    }
+
+    reset();
+
+    LL_WARNS() << "NOT IMPLEMENTED" << LL_ENDL;
+    return false;
+}
+
+bool LLFilePicker::getSaveFile(ESaveFilter filter, const std::string& filename, bool blocking)
+{
+    if( mLocked )
+    {
+        return false;
+    }
+    bool success = false;
+
+    // if local file browsing is turned off, return without opening dialog
+    if ( check_local_file_access_enabled() == false )
+    {
+        return false;
+    }
+
+    // initialize NFD
+    NFD::Guard nfdGuard;
+
+    std::vector<nfdfilteritem_t> filter_vec;
+    std::string saved_filename = filename;
+    switch( filter )
+    {
+    case FFSAVE_ALL:
+        filter_vec.emplace_back(nfdfilteritem_t{"WAV Sounds", "wav"});
+        filter_vec.emplace_back(nfdfilteritem_t{"Targa, Bitmap Images", "tga,bmp"});
+        break;
+    case FFSAVE_WAV:
+        if (filename.empty())
+        {
+            saved_filename = "untitled.wav";
+        }
+        else
+        {
+            saved_filename += ".wav";
+        }
+        filter_vec.emplace_back(nfdfilteritem_t{"WAV Sounds", "wav"});
+        break;
+    case FFSAVE_TGA:
+        if (filename.empty())
+        {
+            saved_filename = "untitled.tga";
+        }
+        else
+        {
+            saved_filename += ".tga";
+        }
+        filter_vec.emplace_back(nfdfilteritem_t{"Targa Images", "tga"});
+        break;
+    case FFSAVE_BMP:
+        if (filename.empty())
+        {
+            saved_filename = "untitled.bmp";
+        }
+        else
+        {
+            saved_filename += ".bmp";
+        }
+        filter_vec.emplace_back(nfdfilteritem_t{"Bitmap Images", "bmp"});
+        break;
+    case FFSAVE_PNG:
+        if (filename.empty())
+        {
+            saved_filename = "untitled.png";
+        }
+        else
+        {
+            saved_filename += ".png";
+        }
+        filter_vec.emplace_back(nfdfilteritem_t{"PNG Images", "png"});
+        break;
+    case FFSAVE_TGAPNG:
+        if (filename.empty())
+        {
+            saved_filename = "untitled.png";
+        }
+        else
+        {
+            saved_filename += ".png";
+        }
+
+        filter_vec.emplace_back(nfdfilteritem_t{"PNG Images", "png"});
+        filter_vec.emplace_back(nfdfilteritem_t{"Targa Images", "tga"});
+        filter_vec.emplace_back(nfdfilteritem_t{"Jpeg Images", "jpg,jpeg"});
+        filter_vec.emplace_back(nfdfilteritem_t{"Jpeg2000 Images", "j2c"});
+        filter_vec.emplace_back(nfdfilteritem_t{"Bitmap Images", "bmp"});
+        break;
+    case FFSAVE_JPEG:
+        if (filename.empty())
+        {
+            saved_filename = "untitled.jpeg";
+        }
+        else
+        {
+            saved_filename += ".jpeg";
+        }
+        filter_vec.emplace_back(nfdfilteritem_t{"Jpeg Images", "jpg,jpeg"});
+        break;
+    case FFSAVE_AVI:
+        if (filename.empty())
+        {
+            saved_filename = "untitled.avi";
+        }
+        else
+        {
+            saved_filename += ".avi";
+        }
+        filter_vec.emplace_back(nfdfilteritem_t{"AVI Movie File", "avi"});
+        break;
+    case FFSAVE_ANIM:
+        if (filename.empty())
+        {
+            saved_filename = "untitled.xaf";
+        }
+        else
+        {
+            saved_filename += ".xaf";
+        }
+        filter_vec.emplace_back(nfdfilteritem_t{"XAF Anim File", "xaf"});
+        break;
+    case FFSAVE_XML:
+        if (filename.empty())
+        {
+            saved_filename = "untitled.xml";
+        }
+        else
+        {
+            saved_filename += ".xml";
+        }
+        filter_vec.emplace_back(nfdfilteritem_t{"XML File", "xml"});
+        break;
+    case FFSAVE_COLLADA:
+        if (filename.empty())
+        {
+            saved_filename = "untitled.collada";
+        }
+        else
+        {
+            saved_filename += ".collada";
+        }
+        filter_vec.emplace_back(nfdfilteritem_t{"COLLADA File", "collada"});
+        break;
+    case FFSAVE_RAW:
+        if (filename.empty())
+        {
+            saved_filename = "untitled.raw";
+        }
+        else
+        {
+            saved_filename += ".raw";
+        }
+        filter_vec.emplace_back(nfdfilteritem_t{"RAW files", "raw"});
+        break;
+    case FFSAVE_J2C:
+        if (filename.empty())
+        {
+            saved_filename = "untitled.j2c";
+        }
+        else
+        {
+            saved_filename += ".j2c";
+        }
+        filter_vec.emplace_back(nfdfilteritem_t{"Compressed Images", "j2c"});
+        break;
+    case FFSAVE_SCRIPT:
+        if (filename.empty())
+        {
+            saved_filename = "untitled.lsl";
+        }
+        else
+        {
+            saved_filename += ".lsl";
+        }
+        filter_vec.emplace_back(nfdfilteritem_t{"LSL Files", "lsl"});
+        break;
+    default:
+        return false;
+    }
+
+    nfdwindowhandle_t windowHandle = nfdwindowhandle_t();
+#if LL_USE_SDL_WINDOW
+    if(!NFD_GetNativeWindowFromSDLWindow((SDL_Window*)gViewerWindow->getPlatformWindow(), &windowHandle))
+    {
+        windowHandle = nfdwindowhandle_t();
+    }
+#endif
+
+    reset();
+
+    if (blocking)
+    {
+        // Modal, so pause agent
+        send_agent_pause();
+    }
+
+    {
+        NFD::UniquePath savePath;
+
+        // show the dialog
+        nfdresult_t result = NFD::SaveDialog(savePath, filter_vec.data(), filter_vec.size(), nullptr, saved_filename.c_str(), windowHandle);
+        if (result == NFD_OKAY) {
+            mFiles.push_back(savePath.get());
+            success = true;
+        }
+        gKeyboard->resetKeys();
+    }
+
+    if (blocking)
+    {
+        send_agent_resume();
+
+        // Account for the fact that the app has been stalled.
+        LLFrameTimer::updateFrameTime();
+    }
+
+    return success;
+}
+
+bool LLFilePicker::getSaveFileModeless(ESaveFilter filter,
+                                       const std::string& filename,
+                                       void (*callback)(bool, std::string&, void*),
+                                       void *userdata)
+{
+    if( mLocked )
+        return false;
+
+    // if local file browsing is turned off, return without opening dialog
+    if ( check_local_file_access_enabled() == false )
+    {
+        return false;
+    }
+
+    reset();
+    LL_WARNS() << "NOT IMPLEMENTED" << LL_ENDL;
+    return false;
+}
+#elif LL_WINDOWS
 
 bool LLFilePicker::setupFilter(ELoadFilter filter)
 {
diff --git a/indra/newview/llfilepicker.h b/indra/newview/llfilepicker.h
index 4d71a3b392..fadebca96c 100644
--- a/indra/newview/llfilepicker.h
+++ b/indra/newview/llfilepicker.h
@@ -54,6 +54,10 @@
 #include <commdlg.h>
 #endif
 
+#if LL_NFD
+#include "nfd.hpp"
+#endif
+
 class LLFilePicker
 {
 public:
@@ -151,6 +155,10 @@ private:
     // is enabled and if not, tidy up and indicate we're not allowed to do this.
     bool check_local_file_access_enabled();
 
+#if LL_NFD
+    std::vector<nfdfilteritem_t> setupFilter(ELoadFilter filter);
+#endif
+
 #if LL_WINDOWS
     OPENFILENAMEW mOFN;             // for open and save dialogs
     WCHAR mFilesW[FILENAME_BUFFER_SIZE];
-- 
cgit v1.2.3


From 90611c1d2ae7f86933bb6092ec6925302a1eb64c Mon Sep 17 00:00:00 2001
From: Rye Cogtail <rye@lindenlab.com>
Date: Tue, 22 Oct 2024 17:24:09 -0400
Subject: Remove dead GTK code

---
 indra/newview/llappviewer.cpp      |   4 -
 indra/newview/llappviewerlinux.cpp |   3 +-
 indra/newview/llfilepicker.cpp     | 489 -------------------------------------
 3 files changed, 2 insertions(+), 494 deletions(-)

(limited to 'indra/newview')

diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 46681af808..423fe2469a 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -273,10 +273,6 @@ using namespace LL;
 // define a self-registering event API object
 #include "llappviewerlistener.h"
 
-#if LL_LINUX && LL_GTK
-#include "glib.h"
-#endif // (LL_LINUX) && LL_GTK
-
 static LLAppViewerListener sAppViewerListener(LLAppViewer::instance);
 
 ////// Windows-specific includes to the bottom - nasty defines in these pollute the preprocessor
diff --git a/indra/newview/llappviewerlinux.cpp b/indra/newview/llappviewerlinux.cpp
index 7ce74649e2..3dbbda11f9 100644
--- a/indra/newview/llappviewerlinux.cpp
+++ b/indra/newview/llappviewerlinux.cpp
@@ -39,8 +39,9 @@
 #include "llfindlocale.h"
 
 #include <exception>
-
+#ifdef LL_GLIB
 #include <gio/gio.h>
+#endif
 #include <resolv.h>
 
 #if (__GLIBC__*1000 + __GLIBC_MINOR__) >= 2034
diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp
index 5c356abc11..8bdaea95c8 100644
--- a/indra/newview/llfilepicker.cpp
+++ b/indra/newview/llfilepicker.cpp
@@ -36,11 +36,6 @@
 #include "llviewercontrol.h"
 #include "llwindow.h"   // beforeDialog()
 
-#if LL_LINUX
-#include "llwindowsdl.h" // for some X/GTK utils to help with filepickers
-#include "llhttpconstants.h"    // file picker uses some of thes constants on Linux
-#endif
-
 #if LL_NFD
 #include "nfd.hpp"
 #if LL_USE_SDL_WINDOW
@@ -1588,488 +1583,6 @@ bool LLFilePicker::getSaveFileModeless(ESaveFilter filter,
 
 #elif LL_LINUX
 
-# if LL_GTK
-
-// static
-void LLFilePicker::add_to_selectedfiles(gpointer data, gpointer user_data)
-{
-    // We need to run g_filename_to_utf8 in the user's locale
-    std::string saved_locale(setlocale(LC_ALL, NULL));
-    setlocale(LC_ALL, "");
-
-    LLFilePicker* picker = (LLFilePicker*) user_data;
-    GError *error = NULL;
-    gchar* filename_utf8 = g_filename_to_utf8((gchar*)data,
-                          -1, NULL, NULL, &error);
-    if (error)
-    {
-        // *FIXME.
-        // This condition should really be notified to the user, e.g.
-        // through a message box.  Just logging it is inappropriate.
-
-        // g_filename_display_name is ideal, but >= glib 2.6, so:
-        // a hand-rolled hacky makeASCII which disallows control chars
-        std::string display_name;
-        for (const gchar *str = (const gchar *)data; *str; str++)
-        {
-            display_name += (char)((*str >= 0x20 && *str <= 0x7E) ? *str : '?');
-        }
-        LL_WARNS() << "g_filename_to_utf8 failed on \"" << display_name << "\": " << error->message << LL_ENDL;
-    }
-
-    if (filename_utf8)
-    {
-        picker->mFiles.push_back(std::string(filename_utf8));
-        LL_DEBUGS() << "ADDED FILE " << filename_utf8 << LL_ENDL;
-        g_free(filename_utf8);
-    }
-
-    setlocale(LC_ALL, saved_locale.c_str());
-}
-
-// static
-void LLFilePicker::chooser_responder(GtkWidget *widget, gint response, gpointer user_data)
-{
-    LLFilePicker* picker = (LLFilePicker*)user_data;
-
-    LL_DEBUGS() << "GTK DIALOG RESPONSE " << response << LL_ENDL;
-
-    if (response == GTK_RESPONSE_ACCEPT)
-    {
-        GSList *file_list = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(widget));
-        g_slist_foreach(file_list, (GFunc)add_to_selectedfiles, user_data);
-        g_slist_foreach(file_list, (GFunc)g_free, NULL);
-        g_slist_free (file_list);
-    }
-
-    // let's save the extension of the last added file(considering current filter)
-    GtkFileFilter *gfilter = gtk_file_chooser_get_filter(GTK_FILE_CHOOSER(widget));
-    if(gfilter)
-    {
-        std::string filter = gtk_file_filter_get_name(gfilter);
-
-        if(filter == LLTrans::getString("png_image_files"))
-        {
-            picker->mCurrentExtension = ".png";
-        }
-        else if(filter == LLTrans::getString("targa_image_files"))
-        {
-            picker->mCurrentExtension = ".tga";
-        }
-    }
-
-    // set the default path for this usage context.
-    const char* cur_folder = gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(widget));
-    if (cur_folder != NULL)
-    {
-        picker->mContextToPathMap[picker->mCurContextName] = cur_folder;
-    }
-
-    gtk_widget_destroy(widget);
-    gtk_main_quit();
-}
-
-
-GtkWindow* LLFilePicker::buildFilePicker(bool is_save, bool is_folder, std::string context)
-{
-#ifndef LL_MESA_HEADLESS
-    if (LLWindowSDL::ll_try_gtk_init())
-    {
-        GtkWidget *win = NULL;
-        GtkFileChooserAction pickertype =
-            is_save?
-            (is_folder?
-             GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER :
-             GTK_FILE_CHOOSER_ACTION_SAVE) :
-            (is_folder?
-             GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER :
-             GTK_FILE_CHOOSER_ACTION_OPEN);
-
-        win = gtk_file_chooser_dialog_new(NULL, NULL,
-                          pickertype,
-                          GTK_STOCK_CANCEL,
-                           GTK_RESPONSE_CANCEL,
-                          is_folder ?
-                          GTK_STOCK_APPLY :
-                          (is_save ?
-                           GTK_STOCK_SAVE :
-                           GTK_STOCK_OPEN),
-                           GTK_RESPONSE_ACCEPT,
-                          (gchar *)NULL);
-        mCurContextName = context;
-
-        // get the default path for this usage context if it's been
-        // seen before.
-        std::map<std::string,std::string>::iterator
-            this_path = mContextToPathMap.find(context);
-        if (this_path != mContextToPathMap.end())
-        {
-            gtk_file_chooser_set_current_folder
-                (GTK_FILE_CHOOSER(win),
-                 this_path->second.c_str());
-        }
-
-#  if LL_X11
-        // Make GTK tell the window manager to associate this
-        // dialog with our non-GTK raw X11 window, which should try
-        // to keep it on top etc.
-        Window XWindowID = LLWindowSDL::get_SDL_XWindowID();
-        if (None != XWindowID)
-        {
-            gtk_widget_realize(GTK_WIDGET(win)); // so we can get its gdkwin
-            GdkWindow *gdkwin = gdk_window_foreign_new(XWindowID);
-            gdk_window_set_transient_for(GTK_WIDGET(win)->window,
-                             gdkwin);
-        }
-        else
-        {
-            LL_WARNS() << "Hmm, couldn't get xwid to use for transient." << LL_ENDL;
-        }
-#  endif //LL_X11
-
-        g_signal_connect (GTK_FILE_CHOOSER(win),
-                  "response",
-                  G_CALLBACK(LLFilePicker::chooser_responder),
-                  this);
-
-        gtk_window_set_modal(GTK_WINDOW(win), TRUE);
-
-        /* GTK 2.6: if (is_folder)
-            gtk_file_chooser_set_show_hidden(GTK_FILE_CHOOSER(win),
-            TRUE); */
-
-        return GTK_WINDOW(win);
-    }
-    else
-    {
-        return NULL;
-    }
-#else
-    return NULL;
-#endif //LL_MESA_HEADLESS
-}
-
-static void add_common_filters_to_gtkchooser(GtkFileFilter *gfilter,
-                         GtkWindow *picker,
-                         std::string filtername)
-{
-    gtk_file_filter_set_name(gfilter, filtername.c_str());
-    gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(picker),
-                    gfilter);
-    GtkFileFilter *allfilter = gtk_file_filter_new();
-    gtk_file_filter_add_pattern(allfilter, "*");
-    gtk_file_filter_set_name(allfilter, LLTrans::getString("all_files").c_str());
-    gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(picker), allfilter);
-    gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(picker), gfilter);
-}
-
-static std::string add_simple_pattern_filter_to_gtkchooser(GtkWindow *picker,
-                               std::string pattern,
-                               std::string filtername)
-{
-    GtkFileFilter *gfilter = gtk_file_filter_new();
-    gtk_file_filter_add_pattern(gfilter, pattern.c_str());
-    add_common_filters_to_gtkchooser(gfilter, picker, filtername);
-    return filtername;
-}
-
-static std::string add_simple_mime_filter_to_gtkchooser(GtkWindow *picker,
-                            std::string mime,
-                            std::string filtername)
-{
-    GtkFileFilter *gfilter = gtk_file_filter_new();
-    gtk_file_filter_add_mime_type(gfilter, mime.c_str());
-    add_common_filters_to_gtkchooser(gfilter, picker, filtername);
-    return filtername;
-}
-
-static std::string add_wav_filter_to_gtkchooser(GtkWindow *picker)
-{
-    return add_simple_mime_filter_to_gtkchooser(picker,  "audio/x-wav",
-                            LLTrans::getString("sound_files") + " (*.wav)");
-}
-
-static std::string add_anim_filter_to_gtkchooser(GtkWindow *picker)
-{
-    GtkFileFilter *gfilter = gtk_file_filter_new();
-    gtk_file_filter_add_pattern(gfilter, "*.bvh");
-    gtk_file_filter_add_pattern(gfilter, "*.anim");
-    std::string filtername = LLTrans::getString("animation_files") + " (*.bvh; *.anim)";
-    add_common_filters_to_gtkchooser(gfilter, picker, filtername);
-    return filtername;
-}
-
-static std::string add_xml_filter_to_gtkchooser(GtkWindow *picker)
-{
-    return add_simple_pattern_filter_to_gtkchooser(picker,  "*.xml",
-                                                   LLTrans::getString("xml_files") + " (*.xml)");
-}
-
-static std::string add_collada_filter_to_gtkchooser(GtkWindow *picker)
-{
-    return add_simple_pattern_filter_to_gtkchooser(picker,  "*.dae",
-                               LLTrans::getString("scene_files") + " (*.dae)");
-}
-
-static std::string add_imageload_filter_to_gtkchooser(GtkWindow *picker)
-{
-    GtkFileFilter *gfilter = gtk_file_filter_new();
-    gtk_file_filter_add_pattern(gfilter, "*.tga");
-    gtk_file_filter_add_mime_type(gfilter, HTTP_CONTENT_IMAGE_JPEG.c_str());
-    gtk_file_filter_add_mime_type(gfilter, HTTP_CONTENT_IMAGE_PNG.c_str());
-    gtk_file_filter_add_mime_type(gfilter, HTTP_CONTENT_IMAGE_BMP.c_str());
-    std::string filtername = LLTrans::getString("image_files") + " (*.tga; *.bmp; *.jpg; *.png)";
-    add_common_filters_to_gtkchooser(gfilter, picker, filtername);
-    return filtername;
-}
-
-static std::string add_script_filter_to_gtkchooser(GtkWindow *picker)
-{
-    return add_simple_mime_filter_to_gtkchooser(picker,  HTTP_CONTENT_TEXT_PLAIN,
-                            LLTrans::getString("script_files") + " (*.lsl)");
-}
-
-static std::string add_dictionary_filter_to_gtkchooser(GtkWindow *picker)
-{
-    return add_simple_mime_filter_to_gtkchooser(picker, HTTP_CONTENT_TEXT_PLAIN,
-                            LLTrans::getString("dictionary_files") + " (*.dic; *.xcu)");
-}
-
-static std::string add_save_texture_filter_to_gtkchooser(GtkWindow *picker)
-{
-    GtkFileFilter *gfilter_tga = gtk_file_filter_new();
-    GtkFileFilter *gfilter_png = gtk_file_filter_new();
-
-    gtk_file_filter_add_pattern(gfilter_tga, "*.tga");
-    gtk_file_filter_add_mime_type(gfilter_png, "image/png");
-    std::string caption = LLTrans::getString("save_texture_image_files") + " (*.tga; *.png)";
-    gtk_file_filter_set_name(gfilter_tga, LLTrans::getString("targa_image_files").c_str());
-    gtk_file_filter_set_name(gfilter_png, LLTrans::getString("png_image_files").c_str());
-
-    gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(picker),
-                    gfilter_png);
-    gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(picker),
-                    gfilter_tga);
-    return caption;
-}
-
-bool LLFilePicker::getSaveFile( ESaveFilter filter, const std::string& filename, bool blocking )
-{
-    bool rtn = false;
-
-    // if local file browsing is turned off, return without opening dialog
-    if (!check_local_file_access_enabled())
-    {
-        return false;
-    }
-
-    gViewerWindow->getWindow()->beforeDialog();
-
-    reset();
-
-    GtkWindow* picker = buildFilePicker(true, false, "savefile");
-
-    if (picker)
-    {
-        std::string suggest_name = "untitled";
-        std::string suggest_ext = "";
-        std::string caption = LLTrans::getString("save_file_verb") + " ";
-        switch (filter)
-        {
-        case FFSAVE_WAV:
-            caption += add_wav_filter_to_gtkchooser(picker);
-            suggest_ext = ".wav";
-            break;
-        case FFSAVE_TGA:
-            caption += add_simple_pattern_filter_to_gtkchooser
-                (picker, "*.tga", LLTrans::getString("targa_image_files") + " (*.tga)");
-            suggest_ext = ".tga";
-            break;
-        case FFSAVE_BMP:
-            caption += add_simple_mime_filter_to_gtkchooser
-                (picker, HTTP_CONTENT_IMAGE_BMP, LLTrans::getString("bitmap_image_files") + " (*.bmp)");
-            suggest_ext = ".bmp";
-            break;
-        case FFSAVE_PNG:
-            caption += add_simple_mime_filter_to_gtkchooser
-                (picker, "image/png", LLTrans::getString("png_image_files") + " (*.png)");
-            suggest_ext = ".png";
-            break;
-        case FFSAVE_TGAPNG:
-            caption += add_save_texture_filter_to_gtkchooser(picker);
-            suggest_ext = ".png";
-            break;
-        case FFSAVE_AVI:
-            caption += add_simple_mime_filter_to_gtkchooser
-                (picker, "video/x-msvideo",
-                 LLTrans::getString("avi_movie_file") + " (*.avi)");
-            suggest_ext = ".avi";
-            break;
-        case FFSAVE_ANIM:
-            caption += add_simple_pattern_filter_to_gtkchooser
-                (picker, "*.xaf", LLTrans::getString("xaf_animation_file") + " (*.xaf)");
-            suggest_ext = ".xaf";
-            break;
-        case FFSAVE_XML:
-            caption += add_simple_pattern_filter_to_gtkchooser
-                (picker, "*.xml", LLTrans::getString("xml_file") + " (*.xml)");
-            suggest_ext = ".xml";
-            break;
-        case FFSAVE_RAW:
-            caption += add_simple_pattern_filter_to_gtkchooser
-                (picker, "*.raw", LLTrans::getString("raw_file") + " (*.raw)");
-            suggest_ext = ".raw";
-            break;
-        case FFSAVE_J2C:
-            // *TODO: Should this be 'image/j2c' ?
-            caption += add_simple_mime_filter_to_gtkchooser
-                (picker, "images/jp2",
-                 LLTrans::getString("compressed_image_files") + " (*.j2c)");
-            suggest_ext = ".j2c";
-            break;
-        case FFSAVE_SCRIPT:
-            caption += add_script_filter_to_gtkchooser(picker);
-            suggest_ext = ".lsl";
-            break;
-        default:;
-            break;
-        }
-
-        gtk_window_set_title(GTK_WINDOW(picker), caption.c_str());
-
-        if (filename.empty())
-        {
-            suggest_name += suggest_ext;
-
-            gtk_file_chooser_set_current_name
-                (GTK_FILE_CHOOSER(picker),
-                 suggest_name.c_str());
-        }
-        else
-        {
-            gtk_file_chooser_set_current_name
-                (GTK_FILE_CHOOSER(picker), filename.c_str());
-        }
-
-        gtk_widget_show_all(GTK_WIDGET(picker));
-
-        gtk_main();
-
-        rtn = (getFileCount() == 1);
-
-        if(rtn && filter == FFSAVE_TGAPNG)
-        {
-            std::string selected_file = mFiles.back();
-            mFiles.pop_back();
-            mFiles.push_back(selected_file + mCurrentExtension);
-        }
-    }
-
-    gViewerWindow->getWindow()->afterDialog();
-
-    return rtn;
-}
-
-bool LLFilePicker::getOpenFile( ELoadFilter filter, bool blocking )
-{
-    bool rtn = false;
-
-    // if local file browsing is turned off, return without opening dialog
-    if (!check_local_file_access_enabled())
-    {
-        return false;
-    }
-
-    gViewerWindow->getWindow()->beforeDialog();
-
-    reset();
-
-    GtkWindow* picker = buildFilePicker(false, false, "openfile");
-
-    if (picker)
-    {
-        std::string caption = LLTrans::getString("load_file_verb") + " ";
-        std::string filtername = "";
-        switch (filter)
-        {
-        case FFLOAD_WAV:
-            filtername = add_wav_filter_to_gtkchooser(picker);
-            break;
-        case FFLOAD_ANIM:
-            filtername = add_anim_filter_to_gtkchooser(picker);
-            break;
-        case FFLOAD_XML:
-            filtername = add_xml_filter_to_gtkchooser(picker);
-            break;
-        case FFLOAD_GLTF:
-            filtername = dead_code_should_blow_up_here(picker);
-            break;
-        case FFLOAD_COLLADA:
-            filtername = add_collada_filter_to_gtkchooser(picker);
-            break;
-        case FFLOAD_IMAGE:
-            filtername = add_imageload_filter_to_gtkchooser(picker);
-            break;
-        case FFLOAD_SCRIPT:
-            filtername = add_script_filter_to_gtkchooser(picker);
-            break;
-        case FFLOAD_DICTIONARY:
-            filtername = add_dictionary_filter_to_gtkchooser(picker);
-            break;
-        default:;
-            break;
-        }
-
-        caption += filtername;
-
-        gtk_window_set_title(GTK_WINDOW(picker), caption.c_str());
-
-        gtk_widget_show_all(GTK_WIDGET(picker));
-        gtk_main();
-
-        rtn = (getFileCount() == 1);
-    }
-
-    gViewerWindow->getWindow()->afterDialog();
-
-    return rtn;
-}
-
-bool LLFilePicker::getMultipleOpenFiles( ELoadFilter filter, bool blocking)
-{
-    bool rtn = false;
-
-    // if local file browsing is turned off, return without opening dialog
-    if (!check_local_file_access_enabled())
-    {
-        return false;
-    }
-
-    gViewerWindow->getWindow()->beforeDialog();
-
-    reset();
-
-    GtkWindow* picker = buildFilePicker(false, false, "openfile");
-
-    if (picker)
-    {
-        gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER(picker),
-                              TRUE);
-
-        gtk_window_set_title(GTK_WINDOW(picker), LLTrans::getString("load_files").c_str());
-
-        gtk_widget_show_all(GTK_WIDGET(picker));
-        gtk_main();
-        rtn = !mFiles.empty();
-    }
-
-    gViewerWindow->getWindow()->afterDialog();
-
-    return rtn;
-}
-
-# else // LL_GTK
-
 // Hacky stubs designed to facilitate fake getSaveFile and getOpenFile with
 // static results, when we don't have a real filepicker.
 
@@ -2157,8 +1670,6 @@ bool LLFilePicker::getMultipleOpenFilesModeless(ELoadFilter filter,
     return false;
 }
 
-#endif // LL_GTK
-
 #else // not implemented
 
 bool LLFilePicker::getSaveFile( ESaveFilter filter, const std::string& filename )
-- 
cgit v1.2.3


From 24e49d9b908969dbfac67364952ec94ef99a6023 Mon Sep 17 00:00:00 2001
From: Rye <rye@lindenlab.com>
Date: Wed, 23 Oct 2024 09:56:25 -0700
Subject: Fix broken viewer under XWayland and whitespace

---
 indra/newview/llfilepicker.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'indra/newview')

diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp
index 8bdaea95c8..760f5a700e 100644
--- a/indra/newview/llfilepicker.cpp
+++ b/indra/newview/llfilepicker.cpp
@@ -261,7 +261,7 @@ bool LLFilePicker::getOpenFile(ELoadFilter filter, bool blocking)
 
     // prepare filters for the dialog
     auto filterItem = setupFilter(filter);
-    
+
     nfdwindowhandle_t windowHandle = nfdwindowhandle_t();
 #if LL_USE_SDL_WINDOW
     if(!NFD_GetNativeWindowFromSDLWindow((SDL_Window*)gViewerWindow->getPlatformWindow(), &windowHandle))
-- 
cgit v1.2.3


From 3fc5545f8a00fec5b15938df1394f664b8396f01 Mon Sep 17 00:00:00 2001
From: Rye Cogtail <rye@lindenlab.com>
Date: Thu, 31 Oct 2024 01:51:43 -0400
Subject: Fix various bugs in NFD impl and fix usage on windows

---
 indra/newview/lldirpicker.cpp      |  6 ++-
 indra/newview/llfilepicker.cpp     | 85 +++++++-------------------------------
 indra/newview/llfilepicker.h       |  4 +-
 indra/newview/llviewermenufile.cpp |  6 +--
 4 files changed, 25 insertions(+), 76 deletions(-)

(limited to 'indra/newview')

diff --git a/indra/newview/lldirpicker.cpp b/indra/newview/lldirpicker.cpp
index 0799d90ce8..032433434d 100644
--- a/indra/newview/lldirpicker.cpp
+++ b/indra/newview/lldirpicker.cpp
@@ -124,6 +124,8 @@ bool LLDirPicker::getDir(std::string* filename, bool blocking)
     {
         windowHandle = nfdwindowhandle_t();
     }
+#elif LL_WINDOWS
+    windowHandle = { NFD_WINDOW_HANDLE_TYPE_WINDOWS, gViewerWindow->getWindow()->getPlatformWindow() };
 #endif
 
     // show the dialog
@@ -379,7 +381,7 @@ std::queue<LLDirPickerThread*> LLDirPickerThread::sDeadQ;
 
 void LLDirPickerThread::getFile()
 {
-#if (LL_WINDOWS && !LL_NFD) || (LL_LINUX && LL_NFD)
+#if LL_WINDOWS || (LL_NFD && !LL_DARWIN)
     start();
 #else
     run();
@@ -389,7 +391,7 @@ void LLDirPickerThread::getFile()
 //virtual
 void LLDirPickerThread::run()
 {
-#if (LL_WINDOWS && !LL_NFD) || (LL_LINUX && LL_NFD)
+#if LL_WINDOWS || (LL_NFD && !LL_DARWIN)
     bool blocking = false;
 #else
     bool blocking = true; // modal
diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp
index 760f5a700e..ca0b58b611 100644
--- a/indra/newview/llfilepicker.cpp
+++ b/indra/newview/llfilepicker.cpp
@@ -82,7 +82,7 @@ LLFilePicker::LLFilePicker()
 {
     reset();
 
-#if LL_WINDOWS
+#if LL_WINDOWS && !LL_NFD
     mOFN.lStructSize = sizeof(OPENFILENAMEW);
     mOFN.hwndOwner = NULL;  // Set later
     mOFN.hInstance = NULL;
@@ -179,15 +179,7 @@ std::vector<nfdfilteritem_t> LLFilePicker::setupFilter(ELoadFilter filter)
 #endif
         break;
     case FFLOAD_ALL:
-        filter_vec.emplace_back(nfdfilteritem_t{"Executables", "exe"});
-        filter_vec.emplace_back(nfdfilteritem_t{"Sounds", "wav"});
-        filter_vec.emplace_back(nfdfilteritem_t{"Animations", "bvh,anim"});
-        filter_vec.emplace_back(nfdfilteritem_t{"Model files", "dae"});
-        filter_vec.emplace_back(nfdfilteritem_t{"RAW files", "raw"});
-        filter_vec.emplace_back(nfdfilteritem_t{"Script files (lsl)", "lsl"});
-        filter_vec.emplace_back(nfdfilteritem_t{"Dictionary files", "dic,xcu"});
-        filter_vec.emplace_back(nfdfilteritem_t{"GLTF Files", "gltf,glb"});
-        filter_vec.emplace_back(nfdfilteritem_t{"Script files (lua)", "lua"});
+        // Empty to allow picking all files by default
         break;
     case FFLOAD_WAV:
         filter_vec.emplace_back(nfdfilteritem_t{"Sounds", "wav"});
@@ -219,19 +211,20 @@ std::vector<nfdfilteritem_t> LLFilePicker::setupFilter(ELoadFilter filter)
         break;
     case FFLOAD_HDRI:
         filter_vec.emplace_back(nfdfilteritem_t{"EXR files", "exr"});
+        break;
     case FFLOAD_MATERIAL_TEXTURE:
         filter_vec.emplace_back(nfdfilteritem_t{"GLTF Import", "gltf,glb,tga,bmp,jpg,jpeg,png"});
         filter_vec.emplace_back(nfdfilteritem_t{"GLTF Files", "gltf,glb"});
         filter_vec.emplace_back(nfdfilteritem_t{"Images", "tga,bmp,jpg,jpeg,png"});
         break;
     case FFLOAD_SCRIPT:
-        filter_vec.emplace_back(nfdfilteritem_t{"Script files", "lsl"});
+        filter_vec.emplace_back(nfdfilteritem_t{"Script files (*.lsl)", "lsl"});
         break;
     case FFLOAD_DICTIONARY:
         filter_vec.emplace_back(nfdfilteritem_t{"Dictionary files", "dic,xcu"});
         break;
     case FFLOAD_LUA:
-        filter_vec.emplace_back(nfdfilteritem_t{"Script files", "lua"});
+        filter_vec.emplace_back(nfdfilteritem_t{"Script files (*.lua)", "lua"});
         break;
     default:
         break;
@@ -268,6 +261,8 @@ bool LLFilePicker::getOpenFile(ELoadFilter filter, bool blocking)
     {
         windowHandle = nfdwindowhandle_t();
     }
+#elif LL_WINDOWS
+    windowHandle = { NFD_WINDOW_HANDLE_TYPE_WINDOWS, gViewerWindow->getWindow()->getPlatformWindow() };
 #endif
 
     if (blocking)
@@ -279,7 +274,7 @@ bool LLFilePicker::getOpenFile(ELoadFilter filter, bool blocking)
     reset();
 
     // show the dialog
-    nfdresult_t result = NFD::OpenDialog(outPath, filterItem.data(), filterItem.size(), nullptr, windowHandle);
+    nfdresult_t result = NFD::OpenDialog(outPath, filterItem.data(), narrow(filterItem.size()), nullptr, windowHandle);
     if (result == NFD_OKAY)
     {
         mFiles.push_back(outPath.get());
@@ -347,13 +342,15 @@ bool LLFilePicker::getMultipleOpenFiles(ELoadFilter filter, bool blocking)
     {
         windowHandle = nfdwindowhandle_t();
     }
+#elif LL_WINDOWS
+    windowHandle = { NFD_WINDOW_HANDLE_TYPE_WINDOWS, gViewerWindow->getWindow()->getPlatformWindow() };
 #endif
 
     // auto-freeing memory
     NFD::UniquePathSet outPaths;
 
     // show the dialog
-    nfdresult_t result = NFD::OpenDialogMultiple(outPaths, filterItem.data(), filterItem.size(), nullptr, windowHandle);
+    nfdresult_t result = NFD::OpenDialogMultiple(outPaths, filterItem.data(), narrow(filterItem.size()), nullptr, windowHandle);
     if (result == NFD_OKAY)
     {
         LL_INFOS() << "Success!" << LL_ENDL;
@@ -440,10 +437,6 @@ bool LLFilePicker::getSaveFile(ESaveFilter filter, const std::string& filename,
         {
             saved_filename = "untitled.wav";
         }
-        else
-        {
-            saved_filename += ".wav";
-        }
         filter_vec.emplace_back(nfdfilteritem_t{"WAV Sounds", "wav"});
         break;
     case FFSAVE_TGA:
@@ -451,10 +444,6 @@ bool LLFilePicker::getSaveFile(ESaveFilter filter, const std::string& filename,
         {
             saved_filename = "untitled.tga";
         }
-        else
-        {
-            saved_filename += ".tga";
-        }
         filter_vec.emplace_back(nfdfilteritem_t{"Targa Images", "tga"});
         break;
     case FFSAVE_BMP:
@@ -462,10 +451,6 @@ bool LLFilePicker::getSaveFile(ESaveFilter filter, const std::string& filename,
         {
             saved_filename = "untitled.bmp";
         }
-        else
-        {
-            saved_filename += ".bmp";
-        }
         filter_vec.emplace_back(nfdfilteritem_t{"Bitmap Images", "bmp"});
         break;
     case FFSAVE_PNG:
@@ -473,10 +458,6 @@ bool LLFilePicker::getSaveFile(ESaveFilter filter, const std::string& filename,
         {
             saved_filename = "untitled.png";
         }
-        else
-        {
-            saved_filename += ".png";
-        }
         filter_vec.emplace_back(nfdfilteritem_t{"PNG Images", "png"});
         break;
     case FFSAVE_TGAPNG:
@@ -484,14 +465,10 @@ bool LLFilePicker::getSaveFile(ESaveFilter filter, const std::string& filename,
         {
             saved_filename = "untitled.png";
         }
-        else
-        {
-            saved_filename += ".png";
-        }
 
         filter_vec.emplace_back(nfdfilteritem_t{"PNG Images", "png"});
         filter_vec.emplace_back(nfdfilteritem_t{"Targa Images", "tga"});
-        filter_vec.emplace_back(nfdfilteritem_t{"Jpeg Images", "jpg,jpeg"});
+        filter_vec.emplace_back(nfdfilteritem_t{"JPEG Images", "jpg,jpeg"});
         filter_vec.emplace_back(nfdfilteritem_t{"Jpeg2000 Images", "j2c"});
         filter_vec.emplace_back(nfdfilteritem_t{"Bitmap Images", "bmp"});
         break;
@@ -500,21 +477,13 @@ bool LLFilePicker::getSaveFile(ESaveFilter filter, const std::string& filename,
         {
             saved_filename = "untitled.jpeg";
         }
-        else
-        {
-            saved_filename += ".jpeg";
-        }
-        filter_vec.emplace_back(nfdfilteritem_t{"Jpeg Images", "jpg,jpeg"});
+        filter_vec.emplace_back(nfdfilteritem_t{"JPEG Images", "jpg,jpeg"});
         break;
     case FFSAVE_AVI:
         if (filename.empty())
         {
             saved_filename = "untitled.avi";
         }
-        else
-        {
-            saved_filename += ".avi";
-        }
         filter_vec.emplace_back(nfdfilteritem_t{"AVI Movie File", "avi"});
         break;
     case FFSAVE_ANIM:
@@ -522,10 +491,6 @@ bool LLFilePicker::getSaveFile(ESaveFilter filter, const std::string& filename,
         {
             saved_filename = "untitled.xaf";
         }
-        else
-        {
-            saved_filename += ".xaf";
-        }
         filter_vec.emplace_back(nfdfilteritem_t{"XAF Anim File", "xaf"});
         break;
     case FFSAVE_XML:
@@ -533,10 +498,6 @@ bool LLFilePicker::getSaveFile(ESaveFilter filter, const std::string& filename,
         {
             saved_filename = "untitled.xml";
         }
-        else
-        {
-            saved_filename += ".xml";
-        }
         filter_vec.emplace_back(nfdfilteritem_t{"XML File", "xml"});
         break;
     case FFSAVE_COLLADA:
@@ -544,10 +505,6 @@ bool LLFilePicker::getSaveFile(ESaveFilter filter, const std::string& filename,
         {
             saved_filename = "untitled.collada";
         }
-        else
-        {
-            saved_filename += ".collada";
-        }
         filter_vec.emplace_back(nfdfilteritem_t{"COLLADA File", "collada"});
         break;
     case FFSAVE_RAW:
@@ -555,10 +512,6 @@ bool LLFilePicker::getSaveFile(ESaveFilter filter, const std::string& filename,
         {
             saved_filename = "untitled.raw";
         }
-        else
-        {
-            saved_filename += ".raw";
-        }
         filter_vec.emplace_back(nfdfilteritem_t{"RAW files", "raw"});
         break;
     case FFSAVE_J2C:
@@ -566,10 +519,6 @@ bool LLFilePicker::getSaveFile(ESaveFilter filter, const std::string& filename,
         {
             saved_filename = "untitled.j2c";
         }
-        else
-        {
-            saved_filename += ".j2c";
-        }
         filter_vec.emplace_back(nfdfilteritem_t{"Compressed Images", "j2c"});
         break;
     case FFSAVE_SCRIPT:
@@ -577,10 +526,6 @@ bool LLFilePicker::getSaveFile(ESaveFilter filter, const std::string& filename,
         {
             saved_filename = "untitled.lsl";
         }
-        else
-        {
-            saved_filename += ".lsl";
-        }
         filter_vec.emplace_back(nfdfilteritem_t{"LSL Files", "lsl"});
         break;
     default:
@@ -593,6 +538,8 @@ bool LLFilePicker::getSaveFile(ESaveFilter filter, const std::string& filename,
     {
         windowHandle = nfdwindowhandle_t();
     }
+#elif LL_WINDOWS
+    windowHandle = { NFD_WINDOW_HANDLE_TYPE_WINDOWS, gViewerWindow->getWindow()->getPlatformWindow() };
 #endif
 
     reset();
@@ -607,7 +554,7 @@ bool LLFilePicker::getSaveFile(ESaveFilter filter, const std::string& filename,
         NFD::UniquePath savePath;
 
         // show the dialog
-        nfdresult_t result = NFD::SaveDialog(savePath, filter_vec.data(), filter_vec.size(), nullptr, saved_filename.c_str(), windowHandle);
+        nfdresult_t result = NFD::SaveDialog(savePath, filter_vec.data(), narrow(filter_vec.size()), nullptr, saved_filename.c_str(), windowHandle);
         if (result == NFD_OKAY) {
             mFiles.push_back(savePath.get());
             success = true;
diff --git a/indra/newview/llfilepicker.h b/indra/newview/llfilepicker.h
index fadebca96c..8c89570174 100644
--- a/indra/newview/llfilepicker.h
+++ b/indra/newview/llfilepicker.h
@@ -159,14 +159,14 @@ private:
     std::vector<nfdfilteritem_t> setupFilter(ELoadFilter filter);
 #endif
 
-#if LL_WINDOWS
+#if LL_WINDOWS && !LL_NFD
     OPENFILENAMEW mOFN;             // for open and save dialogs
     WCHAR mFilesW[FILENAME_BUFFER_SIZE];
 
     bool setupFilter(ELoadFilter filter);
 #endif
 
-#if LL_DARWIN
+#if LL_DARWIN && !LL_NFD
     S32 mPickOptions;
     std::vector<std::string> mFileVector;
 
diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp
index 2a871a24af..14c9c53a9c 100644
--- a/indra/newview/llviewermenufile.cpp
+++ b/indra/newview/llviewermenufile.cpp
@@ -137,10 +137,10 @@ std::queue<LLFilePickerThread*> LLFilePickerThread::sDeadQ;
 
 void LLFilePickerThread::getFile()
 {
-#if LL_WINDOWS
+#if LL_WINDOWS || (LL_NFD && !LL_DARWIN)
     // Todo: get rid of LLFilePickerThread and make this modeless
     start();
-#elif LL_DARWIN
+#elif LL_DARWIN && !LL_NFD
     runModeless();
 #else
     run();
@@ -150,7 +150,7 @@ void LLFilePickerThread::getFile()
 //virtual
 void LLFilePickerThread::run()
 {
-#if LL_WINDOWS
+#if LL_WINDOWS || (LL_NFD && !LL_DARWIN)
     bool blocking = false;
 #else
     bool blocking = true; // modal
-- 
cgit v1.2.3


From 559e2c1bb223e82f29a00a0cf1556e56073dde3a Mon Sep 17 00:00:00 2001
From: Maxim Nikolenko <maximnproductengine@lindenlab.com>
Date: Thu, 31 Oct 2024 13:38:41 +0200
Subject: =?UTF-8?q?#2962=20allow=20the=20script=20to=20=E2=80=98wait?=
 =?UTF-8?q?=E2=80=99=20for=20a=20teleport=20finished/failed=20event?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 indra/newview/llviewerparcelmgr.cpp                | 20 ++++++++++++++++
 indra/newview/llviewerparcelmgr.h                  |  5 ++++
 indra/newview/scripts/lua/frame_profile.lua        |  2 ++
 .../newview/scripts/lua/require/teleport_util.lua  | 28 ++++++++++++++++++++++
 4 files changed, 55 insertions(+)
 create mode 100644 indra/newview/scripts/lua/require/teleport_util.lua

(limited to 'indra/newview')

diff --git a/indra/newview/llviewerparcelmgr.cpp b/indra/newview/llviewerparcelmgr.cpp
index 8c24b2438b..d92341eb96 100644
--- a/indra/newview/llviewerparcelmgr.cpp
+++ b/indra/newview/llviewerparcelmgr.cpp
@@ -1750,6 +1750,8 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use
                 {
                     instance->mTeleportFinishedSignal(instance->mTeleportInProgressPosition, false);
                 }
+                instance->postTeleportFinished(instance->mTeleportWithinRegion);
+                instance->mTeleportWithinRegion = false;
             }
             parcel->setParcelEnvironmentVersion(parcel_environment_version);
             LL_DEBUGS("ENVIRONMENT") << "Parcel environment version is " << parcel->getParcelEnvironmentVersion() << LL_ENDL;
@@ -2709,6 +2711,8 @@ void LLViewerParcelMgr::onTeleportFinished(bool local, const LLVector3d& new_pos
         // Local teleport. We already have the agent parcel data.
         // Emit the signal immediately.
         getInstance()->mTeleportFinishedSignal(new_pos, local);
+
+        postTeleportFinished(true);
     }
     else
     {
@@ -2717,12 +2721,14 @@ void LLViewerParcelMgr::onTeleportFinished(bool local, const LLVector3d& new_pos
         // Let's wait for the update and then emit the signal.
         mTeleportInProgressPosition = new_pos;
         mTeleportInProgress = true;
+        mTeleportWithinRegion = local;
     }
 }
 
 void LLViewerParcelMgr::onTeleportFailed()
 {
     mTeleportFailedSignal();
+    LLEventPumps::instance().obtain("LLTeleport").post(llsd::map("success", false));
 }
 
 bool  LLViewerParcelMgr::getTeleportInProgress()
@@ -2730,3 +2736,17 @@ bool  LLViewerParcelMgr::getTeleportInProgress()
     return mTeleportInProgress // case where parcel data arrives after teleport
         || gAgent.getTeleportState() > LLAgent::TELEPORT_NONE; // For LOCAL, no mTeleportInProgress
 }
+
+void LLViewerParcelMgr::postTeleportFinished(bool local)
+{
+    auto post = []() { LLEventPumps::instance().obtain("LLTeleport").post(llsd::map("success", true)); };
+    if (local)
+    {
+        static LLCachedControl<F32> teleport_local_delay(gSavedSettings, "TeleportLocalDelay");
+        LL::Timers::instance().scheduleAfter(post, teleport_local_delay + 0.5f);
+    }
+    else
+    {
+        post();
+    }
+}
diff --git a/indra/newview/llviewerparcelmgr.h b/indra/newview/llviewerparcelmgr.h
index 974ea39359..4d54593c1e 100644
--- a/indra/newview/llviewerparcelmgr.h
+++ b/indra/newview/llviewerparcelmgr.h
@@ -295,6 +295,8 @@ public:
     void onTeleportFailed();
     bool getTeleportInProgress();
 
+    void postTeleportFinished(bool local);
+
     static bool isParcelOwnedByAgent(const LLParcel* parcelp, U64 group_proxy_power);
     static bool isParcelModifiableByAgent(const LLParcel* parcelp, U64 group_proxy_power);
 
@@ -344,8 +346,11 @@ private:
 
     std::vector<LLParcelObserver*> mObservers;
 
+    // Used to communicate between onTeleportFinished() and processParcelProperties()
     bool                        mTeleportInProgress;
+    bool                        mTeleportWithinRegion{ false };
     LLVector3d                  mTeleportInProgressPosition;
+
     teleport_finished_signal_t  mTeleportFinishedSignal;
     teleport_failed_signal_t    mTeleportFailedSignal;
 
diff --git a/indra/newview/scripts/lua/frame_profile.lua b/indra/newview/scripts/lua/frame_profile.lua
index 3c6353ff68..4d0874f55e 100644
--- a/indra/newview/scripts/lua/frame_profile.lua
+++ b/indra/newview/scripts/lua/frame_profile.lua
@@ -4,11 +4,13 @@ LLAgent = require 'LLAgent'
 startup = require 'startup'
 Timer = (require 'timers').Timer
 UI = require 'UI'
+teleport_util = require('teleport_util')
 
 startup.wait('STATE_STARTED')
 
 -- teleport to http://maps.secondlife.com/secondlife/Bug%20Island/220/224/27
 print(LLAgent.teleport{regionname='Bug Island', x=220, y=224, z=27})
+--teleport_util.wait()
 Timer(10, 'wait')
 LLAgent.setCamera{camera_pos={220, 224, 26}, camera_locked=true,
                   focus_pos ={228, 232, 26}, focus_locked=true}
diff --git a/indra/newview/scripts/lua/require/teleport_util.lua b/indra/newview/scripts/lua/require/teleport_util.lua
new file mode 100644
index 0000000000..8a46768e54
--- /dev/null
+++ b/indra/newview/scripts/lua/require/teleport_util.lua
@@ -0,0 +1,28 @@
+local leap = require 'leap'
+
+local teleport_util = {}
+
+local teleport_pump = 'LLTeleport'
+local waitfor = leap.WaitFor(0, teleport_pump)
+function waitfor:filter(pump, data)
+    if pump == self.name then
+        return data
+    end
+end
+
+function waitfor:process(data)
+    teleport_util._success = data.success
+    leap.WaitFor.process(self, data)
+end
+
+leap.request(leap.cmdpump(),
+             {op='listen', source=teleport_pump, listener='teleport.lua', tweak=true})
+
+function teleport_util.wait()
+    while teleport_util._success == nil do
+      local item = waitfor:wait()
+    end
+    return teleport_util._success
+end
+
+return teleport_util
-- 
cgit v1.2.3


From 8dfc1d0447bae8afd1567abf85ecbec9b43790a0 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Wed, 30 Oct 2024 20:32:22 +0200
Subject: viewer#2653 LOD textures weren't taking callback discard into account

---
 indra/newview/llviewertexture.cpp | 6 ++++++
 1 file changed, 6 insertions(+)

(limited to 'indra/newview')

diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index 7feb807c62..82fefde0a7 100644
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -1691,6 +1691,7 @@ void LLViewerFetchedTexture::processTextureStats()
         if(mDesiredDiscardLevel > mMinDesiredDiscardLevel)//need to load more
         {
             mDesiredDiscardLevel = llmin(mDesiredDiscardLevel, mMinDesiredDiscardLevel);
+            mDesiredDiscardLevel = llmin(mDesiredDiscardLevel, (S32)mLoadedCallbackDesiredDiscardLevel);
             mFullyLoaded = false;
         }
         //setDebugText("fully loaded");
@@ -1740,6 +1741,7 @@ void LLViewerFetchedTexture::processTextureStats()
                                                      log((F32)mFullHeight / mKnownDrawHeight) / log_2);
                 mDesiredDiscardLevel =  llclamp(mDesiredDiscardLevel, (S8)0, (S8)getMaxDiscardLevel());
                 mDesiredDiscardLevel = llmin(mDesiredDiscardLevel, mMinDesiredDiscardLevel);
+                mDesiredDiscardLevel = llmin(mDesiredDiscardLevel, (S32)mLoadedCallbackDesiredDiscardLevel);
             }
             mKnownDrawSizeChanged = false;
 
@@ -2464,6 +2466,7 @@ bool LLViewerFetchedTexture::doLoadedCallbacks()
     if (mIsRawImageValid)
     {
         // If we have an existing raw image, we have a baseline for the raw and auxiliary quality levels.
+        current_raw_discard = mRawDiscardLevel;
         best_raw_discard = llmin(best_raw_discard, mRawDiscardLevel);
         best_aux_discard = llmin(best_aux_discard, mRawDiscardLevel); // We always decode the aux when we decode the base raw
         current_aux_discard = llmin(current_aux_discard, best_aux_discard);
@@ -2922,10 +2925,12 @@ void LLViewerLODTexture::processTextureStats()
     {
         // If the image has not been significantly visible in a while, we don't want it
         mDesiredDiscardLevel = llmin(mMinDesiredDiscardLevel, (S8)(MAX_DISCARD_LEVEL + 1));
+        mDesiredDiscardLevel = llmin(mDesiredDiscardLevel, (S32)mLoadedCallbackDesiredDiscardLevel);
     }
     else if (!mFullWidth  || !mFullHeight)
     {
         mDesiredDiscardLevel =  getMaxDiscardLevel();
+        mDesiredDiscardLevel = llmin(mDesiredDiscardLevel, (S32)mLoadedCallbackDesiredDiscardLevel);
     }
     else
     {
@@ -2995,6 +3000,7 @@ void LLViewerLODTexture::processTextureStats()
             // stop requesting more
             mDesiredDiscardLevel = current_discard;
         }
+        mDesiredDiscardLevel = llmin(mDesiredDiscardLevel, (S32)mLoadedCallbackDesiredDiscardLevel);
     }
 
     if(mForceToSaveRawImage && mDesiredSavedRawDiscardLevel >= 0)
-- 
cgit v1.2.3


From 34e909b6bfbd99d3df481a2f6e566a0b58a15905 Mon Sep 17 00:00:00 2001
From: cosmic-linden <111533034+cosmic-linden@users.noreply.github.com>
Date: Thu, 31 Oct 2024 11:28:13 -0700
Subject: secondlife/viewer#2768: Partial fix for PBR texture animations
 stopping. May also fix some Blinn-Phong texture animations. (#2971)

---
 indra/newview/llvovolume.cpp | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

(limited to 'indra/newview')

diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 31f1bbcc21..39728b6818 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -786,7 +786,24 @@ void LLVOVolume::updateTextureVirtualSize(bool forced)
         LLFace* face = mDrawable->getFace(i);
         if (!face) continue;
         const LLTextureEntry *te = face->getTextureEntry();
-        LLViewerTexture *imagep = face->getTexture();
+        LLViewerTexture *imagep = nullptr;
+        U32 ch_min;
+        U32 ch_max;
+        if (!te->getGLTFRenderMaterial())
+        {
+            ch_min = LLRender::DIFFUSE_MAP;
+            ch_max = LLRender::SPECULAR_MAP;
+        }
+        else
+        {
+            ch_min = LLRender::BASECOLOR_MAP;
+            ch_max = LLRender::EMISSIVE_MAP;
+        }
+        for (U32 ch = ch_min; (!imagep && ch <= ch_max); ++ch)
+        {
+            // Get _a_ non-null texture if possible (usually diffuse/basecolor, but could be something else)
+            imagep = face->getTexture(ch);
+        }
         if (!imagep || !te ||
             face->mExtents[0].equals3(face->mExtents[1]))
         {
-- 
cgit v1.2.3


From 3a81065af528f95814a801e289527db41597b408 Mon Sep 17 00:00:00 2001
From: Rye <rye@lindenlab.com>
Date: Mon, 14 Oct 2024 22:14:25 -0700
Subject: Enable precompiled headers for all platforms

---
 indra/newview/CMakeLists.txt | 20 ++++++++++++++++----
 1 file changed, 16 insertions(+), 4 deletions(-)

(limited to 'indra/newview')

diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 4d79138aaf..95740c0cc1 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -1439,6 +1439,18 @@ if (DARWIN)
   LIST(APPEND viewer_SOURCE_FILES llfilepicker_mac.mm)
   LIST(APPEND viewer_HEADER_FILES llfilepicker_mac.h)
 
+  set_source_files_properties(
+    llappviewermacosx-objc.mm
+    PROPERTIES
+    SKIP_PRECOMPILE_HEADERS TRUE
+  )
+
+  set_source_files_properties(
+    llfilepicker_mac.mm
+    PROPERTIES
+    SKIP_PRECOMPILE_HEADERS TRUE
+  )
+
   # This should be compiled with the viewer.
   LIST(APPEND viewer_SOURCE_FILES llappdelegate-objc.mm)
   set_source_files_properties(
@@ -1734,6 +1746,10 @@ list(APPEND EVENT_HOST_SCRIPTS ${EVENT_HOST_SCRIPT_GLOB_LIST})
 set(PACKAGE ON CACHE BOOL
     "Add a package target that builds an installer package.")
 
+if(USE_PRECOMPILED_HEADERS)
+  target_precompile_headers( ${VIEWER_BINARY_NAME} PRIVATE llviewerprecompiledheaders.h )
+endif(USE_PRECOMPILED_HEADERS)
+
 if (WINDOWS)
     set_target_properties(${VIEWER_BINARY_NAME}
         PROPERTIES
@@ -1744,10 +1760,6 @@ if (WINDOWS)
         )
     target_compile_options(${VIEWER_BINARY_NAME} PRIVATE /bigobj)
 
-    if(USE_PRECOMPILED_HEADERS)
-       target_precompile_headers( ${VIEWER_BINARY_NAME} PRIVATE llviewerprecompiledheaders.h )
-    endif(USE_PRECOMPILED_HEADERS)
-
     # If adding a file to viewer_manifest.py in the WindowsManifest.construct() method, be sure to add the dependency
     # here.
     # *NOTE:Mani - This is a crappy hack to have important dependencies for the viewer_manifest copy action
-- 
cgit v1.2.3


From 0ae72a24eb07bbb2cb15402c6b85b53ab50a6d7a Mon Sep 17 00:00:00 2001
From: Rye <rye@lindenlab.com>
Date: Mon, 14 Oct 2024 22:15:43 -0700
Subject: Try to parallelize xcode builds further and add more headers to PCH
 to reduce build time

---
 indra/newview/CMakeLists.txt               |  1 +
 indra/newview/gltf/common.h                |  2 --
 indra/newview/llinventoryitemslist.cpp     |  2 +-
 indra/newview/llviewerprecompiledheaders.h | 47 +++++++++++++++++++++++++++---
 4 files changed, 45 insertions(+), 7 deletions(-)

(limited to 'indra/newview')

diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 95740c0cc1..b599358aa3 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -1456,6 +1456,7 @@ if (DARWIN)
   set_source_files_properties(
     llappdelegate-objc.mm
     PROPERTIES
+    SKIP_PRECOMPILE_HEADERS TRUE
     COMPILE_DEFINITIONS "${VIEWER_CHANNEL_VERSION_DEFINES}"
     # BugsplatMac is a module, imported with @import. That language feature
     # demands these -f switches.
diff --git a/indra/newview/gltf/common.h b/indra/newview/gltf/common.h
index 742daff715..8cf3f1dff7 100644
--- a/indra/newview/gltf/common.h
+++ b/indra/newview/gltf/common.h
@@ -26,8 +26,6 @@
  * $/LicenseInfo$
  */
 
-#define GLM_ENABLE_EXPERIMENTAL 1
-
 #include "glm/vec2.hpp"
 #include "glm/vec3.hpp"
 #include "glm/vec4.hpp"
diff --git a/indra/newview/llinventoryitemslist.cpp b/indra/newview/llinventoryitemslist.cpp
index 9e936eee5b..2e0669fc38 100644
--- a/indra/newview/llinventoryitemslist.cpp
+++ b/indra/newview/llinventoryitemslist.cpp
@@ -99,7 +99,7 @@ void LLInventoryItemsList::updateSelection()
 
     for(std::vector<LLSD>::const_iterator cur_id_it = cur.begin(); cur_id_it != cur.end() && !mSelectTheseIDs.empty(); ++cur_id_it)
     {
-        uuid_vec_t::iterator select_ids_it = std::find(mSelectTheseIDs.begin(), mSelectTheseIDs.end(), *cur_id_it);
+        uuid_vec_t::iterator select_ids_it = std::find(mSelectTheseIDs.begin(), mSelectTheseIDs.end(), cur_id_it->asUUID());
         if(select_ids_it != mSelectTheseIDs.end())
         {
             selectItemByUUID(*select_ids_it);
diff --git a/indra/newview/llviewerprecompiledheaders.h b/indra/newview/llviewerprecompiledheaders.h
index a857887247..5700d8b278 100644
--- a/indra/newview/llviewerprecompiledheaders.h
+++ b/indra/newview/llviewerprecompiledheaders.h
@@ -29,22 +29,28 @@
 #ifndef LL_LLVIEWERPRECOMPILEDHEADERS_H
 #define LL_LLVIEWERPRECOMPILEDHEADERS_H
 
-#include "llwin32headers.h"
-
 // This file MUST be the first one included by each .cpp file
 // in viewer.
 // It is used to precompile headers for improved build speed.
 
 #include "linden_common.h"
 
+#include "llwin32headers.h"
+
 #include <algorithm>
 #include <deque>
 #include <functional>
+#include <list>
 #include <map>
 #include <set>
 #include <vector>
+#include <string_view>
+#include <unordered_map>
+#include <unordered_set>
 
 // Library headers from llcommon project:
+#include "apply.h"
+#include "function_types.h"
 #include "indra_constants.h"
 #include "llinitparam.h"
 #include "llapp.h"
@@ -54,8 +60,10 @@
 #include "llerror.h"
 #include "llfasttimer.h"
 #include "llframetimer.h"
+#include "llinstancetracker.h"
 #include "llpointer.h"
 #include "llprocessor.h"
+#include "llrand.h"
 #include "llrefcount.h"
 #include "llsafehandle.h"
 #include "llsd.h"
@@ -65,11 +73,13 @@
 #include "llstring.h"
 #include "llsys.h"
 #include "lltimer.h"
+#include "lluuid.h"
 #include "stdtypes.h"
 #include "u64.h"
 
 // Library includes from llmath project
 #include "llmath.h"
+#include "llbbox.h"
 #include "llbboxlocal.h"
 #include "llcamera.h"
 #include "llcoord.h"
@@ -77,9 +87,7 @@
 #include "llcrc.h"
 #include "llplane.h"
 #include "llquantize.h"
-#include "llrand.h"
 #include "llrect.h"
-#include "lluuid.h"
 #include "m3math.h"
 #include "m4math.h"
 #include "llquaternion.h"
@@ -91,11 +99,42 @@
 #include "v4coloru.h"
 #include "v4math.h"
 #include "xform.h"
+#include "llvector4a.h"
+#include "llmatrix4a.h"
+#include "lloctree.h"
+#include "llvolume.h"
 
+// Library includes from llfilesystem project
 #include "lldir.h"
 
 // Library includes from llmessage project
+#include "llassetstorage.h"
+#include "llavatarnamecache.h"
 #include "llcachename.h"
+#include "llcorehttputil.h"
+
+// Library includes from llrender project
+#include "llgl.h"
+#include "llrender.h"
+
+// Library includes from llrender project
+#include "llcharacter.h"
+
+// Library includes from llui project
+#include "llnotifications.h"
+#include "llpanel.h"
+#include "llfloater.h"
+
+#include <boost/function.hpp>
+#include <boost/signals2.hpp>
+#include <boost/unordered_set.hpp>
+#include <boost/unordered_map.hpp>
+#include <boost/json.hpp>
 
+#include "glm/glm.hpp"
+#include "glm/gtc/type_ptr.hpp"
+#include "glm/ext/quaternion_float.hpp"
+#include "glm/gtx/quaternion.hpp"
+#include "glm/gtx/matrix_decompose.hpp"
 
 #endif
-- 
cgit v1.2.3


From 76ff2e0bbc6a209addfa0f427459e7877d87938d Mon Sep 17 00:00:00 2001
From: Maxim Nikolenko <maximnproductengine@lindenlab.com>
Date: Fri, 1 Nov 2024 17:04:37 +0200
Subject: #2938 show confirmation before closing Conference chat

---
 indra/newview/llfloaterimsession.cpp               |  2 +-
 indra/newview/llfloaterimsessiontab.cpp            | 18 ++++++++++++++++
 indra/newview/llfloaterimsessiontab.h              | 24 ++++++++++++----------
 .../newview/skins/default/xui/en/notifications.xml | 16 +++++++++++++++
 4 files changed, 48 insertions(+), 12 deletions(-)

(limited to 'indra/newview')

diff --git a/indra/newview/llfloaterimsession.cpp b/indra/newview/llfloaterimsession.cpp
index e85aac3810..84e51fe6c5 100644
--- a/indra/newview/llfloaterimsession.cpp
+++ b/indra/newview/llfloaterimsession.cpp
@@ -142,7 +142,7 @@ void LLFloaterIMSession::onClickCloseBtn(bool app_qutting)
 {
     if (app_qutting)
     {
-        LLFloaterIMSessionTab::onClickCloseBtn();
+        LLFloaterIMSessionTab::onClickCloseBtn(app_qutting);
         return;
     }
 
diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp
index 0855a628fb..4b1d3da630 100644
--- a/indra/newview/llfloaterimsessiontab.cpp
+++ b/indra/newview/llfloaterimsessiontab.cpp
@@ -47,6 +47,7 @@
 #include "llfloaterimnearbychat.h"
 #include "llgroupiconctrl.h"
 #include "lllayoutstack.h"
+#include "llnotificationsutil.h"
 #include "llpanelemojicomplete.h"
 #include "lltoolbarview.h"
 
@@ -1440,3 +1441,20 @@ bool LLFloaterIMSessionTab::handleKeyHere(KEY key, MASK mask )
     }
     return handled;
 }
+
+void LLFloaterIMSessionTab::onClickCloseBtn(bool app_quitting)
+{
+    bool is_ad_hoc = (mSession ? mSession->isAdHocSessionType() : false);
+    if (is_ad_hoc && !app_quitting)
+    {
+        LLNotificationsUtil::add("ConfirmLeaveAdhoc", LLSD(), LLSD(), [this](const LLSD& notification, const LLSD& response)
+        {
+            if (0 == LLNotificationsUtil::getSelectedOption(notification, response))
+                closeFloater();
+        });
+    }
+    else
+    {
+        closeFloater();
+    }
+}
diff --git a/indra/newview/llfloaterimsessiontab.h b/indra/newview/llfloaterimsessiontab.h
index 890c920bbe..4087ced73d 100644
--- a/indra/newview/llfloaterimsessiontab.h
+++ b/indra/newview/llfloaterimsessiontab.h
@@ -76,13 +76,15 @@ public:
     bool isNearbyChat() {return mIsNearbyChat;}
 
     // LLFloater overrides
-    /*virtual*/ void onOpen(const LLSD& key);
-    /*virtual*/ bool postBuild();
-    /*virtual*/ void draw();
-    /*virtual*/ void setVisible(bool visible);
-    /*virtual*/ void setFocus(bool focus);
-    /*virtual*/ void closeFloater(bool app_quitting = false);
-    /*virtual*/ void deleteAllChildren();
+    /*virtual*/ void onOpen(const LLSD& key) override;
+    /*virtual*/ bool postBuild() override;
+    /*virtual*/ void draw() override;
+    /*virtual*/ void setVisible(bool visible) override;
+    /*virtual*/ void setFocus(bool focus) override;
+    /*virtual*/ void closeFloater(bool app_quitting = false) override;
+    /*virtual*/ void deleteAllChildren() override;
+
+    virtual void onClickCloseBtn(bool app_quitting = false) override;
 
     // Handle the left hand participant list widgets
     void addConversationViewParticipant(LLConversationItem* item, bool update_view = true);
@@ -98,7 +100,7 @@ public:
     virtual void updateMessages() {}
     LLConversationItem* getCurSelectedViewModelItem();
     void forceReshape();
-    virtual bool handleKeyHere( KEY key, MASK mask );
+    virtual bool handleKeyHere( KEY key, MASK mask ) override;
     bool isMessagePaneExpanded(){return mMessagePaneExpanded;}
     void setMessagePaneExpanded(bool expanded){mMessagePaneExpanded = expanded;}
     void restoreFloater();
@@ -139,8 +141,8 @@ protected:
     virtual void enableDisableCallBtn();
 
     // process focus events to set a currently active session
-    /* virtual */ void onFocusReceived();
-    /* virtual */ void onFocusLost();
+    /* virtual */ void onFocusReceived() override;
+    /* virtual */ void onFocusLost() override;
 
     // prepare chat's params and out one message to chatHistory
     void appendMessage(const LLChat& chat, const LLSD& args = LLSD());
@@ -212,7 +214,7 @@ private:
     void getSelectedUUIDs(uuid_vec_t& selected_uuids);
 
     /// Refreshes the floater at a constant rate.
-    virtual void refresh() = 0;
+    virtual void refresh() override = 0;
 
     /**
      * Adjusts chat history height to fit vertically with input chat field
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index cbc0f7ceae..526be61207 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -9595,6 +9595,22 @@ Are you sure you want to leave this call?
     </usetemplate>
   </notification>
 
+  <notification
+   icon="alertmodal.tga"
+   name="ConfirmLeaveAdhoc"
+   type="alertmodal">
+Are you sure you want to leave this conference chat?
+    <tag>confirm</tag>
+    <tag>voice</tag>
+    <usetemplate
+     ignoretext="Confirm before I leave conference chat"
+     name="okcancelignore"
+     notext="No"
+     yestext="Yes">
+      <unique/>
+    </usetemplate>
+  </notification>
+
   <notification
    icon="alertmodal.tga"
    name="ConfirmMuteAll"
-- 
cgit v1.2.3


From afa1305c337186941317b5ee29881de92cf86814 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Fri, 1 Nov 2024 22:19:37 +0200
Subject: viewer#3001 Fix doubletap run

---
 indra/newview/llviewerinput.cpp | 3 +++
 1 file changed, 3 insertions(+)

(limited to 'indra/newview')

diff --git a/indra/newview/llviewerinput.cpp b/indra/newview/llviewerinput.cpp
index 66042128f2..12c0335c4f 100644
--- a/indra/newview/llviewerinput.cpp
+++ b/indra/newview/llviewerinput.cpp
@@ -158,6 +158,9 @@ static void agent_handle_doubletap_run(EKeystate s, LLAgent::EDoubleTapRunMode m
 
 static void agent_push_forwardbackward( EKeystate s, S32 direction, LLAgent::EDoubleTapRunMode mode )
 {
+    agent_handle_doubletap_run(s, mode);
+    if (KEYSTATE_UP == s) return;
+
     F32 time = gKeyboard->getCurKeyElapsedTime();
     S32 frame_count = ll_round(gKeyboard->getCurKeyElapsedFrameCount());
 
-- 
cgit v1.2.3


From 8b7825280004ef694ebcf177329319c51d721462 Mon Sep 17 00:00:00 2001
From: Rye <rye@lindenlab.com>
Date: Sun, 3 Nov 2024 10:37:11 -0500
Subject: Fix crash from null texture entry during updateTextureVirtualSize

---
 indra/newview/llvovolume.cpp | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

(limited to 'indra/newview')

diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 39728b6818..6d33f411ed 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -784,8 +784,10 @@ void LLVOVolume::updateTextureVirtualSize(bool forced)
     for (S32 i = 0; i < num_faces; i++)
     {
         LLFace* face = mDrawable->getFace(i);
-        if (!face) continue;
+        if (!face || face->mExtents[0].equals3(face->mExtents[1])) continue;
         const LLTextureEntry *te = face->getTextureEntry();
+        if (!te) continue;
+
         LLViewerTexture *imagep = nullptr;
         U32 ch_min;
         U32 ch_max;
@@ -804,8 +806,7 @@ void LLVOVolume::updateTextureVirtualSize(bool forced)
             // Get _a_ non-null texture if possible (usually diffuse/basecolor, but could be something else)
             imagep = face->getTexture(ch);
         }
-        if (!imagep || !te ||
-            face->mExtents[0].equals3(face->mExtents[1]))
+        if (!imagep)
         {
             continue;
         }
-- 
cgit v1.2.3


From a895f4e02052729092359ee31a40ee0e4e3ed961 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Fri, 1 Nov 2024 23:49:50 +0200
Subject: viewer#2999 Fix debug text flicker

---
 indra/newview/llhudnametag.cpp | 19 -------------------
 indra/newview/llhudtext.cpp    | 14 --------------
 indra/newview/llhudtext.h      |  1 -
 3 files changed, 34 deletions(-)

(limited to 'indra/newview')

diff --git a/indra/newview/llhudnametag.cpp b/indra/newview/llhudnametag.cpp
index 66130a2744..d56d3a66c5 100644
--- a/indra/newview/llhudnametag.cpp
+++ b/indra/newview/llhudnametag.cpp
@@ -291,15 +291,6 @@ void LLHUDNameTag::renderText()
     LLVector3 render_position = mPositionAgent
             + (x_pixel_vec * screen_offset.mV[VX])
             + (y_pixel_vec * screen_offset.mV[VY]);
-    bool reset_buffers = false;
-    const F32 treshold = 0.000001f;
-    if (abs(mLastRenderPosition.mV[VX] - render_position.mV[VX]) > treshold
-        || abs(mLastRenderPosition.mV[VY] - render_position.mV[VY]) > treshold
-        || abs(mLastRenderPosition.mV[VZ] - render_position.mV[VZ]) > treshold)
-    {
-        reset_buffers = true;
-        mLastRenderPosition = render_position;
-    }
 
     LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
     LLRect screen_rect;
@@ -323,11 +314,6 @@ void LLHUDNameTag::renderText()
         for(std::vector<LLHUDTextSegment>::iterator segment_iter = mLabelSegments.begin();
             segment_iter != mLabelSegments.end(); ++segment_iter )
         {
-            if (reset_buffers)
-            {
-                segment_iter->mFontBufferLabel.reset();
-            }
-
             // Label segments use default font
             const LLFontGL* fontp = (segment_iter->mStyle == LLFontGL::BOLD) ? mBoldFontp : mFontp;
             y_offset -= fontp->getLineHeight();
@@ -365,11 +351,6 @@ void LLHUDNameTag::renderText()
         for (std::vector<LLHUDTextSegment>::iterator segment_iter = mTextSegments.begin() + start_segment;
              segment_iter != mTextSegments.end(); ++segment_iter )
         {
-            if (reset_buffers)
-            {
-                segment_iter->mFontBufferText.reset();
-            }
-
             const LLFontGL* fontp = segment_iter->mFont;
             y_offset -= fontp->getLineHeight();
             y_offset -= LINE_PADDING;
diff --git a/indra/newview/llhudtext.cpp b/indra/newview/llhudtext.cpp
index 818474a0cb..593eaa76ca 100644
--- a/indra/newview/llhudtext.cpp
+++ b/indra/newview/llhudtext.cpp
@@ -185,15 +185,6 @@ void LLHUDText::renderText()
     LLVector3 render_position = mPositionAgent
             + (x_pixel_vec * screen_offset.mV[VX])
             + (y_pixel_vec * screen_offset.mV[VY]);
-    bool reset_buffers = false;
-    const F32 treshold = 0.000001f;
-    if (abs(mLastRenderPosition.mV[VX] - render_position.mV[VX]) > treshold
-        || abs(mLastRenderPosition.mV[VY] - render_position.mV[VY]) > treshold
-        || abs(mLastRenderPosition.mV[VZ] - render_position.mV[VZ]) > treshold)
-    {
-        reset_buffers = true;
-        mLastRenderPosition = render_position;
-    }
 
     F32 y_offset = (F32)mOffsetY;
 
@@ -217,11 +208,6 @@ void LLHUDText::renderText()
         for (std::vector<LLHUDTextSegment>::iterator segment_iter = mTextSegments.begin() + start_segment;
              segment_iter != mTextSegments.end(); ++segment_iter )
         {
-            if (reset_buffers)
-            {
-                segment_iter->mFontBufferText.reset();
-            }
-
             const LLFontGL* fontp = segment_iter->mFont;
             y_offset -= fontp->getLineHeight() - 1; // correction factor to match legacy font metrics
 
diff --git a/indra/newview/llhudtext.h b/indra/newview/llhudtext.h
index 4c850e2d91..390b7dd16e 100644
--- a/indra/newview/llhudtext.h
+++ b/indra/newview/llhudtext.h
@@ -67,7 +67,6 @@ protected:
         LLColor4                mColor;
         LLFontGL::StyleFlags    mStyle;
         const LLFontGL*         mFont;
-        LLFontVertexBuffer      mFontBuffer;
         LLFontVertexBuffer      mFontBufferText;
     private:
         LLWString               mText;
-- 
cgit v1.2.3


From ac8d8aa09e68d749c05f852d92d0bc14274851c7 Mon Sep 17 00:00:00 2001
From: Rye Cogtail <rye@lindenlab.com>
Date: Wed, 30 Oct 2024 17:22:12 -0400
Subject: Fix leak of callback objects on shutdown in LLMaterialMgr

---
 indra/newview/llmaterialmgr.cpp | 22 ++++++++++------------
 indra/newview/llmaterialmgr.h   |  6 +++---
 2 files changed, 13 insertions(+), 15 deletions(-)

(limited to 'indra/newview')

diff --git a/indra/newview/llmaterialmgr.cpp b/indra/newview/llmaterialmgr.cpp
index ee5e5b438e..dbc44ad649 100644
--- a/indra/newview/llmaterialmgr.cpp
+++ b/indra/newview/llmaterialmgr.cpp
@@ -234,7 +234,7 @@ boost::signals2::connection LLMaterialMgr::get(const LLUUID& region_id, const LL
         get_callback_map_t::iterator itCallback = mGetCallbacks.find(material_id);
         if (itCallback == mGetCallbacks.end())
         {
-            std::pair<get_callback_map_t::iterator, bool> ret = mGetCallbacks.insert(std::pair<LLMaterialID, get_callback_t*>(material_id, new get_callback_t()));
+            std::pair<get_callback_map_t::iterator, bool> ret = mGetCallbacks.emplace(material_id, std::make_unique<get_callback_t>());
             itCallback = ret.first;
         }
         connection = itCallback->second->connect(cb);;
@@ -279,7 +279,7 @@ boost::signals2::connection LLMaterialMgr::getTE(const LLUUID& region_id, const
         get_callback_te_map_t::iterator itCallback = mGetTECallbacks.find(te_mat_pair);
         if (itCallback == mGetTECallbacks.end())
         {
-            std::pair<get_callback_te_map_t::iterator, bool> ret = mGetTECallbacks.insert(std::pair<TEMaterialPair, get_callback_te_t*>(te_mat_pair, new get_callback_te_t()));
+            std::pair<get_callback_te_map_t::iterator, bool> ret = mGetTECallbacks.emplace(te_mat_pair, std::make_unique<get_callback_te_t>());
             itCallback = ret.first;
         }
         connection = itCallback->second->connect(cb);
@@ -317,7 +317,7 @@ boost::signals2::connection LLMaterialMgr::getAll(const LLUUID& region_id, LLMat
     getall_callback_map_t::iterator itCallback = mGetAllCallbacks.find(region_id);
     if (mGetAllCallbacks.end() == itCallback)
     {
-        std::pair<getall_callback_map_t::iterator, bool> ret = mGetAllCallbacks.insert(std::pair<LLUUID, getall_callback_t*>(region_id, new getall_callback_t()));
+        std::pair<getall_callback_map_t::iterator, bool> ret = mGetAllCallbacks.emplace(region_id, std::make_unique<getall_callback_t>());
         itCallback = ret.first;
     }
     return itCallback->second->connect(cb);;
@@ -329,8 +329,8 @@ void LLMaterialMgr::put(const LLUUID& object_id, const U8 te, const LLMaterial&
     if (mPutQueue.end() == itQueue)
     {
         LL_DEBUGS("Materials") << "mPutQueue insert object " << object_id << LL_ENDL;
-        mPutQueue.insert(std::pair<LLUUID, facematerial_map_t>(object_id, facematerial_map_t()));
-        itQueue = mPutQueue.find(object_id);
+        auto ret = mPutQueue.emplace(object_id, facematerial_map_t());
+        itQueue = ret.first;
     }
 
     facematerial_map_t::iterator itFace = itQueue->second.find(te);
@@ -361,7 +361,7 @@ void LLMaterialMgr::setLocalMaterial(const LLUUID& region_id, LLMaterialPtr mate
     }
 
     LL_DEBUGS("Materials") << "region " << region_id << "new local material id " << material_id << LL_ENDL;
-    mMaterials.insert(std::pair<LLMaterialID, LLMaterialPtr>(material_id, material_ptr));
+    mMaterials.emplace(material_id, material_ptr);
 
     setMaterialCallbacks(material_id, material_ptr);
 
@@ -376,7 +376,7 @@ const LLMaterialPtr LLMaterialMgr::setMaterial(const LLUUID& region_id, const LL
     {
         LL_DEBUGS("Materials") << "new material" << LL_ENDL;
         LLMaterialPtr newMaterial(new LLMaterial(material_data));
-        std::pair<material_map_t::const_iterator, bool> ret = mMaterials.insert(std::pair<LLMaterialID, LLMaterialPtr>(material_id, newMaterial));
+        std::pair<material_map_t::const_iterator, bool> ret = mMaterials.emplace(material_id, newMaterial);
         itMaterial = ret.first;
     }
 
@@ -400,7 +400,6 @@ void LLMaterialMgr::setMaterialCallbacks(const LLMaterialID& material_id, const
         if (itCallbackTE != mGetTECallbacks.end())
         {
             (*itCallbackTE->second)(material_id, material_ptr, te_mat_pair.te);
-            delete itCallbackTE->second;
             mGetTECallbacks.erase(itCallbackTE);
         }
     }
@@ -410,7 +409,6 @@ void LLMaterialMgr::setMaterialCallbacks(const LLMaterialID& material_id, const
     {
         (*itCallback->second)(material_id, material_ptr);
 
-        delete itCallback->second;
         mGetCallbacks.erase(itCallback);
     }
 }
@@ -509,7 +507,6 @@ void LLMaterialMgr::onGetAllResponse(bool success, const LLSD& content, const LL
     {
         (*itCallback->second)(region_id, materials);
 
-        delete itCallback->second;
         mGetAllCallbacks.erase(itCallback);
     }
 
@@ -549,11 +546,11 @@ void LLMaterialMgr::onPutResponse(bool success, const LLSD& content)
     {
         llassert(response_data.isArray());
         LL_DEBUGS("Materials") << "response has "<< response_data.size() << " materials" << LL_ENDL;
+#ifdef SHOW_ASSERT // same condition that controls llassert()
         for (LLSD::array_const_iterator faceIter = response_data.beginArray(); faceIter != response_data.endArray(); ++faceIter)
         {
-#           ifdef SHOW_ASSERT                  // same condition that controls llassert()
             const LLSD& face_data = *faceIter; // conditional to avoid unused variable warning
-#           endif
+
             llassert(face_data.isMap());
 
             llassert(face_data.has(MATERIALS_CAP_OBJECT_ID_FIELD));
@@ -570,6 +567,7 @@ void LLMaterialMgr::onPutResponse(bool success, const LLSD& content)
 
             // *TODO: do we really still need to process this?
         }
+#endif
     }
 }
 
diff --git a/indra/newview/llmaterialmgr.h b/indra/newview/llmaterialmgr.h
index 1279b77ad4..ac4c18d60c 100644
--- a/indra/newview/llmaterialmgr.h
+++ b/indra/newview/llmaterialmgr.h
@@ -110,13 +110,13 @@ private:
     typedef std::map<LLUUID, material_queue_t> get_queue_t;
     typedef std::pair<const LLUUID, LLMaterialID> pending_material_t;
     typedef std::map<const pending_material_t, F64> get_pending_map_t;
-    typedef std::map<LLMaterialID, get_callback_t*> get_callback_map_t;
+    typedef std::map<LLMaterialID, std::unique_ptr<get_callback_t>> get_callback_map_t;
 
 
-    typedef boost::unordered_map<TEMaterialPair, get_callback_te_t*> get_callback_te_map_t;
+    typedef boost::unordered_map<TEMaterialPair, std::unique_ptr<get_callback_te_t>> get_callback_te_map_t;
     typedef std::set<LLUUID> getall_queue_t;
     typedef std::map<LLUUID, F64> getall_pending_map_t;
-    typedef std::map<LLUUID, getall_callback_t*> getall_callback_map_t;
+    typedef std::map<LLUUID, std::unique_ptr<getall_callback_t>> getall_callback_map_t;
     typedef std::map<U8, LLMaterial> facematerial_map_t;
     typedef std::map<LLUUID, facematerial_map_t> put_queue_t;
 
-- 
cgit v1.2.3


From a4bd6ccb6a5813f2a9e7021f25886a0c34cc8392 Mon Sep 17 00:00:00 2001
From: Rye Cogtail <rye@lindenlab.com>
Date: Wed, 30 Oct 2024 16:07:54 -0400
Subject: Fix leak of notification seperator in tabbed notification floater

---
 indra/newview/llfloaternotificationstabbed.cpp | 4 ++--
 indra/newview/llfloaternotificationstabbed.h   | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

(limited to 'indra/newview')

diff --git a/indra/newview/llfloaternotificationstabbed.cpp b/indra/newview/llfloaternotificationstabbed.cpp
index e571011acf..8eeba095b2 100644
--- a/indra/newview/llfloaternotificationstabbed.cpp
+++ b/indra/newview/llfloaternotificationstabbed.cpp
@@ -45,7 +45,6 @@ LLFloaterNotificationsTabbed::LLFloaterNotificationsTabbed(const LLSD& key) : LL
     mGroupNoticeMessageList(NULL),
     mTransactionMessageList(NULL),
     mSystemMessageList(NULL),
-    mNotificationsSeparator(NULL),
     mNotificationsTabContainer(NULL),
     NOTIFICATION_TABBED_ANCHOR_NAME("notification_well_panel"),
     IM_WELL_ANCHOR_NAME("im_well_panel"),
@@ -54,7 +53,7 @@ LLFloaterNotificationsTabbed::LLFloaterNotificationsTabbed(const LLSD& key) : LL
 {
     setOverlapsScreenChannel(true);
     mNotificationUpdates.reset(new NotificationTabbedChannel(this));
-    mNotificationsSeparator = new LLNotificationSeparator();
+    mNotificationsSeparator = std::make_unique<LLNotificationSeparator>();
 }
 
 //---------------------------------------------------------------------------------
@@ -117,6 +116,7 @@ void LLFloaterNotificationsTabbed::setSysWellChiclet(LLSysWellChiclet* chiclet)
 //---------------------------------------------------------------------------------
 LLFloaterNotificationsTabbed::~LLFloaterNotificationsTabbed()
 {
+    mNotificationsSeparator.reset();
 }
 
 //---------------------------------------------------------------------------------
diff --git a/indra/newview/llfloaternotificationstabbed.h b/indra/newview/llfloaternotificationstabbed.h
index 87e880c8d2..49dfe6033f 100644
--- a/indra/newview/llfloaternotificationstabbed.h
+++ b/indra/newview/llfloaternotificationstabbed.h
@@ -162,7 +162,7 @@ private:
     LLNotificationListView* mGroupNoticeMessageList;
     LLNotificationListView* mTransactionMessageList;
     LLNotificationListView* mSystemMessageList;
-    LLNotificationSeparator* mNotificationsSeparator;
+    std::unique_ptr<LLNotificationSeparator> mNotificationsSeparator;
     LLTabContainer* mNotificationsTabContainer;
     LLButton*   mDeleteAllBtn;
     LLButton*   mCollapseAllBtn;
-- 
cgit v1.2.3


From eee46669d89385745037e9ad4bfb1c27a2597fa2 Mon Sep 17 00:00:00 2001
From: Rye Cogtail <rye@lindenlab.com>
Date: Wed, 30 Oct 2024 16:07:33 -0400
Subject: Fix leak of boost signal objects in marketplace functions

---
 indra/newview/llmarketplacefunctions.cpp | 23 +++++++++--------------
 indra/newview/llmarketplacefunctions.h   | 10 +++++-----
 2 files changed, 14 insertions(+), 19 deletions(-)

(limited to 'indra/newview')

diff --git a/indra/newview/llmarketplacefunctions.cpp b/indra/newview/llmarketplacefunctions.cpp
index 7b8211ded8..53ea345858 100644
--- a/indra/newview/llmarketplacefunctions.cpp
+++ b/indra/newview/llmarketplacefunctions.cpp
@@ -450,17 +450,14 @@ LLMarketplaceInventoryImporter::LLMarketplaceInventoryImporter()
     , mImportInProgress(false)
     , mInitialized(false)
     , mMarketPlaceStatus(MarketplaceStatusCodes::MARKET_PLACE_NOT_INITIALIZED)
-    , mErrorInitSignal(NULL)
-    , mStatusChangedSignal(NULL)
-    , mStatusReportSignal(NULL)
 {
 }
 
 boost::signals2::connection LLMarketplaceInventoryImporter::setInitializationErrorCallback(const status_report_signal_t::slot_type& cb)
 {
-    if (mErrorInitSignal == NULL)
+    if (mErrorInitSignal == nullptr)
     {
-        mErrorInitSignal = new status_report_signal_t();
+        mErrorInitSignal = std::make_unique<status_report_signal_t>();
     }
 
     return mErrorInitSignal->connect(cb);
@@ -468,9 +465,9 @@ boost::signals2::connection LLMarketplaceInventoryImporter::setInitializationErr
 
 boost::signals2::connection LLMarketplaceInventoryImporter::setStatusChangedCallback(const status_changed_signal_t::slot_type& cb)
 {
-    if (mStatusChangedSignal == NULL)
+    if (mStatusChangedSignal == nullptr)
     {
-        mStatusChangedSignal = new status_changed_signal_t();
+        mStatusChangedSignal = std::make_unique<status_changed_signal_t>();
     }
 
     return mStatusChangedSignal->connect(cb);
@@ -478,9 +475,9 @@ boost::signals2::connection LLMarketplaceInventoryImporter::setStatusChangedCall
 
 boost::signals2::connection LLMarketplaceInventoryImporter::setStatusReportCallback(const status_report_signal_t::slot_type& cb)
 {
-    if (mStatusReportSignal == NULL)
+    if (mStatusReportSignal == nullptr)
     {
-        mStatusReportSignal = new status_report_signal_t();
+        mStatusReportSignal = std::make_unique<status_report_signal_t>();
     }
 
     return mStatusReportSignal->connect(cb);
@@ -717,8 +714,6 @@ LLMarketplaceTuple::LLMarketplaceTuple(const LLUUID& folder_id, S32 listing_id,
 LLMarketplaceData::LLMarketplaceData() :
  mMarketPlaceStatus(MarketplaceStatusCodes::MARKET_PLACE_NOT_INITIALIZED),
  mMarketPlaceDataFetched(MarketplaceFetchCodes::MARKET_FETCH_NOT_DONE),
- mStatusUpdatedSignal(NULL),
- mDataFetchedSignal(NULL),
  mDirtyCount(false)
 {
     mInventoryObserver = new LLMarketplaceInventoryObserver;
@@ -752,9 +747,9 @@ LLSD LLMarketplaceData::getMarketplaceStringSubstitutions()
 
 void LLMarketplaceData::initializeSLM(const status_updated_signal_t::slot_type& cb)
 {
-    if (mStatusUpdatedSignal == NULL)
+    if (mStatusUpdatedSignal == nullptr)
     {
-        mStatusUpdatedSignal = new status_updated_signal_t();
+        mStatusUpdatedSignal = std::make_unique<status_updated_signal_t>();
     }
     mStatusUpdatedSignal->connect(cb);
 
@@ -842,7 +837,7 @@ void LLMarketplaceData::setDataFetchedSignal(const status_updated_signal_t::slot
 {
     if (mDataFetchedSignal == NULL)
     {
-        mDataFetchedSignal = new status_updated_signal_t();
+        mDataFetchedSignal = std::make_unique<status_updated_signal_t>();
     }
     mDataFetchedSignal->connect(cb);
 }
diff --git a/indra/newview/llmarketplacefunctions.h b/indra/newview/llmarketplacefunctions.h
index 281743c1d6..4e61b0c7f3 100644
--- a/indra/newview/llmarketplacefunctions.h
+++ b/indra/newview/llmarketplacefunctions.h
@@ -113,9 +113,9 @@ private:
     bool mInitialized;
     U32  mMarketPlaceStatus;
 
-    status_report_signal_t *    mErrorInitSignal;
-    status_changed_signal_t *   mStatusChangedSignal;
-    status_report_signal_t *    mStatusReportSignal;
+    std::unique_ptr<status_report_signal_t>    mErrorInitSignal;
+    std::unique_ptr<status_changed_signal_t>   mStatusChangedSignal;
+    std::unique_ptr<status_report_signal_t>    mStatusReportSignal;
 };
 
 
@@ -276,13 +276,13 @@ private:
     // Handling Marketplace connection and inventory connection
     U32  mMarketPlaceStatus;
     std::string mMarketPlaceFailureReason;
-    status_updated_signal_t* mStatusUpdatedSignal;
+    std::unique_ptr<status_updated_signal_t> mStatusUpdatedSignal;
     LLInventoryObserver* mInventoryObserver;
     bool mDirtyCount;   // If true, stock count value need to be updated at the next check
 
     // Update data
     U32 mMarketPlaceDataFetched;
-    status_updated_signal_t* mDataFetchedSignal;
+    std::unique_ptr<status_updated_signal_t> mDataFetchedSignal;
     std::set<LLUUID> mPendingUpdateSet;
 
     // Listing folders waiting for validation
-- 
cgit v1.2.3


From 5ff70a9dbc5791975a333a973d734f998de7aa3b Mon Sep 17 00:00:00 2001
From: Rye <rye@lindenlab.com>
Date: Sun, 3 Nov 2024 16:08:27 -0500
Subject: Fix possible leak of gesture when region ptr is null

---
 indra/newview/llpreviewgesture.cpp | 3 +++
 1 file changed, 3 insertions(+)

(limited to 'indra/newview')

diff --git a/indra/newview/llpreviewgesture.cpp b/indra/newview/llpreviewgesture.cpp
index 66dcd2f7ba..ee5188b2bb 100644
--- a/indra/newview/llpreviewgesture.cpp
+++ b/indra/newview/llpreviewgesture.cpp
@@ -1096,6 +1096,9 @@ void LLPreviewGesture::saveIfNeeded()
         if (!region)
         {
             LL_WARNS() << "Not connected to a region, cannot save gesture." << LL_ENDL;
+            // we're done with this gesture
+            delete gesture;
+            gesture = NULL;
             return;
         }
         std::string agent_url = region->getCapability("UpdateGestureAgentInventory");
-- 
cgit v1.2.3


From 2c7f57b3d6967c618d90d0cab97ec5dda221d3b0 Mon Sep 17 00:00:00 2001
From: Rye <rye@lindenlab.com>
Date: Sun, 3 Nov 2024 16:08:48 -0500
Subject: Fix leak of LLUUID in ui preview floater

---
 indra/newview/llfloateruipreview.cpp | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

(limited to 'indra/newview')

diff --git a/indra/newview/llfloateruipreview.cpp b/indra/newview/llfloateruipreview.cpp
index 12576c042b..797d146d97 100644
--- a/indra/newview/llfloateruipreview.cpp
+++ b/indra/newview/llfloateruipreview.cpp
@@ -701,13 +701,9 @@ void LLFloaterUIPreview::refreshList()
 // Note: no deduplification (shouldn't be necessary)
 void LLFloaterUIPreview::addFloaterEntry(const std::string& path)
 {
-    LLUUID* entry_id = new LLUUID();                // create a new UUID
-    entry_id->generate(path);
-    const LLUUID& entry_id_ref = *entry_id;         // get a reference to the UUID for the LLSD block
-
     // fill LLSD column entry: initialize row/col structure
     LLSD row;
-    row["id"] = entry_id_ref;
+    row["id"] = LLUUID::generateNewID(path); // create a new UUID;
     LLSD& columns = row["columns"];
 
     // Get name of floater:
-- 
cgit v1.2.3


From a57d82b3a9337eb4ac00340e80749ac97392e03e Mon Sep 17 00:00:00 2001
From: Rye <rye@lindenlab.com>
Date: Fri, 1 Nov 2024 03:30:23 -0400
Subject: Eliminate reduntant copies and full screen passes from post process
 effect chain

---
 indra/newview/CMakeLists.txt                       |   1 +
 indra/newview/app_settings/settings.xml            |  11 +
 .../app_settings/shaders/class1/deferred/CASF.glsl |  59 ++
 .../class1/deferred/postDeferredGammaCorrect.glsl  |  58 --
 .../class1/deferred/postDeferredNoDoFF.glsl        |  47 --
 .../class1/deferred/postDeferredTonemap.glsl       |  63 +-
 indra/newview/featuretable.txt                     |  10 +-
 indra/newview/featuretable_linux.txt               |  14 +-
 indra/newview/featuretable_mac.txt                 |  10 +-
 indra/newview/llgltfmaterialpreviewmgr.cpp         |  18 +-
 indra/newview/llviewercontrol.cpp                  |   1 +
 indra/newview/llviewershadermgr.cpp                |  59 +-
 indra/newview/llviewershadermgr.h                  |   3 +-
 indra/newview/pipeline.cpp                         | 637 ++++++++++-----------
 indra/newview/pipeline.h                           |   8 +-
 .../en/floater_preferences_graphics_advanced.xml   |  15 +-
 16 files changed, 539 insertions(+), 475 deletions(-)
 delete mode 100644 indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl

(limited to 'indra/newview')

diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index b599358aa3..6d852e47f8 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -1686,6 +1686,7 @@ set(viewer_APPSETTINGS_FILES
     packages-info.txt
     featuretable.txt
     featuretable_mac.txt
+    featuretable_linux.txt
     )
 
 source_group("App Settings" FILES ${viewer_APPSETTINGS_FILES})
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 049ec3ad34..129f593454 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -10080,6 +10080,17 @@
       <key>Value</key>
       <string>00000000-0000-0000-0000-000000000000</string>
     </map>
+    <key>RenderCAS</key>
+    <map>
+        <key>Comment</key>
+        <string>Use Contrast Adaptive Sharpening post process effect</string>
+        <key>Persist</key>
+        <integer>0</integer>
+        <key>Type</key>
+        <string>Boolean</string>
+        <key>Value</key>
+        <integer>1</integer>
+    </map>
     <key>RenderCASSharpness</key>
     <map>
         <key>Comment</key>
diff --git a/indra/newview/app_settings/shaders/class1/deferred/CASF.glsl b/indra/newview/app_settings/shaders/class1/deferred/CASF.glsl
index e80c59b39f..abab71e5ce 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/CASF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/CASF.glsl
@@ -38,6 +38,7 @@ uniform sampler2D diffuseRect;
 uniform vec2 out_screen_res;
 uniform uvec4 cas_param_0;
 uniform uvec4 cas_param_1;
+uniform float gamma;
 
 vec3 srgb_to_linear(vec3 cs);
 vec3 linear_to_srgb(vec3 cl);
@@ -2545,11 +2546,69 @@ A_STATIC void CasSetup(
 #endif
 
 #ifdef A_GPU
+
+//=================================
+// borrowed noise from:
+//  <https://www.shadertoy.com/view/4dS3Wd>
+//  By Morgan McGuire @morgan3d, http://graphicscodex.com
+//
+float hash(float n) { return fract(sin(n) * 1e4); }
+float hash(vec2 p) { return fract(1e4 * sin(17.0 * p.x + p.y * 0.1) * (0.1 + abs(sin(p.y * 13.0 + p.x)))); }
+
+float noise(float x) {
+    float i = floor(x);
+    float f = fract(x);
+    float u = f * f * (3.0 - 2.0 * f);
+    return mix(hash(i), hash(i + 1.0), u);
+}
+
+float noise(vec2 x) {
+    vec2 i = floor(x);
+    vec2 f = fract(x);
+
+    // Four corners in 2D of a tile
+    float a = hash(i);
+    float b = hash(i + vec2(1.0, 0.0));
+    float c = hash(i + vec2(0.0, 1.0));
+    float d = hash(i + vec2(1.0, 1.0));
+
+    // Simple 2D lerp using smoothstep envelope between the values.
+    // return vec3(mix(mix(a, b, smoothstep(0.0, 1.0, f.x)),
+    //          mix(c, d, smoothstep(0.0, 1.0, f.x)),
+    //          smoothstep(0.0, 1.0, f.y)));
+
+    // Same code, with the clamps in smoothstep and common subexpressions
+    // optimized away.
+    vec2 u = f * f * (3.0 - 2.0 * f);
+    return mix(a, b, u.x) + (c - a) * u.y * (1.0 - u.x) + (d - b) * u.x * u.y;
+}
+
+//===============================================================
+
+vec3 legacyGamma(vec3 color)
+{
+    vec3 c = 1. - clamp(color, vec3(0.), vec3(1.));
+    c = 1. - pow(c, vec3(gamma)); // s/b inverted already CPU-side
+
+    return c;
+}
+
 void main()
 {
     vec4 diff = vec4(0.f);
     uvec2 point = uvec2(vary_fragcoord * out_screen_res.xy);
     CasFilter(diff.r, diff.g, diff.b, point, cas_param_0, cas_param_1, true);
+    diff.rgb = linear_to_srgb(diff.rgb);
+
+#ifdef LEGACY_GAMMA
+    diff.rgb = legacyGamma(diff.rgb);
+#endif
+
+    vec2 tc = vary_fragcoord.xy*out_screen_res.xy*4.0;
+    vec3 seed = (diff.rgb+vec3(1.0))*vec3(tc.xy, tc.x+tc.y);
+    vec3 nz = vec3(noise(seed.rg), noise(seed.gb), noise(seed.rb));
+    diff.rgb += nz*0.003;
+
     diff.a = texture(diffuseRect, vary_fragcoord).a;
     frag_color = diff;
 }
diff --git a/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl
deleted file mode 100644
index befd2ae6da..0000000000
--- a/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl
+++ /dev/null
@@ -1,58 +0,0 @@
-/**
- * @file postDeferredGammaCorrect.glsl
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2007, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-/*[EXTRA_CODE_HERE]*/
-
-out vec4 frag_color;
-
-uniform sampler2D diffuseRect;
-
-uniform float gamma;
-uniform vec2 screen_res;
-in vec2 vary_fragcoord;
-
-vec3 linear_to_srgb(vec3 cl);
-
-vec3 legacyGamma(vec3 color)
-{
-    vec3 c = 1. - clamp(color, vec3(0.), vec3(1.));
-    c = 1. - pow(c, vec3(gamma)); // s/b inverted already CPU-side
-
-    return c;
-}
-
-void main()
-{
-    //this is the one of the rare spots where diffuseRect contains linear color values (not sRGB)
-    vec4 diff = texture(diffuseRect, vary_fragcoord);
-    diff.rgb = linear_to_srgb(diff.rgb);
-
-#ifdef LEGACY_GAMMA
-    diff.rgb = legacyGamma(diff.rgb);
-#endif
-
-    frag_color = max(diff, vec4(0));
-}
-
diff --git a/indra/newview/app_settings/shaders/class1/deferred/postDeferredNoDoFF.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredNoDoFF.glsl
index 32b0a1ac8e..07384ebe9b 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/postDeferredNoDoFF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/postDeferredNoDoFF.glsl
@@ -33,57 +33,10 @@ uniform sampler2D depthMap;
 uniform vec2 screen_res;
 in vec2 vary_fragcoord;
 
-//=================================
-// borrowed noise from:
-//  <https://www.shadertoy.com/view/4dS3Wd>
-//  By Morgan McGuire @morgan3d, http://graphicscodex.com
-//
-float hash(float n) { return fract(sin(n) * 1e4); }
-float hash(vec2 p) { return fract(1e4 * sin(17.0 * p.x + p.y * 0.1) * (0.1 + abs(sin(p.y * 13.0 + p.x)))); }
-
-float noise(float x) {
-    float i = floor(x);
-    float f = fract(x);
-    float u = f * f * (3.0 - 2.0 * f);
-    return mix(hash(i), hash(i + 1.0), u);
-}
-
-float noise(vec2 x) {
-    vec2 i = floor(x);
-    vec2 f = fract(x);
-
-    // Four corners in 2D of a tile
-    float a = hash(i);
-    float b = hash(i + vec2(1.0, 0.0));
-    float c = hash(i + vec2(0.0, 1.0));
-    float d = hash(i + vec2(1.0, 1.0));
-
-    // Simple 2D lerp using smoothstep envelope between the values.
-    // return vec3(mix(mix(a, b, smoothstep(0.0, 1.0, f.x)),
-    //          mix(c, d, smoothstep(0.0, 1.0, f.x)),
-    //          smoothstep(0.0, 1.0, f.y)));
-
-    // Same code, with the clamps in smoothstep and common subexpressions
-    // optimized away.
-    vec2 u = f * f * (3.0 - 2.0 * f);
-    return mix(a, b, u.x) + (c - a) * u.y * (1.0 - u.x) + (d - b) * u.x * u.y;
-}
-
-//=============================
-
-
-
 void main()
 {
     vec4 diff = texture(diffuseRect, vary_fragcoord.xy);
 
-#ifdef HAS_NOISE
-    vec2 tc = vary_fragcoord.xy*screen_res*4.0;
-    vec3 seed = (diff.rgb+vec3(1.0))*vec3(tc.xy, tc.x+tc.y);
-    vec3 nz = vec3(noise(seed.rg), noise(seed.gb), noise(seed.rb));
-    diff.rgb += nz*0.003;
-#endif
-
     frag_color = diff;
 
     gl_FragDepth = texture(depthMap, vary_fragcoord.xy).r;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/postDeferredTonemap.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredTonemap.glsl
index fc6d4d7727..9d449a5ae2 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/postDeferredTonemap.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/postDeferredTonemap.glsl
@@ -30,6 +30,7 @@ out vec4 frag_color;
 uniform sampler2D diffuseRect;
 uniform sampler2D exposureMap;
 
+uniform float gamma;
 uniform vec2 screen_res;
 in vec2 vary_fragcoord;
 
@@ -149,6 +150,42 @@ vec3 toneMap(vec3 color)
     return color;
 }
 
+//=================================
+// borrowed noise from:
+//  <https://www.shadertoy.com/view/4dS3Wd>
+//  By Morgan McGuire @morgan3d, http://graphicscodex.com
+//
+float hash(float n) { return fract(sin(n) * 1e4); }
+float hash(vec2 p) { return fract(1e4 * sin(17.0 * p.x + p.y * 0.1) * (0.1 + abs(sin(p.y * 13.0 + p.x)))); }
+
+float noise(float x) {
+    float i = floor(x);
+    float f = fract(x);
+    float u = f * f * (3.0 - 2.0 * f);
+    return mix(hash(i), hash(i + 1.0), u);
+}
+
+float noise(vec2 x) {
+    vec2 i = floor(x);
+    vec2 f = fract(x);
+
+    // Four corners in 2D of a tile
+    float a = hash(i);
+    float b = hash(i + vec2(1.0, 0.0));
+    float c = hash(i + vec2(0.0, 1.0));
+    float d = hash(i + vec2(1.0, 1.0));
+
+    // Simple 2D lerp using smoothstep envelope between the values.
+    // return vec3(mix(mix(a, b, smoothstep(0.0, 1.0, f.x)),
+    //          mix(c, d, smoothstep(0.0, 1.0, f.x)),
+    //          smoothstep(0.0, 1.0, f.y)));
+
+    // Same code, with the clamps in smoothstep and common subexpressions
+    // optimized away.
+    vec2 u = f * f * (3.0 - 2.0 * f);
+    return mix(a, b, u.x) + (c - a) * u.y * (1.0 - u.x) + (d - b) * u.x * u.y;
+}
+
 //===============================================================
 
 void debugExposure(inout vec3 color)
@@ -161,16 +198,40 @@ void debugExposure(inout vec3 color)
     }
 }
 
+vec3 legacyGamma(vec3 color)
+{
+    vec3 c = 1. - clamp(color, vec3(0.), vec3(1.));
+    c = 1. - pow(c, vec3(gamma)); // s/b inverted already CPU-side
+
+    return c;
+}
+
 void main()
 {
     //this is the one of the rare spots where diffuseRect contains linear color values (not sRGB)
     vec4 diff = texture(diffuseRect, vary_fragcoord);
 
+#ifdef TONEMAP
 #ifndef NO_POST
     diff.rgb = toneMap(diff.rgb);
-#else
+#endif
+#ifndef GAMMA_CORRECT
     diff.rgb = clamp(diff.rgb, vec3(0.0), vec3(1.0));
 #endif
+#endif
+
+#ifdef GAMMA_CORRECT
+    diff.rgb = linear_to_srgb(diff.rgb);
+
+#ifdef LEGACY_GAMMA
+    diff.rgb = legacyGamma(diff.rgb);
+#endif
+
+    vec2 tc = vary_fragcoord.xy*screen_res*4.0;
+    vec3 seed = (diff.rgb+vec3(1.0))*vec3(tc.xy, tc.x+tc.y);
+    vec3 nz = vec3(noise(seed.rg), noise(seed.gb), noise(seed.rb));
+    diff.rgb += nz*0.003;
+#endif
 
     //debugExposure(diff.rgb);
     frag_color = max(diff, vec4(0));
diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt
index 6390e43b7a..ce9fc853c8 100644
--- a/indra/newview/featuretable.txt
+++ b/indra/newview/featuretable.txt
@@ -1,4 +1,4 @@
-version 64
+version 65
 // The version number above should be incremented IF AND ONLY IF some
 // change has been made that is sufficiently important to justify
 // resetting the graphics preferences of all users to the recommended
@@ -80,6 +80,7 @@ RenderHeroProbeDistance		1	16
 RenderHeroProbeUpdateRate	1	6
 RenderHeroProbeConservativeUpdateMultiplier 1 16
 RenderDownScaleMethod       1   1
+RenderCAS                   1   1
 RenderCASSharpness          1   1
 RenderExposure				1   4
 RenderTonemapType			1   1
@@ -120,6 +121,7 @@ RenderHeroProbeResolution	1	256
 RenderHeroProbeDistance		1	4
 RenderHeroProbeUpdateRate	1	6
 RenderHeroProbeConservativeUpdateMultiplier 1 16
+RenderCAS                   1   0
 RenderCASSharpness          1   0
 RenderExposure				1   1
 RenderTonemapType			1   1
@@ -160,6 +162,7 @@ RenderHeroProbeResolution	1	256
 RenderHeroProbeDistance		1	6
 RenderHeroProbeUpdateRate	1	3
 RenderHeroProbeConservativeUpdateMultiplier 1 16
+RenderCAS                   1   0
 RenderCASSharpness          1   0
 RenderExposure				1   1
 RenderTonemapType			1   1
@@ -200,6 +203,7 @@ RenderHeroProbeResolution	1	512
 RenderHeroProbeDistance		1	6
 RenderHeroProbeUpdateRate	1	3
 RenderHeroProbeConservativeUpdateMultiplier 1 16
+RenderCAS                   1   0
 RenderCASSharpness          1   0
 RenderExposure				1   1
 RenderTonemapType			1   1
@@ -240,6 +244,7 @@ RenderHeroProbeResolution	1	512
 RenderHeroProbeDistance		1	6
 RenderHeroProbeUpdateRate	1	2
 RenderHeroProbeConservativeUpdateMultiplier 1 8
+RenderCAS                   1   0
 RenderCASSharpness          1   0
 RenderExposure				1   1
 RenderTonemapType			1   1
@@ -280,6 +285,7 @@ RenderHeroProbeResolution	1	512
 RenderHeroProbeDistance		1	8
 RenderHeroProbeUpdateRate	1	2
 RenderHeroProbeConservativeUpdateMultiplier 1 8
+RenderCAS                   1   1
 RenderCASSharpness          1   0.4
 RenderExposure				1   1
 RenderTonemapType			1   1
@@ -320,6 +326,7 @@ RenderHeroProbeResolution	1	1024
 RenderHeroProbeDistance		1	16
 RenderHeroProbeUpdateRate	1	1
 RenderHeroProbeConservativeUpdateMultiplier 1 4
+RenderCAS                   1   1
 RenderCASSharpness          1   0.4
 RenderExposure				1   1
 RenderTonemapType			1   1
@@ -360,6 +367,7 @@ RenderHeroProbeResolution	1	2048
 RenderHeroProbeDistance		1	16
 RenderHeroProbeUpdateRate	1	1
 RenderHeroProbeConservativeUpdateMultiplier 1 4
+RenderCAS                   1   1
 RenderCASSharpness          1   0.4
 RenderExposure				1   1
 RenderTonemapType			1   1
diff --git a/indra/newview/featuretable_linux.txt b/indra/newview/featuretable_linux.txt
index 9465acae6b..e8004bc1db 100644
--- a/indra/newview/featuretable_linux.txt
+++ b/indra/newview/featuretable_linux.txt
@@ -1,10 +1,10 @@
-version 30
+version 31
 // The version number above should be incremented IF AND ONLY IF some
 // change has been made that is sufficiently important to justify
 // resetting the graphics preferences of all users to the recommended
 // defaults.  This should be as rare an event as we can manage.
 
-// NOTE: This is mostly identical to featuretable_mac.txt with a few differences
+// NOTE: This is mostly identical to featuretable_mac.txt with a few differences 
 // Should be combined into one table
 
 //
@@ -77,9 +77,10 @@ RenderScreenSpaceReflections 1  1
 RenderMirrors				1	1
 RenderHeroProbeResolution	1	2048
 RenderHeroProbeDistance		1	16
-RenderHeroProbeUpdateRate	1	4
+RenderHeroProbeUpdateRate	1	6
 RenderHeroProbeConservativeUpdateMultiplier 1 16
 RenderDownScaleMethod       1   1
+RenderCAS                   1   1
 RenderCASSharpness          1   1
 RenderExposure				1   4
 RenderTonemapType			1   1
@@ -120,6 +121,7 @@ RenderHeroProbeResolution	1	256
 RenderHeroProbeDistance		1	4
 RenderHeroProbeUpdateRate	1	6
 RenderHeroProbeConservativeUpdateMultiplier 1 16
+RenderCAS                   1   0
 RenderCASSharpness          1   0
 RenderExposure				1   1
 RenderTonemapType			1   1
@@ -160,6 +162,7 @@ RenderHeroProbeResolution	1	256
 RenderHeroProbeDistance		1	6
 RenderHeroProbeUpdateRate	1	3
 RenderHeroProbeConservativeUpdateMultiplier 1 16
+RenderCAS                   1   0
 RenderCASSharpness          1   0
 RenderExposure				1   1
 RenderTonemapType			1   1
@@ -200,6 +203,7 @@ RenderHeroProbeResolution	1	512
 RenderHeroProbeDistance		1	6
 RenderHeroProbeUpdateRate	1	3
 RenderHeroProbeConservativeUpdateMultiplier 1 16
+RenderCAS                   1   0
 RenderCASSharpness          1   0
 RenderExposure				1   1
 RenderTonemapType			1   1
@@ -240,6 +244,7 @@ RenderHeroProbeResolution	1	512
 RenderHeroProbeDistance		1	6
 RenderHeroProbeUpdateRate	1	2
 RenderHeroProbeConservativeUpdateMultiplier 1 8
+RenderCAS                   1   0
 RenderCASSharpness          1   0
 RenderExposure				1   1
 RenderTonemapType			1   1
@@ -280,6 +285,7 @@ RenderHeroProbeResolution	1	512
 RenderHeroProbeDistance		1	8
 RenderHeroProbeUpdateRate	1	2
 RenderHeroProbeConservativeUpdateMultiplier 1 8
+RenderCAS                   1   1
 RenderCASSharpness          1   0.4
 RenderExposure				1   1
 RenderTonemapType			1   1
@@ -320,6 +326,7 @@ RenderHeroProbeResolution	1	1024
 RenderHeroProbeDistance		1	16
 RenderHeroProbeUpdateRate	1	1
 RenderHeroProbeConservativeUpdateMultiplier 1 4
+RenderCAS                   1   1
 RenderCASSharpness          1   0.4
 RenderExposure				1   1
 RenderTonemapType			1   1
@@ -360,6 +367,7 @@ RenderHeroProbeResolution	1	2048
 RenderHeroProbeDistance		1	16
 RenderHeroProbeUpdateRate	1	1
 RenderHeroProbeConservativeUpdateMultiplier 1 4
+RenderCAS                   1   1
 RenderCASSharpness          1   0.4
 RenderExposure				1   1
 RenderTonemapType			1   1
diff --git a/indra/newview/featuretable_mac.txt b/indra/newview/featuretable_mac.txt
index 9ba922c3ce..26ccb17f27 100644
--- a/indra/newview/featuretable_mac.txt
+++ b/indra/newview/featuretable_mac.txt
@@ -1,4 +1,4 @@
-version 62
+version 63
 // The version number above should be incremented IF AND ONLY IF some
 // change has been made that is sufficiently important to justify
 // resetting the graphics preferences of all users to the recommended
@@ -79,6 +79,7 @@ RenderHeroProbeResolution	1	2048
 RenderHeroProbeDistance		1	16
 RenderHeroProbeUpdateRate	1	6
 RenderHeroProbeConservativeUpdateMultiplier 1 16
+RenderCAS                   1   1
 RenderCASSharpness          1   1
 RenderExposure				1   1
 RenderTonemapType			1   1
@@ -119,6 +120,7 @@ RenderHeroProbeResolution	1	256
 RenderHeroProbeDistance		1	4
 RenderHeroProbeUpdateRate	1   6
 RenderHeroProbeConservativeUpdateMultiplier 1 16
+RenderCAS                   1   0
 RenderCASSharpness          1   0
 RenderExposure				1   1
 RenderTonemapType			1   1
@@ -159,6 +161,7 @@ RenderHeroProbeResolution	1	256
 RenderHeroProbeDistance		1	6
 RenderHeroProbeUpdateRate	1	3
 RenderHeroProbeConservativeUpdateMultiplier 1 16
+RenderCAS                   1   0
 RenderCASSharpness          1   0
 RenderExposure				1   1
 RenderTonemapType			1   1
@@ -199,6 +202,7 @@ RenderHeroProbeResolution	1	512
 RenderHeroProbeDistance		1	6
 RenderHeroProbeUpdateRate	1	3
 RenderHeroProbeConservativeUpdateMultiplier 1 16
+RenderCAS                   1   0
 RenderCASSharpness          1   0
 RenderExposure				1   1
 RenderTonemapType			1   1
@@ -239,6 +243,7 @@ RenderHeroProbeResolution	1	512
 RenderHeroProbeDistance		1	6
 RenderHeroProbeUpdateRate	1	2
 RenderHeroProbeConservativeUpdateMultiplier 1 8
+RenderCAS                   1   0
 RenderCASSharpness          1   0
 RenderExposure				1   1
 RenderTonemapType			1   1
@@ -279,6 +284,7 @@ RenderHeroProbeResolution	1	512
 RenderHeroProbeDistance		1	8
 RenderHeroProbeUpdateRate	1	2
 RenderHeroProbeConservativeUpdateMultiplier 1 8
+RenderCAS                   1   0
 RenderCASSharpness          1   0
 RenderExposure				1   1
 RenderTonemapType			1   1
@@ -319,6 +325,7 @@ RenderHeroProbeResolution	1	512
 RenderHeroProbeDistance		1	16
 RenderHeroProbeUpdateRate	1	1
 RenderHeroProbeConservativeUpdateMultiplier 1 4
+RenderCAS                   1   1
 RenderCASSharpness          1   0.4
 RenderExposure				1   1
 RenderTonemapType			1   1
@@ -359,6 +366,7 @@ RenderHeroProbeResolution	1	1024
 RenderHeroProbeDistance		1	16
 RenderHeroProbeUpdateRate	1	1
 RenderHeroProbeConservativeUpdateMultiplier 1 4
+RenderCAS                   1   1
 RenderCASSharpness          1   0.4
 RenderExposure				1   1
 RenderTonemapType			1   1
diff --git a/indra/newview/llgltfmaterialpreviewmgr.cpp b/indra/newview/llgltfmaterialpreviewmgr.cpp
index cf6b08797d..f473afb74c 100644
--- a/indra/newview/llgltfmaterialpreviewmgr.cpp
+++ b/indra/newview/llgltfmaterialpreviewmgr.cpp
@@ -523,12 +523,16 @@ bool LLGLTFPreviewTexture::render()
     gPipeline.copyScreenSpaceReflections(&screen, &gPipeline.mSceneMap);
     gPipeline.generateLuminance(&screen, &gPipeline.mLuminanceMap);
     gPipeline.generateExposure(&gPipeline.mLuminanceMap, &gPipeline.mExposureMap, /*use_history = */ false);
-    gPipeline.gammaCorrect(&screen, &gPipeline.mPostMap);
+
+    LLRenderTarget* src = &gPipeline.mPostPingMap;
+    LLRenderTarget* dst = &gPipeline.mPostPongMap;
+    gPipeline.tonemap(&screen, dst);
+    std::swap(src, dst);
+
     LLVertexBuffer::unbind();
-    gPipeline.generateGlow(&gPipeline.mPostMap);
-    gPipeline.combineGlow(&gPipeline.mPostMap, &screen);
-    gPipeline.renderDoF(&screen, &gPipeline.mPostMap);
-    gPipeline.applyFXAA(&gPipeline.mPostMap, &screen);
+    gPipeline.generateGlow(src);
+    gPipeline.combineGlow(src, dst);
+    std::swap(src, dst);
 
     // *HACK: Restore mExposureMap (it will be consumed by generateExposure next frame)
     gPipeline.mExposureMap.swapFBORefs(gPipeline.mLastExposure);
@@ -538,9 +542,11 @@ bool LLGLTFPreviewTexture::render()
     gDeferredPostNoDoFProgram.bind();
 
     // From LLPipeline::renderFinalize: "Whatever is last in the above post processing chain should _always_ be rendered directly here.  If not, expect problems."
-    gDeferredPostNoDoFProgram.bindTexture(LLShaderMgr::DEFERRED_DIFFUSE, &screen);
+    gDeferredPostNoDoFProgram.bindTexture(LLShaderMgr::DEFERRED_DIFFUSE, src);
     gDeferredPostNoDoFProgram.bindTexture(LLShaderMgr::DEFERRED_DEPTH, mBoundTarget, true);
 
+    gDeferredPostNoDoFProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, (GLfloat)src->getWidth(), (GLfloat)src->getHeight());
+
     {
         LLGLDepthTest depth_test(GL_TRUE, GL_TRUE, GL_ALWAYS);
         gPipeline.mScreenTriangleVB->setBuffer();
diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp
index 184c0e7d8b..e9e231db59 100644
--- a/indra/newview/llviewercontrol.cpp
+++ b/indra/newview/llviewercontrol.cpp
@@ -770,6 +770,7 @@ void settings_setup_listeners()
     setting_setup_signal_listener(gSavedSettings, "OctreeAttachmentSizeFactor", handleRepartition);
     setting_setup_signal_listener(gSavedSettings, "RenderMaxTextureIndex", handleSetShaderChanged);
     setting_setup_signal_listener(gSavedSettings, "RenderUIBuffer", handleWindowResized);
+    setting_setup_signal_listener(gSavedSettings, "RenderCAS", handleReleaseGLBufferChanged);
     setting_setup_signal_listener(gSavedSettings, "RenderDepthOfField", handleReleaseGLBufferChanged);
     setting_setup_signal_listener(gSavedSettings, "RenderFSAAType", handleReleaseGLBufferChanged);
     setting_setup_signal_listener(gSavedSettings, "RenderSpecularResX", handleLUTBufferChanged);
diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp
index c219b0575e..52fd75f672 100644
--- a/indra/newview/llviewershadermgr.cpp
+++ b/indra/newview/llviewershadermgr.cpp
@@ -198,6 +198,7 @@ LLGLSLShader            gDeferredPostTonemapProgram;
 LLGLSLShader            gNoPostTonemapProgram;
 LLGLSLShader            gDeferredPostGammaCorrectProgram;
 LLGLSLShader            gLegacyPostGammaCorrectProgram;
+LLGLSLShader            gNoPostGammaCorrectProgram;
 LLGLSLShader            gExposureProgram;
 LLGLSLShader            gExposureProgramNoFade;
 LLGLSLShader            gLuminanceProgram;
@@ -206,6 +207,7 @@ LLGLSLShader            gSMAAEdgeDetectProgram[4];
 LLGLSLShader            gSMAABlendWeightsProgram[4];
 LLGLSLShader            gSMAANeighborhoodBlendProgram[4];
 LLGLSLShader            gCASProgram;
+LLGLSLShader            gCASLegacyGammaProgram;
 LLGLSLShader            gDeferredPostNoDoFProgram;
 LLGLSLShader            gDeferredPostNoDoFNoiseProgram;
 LLGLSLShader            gDeferredWLSkyProgram;
@@ -434,8 +436,8 @@ void LLViewerShaderMgr::finalizeShaderList()
     mShaderList.push_back(&gHUDPBRAlphaProgram);
     mShaderList.push_back(&gDeferredPostTonemapProgram);
     mShaderList.push_back(&gNoPostTonemapProgram);
-    mShaderList.push_back(&gDeferredPostGammaCorrectProgram); // for gamma
-    mShaderList.push_back(&gLegacyPostGammaCorrectProgram);
+    mShaderList.push_back(&gLegacyPostGammaCorrectProgram); // for gamma
+    mShaderList.push_back(&gCASLegacyGammaProgram); // for gamma
     mShaderList.push_back(&gDeferredDiffuseProgram);
     mShaderList.push_back(&gDeferredBumpProgram);
     mShaderList.push_back(&gDeferredPBROpaqueProgram);
@@ -2326,8 +2328,10 @@ bool LLViewerShaderMgr::loadShadersDeferred()
         gDeferredPostGammaCorrectProgram.mFeatures.isDeferred = true;
         gDeferredPostGammaCorrectProgram.mShaderFiles.clear();
         gDeferredPostGammaCorrectProgram.clearPermutations();
+        gDeferredPostGammaCorrectProgram.addPermutation("TONEMAP", "1");
+        gDeferredPostGammaCorrectProgram.addPermutation("GAMMA_CORRECT", "1");
         gDeferredPostGammaCorrectProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoTCV.glsl", GL_VERTEX_SHADER));
-        gDeferredPostGammaCorrectProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredGammaCorrect.glsl", GL_FRAGMENT_SHADER));
+        gDeferredPostGammaCorrectProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredTonemap.glsl", GL_FRAGMENT_SHADER));
         gDeferredPostGammaCorrectProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
         success = gDeferredPostGammaCorrectProgram.createShader();
         llassert(success);
@@ -2340,14 +2344,30 @@ bool LLViewerShaderMgr::loadShadersDeferred()
         gLegacyPostGammaCorrectProgram.mFeatures.isDeferred = true;
         gLegacyPostGammaCorrectProgram.mShaderFiles.clear();
         gLegacyPostGammaCorrectProgram.clearPermutations();
+        gLegacyPostGammaCorrectProgram.addPermutation("GAMMA_CORRECT", "1");
         gLegacyPostGammaCorrectProgram.addPermutation("LEGACY_GAMMA", "1");
         gLegacyPostGammaCorrectProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoTCV.glsl", GL_VERTEX_SHADER));
-        gLegacyPostGammaCorrectProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredGammaCorrect.glsl", GL_FRAGMENT_SHADER));
+        gLegacyPostGammaCorrectProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredTonemap.glsl", GL_FRAGMENT_SHADER));
         gLegacyPostGammaCorrectProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
         success = gLegacyPostGammaCorrectProgram.createShader();
         llassert(success);
     }
 
+    if (success)
+    {
+        gNoPostGammaCorrectProgram.mName = "No Post Gamma Correction Post Process";
+        gNoPostGammaCorrectProgram.mFeatures.hasSrgb = true;
+        gNoPostGammaCorrectProgram.mFeatures.isDeferred = true;
+        gNoPostGammaCorrectProgram.mShaderFiles.clear();
+        gNoPostGammaCorrectProgram.clearPermutations();
+        gNoPostGammaCorrectProgram.addPermutation("GAMMA_CORRECT", "1");
+        gNoPostGammaCorrectProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoTCV.glsl", GL_VERTEX_SHADER));
+        gNoPostGammaCorrectProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredTonemap.glsl", GL_FRAGMENT_SHADER));
+        gNoPostGammaCorrectProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
+        success = gNoPostGammaCorrectProgram.createShader();
+        llassert(success);
+    }
+
     if (success)
     {
         gDeferredPostTonemapProgram.mName = "Deferred Tonemap Post Process";
@@ -2355,6 +2375,7 @@ bool LLViewerShaderMgr::loadShadersDeferred()
         gDeferredPostTonemapProgram.mFeatures.isDeferred = true;
         gDeferredPostTonemapProgram.mShaderFiles.clear();
         gDeferredPostTonemapProgram.clearPermutations();
+        gDeferredPostTonemapProgram.addPermutation("TONEMAP", "1");
         gDeferredPostTonemapProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoTCV.glsl", GL_VERTEX_SHADER));
         gDeferredPostTonemapProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredTonemap.glsl", GL_FRAGMENT_SHADER));
         gDeferredPostTonemapProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
@@ -2369,6 +2390,7 @@ bool LLViewerShaderMgr::loadShadersDeferred()
         gNoPostTonemapProgram.mFeatures.isDeferred = true;
         gNoPostTonemapProgram.mShaderFiles.clear();
         gNoPostTonemapProgram.clearPermutations();
+        gNoPostTonemapProgram.addPermutation("TONEMAP", "1");
         gNoPostTonemapProgram.addPermutation("NO_POST", "1");
         gNoPostTonemapProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoTCV.glsl", GL_VERTEX_SHADER));
         gNoPostTonemapProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredTonemap.glsl", GL_FRAGMENT_SHADER));
@@ -2498,6 +2520,19 @@ bool LLViewerShaderMgr::loadShadersDeferred()
         gCASProgram.createShader();
     }
 
+    if (success)
+    {
+        gCASLegacyGammaProgram.mName = "Contrast Adaptive Sharpening Legacy Gamma Shader";
+        gCASLegacyGammaProgram.mFeatures.hasSrgb = true;
+        gCASLegacyGammaProgram.clearPermutations();
+        gCASLegacyGammaProgram.addPermutation("LEGACY_GAMMA", "1");
+        gCASLegacyGammaProgram.mShaderFiles.clear();
+        gCASLegacyGammaProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoTCV.glsl", GL_VERTEX_SHADER));
+        gCASLegacyGammaProgram.mShaderFiles.push_back(make_pair("deferred/CASF.glsl", GL_FRAGMENT_SHADER));
+        gCASLegacyGammaProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
+        gCASLegacyGammaProgram.createShader();
+    }
+
     if (success)
     {
         gDeferredPostProgram.mName = "Deferred Post Shader";
@@ -2546,22 +2581,6 @@ bool LLViewerShaderMgr::loadShadersDeferred()
         llassert(success);
     }
 
-    if (success)
-    {
-        gDeferredPostNoDoFNoiseProgram.mName = "Deferred Post NoDoF Noise Shader";
-        gDeferredPostNoDoFNoiseProgram.mFeatures.isDeferred = true;
-        gDeferredPostNoDoFNoiseProgram.mShaderFiles.clear();
-        gDeferredPostNoDoFNoiseProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoTCV.glsl", GL_VERTEX_SHADER));
-        gDeferredPostNoDoFNoiseProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoDoFF.glsl", GL_FRAGMENT_SHADER));
-
-        gDeferredPostNoDoFNoiseProgram.clearPermutations();
-        gDeferredPostNoDoFNoiseProgram.addPermutation("HAS_NOISE", "1");
-
-        gDeferredPostNoDoFNoiseProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
-        success = gDeferredPostNoDoFNoiseProgram.createShader();
-        llassert(success);
-    }
-
     if (success)
     {
         gEnvironmentMapProgram.mName = "Environment Map Program";
diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h
index e654967c46..afc29e6fd2 100644
--- a/indra/newview/llviewershadermgr.h
+++ b/indra/newview/llviewershadermgr.h
@@ -251,10 +251,11 @@ extern LLGLSLShader         gSMAAEdgeDetectProgram[4];
 extern LLGLSLShader         gSMAABlendWeightsProgram[4];
 extern LLGLSLShader         gSMAANeighborhoodBlendProgram[4];
 extern LLGLSLShader         gCASProgram;
+extern LLGLSLShader         gCASLegacyGammaProgram;
 extern LLGLSLShader         gDeferredPostNoDoFProgram;
-extern LLGLSLShader         gDeferredPostNoDoFNoiseProgram;
 extern LLGLSLShader         gDeferredPostGammaCorrectProgram;
 extern LLGLSLShader         gLegacyPostGammaCorrectProgram;
+extern LLGLSLShader         gNoPostGammaCorrectProgram;
 extern LLGLSLShader         gDeferredPostTonemapProgram;
 extern LLGLSLShader         gNoPostTonemapProgram;
 extern LLGLSLShader         gExposureProgram;
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index 0b4b98d674..541208b133 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -828,8 +828,9 @@ bool LLPipeline::allocateScreenBufferInternal(U32 resX, U32 resY)
 
     mRT->deferredScreen.shareDepthBuffer(mRT->screen);
 
-    if (shadow_detail > 0 || ssao || RenderDepthOfField)
-    { //only need mRT->deferredLight for shadows OR ssao OR dof
+    static LLCachedControl<bool> render_cas(gSavedSettings, "RenderCAS", true);
+    if (shadow_detail > 0 || ssao || render_cas)
+    { //only need mRT->deferredLight for shadows OR ssao
         if (!mRT->deferredLight.allocate(resX, resY, GL_RGBA16F)) return false;
     }
     else
@@ -849,13 +850,18 @@ bool LLPipeline::allocateScreenBufferInternal(U32 resX, U32 resY)
             }
         }
 
-        if (RenderFSAAType > 0)
+        if (RenderFSAAType > 0 || RenderDepthOfField)
         {
             if (!mFXAAMap.allocate(resX, resY, GL_RGBA)) return false;
             if (RenderFSAAType == 2)
             {
                 if (!mSMAABlendBuffer.allocate(resX, resY, GL_RGBA, false)) return false;
             }
+            else
+            {
+                mSMAABlendBuffer.release();
+            }
+
         }
         else
         {
@@ -875,7 +881,8 @@ bool LLPipeline::allocateScreenBufferInternal(U32 resX, U32 resY)
             mSceneMap.release();
         }
 
-        mPostMap.allocate(resX, resY, GL_RGBA16F);
+        mPostPingMap.allocate(resX, resY, GL_RGBA);
+        mPostPongMap.allocate(resX, resY, GL_RGBA);
 
         // used to scale down textures
         // See LLViwerTextureList::updateImagesCreateTextures and LLImageGL::scaleDown
@@ -1133,7 +1140,8 @@ void LLPipeline::releaseGLBuffers()
 
     mSceneMap.release();
 
-    mPostMap.release();
+    mPostPingMap.release();
+    mPostPongMap.release();
 
     mFXAAMap.release();
 
@@ -7047,7 +7055,7 @@ void LLPipeline::generateExposure(LLRenderTarget* src, LLRenderTarget* dst, bool
 
 extern LLPointer<LLImageGL> gEXRImage;
 
-void LLPipeline::tonemap(LLRenderTarget* src, LLRenderTarget* dst)
+void LLPipeline::tonemap(LLRenderTarget* src, LLRenderTarget* dst, bool gamma_correct/* = true*/)
 {
     dst->bindTarget();
     // gamma correct lighting
@@ -7064,18 +7072,26 @@ void LLPipeline::tonemap(LLRenderTarget* src, LLRenderTarget* dst)
 
         LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky();
 
-        bool no_post = gSnapshotNoPost || psky->getReflectionProbeAmbiance(should_auto_adjust) == 0.f || (buildNoPost && gFloaterTools->isAvailable());
-        LLGLSLShader& shader = no_post ? gNoPostTonemapProgram : gDeferredPostTonemapProgram;
+        bool no_post = gSnapshotNoPost || (buildNoPost && gFloaterTools->isAvailable());
+        LLGLSLShader* shader = nullptr;
+        if (gamma_correct)
+        {
+            shader = no_post ? &gNoPostGammaCorrectProgram : // no post (no gamma, no exposure, no tonemapping)
+                psky->getReflectionProbeAmbiance(should_auto_adjust) == 0.f ? &gLegacyPostGammaCorrectProgram :
+                &gDeferredPostGammaCorrectProgram;
+        }
+        else
+        {
+            shader = (psky->getReflectionProbeAmbiance(should_auto_adjust) == 0.f || no_post) ? &gNoPostTonemapProgram : &gDeferredPostTonemapProgram;
+        }
 
-        shader.bind();
+        shader->bind();
 
         S32 channel = 0;
 
-        shader.bindTexture(LLShaderMgr::DEFERRED_DIFFUSE, src, false, LLTexUnit::TFO_POINT);
-
-        shader.bindTexture(LLShaderMgr::EXPOSURE_MAP, &mExposureMap);
-
-        shader.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, (GLfloat)src->getWidth(), (GLfloat)src->getHeight());
+        shader->bindTexture(LLShaderMgr::DEFERRED_DIFFUSE, src, false, LLTexUnit::TFO_POINT);
+        shader->bindTexture(LLShaderMgr::EXPOSURE_MAP, &mExposureMap);
+        shader->uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, (GLfloat)src->getWidth(), (GLfloat)src->getHeight());
 
         static LLCachedControl<F32> exposure(gSavedSettings, "RenderExposure", 1.f);
 
@@ -7085,47 +7101,19 @@ void LLPipeline::tonemap(LLRenderTarget* src, LLRenderTarget* dst)
         static LLStaticHashedString tonemap_mix("tonemap_mix");
         static LLStaticHashedString tonemap_type("tonemap_type");
 
-        shader.uniform1f(s_exposure, e);
+        shader->uniform1f(s_exposure, e);
 
         static LLCachedControl<U32> tonemap_type_setting(gSavedSettings, "RenderTonemapType", 0U);
-        shader.uniform1i(tonemap_type, tonemap_type_setting);
+        shader->uniform1i(tonemap_type, tonemap_type_setting);
 
         static LLCachedControl<F32> tonemap_mix_setting(gSavedSettings, "RenderTonemapMix", 1.f);
-        shader.uniform1f(tonemap_mix, tonemap_mix_setting);
+        shader->uniform1f(tonemap_mix, tonemap_mix_setting);
 
         mScreenTriangleVB->setBuffer();
         mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3);
 
         gGL.getTexUnit(channel)->unbind(src->getUsage());
-        shader.unbind();
-    }
-    dst->flush();
-}
-
-void LLPipeline::gammaCorrect(LLRenderTarget* src, LLRenderTarget* dst)
-{
-    dst->bindTarget();
-    // gamma correct lighting
-    {
-        LL_PROFILE_GPU_ZONE("gamma correct");
-
-        LLGLDepthTest depth(GL_FALSE, GL_FALSE);
-
-        static LLCachedControl<bool> buildNoPost(gSavedSettings, "RenderDisablePostProcessing", false);
-        static LLCachedControl<bool> should_auto_adjust(gSavedSettings, "RenderSkyAutoAdjustLegacy", true);
-
-        LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky();
-        LLGLSLShader& shader = psky->getReflectionProbeAmbiance(should_auto_adjust) == 0.f ? gLegacyPostGammaCorrectProgram :
-            gDeferredPostGammaCorrectProgram;
-
-        shader.bind();
-        shader.bindTexture(LLShaderMgr::DEFERRED_DIFFUSE, src, false, LLTexUnit::TFO_POINT);
-        shader.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, (GLfloat)src->getWidth(), (GLfloat)src->getHeight());
-
-        mScreenTriangleVB->setBuffer();
-        mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3);
-
-        shader.unbind();
+        shader->unbind();
     }
     dst->flush();
 }
@@ -7270,13 +7258,10 @@ void LLPipeline::generateGlow(LLRenderTarget* src)
 void LLPipeline::applyCAS(LLRenderTarget* src, LLRenderTarget* dst)
 {
     static LLCachedControl<F32> cas_sharpness(gSavedSettings, "RenderCASSharpness", 0.4f);
-    if (cas_sharpness == 0.0f || !gCASProgram.isComplete())
-    {
-        gPipeline.copyRenderTarget(src, dst);
-        return;
-    }
+    static LLCachedControl<bool> should_auto_adjust(gSavedSettings, "RenderSkyAutoAdjustLegacy", true);
 
-    LLGLSLShader* sharpen_shader = &gCASProgram;
+    LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky();
+    LLGLSLShader* sharpen_shader = psky->getReflectionProbeAmbiance(should_auto_adjust) == 0.f ? &gCASLegacyGammaProgram : &gCASProgram;
 
     // Bind setup:
     dst->bindTarget();
@@ -7314,88 +7299,78 @@ void LLPipeline::applyCAS(LLRenderTarget* src, LLRenderTarget* dst)
 
 void LLPipeline::applyFXAA(LLRenderTarget* src, LLRenderTarget* dst)
 {
-    {
-        llassert(!gCubeSnapshot);
-        bool multisample = RenderFSAAType == 1 && mFXAAMap.isComplete();
-        LLGLSLShader* shader = &gGlowCombineProgram;
-
-        // Present everything.
-        if (multisample)
-        {
-            LL_PROFILE_GPU_ZONE("aa");
-            S32 width = dst->getWidth();
-            S32 height = dst->getHeight();
+    llassert(!gCubeSnapshot);
+    LLGLSLShader* shader = &gGlowCombineProgram;
 
-            // bake out texture2D with RGBL for FXAA shader
-            mFXAAMap.bindTarget();
-            mFXAAMap.invalidate(GL_COLOR_BUFFER_BIT);
+    LL_PROFILE_GPU_ZONE("aa");
+    S32 width = dst->getWidth();
+    S32 height = dst->getHeight();
 
-            shader = &gGlowCombineFXAAProgram;
-            shader->bind();
+    // bake out texture2D with RGBL for FXAA shader
+    mFXAAMap.bindTarget();
+    mFXAAMap.invalidate(GL_COLOR_BUFFER_BIT);
 
-            S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, src->getUsage());
-            if (channel > -1)
-            {
-                src->bindTexture(0, channel, LLTexUnit::TFO_BILINEAR);
-            }
+    shader = &gGlowCombineFXAAProgram;
+    shader->bind();
 
-            {
-                LLGLDepthTest depth_test(GL_TRUE, GL_TRUE, GL_ALWAYS);
-                mScreenTriangleVB->setBuffer();
-                mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3);
-            }
+    S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, src->getUsage());
+    if (channel > -1)
+    {
+        src->bindTexture(0, channel, LLTexUnit::TFO_BILINEAR);
+    }
 
-            shader->disableTexture(LLShaderMgr::DEFERRED_DIFFUSE, src->getUsage());
-            shader->unbind();
+    {
+        LLGLDepthTest depth_test(GL_TRUE, GL_TRUE, GL_ALWAYS);
+        mScreenTriangleVB->setBuffer();
+        mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3);
+    }
 
-            mFXAAMap.flush();
+    shader->disableTexture(LLShaderMgr::DEFERRED_DIFFUSE, src->getUsage());
+    shader->unbind();
 
-            dst->bindTarget();
+    mFXAAMap.flush();
 
-            static LLCachedControl<U32> aa_quality(gSavedSettings, "RenderFSAASamples", 0U);
-            U32 fsaa_quality = std::clamp(aa_quality(), 0U, 3U);
+    dst->bindTarget();
 
-            shader = &gFXAAProgram[fsaa_quality];
-            shader->bind();
+    static LLCachedControl<U32> aa_quality(gSavedSettings, "RenderFSAASamples", 0U);
+    U32 fsaa_quality = std::clamp(aa_quality(), 0U, 3U);
 
-            channel = shader->enableTexture(LLShaderMgr::DIFFUSE_MAP, mFXAAMap.getUsage());
-            if (channel > -1)
-            {
-                mFXAAMap.bindTexture(0, channel, LLTexUnit::TFO_BILINEAR);
-            }
+    shader = &gFXAAProgram[fsaa_quality];
+    shader->bind();
 
-            gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft;
-            gGLViewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom;
-            gGLViewport[2] = gViewerWindow->getWorldViewRectRaw().getWidth();
-            gGLViewport[3] = gViewerWindow->getWorldViewRectRaw().getHeight();
+    channel = shader->enableTexture(LLShaderMgr::DIFFUSE_MAP, mFXAAMap.getUsage());
+    if (channel > -1)
+    {
+        mFXAAMap.bindTexture(0, channel, LLTexUnit::TFO_BILINEAR);
+    }
 
-            glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
+    gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft;
+    gGLViewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom;
+    gGLViewport[2] = gViewerWindow->getWorldViewRectRaw().getWidth();
+    gGLViewport[3] = gViewerWindow->getWorldViewRectRaw().getHeight();
 
-            F32 scale_x = (F32)width / mFXAAMap.getWidth();
-            F32 scale_y = (F32)height / mFXAAMap.getHeight();
-            shader->uniform2f(LLShaderMgr::FXAA_TC_SCALE, scale_x, scale_y);
-            shader->uniform2f(LLShaderMgr::FXAA_RCP_SCREEN_RES, 1.f / width * scale_x, 1.f / height * scale_y);
-            shader->uniform4f(LLShaderMgr::FXAA_RCP_FRAME_OPT, -0.5f / width * scale_x, -0.5f / height * scale_y,
-                0.5f / width * scale_x, 0.5f / height * scale_y);
-            shader->uniform4f(LLShaderMgr::FXAA_RCP_FRAME_OPT2, -2.f / width * scale_x, -2.f / height * scale_y,
-                2.f / width * scale_x, 2.f / height * scale_y);
+    glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
 
-            {
-                LLGLDepthTest depth_test(GL_TRUE, GL_TRUE, GL_ALWAYS);
-                S32 depth_channel = shader->getTextureChannel(LLShaderMgr::DEFERRED_DEPTH);
-                gGL.getTexUnit(depth_channel)->bind(&mRT->deferredScreen, true);
+    F32 scale_x = (F32)width / mFXAAMap.getWidth();
+    F32 scale_y = (F32)height / mFXAAMap.getHeight();
+    shader->uniform2f(LLShaderMgr::FXAA_TC_SCALE, scale_x, scale_y);
+    shader->uniform2f(LLShaderMgr::FXAA_RCP_SCREEN_RES, 1.f / width * scale_x, 1.f / height * scale_y);
+    shader->uniform4f(LLShaderMgr::FXAA_RCP_FRAME_OPT, -0.5f / width * scale_x, -0.5f / height * scale_y,
+        0.5f / width * scale_x, 0.5f / height * scale_y);
+    shader->uniform4f(LLShaderMgr::FXAA_RCP_FRAME_OPT2, -2.f / width * scale_x, -2.f / height * scale_y,
+        2.f / width * scale_x, 2.f / height * scale_y);
 
-                mScreenTriangleVB->setBuffer();
-                mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3);
-            }
+    {
+        LLGLDepthTest depth_test(GL_TRUE, GL_TRUE, GL_ALWAYS);
+        S32 depth_channel = shader->getTextureChannel(LLShaderMgr::DEFERRED_DEPTH);
+        gGL.getTexUnit(depth_channel)->bind(&mRT->deferredScreen, true);
 
-            shader->unbind();
-            dst->flush();
-        }
-        else {
-            copyRenderTarget(src, dst);
-        }
+        mScreenTriangleVB->setBuffer();
+        mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3);
     }
+
+    shader->unbind();
+    dst->flush();
 }
 
 void LLPipeline::generateSMAABuffers(LLRenderTarget* src)
@@ -7520,63 +7495,54 @@ void LLPipeline::generateSMAABuffers(LLRenderTarget* src)
 void LLPipeline::applySMAA(LLRenderTarget* src, LLRenderTarget* dst)
 {
     llassert(!gCubeSnapshot);
-    bool multisample = RenderFSAAType == 2 && mFXAAMap.isComplete() && mSMAABlendBuffer.isComplete();
 
-    // Present everything.
-    if (multisample)
-    {
-        LL_PROFILE_GPU_ZONE("aa");
-        static LLCachedControl<U32> aa_quality(gSavedSettings, "RenderFSAASamples", 0U);
-        U32 fsaa_quality = std::clamp(aa_quality(), 0U, 3U);
+    LL_PROFILE_GPU_ZONE("aa");
+    static LLCachedControl<U32> aa_quality(gSavedSettings, "RenderFSAASamples", 0U);
+    U32 fsaa_quality = std::clamp(aa_quality(), 0U, 3U);
 
-        S32 width = src->getWidth();
-        S32 height = src->getHeight();
+    S32 width = src->getWidth();
+    S32 height = src->getHeight();
 
-        float rt_metrics[] = { 1.f / width, 1.f / height, (float)width, (float)height };
+    float rt_metrics[] = { 1.f / width, 1.f / height, (float)width, (float)height };
 
-        LLGLDepthTest    depth(GL_FALSE, GL_FALSE);
+    LLGLDepthTest    depth(GL_FALSE, GL_FALSE);
 
-        static LLCachedControl<bool> use_sample(gSavedSettings, "RenderSMAAUseSample", false);
-        //static LLCachedControl<bool> use_stencil(gSavedSettings, "RenderSMAAUseStencil", true);
+    static LLCachedControl<bool> use_sample(gSavedSettings, "RenderSMAAUseSample", false);
+    //static LLCachedControl<bool> use_stencil(gSavedSettings, "RenderSMAAUseStencil", true);
 
-        {
-            //LLGLDisable stencil(GL_STENCIL_TEST);
+    {
+        //LLGLDisable stencil(GL_STENCIL_TEST);
 
-            // Bind setup:
-            LLRenderTarget* bound_target = dst;
-            LLGLSLShader& blend_shader = gSMAANeighborhoodBlendProgram[fsaa_quality];
+        // Bind setup:
+        LLRenderTarget* bound_target = dst;
+        LLGLSLShader& blend_shader = gSMAANeighborhoodBlendProgram[fsaa_quality];
 
-            bound_target->bindTarget();
-            bound_target->invalidate(GL_COLOR_BUFFER_BIT);
+        bound_target->bindTarget();
+        bound_target->invalidate(GL_COLOR_BUFFER_BIT);
 
-            blend_shader.bind();
-            blend_shader.uniform4fv(sSmaaRTMetrics, 1, rt_metrics);
+        blend_shader.bind();
+        blend_shader.uniform4fv(sSmaaRTMetrics, 1, rt_metrics);
 
-            S32 diffuse_channel = blend_shader.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE);
-            if(diffuse_channel > -1)
-            {
-                src->bindTexture(0, diffuse_channel, LLTexUnit::TFO_BILINEAR);
-                gGL.getTexUnit(diffuse_channel)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
-            }
+        S32 diffuse_channel = blend_shader.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE);
+        if(diffuse_channel > -1)
+        {
+            src->bindTexture(0, diffuse_channel, LLTexUnit::TFO_BILINEAR);
+            gGL.getTexUnit(diffuse_channel)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
+        }
 
-            S32 blend_channel = blend_shader.enableTexture(LLShaderMgr::SMAA_BLEND_TEX);
-            if (blend_channel > -1)
-            {
-                mSMAABlendBuffer.bindTexture(0, blend_channel, LLTexUnit::TFO_BILINEAR);
-            }
+        S32 blend_channel = blend_shader.enableTexture(LLShaderMgr::SMAA_BLEND_TEX);
+        if (blend_channel > -1)
+        {
+            mSMAABlendBuffer.bindTexture(0, blend_channel, LLTexUnit::TFO_BILINEAR);
+        }
 
-            mScreenTriangleVB->setBuffer();
-            mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3);
+        mScreenTriangleVB->setBuffer();
+        mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3);
 
-            bound_target->flush();
-            blend_shader.unbind();
-            gGL.getTexUnit(diffuse_channel)->unbindFast(LLTexUnit::TT_TEXTURE);
-            gGL.getTexUnit(blend_channel)->unbindFast(LLTexUnit::TT_TEXTURE);
-        }
-    }
-    else
-    {
-        copyRenderTarget(src, dst);
+        bound_target->flush();
+        blend_shader.unbind();
+        gGL.getTexUnit(diffuse_channel)->unbindFast(LLTexUnit::TT_TEXTURE);
+        gGL.getTexUnit(blend_channel)->unbindFast(LLTexUnit::TT_TEXTURE);
     }
 }
 
@@ -7623,198 +7589,186 @@ void LLPipeline::combineGlow(LLRenderTarget* src, LLRenderTarget* dst)
 
 void LLPipeline::renderDoF(LLRenderTarget* src, LLRenderTarget* dst)
 {
-    {
-        bool dof_enabled =
-            (RenderDepthOfFieldInEditMode || !LLToolMgr::getInstance()->inBuildMode()) &&
-            RenderDepthOfField &&
-            !gCubeSnapshot;
-
-        gViewerWindow->setup3DViewport();
-
-        if (dof_enabled)
-        {
-            LL_PROFILE_GPU_ZONE("dof");
-            LLGLDisable blend(GL_BLEND);
+    gViewerWindow->setup3DViewport();
 
-            // depth of field focal plane calculations
-            static F32 current_distance = 16.f;
-            static F32 start_distance = 16.f;
-            static F32 transition_time = 1.f;
+    LL_PROFILE_GPU_ZONE("dof");
+    LLGLDisable blend(GL_BLEND);
 
-            LLVector3 focus_point;
+    // depth of field focal plane calculations
+    static F32 current_distance = 16.f;
+    static F32 start_distance = 16.f;
+    static F32 transition_time = 1.f;
 
-            LLViewerObject* obj = LLViewerMediaFocus::getInstance()->getFocusedObject();
-            if (obj && obj->mDrawable && obj->isSelected())
-            { // focus on selected media object
-                S32 face_idx = LLViewerMediaFocus::getInstance()->getFocusedFace();
-                if (obj && obj->mDrawable)
-                {
-                    LLFace* face = obj->mDrawable->getFace(face_idx);
-                    if (face)
-                    {
-                        focus_point = face->getPositionAgent();
-                    }
-                }
-            }
+    LLVector3 focus_point;
 
-            if (focus_point.isExactlyZero())
+    LLViewerObject* obj = LLViewerMediaFocus::getInstance()->getFocusedObject();
+    if (obj && obj->mDrawable && obj->isSelected())
+    { // focus on selected media object
+        S32 face_idx = LLViewerMediaFocus::getInstance()->getFocusedFace();
+        if (obj && obj->mDrawable)
+        {
+            LLFace* face = obj->mDrawable->getFace(face_idx);
+            if (face)
             {
-                if (LLViewerJoystick::getInstance()->getOverrideCamera())
-                { // focus on point under cursor
-                    focus_point.set(gDebugRaycastIntersection.getF32ptr());
-                }
-                else if (gAgentCamera.cameraMouselook())
-                { // focus on point under mouselook crosshairs
-                    LLVector4a result;
-                    result.clear();
+                focus_point = face->getPositionAgent();
+            }
+        }
+    }
 
-                    gViewerWindow->cursorIntersect(-1, -1, 512.f, nullptr, -1, false, false, true, true, nullptr, nullptr, nullptr, &result);
+    if (focus_point.isExactlyZero())
+    {
+        if (LLViewerJoystick::getInstance()->getOverrideCamera())
+        { // focus on point under cursor
+            focus_point.set(gDebugRaycastIntersection.getF32ptr());
+        }
+        else if (gAgentCamera.cameraMouselook())
+        { // focus on point under mouselook crosshairs
+            LLVector4a result;
+            result.clear();
 
-                    focus_point.set(result.getF32ptr());
-                }
-                else
-                {
-                    // focus on alt-zoom target
-                    LLViewerRegion* region = gAgent.getRegion();
-                    if (region)
-                    {
-                        focus_point = LLVector3(gAgentCamera.getFocusGlobal() - region->getOriginGlobal());
-                    }
-                }
-            }
+            gViewerWindow->cursorIntersect(-1, -1, 512.f, nullptr, -1, false, false, true, true, nullptr, nullptr, nullptr, &result);
 
-            LLVector3 eye = LLViewerCamera::getInstance()->getOrigin();
-            F32 target_distance = 16.f;
-            if (!focus_point.isExactlyZero())
+            focus_point.set(result.getF32ptr());
+        }
+        else
+        {
+            // focus on alt-zoom target
+            LLViewerRegion* region = gAgent.getRegion();
+            if (region)
             {
-                target_distance = LLViewerCamera::getInstance()->getAtAxis() * (focus_point - eye);
+                focus_point = LLVector3(gAgentCamera.getFocusGlobal() - region->getOriginGlobal());
             }
+        }
+    }
 
-            if (transition_time >= 1.f && fabsf(current_distance - target_distance) / current_distance > 0.01f)
-            { // large shift happened, interpolate smoothly to new target distance
-                transition_time = 0.f;
-                start_distance = current_distance;
-            }
-            else if (transition_time < 1.f)
-            { // currently in a transition, continue interpolating
-                transition_time += 1.f / CameraFocusTransitionTime * gFrameIntervalSeconds.value();
-                transition_time = llmin(transition_time, 1.f);
+    LLVector3 eye = LLViewerCamera::getInstance()->getOrigin();
+    F32 target_distance = 16.f;
+    if (!focus_point.isExactlyZero())
+    {
+        target_distance = LLViewerCamera::getInstance()->getAtAxis() * (focus_point - eye);
+    }
 
-                F32 t = cosf(transition_time * F_PI + F_PI) * 0.5f + 0.5f;
-                current_distance = start_distance + (target_distance - start_distance) * t;
-            }
-            else
-            { // small or no change, just snap to target distance
-                current_distance = target_distance;
-            }
+    if (transition_time >= 1.f && fabsf(current_distance - target_distance) / current_distance > 0.01f)
+    { // large shift happened, interpolate smoothly to new target distance
+        transition_time = 0.f;
+        start_distance = current_distance;
+    }
+    else if (transition_time < 1.f)
+    { // currently in a transition, continue interpolating
+        transition_time += 1.f / CameraFocusTransitionTime * gFrameIntervalSeconds.value();
+        transition_time = llmin(transition_time, 1.f);
 
-            // convert to mm
-            F32 subject_distance = current_distance * 1000.f;
-            F32 fnumber = CameraFNumber;
-            F32 default_focal_length = CameraFocalLength;
+        F32 t = cosf(transition_time * F_PI + F_PI) * 0.5f + 0.5f;
+        current_distance = start_distance + (target_distance - start_distance) * t;
+    }
+    else
+    { // small or no change, just snap to target distance
+        current_distance = target_distance;
+    }
 
-            F32 fov = LLViewerCamera::getInstance()->getView();
+    // convert to mm
+    F32 subject_distance = current_distance * 1000.f;
+    F32 fnumber = CameraFNumber;
+    F32 default_focal_length = CameraFocalLength;
 
-            const F32 default_fov = CameraFieldOfView * F_PI / 180.f;
+    F32 fov = LLViewerCamera::getInstance()->getView();
 
-            // F32 aspect_ratio = (F32) mRT->screen.getWidth()/(F32)mRT->screen.getHeight();
+    const F32 default_fov = CameraFieldOfView * F_PI / 180.f;
 
-            F32 dv = 2.f * default_focal_length * tanf(default_fov / 2.f);
+    // F32 aspect_ratio = (F32) mRT->screen.getWidth()/(F32)mRT->screen.getHeight();
 
-            F32 focal_length = dv / (2 * tanf(fov / 2.f));
+    F32 dv = 2.f * default_focal_length * tanf(default_fov / 2.f);
 
-            // F32 tan_pixel_angle = tanf(LLDrawable::sCurPixelAngle);
+    F32 focal_length = dv / (2 * tanf(fov / 2.f));
 
-            // from wikipedia -- c = |s2-s1|/s2 * f^2/(N(S1-f))
-            // where     N = fnumber
-            //           s2 = dot distance
-            //           s1 = subject distance
-            //           f = focal length
-            //
+    // F32 tan_pixel_angle = tanf(LLDrawable::sCurPixelAngle);
 
-            F32 blur_constant = focal_length * focal_length / (fnumber * (subject_distance - focal_length));
-            blur_constant /= 1000.f; // convert to meters for shader
-            F32 magnification = focal_length / (subject_distance - focal_length);
+    // from wikipedia -- c = |s2-s1|/s2 * f^2/(N(S1-f))
+    // where     N = fnumber
+    //           s2 = dot distance
+    //           s1 = subject distance
+    //           f = focal length
+    //
 
-            { // build diffuse+bloom+CoF
-                mRT->deferredLight.bindTarget();
+    F32 blur_constant = focal_length * focal_length / (fnumber * (subject_distance - focal_length));
+    blur_constant /= 1000.f; // convert to meters for shader
+    F32 magnification = focal_length / (subject_distance - focal_length);
 
-                gDeferredCoFProgram.bind();
+    { // build diffuse+bloom+CoF
+        mFXAAMap.bindTarget();
 
-                gDeferredCoFProgram.bindTexture(LLShaderMgr::DEFERRED_DIFFUSE, src, LLTexUnit::TFO_POINT);
-                gDeferredCoFProgram.bindTexture(LLShaderMgr::DEFERRED_DEPTH, &mRT->deferredScreen, true);
+        gDeferredCoFProgram.bind();
 
-                gDeferredCoFProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, (GLfloat)dst->getWidth(), (GLfloat)dst->getHeight());
-                gDeferredCoFProgram.uniform1f(LLShaderMgr::DOF_FOCAL_DISTANCE, -subject_distance / 1000.f);
-                gDeferredCoFProgram.uniform1f(LLShaderMgr::DOF_BLUR_CONSTANT, blur_constant);
-                gDeferredCoFProgram.uniform1f(LLShaderMgr::DOF_TAN_PIXEL_ANGLE, tanf(1.f / LLDrawable::sCurPixelAngle));
-                gDeferredCoFProgram.uniform1f(LLShaderMgr::DOF_MAGNIFICATION, magnification);
-                gDeferredCoFProgram.uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF);
-                gDeferredCoFProgram.uniform1f(LLShaderMgr::DOF_RES_SCALE, CameraDoFResScale);
+        gDeferredCoFProgram.bindTexture(LLShaderMgr::DEFERRED_DIFFUSE, src, LLTexUnit::TFO_POINT);
+        gDeferredCoFProgram.bindTexture(LLShaderMgr::DEFERRED_DEPTH, &mRT->deferredScreen, true);
 
-                mScreenTriangleVB->setBuffer();
-                mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3);
-                gDeferredCoFProgram.unbind();
-                mRT->deferredLight.flush();
-            }
+        gDeferredCoFProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, (GLfloat)dst->getWidth(), (GLfloat)dst->getHeight());
+        gDeferredCoFProgram.uniform1f(LLShaderMgr::DOF_FOCAL_DISTANCE, -subject_distance / 1000.f);
+        gDeferredCoFProgram.uniform1f(LLShaderMgr::DOF_BLUR_CONSTANT, blur_constant);
+        gDeferredCoFProgram.uniform1f(LLShaderMgr::DOF_TAN_PIXEL_ANGLE, tanf(1.f / LLDrawable::sCurPixelAngle));
+        gDeferredCoFProgram.uniform1f(LLShaderMgr::DOF_MAGNIFICATION, magnification);
+        gDeferredCoFProgram.uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF);
+        gDeferredCoFProgram.uniform1f(LLShaderMgr::DOF_RES_SCALE, CameraDoFResScale);
 
-            U32 dof_width = (U32)(mRT->screen.getWidth() * CameraDoFResScale);
-            U32 dof_height = (U32)(mRT->screen.getHeight() * CameraDoFResScale);
+        mScreenTriangleVB->setBuffer();
+        mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3);
+        gDeferredCoFProgram.unbind();
+        mFXAAMap.flush();
+    }
 
-            { // perform DoF sampling at half-res (preserve alpha channel)
-                src->bindTarget();
-                glViewport(0, 0, dof_width, dof_height);
+    U32 dof_width = (U32)(mRT->screen.getWidth() * CameraDoFResScale);
+    U32 dof_height = (U32)(mRT->screen.getHeight() * CameraDoFResScale);
 
-                gGL.setColorMask(true, false);
+    { // perform DoF sampling at half-res (preserve alpha channel)
+        src->bindTarget();
+        glViewport(0, 0, dof_width, dof_height);
 
-                gDeferredPostProgram.bind();
-                gDeferredPostProgram.bindTexture(LLShaderMgr::DEFERRED_DIFFUSE, &mRT->deferredLight, LLTexUnit::TFO_POINT);
+        gGL.setColorMask(true, false);
 
-                gDeferredPostProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, (GLfloat)dst->getWidth(), (GLfloat)dst->getHeight());
-                gDeferredPostProgram.uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF);
-                gDeferredPostProgram.uniform1f(LLShaderMgr::DOF_RES_SCALE, CameraDoFResScale);
+        gDeferredPostProgram.bind();
+        gDeferredPostProgram.bindTexture(LLShaderMgr::DEFERRED_DIFFUSE, &mFXAAMap, LLTexUnit::TFO_POINT);
 
-                mScreenTriangleVB->setBuffer();
-                mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3);
+        gDeferredPostProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, (GLfloat)dst->getWidth(), (GLfloat)dst->getHeight());
+        gDeferredPostProgram.uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF);
+        gDeferredPostProgram.uniform1f(LLShaderMgr::DOF_RES_SCALE, CameraDoFResScale);
 
-                gDeferredPostProgram.unbind();
+        mScreenTriangleVB->setBuffer();
+        mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3);
 
-                src->flush();
-                gGL.setColorMask(true, true);
-            }
+        gDeferredPostProgram.unbind();
 
-            { // combine result based on alpha
+        src->flush();
+        gGL.setColorMask(true, true);
+    }
 
-                dst->bindTarget();
-                glViewport(0, 0, dst->getWidth(), dst->getHeight());
+    { // combine result based on alpha
 
-                gDeferredDoFCombineProgram.bind();
-                gDeferredDoFCombineProgram.bindTexture(LLShaderMgr::DEFERRED_DIFFUSE, src, LLTexUnit::TFO_POINT);
-                gDeferredDoFCombineProgram.bindTexture(LLShaderMgr::DEFERRED_LIGHT, &mRT->deferredLight, LLTexUnit::TFO_POINT);
+        dst->bindTarget();
+        glViewport(0, 0, dst->getWidth(), dst->getHeight());
 
-                gDeferredDoFCombineProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, (GLfloat)dst->getWidth(), (GLfloat)dst->getHeight());
-                gDeferredDoFCombineProgram.uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF);
-                gDeferredDoFCombineProgram.uniform1f(LLShaderMgr::DOF_RES_SCALE, CameraDoFResScale);
-                gDeferredDoFCombineProgram.uniform1f(LLShaderMgr::DOF_WIDTH, (dof_width - 1) / (F32)src->getWidth());
-                gDeferredDoFCombineProgram.uniform1f(LLShaderMgr::DOF_HEIGHT, (dof_height - 1) / (F32)src->getHeight());
+        gDeferredDoFCombineProgram.bind();
+        gDeferredDoFCombineProgram.bindTexture(LLShaderMgr::DEFERRED_DIFFUSE, src, LLTexUnit::TFO_POINT);
+        gDeferredDoFCombineProgram.bindTexture(LLShaderMgr::DEFERRED_LIGHT, &mFXAAMap, LLTexUnit::TFO_POINT);
 
-                mScreenTriangleVB->setBuffer();
-                mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3);
+        gDeferredDoFCombineProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, (GLfloat)dst->getWidth(), (GLfloat)dst->getHeight());
+        gDeferredDoFCombineProgram.uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF);
+        gDeferredDoFCombineProgram.uniform1f(LLShaderMgr::DOF_RES_SCALE, CameraDoFResScale);
+        gDeferredDoFCombineProgram.uniform1f(LLShaderMgr::DOF_WIDTH, (dof_width - 1) / (F32)src->getWidth());
+        gDeferredDoFCombineProgram.uniform1f(LLShaderMgr::DOF_HEIGHT, (dof_height - 1) / (F32)src->getHeight());
 
-                gDeferredDoFCombineProgram.unbind();
+        mScreenTriangleVB->setBuffer();
+        mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3);
 
-                dst->flush();
-            }
-        }
-        else
-        {
-            copyRenderTarget(src, dst);
-        }
+        gDeferredDoFCombineProgram.unbind();
+
+        dst->flush();
     }
 }
 
 void LLPipeline::renderFinalize()
 {
+    // Ensure changes here are propogated to relevant portions of LLGLTFPreviewTexture::render()
+
     llassert(!gCubeSnapshot);
     LLVertexBuffer::unbind();
     LLGLState::checkStates();
@@ -7840,21 +7794,29 @@ void LLPipeline::renderFinalize()
 
     generateExposure(&mLuminanceMap, &mExposureMap);
 
-    tonemap(&mRT->screen, &mPostMap);
-
-    applyCAS(&mPostMap, &mRT->screen);
+    LLRenderTarget* src = &mPostPingMap;
+    LLRenderTarget* dest = &mPostPongMap;
 
-    generateSMAABuffers(&mRT->screen);
+    static LLCachedControl<bool> render_cas(gSavedSettings, "RenderCAS", true);
+    if (render_cas && gCASProgram.isComplete())
+    {
+        tonemap(&mRT->screen, &mRT->deferredLight, false); // Must output to 16F buffer when passing to CAS or banding occurs
 
-    gammaCorrect(&mRT->screen, &mPostMap);
+        applyCAS(&mRT->deferredLight, dest); // Gamma corrects after sharpening
+        std::swap(src, dest);
+    }
+    else
+    {
+        tonemap(&mRT->screen, dest);
+        std::swap(src, dest);
+    }
 
     LLVertexBuffer::unbind();
 
-    applySMAA(&mPostMap, &mRT->screen);
-
-    generateGlow(&mRT->screen);
+    generateGlow(src);
 
-    combineGlow(&mRT->screen, &mPostMap);
+    combineGlow(src, dest);
+    std::swap(src, dest);
 
     gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft;
     gGLViewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom;
@@ -7862,13 +7824,27 @@ void LLPipeline::renderFinalize()
     gGLViewport[3] = gViewerWindow->getWorldViewRectRaw().getHeight();
     glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
 
-    renderDoF(&mPostMap, &mRT->screen);
+    bool dof_enabled =
+        (RenderDepthOfFieldInEditMode || !LLToolMgr::getInstance()->inBuildMode()) &&
+        RenderDepthOfField &&
+        !gCubeSnapshot;
+    if(dof_enabled)
+    {
+        renderDoF(src, dest);
+        std::swap(src, dest);
+    }
+
+    if (RenderFSAAType == 2 && mFXAAMap.isComplete() && mSMAABlendBuffer.isComplete())
+    {
+        generateSMAABuffers(src);
+        applySMAA(src, dest);
+        std::swap(src, dest);
+    }
 
-    LLRenderTarget* finalBuffer = &mRT->screen;
-    if (RenderFSAAType == 1)
+    if (RenderFSAAType == 1 && mFXAAMap.isComplete())
     {
-        applyFXAA(&mRT->screen, &mPostMap);
-        finalBuffer = &mPostMap;
+        applyFXAA(src, dest);
+        std::swap(src, dest);
     }
 
     if (RenderBufferVisualization > -1)
@@ -7879,16 +7855,16 @@ void LLPipeline::renderFinalize()
         case 1:
         case 2:
         case 3:
-            visualizeBuffers(&mRT->deferredScreen, finalBuffer, RenderBufferVisualization);
+            visualizeBuffers(&mRT->deferredScreen, src, RenderBufferVisualization);
             break;
         case 4:
-            visualizeBuffers(&mLuminanceMap, finalBuffer, 0);
+            visualizeBuffers(&mLuminanceMap, src, 0);
             break;
         case 5:
         {
             if (RenderFSAAType > 0)
             {
-                visualizeBuffers(&mFXAAMap, finalBuffer, 0);
+                visualizeBuffers(&mFXAAMap, src, 0);
             }
             break;
         }
@@ -7896,7 +7872,7 @@ void LLPipeline::renderFinalize()
         {
             if (RenderFSAAType == 2)
             {
-                visualizeBuffers(&mSMAABlendBuffer, finalBuffer, 0);
+                visualizeBuffers(&mSMAABlendBuffer, src, 0);
             }
             break;
         }
@@ -7906,14 +7882,13 @@ void LLPipeline::renderFinalize()
     }
 
     // Present the screen target.
-
-    gDeferredPostNoDoFNoiseProgram.bind(); // Add noise as part of final render to screen pass to avoid damaging other post effects
+    gDeferredPostNoDoFProgram.bind(); // Add noise as part of final render to screen pass to avoid damaging other post effects
 
     // Whatever is last in the above post processing chain should _always_ be rendered directly here.  If not, expect problems.
-    gDeferredPostNoDoFNoiseProgram.bindTexture(LLShaderMgr::DEFERRED_DIFFUSE, finalBuffer);
-    gDeferredPostNoDoFNoiseProgram.bindTexture(LLShaderMgr::DEFERRED_DEPTH, &mRT->deferredScreen, true);
+    gDeferredPostNoDoFProgram.bindTexture(LLShaderMgr::DEFERRED_DIFFUSE, src);
+    gDeferredPostNoDoFProgram.bindTexture(LLShaderMgr::DEFERRED_DEPTH, &mRT->deferredScreen, true);
 
-    gDeferredPostNoDoFNoiseProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, (GLfloat)finalBuffer->getWidth(), (GLfloat)finalBuffer->getHeight());
+    gDeferredPostNoDoFProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, (GLfloat)src->getWidth(), (GLfloat)src->getHeight());
 
     {
         LLGLDepthTest depth_test(GL_TRUE, GL_TRUE, GL_ALWAYS);
@@ -7921,7 +7896,7 @@ void LLPipeline::renderFinalize()
         mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3);
     }
 
-    gDeferredPostNoDoFNoiseProgram.unbind();
+    gDeferredPostNoDoFProgram.unbind();
 
     gGL.setSceneBlendType(LLRender::BT_ALPHA);
 
diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h
index c69ca863e7..b76d07704c 100644
--- a/indra/newview/pipeline.h
+++ b/indra/newview/pipeline.h
@@ -155,8 +155,7 @@ public:
     void copyScreenSpaceReflections(LLRenderTarget* src, LLRenderTarget* dst);
     void generateLuminance(LLRenderTarget* src, LLRenderTarget* dst);
     void generateExposure(LLRenderTarget* src, LLRenderTarget* dst, bool use_history = true);
-    void tonemap(LLRenderTarget* src, LLRenderTarget* dst);
-    void gammaCorrect(LLRenderTarget* src, LLRenderTarget* dst);
+    void tonemap(LLRenderTarget* src, LLRenderTarget* dst, bool gamma_correct = true);
     void generateGlow(LLRenderTarget* src);
     void applyCAS(LLRenderTarget* src, LLRenderTarget* dst);
     void applyFXAA(LLRenderTarget* src, LLRenderTarget* dst);
@@ -337,8 +336,6 @@ public:
     // should be called just before rendering pre-water alpha objects
     void doWaterHaze();
 
-    void postDeferredGammaCorrect(LLRenderTarget* screen_target);
-
     void generateSunShadow(LLCamera& camera);
     LLRenderTarget* getSunShadowTarget(U32 i);
     LLRenderTarget* getSpotShadowTarget(U32 i);
@@ -725,7 +722,8 @@ public:
     LLRenderTarget          mLastExposure;
 
     // tonemapped and gamma corrected render ready for post
-    LLRenderTarget          mPostMap;
+    LLRenderTarget          mPostPingMap;
+    LLRenderTarget          mPostPongMap;
 
     // FXAA helper target
     LLRenderTarget          mFXAAMap;
diff --git a/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml b/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml
index e81ff7f343..610cffb84a 100644
--- a/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml
+++ b/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml
@@ -924,6 +924,19 @@
   </combo_box>
   <!-- End of mirror settings -->
   <!-- Sharpening Settings -->
+  <check_box
+    control_name="RenderCAS"
+    height="16"
+    initial_value="false"
+    label="Sharpening"
+    layout="topleft"
+    left="420"
+    name="Sharpening"
+    top_delta="24"
+    width="240">
+    <check_box.commit_callback
+      function="Pref.RenderOptionUpdate" />
+  </check_box>
   <slider
     control_name="RenderCASSharpness"
     decimal_digits="1"
@@ -931,7 +944,7 @@
     height="16"
     increment="0.1"
     initial_value="160"
-    label="Sharpening:"
+    label="Sharpening Strength:"
     label_width="145"
     layout="topleft"
     left="420"
-- 
cgit v1.2.3


From 687930d5094e85c13d5ae7967b09eb08a879b333 Mon Sep 17 00:00:00 2001
From: Rye <rye@lindenlab.com>
Date: Sun, 3 Nov 2024 02:28:39 -0500
Subject: Integrate glow combine pass with other post process render passes to
 reduce another full screen copy

---
 .../class1/deferred/SMAANeighborhoodBlendF.glsl    |  10 +-
 .../app_settings/shaders/class1/deferred/cofF.glsl |   6 +-
 .../class1/deferred/postDeferredNoDoFF.glsl        |   1 -
 .../shaders/class1/interface/glowcombineF.glsl     |   2 +
 .../shaders/class1/interface/glowcombineFXAAF.glsl |   7 +-
 indra/newview/llgltfmaterialpreviewmgr.cpp         |  22 +--
 indra/newview/llviewershadermgr.cpp                |  43 +++++-
 indra/newview/llviewershadermgr.h                  |   2 +
 indra/newview/pipeline.cpp                         | 147 ++++++++++++---------
 indra/newview/pipeline.h                           |   4 +-
 indra/newview/rlvdefines.h                         |  26 ++--
 indra/newview/rlvhelper.h                          |  14 +-
 12 files changed, 171 insertions(+), 113 deletions(-)

(limited to 'indra/newview')

diff --git a/indra/newview/app_settings/shaders/class1/deferred/SMAANeighborhoodBlendF.glsl b/indra/newview/app_settings/shaders/class1/deferred/SMAANeighborhoodBlendF.glsl
index 3276405447..08052a9ddf 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/SMAANeighborhoodBlendF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/SMAANeighborhoodBlendF.glsl
@@ -31,10 +31,12 @@ in vec2 vary_texcoord0;
 in vec4 vary_offset;
 
 uniform sampler2D diffuseRect;
+uniform sampler2D emissiveRect;
 uniform sampler2D blendTex;
 #if SMAA_REPROJECTION
 uniform sampler2D velocityTex;
 #endif
+uniform sampler2D depthMap;
 
 #define float4 vec4
 #define float2 vec2
@@ -51,7 +53,7 @@ float4 SMAANeighborhoodBlendingPS(float2 texcoord,
 
 void main()
 {
-    frag_color = SMAANeighborhoodBlendingPS(vary_texcoord0,
+    vec4 diff = SMAANeighborhoodBlendingPS(vary_texcoord0,
                                             vary_offset,
                                             diffuseRect,
                                             blendTex
@@ -59,5 +61,11 @@ void main()
                                             , velocityTex
                                             #endif
                                             );
+#ifndef NO_GLOW
+    diff.rgb += texture2D(emissiveRect, vary_texcoord0).rgb;
+#endif
+    frag_color = diff;
+
+    gl_FragDepth = texture(depthMap, vary_texcoord0.xy).r;
 }
 
diff --git a/indra/newview/app_settings/shaders/class1/deferred/cofF.glsl b/indra/newview/app_settings/shaders/class1/deferred/cofF.glsl
index 4a26b8924a..36611db2fb 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/cofF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/cofF.glsl
@@ -29,6 +29,7 @@ out vec4 frag_color;
 
 uniform sampler2D diffuseRect;
 uniform sampler2D depthMap;
+uniform sampler2D emissiveRect;
 
 uniform float focal_distance;
 uniform float blur_constant;
@@ -66,12 +67,13 @@ void main()
     vec4 p = inv_proj*ndc;
     float depth = p.z/p.w;
 
-    vec4 diff = texture(diffuseRect, vary_fragcoord.xy);
+    vec4 diff = texture(diffuseRect, tc);
 
     float sc = calc_cof(depth);
     sc = min(sc, max_cof);
     sc = max(sc, -max_cof);
 
-    frag_color.rgb = diff.rgb;
+    vec4 bloom = texture2D(emissiveRect, tc);
+    frag_color.rgb = diff.rgb + bloom.rgb;
     frag_color.a = sc/max_cof*0.5+0.5;
 }
diff --git a/indra/newview/app_settings/shaders/class1/deferred/postDeferredNoDoFF.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredNoDoFF.glsl
index 07384ebe9b..cb0a6edea9 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/postDeferredNoDoFF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/postDeferredNoDoFF.glsl
@@ -30,7 +30,6 @@ out vec4 frag_color;
 uniform sampler2D diffuseRect;
 uniform sampler2D depthMap;
 
-uniform vec2 screen_res;
 in vec2 vary_fragcoord;
 
 void main()
diff --git a/indra/newview/app_settings/shaders/class1/interface/glowcombineF.glsl b/indra/newview/app_settings/shaders/class1/interface/glowcombineF.glsl
index ca000dcb23..0e7858743c 100644
--- a/indra/newview/app_settings/shaders/class1/interface/glowcombineF.glsl
+++ b/indra/newview/app_settings/shaders/class1/interface/glowcombineF.glsl
@@ -29,10 +29,12 @@ out vec4 frag_color;
 
 uniform sampler2D diffuseRect;
 uniform sampler2D emissiveRect;
+uniform sampler2D depthMap;
 
 in vec2 tc;
 
 void main()
 {
     frag_color = texture(diffuseRect, tc) + texture(emissiveRect, tc);
+    gl_FragDepth = texture(depthMap, tc.xy).r;
 }
diff --git a/indra/newview/app_settings/shaders/class1/interface/glowcombineFXAAF.glsl b/indra/newview/app_settings/shaders/class1/interface/glowcombineFXAAF.glsl
index 6d34c8aefa..8a8de88182 100644
--- a/indra/newview/app_settings/shaders/class1/interface/glowcombineFXAAF.glsl
+++ b/indra/newview/app_settings/shaders/class1/interface/glowcombineFXAAF.glsl
@@ -28,6 +28,7 @@
 out vec4 frag_color;
 
 uniform sampler2D diffuseRect;
+uniform sampler2D emissiveRect;
 
 uniform vec2 screen_res;
 
@@ -36,6 +37,8 @@ in vec2 vary_tc;
 void main()
 {
     vec3 col = texture(diffuseRect, vary_tc).rgb;
-
-    frag_color = vec4(col.rgb, dot(col.rgb, vec3(0.299, 0.587, 0.144)));
+#ifndef NO_GLOW
+    col += texture2D(emissiveRect, vary_tc).rgb;
+#endif
+    frag_color = vec4(col, dot(col, vec3(0.299, 0.587, 0.144)));
 }
diff --git a/indra/newview/llgltfmaterialpreviewmgr.cpp b/indra/newview/llgltfmaterialpreviewmgr.cpp
index f473afb74c..5ca841f9f1 100644
--- a/indra/newview/llgltfmaterialpreviewmgr.cpp
+++ b/indra/newview/llgltfmaterialpreviewmgr.cpp
@@ -529,32 +529,14 @@ bool LLGLTFPreviewTexture::render()
     gPipeline.tonemap(&screen, dst);
     std::swap(src, dst);
 
+    // Final render
     LLVertexBuffer::unbind();
     gPipeline.generateGlow(src);
-    gPipeline.combineGlow(src, dst);
-    std::swap(src, dst);
+    gPipeline.combineGlow(src, nullptr);
 
     // *HACK: Restore mExposureMap (it will be consumed by generateExposure next frame)
     gPipeline.mExposureMap.swapFBORefs(gPipeline.mLastExposure);
 
-    // Final render
-
-    gDeferredPostNoDoFProgram.bind();
-
-    // From LLPipeline::renderFinalize: "Whatever is last in the above post processing chain should _always_ be rendered directly here.  If not, expect problems."
-    gDeferredPostNoDoFProgram.bindTexture(LLShaderMgr::DEFERRED_DIFFUSE, src);
-    gDeferredPostNoDoFProgram.bindTexture(LLShaderMgr::DEFERRED_DEPTH, mBoundTarget, true);
-
-    gDeferredPostNoDoFProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, (GLfloat)src->getWidth(), (GLfloat)src->getHeight());
-
-    {
-        LLGLDepthTest depth_test(GL_TRUE, GL_TRUE, GL_ALWAYS);
-        gPipeline.mScreenTriangleVB->setBuffer();
-        gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3);
-    }
-
-    gDeferredPostNoDoFProgram.unbind();
-
     // Clean up
     gPipeline.setupHWLights();
     gPipeline.mReflectionMapManager.forceDefaultProbeAndUpdateUniforms(false);
diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp
index 52fd75f672..4d248af5d5 100644
--- a/indra/newview/llviewershadermgr.cpp
+++ b/indra/newview/llviewershadermgr.cpp
@@ -87,6 +87,7 @@ LLGLSLShader    gRadianceGenProgram;
 LLGLSLShader    gHeroRadianceGenProgram;
 LLGLSLShader    gIrradianceGenProgram;
 LLGLSLShader    gGlowCombineFXAAProgram;
+LLGLSLShader    gFXAALumaGenProgram;
 LLGLSLShader    gTwoTextureCompareProgram;
 LLGLSLShader    gOneTextureFilterProgram;
 LLGLSLShader    gDebugProgram;
@@ -206,6 +207,7 @@ LLGLSLShader            gFXAAProgram[4];
 LLGLSLShader            gSMAAEdgeDetectProgram[4];
 LLGLSLShader            gSMAABlendWeightsProgram[4];
 LLGLSLShader            gSMAANeighborhoodBlendProgram[4];
+LLGLSLShader            gSMAANeighborhoodBlendGlowCombineProgram[4];
 LLGLSLShader            gCASProgram;
 LLGLSLShader            gCASLegacyGammaProgram;
 LLGLSLShader            gDeferredPostNoDoFProgram;
@@ -2496,6 +2498,7 @@ bool LLViewerShaderMgr::loadShadersDeferred()
 
                 gSMAANeighborhoodBlendProgram[i].clearPermutations();
                 gSMAANeighborhoodBlendProgram[i].addPermutations(defines);
+                gSMAANeighborhoodBlendProgram[i].addPermutation("NO_GLOW", "1");
 
                 gSMAANeighborhoodBlendProgram[i].mShaderFiles.clear();
                 gSMAANeighborhoodBlendProgram[i].mShaderFiles.push_back(make_pair("deferred/SMAANeighborhoodBlendF.glsl", GL_FRAGMENT_SHADER_ARB));
@@ -2503,8 +2506,27 @@ bool LLViewerShaderMgr::loadShadersDeferred()
                 gSMAANeighborhoodBlendProgram[i].mShaderFiles.push_back(make_pair("deferred/SMAA.glsl", GL_FRAGMENT_SHADER_ARB));
                 gSMAANeighborhoodBlendProgram[i].mShaderFiles.push_back(make_pair("deferred/SMAA.glsl", GL_VERTEX_SHADER_ARB));
                 gSMAANeighborhoodBlendProgram[i].mShaderLevel = mShaderLevel[SHADER_DEFERRED];
+
                 success = gSMAANeighborhoodBlendProgram[i].createShader();
             }
+
+            if (success)
+            {
+                gSMAANeighborhoodBlendGlowCombineProgram[i].mName = llformat("SMAA Neighborhood Blending Glow Combine (%s)", smaa_pair.second.c_str());
+                gSMAANeighborhoodBlendGlowCombineProgram[i].mFeatures.isDeferred = true;
+
+                gSMAANeighborhoodBlendGlowCombineProgram[i].clearPermutations();
+                gSMAANeighborhoodBlendGlowCombineProgram[i].addPermutations(defines);
+
+                gSMAANeighborhoodBlendGlowCombineProgram[i].mShaderFiles.clear();
+                gSMAANeighborhoodBlendGlowCombineProgram[i].mShaderFiles.push_back(make_pair("deferred/SMAANeighborhoodBlendF.glsl", GL_FRAGMENT_SHADER_ARB));
+                gSMAANeighborhoodBlendGlowCombineProgram[i].mShaderFiles.push_back(make_pair("deferred/SMAANeighborhoodBlendV.glsl", GL_VERTEX_SHADER_ARB));
+                gSMAANeighborhoodBlendGlowCombineProgram[i].mShaderFiles.push_back(make_pair("deferred/SMAA.glsl", GL_FRAGMENT_SHADER_ARB));
+                gSMAANeighborhoodBlendGlowCombineProgram[i].mShaderFiles.push_back(make_pair("deferred/SMAA.glsl", GL_VERTEX_SHADER_ARB));
+                gSMAANeighborhoodBlendGlowCombineProgram[i].mShaderLevel = mShaderLevel[SHADER_DEFERRED];
+
+                success = gSMAANeighborhoodBlendGlowCombineProgram[i].createShader();
+            }
             ++i;
         }
     }
@@ -2970,7 +2992,7 @@ bool LLViewerShaderMgr::loadShadersInterface()
 
     if (success)
     {
-        gGlowCombineFXAAProgram.mName = "Glow CombineFXAA Shader";
+        gGlowCombineFXAAProgram.mName = "Glow Combine FXAA Luma Gen Shader";
         gGlowCombineFXAAProgram.mShaderFiles.clear();
         gGlowCombineFXAAProgram.mShaderFiles.push_back(make_pair("interface/glowcombineFXAAV.glsl", GL_VERTEX_SHADER));
         gGlowCombineFXAAProgram.mShaderFiles.push_back(make_pair("interface/glowcombineFXAAF.glsl", GL_FRAGMENT_SHADER));
@@ -2985,6 +3007,25 @@ bool LLViewerShaderMgr::loadShadersInterface()
         }
     }
 
+    if (success)
+    {
+        gFXAALumaGenProgram.mName = "FXAA Luma Gen Shader";
+        gFXAALumaGenProgram.mShaderFiles.clear();
+        gFXAALumaGenProgram.mShaderFiles.push_back(make_pair("interface/glowcombineFXAAV.glsl", GL_VERTEX_SHADER));
+        gFXAALumaGenProgram.mShaderFiles.push_back(make_pair("interface/glowcombineFXAAF.glsl", GL_FRAGMENT_SHADER));
+        gFXAALumaGenProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
+        gFXAALumaGenProgram.clearPermutations();
+        gFXAALumaGenProgram.addPermutation("NO_GLOW", "1");
+        success = gFXAALumaGenProgram.createShader();
+        if (success)
+        {
+            gFXAALumaGenProgram.bind();
+            gFXAALumaGenProgram.uniform1i(sGlowMap, 0);
+            gFXAALumaGenProgram.uniform1i(sScreenMap, 1);
+            gFXAALumaGenProgram.unbind();
+        }
+    }
+
 #ifdef LL_WINDOWS
     if (success)
     {
diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h
index afc29e6fd2..60b880c161 100644
--- a/indra/newview/llviewershadermgr.h
+++ b/indra/newview/llviewershadermgr.h
@@ -160,6 +160,7 @@ extern LLGLSLShader         gRadianceGenProgram;
 extern LLGLSLShader         gHeroRadianceGenProgram;
 extern LLGLSLShader         gIrradianceGenProgram;
 extern LLGLSLShader         gGlowCombineFXAAProgram;
+extern LLGLSLShader         gFXAALumaGenProgram;
 extern LLGLSLShader         gDebugProgram;
 enum NormalDebugShaderVariant : S32
 {
@@ -250,6 +251,7 @@ extern LLGLSLShader         gFXAAProgram[4];
 extern LLGLSLShader         gSMAAEdgeDetectProgram[4];
 extern LLGLSLShader         gSMAABlendWeightsProgram[4];
 extern LLGLSLShader         gSMAANeighborhoodBlendProgram[4];
+extern LLGLSLShader         gSMAANeighborhoodBlendGlowCombineProgram[4];
 extern LLGLSLShader         gCASProgram;
 extern LLGLSLShader         gCASLegacyGammaProgram;
 extern LLGLSLShader         gDeferredPostNoDoFProgram;
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index 541208b133..a88756452e 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -6903,7 +6903,10 @@ static LLTrace::BlockTimerStatHandle FTM_RENDER_BLOOM("Bloom");
 
 void LLPipeline::visualizeBuffers(LLRenderTarget* src, LLRenderTarget* dst, U32 bufferIndex)
 {
-    dst->bindTarget();
+    if (dst)
+    {
+        dst->bindTarget();
+    }
     gDeferredBufferVisualProgram.bind();
     gDeferredBufferVisualProgram.bindTexture(LLShaderMgr::DEFERRED_DIFFUSE, src, false, LLTexUnit::TFO_BILINEAR, bufferIndex);
 
@@ -6916,7 +6919,10 @@ void LLPipeline::visualizeBuffers(LLRenderTarget* src, LLRenderTarget* dst, U32
     mScreenTriangleVB->setBuffer();
     mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3);
     gDeferredBufferVisualProgram.unbind();
-    dst->flush();
+    if (dst)
+    {
+        dst->flush();
+    }
 }
 
 void LLPipeline::generateLuminance(LLRenderTarget* src, LLRenderTarget* dst)
@@ -7297,20 +7303,20 @@ void LLPipeline::applyCAS(LLRenderTarget* src, LLRenderTarget* dst)
     dst->flush();
 }
 
-void LLPipeline::applyFXAA(LLRenderTarget* src, LLRenderTarget* dst)
+void LLPipeline::applyFXAA(LLRenderTarget* src, LLRenderTarget* dst, bool combine_glow)
 {
     llassert(!gCubeSnapshot);
     LLGLSLShader* shader = &gGlowCombineProgram;
 
     LL_PROFILE_GPU_ZONE("aa");
-    S32 width = dst->getWidth();
-    S32 height = dst->getHeight();
+    S32 width = src->getWidth();
+    S32 height = src->getHeight();
 
     // bake out texture2D with RGBL for FXAA shader
     mFXAAMap.bindTarget();
     mFXAAMap.invalidate(GL_COLOR_BUFFER_BIT);
 
-    shader = &gGlowCombineFXAAProgram;
+    shader = combine_glow ? &gGlowCombineFXAAProgram : &gFXAALumaGenProgram;
     shader->bind();
 
     S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, src->getUsage());
@@ -7318,6 +7324,7 @@ void LLPipeline::applyFXAA(LLRenderTarget* src, LLRenderTarget* dst)
     {
         src->bindTexture(0, channel, LLTexUnit::TFO_BILINEAR);
     }
+    shader->bindTexture(LLShaderMgr::DEFERRED_EMISSIVE, &mGlow[1]);
 
     {
         LLGLDepthTest depth_test(GL_TRUE, GL_TRUE, GL_ALWAYS);
@@ -7330,7 +7337,10 @@ void LLPipeline::applyFXAA(LLRenderTarget* src, LLRenderTarget* dst)
 
     mFXAAMap.flush();
 
-    dst->bindTarget();
+    if (dst)
+    {
+        dst->bindTarget();
+    }
 
     static LLCachedControl<U32> aa_quality(gSavedSettings, "RenderFSAASamples", 0U);
     U32 fsaa_quality = std::clamp(aa_quality(), 0U, 3U);
@@ -7362,15 +7372,17 @@ void LLPipeline::applyFXAA(LLRenderTarget* src, LLRenderTarget* dst)
 
     {
         LLGLDepthTest depth_test(GL_TRUE, GL_TRUE, GL_ALWAYS);
-        S32 depth_channel = shader->getTextureChannel(LLShaderMgr::DEFERRED_DEPTH);
-        gGL.getTexUnit(depth_channel)->bind(&mRT->deferredScreen, true);
+        shader->bindTexture(LLShaderMgr::DEFERRED_DEPTH, &mRT->deferredScreen, true);
 
         mScreenTriangleVB->setBuffer();
         mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3);
     }
 
     shader->unbind();
-    dst->flush();
+    if (dst)
+    {
+        dst->flush();
+    }
 }
 
 void LLPipeline::generateSMAABuffers(LLRenderTarget* src)
@@ -7492,7 +7504,7 @@ void LLPipeline::generateSMAABuffers(LLRenderTarget* src)
     }
 }
 
-void LLPipeline::applySMAA(LLRenderTarget* src, LLRenderTarget* dst)
+void LLPipeline::applySMAA(LLRenderTarget* src, LLRenderTarget* dst, bool combine_glow)
 {
     llassert(!gCubeSnapshot);
 
@@ -7514,11 +7526,14 @@ void LLPipeline::applySMAA(LLRenderTarget* src, LLRenderTarget* dst)
         //LLGLDisable stencil(GL_STENCIL_TEST);
 
         // Bind setup:
-        LLRenderTarget* bound_target = dst;
-        LLGLSLShader& blend_shader = gSMAANeighborhoodBlendProgram[fsaa_quality];
+        LLGLSLShader& blend_shader = combine_glow ? gSMAANeighborhoodBlendGlowCombineProgram[fsaa_quality]
+            : gSMAANeighborhoodBlendProgram[fsaa_quality];
 
-        bound_target->bindTarget();
-        bound_target->invalidate(GL_COLOR_BUFFER_BIT);
+        if(dst)
+        {
+            dst->bindTarget();
+            dst->invalidate(GL_COLOR_BUFFER_BIT);
+        }
 
         blend_shader.bind();
         blend_shader.uniform4fv(sSmaaRTMetrics, 1, rt_metrics);
@@ -7536,13 +7551,21 @@ void LLPipeline::applySMAA(LLRenderTarget* src, LLRenderTarget* dst)
             mSMAABlendBuffer.bindTexture(0, blend_channel, LLTexUnit::TFO_BILINEAR);
         }
 
+        blend_shader.bindTexture(LLShaderMgr::DEFERRED_EMISSIVE, &mGlow[1]);
+
+        blend_shader.bindTexture(LLShaderMgr::DEFERRED_DEPTH, &mRT->deferredScreen, true);
+
         mScreenTriangleVB->setBuffer();
         mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3);
 
-        bound_target->flush();
         blend_shader.unbind();
         gGL.getTexUnit(diffuse_channel)->unbindFast(LLTexUnit::TT_TEXTURE);
         gGL.getTexUnit(blend_channel)->unbindFast(LLTexUnit::TT_TEXTURE);
+
+        if (dst)
+        {
+            dst->flush();
+        }
     }
 }
 
@@ -7571,20 +7594,25 @@ void LLPipeline::combineGlow(LLRenderTarget* src, LLRenderTarget* dst)
 {
     // Go ahead and do our glow combine here in our destination.  We blit this later into the front buffer.
 
-    dst->bindTarget();
-
+    if (dst)
     {
+        dst->bindTarget();
+    }
 
+    {
         gGlowCombineProgram.bind();
 
         gGlowCombineProgram.bindTexture(LLShaderMgr::DEFERRED_DIFFUSE, src);
         gGlowCombineProgram.bindTexture(LLShaderMgr::DEFERRED_EMISSIVE, &mGlow[1]);
+        gGlowCombineProgram.bindTexture(LLShaderMgr::DEFERRED_DEPTH, &mRT->deferredScreen, true);
 
         mScreenTriangleVB->setBuffer();
         mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3);
     }
-
-    dst->flush();
+    if (dst)
+    {
+        dst->flush();
+    }
 }
 
 void LLPipeline::renderDoF(LLRenderTarget* src, LLRenderTarget* dst)
@@ -7702,13 +7730,14 @@ void LLPipeline::renderDoF(LLRenderTarget* src, LLRenderTarget* dst)
         gDeferredCoFProgram.bindTexture(LLShaderMgr::DEFERRED_DIFFUSE, src, LLTexUnit::TFO_POINT);
         gDeferredCoFProgram.bindTexture(LLShaderMgr::DEFERRED_DEPTH, &mRT->deferredScreen, true);
 
-        gDeferredCoFProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, (GLfloat)dst->getWidth(), (GLfloat)dst->getHeight());
+        gDeferredCoFProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, (GLfloat)mFXAAMap.getWidth(), (GLfloat)mFXAAMap.getHeight());
         gDeferredCoFProgram.uniform1f(LLShaderMgr::DOF_FOCAL_DISTANCE, -subject_distance / 1000.f);
         gDeferredCoFProgram.uniform1f(LLShaderMgr::DOF_BLUR_CONSTANT, blur_constant);
         gDeferredCoFProgram.uniform1f(LLShaderMgr::DOF_TAN_PIXEL_ANGLE, tanf(1.f / LLDrawable::sCurPixelAngle));
         gDeferredCoFProgram.uniform1f(LLShaderMgr::DOF_MAGNIFICATION, magnification);
         gDeferredCoFProgram.uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF);
         gDeferredCoFProgram.uniform1f(LLShaderMgr::DOF_RES_SCALE, CameraDoFResScale);
+        gDeferredCoFProgram.bindTexture(LLShaderMgr::DEFERRED_EMISSIVE, &mGlow[1]);
 
         mScreenTriangleVB->setBuffer();
         mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3);
@@ -7728,7 +7757,7 @@ void LLPipeline::renderDoF(LLRenderTarget* src, LLRenderTarget* dst)
         gDeferredPostProgram.bind();
         gDeferredPostProgram.bindTexture(LLShaderMgr::DEFERRED_DIFFUSE, &mFXAAMap, LLTexUnit::TFO_POINT);
 
-        gDeferredPostProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, (GLfloat)dst->getWidth(), (GLfloat)dst->getHeight());
+        gDeferredPostProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, (GLfloat)src->getWidth(), (GLfloat)src->getHeight());
         gDeferredPostProgram.uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF);
         gDeferredPostProgram.uniform1f(LLShaderMgr::DOF_RES_SCALE, CameraDoFResScale);
 
@@ -7743,14 +7772,18 @@ void LLPipeline::renderDoF(LLRenderTarget* src, LLRenderTarget* dst)
 
     { // combine result based on alpha
 
-        dst->bindTarget();
-        glViewport(0, 0, dst->getWidth(), dst->getHeight());
+        if(dst)
+        {
+            dst->bindTarget();
+        }
+        glViewport(0, 0, mFXAAMap.getWidth(), mFXAAMap.getHeight());
 
         gDeferredDoFCombineProgram.bind();
         gDeferredDoFCombineProgram.bindTexture(LLShaderMgr::DEFERRED_DIFFUSE, src, LLTexUnit::TFO_POINT);
         gDeferredDoFCombineProgram.bindTexture(LLShaderMgr::DEFERRED_LIGHT, &mFXAAMap, LLTexUnit::TFO_POINT);
+        gDeferredDoFCombineProgram.bindTexture(LLShaderMgr::DEFERRED_DEPTH, &mRT->deferredScreen, true);
 
-        gDeferredDoFCombineProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, (GLfloat)dst->getWidth(), (GLfloat)dst->getHeight());
+        gDeferredDoFCombineProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, (GLfloat)src->getWidth(), (GLfloat)src->getHeight());
         gDeferredDoFCombineProgram.uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF);
         gDeferredDoFCombineProgram.uniform1f(LLShaderMgr::DOF_RES_SCALE, CameraDoFResScale);
         gDeferredDoFCombineProgram.uniform1f(LLShaderMgr::DOF_WIDTH, (dof_width - 1) / (F32)src->getWidth());
@@ -7761,7 +7794,10 @@ void LLPipeline::renderDoF(LLRenderTarget* src, LLRenderTarget* dst)
 
         gDeferredDoFCombineProgram.unbind();
 
-        dst->flush();
+        if (dst)
+        {
+            dst->flush();
+        }
     }
 }
 
@@ -7815,36 +7851,36 @@ void LLPipeline::renderFinalize()
 
     generateGlow(src);
 
-    combineGlow(src, dest);
-    std::swap(src, dest);
-
     gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft;
     gGLViewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom;
     gGLViewport[2] = gViewerWindow->getWorldViewRectRaw().getWidth();
     gGLViewport[3] = gViewerWindow->getWorldViewRectRaw().getHeight();
     glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
 
-    bool dof_enabled =
-        (RenderDepthOfFieldInEditMode || !LLToolMgr::getInstance()->inBuildMode()) &&
-        RenderDepthOfField &&
-        !gCubeSnapshot;
-    if(dof_enabled)
+    bool smaa_enabled = RenderFSAAType == 2 && mFXAAMap.isComplete() && mSMAABlendBuffer.isComplete();
+    bool fxaa_enabled = RenderFSAAType == 1 && mFXAAMap.isComplete();
+    bool dof_enabled = RenderDepthOfField &&
+        (RenderDepthOfFieldInEditMode || !LLToolMgr::getInstance()->inBuildMode());
+    if(dof_enabled) // DoF Combines Glow
     {
-        renderDoF(src, dest);
-        std::swap(src, dest);
+        LLRenderTarget* dof_dest = (smaa_enabled || fxaa_enabled) ? dest : nullptr; // render to screen if no AA enabled
+        renderDoF(src, dof_dest);
+        std::swap(src, dof_dest);
     }
 
-    if (RenderFSAAType == 2 && mFXAAMap.isComplete() && mSMAABlendBuffer.isComplete())
+    // Render to screen
+    if (smaa_enabled)
     {
         generateSMAABuffers(src);
-        applySMAA(src, dest);
-        std::swap(src, dest);
+        applySMAA(src, nullptr, !dof_enabled);
     }
-
-    if (RenderFSAAType == 1 && mFXAAMap.isComplete())
+    else if (fxaa_enabled)
     {
-        applyFXAA(src, dest);
-        std::swap(src, dest);
+        applyFXAA(src, nullptr, !dof_enabled);
+    }
+    else if (!dof_enabled)
+    {
+        combineGlow(src, nullptr);
     }
 
     if (RenderBufferVisualization > -1)
@@ -7855,16 +7891,16 @@ void LLPipeline::renderFinalize()
         case 1:
         case 2:
         case 3:
-            visualizeBuffers(&mRT->deferredScreen, src, RenderBufferVisualization);
+            visualizeBuffers(&mRT->deferredScreen, nullptr, RenderBufferVisualization);
             break;
         case 4:
-            visualizeBuffers(&mLuminanceMap, src, 0);
+            visualizeBuffers(&mLuminanceMap, nullptr, 0);
             break;
         case 5:
         {
             if (RenderFSAAType > 0)
             {
-                visualizeBuffers(&mFXAAMap, src, 0);
+                visualizeBuffers(&mFXAAMap, nullptr, 0);
             }
             break;
         }
@@ -7872,7 +7908,7 @@ void LLPipeline::renderFinalize()
         {
             if (RenderFSAAType == 2)
             {
-                visualizeBuffers(&mSMAABlendBuffer, src, 0);
+                visualizeBuffers(&mSMAABlendBuffer, nullptr, 0);
             }
             break;
         }
@@ -7881,23 +7917,6 @@ void LLPipeline::renderFinalize()
         }
     }
 
-    // Present the screen target.
-    gDeferredPostNoDoFProgram.bind(); // Add noise as part of final render to screen pass to avoid damaging other post effects
-
-    // Whatever is last in the above post processing chain should _always_ be rendered directly here.  If not, expect problems.
-    gDeferredPostNoDoFProgram.bindTexture(LLShaderMgr::DEFERRED_DIFFUSE, src);
-    gDeferredPostNoDoFProgram.bindTexture(LLShaderMgr::DEFERRED_DEPTH, &mRT->deferredScreen, true);
-
-    gDeferredPostNoDoFProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, (GLfloat)src->getWidth(), (GLfloat)src->getHeight());
-
-    {
-        LLGLDepthTest depth_test(GL_TRUE, GL_TRUE, GL_ALWAYS);
-        mScreenTriangleVB->setBuffer();
-        mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3);
-    }
-
-    gDeferredPostNoDoFProgram.unbind();
-
     gGL.setSceneBlendType(LLRender::BT_ALPHA);
 
     if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PHYSICS_SHAPES))
diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h
index b76d07704c..309665f80a 100644
--- a/indra/newview/pipeline.h
+++ b/indra/newview/pipeline.h
@@ -158,9 +158,9 @@ public:
     void tonemap(LLRenderTarget* src, LLRenderTarget* dst, bool gamma_correct = true);
     void generateGlow(LLRenderTarget* src);
     void applyCAS(LLRenderTarget* src, LLRenderTarget* dst);
-    void applyFXAA(LLRenderTarget* src, LLRenderTarget* dst);
+    void applyFXAA(LLRenderTarget* src, LLRenderTarget* dst, bool combine_glow);
     void generateSMAABuffers(LLRenderTarget* src);
-    void applySMAA(LLRenderTarget* src, LLRenderTarget* dst);
+    void applySMAA(LLRenderTarget* src, LLRenderTarget* dst, bool combine_glow);
     void renderDoF(LLRenderTarget* src, LLRenderTarget* dst);
     void copyRenderTarget(LLRenderTarget* src, LLRenderTarget* dst);
     void combineGlow(LLRenderTarget* src, LLRenderTarget* dst);
diff --git a/indra/newview/rlvdefines.h b/indra/newview/rlvdefines.h
index e39328fdd6..0deb59cad0 100644
--- a/indra/newview/rlvdefines.h
+++ b/indra/newview/rlvdefines.h
@@ -32,24 +32,24 @@
 //
 
 // Defining these makes it easier if we ever need to change our tag
-#define RLV_WARNS		LL_WARNS("RLV")
-#define RLV_INFOS		LL_INFOS("RLV")
-#define RLV_DEBUGS		LL_DEBUGS("RLV")
-#define RLV_ENDL		LL_ENDL
-#define RLV_VERIFY(f)	(f)
+#define RLV_WARNS       LL_WARNS("RLV")
+#define RLV_INFOS       LL_INFOS("RLV")
+#define RLV_DEBUGS      LL_DEBUGS("RLV")
+#define RLV_ENDL        LL_ENDL
+#define RLV_VERIFY(f)   (f)
 
 #if LL_RELEASE_WITH_DEBUG_INFO || LL_DEBUG
     // Make sure we halt execution on errors
-    #define RLV_ERRS				LL_ERRS("RLV")
+    #define RLV_ERRS                LL_ERRS("RLV")
     // Keep our asserts separate from LL's
-    #define RLV_ASSERT(f)			if (!(f)) { RLV_ERRS << "ASSERT (" << #f << ")" << RLV_ENDL; }
-    #define RLV_ASSERT_DBG(f)		RLV_ASSERT(f)
+    #define RLV_ASSERT(f)           if (!(f)) { RLV_ERRS << "ASSERT (" << #f << ")" << RLV_ENDL; }
+    #define RLV_ASSERT_DBG(f)       RLV_ASSERT(f)
 #else
     // Don't halt execution on errors in release
-    #define RLV_ERRS				LL_WARNS("RLV")
+    #define RLV_ERRS                LL_WARNS("RLV")
     // We don't want to check assertions in release builds
     #ifdef RLV_DEBUG
-        #define RLV_ASSERT(f)		RLV_VERIFY(f)
+        #define RLV_ASSERT(f)       RLV_VERIFY(f)
         #define RLV_ASSERT_DBG(f)
     #else
         #define RLV_ASSERT(f)
@@ -142,9 +142,9 @@ namespace Rlv
 
     enum class EExceptionCheck
     {
-        Permissive,						// Exception can be set by any object
-        Strict,							// Exception must be set by all objects holding the restriction
-        Default,						// Permissive or strict will be determined by currently enforced restrictions
+        Permissive,                     // Exception can be set by any object
+        Strict,                         // Exception must be set by all objects holding the restriction
+        Default,                        // Permissive or strict will be determined by currently enforced restrictions
     };
 
     // Replace&remove in c++23
diff --git a/indra/newview/rlvhelper.h b/indra/newview/rlvhelper.h
index f241332594..f0ce35b816 100644
--- a/indra/newview/rlvhelper.h
+++ b/indra/newview/rlvhelper.h
@@ -49,12 +49,12 @@ namespace Rlv
         enum EBehaviourFlags : uint32_t
         {
             // General behaviour flags
-            Strict = 0x0001,				// Behaviour has a "_sec" version
-            Synonym = 0x0002,				// Behaviour is a synonym of another
-            Extended = 0x0004,				// Behaviour is part of the RLVa extended command set
-            Experimental = 0x0008,			// Behaviour is part of the RLVa experimental command set
-            Blocked = 0x0010,				// Behaviour is blocked
-            Deprecated = 0x0020,			// Behaviour is deprecated
+            Strict = 0x0001,                // Behaviour has a "_sec" version
+            Synonym = 0x0002,               // Behaviour is a synonym of another
+            Extended = 0x0004,              // Behaviour is part of the RLVa extended command set
+            Experimental = 0x0008,          // Behaviour is part of the RLVa experimental command set
+            Blocked = 0x0010,               // Behaviour is blocked
+            Deprecated = 0x0020,            // Behaviour is deprecated
             MaskGeneral = 0x0FFF,
 
             // Force-wear specific flags
@@ -175,7 +175,7 @@ namespace Rlv
     template<EBehaviour templBhvr> using ReplyHandler = CommandHandler<EParamType::Reply, templBhvr>;
 
     // List of shared handlers
-    using VersionReplyHandler = ReplyHandler<EBehaviour::Version>;				// Shared between @version and @versionnew
+    using VersionReplyHandler = ReplyHandler<EBehaviour::Version>;              // Shared between @version and @versionnew
 
     //
     // CommandProcessor - Templated glue class that brings BehaviourInfo, CommandHandlerBaseImpl and CommandHandler together
-- 
cgit v1.2.3


From 4686f72cf0509daebba6b47bf3eb2c8382b8b6a3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Lars=20N=C3=A6sbye=20Christensen?= <lars@naesbye.dk>
Date: Tue, 5 Nov 2024 00:00:08 +0100
Subject: remove unused LSRequiresCarbon key (#3006)

---
 indra/newview/Info-SecondLife.plist | 2 --
 1 file changed, 2 deletions(-)

(limited to 'indra/newview')

diff --git a/indra/newview/Info-SecondLife.plist b/indra/newview/Info-SecondLife.plist
index 09b0e1ec1b..53a2590c20 100644
--- a/indra/newview/Info-SecondLife.plist
+++ b/indra/newview/Info-SecondLife.plist
@@ -28,8 +28,6 @@
 	<string>${VIEWER_VERSION_MAJOR}.${VIEWER_VERSION_MINOR}.${VIEWER_VERSION_PATCH}.${VIEWER_VERSION_REVISION}</string>
 	<key>CSResourcesFileMapped</key>
 	<true/>
-	<key>LSRequiresCarbon</key>
-	<true/>
 	<key>NSHumanReadableCopyright</key>
 	<string>${MACOSX_BUNDLE_COPYRIGHT}</string>
 	<key>NSMicrophoneUsageDescription</key>
-- 
cgit v1.2.3


From 3550dc519cbc7a46a25b0597b128fe7e6ef67e27 Mon Sep 17 00:00:00 2001
From: Ansariel <ansariel.hiller@phoenixviewer.com>
Date: Tue, 5 Nov 2024 21:56:17 +0100
Subject: Fix shutdown crash in LLWebRTCVoiceClient

---
 indra/newview/llvoicewebrtc.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'indra/newview')

diff --git a/indra/newview/llvoicewebrtc.cpp b/indra/newview/llvoicewebrtc.cpp
index 66fa3d6921..c7e246b3bf 100644
--- a/indra/newview/llvoicewebrtc.cpp
+++ b/indra/newview/llvoicewebrtc.cpp
@@ -303,7 +303,7 @@ void LLWebRTCVoiceClient::stopTimer()
 {
     if (mIsTimerActive)
     {
-        LLMuteList::instanceExists();
+        if (LLMuteList::instanceExists())
         {
             LLMuteList::getInstance()->removeObserver(this);
         }
-- 
cgit v1.2.3


From 01f51632dec8e3a77b7fba8fc94be0b9d64dc444 Mon Sep 17 00:00:00 2001
From: Cosmic Linden <cosmic@lindenlab.com>
Date: Tue, 5 Nov 2024 15:10:50 -0800
Subject: secondlife/viewer#2768: Fix for PBR texture animations sometimes not
 starting

---
 indra/newview/llvovolume.cpp | 26 ++++++++++++++++++++++++--
 1 file changed, 24 insertions(+), 2 deletions(-)

(limited to 'indra/newview')

diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 6d33f411ed..7289b080a6 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -641,6 +641,15 @@ void LLVOVolume::animateTextures()
                 if (!facep->mTextureMatrix)
                 {
                     facep->mTextureMatrix = new LLMatrix4();
+                    if (facep->getVirtualSize() > MIN_TEX_ANIM_SIZE)
+                    {
+                        // Fix the one edge case missed in
+                        // LLVOVolume::updateTextureVirtualSize when the
+                        // mTextureMatrix is not yet present
+                        gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_TCOORD);
+                        mDrawable->getSpatialGroup()->dirtyGeom();
+                        gPipeline.markRebuild(mDrawable->getSpatialGroup());
+                    }
                 }
 
                 LLMatrix4& tex_mat = *facep->mTextureMatrix;
@@ -832,12 +841,25 @@ void LLVOVolume::updateTextureVirtualSize(bool forced)
         // if the face has gotten small enough to turn off texture animation and texture
         // animation is running, rebuild the render batch for this face to turn off
         // texture animation
+        // Do the opposite when the face gets big enough.
+        // If a face is animatable, it will always have non-null mTextureMatrix
+        // pointer defined after the first call to LLVOVolume::animateTextures,
+        // although the animation is not always turned on.
         if (face->mTextureMatrix != NULL)
         {
-            if ((vsize < MIN_TEX_ANIM_SIZE && old_size > MIN_TEX_ANIM_SIZE) ||
-                (vsize > MIN_TEX_ANIM_SIZE && old_size < MIN_TEX_ANIM_SIZE))
+            if ((vsize > MIN_TEX_ANIM_SIZE) != (old_size > MIN_TEX_ANIM_SIZE))
             {
                 gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_TCOORD);
+                // dirtyGeom+markRebuild tells the engine to call
+                // LLVolumeGeometryManager::rebuildGeom, which rebuilds the
+                // LLDrawInfo for the spatial group containing this LLFace,
+                // safely copying the mTextureMatrix from the LLFace the the
+                // LLDrawInfo. While it's not ideal to call it here, prims with
+                // animated faces get moved to a smaller partition to reduce
+                // side-effects of their updates (see shrinkWrap in
+                // LLVOVolume::animateTextures).
+                mDrawable->getSpatialGroup()->dirtyGeom();
+                gPipeline.markRebuild(mDrawable->getSpatialGroup());
             }
         }
 
-- 
cgit v1.2.3


From 228937571ecdb7335e2ebf5de76aa256280b0bd5 Mon Sep 17 00:00:00 2001
From: Alexander Gavriliuk <gavriliuk@gmail.com>
Date: Wed, 6 Nov 2024 00:30:56 +0100
Subject: #2902 Additional lines are displayed from one corner of the region

---
 indra/newview/llviewerparceloverlay.cpp | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

(limited to 'indra/newview')

diff --git a/indra/newview/llviewerparceloverlay.cpp b/indra/newview/llviewerparceloverlay.cpp
index 019e870829..5b26f9f031 100755
--- a/indra/newview/llviewerparceloverlay.cpp
+++ b/indra/newview/llviewerparceloverlay.cpp
@@ -559,8 +559,7 @@ void LLViewerParcelOverlay::addPropertyLine(F32 start_x, F32 start_y, F32 dx, F3
         {
             F32 new_x = start[VX] + (x - start[VX]) * part;
             F32 new_y = start[VY] + (y - start[VY]) * part;
-            F32 new_z = start[VZ] + (z - start[VZ]) * part;
-            edge.pushVertex(lod, new_x, new_y, new_z, water_z);
+            edge.pushVertex(lod, new_x, new_y, water_z, 0);
         };
 
     auto checkForSplit = [&](U32 lod)
@@ -624,7 +623,6 @@ void LLViewerParcelOverlay::addPropertyLine(F32 start_x, F32 start_y, F32 dx, F3
 
     // Point G simplified (last two vertices)
     move(LINE_WIDTH);
-    checkForSplit(1);
     pushTwoVertices(1);
 
     // Point G detailized (only one vertex)
-- 
cgit v1.2.3


From a01548deae16429072eedc2d18b51e4db908403b Mon Sep 17 00:00:00 2001
From: Cosmic Linden <cosmic@lindenlab.com>
Date: Tue, 5 Nov 2024 15:45:54 -0800
Subject: Miscellaneous cleanup

---
 indra/newview/llface.cpp           |  2 +-
 indra/newview/llspatialpartition.h |  5 ++---
 indra/newview/llviewermenu.cpp     |  9 ++++-----
 indra/newview/llvovolume.cpp       | 16 ++++++++--------
 indra/newview/pipeline.cpp         |  5 -----
 5 files changed, 15 insertions(+), 22 deletions(-)

(limited to 'indra/newview')

diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp
index f3cb07739d..b726e21380 100644
--- a/indra/newview/llface.cpp
+++ b/indra/newview/llface.cpp
@@ -1557,7 +1557,7 @@ bool LLFace::getGeometryVolume(const LLVolume& volume,
             }
 
             U8 texgen = getTextureEntry()->getTexGen();
-            if (rebuild_tcoord && texgen != LLTextureEntry::TEX_GEN_DEFAULT)
+            if (texgen != LLTextureEntry::TEX_GEN_DEFAULT)
             { //planar texgen needs binormals
                 mVObjp->getVolume()->genTangents(face_index);
             }
diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h
index 3aaa3d60e8..016ebff827 100644
--- a/indra/newview/llspatialpartition.h
+++ b/indra/newview/llspatialpartition.h
@@ -123,7 +123,7 @@ public:
 
     std::vector<LLPointer<LLViewerTexture> > mTextureList;
 
-    LLUUID mMaterialID; // id of LLGLTFMaterial or LLMaterial applied to this draw info
+    LLUUID mMaterialHash; // hash of LLGLTFMaterial or LLMaterial applied to this draw info
 
     U32 mShaderMask = 0;
     F32  mEnvIntensity = 0.f;
@@ -272,8 +272,7 @@ public:
         IN_IMAGE_QUEUE          = (ALPHA_DIRTY << 1),
         IMAGE_DIRTY             = (IN_IMAGE_QUEUE << 1),
         MESH_DIRTY              = (IMAGE_DIRTY << 1),
-        NEW_DRAWINFO            = (MESH_DIRTY << 1),
-        IN_BUILD_Q1             = (NEW_DRAWINFO << 1),
+        IN_BUILD_Q1             = (MESH_DIRTY << 1),
         IN_BUILD_Q2             = (IN_BUILD_Q1 << 1),
         STATE_MASK              = 0x0000FFFF,
     } eSpatialState;
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 68c38c3692..247c76c0cb 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -9897,7 +9897,6 @@ void initialize_menus()
     view_listener_t::addMenu(new LLAdvancedClickGLTFEdit(), "Advanced.ClickGLTFEdit", cb_info::UNTRUSTED_BLOCK);
     view_listener_t::addMenu(new LLAdvancedClickResizeWindow(), "Advanced.ClickResizeWindow", cb_info::UNTRUSTED_BLOCK);
     view_listener_t::addMenu(new LLAdvancedPurgeShaderCache(), "Advanced.ClearShaderCache", cb_info::UNTRUSTED_BLOCK);
-    view_listener_t::addMenu(new LLAdvancedRebuildTerrain(), "Advanced.RebuildTerrain", cb_info::UNTRUSTED_BLOCK);
 
     #ifdef TOGGLE_HACKED_GODLIKE_VIEWER
     view_listener_t::addMenu(new LLAdvancedHandleToggleHackedGodmode(), "Advanced.HandleToggleHackedGodmode");
@@ -9915,10 +9914,10 @@ void initialize_menus()
     view_listener_t::addMenu(new LLAdvancedResetInterestLists(), "Advanced.ResetInterestLists");
 
     // Develop > Terrain
-    view_listener_t::addMenu(new LLAdvancedRebuildTerrain(), "Advanced.RebuildTerrain");
-    view_listener_t::addMenu(new LLAdvancedTerrainCreateLocalPaintMap(), "Advanced.TerrainCreateLocalPaintMap");
-    view_listener_t::addMenu(new LLAdvancedTerrainEditLocalPaintMap(), "Advanced.TerrainEditLocalPaintMap");
-    view_listener_t::addMenu(new LLAdvancedTerrainDeleteLocalPaintMap(), "Advanced.TerrainDeleteLocalPaintMap");
+    view_listener_t::addMenu(new LLAdvancedRebuildTerrain(), "Advanced.RebuildTerrain", cb_info::UNTRUSTED_BLOCK);
+    view_listener_t::addMenu(new LLAdvancedTerrainCreateLocalPaintMap(), "Advanced.TerrainCreateLocalPaintMap", cb_info::UNTRUSTED_BLOCK);
+    view_listener_t::addMenu(new LLAdvancedTerrainEditLocalPaintMap(), "Advanced.TerrainEditLocalPaintMap", cb_info::UNTRUSTED_BLOCK);
+    view_listener_t::addMenu(new LLAdvancedTerrainDeleteLocalPaintMap(), "Advanced.TerrainDeleteLocalPaintMap", cb_info::UNTRUSTED_BLOCK);
 
     // Advanced > UI
     registrar.add("Advanced.WebBrowserTest", boost::bind(&handle_web_browser_test, _2));  // sigh! this one opens the MEDIA browser
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 7289b080a6..dec28ad3e8 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -5431,7 +5431,7 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
         info->mEnd - draw_vec[idx]->mStart + facep->getGeomCount() <= (U32) gGLManager.mGLMaxVertexRange &&
         info->mCount + facep->getIndicesCount() <= (U32) gGLManager.mGLMaxIndexRange &&
 #endif
-        info->mMaterialID == mat_id &&
+        info->mMaterialHash == mat_id &&
         info->mFullbright == fullbright &&
         info->mBump == bump &&
         (!mat || (info->mShiny == shiny)) && // need to break batches when a material is shared, but legacy settings are different
@@ -5490,11 +5490,11 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
         if (gltf_mat)
         {
             // just remember the material ID, render pools will reference the GLTF material
-            draw_info->mMaterialID = mat_id;
+            draw_info->mMaterialHash = mat_id;
         }
         else if (mat)
         {
-            draw_info->mMaterialID = mat_id;
+            draw_info->mMaterialHash = mat_id;
 
             // We have a material.  Update our draw info accordingly.
 
@@ -5526,10 +5526,10 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
             }
         }
 
-        // if (type == LLRenderPass::PASS_ALPHA) // always populate the draw_info ptr
-        { //for alpha sorting
-            facep->setDrawInfo(draw_info);
-        }
+        // This backpointer is used by alpha sorting and avatar attachment
+        // accounting.
+        // To be safe, always populate the draw_info ptr.
+        facep->setDrawInfo(draw_info);
 
         if (index < FACE_DO_NOT_BATCH_TEXTURES)
         { //initialize texture list for texture batching
@@ -6151,7 +6151,7 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group)
                 LLVertexBuffer::flushBuffers();
             }
 
-            group->clearState(LLSpatialGroup::MESH_DIRTY | LLSpatialGroup::NEW_DRAWINFO);
+            group->clearState(LLSpatialGroup::MESH_DIRTY);
         }
     }
 }
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index a88756452e..65f7c1d70f 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -3520,11 +3520,6 @@ void LLPipeline::postSort(LLCamera &camera)
             continue;
         }
 
-        if (group->hasState(LLSpatialGroup::NEW_DRAWINFO) && group->hasState(LLSpatialGroup::GEOM_DIRTY) && !gCubeSnapshot)
-        {  // no way this group is going to be drawable without a rebuild
-            group->rebuildGeom();
-        }
-
         for (LLSpatialGroup::draw_map_t::iterator j = group->mDrawMap.begin(); j != group->mDrawMap.end(); ++j)
         {
             LLSpatialGroup::drawmap_elem_t &src_vec = j->second;
-- 
cgit v1.2.3


From c092782cf76f90d42aa21fed318126f3f094d793 Mon Sep 17 00:00:00 2001
From: Rye <rye@lindenlab.com>
Date: Tue, 5 Nov 2024 22:57:25 -0500
Subject: Fix Tracy memory profiling on macos

---
 indra/newview/llappviewermacosx.cpp | 5 +++++
 1 file changed, 5 insertions(+)

(limited to 'indra/newview')

diff --git a/indra/newview/llappviewermacosx.cpp b/indra/newview/llappviewermacosx.cpp
index 4162c0479a..f497a3cdf3 100644
--- a/indra/newview/llappviewermacosx.cpp
+++ b/indra/newview/llappviewermacosx.cpp
@@ -231,6 +231,11 @@ void infos(const std::string& message)
 
 int main( int argc, char **argv )
 {
+    // Call Tracy first thing to have it allocate memory
+    // https://github.com/wolfpld/tracy/issues/196
+    LL_PROFILER_FRAME_END;
+    LL_PROFILER_SET_THREAD_NAME("App");
+
     // Store off the command line args for use later.
     gArgC = argc;
     gArgV = argv;
-- 
cgit v1.2.3


From a783759c11fd1c5ef660fda4a867875fe9fafeb8 Mon Sep 17 00:00:00 2001
From: Rye <rye@lindenlab.com>
Date: Tue, 5 Nov 2024 23:00:17 -0500
Subject: Fix accidental deprecation in shaders causing mac shader compile fail

---
 .../app_settings/shaders/class1/deferred/SMAANeighborhoodBlendF.glsl    | 2 +-
 indra/newview/app_settings/shaders/class1/deferred/cofF.glsl            | 2 +-
 .../newview/app_settings/shaders/class1/interface/glowcombineFXAAF.glsl | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

(limited to 'indra/newview')

diff --git a/indra/newview/app_settings/shaders/class1/deferred/SMAANeighborhoodBlendF.glsl b/indra/newview/app_settings/shaders/class1/deferred/SMAANeighborhoodBlendF.glsl
index 08052a9ddf..6b8e7b1ffe 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/SMAANeighborhoodBlendF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/SMAANeighborhoodBlendF.glsl
@@ -62,7 +62,7 @@ void main()
                                             #endif
                                             );
 #ifndef NO_GLOW
-    diff.rgb += texture2D(emissiveRect, vary_texcoord0).rgb;
+    diff.rgb += texture(emissiveRect, vary_texcoord0).rgb;
 #endif
     frag_color = diff;
 
diff --git a/indra/newview/app_settings/shaders/class1/deferred/cofF.glsl b/indra/newview/app_settings/shaders/class1/deferred/cofF.glsl
index 36611db2fb..7b196f7da8 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/cofF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/cofF.glsl
@@ -73,7 +73,7 @@ void main()
     sc = min(sc, max_cof);
     sc = max(sc, -max_cof);
 
-    vec4 bloom = texture2D(emissiveRect, tc);
+    vec4 bloom = texture(emissiveRect, tc);
     frag_color.rgb = diff.rgb + bloom.rgb;
     frag_color.a = sc/max_cof*0.5+0.5;
 }
diff --git a/indra/newview/app_settings/shaders/class1/interface/glowcombineFXAAF.glsl b/indra/newview/app_settings/shaders/class1/interface/glowcombineFXAAF.glsl
index 8a8de88182..a0d11bb026 100644
--- a/indra/newview/app_settings/shaders/class1/interface/glowcombineFXAAF.glsl
+++ b/indra/newview/app_settings/shaders/class1/interface/glowcombineFXAAF.glsl
@@ -38,7 +38,7 @@ void main()
 {
     vec3 col = texture(diffuseRect, vary_tc).rgb;
 #ifndef NO_GLOW
-    col += texture2D(emissiveRect, vary_tc).rgb;
+    col += texture(emissiveRect, vary_tc).rgb;
 #endif
     frag_color = vec4(col, dot(col, vec3(0.299, 0.587, 0.144)));
 }
-- 
cgit v1.2.3


From d9ee26fcbabbb5fe94006b8d31d4bfb988f7b53e Mon Sep 17 00:00:00 2001
From: Rye <rye@lindenlab.com>
Date: Wed, 6 Nov 2024 04:06:29 -0500
Subject: Improve Tracy OpenGL integration Fix memory profiling when gpu
 profiling enabled Fix disabling renderdoc support

---
 indra/newview/llappviewer.cpp            | 37 +++++++++++++++++---------------
 indra/newview/lldrawpool.h               |  2 +-
 indra/newview/llheroprobemanager.cpp     | 11 +++++++---
 indra/newview/llreflectionmapmanager.cpp |  4 ++++
 indra/newview/llviewerdisplay.cpp        |  2 ++
 indra/newview/pipeline.cpp               | 24 ++++++++++++---------
 6 files changed, 49 insertions(+), 31 deletions(-)

(limited to 'indra/newview')

diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 423fe2469a..fda4f043b0 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -1473,6 +1473,7 @@ void sendGameControlInput()
 bool LLAppViewer::doFrame()
 {
     LL_RECORD_BLOCK_TIME(FTM_FRAME);
+    LL_PROFILE_GPU_ZONE("Frame");
     {
     // and now adjust the visuals from previous frame.
     if(LLPerfStats::tunables.userAutoTuneEnabled && LLPerfStats::tunables.tuningFlag != LLPerfStats::Tunables::Nothing)
@@ -1562,24 +1563,26 @@ bool LLAppViewer::doFrame()
 
         if (!LLApp::isExiting())
         {
-            LL_PROFILE_ZONE_NAMED_CATEGORY_APP("df JoystickKeyboard");
-            pingMainloopTimeout("Main:JoystickKeyboard");
-
-            // Scan keyboard for movement keys.  Command keys and typing
-            // are handled by windows callbacks.  Don't do this until we're
-            // done initializing.  JC
-            if (gViewerWindow
-                && (gHeadlessClient || gViewerWindow->getWindow()->getVisible())
-                && gViewerWindow->getActive()
-                && !gViewerWindow->getWindow()->getMinimized()
-                && LLStartUp::getStartupState() == STATE_STARTED
-                && (gHeadlessClient || !gViewerWindow->getShowProgress())
-                && !gFocusMgr.focusLocked())
             {
-                LLPerfStats::RecordSceneTime T (LLPerfStats::StatType_t::RENDER_IDLE);
-                joystick->scanJoystick();
-                gKeyboard->scanKeyboard();
-                gViewerInput.scanMouse();
+                LL_PROFILE_ZONE_NAMED_CATEGORY_APP("df JoystickKeyboard");
+                pingMainloopTimeout("Main:JoystickKeyboard");
+
+                // Scan keyboard for movement keys.  Command keys and typing
+                // are handled by windows callbacks.  Don't do this until we're
+                // done initializing.  JC
+                if (gViewerWindow
+                    && (gHeadlessClient || gViewerWindow->getWindow()->getVisible())
+                    && gViewerWindow->getActive()
+                    && !gViewerWindow->getWindow()->getMinimized()
+                    && LLStartUp::getStartupState() == STATE_STARTED
+                    && (gHeadlessClient || !gViewerWindow->getShowProgress())
+                    && !gFocusMgr.focusLocked())
+                {
+                    LLPerfStats::RecordSceneTime T(LLPerfStats::StatType_t::RENDER_IDLE);
+                    joystick->scanJoystick();
+                    gKeyboard->scanKeyboard();
+                    gViewerInput.scanMouse();
+                }
             }
 
             // Update state based on messages, user input, object idle.
diff --git a/indra/newview/lldrawpool.h b/indra/newview/lldrawpool.h
index bc412214c7..34257f98f8 100644
--- a/indra/newview/lldrawpool.h
+++ b/indra/newview/lldrawpool.h
@@ -339,7 +339,7 @@ public:
         }
     }
     #else
-    static inline const char* lookupPass(U32 pass) { return ""; }
+    static inline const char* lookupPassName(U32 pass) { return ""; }
     #endif
 
     LLRenderPass(const U32 type);
diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp
index ce419498cf..8e3cd0626f 100644
--- a/indra/newview/llheroprobemanager.cpp
+++ b/indra/newview/llheroprobemanager.cpp
@@ -81,6 +81,7 @@ void LLHeroProbeManager::update()
     }
 
     LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
+    LL_PROFILE_GPU_ZONE("hero manager update");
     llassert(!gCubeSnapshot); // assert a snapshot is not in progress
     if (LLAppViewer::instance()->logoutRequestSent())
     {
@@ -279,6 +280,9 @@ void LLHeroProbeManager::renderProbes()
 // In effect this simulates single-bounce lighting.
 void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, bool is_dynamic, F32 near_clip)
 {
+    LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
+    LL_PROFILE_GPU_ZONE("hero probe update");
+
     // hacky hot-swap of camera specific render targets
     gPipeline.mRT = &gPipeline.mHeroProbeRT;
 
@@ -349,7 +353,7 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, bool
 
         for (int i = 0; i < mMipChain.size(); ++i)
         {
-            LL_PROFILE_GPU_ZONE("probe mip");
+            LL_PROFILE_GPU_ZONE("hero probe mip");
             mMipChain[i].bindTarget();
             if (i == 0)
             {
@@ -376,7 +380,7 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, bool
 
             if (mip >= 0)
             {
-                LL_PROFILE_GPU_ZONE("probe mip copy");
+                LL_PROFILE_GPU_ZONE("hero probe mip copy");
                 mTexture->bind(0);
 
                 glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, 0, 0, sourceIdx * 6 + face, 0, 0, res, res);
@@ -424,7 +428,7 @@ void LLHeroProbeManager::generateRadiance(LLReflectionMap* probe)
 
             for (int i = 0; i < mMipChain.size() / 4; ++i)
             {
-                LL_PROFILE_GPU_ZONE("probe radiance gen");
+                LL_PROFILE_GPU_ZONE("hero probe radiance gen");
                 static LLStaticHashedString sMipLevel("mipLevel");
                 static LLStaticHashedString sRoughness("roughness");
                 static LLStaticHashedString sWidth("u_width");
@@ -471,6 +475,7 @@ void LLHeroProbeManager::updateUniforms()
     }
 
     LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
+    LL_PROFILE_GPU_ZONE("hpmu - uniforms")
 
     LLMatrix4a modelview;
     modelview.loadu(gGLModelView);
diff --git a/indra/newview/llreflectionmapmanager.cpp b/indra/newview/llreflectionmapmanager.cpp
index f083747bfe..4b79ce03eb 100644
--- a/indra/newview/llreflectionmapmanager.cpp
+++ b/indra/newview/llreflectionmapmanager.cpp
@@ -210,6 +210,7 @@ void LLReflectionMapManager::update()
     }
 
     LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
+    LL_PROFILE_GPU_ZONE("reflection manager update");
     llassert(!gCubeSnapshot); // assert a snapshot is not in progress
     if (LLAppViewer::instance()->logoutRequestSent())
     {
@@ -677,6 +678,8 @@ void LLReflectionMapManager::doProbeUpdate()
 // In effect this simulates single-bounce lighting.
 void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
 {
+    LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
+    LL_PROFILE_GPU_ZONE("probe update");
     // hacky hot-swap of camera specific render targets
     gPipeline.mRT = &gPipeline.mAuxillaryRT;
 
@@ -991,6 +994,7 @@ void LLReflectionMapManager::updateUniforms()
     }
 
     LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
+    LL_PROFILE_GPU_ZONE("rmmu - uniforms")
 
     // structure for packing uniform buffer object
     // see class3/deferred/reflectionProbeF.glsl
diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp
index b0e07d8ea3..94ebca77e2 100644
--- a/indra/newview/llviewerdisplay.cpp
+++ b/indra/newview/llviewerdisplay.cpp
@@ -406,6 +406,7 @@ static void update_tp_display(bool minimized)
 void display(bool rebuild, F32 zoom_factor, int subfield, bool for_snapshot)
 {
     LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("Render");
+    LL_PROFILE_GPU_ZONE("Render");
 
     LLPerfStats::RecordSceneTime T (LLPerfStats::StatType_t::RENDER_DISPLAY); // render time capture - This is the main stat for overall rendering.
 
@@ -710,6 +711,7 @@ void display(bool rebuild, F32 zoom_factor, int subfield, bool for_snapshot)
         if (gPipeline.RenderMirrors && !gSnapshot)
         {
             LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("Update hero probes");
+            LL_PROFILE_GPU_ZONE("hero manager")
             gPipeline.mHeroProbeManager.update();
             gPipeline.mHeroProbeManager.renderProbes();
         }
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index a88756452e..a17fd4d551 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -7063,11 +7063,12 @@ extern LLPointer<LLImageGL> gEXRImage;
 
 void LLPipeline::tonemap(LLRenderTarget* src, LLRenderTarget* dst, bool gamma_correct/* = true*/)
 {
-    dst->bindTarget();
     // gamma correct lighting
     {
         LL_PROFILE_GPU_ZONE("tonemap");
 
+        dst->bindTarget();
+
         static LLCachedControl<bool> buildNoPost(gSavedSettings, "RenderDisablePostProcessing", false);
 
         LLGLDepthTest depth(GL_FALSE, GL_FALSE);
@@ -7120,13 +7121,13 @@ void LLPipeline::tonemap(LLRenderTarget* src, LLRenderTarget* dst, bool gamma_co
 
         gGL.getTexUnit(channel)->unbind(src->getUsage());
         shader->unbind();
+
+        dst->flush();
     }
-    dst->flush();
 }
 
 void LLPipeline::copyScreenSpaceReflections(LLRenderTarget* src, LLRenderTarget* dst)
 {
-
     if (RenderScreenSpaceReflections && !gCubeSnapshot)
     {
         LL_PROFILE_GPU_ZONE("ssr copy");
@@ -7153,9 +7154,9 @@ void LLPipeline::copyScreenSpaceReflections(LLRenderTarget* src, LLRenderTarget*
 
 void LLPipeline::generateGlow(LLRenderTarget* src)
 {
+    LL_PROFILE_GPU_ZONE("glow generate");
     if (sRenderGlow)
     {
-        LL_PROFILE_GPU_ZONE("glow");
         mGlow[2].bindTarget();
         mGlow[2].clear();
 
@@ -7266,6 +7267,8 @@ void LLPipeline::applyCAS(LLRenderTarget* src, LLRenderTarget* dst)
     static LLCachedControl<F32> cas_sharpness(gSavedSettings, "RenderCASSharpness", 0.4f);
     static LLCachedControl<bool> should_auto_adjust(gSavedSettings, "RenderSkyAutoAdjustLegacy", true);
 
+    LL_PROFILE_GPU_ZONE("cas");
+
     LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky();
     LLGLSLShader* sharpen_shader = psky->getReflectionProbeAmbiance(should_auto_adjust) == 0.f ? &gCASLegacyGammaProgram : &gCASProgram;
 
@@ -7308,7 +7311,7 @@ void LLPipeline::applyFXAA(LLRenderTarget* src, LLRenderTarget* dst, bool combin
     llassert(!gCubeSnapshot);
     LLGLSLShader* shader = &gGlowCombineProgram;
 
-    LL_PROFILE_GPU_ZONE("aa");
+    LL_PROFILE_GPU_ZONE("FXAA");
     S32 width = src->getWidth();
     S32 height = src->getHeight();
 
@@ -7393,7 +7396,7 @@ void LLPipeline::generateSMAABuffers(LLRenderTarget* src)
     // Present everything.
     if (multisample)
     {
-        LL_PROFILE_GPU_ZONE("aa");
+        LL_PROFILE_GPU_ZONE("SMAA Edge");
         static LLCachedControl<U32> aa_quality(gSavedSettings, "RenderFSAASamples", 0U);
         U32 fsaa_quality = std::clamp(aa_quality(), 0U, 3U);
 
@@ -7508,7 +7511,7 @@ void LLPipeline::applySMAA(LLRenderTarget* src, LLRenderTarget* dst, bool combin
 {
     llassert(!gCubeSnapshot);
 
-    LL_PROFILE_GPU_ZONE("aa");
+    LL_PROFILE_GPU_ZONE("SMAA");
     static LLCachedControl<U32> aa_quality(gSavedSettings, "RenderFSAASamples", 0U);
     U32 fsaa_quality = std::clamp(aa_quality(), 0U, 3U);
 
@@ -7571,7 +7574,6 @@ void LLPipeline::applySMAA(LLRenderTarget* src, LLRenderTarget* dst, bool combin
 
 void LLPipeline::copyRenderTarget(LLRenderTarget* src, LLRenderTarget* dst)
 {
-
     LL_PROFILE_GPU_ZONE("copyRenderTarget");
     dst->bindTarget();
 
@@ -7592,8 +7594,9 @@ void LLPipeline::copyRenderTarget(LLRenderTarget* src, LLRenderTarget* dst)
 
 void LLPipeline::combineGlow(LLRenderTarget* src, LLRenderTarget* dst)
 {
-    // Go ahead and do our glow combine here in our destination.  We blit this later into the front buffer.
+    LL_PROFILE_GPU_ZONE("glow combine");
 
+    // Go ahead and do our glow combine here in our destination.  We blit this later into the front buffer.
     if (dst)
     {
         dst->bindTarget();
@@ -7609,6 +7612,7 @@ void LLPipeline::combineGlow(LLRenderTarget* src, LLRenderTarget* dst)
         mScreenTriangleVB->setBuffer();
         mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3);
     }
+
     if (dst)
     {
         dst->flush();
@@ -7617,9 +7621,9 @@ void LLPipeline::combineGlow(LLRenderTarget* src, LLRenderTarget* dst)
 
 void LLPipeline::renderDoF(LLRenderTarget* src, LLRenderTarget* dst)
 {
+    LL_PROFILE_GPU_ZONE("dof");
     gViewerWindow->setup3DViewport();
 
-    LL_PROFILE_GPU_ZONE("dof");
     LLGLDisable blend(GL_BLEND);
 
     // depth of field focal plane calculations
-- 
cgit v1.2.3


From 15d4bb6353070ecaf3102363ba83b40c015dd9be Mon Sep 17 00:00:00 2001
From: Alexander Gavriliuk <alexandrgproductengine@lindenlab.com>
Date: Wed, 6 Nov 2024 11:48:35 +0100
Subject: #2997 The 'Reset Skeleton' option is missing in the right-click menu

---
 indra/newview/llviewermenu.cpp | 7 ++-----
 1 file changed, 2 insertions(+), 5 deletions(-)

(limited to 'indra/newview')

diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 68c38c3692..0b7d1a7e35 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -6722,11 +6722,8 @@ class LLAvatarEnableResetSkeleton : public view_listener_t
 {
     bool handleEvent(const LLSD& userdata)
     {
-        if (LLVOAvatar* avatar = find_avatar_from_object(LLSelectMgr::getInstance()->getSelection()->getPrimaryObject()))
-        {
-            return true;
-        }
-        return false;
+        LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
+        return obj && obj->getAvatar();
     }
 };
 
-- 
cgit v1.2.3


From 7e479bf89dba7a27c57bf09e346d78eee25ef6f1 Mon Sep 17 00:00:00 2001
From: Maxim Nikolenko <maximnproductengine@lindenlab.com>
Date: Wed, 6 Nov 2024 20:09:19 +0200
Subject: #3029 restore tooltip delay const variable

---
 indra/newview/lltooldraganddrop.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

(limited to 'indra/newview')

diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp
index 6d0704a469..f94d94628d 100644
--- a/indra/newview/lltooldraganddrop.cpp
+++ b/indra/newview/lltooldraganddrop.cpp
@@ -574,12 +574,13 @@ bool LLToolDragAndDrop::handleKey(KEY key, MASK mask)
 
 bool LLToolDragAndDrop::handleToolTip(S32 x, S32 y, MASK mask)
 {
+    const F32 DRAG_N_DROP_TOOLTIP_DELAY = 0.1f;
     if (!mToolTipMsg.empty())
     {
         LLToolTipMgr::instance().unblockToolTips();
         LLToolTipMgr::instance().show(LLToolTip::Params()
             .message(mToolTipMsg)
-            .delay_time(gSavedSettings.getF32( "DragAndDropToolTipDelay" )));
+            .delay_time(DRAG_N_DROP_TOOLTIP_DELAY));
         return true;
     }
     return false;
-- 
cgit v1.2.3


From 0674dec8174b367a24805f662ff6dd2a93dc1e86 Mon Sep 17 00:00:00 2001
From: Cosmic Linden <cosmic@lindenlab.com>
Date: Wed, 6 Nov 2024 17:04:01 -0800
Subject: secondlife/viewer#2991: Fix PBR terrain sometimes not loading
 textures

---
 indra/newview/llfetchedgltfmaterial.h |  6 +++++-
 indra/newview/llvlcomposition.cpp     | 28 ++++++++--------------------
 indra/newview/llvlcomposition.h       | 18 ++++++++----------
 3 files changed, 21 insertions(+), 31 deletions(-)

(limited to 'indra/newview')

diff --git a/indra/newview/llfetchedgltfmaterial.h b/indra/newview/llfetchedgltfmaterial.h
index 634a4853b0..4a33b9f05f 100644
--- a/indra/newview/llfetchedgltfmaterial.h
+++ b/indra/newview/llfetchedgltfmaterial.h
@@ -31,10 +31,14 @@
 #include "llviewertexture.h"
 
 class LLGLSLShader;
+class LLGLTFMaterialList;
+class LLTerrainMaterials;
 
 class LLFetchedGLTFMaterial: public LLGLTFMaterial
 {
-    friend class LLGLTFMaterialList; // for lifetime management
+    // for lifetime management
+    friend class LLGLTFMaterialList;
+    friend class LLTerrainMaterials;
 public:
     LLFetchedGLTFMaterial();
     virtual ~LLFetchedGLTFMaterial();
diff --git a/indra/newview/llvlcomposition.cpp b/indra/newview/llvlcomposition.cpp
index ca76d93cd7..4a5f269c9f 100644
--- a/indra/newview/llvlcomposition.cpp
+++ b/indra/newview/llvlcomposition.cpp
@@ -102,14 +102,6 @@ namespace
     }
 };
 
-LLTerrainMaterials::LLTerrainMaterials()
-{
-    for (S32 i = 0; i < ASSET_COUNT; ++i)
-    {
-        mMaterialTexturesSet[i] = false;
-    }
-}
-
 LLTerrainMaterials::~LLTerrainMaterials()
 {
     unboost();
@@ -199,7 +191,6 @@ void LLTerrainMaterials::setDetailAssetID(S32 asset, const LLUUID& id)
     LLPointer<LLFetchedGLTFMaterial>& mat = mDetailMaterials[asset];
     mat = id.isNull() ? nullptr : gGLTFMaterialList.getMaterial(id);
     mDetailRenderMaterials[asset] = nullptr;
-    mMaterialTexturesSet[asset] = false;
 }
 
 const LLGLTFMaterial* LLTerrainMaterials::getMaterialOverride(S32 asset) const
@@ -262,11 +253,17 @@ bool LLTerrainMaterials::makeMaterialsReady(bool boost, bool strict)
         if (!material_asset_ready(mat)) { continue; }
 
         LLPointer<LLFetchedGLTFMaterial>& render_mat = mDetailRenderMaterials[i];
+        // This will be mutated by materialTexturesReady, due to the way that
+        // function is implemented.
+        bool render_material_textures_set = bool(render_mat);
         if (!render_mat)
         {
             render_mat = new LLFetchedGLTFMaterial();
             *render_mat = *mat;
             // This render_mat is effectively already loaded, because it gets its data from mat.
+            // However, its textures may not be loaded yet.
+            render_mat->materialBegin();
+            render_mat->materialComplete(true);
 
             LLPointer<LLGLTFMaterial>& override_mat = mDetailMaterialOverrides[i];
             if (override_mat)
@@ -275,7 +272,8 @@ bool LLTerrainMaterials::makeMaterialsReady(bool boost, bool strict)
             }
         }
 
-        ready[i] = materialTexturesReady(render_mat, mMaterialTexturesSet[i], boost, strict);
+        ready[i] = materialTexturesReady(render_mat, render_material_textures_set, boost, strict);
+        llassert(render_material_textures_set);
     }
 
 #if 1
@@ -418,16 +416,6 @@ bool LLTerrainMaterials::materialTexturesReady(LLPointer<LLFetchedGLTFMaterial>&
     return true;
 }
 
-// Boost the loading priority of every known texture in the material
-// Return true when ready to use
-// static
-bool LLTerrainMaterials::makeMaterialReady(LLPointer<LLFetchedGLTFMaterial> &mat, bool &textures_set, bool boost, bool strict)
-{
-    if (!material_asset_ready(mat)) { return false; }
-
-    return materialTexturesReady(mat, textures_set, boost, strict);
-}
-
 // static
 const LLUUID (&LLVLComposition::getDefaultTextures())[ASSET_COUNT]
 {
diff --git a/indra/newview/llvlcomposition.h b/indra/newview/llvlcomposition.h
index 21fd484375..9574080b38 100644
--- a/indra/newview/llvlcomposition.h
+++ b/indra/newview/llvlcomposition.h
@@ -27,19 +27,17 @@
 #ifndef LL_LLVLCOMPOSITION_H
 #define LL_LLVLCOMPOSITION_H
 
+#include "llfetchedgltfmaterial.h"
+#include "llimage.h"
+#include "llpointer.h"
+#include "llterrainpaintmap.h"
 #include "llviewerlayer.h"
 #include "llviewershadermgr.h"
 #include "llviewertexture.h"
-#include "llpointer.h"
-#include "llterrainpaintmap.h"
-
-#include "llimage.h"
 
 class LLSurface;
 
 class LLViewerFetchedTexture;
-class LLGLTFMaterial;
-class LLFetchedGLTFMaterial;
 
 class LLModifyRegion
 {
@@ -53,7 +51,7 @@ class LLTerrainMaterials : public LLModifyRegion
 public:
     friend class LLDrawPoolTerrain;
 
-    LLTerrainMaterials();
+    LLTerrainMaterials() {}
     virtual ~LLTerrainMaterials();
 
     void apply(const LLModifyRegion& other);
@@ -106,15 +104,15 @@ protected:
     static bool makeTextureReady(LLPointer<LLViewerFetchedTexture>& tex, bool boost);
     // strict = true -> all materials must be sufficiently loaded
     // strict = false -> at least one material must be loaded
-    static bool makeMaterialReady(LLPointer<LLFetchedGLTFMaterial>& mat, bool& textures_set, bool boost, bool strict);
-    // *NOTE: Prefer calling makeMaterialReady if mat is known to be LLFetchedGLTFMaterial
     static bool materialTexturesReady(LLPointer<LLFetchedGLTFMaterial>& mat, bool& textures_set, bool boost, bool strict);
 
     LLPointer<LLViewerFetchedTexture> mDetailTextures[ASSET_COUNT];
+    // *NOTE: Unlike mDetailRenderMaterials, the textures in this are not
+    // guaranteed to be set or loaded after a true return from
+    // makeMaterialsReady.
     LLPointer<LLFetchedGLTFMaterial> mDetailMaterials[ASSET_COUNT];
     LLPointer<LLGLTFMaterial> mDetailMaterialOverrides[ASSET_COUNT];
     LLPointer<LLFetchedGLTFMaterial> mDetailRenderMaterials[ASSET_COUNT];
-    bool mMaterialTexturesSet[ASSET_COUNT];
 
     U32 mPaintType = TERRAIN_PAINT_TYPE_HEIGHTMAP_WITH_NOISE;
     LLPointer<LLViewerTexture> mPaintMap;
-- 
cgit v1.2.3


From 03231789c016245cdc93d154502c879386030de1 Mon Sep 17 00:00:00 2001
From: Rye <rye@lindenlab.com>
Date: Wed, 6 Nov 2024 10:41:41 -0500
Subject: Update Tracy to 0.11.1

---
 indra/newview/llappviewerlinux.cpp | 5 +++++
 1 file changed, 5 insertions(+)

(limited to 'indra/newview')

diff --git a/indra/newview/llappviewerlinux.cpp b/indra/newview/llappviewerlinux.cpp
index 3dbbda11f9..febe2d1e41 100644
--- a/indra/newview/llappviewerlinux.cpp
+++ b/indra/newview/llappviewerlinux.cpp
@@ -113,6 +113,11 @@ static void exceptionTerminateHandler()
 
 int main( int argc, char **argv )
 {
+    // Call Tracy first thing to have it allocate memory
+    // https://github.com/wolfpld/tracy/issues/196
+    LL_PROFILER_FRAME_END;
+    LL_PROFILER_SET_THREAD_NAME("App");
+
     gArgC = argc;
     gArgV = argv;
 
-- 
cgit v1.2.3


From 4cec03671cd2a4ea3222bfaf4fd755ceaeb14231 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Thu, 7 Nov 2024 16:35:13 +0200
Subject: viewer#3037 hasPendingAttachedMeshes wasn't checking some objects

---
 indra/newview/llvoavatar.cpp | 116 ++++++++++++++++++++++++-------------------
 1 file changed, 66 insertions(+), 50 deletions(-)

(limited to 'indra/newview')

diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index bfed8b9d39..31be509b0b 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -683,7 +683,7 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
     mFullyLoaded(false),
     mPreviousFullyLoaded(false),
     mFullyLoadedInitialized(false),
-    mLastCloudAttachmentCount(0),
+    mLastCloudAttachmentCount(-1),
     mVisualComplexity(VISUAL_COMPLEXITY_UNKNOWN),
     mLoadedCallbacksPaused(false),
     mLoadedCallbackTextures(0),
@@ -7722,6 +7722,64 @@ void LLVOAvatar::cleanupAttachedMesh( LLViewerObject* pVO )
     }
 }
 
+bool check_object_for_mesh_loading(LLViewerObject* objectp)
+{
+    if (!objectp || !objectp->getVolume())
+    {
+        return false;
+    }
+    LLVolume* volp = objectp->getVolume();
+    const LLUUID& mesh_id = volp->getParams().getSculptID();
+    if (mesh_id.isNull())
+    {
+        // No mesh nor skin info needed
+        return false;
+    }
+
+    if (volp->isMeshAssetUnavaliable())
+    {
+        // Mesh failed to load, do not expect it
+        return false;
+    }
+
+    if (!objectp->mDrawable)
+    {
+        return false;
+    }
+
+    LLVOVolume* pvobj = objectp->mDrawable->getVOVolume();
+    if (pvobj)
+    {
+        if (!pvobj->isMesh())
+        {
+            // Not a mesh
+            return false;
+        }
+
+        if (!volp->isMeshAssetLoaded())
+        {
+            // Waiting for mesh
+            return true;
+        }
+
+        const LLMeshSkinInfo* skin_data = pvobj->getSkinInfo();
+        if (skin_data)
+        {
+            // Skin info present, done
+            return false;
+        }
+
+        if (pvobj->isSkinInfoUnavaliable())
+        {
+            // Load failed or info not present, don't expect it
+            return false;
+        }
+    }
+
+    // object is not ready
+    return true;
+}
+
 bool LLVOAvatar::hasPendingAttachedMeshes()
 {
     for (attachment_map_t::iterator iter = mAttachmentPoints.begin();
@@ -7736,62 +7794,20 @@ bool LLVOAvatar::hasPendingAttachedMeshes()
                  ++attachment_iter)
             {
                 LLViewerObject* objectp = attachment_iter->get();
-                if (objectp)
+                if (objectp && !objectp->isDead())
                 {
+                    if (check_object_for_mesh_loading(objectp))
+                    {
+                        return true;
+                    }
                     LLViewerObject::const_child_list_t& child_list = objectp->getChildren();
                     for (LLViewerObject::child_list_t::const_iterator iter1 = child_list.begin();
                          iter1 != child_list.end(); ++iter1)
                     {
                         LLViewerObject* objectchild = *iter1;
-                        if (objectchild && objectchild->getVolume())
+                        if (check_object_for_mesh_loading(objectchild))
                         {
-                            const LLUUID& mesh_id = objectchild->getVolume()->getParams().getSculptID();
-                            if (mesh_id.isNull())
-                            {
-                                // No mesh nor skin info needed
-                                continue;
-                            }
-
-                            if (objectchild->getVolume()->isMeshAssetUnavaliable())
-                            {
-                                // Mesh failed to load, do not expect it
-                                continue;
-                            }
-
-                            if (objectchild->mDrawable)
-                            {
-                                LLVOVolume* pvobj = objectchild->mDrawable->getVOVolume();
-                                if (pvobj)
-                                {
-                                    if (!pvobj->isMesh())
-                                    {
-                                        // Not a mesh
-                                        continue;
-                                    }
-
-                                    if (!objectchild->getVolume()->isMeshAssetLoaded())
-                                    {
-                                        // Waiting for mesh
-                                        return true;
-                                    }
-
-                                    const LLMeshSkinInfo* skin_data = pvobj->getSkinInfo();
-                                    if (skin_data)
-                                    {
-                                        // Skin info present, done
-                                        continue;
-                                    }
-
-                                    if (pvobj->isSkinInfoUnavaliable())
-                                    {
-                                        // Load failed or info not present, don't expect it
-                                        continue;
-                                    }
-                                }
-
-                                // objectchild is not ready
-                                return true;
-                            }
+                            return true;
                         }
                     }
                 }
-- 
cgit v1.2.3


From 7c614d0091874afc0555a1e56594671b1e37aaa9 Mon Sep 17 00:00:00 2001
From: Maxim Nikolenko <maximnproductengine@lindenlab.com>
Date: Fri, 8 Nov 2024 14:23:37 +0200
Subject: #3042 crash at LLViewerMediaTexture::setPlaying

---
 indra/newview/llviewertexture.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'indra/newview')

diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index 82fefde0a7..56abe415fe 100644
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -3507,7 +3507,7 @@ void LLViewerMediaTexture::setPlaying(bool playing)
         {
             LLFace* facep = *iter;
             const LLTextureEntry* te = facep->getTextureEntry();
-            if (te->getGLTFMaterial())
+            if (te && te->getGLTFMaterial())
             {
                 // PBR material, switch emissive and basecolor
                 switchTexture(LLRender::EMISSIVE_MAP, *iter);
-- 
cgit v1.2.3


From a068928c374f7918682d069b284588af464ec43d Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Fri, 8 Nov 2024 12:18:15 +0200
Subject: viewer#3055 Fix texture fetch being stuck

destroyRawImage is the only function that calls saveRawImage(), not
calling it results in fetcher thinking that it still needs data to do
the saving and looping back to trying to fetch.
---
 indra/newview/llviewertexture.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'indra/newview')

diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index 56abe415fe..a17dff3336 100644
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -1555,8 +1555,8 @@ void LLViewerFetchedTexture::postCreateTexture()
     if (!needsToSaveRawImage())
     {
         mNeedsAux = false;
-        destroyRawImage();
     }
+    destroyRawImage(); // will save raw image if needed
 
     mNeedsCreateTexture = false;
 }
-- 
cgit v1.2.3


From 30ca4f02f503248212f7d1301ae2ff1835cf79bd Mon Sep 17 00:00:00 2001
From: Maxim Nikolenko <maximnproductengine@lindenlab.com>
Date: Fri, 8 Nov 2024 19:11:19 +0200
Subject: #3052 remove pointless logging when group notice is received

---
 indra/newview/llimprocessing.cpp | 8 --------
 1 file changed, 8 deletions(-)

(limited to 'indra/newview')

diff --git a/indra/newview/llimprocessing.cpp b/indra/newview/llimprocessing.cpp
index e050fb77e0..4c02511268 100644
--- a/indra/newview/llimprocessing.cpp
+++ b/indra/newview/llimprocessing.cpp
@@ -684,14 +684,6 @@ void LLIMProcessing::processNewMessage(LLUUID from_id,
                     asset_type = (LLAssetType::EType)(atoi((*(iter++)).c_str()));
                     iter++; // wearable type if applicable, otherwise asset type
                     item_name = std::string((*(iter++)).c_str());
-                    // Note There is more elements in 'tokens' ...
-
-
-                    for (int i = 0; i < 6; i++)
-                    {
-                        LL_WARNS() << *(iter++) << LL_ENDL;
-                        iter++;
-                    }
                 }
             }
             else
-- 
cgit v1.2.3


From 8b496685f27a05cb97ac782424f0c9574db02676 Mon Sep 17 00:00:00 2001
From: Rye <rye@lindenlab.com>
Date: Fri, 8 Nov 2024 13:03:31 -0500
Subject: Fix assert when retrieving data while mousing over minimap avatar
 dots

secondlife/viewer#3025
---
 indra/newview/llavatarpropertiesprocessor.cpp | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

(limited to 'indra/newview')

diff --git a/indra/newview/llavatarpropertiesprocessor.cpp b/indra/newview/llavatarpropertiesprocessor.cpp
index 299cc5ed64..a108f5872c 100644
--- a/indra/newview/llavatarpropertiesprocessor.cpp
+++ b/indra/newview/llavatarpropertiesprocessor.cpp
@@ -31,6 +31,7 @@
 // Viewer includes
 #include "llagent.h"
 #include "llagentpicksinfo.h"
+#include "llappviewer.h"
 #include "lldateutil.h"
 #include "llviewergenericmessage.h"
 #include "llstartup.h"
@@ -367,7 +368,11 @@ void LLAvatarPropertiesProcessor::requestAvatarPropertiesCoro(std::string cap_ur
         avatar_data.picks_list.emplace_back(pick_data["id"].asUUID(), pick_data["name"].asString());
     }
 
-    inst.notifyObservers(avatar_id, &avatar_data, type);
+    LLAppViewer::instance()->postToMainCoro([=]()
+        {
+            LLAvatarData av_data = avatar_data;
+            instance().notifyObservers(avatar_id, &av_data, type);
+        });
 }
 
 void LLAvatarPropertiesProcessor::processAvatarLegacyPropertiesReply(LLMessageSystem* msg, void**)
-- 
cgit v1.2.3


From 471f874d17aea462c354c18673caac66bd43e9e7 Mon Sep 17 00:00:00 2001
From: Rider Linden <rider@lindenlab.com>
Date: Fri, 8 Nov 2024 16:49:34 -0800
Subject: Server Issue #1493: New notification message for llTransferOwnership.

---
 indra/newview/skins/default/xui/en/notifications.xml | 8 ++++++++
 1 file changed, 8 insertions(+)

(limited to 'indra/newview')

diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 4d74261a9a..9cca2d5b4d 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -10348,6 +10348,14 @@ You are now the owner of object [OBJECT_NAME]
 
   <notification
    icon="alertmodal.tga"
+   name="NowOwnObjectInv"
+   type="notify">
+   <tag>fail</tag>
+You are now the owner of object [OBJECT_NAME] and it has been placed in your inventory.
+  </notification>
+
+    <notification
+   icon="alertmodal.tga"
    name="CantRezOnLand"
    type="notify">
    <tag>fail</tag>
-- 
cgit v1.2.3