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(-)

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