Sync light state, bound shader, and various gl context states similarly to render matrices. Texture handles now refcounted, as multiple viewer textures could ref the same handle (cubemaps do this) Clean up gl extension loading a bit. Not necessary, but only look for ARB variants if not included in current core version. Removed unused extensions. Use core shader api if supported, else use ARB. (FN signatures are identical. Just doing some pointer substitution to ARB if not core.) Attempt at improving VBO update batching. Subdata updates better batched to gether per-frame. There's probably other stuff I forgot that is in this changeset, too. Todo: Fix lightstate assertion when toggling fullscreen with shaders off.
958 lines
32 KiB
C++
958 lines
32 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;
|
|
|
|
void reset_to_default(const std::string& control);
|
|
void reset_all_to_default(const LLView* panel)
|
|
{
|
|
LLView::child_list_const_iter_t end(panel->endChild());
|
|
for (LLView::child_list_const_iter_t i = panel->beginChild(); i != end; ++i)
|
|
{
|
|
const std::string& control_name((*i)->getControlName());
|
|
if (control_name.empty()) continue;
|
|
if (control_name == "RenderDepthOfField") continue; // Don't touch render settings *sigh* hack
|
|
reset_to_default(control_name);
|
|
}
|
|
}
|
|
|
|
LLPanelDisplay::LLPanelDisplay()
|
|
{
|
|
mCommitCallbackRegistrar.add("Graphics.ResetTab", boost::bind(reset_all_to_default, boost::bind(&LLView::getChildView, this, _2, true, false)));
|
|
LLUICtrlFactory::getInstance()->buildPanel(this, "panel_preferences_graphics1.xml");
|
|
}
|
|
|
|
void updateSliderText(LLSliderCtrl* slider, LLTextBox* text_box);
|
|
|
|
BOOL LLPanelDisplay::postBuild()
|
|
{
|
|
// return to default values
|
|
getChild<LLButton>("Defaults")->setClickedCallback(boost::bind(&LLPanelDisplay::setHardwareDefaults, this));
|
|
|
|
//============================================================================
|
|
// 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);
|
|
}
|
|
|
|
mCtrlAutoDetectAspect = getChild<LLCheckBoxCtrl>( "aspect_auto_detect");
|
|
mCtrlAutoDetectAspect->setCommitCallback(boost::bind(&LLPanelDisplay::onCommitAutoDetectAspect,this,_2));
|
|
|
|
mCtrlAspectRatio = getChild<LLComboBox>( "aspect_ratio");
|
|
mCtrlAspectRatio->setTextEntryCallback(boost::bind(&LLUICtrl::setValue, mCtrlAutoDetectAspect, false));
|
|
mCtrlAspectRatio->setCommitCallback(boost::bind(&LLUICtrl::setValue, mCtrlAutoDetectAspect, false));
|
|
// add default aspect ratios
|
|
mCtrlAspectRatio->add(aspect_ratio_text, &mAspectRatio, ADD_TOP);
|
|
mCtrlAspectRatio->setCurrentByIndex(0);
|
|
|
|
// radio performance box
|
|
mCtrlSliderQuality = getChild<LLSliderCtrl>("QualityPerformanceSelection");
|
|
mCtrlSliderQuality->setSliderMouseUpCallback(boost::bind(&LLPanelDisplay::onChangeQuality,this,_1));
|
|
|
|
mCtrlCustomSettings = getChild<LLCheckBoxCtrl>("CustomSettings");
|
|
mCtrlCustomSettings->setCommitCallback(boost::bind(&LLPanelDisplay::refreshEnabledState, this));
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Enable Bump/Shiny
|
|
mCtrlBumpShiny = getChild<LLCheckBoxCtrl>("BumpShiny");
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Enable Reflections
|
|
mCtrlReflectionDetail = getChild<LLComboBox>("ReflectionDetailCombo");
|
|
mCtrlReflectionDetail->setCommitCallback(boost::bind(&LLPanelDisplay::refreshEnabledState, this));
|
|
|
|
// WindLight
|
|
mCtrlWindLight = getChild<LLCheckBoxCtrl>("WindLightUseAtmosShaders");
|
|
mCtrlWindLight->setCommitCallback(boost::bind(&LLPanelDisplay::refreshEnabledState, this));
|
|
|
|
// Deferred
|
|
mCtrlDeferred = getChild<LLCheckBoxCtrl>("RenderDeferred");
|
|
mCtrlDeferred->setCommitCallback(boost::bind(&LLPanelDisplay::refreshEnabledState, this));
|
|
mCtrlDeferredDoF = getChild<LLCheckBoxCtrl>("RenderDepthOfField");
|
|
mCtrlDeferredDoF->setCommitCallback(boost::bind(&LLPanelDisplay::refreshEnabledState, this));
|
|
mCtrlShadowDetail = getChild<LLComboBox>("ShadowDetailCombo");
|
|
mCtrlShadowDetail->setCommitCallback(boost::bind(&LLPanelDisplay::refreshEnabledState, this));
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Terrain Scale
|
|
mCtrlTerrainScale = getChild<LLComboBox>("TerrainScaleCombo");
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Enable Avatar Shaders
|
|
mCtrlAvatarVP = getChild<LLCheckBoxCtrl>("AvatarVertexProgram");
|
|
mCtrlAvatarVP->setCommitCallback(boost::bind(&LLPanelDisplay::refreshEnabledState, this));
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Avatar Render Mode
|
|
mCtrlAvatarCloth = getChild<LLCheckBoxCtrl>("AvatarCloth");
|
|
mCtrlAvatarImpostors = getChild<LLCheckBoxCtrl>("AvatarImpostors");
|
|
mCtrlAvatarImpostors->setCommitCallback(boost::bind(&LLPanelDisplay::refreshEnabledState, this));
|
|
|
|
//----------------------------------------------------------------------------
|
|
// 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::refreshEnabledState, this));
|
|
|
|
//============================================================================
|
|
|
|
// Object detail slider
|
|
LLSliderCtrl* ctrl_slider = getChild<LLSliderCtrl>("ObjectMeshDetail");
|
|
LLTextBox* slider_text = getChild<LLTextBox>("ObjectMeshDetailText");
|
|
ctrl_slider->setCommitCallback(boost::bind(updateSliderText, ctrl_slider, slider_text));
|
|
updateSliderText(ctrl_slider, slider_text);
|
|
|
|
// Flex object detail slider
|
|
ctrl_slider = getChild<LLSliderCtrl>("FlexibleMeshDetail");
|
|
slider_text = getChild<LLTextBox>("FlexibleMeshDetailText");
|
|
ctrl_slider->setCommitCallback(boost::bind(updateSliderText, ctrl_slider, slider_text));
|
|
updateSliderText(ctrl_slider, slider_text);
|
|
|
|
// Tree detail slider
|
|
ctrl_slider = getChild<LLSliderCtrl>("TreeMeshDetail");
|
|
slider_text = getChild<LLTextBox>("TreeMeshDetailText");
|
|
ctrl_slider->setCommitCallback(boost::bind(updateSliderText, ctrl_slider, slider_text));
|
|
updateSliderText(ctrl_slider, slider_text);
|
|
|
|
// Avatar detail slider
|
|
ctrl_slider = getChild<LLSliderCtrl>("AvatarMeshDetail");
|
|
slider_text = getChild<LLTextBox>("AvatarMeshDetailText");
|
|
ctrl_slider->setCommitCallback(boost::bind(updateSliderText, ctrl_slider, slider_text));
|
|
updateSliderText(ctrl_slider, slider_text);
|
|
|
|
// Avatar physics detail slider
|
|
ctrl_slider = getChild<LLSliderCtrl>("AvatarPhysicsDetail");
|
|
slider_text = getChild<LLTextBox>("AvatarPhysicsDetailText");
|
|
ctrl_slider->setCommitCallback(boost::bind(updateSliderText, ctrl_slider, slider_text));
|
|
updateSliderText(ctrl_slider, slider_text);
|
|
|
|
// Terrain detail slider
|
|
ctrl_slider = getChild<LLSliderCtrl>("TerrainMeshDetail");
|
|
slider_text = getChild<LLTextBox>("TerrainMeshDetailText");
|
|
ctrl_slider->setCommitCallback(boost::bind(updateSliderText, ctrl_slider, slider_text));
|
|
updateSliderText(ctrl_slider, slider_text);
|
|
|
|
// Terrain detail slider
|
|
ctrl_slider = getChild<LLSliderCtrl>("SkyMeshDetail");
|
|
slider_text = getChild<LLTextBox>("SkyMeshDetailText");
|
|
ctrl_slider->setCommitCallback(boost::bind(updateSliderText, ctrl_slider, slider_text));
|
|
updateSliderText(ctrl_slider, slider_text);
|
|
|
|
// Glow detail slider
|
|
ctrl_slider = getChild<LLSliderCtrl>("RenderPostProcess");
|
|
slider_text = getChild<LLTextBox>("PostProcessText");
|
|
ctrl_slider->setCommitCallback(boost::bind(updateSliderText, ctrl_slider, slider_text));
|
|
updateSliderText(ctrl_slider, slider_text);
|
|
|
|
// Text boxes (for enabling/disabling)
|
|
|
|
// Hardware tab
|
|
mVBO = getChild<LLCheckBoxCtrl>("vbo");
|
|
mVBO->setCommitCallback(boost::bind(&LLPanelDisplay::refreshEnabledState, this));
|
|
|
|
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");
|
|
mDeferredSSAO = gSavedSettings.getBOOL("RenderDeferredSSAO");
|
|
|
|
// 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");
|
|
|
|
// 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);
|
|
|
|
// Depth of Field tab
|
|
mFNumber = gSavedSettings.getF32("CameraFNumber");
|
|
mFocalLength = gSavedSettings.getF32("CameraFocalLength");
|
|
mMaxCoF = gSavedSettings.getF32("CameraMaxCoF");
|
|
mFocusTrans = gSavedSettings.getF32("CameraFocusTransitionTime");
|
|
mDoFRes = gSavedSettings.getF32("CameraDoFResScale");
|
|
|
|
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);
|
|
|
|
F32 mem_multiplier = gSavedSettings.getF32("RenderTextureMemoryMultiple");
|
|
S32Megabytes min_tex_mem = LLViewerTextureList::getMinVideoRamSetting();
|
|
S32Megabytes max_tex_mem = LLViewerTextureList::getMaxVideoRamSetting(false, mem_multiplier);
|
|
|
|
// Hardware tab
|
|
getChild<LLUICtrl>("GrapicsCardTextureMemory")->setMinValue(min_tex_mem.value());
|
|
getChild<LLUICtrl>("GrapicsCardTextureMemory")->setMaxValue(max_tex_mem.value());
|
|
|
|
if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderVBOEnable") ||
|
|
!gGLManager.mHasVertexBufferObject)
|
|
{
|
|
mVBO->setEnabled(false);
|
|
mVBO->setValue(false);
|
|
}
|
|
|
|
static LLCachedControl<bool> wlatmos("WindLightUseAtmosShaders",false);
|
|
// if no windlight shaders, enable gamma, and fog distance
|
|
getChildView("gamma")->setEnabled(!wlatmos);
|
|
getChildView("fog")->setEnabled(!wlatmos);
|
|
getChildView("note")->setVisible(wlatmos);
|
|
|
|
// disable graphics settings and exit if it's not set to custom
|
|
if (!gSavedSettings.getBOOL("RenderCustomSettings")) return;
|
|
|
|
// 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);
|
|
|
|
mCtrlAvatarCloth->setEnabled(gSavedSettings.getBOOL("VertexShaderEnable") && gSavedSettings.getBOOL("RenderAvatarVP"));
|
|
|
|
//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 = LLPipeline::isRenderDeferredCapable() &&
|
|
gSavedSettings.getBOOL("VertexShaderEnable") && //Basic Shaders
|
|
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);
|
|
|
|
// 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]
|
|
|
|
// Avatar Mode and FBO
|
|
if (render_deferred && wlatmos && shaders)
|
|
{
|
|
getChildView("fbo")->setEnabled(false);
|
|
//getChildView("fbo")->setValue(true);
|
|
mCtrlAvatarVP->setEnabled(false);
|
|
//gSavedSettings.setBOOL("RenderAvatarVP", true);
|
|
}
|
|
else
|
|
{
|
|
getChildView("fbo")->setEnabled(gGLManager.mHasFramebufferObject);
|
|
//getChildView("fbo")->setValue(gSavedSettings.getBOOL("RenderUseFBO"));
|
|
mCtrlAvatarVP->setEnabled(shaders);
|
|
//if (!shaders) gSavedSettings.setBOOL("RenderAvatarVP", false);
|
|
}
|
|
|
|
// now turn off any features that are unavailable
|
|
disableUnavailableSettings();
|
|
}
|
|
|
|
void LLPanelDisplay::disableUnavailableSettings()
|
|
{
|
|
// disabled terrain scale
|
|
if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderTerrainScale"))
|
|
{
|
|
mCtrlTerrainScale->setEnabled(false);
|
|
mCtrlTerrainScale->setValue(false);
|
|
}
|
|
// disabled impostors
|
|
if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderUseImpostors"))
|
|
{
|
|
mCtrlAvatarImpostors->setEnabled(false);
|
|
mCtrlAvatarImpostors->setValue(false);
|
|
}
|
|
|
|
// if vertex shaders off, disable all shader related products
|
|
// Singu Note: Returns early this, place all unrelated checks above now.
|
|
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);
|
|
return;
|
|
}
|
|
|
|
// 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 av
|
|
if(!LLFeatureManager::getInstance()->isFeatureAvailable("RenderAvatarVP"))
|
|
{
|
|
mCtrlAvatarVP->setEnabled(FALSE);
|
|
mCtrlAvatarVP->setValue(FALSE);
|
|
|
|
mCtrlAvatarCloth->setEnabled(FALSE);
|
|
mCtrlAvatarCloth->setValue(FALSE);
|
|
}
|
|
// disabled cloth
|
|
else if(!LLFeatureManager::getInstance()->isFeatureAvailable("RenderAvatarCloth"))
|
|
{
|
|
mCtrlAvatarCloth->setEnabled(FALSE);
|
|
mCtrlAvatarCloth->setValue(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::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.setBOOL("RenderDeferredSSAO", mDeferredSSAO);
|
|
|
|
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);
|
|
|
|
// Depth of Field tab
|
|
gSavedSettings.setF32("CameraFNumber", mFNumber);
|
|
gSavedSettings.setF32("CameraFocalLength", mFocalLength);
|
|
gSavedSettings.setF32("CameraMaxCoF", mMaxCoF);
|
|
gSavedSettings.setF32("CameraFocusTransitionTime", mFocusTrans);
|
|
gSavedSettings.setF32("CameraDoFResScale", mDoFRes);
|
|
}
|
|
|
|
void LLPanelDisplay::apply()
|
|
{
|
|
bool can_defer = LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred");
|
|
|
|
S32 vsync_value = childGetValue("vsync").asInteger();
|
|
bool fbo_value = childGetValue("fbo").asBoolean() || (can_defer && mCtrlDeferred->getValue().asBoolean());
|
|
bool fbo_prior_value = mUseFBO || (can_defer && mDeferred );
|
|
U8 fsaa_value = fbo_value ? 0 : childGetValue("fsaa").asInteger();
|
|
U8 fsaa_prior_value = fbo_prior_value ? 0 : mFSAASamples;
|
|
LLWindow* window = gViewerWindow->getWindow();
|
|
|
|
if(vsync_value == -1 && !gGLManager.mHasAdaptiveVsync)
|
|
vsync_value = 0;
|
|
|
|
bool apply_fsaa_change = fsaa_value != fsaa_prior_value;
|
|
|
|
bool apply_vsync_change = vsync_value != mVsyncMode;
|
|
|
|
gSavedSettings.setU32("RenderFSAASamples", childGetValue("fsaa").asInteger());
|
|
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);
|
|
LLGLStateValidator::checkStates();
|
|
LLGLStateValidator::checkTextureChannels();
|
|
gViewerWindow->changeDisplaySettings(window->getFullscreen(),
|
|
size,
|
|
vsync_value,
|
|
logged_in);
|
|
LLGLStateValidator::checkStates();
|
|
LLGLStateValidator::checkTextureChannels();
|
|
}
|
|
}
|
|
|
|
void LLPanelDisplay::onChangeQuality(LLUICtrl* ctrl)
|
|
{
|
|
LLFeatureManager::getInstance()->setGraphicsLevel(ctrl->getValue(), true);
|
|
refreshEnabledState();
|
|
refresh();
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
//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 = ll_round(decimal_val * test_denominator);
|
|
denominator = ll_round(test_denominator);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void LLPanelDisplay::setHardwareDefaults()
|
|
{
|
|
LLFeatureManager::getInstance()->applyRecommendedSettings();
|
|
if (LLControlVariable* controlp = gSavedSettings.getControl("RenderAvatarMaxVisible"))
|
|
{
|
|
controlp->resetToDefault(true);
|
|
}
|
|
refreshEnabledState();
|
|
}
|
|
|
|
void updateSliderText(LLSliderCtrl* slider, LLTextBox* text_box)
|
|
{
|
|
// get range and points when text should change
|
|
const F32 value = slider->getValue().asFloat();
|
|
const F32 min_val = slider->getMinValue();
|
|
const F32 max_val = slider->getMaxValue();
|
|
const F32 range = (max_val - min_val)/3.f;
|
|
|
|
// choose the right text
|
|
if (value < min_val + range)
|
|
{
|
|
//Hack to display 'Off' for avatar physics slider.
|
|
if (!value && slider->getName() == "AvatarPhysicsDetail")
|
|
text_box->setText(std::string("Off"));
|
|
else
|
|
text_box->setText(std::string("Low"));
|
|
}
|
|
else if (value < min_val + 2.0f * range)
|
|
{
|
|
text_box->setText(std::string("Mid"));
|
|
}
|
|
else if (value < max_val)
|
|
{
|
|
text_box->setText(std::string("High"));
|
|
}
|
|
else
|
|
{
|
|
text_box->setText(std::string("Max"));
|
|
}
|
|
}
|
|
|