Files
SingularityViewer/indra/newview/llpaneldisplay.cpp

1158 lines
38 KiB
C++

/**
* @file llpaneldisplay.cpp
* @brief Display preferences for the preferences floater
*
* $LicenseInfo:firstyear=2001&license=viewergpl$
*
* Copyright (c) 2001-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "llviewerprecompiledheaders.h"
// file include
#include "llpaneldisplay.h"
// linden library includes
#include "llerror.h"
#include "llfontgl.h"
#include "llrect.h"
#include "llstring.h"
// project includes
#include "llagent.h"
#include "llbutton.h"
#include "llcheckboxctrl.h"
#include "llcombobox.h"
#include "llflexibleobject.h"
#include "lllineeditor.h"
#include "llradiogroup.h"
#include "llresmgr.h"
#include "llsliderctrl.h"
#include "llspinctrl.h"
#include "llstartup.h"
#include "lltextbox.h"
#include "lltexteditor.h"
#include "llui.h"
#include "llviewercamera.h"
#include "llviewertexturelist.h"
#include "llviewermessage.h"
#include "llviewerobjectlist.h"
#include "llviewerwindow.h"
#include "llvoavatar.h"
#include "llvovolume.h"
#include "llvotree.h"
#include "llvosky.h"
#include "llwindow.h"
#include "llworld.h"
#include "pipeline.h"
#include "lluictrlfactory.h"
#include "llfeaturemanager.h"
#include "llviewershadermgr.h"
#include "llboost.h"
//RN temporary includes for resolution switching
#include "llglheaders.h"
#include "llviewercontrol.h"
#include "llsky.h"
// parent
#include "llfloaterpreference.h"
// [RLVa:KB]
#include "rlvhandler.h"
// [/RLVa:KB]
#if LL_MSVC
#pragma warning( disable : 4265 ) // "class has virtual functions, but destructor is not virtual"
#endif
#include <boost/regex.hpp>
const F32 MAX_USER_FAR_CLIP = 512.f;
const F32 MIN_USER_FAR_CLIP = 64.f;
const S32 ASPECT_RATIO_STR_LEN = 100;
LLPanelDisplay::LLPanelDisplay()
{
LLUICtrlFactory::getInstance()->buildPanel(this, "panel_preferences_graphics1.xml");
}
BOOL LLPanelDisplay::postBuild()
{
// return to default values
getChild<LLButton>("Defaults")->setClickedCallback(boost::bind(&LLPanelDisplay::setHardwareDefaults));
//============================================================================
// Resolution
// radio set for fullscreen size
mCtrlWindowed = getChild<LLCheckBoxCtrl>( "windowed mode");
mCtrlWindowed->setCommitCallback(boost::bind(&LLPanelDisplay::onCommitWindowedMode,this));
mAspectRatioLabel1 = getChild<LLTextBox>("AspectRatioLabel1");
mDisplayResLabel = getChild<LLTextBox>("DisplayResLabel");
S32 num_resolutions = 0;
LLWindow::LLWindowResolution* supported_resolutions = gViewerWindow->getWindow()->getSupportedResolutions(num_resolutions);
S32 fullscreen_mode = num_resolutions - 1;
mCtrlFullScreen = getChild<LLComboBox>( "fullscreen combo");
LLUIString resolution_label = getString("resolution_format");
for (S32 i = 0; i < num_resolutions; i++)
{
resolution_label.setArg("[RES_X]", llformat("%d", supported_resolutions[i].mWidth));
resolution_label.setArg("[RES_Y]", llformat("%d", supported_resolutions[i].mHeight));
mCtrlFullScreen->add( resolution_label, ADD_BOTTOM );
}
{
BOOL targetFullscreen;
S32 targetWidth;
S32 targetHeight;
gViewerWindow->getTargetWindow(targetFullscreen, targetWidth, targetHeight);
if (targetFullscreen)
{
fullscreen_mode = 0; // default to 800x600
for (S32 i = 0; i < num_resolutions; i++)
{
if (targetWidth == supported_resolutions[i].mWidth
&& targetHeight == supported_resolutions[i].mHeight)
{
fullscreen_mode = i;
}
}
mCtrlFullScreen->setCurrentByIndex(fullscreen_mode);
mCtrlWindowed->set(FALSE);
mCtrlFullScreen->setVisible(TRUE);
}
else
{
// set to windowed mode
//fullscreen_mode = mCtrlFullScreen->getItemCount() - 1;
mCtrlWindowed->set(TRUE);
mCtrlFullScreen->setCurrentByIndex(0);
mCtrlFullScreen->setVisible(FALSE);
}
}
initWindowSizeControls();
if (gSavedSettings.getBOOL("FullScreenAutoDetectAspectRatio"))
{
mAspectRatio = gViewerWindow->getDisplayAspectRatio();
}
else
{
mAspectRatio = gSavedSettings.getF32("FullScreenAspectRatio");
}
S32 numerator = 0;
S32 denominator = 0;
fractionFromDecimal(mAspectRatio, numerator, denominator);
LLUIString aspect_ratio_text = getString("aspect_ratio_text");
if (numerator != 0)
{
aspect_ratio_text.setArg("[NUM]", llformat("%d", numerator));
aspect_ratio_text.setArg("[DEN]", llformat("%d", denominator));
}
else
{
aspect_ratio_text = llformat("%.3f", mAspectRatio);
}
mCtrlAspectRatio = getChild<LLComboBox>( "aspect_ratio");
mCtrlAspectRatio->setTextEntryCallback(boost::bind(&LLPanelDisplay::onKeystrokeAspectRatio,this));
mCtrlAspectRatio->setCommitCallback(boost::bind(&LLPanelDisplay::onSelectAspectRatio,this));
// add default aspect ratios
mCtrlAspectRatio->add(aspect_ratio_text, &mAspectRatio, ADD_TOP);
mCtrlAspectRatio->setCurrentByIndex(0);
mCtrlAutoDetectAspect = getChild<LLCheckBoxCtrl>( "aspect_auto_detect");
mCtrlAutoDetectAspect->setCommitCallback(boost::bind(&LLPanelDisplay::onCommitAutoDetectAspect,this,_2));
// radio performance box
mCtrlSliderQuality = getChild<LLSliderCtrl>("QualityPerformanceSelection");
mCtrlSliderQuality->setSliderMouseUpCallback(boost::bind(&LLPanelDisplay::onChangeQuality,this,_1));
mCtrlCustomSettings = getChild<LLCheckBoxCtrl>("CustomSettings");
mCtrlCustomSettings->setCommitCallback(boost::bind(&LLPanelDisplay::onChangeCustom));
//mGraphicsBorder = getChild<LLViewBorder>("GraphicsBorder");
// Enable Transparent Water
mCtrlTransparentWater = getChild<LLCheckBoxCtrl>("TransparentWater");
//----------------------------------------------------------------------------
// Enable Bump/Shiny
mCtrlBumpShiny = getChild<LLCheckBoxCtrl>("BumpShiny");
//----------------------------------------------------------------------------
// Enable Reflections
mCtrlReflectionDetail = getChild<LLComboBox>("ReflectionDetailCombo");
mCtrlReflectionDetail->setCommitCallback(boost::bind(&LLPanelDisplay::onVertexShaderEnable));
// WindLight
mCtrlWindLight = getChild<LLCheckBoxCtrl>("WindLightUseAtmosShaders");
mCtrlWindLight->setCommitCallback(boost::bind(&LLPanelDisplay::onVertexShaderEnable));
// Deferred
mCtrlDeferred = getChild<LLCheckBoxCtrl>("RenderDeferred");
mCtrlDeferred->setCommitCallback(boost::bind(&LLPanelDisplay::onVertexShaderEnable));
mCtrlDeferredDoF = getChild<LLCheckBoxCtrl>("RenderDepthOfField");
mCtrlDeferredDoF->setCommitCallback(boost::bind(&LLPanelDisplay::onVertexShaderEnable));
mCtrlShadowDetail = getChild<LLComboBox>("ShadowDetailCombo");
mCtrlShadowDetail->setCommitCallback(boost::bind(&LLPanelDisplay::onVertexShaderEnable));
//----------------------------------------------------------------------------
// Terrain Scale
mCtrlTerrainScale = getChild<LLComboBox>("TerrainScaleCombo");
//----------------------------------------------------------------------------
// Enable Avatar Shaders
mCtrlAvatarVP = getChild<LLCheckBoxCtrl>("AvatarVertexProgram");
mCtrlAvatarVP->setCommitCallback(boost::bind(&LLPanelDisplay::onVertexShaderEnable));
//----------------------------------------------------------------------------
// Avatar Render Mode
mCtrlAvatarCloth = getChild<LLCheckBoxCtrl>("AvatarCloth");
mCtrlAvatarImpostors = getChild<LLCheckBoxCtrl>("AvatarImpostors");
mCtrlAvatarImpostors->setCommitCallback(boost::bind(&LLPanelDisplay::onVertexShaderEnable));
mCtrlNonImpostors = getChild<LLSliderCtrl>("AvatarMaxVisible");
//----------------------------------------------------------------------------
// Checkbox for lighting detail
mCtrlLightingDetail2 = getChild<LLCheckBoxCtrl>("LightingDetailRadio");
//----------------------------------------------------------------------------
// Checkbox for ambient occlusion
mCtrlAmbientOcc = getChild<LLCheckBoxCtrl>("UseSSAO");
//----------------------------------------------------------------------------
// radio set for terrain detail mode
mRadioTerrainDetail = getChild<LLRadioGroup>("TerrainDetailRadio");
//----------------------------------------------------------------------------
// Global Shader Enable
mCtrlShaderEnable = getChild<LLCheckBoxCtrl>("BasicShaders");
mCtrlShaderEnable->setCommitCallback(boost::bind(&LLPanelDisplay::onVertexShaderEnable));
//============================================================================
// Object detail slider
mCtrlDrawDistance = getChild<LLSliderCtrl>("DrawDistance");
mDrawDistanceMeterText1 = getChild<LLTextBox>("DrawDistanceMeterText1");
mDrawDistanceMeterText2 = getChild<LLTextBox>("DrawDistanceMeterText2");
mCtrlDrawDistance->setCommitCallback(boost::bind(&LLPanelDisplay::updateMeterText, this));
// Object detail slider
mCtrlLODFactor = getChild<LLSliderCtrl>("ObjectMeshDetail");
mLODFactorText = getChild<LLTextBox>("ObjectMeshDetailText");
mCtrlLODFactor->setCommitCallback(boost::bind(&LLPanelDisplay::updateSliderText, _1,mLODFactorText));
// Flex object detail slider
mCtrlFlexFactor = getChild<LLSliderCtrl>("FlexibleMeshDetail");
mFlexFactorText = getChild<LLTextBox>("FlexibleMeshDetailText");
mCtrlFlexFactor->setCommitCallback(boost::bind(&LLPanelDisplay::updateSliderText,_1, mFlexFactorText));
// Tree detail slider
mCtrlTreeFactor = getChild<LLSliderCtrl>("TreeMeshDetail");
mTreeFactorText = getChild<LLTextBox>("TreeMeshDetailText");
mCtrlTreeFactor->setCommitCallback(boost::bind(&LLPanelDisplay::updateSliderText, _1, mTreeFactorText));
// Avatar detail slider
mCtrlAvatarFactor = getChild<LLSliderCtrl>("AvatarMeshDetail");
mAvatarFactorText = getChild<LLTextBox>("AvatarMeshDetailText");
mCtrlAvatarFactor->setCommitCallback(boost::bind(&LLPanelDisplay::updateSliderText, _1, mAvatarFactorText));
// Avatar physics detail slider
mCtrlAvatarPhysicsFactor = getChild<LLSliderCtrl>("AvatarPhysicsDetail");
mAvatarPhysicsFactorText = getChild<LLTextBox>("AvatarPhysicsDetailText");
mCtrlAvatarPhysicsFactor->setCommitCallback(boost::bind(&LLPanelDisplay::updateSliderText, _1, mAvatarPhysicsFactorText));
// Terrain detail slider
mCtrlTerrainFactor = getChild<LLSliderCtrl>("TerrainMeshDetail");
mTerrainFactorText = getChild<LLTextBox>("TerrainMeshDetailText");
mCtrlTerrainFactor->setCommitCallback(boost::bind(&LLPanelDisplay::updateSliderText, _1, mTerrainFactorText));
// Terrain detail slider
mCtrlSkyFactor = getChild<LLSliderCtrl>("SkyMeshDetail");
mSkyFactorText = getChild<LLTextBox>("SkyMeshDetailText");
mCtrlSkyFactor->setCommitCallback(boost::bind(&LLPanelDisplay::updateSliderText, _1, mSkyFactorText));
// Particle detail slider
mCtrlMaxParticle = getChild<LLSliderCtrl>("MaxParticleCount");
// Glow detail slider
mCtrlPostProcess = getChild<LLSliderCtrl>("RenderPostProcess");
mPostProcessText = getChild<LLTextBox>("PostProcessText");
mCtrlPostProcess->setCommitCallback(boost::bind(&LLPanelDisplay::updateSliderText, _1, mPostProcessText));
// Text boxes (for enabling/disabling)
mShaderText = getChild<LLTextBox>("ShadersText");
mReflectionText = getChild<LLTextBox>("ReflectionDetailText");
mAvatarText = getChild<LLTextBox>("AvatarRenderingText");
mTerrainText = getChild<LLTextBox>("TerrainDetailText");
mMeshDetailText = getChild<LLTextBox>("MeshDetailText");
mShadowDetailText = getChild<LLTextBox>("ShadowDetailText");
mTerrainScaleText = getChild<LLTextBox>("TerrainScaleText");
// Hardware tab
mVBO = getChild<LLCheckBoxCtrl>("vbo");
mVBO->setCommitCallback(boost::bind(&LLPanelDisplay::onVertexShaderEnable));
mVBOStream = getChild<LLCheckBoxCtrl>("vbo_stream");
if(gGLManager.mIsATI) //AMD gpus don't go beyond 8x fsaa.
{
LLComboBox* fsaa = getChild<LLComboBox>("fsaa");
fsaa->remove("16x");
}
if(!gGLManager.mHasAdaptiveVsync)
{
LLComboBox* vsync = getChild<LLComboBox>("vsync");
vsync->remove("VSyncAdaptive");
}
refresh();
return TRUE;
}
void LLPanelDisplay::initWindowSizeControls()
{
// Window size
mWindowSizeLabel = getChild<LLTextBox>("WindowSizeLabel");
mCtrlWindowSize = getChild<LLComboBox>("windowsize combo");
// Look to see if current window size matches existing window sizes, if so then
// just set the selection value...
const U32 height = gViewerWindow->getWindowDisplayHeight();
const U32 width = gViewerWindow->getWindowDisplayWidth();
for (S32 i=0; i < mCtrlWindowSize->getItemCount(); i++)
{
U32 height_test = 0;
U32 width_test = 0;
mCtrlWindowSize->setCurrentByIndex(i);
if (extractWindowSizeFromString(mCtrlWindowSize->getValue().asString(), width_test, height_test))
{
if ((height_test == height) && (width_test == width))
{
return;
}
}
}
// ...otherwise, add a new entry with the current window height/width.
LLUIString resolution_label = getString("resolution_format");
resolution_label.setArg("[RES_X]", llformat("%d", width));
resolution_label.setArg("[RES_Y]", llformat("%d", height));
mCtrlWindowSize->add(resolution_label, ADD_TOP);
mCtrlWindowSize->setCurrentByIndex(0);
}
LLPanelDisplay::~LLPanelDisplay()
{
// clean up user data
for (S32 i = 0; i < mCtrlAspectRatio->getItemCount(); i++)
{
mCtrlAspectRatio->setCurrentByIndex(i);
}
for (S32 i = 0; i < mCtrlWindowSize->getItemCount(); i++)
{
mCtrlWindowSize->setCurrentByIndex(i);
}
}
void LLPanelDisplay::refresh()
{
LLPanel::refresh();
mFSAutoDetectAspect = gSavedSettings.getBOOL("FullScreenAutoDetectAspectRatio");
mQualityPerformance = gSavedSettings.getU32("RenderQualityPerformance");
mCustomSettings = gSavedSettings.getBOOL("RenderCustomSettings");
mTransparentWater = gSavedSettings.getBOOL("RenderTransparentWater");
// shader settings
mBumpShiny = gSavedSettings.getBOOL("RenderObjectBump");
mShaderEnable = gSavedSettings.getBOOL("VertexShaderEnable");
mWindLight = gSavedSettings.getBOOL("WindLightUseAtmosShaders");
mAvatarVP = gSavedSettings.getBOOL("RenderAvatarVP");
mDeferred = gSavedSettings.getBOOL("RenderDeferred");
mDeferredDoF = gSavedSettings.getBOOL("RenderDepthOfField");
// combo boxes
mReflectionDetail = gSavedSettings.getS32("RenderReflectionDetail");
mShadowDetail = gSavedSettings.getS32("RenderShadowDetail");
mTerrainScale = gSavedSettings.getF32("RenderTerrainScale");
// avatar settings
mAvatarImpostors = gSavedSettings.getBOOL("RenderUseImpostors");
mNonImpostors = gSavedSettings.getS32("RenderAvatarMaxVisible");
mAvatarCloth = gSavedSettings.getBOOL("RenderAvatarCloth");
// Draw distance
mRenderFarClip = gSavedSettings.getF32("RenderFarClip");
// sliders and their text boxes
mPrimLOD = gSavedSettings.getF32("RenderVolumeLODFactor");
mFlexLOD = gSavedSettings.getF32("RenderFlexTimeFactor");
mTreeLOD = gSavedSettings.getF32("RenderTreeLODFactor");
mAvatarLOD = gSavedSettings.getF32("RenderAvatarLODFactor");
mTerrainLOD = gSavedSettings.getF32("RenderTerrainLODFactor");
mSkyLOD = gSavedSettings.getU32("WLSkyDetail");
mParticleCount = gSavedSettings.getS32("RenderMaxPartCount");
mPostProcess = gSavedSettings.getS32("RenderGlowResolutionPow");
// lighting and terrain radios
mLocalLights = gSavedSettings.getBOOL("RenderLocalLights");
mTerrainDetail = gSavedSettings.getS32("RenderTerrainDetail");
// slider text boxes
updateSliderText(mCtrlLODFactor, mLODFactorText);
updateSliderText(mCtrlFlexFactor, mFlexFactorText);
updateSliderText(mCtrlTreeFactor, mTreeFactorText);
updateSliderText(mCtrlAvatarFactor, mAvatarFactorText);
updateSliderText(mCtrlAvatarPhysicsFactor, mAvatarPhysicsFactorText);
updateSliderText(mCtrlTerrainFactor, mTerrainFactorText);
updateSliderText(mCtrlPostProcess, mPostProcessText);
updateSliderText(mCtrlSkyFactor, mSkyFactorText);
// Hardware tab
mUseVBO = gSavedSettings.getBOOL("RenderVBOEnable");
mUseFBO = gSavedSettings.getBOOL("RenderUseFBO");
mUseAniso = gSavedSettings.getBOOL("RenderAnisotropic");
mFSAASamples = gSavedSettings.getU32("RenderFSAASamples");
mGamma = gSavedSettings.getF32("RenderGamma");
mVideoCardMem = gSavedSettings.getS32("TextureMemory");
mFogRatio = gSavedSettings.getF32("RenderFogRatio");
mVsyncMode = gSavedSettings.getS32("SHRenderVsyncMode");
childSetValue("fsaa", (LLSD::Integer) mFSAASamples);
childSetValue("vsync", (LLSD::Integer) mVsyncMode);
refreshEnabledState();
}
void LLPanelDisplay::refreshEnabledState()
{
// if in windowed mode, disable full screen options
bool isFullScreen = !mCtrlWindowed->get();
mDisplayResLabel->setVisible(isFullScreen);
mCtrlFullScreen->setVisible(isFullScreen);
mCtrlAspectRatio->setVisible(isFullScreen);
mAspectRatioLabel1->setVisible(isFullScreen);
mCtrlAutoDetectAspect->setVisible(isFullScreen);
mWindowSizeLabel->setVisible(!isFullScreen);
mCtrlWindowSize->setVisible(!isFullScreen);
// disable graphics settings and exit if it's not set to custom
if(!gSavedSettings.getBOOL("RenderCustomSettings"))
{
setHiddenGraphicsState(true);
return;
}
// otherwise turn them all on and selectively turn off others
else
{
setHiddenGraphicsState(false);
}
// Reflections
BOOL reflections = gSavedSettings.getBOOL("VertexShaderEnable")
&& gGLManager.mHasCubeMap
&& LLCubeMap::sUseCubeMaps;
mCtrlReflectionDetail->setEnabled(reflections);
// Bump & Shiny
bool bumpshiny = gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps && LLFeatureManager::getInstance()->isFeatureAvailable("RenderObjectBump");
mCtrlBumpShiny->setEnabled(bumpshiny ? TRUE : FALSE);
if (gSavedSettings.getBOOL("VertexShaderEnable") == FALSE ||
gSavedSettings.getBOOL("RenderAvatarVP") == FALSE)
{
mCtrlAvatarCloth->setEnabled(false);
}
else
{
mCtrlAvatarCloth->setEnabled(true);
}
static LLCachedControl<bool> wlatmos("WindLightUseAtmosShaders",false);
//I actually recommend RenderUseFBO:FALSE for ati users when not using deferred, so RenderUseFBO shouldn't control visibility of the element.
// Instead, gGLManager.mHasFramebufferObject seems better as it is determined by hardware and not current user settings. -Shyotl
//Enabling deferred will force RenderUseFBO to TRUE.
BOOL can_defer = gGLManager.mHasFramebufferObject &&
LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred") && //Ensure it's enabled in the gpu feature table
LLFeatureManager::getInstance()->isFeatureAvailable("RenderAvatarVP") && //Hardware Skinning. Deferred forces RenderAvatarVP to true
LLFeatureManager::getInstance()->isFeatureAvailable("VertexShaderEnable") && gSavedSettings.getBOOL("VertexShaderEnable") && //Basic Shaders
LLFeatureManager::getInstance()->isFeatureAvailable("WindLightUseAtmosShaders") && wlatmos; //Atmospheric Shaders
mCtrlDeferred->setEnabled(can_defer);
static LLCachedControl<bool> render_deferred("RenderDeferred",false);
mCtrlShadowDetail->setEnabled(can_defer && render_deferred);
mCtrlAmbientOcc->setEnabled(can_defer && render_deferred);
mCtrlDeferredDoF->setEnabled(can_defer && render_deferred);
// Disable max non-impostors slider if avatar impostors are off
mCtrlNonImpostors->setEnabled(gSavedSettings.getBOOL("RenderUseImpostors"));
// Vertex Shaders
// mCtrlShaderEnable->setEnabled(LLFeatureManager::getInstance()->isFeatureAvailable("VertexShaderEnable"));
// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | Modified: RLVa-0.2.0a
// "Basic Shaders" can't be disabled - but can be enabled - under @setenv=n
bool fCtrlShaderEnable = LLFeatureManager::getInstance()->isFeatureAvailable("VertexShaderEnable");
mCtrlShaderEnable->setEnabled(fCtrlShaderEnable && (!gRlvHandler.hasBehaviour(RLV_BHVR_SETENV) || !mShaderEnable));
// [/RLVa:KB]
bool shaders = mCtrlShaderEnable->get();
if (shaders)
{
mRadioTerrainDetail->setValue(1);
mRadioTerrainDetail->setEnabled(false);
}
else
{
mRadioTerrainDetail->setEnabled(true);
}
// *HACK just checks to see if we can use shaders...
// maybe some cards that use shaders, but don't support windlight
// mCtrlWindLight->setEnabled(mCtrlShaderEnable->getEnabled() && shaders);
// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | Modified: RLVa-0.2.0a
// "Atmospheric Shaders" can't be disabled - but can be enabled - under @setenv=n
bool fCtrlWindLightEnable = fCtrlShaderEnable && shaders;
mCtrlWindLight->setEnabled(fCtrlWindLightEnable && (!gRlvHandler.hasBehaviour(RLV_BHVR_SETENV) || !mWindLight));
// [/RLVa:KB]
// turn off sky detail if atmospherics isn't on
mCtrlSkyFactor->setEnabled(wlatmos);
mSkyFactorText->setEnabled(wlatmos);
// Avatar Mode and FBO
if (render_deferred && wlatmos && shaders)
{
childSetEnabled("fbo", false);
childSetValue("fbo", true);
mCtrlAvatarVP->setEnabled(false);
gSavedSettings.setBOOL("RenderAvatarVP", true);
}
else if (!shaders)
{
childSetEnabled("fbo", gGLManager.mHasFramebufferObject);
mCtrlAvatarVP->setEnabled(false);
gSavedSettings.setBOOL("RenderAvatarVP", false);
}
else
{
childSetEnabled("fbo", gGLManager.mHasFramebufferObject);
mCtrlAvatarVP->setEnabled(true);
}
// Hardware tab
S32 min_tex_mem = LLViewerTextureList::getMinVideoRamSetting();
S32 max_tex_mem = LLViewerTextureList::getMaxVideoRamSetting();
childSetMinValue("GrapicsCardTextureMemory", min_tex_mem);
childSetMaxValue("GrapicsCardTextureMemory", max_tex_mem);
if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderVBOEnable") ||
!gGLManager.mHasVertexBufferObject)
{
mVBO->setEnabled(false);
//Streaming VBOs -Shyotl
mVBOStream->setEnabled(false);
}
else
{
mVBOStream->setEnabled(gSavedSettings.getBOOL("RenderVBOEnable"));
}
// if no windlight shaders, enable gamma, and fog distance
childSetEnabled("gamma",!wlatmos);
childSetEnabled("fog", !wlatmos);
childSetVisible("note", wlatmos);
// now turn off any features that are unavailable
disableUnavailableSettings();
}
void LLPanelDisplay::disableUnavailableSettings()
{
// if vertex shaders off, disable all shader related products
if(!LLFeatureManager::getInstance()->isFeatureAvailable("VertexShaderEnable"))
{
mCtrlShaderEnable->setEnabled(FALSE);
mCtrlShaderEnable->setValue(FALSE);
mCtrlWindLight->setEnabled(FALSE);
mCtrlWindLight->setValue(FALSE);
mCtrlReflectionDetail->setEnabled(FALSE);
mCtrlReflectionDetail->setValue(FALSE);
mCtrlAvatarVP->setEnabled(FALSE);
mCtrlAvatarVP->setValue(FALSE);
mCtrlAvatarCloth->setEnabled(FALSE);
mCtrlAvatarCloth->setValue(FALSE);
mCtrlDeferred->setEnabled(FALSE);
mCtrlDeferred->setValue(FALSE);
mCtrlAmbientOcc->setEnabled(FALSE);
mCtrlAmbientOcc->setValue(FALSE);
mCtrlDeferredDoF->setEnabled(FALSE);
mCtrlDeferredDoF->setValue(FALSE);
mCtrlShadowDetail->setEnabled(FALSE);
mCtrlShadowDetail->setValue(FALSE);
}
// disabled windlight
if(!LLFeatureManager::getInstance()->isFeatureAvailable("WindLightUseAtmosShaders"))
{
mCtrlWindLight->setEnabled(FALSE);
mCtrlWindLight->setValue(FALSE);
}
// disabled reflections
if(!LLFeatureManager::getInstance()->isFeatureAvailable("RenderReflectionDetail"))
{
mCtrlReflectionDetail->setEnabled(FALSE);
mCtrlReflectionDetail->setValue(FALSE);
}
// disabled terrain scale
if(!LLFeatureManager::getInstance()->isFeatureAvailable("RenderTerrainScale"))
{
mCtrlTerrainScale->setEnabled(false);
mCtrlTerrainScale->setValue(false);
}
// disabled av
if(!LLFeatureManager::getInstance()->isFeatureAvailable("RenderAvatarVP"))
{
mCtrlAvatarVP->setEnabled(FALSE);
mCtrlAvatarVP->setValue(FALSE);
mCtrlAvatarCloth->setEnabled(FALSE);
mCtrlAvatarCloth->setValue(FALSE);
}
// disabled cloth
if(!LLFeatureManager::getInstance()->isFeatureAvailable("RenderAvatarCloth"))
{
mCtrlAvatarCloth->setEnabled(FALSE);
mCtrlAvatarCloth->setValue(FALSE);
}
// disabled impostors
if(!LLFeatureManager::getInstance()->isFeatureAvailable("RenderUseImpostors"))
{
mCtrlAvatarImpostors->setEnabled(FALSE);
mCtrlAvatarImpostors->setValue(FALSE);
mCtrlNonImpostors->setEnabled(FALSE);
}
// disabled deferred
if(!LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred"))
{
mCtrlDeferred->setEnabled(FALSE);
mCtrlDeferred->setValue(FALSE);
mCtrlAmbientOcc->setEnabled(FALSE);
mCtrlAmbientOcc->setValue(FALSE);
mCtrlDeferredDoF->setEnabled(FALSE);
mCtrlDeferredDoF->setValue(FALSE);
mCtrlShadowDetail->setEnabled(FALSE);
mCtrlShadowDetail->setValue(FALSE);
}
}
void LLPanelDisplay::setHiddenGraphicsState(bool isHidden)
{
// quick check
//llassert(mGraphicsBorder != NULL);
llassert(mCtrlDrawDistance != NULL);
llassert(mCtrlLODFactor != NULL);
llassert(mCtrlFlexFactor != NULL);
llassert(mCtrlTreeFactor != NULL);
llassert(mCtrlAvatarFactor != NULL);
llassert(mCtrlTerrainFactor != NULL);
llassert(mCtrlSkyFactor != NULL);
llassert(mCtrlMaxParticle != NULL);
llassert(mCtrlPostProcess != NULL);
llassert(mLODFactorText != NULL);
llassert(mFlexFactorText != NULL);
llassert(mTreeFactorText != NULL);
llassert(mAvatarFactorText != NULL);
llassert(mTerrainFactorText != NULL);
llassert(mSkyFactorText != NULL);
llassert(mPostProcessText != NULL);
llassert(mCtrlTransparentWater != NULL);
llassert(mCtrlBumpShiny != NULL);
llassert(mCtrlWindLight != NULL);
llassert(mCtrlAvatarVP != NULL);
llassert(mCtrlShaderEnable != NULL);
llassert(mCtrlAvatarImpostors != NULL);
llassert(mCtrlNonImpostors != NULL);
llassert(mCtrlAvatarCloth != NULL);
llassert(mCtrlLightingDetail2 != NULL);
llassert(mCtrlAmbientOcc != NULL);
llassert(mRadioTerrainDetail != NULL);
llassert(mCtrlReflectionDetail != NULL);
llassert(mCtrlTerrainScale != NULL);
llassert(mMeshDetailText != NULL);
llassert(mShaderText != NULL);
llassert(mReflectionText != NULL);
llassert(mTerrainScaleText != NULL);
llassert(mAvatarText != NULL);
llassert(mTerrainText != NULL);
llassert(mDrawDistanceMeterText1 != NULL);
llassert(mDrawDistanceMeterText2 != NULL);
// enable/disable the states
//mGraphicsBorder->setVisible(!isHidden);
/*
LLColor4 light(.45098f, .51765f, .6078f, 1.0f);
LLColor4 dark(.10196f, .10196f, .10196f, 1.0f);
b ? mGraphicsBorder->setColors(dark, light) : mGraphicsBorder->setColors(dark, dark);
*/
mCtrlDrawDistance->setVisible(!isHidden);
mCtrlLODFactor->setVisible(!isHidden);
mCtrlFlexFactor->setVisible(!isHidden);
mCtrlTreeFactor->setVisible(!isHidden);
mCtrlAvatarFactor->setVisible(!isHidden);
mCtrlAvatarPhysicsFactor->setVisible(!isHidden);
mCtrlTerrainFactor->setVisible(!isHidden);
mCtrlSkyFactor->setVisible(!isHidden);
mCtrlMaxParticle->setVisible(!isHidden);
mCtrlPostProcess->setVisible(!isHidden);
mLODFactorText->setVisible(!isHidden);
mFlexFactorText->setVisible(!isHidden);
mTreeFactorText->setVisible(!isHidden);
mAvatarFactorText->setVisible(!isHidden);
mAvatarPhysicsFactorText->setVisible(!isHidden);
mTerrainFactorText->setVisible(!isHidden);
mSkyFactorText->setVisible(!isHidden);
mPostProcessText->setVisible(!isHidden);
mCtrlTransparentWater->setVisible(!isHidden);
mCtrlBumpShiny->setVisible(!isHidden);
mCtrlWindLight->setVisible(!isHidden);
mCtrlAvatarVP->setVisible(!isHidden);
mCtrlShaderEnable->setVisible(!isHidden);
mCtrlAvatarImpostors->setVisible(!isHidden);
mCtrlNonImpostors->setVisible(!isHidden);
mCtrlAvatarCloth->setVisible(!isHidden);
mCtrlLightingDetail2->setVisible(!isHidden);
mCtrlAmbientOcc->setVisible(!isHidden);
mRadioTerrainDetail->setVisible(!isHidden);
mCtrlReflectionDetail->setVisible(!isHidden);
mCtrlTerrainScale->setVisible(!isHidden);
mCtrlDeferred->setVisible(!isHidden);
mCtrlDeferredDoF->setVisible(!isHidden);
mCtrlShadowDetail->setVisible(!isHidden);
// text boxes
mShaderText->setVisible(!isHidden);
mReflectionText->setVisible(!isHidden);
mAvatarText->setVisible(!isHidden);
mTerrainText->setVisible(!isHidden);
mDrawDistanceMeterText1->setVisible(!isHidden);
mDrawDistanceMeterText2->setVisible(!isHidden);
mShadowDetailText->setVisible(!isHidden);
mTerrainScaleText->setVisible(!isHidden);
// hide one meter text if we're making things visible
if(!isHidden)
{
updateMeterText();
}
mMeshDetailText->setVisible(!isHidden);
}
void LLPanelDisplay::cancel()
{
gSavedSettings.setBOOL("FullScreenAutoDetectAspectRatio", mFSAutoDetectAspect);
gSavedSettings.setF32("FullScreenAspectRatio", mAspectRatio);
gSavedSettings.setU32("RenderQualityPerformance", mQualityPerformance);
gSavedSettings.setBOOL("RenderCustomSettings", mCustomSettings);
gSavedSettings.setBOOL("RenderTransparentWater", mTransparentWater);
gSavedSettings.setBOOL("RenderObjectBump", mBumpShiny);
gSavedSettings.setBOOL("VertexShaderEnable", mShaderEnable);
gSavedSettings.setBOOL("WindLightUseAtmosShaders", mWindLight);
gSavedSettings.setBOOL("RenderAvatarVP", mAvatarVP);
gSavedSettings.setBOOL("RenderDeferred", mDeferred);
gSavedSettings.setBOOL("RenderDepthOfField", mDeferredDoF);
gSavedSettings.setS32("RenderReflectionDetail", mReflectionDetail);
gSavedSettings.setS32("RenderShadowDetail", mShadowDetail);
gSavedSettings.setF32("RenderTerrainScale", mTerrainScale);
gSavedSettings.setBOOL("RenderUseImpostors", mAvatarImpostors);
gSavedSettings.setS32("RenderAvatarMaxVisible", mNonImpostors);
gSavedSettings.setBOOL("RenderAvatarCloth", mAvatarCloth);
gSavedSettings.setBOOL("RenderLocalLights", mLocalLights);
gSavedSettings.setS32("RenderTerrainDetail", mTerrainDetail);
gSavedSettings.setF32("RenderFarClip", mRenderFarClip);
gSavedSettings.setF32("RenderVolumeLODFactor", mPrimLOD);
gSavedSettings.setF32("RenderFlexTimeFactor", mFlexLOD);
gSavedSettings.setF32("RenderTreeLODFactor", mTreeLOD);
gSavedSettings.setF32("RenderAvatarLODFactor", mAvatarLOD);
gSavedSettings.setF32("RenderTerrainLODFactor", mTerrainLOD);
gSavedSettings.setU32("WLSkyDetail", mSkyLOD);
gSavedSettings.setS32("RenderMaxPartCount", mParticleCount);
gSavedSettings.setS32("RenderGlowResolutionPow", mPostProcess);
// Hardware tab
gSavedSettings.setBOOL("RenderVBOEnable", mUseVBO);
gSavedSettings.setBOOL("RenderUseFBO", mUseFBO);
gSavedSettings.setBOOL("RenderAnisotropic", mUseAniso);
gSavedSettings.setU32("RenderFSAASamples", mFSAASamples);
gSavedSettings.setF32("RenderGamma", mGamma);
gSavedSettings.setS32("TextureMemory", mVideoCardMem);
gSavedSettings.setF32("RenderFogRatio", mFogRatio);
gSavedSettings.setS32("SHRenderVsyncMode", mVsyncMode);
}
void LLPanelDisplay::apply()
{
U32 fsaa_value = childGetValue("fsaa").asInteger();
S32 vsync_value = childGetValue("vsync").asInteger();
bool fbo_value = childGetValue("fbo").asBoolean();
LLWindow* window = gViewerWindow->getWindow();
if(vsync_value == -1 && !gGLManager.mHasAdaptiveVsync)
vsync_value = 0;
bool apply_fsaa_change = fbo_value ? false : (mFSAASamples != fsaa_value);
if(!apply_fsaa_change && (bool)mUseFBO != fbo_value)
{
apply_fsaa_change = fsaa_value != 0 || mFSAASamples != 0 ;
}
bool apply_vsync_change = vsync_value != mVsyncMode;
gSavedSettings.setU32("RenderFSAASamples", fsaa_value);
gSavedSettings.setS32("SHRenderVsyncMode", vsync_value);
applyResolution();
// Only set window size if we're not in fullscreen mode
if (mCtrlWindowed->get())
{
applyWindowSize();
}
// Hardware tab
//Still do a bit of voodoo here. V2 forces restart to change FSAA with FBOs off.
//Let's not do that, and instead do pre-V2 FSAA change handling for that particular case
if(apply_fsaa_change || apply_vsync_change)
{
bool logged_in = (LLStartUp::getStartupState() >= STATE_STARTED);
LLCoordScreen size;
window->getSize(&size);
LLGLState::checkStates();
LLGLState::checkTextureChannels();
gViewerWindow->changeDisplaySettings(window->getFullscreen(),
size,
vsync_value,
logged_in);
LLGLState::checkStates();
LLGLState::checkTextureChannels();
}
}
void LLPanelDisplay::onChangeQuality(LLUICtrl* caller)
{
LLSlider* sldr = dynamic_cast<LLSlider*>(caller);
if(sldr == NULL)
{
return;
}
U32 set = (U32)sldr->getValueF32();
LLFeatureManager::getInstance()->setGraphicsLevel(set, true);
LLFloaterPreference::refreshEnabledGraphics();
refresh();
}
void LLPanelDisplay::onChangeCustom()
{
LLFloaterPreference::refreshEnabledGraphics();
}
void LLPanelDisplay::applyResolution()
{
gGL.flush();
char aspect_ratio_text[ASPECT_RATIO_STR_LEN]; /*Flawfinder: ignore*/
if (mCtrlAspectRatio->getCurrentIndex() == -1)
{
// *Can't pass const char* from c_str() into strtok
strncpy(aspect_ratio_text, mCtrlAspectRatio->getSimple().c_str(), sizeof(aspect_ratio_text) -1); /*Flawfinder: ignore*/
aspect_ratio_text[sizeof(aspect_ratio_text) -1] = '\0';
char *element = strtok(aspect_ratio_text, ":/\\");
if (!element)
{
mAspectRatio = 0.f; // will be clamped later
}
else
{
LLLocale locale(LLLocale::USER_LOCALE);
mAspectRatio = (F32)atof(element);
}
// look for denominator
element = strtok(NULL, ":/\\");
if (element)
{
LLLocale locale(LLLocale::USER_LOCALE);
F32 denominator = (F32)atof(element);
if (denominator != 0.f)
{
mAspectRatio /= denominator;
}
}
}
else
{
mAspectRatio = (F32)mCtrlAspectRatio->getValue().asReal();
}
// presumably, user entered a non-numeric value if aspect_ratio == 0.f
if (mAspectRatio != 0.f)
{
mAspectRatio = llclamp(mAspectRatio, 0.2f, 5.f);
gSavedSettings.setF32("FullScreenAspectRatio", mAspectRatio);
}
// Screen resolution
S32 num_resolutions;
LLWindow::LLWindowResolution* supported_resolutions =
gViewerWindow->getWindow()->getSupportedResolutions(num_resolutions);
U32 resIndex = mCtrlFullScreen->getCurrentIndex();
gSavedSettings.setS32("FullScreenWidth", supported_resolutions[resIndex].mWidth);
gSavedSettings.setS32("FullScreenHeight", supported_resolutions[resIndex].mHeight);
gViewerWindow->requestResolutionUpdate(!mCtrlWindowed->get());
send_agent_update(TRUE);
// Update enable/disable
refresh();
}
// Extract from strings of the form "<width> x <height>", e.g. "640 x 480".
bool LLPanelDisplay::extractWindowSizeFromString(const std::string& instr, U32 &width, U32 &height)
{
using namespace boost;
cmatch what;
const regex expression("([0-9]+) x ([0-9]+)");
if (regex_match(instr.c_str(), what, expression))
{
width = atoi(what[1].first);
height = atoi(what[2].first);
return true;
}
width = height = 0;
return false;
}
void LLPanelDisplay::applyWindowSize()
{
if (mCtrlWindowSize->getVisible() && (mCtrlWindowSize->getCurrentIndex() != -1))
{
U32 width = 0;
U32 height = 0;
if (extractWindowSizeFromString(mCtrlWindowSize->getValue().asString().c_str(), width,height))
{
LLViewerWindow::movieSize(width, height);
}
}
}
void LLPanelDisplay::onCommitWindowedMode()
{
refresh();
}
void LLPanelDisplay::onCommitAutoDetectAspect(const LLSD& value)
{
BOOL auto_detect = value.asBoolean();
F32 ratio;
if (auto_detect)
{
S32 numerator = 0;
S32 denominator = 0;
// clear any aspect ratio override
gViewerWindow->getWindow()->setNativeAspectRatio(0.f);
fractionFromDecimal(gViewerWindow->getWindow()->getNativeAspectRatio(), numerator, denominator);
std::string aspect;
if (numerator != 0)
{
aspect = llformat("%d:%d", numerator, denominator);
}
else
{
aspect = llformat("%.3f", gViewerWindow->getWindow()->getNativeAspectRatio());
}
mCtrlAspectRatio->setLabel(aspect);
ratio = gViewerWindow->getWindow()->getNativeAspectRatio();
gSavedSettings.setF32("FullScreenAspectRatio", ratio);
}
}
void LLPanelDisplay::onKeystrokeAspectRatio()
{
mCtrlAutoDetectAspect->set(FALSE);
}
void LLPanelDisplay::onSelectAspectRatio()
{
mCtrlAutoDetectAspect->set(FALSE);
}
//static
void LLPanelDisplay::fractionFromDecimal(F32 decimal_val, S32& numerator, S32& denominator)
{
numerator = 0;
denominator = 0;
for (F32 test_denominator = 1.f; test_denominator < 30.f; test_denominator += 1.f)
{
if (fmodf((decimal_val * test_denominator) + 0.01f, 1.f) < 0.02f)
{
numerator = llround(decimal_val * test_denominator);
denominator = llround(test_denominator);
break;
}
}
}
void LLPanelDisplay::onVertexShaderEnable()
{
LLFloaterPreference::refreshEnabledGraphics();
}
//static
void LLPanelDisplay::setHardwareDefaults()
{
LLFeatureManager::getInstance()->applyRecommendedSettings();
LLControlVariable* controlp = gSavedSettings.getControl("RenderAvatarMaxVisible");
if (controlp)
{
controlp->resetToDefault(true);
}
LLFloaterPreference::refreshEnabledGraphics();
}
//static
void LLPanelDisplay::updateSliderText(LLUICtrl* ctrl, LLTextBox* text_box)
{
// get our UI widgets
LLSliderCtrl* slider = dynamic_cast<LLSliderCtrl*>(ctrl);
if(text_box == NULL || slider == NULL)
{
return;
}
//Hack to display 'Off' for avatar physics slider.
if(slider->getName() == "AvatarPhysicsDetail" && !slider->getValueF32())
{
text_box->setText(std::string("Off"));
return;
}
// get range and points when text should change
F32 range = slider->getMaxValue() - slider->getMinValue();
llassert(range > 0);
F32 midPoint = slider->getMinValue() + range / 3.0f;
F32 highPoint = slider->getMinValue() + (2.0f * range / 3.0f);
// choose the right text
if(slider->getValueF32() < midPoint)
{
text_box->setText(std::string("Low"));
}
else if (slider->getValueF32() < highPoint)
{
text_box->setText(std::string("Mid"));
}
else if(slider->getValueF32() < slider->getMaxValue())
{
text_box->setText(std::string("High"));
}
else
{
text_box->setText(std::string("Max"));
}
}
void LLPanelDisplay::updateMeterText()
{
// toggle the two text boxes based on whether we have 2 or 3 digits
F32 val = mCtrlDrawDistance->getValueF32();
bool two_digits = val < 100;
mDrawDistanceMeterText1->setVisible(two_digits);
mDrawDistanceMeterText2->setVisible(!two_digits);
}