diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 0ccf74e923ad46c49a5b5d3e2d7ae9d9da61d50c..442ac8895c23cbd6e1dd98e9b42d8aad8cd74694 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -16620,6 +16620,63 @@
       <key>Value</key>
       <integer>0</integer>
     </map>
+    <key>AutoFPS</key>
+    <map>
+      <key>Comment</key>
+      <string>
+        Allow dynamic adjustment of graphics preferences
+      </string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>Boolean</string>
+      <key>Value</key>
+      <integer>0</integer>
+    </map>
+  <key>AutoAdjustmentTimeout</key>
+  <map>
+    <key>Comment</key>
+    <string>Time before next iteration of automatic adjustments</string>
+    <key>Persist</key>
+    <integer>1</integer>
+    <key>Type</key>
+    <string>F32</string>
+    <key>Value</key>
+    <real>5</real>
+  </map>
+  <key>InitialAdjustmentTimeout</key>
+  <map>
+    <key>Comment</key>
+    <string>Time before first iteration of automatic adjustments after login to the world, teleporting, maximizing Viewer etc.</string>
+    <key>Persist</key>
+    <integer>1</integer>
+    <key>Type</key>
+    <string>F32</string>
+    <key>Value</key>
+    <real>10</real>
+  </map>
+  <key>AutoFPSLowerBoundary</key>
+  <map>
+    <key>Comment</key>
+    <string>FPS lower boundary when automatic adjustments are occured to reduce graphics quality to increase FPS</string>
+    <key>Persist</key>
+    <integer>1</integer>
+    <key>Type</key>
+    <string>S32</string>
+    <key>Value</key>
+    <real>30</real>
+  </map>
+  <key>AutoFPSUpperBoundary</key>
+  <map>
+    <key>Comment</key>
+    <string>FPS upper boundary when automatic adjustments are occured to increase graphics quality</string>
+    <key>Persist</key>
+    <integer>1</integer>
+    <key>Type</key>
+    <string>S32</string>
+    <key>Value</key>
+    <real>50</real>
+  </map>
   <key>CameraOpacity</key>
   <map>
     <key>Comment</key>
diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index de382d4e234d9b575b47c2994c60aec1bad76a56..b377d099beeb98122b589edcfbc2723241e3a6e6 100644
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -4078,6 +4078,8 @@ void LLAgent::handleTeleportFinished()
             mRegionp->setCapabilitiesReceivedCallback(boost::bind(&LLAgent::onCapabilitiesReceivedAfterTeleport));
         }
     }
+
+    gPipeline.setAdjustmentTimerExpiry(gSavedSettings.getF32("InitialAdjustmentTimeout"));
 }
 
 void LLAgent::handleTeleportFailed()
@@ -4109,6 +4111,8 @@ void LLAgent::handleTeleportFailed()
 	}
 
     mTPNeedsNeabyChatSeparator = false;
+
+    gPipeline.setAdjustmentTimerExpiry(gSavedSettings.getF32("InitialAdjustmentTimeout"));
 }
 
 /*static*/
diff --git a/indra/newview/llfloaterperformance.cpp b/indra/newview/llfloaterperformance.cpp
index e53154dd75a52d6785f37153938a86596caeac6b..e44c161b276131cec7a7064b045e83f3e601b88f 100644
--- a/indra/newview/llfloaterperformance.cpp
+++ b/indra/newview/llfloaterperformance.cpp
@@ -36,13 +36,15 @@
 #include "llfloaterpreference.h" // LLAvatarComplexityControls
 #include "llfloaterreg.h"
 #include "llnamelistctrl.h"
+#include "llnotificationsutil.h"
 #include "llradiogroup.h"
 #include "llsliderctrl.h"
 #include "lltextbox.h"
 #include "lltrans.h"
 #include "llviewerobjectlist.h"
 #include "llvoavatar.h"
-#include "llvoavatarself.h" 
+#include "llvoavatarself.h"
+#include "llworld.h"
 #include "pipeline.h"
 
 const F32 REFRESH_INTERVAL = 1.0f;
@@ -77,6 +79,8 @@ LLFloaterPerformance::LLFloaterPerformance(const LLSD& key)
     mNearbyMaxComplexity(0)
 {
     mContextMenu = new LLExceptionsContextMenu(this);
+
+    mCommitCallbackRegistrar.add("Pref.MouseDown", boost::bind(&LLFloaterPerformance::onUICtrlMouseDown, this));
 }
 
 LLFloaterPerformance::~LLFloaterPerformance()
@@ -328,7 +332,7 @@ void LLFloaterPerformance::populateNearbyList()
 
     static LLCachedControl<U32> max_render_cost(gSavedSettings, "RenderAvatarMaxComplexity", 0);
     std::vector<LLCharacter*> valid_nearby_avs;
-    getNearbyAvatars(valid_nearby_avs);
+    mNearbyMaxComplexity = LLWorld::getInstance()->getNearbyAvatarsAndCompl(valid_nearby_avs);
 
     std::vector<LLCharacter*>::iterator char_iter = valid_nearby_avs.begin();
     while (char_iter != valid_nearby_avs.end())
@@ -401,31 +405,6 @@ void LLFloaterPerformance::populateNearbyList()
     mNearbyList->selectByID(prev_selected_id);
 }
 
-void LLFloaterPerformance::getNearbyAvatars(std::vector<LLCharacter*> &valid_nearby_avs)
-{
-    static LLCachedControl<F32> render_far_clip(gSavedSettings, "RenderFarClip", 64);
-    mNearbyMaxComplexity = 0;
-    F32 radius = render_far_clip * render_far_clip;
-    std::vector<LLCharacter*>::iterator char_iter = LLCharacter::sInstances.begin();
-    while (char_iter != LLCharacter::sInstances.end())
-    {
-        LLVOAvatar* avatar = dynamic_cast<LLVOAvatar*>(*char_iter);
-        if (avatar && !avatar->isDead() && !avatar->isControlAvatar())
-        {
-            if ((dist_vec_squared(avatar->getPositionGlobal(), gAgent.getPositionGlobal()) > radius) &&
-                (dist_vec_squared(avatar->getPositionGlobal(), gAgentCamera.getCameraPositionGlobal()) > radius))
-            {
-                char_iter++;
-                continue;
-            }
-            avatar->calculateUpdateRenderComplexity();
-            mNearbyMaxComplexity = llmax(mNearbyMaxComplexity, (S32)avatar->getVisualComplexity());
-            valid_nearby_avs.push_back(*char_iter);
-        }
-        char_iter++;
-    }
-}
-
 void LLFloaterPerformance::detachItem(const LLUUID& item_id)
 {
     LLAppearanceMgr::instance().removeItemFromAvatar(item_id);
@@ -561,4 +540,21 @@ void LLFloaterPerformance::onAvatarListRightClick(LLUICtrl* ctrl, S32 x, S32 y)
     }
 }
 
+void LLFloaterPerformance::onUICtrlMouseDown()
+{
+    static LLCachedControl<bool> use_auto_adjust(gSavedSettings,"AutoFPS");
+    if (use_auto_adjust)
+    {
+        LLNotificationsUtil::add("AutoFPSConfirmDisable", LLSD(), LLSD(),
+            [this](const LLSD&notif, const LLSD&resp)
+        {
+            S32 opt = LLNotificationsUtil::getSelectedOption(notif, resp);
+            if (opt == 0)
+            {
+                gSavedSettings.setBOOL("AutoFPS", FALSE);
+            }
+        });
+    }
+}
+
 // EOF
diff --git a/indra/newview/llfloaterperformance.h b/indra/newview/llfloaterperformance.h
index a5549685f6efd5c389f1d3e1d916295940964fd6..7a1394c51be09172c7986b9348dc850141f2f61a 100644
--- a/indra/newview/llfloaterperformance.h
+++ b/indra/newview/llfloaterperformance.h
@@ -63,11 +63,11 @@ class LLFloaterPerformance : public LLFloater
     void onClickHideAvatars();
     void onClickExceptions();
 
+    void onUICtrlMouseDown();
+
     void updateMaxComplexity();
     void updateComplexityText();
 
-    void getNearbyAvatars(std::vector<LLCharacter*> &valid_nearby_avs);
-
     LLPanel* mMainPanel;
     LLPanel* mNearbyPanel;
     LLPanel* mComplexityPanel;
diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp
index 8ea5519929d66fb79f947e98eeb97670e9287a04..fbc3275b1e443655a3bc10474cd36b450800a297 100644
--- a/indra/newview/llfloaterpreference.cpp
+++ b/indra/newview/llfloaterpreference.cpp
@@ -304,6 +304,7 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key)
 	mCommitCallbackRegistrar.add("Pref.RememberedUsernames",    boost::bind(&LLFloaterPreference::onClickRememberedUsernames, this));
 	mCommitCallbackRegistrar.add("Pref.SpellChecker",           boost::bind(&LLFloaterPreference::onClickSpellChecker, this));
 	mCommitCallbackRegistrar.add("Pref.Advanced",				boost::bind(&LLFloaterPreference::onClickAdvanced, this));
+    mCommitCallbackRegistrar.add("Pref.MouseDown",				boost::bind(&LLFloaterPreference::onUICtrlMouseDown, this));
 
 	sSkin = gSavedSettings.getString("SkinCurrent");
 
@@ -1782,6 +1783,23 @@ void LLFloaterPreference::updateSearchableItems()
     mSearchDataDirty = true;
 }
 
+void LLFloaterPreference::onUICtrlMouseDown()
+{
+    static LLCachedControl<bool> use_auto_adjust(gSavedSettings,"AutoFPS");
+    if (use_auto_adjust)
+    {
+        LLNotificationsUtil::add("AutoFPSConfirmDisable", LLSD(), LLSD(),
+            [this](const LLSD&notif, const LLSD&resp)
+        {
+            S32 opt = LLNotificationsUtil::getSelectedOption(notif, resp);
+            if (opt == 0)
+            {
+                gSavedSettings.setBOOL("AutoFPS", FALSE);
+            }
+        });
+    }
+}
+
 void LLFloaterPreference::applyUIColor(LLUICtrl* ctrl, const LLSD& param)
 {
 	LLUIColorTable::instance().setColor(param.asString(), LLColor4(ctrl->getValue()));
diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h
index 788db960f06b40ef5b3d3e2d6c580c66d9bd2161..8a68f9f279e2985743902a0976a88eb7cd9054ae 100644
--- a/indra/newview/llfloaterpreference.h
+++ b/indra/newview/llfloaterpreference.h
@@ -110,6 +110,8 @@ class LLFloaterPreference : public LLFloater, public LLAvatarPropertiesObserver,
 	void updateClickActionViews();
     void updateSearchableItems();
 
+    void onUICtrlMouseDown();
+
     void		onBtnOK(const LLSD& userdata);
     void		onBtnCancel(const LLSD& userdata);
 
diff --git a/indra/newview/llfloaterpreferencesgraphicsadvanced.cpp b/indra/newview/llfloaterpreferencesgraphicsadvanced.cpp
index af5296117b6fe826f56e5e9e890f2b8652c46e4f..fdc36077a81eb0c94aba5e17353dcd614d77281b 100644
--- a/indra/newview/llfloaterpreferencesgraphicsadvanced.cpp
+++ b/indra/newview/llfloaterpreferencesgraphicsadvanced.cpp
@@ -32,6 +32,7 @@
 #include "llfeaturemanager.h"
 #include "llfloaterpreference.h"
 #include "llfloaterreg.h"
+#include "llnotificationsutil.h"
 #include "llsliderctrl.h"
 #include "lltextbox.h"
 #include "lltrans.h"
@@ -48,8 +49,12 @@ LLFloaterPreferenceGraphicsAdvanced::LLFloaterPreferenceGraphicsAdvanced(const L
     mCommitCallbackRegistrar.add("Pref.UpdateIndirectMaxNonImpostors", boost::bind(&LLFloaterPreferenceGraphicsAdvanced::updateMaxNonImpostors,this));
     mCommitCallbackRegistrar.add("Pref.UpdateIndirectMaxComplexity",   boost::bind(&LLFloaterPreferenceGraphicsAdvanced::updateMaxComplexity,this));
 
+    mCommitCallbackRegistrar.add("Pref.MouseDown", boost::bind(&LLFloaterPreferenceGraphicsAdvanced::onUICtrlMouseDown, this));
+
     mCommitCallbackRegistrar.add("Pref.Cancel", boost::bind(&LLFloaterPreferenceGraphicsAdvanced::onBtnCancel, this, _2));
     mCommitCallbackRegistrar.add("Pref.OK",     boost::bind(&LLFloaterPreferenceGraphicsAdvanced::onBtnOK, this, _2));
+
+    gSavedSettings.getControl("RenderAvatarMaxNonImpostors")->getSignal()->connect(boost::bind(&LLFloaterPreferenceGraphicsAdvanced::updateIndirectMaxNonImpostors, this, _2));
 }
 
 LLFloaterPreferenceGraphicsAdvanced::~LLFloaterPreferenceGraphicsAdvanced()
@@ -190,6 +195,23 @@ void LLFloaterPreferenceGraphicsAdvanced::updateSliderText(LLSliderCtrl* ctrl, L
     }
 }
 
+void LLFloaterPreferenceGraphicsAdvanced::onUICtrlMouseDown()
+{
+    static LLCachedControl<bool> use_auto_adjust(gSavedSettings,"AutoFPS");
+    if (use_auto_adjust)
+    {
+        LLNotificationsUtil::add("AutoFPSConfirmDisable", LLSD(), LLSD(),
+            [this](const LLSD&notif, const LLSD&resp)
+        {
+            S32 opt = LLNotificationsUtil::getSelectedOption(notif, resp);
+            if (opt == 0)
+            {
+                gSavedSettings.setBOOL("AutoFPS", FALSE);
+            }
+        });
+    }
+}
+
 void LLFloaterPreferenceGraphicsAdvanced::updateMaxNonImpostors()
 {
     // Called when the IndirectMaxNonImpostors control changes
@@ -206,6 +228,16 @@ void LLFloaterPreferenceGraphicsAdvanced::updateMaxNonImpostors()
     setMaxNonImpostorsText(value, getChild<LLTextBox>("IndirectMaxNonImpostorsText"));
 }
 
+void LLFloaterPreferenceGraphicsAdvanced::updateIndirectMaxNonImpostors(const LLSD& newvalue)
+{
+    U32 value = newvalue.asInteger();
+    if ((value != 0) && (value != gSavedSettings.getU32("IndirectMaxNonImpostors")))
+    {
+        gSavedSettings.setU32("IndirectMaxNonImpostors", value);
+        setMaxNonImpostorsText(value, getChild<LLTextBox>("IndirectMaxNonImpostorsText"));
+    }
+}
+
 void LLFloaterPreferenceGraphicsAdvanced::setMaxNonImpostorsText(U32 value, LLTextBox* text_box)
 {
     if (0 == value)
@@ -340,9 +372,6 @@ void LLFloaterPreferenceGraphicsAdvanced::refreshEnabledState()
     ctrl_reflections->setEnabled(reflections);
     reflections_text->setEnabled(reflections);
 
-    // Transparent Water
-    LLCheckBoxCtrl* transparent_water_ctrl = getChild<LLCheckBoxCtrl>("TransparentWater");
-
     // Bump & Shiny	
     LLCheckBoxCtrl* bumpshiny_ctrl = getChild<LLCheckBoxCtrl>("BumpShiny");
     bool bumpshiny = gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps && LLFeatureManager::getInstance()->isFeatureAvailable("RenderObjectBump");
@@ -393,9 +422,7 @@ void LLFloaterPreferenceGraphicsAdvanced::refreshEnabledState()
 
     BOOL enabled = LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred") &&
         ((bumpshiny_ctrl && bumpshiny_ctrl->get()) ? TRUE : FALSE) &&
-        ((transparent_water_ctrl && transparent_water_ctrl->get()) ? TRUE : FALSE) &&
         gGLManager.mHasFramebufferObject &&
-        gSavedSettings.getBOOL("RenderAvatarVP") &&
         (ctrl_wind_light->get()) ? TRUE : FALSE;
 
     ctrl_deferred->setEnabled(enabled);
diff --git a/indra/newview/llfloaterpreferencesgraphicsadvanced.h b/indra/newview/llfloaterpreferencesgraphicsadvanced.h
index c5d21ba35b93a2aa4e20a021221b8ce37a7476e5..cf3ed02614aff2f2e2f900b665308e91106a6cf3 100644
--- a/indra/newview/llfloaterpreferencesgraphicsadvanced.h
+++ b/indra/newview/llfloaterpreferencesgraphicsadvanced.h
@@ -45,6 +45,8 @@ class LLFloaterPreferenceGraphicsAdvanced : public LLFloater
     void refreshEnabledState();
     void updateSliderText(LLSliderCtrl* ctrl, LLTextBox* text_box);
     void updateMaxNonImpostors();
+    void updateIndirectMaxNonImpostors(const LLSD& newvalue);
+    void onUICtrlMouseDown();
     void setMaxNonImpostorsText(U32 value, LLTextBox* text_box);
     void updateMaxComplexity();
     void updateComplexityText();
diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp
index b5d3dc5d30a66f01dd98efcde62281258ce3c5ed..a26331251ced5089113890803e43849760783606 100644
--- a/indra/newview/llviewerdisplay.cpp
+++ b/indra/newview/llviewerdisplay.cpp
@@ -1024,6 +1024,8 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
 		gPipeline.clearReferences();
 
 		gPipeline.rebuildGroups();
+
+        gPipeline.autoAdjustSettings();
 	}
 
 	LLAppViewer::instance()->pingMainloopTimeout("Display:FrameStats");
diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp
index 6746a3a902c6f396af04b1109965cf71b335a501..0a2ad8235404a20981c4540060fc2546e12c265e 100644
--- a/indra/newview/llworld.cpp
+++ b/indra/newview/llworld.cpp
@@ -33,6 +33,7 @@
 #include "llstl.h"
 
 #include "llagent.h"
+#include "llagentcamera.h"
 #include "llviewercontrol.h"
 #include "lldrawpool.h"
 #include "llglheaders.h"
@@ -1396,6 +1397,32 @@ void LLWorld::getAvatars(uuid_vec_t* avatar_ids, std::vector<LLVector3d>* positi
 	}
 }
 
+S32 LLWorld::getNearbyAvatarsAndCompl(std::vector<LLCharacter*> &valid_nearby_avs)
+{
+    static LLCachedControl<F32> render_far_clip(gSavedSettings, "RenderFarClip", 64);
+    S32 nearby_max_complexity = 0;
+    F32 radius = render_far_clip * render_far_clip;
+    std::vector<LLCharacter*>::iterator char_iter = LLCharacter::sInstances.begin();
+    while (char_iter != LLCharacter::sInstances.end())
+    {
+        LLVOAvatar* avatar = dynamic_cast<LLVOAvatar*>(*char_iter);
+        if (avatar && !avatar->isDead() && !avatar->isControlAvatar())
+        {
+            if ((dist_vec_squared(avatar->getPositionGlobal(), gAgent.getPositionGlobal()) > radius) &&
+                (dist_vec_squared(avatar->getPositionGlobal(), gAgentCamera.getCameraPositionGlobal()) > radius))
+            {
+                char_iter++;
+                continue;
+            }
+            avatar->calculateUpdateRenderComplexity();
+            nearby_max_complexity = llmax(nearby_max_complexity, (S32)avatar->getVisualComplexity());
+            valid_nearby_avs.push_back(*char_iter);
+        }
+        char_iter++;
+    }
+    return nearby_max_complexity;
+}
+
 bool LLWorld::isRegionListed(const LLViewerRegion* region) const
 {
 	region_list_t::const_iterator it = find(mRegionList.begin(), mRegionList.end(), region);
diff --git a/indra/newview/llworld.h b/indra/newview/llworld.h
index 69f2df42032313e4471ad0cd99fe6a1f83fa2bcf..1c12ad0e2c666035676e1235c10fc81ac71ace28 100644
--- a/indra/newview/llworld.h
+++ b/indra/newview/llworld.h
@@ -51,6 +51,7 @@ class LLHost;
 class LLViewerObject;
 class LLSurfacePatch;
 
+class LLCharacter;
 class LLCloudPuff;
 class LLCloudGroup;
 class LLVOAvatar;
@@ -172,6 +173,8 @@ class LLWorld : public LLSimpleton<LLWorld>
 	// or if the circuit to this simulator had been lost.
 	bool isRegionListed(const LLViewerRegion* region) const;
 
+    S32 getNearbyAvatarsAndCompl(std::vector<LLCharacter*> &valid_nearby_avs);
+
 private:
 	region_list_t	mActiveRegionList;
 	region_list_t	mRegionList;
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index dd9999d73a8063adcaf5bd5809b7a6bb3427f24b..96dd0b895dfb0def44338c99b2422b6d05eeb7d8 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -43,6 +43,7 @@
 #include "llui.h" 
 #include "llglheaders.h"
 #include "llrender.h"
+#include "llstartup.h"
 #include "llwindow.h"	// swapBuffers()
 
 // newview includes
@@ -405,7 +406,8 @@ LLPipeline::LLPipeline() :
 	mLightMovingMask(0),
 	mLightingDetail(0),
 	mScreenWidth(0),
-	mScreenHeight(0)
+	mScreenHeight(0),
+    mUpdateTimer(new LLTimer())
 {
 	mNoiseMap = 0;
 	mTrueNoiseMap = 0;
@@ -613,7 +615,7 @@ void LLPipeline::init()
 
 LLPipeline::~LLPipeline()
 {
-
+    delete mUpdateTimer;
 }
 
 void LLPipeline::cleanup()
@@ -11428,3 +11430,117 @@ void LLPipeline::restoreHiddenObject( const LLUUID& id )
 	}
 }
 
+const F32 MIN_DRAW_DISTANCE = 64;
+const F32 MAX_DRAW_DISTANCE = 256;
+
+void update_far_clip(F32 fps_dif)
+{
+    F32 DIST_PER_FRAME_DIF = 16;
+
+    F32 new_far_clip = llclamp(LLPipeline::RenderFarClip - llmin(fps_dif * DIST_PER_FRAME_DIF, (F32)128), MIN_DRAW_DISTANCE, MAX_DRAW_DISTANCE);
+    gSavedSettings.setF32("RenderFarClip", new_far_clip);
+}
+
+void update_max_non_impostors(F32 fps_dif, S32 max_avatars)
+{
+    const F32 IMPOSTORS_PER_FRAME_DIF = 0.5;
+
+    U32 new_non_imp = (U32)llclamp((S32)(LLVOAvatar::sMaxNonImpostors - llmin((S32)(fps_dif / IMPOSTORS_PER_FRAME_DIF), 10)), 1, max_avatars);
+    gSavedSettings.setU32("RenderAvatarMaxNonImpostors", new_non_imp);
+}
+
+void LLPipeline::autoAdjustSettings()
+{
+    static LLCachedControl<bool> use_auto_adjustment(gSavedSettings,"AutoFPS");
+    if (!use_auto_adjustment)
+    {
+        return;
+    }
+    
+    if (LLStartUp::getStartupState() < STATE_STARTED || LLApp::isExiting())
+    {
+        return;
+    }
+
+    static LLCachedControl<F32> adjustment_timeout(gSavedSettings, "AutoAdjustmentTimeout");
+    static LLCachedControl<F32> initial_adjustment_timeout(gSavedSettings, "InitialAdjustmentTimeout");
+ 
+    static LLCachedControl<S32> fps_lower_boundary(gSavedSettings, "AutoFPSLowerBoundary");
+    static LLCachedControl<S32> fps_upper_boundary(gSavedSettings, "AutoFPSUpperBoundary");
+
+    if (gViewerWindow && gViewerWindow->getWindow()->getVisible()
+        && gFocusMgr.getAppHasFocus() && !gTeleportDisplay)
+    {
+        static bool is_init = false;
+        if (!is_init)
+        {
+            //wait for FPS to stabilize after login in-world
+            mUpdateTimer->setTimerExpirySec((F32)initial_adjustment_timeout);
+            is_init = true;
+        }
+        if (mUpdateTimer->hasExpired())
+        {
+            mUpdateTimer->setTimerExpirySec((F32)adjustment_timeout);
+
+            const S32 FPS_STAT_PERIODS = 50;
+            S32 fps = (S32)llround(LLTrace::get_frame_recording().getPeriodMedianPerSec(LLStatViewer::FPS, FPS_STAT_PERIODS));
+            if (fps < fps_lower_boundary)
+            {
+                S32 fps_dif = fps_lower_boundary - fps;
+                
+                if (LLPipeline::sRenderDeferred && RenderShadowDetail > 0)
+                {
+                    S32 shadow_detail = RenderShadowDetail - 1;
+                    gSavedSettings.setS32("RenderShadowDetail", shadow_detail);
+                    return;
+                }
+                
+                if (RenderFarClip > MIN_DRAW_DISTANCE)
+                {
+                    update_far_clip(fps_dif);
+                }
+
+                std::vector<LLCharacter*> valid_nearby_avs;
+                LLWorld::getInstance()->getNearbyAvatarsAndCompl(valid_nearby_avs);
+
+                if (valid_nearby_avs.size() > 1 && LLVOAvatar::sMaxNonImpostors > 1) 
+                {
+                    update_max_non_impostors(fps_dif, valid_nearby_avs.size());
+                }
+            }
+            else if (fps > fps_upper_boundary)
+            {
+                S32 fps_dif = fps_upper_boundary - fps;
+
+                std::vector<LLCharacter*> valid_nearby_avs;
+                LLWorld::getInstance()->getNearbyAvatarsAndCompl(valid_nearby_avs);
+                if (valid_nearby_avs.size() > 1 && (LLVOAvatar::sMaxNonImpostors < valid_nearby_avs.size()))
+                {
+                    update_max_non_impostors(fps_dif, valid_nearby_avs.size());
+                    return;
+                }
+                
+                if (RenderFarClip < MAX_DRAW_DISTANCE)
+                {
+                    update_far_clip(fps_dif);
+                }
+
+                if (LLPipeline::sRenderDeferred && RenderShadowDetail < 2)
+                {
+                    S32 shadow_detail = RenderShadowDetail + 1;
+                    gSavedSettings.setS32("RenderShadowDetail", shadow_detail);
+                }
+            }
+        }
+    }
+    else
+    {
+        //wait for FPS to stabilize if the window was minimized or not focused before
+        mUpdateTimer->setTimerExpirySec((F32)initial_adjustment_timeout);
+    }
+}
+
+void LLPipeline::setAdjustmentTimerExpiry(F32 expiration)
+{
+    mUpdateTimer->setTimerExpirySec(expiration);
+}
diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h
index fdc3738472fd02d8c968ac9d451103dfa0c1eb16..7eff573a34d6b664d05b9d174a3a2d4b6b47853c 100644
--- a/indra/newview/pipeline.h
+++ b/indra/newview/pipeline.h
@@ -424,6 +424,9 @@ class LLPipeline
 	void hideObject( const LLUUID& id );
 	void restoreHiddenObject( const LLUUID& id );
 
+    void autoAdjustSettings();
+    void setAdjustmentTimerExpiry(F32 expiration);
+
 private:
 	void unloadShaders();
 	void addToQuickLookup( LLDrawPool* new_poolp );
@@ -715,7 +718,8 @@ class LLPipeline
 	U64						mOldRenderDebugMask;
 	std::stack<U32>			mRenderDebugFeatureStack;
 
-	
+    LLTimer* mUpdateTimer;
+
 	/////////////////////////////////////////////
 	//
 	//
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 d1e167df64435c6e87d0aedf1b80390cad139852..5978ae685a157b7a24bfa367fdb67a344869f2e8 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
@@ -39,7 +39,10 @@
     max_val="512"
     name="DrawDistance"
     top_delta="16"
-    width="330" />
+    width="330">
+    <slider.mouse_down_callback
+      function="Pref.MouseDown" />
+    </slider>
   <text
     type="string"
     length="1"
@@ -182,6 +185,8 @@
     <slider.commit_callback
       function="Pref.UpdateIndirectMaxNonImpostors"
       parameter="IndirectNonImpostorsText" />
+    <slider.mouse_down_callback
+      function="Pref.MouseDown" />
   </slider>
   <text
     type="string"
@@ -850,6 +855,8 @@
    top_delta="0" 
    name="ShadowDetail"
    width="150">
+    <combo_box.mouse_down_callback
+ function="Pref.MouseDown" />
      <combo_box.item
        label="None"
        name="0"
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index d4f71fb370c2f473bf967cc89b8e4db2065d960f..2fed214d698e29d25891c4682534498384778b33 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -1847,6 +1847,19 @@ Graphics Quality can be raised in Preferences &gt; Graphics.
   <tag>fail</tag>
   </notification>
 
+  <notification
+ icon="alertmodal.tga"
+ name="AutoFPSConfirmDisable"
+ type="alertmodal">
+    Changing this setting will disable automatic adjustment and turn off 'Auto FPS' setting.
+Are you sure you want to continue?
+    <tag>confirm</tag>
+    <usetemplate
+     name="okcancelbuttons"
+     notext="Cancel"
+     yestext="Continue"/>
+  </notification>
+
   <notification
    icon="alertmodal.tga"
    name="RegionNoTerraforming"
diff --git a/indra/newview/skins/default/xui/en/panel_performance_preferences.xml b/indra/newview/skins/default/xui/en/panel_performance_preferences.xml
index 221dfa02229cea0ce92fd2da426140da7dd2bba2..60792c2f7dcbd0fcaab2decb15df563c77a83756 100644
--- a/indra/newview/skins/default/xui/en/panel_performance_preferences.xml
+++ b/indra/newview/skins/default/xui/en/panel_performance_preferences.xml
@@ -206,7 +206,10 @@
     max_val="512"
     name="draw_distance"
     left_pad="5"
-    width="250" />
+    width="250">
+    <slider.mouse_down_callback
+      function="Pref.MouseDown" />
+  </slider>
   <text
     type="string"
     length="1"
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml b/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml
index 5aff7a512768ab1d69fdf897df8f5c6958598d0b..6e4a1a68590ae671f93962cc8bb50251f827ab82 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml
@@ -217,7 +217,10 @@
     max_val="512"
     name="DrawDistance"
     top_delta="40"
-    width="330" />
+    width="330">
+    <slider.mouse_down_callback
+      function="Pref.MouseDown" />
+  </slider>
   <text
     type="string"
     length="1"
@@ -258,6 +261,18 @@
     <check_box.commit_callback
       function="Pref.RenderOptionUpdate" />
   </check_box>
+
+  <check_box
+    control_name="AutoFPS"
+    height="16"
+    initial_value="true"
+    label="Auto FPS"
+    layout="topleft"
+    left="30"
+    name="AutoFPS"
+    top_delta="30"
+    width="256">
+  </check_box>
   
   <slider
     control_name="IndirectMaxComplexity"
@@ -274,7 +289,7 @@
     max_val="101"
     name="IndirectMaxComplexity"
     show_text="false"
-    top_delta="60"
+    top_delta="34"
     width="300">
     <slider.commit_callback
       function="Pref.UpdateIndirectMaxComplexity"