Skip to content
Snippets Groups Projects
pipeline.cpp 273 KiB
Newer Older
James Cook's avatar
James Cook committed
/** 
 * @file pipeline.cpp
 * @brief Rendering pipeline.
 *
 * $LicenseInfo:firstyear=2005&license=viewerlgpl$
 * Second Life Viewer Source Code
 * Copyright (C) 2010, Linden Research, Inc.
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation;
 * version 2.1 of the License only.
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 * $/LicenseInfo$
James Cook's avatar
James Cook committed
 */

#include "llviewerprecompiledheaders.h"

#include "pipeline.h"

// library includes
#include "llaudioengine.h" // For debugging.
James Cook's avatar
James Cook committed
#include "llerror.h"
#include "llviewercontrol.h"
#include "llfasttimer.h"
#include "llfontgl.h"
#include "llnamevalue.h"
James Cook's avatar
James Cook committed
#include "llprimitive.h"
#include "llvolume.h"
#include "material_codes.h"
#include "v3color.h"
#include "llglheaders.h"
#include "llrender.h"
#include "llwindow.h"	// swapBuffers()
James Cook's avatar
James Cook committed

// newview includes
#include "llagent.h"
#include "llappviewer.h"
#include "lltexturecache.h"
#include "lltexturefetch.h"
#include "llimageworker.h"
James Cook's avatar
James Cook committed
#include "lldrawable.h"
#include "lldrawpoolalpha.h"
#include "lldrawpoolavatar.h"
#include "lldrawpoolground.h"
#include "lldrawpoolbump.h"
James Cook's avatar
James Cook committed
#include "lldrawpooltree.h"
#include "lldrawpoolwater.h"
#include "llface.h"
#include "llfeaturemanager.h"
#include "llfloatertelehub.h"
#include "llfloaterreg.h"
James Cook's avatar
James Cook committed
#include "llgldbg.h"
#include "llhudmanager.h"
#include "llhudnametag.h"
James Cook's avatar
James Cook committed
#include "lllightconstants.h"
David Parks's avatar
David Parks committed
#include "llmeshrepository.h"
#include "llpipelinelistener.h"
James Cook's avatar
James Cook committed
#include "llresmgr.h"
#include "llselectmgr.h"
#include "llsky.h"
#include "lltracker.h"
#include "lltool.h"
#include "lltoolmgr.h"
#include "llviewercamera.h"
David Parks's avatar
David Parks committed
#include "llviewermediafocus.h"
#include "llviewertexturelist.h"
James Cook's avatar
James Cook committed
#include "llviewerobject.h"
#include "llviewerobjectlist.h"
#include "llviewerparcelmgr.h"
#include "llviewerregion.h" // for audio debugging.
#include "llviewerwindow.h" // For getSpinAxis
#include "llvoavatarself.h"
James Cook's avatar
James Cook committed
#include "llvoground.h"
#include "llvosky.h"
#include "llvotree.h"
#include "llvovolume.h"
#include "llvosurfacepatch.h"
#include "llvowater.h"
#include "llvotree.h"
#include "llvopartgroup.h"
James Cook's avatar
James Cook committed
#include "llworld.h"
#include "llcubemap.h"
#include "llviewershadermgr.h"
#include "llviewerstats.h"
#include "llwlparammanager.h"
#include "llwaterparammanager.h"
#include "llspatialpartition.h"
#include "lltoolpie.h"
#include "llnotifications.h"
#include "llfloatertools.h"
#include "llpanelface.h"
#include "llcleanup.h"
// [RLVa:KB] - Checked: RLVa-2.0.0
#include "rlvactions.h"
// [/RLVa:KB]
James Cook's avatar
James Cook committed

Drake Arconis's avatar
Drake Arconis committed
#include "llglmhelpers.h"

Drake Arconis's avatar
Drake Arconis committed
#include <glm/vec3.hpp>
#include <glm/vec4.hpp>
#include <glm/mat4x4.hpp>
#include <glm/gtc/matrix_inverse.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>

James Cook's avatar
James Cook committed
#ifdef _DEBUG
// Debug indices is disabled for now for debug performance - djs 4/24/02
//#define DEBUG_INDICES
#else
//#define DEBUG_INDICES
#endif

bool gShiftFrame = false;

bool LLPipeline::RenderAvatarVP;
bool LLPipeline::VertexShaderEnable;
bool LLPipeline::WindLightUseAtmosShaders;
bool LLPipeline::RenderDeferred;
F32 LLPipeline::RenderDeferredSunWash;
U32 LLPipeline::RenderFSAASamples;
U32 LLPipeline::RenderResolutionDivisor;
// [SL:KB] - Patch: Settings-RenderResolutionMultiplier | Checked: Catznip-5.4
F32 LLPipeline::RenderResolutionMultiplier;
// [/SL:KB]
bool LLPipeline::RenderUIBuffer;
bool LLPipeline::RenderDeferredSSAO;
F32 LLPipeline::RenderDeferredSSAOResolutionScale;
F32 LLPipeline::RenderShadowResolutionScale;
bool LLPipeline::RenderLocalLights;
bool LLPipeline::RenderDelayCreation;
bool LLPipeline::RenderAnimateRes;
bool LLPipeline::FreezeTime;
S32 LLPipeline::DebugBeaconLineWidth;
F32 LLPipeline::RenderHighlightBrightness;
LLColor4 LLPipeline::RenderHighlightColor;
F32 LLPipeline::RenderHighlightThickness;
bool LLPipeline::RenderSpotLightsInNondeferred;
LLColor4 LLPipeline::PreviewAmbientColor;
LLColor4 LLPipeline::PreviewDiffuse0;
LLColor4 LLPipeline::PreviewSpecular0;
LLColor4 LLPipeline::PreviewDiffuse1;
LLColor4 LLPipeline::PreviewSpecular1;
LLColor4 LLPipeline::PreviewDiffuse2;
LLColor4 LLPipeline::PreviewSpecular2;
LLVector3 LLPipeline::PreviewDirection0;
LLVector3 LLPipeline::PreviewDirection1;
LLVector3 LLPipeline::PreviewDirection2;
F32 LLPipeline::RenderGlowMinLuminance;
F32 LLPipeline::RenderGlowMaxExtractAlpha;
F32 LLPipeline::RenderGlowWarmthAmount;
LLVector3 LLPipeline::RenderGlowLumWeights;
LLVector3 LLPipeline::RenderGlowWarmthWeights;
S32 LLPipeline::RenderGlowResolutionPow;
S32 LLPipeline::RenderGlowIterations;
F32 LLPipeline::RenderGlowWidth;
F32 LLPipeline::RenderGlowStrength;
bool LLPipeline::RenderDepthOfField;
bool LLPipeline::RenderDepthOfFieldInEditMode;
F32 LLPipeline::CameraFocusTransitionTime;
F32 LLPipeline::CameraFNumber;
F32 LLPipeline::CameraFocalLength;
F32 LLPipeline::CameraFieldOfView;
F32 LLPipeline::RenderShadowNoise;
F32 LLPipeline::RenderShadowBlurSize;
F32 LLPipeline::RenderSSAOScale;
U32 LLPipeline::RenderSSAOMaxScale;
F32 LLPipeline::RenderSSAOFactor;
LLVector3 LLPipeline::RenderSSAOEffect;
F32 LLPipeline::RenderShadowOffsetError;
F32 LLPipeline::RenderShadowBiasError;
F32 LLPipeline::RenderShadowOffset;
F32 LLPipeline::RenderShadowBias;
F32 LLPipeline::RenderSpotShadowOffset;
F32 LLPipeline::RenderSpotShadowBias;
F32 LLPipeline::RenderEdgeDepthCutoff;
F32 LLPipeline::RenderEdgeNormCutoff;
LLVector3 LLPipeline::RenderShadowGaussian;
F32 LLPipeline::RenderShadowBlurDistFactor;
bool LLPipeline::RenderDeferredAtmospheric;
S32 LLPipeline::RenderReflectionDetail;
F32 LLPipeline::RenderHighlightFadeTime;
LLVector3 LLPipeline::RenderShadowClipPlanes;
LLVector3 LLPipeline::RenderShadowOrthoClipPlanes;
LLVector3 LLPipeline::RenderShadowNearDist;
F32 LLPipeline::RenderFarClip;
LLVector3 LLPipeline::RenderShadowSplitExponent;
F32 LLPipeline::RenderShadowErrorCutoff;
F32 LLPipeline::RenderShadowFOVCutoff;
bool LLPipeline::CameraOffset;
F32 LLPipeline::CameraMaxCoF;
F32 LLPipeline::CameraDoFResScale;
F32 LLPipeline::RenderAutoHideSurfaceAreaLimit;
Cinder's avatar
Cinder committed
BOOL LLPipeline::RenderDeferredAlwaysSoftenShadows;
BOOL LLPipeline::RenderAggressiveBatching;
BOOL LLPipeline::RenderDeferredFullbright;

LLTrace::EventStatHandle<S64> LLPipeline::sStatBatchSize("renderbatchsize");
James Cook's avatar
James Cook committed
const F32 BACKLIGHT_DAY_MAGNITUDE_OBJECT = 0.1f;
const F32 BACKLIGHT_NIGHT_MAGNITUDE_OBJECT = 0.08f;
const U32 AUX_VB_MASK = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_TEXCOORD1;
James Cook's avatar
James Cook committed

extern S32 gBoxFrame;
extern BOOL gDebugGL;
James Cook's avatar
James Cook committed

bool	gAvatarBacklight = false;
James Cook's avatar
James Cook committed

bool	gDebugPipeline = false;
Cinder's avatar
Cinder committed
const LLMatrix4* gGLLastMatrix = nullptr;
LLTrace::BlockTimerStatHandle FTM_RENDER_GEOMETRY("Render Geometry");
LLTrace::BlockTimerStatHandle FTM_RENDER_GRASS("Grass");
LLTrace::BlockTimerStatHandle FTM_RENDER_INVISIBLE("Invisible");
LLTrace::BlockTimerStatHandle FTM_RENDER_OCCLUSION("Occlusion");
LLTrace::BlockTimerStatHandle FTM_RENDER_SHINY("Shiny");
LLTrace::BlockTimerStatHandle FTM_RENDER_SIMPLE("Simple");
LLTrace::BlockTimerStatHandle FTM_RENDER_TERRAIN("Terrain");
LLTrace::BlockTimerStatHandle FTM_RENDER_TREES("Trees");
LLTrace::BlockTimerStatHandle FTM_RENDER_UI("UI");
LLTrace::BlockTimerStatHandle FTM_RENDER_WATER("Water");
LLTrace::BlockTimerStatHandle FTM_RENDER_WL_SKY("Windlight Sky");
LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA("Alpha Objects");
LLTrace::BlockTimerStatHandle FTM_RENDER_CHARACTERS("Avatars");
LLTrace::BlockTimerStatHandle FTM_RENDER_BUMP("Bump");
LLTrace::BlockTimerStatHandle FTM_RENDER_MATERIALS("Render Materials");
LLTrace::BlockTimerStatHandle FTM_RENDER_FULLBRIGHT("Fullbright");
LLTrace::BlockTimerStatHandle FTM_RENDER_GLOW("Glow");
LLTrace::BlockTimerStatHandle FTM_GEO_UPDATE("Geo Update");
LLTrace::BlockTimerStatHandle FTM_PIPELINE_CREATE("Pipeline Create");
LLTrace::BlockTimerStatHandle FTM_POOLRENDER("RenderPool");
LLTrace::BlockTimerStatHandle FTM_POOLS("Pools");
LLTrace::BlockTimerStatHandle FTM_DEFERRED_POOLRENDER("RenderPool (Deferred)");
LLTrace::BlockTimerStatHandle FTM_DEFERRED_POOLS("Pools (Deferred)");
LLTrace::BlockTimerStatHandle FTM_POST_DEFERRED_POOLRENDER("RenderPool (Post)");
LLTrace::BlockTimerStatHandle FTM_POST_DEFERRED_POOLS("Pools (Post)");
LLTrace::BlockTimerStatHandle FTM_RENDER_BLOOM_FBO("First FBO");
LLTrace::BlockTimerStatHandle FTM_STATESORT("Sort Draw State");
LLTrace::BlockTimerStatHandle FTM_PIPELINE("Pipeline");
LLTrace::BlockTimerStatHandle FTM_CLIENT_COPY("Client Copy");
LLTrace::BlockTimerStatHandle FTM_RENDER_DEFERRED("Deferred Shading");


static LLTrace::BlockTimerStatHandle FTM_STATESORT_DRAWABLE("Sort Drawables");
static LLTrace::BlockTimerStatHandle FTM_STATESORT_POSTSORT("Post Sort");
static LLStaticHashedString sDelta("delta");
static LLStaticHashedString sDistFactor("dist_factor");
static LLStaticHashedString sScreenRes("framebuffer_res");
James Cook's avatar
James Cook committed
//----------------------------------------
std::string gPoolNames[] = 
{
	// Correspond to LLDrawpool enum render type
	"NONE",
	"POOL_SIMPLE",
David Parks's avatar
David Parks committed
	"POOL_GROUND",
	"POOL_FULLBRIGHT",
Cinder's avatar
Cinder committed
	"POOL_TERRAIN",	
	"POOL_TREE",
	"POOL_SKY",
	"POOL_WL_SKY",
	"POOL_ALPHA_MASK",
	"POOL_FULLBRIGHT_ALPHA_MASK",
David Parks's avatar
David Parks committed
	"POOL_GRASS",
David Parks's avatar
David Parks committed
	"POOL_VOIDWATER",
	"POOL_WATER",
	"POOL_GLOW",
David Parks's avatar
David Parks committed
	"POOL_ALPHA"
David Parks's avatar
David Parks committed
void drawBox(const LLVector4a& c, const LLVector4a& r);
void drawBoxOutline(const LLVector3& pos, const LLVector3& size);
LLVertexBuffer* ll_create_cube_vb(U32 type_mask, U32 usage);
Drake Arconis's avatar
Drake Arconis committed
glm::mat4 glm_copy_matrix(F32* src)
Drake Arconis's avatar
Drake Arconis committed
	return glm::make_mat4(src);
Drake Arconis's avatar
Drake Arconis committed
glm::mat4 glm_get_current_modelview()
Drake Arconis's avatar
Drake Arconis committed
	return glm_copy_matrix(gGLModelView);
Drake Arconis's avatar
Drake Arconis committed
glm::mat4 glm_get_current_projection()
Drake Arconis's avatar
Drake Arconis committed
	return glm_copy_matrix(gGLProjection);
Drake Arconis's avatar
Drake Arconis committed
glm::mat4 glm_get_last_modelview()
David Parks's avatar
David Parks committed
{
Drake Arconis's avatar
Drake Arconis committed
	return glm_copy_matrix(gGLLastModelView);
David Parks's avatar
David Parks committed
}

Drake Arconis's avatar
Drake Arconis committed
glm::mat4 glm_get_last_projection()
David Parks's avatar
David Parks committed
{
Drake Arconis's avatar
Drake Arconis committed
	return glm_copy_matrix(gGLLastProjection);
David Parks's avatar
David Parks committed
}

Drake Arconis's avatar
Drake Arconis committed
void glm_copy_matrix(const glm::mat4& src, F32* dst)
Drake Arconis's avatar
Drake Arconis committed
	memcpy(dst, glm::value_ptr(src), sizeof(F32) * 16);
Drake Arconis's avatar
Drake Arconis committed
void glm_set_current_modelview(const glm::mat4& mat)
Drake Arconis's avatar
Drake Arconis committed
	glm_copy_matrix(mat, gGLModelView);
Drake Arconis's avatar
Drake Arconis committed
void glm_set_current_projection(const glm::mat4& mat)
Drake Arconis's avatar
Drake Arconis committed
	glm_copy_matrix(mat, gGLProjection);
void display_update_camera();
James Cook's avatar
James Cook committed
//----------------------------------------

S32		LLPipeline::sCompiles = 0;
bool	LLPipeline::sPickAvatar = true;
bool	LLPipeline::sDynamicLOD = true;
bool	LLPipeline::sShowHUDAttachments = true;
bool	LLPipeline::sRenderMOAPBeacons = false;
bool	LLPipeline::sRenderPhysicalBeacons = true;
bool	LLPipeline::sRenderScriptedBeacons = false;
bool	LLPipeline::sRenderScriptedTouchBeacons = true;
bool	LLPipeline::sRenderParticleBeacons = false;
bool	LLPipeline::sRenderSoundBeacons = false;
bool	LLPipeline::sRenderBeacons = false;
bool	LLPipeline::sRenderHighlight = true;
LLRender::eTexIndex LLPipeline::sRenderHighlightTextureChannel = LLRender::DIFFUSE_MAP;
bool	LLPipeline::sForceOldBakedUpload = false;
bool	LLPipeline::sDelayVBUpdate = true;
bool	LLPipeline::sAutoMaskAlphaDeferred = true;
bool	LLPipeline::sAutoMaskAlphaNonDeferred = false;
bool	LLPipeline::sDisableShaders = false;
bool	LLPipeline::sRenderBump = true;
bool	LLPipeline::sNoAlpha = false;
bool	LLPipeline::sUseTriStrips = true;
bool	LLPipeline::sUseFarClip = true;
bool	LLPipeline::sShadowRender = false;
bool	LLPipeline::sWaterReflections = false;
bool	LLPipeline::sRenderGlow = false;
bool	LLPipeline::sReflectionRender = false;
bool	LLPipeline::sImpostorRender = false;
bool	LLPipeline::sImpostorRenderAlphaDepthPass = false;
bool	LLPipeline::sUnderWaterRender = false;
bool	LLPipeline::sTextureBindTest = false;
bool	LLPipeline::sRenderFrameTest = false;
bool	LLPipeline::sRenderAttachedLights = true;
bool	LLPipeline::sRenderAttachedParticles = true;
bool	LLPipeline::sRenderDeferred = false;
bool    LLPipeline::sMemAllocationThrottled = false;
S32		LLPipeline::sVisibleLightCount = 0;
F32		LLPipeline::sMinRenderSize = 0.f;
Drake Arconis's avatar
Drake Arconis committed
bool	LLPipeline::sRenderingHUDs = FALSE;
// [SL:KB] - Patch: Render-TextureToggle (Catznip-4.0)
bool	LLPipeline::sRenderTextures = true;
// [/SL:KB]
// EventHost API LLPipeline listener.
static LLPipelineListener sPipelineListener;
Cinder's avatar
Cinder committed
static LLCullResult* sCull = nullptr;
James Cook's avatar
James Cook committed

bool addDeferredAttachments(LLRenderTarget& target)
	return target.addColorAttachment(GL_SRGB8_ALPHA8
		, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV) && //specular
			target.addColorAttachment(GL_RGBA12, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV); //normal+z
James Cook's avatar
James Cook committed
LLPipeline::LLPipeline() :
	mBackfaceCull(false),
	mMatrixOpCount(0),
	mTextureMatrixOps(0),
	mNumVisibleNodes(0),
	mNumVisibleFaces(0),

Cinder's avatar
Cinder committed
	mScreenWidth(0),
	mScreenHeight(0),
	mInitialized(false),
	mVertexShadersEnabled(false),
James Cook's avatar
James Cook committed
	mVertexShadersLoaded(0),
	mRenderDebugFeatureMask(0),
	mRenderDebugMask(0),
	mOldRenderDebugMask(0),
David Parks's avatar
David Parks committed
	mGroupQ2Locked(false),
Cinder's avatar
Cinder committed
	mGroupQ1Locked(false),
Cinder's avatar
Cinder committed
	mLastRebuildPool(nullptr),
	mAlphaPool(nullptr),
	mSkyPool(nullptr),
	mTerrainPool(nullptr),
	mWaterPool(nullptr),
	mGroundPool(nullptr),
	mSimplePool(nullptr),
	mGrassPool(nullptr),
	mAlphaMaskPool(nullptr),
	mFullbrightAlphaMaskPool(nullptr),
	mFullbrightPool(nullptr),
	mGlowPool(nullptr),
	mBumpPool(nullptr),
	mMaterialsPool(nullptr),
	mWLSkyPool(nullptr),
James Cook's avatar
James Cook committed
	mLightMask(0),
Cinder's avatar
Cinder committed
	mLightingDetail(0)
James Cook's avatar
James Cook committed
{
	mLightFunc = 0;
Drake Arconis's avatar
Drake Arconis committed
void LLPipeline::connectRefreshCachedSettingsSafe(const std::string& name)
{
	LLPointer<LLControlVariable> cntrl_ptr = gSavedSettings.getControl(name);
	if ( cntrl_ptr.isNull() )
	{
		LL_WARNS() << "Global setting name not found:" << name << LL_ENDL;
	}
	else
	{
		cntrl_ptr->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
	}
}

James Cook's avatar
James Cook committed
void LLPipeline::init()
{
	gOctreeMaxCapacity = gSavedSettings.getU32("OctreeMaxNodeCapacity");
	gOctreeMinSize = gSavedSettings.getF32("OctreeMinimumNodeSize");
	sDynamicLOD = gSavedSettings.getBOOL("RenderDynamicLOD");
	sRenderBump = gSavedSettings.getBOOL("RenderObjectBump");
	sUseTriStrips = gSavedSettings.getBOOL("RenderUseTriStrips");
	LLVertexBuffer::sUseStreamDraw = gSavedSettings.getBOOL("RenderUseStreamVBO");
	LLVertexBuffer::sUseVAO = gSavedSettings.getBOOL("RenderUseVAO");
David Parks's avatar
David Parks committed
	LLVertexBuffer::sPreferStreamDraw = gSavedSettings.getBOOL("RenderPreferStreamDraw");
	sRenderAttachedLights = gSavedSettings.getBOOL("RenderAttachedLights");
	sRenderAttachedParticles = gSavedSettings.getBOOL("RenderAttachedParticles");
	mInitialized = true;
James Cook's avatar
James Cook committed
	
	stop_glerror();

	//create render pass pools
	getPool(LLDrawPool::POOL_ALPHA);
	getPool(LLDrawPool::POOL_SIMPLE);
	getPool(LLDrawPool::POOL_ALPHA_MASK);
	getPool(LLDrawPool::POOL_FULLBRIGHT_ALPHA_MASK);
	getPool(LLDrawPool::POOL_GRASS);
	getPool(LLDrawPool::POOL_FULLBRIGHT);
	getPool(LLDrawPool::POOL_BUMP);
	getPool(LLDrawPool::POOL_MATERIALS);
James Cook's avatar
James Cook committed
	resetFrameStats();

	if (gSavedSettings.getBOOL("DisableAllRenderFeatures"))
		setAllRenderDebugFeatures(); // By default, all debugging features on
	clearAllRenderDebugDisplays(); // All debug displays off
	if (gSavedSettings.getBOOL("DisableAllRenderTypes"))
		setAllRenderTypes(); // By default, all rendering types start enabled
		// Don't turn on ground when this is set
		// Mac Books with intel 950s need this
		if(!gSavedSettings.getBOOL("RenderGround"))
		{
			toggleRenderType(RENDER_TYPE_GROUND);
		}
David Parks's avatar
David Parks committed
	// make sure RenderPerformanceTest persists (hackity hack hack)
	// disables non-object rendering (UI, sky, water, etc)
	if (gSavedSettings.getBOOL("RenderPerformanceTest"))
	{
		gSavedSettings.setBOOL("RenderPerformanceTest", FALSE);
		gSavedSettings.setBOOL("RenderPerformanceTest", TRUE);
	}

	mOldRenderDebugMask = mRenderDebugMask;
	mBackfaceCull = true;
James Cook's avatar
James Cook committed

	stop_glerror();
	
	// Enable features
	LLViewerShaderMgr::instance()->setShaders();
	for (float& i : mSpotLightFade)
    {
        i = 1.f;
	if (mCubeVB.isNull())
	{
		mCubeVB = ll_create_cube_vb(LLVertexBuffer::MAP_VERTEX, GL_STATIC_DRAW_ARB);
	}

	setLightingDetail(-1);
	
	//
	// Update all settings to trigger a cached settings refresh
	//
	connectRefreshCachedSettingsSafe("RenderAutoMaskAlphaDeferred");
	connectRefreshCachedSettingsSafe("RenderAutoMaskAlphaNonDeferred");
	connectRefreshCachedSettingsSafe("RenderUseFarClip");
	connectRefreshCachedSettingsSafe("RenderAvatarMaxNonImpostors");
	connectRefreshCachedSettingsSafe("RenderDelayVBUpdate");
	connectRefreshCachedSettingsSafe("UseOcclusion");
	connectRefreshCachedSettingsSafe("VertexShaderEnable");
	connectRefreshCachedSettingsSafe("RenderAvatarVP");
	connectRefreshCachedSettingsSafe("WindLightUseAtmosShaders");
	connectRefreshCachedSettingsSafe("RenderDeferred");
	connectRefreshCachedSettingsSafe("RenderDeferredSunWash");
	connectRefreshCachedSettingsSafe("RenderFSAASamples");
	connectRefreshCachedSettingsSafe("RenderResolutionDivisor");
// [SL:KB] - Patch: Settings-RenderResolutionMultiplier | Checked: Catznip-5.4
	connectRefreshCachedSettingsSafe("RenderResolutionMultiplier");
// [/SL:KB]
	connectRefreshCachedSettingsSafe("RenderUIBuffer");
	connectRefreshCachedSettingsSafe("RenderShadowDetail");
	connectRefreshCachedSettingsSafe("RenderDeferredSSAO");
	connectRefreshCachedSettingsSafe("RenderDeferredSSAOResolutionScale");
	connectRefreshCachedSettingsSafe("RenderShadowResolutionScale");
	connectRefreshCachedSettingsSafe("RenderLocalLights");
	connectRefreshCachedSettingsSafe("RenderDelayCreation");
	connectRefreshCachedSettingsSafe("RenderAnimateRes");
	connectRefreshCachedSettingsSafe("FreezeTime");
	connectRefreshCachedSettingsSafe("DebugBeaconLineWidth");
	connectRefreshCachedSettingsSafe("RenderHighlightBrightness");
	connectRefreshCachedSettingsSafe("RenderHighlightColor");
	connectRefreshCachedSettingsSafe("RenderHighlightThickness");
	connectRefreshCachedSettingsSafe("RenderSpotLightsInNondeferred");
	connectRefreshCachedSettingsSafe("PreviewAmbientColor");
	connectRefreshCachedSettingsSafe("PreviewDiffuse0");
	connectRefreshCachedSettingsSafe("PreviewSpecular0");
	connectRefreshCachedSettingsSafe("PreviewDiffuse1");
	connectRefreshCachedSettingsSafe("PreviewSpecular1");
	connectRefreshCachedSettingsSafe("PreviewDiffuse2");
	connectRefreshCachedSettingsSafe("PreviewSpecular2");
	connectRefreshCachedSettingsSafe("PreviewDirection0");
	connectRefreshCachedSettingsSafe("PreviewDirection1");
	connectRefreshCachedSettingsSafe("PreviewDirection2");
	connectRefreshCachedSettingsSafe("RenderGlowMinLuminance");
	connectRefreshCachedSettingsSafe("RenderGlowMaxExtractAlpha");
	connectRefreshCachedSettingsSafe("RenderGlowWarmthAmount");
	connectRefreshCachedSettingsSafe("RenderGlowLumWeights");
	connectRefreshCachedSettingsSafe("RenderGlowWarmthWeights");
	connectRefreshCachedSettingsSafe("RenderGlowResolutionPow");
	connectRefreshCachedSettingsSafe("RenderGlowIterations");
	connectRefreshCachedSettingsSafe("RenderGlowWidth");
	connectRefreshCachedSettingsSafe("RenderGlowStrength");
	connectRefreshCachedSettingsSafe("RenderDepthOfField");
	connectRefreshCachedSettingsSafe("RenderDepthOfFieldInEditMode");
	connectRefreshCachedSettingsSafe("CameraFocusTransitionTime");
	connectRefreshCachedSettingsSafe("CameraFNumber");
	connectRefreshCachedSettingsSafe("CameraFocalLength");
	connectRefreshCachedSettingsSafe("CameraFieldOfView");
	connectRefreshCachedSettingsSafe("RenderShadowNoise");
	connectRefreshCachedSettingsSafe("RenderShadowBlurSize");
	connectRefreshCachedSettingsSafe("RenderSSAOScale");
	connectRefreshCachedSettingsSafe("RenderSSAOMaxScale");
	connectRefreshCachedSettingsSafe("RenderSSAOFactor");
	connectRefreshCachedSettingsSafe("RenderSSAOEffect");
	connectRefreshCachedSettingsSafe("RenderShadowOffsetError");
	connectRefreshCachedSettingsSafe("RenderShadowBiasError");
	connectRefreshCachedSettingsSafe("RenderShadowOffset");
	connectRefreshCachedSettingsSafe("RenderShadowBias");
	connectRefreshCachedSettingsSafe("RenderSpotShadowOffset");
	connectRefreshCachedSettingsSafe("RenderSpotShadowBias");
	connectRefreshCachedSettingsSafe("RenderEdgeDepthCutoff");
	connectRefreshCachedSettingsSafe("RenderEdgeNormCutoff");
	connectRefreshCachedSettingsSafe("RenderShadowGaussian");
	connectRefreshCachedSettingsSafe("RenderShadowBlurDistFactor");
	connectRefreshCachedSettingsSafe("RenderDeferredAtmospheric");
	connectRefreshCachedSettingsSafe("RenderReflectionDetail");
	connectRefreshCachedSettingsSafe("RenderHighlightFadeTime");
	connectRefreshCachedSettingsSafe("RenderShadowClipPlanes");
	connectRefreshCachedSettingsSafe("RenderShadowOrthoClipPlanes");
	connectRefreshCachedSettingsSafe("RenderShadowNearDist");
	connectRefreshCachedSettingsSafe("RenderFarClip");
	connectRefreshCachedSettingsSafe("RenderShadowSplitExponent");
	connectRefreshCachedSettingsSafe("RenderShadowErrorCutoff");
	connectRefreshCachedSettingsSafe("RenderShadowFOVCutoff");
	connectRefreshCachedSettingsSafe("CameraOffset");
	connectRefreshCachedSettingsSafe("CameraMaxCoF");
	connectRefreshCachedSettingsSafe("CameraDoFResScale");
	connectRefreshCachedSettingsSafe("RenderAutoHideSurfaceAreaLimit");
	connectRefreshCachedSettingsSafe("RenderDeferredAlwaysSoftenShadows");
	connectRefreshCachedSettingsSafe("RenderAggressiveBatching");
	connectRefreshCachedSettingsSafe("RenderDeferredFullbright");
James Cook's avatar
James Cook committed
}

LLPipeline::~LLPipeline()
{

}

void LLPipeline::cleanup()
{
James Cook's avatar
James Cook committed
	for(pool_set_t::iterator iter = mPools.begin();
		iter != mPools.end(); )
	{
		pool_set_t::iterator curiter = iter++;
		LLDrawPool* poolp = *curiter;
		if (poolp->isFacePool())
		{
			LLFacePool* face_pool = (LLFacePool*) poolp;
			if (face_pool->mReferences.empty())
			{
				mPools.erase(curiter);
				removeFromQuickLookup( poolp );
				delete poolp;
			}
		}
		else
James Cook's avatar
James Cook committed
		{
			mPools.erase(curiter);
			removeFromQuickLookup( poolp );
			delete poolp;
		}
	}
	
	if (!mTerrainPools.empty())
	{
		LL_WARNS() << "Terrain Pools not cleaned up" << LL_ENDL;
James Cook's avatar
James Cook committed
	}
	if (!mTreePools.empty())
	{
		LL_WARNS() << "Tree Pools not cleaned up" << LL_ENDL;
James Cook's avatar
James Cook committed
	}
James Cook's avatar
James Cook committed
	delete mAlphaPool;
Cinder's avatar
Cinder committed
	mAlphaPool = nullptr;
James Cook's avatar
James Cook committed
	delete mSkyPool;
Cinder's avatar
Cinder committed
	mSkyPool = nullptr;
James Cook's avatar
James Cook committed
	delete mTerrainPool;
Cinder's avatar
Cinder committed
	mTerrainPool = nullptr;
James Cook's avatar
James Cook committed
	delete mWaterPool;
Cinder's avatar
Cinder committed
	mWaterPool = nullptr;
James Cook's avatar
James Cook committed
	delete mGroundPool;
Cinder's avatar
Cinder committed
	mGroundPool = nullptr;
Cinder's avatar
Cinder committed
	mSimplePool = nullptr;
Cinder's avatar
Cinder committed
	mFullbrightPool = nullptr;
Cinder's avatar
Cinder committed
	mGlowPool = nullptr;
Cinder's avatar
Cinder committed
	mBumpPool = nullptr;
	// don't delete wl sky pool it was handled above in the for loop
	//delete mWLSkyPool;
Cinder's avatar
Cinder committed
	mWLSkyPool = nullptr;
James Cook's avatar
James Cook committed

James Cook's avatar
James Cook committed

Cinder's avatar
Cinder committed
	mFaceSelectImagep = nullptr;
James Cook's avatar
James Cook committed

	mMovedBridge.clear();
	mInitialized = false;
Cinder's avatar
Cinder committed
	mAuxScreenRectVB = nullptr;
	mCubeVB = nullptr;
//============================================================================
James Cook's avatar
James Cook committed

void LLPipeline::destroyGL() 
James Cook's avatar
James Cook committed
{
	stop_glerror();
	unloadShaders();
	mHighlightFaces.clear();
	resetVertexBuffers();
James Cook's avatar
James Cook committed

		LLVertexBuffer::sEnableVBOs = FALSE;

	if (mMeshDirtyQueryObject)
	{
		glDeleteQueriesARB(1, &mMeshDirtyQueryObject);
		mMeshDirtyQueryObject = 0;
	}
static LLTrace::BlockTimerStatHandle FTM_RESIZE_SCREEN_TEXTURE("Resize Screen Texture");
void LLPipeline::throttleNewMemoryAllocation(bool disable)
{
	if(sMemAllocationThrottled != disable)
	{
		sMemAllocationThrottled = disable ;

		if(sMemAllocationThrottled)
		{
			//send out notification
			LLNotification::Params params("LowMemory");
			LLNotifications::instance().add(params);

			//release some memory.
		}
	}
}

void LLPipeline::resizeScreenTexture()
{
	LL_RECORD_BLOCK_TIME(FTM_RESIZE_SCREEN_TEXTURE);
	if (gPipeline.canUseVertexShaders() && assertInitialized())
David Parks's avatar
David Parks committed
		GLuint resX = gViewerWindow->getWorldViewWidthRaw();
		GLuint resY = gViewerWindow->getWorldViewHeightRaw();
// [SL:KB] - Patch: Settings-RenderResolutionMultiplier | Checked: Catznip-5.4
		if ( (RenderResolutionDivisor > 1) && (RenderResolutionDivisor < resX) && (RenderResolutionDivisor < resY) )
			resX /= RenderResolutionDivisor;
			resY /= RenderResolutionDivisor;
		else if (RenderResolutionMultiplier != 1.f)
		{
			resX *= RenderResolutionMultiplier;
			resY *= RenderResolutionMultiplier;
		}
// [/SL:KB]
		if ((resX != mScreen.getWidth()) || (resY != mScreen.getHeight()))
		{
			releaseScreenBuffers();
		if (!allocateScreenBuffer(resX,resY))
#if PROBABLE_FALSE_DISABLES_OF_ALM_HERE
				//FAILSAFE: screen buffer allocation failed, disable deferred rendering if it's enabled
			//NOTE: if the session closes successfully after this call, deferred rendering will be 
			// disabled on future sessions
			if (LLPipeline::sRenderDeferred)
			{
				gSavedSettings.setBOOL("RenderDeferred", FALSE);
				LLPipeline::refreshCachedSettings();
James Cook's avatar
James Cook committed
	}
David Parks's avatar
David Parks committed
void LLPipeline::allocatePhysicsBuffer()
{
	GLuint resX = gViewerWindow->getWorldViewWidthRaw();
	GLuint resY = gViewerWindow->getWorldViewHeightRaw();

	if (mPhysicsDisplay.getWidth() != resX || mPhysicsDisplay.getHeight() != resY)
	{
		mPhysicsDisplay.allocate(resX, resY, GL_RGBA, TRUE, FALSE, LLTexUnit::TT_TEXTURE, FALSE, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV);
David Parks's avatar
David Parks committed
	}
}

bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY)
	//bool save_settings = sRenderDeferred;
	//if (save_settings)
	//{
	//	// Set this flag in case we crash while resizing window or allocating space for deferred rendering targets
	//	gSavedSettings.setBOOL("RenderInitError", TRUE);
	//	gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile"), TRUE );
	//}
	eFBOStatus ret = doAllocateScreenBuffer(resX, resY);
David Parks's avatar
David Parks committed

	//if (save_settings)
	//{
	//	// don't disable shaders on next session
	//	gSavedSettings.setBOOL("RenderInitError", FALSE);
	//	gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile"), TRUE );
	//}
	if (ret == FBO_FAILURE)
	{ //FAILSAFE: screen buffer allocation failed, disable deferred rendering if it's enabled
		//NOTE: if the session closes successfully after this call, deferred rendering will be 
		// disabled on future sessions
		if (LLPipeline::sRenderDeferred)
		{
			gSavedSettings.setBOOL("RenderDeferred", FALSE);
			LLPipeline::refreshCachedSettings();
		}
	}

	return ret == FBO_SUCCESS_FULLRES;
David Parks's avatar
David Parks committed

LLPipeline::eFBOStatus LLPipeline::doAllocateScreenBuffer(U32 resX, U32 resY)
	// try to allocate screen buffers at requested resolution and samples
	// - on failure, shrink number of samples and try again
	// - if not multisampled, shrink resolution and try again (favor X resolution over Y)
	// Make sure to call "releaseScreenBuffers" after each failure to cleanup the partially loaded state

	eFBOStatus ret = FBO_SUCCESS_FULLRES;
	if (!allocateScreenBuffer(resX, resY, samples))
	{
		//failed to allocate at requested specification, return false
		releaseScreenBuffers();
		//reduce number of samples 
		while (samples > 0)
		{
			samples /= 2;
			if (allocateScreenBuffer(resX, resY, samples))
			{ //success
		//reduce resolution
		while (resY > 0 && resX > 0)
		{
			resY /= 2;
			if (allocateScreenBuffer(resX, resY, samples))
			{
			}
			releaseScreenBuffers();

			resX /= 2;
			if (allocateScreenBuffer(resX, resY, samples))
			{
		LL_WARNS() << "Unable to allocate screen buffer at any resolution!" << LL_ENDL;
}

bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)
{
Cinder's avatar
Cinder committed
	mAuxScreenRectVB = nullptr;
	// remember these dimensions
	mScreenWidth = resX;
	mScreenHeight = resY;
	
	U32 res_mod = RenderResolutionDivisor;
David Parks's avatar
David Parks committed

	if (res_mod > 1 && res_mod < resX && res_mod < resY)
	{
		resX /= res_mod;
		resY /= res_mod;
	}
// [SL:KB] - Patch: Settings-RenderResolutionMultiplier | Checked: Catznip-5.4
	else if (RenderResolutionMultiplier != 1.f)
	{
		resX *= RenderResolutionMultiplier;
		resY *= RenderResolutionMultiplier;
	}
// [/SL:KB]
		if (!mUIScreen.allocate(resX,resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_TEXTURE, FALSE, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV))
	if (LLPipeline::sRenderDeferred)
James Cook's avatar
James Cook committed
	{
		S32 shadow_detail = RenderShadowDetail;
		bool ssao = RenderDeferredSSAO;
		//allocate deferred rendering color buffers
		if (!mDeferredScreen.allocate(resX, resY, GL_SRGB8_ALPHA8, TRUE, TRUE, LLTexUnit::TT_TEXTURE, FALSE, samples, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV)) return false;
		if (!mDeferredDepth.allocate(resX, resY, 0, TRUE, FALSE, LLTexUnit::TT_TEXTURE, FALSE, samples)) return false;
		if (!addDeferredAttachments(mDeferredScreen)) return false;
		GLuint pixFormat = GL_BGRA;
		GLuint pixType = GL_UNSIGNED_INT_8_8_8_8_REV;
		if (gGLManager.mIsATI)
		{
			screenFormat = GL_RGBA12;
		}

		if (gGLManager.mGLVersion < 4.f && gGLManager.mIsNVIDIA)
		{
			screenFormat = GL_RGBA16F_ARB;
		if (!mScreen.allocate(resX, resY, screenFormat, FALSE, FALSE, LLTexUnit::TT_TEXTURE, FALSE, samples, pixFormat, pixType)) return false;
		if (!mFinalScreen.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_TEXTURE, FALSE, samples, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV)) return false;
			if (!mFXAABuffer.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_TEXTURE, FALSE, samples, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV)) return false;
David Parks's avatar
David Parks committed
		}
		else
David Parks's avatar
David Parks committed
		}
		if (shadow_detail > 0 || ssao || RenderDepthOfField || samples > 0)
		{ //only need mDeferredLight for shadows OR ssao OR dof OR fxaa
			if (!mDeferredLight.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_TEXTURE, FALSE, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV)) return false;
			if(ssao)
			{
				F32 scale = llclamp(RenderDeferredSSAOResolutionScale, 0.01f, 1.f);
				if( scale < 1.f && !mDeferredDownsampledDepth.allocate(llceil(F32(resX)*scale), llceil(F32(resY)*scale), 0, TRUE, FALSE, LLTexUnit::TT_TEXTURE, FALSE) ) return false;
David Parks's avatar
David Parks committed
		}
		else
		{
		F32 scale = llmax(0.f, RenderShadowResolutionScale);
David Parks's avatar
David Parks committed
		if (shadow_detail > 0)
		{ //allocate 4 sun shadow maps
			U32 sun_shadow_map_width = ((U32(resX*scale)+1)&~1); // must be even to avoid a stripe in the horizontal shadow blur
David Parks's avatar
David Parks committed
			for (U32 i = 0; i < 4; i++)
			{