diff --git a/autobuild.xml b/autobuild.xml
index ac4735ce446242e3b221316dfdb7a6cfa0d883a8..2ff33714b11973988a618c0778096baafe8ac183 100644
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -1110,9 +1110,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>49f3d038379af818f9fc8f57cc4e313f</string>
+              <string>e26b6d955394e079a151ad3b0d7d5c90</string>
               <key>url</key>
-              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/stinson_llpathinglibrary/rev/248427/arch/Linux/installer/llphysicsextensions-0.1-linux-20120126.tar.bz2</string>
+              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/stinson_llpathinglibrary/rev/248566/arch/Linux/installer/llphysicsextensions-0.1-linux-20120127.tar.bz2</string>
             </map>
             <key>name</key>
             <string>linux</string>
@@ -1122,9 +1122,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>573a0daa04bde79bd7b7b338984dfbf3</string>
+              <string>0afb3d1e08c56c74db31ae3e78640abc</string>
               <key>url</key>
-              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/stinson_llpathinglibrary/rev/248427/arch/CYGWIN/installer/llphysicsextensions-0.1-windows-20120125.tar.bz2</string>
+              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/stinson_llpathinglibrary/rev/248567/arch/CYGWIN/installer/llphysicsextensions-0.1-windows-20120127.tar.bz2</string>
             </map>
             <key>name</key>
             <string>windows</string>
diff --git a/indra/cmake/LLPhysicsExtensions.cmake b/indra/cmake/LLPhysicsExtensions.cmake
index 598ac728495f422df66058707dae3e3a96169d8c..53972e050a91ff88e29c5b4fea1f2dc50dfd164f 100644
--- a/indra/cmake/LLPhysicsExtensions.cmake
+++ b/indra/cmake/LLPhysicsExtensions.cmake
@@ -1,14 +1,21 @@
 # -*- cmake -*-
 include(Prebuilt)
 
-use_prebuilt_binary(llphysicsextensions)
+if (INSTALL_PROPRIETARY AND NOT STANDALONE)
+   use_prebuilt_binary(llphysicsextensions)
+   set(LLPHYSICS_EXTENSIONS_LIB_NAME llphysicsextensions)
+else (INSTALL_PROPRIETARY AND NOT STANDALONE)
+  use_prebuilt_binary(llphysicsextensionsstub)
+  set(LLPHYSICS_EXTENSIONS_LIB_NAME llphysicsextensionsstub)
+endif (INSTALL_PROPRIETARY AND NOT STANDALONE)
+
 set(LLPHYSICS_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/lib/include)
 
 set(LLPHYSICS_DEBUG_LIBRARY_PATH ${LIBS_PREBUILT_DIR}/lib/debug)
 set(LLPHYSICS_RELEASE_LIBRARY_PATH ${LIBS_PREBUILT_DIR}/lib/release)
 
-find_library(LL_PHYSICS_DEBUG_LIB llphysicsextensions PATHS ${LLPHYSICS_DEBUG_LIBRARY_PATH})
-find_library(LL_PHYSICS_RELEASE_LIB llphysicsextensions PATHS ${LLPHYSICS_RELEASE_LIBRARY_PATH})
+find_library(LL_PHYSICS_DEBUG_LIB ${LLPHYSICS_EXTENSIONS_LIB_NAME} PATHS ${LLPHYSICS_DEBUG_LIBRARY_PATH})
+find_library(LL_PHYSICS_RELEASE_LIB ${LLPHYSICS_EXTENSIONS_LIB_NAME} PATHS ${LLPHYSICS_RELEASE_LIBRARY_PATH})
 
 set(LLPHYSICS_LIBRARIES
 
@@ -21,11 +28,3 @@ if (LINUX)
     list(APPEND LLPHYSICS_LIBRARIES -Wl,--end-group)
 endif (LINUX)
 
-# if (INSTALL_PROPRIETARY AND NOT STANDALONE)
-#   use_prebuilt_binary(llconvexdecomposition)
-#   set(LLCONVEXDECOMP_LIBRARY llconvexdecomposition)
-# else (INSTALL_PROPRIETARY AND NOT STANDALONE)
-#  use_prebuilt_binary(llconvexdecompositionstub)
-#  set(LLCONVEXDECOMP_LIBRARY llconvexdecompositionstub)
-# endif (INSTALL_PROPRIETARY AND NOT STANDALONE)
-
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index a455d359bfce352479c52872c78a6b475c24bc3b..85e6cd3d3fb316e877dc08724e24848ed8bb0b93 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -106,6 +106,7 @@
 #include "llvfsthread.h"
 #include "llvolumemgr.h"
 #include "llxfermanager.h"
+#include "llphysicsextensions.h"
 
 #include "llnotificationmanager.h"
 #include "llnotifications.h"
@@ -1543,6 +1544,9 @@ bool LLAppViewer::cleanup()
 	// shut down mesh streamer
 	gMeshRepo.shutdown();
 
+	// shut down Havok
+	LLPhysicsExtensions::quitSystem();
+
 	// Must clean up texture references before viewer window is destroyed.
 	if(LLHUDManager::instanceExists())
 	{
diff --git a/indra/newview/llfloaterpathfindingconsole.cpp b/indra/newview/llfloaterpathfindingconsole.cpp
index 772f42860f177078bfef205627b2be71220251b3..fce67c4171792f118ac15c496212dcaa7b24d18c 100644
--- a/indra/newview/llfloaterpathfindingconsole.cpp
+++ b/indra/newview/llfloaterpathfindingconsole.cpp
@@ -1,621 +1,621 @@
-/** 
-* @file llfloaterpathfindingconsole.cpp
-* @author William Todd Stinson
-* @brief "Pathfinding console" floater, allowing manipulation of the Havok AI pathfinding settings.
-*
-* $LicenseInfo:firstyear=2002&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$
-*/
-
-#include "llviewerprecompiledheaders.h"
-#include "llfloaterpathfindingconsole.h"
-#include "llfloaterpathfindinglinksets.h"
-
-#include "llsd.h"
-#include "llagent.h"
-#include "llbutton.h"
-#include "llradiogroup.h"
-#include "llsliderctrl.h"
-#include "lllineeditor.h"
-#include "lltextbase.h"
-#include "lltextvalidate.h"
-#include "llnavmeshstation.h"
-#include "llviewerregion.h"
-
-#include "llphysicsextensions.h"
-
-#define XUI_RENDER_OVERLAY_ON_FIXED_PHYSICS_GEOMETRY 1
-#define XUI_RENDER_OVERLAY_ON_ALL_RENDERABLE_GEOMETRY 2
-
-#define XUI_PATH_SELECT_NONE 0
-#define XUI_PATH_SELECT_START_POINT 1
-#define XUI_PATH_SELECT_END_POINT 2
-
-#define XUI_CHARACTER_TYPE_A 1
-#define XUI_CHARACTER_TYPE_B 2
-#define XUI_CHARACTER_TYPE_C 3
-#define XUI_CHARACTER_TYPE_D 4
-
-const int CURRENT_REGION = 99;
-const int MAX_OBSERVERS = 10;
-//---------------------------------------------------------------------------
-// LLFloaterPathfindingConsole
-//---------------------------------------------------------------------------
-
-BOOL LLFloaterPathfindingConsole::postBuild()
-{
-	childSetAction("view_and_edit_linksets", boost::bind(&LLFloaterPathfindingConsole::onViewEditLinksetClicked, this));
-	childSetAction("rebuild_navmesh", boost::bind(&LLFloaterPathfindingConsole::onRebuildNavMeshClicked, this));
-	childSetAction("refresh_navmesh", boost::bind(&LLFloaterPathfindingConsole::onRefreshNavMeshClicked, this));
-
-	mShowNavMeshCheckBox = findChild<LLCheckBoxCtrl>("show_navmesh_overlay");
-	llassert(mShowNavMeshCheckBox != NULL);
-	mShowNavMeshCheckBox->setCommitCallback(boost::bind(&LLFloaterPathfindingConsole::onShowNavMeshToggle, this));
-
-	mShowExcludeVolumesCheckBox = findChild<LLCheckBoxCtrl>("show_exclusion_volumes");
-	llassert(mShowExcludeVolumesCheckBox != NULL);
-	mShowExcludeVolumesCheckBox->setCommitCallback(boost::bind(&LLFloaterPathfindingConsole::onShowExcludeVolumesToggle, this));
-
-	mShowPathCheckBox = findChild<LLCheckBoxCtrl>("show_path");
-	llassert(mShowPathCheckBox != NULL);
-	mShowPathCheckBox->setCommitCallback(boost::bind(&LLFloaterPathfindingConsole::onShowPathToggle, this));
-
-	mShowWaterPlaneCheckBox = findChild<LLCheckBoxCtrl>("show_water_plane");
-	llassert(mShowWaterPlaneCheckBox != NULL);
-	mShowWaterPlaneCheckBox->setCommitCallback(boost::bind(&LLFloaterPathfindingConsole::onShowWaterPlaneToggle, this));
-
-	mRegionOverlayDisplayRadioGroup = findChild<LLRadioGroup>("region_overlay_display");
-	llassert(mRegionOverlayDisplayRadioGroup != NULL);
-	mRegionOverlayDisplayRadioGroup->setCommitCallback(boost::bind(&LLFloaterPathfindingConsole::onRegionOverlayDisplaySwitch, this));
-
-	mPathSelectionRadioGroup = findChild<LLRadioGroup>("path_selection");
-	llassert(mPathSelectionRadioGroup  != NULL);
-	mPathSelectionRadioGroup ->setCommitCallback(boost::bind(&LLFloaterPathfindingConsole::onPathSelectionSwitch, this));
-
-	mCharacterWidthSlider = findChild<LLSliderCtrl>("character_width");
-	llassert(mCharacterWidthSlider != NULL);
-	mCharacterWidthSlider->setCommitCallback(boost::bind(&LLFloaterPathfindingConsole::onCharacterWidthSet, this));
-
-	mCharacterTypeRadioGroup = findChild<LLRadioGroup>("character_type");
-	llassert(mCharacterTypeRadioGroup  != NULL);
-	mCharacterTypeRadioGroup->setCommitCallback(boost::bind(&LLFloaterPathfindingConsole::onCharacterTypeSwitch, this));
-
-	mPathfindingStatus = findChild<LLTextBase>("pathfinding_status");
-	llassert(mPathfindingStatus != NULL);
-
-	mTerrainMaterialA = findChild<LLLineEditor>("terrain_material_a");
-	llassert(mTerrainMaterialA != NULL);
-	mTerrainMaterialA->setCommitCallback(boost::bind(&LLFloaterPathfindingConsole::onTerrainMaterialASet, this));
-	mTerrainMaterialA->setPrevalidate(LLTextValidate::validateFloat);
-
-	mTerrainMaterialB = findChild<LLLineEditor>("terrain_material_b");
-	llassert(mTerrainMaterialB != NULL);
-	mTerrainMaterialB->setCommitCallback(boost::bind(&LLFloaterPathfindingConsole::onTerrainMaterialBSet, this));
-	mTerrainMaterialB->setPrevalidate(LLTextValidate::validateFloat);
-
-	mTerrainMaterialC = findChild<LLLineEditor>("terrain_material_c");
-	llassert(mTerrainMaterialC != NULL);
-	mTerrainMaterialC->setCommitCallback(boost::bind(&LLFloaterPathfindingConsole::onTerrainMaterialCSet, this));
-	mTerrainMaterialC->setPrevalidate(LLTextValidate::validateFloat);
-
-	mTerrainMaterialD = findChild<LLLineEditor>("terrain_material_d");
-	llassert(mTerrainMaterialD != NULL);
-	mTerrainMaterialD->setCommitCallback(boost::bind(&LLFloaterPathfindingConsole::onTerrainMaterialDSet, this));
-	mTerrainMaterialD->setPrevalidate(LLTextValidate::validateFloat);
-
-	return LLFloater::postBuild();
-}
-
-LLFloaterPathfindingConsole::ERegionOverlayDisplay LLFloaterPathfindingConsole::getRegionOverlayDisplay() const
-{
-	ERegionOverlayDisplay regionOverlayDisplay;
-	switch (mRegionOverlayDisplayRadioGroup->getValue().asInteger())
-	{
-	case XUI_RENDER_OVERLAY_ON_FIXED_PHYSICS_GEOMETRY :
-		regionOverlayDisplay = kRenderOverlayOnFixedPhysicsGeometry;
-		break;
-	case XUI_RENDER_OVERLAY_ON_ALL_RENDERABLE_GEOMETRY :
-		regionOverlayDisplay = kRenderOverlayOnAllRenderableGeometry;
-		break;
-	default :
-		regionOverlayDisplay = kRenderOverlayOnFixedPhysicsGeometry;
-		llassert(0);
-		break;
-	}
-
-	return regionOverlayDisplay;
-}
-
-void LLFloaterPathfindingConsole::setRegionOverlayDisplay(ERegionOverlayDisplay pRegionOverlayDisplay)
-{
-	LLSD radioGroupValue;
-
-	switch (pRegionOverlayDisplay)
-	{
-	case kRenderOverlayOnFixedPhysicsGeometry :
-		radioGroupValue = XUI_RENDER_OVERLAY_ON_FIXED_PHYSICS_GEOMETRY;
-		break;
-	case kRenderOverlayOnAllRenderableGeometry :
-		radioGroupValue = XUI_RENDER_OVERLAY_ON_ALL_RENDERABLE_GEOMETRY;
-		break;
-	default :
-		radioGroupValue = XUI_RENDER_OVERLAY_ON_FIXED_PHYSICS_GEOMETRY;
-		llassert(0);
-		break;
-	}
-
-	mRegionOverlayDisplayRadioGroup->setValue(radioGroupValue);
-}
-
-LLFloaterPathfindingConsole::EPathSelectionState LLFloaterPathfindingConsole::getPathSelectionState() const
-{
-	EPathSelectionState pathSelectionState;
-
-	switch (mPathSelectionRadioGroup->getValue().asInteger())
-	{
-	case XUI_PATH_SELECT_START_POINT :
-		pathSelectionState = kPathSelectStartPoint;
-		break;
-	case XUI_PATH_SELECT_END_POINT :
-		pathSelectionState = kPathSelectEndPoint;
-		break;
-	default :
-		pathSelectionState = kPathSelectNone;
-		break;
-	}
-
-	return pathSelectionState;
-}
-
-void LLFloaterPathfindingConsole::setPathSelectionState(EPathSelectionState pPathSelectionState)
-{
-	LLSD radioGroupValue;
-
-	switch (pPathSelectionState)
-	{
-	case kPathSelectStartPoint :
-		radioGroupValue = XUI_PATH_SELECT_START_POINT;
-		break;
-	case kPathSelectEndPoint :
-		radioGroupValue = XUI_PATH_SELECT_END_POINT;
-		break;
-	default :
-		radioGroupValue = XUI_PATH_SELECT_NONE;
-		break;
-	}
-
-	mPathSelectionRadioGroup->setValue(radioGroupValue);
-}
-
-F32 LLFloaterPathfindingConsole::getCharacterWidth() const
-{
-	return mCharacterWidthSlider->getValueF32();
-}
-
-void LLFloaterPathfindingConsole::setCharacterWidth(F32 pCharacterWidth)
-{
-	mCharacterWidthSlider->setValue(LLSD(pCharacterWidth));
-}
-
-LLFloaterPathfindingConsole::ECharacterType LLFloaterPathfindingConsole::getCharacterType() const
-{
-	ECharacterType characterType;
-
-	switch (mCharacterTypeRadioGroup->getValue().asInteger())
-	{
-	case XUI_CHARACTER_TYPE_A :
-		characterType = kCharacterTypeA;
-		break;
-	case XUI_CHARACTER_TYPE_B :
-		characterType = kCharacterTypeB;
-		break;
-	case XUI_CHARACTER_TYPE_C :
-		characterType = kCharacterTypeC;
-		break;
-	case XUI_CHARACTER_TYPE_D :
-		characterType = kCharacterTypeD;
-		break;
-	default :
-		characterType = kCharacterTypeA;
-		llassert(0);
-		break;
-	}
-
-	return characterType;
-}
-
-void LLFloaterPathfindingConsole::setCharacterType(ECharacterType pCharacterType)
-{
-	LLSD radioGroupValue;
-
-	switch (pCharacterType)
-	{
-	case kCharacterTypeA :
-		radioGroupValue = XUI_CHARACTER_TYPE_A;
-		break;
-	case kCharacterTypeB :
-		radioGroupValue = XUI_CHARACTER_TYPE_B;
-		break;
-	case kCharacterTypeC :
-		radioGroupValue = XUI_CHARACTER_TYPE_C;
-		break;
-	case kCharacterTypeD :
-		radioGroupValue = XUI_CHARACTER_TYPE_D;
-		break;
-	default :
-		radioGroupValue = XUI_CHARACTER_TYPE_A;
-		llassert(0);
-		break;
-	}
-
-	mCharacterTypeRadioGroup->setValue(radioGroupValue);
-}
-
-F32 LLFloaterPathfindingConsole::getTerrainMaterialA() const
-{
-	return mTerrainMaterialA->getValue().asReal();
-}
-
-void LLFloaterPathfindingConsole::setTerrainMaterialA(F32 pTerrainMaterial)
-{
-	mTerrainMaterialA->setValue(LLSD(pTerrainMaterial));
-}
-
-F32 LLFloaterPathfindingConsole::getTerrainMaterialB() const
-{
-	return mTerrainMaterialB->getValue().asReal();
-}
-
-void LLFloaterPathfindingConsole::setTerrainMaterialB(F32 pTerrainMaterial)
-{
-	mTerrainMaterialB->setValue(LLSD(pTerrainMaterial));
-}
-
-F32 LLFloaterPathfindingConsole::getTerrainMaterialC() const
-{
-	return mTerrainMaterialC->getValue().asReal();
-}
-
-void LLFloaterPathfindingConsole::setTerrainMaterialC(F32 pTerrainMaterial)
-{
-	mTerrainMaterialC->setValue(LLSD(pTerrainMaterial));
-}
-
-F32 LLFloaterPathfindingConsole::getTerrainMaterialD() const
-{
-	return mTerrainMaterialD->getValue().asReal();
-}
-
-void LLFloaterPathfindingConsole::setTerrainMaterialD(F32 pTerrainMaterial)
-{
-	mTerrainMaterialD->setValue(LLSD(pTerrainMaterial));
-}
-
-void LLFloaterPathfindingConsole::setHasNavMeshReceived()
-{
-	std::string str = getString("navmesh_fetch_complete_available");
-	mPathfindingStatus->setText((LLStringExplicit)str);
-}
-
-void LLFloaterPathfindingConsole::setHasNoNavMesh()
-{
-	std::string str = getString("navmesh_fetch_complete_none");
-	mPathfindingStatus->setText((LLStringExplicit)str);
-}
-
-LLFloaterPathfindingConsole::LLFloaterPathfindingConsole(const LLSD& pSeed)
-	: LLFloater(pSeed),
-	mShowNavMeshCheckBox(NULL),
-	mShowExcludeVolumesCheckBox(NULL),
-	mShowPathCheckBox(NULL),
-	mShowWaterPlaneCheckBox(NULL),
-	mRegionOverlayDisplayRadioGroup(NULL),
-	mPathSelectionRadioGroup(NULL),
-	mCharacterWidthSlider(NULL),
-	mCharacterTypeRadioGroup(NULL),
-	mPathfindingStatus(NULL),
-	mTerrainMaterialA(NULL),
-	mTerrainMaterialB(NULL),
-	mTerrainMaterialC(NULL),
-	mTerrainMaterialD(NULL)
-{
-	for (int i=0;i<MAX_OBSERVERS;++i)
-	{
-		mNavMeshDownloadObserver[i].setPathfindingConsole(this);
-	}
-}
-
-LLFloaterPathfindingConsole::~LLFloaterPathfindingConsole()
-{
-}
-
-void LLFloaterPathfindingConsole::onOpen(const LLSD& pKey)
-{
-	//make sure we have a pathing system
-	if ( !LLPathingLib::getInstance() )
-	{
-		LLPathingLib::initSystem();
-	}
-	//prep# test remove
-	//LLSD content;
-	//LLPathingLib::getInstance()->extractNavMeshSrcFromLLSD( content );
-	//return true;
-	//prep# end test
-	if ( LLPathingLib::getInstance() == NULL )
-	{ 
-		std::string str = getString("navmesh_library_not_implemented");
-		LLStyle::Params styleParams;
-		styleParams.color = LLUIColorTable::instance().getColor("DrYellow");
-		mPathfindingStatus->setText((LLStringExplicit)str, styleParams);
-		llwarns <<"Errror: cannout find pathing library implementation."<<llendl;
-	}
-	else
-	{		
-		mCurrentMDO = 0;
-		//make sure the region is essentially enabled for navmesh support
-		std::string capability = "RetrieveNavMeshSrc";
-
-		//prep# neighboring navmesh support proto
-		LLViewerRegion* pCurrentRegion = gAgent.getRegion();
-		std::vector<LLViewerRegion*> regions;
-		regions.push_back( pCurrentRegion );
-		//pCurrentRegion->getNeighboringRegions( regions );
-
-		std::vector<int> shift;
-		shift.push_back( CURRENT_REGION );
-		//pCurrentRegion->getNeighboringRegionsStatus( shift );
-
-		int regionCnt = regions.size();
-		for ( int i=0; i<regionCnt; ++i )
-		{
-			std::string url = regions[i]->getCapability( capability );
-
-			if ( !url.empty() )
-			{
-				std::string str = getString("navmesh_fetch_inprogress");
-				mPathfindingStatus->setText((LLStringExplicit)str);
-				LLNavMeshStation::getInstance()->setNavMeshDownloadURL( url );
-				int dir = shift[i];
-				LLNavMeshStation::getInstance()->downloadNavMeshSrc( mNavMeshDownloadObserver[mCurrentMDO].getObserverHandle(), dir );				
-				++mCurrentMDO;
-			}				
-			else
-			{
-				std::string str = getString("navmesh_region_not_enabled");
-				LLStyle::Params styleParams;
-				styleParams.color = LLUIColorTable::instance().getColor("DrYellow");
-				mPathfindingStatus->setText((LLStringExplicit)str, styleParams);
-				llinfos<<"Region has does not required caps of type ["<<capability<<"]"<<llendl;
-			}
-		}
-	}		
-}
-
-void LLFloaterPathfindingConsole::onShowNavMeshToggle()
-{
-	BOOL checkBoxValue = mShowNavMeshCheckBox->get();
-
-	LLPathingLib *llPathingLibInstance = LLPathingLib::getInstance();
-	if (llPathingLibInstance != NULL)
-	{
-		llPathingLibInstance->setRenderNavMesh(checkBoxValue);
-	}
-	else
-	{
-		mShowNavMeshCheckBox->set(FALSE);
-		llwarns << "cannot find LLPathingLib instance" << llendl;
-	}
-}
-
-void LLFloaterPathfindingConsole::onShowExcludeVolumesToggle()
-{
-	BOOL checkBoxValue = mShowExcludeVolumesCheckBox->get();
-
-	LLPathingLib *llPathingLibInstance = LLPathingLib::getInstance();
-	if (llPathingLibInstance != NULL)
-	{
-		llPathingLibInstance->setRenderNavMeshandShapes(checkBoxValue);
-	}
-	else
-	{
-		mShowExcludeVolumesCheckBox->set(FALSE);
-		llwarns << "cannot find LLPathingLib instance" << llendl;
-	}
-}
-
-void LLFloaterPathfindingConsole::onShowPathToggle()
-{
-	BOOL checkBoxValue = mShowPathCheckBox->get();
-
-	llwarns << "functionality has not yet been implemented to toggle '"
-		<< mShowPathCheckBox->getLabel() << "' to "
-		<< (checkBoxValue ? "ON" : "OFF") << llendl;
-}
-
-void LLFloaterPathfindingConsole::onShowWaterPlaneToggle()
-{
-	BOOL checkBoxValue = mShowWaterPlaneCheckBox->get();
-
-	llwarns << "functionality has not yet been implemented to toggle '"
-		<< mShowWaterPlaneCheckBox->getLabel() << "' to "
-		<< (checkBoxValue ? "ON" : "OFF") << llendl;
-}
-
-void LLFloaterPathfindingConsole::onRegionOverlayDisplaySwitch()
-{
-	switch (getRegionOverlayDisplay())
-	{
-	case kRenderOverlayOnFixedPhysicsGeometry :
-		llwarns << "functionality has not yet been implemented to toggle '"
-			<< mRegionOverlayDisplayRadioGroup->getName() << "' to RenderOverlayOnFixedPhysicsGeometry"
-			<< llendl;
-		break;
-	case kRenderOverlayOnAllRenderableGeometry :
-		llwarns << "functionality has not yet been implemented to toggle '"
-			<< mRegionOverlayDisplayRadioGroup->getName() << "' to RenderOverlayOnAllRenderableGeometry"
-			<< llendl;
-		break;
-	default :
-		llassert(0);
-		break;
-	}
-}
-
-void LLFloaterPathfindingConsole::onPathSelectionSwitch()
-{
-	switch (getPathSelectionState())
-	{
-	case kPathSelectNone :
-		llwarns << "functionality has not yet been implemented to toggle '"
-			<< mPathSelectionRadioGroup->getName() << "' to PathSelectNone"
-			<< llendl;
-		break;
-	case kPathSelectStartPoint :
-		llwarns << "functionality has not yet been implemented to toggle '"
-			<< mPathSelectionRadioGroup->getName() << "' to PathSelectStartPoint"
-			<< llendl;
-		break;
-	case kPathSelectEndPoint :
-		llwarns << "functionality has not yet been implemented to toggle '"
-			<< mPathSelectionRadioGroup->getName() << "' to PathSelectEndPoint"
-			<< llendl;
-		break;
-	default :
-		llassert(0);
-		break;
-	}
-}
-
-void LLFloaterPathfindingConsole::onCharacterWidthSet()
-{
-	F32 characterWidth = getCharacterWidth();
-	llwarns << "functionality has not yet been implemented to set '" << mCharacterWidthSlider->getName()
-		<< "' to the value (" << characterWidth << ")" << llendl;
-}
-
-void LLFloaterPathfindingConsole::onCharacterTypeSwitch()
-{
-	switch (getCharacterType())
-	{
-	case kCharacterTypeA :
-		llwarns << "functionality has not yet been implemented to toggle '"
-			<< mCharacterTypeRadioGroup->getName() << "' to CharacterTypeA"
-			<< llendl;
-		break;
-	case kCharacterTypeB :
-		llwarns << "functionality has not yet been implemented to toggle '"
-			<< mCharacterTypeRadioGroup->getName() << "' to CharacterTypeB"
-			<< llendl;
-		break;
-	case kCharacterTypeC :
-		llwarns << "functionality has not yet been implemented to toggle '"
-			<< mCharacterTypeRadioGroup->getName() << "' to CharacterTypeC"
-			<< llendl;
-		break;
-	case kCharacterTypeD :
-		llwarns << "functionality has not yet been implemented to toggle '"
-			<< mCharacterTypeRadioGroup->getName() << "' to CharacterTypeD"
-			<< llendl;
-		break;
-	default :
-		llassert(0);
-		break;
-	}
-
-}
-
-void LLFloaterPathfindingConsole::onViewEditLinksetClicked()
-{
-	LLFloaterPathfindingLinksets::openLinksetsEditor();
-}
-
-void LLFloaterPathfindingConsole::onRebuildNavMeshClicked()
-{
-	llwarns << "functionality has not yet been implemented to handle rebuilding of the navmesh" << llendl;
-}
-
-void LLFloaterPathfindingConsole::onRefreshNavMeshClicked()
-{
-	llwarns << "functionality has not yet been implemented to handle refreshing of the navmesh" << llendl;
-}
-
-void LLFloaterPathfindingConsole::onTerrainMaterialASet()
-{
-	F32 terrainMaterial = getTerrainMaterialA();
-	llwarns << "functionality has not yet been implemented to setting '" << mTerrainMaterialA->getName()
-		<< "' to value (" << terrainMaterial << ")" << llendl;
-}
-
-void LLFloaterPathfindingConsole::onTerrainMaterialBSet()
-{
-	F32 terrainMaterial = getTerrainMaterialB();
-	llwarns << "functionality has not yet been implemented to setting '" << mTerrainMaterialB->getName()
-		<< "' to value (" << terrainMaterial << ")" << llendl;
-}
-
-void LLFloaterPathfindingConsole::onTerrainMaterialCSet()
-{
-	F32 terrainMaterial = getTerrainMaterialC();
-	llwarns << "functionality has not yet been implemented to setting '" << mTerrainMaterialC->getName()
-		<< "' to value (" << terrainMaterial << ")" << llendl;
-}
-
-void LLFloaterPathfindingConsole::onTerrainMaterialDSet()
-{
-	F32 terrainMaterial = getTerrainMaterialD();
-	llwarns << "functionality has not yet been implemented to setting '" << mTerrainMaterialD->getName()
-		<< "' to value (" << terrainMaterial << ")" << llendl;
-}
-
-
-BOOL LLFloaterPathfindingConsole::allowAllRenderables() const
-{
-	return getRegionOverlayDisplay() == kRenderOverlayOnAllRenderableGeometry ? true : false;
-}
-
-void LLFloaterPathfindingConsole::providePathingData( const LLVector3& point1, const LLVector3& point2 )
-{
-	switch (getPathSelectionState())
-	{
-	case kPathSelectNone :
-		llwarns << "not yet been implemented to toggle '"
-			<< mPathSelectionRadioGroup->getName() << "' to PathSelectNone"
-			<< llendl;
-		break;
-
-	case kPathSelectStartPoint :
-		mPathData.mStartPointA	= point1;
-		mPathData.mEndPointA	= point2;
-		break;
-
-	case kPathSelectEndPoint :
-		mPathData.mStartPointB		= point1;
-		mPathData.mEndPointB		= point2;		
-		mPathData.mCharacterWidth	= getCharacterWidth();
-		//prep#TODO# possibly consider an alternate behavior - perhaps add a "path" button to submit the data.
-		LLPathingLib::getInstance()->generatePath( mPathData );
-		break;
-
-	default :
-		llassert(0);
-		break;
-	}	
-}
+/** 
+* @file llfloaterpathfindingconsole.cpp
+* @author William Todd Stinson
+* @brief "Pathfinding console" floater, allowing manipulation of the Havok AI pathfinding settings.
+*
+* $LicenseInfo:firstyear=2002&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$
+*/
+
+#include "llviewerprecompiledheaders.h"
+#include "llfloaterpathfindingconsole.h"
+#include "llfloaterpathfindinglinksets.h"
+
+#include "llsd.h"
+#include "llagent.h"
+#include "llbutton.h"
+#include "llradiogroup.h"
+#include "llsliderctrl.h"
+#include "lllineeditor.h"
+#include "lltextbase.h"
+#include "lltextvalidate.h"
+#include "llnavmeshstation.h"
+#include "llviewerregion.h"
+
+#include "LLPathingLib.h"
+
+#define XUI_RENDER_OVERLAY_ON_FIXED_PHYSICS_GEOMETRY 1
+#define XUI_RENDER_OVERLAY_ON_ALL_RENDERABLE_GEOMETRY 2
+
+#define XUI_PATH_SELECT_NONE 0
+#define XUI_PATH_SELECT_START_POINT 1
+#define XUI_PATH_SELECT_END_POINT 2
+
+#define XUI_CHARACTER_TYPE_A 1
+#define XUI_CHARACTER_TYPE_B 2
+#define XUI_CHARACTER_TYPE_C 3
+#define XUI_CHARACTER_TYPE_D 4
+
+const int CURRENT_REGION = 99;
+const int MAX_OBSERVERS = 10;
+//---------------------------------------------------------------------------
+// LLFloaterPathfindingConsole
+//---------------------------------------------------------------------------
+
+BOOL LLFloaterPathfindingConsole::postBuild()
+{
+	childSetAction("view_and_edit_linksets", boost::bind(&LLFloaterPathfindingConsole::onViewEditLinksetClicked, this));
+	childSetAction("rebuild_navmesh", boost::bind(&LLFloaterPathfindingConsole::onRebuildNavMeshClicked, this));
+	childSetAction("refresh_navmesh", boost::bind(&LLFloaterPathfindingConsole::onRefreshNavMeshClicked, this));
+
+	mShowNavMeshCheckBox = findChild<LLCheckBoxCtrl>("show_navmesh_overlay");
+	llassert(mShowNavMeshCheckBox != NULL);
+	mShowNavMeshCheckBox->setCommitCallback(boost::bind(&LLFloaterPathfindingConsole::onShowNavMeshToggle, this));
+
+	mShowExcludeVolumesCheckBox = findChild<LLCheckBoxCtrl>("show_exclusion_volumes");
+	llassert(mShowExcludeVolumesCheckBox != NULL);
+	mShowExcludeVolumesCheckBox->setCommitCallback(boost::bind(&LLFloaterPathfindingConsole::onShowExcludeVolumesToggle, this));
+
+	mShowPathCheckBox = findChild<LLCheckBoxCtrl>("show_path");
+	llassert(mShowPathCheckBox != NULL);
+	mShowPathCheckBox->setCommitCallback(boost::bind(&LLFloaterPathfindingConsole::onShowPathToggle, this));
+
+	mShowWaterPlaneCheckBox = findChild<LLCheckBoxCtrl>("show_water_plane");
+	llassert(mShowWaterPlaneCheckBox != NULL);
+	mShowWaterPlaneCheckBox->setCommitCallback(boost::bind(&LLFloaterPathfindingConsole::onShowWaterPlaneToggle, this));
+
+	mRegionOverlayDisplayRadioGroup = findChild<LLRadioGroup>("region_overlay_display");
+	llassert(mRegionOverlayDisplayRadioGroup != NULL);
+	mRegionOverlayDisplayRadioGroup->setCommitCallback(boost::bind(&LLFloaterPathfindingConsole::onRegionOverlayDisplaySwitch, this));
+
+	mPathSelectionRadioGroup = findChild<LLRadioGroup>("path_selection");
+	llassert(mPathSelectionRadioGroup  != NULL);
+	mPathSelectionRadioGroup ->setCommitCallback(boost::bind(&LLFloaterPathfindingConsole::onPathSelectionSwitch, this));
+
+	mCharacterWidthSlider = findChild<LLSliderCtrl>("character_width");
+	llassert(mCharacterWidthSlider != NULL);
+	mCharacterWidthSlider->setCommitCallback(boost::bind(&LLFloaterPathfindingConsole::onCharacterWidthSet, this));
+
+	mCharacterTypeRadioGroup = findChild<LLRadioGroup>("character_type");
+	llassert(mCharacterTypeRadioGroup  != NULL);
+	mCharacterTypeRadioGroup->setCommitCallback(boost::bind(&LLFloaterPathfindingConsole::onCharacterTypeSwitch, this));
+
+	mPathfindingStatus = findChild<LLTextBase>("pathfinding_status");
+	llassert(mPathfindingStatus != NULL);
+
+	mTerrainMaterialA = findChild<LLLineEditor>("terrain_material_a");
+	llassert(mTerrainMaterialA != NULL);
+	mTerrainMaterialA->setCommitCallback(boost::bind(&LLFloaterPathfindingConsole::onTerrainMaterialASet, this));
+	mTerrainMaterialA->setPrevalidate(LLTextValidate::validateFloat);
+
+	mTerrainMaterialB = findChild<LLLineEditor>("terrain_material_b");
+	llassert(mTerrainMaterialB != NULL);
+	mTerrainMaterialB->setCommitCallback(boost::bind(&LLFloaterPathfindingConsole::onTerrainMaterialBSet, this));
+	mTerrainMaterialB->setPrevalidate(LLTextValidate::validateFloat);
+
+	mTerrainMaterialC = findChild<LLLineEditor>("terrain_material_c");
+	llassert(mTerrainMaterialC != NULL);
+	mTerrainMaterialC->setCommitCallback(boost::bind(&LLFloaterPathfindingConsole::onTerrainMaterialCSet, this));
+	mTerrainMaterialC->setPrevalidate(LLTextValidate::validateFloat);
+
+	mTerrainMaterialD = findChild<LLLineEditor>("terrain_material_d");
+	llassert(mTerrainMaterialD != NULL);
+	mTerrainMaterialD->setCommitCallback(boost::bind(&LLFloaterPathfindingConsole::onTerrainMaterialDSet, this));
+	mTerrainMaterialD->setPrevalidate(LLTextValidate::validateFloat);
+
+	return LLFloater::postBuild();
+}
+
+LLFloaterPathfindingConsole::ERegionOverlayDisplay LLFloaterPathfindingConsole::getRegionOverlayDisplay() const
+{
+	ERegionOverlayDisplay regionOverlayDisplay;
+	switch (mRegionOverlayDisplayRadioGroup->getValue().asInteger())
+	{
+	case XUI_RENDER_OVERLAY_ON_FIXED_PHYSICS_GEOMETRY :
+		regionOverlayDisplay = kRenderOverlayOnFixedPhysicsGeometry;
+		break;
+	case XUI_RENDER_OVERLAY_ON_ALL_RENDERABLE_GEOMETRY :
+		regionOverlayDisplay = kRenderOverlayOnAllRenderableGeometry;
+		break;
+	default :
+		regionOverlayDisplay = kRenderOverlayOnFixedPhysicsGeometry;
+		llassert(0);
+		break;
+	}
+
+	return regionOverlayDisplay;
+}
+
+void LLFloaterPathfindingConsole::setRegionOverlayDisplay(ERegionOverlayDisplay pRegionOverlayDisplay)
+{
+	LLSD radioGroupValue;
+
+	switch (pRegionOverlayDisplay)
+	{
+	case kRenderOverlayOnFixedPhysicsGeometry :
+		radioGroupValue = XUI_RENDER_OVERLAY_ON_FIXED_PHYSICS_GEOMETRY;
+		break;
+	case kRenderOverlayOnAllRenderableGeometry :
+		radioGroupValue = XUI_RENDER_OVERLAY_ON_ALL_RENDERABLE_GEOMETRY;
+		break;
+	default :
+		radioGroupValue = XUI_RENDER_OVERLAY_ON_FIXED_PHYSICS_GEOMETRY;
+		llassert(0);
+		break;
+	}
+
+	mRegionOverlayDisplayRadioGroup->setValue(radioGroupValue);
+}
+
+LLFloaterPathfindingConsole::EPathSelectionState LLFloaterPathfindingConsole::getPathSelectionState() const
+{
+	EPathSelectionState pathSelectionState;
+
+	switch (mPathSelectionRadioGroup->getValue().asInteger())
+	{
+	case XUI_PATH_SELECT_START_POINT :
+		pathSelectionState = kPathSelectStartPoint;
+		break;
+	case XUI_PATH_SELECT_END_POINT :
+		pathSelectionState = kPathSelectEndPoint;
+		break;
+	default :
+		pathSelectionState = kPathSelectNone;
+		break;
+	}
+
+	return pathSelectionState;
+}
+
+void LLFloaterPathfindingConsole::setPathSelectionState(EPathSelectionState pPathSelectionState)
+{
+	LLSD radioGroupValue;
+
+	switch (pPathSelectionState)
+	{
+	case kPathSelectStartPoint :
+		radioGroupValue = XUI_PATH_SELECT_START_POINT;
+		break;
+	case kPathSelectEndPoint :
+		radioGroupValue = XUI_PATH_SELECT_END_POINT;
+		break;
+	default :
+		radioGroupValue = XUI_PATH_SELECT_NONE;
+		break;
+	}
+
+	mPathSelectionRadioGroup->setValue(radioGroupValue);
+}
+
+F32 LLFloaterPathfindingConsole::getCharacterWidth() const
+{
+	return mCharacterWidthSlider->getValueF32();
+}
+
+void LLFloaterPathfindingConsole::setCharacterWidth(F32 pCharacterWidth)
+{
+	mCharacterWidthSlider->setValue(LLSD(pCharacterWidth));
+}
+
+LLFloaterPathfindingConsole::ECharacterType LLFloaterPathfindingConsole::getCharacterType() const
+{
+	ECharacterType characterType;
+
+	switch (mCharacterTypeRadioGroup->getValue().asInteger())
+	{
+	case XUI_CHARACTER_TYPE_A :
+		characterType = kCharacterTypeA;
+		break;
+	case XUI_CHARACTER_TYPE_B :
+		characterType = kCharacterTypeB;
+		break;
+	case XUI_CHARACTER_TYPE_C :
+		characterType = kCharacterTypeC;
+		break;
+	case XUI_CHARACTER_TYPE_D :
+		characterType = kCharacterTypeD;
+		break;
+	default :
+		characterType = kCharacterTypeA;
+		llassert(0);
+		break;
+	}
+
+	return characterType;
+}
+
+void LLFloaterPathfindingConsole::setCharacterType(ECharacterType pCharacterType)
+{
+	LLSD radioGroupValue;
+
+	switch (pCharacterType)
+	{
+	case kCharacterTypeA :
+		radioGroupValue = XUI_CHARACTER_TYPE_A;
+		break;
+	case kCharacterTypeB :
+		radioGroupValue = XUI_CHARACTER_TYPE_B;
+		break;
+	case kCharacterTypeC :
+		radioGroupValue = XUI_CHARACTER_TYPE_C;
+		break;
+	case kCharacterTypeD :
+		radioGroupValue = XUI_CHARACTER_TYPE_D;
+		break;
+	default :
+		radioGroupValue = XUI_CHARACTER_TYPE_A;
+		llassert(0);
+		break;
+	}
+
+	mCharacterTypeRadioGroup->setValue(radioGroupValue);
+}
+
+F32 LLFloaterPathfindingConsole::getTerrainMaterialA() const
+{
+	return mTerrainMaterialA->getValue().asReal();
+}
+
+void LLFloaterPathfindingConsole::setTerrainMaterialA(F32 pTerrainMaterial)
+{
+	mTerrainMaterialA->setValue(LLSD(pTerrainMaterial));
+}
+
+F32 LLFloaterPathfindingConsole::getTerrainMaterialB() const
+{
+	return mTerrainMaterialB->getValue().asReal();
+}
+
+void LLFloaterPathfindingConsole::setTerrainMaterialB(F32 pTerrainMaterial)
+{
+	mTerrainMaterialB->setValue(LLSD(pTerrainMaterial));
+}
+
+F32 LLFloaterPathfindingConsole::getTerrainMaterialC() const
+{
+	return mTerrainMaterialC->getValue().asReal();
+}
+
+void LLFloaterPathfindingConsole::setTerrainMaterialC(F32 pTerrainMaterial)
+{
+	mTerrainMaterialC->setValue(LLSD(pTerrainMaterial));
+}
+
+F32 LLFloaterPathfindingConsole::getTerrainMaterialD() const
+{
+	return mTerrainMaterialD->getValue().asReal();
+}
+
+void LLFloaterPathfindingConsole::setTerrainMaterialD(F32 pTerrainMaterial)
+{
+	mTerrainMaterialD->setValue(LLSD(pTerrainMaterial));
+}
+
+void LLFloaterPathfindingConsole::setHasNavMeshReceived()
+{
+	std::string str = getString("navmesh_fetch_complete_available");
+	mPathfindingStatus->setText((LLStringExplicit)str);
+}
+
+void LLFloaterPathfindingConsole::setHasNoNavMesh()
+{
+	std::string str = getString("navmesh_fetch_complete_none");
+	mPathfindingStatus->setText((LLStringExplicit)str);
+}
+
+LLFloaterPathfindingConsole::LLFloaterPathfindingConsole(const LLSD& pSeed)
+	: LLFloater(pSeed),
+	mShowNavMeshCheckBox(NULL),
+	mShowExcludeVolumesCheckBox(NULL),
+	mShowPathCheckBox(NULL),
+	mShowWaterPlaneCheckBox(NULL),
+	mRegionOverlayDisplayRadioGroup(NULL),
+	mPathSelectionRadioGroup(NULL),
+	mCharacterWidthSlider(NULL),
+	mCharacterTypeRadioGroup(NULL),
+	mPathfindingStatus(NULL),
+	mTerrainMaterialA(NULL),
+	mTerrainMaterialB(NULL),
+	mTerrainMaterialC(NULL),
+	mTerrainMaterialD(NULL)
+{
+	for (int i=0;i<MAX_OBSERVERS;++i)
+	{
+		mNavMeshDownloadObserver[i].setPathfindingConsole(this);
+	}
+}
+
+LLFloaterPathfindingConsole::~LLFloaterPathfindingConsole()
+{
+}
+
+void LLFloaterPathfindingConsole::onOpen(const LLSD& pKey)
+{
+	//make sure we have a pathing system
+	if ( !LLPathingLib::getInstance() )
+	{
+		LLPathingLib::initSystem();
+	}
+	//prep# test remove
+	//LLSD content;
+	//LLPathingLib::getInstance()->extractNavMeshSrcFromLLSD( content );
+	//return true;
+	//prep# end test
+	if ( LLPathingLib::getInstance() == NULL )
+	{ 
+		std::string str = getString("navmesh_library_not_implemented");
+		LLStyle::Params styleParams;
+		styleParams.color = LLUIColorTable::instance().getColor("DrYellow");
+		mPathfindingStatus->setText((LLStringExplicit)str, styleParams);
+		llwarns <<"Errror: cannout find pathing library implementation."<<llendl;
+	}
+	else
+	{		
+		mCurrentMDO = 0;
+		//make sure the region is essentially enabled for navmesh support
+		std::string capability = "RetrieveNavMeshSrc";
+
+		//prep# neighboring navmesh support proto
+		LLViewerRegion* pCurrentRegion = gAgent.getRegion();
+		std::vector<LLViewerRegion*> regions;
+		regions.push_back( pCurrentRegion );
+		//pCurrentRegion->getNeighboringRegions( regions );
+
+		std::vector<int> shift;
+		shift.push_back( CURRENT_REGION );
+		//pCurrentRegion->getNeighboringRegionsStatus( shift );
+
+		int regionCnt = regions.size();
+		for ( int i=0; i<regionCnt; ++i )
+		{
+			std::string url = regions[i]->getCapability( capability );
+
+			if ( !url.empty() )
+			{
+				std::string str = getString("navmesh_fetch_inprogress");
+				mPathfindingStatus->setText((LLStringExplicit)str);
+				LLNavMeshStation::getInstance()->setNavMeshDownloadURL( url );
+				int dir = shift[i];
+				LLNavMeshStation::getInstance()->downloadNavMeshSrc( mNavMeshDownloadObserver[mCurrentMDO].getObserverHandle(), dir );				
+				++mCurrentMDO;
+			}				
+			else
+			{
+				std::string str = getString("navmesh_region_not_enabled");
+				LLStyle::Params styleParams;
+				styleParams.color = LLUIColorTable::instance().getColor("DrYellow");
+				mPathfindingStatus->setText((LLStringExplicit)str, styleParams);
+				llinfos<<"Region has does not required caps of type ["<<capability<<"]"<<llendl;
+			}
+		}
+	}		
+}
+
+void LLFloaterPathfindingConsole::onShowNavMeshToggle()
+{
+	BOOL checkBoxValue = mShowNavMeshCheckBox->get();
+
+	LLPathingLib *llPathingLibInstance = LLPathingLib::getInstance();
+	if (llPathingLibInstance != NULL)
+	{
+		llPathingLibInstance->setRenderNavMesh(checkBoxValue);
+	}
+	else
+	{
+		mShowNavMeshCheckBox->set(FALSE);
+		llwarns << "cannot find LLPathingLib instance" << llendl;
+	}
+}
+
+void LLFloaterPathfindingConsole::onShowExcludeVolumesToggle()
+{
+	BOOL checkBoxValue = mShowExcludeVolumesCheckBox->get();
+
+	LLPathingLib *llPathingLibInstance = LLPathingLib::getInstance();
+	if (llPathingLibInstance != NULL)
+	{
+		llPathingLibInstance->setRenderNavMeshandShapes(checkBoxValue);
+	}
+	else
+	{
+		mShowExcludeVolumesCheckBox->set(FALSE);
+		llwarns << "cannot find LLPathingLib instance" << llendl;
+	}
+}
+
+void LLFloaterPathfindingConsole::onShowPathToggle()
+{
+	BOOL checkBoxValue = mShowPathCheckBox->get();
+
+	llwarns << "functionality has not yet been implemented to toggle '"
+		<< mShowPathCheckBox->getLabel() << "' to "
+		<< (checkBoxValue ? "ON" : "OFF") << llendl;
+}
+
+void LLFloaterPathfindingConsole::onShowWaterPlaneToggle()
+{
+	BOOL checkBoxValue = mShowWaterPlaneCheckBox->get();
+
+	llwarns << "functionality has not yet been implemented to toggle '"
+		<< mShowWaterPlaneCheckBox->getLabel() << "' to "
+		<< (checkBoxValue ? "ON" : "OFF") << llendl;
+}
+
+void LLFloaterPathfindingConsole::onRegionOverlayDisplaySwitch()
+{
+	switch (getRegionOverlayDisplay())
+	{
+	case kRenderOverlayOnFixedPhysicsGeometry :
+		llwarns << "functionality has not yet been implemented to toggle '"
+			<< mRegionOverlayDisplayRadioGroup->getName() << "' to RenderOverlayOnFixedPhysicsGeometry"
+			<< llendl;
+		break;
+	case kRenderOverlayOnAllRenderableGeometry :
+		llwarns << "functionality has not yet been implemented to toggle '"
+			<< mRegionOverlayDisplayRadioGroup->getName() << "' to RenderOverlayOnAllRenderableGeometry"
+			<< llendl;
+		break;
+	default :
+		llassert(0);
+		break;
+	}
+}
+
+void LLFloaterPathfindingConsole::onPathSelectionSwitch()
+{
+	switch (getPathSelectionState())
+	{
+	case kPathSelectNone :
+		llwarns << "functionality has not yet been implemented to toggle '"
+			<< mPathSelectionRadioGroup->getName() << "' to PathSelectNone"
+			<< llendl;
+		break;
+	case kPathSelectStartPoint :
+		llwarns << "functionality has not yet been implemented to toggle '"
+			<< mPathSelectionRadioGroup->getName() << "' to PathSelectStartPoint"
+			<< llendl;
+		break;
+	case kPathSelectEndPoint :
+		llwarns << "functionality has not yet been implemented to toggle '"
+			<< mPathSelectionRadioGroup->getName() << "' to PathSelectEndPoint"
+			<< llendl;
+		break;
+	default :
+		llassert(0);
+		break;
+	}
+}
+
+void LLFloaterPathfindingConsole::onCharacterWidthSet()
+{
+	F32 characterWidth = getCharacterWidth();
+	llwarns << "functionality has not yet been implemented to set '" << mCharacterWidthSlider->getName()
+		<< "' to the value (" << characterWidth << ")" << llendl;
+}
+
+void LLFloaterPathfindingConsole::onCharacterTypeSwitch()
+{
+	switch (getCharacterType())
+	{
+	case kCharacterTypeA :
+		llwarns << "functionality has not yet been implemented to toggle '"
+			<< mCharacterTypeRadioGroup->getName() << "' to CharacterTypeA"
+			<< llendl;
+		break;
+	case kCharacterTypeB :
+		llwarns << "functionality has not yet been implemented to toggle '"
+			<< mCharacterTypeRadioGroup->getName() << "' to CharacterTypeB"
+			<< llendl;
+		break;
+	case kCharacterTypeC :
+		llwarns << "functionality has not yet been implemented to toggle '"
+			<< mCharacterTypeRadioGroup->getName() << "' to CharacterTypeC"
+			<< llendl;
+		break;
+	case kCharacterTypeD :
+		llwarns << "functionality has not yet been implemented to toggle '"
+			<< mCharacterTypeRadioGroup->getName() << "' to CharacterTypeD"
+			<< llendl;
+		break;
+	default :
+		llassert(0);
+		break;
+	}
+
+}
+
+void LLFloaterPathfindingConsole::onViewEditLinksetClicked()
+{
+	LLFloaterPathfindingLinksets::openLinksetsEditor();
+}
+
+void LLFloaterPathfindingConsole::onRebuildNavMeshClicked()
+{
+	llwarns << "functionality has not yet been implemented to handle rebuilding of the navmesh" << llendl;
+}
+
+void LLFloaterPathfindingConsole::onRefreshNavMeshClicked()
+{
+	llwarns << "functionality has not yet been implemented to handle refreshing of the navmesh" << llendl;
+}
+
+void LLFloaterPathfindingConsole::onTerrainMaterialASet()
+{
+	F32 terrainMaterial = getTerrainMaterialA();
+	llwarns << "functionality has not yet been implemented to setting '" << mTerrainMaterialA->getName()
+		<< "' to value (" << terrainMaterial << ")" << llendl;
+}
+
+void LLFloaterPathfindingConsole::onTerrainMaterialBSet()
+{
+	F32 terrainMaterial = getTerrainMaterialB();
+	llwarns << "functionality has not yet been implemented to setting '" << mTerrainMaterialB->getName()
+		<< "' to value (" << terrainMaterial << ")" << llendl;
+}
+
+void LLFloaterPathfindingConsole::onTerrainMaterialCSet()
+{
+	F32 terrainMaterial = getTerrainMaterialC();
+	llwarns << "functionality has not yet been implemented to setting '" << mTerrainMaterialC->getName()
+		<< "' to value (" << terrainMaterial << ")" << llendl;
+}
+
+void LLFloaterPathfindingConsole::onTerrainMaterialDSet()
+{
+	F32 terrainMaterial = getTerrainMaterialD();
+	llwarns << "functionality has not yet been implemented to setting '" << mTerrainMaterialD->getName()
+		<< "' to value (" << terrainMaterial << ")" << llendl;
+}
+
+
+BOOL LLFloaterPathfindingConsole::allowAllRenderables() const
+{
+	return getRegionOverlayDisplay() == kRenderOverlayOnAllRenderableGeometry ? true : false;
+}
+
+void LLFloaterPathfindingConsole::providePathingData( const LLVector3& point1, const LLVector3& point2 )
+{
+	switch (getPathSelectionState())
+	{
+	case kPathSelectNone :
+		llwarns << "not yet been implemented to toggle '"
+			<< mPathSelectionRadioGroup->getName() << "' to PathSelectNone"
+			<< llendl;
+		break;
+
+	case kPathSelectStartPoint :
+		mPathData.mStartPointA	= point1;
+		mPathData.mEndPointA	= point2;
+		break;
+
+	case kPathSelectEndPoint :
+		mPathData.mStartPointB		= point1;
+		mPathData.mEndPointB		= point2;		
+		mPathData.mCharacterWidth	= getCharacterWidth();
+		//prep#TODO# possibly consider an alternate behavior - perhaps add a "path" button to submit the data.
+		LLPathingLib::getInstance()->generatePath( mPathData );
+		break;
+
+	default :
+		llassert(0);
+		break;
+	}	
+}
diff --git a/indra/newview/llfloaterpathfindingconsole.h b/indra/newview/llfloaterpathfindingconsole.h
index c46fead91b00f3dde50faa2cd44735ca9dd52c74..3ae5e25695b176ddf1c9cafef20bc2135271bedf 100644
--- a/indra/newview/llfloaterpathfindingconsole.h
+++ b/indra/newview/llfloaterpathfindingconsole.h
@@ -1,151 +1,151 @@
-/** 
- * @file llfloaterpathfindingconsole.h
- * @author William Todd Stinson
- * @brief "Pathfinding console" floater, allowing manipulation of the Havok AI pathfinding settings.
- *
- * $LicenseInfo:firstyear=2002&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$
- */
-
-#ifndef LL_LLFLOATERPATHFINDINGCONSOLE_H
-#define LL_LLFLOATERPATHFINDINGCONSOLE_H
-
-#include "llfloater.h"
-#include "llnavmeshstation.h"
-#include "llphysicsextensions.h"
-#include "llcheckboxctrl.h"
-
-class LLSD;
-class LLRadioGroup;
-class LLSliderCtrl;
-class LLLineEditor;
-class LLTextBase;
-
-class LLFloaterPathfindingConsole
-:	public LLFloater
-{
-	friend class LLFloaterReg;
-
-public:
-	typedef enum
-	{
-		kRenderOverlayOnFixedPhysicsGeometry  = 0,
-		kRenderOverlayOnAllRenderableGeometry = 1
-	} ERegionOverlayDisplay;
-
-	typedef enum
-	{
-		kPathSelectNone       = 0,
-		kPathSelectStartPoint = 1,
-		kPathSelectEndPoint   = 2
-	} EPathSelectionState;
-
-	typedef enum
-	{
-		kCharacterTypeA = 0,
-		kCharacterTypeB = 1,
-		kCharacterTypeC = 2,
-		kCharacterTypeD = 3
-	} ECharacterType;
-
-	virtual BOOL postBuild();
-	//Accessor to determine whether renderables are allowed
-	BOOL allowAllRenderables() const;
-	//Populates a data packet that is forwarded onto the LLPathingSystem
-	void providePathingData( const LLVector3& point1, const LLVector3& point2 );
-
-	ERegionOverlayDisplay getRegionOverlayDisplay() const;
-    void                  setRegionOverlayDisplay(ERegionOverlayDisplay pRegionOverlayDisplay);
-
-    EPathSelectionState   getPathSelectionState() const;
-    void                  setPathSelectionState(EPathSelectionState pPathSelectionState);
-
-    F32                   getCharacterWidth() const;
-    void                  setCharacterWidth(F32 pCharacterWidth);
-
-    ECharacterType        getCharacterType() const;
-    void                  setCharacterType(ECharacterType pCharacterType);
-
-    F32                   getTerrainMaterialA() const;
-    void                  setTerrainMaterialA(F32 pTerrainMaterial);
-
-    F32                   getTerrainMaterialB() const;
-    void                  setTerrainMaterialB(F32 pTerrainMaterial);
-
-    F32                   getTerrainMaterialC() const;
-    void                  setTerrainMaterialC(F32 pTerrainMaterial);
-
-    F32                   getTerrainMaterialD() const;
-    void                  setTerrainMaterialD(F32 pTerrainMaterial);
-
-	BOOL				  getShowPathToggle() const {return mShowPathCheckBox->get(); }
-
-	void setHasNavMeshReceived();
-	void setHasNoNavMesh();
-
-protected:
-
-private:
-	// Does its own instance management, so clients not allowed
-	// to allocate or destroy.
-	LLFloaterPathfindingConsole(const LLSD& pSeed);
-	virtual ~LLFloaterPathfindingConsole();
-
-	virtual void onOpen(const LLSD& pKey);
-
-	void onShowNavMeshToggle();
-	void onShowExcludeVolumesToggle();
-	void onShowPathToggle();
-	void onShowWaterPlaneToggle();
-	void onRegionOverlayDisplaySwitch();
-	void onPathSelectionSwitch();
-	void onCharacterWidthSet();
-	void onCharacterTypeSwitch();
-	void onViewEditLinksetClicked();
-	void onRebuildNavMeshClicked();
-	void onRefreshNavMeshClicked();
-	void onTerrainMaterialASet();
-	void onTerrainMaterialBSet();
-	void onTerrainMaterialCSet();
-	void onTerrainMaterialDSet();
-
-	LLCheckBoxCtrl *mShowNavMeshCheckBox;
-	LLCheckBoxCtrl *mShowExcludeVolumesCheckBox;
-	LLCheckBoxCtrl *mShowPathCheckBox;
-	LLCheckBoxCtrl *mShowWaterPlaneCheckBox;
-	LLRadioGroup   *mRegionOverlayDisplayRadioGroup;
-	LLRadioGroup   *mPathSelectionRadioGroup;
-	LLSliderCtrl   *mCharacterWidthSlider;
-	LLRadioGroup   *mCharacterTypeRadioGroup;
-	LLTextBase     *mPathfindingStatus;
-	LLLineEditor   *mTerrainMaterialA;
-	LLLineEditor   *mTerrainMaterialB;
-	LLLineEditor   *mTerrainMaterialC;
-	LLLineEditor   *mTerrainMaterialD;
-
-	LLNavMeshDownloadObserver	mNavMeshDownloadObserver[10];
-	int							mCurrentMDO;
-
-	//Container that is populated and subsequently submitted to the LLPathingSystem for processing
-	LLPathingLib::PathingPacket		mPathData;
-};
-
-#endif // LL_LLFLOATERPATHFINDINGCONSOLE_H
+/** 
+ * @file llfloaterpathfindingconsole.h
+ * @author William Todd Stinson
+ * @brief "Pathfinding console" floater, allowing manipulation of the Havok AI pathfinding settings.
+ *
+ * $LicenseInfo:firstyear=2002&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$
+ */
+
+#ifndef LL_LLFLOATERPATHFINDINGCONSOLE_H
+#define LL_LLFLOATERPATHFINDINGCONSOLE_H
+
+#include "llfloater.h"
+#include "llnavmeshstation.h"
+#include "LLPathingLib.h"
+#include "llcheckboxctrl.h"
+
+class LLSD;
+class LLRadioGroup;
+class LLSliderCtrl;
+class LLLineEditor;
+class LLTextBase;
+
+class LLFloaterPathfindingConsole
+:	public LLFloater
+{
+	friend class LLFloaterReg;
+
+public:
+	typedef enum
+	{
+		kRenderOverlayOnFixedPhysicsGeometry  = 0,
+		kRenderOverlayOnAllRenderableGeometry = 1
+	} ERegionOverlayDisplay;
+
+	typedef enum
+	{
+		kPathSelectNone       = 0,
+		kPathSelectStartPoint = 1,
+		kPathSelectEndPoint   = 2
+	} EPathSelectionState;
+
+	typedef enum
+	{
+		kCharacterTypeA = 0,
+		kCharacterTypeB = 1,
+		kCharacterTypeC = 2,
+		kCharacterTypeD = 3
+	} ECharacterType;
+
+	virtual BOOL postBuild();
+	//Accessor to determine whether renderables are allowed
+	BOOL allowAllRenderables() const;
+	//Populates a data packet that is forwarded onto the LLPathingSystem
+	void providePathingData( const LLVector3& point1, const LLVector3& point2 );
+
+	ERegionOverlayDisplay getRegionOverlayDisplay() const;
+    void                  setRegionOverlayDisplay(ERegionOverlayDisplay pRegionOverlayDisplay);
+
+    EPathSelectionState   getPathSelectionState() const;
+    void                  setPathSelectionState(EPathSelectionState pPathSelectionState);
+
+    F32                   getCharacterWidth() const;
+    void                  setCharacterWidth(F32 pCharacterWidth);
+
+    ECharacterType        getCharacterType() const;
+    void                  setCharacterType(ECharacterType pCharacterType);
+
+    F32                   getTerrainMaterialA() const;
+    void                  setTerrainMaterialA(F32 pTerrainMaterial);
+
+    F32                   getTerrainMaterialB() const;
+    void                  setTerrainMaterialB(F32 pTerrainMaterial);
+
+    F32                   getTerrainMaterialC() const;
+    void                  setTerrainMaterialC(F32 pTerrainMaterial);
+
+    F32                   getTerrainMaterialD() const;
+    void                  setTerrainMaterialD(F32 pTerrainMaterial);
+
+	BOOL				  getShowPathToggle() const {return mShowPathCheckBox->get(); }
+
+	void setHasNavMeshReceived();
+	void setHasNoNavMesh();
+
+protected:
+
+private:
+	// Does its own instance management, so clients not allowed
+	// to allocate or destroy.
+	LLFloaterPathfindingConsole(const LLSD& pSeed);
+	virtual ~LLFloaterPathfindingConsole();
+
+	virtual void onOpen(const LLSD& pKey);
+
+	void onShowNavMeshToggle();
+	void onShowExcludeVolumesToggle();
+	void onShowPathToggle();
+	void onShowWaterPlaneToggle();
+	void onRegionOverlayDisplaySwitch();
+	void onPathSelectionSwitch();
+	void onCharacterWidthSet();
+	void onCharacterTypeSwitch();
+	void onViewEditLinksetClicked();
+	void onRebuildNavMeshClicked();
+	void onRefreshNavMeshClicked();
+	void onTerrainMaterialASet();
+	void onTerrainMaterialBSet();
+	void onTerrainMaterialCSet();
+	void onTerrainMaterialDSet();
+
+	LLCheckBoxCtrl *mShowNavMeshCheckBox;
+	LLCheckBoxCtrl *mShowExcludeVolumesCheckBox;
+	LLCheckBoxCtrl *mShowPathCheckBox;
+	LLCheckBoxCtrl *mShowWaterPlaneCheckBox;
+	LLRadioGroup   *mRegionOverlayDisplayRadioGroup;
+	LLRadioGroup   *mPathSelectionRadioGroup;
+	LLSliderCtrl   *mCharacterWidthSlider;
+	LLRadioGroup   *mCharacterTypeRadioGroup;
+	LLTextBase     *mPathfindingStatus;
+	LLLineEditor   *mTerrainMaterialA;
+	LLLineEditor   *mTerrainMaterialB;
+	LLLineEditor   *mTerrainMaterialC;
+	LLLineEditor   *mTerrainMaterialD;
+
+	LLNavMeshDownloadObserver	mNavMeshDownloadObserver[10];
+	int							mCurrentMDO;
+
+	//Container that is populated and subsequently submitted to the LLPathingSystem for processing
+	LLPathingLib::PathingPacket		mPathData;
+};
+
+#endif // LL_LLFLOATERPATHFINDINGCONSOLE_H
diff --git a/indra/newview/llnavmeshstation.cpp b/indra/newview/llnavmeshstation.cpp
index 586ed4715de46d49ef4c1db30f2a04dee69adc03..87f7e92ddd19143388e3cd6720f2b7dd0a67f438 100644
--- a/indra/newview/llnavmeshstation.cpp
+++ b/indra/newview/llnavmeshstation.cpp
@@ -27,7 +27,7 @@
 #include "llviewerprecompiledheaders.h"
 #include "llnavmeshstation.h"
 #include "llcurl.h"
-#include "llphysicsextensions.h"
+#include "LLPathingLib.h"
 #include "llagent.h"
 #include "llviewerregion.h"
 #include "llsdutil.h"
diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp
index d2da940260b6722a659b1350417e27e0ab1989d9..e8029293fc12f1127174b66d7b545dcb84ef20ef 100644
--- a/indra/newview/llviewerdisplay.cpp
+++ b/indra/newview/llviewerdisplay.cpp
@@ -1,1604 +1,1604 @@
-/** 
- * @file llviewerdisplay.cpp
- * @brief LLViewerDisplay class implementation
- *
- * $LicenseInfo:firstyear=2004&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$
- */
-
-#include "llviewerprecompiledheaders.h"
-
-#include "llviewerdisplay.h"
-
-#include "llgl.h"
-#include "llrender.h"
-#include "llglheaders.h"
-#include "llagent.h"
-#include "llagentcamera.h"
-#include "llviewercontrol.h"
-#include "llcoord.h"
-#include "llcriticaldamp.h"
-#include "lldir.h"
-#include "lldynamictexture.h"
-#include "lldrawpoolalpha.h"
-#include "llfeaturemanager.h"
-//#include "llfirstuse.h"
-#include "llhudmanager.h"
-#include "llimagebmp.h"
-#include "llmemory.h"
-#include "llselectmgr.h"
-#include "llsky.h"
-#include "llstartup.h"
-#include "lltoolfocus.h"
-#include "lltoolmgr.h"
-#include "lltooldraganddrop.h"
-#include "lltoolpie.h"
-#include "lltracker.h"
-#include "lltrans.h"
-#include "llui.h"
-#include "llviewercamera.h"
-#include "llviewerobjectlist.h"
-#include "llviewerparcelmgr.h"
-#include "llviewerwindow.h"
-#include "llvoavatarself.h"
-#include "llvograss.h"
-#include "llworld.h"
-#include "pipeline.h"
-#include "llspatialpartition.h"
-#include "llappviewer.h"
-#include "llstartup.h"
-#include "llviewershadermgr.h"
-#include "llfasttimer.h"
-#include "llfloatertools.h"
-#include "llviewertexturelist.h"
-#include "llfocusmgr.h"
-#include "llcubemap.h"
-#include "llviewerregion.h"
-#include "lldrawpoolwater.h"
-#include "lldrawpoolbump.h"
-#include "llwlparammanager.h"
-#include "llwaterparammanager.h"
-#include "llpostprocess.h"
-#include "llphysicsextensions.h"
-#include "llfloaterpathfindingconsole.h"
-#include "llfloaterreg.h"
-
-extern LLPointer<LLViewerTexture> gStartTexture;
-
-LLPointer<LLViewerTexture> gDisconnectedImagep = NULL;
-
-// used to toggle renderer back on after teleport
-const F32 TELEPORT_RENDER_DELAY = 20.f; // Max time a teleport is allowed to take before we raise the curtain
-const F32 TELEPORT_ARRIVAL_DELAY = 2.f; // Time to preload the world before raising the curtain after we've actually already arrived.
-const F32 TELEPORT_LOCAL_DELAY = 1.0f;  // Delay to prevent teleports after starting an in-sim teleport.
-BOOL		 gTeleportDisplay = FALSE;
-LLFrameTimer gTeleportDisplayTimer;
-LLFrameTimer gTeleportArrivalTimer;
-const F32		RESTORE_GL_TIME = 5.f;	// Wait this long while reloading textures before we raise the curtain
-
-BOOL gForceRenderLandFence = FALSE;
-BOOL gDisplaySwapBuffers = FALSE;
-BOOL gDepthDirty = FALSE;
-BOOL gResizeScreenTexture = FALSE;
-BOOL gWindowResized = FALSE;
-BOOL gSnapshot = FALSE;
-
-U32 gRecentFrameCount = 0; // number of 'recent' frames
-LLFrameTimer gRecentFPSTime;
-LLFrameTimer gRecentMemoryTime;
-
-// Rendering stuff
-void pre_show_depth_buffer();
-void post_show_depth_buffer();
-void render_ui(F32 zoom_factor = 1.f, int subfield = 0);
-void render_hud_attachments();
-void render_ui_3d();
-void render_ui_2d();
-void render_disconnected_background();
-
-void display_startup()
-{
-	if (   !gViewerWindow->getActive()
-		|| !gViewerWindow->getWindow()->getVisible() 
-		|| gViewerWindow->getWindow()->getMinimized() )
-	{
-		return; 
-	}
-
-	gPipeline.updateGL();
-
-	// Update images?
-	//gImageList.updateImages(0.01f);
-	LLTexUnit::sWhiteTexture = LLViewerFetchedTexture::sWhiteImagep->getTexName();
-
-	LLGLSDefault gls_default;
-
-	// Required for HTML update in login screen
-	static S32 frame_count = 0;
-
-	LLGLState::checkStates();
-	LLGLState::checkTextureChannels();
-
-	if (frame_count++ > 1) // make sure we have rendered a frame first
-	{
-		LLViewerDynamicTexture::updateAllInstances();
-	}
-
-	LLGLState::checkStates();
-	LLGLState::checkTextureChannels();
-
-	glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
-	LLGLSUIDefault gls_ui;
-	gPipeline.disableLights();
-
-	gViewerWindow->setup2DRender();
-	gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
-
-	gGL.color4f(1,1,1,1);
-	gViewerWindow->draw();
-	gGL.flush();
-
-	LLVertexBuffer::unbind();
-
-	LLGLState::checkStates();
-	LLGLState::checkTextureChannels();
-
-	gViewerWindow->getWindow()->swapBuffers();
-	glClear(GL_DEPTH_BUFFER_BIT);
-}
-
-void display_update_camera()
-{
-	LLMemType mt_uc(LLMemType::MTYPE_DISPLAY_UPDATE_CAMERA);
-	// TODO: cut draw distance down if customizing avatar?
-	// TODO: cut draw distance on per-parcel basis?
-
-	// Cut draw distance in half when customizing avatar,
-	// but on the viewer only.
-	F32 final_far = gAgentCamera.mDrawDistance;
-	if (CAMERA_MODE_CUSTOMIZE_AVATAR == gAgentCamera.getCameraMode())
-	{
-		final_far *= 0.5f;
-	}
-	LLViewerCamera::getInstance()->setFar(final_far);
-	gViewerWindow->setup3DRender();
-	
-	// update all the sky/atmospheric/water settings
-	LLWLParamManager::getInstance()->update(LLViewerCamera::getInstance());
-	LLWaterParamManager::getInstance()->update(LLViewerCamera::getInstance());
-
-	// Update land visibility too
-	LLWorld::getInstance()->setLandFarClip(final_far);
-}
-
-// Write some stats to llinfos
-void display_stats()
-{
-	F32 fps_log_freq = gSavedSettings.getF32("FPSLogFrequency");
-	if (fps_log_freq > 0.f && gRecentFPSTime.getElapsedTimeF32() >= fps_log_freq)
-	{
-		F32 fps = gRecentFrameCount / fps_log_freq;
-		llinfos << llformat("FPS: %.02f", fps) << llendl;
-		gRecentFrameCount = 0;
-		gRecentFPSTime.reset();
-	}
-	F32 mem_log_freq = gSavedSettings.getF32("MemoryLogFrequency");
-	if (mem_log_freq > 0.f && gRecentMemoryTime.getElapsedTimeF32() >= mem_log_freq)
-	{
-		gMemoryAllocated = LLMemory::getCurrentRSS();
-		U32 memory = (U32)(gMemoryAllocated / (1024*1024));
-		llinfos << llformat("MEMORY: %d MB", memory) << llendl;
-		LLMemory::logMemoryInfo(TRUE) ;
-		gRecentMemoryTime.reset();
-	}
-}
-
-static LLFastTimer::DeclareTimer FTM_PICK("Picking");
-static LLFastTimer::DeclareTimer FTM_RENDER("Render", true);
-static LLFastTimer::DeclareTimer FTM_UPDATE_SKY("Update Sky");
-static LLFastTimer::DeclareTimer FTM_UPDATE_TEXTURES("Update Textures");
-static LLFastTimer::DeclareTimer FTM_IMAGE_UPDATE("Update Images");
-static LLFastTimer::DeclareTimer FTM_IMAGE_UPDATE_CLASS("Class");
-static LLFastTimer::DeclareTimer FTM_IMAGE_UPDATE_BUMP("Bump");
-static LLFastTimer::DeclareTimer FTM_IMAGE_UPDATE_LIST("List");
-static LLFastTimer::DeclareTimer FTM_IMAGE_UPDATE_DELETE("Delete");
-
-// Paint the display!
-void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
-{
-	LLMemType mt_render(LLMemType::MTYPE_RENDER);
-	LLFastTimer t(FTM_RENDER);
-
-	if (gWindowResized)
-	{ //skip render on frames where window has been resized
-		gGL.flush();
-		glClear(GL_COLOR_BUFFER_BIT);
-		gViewerWindow->getWindow()->swapBuffers();
-		LLPipeline::refreshCachedSettings();
-		gPipeline.resizeScreenTexture();
-		gResizeScreenTexture = FALSE;
-		gWindowResized = FALSE;
-		return;
-	}
-
-	if (LLPipeline::sRenderDeferred)
-	{ //hack to make sky show up in deferred snapshots
-		for_snapshot = FALSE;
-	}
-
-	if (LLPipeline::sRenderFrameTest)
-	{
-		send_agent_pause();
-	}
-
-	gSnapshot = for_snapshot;
-
-	LLGLSDefault gls_default;
-	LLGLDepthTest gls_depth(GL_TRUE, GL_TRUE, GL_LEQUAL);
-	
-	LLVertexBuffer::unbind();
-
-	LLGLState::checkStates();
-	LLGLState::checkTextureChannels();
-	
-	stop_glerror();
-
-	gPipeline.disableLights();
-	
-	stop_glerror();
-
-	// Don't draw if the window is hidden or minimized.
-	// In fact, must explicitly check the minimized state before drawing.
-	// Attempting to draw into a minimized window causes a GL error. JC
-	if (   !gViewerWindow->getActive()
-		|| !gViewerWindow->getWindow()->getVisible() 
-		|| gViewerWindow->getWindow()->getMinimized() )
-	{
-		// Clean up memory the pools may have allocated
-		if (rebuild)
-		{
-			stop_glerror();
-			gPipeline.rebuildPools();
-			stop_glerror();
-		}
-
-		stop_glerror();
-		gViewerWindow->returnEmptyPicks();
-		stop_glerror();
-		return; 
-	}
-
-	gViewerWindow->checkSettings();
-	
-	{
-		LLFastTimer ftm(FTM_PICK);
-		LLAppViewer::instance()->pingMainloopTimeout("Display:Pick");
-		gViewerWindow->performPick();
-	}
-	
-	LLAppViewer::instance()->pingMainloopTimeout("Display:CheckStates");
-	LLGLState::checkStates();
-	LLGLState::checkTextureChannels();
-	
-	//////////////////////////////////////////////////////////
-	//
-	// Logic for forcing window updates if we're in drone mode.
-	//
-
-	// *TODO: Investigate running display() during gHeadlessClient.  See if this early exit is needed DK 2011-02-18
-	if (gHeadlessClient) 
-	{
-#if LL_WINDOWS
-		static F32 last_update_time = 0.f;
-		if ((gFrameTimeSeconds - last_update_time) > 1.f)
-		{
-			InvalidateRect((HWND)gViewerWindow->getPlatformWindow(), NULL, FALSE);
-			last_update_time = gFrameTimeSeconds;
-		}
-#elif LL_DARWIN
-		// MBW -- Do something clever here.
-#endif
-		// Not actually rendering, don't bother.
-		return;
-	}
-
-
-	//
-	// Bail out if we're in the startup state and don't want to try to
-	// render the world.
-	//
-	if (LLStartUp::getStartupState() < STATE_STARTED)
-	{
-		LLAppViewer::instance()->pingMainloopTimeout("Display:Startup");
-		display_startup();
-		return;
-	}
-
-	//LLGLState::verify(FALSE);
-
-	/////////////////////////////////////////////////
-	//
-	// Update GL Texture statistics (used for discard logic?)
-	//
-
-	LLAppViewer::instance()->pingMainloopTimeout("Display:TextureStats");
-	stop_glerror();
-
-	LLImageGL::updateStats(gFrameTimeSeconds);
-	
-	LLVOAvatar::sRenderName = gSavedSettings.getS32("AvatarNameTagMode");
-	LLVOAvatar::sRenderGroupTitles = (gSavedSettings.getBOOL("NameTagShowGroupTitles") && gSavedSettings.getS32("AvatarNameTagMode"));
-	
-	gPipeline.mBackfaceCull = TRUE;
-	gFrameCount++;
-	gRecentFrameCount++;
-	if (gFocusMgr.getAppHasFocus())
-	{
-		gForegroundFrameCount++;
-	}
-
-	//////////////////////////////////////////////////////////
-	//
-	// Display start screen if we're teleporting, and skip render
-	//
-
-	if (gTeleportDisplay)
-	{
-		LLAppViewer::instance()->pingMainloopTimeout("Display:Teleport");
-		const F32 TELEPORT_ARRIVAL_DELAY = 2.f; // Time to preload the world before raising the curtain after we've actually already arrived.
-
-		S32 attach_count = 0;
-		if (isAgentAvatarValid())
-		{
-			attach_count = gAgentAvatarp->getAttachmentCount();
-		}
-		F32 teleport_save_time = TELEPORT_EXPIRY + TELEPORT_EXPIRY_PER_ATTACHMENT * attach_count;
-		F32 teleport_elapsed = gTeleportDisplayTimer.getElapsedTimeF32();
-		F32 teleport_percent = teleport_elapsed * (100.f / teleport_save_time);
-		if( (gAgent.getTeleportState() != LLAgent::TELEPORT_START) && (teleport_percent > 100.f) )
-		{
-			// Give up.  Don't keep the UI locked forever.
-			gAgent.setTeleportState( LLAgent::TELEPORT_NONE );
-			gAgent.setTeleportMessage(std::string());
-		}
-
-		const std::string& message = gAgent.getTeleportMessage();
-		switch( gAgent.getTeleportState() )
-		{
-		case LLAgent::TELEPORT_START:
-			// Transition to REQUESTED.  Viewer has sent some kind
-			// of TeleportRequest to the source simulator
-			gTeleportDisplayTimer.reset();
-			gViewerWindow->setShowProgress(TRUE);
-			gViewerWindow->setProgressPercent(0);
-			gAgent.setTeleportState( LLAgent::TELEPORT_REQUESTED );
-			gAgent.setTeleportMessage(
-				LLAgent::sTeleportProgressMessages["requesting"]);
-			break;
-
-		case LLAgent::TELEPORT_REQUESTED:
-			// Waiting for source simulator to respond
-			gViewerWindow->setProgressPercent( llmin(teleport_percent, 37.5f) );
-			gViewerWindow->setProgressString(message);
-			break;
-
-		case LLAgent::TELEPORT_MOVING:
-			// Viewer has received destination location from source simulator
-			gViewerWindow->setProgressPercent( llmin(teleport_percent, 75.f) );
-			gViewerWindow->setProgressString(message);
-			break;
-
-		case LLAgent::TELEPORT_START_ARRIVAL:
-			// Transition to ARRIVING.  Viewer has received avatar update, etc., from destination simulator
-			gTeleportArrivalTimer.reset();
-				gViewerWindow->setProgressCancelButtonVisible(FALSE, LLTrans::getString("Cancel"));
-			gViewerWindow->setProgressPercent(75.f);
-			gAgent.setTeleportState( LLAgent::TELEPORT_ARRIVING );
-			gAgent.setTeleportMessage(
-				LLAgent::sTeleportProgressMessages["arriving"]);
-			gTextureList.mForceResetTextureStats = TRUE;
-			gAgentCamera.resetView(TRUE, TRUE);
-			break;
-
-		case LLAgent::TELEPORT_ARRIVING:
-			// Make the user wait while content "pre-caches"
-			{
-				F32 arrival_fraction = (gTeleportArrivalTimer.getElapsedTimeF32() / TELEPORT_ARRIVAL_DELAY);
-				if( arrival_fraction > 1.f )
-				{
-					arrival_fraction = 1.f;
-					//LLFirstUse::useTeleport();
-					gAgent.setTeleportState( LLAgent::TELEPORT_NONE );
-				}
-				gViewerWindow->setProgressCancelButtonVisible(FALSE, LLTrans::getString("Cancel"));
-				gViewerWindow->setProgressPercent(  arrival_fraction * 25.f + 75.f);
-				gViewerWindow->setProgressString(message);
-			}
-			break;
-
-		case LLAgent::TELEPORT_LOCAL:
-			// Short delay when teleporting in the same sim (progress screen active but not shown - did not
-			// fall-through from TELEPORT_START)
-			{
-				if( gTeleportDisplayTimer.getElapsedTimeF32() > TELEPORT_LOCAL_DELAY )
-				{
-					//LLFirstUse::useTeleport();
-					gAgent.setTeleportState( LLAgent::TELEPORT_NONE );
-				}
-			}
-			break;
-
-		case LLAgent::TELEPORT_NONE:
-			// No teleport in progress
-			gViewerWindow->setShowProgress(FALSE);
-			gTeleportDisplay = FALSE;
-			break;
-		}
-	}
-    else if(LLAppViewer::instance()->logoutRequestSent())
-	{
-		LLAppViewer::instance()->pingMainloopTimeout("Display:Logout");
-		F32 percent_done = gLogoutTimer.getElapsedTimeF32() * 100.f / gLogoutMaxTime;
-		if (percent_done > 100.f)
-		{
-			percent_done = 100.f;
-		}
-
-		if( LLApp::isExiting() )
-		{
-			percent_done = 100.f;
-		}
-		
-		gViewerWindow->setProgressPercent( percent_done );
-	}
-	else
-	if (gRestoreGL)
-	{
-		LLAppViewer::instance()->pingMainloopTimeout("Display:RestoreGL");
-		F32 percent_done = gRestoreGLTimer.getElapsedTimeF32() * 100.f / RESTORE_GL_TIME;
-		if( percent_done > 100.f )
-		{
-			gViewerWindow->setShowProgress(FALSE);
-			gRestoreGL = FALSE;
-		}
-		else
-		{
-
-			if( LLApp::isExiting() )
-			{
-				percent_done = 100.f;
-			}
-			
-			gViewerWindow->setProgressPercent( percent_done );
-		}
-	}
-
-	//////////////////////////
-	//
-	// Prepare for the next frame
-	//
-
-	/////////////////////////////
-	//
-	// Update the camera
-	//
-	//
-
-	LLAppViewer::instance()->pingMainloopTimeout("Display:Camera");
-	LLViewerCamera::getInstance()->setZoomParameters(zoom_factor, subfield);
-	LLViewerCamera::getInstance()->setNear(MIN_NEAR_PLANE);
-
-	//////////////////////////
-	//
-	// clear the next buffer
-	// (must follow dynamic texture writing since that uses the frame buffer)
-	//
-
-	if (gDisconnected)
-	{
-		LLAppViewer::instance()->pingMainloopTimeout("Display:Disconnected");
-		render_ui();
-	}
-	
-	//////////////////////////
-	//
-	// Set rendering options
-	//
-	//
-	LLAppViewer::instance()->pingMainloopTimeout("Display:RenderSetup");
-	stop_glerror();
-
-	///////////////////////////////////////
-	//
-	// Slam lighting parameters back to our defaults.
-	// Note that these are not the same as GL defaults...
-
-	stop_glerror();
-	gGL.setAmbientLightColor(LLColor4::white);
-	stop_glerror();
-			
-	/////////////////////////////////////
-	//
-	// Render
-	//
-	// Actually push all of our triangles to the screen.
-	//
-
-	// do render-to-texture stuff here
-	if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_DYNAMIC_TEXTURES))
-	{
-		LLAppViewer::instance()->pingMainloopTimeout("Display:DynamicTextures");
-		LLFastTimer t(FTM_UPDATE_TEXTURES);
-		if (LLViewerDynamicTexture::updateAllInstances())
-		{
-			gGL.setColorMask(true, true);
-			glClear(GL_DEPTH_BUFFER_BIT);
-		}
-	}
-
-	gViewerWindow->setup3DViewport();
-
-	gPipeline.resetFrameStats();	// Reset per-frame statistics.
-	
-	if (!gDisconnected)
-	{
-		LLMemType mt_du(LLMemType::MTYPE_DISPLAY_UPDATE);
-		LLAppViewer::instance()->pingMainloopTimeout("Display:Update");
-		if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD))
-		{ //don't draw hud objects in this frame
-			gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD);
-		}
-
-		if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD_PARTICLES))
-		{ //don't draw hud particles in this frame
-			gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD_PARTICLES);
-		}
-
-		//upkeep gl name pools
-		LLGLNamePool::upkeepPools();
-		
-		stop_glerror();
-		display_update_camera();
-		stop_glerror();
-				
-		// *TODO: merge these two methods
-		{
-			LLMemType mt_uh(LLMemType::MTYPE_DISPLAY_UPDATE_HUD);
-			LLHUDManager::getInstance()->updateEffects();
-			LLHUDObject::updateAll();
-			stop_glerror();
-		}
-
-		{
-			LLMemType mt_ug(LLMemType::MTYPE_DISPLAY_UPDATE_GEOM);
-			const F32 max_geom_update_time = 0.005f*10.f*gFrameIntervalSeconds; // 50 ms/second update time
-			gPipeline.createObjects(max_geom_update_time);
-			gPipeline.processPartitionQ();
-			gPipeline.updateGeom(max_geom_update_time);
-			stop_glerror();
-		}
-
-		gPipeline.updateGL();
-		stop_glerror();
-
-		S32 water_clip = 0;
-		if ((LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_ENVIRONMENT) > 1) &&
-			 (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_WATER) || 
-			  gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_VOIDWATER)))
-		{
-			if (LLViewerCamera::getInstance()->cameraUnderWater())
-			{
-				water_clip = -1;
-			}
-			else
-			{
-				water_clip = 1;
-			}
-		}
-		
-		LLAppViewer::instance()->pingMainloopTimeout("Display:Cull");
-		
-		//Increment drawable frame counter
-		LLDrawable::incrementVisible();
-
-		LLSpatialGroup::sNoDelete = TRUE;
-		LLTexUnit::sWhiteTexture = LLViewerFetchedTexture::sWhiteImagep->getTexName();
-
-		/*if (LLPipeline::sUseOcclusion && LLPipeline::sRenderDeferred)
-		{ //force occlusion on for all render types if doing deferred render (tighter shadow frustum)
-			LLPipeline::sUseOcclusion = 3;
-		}*/
-
-		S32 occlusion = LLPipeline::sUseOcclusion;
-		if (gDepthDirty)
-		{ //depth buffer is invalid, don't overwrite occlusion state
-			LLPipeline::sUseOcclusion = llmin(occlusion, 1);
-		}
-		gDepthDirty = FALSE;
-
-		LLGLState::checkStates();
-		LLGLState::checkTextureChannels();
-		LLGLState::checkClientArrays();
-
-		static LLCullResult result;
-		LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
-		gPipeline.updateCull(*LLViewerCamera::getInstance(), result, water_clip);
-		stop_glerror();
-
-		LLGLState::checkStates();
-		LLGLState::checkTextureChannels();
-		LLGLState::checkClientArrays();
-
-		BOOL to_texture = gPipeline.canUseVertexShaders() &&
-						LLPipeline::sRenderGlow;
-
-		LLAppViewer::instance()->pingMainloopTimeout("Display:Swap");
-		
-		{ 
-			LLMemType mt_ds(LLMemType::MTYPE_DISPLAY_SWAP);
-
-			if (gResizeScreenTexture)
-			{
-				gResizeScreenTexture = FALSE;
-				gPipeline.resizeScreenTexture();
-			}
-
-			gGL.setColorMask(true, true);
-			glClearColor(0,0,0,0);
-
-			LLGLState::checkStates();
-			LLGLState::checkTextureChannels();
-			LLGLState::checkClientArrays();
-
-			if (!for_snapshot)
-			{
-				if (gFrameCount > 1)
-				{ //for some reason, ATI 4800 series will error out if you 
-				  //try to generate a shadow before the first frame is through
-					gPipeline.generateSunShadow(*LLViewerCamera::getInstance());
-				}
-
-				LLVertexBuffer::unbind();
-
-				LLGLState::checkStates();
-				LLGLState::checkTextureChannels();
-				LLGLState::checkClientArrays();
-
-				glh::matrix4f proj = glh_get_current_projection();
-				glh::matrix4f mod = glh_get_current_modelview();
-				glViewport(0,0,512,512);
-				LLVOAvatar::updateFreezeCounter() ;
-
-				if(!LLPipeline::sMemAllocationThrottled)
-				{		
-					LLVOAvatar::updateImpostors();
-				}
-
-				glh_set_current_projection(proj);
-				glh_set_current_modelview(mod);
-				gGL.matrixMode(LLRender::MM_PROJECTION);
-				gGL.loadMatrix(proj.m);
-				gGL.matrixMode(LLRender::MM_MODELVIEW);
-				gGL.loadMatrix(mod.m);
-				gViewerWindow->setup3DViewport();
-
-				LLGLState::checkStates();
-				LLGLState::checkTextureChannels();
-				LLGLState::checkClientArrays();
-
-			}
-			glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
-		}
-
-		LLGLState::checkStates();
-		LLGLState::checkClientArrays();
-
-		//if (!for_snapshot)
-		{
-			LLMemType mt_gw(LLMemType::MTYPE_DISPLAY_GEN_REFLECTION);
-			LLAppViewer::instance()->pingMainloopTimeout("Display:Imagery");
-			gPipeline.generateWaterReflection(*LLViewerCamera::getInstance());
-			gPipeline.generateHighlight(*LLViewerCamera::getInstance());
-			gPipeline.renderPhysicsDisplay();
-		}
-
-		LLGLState::checkStates();
-		LLGLState::checkClientArrays();
-
-		//////////////////////////////////////
-		//
-		// Update images, using the image stats generated during object update/culling
-		//
-		// Can put objects onto the retextured list.
-		//
-		// Doing this here gives hardware occlusion queries extra time to complete
-		LLAppViewer::instance()->pingMainloopTimeout("Display:UpdateImages");
-		
-		{
-			LLMemType mt_iu(LLMemType::MTYPE_DISPLAY_IMAGE_UPDATE);
-			LLFastTimer t(FTM_IMAGE_UPDATE);
-			
-			{
-				LLFastTimer t(FTM_IMAGE_UPDATE_CLASS);
-				LLViewerTexture::updateClass(LLViewerCamera::getInstance()->getVelocityStat()->getMean(),
-											LLViewerCamera::getInstance()->getAngularVelocityStat()->getMean());
-			}
-
-			
-			{
-				LLFastTimer t(FTM_IMAGE_UPDATE_BUMP);
-				gBumpImageList.updateImages();  // must be called before gTextureList version so that it's textures are thrown out first.
-			}
-
-			{
-				LLFastTimer t(FTM_IMAGE_UPDATE_LIST);
-				F32 max_image_decode_time = 0.050f*gFrameIntervalSeconds; // 50 ms/second decode time
-				max_image_decode_time = llclamp(max_image_decode_time, 0.002f, 0.005f ); // min 2ms/frame, max 5ms/frame)
-				gTextureList.updateImages(max_image_decode_time);
-			}
-
-			{
-				LLFastTimer t(FTM_IMAGE_UPDATE_DELETE);
-				//remove dead textures from GL
-				LLImageGL::deleteDeadTextures();
-				stop_glerror();
-			}
-		}
-
-		LLGLState::checkStates();
-		LLGLState::checkClientArrays();
-
-		///////////////////////////////////
-		//
-		// StateSort
-		//
-		// Responsible for taking visible objects, and adding them to the appropriate draw orders.
-		// In the case of alpha objects, z-sorts them first.
-		// Also creates special lists for outlines and selected face rendering.
-		//
-		LLAppViewer::instance()->pingMainloopTimeout("Display:StateSort");
-		{
-			LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
-			LLMemType mt_ss(LLMemType::MTYPE_DISPLAY_STATE_SORT);
-			gPipeline.stateSort(*LLViewerCamera::getInstance(), result);
-			stop_glerror();
-				
-			if (rebuild)
-			{
-				//////////////////////////////////////
-				//
-				// rebuildPools
-				//
-				//
-				gPipeline.rebuildPools();
-				stop_glerror();
-			}
-		}
-
-		LLGLState::checkStates();
-		LLGLState::checkClientArrays();
-
-		LLPipeline::sUseOcclusion = occlusion;
-
-		{
-			LLMemType mt_ds(LLMemType::MTYPE_DISPLAY_SKY);
-			LLAppViewer::instance()->pingMainloopTimeout("Display:Sky");
-			LLFastTimer t(FTM_UPDATE_SKY);	
-			gSky.updateSky();
-		}
-
-		if(gUseWireframe)
-		{
-			glClearColor(0.5f, 0.5f, 0.5f, 0.f);
-			glClear(GL_COLOR_BUFFER_BIT);
-			glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
-		}
-
-		LLAppViewer::instance()->pingMainloopTimeout("Display:RenderStart");
-		
-		//// render frontmost floater opaque for occlusion culling purposes
-		//LLFloater* frontmost_floaterp = gFloaterView->getFrontmost();
-		//// assumes frontmost floater with focus is opaque
-		//if (frontmost_floaterp && gFocusMgr.childHasKeyboardFocus(frontmost_floaterp))
-		//{
-		//	gGL.matrixMode(LLRender::MM_MODELVIEW);
-		//	gGL.pushMatrix();
-		//	{
-		//		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-
-		//		glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
-		//		gGL.loadIdentity();
-
-		//		LLRect floater_rect = frontmost_floaterp->calcScreenRect();
-		//		// deflate by one pixel so rounding errors don't occlude outside of floater extents
-		//		floater_rect.stretch(-1);
-		//		LLRectf floater_3d_rect((F32)floater_rect.mLeft / (F32)gViewerWindow->getWindowWidthScaled(), 
-		//								(F32)floater_rect.mTop / (F32)gViewerWindow->getWindowHeightScaled(),
-		//								(F32)floater_rect.mRight / (F32)gViewerWindow->getWindowWidthScaled(),
-		//								(F32)floater_rect.mBottom / (F32)gViewerWindow->getWindowHeightScaled());
-		//		floater_3d_rect.translate(-0.5f, -0.5f);
-		//		gGL.translatef(0.f, 0.f, -LLViewerCamera::getInstance()->getNear());
-		//		gGL.scalef(LLViewerCamera::getInstance()->getNear() * LLViewerCamera::getInstance()->getAspect() / sinf(LLViewerCamera::getInstance()->getView()), LLViewerCamera::getInstance()->getNear() / sinf(LLViewerCamera::getInstance()->getView()), 1.f);
-		//		gGL.color4fv(LLColor4::white.mV);
-		//		gGL.begin(LLVertexBuffer::QUADS);
-		//		{
-		//			gGL.vertex3f(floater_3d_rect.mLeft, floater_3d_rect.mBottom, 0.f);
-		//			gGL.vertex3f(floater_3d_rect.mLeft, floater_3d_rect.mTop, 0.f);
-		//			gGL.vertex3f(floater_3d_rect.mRight, floater_3d_rect.mTop, 0.f);
-		//			gGL.vertex3f(floater_3d_rect.mRight, floater_3d_rect.mBottom, 0.f);
-		//		}
-		//		gGL.end();
-		//		glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
-		//	}
-		//	gGL.popMatrix();
-		//}
-
-		LLPipeline::sUnderWaterRender = LLViewerCamera::getInstance()->cameraUnderWater() ? TRUE : FALSE;
-		
-		LLGLState::checkStates();
-		LLGLState::checkClientArrays();
-
-		stop_glerror();
-
-		if (to_texture)
-		{
-			gGL.setColorMask(true, true);
-					
-			if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender)
-			{
-				gPipeline.mDeferredScreen.bindTarget();
-				glClearColor(1,0,1,1);
-				gPipeline.mDeferredScreen.clear();
-			}
-			else
-			{
-				gPipeline.mScreen.bindTarget();
-				if (LLPipeline::sUnderWaterRender && !gPipeline.canUseWindLightShaders())
-				{
-					const LLColor4 &col = LLDrawPoolWater::sWaterFogColor;
-					glClearColor(col.mV[0], col.mV[1], col.mV[2], 0.f);
-				}
-				gPipeline.mScreen.clear();
-			}
-			
-			gGL.setColorMask(true, false);
-		}
-		
-		LLAppViewer::instance()->pingMainloopTimeout("Display:RenderGeom");
-		bool exclusiveDraw = false;
-		BOOL allowRenderables = false;
-		BOOL allowPathToBeDrawn = false;
-		if (!(LLAppViewer::instance()->logoutRequestSent() && LLAppViewer::instance()->hasSavedFinalSnapshot())
-				&& !gRestoreGL)
-		{
-			LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
-			LLMemType mt_rg(LLMemType::MTYPE_DISPLAY_RENDER_GEOM);
-			gGL.setColorMask(true, false);
-			if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender)
-			{
-				gPipeline.renderGeomDeferred(*LLViewerCamera::getInstance());
-			}
-			else
-			{
-				//Render any navmesh geometry	
-				if ( LLPathingLib::getInstance() ) 
-				{	
-					//Determine if we can should overlay the navmesh ontop of the scenes typical renderables
-					LLFloaterPathfindingConsole* pFloater = LLFloaterReg::getTypedInstance<LLFloaterPathfindingConsole>("pathfinding_console");
-					if ( pFloater && pFloater->allowAllRenderables() )
-					{
-						allowRenderables = true;
-					}
-					//Determine if we should also draw a user supplied path on top of the scene
-					if ( pFloater && pFloater->getShowPathToggle() )
-					{
-						allowPathToBeDrawn = true;
-					}
-					//NavMesh
-					if ( LLPathingLib::getInstance()->getRenderNavMeshState() )
-					{
-						glClearColor(0.0f, 0.0f, 0.0f, 0.5f);          												
-						glEnable(GL_DEPTH_TEST);                        
-						gGL.setAmbientLightColor( LLColor4::white );
-						LLPathingLib::getInstance()->renderNavMesh( allowRenderables );
-						exclusiveDraw = true;
-					}
-					//physics/exclusion shapes
-					if ( LLPathingLib::getInstance()->getRenderShapeState() )
-					{						
-						LLPathingLib::getInstance()->renderNavMeshShapesVBO();
-						exclusiveDraw = true;
-					}	
-					//User designated path
-					if ( allowPathToBeDrawn )
-					{
-						LLPathingLib::getInstance()->renderPath();
-					}
-				}			
-			}
-			
-			if ( !exclusiveDraw || allowRenderables )					
-			{
-				gPipeline.renderGeom(*LLViewerCamera::getInstance(), TRUE);
-			}
-
-			gGL.setColorMask(true, true);
-
-			//store this frame's modelview matrix for use
-			//when rendering next frame's occlusion queries
-			for (U32 i = 0; i < 16; i++)
-			{
-				gGLLastModelView[i] = gGLModelView[i];
-				gGLLastProjection[i] = gGLProjection[i];
-			}
-			stop_glerror();
-		}
-
-		for (U32 i = 0; i < gGLManager.mNumTextureImageUnits; i++)
-		{ //dummy cleanup of any currently bound textures
-			if (gGL.getTexUnit(i)->getCurrType() != LLTexUnit::TT_NONE)
-			{
-				gGL.getTexUnit(i)->unbind(gGL.getTexUnit(i)->getCurrType());
-				gGL.getTexUnit(i)->disable();
-			}
-		}
-		LLAppViewer::instance()->pingMainloopTimeout("Display:RenderFlush");		
-		
-		if (to_texture)
-		{
-			LLMemType mt_rf(LLMemType::MTYPE_DISPLAY_RENDER_FLUSH);
-			if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender)
-			{
-				gPipeline.mDeferredScreen.flush();
-				if(LLRenderTarget::sUseFBO)
-				{
-					LLRenderTarget::copyContentsToFramebuffer(gPipeline.mDeferredScreen, 0, 0, gPipeline.mDeferredScreen.getWidth(), 
-															  gPipeline.mDeferredScreen.getHeight(), 0, 0, 
-															  gPipeline.mDeferredScreen.getWidth(), 
-															  gPipeline.mDeferredScreen.getHeight(), 
-															  GL_DEPTH_BUFFER_BIT, GL_NEAREST);
-				}
-			}
-			else
-			{
-				gPipeline.mScreen.flush();
-				if(LLRenderTarget::sUseFBO)
-				{				
-					LLRenderTarget::copyContentsToFramebuffer(gPipeline.mScreen, 0, 0, gPipeline.mScreen.getWidth(), 
-															  gPipeline.mScreen.getHeight(), 0, 0, 
-															  gPipeline.mScreen.getWidth(), 
-															  gPipeline.mScreen.getHeight(), 
-															  GL_DEPTH_BUFFER_BIT, GL_NEAREST);
-				}
-			}
-		}
-
-		if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender)
-		{
-			gPipeline.renderDeferredLighting();
-		}
-
-		LLPipeline::sUnderWaterRender = FALSE;
-
-		LLAppViewer::instance()->pingMainloopTimeout("Display:RenderUI");
-		if (!for_snapshot)
-		{
-			LLFastTimer t(FTM_RENDER_UI);
-			render_ui();
-		}
-
-		
-		LLSpatialGroup::sNoDelete = FALSE;
-		gPipeline.clearReferences();
-
-		gPipeline.rebuildGroups();
-	}
-
-	LLAppViewer::instance()->pingMainloopTimeout("Display:FrameStats");
-	
-	stop_glerror();
-
-	if (LLPipeline::sRenderFrameTest)
-	{
-		send_agent_resume();
-		LLPipeline::sRenderFrameTest = FALSE;
-	}
-
-	display_stats();
-				
-	LLAppViewer::instance()->pingMainloopTimeout("Display:Done");
-}
-
-void render_hud_attachments()
-{
-	LLMemType mt_ra(LLMemType::MTYPE_DISPLAY_RENDER_ATTACHMENTS);
-	gGL.matrixMode(LLRender::MM_PROJECTION);
-	gGL.pushMatrix();
-	gGL.matrixMode(LLRender::MM_MODELVIEW);
-	gGL.pushMatrix();
-		
-	glh::matrix4f current_proj = glh_get_current_projection();
-	glh::matrix4f current_mod = glh_get_current_modelview();
-
-	// clamp target zoom level to reasonable values
-	gAgentCamera.mHUDTargetZoom = llclamp(gAgentCamera.mHUDTargetZoom, 0.1f, 1.f);
-	// smoothly interpolate current zoom level
-	gAgentCamera.mHUDCurZoom = lerp(gAgentCamera.mHUDCurZoom, gAgentCamera.mHUDTargetZoom, LLCriticalDamp::getInterpolant(0.03f));
-
-	if (LLPipeline::sShowHUDAttachments && !gDisconnected && setup_hud_matrices())
-	{
-		LLCamera hud_cam = *LLViewerCamera::getInstance();
-		LLVector3 origin = hud_cam.getOrigin();
-		hud_cam.setOrigin(-1.f,0,0);
-		hud_cam.setAxes(LLVector3(1,0,0), LLVector3(0,1,0), LLVector3(0,0,1));
-		LLViewerCamera::updateFrustumPlanes(hud_cam, TRUE);
-
-		bool render_particles = gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES) && gSavedSettings.getBOOL("RenderHUDParticles");
-		
-		//only render hud objects
-		gPipeline.pushRenderTypeMask();
-		
-		// turn off everything
-		gPipeline.andRenderTypeMask(LLPipeline::END_RENDER_TYPES);
-		// turn on HUD
-		gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD);
-		// turn on HUD particles
-		gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD_PARTICLES);
-
-		// if particles are off, turn off hud-particles as well
-		if (!render_particles)
-		{
-			// turn back off HUD particles
-			gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD_PARTICLES);
-		}
-
-		bool has_ui = gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI);
-		if (has_ui)
-		{
-			gPipeline.toggleRenderDebugFeature((void*) LLPipeline::RENDER_DEBUG_FEATURE_UI);
-		}
-
-		S32 use_occlusion = LLPipeline::sUseOcclusion;
-		LLPipeline::sUseOcclusion = 0;
-				
-		//cull, sort, and render hud objects
-		static LLCullResult result;
-		LLSpatialGroup::sNoDelete = TRUE;
-
-		LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
-		gPipeline.updateCull(hud_cam, result);
-
-		gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_BUMP);
-		gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_SIMPLE);
-		gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_VOLUME);
-		gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_ALPHA);
-		gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_FULLBRIGHT);
-		gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_ALPHA);
-		gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_ALPHA_MASK);
-		gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_BUMP);
-		gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT);
-		gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK);
-		gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_SHINY);
-		gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_SHINY);
-		gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_INVISIBLE);
-		gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_INVISI_SHINY);
-		
-		gPipeline.stateSort(hud_cam, result);
-
-		gPipeline.renderGeom(hud_cam);
-
-		LLSpatialGroup::sNoDelete = FALSE;
-		//gPipeline.clearReferences();
-
-		render_hud_elements();
-
-		//restore type mask
-		gPipeline.popRenderTypeMask();
-
-		if (has_ui)
-		{
-			gPipeline.toggleRenderDebugFeature((void*) LLPipeline::RENDER_DEBUG_FEATURE_UI);
-		}
-		LLPipeline::sUseOcclusion = use_occlusion;
-	}
-	gGL.matrixMode(LLRender::MM_PROJECTION);
-	gGL.popMatrix();
-	gGL.matrixMode(LLRender::MM_MODELVIEW);
-	gGL.popMatrix();
-	
-	glh_set_current_projection(current_proj);
-	glh_set_current_modelview(current_mod);
-}
-
-LLRect get_whole_screen_region()
-{
-	LLRect whole_screen = gViewerWindow->getWorldViewRectScaled();
-	
-	// apply camera zoom transform (for high res screenshots)
-	F32 zoom_factor = LLViewerCamera::getInstance()->getZoomFactor();
-	S16 sub_region = LLViewerCamera::getInstance()->getZoomSubRegion();
-	if (zoom_factor > 1.f)
-	{
-		S32 num_horizontal_tiles = llceil(zoom_factor);
-		S32 tile_width = llround((F32)gViewerWindow->getWorldViewWidthScaled() / zoom_factor);
-		S32 tile_height = llround((F32)gViewerWindow->getWorldViewHeightScaled() / zoom_factor);
-		int tile_y = sub_region / num_horizontal_tiles;
-		int tile_x = sub_region - (tile_y * num_horizontal_tiles);
-			
-		whole_screen.setLeftTopAndSize(tile_x * tile_width, gViewerWindow->getWorldViewHeightScaled() - (tile_y * tile_height), tile_width, tile_height);
-	}
-	return whole_screen;
-}
-
-bool get_hud_matrices(const LLRect& screen_region, glh::matrix4f &proj, glh::matrix4f &model)
-{
-	if (isAgentAvatarValid() && gAgentAvatarp->hasHUDAttachment())
-	{
-		F32 zoom_level = gAgentCamera.mHUDCurZoom;
-		LLBBox hud_bbox = gAgentAvatarp->getHUDBBox();
-		
-		F32 hud_depth = llmax(1.f, hud_bbox.getExtentLocal().mV[VX] * 1.1f);
-		proj = gl_ortho(-0.5f * LLViewerCamera::getInstance()->getAspect(), 0.5f * LLViewerCamera::getInstance()->getAspect(), -0.5f, 0.5f, 0.f, hud_depth);
-		proj.element(2,2) = -0.01f;
-		
-		F32 aspect_ratio = LLViewerCamera::getInstance()->getAspect();
-		
-		glh::matrix4f mat;
-		F32 scale_x = (F32)gViewerWindow->getWorldViewWidthScaled() / (F32)screen_region.getWidth();
-		F32 scale_y = (F32)gViewerWindow->getWorldViewHeightScaled() / (F32)screen_region.getHeight();
-		mat.set_scale(glh::vec3f(scale_x, scale_y, 1.f));
-		mat.set_translate(
-			glh::vec3f(clamp_rescale((F32)(screen_region.getCenterX() - screen_region.mLeft), 0.f, (F32)gViewerWindow->getWorldViewWidthScaled(), 0.5f * scale_x * aspect_ratio, -0.5f * scale_x * aspect_ratio),
-					   clamp_rescale((F32)(screen_region.getCenterY() - screen_region.mBottom), 0.f, (F32)gViewerWindow->getWorldViewHeightScaled(), 0.5f * scale_y, -0.5f * scale_y),
-					   0.f));
-		proj *= mat;
-		
-		glh::matrix4f tmp_model((GLfloat*) OGL_TO_CFR_ROTATION);
-		
-		mat.set_scale(glh::vec3f(zoom_level, zoom_level, zoom_level));
-		mat.set_translate(glh::vec3f(-hud_bbox.getCenterLocal().mV[VX] + (hud_depth * 0.5f), 0.f, 0.f));
-		
-		tmp_model *= mat;
-		model = tmp_model;		
-		return TRUE;
-	}
-	else
-	{
-		return FALSE;
-	}
-}
-
-bool get_hud_matrices(glh::matrix4f &proj, glh::matrix4f &model)
-{
-	LLRect whole_screen = get_whole_screen_region();
-	return get_hud_matrices(whole_screen, proj, model);
-}
-
-BOOL setup_hud_matrices()
-{
-	LLRect whole_screen = get_whole_screen_region();
-	return setup_hud_matrices(whole_screen);
-}
-
-BOOL setup_hud_matrices(const LLRect& screen_region)
-{
-	glh::matrix4f proj, model;
-	bool result = get_hud_matrices(screen_region, proj, model);
-	if (!result) return result;
-	
-	// set up transform to keep HUD objects in front of camera
-	gGL.matrixMode(LLRender::MM_PROJECTION);
-	gGL.loadMatrix(proj.m);
-	glh_set_current_projection(proj);
-	
-	gGL.matrixMode(LLRender::MM_MODELVIEW);
-	gGL.loadMatrix(model.m);
-	glh_set_current_modelview(model);
-	return TRUE;
-}
-
-static LLFastTimer::DeclareTimer FTM_SWAP("Swap");
-
-void render_ui(F32 zoom_factor, int subfield)
-{
-	LLMemType mt_ru(LLMemType::MTYPE_DISPLAY_RENDER_UI);
-	LLGLState::checkStates();
-	
-	glh::matrix4f saved_view = glh_get_current_modelview();
-
-	if (!gSnapshot)
-	{
-		gGL.pushMatrix();
-		gGL.loadMatrix(gGLLastModelView);
-		glh_set_current_modelview(glh_copy_matrix(gGLLastModelView));
-	}
-	
-	{
-		BOOL to_texture = gPipeline.canUseVertexShaders() &&
-							LLPipeline::sRenderGlow;
-
-		if (to_texture)
-		{
-			gPipeline.renderBloom(gSnapshot, zoom_factor, subfield);
-		}
-		
-		render_hud_elements();
-		render_hud_attachments();
-	}
-
-	LLGLSDefault gls_default;
-	LLGLSUIDefault gls_ui;
-	{
-		gPipeline.disableLights();
-	}
-
-	{
-		gGL.color4f(1,1,1,1);
-		if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
-		{
-			LLFastTimer t(FTM_RENDER_UI);
-
-			if (!gDisconnected)
-			{
-				render_ui_3d();
-				LLGLState::checkStates();
-			}
-			else
-			{
-				render_disconnected_background();
-			}
-
-			render_ui_2d();
-			LLGLState::checkStates();
-		}
-		gGL.flush();
-
-		{
-			gViewerWindow->setup2DRender();
-			gViewerWindow->updateDebugText();
-			gViewerWindow->drawDebugText();
-		}
-
-		LLVertexBuffer::unbind();
-	}
-
-	if (!gSnapshot)
-	{
-		glh_set_current_modelview(saved_view);
-		gGL.popMatrix();
-	}
-
-	if (gDisplaySwapBuffers)
-	{
-		LLFastTimer t(FTM_SWAP);
-		gViewerWindow->getWindow()->swapBuffers();
-	}
-	gDisplaySwapBuffers = TRUE;
-}
-
-void renderCoordinateAxes()
-{
-	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-	gGL.begin(LLRender::LINES);
-		gGL.color3f(1.0f, 0.0f, 0.0f);   // i direction = X-Axis = red
-		gGL.vertex3f(0.0f, 0.0f, 0.0f);
-		gGL.vertex3f(2.0f, 0.0f, 0.0f);
-		gGL.vertex3f(3.0f, 0.0f, 0.0f);
-		gGL.vertex3f(5.0f, 0.0f, 0.0f);
-		gGL.vertex3f(6.0f, 0.0f, 0.0f);
-		gGL.vertex3f(8.0f, 0.0f, 0.0f);
-		// Make an X
-		gGL.vertex3f(11.0f, 1.0f, 1.0f);
-		gGL.vertex3f(11.0f, -1.0f, -1.0f);
-		gGL.vertex3f(11.0f, 1.0f, -1.0f);
-		gGL.vertex3f(11.0f, -1.0f, 1.0f);
-
-		gGL.color3f(0.0f, 1.0f, 0.0f);   // j direction = Y-Axis = green
-		gGL.vertex3f(0.0f, 0.0f, 0.0f);
-		gGL.vertex3f(0.0f, 2.0f, 0.0f);
-		gGL.vertex3f(0.0f, 3.0f, 0.0f);
-		gGL.vertex3f(0.0f, 5.0f, 0.0f);
-		gGL.vertex3f(0.0f, 6.0f, 0.0f);
-		gGL.vertex3f(0.0f, 8.0f, 0.0f);
-		// Make a Y
-		gGL.vertex3f(1.0f, 11.0f, 1.0f);
-		gGL.vertex3f(0.0f, 11.0f, 0.0f);
-		gGL.vertex3f(-1.0f, 11.0f, 1.0f);
-		gGL.vertex3f(0.0f, 11.0f, 0.0f);
-		gGL.vertex3f(0.0f, 11.0f, 0.0f);
-		gGL.vertex3f(0.0f, 11.0f, -1.0f);
-
-		gGL.color3f(0.0f, 0.0f, 1.0f);   // Z-Axis = blue
-		gGL.vertex3f(0.0f, 0.0f, 0.0f);
-		gGL.vertex3f(0.0f, 0.0f, 2.0f);
-		gGL.vertex3f(0.0f, 0.0f, 3.0f);
-		gGL.vertex3f(0.0f, 0.0f, 5.0f);
-		gGL.vertex3f(0.0f, 0.0f, 6.0f);
-		gGL.vertex3f(0.0f, 0.0f, 8.0f);
-		// Make a Z
-		gGL.vertex3f(-1.0f, 1.0f, 11.0f);
-		gGL.vertex3f(1.0f, 1.0f, 11.0f);
-		gGL.vertex3f(1.0f, 1.0f, 11.0f);
-		gGL.vertex3f(-1.0f, -1.0f, 11.0f);
-		gGL.vertex3f(-1.0f, -1.0f, 11.0f);
-		gGL.vertex3f(1.0f, -1.0f, 11.0f);
-	gGL.end();
-}
-
-
-void draw_axes() 
-{
-	LLGLSUIDefault gls_ui;
-	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-	// A vertical white line at origin
-	LLVector3 v = gAgent.getPositionAgent();
-	gGL.begin(LLRender::LINES);
-		gGL.color3f(1.0f, 1.0f, 1.0f); 
-		gGL.vertex3f(0.0f, 0.0f, 0.0f);
-		gGL.vertex3f(0.0f, 0.0f, 40.0f);
-	gGL.end();
-	// Some coordinate axes
-	gGL.pushMatrix();
-		gGL.translatef( v.mV[VX], v.mV[VY], v.mV[VZ] );
-		renderCoordinateAxes();
-	gGL.popMatrix();
-}
-
-void render_ui_3d()
-{
-	LLGLSPipeline gls_pipeline;
-
-	//////////////////////////////////////
-	//
-	// Render 3D UI elements
-	// NOTE: zbuffer is cleared before we get here by LLDrawPoolHUD,
-	//		 so 3d elements requiring Z buffer are moved to LLDrawPoolHUD
-	//
-
-	/////////////////////////////////////////////////////////////
-	//
-	// Render 2.5D elements (2D elements in the world)
-	// Stuff without z writes
-	//
-
-	// Debugging stuff goes before the UI.
-
-	stop_glerror();
-	
-	if (LLGLSLShader::sNoFixedFunction)
-	{
-		gUIProgram.bind();
-	}
-
-	// Coordinate axes
-	if (gSavedSettings.getBOOL("ShowAxes"))
-	{
-		draw_axes();
-	}
-
-	gViewerWindow->renderSelections(FALSE, FALSE, TRUE); // Non HUD call in render_hud_elements
-	stop_glerror();
-}
-
-void render_ui_2d()
-{
-	LLGLSUIDefault gls_ui;
-
-	/////////////////////////////////////////////////////////////
-	//
-	// Render 2D UI elements that overlay the world (no z compare)
-
-	//  Disable wireframe mode below here, as this is HUD/menus
-	glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
-
-	//  Menu overlays, HUD, etc
-	gViewerWindow->setup2DRender();
-
-	F32 zoom_factor = LLViewerCamera::getInstance()->getZoomFactor();
-	S16 sub_region = LLViewerCamera::getInstance()->getZoomSubRegion();
-
-	if (zoom_factor > 1.f)
-	{
-		//decompose subregion number to x and y values
-		int pos_y = sub_region / llceil(zoom_factor);
-		int pos_x = sub_region - (pos_y*llceil(zoom_factor));
-		// offset for this tile
-		LLFontGL::sCurOrigin.mX -= llround((F32)gViewerWindow->getWindowWidthScaled() * (F32)pos_x / zoom_factor);
-		LLFontGL::sCurOrigin.mY -= llround((F32)gViewerWindow->getWindowHeightScaled() * (F32)pos_y / zoom_factor);
-	}
-
-	stop_glerror();
-	//gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
-
-	// render outline for HUD
-	if (isAgentAvatarValid() && gAgentCamera.mHUDCurZoom < 0.98f)
-	{
-		gGL.pushMatrix();
-		S32 half_width = (gViewerWindow->getWorldViewWidthScaled() / 2);
-		S32 half_height = (gViewerWindow->getWorldViewHeightScaled() / 2);
-		gGL.scalef(LLUI::sGLScaleFactor.mV[0], LLUI::sGLScaleFactor.mV[1], 1.f);
-		gGL.translatef((F32)half_width, (F32)half_height, 0.f);
-		F32 zoom = gAgentCamera.mHUDCurZoom;
-		gGL.scalef(zoom,zoom,1.f);
-		gGL.color4fv(LLColor4::white.mV);
-		gl_rect_2d(-half_width, half_height, half_width, -half_height, FALSE);
-		gGL.popMatrix();
-		stop_glerror();
-	}
-	
-
-	if (gSavedSettings.getBOOL("RenderUIBuffer"))
-	{
-		if (LLUI::sDirty)
-		{
-			LLUI::sDirty = FALSE;
-			LLRect t_rect;
-
-			gPipeline.mUIScreen.bindTarget();
-			gGL.setColorMask(true, true);
-			{
-				static const S32 pad = 8;
-
-				LLUI::sDirtyRect.mLeft -= pad;
-				LLUI::sDirtyRect.mRight += pad;
-				LLUI::sDirtyRect.mBottom -= pad;
-				LLUI::sDirtyRect.mTop += pad;
-
-				LLGLEnable scissor(GL_SCISSOR_TEST);
-				static LLRect last_rect = LLUI::sDirtyRect;
-
-				//union with last rect to avoid mouse poop
-				last_rect.unionWith(LLUI::sDirtyRect);
-								
-				t_rect = LLUI::sDirtyRect;
-				LLUI::sDirtyRect = last_rect;
-				last_rect = t_rect;
-			
-				last_rect.mLeft = LLRect::tCoordType(last_rect.mLeft / LLUI::sGLScaleFactor.mV[0]);
-				last_rect.mRight = LLRect::tCoordType(last_rect.mRight / LLUI::sGLScaleFactor.mV[0]);
-				last_rect.mTop = LLRect::tCoordType(last_rect.mTop / LLUI::sGLScaleFactor.mV[1]);
-				last_rect.mBottom = LLRect::tCoordType(last_rect.mBottom / LLUI::sGLScaleFactor.mV[1]);
-
-				LLRect clip_rect(last_rect);
-				
-				glClear(GL_COLOR_BUFFER_BIT);
-
-				gViewerWindow->draw();
-			}
-
-			gPipeline.mUIScreen.flush();
-			gGL.setColorMask(true, false);
-
-			LLUI::sDirtyRect = t_rect;
-		}
-
-		LLGLDisable cull(GL_CULL_FACE);
-		LLGLDisable blend(GL_BLEND);
-		S32 width = gViewerWindow->getWindowWidthScaled();
-		S32 height = gViewerWindow->getWindowHeightScaled();
-		gGL.getTexUnit(0)->bind(&gPipeline.mUIScreen);
-		gGL.begin(LLRender::TRIANGLE_STRIP);
-		gGL.color4f(1,1,1,1);
-		gGL.texCoord2f(0, 0);			gGL.vertex2i(0, 0);
-		gGL.texCoord2f(width, 0);		gGL.vertex2i(width, 0);
-		gGL.texCoord2f(0, height);		gGL.vertex2i(0, height);
-		gGL.texCoord2f(width, height);	gGL.vertex2i(width, height);
-		gGL.end();
-	}
-	else
-	{
-		gViewerWindow->draw();
-	}
-
-
-
-	// reset current origin for font rendering, in case of tiling render
-	LLFontGL::sCurOrigin.set(0, 0);
-}
-
-void render_disconnected_background()
-{
-	if (LLGLSLShader::sNoFixedFunction)
-	{
-		gUIProgram.bind();
-	}
-
-	gGL.color4f(1,1,1,1);
-	if (!gDisconnectedImagep && gDisconnected)
-	{
-		llinfos << "Loading last bitmap..." << llendl;
-
-		std::string temp_str;
-		temp_str = gDirUtilp->getLindenUserDir() + gDirUtilp->getDirDelimiter() + SCREEN_LAST_FILENAME;
-
-		LLPointer<LLImageBMP> image_bmp = new LLImageBMP;
-		if( !image_bmp->load(temp_str) )
-		{
-			//llinfos << "Bitmap load failed" << llendl;
-			return;
-		}
-		
-		LLPointer<LLImageRaw> raw = new LLImageRaw;
-		if (!image_bmp->decode(raw, 0.0f))
-		{
-			llinfos << "Bitmap decode failed" << llendl;
-			gDisconnectedImagep = NULL;
-			return;
-		}
-
-		U8 *rawp = raw->getData();
-		S32 npixels = (S32)image_bmp->getWidth()*(S32)image_bmp->getHeight();
-		for (S32 i = 0; i < npixels; i++)
-		{
-			S32 sum = 0;
-			sum = *rawp + *(rawp+1) + *(rawp+2);
-			sum /= 3;
-			*rawp = ((S32)sum*6 + *rawp)/7;
-			rawp++;
-			*rawp = ((S32)sum*6 + *rawp)/7;
-			rawp++;
-			*rawp = ((S32)sum*6 + *rawp)/7;
-			rawp++;
-		}
-
-		
-		raw->expandToPowerOfTwo();
-		gDisconnectedImagep = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE );
-		gStartTexture = gDisconnectedImagep;
-		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-	}
-
-	// Make sure the progress view always fills the entire window.
-	S32 width = gViewerWindow->getWindowWidthScaled();
-	S32 height = gViewerWindow->getWindowHeightScaled();
-
-	if (gDisconnectedImagep)
-	{
-		LLGLSUIDefault gls_ui;
-		gViewerWindow->setup2DRender();
-		gGL.pushMatrix();
-		{
-			// scale ui to reflect UIScaleFactor
-			// this can't be done in setup2DRender because it requires a
-			// pushMatrix/popMatrix pair
-			const LLVector2& display_scale = gViewerWindow->getDisplayScale();
-			gGL.scalef(display_scale.mV[VX], display_scale.mV[VY], 1.f);
-
-			gGL.getTexUnit(0)->bind(gDisconnectedImagep);
-			gGL.color4f(1.f, 1.f, 1.f, 1.f);
-			gl_rect_2d_simple_tex(width, height);
-			gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-		}
-		gGL.popMatrix();
-	}
-	gGL.flush();
-
-	if (LLGLSLShader::sNoFixedFunction)
-	{
-		gUIProgram.unbind();
-	}
-
-}
-
-void display_cleanup()
-{
-	gDisconnectedImagep = NULL;
-}
+/** 
+ * @file llviewerdisplay.cpp
+ * @brief LLViewerDisplay class implementation
+ *
+ * $LicenseInfo:firstyear=2004&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$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llviewerdisplay.h"
+
+#include "llgl.h"
+#include "llrender.h"
+#include "llglheaders.h"
+#include "llagent.h"
+#include "llagentcamera.h"
+#include "llviewercontrol.h"
+#include "llcoord.h"
+#include "llcriticaldamp.h"
+#include "lldir.h"
+#include "lldynamictexture.h"
+#include "lldrawpoolalpha.h"
+#include "llfeaturemanager.h"
+//#include "llfirstuse.h"
+#include "llhudmanager.h"
+#include "llimagebmp.h"
+#include "llmemory.h"
+#include "llselectmgr.h"
+#include "llsky.h"
+#include "llstartup.h"
+#include "lltoolfocus.h"
+#include "lltoolmgr.h"
+#include "lltooldraganddrop.h"
+#include "lltoolpie.h"
+#include "lltracker.h"
+#include "lltrans.h"
+#include "llui.h"
+#include "llviewercamera.h"
+#include "llviewerobjectlist.h"
+#include "llviewerparcelmgr.h"
+#include "llviewerwindow.h"
+#include "llvoavatarself.h"
+#include "llvograss.h"
+#include "llworld.h"
+#include "pipeline.h"
+#include "llspatialpartition.h"
+#include "llappviewer.h"
+#include "llstartup.h"
+#include "llviewershadermgr.h"
+#include "llfasttimer.h"
+#include "llfloatertools.h"
+#include "llviewertexturelist.h"
+#include "llfocusmgr.h"
+#include "llcubemap.h"
+#include "llviewerregion.h"
+#include "lldrawpoolwater.h"
+#include "lldrawpoolbump.h"
+#include "llwlparammanager.h"
+#include "llwaterparammanager.h"
+#include "llpostprocess.h"
+#include "LLPathingLib.h"
+#include "llfloaterpathfindingconsole.h"
+#include "llfloaterreg.h"
+
+extern LLPointer<LLViewerTexture> gStartTexture;
+
+LLPointer<LLViewerTexture> gDisconnectedImagep = NULL;
+
+// used to toggle renderer back on after teleport
+const F32 TELEPORT_RENDER_DELAY = 20.f; // Max time a teleport is allowed to take before we raise the curtain
+const F32 TELEPORT_ARRIVAL_DELAY = 2.f; // Time to preload the world before raising the curtain after we've actually already arrived.
+const F32 TELEPORT_LOCAL_DELAY = 1.0f;  // Delay to prevent teleports after starting an in-sim teleport.
+BOOL		 gTeleportDisplay = FALSE;
+LLFrameTimer gTeleportDisplayTimer;
+LLFrameTimer gTeleportArrivalTimer;
+const F32		RESTORE_GL_TIME = 5.f;	// Wait this long while reloading textures before we raise the curtain
+
+BOOL gForceRenderLandFence = FALSE;
+BOOL gDisplaySwapBuffers = FALSE;
+BOOL gDepthDirty = FALSE;
+BOOL gResizeScreenTexture = FALSE;
+BOOL gWindowResized = FALSE;
+BOOL gSnapshot = FALSE;
+
+U32 gRecentFrameCount = 0; // number of 'recent' frames
+LLFrameTimer gRecentFPSTime;
+LLFrameTimer gRecentMemoryTime;
+
+// Rendering stuff
+void pre_show_depth_buffer();
+void post_show_depth_buffer();
+void render_ui(F32 zoom_factor = 1.f, int subfield = 0);
+void render_hud_attachments();
+void render_ui_3d();
+void render_ui_2d();
+void render_disconnected_background();
+
+void display_startup()
+{
+	if (   !gViewerWindow->getActive()
+		|| !gViewerWindow->getWindow()->getVisible() 
+		|| gViewerWindow->getWindow()->getMinimized() )
+	{
+		return; 
+	}
+
+	gPipeline.updateGL();
+
+	// Update images?
+	//gImageList.updateImages(0.01f);
+	LLTexUnit::sWhiteTexture = LLViewerFetchedTexture::sWhiteImagep->getTexName();
+
+	LLGLSDefault gls_default;
+
+	// Required for HTML update in login screen
+	static S32 frame_count = 0;
+
+	LLGLState::checkStates();
+	LLGLState::checkTextureChannels();
+
+	if (frame_count++ > 1) // make sure we have rendered a frame first
+	{
+		LLViewerDynamicTexture::updateAllInstances();
+	}
+
+	LLGLState::checkStates();
+	LLGLState::checkTextureChannels();
+
+	glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+	LLGLSUIDefault gls_ui;
+	gPipeline.disableLights();
+
+	gViewerWindow->setup2DRender();
+	gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
+
+	gGL.color4f(1,1,1,1);
+	gViewerWindow->draw();
+	gGL.flush();
+
+	LLVertexBuffer::unbind();
+
+	LLGLState::checkStates();
+	LLGLState::checkTextureChannels();
+
+	gViewerWindow->getWindow()->swapBuffers();
+	glClear(GL_DEPTH_BUFFER_BIT);
+}
+
+void display_update_camera()
+{
+	LLMemType mt_uc(LLMemType::MTYPE_DISPLAY_UPDATE_CAMERA);
+	// TODO: cut draw distance down if customizing avatar?
+	// TODO: cut draw distance on per-parcel basis?
+
+	// Cut draw distance in half when customizing avatar,
+	// but on the viewer only.
+	F32 final_far = gAgentCamera.mDrawDistance;
+	if (CAMERA_MODE_CUSTOMIZE_AVATAR == gAgentCamera.getCameraMode())
+	{
+		final_far *= 0.5f;
+	}
+	LLViewerCamera::getInstance()->setFar(final_far);
+	gViewerWindow->setup3DRender();
+	
+	// update all the sky/atmospheric/water settings
+	LLWLParamManager::getInstance()->update(LLViewerCamera::getInstance());
+	LLWaterParamManager::getInstance()->update(LLViewerCamera::getInstance());
+
+	// Update land visibility too
+	LLWorld::getInstance()->setLandFarClip(final_far);
+}
+
+// Write some stats to llinfos
+void display_stats()
+{
+	F32 fps_log_freq = gSavedSettings.getF32("FPSLogFrequency");
+	if (fps_log_freq > 0.f && gRecentFPSTime.getElapsedTimeF32() >= fps_log_freq)
+	{
+		F32 fps = gRecentFrameCount / fps_log_freq;
+		llinfos << llformat("FPS: %.02f", fps) << llendl;
+		gRecentFrameCount = 0;
+		gRecentFPSTime.reset();
+	}
+	F32 mem_log_freq = gSavedSettings.getF32("MemoryLogFrequency");
+	if (mem_log_freq > 0.f && gRecentMemoryTime.getElapsedTimeF32() >= mem_log_freq)
+	{
+		gMemoryAllocated = LLMemory::getCurrentRSS();
+		U32 memory = (U32)(gMemoryAllocated / (1024*1024));
+		llinfos << llformat("MEMORY: %d MB", memory) << llendl;
+		LLMemory::logMemoryInfo(TRUE) ;
+		gRecentMemoryTime.reset();
+	}
+}
+
+static LLFastTimer::DeclareTimer FTM_PICK("Picking");
+static LLFastTimer::DeclareTimer FTM_RENDER("Render", true);
+static LLFastTimer::DeclareTimer FTM_UPDATE_SKY("Update Sky");
+static LLFastTimer::DeclareTimer FTM_UPDATE_TEXTURES("Update Textures");
+static LLFastTimer::DeclareTimer FTM_IMAGE_UPDATE("Update Images");
+static LLFastTimer::DeclareTimer FTM_IMAGE_UPDATE_CLASS("Class");
+static LLFastTimer::DeclareTimer FTM_IMAGE_UPDATE_BUMP("Bump");
+static LLFastTimer::DeclareTimer FTM_IMAGE_UPDATE_LIST("List");
+static LLFastTimer::DeclareTimer FTM_IMAGE_UPDATE_DELETE("Delete");
+
+// Paint the display!
+void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
+{
+	LLMemType mt_render(LLMemType::MTYPE_RENDER);
+	LLFastTimer t(FTM_RENDER);
+
+	if (gWindowResized)
+	{ //skip render on frames where window has been resized
+		gGL.flush();
+		glClear(GL_COLOR_BUFFER_BIT);
+		gViewerWindow->getWindow()->swapBuffers();
+		LLPipeline::refreshCachedSettings();
+		gPipeline.resizeScreenTexture();
+		gResizeScreenTexture = FALSE;
+		gWindowResized = FALSE;
+		return;
+	}
+
+	if (LLPipeline::sRenderDeferred)
+	{ //hack to make sky show up in deferred snapshots
+		for_snapshot = FALSE;
+	}
+
+	if (LLPipeline::sRenderFrameTest)
+	{
+		send_agent_pause();
+	}
+
+	gSnapshot = for_snapshot;
+
+	LLGLSDefault gls_default;
+	LLGLDepthTest gls_depth(GL_TRUE, GL_TRUE, GL_LEQUAL);
+	
+	LLVertexBuffer::unbind();
+
+	LLGLState::checkStates();
+	LLGLState::checkTextureChannels();
+	
+	stop_glerror();
+
+	gPipeline.disableLights();
+	
+	stop_glerror();
+
+	// Don't draw if the window is hidden or minimized.
+	// In fact, must explicitly check the minimized state before drawing.
+	// Attempting to draw into a minimized window causes a GL error. JC
+	if (   !gViewerWindow->getActive()
+		|| !gViewerWindow->getWindow()->getVisible() 
+		|| gViewerWindow->getWindow()->getMinimized() )
+	{
+		// Clean up memory the pools may have allocated
+		if (rebuild)
+		{
+			stop_glerror();
+			gPipeline.rebuildPools();
+			stop_glerror();
+		}
+
+		stop_glerror();
+		gViewerWindow->returnEmptyPicks();
+		stop_glerror();
+		return; 
+	}
+
+	gViewerWindow->checkSettings();
+	
+	{
+		LLFastTimer ftm(FTM_PICK);
+		LLAppViewer::instance()->pingMainloopTimeout("Display:Pick");
+		gViewerWindow->performPick();
+	}
+	
+	LLAppViewer::instance()->pingMainloopTimeout("Display:CheckStates");
+	LLGLState::checkStates();
+	LLGLState::checkTextureChannels();
+	
+	//////////////////////////////////////////////////////////
+	//
+	// Logic for forcing window updates if we're in drone mode.
+	//
+
+	// *TODO: Investigate running display() during gHeadlessClient.  See if this early exit is needed DK 2011-02-18
+	if (gHeadlessClient) 
+	{
+#if LL_WINDOWS
+		static F32 last_update_time = 0.f;
+		if ((gFrameTimeSeconds - last_update_time) > 1.f)
+		{
+			InvalidateRect((HWND)gViewerWindow->getPlatformWindow(), NULL, FALSE);
+			last_update_time = gFrameTimeSeconds;
+		}
+#elif LL_DARWIN
+		// MBW -- Do something clever here.
+#endif
+		// Not actually rendering, don't bother.
+		return;
+	}
+
+
+	//
+	// Bail out if we're in the startup state and don't want to try to
+	// render the world.
+	//
+	if (LLStartUp::getStartupState() < STATE_STARTED)
+	{
+		LLAppViewer::instance()->pingMainloopTimeout("Display:Startup");
+		display_startup();
+		return;
+	}
+
+	//LLGLState::verify(FALSE);
+
+	/////////////////////////////////////////////////
+	//
+	// Update GL Texture statistics (used for discard logic?)
+	//
+
+	LLAppViewer::instance()->pingMainloopTimeout("Display:TextureStats");
+	stop_glerror();
+
+	LLImageGL::updateStats(gFrameTimeSeconds);
+	
+	LLVOAvatar::sRenderName = gSavedSettings.getS32("AvatarNameTagMode");
+	LLVOAvatar::sRenderGroupTitles = (gSavedSettings.getBOOL("NameTagShowGroupTitles") && gSavedSettings.getS32("AvatarNameTagMode"));
+	
+	gPipeline.mBackfaceCull = TRUE;
+	gFrameCount++;
+	gRecentFrameCount++;
+	if (gFocusMgr.getAppHasFocus())
+	{
+		gForegroundFrameCount++;
+	}
+
+	//////////////////////////////////////////////////////////
+	//
+	// Display start screen if we're teleporting, and skip render
+	//
+
+	if (gTeleportDisplay)
+	{
+		LLAppViewer::instance()->pingMainloopTimeout("Display:Teleport");
+		const F32 TELEPORT_ARRIVAL_DELAY = 2.f; // Time to preload the world before raising the curtain after we've actually already arrived.
+
+		S32 attach_count = 0;
+		if (isAgentAvatarValid())
+		{
+			attach_count = gAgentAvatarp->getAttachmentCount();
+		}
+		F32 teleport_save_time = TELEPORT_EXPIRY + TELEPORT_EXPIRY_PER_ATTACHMENT * attach_count;
+		F32 teleport_elapsed = gTeleportDisplayTimer.getElapsedTimeF32();
+		F32 teleport_percent = teleport_elapsed * (100.f / teleport_save_time);
+		if( (gAgent.getTeleportState() != LLAgent::TELEPORT_START) && (teleport_percent > 100.f) )
+		{
+			// Give up.  Don't keep the UI locked forever.
+			gAgent.setTeleportState( LLAgent::TELEPORT_NONE );
+			gAgent.setTeleportMessage(std::string());
+		}
+
+		const std::string& message = gAgent.getTeleportMessage();
+		switch( gAgent.getTeleportState() )
+		{
+		case LLAgent::TELEPORT_START:
+			// Transition to REQUESTED.  Viewer has sent some kind
+			// of TeleportRequest to the source simulator
+			gTeleportDisplayTimer.reset();
+			gViewerWindow->setShowProgress(TRUE);
+			gViewerWindow->setProgressPercent(0);
+			gAgent.setTeleportState( LLAgent::TELEPORT_REQUESTED );
+			gAgent.setTeleportMessage(
+				LLAgent::sTeleportProgressMessages["requesting"]);
+			break;
+
+		case LLAgent::TELEPORT_REQUESTED:
+			// Waiting for source simulator to respond
+			gViewerWindow->setProgressPercent( llmin(teleport_percent, 37.5f) );
+			gViewerWindow->setProgressString(message);
+			break;
+
+		case LLAgent::TELEPORT_MOVING:
+			// Viewer has received destination location from source simulator
+			gViewerWindow->setProgressPercent( llmin(teleport_percent, 75.f) );
+			gViewerWindow->setProgressString(message);
+			break;
+
+		case LLAgent::TELEPORT_START_ARRIVAL:
+			// Transition to ARRIVING.  Viewer has received avatar update, etc., from destination simulator
+			gTeleportArrivalTimer.reset();
+				gViewerWindow->setProgressCancelButtonVisible(FALSE, LLTrans::getString("Cancel"));
+			gViewerWindow->setProgressPercent(75.f);
+			gAgent.setTeleportState( LLAgent::TELEPORT_ARRIVING );
+			gAgent.setTeleportMessage(
+				LLAgent::sTeleportProgressMessages["arriving"]);
+			gTextureList.mForceResetTextureStats = TRUE;
+			gAgentCamera.resetView(TRUE, TRUE);
+			break;
+
+		case LLAgent::TELEPORT_ARRIVING:
+			// Make the user wait while content "pre-caches"
+			{
+				F32 arrival_fraction = (gTeleportArrivalTimer.getElapsedTimeF32() / TELEPORT_ARRIVAL_DELAY);
+				if( arrival_fraction > 1.f )
+				{
+					arrival_fraction = 1.f;
+					//LLFirstUse::useTeleport();
+					gAgent.setTeleportState( LLAgent::TELEPORT_NONE );
+				}
+				gViewerWindow->setProgressCancelButtonVisible(FALSE, LLTrans::getString("Cancel"));
+				gViewerWindow->setProgressPercent(  arrival_fraction * 25.f + 75.f);
+				gViewerWindow->setProgressString(message);
+			}
+			break;
+
+		case LLAgent::TELEPORT_LOCAL:
+			// Short delay when teleporting in the same sim (progress screen active but not shown - did not
+			// fall-through from TELEPORT_START)
+			{
+				if( gTeleportDisplayTimer.getElapsedTimeF32() > TELEPORT_LOCAL_DELAY )
+				{
+					//LLFirstUse::useTeleport();
+					gAgent.setTeleportState( LLAgent::TELEPORT_NONE );
+				}
+			}
+			break;
+
+		case LLAgent::TELEPORT_NONE:
+			// No teleport in progress
+			gViewerWindow->setShowProgress(FALSE);
+			gTeleportDisplay = FALSE;
+			break;
+		}
+	}
+    else if(LLAppViewer::instance()->logoutRequestSent())
+	{
+		LLAppViewer::instance()->pingMainloopTimeout("Display:Logout");
+		F32 percent_done = gLogoutTimer.getElapsedTimeF32() * 100.f / gLogoutMaxTime;
+		if (percent_done > 100.f)
+		{
+			percent_done = 100.f;
+		}
+
+		if( LLApp::isExiting() )
+		{
+			percent_done = 100.f;
+		}
+		
+		gViewerWindow->setProgressPercent( percent_done );
+	}
+	else
+	if (gRestoreGL)
+	{
+		LLAppViewer::instance()->pingMainloopTimeout("Display:RestoreGL");
+		F32 percent_done = gRestoreGLTimer.getElapsedTimeF32() * 100.f / RESTORE_GL_TIME;
+		if( percent_done > 100.f )
+		{
+			gViewerWindow->setShowProgress(FALSE);
+			gRestoreGL = FALSE;
+		}
+		else
+		{
+
+			if( LLApp::isExiting() )
+			{
+				percent_done = 100.f;
+			}
+			
+			gViewerWindow->setProgressPercent( percent_done );
+		}
+	}
+
+	//////////////////////////
+	//
+	// Prepare for the next frame
+	//
+
+	/////////////////////////////
+	//
+	// Update the camera
+	//
+	//
+
+	LLAppViewer::instance()->pingMainloopTimeout("Display:Camera");
+	LLViewerCamera::getInstance()->setZoomParameters(zoom_factor, subfield);
+	LLViewerCamera::getInstance()->setNear(MIN_NEAR_PLANE);
+
+	//////////////////////////
+	//
+	// clear the next buffer
+	// (must follow dynamic texture writing since that uses the frame buffer)
+	//
+
+	if (gDisconnected)
+	{
+		LLAppViewer::instance()->pingMainloopTimeout("Display:Disconnected");
+		render_ui();
+	}
+	
+	//////////////////////////
+	//
+	// Set rendering options
+	//
+	//
+	LLAppViewer::instance()->pingMainloopTimeout("Display:RenderSetup");
+	stop_glerror();
+
+	///////////////////////////////////////
+	//
+	// Slam lighting parameters back to our defaults.
+	// Note that these are not the same as GL defaults...
+
+	stop_glerror();
+	gGL.setAmbientLightColor(LLColor4::white);
+	stop_glerror();
+			
+	/////////////////////////////////////
+	//
+	// Render
+	//
+	// Actually push all of our triangles to the screen.
+	//
+
+	// do render-to-texture stuff here
+	if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_DYNAMIC_TEXTURES))
+	{
+		LLAppViewer::instance()->pingMainloopTimeout("Display:DynamicTextures");
+		LLFastTimer t(FTM_UPDATE_TEXTURES);
+		if (LLViewerDynamicTexture::updateAllInstances())
+		{
+			gGL.setColorMask(true, true);
+			glClear(GL_DEPTH_BUFFER_BIT);
+		}
+	}
+
+	gViewerWindow->setup3DViewport();
+
+	gPipeline.resetFrameStats();	// Reset per-frame statistics.
+	
+	if (!gDisconnected)
+	{
+		LLMemType mt_du(LLMemType::MTYPE_DISPLAY_UPDATE);
+		LLAppViewer::instance()->pingMainloopTimeout("Display:Update");
+		if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD))
+		{ //don't draw hud objects in this frame
+			gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD);
+		}
+
+		if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD_PARTICLES))
+		{ //don't draw hud particles in this frame
+			gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD_PARTICLES);
+		}
+
+		//upkeep gl name pools
+		LLGLNamePool::upkeepPools();
+		
+		stop_glerror();
+		display_update_camera();
+		stop_glerror();
+				
+		// *TODO: merge these two methods
+		{
+			LLMemType mt_uh(LLMemType::MTYPE_DISPLAY_UPDATE_HUD);
+			LLHUDManager::getInstance()->updateEffects();
+			LLHUDObject::updateAll();
+			stop_glerror();
+		}
+
+		{
+			LLMemType mt_ug(LLMemType::MTYPE_DISPLAY_UPDATE_GEOM);
+			const F32 max_geom_update_time = 0.005f*10.f*gFrameIntervalSeconds; // 50 ms/second update time
+			gPipeline.createObjects(max_geom_update_time);
+			gPipeline.processPartitionQ();
+			gPipeline.updateGeom(max_geom_update_time);
+			stop_glerror();
+		}
+
+		gPipeline.updateGL();
+		stop_glerror();
+
+		S32 water_clip = 0;
+		if ((LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_ENVIRONMENT) > 1) &&
+			 (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_WATER) || 
+			  gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_VOIDWATER)))
+		{
+			if (LLViewerCamera::getInstance()->cameraUnderWater())
+			{
+				water_clip = -1;
+			}
+			else
+			{
+				water_clip = 1;
+			}
+		}
+		
+		LLAppViewer::instance()->pingMainloopTimeout("Display:Cull");
+		
+		//Increment drawable frame counter
+		LLDrawable::incrementVisible();
+
+		LLSpatialGroup::sNoDelete = TRUE;
+		LLTexUnit::sWhiteTexture = LLViewerFetchedTexture::sWhiteImagep->getTexName();
+
+		/*if (LLPipeline::sUseOcclusion && LLPipeline::sRenderDeferred)
+		{ //force occlusion on for all render types if doing deferred render (tighter shadow frustum)
+			LLPipeline::sUseOcclusion = 3;
+		}*/
+
+		S32 occlusion = LLPipeline::sUseOcclusion;
+		if (gDepthDirty)
+		{ //depth buffer is invalid, don't overwrite occlusion state
+			LLPipeline::sUseOcclusion = llmin(occlusion, 1);
+		}
+		gDepthDirty = FALSE;
+
+		LLGLState::checkStates();
+		LLGLState::checkTextureChannels();
+		LLGLState::checkClientArrays();
+
+		static LLCullResult result;
+		LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
+		gPipeline.updateCull(*LLViewerCamera::getInstance(), result, water_clip);
+		stop_glerror();
+
+		LLGLState::checkStates();
+		LLGLState::checkTextureChannels();
+		LLGLState::checkClientArrays();
+
+		BOOL to_texture = gPipeline.canUseVertexShaders() &&
+						LLPipeline::sRenderGlow;
+
+		LLAppViewer::instance()->pingMainloopTimeout("Display:Swap");
+		
+		{ 
+			LLMemType mt_ds(LLMemType::MTYPE_DISPLAY_SWAP);
+
+			if (gResizeScreenTexture)
+			{
+				gResizeScreenTexture = FALSE;
+				gPipeline.resizeScreenTexture();
+			}
+
+			gGL.setColorMask(true, true);
+			glClearColor(0,0,0,0);
+
+			LLGLState::checkStates();
+			LLGLState::checkTextureChannels();
+			LLGLState::checkClientArrays();
+
+			if (!for_snapshot)
+			{
+				if (gFrameCount > 1)
+				{ //for some reason, ATI 4800 series will error out if you 
+				  //try to generate a shadow before the first frame is through
+					gPipeline.generateSunShadow(*LLViewerCamera::getInstance());
+				}
+
+				LLVertexBuffer::unbind();
+
+				LLGLState::checkStates();
+				LLGLState::checkTextureChannels();
+				LLGLState::checkClientArrays();
+
+				glh::matrix4f proj = glh_get_current_projection();
+				glh::matrix4f mod = glh_get_current_modelview();
+				glViewport(0,0,512,512);
+				LLVOAvatar::updateFreezeCounter() ;
+
+				if(!LLPipeline::sMemAllocationThrottled)
+				{		
+					LLVOAvatar::updateImpostors();
+				}
+
+				glh_set_current_projection(proj);
+				glh_set_current_modelview(mod);
+				gGL.matrixMode(LLRender::MM_PROJECTION);
+				gGL.loadMatrix(proj.m);
+				gGL.matrixMode(LLRender::MM_MODELVIEW);
+				gGL.loadMatrix(mod.m);
+				gViewerWindow->setup3DViewport();
+
+				LLGLState::checkStates();
+				LLGLState::checkTextureChannels();
+				LLGLState::checkClientArrays();
+
+			}
+			glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+		}
+
+		LLGLState::checkStates();
+		LLGLState::checkClientArrays();
+
+		//if (!for_snapshot)
+		{
+			LLMemType mt_gw(LLMemType::MTYPE_DISPLAY_GEN_REFLECTION);
+			LLAppViewer::instance()->pingMainloopTimeout("Display:Imagery");
+			gPipeline.generateWaterReflection(*LLViewerCamera::getInstance());
+			gPipeline.generateHighlight(*LLViewerCamera::getInstance());
+			gPipeline.renderPhysicsDisplay();
+		}
+
+		LLGLState::checkStates();
+		LLGLState::checkClientArrays();
+
+		//////////////////////////////////////
+		//
+		// Update images, using the image stats generated during object update/culling
+		//
+		// Can put objects onto the retextured list.
+		//
+		// Doing this here gives hardware occlusion queries extra time to complete
+		LLAppViewer::instance()->pingMainloopTimeout("Display:UpdateImages");
+		
+		{
+			LLMemType mt_iu(LLMemType::MTYPE_DISPLAY_IMAGE_UPDATE);
+			LLFastTimer t(FTM_IMAGE_UPDATE);
+			
+			{
+				LLFastTimer t(FTM_IMAGE_UPDATE_CLASS);
+				LLViewerTexture::updateClass(LLViewerCamera::getInstance()->getVelocityStat()->getMean(),
+											LLViewerCamera::getInstance()->getAngularVelocityStat()->getMean());
+			}
+
+			
+			{
+				LLFastTimer t(FTM_IMAGE_UPDATE_BUMP);
+				gBumpImageList.updateImages();  // must be called before gTextureList version so that it's textures are thrown out first.
+			}
+
+			{
+				LLFastTimer t(FTM_IMAGE_UPDATE_LIST);
+				F32 max_image_decode_time = 0.050f*gFrameIntervalSeconds; // 50 ms/second decode time
+				max_image_decode_time = llclamp(max_image_decode_time, 0.002f, 0.005f ); // min 2ms/frame, max 5ms/frame)
+				gTextureList.updateImages(max_image_decode_time);
+			}
+
+			{
+				LLFastTimer t(FTM_IMAGE_UPDATE_DELETE);
+				//remove dead textures from GL
+				LLImageGL::deleteDeadTextures();
+				stop_glerror();
+			}
+		}
+
+		LLGLState::checkStates();
+		LLGLState::checkClientArrays();
+
+		///////////////////////////////////
+		//
+		// StateSort
+		//
+		// Responsible for taking visible objects, and adding them to the appropriate draw orders.
+		// In the case of alpha objects, z-sorts them first.
+		// Also creates special lists for outlines and selected face rendering.
+		//
+		LLAppViewer::instance()->pingMainloopTimeout("Display:StateSort");
+		{
+			LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
+			LLMemType mt_ss(LLMemType::MTYPE_DISPLAY_STATE_SORT);
+			gPipeline.stateSort(*LLViewerCamera::getInstance(), result);
+			stop_glerror();
+				
+			if (rebuild)
+			{
+				//////////////////////////////////////
+				//
+				// rebuildPools
+				//
+				//
+				gPipeline.rebuildPools();
+				stop_glerror();
+			}
+		}
+
+		LLGLState::checkStates();
+		LLGLState::checkClientArrays();
+
+		LLPipeline::sUseOcclusion = occlusion;
+
+		{
+			LLMemType mt_ds(LLMemType::MTYPE_DISPLAY_SKY);
+			LLAppViewer::instance()->pingMainloopTimeout("Display:Sky");
+			LLFastTimer t(FTM_UPDATE_SKY);	
+			gSky.updateSky();
+		}
+
+		if(gUseWireframe)
+		{
+			glClearColor(0.5f, 0.5f, 0.5f, 0.f);
+			glClear(GL_COLOR_BUFFER_BIT);
+			glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+		}
+
+		LLAppViewer::instance()->pingMainloopTimeout("Display:RenderStart");
+		
+		//// render frontmost floater opaque for occlusion culling purposes
+		//LLFloater* frontmost_floaterp = gFloaterView->getFrontmost();
+		//// assumes frontmost floater with focus is opaque
+		//if (frontmost_floaterp && gFocusMgr.childHasKeyboardFocus(frontmost_floaterp))
+		//{
+		//	gGL.matrixMode(LLRender::MM_MODELVIEW);
+		//	gGL.pushMatrix();
+		//	{
+		//		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+
+		//		glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
+		//		gGL.loadIdentity();
+
+		//		LLRect floater_rect = frontmost_floaterp->calcScreenRect();
+		//		// deflate by one pixel so rounding errors don't occlude outside of floater extents
+		//		floater_rect.stretch(-1);
+		//		LLRectf floater_3d_rect((F32)floater_rect.mLeft / (F32)gViewerWindow->getWindowWidthScaled(), 
+		//								(F32)floater_rect.mTop / (F32)gViewerWindow->getWindowHeightScaled(),
+		//								(F32)floater_rect.mRight / (F32)gViewerWindow->getWindowWidthScaled(),
+		//								(F32)floater_rect.mBottom / (F32)gViewerWindow->getWindowHeightScaled());
+		//		floater_3d_rect.translate(-0.5f, -0.5f);
+		//		gGL.translatef(0.f, 0.f, -LLViewerCamera::getInstance()->getNear());
+		//		gGL.scalef(LLViewerCamera::getInstance()->getNear() * LLViewerCamera::getInstance()->getAspect() / sinf(LLViewerCamera::getInstance()->getView()), LLViewerCamera::getInstance()->getNear() / sinf(LLViewerCamera::getInstance()->getView()), 1.f);
+		//		gGL.color4fv(LLColor4::white.mV);
+		//		gGL.begin(LLVertexBuffer::QUADS);
+		//		{
+		//			gGL.vertex3f(floater_3d_rect.mLeft, floater_3d_rect.mBottom, 0.f);
+		//			gGL.vertex3f(floater_3d_rect.mLeft, floater_3d_rect.mTop, 0.f);
+		//			gGL.vertex3f(floater_3d_rect.mRight, floater_3d_rect.mTop, 0.f);
+		//			gGL.vertex3f(floater_3d_rect.mRight, floater_3d_rect.mBottom, 0.f);
+		//		}
+		//		gGL.end();
+		//		glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+		//	}
+		//	gGL.popMatrix();
+		//}
+
+		LLPipeline::sUnderWaterRender = LLViewerCamera::getInstance()->cameraUnderWater() ? TRUE : FALSE;
+		
+		LLGLState::checkStates();
+		LLGLState::checkClientArrays();
+
+		stop_glerror();
+
+		if (to_texture)
+		{
+			gGL.setColorMask(true, true);
+					
+			if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender)
+			{
+				gPipeline.mDeferredScreen.bindTarget();
+				glClearColor(1,0,1,1);
+				gPipeline.mDeferredScreen.clear();
+			}
+			else
+			{
+				gPipeline.mScreen.bindTarget();
+				if (LLPipeline::sUnderWaterRender && !gPipeline.canUseWindLightShaders())
+				{
+					const LLColor4 &col = LLDrawPoolWater::sWaterFogColor;
+					glClearColor(col.mV[0], col.mV[1], col.mV[2], 0.f);
+				}
+				gPipeline.mScreen.clear();
+			}
+			
+			gGL.setColorMask(true, false);
+		}
+		
+		LLAppViewer::instance()->pingMainloopTimeout("Display:RenderGeom");
+		bool exclusiveDraw = false;
+		BOOL allowRenderables = false;
+		BOOL allowPathToBeDrawn = false;
+		if (!(LLAppViewer::instance()->logoutRequestSent() && LLAppViewer::instance()->hasSavedFinalSnapshot())
+				&& !gRestoreGL)
+		{
+			LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
+			LLMemType mt_rg(LLMemType::MTYPE_DISPLAY_RENDER_GEOM);
+			gGL.setColorMask(true, false);
+			if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender)
+			{
+				gPipeline.renderGeomDeferred(*LLViewerCamera::getInstance());
+			}
+			else
+			{
+				//Render any navmesh geometry	
+				if ( LLPathingLib::getInstance() ) 
+				{	
+					//Determine if we can should overlay the navmesh ontop of the scenes typical renderables
+					LLFloaterPathfindingConsole* pFloater = LLFloaterReg::getTypedInstance<LLFloaterPathfindingConsole>("pathfinding_console");
+					if ( pFloater && pFloater->allowAllRenderables() )
+					{
+						allowRenderables = true;
+					}
+					//Determine if we should also draw a user supplied path on top of the scene
+					if ( pFloater && pFloater->getShowPathToggle() )
+					{
+						allowPathToBeDrawn = true;
+					}
+					//NavMesh
+					if ( LLPathingLib::getInstance()->getRenderNavMeshState() )
+					{
+						glClearColor(0.0f, 0.0f, 0.0f, 0.5f);          												
+						glEnable(GL_DEPTH_TEST);                        
+						gGL.setAmbientLightColor( LLColor4::white );
+						LLPathingLib::getInstance()->renderNavMesh( allowRenderables );
+						exclusiveDraw = true;
+					}
+					//physics/exclusion shapes
+					if ( LLPathingLib::getInstance()->getRenderShapeState() )
+					{						
+						LLPathingLib::getInstance()->renderNavMeshShapesVBO();
+						exclusiveDraw = true;
+					}	
+					//User designated path
+					if ( allowPathToBeDrawn )
+					{
+						LLPathingLib::getInstance()->renderPath();
+					}
+				}			
+			}
+			
+			if ( !exclusiveDraw || allowRenderables )					
+			{
+				gPipeline.renderGeom(*LLViewerCamera::getInstance(), TRUE);
+			}
+
+			gGL.setColorMask(true, true);
+
+			//store this frame's modelview matrix for use
+			//when rendering next frame's occlusion queries
+			for (U32 i = 0; i < 16; i++)
+			{
+				gGLLastModelView[i] = gGLModelView[i];
+				gGLLastProjection[i] = gGLProjection[i];
+			}
+			stop_glerror();
+		}
+
+		for (U32 i = 0; i < gGLManager.mNumTextureImageUnits; i++)
+		{ //dummy cleanup of any currently bound textures
+			if (gGL.getTexUnit(i)->getCurrType() != LLTexUnit::TT_NONE)
+			{
+				gGL.getTexUnit(i)->unbind(gGL.getTexUnit(i)->getCurrType());
+				gGL.getTexUnit(i)->disable();
+			}
+		}
+		LLAppViewer::instance()->pingMainloopTimeout("Display:RenderFlush");		
+		
+		if (to_texture)
+		{
+			LLMemType mt_rf(LLMemType::MTYPE_DISPLAY_RENDER_FLUSH);
+			if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender)
+			{
+				gPipeline.mDeferredScreen.flush();
+				if(LLRenderTarget::sUseFBO)
+				{
+					LLRenderTarget::copyContentsToFramebuffer(gPipeline.mDeferredScreen, 0, 0, gPipeline.mDeferredScreen.getWidth(), 
+															  gPipeline.mDeferredScreen.getHeight(), 0, 0, 
+															  gPipeline.mDeferredScreen.getWidth(), 
+															  gPipeline.mDeferredScreen.getHeight(), 
+															  GL_DEPTH_BUFFER_BIT, GL_NEAREST);
+				}
+			}
+			else
+			{
+				gPipeline.mScreen.flush();
+				if(LLRenderTarget::sUseFBO)
+				{				
+					LLRenderTarget::copyContentsToFramebuffer(gPipeline.mScreen, 0, 0, gPipeline.mScreen.getWidth(), 
+															  gPipeline.mScreen.getHeight(), 0, 0, 
+															  gPipeline.mScreen.getWidth(), 
+															  gPipeline.mScreen.getHeight(), 
+															  GL_DEPTH_BUFFER_BIT, GL_NEAREST);
+				}
+			}
+		}
+
+		if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender)
+		{
+			gPipeline.renderDeferredLighting();
+		}
+
+		LLPipeline::sUnderWaterRender = FALSE;
+
+		LLAppViewer::instance()->pingMainloopTimeout("Display:RenderUI");
+		if (!for_snapshot)
+		{
+			LLFastTimer t(FTM_RENDER_UI);
+			render_ui();
+		}
+
+		
+		LLSpatialGroup::sNoDelete = FALSE;
+		gPipeline.clearReferences();
+
+		gPipeline.rebuildGroups();
+	}
+
+	LLAppViewer::instance()->pingMainloopTimeout("Display:FrameStats");
+	
+	stop_glerror();
+
+	if (LLPipeline::sRenderFrameTest)
+	{
+		send_agent_resume();
+		LLPipeline::sRenderFrameTest = FALSE;
+	}
+
+	display_stats();
+				
+	LLAppViewer::instance()->pingMainloopTimeout("Display:Done");
+}
+
+void render_hud_attachments()
+{
+	LLMemType mt_ra(LLMemType::MTYPE_DISPLAY_RENDER_ATTACHMENTS);
+	gGL.matrixMode(LLRender::MM_PROJECTION);
+	gGL.pushMatrix();
+	gGL.matrixMode(LLRender::MM_MODELVIEW);
+	gGL.pushMatrix();
+		
+	glh::matrix4f current_proj = glh_get_current_projection();
+	glh::matrix4f current_mod = glh_get_current_modelview();
+
+	// clamp target zoom level to reasonable values
+	gAgentCamera.mHUDTargetZoom = llclamp(gAgentCamera.mHUDTargetZoom, 0.1f, 1.f);
+	// smoothly interpolate current zoom level
+	gAgentCamera.mHUDCurZoom = lerp(gAgentCamera.mHUDCurZoom, gAgentCamera.mHUDTargetZoom, LLCriticalDamp::getInterpolant(0.03f));
+
+	if (LLPipeline::sShowHUDAttachments && !gDisconnected && setup_hud_matrices())
+	{
+		LLCamera hud_cam = *LLViewerCamera::getInstance();
+		LLVector3 origin = hud_cam.getOrigin();
+		hud_cam.setOrigin(-1.f,0,0);
+		hud_cam.setAxes(LLVector3(1,0,0), LLVector3(0,1,0), LLVector3(0,0,1));
+		LLViewerCamera::updateFrustumPlanes(hud_cam, TRUE);
+
+		bool render_particles = gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES) && gSavedSettings.getBOOL("RenderHUDParticles");
+		
+		//only render hud objects
+		gPipeline.pushRenderTypeMask();
+		
+		// turn off everything
+		gPipeline.andRenderTypeMask(LLPipeline::END_RENDER_TYPES);
+		// turn on HUD
+		gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD);
+		// turn on HUD particles
+		gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD_PARTICLES);
+
+		// if particles are off, turn off hud-particles as well
+		if (!render_particles)
+		{
+			// turn back off HUD particles
+			gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD_PARTICLES);
+		}
+
+		bool has_ui = gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI);
+		if (has_ui)
+		{
+			gPipeline.toggleRenderDebugFeature((void*) LLPipeline::RENDER_DEBUG_FEATURE_UI);
+		}
+
+		S32 use_occlusion = LLPipeline::sUseOcclusion;
+		LLPipeline::sUseOcclusion = 0;
+				
+		//cull, sort, and render hud objects
+		static LLCullResult result;
+		LLSpatialGroup::sNoDelete = TRUE;
+
+		LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
+		gPipeline.updateCull(hud_cam, result);
+
+		gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_BUMP);
+		gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_SIMPLE);
+		gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_VOLUME);
+		gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_ALPHA);
+		gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_FULLBRIGHT);
+		gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_ALPHA);
+		gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_ALPHA_MASK);
+		gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_BUMP);
+		gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT);
+		gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK);
+		gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_SHINY);
+		gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_SHINY);
+		gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_INVISIBLE);
+		gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_INVISI_SHINY);
+		
+		gPipeline.stateSort(hud_cam, result);
+
+		gPipeline.renderGeom(hud_cam);
+
+		LLSpatialGroup::sNoDelete = FALSE;
+		//gPipeline.clearReferences();
+
+		render_hud_elements();
+
+		//restore type mask
+		gPipeline.popRenderTypeMask();
+
+		if (has_ui)
+		{
+			gPipeline.toggleRenderDebugFeature((void*) LLPipeline::RENDER_DEBUG_FEATURE_UI);
+		}
+		LLPipeline::sUseOcclusion = use_occlusion;
+	}
+	gGL.matrixMode(LLRender::MM_PROJECTION);
+	gGL.popMatrix();
+	gGL.matrixMode(LLRender::MM_MODELVIEW);
+	gGL.popMatrix();
+	
+	glh_set_current_projection(current_proj);
+	glh_set_current_modelview(current_mod);
+}
+
+LLRect get_whole_screen_region()
+{
+	LLRect whole_screen = gViewerWindow->getWorldViewRectScaled();
+	
+	// apply camera zoom transform (for high res screenshots)
+	F32 zoom_factor = LLViewerCamera::getInstance()->getZoomFactor();
+	S16 sub_region = LLViewerCamera::getInstance()->getZoomSubRegion();
+	if (zoom_factor > 1.f)
+	{
+		S32 num_horizontal_tiles = llceil(zoom_factor);
+		S32 tile_width = llround((F32)gViewerWindow->getWorldViewWidthScaled() / zoom_factor);
+		S32 tile_height = llround((F32)gViewerWindow->getWorldViewHeightScaled() / zoom_factor);
+		int tile_y = sub_region / num_horizontal_tiles;
+		int tile_x = sub_region - (tile_y * num_horizontal_tiles);
+			
+		whole_screen.setLeftTopAndSize(tile_x * tile_width, gViewerWindow->getWorldViewHeightScaled() - (tile_y * tile_height), tile_width, tile_height);
+	}
+	return whole_screen;
+}
+
+bool get_hud_matrices(const LLRect& screen_region, glh::matrix4f &proj, glh::matrix4f &model)
+{
+	if (isAgentAvatarValid() && gAgentAvatarp->hasHUDAttachment())
+	{
+		F32 zoom_level = gAgentCamera.mHUDCurZoom;
+		LLBBox hud_bbox = gAgentAvatarp->getHUDBBox();
+		
+		F32 hud_depth = llmax(1.f, hud_bbox.getExtentLocal().mV[VX] * 1.1f);
+		proj = gl_ortho(-0.5f * LLViewerCamera::getInstance()->getAspect(), 0.5f * LLViewerCamera::getInstance()->getAspect(), -0.5f, 0.5f, 0.f, hud_depth);
+		proj.element(2,2) = -0.01f;
+		
+		F32 aspect_ratio = LLViewerCamera::getInstance()->getAspect();
+		
+		glh::matrix4f mat;
+		F32 scale_x = (F32)gViewerWindow->getWorldViewWidthScaled() / (F32)screen_region.getWidth();
+		F32 scale_y = (F32)gViewerWindow->getWorldViewHeightScaled() / (F32)screen_region.getHeight();
+		mat.set_scale(glh::vec3f(scale_x, scale_y, 1.f));
+		mat.set_translate(
+			glh::vec3f(clamp_rescale((F32)(screen_region.getCenterX() - screen_region.mLeft), 0.f, (F32)gViewerWindow->getWorldViewWidthScaled(), 0.5f * scale_x * aspect_ratio, -0.5f * scale_x * aspect_ratio),
+					   clamp_rescale((F32)(screen_region.getCenterY() - screen_region.mBottom), 0.f, (F32)gViewerWindow->getWorldViewHeightScaled(), 0.5f * scale_y, -0.5f * scale_y),
+					   0.f));
+		proj *= mat;
+		
+		glh::matrix4f tmp_model((GLfloat*) OGL_TO_CFR_ROTATION);
+		
+		mat.set_scale(glh::vec3f(zoom_level, zoom_level, zoom_level));
+		mat.set_translate(glh::vec3f(-hud_bbox.getCenterLocal().mV[VX] + (hud_depth * 0.5f), 0.f, 0.f));
+		
+		tmp_model *= mat;
+		model = tmp_model;		
+		return TRUE;
+	}
+	else
+	{
+		return FALSE;
+	}
+}
+
+bool get_hud_matrices(glh::matrix4f &proj, glh::matrix4f &model)
+{
+	LLRect whole_screen = get_whole_screen_region();
+	return get_hud_matrices(whole_screen, proj, model);
+}
+
+BOOL setup_hud_matrices()
+{
+	LLRect whole_screen = get_whole_screen_region();
+	return setup_hud_matrices(whole_screen);
+}
+
+BOOL setup_hud_matrices(const LLRect& screen_region)
+{
+	glh::matrix4f proj, model;
+	bool result = get_hud_matrices(screen_region, proj, model);
+	if (!result) return result;
+	
+	// set up transform to keep HUD objects in front of camera
+	gGL.matrixMode(LLRender::MM_PROJECTION);
+	gGL.loadMatrix(proj.m);
+	glh_set_current_projection(proj);
+	
+	gGL.matrixMode(LLRender::MM_MODELVIEW);
+	gGL.loadMatrix(model.m);
+	glh_set_current_modelview(model);
+	return TRUE;
+}
+
+static LLFastTimer::DeclareTimer FTM_SWAP("Swap");
+
+void render_ui(F32 zoom_factor, int subfield)
+{
+	LLMemType mt_ru(LLMemType::MTYPE_DISPLAY_RENDER_UI);
+	LLGLState::checkStates();
+	
+	glh::matrix4f saved_view = glh_get_current_modelview();
+
+	if (!gSnapshot)
+	{
+		gGL.pushMatrix();
+		gGL.loadMatrix(gGLLastModelView);
+		glh_set_current_modelview(glh_copy_matrix(gGLLastModelView));
+	}
+	
+	{
+		BOOL to_texture = gPipeline.canUseVertexShaders() &&
+							LLPipeline::sRenderGlow;
+
+		if (to_texture)
+		{
+			gPipeline.renderBloom(gSnapshot, zoom_factor, subfield);
+		}
+		
+		render_hud_elements();
+		render_hud_attachments();
+	}
+
+	LLGLSDefault gls_default;
+	LLGLSUIDefault gls_ui;
+	{
+		gPipeline.disableLights();
+	}
+
+	{
+		gGL.color4f(1,1,1,1);
+		if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
+		{
+			LLFastTimer t(FTM_RENDER_UI);
+
+			if (!gDisconnected)
+			{
+				render_ui_3d();
+				LLGLState::checkStates();
+			}
+			else
+			{
+				render_disconnected_background();
+			}
+
+			render_ui_2d();
+			LLGLState::checkStates();
+		}
+		gGL.flush();
+
+		{
+			gViewerWindow->setup2DRender();
+			gViewerWindow->updateDebugText();
+			gViewerWindow->drawDebugText();
+		}
+
+		LLVertexBuffer::unbind();
+	}
+
+	if (!gSnapshot)
+	{
+		glh_set_current_modelview(saved_view);
+		gGL.popMatrix();
+	}
+
+	if (gDisplaySwapBuffers)
+	{
+		LLFastTimer t(FTM_SWAP);
+		gViewerWindow->getWindow()->swapBuffers();
+	}
+	gDisplaySwapBuffers = TRUE;
+}
+
+void renderCoordinateAxes()
+{
+	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+	gGL.begin(LLRender::LINES);
+		gGL.color3f(1.0f, 0.0f, 0.0f);   // i direction = X-Axis = red
+		gGL.vertex3f(0.0f, 0.0f, 0.0f);
+		gGL.vertex3f(2.0f, 0.0f, 0.0f);
+		gGL.vertex3f(3.0f, 0.0f, 0.0f);
+		gGL.vertex3f(5.0f, 0.0f, 0.0f);
+		gGL.vertex3f(6.0f, 0.0f, 0.0f);
+		gGL.vertex3f(8.0f, 0.0f, 0.0f);
+		// Make an X
+		gGL.vertex3f(11.0f, 1.0f, 1.0f);
+		gGL.vertex3f(11.0f, -1.0f, -1.0f);
+		gGL.vertex3f(11.0f, 1.0f, -1.0f);
+		gGL.vertex3f(11.0f, -1.0f, 1.0f);
+
+		gGL.color3f(0.0f, 1.0f, 0.0f);   // j direction = Y-Axis = green
+		gGL.vertex3f(0.0f, 0.0f, 0.0f);
+		gGL.vertex3f(0.0f, 2.0f, 0.0f);
+		gGL.vertex3f(0.0f, 3.0f, 0.0f);
+		gGL.vertex3f(0.0f, 5.0f, 0.0f);
+		gGL.vertex3f(0.0f, 6.0f, 0.0f);
+		gGL.vertex3f(0.0f, 8.0f, 0.0f);
+		// Make a Y
+		gGL.vertex3f(1.0f, 11.0f, 1.0f);
+		gGL.vertex3f(0.0f, 11.0f, 0.0f);
+		gGL.vertex3f(-1.0f, 11.0f, 1.0f);
+		gGL.vertex3f(0.0f, 11.0f, 0.0f);
+		gGL.vertex3f(0.0f, 11.0f, 0.0f);
+		gGL.vertex3f(0.0f, 11.0f, -1.0f);
+
+		gGL.color3f(0.0f, 0.0f, 1.0f);   // Z-Axis = blue
+		gGL.vertex3f(0.0f, 0.0f, 0.0f);
+		gGL.vertex3f(0.0f, 0.0f, 2.0f);
+		gGL.vertex3f(0.0f, 0.0f, 3.0f);
+		gGL.vertex3f(0.0f, 0.0f, 5.0f);
+		gGL.vertex3f(0.0f, 0.0f, 6.0f);
+		gGL.vertex3f(0.0f, 0.0f, 8.0f);
+		// Make a Z
+		gGL.vertex3f(-1.0f, 1.0f, 11.0f);
+		gGL.vertex3f(1.0f, 1.0f, 11.0f);
+		gGL.vertex3f(1.0f, 1.0f, 11.0f);
+		gGL.vertex3f(-1.0f, -1.0f, 11.0f);
+		gGL.vertex3f(-1.0f, -1.0f, 11.0f);
+		gGL.vertex3f(1.0f, -1.0f, 11.0f);
+	gGL.end();
+}
+
+
+void draw_axes() 
+{
+	LLGLSUIDefault gls_ui;
+	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+	// A vertical white line at origin
+	LLVector3 v = gAgent.getPositionAgent();
+	gGL.begin(LLRender::LINES);
+		gGL.color3f(1.0f, 1.0f, 1.0f); 
+		gGL.vertex3f(0.0f, 0.0f, 0.0f);
+		gGL.vertex3f(0.0f, 0.0f, 40.0f);
+	gGL.end();
+	// Some coordinate axes
+	gGL.pushMatrix();
+		gGL.translatef( v.mV[VX], v.mV[VY], v.mV[VZ] );
+		renderCoordinateAxes();
+	gGL.popMatrix();
+}
+
+void render_ui_3d()
+{
+	LLGLSPipeline gls_pipeline;
+
+	//////////////////////////////////////
+	//
+	// Render 3D UI elements
+	// NOTE: zbuffer is cleared before we get here by LLDrawPoolHUD,
+	//		 so 3d elements requiring Z buffer are moved to LLDrawPoolHUD
+	//
+
+	/////////////////////////////////////////////////////////////
+	//
+	// Render 2.5D elements (2D elements in the world)
+	// Stuff without z writes
+	//
+
+	// Debugging stuff goes before the UI.
+
+	stop_glerror();
+	
+	if (LLGLSLShader::sNoFixedFunction)
+	{
+		gUIProgram.bind();
+	}
+
+	// Coordinate axes
+	if (gSavedSettings.getBOOL("ShowAxes"))
+	{
+		draw_axes();
+	}
+
+	gViewerWindow->renderSelections(FALSE, FALSE, TRUE); // Non HUD call in render_hud_elements
+	stop_glerror();
+}
+
+void render_ui_2d()
+{
+	LLGLSUIDefault gls_ui;
+
+	/////////////////////////////////////////////////////////////
+	//
+	// Render 2D UI elements that overlay the world (no z compare)
+
+	//  Disable wireframe mode below here, as this is HUD/menus
+	glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+
+	//  Menu overlays, HUD, etc
+	gViewerWindow->setup2DRender();
+
+	F32 zoom_factor = LLViewerCamera::getInstance()->getZoomFactor();
+	S16 sub_region = LLViewerCamera::getInstance()->getZoomSubRegion();
+
+	if (zoom_factor > 1.f)
+	{
+		//decompose subregion number to x and y values
+		int pos_y = sub_region / llceil(zoom_factor);
+		int pos_x = sub_region - (pos_y*llceil(zoom_factor));
+		// offset for this tile
+		LLFontGL::sCurOrigin.mX -= llround((F32)gViewerWindow->getWindowWidthScaled() * (F32)pos_x / zoom_factor);
+		LLFontGL::sCurOrigin.mY -= llround((F32)gViewerWindow->getWindowHeightScaled() * (F32)pos_y / zoom_factor);
+	}
+
+	stop_glerror();
+	//gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
+
+	// render outline for HUD
+	if (isAgentAvatarValid() && gAgentCamera.mHUDCurZoom < 0.98f)
+	{
+		gGL.pushMatrix();
+		S32 half_width = (gViewerWindow->getWorldViewWidthScaled() / 2);
+		S32 half_height = (gViewerWindow->getWorldViewHeightScaled() / 2);
+		gGL.scalef(LLUI::sGLScaleFactor.mV[0], LLUI::sGLScaleFactor.mV[1], 1.f);
+		gGL.translatef((F32)half_width, (F32)half_height, 0.f);
+		F32 zoom = gAgentCamera.mHUDCurZoom;
+		gGL.scalef(zoom,zoom,1.f);
+		gGL.color4fv(LLColor4::white.mV);
+		gl_rect_2d(-half_width, half_height, half_width, -half_height, FALSE);
+		gGL.popMatrix();
+		stop_glerror();
+	}
+	
+
+	if (gSavedSettings.getBOOL("RenderUIBuffer"))
+	{
+		if (LLUI::sDirty)
+		{
+			LLUI::sDirty = FALSE;
+			LLRect t_rect;
+
+			gPipeline.mUIScreen.bindTarget();
+			gGL.setColorMask(true, true);
+			{
+				static const S32 pad = 8;
+
+				LLUI::sDirtyRect.mLeft -= pad;
+				LLUI::sDirtyRect.mRight += pad;
+				LLUI::sDirtyRect.mBottom -= pad;
+				LLUI::sDirtyRect.mTop += pad;
+
+				LLGLEnable scissor(GL_SCISSOR_TEST);
+				static LLRect last_rect = LLUI::sDirtyRect;
+
+				//union with last rect to avoid mouse poop
+				last_rect.unionWith(LLUI::sDirtyRect);
+								
+				t_rect = LLUI::sDirtyRect;
+				LLUI::sDirtyRect = last_rect;
+				last_rect = t_rect;
+			
+				last_rect.mLeft = LLRect::tCoordType(last_rect.mLeft / LLUI::sGLScaleFactor.mV[0]);
+				last_rect.mRight = LLRect::tCoordType(last_rect.mRight / LLUI::sGLScaleFactor.mV[0]);
+				last_rect.mTop = LLRect::tCoordType(last_rect.mTop / LLUI::sGLScaleFactor.mV[1]);
+				last_rect.mBottom = LLRect::tCoordType(last_rect.mBottom / LLUI::sGLScaleFactor.mV[1]);
+
+				LLRect clip_rect(last_rect);
+				
+				glClear(GL_COLOR_BUFFER_BIT);
+
+				gViewerWindow->draw();
+			}
+
+			gPipeline.mUIScreen.flush();
+			gGL.setColorMask(true, false);
+
+			LLUI::sDirtyRect = t_rect;
+		}
+
+		LLGLDisable cull(GL_CULL_FACE);
+		LLGLDisable blend(GL_BLEND);
+		S32 width = gViewerWindow->getWindowWidthScaled();
+		S32 height = gViewerWindow->getWindowHeightScaled();
+		gGL.getTexUnit(0)->bind(&gPipeline.mUIScreen);
+		gGL.begin(LLRender::TRIANGLE_STRIP);
+		gGL.color4f(1,1,1,1);
+		gGL.texCoord2f(0, 0);			gGL.vertex2i(0, 0);
+		gGL.texCoord2f(width, 0);		gGL.vertex2i(width, 0);
+		gGL.texCoord2f(0, height);		gGL.vertex2i(0, height);
+		gGL.texCoord2f(width, height);	gGL.vertex2i(width, height);
+		gGL.end();
+	}
+	else
+	{
+		gViewerWindow->draw();
+	}
+
+
+
+	// reset current origin for font rendering, in case of tiling render
+	LLFontGL::sCurOrigin.set(0, 0);
+}
+
+void render_disconnected_background()
+{
+	if (LLGLSLShader::sNoFixedFunction)
+	{
+		gUIProgram.bind();
+	}
+
+	gGL.color4f(1,1,1,1);
+	if (!gDisconnectedImagep && gDisconnected)
+	{
+		llinfos << "Loading last bitmap..." << llendl;
+
+		std::string temp_str;
+		temp_str = gDirUtilp->getLindenUserDir() + gDirUtilp->getDirDelimiter() + SCREEN_LAST_FILENAME;
+
+		LLPointer<LLImageBMP> image_bmp = new LLImageBMP;
+		if( !image_bmp->load(temp_str) )
+		{
+			//llinfos << "Bitmap load failed" << llendl;
+			return;
+		}
+		
+		LLPointer<LLImageRaw> raw = new LLImageRaw;
+		if (!image_bmp->decode(raw, 0.0f))
+		{
+			llinfos << "Bitmap decode failed" << llendl;
+			gDisconnectedImagep = NULL;
+			return;
+		}
+
+		U8 *rawp = raw->getData();
+		S32 npixels = (S32)image_bmp->getWidth()*(S32)image_bmp->getHeight();
+		for (S32 i = 0; i < npixels; i++)
+		{
+			S32 sum = 0;
+			sum = *rawp + *(rawp+1) + *(rawp+2);
+			sum /= 3;
+			*rawp = ((S32)sum*6 + *rawp)/7;
+			rawp++;
+			*rawp = ((S32)sum*6 + *rawp)/7;
+			rawp++;
+			*rawp = ((S32)sum*6 + *rawp)/7;
+			rawp++;
+		}
+
+		
+		raw->expandToPowerOfTwo();
+		gDisconnectedImagep = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE );
+		gStartTexture = gDisconnectedImagep;
+		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+	}
+
+	// Make sure the progress view always fills the entire window.
+	S32 width = gViewerWindow->getWindowWidthScaled();
+	S32 height = gViewerWindow->getWindowHeightScaled();
+
+	if (gDisconnectedImagep)
+	{
+		LLGLSUIDefault gls_ui;
+		gViewerWindow->setup2DRender();
+		gGL.pushMatrix();
+		{
+			// scale ui to reflect UIScaleFactor
+			// this can't be done in setup2DRender because it requires a
+			// pushMatrix/popMatrix pair
+			const LLVector2& display_scale = gViewerWindow->getDisplayScale();
+			gGL.scalef(display_scale.mV[VX], display_scale.mV[VY], 1.f);
+
+			gGL.getTexUnit(0)->bind(gDisconnectedImagep);
+			gGL.color4f(1.f, 1.f, 1.f, 1.f);
+			gl_rect_2d_simple_tex(width, height);
+			gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+		}
+		gGL.popMatrix();
+	}
+	gGL.flush();
+
+	if (LLGLSLShader::sNoFixedFunction)
+	{
+		gUIProgram.unbind();
+	}
+
+}
+
+void display_cleanup()
+{
+	gDisconnectedImagep = NULL;
+}
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index 4f34520924fd87506541e5b1375aeb738ef0381e..7f2aefcc2b43b05d3f9ccf1ac6703af89780e2d7 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -1,5286 +1,5286 @@
-/** 
- * @file llviewerwindow.cpp
- * @brief Implementation of the LLViewerWindow class.
- *
- * $LicenseInfo:firstyear=2001&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$
- */
-
-#include "llviewerprecompiledheaders.h"
-#include "llviewerwindow.h"
-
-#if LL_WINDOWS
-#pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally
-#endif
-
-// system library includes
-#include <stdio.h>
-#include <iostream>
-#include <fstream>
-#include <algorithm>
-#include <boost/lambda/core.hpp>
-
-#include "llagent.h"
-#include "llagentcamera.h"
-#include "llfloaterreg.h"
-#include "llmeshrepository.h"
-#include "llpanellogin.h"
-#include "llviewerkeyboard.h"
-#include "llviewermenu.h"
-
-#include "llviewquery.h"
-#include "llxmltree.h"
-#include "llslurl.h"
-//#include "llviewercamera.h"
-#include "llrender.h"
-
-#include "llvoiceclient.h"	// for push-to-talk button handling
-
-//
-// TODO: Many of these includes are unnecessary.  Remove them.
-//
-
-// linden library includes
-#include "llaudioengine.h"		// mute on minimize
-#include "indra_constants.h"
-#include "llassetstorage.h"
-#include "llerrorcontrol.h"
-#include "llfontgl.h"
-#include "llmousehandler.h"
-#include "llrect.h"
-#include "llsky.h"
-#include "llstring.h"
-#include "llui.h"
-#include "lluuid.h"
-#include "llview.h"
-#include "llxfermanager.h"
-#include "message.h"
-#include "object_flags.h"
-#include "lltimer.h"
-#include "timing.h"
-#include "llviewermenu.h"
-#include "lltooltip.h"
-#include "llmediaentry.h"
-#include "llurldispatcher.h"
-#include "raytrace.h"
-
-// newview includes
-#include "llagent.h"
-#include "llbox.h"
-#include "llchicletbar.h"
-#include "llconsole.h"
-#include "llviewercontrol.h"
-#include "llcylinder.h"
-#include "lldebugview.h"
-#include "lldir.h"
-#include "lldrawable.h"
-#include "lldrawpoolalpha.h"
-#include "lldrawpoolbump.h"
-#include "lldrawpoolwater.h"
-#include "llmaniptranslate.h"
-#include "llface.h"
-#include "llfeaturemanager.h"
-#include "llfilepicker.h"
-#include "llfirstuse.h"
-#include "llfloater.h"
-#include "llfloaterbuildoptions.h"
-#include "llfloaterbuyland.h"
-#include "llfloatercamera.h"
-#include "llfloaterland.h"
-#include "llfloaterinspect.h"
-#include "llfloatermap.h"
-#include "llfloaternamedesc.h"
-#include "llfloaterpreference.h"
-#include "llfloatersnapshot.h"
-#include "llfloatertools.h"
-#include "llfloaterworldmap.h"
-#include "llfocusmgr.h"
-#include "llfontfreetype.h"
-#include "llgesturemgr.h"
-#include "llglheaders.h"
-#include "lltooltip.h"
-#include "llhudmanager.h"
-#include "llhudobject.h"
-#include "llhudview.h"
-#include "llimagebmp.h"
-#include "llimagej2c.h"
-#include "llimageworker.h"
-#include "llkeyboard.h"
-#include "lllineeditor.h"
-#include "llmenugl.h"
-#include "llmodaldialog.h"
-#include "llmorphview.h"
-#include "llmoveview.h"
-#include "llnavigationbar.h"
-#include "llpaneltopinfobar.h"
-#include "llpopupview.h"
-#include "llpreviewtexture.h"
-#include "llprogressview.h"
-#include "llresmgr.h"
-#include "llselectmgr.h"
-#include "llrootview.h"
-#include "llrendersphere.h"
-#include "llstartup.h"
-#include "llstatusbar.h"
-#include "llstatview.h"
-#include "llsurface.h"
-#include "llsurfacepatch.h"
-#include "lltexlayer.h"
-#include "lltextbox.h"
-#include "lltexturecache.h"
-#include "lltexturefetch.h"
-#include "lltextureview.h"
-#include "lltool.h"
-#include "lltoolbarview.h"
-#include "lltoolcomp.h"
-#include "lltooldraganddrop.h"
-#include "lltoolface.h"
-#include "lltoolfocus.h"
-#include "lltoolgrab.h"
-#include "lltoolmgr.h"
-#include "lltoolmorph.h"
-#include "lltoolpie.h"
-#include "lltoolselectland.h"
-#include "lltrans.h"
-#include "lluictrlfactory.h"
-#include "llurldispatcher.h"		// SLURL from other app instance
-#include "llversioninfo.h"
-#include "llvieweraudio.h"
-#include "llviewercamera.h"
-#include "llviewergesture.h"
-#include "llviewertexturelist.h"
-#include "llviewerinventory.h"
-#include "llviewerkeyboard.h"
-#include "llviewermedia.h"
-#include "llviewermediafocus.h"
-#include "llviewermenu.h"
-#include "llviewermessage.h"
-#include "llviewerobjectlist.h"
-#include "llviewerparcelmgr.h"
-#include "llviewerregion.h"
-#include "llviewershadermgr.h"
-#include "llviewerstats.h"
-#include "llvoavatarself.h"
-#include "llvovolume.h"
-#include "llworld.h"
-#include "llworldmapview.h"
-#include "pipeline.h"
-#include "llappviewer.h"
-#include "llviewerdisplay.h"
-#include "llspatialpartition.h"
-#include "llviewerjoystick.h"
-#include "llviewernetwork.h"
-#include "llpostprocess.h"
-#include "llnearbychatbar.h"
-#include "llagentui.h"
-#include "llwearablelist.h"
-
-#include "llnotifications.h"
-#include "llnotificationsutil.h"
-#include "llnotificationmanager.h"
-
-#include "llfloaternotificationsconsole.h"
-
-#include "llnearbychat.h"
-#include "llwindowlistener.h"
-#include "llviewerwindowlistener.h"
-#include "llpaneltopinfobar.h"
-#include "llphysicsextensions.h"
-#include "llfloaterpathfindingconsole.h"
-
-#if LL_WINDOWS
-#include <tchar.h> // For Unicode conversion methods
-#endif
-
-//
-// Globals
-//
-void render_ui(F32 zoom_factor = 1.f, int subfield = 0);
-
-extern BOOL gDebugClicks;
-extern BOOL gDisplaySwapBuffers;
-extern BOOL gDepthDirty;
-extern BOOL gResizeScreenTexture;
-
-LLViewerWindow	*gViewerWindow = NULL;
-
-LLFrameTimer	gAwayTimer;
-LLFrameTimer	gAwayTriggerTimer;
-
-BOOL			gShowOverlayTitle = FALSE;
-
-LLViewerObject*  gDebugRaycastObject = NULL;
-LLVector3       gDebugRaycastIntersection;
-LLVector2       gDebugRaycastTexCoord;
-LLVector3       gDebugRaycastNormal;
-LLVector3       gDebugRaycastBinormal;
-S32				gDebugRaycastFaceHit;
-LLVector3		gDebugRaycastStart;
-LLVector3		gDebugRaycastEnd;
-
-// HUD display lines in lower right
-BOOL				gDisplayWindInfo = FALSE;
-BOOL				gDisplayCameraPos = FALSE;
-BOOL				gDisplayFOV = FALSE;
-BOOL				gDisplayBadge = FALSE;
-
-static const U8 NO_FACE = 255;
-BOOL gQuietSnapshot = FALSE;
-
-static const F32 MIN_DISPLAY_SCALE = 0.75f;
-
-std::string	LLViewerWindow::sSnapshotBaseName;
-std::string	LLViewerWindow::sSnapshotDir;
-
-std::string	LLViewerWindow::sMovieBaseName;
-
-class RecordToChatConsole : public LLError::Recorder, public LLSingleton<RecordToChatConsole>
-{
-public:
-	virtual void recordMessage(LLError::ELevel level,
-								const std::string& message)
-	{
-		//FIXME: this is NOT thread safe, and will do bad things when a warning is issued from a non-UI thread
-
-		// only log warnings to chat console
-		//if (level == LLError::LEVEL_WARN)
-		//{
-			//LLFloaterChat* chat_floater = LLFloaterReg::findTypedInstance<LLFloaterChat>("chat");
-			//if (chat_floater && gSavedSettings.getBOOL("WarningsAsChat"))
-			//{
-			//	LLChat chat;
-			//	chat.mText = message;
-			//	chat.mSourceType = CHAT_SOURCE_SYSTEM;
-
-			//	chat_floater->addChat(chat, FALSE, FALSE);
-			//}
-		//}
-	}
-};
-
-////////////////////////////////////////////////////////////////////////////
-//
-// LLDebugText
-//
-
-class LLDebugText
-{
-private:
-	struct Line
-	{
-		Line(const std::string& in_text, S32 in_x, S32 in_y) : text(in_text), x(in_x), y(in_y) {}
-		std::string text;
-		S32 x,y;
-	};
-
-	LLViewerWindow *mWindow;
-	
-	typedef std::vector<Line> line_list_t;
-	line_list_t mLineList;
-	LLColor4 mTextColor;
-	
-	void addText(S32 x, S32 y, const std::string &text) 
-	{
-		mLineList.push_back(Line(text, x, y));
-	}
-	
-	void clearText() { mLineList.clear(); }
-	
-public:
-	LLDebugText(LLViewerWindow* window) : mWindow(window) {}
-
-	void update()
-	{
-		static LLCachedControl<bool> log_texture_traffic(gSavedSettings,"LogTextureNetworkTraffic") ;
-
-		std::string wind_vel_text;
-		std::string wind_vector_text;
-		std::string rwind_vel_text;
-		std::string rwind_vector_text;
-		std::string audio_text;
-
-		static const std::string beacon_particle = LLTrans::getString("BeaconParticle");
-		static const std::string beacon_physical = LLTrans::getString("BeaconPhysical");
-		static const std::string beacon_scripted = LLTrans::getString("BeaconScripted");
-		static const std::string beacon_scripted_touch = LLTrans::getString("BeaconScriptedTouch");
-		static const std::string beacon_sound = LLTrans::getString("BeaconSound");
-		static const std::string beacon_media = LLTrans::getString("BeaconMedia");
-		static const std::string particle_hiding = LLTrans::getString("ParticleHiding");
-
-		// Draw the statistics in a light gray
-		// and in a thin font
-		mTextColor = LLColor4( 0.86f, 0.86f, 0.86f, 1.f );
-
-		// Draw stuff growing up from right lower corner of screen
-		U32 xpos = mWindow->getWorldViewWidthScaled() - 350;
-		U32 ypos = 64;
-		const U32 y_inc = 20;
-
-		clearText();
-		
-		if (gSavedSettings.getBOOL("DebugShowTime"))
-		{
-			const U32 y_inc2 = 15;
-			for (std::map<S32,LLFrameTimer>::reverse_iterator iter = gDebugTimers.rbegin();
-				 iter != gDebugTimers.rend(); ++iter)
-			{
-				S32 idx = iter->first;
-				LLFrameTimer& timer = iter->second;
-				F32 time = timer.getElapsedTimeF32();
-				S32 hours = (S32)(time / (60*60));
-				S32 mins = (S32)((time - hours*(60*60)) / 60);
-				S32 secs = (S32)((time - hours*(60*60) - mins*60));
-				std::string label = gDebugTimerLabel[idx];
-				if (label.empty()) label = llformat("Debug: %d", idx);
-				addText(xpos, ypos, llformat(" %s: %d:%02d:%02d", label.c_str(), hours,mins,secs)); ypos += y_inc2;
-			}
-			
-			F32 time = gFrameTimeSeconds;
-			S32 hours = (S32)(time / (60*60));
-			S32 mins = (S32)((time - hours*(60*60)) / 60);
-			S32 secs = (S32)((time - hours*(60*60) - mins*60));
-			addText(xpos, ypos, llformat("Time: %d:%02d:%02d", hours,mins,secs)); ypos += y_inc;
-		}
-		
-#if LL_WINDOWS
-		if (gSavedSettings.getBOOL("DebugShowMemory"))
-		{
-			addText(xpos, ypos, llformat("Memory: %d (KB)", LLMemory::getWorkingSetSize() / 1024)); 
-			ypos += y_inc;
-		}
-#endif
-
-		if (gDisplayCameraPos)
-		{
-			std::string camera_view_text;
-			std::string camera_center_text;
-			std::string agent_view_text;
-			std::string agent_left_text;
-			std::string agent_center_text;
-			std::string agent_root_center_text;
-
-			LLVector3d tvector; // Temporary vector to hold data for printing.
-
-			// Update camera center, camera view, wind info every other frame
-			tvector = gAgent.getPositionGlobal();
-			agent_center_text = llformat("AgentCenter  %f %f %f",
-										 (F32)(tvector.mdV[VX]), (F32)(tvector.mdV[VY]), (F32)(tvector.mdV[VZ]));
-
-			if (isAgentAvatarValid())
-			{
-				tvector = gAgent.getPosGlobalFromAgent(gAgentAvatarp->mRoot.getWorldPosition());
-				agent_root_center_text = llformat("AgentRootCenter %f %f %f",
-												  (F32)(tvector.mdV[VX]), (F32)(tvector.mdV[VY]), (F32)(tvector.mdV[VZ]));
-			}
-			else
-			{
-				agent_root_center_text = "---";
-			}
-
-
-			tvector = LLVector4(gAgent.getFrameAgent().getAtAxis());
-			agent_view_text = llformat("AgentAtAxis  %f %f %f",
-									   (F32)(tvector.mdV[VX]), (F32)(tvector.mdV[VY]), (F32)(tvector.mdV[VZ]));
-
-			tvector = LLVector4(gAgent.getFrameAgent().getLeftAxis());
-			agent_left_text = llformat("AgentLeftAxis  %f %f %f",
-									   (F32)(tvector.mdV[VX]), (F32)(tvector.mdV[VY]), (F32)(tvector.mdV[VZ]));
-
-			tvector = gAgentCamera.getCameraPositionGlobal();
-			camera_center_text = llformat("CameraCenter %f %f %f",
-										  (F32)(tvector.mdV[VX]), (F32)(tvector.mdV[VY]), (F32)(tvector.mdV[VZ]));
-
-			tvector = LLVector4(LLViewerCamera::getInstance()->getAtAxis());
-			camera_view_text = llformat("CameraAtAxis    %f %f %f",
-										(F32)(tvector.mdV[VX]), (F32)(tvector.mdV[VY]), (F32)(tvector.mdV[VZ]));
-		
-			addText(xpos, ypos, agent_center_text);  ypos += y_inc;
-			addText(xpos, ypos, agent_root_center_text);  ypos += y_inc;
-			addText(xpos, ypos, agent_view_text);  ypos += y_inc;
-			addText(xpos, ypos, agent_left_text);  ypos += y_inc;
-			addText(xpos, ypos, camera_center_text);  ypos += y_inc;
-			addText(xpos, ypos, camera_view_text);  ypos += y_inc;
-		}
-
-		if (gDisplayWindInfo)
-		{
-			wind_vel_text = llformat("Wind velocity %.2f m/s", gWindVec.magVec());
-			wind_vector_text = llformat("Wind vector   %.2f %.2f %.2f", gWindVec.mV[0], gWindVec.mV[1], gWindVec.mV[2]);
-			rwind_vel_text = llformat("RWind vel %.2f m/s", gRelativeWindVec.magVec());
-			rwind_vector_text = llformat("RWind vec   %.2f %.2f %.2f", gRelativeWindVec.mV[0], gRelativeWindVec.mV[1], gRelativeWindVec.mV[2]);
-
-			addText(xpos, ypos, wind_vel_text);  ypos += y_inc;
-			addText(xpos, ypos, wind_vector_text);  ypos += y_inc;
-			addText(xpos, ypos, rwind_vel_text);  ypos += y_inc;
-			addText(xpos, ypos, rwind_vector_text);  ypos += y_inc;
-		}
-		if (gDisplayWindInfo)
-		{
-			if (gAudiop)
-			{
-				audio_text= llformat("Audio for wind: %d", gAudiop->isWindEnabled());
-			}
-			addText(xpos, ypos, audio_text);  ypos += y_inc;
-		}
-		if (gDisplayFOV)
-		{
-			addText(xpos, ypos, llformat("FOV: %2.1f deg", RAD_TO_DEG * LLViewerCamera::getInstance()->getView()));
-			ypos += y_inc;
-		}
-		if (gDisplayBadge)
-		{
-			addText(xpos, ypos+(y_inc/2), llformat("Hippos!", RAD_TO_DEG * LLViewerCamera::getInstance()->getView()));
-			ypos += y_inc * 2;
-		}
-		
-		/*if (LLViewerJoystick::getInstance()->getOverrideCamera())
-		{
-			addText(xpos + 200, ypos, llformat("Flycam"));
-			ypos += y_inc;
-		}*/
-		
-		if (gSavedSettings.getBOOL("DebugShowRenderInfo"))
-		{
-			if (gPipeline.getUseVertexShaders() == 0)
-			{
-				addText(xpos, ypos, "Shaders Disabled");
-				ypos += y_inc;
-			}
-
-			if (gGLManager.mHasATIMemInfo)
-			{
-				S32 meminfo[4];
-				glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, meminfo);
-
-				addText(xpos, ypos, llformat("%.2f MB Texture Memory Free", meminfo[0]/1024.f));
-				ypos += y_inc;
-
-				if (gGLManager.mHasVertexBufferObject)
-				{
-					glGetIntegerv(GL_VBO_FREE_MEMORY_ATI, meminfo);
-					addText(xpos, ypos, llformat("%.2f MB VBO Memory Free", meminfo[0]/1024.f));
-					ypos += y_inc;
-				}
-			}
-			else if (gGLManager.mHasNVXMemInfo)
-			{
-				S32 free_memory;
-				glGetIntegerv(GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, &free_memory);
-				addText(xpos, ypos, llformat("%.2f MB Video Memory Free", free_memory/1024.f));
-				ypos += y_inc;
-			}
-
-			//show streaming cost/triangle count of known prims in current region OR selection
-			{
-				F32 cost = 0.f;
-				S32 count = 0;
-				S32 vcount = 0;
-				S32 object_count = 0;
-				S32 total_bytes = 0;
-				S32 visible_bytes = 0;
-
-				const char* label = "Region";
-				if (LLSelectMgr::getInstance()->getSelection()->getObjectCount() == 0)
-				{ //region
-					LLViewerRegion* region = gAgent.getRegion();
-					if (region)
-					{
-						for (U32 i = 0; i < gObjectList.getNumObjects(); ++i)
-						{
-							LLViewerObject* object = gObjectList.getObject(i);
-							if (object && 
-								object->getRegion() == region &&
-								object->getVolume())
-							{
-								object_count++;
-								S32 bytes = 0;	
-								S32 visible = 0;
-								cost += object->getStreamingCost(&bytes, &visible);
-								S32 vt = 0;
-								count += object->getTriangleCount(&vt);
-								vcount += vt;
-								total_bytes += bytes;
-								visible_bytes += visible;
-							}
-						}
-					}
-				}
-				else
-				{
-					label = "Selection";
-					cost = LLSelectMgr::getInstance()->getSelection()->getSelectedObjectStreamingCost(&total_bytes, &visible_bytes);
-					count = LLSelectMgr::getInstance()->getSelection()->getSelectedObjectTriangleCount(&vcount);
-					object_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount();
-				}
-					
-				addText(xpos,ypos, llformat("%s streaming cost: %.1f", label, cost));
-				ypos += y_inc;
-
-				addText(xpos, ypos, llformat("    %.3f KTris, %.3f KVerts, %.1f/%.1f KB, %d objects",
-										count/1000.f, vcount/1000.f, visible_bytes/1024.f, total_bytes/1024.f, object_count));
-				ypos += y_inc;
-			
-			}
-
-			addText(xpos, ypos, llformat("%d MB Vertex Data (%d MB Pooled)", LLVertexBuffer::sAllocatedBytes/(1024*1024), LLVBOPool::sBytesPooled/(1024*1024)));
-			ypos += y_inc;
-
-			addText(xpos, ypos, llformat("%d Vertex Buffers", LLVertexBuffer::sGLCount));
-			ypos += y_inc;
-
-			addText(xpos, ypos, llformat("%d Mapped Buffers", LLVertexBuffer::sMappedCount));
-			ypos += y_inc;
-
-			addText(xpos, ypos, llformat("%d Vertex Buffer Binds", LLVertexBuffer::sBindCount));
-			ypos += y_inc;
-
-			addText(xpos, ypos, llformat("%d Vertex Buffer Sets", LLVertexBuffer::sSetCount));
-			ypos += y_inc;
-
-			addText(xpos, ypos, llformat("%d Texture Binds", LLImageGL::sBindCount));
-			ypos += y_inc;
-
-			addText(xpos, ypos, llformat("%d Unique Textures", LLImageGL::sUniqueCount));
-			ypos += y_inc;
-
-			addText(xpos, ypos, llformat("%d Render Calls", gPipeline.mBatchCount));
-            ypos += y_inc;
-
-			addText(xpos, ypos, llformat("%d Matrix Ops", gPipeline.mMatrixOpCount));
-			ypos += y_inc;
-
-			addText(xpos, ypos, llformat("%d Texture Matrix Ops", gPipeline.mTextureMatrixOps));
-			ypos += y_inc;
-
-			gPipeline.mTextureMatrixOps = 0;
-			gPipeline.mMatrixOpCount = 0;
-
-			if (gPipeline.mBatchCount > 0)
-			{
-				addText(xpos, ypos, llformat("Batch min/max/mean: %d/%d/%d", gPipeline.mMinBatchSize, gPipeline.mMaxBatchSize, 
-					gPipeline.mTrianglesDrawn/gPipeline.mBatchCount));
-
-				gPipeline.mMinBatchSize = gPipeline.mMaxBatchSize;
-				gPipeline.mMaxBatchSize = 0;
-				gPipeline.mBatchCount = 0;
-			}
-            ypos += y_inc;
-
-			addText(xpos, ypos, llformat("UI Verts/Calls: %d/%d", LLRender::sUIVerts, LLRender::sUICalls));
-			LLRender::sUICalls = LLRender::sUIVerts = 0;
-			ypos += y_inc;
-
-			addText(xpos,ypos, llformat("%d/%d Nodes visible", gPipeline.mNumVisibleNodes, LLSpatialGroup::sNodeCount));
-			
-			ypos += y_inc;
-
-			if (!LLSpatialGroup::sPendingQueries.empty())
-			{
-				addText(xpos,ypos, llformat("%d Queries pending", LLSpatialGroup::sPendingQueries.size()));
-				ypos += y_inc;
-			}
-
-
-			addText(xpos,ypos, llformat("%d Avatars visible", LLVOAvatar::sNumVisibleAvatars));
-			
-			ypos += y_inc;
-
-			addText(xpos,ypos, llformat("%d Lights visible", LLPipeline::sVisibleLightCount));
-			
-			ypos += y_inc;
-
-			if (gMeshRepo.meshRezEnabled())
-			{
-				addText(xpos, ypos, llformat("%.3f MB Mesh Data Received", LLMeshRepository::sBytesReceived/(1024.f*1024.f)));
-				
-				ypos += y_inc;
-				
-				addText(xpos, ypos, llformat("%d/%d Mesh HTTP Requests/Retries", LLMeshRepository::sHTTPRequestCount,
-					LLMeshRepository::sHTTPRetryCount));
-				
-				ypos += y_inc;
-
-				addText(xpos, ypos, llformat("%.3f/%.3f MB Mesh Cache Read/Write ", LLMeshRepository::sCacheBytesRead/(1024.f*1024.f), LLMeshRepository::sCacheBytesWritten/(1024.f*1024.f)));
-
-				ypos += y_inc;
-			}
-
-			LLVertexBuffer::sBindCount = LLImageGL::sBindCount = 
-				LLVertexBuffer::sSetCount = LLImageGL::sUniqueCount = 
-				gPipeline.mNumVisibleNodes = LLPipeline::sVisibleLightCount = 0;
-		}
-		if (gSavedSettings.getBOOL("DebugShowRenderMatrices"))
-		{
-			addText(xpos, ypos, llformat("%.4f    .%4f    %.4f    %.4f", gGLProjection[12], gGLProjection[13], gGLProjection[14], gGLProjection[15]));
-			ypos += y_inc;
-
-			addText(xpos, ypos, llformat("%.4f    .%4f    %.4f    %.4f", gGLProjection[8], gGLProjection[9], gGLProjection[10], gGLProjection[11]));
-			ypos += y_inc;
-
-			addText(xpos, ypos, llformat("%.4f    .%4f    %.4f    %.4f", gGLProjection[4], gGLProjection[5], gGLProjection[6], gGLProjection[7]));
-			ypos += y_inc;
-
-			addText(xpos, ypos, llformat("%.4f    .%4f    %.4f    %.4f", gGLProjection[0], gGLProjection[1], gGLProjection[2], gGLProjection[3]));
-			ypos += y_inc;
-
-			addText(xpos, ypos, "Projection Matrix");
-			ypos += y_inc;
-
-
-			addText(xpos, ypos, llformat("%.4f    .%4f    %.4f    %.4f", gGLModelView[12], gGLModelView[13], gGLModelView[14], gGLModelView[15]));
-			ypos += y_inc;
-
-			addText(xpos, ypos, llformat("%.4f    .%4f    %.4f    %.4f", gGLModelView[8], gGLModelView[9], gGLModelView[10], gGLModelView[11]));
-			ypos += y_inc;
-
-			addText(xpos, ypos, llformat("%.4f    .%4f    %.4f    %.4f", gGLModelView[4], gGLModelView[5], gGLModelView[6], gGLModelView[7]));
-			ypos += y_inc;
-
-			addText(xpos, ypos, llformat("%.4f    .%4f    %.4f    %.4f", gGLModelView[0], gGLModelView[1], gGLModelView[2], gGLModelView[3]));
-			ypos += y_inc;
-
-			addText(xpos, ypos, "View Matrix");
-			ypos += y_inc;
-		}
-		if (gSavedSettings.getBOOL("DebugShowColor"))
-		{
-			U8 color[4];
-			LLCoordGL coord = gViewerWindow->getCurrentMouse();
-			glReadPixels(coord.mX, coord.mY, 1,1,GL_RGBA, GL_UNSIGNED_BYTE, color);
-			addText(xpos, ypos, llformat("%d %d %d %d", color[0], color[1], color[2], color[3]));
-			ypos += y_inc;
-		}
-
-		if (gSavedSettings.getBOOL("DebugShowPrivateMem"))
-		{
-			LLPrivateMemoryPoolManager::getInstance()->updateStatistics() ;
-			addText(xpos, ypos, llformat("Total Reserved(KB): %d", LLPrivateMemoryPoolManager::getInstance()->mTotalReservedSize / 1024));
-			ypos += y_inc;
-
-			addText(xpos, ypos, llformat("Total Allocated(KB): %d", LLPrivateMemoryPoolManager::getInstance()->mTotalAllocatedSize / 1024));
-			ypos += y_inc;
-		}
-
-		// only display these messages if we are actually rendering beacons at this moment
-		if (LLPipeline::getRenderBeacons(NULL) && LLFloaterReg::instanceVisible("beacons"))
-		{
-			if (LLPipeline::getRenderMOAPBeacons(NULL))
-			{
-				addText(xpos, ypos, "Viewing media beacons (white)");
-				ypos += y_inc;
-			}
-
-			if (LLPipeline::toggleRenderTypeControlNegated((void*)LLPipeline::RENDER_TYPE_PARTICLES))
-			{
-				addText(xpos, ypos, particle_hiding);
-				ypos += y_inc;
-			}
-
-			if (LLPipeline::getRenderParticleBeacons(NULL))
-			{
-				addText(xpos, ypos, "Viewing particle beacons (blue)");
-				ypos += y_inc;
-			}
-
-			if (LLPipeline::getRenderSoundBeacons(NULL))
-			{
-				addText(xpos, ypos, "Viewing sound beacons (yellow)");
-				ypos += y_inc;
-			}
-
-			if (LLPipeline::getRenderScriptedBeacons(NULL))
-			{
-				addText(xpos, ypos, beacon_scripted);
-				ypos += y_inc;
-			}
-			else
-				if (LLPipeline::getRenderScriptedTouchBeacons(NULL))
-				{
-					addText(xpos, ypos, beacon_scripted_touch);
-					ypos += y_inc;
-				}
-
-			if (LLPipeline::getRenderPhysicalBeacons(NULL))
-			{
-				addText(xpos, ypos, "Viewing physical object beacons (green)");
-				ypos += y_inc;
-			}
-		}
-
-		if(log_texture_traffic)
-		{	
-			U32 old_y = ypos ;
-			for(S32 i = LLViewerTexture::BOOST_NONE; i < LLViewerTexture::MAX_GL_IMAGE_CATEGORY; i++)
-			{
-				if(gTotalTextureBytesPerBoostLevel[i] > 0)
-				{
-					addText(xpos, ypos, llformat("Boost_Level %d:  %.3f MB", i, (F32)gTotalTextureBytesPerBoostLevel[i] / (1024 * 1024)));
-					ypos += y_inc;
-				}
-			}
-			if(ypos != old_y)
-			{
-				addText(xpos, ypos, "Network traffic for textures:");
-				ypos += y_inc;
-			}
-		}				
-
-		if (gSavedSettings.getBOOL("DebugShowTextureInfo"))
-		{
-			LLViewerObject* objectp = NULL ;
-			//objectp = = gAgentCamera.getFocusObject();
-			
-			LLSelectNode* nodep = LLSelectMgr::instance().getHoverNode();
-			if (nodep)
-			{
-				objectp = nodep->getObject();			
-			}
-			if (objectp && !objectp->isDead())
-			{
-				S32 num_faces = objectp->mDrawable->getNumFaces() ;
-				
-				for(S32 i = 0 ; i < num_faces; i++)
-				{
-					LLFace* facep = objectp->mDrawable->getFace(i) ;
-					if(facep)
-					{
-						//addText(xpos, ypos, llformat("ts_min: %.3f ts_max: %.3f tt_min: %.3f tt_max: %.3f", facep->mTexExtents[0].mV[0], facep->mTexExtents[1].mV[0],
-						//		facep->mTexExtents[0].mV[1], facep->mTexExtents[1].mV[1]));
-						//ypos += y_inc;
-						
-						addText(xpos, ypos, llformat("v_size: %.3f:  p_size: %.3f", facep->getVirtualSize(), facep->getPixelArea()));
-						ypos += y_inc;
-						
-						//const LLTextureEntry *tep = facep->getTextureEntry();
-						//if(tep)
-						//{
-						//	addText(xpos, ypos, llformat("scale_s: %.3f:  scale_t: %.3f", tep->mScaleS, tep->mScaleT)) ;
-						//	ypos += y_inc;
-						//}
-						
-						LLViewerTexture* tex = facep->getTexture() ;
-						if(tex)
-						{
-							addText(xpos, ypos, llformat("ID: %s v_size: %.3f", tex->getID().asString().c_str(), tex->getMaxVirtualSize()));
-							ypos += y_inc;
-						}
-					}
-				}
-			}
-		}
-	}
-
-	void draw()
-	{
-		for (line_list_t::iterator iter = mLineList.begin();
-			 iter != mLineList.end(); ++iter)
-		{
-			const Line& line = *iter;
-			LLFontGL::getFontMonospace()->renderUTF8(line.text, 0, (F32)line.x, (F32)line.y, mTextColor,
-											 LLFontGL::LEFT, LLFontGL::TOP,
-											 LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE);
-		}
-		mLineList.clear();
-	}
-
-};
-
-void LLViewerWindow::updateDebugText()
-{
-	mDebugText->update();
-}
-
-////////////////////////////////////////////////////////////////////////////
-//
-// LLViewerWindow
-//
-
-LLViewerWindow::Params::Params()
-:	title("title"),
-	name("name"),
-	x("x"),
-	y("y"),
-	width("width"),
-	height("height"),
-	min_width("min_width"),
-	min_height("min_height"),
-	fullscreen("fullscreen", false),
-	ignore_pixel_depth("ignore_pixel_depth", false)
-{}
-
-
-BOOL LLViewerWindow::handleAnyMouseClick(LLWindow *window,  LLCoordGL pos, MASK mask, LLMouseHandler::EClickType clicktype, BOOL down)
-{
-	const char* buttonname = "";
-	const char* buttonstatestr = "";
-	S32 x = pos.mX;
-	S32 y = pos.mY;
-	x = llround((F32)x / mDisplayScale.mV[VX]);
-	y = llround((F32)y / mDisplayScale.mV[VY]);
-
-				
-	// only send mouse clicks to UI if UI is visible
-	if(gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
-	{	
-
-		if (down)
-		{
-			buttonstatestr = "down" ;
-		}
-		else
-		{
-			buttonstatestr = "up" ;
-		}
-		
-		switch (clicktype)
-		{
-		case LLMouseHandler::CLICK_LEFT:
-			mLeftMouseDown = down;
-			buttonname = "Left";
-			break;
-		case LLMouseHandler::CLICK_RIGHT:
-			mRightMouseDown = down;
-			buttonname = "Right";
-			break;
-		case LLMouseHandler::CLICK_MIDDLE:
-			mMiddleMouseDown = down;
-			buttonname = "Middle";
-			break;
-		case LLMouseHandler::CLICK_DOUBLELEFT:
-			mLeftMouseDown = down;
-			buttonname = "Left Double Click";
-			break;
-		}
-		
-		LLView::sMouseHandlerMessage.clear();
-
-		if (gMenuBarView)
-		{
-			// stop ALT-key access to menu
-			gMenuBarView->resetMenuTrigger();
-		}
-
-		if (gDebugClicks)
-		{	
-			llinfos << "ViewerWindow " << buttonname << " mouse " << buttonstatestr << " at " << x << "," << y << llendl;
-		}
-
-		// Make sure we get a corresponding mouseup event, even if the mouse leaves the window
-		if (down)
-			mWindow->captureMouse();
-		else
-			mWindow->releaseMouse();
-
-		// Indicate mouse was active
-		LLUI::resetMouseIdleTimer();
-
-		// Don't let the user move the mouse out of the window until mouse up.
-		if( LLToolMgr::getInstance()->getCurrentTool()->clipMouseWhenDown() )
-		{
-			mWindow->setMouseClipping(down);
-		}
-
-		LLMouseHandler* mouse_captor = gFocusMgr.getMouseCapture();
-		if( mouse_captor )
-		{
-			S32 local_x;
-			S32 local_y;
-			mouse_captor->screenPointToLocal( x, y, &local_x, &local_y );
-			if (LLView::sDebugMouseHandling)
-			{
-				llinfos << buttonname << " Mouse " << buttonstatestr << " handled by captor " << mouse_captor->getName() << llendl;
-			}
-			return mouse_captor->handleAnyMouseClick(local_x, local_y, mask, clicktype, down);
-		}
-
-		// Topmost view gets a chance before the hierarchy
-		//LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl();
-		//if (top_ctrl)
-		//{
-		//	S32 local_x, local_y;
-		//	top_ctrl->screenPointToLocal( x, y, &local_x, &local_y );
-		//		if (top_ctrl->pointInView(local_x, local_y))
-		//		{
-		//			return top_ctrl->handleAnyMouseClick(local_x, local_y, mask, clicktype, down)	;
-		//		}
-		//		else
-		//		{
-		//		if (down)
-		//		{
-		//			gFocusMgr.setTopCtrl(NULL);
-		//		}
-		//	}
-		//}
-
-		// Mark the click as handled and return if we aren't within the root view to avoid spurious bugs
-		if( !mRootView->pointInView(x, y) )
-		{
-			return TRUE;
-		}
-		// Give the UI views a chance to process the click
-		if( mRootView->handleAnyMouseClick(x, y, mask, clicktype, down) )
-		{
-			if (LLView::sDebugMouseHandling)
-			{
-				llinfos << buttonname << " Mouse " << buttonstatestr << " " << LLView::sMouseHandlerMessage << llendl;
-			}
-			return TRUE;
-		}
-		else if (LLView::sDebugMouseHandling)
-		{
-			llinfos << buttonname << " Mouse " << buttonstatestr << " not handled by view" << llendl;
-		}
-	}
-
-
-	//Determine if we have a pathing system and subsequently provide any mouse input
-	if ( LLPathingLib::getInstance() && mLeftMouseDown == down )
-	{
-		LLVector3 dv		= mouseDirectionGlobal(x,y);
-		LLVector3 mousePos	= LLViewerCamera::getInstance()->getOrigin();
-		LLVector3 rayStart	= mousePos;
-		LLVector3 rayEnd	= mousePos + dv * 150;
-	
-		//Determine if alt is being held in conjunction with a lmb click, if alt is being held
-		//then do not provide any input to the pathingLib console
-		MASK currentKeyMask = gKeyboard->currentMask(TRUE);
-		if ( !(currentKeyMask & MASK_ALT) )
-		{
-			LLFloaterPathfindingConsole* pFloater = LLFloaterReg::getTypedInstance<LLFloaterPathfindingConsole>("pathfinding_console");
-			if ( pFloater )
-			{
-				//The floater takes care of determining what stage - essentially where the data goes into the pathing packet(start or end)
-				pFloater->providePathingData( rayStart, rayEnd );
-			}
-		}
-	}
-
-	// Do not allow tool manager to handle mouseclicks if we have disconnected	
-	if(!gDisconnected && LLToolMgr::getInstance()->getCurrentTool()->handleAnyMouseClick( x, y, mask, clicktype, down ) )
-	{
-		return TRUE;
-	}
-	
-
-	// If we got this far on a down-click, it wasn't handled.
-	// Up-clicks, though, are always handled as far as the OS is concerned.
-	BOOL default_rtn = !down;
-	return default_rtn;
-}
-
-BOOL LLViewerWindow::handleMouseDown(LLWindow *window,  LLCoordGL pos, MASK mask)
-{
-	BOOL down = TRUE;
-	return handleAnyMouseClick(window,pos,mask,LLMouseHandler::CLICK_LEFT,down);
-}
-
-BOOL LLViewerWindow::handleDoubleClick(LLWindow *window,  LLCoordGL pos, MASK mask)
-{
-	// try handling as a double-click first, then a single-click if that
-	// wasn't handled.
-	BOOL down = TRUE;
-	if (handleAnyMouseClick(window, pos, mask,
-				LLMouseHandler::CLICK_DOUBLELEFT, down))
-	{
-		return TRUE;
-	}
-	return handleMouseDown(window, pos, mask);
-}
-
-BOOL LLViewerWindow::handleMouseUp(LLWindow *window,  LLCoordGL pos, MASK mask)
-{
-	BOOL down = FALSE;
-	return handleAnyMouseClick(window,pos,mask,LLMouseHandler::CLICK_LEFT,down);
-}
-
-
-BOOL LLViewerWindow::handleRightMouseDown(LLWindow *window,  LLCoordGL pos, MASK mask)
-{
-	S32 x = pos.mX;
-	S32 y = pos.mY;
-	x = llround((F32)x / mDisplayScale.mV[VX]);
-	y = llround((F32)y / mDisplayScale.mV[VY]);
-
-	BOOL down = TRUE;
-	BOOL handle = handleAnyMouseClick(window,pos,mask,LLMouseHandler::CLICK_RIGHT,down);
-	if (handle)
-		return handle;
-
-	// *HACK: this should be rolled into the composite tool logic, not
-	// hardcoded at the top level.
-	if (CAMERA_MODE_CUSTOMIZE_AVATAR != gAgentCamera.getCameraMode() && LLToolMgr::getInstance()->getCurrentTool() != LLToolPie::getInstance())
-	{
-		// If the current tool didn't process the click, we should show
-		// the pie menu.  This can be done by passing the event to the pie
-		// menu tool.
-		LLToolPie::getInstance()->handleRightMouseDown(x, y, mask);
-		// show_context_menu( x, y, mask );
-	}
-
-	return TRUE;
-}
-
-BOOL LLViewerWindow::handleRightMouseUp(LLWindow *window,  LLCoordGL pos, MASK mask)
-{
-	BOOL down = FALSE;
- 	return handleAnyMouseClick(window,pos,mask,LLMouseHandler::CLICK_RIGHT,down);
-}
-
-BOOL LLViewerWindow::handleMiddleMouseDown(LLWindow *window,  LLCoordGL pos, MASK mask)
-{
-	BOOL down = TRUE;
-	LLVoiceClient::getInstance()->middleMouseState(true);
- 	handleAnyMouseClick(window,pos,mask,LLMouseHandler::CLICK_MIDDLE,down);
-  
-  	// Always handled as far as the OS is concerned.
-	return TRUE;
-}
-
-LLWindowCallbacks::DragNDropResult LLViewerWindow::handleDragNDrop( LLWindow *window, LLCoordGL pos, MASK mask, LLWindowCallbacks::DragNDropAction action, std::string data)
-{
-	LLWindowCallbacks::DragNDropResult result = LLWindowCallbacks::DND_NONE;
-
-	const bool prim_media_dnd_enabled = gSavedSettings.getBOOL("PrimMediaDragNDrop");
-	const bool slurl_dnd_enabled = gSavedSettings.getBOOL("SLURLDragNDrop");
-	
-	if ( prim_media_dnd_enabled || slurl_dnd_enabled )
-	{
-		switch(action)
-		{
-			// Much of the handling for these two cases is the same.
-			case LLWindowCallbacks::DNDA_TRACK:
-			case LLWindowCallbacks::DNDA_DROPPED:
-			case LLWindowCallbacks::DNDA_START_TRACKING:
-			{
-				bool drop = (LLWindowCallbacks::DNDA_DROPPED == action);
-					
-				if (slurl_dnd_enabled)
-				{
-					LLSLURL dropped_slurl(data);
-					if(dropped_slurl.isSpatial())
-					{
-						if (drop)
-						{
-							LLURLDispatcher::dispatch( dropped_slurl.getSLURLString(), "clicked", NULL, true );
-							return LLWindowCallbacks::DND_MOVE;
-						}
-						return LLWindowCallbacks::DND_COPY;
-					}
-				}
-
-				if (prim_media_dnd_enabled)
-				{
-					LLPickInfo pick_info = pickImmediate( pos.mX, pos.mY,  TRUE /*BOOL pick_transparent*/ );
-
-					LLUUID object_id = pick_info.getObjectID();
-					S32 object_face = pick_info.mObjectFace;
-					std::string url = data;
-
-					lldebugs << "Object: picked at " << pos.mX << ", " << pos.mY << " - face = " << object_face << " - URL = " << url << llendl;
-
-					LLVOVolume *obj = dynamic_cast<LLVOVolume*>(static_cast<LLViewerObject*>(pick_info.getObject()));
-				
-					if (obj && !obj->getRegion()->getCapability("ObjectMedia").empty())
-					{
-						LLTextureEntry *te = obj->getTE(object_face);
-
-						// can modify URL if we can modify the object or we have navigate permissions
-						bool allow_modify_url = obj->permModify() || obj->hasMediaPermission( te->getMediaData(), LLVOVolume::MEDIA_PERM_INTERACT );
-
-						if (te && allow_modify_url )
-						{
-							if (drop)
-							{
-								// object does NOT have media already
-								if ( ! te->hasMedia() )
-								{
-									// we are allowed to modify the object
-									if ( obj->permModify() )
-									{
-										// Create new media entry
-										LLSD media_data;
-										// XXX Should we really do Home URL too?
-										media_data[LLMediaEntry::HOME_URL_KEY] = url;
-										media_data[LLMediaEntry::CURRENT_URL_KEY] = url;
-										media_data[LLMediaEntry::AUTO_PLAY_KEY] = true;
-										obj->syncMediaData(object_face, media_data, true, true);
-										// XXX This shouldn't be necessary, should it ?!?
-										if (obj->getMediaImpl(object_face))
-											obj->getMediaImpl(object_face)->navigateReload();
-										obj->sendMediaDataUpdate();
-
-										result = LLWindowCallbacks::DND_COPY;
-									}
-								}
-								else 
-								// object HAS media already
-								{
-									// URL passes the whitelist
-									if (te->getMediaData()->checkCandidateUrl( url ) )
-									{
-										// just navigate to the URL
-										if (obj->getMediaImpl(object_face))
-										{
-											obj->getMediaImpl(object_face)->navigateTo(url);
-										}
-										else 
-										{
-											// This is very strange.  Navigation should
-											// happen via the Impl, but we don't have one.
-											// This sends it to the server, which /should/
-											// trigger us getting it.  Hopefully.
-											LLSD media_data;
-											media_data[LLMediaEntry::CURRENT_URL_KEY] = url;
-											obj->syncMediaData(object_face, media_data, true, true);
-											obj->sendMediaDataUpdate();
-										}
-										result = LLWindowCallbacks::DND_LINK;
-										
-									}
-								}
-								LLSelectMgr::getInstance()->unhighlightObjectOnly(mDragHoveredObject);
-								mDragHoveredObject = NULL;
-							
-							}
-							else 
-							{
-								// Check the whitelist, if there's media (otherwise just show it)
-								if (te->getMediaData() == NULL || te->getMediaData()->checkCandidateUrl(url))
-								{
-									if ( obj != mDragHoveredObject)
-									{
-										// Highlight the dragged object
-										LLSelectMgr::getInstance()->unhighlightObjectOnly(mDragHoveredObject);
-										mDragHoveredObject = obj;
-										LLSelectMgr::getInstance()->highlightObjectOnly(mDragHoveredObject);
-									}
-									result = (! te->hasMedia()) ? LLWindowCallbacks::DND_COPY : LLWindowCallbacks::DND_LINK;
-
-								}
-							}
-						}
-					}
-				}
-			}
-			break;
-			
-			case LLWindowCallbacks::DNDA_STOP_TRACKING:
-				// The cleanup case below will make sure things are unhilighted if necessary.
-			break;
-		}
-
-		if (prim_media_dnd_enabled &&
-			result == LLWindowCallbacks::DND_NONE && !mDragHoveredObject.isNull())
-		{
-			LLSelectMgr::getInstance()->unhighlightObjectOnly(mDragHoveredObject);
-			mDragHoveredObject = NULL;
-		}
-	}
-	
-	return result;
-}
-  
-BOOL LLViewerWindow::handleMiddleMouseUp(LLWindow *window,  LLCoordGL pos, MASK mask)
-{
-	BOOL down = FALSE;
-	LLVoiceClient::getInstance()->middleMouseState(false);
- 	handleAnyMouseClick(window,pos,mask,LLMouseHandler::CLICK_MIDDLE,down);
-  
-  	// Always handled as far as the OS is concerned.
-	return TRUE;
-}
-
-// WARNING: this is potentially called multiple times per frame
-void LLViewerWindow::handleMouseMove(LLWindow *window,  LLCoordGL pos, MASK mask)
-{
-	S32 x = pos.mX;
-	S32 y = pos.mY;
-
-	x = llround((F32)x / mDisplayScale.mV[VX]);
-	y = llround((F32)y / mDisplayScale.mV[VY]);
-
-	mMouseInWindow = TRUE;
-
-	// Save mouse point for access during idle() and display()
-
-	LLCoordGL mouse_point(x, y);
-
-	if (mouse_point != mCurrentMousePoint)
-	{
-		LLUI::resetMouseIdleTimer();
-	}
-
-	saveLastMouse(mouse_point);
-
-	mWindow->showCursorFromMouseMove();
-
-	if (gAwayTimer.getElapsedTimeF32() > LLAgent::MIN_AFK_TIME
-		&& !gDisconnected)
-	{
-		gAgent.clearAFK();
-	}
-}
-
-void LLViewerWindow::handleMouseLeave(LLWindow *window)
-{
-	// Note: we won't get this if we have captured the mouse.
-	llassert( gFocusMgr.getMouseCapture() == NULL );
-	mMouseInWindow = FALSE;
-	LLToolTipMgr::instance().blockToolTips();
-}
-
-BOOL LLViewerWindow::handleCloseRequest(LLWindow *window)
-{
-	// User has indicated they want to close, but we may need to ask
-	// about modified documents.
-	LLAppViewer::instance()->userQuit();
-	// Don't quit immediately
-	return FALSE;
-}
-
-void LLViewerWindow::handleQuit(LLWindow *window)
-{
-	LLAppViewer::instance()->forceQuit();
-}
-
-void LLViewerWindow::handleResize(LLWindow *window,  S32 width,  S32 height)
-{
-	reshape(width, height);
-	mResDirty = true;
-}
-
-// The top-level window has gained focus (e.g. via ALT-TAB)
-void LLViewerWindow::handleFocus(LLWindow *window)
-{
-	gFocusMgr.setAppHasFocus(TRUE);
-	LLModalDialog::onAppFocusGained();
-
-	gAgent.onAppFocusGained();
-	LLToolMgr::getInstance()->onAppFocusGained();
-
-	// See if we're coming in with modifier keys held down
-	if (gKeyboard)
-	{
-		gKeyboard->resetMaskKeys();
-	}
-
-	// resume foreground running timer
-	// since we artifically limit framerate when not frontmost
-	gForegroundTime.unpause();
-}
-
-// The top-level window has lost focus (e.g. via ALT-TAB)
-void LLViewerWindow::handleFocusLost(LLWindow *window)
-{
-	gFocusMgr.setAppHasFocus(FALSE);
-	//LLModalDialog::onAppFocusLost();
-	LLToolMgr::getInstance()->onAppFocusLost();
-	gFocusMgr.setMouseCapture( NULL );
-
-	if (gMenuBarView)
-	{
-		// stop ALT-key access to menu
-		gMenuBarView->resetMenuTrigger();
-	}
-
-	// restore mouse cursor
-	showCursor();
-	getWindow()->setMouseClipping(FALSE);
-
-	// If losing focus while keys are down, reset them.
-	if (gKeyboard)
-	{
-		gKeyboard->resetKeys();
-	}
-
-	// pause timer that tracks total foreground running time
-	gForegroundTime.pause();
-}
-
-
-BOOL LLViewerWindow::handleTranslatedKeyDown(KEY key,  MASK mask, BOOL repeated)
-{
-	// Let the voice chat code check for its PTT key.  Note that this never affects event processing.
-	LLVoiceClient::getInstance()->keyDown(key, mask);
-	
-	if (gAwayTimer.getElapsedTimeF32() > LLAgent::MIN_AFK_TIME)
-	{
-		gAgent.clearAFK();
-	}
-
-	// *NOTE: We want to interpret KEY_RETURN later when it arrives as
-	// a Unicode char, not as a keydown.  Otherwise when client frame
-	// rate is really low, hitting return sends your chat text before
-	// it's all entered/processed.
-	if (key == KEY_RETURN && mask == MASK_NONE)
-	{
-		return FALSE;
-	}
-
-	return gViewerKeyboard.handleKey(key, mask, repeated);
-}
-
-BOOL LLViewerWindow::handleTranslatedKeyUp(KEY key,  MASK mask)
-{
-	// Let the voice chat code check for its PTT key.  Note that this never affects event processing.
-	LLVoiceClient::getInstance()->keyUp(key, mask);
-
-	return FALSE;
-}
-
-
-void LLViewerWindow::handleScanKey(KEY key, BOOL key_down, BOOL key_up, BOOL key_level)
-{
-	LLViewerJoystick::getInstance()->setCameraNeedsUpdate(true);
-	return gViewerKeyboard.scanKey(key, key_down, key_up, key_level);
-}
-
-
-
-
-BOOL LLViewerWindow::handleActivate(LLWindow *window, BOOL activated)
-{
-	if (activated)
-	{
-		mActive = true;
-		send_agent_resume();
-		gAgent.clearAFK();
-		
-		// Unmute audio
-		audio_update_volume();
-	}
-	else
-	{
-		mActive = false;
-				
-		// if the user has chosen to go Away automatically after some time, then go Away when minimizing
-		if (gSavedSettings.getS32("AFKTimeout"))
-		{
-			gAgent.setAFK();
-		}
-		
-		// SL-53351: Make sure we're not in mouselook when minimised, to prevent control issues
-		if (gAgentCamera.getCameraMode() == CAMERA_MODE_MOUSELOOK)
-		{
-			gAgentCamera.changeCameraToDefault();
-		}
-		
-		send_agent_pause();
-	
-		// Mute audio
-		audio_update_volume();
-	}
-	return TRUE;
-}
-
-BOOL LLViewerWindow::handleActivateApp(LLWindow *window, BOOL activating)
-{
-	//if (!activating) gAgentCamera.changeCameraToDefault();
-
-	LLViewerJoystick::getInstance()->setNeedsReset(true);
-	return FALSE;
-}
-
-
-void LLViewerWindow::handleMenuSelect(LLWindow *window,  S32 menu_item)
-{
-}
-
-
-BOOL LLViewerWindow::handlePaint(LLWindow *window,  S32 x,  S32 y, S32 width,  S32 height)
-{
-	// *TODO: Enable similar information output for other platforms?  DK 2011-02-18
-#if LL_WINDOWS
-	if (gHeadlessClient)
-	{
-		HWND window_handle = (HWND)window->getPlatformWindow();
-		PAINTSTRUCT ps; 
-		HDC hdc; 
- 
-		RECT wnd_rect;
-		wnd_rect.left = 0;
-		wnd_rect.top = 0;
-		wnd_rect.bottom = 200;
-		wnd_rect.right = 500;
-
-		hdc = BeginPaint(window_handle, &ps); 
-		//SetBKColor(hdc, RGB(255, 255, 255));
-		FillRect(hdc, &wnd_rect, CreateSolidBrush(RGB(255, 255, 255)));
-
-		std::string temp_str;
-		temp_str = llformat( "FPS %3.1f Phy FPS %2.1f Time Dil %1.3f",		/* Flawfinder: ignore */
-				LLViewerStats::getInstance()->mFPSStat.getMeanPerSec(),
-				LLViewerStats::getInstance()->mSimPhysicsFPS.getPrev(0),
-				LLViewerStats::getInstance()->mSimTimeDilation.getPrev(0));
-		S32 len = temp_str.length();
-		TextOutA(hdc, 0, 0, temp_str.c_str(), len); 
-
-
-		LLVector3d pos_global = gAgent.getPositionGlobal();
-		temp_str = llformat( "Avatar pos %6.1lf %6.1lf %6.1lf", pos_global.mdV[0], pos_global.mdV[1], pos_global.mdV[2]);
-		len = temp_str.length();
-		TextOutA(hdc, 0, 25, temp_str.c_str(), len); 
-
-		TextOutA(hdc, 0, 50, "Set \"HeadlessClient FALSE\" in settings.ini file to reenable", 61);
-		EndPaint(window_handle, &ps); 
-		return TRUE;
-	}
-#endif
-	return FALSE;
-}
-
-
-void LLViewerWindow::handleScrollWheel(LLWindow *window,  S32 clicks)
-{
-	handleScrollWheel( clicks );
-}
-
-void LLViewerWindow::handleWindowBlock(LLWindow *window)
-{
-	send_agent_pause();
-}
-
-void LLViewerWindow::handleWindowUnblock(LLWindow *window)
-{
-	send_agent_resume();
-}
-
-void LLViewerWindow::handleDataCopy(LLWindow *window, S32 data_type, void *data)
-{
-	const S32 SLURL_MESSAGE_TYPE = 0;
-	switch (data_type)
-	{
-	case SLURL_MESSAGE_TYPE:
-		// received URL
-		std::string url = (const char*)data;
-		LLMediaCtrl* web = NULL;
-		const bool trusted_browser = false;
-		// don't treat slapps coming from external browsers as "clicks" as this would bypass throttling
-		if (LLURLDispatcher::dispatch(url, "", web, trusted_browser))
-		{
-			// bring window to foreground, as it has just been "launched" from a URL
-			mWindow->bringToFront();
-		}
-		break;
-	}
-}
-
-BOOL LLViewerWindow::handleTimerEvent(LLWindow *window)
-{
-	if (LLViewerJoystick::getInstance()->getOverrideCamera())
-	{
-		LLViewerJoystick::getInstance()->updateStatus();
-		return TRUE;
-	}
-	return FALSE;
-}
-
-BOOL LLViewerWindow::handleDeviceChange(LLWindow *window)
-{
-	// give a chance to use a joystick after startup (hot-plugging)
-	if (!LLViewerJoystick::getInstance()->isJoystickInitialized() )
-	{
-		LLViewerJoystick::getInstance()->init(true);
-		return TRUE;
-	}
-	return FALSE;
-}
-
-void LLViewerWindow::handlePingWatchdog(LLWindow *window, const char * msg)
-{
-	LLAppViewer::instance()->pingMainloopTimeout(msg);
-}
-
-
-void LLViewerWindow::handleResumeWatchdog(LLWindow *window)
-{
-	LLAppViewer::instance()->resumeMainloopTimeout();
-}
-
-void LLViewerWindow::handlePauseWatchdog(LLWindow *window)
-{
-	LLAppViewer::instance()->pauseMainloopTimeout();
-}
-
-//virtual
-std::string LLViewerWindow::translateString(const char* tag)
-{
-	return LLTrans::getString( std::string(tag) );
-}
-
-//virtual
-std::string LLViewerWindow::translateString(const char* tag,
-		const std::map<std::string, std::string>& args)
-{
-	// LLTrans uses a special subclass of std::string for format maps,
-	// but we must use std::map<> in these callbacks, otherwise we create
-	// a dependency between LLWindow and LLFormatMapString.  So copy the data.
-	LLStringUtil::format_map_t args_copy;
-	std::map<std::string,std::string>::const_iterator it = args.begin();
-	for ( ; it != args.end(); ++it)
-	{
-		args_copy[it->first] = it->second;
-	}
-	return LLTrans::getString( std::string(tag), args_copy);
-}
-
-//
-// Classes
-//
-LLViewerWindow::LLViewerWindow(const Params& p)
-:	mWindow(NULL),
-	mActive(true),
-	mUIVisible(true),
-	mWindowRectRaw(0, p.height, p.width, 0),
-	mWindowRectScaled(0, p.height, p.width, 0),
-	mWorldViewRectRaw(0, p.height, p.width, 0),
-	mLeftMouseDown(FALSE),
-	mMiddleMouseDown(FALSE),
-	mRightMouseDown(FALSE),
-	mMouseInWindow( FALSE ),
-	mLastMask( MASK_NONE ),
-	mToolStored( NULL ),
-	mHideCursorPermanent( FALSE ),
-	mCursorHidden(FALSE),
-	mIgnoreActivate( FALSE ),
-	mResDirty(false),
-	mStatesDirty(false),
-	mCurrResolutionIndex(0),
-	// gKeyboard is still NULL, so it doesn't do LLWindowListener any good to
-	// pass its value right now. Instead, pass it a nullary function that
-	// will, when we later need it, return the value of gKeyboard.
-	// boost::lambda::var() constructs such a functor on the fly.
-	mWindowListener(new LLWindowListener(this, boost::lambda::var(gKeyboard))),
-	mViewerWindowListener(new LLViewerWindowListener(this)),
-	mProgressView(NULL)
-{
-	LLNotificationChannel::buildChannel("VW_alerts", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "alert"));
-	LLNotificationChannel::buildChannel("VW_alertmodal", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "alertmodal"));
-
-	LLNotifications::instance().getChannel("VW_alerts")->connectChanged(&LLViewerWindow::onAlert);
-	LLNotifications::instance().getChannel("VW_alertmodal")->connectChanged(&LLViewerWindow::onAlert);
-	LLNotifications::instance().setIgnoreAllNotifications(gSavedSettings.getBOOL("IgnoreAllNotifications"));
-	llinfos << "NOTE: ALL NOTIFICATIONS THAT OCCUR WILL GET ADDED TO IGNORE LIST FOR LATER RUNS." << llendl;
-
-	// Default to application directory.
-	LLViewerWindow::sSnapshotBaseName = "Snapshot";
-	LLViewerWindow::sMovieBaseName = "SLmovie";
-	resetSnapshotLoc();
-
-	// create window
-	mWindow = LLWindowManager::createWindow(this,
-		p.title, p.name, p.x, p.y, p.width, p.height, 0,
-		p.fullscreen, 
-		gHeadlessClient,
-		gSavedSettings.getBOOL("DisableVerticalSync"),
-		!gHeadlessClient,
-		p.ignore_pixel_depth,
-		gSavedSettings.getBOOL("RenderDeferred") ? 0 : gSavedSettings.getU32("RenderFSAASamples")); //don't use window level anti-aliasing if FBOs are enabled
-
-	if (!LLViewerShaderMgr::sInitialized)
-	{ //immediately initialize shaders
-		LLViewerShaderMgr::sInitialized = TRUE;
-		LLViewerShaderMgr::instance()->setShaders();
-	}
-
-	if (NULL == mWindow)
-	{
-		LLSplashScreen::update(LLTrans::getString("StartupRequireDriverUpdate"));
-	
-		LL_WARNS("Window") << "Failed to create window, to be shutting Down, be sure your graphics driver is updated." << llendl ;
-
-		ms_sleep(5000) ; //wait for 5 seconds.
-
-		LLSplashScreen::update(LLTrans::getString("ShuttingDown"));
-#if LL_LINUX || LL_SOLARIS
-		llwarns << "Unable to create window, be sure screen is set at 32-bit color and your graphics driver is configured correctly.  See README-linux.txt or README-solaris.txt for further information."
-				<< llendl;
-#else
-		LL_WARNS("Window") << "Unable to create window, be sure screen is set at 32-bit color in Control Panels->Display->Settings"
-				<< LL_ENDL;
-#endif
-        LLAppViewer::instance()->fastQuit(1);
-	}
-	
-	if (!LLAppViewer::instance()->restoreErrorTrap())
-	{
-		LL_WARNS("Window") << " Someone took over my signal/exception handler (post createWindow)!" << LL_ENDL;
-	}
-
-	const bool do_not_enforce = false;
-	mWindow->setMinSize(p.min_width, p.min_height, do_not_enforce);  // root view not set 
-	LLCoordScreen scr;
-    mWindow->getSize(&scr);
-
-    if(p.fullscreen && ( scr.mX!=p.width || scr.mY!=p.height))
-    {
-		llwarns << "Fullscreen has forced us in to a different resolution now using "<<scr.mX<<" x "<<scr.mY<<llendl;
-		gSavedSettings.setS32("FullScreenWidth",scr.mX);
-		gSavedSettings.setS32("FullScreenHeight",scr.mY);
-    }
-
-	// Get the real window rect the window was created with (since there are various OS-dependent reasons why
-	// the size of a window or fullscreen context may have been adjusted slightly...)
-	F32 ui_scale_factor = gSavedSettings.getF32("UIScaleFactor");
-	
-	mDisplayScale.setVec(llmax(1.f / mWindow->getPixelAspectRatio(), 1.f), llmax(mWindow->getPixelAspectRatio(), 1.f));
-	mDisplayScale *= ui_scale_factor;
-	LLUI::setScaleFactor(mDisplayScale);
-
-	{
-		LLCoordWindow size;
-		mWindow->getSize(&size);
-		mWindowRectRaw.set(0, size.mY, size.mX, 0);
-		mWindowRectScaled.set(0, llround((F32)size.mY / mDisplayScale.mV[VY]), llround((F32)size.mX / mDisplayScale.mV[VX]), 0);
-	}
-	
-	LLFontManager::initClass();
-
-	//
-	// We want to set this stuff up BEFORE we initialize the pipeline, so we can turn off
-	// stuff like AGP if we think that it'll crash the viewer.
-	//
-	LL_DEBUGS("Window") << "Loading feature tables." << LL_ENDL;
-
-	LLFeatureManager::getInstance()->init();
-
-	// Initialize OpenGL Renderer
-	if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderVBOEnable") ||
-		!gGLManager.mHasVertexBufferObject)
-	{
-		gSavedSettings.setBOOL("RenderVBOEnable", FALSE);
-	}
-	LLVertexBuffer::initClass(gSavedSettings.getBOOL("RenderVBOEnable"), gSavedSettings.getBOOL("RenderVBOMappingDisable"));
-	LL_INFOS("RenderInit") << "LLVertexBuffer initialization done." << LL_ENDL ;
-	gGL.init() ;
-
-	if (LLFeatureManager::getInstance()->isSafe()
-		|| (gSavedSettings.getS32("LastFeatureVersion") != LLFeatureManager::getInstance()->getVersion())
-		|| (gSavedSettings.getString("LastGPUString") != LLFeatureManager::getInstance()->getGPUString())
-		|| (gSavedSettings.getBOOL("ProbeHardwareOnStartup")))
-	{
-		LLFeatureManager::getInstance()->applyRecommendedSettings();
-		gSavedSettings.setBOOL("ProbeHardwareOnStartup", FALSE);
-	}
-
-	if (!gGLManager.mHasDepthClamp)
-	{
-		LL_INFOS("RenderInit") << "Missing feature GL_ARB_depth_clamp. Void water might disappear in rare cases." << LL_ENDL;
-	}
-	
-	// If we crashed while initializng GL stuff last time, disable certain features
-	if (gSavedSettings.getBOOL("RenderInitError"))
-	{
-		mInitAlert = "DisplaySettingsNoShaders";
-		LLFeatureManager::getInstance()->setGraphicsLevel(0, false);
-		gSavedSettings.setU32("RenderQualityPerformance", 0);		
-	}
-		
-	// Init the image list.  Must happen after GL is initialized and before the images that
-	// LLViewerWindow needs are requested.
-	LLImageGL::initClass(LLViewerTexture::MAX_GL_IMAGE_CATEGORY) ;
-	gTextureList.init();
-	LLViewerTextureManager::init() ;
-	gBumpImageList.init();
-	
-	// Init font system, but don't actually load the fonts yet
-	// because our window isn't onscreen and they take several
-	// seconds to parse.
-	LLFontGL::initClass( gSavedSettings.getF32("FontScreenDPI"),
-								mDisplayScale.mV[VX],
-								mDisplayScale.mV[VY],
-								gDirUtilp->getAppRODataDir(),
-								LLUI::getXUIPaths());
-	
-	// Create container for all sub-views
-	LLView::Params rvp;
-	rvp.name("root");
-	rvp.rect(mWindowRectScaled);
-	rvp.mouse_opaque(false);
-	rvp.follows.flags(FOLLOWS_NONE);
-	mRootView = LLUICtrlFactory::create<LLRootView>(rvp);
-	LLUI::setRootView(mRootView);
-
-	// Make avatar head look forward at start
-	mCurrentMousePoint.mX = getWindowWidthScaled() / 2;
-	mCurrentMousePoint.mY = getWindowHeightScaled() / 2;
-
-	gShowOverlayTitle = gSavedSettings.getBOOL("ShowOverlayTitle");
-	mOverlayTitle = gSavedSettings.getString("OverlayTitle");
-	// Can't have spaces in settings.ini strings, so use underscores instead and convert them.
-	LLStringUtil::replaceChar(mOverlayTitle, '_', ' ');
-
-	// sync the keyboard's setting with the saved setting
-	gSavedSettings.getControl("NumpadControl")->firePropertyChanged();
-
-	mDebugText = new LLDebugText(this);
-
-	mWorldViewRectScaled = calcScaledRect(mWorldViewRectRaw, mDisplayScale);
-}
-
-void LLViewerWindow::initGLDefaults()
-{
-	gGL.setSceneBlendType(LLRender::BT_ALPHA);
-
-	if (!LLGLSLShader::sNoFixedFunction)
-	{ //initialize fixed function state
-		glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE );
-
-		glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT,LLColor4::black.mV);
-		glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,LLColor4::white.mV);
-
-		// lights for objects
-		glShadeModel( GL_SMOOTH );
-
-		gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
-		gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
-	}
-
-	glPixelStorei(GL_PACK_ALIGNMENT,1);
-	glPixelStorei(GL_UNPACK_ALIGNMENT,1);
-
-	gGL.setAmbientLightColor(LLColor4::black);
-		
-	glCullFace(GL_BACK);
-
-	// RN: Need this for translation and stretch manip.
-	gBox.prerender();
-}
-
-struct MainPanel : public LLPanel
-{
-};
-
-void LLViewerWindow::initBase()
-{
-	S32 height = getWindowHeightScaled();
-	S32 width = getWindowWidthScaled();
-
-	LLRect full_window(0, height, width, 0);
-
-	////////////////////
-	//
-	// Set the gamma
-	//
-
-	F32 gamma = gSavedSettings.getF32("RenderGamma");
-	if (gamma != 0.0f)
-	{
-		getWindow()->setGamma(gamma);
-	}
-
-	// Create global views
-
-	// Create the floater view at the start so that other views can add children to it. 
-	// (But wait to add it as a child of the root view so that it will be in front of the 
-	// other views.)
-	MainPanel* main_view = new MainPanel();
-	main_view->buildFromFile("main_view.xml");
-	main_view->setShape(full_window);
-	getRootView()->addChild(main_view);
-
-	// placeholder widget that controls where "world" is rendered
-	mWorldViewPlaceholder = main_view->getChildView("world_view_rect")->getHandle();
-	mPopupView = main_view->getChild<LLPopupView>("popup_holder");
-	mHintHolder = main_view->getChild<LLView>("hint_holder")->getHandle();
-	mLoginPanelHolder = main_view->getChild<LLView>("login_panel_holder")->getHandle();
-
-	// Create the toolbar view
-	// Get a pointer to the toolbar view holder
-	LLPanel* panel_holder = main_view->getChild<LLPanel>("toolbar_view_holder");
-	// Load the toolbar view from file 
-	gToolBarView = LLUICtrlFactory::getInstance()->createFromFile<LLToolBarView>("panel_toolbar_view.xml", panel_holder, LLDefaultChildRegistry::instance());
-	gToolBarView->setShape(panel_holder->getLocalRect());
-	// Hide the toolbars for the moment: we'll make them visible after logging in world (see LLViewerWindow::initWorldUI())
-	gToolBarView->setVisible(FALSE);
-
-	// Constrain floaters to inside the menu and status bar regions.
-	gFloaterView = main_view->getChild<LLFloaterView>("Floater View");
-	gFloaterView->setFloaterSnapView(main_view->getChild<LLView>("floater_snap_region")->getHandle());
-	gSnapshotFloaterView = main_view->getChild<LLSnapshotFloaterView>("Snapshot Floater View");
-	
-
-	// Console
-	llassert( !gConsole );
-	LLConsole::Params cp;
-	cp.name("console");
-	cp.max_lines(gSavedSettings.getS32("ConsoleBufferSize"));
-	cp.rect(getChatConsoleRect());
-	cp.persist_time(gSavedSettings.getF32("ChatPersistTime"));
-	cp.font_size_index(gSavedSettings.getS32("ChatFontSize"));
-	cp.follows.flags(FOLLOWS_LEFT | FOLLOWS_RIGHT | FOLLOWS_BOTTOM);
-	gConsole = LLUICtrlFactory::create<LLConsole>(cp);
-	getRootView()->addChild(gConsole);
-
-	// optionally forward warnings to chat console/chat floater
-	// for qa runs and dev builds
-#if  !LL_RELEASE_FOR_DOWNLOAD
-	LLError::addRecorder(RecordToChatConsole::getInstance());
-#else
-	if(gSavedSettings.getBOOL("QAMode"))
-	{
-		LLError::addRecorder(RecordToChatConsole::getInstance());
-	}
-#endif
-
-	gDebugView = getRootView()->getChild<LLDebugView>("DebugView");
-	gDebugView->init();
-	gToolTipView = getRootView()->getChild<LLToolTipView>("tooltip view");
-
-	// Initialize busy response message when logged in
-	LLAppViewer::instance()->setOnLoginCompletedCallback(boost::bind(&LLFloaterPreference::initBusyResponse));
-
-	// Add the progress bar view (startup view), which overrides everything
-	mProgressView = getRootView()->findChild<LLProgressView>("progress_view");
-	setShowProgress(FALSE);
-	setProgressCancelButtonVisible(FALSE);
-
-	gMenuHolder = getRootView()->getChild<LLViewerMenuHolderGL>("Menu Holder");
-
-	LLMenuGL::sMenuContainer = gMenuHolder;
-
-}
-
-void LLViewerWindow::initWorldUI()
-{
-	S32 height = mRootView->getRect().getHeight();
-	S32 width = mRootView->getRect().getWidth();
-	LLRect full_window(0, height, width, 0);
-
-
-	gIMMgr = LLIMMgr::getInstance();
-
-	//getRootView()->sendChildToFront(gFloaterView);
-	//getRootView()->sendChildToFront(gSnapshotFloaterView);
-
-	LLPanel* chiclet_container = getRootView()->getChild<LLPanel>("chiclet_container");
-	LLChicletBar* chiclet_bar = LLChicletBar::getInstance();
-	chiclet_bar->setShape(chiclet_container->getLocalRect());
-	chiclet_bar->setFollowsAll();
-	chiclet_container->addChild(chiclet_bar);
-	chiclet_container->setVisible(TRUE);
-
-	LLRect morph_view_rect = full_window;
-	morph_view_rect.stretch( -STATUS_BAR_HEIGHT );
-	morph_view_rect.mTop = full_window.mTop - 32;
-	LLMorphView::Params mvp;
-	mvp.name("MorphView");
-	mvp.rect(morph_view_rect);
-	mvp.visible(false);
-	gMorphView = LLUICtrlFactory::create<LLMorphView>(mvp);
-	getRootView()->addChild(gMorphView);
-
-	LLWorldMapView::initClass();
-	
-	// Force gFloaterWorldMap to initialize
-	LLFloaterReg::getInstance("world_map");
-
-	// Force gFloaterTools to initialize
-	LLFloaterReg::getInstance("build");
-	LLFloaterReg::hideInstance("build");
-
-	// Status bar
-	LLPanel* status_bar_container = getRootView()->getChild<LLPanel>("status_bar_container");
-	gStatusBar = new LLStatusBar(status_bar_container->getLocalRect());
-	gStatusBar->setFollowsAll();
-	gStatusBar->setShape(status_bar_container->getLocalRect());
-	// sync bg color with menu bar
-	gStatusBar->setBackgroundColor( gMenuBarView->getBackgroundColor().get() );
-	status_bar_container->addChildInBack(gStatusBar);
-	status_bar_container->setVisible(TRUE);
-
-	// Navigation bar
-	LLPanel* nav_bar_container = getRootView()->getChild<LLPanel>("nav_bar_container");
-
-	LLNavigationBar* navbar = LLNavigationBar::getInstance();
-	navbar->setShape(nav_bar_container->getLocalRect());
-	navbar->setBackgroundColor(gMenuBarView->getBackgroundColor().get());
-	nav_bar_container->addChild(navbar);
-	nav_bar_container->setVisible(TRUE);
-	
-	if (!gSavedSettings.getBOOL("ShowNavbarNavigationPanel"))
-	{
-		navbar->setVisible(FALSE);
-	}
-
-	// Top Info bar
-	LLPanel* topinfo_bar_container = getRootView()->getChild<LLPanel>("topinfo_bar_container");
-	LLPanelTopInfoBar* topinfo_bar = LLPanelTopInfoBar::getInstance();
-
-	topinfo_bar->setShape(topinfo_bar_container->getLocalRect());
-
-	topinfo_bar_container->addChild(topinfo_bar);
-	topinfo_bar_container->setVisible(TRUE);
-
-	if (!gSavedSettings.getBOOL("ShowMiniLocationPanel"))
-	{
-		topinfo_bar->setVisible(FALSE);
-	}
-
-	if ( gHUDView == NULL )
-	{
-		LLRect hud_rect = full_window;
-		hud_rect.mBottom += 50;
-		if (gMenuBarView && gMenuBarView->isInVisibleChain())
-		{
-			hud_rect.mTop -= gMenuBarView->getRect().getHeight();
-		}
-		gHUDView = new LLHUDView(hud_rect);
-		getRootView()->addChild(gHUDView);
-	}
-
-	LLPanel* panel_ssf_container = getRootView()->getChild<LLPanel>("stand_stop_flying_container");
-	LLPanelStandStopFlying* panel_stand_stop_flying	= LLPanelStandStopFlying::getInstance();
-	panel_ssf_container->addChild(panel_stand_stop_flying);
-	panel_ssf_container->setVisible(TRUE);
-
-	// Load and make the toolbars visible
-	// Note: we need to load the toolbars only *after* the user is logged in and IW
-	if (gToolBarView)
-	{
-		gToolBarView->loadToolbars();
-		gToolBarView->setVisible(TRUE);
-	}
-
-	LLMediaCtrl* destinations = LLFloaterReg::getInstance("destinations")->getChild<LLMediaCtrl>("destination_guide_contents");
-	if (destinations)
-	{
-		destinations->setErrorPageURL(gSavedSettings.getString("GenericErrorPageURL"));
-		std::string url = gSavedSettings.getString("DestinationGuideURL");
-		url = LLWeb::expandURLSubstitutions(url, LLSD());
-		destinations->navigateTo(url, "text/html");
-	}
-	LLMediaCtrl* avatar_picker = LLFloaterReg::getInstance("avatar")->findChild<LLMediaCtrl>("avatar_picker_contents");
-	if (avatar_picker)
-	{
-		avatar_picker->setErrorPageURL(gSavedSettings.getString("GenericErrorPageURL"));
-		std::string url = gSavedSettings.getString("AvatarPickerURL");
-		url = LLWeb::expandURLSubstitutions(url, LLSD());
-		avatar_picker->navigateTo(url, "text/html");
-	}
-}
-
-// Destroy the UI
-void LLViewerWindow::shutdownViews()
-{
-	// clean up warning logger
-	LLError::removeRecorder(RecordToChatConsole::getInstance());
-
-	delete mDebugText;
-	mDebugText = NULL;
-	
-	// Cleanup global views
-	if (gMorphView)
-	{
-		gMorphView->setVisible(FALSE);
-	}
-
-	// DEV-40930: Clear sModalStack. Otherwise, any LLModalDialog left open
-	// will crump with LL_ERRS.
-	LLModalDialog::shutdownModals();
-	
-	// destroy the nav bar, not currently part of gViewerWindow
-	// *TODO: Make LLNavigationBar part of gViewerWindow
-	if (LLNavigationBar::instanceExists())
-	{
-		delete LLNavigationBar::getInstance();
-	}
-
-	// destroy menus after instantiating navbar above, as it needs
-	// access to gMenuHolder
-	cleanup_menus();
-
-	// Delete all child views.
-	delete mRootView;
-	mRootView = NULL;
-
-	// Automatically deleted as children of mRootView.  Fix the globals.
-	gStatusBar = NULL;
-	gIMMgr = NULL;
-	gToolTipView = NULL;
-
-	gToolBarView = NULL;
-	gFloaterView = NULL;
-	gMorphView = NULL;
-
-	gHUDView = NULL;
-}
-
-void LLViewerWindow::shutdownGL()
-{
-	//--------------------------------------------------------
-	// Shutdown GL cleanly.  Order is very important here.
-	//--------------------------------------------------------
-	LLFontGL::destroyDefaultFonts();
-	LLFontManager::cleanupClass();
-	stop_glerror();
-
-	gSky.cleanup();
-	stop_glerror();
-
-	LLWearableList::instance().cleanup() ;
-
-	gTextureList.shutdown();
-	stop_glerror();
-
-	gBumpImageList.shutdown();
-	stop_glerror();
-
-	LLWorldMapView::cleanupTextures();
-
-	llinfos << "Cleaning up pipeline" << llendl;
-	gPipeline.cleanup();
-	stop_glerror();
-
-	LLViewerTextureManager::cleanup() ;
-	LLImageGL::cleanupClass() ;
-
-	llinfos << "All textures and llimagegl images are destroyed!" << llendl ;
-
-	llinfos << "Cleaning up select manager" << llendl;
-	LLSelectMgr::getInstance()->cleanup();	
-
-	llinfos << "Stopping GL during shutdown" << llendl;
-	stopGL(FALSE);
-	stop_glerror();
-
-	gGL.shutdown();
-
-	LLVertexBuffer::cleanupClass();
-
-	llinfos << "LLVertexBuffer cleaned." << llendl ;
-}
-
-// shutdownViews() and shutdownGL() need to be called first
-LLViewerWindow::~LLViewerWindow()
-{
-	llinfos << "Destroying Window" << llendl;
-	destroyWindow();
-
-	delete mDebugText;
-	mDebugText = NULL;
-}
-
-
-void LLViewerWindow::setCursor( ECursorType c )
-{
-	mWindow->setCursor( c );
-}
-
-void LLViewerWindow::showCursor()
-{
-	mWindow->showCursor();
-	
-	mCursorHidden = FALSE;
-}
-
-void LLViewerWindow::hideCursor()
-{
-	// And hide the cursor
-	mWindow->hideCursor();
-
-	mCursorHidden = TRUE;
-}
-
-void LLViewerWindow::sendShapeToSim()
-{
-	LLMessageSystem* msg = gMessageSystem;
-	if(!msg) return;
-	msg->newMessageFast(_PREHASH_AgentHeightWidth);
-	msg->nextBlockFast(_PREHASH_AgentData);
-	msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
-	msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
-	msg->addU32Fast(_PREHASH_CircuitCode, gMessageSystem->mOurCircuitCode);
-	msg->nextBlockFast(_PREHASH_HeightWidthBlock);
-	msg->addU32Fast(_PREHASH_GenCounter, 0);
-	U16 height16 = (U16) mWorldViewRectRaw.getHeight();
-	U16 width16 = (U16) mWorldViewRectRaw.getWidth();
-	msg->addU16Fast(_PREHASH_Height, height16);
-	msg->addU16Fast(_PREHASH_Width, width16);
-	gAgent.sendReliableMessage();
-}
-
-// Must be called after window is created to set up agent
-// camera variables and UI variables.
-void LLViewerWindow::reshape(S32 width, S32 height)
-{
-	// Destroying the window at quit time generates spurious
-	// reshape messages.  We don't care about these, and we
-	// don't want to send messages because the message system
-	// may have been destructed.
-	if (!LLApp::isExiting())
-	{
-		gWindowResized = TRUE;
-
-		// update our window rectangle
-		mWindowRectRaw.mRight = mWindowRectRaw.mLeft + width;
-		mWindowRectRaw.mTop = mWindowRectRaw.mBottom + height;
-
-		//glViewport(0, 0, width, height );
-
-		if (height > 0)
-		{ 
-			LLViewerCamera::getInstance()->setViewHeightInPixels( mWorldViewRectRaw.getHeight() );
-			LLViewerCamera::getInstance()->setAspect( getWorldViewAspectRatio() );
-		}
-
-		calcDisplayScale();
-	
-		BOOL display_scale_changed = mDisplayScale != LLUI::sGLScaleFactor;
-		LLUI::setScaleFactor(mDisplayScale);
-
-		// update our window rectangle
-		mWindowRectScaled.mRight = mWindowRectScaled.mLeft + llround((F32)width / mDisplayScale.mV[VX]);
-		mWindowRectScaled.mTop = mWindowRectScaled.mBottom + llround((F32)height / mDisplayScale.mV[VY]);
-
-		setup2DViewport();
-
-		// Inform lower views of the change
-		// round up when converting coordinates to make sure there are no gaps at edge of window
-		LLView::sForceReshape = display_scale_changed;
-		mRootView->reshape(llceil((F32)width / mDisplayScale.mV[VX]), llceil((F32)height / mDisplayScale.mV[VY]));
-		LLView::sForceReshape = FALSE;
-
-		// clear font width caches
-		if (display_scale_changed)
-		{
-			LLHUDObject::reshapeAll();
-		}
-
-		sendShapeToSim();
-
-		// store new settings for the mode we are in, regardless
-		BOOL maximized = mWindow->getMaximized();
-		gSavedSettings.setBOOL("WindowMaximized", maximized);
-
-		if (!maximized)
-		{
-			U32 min_window_width=gSavedSettings.getU32("MinWindowWidth");
-			U32 min_window_height=gSavedSettings.getU32("MinWindowHeight");
-			// tell the OS specific window code about min window size
-			mWindow->setMinSize(min_window_width, min_window_height);
-
-			// Only save size if not maximized
-			gSavedSettings.setU32("WindowWidth", mWindowRectRaw.getWidth());
-			gSavedSettings.setU32("WindowHeight", mWindowRectRaw.getHeight());
-		}
-
-		LLViewerStats::getInstance()->setStat(LLViewerStats::ST_WINDOW_WIDTH, (F64)width);
-		LLViewerStats::getInstance()->setStat(LLViewerStats::ST_WINDOW_HEIGHT, (F64)height);
-	}
-}
-
-
-// Hide normal UI when a logon fails
-void LLViewerWindow::setNormalControlsVisible( BOOL visible )
-{
-	if(LLChicletBar::instanceExists())
-	{
-		LLChicletBar::getInstance()->setVisible(visible);
-		LLChicletBar::getInstance()->setEnabled(visible);
-	}
-
-	if ( gMenuBarView )
-	{
-		gMenuBarView->setVisible( visible );
-		gMenuBarView->setEnabled( visible );
-
-		// ...and set the menu color appropriately.
-		setMenuBackgroundColor(gAgent.getGodLevel() > GOD_NOT, 
-			LLGridManager::getInstance()->isInProductionGrid());
-	}
-        
-	if ( gStatusBar )
-	{
-		gStatusBar->setVisible( visible );	
-		gStatusBar->setEnabled( visible );	
-	}
-	
-	LLNavigationBar* navbarp = LLUI::getRootView()->findChild<LLNavigationBar>("navigation_bar");
-	if (navbarp)
-	{
-		// when it's time to show navigation bar we need to ensure that the user wants to see it
-		// i.e. ShowNavbarNavigationPanel option is true
-		navbarp->setVisible( visible && gSavedSettings.getBOOL("ShowNavbarNavigationPanel") );
-	}
-}
-
-void LLViewerWindow::setMenuBackgroundColor(bool god_mode, bool dev_grid)
-{
-    LLSD args;
-    LLColor4 new_bg_color;
-
-	// no l10n problem because channel is always an english string
-	std::string channel = LLVersionInfo::getChannel();
-	bool isProject = (channel.find("Project") != std::string::npos);
-	
-	// god more important than project, proj more important than grid
-    if(god_mode && LLGridManager::getInstance()->isInProductionGrid())
-    {
-        new_bg_color = LLUIColorTable::instance().getColor( "MenuBarGodBgColor" );
-    }
-    else if(god_mode && !LLGridManager::getInstance()->isInProductionGrid())
-    {
-        new_bg_color = LLUIColorTable::instance().getColor( "MenuNonProductionGodBgColor" );
-    }
-	else if (!god_mode && isProject)
-	{
-		new_bg_color = LLUIColorTable::instance().getColor( "MenuBarProjectBgColor" );
-    }
-    else if(!god_mode && !LLGridManager::getInstance()->isInProductionGrid())
-    {
-        new_bg_color = LLUIColorTable::instance().getColor( "MenuNonProductionBgColor" );
-    }
-    else 
-    {
-        new_bg_color = LLUIColorTable::instance().getColor( "MenuBarBgColor" );
-    }
-
-    if(gMenuBarView)
-    {
-        gMenuBarView->setBackgroundColor( new_bg_color );
-    }
-
-    if(gStatusBar)
-    {
-        gStatusBar->setBackgroundColor( new_bg_color );
-    }
-}
-
-void LLViewerWindow::drawDebugText()
-{
-	gGL.color4f(1,1,1,1);
-	gGL.pushMatrix();
-	gGL.pushUIMatrix();
-	if (LLGLSLShader::sNoFixedFunction)
-	{
-		gUIProgram.bind();
-	}
-	{
-		// scale view by UI global scale factor and aspect ratio correction factor
-		gGL.scaleUI(mDisplayScale.mV[VX], mDisplayScale.mV[VY], 1.f);
-		mDebugText->draw();
-	}
-	gGL.popUIMatrix();
-	gGL.popMatrix();
-
-	gGL.flush();
-	if (LLGLSLShader::sNoFixedFunction)
-	{
-		gUIProgram.unbind();
-	}
-}
-
-void LLViewerWindow::draw()
-{
-	
-//#if LL_DEBUG
-	LLView::sIsDrawing = TRUE;
-//#endif
-	stop_glerror();
-	
-	LLUI::setLineWidth(1.f);
-
-	LLUI::setLineWidth(1.f);
-	// Reset any left-over transforms
-	gGL.matrixMode(LLRender::MM_MODELVIEW);
-	
-	gGL.loadIdentity();
-
-	//S32 screen_x, screen_y;
-
-	if (!gSavedSettings.getBOOL("RenderUIBuffer"))
-	{
-		LLUI::sDirtyRect = getWindowRectScaled();
-	}
-
-	// HACK for timecode debugging
-	if (gSavedSettings.getBOOL("DisplayTimecode"))
-	{
-		// draw timecode block
-		std::string text;
-
-		gGL.loadIdentity();
-
-		microsecondsToTimecodeString(gFrameTime,text);
-		const LLFontGL* font = LLFontGL::getFontSansSerif();
-		font->renderUTF8(text, 0,
-						llround((getWindowWidthScaled()/2)-100.f),
-						llround((getWindowHeightScaled()-60.f)),
-			LLColor4( 1.f, 1.f, 1.f, 1.f ),
-			LLFontGL::LEFT, LLFontGL::TOP);
-	}
-
-	// Draw all nested UI views.
-	// No translation needed, this view is glued to 0,0
-
-	if (LLGLSLShader::sNoFixedFunction)
-	{
-		gUIProgram.bind();
-	}
-
-	gGL.pushMatrix();
-	LLUI::pushMatrix();
-	{
-		
-		// scale view by UI global scale factor and aspect ratio correction factor
-		gGL.scaleUI(mDisplayScale.mV[VX], mDisplayScale.mV[VY], 1.f);
-
-		LLVector2 old_scale_factor = LLUI::sGLScaleFactor;
-		// apply camera zoom transform (for high res screenshots)
-		F32 zoom_factor = LLViewerCamera::getInstance()->getZoomFactor();
-		S16 sub_region = LLViewerCamera::getInstance()->getZoomSubRegion();
-		if (zoom_factor > 1.f)
-		{
-			//decompose subregion number to x and y values
-			int pos_y = sub_region / llceil(zoom_factor);
-			int pos_x = sub_region - (pos_y*llceil(zoom_factor));
-			// offset for this tile
-			gGL.translatef((F32)getWindowWidthScaled() * -(F32)pos_x, 
-						(F32)getWindowHeightScaled() * -(F32)pos_y, 
-						0.f);
-			gGL.scalef(zoom_factor, zoom_factor, 1.f);
-			LLUI::sGLScaleFactor *= zoom_factor;
-		}
-
-		// Draw tool specific overlay on world
-		LLToolMgr::getInstance()->getCurrentTool()->draw();
-
-		if( gAgentCamera.cameraMouselook() || LLFloaterCamera::inFreeCameraMode() )
-		{
-			drawMouselookInstructions();
-			stop_glerror();
-		}
-
-		// Draw all nested UI views.
-		// No translation needed, this view is glued to 0,0
-		mRootView->draw();
-
-		if (LLView::sDebugRects)
-		{
-			gToolTipView->drawStickyRect();
-		}
-
-		// Draw optional on-top-of-everyone view
-		LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl();
-		if (top_ctrl && top_ctrl->getVisible())
-		{
-			S32 screen_x, screen_y;
-			top_ctrl->localPointToScreen(0, 0, &screen_x, &screen_y);
-
-			gGL.matrixMode(LLRender::MM_MODELVIEW);
-			LLUI::pushMatrix();
-			LLUI::translate( (F32) screen_x, (F32) screen_y, 0.f);
-			top_ctrl->draw();	
-			LLUI::popMatrix();
-		}
-
-
-		if( gShowOverlayTitle && !mOverlayTitle.empty() )
-		{
-			// Used for special titles such as "Second Life - Special E3 2003 Beta"
-			const S32 DIST_FROM_TOP = 20;
-			LLFontGL::getFontSansSerifBig()->renderUTF8(
-				mOverlayTitle, 0,
-				llround( getWindowWidthScaled() * 0.5f),
-				getWindowHeightScaled() - DIST_FROM_TOP,
-				LLColor4(1, 1, 1, 0.4f),
-				LLFontGL::HCENTER, LLFontGL::TOP);
-		}
-
-		LLUI::sGLScaleFactor = old_scale_factor;
-	}
-	LLUI::popMatrix();
-	gGL.popMatrix();
-
-	if (LLGLSLShader::sNoFixedFunction)
-	{
-		gUIProgram.unbind();
-	}
-
-//#if LL_DEBUG
-	LLView::sIsDrawing = FALSE;
-//#endif
-}
-
-// Takes a single keydown event, usually when UI is visible
-BOOL LLViewerWindow::handleKey(KEY key, MASK mask)
-{
-	// hide tooltips on keypress
-	LLToolTipMgr::instance().blockToolTips();
-
-	if (gFocusMgr.getKeyboardFocus() 
-		&& !(mask & (MASK_CONTROL | MASK_ALT))
-		&& !gFocusMgr.getKeystrokesOnly())
-	{
-		// We have keyboard focus, and it's not an accelerator
-		if (key < 0x80)
-		{
-			// Not a special key, so likely (we hope) to generate a character.  Let it fall through to character handler first.
-			return (gFocusMgr.getKeyboardFocus() != NULL);
-		}
-	}
-
-	// let menus handle navigation keys for navigation
-	if ((gMenuBarView && gMenuBarView->handleKey(key, mask, TRUE))
-		||(gLoginMenuBarView && gLoginMenuBarView->handleKey(key, mask, TRUE))
-		||(gMenuHolder && gMenuHolder->handleKey(key, mask, TRUE)))
-	{
-		return TRUE;
-	}
-
-	LLFocusableElement* keyboard_focus = gFocusMgr.getKeyboardFocus();
-
-	// give menus a chance to handle modified (Ctrl, Alt) shortcut keys before current focus 
-	// as long as focus isn't locked
-	if (mask & (MASK_CONTROL | MASK_ALT) && !gFocusMgr.focusLocked())
-	{
-		// Check the current floater's menu first, if it has one.
-		if (gFocusMgr.keyboardFocusHasAccelerators()
-			&& keyboard_focus 
-			&& keyboard_focus->handleKey(key,mask,FALSE))
-		{
-			return TRUE;
-		}
-
-		if ((gMenuBarView && gMenuBarView->handleAcceleratorKey(key, mask))
-			||(gLoginMenuBarView && gLoginMenuBarView->handleAcceleratorKey(key, mask)))
-		{
-			return TRUE;
-		}
-	}
-
-	// give floaters first chance to handle TAB key
-	// so frontmost floater gets focus
-	// if nothing has focus, go to first or last UI element as appropriate
-	if (key == KEY_TAB && (mask & MASK_CONTROL || gFocusMgr.getKeyboardFocus() == NULL))
-	{
-		if (gMenuHolder) gMenuHolder->hideMenus();
-
-		// if CTRL-tabbing (and not just TAB with no focus), go into window cycle mode
-		gFloaterView->setCycleMode((mask & MASK_CONTROL) != 0);
-
-		// do CTRL-TAB and CTRL-SHIFT-TAB logic
-		if (mask & MASK_SHIFT)
-		{
-			mRootView->focusPrevRoot();
-		}
-		else
-		{
-			mRootView->focusNextRoot();
-		}
-		return TRUE;
-	}
-	// hidden edit menu for cut/copy/paste
-	if (gEditMenu && gEditMenu->handleAcceleratorKey(key, mask))
-	{
-		return TRUE;
-	}
-
-	// Traverses up the hierarchy
-	if( keyboard_focus )
-	{
-		LLNearbyChatBar* nearby_chat = LLFloaterReg::findTypedInstance<LLNearbyChatBar>("chat_bar");
-
-		if (nearby_chat)
-		{
-			LLLineEditor* chat_editor = nearby_chat->getChatBox();
-		
-		// arrow keys move avatar while chatting hack
-		if (chat_editor && chat_editor->hasFocus())
-		{
-			// If text field is empty, there's no point in trying to move
-			// cursor with arrow keys, so allow movement
-			if (chat_editor->getText().empty() 
-				|| gSavedSettings.getBOOL("ArrowKeysAlwaysMove"))
-			{
-				// let Control-Up and Control-Down through for chat line history,
-				if (!(key == KEY_UP && mask == MASK_CONTROL)
-					&& !(key == KEY_DOWN && mask == MASK_CONTROL))
-				{
-					switch(key)
-					{
-					case KEY_LEFT:
-					case KEY_RIGHT:
-					case KEY_UP:
-					case KEY_DOWN:
-					case KEY_PAGE_UP:
-					case KEY_PAGE_DOWN:
-					case KEY_HOME:
-						// when chatbar is empty or ArrowKeysAlwaysMove set,
-						// pass arrow keys on to avatar...
-						return FALSE;
-					default:
-						break;
-					}
-				}
-			}
-		}
-		}
-		if (keyboard_focus->handleKey(key, mask, FALSE))
-		{
-			return TRUE;
-		}
-	}
-
-	if( LLToolMgr::getInstance()->getCurrentTool()->handleKey(key, mask) )
-	{
-		return TRUE;
-	}
-
-	// Try for a new-format gesture
-	if (LLGestureMgr::instance().triggerGesture(key, mask))
-	{
-		return TRUE;
-	}
-
-	// See if this is a gesture trigger.  If so, eat the key and
-	// don't pass it down to the menus.
-	if (gGestureList.trigger(key, mask))
-	{
-		return TRUE;
-	}
-
-	// If "Pressing letter keys starts local chat" option is selected, we are not in mouselook, 
-	// no view has keyboard focus, this is a printable character key (and no modifier key is 
-	// pressed except shift), then give focus to nearby chat (STORM-560)
-	if ( gSavedSettings.getS32("LetterKeysFocusChatBar") && !gAgentCamera.cameraMouselook() && 
-		!keyboard_focus && key < 0x80 && (mask == MASK_NONE || mask == MASK_SHIFT) )
-	{
-		LLLineEditor* chat_editor = LLFloaterReg::getTypedInstance<LLNearbyChatBar>("chat_bar")->getChatBox();
-		if (chat_editor)
-		{
-			// passing NULL here, character will be added later when it is handled by character handler.
-			LLNearbyChatBar::getInstance()->startChat(NULL);
-			return TRUE;
-		}
-	}
-
-	// give menus a chance to handle unmodified accelerator keys
-	if ((gMenuBarView && gMenuBarView->handleAcceleratorKey(key, mask))
-		||(gLoginMenuBarView && gLoginMenuBarView->handleAcceleratorKey(key, mask)))
-	{
-		return TRUE;
-	}
-
-	// don't pass keys on to world when something in ui has focus
-	return gFocusMgr.childHasKeyboardFocus(mRootView) 
-		|| LLMenuGL::getKeyboardMode() 
-		|| (gMenuBarView && gMenuBarView->getHighlightedItem() && gMenuBarView->getHighlightedItem()->isActive());
-}
-
-
-BOOL LLViewerWindow::handleUnicodeChar(llwchar uni_char, MASK mask)
-{
-	// HACK:  We delay processing of return keys until they arrive as a Unicode char,
-	// so that if you're typing chat text at low frame rate, we don't send the chat
-	// until all keystrokes have been entered. JC
-	// HACK: Numeric keypad <enter> on Mac is Unicode 3
-	// HACK: Control-M on Windows is Unicode 13
-	if ((uni_char == 13 && mask != MASK_CONTROL)
-		|| (uni_char == 3 && mask == MASK_NONE))
-	{
-		return gViewerKeyboard.handleKey(KEY_RETURN, mask, gKeyboard->getKeyRepeated(KEY_RETURN));
-	}
-
-	// let menus handle navigation (jump) keys
-	if (gMenuBarView && gMenuBarView->handleUnicodeChar(uni_char, TRUE))
-	{
-		return TRUE;
-	}
-
-	// Traverses up the hierarchy
-	LLFocusableElement* keyboard_focus = gFocusMgr.getKeyboardFocus();
-	if( keyboard_focus )
-	{
-		if (keyboard_focus->handleUnicodeChar(uni_char, FALSE))
-		{
-			return TRUE;
-		}
-
-		//// Topmost view gets a chance before the hierarchy
-		//LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl();
-		//if (top_ctrl && top_ctrl->handleUnicodeChar( uni_char, FALSE ) )
-		//{
-		//	return TRUE;
-		//}
-
-		return TRUE;
-	}
-
-	return FALSE;
-}
-
-
-void LLViewerWindow::handleScrollWheel(S32 clicks)
-{
-	LLView::sMouseHandlerMessage.clear();
-
-	LLUI::resetMouseIdleTimer();
-	
-	LLMouseHandler* mouse_captor = gFocusMgr.getMouseCapture();
-	if( mouse_captor )
-	{
-		S32 local_x;
-		S32 local_y;
-		mouse_captor->screenPointToLocal( mCurrentMousePoint.mX, mCurrentMousePoint.mY, &local_x, &local_y );
-		mouse_captor->handleScrollWheel(local_x, local_y, clicks);
-		if (LLView::sDebugMouseHandling)
-		{
-			llinfos << "Scroll Wheel handled by captor " << mouse_captor->getName() << llendl;
-		}
-		return;
-	}
-
-	LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl();
-	if (top_ctrl)
-	{
-		S32 local_x;
-		S32 local_y;
-		top_ctrl->screenPointToLocal( mCurrentMousePoint.mX, mCurrentMousePoint.mY, &local_x, &local_y );
-		if (top_ctrl->handleScrollWheel(local_x, local_y, clicks)) return;
-	}
-
-	if (mRootView->handleScrollWheel(mCurrentMousePoint.mX, mCurrentMousePoint.mY, clicks) )
-	{
-		if (LLView::sDebugMouseHandling)
-		{
-			llinfos << "Scroll Wheel" << LLView::sMouseHandlerMessage << llendl;
-		}
-		return;
-	}
-	else if (LLView::sDebugMouseHandling)
-	{
-		llinfos << "Scroll Wheel not handled by view" << llendl;
-	}
-
-	// Zoom the camera in and out behavior
-
-	if(top_ctrl == 0 
-		&& getWorldViewRectScaled().pointInRect(mCurrentMousePoint.mX, mCurrentMousePoint.mY) 
-		&& gAgentCamera.isInitialized())
-		gAgentCamera.handleScrollWheel(clicks);
-
-	return;
-}
-
-void LLViewerWindow::addPopup(LLView* popup)
-{
-	if (mPopupView)
-	{
-		mPopupView->addPopup(popup);
-	}
-}
-
-void LLViewerWindow::removePopup(LLView* popup)
-{
-	if (mPopupView)
-	{
-		mPopupView->removePopup(popup);
-	}
-}
-
-void LLViewerWindow::clearPopups()
-{
-	if (mPopupView)
-	{
-		mPopupView->clearPopups();
-	}
-}
-
-void LLViewerWindow::moveCursorToCenter()
-{
-	if (! gSavedSettings.getBOOL("DisableMouseWarp"))
-	{
-		S32 x = getWorldViewWidthScaled() / 2;
-		S32 y = getWorldViewHeightScaled() / 2;
-	
-		//on a forced move, all deltas get zeroed out to prevent jumping
-		mCurrentMousePoint.set(x,y);
-		mLastMousePoint.set(x,y);
-		mCurrentMouseDelta.set(0,0);	
-
-		LLUI::setMousePositionScreen(x, y);	
-	}
-}
-
-
-//////////////////////////////////////////////////////////////////////
-//
-// Hover handlers
-//
-
-void append_xui_tooltip(LLView* viewp, LLToolTip::Params& params)
-{
-	if (viewp) 
-	{
-		if (!params.styled_message.empty())
-		{
-			params.styled_message.add().text("\n---------\n"); 
-		}
-		LLView::root_to_view_iterator_t end_tooltip_it = viewp->endRootToView();
-		// NOTE: we skip "root" since it is assumed
-		for (LLView::root_to_view_iterator_t tooltip_it = ++viewp->beginRootToView();
-			tooltip_it != end_tooltip_it;
-			++tooltip_it)
-		{
-			LLView* viewp = *tooltip_it;
-		
-			params.styled_message.add().text(viewp->getName());
-
-			LLPanel* panelp = dynamic_cast<LLPanel*>(viewp);
-			if (panelp && !panelp->getXMLFilename().empty())
-			{
-				params.styled_message.add()
-					.text("(" + panelp->getXMLFilename() + ")")
-					.style.color(LLColor4(0.7f, 0.7f, 1.f, 1.f));
-			}
-			params.styled_message.add().text("/");
-		}
-	}
-}
-
-// Update UI based on stored mouse position from mouse-move
-// event processing.
-void LLViewerWindow::updateUI()
-{
-	static LLFastTimer::DeclareTimer ftm("Update UI");
-	LLFastTimer t(ftm);
-
-	static std::string last_handle_msg;
-
-	if (gLoggedInTime.getStarted())
-	{
-		if (gLoggedInTime.getElapsedTimeF32() > gSavedSettings.getF32("DestinationGuideHintTimeout"))
-		{
-			LLFirstUse::notUsingDestinationGuide();
-		}
-		if (gLoggedInTime.getElapsedTimeF32() > gSavedSettings.getF32("SidePanelHintTimeout"))
-		{
-			LLFirstUse::notUsingSidePanel();
-		}
-	}
-
-	LLConsole::updateClass();
-
-	// animate layout stacks so we have up to date rect for world view
-	LLLayoutStack::updateClass();
-
-	// use full window for world view when not rendering UI
-	bool world_view_uses_full_window = gAgentCamera.cameraMouselook() || !gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI);
-	updateWorldViewRect(world_view_uses_full_window);
-
-	LLView::sMouseHandlerMessage.clear();
-
-	S32 x = mCurrentMousePoint.mX;
-	S32 y = mCurrentMousePoint.mY;
-
-	MASK	mask = gKeyboard->currentMask(TRUE);
-
-	if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_RAYCAST))
-	{
-		gDebugRaycastFaceHit = -1;
-		gDebugRaycastObject = cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE,
-											  &gDebugRaycastFaceHit,
-											  &gDebugRaycastIntersection,
-											  &gDebugRaycastTexCoord,
-											  &gDebugRaycastNormal,
-											  &gDebugRaycastBinormal,
-											  &gDebugRaycastStart,
-											  &gDebugRaycastEnd);
-	}
-
-	updateMouseDelta();
-	updateKeyboardFocus();
-
-	BOOL handled = FALSE;
-
-	BOOL handled_by_top_ctrl = FALSE;
-	LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl();
-	LLMouseHandler* mouse_captor = gFocusMgr.getMouseCapture();
-	LLView* captor_view = dynamic_cast<LLView*>(mouse_captor);
-
-	//FIXME: only include captor and captor's ancestors if mouse is truly over them --RN
-
-	//build set of views containing mouse cursor by traversing UI hierarchy and testing 
-	//screen rect against mouse cursor
-	view_handle_set_t mouse_hover_set;
-
-	// constraint mouse enter events to children of mouse captor
-	LLView* root_view = captor_view;
-
-	// if mouse captor doesn't exist or isn't a LLView
-	// then allow mouse enter events on entire UI hierarchy
-	if (!root_view)
-	{
-		root_view = mRootView;
-	}
-
-	// only update mouse hover set when UI is visible (since we shouldn't send hover events to invisible UI
-	if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
-	{
-		// include all ancestors of captor_view as automatically having mouse
-		if (captor_view)
-		{
-			LLView* captor_parent_view = captor_view->getParent();
-			while(captor_parent_view)
-			{
-				mouse_hover_set.insert(captor_parent_view->getHandle());
-				captor_parent_view = captor_parent_view->getParent();
-			}
-		}
-
-		// aggregate visible views that contain mouse cursor in display order
-		LLPopupView::popup_list_t popups = mPopupView->getCurrentPopups();
-
-		for(LLPopupView::popup_list_t::iterator popup_it = popups.begin(); popup_it != popups.end(); ++popup_it)
-		{
-			LLView* popup = popup_it->get();
-			if (popup && popup->calcScreenBoundingRect().pointInRect(x, y))
-			{
-				// iterator over contents of top_ctrl, and throw into mouse_hover_set
-				for (LLView::tree_iterator_t it = popup->beginTreeDFS();
-					it != popup->endTreeDFS();
-					++it)
-				{
-					LLView* viewp = *it;
-					if (viewp->getVisible()
-						&& viewp->calcScreenBoundingRect().pointInRect(x, y))
-					{
-						// we have a view that contains the mouse, add it to the set
-						mouse_hover_set.insert(viewp->getHandle());
-					}
-					else
-					{
-						// skip this view and all of its children
-						it.skipDescendants();
-					}
-				}
-			}
-		}
-
-		// while the top_ctrl contains the mouse cursor, only it and its descendants will receive onMouseEnter events
-		if (top_ctrl && top_ctrl->calcScreenBoundingRect().pointInRect(x, y))
-		{
-			// iterator over contents of top_ctrl, and throw into mouse_hover_set
-			for (LLView::tree_iterator_t it = top_ctrl->beginTreeDFS();
-				it != top_ctrl->endTreeDFS();
-				++it)
-			{
-				LLView* viewp = *it;
-				if (viewp->getVisible()
-					&& viewp->calcScreenBoundingRect().pointInRect(x, y))
-				{
-					// we have a view that contains the mouse, add it to the set
-					mouse_hover_set.insert(viewp->getHandle());
-				}
-				else
-				{
-					// skip this view and all of its children
-					it.skipDescendants();
-				}
-			}
-		}
-		else
-		{
-			// walk UI tree in depth-first order
-			for (LLView::tree_iterator_t it = root_view->beginTreeDFS();
-				it != root_view->endTreeDFS();
-				++it)
-			{
-				LLView* viewp = *it;
-				// calculating the screen rect involves traversing the parent, so this is less than optimal
-				if (viewp->getVisible()
-					&& viewp->calcScreenBoundingRect().pointInRect(x, y))
-				{
-
-					// if this view is mouse opaque, nothing behind it should be in mouse_hover_set
-					if (viewp->getMouseOpaque())
-					{
-						// constrain further iteration to children of this widget
-						it = viewp->beginTreeDFS();
-					}
-		
-					// we have a view that contains the mouse, add it to the set
-					mouse_hover_set.insert(viewp->getHandle());
-				}
-				else
-				{
-					// skip this view and all of its children
-					it.skipDescendants();
-				}
-			}
-		}
-	}
-
-	typedef std::vector<LLHandle<LLView> > view_handle_list_t;
-
-	// call onMouseEnter() on all views which contain the mouse cursor but did not before
-	view_handle_list_t mouse_enter_views;
-	std::set_difference(mouse_hover_set.begin(), mouse_hover_set.end(),
-						mMouseHoverViews.begin(), mMouseHoverViews.end(),
-						std::back_inserter(mouse_enter_views));
-	for (view_handle_list_t::iterator it = mouse_enter_views.begin();
-		it != mouse_enter_views.end();
-		++it)
-	{
-		LLView* viewp = it->get();
-		if (viewp)
-		{
-			LLRect view_screen_rect = viewp->calcScreenRect();
-			viewp->onMouseEnter(x - view_screen_rect.mLeft, y - view_screen_rect.mBottom, mask);
-		}
-	}
-
-	// call onMouseLeave() on all views which no longer contain the mouse cursor
-	view_handle_list_t mouse_leave_views;
-	std::set_difference(mMouseHoverViews.begin(), mMouseHoverViews.end(),
-						mouse_hover_set.begin(), mouse_hover_set.end(),
-						std::back_inserter(mouse_leave_views));
-	for (view_handle_list_t::iterator it = mouse_leave_views.begin();
-		it != mouse_leave_views.end();
-		++it)
-	{
-		LLView* viewp = it->get();
-		if (viewp)
-		{
-			LLRect view_screen_rect = viewp->calcScreenRect();
-			viewp->onMouseLeave(x - view_screen_rect.mLeft, y - view_screen_rect.mBottom, mask);
-		}
-	}
-
-	// store resulting hover set for next frame
-	swap(mMouseHoverViews, mouse_hover_set);
-
-	// only handle hover events when UI is enabled
-	if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
-	{	
-
-		if( mouse_captor )
-		{
-			// Pass hover events to object capturing mouse events.
-			S32 local_x;
-			S32 local_y; 
-			mouse_captor->screenPointToLocal( x, y, &local_x, &local_y );
-			handled = mouse_captor->handleHover(local_x, local_y, mask);
-			if (LLView::sDebugMouseHandling)
-			{
-				llinfos << "Hover handled by captor " << mouse_captor->getName() << llendl;
-			}
-
-			if( !handled )
-			{
-				lldebugst(LLERR_USER_INPUT) << "hover not handled by mouse captor" << llendl;
-			}
-		}
-		else
-		{
-			if (top_ctrl)
-			{
-				S32 local_x, local_y;
-				top_ctrl->screenPointToLocal( x, y, &local_x, &local_y );
-				handled = top_ctrl->pointInView(local_x, local_y) && top_ctrl->handleHover(local_x, local_y, mask);
-				handled_by_top_ctrl = TRUE;
-			}
-
-			if ( !handled )
-			{
-				// x and y are from last time mouse was in window
-				// mMouseInWindow tracks *actual* mouse location
-				if (mMouseInWindow && mRootView->handleHover(x, y, mask) )
-				{
-					if (LLView::sDebugMouseHandling && LLView::sMouseHandlerMessage != last_handle_msg)
-					{
-						last_handle_msg = LLView::sMouseHandlerMessage;
-						llinfos << "Hover" << LLView::sMouseHandlerMessage << llendl;
-					}
-					handled = TRUE;
-				}
-				else if (LLView::sDebugMouseHandling)
-				{
-					if (last_handle_msg != LLStringUtil::null)
-					{
-						last_handle_msg.clear();
-						llinfos << "Hover not handled by view" << llendl;
-					}
-				}
-			}
-		
-			if (!handled)
-			{
-				LLTool *tool = LLToolMgr::getInstance()->getCurrentTool();
-
-				if(mMouseInWindow && tool)
-				{
-					handled = tool->handleHover(x, y, mask);
-				}
-			}
-		}
-
-		// Show a new tool tip (or update one that is already shown)
-		BOOL tool_tip_handled = FALSE;
-		std::string tool_tip_msg;
-		if( handled 
-			&& !mWindow->isCursorHidden())
-		{
-			LLRect screen_sticky_rect = mRootView->getLocalRect();
-			S32 local_x, local_y;
-
-			if (gSavedSettings.getBOOL("DebugShowXUINames"))
-			{
-				LLToolTip::Params params;
-
-				LLView* tooltip_view = mRootView;
-				LLView::tree_iterator_t end_it = mRootView->endTreeDFS();
-				for (LLView::tree_iterator_t it = mRootView->beginTreeDFS(); it != end_it; ++it)
-				{
-					LLView* viewp = *it;
-					LLRect screen_rect;
-					viewp->localRectToScreen(viewp->getLocalRect(), &screen_rect);
-					if (!(viewp->getVisible()
-						 && screen_rect.pointInRect(x, y)))
-					{
-						it.skipDescendants();
-					}
-					// only report xui names for LLUICtrls, 
-					// and blacklist the various containers we don't care about
-					else if (dynamic_cast<LLUICtrl*>(viewp) 
-							&& viewp != gMenuHolder
-							&& viewp != gFloaterView
-							&& viewp != gConsole) 
-					{
-						if (dynamic_cast<LLFloater*>(viewp))
-						{
-							// constrain search to descendants of this (frontmost) floater
-							// by resetting iterator
-							it = viewp->beginTreeDFS();
-						}
-
-						// if we are in a new part of the tree (not a descendent of current tooltip_view)
-						// then push the results for tooltip_view and start with a new potential view
-						// NOTE: this emulates visiting only the leaf nodes that meet our criteria
-						if (!viewp->hasAncestor(tooltip_view))
-						{
-							append_xui_tooltip(tooltip_view, params);
-							screen_sticky_rect.intersectWith(tooltip_view->calcScreenRect());
-						}
-						tooltip_view = viewp;
-					}
-				}
-
-				append_xui_tooltip(tooltip_view, params);
-				screen_sticky_rect.intersectWith(tooltip_view->calcScreenRect());
-				
-				params.sticky_rect = screen_sticky_rect;
-				params.max_width = 400;
-
-				LLToolTipMgr::instance().show(params);
-			}
-			// if there is a mouse captor, nothing else gets a tooltip
-			else if (mouse_captor)
-			{
-				mouse_captor->screenPointToLocal(x, y, &local_x, &local_y);
-				tool_tip_handled = mouse_captor->handleToolTip(local_x, local_y, mask);
-			}
-			else 
-			{
-				// next is top_ctrl
-				if (!tool_tip_handled && top_ctrl)
-				{
-					top_ctrl->screenPointToLocal(x, y, &local_x, &local_y);
-					tool_tip_handled = top_ctrl->handleToolTip(local_x, local_y, mask );
-				}
-				
-				if (!tool_tip_handled)
-				{
-					local_x = x; local_y = y;
-					tool_tip_handled = mRootView->handleToolTip(local_x, local_y, mask );
-				}
-
-				LLTool* current_tool = LLToolMgr::getInstance()->getCurrentTool();
-				if (!tool_tip_handled && current_tool)
-				{
-					current_tool->screenPointToLocal(x, y, &local_x, &local_y);
-					tool_tip_handled = current_tool->handleToolTip(local_x, local_y, mask );
-				}
-			}
-		}		
-	}
-	else
-	{	// just have tools handle hover when UI is turned off
-		LLTool *tool = LLToolMgr::getInstance()->getCurrentTool();
-
-		if(mMouseInWindow && tool)
-		{
-			handled = tool->handleHover(x, y, mask);
-		}
-	}
-
-	updateLayout();
-
-	mLastMousePoint = mCurrentMousePoint;
-
-	// cleanup unused selections when no modal dialogs are open
-	if (LLModalDialog::activeCount() == 0)
-	{
-		LLViewerParcelMgr::getInstance()->deselectUnused();
-	}
-
-	if (LLModalDialog::activeCount() == 0)
-	{
-		LLSelectMgr::getInstance()->deselectUnused();
-	}
-}
-
-
-void LLViewerWindow::updateLayout()
-{
-	LLTool* tool = LLToolMgr::getInstance()->getCurrentTool();
-	if (gFloaterTools != NULL
-		&& tool != NULL
-		&& tool != gToolNull  
-		&& tool != LLToolCompInspect::getInstance() 
-		&& tool != LLToolDragAndDrop::getInstance() 
-		&& !gSavedSettings.getBOOL("FreezeTime"))
-	{ 
-		// Suppress the toolbox view if our source tool was the pie tool,
-		// and we've overridden to something else.
-		bool suppress_toolbox = 
-			(LLToolMgr::getInstance()->getBaseTool() == LLToolPie::getInstance()) &&
-			(LLToolMgr::getInstance()->getCurrentTool() != LLToolPie::getInstance());
-
-		LLMouseHandler *captor = gFocusMgr.getMouseCapture();
-		// With the null, inspect, or drag and drop tool, don't muck
-		// with visibility.
-
-		if (gFloaterTools->isMinimized()
-			||	(tool != LLToolPie::getInstance()						// not default tool
-				&& tool != LLToolCompGun::getInstance()					// not coming out of mouselook
-				&& !suppress_toolbox									// not override in third person
-				&& LLToolMgr::getInstance()->getCurrentToolset() != gFaceEditToolset	// not special mode
-				&& LLToolMgr::getInstance()->getCurrentToolset() != gMouselookToolset
-				&& (!captor || dynamic_cast<LLView*>(captor) != NULL)))						// not dragging
-		{
-			// Force floater tools to be visible (unless minimized)
-			if (!gFloaterTools->getVisible())
-			{
-				gFloaterTools->openFloater();
-			}
-			// Update the location of the blue box tool popup
-			LLCoordGL select_center_screen;
-			MASK	mask = gKeyboard->currentMask(TRUE);
-			gFloaterTools->updatePopup( select_center_screen, mask );
-		}
-		else
-		{
-			gFloaterTools->setVisible(FALSE);
-		}
-		//gMenuBarView->setItemVisible("BuildTools", gFloaterTools->getVisible());
-	}
-
-	LLFloaterBuildOptions* build_options_floater = LLFloaterReg::findTypedInstance<LLFloaterBuildOptions>("build_options");
-	if (build_options_floater && build_options_floater->getVisible())
-	{
-		build_options_floater->updateGridMode();
-	}
-
-	// Always update console
-	if(gConsole)
-	{
-		LLRect console_rect = getChatConsoleRect();
-		gConsole->reshape(console_rect.getWidth(), console_rect.getHeight());
-		gConsole->setRect(console_rect);
-	}
-}
-
-void LLViewerWindow::updateMouseDelta()
-{
-	S32 dx = lltrunc((F32) (mCurrentMousePoint.mX - mLastMousePoint.mX) * LLUI::sGLScaleFactor.mV[VX]);
-	S32 dy = lltrunc((F32) (mCurrentMousePoint.mY - mLastMousePoint.mY) * LLUI::sGLScaleFactor.mV[VY]);
-
-	//RN: fix for asynchronous notification of mouse leaving window not working
-	LLCoordWindow mouse_pos;
-	mWindow->getCursorPosition(&mouse_pos);
-	if (mouse_pos.mX < 0 || 
-		mouse_pos.mY < 0 ||
-		mouse_pos.mX > mWindowRectRaw.getWidth() ||
-		mouse_pos.mY > mWindowRectRaw.getHeight())
-	{
-		mMouseInWindow = FALSE;
-	}
-	else
-	{
-		mMouseInWindow = TRUE;
-	}
-
-	LLVector2 mouse_vel; 
-
-	if (gSavedSettings.getBOOL("MouseSmooth"))
-	{
-		static F32 fdx = 0.f;
-		static F32 fdy = 0.f;
-
-		F32 amount = 16.f;
-		fdx = fdx + ((F32) dx - fdx) * llmin(gFrameIntervalSeconds*amount,1.f);
-		fdy = fdy + ((F32) dy - fdy) * llmin(gFrameIntervalSeconds*amount,1.f);
-
-		mCurrentMouseDelta.set(llround(fdx), llround(fdy));
-		mouse_vel.setVec(fdx,fdy);
-	}
-	else
-	{
-		mCurrentMouseDelta.set(dx, dy);
-		mouse_vel.setVec((F32) dx, (F32) dy);
-	}
-    
-	mMouseVelocityStat.addValue(mouse_vel.magVec());
-}
-
-void LLViewerWindow::updateKeyboardFocus()
-{
-	if (!gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
-	{
-		gFocusMgr.setKeyboardFocus(NULL);
-	}
-
-	// clean up current focus
-	LLUICtrl* cur_focus = dynamic_cast<LLUICtrl*>(gFocusMgr.getKeyboardFocus());
-	if (cur_focus)
-	{
-		if (!cur_focus->isInVisibleChain() || !cur_focus->isInEnabledChain())
-		{
-            // don't release focus, just reassign so that if being given
-            // to a sibling won't call onFocusLost on all the ancestors
-			// gFocusMgr.releaseFocusIfNeeded(cur_focus);
-
-			LLUICtrl* parent = cur_focus->getParentUICtrl();
-			const LLUICtrl* focus_root = cur_focus->findRootMostFocusRoot();
-			bool new_focus_found = false;
-			while(parent)
-			{
-				if (parent->isCtrl() 
-					&& (parent->hasTabStop() || parent == focus_root) 
-					&& !parent->getIsChrome() 
-					&& parent->isInVisibleChain() 
-					&& parent->isInEnabledChain())
-				{
-					if (!parent->focusFirstItem())
-					{
-						parent->setFocus(TRUE);
-					}
-					new_focus_found = true;
-					break;
-				}
-				parent = parent->getParentUICtrl();
-			}
-
-			// if we didn't find a better place to put focus, just release it
-			// hasFocus() will return true if and only if we didn't touch focus since we
-			// are only moving focus higher in the hierarchy
-			if (!new_focus_found)
-			{
-				cur_focus->setFocus(FALSE);
-			}
-		}
-		else if (cur_focus->isFocusRoot())
-		{
-			// focus roots keep trying to delegate focus to their first valid descendant
-			// this assumes that focus roots are not valid focus holders on their own
-			cur_focus->focusFirstItem();
-		}
-	}
-
-	// last ditch force of edit menu to selection manager
-	if (LLEditMenuHandler::gEditMenuHandler == NULL && LLSelectMgr::getInstance()->getSelection()->getObjectCount())
-	{
-		LLEditMenuHandler::gEditMenuHandler = LLSelectMgr::getInstance();
-	}
-
-	if (gFloaterView->getCycleMode())
-	{
-		// sync all floaters with their focus state
-		gFloaterView->highlightFocusedFloater();
-		gSnapshotFloaterView->highlightFocusedFloater();
-		MASK	mask = gKeyboard->currentMask(TRUE);
-		if ((mask & MASK_CONTROL) == 0)
-		{
-			// control key no longer held down, finish cycle mode
-			gFloaterView->setCycleMode(FALSE);
-
-			gFloaterView->syncFloaterTabOrder();
-		}
-		else
-		{
-			// user holding down CTRL, don't update tab order of floaters
-		}
-	}
-	else
-	{
-		// update focused floater
-		gFloaterView->highlightFocusedFloater();
-		gSnapshotFloaterView->highlightFocusedFloater();
-		// make sure floater visible order is in sync with tab order
-		gFloaterView->syncFloaterTabOrder();
-	}
-}
-
-static LLFastTimer::DeclareTimer FTM_UPDATE_WORLD_VIEW("Update World View");
-void LLViewerWindow::updateWorldViewRect(bool use_full_window)
-{
-	LLFastTimer ft(FTM_UPDATE_WORLD_VIEW);
-
-	// start off using whole window to render world
-	LLRect new_world_rect = mWindowRectRaw;
-
-	if (use_full_window == false && mWorldViewPlaceholder.get())
-	{
-		new_world_rect = mWorldViewPlaceholder.get()->calcScreenRect();
-		// clamp to at least a 1x1 rect so we don't try to allocate zero width gl buffers
-		new_world_rect.mTop = llmax(new_world_rect.mTop, new_world_rect.mBottom + 1);
-		new_world_rect.mRight = llmax(new_world_rect.mRight, new_world_rect.mLeft + 1);
-
-		new_world_rect.mLeft = llround((F32)new_world_rect.mLeft * mDisplayScale.mV[VX]);
-		new_world_rect.mRight = llround((F32)new_world_rect.mRight * mDisplayScale.mV[VX]);
-		new_world_rect.mBottom = llround((F32)new_world_rect.mBottom * mDisplayScale.mV[VY]);
-		new_world_rect.mTop = llround((F32)new_world_rect.mTop * mDisplayScale.mV[VY]);
-	}
-
-	if (mWorldViewRectRaw != new_world_rect)
-	{
-		mWorldViewRectRaw = new_world_rect;
-		gResizeScreenTexture = TRUE;
-		LLViewerCamera::getInstance()->setViewHeightInPixels( mWorldViewRectRaw.getHeight() );
-		LLViewerCamera::getInstance()->setAspect( getWorldViewAspectRatio() );
-
-		LLRect old_world_rect_scaled = mWorldViewRectScaled;
-		mWorldViewRectScaled = calcScaledRect(mWorldViewRectRaw, mDisplayScale);
-
-		// sending a signal with a new WorldView rect
-		mOnWorldViewRectUpdated(old_world_rect_scaled, mWorldViewRectScaled);
-	}
-}
-
-void LLViewerWindow::saveLastMouse(const LLCoordGL &point)
-{
-	// Store last mouse location.
-	// If mouse leaves window, pretend last point was on edge of window
-	if (point.mX < 0)
-	{
-		mCurrentMousePoint.mX = 0;
-	}
-	else if (point.mX > getWindowWidthScaled())
-	{
-		mCurrentMousePoint.mX = getWindowWidthScaled();
-	}
-	else
-	{
-		mCurrentMousePoint.mX = point.mX;
-	}
-
-	if (point.mY < 0)
-	{
-		mCurrentMousePoint.mY = 0;
-	}
-	else if (point.mY > getWindowHeightScaled() )
-	{
-		mCurrentMousePoint.mY = getWindowHeightScaled();
-	}
-	else
-	{
-		mCurrentMousePoint.mY = point.mY;
-	}
-}
-
-
-// Draws the selection outlines for the currently selected objects
-// Must be called after displayObjects is called, which sets the mGLName parameter
-// NOTE: This function gets called 3 times:
-//  render_ui_3d: 			FALSE, FALSE, TRUE
-//  render_hud_elements:	FALSE, FALSE, FALSE
-void LLViewerWindow::renderSelections( BOOL for_gl_pick, BOOL pick_parcel_walls, BOOL for_hud )
-{
-	LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
-
-	if (!for_hud && !for_gl_pick)
-	{
-		// Call this once and only once
-		LLSelectMgr::getInstance()->updateSilhouettes();
-	}
-	
-	// Draw fence around land selections
-	if (for_gl_pick)
-	{
-		if (pick_parcel_walls)
-		{
-			LLViewerParcelMgr::getInstance()->renderParcelCollision();
-		}
-	}
-	else if (( for_hud && selection->getSelectType() == SELECT_TYPE_HUD) ||
-			 (!for_hud && selection->getSelectType() != SELECT_TYPE_HUD))
-	{		
-		LLSelectMgr::getInstance()->renderSilhouettes(for_hud);
-		
-		stop_glerror();
-
-		// setup HUD render
-		if (selection->getSelectType() == SELECT_TYPE_HUD && LLSelectMgr::getInstance()->getSelection()->getObjectCount())
-		{
-			LLBBox hud_bbox = gAgentAvatarp->getHUDBBox();
-
-			// set up transform to encompass bounding box of HUD
-			gGL.matrixMode(LLRender::MM_PROJECTION);
-			gGL.pushMatrix();
-			gGL.loadIdentity();
-			F32 depth = llmax(1.f, hud_bbox.getExtentLocal().mV[VX] * 1.1f);
-			gGL.ortho(-0.5f * LLViewerCamera::getInstance()->getAspect(), 0.5f * LLViewerCamera::getInstance()->getAspect(), -0.5f, 0.5f, 0.f, depth);
-			
-			gGL.matrixMode(LLRender::MM_MODELVIEW);
-			gGL.pushMatrix();
-			gGL.loadIdentity();
-			gGL.loadMatrix(OGL_TO_CFR_ROTATION);		// Load Cory's favorite reference frame
-			gGL.translatef(-hud_bbox.getCenterLocal().mV[VX] + (depth *0.5f), 0.f, 0.f);
-		}
-
-		// Render light for editing
-		if (LLSelectMgr::sRenderLightRadius && LLToolMgr::getInstance()->inEdit())
-		{
-			gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-			LLGLEnable gls_blend(GL_BLEND);
-			LLGLEnable gls_cull(GL_CULL_FACE);
-			LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
-			gGL.matrixMode(LLRender::MM_MODELVIEW);
-			gGL.pushMatrix();
-			if (selection->getSelectType() == SELECT_TYPE_HUD)
-			{
-				F32 zoom = gAgentCamera.mHUDCurZoom;
-				gGL.scalef(zoom, zoom, zoom);
-			}
-
-			struct f : public LLSelectedObjectFunctor
-			{
-				virtual bool apply(LLViewerObject* object)
-				{
-					LLDrawable* drawable = object->mDrawable;
-					if (drawable && drawable->isLight())
-					{
-						LLVOVolume* vovolume = drawable->getVOVolume();
-						gGL.pushMatrix();
-
-						LLVector3 center = drawable->getPositionAgent();
-						gGL.translatef(center[0], center[1], center[2]);
-						F32 scale = vovolume->getLightRadius();
-						gGL.scalef(scale, scale, scale);
-
-						LLColor4 color(vovolume->getLightColor(), .5f);
-						gGL.color4fv(color.mV);
-					
-						//F32 pixel_area = 100000.f;
-						// Render Outside
-						gSphere.render();
-
-						// Render Inside
-						glCullFace(GL_FRONT);
-						gSphere.render();
-						glCullFace(GL_BACK);
-					
-						gGL.popMatrix();
-					}
-					return true;
-				}
-			} func;
-			LLSelectMgr::getInstance()->getSelection()->applyToObjects(&func);
-			
-			gGL.popMatrix();
-		}				
-		
-		// NOTE: The average position for the axis arrows of the selected objects should
-		// not be recalculated at this time.  If they are, then group rotations will break.
-
-		// Draw arrows at average center of all selected objects
-		LLTool* tool = LLToolMgr::getInstance()->getCurrentTool();
-		if (tool)
-		{
-			if(tool->isAlwaysRendered())
-			{
-				tool->render();
-			}
-			else
-			{
-				if( !LLSelectMgr::getInstance()->getSelection()->isEmpty() )
-				{
-					BOOL moveable_object_selected = FALSE;
-					BOOL all_selected_objects_move = TRUE;
-					BOOL all_selected_objects_modify = TRUE;
-					BOOL selecting_linked_set = !gSavedSettings.getBOOL("EditLinkedParts");
-
-					for (LLObjectSelection::iterator iter = LLSelectMgr::getInstance()->getSelection()->begin();
-						 iter != LLSelectMgr::getInstance()->getSelection()->end(); iter++)
-					{
-						LLSelectNode* nodep = *iter;
-						LLViewerObject* object = nodep->getObject();
-						BOOL this_object_movable = FALSE;
-						if (object->permMove() && (object->permModify() || selecting_linked_set))
-						{
-							moveable_object_selected = TRUE;
-							this_object_movable = TRUE;
-						}
-						all_selected_objects_move = all_selected_objects_move && this_object_movable;
-						all_selected_objects_modify = all_selected_objects_modify && object->permModify();
-					}
-
-					BOOL draw_handles = TRUE;
-
-					if (tool == LLToolCompTranslate::getInstance() && (!moveable_object_selected || !all_selected_objects_move))
-					{
-						draw_handles = FALSE;
-					}
-
-					if (tool == LLToolCompRotate::getInstance() && (!moveable_object_selected || !all_selected_objects_move))
-					{
-						draw_handles = FALSE;
-					}
-
-					if ( !all_selected_objects_modify && tool == LLToolCompScale::getInstance() )
-					{
-						draw_handles = FALSE;
-					}
-				
-					if( draw_handles )
-					{
-						tool->render();
-					}
-				}
-			}
-			if (selection->getSelectType() == SELECT_TYPE_HUD && selection->getObjectCount())
-			{
-				gGL.matrixMode(LLRender::MM_PROJECTION);
-				gGL.popMatrix();
-
-				gGL.matrixMode(LLRender::MM_MODELVIEW);
-				gGL.popMatrix();
-				stop_glerror();
-			}
-		}
-	}
-}
-
-// Return a point near the clicked object representative of the place the object was clicked.
-LLVector3d LLViewerWindow::clickPointInWorldGlobal(S32 x, S32 y_from_bot, LLViewerObject* clicked_object) const
-{
-	// create a normalized vector pointing from the camera center into the 
-	// world at the location of the mouse click
-	LLVector3 mouse_direction_global = mouseDirectionGlobal( x, y_from_bot );
-
-	LLVector3d relative_object = clicked_object->getPositionGlobal() - gAgentCamera.getCameraPositionGlobal();
-
-	// make mouse vector as long as object vector, so it touchs a point near
-	// where the user clicked on the object
-	mouse_direction_global *= (F32) relative_object.magVec();
-
-	LLVector3d new_pos;
-	new_pos.setVec(mouse_direction_global);
-	// transform mouse vector back to world coords
-	new_pos += gAgentCamera.getCameraPositionGlobal();
-
-	return new_pos;
-}
-
-
-BOOL LLViewerWindow::clickPointOnSurfaceGlobal(const S32 x, const S32 y, LLViewerObject *objectp, LLVector3d &point_global) const
-{
-	BOOL intersect = FALSE;
-
-//	U8 shape = objectp->mPrimitiveCode & LL_PCODE_BASE_MASK;
-	if (!intersect)
-	{
-		point_global = clickPointInWorldGlobal(x, y, objectp);
-		llinfos << "approx intersection at " <<  (objectp->getPositionGlobal() - point_global) << llendl;
-	}
-	else
-	{
-		llinfos << "good intersection at " <<  (objectp->getPositionGlobal() - point_global) << llendl;
-	}
-
-	return intersect;
-}
-
-void LLViewerWindow::pickAsync(S32 x, S32 y_from_bot, MASK mask, void (*callback)(const LLPickInfo& info), BOOL pick_transparent)
-{
-	BOOL in_build_mode = LLFloaterReg::instanceVisible("build");
-	if (in_build_mode || LLDrawPoolAlpha::sShowDebugAlpha)
-	{
-		// build mode allows interaction with all transparent objects
-		// "Show Debug Alpha" means no object actually transparent
-		pick_transparent = TRUE;
-	}
-
-	LLPickInfo pick_info(LLCoordGL(x, y_from_bot), mask, pick_transparent, TRUE, callback);
-	schedulePick(pick_info);
-}
-
-void LLViewerWindow::schedulePick(LLPickInfo& pick_info)
-{
-	if (mPicks.size() >= 1024 || mWindow->getMinimized())
-	{ //something went wrong, picks are being scheduled but not processed
-		
-		if (pick_info.mPickCallback)
-		{
-			pick_info.mPickCallback(pick_info);
-		}
-	
-		return;
-	}
-	mPicks.push_back(pick_info);
-	
-	// delay further event processing until we receive results of pick
-	// only do this for async picks so that handleMouseUp won't be called
-	// until the pick triggered in handleMouseDown has been processed, for example
-	mWindow->delayInputProcessing();
-}
-
-
-void LLViewerWindow::performPick()
-{
-	if (!mPicks.empty())
-	{
-		std::vector<LLPickInfo>::iterator pick_it;
-		for (pick_it = mPicks.begin(); pick_it != mPicks.end(); ++pick_it)
-		{
-			pick_it->fetchResults();
-		}
-
-		mLastPick = mPicks.back();
-		mPicks.clear();
-	}
-}
-
-void LLViewerWindow::returnEmptyPicks()
-{
-	std::vector<LLPickInfo>::iterator pick_it;
-	for (pick_it = mPicks.begin(); pick_it != mPicks.end(); ++pick_it)
-	{
-		mLastPick = *pick_it;
-		// just trigger callback with empty results
-		if (pick_it->mPickCallback)
-		{
-			pick_it->mPickCallback(*pick_it);
-		}
-	}
-	mPicks.clear();
-}
-
-// Performs the GL object/land pick.
-LLPickInfo LLViewerWindow::pickImmediate(S32 x, S32 y_from_bot,  BOOL pick_transparent)
-{
-	BOOL in_build_mode = LLFloaterReg::instanceVisible("build");
-	if (in_build_mode || LLDrawPoolAlpha::sShowDebugAlpha)
-	{
-		// build mode allows interaction with all transparent objects
-		// "Show Debug Alpha" means no object actually transparent
-		pick_transparent = TRUE;
-	}
-
-	// shortcut queueing in mPicks and just update mLastPick in place
-	MASK	key_mask = gKeyboard->currentMask(TRUE);
-	mLastPick = LLPickInfo(LLCoordGL(x, y_from_bot), key_mask, pick_transparent, TRUE, NULL);
-	mLastPick.fetchResults();
-
-	return mLastPick;
-}
-
-LLHUDIcon* LLViewerWindow::cursorIntersectIcon(S32 mouse_x, S32 mouse_y, F32 depth,
-										   LLVector3* intersection)
-{
-	S32 x = mouse_x;
-	S32 y = mouse_y;
-
-	if ((mouse_x == -1) && (mouse_y == -1)) // use current mouse position
-	{
-		x = getCurrentMouseX();
-		y = getCurrentMouseY();
-	}
-
-	// world coordinates of mouse
-	LLVector3 mouse_direction_global = mouseDirectionGlobal(x,y);
-	LLVector3 mouse_point_global = LLViewerCamera::getInstance()->getOrigin();
-	LLVector3 mouse_world_start = mouse_point_global;
-	LLVector3 mouse_world_end   = mouse_point_global + mouse_direction_global * depth;
-
-	return LLHUDIcon::lineSegmentIntersectAll(mouse_world_start, mouse_world_end, intersection);
-
-	
-}
-
-LLViewerObject* LLViewerWindow::cursorIntersect(S32 mouse_x, S32 mouse_y, F32 depth,
-												LLViewerObject *this_object,
-												S32 this_face,
-												BOOL pick_transparent,
-												S32* face_hit,
-												LLVector3 *intersection,
-												LLVector2 *uv,
-												LLVector3 *normal,
-												LLVector3 *binormal,
-												LLVector3* start,
-												LLVector3* end)
-{
-	S32 x = mouse_x;
-	S32 y = mouse_y;
-
-	if ((mouse_x == -1) && (mouse_y == -1)) // use current mouse position
-	{
-		x = getCurrentMouseX();
-		y = getCurrentMouseY();
-	}
-
-	// HUD coordinates of mouse
-	LLVector3 mouse_point_hud = mousePointHUD(x, y);
-	LLVector3 mouse_hud_start = mouse_point_hud - LLVector3(depth, 0, 0);
-	LLVector3 mouse_hud_end   = mouse_point_hud + LLVector3(depth, 0, 0);
-	
-	// world coordinates of mouse
-	LLVector3 mouse_direction_global = mouseDirectionGlobal(x,y);
-	LLVector3 mouse_point_global = LLViewerCamera::getInstance()->getOrigin();
-	
-	//get near clip plane
-	LLVector3 n = LLViewerCamera::getInstance()->getAtAxis();
-	LLVector3 p = mouse_point_global + n * LLViewerCamera::getInstance()->getNear();
-
-	//project mouse point onto plane
-	LLVector3 pos;
-	line_plane(mouse_point_global, mouse_direction_global, p, n, pos);
-	mouse_point_global = pos;
-
-	LLVector3 mouse_world_start = mouse_point_global;
-	LLVector3 mouse_world_end   = mouse_point_global + mouse_direction_global * depth;
-
-	if (!LLViewerJoystick::getInstance()->getOverrideCamera())
-	{ //always set raycast intersection to mouse_world_end unless
-		//flycam is on (for DoF effect)
-		gDebugRaycastIntersection = mouse_world_end;
-	}
-
-	if (start)
-	{
-		*start = mouse_world_start;
-	}
-
-	if (end)
-	{
-		*end = mouse_world_end;
-	}
-
-	LLViewerObject* found = NULL;
-
-	if (this_object)  // check only this object
-	{
-		if (this_object->isHUDAttachment()) // is a HUD object?
-		{
-			if (this_object->lineSegmentIntersect(mouse_hud_start, mouse_hud_end, this_face, pick_transparent,
-												  face_hit, intersection, uv, normal, binormal))
-			{
-				found = this_object;
-			}
-		}
-		else // is a world object
-		{
-			if (this_object->lineSegmentIntersect(mouse_world_start, mouse_world_end, this_face, pick_transparent,
-												  face_hit, intersection, uv, normal, binormal))
-			{
-				found = this_object;
-			}
-		}
-	}
-	else // check ALL objects
-	{
-		found = gPipeline.lineSegmentIntersectInHUD(mouse_hud_start, mouse_hud_end, pick_transparent,
-													face_hit, intersection, uv, normal, binormal);
-
-		if (!found) // if not found in HUD, look in world:
-		{
-			found = gPipeline.lineSegmentIntersectInWorld(mouse_world_start, mouse_world_end, pick_transparent,
-														  face_hit, intersection, uv, normal, binormal);
-			if (found && !pick_transparent)
-			{
-				gDebugRaycastIntersection = *intersection;
-			}
-		}
-	}
-
-	return found;
-}
-
-// Returns unit vector relative to camera
-// indicating direction of point on screen x,y
-LLVector3 LLViewerWindow::mouseDirectionGlobal(const S32 x, const S32 y) const
-{
-	// find vertical field of view
-	F32			fov = LLViewerCamera::getInstance()->getView();
-
-	// find world view center in scaled ui coordinates
-	F32			center_x = getWorldViewRectScaled().getCenterX();
-	F32			center_y = getWorldViewRectScaled().getCenterY();
-
-	// calculate pixel distance to screen
-	F32			distance = ((F32)getWorldViewHeightScaled() * 0.5f) / (tan(fov / 2.f));
-
-	// calculate click point relative to middle of screen
-	F32			click_x = x - center_x;
-	F32			click_y = y - center_y;
-
-	// compute mouse vector
-	LLVector3	mouse_vector =	distance * LLViewerCamera::getInstance()->getAtAxis()
-								- click_x * LLViewerCamera::getInstance()->getLeftAxis()
-								+ click_y * LLViewerCamera::getInstance()->getUpAxis();
-
-	mouse_vector.normVec();
-
-	return mouse_vector;
-}
-
-LLVector3 LLViewerWindow::mousePointHUD(const S32 x, const S32 y) const
-{
-	// find screen resolution
-	S32			height = getWorldViewHeightScaled();
-
-	// find world view center
-	F32			center_x = getWorldViewRectScaled().getCenterX();
-	F32			center_y = getWorldViewRectScaled().getCenterY();
-
-	// remap with uniform scale (1/height) so that top is -0.5, bottom is +0.5
-	F32 hud_x = -((F32)x - center_x)  / height;
-	F32 hud_y = ((F32)y - center_y) / height;
-
-	return LLVector3(0.f, hud_x/gAgentCamera.mHUDCurZoom, hud_y/gAgentCamera.mHUDCurZoom);
-}
-
-// Returns unit vector relative to camera in camera space
-// indicating direction of point on screen x,y
-LLVector3 LLViewerWindow::mouseDirectionCamera(const S32 x, const S32 y) const
-{
-	// find vertical field of view
-	F32			fov_height = LLViewerCamera::getInstance()->getView();
-	F32			fov_width = fov_height * LLViewerCamera::getInstance()->getAspect();
-
-	// find screen resolution
-	S32			height = getWorldViewHeightScaled();
-	S32			width = getWorldViewWidthScaled();
-
-	// find world view center
-	F32			center_x = getWorldViewRectScaled().getCenterX();
-	F32			center_y = getWorldViewRectScaled().getCenterY();
-
-	// calculate click point relative to middle of screen
-	F32			click_x = (((F32)x - center_x) / (F32)width) * fov_width * -1.f;
-	F32			click_y = (((F32)y - center_y) / (F32)height) * fov_height;
-
-	// compute mouse vector
-	LLVector3	mouse_vector =	LLVector3(0.f, 0.f, -1.f);
-	LLQuaternion mouse_rotate;
-	mouse_rotate.setQuat(click_y, click_x, 0.f);
-
-	mouse_vector = mouse_vector * mouse_rotate;
-	// project to z = -1 plane;
-	mouse_vector = mouse_vector * (-1.f / mouse_vector.mV[VZ]);
-
-	return mouse_vector;
-}
-
-
-
-BOOL LLViewerWindow::mousePointOnPlaneGlobal(LLVector3d& point, const S32 x, const S32 y, 
-										const LLVector3d &plane_point_global, 
-										const LLVector3 &plane_normal_global)
-{
-	LLVector3d	mouse_direction_global_d;
-
-	mouse_direction_global_d.setVec(mouseDirectionGlobal(x,y));
-	LLVector3d	plane_normal_global_d;
-	plane_normal_global_d.setVec(plane_normal_global);
-	F64 plane_mouse_dot = (plane_normal_global_d * mouse_direction_global_d);
-	LLVector3d plane_origin_camera_rel = plane_point_global - gAgentCamera.getCameraPositionGlobal();
-	F64	mouse_look_at_scale = (plane_normal_global_d * plane_origin_camera_rel)
-								/ plane_mouse_dot;
-	if (llabs(plane_mouse_dot) < 0.00001)
-	{
-		// if mouse is parallel to plane, return closest point on line through plane origin
-		// that is parallel to camera plane by scaling mouse direction vector
-		// by distance to plane origin, modulated by deviation of mouse direction from plane origin
-		LLVector3d plane_origin_dir = plane_origin_camera_rel;
-		plane_origin_dir.normVec();
-		
-		mouse_look_at_scale = plane_origin_camera_rel.magVec() / (plane_origin_dir * mouse_direction_global_d);
-	}
-
-	point = gAgentCamera.getCameraPositionGlobal() + mouse_look_at_scale * mouse_direction_global_d;
-
-	return mouse_look_at_scale > 0.0;
-}
-
-
-// Returns global position
-BOOL LLViewerWindow::mousePointOnLandGlobal(const S32 x, const S32 y, LLVector3d *land_position_global)
-{
-	LLVector3		mouse_direction_global = mouseDirectionGlobal(x,y);
-	F32				mouse_dir_scale;
-	BOOL			hit_land = FALSE;
-	LLViewerRegion	*regionp;
-	F32			land_z;
-	const F32	FIRST_PASS_STEP = 1.0f;		// meters
-	const F32	SECOND_PASS_STEP = 0.1f;	// meters
-	LLVector3d	camera_pos_global;
-
-	camera_pos_global = gAgentCamera.getCameraPositionGlobal();
-	LLVector3d		probe_point_global;
-	LLVector3		probe_point_region;
-
-	// walk forwards to find the point
-	for (mouse_dir_scale = FIRST_PASS_STEP; mouse_dir_scale < gAgentCamera.mDrawDistance; mouse_dir_scale += FIRST_PASS_STEP)
-	{
-		LLVector3d mouse_direction_global_d;
-		mouse_direction_global_d.setVec(mouse_direction_global * mouse_dir_scale);
-		probe_point_global = camera_pos_global + mouse_direction_global_d;
-
-		regionp = LLWorld::getInstance()->resolveRegionGlobal(probe_point_region, probe_point_global);
-
-		if (!regionp)
-		{
-			// ...we're outside the world somehow
-			continue;
-		}
-
-		S32 i = (S32) (probe_point_region.mV[VX]/regionp->getLand().getMetersPerGrid());
-		S32 j = (S32) (probe_point_region.mV[VY]/regionp->getLand().getMetersPerGrid());
-		S32 grids_per_edge = (S32) regionp->getLand().mGridsPerEdge;
-		if ((i >= grids_per_edge) || (j >= grids_per_edge))
-		{
-			//llinfos << "LLViewerWindow::mousePointOnLand probe_point is out of region" << llendl;
-			continue;
-		}
-
-		land_z = regionp->getLand().resolveHeightRegion(probe_point_region);
-
-		//llinfos << "mousePointOnLand initial z " << land_z << llendl;
-
-		if (probe_point_region.mV[VZ] < land_z)
-		{
-			// ...just went under land
-
-			// cout << "under land at " << probe_point << " scale " << mouse_vec_scale << endl;
-
-			hit_land = TRUE;
-			break;
-		}
-	}
-
-
-	if (hit_land)
-	{
-		// Don't go more than one step beyond where we stopped above.
-		// This can't just be "mouse_vec_scale" because floating point error
-		// will stop the loop before the last increment.... X - 1.0 + 0.1 + 0.1 + ... + 0.1 != X
-		F32 stop_mouse_dir_scale = mouse_dir_scale + FIRST_PASS_STEP;
-
-		// take a step backwards, then walk forwards again to refine position
-		for ( mouse_dir_scale -= FIRST_PASS_STEP; mouse_dir_scale <= stop_mouse_dir_scale; mouse_dir_scale += SECOND_PASS_STEP)
-		{
-			LLVector3d mouse_direction_global_d;
-			mouse_direction_global_d.setVec(mouse_direction_global * mouse_dir_scale);
-			probe_point_global = camera_pos_global + mouse_direction_global_d;
-
-			regionp = LLWorld::getInstance()->resolveRegionGlobal(probe_point_region, probe_point_global);
-
-			if (!regionp)
-			{
-				// ...we're outside the world somehow
-				continue;
-			}
-
-			/*
-			i = (S32) (local_probe_point.mV[VX]/regionp->getLand().getMetersPerGrid());
-			j = (S32) (local_probe_point.mV[VY]/regionp->getLand().getMetersPerGrid());
-			if ((i >= regionp->getLand().mGridsPerEdge) || (j >= regionp->getLand().mGridsPerEdge))
-			{
-				// llinfos << "LLViewerWindow::mousePointOnLand probe_point is out of region" << llendl;
-				continue;
-			}
-			land_z = regionp->getLand().mSurfaceZ[ i + j * (regionp->getLand().mGridsPerEdge) ];
-			*/
-
-			land_z = regionp->getLand().resolveHeightRegion(probe_point_region);
-
-			//llinfos << "mousePointOnLand refine z " << land_z << llendl;
-
-			if (probe_point_region.mV[VZ] < land_z)
-			{
-				// ...just went under land again
-
-				*land_position_global = probe_point_global;
-				return TRUE;
-			}
-		}
-	}
-
-	return FALSE;
-}
-
-// Saves an image to the harddrive as "SnapshotX" where X >= 1.
-BOOL LLViewerWindow::saveImageNumbered(LLImageFormatted *image, bool force_picker)
-{
-	if (!image)
-	{
-		llwarns << "No image to save" << llendl;
-		return FALSE;
-	}
-
-	LLFilePicker::ESaveFilter pick_type;
-	std::string extension("." + image->getExtension());
-	if (extension == ".j2c")
-		pick_type = LLFilePicker::FFSAVE_J2C;
-	else if (extension == ".bmp")
-		pick_type = LLFilePicker::FFSAVE_BMP;
-	else if (extension == ".jpg")
-		pick_type = LLFilePicker::FFSAVE_JPEG;
-	else if (extension == ".png")
-		pick_type = LLFilePicker::FFSAVE_PNG;
-	else if (extension == ".tga")
-		pick_type = LLFilePicker::FFSAVE_TGA;
-	else
-		pick_type = LLFilePicker::FFSAVE_ALL; // ???
-	
-	// Get a base file location if needed.
-	if (force_picker || !isSnapshotLocSet())
-	{
-		std::string proposed_name( sSnapshotBaseName );
-
-		// getSaveFile will append an appropriate extension to the proposed name, based on the ESaveFilter constant passed in.
-
-		// pick a directory in which to save
-		LLFilePicker& picker = LLFilePicker::instance();
-		if (!picker.getSaveFile(pick_type, proposed_name))
-		{
-			// Clicked cancel
-			return FALSE;
-		}
-
-		// Copy the directory + file name
-		std::string filepath = picker.getFirstFile();
-
-		LLViewerWindow::sSnapshotBaseName = gDirUtilp->getBaseFileName(filepath, true);
-		LLViewerWindow::sSnapshotDir = gDirUtilp->getDirName(filepath);
-	}
-
-	// Look for an unused file name
-	std::string filepath;
-	S32 i = 1;
-	S32 err = 0;
-
-	do
-	{
-		filepath = sSnapshotDir;
-		filepath += gDirUtilp->getDirDelimiter();
-		filepath += sSnapshotBaseName;
-		filepath += llformat("_%.3d",i);
-		filepath += extension;
-
-		llstat stat_info;
-		err = LLFile::stat( filepath, &stat_info );
-		i++;
-	}
-	while( -1 != err );  // search until the file is not found (i.e., stat() gives an error).
-
-	llinfos << "Saving snapshot to " << filepath << llendl;
-	return image->save(filepath);
-}
-
-void LLViewerWindow::resetSnapshotLoc()
-{
-	sSnapshotDir.clear();
-}
-
-// static
-void LLViewerWindow::movieSize(S32 new_width, S32 new_height)
-{
-	LLCoordWindow size;
-	gViewerWindow->getWindow()->getSize(&size);
-	if ( size.mX != new_width
-		|| size.mY != new_height)
-	{
-		LLCoordWindow new_size(new_width, new_height);
-		LLCoordScreen screen_size;
-		gViewerWindow->getWindow()->convertCoords(new_size, &screen_size);
-		gViewerWindow->getWindow()->setSize(screen_size);
-	}
-}
-
-BOOL LLViewerWindow::saveSnapshot( const std::string& filepath, S32 image_width, S32 image_height, BOOL show_ui, BOOL do_rebuild, ESnapshotType type)
-{
-	llinfos << "Saving snapshot to: " << filepath << llendl;
-
-	LLPointer<LLImageRaw> raw = new LLImageRaw;
-	BOOL success = rawSnapshot(raw, image_width, image_height, TRUE, FALSE, show_ui, do_rebuild);
-
-	if (success)
-	{
-		LLPointer<LLImageBMP> bmp_image = new LLImageBMP;
-		success = bmp_image->encode(raw, 0.0f);
-		if( success )
-		{
-			success = bmp_image->save(filepath);
-		}
-		else
-		{
-			llwarns << "Unable to encode bmp snapshot" << llendl;
-		}
-	}
-	else
-	{
-		llwarns << "Unable to capture raw snapshot" << llendl;
-	}
-
-	return success;
-}
-
-
-void LLViewerWindow::playSnapshotAnimAndSound()
-{
-	if (gSavedSettings.getBOOL("QuietSnapshotsToDisk"))
-	{
-		return;
-	}
-	gAgent.sendAnimationRequest(ANIM_AGENT_SNAPSHOT, ANIM_REQUEST_START);
-	send_sound_trigger(LLUUID(gSavedSettings.getString("UISndSnapshot")), 1.0f);
-}
-
-BOOL LLViewerWindow::thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 preview_height, BOOL show_ui, BOOL do_rebuild, ESnapshotType type)
-{
-	return rawSnapshot(raw, preview_width, preview_height, FALSE, FALSE, show_ui, do_rebuild, type);
-}
-
-// Saves the image from the screen to a raw image
-// Since the required size might be bigger than the available screen, this method rerenders the scene in parts (called subimages) and copy
-// the results over to the final raw image.
-BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_height, 
-								 BOOL keep_window_aspect, BOOL is_texture, BOOL show_ui, BOOL do_rebuild, ESnapshotType type, S32 max_size)
-{
-	if (!raw)
-	{
-		return FALSE;
-	}
-	//check if there is enough memory for the snapshot image
-	if(LLPipeline::sMemAllocationThrottled)
-	{
-		return FALSE ; //snapshot taking is disabled due to memory restriction.
-	}
-	if(image_width * image_height > (1 << 22)) //if snapshot image is larger than 2K by 2K
-	{
-		if(!LLMemory::tryToAlloc(NULL, image_width * image_height * 3))
-		{
-			llwarns << "No enough memory to take the snapshot with size (w : h): " << image_width << " : " << image_height << llendl ;
-			return FALSE ; //there is no enough memory for taking this snapshot.
-		}
-	}
-
-	// PRE SNAPSHOT
-	gDisplaySwapBuffers = FALSE;
-	
-	glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
-	setCursor(UI_CURSOR_WAIT);
-
-	// Hide all the UI widgets first and draw a frame
-	BOOL prev_draw_ui = gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI) ? TRUE : FALSE;
-
-	if ( prev_draw_ui != show_ui)
-	{
-		LLPipeline::toggleRenderDebugFeature((void*)LLPipeline::RENDER_DEBUG_FEATURE_UI);
-	}
-
-	BOOL hide_hud = !gSavedSettings.getBOOL("RenderHUDInSnapshot") && LLPipeline::sShowHUDAttachments;
-	if (hide_hud)
-	{
-		LLPipeline::sShowHUDAttachments = FALSE;
-	}
-
-	// if not showing ui, use full window to render world view
-	updateWorldViewRect(!show_ui);
-
-	// Copy screen to a buffer
-	// crop sides or top and bottom, if taking a snapshot of different aspect ratio
-	// from window
-	LLRect window_rect = show_ui ? getWindowRectRaw() : getWorldViewRectRaw(); 
-
-	S32 snapshot_width  = window_rect.getWidth();
-	S32 snapshot_height = window_rect.getHeight();
-	// SNAPSHOT
-	S32 window_width  = snapshot_width;
-	S32 window_height = snapshot_height;
-	
-	// Note: Scaling of the UI is currently *not* supported so we limit the output size if UI is requested
-	if (show_ui)
-	{
-		// If the user wants the UI, limit the output size to the available screen size
-		image_width  = llmin(image_width, window_width);
-		image_height = llmin(image_height, window_height);
-	}
-
-	F32 scale_factor = 1.0f ;
-	if (!keep_window_aspect || (image_width > window_width) || (image_height > window_height))
-	{	
-		// if image cropping or need to enlarge the scene, compute a scale_factor
-		F32 ratio = llmin( (F32)window_width / image_width , (F32)window_height / image_height) ;
-		snapshot_width  = (S32)(ratio * image_width) ;
-		snapshot_height = (S32)(ratio * image_height) ;
-		scale_factor = llmax(1.0f, 1.0f / ratio) ;
-	}
-	
-	if (show_ui && scale_factor > 1.f)
-	{
-		// Note: we should never get there...
-		llwarns << "over scaling UI not supported." << llendl;
-	}
-
-	S32 buffer_x_offset = llfloor(((window_width  - snapshot_width)  * scale_factor) / 2.f);
-	S32 buffer_y_offset = llfloor(((window_height - snapshot_height) * scale_factor) / 2.f);
-
-	S32 image_buffer_x = llfloor(snapshot_width  * scale_factor) ;
-	S32 image_buffer_y = llfloor(snapshot_height * scale_factor) ;
-
-	if ((image_buffer_x > max_size) || (image_buffer_y > max_size)) // boundary check to avoid memory overflow
-	{
-		scale_factor *= llmin((F32)max_size / image_buffer_x, (F32)max_size / image_buffer_y) ;
-		image_buffer_x = llfloor(snapshot_width  * scale_factor) ;
-		image_buffer_y = llfloor(snapshot_height * scale_factor) ;
-	}
-	if ((image_buffer_x > 0) && (image_buffer_y > 0))
-	{
-		raw->resize(image_buffer_x, image_buffer_y, 3);
-	}
-	else
-	{
-		return FALSE ;
-	}
-	if (raw->isBufferInvalid())
-	{
-		return FALSE ;
-	}
-
-	BOOL high_res = scale_factor >= 2.f; // Font scaling is slow, only do so if rez is much higher
-	if (high_res && show_ui)
-	{
-		// Note: we should never get there...
-		llwarns << "High res UI snapshot not supported. " << llendl;
-		/*send_agent_pause();
-		//rescale fonts
-		initFonts(scale_factor);
-		LLHUDObject::reshapeAll();*/
-	}
-
-	S32 output_buffer_offset_y = 0;
-
-	F32 depth_conversion_factor_1 = (LLViewerCamera::getInstance()->getFar() + LLViewerCamera::getInstance()->getNear()) / (2.f * LLViewerCamera::getInstance()->getFar() * LLViewerCamera::getInstance()->getNear());
-	F32 depth_conversion_factor_2 = (LLViewerCamera::getInstance()->getFar() - LLViewerCamera::getInstance()->getNear()) / (2.f * LLViewerCamera::getInstance()->getFar() * LLViewerCamera::getInstance()->getNear());
-
-	gObjectList.generatePickList(*LLViewerCamera::getInstance());
-
-	// Subimages are in fact partial rendering of the final view. This happens when the final view is bigger than the screen.
-	// In most common cases, scale_factor is 1 and there's no more than 1 iteration on x and y
-	for (int subimage_y = 0; subimage_y < scale_factor; ++subimage_y)
-	{
-		S32 subimage_y_offset = llclamp(buffer_y_offset - (subimage_y * window_height), 0, window_height);;
-		// handle fractional columns
-		U32 read_height = llmax(0, (window_height - subimage_y_offset) -
-			llmax(0, (window_height * (subimage_y + 1)) - (buffer_y_offset + raw->getHeight())));
-
-		S32 output_buffer_offset_x = 0;
-		for (int subimage_x = 0; subimage_x < scale_factor; ++subimage_x)
-		{
-			gDisplaySwapBuffers = FALSE;
-			gDepthDirty = TRUE;
-
-			S32 subimage_x_offset = llclamp(buffer_x_offset - (subimage_x * window_width), 0, window_width);
-			// handle fractional rows
-			U32 read_width = llmax(0, (window_width - subimage_x_offset) -
-									llmax(0, (window_width * (subimage_x + 1)) - (buffer_x_offset + raw->getWidth())));
-			
-			// Skip rendering and sampling altogether if either width or height is degenerated to 0 (common in cropping cases)
-			if (read_width && read_height)
-			{
-				const U32 subfield = subimage_x+(subimage_y*llceil(scale_factor));
-				display(do_rebuild, scale_factor, subfield, TRUE);
-				
-				if (!LLPipeline::sRenderDeferred)
-				{
-					// Required for showing the GUI in snapshots and performing bloom composite overlay
-					// Call even if show_ui is FALSE
-					render_ui(scale_factor, subfield);
-				}
-				
-				for (U32 out_y = 0; out_y < read_height ; out_y++)
-				{
-					S32 output_buffer_offset = ( 
-												(out_y * (raw->getWidth())) // ...plus iterated y...
-												+ (window_width * subimage_x) // ...plus subimage start in x...
-												+ (raw->getWidth() * window_height * subimage_y) // ...plus subimage start in y...
-												- output_buffer_offset_x // ...minus buffer padding x...
-												- (output_buffer_offset_y * (raw->getWidth()))  // ...minus buffer padding y...
-												) * raw->getComponents();
-				
-					// Ping the watchdog thread every 100 lines to keep us alive (arbitrary number, feel free to change)
-					if (out_y % 100 == 0)
-					{
-						LLAppViewer::instance()->pingMainloopTimeout("LLViewerWindow::rawSnapshot");
-					}
-				
-					if (type == SNAPSHOT_TYPE_COLOR)
-					{
-						glReadPixels(
-									 subimage_x_offset, out_y + subimage_y_offset,
-									 read_width, 1,
-									 GL_RGB, GL_UNSIGNED_BYTE,
-									 raw->getData() + output_buffer_offset
-									 );
-					}
-					else // SNAPSHOT_TYPE_DEPTH
-					{
-						LLPointer<LLImageRaw> depth_line_buffer = new LLImageRaw(read_width, 1, sizeof(GL_FLOAT)); // need to store floating point values
-						glReadPixels(
-									 subimage_x_offset, out_y + subimage_y_offset,
-									 read_width, 1,
-									 GL_DEPTH_COMPONENT, GL_FLOAT,
-									 depth_line_buffer->getData()// current output pixel is beginning of buffer...
-									 );
-
-						for (S32 i = 0; i < (S32)read_width; i++)
-						{
-							F32 depth_float = *(F32*)(depth_line_buffer->getData() + (i * sizeof(F32)));
-					
-							F32 linear_depth_float = 1.f / (depth_conversion_factor_1 - (depth_float * depth_conversion_factor_2));
-							U8 depth_byte = F32_to_U8(linear_depth_float, LLViewerCamera::getInstance()->getNear(), LLViewerCamera::getInstance()->getFar());
-							// write converted scanline out to result image
-							for (S32 j = 0; j < raw->getComponents(); j++)
-							{
-								*(raw->getData() + output_buffer_offset + (i * raw->getComponents()) + j) = depth_byte;
-							}
-						}
-					}
-				}
-			}
-			output_buffer_offset_x += subimage_x_offset;
-			stop_glerror();
-		}
-		output_buffer_offset_y += subimage_y_offset;
-	}
-
-	gDisplaySwapBuffers = FALSE;
-	gDepthDirty = TRUE;
-
-	// POST SNAPSHOT
-	if (!gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
-	{
-		LLPipeline::toggleRenderDebugFeature((void*)LLPipeline::RENDER_DEBUG_FEATURE_UI);
-	}
-
-	if (hide_hud)
-	{
-		LLPipeline::sShowHUDAttachments = TRUE;
-	}
-
-	/*if (high_res)
-	{
-		initFonts(1.f);
-		LLHUDObject::reshapeAll();
-	}*/
-
-	// Pre-pad image to number of pixels such that the line length is a multiple of 4 bytes (for BMP encoding)
-	// Note: this formula depends on the number of components being 3.  Not obvious, but it's correct.	
-	image_width += (image_width * 3) % 4;
-
-	BOOL ret = TRUE ;
-	// Resize image
-	if(llabs(image_width - image_buffer_x) > 4 || llabs(image_height - image_buffer_y) > 4)
-	{
-		ret = raw->scale( image_width, image_height );  
-	}
-	else if(image_width != image_buffer_x || image_height != image_buffer_y)
-	{
-		ret = raw->scale( image_width, image_height, FALSE );  
-	}
-	
-
-	setCursor(UI_CURSOR_ARROW);
-
-	if (do_rebuild)
-	{
-		// If we had to do a rebuild, that means that the lists of drawables to be rendered
-		// was empty before we started.
-		// Need to reset these, otherwise we call state sort on it again when render gets called the next time
-		// and we stand a good chance of crashing on rebuild because the render drawable arrays have multiple copies of
-		// objects on them.
-		gPipeline.resetDrawOrders();
-	}
-
-	if (high_res)
-	{
-		send_agent_resume();
-	}
-
-	return ret;
-}
-
-void LLViewerWindow::destroyWindow()
-{
-	if (mWindow)
-	{
-		LLWindowManager::destroyWindow(mWindow);
-	}
-	mWindow = NULL;
-}
-
-
-void LLViewerWindow::drawMouselookInstructions()
-{
-	// Draw instructions for mouselook ("Press ESC to return to World View" partially transparent at the bottom of the screen.)
-	const std::string instructions = LLTrans::getString("LeaveMouselook");
-	const LLFontGL* font = LLFontGL::getFont(LLFontDescriptor("SansSerif", "Large", LLFontGL::BOLD));
-	
-	//to be on top of Bottom bar when it is opened
-	const S32 INSTRUCTIONS_PAD = 50;
-
-	font->renderUTF8( 
-		instructions, 0,
-		getWorldViewRectScaled().getCenterX(),
-		getWorldViewRectScaled().mBottom + INSTRUCTIONS_PAD,
-		LLColor4( 1.0f, 1.0f, 1.0f, 0.5f ),
-		LLFontGL::HCENTER, LLFontGL::TOP,
-		LLFontGL::NORMAL,LLFontGL::DROP_SHADOW);
-}
-
-void* LLViewerWindow::getPlatformWindow() const
-{
-	return mWindow->getPlatformWindow();
-}
-
-void* LLViewerWindow::getMediaWindow() 	const
-{
-	return mWindow->getMediaWindow();
-}
-
-void LLViewerWindow::focusClient()		const
-{
-	return mWindow->focusClient();
-}
-
-LLRootView*	LLViewerWindow::getRootView() const
-{
-	return mRootView;
-}
-
-LLRect LLViewerWindow::getWorldViewRectScaled() const
-{
-	return mWorldViewRectScaled;
-}
-
-S32 LLViewerWindow::getWorldViewHeightScaled() const
-{
-	return mWorldViewRectScaled.getHeight();
-}
-
-S32 LLViewerWindow::getWorldViewWidthScaled() const
-{
-	return mWorldViewRectScaled.getWidth();
-}
-
-
-S32 LLViewerWindow::getWorldViewHeightRaw() const
-{
-	return mWorldViewRectRaw.getHeight(); 
-}
-
-S32 LLViewerWindow::getWorldViewWidthRaw() const
-{
-	return mWorldViewRectRaw.getWidth(); 
-}
-
-S32	LLViewerWindow::getWindowHeightScaled()	const 	
-{ 
-	return mWindowRectScaled.getHeight(); 
-}
-
-S32	LLViewerWindow::getWindowWidthScaled() const 	
-{ 
-	return mWindowRectScaled.getWidth(); 
-}
-
-S32	LLViewerWindow::getWindowHeightRaw()	const 	
-{ 
-	return mWindowRectRaw.getHeight(); 
-}
-
-S32	LLViewerWindow::getWindowWidthRaw() const 	
-{ 
-	return mWindowRectRaw.getWidth(); 
-}
-
-void LLViewerWindow::setup2DRender()
-{
-	// setup ortho camera
-	gl_state_for_2d(mWindowRectRaw.getWidth(), mWindowRectRaw.getHeight());
-	setup2DViewport();
-}
-
-void LLViewerWindow::setup2DViewport(S32 x_offset, S32 y_offset)
-{
-	gGLViewport[0] = mWindowRectRaw.mLeft + x_offset;
-	gGLViewport[1] = mWindowRectRaw.mBottom + y_offset;
-	gGLViewport[2] = mWindowRectRaw.getWidth();
-	gGLViewport[3] = mWindowRectRaw.getHeight();
-	glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
-}
-
-
-void LLViewerWindow::setup3DRender()
-{
-	// setup perspective camera
-	LLViewerCamera::getInstance()->setPerspective(NOT_FOR_SELECTION, mWorldViewRectRaw.mLeft, mWorldViewRectRaw.mBottom,  mWorldViewRectRaw.getWidth(), mWorldViewRectRaw.getHeight(), FALSE, LLViewerCamera::getInstance()->getNear(), MAX_FAR_CLIP*2.f);
-	setup3DViewport();
-}
-
-void LLViewerWindow::setup3DViewport(S32 x_offset, S32 y_offset)
-{
-	gGLViewport[0] = mWorldViewRectRaw.mLeft + x_offset;
-	gGLViewport[1] = mWorldViewRectRaw.mBottom + y_offset;
-	gGLViewport[2] = mWorldViewRectRaw.getWidth();
-	gGLViewport[3] = mWorldViewRectRaw.getHeight();
-	glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
-}
-
-void LLViewerWindow::revealIntroPanel()
-{
-	if (mProgressView)
-	{
-		mProgressView->revealIntroPanel();
-	}
-}
-
-void LLViewerWindow::setShowProgress(const BOOL show)
-{
-	if (mProgressView)
-	{
-		mProgressView->setVisible(show);
-	}
-}
-
-void LLViewerWindow::setStartupComplete()
-{
-	if (mProgressView)
-	{
-		mProgressView->setStartupComplete();
-	}
-}
-
-BOOL LLViewerWindow::getShowProgress() const
-{
-	return (mProgressView && mProgressView->getVisible());
-}
-
-void LLViewerWindow::setProgressString(const std::string& string)
-{
-	if (mProgressView)
-	{
-		mProgressView->setText(string);
-	}
-}
-
-void LLViewerWindow::setProgressMessage(const std::string& msg)
-{
-	if(mProgressView)
-	{
-		mProgressView->setMessage(msg);
-	}
-}
-
-void LLViewerWindow::setProgressPercent(const F32 percent)
-{
-	if (mProgressView)
-	{
-		mProgressView->setPercent(percent);
-	}
-}
-
-void LLViewerWindow::setProgressCancelButtonVisible( BOOL b, const std::string& label )
-{
-	if (mProgressView)
-	{
-		mProgressView->setCancelButtonVisible( b, label );
-	}
-}
-
-
-LLProgressView *LLViewerWindow::getProgressView() const
-{
-	return mProgressView;
-}
-
-void LLViewerWindow::dumpState()
-{
-	llinfos << "LLViewerWindow Active " << S32(mActive) << llendl;
-	llinfos << "mWindow visible " << S32(mWindow->getVisible())
-		<< " minimized " << S32(mWindow->getMinimized())
-		<< llendl;
-}
-
-void LLViewerWindow::stopGL(BOOL save_state)
-{
-	//Note: --bao
-	//if not necessary, do not change the order of the function calls in this function.
-	//if change something, make sure it will not break anything.
-	//especially be careful to put anything behind gTextureList.destroyGL(save_state);
-	if (!gGLManager.mIsDisabled)
-	{
-		llinfos << "Shutting down GL..." << llendl;
-
-		// Pause texture decode threads (will get unpaused during main loop)
-		LLAppViewer::getTextureCache()->pause();
-		LLAppViewer::getImageDecodeThread()->pause();
-		LLAppViewer::getTextureFetch()->pause();
-				
-		gSky.destroyGL();
-		stop_glerror();		
-
-		LLManipTranslate::destroyGL() ;
-		stop_glerror();		
-
-		gBumpImageList.destroyGL();
-		stop_glerror();
-
-		LLFontGL::destroyAllGL();
-		stop_glerror();
-
-		LLVOAvatar::destroyGL();
-		stop_glerror();
-
-		LLViewerDynamicTexture::destroyGL();
-		stop_glerror();
-
-		if (gPipeline.isInit())
-		{
-			gPipeline.destroyGL();
-		}
-		
-		gBox.cleanupGL();
-		
-		if(gPostProcess)
-		{
-			gPostProcess->invalidate();
-		}
-
-		gTextureList.destroyGL(save_state);
-		stop_glerror();
-		
-		gGLManager.mIsDisabled = TRUE;
-		stop_glerror();
-		
-		llinfos << "Remaining allocated texture memory: " << LLImageGL::sGlobalTextureMemoryInBytes << " bytes" << llendl;
-	}
-}
-
-void LLViewerWindow::restoreGL(const std::string& progress_message)
-{
-	//Note: --bao
-	//if not necessary, do not change the order of the function calls in this function.
-	//if change something, make sure it will not break anything. 
-	//especially, be careful to put something before gTextureList.restoreGL();
-	if (gGLManager.mIsDisabled)
-	{
-		llinfos << "Restoring GL..." << llendl;
-		gGLManager.mIsDisabled = FALSE;
-		
-		initGLDefaults();
-		LLGLState::restoreGL();
-		
-		gTextureList.restoreGL();
-		
-		// for future support of non-square pixels, and fonts that are properly stretched
-		//LLFontGL::destroyDefaultFonts();
-		initFonts();
-				
-		gSky.restoreGL();
-		gPipeline.restoreGL();
-		LLDrawPoolWater::restoreGL();
-		LLManipTranslate::restoreGL();
-		
-		gBumpImageList.restoreGL();
-		LLViewerDynamicTexture::restoreGL();
-		LLVOAvatar::restoreGL();
-		
-		gResizeScreenTexture = TRUE;
-		gWindowResized = TRUE;
-
-		if (isAgentAvatarValid() && !gAgentAvatarp->isUsingBakedTextures())
-		{
-			LLVisualParamHint::requestHintUpdates();
-		}
-
-		if (!progress_message.empty())
-		{
-			gRestoreGLTimer.reset();
-			gRestoreGL = TRUE;
-			setShowProgress(TRUE);
-			setProgressString(progress_message);
-		}
-		llinfos << "...Restoring GL done" << llendl;
-		if(!LLAppViewer::instance()->restoreErrorTrap())
-		{
-			llwarns << " Someone took over my signal/exception handler (post restoreGL)!" << llendl;
-		}
-
-	}
-}
-
-void LLViewerWindow::initFonts(F32 zoom_factor)
-{
-	LLFontGL::destroyAllGL();
-	// Initialize with possibly different zoom factor
-
-	LLFontManager::initClass();
-
-	LLFontGL::initClass( gSavedSettings.getF32("FontScreenDPI"),
-								mDisplayScale.mV[VX] * zoom_factor,
-								mDisplayScale.mV[VY] * zoom_factor,
-								gDirUtilp->getAppRODataDir(),
-								LLUI::getXUIPaths());
-	// Force font reloads, which can be very slow
-	LLFontGL::loadDefaultFonts();
-}
-
-void LLViewerWindow::requestResolutionUpdate()
-{
-	mResDirty = true;
-}
-
-void LLViewerWindow::checkSettings()
-{
-	if (mStatesDirty)
-	{
-		gGL.refreshState();
-		LLViewerShaderMgr::instance()->setShaders();
-		mStatesDirty = false;
-	}
-	
-	// We want to update the resolution AFTER the states getting refreshed not before.
-	if (mResDirty)
-	{
-		reshape(getWindowWidthRaw(), getWindowHeightRaw());
-		mResDirty = false;
-	}	
-}
-
-void LLViewerWindow::restartDisplay(BOOL show_progress_bar)
-{
-	llinfos << "Restaring GL" << llendl;
-	stopGL();
-	if (show_progress_bar)
-	{
-		restoreGL(LLTrans::getString("ProgressChangingResolution"));
-	}
-	else
-	{
-		restoreGL();
-	}
-}
-
-BOOL LLViewerWindow::changeDisplaySettings(LLCoordScreen size, BOOL disable_vsync, BOOL show_progress_bar)
-{
-	//BOOL was_maximized = gSavedSettings.getBOOL("WindowMaximized");
-
-	//gResizeScreenTexture = TRUE;
-
-
-	//U32 fsaa = gSavedSettings.getU32("RenderFSAASamples");
-	//U32 old_fsaa = mWindow->getFSAASamples();
-
-	// if not maximized, use the request size
-	if (!mWindow->getMaximized())
-	{
-		mWindow->setSize(size);
-	}
-
-	//if (fsaa == old_fsaa)
-	{
-		return TRUE;
-	}
-
-/*
-
-	// Close floaters that don't handle settings change
-	LLFloaterReg::hideInstance("snapshot");
-	
-	BOOL result_first_try = FALSE;
-	BOOL result_second_try = FALSE;
-
-	LLFocusableElement* keyboard_focus = gFocusMgr.getKeyboardFocus();
-	send_agent_pause();
-	llinfos << "Stopping GL during changeDisplaySettings" << llendl;
-	stopGL();
-	mIgnoreActivate = TRUE;
-	LLCoordScreen old_size;
-	LLCoordScreen old_pos;
-	mWindow->getSize(&old_size);
-
-	//mWindow->setFSAASamples(fsaa);
-
-	result_first_try = mWindow->switchContext(false, size, disable_vsync);
-	if (!result_first_try)
-	{
-		// try to switch back
-		//mWindow->setFSAASamples(old_fsaa);
-		result_second_try = mWindow->switchContext(false, old_size, disable_vsync);
-
-		if (!result_second_try)
-		{
-			// we are stuck...try once again with a minimal resolution?
-			send_agent_resume();
-			mIgnoreActivate = FALSE;
-			return FALSE;
-		}
-	}
-	send_agent_resume();
-
-	llinfos << "Restoring GL during resolution change" << llendl;
-	if (show_progress_bar)
-	{
-		restoreGL(LLTrans::getString("ProgressChangingResolution"));
-	}
-	else
-	{
-		restoreGL();
-	}
-
-	if (!result_first_try)
-	{
-		LLSD args;
-		args["RESX"] = llformat("%d",size.mX);
-		args["RESY"] = llformat("%d",size.mY);
-		LLNotificationsUtil::add("ResolutionSwitchFail", args);
-		size = old_size; // for reshape below
-	}
-
-	BOOL success = result_first_try || result_second_try;
-
-	if (success)
-	{
-		// maximize window if was maximized, else reposition
-		if (was_maximized)
-		{
-			mWindow->maximize();
-		}
-		else
-		{
-			S32 windowX = gSavedSettings.getS32("WindowX");
-			S32 windowY = gSavedSettings.getS32("WindowY");
-
-			mWindow->setPosition(LLCoordScreen ( windowX, windowY ) );
-		}
-	}
-
-	mIgnoreActivate = FALSE;
-	gFocusMgr.setKeyboardFocus(keyboard_focus);
-	
-	return success;
-
-	*/
-}
-
-F32	LLViewerWindow::getWorldViewAspectRatio() const
-{
-	F32 world_aspect = (F32)mWorldViewRectRaw.getWidth() / (F32)mWorldViewRectRaw.getHeight();
-	return world_aspect;
-}
-
-void LLViewerWindow::calcDisplayScale()
-{
-	F32 ui_scale_factor = gSavedSettings.getF32("UIScaleFactor");
-	LLVector2 display_scale;
-	display_scale.setVec(llmax(1.f / mWindow->getPixelAspectRatio(), 1.f), llmax(mWindow->getPixelAspectRatio(), 1.f));
-	display_scale *= ui_scale_factor;
-
-	// limit minimum display scale
-	if (display_scale.mV[VX] < MIN_DISPLAY_SCALE || display_scale.mV[VY] < MIN_DISPLAY_SCALE)
-	{
-		display_scale *= MIN_DISPLAY_SCALE / llmin(display_scale.mV[VX], display_scale.mV[VY]);
-	}
-	
-	if (display_scale != mDisplayScale)
-	{
-		llinfos << "Setting display scale to " << display_scale << llendl;
-
-		mDisplayScale = display_scale;
-		// Init default fonts
-		initFonts();
-	}
-}
-
-//static
-LLRect 	LLViewerWindow::calcScaledRect(const LLRect & rect, const LLVector2& display_scale)
-{
-	LLRect res = rect;
-	res.mLeft = llround((F32)res.mLeft / display_scale.mV[VX]);
-	res.mRight = llround((F32)res.mRight / display_scale.mV[VX]);
-	res.mBottom = llround((F32)res.mBottom / display_scale.mV[VY]);
-	res.mTop = llround((F32)res.mTop / display_scale.mV[VY]);
-
-	return res;
-}
-
-S32 LLViewerWindow::getChatConsoleBottomPad()
-{
-	S32 offset = 0;
-
-	if(gToolBarView)
-		offset += gToolBarView->getChild<LLView>("bottom_toolbar_panel")->getRect().getHeight();
-
-	return offset;
-}
-
-LLRect LLViewerWindow::getChatConsoleRect()
-{
-	LLRect full_window(0, getWindowHeightScaled(), getWindowWidthScaled(), 0);
-	LLRect console_rect = full_window;
-
-	const S32 CONSOLE_PADDING_TOP = 24;
-	const S32 CONSOLE_PADDING_LEFT = 24;
-	const S32 CONSOLE_PADDING_RIGHT = 10;
-
-	console_rect.mTop    -= CONSOLE_PADDING_TOP;
-	console_rect.mBottom += getChatConsoleBottomPad();
-
-	console_rect.mLeft   += CONSOLE_PADDING_LEFT; 
-
-	static const BOOL CHAT_FULL_WIDTH = gSavedSettings.getBOOL("ChatFullWidth");
-
-	if (CHAT_FULL_WIDTH)
-	{
-		console_rect.mRight -= CONSOLE_PADDING_RIGHT;
-	}
-	else
-	{
-		// Make console rect somewhat narrow so having inventory open is
-		// less of a problem.
-		console_rect.mRight  = console_rect.mLeft + 2 * getWindowWidthScaled() / 3;
-	}
-
-	return console_rect;
-}
-//----------------------------------------------------------------------------
-
-
-//static 
-bool LLViewerWindow::onAlert(const LLSD& notify)
-{
-	LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID());
-
-	if (gHeadlessClient)
-	{
-		llinfos << "Alert: " << notification->getName() << llendl;
-	}
-
-	// If we're in mouselook, the mouse is hidden and so the user can't click 
-	// the dialog buttons.  In that case, change to First Person instead.
-	if( gAgentCamera.cameraMouselook() )
-	{
-		gAgentCamera.changeCameraToDefault();
-	}
-	return false;
-}
-
-void LLViewerWindow::setUIVisibility(bool visible)
-{
-	mUIVisible = visible;
-
-	if (!visible)
-	{
-		gAgentCamera.changeCameraToThirdPerson(FALSE);
-		gFloaterView->hideAllFloaters();
-	}
-	else
-	{
-		gFloaterView->showHiddenFloaters();
-	}
-
-	if (gToolBarView)
-	{
-		gToolBarView->setToolBarsVisible(visible);
-	}
-
-	LLNavigationBar::getInstance()->setVisible(visible ? gSavedSettings.getBOOL("ShowNavbarNavigationPanel") : FALSE);
-	LLPanelTopInfoBar::getInstance()->setVisible(visible? gSavedSettings.getBOOL("ShowMiniLocationPanel") : FALSE);
-	mRootView->getChildView("status_bar_container")->setVisible(visible);
-}
-
-bool LLViewerWindow::getUIVisibility()
-{
-	return mUIVisible;
-}
-
-////////////////////////////////////////////////////////////////////////////
-//
-// LLPickInfo
-//
-LLPickInfo::LLPickInfo()
-	: mKeyMask(MASK_NONE),
-	  mPickCallback(NULL),
-	  mPickType(PICK_INVALID),
-	  mWantSurfaceInfo(FALSE),
-	  mObjectFace(-1),
-	  mUVCoords(-1.f, -1.f),
-	  mSTCoords(-1.f, -1.f),
-	  mXYCoords(-1, -1),
-	  mIntersection(),
-	  mNormal(),
-	  mBinormal(),
-	  mHUDIcon(NULL),
-	  mPickTransparent(FALSE)
-{
-}
-
-LLPickInfo::LLPickInfo(const LLCoordGL& mouse_pos, 
-		       MASK keyboard_mask, 
-		       BOOL pick_transparent,
-		       BOOL pick_uv_coords,
-		       void (*pick_callback)(const LLPickInfo& pick_info))
-	: mMousePt(mouse_pos),
-	  mKeyMask(keyboard_mask),
-	  mPickCallback(pick_callback),
-	  mPickType(PICK_INVALID),
-	  mWantSurfaceInfo(pick_uv_coords),
-	  mObjectFace(-1),
-	  mUVCoords(-1.f, -1.f),
-	  mSTCoords(-1.f, -1.f),
-	  mXYCoords(-1, -1),
-	  mNormal(),
-	  mBinormal(),
-	  mHUDIcon(NULL),
-	  mPickTransparent(pick_transparent)
-{
-}
-
-void LLPickInfo::fetchResults()
-{
-
-	S32 face_hit = -1;
-	LLVector3 intersection, normal, binormal;
-	LLVector2 uv;
-
-	LLHUDIcon* hit_icon = gViewerWindow->cursorIntersectIcon(mMousePt.mX, mMousePt.mY, 512.f, &intersection);
-	
-	F32 icon_dist = 0.f;
-	if (hit_icon)
-	{
-		icon_dist = (LLViewerCamera::getInstance()->getOrigin()-intersection).magVec();
-	}
-	LLViewerObject* hit_object = gViewerWindow->cursorIntersect(mMousePt.mX, mMousePt.mY, 512.f,
-									NULL, -1, mPickTransparent, &face_hit,
-									&intersection, &uv, &normal, &binormal);
-	
-	mPickPt = mMousePt;
-
-	U32 te_offset = face_hit > -1 ? face_hit : 0;
-
-	//unproject relative clicked coordinate from window coordinate using GL
-	
-	LLViewerObject* objectp = hit_object;
-
-	if (hit_icon && 
-		(!objectp || 
-		icon_dist < (LLViewerCamera::getInstance()->getOrigin()-intersection).magVec()))
-	{
-		// was this name referring to a hud icon?
-		mHUDIcon = hit_icon;
-		mPickType = PICK_ICON;
-		mPosGlobal = mHUDIcon->getPositionGlobal();
-	}
-	else if (objectp)
-	{
-		if( objectp->getPCode() == LLViewerObject::LL_VO_SURFACE_PATCH )
-		{
-			// Hit land
-			mPickType = PICK_LAND;
-			mObjectID.setNull(); // land has no id
-
-			// put global position into land_pos
-			LLVector3d land_pos;
-			if (!gViewerWindow->mousePointOnLandGlobal(mPickPt.mX, mPickPt.mY, &land_pos))
-			{
-				// The selected point is beyond the draw distance or is otherwise 
-				// not selectable. Return before calling mPickCallback().
-				return;
-			}
-
-			// Fudge the land focus a little bit above ground.
-			mPosGlobal = land_pos + LLVector3d::z_axis * 0.1f;
-		}
-		else
-		{
-			if(isFlora(objectp))
-			{
-				mPickType = PICK_FLORA;
-			}
-			else
-			{
-				mPickType = PICK_OBJECT;
-			}
-			mObjectOffset = gAgentCamera.calcFocusOffset(objectp, intersection, mPickPt.mX, mPickPt.mY);
-			mObjectID = objectp->mID;
-			mObjectFace = (te_offset == NO_FACE) ? -1 : (S32)te_offset;
-
-			mPosGlobal = gAgent.getPosGlobalFromAgent(intersection);
-			
-			if (mWantSurfaceInfo)
-			{
-				getSurfaceInfo();
-			}
-		}
-	}
-	
-	if (mPickCallback)
-	{
-		mPickCallback(*this);
-	}
-}
-
-LLPointer<LLViewerObject> LLPickInfo::getObject() const
-{
-	return gObjectList.findObject( mObjectID );
-}
-
-void LLPickInfo::updateXYCoords()
-{
-	if (mObjectFace > -1)
-	{
-		const LLTextureEntry* tep = getObject()->getTE(mObjectFace);
-		LLPointer<LLViewerTexture> imagep = LLViewerTextureManager::getFetchedTexture(tep->getID());
-		if(mUVCoords.mV[VX] >= 0.f && mUVCoords.mV[VY] >= 0.f && imagep.notNull())
-		{
-			mXYCoords.mX = llround(mUVCoords.mV[VX] * (F32)imagep->getWidth());
-			mXYCoords.mY = llround((1.f - mUVCoords.mV[VY]) * (F32)imagep->getHeight());
-		}
-	}
-}
-
-void LLPickInfo::getSurfaceInfo()
-{
-	// set values to uninitialized - this is what we return if no intersection is found
-	mObjectFace   = -1;
-	mUVCoords     = LLVector2(-1, -1);
-	mSTCoords     = LLVector2(-1, -1);
-	mXYCoords	  = LLCoordScreen(-1, -1);
-	mIntersection = LLVector3(0,0,0);
-	mNormal       = LLVector3(0,0,0);
-	mBinormal     = LLVector3(0,0,0);
-	
-	LLViewerObject* objectp = getObject();
-
-	if (objectp)
-	{
-		if (gViewerWindow->cursorIntersect(llround((F32)mMousePt.mX), llround((F32)mMousePt.mY), 1024.f,
-										   objectp, -1, mPickTransparent,
-										   &mObjectFace,
-										   &mIntersection,
-										   &mSTCoords,
-										   &mNormal,
-										   &mBinormal))
-		{
-			// if we succeeded with the intersect above, compute the texture coordinates:
-
-			if (objectp->mDrawable.notNull() && mObjectFace > -1)
-			{
-				LLFace* facep = objectp->mDrawable->getFace(mObjectFace);
-
-				mUVCoords = facep->surfaceToTexture(mSTCoords, mIntersection, mNormal);
-			}
-
-			// and XY coords:
-			updateXYCoords();
-			
-		}
-	}
-}
-
-
-/* code to get UV via a special UV render - removed in lieu of raycast method
-LLVector2 LLPickInfo::pickUV()
-{
-	LLVector2 result(-1.f, -1.f);
-
-	LLViewerObject* objectp = getObject();
-	if (!objectp)
-	{
-		return result;
-	}
-
-	if (mObjectFace > -1 &&
-		objectp->mDrawable.notNull() && objectp->getPCode() == LL_PCODE_VOLUME &&
-		mObjectFace < objectp->mDrawable->getNumFaces())
-	{
-		S32 scaled_x = llround((F32)mPickPt.mX * gViewerWindow->getDisplayScale().mV[VX]);
-		S32 scaled_y = llround((F32)mPickPt.mY * gViewerWindow->getDisplayScale().mV[VY]);
-		const S32 UV_PICK_WIDTH = 5;
-		const S32 UV_PICK_HALF_WIDTH = (UV_PICK_WIDTH - 1) / 2;
-		U8 uv_pick_buffer[UV_PICK_WIDTH * UV_PICK_WIDTH * 4];
-		LLFace* facep = objectp->mDrawable->getFace(mObjectFace);
-		if (facep)
-		{
-			LLGLState scissor_state(GL_SCISSOR_TEST);
-			scissor_state.enable();
-			LLViewerCamera::getInstance()->setPerspective(FOR_SELECTION, scaled_x - UV_PICK_HALF_WIDTH, scaled_y - UV_PICK_HALF_WIDTH, UV_PICK_WIDTH, UV_PICK_WIDTH, FALSE);
-			//glViewport(scaled_x - UV_PICK_HALF_WIDTH, scaled_y - UV_PICK_HALF_WIDTH, UV_PICK_WIDTH, UV_PICK_WIDTH);
-			glScissor(scaled_x - UV_PICK_HALF_WIDTH, scaled_y - UV_PICK_HALF_WIDTH, UV_PICK_WIDTH, UV_PICK_WIDTH);
-
-			glClear(GL_DEPTH_BUFFER_BIT);
-
-			facep->renderSelectedUV();
-
-			glReadPixels(scaled_x - UV_PICK_HALF_WIDTH, scaled_y - UV_PICK_HALF_WIDTH, UV_PICK_WIDTH, UV_PICK_WIDTH, GL_RGBA, GL_UNSIGNED_BYTE, uv_pick_buffer);
-			U8* center_pixel = &uv_pick_buffer[4 * ((UV_PICK_WIDTH * UV_PICK_HALF_WIDTH) + UV_PICK_HALF_WIDTH + 1)];
-
-			result.mV[VX] = (F32)((center_pixel[VGREEN] & 0xf) + (16.f * center_pixel[VRED])) / 4095.f;
-			result.mV[VY] = (F32)((center_pixel[VGREEN] >> 4) + (16.f * center_pixel[VBLUE])) / 4095.f;
-		}
-	}
-
-	return result;
-} */
-
-
-//static 
-bool LLPickInfo::isFlora(LLViewerObject* object)
-{
-	if (!object) return false;
-
-	LLPCode pcode = object->getPCode();
-
-	if( (LL_PCODE_LEGACY_GRASS == pcode) 
-		|| (LL_PCODE_LEGACY_TREE == pcode) 
-		|| (LL_PCODE_TREE_NEW == pcode))
-	{
-		return true;
-	}
-	return false;
-}
+/** 
+ * @file llviewerwindow.cpp
+ * @brief Implementation of the LLViewerWindow class.
+ *
+ * $LicenseInfo:firstyear=2001&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$
+ */
+
+#include "llviewerprecompiledheaders.h"
+#include "llviewerwindow.h"
+
+#if LL_WINDOWS
+#pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally
+#endif
+
+// system library includes
+#include <stdio.h>
+#include <iostream>
+#include <fstream>
+#include <algorithm>
+#include <boost/lambda/core.hpp>
+
+#include "llagent.h"
+#include "llagentcamera.h"
+#include "llfloaterreg.h"
+#include "llmeshrepository.h"
+#include "llpanellogin.h"
+#include "llviewerkeyboard.h"
+#include "llviewermenu.h"
+
+#include "llviewquery.h"
+#include "llxmltree.h"
+#include "llslurl.h"
+//#include "llviewercamera.h"
+#include "llrender.h"
+
+#include "llvoiceclient.h"	// for push-to-talk button handling
+
+//
+// TODO: Many of these includes are unnecessary.  Remove them.
+//
+
+// linden library includes
+#include "llaudioengine.h"		// mute on minimize
+#include "indra_constants.h"
+#include "llassetstorage.h"
+#include "llerrorcontrol.h"
+#include "llfontgl.h"
+#include "llmousehandler.h"
+#include "llrect.h"
+#include "llsky.h"
+#include "llstring.h"
+#include "llui.h"
+#include "lluuid.h"
+#include "llview.h"
+#include "llxfermanager.h"
+#include "message.h"
+#include "object_flags.h"
+#include "lltimer.h"
+#include "timing.h"
+#include "llviewermenu.h"
+#include "lltooltip.h"
+#include "llmediaentry.h"
+#include "llurldispatcher.h"
+#include "raytrace.h"
+
+// newview includes
+#include "llagent.h"
+#include "llbox.h"
+#include "llchicletbar.h"
+#include "llconsole.h"
+#include "llviewercontrol.h"
+#include "llcylinder.h"
+#include "lldebugview.h"
+#include "lldir.h"
+#include "lldrawable.h"
+#include "lldrawpoolalpha.h"
+#include "lldrawpoolbump.h"
+#include "lldrawpoolwater.h"
+#include "llmaniptranslate.h"
+#include "llface.h"
+#include "llfeaturemanager.h"
+#include "llfilepicker.h"
+#include "llfirstuse.h"
+#include "llfloater.h"
+#include "llfloaterbuildoptions.h"
+#include "llfloaterbuyland.h"
+#include "llfloatercamera.h"
+#include "llfloaterland.h"
+#include "llfloaterinspect.h"
+#include "llfloatermap.h"
+#include "llfloaternamedesc.h"
+#include "llfloaterpreference.h"
+#include "llfloatersnapshot.h"
+#include "llfloatertools.h"
+#include "llfloaterworldmap.h"
+#include "llfocusmgr.h"
+#include "llfontfreetype.h"
+#include "llgesturemgr.h"
+#include "llglheaders.h"
+#include "lltooltip.h"
+#include "llhudmanager.h"
+#include "llhudobject.h"
+#include "llhudview.h"
+#include "llimagebmp.h"
+#include "llimagej2c.h"
+#include "llimageworker.h"
+#include "llkeyboard.h"
+#include "lllineeditor.h"
+#include "llmenugl.h"
+#include "llmodaldialog.h"
+#include "llmorphview.h"
+#include "llmoveview.h"
+#include "llnavigationbar.h"
+#include "llpaneltopinfobar.h"
+#include "llpopupview.h"
+#include "llpreviewtexture.h"
+#include "llprogressview.h"
+#include "llresmgr.h"
+#include "llselectmgr.h"
+#include "llrootview.h"
+#include "llrendersphere.h"
+#include "llstartup.h"
+#include "llstatusbar.h"
+#include "llstatview.h"
+#include "llsurface.h"
+#include "llsurfacepatch.h"
+#include "lltexlayer.h"
+#include "lltextbox.h"
+#include "lltexturecache.h"
+#include "lltexturefetch.h"
+#include "lltextureview.h"
+#include "lltool.h"
+#include "lltoolbarview.h"
+#include "lltoolcomp.h"
+#include "lltooldraganddrop.h"
+#include "lltoolface.h"
+#include "lltoolfocus.h"
+#include "lltoolgrab.h"
+#include "lltoolmgr.h"
+#include "lltoolmorph.h"
+#include "lltoolpie.h"
+#include "lltoolselectland.h"
+#include "lltrans.h"
+#include "lluictrlfactory.h"
+#include "llurldispatcher.h"		// SLURL from other app instance
+#include "llversioninfo.h"
+#include "llvieweraudio.h"
+#include "llviewercamera.h"
+#include "llviewergesture.h"
+#include "llviewertexturelist.h"
+#include "llviewerinventory.h"
+#include "llviewerkeyboard.h"
+#include "llviewermedia.h"
+#include "llviewermediafocus.h"
+#include "llviewermenu.h"
+#include "llviewermessage.h"
+#include "llviewerobjectlist.h"
+#include "llviewerparcelmgr.h"
+#include "llviewerregion.h"
+#include "llviewershadermgr.h"
+#include "llviewerstats.h"
+#include "llvoavatarself.h"
+#include "llvovolume.h"
+#include "llworld.h"
+#include "llworldmapview.h"
+#include "pipeline.h"
+#include "llappviewer.h"
+#include "llviewerdisplay.h"
+#include "llspatialpartition.h"
+#include "llviewerjoystick.h"
+#include "llviewernetwork.h"
+#include "llpostprocess.h"
+#include "llnearbychatbar.h"
+#include "llagentui.h"
+#include "llwearablelist.h"
+
+#include "llnotifications.h"
+#include "llnotificationsutil.h"
+#include "llnotificationmanager.h"
+
+#include "llfloaternotificationsconsole.h"
+
+#include "llnearbychat.h"
+#include "llwindowlistener.h"
+#include "llviewerwindowlistener.h"
+#include "llpaneltopinfobar.h"
+#include "LLPathingLib.h"
+#include "llfloaterpathfindingconsole.h"
+
+#if LL_WINDOWS
+#include <tchar.h> // For Unicode conversion methods
+#endif
+
+//
+// Globals
+//
+void render_ui(F32 zoom_factor = 1.f, int subfield = 0);
+
+extern BOOL gDebugClicks;
+extern BOOL gDisplaySwapBuffers;
+extern BOOL gDepthDirty;
+extern BOOL gResizeScreenTexture;
+
+LLViewerWindow	*gViewerWindow = NULL;
+
+LLFrameTimer	gAwayTimer;
+LLFrameTimer	gAwayTriggerTimer;
+
+BOOL			gShowOverlayTitle = FALSE;
+
+LLViewerObject*  gDebugRaycastObject = NULL;
+LLVector3       gDebugRaycastIntersection;
+LLVector2       gDebugRaycastTexCoord;
+LLVector3       gDebugRaycastNormal;
+LLVector3       gDebugRaycastBinormal;
+S32				gDebugRaycastFaceHit;
+LLVector3		gDebugRaycastStart;
+LLVector3		gDebugRaycastEnd;
+
+// HUD display lines in lower right
+BOOL				gDisplayWindInfo = FALSE;
+BOOL				gDisplayCameraPos = FALSE;
+BOOL				gDisplayFOV = FALSE;
+BOOL				gDisplayBadge = FALSE;
+
+static const U8 NO_FACE = 255;
+BOOL gQuietSnapshot = FALSE;
+
+static const F32 MIN_DISPLAY_SCALE = 0.75f;
+
+std::string	LLViewerWindow::sSnapshotBaseName;
+std::string	LLViewerWindow::sSnapshotDir;
+
+std::string	LLViewerWindow::sMovieBaseName;
+
+class RecordToChatConsole : public LLError::Recorder, public LLSingleton<RecordToChatConsole>
+{
+public:
+	virtual void recordMessage(LLError::ELevel level,
+								const std::string& message)
+	{
+		//FIXME: this is NOT thread safe, and will do bad things when a warning is issued from a non-UI thread
+
+		// only log warnings to chat console
+		//if (level == LLError::LEVEL_WARN)
+		//{
+			//LLFloaterChat* chat_floater = LLFloaterReg::findTypedInstance<LLFloaterChat>("chat");
+			//if (chat_floater && gSavedSettings.getBOOL("WarningsAsChat"))
+			//{
+			//	LLChat chat;
+			//	chat.mText = message;
+			//	chat.mSourceType = CHAT_SOURCE_SYSTEM;
+
+			//	chat_floater->addChat(chat, FALSE, FALSE);
+			//}
+		//}
+	}
+};
+
+////////////////////////////////////////////////////////////////////////////
+//
+// LLDebugText
+//
+
+class LLDebugText
+{
+private:
+	struct Line
+	{
+		Line(const std::string& in_text, S32 in_x, S32 in_y) : text(in_text), x(in_x), y(in_y) {}
+		std::string text;
+		S32 x,y;
+	};
+
+	LLViewerWindow *mWindow;
+	
+	typedef std::vector<Line> line_list_t;
+	line_list_t mLineList;
+	LLColor4 mTextColor;
+	
+	void addText(S32 x, S32 y, const std::string &text) 
+	{
+		mLineList.push_back(Line(text, x, y));
+	}
+	
+	void clearText() { mLineList.clear(); }
+	
+public:
+	LLDebugText(LLViewerWindow* window) : mWindow(window) {}
+
+	void update()
+	{
+		static LLCachedControl<bool> log_texture_traffic(gSavedSettings,"LogTextureNetworkTraffic") ;
+
+		std::string wind_vel_text;
+		std::string wind_vector_text;
+		std::string rwind_vel_text;
+		std::string rwind_vector_text;
+		std::string audio_text;
+
+		static const std::string beacon_particle = LLTrans::getString("BeaconParticle");
+		static const std::string beacon_physical = LLTrans::getString("BeaconPhysical");
+		static const std::string beacon_scripted = LLTrans::getString("BeaconScripted");
+		static const std::string beacon_scripted_touch = LLTrans::getString("BeaconScriptedTouch");
+		static const std::string beacon_sound = LLTrans::getString("BeaconSound");
+		static const std::string beacon_media = LLTrans::getString("BeaconMedia");
+		static const std::string particle_hiding = LLTrans::getString("ParticleHiding");
+
+		// Draw the statistics in a light gray
+		// and in a thin font
+		mTextColor = LLColor4( 0.86f, 0.86f, 0.86f, 1.f );
+
+		// Draw stuff growing up from right lower corner of screen
+		U32 xpos = mWindow->getWorldViewWidthScaled() - 350;
+		U32 ypos = 64;
+		const U32 y_inc = 20;
+
+		clearText();
+		
+		if (gSavedSettings.getBOOL("DebugShowTime"))
+		{
+			const U32 y_inc2 = 15;
+			for (std::map<S32,LLFrameTimer>::reverse_iterator iter = gDebugTimers.rbegin();
+				 iter != gDebugTimers.rend(); ++iter)
+			{
+				S32 idx = iter->first;
+				LLFrameTimer& timer = iter->second;
+				F32 time = timer.getElapsedTimeF32();
+				S32 hours = (S32)(time / (60*60));
+				S32 mins = (S32)((time - hours*(60*60)) / 60);
+				S32 secs = (S32)((time - hours*(60*60) - mins*60));
+				std::string label = gDebugTimerLabel[idx];
+				if (label.empty()) label = llformat("Debug: %d", idx);
+				addText(xpos, ypos, llformat(" %s: %d:%02d:%02d", label.c_str(), hours,mins,secs)); ypos += y_inc2;
+			}
+			
+			F32 time = gFrameTimeSeconds;
+			S32 hours = (S32)(time / (60*60));
+			S32 mins = (S32)((time - hours*(60*60)) / 60);
+			S32 secs = (S32)((time - hours*(60*60) - mins*60));
+			addText(xpos, ypos, llformat("Time: %d:%02d:%02d", hours,mins,secs)); ypos += y_inc;
+		}
+		
+#if LL_WINDOWS
+		if (gSavedSettings.getBOOL("DebugShowMemory"))
+		{
+			addText(xpos, ypos, llformat("Memory: %d (KB)", LLMemory::getWorkingSetSize() / 1024)); 
+			ypos += y_inc;
+		}
+#endif
+
+		if (gDisplayCameraPos)
+		{
+			std::string camera_view_text;
+			std::string camera_center_text;
+			std::string agent_view_text;
+			std::string agent_left_text;
+			std::string agent_center_text;
+			std::string agent_root_center_text;
+
+			LLVector3d tvector; // Temporary vector to hold data for printing.
+
+			// Update camera center, camera view, wind info every other frame
+			tvector = gAgent.getPositionGlobal();
+			agent_center_text = llformat("AgentCenter  %f %f %f",
+										 (F32)(tvector.mdV[VX]), (F32)(tvector.mdV[VY]), (F32)(tvector.mdV[VZ]));
+
+			if (isAgentAvatarValid())
+			{
+				tvector = gAgent.getPosGlobalFromAgent(gAgentAvatarp->mRoot.getWorldPosition());
+				agent_root_center_text = llformat("AgentRootCenter %f %f %f",
+												  (F32)(tvector.mdV[VX]), (F32)(tvector.mdV[VY]), (F32)(tvector.mdV[VZ]));
+			}
+			else
+			{
+				agent_root_center_text = "---";
+			}
+
+
+			tvector = LLVector4(gAgent.getFrameAgent().getAtAxis());
+			agent_view_text = llformat("AgentAtAxis  %f %f %f",
+									   (F32)(tvector.mdV[VX]), (F32)(tvector.mdV[VY]), (F32)(tvector.mdV[VZ]));
+
+			tvector = LLVector4(gAgent.getFrameAgent().getLeftAxis());
+			agent_left_text = llformat("AgentLeftAxis  %f %f %f",
+									   (F32)(tvector.mdV[VX]), (F32)(tvector.mdV[VY]), (F32)(tvector.mdV[VZ]));
+
+			tvector = gAgentCamera.getCameraPositionGlobal();
+			camera_center_text = llformat("CameraCenter %f %f %f",
+										  (F32)(tvector.mdV[VX]), (F32)(tvector.mdV[VY]), (F32)(tvector.mdV[VZ]));
+
+			tvector = LLVector4(LLViewerCamera::getInstance()->getAtAxis());
+			camera_view_text = llformat("CameraAtAxis    %f %f %f",
+										(F32)(tvector.mdV[VX]), (F32)(tvector.mdV[VY]), (F32)(tvector.mdV[VZ]));
+		
+			addText(xpos, ypos, agent_center_text);  ypos += y_inc;
+			addText(xpos, ypos, agent_root_center_text);  ypos += y_inc;
+			addText(xpos, ypos, agent_view_text);  ypos += y_inc;
+			addText(xpos, ypos, agent_left_text);  ypos += y_inc;
+			addText(xpos, ypos, camera_center_text);  ypos += y_inc;
+			addText(xpos, ypos, camera_view_text);  ypos += y_inc;
+		}
+
+		if (gDisplayWindInfo)
+		{
+			wind_vel_text = llformat("Wind velocity %.2f m/s", gWindVec.magVec());
+			wind_vector_text = llformat("Wind vector   %.2f %.2f %.2f", gWindVec.mV[0], gWindVec.mV[1], gWindVec.mV[2]);
+			rwind_vel_text = llformat("RWind vel %.2f m/s", gRelativeWindVec.magVec());
+			rwind_vector_text = llformat("RWind vec   %.2f %.2f %.2f", gRelativeWindVec.mV[0], gRelativeWindVec.mV[1], gRelativeWindVec.mV[2]);
+
+			addText(xpos, ypos, wind_vel_text);  ypos += y_inc;
+			addText(xpos, ypos, wind_vector_text);  ypos += y_inc;
+			addText(xpos, ypos, rwind_vel_text);  ypos += y_inc;
+			addText(xpos, ypos, rwind_vector_text);  ypos += y_inc;
+		}
+		if (gDisplayWindInfo)
+		{
+			if (gAudiop)
+			{
+				audio_text= llformat("Audio for wind: %d", gAudiop->isWindEnabled());
+			}
+			addText(xpos, ypos, audio_text);  ypos += y_inc;
+		}
+		if (gDisplayFOV)
+		{
+			addText(xpos, ypos, llformat("FOV: %2.1f deg", RAD_TO_DEG * LLViewerCamera::getInstance()->getView()));
+			ypos += y_inc;
+		}
+		if (gDisplayBadge)
+		{
+			addText(xpos, ypos+(y_inc/2), llformat("Hippos!", RAD_TO_DEG * LLViewerCamera::getInstance()->getView()));
+			ypos += y_inc * 2;
+		}
+		
+		/*if (LLViewerJoystick::getInstance()->getOverrideCamera())
+		{
+			addText(xpos + 200, ypos, llformat("Flycam"));
+			ypos += y_inc;
+		}*/
+		
+		if (gSavedSettings.getBOOL("DebugShowRenderInfo"))
+		{
+			if (gPipeline.getUseVertexShaders() == 0)
+			{
+				addText(xpos, ypos, "Shaders Disabled");
+				ypos += y_inc;
+			}
+
+			if (gGLManager.mHasATIMemInfo)
+			{
+				S32 meminfo[4];
+				glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, meminfo);
+
+				addText(xpos, ypos, llformat("%.2f MB Texture Memory Free", meminfo[0]/1024.f));
+				ypos += y_inc;
+
+				if (gGLManager.mHasVertexBufferObject)
+				{
+					glGetIntegerv(GL_VBO_FREE_MEMORY_ATI, meminfo);
+					addText(xpos, ypos, llformat("%.2f MB VBO Memory Free", meminfo[0]/1024.f));
+					ypos += y_inc;
+				}
+			}
+			else if (gGLManager.mHasNVXMemInfo)
+			{
+				S32 free_memory;
+				glGetIntegerv(GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, &free_memory);
+				addText(xpos, ypos, llformat("%.2f MB Video Memory Free", free_memory/1024.f));
+				ypos += y_inc;
+			}
+
+			//show streaming cost/triangle count of known prims in current region OR selection
+			{
+				F32 cost = 0.f;
+				S32 count = 0;
+				S32 vcount = 0;
+				S32 object_count = 0;
+				S32 total_bytes = 0;
+				S32 visible_bytes = 0;
+
+				const char* label = "Region";
+				if (LLSelectMgr::getInstance()->getSelection()->getObjectCount() == 0)
+				{ //region
+					LLViewerRegion* region = gAgent.getRegion();
+					if (region)
+					{
+						for (U32 i = 0; i < gObjectList.getNumObjects(); ++i)
+						{
+							LLViewerObject* object = gObjectList.getObject(i);
+							if (object && 
+								object->getRegion() == region &&
+								object->getVolume())
+							{
+								object_count++;
+								S32 bytes = 0;	
+								S32 visible = 0;
+								cost += object->getStreamingCost(&bytes, &visible);
+								S32 vt = 0;
+								count += object->getTriangleCount(&vt);
+								vcount += vt;
+								total_bytes += bytes;
+								visible_bytes += visible;
+							}
+						}
+					}
+				}
+				else
+				{
+					label = "Selection";
+					cost = LLSelectMgr::getInstance()->getSelection()->getSelectedObjectStreamingCost(&total_bytes, &visible_bytes);
+					count = LLSelectMgr::getInstance()->getSelection()->getSelectedObjectTriangleCount(&vcount);
+					object_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount();
+				}
+					
+				addText(xpos,ypos, llformat("%s streaming cost: %.1f", label, cost));
+				ypos += y_inc;
+
+				addText(xpos, ypos, llformat("    %.3f KTris, %.3f KVerts, %.1f/%.1f KB, %d objects",
+										count/1000.f, vcount/1000.f, visible_bytes/1024.f, total_bytes/1024.f, object_count));
+				ypos += y_inc;
+			
+			}
+
+			addText(xpos, ypos, llformat("%d MB Vertex Data (%d MB Pooled)", LLVertexBuffer::sAllocatedBytes/(1024*1024), LLVBOPool::sBytesPooled/(1024*1024)));
+			ypos += y_inc;
+
+			addText(xpos, ypos, llformat("%d Vertex Buffers", LLVertexBuffer::sGLCount));
+			ypos += y_inc;
+
+			addText(xpos, ypos, llformat("%d Mapped Buffers", LLVertexBuffer::sMappedCount));
+			ypos += y_inc;
+
+			addText(xpos, ypos, llformat("%d Vertex Buffer Binds", LLVertexBuffer::sBindCount));
+			ypos += y_inc;
+
+			addText(xpos, ypos, llformat("%d Vertex Buffer Sets", LLVertexBuffer::sSetCount));
+			ypos += y_inc;
+
+			addText(xpos, ypos, llformat("%d Texture Binds", LLImageGL::sBindCount));
+			ypos += y_inc;
+
+			addText(xpos, ypos, llformat("%d Unique Textures", LLImageGL::sUniqueCount));
+			ypos += y_inc;
+
+			addText(xpos, ypos, llformat("%d Render Calls", gPipeline.mBatchCount));
+            ypos += y_inc;
+
+			addText(xpos, ypos, llformat("%d Matrix Ops", gPipeline.mMatrixOpCount));
+			ypos += y_inc;
+
+			addText(xpos, ypos, llformat("%d Texture Matrix Ops", gPipeline.mTextureMatrixOps));
+			ypos += y_inc;
+
+			gPipeline.mTextureMatrixOps = 0;
+			gPipeline.mMatrixOpCount = 0;
+
+			if (gPipeline.mBatchCount > 0)
+			{
+				addText(xpos, ypos, llformat("Batch min/max/mean: %d/%d/%d", gPipeline.mMinBatchSize, gPipeline.mMaxBatchSize, 
+					gPipeline.mTrianglesDrawn/gPipeline.mBatchCount));
+
+				gPipeline.mMinBatchSize = gPipeline.mMaxBatchSize;
+				gPipeline.mMaxBatchSize = 0;
+				gPipeline.mBatchCount = 0;
+			}
+            ypos += y_inc;
+
+			addText(xpos, ypos, llformat("UI Verts/Calls: %d/%d", LLRender::sUIVerts, LLRender::sUICalls));
+			LLRender::sUICalls = LLRender::sUIVerts = 0;
+			ypos += y_inc;
+
+			addText(xpos,ypos, llformat("%d/%d Nodes visible", gPipeline.mNumVisibleNodes, LLSpatialGroup::sNodeCount));
+			
+			ypos += y_inc;
+
+			if (!LLSpatialGroup::sPendingQueries.empty())
+			{
+				addText(xpos,ypos, llformat("%d Queries pending", LLSpatialGroup::sPendingQueries.size()));
+				ypos += y_inc;
+			}
+
+
+			addText(xpos,ypos, llformat("%d Avatars visible", LLVOAvatar::sNumVisibleAvatars));
+			
+			ypos += y_inc;
+
+			addText(xpos,ypos, llformat("%d Lights visible", LLPipeline::sVisibleLightCount));
+			
+			ypos += y_inc;
+
+			if (gMeshRepo.meshRezEnabled())
+			{
+				addText(xpos, ypos, llformat("%.3f MB Mesh Data Received", LLMeshRepository::sBytesReceived/(1024.f*1024.f)));
+				
+				ypos += y_inc;
+				
+				addText(xpos, ypos, llformat("%d/%d Mesh HTTP Requests/Retries", LLMeshRepository::sHTTPRequestCount,
+					LLMeshRepository::sHTTPRetryCount));
+				
+				ypos += y_inc;
+
+				addText(xpos, ypos, llformat("%.3f/%.3f MB Mesh Cache Read/Write ", LLMeshRepository::sCacheBytesRead/(1024.f*1024.f), LLMeshRepository::sCacheBytesWritten/(1024.f*1024.f)));
+
+				ypos += y_inc;
+			}
+
+			LLVertexBuffer::sBindCount = LLImageGL::sBindCount = 
+				LLVertexBuffer::sSetCount = LLImageGL::sUniqueCount = 
+				gPipeline.mNumVisibleNodes = LLPipeline::sVisibleLightCount = 0;
+		}
+		if (gSavedSettings.getBOOL("DebugShowRenderMatrices"))
+		{
+			addText(xpos, ypos, llformat("%.4f    .%4f    %.4f    %.4f", gGLProjection[12], gGLProjection[13], gGLProjection[14], gGLProjection[15]));
+			ypos += y_inc;
+
+			addText(xpos, ypos, llformat("%.4f    .%4f    %.4f    %.4f", gGLProjection[8], gGLProjection[9], gGLProjection[10], gGLProjection[11]));
+			ypos += y_inc;
+
+			addText(xpos, ypos, llformat("%.4f    .%4f    %.4f    %.4f", gGLProjection[4], gGLProjection[5], gGLProjection[6], gGLProjection[7]));
+			ypos += y_inc;
+
+			addText(xpos, ypos, llformat("%.4f    .%4f    %.4f    %.4f", gGLProjection[0], gGLProjection[1], gGLProjection[2], gGLProjection[3]));
+			ypos += y_inc;
+
+			addText(xpos, ypos, "Projection Matrix");
+			ypos += y_inc;
+
+
+			addText(xpos, ypos, llformat("%.4f    .%4f    %.4f    %.4f", gGLModelView[12], gGLModelView[13], gGLModelView[14], gGLModelView[15]));
+			ypos += y_inc;
+
+			addText(xpos, ypos, llformat("%.4f    .%4f    %.4f    %.4f", gGLModelView[8], gGLModelView[9], gGLModelView[10], gGLModelView[11]));
+			ypos += y_inc;
+
+			addText(xpos, ypos, llformat("%.4f    .%4f    %.4f    %.4f", gGLModelView[4], gGLModelView[5], gGLModelView[6], gGLModelView[7]));
+			ypos += y_inc;
+
+			addText(xpos, ypos, llformat("%.4f    .%4f    %.4f    %.4f", gGLModelView[0], gGLModelView[1], gGLModelView[2], gGLModelView[3]));
+			ypos += y_inc;
+
+			addText(xpos, ypos, "View Matrix");
+			ypos += y_inc;
+		}
+		if (gSavedSettings.getBOOL("DebugShowColor"))
+		{
+			U8 color[4];
+			LLCoordGL coord = gViewerWindow->getCurrentMouse();
+			glReadPixels(coord.mX, coord.mY, 1,1,GL_RGBA, GL_UNSIGNED_BYTE, color);
+			addText(xpos, ypos, llformat("%d %d %d %d", color[0], color[1], color[2], color[3]));
+			ypos += y_inc;
+		}
+
+		if (gSavedSettings.getBOOL("DebugShowPrivateMem"))
+		{
+			LLPrivateMemoryPoolManager::getInstance()->updateStatistics() ;
+			addText(xpos, ypos, llformat("Total Reserved(KB): %d", LLPrivateMemoryPoolManager::getInstance()->mTotalReservedSize / 1024));
+			ypos += y_inc;
+
+			addText(xpos, ypos, llformat("Total Allocated(KB): %d", LLPrivateMemoryPoolManager::getInstance()->mTotalAllocatedSize / 1024));
+			ypos += y_inc;
+		}
+
+		// only display these messages if we are actually rendering beacons at this moment
+		if (LLPipeline::getRenderBeacons(NULL) && LLFloaterReg::instanceVisible("beacons"))
+		{
+			if (LLPipeline::getRenderMOAPBeacons(NULL))
+			{
+				addText(xpos, ypos, "Viewing media beacons (white)");
+				ypos += y_inc;
+			}
+
+			if (LLPipeline::toggleRenderTypeControlNegated((void*)LLPipeline::RENDER_TYPE_PARTICLES))
+			{
+				addText(xpos, ypos, particle_hiding);
+				ypos += y_inc;
+			}
+
+			if (LLPipeline::getRenderParticleBeacons(NULL))
+			{
+				addText(xpos, ypos, "Viewing particle beacons (blue)");
+				ypos += y_inc;
+			}
+
+			if (LLPipeline::getRenderSoundBeacons(NULL))
+			{
+				addText(xpos, ypos, "Viewing sound beacons (yellow)");
+				ypos += y_inc;
+			}
+
+			if (LLPipeline::getRenderScriptedBeacons(NULL))
+			{
+				addText(xpos, ypos, beacon_scripted);
+				ypos += y_inc;
+			}
+			else
+				if (LLPipeline::getRenderScriptedTouchBeacons(NULL))
+				{
+					addText(xpos, ypos, beacon_scripted_touch);
+					ypos += y_inc;
+				}
+
+			if (LLPipeline::getRenderPhysicalBeacons(NULL))
+			{
+				addText(xpos, ypos, "Viewing physical object beacons (green)");
+				ypos += y_inc;
+			}
+		}
+
+		if(log_texture_traffic)
+		{	
+			U32 old_y = ypos ;
+			for(S32 i = LLViewerTexture::BOOST_NONE; i < LLViewerTexture::MAX_GL_IMAGE_CATEGORY; i++)
+			{
+				if(gTotalTextureBytesPerBoostLevel[i] > 0)
+				{
+					addText(xpos, ypos, llformat("Boost_Level %d:  %.3f MB", i, (F32)gTotalTextureBytesPerBoostLevel[i] / (1024 * 1024)));
+					ypos += y_inc;
+				}
+			}
+			if(ypos != old_y)
+			{
+				addText(xpos, ypos, "Network traffic for textures:");
+				ypos += y_inc;
+			}
+		}				
+
+		if (gSavedSettings.getBOOL("DebugShowTextureInfo"))
+		{
+			LLViewerObject* objectp = NULL ;
+			//objectp = = gAgentCamera.getFocusObject();
+			
+			LLSelectNode* nodep = LLSelectMgr::instance().getHoverNode();
+			if (nodep)
+			{
+				objectp = nodep->getObject();			
+			}
+			if (objectp && !objectp->isDead())
+			{
+				S32 num_faces = objectp->mDrawable->getNumFaces() ;
+				
+				for(S32 i = 0 ; i < num_faces; i++)
+				{
+					LLFace* facep = objectp->mDrawable->getFace(i) ;
+					if(facep)
+					{
+						//addText(xpos, ypos, llformat("ts_min: %.3f ts_max: %.3f tt_min: %.3f tt_max: %.3f", facep->mTexExtents[0].mV[0], facep->mTexExtents[1].mV[0],
+						//		facep->mTexExtents[0].mV[1], facep->mTexExtents[1].mV[1]));
+						//ypos += y_inc;
+						
+						addText(xpos, ypos, llformat("v_size: %.3f:  p_size: %.3f", facep->getVirtualSize(), facep->getPixelArea()));
+						ypos += y_inc;
+						
+						//const LLTextureEntry *tep = facep->getTextureEntry();
+						//if(tep)
+						//{
+						//	addText(xpos, ypos, llformat("scale_s: %.3f:  scale_t: %.3f", tep->mScaleS, tep->mScaleT)) ;
+						//	ypos += y_inc;
+						//}
+						
+						LLViewerTexture* tex = facep->getTexture() ;
+						if(tex)
+						{
+							addText(xpos, ypos, llformat("ID: %s v_size: %.3f", tex->getID().asString().c_str(), tex->getMaxVirtualSize()));
+							ypos += y_inc;
+						}
+					}
+				}
+			}
+		}
+	}
+
+	void draw()
+	{
+		for (line_list_t::iterator iter = mLineList.begin();
+			 iter != mLineList.end(); ++iter)
+		{
+			const Line& line = *iter;
+			LLFontGL::getFontMonospace()->renderUTF8(line.text, 0, (F32)line.x, (F32)line.y, mTextColor,
+											 LLFontGL::LEFT, LLFontGL::TOP,
+											 LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE);
+		}
+		mLineList.clear();
+	}
+
+};
+
+void LLViewerWindow::updateDebugText()
+{
+	mDebugText->update();
+}
+
+////////////////////////////////////////////////////////////////////////////
+//
+// LLViewerWindow
+//
+
+LLViewerWindow::Params::Params()
+:	title("title"),
+	name("name"),
+	x("x"),
+	y("y"),
+	width("width"),
+	height("height"),
+	min_width("min_width"),
+	min_height("min_height"),
+	fullscreen("fullscreen", false),
+	ignore_pixel_depth("ignore_pixel_depth", false)
+{}
+
+
+BOOL LLViewerWindow::handleAnyMouseClick(LLWindow *window,  LLCoordGL pos, MASK mask, LLMouseHandler::EClickType clicktype, BOOL down)
+{
+	const char* buttonname = "";
+	const char* buttonstatestr = "";
+	S32 x = pos.mX;
+	S32 y = pos.mY;
+	x = llround((F32)x / mDisplayScale.mV[VX]);
+	y = llround((F32)y / mDisplayScale.mV[VY]);
+
+				
+	// only send mouse clicks to UI if UI is visible
+	if(gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
+	{	
+
+		if (down)
+		{
+			buttonstatestr = "down" ;
+		}
+		else
+		{
+			buttonstatestr = "up" ;
+		}
+		
+		switch (clicktype)
+		{
+		case LLMouseHandler::CLICK_LEFT:
+			mLeftMouseDown = down;
+			buttonname = "Left";
+			break;
+		case LLMouseHandler::CLICK_RIGHT:
+			mRightMouseDown = down;
+			buttonname = "Right";
+			break;
+		case LLMouseHandler::CLICK_MIDDLE:
+			mMiddleMouseDown = down;
+			buttonname = "Middle";
+			break;
+		case LLMouseHandler::CLICK_DOUBLELEFT:
+			mLeftMouseDown = down;
+			buttonname = "Left Double Click";
+			break;
+		}
+		
+		LLView::sMouseHandlerMessage.clear();
+
+		if (gMenuBarView)
+		{
+			// stop ALT-key access to menu
+			gMenuBarView->resetMenuTrigger();
+		}
+
+		if (gDebugClicks)
+		{	
+			llinfos << "ViewerWindow " << buttonname << " mouse " << buttonstatestr << " at " << x << "," << y << llendl;
+		}
+
+		// Make sure we get a corresponding mouseup event, even if the mouse leaves the window
+		if (down)
+			mWindow->captureMouse();
+		else
+			mWindow->releaseMouse();
+
+		// Indicate mouse was active
+		LLUI::resetMouseIdleTimer();
+
+		// Don't let the user move the mouse out of the window until mouse up.
+		if( LLToolMgr::getInstance()->getCurrentTool()->clipMouseWhenDown() )
+		{
+			mWindow->setMouseClipping(down);
+		}
+
+		LLMouseHandler* mouse_captor = gFocusMgr.getMouseCapture();
+		if( mouse_captor )
+		{
+			S32 local_x;
+			S32 local_y;
+			mouse_captor->screenPointToLocal( x, y, &local_x, &local_y );
+			if (LLView::sDebugMouseHandling)
+			{
+				llinfos << buttonname << " Mouse " << buttonstatestr << " handled by captor " << mouse_captor->getName() << llendl;
+			}
+			return mouse_captor->handleAnyMouseClick(local_x, local_y, mask, clicktype, down);
+		}
+
+		// Topmost view gets a chance before the hierarchy
+		//LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl();
+		//if (top_ctrl)
+		//{
+		//	S32 local_x, local_y;
+		//	top_ctrl->screenPointToLocal( x, y, &local_x, &local_y );
+		//		if (top_ctrl->pointInView(local_x, local_y))
+		//		{
+		//			return top_ctrl->handleAnyMouseClick(local_x, local_y, mask, clicktype, down)	;
+		//		}
+		//		else
+		//		{
+		//		if (down)
+		//		{
+		//			gFocusMgr.setTopCtrl(NULL);
+		//		}
+		//	}
+		//}
+
+		// Mark the click as handled and return if we aren't within the root view to avoid spurious bugs
+		if( !mRootView->pointInView(x, y) )
+		{
+			return TRUE;
+		}
+		// Give the UI views a chance to process the click
+		if( mRootView->handleAnyMouseClick(x, y, mask, clicktype, down) )
+		{
+			if (LLView::sDebugMouseHandling)
+			{
+				llinfos << buttonname << " Mouse " << buttonstatestr << " " << LLView::sMouseHandlerMessage << llendl;
+			}
+			return TRUE;
+		}
+		else if (LLView::sDebugMouseHandling)
+		{
+			llinfos << buttonname << " Mouse " << buttonstatestr << " not handled by view" << llendl;
+		}
+	}
+
+
+	//Determine if we have a pathing system and subsequently provide any mouse input
+	if ( LLPathingLib::getInstance() && mLeftMouseDown == down )
+	{
+		LLVector3 dv		= mouseDirectionGlobal(x,y);
+		LLVector3 mousePos	= LLViewerCamera::getInstance()->getOrigin();
+		LLVector3 rayStart	= mousePos;
+		LLVector3 rayEnd	= mousePos + dv * 150;
+	
+		//Determine if alt is being held in conjunction with a lmb click, if alt is being held
+		//then do not provide any input to the pathingLib console
+		MASK currentKeyMask = gKeyboard->currentMask(TRUE);
+		if ( !(currentKeyMask & MASK_ALT) )
+		{
+			LLFloaterPathfindingConsole* pFloater = LLFloaterReg::getTypedInstance<LLFloaterPathfindingConsole>("pathfinding_console");
+			if ( pFloater )
+			{
+				//The floater takes care of determining what stage - essentially where the data goes into the pathing packet(start or end)
+				pFloater->providePathingData( rayStart, rayEnd );
+			}
+		}
+	}
+
+	// Do not allow tool manager to handle mouseclicks if we have disconnected	
+	if(!gDisconnected && LLToolMgr::getInstance()->getCurrentTool()->handleAnyMouseClick( x, y, mask, clicktype, down ) )
+	{
+		return TRUE;
+	}
+	
+
+	// If we got this far on a down-click, it wasn't handled.
+	// Up-clicks, though, are always handled as far as the OS is concerned.
+	BOOL default_rtn = !down;
+	return default_rtn;
+}
+
+BOOL LLViewerWindow::handleMouseDown(LLWindow *window,  LLCoordGL pos, MASK mask)
+{
+	BOOL down = TRUE;
+	return handleAnyMouseClick(window,pos,mask,LLMouseHandler::CLICK_LEFT,down);
+}
+
+BOOL LLViewerWindow::handleDoubleClick(LLWindow *window,  LLCoordGL pos, MASK mask)
+{
+	// try handling as a double-click first, then a single-click if that
+	// wasn't handled.
+	BOOL down = TRUE;
+	if (handleAnyMouseClick(window, pos, mask,
+				LLMouseHandler::CLICK_DOUBLELEFT, down))
+	{
+		return TRUE;
+	}
+	return handleMouseDown(window, pos, mask);
+}
+
+BOOL LLViewerWindow::handleMouseUp(LLWindow *window,  LLCoordGL pos, MASK mask)
+{
+	BOOL down = FALSE;
+	return handleAnyMouseClick(window,pos,mask,LLMouseHandler::CLICK_LEFT,down);
+}
+
+
+BOOL LLViewerWindow::handleRightMouseDown(LLWindow *window,  LLCoordGL pos, MASK mask)
+{
+	S32 x = pos.mX;
+	S32 y = pos.mY;
+	x = llround((F32)x / mDisplayScale.mV[VX]);
+	y = llround((F32)y / mDisplayScale.mV[VY]);
+
+	BOOL down = TRUE;
+	BOOL handle = handleAnyMouseClick(window,pos,mask,LLMouseHandler::CLICK_RIGHT,down);
+	if (handle)
+		return handle;
+
+	// *HACK: this should be rolled into the composite tool logic, not
+	// hardcoded at the top level.
+	if (CAMERA_MODE_CUSTOMIZE_AVATAR != gAgentCamera.getCameraMode() && LLToolMgr::getInstance()->getCurrentTool() != LLToolPie::getInstance())
+	{
+		// If the current tool didn't process the click, we should show
+		// the pie menu.  This can be done by passing the event to the pie
+		// menu tool.
+		LLToolPie::getInstance()->handleRightMouseDown(x, y, mask);
+		// show_context_menu( x, y, mask );
+	}
+
+	return TRUE;
+}
+
+BOOL LLViewerWindow::handleRightMouseUp(LLWindow *window,  LLCoordGL pos, MASK mask)
+{
+	BOOL down = FALSE;
+ 	return handleAnyMouseClick(window,pos,mask,LLMouseHandler::CLICK_RIGHT,down);
+}
+
+BOOL LLViewerWindow::handleMiddleMouseDown(LLWindow *window,  LLCoordGL pos, MASK mask)
+{
+	BOOL down = TRUE;
+	LLVoiceClient::getInstance()->middleMouseState(true);
+ 	handleAnyMouseClick(window,pos,mask,LLMouseHandler::CLICK_MIDDLE,down);
+  
+  	// Always handled as far as the OS is concerned.
+	return TRUE;
+}
+
+LLWindowCallbacks::DragNDropResult LLViewerWindow::handleDragNDrop( LLWindow *window, LLCoordGL pos, MASK mask, LLWindowCallbacks::DragNDropAction action, std::string data)
+{
+	LLWindowCallbacks::DragNDropResult result = LLWindowCallbacks::DND_NONE;
+
+	const bool prim_media_dnd_enabled = gSavedSettings.getBOOL("PrimMediaDragNDrop");
+	const bool slurl_dnd_enabled = gSavedSettings.getBOOL("SLURLDragNDrop");
+	
+	if ( prim_media_dnd_enabled || slurl_dnd_enabled )
+	{
+		switch(action)
+		{
+			// Much of the handling for these two cases is the same.
+			case LLWindowCallbacks::DNDA_TRACK:
+			case LLWindowCallbacks::DNDA_DROPPED:
+			case LLWindowCallbacks::DNDA_START_TRACKING:
+			{
+				bool drop = (LLWindowCallbacks::DNDA_DROPPED == action);
+					
+				if (slurl_dnd_enabled)
+				{
+					LLSLURL dropped_slurl(data);
+					if(dropped_slurl.isSpatial())
+					{
+						if (drop)
+						{
+							LLURLDispatcher::dispatch( dropped_slurl.getSLURLString(), "clicked", NULL, true );
+							return LLWindowCallbacks::DND_MOVE;
+						}
+						return LLWindowCallbacks::DND_COPY;
+					}
+				}
+
+				if (prim_media_dnd_enabled)
+				{
+					LLPickInfo pick_info = pickImmediate( pos.mX, pos.mY,  TRUE /*BOOL pick_transparent*/ );
+
+					LLUUID object_id = pick_info.getObjectID();
+					S32 object_face = pick_info.mObjectFace;
+					std::string url = data;
+
+					lldebugs << "Object: picked at " << pos.mX << ", " << pos.mY << " - face = " << object_face << " - URL = " << url << llendl;
+
+					LLVOVolume *obj = dynamic_cast<LLVOVolume*>(static_cast<LLViewerObject*>(pick_info.getObject()));
+				
+					if (obj && !obj->getRegion()->getCapability("ObjectMedia").empty())
+					{
+						LLTextureEntry *te = obj->getTE(object_face);
+
+						// can modify URL if we can modify the object or we have navigate permissions
+						bool allow_modify_url = obj->permModify() || obj->hasMediaPermission( te->getMediaData(), LLVOVolume::MEDIA_PERM_INTERACT );
+
+						if (te && allow_modify_url )
+						{
+							if (drop)
+							{
+								// object does NOT have media already
+								if ( ! te->hasMedia() )
+								{
+									// we are allowed to modify the object
+									if ( obj->permModify() )
+									{
+										// Create new media entry
+										LLSD media_data;
+										// XXX Should we really do Home URL too?
+										media_data[LLMediaEntry::HOME_URL_KEY] = url;
+										media_data[LLMediaEntry::CURRENT_URL_KEY] = url;
+										media_data[LLMediaEntry::AUTO_PLAY_KEY] = true;
+										obj->syncMediaData(object_face, media_data, true, true);
+										// XXX This shouldn't be necessary, should it ?!?
+										if (obj->getMediaImpl(object_face))
+											obj->getMediaImpl(object_face)->navigateReload();
+										obj->sendMediaDataUpdate();
+
+										result = LLWindowCallbacks::DND_COPY;
+									}
+								}
+								else 
+								// object HAS media already
+								{
+									// URL passes the whitelist
+									if (te->getMediaData()->checkCandidateUrl( url ) )
+									{
+										// just navigate to the URL
+										if (obj->getMediaImpl(object_face))
+										{
+											obj->getMediaImpl(object_face)->navigateTo(url);
+										}
+										else 
+										{
+											// This is very strange.  Navigation should
+											// happen via the Impl, but we don't have one.
+											// This sends it to the server, which /should/
+											// trigger us getting it.  Hopefully.
+											LLSD media_data;
+											media_data[LLMediaEntry::CURRENT_URL_KEY] = url;
+											obj->syncMediaData(object_face, media_data, true, true);
+											obj->sendMediaDataUpdate();
+										}
+										result = LLWindowCallbacks::DND_LINK;
+										
+									}
+								}
+								LLSelectMgr::getInstance()->unhighlightObjectOnly(mDragHoveredObject);
+								mDragHoveredObject = NULL;
+							
+							}
+							else 
+							{
+								// Check the whitelist, if there's media (otherwise just show it)
+								if (te->getMediaData() == NULL || te->getMediaData()->checkCandidateUrl(url))
+								{
+									if ( obj != mDragHoveredObject)
+									{
+										// Highlight the dragged object
+										LLSelectMgr::getInstance()->unhighlightObjectOnly(mDragHoveredObject);
+										mDragHoveredObject = obj;
+										LLSelectMgr::getInstance()->highlightObjectOnly(mDragHoveredObject);
+									}
+									result = (! te->hasMedia()) ? LLWindowCallbacks::DND_COPY : LLWindowCallbacks::DND_LINK;
+
+								}
+							}
+						}
+					}
+				}
+			}
+			break;
+			
+			case LLWindowCallbacks::DNDA_STOP_TRACKING:
+				// The cleanup case below will make sure things are unhilighted if necessary.
+			break;
+		}
+
+		if (prim_media_dnd_enabled &&
+			result == LLWindowCallbacks::DND_NONE && !mDragHoveredObject.isNull())
+		{
+			LLSelectMgr::getInstance()->unhighlightObjectOnly(mDragHoveredObject);
+			mDragHoveredObject = NULL;
+		}
+	}
+	
+	return result;
+}
+  
+BOOL LLViewerWindow::handleMiddleMouseUp(LLWindow *window,  LLCoordGL pos, MASK mask)
+{
+	BOOL down = FALSE;
+	LLVoiceClient::getInstance()->middleMouseState(false);
+ 	handleAnyMouseClick(window,pos,mask,LLMouseHandler::CLICK_MIDDLE,down);
+  
+  	// Always handled as far as the OS is concerned.
+	return TRUE;
+}
+
+// WARNING: this is potentially called multiple times per frame
+void LLViewerWindow::handleMouseMove(LLWindow *window,  LLCoordGL pos, MASK mask)
+{
+	S32 x = pos.mX;
+	S32 y = pos.mY;
+
+	x = llround((F32)x / mDisplayScale.mV[VX]);
+	y = llround((F32)y / mDisplayScale.mV[VY]);
+
+	mMouseInWindow = TRUE;
+
+	// Save mouse point for access during idle() and display()
+
+	LLCoordGL mouse_point(x, y);
+
+	if (mouse_point != mCurrentMousePoint)
+	{
+		LLUI::resetMouseIdleTimer();
+	}
+
+	saveLastMouse(mouse_point);
+
+	mWindow->showCursorFromMouseMove();
+
+	if (gAwayTimer.getElapsedTimeF32() > LLAgent::MIN_AFK_TIME
+		&& !gDisconnected)
+	{
+		gAgent.clearAFK();
+	}
+}
+
+void LLViewerWindow::handleMouseLeave(LLWindow *window)
+{
+	// Note: we won't get this if we have captured the mouse.
+	llassert( gFocusMgr.getMouseCapture() == NULL );
+	mMouseInWindow = FALSE;
+	LLToolTipMgr::instance().blockToolTips();
+}
+
+BOOL LLViewerWindow::handleCloseRequest(LLWindow *window)
+{
+	// User has indicated they want to close, but we may need to ask
+	// about modified documents.
+	LLAppViewer::instance()->userQuit();
+	// Don't quit immediately
+	return FALSE;
+}
+
+void LLViewerWindow::handleQuit(LLWindow *window)
+{
+	LLAppViewer::instance()->forceQuit();
+}
+
+void LLViewerWindow::handleResize(LLWindow *window,  S32 width,  S32 height)
+{
+	reshape(width, height);
+	mResDirty = true;
+}
+
+// The top-level window has gained focus (e.g. via ALT-TAB)
+void LLViewerWindow::handleFocus(LLWindow *window)
+{
+	gFocusMgr.setAppHasFocus(TRUE);
+	LLModalDialog::onAppFocusGained();
+
+	gAgent.onAppFocusGained();
+	LLToolMgr::getInstance()->onAppFocusGained();
+
+	// See if we're coming in with modifier keys held down
+	if (gKeyboard)
+	{
+		gKeyboard->resetMaskKeys();
+	}
+
+	// resume foreground running timer
+	// since we artifically limit framerate when not frontmost
+	gForegroundTime.unpause();
+}
+
+// The top-level window has lost focus (e.g. via ALT-TAB)
+void LLViewerWindow::handleFocusLost(LLWindow *window)
+{
+	gFocusMgr.setAppHasFocus(FALSE);
+	//LLModalDialog::onAppFocusLost();
+	LLToolMgr::getInstance()->onAppFocusLost();
+	gFocusMgr.setMouseCapture( NULL );
+
+	if (gMenuBarView)
+	{
+		// stop ALT-key access to menu
+		gMenuBarView->resetMenuTrigger();
+	}
+
+	// restore mouse cursor
+	showCursor();
+	getWindow()->setMouseClipping(FALSE);
+
+	// If losing focus while keys are down, reset them.
+	if (gKeyboard)
+	{
+		gKeyboard->resetKeys();
+	}
+
+	// pause timer that tracks total foreground running time
+	gForegroundTime.pause();
+}
+
+
+BOOL LLViewerWindow::handleTranslatedKeyDown(KEY key,  MASK mask, BOOL repeated)
+{
+	// Let the voice chat code check for its PTT key.  Note that this never affects event processing.
+	LLVoiceClient::getInstance()->keyDown(key, mask);
+	
+	if (gAwayTimer.getElapsedTimeF32() > LLAgent::MIN_AFK_TIME)
+	{
+		gAgent.clearAFK();
+	}
+
+	// *NOTE: We want to interpret KEY_RETURN later when it arrives as
+	// a Unicode char, not as a keydown.  Otherwise when client frame
+	// rate is really low, hitting return sends your chat text before
+	// it's all entered/processed.
+	if (key == KEY_RETURN && mask == MASK_NONE)
+	{
+		return FALSE;
+	}
+
+	return gViewerKeyboard.handleKey(key, mask, repeated);
+}
+
+BOOL LLViewerWindow::handleTranslatedKeyUp(KEY key,  MASK mask)
+{
+	// Let the voice chat code check for its PTT key.  Note that this never affects event processing.
+	LLVoiceClient::getInstance()->keyUp(key, mask);
+
+	return FALSE;
+}
+
+
+void LLViewerWindow::handleScanKey(KEY key, BOOL key_down, BOOL key_up, BOOL key_level)
+{
+	LLViewerJoystick::getInstance()->setCameraNeedsUpdate(true);
+	return gViewerKeyboard.scanKey(key, key_down, key_up, key_level);
+}
+
+
+
+
+BOOL LLViewerWindow::handleActivate(LLWindow *window, BOOL activated)
+{
+	if (activated)
+	{
+		mActive = true;
+		send_agent_resume();
+		gAgent.clearAFK();
+		
+		// Unmute audio
+		audio_update_volume();
+	}
+	else
+	{
+		mActive = false;
+				
+		// if the user has chosen to go Away automatically after some time, then go Away when minimizing
+		if (gSavedSettings.getS32("AFKTimeout"))
+		{
+			gAgent.setAFK();
+		}
+		
+		// SL-53351: Make sure we're not in mouselook when minimised, to prevent control issues
+		if (gAgentCamera.getCameraMode() == CAMERA_MODE_MOUSELOOK)
+		{
+			gAgentCamera.changeCameraToDefault();
+		}
+		
+		send_agent_pause();
+	
+		// Mute audio
+		audio_update_volume();
+	}
+	return TRUE;
+}
+
+BOOL LLViewerWindow::handleActivateApp(LLWindow *window, BOOL activating)
+{
+	//if (!activating) gAgentCamera.changeCameraToDefault();
+
+	LLViewerJoystick::getInstance()->setNeedsReset(true);
+	return FALSE;
+}
+
+
+void LLViewerWindow::handleMenuSelect(LLWindow *window,  S32 menu_item)
+{
+}
+
+
+BOOL LLViewerWindow::handlePaint(LLWindow *window,  S32 x,  S32 y, S32 width,  S32 height)
+{
+	// *TODO: Enable similar information output for other platforms?  DK 2011-02-18
+#if LL_WINDOWS
+	if (gHeadlessClient)
+	{
+		HWND window_handle = (HWND)window->getPlatformWindow();
+		PAINTSTRUCT ps; 
+		HDC hdc; 
+ 
+		RECT wnd_rect;
+		wnd_rect.left = 0;
+		wnd_rect.top = 0;
+		wnd_rect.bottom = 200;
+		wnd_rect.right = 500;
+
+		hdc = BeginPaint(window_handle, &ps); 
+		//SetBKColor(hdc, RGB(255, 255, 255));
+		FillRect(hdc, &wnd_rect, CreateSolidBrush(RGB(255, 255, 255)));
+
+		std::string temp_str;
+		temp_str = llformat( "FPS %3.1f Phy FPS %2.1f Time Dil %1.3f",		/* Flawfinder: ignore */
+				LLViewerStats::getInstance()->mFPSStat.getMeanPerSec(),
+				LLViewerStats::getInstance()->mSimPhysicsFPS.getPrev(0),
+				LLViewerStats::getInstance()->mSimTimeDilation.getPrev(0));
+		S32 len = temp_str.length();
+		TextOutA(hdc, 0, 0, temp_str.c_str(), len); 
+
+
+		LLVector3d pos_global = gAgent.getPositionGlobal();
+		temp_str = llformat( "Avatar pos %6.1lf %6.1lf %6.1lf", pos_global.mdV[0], pos_global.mdV[1], pos_global.mdV[2]);
+		len = temp_str.length();
+		TextOutA(hdc, 0, 25, temp_str.c_str(), len); 
+
+		TextOutA(hdc, 0, 50, "Set \"HeadlessClient FALSE\" in settings.ini file to reenable", 61);
+		EndPaint(window_handle, &ps); 
+		return TRUE;
+	}
+#endif
+	return FALSE;
+}
+
+
+void LLViewerWindow::handleScrollWheel(LLWindow *window,  S32 clicks)
+{
+	handleScrollWheel( clicks );
+}
+
+void LLViewerWindow::handleWindowBlock(LLWindow *window)
+{
+	send_agent_pause();
+}
+
+void LLViewerWindow::handleWindowUnblock(LLWindow *window)
+{
+	send_agent_resume();
+}
+
+void LLViewerWindow::handleDataCopy(LLWindow *window, S32 data_type, void *data)
+{
+	const S32 SLURL_MESSAGE_TYPE = 0;
+	switch (data_type)
+	{
+	case SLURL_MESSAGE_TYPE:
+		// received URL
+		std::string url = (const char*)data;
+		LLMediaCtrl* web = NULL;
+		const bool trusted_browser = false;
+		// don't treat slapps coming from external browsers as "clicks" as this would bypass throttling
+		if (LLURLDispatcher::dispatch(url, "", web, trusted_browser))
+		{
+			// bring window to foreground, as it has just been "launched" from a URL
+			mWindow->bringToFront();
+		}
+		break;
+	}
+}
+
+BOOL LLViewerWindow::handleTimerEvent(LLWindow *window)
+{
+	if (LLViewerJoystick::getInstance()->getOverrideCamera())
+	{
+		LLViewerJoystick::getInstance()->updateStatus();
+		return TRUE;
+	}
+	return FALSE;
+}
+
+BOOL LLViewerWindow::handleDeviceChange(LLWindow *window)
+{
+	// give a chance to use a joystick after startup (hot-plugging)
+	if (!LLViewerJoystick::getInstance()->isJoystickInitialized() )
+	{
+		LLViewerJoystick::getInstance()->init(true);
+		return TRUE;
+	}
+	return FALSE;
+}
+
+void LLViewerWindow::handlePingWatchdog(LLWindow *window, const char * msg)
+{
+	LLAppViewer::instance()->pingMainloopTimeout(msg);
+}
+
+
+void LLViewerWindow::handleResumeWatchdog(LLWindow *window)
+{
+	LLAppViewer::instance()->resumeMainloopTimeout();
+}
+
+void LLViewerWindow::handlePauseWatchdog(LLWindow *window)
+{
+	LLAppViewer::instance()->pauseMainloopTimeout();
+}
+
+//virtual
+std::string LLViewerWindow::translateString(const char* tag)
+{
+	return LLTrans::getString( std::string(tag) );
+}
+
+//virtual
+std::string LLViewerWindow::translateString(const char* tag,
+		const std::map<std::string, std::string>& args)
+{
+	// LLTrans uses a special subclass of std::string for format maps,
+	// but we must use std::map<> in these callbacks, otherwise we create
+	// a dependency between LLWindow and LLFormatMapString.  So copy the data.
+	LLStringUtil::format_map_t args_copy;
+	std::map<std::string,std::string>::const_iterator it = args.begin();
+	for ( ; it != args.end(); ++it)
+	{
+		args_copy[it->first] = it->second;
+	}
+	return LLTrans::getString( std::string(tag), args_copy);
+}
+
+//
+// Classes
+//
+LLViewerWindow::LLViewerWindow(const Params& p)
+:	mWindow(NULL),
+	mActive(true),
+	mUIVisible(true),
+	mWindowRectRaw(0, p.height, p.width, 0),
+	mWindowRectScaled(0, p.height, p.width, 0),
+	mWorldViewRectRaw(0, p.height, p.width, 0),
+	mLeftMouseDown(FALSE),
+	mMiddleMouseDown(FALSE),
+	mRightMouseDown(FALSE),
+	mMouseInWindow( FALSE ),
+	mLastMask( MASK_NONE ),
+	mToolStored( NULL ),
+	mHideCursorPermanent( FALSE ),
+	mCursorHidden(FALSE),
+	mIgnoreActivate( FALSE ),
+	mResDirty(false),
+	mStatesDirty(false),
+	mCurrResolutionIndex(0),
+	// gKeyboard is still NULL, so it doesn't do LLWindowListener any good to
+	// pass its value right now. Instead, pass it a nullary function that
+	// will, when we later need it, return the value of gKeyboard.
+	// boost::lambda::var() constructs such a functor on the fly.
+	mWindowListener(new LLWindowListener(this, boost::lambda::var(gKeyboard))),
+	mViewerWindowListener(new LLViewerWindowListener(this)),
+	mProgressView(NULL)
+{
+	LLNotificationChannel::buildChannel("VW_alerts", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "alert"));
+	LLNotificationChannel::buildChannel("VW_alertmodal", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "alertmodal"));
+
+	LLNotifications::instance().getChannel("VW_alerts")->connectChanged(&LLViewerWindow::onAlert);
+	LLNotifications::instance().getChannel("VW_alertmodal")->connectChanged(&LLViewerWindow::onAlert);
+	LLNotifications::instance().setIgnoreAllNotifications(gSavedSettings.getBOOL("IgnoreAllNotifications"));
+	llinfos << "NOTE: ALL NOTIFICATIONS THAT OCCUR WILL GET ADDED TO IGNORE LIST FOR LATER RUNS." << llendl;
+
+	// Default to application directory.
+	LLViewerWindow::sSnapshotBaseName = "Snapshot";
+	LLViewerWindow::sMovieBaseName = "SLmovie";
+	resetSnapshotLoc();
+
+	// create window
+	mWindow = LLWindowManager::createWindow(this,
+		p.title, p.name, p.x, p.y, p.width, p.height, 0,
+		p.fullscreen, 
+		gHeadlessClient,
+		gSavedSettings.getBOOL("DisableVerticalSync"),
+		!gHeadlessClient,
+		p.ignore_pixel_depth,
+		gSavedSettings.getBOOL("RenderDeferred") ? 0 : gSavedSettings.getU32("RenderFSAASamples")); //don't use window level anti-aliasing if FBOs are enabled
+
+	if (!LLViewerShaderMgr::sInitialized)
+	{ //immediately initialize shaders
+		LLViewerShaderMgr::sInitialized = TRUE;
+		LLViewerShaderMgr::instance()->setShaders();
+	}
+
+	if (NULL == mWindow)
+	{
+		LLSplashScreen::update(LLTrans::getString("StartupRequireDriverUpdate"));
+	
+		LL_WARNS("Window") << "Failed to create window, to be shutting Down, be sure your graphics driver is updated." << llendl ;
+
+		ms_sleep(5000) ; //wait for 5 seconds.
+
+		LLSplashScreen::update(LLTrans::getString("ShuttingDown"));
+#if LL_LINUX || LL_SOLARIS
+		llwarns << "Unable to create window, be sure screen is set at 32-bit color and your graphics driver is configured correctly.  See README-linux.txt or README-solaris.txt for further information."
+				<< llendl;
+#else
+		LL_WARNS("Window") << "Unable to create window, be sure screen is set at 32-bit color in Control Panels->Display->Settings"
+				<< LL_ENDL;
+#endif
+        LLAppViewer::instance()->fastQuit(1);
+	}
+	
+	if (!LLAppViewer::instance()->restoreErrorTrap())
+	{
+		LL_WARNS("Window") << " Someone took over my signal/exception handler (post createWindow)!" << LL_ENDL;
+	}
+
+	const bool do_not_enforce = false;
+	mWindow->setMinSize(p.min_width, p.min_height, do_not_enforce);  // root view not set 
+	LLCoordScreen scr;
+    mWindow->getSize(&scr);
+
+    if(p.fullscreen && ( scr.mX!=p.width || scr.mY!=p.height))
+    {
+		llwarns << "Fullscreen has forced us in to a different resolution now using "<<scr.mX<<" x "<<scr.mY<<llendl;
+		gSavedSettings.setS32("FullScreenWidth",scr.mX);
+		gSavedSettings.setS32("FullScreenHeight",scr.mY);
+    }
+
+	// Get the real window rect the window was created with (since there are various OS-dependent reasons why
+	// the size of a window or fullscreen context may have been adjusted slightly...)
+	F32 ui_scale_factor = gSavedSettings.getF32("UIScaleFactor");
+	
+	mDisplayScale.setVec(llmax(1.f / mWindow->getPixelAspectRatio(), 1.f), llmax(mWindow->getPixelAspectRatio(), 1.f));
+	mDisplayScale *= ui_scale_factor;
+	LLUI::setScaleFactor(mDisplayScale);
+
+	{
+		LLCoordWindow size;
+		mWindow->getSize(&size);
+		mWindowRectRaw.set(0, size.mY, size.mX, 0);
+		mWindowRectScaled.set(0, llround((F32)size.mY / mDisplayScale.mV[VY]), llround((F32)size.mX / mDisplayScale.mV[VX]), 0);
+	}
+	
+	LLFontManager::initClass();
+
+	//
+	// We want to set this stuff up BEFORE we initialize the pipeline, so we can turn off
+	// stuff like AGP if we think that it'll crash the viewer.
+	//
+	LL_DEBUGS("Window") << "Loading feature tables." << LL_ENDL;
+
+	LLFeatureManager::getInstance()->init();
+
+	// Initialize OpenGL Renderer
+	if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderVBOEnable") ||
+		!gGLManager.mHasVertexBufferObject)
+	{
+		gSavedSettings.setBOOL("RenderVBOEnable", FALSE);
+	}
+	LLVertexBuffer::initClass(gSavedSettings.getBOOL("RenderVBOEnable"), gSavedSettings.getBOOL("RenderVBOMappingDisable"));
+	LL_INFOS("RenderInit") << "LLVertexBuffer initialization done." << LL_ENDL ;
+	gGL.init() ;
+
+	if (LLFeatureManager::getInstance()->isSafe()
+		|| (gSavedSettings.getS32("LastFeatureVersion") != LLFeatureManager::getInstance()->getVersion())
+		|| (gSavedSettings.getString("LastGPUString") != LLFeatureManager::getInstance()->getGPUString())
+		|| (gSavedSettings.getBOOL("ProbeHardwareOnStartup")))
+	{
+		LLFeatureManager::getInstance()->applyRecommendedSettings();
+		gSavedSettings.setBOOL("ProbeHardwareOnStartup", FALSE);
+	}
+
+	if (!gGLManager.mHasDepthClamp)
+	{
+		LL_INFOS("RenderInit") << "Missing feature GL_ARB_depth_clamp. Void water might disappear in rare cases." << LL_ENDL;
+	}
+	
+	// If we crashed while initializng GL stuff last time, disable certain features
+	if (gSavedSettings.getBOOL("RenderInitError"))
+	{
+		mInitAlert = "DisplaySettingsNoShaders";
+		LLFeatureManager::getInstance()->setGraphicsLevel(0, false);
+		gSavedSettings.setU32("RenderQualityPerformance", 0);		
+	}
+		
+	// Init the image list.  Must happen after GL is initialized and before the images that
+	// LLViewerWindow needs are requested.
+	LLImageGL::initClass(LLViewerTexture::MAX_GL_IMAGE_CATEGORY) ;
+	gTextureList.init();
+	LLViewerTextureManager::init() ;
+	gBumpImageList.init();
+	
+	// Init font system, but don't actually load the fonts yet
+	// because our window isn't onscreen and they take several
+	// seconds to parse.
+	LLFontGL::initClass( gSavedSettings.getF32("FontScreenDPI"),
+								mDisplayScale.mV[VX],
+								mDisplayScale.mV[VY],
+								gDirUtilp->getAppRODataDir(),
+								LLUI::getXUIPaths());
+	
+	// Create container for all sub-views
+	LLView::Params rvp;
+	rvp.name("root");
+	rvp.rect(mWindowRectScaled);
+	rvp.mouse_opaque(false);
+	rvp.follows.flags(FOLLOWS_NONE);
+	mRootView = LLUICtrlFactory::create<LLRootView>(rvp);
+	LLUI::setRootView(mRootView);
+
+	// Make avatar head look forward at start
+	mCurrentMousePoint.mX = getWindowWidthScaled() / 2;
+	mCurrentMousePoint.mY = getWindowHeightScaled() / 2;
+
+	gShowOverlayTitle = gSavedSettings.getBOOL("ShowOverlayTitle");
+	mOverlayTitle = gSavedSettings.getString("OverlayTitle");
+	// Can't have spaces in settings.ini strings, so use underscores instead and convert them.
+	LLStringUtil::replaceChar(mOverlayTitle, '_', ' ');
+
+	// sync the keyboard's setting with the saved setting
+	gSavedSettings.getControl("NumpadControl")->firePropertyChanged();
+
+	mDebugText = new LLDebugText(this);
+
+	mWorldViewRectScaled = calcScaledRect(mWorldViewRectRaw, mDisplayScale);
+}
+
+void LLViewerWindow::initGLDefaults()
+{
+	gGL.setSceneBlendType(LLRender::BT_ALPHA);
+
+	if (!LLGLSLShader::sNoFixedFunction)
+	{ //initialize fixed function state
+		glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE );
+
+		glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT,LLColor4::black.mV);
+		glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,LLColor4::white.mV);
+
+		// lights for objects
+		glShadeModel( GL_SMOOTH );
+
+		gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
+		gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
+	}
+
+	glPixelStorei(GL_PACK_ALIGNMENT,1);
+	glPixelStorei(GL_UNPACK_ALIGNMENT,1);
+
+	gGL.setAmbientLightColor(LLColor4::black);
+		
+	glCullFace(GL_BACK);
+
+	// RN: Need this for translation and stretch manip.
+	gBox.prerender();
+}
+
+struct MainPanel : public LLPanel
+{
+};
+
+void LLViewerWindow::initBase()
+{
+	S32 height = getWindowHeightScaled();
+	S32 width = getWindowWidthScaled();
+
+	LLRect full_window(0, height, width, 0);
+
+	////////////////////
+	//
+	// Set the gamma
+	//
+
+	F32 gamma = gSavedSettings.getF32("RenderGamma");
+	if (gamma != 0.0f)
+	{
+		getWindow()->setGamma(gamma);
+	}
+
+	// Create global views
+
+	// Create the floater view at the start so that other views can add children to it. 
+	// (But wait to add it as a child of the root view so that it will be in front of the 
+	// other views.)
+	MainPanel* main_view = new MainPanel();
+	main_view->buildFromFile("main_view.xml");
+	main_view->setShape(full_window);
+	getRootView()->addChild(main_view);
+
+	// placeholder widget that controls where "world" is rendered
+	mWorldViewPlaceholder = main_view->getChildView("world_view_rect")->getHandle();
+	mPopupView = main_view->getChild<LLPopupView>("popup_holder");
+	mHintHolder = main_view->getChild<LLView>("hint_holder")->getHandle();
+	mLoginPanelHolder = main_view->getChild<LLView>("login_panel_holder")->getHandle();
+
+	// Create the toolbar view
+	// Get a pointer to the toolbar view holder
+	LLPanel* panel_holder = main_view->getChild<LLPanel>("toolbar_view_holder");
+	// Load the toolbar view from file 
+	gToolBarView = LLUICtrlFactory::getInstance()->createFromFile<LLToolBarView>("panel_toolbar_view.xml", panel_holder, LLDefaultChildRegistry::instance());
+	gToolBarView->setShape(panel_holder->getLocalRect());
+	// Hide the toolbars for the moment: we'll make them visible after logging in world (see LLViewerWindow::initWorldUI())
+	gToolBarView->setVisible(FALSE);
+
+	// Constrain floaters to inside the menu and status bar regions.
+	gFloaterView = main_view->getChild<LLFloaterView>("Floater View");
+	gFloaterView->setFloaterSnapView(main_view->getChild<LLView>("floater_snap_region")->getHandle());
+	gSnapshotFloaterView = main_view->getChild<LLSnapshotFloaterView>("Snapshot Floater View");
+	
+
+	// Console
+	llassert( !gConsole );
+	LLConsole::Params cp;
+	cp.name("console");
+	cp.max_lines(gSavedSettings.getS32("ConsoleBufferSize"));
+	cp.rect(getChatConsoleRect());
+	cp.persist_time(gSavedSettings.getF32("ChatPersistTime"));
+	cp.font_size_index(gSavedSettings.getS32("ChatFontSize"));
+	cp.follows.flags(FOLLOWS_LEFT | FOLLOWS_RIGHT | FOLLOWS_BOTTOM);
+	gConsole = LLUICtrlFactory::create<LLConsole>(cp);
+	getRootView()->addChild(gConsole);
+
+	// optionally forward warnings to chat console/chat floater
+	// for qa runs and dev builds
+#if  !LL_RELEASE_FOR_DOWNLOAD
+	LLError::addRecorder(RecordToChatConsole::getInstance());
+#else
+	if(gSavedSettings.getBOOL("QAMode"))
+	{
+		LLError::addRecorder(RecordToChatConsole::getInstance());
+	}
+#endif
+
+	gDebugView = getRootView()->getChild<LLDebugView>("DebugView");
+	gDebugView->init();
+	gToolTipView = getRootView()->getChild<LLToolTipView>("tooltip view");
+
+	// Initialize busy response message when logged in
+	LLAppViewer::instance()->setOnLoginCompletedCallback(boost::bind(&LLFloaterPreference::initBusyResponse));
+
+	// Add the progress bar view (startup view), which overrides everything
+	mProgressView = getRootView()->findChild<LLProgressView>("progress_view");
+	setShowProgress(FALSE);
+	setProgressCancelButtonVisible(FALSE);
+
+	gMenuHolder = getRootView()->getChild<LLViewerMenuHolderGL>("Menu Holder");
+
+	LLMenuGL::sMenuContainer = gMenuHolder;
+
+}
+
+void LLViewerWindow::initWorldUI()
+{
+	S32 height = mRootView->getRect().getHeight();
+	S32 width = mRootView->getRect().getWidth();
+	LLRect full_window(0, height, width, 0);
+
+
+	gIMMgr = LLIMMgr::getInstance();
+
+	//getRootView()->sendChildToFront(gFloaterView);
+	//getRootView()->sendChildToFront(gSnapshotFloaterView);
+
+	LLPanel* chiclet_container = getRootView()->getChild<LLPanel>("chiclet_container");
+	LLChicletBar* chiclet_bar = LLChicletBar::getInstance();
+	chiclet_bar->setShape(chiclet_container->getLocalRect());
+	chiclet_bar->setFollowsAll();
+	chiclet_container->addChild(chiclet_bar);
+	chiclet_container->setVisible(TRUE);
+
+	LLRect morph_view_rect = full_window;
+	morph_view_rect.stretch( -STATUS_BAR_HEIGHT );
+	morph_view_rect.mTop = full_window.mTop - 32;
+	LLMorphView::Params mvp;
+	mvp.name("MorphView");
+	mvp.rect(morph_view_rect);
+	mvp.visible(false);
+	gMorphView = LLUICtrlFactory::create<LLMorphView>(mvp);
+	getRootView()->addChild(gMorphView);
+
+	LLWorldMapView::initClass();
+	
+	// Force gFloaterWorldMap to initialize
+	LLFloaterReg::getInstance("world_map");
+
+	// Force gFloaterTools to initialize
+	LLFloaterReg::getInstance("build");
+	LLFloaterReg::hideInstance("build");
+
+	// Status bar
+	LLPanel* status_bar_container = getRootView()->getChild<LLPanel>("status_bar_container");
+	gStatusBar = new LLStatusBar(status_bar_container->getLocalRect());
+	gStatusBar->setFollowsAll();
+	gStatusBar->setShape(status_bar_container->getLocalRect());
+	// sync bg color with menu bar
+	gStatusBar->setBackgroundColor( gMenuBarView->getBackgroundColor().get() );
+	status_bar_container->addChildInBack(gStatusBar);
+	status_bar_container->setVisible(TRUE);
+
+	// Navigation bar
+	LLPanel* nav_bar_container = getRootView()->getChild<LLPanel>("nav_bar_container");
+
+	LLNavigationBar* navbar = LLNavigationBar::getInstance();
+	navbar->setShape(nav_bar_container->getLocalRect());
+	navbar->setBackgroundColor(gMenuBarView->getBackgroundColor().get());
+	nav_bar_container->addChild(navbar);
+	nav_bar_container->setVisible(TRUE);
+	
+	if (!gSavedSettings.getBOOL("ShowNavbarNavigationPanel"))
+	{
+		navbar->setVisible(FALSE);
+	}
+
+	// Top Info bar
+	LLPanel* topinfo_bar_container = getRootView()->getChild<LLPanel>("topinfo_bar_container");
+	LLPanelTopInfoBar* topinfo_bar = LLPanelTopInfoBar::getInstance();
+
+	topinfo_bar->setShape(topinfo_bar_container->getLocalRect());
+
+	topinfo_bar_container->addChild(topinfo_bar);
+	topinfo_bar_container->setVisible(TRUE);
+
+	if (!gSavedSettings.getBOOL("ShowMiniLocationPanel"))
+	{
+		topinfo_bar->setVisible(FALSE);
+	}
+
+	if ( gHUDView == NULL )
+	{
+		LLRect hud_rect = full_window;
+		hud_rect.mBottom += 50;
+		if (gMenuBarView && gMenuBarView->isInVisibleChain())
+		{
+			hud_rect.mTop -= gMenuBarView->getRect().getHeight();
+		}
+		gHUDView = new LLHUDView(hud_rect);
+		getRootView()->addChild(gHUDView);
+	}
+
+	LLPanel* panel_ssf_container = getRootView()->getChild<LLPanel>("stand_stop_flying_container");
+	LLPanelStandStopFlying* panel_stand_stop_flying	= LLPanelStandStopFlying::getInstance();
+	panel_ssf_container->addChild(panel_stand_stop_flying);
+	panel_ssf_container->setVisible(TRUE);
+
+	// Load and make the toolbars visible
+	// Note: we need to load the toolbars only *after* the user is logged in and IW
+	if (gToolBarView)
+	{
+		gToolBarView->loadToolbars();
+		gToolBarView->setVisible(TRUE);
+	}
+
+	LLMediaCtrl* destinations = LLFloaterReg::getInstance("destinations")->getChild<LLMediaCtrl>("destination_guide_contents");
+	if (destinations)
+	{
+		destinations->setErrorPageURL(gSavedSettings.getString("GenericErrorPageURL"));
+		std::string url = gSavedSettings.getString("DestinationGuideURL");
+		url = LLWeb::expandURLSubstitutions(url, LLSD());
+		destinations->navigateTo(url, "text/html");
+	}
+	LLMediaCtrl* avatar_picker = LLFloaterReg::getInstance("avatar")->findChild<LLMediaCtrl>("avatar_picker_contents");
+	if (avatar_picker)
+	{
+		avatar_picker->setErrorPageURL(gSavedSettings.getString("GenericErrorPageURL"));
+		std::string url = gSavedSettings.getString("AvatarPickerURL");
+		url = LLWeb::expandURLSubstitutions(url, LLSD());
+		avatar_picker->navigateTo(url, "text/html");
+	}
+}
+
+// Destroy the UI
+void LLViewerWindow::shutdownViews()
+{
+	// clean up warning logger
+	LLError::removeRecorder(RecordToChatConsole::getInstance());
+
+	delete mDebugText;
+	mDebugText = NULL;
+	
+	// Cleanup global views
+	if (gMorphView)
+	{
+		gMorphView->setVisible(FALSE);
+	}
+
+	// DEV-40930: Clear sModalStack. Otherwise, any LLModalDialog left open
+	// will crump with LL_ERRS.
+	LLModalDialog::shutdownModals();
+	
+	// destroy the nav bar, not currently part of gViewerWindow
+	// *TODO: Make LLNavigationBar part of gViewerWindow
+	if (LLNavigationBar::instanceExists())
+	{
+		delete LLNavigationBar::getInstance();
+	}
+
+	// destroy menus after instantiating navbar above, as it needs
+	// access to gMenuHolder
+	cleanup_menus();
+
+	// Delete all child views.
+	delete mRootView;
+	mRootView = NULL;
+
+	// Automatically deleted as children of mRootView.  Fix the globals.
+	gStatusBar = NULL;
+	gIMMgr = NULL;
+	gToolTipView = NULL;
+
+	gToolBarView = NULL;
+	gFloaterView = NULL;
+	gMorphView = NULL;
+
+	gHUDView = NULL;
+}
+
+void LLViewerWindow::shutdownGL()
+{
+	//--------------------------------------------------------
+	// Shutdown GL cleanly.  Order is very important here.
+	//--------------------------------------------------------
+	LLFontGL::destroyDefaultFonts();
+	LLFontManager::cleanupClass();
+	stop_glerror();
+
+	gSky.cleanup();
+	stop_glerror();
+
+	LLWearableList::instance().cleanup() ;
+
+	gTextureList.shutdown();
+	stop_glerror();
+
+	gBumpImageList.shutdown();
+	stop_glerror();
+
+	LLWorldMapView::cleanupTextures();
+
+	llinfos << "Cleaning up pipeline" << llendl;
+	gPipeline.cleanup();
+	stop_glerror();
+
+	LLViewerTextureManager::cleanup() ;
+	LLImageGL::cleanupClass() ;
+
+	llinfos << "All textures and llimagegl images are destroyed!" << llendl ;
+
+	llinfos << "Cleaning up select manager" << llendl;
+	LLSelectMgr::getInstance()->cleanup();	
+
+	llinfos << "Stopping GL during shutdown" << llendl;
+	stopGL(FALSE);
+	stop_glerror();
+
+	gGL.shutdown();
+
+	LLVertexBuffer::cleanupClass();
+
+	llinfos << "LLVertexBuffer cleaned." << llendl ;
+}
+
+// shutdownViews() and shutdownGL() need to be called first
+LLViewerWindow::~LLViewerWindow()
+{
+	llinfos << "Destroying Window" << llendl;
+	destroyWindow();
+
+	delete mDebugText;
+	mDebugText = NULL;
+}
+
+
+void LLViewerWindow::setCursor( ECursorType c )
+{
+	mWindow->setCursor( c );
+}
+
+void LLViewerWindow::showCursor()
+{
+	mWindow->showCursor();
+	
+	mCursorHidden = FALSE;
+}
+
+void LLViewerWindow::hideCursor()
+{
+	// And hide the cursor
+	mWindow->hideCursor();
+
+	mCursorHidden = TRUE;
+}
+
+void LLViewerWindow::sendShapeToSim()
+{
+	LLMessageSystem* msg = gMessageSystem;
+	if(!msg) return;
+	msg->newMessageFast(_PREHASH_AgentHeightWidth);
+	msg->nextBlockFast(_PREHASH_AgentData);
+	msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+	msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+	msg->addU32Fast(_PREHASH_CircuitCode, gMessageSystem->mOurCircuitCode);
+	msg->nextBlockFast(_PREHASH_HeightWidthBlock);
+	msg->addU32Fast(_PREHASH_GenCounter, 0);
+	U16 height16 = (U16) mWorldViewRectRaw.getHeight();
+	U16 width16 = (U16) mWorldViewRectRaw.getWidth();
+	msg->addU16Fast(_PREHASH_Height, height16);
+	msg->addU16Fast(_PREHASH_Width, width16);
+	gAgent.sendReliableMessage();
+}
+
+// Must be called after window is created to set up agent
+// camera variables and UI variables.
+void LLViewerWindow::reshape(S32 width, S32 height)
+{
+	// Destroying the window at quit time generates spurious
+	// reshape messages.  We don't care about these, and we
+	// don't want to send messages because the message system
+	// may have been destructed.
+	if (!LLApp::isExiting())
+	{
+		gWindowResized = TRUE;
+
+		// update our window rectangle
+		mWindowRectRaw.mRight = mWindowRectRaw.mLeft + width;
+		mWindowRectRaw.mTop = mWindowRectRaw.mBottom + height;
+
+		//glViewport(0, 0, width, height );
+
+		if (height > 0)
+		{ 
+			LLViewerCamera::getInstance()->setViewHeightInPixels( mWorldViewRectRaw.getHeight() );
+			LLViewerCamera::getInstance()->setAspect( getWorldViewAspectRatio() );
+		}
+
+		calcDisplayScale();
+	
+		BOOL display_scale_changed = mDisplayScale != LLUI::sGLScaleFactor;
+		LLUI::setScaleFactor(mDisplayScale);
+
+		// update our window rectangle
+		mWindowRectScaled.mRight = mWindowRectScaled.mLeft + llround((F32)width / mDisplayScale.mV[VX]);
+		mWindowRectScaled.mTop = mWindowRectScaled.mBottom + llround((F32)height / mDisplayScale.mV[VY]);
+
+		setup2DViewport();
+
+		// Inform lower views of the change
+		// round up when converting coordinates to make sure there are no gaps at edge of window
+		LLView::sForceReshape = display_scale_changed;
+		mRootView->reshape(llceil((F32)width / mDisplayScale.mV[VX]), llceil((F32)height / mDisplayScale.mV[VY]));
+		LLView::sForceReshape = FALSE;
+
+		// clear font width caches
+		if (display_scale_changed)
+		{
+			LLHUDObject::reshapeAll();
+		}
+
+		sendShapeToSim();
+
+		// store new settings for the mode we are in, regardless
+		BOOL maximized = mWindow->getMaximized();
+		gSavedSettings.setBOOL("WindowMaximized", maximized);
+
+		if (!maximized)
+		{
+			U32 min_window_width=gSavedSettings.getU32("MinWindowWidth");
+			U32 min_window_height=gSavedSettings.getU32("MinWindowHeight");
+			// tell the OS specific window code about min window size
+			mWindow->setMinSize(min_window_width, min_window_height);
+
+			// Only save size if not maximized
+			gSavedSettings.setU32("WindowWidth", mWindowRectRaw.getWidth());
+			gSavedSettings.setU32("WindowHeight", mWindowRectRaw.getHeight());
+		}
+
+		LLViewerStats::getInstance()->setStat(LLViewerStats::ST_WINDOW_WIDTH, (F64)width);
+		LLViewerStats::getInstance()->setStat(LLViewerStats::ST_WINDOW_HEIGHT, (F64)height);
+	}
+}
+
+
+// Hide normal UI when a logon fails
+void LLViewerWindow::setNormalControlsVisible( BOOL visible )
+{
+	if(LLChicletBar::instanceExists())
+	{
+		LLChicletBar::getInstance()->setVisible(visible);
+		LLChicletBar::getInstance()->setEnabled(visible);
+	}
+
+	if ( gMenuBarView )
+	{
+		gMenuBarView->setVisible( visible );
+		gMenuBarView->setEnabled( visible );
+
+		// ...and set the menu color appropriately.
+		setMenuBackgroundColor(gAgent.getGodLevel() > GOD_NOT, 
+			LLGridManager::getInstance()->isInProductionGrid());
+	}
+        
+	if ( gStatusBar )
+	{
+		gStatusBar->setVisible( visible );	
+		gStatusBar->setEnabled( visible );	
+	}
+	
+	LLNavigationBar* navbarp = LLUI::getRootView()->findChild<LLNavigationBar>("navigation_bar");
+	if (navbarp)
+	{
+		// when it's time to show navigation bar we need to ensure that the user wants to see it
+		// i.e. ShowNavbarNavigationPanel option is true
+		navbarp->setVisible( visible && gSavedSettings.getBOOL("ShowNavbarNavigationPanel") );
+	}
+}
+
+void LLViewerWindow::setMenuBackgroundColor(bool god_mode, bool dev_grid)
+{
+    LLSD args;
+    LLColor4 new_bg_color;
+
+	// no l10n problem because channel is always an english string
+	std::string channel = LLVersionInfo::getChannel();
+	bool isProject = (channel.find("Project") != std::string::npos);
+	
+	// god more important than project, proj more important than grid
+    if(god_mode && LLGridManager::getInstance()->isInProductionGrid())
+    {
+        new_bg_color = LLUIColorTable::instance().getColor( "MenuBarGodBgColor" );
+    }
+    else if(god_mode && !LLGridManager::getInstance()->isInProductionGrid())
+    {
+        new_bg_color = LLUIColorTable::instance().getColor( "MenuNonProductionGodBgColor" );
+    }
+	else if (!god_mode && isProject)
+	{
+		new_bg_color = LLUIColorTable::instance().getColor( "MenuBarProjectBgColor" );
+    }
+    else if(!god_mode && !LLGridManager::getInstance()->isInProductionGrid())
+    {
+        new_bg_color = LLUIColorTable::instance().getColor( "MenuNonProductionBgColor" );
+    }
+    else 
+    {
+        new_bg_color = LLUIColorTable::instance().getColor( "MenuBarBgColor" );
+    }
+
+    if(gMenuBarView)
+    {
+        gMenuBarView->setBackgroundColor( new_bg_color );
+    }
+
+    if(gStatusBar)
+    {
+        gStatusBar->setBackgroundColor( new_bg_color );
+    }
+}
+
+void LLViewerWindow::drawDebugText()
+{
+	gGL.color4f(1,1,1,1);
+	gGL.pushMatrix();
+	gGL.pushUIMatrix();
+	if (LLGLSLShader::sNoFixedFunction)
+	{
+		gUIProgram.bind();
+	}
+	{
+		// scale view by UI global scale factor and aspect ratio correction factor
+		gGL.scaleUI(mDisplayScale.mV[VX], mDisplayScale.mV[VY], 1.f);
+		mDebugText->draw();
+	}
+	gGL.popUIMatrix();
+	gGL.popMatrix();
+
+	gGL.flush();
+	if (LLGLSLShader::sNoFixedFunction)
+	{
+		gUIProgram.unbind();
+	}
+}
+
+void LLViewerWindow::draw()
+{
+	
+//#if LL_DEBUG
+	LLView::sIsDrawing = TRUE;
+//#endif
+	stop_glerror();
+	
+	LLUI::setLineWidth(1.f);
+
+	LLUI::setLineWidth(1.f);
+	// Reset any left-over transforms
+	gGL.matrixMode(LLRender::MM_MODELVIEW);
+	
+	gGL.loadIdentity();
+
+	//S32 screen_x, screen_y;
+
+	if (!gSavedSettings.getBOOL("RenderUIBuffer"))
+	{
+		LLUI::sDirtyRect = getWindowRectScaled();
+	}
+
+	// HACK for timecode debugging
+	if (gSavedSettings.getBOOL("DisplayTimecode"))
+	{
+		// draw timecode block
+		std::string text;
+
+		gGL.loadIdentity();
+
+		microsecondsToTimecodeString(gFrameTime,text);
+		const LLFontGL* font = LLFontGL::getFontSansSerif();
+		font->renderUTF8(text, 0,
+						llround((getWindowWidthScaled()/2)-100.f),
+						llround((getWindowHeightScaled()-60.f)),
+			LLColor4( 1.f, 1.f, 1.f, 1.f ),
+			LLFontGL::LEFT, LLFontGL::TOP);
+	}
+
+	// Draw all nested UI views.
+	// No translation needed, this view is glued to 0,0
+
+	if (LLGLSLShader::sNoFixedFunction)
+	{
+		gUIProgram.bind();
+	}
+
+	gGL.pushMatrix();
+	LLUI::pushMatrix();
+	{
+		
+		// scale view by UI global scale factor and aspect ratio correction factor
+		gGL.scaleUI(mDisplayScale.mV[VX], mDisplayScale.mV[VY], 1.f);
+
+		LLVector2 old_scale_factor = LLUI::sGLScaleFactor;
+		// apply camera zoom transform (for high res screenshots)
+		F32 zoom_factor = LLViewerCamera::getInstance()->getZoomFactor();
+		S16 sub_region = LLViewerCamera::getInstance()->getZoomSubRegion();
+		if (zoom_factor > 1.f)
+		{
+			//decompose subregion number to x and y values
+			int pos_y = sub_region / llceil(zoom_factor);
+			int pos_x = sub_region - (pos_y*llceil(zoom_factor));
+			// offset for this tile
+			gGL.translatef((F32)getWindowWidthScaled() * -(F32)pos_x, 
+						(F32)getWindowHeightScaled() * -(F32)pos_y, 
+						0.f);
+			gGL.scalef(zoom_factor, zoom_factor, 1.f);
+			LLUI::sGLScaleFactor *= zoom_factor;
+		}
+
+		// Draw tool specific overlay on world
+		LLToolMgr::getInstance()->getCurrentTool()->draw();
+
+		if( gAgentCamera.cameraMouselook() || LLFloaterCamera::inFreeCameraMode() )
+		{
+			drawMouselookInstructions();
+			stop_glerror();
+		}
+
+		// Draw all nested UI views.
+		// No translation needed, this view is glued to 0,0
+		mRootView->draw();
+
+		if (LLView::sDebugRects)
+		{
+			gToolTipView->drawStickyRect();
+		}
+
+		// Draw optional on-top-of-everyone view
+		LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl();
+		if (top_ctrl && top_ctrl->getVisible())
+		{
+			S32 screen_x, screen_y;
+			top_ctrl->localPointToScreen(0, 0, &screen_x, &screen_y);
+
+			gGL.matrixMode(LLRender::MM_MODELVIEW);
+			LLUI::pushMatrix();
+			LLUI::translate( (F32) screen_x, (F32) screen_y, 0.f);
+			top_ctrl->draw();	
+			LLUI::popMatrix();
+		}
+
+
+		if( gShowOverlayTitle && !mOverlayTitle.empty() )
+		{
+			// Used for special titles such as "Second Life - Special E3 2003 Beta"
+			const S32 DIST_FROM_TOP = 20;
+			LLFontGL::getFontSansSerifBig()->renderUTF8(
+				mOverlayTitle, 0,
+				llround( getWindowWidthScaled() * 0.5f),
+				getWindowHeightScaled() - DIST_FROM_TOP,
+				LLColor4(1, 1, 1, 0.4f),
+				LLFontGL::HCENTER, LLFontGL::TOP);
+		}
+
+		LLUI::sGLScaleFactor = old_scale_factor;
+	}
+	LLUI::popMatrix();
+	gGL.popMatrix();
+
+	if (LLGLSLShader::sNoFixedFunction)
+	{
+		gUIProgram.unbind();
+	}
+
+//#if LL_DEBUG
+	LLView::sIsDrawing = FALSE;
+//#endif
+}
+
+// Takes a single keydown event, usually when UI is visible
+BOOL LLViewerWindow::handleKey(KEY key, MASK mask)
+{
+	// hide tooltips on keypress
+	LLToolTipMgr::instance().blockToolTips();
+
+	if (gFocusMgr.getKeyboardFocus() 
+		&& !(mask & (MASK_CONTROL | MASK_ALT))
+		&& !gFocusMgr.getKeystrokesOnly())
+	{
+		// We have keyboard focus, and it's not an accelerator
+		if (key < 0x80)
+		{
+			// Not a special key, so likely (we hope) to generate a character.  Let it fall through to character handler first.
+			return (gFocusMgr.getKeyboardFocus() != NULL);
+		}
+	}
+
+	// let menus handle navigation keys for navigation
+	if ((gMenuBarView && gMenuBarView->handleKey(key, mask, TRUE))
+		||(gLoginMenuBarView && gLoginMenuBarView->handleKey(key, mask, TRUE))
+		||(gMenuHolder && gMenuHolder->handleKey(key, mask, TRUE)))
+	{
+		return TRUE;
+	}
+
+	LLFocusableElement* keyboard_focus = gFocusMgr.getKeyboardFocus();
+
+	// give menus a chance to handle modified (Ctrl, Alt) shortcut keys before current focus 
+	// as long as focus isn't locked
+	if (mask & (MASK_CONTROL | MASK_ALT) && !gFocusMgr.focusLocked())
+	{
+		// Check the current floater's menu first, if it has one.
+		if (gFocusMgr.keyboardFocusHasAccelerators()
+			&& keyboard_focus 
+			&& keyboard_focus->handleKey(key,mask,FALSE))
+		{
+			return TRUE;
+		}
+
+		if ((gMenuBarView && gMenuBarView->handleAcceleratorKey(key, mask))
+			||(gLoginMenuBarView && gLoginMenuBarView->handleAcceleratorKey(key, mask)))
+		{
+			return TRUE;
+		}
+	}
+
+	// give floaters first chance to handle TAB key
+	// so frontmost floater gets focus
+	// if nothing has focus, go to first or last UI element as appropriate
+	if (key == KEY_TAB && (mask & MASK_CONTROL || gFocusMgr.getKeyboardFocus() == NULL))
+	{
+		if (gMenuHolder) gMenuHolder->hideMenus();
+
+		// if CTRL-tabbing (and not just TAB with no focus), go into window cycle mode
+		gFloaterView->setCycleMode((mask & MASK_CONTROL) != 0);
+
+		// do CTRL-TAB and CTRL-SHIFT-TAB logic
+		if (mask & MASK_SHIFT)
+		{
+			mRootView->focusPrevRoot();
+		}
+		else
+		{
+			mRootView->focusNextRoot();
+		}
+		return TRUE;
+	}
+	// hidden edit menu for cut/copy/paste
+	if (gEditMenu && gEditMenu->handleAcceleratorKey(key, mask))
+	{
+		return TRUE;
+	}
+
+	// Traverses up the hierarchy
+	if( keyboard_focus )
+	{
+		LLNearbyChatBar* nearby_chat = LLFloaterReg::findTypedInstance<LLNearbyChatBar>("chat_bar");
+
+		if (nearby_chat)
+		{
+			LLLineEditor* chat_editor = nearby_chat->getChatBox();
+		
+		// arrow keys move avatar while chatting hack
+		if (chat_editor && chat_editor->hasFocus())
+		{
+			// If text field is empty, there's no point in trying to move
+			// cursor with arrow keys, so allow movement
+			if (chat_editor->getText().empty() 
+				|| gSavedSettings.getBOOL("ArrowKeysAlwaysMove"))
+			{
+				// let Control-Up and Control-Down through for chat line history,
+				if (!(key == KEY_UP && mask == MASK_CONTROL)
+					&& !(key == KEY_DOWN && mask == MASK_CONTROL))
+				{
+					switch(key)
+					{
+					case KEY_LEFT:
+					case KEY_RIGHT:
+					case KEY_UP:
+					case KEY_DOWN:
+					case KEY_PAGE_UP:
+					case KEY_PAGE_DOWN:
+					case KEY_HOME:
+						// when chatbar is empty or ArrowKeysAlwaysMove set,
+						// pass arrow keys on to avatar...
+						return FALSE;
+					default:
+						break;
+					}
+				}
+			}
+		}
+		}
+		if (keyboard_focus->handleKey(key, mask, FALSE))
+		{
+			return TRUE;
+		}
+	}
+
+	if( LLToolMgr::getInstance()->getCurrentTool()->handleKey(key, mask) )
+	{
+		return TRUE;
+	}
+
+	// Try for a new-format gesture
+	if (LLGestureMgr::instance().triggerGesture(key, mask))
+	{
+		return TRUE;
+	}
+
+	// See if this is a gesture trigger.  If so, eat the key and
+	// don't pass it down to the menus.
+	if (gGestureList.trigger(key, mask))
+	{
+		return TRUE;
+	}
+
+	// If "Pressing letter keys starts local chat" option is selected, we are not in mouselook, 
+	// no view has keyboard focus, this is a printable character key (and no modifier key is 
+	// pressed except shift), then give focus to nearby chat (STORM-560)
+	if ( gSavedSettings.getS32("LetterKeysFocusChatBar") && !gAgentCamera.cameraMouselook() && 
+		!keyboard_focus && key < 0x80 && (mask == MASK_NONE || mask == MASK_SHIFT) )
+	{
+		LLLineEditor* chat_editor = LLFloaterReg::getTypedInstance<LLNearbyChatBar>("chat_bar")->getChatBox();
+		if (chat_editor)
+		{
+			// passing NULL here, character will be added later when it is handled by character handler.
+			LLNearbyChatBar::getInstance()->startChat(NULL);
+			return TRUE;
+		}
+	}
+
+	// give menus a chance to handle unmodified accelerator keys
+	if ((gMenuBarView && gMenuBarView->handleAcceleratorKey(key, mask))
+		||(gLoginMenuBarView && gLoginMenuBarView->handleAcceleratorKey(key, mask)))
+	{
+		return TRUE;
+	}
+
+	// don't pass keys on to world when something in ui has focus
+	return gFocusMgr.childHasKeyboardFocus(mRootView) 
+		|| LLMenuGL::getKeyboardMode() 
+		|| (gMenuBarView && gMenuBarView->getHighlightedItem() && gMenuBarView->getHighlightedItem()->isActive());
+}
+
+
+BOOL LLViewerWindow::handleUnicodeChar(llwchar uni_char, MASK mask)
+{
+	// HACK:  We delay processing of return keys until they arrive as a Unicode char,
+	// so that if you're typing chat text at low frame rate, we don't send the chat
+	// until all keystrokes have been entered. JC
+	// HACK: Numeric keypad <enter> on Mac is Unicode 3
+	// HACK: Control-M on Windows is Unicode 13
+	if ((uni_char == 13 && mask != MASK_CONTROL)
+		|| (uni_char == 3 && mask == MASK_NONE))
+	{
+		return gViewerKeyboard.handleKey(KEY_RETURN, mask, gKeyboard->getKeyRepeated(KEY_RETURN));
+	}
+
+	// let menus handle navigation (jump) keys
+	if (gMenuBarView && gMenuBarView->handleUnicodeChar(uni_char, TRUE))
+	{
+		return TRUE;
+	}
+
+	// Traverses up the hierarchy
+	LLFocusableElement* keyboard_focus = gFocusMgr.getKeyboardFocus();
+	if( keyboard_focus )
+	{
+		if (keyboard_focus->handleUnicodeChar(uni_char, FALSE))
+		{
+			return TRUE;
+		}
+
+		//// Topmost view gets a chance before the hierarchy
+		//LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl();
+		//if (top_ctrl && top_ctrl->handleUnicodeChar( uni_char, FALSE ) )
+		//{
+		//	return TRUE;
+		//}
+
+		return TRUE;
+	}
+
+	return FALSE;
+}
+
+
+void LLViewerWindow::handleScrollWheel(S32 clicks)
+{
+	LLView::sMouseHandlerMessage.clear();
+
+	LLUI::resetMouseIdleTimer();
+	
+	LLMouseHandler* mouse_captor = gFocusMgr.getMouseCapture();
+	if( mouse_captor )
+	{
+		S32 local_x;
+		S32 local_y;
+		mouse_captor->screenPointToLocal( mCurrentMousePoint.mX, mCurrentMousePoint.mY, &local_x, &local_y );
+		mouse_captor->handleScrollWheel(local_x, local_y, clicks);
+		if (LLView::sDebugMouseHandling)
+		{
+			llinfos << "Scroll Wheel handled by captor " << mouse_captor->getName() << llendl;
+		}
+		return;
+	}
+
+	LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl();
+	if (top_ctrl)
+	{
+		S32 local_x;
+		S32 local_y;
+		top_ctrl->screenPointToLocal( mCurrentMousePoint.mX, mCurrentMousePoint.mY, &local_x, &local_y );
+		if (top_ctrl->handleScrollWheel(local_x, local_y, clicks)) return;
+	}
+
+	if (mRootView->handleScrollWheel(mCurrentMousePoint.mX, mCurrentMousePoint.mY, clicks) )
+	{
+		if (LLView::sDebugMouseHandling)
+		{
+			llinfos << "Scroll Wheel" << LLView::sMouseHandlerMessage << llendl;
+		}
+		return;
+	}
+	else if (LLView::sDebugMouseHandling)
+	{
+		llinfos << "Scroll Wheel not handled by view" << llendl;
+	}
+
+	// Zoom the camera in and out behavior
+
+	if(top_ctrl == 0 
+		&& getWorldViewRectScaled().pointInRect(mCurrentMousePoint.mX, mCurrentMousePoint.mY) 
+		&& gAgentCamera.isInitialized())
+		gAgentCamera.handleScrollWheel(clicks);
+
+	return;
+}
+
+void LLViewerWindow::addPopup(LLView* popup)
+{
+	if (mPopupView)
+	{
+		mPopupView->addPopup(popup);
+	}
+}
+
+void LLViewerWindow::removePopup(LLView* popup)
+{
+	if (mPopupView)
+	{
+		mPopupView->removePopup(popup);
+	}
+}
+
+void LLViewerWindow::clearPopups()
+{
+	if (mPopupView)
+	{
+		mPopupView->clearPopups();
+	}
+}
+
+void LLViewerWindow::moveCursorToCenter()
+{
+	if (! gSavedSettings.getBOOL("DisableMouseWarp"))
+	{
+		S32 x = getWorldViewWidthScaled() / 2;
+		S32 y = getWorldViewHeightScaled() / 2;
+	
+		//on a forced move, all deltas get zeroed out to prevent jumping
+		mCurrentMousePoint.set(x,y);
+		mLastMousePoint.set(x,y);
+		mCurrentMouseDelta.set(0,0);	
+
+		LLUI::setMousePositionScreen(x, y);	
+	}
+}
+
+
+//////////////////////////////////////////////////////////////////////
+//
+// Hover handlers
+//
+
+void append_xui_tooltip(LLView* viewp, LLToolTip::Params& params)
+{
+	if (viewp) 
+	{
+		if (!params.styled_message.empty())
+		{
+			params.styled_message.add().text("\n---------\n"); 
+		}
+		LLView::root_to_view_iterator_t end_tooltip_it = viewp->endRootToView();
+		// NOTE: we skip "root" since it is assumed
+		for (LLView::root_to_view_iterator_t tooltip_it = ++viewp->beginRootToView();
+			tooltip_it != end_tooltip_it;
+			++tooltip_it)
+		{
+			LLView* viewp = *tooltip_it;
+		
+			params.styled_message.add().text(viewp->getName());
+
+			LLPanel* panelp = dynamic_cast<LLPanel*>(viewp);
+			if (panelp && !panelp->getXMLFilename().empty())
+			{
+				params.styled_message.add()
+					.text("(" + panelp->getXMLFilename() + ")")
+					.style.color(LLColor4(0.7f, 0.7f, 1.f, 1.f));
+			}
+			params.styled_message.add().text("/");
+		}
+	}
+}
+
+// Update UI based on stored mouse position from mouse-move
+// event processing.
+void LLViewerWindow::updateUI()
+{
+	static LLFastTimer::DeclareTimer ftm("Update UI");
+	LLFastTimer t(ftm);
+
+	static std::string last_handle_msg;
+
+	if (gLoggedInTime.getStarted())
+	{
+		if (gLoggedInTime.getElapsedTimeF32() > gSavedSettings.getF32("DestinationGuideHintTimeout"))
+		{
+			LLFirstUse::notUsingDestinationGuide();
+		}
+		if (gLoggedInTime.getElapsedTimeF32() > gSavedSettings.getF32("SidePanelHintTimeout"))
+		{
+			LLFirstUse::notUsingSidePanel();
+		}
+	}
+
+	LLConsole::updateClass();
+
+	// animate layout stacks so we have up to date rect for world view
+	LLLayoutStack::updateClass();
+
+	// use full window for world view when not rendering UI
+	bool world_view_uses_full_window = gAgentCamera.cameraMouselook() || !gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI);
+	updateWorldViewRect(world_view_uses_full_window);
+
+	LLView::sMouseHandlerMessage.clear();
+
+	S32 x = mCurrentMousePoint.mX;
+	S32 y = mCurrentMousePoint.mY;
+
+	MASK	mask = gKeyboard->currentMask(TRUE);
+
+	if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_RAYCAST))
+	{
+		gDebugRaycastFaceHit = -1;
+		gDebugRaycastObject = cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE,
+											  &gDebugRaycastFaceHit,
+											  &gDebugRaycastIntersection,
+											  &gDebugRaycastTexCoord,
+											  &gDebugRaycastNormal,
+											  &gDebugRaycastBinormal,
+											  &gDebugRaycastStart,
+											  &gDebugRaycastEnd);
+	}
+
+	updateMouseDelta();
+	updateKeyboardFocus();
+
+	BOOL handled = FALSE;
+
+	BOOL handled_by_top_ctrl = FALSE;
+	LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl();
+	LLMouseHandler* mouse_captor = gFocusMgr.getMouseCapture();
+	LLView* captor_view = dynamic_cast<LLView*>(mouse_captor);
+
+	//FIXME: only include captor and captor's ancestors if mouse is truly over them --RN
+
+	//build set of views containing mouse cursor by traversing UI hierarchy and testing 
+	//screen rect against mouse cursor
+	view_handle_set_t mouse_hover_set;
+
+	// constraint mouse enter events to children of mouse captor
+	LLView* root_view = captor_view;
+
+	// if mouse captor doesn't exist or isn't a LLView
+	// then allow mouse enter events on entire UI hierarchy
+	if (!root_view)
+	{
+		root_view = mRootView;
+	}
+
+	// only update mouse hover set when UI is visible (since we shouldn't send hover events to invisible UI
+	if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
+	{
+		// include all ancestors of captor_view as automatically having mouse
+		if (captor_view)
+		{
+			LLView* captor_parent_view = captor_view->getParent();
+			while(captor_parent_view)
+			{
+				mouse_hover_set.insert(captor_parent_view->getHandle());
+				captor_parent_view = captor_parent_view->getParent();
+			}
+		}
+
+		// aggregate visible views that contain mouse cursor in display order
+		LLPopupView::popup_list_t popups = mPopupView->getCurrentPopups();
+
+		for(LLPopupView::popup_list_t::iterator popup_it = popups.begin(); popup_it != popups.end(); ++popup_it)
+		{
+			LLView* popup = popup_it->get();
+			if (popup && popup->calcScreenBoundingRect().pointInRect(x, y))
+			{
+				// iterator over contents of top_ctrl, and throw into mouse_hover_set
+				for (LLView::tree_iterator_t it = popup->beginTreeDFS();
+					it != popup->endTreeDFS();
+					++it)
+				{
+					LLView* viewp = *it;
+					if (viewp->getVisible()
+						&& viewp->calcScreenBoundingRect().pointInRect(x, y))
+					{
+						// we have a view that contains the mouse, add it to the set
+						mouse_hover_set.insert(viewp->getHandle());
+					}
+					else
+					{
+						// skip this view and all of its children
+						it.skipDescendants();
+					}
+				}
+			}
+		}
+
+		// while the top_ctrl contains the mouse cursor, only it and its descendants will receive onMouseEnter events
+		if (top_ctrl && top_ctrl->calcScreenBoundingRect().pointInRect(x, y))
+		{
+			// iterator over contents of top_ctrl, and throw into mouse_hover_set
+			for (LLView::tree_iterator_t it = top_ctrl->beginTreeDFS();
+				it != top_ctrl->endTreeDFS();
+				++it)
+			{
+				LLView* viewp = *it;
+				if (viewp->getVisible()
+					&& viewp->calcScreenBoundingRect().pointInRect(x, y))
+				{
+					// we have a view that contains the mouse, add it to the set
+					mouse_hover_set.insert(viewp->getHandle());
+				}
+				else
+				{
+					// skip this view and all of its children
+					it.skipDescendants();
+				}
+			}
+		}
+		else
+		{
+			// walk UI tree in depth-first order
+			for (LLView::tree_iterator_t it = root_view->beginTreeDFS();
+				it != root_view->endTreeDFS();
+				++it)
+			{
+				LLView* viewp = *it;
+				// calculating the screen rect involves traversing the parent, so this is less than optimal
+				if (viewp->getVisible()
+					&& viewp->calcScreenBoundingRect().pointInRect(x, y))
+				{
+
+					// if this view is mouse opaque, nothing behind it should be in mouse_hover_set
+					if (viewp->getMouseOpaque())
+					{
+						// constrain further iteration to children of this widget
+						it = viewp->beginTreeDFS();
+					}
+		
+					// we have a view that contains the mouse, add it to the set
+					mouse_hover_set.insert(viewp->getHandle());
+				}
+				else
+				{
+					// skip this view and all of its children
+					it.skipDescendants();
+				}
+			}
+		}
+	}
+
+	typedef std::vector<LLHandle<LLView> > view_handle_list_t;
+
+	// call onMouseEnter() on all views which contain the mouse cursor but did not before
+	view_handle_list_t mouse_enter_views;
+	std::set_difference(mouse_hover_set.begin(), mouse_hover_set.end(),
+						mMouseHoverViews.begin(), mMouseHoverViews.end(),
+						std::back_inserter(mouse_enter_views));
+	for (view_handle_list_t::iterator it = mouse_enter_views.begin();
+		it != mouse_enter_views.end();
+		++it)
+	{
+		LLView* viewp = it->get();
+		if (viewp)
+		{
+			LLRect view_screen_rect = viewp->calcScreenRect();
+			viewp->onMouseEnter(x - view_screen_rect.mLeft, y - view_screen_rect.mBottom, mask);
+		}
+	}
+
+	// call onMouseLeave() on all views which no longer contain the mouse cursor
+	view_handle_list_t mouse_leave_views;
+	std::set_difference(mMouseHoverViews.begin(), mMouseHoverViews.end(),
+						mouse_hover_set.begin(), mouse_hover_set.end(),
+						std::back_inserter(mouse_leave_views));
+	for (view_handle_list_t::iterator it = mouse_leave_views.begin();
+		it != mouse_leave_views.end();
+		++it)
+	{
+		LLView* viewp = it->get();
+		if (viewp)
+		{
+			LLRect view_screen_rect = viewp->calcScreenRect();
+			viewp->onMouseLeave(x - view_screen_rect.mLeft, y - view_screen_rect.mBottom, mask);
+		}
+	}
+
+	// store resulting hover set for next frame
+	swap(mMouseHoverViews, mouse_hover_set);
+
+	// only handle hover events when UI is enabled
+	if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
+	{	
+
+		if( mouse_captor )
+		{
+			// Pass hover events to object capturing mouse events.
+			S32 local_x;
+			S32 local_y; 
+			mouse_captor->screenPointToLocal( x, y, &local_x, &local_y );
+			handled = mouse_captor->handleHover(local_x, local_y, mask);
+			if (LLView::sDebugMouseHandling)
+			{
+				llinfos << "Hover handled by captor " << mouse_captor->getName() << llendl;
+			}
+
+			if( !handled )
+			{
+				lldebugst(LLERR_USER_INPUT) << "hover not handled by mouse captor" << llendl;
+			}
+		}
+		else
+		{
+			if (top_ctrl)
+			{
+				S32 local_x, local_y;
+				top_ctrl->screenPointToLocal( x, y, &local_x, &local_y );
+				handled = top_ctrl->pointInView(local_x, local_y) && top_ctrl->handleHover(local_x, local_y, mask);
+				handled_by_top_ctrl = TRUE;
+			}
+
+			if ( !handled )
+			{
+				// x and y are from last time mouse was in window
+				// mMouseInWindow tracks *actual* mouse location
+				if (mMouseInWindow && mRootView->handleHover(x, y, mask) )
+				{
+					if (LLView::sDebugMouseHandling && LLView::sMouseHandlerMessage != last_handle_msg)
+					{
+						last_handle_msg = LLView::sMouseHandlerMessage;
+						llinfos << "Hover" << LLView::sMouseHandlerMessage << llendl;
+					}
+					handled = TRUE;
+				}
+				else if (LLView::sDebugMouseHandling)
+				{
+					if (last_handle_msg != LLStringUtil::null)
+					{
+						last_handle_msg.clear();
+						llinfos << "Hover not handled by view" << llendl;
+					}
+				}
+			}
+		
+			if (!handled)
+			{
+				LLTool *tool = LLToolMgr::getInstance()->getCurrentTool();
+
+				if(mMouseInWindow && tool)
+				{
+					handled = tool->handleHover(x, y, mask);
+				}
+			}
+		}
+
+		// Show a new tool tip (or update one that is already shown)
+		BOOL tool_tip_handled = FALSE;
+		std::string tool_tip_msg;
+		if( handled 
+			&& !mWindow->isCursorHidden())
+		{
+			LLRect screen_sticky_rect = mRootView->getLocalRect();
+			S32 local_x, local_y;
+
+			if (gSavedSettings.getBOOL("DebugShowXUINames"))
+			{
+				LLToolTip::Params params;
+
+				LLView* tooltip_view = mRootView;
+				LLView::tree_iterator_t end_it = mRootView->endTreeDFS();
+				for (LLView::tree_iterator_t it = mRootView->beginTreeDFS(); it != end_it; ++it)
+				{
+					LLView* viewp = *it;
+					LLRect screen_rect;
+					viewp->localRectToScreen(viewp->getLocalRect(), &screen_rect);
+					if (!(viewp->getVisible()
+						 && screen_rect.pointInRect(x, y)))
+					{
+						it.skipDescendants();
+					}
+					// only report xui names for LLUICtrls, 
+					// and blacklist the various containers we don't care about
+					else if (dynamic_cast<LLUICtrl*>(viewp) 
+							&& viewp != gMenuHolder
+							&& viewp != gFloaterView
+							&& viewp != gConsole) 
+					{
+						if (dynamic_cast<LLFloater*>(viewp))
+						{
+							// constrain search to descendants of this (frontmost) floater
+							// by resetting iterator
+							it = viewp->beginTreeDFS();
+						}
+
+						// if we are in a new part of the tree (not a descendent of current tooltip_view)
+						// then push the results for tooltip_view and start with a new potential view
+						// NOTE: this emulates visiting only the leaf nodes that meet our criteria
+						if (!viewp->hasAncestor(tooltip_view))
+						{
+							append_xui_tooltip(tooltip_view, params);
+							screen_sticky_rect.intersectWith(tooltip_view->calcScreenRect());
+						}
+						tooltip_view = viewp;
+					}
+				}
+
+				append_xui_tooltip(tooltip_view, params);
+				screen_sticky_rect.intersectWith(tooltip_view->calcScreenRect());
+				
+				params.sticky_rect = screen_sticky_rect;
+				params.max_width = 400;
+
+				LLToolTipMgr::instance().show(params);
+			}
+			// if there is a mouse captor, nothing else gets a tooltip
+			else if (mouse_captor)
+			{
+				mouse_captor->screenPointToLocal(x, y, &local_x, &local_y);
+				tool_tip_handled = mouse_captor->handleToolTip(local_x, local_y, mask);
+			}
+			else 
+			{
+				// next is top_ctrl
+				if (!tool_tip_handled && top_ctrl)
+				{
+					top_ctrl->screenPointToLocal(x, y, &local_x, &local_y);
+					tool_tip_handled = top_ctrl->handleToolTip(local_x, local_y, mask );
+				}
+				
+				if (!tool_tip_handled)
+				{
+					local_x = x; local_y = y;
+					tool_tip_handled = mRootView->handleToolTip(local_x, local_y, mask );
+				}
+
+				LLTool* current_tool = LLToolMgr::getInstance()->getCurrentTool();
+				if (!tool_tip_handled && current_tool)
+				{
+					current_tool->screenPointToLocal(x, y, &local_x, &local_y);
+					tool_tip_handled = current_tool->handleToolTip(local_x, local_y, mask );
+				}
+			}
+		}		
+	}
+	else
+	{	// just have tools handle hover when UI is turned off
+		LLTool *tool = LLToolMgr::getInstance()->getCurrentTool();
+
+		if(mMouseInWindow && tool)
+		{
+			handled = tool->handleHover(x, y, mask);
+		}
+	}
+
+	updateLayout();
+
+	mLastMousePoint = mCurrentMousePoint;
+
+	// cleanup unused selections when no modal dialogs are open
+	if (LLModalDialog::activeCount() == 0)
+	{
+		LLViewerParcelMgr::getInstance()->deselectUnused();
+	}
+
+	if (LLModalDialog::activeCount() == 0)
+	{
+		LLSelectMgr::getInstance()->deselectUnused();
+	}
+}
+
+
+void LLViewerWindow::updateLayout()
+{
+	LLTool* tool = LLToolMgr::getInstance()->getCurrentTool();
+	if (gFloaterTools != NULL
+		&& tool != NULL
+		&& tool != gToolNull  
+		&& tool != LLToolCompInspect::getInstance() 
+		&& tool != LLToolDragAndDrop::getInstance() 
+		&& !gSavedSettings.getBOOL("FreezeTime"))
+	{ 
+		// Suppress the toolbox view if our source tool was the pie tool,
+		// and we've overridden to something else.
+		bool suppress_toolbox = 
+			(LLToolMgr::getInstance()->getBaseTool() == LLToolPie::getInstance()) &&
+			(LLToolMgr::getInstance()->getCurrentTool() != LLToolPie::getInstance());
+
+		LLMouseHandler *captor = gFocusMgr.getMouseCapture();
+		// With the null, inspect, or drag and drop tool, don't muck
+		// with visibility.
+
+		if (gFloaterTools->isMinimized()
+			||	(tool != LLToolPie::getInstance()						// not default tool
+				&& tool != LLToolCompGun::getInstance()					// not coming out of mouselook
+				&& !suppress_toolbox									// not override in third person
+				&& LLToolMgr::getInstance()->getCurrentToolset() != gFaceEditToolset	// not special mode
+				&& LLToolMgr::getInstance()->getCurrentToolset() != gMouselookToolset
+				&& (!captor || dynamic_cast<LLView*>(captor) != NULL)))						// not dragging
+		{
+			// Force floater tools to be visible (unless minimized)
+			if (!gFloaterTools->getVisible())
+			{
+				gFloaterTools->openFloater();
+			}
+			// Update the location of the blue box tool popup
+			LLCoordGL select_center_screen;
+			MASK	mask = gKeyboard->currentMask(TRUE);
+			gFloaterTools->updatePopup( select_center_screen, mask );
+		}
+		else
+		{
+			gFloaterTools->setVisible(FALSE);
+		}
+		//gMenuBarView->setItemVisible("BuildTools", gFloaterTools->getVisible());
+	}
+
+	LLFloaterBuildOptions* build_options_floater = LLFloaterReg::findTypedInstance<LLFloaterBuildOptions>("build_options");
+	if (build_options_floater && build_options_floater->getVisible())
+	{
+		build_options_floater->updateGridMode();
+	}
+
+	// Always update console
+	if(gConsole)
+	{
+		LLRect console_rect = getChatConsoleRect();
+		gConsole->reshape(console_rect.getWidth(), console_rect.getHeight());
+		gConsole->setRect(console_rect);
+	}
+}
+
+void LLViewerWindow::updateMouseDelta()
+{
+	S32 dx = lltrunc((F32) (mCurrentMousePoint.mX - mLastMousePoint.mX) * LLUI::sGLScaleFactor.mV[VX]);
+	S32 dy = lltrunc((F32) (mCurrentMousePoint.mY - mLastMousePoint.mY) * LLUI::sGLScaleFactor.mV[VY]);
+
+	//RN: fix for asynchronous notification of mouse leaving window not working
+	LLCoordWindow mouse_pos;
+	mWindow->getCursorPosition(&mouse_pos);
+	if (mouse_pos.mX < 0 || 
+		mouse_pos.mY < 0 ||
+		mouse_pos.mX > mWindowRectRaw.getWidth() ||
+		mouse_pos.mY > mWindowRectRaw.getHeight())
+	{
+		mMouseInWindow = FALSE;
+	}
+	else
+	{
+		mMouseInWindow = TRUE;
+	}
+
+	LLVector2 mouse_vel; 
+
+	if (gSavedSettings.getBOOL("MouseSmooth"))
+	{
+		static F32 fdx = 0.f;
+		static F32 fdy = 0.f;
+
+		F32 amount = 16.f;
+		fdx = fdx + ((F32) dx - fdx) * llmin(gFrameIntervalSeconds*amount,1.f);
+		fdy = fdy + ((F32) dy - fdy) * llmin(gFrameIntervalSeconds*amount,1.f);
+
+		mCurrentMouseDelta.set(llround(fdx), llround(fdy));
+		mouse_vel.setVec(fdx,fdy);
+	}
+	else
+	{
+		mCurrentMouseDelta.set(dx, dy);
+		mouse_vel.setVec((F32) dx, (F32) dy);
+	}
+    
+	mMouseVelocityStat.addValue(mouse_vel.magVec());
+}
+
+void LLViewerWindow::updateKeyboardFocus()
+{
+	if (!gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
+	{
+		gFocusMgr.setKeyboardFocus(NULL);
+	}
+
+	// clean up current focus
+	LLUICtrl* cur_focus = dynamic_cast<LLUICtrl*>(gFocusMgr.getKeyboardFocus());
+	if (cur_focus)
+	{
+		if (!cur_focus->isInVisibleChain() || !cur_focus->isInEnabledChain())
+		{
+            // don't release focus, just reassign so that if being given
+            // to a sibling won't call onFocusLost on all the ancestors
+			// gFocusMgr.releaseFocusIfNeeded(cur_focus);
+
+			LLUICtrl* parent = cur_focus->getParentUICtrl();
+			const LLUICtrl* focus_root = cur_focus->findRootMostFocusRoot();
+			bool new_focus_found = false;
+			while(parent)
+			{
+				if (parent->isCtrl() 
+					&& (parent->hasTabStop() || parent == focus_root) 
+					&& !parent->getIsChrome() 
+					&& parent->isInVisibleChain() 
+					&& parent->isInEnabledChain())
+				{
+					if (!parent->focusFirstItem())
+					{
+						parent->setFocus(TRUE);
+					}
+					new_focus_found = true;
+					break;
+				}
+				parent = parent->getParentUICtrl();
+			}
+
+			// if we didn't find a better place to put focus, just release it
+			// hasFocus() will return true if and only if we didn't touch focus since we
+			// are only moving focus higher in the hierarchy
+			if (!new_focus_found)
+			{
+				cur_focus->setFocus(FALSE);
+			}
+		}
+		else if (cur_focus->isFocusRoot())
+		{
+			// focus roots keep trying to delegate focus to their first valid descendant
+			// this assumes that focus roots are not valid focus holders on their own
+			cur_focus->focusFirstItem();
+		}
+	}
+
+	// last ditch force of edit menu to selection manager
+	if (LLEditMenuHandler::gEditMenuHandler == NULL && LLSelectMgr::getInstance()->getSelection()->getObjectCount())
+	{
+		LLEditMenuHandler::gEditMenuHandler = LLSelectMgr::getInstance();
+	}
+
+	if (gFloaterView->getCycleMode())
+	{
+		// sync all floaters with their focus state
+		gFloaterView->highlightFocusedFloater();
+		gSnapshotFloaterView->highlightFocusedFloater();
+		MASK	mask = gKeyboard->currentMask(TRUE);
+		if ((mask & MASK_CONTROL) == 0)
+		{
+			// control key no longer held down, finish cycle mode
+			gFloaterView->setCycleMode(FALSE);
+
+			gFloaterView->syncFloaterTabOrder();
+		}
+		else
+		{
+			// user holding down CTRL, don't update tab order of floaters
+		}
+	}
+	else
+	{
+		// update focused floater
+		gFloaterView->highlightFocusedFloater();
+		gSnapshotFloaterView->highlightFocusedFloater();
+		// make sure floater visible order is in sync with tab order
+		gFloaterView->syncFloaterTabOrder();
+	}
+}
+
+static LLFastTimer::DeclareTimer FTM_UPDATE_WORLD_VIEW("Update World View");
+void LLViewerWindow::updateWorldViewRect(bool use_full_window)
+{
+	LLFastTimer ft(FTM_UPDATE_WORLD_VIEW);
+
+	// start off using whole window to render world
+	LLRect new_world_rect = mWindowRectRaw;
+
+	if (use_full_window == false && mWorldViewPlaceholder.get())
+	{
+		new_world_rect = mWorldViewPlaceholder.get()->calcScreenRect();
+		// clamp to at least a 1x1 rect so we don't try to allocate zero width gl buffers
+		new_world_rect.mTop = llmax(new_world_rect.mTop, new_world_rect.mBottom + 1);
+		new_world_rect.mRight = llmax(new_world_rect.mRight, new_world_rect.mLeft + 1);
+
+		new_world_rect.mLeft = llround((F32)new_world_rect.mLeft * mDisplayScale.mV[VX]);
+		new_world_rect.mRight = llround((F32)new_world_rect.mRight * mDisplayScale.mV[VX]);
+		new_world_rect.mBottom = llround((F32)new_world_rect.mBottom * mDisplayScale.mV[VY]);
+		new_world_rect.mTop = llround((F32)new_world_rect.mTop * mDisplayScale.mV[VY]);
+	}
+
+	if (mWorldViewRectRaw != new_world_rect)
+	{
+		mWorldViewRectRaw = new_world_rect;
+		gResizeScreenTexture = TRUE;
+		LLViewerCamera::getInstance()->setViewHeightInPixels( mWorldViewRectRaw.getHeight() );
+		LLViewerCamera::getInstance()->setAspect( getWorldViewAspectRatio() );
+
+		LLRect old_world_rect_scaled = mWorldViewRectScaled;
+		mWorldViewRectScaled = calcScaledRect(mWorldViewRectRaw, mDisplayScale);
+
+		// sending a signal with a new WorldView rect
+		mOnWorldViewRectUpdated(old_world_rect_scaled, mWorldViewRectScaled);
+	}
+}
+
+void LLViewerWindow::saveLastMouse(const LLCoordGL &point)
+{
+	// Store last mouse location.
+	// If mouse leaves window, pretend last point was on edge of window
+	if (point.mX < 0)
+	{
+		mCurrentMousePoint.mX = 0;
+	}
+	else if (point.mX > getWindowWidthScaled())
+	{
+		mCurrentMousePoint.mX = getWindowWidthScaled();
+	}
+	else
+	{
+		mCurrentMousePoint.mX = point.mX;
+	}
+
+	if (point.mY < 0)
+	{
+		mCurrentMousePoint.mY = 0;
+	}
+	else if (point.mY > getWindowHeightScaled() )
+	{
+		mCurrentMousePoint.mY = getWindowHeightScaled();
+	}
+	else
+	{
+		mCurrentMousePoint.mY = point.mY;
+	}
+}
+
+
+// Draws the selection outlines for the currently selected objects
+// Must be called after displayObjects is called, which sets the mGLName parameter
+// NOTE: This function gets called 3 times:
+//  render_ui_3d: 			FALSE, FALSE, TRUE
+//  render_hud_elements:	FALSE, FALSE, FALSE
+void LLViewerWindow::renderSelections( BOOL for_gl_pick, BOOL pick_parcel_walls, BOOL for_hud )
+{
+	LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
+
+	if (!for_hud && !for_gl_pick)
+	{
+		// Call this once and only once
+		LLSelectMgr::getInstance()->updateSilhouettes();
+	}
+	
+	// Draw fence around land selections
+	if (for_gl_pick)
+	{
+		if (pick_parcel_walls)
+		{
+			LLViewerParcelMgr::getInstance()->renderParcelCollision();
+		}
+	}
+	else if (( for_hud && selection->getSelectType() == SELECT_TYPE_HUD) ||
+			 (!for_hud && selection->getSelectType() != SELECT_TYPE_HUD))
+	{		
+		LLSelectMgr::getInstance()->renderSilhouettes(for_hud);
+		
+		stop_glerror();
+
+		// setup HUD render
+		if (selection->getSelectType() == SELECT_TYPE_HUD && LLSelectMgr::getInstance()->getSelection()->getObjectCount())
+		{
+			LLBBox hud_bbox = gAgentAvatarp->getHUDBBox();
+
+			// set up transform to encompass bounding box of HUD
+			gGL.matrixMode(LLRender::MM_PROJECTION);
+			gGL.pushMatrix();
+			gGL.loadIdentity();
+			F32 depth = llmax(1.f, hud_bbox.getExtentLocal().mV[VX] * 1.1f);
+			gGL.ortho(-0.5f * LLViewerCamera::getInstance()->getAspect(), 0.5f * LLViewerCamera::getInstance()->getAspect(), -0.5f, 0.5f, 0.f, depth);
+			
+			gGL.matrixMode(LLRender::MM_MODELVIEW);
+			gGL.pushMatrix();
+			gGL.loadIdentity();
+			gGL.loadMatrix(OGL_TO_CFR_ROTATION);		// Load Cory's favorite reference frame
+			gGL.translatef(-hud_bbox.getCenterLocal().mV[VX] + (depth *0.5f), 0.f, 0.f);
+		}
+
+		// Render light for editing
+		if (LLSelectMgr::sRenderLightRadius && LLToolMgr::getInstance()->inEdit())
+		{
+			gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+			LLGLEnable gls_blend(GL_BLEND);
+			LLGLEnable gls_cull(GL_CULL_FACE);
+			LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
+			gGL.matrixMode(LLRender::MM_MODELVIEW);
+			gGL.pushMatrix();
+			if (selection->getSelectType() == SELECT_TYPE_HUD)
+			{
+				F32 zoom = gAgentCamera.mHUDCurZoom;
+				gGL.scalef(zoom, zoom, zoom);
+			}
+
+			struct f : public LLSelectedObjectFunctor
+			{
+				virtual bool apply(LLViewerObject* object)
+				{
+					LLDrawable* drawable = object->mDrawable;
+					if (drawable && drawable->isLight())
+					{
+						LLVOVolume* vovolume = drawable->getVOVolume();
+						gGL.pushMatrix();
+
+						LLVector3 center = drawable->getPositionAgent();
+						gGL.translatef(center[0], center[1], center[2]);
+						F32 scale = vovolume->getLightRadius();
+						gGL.scalef(scale, scale, scale);
+
+						LLColor4 color(vovolume->getLightColor(), .5f);
+						gGL.color4fv(color.mV);
+					
+						//F32 pixel_area = 100000.f;
+						// Render Outside
+						gSphere.render();
+
+						// Render Inside
+						glCullFace(GL_FRONT);
+						gSphere.render();
+						glCullFace(GL_BACK);
+					
+						gGL.popMatrix();
+					}
+					return true;
+				}
+			} func;
+			LLSelectMgr::getInstance()->getSelection()->applyToObjects(&func);
+			
+			gGL.popMatrix();
+		}				
+		
+		// NOTE: The average position for the axis arrows of the selected objects should
+		// not be recalculated at this time.  If they are, then group rotations will break.
+
+		// Draw arrows at average center of all selected objects
+		LLTool* tool = LLToolMgr::getInstance()->getCurrentTool();
+		if (tool)
+		{
+			if(tool->isAlwaysRendered())
+			{
+				tool->render();
+			}
+			else
+			{
+				if( !LLSelectMgr::getInstance()->getSelection()->isEmpty() )
+				{
+					BOOL moveable_object_selected = FALSE;
+					BOOL all_selected_objects_move = TRUE;
+					BOOL all_selected_objects_modify = TRUE;
+					BOOL selecting_linked_set = !gSavedSettings.getBOOL("EditLinkedParts");
+
+					for (LLObjectSelection::iterator iter = LLSelectMgr::getInstance()->getSelection()->begin();
+						 iter != LLSelectMgr::getInstance()->getSelection()->end(); iter++)
+					{
+						LLSelectNode* nodep = *iter;
+						LLViewerObject* object = nodep->getObject();
+						BOOL this_object_movable = FALSE;
+						if (object->permMove() && (object->permModify() || selecting_linked_set))
+						{
+							moveable_object_selected = TRUE;
+							this_object_movable = TRUE;
+						}
+						all_selected_objects_move = all_selected_objects_move && this_object_movable;
+						all_selected_objects_modify = all_selected_objects_modify && object->permModify();
+					}
+
+					BOOL draw_handles = TRUE;
+
+					if (tool == LLToolCompTranslate::getInstance() && (!moveable_object_selected || !all_selected_objects_move))
+					{
+						draw_handles = FALSE;
+					}
+
+					if (tool == LLToolCompRotate::getInstance() && (!moveable_object_selected || !all_selected_objects_move))
+					{
+						draw_handles = FALSE;
+					}
+
+					if ( !all_selected_objects_modify && tool == LLToolCompScale::getInstance() )
+					{
+						draw_handles = FALSE;
+					}
+				
+					if( draw_handles )
+					{
+						tool->render();
+					}
+				}
+			}
+			if (selection->getSelectType() == SELECT_TYPE_HUD && selection->getObjectCount())
+			{
+				gGL.matrixMode(LLRender::MM_PROJECTION);
+				gGL.popMatrix();
+
+				gGL.matrixMode(LLRender::MM_MODELVIEW);
+				gGL.popMatrix();
+				stop_glerror();
+			}
+		}
+	}
+}
+
+// Return a point near the clicked object representative of the place the object was clicked.
+LLVector3d LLViewerWindow::clickPointInWorldGlobal(S32 x, S32 y_from_bot, LLViewerObject* clicked_object) const
+{
+	// create a normalized vector pointing from the camera center into the 
+	// world at the location of the mouse click
+	LLVector3 mouse_direction_global = mouseDirectionGlobal( x, y_from_bot );
+
+	LLVector3d relative_object = clicked_object->getPositionGlobal() - gAgentCamera.getCameraPositionGlobal();
+
+	// make mouse vector as long as object vector, so it touchs a point near
+	// where the user clicked on the object
+	mouse_direction_global *= (F32) relative_object.magVec();
+
+	LLVector3d new_pos;
+	new_pos.setVec(mouse_direction_global);
+	// transform mouse vector back to world coords
+	new_pos += gAgentCamera.getCameraPositionGlobal();
+
+	return new_pos;
+}
+
+
+BOOL LLViewerWindow::clickPointOnSurfaceGlobal(const S32 x, const S32 y, LLViewerObject *objectp, LLVector3d &point_global) const
+{
+	BOOL intersect = FALSE;
+
+//	U8 shape = objectp->mPrimitiveCode & LL_PCODE_BASE_MASK;
+	if (!intersect)
+	{
+		point_global = clickPointInWorldGlobal(x, y, objectp);
+		llinfos << "approx intersection at " <<  (objectp->getPositionGlobal() - point_global) << llendl;
+	}
+	else
+	{
+		llinfos << "good intersection at " <<  (objectp->getPositionGlobal() - point_global) << llendl;
+	}
+
+	return intersect;
+}
+
+void LLViewerWindow::pickAsync(S32 x, S32 y_from_bot, MASK mask, void (*callback)(const LLPickInfo& info), BOOL pick_transparent)
+{
+	BOOL in_build_mode = LLFloaterReg::instanceVisible("build");
+	if (in_build_mode || LLDrawPoolAlpha::sShowDebugAlpha)
+	{
+		// build mode allows interaction with all transparent objects
+		// "Show Debug Alpha" means no object actually transparent
+		pick_transparent = TRUE;
+	}
+
+	LLPickInfo pick_info(LLCoordGL(x, y_from_bot), mask, pick_transparent, TRUE, callback);
+	schedulePick(pick_info);
+}
+
+void LLViewerWindow::schedulePick(LLPickInfo& pick_info)
+{
+	if (mPicks.size() >= 1024 || mWindow->getMinimized())
+	{ //something went wrong, picks are being scheduled but not processed
+		
+		if (pick_info.mPickCallback)
+		{
+			pick_info.mPickCallback(pick_info);
+		}
+	
+		return;
+	}
+	mPicks.push_back(pick_info);
+	
+	// delay further event processing until we receive results of pick
+	// only do this for async picks so that handleMouseUp won't be called
+	// until the pick triggered in handleMouseDown has been processed, for example
+	mWindow->delayInputProcessing();
+}
+
+
+void LLViewerWindow::performPick()
+{
+	if (!mPicks.empty())
+	{
+		std::vector<LLPickInfo>::iterator pick_it;
+		for (pick_it = mPicks.begin(); pick_it != mPicks.end(); ++pick_it)
+		{
+			pick_it->fetchResults();
+		}
+
+		mLastPick = mPicks.back();
+		mPicks.clear();
+	}
+}
+
+void LLViewerWindow::returnEmptyPicks()
+{
+	std::vector<LLPickInfo>::iterator pick_it;
+	for (pick_it = mPicks.begin(); pick_it != mPicks.end(); ++pick_it)
+	{
+		mLastPick = *pick_it;
+		// just trigger callback with empty results
+		if (pick_it->mPickCallback)
+		{
+			pick_it->mPickCallback(*pick_it);
+		}
+	}
+	mPicks.clear();
+}
+
+// Performs the GL object/land pick.
+LLPickInfo LLViewerWindow::pickImmediate(S32 x, S32 y_from_bot,  BOOL pick_transparent)
+{
+	BOOL in_build_mode = LLFloaterReg::instanceVisible("build");
+	if (in_build_mode || LLDrawPoolAlpha::sShowDebugAlpha)
+	{
+		// build mode allows interaction with all transparent objects
+		// "Show Debug Alpha" means no object actually transparent
+		pick_transparent = TRUE;
+	}
+
+	// shortcut queueing in mPicks and just update mLastPick in place
+	MASK	key_mask = gKeyboard->currentMask(TRUE);
+	mLastPick = LLPickInfo(LLCoordGL(x, y_from_bot), key_mask, pick_transparent, TRUE, NULL);
+	mLastPick.fetchResults();
+
+	return mLastPick;
+}
+
+LLHUDIcon* LLViewerWindow::cursorIntersectIcon(S32 mouse_x, S32 mouse_y, F32 depth,
+										   LLVector3* intersection)
+{
+	S32 x = mouse_x;
+	S32 y = mouse_y;
+
+	if ((mouse_x == -1) && (mouse_y == -1)) // use current mouse position
+	{
+		x = getCurrentMouseX();
+		y = getCurrentMouseY();
+	}
+
+	// world coordinates of mouse
+	LLVector3 mouse_direction_global = mouseDirectionGlobal(x,y);
+	LLVector3 mouse_point_global = LLViewerCamera::getInstance()->getOrigin();
+	LLVector3 mouse_world_start = mouse_point_global;
+	LLVector3 mouse_world_end   = mouse_point_global + mouse_direction_global * depth;
+
+	return LLHUDIcon::lineSegmentIntersectAll(mouse_world_start, mouse_world_end, intersection);
+
+	
+}
+
+LLViewerObject* LLViewerWindow::cursorIntersect(S32 mouse_x, S32 mouse_y, F32 depth,
+												LLViewerObject *this_object,
+												S32 this_face,
+												BOOL pick_transparent,
+												S32* face_hit,
+												LLVector3 *intersection,
+												LLVector2 *uv,
+												LLVector3 *normal,
+												LLVector3 *binormal,
+												LLVector3* start,
+												LLVector3* end)
+{
+	S32 x = mouse_x;
+	S32 y = mouse_y;
+
+	if ((mouse_x == -1) && (mouse_y == -1)) // use current mouse position
+	{
+		x = getCurrentMouseX();
+		y = getCurrentMouseY();
+	}
+
+	// HUD coordinates of mouse
+	LLVector3 mouse_point_hud = mousePointHUD(x, y);
+	LLVector3 mouse_hud_start = mouse_point_hud - LLVector3(depth, 0, 0);
+	LLVector3 mouse_hud_end   = mouse_point_hud + LLVector3(depth, 0, 0);
+	
+	// world coordinates of mouse
+	LLVector3 mouse_direction_global = mouseDirectionGlobal(x,y);
+	LLVector3 mouse_point_global = LLViewerCamera::getInstance()->getOrigin();
+	
+	//get near clip plane
+	LLVector3 n = LLViewerCamera::getInstance()->getAtAxis();
+	LLVector3 p = mouse_point_global + n * LLViewerCamera::getInstance()->getNear();
+
+	//project mouse point onto plane
+	LLVector3 pos;
+	line_plane(mouse_point_global, mouse_direction_global, p, n, pos);
+	mouse_point_global = pos;
+
+	LLVector3 mouse_world_start = mouse_point_global;
+	LLVector3 mouse_world_end   = mouse_point_global + mouse_direction_global * depth;
+
+	if (!LLViewerJoystick::getInstance()->getOverrideCamera())
+	{ //always set raycast intersection to mouse_world_end unless
+		//flycam is on (for DoF effect)
+		gDebugRaycastIntersection = mouse_world_end;
+	}
+
+	if (start)
+	{
+		*start = mouse_world_start;
+	}
+
+	if (end)
+	{
+		*end = mouse_world_end;
+	}
+
+	LLViewerObject* found = NULL;
+
+	if (this_object)  // check only this object
+	{
+		if (this_object->isHUDAttachment()) // is a HUD object?
+		{
+			if (this_object->lineSegmentIntersect(mouse_hud_start, mouse_hud_end, this_face, pick_transparent,
+												  face_hit, intersection, uv, normal, binormal))
+			{
+				found = this_object;
+			}
+		}
+		else // is a world object
+		{
+			if (this_object->lineSegmentIntersect(mouse_world_start, mouse_world_end, this_face, pick_transparent,
+												  face_hit, intersection, uv, normal, binormal))
+			{
+				found = this_object;
+			}
+		}
+	}
+	else // check ALL objects
+	{
+		found = gPipeline.lineSegmentIntersectInHUD(mouse_hud_start, mouse_hud_end, pick_transparent,
+													face_hit, intersection, uv, normal, binormal);
+
+		if (!found) // if not found in HUD, look in world:
+		{
+			found = gPipeline.lineSegmentIntersectInWorld(mouse_world_start, mouse_world_end, pick_transparent,
+														  face_hit, intersection, uv, normal, binormal);
+			if (found && !pick_transparent)
+			{
+				gDebugRaycastIntersection = *intersection;
+			}
+		}
+	}
+
+	return found;
+}
+
+// Returns unit vector relative to camera
+// indicating direction of point on screen x,y
+LLVector3 LLViewerWindow::mouseDirectionGlobal(const S32 x, const S32 y) const
+{
+	// find vertical field of view
+	F32			fov = LLViewerCamera::getInstance()->getView();
+
+	// find world view center in scaled ui coordinates
+	F32			center_x = getWorldViewRectScaled().getCenterX();
+	F32			center_y = getWorldViewRectScaled().getCenterY();
+
+	// calculate pixel distance to screen
+	F32			distance = ((F32)getWorldViewHeightScaled() * 0.5f) / (tan(fov / 2.f));
+
+	// calculate click point relative to middle of screen
+	F32			click_x = x - center_x;
+	F32			click_y = y - center_y;
+
+	// compute mouse vector
+	LLVector3	mouse_vector =	distance * LLViewerCamera::getInstance()->getAtAxis()
+								- click_x * LLViewerCamera::getInstance()->getLeftAxis()
+								+ click_y * LLViewerCamera::getInstance()->getUpAxis();
+
+	mouse_vector.normVec();
+
+	return mouse_vector;
+}
+
+LLVector3 LLViewerWindow::mousePointHUD(const S32 x, const S32 y) const
+{
+	// find screen resolution
+	S32			height = getWorldViewHeightScaled();
+
+	// find world view center
+	F32			center_x = getWorldViewRectScaled().getCenterX();
+	F32			center_y = getWorldViewRectScaled().getCenterY();
+
+	// remap with uniform scale (1/height) so that top is -0.5, bottom is +0.5
+	F32 hud_x = -((F32)x - center_x)  / height;
+	F32 hud_y = ((F32)y - center_y) / height;
+
+	return LLVector3(0.f, hud_x/gAgentCamera.mHUDCurZoom, hud_y/gAgentCamera.mHUDCurZoom);
+}
+
+// Returns unit vector relative to camera in camera space
+// indicating direction of point on screen x,y
+LLVector3 LLViewerWindow::mouseDirectionCamera(const S32 x, const S32 y) const
+{
+	// find vertical field of view
+	F32			fov_height = LLViewerCamera::getInstance()->getView();
+	F32			fov_width = fov_height * LLViewerCamera::getInstance()->getAspect();
+
+	// find screen resolution
+	S32			height = getWorldViewHeightScaled();
+	S32			width = getWorldViewWidthScaled();
+
+	// find world view center
+	F32			center_x = getWorldViewRectScaled().getCenterX();
+	F32			center_y = getWorldViewRectScaled().getCenterY();
+
+	// calculate click point relative to middle of screen
+	F32			click_x = (((F32)x - center_x) / (F32)width) * fov_width * -1.f;
+	F32			click_y = (((F32)y - center_y) / (F32)height) * fov_height;
+
+	// compute mouse vector
+	LLVector3	mouse_vector =	LLVector3(0.f, 0.f, -1.f);
+	LLQuaternion mouse_rotate;
+	mouse_rotate.setQuat(click_y, click_x, 0.f);
+
+	mouse_vector = mouse_vector * mouse_rotate;
+	// project to z = -1 plane;
+	mouse_vector = mouse_vector * (-1.f / mouse_vector.mV[VZ]);
+
+	return mouse_vector;
+}
+
+
+
+BOOL LLViewerWindow::mousePointOnPlaneGlobal(LLVector3d& point, const S32 x, const S32 y, 
+										const LLVector3d &plane_point_global, 
+										const LLVector3 &plane_normal_global)
+{
+	LLVector3d	mouse_direction_global_d;
+
+	mouse_direction_global_d.setVec(mouseDirectionGlobal(x,y));
+	LLVector3d	plane_normal_global_d;
+	plane_normal_global_d.setVec(plane_normal_global);
+	F64 plane_mouse_dot = (plane_normal_global_d * mouse_direction_global_d);
+	LLVector3d plane_origin_camera_rel = plane_point_global - gAgentCamera.getCameraPositionGlobal();
+	F64	mouse_look_at_scale = (plane_normal_global_d * plane_origin_camera_rel)
+								/ plane_mouse_dot;
+	if (llabs(plane_mouse_dot) < 0.00001)
+	{
+		// if mouse is parallel to plane, return closest point on line through plane origin
+		// that is parallel to camera plane by scaling mouse direction vector
+		// by distance to plane origin, modulated by deviation of mouse direction from plane origin
+		LLVector3d plane_origin_dir = plane_origin_camera_rel;
+		plane_origin_dir.normVec();
+		
+		mouse_look_at_scale = plane_origin_camera_rel.magVec() / (plane_origin_dir * mouse_direction_global_d);
+	}
+
+	point = gAgentCamera.getCameraPositionGlobal() + mouse_look_at_scale * mouse_direction_global_d;
+
+	return mouse_look_at_scale > 0.0;
+}
+
+
+// Returns global position
+BOOL LLViewerWindow::mousePointOnLandGlobal(const S32 x, const S32 y, LLVector3d *land_position_global)
+{
+	LLVector3		mouse_direction_global = mouseDirectionGlobal(x,y);
+	F32				mouse_dir_scale;
+	BOOL			hit_land = FALSE;
+	LLViewerRegion	*regionp;
+	F32			land_z;
+	const F32	FIRST_PASS_STEP = 1.0f;		// meters
+	const F32	SECOND_PASS_STEP = 0.1f;	// meters
+	LLVector3d	camera_pos_global;
+
+	camera_pos_global = gAgentCamera.getCameraPositionGlobal();
+	LLVector3d		probe_point_global;
+	LLVector3		probe_point_region;
+
+	// walk forwards to find the point
+	for (mouse_dir_scale = FIRST_PASS_STEP; mouse_dir_scale < gAgentCamera.mDrawDistance; mouse_dir_scale += FIRST_PASS_STEP)
+	{
+		LLVector3d mouse_direction_global_d;
+		mouse_direction_global_d.setVec(mouse_direction_global * mouse_dir_scale);
+		probe_point_global = camera_pos_global + mouse_direction_global_d;
+
+		regionp = LLWorld::getInstance()->resolveRegionGlobal(probe_point_region, probe_point_global);
+
+		if (!regionp)
+		{
+			// ...we're outside the world somehow
+			continue;
+		}
+
+		S32 i = (S32) (probe_point_region.mV[VX]/regionp->getLand().getMetersPerGrid());
+		S32 j = (S32) (probe_point_region.mV[VY]/regionp->getLand().getMetersPerGrid());
+		S32 grids_per_edge = (S32) regionp->getLand().mGridsPerEdge;
+		if ((i >= grids_per_edge) || (j >= grids_per_edge))
+		{
+			//llinfos << "LLViewerWindow::mousePointOnLand probe_point is out of region" << llendl;
+			continue;
+		}
+
+		land_z = regionp->getLand().resolveHeightRegion(probe_point_region);
+
+		//llinfos << "mousePointOnLand initial z " << land_z << llendl;
+
+		if (probe_point_region.mV[VZ] < land_z)
+		{
+			// ...just went under land
+
+			// cout << "under land at " << probe_point << " scale " << mouse_vec_scale << endl;
+
+			hit_land = TRUE;
+			break;
+		}
+	}
+
+
+	if (hit_land)
+	{
+		// Don't go more than one step beyond where we stopped above.
+		// This can't just be "mouse_vec_scale" because floating point error
+		// will stop the loop before the last increment.... X - 1.0 + 0.1 + 0.1 + ... + 0.1 != X
+		F32 stop_mouse_dir_scale = mouse_dir_scale + FIRST_PASS_STEP;
+
+		// take a step backwards, then walk forwards again to refine position
+		for ( mouse_dir_scale -= FIRST_PASS_STEP; mouse_dir_scale <= stop_mouse_dir_scale; mouse_dir_scale += SECOND_PASS_STEP)
+		{
+			LLVector3d mouse_direction_global_d;
+			mouse_direction_global_d.setVec(mouse_direction_global * mouse_dir_scale);
+			probe_point_global = camera_pos_global + mouse_direction_global_d;
+
+			regionp = LLWorld::getInstance()->resolveRegionGlobal(probe_point_region, probe_point_global);
+
+			if (!regionp)
+			{
+				// ...we're outside the world somehow
+				continue;
+			}
+
+			/*
+			i = (S32) (local_probe_point.mV[VX]/regionp->getLand().getMetersPerGrid());
+			j = (S32) (local_probe_point.mV[VY]/regionp->getLand().getMetersPerGrid());
+			if ((i >= regionp->getLand().mGridsPerEdge) || (j >= regionp->getLand().mGridsPerEdge))
+			{
+				// llinfos << "LLViewerWindow::mousePointOnLand probe_point is out of region" << llendl;
+				continue;
+			}
+			land_z = regionp->getLand().mSurfaceZ[ i + j * (regionp->getLand().mGridsPerEdge) ];
+			*/
+
+			land_z = regionp->getLand().resolveHeightRegion(probe_point_region);
+
+			//llinfos << "mousePointOnLand refine z " << land_z << llendl;
+
+			if (probe_point_region.mV[VZ] < land_z)
+			{
+				// ...just went under land again
+
+				*land_position_global = probe_point_global;
+				return TRUE;
+			}
+		}
+	}
+
+	return FALSE;
+}
+
+// Saves an image to the harddrive as "SnapshotX" where X >= 1.
+BOOL LLViewerWindow::saveImageNumbered(LLImageFormatted *image, bool force_picker)
+{
+	if (!image)
+	{
+		llwarns << "No image to save" << llendl;
+		return FALSE;
+	}
+
+	LLFilePicker::ESaveFilter pick_type;
+	std::string extension("." + image->getExtension());
+	if (extension == ".j2c")
+		pick_type = LLFilePicker::FFSAVE_J2C;
+	else if (extension == ".bmp")
+		pick_type = LLFilePicker::FFSAVE_BMP;
+	else if (extension == ".jpg")
+		pick_type = LLFilePicker::FFSAVE_JPEG;
+	else if (extension == ".png")
+		pick_type = LLFilePicker::FFSAVE_PNG;
+	else if (extension == ".tga")
+		pick_type = LLFilePicker::FFSAVE_TGA;
+	else
+		pick_type = LLFilePicker::FFSAVE_ALL; // ???
+	
+	// Get a base file location if needed.
+	if (force_picker || !isSnapshotLocSet())
+	{
+		std::string proposed_name( sSnapshotBaseName );
+
+		// getSaveFile will append an appropriate extension to the proposed name, based on the ESaveFilter constant passed in.
+
+		// pick a directory in which to save
+		LLFilePicker& picker = LLFilePicker::instance();
+		if (!picker.getSaveFile(pick_type, proposed_name))
+		{
+			// Clicked cancel
+			return FALSE;
+		}
+
+		// Copy the directory + file name
+		std::string filepath = picker.getFirstFile();
+
+		LLViewerWindow::sSnapshotBaseName = gDirUtilp->getBaseFileName(filepath, true);
+		LLViewerWindow::sSnapshotDir = gDirUtilp->getDirName(filepath);
+	}
+
+	// Look for an unused file name
+	std::string filepath;
+	S32 i = 1;
+	S32 err = 0;
+
+	do
+	{
+		filepath = sSnapshotDir;
+		filepath += gDirUtilp->getDirDelimiter();
+		filepath += sSnapshotBaseName;
+		filepath += llformat("_%.3d",i);
+		filepath += extension;
+
+		llstat stat_info;
+		err = LLFile::stat( filepath, &stat_info );
+		i++;
+	}
+	while( -1 != err );  // search until the file is not found (i.e., stat() gives an error).
+
+	llinfos << "Saving snapshot to " << filepath << llendl;
+	return image->save(filepath);
+}
+
+void LLViewerWindow::resetSnapshotLoc()
+{
+	sSnapshotDir.clear();
+}
+
+// static
+void LLViewerWindow::movieSize(S32 new_width, S32 new_height)
+{
+	LLCoordWindow size;
+	gViewerWindow->getWindow()->getSize(&size);
+	if ( size.mX != new_width
+		|| size.mY != new_height)
+	{
+		LLCoordWindow new_size(new_width, new_height);
+		LLCoordScreen screen_size;
+		gViewerWindow->getWindow()->convertCoords(new_size, &screen_size);
+		gViewerWindow->getWindow()->setSize(screen_size);
+	}
+}
+
+BOOL LLViewerWindow::saveSnapshot( const std::string& filepath, S32 image_width, S32 image_height, BOOL show_ui, BOOL do_rebuild, ESnapshotType type)
+{
+	llinfos << "Saving snapshot to: " << filepath << llendl;
+
+	LLPointer<LLImageRaw> raw = new LLImageRaw;
+	BOOL success = rawSnapshot(raw, image_width, image_height, TRUE, FALSE, show_ui, do_rebuild);
+
+	if (success)
+	{
+		LLPointer<LLImageBMP> bmp_image = new LLImageBMP;
+		success = bmp_image->encode(raw, 0.0f);
+		if( success )
+		{
+			success = bmp_image->save(filepath);
+		}
+		else
+		{
+			llwarns << "Unable to encode bmp snapshot" << llendl;
+		}
+	}
+	else
+	{
+		llwarns << "Unable to capture raw snapshot" << llendl;
+	}
+
+	return success;
+}
+
+
+void LLViewerWindow::playSnapshotAnimAndSound()
+{
+	if (gSavedSettings.getBOOL("QuietSnapshotsToDisk"))
+	{
+		return;
+	}
+	gAgent.sendAnimationRequest(ANIM_AGENT_SNAPSHOT, ANIM_REQUEST_START);
+	send_sound_trigger(LLUUID(gSavedSettings.getString("UISndSnapshot")), 1.0f);
+}
+
+BOOL LLViewerWindow::thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 preview_height, BOOL show_ui, BOOL do_rebuild, ESnapshotType type)
+{
+	return rawSnapshot(raw, preview_width, preview_height, FALSE, FALSE, show_ui, do_rebuild, type);
+}
+
+// Saves the image from the screen to a raw image
+// Since the required size might be bigger than the available screen, this method rerenders the scene in parts (called subimages) and copy
+// the results over to the final raw image.
+BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_height, 
+								 BOOL keep_window_aspect, BOOL is_texture, BOOL show_ui, BOOL do_rebuild, ESnapshotType type, S32 max_size)
+{
+	if (!raw)
+	{
+		return FALSE;
+	}
+	//check if there is enough memory for the snapshot image
+	if(LLPipeline::sMemAllocationThrottled)
+	{
+		return FALSE ; //snapshot taking is disabled due to memory restriction.
+	}
+	if(image_width * image_height > (1 << 22)) //if snapshot image is larger than 2K by 2K
+	{
+		if(!LLMemory::tryToAlloc(NULL, image_width * image_height * 3))
+		{
+			llwarns << "No enough memory to take the snapshot with size (w : h): " << image_width << " : " << image_height << llendl ;
+			return FALSE ; //there is no enough memory for taking this snapshot.
+		}
+	}
+
+	// PRE SNAPSHOT
+	gDisplaySwapBuffers = FALSE;
+	
+	glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+	setCursor(UI_CURSOR_WAIT);
+
+	// Hide all the UI widgets first and draw a frame
+	BOOL prev_draw_ui = gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI) ? TRUE : FALSE;
+
+	if ( prev_draw_ui != show_ui)
+	{
+		LLPipeline::toggleRenderDebugFeature((void*)LLPipeline::RENDER_DEBUG_FEATURE_UI);
+	}
+
+	BOOL hide_hud = !gSavedSettings.getBOOL("RenderHUDInSnapshot") && LLPipeline::sShowHUDAttachments;
+	if (hide_hud)
+	{
+		LLPipeline::sShowHUDAttachments = FALSE;
+	}
+
+	// if not showing ui, use full window to render world view
+	updateWorldViewRect(!show_ui);
+
+	// Copy screen to a buffer
+	// crop sides or top and bottom, if taking a snapshot of different aspect ratio
+	// from window
+	LLRect window_rect = show_ui ? getWindowRectRaw() : getWorldViewRectRaw(); 
+
+	S32 snapshot_width  = window_rect.getWidth();
+	S32 snapshot_height = window_rect.getHeight();
+	// SNAPSHOT
+	S32 window_width  = snapshot_width;
+	S32 window_height = snapshot_height;
+	
+	// Note: Scaling of the UI is currently *not* supported so we limit the output size if UI is requested
+	if (show_ui)
+	{
+		// If the user wants the UI, limit the output size to the available screen size
+		image_width  = llmin(image_width, window_width);
+		image_height = llmin(image_height, window_height);
+	}
+
+	F32 scale_factor = 1.0f ;
+	if (!keep_window_aspect || (image_width > window_width) || (image_height > window_height))
+	{	
+		// if image cropping or need to enlarge the scene, compute a scale_factor
+		F32 ratio = llmin( (F32)window_width / image_width , (F32)window_height / image_height) ;
+		snapshot_width  = (S32)(ratio * image_width) ;
+		snapshot_height = (S32)(ratio * image_height) ;
+		scale_factor = llmax(1.0f, 1.0f / ratio) ;
+	}
+	
+	if (show_ui && scale_factor > 1.f)
+	{
+		// Note: we should never get there...
+		llwarns << "over scaling UI not supported." << llendl;
+	}
+
+	S32 buffer_x_offset = llfloor(((window_width  - snapshot_width)  * scale_factor) / 2.f);
+	S32 buffer_y_offset = llfloor(((window_height - snapshot_height) * scale_factor) / 2.f);
+
+	S32 image_buffer_x = llfloor(snapshot_width  * scale_factor) ;
+	S32 image_buffer_y = llfloor(snapshot_height * scale_factor) ;
+
+	if ((image_buffer_x > max_size) || (image_buffer_y > max_size)) // boundary check to avoid memory overflow
+	{
+		scale_factor *= llmin((F32)max_size / image_buffer_x, (F32)max_size / image_buffer_y) ;
+		image_buffer_x = llfloor(snapshot_width  * scale_factor) ;
+		image_buffer_y = llfloor(snapshot_height * scale_factor) ;
+	}
+	if ((image_buffer_x > 0) && (image_buffer_y > 0))
+	{
+		raw->resize(image_buffer_x, image_buffer_y, 3);
+	}
+	else
+	{
+		return FALSE ;
+	}
+	if (raw->isBufferInvalid())
+	{
+		return FALSE ;
+	}
+
+	BOOL high_res = scale_factor >= 2.f; // Font scaling is slow, only do so if rez is much higher
+	if (high_res && show_ui)
+	{
+		// Note: we should never get there...
+		llwarns << "High res UI snapshot not supported. " << llendl;
+		/*send_agent_pause();
+		//rescale fonts
+		initFonts(scale_factor);
+		LLHUDObject::reshapeAll();*/
+	}
+
+	S32 output_buffer_offset_y = 0;
+
+	F32 depth_conversion_factor_1 = (LLViewerCamera::getInstance()->getFar() + LLViewerCamera::getInstance()->getNear()) / (2.f * LLViewerCamera::getInstance()->getFar() * LLViewerCamera::getInstance()->getNear());
+	F32 depth_conversion_factor_2 = (LLViewerCamera::getInstance()->getFar() - LLViewerCamera::getInstance()->getNear()) / (2.f * LLViewerCamera::getInstance()->getFar() * LLViewerCamera::getInstance()->getNear());
+
+	gObjectList.generatePickList(*LLViewerCamera::getInstance());
+
+	// Subimages are in fact partial rendering of the final view. This happens when the final view is bigger than the screen.
+	// In most common cases, scale_factor is 1 and there's no more than 1 iteration on x and y
+	for (int subimage_y = 0; subimage_y < scale_factor; ++subimage_y)
+	{
+		S32 subimage_y_offset = llclamp(buffer_y_offset - (subimage_y * window_height), 0, window_height);;
+		// handle fractional columns
+		U32 read_height = llmax(0, (window_height - subimage_y_offset) -
+			llmax(0, (window_height * (subimage_y + 1)) - (buffer_y_offset + raw->getHeight())));
+
+		S32 output_buffer_offset_x = 0;
+		for (int subimage_x = 0; subimage_x < scale_factor; ++subimage_x)
+		{
+			gDisplaySwapBuffers = FALSE;
+			gDepthDirty = TRUE;
+
+			S32 subimage_x_offset = llclamp(buffer_x_offset - (subimage_x * window_width), 0, window_width);
+			// handle fractional rows
+			U32 read_width = llmax(0, (window_width - subimage_x_offset) -
+									llmax(0, (window_width * (subimage_x + 1)) - (buffer_x_offset + raw->getWidth())));
+			
+			// Skip rendering and sampling altogether if either width or height is degenerated to 0 (common in cropping cases)
+			if (read_width && read_height)
+			{
+				const U32 subfield = subimage_x+(subimage_y*llceil(scale_factor));
+				display(do_rebuild, scale_factor, subfield, TRUE);
+				
+				if (!LLPipeline::sRenderDeferred)
+				{
+					// Required for showing the GUI in snapshots and performing bloom composite overlay
+					// Call even if show_ui is FALSE
+					render_ui(scale_factor, subfield);
+				}
+				
+				for (U32 out_y = 0; out_y < read_height ; out_y++)
+				{
+					S32 output_buffer_offset = ( 
+												(out_y * (raw->getWidth())) // ...plus iterated y...
+												+ (window_width * subimage_x) // ...plus subimage start in x...
+												+ (raw->getWidth() * window_height * subimage_y) // ...plus subimage start in y...
+												- output_buffer_offset_x // ...minus buffer padding x...
+												- (output_buffer_offset_y * (raw->getWidth()))  // ...minus buffer padding y...
+												) * raw->getComponents();
+				
+					// Ping the watchdog thread every 100 lines to keep us alive (arbitrary number, feel free to change)
+					if (out_y % 100 == 0)
+					{
+						LLAppViewer::instance()->pingMainloopTimeout("LLViewerWindow::rawSnapshot");
+					}
+				
+					if (type == SNAPSHOT_TYPE_COLOR)
+					{
+						glReadPixels(
+									 subimage_x_offset, out_y + subimage_y_offset,
+									 read_width, 1,
+									 GL_RGB, GL_UNSIGNED_BYTE,
+									 raw->getData() + output_buffer_offset
+									 );
+					}
+					else // SNAPSHOT_TYPE_DEPTH
+					{
+						LLPointer<LLImageRaw> depth_line_buffer = new LLImageRaw(read_width, 1, sizeof(GL_FLOAT)); // need to store floating point values
+						glReadPixels(
+									 subimage_x_offset, out_y + subimage_y_offset,
+									 read_width, 1,
+									 GL_DEPTH_COMPONENT, GL_FLOAT,
+									 depth_line_buffer->getData()// current output pixel is beginning of buffer...
+									 );
+
+						for (S32 i = 0; i < (S32)read_width; i++)
+						{
+							F32 depth_float = *(F32*)(depth_line_buffer->getData() + (i * sizeof(F32)));
+					
+							F32 linear_depth_float = 1.f / (depth_conversion_factor_1 - (depth_float * depth_conversion_factor_2));
+							U8 depth_byte = F32_to_U8(linear_depth_float, LLViewerCamera::getInstance()->getNear(), LLViewerCamera::getInstance()->getFar());
+							// write converted scanline out to result image
+							for (S32 j = 0; j < raw->getComponents(); j++)
+							{
+								*(raw->getData() + output_buffer_offset + (i * raw->getComponents()) + j) = depth_byte;
+							}
+						}
+					}
+				}
+			}
+			output_buffer_offset_x += subimage_x_offset;
+			stop_glerror();
+		}
+		output_buffer_offset_y += subimage_y_offset;
+	}
+
+	gDisplaySwapBuffers = FALSE;
+	gDepthDirty = TRUE;
+
+	// POST SNAPSHOT
+	if (!gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
+	{
+		LLPipeline::toggleRenderDebugFeature((void*)LLPipeline::RENDER_DEBUG_FEATURE_UI);
+	}
+
+	if (hide_hud)
+	{
+		LLPipeline::sShowHUDAttachments = TRUE;
+	}
+
+	/*if (high_res)
+	{
+		initFonts(1.f);
+		LLHUDObject::reshapeAll();
+	}*/
+
+	// Pre-pad image to number of pixels such that the line length is a multiple of 4 bytes (for BMP encoding)
+	// Note: this formula depends on the number of components being 3.  Not obvious, but it's correct.	
+	image_width += (image_width * 3) % 4;
+
+	BOOL ret = TRUE ;
+	// Resize image
+	if(llabs(image_width - image_buffer_x) > 4 || llabs(image_height - image_buffer_y) > 4)
+	{
+		ret = raw->scale( image_width, image_height );  
+	}
+	else if(image_width != image_buffer_x || image_height != image_buffer_y)
+	{
+		ret = raw->scale( image_width, image_height, FALSE );  
+	}
+	
+
+	setCursor(UI_CURSOR_ARROW);
+
+	if (do_rebuild)
+	{
+		// If we had to do a rebuild, that means that the lists of drawables to be rendered
+		// was empty before we started.
+		// Need to reset these, otherwise we call state sort on it again when render gets called the next time
+		// and we stand a good chance of crashing on rebuild because the render drawable arrays have multiple copies of
+		// objects on them.
+		gPipeline.resetDrawOrders();
+	}
+
+	if (high_res)
+	{
+		send_agent_resume();
+	}
+
+	return ret;
+}
+
+void LLViewerWindow::destroyWindow()
+{
+	if (mWindow)
+	{
+		LLWindowManager::destroyWindow(mWindow);
+	}
+	mWindow = NULL;
+}
+
+
+void LLViewerWindow::drawMouselookInstructions()
+{
+	// Draw instructions for mouselook ("Press ESC to return to World View" partially transparent at the bottom of the screen.)
+	const std::string instructions = LLTrans::getString("LeaveMouselook");
+	const LLFontGL* font = LLFontGL::getFont(LLFontDescriptor("SansSerif", "Large", LLFontGL::BOLD));
+	
+	//to be on top of Bottom bar when it is opened
+	const S32 INSTRUCTIONS_PAD = 50;
+
+	font->renderUTF8( 
+		instructions, 0,
+		getWorldViewRectScaled().getCenterX(),
+		getWorldViewRectScaled().mBottom + INSTRUCTIONS_PAD,
+		LLColor4( 1.0f, 1.0f, 1.0f, 0.5f ),
+		LLFontGL::HCENTER, LLFontGL::TOP,
+		LLFontGL::NORMAL,LLFontGL::DROP_SHADOW);
+}
+
+void* LLViewerWindow::getPlatformWindow() const
+{
+	return mWindow->getPlatformWindow();
+}
+
+void* LLViewerWindow::getMediaWindow() 	const
+{
+	return mWindow->getMediaWindow();
+}
+
+void LLViewerWindow::focusClient()		const
+{
+	return mWindow->focusClient();
+}
+
+LLRootView*	LLViewerWindow::getRootView() const
+{
+	return mRootView;
+}
+
+LLRect LLViewerWindow::getWorldViewRectScaled() const
+{
+	return mWorldViewRectScaled;
+}
+
+S32 LLViewerWindow::getWorldViewHeightScaled() const
+{
+	return mWorldViewRectScaled.getHeight();
+}
+
+S32 LLViewerWindow::getWorldViewWidthScaled() const
+{
+	return mWorldViewRectScaled.getWidth();
+}
+
+
+S32 LLViewerWindow::getWorldViewHeightRaw() const
+{
+	return mWorldViewRectRaw.getHeight(); 
+}
+
+S32 LLViewerWindow::getWorldViewWidthRaw() const
+{
+	return mWorldViewRectRaw.getWidth(); 
+}
+
+S32	LLViewerWindow::getWindowHeightScaled()	const 	
+{ 
+	return mWindowRectScaled.getHeight(); 
+}
+
+S32	LLViewerWindow::getWindowWidthScaled() const 	
+{ 
+	return mWindowRectScaled.getWidth(); 
+}
+
+S32	LLViewerWindow::getWindowHeightRaw()	const 	
+{ 
+	return mWindowRectRaw.getHeight(); 
+}
+
+S32	LLViewerWindow::getWindowWidthRaw() const 	
+{ 
+	return mWindowRectRaw.getWidth(); 
+}
+
+void LLViewerWindow::setup2DRender()
+{
+	// setup ortho camera
+	gl_state_for_2d(mWindowRectRaw.getWidth(), mWindowRectRaw.getHeight());
+	setup2DViewport();
+}
+
+void LLViewerWindow::setup2DViewport(S32 x_offset, S32 y_offset)
+{
+	gGLViewport[0] = mWindowRectRaw.mLeft + x_offset;
+	gGLViewport[1] = mWindowRectRaw.mBottom + y_offset;
+	gGLViewport[2] = mWindowRectRaw.getWidth();
+	gGLViewport[3] = mWindowRectRaw.getHeight();
+	glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
+}
+
+
+void LLViewerWindow::setup3DRender()
+{
+	// setup perspective camera
+	LLViewerCamera::getInstance()->setPerspective(NOT_FOR_SELECTION, mWorldViewRectRaw.mLeft, mWorldViewRectRaw.mBottom,  mWorldViewRectRaw.getWidth(), mWorldViewRectRaw.getHeight(), FALSE, LLViewerCamera::getInstance()->getNear(), MAX_FAR_CLIP*2.f);
+	setup3DViewport();
+}
+
+void LLViewerWindow::setup3DViewport(S32 x_offset, S32 y_offset)
+{
+	gGLViewport[0] = mWorldViewRectRaw.mLeft + x_offset;
+	gGLViewport[1] = mWorldViewRectRaw.mBottom + y_offset;
+	gGLViewport[2] = mWorldViewRectRaw.getWidth();
+	gGLViewport[3] = mWorldViewRectRaw.getHeight();
+	glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
+}
+
+void LLViewerWindow::revealIntroPanel()
+{
+	if (mProgressView)
+	{
+		mProgressView->revealIntroPanel();
+	}
+}
+
+void LLViewerWindow::setShowProgress(const BOOL show)
+{
+	if (mProgressView)
+	{
+		mProgressView->setVisible(show);
+	}
+}
+
+void LLViewerWindow::setStartupComplete()
+{
+	if (mProgressView)
+	{
+		mProgressView->setStartupComplete();
+	}
+}
+
+BOOL LLViewerWindow::getShowProgress() const
+{
+	return (mProgressView && mProgressView->getVisible());
+}
+
+void LLViewerWindow::setProgressString(const std::string& string)
+{
+	if (mProgressView)
+	{
+		mProgressView->setText(string);
+	}
+}
+
+void LLViewerWindow::setProgressMessage(const std::string& msg)
+{
+	if(mProgressView)
+	{
+		mProgressView->setMessage(msg);
+	}
+}
+
+void LLViewerWindow::setProgressPercent(const F32 percent)
+{
+	if (mProgressView)
+	{
+		mProgressView->setPercent(percent);
+	}
+}
+
+void LLViewerWindow::setProgressCancelButtonVisible( BOOL b, const std::string& label )
+{
+	if (mProgressView)
+	{
+		mProgressView->setCancelButtonVisible( b, label );
+	}
+}
+
+
+LLProgressView *LLViewerWindow::getProgressView() const
+{
+	return mProgressView;
+}
+
+void LLViewerWindow::dumpState()
+{
+	llinfos << "LLViewerWindow Active " << S32(mActive) << llendl;
+	llinfos << "mWindow visible " << S32(mWindow->getVisible())
+		<< " minimized " << S32(mWindow->getMinimized())
+		<< llendl;
+}
+
+void LLViewerWindow::stopGL(BOOL save_state)
+{
+	//Note: --bao
+	//if not necessary, do not change the order of the function calls in this function.
+	//if change something, make sure it will not break anything.
+	//especially be careful to put anything behind gTextureList.destroyGL(save_state);
+	if (!gGLManager.mIsDisabled)
+	{
+		llinfos << "Shutting down GL..." << llendl;
+
+		// Pause texture decode threads (will get unpaused during main loop)
+		LLAppViewer::getTextureCache()->pause();
+		LLAppViewer::getImageDecodeThread()->pause();
+		LLAppViewer::getTextureFetch()->pause();
+				
+		gSky.destroyGL();
+		stop_glerror();		
+
+		LLManipTranslate::destroyGL() ;
+		stop_glerror();		
+
+		gBumpImageList.destroyGL();
+		stop_glerror();
+
+		LLFontGL::destroyAllGL();
+		stop_glerror();
+
+		LLVOAvatar::destroyGL();
+		stop_glerror();
+
+		LLViewerDynamicTexture::destroyGL();
+		stop_glerror();
+
+		if (gPipeline.isInit())
+		{
+			gPipeline.destroyGL();
+		}
+		
+		gBox.cleanupGL();
+		
+		if(gPostProcess)
+		{
+			gPostProcess->invalidate();
+		}
+
+		gTextureList.destroyGL(save_state);
+		stop_glerror();
+		
+		gGLManager.mIsDisabled = TRUE;
+		stop_glerror();
+		
+		llinfos << "Remaining allocated texture memory: " << LLImageGL::sGlobalTextureMemoryInBytes << " bytes" << llendl;
+	}
+}
+
+void LLViewerWindow::restoreGL(const std::string& progress_message)
+{
+	//Note: --bao
+	//if not necessary, do not change the order of the function calls in this function.
+	//if change something, make sure it will not break anything. 
+	//especially, be careful to put something before gTextureList.restoreGL();
+	if (gGLManager.mIsDisabled)
+	{
+		llinfos << "Restoring GL..." << llendl;
+		gGLManager.mIsDisabled = FALSE;
+		
+		initGLDefaults();
+		LLGLState::restoreGL();
+		
+		gTextureList.restoreGL();
+		
+		// for future support of non-square pixels, and fonts that are properly stretched
+		//LLFontGL::destroyDefaultFonts();
+		initFonts();
+				
+		gSky.restoreGL();
+		gPipeline.restoreGL();
+		LLDrawPoolWater::restoreGL();
+		LLManipTranslate::restoreGL();
+		
+		gBumpImageList.restoreGL();
+		LLViewerDynamicTexture::restoreGL();
+		LLVOAvatar::restoreGL();
+		
+		gResizeScreenTexture = TRUE;
+		gWindowResized = TRUE;
+
+		if (isAgentAvatarValid() && !gAgentAvatarp->isUsingBakedTextures())
+		{
+			LLVisualParamHint::requestHintUpdates();
+		}
+
+		if (!progress_message.empty())
+		{
+			gRestoreGLTimer.reset();
+			gRestoreGL = TRUE;
+			setShowProgress(TRUE);
+			setProgressString(progress_message);
+		}
+		llinfos << "...Restoring GL done" << llendl;
+		if(!LLAppViewer::instance()->restoreErrorTrap())
+		{
+			llwarns << " Someone took over my signal/exception handler (post restoreGL)!" << llendl;
+		}
+
+	}
+}
+
+void LLViewerWindow::initFonts(F32 zoom_factor)
+{
+	LLFontGL::destroyAllGL();
+	// Initialize with possibly different zoom factor
+
+	LLFontManager::initClass();
+
+	LLFontGL::initClass( gSavedSettings.getF32("FontScreenDPI"),
+								mDisplayScale.mV[VX] * zoom_factor,
+								mDisplayScale.mV[VY] * zoom_factor,
+								gDirUtilp->getAppRODataDir(),
+								LLUI::getXUIPaths());
+	// Force font reloads, which can be very slow
+	LLFontGL::loadDefaultFonts();
+}
+
+void LLViewerWindow::requestResolutionUpdate()
+{
+	mResDirty = true;
+}
+
+void LLViewerWindow::checkSettings()
+{
+	if (mStatesDirty)
+	{
+		gGL.refreshState();
+		LLViewerShaderMgr::instance()->setShaders();
+		mStatesDirty = false;
+	}
+	
+	// We want to update the resolution AFTER the states getting refreshed not before.
+	if (mResDirty)
+	{
+		reshape(getWindowWidthRaw(), getWindowHeightRaw());
+		mResDirty = false;
+	}	
+}
+
+void LLViewerWindow::restartDisplay(BOOL show_progress_bar)
+{
+	llinfos << "Restaring GL" << llendl;
+	stopGL();
+	if (show_progress_bar)
+	{
+		restoreGL(LLTrans::getString("ProgressChangingResolution"));
+	}
+	else
+	{
+		restoreGL();
+	}
+}
+
+BOOL LLViewerWindow::changeDisplaySettings(LLCoordScreen size, BOOL disable_vsync, BOOL show_progress_bar)
+{
+	//BOOL was_maximized = gSavedSettings.getBOOL("WindowMaximized");
+
+	//gResizeScreenTexture = TRUE;
+
+
+	//U32 fsaa = gSavedSettings.getU32("RenderFSAASamples");
+	//U32 old_fsaa = mWindow->getFSAASamples();
+
+	// if not maximized, use the request size
+	if (!mWindow->getMaximized())
+	{
+		mWindow->setSize(size);
+	}
+
+	//if (fsaa == old_fsaa)
+	{
+		return TRUE;
+	}
+
+/*
+
+	// Close floaters that don't handle settings change
+	LLFloaterReg::hideInstance("snapshot");
+	
+	BOOL result_first_try = FALSE;
+	BOOL result_second_try = FALSE;
+
+	LLFocusableElement* keyboard_focus = gFocusMgr.getKeyboardFocus();
+	send_agent_pause();
+	llinfos << "Stopping GL during changeDisplaySettings" << llendl;
+	stopGL();
+	mIgnoreActivate = TRUE;
+	LLCoordScreen old_size;
+	LLCoordScreen old_pos;
+	mWindow->getSize(&old_size);
+
+	//mWindow->setFSAASamples(fsaa);
+
+	result_first_try = mWindow->switchContext(false, size, disable_vsync);
+	if (!result_first_try)
+	{
+		// try to switch back
+		//mWindow->setFSAASamples(old_fsaa);
+		result_second_try = mWindow->switchContext(false, old_size, disable_vsync);
+
+		if (!result_second_try)
+		{
+			// we are stuck...try once again with a minimal resolution?
+			send_agent_resume();
+			mIgnoreActivate = FALSE;
+			return FALSE;
+		}
+	}
+	send_agent_resume();
+
+	llinfos << "Restoring GL during resolution change" << llendl;
+	if (show_progress_bar)
+	{
+		restoreGL(LLTrans::getString("ProgressChangingResolution"));
+	}
+	else
+	{
+		restoreGL();
+	}
+
+	if (!result_first_try)
+	{
+		LLSD args;
+		args["RESX"] = llformat("%d",size.mX);
+		args["RESY"] = llformat("%d",size.mY);
+		LLNotificationsUtil::add("ResolutionSwitchFail", args);
+		size = old_size; // for reshape below
+	}
+
+	BOOL success = result_first_try || result_second_try;
+
+	if (success)
+	{
+		// maximize window if was maximized, else reposition
+		if (was_maximized)
+		{
+			mWindow->maximize();
+		}
+		else
+		{
+			S32 windowX = gSavedSettings.getS32("WindowX");
+			S32 windowY = gSavedSettings.getS32("WindowY");
+
+			mWindow->setPosition(LLCoordScreen ( windowX, windowY ) );
+		}
+	}
+
+	mIgnoreActivate = FALSE;
+	gFocusMgr.setKeyboardFocus(keyboard_focus);
+	
+	return success;
+
+	*/
+}
+
+F32	LLViewerWindow::getWorldViewAspectRatio() const
+{
+	F32 world_aspect = (F32)mWorldViewRectRaw.getWidth() / (F32)mWorldViewRectRaw.getHeight();
+	return world_aspect;
+}
+
+void LLViewerWindow::calcDisplayScale()
+{
+	F32 ui_scale_factor = gSavedSettings.getF32("UIScaleFactor");
+	LLVector2 display_scale;
+	display_scale.setVec(llmax(1.f / mWindow->getPixelAspectRatio(), 1.f), llmax(mWindow->getPixelAspectRatio(), 1.f));
+	display_scale *= ui_scale_factor;
+
+	// limit minimum display scale
+	if (display_scale.mV[VX] < MIN_DISPLAY_SCALE || display_scale.mV[VY] < MIN_DISPLAY_SCALE)
+	{
+		display_scale *= MIN_DISPLAY_SCALE / llmin(display_scale.mV[VX], display_scale.mV[VY]);
+	}
+	
+	if (display_scale != mDisplayScale)
+	{
+		llinfos << "Setting display scale to " << display_scale << llendl;
+
+		mDisplayScale = display_scale;
+		// Init default fonts
+		initFonts();
+	}
+}
+
+//static
+LLRect 	LLViewerWindow::calcScaledRect(const LLRect & rect, const LLVector2& display_scale)
+{
+	LLRect res = rect;
+	res.mLeft = llround((F32)res.mLeft / display_scale.mV[VX]);
+	res.mRight = llround((F32)res.mRight / display_scale.mV[VX]);
+	res.mBottom = llround((F32)res.mBottom / display_scale.mV[VY]);
+	res.mTop = llround((F32)res.mTop / display_scale.mV[VY]);
+
+	return res;
+}
+
+S32 LLViewerWindow::getChatConsoleBottomPad()
+{
+	S32 offset = 0;
+
+	if(gToolBarView)
+		offset += gToolBarView->getChild<LLView>("bottom_toolbar_panel")->getRect().getHeight();
+
+	return offset;
+}
+
+LLRect LLViewerWindow::getChatConsoleRect()
+{
+	LLRect full_window(0, getWindowHeightScaled(), getWindowWidthScaled(), 0);
+	LLRect console_rect = full_window;
+
+	const S32 CONSOLE_PADDING_TOP = 24;
+	const S32 CONSOLE_PADDING_LEFT = 24;
+	const S32 CONSOLE_PADDING_RIGHT = 10;
+
+	console_rect.mTop    -= CONSOLE_PADDING_TOP;
+	console_rect.mBottom += getChatConsoleBottomPad();
+
+	console_rect.mLeft   += CONSOLE_PADDING_LEFT; 
+
+	static const BOOL CHAT_FULL_WIDTH = gSavedSettings.getBOOL("ChatFullWidth");
+
+	if (CHAT_FULL_WIDTH)
+	{
+		console_rect.mRight -= CONSOLE_PADDING_RIGHT;
+	}
+	else
+	{
+		// Make console rect somewhat narrow so having inventory open is
+		// less of a problem.
+		console_rect.mRight  = console_rect.mLeft + 2 * getWindowWidthScaled() / 3;
+	}
+
+	return console_rect;
+}
+//----------------------------------------------------------------------------
+
+
+//static 
+bool LLViewerWindow::onAlert(const LLSD& notify)
+{
+	LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID());
+
+	if (gHeadlessClient)
+	{
+		llinfos << "Alert: " << notification->getName() << llendl;
+	}
+
+	// If we're in mouselook, the mouse is hidden and so the user can't click 
+	// the dialog buttons.  In that case, change to First Person instead.
+	if( gAgentCamera.cameraMouselook() )
+	{
+		gAgentCamera.changeCameraToDefault();
+	}
+	return false;
+}
+
+void LLViewerWindow::setUIVisibility(bool visible)
+{
+	mUIVisible = visible;
+
+	if (!visible)
+	{
+		gAgentCamera.changeCameraToThirdPerson(FALSE);
+		gFloaterView->hideAllFloaters();
+	}
+	else
+	{
+		gFloaterView->showHiddenFloaters();
+	}
+
+	if (gToolBarView)
+	{
+		gToolBarView->setToolBarsVisible(visible);
+	}
+
+	LLNavigationBar::getInstance()->setVisible(visible ? gSavedSettings.getBOOL("ShowNavbarNavigationPanel") : FALSE);
+	LLPanelTopInfoBar::getInstance()->setVisible(visible? gSavedSettings.getBOOL("ShowMiniLocationPanel") : FALSE);
+	mRootView->getChildView("status_bar_container")->setVisible(visible);
+}
+
+bool LLViewerWindow::getUIVisibility()
+{
+	return mUIVisible;
+}
+
+////////////////////////////////////////////////////////////////////////////
+//
+// LLPickInfo
+//
+LLPickInfo::LLPickInfo()
+	: mKeyMask(MASK_NONE),
+	  mPickCallback(NULL),
+	  mPickType(PICK_INVALID),
+	  mWantSurfaceInfo(FALSE),
+	  mObjectFace(-1),
+	  mUVCoords(-1.f, -1.f),
+	  mSTCoords(-1.f, -1.f),
+	  mXYCoords(-1, -1),
+	  mIntersection(),
+	  mNormal(),
+	  mBinormal(),
+	  mHUDIcon(NULL),
+	  mPickTransparent(FALSE)
+{
+}
+
+LLPickInfo::LLPickInfo(const LLCoordGL& mouse_pos, 
+		       MASK keyboard_mask, 
+		       BOOL pick_transparent,
+		       BOOL pick_uv_coords,
+		       void (*pick_callback)(const LLPickInfo& pick_info))
+	: mMousePt(mouse_pos),
+	  mKeyMask(keyboard_mask),
+	  mPickCallback(pick_callback),
+	  mPickType(PICK_INVALID),
+	  mWantSurfaceInfo(pick_uv_coords),
+	  mObjectFace(-1),
+	  mUVCoords(-1.f, -1.f),
+	  mSTCoords(-1.f, -1.f),
+	  mXYCoords(-1, -1),
+	  mNormal(),
+	  mBinormal(),
+	  mHUDIcon(NULL),
+	  mPickTransparent(pick_transparent)
+{
+}
+
+void LLPickInfo::fetchResults()
+{
+
+	S32 face_hit = -1;
+	LLVector3 intersection, normal, binormal;
+	LLVector2 uv;
+
+	LLHUDIcon* hit_icon = gViewerWindow->cursorIntersectIcon(mMousePt.mX, mMousePt.mY, 512.f, &intersection);
+	
+	F32 icon_dist = 0.f;
+	if (hit_icon)
+	{
+		icon_dist = (LLViewerCamera::getInstance()->getOrigin()-intersection).magVec();
+	}
+	LLViewerObject* hit_object = gViewerWindow->cursorIntersect(mMousePt.mX, mMousePt.mY, 512.f,
+									NULL, -1, mPickTransparent, &face_hit,
+									&intersection, &uv, &normal, &binormal);
+	
+	mPickPt = mMousePt;
+
+	U32 te_offset = face_hit > -1 ? face_hit : 0;
+
+	//unproject relative clicked coordinate from window coordinate using GL
+	
+	LLViewerObject* objectp = hit_object;
+
+	if (hit_icon && 
+		(!objectp || 
+		icon_dist < (LLViewerCamera::getInstance()->getOrigin()-intersection).magVec()))
+	{
+		// was this name referring to a hud icon?
+		mHUDIcon = hit_icon;
+		mPickType = PICK_ICON;
+		mPosGlobal = mHUDIcon->getPositionGlobal();
+	}
+	else if (objectp)
+	{
+		if( objectp->getPCode() == LLViewerObject::LL_VO_SURFACE_PATCH )
+		{
+			// Hit land
+			mPickType = PICK_LAND;
+			mObjectID.setNull(); // land has no id
+
+			// put global position into land_pos
+			LLVector3d land_pos;
+			if (!gViewerWindow->mousePointOnLandGlobal(mPickPt.mX, mPickPt.mY, &land_pos))
+			{
+				// The selected point is beyond the draw distance or is otherwise 
+				// not selectable. Return before calling mPickCallback().
+				return;
+			}
+
+			// Fudge the land focus a little bit above ground.
+			mPosGlobal = land_pos + LLVector3d::z_axis * 0.1f;
+		}
+		else
+		{
+			if(isFlora(objectp))
+			{
+				mPickType = PICK_FLORA;
+			}
+			else
+			{
+				mPickType = PICK_OBJECT;
+			}
+			mObjectOffset = gAgentCamera.calcFocusOffset(objectp, intersection, mPickPt.mX, mPickPt.mY);
+			mObjectID = objectp->mID;
+			mObjectFace = (te_offset == NO_FACE) ? -1 : (S32)te_offset;
+
+			mPosGlobal = gAgent.getPosGlobalFromAgent(intersection);
+			
+			if (mWantSurfaceInfo)
+			{
+				getSurfaceInfo();
+			}
+		}
+	}
+	
+	if (mPickCallback)
+	{
+		mPickCallback(*this);
+	}
+}
+
+LLPointer<LLViewerObject> LLPickInfo::getObject() const
+{
+	return gObjectList.findObject( mObjectID );
+}
+
+void LLPickInfo::updateXYCoords()
+{
+	if (mObjectFace > -1)
+	{
+		const LLTextureEntry* tep = getObject()->getTE(mObjectFace);
+		LLPointer<LLViewerTexture> imagep = LLViewerTextureManager::getFetchedTexture(tep->getID());
+		if(mUVCoords.mV[VX] >= 0.f && mUVCoords.mV[VY] >= 0.f && imagep.notNull())
+		{
+			mXYCoords.mX = llround(mUVCoords.mV[VX] * (F32)imagep->getWidth());
+			mXYCoords.mY = llround((1.f - mUVCoords.mV[VY]) * (F32)imagep->getHeight());
+		}
+	}
+}
+
+void LLPickInfo::getSurfaceInfo()
+{
+	// set values to uninitialized - this is what we return if no intersection is found
+	mObjectFace   = -1;
+	mUVCoords     = LLVector2(-1, -1);
+	mSTCoords     = LLVector2(-1, -1);
+	mXYCoords	  = LLCoordScreen(-1, -1);
+	mIntersection = LLVector3(0,0,0);
+	mNormal       = LLVector3(0,0,0);
+	mBinormal     = LLVector3(0,0,0);
+	
+	LLViewerObject* objectp = getObject();
+
+	if (objectp)
+	{
+		if (gViewerWindow->cursorIntersect(llround((F32)mMousePt.mX), llround((F32)mMousePt.mY), 1024.f,
+										   objectp, -1, mPickTransparent,
+										   &mObjectFace,
+										   &mIntersection,
+										   &mSTCoords,
+										   &mNormal,
+										   &mBinormal))
+		{
+			// if we succeeded with the intersect above, compute the texture coordinates:
+
+			if (objectp->mDrawable.notNull() && mObjectFace > -1)
+			{
+				LLFace* facep = objectp->mDrawable->getFace(mObjectFace);
+
+				mUVCoords = facep->surfaceToTexture(mSTCoords, mIntersection, mNormal);
+			}
+
+			// and XY coords:
+			updateXYCoords();
+			
+		}
+	}
+}
+
+
+/* code to get UV via a special UV render - removed in lieu of raycast method
+LLVector2 LLPickInfo::pickUV()
+{
+	LLVector2 result(-1.f, -1.f);
+
+	LLViewerObject* objectp = getObject();
+	if (!objectp)
+	{
+		return result;
+	}
+
+	if (mObjectFace > -1 &&
+		objectp->mDrawable.notNull() && objectp->getPCode() == LL_PCODE_VOLUME &&
+		mObjectFace < objectp->mDrawable->getNumFaces())
+	{
+		S32 scaled_x = llround((F32)mPickPt.mX * gViewerWindow->getDisplayScale().mV[VX]);
+		S32 scaled_y = llround((F32)mPickPt.mY * gViewerWindow->getDisplayScale().mV[VY]);
+		const S32 UV_PICK_WIDTH = 5;
+		const S32 UV_PICK_HALF_WIDTH = (UV_PICK_WIDTH - 1) / 2;
+		U8 uv_pick_buffer[UV_PICK_WIDTH * UV_PICK_WIDTH * 4];
+		LLFace* facep = objectp->mDrawable->getFace(mObjectFace);
+		if (facep)
+		{
+			LLGLState scissor_state(GL_SCISSOR_TEST);
+			scissor_state.enable();
+			LLViewerCamera::getInstance()->setPerspective(FOR_SELECTION, scaled_x - UV_PICK_HALF_WIDTH, scaled_y - UV_PICK_HALF_WIDTH, UV_PICK_WIDTH, UV_PICK_WIDTH, FALSE);
+			//glViewport(scaled_x - UV_PICK_HALF_WIDTH, scaled_y - UV_PICK_HALF_WIDTH, UV_PICK_WIDTH, UV_PICK_WIDTH);
+			glScissor(scaled_x - UV_PICK_HALF_WIDTH, scaled_y - UV_PICK_HALF_WIDTH, UV_PICK_WIDTH, UV_PICK_WIDTH);
+
+			glClear(GL_DEPTH_BUFFER_BIT);
+
+			facep->renderSelectedUV();
+
+			glReadPixels(scaled_x - UV_PICK_HALF_WIDTH, scaled_y - UV_PICK_HALF_WIDTH, UV_PICK_WIDTH, UV_PICK_WIDTH, GL_RGBA, GL_UNSIGNED_BYTE, uv_pick_buffer);
+			U8* center_pixel = &uv_pick_buffer[4 * ((UV_PICK_WIDTH * UV_PICK_HALF_WIDTH) + UV_PICK_HALF_WIDTH + 1)];
+
+			result.mV[VX] = (F32)((center_pixel[VGREEN] & 0xf) + (16.f * center_pixel[VRED])) / 4095.f;
+			result.mV[VY] = (F32)((center_pixel[VGREEN] >> 4) + (16.f * center_pixel[VBLUE])) / 4095.f;
+		}
+	}
+
+	return result;
+} */
+
+
+//static 
+bool LLPickInfo::isFlora(LLViewerObject* object)
+{
+	if (!object) return false;
+
+	LLPCode pcode = object->getPCode();
+
+	if( (LL_PCODE_LEGACY_GRASS == pcode) 
+		|| (LL_PCODE_LEGACY_TREE == pcode) 
+		|| (LL_PCODE_TREE_NEW == pcode))
+	{
+		return true;
+	}
+	return false;
+}
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index 61ec02c4e2282006a3b2c971e0c89c255b631e03..a929d7a6dd8c2406d95d71a9a6b8807ea5a0458b 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -1,9806 +1,9806 @@
-/** 
- * @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$
- */
-
-#include "llviewerprecompiledheaders.h"
-
-#include "pipeline.h"
-
-// library includes
-#include "llaudioengine.h" // For debugging.
-#include "imageids.h"
-#include "llerror.h"
-#include "llviewercontrol.h"
-#include "llfasttimer.h"
-#include "llfontgl.h"
-#include "llmemtype.h"
-#include "llnamevalue.h"
-#include "llpointer.h"
-#include "llprimitive.h"
-#include "llvolume.h"
-#include "material_codes.h"
-#include "timing.h"
-#include "v3color.h"
-#include "llui.h" 
-#include "llglheaders.h"
-#include "llrender.h"
-#include "llwindow.h"	// swapBuffers()
-
-// newview includes
-#include "llagent.h"
-#include "llagentcamera.h"
-#include "lldrawable.h"
-#include "lldrawpoolalpha.h"
-#include "lldrawpoolavatar.h"
-#include "lldrawpoolground.h"
-#include "lldrawpoolbump.h"
-#include "lldrawpooltree.h"
-#include "lldrawpoolwater.h"
-#include "llface.h"
-#include "llfeaturemanager.h"
-#include "llfloatertelehub.h"
-#include "llfloaterreg.h"
-#include "llgldbg.h"
-#include "llhudmanager.h"
-#include "llhudnametag.h"
-#include "llhudtext.h"
-#include "lllightconstants.h"
-#include "llmeshrepository.h"
-#include "llresmgr.h"
-#include "llselectmgr.h"
-#include "llsky.h"
-#include "lltracker.h"
-#include "lltool.h"
-#include "lltoolmgr.h"
-#include "llviewercamera.h"
-#include "llviewermediafocus.h"
-#include "llviewertexturelist.h"
-#include "llviewerobject.h"
-#include "llviewerobjectlist.h"
-#include "llviewerparcelmgr.h"
-#include "llviewerregion.h" // for audio debugging.
-#include "llviewerwindow.h" // For getSpinAxis
-#include "llvoavatarself.h"
-#include "llvoground.h"
-#include "llvosky.h"
-#include "llvotree.h"
-#include "llvovolume.h"
-#include "llvosurfacepatch.h"
-#include "llvowater.h"
-#include "llvotree.h"
-#include "llvopartgroup.h"
-#include "llworld.h"
-#include "llcubemap.h"
-#include "llviewershadermgr.h"
-#include "llviewerstats.h"
-#include "llviewerjoystick.h"
-#include "llviewerdisplay.h"
-#include "llwlparammanager.h"
-#include "llwaterparammanager.h"
-#include "llspatialpartition.h"
-#include "llmutelist.h"
-#include "lltoolpie.h"
-#include "llcurl.h"
-#include "llnotifications.h"
-#include "llphysicsextensions.h"
-
-#ifdef _DEBUG
-// Debug indices is disabled for now for debug performance - djs 4/24/02
-//#define DEBUG_INDICES
-#else
-//#define DEBUG_INDICES
-#endif
-
-//cached settings
-BOOL LLPipeline::RenderAvatarVP;
-BOOL LLPipeline::VertexShaderEnable;
-BOOL LLPipeline::WindLightUseAtmosShaders;
-BOOL LLPipeline::RenderDeferred;
-F32 LLPipeline::RenderDeferredSunWash;
-U32 LLPipeline::RenderFSAASamples;
-U32 LLPipeline::RenderResolutionDivisor;
-BOOL LLPipeline::RenderUIBuffer;
-S32 LLPipeline::RenderShadowDetail;
-BOOL LLPipeline::RenderDeferredSSAO;
-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;
-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;
-
-const F32 BACKLIGHT_DAY_MAGNITUDE_AVATAR = 0.2f;
-const F32 BACKLIGHT_NIGHT_MAGNITUDE_AVATAR = 0.1f;
-const F32 BACKLIGHT_DAY_MAGNITUDE_OBJECT = 0.1f;
-const F32 BACKLIGHT_NIGHT_MAGNITUDE_OBJECT = 0.08f;
-const S32 MAX_OFFSCREEN_GEOMETRY_CHANGES_PER_FRAME = 10;
-const U32 REFLECTION_MAP_RES = 128;
-const U32 DEFERRED_VB_MASK = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_TEXCOORD1;
-// Max number of occluders to search for. JC
-const S32 MAX_OCCLUDER_COUNT = 2;
-
-extern S32 gBoxFrame;
-//extern BOOL gHideSelectedObjects;
-extern BOOL gDisplaySwapBuffers;
-extern BOOL gDebugGL;
-
-// hack counter for rendering a fixed number of frames after toggling
-// fullscreen to work around DEV-5361
-static S32 sDelayedVBOEnable = 0;
-
-BOOL	gAvatarBacklight = FALSE;
-
-BOOL	gDebugPipeline = FALSE;
-LLPipeline gPipeline;
-const LLMatrix4* gGLLastMatrix = NULL;
-
-LLFastTimer::DeclareTimer FTM_RENDER_GEOMETRY("Geometry");
-LLFastTimer::DeclareTimer FTM_RENDER_GRASS("Grass");
-LLFastTimer::DeclareTimer FTM_RENDER_INVISIBLE("Invisible");
-LLFastTimer::DeclareTimer FTM_RENDER_OCCLUSION("Occlusion");
-LLFastTimer::DeclareTimer FTM_RENDER_SHINY("Shiny");
-LLFastTimer::DeclareTimer FTM_RENDER_SIMPLE("Simple");
-LLFastTimer::DeclareTimer FTM_RENDER_TERRAIN("Terrain");
-LLFastTimer::DeclareTimer FTM_RENDER_TREES("Trees");
-LLFastTimer::DeclareTimer FTM_RENDER_UI("UI");
-LLFastTimer::DeclareTimer FTM_RENDER_WATER("Water");
-LLFastTimer::DeclareTimer FTM_RENDER_WL_SKY("Windlight Sky");
-LLFastTimer::DeclareTimer FTM_RENDER_ALPHA("Alpha Objects");
-LLFastTimer::DeclareTimer FTM_RENDER_CHARACTERS("Avatars");
-LLFastTimer::DeclareTimer FTM_RENDER_BUMP("Bump");
-LLFastTimer::DeclareTimer FTM_RENDER_FULLBRIGHT("Fullbright");
-LLFastTimer::DeclareTimer FTM_RENDER_GLOW("Glow");
-LLFastTimer::DeclareTimer FTM_GEO_UPDATE("Geo Update");
-LLFastTimer::DeclareTimer FTM_POOLRENDER("RenderPool");
-LLFastTimer::DeclareTimer FTM_POOLS("Pools");
-LLFastTimer::DeclareTimer FTM_RENDER_BLOOM_FBO("First FBO");
-LLFastTimer::DeclareTimer FTM_STATESORT("Sort Draw State");
-LLFastTimer::DeclareTimer FTM_PIPELINE("Pipeline");
-LLFastTimer::DeclareTimer FTM_CLIENT_COPY("Client Copy");
-LLFastTimer::DeclareTimer FTM_RENDER_DEFERRED("Deferred Shading");
-
-
-static LLFastTimer::DeclareTimer FTM_STATESORT_DRAWABLE("Sort Drawables");
-static LLFastTimer::DeclareTimer FTM_STATESORT_POSTSORT("Post Sort");
-
-//----------------------------------------
-std::string gPoolNames[] = 
-{
-	// Correspond to LLDrawpool enum render type
-	"NONE",
-	"POOL_SIMPLE",
-	"POOL_GROUND",
-	"POOL_FULLBRIGHT",
-	"POOL_BUMP",
-	"POOL_TERRAIN,"	
-	"POOL_SKY",
-	"POOL_WL_SKY",
-	"POOL_TREE",
-	"POOL_GRASS",
-	"POOL_INVISIBLE",
-	"POOL_AVATAR",
-	"POOL_VOIDWATER",
-	"POOL_WATER",
-	"POOL_GLOW",
-	"POOL_ALPHA"
-};
-
-void drawBox(const LLVector3& c, const LLVector3& r);
-void drawBoxOutline(const LLVector3& pos, const LLVector3& size);
-U32 nhpo2(U32 v);
-
-glh::matrix4f glh_copy_matrix(F32* src)
-{
-	glh::matrix4f ret;
-	ret.set_value(src);
-	return ret;
-}
-
-glh::matrix4f glh_get_current_modelview()
-{
-	return glh_copy_matrix(gGLModelView);
-}
-
-glh::matrix4f glh_get_current_projection()
-{
-	return glh_copy_matrix(gGLProjection);
-}
-
-glh::matrix4f glh_get_last_modelview()
-{
-	return glh_copy_matrix(gGLLastModelView);
-}
-
-glh::matrix4f glh_get_last_projection()
-{
-	return glh_copy_matrix(gGLLastProjection);
-}
-
-void glh_copy_matrix(const glh::matrix4f& src, F32* dst)
-{
-	for (U32 i = 0; i < 16; i++)
-	{
-		dst[i] = src.m[i];
-	}
-}
-
-void glh_set_current_modelview(const glh::matrix4f& mat)
-{
-	glh_copy_matrix(mat, gGLModelView);
-}
-
-void glh_set_current_projection(glh::matrix4f& mat)
-{
-	glh_copy_matrix(mat, gGLProjection);
-}
-
-glh::matrix4f gl_ortho(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat znear, GLfloat zfar)
-{
-	glh::matrix4f ret(
-		2.f/(right-left), 0.f, 0.f, -(right+left)/(right-left),
-		0.f, 2.f/(top-bottom), 0.f, -(top+bottom)/(top-bottom),
-		0.f, 0.f, -2.f/(zfar-znear),  -(zfar+znear)/(zfar-znear),
-		0.f, 0.f, 0.f, 1.f);
-
-	return ret;
-}
-
-void display_update_camera();
-//----------------------------------------
-
-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;
-BOOL	LLPipeline::sForceOldBakedUpload = FALSE;
-S32		LLPipeline::sUseOcclusion = 0;
-BOOL	LLPipeline::sDelayVBUpdate = TRUE;
-BOOL	LLPipeline::sAutoMaskAlphaDeferred = TRUE;
-BOOL	LLPipeline::sAutoMaskAlphaNonDeferred = FALSE;
-BOOL	LLPipeline::sDisableShaders = FALSE;
-BOOL	LLPipeline::sRenderBump = TRUE;
-BOOL	LLPipeline::sBakeSunlight = FALSE;
-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::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;
-
-
-static LLCullResult* sCull = NULL;
-
-static const U32 gl_cube_face[] = 
-{
-	GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB,
-	GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB,
-	GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB,
-	GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB,
-	GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB,
-	GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB,
-};
-
-void validate_framebuffer_object();
-
-
-bool addDeferredAttachments(LLRenderTarget& target)
-{
-	return target.addColorAttachment(GL_RGBA) && //specular
-			target.addColorAttachment(GL_RGBA); //normal+z	
-}
-
-LLPipeline::LLPipeline() :
-	mBackfaceCull(FALSE),
-	mBatchCount(0),
-	mMatrixOpCount(0),
-	mTextureMatrixOps(0),
-	mMaxBatchSize(0),
-	mMinBatchSize(0),
-	mMeanBatchSize(0),
-	mTrianglesDrawn(0),
-	mNumVisibleNodes(0),
-	mVerticesRelit(0),
-	mLightingChanges(0),
-	mGeometryChanges(0),
-	mNumVisibleFaces(0),
-
-	mInitialized(FALSE),
-	mVertexShadersEnabled(FALSE),
-	mVertexShadersLoaded(0),
-	mRenderDebugFeatureMask(0),
-	mRenderDebugMask(0),
-	mOldRenderDebugMask(0),
-	mGroupQ1Locked(false),
-	mGroupQ2Locked(false),
-	mLastRebuildPool(NULL),
-	mAlphaPool(NULL),
-	mSkyPool(NULL),
-	mTerrainPool(NULL),
-	mWaterPool(NULL),
-	mGroundPool(NULL),
-	mSimplePool(NULL),
-	mFullbrightPool(NULL),
-	mInvisiblePool(NULL),
-	mGlowPool(NULL),
-	mBumpPool(NULL),
-	mWLSkyPool(NULL),
-	mLightMask(0),
-	mLightMovingMask(0),
-	mLightingDetail(0),
-	mScreenWidth(0),
-	mScreenHeight(0)
-{
-	mNoiseMap = 0;
-	mTrueNoiseMap = 0;
-	mLightFunc = 0;
-}
-
-void LLPipeline::init()
-{
-	LLMemType mt(LLMemType::MTYPE_PIPELINE_INIT);
-
-	refreshCachedSettings();
-
-	gOctreeMaxCapacity = gSavedSettings.getU32("OctreeMaxNodeCapacity");
-	sDynamicLOD = gSavedSettings.getBOOL("RenderDynamicLOD");
-	sRenderBump = gSavedSettings.getBOOL("RenderObjectBump");
-	sUseTriStrips = gSavedSettings.getBOOL("RenderUseTriStrips");
-	LLVertexBuffer::sUseStreamDraw = gSavedSettings.getBOOL("RenderUseStreamVBO");
-	LLVertexBuffer::sUseVAO = gSavedSettings.getBOOL("RenderUseVAO");
-	LLVertexBuffer::sPreferStreamDraw = gSavedSettings.getBOOL("RenderPreferStreamDraw");
-	sRenderAttachedLights = gSavedSettings.getBOOL("RenderAttachedLights");
-	sRenderAttachedParticles = gSavedSettings.getBOOL("RenderAttachedParticles");
-
-	mInitialized = TRUE;
-	
-	stop_glerror();
-
-	//create render pass pools
-	getPool(LLDrawPool::POOL_ALPHA);
-	getPool(LLDrawPool::POOL_SIMPLE);
-	getPool(LLDrawPool::POOL_GRASS);
-	getPool(LLDrawPool::POOL_FULLBRIGHT);
-	getPool(LLDrawPool::POOL_INVISIBLE);
-	getPool(LLDrawPool::POOL_BUMP);
-	getPool(LLDrawPool::POOL_GLOW);
-
-	LLViewerStats::getInstance()->mTrianglesDrawnStat.reset();
-	resetFrameStats();
-
-	for (U32 i = 0; i < NUM_RENDER_TYPES; ++i)
-	{
-		mRenderTypeEnabled[i] = TRUE; //all rendering types start enabled
-	}
-
-	mRenderDebugFeatureMask = 0xffffffff; // All debugging features on
-	mRenderDebugMask = 0;	// All debug starts off
-
-	// Don't turn on ground when this is set
-	// Mac Books with intel 950s need this
-	if(!gSavedSettings.getBOOL("RenderGround"))
-	{
-		toggleRenderType(RENDER_TYPE_GROUND);
-	}
-
-	// 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;
-
-	stop_glerror();
-	
-	// Enable features
-		
-	LLViewerShaderMgr::instance()->setShaders();
-
-	stop_glerror();
-
-	for (U32 i = 0; i < 2; ++i)
-	{
-		mSpotLightFade[i] = 1.f;
-	}
-
-	mDeferredVB = new LLVertexBuffer(DEFERRED_VB_MASK, 0);
-	mDeferredVB->allocateBuffer(8, 0, true);
-	setLightingDetail(-1);
-	
-	//
-	// Update all settings to trigger a cached settings refresh
-	//
-
-	gSavedSettings.getControl("RenderAutoMaskAlphaDeferred")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("RenderAutoMaskAlphaNonDeferred")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("RenderUseFarClip")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("RenderAvatarMaxVisible")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("RenderDelayVBUpdate")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	
-	gSavedSettings.getControl("UseOcclusion")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	
-	gSavedSettings.getControl("VertexShaderEnable")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("RenderAvatarVP")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("WindLightUseAtmosShaders")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("RenderDeferred")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("RenderDeferredSunWash")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("RenderFSAASamples")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("RenderResolutionDivisor")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("RenderUIBuffer")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("RenderShadowDetail")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("RenderDeferredSSAO")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("RenderShadowResolutionScale")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("RenderLocalLights")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("RenderDelayCreation")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("RenderAnimateRes")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("FreezeTime")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("DebugBeaconLineWidth")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("RenderHighlightBrightness")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("RenderHighlightColor")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("RenderHighlightThickness")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("RenderSpotLightsInNondeferred")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("PreviewAmbientColor")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("PreviewDiffuse0")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("PreviewSpecular0")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("PreviewDiffuse1")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("PreviewSpecular1")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("PreviewDiffuse2")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("PreviewSpecular2")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("PreviewDirection0")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("PreviewDirection1")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("PreviewDirection2")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("RenderGlowMinLuminance")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("RenderGlowMaxExtractAlpha")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("RenderGlowWarmthAmount")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("RenderGlowLumWeights")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("RenderGlowWarmthWeights")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("RenderGlowResolutionPow")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("RenderGlowIterations")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("RenderGlowWidth")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("RenderGlowStrength")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("RenderDepthOfField")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("CameraFocusTransitionTime")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("CameraFNumber")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("CameraFocalLength")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("CameraFieldOfView")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("RenderShadowNoise")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("RenderShadowBlurSize")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("RenderSSAOScale")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("RenderSSAOMaxScale")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("RenderSSAOFactor")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("RenderSSAOEffect")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("RenderShadowOffsetError")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("RenderShadowBiasError")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("RenderShadowOffset")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("RenderShadowBias")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("RenderSpotShadowOffset")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("RenderSpotShadowBias")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("RenderEdgeDepthCutoff")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("RenderEdgeNormCutoff")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("RenderShadowGaussian")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("RenderShadowBlurDistFactor")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("RenderDeferredAtmospheric")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("RenderReflectionDetail")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("RenderHighlightFadeTime")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("RenderShadowClipPlanes")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("RenderShadowOrthoClipPlanes")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("RenderShadowNearDist")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("RenderFarClip")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("RenderShadowSplitExponent")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("RenderShadowErrorCutoff")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("RenderShadowFOVCutoff")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("CameraOffset")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("CameraMaxCoF")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-	gSavedSettings.getControl("CameraDoFResScale")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-}
-
-LLPipeline::~LLPipeline()
-{
-
-}
-
-void LLPipeline::cleanup()
-{
-	assertInitialized();
-
-	mGroupQ1.clear() ;
-	mGroupQ2.clear() ;
-
-	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
-		{
-			mPools.erase(curiter);
-			removeFromQuickLookup( poolp );
-			delete poolp;
-		}
-	}
-	
-	if (!mTerrainPools.empty())
-	{
-		llwarns << "Terrain Pools not cleaned up" << llendl;
-	}
-	if (!mTreePools.empty())
-	{
-		llwarns << "Tree Pools not cleaned up" << llendl;
-	}
-		
-	delete mAlphaPool;
-	mAlphaPool = NULL;
-	delete mSkyPool;
-	mSkyPool = NULL;
-	delete mTerrainPool;
-	mTerrainPool = NULL;
-	delete mWaterPool;
-	mWaterPool = NULL;
-	delete mGroundPool;
-	mGroundPool = NULL;
-	delete mSimplePool;
-	mSimplePool = NULL;
-	delete mFullbrightPool;
-	mFullbrightPool = NULL;
-	delete mInvisiblePool;
-	mInvisiblePool = NULL;
-	delete mGlowPool;
-	mGlowPool = NULL;
-	delete mBumpPool;
-	mBumpPool = NULL;
-	// don't delete wl sky pool it was handled above in the for loop
-	//delete mWLSkyPool;
-	mWLSkyPool = NULL;
-
-	releaseGLBuffers();
-
-	mFaceSelectImagep = NULL;
-
-	mMovedBridge.clear();
-
-	mInitialized = FALSE;
-
-	mDeferredVB = NULL;
-}
-
-//============================================================================
-
-void LLPipeline::destroyGL() 
-{
-	stop_glerror();
-	unloadShaders();
-	mHighlightFaces.clear();
-	
-	resetDrawOrders();
-
-	resetVertexBuffers();
-
-	releaseGLBuffers();
-
-	if (LLVertexBuffer::sEnableVBOs)
-	{
-		// render 30 frames after switching to work around DEV-5361
-		sDelayedVBOEnable = 30;
-		LLVertexBuffer::sEnableVBOs = FALSE;
-	}
-}
-
-static LLFastTimer::DeclareTimer FTM_RESIZE_SCREEN_TEXTURE("Resize Screen Texture");
-
-//static
-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()
-{
-	LLFastTimer ft(FTM_RESIZE_SCREEN_TEXTURE);
-	if (gPipeline.canUseVertexShaders() && assertInitialized())
-	{
-		GLuint resX = gViewerWindow->getWorldViewWidthRaw();
-		GLuint resY = gViewerWindow->getWorldViewHeightRaw();
-	
-		allocateScreenBuffer(resX,resY);
-	}
-}
-
-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_RECT_TEXTURE, FALSE);
-	}
-}
-
-void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY)
-{
-	refreshCachedSettings();
-	U32 samples = RenderFSAASamples;
-
-	//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
-
-	if (!allocateScreenBuffer(resX, resY, samples))
-	{
-		releaseScreenBuffers();
-		//reduce number of samples 
-		while (samples > 0)
-		{
-			samples /= 2;
-			if (allocateScreenBuffer(resX, resY, samples))
-			{ //success
-				return;
-			}
-			releaseScreenBuffers();
-		}
-
-		samples = 0;
-
-		//reduce resolution
-		while (resY > 0 && resX > 0)
-		{
-			resY /= 2;
-			if (allocateScreenBuffer(resX, resY, samples))
-			{
-				return;
-			}
-			releaseScreenBuffers();
-
-			resX /= 2;
-			if (allocateScreenBuffer(resX, resY, samples))
-			{
-				return;
-			}
-			releaseScreenBuffers();
-		}
-
-		llwarns << "Unable to allocate screen buffer at any resolution!" << llendl;
-	}
-}
-
-
-bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)
-{
-	refreshCachedSettings();
-
-	// remember these dimensions
-	mScreenWidth = resX;
-	mScreenHeight = resY;
-	
-	U32 res_mod = RenderResolutionDivisor;
-
-	if (res_mod > 1 && res_mod < resX && res_mod < resY)
-	{
-		resX /= res_mod;
-		resY /= res_mod;
-	}
-
-	if (RenderUIBuffer)
-	{
-		if (!mUIScreen.allocate(resX,resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE))
-		{
-			return false;
-		}
-	}	
-
-	if (LLPipeline::sRenderDeferred)
-	{
-		S32 shadow_detail = RenderShadowDetail;
-		BOOL ssao = RenderDeferredSSAO;
-		
-		//allocate deferred rendering color buffers
-		if (!mDeferredScreen.allocate(resX, resY, GL_RGBA, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false;
-		if (!mDeferredDepth.allocate(resX, resY, 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false;
-		if (!addDeferredAttachments(mDeferredScreen)) return false;
-	
-		if (!mScreen.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false;
-		if (samples > 0)
-		{
-			if (!mFXAABuffer.allocate(nhpo2(resX), nhpo2(resY), GL_RGBA, FALSE, FALSE, LLTexUnit::TT_TEXTURE, FALSE, samples)) return false;
-		}
-		else
-		{
-			mFXAABuffer.release();
-		}
-		
-		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_RECT_TEXTURE, FALSE)) return false;
-		}
-		else
-		{
-			mDeferredLight.release();
-		}
-
-		F32 scale = RenderShadowResolutionScale;
-
-		if (shadow_detail > 0)
-		{ //allocate 4 sun shadow maps
-			for (U32 i = 0; i < 4; i++)
-			{
-				if (!mShadow[i].allocate(U32(resX*scale),U32(resY*scale), 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE)) return false;
-			}
-		}
-		else
-		{
-			for (U32 i = 0; i < 4; i++)
-			{
-				mShadow[i].release();
-			}
-		}
-
-		U32 width = nhpo2(U32(resX*scale))/2;
-		U32 height = width;
-
-		if (shadow_detail > 1)
-		{ //allocate two spot shadow maps
-			for (U32 i = 4; i < 6; i++)
-			{
-				if (!mShadow[i].allocate(width, height, 0, TRUE, FALSE)) return false;
-			}
-		}
-		else
-		{
-			for (U32 i = 4; i < 6; i++)
-			{
-				mShadow[i].release();
-			}
-		}
-	}
-	else
-	{
-		mDeferredLight.release();
-				
-		for (U32 i = 0; i < 6; i++)
-		{
-			mShadow[i].release();
-		}
-		mFXAABuffer.release();
-		mScreen.release();
-		mDeferredScreen.release(); //make sure to release any render targets that share a depth buffer with mDeferredScreen first
-		mDeferredDepth.release();
-						
-		if (!mScreen.allocate(resX, resY, GL_RGBA, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE)) return false;		
-	}
-	
-	if (LLPipeline::sRenderDeferred)
-	{ //share depth buffer between deferred targets
-		mDeferredScreen.shareDepthBuffer(mScreen);
-	}
-
-	gGL.getTexUnit(0)->disable();
-
-	stop_glerror();
-
-	return true;
-}
-
-//static
-void LLPipeline::updateRenderDeferred()
-{
-	BOOL deferred = ((RenderDeferred && 
-					 LLRenderTarget::sUseFBO &&
-					 LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred") &&	 
-					 VertexShaderEnable && 
-					 RenderAvatarVP &&
-					 WindLightUseAtmosShaders) ? TRUE : FALSE) &&
-					!gUseWireframe;
-
-	sRenderDeferred = deferred;	
-	if (deferred)
-	{ //must render glow when rendering deferred since post effect pass is needed to present any lighting at all
-		sRenderGlow = TRUE;
-	}
-}
-
-//static
-void LLPipeline::refreshCachedSettings()
-{
-	LLPipeline::sAutoMaskAlphaDeferred = gSavedSettings.getBOOL("RenderAutoMaskAlphaDeferred");
-	LLPipeline::sAutoMaskAlphaNonDeferred = gSavedSettings.getBOOL("RenderAutoMaskAlphaNonDeferred");
-	LLPipeline::sUseFarClip = gSavedSettings.getBOOL("RenderUseFarClip");
-	LLVOAvatar::sMaxVisible = (U32)gSavedSettings.getS32("RenderAvatarMaxVisible");
-	LLPipeline::sDelayVBUpdate = gSavedSettings.getBOOL("RenderDelayVBUpdate");
-
-	LLPipeline::sUseOcclusion = 
-			(!gUseWireframe
-			&& LLFeatureManager::getInstance()->isFeatureAvailable("UseOcclusion") 
-			&& gSavedSettings.getBOOL("UseOcclusion") 
-			&& gGLManager.mHasOcclusionQuery) ? 2 : 0;
-	
-	VertexShaderEnable = gSavedSettings.getBOOL("VertexShaderEnable");
-	RenderAvatarVP = gSavedSettings.getBOOL("RenderAvatarVP");
-	WindLightUseAtmosShaders = gSavedSettings.getBOOL("WindLightUseAtmosShaders");
-	RenderDeferred = gSavedSettings.getBOOL("RenderDeferred");
-	RenderDeferredSunWash = gSavedSettings.getF32("RenderDeferredSunWash");
-	RenderFSAASamples = gSavedSettings.getU32("RenderFSAASamples");
-	RenderResolutionDivisor = gSavedSettings.getU32("RenderResolutionDivisor");
-	RenderUIBuffer = gSavedSettings.getBOOL("RenderUIBuffer");
-	RenderShadowDetail = gSavedSettings.getS32("RenderShadowDetail");
-	RenderDeferredSSAO = gSavedSettings.getBOOL("RenderDeferredSSAO");
-	RenderShadowResolutionScale = gSavedSettings.getF32("RenderShadowResolutionScale");
-	RenderLocalLights = gSavedSettings.getBOOL("RenderLocalLights");
-	RenderDelayCreation = gSavedSettings.getBOOL("RenderDelayCreation");
-	RenderAnimateRes = gSavedSettings.getBOOL("RenderAnimateRes");
-	FreezeTime = gSavedSettings.getBOOL("FreezeTime");
-	DebugBeaconLineWidth = gSavedSettings.getS32("DebugBeaconLineWidth");
-	RenderHighlightBrightness = gSavedSettings.getF32("RenderHighlightBrightness");
-	RenderHighlightColor = gSavedSettings.getColor4("RenderHighlightColor");
-	RenderHighlightThickness = gSavedSettings.getF32("RenderHighlightThickness");
-	RenderSpotLightsInNondeferred = gSavedSettings.getBOOL("RenderSpotLightsInNondeferred");
-	PreviewAmbientColor = gSavedSettings.getColor4("PreviewAmbientColor");
-	PreviewDiffuse0 = gSavedSettings.getColor4("PreviewDiffuse0");
-	PreviewSpecular0 = gSavedSettings.getColor4("PreviewSpecular0");
-	PreviewDiffuse1 = gSavedSettings.getColor4("PreviewDiffuse1");
-	PreviewSpecular1 = gSavedSettings.getColor4("PreviewSpecular1");
-	PreviewDiffuse2 = gSavedSettings.getColor4("PreviewDiffuse2");
-	PreviewSpecular2 = gSavedSettings.getColor4("PreviewSpecular2");
-	PreviewDirection0 = gSavedSettings.getVector3("PreviewDirection0");
-	PreviewDirection1 = gSavedSettings.getVector3("PreviewDirection1");
-	PreviewDirection2 = gSavedSettings.getVector3("PreviewDirection2");
-	RenderGlowMinLuminance = gSavedSettings.getF32("RenderGlowMinLuminance");
-	RenderGlowMaxExtractAlpha = gSavedSettings.getF32("RenderGlowMaxExtractAlpha");
-	RenderGlowWarmthAmount = gSavedSettings.getF32("RenderGlowWarmthAmount");
-	RenderGlowLumWeights = gSavedSettings.getVector3("RenderGlowLumWeights");
-	RenderGlowWarmthWeights = gSavedSettings.getVector3("RenderGlowWarmthWeights");
-	RenderGlowResolutionPow = gSavedSettings.getS32("RenderGlowResolutionPow");
-	RenderGlowIterations = gSavedSettings.getS32("RenderGlowIterations");
-	RenderGlowWidth = gSavedSettings.getF32("RenderGlowWidth");
-	RenderGlowStrength = gSavedSettings.getF32("RenderGlowStrength");
-	RenderDepthOfField = gSavedSettings.getBOOL("RenderDepthOfField");
-	CameraFocusTransitionTime = gSavedSettings.getF32("CameraFocusTransitionTime");
-	CameraFNumber = gSavedSettings.getF32("CameraFNumber");
-	CameraFocalLength = gSavedSettings.getF32("CameraFocalLength");
-	CameraFieldOfView = gSavedSettings.getF32("CameraFieldOfView");
-	RenderShadowNoise = gSavedSettings.getF32("RenderShadowNoise");
-	RenderShadowBlurSize = gSavedSettings.getF32("RenderShadowBlurSize");
-	RenderSSAOScale = gSavedSettings.getF32("RenderSSAOScale");
-	RenderSSAOMaxScale = gSavedSettings.getU32("RenderSSAOMaxScale");
-	RenderSSAOFactor = gSavedSettings.getF32("RenderSSAOFactor");
-	RenderSSAOEffect = gSavedSettings.getVector3("RenderSSAOEffect");
-	RenderShadowOffsetError = gSavedSettings.getF32("RenderShadowOffsetError");
-	RenderShadowBiasError = gSavedSettings.getF32("RenderShadowBiasError");
-	RenderShadowOffset = gSavedSettings.getF32("RenderShadowOffset");
-	RenderShadowBias = gSavedSettings.getF32("RenderShadowBias");
-	RenderSpotShadowOffset = gSavedSettings.getF32("RenderSpotShadowOffset");
-	RenderSpotShadowBias = gSavedSettings.getF32("RenderSpotShadowBias");
-	RenderEdgeDepthCutoff = gSavedSettings.getF32("RenderEdgeDepthCutoff");
-	RenderEdgeNormCutoff = gSavedSettings.getF32("RenderEdgeNormCutoff");
-	RenderShadowGaussian = gSavedSettings.getVector3("RenderShadowGaussian");
-	RenderShadowBlurDistFactor = gSavedSettings.getF32("RenderShadowBlurDistFactor");
-	RenderDeferredAtmospheric = gSavedSettings.getBOOL("RenderDeferredAtmospheric");
-	RenderReflectionDetail = gSavedSettings.getS32("RenderReflectionDetail");
-	RenderHighlightFadeTime = gSavedSettings.getF32("RenderHighlightFadeTime");
-	RenderShadowClipPlanes = gSavedSettings.getVector3("RenderShadowClipPlanes");
-	RenderShadowOrthoClipPlanes = gSavedSettings.getVector3("RenderShadowOrthoClipPlanes");
-	RenderShadowNearDist = gSavedSettings.getVector3("RenderShadowNearDist");
-	RenderFarClip = gSavedSettings.getF32("RenderFarClip");
-	RenderShadowSplitExponent = gSavedSettings.getVector3("RenderShadowSplitExponent");
-	RenderShadowErrorCutoff = gSavedSettings.getF32("RenderShadowErrorCutoff");
-	RenderShadowFOVCutoff = gSavedSettings.getF32("RenderShadowFOVCutoff");
-	CameraOffset = gSavedSettings.getBOOL("CameraOffset");
-	CameraMaxCoF = gSavedSettings.getF32("CameraMaxCoF");
-	CameraDoFResScale = gSavedSettings.getF32("CameraDoFResScale");
-	
-	updateRenderDeferred();
-}
-
-void LLPipeline::releaseGLBuffers()
-{
-	assertInitialized();
-	
-	if (mNoiseMap)
-	{
-		LLImageGL::deleteTextures(1, &mNoiseMap);
-		mNoiseMap = 0;
-	}
-
-	if (mTrueNoiseMap)
-	{
-		LLImageGL::deleteTextures(1, &mTrueNoiseMap);
-		mTrueNoiseMap = 0;
-	}
-
-	if (mLightFunc)
-	{
-		LLImageGL::deleteTextures(1, &mLightFunc);
-		mLightFunc = 0;
-	}
-
-	mWaterRef.release();
-	mWaterDis.release();
-	
-	for (U32 i = 0; i < 3; i++)
-	{
-		mGlow[i].release();
-	}
-
-	releaseScreenBuffers();
-
-	gBumpImageList.destroyGL();
-	LLVOAvatar::resetImpostors();
-}
-
-void LLPipeline::releaseScreenBuffers()
-{
-	mUIScreen.release();
-	mScreen.release();
-	mFXAABuffer.release();
-	mPhysicsDisplay.release();
-	mDeferredScreen.release();
-	mDeferredDepth.release();
-	mDeferredLight.release();
-	
-	mHighlight.release();
-		
-	for (U32 i = 0; i < 6; i++)
-	{
-		mShadow[i].release();
-	}
-}
-
-
-void LLPipeline::createGLBuffers()
-{
-	stop_glerror();
-	LLMemType mt_cb(LLMemType::MTYPE_PIPELINE_CREATE_BUFFERS);
-	assertInitialized();
-
-	updateRenderDeferred();
-
-	if (LLPipeline::sWaterReflections)
-	{ //water reflection texture
-		U32 res = (U32) gSavedSettings.getS32("RenderWaterRefResolution");
-			
-		mWaterRef.allocate(res,res,GL_RGBA,TRUE,FALSE);
-		mWaterDis.allocate(res,res,GL_RGBA,TRUE,FALSE);
-	}
-
-	mHighlight.allocate(256,256,GL_RGBA, FALSE, FALSE);
-
-	stop_glerror();
-
-	GLuint resX = gViewerWindow->getWorldViewWidthRaw();
-	GLuint resY = gViewerWindow->getWorldViewHeightRaw();
-	
-	if (LLPipeline::sRenderGlow)
-	{ //screen space glow buffers
-		const U32 glow_res = llmax(1, 
-			llmin(512, 1 << gSavedSettings.getS32("RenderGlowResolutionPow")));
-
-		for (U32 i = 0; i < 3; i++)
-		{
-			mGlow[i].allocate(512,glow_res,GL_RGBA,FALSE,FALSE);
-		}
-
-		allocateScreenBuffer(resX,resY);
-		mScreenWidth = 0;
-		mScreenHeight = 0;
-	}
-	
-	if (sRenderDeferred)
-	{
-		if (!mNoiseMap)
-		{
-			const U32 noiseRes = 128;
-			LLVector3 noise[noiseRes*noiseRes];
-
-			F32 scaler = gSavedSettings.getF32("RenderDeferredNoise")/100.f;
-			for (U32 i = 0; i < noiseRes*noiseRes; ++i)
-			{
-				noise[i] = LLVector3(ll_frand()-0.5f, ll_frand()-0.5f, 0.f);
-				noise[i].normVec();
-				noise[i].mV[2] = ll_frand()*scaler+1.f-scaler/2.f;
-			}
-
-			LLImageGL::generateTextures(1, &mNoiseMap);
-			
-			gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mNoiseMap);
-			LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGB16F_ARB, noiseRes, noiseRes, GL_RGB, GL_FLOAT, noise);
-			gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
-		}
-
-		if (!mTrueNoiseMap)
-		{
-			const U32 noiseRes = 128;
-			F32 noise[noiseRes*noiseRes*3];
-			for (U32 i = 0; i < noiseRes*noiseRes*3; i++)
-			{
-				noise[i] = ll_frand()*2.0-1.0;
-			}
-
-			LLImageGL::generateTextures(1, &mTrueNoiseMap);
-			gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mTrueNoiseMap);
-			LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGB16F_ARB, noiseRes, noiseRes, GL_RGB,GL_FLOAT, noise);
-			gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
-		}
-
-		if (!mLightFunc)
-		{
-			U32 lightResX = gSavedSettings.getU32("RenderSpecularResX");
-			U32 lightResY = gSavedSettings.getU32("RenderSpecularResY");
-			U8* lg = new U8[lightResX*lightResY];
-
-			for (U32 y = 0; y < lightResY; ++y)
-			{
-				for (U32 x = 0; x < lightResX; ++x)
-				{
-					//spec func
-					F32 sa = (F32) x/(lightResX-1);
-					F32 spec = (F32) y/(lightResY-1);
-					//lg[y*lightResX+x] = (U8) (powf(sa, 128.f*spec*spec)*255);
-
-					//F32 sp = acosf(sa)/(1.f-spec);
-
-					sa = powf(sa, gSavedSettings.getF32("RenderSpecularExponent"));
-					F32 a = acosf(sa*0.25f+0.75f);
-					F32 m = llmax(0.5f-spec*0.5f, 0.001f);
-					F32 t2 = tanf(a)/m;
-					t2 *= t2;
-
-					F32 c4a = (3.f+4.f*cosf(2.f*a)+cosf(4.f*a))/8.f;
-					F32 bd = 1.f/(4.f*m*m*c4a)*powf(F_E, -t2);
-
-					lg[y*lightResX+x] = (U8) (llclamp(bd, 0.f, 1.f)*255);
-				}
-			}
-
-			LLImageGL::generateTextures(1, &mLightFunc);
-			gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mLightFunc);
-			LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_R8, lightResX, lightResY, GL_RED, GL_UNSIGNED_BYTE, lg);
-			gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
-			gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_TRILINEAR);
-
-			delete [] lg;
-		}
-	}
-
-	gBumpImageList.restoreGL();
-}
-
-void LLPipeline::restoreGL() 
-{
-	LLMemType mt_cb(LLMemType::MTYPE_PIPELINE_RESTORE_GL);
-	assertInitialized();
-
-	if (mVertexShadersEnabled)
-	{
-		LLViewerShaderMgr::instance()->setShaders();
-	}
-
-	for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
-			iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
-	{
-		LLViewerRegion* region = *iter;
-		for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
-		{
-			LLSpatialPartition* part = region->getSpatialPartition(i);
-			if (part)
-			{
-				part->restoreGL();
-			}
-		}
-	}
-}
-
-
-BOOL LLPipeline::canUseVertexShaders()
-{
-	if (sDisableShaders ||
-		!gGLManager.mHasVertexShader ||
-		!gGLManager.mHasFragmentShader ||
-		!LLFeatureManager::getInstance()->isFeatureAvailable("VertexShaderEnable") ||
-		(assertInitialized() && mVertexShadersLoaded != 1) )
-	{
-		return FALSE;
-	}
-	else
-	{
-		return TRUE;
-	}
-}
-
-BOOL LLPipeline::canUseWindLightShaders() const
-{
-	return (!LLPipeline::sDisableShaders &&
-			gWLSkyProgram.mProgramObject != 0 &&
-			LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_WINDLIGHT) > 1);
-}
-
-BOOL LLPipeline::canUseWindLightShadersOnObjects() const
-{
-	return (canUseWindLightShaders() 
-		&& LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 0);
-}
-
-BOOL LLPipeline::canUseAntiAliasing() const
-{
-	return TRUE;
-}
-
-void LLPipeline::unloadShaders()
-{
-	LLMemType mt_us(LLMemType::MTYPE_PIPELINE_UNLOAD_SHADERS);
-	LLViewerShaderMgr::instance()->unloadShaders();
-
-	mVertexShadersLoaded = 0;
-}
-
-void LLPipeline::assertInitializedDoError()
-{
-	llerrs << "LLPipeline used when uninitialized." << llendl;
-}
-
-//============================================================================
-
-void LLPipeline::enableShadows(const BOOL enable_shadows)
-{
-	//should probably do something here to wrangle shadows....	
-}
-
-S32 LLPipeline::getMaxLightingDetail() const
-{
-	/*if (mVertexShaderLevel[SHADER_OBJECT] >= LLDrawPoolSimple::SHADER_LEVEL_LOCAL_LIGHTS)
-	{
-		return 3;
-	}
-	else*/
-	{
-		return 1;
-	}
-}
-
-S32 LLPipeline::setLightingDetail(S32 level)
-{
-	LLMemType mt_ld(LLMemType::MTYPE_PIPELINE_LIGHTING_DETAIL);
-	refreshCachedSettings();
-
-	if (level < 0)
-	{
-		if (RenderLocalLights)
-		{
-			level = 1;
-		}
-		else
-		{
-			level = 0;
-		}
-	}
-	level = llclamp(level, 0, getMaxLightingDetail());
-	mLightingDetail = level;
-	
-	return mLightingDetail;
-}
-
-class LLOctreeDirtyTexture : public LLOctreeTraveler<LLDrawable>
-{
-public:
-	const std::set<LLViewerFetchedTexture*>& mTextures;
-
-	LLOctreeDirtyTexture(const std::set<LLViewerFetchedTexture*>& textures) : mTextures(textures) { }
-
-	virtual void visit(const LLOctreeNode<LLDrawable>* node)
-	{
-		LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0);
-
-		if (!group->isState(LLSpatialGroup::GEOM_DIRTY) && !group->getData().empty())
-		{
-			for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i)
-			{
-				for (LLSpatialGroup::drawmap_elem_t::iterator j = i->second.begin(); j != i->second.end(); ++j) 
-				{
-					LLDrawInfo* params = *j;
-					LLViewerFetchedTexture* tex = LLViewerTextureManager::staticCastToFetchedTexture(params->mTexture);
-					if (tex && mTextures.find(tex) != mTextures.end())
-					{ 
-						group->setState(LLSpatialGroup::GEOM_DIRTY);
-					}
-				}
-			}
-		}
-
-		for (LLSpatialGroup::bridge_list_t::iterator i = group->mBridgeList.begin(); i != group->mBridgeList.end(); ++i)
-		{
-			LLSpatialBridge* bridge = *i;
-			traverse(bridge->mOctree);
-		}
-	}
-};
-
-// Called when a texture changes # of channels (causes faces to move to alpha pool)
-void LLPipeline::dirtyPoolObjectTextures(const std::set<LLViewerFetchedTexture*>& textures)
-{
-	assertInitialized();
-
-	// *TODO: This is inefficient and causes frame spikes; need a better way to do this
-	//        Most of the time is spent in dirty.traverse.
-
-	for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
-	{
-		LLDrawPool *poolp = *iter;
-		if (poolp->isFacePool())
-		{
-			((LLFacePool*) poolp)->dirtyTextures(textures);
-		}
-	}
-	
-	LLOctreeDirtyTexture dirty(textures);
-	for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
-			iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
-	{
-		LLViewerRegion* region = *iter;
-		for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
-		{
-			LLSpatialPartition* part = region->getSpatialPartition(i);
-			if (part)
-			{
-				dirty.traverse(part->mOctree);
-			}
-		}
-	}
-}
-
-LLDrawPool *LLPipeline::findPool(const U32 type, LLViewerTexture *tex0)
-{
-	assertInitialized();
-
-	LLDrawPool *poolp = NULL;
-	switch( type )
-	{
-	case LLDrawPool::POOL_SIMPLE:
-		poolp = mSimplePool;
-		break;
-
-	case LLDrawPool::POOL_GRASS:
-		poolp = mGrassPool;
-		break;
-
-	case LLDrawPool::POOL_FULLBRIGHT:
-		poolp = mFullbrightPool;
-		break;
-
-	case LLDrawPool::POOL_INVISIBLE:
-		poolp = mInvisiblePool;
-		break;
-
-	case LLDrawPool::POOL_GLOW:
-		poolp = mGlowPool;
-		break;
-
-	case LLDrawPool::POOL_TREE:
-		poolp = get_if_there(mTreePools, (uintptr_t)tex0, (LLDrawPool*)0 );
-		break;
-
-	case LLDrawPool::POOL_TERRAIN:
-		poolp = get_if_there(mTerrainPools, (uintptr_t)tex0, (LLDrawPool*)0 );
-		break;
-
-	case LLDrawPool::POOL_BUMP:
-		poolp = mBumpPool;
-		break;
-
-	case LLDrawPool::POOL_ALPHA:
-		poolp = mAlphaPool;
-		break;
-
-	case LLDrawPool::POOL_AVATAR:
-		break; // Do nothing
-
-	case LLDrawPool::POOL_SKY:
-		poolp = mSkyPool;
-		break;
-
-	case LLDrawPool::POOL_WATER:
-		poolp = mWaterPool;
-		break;
-
-	case LLDrawPool::POOL_GROUND:
-		poolp = mGroundPool;
-		break;
-
-	case LLDrawPool::POOL_WL_SKY:
-		poolp = mWLSkyPool;
-		break;
-
-	default:
-		llassert(0);
-		llerrs << "Invalid Pool Type in  LLPipeline::findPool() type=" << type << llendl;
-		break;
-	}
-
-	return poolp;
-}
-
-
-LLDrawPool *LLPipeline::getPool(const U32 type,	LLViewerTexture *tex0)
-{
-	LLMemType mt(LLMemType::MTYPE_PIPELINE);
-	LLDrawPool *poolp = findPool(type, tex0);
-	if (poolp)
-	{
-		return poolp;
-	}
-
-	LLDrawPool *new_poolp = LLDrawPool::createPool(type, tex0);
-	addPool( new_poolp );
-
-	return new_poolp;
-}
-
-
-// static
-LLDrawPool* LLPipeline::getPoolFromTE(const LLTextureEntry* te, LLViewerTexture* imagep)
-{
-	LLMemType mt(LLMemType::MTYPE_PIPELINE);
-	U32 type = getPoolTypeFromTE(te, imagep);
-	return gPipeline.getPool(type, imagep);
-}
-
-//static 
-U32 LLPipeline::getPoolTypeFromTE(const LLTextureEntry* te, LLViewerTexture* imagep)
-{
-	LLMemType mt_gpt(LLMemType::MTYPE_PIPELINE_GET_POOL_TYPE);
-	
-	if (!te || !imagep)
-	{
-		return 0;
-	}
-		
-	bool alpha = te->getColor().mV[3] < 0.999f;
-	if (imagep)
-	{
-		alpha = alpha || (imagep->getComponents() == 4 && imagep->getType() != LLViewerTexture::MEDIA_TEXTURE) || (imagep->getComponents() == 2);
-	}
-
-	if (alpha)
-	{
-		return LLDrawPool::POOL_ALPHA;
-	}
-	else if ((te->getBumpmap() || te->getShiny()))
-	{
-		return LLDrawPool::POOL_BUMP;
-	}
-	else
-	{
-		return LLDrawPool::POOL_SIMPLE;
-	}
-}
-
-
-void LLPipeline::addPool(LLDrawPool *new_poolp)
-{
-	LLMemType mt_a(LLMemType::MTYPE_PIPELINE_ADD_POOL);
-	assertInitialized();
-	mPools.insert(new_poolp);
-	addToQuickLookup( new_poolp );
-}
-
-void LLPipeline::allocDrawable(LLViewerObject *vobj)
-{
-	LLMemType mt_ad(LLMemType::MTYPE_PIPELINE_ALLOCATE_DRAWABLE);
-	LLDrawable *drawable = new LLDrawable();
-	vobj->mDrawable = drawable;
-	
-	drawable->mVObjp     = vobj;
-	
-	//encompass completely sheared objects by taking 
-	//the most extreme point possible (<1,1,0.5>)
-	drawable->setRadius(LLVector3(1,1,0.5f).scaleVec(vobj->getScale()).length());
-	if (vobj->isOrphaned())
-	{
-		drawable->setState(LLDrawable::FORCE_INVISIBLE);
-	}
-	drawable->updateXform(TRUE);
-}
-
-
-static LLFastTimer::DeclareTimer FTM_UNLINK("Unlink");
-static LLFastTimer::DeclareTimer FTM_REMOVE_FROM_MOVE_LIST("Movelist");
-static LLFastTimer::DeclareTimer FTM_REMOVE_FROM_SPATIAL_PARTITION("Spatial Partition");
-static LLFastTimer::DeclareTimer FTM_REMOVE_FROM_LIGHT_SET("Light Set");
-static LLFastTimer::DeclareTimer FTM_REMOVE_FROM_HIGHLIGHT_SET("Highlight Set");
-
-void LLPipeline::unlinkDrawable(LLDrawable *drawable)
-{
-	LLFastTimer t(FTM_UNLINK);
-
-	assertInitialized();
-
-	LLPointer<LLDrawable> drawablep = drawable; // make sure this doesn't get deleted before we are done
-	
-	// Based on flags, remove the drawable from the queues that it's on.
-	if (drawablep->isState(LLDrawable::ON_MOVE_LIST))
-	{
-		LLFastTimer t(FTM_REMOVE_FROM_MOVE_LIST);
-		LLDrawable::drawable_vector_t::iterator iter = std::find(mMovedList.begin(), mMovedList.end(), drawablep);
-		if (iter != mMovedList.end())
-		{
-			mMovedList.erase(iter);
-		}
-	}
-
-	if (drawablep->getSpatialGroup())
-	{
-		LLFastTimer t(FTM_REMOVE_FROM_SPATIAL_PARTITION);
-		if (!drawablep->getSpatialGroup()->mSpatialPartition->remove(drawablep, drawablep->getSpatialGroup()))
-		{
-#ifdef LL_RELEASE_FOR_DOWNLOAD
-			llwarns << "Couldn't remove object from spatial group!" << llendl;
-#else
-			llerrs << "Couldn't remove object from spatial group!" << llendl;
-#endif
-		}
-	}
-
-	{
-		LLFastTimer t(FTM_REMOVE_FROM_LIGHT_SET);
-		mLights.erase(drawablep);
-
-		for (light_set_t::iterator iter = mNearbyLights.begin();
-					iter != mNearbyLights.end(); iter++)
-		{
-			if (iter->drawable == drawablep)
-			{
-				mNearbyLights.erase(iter);
-				break;
-			}
-		}
-	}
-
-	{
-		LLFastTimer t(FTM_REMOVE_FROM_HIGHLIGHT_SET);
-		HighlightItem item(drawablep);
-		mHighlightSet.erase(item);
-
-		if (mHighlightObject == drawablep)
-		{
-			mHighlightObject = NULL;
-		}
-	}
-
-	for (U32 i = 0; i < 2; ++i)
-	{
-		if (mShadowSpotLight[i] == drawablep)
-		{
-			mShadowSpotLight[i] = NULL;
-		}
-
-		if (mTargetShadowSpotLight[i] == drawablep)
-		{
-			mTargetShadowSpotLight[i] = NULL;
-		}
-	}
-
-
-}
-
-U32 LLPipeline::addObject(LLViewerObject *vobj)
-{
-	LLMemType mt_ao(LLMemType::MTYPE_PIPELINE_ADD_OBJECT);
-
-	if (RenderDelayCreation)
-	{
-		mCreateQ.push_back(vobj);
-	}
-	else
-	{
-		createObject(vobj);
-	}
-
-	return 1;
-}
-
-void LLPipeline::createObjects(F32 max_dtime)
-{
-	LLFastTimer ftm(FTM_GEO_UPDATE);
-	LLMemType mt(LLMemType::MTYPE_PIPELINE_CREATE_OBJECTS);
-
-	LLTimer update_timer;
-
-	while (!mCreateQ.empty() && update_timer.getElapsedTimeF32() < max_dtime)
-	{
-		LLViewerObject* vobj = mCreateQ.front();
-		if (!vobj->isDead())
-		{
-			createObject(vobj);
-		}
-		mCreateQ.pop_front();
-	}
-	
-	//for (LLViewerObject::vobj_list_t::iterator iter = mCreateQ.begin(); iter != mCreateQ.end(); ++iter)
-	//{
-	//	createObject(*iter);
-	//}
-
-	//mCreateQ.clear();
-}
-
-void LLPipeline::createObject(LLViewerObject* vobj)
-{
-	LLDrawable* drawablep = vobj->mDrawable;
-
-	if (!drawablep)
-	{
-		drawablep = vobj->createDrawable(this);
-	}
-	else
-	{
-		llerrs << "Redundant drawable creation!" << llendl;
-	}
-		
-	llassert(drawablep);
-
-	if (vobj->getParent())
-	{
-		vobj->setDrawableParent(((LLViewerObject*)vobj->getParent())->mDrawable); // LLPipeline::addObject 1
-	}
-	else
-	{
-		vobj->setDrawableParent(NULL); // LLPipeline::addObject 2
-	}
-
-	markRebuild(drawablep, LLDrawable::REBUILD_ALL, TRUE);
-
-	if (drawablep->getVOVolume() && RenderAnimateRes)
-	{
-		// fun animated res
-		drawablep->updateXform(TRUE);
-		drawablep->clearState(LLDrawable::MOVE_UNDAMPED);
-		drawablep->setScale(LLVector3(0,0,0));
-		drawablep->makeActive();
-	}
-}
-
-
-void LLPipeline::resetFrameStats()
-{
-	assertInitialized();
-
-	LLViewerStats::getInstance()->mTrianglesDrawnStat.addValue(mTrianglesDrawn/1000.f);
-
-	if (mBatchCount > 0)
-	{
-		mMeanBatchSize = gPipeline.mTrianglesDrawn/gPipeline.mBatchCount;
-	}
-	mTrianglesDrawn = 0;
-	sCompiles        = 0;
-	mVerticesRelit   = 0;
-	mLightingChanges = 0;
-	mGeometryChanges = 0;
-	mNumVisibleFaces = 0;
-
-	if (mOldRenderDebugMask != mRenderDebugMask)
-	{
-		gObjectList.clearDebugText();
-		mOldRenderDebugMask = mRenderDebugMask;
-	}
-		
-}
-
-//external functions for asynchronous updating
-void LLPipeline::updateMoveDampedAsync(LLDrawable* drawablep)
-{
-	if (FreezeTime)
-	{
-		return;
-	}
-	if (!drawablep)
-	{
-		llerrs << "updateMove called with NULL drawablep" << llendl;
-		return;
-	}
-	if (drawablep->isState(LLDrawable::EARLY_MOVE))
-	{
-		return;
-	}
-
-	assertInitialized();
-
-	// update drawable now
-	drawablep->clearState(LLDrawable::MOVE_UNDAMPED); // force to DAMPED
-	drawablep->updateMove(); // returns done
-	drawablep->setState(LLDrawable::EARLY_MOVE); // flag says we already did an undamped move this frame
-	// Put on move list so that EARLY_MOVE gets cleared
-	if (!drawablep->isState(LLDrawable::ON_MOVE_LIST))
-	{
-		mMovedList.push_back(drawablep);
-		drawablep->setState(LLDrawable::ON_MOVE_LIST);
-	}
-}
-
-void LLPipeline::updateMoveNormalAsync(LLDrawable* drawablep)
-{
-	if (FreezeTime)
-	{
-		return;
-	}
-	if (!drawablep)
-	{
-		llerrs << "updateMove called with NULL drawablep" << llendl;
-		return;
-	}
-	if (drawablep->isState(LLDrawable::EARLY_MOVE))
-	{
-		return;
-	}
-
-	assertInitialized();
-
-	// update drawable now
-	drawablep->setState(LLDrawable::MOVE_UNDAMPED); // force to UNDAMPED
-	drawablep->updateMove();
-	drawablep->setState(LLDrawable::EARLY_MOVE); // flag says we already did an undamped move this frame
-	// Put on move list so that EARLY_MOVE gets cleared
-	if (!drawablep->isState(LLDrawable::ON_MOVE_LIST))
-	{
-		mMovedList.push_back(drawablep);
-		drawablep->setState(LLDrawable::ON_MOVE_LIST);
-	}
-}
-
-void LLPipeline::updateMovedList(LLDrawable::drawable_vector_t& moved_list)
-{
-	for (LLDrawable::drawable_vector_t::iterator iter = moved_list.begin();
-		 iter != moved_list.end(); )
-	{
-		LLDrawable::drawable_vector_t::iterator curiter = iter++;
-		LLDrawable *drawablep = *curiter;
-		BOOL done = TRUE;
-		if (!drawablep->isDead() && (!drawablep->isState(LLDrawable::EARLY_MOVE)))
-		{
-			done = drawablep->updateMove();
-		}
-		drawablep->clearState(LLDrawable::EARLY_MOVE | LLDrawable::MOVE_UNDAMPED);
-		if (done)
-		{
-			drawablep->clearState(LLDrawable::ON_MOVE_LIST);
-			iter = moved_list.erase(curiter);
-		}
-	}
-}
-
-static LLFastTimer::DeclareTimer FTM_OCTREE_BALANCE("Balance Octree");
-static LLFastTimer::DeclareTimer FTM_UPDATE_MOVE("Update Move");
-
-void LLPipeline::updateMove()
-{
-	LLFastTimer t(FTM_UPDATE_MOVE);
-	LLMemType mt_um(LLMemType::MTYPE_PIPELINE_UPDATE_MOVE);
-
-	if (FreezeTime)
-	{
-		return;
-	}
-
-	assertInitialized();
-
-	{
-		static LLFastTimer::DeclareTimer ftm("Retexture");
-		LLFastTimer t(ftm);
-
-		for (LLDrawable::drawable_set_t::iterator iter = mRetexturedList.begin();
-			 iter != mRetexturedList.end(); ++iter)
-		{
-			LLDrawable* drawablep = *iter;
-			if (drawablep && !drawablep->isDead())
-			{
-				drawablep->updateTexture();
-			}
-		}
-		mRetexturedList.clear();
-	}
-
-	{
-		static LLFastTimer::DeclareTimer ftm("Moved List");
-		LLFastTimer t(ftm);
-		updateMovedList(mMovedList);
-	}
-
-	//balance octrees
-	{
- 		LLFastTimer ot(FTM_OCTREE_BALANCE);
-
-		for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
-			iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
-		{
-			LLViewerRegion* region = *iter;
-			for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
-			{
-				LLSpatialPartition* part = region->getSpatialPartition(i);
-				if (part)
-				{
-					part->mOctree->balance();
-				}
-			}
-		}
-	}
-}
-
-/////////////////////////////////////////////////////////////////////////////
-// Culling and occlusion testing
-/////////////////////////////////////////////////////////////////////////////
-
-//static
-F32 LLPipeline::calcPixelArea(LLVector3 center, LLVector3 size, LLCamera &camera)
-{
-	LLVector3 lookAt = center - camera.getOrigin();
-	F32 dist = lookAt.length();
-
-	//ramp down distance for nearby objects
-	//shrink dist by dist/16.
-	if (dist < 16.f)
-	{
-		dist /= 16.f;
-		dist *= dist;
-		dist *= 16.f;
-	}
-
-	//get area of circle around node
-	F32 app_angle = atanf(size.length()/dist);
-	F32 radius = app_angle*LLDrawable::sCurPixelAngle;
-	return radius*radius * F_PI;
-}
-
-//static
-F32 LLPipeline::calcPixelArea(const LLVector4a& center, const LLVector4a& size, LLCamera &camera)
-{
-	LLVector4a origin;
-	origin.load3(camera.getOrigin().mV);
-
-	LLVector4a lookAt;
-	lookAt.setSub(center, origin);
-	F32 dist = lookAt.getLength3().getF32();
-
-	//ramp down distance for nearby objects
-	//shrink dist by dist/16.
-	if (dist < 16.f)
-	{
-		dist /= 16.f;
-		dist *= dist;
-		dist *= 16.f;
-	}
-
-	//get area of circle around node
-	F32 app_angle = atanf(size.getLength3().getF32()/dist);
-	F32 radius = app_angle*LLDrawable::sCurPixelAngle;
-	return radius*radius * F_PI;
-}
-
-void LLPipeline::grabReferences(LLCullResult& result)
-{
-	sCull = &result;
-}
-
-void LLPipeline::clearReferences()
-{
-	sCull = NULL;
-}
-
-void check_references(LLSpatialGroup* group, LLDrawable* drawable)
-{
-	for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i)
-	{
-		if (drawable == *i)
-		{
-			llerrs << "LLDrawable deleted while actively reference by LLPipeline." << llendl;
-		}
-	}			
-}
-
-void check_references(LLDrawable* drawable, LLFace* face)
-{
-	for (S32 i = 0; i < drawable->getNumFaces(); ++i)
-	{
-		if (drawable->getFace(i) == face)
-		{
-			llerrs << "LLFace deleted while actively referenced by LLPipeline." << llendl;
-		}
-	}
-}
-
-void check_references(LLSpatialGroup* group, LLFace* face)
-{
-	for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i)
-	{
-		LLDrawable* drawable = *i;
-		check_references(drawable, face);
-	}			
-}
-
-void LLPipeline::checkReferences(LLFace* face)
-{
-#if 0
-	if (sCull)
-	{
-		for (LLCullResult::sg_list_t::iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter)
-		{
-			LLSpatialGroup* group = *iter;
-			check_references(group, face);
-		}
-
-		for (LLCullResult::sg_list_t::iterator iter = sCull->beginAlphaGroups(); iter != sCull->endAlphaGroups(); ++iter)
-		{
-			LLSpatialGroup* group = *iter;
-			check_references(group, face);
-		}
-
-		for (LLCullResult::sg_list_t::iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter)
-		{
-			LLSpatialGroup* group = *iter;
-			check_references(group, face);
-		}
-
-		for (LLCullResult::drawable_list_t::iterator iter = sCull->beginVisibleList(); iter != sCull->endVisibleList(); ++iter)
-		{
-			LLDrawable* drawable = *iter;
-			check_references(drawable, face);	
-		}
-	}
-#endif
-}
-
-void LLPipeline::checkReferences(LLDrawable* drawable)
-{
-#if 0
-	if (sCull)
-	{
-		for (LLCullResult::sg_list_t::iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter)
-		{
-			LLSpatialGroup* group = *iter;
-			check_references(group, drawable);
-		}
-
-		for (LLCullResult::sg_list_t::iterator iter = sCull->beginAlphaGroups(); iter != sCull->endAlphaGroups(); ++iter)
-		{
-			LLSpatialGroup* group = *iter;
-			check_references(group, drawable);
-		}
-
-		for (LLCullResult::sg_list_t::iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter)
-		{
-			LLSpatialGroup* group = *iter;
-			check_references(group, drawable);
-		}
-
-		for (LLCullResult::drawable_list_t::iterator iter = sCull->beginVisibleList(); iter != sCull->endVisibleList(); ++iter)
-		{
-			if (drawable == *iter)
-			{
-				llerrs << "LLDrawable deleted while actively referenced by LLPipeline." << llendl;
-			}
-		}
-	}
-#endif
-}
-
-void check_references(LLSpatialGroup* group, LLDrawInfo* draw_info)
-{
-	for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i)
-	{
-		LLSpatialGroup::drawmap_elem_t& draw_vec = i->second;
-		for (LLSpatialGroup::drawmap_elem_t::iterator j = draw_vec.begin(); j != draw_vec.end(); ++j)
-		{
-			LLDrawInfo* params = *j;
-			if (params == draw_info)
-			{
-				llerrs << "LLDrawInfo deleted while actively referenced by LLPipeline." << llendl;
-			}
-		}
-	}
-}
-
-
-void LLPipeline::checkReferences(LLDrawInfo* draw_info)
-{
-#if 0
-	if (sCull)
-	{
-		for (LLCullResult::sg_list_t::iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter)
-		{
-			LLSpatialGroup* group = *iter;
-			check_references(group, draw_info);
-		}
-
-		for (LLCullResult::sg_list_t::iterator iter = sCull->beginAlphaGroups(); iter != sCull->endAlphaGroups(); ++iter)
-		{
-			LLSpatialGroup* group = *iter;
-			check_references(group, draw_info);
-		}
-
-		for (LLCullResult::sg_list_t::iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter)
-		{
-			LLSpatialGroup* group = *iter;
-			check_references(group, draw_info);
-		}
-	}
-#endif
-}
-
-void LLPipeline::checkReferences(LLSpatialGroup* group)
-{
-#if 0
-	if (sCull)
-	{
-		for (LLCullResult::sg_list_t::iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter)
-		{
-			if (group == *iter)
-			{
-				llerrs << "LLSpatialGroup deleted while actively referenced by LLPipeline." << llendl;
-			}
-		}
-
-		for (LLCullResult::sg_list_t::iterator iter = sCull->beginAlphaGroups(); iter != sCull->endAlphaGroups(); ++iter)
-		{
-			if (group == *iter)
-			{
-				llerrs << "LLSpatialGroup deleted while actively referenced by LLPipeline." << llendl;
-			}
-		}
-
-		for (LLCullResult::sg_list_t::iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter)
-		{
-			if (group == *iter)
-			{
-				llerrs << "LLSpatialGroup deleted while actively referenced by LLPipeline." << llendl;
-			}
-		}
-	}
-#endif
-}
-
-
-BOOL LLPipeline::visibleObjectsInFrustum(LLCamera& camera)
-{
-	for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
-			iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
-	{
-		LLViewerRegion* region = *iter;
-
-		for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
-		{
-			LLSpatialPartition* part = region->getSpatialPartition(i);
-			if (part)
-			{
-				if (hasRenderType(part->mDrawableType))
-				{
-					if (part->visibleObjectsInFrustum(camera))
-					{
-						return TRUE;
-					}
-				}
-			}
-		}
-	}
-
-	return FALSE;
-}
-
-BOOL LLPipeline::getVisibleExtents(LLCamera& camera, LLVector3& min, LLVector3& max)
-{
-	const F32 X = 65536.f;
-
-	min = LLVector3(X,X,X);
-	max = LLVector3(-X,-X,-X);
-
-	U32 saved_camera_id = LLViewerCamera::sCurCameraID;
-	LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
-
-	BOOL res = TRUE;
-
-	for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
-			iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
-	{
-		LLViewerRegion* region = *iter;
-
-		for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
-		{
-			LLSpatialPartition* part = region->getSpatialPartition(i);
-			if (part)
-			{
-				if (hasRenderType(part->mDrawableType))
-				{
-					if (!part->getVisibleExtents(camera, min, max))
-					{
-						res = FALSE;
-					}
-				}
-			}
-		}
-	}
-
-	LLViewerCamera::sCurCameraID = saved_camera_id;
-
-	return res;
-}
-
-static LLFastTimer::DeclareTimer FTM_CULL("Object Culling");
-
-void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_clip, LLPlane* planep)
-{
-	LLFastTimer t(FTM_CULL);
-	LLMemType mt_uc(LLMemType::MTYPE_PIPELINE_UPDATE_CULL);
-
-	grabReferences(result);
-
-	sCull->clear();
-
-	BOOL to_texture =	LLPipeline::sUseOcclusion > 1 &&
-						!hasRenderType(LLPipeline::RENDER_TYPE_HUD) && 
-						LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD &&
-						gPipeline.canUseVertexShaders() &&
-						sRenderGlow;
-
-	if (to_texture)
-	{
-		mScreen.bindTarget();
-	}
-
-	if (sUseOcclusion > 1)
-	{
-		gGL.setColorMask(false, false);
-	}
-
-	gGL.matrixMode(LLRender::MM_PROJECTION);
-	gGL.pushMatrix();
-	gGL.loadMatrix(gGLLastProjection);
-	gGL.matrixMode(LLRender::MM_MODELVIEW);
-	gGL.pushMatrix();
-	gGLLastMatrix = NULL;
-	gGL.loadMatrix(gGLLastModelView);
-
-
-	LLVertexBuffer::unbind();
-	LLGLDisable blend(GL_BLEND);
-	LLGLDisable test(GL_ALPHA_TEST);
-	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-
-
-	//setup a clip plane in projection matrix for reflection renders (prevents flickering from occlusion culling)
-	LLViewerRegion* region = gAgent.getRegion();
-	LLPlane plane;
-
-	if (planep)
-	{
-		plane = *planep;
-	}
-	else 
-	{
-		if (region)
-		{
-			LLVector3 pnorm;
-			F32 height = region->getWaterHeight();
-			if (water_clip < 0)
-			{ //camera is above water, clip plane points up
-				pnorm.setVec(0,0,1);
-				plane.setVec(pnorm, -height);
-			}
-			else if (water_clip > 0)
-			{	//camera is below water, clip plane points down
-				pnorm = LLVector3(0,0,-1);
-				plane.setVec(pnorm, height);
-			}
-		}
-	}
-	
-	glh::matrix4f modelview = glh_get_last_modelview();
-	glh::matrix4f proj = glh_get_last_projection();
-	LLGLUserClipPlane clip(plane, modelview, proj, water_clip != 0 && LLPipeline::sReflectionRender);
-
-	LLGLDepthTest depth(GL_TRUE, GL_FALSE);
-
-	bool bound_shader = false;
-	if (gPipeline.canUseVertexShaders() && LLGLSLShader::sCurBoundShader == 0)
-	{ //if no shader is currently bound, use the occlusion shader instead of fixed function if we can
-		// (shadow render uses a special shader that clamps to clip planes)
-		bound_shader = true;
-		gOcclusionProgram.bind();
-	}
-	
-	for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
-			iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
-	{
-		LLViewerRegion* region = *iter;
-		if (water_clip != 0)
-		{
-			LLPlane plane(LLVector3(0,0, (F32) -water_clip), (F32) water_clip*region->getWaterHeight());
-			camera.setUserClipPlane(plane);
-		}
-		else
-		{
-			camera.disableUserClipPlane();
-		}
-
-		for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
-		{
-			LLSpatialPartition* part = region->getSpatialPartition(i);
-			if (part)
-			{
-				if (hasRenderType(part->mDrawableType))
-				{
-					part->cull(camera);
-				}
-			}
-		}
-	}
-
-	if (bound_shader)
-	{
-		gOcclusionProgram.unbind();
-	}
-
-	camera.disableUserClipPlane();
-
-	if (hasRenderType(LLPipeline::RENDER_TYPE_SKY) && 
-		gSky.mVOSkyp.notNull() && 
-		gSky.mVOSkyp->mDrawable.notNull())
-	{
-		gSky.mVOSkyp->mDrawable->setVisible(camera);
-		sCull->pushDrawable(gSky.mVOSkyp->mDrawable);
-		gSky.updateCull();
-		stop_glerror();
-	}
-
-	if (hasRenderType(LLPipeline::RENDER_TYPE_GROUND) && 
-		!gPipeline.canUseWindLightShaders() &&
-		gSky.mVOGroundp.notNull() && 
-		gSky.mVOGroundp->mDrawable.notNull() &&
-		!LLPipeline::sWaterReflections)
-	{
-		gSky.mVOGroundp->mDrawable->setVisible(camera);
-		sCull->pushDrawable(gSky.mVOGroundp->mDrawable);
-	}
-	
-	
-	gGL.matrixMode(LLRender::MM_PROJECTION);
-	gGL.popMatrix();
-	gGL.matrixMode(LLRender::MM_MODELVIEW);
-	gGL.popMatrix();
-
-	if (sUseOcclusion > 1)
-	{
-		gGL.setColorMask(true, false);
-	}
-
-	if (to_texture)
-	{
-		mScreen.flush();
-	}
-}
-
-void LLPipeline::markNotCulled(LLSpatialGroup* group, LLCamera& camera)
-{
-	if (group->getData().empty())
-	{ 
-		return;
-	}
-	
-	group->setVisible();
-
-	if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD)
-	{
-		group->updateDistance(camera);
-	}
-	
-	const F32 MINIMUM_PIXEL_AREA = 16.f;
-
-	if (group->mPixelArea < MINIMUM_PIXEL_AREA)
-	{
-		return;
-	}
-
-	if (sMinRenderSize > 0.f && 
-			llmax(llmax(group->mBounds[1][0], group->mBounds[1][1]), group->mBounds[1][2]) < sMinRenderSize)
-	{
-		return;
-	}
-
-	assertInitialized();
-	
-	if (!group->mSpatialPartition->mRenderByGroup)
-	{ //render by drawable
-		sCull->pushDrawableGroup(group);
-	}
-	else
-	{   //render by group
-		sCull->pushVisibleGroup(group);
-	}
-
-	mNumVisibleNodes++;
-}
-
-void LLPipeline::markOccluder(LLSpatialGroup* group)
-{
-	if (sUseOcclusion > 1 && group && !group->isOcclusionState(LLSpatialGroup::ACTIVE_OCCLUSION))
-	{
-		LLSpatialGroup* parent = group->getParent();
-
-		if (!parent || !parent->isOcclusionState(LLSpatialGroup::OCCLUDED))
-		{ //only mark top most occluders as active occlusion
-			sCull->pushOcclusionGroup(group);
-			group->setOcclusionState(LLSpatialGroup::ACTIVE_OCCLUSION);
-				
-			if (parent && 
-				!parent->isOcclusionState(LLSpatialGroup::ACTIVE_OCCLUSION) &&
-				parent->getElementCount() == 0 &&
-				parent->needsUpdate())
-			{
-				sCull->pushOcclusionGroup(group);
-				parent->setOcclusionState(LLSpatialGroup::ACTIVE_OCCLUSION);
-			}
-		}
-	}
-}
-
-void LLPipeline::doOcclusion(LLCamera& camera)
-{
-	if (LLPipeline::sUseOcclusion > 1 && sCull->hasOcclusionGroups())
-	{
-		LLVertexBuffer::unbind();
-
-		if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCCLUSION))
-		{
-			gGL.setColorMask(true, false, false, false);
-		}
-		else
-		{
-			gGL.setColorMask(false, false);
-		}
-		LLGLDisable blend(GL_BLEND);
-		LLGLDisable test(GL_ALPHA_TEST);
-		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-		LLGLDepthTest depth(GL_TRUE, GL_FALSE);
-
-		LLGLDisable cull(GL_CULL_FACE);
-
-		
-		bool bind_shader = LLGLSLShader::sNoFixedFunction && LLGLSLShader::sCurBoundShader == 0;
-		if (bind_shader)
-		{
-			if (LLPipeline::sShadowRender)
-			{
-				gDeferredShadowProgram.bind();
-			}
-			else
-			{
-				gOcclusionProgram.bind();
-			}
-		}
-
-		for (LLCullResult::sg_list_t::iterator iter = sCull->beginOcclusionGroups(); iter != sCull->endOcclusionGroups(); ++iter)
-		{
-			LLSpatialGroup* group = *iter;
-			group->doOcclusion(&camera);
-			group->clearOcclusionState(LLSpatialGroup::ACTIVE_OCCLUSION);
-		}
-	
-		if (bind_shader)
-		{
-			if (LLPipeline::sShadowRender)
-			{
-				gDeferredShadowProgram.unbind();
-			}
-			else
-			{
-				gOcclusionProgram.unbind();
-			}
-		}
-
-		gGL.setColorMask(true, false);
-	}
-}
-	
-BOOL LLPipeline::updateDrawableGeom(LLDrawable* drawablep, BOOL priority)
-{
-	BOOL update_complete = drawablep->updateGeometry(priority);
-	if (update_complete && assertInitialized())
-	{
-		drawablep->setState(LLDrawable::BUILT);
-		mGeometryChanges++;
-	}
-	return update_complete;
-}
-
-void LLPipeline::updateGL()
-{
-	while (!LLGLUpdate::sGLQ.empty())
-	{
-		LLGLUpdate* glu = LLGLUpdate::sGLQ.front();
-		glu->updateGL();
-		glu->mInQ = FALSE;
-		LLGLUpdate::sGLQ.pop_front();
-	}
-}
-
-void LLPipeline::rebuildPriorityGroups()
-{
-	LLTimer update_timer;
-	LLMemType mt(LLMemType::MTYPE_PIPELINE);
-	
-	assertInitialized();
-
-	gMeshRepo.notifyLoadedMeshes();
-
-	mGroupQ1Locked = true;
-	// Iterate through all drawables on the priority build queue,
-	for (LLSpatialGroup::sg_vector_t::iterator iter = mGroupQ1.begin();
-		 iter != mGroupQ1.end(); ++iter)
-	{
-		LLSpatialGroup* group = *iter;
-		group->rebuildGeom();
-		group->clearState(LLSpatialGroup::IN_BUILD_Q1);
-	}
-
-	mGroupQ1.clear();
-	mGroupQ1Locked = false;
-
-}
-		
-void LLPipeline::rebuildGroups()
-{
-	if (mGroupQ2.empty())
-	{
-		return;
-	}
-
-	mGroupQ2Locked = true;
-	// Iterate through some drawables on the non-priority build queue
-	S32 size = (S32) mGroupQ2.size();
-	S32 min_count = llclamp((S32) ((F32) (size * size)/4096*0.25f), 1, size);
-			
-	S32 count = 0;
-	
-	std::sort(mGroupQ2.begin(), mGroupQ2.end(), LLSpatialGroup::CompareUpdateUrgency());
-
-	LLSpatialGroup::sg_vector_t::iterator iter;
-	LLSpatialGroup::sg_vector_t::iterator last_iter = mGroupQ2.begin();
-
-	for (iter = mGroupQ2.begin();
-		 iter != mGroupQ2.end() && count <= min_count; ++iter)
-	{
-		LLSpatialGroup* group = *iter;
-		last_iter = iter;
-
-		if (!group->isDead())
-		{
-			group->rebuildGeom();
-			
-			if (group->mSpatialPartition->mRenderByGroup)
-			{
-				count++;
-			}
-		}
-
-		group->clearState(LLSpatialGroup::IN_BUILD_Q2);
-	}	
-
-	mGroupQ2.erase(mGroupQ2.begin(), ++last_iter);
-
-	mGroupQ2Locked = false;
-
-	updateMovedList(mMovedBridge);
-}
-
-void LLPipeline::updateGeom(F32 max_dtime)
-{
-	LLTimer update_timer;
-	LLMemType mt(LLMemType::MTYPE_PIPELINE_UPDATE_GEOM);
-	LLPointer<LLDrawable> drawablep;
-
-	LLFastTimer t(FTM_GEO_UPDATE);
-
-	assertInitialized();
-
-	if (sDelayedVBOEnable > 0)
-	{
-		if (--sDelayedVBOEnable <= 0)
-		{
-			resetVertexBuffers();
-			LLVertexBuffer::sEnableVBOs = TRUE;
-		}
-	}
-
-	// notify various object types to reset internal cost metrics, etc.
-	// for now, only LLVOVolume does this to throttle LOD changes
-	LLVOVolume::preUpdateGeom();
-
-	// Iterate through all drawables on the priority build queue,
-	for (LLDrawable::drawable_list_t::iterator iter = mBuildQ1.begin();
-		 iter != mBuildQ1.end();)
-	{
-		LLDrawable::drawable_list_t::iterator curiter = iter++;
-		LLDrawable* drawablep = *curiter;
-		if (drawablep && !drawablep->isDead())
-		{
-			if (drawablep->isState(LLDrawable::IN_REBUILD_Q2))
-			{
-				drawablep->clearState(LLDrawable::IN_REBUILD_Q2);
-				LLDrawable::drawable_list_t::iterator find = std::find(mBuildQ2.begin(), mBuildQ2.end(), drawablep);
-				if (find != mBuildQ2.end())
-				{
-					mBuildQ2.erase(find);
-				}
-			}
-
-			if (updateDrawableGeom(drawablep, TRUE))
-			{
-				drawablep->clearState(LLDrawable::IN_REBUILD_Q1);
-				mBuildQ1.erase(curiter);
-			}
-		}
-		else
-		{
-			mBuildQ1.erase(curiter);
-		}
-	}
-		
-	// Iterate through some drawables on the non-priority build queue
-	S32 min_count = 16;
-	S32 size = (S32) mBuildQ2.size();
-	if (size > 1024)
-	{
-		min_count = llclamp((S32) (size * (F32) size/4096), 16, size);
-	}
-		
-	S32 count = 0;
-	
-	max_dtime = llmax(update_timer.getElapsedTimeF32()+0.001f, max_dtime);
-	LLSpatialGroup* last_group = NULL;
-	LLSpatialBridge* last_bridge = NULL;
-
-	for (LLDrawable::drawable_list_t::iterator iter = mBuildQ2.begin();
-		 iter != mBuildQ2.end(); )
-	{
-		LLDrawable::drawable_list_t::iterator curiter = iter++;
-		LLDrawable* drawablep = *curiter;
-
-		LLSpatialBridge* bridge = drawablep->isRoot() ? drawablep->getSpatialBridge() :
-									drawablep->getParent()->getSpatialBridge();
-
-		if (drawablep->getSpatialGroup() != last_group && 
-			(!last_bridge || bridge != last_bridge) &&
-			(update_timer.getElapsedTimeF32() >= max_dtime) && count > min_count)
-		{
-			break;
-		}
-
-		//make sure updates don't stop in the middle of a spatial group
-		//to avoid thrashing (objects are enqueued by group)
-		last_group = drawablep->getSpatialGroup();
-		last_bridge = bridge;
-
-		BOOL update_complete = TRUE;
-		if (!drawablep->isDead())
-		{
-			update_complete = updateDrawableGeom(drawablep, FALSE);
-			count++;
-		}
-		if (update_complete)
-		{
-			drawablep->clearState(LLDrawable::IN_REBUILD_Q2);
-			mBuildQ2.erase(curiter);
-		}
-	}	
-
-	updateMovedList(mMovedBridge);
-}
-
-void LLPipeline::markVisible(LLDrawable *drawablep, LLCamera& camera)
-{
-	LLMemType mt(LLMemType::MTYPE_PIPELINE_MARK_VISIBLE);
-
-	if(drawablep && !drawablep->isDead())
-	{
-		if (drawablep->isSpatialBridge())
-		{
-			const LLDrawable* root = ((LLSpatialBridge*) drawablep)->mDrawable;
-			llassert(root); // trying to catch a bad assumption
-			if (root && //  // this test may not be needed, see above
-					root->getVObj()->isAttachment())
-			{
-				LLDrawable* rootparent = root->getParent();
-				if (rootparent) // this IS sometimes NULL
-				{
-					LLViewerObject *vobj = rootparent->getVObj();
-					llassert(vobj); // trying to catch a bad assumption
-					if (vobj) // this test may not be needed, see above
-					{
-						const LLVOAvatar* av = vobj->asAvatar();
-						if (av && av->isImpostor())
-						{
-							return;
-						}
-					}
-				}
-			}
-			sCull->pushBridge((LLSpatialBridge*) drawablep);
-		}
-		else
-		{
-			sCull->pushDrawable(drawablep);
-		}
-
-		drawablep->setVisible(camera);
-	}
-}
-
-void LLPipeline::markMoved(LLDrawable *drawablep, BOOL damped_motion)
-{
-	LLMemType mt_mm(LLMemType::MTYPE_PIPELINE_MARK_MOVED);
-
-	if (!drawablep)
-	{
-		//llerrs << "Sending null drawable to moved list!" << llendl;
-		return;
-	}
-	
-	if (drawablep->isDead())
-	{
-		llwarns << "Marking NULL or dead drawable moved!" << llendl;
-		return;
-	}
-	
-	if (drawablep->getParent()) 
-	{
-		//ensure that parent drawables are moved first
-		markMoved(drawablep->getParent(), damped_motion);
-	}
-
-	assertInitialized();
-
-	if (!drawablep->isState(LLDrawable::ON_MOVE_LIST))
-	{
-		if (drawablep->isSpatialBridge())
-		{
-			mMovedBridge.push_back(drawablep);
-		}
-		else
-		{
-			mMovedList.push_back(drawablep);
-		}
-		drawablep->setState(LLDrawable::ON_MOVE_LIST);
-	}
-	if (damped_motion == FALSE)
-	{
-		drawablep->setState(LLDrawable::MOVE_UNDAMPED); // UNDAMPED trumps DAMPED
-	}
-	else if (drawablep->isState(LLDrawable::MOVE_UNDAMPED))
-	{
-		drawablep->clearState(LLDrawable::MOVE_UNDAMPED);
-	}
-}
-
-void LLPipeline::markShift(LLDrawable *drawablep)
-{
-	LLMemType mt(LLMemType::MTYPE_PIPELINE_MARK_SHIFT);
-
-	if (!drawablep || drawablep->isDead())
-	{
-		return;
-	}
-
-	assertInitialized();
-
-	if (!drawablep->isState(LLDrawable::ON_SHIFT_LIST))
-	{
-		drawablep->getVObj()->setChanged(LLXform::SHIFTED | LLXform::SILHOUETTE);
-		if (drawablep->getParent()) 
-		{
-			markShift(drawablep->getParent());
-		}
-		mShiftList.push_back(drawablep);
-		drawablep->setState(LLDrawable::ON_SHIFT_LIST);
-	}
-}
-
-void LLPipeline::shiftObjects(const LLVector3 &offset)
-{
-	LLMemType mt(LLMemType::MTYPE_PIPELINE_SHIFT_OBJECTS);
-
-	assertInitialized();
-
-	glClear(GL_DEPTH_BUFFER_BIT);
-	gDepthDirty = TRUE;
-		
-	LLVector4a offseta;
-	offseta.load3(offset.mV);
-
-	for (LLDrawable::drawable_vector_t::iterator iter = mShiftList.begin();
-		 iter != mShiftList.end(); iter++)
-	{
-		LLDrawable *drawablep = *iter;
-		if (drawablep->isDead())
-		{
-			continue;
-		}	
-		drawablep->shiftPos(offseta);	
-		drawablep->clearState(LLDrawable::ON_SHIFT_LIST);
-	}
-	mShiftList.resize(0);
-
-	for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
-			iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
-	{
-		LLViewerRegion* region = *iter;
-		for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
-		{
-			LLSpatialPartition* part = region->getSpatialPartition(i);
-			if (part)
-			{
-				part->shift(offseta);
-			}
-		}
-	}
-
-	LLHUDText::shiftAll(offset);
-	LLHUDNameTag::shiftAll(offset);
-	display_update_camera();
-}
-
-void LLPipeline::markTextured(LLDrawable *drawablep)
-{
-	LLMemType mt(LLMemType::MTYPE_PIPELINE_MARK_TEXTURED);
-
-	if (drawablep && !drawablep->isDead() && assertInitialized())
-	{
-		mRetexturedList.insert(drawablep);
-	}
-}
-
-void LLPipeline::markGLRebuild(LLGLUpdate* glu)
-{
-	if (glu && !glu->mInQ)
-	{
-		LLGLUpdate::sGLQ.push_back(glu);
-		glu->mInQ = TRUE;
-	}
-}
-
-void LLPipeline::markPartitionMove(LLDrawable* drawable)
-{
-	if (!drawable->isState(LLDrawable::PARTITION_MOVE) && 
-		!drawable->getPositionGroup().equals3(LLVector4a::getZero()))
-	{
-		drawable->setState(LLDrawable::PARTITION_MOVE);
-		mPartitionQ.push_back(drawable);
-	}
-}
-
-void LLPipeline::processPartitionQ()
-{
-	for (LLDrawable::drawable_list_t::iterator iter = mPartitionQ.begin(); iter != mPartitionQ.end(); ++iter)
-	{
-		LLDrawable* drawable = *iter;
-		if (!drawable->isDead())
-		{
-			drawable->updateBinRadius();
-			drawable->movePartition();
-		}
-		drawable->clearState(LLDrawable::PARTITION_MOVE);
-	}
-
-	mPartitionQ.clear();
-}
-
-void LLPipeline::markRebuild(LLSpatialGroup* group, BOOL priority)
-{
-	LLMemType mt(LLMemType::MTYPE_PIPELINE);
-	
-	if (group && !group->isDead() && group->mSpatialPartition)
-	{
-		if (group->mSpatialPartition->mPartitionType == LLViewerRegion::PARTITION_HUD)
-		{
-			priority = TRUE;
-		}
-
-		if (priority)
-		{
-			if (!group->isState(LLSpatialGroup::IN_BUILD_Q1))
-			{
-				llassert_always(!mGroupQ1Locked);
-
-				mGroupQ1.push_back(group);
-				group->setState(LLSpatialGroup::IN_BUILD_Q1);
-
-				if (group->isState(LLSpatialGroup::IN_BUILD_Q2))
-				{
-					LLSpatialGroup::sg_vector_t::iterator iter = std::find(mGroupQ2.begin(), mGroupQ2.end(), group);
-					if (iter != mGroupQ2.end())
-					{
-						mGroupQ2.erase(iter);
-					}
-					group->clearState(LLSpatialGroup::IN_BUILD_Q2);
-				}
-			}
-		}
-		else if (!group->isState(LLSpatialGroup::IN_BUILD_Q2 | LLSpatialGroup::IN_BUILD_Q1))
-		{
-			llassert_always(!mGroupQ2Locked);
-			mGroupQ2.push_back(group);
-			group->setState(LLSpatialGroup::IN_BUILD_Q2);
-
-		}
-	}
-}
-
-void LLPipeline::markRebuild(LLDrawable *drawablep, LLDrawable::EDrawableFlags flag, BOOL priority)
-{
-	LLMemType mt(LLMemType::MTYPE_PIPELINE_MARK_REBUILD);
-
-	if (drawablep && !drawablep->isDead() && assertInitialized())
-	{
-		if (!drawablep->isState(LLDrawable::BUILT))
-		{
-			priority = TRUE;
-		}
-		if (priority)
-		{
-			if (!drawablep->isState(LLDrawable::IN_REBUILD_Q1))
-			{
-				mBuildQ1.push_back(drawablep);
-				drawablep->setState(LLDrawable::IN_REBUILD_Q1); // mark drawable as being in priority queue
-			}
-		}
-		else if (!drawablep->isState(LLDrawable::IN_REBUILD_Q2))
-		{
-			mBuildQ2.push_back(drawablep);
-			drawablep->setState(LLDrawable::IN_REBUILD_Q2); // need flag here because it is just a list
-		}
-		if (flag & (LLDrawable::REBUILD_VOLUME | LLDrawable::REBUILD_POSITION))
-		{
-			drawablep->getVObj()->setChanged(LLXform::SILHOUETTE);
-		}
-		drawablep->setState(flag);
-	}
-}
-
-static LLFastTimer::DeclareTimer FTM_RESET_DRAWORDER("Reset Draw Order");
-
-void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result)
-{
-	if (hasAnyRenderType(LLPipeline::RENDER_TYPE_AVATAR,
-					  LLPipeline::RENDER_TYPE_GROUND,
-					  LLPipeline::RENDER_TYPE_TERRAIN,
-					  LLPipeline::RENDER_TYPE_TREE,
-					  LLPipeline::RENDER_TYPE_SKY,
-					  LLPipeline::RENDER_TYPE_VOIDWATER,
-					  LLPipeline::RENDER_TYPE_WATER,
-					  LLPipeline::END_RENDER_TYPES))
-	{
-		//clear faces from face pools
-		LLFastTimer t(FTM_RESET_DRAWORDER);
-		gPipeline.resetDrawOrders();
-	}
-
-	LLFastTimer ftm(FTM_STATESORT);
-	LLMemType mt(LLMemType::MTYPE_PIPELINE_STATE_SORT);
-
-	//LLVertexBuffer::unbind();
-
-	grabReferences(result);
-	for (LLCullResult::sg_list_t::iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter)
-	{
-		LLSpatialGroup* group = *iter;
-		group->checkOcclusion();
-		if (sUseOcclusion > 1 && group->isOcclusionState(LLSpatialGroup::OCCLUDED))
-		{
-			markOccluder(group);
-		}
-		else
-		{
-			group->setVisible();
-			for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i)
-			{
-				markVisible(*i, camera);
-			}
-
-			if (!sDelayVBUpdate)
-			{ //rebuild mesh as soon as we know it's visible
-				group->rebuildMesh();
-			}
-		}
-	}
-
-	if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD)
-	{
-		LLSpatialGroup* last_group = NULL;
-		for (LLCullResult::bridge_list_t::iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i)
-		{
-			LLCullResult::bridge_list_t::iterator cur_iter = i;
-			LLSpatialBridge* bridge = *cur_iter;
-			LLSpatialGroup* group = bridge->getSpatialGroup();
-
-			if (last_group == NULL)
-			{
-				last_group = group;
-			}
-
-			if (!bridge->isDead() && group && !group->isOcclusionState(LLSpatialGroup::OCCLUDED))
-			{
-				stateSort(bridge, camera);
-			}
-
-			if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD &&
-				last_group != group && last_group->changeLOD())
-			{
-				last_group->mLastUpdateDistance = last_group->mDistance;
-			}
-
-			last_group = group;
-		}
-
-		if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD &&
-			last_group && last_group->changeLOD())
-		{
-			last_group->mLastUpdateDistance = last_group->mDistance;
-		}
-	}
-
-	for (LLCullResult::sg_list_t::iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter)
-	{
-		LLSpatialGroup* group = *iter;
-		group->checkOcclusion();
-		if (sUseOcclusion > 1 && group->isOcclusionState(LLSpatialGroup::OCCLUDED))
-		{
-			markOccluder(group);
-		}
-		else
-		{
-			group->setVisible();
-			stateSort(group, camera);
-
-			if (!sDelayVBUpdate)
-			{ //rebuild mesh as soon as we know it's visible
-				group->rebuildMesh();
-			}
-		}
-	}
-	
-	{
-		LLFastTimer ftm(FTM_STATESORT_DRAWABLE);
-		for (LLCullResult::drawable_list_t::iterator iter = sCull->beginVisibleList();
-			 iter != sCull->endVisibleList(); ++iter)
-		{
-			LLDrawable *drawablep = *iter;
-			if (!drawablep->isDead())
-			{
-				stateSort(drawablep, camera);
-			}
-		}
-	}
-		
-	postSort(camera);	
-}
-
-void LLPipeline::stateSort(LLSpatialGroup* group, LLCamera& camera)
-{
-	LLMemType mt(LLMemType::MTYPE_PIPELINE_STATE_SORT);
-	if (group->changeLOD())
-	{
-		for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i)
-		{
-			LLDrawable* drawablep = *i;
-			stateSort(drawablep, camera);
-		}
-
-		if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD)
-		{ //avoid redundant stateSort calls
-			group->mLastUpdateDistance = group->mDistance;
-		}
-	}
-
-}
-
-void LLPipeline::stateSort(LLSpatialBridge* bridge, LLCamera& camera)
-{
-	LLMemType mt(LLMemType::MTYPE_PIPELINE_STATE_SORT);
-	if (bridge->getSpatialGroup()->changeLOD())
-	{
-		bool force_update = false;
-		bridge->updateDistance(camera, force_update);
-	}
-}
-
-void LLPipeline::stateSort(LLDrawable* drawablep, LLCamera& camera)
-{
-	LLMemType mt(LLMemType::MTYPE_PIPELINE_STATE_SORT);
-		
-	if (!drawablep
-		|| drawablep->isDead() 
-		|| !hasRenderType(drawablep->getRenderType()))
-	{
-		return;
-	}
-	
-	if (LLSelectMgr::getInstance()->mHideSelectedObjects)
-	{
-		if (drawablep->getVObj().notNull() &&
-			drawablep->getVObj()->isSelected())
-		{
-			return;
-		}
-	}
-
-	if (drawablep->isAvatar())
-	{ //don't draw avatars beyond render distance or if we don't have a spatial group.
-		if ((drawablep->getSpatialGroup() == NULL) || 
-			(drawablep->getSpatialGroup()->mDistance > LLVOAvatar::sRenderDistance))
-		{
-			return;
-		}
-
-		LLVOAvatar* avatarp = (LLVOAvatar*) drawablep->getVObj().get();
-		if (!avatarp->isVisible())
-		{
-			return;
-		}
-	}
-
-	assertInitialized();
-
-	if (hasRenderType(drawablep->mRenderType))
-	{
-		if (!drawablep->isState(LLDrawable::INVISIBLE|LLDrawable::FORCE_INVISIBLE))
-		{
-			drawablep->setVisible(camera, NULL, FALSE);
-		}
-		else if (drawablep->isState(LLDrawable::CLEAR_INVISIBLE))
-		{
-			// clear invisible flag here to avoid single frame glitch
-			drawablep->clearState(LLDrawable::FORCE_INVISIBLE|LLDrawable::CLEAR_INVISIBLE);
-		}
-	}
-
-	if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD)
-	{
-		//if (drawablep->isVisible()) isVisible() check here is redundant, if it wasn't visible, it wouldn't be here
-		{
-			if (!drawablep->isActive())
-			{
-				bool force_update = false;
-				drawablep->updateDistance(camera, force_update);
-			}
-			else if (drawablep->isAvatar())
-			{
-				bool force_update = false;
-				drawablep->updateDistance(camera, force_update); // calls vobj->updateLOD() which calls LLVOAvatar::updateVisibility()
-			}
-		}
-	}
-
-	if (!drawablep->getVOVolume())
-	{
-		for (LLDrawable::face_list_t::iterator iter = drawablep->mFaces.begin();
-				iter != drawablep->mFaces.end(); iter++)
-		{
-			LLFace* facep = *iter;
-
-			if (facep->hasGeometry())
-			{
-				if (facep->getPool())
-				{
-					facep->getPool()->enqueue(facep);
-				}
-				else
-				{
-					break;
-				}
-			}
-		}
-	}
-	
-
-	mNumVisibleFaces += drawablep->getNumFaces();
-}
-
-
-void forAllDrawables(LLCullResult::sg_list_t::iterator begin, 
-					 LLCullResult::sg_list_t::iterator end,
-					 void (*func)(LLDrawable*))
-{
-	for (LLCullResult::sg_list_t::iterator i = begin; i != end; ++i)
-	{
-		for (LLSpatialGroup::element_iter j = (*i)->getData().begin(); j != (*i)->getData().end(); ++j)
-		{
-			func(*j);	
-		}
-	}
-}
-
-void LLPipeline::forAllVisibleDrawables(void (*func)(LLDrawable*))
-{
-	forAllDrawables(sCull->beginDrawableGroups(), sCull->endDrawableGroups(), func);
-	forAllDrawables(sCull->beginVisibleGroups(), sCull->endVisibleGroups(), func);
-}
-
-//function for creating scripted beacons
-void renderScriptedBeacons(LLDrawable* drawablep)
-{
-	LLViewerObject *vobj = drawablep->getVObj();
-	if (vobj 
-		&& !vobj->isAvatar() 
-		&& !vobj->getParent()
-		&& vobj->flagScripted())
-	{
-		if (gPipeline.sRenderBeacons)
-		{
-			gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", LLColor4(1.f, 0.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), LLPipeline::DebugBeaconLineWidth);
-		}
-
-		if (gPipeline.sRenderHighlight)
-		{
-			S32 face_id;
-			S32 count = drawablep->getNumFaces();
-			for (face_id = 0; face_id < count; face_id++)
-			{
-				gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) );
-			}
-		}
-	}
-}
-
-void renderScriptedTouchBeacons(LLDrawable* drawablep)
-{
-	LLViewerObject *vobj = drawablep->getVObj();
-	if (vobj 
-		&& !vobj->isAvatar() 
-		&& !vobj->getParent()
-		&& vobj->flagScripted()
-		&& vobj->flagHandleTouch())
-	{
-		if (gPipeline.sRenderBeacons)
-		{
-			gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", LLColor4(1.f, 0.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), LLPipeline::DebugBeaconLineWidth);
-		}
-
-		if (gPipeline.sRenderHighlight)
-		{
-			S32 face_id;
-			S32 count = drawablep->getNumFaces();
-			for (face_id = 0; face_id < count; face_id++)
-			{
-				gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) );
-			}
-		}
-	}
-}
-
-void renderPhysicalBeacons(LLDrawable* drawablep)
-{
-	LLViewerObject *vobj = drawablep->getVObj();
-	if (vobj 
-		&& !vobj->isAvatar() 
-		//&& !vobj->getParent()
-		&& vobj->usePhysics())
-	{
-		if (gPipeline.sRenderBeacons)
-		{
-			gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", LLColor4(0.f, 1.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), LLPipeline::DebugBeaconLineWidth);
-		}
-
-		if (gPipeline.sRenderHighlight)
-		{
-			S32 face_id;
-			S32 count = drawablep->getNumFaces();
-			for (face_id = 0; face_id < count; face_id++)
-			{
-				gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) );
-			}
-		}
-	}
-}
-
-void renderMOAPBeacons(LLDrawable* drawablep)
-{
-	LLViewerObject *vobj = drawablep->getVObj();
-
-	if(!vobj || vobj->isAvatar())
-		return;
-
-	BOOL beacon=FALSE;
-	U8 tecount=vobj->getNumTEs();
-	for(int x=0;x<tecount;x++)
-	{
-		if(vobj->getTE(x)->hasMedia())
-		{
-			beacon=TRUE;
-			break;
-		}
-	}
-	if(beacon==TRUE)
-	{
-		if (gPipeline.sRenderBeacons)
-		{
-			gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", LLColor4(1.f, 1.f, 1.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), LLPipeline::DebugBeaconLineWidth);
-		}
-
-		if (gPipeline.sRenderHighlight)
-		{
-			S32 face_id;
-			S32 count = drawablep->getNumFaces();
-			for (face_id = 0; face_id < count; face_id++)
-			{
-				gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) );
-			}
-		}
-	}
-}
-
-void renderParticleBeacons(LLDrawable* drawablep)
-{
-	// Look for attachments, objects, etc.
-	LLViewerObject *vobj = drawablep->getVObj();
-	if (vobj 
-		&& vobj->isParticleSource())
-	{
-		if (gPipeline.sRenderBeacons)
-		{
-			LLColor4 light_blue(0.5f, 0.5f, 1.f, 0.5f);
-			gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", light_blue, LLColor4(1.f, 1.f, 1.f, 0.5f), LLPipeline::DebugBeaconLineWidth);
-		}
-
-		if (gPipeline.sRenderHighlight)
-		{
-			S32 face_id;
-			S32 count = drawablep->getNumFaces();
-			for (face_id = 0; face_id < count; face_id++)
-			{
-				gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) );
-			}
-		}
-	}
-}
-
-void renderSoundHighlights(LLDrawable* drawablep)
-{
-	// Look for attachments, objects, etc.
-	LLViewerObject *vobj = drawablep->getVObj();
-	if (vobj && vobj->isAudioSource())
-	{
-		if (gPipeline.sRenderHighlight)
-		{
-			S32 face_id;
-			S32 count = drawablep->getNumFaces();
-			for (face_id = 0; face_id < count; face_id++)
-			{
-				gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) );
-			}
-		}
-	}
-}
-
-void LLPipeline::postSort(LLCamera& camera)
-{
-	LLMemType mt(LLMemType::MTYPE_PIPELINE_POST_SORT);
-	LLFastTimer ftm(FTM_STATESORT_POSTSORT);
-
-	assertInitialized();
-
-	llpushcallstacks ;
-	//rebuild drawable geometry
-	for (LLCullResult::sg_list_t::iterator i = sCull->beginDrawableGroups(); i != sCull->endDrawableGroups(); ++i)
-	{
-		LLSpatialGroup* group = *i;
-		if (!sUseOcclusion || 
-			!group->isOcclusionState(LLSpatialGroup::OCCLUDED))
-		{
-			group->rebuildGeom();
-		}
-	}
-	llpushcallstacks ;
-	//rebuild groups
-	sCull->assertDrawMapsEmpty();
-
-	rebuildPriorityGroups();
-	llpushcallstacks ;
-
-	const S32 bin_count = 1024*8;
-		
-	static LLCullResult::drawinfo_list_t alpha_bins[bin_count];
-	static U32 bin_size[bin_count];
-
-	//clear one bin per frame to avoid memory bloat
-	static S32 clear_idx = 0;
-	clear_idx = (1+clear_idx)%bin_count;
-	alpha_bins[clear_idx].clear();
-
-	for (U32 j = 0; j < bin_count; j++)
-	{
-		bin_size[j] = 0;
-	}
-
-	//build render map
-	for (LLCullResult::sg_list_t::iterator i = sCull->beginVisibleGroups(); i != sCull->endVisibleGroups(); ++i)
-	{
-		LLSpatialGroup* group = *i;
-		if (sUseOcclusion && 
-			group->isOcclusionState(LLSpatialGroup::OCCLUDED))
-		{
-			continue;
-		}
-
-		if (group->isState(LLSpatialGroup::NEW_DRAWINFO) && group->isState(LLSpatialGroup::GEOM_DIRTY))
-		{ //no way this group is going to be drawable without a rebuild
-			group->rebuildGeom();
-		}
-
-		for (LLSpatialGroup::draw_map_t::iterator j = group->mDrawMap.begin(); j != group->mDrawMap.end(); ++j)
-		{
-			LLSpatialGroup::drawmap_elem_t& src_vec = j->second;	
-			if (!hasRenderType(j->first))
-			{
-				continue;
-			}
-			
-			for (LLSpatialGroup::drawmap_elem_t::iterator k = src_vec.begin(); k != src_vec.end(); ++k)
-			{
-				if (sMinRenderSize > 0.f)
-				{
-					LLVector4a bounds;
-					bounds.setSub((*k)->mExtents[1],(*k)->mExtents[0]);
-
-					if (llmax(llmax(bounds[0], bounds[1]), bounds[2]) > sMinRenderSize)
-					{
-						sCull->pushDrawInfo(j->first, *k);
-					}
-				}
-				else
-				{
-					sCull->pushDrawInfo(j->first, *k);
-				}
-			}
-		}
-
-		if (hasRenderType(LLPipeline::RENDER_TYPE_PASS_ALPHA))
-		{
-			LLSpatialGroup::draw_map_t::iterator alpha = group->mDrawMap.find(LLRenderPass::PASS_ALPHA);
-			
-			if (alpha != group->mDrawMap.end())
-			{ //store alpha groups for sorting
-				LLSpatialBridge* bridge = group->mSpatialPartition->asBridge();
-				if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD)
-				{
-					if (bridge)
-					{
-						LLCamera trans_camera = bridge->transformCamera(camera);
-						group->updateDistance(trans_camera);
-					}
-					else
-					{
-						group->updateDistance(camera);
-					}
-				}
-							
-				if (hasRenderType(LLDrawPool::POOL_ALPHA))
-				{
-					sCull->pushAlphaGroup(group);
-				}
-			}
-		}
-	}
-		
-	if (!sShadowRender)
-	{
-		std::sort(sCull->beginAlphaGroups(), sCull->endAlphaGroups(), LLSpatialGroup::CompareDepthGreater());
-	}
-	llpushcallstacks ;
-	// only render if the flag is set. The flag is only set if we are in edit mode or the toggle is set in the menus
-	if (LLFloaterReg::instanceVisible("beacons") && !sShadowRender)
-	{
-		if (sRenderScriptedTouchBeacons)
-		{
-			// Only show the beacon on the root object.
-			forAllVisibleDrawables(renderScriptedTouchBeacons);
-		}
-		else
-		if (sRenderScriptedBeacons)
-		{
-			// Only show the beacon on the root object.
-			forAllVisibleDrawables(renderScriptedBeacons);
-		}
-
-		if (sRenderPhysicalBeacons)
-		{
-			// Only show the beacon on the root object.
-			forAllVisibleDrawables(renderPhysicalBeacons);
-		}
-
-		if(sRenderMOAPBeacons)
-		{
-			forAllVisibleDrawables(renderMOAPBeacons);
-		}
-
-		if (sRenderParticleBeacons)
-		{
-			forAllVisibleDrawables(renderParticleBeacons);
-		}
-
-		// If god mode, also show audio cues
-		if (sRenderSoundBeacons && gAudiop)
-		{
-			// Walk all sound sources and render out beacons for them. Note, this isn't done in the ForAllVisibleDrawables function, because some are not visible.
-			LLAudioEngine::source_map::iterator iter;
-			for (iter = gAudiop->mAllSources.begin(); iter != gAudiop->mAllSources.end(); ++iter)
-			{
-				LLAudioSource *sourcep = iter->second;
-
-				LLVector3d pos_global = sourcep->getPositionGlobal();
-				LLVector3 pos = gAgent.getPosAgentFromGlobal(pos_global);
-				if (gPipeline.sRenderBeacons)
-				{
-					//pos += LLVector3(0.f, 0.f, 0.2f);
-					gObjectList.addDebugBeacon(pos, "", LLColor4(1.f, 1.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), DebugBeaconLineWidth);
-				}
-			}
-			// now deal with highlights for all those seeable sound sources
-			forAllVisibleDrawables(renderSoundHighlights);
-		}
-	}
-	llpushcallstacks ;
-	// If managing your telehub, draw beacons at telehub and currently selected spawnpoint.
-	if (LLFloaterTelehub::renderBeacons())
-	{
-		LLFloaterTelehub::addBeacons();
-	}
-
-	if (!sShadowRender)
-	{
-		mSelectedFaces.clear();
-		
-		// Draw face highlights for selected faces.
-		if (LLSelectMgr::getInstance()->getTEMode())
-		{
-			struct f : public LLSelectedTEFunctor
-			{
-				virtual bool apply(LLViewerObject* object, S32 te)
-				{
-					if (object->mDrawable)
-					{
-						gPipeline.mSelectedFaces.push_back(object->mDrawable->getFace(te));
-					}
-					return true;
-				}
-			} func;
-			LLSelectMgr::getInstance()->getSelection()->applyToTEs(&func);
-		}
-	}
-
-	//LLSpatialGroup::sNoDelete = FALSE;
-	llpushcallstacks ;
-}
-
-
-void render_hud_elements()
-{
-	LLMemType mt_rhe(LLMemType::MTYPE_PIPELINE_RENDER_HUD_ELS);
-	LLFastTimer t(FTM_RENDER_UI);
-	gPipeline.disableLights();		
-	
-	LLGLDisable fog(GL_FOG);
-	LLGLSUIDefault gls_ui;
-
-	LLGLEnable stencil(GL_STENCIL_TEST);
-	glStencilFunc(GL_ALWAYS, 255, 0xFFFFFFFF);
-	glStencilMask(0xFFFFFFFF);
-	glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
-	
-	gGL.color4f(1,1,1,1);
-	
-	if (LLGLSLShader::sNoFixedFunction)
-	{
-		gUIProgram.bind();
-	}
-	LLGLDepthTest depth(GL_TRUE, GL_FALSE);
-
-	if (!LLPipeline::sReflectionRender && gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
-	{
-		LLGLEnable multisample(LLPipeline::RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0);
-		gViewerWindow->renderSelections(FALSE, FALSE, FALSE); // For HUD version in render_ui_3d()
-	
-		// Draw the tracking overlays
-		LLTracker::render3D();
-		
-		// Show the property lines
-		LLWorld::getInstance()->renderPropertyLines();
-		LLViewerParcelMgr::getInstance()->render();
-		LLViewerParcelMgr::getInstance()->renderParcelCollision();
-	
-		// Render name tags.
-		LLHUDObject::renderAll();
-	}
-	else if (gForceRenderLandFence)
-	{
-		// This is only set when not rendering the UI, for parcel snapshots
-		LLViewerParcelMgr::getInstance()->render();
-	}
-	else if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD))
-	{
-		LLHUDText::renderAllHUD();
-	}
-
-	if (LLGLSLShader::sNoFixedFunction)
-	{
-		gUIProgram.unbind();
-	}
-	gGL.flush();
-}
-
-void LLPipeline::renderHighlights()
-{
-	LLMemType mt(LLMemType::MTYPE_PIPELINE_RENDER_HL);
-
-	assertInitialized();
-
-	// Draw 3D UI elements here (before we clear the Z buffer in POOL_HUD)
-	// Render highlighted faces.
-	LLGLSPipelineAlpha gls_pipeline_alpha;
-	LLColor4 color(1.f, 1.f, 1.f, 0.5f);
-	LLGLEnable color_mat(GL_COLOR_MATERIAL);
-	disableLights();
-
-	if (!hasRenderType(LLPipeline::RENDER_TYPE_HUD) && !mHighlightSet.empty())
-	{ //draw blurry highlight image over screen
-		LLGLEnable blend(GL_BLEND);
-		LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS);
-		LLGLDisable test(GL_ALPHA_TEST);
-
-		LLGLEnable stencil(GL_STENCIL_TEST);
-		gGL.flush();
-		glStencilMask(0xFFFFFFFF);
-		glClearStencil(1);
-		glClear(GL_STENCIL_BUFFER_BIT);
-
-		glStencilFunc(GL_ALWAYS, 0, 0xFFFFFFFF);
-		glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
-				
-		gGL.setColorMask(false, false);
-		for (std::set<HighlightItem>::iterator iter = mHighlightSet.begin(); iter != mHighlightSet.end(); ++iter)
-		{
-			renderHighlight(iter->mItem->getVObj(), 1.f);
-		}
-		gGL.setColorMask(true, false);
-
-		glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
-		glStencilFunc(GL_NOTEQUAL, 0, 0xFFFFFFFF);
-		
-		//gGL.setSceneBlendType(LLRender::BT_ADD_WITH_ALPHA);
-
-		gGL.pushMatrix();
-		gGL.loadIdentity();
-		gGL.matrixMode(LLRender::MM_PROJECTION);
-		gGL.pushMatrix();
-		gGL.loadIdentity();
-
-		gGL.getTexUnit(0)->bind(&mHighlight);
-
-		LLVector2 tc1;
-		LLVector2 tc2;
-
-		tc1.setVec(0,0);
-		tc2.setVec(2,2);
-
-		gGL.begin(LLRender::TRIANGLES);
-				
-		F32 scale = RenderHighlightBrightness;
-		LLColor4 color = RenderHighlightColor;
-		F32 thickness = RenderHighlightThickness;
-
-		for (S32 pass = 0; pass < 2; ++pass)
-		{
-			if (pass == 0)
-			{
-				gGL.setSceneBlendType(LLRender::BT_ADD_WITH_ALPHA);
-			}
-			else
-			{
-				gGL.setSceneBlendType(LLRender::BT_ALPHA);
-			}
-
-			for (S32 i = 0; i < 8; ++i)
-			{
-				for (S32 j = 0; j < 8; ++j)
-				{
-					LLVector2 tc(i-4+0.5f, j-4+0.5f);
-
-					F32 dist = 1.f-(tc.length()/sqrtf(32.f));
-					dist *= scale/64.f;
-
-					tc *= thickness;
-					tc.mV[0] = (tc.mV[0])/mHighlight.getWidth();
-					tc.mV[1] = (tc.mV[1])/mHighlight.getHeight();
-
-					gGL.color4f(color.mV[0],
-								color.mV[1],
-								color.mV[2],
-								color.mV[3]*dist);
-					
-					gGL.texCoord2f(tc.mV[0]+tc1.mV[0], tc.mV[1]+tc2.mV[1]);
-					gGL.vertex2f(-1,3);
-					
-					gGL.texCoord2f(tc.mV[0]+tc1.mV[0], tc.mV[1]+tc1.mV[1]);
-					gGL.vertex2f(-1,-1);
-					
-					gGL.texCoord2f(tc.mV[0]+tc2.mV[0], tc.mV[1]+tc1.mV[1]);
-					gGL.vertex2f(3,-1);
-				}
-			}
-		}
-
-		gGL.end();
-
-		gGL.popMatrix();
-		gGL.matrixMode(LLRender::MM_MODELVIEW);
-		gGL.popMatrix();
-		
-		//gGL.setSceneBlendType(LLRender::BT_ALPHA);
-	}
-
-	if ((LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0))
-	{
-		gHighlightProgram.bind();
-		gGL.diffuseColor4f(1,1,1,0.5f);
-	}
-	
-	if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED))
-	{
-		// Make sure the selection image gets downloaded and decoded
-		if (!mFaceSelectImagep)
-		{
-			mFaceSelectImagep = LLViewerTextureManager::getFetchedTexture(IMG_FACE_SELECT);
-		}
-		mFaceSelectImagep->addTextureStats((F32)MAX_IMAGE_AREA);
-
-		U32 count = mSelectedFaces.size();
-		for (U32 i = 0; i < count; i++)
-		{
-			LLFace *facep = mSelectedFaces[i];
-			if (!facep || facep->getDrawable()->isDead())
-			{
-				llerrs << "Bad face on selection" << llendl;
-				return;
-			}
-			
-			facep->renderSelected(mFaceSelectImagep, color);
-		}
-	}
-
-	if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED))
-	{
-		// Paint 'em red!
-		color.setVec(1.f, 0.f, 0.f, 0.5f);
-		
-		int count = mHighlightFaces.size();
-		for (S32 i = 0; i < count; i++)
-		{
-			LLFace* facep = mHighlightFaces[i];
-			facep->renderSelected(LLViewerTexture::sNullImagep, color);
-		}
-	}
-
-	// Contains a list of the faces of objects that are physical or
-	// have touch-handlers.
-	mHighlightFaces.clear();
-
-	if (LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0)
-	{
-		gHighlightProgram.unbind();
-	}
-}
-
-//debug use
-U32 LLPipeline::sCurRenderPoolType = 0 ;
-
-void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate)
-{
-	LLMemType mt(LLMemType::MTYPE_PIPELINE_RENDER_GEOM);
-	LLFastTimer t(FTM_RENDER_GEOMETRY);
-
-	assertInitialized();
-
-	F32 saved_modelview[16];
-	F32 saved_projection[16];
-
-	//HACK: preserve/restore matrices around HUD render
-	if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD))
-	{
-		for (U32 i = 0; i < 16; i++)
-		{
-			saved_modelview[i] = gGLModelView[i];
-			saved_projection[i] = gGLProjection[i];
-		}
-	}
-
-	///////////////////////////////////////////
-	//
-	// Sync and verify GL state
-	//
-	//
-
-	stop_glerror();
-
-	LLVertexBuffer::unbind();
-
-	// Do verification of GL state
-	LLGLState::checkStates();
-	LLGLState::checkTextureChannels();
-	LLGLState::checkClientArrays();
-	if (mRenderDebugMask & RENDER_DEBUG_VERIFY)
-	{
-		if (!verify())
-		{
-			llerrs << "Pipeline verification failed!" << llendl;
-		}
-	}
-
-	LLAppViewer::instance()->pingMainloopTimeout("Pipeline:ForceVBO");
-	
-	// Initialize lots of GL state to "safe" values
-	gGL.matrixMode(LLRender::MM_TEXTURE);
-	gGL.loadIdentity();
-	gGL.matrixMode(LLRender::MM_MODELVIEW);
-
-	LLGLSPipeline gls_pipeline;
-	LLGLEnable multisample(RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0);
-
-	LLGLState gls_color_material(GL_COLOR_MATERIAL, mLightingDetail < 2);
-				
-	// Toggle backface culling for debugging
-	LLGLEnable cull_face(mBackfaceCull ? GL_CULL_FACE : 0);
-	// Set fog
-	BOOL use_fog = hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_FOG);
-	LLGLEnable fog_enable(use_fog &&
-						  !gPipeline.canUseWindLightShadersOnObjects() ? GL_FOG : 0);
-	gSky.updateFog(camera.getFar());
-	if (!use_fog)
-	{
-		sUnderWaterRender = FALSE;
-	}
-
-	gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sDefaultImagep);
-	LLViewerFetchedTexture::sDefaultImagep->setAddressMode(LLTexUnit::TAM_WRAP);
-	
-
-	//////////////////////////////////////////////
-	//
-	// Actually render all of the geometry
-	//
-	//	
-	stop_glerror();
-	
-	LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderDrawPools");
-
-	for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
-	{
-		LLDrawPool *poolp = *iter;
-		if (hasRenderType(poolp->getType()))
-		{
-			poolp->prerender();
-		}
-	}
-
-	{
-		LLFastTimer t(FTM_POOLS);
-		
-		// HACK: don't calculate local lights if we're rendering the HUD!
-		//    Removing this check will cause bad flickering when there are 
-		//    HUD elements being rendered AND the user is in flycam mode  -nyx
-		if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD))
-		{
-			calcNearbyLights(camera);
-			setupHWLights(NULL);
-		}
-
-		BOOL occlude = sUseOcclusion > 1;
-		U32 cur_type = 0;
-
-		pool_set_t::iterator iter1 = mPools.begin();
-		while ( iter1 != mPools.end() )
-		{
-			LLDrawPool *poolp = *iter1;
-			
-			cur_type = poolp->getType();
-
-			//debug use
-			sCurRenderPoolType = cur_type ;
-
-			if (occlude && cur_type >= LLDrawPool::POOL_GRASS)
-			{
-				occlude = FALSE;
-				gGLLastMatrix = NULL;
-				gGL.loadMatrix(gGLModelView);
-				LLGLSLShader::bindNoShader();
-				doOcclusion(camera);
-			}
-
-			pool_set_t::iterator iter2 = iter1;
-			if (hasRenderType(poolp->getType()) && poolp->getNumPasses() > 0)
-			{
-				LLFastTimer t(FTM_POOLRENDER);
-
-				gGLLastMatrix = NULL;
-				gGL.loadMatrix(gGLModelView);
-			
-				for( S32 i = 0; i < poolp->getNumPasses(); i++ )
-				{
-					LLVertexBuffer::unbind();
-					poolp->beginRenderPass(i);
-					for (iter2 = iter1; iter2 != mPools.end(); iter2++)
-					{
-						LLDrawPool *p = *iter2;
-						if (p->getType() != cur_type)
-						{
-							break;
-						}
-						
-						p->render(i);
-					}
-					poolp->endRenderPass(i);
-					LLVertexBuffer::unbind();
-					if (gDebugGL)
-					{
-						std::string msg = llformat("pass %d", i);
-						LLGLState::checkStates(msg);
-						//LLGLState::checkTextureChannels(msg);
-						//LLGLState::checkClientArrays(msg);
-					}
-				}
-			}
-			else
-			{
-				// Skip all pools of this type
-				for (iter2 = iter1; iter2 != mPools.end(); iter2++)
-				{
-					LLDrawPool *p = *iter2;
-					if (p->getType() != cur_type)
-					{
-						break;
-					}
-				}
-			}
-			iter1 = iter2;
-			stop_glerror();
-		}
-		
-		LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderDrawPoolsEnd");
-
-		LLVertexBuffer::unbind();
-			
-		gGLLastMatrix = NULL;
-		gGL.loadMatrix(gGLModelView);
-
-		if (occlude)
-		{
-			occlude = FALSE;
-			gGLLastMatrix = NULL;
-			gGL.loadMatrix(gGLModelView);
-			LLGLSLShader::bindNoShader();
-			doOcclusion(camera);
-		}
-	}
-
-	LLVertexBuffer::unbind();
-	LLGLState::checkStates();
-
-	if (!LLPipeline::sImpostorRender)
-	{
-		LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderHighlights");
-
-		if (!sReflectionRender)
-		{
-			renderHighlights();
-		}
-
-		// Contains a list of the faces of objects that are physical or
-		// have touch-handlers.
-		mHighlightFaces.clear();
-
-		LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderDebug");
-	
-		renderDebug();
-
-		LLVertexBuffer::unbind();
-	
-		if (!LLPipeline::sReflectionRender && !LLPipeline::sRenderDeferred)
-		{
-			if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
-			{
-				// Render debugging beacons.
-				gObjectList.renderObjectBeacons();
-				gObjectList.resetObjectBeacons();
-			}
-			else
-			{
-				// Make sure particle effects disappear
-				LLHUDObject::renderAllForTimer();
-			}
-		}
-		else
-		{
-			// Make sure particle effects disappear
-			LLHUDObject::renderAllForTimer();
-		}
-
-		LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderGeomEnd");
-
-		//HACK: preserve/restore matrices around HUD render
-		if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD))
-		{
-			for (U32 i = 0; i < 16; i++)
-			{
-				gGLModelView[i] = saved_modelview[i];
-				gGLProjection[i] = saved_projection[i];
-			}
-		}
-	}
-
-	LLVertexBuffer::unbind();
-
-	LLGLState::checkStates();
-//	LLGLState::checkTextureChannels();
-//	LLGLState::checkClientArrays();
-}
-
-void LLPipeline::renderGeomDeferred(LLCamera& camera)
-{
-	LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderGeomDeferred");
-
-	LLMemType mt_rgd(LLMemType::MTYPE_PIPELINE_RENDER_GEOM_DEFFERRED);
-	LLFastTimer t(FTM_RENDER_GEOMETRY);
-
-	LLFastTimer t2(FTM_POOLS);
-
-	LLGLEnable cull(GL_CULL_FACE);
-
-	LLGLEnable stencil(GL_STENCIL_TEST);
-	glStencilFunc(GL_ALWAYS, 1, 0xFFFFFFFF);
-	stop_glerror();
-	glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
-	stop_glerror();
-
-	for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
-	{
-		LLDrawPool *poolp = *iter;
-		if (hasRenderType(poolp->getType()))
-		{
-			poolp->prerender();
-		}
-	}
-
-	LLGLEnable multisample(RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0);
-
-	LLVertexBuffer::unbind();
-
-	LLGLState::checkStates();
-	LLGLState::checkTextureChannels();
-	LLGLState::checkClientArrays();
-
-	U32 cur_type = 0;
-
-	gGL.setColorMask(true, true);
-	
-	pool_set_t::iterator iter1 = mPools.begin();
-
-	while ( iter1 != mPools.end() )
-	{
-		LLDrawPool *poolp = *iter1;
-		
-		cur_type = poolp->getType();
-
-		pool_set_t::iterator iter2 = iter1;
-		if (hasRenderType(poolp->getType()) && poolp->getNumDeferredPasses() > 0)
-		{
-			LLFastTimer t(FTM_POOLRENDER);
-
-			gGLLastMatrix = NULL;
-			gGL.loadMatrix(gGLModelView);
-		
-			for( S32 i = 0; i < poolp->getNumDeferredPasses(); i++ )
-			{
-				LLVertexBuffer::unbind();
-				poolp->beginDeferredPass(i);
-				for (iter2 = iter1; iter2 != mPools.end(); iter2++)
-				{
-					LLDrawPool *p = *iter2;
-					if (p->getType() != cur_type)
-					{
-						break;
-					}
-										
-					p->renderDeferred(i);
-				}
-				poolp->endDeferredPass(i);
-				LLVertexBuffer::unbind();
-
-				if (gDebugGL || gDebugPipeline)
-				{
-					LLGLState::checkStates();
-				}
-			}
-		}
-		else
-		{
-			// Skip all pools of this type
-			for (iter2 = iter1; iter2 != mPools.end(); iter2++)
-			{
-				LLDrawPool *p = *iter2;
-				if (p->getType() != cur_type)
-				{
-					break;
-				}
-			}
-		}
-		iter1 = iter2;
-		stop_glerror();
-	}
-
-	gGLLastMatrix = NULL;
-	gGL.loadMatrix(gGLModelView);
-
-	gGL.setColorMask(true, false);
-}
-
-void LLPipeline::renderGeomPostDeferred(LLCamera& camera)
-{
-	LLMemType mt_rgpd(LLMemType::MTYPE_PIPELINE_RENDER_GEOM_POST_DEF);
-	LLFastTimer t(FTM_POOLS);
-	U32 cur_type = 0;
-
-	LLGLEnable cull(GL_CULL_FACE);
-
-	LLGLEnable multisample(RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0);
-
-	calcNearbyLights(camera);
-	setupHWLights(NULL);
-
-	gGL.setColorMask(true, false);
-
-	pool_set_t::iterator iter1 = mPools.begin();
-	BOOL occlude = LLPipeline::sUseOcclusion > 1;
-
-	while ( iter1 != mPools.end() )
-	{
-		LLDrawPool *poolp = *iter1;
-		
-		cur_type = poolp->getType();
-
-		if (occlude && cur_type >= LLDrawPool::POOL_GRASS)
-		{
-			occlude = FALSE;
-			gGLLastMatrix = NULL;
-			gGL.loadMatrix(gGLModelView);
-			LLGLSLShader::bindNoShader();
-			doOcclusion(camera);
-			gGL.setColorMask(true, false);
-		}
-
-		pool_set_t::iterator iter2 = iter1;
-		if (hasRenderType(poolp->getType()) && poolp->getNumPostDeferredPasses() > 0)
-		{
-			LLFastTimer t(FTM_POOLRENDER);
-
-			gGLLastMatrix = NULL;
-			gGL.loadMatrix(gGLModelView);
-		
-			for( S32 i = 0; i < poolp->getNumPostDeferredPasses(); i++ )
-			{
-				LLVertexBuffer::unbind();
-				poolp->beginPostDeferredPass(i);
-				for (iter2 = iter1; iter2 != mPools.end(); iter2++)
-				{
-					LLDrawPool *p = *iter2;
-					if (p->getType() != cur_type)
-					{
-						break;
-					}
-										
-					p->renderPostDeferred(i);
-				}
-				poolp->endPostDeferredPass(i);
-				LLVertexBuffer::unbind();
-
-				if (gDebugGL || gDebugPipeline)
-				{
-					LLGLState::checkStates();
-				}
-			}
-		}
-		else
-		{
-			// Skip all pools of this type
-			for (iter2 = iter1; iter2 != mPools.end(); iter2++)
-			{
-				LLDrawPool *p = *iter2;
-				if (p->getType() != cur_type)
-				{
-					break;
-				}
-			}
-		}
-		iter1 = iter2;
-		stop_glerror();
-	}
-
-	gGLLastMatrix = NULL;
-	gGL.loadMatrix(gGLModelView);
-
-	if (occlude)
-	{
-		occlude = FALSE;
-		gGLLastMatrix = NULL;
-		gGL.loadMatrix(gGLModelView);
-		LLGLSLShader::bindNoShader();
-		doOcclusion(camera);
-		gGLLastMatrix = NULL;
-		gGL.loadMatrix(gGLModelView);
-	}
-}
-
-void LLPipeline::renderGeomShadow(LLCamera& camera)
-{
-	LLMemType mt_rgs(LLMemType::MTYPE_PIPELINE_RENDER_GEOM_SHADOW);
-	U32 cur_type = 0;
-	
-	LLGLEnable cull(GL_CULL_FACE);
-
-	LLVertexBuffer::unbind();
-
-	pool_set_t::iterator iter1 = mPools.begin();
-	
-	while ( iter1 != mPools.end() )
-	{
-		LLDrawPool *poolp = *iter1;
-		
-		cur_type = poolp->getType();
-
-		pool_set_t::iterator iter2 = iter1;
-		if (hasRenderType(poolp->getType()) && poolp->getNumShadowPasses() > 0)
-		{
-			poolp->prerender() ;
-
-			gGLLastMatrix = NULL;
-			gGL.loadMatrix(gGLModelView);
-		
-			for( S32 i = 0; i < poolp->getNumShadowPasses(); i++ )
-			{
-				LLVertexBuffer::unbind();
-				poolp->beginShadowPass(i);
-				for (iter2 = iter1; iter2 != mPools.end(); iter2++)
-				{
-					LLDrawPool *p = *iter2;
-					if (p->getType() != cur_type)
-					{
-						break;
-					}
-										
-					p->renderShadow(i);
-				}
-				poolp->endShadowPass(i);
-				LLVertexBuffer::unbind();
-
-				LLGLState::checkStates();
-			}
-		}
-		else
-		{
-			// Skip all pools of this type
-			for (iter2 = iter1; iter2 != mPools.end(); iter2++)
-			{
-				LLDrawPool *p = *iter2;
-				if (p->getType() != cur_type)
-				{
-					break;
-				}
-			}
-		}
-		iter1 = iter2;
-		stop_glerror();
-	}
-
-	gGLLastMatrix = NULL;
-	gGL.loadMatrix(gGLModelView);
-}
-
-
-void LLPipeline::addTrianglesDrawn(S32 index_count, U32 render_type)
-{
-	assertInitialized();
-	S32 count = 0;
-	if (render_type == LLRender::TRIANGLE_STRIP)
-	{
-		count = index_count-2;
-	}
-	else
-	{
-		count = index_count/3;
-	}
-
-	mTrianglesDrawn += count;
-	mBatchCount++;
-	mMaxBatchSize = llmax(mMaxBatchSize, count);
-	mMinBatchSize = llmin(mMinBatchSize, count);
-
-	if (LLPipeline::sRenderFrameTest)
-	{
-		gViewerWindow->getWindow()->swapBuffers();
-		ms_sleep(16);
-	}
-}
-
-void LLPipeline::renderPhysicsDisplay()
-{
-	if (!hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PHYSICS_SHAPES))
-	{
-		return;
-	}
-
-	allocatePhysicsBuffer();
-
-	gGL.flush();
-	mPhysicsDisplay.bindTarget();
-	glClearColor(0,0,0,1);
-	gGL.setColorMask(true, true);
-	mPhysicsDisplay.clear();
-	glClearColor(0,0,0,0);
-
-	gGL.setColorMask(true, false);
-
-	if (LLGLSLShader::sNoFixedFunction)
-	{
-		gDebugProgram.bind();
-	}
-
-	for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
-			iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
-	{
-		LLViewerRegion* region = *iter;
-		for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
-		{
-			LLSpatialPartition* part = region->getSpatialPartition(i);
-			if (part)
-			{
-				if (hasRenderType(part->mDrawableType))
-				{
-					part->renderPhysicsShapes();
-				}
-			}
-		}
-	}
-
-	for (LLCullResult::bridge_list_t::const_iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i)
-	{
-		LLSpatialBridge* bridge = *i;
-		if (!bridge->isDead() && hasRenderType(bridge->mDrawableType))
-		{
-			gGL.pushMatrix();
-			gGL.multMatrix((F32*)bridge->mDrawable->getRenderMatrix().mMatrix);
-			bridge->renderPhysicsShapes();
-			gGL.popMatrix();
-		}
-	}
-
-	gGL.flush();
-
-	if (LLGLSLShader::sNoFixedFunction)
-	{
-		gDebugProgram.unbind();
-	}
-
-	mPhysicsDisplay.flush();
-}
-
-
-void LLPipeline::renderDebug()
-{
-	LLMemType mt(LLMemType::MTYPE_PIPELINE);
-
-	assertInitialized();
-
-	gGL.color4f(1,1,1,1);
-
-	gGLLastMatrix = NULL;
-	gGL.loadMatrix(gGLModelView);
-	gGL.setColorMask(true, false);
-
-	bool hud_only = hasRenderType(LLPipeline::RENDER_TYPE_HUD);
-
-	
-	if (!hud_only && !mDebugBlips.empty())
-	{ //render debug blips
-		if (LLGLSLShader::sNoFixedFunction)
-		{
-			gUIProgram.bind();
-		}
-
-		gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sWhiteImagep, true);
-
-		glPointSize(8.f);
-		LLGLDepthTest depth(GL_TRUE, GL_TRUE, GL_ALWAYS);
-
-		gGL.begin(LLRender::POINTS);
-		for (std::list<DebugBlip>::iterator iter = mDebugBlips.begin(); iter != mDebugBlips.end(); )
-		{
-			DebugBlip& blip = *iter;
-
-			blip.mAge += gFrameIntervalSeconds;
-			if (blip.mAge > 2.f)
-			{
-				mDebugBlips.erase(iter++);
-			}
-			else
-			{
-				iter++;
-			}
-
-			blip.mPosition.mV[2] += gFrameIntervalSeconds*2.f;
-
-			gGL.color4fv(blip.mColor.mV);
-			gGL.vertex3fv(blip.mPosition.mV);
-		}
-		gGL.end();
-		gGL.flush();
-		glPointSize(1.f);
-	}
-
-
-	// Debug stuff.
-	for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
-			iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
-	{
-		LLViewerRegion* region = *iter;
-		for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
-		{
-			LLSpatialPartition* part = region->getSpatialPartition(i);
-			if (part)
-			{
-				if ( hud_only && (part->mDrawableType == RENDER_TYPE_HUD || part->mDrawableType == RENDER_TYPE_HUD_PARTICLES) ||
-					 !hud_only && hasRenderType(part->mDrawableType) )
-				{
-					part->renderDebug();
-				}
-			}
-		}
-	}
-
-	for (LLCullResult::bridge_list_t::const_iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i)
-	{
-		LLSpatialBridge* bridge = *i;
-		if (!bridge->isDead() && hasRenderType(bridge->mDrawableType))
-		{
-			gGL.pushMatrix();
-			gGL.multMatrix((F32*)bridge->mDrawable->getRenderMatrix().mMatrix);
-			bridge->renderDebug();
-			gGL.popMatrix();
-		}
-	}
-
-	if (LLGLSLShader::sNoFixedFunction)
-	{
-		gUIProgram.bind();
-	}
-
-	if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
-	{
-		LLVertexBuffer::unbind();
-
-		LLGLEnable blend(GL_BLEND);
-		LLGLDepthTest depth(TRUE, FALSE);
-		LLGLDisable cull(GL_CULL_FACE);
-
-		gGL.color4f(1,1,1,1);
-		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-				
-		F32 a = 0.1f;
-
-		F32 col[] =
-		{
-			1,0,0,a,
-			0,1,0,a,
-			0,0,1,a,
-			1,0,1,a,
-			
-			1,1,0,a,
-			0,1,1,a,
-			1,1,1,a,
-			1,0,1,a,
-		};
-
-		for (U32 i = 0; i < 8; i++)
-		{
-			LLVector3* frust = mShadowCamera[i].mAgentFrustum;
-
-			if (i > 3)
-			{ //render shadow frusta as volumes
-				if (mShadowFrustPoints[i-4].empty())
-			{
-					continue;
-				}
-
-				gGL.color4fv(col+(i-4)*4);	
-			
-				gGL.begin(LLRender::TRIANGLE_STRIP);
-				gGL.vertex3fv(frust[0].mV); gGL.vertex3fv(frust[4].mV);
-				gGL.vertex3fv(frust[1].mV); gGL.vertex3fv(frust[5].mV);
-				gGL.vertex3fv(frust[2].mV); gGL.vertex3fv(frust[6].mV);
-				gGL.vertex3fv(frust[3].mV); gGL.vertex3fv(frust[7].mV);
-				gGL.vertex3fv(frust[0].mV); gGL.vertex3fv(frust[4].mV);
-				gGL.end();
-				
-				
-				gGL.begin(LLRender::TRIANGLE_STRIP);
-				gGL.vertex3fv(frust[0].mV);
-				gGL.vertex3fv(frust[1].mV);
-				gGL.vertex3fv(frust[3].mV);
-				gGL.vertex3fv(frust[2].mV);
-				gGL.end();
-				
-				gGL.begin(LLRender::TRIANGLE_STRIP);
-				gGL.vertex3fv(frust[4].mV);
-				gGL.vertex3fv(frust[5].mV);
-				gGL.vertex3fv(frust[7].mV);
-				gGL.vertex3fv(frust[6].mV);
-				gGL.end();		
-			}
-
-	
-			if (i < 4)
-			{
-				
-				//if (i == 0 || !mShadowFrustPoints[i].empty())
-				{
-					//render visible point cloud
-					gGL.flush();
-					glPointSize(8.f);
-					gGL.begin(LLRender::POINTS);
-					
-					F32* c = col+i*4;
-					gGL.color3fv(c);
-
-					for (U32 j = 0; j < mShadowFrustPoints[i].size(); ++j)
-						{
-							gGL.vertex3fv(mShadowFrustPoints[i][j].mV);
-						
-						}
-					gGL.end();
-
-					gGL.flush();
-					glPointSize(1.f);
-
-					LLVector3* ext = mShadowExtents[i]; 
-					LLVector3 pos = (ext[0]+ext[1])*0.5f;
-					LLVector3 size = (ext[1]-ext[0])*0.5f;
-					drawBoxOutline(pos, size);
-
-					//render camera frustum splits as outlines
-					gGL.begin(LLRender::LINES);
-					gGL.vertex3fv(frust[0].mV); gGL.vertex3fv(frust[1].mV);
-					gGL.vertex3fv(frust[1].mV); gGL.vertex3fv(frust[2].mV);
-					gGL.vertex3fv(frust[2].mV); gGL.vertex3fv(frust[3].mV);
-					gGL.vertex3fv(frust[3].mV); gGL.vertex3fv(frust[0].mV);
-					gGL.vertex3fv(frust[4].mV); gGL.vertex3fv(frust[5].mV);
-					gGL.vertex3fv(frust[5].mV); gGL.vertex3fv(frust[6].mV);
-					gGL.vertex3fv(frust[6].mV); gGL.vertex3fv(frust[7].mV);
-					gGL.vertex3fv(frust[7].mV); gGL.vertex3fv(frust[4].mV);
-					gGL.vertex3fv(frust[0].mV); gGL.vertex3fv(frust[4].mV);
-					gGL.vertex3fv(frust[1].mV); gGL.vertex3fv(frust[5].mV);
-					gGL.vertex3fv(frust[2].mV); gGL.vertex3fv(frust[6].mV);
-					gGL.vertex3fv(frust[3].mV); gGL.vertex3fv(frust[7].mV);
-					gGL.end();
-				}
-			}
-
-			/*gGL.flush();
-			glLineWidth(16-i*2);
-			for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
-					iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
-			{
-				LLViewerRegion* region = *iter;
-				for (U32 j = 0; j < LLViewerRegion::NUM_PARTITIONS; j++)
-				{
-					LLSpatialPartition* part = region->getSpatialPartition(j);
-					if (part)
-					{
-						if (hasRenderType(part->mDrawableType))
-						{
-							part->renderIntersectingBBoxes(&mShadowCamera[i]);
-						}
-					}
-				}
-			}
-			gGL.flush();
-			glLineWidth(1.f);*/
-		}
-	}
-
-	if (mRenderDebugMask & RENDER_DEBUG_WIND_VECTORS)
-	{
-		gAgent.getRegion()->mWind.renderVectors();
-	}
-	
-	if (mRenderDebugMask & RENDER_DEBUG_COMPOSITION)
-	{
-		// Debug composition layers
-		F32 x, y;
-
-		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-
-		if (gAgent.getRegion())
-		{
-			gGL.begin(LLRender::POINTS);
-			// Draw the composition layer for the region that I'm in.
-			for (x = 0; x <= 260; x++)
-			{
-				for (y = 0; y <= 260; y++)
-				{
-					if ((x > 255) || (y > 255))
-					{
-						gGL.color4f(1.f, 0.f, 0.f, 1.f);
-					}
-					else
-					{
-						gGL.color4f(0.f, 0.f, 1.f, 1.f);
-					}
-					F32 z = gAgent.getRegion()->getCompositionXY((S32)x, (S32)y);
-					z *= 5.f;
-					z += 50.f;
-					gGL.vertex3f(x, y, z);
-				}
-			}
-			gGL.end();
-		}
-	}
-
-	if (mRenderDebugMask & LLPipeline::RENDER_DEBUG_BUILD_QUEUE)
-	{
-		U32 count = 0;
-		U32 size = mGroupQ2.size();
-		LLColor4 col;
-
-		LLVertexBuffer::unbind();
-		LLGLEnable blend(GL_BLEND);
-		gGL.setSceneBlendType(LLRender::BT_ALPHA);
-		LLGLDepthTest depth(GL_TRUE, GL_FALSE);
-		gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sWhiteImagep);
-		
-		gGL.pushMatrix();
-		gGL.loadMatrix(gGLModelView);
-		gGLLastMatrix = NULL;
-
-		for (LLSpatialGroup::sg_vector_t::iterator iter = mGroupQ2.begin(); iter != mGroupQ2.end(); ++iter)
-		{
-			LLSpatialGroup* group = *iter;
-			if (group->isDead())
-			{
-				continue;
-			}
-
-			LLSpatialBridge* bridge = group->mSpatialPartition->asBridge();
-
-			if (bridge && (!bridge->mDrawable || bridge->mDrawable->isDead()))
-			{
-				continue;
-			}
-
-			if (bridge)
-			{
-				gGL.pushMatrix();
-				gGL.multMatrix((F32*)bridge->mDrawable->getRenderMatrix().mMatrix);
-			}
-
-			F32 alpha = llclamp((F32) (size-count)/size, 0.f, 1.f);
-
-			
-			LLVector2 c(1.f-alpha, alpha);
-			c.normVec();
-
-			
-			++count;
-			col.set(c.mV[0], c.mV[1], 0, alpha*0.5f+0.5f);
-			group->drawObjectBox(col);
-
-			if (bridge)
-			{
-				gGL.popMatrix();
-			}
-		}
-
-		gGL.popMatrix();
-	}
-
-	gGL.flush();
-	if (LLGLSLShader::sNoFixedFunction)
-	{
-		gUIProgram.unbind();
-	}
-}
-
-void LLPipeline::rebuildPools()
-{
-	LLMemType mt(LLMemType::MTYPE_PIPELINE_REBUILD_POOLS);
-
-	assertInitialized();
-
-	S32 max_count = mPools.size();
-	pool_set_t::iterator iter1 = mPools.upper_bound(mLastRebuildPool);
-	while(max_count > 0 && mPools.size() > 0) // && num_rebuilds < MAX_REBUILDS)
-	{
-		if (iter1 == mPools.end())
-		{
-			iter1 = mPools.begin();
-		}
-		LLDrawPool* poolp = *iter1;
-
-		if (poolp->isDead())
-		{
-			mPools.erase(iter1++);
-			removeFromQuickLookup( poolp );
-			if (poolp == mLastRebuildPool)
-			{
-				mLastRebuildPool = NULL;
-			}
-			delete poolp;
-		}
-		else
-		{
-			mLastRebuildPool = poolp;
-			iter1++;
-		}
-		max_count--;
-	}
-
-	if (isAgentAvatarValid())
-	{
-		gAgentAvatarp->rebuildHUD();
-	}
-}
-
-void LLPipeline::addToQuickLookup( LLDrawPool* new_poolp )
-{
-	LLMemType mt(LLMemType::MTYPE_PIPELINE_QUICK_LOOKUP);
-
-	assertInitialized();
-
-	switch( new_poolp->getType() )
-	{
-	case LLDrawPool::POOL_SIMPLE:
-		if (mSimplePool)
-		{
-			llassert(0);
-			llwarns << "Ignoring duplicate simple pool." << llendl;
-		}
-		else
-		{
-			mSimplePool = (LLRenderPass*) new_poolp;
-		}
-		break;
-
-	case LLDrawPool::POOL_GRASS:
-		if (mGrassPool)
-		{
-			llassert(0);
-			llwarns << "Ignoring duplicate grass pool." << llendl;
-		}
-		else
-		{
-			mGrassPool = (LLRenderPass*) new_poolp;
-		}
-		break;
-
-	case LLDrawPool::POOL_FULLBRIGHT:
-		if (mFullbrightPool)
-		{
-			llassert(0);
-			llwarns << "Ignoring duplicate simple pool." << llendl;
-		}
-		else
-		{
-			mFullbrightPool = (LLRenderPass*) new_poolp;
-		}
-		break;
-
-	case LLDrawPool::POOL_INVISIBLE:
-		if (mInvisiblePool)
-		{
-			llassert(0);
-			llwarns << "Ignoring duplicate simple pool." << llendl;
-		}
-		else
-		{
-			mInvisiblePool = (LLRenderPass*) new_poolp;
-		}
-		break;
-
-	case LLDrawPool::POOL_GLOW:
-		if (mGlowPool)
-		{
-			llassert(0);
-			llwarns << "Ignoring duplicate glow pool." << llendl;
-		}
-		else
-		{
-			mGlowPool = (LLRenderPass*) new_poolp;
-		}
-		break;
-
-	case LLDrawPool::POOL_TREE:
-		mTreePools[ uintptr_t(new_poolp->getTexture()) ] = new_poolp ;
-		break;
- 
-	case LLDrawPool::POOL_TERRAIN:
-		mTerrainPools[ uintptr_t(new_poolp->getTexture()) ] = new_poolp ;
-		break;
-
-	case LLDrawPool::POOL_BUMP:
-		if (mBumpPool)
-		{
-			llassert(0);
-			llwarns << "Ignoring duplicate bump pool." << llendl;
-		}
-		else
-		{
-			mBumpPool = new_poolp;
-		}
-		break;
-
-	case LLDrawPool::POOL_ALPHA:
-		if( mAlphaPool )
-		{
-			llassert(0);
-			llwarns << "LLPipeline::addPool(): Ignoring duplicate Alpha pool" << llendl;
-		}
-		else
-		{
-			mAlphaPool = new_poolp;
-		}
-		break;
-
-	case LLDrawPool::POOL_AVATAR:
-		break; // Do nothing
-
-	case LLDrawPool::POOL_SKY:
-		if( mSkyPool )
-		{
-			llassert(0);
-			llwarns << "LLPipeline::addPool(): Ignoring duplicate Sky pool" << llendl;
-		}
-		else
-		{
-			mSkyPool = new_poolp;
-		}
-		break;
-	
-	case LLDrawPool::POOL_WATER:
-		if( mWaterPool )
-		{
-			llassert(0);
-			llwarns << "LLPipeline::addPool(): Ignoring duplicate Water pool" << llendl;
-		}
-		else
-		{
-			mWaterPool = new_poolp;
-		}
-		break;
-
-	case LLDrawPool::POOL_GROUND:
-		if( mGroundPool )
-		{
-			llassert(0);
-			llwarns << "LLPipeline::addPool(): Ignoring duplicate Ground Pool" << llendl;
-		}
-		else
-		{ 
-			mGroundPool = new_poolp;
-		}
-		break;
-
-	case LLDrawPool::POOL_WL_SKY:
-		if( mWLSkyPool )
-		{
-			llassert(0);
-			llwarns << "LLPipeline::addPool(): Ignoring duplicate WLSky Pool" << llendl;
-		}
-		else
-		{ 
-			mWLSkyPool = new_poolp;
-		}
-		break;
-
-	default:
-		llassert(0);
-		llwarns << "Invalid Pool Type in  LLPipeline::addPool()" << llendl;
-		break;
-	}
-}
-
-void LLPipeline::removePool( LLDrawPool* poolp )
-{
-	assertInitialized();
-	removeFromQuickLookup(poolp);
-	mPools.erase(poolp);
-	delete poolp;
-}
-
-void LLPipeline::removeFromQuickLookup( LLDrawPool* poolp )
-{
-	assertInitialized();
-	LLMemType mt(LLMemType::MTYPE_PIPELINE);
-	switch( poolp->getType() )
-	{
-	case LLDrawPool::POOL_SIMPLE:
-		llassert(mSimplePool == poolp);
-		mSimplePool = NULL;
-		break;
-
-	case LLDrawPool::POOL_GRASS:
-		llassert(mGrassPool == poolp);
-		mGrassPool = NULL;
-		break;
-
-	case LLDrawPool::POOL_FULLBRIGHT:
-		llassert(mFullbrightPool == poolp);
-		mFullbrightPool = NULL;
-		break;
-
-	case LLDrawPool::POOL_INVISIBLE:
-		llassert(mInvisiblePool == poolp);
-		mInvisiblePool = NULL;
-		break;
-
-	case LLDrawPool::POOL_WL_SKY:
-		llassert(mWLSkyPool == poolp);
-		mWLSkyPool = NULL;
-		break;
-
-	case LLDrawPool::POOL_GLOW:
-		llassert(mGlowPool == poolp);
-		mGlowPool = NULL;
-		break;
-
-	case LLDrawPool::POOL_TREE:
-		#ifdef _DEBUG
-			{
-				BOOL found = mTreePools.erase( (uintptr_t)poolp->getTexture() );
-				llassert( found );
-			}
-		#else
-			mTreePools.erase( (uintptr_t)poolp->getTexture() );
-		#endif
-		break;
-
-	case LLDrawPool::POOL_TERRAIN:
-		#ifdef _DEBUG
-			{
-				BOOL found = mTerrainPools.erase( (uintptr_t)poolp->getTexture() );
-				llassert( found );
-			}
-		#else
-			mTerrainPools.erase( (uintptr_t)poolp->getTexture() );
-		#endif
-		break;
-
-	case LLDrawPool::POOL_BUMP:
-		llassert( poolp == mBumpPool );
-		mBumpPool = NULL;
-		break;
-	
-	case LLDrawPool::POOL_ALPHA:
-		llassert( poolp == mAlphaPool );
-		mAlphaPool = NULL;
-		break;
-
-	case LLDrawPool::POOL_AVATAR:
-		break; // Do nothing
-
-	case LLDrawPool::POOL_SKY:
-		llassert( poolp == mSkyPool );
-		mSkyPool = NULL;
-		break;
-
-	case LLDrawPool::POOL_WATER:
-		llassert( poolp == mWaterPool );
-		mWaterPool = NULL;
-		break;
-
-	case LLDrawPool::POOL_GROUND:
-		llassert( poolp == mGroundPool );
-		mGroundPool = NULL;
-		break;
-
-	default:
-		llassert(0);
-		llwarns << "Invalid Pool Type in  LLPipeline::removeFromQuickLookup() type=" << poolp->getType() << llendl;
-		break;
-	}
-}
-
-void LLPipeline::resetDrawOrders()
-{
-	assertInitialized();
-	// Iterate through all of the draw pools and rebuild them.
-	for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
-	{
-		LLDrawPool *poolp = *iter;
-		poolp->resetDrawOrders();
-	}
-}
-
-//============================================================================
-// Once-per-frame setup of hardware lights,
-// including sun/moon, avatar backlight, and up to 6 local lights
-
-void LLPipeline::setupAvatarLights(BOOL for_edit)
-{
-	assertInitialized();
-
-	if (for_edit)
-	{
-		LLColor4 diffuse(1.f, 1.f, 1.f, 0.f);
-		LLVector4 light_pos_cam(-8.f, 0.25f, 10.f, 0.f);  // w==0 => directional light
-		LLMatrix4 camera_mat = LLViewerCamera::getInstance()->getModelview();
-		LLMatrix4 camera_rot(camera_mat.getMat3());
-		camera_rot.invert();
-		LLVector4 light_pos = light_pos_cam * camera_rot;
-		
-		light_pos.normalize();
-
-		LLLightState* light = gGL.getLight(1);
-
-		mHWLightColors[1] = diffuse;
-
-		light->setDiffuse(diffuse);
-		light->setAmbient(LLColor4::black);
-		light->setSpecular(LLColor4::black);
-		light->setPosition(light_pos);
-		light->setConstantAttenuation(1.f);
-		light->setLinearAttenuation(0.f);
-		light->setQuadraticAttenuation(0.f);
-		light->setSpotExponent(0.f);
-		light->setSpotCutoff(180.f);
-	}
-	else if (gAvatarBacklight) // Always true (unless overridden in a devs .ini)
-	{
-		LLVector3 opposite_pos = -1.f * mSunDir;
-		LLVector3 orthog_light_pos = mSunDir % LLVector3::z_axis;
-		LLVector4 backlight_pos = LLVector4(lerp(opposite_pos, orthog_light_pos, 0.3f), 0.0f);
-		backlight_pos.normalize();
-			
-		LLColor4 light_diffuse = mSunDiffuse;
-		LLColor4 backlight_diffuse(1.f - light_diffuse.mV[VRED], 1.f - light_diffuse.mV[VGREEN], 1.f - light_diffuse.mV[VBLUE], 1.f);
-		F32 max_component = 0.001f;
-		for (S32 i = 0; i < 3; i++)
-		{
-			if (backlight_diffuse.mV[i] > max_component)
-			{
-				max_component = backlight_diffuse.mV[i];
-			}
-		}
-		F32 backlight_mag;
-		if (gSky.getSunDirection().mV[2] >= LLSky::NIGHTTIME_ELEVATION_COS)
-		{
-			backlight_mag = BACKLIGHT_DAY_MAGNITUDE_OBJECT;
-		}
-		else
-		{
-			backlight_mag = BACKLIGHT_NIGHT_MAGNITUDE_OBJECT;
-		}
-		backlight_diffuse *= backlight_mag / max_component;
-
-		mHWLightColors[1] = backlight_diffuse;
-
-		LLLightState* light = gGL.getLight(1);
-
-		light->setPosition(backlight_pos);
-		light->setDiffuse(backlight_diffuse);
-		light->setAmbient(LLColor4::black);
-		light->setSpecular(LLColor4::black);
-		light->setConstantAttenuation(1.f);
-		light->setLinearAttenuation(0.f);
-		light->setQuadraticAttenuation(0.f);
-		light->setSpotExponent(0.f);
-		light->setSpotCutoff(180.f);
-	}
-	else
-	{
-		LLLightState* light = gGL.getLight(1);
-
-		mHWLightColors[1] = LLColor4::black;
-
-		light->setDiffuse(LLColor4::black);
-		light->setAmbient(LLColor4::black);
-		light->setSpecular(LLColor4::black);
-	}
-}
-
-static F32 calc_light_dist(LLVOVolume* light, const LLVector3& cam_pos, F32 max_dist)
-{
-	F32 inten = light->getLightIntensity();
-	if (inten < .001f)
-	{
-		return max_dist;
-	}
-	F32 radius = light->getLightRadius();
-	BOOL selected = light->isSelected();
-	LLVector3 dpos = light->getRenderPosition() - cam_pos;
-	F32 dist2 = dpos.lengthSquared();
-	if (!selected && dist2 > (max_dist + radius)*(max_dist + radius))
-	{
-		return max_dist;
-	}
-	F32 dist = (F32) sqrt(dist2);
-	dist *= 1.f / inten;
-	dist -= radius;
-	if (selected)
-	{
-		dist -= 10000.f; // selected lights get highest priority
-	}
-	if (light->mDrawable.notNull() && light->mDrawable->isState(LLDrawable::ACTIVE))
-	{
-		// moving lights get a little higher priority (too much causes artifacts)
-		dist -= light->getLightRadius()*0.25f;
-	}
-	return dist;
-}
-
-void LLPipeline::calcNearbyLights(LLCamera& camera)
-{
-	assertInitialized();
-
-	if (LLPipeline::sReflectionRender)
-	{
-		return;
-	}
-
-	if (mLightingDetail >= 1)
-	{
-		// mNearbyLight (and all light_set_t's) are sorted such that
-		// begin() == the closest light and rbegin() == the farthest light
-		const S32 MAX_LOCAL_LIGHTS = 6;
-// 		LLVector3 cam_pos = gAgent.getCameraPositionAgent();
-		LLVector3 cam_pos = LLViewerJoystick::getInstance()->getOverrideCamera() ?
-						camera.getOrigin() : 
-						gAgent.getPositionAgent();
-
-		F32 max_dist = LIGHT_MAX_RADIUS * 4.f; // ignore enitrely lights > 4 * max light rad
-		
-		// UPDATE THE EXISTING NEARBY LIGHTS
-		light_set_t cur_nearby_lights;
-		for (light_set_t::iterator iter = mNearbyLights.begin();
-			iter != mNearbyLights.end(); iter++)
-		{
-			const Light* light = &(*iter);
-			LLDrawable* drawable = light->drawable;
-			LLVOVolume* volight = drawable->getVOVolume();
-			if (!volight || !drawable->isState(LLDrawable::LIGHT))
-			{
-				drawable->clearState(LLDrawable::NEARBY_LIGHT);
-				continue;
-			}
-			if (light->fade <= -LIGHT_FADE_TIME)
-			{
-				drawable->clearState(LLDrawable::NEARBY_LIGHT);
-				continue;
-			}
-			if (!sRenderAttachedLights && volight && volight->isAttachment())
-			{
-				drawable->clearState(LLDrawable::NEARBY_LIGHT);
-				continue;
-			}
-
-			F32 dist = calc_light_dist(volight, cam_pos, max_dist);
-			cur_nearby_lights.insert(Light(drawable, dist, light->fade));
-		}
-		mNearbyLights = cur_nearby_lights;
-				
-		// FIND NEW LIGHTS THAT ARE IN RANGE
-		light_set_t new_nearby_lights;
-		for (LLDrawable::drawable_set_t::iterator iter = mLights.begin();
-			 iter != mLights.end(); ++iter)
-		{
-			LLDrawable* drawable = *iter;
-			LLVOVolume* light = drawable->getVOVolume();
-			if (!light || drawable->isState(LLDrawable::NEARBY_LIGHT))
-			{
-				continue;
-			}
-			if (light->isHUDAttachment())
-			{
-				continue; // no lighting from HUD objects
-			}
-			F32 dist = calc_light_dist(light, cam_pos, max_dist);
-			if (dist >= max_dist)
-			{
-				continue;
-			}
-			if (!sRenderAttachedLights && light && light->isAttachment())
-			{
-				continue;
-			}
-			new_nearby_lights.insert(Light(drawable, dist, 0.f));
-			if (new_nearby_lights.size() > (U32)MAX_LOCAL_LIGHTS)
-			{
-				new_nearby_lights.erase(--new_nearby_lights.end());
-				const Light& last = *new_nearby_lights.rbegin();
-				max_dist = last.dist;
-			}
-		}
-
-		// INSERT ANY NEW LIGHTS
-		for (light_set_t::iterator iter = new_nearby_lights.begin();
-			 iter != new_nearby_lights.end(); iter++)
-		{
-			const Light* light = &(*iter);
-			if (mNearbyLights.size() < (U32)MAX_LOCAL_LIGHTS)
-			{
-				mNearbyLights.insert(*light);
-				((LLDrawable*) light->drawable)->setState(LLDrawable::NEARBY_LIGHT);
-			}
-			else
-			{
-				// crazy cast so that we can overwrite the fade value
-				// even though gcc enforces sets as const
-				// (fade value doesn't affect sort so this is safe)
-				Light* farthest_light = ((Light*) (&(*(mNearbyLights.rbegin()))));
-				if (light->dist < farthest_light->dist)
-				{
-					if (farthest_light->fade >= 0.f)
-					{
-						farthest_light->fade = -gFrameIntervalSeconds;
-					}
-				}
-				else
-				{
-					break; // none of the other lights are closer
-				}
-			}
-		}
-		
-	}
-}
-
-void LLPipeline::setupHWLights(LLDrawPool* pool)
-{
-	assertInitialized();
-	
-	// Ambient
-	if (!LLGLSLShader::sNoFixedFunction)
-	{
-		gGL.syncMatrices();
-		LLColor4 ambient = gSky.getTotalAmbientColor();
-		gGL.setAmbientLightColor(ambient);
-	}
-
-	// Light 0 = Sun or Moon (All objects)
-	{
-		if (gSky.getSunDirection().mV[2] >= LLSky::NIGHTTIME_ELEVATION_COS)
-		{
-			mSunDir.setVec(gSky.getSunDirection());
-			mSunDiffuse.setVec(gSky.getSunDiffuseColor());
-		}
-		else
-		{
-			mSunDir.setVec(gSky.getMoonDirection());
-			mSunDiffuse.setVec(gSky.getMoonDiffuseColor());
-		}
-
-		F32 max_color = llmax(mSunDiffuse.mV[0], mSunDiffuse.mV[1], mSunDiffuse.mV[2]);
-		if (max_color > 1.f)
-		{
-			mSunDiffuse *= 1.f/max_color;
-		}
-		mSunDiffuse.clamp();
-
-		LLVector4 light_pos(mSunDir, 0.0f);
-		LLColor4 light_diffuse = mSunDiffuse;
-		mHWLightColors[0] = light_diffuse;
-
-		LLLightState* light = gGL.getLight(0);
-		light->setPosition(light_pos);
-		light->setDiffuse(light_diffuse);
-		light->setAmbient(LLColor4::black);
-		light->setSpecular(LLColor4::black);
-		light->setConstantAttenuation(1.f);
-		light->setLinearAttenuation(0.f);
-		light->setQuadraticAttenuation(0.f);
-		light->setSpotExponent(0.f);
-		light->setSpotCutoff(180.f);
-	}
-	
-	// Light 1 = Backlight (for avatars)
-	// (set by enableLightsAvatar)
-	
-	S32 cur_light = 2;
-	
-	// Nearby lights = LIGHT 2-7
-
-	mLightMovingMask = 0;
-	
-	if (mLightingDetail >= 1)
-	{
-		for (light_set_t::iterator iter = mNearbyLights.begin();
-			 iter != mNearbyLights.end(); ++iter)
-		{
-			LLDrawable* drawable = iter->drawable;
-			LLVOVolume* light = drawable->getVOVolume();
-			if (!light)
-			{
-				continue;
-			}
-			if (drawable->isState(LLDrawable::ACTIVE))
-			{
-				mLightMovingMask |= (1<<cur_light);
-			}
-			
-			LLColor4  light_color = light->getLightColor();
-			light_color.mV[3] = 0.0f;
-
-			F32 fade = iter->fade;
-			if (fade < LIGHT_FADE_TIME)
-			{
-				// fade in/out light
-				if (fade >= 0.f)
-				{
-					fade = fade / LIGHT_FADE_TIME;
-					((Light*) (&(*iter)))->fade += gFrameIntervalSeconds;
-				}
-				else
-				{
-					fade = 1.f + fade / LIGHT_FADE_TIME;
-					((Light*) (&(*iter)))->fade -= gFrameIntervalSeconds;
-				}
-				fade = llclamp(fade,0.f,1.f);
-				light_color *= fade;
-			}
-
-			LLVector3 light_pos(light->getRenderPosition());
-			LLVector4 light_pos_gl(light_pos, 1.0f);
-	
-			F32 light_radius = llmax(light->getLightRadius(), 0.001f);
-
-			F32 x = (3.f * (1.f + light->getLightFalloff())); // why this magic?  probably trying to match a historic behavior.
-			float linatten = x / (light_radius); // % of brightness at radius
-
-			mHWLightColors[cur_light] = light_color;
-			LLLightState* light_state = gGL.getLight(cur_light);
-			
-			light_state->setPosition(light_pos_gl);
-			light_state->setDiffuse(light_color);
-			light_state->setAmbient(LLColor4::black);
-			light_state->setConstantAttenuation(0.f);
-			if (sRenderDeferred)
-			{
-				light_state->setLinearAttenuation(light_radius*1.5f);
-				light_state->setQuadraticAttenuation(light->getLightFalloff()*0.5f+1.f);
-			}
-			else
-			{
-				light_state->setLinearAttenuation(linatten);
-				light_state->setQuadraticAttenuation(0.f);
-			}
-			
-
-			if (light->isLightSpotlight() // directional (spot-)light
-			    && (LLPipeline::sRenderDeferred || RenderSpotLightsInNondeferred)) // these are only rendered as GL spotlights if we're in deferred rendering mode *or* the setting forces them on
-			{
-				LLVector3 spotparams = light->getSpotLightParams();
-				LLQuaternion quat = light->getRenderRotation();
-				LLVector3 at_axis(0,0,-1); // this matches deferred rendering's object light direction
-				at_axis *= quat;
-
-				light_state->setSpotDirection(at_axis);
-				light_state->setSpotCutoff(90.f);
-				light_state->setSpotExponent(2.f);
-	
-				light_state->setSpecular(LLColor4::black);
-			}
-			else // omnidirectional (point) light
-			{
-				light_state->setSpotExponent(0.f);
-				light_state->setSpotCutoff(180.f);
-				
-				// we use specular.w = 1.0 as a cheap hack for the shaders to know that this is omnidirectional rather than a spotlight
-				const LLColor4 specular(0.f, 0.f, 0.f, 1.f);
-				light_state->setSpecular(specular);				
-			}
-			cur_light++;
-			if (cur_light >= 8)
-			{
-				break; // safety
-			}
-		}
-	}
-	for ( ; cur_light < 8 ; cur_light++)
-	{
-		mHWLightColors[cur_light] = LLColor4::black;
-		LLLightState* light = gGL.getLight(cur_light);
-
-		light->setDiffuse(LLColor4::black);
-		light->setAmbient(LLColor4::black);
-		light->setSpecular(LLColor4::black);
-	}
-	if (gAgentAvatarp &&
-		gAgentAvatarp->mSpecialRenderMode == 3)
-	{
-		LLColor4  light_color = LLColor4::white;
-		light_color.mV[3] = 0.0f;
-
-		LLVector3 light_pos(LLViewerCamera::getInstance()->getOrigin());
-		LLVector4 light_pos_gl(light_pos, 1.0f);
-
-		F32 light_radius = 16.f;
-
-			F32 x = 3.f;
-		float linatten = x / (light_radius); // % of brightness at radius
-
-		mHWLightColors[2] = light_color;
-		LLLightState* light = gGL.getLight(2);
-
-		light->setPosition(light_pos_gl);
-		light->setDiffuse(light_color);
-		light->setAmbient(LLColor4::black);
-		light->setSpecular(LLColor4::black);
-		light->setQuadraticAttenuation(0.f);
-		light->setConstantAttenuation(0.f);
-		light->setLinearAttenuation(linatten);
-		light->setSpotExponent(0.f);
-		light->setSpotCutoff(180.f);
-	}
-
-	// Init GL state
-	if (!LLGLSLShader::sNoFixedFunction)
-	{
-		glDisable(GL_LIGHTING);
-	}
-
-	for (S32 i = 0; i < 8; ++i)
-	{
-		gGL.getLight(i)->disable();
-	}
-	mLightMask = 0;
-}
-
-void LLPipeline::enableLights(U32 mask)
-{
-	assertInitialized();
-
-	if (mLightingDetail == 0)
-	{
-		mask &= 0xf003; // sun and backlight only (and fullbright bit)
-	}
-	if (mLightMask != mask)
-	{
-		stop_glerror();
-		if (!mLightMask)
-		{
-			if (!LLGLSLShader::sNoFixedFunction)
-			{
-				glEnable(GL_LIGHTING);
-			}
-		}
-		if (mask)
-		{
-			stop_glerror();
-			for (S32 i=0; i<8; i++)
-			{
-				LLLightState* light = gGL.getLight(i);
-				if (mask & (1<<i))
-				{
-					light->enable();
-					light->setDiffuse(mHWLightColors[i]);
-				}
-				else
-				{
-					light->disable();
-					light->setDiffuse(LLColor4::black);
-				}
-			}
-			stop_glerror();
-		}
-		else
-		{
-			if (!LLGLSLShader::sNoFixedFunction)
-			{
-				glDisable(GL_LIGHTING);
-			}
-		}
-		mLightMask = mask;
-		stop_glerror();
-
-		LLColor4 ambient = gSky.getTotalAmbientColor();
-		gGL.setAmbientLightColor(ambient);
-	}
-}
-
-void LLPipeline::enableLightsStatic()
-{
-	assertInitialized();
-	U32 mask = 0x01; // Sun
-	if (mLightingDetail >= 2)
-	{
-		mask |= mLightMovingMask; // Hardware moving lights
-	}
-	else
-	{
-		mask |= 0xff & (~2); // Hardware local lights
-	}
-	enableLights(mask);
-}
-
-void LLPipeline::enableLightsDynamic()
-{
-	assertInitialized();
-	U32 mask = 0xff & (~2); // Local lights
-	enableLights(mask);
-	
-	if (isAgentAvatarValid() && getLightingDetail() <= 0)
-	{
-		if (gAgentAvatarp->mSpecialRenderMode == 0) // normal
-		{
-			gPipeline.enableLightsAvatar();
-		}
-		else if (gAgentAvatarp->mSpecialRenderMode >= 1)  // anim preview
-		{
-			gPipeline.enableLightsAvatarEdit(LLColor4(0.7f, 0.6f, 0.3f, 1.f));
-		}
-	}
-}
-
-void LLPipeline::enableLightsAvatar()
-{
-	U32 mask = 0xff; // All lights
-	setupAvatarLights(FALSE);
-	enableLights(mask);
-}
-
-void LLPipeline::enableLightsPreview()
-{
-	disableLights();
-
-	if (!LLGLSLShader::sNoFixedFunction)
-	{
-		glEnable(GL_LIGHTING);
-	}
-
-	LLColor4 ambient = PreviewAmbientColor;
-	gGL.setAmbientLightColor(ambient);
-
-	LLColor4 diffuse0 = PreviewDiffuse0;
-	LLColor4 specular0 = PreviewSpecular0;
-	LLColor4 diffuse1 = PreviewDiffuse1;
-	LLColor4 specular1 = PreviewSpecular1;
-	LLColor4 diffuse2 = PreviewDiffuse2;
-	LLColor4 specular2 = PreviewSpecular2;
-
-	LLVector3 dir0 = PreviewDirection0;
-	LLVector3 dir1 = PreviewDirection1;
-	LLVector3 dir2 = PreviewDirection2;
-
-	dir0.normVec();
-	dir1.normVec();
-	dir2.normVec();
-	
-	LLVector4 light_pos(dir0, 0.0f);
-
-	LLLightState* light = gGL.getLight(0);
-
-	light->enable();
-	light->setPosition(light_pos);
-	light->setDiffuse(diffuse0);
-	light->setAmbient(LLColor4::black);
-	light->setSpecular(specular0);
-	light->setSpotExponent(0.f);
-	light->setSpotCutoff(180.f);
-
-	light_pos = LLVector4(dir1, 0.f);
-
-	light = gGL.getLight(1);
-	light->enable();
-	light->setPosition(light_pos);
-	light->setDiffuse(diffuse1);
-	light->setAmbient(LLColor4::black);
-	light->setSpecular(specular1);
-	light->setSpotExponent(0.f);
-	light->setSpotCutoff(180.f);
-
-	light_pos = LLVector4(dir2, 0.f);
-	light = gGL.getLight(2);
-	light->enable();
-	light->setPosition(light_pos);
-	light->setDiffuse(diffuse2);
-	light->setAmbient(LLColor4::black);
-	light->setSpecular(specular2);
-	light->setSpotExponent(0.f);
-	light->setSpotCutoff(180.f);
-}
-
-
-void LLPipeline::enableLightsAvatarEdit(const LLColor4& color)
-{
-	U32 mask = 0x2002; // Avatar backlight only, set ambient
-	setupAvatarLights(TRUE);
-	enableLights(mask);
-
-	gGL.setAmbientLightColor(color);
-}
-
-void LLPipeline::enableLightsFullbright(const LLColor4& color)
-{
-	assertInitialized();
-	U32 mask = 0x1000; // Non-0 mask, set ambient
-	enableLights(mask);
-
-	gGL.setAmbientLightColor(color);
-}
-
-void LLPipeline::disableLights()
-{
-	enableLights(0); // no lighting (full bright)
-}
-
-//============================================================================
-
-class LLMenuItemGL;
-class LLInvFVBridge;
-struct cat_folder_pair;
-class LLVOBranch;
-class LLVOLeaf;
-
-void LLPipeline::findReferences(LLDrawable *drawablep)
-{
-	assertInitialized();
-	if (mLights.find(drawablep) != mLights.end())
-	{
-		llinfos << "In mLights" << llendl;
-	}
-	if (std::find(mMovedList.begin(), mMovedList.end(), drawablep) != mMovedList.end())
-	{
-		llinfos << "In mMovedList" << llendl;
-	}
-	if (std::find(mShiftList.begin(), mShiftList.end(), drawablep) != mShiftList.end())
-	{
-		llinfos << "In mShiftList" << llendl;
-	}
-	if (mRetexturedList.find(drawablep) != mRetexturedList.end())
-	{
-		llinfos << "In mRetexturedList" << llendl;
-	}
-	
-	if (std::find(mBuildQ1.begin(), mBuildQ1.end(), drawablep) != mBuildQ1.end())
-	{
-		llinfos << "In mBuildQ1" << llendl;
-	}
-	if (std::find(mBuildQ2.begin(), mBuildQ2.end(), drawablep) != mBuildQ2.end())
-	{
-		llinfos << "In mBuildQ2" << llendl;
-	}
-
-	S32 count;
-	
-	count = gObjectList.findReferences(drawablep);
-	if (count)
-	{
-		llinfos << "In other drawables: " << count << " references" << llendl;
-	}
-}
-
-BOOL LLPipeline::verify()
-{
-	BOOL ok = assertInitialized();
-	if (ok) 
-	{
-		for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
-		{
-			LLDrawPool *poolp = *iter;
-			if (!poolp->verify())
-			{
-				ok = FALSE;
-			}
-		}
-	}
-
-	if (!ok)
-	{
-		llwarns << "Pipeline verify failed!" << llendl;
-	}
-	return ok;
-}
-
-//////////////////////////////
-//
-// Collision detection
-//
-//
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-/**
- *	A method to compute a ray-AABB intersection.
- *	Original code by Andrew Woo, from "Graphics Gems", Academic Press, 1990
- *	Optimized code by Pierre Terdiman, 2000 (~20-30% faster on my Celeron 500)
- *	Epsilon value added by Klaus Hartmann. (discarding it saves a few cycles only)
- *
- *	Hence this version is faster as well as more robust than the original one.
- *
- *	Should work provided:
- *	1) the integer representation of 0.0f is 0x00000000
- *	2) the sign bit of the float is the most significant one
- *
- *	Report bugs: p.terdiman@codercorner.com
- *
- *	\param		aabb		[in] the axis-aligned bounding box
- *	\param		origin		[in] ray origin
- *	\param		dir			[in] ray direction
- *	\param		coord		[out] impact coordinates
- *	\return		true if ray intersects AABB
- */
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//#define RAYAABB_EPSILON 0.00001f
-#define IR(x)	((U32&)x)
-
-bool LLRayAABB(const LLVector3 &center, const LLVector3 &size, const LLVector3& origin, const LLVector3& dir, LLVector3 &coord, F32 epsilon)
-{
-	BOOL Inside = TRUE;
-	LLVector3 MinB = center - size;
-	LLVector3 MaxB = center + size;
-	LLVector3 MaxT;
-	MaxT.mV[VX]=MaxT.mV[VY]=MaxT.mV[VZ]=-1.0f;
-
-	// Find candidate planes.
-	for(U32 i=0;i<3;i++)
-	{
-		if(origin.mV[i] < MinB.mV[i])
-		{
-			coord.mV[i]	= MinB.mV[i];
-			Inside		= FALSE;
-
-			// Calculate T distances to candidate planes
-			if(IR(dir.mV[i]))	MaxT.mV[i] = (MinB.mV[i] - origin.mV[i]) / dir.mV[i];
-		}
-		else if(origin.mV[i] > MaxB.mV[i])
-		{
-			coord.mV[i]	= MaxB.mV[i];
-			Inside		= FALSE;
-
-			// Calculate T distances to candidate planes
-			if(IR(dir.mV[i]))	MaxT.mV[i] = (MaxB.mV[i] - origin.mV[i]) / dir.mV[i];
-		}
-	}
-
-	// Ray origin inside bounding box
-	if(Inside)
-	{
-		coord = origin;
-		return true;
-	}
-
-	// Get largest of the maxT's for final choice of intersection
-	U32 WhichPlane = 0;
-	if(MaxT.mV[1] > MaxT.mV[WhichPlane])	WhichPlane = 1;
-	if(MaxT.mV[2] > MaxT.mV[WhichPlane])	WhichPlane = 2;
-
-	// Check final candidate actually inside box
-	if(IR(MaxT.mV[WhichPlane])&0x80000000) return false;
-
-	for(U32 i=0;i<3;i++)
-	{
-		if(i!=WhichPlane)
-		{
-			coord.mV[i] = origin.mV[i] + MaxT.mV[WhichPlane] * dir.mV[i];
-			if (epsilon > 0)
-			{
-				if(coord.mV[i] < MinB.mV[i] - epsilon || coord.mV[i] > MaxB.mV[i] + epsilon)	return false;
-			}
-			else
-			{
-				if(coord.mV[i] < MinB.mV[i] || coord.mV[i] > MaxB.mV[i])	return false;
-			}
-		}
-	}
-	return true;	// ray hits box
-}
-
-//////////////////////////////
-//
-// Macros, functions, and inline methods from other classes
-//
-//
-
-void LLPipeline::setLight(LLDrawable *drawablep, BOOL is_light)
-{
-	if (drawablep && assertInitialized())
-	{
-		if (is_light)
-		{
-			mLights.insert(drawablep);
-			drawablep->setState(LLDrawable::LIGHT);
-		}
-		else
-		{
-			drawablep->clearState(LLDrawable::LIGHT);
-			mLights.erase(drawablep);
-		}
-	}
-}
-
-//static
-void LLPipeline::toggleRenderType(U32 type)
-{
-	gPipeline.mRenderTypeEnabled[type] = !gPipeline.mRenderTypeEnabled[type];
-	if (type == LLPipeline::RENDER_TYPE_WATER)
-	{
-		gPipeline.mRenderTypeEnabled[LLPipeline::RENDER_TYPE_VOIDWATER] = !gPipeline.mRenderTypeEnabled[LLPipeline::RENDER_TYPE_VOIDWATER];
-	}
-}
-
-//static
-void LLPipeline::toggleRenderTypeControl(void* data)
-{
-	U32 type = (U32)(intptr_t)data;
-	U32 bit = (1<<type);
-	if (gPipeline.hasRenderType(type))
-	{
-		llinfos << "Toggling render type mask " << std::hex << bit << " off" << std::dec << llendl;
-	}
-	else
-	{
-		llinfos << "Toggling render type mask " << std::hex << bit << " on" << std::dec << llendl;
-	}
-	gPipeline.toggleRenderType(type);
-}
-
-//static
-BOOL LLPipeline::hasRenderTypeControl(void* data)
-{
-	U32 type = (U32)(intptr_t)data;
-	return gPipeline.hasRenderType(type);
-}
-
-// Allows UI items labeled "Hide foo" instead of "Show foo"
-//static
-BOOL LLPipeline::toggleRenderTypeControlNegated(void* data)
-{
-	S32 type = (S32)(intptr_t)data;
-	return !gPipeline.hasRenderType(type);
-}
-
-//static
-void LLPipeline::toggleRenderDebug(void* data)
-{
-	U32 bit = (U32)(intptr_t)data;
-	if (gPipeline.hasRenderDebugMask(bit))
-	{
-		llinfos << "Toggling render debug mask " << std::hex << bit << " off" << std::dec << llendl;
-	}
-	else
-	{
-		llinfos << "Toggling render debug mask " << std::hex << bit << " on" << std::dec << llendl;
-	}
-	gPipeline.mRenderDebugMask ^= bit;
-}
-
-
-//static
-BOOL LLPipeline::toggleRenderDebugControl(void* data)
-{
-	U32 bit = (U32)(intptr_t)data;
-	return gPipeline.hasRenderDebugMask(bit);
-}
-
-//static
-void LLPipeline::toggleRenderDebugFeature(void* data)
-{
-	U32 bit = (U32)(intptr_t)data;
-	gPipeline.mRenderDebugFeatureMask ^= bit;
-}
-
-
-//static
-BOOL LLPipeline::toggleRenderDebugFeatureControl(void* data)
-{
-	U32 bit = (U32)(intptr_t)data;
-	return gPipeline.hasRenderDebugFeatureMask(bit);
-}
-
-void LLPipeline::setRenderDebugFeatureControl(U32 bit, bool value)
-{
-	if (value)
-	{
-		gPipeline.mRenderDebugFeatureMask |= bit;
-	}
-	else
-	{
-		gPipeline.mRenderDebugFeatureMask &= !bit;
-	}
-}
-
-// static
-void LLPipeline::setRenderScriptedBeacons(BOOL val)
-{
-	sRenderScriptedBeacons = val;
-}
-
-// static
-void LLPipeline::toggleRenderScriptedBeacons(void*)
-{
-	sRenderScriptedBeacons = !sRenderScriptedBeacons;
-}
-
-// static
-BOOL LLPipeline::getRenderScriptedBeacons(void*)
-{
-	return sRenderScriptedBeacons;
-}
-
-// static
-void LLPipeline::setRenderScriptedTouchBeacons(BOOL val)
-{
-	sRenderScriptedTouchBeacons = val;
-}
-
-// static
-void LLPipeline::toggleRenderScriptedTouchBeacons(void*)
-{
-	sRenderScriptedTouchBeacons = !sRenderScriptedTouchBeacons;
-}
-
-// static
-BOOL LLPipeline::getRenderScriptedTouchBeacons(void*)
-{
-	return sRenderScriptedTouchBeacons;
-}
-
-// static
-void LLPipeline::setRenderMOAPBeacons(BOOL val)
-{
-	sRenderMOAPBeacons = val;
-}
-
-// static
-void LLPipeline::toggleRenderMOAPBeacons(void*)
-{
-	sRenderMOAPBeacons = !sRenderMOAPBeacons;
-}
-
-// static
-BOOL LLPipeline::getRenderMOAPBeacons(void*)
-{
-	return sRenderMOAPBeacons;
-}
-
-// static
-void LLPipeline::setRenderPhysicalBeacons(BOOL val)
-{
-	sRenderPhysicalBeacons = val;
-}
-
-// static
-void LLPipeline::toggleRenderPhysicalBeacons(void*)
-{
-	sRenderPhysicalBeacons = !sRenderPhysicalBeacons;
-}
-
-// static
-BOOL LLPipeline::getRenderPhysicalBeacons(void*)
-{
-	return sRenderPhysicalBeacons;
-}
-
-// static
-void LLPipeline::setRenderParticleBeacons(BOOL val)
-{
-	sRenderParticleBeacons = val;
-}
-
-// static
-void LLPipeline::toggleRenderParticleBeacons(void*)
-{
-	sRenderParticleBeacons = !sRenderParticleBeacons;
-}
-
-// static
-BOOL LLPipeline::getRenderParticleBeacons(void*)
-{
-	return sRenderParticleBeacons;
-}
-
-// static
-void LLPipeline::setRenderSoundBeacons(BOOL val)
-{
-	sRenderSoundBeacons = val;
-}
-
-// static
-void LLPipeline::toggleRenderSoundBeacons(void*)
-{
-	sRenderSoundBeacons = !sRenderSoundBeacons;
-}
-
-// static
-BOOL LLPipeline::getRenderSoundBeacons(void*)
-{
-	return sRenderSoundBeacons;
-}
-
-// static
-void LLPipeline::setRenderBeacons(BOOL val)
-{
-	sRenderBeacons = val;
-}
-
-// static
-void LLPipeline::toggleRenderBeacons(void*)
-{
-	sRenderBeacons = !sRenderBeacons;
-}
-
-// static
-BOOL LLPipeline::getRenderBeacons(void*)
-{
-	return sRenderBeacons;
-}
-
-// static
-void LLPipeline::setRenderHighlights(BOOL val)
-{
-	sRenderHighlight = val;
-}
-
-// static
-void LLPipeline::toggleRenderHighlights(void*)
-{
-	sRenderHighlight = !sRenderHighlight;
-}
-
-// static
-BOOL LLPipeline::getRenderHighlights(void*)
-{
-	return sRenderHighlight;
-}
-
-LLViewerObject* LLPipeline::lineSegmentIntersectInWorld(const LLVector3& start, const LLVector3& end,
-														BOOL pick_transparent,												
-														S32* face_hit,
-														LLVector3* intersection,         // return the intersection point
-														LLVector2* tex_coord,            // return the texture coordinates of the intersection point
-														LLVector3* normal,               // return the surface normal at the intersection point
-														LLVector3* bi_normal             // return the surface bi-normal at the intersection point
-	)
-{
-	LLDrawable* drawable = NULL;
-
-	LLVector3 local_end = end;
-
-	LLVector3 position;
-
-	sPickAvatar = FALSE; //LLToolMgr::getInstance()->inBuildMode() ? FALSE : TRUE;
-	
-	for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
-			iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
-	{
-		LLViewerRegion* region = *iter;
-
-		for (U32 j = 0; j < LLViewerRegion::NUM_PARTITIONS; j++)
-		{
-			if ((j == LLViewerRegion::PARTITION_VOLUME) || 
-				(j == LLViewerRegion::PARTITION_BRIDGE) || 
-				(j == LLViewerRegion::PARTITION_TERRAIN) ||
-				(j == LLViewerRegion::PARTITION_TREE) ||
-				(j == LLViewerRegion::PARTITION_GRASS))  // only check these partitions for now
-			{
-				LLSpatialPartition* part = region->getSpatialPartition(j);
-				if (part && hasRenderType(part->mDrawableType))
-				{
-					LLDrawable* hit = part->lineSegmentIntersect(start, local_end, pick_transparent, face_hit, &position, tex_coord, normal, bi_normal);
-					if (hit)
-					{
-						drawable = hit;
-						local_end = position;						
-					}
-				}
-			}
-		}
-	}
-	
-	if (!sPickAvatar)
-	{
-		//save hit info in case we need to restore
-		//due to attachment override
-		LLVector3 local_normal;
-		LLVector3 local_binormal;
-		LLVector2 local_texcoord;
-		S32 local_face_hit = -1;
-
-		if (face_hit)
-		{ 
-			local_face_hit = *face_hit;
-		}
-		if (tex_coord)
-		{
-			local_texcoord = *tex_coord;
-		}
-		if (bi_normal)
-		{
-			local_binormal = *bi_normal;
-		}
-		if (normal)
-		{
-			local_normal = *normal;
-		}
-				
-		const F32 ATTACHMENT_OVERRIDE_DIST = 0.1f;
-
-		//check against avatars
-		sPickAvatar = TRUE;
-		for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
-				iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
-		{
-			LLViewerRegion* region = *iter;
-
-			LLSpatialPartition* part = region->getSpatialPartition(LLViewerRegion::PARTITION_BRIDGE);
-			if (part && hasRenderType(part->mDrawableType))
-			{
-				LLDrawable* hit = part->lineSegmentIntersect(start, local_end, pick_transparent, face_hit, &position, tex_coord, normal, bi_normal);
-				if (hit)
-				{
-					if (!drawable || 
-						!drawable->getVObj()->isAttachment() ||
-						(position-local_end).magVec() > ATTACHMENT_OVERRIDE_DIST)
-					{ //avatar overrides if previously hit drawable is not an attachment or 
-					  //attachment is far enough away from detected intersection
-						drawable = hit;
-						local_end = position;						
-					}
-					else
-					{ //prioritize attachments over avatars
-						position = local_end;
-
-						if (face_hit)
-						{
-							*face_hit = local_face_hit;
-						}
-						if (tex_coord)
-						{
-							*tex_coord = local_texcoord;
-						}
-						if (bi_normal)
-						{
-							*bi_normal = local_binormal;
-						}
-						if (normal)
-						{
-							*normal = local_normal;
-						}
-					}
-				}
-			}
-		}
-	}
-
-	//check all avatar nametags (silly, isn't it?)
-	for (std::vector< LLCharacter* >::iterator iter = LLCharacter::sInstances.begin();
-		iter != LLCharacter::sInstances.end();
-		++iter)
-	{
-		LLVOAvatar* av = (LLVOAvatar*) *iter;
-		if (av->mNameText.notNull()
-			&& av->mNameText->lineSegmentIntersect(start, local_end, position))
-		{
-			drawable = av->mDrawable;
-			local_end = position;
-		}
-	}
-
-	if (intersection)
-	{
-		*intersection = position;
-	}
-
-	return drawable ? drawable->getVObj().get() : NULL;
-}
-
-LLViewerObject* LLPipeline::lineSegmentIntersectInHUD(const LLVector3& start, const LLVector3& end,
-													  BOOL pick_transparent,													
-													  S32* face_hit,
-													  LLVector3* intersection,         // return the intersection point
-													  LLVector2* tex_coord,            // return the texture coordinates of the intersection point
-													  LLVector3* normal,               // return the surface normal at the intersection point
-													  LLVector3* bi_normal             // return the surface bi-normal at the intersection point
-	)
-{
-	LLDrawable* drawable = NULL;
-
-	for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
-			iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
-	{
-		LLViewerRegion* region = *iter;
-
-		BOOL toggle = FALSE;
-		if (!hasRenderType(LLPipeline::RENDER_TYPE_HUD))
-		{
-			toggleRenderType(LLPipeline::RENDER_TYPE_HUD);
-			toggle = TRUE;
-		}
-
-		LLSpatialPartition* part = region->getSpatialPartition(LLViewerRegion::PARTITION_HUD);
-		if (part)
-		{
-			LLDrawable* hit = part->lineSegmentIntersect(start, end, pick_transparent, face_hit, intersection, tex_coord, normal, bi_normal);
-			if (hit)
-			{
-				drawable = hit;
-			}
-		}
-
-		if (toggle)
-		{
-			toggleRenderType(LLPipeline::RENDER_TYPE_HUD);
-		}
-	}
-	return drawable ? drawable->getVObj().get() : NULL;
-}
-
-LLSpatialPartition* LLPipeline::getSpatialPartition(LLViewerObject* vobj)
-{
-	if (vobj)
-	{
-		LLViewerRegion* region = vobj->getRegion();
-		if (region)
-		{
-			return region->getSpatialPartition(vobj->getPartitionType());
-		}
-	}
-	return NULL;
-}
-
-void LLPipeline::resetVertexBuffers(LLDrawable* drawable)
-{
-	if (!drawable || drawable->isDead())
-	{
-		return;
-	}
-
-	for (S32 i = 0; i < drawable->getNumFaces(); i++)
-	{
-		LLFace* facep = drawable->getFace(i);
-		facep->clearVertexBuffer();
-	}
-}
-
-void LLPipeline::resetVertexBuffers()
-{	
-	for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
-			iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
-	{
-		LLViewerRegion* region = *iter;
-		for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
-		{
-			LLSpatialPartition* part = region->getSpatialPartition(i);
-			if (part)
-			{
-				part->resetVertexBuffers();
-			}
-		}
-	}
-
-	resetDrawOrders();
-
-	gSky.resetVertexBuffers();
-
-	if ( LLPathingLib::getInstance() )
-	{
-		LLPathingLib::getInstance()->cleanupVBOManger();
-	}
-	LLVertexBuffer::cleanupClass();
-	
-	//delete all name pool caches
-	LLGLNamePool::cleanupPools();
-
-	if (LLVertexBuffer::sGLCount > 0)
-	{
-		llwarns << "VBO wipe failed." << llendl;
-	}
-
-	llassert(LLVertexBuffer::sGLCount == 0);
-
-	LLVertexBuffer::unbind();	
-	
-	sRenderBump = gSavedSettings.getBOOL("RenderObjectBump");
-	sUseTriStrips = gSavedSettings.getBOOL("RenderUseTriStrips");
-	LLVertexBuffer::sUseStreamDraw = gSavedSettings.getBOOL("RenderUseStreamVBO");
-	LLVertexBuffer::sUseVAO = gSavedSettings.getBOOL("RenderUseVAO");
-	LLVertexBuffer::sPreferStreamDraw = gSavedSettings.getBOOL("RenderPreferStreamDraw");
-	LLVertexBuffer::sEnableVBOs = gSavedSettings.getBOOL("RenderVBOEnable");
-	LLVertexBuffer::sDisableVBOMapping = LLVertexBuffer::sEnableVBOs && gSavedSettings.getBOOL("RenderVBOMappingDisable") ;
-	sBakeSunlight = gSavedSettings.getBOOL("RenderBakeSunlight");
-	sNoAlpha = gSavedSettings.getBOOL("RenderNoAlpha");
-	LLPipeline::sTextureBindTest = gSavedSettings.getBOOL("RenderDebugTextureBind");
-
-	LLVertexBuffer::initClass(LLVertexBuffer::sEnableVBOs, LLVertexBuffer::sDisableVBOMapping);
-}
-
-void LLPipeline::renderObjects(U32 type, U32 mask, BOOL texture, BOOL batch_texture)
-{
-	LLMemType mt_ro(LLMemType::MTYPE_PIPELINE_RENDER_OBJECTS);
-	assertInitialized();
-	gGL.loadMatrix(gGLModelView);
-	gGLLastMatrix = NULL;
-	mSimplePool->pushBatches(type, mask, texture, batch_texture);
-	gGL.loadMatrix(gGLModelView);
-	gGLLastMatrix = NULL;		
-}
-
-void apply_cube_face_rotation(U32 face)
-{
-	switch (face)
-	{
-		case 0: 
-			gGL.rotatef(90.f, 0, 1, 0);
-			gGL.rotatef(180.f, 1, 0, 0);
-		break;
-		case 2: 
-			gGL.rotatef(-90.f, 1, 0, 0);
-		break;
-		case 4:
-			gGL.rotatef(180.f, 0, 1, 0);
-			gGL.rotatef(180.f, 0, 0, 1);
-		break;
-		case 1: 
-			gGL.rotatef(-90.f, 0, 1, 0);
-			gGL.rotatef(180.f, 1, 0, 0);
-		break;
-		case 3:
-			gGL.rotatef(90, 1, 0, 0);
-		break;
-		case 5: 
-			gGL.rotatef(180, 0, 0, 1);
-		break;
-	}
-}
-
-void validate_framebuffer_object()
-{                                                           
-	GLenum status;                                            
-	status = glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT); 
-	switch(status) 
-	{                                          
-		case GL_FRAMEBUFFER_COMPLETE:                       
-			//framebuffer OK, no error.
-			break;
-		case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
-			// frame buffer not OK: probably means unsupported depth buffer format
-			llerrs << "Framebuffer Incomplete Missing Attachment." << llendl;
-			break;
-		case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
-			// frame buffer not OK: probably means unsupported depth buffer format
-			llerrs << "Framebuffer Incomplete Attachment." << llendl;
-			break; 
-		case GL_FRAMEBUFFER_UNSUPPORTED:                    
-			/* choose different formats */                        
-			llerrs << "Framebuffer unsupported." << llendl;
-			break;                                                
-		default:                                                
-			llerrs << "Unknown framebuffer status." << llendl;
-			break;
-	}
-}
-
-void LLPipeline::bindScreenToTexture() 
-{
-	
-}
-
-static LLFastTimer::DeclareTimer FTM_RENDER_BLOOM("Bloom");
-
-void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield)
-{
-	LLMemType mt_ru(LLMemType::MTYPE_PIPELINE_RENDER_BLOOM);
-	if (!(gPipeline.canUseVertexShaders() &&
-		sRenderGlow))
-	{
-		return;
-	}
-
-	LLVertexBuffer::unbind();
-	LLGLState::checkStates();
-	LLGLState::checkTextureChannels();
-
-	assertInitialized();
-
-	if (gUseWireframe)
-	{
-		glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
-	}
-
-	LLVector2 tc1(0,0);
-	LLVector2 tc2((F32) mScreen.getWidth()*2,
-				  (F32) mScreen.getHeight()*2);
-
-	LLFastTimer ftm(FTM_RENDER_BLOOM);
-	gGL.color4f(1,1,1,1);
-	LLGLDepthTest depth(GL_FALSE);
-	LLGLDisable blend(GL_BLEND);
-	LLGLDisable cull(GL_CULL_FACE);
-	
-	enableLightsFullbright(LLColor4(1,1,1,1));
-
-	gGL.matrixMode(LLRender::MM_PROJECTION);
-	gGL.pushMatrix();
-	gGL.loadIdentity();
-	gGL.matrixMode(LLRender::MM_MODELVIEW);
-	gGL.pushMatrix();
-	gGL.loadIdentity();
-
-	LLGLDisable test(GL_ALPHA_TEST);
-
-	gGL.setColorMask(true, true);
-	glClearColor(0,0,0,0);
-		
-	{
-		{
-			LLFastTimer ftm(FTM_RENDER_BLOOM_FBO);
-			mGlow[2].bindTarget();
-			mGlow[2].clear();
-		}
-		
-		gGlowExtractProgram.bind();
-		F32 minLum = llmax((F32) RenderGlowMinLuminance, 0.0f);
-		F32 maxAlpha = RenderGlowMaxExtractAlpha;		
-		F32 warmthAmount = RenderGlowWarmthAmount;	
-		LLVector3 lumWeights = RenderGlowLumWeights;
-		LLVector3 warmthWeights = RenderGlowWarmthWeights;
-
-
-		gGlowExtractProgram.uniform1f(LLShaderMgr::GLOW_MIN_LUMINANCE, minLum);
-		gGlowExtractProgram.uniform1f(LLShaderMgr::GLOW_MAX_EXTRACT_ALPHA, maxAlpha);
-		gGlowExtractProgram.uniform3f(LLShaderMgr::GLOW_LUM_WEIGHTS, lumWeights.mV[0], lumWeights.mV[1], lumWeights.mV[2]);
-		gGlowExtractProgram.uniform3f(LLShaderMgr::GLOW_WARMTH_WEIGHTS, warmthWeights.mV[0], warmthWeights.mV[1], warmthWeights.mV[2]);
-		gGlowExtractProgram.uniform1f(LLShaderMgr::GLOW_WARMTH_AMOUNT, warmthAmount);
-		LLGLEnable blend_on(GL_BLEND);
-		LLGLEnable test(GL_ALPHA_TEST);
-		
-		gGL.setSceneBlendType(LLRender::BT_ADD_WITH_ALPHA);
-		
-		mScreen.bindTexture(0, 0);
-		
-		gGL.color4f(1,1,1,1);
-		gPipeline.enableLightsFullbright(LLColor4(1,1,1,1));
-		gGL.begin(LLRender::TRIANGLE_STRIP);
-		gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
-		gGL.vertex2f(-1,-1);
-		
-		gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
-		gGL.vertex2f(-1,3);
-		
-		gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
-		gGL.vertex2f(3,-1);
-		
-		gGL.end();
-		
-		gGL.getTexUnit(0)->unbind(mScreen.getUsage());
-
-		mGlow[2].flush();
-	}
-
-	tc1.setVec(0,0);
-	tc2.setVec(2,2);
-
-	// power of two between 1 and 1024
-	U32 glowResPow = RenderGlowResolutionPow;
-	const U32 glow_res = llmax(1, 
-		llmin(1024, 1 << glowResPow));
-
-	S32 kernel = RenderGlowIterations*2;
-	F32 delta = RenderGlowWidth / glow_res;
-	// Use half the glow width if we have the res set to less than 9 so that it looks
-	// almost the same in either case.
-	if (glowResPow < 9)
-	{
-		delta *= 0.5f;
-	}
-	F32 strength = RenderGlowStrength;
-
-	gGlowProgram.bind();
-	gGlowProgram.uniform1f(LLShaderMgr::GLOW_STRENGTH, strength);
-
-	for (S32 i = 0; i < kernel; i++)
-	{
-		{
-			LLFastTimer ftm(FTM_RENDER_BLOOM_FBO);
-			mGlow[i%2].bindTarget();
-			mGlow[i%2].clear();
-		}
-			
-		if (i == 0)
-		{
-			gGL.getTexUnit(0)->bind(&mGlow[2]);
-		}
-		else
-		{
-			gGL.getTexUnit(0)->bind(&mGlow[(i-1)%2]);
-		}
-
-		if (i%2 == 0)
-		{
-			gGlowProgram.uniform2f(LLShaderMgr::GLOW_DELTA, delta, 0);
-		}
-		else
-		{
-			gGlowProgram.uniform2f(LLShaderMgr::GLOW_DELTA, 0, delta);
-		}
-
-		gGL.begin(LLRender::TRIANGLE_STRIP);
-		gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
-		gGL.vertex2f(-1,-1);
-		
-		gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
-		gGL.vertex2f(-1,3);
-		
-		gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
-		gGL.vertex2f(3,-1);
-		
-		gGL.end();
-		
-		mGlow[i%2].flush();
-	}
-
-	gGlowProgram.unbind();
-
-	if (LLRenderTarget::sUseFBO)
-	{
-		LLFastTimer ftm(FTM_RENDER_BLOOM_FBO);
-		glBindFramebuffer(GL_FRAMEBUFFER, 0);
-	}
-
-	gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft;
-	gGLViewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom;
-	gGLViewport[2] = gViewerWindow->getWorldViewRectRaw().getWidth();
-	gGLViewport[3] = gViewerWindow->getWorldViewRectRaw().getHeight();
-	glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
-
-	tc2.setVec((F32) mScreen.getWidth(),
-			(F32) mScreen.getHeight());
-
-	gGL.flush();
-	
-	LLVertexBuffer::unbind();
-
-	if (LLPipeline::sRenderDeferred)
-	{
-
-		bool dof_enabled = !LLViewerCamera::getInstance()->cameraUnderWater() &&
-							!LLToolMgr::getInstance()->inBuildMode() &&
-							RenderDepthOfField;
-
-
-		bool multisample = RenderFSAASamples > 1 && mFXAABuffer.isComplete();
-
-		gViewerWindow->setup3DViewport();
-				
-		if (dof_enabled)
-		{
-			LLGLSLShader* shader = &gDeferredPostProgram;
-			LLGLDisable blend(GL_BLEND);
-
-			//depth of field focal plane calculations
-			static F32 current_distance = 16.f;
-			static F32 start_distance = 16.f;
-			static F32 transition_time = 1.f;
-
-			LLVector3 focus_point;
-
-			LLViewerObject* obj = LLViewerMediaFocus::getInstance()->getFocusedObject();
-			if (obj && obj->mDrawable && obj->isSelected())
-			{ //focus on selected media object
-				S32 face_idx = LLViewerMediaFocus::getInstance()->getFocusedFace();
-				if (obj && obj->mDrawable)
-				{
-					LLFace* face = obj->mDrawable->getFace(face_idx);
-					if (face)
-					{
-						focus_point = face->getPositionAgent();
-					}
-				}
-			}
-		
-			if (focus_point.isExactlyZero())
-			{
-				if (LLViewerJoystick::getInstance()->getOverrideCamera())
-				{ //focus on point under cursor
-					focus_point = gDebugRaycastIntersection;
-				}
-				else if (gAgentCamera.cameraMouselook())
-				{ //focus on point under mouselook crosshairs
-					gViewerWindow->cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE,
-													NULL,
-													&focus_point);
-				}
-				else
-				{
-					LLViewerObject* obj = gAgentCamera.getFocusObject();
-					if (obj)
-					{ //focus on alt-zoom target
-						focus_point = LLVector3(gAgentCamera.getFocusGlobal()-gAgent.getRegion()->getOriginGlobal());
-					}
-					else
-					{ //focus on your avatar
-						focus_point = gAgent.getPositionAgent();
-					}
-				}
-			}
-
-			LLVector3 eye = LLViewerCamera::getInstance()->getOrigin();
-			F32 target_distance = 16.f;
-			if (!focus_point.isExactlyZero())
-			{
-				target_distance = LLViewerCamera::getInstance()->getAtAxis() * (focus_point-eye);
-			}
-
-			if (transition_time >= 1.f &&
-				fabsf(current_distance-target_distance)/current_distance > 0.01f)
-			{ //large shift happened, interpolate smoothly to new target distance
-				transition_time = 0.f;
-				start_distance = current_distance;
-			}
-			else if (transition_time < 1.f)
-			{ //currently in a transition, continue interpolating
-				transition_time += 1.f/CameraFocusTransitionTime*gFrameIntervalSeconds;
-				transition_time = llmin(transition_time, 1.f);
-
-				F32 t = cosf(transition_time*F_PI+F_PI)*0.5f+0.5f;
-				current_distance = start_distance + (target_distance-start_distance)*t;
-			}
-			else
-			{ //small or no change, just snap to target distance
-				current_distance = target_distance;
-			}
-
-			//convert to mm
-			F32 subject_distance = current_distance*1000.f;
-			F32 fnumber = CameraFNumber;
-			F32 default_focal_length = CameraFocalLength;
-
-			F32 fov = LLViewerCamera::getInstance()->getView();
-		
-			const F32 default_fov = CameraFieldOfView * F_PI/180.f;
-			//const F32 default_aspect_ratio = gSavedSettings.getF32("CameraAspectRatio");
-		
-			//F32 aspect_ratio = (F32) mScreen.getWidth()/(F32)mScreen.getHeight();
-		
-			F32 dv = 2.f*default_focal_length * tanf(default_fov/2.f);
-			//F32 dh = 2.f*default_focal_length * tanf(default_fov*default_aspect_ratio/2.f);
-
-			F32 focal_length = dv/(2*tanf(fov/2.f));
-		 
-			//F32 tan_pixel_angle = tanf(LLDrawable::sCurPixelAngle);
-	
-			// from wikipedia -- c = |s2-s1|/s2 * f^2/(N(S1-f))
-			// where	 N = fnumber
-			//			 s2 = dot distance
-			//			 s1 = subject distance
-			//			 f = focal length
-			//	
-
-			F32 blur_constant = focal_length*focal_length/(fnumber*(subject_distance-focal_length));
-			blur_constant /= 1000.f; //convert to meters for shader
-			F32 magnification = focal_length/(subject_distance-focal_length);
-
-			{ //build diffuse+bloom+CoF
-				mDeferredLight.bindTarget();
-				shader = &gDeferredCoFProgram;
-
-				bindDeferredShader(*shader);
-
-				S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mScreen.getUsage());
-				if (channel > -1)
-				{
-					mScreen.bindTexture(0, channel);
-				}
-
-				shader->uniform1f(LLShaderMgr::DOF_FOCAL_DISTANCE, -subject_distance/1000.f);
-				shader->uniform1f(LLShaderMgr::DOF_BLUR_CONSTANT, blur_constant);
-				shader->uniform1f(LLShaderMgr::DOF_TAN_PIXEL_ANGLE, tanf(1.f/LLDrawable::sCurPixelAngle));
-				shader->uniform1f(LLShaderMgr::DOF_MAGNIFICATION, magnification);
-				shader->uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF);
-				shader->uniform1f(LLShaderMgr::DOF_RES_SCALE, CameraDoFResScale);
-
-				gGL.begin(LLRender::TRIANGLE_STRIP);
-				gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
-				gGL.vertex2f(-1,-1);
-		
-				gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
-				gGL.vertex2f(-1,3);
-		
-				gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
-				gGL.vertex2f(3,-1);
-		
-				gGL.end();
-
-				unbindDeferredShader(*shader);
-				mDeferredLight.flush();
-			}
-
-			{ //perform DoF sampling at half-res (preserve alpha channel)
-				mScreen.bindTarget();
-				glViewport(0,0,(GLsizei) (mScreen.getWidth()*CameraDoFResScale), (GLsizei) (mScreen.getHeight()*CameraDoFResScale));
-				gGL.setColorMask(true, false);
-
-				shader = &gDeferredPostProgram;
-				bindDeferredShader(*shader);
-				S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mDeferredLight.getUsage());
-				if (channel > -1)
-				{
-					mDeferredLight.bindTexture(0, channel);
-				}
-
-				shader->uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF);
-				shader->uniform1f(LLShaderMgr::DOF_RES_SCALE, CameraDoFResScale);
-
-				gGL.begin(LLRender::TRIANGLE_STRIP);
-				gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
-				gGL.vertex2f(-1,-1);
-		
-				gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
-				gGL.vertex2f(-1,3);
-		
-				gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
-				gGL.vertex2f(3,-1);
-		
-				gGL.end();
-
-				unbindDeferredShader(*shader);
-				mScreen.flush();
-				gGL.setColorMask(true, true);
-			}
-	
-			{ //combine result based on alpha
-				if (multisample)
-				{
-					mDeferredLight.bindTarget();
-					glViewport(0, 0, mDeferredScreen.getWidth(), mDeferredScreen.getHeight());
-				}
-				else
-				{
-					gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft;
-					gGLViewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom;
-					gGLViewport[2] = gViewerWindow->getWorldViewRectRaw().getWidth();
-					gGLViewport[3] = gViewerWindow->getWorldViewRectRaw().getHeight();
-					glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
-				}
-
-				shader = &gDeferredDoFCombineProgram;
-				bindDeferredShader(*shader);
-				
-				S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mScreen.getUsage());
-				if (channel > -1)
-				{
-					mScreen.bindTexture(0, channel);
-					gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
-				}
-
-				shader->uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF);
-				shader->uniform1f(LLShaderMgr::DOF_RES_SCALE, CameraDoFResScale);
-
-				gGL.begin(LLRender::TRIANGLE_STRIP);
-				gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
-				gGL.vertex2f(-1,-1);
-		
-				gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
-				gGL.vertex2f(-1,3);
-		
-				gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
-				gGL.vertex2f(3,-1);
-		
-				gGL.end();
-
-				unbindDeferredShader(*shader);
-
-				if (multisample)
-				{
-					mDeferredLight.flush();
-				}
-			}
-		}
-		else
-		{
-			if (multisample)
-			{
-				mDeferredLight.bindTarget();
-			}
-			LLGLSLShader* shader = &gDeferredPostNoDoFProgram;
-			
-			bindDeferredShader(*shader);
-							
-			S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mScreen.getUsage());
-			if (channel > -1)
-			{
-				mScreen.bindTexture(0, channel);
-			}
-
-			gGL.begin(LLRender::TRIANGLE_STRIP);
-			gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
-			gGL.vertex2f(-1,-1);
-		
-			gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
-			gGL.vertex2f(-1,3);
-		
-			gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
-			gGL.vertex2f(3,-1);
-		
-			gGL.end();
-
-			unbindDeferredShader(*shader);
-
-			if (multisample)
-			{
-				mDeferredLight.flush();
-			}
-		}
-
-		if (multisample)
-		{
-			//bake out texture2D with RGBL for FXAA shader
-			mFXAABuffer.bindTarget();
-			
-			S32 width = mScreen.getWidth();
-			S32 height = mScreen.getHeight();
-			glViewport(0, 0, width, height);
-
-			LLGLSLShader* shader = &gGlowCombineFXAAProgram;
-
-			shader->bind();
-			shader->uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, width, height);
-
-			S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mDeferredLight.getUsage());
-			if (channel > -1)
-			{
-				mDeferredLight.bindTexture(0, channel);
-			}
-						
-			gGL.begin(LLRender::TRIANGLE_STRIP);
-			gGL.vertex2f(-1,-1);
-			gGL.vertex2f(-1,3);
-			gGL.vertex2f(3,-1);
-			gGL.end();
-
-			gGL.flush();
-
-			shader->disableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mDeferredLight.getUsage());
-			shader->unbind();
-			
-			mFXAABuffer.flush();
-
-			shader = &gFXAAProgram;
-			shader->bind();
-
-			channel = shader->enableTexture(LLShaderMgr::DIFFUSE_MAP, mFXAABuffer.getUsage());
-			if (channel > -1)
-			{
-				mFXAABuffer.bindTexture(0, channel);
-				gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
-			}
-						
-			gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft;
-			gGLViewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom;
-			gGLViewport[2] = gViewerWindow->getWorldViewRectRaw().getWidth();
-			gGLViewport[3] = gViewerWindow->getWorldViewRectRaw().getHeight();
-			glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
-
-			F32 scale_x = (F32) width/mFXAABuffer.getWidth();
-			F32 scale_y = (F32) height/mFXAABuffer.getHeight();
-			shader->uniform2f(LLShaderMgr::FXAA_TC_SCALE, scale_x, scale_y);
-			shader->uniform2f(LLShaderMgr::FXAA_RCP_SCREEN_RES, 1.f/width*scale_x, 1.f/height*scale_y);
-			shader->uniform4f(LLShaderMgr::FXAA_RCP_FRAME_OPT, -0.5f/width*scale_x, -0.5f/height*scale_y, 0.5f/width*scale_x, 0.5f/height*scale_y);
-			shader->uniform4f(LLShaderMgr::FXAA_RCP_FRAME_OPT2, -2.f/width*scale_x, -2.f/height*scale_y, 2.f/width*scale_x, 2.f/height*scale_y);
-			
-			gGL.begin(LLRender::TRIANGLE_STRIP);
-			gGL.vertex2f(-1,-1);
-			gGL.vertex2f(-1,3);
-			gGL.vertex2f(3,-1);
-			gGL.end();
-
-			gGL.flush();
-			shader->unbind();
-		}
-	}
-	else
-	{
-		U32 mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_TEXCOORD1;
-		LLPointer<LLVertexBuffer> buff = new LLVertexBuffer(mask, 0);
-		buff->allocateBuffer(3,0,TRUE);
-
-		LLStrider<LLVector3> v;
-		LLStrider<LLVector2> uv1;
-		LLStrider<LLVector2> uv2;
-
-		buff->getVertexStrider(v);
-		buff->getTexCoord0Strider(uv1);
-		buff->getTexCoord1Strider(uv2);
-		
-		uv1[0] = LLVector2(0, 0);
-		uv1[1] = LLVector2(0, 2);
-		uv1[2] = LLVector2(2, 0);
-		
-		uv2[0] = LLVector2(0, 0);
-		uv2[1] = LLVector2(0, tc2.mV[1]*2.f);
-		uv2[2] = LLVector2(tc2.mV[0]*2.f, 0);
-		
-		v[0] = LLVector3(-1,-1,0);
-		v[1] = LLVector3(-1,3,0);
-		v[2] = LLVector3(3,-1,0);
-				
-		buff->flush();
-
-		LLGLDisable blend(GL_BLEND);
-
-		if (LLGLSLShader::sNoFixedFunction)
-		{
-			gGlowCombineProgram.bind();
-		}
-		else
-		{
-			//tex unit 0
-			gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_COLOR);
-			//tex unit 1
-			gGL.getTexUnit(1)->setTextureColorBlend(LLTexUnit::TBO_ADD, LLTexUnit::TBS_TEX_COLOR, LLTexUnit::TBS_PREV_COLOR);
-		}
-		
-		gGL.getTexUnit(0)->bind(&mGlow[1]);
-		gGL.getTexUnit(1)->bind(&mScreen);
-		
-		LLGLEnable multisample(RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0);
-		
-		buff->setBuffer(mask);
-		buff->drawArrays(LLRender::TRIANGLE_STRIP, 0, 3);
-		
-		if (LLGLSLShader::sNoFixedFunction)
-		{
-			gGlowCombineProgram.unbind();
-		}
-		else
-		{
-			gGL.getTexUnit(1)->disable();
-			gGL.getTexUnit(1)->setTextureBlendType(LLTexUnit::TB_MULT);
-
-			gGL.getTexUnit(0)->activate();
-			gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
-		}
-		
-	}
-
-	gGL.setSceneBlendType(LLRender::BT_ALPHA);
-
-	if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PHYSICS_SHAPES))
-	{
-		if (LLGLSLShader::sNoFixedFunction)
-		{
-			gSplatTextureRectProgram.bind();
-		}
-
-		gGL.setColorMask(true, false);
-
-		LLVector2 tc1(0,0);
-		LLVector2 tc2((F32) gViewerWindow->getWorldViewWidthRaw()*2,
-				  (F32) gViewerWindow->getWorldViewHeightRaw()*2);
-
-		LLGLEnable blend(GL_BLEND);
-		gGL.color4f(1,1,1,0.75f);
-
-		gGL.getTexUnit(0)->bind(&mPhysicsDisplay);
-
-		gGL.begin(LLRender::TRIANGLES);
-		gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
-		gGL.vertex2f(-1,-1);
-		
-		gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
-		gGL.vertex2f(-1,3);
-		
-		gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
-		gGL.vertex2f(3,-1);
-		
-		gGL.end();
-		gGL.flush();
-
-		if (LLGLSLShader::sNoFixedFunction)
-		{
-			gSplatTextureRectProgram.unbind();
-		}
-	}
-
-	
-	if (LLRenderTarget::sUseFBO)
-	{ //copy depth buffer from mScreen to framebuffer
-		LLRenderTarget::copyContentsToFramebuffer(mScreen, 0, 0, mScreen.getWidth(), mScreen.getHeight(), 
-			0, 0, mScreen.getWidth(), mScreen.getHeight(), GL_DEPTH_BUFFER_BIT, GL_NEAREST);
-	}
-	
-
-	gGL.matrixMode(LLRender::MM_PROJECTION);
-	gGL.popMatrix();
-	gGL.matrixMode(LLRender::MM_MODELVIEW);
-	gGL.popMatrix();
-
-	LLVertexBuffer::unbind();
-
-	LLGLState::checkStates();
-	LLGLState::checkTextureChannels();
-
-}
-
-static LLFastTimer::DeclareTimer FTM_BIND_DEFERRED("Bind Deferred");
-
-void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, U32 noise_map)
-{
-	LLFastTimer t(FTM_BIND_DEFERRED);
-
-	if (noise_map == 0xFFFFFFFF)
-	{
-		noise_map = mNoiseMap;
-	}
-
-	shader.bind();
-	S32 channel = 0;
-	channel = shader.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mDeferredScreen.getUsage());
-	if (channel > -1)
-	{
-		mDeferredScreen.bindTexture(0,channel);
-		gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
-	}
-
-	channel = shader.enableTexture(LLShaderMgr::DEFERRED_SPECULAR, mDeferredScreen.getUsage());
-	if (channel > -1)
-	{
-		mDeferredScreen.bindTexture(1, channel);
-		gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
-	}
-
-	channel = shader.enableTexture(LLShaderMgr::DEFERRED_NORMAL, mDeferredScreen.getUsage());
-	if (channel > -1)
-	{
-		mDeferredScreen.bindTexture(2, channel);
-		gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
-	}
-
-	channel = shader.enableTexture(LLShaderMgr::DEFERRED_DEPTH, mDeferredDepth.getUsage());
-	if (channel > -1)
-	{
-		gGL.getTexUnit(channel)->bind(&mDeferredDepth, TRUE);
-		stop_glerror();
-		
-		//glTexParameteri(LLTexUnit::getInternalType(mDeferredDepth.getUsage()), GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE);		
-		//glTexParameteri(LLTexUnit::getInternalType(mDeferredDepth.getUsage()), GL_DEPTH_TEXTURE_MODE_ARB, GL_ALPHA);		
-
-		stop_glerror();
-
-		glh::matrix4f projection = glh_get_current_projection();
-		glh::matrix4f inv_proj = projection.inverse();
-		
-		shader.uniformMatrix4fv(LLShaderMgr::INVERSE_PROJECTION_MATRIX, 1, FALSE, inv_proj.m);
-		shader.uniform4f(LLShaderMgr::VIEWPORT, (F32) gGLViewport[0],
-									(F32) gGLViewport[1],
-									(F32) gGLViewport[2],
-									(F32) gGLViewport[3]);
-	}
-
-	channel = shader.enableTexture(LLShaderMgr::DEFERRED_NOISE);
-	if (channel > -1)
-	{
-		gGL.getTexUnit(channel)->bindManual(LLTexUnit::TT_TEXTURE, noise_map);
-		gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
-	}
-
-	channel = shader.enableTexture(LLShaderMgr::DEFERRED_LIGHTFUNC);
-	if (channel > -1)
-	{
-		gGL.getTexUnit(channel)->bindManual(LLTexUnit::TT_TEXTURE, mLightFunc);
-	}
-
-	stop_glerror();
-
-	channel = shader.enableTexture(LLShaderMgr::DEFERRED_LIGHT, mDeferredLight.getUsage());
-	if (channel > -1)
-	{
-		if (light_index > 0)
-		{
-			mScreen.bindTexture(0, channel);
-		}
-		else
-		{
-			mDeferredLight.bindTexture(0, channel);
-		}
-		gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
-	}
-
-	channel = shader.enableTexture(LLShaderMgr::DEFERRED_BLOOM);
-	if (channel > -1)
-	{
-		mGlow[1].bindTexture(0, channel);
-	}
-
-	stop_glerror();
-
-	for (U32 i = 0; i < 4; i++)
-	{
-		channel = shader.enableTexture(LLShaderMgr::DEFERRED_SHADOW0+i, LLTexUnit::TT_RECT_TEXTURE);
-		stop_glerror();
-		if (channel > -1)
-		{
-			stop_glerror();
-			gGL.getTexUnit(channel)->bind(&mShadow[i], TRUE);
-			gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
-			gGL.getTexUnit(channel)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
-			stop_glerror();
-			
-			glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);
-			glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
-			stop_glerror();
-		}
-	}
-
-	for (U32 i = 4; i < 6; i++)
-	{
-		channel = shader.enableTexture(LLShaderMgr::DEFERRED_SHADOW0+i);
-		stop_glerror();
-		if (channel > -1)
-		{
-			stop_glerror();
-			gGL.getTexUnit(channel)->bind(&mShadow[i], TRUE);
-			gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
-			gGL.getTexUnit(channel)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
-			stop_glerror();
-			
-			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);
-			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
-			stop_glerror();
-		}
-	}
-
-	stop_glerror();
-
-	F32 mat[16*6];
-	for (U32 i = 0; i < 16; i++)
-	{
-		mat[i] = mSunShadowMatrix[0].m[i];
-		mat[i+16] = mSunShadowMatrix[1].m[i];
-		mat[i+32] = mSunShadowMatrix[2].m[i];
-		mat[i+48] = mSunShadowMatrix[3].m[i];
-		mat[i+64] = mSunShadowMatrix[4].m[i];
-		mat[i+80] = mSunShadowMatrix[5].m[i];
-	}
-
-	shader.uniformMatrix4fv(LLShaderMgr::DEFERRED_SHADOW_MATRIX, 6, FALSE, mat);
-
-	stop_glerror();
-
-	channel = shader.enableTexture(LLShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP);
-	if (channel > -1)
-	{
-		LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL;
-		if (cube_map)
-		{
-			cube_map->enable(channel);
-			cube_map->bind();
-			F32* m = gGLModelView;
-						
-			F32 mat[] = { m[0], m[1], m[2],
-						  m[4], m[5], m[6],
-						  m[8], m[9], m[10] };
-		
-			shader.uniformMatrix3fv(LLShaderMgr::DEFERRED_ENV_MAT, 1, TRUE, mat);
-		}
-	}
-
-	shader.uniform4fv(LLShaderMgr::DEFERRED_SHADOW_CLIP, 1, mSunClipPlanes.mV);
-	shader.uniform1f(LLShaderMgr::DEFERRED_SUN_WASH, RenderDeferredSunWash);
-	shader.uniform1f(LLShaderMgr::DEFERRED_SHADOW_NOISE, RenderShadowNoise);
-	shader.uniform1f(LLShaderMgr::DEFERRED_BLUR_SIZE, RenderShadowBlurSize);
-
-	shader.uniform1f(LLShaderMgr::DEFERRED_SSAO_RADIUS, RenderSSAOScale);
-	shader.uniform1f(LLShaderMgr::DEFERRED_SSAO_MAX_RADIUS, RenderSSAOMaxScale);
-
-	F32 ssao_factor = RenderSSAOFactor;
-	shader.uniform1f(LLShaderMgr::DEFERRED_SSAO_FACTOR, ssao_factor);
-	shader.uniform1f(LLShaderMgr::DEFERRED_SSAO_FACTOR_INV, 1.0/ssao_factor);
-
-	LLVector3 ssao_effect = RenderSSAOEffect;
-	F32 matrix_diag = (ssao_effect[0] + 2.0*ssao_effect[1])/3.0;
-	F32 matrix_nondiag = (ssao_effect[0] - ssao_effect[1])/3.0;
-	// This matrix scales (proj of color onto <1/rt(3),1/rt(3),1/rt(3)>) by
-	// value factor, and scales remainder by saturation factor
-	F32 ssao_effect_mat[] = {	matrix_diag, matrix_nondiag, matrix_nondiag,
-								matrix_nondiag, matrix_diag, matrix_nondiag,
-								matrix_nondiag, matrix_nondiag, matrix_diag};
-	shader.uniformMatrix3fv(LLShaderMgr::DEFERRED_SSAO_EFFECT_MAT, 1, GL_FALSE, ssao_effect_mat);
-
-	F32 shadow_offset_error = 1.f + RenderShadowOffsetError * fabsf(LLViewerCamera::getInstance()->getOrigin().mV[2]);
-	F32 shadow_bias_error = 1.f + RenderShadowBiasError * fabsf(LLViewerCamera::getInstance()->getOrigin().mV[2]);
-
-	shader.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, mDeferredScreen.getWidth(), mDeferredScreen.getHeight());
-	shader.uniform1f(LLShaderMgr::DEFERRED_NEAR_CLIP, LLViewerCamera::getInstance()->getNear()*2.f);
-	shader.uniform1f (LLShaderMgr::DEFERRED_SHADOW_OFFSET, RenderShadowOffset*shadow_offset_error);
-	shader.uniform1f(LLShaderMgr::DEFERRED_SHADOW_BIAS, RenderShadowBias*shadow_bias_error);
-	shader.uniform1f(LLShaderMgr::DEFERRED_SPOT_SHADOW_OFFSET, RenderSpotShadowOffset);
-	shader.uniform1f(LLShaderMgr::DEFERRED_SPOT_SHADOW_BIAS, RenderSpotShadowBias);	
-
-	shader.uniform3fv(LLShaderMgr::DEFERRED_SUN_DIR, 1, mTransformedSunDir.mV);
-	shader.uniform2f(LLShaderMgr::DEFERRED_SHADOW_RES, mShadow[0].getWidth(), mShadow[0].getHeight());
-	shader.uniform2f(LLShaderMgr::DEFERRED_PROJ_SHADOW_RES, mShadow[4].getWidth(), mShadow[4].getHeight());
-	shader.uniform1f(LLShaderMgr::DEFERRED_DEPTH_CUTOFF, RenderEdgeDepthCutoff);
-	shader.uniform1f(LLShaderMgr::DEFERRED_NORM_CUTOFF, RenderEdgeNormCutoff);
-	
-
-	if (shader.getUniformLocation("norm_mat") >= 0)
-	{
-		glh::matrix4f norm_mat = glh_get_current_modelview().inverse().transpose();
-		shader.uniformMatrix4fv("norm_mat", 1, FALSE, norm_mat.m);
-	}
-}
-
-static LLFastTimer::DeclareTimer FTM_GI_TRACE("Trace");
-static LLFastTimer::DeclareTimer FTM_GI_GATHER("Gather");
-static LLFastTimer::DeclareTimer FTM_SUN_SHADOW("Shadow Map");
-static LLFastTimer::DeclareTimer FTM_SOFTEN_SHADOW("Shadow Soften");
-static LLFastTimer::DeclareTimer FTM_EDGE_DETECTION("Find Edges");
-static LLFastTimer::DeclareTimer FTM_LOCAL_LIGHTS("Local Lights");
-static LLFastTimer::DeclareTimer FTM_ATMOSPHERICS("Atmospherics");
-static LLFastTimer::DeclareTimer FTM_FULLSCREEN_LIGHTS("Fullscreen Lights");
-static LLFastTimer::DeclareTimer FTM_PROJECTORS("Projectors");
-static LLFastTimer::DeclareTimer FTM_POST("Post");
-
-
-void LLPipeline::renderDeferredLighting()
-{
-	if (!sCull)
-	{
-		return;
-	}
-
-	{
-		LLFastTimer ftm(FTM_RENDER_DEFERRED);
-
-		LLViewerCamera* camera = LLViewerCamera::getInstance();
-		{
-			LLGLDepthTest depth(GL_TRUE);
-			mDeferredDepth.copyContents(mDeferredScreen, 0, 0, mDeferredScreen.getWidth(), mDeferredScreen.getHeight(),
-							0, 0, mDeferredDepth.getWidth(), mDeferredDepth.getHeight(), GL_DEPTH_BUFFER_BIT, GL_NEAREST);	
-		}
-
-		LLGLEnable multisample(RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0);
-
-		if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD))
-		{
-			gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD);
-		}
-
-		//ati doesn't seem to love actually using the stencil buffer on FBO's
-		LLGLDisable stencil(GL_STENCIL_TEST);
-		//glStencilFunc(GL_EQUAL, 1, 0xFFFFFFFF);
-		//glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
-
-		gGL.setColorMask(true, true);
-		
-		//draw a cube around every light
-		LLVertexBuffer::unbind();
-
-		LLGLEnable cull(GL_CULL_FACE);
-		LLGLEnable blend(GL_BLEND);
-
-		glh::matrix4f mat = glh_copy_matrix(gGLModelView);
-
-		LLStrider<LLVector3> vert; 
-		mDeferredVB->getVertexStrider(vert);
-		LLStrider<LLVector2> tc0;
-		LLStrider<LLVector2> tc1;
-		mDeferredVB->getTexCoord0Strider(tc0);
-		mDeferredVB->getTexCoord1Strider(tc1);
-
-		vert[0].set(-1,1,0);
-		vert[1].set(-1,-3,0);
-		vert[2].set(3,1,0);
-		
-		{
-			setupHWLights(NULL); //to set mSunDir;
-			LLVector4 dir(mSunDir, 0.f);
-			glh::vec4f tc(dir.mV);
-			mat.mult_matrix_vec(tc);
-			mTransformedSunDir.set(tc.v);
-		}
-
-		gGL.pushMatrix();
-		gGL.loadIdentity();
-		gGL.matrixMode(LLRender::MM_PROJECTION);
-		gGL.pushMatrix();
-		gGL.loadIdentity();
-
-		if (RenderDeferredSSAO || RenderShadowDetail > 0)
-		{
-			mDeferredLight.bindTarget();
-			{ //paint shadow/SSAO light map (direct lighting lightmap)
-				LLFastTimer ftm(FTM_SUN_SHADOW);
-				bindDeferredShader(gDeferredSunProgram, 0);
-				mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
-				glClearColor(1,1,1,1);
-				mDeferredLight.clear(GL_COLOR_BUFFER_BIT);
-				glClearColor(0,0,0,0);
-
-				glh::matrix4f inv_trans = glh_get_current_modelview().inverse().transpose();
-
-				const U32 slice = 32;
-				F32 offset[slice*3];
-				for (U32 i = 0; i < 4; i++)
-				{
-					for (U32 j = 0; j < 8; j++)
-					{
-						glh::vec3f v;
-						v.set_value(sinf(6.284f/8*j), cosf(6.284f/8*j), -(F32) i);
-						v.normalize();
-						inv_trans.mult_matrix_vec(v);
-						v.normalize();
-						offset[(i*8+j)*3+0] = v.v[0];
-						offset[(i*8+j)*3+1] = v.v[2];
-						offset[(i*8+j)*3+2] = v.v[1];
-					}
-				}
-
-				gDeferredSunProgram.uniform3fv("offset", slice, offset);
-				gDeferredSunProgram.uniform2f("screenRes", mDeferredLight.getWidth(), mDeferredLight.getHeight());
-				
-				{
-					LLGLDisable blend(GL_BLEND);
-					LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS);
-					stop_glerror();
-					mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
-					stop_glerror();
-				}
-				
-				unbindDeferredShader(gDeferredSunProgram);
-			}
-			mDeferredLight.flush();
-		}
-		
-		if (RenderDeferredSSAO)
-		{ //soften direct lighting lightmap
-			LLFastTimer ftm(FTM_SOFTEN_SHADOW);
-			//blur lightmap
-			mScreen.bindTarget();
-			glClearColor(1,1,1,1);
-			mScreen.clear(GL_COLOR_BUFFER_BIT);
-			glClearColor(0,0,0,0);
-			
-			bindDeferredShader(gDeferredBlurLightProgram);
-			mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
-			LLVector3 go = RenderShadowGaussian;
-			const U32 kern_length = 4;
-			F32 blur_size = RenderShadowBlurSize;
-			F32 dist_factor = RenderShadowBlurDistFactor;
-
-			// sample symmetrically with the middle sample falling exactly on 0.0
-			F32 x = 0.f;
-
-			LLVector3 gauss[32]; // xweight, yweight, offset
-
-			for (U32 i = 0; i < kern_length; i++)
-			{
-				gauss[i].mV[0] = llgaussian(x, go.mV[0]);
-				gauss[i].mV[1] = llgaussian(x, go.mV[1]);
-				gauss[i].mV[2] = x;
-				x += 1.f;
-			}
-
-			gDeferredBlurLightProgram.uniform2f("delta", 1.f, 0.f);
-			gDeferredBlurLightProgram.uniform1f("dist_factor", dist_factor);
-			gDeferredBlurLightProgram.uniform3fv("kern", kern_length, gauss[0].mV);
-			gDeferredBlurLightProgram.uniform1f("kern_scale", blur_size * (kern_length/2.f - 0.5f));
-		
-			{
-				LLGLDisable blend(GL_BLEND);
-				LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS);
-				stop_glerror();
-				mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
-				stop_glerror();
-			}
-			
-			mScreen.flush();
-			unbindDeferredShader(gDeferredBlurLightProgram);
-
-			bindDeferredShader(gDeferredBlurLightProgram, 1);
-			mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
-			mDeferredLight.bindTarget();
-
-			gDeferredBlurLightProgram.uniform2f("delta", 0.f, 1.f);
-
-			{
-				LLGLDisable blend(GL_BLEND);
-				LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS);
-				stop_glerror();
-				mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
-				stop_glerror();
-			}
-			mDeferredLight.flush();
-			unbindDeferredShader(gDeferredBlurLightProgram);
-		}
-
-		stop_glerror();
-		gGL.popMatrix();
-		stop_glerror();
-		gGL.matrixMode(LLRender::MM_MODELVIEW);
-		stop_glerror();
-		gGL.popMatrix();
-		stop_glerror();
-
-		//copy depth and stencil from deferred screen
-		//mScreen.copyContents(mDeferredScreen, 0, 0, mDeferredScreen.getWidth(), mDeferredScreen.getHeight(),
-		//					0, 0, mScreen.getWidth(), mScreen.getHeight(), GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
-
-		mScreen.bindTarget();
-		// clear color buffer here - zeroing alpha (glow) is important or it will accumulate against sky
-		glClearColor(0,0,0,0);
-		mScreen.clear(GL_COLOR_BUFFER_BIT);
-		
-		if (RenderDeferredAtmospheric)
-		{ //apply sunlight contribution 
-			LLFastTimer ftm(FTM_ATMOSPHERICS);
-			bindDeferredShader(gDeferredSoftenProgram);	
-			{
-				LLGLDepthTest depth(GL_FALSE);
-				LLGLDisable blend(GL_BLEND);
-				LLGLDisable test(GL_ALPHA_TEST);
-
-				//full screen blit
-				gGL.pushMatrix();
-				gGL.loadIdentity();
-				gGL.matrixMode(LLRender::MM_PROJECTION);
-				gGL.pushMatrix();
-				gGL.loadIdentity();
-
-				mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
-				
-				mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
-
-				gGL.popMatrix();
-				gGL.matrixMode(LLRender::MM_MODELVIEW);
-				gGL.popMatrix();
-			}
-
-			unbindDeferredShader(gDeferredSoftenProgram);
-		}
-
-		{ //render non-deferred geometry (fullbright, alpha, etc)
-			LLGLDisable blend(GL_BLEND);
-			LLGLDisable stencil(GL_STENCIL_TEST);
-			gGL.setSceneBlendType(LLRender::BT_ALPHA);
-
-			gPipeline.pushRenderTypeMask();
-			
-			gPipeline.andRenderTypeMask(LLPipeline::RENDER_TYPE_SKY,
-										LLPipeline::RENDER_TYPE_CLOUDS,
-										LLPipeline::RENDER_TYPE_WL_SKY,
-										LLPipeline::END_RENDER_TYPES);
-								
-			
-			renderGeomPostDeferred(*LLViewerCamera::getInstance());
-			gPipeline.popRenderTypeMask();
-		}
-
-		BOOL render_local = RenderLocalLights;
-				
-		if (render_local)
-		{
-			gGL.setSceneBlendType(LLRender::BT_ADD);
-			std::list<LLVector4> fullscreen_lights;
-			LLDrawable::drawable_list_t spot_lights;
-			LLDrawable::drawable_list_t fullscreen_spot_lights;
-
-			for (U32 i = 0; i < 2; i++)
-			{
-				mTargetShadowSpotLight[i] = NULL;
-			}
-
-			std::list<LLVector4> light_colors;
-
-			LLVertexBuffer::unbind();
-			LLVector4a* v = (LLVector4a*) vert.get();
-
-			{
-				bindDeferredShader(gDeferredLightProgram);
-				mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
-
-				LLGLDepthTest depth(GL_TRUE, GL_FALSE);
-				for (LLDrawable::drawable_set_t::iterator iter = mLights.begin(); iter != mLights.end(); ++iter)
-				{
-					LLDrawable* drawablep = *iter;
-					
-					LLVOVolume* volume = drawablep->getVOVolume();
-					if (!volume)
-					{
-						continue;
-					}
-
-					if (volume->isAttachment())
-					{
-						if (!sRenderAttachedLights)
-						{
-							continue;
-						}
-					}
-
-
-					LLVector4a center;
-					center.load3(drawablep->getPositionAgent().mV);
-					const F32* c = center.getF32ptr();
-					F32 s = volume->getLightRadius()*1.5f;
-
-					LLColor3 col = volume->getLightColor();
-
-					if (col.magVecSquared() < 0.001f)
-					{
-						continue;
-					}
-
-					if (s <= 0.001f)
-					{
-						continue;
-					}
-
-					LLVector4a sa;
-					sa.splat(s);
-					if (camera->AABBInFrustumNoFarClip(center, sa) == 0)
-					{
-						continue;
-					}
-
-					sVisibleLightCount++;
-
-					glh::vec3f tc(c);
-					mat.mult_matrix_vec(tc);
-					
-					//vertex positions are encoded so the 3 bits of their vertex index 
-					//correspond to their axis facing, with bit position 3,2,1 matching
-					//axis facing x,y,z, bit set meaning positive facing, bit clear 
-					//meaning negative facing
-					mDeferredVB->getVertexStrider(vert);
-					v[0].set(c[0]-s,c[1]-s,c[2]-s);  // 0 - 0000 
-					v[1].set(c[0]-s,c[1]-s,c[2]+s);  // 1 - 0001
-					v[2].set(c[0]-s,c[1]+s,c[2]-s);  // 2 - 0010
-					v[3].set(c[0]-s,c[1]+s,c[2]+s);  // 3 - 0011
-																									   
-					v[4].set(c[0]+s,c[1]-s,c[2]-s); // 4 - 0100
-					v[5].set(c[0]+s,c[1]-s,c[2]+s); // 5 - 0101
-					v[6].set(c[0]+s,c[1]+s,c[2]-s); // 6 - 0110
-					v[7].set(c[0]+s,c[1]+s,c[2]+s); // 7 - 0111
-
-					if (camera->getOrigin().mV[0] > c[0] + s + 0.2f ||
-						camera->getOrigin().mV[0] < c[0] - s - 0.2f ||
-						camera->getOrigin().mV[1] > c[1] + s + 0.2f ||
-						camera->getOrigin().mV[1] < c[1] - s - 0.2f ||
-						camera->getOrigin().mV[2] > c[2] + s + 0.2f ||
-						camera->getOrigin().mV[2] < c[2] - s - 0.2f)
-					{ //draw box if camera is outside box
-						if (render_local)
-						{
-							if (volume->isLightSpotlight())
-							{
-								drawablep->getVOVolume()->updateSpotLightPriority();
-								spot_lights.push_back(drawablep);
-								continue;
-							}
-							
-							LLFastTimer ftm(FTM_LOCAL_LIGHTS);
-							//glTexCoord4f(tc.v[0], tc.v[1], tc.v[2], s*s);
-							gDeferredLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, tc.v);
-							gDeferredLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s*s);
-							gDeferredLightProgram.uniform3fv(LLShaderMgr::DIFFUSE_COLOR, 1, col.mV);
-							gDeferredLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, volume->getLightFalloff()*0.5f);
-							//gGL.diffuseColor4f(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff()*0.5f);
-							gGL.syncMatrices();
-							mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
-							glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8,
-								GL_UNSIGNED_SHORT, get_box_fan_indices_ptr(camera, center));
-							stop_glerror();
-						}
-					}
-					else
-					{	
-						if (volume->isLightSpotlight())
-						{
-							drawablep->getVOVolume()->updateSpotLightPriority();
-							fullscreen_spot_lights.push_back(drawablep);
-							continue;
-						}
-
-						fullscreen_lights.push_back(LLVector4(tc.v[0], tc.v[1], tc.v[2], s*s));
-						light_colors.push_back(LLVector4(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff()*0.5f));
-					}
-				}
-				unbindDeferredShader(gDeferredLightProgram);
-			}
-
-			if (!spot_lights.empty())
-			{
-				LLGLDepthTest depth(GL_TRUE, GL_FALSE);
-				bindDeferredShader(gDeferredSpotLightProgram);
-
-				mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
-
-				gDeferredSpotLightProgram.enableTexture(LLShaderMgr::DEFERRED_PROJECTION);
-
-				for (LLDrawable::drawable_list_t::iterator iter = spot_lights.begin(); iter != spot_lights.end(); ++iter)
-				{
-					LLFastTimer ftm(FTM_PROJECTORS);
-					LLDrawable* drawablep = *iter;
-
-					LLVOVolume* volume = drawablep->getVOVolume();
-
-					LLVector4a center;
-					center.load3(drawablep->getPositionAgent().mV);
-					const F32* c = center.getF32ptr();
-					F32 s = volume->getLightRadius()*1.5f;
-
-					sVisibleLightCount++;
-
-					glh::vec3f tc(c);
-					mat.mult_matrix_vec(tc);
-					
-					setupSpotLight(gDeferredSpotLightProgram, drawablep);
-					
-					LLColor3 col = volume->getLightColor();
-
-					//vertex positions are encoded so the 3 bits of their vertex index 
-					//correspond to their axis facing, with bit position 3,2,1 matching
-					//axis facing x,y,z, bit set meaning positive facing, bit clear 
-					//meaning negative facing
-					mDeferredVB->getVertexStrider(vert);
-					v[0].set(c[0]-s,c[1]-s,c[2]-s);  // 0 - 0000 
-					v[1].set(c[0]-s,c[1]-s,c[2]+s);  // 1 - 0001
-					v[2].set(c[0]-s,c[1]+s,c[2]-s);  // 2 - 0010
-					v[3].set(c[0]-s,c[1]+s,c[2]+s);  // 3 - 0011
-																									   
-					v[4].set(c[0]+s,c[1]-s,c[2]-s); // 4 - 0100
-					v[5].set(c[0]+s,c[1]-s,c[2]+s); // 5 - 0101
-					v[6].set(c[0]+s,c[1]+s,c[2]-s); // 6 - 0110
-					v[7].set(c[0]+s,c[1]+s,c[2]+s); // 7 - 0111
-					
-					gDeferredSpotLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, tc.v);
-					gDeferredSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s*s);
-					gDeferredSpotLightProgram.uniform3fv(LLShaderMgr::DIFFUSE_COLOR, 1, col.mV);
-					gDeferredSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, volume->getLightFalloff()*0.5f);
-					gGL.syncMatrices();
-					mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
-					glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8,
-							GL_UNSIGNED_SHORT, get_box_fan_indices_ptr(camera, center));
-				}
-				gDeferredSpotLightProgram.disableTexture(LLShaderMgr::DEFERRED_PROJECTION);
-				unbindDeferredShader(gDeferredSpotLightProgram);
-			}
-
-			//reset mDeferredVB to fullscreen triangle
-			mDeferredVB->getVertexStrider(vert);
-			vert[0].set(-1,1,0);
-			vert[1].set(-1,-3,0);
-			vert[2].set(3,1,0);
-
-			{
-				bindDeferredShader(gDeferredMultiLightProgram);
-			
-				mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
-
-				LLGLDepthTest depth(GL_FALSE);
-
-				//full screen blit
-				gGL.pushMatrix();
-				gGL.loadIdentity();
-				gGL.matrixMode(LLRender::MM_PROJECTION);
-				gGL.pushMatrix();
-				gGL.loadIdentity();
-
-				U32 count = 0;
-
-				const U32 max_count = 8;
-				LLVector4 light[max_count];
-				LLVector4 col[max_count];
-
-//				glVertexPointer(2, GL_FLOAT, 0, vert);
-
-				F32 far_z = 0.f;
-
-				while (!fullscreen_lights.empty())
-				{
-					LLFastTimer ftm(FTM_FULLSCREEN_LIGHTS);
-					light[count] = fullscreen_lights.front();
-					fullscreen_lights.pop_front();
-					col[count] = light_colors.front();
-					light_colors.pop_front();
-
-					far_z = llmin(light[count].mV[2]-sqrtf(light[count].mV[3]), far_z);
-
-					count++;
-					if (count == max_count || fullscreen_lights.empty())
-					{
-						gDeferredMultiLightProgram.uniform1i(LLShaderMgr::MULTI_LIGHT_COUNT, count);
-						gDeferredMultiLightProgram.uniform4fv(LLShaderMgr::MULTI_LIGHT, count, (GLfloat*) light);
-						gDeferredMultiLightProgram.uniform4fv(LLShaderMgr::MULTI_LIGHT_COL, count, (GLfloat*) col);
-						gDeferredMultiLightProgram.uniform1f(LLShaderMgr::MULTI_LIGHT_FAR_Z, far_z);
-						far_z = 0.f;
-						count = 0; 
-						mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
-					}
-				}
-				
-				unbindDeferredShader(gDeferredMultiLightProgram);
-
-				bindDeferredShader(gDeferredMultiSpotLightProgram);
-
-				gDeferredMultiSpotLightProgram.enableTexture(LLShaderMgr::DEFERRED_PROJECTION);
-
-				mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
-
-				for (LLDrawable::drawable_list_t::iterator iter = fullscreen_spot_lights.begin(); iter != fullscreen_spot_lights.end(); ++iter)
-				{
-					LLFastTimer ftm(FTM_PROJECTORS);
-					LLDrawable* drawablep = *iter;
-					
-					LLVOVolume* volume = drawablep->getVOVolume();
-
-					LLVector3 center = drawablep->getPositionAgent();
-					F32* c = center.mV;
-					F32 s = volume->getLightRadius()*1.5f;
-
-					sVisibleLightCount++;
-
-					glh::vec3f tc(c);
-					mat.mult_matrix_vec(tc);
-					
-					setupSpotLight(gDeferredMultiSpotLightProgram, drawablep);
-
-					LLColor3 col = volume->getLightColor();
-
-					gDeferredMultiSpotLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, tc.v);
-					gDeferredMultiSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s*s);
-					gDeferredMultiSpotLightProgram.uniform3fv(LLShaderMgr::DIFFUSE_COLOR, 1, col.mV);
-					gDeferredMultiSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, volume->getLightFalloff()*0.5f);
-					mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
-				}
-
-				gDeferredMultiSpotLightProgram.disableTexture(LLShaderMgr::DEFERRED_PROJECTION);
-				unbindDeferredShader(gDeferredMultiSpotLightProgram);
-
-				gGL.popMatrix();
-				gGL.matrixMode(LLRender::MM_MODELVIEW);
-				gGL.popMatrix();
-			}
-		}
-
-		gGL.setColorMask(true, true);
-	}
-
-	{ //render non-deferred geometry (alpha, fullbright, glow)
-		LLGLDisable blend(GL_BLEND);
-		LLGLDisable stencil(GL_STENCIL_TEST);
-
-		pushRenderTypeMask();
-		andRenderTypeMask(LLPipeline::RENDER_TYPE_ALPHA,
-						 LLPipeline::RENDER_TYPE_FULLBRIGHT,
-						 LLPipeline::RENDER_TYPE_VOLUME,
-						 LLPipeline::RENDER_TYPE_GLOW,
-						 LLPipeline::RENDER_TYPE_BUMP,
-						 LLPipeline::RENDER_TYPE_PASS_SIMPLE,
-						 LLPipeline::RENDER_TYPE_PASS_ALPHA,
-						 LLPipeline::RENDER_TYPE_PASS_ALPHA_MASK,
-						 LLPipeline::RENDER_TYPE_PASS_BUMP,
-						 LLPipeline::RENDER_TYPE_PASS_POST_BUMP,
-						 LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT,
-						 LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK,
-						 LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_SHINY,
-						 LLPipeline::RENDER_TYPE_PASS_GLOW,
-						 LLPipeline::RENDER_TYPE_PASS_GRASS,
-						 LLPipeline::RENDER_TYPE_PASS_SHINY,
-						 LLPipeline::RENDER_TYPE_PASS_INVISIBLE,
-						 LLPipeline::RENDER_TYPE_PASS_INVISI_SHINY,
-						 LLPipeline::RENDER_TYPE_AVATAR,
-						 END_RENDER_TYPES);
-		
-		renderGeomPostDeferred(*LLViewerCamera::getInstance());
-		popRenderTypeMask();
-	}
-
-	{
-		//render highlights, etc.
-		renderHighlights();
-		mHighlightFaces.clear();
-
-		renderDebug();
-
-		LLVertexBuffer::unbind();
-
-		if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
-		{
-			// Render debugging beacons.
-			gObjectList.renderObjectBeacons();
-			gObjectList.resetObjectBeacons();
-		}
-	}
-
-	mScreen.flush();
-						
-}
-
-void LLPipeline::setupSpotLight(LLGLSLShader& shader, LLDrawable* drawablep)
-{
-	//construct frustum
-	LLVOVolume* volume = drawablep->getVOVolume();
-	LLVector3 params = volume->getSpotLightParams();
-
-	F32 fov = params.mV[0];
-	F32 focus = params.mV[1];
-
-	LLVector3 pos = drawablep->getPositionAgent();
-	LLQuaternion quat = volume->getRenderRotation();
-	LLVector3 scale = volume->getScale();
-	
-	//get near clip plane
-	LLVector3 at_axis(0,0,-scale.mV[2]*0.5f);
-	at_axis *= quat;
-
-	LLVector3 np = pos+at_axis;
-	at_axis.normVec();
-
-	//get origin that has given fov for plane np, at_axis, and given scale
-	F32 dist = (scale.mV[1]*0.5f)/tanf(fov*0.5f);
-
-	LLVector3 origin = np - at_axis*dist;
-
-	//matrix from volume space to agent space
-	LLMatrix4 light_mat(quat, LLVector4(origin,1.f));
-
-	glh::matrix4f light_to_agent((F32*) light_mat.mMatrix);
-	glh::matrix4f light_to_screen = glh_get_current_modelview() * light_to_agent;
-
-	glh::matrix4f screen_to_light = light_to_screen.inverse();
-
-	F32 s = volume->getLightRadius()*1.5f;
-	F32 near_clip = dist;
-	F32 width = scale.mV[VX];
-	F32 height = scale.mV[VY];
-	F32 far_clip = s+dist-scale.mV[VZ];
-
-	F32 fovy = fov * RAD_TO_DEG;
-	F32 aspect = width/height;
-
-	glh::matrix4f trans(0.5f, 0.f, 0.f, 0.5f,
-				0.f, 0.5f, 0.f, 0.5f,
-				0.f, 0.f, 0.5f, 0.5f,
-				0.f, 0.f, 0.f, 1.f);
-
-	glh::vec3f p1(0, 0, -(near_clip+0.01f));
-	glh::vec3f p2(0, 0, -(near_clip+1.f));
-
-	glh::vec3f screen_origin(0, 0, 0);
-
-	light_to_screen.mult_matrix_vec(p1);
-	light_to_screen.mult_matrix_vec(p2);
-	light_to_screen.mult_matrix_vec(screen_origin);
-
-	glh::vec3f n = p2-p1;
-	n.normalize();
-	
-	F32 proj_range = far_clip - near_clip;
-	glh::matrix4f light_proj = gl_perspective(fovy, aspect, near_clip, far_clip);
-	screen_to_light = trans * light_proj * screen_to_light;
-	shader.uniformMatrix4fv(LLShaderMgr::PROJECTOR_MATRIX, 1, FALSE, screen_to_light.m);
-	shader.uniform1f(LLShaderMgr::PROJECTOR_NEAR, near_clip);
-	shader.uniform3fv(LLShaderMgr::PROJECTOR_P, 1, p1.v);
-	shader.uniform3fv(LLShaderMgr::PROJECTOR_N, 1, n.v);
-	shader.uniform3fv(LLShaderMgr::PROJECTOR_ORIGIN, 1, screen_origin.v);
-	shader.uniform1f(LLShaderMgr::PROJECTOR_RANGE, proj_range);
-	shader.uniform1f(LLShaderMgr::PROJECTOR_AMBIANCE, params.mV[2]);
-	S32 s_idx = -1;
-
-	for (U32 i = 0; i < 2; i++)
-	{
-		if (mShadowSpotLight[i] == drawablep)
-		{
-			s_idx = i;
-		}
-	}
-
-	shader.uniform1i(LLShaderMgr::PROJECTOR_SHADOW_INDEX, s_idx);
-
-	if (s_idx >= 0)
-	{
-		shader.uniform1f(LLShaderMgr::PROJECTOR_SHADOW_FADE, 1.f-mSpotLightFade[s_idx]);
-	}
-	else
-	{
-		shader.uniform1f(LLShaderMgr::PROJECTOR_SHADOW_FADE, 1.f);
-	}
-
-	{
-		LLDrawable* potential = drawablep;
-		//determine if this is a good light for casting shadows
-		F32 m_pri = volume->getSpotLightPriority();
-
-		for (U32 i = 0; i < 2; i++)
-		{
-			F32 pri = 0.f;
-
-			if (mTargetShadowSpotLight[i].notNull())
-			{
-				pri = mTargetShadowSpotLight[i]->getVOVolume()->getSpotLightPriority();			
-			}
-
-			if (m_pri > pri)
-			{
-				LLDrawable* temp = mTargetShadowSpotLight[i];
-				mTargetShadowSpotLight[i] = potential;
-				potential = temp;
-				m_pri = pri;
-			}
-		}
-	}
-
-	LLViewerTexture* img = volume->getLightTexture();
-
-	if (img == NULL)
-	{
-		img = LLViewerFetchedTexture::sWhiteImagep;
-	}
-
-	S32 channel = shader.enableTexture(LLShaderMgr::DEFERRED_PROJECTION);
-
-	if (channel > -1)
-	{
-		if (img)
-		{
-			gGL.getTexUnit(channel)->bind(img);
-
-			F32 lod_range = logf(img->getWidth())/logf(2.f);
-
-			shader.uniform1f(LLShaderMgr::PROJECTOR_FOCUS, focus);
-			shader.uniform1f(LLShaderMgr::PROJECTOR_LOD, lod_range);
-			shader.uniform1f(LLShaderMgr::PROJECTOR_AMBIENT_LOD, llclamp((proj_range-focus)/proj_range*lod_range, 0.f, 1.f));
-		}
-	}
-		
-}
-
-void LLPipeline::unbindDeferredShader(LLGLSLShader &shader)
-{
-	stop_glerror();
-	shader.disableTexture(LLShaderMgr::DEFERRED_NORMAL, mDeferredScreen.getUsage());
-	shader.disableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mDeferredScreen.getUsage());
-	shader.disableTexture(LLShaderMgr::DEFERRED_SPECULAR, mDeferredScreen.getUsage());
-	shader.disableTexture(LLShaderMgr::DEFERRED_DEPTH, mDeferredScreen.getUsage());
-	shader.disableTexture(LLShaderMgr::DEFERRED_LIGHT, mDeferredLight.getUsage());
-	shader.disableTexture(LLShaderMgr::DIFFUSE_MAP);
-	shader.disableTexture(LLShaderMgr::DEFERRED_BLOOM);
-
-	for (U32 i = 0; i < 4; i++)
-	{
-		if (shader.disableTexture(LLShaderMgr::DEFERRED_SHADOW0+i, LLTexUnit::TT_RECT_TEXTURE) > -1)
-		{
-			glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE);
-		}
-	}
-
-	for (U32 i = 4; i < 6; i++)
-	{
-		if (shader.disableTexture(LLShaderMgr::DEFERRED_SHADOW0+i) > -1)
-		{
-			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE);
-		}
-	}
-
-	shader.disableTexture(LLShaderMgr::DEFERRED_NOISE);
-	shader.disableTexture(LLShaderMgr::DEFERRED_LIGHTFUNC);
-
-	S32 channel = shader.disableTexture(LLShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP);
-	if (channel > -1)
-	{
-		LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL;
-		if (cube_map)
-		{
-			cube_map->disable();
-		}
-	}
-	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-	gGL.getTexUnit(0)->activate();
-	shader.unbind();
-}
-
-inline float sgn(float a)
-{
-    if (a > 0.0F) return (1.0F);
-    if (a < 0.0F) return (-1.0F);
-    return (0.0F);
-}
-
-void LLPipeline::generateWaterReflection(LLCamera& camera_in)
-{	
-	if (LLPipeline::sWaterReflections && assertInitialized() && LLDrawPoolWater::sNeedsReflectionUpdate)
-	{
-		BOOL skip_avatar_update = FALSE;
-		if (!isAgentAvatarValid() || gAgentCamera.getCameraAnimating() || gAgentCamera.getCameraMode() != CAMERA_MODE_MOUSELOOK || !LLVOAvatar::sVisibleInFirstPerson)
-		{
-			skip_avatar_update = TRUE;
-		}
-		
-		if (!skip_avatar_update)
-		{
-			gAgentAvatarp->updateAttachmentVisibility(CAMERA_MODE_THIRD_PERSON);
-		}
-		LLVertexBuffer::unbind();
-
-		LLGLState::checkStates();
-		LLGLState::checkTextureChannels();
-		LLGLState::checkClientArrays();
-
-		LLCamera camera = camera_in;
-		camera.setFar(camera.getFar()*0.87654321f);
-		LLPipeline::sReflectionRender = TRUE;
-		
-		gPipeline.pushRenderTypeMask();
-
-		glh::matrix4f projection = glh_get_current_projection();
-		glh::matrix4f mat;
-
-		stop_glerror();
-		LLPlane plane;
-
-		F32 height = gAgent.getRegion()->getWaterHeight(); 
-		F32 to_clip = fabsf(camera.getOrigin().mV[2]-height);
-		F32 pad = -to_clip*0.05f; //amount to "pad" clip plane by
-
-		//plane params
-		LLVector3 pnorm;
-		F32 pd;
-
-		S32 water_clip = 0;
-		if (!LLViewerCamera::getInstance()->cameraUnderWater())
-		{ //camera is above water, clip plane points up
-			pnorm.setVec(0,0,1);
-			pd = -height;
-			plane.setVec(pnorm, pd);
-			water_clip = -1;
-		}
-		else
-		{	//camera is below water, clip plane points down
-			pnorm = LLVector3(0,0,-1);
-			pd = height;
-			plane.setVec(pnorm, pd);
-			water_clip = 1;
-		}
-
-		if (!LLViewerCamera::getInstance()->cameraUnderWater())
-		{	//generate planar reflection map
-
-			//disable occlusion culling for reflection map for now
-			S32 occlusion = LLPipeline::sUseOcclusion;
-			LLPipeline::sUseOcclusion = 0;
-			gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-			glClearColor(0,0,0,0);
-			mWaterRef.bindTarget();
-			LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WATER0;
-			gGL.setColorMask(true, true);
-			mWaterRef.clear();
-			gGL.setColorMask(true, false);
-
-			mWaterRef.getViewport(gGLViewport);
-
-			stop_glerror();
-
-			gGL.pushMatrix();
-
-			mat.set_scale(glh::vec3f(1,1,-1));
-			mat.set_translate(glh::vec3f(0,0,height*2.f));
-
-			glh::matrix4f current = glh_get_current_modelview();
-
-			mat = current * mat;
-
-			glh_set_current_modelview(mat);
-			gGL.loadMatrix(mat.m);
-
-			LLViewerCamera::updateFrustumPlanes(camera, FALSE, TRUE);
-
-			glh::matrix4f inv_mat = mat.inverse();
-
-			glh::vec3f origin(0,0,0);
-			inv_mat.mult_matrix_vec(origin);
-
-			camera.setOrigin(origin.v);
-
-			glCullFace(GL_FRONT);
-
-			static LLCullResult ref_result;
-
-			if (LLDrawPoolWater::sNeedsReflectionUpdate)
-			{
-				//initial sky pass (no user clip plane)
-				{ //mask out everything but the sky
-					gPipeline.pushRenderTypeMask();
-					gPipeline.andRenderTypeMask(LLPipeline::RENDER_TYPE_SKY,
-						LLPipeline::RENDER_TYPE_WL_SKY,
-						LLPipeline::RENDER_TYPE_CLOUDS,
-						LLPipeline::END_RENDER_TYPES);
-
-					static LLCullResult result;
-					updateCull(camera, result);
-					stateSort(camera, result);
-
-					renderGeom(camera, TRUE);
-
-					gPipeline.popRenderTypeMask();
-				}
-
-				gPipeline.pushRenderTypeMask();
-
-				clearRenderTypeMask(LLPipeline::RENDER_TYPE_WATER,
-					LLPipeline::RENDER_TYPE_VOIDWATER,
-					LLPipeline::RENDER_TYPE_GROUND,
-					LLPipeline::RENDER_TYPE_SKY,
-					LLPipeline::RENDER_TYPE_CLOUDS,
-					LLPipeline::END_RENDER_TYPES);	
-
-				S32 detail = RenderReflectionDetail;
-				if (detail > 0)
-				{ //mask out selected geometry based on reflection detail
-					if (detail < 4)
-					{
-						clearRenderTypeMask(LLPipeline::RENDER_TYPE_PARTICLES, END_RENDER_TYPES);
-						if (detail < 3)
-						{
-							clearRenderTypeMask(LLPipeline::RENDER_TYPE_AVATAR, END_RENDER_TYPES);
-							if (detail < 2)
-							{
-								clearRenderTypeMask(LLPipeline::RENDER_TYPE_VOLUME, END_RENDER_TYPES);
-							}
-						}
-					}
-
-					LLGLUserClipPlane clip_plane(plane, mat, projection);
-					LLGLDisable cull(GL_CULL_FACE);
-					updateCull(camera, ref_result, -water_clip, &plane);
-					stateSort(camera, ref_result);
-				}	
-
-				if (LLDrawPoolWater::sNeedsDistortionUpdate)
-				{
-					if (RenderReflectionDetail > 0)
-					{
-						gPipeline.grabReferences(ref_result);
-						LLGLUserClipPlane clip_plane(plane, mat, projection);
-						renderGeom(camera);
-					}
-				}	
-
-				gPipeline.popRenderTypeMask();
-			}	
-			glCullFace(GL_BACK);
-			gGL.popMatrix();
-			mWaterRef.flush();
-			glh_set_current_modelview(current);
-			LLPipeline::sUseOcclusion = occlusion;
-		}
-
-		camera.setOrigin(camera_in.getOrigin());
-		//render distortion map
-		static BOOL last_update = TRUE;
-		if (last_update)
-		{
-			camera.setFar(camera_in.getFar());
-			clearRenderTypeMask(LLPipeline::RENDER_TYPE_WATER,
-								LLPipeline::RENDER_TYPE_VOIDWATER,
-								LLPipeline::RENDER_TYPE_GROUND,
-								END_RENDER_TYPES);	
-			stop_glerror();
-
-			LLPipeline::sUnderWaterRender = LLViewerCamera::getInstance()->cameraUnderWater() ? FALSE : TRUE;
-
-			if (LLPipeline::sUnderWaterRender)
-			{
-				clearRenderTypeMask(LLPipeline::RENDER_TYPE_GROUND,
-									LLPipeline::RENDER_TYPE_SKY,
-									LLPipeline::RENDER_TYPE_CLOUDS,
-									LLPipeline::RENDER_TYPE_WL_SKY,
-									END_RENDER_TYPES);		
-			}
-			LLViewerCamera::updateFrustumPlanes(camera);
-
-			gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-			LLColor4& col = LLDrawPoolWater::sWaterFogColor;
-			glClearColor(col.mV[0], col.mV[1], col.mV[2], 0.f);
-			mWaterDis.bindTarget();
-			LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WATER1;
-			mWaterDis.getViewport(gGLViewport);
-			
-			if (!LLPipeline::sUnderWaterRender || LLDrawPoolWater::sNeedsReflectionUpdate)
-			{
-				//clip out geometry on the same side of water as the camera
-				mat = glh_get_current_modelview();
-				LLPlane plane(-pnorm, -(pd+pad));
-
-				LLGLUserClipPlane clip_plane(plane, mat, projection);
-				static LLCullResult result;
-				updateCull(camera, result, water_clip, &plane);
-				stateSort(camera, result);
-
-				gGL.setColorMask(true, true);
-				mWaterDis.clear();
-				gGL.setColorMask(true, false);
-
-				renderGeom(camera);
-
-			}
-
-			LLPipeline::sUnderWaterRender = FALSE;
-			mWaterDis.flush();
-		}
-		last_update = LLDrawPoolWater::sNeedsReflectionUpdate && LLDrawPoolWater::sNeedsDistortionUpdate;
-
-		LLRenderTarget::unbindTarget();
-
-		LLPipeline::sReflectionRender = FALSE;
-
-		if (!LLRenderTarget::sUseFBO)
-		{
-			glClear(GL_DEPTH_BUFFER_BIT);
-		}
-		glClearColor(0.f, 0.f, 0.f, 0.f);
-		gViewerWindow->setup3DViewport();
-		gPipeline.popRenderTypeMask();
-		LLDrawPoolWater::sNeedsReflectionUpdate = FALSE;
-		LLDrawPoolWater::sNeedsDistortionUpdate = FALSE;
-		LLPlane npnorm(-pnorm, -pd);
-		LLViewerCamera::getInstance()->setUserClipPlane(npnorm);
-		
-		LLGLState::checkStates();
-
-		if (!skip_avatar_update)
-		{
-			gAgentAvatarp->updateAttachmentVisibility(gAgentCamera.getCameraMode());
-		}
-
-		LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
-	}
-}
-
-glh::matrix4f look(const LLVector3 pos, const LLVector3 dir, const LLVector3 up)
-{
-	glh::matrix4f ret;
-
-	LLVector3 dirN;
-	LLVector3 upN;
-	LLVector3 lftN;
-
-	lftN = dir % up;
-	lftN.normVec();
-	
-	upN = lftN % dir;
-	upN.normVec();
-	
-	dirN = dir;
-	dirN.normVec();
-
-	ret.m[ 0] = lftN[0];
-	ret.m[ 1] = upN[0];
-	ret.m[ 2] = -dirN[0];
-	ret.m[ 3] = 0.f;
-
-	ret.m[ 4] = lftN[1];
-	ret.m[ 5] = upN[1];
-	ret.m[ 6] = -dirN[1];
-	ret.m[ 7] = 0.f;
-
-	ret.m[ 8] = lftN[2];
-	ret.m[ 9] = upN[2];
-	ret.m[10] = -dirN[2];
-	ret.m[11] = 0.f;
-
-	ret.m[12] = -(lftN*pos);
-	ret.m[13] = -(upN*pos);
-	ret.m[14] = dirN*pos;
-	ret.m[15] = 1.f;
-
-	return ret;
-}
-
-glh::matrix4f scale_translate_to_fit(const LLVector3 min, const LLVector3 max)
-{
-	glh::matrix4f ret;
-	ret.m[ 0] = 2/(max[0]-min[0]);
-	ret.m[ 4] = 0;
-	ret.m[ 8] = 0;
-	ret.m[12] = -(max[0]+min[0])/(max[0]-min[0]);
-
-	ret.m[ 1] = 0;
-	ret.m[ 5] = 2/(max[1]-min[1]);
-	ret.m[ 9] = 0;
-	ret.m[13] = -(max[1]+min[1])/(max[1]-min[1]);
-
-	ret.m[ 2] = 0;
-	ret.m[ 6] = 0;
-	ret.m[10] = 2/(max[2]-min[2]);
-	ret.m[14] = -(max[2]+min[2])/(max[2]-min[2]);
-
-	ret.m[ 3] = 0;
-	ret.m[ 7] = 0;
-	ret.m[11] = 0;
-	ret.m[15] = 1;
-
-	return ret;
-}
-
-static LLFastTimer::DeclareTimer FTM_SHADOW_RENDER("Render Shadows");
-static LLFastTimer::DeclareTimer FTM_SHADOW_ALPHA("Alpha Shadow");
-static LLFastTimer::DeclareTimer FTM_SHADOW_SIMPLE("Simple Shadow");
-
-void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera& shadow_cam, LLCullResult &result, BOOL use_shader, BOOL use_occlusion)
-{
-	LLFastTimer t(FTM_SHADOW_RENDER);
-
-	//clip out geometry on the same side of water as the camera
-	S32 occlude = LLPipeline::sUseOcclusion;
-	if (!use_occlusion)
-	{
-		LLPipeline::sUseOcclusion = 0;
-	}
-	LLPipeline::sShadowRender = TRUE;
-	
-	U32 types[] = { 
-		LLRenderPass::PASS_SIMPLE, 
-		LLRenderPass::PASS_FULLBRIGHT, 
-		LLRenderPass::PASS_SHINY, 
-		LLRenderPass::PASS_BUMP, 
-		LLRenderPass::PASS_FULLBRIGHT_SHINY 
-	};
-
-	LLGLEnable cull(GL_CULL_FACE);
-
-	if (use_shader)
-	{
-		gDeferredShadowProgram.bind();
-	}
-
-	updateCull(shadow_cam, result);
-	stateSort(shadow_cam, result);
-	
-	//generate shadow map
-	gGL.matrixMode(LLRender::MM_PROJECTION);
-	gGL.pushMatrix();
-	gGL.loadMatrix(proj.m);
-	gGL.matrixMode(LLRender::MM_MODELVIEW);
-	gGL.pushMatrix();
-	gGL.loadMatrix(gGLModelView);
-
-	stop_glerror();
-	gGLLastMatrix = NULL;
-
-	{
-		//LLGLDepthTest depth(GL_TRUE);
-		//glClear(GL_DEPTH_BUFFER_BIT);
-	}
-
-	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-	
-	stop_glerror();
-	
-	//glCullFace(GL_FRONT);
-
-	LLVertexBuffer::unbind();
-
-	{
-		if (!use_shader)
-		{ //occlusion program is general purpose depth-only no-textures
-			gOcclusionProgram.bind();
-		}
-
-		gGL.diffuseColor4f(1,1,1,1);
-		gGL.setColorMask(false, false);
-	
-		LLFastTimer ftm(FTM_SHADOW_SIMPLE);
-		gGL.getTexUnit(0)->disable();
-		for (U32 i = 0; i < sizeof(types)/sizeof(U32); ++i)
-		{
-			renderObjects(types[i], LLVertexBuffer::MAP_VERTEX, FALSE);
-		}
-		gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
-		if (!use_shader)
-		{
-			gOcclusionProgram.unbind();
-		}
-	}
-	
-	if (use_shader)
-	{
-		gDeferredShadowProgram.unbind();
-		renderGeomShadow(shadow_cam);
-		gDeferredShadowProgram.bind();
-	}
-	else
-	{
-		renderGeomShadow(shadow_cam);
-	}
-
-	{
-		LLFastTimer ftm(FTM_SHADOW_ALPHA);
-		gDeferredShadowAlphaMaskProgram.bind();
-		gDeferredShadowAlphaMaskProgram.setMinimumAlpha(0.598f);
-		
-		U32 mask =	LLVertexBuffer::MAP_VERTEX | 
-					LLVertexBuffer::MAP_TEXCOORD0 | 
-					LLVertexBuffer::MAP_COLOR | 
-					LLVertexBuffer::MAP_TEXTURE_INDEX;
-
-		renderObjects(LLRenderPass::PASS_ALPHA_MASK, mask, TRUE, TRUE);
-		renderObjects(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, mask, TRUE, TRUE);
-		renderObjects(LLRenderPass::PASS_ALPHA, mask, TRUE, TRUE);
-		gDeferredTreeShadowProgram.bind();
-		gDeferredTreeShadowProgram.setMinimumAlpha(0.598f);
-		renderObjects(LLRenderPass::PASS_GRASS, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, TRUE);
-	}
-
-	//glCullFace(GL_BACK);
-
-	gDeferredShadowProgram.bind();
-	gGLLastMatrix = NULL;
-	gGL.loadMatrix(gGLModelView);
-	doOcclusion(shadow_cam);
-
-	if (use_shader)
-	{
-		gDeferredShadowProgram.unbind();
-	}
-	
-	gGL.setColorMask(true, true);
-			
-	gGL.matrixMode(LLRender::MM_PROJECTION);
-	gGL.popMatrix();
-	gGL.matrixMode(LLRender::MM_MODELVIEW);
-	gGL.popMatrix();
-	gGLLastMatrix = NULL;
-
-	LLPipeline::sUseOcclusion = occlude;
-	LLPipeline::sShadowRender = FALSE;
-}
-
-static LLFastTimer::DeclareTimer FTM_VISIBLE_CLOUD("Visible Cloud");
-BOOL LLPipeline::getVisiblePointCloud(LLCamera& camera, LLVector3& min, LLVector3& max, std::vector<LLVector3>& fp, LLVector3 light_dir)
-{
-	LLFastTimer t(FTM_VISIBLE_CLOUD);
-	//get point cloud of intersection of frust and min, max
-
-	if (getVisibleExtents(camera, min, max))
-	{
-		return FALSE;
-	}
-
-	//get set of planes on bounding box
-	LLPlane bp[] = { 
-		LLPlane(min, LLVector3(-1,0,0)),
-		LLPlane(min, LLVector3(0,-1,0)),
-		LLPlane(min, LLVector3(0,0,-1)),
-		LLPlane(max, LLVector3(1,0,0)),
-		LLPlane(max, LLVector3(0,1,0)),
-		LLPlane(max, LLVector3(0,0,1))};
-	
-	//potential points
-	std::vector<LLVector3> pp;
-
-	//add corners of AABB
-	pp.push_back(LLVector3(min.mV[0], min.mV[1], min.mV[2]));
-	pp.push_back(LLVector3(max.mV[0], min.mV[1], min.mV[2]));
-	pp.push_back(LLVector3(min.mV[0], max.mV[1], min.mV[2]));
-	pp.push_back(LLVector3(max.mV[0], max.mV[1], min.mV[2]));
-	pp.push_back(LLVector3(min.mV[0], min.mV[1], max.mV[2]));
-	pp.push_back(LLVector3(max.mV[0], min.mV[1], max.mV[2]));
-	pp.push_back(LLVector3(min.mV[0], max.mV[1], max.mV[2]));
-	pp.push_back(LLVector3(max.mV[0], max.mV[1], max.mV[2]));
-
-	//add corners of camera frustum
-	for (U32 i = 0; i < 8; i++)
-	{
-		pp.push_back(camera.mAgentFrustum[i]);
-	}
-
-
-	//bounding box line segments
-	U32 bs[] = 
-			{
-		0,1,
-		1,3,
-		3,2,
-		2,0,
-
-		4,5,
-		5,7,
-		7,6,
-		6,4,
-
-		0,4,
-		1,5,
-		3,7,
-		2,6
-	};
-
-	for (U32 i = 0; i < 12; i++)
-	{ //for each line segment in bounding box
-		for (U32 j = 0; j < 6; j++) 
-		{ //for each plane in camera frustum
-			const LLPlane& cp = camera.getAgentPlane(j);
-			const LLVector3& v1 = pp[bs[i*2+0]];
-			const LLVector3& v2 = pp[bs[i*2+1]];
-			LLVector3 n;
-			cp.getVector3(n);
-
-			LLVector3 line = v1-v2;
-
-			F32 d1 = line*n;
-			F32 d2 = -cp.dist(v2);
-
-			F32 t = d2/d1;
-
-			if (t > 0.f && t < 1.f)
-			{
-				LLVector3 intersect = v2+line*t;
-				pp.push_back(intersect);
-			}
-		}
-	}
-			
-	//camera frustum line segments
-	const U32 fs[] =
-	{
-		0,1,
-		1,2,
-		2,3,
-		3,0,
-
-		4,5,
-		5,6,
-		6,7,
-		7,4,
-	
-		0,4,
-		1,5,
-		2,6,
-		3,7	
-	};
-
-	LLVector3 center = (max+min)*0.5f;
-	LLVector3 size = (max-min)*0.5f;
-	
-	for (U32 i = 0; i < 12; i++)
-	{
-		for (U32 j = 0; j < 6; ++j)
-		{
-			const LLVector3& v1 = pp[fs[i*2+0]+8];
-			const LLVector3& v2 = pp[fs[i*2+1]+8];
-			const LLPlane& cp = bp[j];
-			LLVector3 n;
-			cp.getVector3(n);
-
-			LLVector3 line = v1-v2;
-
-			F32 d1 = line*n;
-			F32 d2 = -cp.dist(v2);
-
-			F32 t = d2/d1;
-
-			if (t > 0.f && t < 1.f)
-			{
-				LLVector3 intersect = v2+line*t;
-				pp.push_back(intersect);
-			}	
-		}
-	}
-
-	LLVector3 ext[] = { min-LLVector3(0.05f,0.05f,0.05f),
-		max+LLVector3(0.05f,0.05f,0.05f) };
-
-	for (U32 i = 0; i < pp.size(); ++i)
-	{
-		bool found = true;
-
-		const F32* p = pp[i].mV;
-			
-		for (U32 j = 0; j < 3; ++j)
-		{
-			if (p[j] < ext[0].mV[j] ||
-				p[j] > ext[1].mV[j])
-			{
-				found = false;
-				break;
-			}
-		}
-				
-		for (U32 j = 0; j < 6; ++j)
-		{
-			const LLPlane& cp = camera.getAgentPlane(j);
-			F32 dist = cp.dist(pp[i]);
-			if (dist > 0.05f) //point is above some plane, not contained
-					{
-				found = false;
-				break;
-						}
-					}
-
-					if (found)
-					{
-			fp.push_back(pp[i]);
-		}
-	}
-	
-	if (fp.empty())
-	{
-		return FALSE;
-	}
-	
-	return TRUE;
-}
-
-void LLPipeline::renderHighlight(const LLViewerObject* obj, F32 fade)
-{
-	if (obj && obj->getVolume())
-	{
-		for (LLViewerObject::child_list_t::const_iterator iter = obj->getChildren().begin(); iter != obj->getChildren().end(); ++iter)
-		{
-			renderHighlight(*iter, fade);
-		}
-
-		LLDrawable* drawable = obj->mDrawable;
-		if (drawable)
-		{
-			for (S32 i = 0; i < drawable->getNumFaces(); ++i)
-			{
-				LLFace* face = drawable->getFace(i);
-				if (face)
-				{
-					face->renderSelected(LLViewerTexture::sNullImagep, LLColor4(1,1,1,fade));
-				}
-			}
-		}
-	}
-}
-
-void LLPipeline::generateHighlight(LLCamera& camera)
-{
-	//render highlighted object as white into offscreen render target
-	if (mHighlightObject.notNull())
-	{
-		mHighlightSet.insert(HighlightItem(mHighlightObject));
-	}
-	
-	if (!mHighlightSet.empty())
-	{
-		F32 transition = gFrameIntervalSeconds/RenderHighlightFadeTime;
-
-		LLGLDisable test(GL_ALPHA_TEST);
-		LLGLDepthTest depth(GL_FALSE);
-		mHighlight.bindTarget();
-		disableLights();
-		gGL.setColorMask(true, true);
-		mHighlight.clear();
-
-		gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sWhiteImagep);
-		for (std::set<HighlightItem>::iterator iter = mHighlightSet.begin(); iter != mHighlightSet.end(); )
-		{
-			std::set<HighlightItem>::iterator cur_iter = iter++;
-
-			if (cur_iter->mItem.isNull())
-			{
-				mHighlightSet.erase(cur_iter);
-				continue;
-			}
-
-			if (cur_iter->mItem == mHighlightObject)
-			{
-				cur_iter->incrFade(transition); 
-			}
-			else
-			{
-				cur_iter->incrFade(-transition);
-				if (cur_iter->mFade <= 0.f)
-				{
-					mHighlightSet.erase(cur_iter);
-					continue;
-				}
-			}
-
-			renderHighlight(cur_iter->mItem->getVObj(), cur_iter->mFade);
-		}
-
-		mHighlight.flush();
-		gGL.setColorMask(true, false);
-		gViewerWindow->setup3DViewport();
-	}
-}
-
-
-void LLPipeline::generateSunShadow(LLCamera& camera)
-{
-	if (!sRenderDeferred || RenderShadowDetail <= 0)
-	{
-		return;
-	}
-
-	BOOL skip_avatar_update = FALSE;
-	if (!isAgentAvatarValid() || gAgentCamera.getCameraAnimating() || gAgentCamera.getCameraMode() != CAMERA_MODE_MOUSELOOK || !LLVOAvatar::sVisibleInFirstPerson)
-	{
-
-		skip_avatar_update = TRUE;
-	}
-
-	if (!skip_avatar_update)
-	{
-		gAgentAvatarp->updateAttachmentVisibility(CAMERA_MODE_THIRD_PERSON);
-	}
-
-	F64 last_modelview[16];
-	F64 last_projection[16];
-	for (U32 i = 0; i < 16; i++)
-	{ //store last_modelview of world camera
-		last_modelview[i] = gGLLastModelView[i];
-		last_projection[i] = gGLLastProjection[i];
-	}
-
-	pushRenderTypeMask();
-	andRenderTypeMask(LLPipeline::RENDER_TYPE_SIMPLE,
-					LLPipeline::RENDER_TYPE_ALPHA,
-					LLPipeline::RENDER_TYPE_GRASS,
-					LLPipeline::RENDER_TYPE_FULLBRIGHT,
-					LLPipeline::RENDER_TYPE_BUMP,
-					LLPipeline::RENDER_TYPE_VOLUME,
-					LLPipeline::RENDER_TYPE_AVATAR,
-					LLPipeline::RENDER_TYPE_TREE, 
-					LLPipeline::RENDER_TYPE_TERRAIN,
-					LLPipeline::RENDER_TYPE_WATER,
-					LLPipeline::RENDER_TYPE_VOIDWATER,
-					LLPipeline::RENDER_TYPE_PASS_ALPHA,
-					LLPipeline::RENDER_TYPE_PASS_ALPHA_MASK,
-					LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK,
-					LLPipeline::RENDER_TYPE_PASS_GRASS,
-					LLPipeline::RENDER_TYPE_PASS_SIMPLE,
-					LLPipeline::RENDER_TYPE_PASS_BUMP,
-					LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT,
-					LLPipeline::RENDER_TYPE_PASS_SHINY,
-					LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_SHINY,
-					END_RENDER_TYPES);
-
-	gGL.setColorMask(false, false);
-
-	//get sun view matrix
-	
-	//store current projection/modelview matrix
-	glh::matrix4f saved_proj = glh_get_current_projection();
-	glh::matrix4f saved_view = glh_get_current_modelview();
-	glh::matrix4f inv_view = saved_view.inverse();
-
-	glh::matrix4f view[6];
-	glh::matrix4f proj[6];
-	
-	//clip contains parallel split distances for 3 splits
-	LLVector3 clip = RenderShadowClipPlanes;
-
-	//F32 slope_threshold = gSavedSettings.getF32("RenderShadowSlopeThreshold");
-
-	//far clip on last split is minimum of camera view distance and 128
-	mSunClipPlanes = LLVector4(clip, clip.mV[2] * clip.mV[2]/clip.mV[1]);
-
-	clip = RenderShadowOrthoClipPlanes;
-	mSunOrthoClipPlanes = LLVector4(clip, clip.mV[2]*clip.mV[2]/clip.mV[1]);
-
-	//currently used for amount to extrude frusta corners for constructing shadow frusta
-	LLVector3 n = RenderShadowNearDist;
-	//F32 nearDist[] = { n.mV[0], n.mV[1], n.mV[2], n.mV[2] };
-
-	//put together a universal "near clip" plane for shadow frusta
-	LLPlane shadow_near_clip;
-	{
-		LLVector3 p = gAgent.getPositionAgent();
-		p += mSunDir * RenderFarClip*2.f;
-		shadow_near_clip.setVec(p, mSunDir);
-	}
-
-	LLVector3 lightDir = -mSunDir;
-	lightDir.normVec();
-
-	glh::vec3f light_dir(lightDir.mV);
-
-	//create light space camera matrix
-	
-	LLVector3 at = lightDir;
-
-	LLVector3 up = camera.getAtAxis();
-
-	if (fabsf(up*lightDir) > 0.75f)
-	{
-		up = camera.getUpAxis();
-	}
-
-	/*LLVector3 left = up%at;
-	up = at%left;*/
-
-	up.normVec();
-	at.normVec();
-	
-	
-	LLCamera main_camera = camera;
-	
-	F32 near_clip = 0.f;
-	{
-		//get visible point cloud
-		std::vector<LLVector3> fp;
-
-		main_camera.calcAgentFrustumPlanes(main_camera.mAgentFrustum);
-		
-		LLVector3 min,max;
-		getVisiblePointCloud(main_camera,min,max,fp);
-
-		if (fp.empty())
-		{
-			if (!hasRenderDebugMask(RENDER_DEBUG_SHADOW_FRUSTA))
-			{
-				mShadowCamera[0] = main_camera;
-				mShadowExtents[0][0] = min;
-				mShadowExtents[0][1] = max;
-
-				mShadowFrustPoints[0].clear();
-				mShadowFrustPoints[1].clear();
-				mShadowFrustPoints[2].clear();
-				mShadowFrustPoints[3].clear();
-			}
-			popRenderTypeMask();
-
-			if (!skip_avatar_update)
-			{
-				gAgentAvatarp->updateAttachmentVisibility(gAgentCamera.getCameraMode());
-			}
-
-			return;
-		}
-
-		//get good split distances for frustum
-		for (U32 i = 0; i < fp.size(); ++i)
-		{
-			glh::vec3f v(fp[i].mV);
-			saved_view.mult_matrix_vec(v);
-			fp[i].setVec(v.v);
-		}
-
-		min = fp[0];
-		max = fp[0];
-
-		//get camera space bounding box
-		for (U32 i = 1; i < fp.size(); ++i)
-		{
-			update_min_max(min, max, fp[i]);
-		}
-
-		near_clip = -max.mV[2];
-		F32 far_clip = -min.mV[2]*2.f;
-
-		//far_clip = llmin(far_clip, 128.f);
-		far_clip = llmin(far_clip, camera.getFar());
-
-		F32 range = far_clip-near_clip;
-
-		LLVector3 split_exp = RenderShadowSplitExponent;
-
-		F32 da = 1.f-llmax( fabsf(lightDir*up), fabsf(lightDir*camera.getLeftAxis()) );
-		
-		da = powf(da, split_exp.mV[2]);
-
-
-		F32 sxp = split_exp.mV[1] + (split_exp.mV[0]-split_exp.mV[1])*da;
-
-
-		for (U32 i = 0; i < 4; ++i)
-		{
-			F32 x = (F32)(i+1)/4.f;
-			x = powf(x, sxp);
-			mSunClipPlanes.mV[i] = near_clip+range*x;
-		}
-	}
-
-	// convenience array of 4 near clip plane distances
-	F32 dist[] = { near_clip, mSunClipPlanes.mV[0], mSunClipPlanes.mV[1], mSunClipPlanes.mV[2], mSunClipPlanes.mV[3] };
-	
-
-	if (mSunDiffuse == LLColor4::black)
-	{ //sun diffuse is totally black, shadows don't matter
-		LLGLDepthTest depth(GL_TRUE);
-
-		for (S32 j = 0; j < 4; j++)
-		{
-			mShadow[j].bindTarget();
-			mShadow[j].clear();
-			mShadow[j].flush();
-		}
-	}
-	else
-	{
-		for (S32 j = 0; j < 4; j++)
-		{
-			if (!hasRenderDebugMask(RENDER_DEBUG_SHADOW_FRUSTA))
-			{
-				mShadowFrustPoints[j].clear();
-			}
-
-			LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_SHADOW0+j;
-
-			//restore render matrices
-			glh_set_current_modelview(saved_view);
-			glh_set_current_projection(saved_proj);
-
-			LLVector3 eye = camera.getOrigin();
-
-			//camera used for shadow cull/render
-			LLCamera shadow_cam;
-		
-			//create world space camera frustum for this split
-			shadow_cam = camera;
-			shadow_cam.setFar(16.f);
-	
-			LLViewerCamera::updateFrustumPlanes(shadow_cam, FALSE, FALSE, TRUE);
-
-			LLVector3* frust = shadow_cam.mAgentFrustum;
-
-			LLVector3 pn = shadow_cam.getAtAxis();
-		
-			LLVector3 min, max;
-
-			//construct 8 corners of split frustum section
-			for (U32 i = 0; i < 4; i++)
-			{
-				LLVector3 delta = frust[i+4]-eye;
-				delta += (frust[i+4]-frust[(i+2)%4+4])*0.05f;
-				delta.normVec();
-				F32 dp = delta*pn;
-				frust[i] = eye + (delta*dist[j]*0.95f)/dp;
-				frust[i+4] = eye + (delta*dist[j+1]*1.05f)/dp;
-			}
-						
-			shadow_cam.calcAgentFrustumPlanes(frust);
-			shadow_cam.mFrustumCornerDist = 0.f;
-		
-			if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
-			{
-				mShadowCamera[j] = shadow_cam;
-			}
-
-			std::vector<LLVector3> fp;
-
-			if (!gPipeline.getVisiblePointCloud(shadow_cam, min, max, fp, lightDir))
-			{
-				//no possible shadow receivers
-				if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
-				{
-					mShadowExtents[j][0] = LLVector3();
-					mShadowExtents[j][1] = LLVector3();
-					mShadowCamera[j+4] = shadow_cam;
-				}
-
-				mShadow[j].bindTarget();
-				{
-					LLGLDepthTest depth(GL_TRUE);
-					mShadow[j].clear();
-				}
-				mShadow[j].flush();
-
-				mShadowError.mV[j] = 0.f;
-				mShadowFOV.mV[j] = 0.f;
-
-				continue;
-			}
-
-			if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
-			{
-				mShadowExtents[j][0] = min;
-				mShadowExtents[j][1] = max;
-				mShadowFrustPoints[j] = fp;
-			}
-				
-
-			//find a good origin for shadow projection
-			LLVector3 origin;
-
-			//get a temporary view projection
-			view[j] = look(camera.getOrigin(), lightDir, -up);
-
-			std::vector<LLVector3> wpf;
-
-			for (U32 i = 0; i < fp.size(); i++)
-			{
-				glh::vec3f p = glh::vec3f(fp[i].mV);
-				view[j].mult_matrix_vec(p);
-				wpf.push_back(LLVector3(p.v));
-			}
-
-			min = wpf[0];
-			max = wpf[0];
-
-			for (U32 i = 0; i < fp.size(); ++i)
-			{ //get AABB in camera space
-				update_min_max(min, max, wpf[i]);
-			}
-
-			// Construct a perspective transform with perspective along y-axis that contains
-			// points in wpf
-			//Known:
-			// - far clip plane
-			// - near clip plane
-			// - points in frustum
-			//Find:
-			// - origin
-
-			//get some "interesting" points of reference
-			LLVector3 center = (min+max)*0.5f;
-			LLVector3 size = (max-min)*0.5f;
-			LLVector3 near_center = center;
-			near_center.mV[1] += size.mV[1]*2.f;
-		
-		
-			//put all points in wpf in quadrant 0, reletive to center of min/max
-			//get the best fit line using least squares
-			F32 bfm = 0.f;
-			F32 bfb = 0.f;
-
-			for (U32 i = 0; i < wpf.size(); ++i)
-			{
-				wpf[i] -= center;
-				wpf[i].mV[0] = fabsf(wpf[i].mV[0]);
-				wpf[i].mV[2] = fabsf(wpf[i].mV[2]);
-			}
-
-			if (!wpf.empty())
-			{ 
-				F32 sx = 0.f;
-				F32 sx2 = 0.f;
-				F32 sy = 0.f;
-				F32 sxy = 0.f;
-			
-				for (U32 i = 0; i < wpf.size(); ++i)
-				{		
-					sx += wpf[i].mV[0];
-					sx2 += wpf[i].mV[0]*wpf[i].mV[0];
-					sy += wpf[i].mV[1];
-					sxy += wpf[i].mV[0]*wpf[i].mV[1]; 
-				}
-
-				bfm = (sy*sx-wpf.size()*sxy)/(sx*sx-wpf.size()*sx2);
-				bfb = (sx*sxy-sy*sx2)/(sx*sx-bfm*sx2);
-			}
-		
-			{
-				// best fit line is y=bfm*x+bfb
-		
-				//find point that is furthest to the right of line
-				F32 off_x = -1.f;
-				LLVector3 lp;
-
-				for (U32 i = 0; i < wpf.size(); ++i)
-				{
-					//y = bfm*x+bfb
-					//x = (y-bfb)/bfm
-					F32 lx = (wpf[i].mV[1]-bfb)/bfm;
-
-					lx = wpf[i].mV[0]-lx;
-				
-					if (off_x < lx)
-					{
-						off_x = lx;
-						lp = wpf[i];
-					}
-				}
-
-				//get line with slope bfm through lp
-				// bfb = y-bfm*x
-				bfb = lp.mV[1]-bfm*lp.mV[0];
-
-				//calculate error
-				mShadowError.mV[j] = 0.f;
-
-				for (U32 i = 0; i < wpf.size(); ++i)
-				{
-					F32 lx = (wpf[i].mV[1]-bfb)/bfm;
-					mShadowError.mV[j] += fabsf(wpf[i].mV[0]-lx);
-				}
-
-				mShadowError.mV[j] /= wpf.size();
-				mShadowError.mV[j] /= size.mV[0];
-
-				if (mShadowError.mV[j] > RenderShadowErrorCutoff)
-				{ //just use ortho projection
-					mShadowFOV.mV[j] = -1.f;
-					origin.clearVec();
-					proj[j] = gl_ortho(min.mV[0], max.mV[0],
-										min.mV[1], max.mV[1],
-										-max.mV[2], -min.mV[2]);
-				}
-				else
-				{
-					//origin is where line x = 0;
-					origin.setVec(0,bfb,0);
-
-					F32 fovz = 1.f;
-					F32 fovx = 1.f;
-				
-					LLVector3 zp;
-					LLVector3 xp;
-
-					for (U32 i = 0; i < wpf.size(); ++i)
-					{
-						LLVector3 atz = wpf[i]-origin;
-						atz.mV[0] = 0.f;
-						atz.normVec();
-						if (fovz > -atz.mV[1])
-						{
-							zp = wpf[i];
-							fovz = -atz.mV[1];
-						}
-					
-						LLVector3 atx = wpf[i]-origin;
-						atx.mV[2] = 0.f;
-						atx.normVec();
-						if (fovx > -atx.mV[1])
-						{
-							fovx = -atx.mV[1];
-							xp = wpf[i];
-						}
-					}
-
-					fovx = acos(fovx);
-					fovz = acos(fovz);
-
-					F32 cutoff = llmin((F32) RenderShadowFOVCutoff, 1.4f);
-				
-					mShadowFOV.mV[j] = fovx;
-				
-					if (fovx < cutoff && fovz > cutoff)
-					{
-						//x is a good fit, but z is too big, move away from zp enough so that fovz matches cutoff
-						F32 d = zp.mV[2]/tan(cutoff);
-						F32 ny = zp.mV[1] + fabsf(d);
-
-						origin.mV[1] = ny;
-
-						fovz = 1.f;
-						fovx = 1.f;
-
-						for (U32 i = 0; i < wpf.size(); ++i)
-						{
-							LLVector3 atz = wpf[i]-origin;
-							atz.mV[0] = 0.f;
-							atz.normVec();
-							fovz = llmin(fovz, -atz.mV[1]);
-
-							LLVector3 atx = wpf[i]-origin;
-							atx.mV[2] = 0.f;
-							atx.normVec();
-							fovx = llmin(fovx, -atx.mV[1]);
-						}
-
-						fovx = acos(fovx);
-						fovz = acos(fovz);
-
-						mShadowFOV.mV[j] = cutoff;
-					}
-
-				
-					origin += center;
-			
-					F32 ynear = -(max.mV[1]-origin.mV[1]);
-					F32 yfar = -(min.mV[1]-origin.mV[1]);
-				
-					if (ynear < 0.1f) //keep a sensible near clip plane
-					{
-						F32 diff = 0.1f-ynear;
-						origin.mV[1] += diff;
-						ynear += diff;
-						yfar += diff;
-					}
-								
-					if (fovx > cutoff)
-					{ //just use ortho projection
-						origin.clearVec();
-						mShadowError.mV[j] = -1.f;
-						proj[j] = gl_ortho(min.mV[0], max.mV[0],
-								min.mV[1], max.mV[1],
-								-max.mV[2], -min.mV[2]);
-					}
-					else
-					{
-						//get perspective projection
-						view[j] = view[j].inverse();
-
-						glh::vec3f origin_agent(origin.mV);
-					
-						//translate view to origin
-						view[j].mult_matrix_vec(origin_agent);
-
-						eye = LLVector3(origin_agent.v);
-
-						if (!hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
-						{
-							mShadowFrustOrigin[j] = eye;
-						}
-				
-						view[j] = look(LLVector3(origin_agent.v), lightDir, -up);
-
-						F32 fx = 1.f/tanf(fovx);
-						F32 fz = 1.f/tanf(fovz);
-
-						proj[j] = glh::matrix4f(-fx, 0, 0, 0,
-												0, (yfar+ynear)/(ynear-yfar), 0, (2.f*yfar*ynear)/(ynear-yfar),
-												0, 0, -fz, 0,
-												0, -1.f, 0, 0);
-					}
-				}
-			}
-
-			//shadow_cam.setFar(128.f);
-			shadow_cam.setOriginAndLookAt(eye, up, center);
-
-			shadow_cam.setOrigin(0,0,0);
-
-			glh_set_current_modelview(view[j]);
-			glh_set_current_projection(proj[j]);
-
-			LLViewerCamera::updateFrustumPlanes(shadow_cam, FALSE, FALSE, TRUE);
-
-			//shadow_cam.ignoreAgentFrustumPlane(LLCamera::AGENT_PLANE_NEAR);
-			shadow_cam.getAgentPlane(LLCamera::AGENT_PLANE_NEAR).set(shadow_near_clip);
-
-			//translate and scale to from [-1, 1] to [0, 1]
-			glh::matrix4f trans(0.5f, 0.f, 0.f, 0.5f,
-							0.f, 0.5f, 0.f, 0.5f,
-							0.f, 0.f, 0.5f, 0.5f,
-							0.f, 0.f, 0.f, 1.f);
-
-			glh_set_current_modelview(view[j]);
-			glh_set_current_projection(proj[j]);
-
-			for (U32 i = 0; i < 16; i++)
-			{
-				gGLLastModelView[i] = mShadowModelview[j].m[i];
-				gGLLastProjection[i] = mShadowProjection[j].m[i];
-			}
-
-			mShadowModelview[j] = view[j];
-			mShadowProjection[j] = proj[j];
-
-	
-			mSunShadowMatrix[j] = trans*proj[j]*view[j]*inv_view;
-		
-			stop_glerror();
-
-			mShadow[j].bindTarget();
-			mShadow[j].getViewport(gGLViewport);
-			mShadow[j].clear();
-		
-			{
-				static LLCullResult result[4];
-
-				//LLGLEnable enable(GL_DEPTH_CLAMP_NV);
-				renderShadow(view[j], proj[j], shadow_cam, result[j], TRUE);
-			}
-
-			mShadow[j].flush();
- 
-			if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
-			{
-				LLViewerCamera::updateFrustumPlanes(shadow_cam, FALSE, FALSE, TRUE);
-				mShadowCamera[j+4] = shadow_cam;
-			}
-		}
-	}
-
-	
-	//hack to disable projector shadows 
-	bool gen_shadow = RenderShadowDetail > 1;
-
-	if (gen_shadow)
-	{
-		F32 fade_amt = gFrameIntervalSeconds * llmax(LLViewerCamera::getInstance()->getVelocityStat()->getCurrentPerSec(), 1.f);
-
-		//update shadow targets
-		for (U32 i = 0; i < 2; i++)
-		{ //for each current shadow
-			LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_SHADOW4+i;
-
-			if (mShadowSpotLight[i].notNull() && 
-				(mShadowSpotLight[i] == mTargetShadowSpotLight[0] ||
-				mShadowSpotLight[i] == mTargetShadowSpotLight[1]))
-			{ //keep this spotlight
-				mSpotLightFade[i] = llmin(mSpotLightFade[i]+fade_amt, 1.f);
-			}
-			else
-			{ //fade out this light
-				mSpotLightFade[i] = llmax(mSpotLightFade[i]-fade_amt, 0.f);
-				
-				if (mSpotLightFade[i] == 0.f || mShadowSpotLight[i].isNull())
-				{ //faded out, grab one of the pending spots (whichever one isn't already taken)
-					if (mTargetShadowSpotLight[0] != mShadowSpotLight[(i+1)%2])
-					{
-						mShadowSpotLight[i] = mTargetShadowSpotLight[0];
-					}
-					else
-					{
-						mShadowSpotLight[i] = mTargetShadowSpotLight[1];
-					}
-				}
-			}
-		}
-
-		for (S32 i = 0; i < 2; i++)
-		{
-			glh_set_current_modelview(saved_view);
-			glh_set_current_projection(saved_proj);
-
-			if (mShadowSpotLight[i].isNull())
-			{
-				continue;
-			}
-
-			LLVOVolume* volume = mShadowSpotLight[i]->getVOVolume();
-
-			if (!volume)
-			{
-				mShadowSpotLight[i] = NULL;
-				continue;
-			}
-
-			LLDrawable* drawable = mShadowSpotLight[i];
-
-			LLVector3 params = volume->getSpotLightParams();
-			F32 fov = params.mV[0];
-
-			//get agent->light space matrix (modelview)
-			LLVector3 center = drawable->getPositionAgent();
-			LLQuaternion quat = volume->getRenderRotation();
-
-			//get near clip plane
-			LLVector3 scale = volume->getScale();
-			LLVector3 at_axis(0,0,-scale.mV[2]*0.5f);
-			at_axis *= quat;
-
-			LLVector3 np = center+at_axis;
-			at_axis.normVec();
-
-			//get origin that has given fov for plane np, at_axis, and given scale
-			F32 dist = (scale.mV[1]*0.5f)/tanf(fov*0.5f);
-
-			LLVector3 origin = np - at_axis*dist;
-
-			LLMatrix4 mat(quat, LLVector4(origin, 1.f));
-
-			view[i+4] = glh::matrix4f((F32*) mat.mMatrix);
-
-			view[i+4] = view[i+4].inverse();
-
-			//get perspective matrix
-			F32 near_clip = dist+0.01f;
-			F32 width = scale.mV[VX];
-			F32 height = scale.mV[VY];
-			F32 far_clip = dist+volume->getLightRadius()*1.5f;
-
-			F32 fovy = fov * RAD_TO_DEG;
-			F32 aspect = width/height;
-			
-			proj[i+4] = gl_perspective(fovy, aspect, near_clip, far_clip);
-
-			//translate and scale to from [-1, 1] to [0, 1]
-			glh::matrix4f trans(0.5f, 0.f, 0.f, 0.5f,
-							0.f, 0.5f, 0.f, 0.5f,
-							0.f, 0.f, 0.5f, 0.5f,
-							0.f, 0.f, 0.f, 1.f);
-
-			glh_set_current_modelview(view[i+4]);
-			glh_set_current_projection(proj[i+4]);
-
-			mSunShadowMatrix[i+4] = trans*proj[i+4]*view[i+4]*inv_view;
-			
-			for (U32 j = 0; j < 16; j++)
-			{
-				gGLLastModelView[j] = mShadowModelview[i+4].m[j];
-				gGLLastProjection[j] = mShadowProjection[i+4].m[j];
-			}
-
-			mShadowModelview[i+4] = view[i+4];
-			mShadowProjection[i+4] = proj[i+4];
-
-			LLCamera shadow_cam = camera;
-			shadow_cam.setFar(far_clip);
-			shadow_cam.setOrigin(origin);
-
-			LLViewerCamera::updateFrustumPlanes(shadow_cam, FALSE, FALSE, TRUE);
-
-			stop_glerror();
-
-			mShadow[i+4].bindTarget();
-			mShadow[i+4].getViewport(gGLViewport);
-			mShadow[i+4].clear();
-
-			static LLCullResult result[2];
-
-			LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_SHADOW0+i+4;
-
-			renderShadow(view[i+4], proj[i+4], shadow_cam, result[i], FALSE, FALSE);
-
-			mShadow[i+4].flush();
- 		}
-	}
-	else
-	{ //no spotlight shadows
-		mShadowSpotLight[0] = mShadowSpotLight[1] = NULL;
-	}
-
-
-	if (!CameraOffset)
-	{
-		glh_set_current_modelview(saved_view);
-		glh_set_current_projection(saved_proj);
-	}
-	else
-	{
-		glh_set_current_modelview(view[1]);
-		glh_set_current_projection(proj[1]);
-		gGL.loadMatrix(view[1].m);
-		gGL.matrixMode(LLRender::MM_PROJECTION);
-		gGL.loadMatrix(proj[1].m);
-		gGL.matrixMode(LLRender::MM_MODELVIEW);
-	}
-	gGL.setColorMask(true, false);
-
-	for (U32 i = 0; i < 16; i++)
-	{
-		gGLLastModelView[i] = last_modelview[i];
-		gGLLastProjection[i] = last_projection[i];
-	}
-
-	popRenderTypeMask();
-
-	if (!skip_avatar_update)
-	{
-		gAgentAvatarp->updateAttachmentVisibility(gAgentCamera.getCameraMode());
-	}
-}
-
-void LLPipeline::renderGroups(LLRenderPass* pass, U32 type, U32 mask, BOOL texture)
-{
-	for (LLCullResult::sg_list_t::iterator i = sCull->beginVisibleGroups(); i != sCull->endVisibleGroups(); ++i)
-	{
-		LLSpatialGroup* group = *i;
-		if (!group->isDead() &&
-			(!sUseOcclusion || !group->isOcclusionState(LLSpatialGroup::OCCLUDED)) &&
-			gPipeline.hasRenderType(group->mSpatialPartition->mDrawableType) &&
-			group->mDrawMap.find(type) != group->mDrawMap.end())
-		{
-			pass->renderGroup(group,type,mask,texture);
-		}
-	}
-}
-
-void LLPipeline::generateImpostor(LLVOAvatar* avatar)
-{
-	LLMemType mt_gi(LLMemType::MTYPE_PIPELINE_GENERATE_IMPOSTOR);
-	LLGLState::checkStates();
-	LLGLState::checkTextureChannels();
-	LLGLState::checkClientArrays();
-
-	static LLCullResult result;
-	result.clear();
-	grabReferences(result);
-	
-	if (!avatar || !avatar->mDrawable)
-	{
-		return;
-	}
-
-	assertInitialized();
-
-	BOOL muted = LLMuteList::getInstance()->isMuted(avatar->getID());
-
-	pushRenderTypeMask();
-	
-	if (muted)
-	{
-		andRenderTypeMask(LLPipeline::RENDER_TYPE_AVATAR, END_RENDER_TYPES);
-	}
-	else
-	{
-		andRenderTypeMask(LLPipeline::RENDER_TYPE_VOLUME,
-						LLPipeline::RENDER_TYPE_AVATAR,
-						LLPipeline::RENDER_TYPE_BUMP,
-						LLPipeline::RENDER_TYPE_GRASS,
-						LLPipeline::RENDER_TYPE_SIMPLE,
-						LLPipeline::RENDER_TYPE_FULLBRIGHT,
-						LLPipeline::RENDER_TYPE_ALPHA, 
-						LLPipeline::RENDER_TYPE_INVISIBLE,
-						LLPipeline::RENDER_TYPE_PASS_SIMPLE,
-						LLPipeline::RENDER_TYPE_PASS_ALPHA,
-						LLPipeline::RENDER_TYPE_PASS_ALPHA_MASK,
-						LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT,
-						LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK,
-						LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_SHINY,
-						LLPipeline::RENDER_TYPE_PASS_SHINY,
-						LLPipeline::RENDER_TYPE_PASS_INVISIBLE,
-						LLPipeline::RENDER_TYPE_PASS_INVISI_SHINY,
-						END_RENDER_TYPES);
-	}
-	
-	S32 occlusion = sUseOcclusion;
-	sUseOcclusion = 0;
-	sReflectionRender = sRenderDeferred ? FALSE : TRUE;
-	sShadowRender = TRUE;
-	sImpostorRender = TRUE;
-
-	LLViewerCamera* viewer_camera = LLViewerCamera::getInstance();
-	markVisible(avatar->mDrawable, *viewer_camera);
-	LLVOAvatar::sUseImpostors = FALSE;
-
-	LLVOAvatar::attachment_map_t::iterator iter;
-	for (iter = avatar->mAttachmentPoints.begin();
-		iter != avatar->mAttachmentPoints.end();
-		++iter)
-	{
-		LLViewerJointAttachment *attachment = iter->second;
-		for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
-			 attachment_iter != attachment->mAttachedObjects.end();
-			 ++attachment_iter)
-		{
-			if (LLViewerObject* attached_object = (*attachment_iter))
-			{
-				markVisible(attached_object->mDrawable->getSpatialBridge(), *viewer_camera);
-			}
-		}
-	}
-
-	stateSort(*LLViewerCamera::getInstance(), result);
-	
-	const LLVector4a* ext = avatar->mDrawable->getSpatialExtents();
-	LLVector3 pos(avatar->getRenderPosition()+avatar->getImpostorOffset());
-
-	LLCamera camera = *viewer_camera;
-
-	camera.lookAt(viewer_camera->getOrigin(), pos, viewer_camera->getUpAxis());
-	
-	LLVector2 tdim;
-
-
-	LLVector4a half_height;
-	half_height.setSub(ext[1], ext[0]);
-	half_height.mul(0.5f);
-
-	LLVector4a left;
-	left.load3(camera.getLeftAxis().mV);
-	left.mul(left);
-	left.normalize3fast();
-
-	LLVector4a up;
-	up.load3(camera.getUpAxis().mV);
-	up.mul(up);
-	up.normalize3fast();
-
-	tdim.mV[0] = fabsf(half_height.dot3(left).getF32());
-	tdim.mV[1] = fabsf(half_height.dot3(up).getF32());
-
-	gGL.matrixMode(LLRender::MM_PROJECTION);
-	gGL.pushMatrix();
-	
-	F32 distance = (pos-camera.getOrigin()).length();
-	F32 fov = atanf(tdim.mV[1]/distance)*2.f*RAD_TO_DEG;
-	F32 aspect = tdim.mV[0]/tdim.mV[1];
-	glh::matrix4f persp = gl_perspective(fov, aspect, 1.f, 256.f);
-	glh_set_current_projection(persp);
-	gGL.loadMatrix(persp.m);
-
-	gGL.matrixMode(LLRender::MM_MODELVIEW);
-	gGL.pushMatrix();
-	glh::matrix4f mat;
-	camera.getOpenGLTransform(mat.m);
-
-	mat = glh::matrix4f((GLfloat*) OGL_TO_CFR_ROTATION) * mat;
-
-	gGL.loadMatrix(mat.m);
-	glh_set_current_modelview(mat);
-
-	glClearColor(0.0f,0.0f,0.0f,0.0f);
-	gGL.setColorMask(true, true);
-	
-	// get the number of pixels per angle
-	F32 pa = gViewerWindow->getWindowHeightRaw() / (RAD_TO_DEG * viewer_camera->getView());
-
-	//get resolution based on angle width and height of impostor (double desired resolution to prevent aliasing)
-	U32 resY = llmin(nhpo2((U32) (fov*pa)), (U32) 512);
-	U32 resX = llmin(nhpo2((U32) (atanf(tdim.mV[0]/distance)*2.f*RAD_TO_DEG*pa)), (U32) 512);
-
-	if (!avatar->mImpostor.isComplete() || resX != avatar->mImpostor.getWidth() ||
-		resY != avatar->mImpostor.getHeight())
-	{
-		avatar->mImpostor.allocate(resX,resY,GL_RGBA,TRUE,FALSE);
-		
-		if (LLPipeline::sRenderDeferred)
-		{
-			addDeferredAttachments(avatar->mImpostor);
-		}
-		
-		gGL.getTexUnit(0)->bind(&avatar->mImpostor);
-		gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
-		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-	}
-
-	avatar->mImpostor.bindTarget();
-
-	if (LLPipeline::sRenderDeferred)
-	{
-		avatar->mImpostor.clear();
-		renderGeomDeferred(camera);
-		renderGeomPostDeferred(camera);
-	}
-	else
-	{
-		LLGLEnable scissor(GL_SCISSOR_TEST);
-		glScissor(0, 0, resX, resY);
-		avatar->mImpostor.clear();
-		renderGeom(camera);
-	}
-	
-	{ //create alpha mask based on depth buffer (grey out if muted)
-		if (LLPipeline::sRenderDeferred)
-		{
-			GLuint buff = GL_COLOR_ATTACHMENT0;
-			glDrawBuffersARB(1, &buff);
-		}
-
-		LLGLDisable blend(GL_BLEND);
-
-		if (muted)
-		{
-			gGL.setColorMask(true, true);
-		}
-		else
-		{
-			gGL.setColorMask(false, true);
-		}
-		
-		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-
-		LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_GREATER);
-
-		gGL.flush();
-
-		gGL.pushMatrix();
-		gGL.loadIdentity();
-		gGL.matrixMode(LLRender::MM_PROJECTION);
-		gGL.pushMatrix();
-		gGL.loadIdentity();
-
-		static const F32 clip_plane = 0.99999f;
-
-		if (LLGLSLShader::sNoFixedFunction)
-		{
-			gUIProgram.bind();
-		}
-
-		gGL.color4ub(64,64,64,255);
-		gGL.begin(LLRender::QUADS);
-		gGL.vertex3f(-1, -1, clip_plane);
-		gGL.vertex3f(1, -1, clip_plane);
-		gGL.vertex3f(1, 1, clip_plane);
-		gGL.vertex3f(-1, 1, clip_plane);
-		gGL.end();
-		gGL.flush();
-
-		if (LLGLSLShader::sNoFixedFunction)
-		{
-			gUIProgram.unbind();
-		}
-
-		gGL.popMatrix();
-		gGL.matrixMode(LLRender::MM_MODELVIEW);
-		gGL.popMatrix();
-	}
-
-	avatar->mImpostor.flush();
-
-	avatar->setImpostorDim(tdim);
-
-	LLVOAvatar::sUseImpostors = TRUE;
-	sUseOcclusion = occlusion;
-	sReflectionRender = FALSE;
-	sImpostorRender = FALSE;
-	sShadowRender = FALSE;
-	popRenderTypeMask();
-
-	gGL.matrixMode(LLRender::MM_PROJECTION);
-	gGL.popMatrix();
-	gGL.matrixMode(LLRender::MM_MODELVIEW);
-	gGL.popMatrix();
-
-	avatar->mNeedsImpostorUpdate = FALSE;
-	avatar->cacheImpostorValues();
-
-	LLVertexBuffer::unbind();
-	LLGLState::checkStates();
-	LLGLState::checkTextureChannels();
-	LLGLState::checkClientArrays();
-}
-
-BOOL LLPipeline::hasRenderBatches(const U32 type) const
-{
-	return sCull->getRenderMapSize(type) > 0;
-}
-
-LLCullResult::drawinfo_list_t::iterator LLPipeline::beginRenderMap(U32 type)
-{
-	return sCull->beginRenderMap(type);
-}
-
-LLCullResult::drawinfo_list_t::iterator LLPipeline::endRenderMap(U32 type)
-{
-	return sCull->endRenderMap(type);
-}
-
-LLCullResult::sg_list_t::iterator LLPipeline::beginAlphaGroups()
-{
-	return sCull->beginAlphaGroups();
-}
-
-LLCullResult::sg_list_t::iterator LLPipeline::endAlphaGroups()
-{
-	return sCull->endAlphaGroups();
-}
-
-BOOL LLPipeline::hasRenderType(const U32 type) const
-{
-    // STORM-365 : LLViewerJointAttachment::setAttachmentVisibility() is setting type to 0 to actually mean "do not render"
-    // We then need to test that value here and return FALSE to prevent attachment to render (in mouselook for instance)
-    // TODO: reintroduce RENDER_TYPE_NONE in LLRenderTypeMask and initialize its mRenderTypeEnabled[RENDER_TYPE_NONE] to FALSE explicitely
-	return (type == 0 ? FALSE : mRenderTypeEnabled[type]);
-}
-
-void LLPipeline::setRenderTypeMask(U32 type, ...)
-{
-	va_list args;
-
-	va_start(args, type);
-	while (type < END_RENDER_TYPES)
-	{
-		mRenderTypeEnabled[type] = TRUE;
-		type = va_arg(args, U32);
-	}
-	va_end(args);
-
-	if (type > END_RENDER_TYPES)
-	{
-		llerrs << "Invalid render type." << llendl;
-	}
-}
-
-BOOL LLPipeline::hasAnyRenderType(U32 type, ...) const
-{
-	va_list args;
-
-	va_start(args, type);
-	while (type < END_RENDER_TYPES)
-	{
-		if (mRenderTypeEnabled[type])
-		{
-			return TRUE;
-		}
-		type = va_arg(args, U32);
-	}
-	va_end(args);
-
-	if (type > END_RENDER_TYPES)
-	{
-		llerrs << "Invalid render type." << llendl;
-	}
-
-	return FALSE;
-}
-
-void LLPipeline::pushRenderTypeMask()
-{
-	std::string cur_mask;
-	cur_mask.assign((const char*) mRenderTypeEnabled, sizeof(mRenderTypeEnabled));
-	mRenderTypeEnableStack.push(cur_mask);
-}
-
-void LLPipeline::popRenderTypeMask()
-{
-	if (mRenderTypeEnableStack.empty())
-	{
-		llerrs << "Depleted render type stack." << llendl;
-	}
-
-	memcpy(mRenderTypeEnabled, mRenderTypeEnableStack.top().data(), sizeof(mRenderTypeEnabled));
-	mRenderTypeEnableStack.pop();
-}
-
-void LLPipeline::andRenderTypeMask(U32 type, ...)
-{
-	va_list args;
-
-	BOOL tmp[NUM_RENDER_TYPES];
-	for (U32 i = 0; i < NUM_RENDER_TYPES; ++i)
-	{
-		tmp[i] = FALSE;
-	}
-
-	va_start(args, type);
-	while (type < END_RENDER_TYPES)
-	{
-		if (mRenderTypeEnabled[type]) 
-		{
-			tmp[type] = TRUE;
-		}
-
-		type = va_arg(args, U32);
-	}
-	va_end(args);
-
-	if (type > END_RENDER_TYPES)
-	{
-		llerrs << "Invalid render type." << llendl;
-	}
-
-	for (U32 i = 0; i < LLPipeline::NUM_RENDER_TYPES; ++i)
-	{
-		mRenderTypeEnabled[i] = tmp[i];
-	}
-
-}
-
-void LLPipeline::clearRenderTypeMask(U32 type, ...)
-{
-	va_list args;
-
-	va_start(args, type);
-	while (type < END_RENDER_TYPES)
-	{
-		mRenderTypeEnabled[type] = FALSE;
-		
-		type = va_arg(args, U32);
-	}
-	va_end(args);
-
-	if (type > END_RENDER_TYPES)
-	{
-		llerrs << "Invalid render type." << llendl;
-	}
-}
-
-void LLPipeline::addDebugBlip(const LLVector3& position, const LLColor4& color)
-{
-	DebugBlip blip(position, color);
-	mDebugBlips.push_back(blip);
-}
-
+/** 
+ * @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$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "pipeline.h"
+
+// library includes
+#include "llaudioengine.h" // For debugging.
+#include "imageids.h"
+#include "llerror.h"
+#include "llviewercontrol.h"
+#include "llfasttimer.h"
+#include "llfontgl.h"
+#include "llmemtype.h"
+#include "llnamevalue.h"
+#include "llpointer.h"
+#include "llprimitive.h"
+#include "llvolume.h"
+#include "material_codes.h"
+#include "timing.h"
+#include "v3color.h"
+#include "llui.h" 
+#include "llglheaders.h"
+#include "llrender.h"
+#include "llwindow.h"	// swapBuffers()
+
+// newview includes
+#include "llagent.h"
+#include "llagentcamera.h"
+#include "lldrawable.h"
+#include "lldrawpoolalpha.h"
+#include "lldrawpoolavatar.h"
+#include "lldrawpoolground.h"
+#include "lldrawpoolbump.h"
+#include "lldrawpooltree.h"
+#include "lldrawpoolwater.h"
+#include "llface.h"
+#include "llfeaturemanager.h"
+#include "llfloatertelehub.h"
+#include "llfloaterreg.h"
+#include "llgldbg.h"
+#include "llhudmanager.h"
+#include "llhudnametag.h"
+#include "llhudtext.h"
+#include "lllightconstants.h"
+#include "llmeshrepository.h"
+#include "llresmgr.h"
+#include "llselectmgr.h"
+#include "llsky.h"
+#include "lltracker.h"
+#include "lltool.h"
+#include "lltoolmgr.h"
+#include "llviewercamera.h"
+#include "llviewermediafocus.h"
+#include "llviewertexturelist.h"
+#include "llviewerobject.h"
+#include "llviewerobjectlist.h"
+#include "llviewerparcelmgr.h"
+#include "llviewerregion.h" // for audio debugging.
+#include "llviewerwindow.h" // For getSpinAxis
+#include "llvoavatarself.h"
+#include "llvoground.h"
+#include "llvosky.h"
+#include "llvotree.h"
+#include "llvovolume.h"
+#include "llvosurfacepatch.h"
+#include "llvowater.h"
+#include "llvotree.h"
+#include "llvopartgroup.h"
+#include "llworld.h"
+#include "llcubemap.h"
+#include "llviewershadermgr.h"
+#include "llviewerstats.h"
+#include "llviewerjoystick.h"
+#include "llviewerdisplay.h"
+#include "llwlparammanager.h"
+#include "llwaterparammanager.h"
+#include "llspatialpartition.h"
+#include "llmutelist.h"
+#include "lltoolpie.h"
+#include "llcurl.h"
+#include "llnotifications.h"
+#include "LLPathingLib.h"
+
+#ifdef _DEBUG
+// Debug indices is disabled for now for debug performance - djs 4/24/02
+//#define DEBUG_INDICES
+#else
+//#define DEBUG_INDICES
+#endif
+
+//cached settings
+BOOL LLPipeline::RenderAvatarVP;
+BOOL LLPipeline::VertexShaderEnable;
+BOOL LLPipeline::WindLightUseAtmosShaders;
+BOOL LLPipeline::RenderDeferred;
+F32 LLPipeline::RenderDeferredSunWash;
+U32 LLPipeline::RenderFSAASamples;
+U32 LLPipeline::RenderResolutionDivisor;
+BOOL LLPipeline::RenderUIBuffer;
+S32 LLPipeline::RenderShadowDetail;
+BOOL LLPipeline::RenderDeferredSSAO;
+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;
+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;
+
+const F32 BACKLIGHT_DAY_MAGNITUDE_AVATAR = 0.2f;
+const F32 BACKLIGHT_NIGHT_MAGNITUDE_AVATAR = 0.1f;
+const F32 BACKLIGHT_DAY_MAGNITUDE_OBJECT = 0.1f;
+const F32 BACKLIGHT_NIGHT_MAGNITUDE_OBJECT = 0.08f;
+const S32 MAX_OFFSCREEN_GEOMETRY_CHANGES_PER_FRAME = 10;
+const U32 REFLECTION_MAP_RES = 128;
+const U32 DEFERRED_VB_MASK = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_TEXCOORD1;
+// Max number of occluders to search for. JC
+const S32 MAX_OCCLUDER_COUNT = 2;
+
+extern S32 gBoxFrame;
+//extern BOOL gHideSelectedObjects;
+extern BOOL gDisplaySwapBuffers;
+extern BOOL gDebugGL;
+
+// hack counter for rendering a fixed number of frames after toggling
+// fullscreen to work around DEV-5361
+static S32 sDelayedVBOEnable = 0;
+
+BOOL	gAvatarBacklight = FALSE;
+
+BOOL	gDebugPipeline = FALSE;
+LLPipeline gPipeline;
+const LLMatrix4* gGLLastMatrix = NULL;
+
+LLFastTimer::DeclareTimer FTM_RENDER_GEOMETRY("Geometry");
+LLFastTimer::DeclareTimer FTM_RENDER_GRASS("Grass");
+LLFastTimer::DeclareTimer FTM_RENDER_INVISIBLE("Invisible");
+LLFastTimer::DeclareTimer FTM_RENDER_OCCLUSION("Occlusion");
+LLFastTimer::DeclareTimer FTM_RENDER_SHINY("Shiny");
+LLFastTimer::DeclareTimer FTM_RENDER_SIMPLE("Simple");
+LLFastTimer::DeclareTimer FTM_RENDER_TERRAIN("Terrain");
+LLFastTimer::DeclareTimer FTM_RENDER_TREES("Trees");
+LLFastTimer::DeclareTimer FTM_RENDER_UI("UI");
+LLFastTimer::DeclareTimer FTM_RENDER_WATER("Water");
+LLFastTimer::DeclareTimer FTM_RENDER_WL_SKY("Windlight Sky");
+LLFastTimer::DeclareTimer FTM_RENDER_ALPHA("Alpha Objects");
+LLFastTimer::DeclareTimer FTM_RENDER_CHARACTERS("Avatars");
+LLFastTimer::DeclareTimer FTM_RENDER_BUMP("Bump");
+LLFastTimer::DeclareTimer FTM_RENDER_FULLBRIGHT("Fullbright");
+LLFastTimer::DeclareTimer FTM_RENDER_GLOW("Glow");
+LLFastTimer::DeclareTimer FTM_GEO_UPDATE("Geo Update");
+LLFastTimer::DeclareTimer FTM_POOLRENDER("RenderPool");
+LLFastTimer::DeclareTimer FTM_POOLS("Pools");
+LLFastTimer::DeclareTimer FTM_RENDER_BLOOM_FBO("First FBO");
+LLFastTimer::DeclareTimer FTM_STATESORT("Sort Draw State");
+LLFastTimer::DeclareTimer FTM_PIPELINE("Pipeline");
+LLFastTimer::DeclareTimer FTM_CLIENT_COPY("Client Copy");
+LLFastTimer::DeclareTimer FTM_RENDER_DEFERRED("Deferred Shading");
+
+
+static LLFastTimer::DeclareTimer FTM_STATESORT_DRAWABLE("Sort Drawables");
+static LLFastTimer::DeclareTimer FTM_STATESORT_POSTSORT("Post Sort");
+
+//----------------------------------------
+std::string gPoolNames[] = 
+{
+	// Correspond to LLDrawpool enum render type
+	"NONE",
+	"POOL_SIMPLE",
+	"POOL_GROUND",
+	"POOL_FULLBRIGHT",
+	"POOL_BUMP",
+	"POOL_TERRAIN,"	
+	"POOL_SKY",
+	"POOL_WL_SKY",
+	"POOL_TREE",
+	"POOL_GRASS",
+	"POOL_INVISIBLE",
+	"POOL_AVATAR",
+	"POOL_VOIDWATER",
+	"POOL_WATER",
+	"POOL_GLOW",
+	"POOL_ALPHA"
+};
+
+void drawBox(const LLVector3& c, const LLVector3& r);
+void drawBoxOutline(const LLVector3& pos, const LLVector3& size);
+U32 nhpo2(U32 v);
+
+glh::matrix4f glh_copy_matrix(F32* src)
+{
+	glh::matrix4f ret;
+	ret.set_value(src);
+	return ret;
+}
+
+glh::matrix4f glh_get_current_modelview()
+{
+	return glh_copy_matrix(gGLModelView);
+}
+
+glh::matrix4f glh_get_current_projection()
+{
+	return glh_copy_matrix(gGLProjection);
+}
+
+glh::matrix4f glh_get_last_modelview()
+{
+	return glh_copy_matrix(gGLLastModelView);
+}
+
+glh::matrix4f glh_get_last_projection()
+{
+	return glh_copy_matrix(gGLLastProjection);
+}
+
+void glh_copy_matrix(const glh::matrix4f& src, F32* dst)
+{
+	for (U32 i = 0; i < 16; i++)
+	{
+		dst[i] = src.m[i];
+	}
+}
+
+void glh_set_current_modelview(const glh::matrix4f& mat)
+{
+	glh_copy_matrix(mat, gGLModelView);
+}
+
+void glh_set_current_projection(glh::matrix4f& mat)
+{
+	glh_copy_matrix(mat, gGLProjection);
+}
+
+glh::matrix4f gl_ortho(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat znear, GLfloat zfar)
+{
+	glh::matrix4f ret(
+		2.f/(right-left), 0.f, 0.f, -(right+left)/(right-left),
+		0.f, 2.f/(top-bottom), 0.f, -(top+bottom)/(top-bottom),
+		0.f, 0.f, -2.f/(zfar-znear),  -(zfar+znear)/(zfar-znear),
+		0.f, 0.f, 0.f, 1.f);
+
+	return ret;
+}
+
+void display_update_camera();
+//----------------------------------------
+
+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;
+BOOL	LLPipeline::sForceOldBakedUpload = FALSE;
+S32		LLPipeline::sUseOcclusion = 0;
+BOOL	LLPipeline::sDelayVBUpdate = TRUE;
+BOOL	LLPipeline::sAutoMaskAlphaDeferred = TRUE;
+BOOL	LLPipeline::sAutoMaskAlphaNonDeferred = FALSE;
+BOOL	LLPipeline::sDisableShaders = FALSE;
+BOOL	LLPipeline::sRenderBump = TRUE;
+BOOL	LLPipeline::sBakeSunlight = FALSE;
+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::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;
+
+
+static LLCullResult* sCull = NULL;
+
+static const U32 gl_cube_face[] = 
+{
+	GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB,
+	GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB,
+	GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB,
+	GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB,
+	GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB,
+	GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB,
+};
+
+void validate_framebuffer_object();
+
+
+bool addDeferredAttachments(LLRenderTarget& target)
+{
+	return target.addColorAttachment(GL_RGBA) && //specular
+			target.addColorAttachment(GL_RGBA); //normal+z	
+}
+
+LLPipeline::LLPipeline() :
+	mBackfaceCull(FALSE),
+	mBatchCount(0),
+	mMatrixOpCount(0),
+	mTextureMatrixOps(0),
+	mMaxBatchSize(0),
+	mMinBatchSize(0),
+	mMeanBatchSize(0),
+	mTrianglesDrawn(0),
+	mNumVisibleNodes(0),
+	mVerticesRelit(0),
+	mLightingChanges(0),
+	mGeometryChanges(0),
+	mNumVisibleFaces(0),
+
+	mInitialized(FALSE),
+	mVertexShadersEnabled(FALSE),
+	mVertexShadersLoaded(0),
+	mRenderDebugFeatureMask(0),
+	mRenderDebugMask(0),
+	mOldRenderDebugMask(0),
+	mGroupQ1Locked(false),
+	mGroupQ2Locked(false),
+	mLastRebuildPool(NULL),
+	mAlphaPool(NULL),
+	mSkyPool(NULL),
+	mTerrainPool(NULL),
+	mWaterPool(NULL),
+	mGroundPool(NULL),
+	mSimplePool(NULL),
+	mFullbrightPool(NULL),
+	mInvisiblePool(NULL),
+	mGlowPool(NULL),
+	mBumpPool(NULL),
+	mWLSkyPool(NULL),
+	mLightMask(0),
+	mLightMovingMask(0),
+	mLightingDetail(0),
+	mScreenWidth(0),
+	mScreenHeight(0)
+{
+	mNoiseMap = 0;
+	mTrueNoiseMap = 0;
+	mLightFunc = 0;
+}
+
+void LLPipeline::init()
+{
+	LLMemType mt(LLMemType::MTYPE_PIPELINE_INIT);
+
+	refreshCachedSettings();
+
+	gOctreeMaxCapacity = gSavedSettings.getU32("OctreeMaxNodeCapacity");
+	sDynamicLOD = gSavedSettings.getBOOL("RenderDynamicLOD");
+	sRenderBump = gSavedSettings.getBOOL("RenderObjectBump");
+	sUseTriStrips = gSavedSettings.getBOOL("RenderUseTriStrips");
+	LLVertexBuffer::sUseStreamDraw = gSavedSettings.getBOOL("RenderUseStreamVBO");
+	LLVertexBuffer::sUseVAO = gSavedSettings.getBOOL("RenderUseVAO");
+	LLVertexBuffer::sPreferStreamDraw = gSavedSettings.getBOOL("RenderPreferStreamDraw");
+	sRenderAttachedLights = gSavedSettings.getBOOL("RenderAttachedLights");
+	sRenderAttachedParticles = gSavedSettings.getBOOL("RenderAttachedParticles");
+
+	mInitialized = TRUE;
+	
+	stop_glerror();
+
+	//create render pass pools
+	getPool(LLDrawPool::POOL_ALPHA);
+	getPool(LLDrawPool::POOL_SIMPLE);
+	getPool(LLDrawPool::POOL_GRASS);
+	getPool(LLDrawPool::POOL_FULLBRIGHT);
+	getPool(LLDrawPool::POOL_INVISIBLE);
+	getPool(LLDrawPool::POOL_BUMP);
+	getPool(LLDrawPool::POOL_GLOW);
+
+	LLViewerStats::getInstance()->mTrianglesDrawnStat.reset();
+	resetFrameStats();
+
+	for (U32 i = 0; i < NUM_RENDER_TYPES; ++i)
+	{
+		mRenderTypeEnabled[i] = TRUE; //all rendering types start enabled
+	}
+
+	mRenderDebugFeatureMask = 0xffffffff; // All debugging features on
+	mRenderDebugMask = 0;	// All debug starts off
+
+	// Don't turn on ground when this is set
+	// Mac Books with intel 950s need this
+	if(!gSavedSettings.getBOOL("RenderGround"))
+	{
+		toggleRenderType(RENDER_TYPE_GROUND);
+	}
+
+	// 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;
+
+	stop_glerror();
+	
+	// Enable features
+		
+	LLViewerShaderMgr::instance()->setShaders();
+
+	stop_glerror();
+
+	for (U32 i = 0; i < 2; ++i)
+	{
+		mSpotLightFade[i] = 1.f;
+	}
+
+	mDeferredVB = new LLVertexBuffer(DEFERRED_VB_MASK, 0);
+	mDeferredVB->allocateBuffer(8, 0, true);
+	setLightingDetail(-1);
+	
+	//
+	// Update all settings to trigger a cached settings refresh
+	//
+
+	gSavedSettings.getControl("RenderAutoMaskAlphaDeferred")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("RenderAutoMaskAlphaNonDeferred")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("RenderUseFarClip")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("RenderAvatarMaxVisible")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("RenderDelayVBUpdate")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	
+	gSavedSettings.getControl("UseOcclusion")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	
+	gSavedSettings.getControl("VertexShaderEnable")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("RenderAvatarVP")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("WindLightUseAtmosShaders")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("RenderDeferred")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("RenderDeferredSunWash")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("RenderFSAASamples")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("RenderResolutionDivisor")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("RenderUIBuffer")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("RenderShadowDetail")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("RenderDeferredSSAO")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("RenderShadowResolutionScale")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("RenderLocalLights")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("RenderDelayCreation")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("RenderAnimateRes")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("FreezeTime")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("DebugBeaconLineWidth")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("RenderHighlightBrightness")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("RenderHighlightColor")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("RenderHighlightThickness")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("RenderSpotLightsInNondeferred")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("PreviewAmbientColor")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("PreviewDiffuse0")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("PreviewSpecular0")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("PreviewDiffuse1")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("PreviewSpecular1")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("PreviewDiffuse2")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("PreviewSpecular2")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("PreviewDirection0")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("PreviewDirection1")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("PreviewDirection2")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("RenderGlowMinLuminance")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("RenderGlowMaxExtractAlpha")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("RenderGlowWarmthAmount")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("RenderGlowLumWeights")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("RenderGlowWarmthWeights")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("RenderGlowResolutionPow")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("RenderGlowIterations")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("RenderGlowWidth")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("RenderGlowStrength")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("RenderDepthOfField")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("CameraFocusTransitionTime")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("CameraFNumber")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("CameraFocalLength")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("CameraFieldOfView")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("RenderShadowNoise")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("RenderShadowBlurSize")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("RenderSSAOScale")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("RenderSSAOMaxScale")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("RenderSSAOFactor")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("RenderSSAOEffect")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("RenderShadowOffsetError")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("RenderShadowBiasError")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("RenderShadowOffset")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("RenderShadowBias")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("RenderSpotShadowOffset")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("RenderSpotShadowBias")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("RenderEdgeDepthCutoff")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("RenderEdgeNormCutoff")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("RenderShadowGaussian")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("RenderShadowBlurDistFactor")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("RenderDeferredAtmospheric")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("RenderReflectionDetail")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("RenderHighlightFadeTime")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("RenderShadowClipPlanes")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("RenderShadowOrthoClipPlanes")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("RenderShadowNearDist")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("RenderFarClip")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("RenderShadowSplitExponent")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("RenderShadowErrorCutoff")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("RenderShadowFOVCutoff")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("CameraOffset")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("CameraMaxCoF")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+	gSavedSettings.getControl("CameraDoFResScale")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+}
+
+LLPipeline::~LLPipeline()
+{
+
+}
+
+void LLPipeline::cleanup()
+{
+	assertInitialized();
+
+	mGroupQ1.clear() ;
+	mGroupQ2.clear() ;
+
+	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
+		{
+			mPools.erase(curiter);
+			removeFromQuickLookup( poolp );
+			delete poolp;
+		}
+	}
+	
+	if (!mTerrainPools.empty())
+	{
+		llwarns << "Terrain Pools not cleaned up" << llendl;
+	}
+	if (!mTreePools.empty())
+	{
+		llwarns << "Tree Pools not cleaned up" << llendl;
+	}
+		
+	delete mAlphaPool;
+	mAlphaPool = NULL;
+	delete mSkyPool;
+	mSkyPool = NULL;
+	delete mTerrainPool;
+	mTerrainPool = NULL;
+	delete mWaterPool;
+	mWaterPool = NULL;
+	delete mGroundPool;
+	mGroundPool = NULL;
+	delete mSimplePool;
+	mSimplePool = NULL;
+	delete mFullbrightPool;
+	mFullbrightPool = NULL;
+	delete mInvisiblePool;
+	mInvisiblePool = NULL;
+	delete mGlowPool;
+	mGlowPool = NULL;
+	delete mBumpPool;
+	mBumpPool = NULL;
+	// don't delete wl sky pool it was handled above in the for loop
+	//delete mWLSkyPool;
+	mWLSkyPool = NULL;
+
+	releaseGLBuffers();
+
+	mFaceSelectImagep = NULL;
+
+	mMovedBridge.clear();
+
+	mInitialized = FALSE;
+
+	mDeferredVB = NULL;
+}
+
+//============================================================================
+
+void LLPipeline::destroyGL() 
+{
+	stop_glerror();
+	unloadShaders();
+	mHighlightFaces.clear();
+	
+	resetDrawOrders();
+
+	resetVertexBuffers();
+
+	releaseGLBuffers();
+
+	if (LLVertexBuffer::sEnableVBOs)
+	{
+		// render 30 frames after switching to work around DEV-5361
+		sDelayedVBOEnable = 30;
+		LLVertexBuffer::sEnableVBOs = FALSE;
+	}
+}
+
+static LLFastTimer::DeclareTimer FTM_RESIZE_SCREEN_TEXTURE("Resize Screen Texture");
+
+//static
+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()
+{
+	LLFastTimer ft(FTM_RESIZE_SCREEN_TEXTURE);
+	if (gPipeline.canUseVertexShaders() && assertInitialized())
+	{
+		GLuint resX = gViewerWindow->getWorldViewWidthRaw();
+		GLuint resY = gViewerWindow->getWorldViewHeightRaw();
+	
+		allocateScreenBuffer(resX,resY);
+	}
+}
+
+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_RECT_TEXTURE, FALSE);
+	}
+}
+
+void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY)
+{
+	refreshCachedSettings();
+	U32 samples = RenderFSAASamples;
+
+	//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
+
+	if (!allocateScreenBuffer(resX, resY, samples))
+	{
+		releaseScreenBuffers();
+		//reduce number of samples 
+		while (samples > 0)
+		{
+			samples /= 2;
+			if (allocateScreenBuffer(resX, resY, samples))
+			{ //success
+				return;
+			}
+			releaseScreenBuffers();
+		}
+
+		samples = 0;
+
+		//reduce resolution
+		while (resY > 0 && resX > 0)
+		{
+			resY /= 2;
+			if (allocateScreenBuffer(resX, resY, samples))
+			{
+				return;
+			}
+			releaseScreenBuffers();
+
+			resX /= 2;
+			if (allocateScreenBuffer(resX, resY, samples))
+			{
+				return;
+			}
+			releaseScreenBuffers();
+		}
+
+		llwarns << "Unable to allocate screen buffer at any resolution!" << llendl;
+	}
+}
+
+
+bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)
+{
+	refreshCachedSettings();
+
+	// remember these dimensions
+	mScreenWidth = resX;
+	mScreenHeight = resY;
+	
+	U32 res_mod = RenderResolutionDivisor;
+
+	if (res_mod > 1 && res_mod < resX && res_mod < resY)
+	{
+		resX /= res_mod;
+		resY /= res_mod;
+	}
+
+	if (RenderUIBuffer)
+	{
+		if (!mUIScreen.allocate(resX,resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE))
+		{
+			return false;
+		}
+	}	
+
+	if (LLPipeline::sRenderDeferred)
+	{
+		S32 shadow_detail = RenderShadowDetail;
+		BOOL ssao = RenderDeferredSSAO;
+		
+		//allocate deferred rendering color buffers
+		if (!mDeferredScreen.allocate(resX, resY, GL_RGBA, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false;
+		if (!mDeferredDepth.allocate(resX, resY, 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false;
+		if (!addDeferredAttachments(mDeferredScreen)) return false;
+	
+		if (!mScreen.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false;
+		if (samples > 0)
+		{
+			if (!mFXAABuffer.allocate(nhpo2(resX), nhpo2(resY), GL_RGBA, FALSE, FALSE, LLTexUnit::TT_TEXTURE, FALSE, samples)) return false;
+		}
+		else
+		{
+			mFXAABuffer.release();
+		}
+		
+		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_RECT_TEXTURE, FALSE)) return false;
+		}
+		else
+		{
+			mDeferredLight.release();
+		}
+
+		F32 scale = RenderShadowResolutionScale;
+
+		if (shadow_detail > 0)
+		{ //allocate 4 sun shadow maps
+			for (U32 i = 0; i < 4; i++)
+			{
+				if (!mShadow[i].allocate(U32(resX*scale),U32(resY*scale), 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE)) return false;
+			}
+		}
+		else
+		{
+			for (U32 i = 0; i < 4; i++)
+			{
+				mShadow[i].release();
+			}
+		}
+
+		U32 width = nhpo2(U32(resX*scale))/2;
+		U32 height = width;
+
+		if (shadow_detail > 1)
+		{ //allocate two spot shadow maps
+			for (U32 i = 4; i < 6; i++)
+			{
+				if (!mShadow[i].allocate(width, height, 0, TRUE, FALSE)) return false;
+			}
+		}
+		else
+		{
+			for (U32 i = 4; i < 6; i++)
+			{
+				mShadow[i].release();
+			}
+		}
+	}
+	else
+	{
+		mDeferredLight.release();
+				
+		for (U32 i = 0; i < 6; i++)
+		{
+			mShadow[i].release();
+		}
+		mFXAABuffer.release();
+		mScreen.release();
+		mDeferredScreen.release(); //make sure to release any render targets that share a depth buffer with mDeferredScreen first
+		mDeferredDepth.release();
+						
+		if (!mScreen.allocate(resX, resY, GL_RGBA, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE)) return false;		
+	}
+	
+	if (LLPipeline::sRenderDeferred)
+	{ //share depth buffer between deferred targets
+		mDeferredScreen.shareDepthBuffer(mScreen);
+	}
+
+	gGL.getTexUnit(0)->disable();
+
+	stop_glerror();
+
+	return true;
+}
+
+//static
+void LLPipeline::updateRenderDeferred()
+{
+	BOOL deferred = ((RenderDeferred && 
+					 LLRenderTarget::sUseFBO &&
+					 LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred") &&	 
+					 VertexShaderEnable && 
+					 RenderAvatarVP &&
+					 WindLightUseAtmosShaders) ? TRUE : FALSE) &&
+					!gUseWireframe;
+
+	sRenderDeferred = deferred;	
+	if (deferred)
+	{ //must render glow when rendering deferred since post effect pass is needed to present any lighting at all
+		sRenderGlow = TRUE;
+	}
+}
+
+//static
+void LLPipeline::refreshCachedSettings()
+{
+	LLPipeline::sAutoMaskAlphaDeferred = gSavedSettings.getBOOL("RenderAutoMaskAlphaDeferred");
+	LLPipeline::sAutoMaskAlphaNonDeferred = gSavedSettings.getBOOL("RenderAutoMaskAlphaNonDeferred");
+	LLPipeline::sUseFarClip = gSavedSettings.getBOOL("RenderUseFarClip");
+	LLVOAvatar::sMaxVisible = (U32)gSavedSettings.getS32("RenderAvatarMaxVisible");
+	LLPipeline::sDelayVBUpdate = gSavedSettings.getBOOL("RenderDelayVBUpdate");
+
+	LLPipeline::sUseOcclusion = 
+			(!gUseWireframe
+			&& LLFeatureManager::getInstance()->isFeatureAvailable("UseOcclusion") 
+			&& gSavedSettings.getBOOL("UseOcclusion") 
+			&& gGLManager.mHasOcclusionQuery) ? 2 : 0;
+	
+	VertexShaderEnable = gSavedSettings.getBOOL("VertexShaderEnable");
+	RenderAvatarVP = gSavedSettings.getBOOL("RenderAvatarVP");
+	WindLightUseAtmosShaders = gSavedSettings.getBOOL("WindLightUseAtmosShaders");
+	RenderDeferred = gSavedSettings.getBOOL("RenderDeferred");
+	RenderDeferredSunWash = gSavedSettings.getF32("RenderDeferredSunWash");
+	RenderFSAASamples = gSavedSettings.getU32("RenderFSAASamples");
+	RenderResolutionDivisor = gSavedSettings.getU32("RenderResolutionDivisor");
+	RenderUIBuffer = gSavedSettings.getBOOL("RenderUIBuffer");
+	RenderShadowDetail = gSavedSettings.getS32("RenderShadowDetail");
+	RenderDeferredSSAO = gSavedSettings.getBOOL("RenderDeferredSSAO");
+	RenderShadowResolutionScale = gSavedSettings.getF32("RenderShadowResolutionScale");
+	RenderLocalLights = gSavedSettings.getBOOL("RenderLocalLights");
+	RenderDelayCreation = gSavedSettings.getBOOL("RenderDelayCreation");
+	RenderAnimateRes = gSavedSettings.getBOOL("RenderAnimateRes");
+	FreezeTime = gSavedSettings.getBOOL("FreezeTime");
+	DebugBeaconLineWidth = gSavedSettings.getS32("DebugBeaconLineWidth");
+	RenderHighlightBrightness = gSavedSettings.getF32("RenderHighlightBrightness");
+	RenderHighlightColor = gSavedSettings.getColor4("RenderHighlightColor");
+	RenderHighlightThickness = gSavedSettings.getF32("RenderHighlightThickness");
+	RenderSpotLightsInNondeferred = gSavedSettings.getBOOL("RenderSpotLightsInNondeferred");
+	PreviewAmbientColor = gSavedSettings.getColor4("PreviewAmbientColor");
+	PreviewDiffuse0 = gSavedSettings.getColor4("PreviewDiffuse0");
+	PreviewSpecular0 = gSavedSettings.getColor4("PreviewSpecular0");
+	PreviewDiffuse1 = gSavedSettings.getColor4("PreviewDiffuse1");
+	PreviewSpecular1 = gSavedSettings.getColor4("PreviewSpecular1");
+	PreviewDiffuse2 = gSavedSettings.getColor4("PreviewDiffuse2");
+	PreviewSpecular2 = gSavedSettings.getColor4("PreviewSpecular2");
+	PreviewDirection0 = gSavedSettings.getVector3("PreviewDirection0");
+	PreviewDirection1 = gSavedSettings.getVector3("PreviewDirection1");
+	PreviewDirection2 = gSavedSettings.getVector3("PreviewDirection2");
+	RenderGlowMinLuminance = gSavedSettings.getF32("RenderGlowMinLuminance");
+	RenderGlowMaxExtractAlpha = gSavedSettings.getF32("RenderGlowMaxExtractAlpha");
+	RenderGlowWarmthAmount = gSavedSettings.getF32("RenderGlowWarmthAmount");
+	RenderGlowLumWeights = gSavedSettings.getVector3("RenderGlowLumWeights");
+	RenderGlowWarmthWeights = gSavedSettings.getVector3("RenderGlowWarmthWeights");
+	RenderGlowResolutionPow = gSavedSettings.getS32("RenderGlowResolutionPow");
+	RenderGlowIterations = gSavedSettings.getS32("RenderGlowIterations");
+	RenderGlowWidth = gSavedSettings.getF32("RenderGlowWidth");
+	RenderGlowStrength = gSavedSettings.getF32("RenderGlowStrength");
+	RenderDepthOfField = gSavedSettings.getBOOL("RenderDepthOfField");
+	CameraFocusTransitionTime = gSavedSettings.getF32("CameraFocusTransitionTime");
+	CameraFNumber = gSavedSettings.getF32("CameraFNumber");
+	CameraFocalLength = gSavedSettings.getF32("CameraFocalLength");
+	CameraFieldOfView = gSavedSettings.getF32("CameraFieldOfView");
+	RenderShadowNoise = gSavedSettings.getF32("RenderShadowNoise");
+	RenderShadowBlurSize = gSavedSettings.getF32("RenderShadowBlurSize");
+	RenderSSAOScale = gSavedSettings.getF32("RenderSSAOScale");
+	RenderSSAOMaxScale = gSavedSettings.getU32("RenderSSAOMaxScale");
+	RenderSSAOFactor = gSavedSettings.getF32("RenderSSAOFactor");
+	RenderSSAOEffect = gSavedSettings.getVector3("RenderSSAOEffect");
+	RenderShadowOffsetError = gSavedSettings.getF32("RenderShadowOffsetError");
+	RenderShadowBiasError = gSavedSettings.getF32("RenderShadowBiasError");
+	RenderShadowOffset = gSavedSettings.getF32("RenderShadowOffset");
+	RenderShadowBias = gSavedSettings.getF32("RenderShadowBias");
+	RenderSpotShadowOffset = gSavedSettings.getF32("RenderSpotShadowOffset");
+	RenderSpotShadowBias = gSavedSettings.getF32("RenderSpotShadowBias");
+	RenderEdgeDepthCutoff = gSavedSettings.getF32("RenderEdgeDepthCutoff");
+	RenderEdgeNormCutoff = gSavedSettings.getF32("RenderEdgeNormCutoff");
+	RenderShadowGaussian = gSavedSettings.getVector3("RenderShadowGaussian");
+	RenderShadowBlurDistFactor = gSavedSettings.getF32("RenderShadowBlurDistFactor");
+	RenderDeferredAtmospheric = gSavedSettings.getBOOL("RenderDeferredAtmospheric");
+	RenderReflectionDetail = gSavedSettings.getS32("RenderReflectionDetail");
+	RenderHighlightFadeTime = gSavedSettings.getF32("RenderHighlightFadeTime");
+	RenderShadowClipPlanes = gSavedSettings.getVector3("RenderShadowClipPlanes");
+	RenderShadowOrthoClipPlanes = gSavedSettings.getVector3("RenderShadowOrthoClipPlanes");
+	RenderShadowNearDist = gSavedSettings.getVector3("RenderShadowNearDist");
+	RenderFarClip = gSavedSettings.getF32("RenderFarClip");
+	RenderShadowSplitExponent = gSavedSettings.getVector3("RenderShadowSplitExponent");
+	RenderShadowErrorCutoff = gSavedSettings.getF32("RenderShadowErrorCutoff");
+	RenderShadowFOVCutoff = gSavedSettings.getF32("RenderShadowFOVCutoff");
+	CameraOffset = gSavedSettings.getBOOL("CameraOffset");
+	CameraMaxCoF = gSavedSettings.getF32("CameraMaxCoF");
+	CameraDoFResScale = gSavedSettings.getF32("CameraDoFResScale");
+	
+	updateRenderDeferred();
+}
+
+void LLPipeline::releaseGLBuffers()
+{
+	assertInitialized();
+	
+	if (mNoiseMap)
+	{
+		LLImageGL::deleteTextures(1, &mNoiseMap);
+		mNoiseMap = 0;
+	}
+
+	if (mTrueNoiseMap)
+	{
+		LLImageGL::deleteTextures(1, &mTrueNoiseMap);
+		mTrueNoiseMap = 0;
+	}
+
+	if (mLightFunc)
+	{
+		LLImageGL::deleteTextures(1, &mLightFunc);
+		mLightFunc = 0;
+	}
+
+	mWaterRef.release();
+	mWaterDis.release();
+	
+	for (U32 i = 0; i < 3; i++)
+	{
+		mGlow[i].release();
+	}
+
+	releaseScreenBuffers();
+
+	gBumpImageList.destroyGL();
+	LLVOAvatar::resetImpostors();
+}
+
+void LLPipeline::releaseScreenBuffers()
+{
+	mUIScreen.release();
+	mScreen.release();
+	mFXAABuffer.release();
+	mPhysicsDisplay.release();
+	mDeferredScreen.release();
+	mDeferredDepth.release();
+	mDeferredLight.release();
+	
+	mHighlight.release();
+		
+	for (U32 i = 0; i < 6; i++)
+	{
+		mShadow[i].release();
+	}
+}
+
+
+void LLPipeline::createGLBuffers()
+{
+	stop_glerror();
+	LLMemType mt_cb(LLMemType::MTYPE_PIPELINE_CREATE_BUFFERS);
+	assertInitialized();
+
+	updateRenderDeferred();
+
+	if (LLPipeline::sWaterReflections)
+	{ //water reflection texture
+		U32 res = (U32) gSavedSettings.getS32("RenderWaterRefResolution");
+			
+		mWaterRef.allocate(res,res,GL_RGBA,TRUE,FALSE);
+		mWaterDis.allocate(res,res,GL_RGBA,TRUE,FALSE);
+	}
+
+	mHighlight.allocate(256,256,GL_RGBA, FALSE, FALSE);
+
+	stop_glerror();
+
+	GLuint resX = gViewerWindow->getWorldViewWidthRaw();
+	GLuint resY = gViewerWindow->getWorldViewHeightRaw();
+	
+	if (LLPipeline::sRenderGlow)
+	{ //screen space glow buffers
+		const U32 glow_res = llmax(1, 
+			llmin(512, 1 << gSavedSettings.getS32("RenderGlowResolutionPow")));
+
+		for (U32 i = 0; i < 3; i++)
+		{
+			mGlow[i].allocate(512,glow_res,GL_RGBA,FALSE,FALSE);
+		}
+
+		allocateScreenBuffer(resX,resY);
+		mScreenWidth = 0;
+		mScreenHeight = 0;
+	}
+	
+	if (sRenderDeferred)
+	{
+		if (!mNoiseMap)
+		{
+			const U32 noiseRes = 128;
+			LLVector3 noise[noiseRes*noiseRes];
+
+			F32 scaler = gSavedSettings.getF32("RenderDeferredNoise")/100.f;
+			for (U32 i = 0; i < noiseRes*noiseRes; ++i)
+			{
+				noise[i] = LLVector3(ll_frand()-0.5f, ll_frand()-0.5f, 0.f);
+				noise[i].normVec();
+				noise[i].mV[2] = ll_frand()*scaler+1.f-scaler/2.f;
+			}
+
+			LLImageGL::generateTextures(1, &mNoiseMap);
+			
+			gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mNoiseMap);
+			LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGB16F_ARB, noiseRes, noiseRes, GL_RGB, GL_FLOAT, noise);
+			gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
+		}
+
+		if (!mTrueNoiseMap)
+		{
+			const U32 noiseRes = 128;
+			F32 noise[noiseRes*noiseRes*3];
+			for (U32 i = 0; i < noiseRes*noiseRes*3; i++)
+			{
+				noise[i] = ll_frand()*2.0-1.0;
+			}
+
+			LLImageGL::generateTextures(1, &mTrueNoiseMap);
+			gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mTrueNoiseMap);
+			LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGB16F_ARB, noiseRes, noiseRes, GL_RGB,GL_FLOAT, noise);
+			gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
+		}
+
+		if (!mLightFunc)
+		{
+			U32 lightResX = gSavedSettings.getU32("RenderSpecularResX");
+			U32 lightResY = gSavedSettings.getU32("RenderSpecularResY");
+			U8* lg = new U8[lightResX*lightResY];
+
+			for (U32 y = 0; y < lightResY; ++y)
+			{
+				for (U32 x = 0; x < lightResX; ++x)
+				{
+					//spec func
+					F32 sa = (F32) x/(lightResX-1);
+					F32 spec = (F32) y/(lightResY-1);
+					//lg[y*lightResX+x] = (U8) (powf(sa, 128.f*spec*spec)*255);
+
+					//F32 sp = acosf(sa)/(1.f-spec);
+
+					sa = powf(sa, gSavedSettings.getF32("RenderSpecularExponent"));
+					F32 a = acosf(sa*0.25f+0.75f);
+					F32 m = llmax(0.5f-spec*0.5f, 0.001f);
+					F32 t2 = tanf(a)/m;
+					t2 *= t2;
+
+					F32 c4a = (3.f+4.f*cosf(2.f*a)+cosf(4.f*a))/8.f;
+					F32 bd = 1.f/(4.f*m*m*c4a)*powf(F_E, -t2);
+
+					lg[y*lightResX+x] = (U8) (llclamp(bd, 0.f, 1.f)*255);
+				}
+			}
+
+			LLImageGL::generateTextures(1, &mLightFunc);
+			gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mLightFunc);
+			LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_R8, lightResX, lightResY, GL_RED, GL_UNSIGNED_BYTE, lg);
+			gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
+			gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_TRILINEAR);
+
+			delete [] lg;
+		}
+	}
+
+	gBumpImageList.restoreGL();
+}
+
+void LLPipeline::restoreGL() 
+{
+	LLMemType mt_cb(LLMemType::MTYPE_PIPELINE_RESTORE_GL);
+	assertInitialized();
+
+	if (mVertexShadersEnabled)
+	{
+		LLViewerShaderMgr::instance()->setShaders();
+	}
+
+	for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
+			iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
+	{
+		LLViewerRegion* region = *iter;
+		for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
+		{
+			LLSpatialPartition* part = region->getSpatialPartition(i);
+			if (part)
+			{
+				part->restoreGL();
+			}
+		}
+	}
+}
+
+
+BOOL LLPipeline::canUseVertexShaders()
+{
+	if (sDisableShaders ||
+		!gGLManager.mHasVertexShader ||
+		!gGLManager.mHasFragmentShader ||
+		!LLFeatureManager::getInstance()->isFeatureAvailable("VertexShaderEnable") ||
+		(assertInitialized() && mVertexShadersLoaded != 1) )
+	{
+		return FALSE;
+	}
+	else
+	{
+		return TRUE;
+	}
+}
+
+BOOL LLPipeline::canUseWindLightShaders() const
+{
+	return (!LLPipeline::sDisableShaders &&
+			gWLSkyProgram.mProgramObject != 0 &&
+			LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_WINDLIGHT) > 1);
+}
+
+BOOL LLPipeline::canUseWindLightShadersOnObjects() const
+{
+	return (canUseWindLightShaders() 
+		&& LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 0);
+}
+
+BOOL LLPipeline::canUseAntiAliasing() const
+{
+	return TRUE;
+}
+
+void LLPipeline::unloadShaders()
+{
+	LLMemType mt_us(LLMemType::MTYPE_PIPELINE_UNLOAD_SHADERS);
+	LLViewerShaderMgr::instance()->unloadShaders();
+
+	mVertexShadersLoaded = 0;
+}
+
+void LLPipeline::assertInitializedDoError()
+{
+	llerrs << "LLPipeline used when uninitialized." << llendl;
+}
+
+//============================================================================
+
+void LLPipeline::enableShadows(const BOOL enable_shadows)
+{
+	//should probably do something here to wrangle shadows....	
+}
+
+S32 LLPipeline::getMaxLightingDetail() const
+{
+	/*if (mVertexShaderLevel[SHADER_OBJECT] >= LLDrawPoolSimple::SHADER_LEVEL_LOCAL_LIGHTS)
+	{
+		return 3;
+	}
+	else*/
+	{
+		return 1;
+	}
+}
+
+S32 LLPipeline::setLightingDetail(S32 level)
+{
+	LLMemType mt_ld(LLMemType::MTYPE_PIPELINE_LIGHTING_DETAIL);
+	refreshCachedSettings();
+
+	if (level < 0)
+	{
+		if (RenderLocalLights)
+		{
+			level = 1;
+		}
+		else
+		{
+			level = 0;
+		}
+	}
+	level = llclamp(level, 0, getMaxLightingDetail());
+	mLightingDetail = level;
+	
+	return mLightingDetail;
+}
+
+class LLOctreeDirtyTexture : public LLOctreeTraveler<LLDrawable>
+{
+public:
+	const std::set<LLViewerFetchedTexture*>& mTextures;
+
+	LLOctreeDirtyTexture(const std::set<LLViewerFetchedTexture*>& textures) : mTextures(textures) { }
+
+	virtual void visit(const LLOctreeNode<LLDrawable>* node)
+	{
+		LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0);
+
+		if (!group->isState(LLSpatialGroup::GEOM_DIRTY) && !group->getData().empty())
+		{
+			for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i)
+			{
+				for (LLSpatialGroup::drawmap_elem_t::iterator j = i->second.begin(); j != i->second.end(); ++j) 
+				{
+					LLDrawInfo* params = *j;
+					LLViewerFetchedTexture* tex = LLViewerTextureManager::staticCastToFetchedTexture(params->mTexture);
+					if (tex && mTextures.find(tex) != mTextures.end())
+					{ 
+						group->setState(LLSpatialGroup::GEOM_DIRTY);
+					}
+				}
+			}
+		}
+
+		for (LLSpatialGroup::bridge_list_t::iterator i = group->mBridgeList.begin(); i != group->mBridgeList.end(); ++i)
+		{
+			LLSpatialBridge* bridge = *i;
+			traverse(bridge->mOctree);
+		}
+	}
+};
+
+// Called when a texture changes # of channels (causes faces to move to alpha pool)
+void LLPipeline::dirtyPoolObjectTextures(const std::set<LLViewerFetchedTexture*>& textures)
+{
+	assertInitialized();
+
+	// *TODO: This is inefficient and causes frame spikes; need a better way to do this
+	//        Most of the time is spent in dirty.traverse.
+
+	for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
+	{
+		LLDrawPool *poolp = *iter;
+		if (poolp->isFacePool())
+		{
+			((LLFacePool*) poolp)->dirtyTextures(textures);
+		}
+	}
+	
+	LLOctreeDirtyTexture dirty(textures);
+	for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
+			iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
+	{
+		LLViewerRegion* region = *iter;
+		for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
+		{
+			LLSpatialPartition* part = region->getSpatialPartition(i);
+			if (part)
+			{
+				dirty.traverse(part->mOctree);
+			}
+		}
+	}
+}
+
+LLDrawPool *LLPipeline::findPool(const U32 type, LLViewerTexture *tex0)
+{
+	assertInitialized();
+
+	LLDrawPool *poolp = NULL;
+	switch( type )
+	{
+	case LLDrawPool::POOL_SIMPLE:
+		poolp = mSimplePool;
+		break;
+
+	case LLDrawPool::POOL_GRASS:
+		poolp = mGrassPool;
+		break;
+
+	case LLDrawPool::POOL_FULLBRIGHT:
+		poolp = mFullbrightPool;
+		break;
+
+	case LLDrawPool::POOL_INVISIBLE:
+		poolp = mInvisiblePool;
+		break;
+
+	case LLDrawPool::POOL_GLOW:
+		poolp = mGlowPool;
+		break;
+
+	case LLDrawPool::POOL_TREE:
+		poolp = get_if_there(mTreePools, (uintptr_t)tex0, (LLDrawPool*)0 );
+		break;
+
+	case LLDrawPool::POOL_TERRAIN:
+		poolp = get_if_there(mTerrainPools, (uintptr_t)tex0, (LLDrawPool*)0 );
+		break;
+
+	case LLDrawPool::POOL_BUMP:
+		poolp = mBumpPool;
+		break;
+
+	case LLDrawPool::POOL_ALPHA:
+		poolp = mAlphaPool;
+		break;
+
+	case LLDrawPool::POOL_AVATAR:
+		break; // Do nothing
+
+	case LLDrawPool::POOL_SKY:
+		poolp = mSkyPool;
+		break;
+
+	case LLDrawPool::POOL_WATER:
+		poolp = mWaterPool;
+		break;
+
+	case LLDrawPool::POOL_GROUND:
+		poolp = mGroundPool;
+		break;
+
+	case LLDrawPool::POOL_WL_SKY:
+		poolp = mWLSkyPool;
+		break;
+
+	default:
+		llassert(0);
+		llerrs << "Invalid Pool Type in  LLPipeline::findPool() type=" << type << llendl;
+		break;
+	}
+
+	return poolp;
+}
+
+
+LLDrawPool *LLPipeline::getPool(const U32 type,	LLViewerTexture *tex0)
+{
+	LLMemType mt(LLMemType::MTYPE_PIPELINE);
+	LLDrawPool *poolp = findPool(type, tex0);
+	if (poolp)
+	{
+		return poolp;
+	}
+
+	LLDrawPool *new_poolp = LLDrawPool::createPool(type, tex0);
+	addPool( new_poolp );
+
+	return new_poolp;
+}
+
+
+// static
+LLDrawPool* LLPipeline::getPoolFromTE(const LLTextureEntry* te, LLViewerTexture* imagep)
+{
+	LLMemType mt(LLMemType::MTYPE_PIPELINE);
+	U32 type = getPoolTypeFromTE(te, imagep);
+	return gPipeline.getPool(type, imagep);
+}
+
+//static 
+U32 LLPipeline::getPoolTypeFromTE(const LLTextureEntry* te, LLViewerTexture* imagep)
+{
+	LLMemType mt_gpt(LLMemType::MTYPE_PIPELINE_GET_POOL_TYPE);
+	
+	if (!te || !imagep)
+	{
+		return 0;
+	}
+		
+	bool alpha = te->getColor().mV[3] < 0.999f;
+	if (imagep)
+	{
+		alpha = alpha || (imagep->getComponents() == 4 && imagep->getType() != LLViewerTexture::MEDIA_TEXTURE) || (imagep->getComponents() == 2);
+	}
+
+	if (alpha)
+	{
+		return LLDrawPool::POOL_ALPHA;
+	}
+	else if ((te->getBumpmap() || te->getShiny()))
+	{
+		return LLDrawPool::POOL_BUMP;
+	}
+	else
+	{
+		return LLDrawPool::POOL_SIMPLE;
+	}
+}
+
+
+void LLPipeline::addPool(LLDrawPool *new_poolp)
+{
+	LLMemType mt_a(LLMemType::MTYPE_PIPELINE_ADD_POOL);
+	assertInitialized();
+	mPools.insert(new_poolp);
+	addToQuickLookup( new_poolp );
+}
+
+void LLPipeline::allocDrawable(LLViewerObject *vobj)
+{
+	LLMemType mt_ad(LLMemType::MTYPE_PIPELINE_ALLOCATE_DRAWABLE);
+	LLDrawable *drawable = new LLDrawable();
+	vobj->mDrawable = drawable;
+	
+	drawable->mVObjp     = vobj;
+	
+	//encompass completely sheared objects by taking 
+	//the most extreme point possible (<1,1,0.5>)
+	drawable->setRadius(LLVector3(1,1,0.5f).scaleVec(vobj->getScale()).length());
+	if (vobj->isOrphaned())
+	{
+		drawable->setState(LLDrawable::FORCE_INVISIBLE);
+	}
+	drawable->updateXform(TRUE);
+}
+
+
+static LLFastTimer::DeclareTimer FTM_UNLINK("Unlink");
+static LLFastTimer::DeclareTimer FTM_REMOVE_FROM_MOVE_LIST("Movelist");
+static LLFastTimer::DeclareTimer FTM_REMOVE_FROM_SPATIAL_PARTITION("Spatial Partition");
+static LLFastTimer::DeclareTimer FTM_REMOVE_FROM_LIGHT_SET("Light Set");
+static LLFastTimer::DeclareTimer FTM_REMOVE_FROM_HIGHLIGHT_SET("Highlight Set");
+
+void LLPipeline::unlinkDrawable(LLDrawable *drawable)
+{
+	LLFastTimer t(FTM_UNLINK);
+
+	assertInitialized();
+
+	LLPointer<LLDrawable> drawablep = drawable; // make sure this doesn't get deleted before we are done
+	
+	// Based on flags, remove the drawable from the queues that it's on.
+	if (drawablep->isState(LLDrawable::ON_MOVE_LIST))
+	{
+		LLFastTimer t(FTM_REMOVE_FROM_MOVE_LIST);
+		LLDrawable::drawable_vector_t::iterator iter = std::find(mMovedList.begin(), mMovedList.end(), drawablep);
+		if (iter != mMovedList.end())
+		{
+			mMovedList.erase(iter);
+		}
+	}
+
+	if (drawablep->getSpatialGroup())
+	{
+		LLFastTimer t(FTM_REMOVE_FROM_SPATIAL_PARTITION);
+		if (!drawablep->getSpatialGroup()->mSpatialPartition->remove(drawablep, drawablep->getSpatialGroup()))
+		{
+#ifdef LL_RELEASE_FOR_DOWNLOAD
+			llwarns << "Couldn't remove object from spatial group!" << llendl;
+#else
+			llerrs << "Couldn't remove object from spatial group!" << llendl;
+#endif
+		}
+	}
+
+	{
+		LLFastTimer t(FTM_REMOVE_FROM_LIGHT_SET);
+		mLights.erase(drawablep);
+
+		for (light_set_t::iterator iter = mNearbyLights.begin();
+					iter != mNearbyLights.end(); iter++)
+		{
+			if (iter->drawable == drawablep)
+			{
+				mNearbyLights.erase(iter);
+				break;
+			}
+		}
+	}
+
+	{
+		LLFastTimer t(FTM_REMOVE_FROM_HIGHLIGHT_SET);
+		HighlightItem item(drawablep);
+		mHighlightSet.erase(item);
+
+		if (mHighlightObject == drawablep)
+		{
+			mHighlightObject = NULL;
+		}
+	}
+
+	for (U32 i = 0; i < 2; ++i)
+	{
+		if (mShadowSpotLight[i] == drawablep)
+		{
+			mShadowSpotLight[i] = NULL;
+		}
+
+		if (mTargetShadowSpotLight[i] == drawablep)
+		{
+			mTargetShadowSpotLight[i] = NULL;
+		}
+	}
+
+
+}
+
+U32 LLPipeline::addObject(LLViewerObject *vobj)
+{
+	LLMemType mt_ao(LLMemType::MTYPE_PIPELINE_ADD_OBJECT);
+
+	if (RenderDelayCreation)
+	{
+		mCreateQ.push_back(vobj);
+	}
+	else
+	{
+		createObject(vobj);
+	}
+
+	return 1;
+}
+
+void LLPipeline::createObjects(F32 max_dtime)
+{
+	LLFastTimer ftm(FTM_GEO_UPDATE);
+	LLMemType mt(LLMemType::MTYPE_PIPELINE_CREATE_OBJECTS);
+
+	LLTimer update_timer;
+
+	while (!mCreateQ.empty() && update_timer.getElapsedTimeF32() < max_dtime)
+	{
+		LLViewerObject* vobj = mCreateQ.front();
+		if (!vobj->isDead())
+		{
+			createObject(vobj);
+		}
+		mCreateQ.pop_front();
+	}
+	
+	//for (LLViewerObject::vobj_list_t::iterator iter = mCreateQ.begin(); iter != mCreateQ.end(); ++iter)
+	//{
+	//	createObject(*iter);
+	//}
+
+	//mCreateQ.clear();
+}
+
+void LLPipeline::createObject(LLViewerObject* vobj)
+{
+	LLDrawable* drawablep = vobj->mDrawable;
+
+	if (!drawablep)
+	{
+		drawablep = vobj->createDrawable(this);
+	}
+	else
+	{
+		llerrs << "Redundant drawable creation!" << llendl;
+	}
+		
+	llassert(drawablep);
+
+	if (vobj->getParent())
+	{
+		vobj->setDrawableParent(((LLViewerObject*)vobj->getParent())->mDrawable); // LLPipeline::addObject 1
+	}
+	else
+	{
+		vobj->setDrawableParent(NULL); // LLPipeline::addObject 2
+	}
+
+	markRebuild(drawablep, LLDrawable::REBUILD_ALL, TRUE);
+
+	if (drawablep->getVOVolume() && RenderAnimateRes)
+	{
+		// fun animated res
+		drawablep->updateXform(TRUE);
+		drawablep->clearState(LLDrawable::MOVE_UNDAMPED);
+		drawablep->setScale(LLVector3(0,0,0));
+		drawablep->makeActive();
+	}
+}
+
+
+void LLPipeline::resetFrameStats()
+{
+	assertInitialized();
+
+	LLViewerStats::getInstance()->mTrianglesDrawnStat.addValue(mTrianglesDrawn/1000.f);
+
+	if (mBatchCount > 0)
+	{
+		mMeanBatchSize = gPipeline.mTrianglesDrawn/gPipeline.mBatchCount;
+	}
+	mTrianglesDrawn = 0;
+	sCompiles        = 0;
+	mVerticesRelit   = 0;
+	mLightingChanges = 0;
+	mGeometryChanges = 0;
+	mNumVisibleFaces = 0;
+
+	if (mOldRenderDebugMask != mRenderDebugMask)
+	{
+		gObjectList.clearDebugText();
+		mOldRenderDebugMask = mRenderDebugMask;
+	}
+		
+}
+
+//external functions for asynchronous updating
+void LLPipeline::updateMoveDampedAsync(LLDrawable* drawablep)
+{
+	if (FreezeTime)
+	{
+		return;
+	}
+	if (!drawablep)
+	{
+		llerrs << "updateMove called with NULL drawablep" << llendl;
+		return;
+	}
+	if (drawablep->isState(LLDrawable::EARLY_MOVE))
+	{
+		return;
+	}
+
+	assertInitialized();
+
+	// update drawable now
+	drawablep->clearState(LLDrawable::MOVE_UNDAMPED); // force to DAMPED
+	drawablep->updateMove(); // returns done
+	drawablep->setState(LLDrawable::EARLY_MOVE); // flag says we already did an undamped move this frame
+	// Put on move list so that EARLY_MOVE gets cleared
+	if (!drawablep->isState(LLDrawable::ON_MOVE_LIST))
+	{
+		mMovedList.push_back(drawablep);
+		drawablep->setState(LLDrawable::ON_MOVE_LIST);
+	}
+}
+
+void LLPipeline::updateMoveNormalAsync(LLDrawable* drawablep)
+{
+	if (FreezeTime)
+	{
+		return;
+	}
+	if (!drawablep)
+	{
+		llerrs << "updateMove called with NULL drawablep" << llendl;
+		return;
+	}
+	if (drawablep->isState(LLDrawable::EARLY_MOVE))
+	{
+		return;
+	}
+
+	assertInitialized();
+
+	// update drawable now
+	drawablep->setState(LLDrawable::MOVE_UNDAMPED); // force to UNDAMPED
+	drawablep->updateMove();
+	drawablep->setState(LLDrawable::EARLY_MOVE); // flag says we already did an undamped move this frame
+	// Put on move list so that EARLY_MOVE gets cleared
+	if (!drawablep->isState(LLDrawable::ON_MOVE_LIST))
+	{
+		mMovedList.push_back(drawablep);
+		drawablep->setState(LLDrawable::ON_MOVE_LIST);
+	}
+}
+
+void LLPipeline::updateMovedList(LLDrawable::drawable_vector_t& moved_list)
+{
+	for (LLDrawable::drawable_vector_t::iterator iter = moved_list.begin();
+		 iter != moved_list.end(); )
+	{
+		LLDrawable::drawable_vector_t::iterator curiter = iter++;
+		LLDrawable *drawablep = *curiter;
+		BOOL done = TRUE;
+		if (!drawablep->isDead() && (!drawablep->isState(LLDrawable::EARLY_MOVE)))
+		{
+			done = drawablep->updateMove();
+		}
+		drawablep->clearState(LLDrawable::EARLY_MOVE | LLDrawable::MOVE_UNDAMPED);
+		if (done)
+		{
+			drawablep->clearState(LLDrawable::ON_MOVE_LIST);
+			iter = moved_list.erase(curiter);
+		}
+	}
+}
+
+static LLFastTimer::DeclareTimer FTM_OCTREE_BALANCE("Balance Octree");
+static LLFastTimer::DeclareTimer FTM_UPDATE_MOVE("Update Move");
+
+void LLPipeline::updateMove()
+{
+	LLFastTimer t(FTM_UPDATE_MOVE);
+	LLMemType mt_um(LLMemType::MTYPE_PIPELINE_UPDATE_MOVE);
+
+	if (FreezeTime)
+	{
+		return;
+	}
+
+	assertInitialized();
+
+	{
+		static LLFastTimer::DeclareTimer ftm("Retexture");
+		LLFastTimer t(ftm);
+
+		for (LLDrawable::drawable_set_t::iterator iter = mRetexturedList.begin();
+			 iter != mRetexturedList.end(); ++iter)
+		{
+			LLDrawable* drawablep = *iter;
+			if (drawablep && !drawablep->isDead())
+			{
+				drawablep->updateTexture();
+			}
+		}
+		mRetexturedList.clear();
+	}
+
+	{
+		static LLFastTimer::DeclareTimer ftm("Moved List");
+		LLFastTimer t(ftm);
+		updateMovedList(mMovedList);
+	}
+
+	//balance octrees
+	{
+ 		LLFastTimer ot(FTM_OCTREE_BALANCE);
+
+		for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
+			iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
+		{
+			LLViewerRegion* region = *iter;
+			for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
+			{
+				LLSpatialPartition* part = region->getSpatialPartition(i);
+				if (part)
+				{
+					part->mOctree->balance();
+				}
+			}
+		}
+	}
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// Culling and occlusion testing
+/////////////////////////////////////////////////////////////////////////////
+
+//static
+F32 LLPipeline::calcPixelArea(LLVector3 center, LLVector3 size, LLCamera &camera)
+{
+	LLVector3 lookAt = center - camera.getOrigin();
+	F32 dist = lookAt.length();
+
+	//ramp down distance for nearby objects
+	//shrink dist by dist/16.
+	if (dist < 16.f)
+	{
+		dist /= 16.f;
+		dist *= dist;
+		dist *= 16.f;
+	}
+
+	//get area of circle around node
+	F32 app_angle = atanf(size.length()/dist);
+	F32 radius = app_angle*LLDrawable::sCurPixelAngle;
+	return radius*radius * F_PI;
+}
+
+//static
+F32 LLPipeline::calcPixelArea(const LLVector4a& center, const LLVector4a& size, LLCamera &camera)
+{
+	LLVector4a origin;
+	origin.load3(camera.getOrigin().mV);
+
+	LLVector4a lookAt;
+	lookAt.setSub(center, origin);
+	F32 dist = lookAt.getLength3().getF32();
+
+	//ramp down distance for nearby objects
+	//shrink dist by dist/16.
+	if (dist < 16.f)
+	{
+		dist /= 16.f;
+		dist *= dist;
+		dist *= 16.f;
+	}
+
+	//get area of circle around node
+	F32 app_angle = atanf(size.getLength3().getF32()/dist);
+	F32 radius = app_angle*LLDrawable::sCurPixelAngle;
+	return radius*radius * F_PI;
+}
+
+void LLPipeline::grabReferences(LLCullResult& result)
+{
+	sCull = &result;
+}
+
+void LLPipeline::clearReferences()
+{
+	sCull = NULL;
+}
+
+void check_references(LLSpatialGroup* group, LLDrawable* drawable)
+{
+	for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i)
+	{
+		if (drawable == *i)
+		{
+			llerrs << "LLDrawable deleted while actively reference by LLPipeline." << llendl;
+		}
+	}			
+}
+
+void check_references(LLDrawable* drawable, LLFace* face)
+{
+	for (S32 i = 0; i < drawable->getNumFaces(); ++i)
+	{
+		if (drawable->getFace(i) == face)
+		{
+			llerrs << "LLFace deleted while actively referenced by LLPipeline." << llendl;
+		}
+	}
+}
+
+void check_references(LLSpatialGroup* group, LLFace* face)
+{
+	for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i)
+	{
+		LLDrawable* drawable = *i;
+		check_references(drawable, face);
+	}			
+}
+
+void LLPipeline::checkReferences(LLFace* face)
+{
+#if 0
+	if (sCull)
+	{
+		for (LLCullResult::sg_list_t::iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter)
+		{
+			LLSpatialGroup* group = *iter;
+			check_references(group, face);
+		}
+
+		for (LLCullResult::sg_list_t::iterator iter = sCull->beginAlphaGroups(); iter != sCull->endAlphaGroups(); ++iter)
+		{
+			LLSpatialGroup* group = *iter;
+			check_references(group, face);
+		}
+
+		for (LLCullResult::sg_list_t::iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter)
+		{
+			LLSpatialGroup* group = *iter;
+			check_references(group, face);
+		}
+
+		for (LLCullResult::drawable_list_t::iterator iter = sCull->beginVisibleList(); iter != sCull->endVisibleList(); ++iter)
+		{
+			LLDrawable* drawable = *iter;
+			check_references(drawable, face);	
+		}
+	}
+#endif
+}
+
+void LLPipeline::checkReferences(LLDrawable* drawable)
+{
+#if 0
+	if (sCull)
+	{
+		for (LLCullResult::sg_list_t::iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter)
+		{
+			LLSpatialGroup* group = *iter;
+			check_references(group, drawable);
+		}
+
+		for (LLCullResult::sg_list_t::iterator iter = sCull->beginAlphaGroups(); iter != sCull->endAlphaGroups(); ++iter)
+		{
+			LLSpatialGroup* group = *iter;
+			check_references(group, drawable);
+		}
+
+		for (LLCullResult::sg_list_t::iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter)
+		{
+			LLSpatialGroup* group = *iter;
+			check_references(group, drawable);
+		}
+
+		for (LLCullResult::drawable_list_t::iterator iter = sCull->beginVisibleList(); iter != sCull->endVisibleList(); ++iter)
+		{
+			if (drawable == *iter)
+			{
+				llerrs << "LLDrawable deleted while actively referenced by LLPipeline." << llendl;
+			}
+		}
+	}
+#endif
+}
+
+void check_references(LLSpatialGroup* group, LLDrawInfo* draw_info)
+{
+	for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i)
+	{
+		LLSpatialGroup::drawmap_elem_t& draw_vec = i->second;
+		for (LLSpatialGroup::drawmap_elem_t::iterator j = draw_vec.begin(); j != draw_vec.end(); ++j)
+		{
+			LLDrawInfo* params = *j;
+			if (params == draw_info)
+			{
+				llerrs << "LLDrawInfo deleted while actively referenced by LLPipeline." << llendl;
+			}
+		}
+	}
+}
+
+
+void LLPipeline::checkReferences(LLDrawInfo* draw_info)
+{
+#if 0
+	if (sCull)
+	{
+		for (LLCullResult::sg_list_t::iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter)
+		{
+			LLSpatialGroup* group = *iter;
+			check_references(group, draw_info);
+		}
+
+		for (LLCullResult::sg_list_t::iterator iter = sCull->beginAlphaGroups(); iter != sCull->endAlphaGroups(); ++iter)
+		{
+			LLSpatialGroup* group = *iter;
+			check_references(group, draw_info);
+		}
+
+		for (LLCullResult::sg_list_t::iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter)
+		{
+			LLSpatialGroup* group = *iter;
+			check_references(group, draw_info);
+		}
+	}
+#endif
+}
+
+void LLPipeline::checkReferences(LLSpatialGroup* group)
+{
+#if 0
+	if (sCull)
+	{
+		for (LLCullResult::sg_list_t::iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter)
+		{
+			if (group == *iter)
+			{
+				llerrs << "LLSpatialGroup deleted while actively referenced by LLPipeline." << llendl;
+			}
+		}
+
+		for (LLCullResult::sg_list_t::iterator iter = sCull->beginAlphaGroups(); iter != sCull->endAlphaGroups(); ++iter)
+		{
+			if (group == *iter)
+			{
+				llerrs << "LLSpatialGroup deleted while actively referenced by LLPipeline." << llendl;
+			}
+		}
+
+		for (LLCullResult::sg_list_t::iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter)
+		{
+			if (group == *iter)
+			{
+				llerrs << "LLSpatialGroup deleted while actively referenced by LLPipeline." << llendl;
+			}
+		}
+	}
+#endif
+}
+
+
+BOOL LLPipeline::visibleObjectsInFrustum(LLCamera& camera)
+{
+	for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
+			iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
+	{
+		LLViewerRegion* region = *iter;
+
+		for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
+		{
+			LLSpatialPartition* part = region->getSpatialPartition(i);
+			if (part)
+			{
+				if (hasRenderType(part->mDrawableType))
+				{
+					if (part->visibleObjectsInFrustum(camera))
+					{
+						return TRUE;
+					}
+				}
+			}
+		}
+	}
+
+	return FALSE;
+}
+
+BOOL LLPipeline::getVisibleExtents(LLCamera& camera, LLVector3& min, LLVector3& max)
+{
+	const F32 X = 65536.f;
+
+	min = LLVector3(X,X,X);
+	max = LLVector3(-X,-X,-X);
+
+	U32 saved_camera_id = LLViewerCamera::sCurCameraID;
+	LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
+
+	BOOL res = TRUE;
+
+	for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
+			iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
+	{
+		LLViewerRegion* region = *iter;
+
+		for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
+		{
+			LLSpatialPartition* part = region->getSpatialPartition(i);
+			if (part)
+			{
+				if (hasRenderType(part->mDrawableType))
+				{
+					if (!part->getVisibleExtents(camera, min, max))
+					{
+						res = FALSE;
+					}
+				}
+			}
+		}
+	}
+
+	LLViewerCamera::sCurCameraID = saved_camera_id;
+
+	return res;
+}
+
+static LLFastTimer::DeclareTimer FTM_CULL("Object Culling");
+
+void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_clip, LLPlane* planep)
+{
+	LLFastTimer t(FTM_CULL);
+	LLMemType mt_uc(LLMemType::MTYPE_PIPELINE_UPDATE_CULL);
+
+	grabReferences(result);
+
+	sCull->clear();
+
+	BOOL to_texture =	LLPipeline::sUseOcclusion > 1 &&
+						!hasRenderType(LLPipeline::RENDER_TYPE_HUD) && 
+						LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD &&
+						gPipeline.canUseVertexShaders() &&
+						sRenderGlow;
+
+	if (to_texture)
+	{
+		mScreen.bindTarget();
+	}
+
+	if (sUseOcclusion > 1)
+	{
+		gGL.setColorMask(false, false);
+	}
+
+	gGL.matrixMode(LLRender::MM_PROJECTION);
+	gGL.pushMatrix();
+	gGL.loadMatrix(gGLLastProjection);
+	gGL.matrixMode(LLRender::MM_MODELVIEW);
+	gGL.pushMatrix();
+	gGLLastMatrix = NULL;
+	gGL.loadMatrix(gGLLastModelView);
+
+
+	LLVertexBuffer::unbind();
+	LLGLDisable blend(GL_BLEND);
+	LLGLDisable test(GL_ALPHA_TEST);
+	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+
+
+	//setup a clip plane in projection matrix for reflection renders (prevents flickering from occlusion culling)
+	LLViewerRegion* region = gAgent.getRegion();
+	LLPlane plane;
+
+	if (planep)
+	{
+		plane = *planep;
+	}
+	else 
+	{
+		if (region)
+		{
+			LLVector3 pnorm;
+			F32 height = region->getWaterHeight();
+			if (water_clip < 0)
+			{ //camera is above water, clip plane points up
+				pnorm.setVec(0,0,1);
+				plane.setVec(pnorm, -height);
+			}
+			else if (water_clip > 0)
+			{	//camera is below water, clip plane points down
+				pnorm = LLVector3(0,0,-1);
+				plane.setVec(pnorm, height);
+			}
+		}
+	}
+	
+	glh::matrix4f modelview = glh_get_last_modelview();
+	glh::matrix4f proj = glh_get_last_projection();
+	LLGLUserClipPlane clip(plane, modelview, proj, water_clip != 0 && LLPipeline::sReflectionRender);
+
+	LLGLDepthTest depth(GL_TRUE, GL_FALSE);
+
+	bool bound_shader = false;
+	if (gPipeline.canUseVertexShaders() && LLGLSLShader::sCurBoundShader == 0)
+	{ //if no shader is currently bound, use the occlusion shader instead of fixed function if we can
+		// (shadow render uses a special shader that clamps to clip planes)
+		bound_shader = true;
+		gOcclusionProgram.bind();
+	}
+	
+	for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
+			iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
+	{
+		LLViewerRegion* region = *iter;
+		if (water_clip != 0)
+		{
+			LLPlane plane(LLVector3(0,0, (F32) -water_clip), (F32) water_clip*region->getWaterHeight());
+			camera.setUserClipPlane(plane);
+		}
+		else
+		{
+			camera.disableUserClipPlane();
+		}
+
+		for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
+		{
+			LLSpatialPartition* part = region->getSpatialPartition(i);
+			if (part)
+			{
+				if (hasRenderType(part->mDrawableType))
+				{
+					part->cull(camera);
+				}
+			}
+		}
+	}
+
+	if (bound_shader)
+	{
+		gOcclusionProgram.unbind();
+	}
+
+	camera.disableUserClipPlane();
+
+	if (hasRenderType(LLPipeline::RENDER_TYPE_SKY) && 
+		gSky.mVOSkyp.notNull() && 
+		gSky.mVOSkyp->mDrawable.notNull())
+	{
+		gSky.mVOSkyp->mDrawable->setVisible(camera);
+		sCull->pushDrawable(gSky.mVOSkyp->mDrawable);
+		gSky.updateCull();
+		stop_glerror();
+	}
+
+	if (hasRenderType(LLPipeline::RENDER_TYPE_GROUND) && 
+		!gPipeline.canUseWindLightShaders() &&
+		gSky.mVOGroundp.notNull() && 
+		gSky.mVOGroundp->mDrawable.notNull() &&
+		!LLPipeline::sWaterReflections)
+	{
+		gSky.mVOGroundp->mDrawable->setVisible(camera);
+		sCull->pushDrawable(gSky.mVOGroundp->mDrawable);
+	}
+	
+	
+	gGL.matrixMode(LLRender::MM_PROJECTION);
+	gGL.popMatrix();
+	gGL.matrixMode(LLRender::MM_MODELVIEW);
+	gGL.popMatrix();
+
+	if (sUseOcclusion > 1)
+	{
+		gGL.setColorMask(true, false);
+	}
+
+	if (to_texture)
+	{
+		mScreen.flush();
+	}
+}
+
+void LLPipeline::markNotCulled(LLSpatialGroup* group, LLCamera& camera)
+{
+	if (group->getData().empty())
+	{ 
+		return;
+	}
+	
+	group->setVisible();
+
+	if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD)
+	{
+		group->updateDistance(camera);
+	}
+	
+	const F32 MINIMUM_PIXEL_AREA = 16.f;
+
+	if (group->mPixelArea < MINIMUM_PIXEL_AREA)
+	{
+		return;
+	}
+
+	if (sMinRenderSize > 0.f && 
+			llmax(llmax(group->mBounds[1][0], group->mBounds[1][1]), group->mBounds[1][2]) < sMinRenderSize)
+	{
+		return;
+	}
+
+	assertInitialized();
+	
+	if (!group->mSpatialPartition->mRenderByGroup)
+	{ //render by drawable
+		sCull->pushDrawableGroup(group);
+	}
+	else
+	{   //render by group
+		sCull->pushVisibleGroup(group);
+	}
+
+	mNumVisibleNodes++;
+}
+
+void LLPipeline::markOccluder(LLSpatialGroup* group)
+{
+	if (sUseOcclusion > 1 && group && !group->isOcclusionState(LLSpatialGroup::ACTIVE_OCCLUSION))
+	{
+		LLSpatialGroup* parent = group->getParent();
+
+		if (!parent || !parent->isOcclusionState(LLSpatialGroup::OCCLUDED))
+		{ //only mark top most occluders as active occlusion
+			sCull->pushOcclusionGroup(group);
+			group->setOcclusionState(LLSpatialGroup::ACTIVE_OCCLUSION);
+				
+			if (parent && 
+				!parent->isOcclusionState(LLSpatialGroup::ACTIVE_OCCLUSION) &&
+				parent->getElementCount() == 0 &&
+				parent->needsUpdate())
+			{
+				sCull->pushOcclusionGroup(group);
+				parent->setOcclusionState(LLSpatialGroup::ACTIVE_OCCLUSION);
+			}
+		}
+	}
+}
+
+void LLPipeline::doOcclusion(LLCamera& camera)
+{
+	if (LLPipeline::sUseOcclusion > 1 && sCull->hasOcclusionGroups())
+	{
+		LLVertexBuffer::unbind();
+
+		if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCCLUSION))
+		{
+			gGL.setColorMask(true, false, false, false);
+		}
+		else
+		{
+			gGL.setColorMask(false, false);
+		}
+		LLGLDisable blend(GL_BLEND);
+		LLGLDisable test(GL_ALPHA_TEST);
+		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+		LLGLDepthTest depth(GL_TRUE, GL_FALSE);
+
+		LLGLDisable cull(GL_CULL_FACE);
+
+		
+		bool bind_shader = LLGLSLShader::sNoFixedFunction && LLGLSLShader::sCurBoundShader == 0;
+		if (bind_shader)
+		{
+			if (LLPipeline::sShadowRender)
+			{
+				gDeferredShadowProgram.bind();
+			}
+			else
+			{
+				gOcclusionProgram.bind();
+			}
+		}
+
+		for (LLCullResult::sg_list_t::iterator iter = sCull->beginOcclusionGroups(); iter != sCull->endOcclusionGroups(); ++iter)
+		{
+			LLSpatialGroup* group = *iter;
+			group->doOcclusion(&camera);
+			group->clearOcclusionState(LLSpatialGroup::ACTIVE_OCCLUSION);
+		}
+	
+		if (bind_shader)
+		{
+			if (LLPipeline::sShadowRender)
+			{
+				gDeferredShadowProgram.unbind();
+			}
+			else
+			{
+				gOcclusionProgram.unbind();
+			}
+		}
+
+		gGL.setColorMask(true, false);
+	}
+}
+	
+BOOL LLPipeline::updateDrawableGeom(LLDrawable* drawablep, BOOL priority)
+{
+	BOOL update_complete = drawablep->updateGeometry(priority);
+	if (update_complete && assertInitialized())
+	{
+		drawablep->setState(LLDrawable::BUILT);
+		mGeometryChanges++;
+	}
+	return update_complete;
+}
+
+void LLPipeline::updateGL()
+{
+	while (!LLGLUpdate::sGLQ.empty())
+	{
+		LLGLUpdate* glu = LLGLUpdate::sGLQ.front();
+		glu->updateGL();
+		glu->mInQ = FALSE;
+		LLGLUpdate::sGLQ.pop_front();
+	}
+}
+
+void LLPipeline::rebuildPriorityGroups()
+{
+	LLTimer update_timer;
+	LLMemType mt(LLMemType::MTYPE_PIPELINE);
+	
+	assertInitialized();
+
+	gMeshRepo.notifyLoadedMeshes();
+
+	mGroupQ1Locked = true;
+	// Iterate through all drawables on the priority build queue,
+	for (LLSpatialGroup::sg_vector_t::iterator iter = mGroupQ1.begin();
+		 iter != mGroupQ1.end(); ++iter)
+	{
+		LLSpatialGroup* group = *iter;
+		group->rebuildGeom();
+		group->clearState(LLSpatialGroup::IN_BUILD_Q1);
+	}
+
+	mGroupQ1.clear();
+	mGroupQ1Locked = false;
+
+}
+		
+void LLPipeline::rebuildGroups()
+{
+	if (mGroupQ2.empty())
+	{
+		return;
+	}
+
+	mGroupQ2Locked = true;
+	// Iterate through some drawables on the non-priority build queue
+	S32 size = (S32) mGroupQ2.size();
+	S32 min_count = llclamp((S32) ((F32) (size * size)/4096*0.25f), 1, size);
+			
+	S32 count = 0;
+	
+	std::sort(mGroupQ2.begin(), mGroupQ2.end(), LLSpatialGroup::CompareUpdateUrgency());
+
+	LLSpatialGroup::sg_vector_t::iterator iter;
+	LLSpatialGroup::sg_vector_t::iterator last_iter = mGroupQ2.begin();
+
+	for (iter = mGroupQ2.begin();
+		 iter != mGroupQ2.end() && count <= min_count; ++iter)
+	{
+		LLSpatialGroup* group = *iter;
+		last_iter = iter;
+
+		if (!group->isDead())
+		{
+			group->rebuildGeom();
+			
+			if (group->mSpatialPartition->mRenderByGroup)
+			{
+				count++;
+			}
+		}
+
+		group->clearState(LLSpatialGroup::IN_BUILD_Q2);
+	}	
+
+	mGroupQ2.erase(mGroupQ2.begin(), ++last_iter);
+
+	mGroupQ2Locked = false;
+
+	updateMovedList(mMovedBridge);
+}
+
+void LLPipeline::updateGeom(F32 max_dtime)
+{
+	LLTimer update_timer;
+	LLMemType mt(LLMemType::MTYPE_PIPELINE_UPDATE_GEOM);
+	LLPointer<LLDrawable> drawablep;
+
+	LLFastTimer t(FTM_GEO_UPDATE);
+
+	assertInitialized();
+
+	if (sDelayedVBOEnable > 0)
+	{
+		if (--sDelayedVBOEnable <= 0)
+		{
+			resetVertexBuffers();
+			LLVertexBuffer::sEnableVBOs = TRUE;
+		}
+	}
+
+	// notify various object types to reset internal cost metrics, etc.
+	// for now, only LLVOVolume does this to throttle LOD changes
+	LLVOVolume::preUpdateGeom();
+
+	// Iterate through all drawables on the priority build queue,
+	for (LLDrawable::drawable_list_t::iterator iter = mBuildQ1.begin();
+		 iter != mBuildQ1.end();)
+	{
+		LLDrawable::drawable_list_t::iterator curiter = iter++;
+		LLDrawable* drawablep = *curiter;
+		if (drawablep && !drawablep->isDead())
+		{
+			if (drawablep->isState(LLDrawable::IN_REBUILD_Q2))
+			{
+				drawablep->clearState(LLDrawable::IN_REBUILD_Q2);
+				LLDrawable::drawable_list_t::iterator find = std::find(mBuildQ2.begin(), mBuildQ2.end(), drawablep);
+				if (find != mBuildQ2.end())
+				{
+					mBuildQ2.erase(find);
+				}
+			}
+
+			if (updateDrawableGeom(drawablep, TRUE))
+			{
+				drawablep->clearState(LLDrawable::IN_REBUILD_Q1);
+				mBuildQ1.erase(curiter);
+			}
+		}
+		else
+		{
+			mBuildQ1.erase(curiter);
+		}
+	}
+		
+	// Iterate through some drawables on the non-priority build queue
+	S32 min_count = 16;
+	S32 size = (S32) mBuildQ2.size();
+	if (size > 1024)
+	{
+		min_count = llclamp((S32) (size * (F32) size/4096), 16, size);
+	}
+		
+	S32 count = 0;
+	
+	max_dtime = llmax(update_timer.getElapsedTimeF32()+0.001f, max_dtime);
+	LLSpatialGroup* last_group = NULL;
+	LLSpatialBridge* last_bridge = NULL;
+
+	for (LLDrawable::drawable_list_t::iterator iter = mBuildQ2.begin();
+		 iter != mBuildQ2.end(); )
+	{
+		LLDrawable::drawable_list_t::iterator curiter = iter++;
+		LLDrawable* drawablep = *curiter;
+
+		LLSpatialBridge* bridge = drawablep->isRoot() ? drawablep->getSpatialBridge() :
+									drawablep->getParent()->getSpatialBridge();
+
+		if (drawablep->getSpatialGroup() != last_group && 
+			(!last_bridge || bridge != last_bridge) &&
+			(update_timer.getElapsedTimeF32() >= max_dtime) && count > min_count)
+		{
+			break;
+		}
+
+		//make sure updates don't stop in the middle of a spatial group
+		//to avoid thrashing (objects are enqueued by group)
+		last_group = drawablep->getSpatialGroup();
+		last_bridge = bridge;
+
+		BOOL update_complete = TRUE;
+		if (!drawablep->isDead())
+		{
+			update_complete = updateDrawableGeom(drawablep, FALSE);
+			count++;
+		}
+		if (update_complete)
+		{
+			drawablep->clearState(LLDrawable::IN_REBUILD_Q2);
+			mBuildQ2.erase(curiter);
+		}
+	}	
+
+	updateMovedList(mMovedBridge);
+}
+
+void LLPipeline::markVisible(LLDrawable *drawablep, LLCamera& camera)
+{
+	LLMemType mt(LLMemType::MTYPE_PIPELINE_MARK_VISIBLE);
+
+	if(drawablep && !drawablep->isDead())
+	{
+		if (drawablep->isSpatialBridge())
+		{
+			const LLDrawable* root = ((LLSpatialBridge*) drawablep)->mDrawable;
+			llassert(root); // trying to catch a bad assumption
+			if (root && //  // this test may not be needed, see above
+					root->getVObj()->isAttachment())
+			{
+				LLDrawable* rootparent = root->getParent();
+				if (rootparent) // this IS sometimes NULL
+				{
+					LLViewerObject *vobj = rootparent->getVObj();
+					llassert(vobj); // trying to catch a bad assumption
+					if (vobj) // this test may not be needed, see above
+					{
+						const LLVOAvatar* av = vobj->asAvatar();
+						if (av && av->isImpostor())
+						{
+							return;
+						}
+					}
+				}
+			}
+			sCull->pushBridge((LLSpatialBridge*) drawablep);
+		}
+		else
+		{
+			sCull->pushDrawable(drawablep);
+		}
+
+		drawablep->setVisible(camera);
+	}
+}
+
+void LLPipeline::markMoved(LLDrawable *drawablep, BOOL damped_motion)
+{
+	LLMemType mt_mm(LLMemType::MTYPE_PIPELINE_MARK_MOVED);
+
+	if (!drawablep)
+	{
+		//llerrs << "Sending null drawable to moved list!" << llendl;
+		return;
+	}
+	
+	if (drawablep->isDead())
+	{
+		llwarns << "Marking NULL or dead drawable moved!" << llendl;
+		return;
+	}
+	
+	if (drawablep->getParent()) 
+	{
+		//ensure that parent drawables are moved first
+		markMoved(drawablep->getParent(), damped_motion);
+	}
+
+	assertInitialized();
+
+	if (!drawablep->isState(LLDrawable::ON_MOVE_LIST))
+	{
+		if (drawablep->isSpatialBridge())
+		{
+			mMovedBridge.push_back(drawablep);
+		}
+		else
+		{
+			mMovedList.push_back(drawablep);
+		}
+		drawablep->setState(LLDrawable::ON_MOVE_LIST);
+	}
+	if (damped_motion == FALSE)
+	{
+		drawablep->setState(LLDrawable::MOVE_UNDAMPED); // UNDAMPED trumps DAMPED
+	}
+	else if (drawablep->isState(LLDrawable::MOVE_UNDAMPED))
+	{
+		drawablep->clearState(LLDrawable::MOVE_UNDAMPED);
+	}
+}
+
+void LLPipeline::markShift(LLDrawable *drawablep)
+{
+	LLMemType mt(LLMemType::MTYPE_PIPELINE_MARK_SHIFT);
+
+	if (!drawablep || drawablep->isDead())
+	{
+		return;
+	}
+
+	assertInitialized();
+
+	if (!drawablep->isState(LLDrawable::ON_SHIFT_LIST))
+	{
+		drawablep->getVObj()->setChanged(LLXform::SHIFTED | LLXform::SILHOUETTE);
+		if (drawablep->getParent()) 
+		{
+			markShift(drawablep->getParent());
+		}
+		mShiftList.push_back(drawablep);
+		drawablep->setState(LLDrawable::ON_SHIFT_LIST);
+	}
+}
+
+void LLPipeline::shiftObjects(const LLVector3 &offset)
+{
+	LLMemType mt(LLMemType::MTYPE_PIPELINE_SHIFT_OBJECTS);
+
+	assertInitialized();
+
+	glClear(GL_DEPTH_BUFFER_BIT);
+	gDepthDirty = TRUE;
+		
+	LLVector4a offseta;
+	offseta.load3(offset.mV);
+
+	for (LLDrawable::drawable_vector_t::iterator iter = mShiftList.begin();
+		 iter != mShiftList.end(); iter++)
+	{
+		LLDrawable *drawablep = *iter;
+		if (drawablep->isDead())
+		{
+			continue;
+		}	
+		drawablep->shiftPos(offseta);	
+		drawablep->clearState(LLDrawable::ON_SHIFT_LIST);
+	}
+	mShiftList.resize(0);
+
+	for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
+			iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
+	{
+		LLViewerRegion* region = *iter;
+		for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
+		{
+			LLSpatialPartition* part = region->getSpatialPartition(i);
+			if (part)
+			{
+				part->shift(offseta);
+			}
+		}
+	}
+
+	LLHUDText::shiftAll(offset);
+	LLHUDNameTag::shiftAll(offset);
+	display_update_camera();
+}
+
+void LLPipeline::markTextured(LLDrawable *drawablep)
+{
+	LLMemType mt(LLMemType::MTYPE_PIPELINE_MARK_TEXTURED);
+
+	if (drawablep && !drawablep->isDead() && assertInitialized())
+	{
+		mRetexturedList.insert(drawablep);
+	}
+}
+
+void LLPipeline::markGLRebuild(LLGLUpdate* glu)
+{
+	if (glu && !glu->mInQ)
+	{
+		LLGLUpdate::sGLQ.push_back(glu);
+		glu->mInQ = TRUE;
+	}
+}
+
+void LLPipeline::markPartitionMove(LLDrawable* drawable)
+{
+	if (!drawable->isState(LLDrawable::PARTITION_MOVE) && 
+		!drawable->getPositionGroup().equals3(LLVector4a::getZero()))
+	{
+		drawable->setState(LLDrawable::PARTITION_MOVE);
+		mPartitionQ.push_back(drawable);
+	}
+}
+
+void LLPipeline::processPartitionQ()
+{
+	for (LLDrawable::drawable_list_t::iterator iter = mPartitionQ.begin(); iter != mPartitionQ.end(); ++iter)
+	{
+		LLDrawable* drawable = *iter;
+		if (!drawable->isDead())
+		{
+			drawable->updateBinRadius();
+			drawable->movePartition();
+		}
+		drawable->clearState(LLDrawable::PARTITION_MOVE);
+	}
+
+	mPartitionQ.clear();
+}
+
+void LLPipeline::markRebuild(LLSpatialGroup* group, BOOL priority)
+{
+	LLMemType mt(LLMemType::MTYPE_PIPELINE);
+	
+	if (group && !group->isDead() && group->mSpatialPartition)
+	{
+		if (group->mSpatialPartition->mPartitionType == LLViewerRegion::PARTITION_HUD)
+		{
+			priority = TRUE;
+		}
+
+		if (priority)
+		{
+			if (!group->isState(LLSpatialGroup::IN_BUILD_Q1))
+			{
+				llassert_always(!mGroupQ1Locked);
+
+				mGroupQ1.push_back(group);
+				group->setState(LLSpatialGroup::IN_BUILD_Q1);
+
+				if (group->isState(LLSpatialGroup::IN_BUILD_Q2))
+				{
+					LLSpatialGroup::sg_vector_t::iterator iter = std::find(mGroupQ2.begin(), mGroupQ2.end(), group);
+					if (iter != mGroupQ2.end())
+					{
+						mGroupQ2.erase(iter);
+					}
+					group->clearState(LLSpatialGroup::IN_BUILD_Q2);
+				}
+			}
+		}
+		else if (!group->isState(LLSpatialGroup::IN_BUILD_Q2 | LLSpatialGroup::IN_BUILD_Q1))
+		{
+			llassert_always(!mGroupQ2Locked);
+			mGroupQ2.push_back(group);
+			group->setState(LLSpatialGroup::IN_BUILD_Q2);
+
+		}
+	}
+}
+
+void LLPipeline::markRebuild(LLDrawable *drawablep, LLDrawable::EDrawableFlags flag, BOOL priority)
+{
+	LLMemType mt(LLMemType::MTYPE_PIPELINE_MARK_REBUILD);
+
+	if (drawablep && !drawablep->isDead() && assertInitialized())
+	{
+		if (!drawablep->isState(LLDrawable::BUILT))
+		{
+			priority = TRUE;
+		}
+		if (priority)
+		{
+			if (!drawablep->isState(LLDrawable::IN_REBUILD_Q1))
+			{
+				mBuildQ1.push_back(drawablep);
+				drawablep->setState(LLDrawable::IN_REBUILD_Q1); // mark drawable as being in priority queue
+			}
+		}
+		else if (!drawablep->isState(LLDrawable::IN_REBUILD_Q2))
+		{
+			mBuildQ2.push_back(drawablep);
+			drawablep->setState(LLDrawable::IN_REBUILD_Q2); // need flag here because it is just a list
+		}
+		if (flag & (LLDrawable::REBUILD_VOLUME | LLDrawable::REBUILD_POSITION))
+		{
+			drawablep->getVObj()->setChanged(LLXform::SILHOUETTE);
+		}
+		drawablep->setState(flag);
+	}
+}
+
+static LLFastTimer::DeclareTimer FTM_RESET_DRAWORDER("Reset Draw Order");
+
+void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result)
+{
+	if (hasAnyRenderType(LLPipeline::RENDER_TYPE_AVATAR,
+					  LLPipeline::RENDER_TYPE_GROUND,
+					  LLPipeline::RENDER_TYPE_TERRAIN,
+					  LLPipeline::RENDER_TYPE_TREE,
+					  LLPipeline::RENDER_TYPE_SKY,
+					  LLPipeline::RENDER_TYPE_VOIDWATER,
+					  LLPipeline::RENDER_TYPE_WATER,
+					  LLPipeline::END_RENDER_TYPES))
+	{
+		//clear faces from face pools
+		LLFastTimer t(FTM_RESET_DRAWORDER);
+		gPipeline.resetDrawOrders();
+	}
+
+	LLFastTimer ftm(FTM_STATESORT);
+	LLMemType mt(LLMemType::MTYPE_PIPELINE_STATE_SORT);
+
+	//LLVertexBuffer::unbind();
+
+	grabReferences(result);
+	for (LLCullResult::sg_list_t::iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter)
+	{
+		LLSpatialGroup* group = *iter;
+		group->checkOcclusion();
+		if (sUseOcclusion > 1 && group->isOcclusionState(LLSpatialGroup::OCCLUDED))
+		{
+			markOccluder(group);
+		}
+		else
+		{
+			group->setVisible();
+			for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i)
+			{
+				markVisible(*i, camera);
+			}
+
+			if (!sDelayVBUpdate)
+			{ //rebuild mesh as soon as we know it's visible
+				group->rebuildMesh();
+			}
+		}
+	}
+
+	if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD)
+	{
+		LLSpatialGroup* last_group = NULL;
+		for (LLCullResult::bridge_list_t::iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i)
+		{
+			LLCullResult::bridge_list_t::iterator cur_iter = i;
+			LLSpatialBridge* bridge = *cur_iter;
+			LLSpatialGroup* group = bridge->getSpatialGroup();
+
+			if (last_group == NULL)
+			{
+				last_group = group;
+			}
+
+			if (!bridge->isDead() && group && !group->isOcclusionState(LLSpatialGroup::OCCLUDED))
+			{
+				stateSort(bridge, camera);
+			}
+
+			if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD &&
+				last_group != group && last_group->changeLOD())
+			{
+				last_group->mLastUpdateDistance = last_group->mDistance;
+			}
+
+			last_group = group;
+		}
+
+		if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD &&
+			last_group && last_group->changeLOD())
+		{
+			last_group->mLastUpdateDistance = last_group->mDistance;
+		}
+	}
+
+	for (LLCullResult::sg_list_t::iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter)
+	{
+		LLSpatialGroup* group = *iter;
+		group->checkOcclusion();
+		if (sUseOcclusion > 1 && group->isOcclusionState(LLSpatialGroup::OCCLUDED))
+		{
+			markOccluder(group);
+		}
+		else
+		{
+			group->setVisible();
+			stateSort(group, camera);
+
+			if (!sDelayVBUpdate)
+			{ //rebuild mesh as soon as we know it's visible
+				group->rebuildMesh();
+			}
+		}
+	}
+	
+	{
+		LLFastTimer ftm(FTM_STATESORT_DRAWABLE);
+		for (LLCullResult::drawable_list_t::iterator iter = sCull->beginVisibleList();
+			 iter != sCull->endVisibleList(); ++iter)
+		{
+			LLDrawable *drawablep = *iter;
+			if (!drawablep->isDead())
+			{
+				stateSort(drawablep, camera);
+			}
+		}
+	}
+		
+	postSort(camera);	
+}
+
+void LLPipeline::stateSort(LLSpatialGroup* group, LLCamera& camera)
+{
+	LLMemType mt(LLMemType::MTYPE_PIPELINE_STATE_SORT);
+	if (group->changeLOD())
+	{
+		for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i)
+		{
+			LLDrawable* drawablep = *i;
+			stateSort(drawablep, camera);
+		}
+
+		if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD)
+		{ //avoid redundant stateSort calls
+			group->mLastUpdateDistance = group->mDistance;
+		}
+	}
+
+}
+
+void LLPipeline::stateSort(LLSpatialBridge* bridge, LLCamera& camera)
+{
+	LLMemType mt(LLMemType::MTYPE_PIPELINE_STATE_SORT);
+	if (bridge->getSpatialGroup()->changeLOD())
+	{
+		bool force_update = false;
+		bridge->updateDistance(camera, force_update);
+	}
+}
+
+void LLPipeline::stateSort(LLDrawable* drawablep, LLCamera& camera)
+{
+	LLMemType mt(LLMemType::MTYPE_PIPELINE_STATE_SORT);
+		
+	if (!drawablep
+		|| drawablep->isDead() 
+		|| !hasRenderType(drawablep->getRenderType()))
+	{
+		return;
+	}
+	
+	if (LLSelectMgr::getInstance()->mHideSelectedObjects)
+	{
+		if (drawablep->getVObj().notNull() &&
+			drawablep->getVObj()->isSelected())
+		{
+			return;
+		}
+	}
+
+	if (drawablep->isAvatar())
+	{ //don't draw avatars beyond render distance or if we don't have a spatial group.
+		if ((drawablep->getSpatialGroup() == NULL) || 
+			(drawablep->getSpatialGroup()->mDistance > LLVOAvatar::sRenderDistance))
+		{
+			return;
+		}
+
+		LLVOAvatar* avatarp = (LLVOAvatar*) drawablep->getVObj().get();
+		if (!avatarp->isVisible())
+		{
+			return;
+		}
+	}
+
+	assertInitialized();
+
+	if (hasRenderType(drawablep->mRenderType))
+	{
+		if (!drawablep->isState(LLDrawable::INVISIBLE|LLDrawable::FORCE_INVISIBLE))
+		{
+			drawablep->setVisible(camera, NULL, FALSE);
+		}
+		else if (drawablep->isState(LLDrawable::CLEAR_INVISIBLE))
+		{
+			// clear invisible flag here to avoid single frame glitch
+			drawablep->clearState(LLDrawable::FORCE_INVISIBLE|LLDrawable::CLEAR_INVISIBLE);
+		}
+	}
+
+	if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD)
+	{
+		//if (drawablep->isVisible()) isVisible() check here is redundant, if it wasn't visible, it wouldn't be here
+		{
+			if (!drawablep->isActive())
+			{
+				bool force_update = false;
+				drawablep->updateDistance(camera, force_update);
+			}
+			else if (drawablep->isAvatar())
+			{
+				bool force_update = false;
+				drawablep->updateDistance(camera, force_update); // calls vobj->updateLOD() which calls LLVOAvatar::updateVisibility()
+			}
+		}
+	}
+
+	if (!drawablep->getVOVolume())
+	{
+		for (LLDrawable::face_list_t::iterator iter = drawablep->mFaces.begin();
+				iter != drawablep->mFaces.end(); iter++)
+		{
+			LLFace* facep = *iter;
+
+			if (facep->hasGeometry())
+			{
+				if (facep->getPool())
+				{
+					facep->getPool()->enqueue(facep);
+				}
+				else
+				{
+					break;
+				}
+			}
+		}
+	}
+	
+
+	mNumVisibleFaces += drawablep->getNumFaces();
+}
+
+
+void forAllDrawables(LLCullResult::sg_list_t::iterator begin, 
+					 LLCullResult::sg_list_t::iterator end,
+					 void (*func)(LLDrawable*))
+{
+	for (LLCullResult::sg_list_t::iterator i = begin; i != end; ++i)
+	{
+		for (LLSpatialGroup::element_iter j = (*i)->getData().begin(); j != (*i)->getData().end(); ++j)
+		{
+			func(*j);	
+		}
+	}
+}
+
+void LLPipeline::forAllVisibleDrawables(void (*func)(LLDrawable*))
+{
+	forAllDrawables(sCull->beginDrawableGroups(), sCull->endDrawableGroups(), func);
+	forAllDrawables(sCull->beginVisibleGroups(), sCull->endVisibleGroups(), func);
+}
+
+//function for creating scripted beacons
+void renderScriptedBeacons(LLDrawable* drawablep)
+{
+	LLViewerObject *vobj = drawablep->getVObj();
+	if (vobj 
+		&& !vobj->isAvatar() 
+		&& !vobj->getParent()
+		&& vobj->flagScripted())
+	{
+		if (gPipeline.sRenderBeacons)
+		{
+			gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", LLColor4(1.f, 0.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), LLPipeline::DebugBeaconLineWidth);
+		}
+
+		if (gPipeline.sRenderHighlight)
+		{
+			S32 face_id;
+			S32 count = drawablep->getNumFaces();
+			for (face_id = 0; face_id < count; face_id++)
+			{
+				gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) );
+			}
+		}
+	}
+}
+
+void renderScriptedTouchBeacons(LLDrawable* drawablep)
+{
+	LLViewerObject *vobj = drawablep->getVObj();
+	if (vobj 
+		&& !vobj->isAvatar() 
+		&& !vobj->getParent()
+		&& vobj->flagScripted()
+		&& vobj->flagHandleTouch())
+	{
+		if (gPipeline.sRenderBeacons)
+		{
+			gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", LLColor4(1.f, 0.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), LLPipeline::DebugBeaconLineWidth);
+		}
+
+		if (gPipeline.sRenderHighlight)
+		{
+			S32 face_id;
+			S32 count = drawablep->getNumFaces();
+			for (face_id = 0; face_id < count; face_id++)
+			{
+				gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) );
+			}
+		}
+	}
+}
+
+void renderPhysicalBeacons(LLDrawable* drawablep)
+{
+	LLViewerObject *vobj = drawablep->getVObj();
+	if (vobj 
+		&& !vobj->isAvatar() 
+		//&& !vobj->getParent()
+		&& vobj->usePhysics())
+	{
+		if (gPipeline.sRenderBeacons)
+		{
+			gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", LLColor4(0.f, 1.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), LLPipeline::DebugBeaconLineWidth);
+		}
+
+		if (gPipeline.sRenderHighlight)
+		{
+			S32 face_id;
+			S32 count = drawablep->getNumFaces();
+			for (face_id = 0; face_id < count; face_id++)
+			{
+				gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) );
+			}
+		}
+	}
+}
+
+void renderMOAPBeacons(LLDrawable* drawablep)
+{
+	LLViewerObject *vobj = drawablep->getVObj();
+
+	if(!vobj || vobj->isAvatar())
+		return;
+
+	BOOL beacon=FALSE;
+	U8 tecount=vobj->getNumTEs();
+	for(int x=0;x<tecount;x++)
+	{
+		if(vobj->getTE(x)->hasMedia())
+		{
+			beacon=TRUE;
+			break;
+		}
+	}
+	if(beacon==TRUE)
+	{
+		if (gPipeline.sRenderBeacons)
+		{
+			gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", LLColor4(1.f, 1.f, 1.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), LLPipeline::DebugBeaconLineWidth);
+		}
+
+		if (gPipeline.sRenderHighlight)
+		{
+			S32 face_id;
+			S32 count = drawablep->getNumFaces();
+			for (face_id = 0; face_id < count; face_id++)
+			{
+				gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) );
+			}
+		}
+	}
+}
+
+void renderParticleBeacons(LLDrawable* drawablep)
+{
+	// Look for attachments, objects, etc.
+	LLViewerObject *vobj = drawablep->getVObj();
+	if (vobj 
+		&& vobj->isParticleSource())
+	{
+		if (gPipeline.sRenderBeacons)
+		{
+			LLColor4 light_blue(0.5f, 0.5f, 1.f, 0.5f);
+			gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", light_blue, LLColor4(1.f, 1.f, 1.f, 0.5f), LLPipeline::DebugBeaconLineWidth);
+		}
+
+		if (gPipeline.sRenderHighlight)
+		{
+			S32 face_id;
+			S32 count = drawablep->getNumFaces();
+			for (face_id = 0; face_id < count; face_id++)
+			{
+				gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) );
+			}
+		}
+	}
+}
+
+void renderSoundHighlights(LLDrawable* drawablep)
+{
+	// Look for attachments, objects, etc.
+	LLViewerObject *vobj = drawablep->getVObj();
+	if (vobj && vobj->isAudioSource())
+	{
+		if (gPipeline.sRenderHighlight)
+		{
+			S32 face_id;
+			S32 count = drawablep->getNumFaces();
+			for (face_id = 0; face_id < count; face_id++)
+			{
+				gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) );
+			}
+		}
+	}
+}
+
+void LLPipeline::postSort(LLCamera& camera)
+{
+	LLMemType mt(LLMemType::MTYPE_PIPELINE_POST_SORT);
+	LLFastTimer ftm(FTM_STATESORT_POSTSORT);
+
+	assertInitialized();
+
+	llpushcallstacks ;
+	//rebuild drawable geometry
+	for (LLCullResult::sg_list_t::iterator i = sCull->beginDrawableGroups(); i != sCull->endDrawableGroups(); ++i)
+	{
+		LLSpatialGroup* group = *i;
+		if (!sUseOcclusion || 
+			!group->isOcclusionState(LLSpatialGroup::OCCLUDED))
+		{
+			group->rebuildGeom();
+		}
+	}
+	llpushcallstacks ;
+	//rebuild groups
+	sCull->assertDrawMapsEmpty();
+
+	rebuildPriorityGroups();
+	llpushcallstacks ;
+
+	const S32 bin_count = 1024*8;
+		
+	static LLCullResult::drawinfo_list_t alpha_bins[bin_count];
+	static U32 bin_size[bin_count];
+
+	//clear one bin per frame to avoid memory bloat
+	static S32 clear_idx = 0;
+	clear_idx = (1+clear_idx)%bin_count;
+	alpha_bins[clear_idx].clear();
+
+	for (U32 j = 0; j < bin_count; j++)
+	{
+		bin_size[j] = 0;
+	}
+
+	//build render map
+	for (LLCullResult::sg_list_t::iterator i = sCull->beginVisibleGroups(); i != sCull->endVisibleGroups(); ++i)
+	{
+		LLSpatialGroup* group = *i;
+		if (sUseOcclusion && 
+			group->isOcclusionState(LLSpatialGroup::OCCLUDED))
+		{
+			continue;
+		}
+
+		if (group->isState(LLSpatialGroup::NEW_DRAWINFO) && group->isState(LLSpatialGroup::GEOM_DIRTY))
+		{ //no way this group is going to be drawable without a rebuild
+			group->rebuildGeom();
+		}
+
+		for (LLSpatialGroup::draw_map_t::iterator j = group->mDrawMap.begin(); j != group->mDrawMap.end(); ++j)
+		{
+			LLSpatialGroup::drawmap_elem_t& src_vec = j->second;	
+			if (!hasRenderType(j->first))
+			{
+				continue;
+			}
+			
+			for (LLSpatialGroup::drawmap_elem_t::iterator k = src_vec.begin(); k != src_vec.end(); ++k)
+			{
+				if (sMinRenderSize > 0.f)
+				{
+					LLVector4a bounds;
+					bounds.setSub((*k)->mExtents[1],(*k)->mExtents[0]);
+
+					if (llmax(llmax(bounds[0], bounds[1]), bounds[2]) > sMinRenderSize)
+					{
+						sCull->pushDrawInfo(j->first, *k);
+					}
+				}
+				else
+				{
+					sCull->pushDrawInfo(j->first, *k);
+				}
+			}
+		}
+
+		if (hasRenderType(LLPipeline::RENDER_TYPE_PASS_ALPHA))
+		{
+			LLSpatialGroup::draw_map_t::iterator alpha = group->mDrawMap.find(LLRenderPass::PASS_ALPHA);
+			
+			if (alpha != group->mDrawMap.end())
+			{ //store alpha groups for sorting
+				LLSpatialBridge* bridge = group->mSpatialPartition->asBridge();
+				if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD)
+				{
+					if (bridge)
+					{
+						LLCamera trans_camera = bridge->transformCamera(camera);
+						group->updateDistance(trans_camera);
+					}
+					else
+					{
+						group->updateDistance(camera);
+					}
+				}
+							
+				if (hasRenderType(LLDrawPool::POOL_ALPHA))
+				{
+					sCull->pushAlphaGroup(group);
+				}
+			}
+		}
+	}
+		
+	if (!sShadowRender)
+	{
+		std::sort(sCull->beginAlphaGroups(), sCull->endAlphaGroups(), LLSpatialGroup::CompareDepthGreater());
+	}
+	llpushcallstacks ;
+	// only render if the flag is set. The flag is only set if we are in edit mode or the toggle is set in the menus
+	if (LLFloaterReg::instanceVisible("beacons") && !sShadowRender)
+	{
+		if (sRenderScriptedTouchBeacons)
+		{
+			// Only show the beacon on the root object.
+			forAllVisibleDrawables(renderScriptedTouchBeacons);
+		}
+		else
+		if (sRenderScriptedBeacons)
+		{
+			// Only show the beacon on the root object.
+			forAllVisibleDrawables(renderScriptedBeacons);
+		}
+
+		if (sRenderPhysicalBeacons)
+		{
+			// Only show the beacon on the root object.
+			forAllVisibleDrawables(renderPhysicalBeacons);
+		}
+
+		if(sRenderMOAPBeacons)
+		{
+			forAllVisibleDrawables(renderMOAPBeacons);
+		}
+
+		if (sRenderParticleBeacons)
+		{
+			forAllVisibleDrawables(renderParticleBeacons);
+		}
+
+		// If god mode, also show audio cues
+		if (sRenderSoundBeacons && gAudiop)
+		{
+			// Walk all sound sources and render out beacons for them. Note, this isn't done in the ForAllVisibleDrawables function, because some are not visible.
+			LLAudioEngine::source_map::iterator iter;
+			for (iter = gAudiop->mAllSources.begin(); iter != gAudiop->mAllSources.end(); ++iter)
+			{
+				LLAudioSource *sourcep = iter->second;
+
+				LLVector3d pos_global = sourcep->getPositionGlobal();
+				LLVector3 pos = gAgent.getPosAgentFromGlobal(pos_global);
+				if (gPipeline.sRenderBeacons)
+				{
+					//pos += LLVector3(0.f, 0.f, 0.2f);
+					gObjectList.addDebugBeacon(pos, "", LLColor4(1.f, 1.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), DebugBeaconLineWidth);
+				}
+			}
+			// now deal with highlights for all those seeable sound sources
+			forAllVisibleDrawables(renderSoundHighlights);
+		}
+	}
+	llpushcallstacks ;
+	// If managing your telehub, draw beacons at telehub and currently selected spawnpoint.
+	if (LLFloaterTelehub::renderBeacons())
+	{
+		LLFloaterTelehub::addBeacons();
+	}
+
+	if (!sShadowRender)
+	{
+		mSelectedFaces.clear();
+		
+		// Draw face highlights for selected faces.
+		if (LLSelectMgr::getInstance()->getTEMode())
+		{
+			struct f : public LLSelectedTEFunctor
+			{
+				virtual bool apply(LLViewerObject* object, S32 te)
+				{
+					if (object->mDrawable)
+					{
+						gPipeline.mSelectedFaces.push_back(object->mDrawable->getFace(te));
+					}
+					return true;
+				}
+			} func;
+			LLSelectMgr::getInstance()->getSelection()->applyToTEs(&func);
+		}
+	}
+
+	//LLSpatialGroup::sNoDelete = FALSE;
+	llpushcallstacks ;
+}
+
+
+void render_hud_elements()
+{
+	LLMemType mt_rhe(LLMemType::MTYPE_PIPELINE_RENDER_HUD_ELS);
+	LLFastTimer t(FTM_RENDER_UI);
+	gPipeline.disableLights();		
+	
+	LLGLDisable fog(GL_FOG);
+	LLGLSUIDefault gls_ui;
+
+	LLGLEnable stencil(GL_STENCIL_TEST);
+	glStencilFunc(GL_ALWAYS, 255, 0xFFFFFFFF);
+	glStencilMask(0xFFFFFFFF);
+	glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
+	
+	gGL.color4f(1,1,1,1);
+	
+	if (LLGLSLShader::sNoFixedFunction)
+	{
+		gUIProgram.bind();
+	}
+	LLGLDepthTest depth(GL_TRUE, GL_FALSE);
+
+	if (!LLPipeline::sReflectionRender && gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
+	{
+		LLGLEnable multisample(LLPipeline::RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0);
+		gViewerWindow->renderSelections(FALSE, FALSE, FALSE); // For HUD version in render_ui_3d()
+	
+		// Draw the tracking overlays
+		LLTracker::render3D();
+		
+		// Show the property lines
+		LLWorld::getInstance()->renderPropertyLines();
+		LLViewerParcelMgr::getInstance()->render();
+		LLViewerParcelMgr::getInstance()->renderParcelCollision();
+	
+		// Render name tags.
+		LLHUDObject::renderAll();
+	}
+	else if (gForceRenderLandFence)
+	{
+		// This is only set when not rendering the UI, for parcel snapshots
+		LLViewerParcelMgr::getInstance()->render();
+	}
+	else if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD))
+	{
+		LLHUDText::renderAllHUD();
+	}
+
+	if (LLGLSLShader::sNoFixedFunction)
+	{
+		gUIProgram.unbind();
+	}
+	gGL.flush();
+}
+
+void LLPipeline::renderHighlights()
+{
+	LLMemType mt(LLMemType::MTYPE_PIPELINE_RENDER_HL);
+
+	assertInitialized();
+
+	// Draw 3D UI elements here (before we clear the Z buffer in POOL_HUD)
+	// Render highlighted faces.
+	LLGLSPipelineAlpha gls_pipeline_alpha;
+	LLColor4 color(1.f, 1.f, 1.f, 0.5f);
+	LLGLEnable color_mat(GL_COLOR_MATERIAL);
+	disableLights();
+
+	if (!hasRenderType(LLPipeline::RENDER_TYPE_HUD) && !mHighlightSet.empty())
+	{ //draw blurry highlight image over screen
+		LLGLEnable blend(GL_BLEND);
+		LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS);
+		LLGLDisable test(GL_ALPHA_TEST);
+
+		LLGLEnable stencil(GL_STENCIL_TEST);
+		gGL.flush();
+		glStencilMask(0xFFFFFFFF);
+		glClearStencil(1);
+		glClear(GL_STENCIL_BUFFER_BIT);
+
+		glStencilFunc(GL_ALWAYS, 0, 0xFFFFFFFF);
+		glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
+				
+		gGL.setColorMask(false, false);
+		for (std::set<HighlightItem>::iterator iter = mHighlightSet.begin(); iter != mHighlightSet.end(); ++iter)
+		{
+			renderHighlight(iter->mItem->getVObj(), 1.f);
+		}
+		gGL.setColorMask(true, false);
+
+		glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
+		glStencilFunc(GL_NOTEQUAL, 0, 0xFFFFFFFF);
+		
+		//gGL.setSceneBlendType(LLRender::BT_ADD_WITH_ALPHA);
+
+		gGL.pushMatrix();
+		gGL.loadIdentity();
+		gGL.matrixMode(LLRender::MM_PROJECTION);
+		gGL.pushMatrix();
+		gGL.loadIdentity();
+
+		gGL.getTexUnit(0)->bind(&mHighlight);
+
+		LLVector2 tc1;
+		LLVector2 tc2;
+
+		tc1.setVec(0,0);
+		tc2.setVec(2,2);
+
+		gGL.begin(LLRender::TRIANGLES);
+				
+		F32 scale = RenderHighlightBrightness;
+		LLColor4 color = RenderHighlightColor;
+		F32 thickness = RenderHighlightThickness;
+
+		for (S32 pass = 0; pass < 2; ++pass)
+		{
+			if (pass == 0)
+			{
+				gGL.setSceneBlendType(LLRender::BT_ADD_WITH_ALPHA);
+			}
+			else
+			{
+				gGL.setSceneBlendType(LLRender::BT_ALPHA);
+			}
+
+			for (S32 i = 0; i < 8; ++i)
+			{
+				for (S32 j = 0; j < 8; ++j)
+				{
+					LLVector2 tc(i-4+0.5f, j-4+0.5f);
+
+					F32 dist = 1.f-(tc.length()/sqrtf(32.f));
+					dist *= scale/64.f;
+
+					tc *= thickness;
+					tc.mV[0] = (tc.mV[0])/mHighlight.getWidth();
+					tc.mV[1] = (tc.mV[1])/mHighlight.getHeight();
+
+					gGL.color4f(color.mV[0],
+								color.mV[1],
+								color.mV[2],
+								color.mV[3]*dist);
+					
+					gGL.texCoord2f(tc.mV[0]+tc1.mV[0], tc.mV[1]+tc2.mV[1]);
+					gGL.vertex2f(-1,3);
+					
+					gGL.texCoord2f(tc.mV[0]+tc1.mV[0], tc.mV[1]+tc1.mV[1]);
+					gGL.vertex2f(-1,-1);
+					
+					gGL.texCoord2f(tc.mV[0]+tc2.mV[0], tc.mV[1]+tc1.mV[1]);
+					gGL.vertex2f(3,-1);
+				}
+			}
+		}
+
+		gGL.end();
+
+		gGL.popMatrix();
+		gGL.matrixMode(LLRender::MM_MODELVIEW);
+		gGL.popMatrix();
+		
+		//gGL.setSceneBlendType(LLRender::BT_ALPHA);
+	}
+
+	if ((LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0))
+	{
+		gHighlightProgram.bind();
+		gGL.diffuseColor4f(1,1,1,0.5f);
+	}
+	
+	if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED))
+	{
+		// Make sure the selection image gets downloaded and decoded
+		if (!mFaceSelectImagep)
+		{
+			mFaceSelectImagep = LLViewerTextureManager::getFetchedTexture(IMG_FACE_SELECT);
+		}
+		mFaceSelectImagep->addTextureStats((F32)MAX_IMAGE_AREA);
+
+		U32 count = mSelectedFaces.size();
+		for (U32 i = 0; i < count; i++)
+		{
+			LLFace *facep = mSelectedFaces[i];
+			if (!facep || facep->getDrawable()->isDead())
+			{
+				llerrs << "Bad face on selection" << llendl;
+				return;
+			}
+			
+			facep->renderSelected(mFaceSelectImagep, color);
+		}
+	}
+
+	if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED))
+	{
+		// Paint 'em red!
+		color.setVec(1.f, 0.f, 0.f, 0.5f);
+		
+		int count = mHighlightFaces.size();
+		for (S32 i = 0; i < count; i++)
+		{
+			LLFace* facep = mHighlightFaces[i];
+			facep->renderSelected(LLViewerTexture::sNullImagep, color);
+		}
+	}
+
+	// Contains a list of the faces of objects that are physical or
+	// have touch-handlers.
+	mHighlightFaces.clear();
+
+	if (LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0)
+	{
+		gHighlightProgram.unbind();
+	}
+}
+
+//debug use
+U32 LLPipeline::sCurRenderPoolType = 0 ;
+
+void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate)
+{
+	LLMemType mt(LLMemType::MTYPE_PIPELINE_RENDER_GEOM);
+	LLFastTimer t(FTM_RENDER_GEOMETRY);
+
+	assertInitialized();
+
+	F32 saved_modelview[16];
+	F32 saved_projection[16];
+
+	//HACK: preserve/restore matrices around HUD render
+	if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD))
+	{
+		for (U32 i = 0; i < 16; i++)
+		{
+			saved_modelview[i] = gGLModelView[i];
+			saved_projection[i] = gGLProjection[i];
+		}
+	}
+
+	///////////////////////////////////////////
+	//
+	// Sync and verify GL state
+	//
+	//
+
+	stop_glerror();
+
+	LLVertexBuffer::unbind();
+
+	// Do verification of GL state
+	LLGLState::checkStates();
+	LLGLState::checkTextureChannels();
+	LLGLState::checkClientArrays();
+	if (mRenderDebugMask & RENDER_DEBUG_VERIFY)
+	{
+		if (!verify())
+		{
+			llerrs << "Pipeline verification failed!" << llendl;
+		}
+	}
+
+	LLAppViewer::instance()->pingMainloopTimeout("Pipeline:ForceVBO");
+	
+	// Initialize lots of GL state to "safe" values
+	gGL.matrixMode(LLRender::MM_TEXTURE);
+	gGL.loadIdentity();
+	gGL.matrixMode(LLRender::MM_MODELVIEW);
+
+	LLGLSPipeline gls_pipeline;
+	LLGLEnable multisample(RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0);
+
+	LLGLState gls_color_material(GL_COLOR_MATERIAL, mLightingDetail < 2);
+				
+	// Toggle backface culling for debugging
+	LLGLEnable cull_face(mBackfaceCull ? GL_CULL_FACE : 0);
+	// Set fog
+	BOOL use_fog = hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_FOG);
+	LLGLEnable fog_enable(use_fog &&
+						  !gPipeline.canUseWindLightShadersOnObjects() ? GL_FOG : 0);
+	gSky.updateFog(camera.getFar());
+	if (!use_fog)
+	{
+		sUnderWaterRender = FALSE;
+	}
+
+	gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sDefaultImagep);
+	LLViewerFetchedTexture::sDefaultImagep->setAddressMode(LLTexUnit::TAM_WRAP);
+	
+
+	//////////////////////////////////////////////
+	//
+	// Actually render all of the geometry
+	//
+	//	
+	stop_glerror();
+	
+	LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderDrawPools");
+
+	for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
+	{
+		LLDrawPool *poolp = *iter;
+		if (hasRenderType(poolp->getType()))
+		{
+			poolp->prerender();
+		}
+	}
+
+	{
+		LLFastTimer t(FTM_POOLS);
+		
+		// HACK: don't calculate local lights if we're rendering the HUD!
+		//    Removing this check will cause bad flickering when there are 
+		//    HUD elements being rendered AND the user is in flycam mode  -nyx
+		if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD))
+		{
+			calcNearbyLights(camera);
+			setupHWLights(NULL);
+		}
+
+		BOOL occlude = sUseOcclusion > 1;
+		U32 cur_type = 0;
+
+		pool_set_t::iterator iter1 = mPools.begin();
+		while ( iter1 != mPools.end() )
+		{
+			LLDrawPool *poolp = *iter1;
+			
+			cur_type = poolp->getType();
+
+			//debug use
+			sCurRenderPoolType = cur_type ;
+
+			if (occlude && cur_type >= LLDrawPool::POOL_GRASS)
+			{
+				occlude = FALSE;
+				gGLLastMatrix = NULL;
+				gGL.loadMatrix(gGLModelView);
+				LLGLSLShader::bindNoShader();
+				doOcclusion(camera);
+			}
+
+			pool_set_t::iterator iter2 = iter1;
+			if (hasRenderType(poolp->getType()) && poolp->getNumPasses() > 0)
+			{
+				LLFastTimer t(FTM_POOLRENDER);
+
+				gGLLastMatrix = NULL;
+				gGL.loadMatrix(gGLModelView);
+			
+				for( S32 i = 0; i < poolp->getNumPasses(); i++ )
+				{
+					LLVertexBuffer::unbind();
+					poolp->beginRenderPass(i);
+					for (iter2 = iter1; iter2 != mPools.end(); iter2++)
+					{
+						LLDrawPool *p = *iter2;
+						if (p->getType() != cur_type)
+						{
+							break;
+						}
+						
+						p->render(i);
+					}
+					poolp->endRenderPass(i);
+					LLVertexBuffer::unbind();
+					if (gDebugGL)
+					{
+						std::string msg = llformat("pass %d", i);
+						LLGLState::checkStates(msg);
+						//LLGLState::checkTextureChannels(msg);
+						//LLGLState::checkClientArrays(msg);
+					}
+				}
+			}
+			else
+			{
+				// Skip all pools of this type
+				for (iter2 = iter1; iter2 != mPools.end(); iter2++)
+				{
+					LLDrawPool *p = *iter2;
+					if (p->getType() != cur_type)
+					{
+						break;
+					}
+				}
+			}
+			iter1 = iter2;
+			stop_glerror();
+		}
+		
+		LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderDrawPoolsEnd");
+
+		LLVertexBuffer::unbind();
+			
+		gGLLastMatrix = NULL;
+		gGL.loadMatrix(gGLModelView);
+
+		if (occlude)
+		{
+			occlude = FALSE;
+			gGLLastMatrix = NULL;
+			gGL.loadMatrix(gGLModelView);
+			LLGLSLShader::bindNoShader();
+			doOcclusion(camera);
+		}
+	}
+
+	LLVertexBuffer::unbind();
+	LLGLState::checkStates();
+
+	if (!LLPipeline::sImpostorRender)
+	{
+		LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderHighlights");
+
+		if (!sReflectionRender)
+		{
+			renderHighlights();
+		}
+
+		// Contains a list of the faces of objects that are physical or
+		// have touch-handlers.
+		mHighlightFaces.clear();
+
+		LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderDebug");
+	
+		renderDebug();
+
+		LLVertexBuffer::unbind();
+	
+		if (!LLPipeline::sReflectionRender && !LLPipeline::sRenderDeferred)
+		{
+			if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
+			{
+				// Render debugging beacons.
+				gObjectList.renderObjectBeacons();
+				gObjectList.resetObjectBeacons();
+			}
+			else
+			{
+				// Make sure particle effects disappear
+				LLHUDObject::renderAllForTimer();
+			}
+		}
+		else
+		{
+			// Make sure particle effects disappear
+			LLHUDObject::renderAllForTimer();
+		}
+
+		LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderGeomEnd");
+
+		//HACK: preserve/restore matrices around HUD render
+		if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD))
+		{
+			for (U32 i = 0; i < 16; i++)
+			{
+				gGLModelView[i] = saved_modelview[i];
+				gGLProjection[i] = saved_projection[i];
+			}
+		}
+	}
+
+	LLVertexBuffer::unbind();
+
+	LLGLState::checkStates();
+//	LLGLState::checkTextureChannels();
+//	LLGLState::checkClientArrays();
+}
+
+void LLPipeline::renderGeomDeferred(LLCamera& camera)
+{
+	LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderGeomDeferred");
+
+	LLMemType mt_rgd(LLMemType::MTYPE_PIPELINE_RENDER_GEOM_DEFFERRED);
+	LLFastTimer t(FTM_RENDER_GEOMETRY);
+
+	LLFastTimer t2(FTM_POOLS);
+
+	LLGLEnable cull(GL_CULL_FACE);
+
+	LLGLEnable stencil(GL_STENCIL_TEST);
+	glStencilFunc(GL_ALWAYS, 1, 0xFFFFFFFF);
+	stop_glerror();
+	glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
+	stop_glerror();
+
+	for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
+	{
+		LLDrawPool *poolp = *iter;
+		if (hasRenderType(poolp->getType()))
+		{
+			poolp->prerender();
+		}
+	}
+
+	LLGLEnable multisample(RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0);
+
+	LLVertexBuffer::unbind();
+
+	LLGLState::checkStates();
+	LLGLState::checkTextureChannels();
+	LLGLState::checkClientArrays();
+
+	U32 cur_type = 0;
+
+	gGL.setColorMask(true, true);
+	
+	pool_set_t::iterator iter1 = mPools.begin();
+
+	while ( iter1 != mPools.end() )
+	{
+		LLDrawPool *poolp = *iter1;
+		
+		cur_type = poolp->getType();
+
+		pool_set_t::iterator iter2 = iter1;
+		if (hasRenderType(poolp->getType()) && poolp->getNumDeferredPasses() > 0)
+		{
+			LLFastTimer t(FTM_POOLRENDER);
+
+			gGLLastMatrix = NULL;
+			gGL.loadMatrix(gGLModelView);
+		
+			for( S32 i = 0; i < poolp->getNumDeferredPasses(); i++ )
+			{
+				LLVertexBuffer::unbind();
+				poolp->beginDeferredPass(i);
+				for (iter2 = iter1; iter2 != mPools.end(); iter2++)
+				{
+					LLDrawPool *p = *iter2;
+					if (p->getType() != cur_type)
+					{
+						break;
+					}
+										
+					p->renderDeferred(i);
+				}
+				poolp->endDeferredPass(i);
+				LLVertexBuffer::unbind();
+
+				if (gDebugGL || gDebugPipeline)
+				{
+					LLGLState::checkStates();
+				}
+			}
+		}
+		else
+		{
+			// Skip all pools of this type
+			for (iter2 = iter1; iter2 != mPools.end(); iter2++)
+			{
+				LLDrawPool *p = *iter2;
+				if (p->getType() != cur_type)
+				{
+					break;
+				}
+			}
+		}
+		iter1 = iter2;
+		stop_glerror();
+	}
+
+	gGLLastMatrix = NULL;
+	gGL.loadMatrix(gGLModelView);
+
+	gGL.setColorMask(true, false);
+}
+
+void LLPipeline::renderGeomPostDeferred(LLCamera& camera)
+{
+	LLMemType mt_rgpd(LLMemType::MTYPE_PIPELINE_RENDER_GEOM_POST_DEF);
+	LLFastTimer t(FTM_POOLS);
+	U32 cur_type = 0;
+
+	LLGLEnable cull(GL_CULL_FACE);
+
+	LLGLEnable multisample(RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0);
+
+	calcNearbyLights(camera);
+	setupHWLights(NULL);
+
+	gGL.setColorMask(true, false);
+
+	pool_set_t::iterator iter1 = mPools.begin();
+	BOOL occlude = LLPipeline::sUseOcclusion > 1;
+
+	while ( iter1 != mPools.end() )
+	{
+		LLDrawPool *poolp = *iter1;
+		
+		cur_type = poolp->getType();
+
+		if (occlude && cur_type >= LLDrawPool::POOL_GRASS)
+		{
+			occlude = FALSE;
+			gGLLastMatrix = NULL;
+			gGL.loadMatrix(gGLModelView);
+			LLGLSLShader::bindNoShader();
+			doOcclusion(camera);
+			gGL.setColorMask(true, false);
+		}
+
+		pool_set_t::iterator iter2 = iter1;
+		if (hasRenderType(poolp->getType()) && poolp->getNumPostDeferredPasses() > 0)
+		{
+			LLFastTimer t(FTM_POOLRENDER);
+
+			gGLLastMatrix = NULL;
+			gGL.loadMatrix(gGLModelView);
+		
+			for( S32 i = 0; i < poolp->getNumPostDeferredPasses(); i++ )
+			{
+				LLVertexBuffer::unbind();
+				poolp->beginPostDeferredPass(i);
+				for (iter2 = iter1; iter2 != mPools.end(); iter2++)
+				{
+					LLDrawPool *p = *iter2;
+					if (p->getType() != cur_type)
+					{
+						break;
+					}
+										
+					p->renderPostDeferred(i);
+				}
+				poolp->endPostDeferredPass(i);
+				LLVertexBuffer::unbind();
+
+				if (gDebugGL || gDebugPipeline)
+				{
+					LLGLState::checkStates();
+				}
+			}
+		}
+		else
+		{
+			// Skip all pools of this type
+			for (iter2 = iter1; iter2 != mPools.end(); iter2++)
+			{
+				LLDrawPool *p = *iter2;
+				if (p->getType() != cur_type)
+				{
+					break;
+				}
+			}
+		}
+		iter1 = iter2;
+		stop_glerror();
+	}
+
+	gGLLastMatrix = NULL;
+	gGL.loadMatrix(gGLModelView);
+
+	if (occlude)
+	{
+		occlude = FALSE;
+		gGLLastMatrix = NULL;
+		gGL.loadMatrix(gGLModelView);
+		LLGLSLShader::bindNoShader();
+		doOcclusion(camera);
+		gGLLastMatrix = NULL;
+		gGL.loadMatrix(gGLModelView);
+	}
+}
+
+void LLPipeline::renderGeomShadow(LLCamera& camera)
+{
+	LLMemType mt_rgs(LLMemType::MTYPE_PIPELINE_RENDER_GEOM_SHADOW);
+	U32 cur_type = 0;
+	
+	LLGLEnable cull(GL_CULL_FACE);
+
+	LLVertexBuffer::unbind();
+
+	pool_set_t::iterator iter1 = mPools.begin();
+	
+	while ( iter1 != mPools.end() )
+	{
+		LLDrawPool *poolp = *iter1;
+		
+		cur_type = poolp->getType();
+
+		pool_set_t::iterator iter2 = iter1;
+		if (hasRenderType(poolp->getType()) && poolp->getNumShadowPasses() > 0)
+		{
+			poolp->prerender() ;
+
+			gGLLastMatrix = NULL;
+			gGL.loadMatrix(gGLModelView);
+		
+			for( S32 i = 0; i < poolp->getNumShadowPasses(); i++ )
+			{
+				LLVertexBuffer::unbind();
+				poolp->beginShadowPass(i);
+				for (iter2 = iter1; iter2 != mPools.end(); iter2++)
+				{
+					LLDrawPool *p = *iter2;
+					if (p->getType() != cur_type)
+					{
+						break;
+					}
+										
+					p->renderShadow(i);
+				}
+				poolp->endShadowPass(i);
+				LLVertexBuffer::unbind();
+
+				LLGLState::checkStates();
+			}
+		}
+		else
+		{
+			// Skip all pools of this type
+			for (iter2 = iter1; iter2 != mPools.end(); iter2++)
+			{
+				LLDrawPool *p = *iter2;
+				if (p->getType() != cur_type)
+				{
+					break;
+				}
+			}
+		}
+		iter1 = iter2;
+		stop_glerror();
+	}
+
+	gGLLastMatrix = NULL;
+	gGL.loadMatrix(gGLModelView);
+}
+
+
+void LLPipeline::addTrianglesDrawn(S32 index_count, U32 render_type)
+{
+	assertInitialized();
+	S32 count = 0;
+	if (render_type == LLRender::TRIANGLE_STRIP)
+	{
+		count = index_count-2;
+	}
+	else
+	{
+		count = index_count/3;
+	}
+
+	mTrianglesDrawn += count;
+	mBatchCount++;
+	mMaxBatchSize = llmax(mMaxBatchSize, count);
+	mMinBatchSize = llmin(mMinBatchSize, count);
+
+	if (LLPipeline::sRenderFrameTest)
+	{
+		gViewerWindow->getWindow()->swapBuffers();
+		ms_sleep(16);
+	}
+}
+
+void LLPipeline::renderPhysicsDisplay()
+{
+	if (!hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PHYSICS_SHAPES))
+	{
+		return;
+	}
+
+	allocatePhysicsBuffer();
+
+	gGL.flush();
+	mPhysicsDisplay.bindTarget();
+	glClearColor(0,0,0,1);
+	gGL.setColorMask(true, true);
+	mPhysicsDisplay.clear();
+	glClearColor(0,0,0,0);
+
+	gGL.setColorMask(true, false);
+
+	if (LLGLSLShader::sNoFixedFunction)
+	{
+		gDebugProgram.bind();
+	}
+
+	for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
+			iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
+	{
+		LLViewerRegion* region = *iter;
+		for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
+		{
+			LLSpatialPartition* part = region->getSpatialPartition(i);
+			if (part)
+			{
+				if (hasRenderType(part->mDrawableType))
+				{
+					part->renderPhysicsShapes();
+				}
+			}
+		}
+	}
+
+	for (LLCullResult::bridge_list_t::const_iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i)
+	{
+		LLSpatialBridge* bridge = *i;
+		if (!bridge->isDead() && hasRenderType(bridge->mDrawableType))
+		{
+			gGL.pushMatrix();
+			gGL.multMatrix((F32*)bridge->mDrawable->getRenderMatrix().mMatrix);
+			bridge->renderPhysicsShapes();
+			gGL.popMatrix();
+		}
+	}
+
+	gGL.flush();
+
+	if (LLGLSLShader::sNoFixedFunction)
+	{
+		gDebugProgram.unbind();
+	}
+
+	mPhysicsDisplay.flush();
+}
+
+
+void LLPipeline::renderDebug()
+{
+	LLMemType mt(LLMemType::MTYPE_PIPELINE);
+
+	assertInitialized();
+
+	gGL.color4f(1,1,1,1);
+
+	gGLLastMatrix = NULL;
+	gGL.loadMatrix(gGLModelView);
+	gGL.setColorMask(true, false);
+
+	bool hud_only = hasRenderType(LLPipeline::RENDER_TYPE_HUD);
+
+	
+	if (!hud_only && !mDebugBlips.empty())
+	{ //render debug blips
+		if (LLGLSLShader::sNoFixedFunction)
+		{
+			gUIProgram.bind();
+		}
+
+		gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sWhiteImagep, true);
+
+		glPointSize(8.f);
+		LLGLDepthTest depth(GL_TRUE, GL_TRUE, GL_ALWAYS);
+
+		gGL.begin(LLRender::POINTS);
+		for (std::list<DebugBlip>::iterator iter = mDebugBlips.begin(); iter != mDebugBlips.end(); )
+		{
+			DebugBlip& blip = *iter;
+
+			blip.mAge += gFrameIntervalSeconds;
+			if (blip.mAge > 2.f)
+			{
+				mDebugBlips.erase(iter++);
+			}
+			else
+			{
+				iter++;
+			}
+
+			blip.mPosition.mV[2] += gFrameIntervalSeconds*2.f;
+
+			gGL.color4fv(blip.mColor.mV);
+			gGL.vertex3fv(blip.mPosition.mV);
+		}
+		gGL.end();
+		gGL.flush();
+		glPointSize(1.f);
+	}
+
+
+	// Debug stuff.
+	for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
+			iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
+	{
+		LLViewerRegion* region = *iter;
+		for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
+		{
+			LLSpatialPartition* part = region->getSpatialPartition(i);
+			if (part)
+			{
+				if ( hud_only && (part->mDrawableType == RENDER_TYPE_HUD || part->mDrawableType == RENDER_TYPE_HUD_PARTICLES) ||
+					 !hud_only && hasRenderType(part->mDrawableType) )
+				{
+					part->renderDebug();
+				}
+			}
+		}
+	}
+
+	for (LLCullResult::bridge_list_t::const_iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i)
+	{
+		LLSpatialBridge* bridge = *i;
+		if (!bridge->isDead() && hasRenderType(bridge->mDrawableType))
+		{
+			gGL.pushMatrix();
+			gGL.multMatrix((F32*)bridge->mDrawable->getRenderMatrix().mMatrix);
+			bridge->renderDebug();
+			gGL.popMatrix();
+		}
+	}
+
+	if (LLGLSLShader::sNoFixedFunction)
+	{
+		gUIProgram.bind();
+	}
+
+	if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
+	{
+		LLVertexBuffer::unbind();
+
+		LLGLEnable blend(GL_BLEND);
+		LLGLDepthTest depth(TRUE, FALSE);
+		LLGLDisable cull(GL_CULL_FACE);
+
+		gGL.color4f(1,1,1,1);
+		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+				
+		F32 a = 0.1f;
+
+		F32 col[] =
+		{
+			1,0,0,a,
+			0,1,0,a,
+			0,0,1,a,
+			1,0,1,a,
+			
+			1,1,0,a,
+			0,1,1,a,
+			1,1,1,a,
+			1,0,1,a,
+		};
+
+		for (U32 i = 0; i < 8; i++)
+		{
+			LLVector3* frust = mShadowCamera[i].mAgentFrustum;
+
+			if (i > 3)
+			{ //render shadow frusta as volumes
+				if (mShadowFrustPoints[i-4].empty())
+			{
+					continue;
+				}
+
+				gGL.color4fv(col+(i-4)*4);	
+			
+				gGL.begin(LLRender::TRIANGLE_STRIP);
+				gGL.vertex3fv(frust[0].mV); gGL.vertex3fv(frust[4].mV);
+				gGL.vertex3fv(frust[1].mV); gGL.vertex3fv(frust[5].mV);
+				gGL.vertex3fv(frust[2].mV); gGL.vertex3fv(frust[6].mV);
+				gGL.vertex3fv(frust[3].mV); gGL.vertex3fv(frust[7].mV);
+				gGL.vertex3fv(frust[0].mV); gGL.vertex3fv(frust[4].mV);
+				gGL.end();
+				
+				
+				gGL.begin(LLRender::TRIANGLE_STRIP);
+				gGL.vertex3fv(frust[0].mV);
+				gGL.vertex3fv(frust[1].mV);
+				gGL.vertex3fv(frust[3].mV);
+				gGL.vertex3fv(frust[2].mV);
+				gGL.end();
+				
+				gGL.begin(LLRender::TRIANGLE_STRIP);
+				gGL.vertex3fv(frust[4].mV);
+				gGL.vertex3fv(frust[5].mV);
+				gGL.vertex3fv(frust[7].mV);
+				gGL.vertex3fv(frust[6].mV);
+				gGL.end();		
+			}
+
+	
+			if (i < 4)
+			{
+				
+				//if (i == 0 || !mShadowFrustPoints[i].empty())
+				{
+					//render visible point cloud
+					gGL.flush();
+					glPointSize(8.f);
+					gGL.begin(LLRender::POINTS);
+					
+					F32* c = col+i*4;
+					gGL.color3fv(c);
+
+					for (U32 j = 0; j < mShadowFrustPoints[i].size(); ++j)
+						{
+							gGL.vertex3fv(mShadowFrustPoints[i][j].mV);
+						
+						}
+					gGL.end();
+
+					gGL.flush();
+					glPointSize(1.f);
+
+					LLVector3* ext = mShadowExtents[i]; 
+					LLVector3 pos = (ext[0]+ext[1])*0.5f;
+					LLVector3 size = (ext[1]-ext[0])*0.5f;
+					drawBoxOutline(pos, size);
+
+					//render camera frustum splits as outlines
+					gGL.begin(LLRender::LINES);
+					gGL.vertex3fv(frust[0].mV); gGL.vertex3fv(frust[1].mV);
+					gGL.vertex3fv(frust[1].mV); gGL.vertex3fv(frust[2].mV);
+					gGL.vertex3fv(frust[2].mV); gGL.vertex3fv(frust[3].mV);
+					gGL.vertex3fv(frust[3].mV); gGL.vertex3fv(frust[0].mV);
+					gGL.vertex3fv(frust[4].mV); gGL.vertex3fv(frust[5].mV);
+					gGL.vertex3fv(frust[5].mV); gGL.vertex3fv(frust[6].mV);
+					gGL.vertex3fv(frust[6].mV); gGL.vertex3fv(frust[7].mV);
+					gGL.vertex3fv(frust[7].mV); gGL.vertex3fv(frust[4].mV);
+					gGL.vertex3fv(frust[0].mV); gGL.vertex3fv(frust[4].mV);
+					gGL.vertex3fv(frust[1].mV); gGL.vertex3fv(frust[5].mV);
+					gGL.vertex3fv(frust[2].mV); gGL.vertex3fv(frust[6].mV);
+					gGL.vertex3fv(frust[3].mV); gGL.vertex3fv(frust[7].mV);
+					gGL.end();
+				}
+			}
+
+			/*gGL.flush();
+			glLineWidth(16-i*2);
+			for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
+					iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
+			{
+				LLViewerRegion* region = *iter;
+				for (U32 j = 0; j < LLViewerRegion::NUM_PARTITIONS; j++)
+				{
+					LLSpatialPartition* part = region->getSpatialPartition(j);
+					if (part)
+					{
+						if (hasRenderType(part->mDrawableType))
+						{
+							part->renderIntersectingBBoxes(&mShadowCamera[i]);
+						}
+					}
+				}
+			}
+			gGL.flush();
+			glLineWidth(1.f);*/
+		}
+	}
+
+	if (mRenderDebugMask & RENDER_DEBUG_WIND_VECTORS)
+	{
+		gAgent.getRegion()->mWind.renderVectors();
+	}
+	
+	if (mRenderDebugMask & RENDER_DEBUG_COMPOSITION)
+	{
+		// Debug composition layers
+		F32 x, y;
+
+		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+
+		if (gAgent.getRegion())
+		{
+			gGL.begin(LLRender::POINTS);
+			// Draw the composition layer for the region that I'm in.
+			for (x = 0; x <= 260; x++)
+			{
+				for (y = 0; y <= 260; y++)
+				{
+					if ((x > 255) || (y > 255))
+					{
+						gGL.color4f(1.f, 0.f, 0.f, 1.f);
+					}
+					else
+					{
+						gGL.color4f(0.f, 0.f, 1.f, 1.f);
+					}
+					F32 z = gAgent.getRegion()->getCompositionXY((S32)x, (S32)y);
+					z *= 5.f;
+					z += 50.f;
+					gGL.vertex3f(x, y, z);
+				}
+			}
+			gGL.end();
+		}
+	}
+
+	if (mRenderDebugMask & LLPipeline::RENDER_DEBUG_BUILD_QUEUE)
+	{
+		U32 count = 0;
+		U32 size = mGroupQ2.size();
+		LLColor4 col;
+
+		LLVertexBuffer::unbind();
+		LLGLEnable blend(GL_BLEND);
+		gGL.setSceneBlendType(LLRender::BT_ALPHA);
+		LLGLDepthTest depth(GL_TRUE, GL_FALSE);
+		gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sWhiteImagep);
+		
+		gGL.pushMatrix();
+		gGL.loadMatrix(gGLModelView);
+		gGLLastMatrix = NULL;
+
+		for (LLSpatialGroup::sg_vector_t::iterator iter = mGroupQ2.begin(); iter != mGroupQ2.end(); ++iter)
+		{
+			LLSpatialGroup* group = *iter;
+			if (group->isDead())
+			{
+				continue;
+			}
+
+			LLSpatialBridge* bridge = group->mSpatialPartition->asBridge();
+
+			if (bridge && (!bridge->mDrawable || bridge->mDrawable->isDead()))
+			{
+				continue;
+			}
+
+			if (bridge)
+			{
+				gGL.pushMatrix();
+				gGL.multMatrix((F32*)bridge->mDrawable->getRenderMatrix().mMatrix);
+			}
+
+			F32 alpha = llclamp((F32) (size-count)/size, 0.f, 1.f);
+
+			
+			LLVector2 c(1.f-alpha, alpha);
+			c.normVec();
+
+			
+			++count;
+			col.set(c.mV[0], c.mV[1], 0, alpha*0.5f+0.5f);
+			group->drawObjectBox(col);
+
+			if (bridge)
+			{
+				gGL.popMatrix();
+			}
+		}
+
+		gGL.popMatrix();
+	}
+
+	gGL.flush();
+	if (LLGLSLShader::sNoFixedFunction)
+	{
+		gUIProgram.unbind();
+	}
+}
+
+void LLPipeline::rebuildPools()
+{
+	LLMemType mt(LLMemType::MTYPE_PIPELINE_REBUILD_POOLS);
+
+	assertInitialized();
+
+	S32 max_count = mPools.size();
+	pool_set_t::iterator iter1 = mPools.upper_bound(mLastRebuildPool);
+	while(max_count > 0 && mPools.size() > 0) // && num_rebuilds < MAX_REBUILDS)
+	{
+		if (iter1 == mPools.end())
+		{
+			iter1 = mPools.begin();
+		}
+		LLDrawPool* poolp = *iter1;
+
+		if (poolp->isDead())
+		{
+			mPools.erase(iter1++);
+			removeFromQuickLookup( poolp );
+			if (poolp == mLastRebuildPool)
+			{
+				mLastRebuildPool = NULL;
+			}
+			delete poolp;
+		}
+		else
+		{
+			mLastRebuildPool = poolp;
+			iter1++;
+		}
+		max_count--;
+	}
+
+	if (isAgentAvatarValid())
+	{
+		gAgentAvatarp->rebuildHUD();
+	}
+}
+
+void LLPipeline::addToQuickLookup( LLDrawPool* new_poolp )
+{
+	LLMemType mt(LLMemType::MTYPE_PIPELINE_QUICK_LOOKUP);
+
+	assertInitialized();
+
+	switch( new_poolp->getType() )
+	{
+	case LLDrawPool::POOL_SIMPLE:
+		if (mSimplePool)
+		{
+			llassert(0);
+			llwarns << "Ignoring duplicate simple pool." << llendl;
+		}
+		else
+		{
+			mSimplePool = (LLRenderPass*) new_poolp;
+		}
+		break;
+
+	case LLDrawPool::POOL_GRASS:
+		if (mGrassPool)
+		{
+			llassert(0);
+			llwarns << "Ignoring duplicate grass pool." << llendl;
+		}
+		else
+		{
+			mGrassPool = (LLRenderPass*) new_poolp;
+		}
+		break;
+
+	case LLDrawPool::POOL_FULLBRIGHT:
+		if (mFullbrightPool)
+		{
+			llassert(0);
+			llwarns << "Ignoring duplicate simple pool." << llendl;
+		}
+		else
+		{
+			mFullbrightPool = (LLRenderPass*) new_poolp;
+		}
+		break;
+
+	case LLDrawPool::POOL_INVISIBLE:
+		if (mInvisiblePool)
+		{
+			llassert(0);
+			llwarns << "Ignoring duplicate simple pool." << llendl;
+		}
+		else
+		{
+			mInvisiblePool = (LLRenderPass*) new_poolp;
+		}
+		break;
+
+	case LLDrawPool::POOL_GLOW:
+		if (mGlowPool)
+		{
+			llassert(0);
+			llwarns << "Ignoring duplicate glow pool." << llendl;
+		}
+		else
+		{
+			mGlowPool = (LLRenderPass*) new_poolp;
+		}
+		break;
+
+	case LLDrawPool::POOL_TREE:
+		mTreePools[ uintptr_t(new_poolp->getTexture()) ] = new_poolp ;
+		break;
+ 
+	case LLDrawPool::POOL_TERRAIN:
+		mTerrainPools[ uintptr_t(new_poolp->getTexture()) ] = new_poolp ;
+		break;
+
+	case LLDrawPool::POOL_BUMP:
+		if (mBumpPool)
+		{
+			llassert(0);
+			llwarns << "Ignoring duplicate bump pool." << llendl;
+		}
+		else
+		{
+			mBumpPool = new_poolp;
+		}
+		break;
+
+	case LLDrawPool::POOL_ALPHA:
+		if( mAlphaPool )
+		{
+			llassert(0);
+			llwarns << "LLPipeline::addPool(): Ignoring duplicate Alpha pool" << llendl;
+		}
+		else
+		{
+			mAlphaPool = new_poolp;
+		}
+		break;
+
+	case LLDrawPool::POOL_AVATAR:
+		break; // Do nothing
+
+	case LLDrawPool::POOL_SKY:
+		if( mSkyPool )
+		{
+			llassert(0);
+			llwarns << "LLPipeline::addPool(): Ignoring duplicate Sky pool" << llendl;
+		}
+		else
+		{
+			mSkyPool = new_poolp;
+		}
+		break;
+	
+	case LLDrawPool::POOL_WATER:
+		if( mWaterPool )
+		{
+			llassert(0);
+			llwarns << "LLPipeline::addPool(): Ignoring duplicate Water pool" << llendl;
+		}
+		else
+		{
+			mWaterPool = new_poolp;
+		}
+		break;
+
+	case LLDrawPool::POOL_GROUND:
+		if( mGroundPool )
+		{
+			llassert(0);
+			llwarns << "LLPipeline::addPool(): Ignoring duplicate Ground Pool" << llendl;
+		}
+		else
+		{ 
+			mGroundPool = new_poolp;
+		}
+		break;
+
+	case LLDrawPool::POOL_WL_SKY:
+		if( mWLSkyPool )
+		{
+			llassert(0);
+			llwarns << "LLPipeline::addPool(): Ignoring duplicate WLSky Pool" << llendl;
+		}
+		else
+		{ 
+			mWLSkyPool = new_poolp;
+		}
+		break;
+
+	default:
+		llassert(0);
+		llwarns << "Invalid Pool Type in  LLPipeline::addPool()" << llendl;
+		break;
+	}
+}
+
+void LLPipeline::removePool( LLDrawPool* poolp )
+{
+	assertInitialized();
+	removeFromQuickLookup(poolp);
+	mPools.erase(poolp);
+	delete poolp;
+}
+
+void LLPipeline::removeFromQuickLookup( LLDrawPool* poolp )
+{
+	assertInitialized();
+	LLMemType mt(LLMemType::MTYPE_PIPELINE);
+	switch( poolp->getType() )
+	{
+	case LLDrawPool::POOL_SIMPLE:
+		llassert(mSimplePool == poolp);
+		mSimplePool = NULL;
+		break;
+
+	case LLDrawPool::POOL_GRASS:
+		llassert(mGrassPool == poolp);
+		mGrassPool = NULL;
+		break;
+
+	case LLDrawPool::POOL_FULLBRIGHT:
+		llassert(mFullbrightPool == poolp);
+		mFullbrightPool = NULL;
+		break;
+
+	case LLDrawPool::POOL_INVISIBLE:
+		llassert(mInvisiblePool == poolp);
+		mInvisiblePool = NULL;
+		break;
+
+	case LLDrawPool::POOL_WL_SKY:
+		llassert(mWLSkyPool == poolp);
+		mWLSkyPool = NULL;
+		break;
+
+	case LLDrawPool::POOL_GLOW:
+		llassert(mGlowPool == poolp);
+		mGlowPool = NULL;
+		break;
+
+	case LLDrawPool::POOL_TREE:
+		#ifdef _DEBUG
+			{
+				BOOL found = mTreePools.erase( (uintptr_t)poolp->getTexture() );
+				llassert( found );
+			}
+		#else
+			mTreePools.erase( (uintptr_t)poolp->getTexture() );
+		#endif
+		break;
+
+	case LLDrawPool::POOL_TERRAIN:
+		#ifdef _DEBUG
+			{
+				BOOL found = mTerrainPools.erase( (uintptr_t)poolp->getTexture() );
+				llassert( found );
+			}
+		#else
+			mTerrainPools.erase( (uintptr_t)poolp->getTexture() );
+		#endif
+		break;
+
+	case LLDrawPool::POOL_BUMP:
+		llassert( poolp == mBumpPool );
+		mBumpPool = NULL;
+		break;
+	
+	case LLDrawPool::POOL_ALPHA:
+		llassert( poolp == mAlphaPool );
+		mAlphaPool = NULL;
+		break;
+
+	case LLDrawPool::POOL_AVATAR:
+		break; // Do nothing
+
+	case LLDrawPool::POOL_SKY:
+		llassert( poolp == mSkyPool );
+		mSkyPool = NULL;
+		break;
+
+	case LLDrawPool::POOL_WATER:
+		llassert( poolp == mWaterPool );
+		mWaterPool = NULL;
+		break;
+
+	case LLDrawPool::POOL_GROUND:
+		llassert( poolp == mGroundPool );
+		mGroundPool = NULL;
+		break;
+
+	default:
+		llassert(0);
+		llwarns << "Invalid Pool Type in  LLPipeline::removeFromQuickLookup() type=" << poolp->getType() << llendl;
+		break;
+	}
+}
+
+void LLPipeline::resetDrawOrders()
+{
+	assertInitialized();
+	// Iterate through all of the draw pools and rebuild them.
+	for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
+	{
+		LLDrawPool *poolp = *iter;
+		poolp->resetDrawOrders();
+	}
+}
+
+//============================================================================
+// Once-per-frame setup of hardware lights,
+// including sun/moon, avatar backlight, and up to 6 local lights
+
+void LLPipeline::setupAvatarLights(BOOL for_edit)
+{
+	assertInitialized();
+
+	if (for_edit)
+	{
+		LLColor4 diffuse(1.f, 1.f, 1.f, 0.f);
+		LLVector4 light_pos_cam(-8.f, 0.25f, 10.f, 0.f);  // w==0 => directional light
+		LLMatrix4 camera_mat = LLViewerCamera::getInstance()->getModelview();
+		LLMatrix4 camera_rot(camera_mat.getMat3());
+		camera_rot.invert();
+		LLVector4 light_pos = light_pos_cam * camera_rot;
+		
+		light_pos.normalize();
+
+		LLLightState* light = gGL.getLight(1);
+
+		mHWLightColors[1] = diffuse;
+
+		light->setDiffuse(diffuse);
+		light->setAmbient(LLColor4::black);
+		light->setSpecular(LLColor4::black);
+		light->setPosition(light_pos);
+		light->setConstantAttenuation(1.f);
+		light->setLinearAttenuation(0.f);
+		light->setQuadraticAttenuation(0.f);
+		light->setSpotExponent(0.f);
+		light->setSpotCutoff(180.f);
+	}
+	else if (gAvatarBacklight) // Always true (unless overridden in a devs .ini)
+	{
+		LLVector3 opposite_pos = -1.f * mSunDir;
+		LLVector3 orthog_light_pos = mSunDir % LLVector3::z_axis;
+		LLVector4 backlight_pos = LLVector4(lerp(opposite_pos, orthog_light_pos, 0.3f), 0.0f);
+		backlight_pos.normalize();
+			
+		LLColor4 light_diffuse = mSunDiffuse;
+		LLColor4 backlight_diffuse(1.f - light_diffuse.mV[VRED], 1.f - light_diffuse.mV[VGREEN], 1.f - light_diffuse.mV[VBLUE], 1.f);
+		F32 max_component = 0.001f;
+		for (S32 i = 0; i < 3; i++)
+		{
+			if (backlight_diffuse.mV[i] > max_component)
+			{
+				max_component = backlight_diffuse.mV[i];
+			}
+		}
+		F32 backlight_mag;
+		if (gSky.getSunDirection().mV[2] >= LLSky::NIGHTTIME_ELEVATION_COS)
+		{
+			backlight_mag = BACKLIGHT_DAY_MAGNITUDE_OBJECT;
+		}
+		else
+		{
+			backlight_mag = BACKLIGHT_NIGHT_MAGNITUDE_OBJECT;
+		}
+		backlight_diffuse *= backlight_mag / max_component;
+
+		mHWLightColors[1] = backlight_diffuse;
+
+		LLLightState* light = gGL.getLight(1);
+
+		light->setPosition(backlight_pos);
+		light->setDiffuse(backlight_diffuse);
+		light->setAmbient(LLColor4::black);
+		light->setSpecular(LLColor4::black);
+		light->setConstantAttenuation(1.f);
+		light->setLinearAttenuation(0.f);
+		light->setQuadraticAttenuation(0.f);
+		light->setSpotExponent(0.f);
+		light->setSpotCutoff(180.f);
+	}
+	else
+	{
+		LLLightState* light = gGL.getLight(1);
+
+		mHWLightColors[1] = LLColor4::black;
+
+		light->setDiffuse(LLColor4::black);
+		light->setAmbient(LLColor4::black);
+		light->setSpecular(LLColor4::black);
+	}
+}
+
+static F32 calc_light_dist(LLVOVolume* light, const LLVector3& cam_pos, F32 max_dist)
+{
+	F32 inten = light->getLightIntensity();
+	if (inten < .001f)
+	{
+		return max_dist;
+	}
+	F32 radius = light->getLightRadius();
+	BOOL selected = light->isSelected();
+	LLVector3 dpos = light->getRenderPosition() - cam_pos;
+	F32 dist2 = dpos.lengthSquared();
+	if (!selected && dist2 > (max_dist + radius)*(max_dist + radius))
+	{
+		return max_dist;
+	}
+	F32 dist = (F32) sqrt(dist2);
+	dist *= 1.f / inten;
+	dist -= radius;
+	if (selected)
+	{
+		dist -= 10000.f; // selected lights get highest priority
+	}
+	if (light->mDrawable.notNull() && light->mDrawable->isState(LLDrawable::ACTIVE))
+	{
+		// moving lights get a little higher priority (too much causes artifacts)
+		dist -= light->getLightRadius()*0.25f;
+	}
+	return dist;
+}
+
+void LLPipeline::calcNearbyLights(LLCamera& camera)
+{
+	assertInitialized();
+
+	if (LLPipeline::sReflectionRender)
+	{
+		return;
+	}
+
+	if (mLightingDetail >= 1)
+	{
+		// mNearbyLight (and all light_set_t's) are sorted such that
+		// begin() == the closest light and rbegin() == the farthest light
+		const S32 MAX_LOCAL_LIGHTS = 6;
+// 		LLVector3 cam_pos = gAgent.getCameraPositionAgent();
+		LLVector3 cam_pos = LLViewerJoystick::getInstance()->getOverrideCamera() ?
+						camera.getOrigin() : 
+						gAgent.getPositionAgent();
+
+		F32 max_dist = LIGHT_MAX_RADIUS * 4.f; // ignore enitrely lights > 4 * max light rad
+		
+		// UPDATE THE EXISTING NEARBY LIGHTS
+		light_set_t cur_nearby_lights;
+		for (light_set_t::iterator iter = mNearbyLights.begin();
+			iter != mNearbyLights.end(); iter++)
+		{
+			const Light* light = &(*iter);
+			LLDrawable* drawable = light->drawable;
+			LLVOVolume* volight = drawable->getVOVolume();
+			if (!volight || !drawable->isState(LLDrawable::LIGHT))
+			{
+				drawable->clearState(LLDrawable::NEARBY_LIGHT);
+				continue;
+			}
+			if (light->fade <= -LIGHT_FADE_TIME)
+			{
+				drawable->clearState(LLDrawable::NEARBY_LIGHT);
+				continue;
+			}
+			if (!sRenderAttachedLights && volight && volight->isAttachment())
+			{
+				drawable->clearState(LLDrawable::NEARBY_LIGHT);
+				continue;
+			}
+
+			F32 dist = calc_light_dist(volight, cam_pos, max_dist);
+			cur_nearby_lights.insert(Light(drawable, dist, light->fade));
+		}
+		mNearbyLights = cur_nearby_lights;
+				
+		// FIND NEW LIGHTS THAT ARE IN RANGE
+		light_set_t new_nearby_lights;
+		for (LLDrawable::drawable_set_t::iterator iter = mLights.begin();
+			 iter != mLights.end(); ++iter)
+		{
+			LLDrawable* drawable = *iter;
+			LLVOVolume* light = drawable->getVOVolume();
+			if (!light || drawable->isState(LLDrawable::NEARBY_LIGHT))
+			{
+				continue;
+			}
+			if (light->isHUDAttachment())
+			{
+				continue; // no lighting from HUD objects
+			}
+			F32 dist = calc_light_dist(light, cam_pos, max_dist);
+			if (dist >= max_dist)
+			{
+				continue;
+			}
+			if (!sRenderAttachedLights && light && light->isAttachment())
+			{
+				continue;
+			}
+			new_nearby_lights.insert(Light(drawable, dist, 0.f));
+			if (new_nearby_lights.size() > (U32)MAX_LOCAL_LIGHTS)
+			{
+				new_nearby_lights.erase(--new_nearby_lights.end());
+				const Light& last = *new_nearby_lights.rbegin();
+				max_dist = last.dist;
+			}
+		}
+
+		// INSERT ANY NEW LIGHTS
+		for (light_set_t::iterator iter = new_nearby_lights.begin();
+			 iter != new_nearby_lights.end(); iter++)
+		{
+			const Light* light = &(*iter);
+			if (mNearbyLights.size() < (U32)MAX_LOCAL_LIGHTS)
+			{
+				mNearbyLights.insert(*light);
+				((LLDrawable*) light->drawable)->setState(LLDrawable::NEARBY_LIGHT);
+			}
+			else
+			{
+				// crazy cast so that we can overwrite the fade value
+				// even though gcc enforces sets as const
+				// (fade value doesn't affect sort so this is safe)
+				Light* farthest_light = ((Light*) (&(*(mNearbyLights.rbegin()))));
+				if (light->dist < farthest_light->dist)
+				{
+					if (farthest_light->fade >= 0.f)
+					{
+						farthest_light->fade = -gFrameIntervalSeconds;
+					}
+				}
+				else
+				{
+					break; // none of the other lights are closer
+				}
+			}
+		}
+		
+	}
+}
+
+void LLPipeline::setupHWLights(LLDrawPool* pool)
+{
+	assertInitialized();
+	
+	// Ambient
+	if (!LLGLSLShader::sNoFixedFunction)
+	{
+		gGL.syncMatrices();
+		LLColor4 ambient = gSky.getTotalAmbientColor();
+		gGL.setAmbientLightColor(ambient);
+	}
+
+	// Light 0 = Sun or Moon (All objects)
+	{
+		if (gSky.getSunDirection().mV[2] >= LLSky::NIGHTTIME_ELEVATION_COS)
+		{
+			mSunDir.setVec(gSky.getSunDirection());
+			mSunDiffuse.setVec(gSky.getSunDiffuseColor());
+		}
+		else
+		{
+			mSunDir.setVec(gSky.getMoonDirection());
+			mSunDiffuse.setVec(gSky.getMoonDiffuseColor());
+		}
+
+		F32 max_color = llmax(mSunDiffuse.mV[0], mSunDiffuse.mV[1], mSunDiffuse.mV[2]);
+		if (max_color > 1.f)
+		{
+			mSunDiffuse *= 1.f/max_color;
+		}
+		mSunDiffuse.clamp();
+
+		LLVector4 light_pos(mSunDir, 0.0f);
+		LLColor4 light_diffuse = mSunDiffuse;
+		mHWLightColors[0] = light_diffuse;
+
+		LLLightState* light = gGL.getLight(0);
+		light->setPosition(light_pos);
+		light->setDiffuse(light_diffuse);
+		light->setAmbient(LLColor4::black);
+		light->setSpecular(LLColor4::black);
+		light->setConstantAttenuation(1.f);
+		light->setLinearAttenuation(0.f);
+		light->setQuadraticAttenuation(0.f);
+		light->setSpotExponent(0.f);
+		light->setSpotCutoff(180.f);
+	}
+	
+	// Light 1 = Backlight (for avatars)
+	// (set by enableLightsAvatar)
+	
+	S32 cur_light = 2;
+	
+	// Nearby lights = LIGHT 2-7
+
+	mLightMovingMask = 0;
+	
+	if (mLightingDetail >= 1)
+	{
+		for (light_set_t::iterator iter = mNearbyLights.begin();
+			 iter != mNearbyLights.end(); ++iter)
+		{
+			LLDrawable* drawable = iter->drawable;
+			LLVOVolume* light = drawable->getVOVolume();
+			if (!light)
+			{
+				continue;
+			}
+			if (drawable->isState(LLDrawable::ACTIVE))
+			{
+				mLightMovingMask |= (1<<cur_light);
+			}
+			
+			LLColor4  light_color = light->getLightColor();
+			light_color.mV[3] = 0.0f;
+
+			F32 fade = iter->fade;
+			if (fade < LIGHT_FADE_TIME)
+			{
+				// fade in/out light
+				if (fade >= 0.f)
+				{
+					fade = fade / LIGHT_FADE_TIME;
+					((Light*) (&(*iter)))->fade += gFrameIntervalSeconds;
+				}
+				else
+				{
+					fade = 1.f + fade / LIGHT_FADE_TIME;
+					((Light*) (&(*iter)))->fade -= gFrameIntervalSeconds;
+				}
+				fade = llclamp(fade,0.f,1.f);
+				light_color *= fade;
+			}
+
+			LLVector3 light_pos(light->getRenderPosition());
+			LLVector4 light_pos_gl(light_pos, 1.0f);
+	
+			F32 light_radius = llmax(light->getLightRadius(), 0.001f);
+
+			F32 x = (3.f * (1.f + light->getLightFalloff())); // why this magic?  probably trying to match a historic behavior.
+			float linatten = x / (light_radius); // % of brightness at radius
+
+			mHWLightColors[cur_light] = light_color;
+			LLLightState* light_state = gGL.getLight(cur_light);
+			
+			light_state->setPosition(light_pos_gl);
+			light_state->setDiffuse(light_color);
+			light_state->setAmbient(LLColor4::black);
+			light_state->setConstantAttenuation(0.f);
+			if (sRenderDeferred)
+			{
+				light_state->setLinearAttenuation(light_radius*1.5f);
+				light_state->setQuadraticAttenuation(light->getLightFalloff()*0.5f+1.f);
+			}
+			else
+			{
+				light_state->setLinearAttenuation(linatten);
+				light_state->setQuadraticAttenuation(0.f);
+			}
+			
+
+			if (light->isLightSpotlight() // directional (spot-)light
+			    && (LLPipeline::sRenderDeferred || RenderSpotLightsInNondeferred)) // these are only rendered as GL spotlights if we're in deferred rendering mode *or* the setting forces them on
+			{
+				LLVector3 spotparams = light->getSpotLightParams();
+				LLQuaternion quat = light->getRenderRotation();
+				LLVector3 at_axis(0,0,-1); // this matches deferred rendering's object light direction
+				at_axis *= quat;
+
+				light_state->setSpotDirection(at_axis);
+				light_state->setSpotCutoff(90.f);
+				light_state->setSpotExponent(2.f);
+	
+				light_state->setSpecular(LLColor4::black);
+			}
+			else // omnidirectional (point) light
+			{
+				light_state->setSpotExponent(0.f);
+				light_state->setSpotCutoff(180.f);
+				
+				// we use specular.w = 1.0 as a cheap hack for the shaders to know that this is omnidirectional rather than a spotlight
+				const LLColor4 specular(0.f, 0.f, 0.f, 1.f);
+				light_state->setSpecular(specular);				
+			}
+			cur_light++;
+			if (cur_light >= 8)
+			{
+				break; // safety
+			}
+		}
+	}
+	for ( ; cur_light < 8 ; cur_light++)
+	{
+		mHWLightColors[cur_light] = LLColor4::black;
+		LLLightState* light = gGL.getLight(cur_light);
+
+		light->setDiffuse(LLColor4::black);
+		light->setAmbient(LLColor4::black);
+		light->setSpecular(LLColor4::black);
+	}
+	if (gAgentAvatarp &&
+		gAgentAvatarp->mSpecialRenderMode == 3)
+	{
+		LLColor4  light_color = LLColor4::white;
+		light_color.mV[3] = 0.0f;
+
+		LLVector3 light_pos(LLViewerCamera::getInstance()->getOrigin());
+		LLVector4 light_pos_gl(light_pos, 1.0f);
+
+		F32 light_radius = 16.f;
+
+			F32 x = 3.f;
+		float linatten = x / (light_radius); // % of brightness at radius
+
+		mHWLightColors[2] = light_color;
+		LLLightState* light = gGL.getLight(2);
+
+		light->setPosition(light_pos_gl);
+		light->setDiffuse(light_color);
+		light->setAmbient(LLColor4::black);
+		light->setSpecular(LLColor4::black);
+		light->setQuadraticAttenuation(0.f);
+		light->setConstantAttenuation(0.f);
+		light->setLinearAttenuation(linatten);
+		light->setSpotExponent(0.f);
+		light->setSpotCutoff(180.f);
+	}
+
+	// Init GL state
+	if (!LLGLSLShader::sNoFixedFunction)
+	{
+		glDisable(GL_LIGHTING);
+	}
+
+	for (S32 i = 0; i < 8; ++i)
+	{
+		gGL.getLight(i)->disable();
+	}
+	mLightMask = 0;
+}
+
+void LLPipeline::enableLights(U32 mask)
+{
+	assertInitialized();
+
+	if (mLightingDetail == 0)
+	{
+		mask &= 0xf003; // sun and backlight only (and fullbright bit)
+	}
+	if (mLightMask != mask)
+	{
+		stop_glerror();
+		if (!mLightMask)
+		{
+			if (!LLGLSLShader::sNoFixedFunction)
+			{
+				glEnable(GL_LIGHTING);
+			}
+		}
+		if (mask)
+		{
+			stop_glerror();
+			for (S32 i=0; i<8; i++)
+			{
+				LLLightState* light = gGL.getLight(i);
+				if (mask & (1<<i))
+				{
+					light->enable();
+					light->setDiffuse(mHWLightColors[i]);
+				}
+				else
+				{
+					light->disable();
+					light->setDiffuse(LLColor4::black);
+				}
+			}
+			stop_glerror();
+		}
+		else
+		{
+			if (!LLGLSLShader::sNoFixedFunction)
+			{
+				glDisable(GL_LIGHTING);
+			}
+		}
+		mLightMask = mask;
+		stop_glerror();
+
+		LLColor4 ambient = gSky.getTotalAmbientColor();
+		gGL.setAmbientLightColor(ambient);
+	}
+}
+
+void LLPipeline::enableLightsStatic()
+{
+	assertInitialized();
+	U32 mask = 0x01; // Sun
+	if (mLightingDetail >= 2)
+	{
+		mask |= mLightMovingMask; // Hardware moving lights
+	}
+	else
+	{
+		mask |= 0xff & (~2); // Hardware local lights
+	}
+	enableLights(mask);
+}
+
+void LLPipeline::enableLightsDynamic()
+{
+	assertInitialized();
+	U32 mask = 0xff & (~2); // Local lights
+	enableLights(mask);
+	
+	if (isAgentAvatarValid() && getLightingDetail() <= 0)
+	{
+		if (gAgentAvatarp->mSpecialRenderMode == 0) // normal
+		{
+			gPipeline.enableLightsAvatar();
+		}
+		else if (gAgentAvatarp->mSpecialRenderMode >= 1)  // anim preview
+		{
+			gPipeline.enableLightsAvatarEdit(LLColor4(0.7f, 0.6f, 0.3f, 1.f));
+		}
+	}
+}
+
+void LLPipeline::enableLightsAvatar()
+{
+	U32 mask = 0xff; // All lights
+	setupAvatarLights(FALSE);
+	enableLights(mask);
+}
+
+void LLPipeline::enableLightsPreview()
+{
+	disableLights();
+
+	if (!LLGLSLShader::sNoFixedFunction)
+	{
+		glEnable(GL_LIGHTING);
+	}
+
+	LLColor4 ambient = PreviewAmbientColor;
+	gGL.setAmbientLightColor(ambient);
+
+	LLColor4 diffuse0 = PreviewDiffuse0;
+	LLColor4 specular0 = PreviewSpecular0;
+	LLColor4 diffuse1 = PreviewDiffuse1;
+	LLColor4 specular1 = PreviewSpecular1;
+	LLColor4 diffuse2 = PreviewDiffuse2;
+	LLColor4 specular2 = PreviewSpecular2;
+
+	LLVector3 dir0 = PreviewDirection0;
+	LLVector3 dir1 = PreviewDirection1;
+	LLVector3 dir2 = PreviewDirection2;
+
+	dir0.normVec();
+	dir1.normVec();
+	dir2.normVec();
+	
+	LLVector4 light_pos(dir0, 0.0f);
+
+	LLLightState* light = gGL.getLight(0);
+
+	light->enable();
+	light->setPosition(light_pos);
+	light->setDiffuse(diffuse0);
+	light->setAmbient(LLColor4::black);
+	light->setSpecular(specular0);
+	light->setSpotExponent(0.f);
+	light->setSpotCutoff(180.f);
+
+	light_pos = LLVector4(dir1, 0.f);
+
+	light = gGL.getLight(1);
+	light->enable();
+	light->setPosition(light_pos);
+	light->setDiffuse(diffuse1);
+	light->setAmbient(LLColor4::black);
+	light->setSpecular(specular1);
+	light->setSpotExponent(0.f);
+	light->setSpotCutoff(180.f);
+
+	light_pos = LLVector4(dir2, 0.f);
+	light = gGL.getLight(2);
+	light->enable();
+	light->setPosition(light_pos);
+	light->setDiffuse(diffuse2);
+	light->setAmbient(LLColor4::black);
+	light->setSpecular(specular2);
+	light->setSpotExponent(0.f);
+	light->setSpotCutoff(180.f);
+}
+
+
+void LLPipeline::enableLightsAvatarEdit(const LLColor4& color)
+{
+	U32 mask = 0x2002; // Avatar backlight only, set ambient
+	setupAvatarLights(TRUE);
+	enableLights(mask);
+
+	gGL.setAmbientLightColor(color);
+}
+
+void LLPipeline::enableLightsFullbright(const LLColor4& color)
+{
+	assertInitialized();
+	U32 mask = 0x1000; // Non-0 mask, set ambient
+	enableLights(mask);
+
+	gGL.setAmbientLightColor(color);
+}
+
+void LLPipeline::disableLights()
+{
+	enableLights(0); // no lighting (full bright)
+}
+
+//============================================================================
+
+class LLMenuItemGL;
+class LLInvFVBridge;
+struct cat_folder_pair;
+class LLVOBranch;
+class LLVOLeaf;
+
+void LLPipeline::findReferences(LLDrawable *drawablep)
+{
+	assertInitialized();
+	if (mLights.find(drawablep) != mLights.end())
+	{
+		llinfos << "In mLights" << llendl;
+	}
+	if (std::find(mMovedList.begin(), mMovedList.end(), drawablep) != mMovedList.end())
+	{
+		llinfos << "In mMovedList" << llendl;
+	}
+	if (std::find(mShiftList.begin(), mShiftList.end(), drawablep) != mShiftList.end())
+	{
+		llinfos << "In mShiftList" << llendl;
+	}
+	if (mRetexturedList.find(drawablep) != mRetexturedList.end())
+	{
+		llinfos << "In mRetexturedList" << llendl;
+	}
+	
+	if (std::find(mBuildQ1.begin(), mBuildQ1.end(), drawablep) != mBuildQ1.end())
+	{
+		llinfos << "In mBuildQ1" << llendl;
+	}
+	if (std::find(mBuildQ2.begin(), mBuildQ2.end(), drawablep) != mBuildQ2.end())
+	{
+		llinfos << "In mBuildQ2" << llendl;
+	}
+
+	S32 count;
+	
+	count = gObjectList.findReferences(drawablep);
+	if (count)
+	{
+		llinfos << "In other drawables: " << count << " references" << llendl;
+	}
+}
+
+BOOL LLPipeline::verify()
+{
+	BOOL ok = assertInitialized();
+	if (ok) 
+	{
+		for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
+		{
+			LLDrawPool *poolp = *iter;
+			if (!poolp->verify())
+			{
+				ok = FALSE;
+			}
+		}
+	}
+
+	if (!ok)
+	{
+		llwarns << "Pipeline verify failed!" << llendl;
+	}
+	return ok;
+}
+
+//////////////////////////////
+//
+// Collision detection
+//
+//
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	A method to compute a ray-AABB intersection.
+ *	Original code by Andrew Woo, from "Graphics Gems", Academic Press, 1990
+ *	Optimized code by Pierre Terdiman, 2000 (~20-30% faster on my Celeron 500)
+ *	Epsilon value added by Klaus Hartmann. (discarding it saves a few cycles only)
+ *
+ *	Hence this version is faster as well as more robust than the original one.
+ *
+ *	Should work provided:
+ *	1) the integer representation of 0.0f is 0x00000000
+ *	2) the sign bit of the float is the most significant one
+ *
+ *	Report bugs: p.terdiman@codercorner.com
+ *
+ *	\param		aabb		[in] the axis-aligned bounding box
+ *	\param		origin		[in] ray origin
+ *	\param		dir			[in] ray direction
+ *	\param		coord		[out] impact coordinates
+ *	\return		true if ray intersects AABB
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//#define RAYAABB_EPSILON 0.00001f
+#define IR(x)	((U32&)x)
+
+bool LLRayAABB(const LLVector3 &center, const LLVector3 &size, const LLVector3& origin, const LLVector3& dir, LLVector3 &coord, F32 epsilon)
+{
+	BOOL Inside = TRUE;
+	LLVector3 MinB = center - size;
+	LLVector3 MaxB = center + size;
+	LLVector3 MaxT;
+	MaxT.mV[VX]=MaxT.mV[VY]=MaxT.mV[VZ]=-1.0f;
+
+	// Find candidate planes.
+	for(U32 i=0;i<3;i++)
+	{
+		if(origin.mV[i] < MinB.mV[i])
+		{
+			coord.mV[i]	= MinB.mV[i];
+			Inside		= FALSE;
+
+			// Calculate T distances to candidate planes
+			if(IR(dir.mV[i]))	MaxT.mV[i] = (MinB.mV[i] - origin.mV[i]) / dir.mV[i];
+		}
+		else if(origin.mV[i] > MaxB.mV[i])
+		{
+			coord.mV[i]	= MaxB.mV[i];
+			Inside		= FALSE;
+
+			// Calculate T distances to candidate planes
+			if(IR(dir.mV[i]))	MaxT.mV[i] = (MaxB.mV[i] - origin.mV[i]) / dir.mV[i];
+		}
+	}
+
+	// Ray origin inside bounding box
+	if(Inside)
+	{
+		coord = origin;
+		return true;
+	}
+
+	// Get largest of the maxT's for final choice of intersection
+	U32 WhichPlane = 0;
+	if(MaxT.mV[1] > MaxT.mV[WhichPlane])	WhichPlane = 1;
+	if(MaxT.mV[2] > MaxT.mV[WhichPlane])	WhichPlane = 2;
+
+	// Check final candidate actually inside box
+	if(IR(MaxT.mV[WhichPlane])&0x80000000) return false;
+
+	for(U32 i=0;i<3;i++)
+	{
+		if(i!=WhichPlane)
+		{
+			coord.mV[i] = origin.mV[i] + MaxT.mV[WhichPlane] * dir.mV[i];
+			if (epsilon > 0)
+			{
+				if(coord.mV[i] < MinB.mV[i] - epsilon || coord.mV[i] > MaxB.mV[i] + epsilon)	return false;
+			}
+			else
+			{
+				if(coord.mV[i] < MinB.mV[i] || coord.mV[i] > MaxB.mV[i])	return false;
+			}
+		}
+	}
+	return true;	// ray hits box
+}
+
+//////////////////////////////
+//
+// Macros, functions, and inline methods from other classes
+//
+//
+
+void LLPipeline::setLight(LLDrawable *drawablep, BOOL is_light)
+{
+	if (drawablep && assertInitialized())
+	{
+		if (is_light)
+		{
+			mLights.insert(drawablep);
+			drawablep->setState(LLDrawable::LIGHT);
+		}
+		else
+		{
+			drawablep->clearState(LLDrawable::LIGHT);
+			mLights.erase(drawablep);
+		}
+	}
+}
+
+//static
+void LLPipeline::toggleRenderType(U32 type)
+{
+	gPipeline.mRenderTypeEnabled[type] = !gPipeline.mRenderTypeEnabled[type];
+	if (type == LLPipeline::RENDER_TYPE_WATER)
+	{
+		gPipeline.mRenderTypeEnabled[LLPipeline::RENDER_TYPE_VOIDWATER] = !gPipeline.mRenderTypeEnabled[LLPipeline::RENDER_TYPE_VOIDWATER];
+	}
+}
+
+//static
+void LLPipeline::toggleRenderTypeControl(void* data)
+{
+	U32 type = (U32)(intptr_t)data;
+	U32 bit = (1<<type);
+	if (gPipeline.hasRenderType(type))
+	{
+		llinfos << "Toggling render type mask " << std::hex << bit << " off" << std::dec << llendl;
+	}
+	else
+	{
+		llinfos << "Toggling render type mask " << std::hex << bit << " on" << std::dec << llendl;
+	}
+	gPipeline.toggleRenderType(type);
+}
+
+//static
+BOOL LLPipeline::hasRenderTypeControl(void* data)
+{
+	U32 type = (U32)(intptr_t)data;
+	return gPipeline.hasRenderType(type);
+}
+
+// Allows UI items labeled "Hide foo" instead of "Show foo"
+//static
+BOOL LLPipeline::toggleRenderTypeControlNegated(void* data)
+{
+	S32 type = (S32)(intptr_t)data;
+	return !gPipeline.hasRenderType(type);
+}
+
+//static
+void LLPipeline::toggleRenderDebug(void* data)
+{
+	U32 bit = (U32)(intptr_t)data;
+	if (gPipeline.hasRenderDebugMask(bit))
+	{
+		llinfos << "Toggling render debug mask " << std::hex << bit << " off" << std::dec << llendl;
+	}
+	else
+	{
+		llinfos << "Toggling render debug mask " << std::hex << bit << " on" << std::dec << llendl;
+	}
+	gPipeline.mRenderDebugMask ^= bit;
+}
+
+
+//static
+BOOL LLPipeline::toggleRenderDebugControl(void* data)
+{
+	U32 bit = (U32)(intptr_t)data;
+	return gPipeline.hasRenderDebugMask(bit);
+}
+
+//static
+void LLPipeline::toggleRenderDebugFeature(void* data)
+{
+	U32 bit = (U32)(intptr_t)data;
+	gPipeline.mRenderDebugFeatureMask ^= bit;
+}
+
+
+//static
+BOOL LLPipeline::toggleRenderDebugFeatureControl(void* data)
+{
+	U32 bit = (U32)(intptr_t)data;
+	return gPipeline.hasRenderDebugFeatureMask(bit);
+}
+
+void LLPipeline::setRenderDebugFeatureControl(U32 bit, bool value)
+{
+	if (value)
+	{
+		gPipeline.mRenderDebugFeatureMask |= bit;
+	}
+	else
+	{
+		gPipeline.mRenderDebugFeatureMask &= !bit;
+	}
+}
+
+// static
+void LLPipeline::setRenderScriptedBeacons(BOOL val)
+{
+	sRenderScriptedBeacons = val;
+}
+
+// static
+void LLPipeline::toggleRenderScriptedBeacons(void*)
+{
+	sRenderScriptedBeacons = !sRenderScriptedBeacons;
+}
+
+// static
+BOOL LLPipeline::getRenderScriptedBeacons(void*)
+{
+	return sRenderScriptedBeacons;
+}
+
+// static
+void LLPipeline::setRenderScriptedTouchBeacons(BOOL val)
+{
+	sRenderScriptedTouchBeacons = val;
+}
+
+// static
+void LLPipeline::toggleRenderScriptedTouchBeacons(void*)
+{
+	sRenderScriptedTouchBeacons = !sRenderScriptedTouchBeacons;
+}
+
+// static
+BOOL LLPipeline::getRenderScriptedTouchBeacons(void*)
+{
+	return sRenderScriptedTouchBeacons;
+}
+
+// static
+void LLPipeline::setRenderMOAPBeacons(BOOL val)
+{
+	sRenderMOAPBeacons = val;
+}
+
+// static
+void LLPipeline::toggleRenderMOAPBeacons(void*)
+{
+	sRenderMOAPBeacons = !sRenderMOAPBeacons;
+}
+
+// static
+BOOL LLPipeline::getRenderMOAPBeacons(void*)
+{
+	return sRenderMOAPBeacons;
+}
+
+// static
+void LLPipeline::setRenderPhysicalBeacons(BOOL val)
+{
+	sRenderPhysicalBeacons = val;
+}
+
+// static
+void LLPipeline::toggleRenderPhysicalBeacons(void*)
+{
+	sRenderPhysicalBeacons = !sRenderPhysicalBeacons;
+}
+
+// static
+BOOL LLPipeline::getRenderPhysicalBeacons(void*)
+{
+	return sRenderPhysicalBeacons;
+}
+
+// static
+void LLPipeline::setRenderParticleBeacons(BOOL val)
+{
+	sRenderParticleBeacons = val;
+}
+
+// static
+void LLPipeline::toggleRenderParticleBeacons(void*)
+{
+	sRenderParticleBeacons = !sRenderParticleBeacons;
+}
+
+// static
+BOOL LLPipeline::getRenderParticleBeacons(void*)
+{
+	return sRenderParticleBeacons;
+}
+
+// static
+void LLPipeline::setRenderSoundBeacons(BOOL val)
+{
+	sRenderSoundBeacons = val;
+}
+
+// static
+void LLPipeline::toggleRenderSoundBeacons(void*)
+{
+	sRenderSoundBeacons = !sRenderSoundBeacons;
+}
+
+// static
+BOOL LLPipeline::getRenderSoundBeacons(void*)
+{
+	return sRenderSoundBeacons;
+}
+
+// static
+void LLPipeline::setRenderBeacons(BOOL val)
+{
+	sRenderBeacons = val;
+}
+
+// static
+void LLPipeline::toggleRenderBeacons(void*)
+{
+	sRenderBeacons = !sRenderBeacons;
+}
+
+// static
+BOOL LLPipeline::getRenderBeacons(void*)
+{
+	return sRenderBeacons;
+}
+
+// static
+void LLPipeline::setRenderHighlights(BOOL val)
+{
+	sRenderHighlight = val;
+}
+
+// static
+void LLPipeline::toggleRenderHighlights(void*)
+{
+	sRenderHighlight = !sRenderHighlight;
+}
+
+// static
+BOOL LLPipeline::getRenderHighlights(void*)
+{
+	return sRenderHighlight;
+}
+
+LLViewerObject* LLPipeline::lineSegmentIntersectInWorld(const LLVector3& start, const LLVector3& end,
+														BOOL pick_transparent,												
+														S32* face_hit,
+														LLVector3* intersection,         // return the intersection point
+														LLVector2* tex_coord,            // return the texture coordinates of the intersection point
+														LLVector3* normal,               // return the surface normal at the intersection point
+														LLVector3* bi_normal             // return the surface bi-normal at the intersection point
+	)
+{
+	LLDrawable* drawable = NULL;
+
+	LLVector3 local_end = end;
+
+	LLVector3 position;
+
+	sPickAvatar = FALSE; //LLToolMgr::getInstance()->inBuildMode() ? FALSE : TRUE;
+	
+	for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
+			iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
+	{
+		LLViewerRegion* region = *iter;
+
+		for (U32 j = 0; j < LLViewerRegion::NUM_PARTITIONS; j++)
+		{
+			if ((j == LLViewerRegion::PARTITION_VOLUME) || 
+				(j == LLViewerRegion::PARTITION_BRIDGE) || 
+				(j == LLViewerRegion::PARTITION_TERRAIN) ||
+				(j == LLViewerRegion::PARTITION_TREE) ||
+				(j == LLViewerRegion::PARTITION_GRASS))  // only check these partitions for now
+			{
+				LLSpatialPartition* part = region->getSpatialPartition(j);
+				if (part && hasRenderType(part->mDrawableType))
+				{
+					LLDrawable* hit = part->lineSegmentIntersect(start, local_end, pick_transparent, face_hit, &position, tex_coord, normal, bi_normal);
+					if (hit)
+					{
+						drawable = hit;
+						local_end = position;						
+					}
+				}
+			}
+		}
+	}
+	
+	if (!sPickAvatar)
+	{
+		//save hit info in case we need to restore
+		//due to attachment override
+		LLVector3 local_normal;
+		LLVector3 local_binormal;
+		LLVector2 local_texcoord;
+		S32 local_face_hit = -1;
+
+		if (face_hit)
+		{ 
+			local_face_hit = *face_hit;
+		}
+		if (tex_coord)
+		{
+			local_texcoord = *tex_coord;
+		}
+		if (bi_normal)
+		{
+			local_binormal = *bi_normal;
+		}
+		if (normal)
+		{
+			local_normal = *normal;
+		}
+				
+		const F32 ATTACHMENT_OVERRIDE_DIST = 0.1f;
+
+		//check against avatars
+		sPickAvatar = TRUE;
+		for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
+				iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
+		{
+			LLViewerRegion* region = *iter;
+
+			LLSpatialPartition* part = region->getSpatialPartition(LLViewerRegion::PARTITION_BRIDGE);
+			if (part && hasRenderType(part->mDrawableType))
+			{
+				LLDrawable* hit = part->lineSegmentIntersect(start, local_end, pick_transparent, face_hit, &position, tex_coord, normal, bi_normal);
+				if (hit)
+				{
+					if (!drawable || 
+						!drawable->getVObj()->isAttachment() ||
+						(position-local_end).magVec() > ATTACHMENT_OVERRIDE_DIST)
+					{ //avatar overrides if previously hit drawable is not an attachment or 
+					  //attachment is far enough away from detected intersection
+						drawable = hit;
+						local_end = position;						
+					}
+					else
+					{ //prioritize attachments over avatars
+						position = local_end;
+
+						if (face_hit)
+						{
+							*face_hit = local_face_hit;
+						}
+						if (tex_coord)
+						{
+							*tex_coord = local_texcoord;
+						}
+						if (bi_normal)
+						{
+							*bi_normal = local_binormal;
+						}
+						if (normal)
+						{
+							*normal = local_normal;
+						}
+					}
+				}
+			}
+		}
+	}
+
+	//check all avatar nametags (silly, isn't it?)
+	for (std::vector< LLCharacter* >::iterator iter = LLCharacter::sInstances.begin();
+		iter != LLCharacter::sInstances.end();
+		++iter)
+	{
+		LLVOAvatar* av = (LLVOAvatar*) *iter;
+		if (av->mNameText.notNull()
+			&& av->mNameText->lineSegmentIntersect(start, local_end, position))
+		{
+			drawable = av->mDrawable;
+			local_end = position;
+		}
+	}
+
+	if (intersection)
+	{
+		*intersection = position;
+	}
+
+	return drawable ? drawable->getVObj().get() : NULL;
+}
+
+LLViewerObject* LLPipeline::lineSegmentIntersectInHUD(const LLVector3& start, const LLVector3& end,
+													  BOOL pick_transparent,													
+													  S32* face_hit,
+													  LLVector3* intersection,         // return the intersection point
+													  LLVector2* tex_coord,            // return the texture coordinates of the intersection point
+													  LLVector3* normal,               // return the surface normal at the intersection point
+													  LLVector3* bi_normal             // return the surface bi-normal at the intersection point
+	)
+{
+	LLDrawable* drawable = NULL;
+
+	for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
+			iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
+	{
+		LLViewerRegion* region = *iter;
+
+		BOOL toggle = FALSE;
+		if (!hasRenderType(LLPipeline::RENDER_TYPE_HUD))
+		{
+			toggleRenderType(LLPipeline::RENDER_TYPE_HUD);
+			toggle = TRUE;
+		}
+
+		LLSpatialPartition* part = region->getSpatialPartition(LLViewerRegion::PARTITION_HUD);
+		if (part)
+		{
+			LLDrawable* hit = part->lineSegmentIntersect(start, end, pick_transparent, face_hit, intersection, tex_coord, normal, bi_normal);
+			if (hit)
+			{
+				drawable = hit;
+			}
+		}
+
+		if (toggle)
+		{
+			toggleRenderType(LLPipeline::RENDER_TYPE_HUD);
+		}
+	}
+	return drawable ? drawable->getVObj().get() : NULL;
+}
+
+LLSpatialPartition* LLPipeline::getSpatialPartition(LLViewerObject* vobj)
+{
+	if (vobj)
+	{
+		LLViewerRegion* region = vobj->getRegion();
+		if (region)
+		{
+			return region->getSpatialPartition(vobj->getPartitionType());
+		}
+	}
+	return NULL;
+}
+
+void LLPipeline::resetVertexBuffers(LLDrawable* drawable)
+{
+	if (!drawable || drawable->isDead())
+	{
+		return;
+	}
+
+	for (S32 i = 0; i < drawable->getNumFaces(); i++)
+	{
+		LLFace* facep = drawable->getFace(i);
+		facep->clearVertexBuffer();
+	}
+}
+
+void LLPipeline::resetVertexBuffers()
+{	
+	for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
+			iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
+	{
+		LLViewerRegion* region = *iter;
+		for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
+		{
+			LLSpatialPartition* part = region->getSpatialPartition(i);
+			if (part)
+			{
+				part->resetVertexBuffers();
+			}
+		}
+	}
+
+	resetDrawOrders();
+
+	gSky.resetVertexBuffers();
+
+	if ( LLPathingLib::getInstance() )
+	{
+		LLPathingLib::getInstance()->cleanupVBOManger();
+	}
+	LLVertexBuffer::cleanupClass();
+	
+	//delete all name pool caches
+	LLGLNamePool::cleanupPools();
+
+	if (LLVertexBuffer::sGLCount > 0)
+	{
+		llwarns << "VBO wipe failed." << llendl;
+	}
+
+	llassert(LLVertexBuffer::sGLCount == 0);
+
+	LLVertexBuffer::unbind();	
+	
+	sRenderBump = gSavedSettings.getBOOL("RenderObjectBump");
+	sUseTriStrips = gSavedSettings.getBOOL("RenderUseTriStrips");
+	LLVertexBuffer::sUseStreamDraw = gSavedSettings.getBOOL("RenderUseStreamVBO");
+	LLVertexBuffer::sUseVAO = gSavedSettings.getBOOL("RenderUseVAO");
+	LLVertexBuffer::sPreferStreamDraw = gSavedSettings.getBOOL("RenderPreferStreamDraw");
+	LLVertexBuffer::sEnableVBOs = gSavedSettings.getBOOL("RenderVBOEnable");
+	LLVertexBuffer::sDisableVBOMapping = LLVertexBuffer::sEnableVBOs && gSavedSettings.getBOOL("RenderVBOMappingDisable") ;
+	sBakeSunlight = gSavedSettings.getBOOL("RenderBakeSunlight");
+	sNoAlpha = gSavedSettings.getBOOL("RenderNoAlpha");
+	LLPipeline::sTextureBindTest = gSavedSettings.getBOOL("RenderDebugTextureBind");
+
+	LLVertexBuffer::initClass(LLVertexBuffer::sEnableVBOs, LLVertexBuffer::sDisableVBOMapping);
+}
+
+void LLPipeline::renderObjects(U32 type, U32 mask, BOOL texture, BOOL batch_texture)
+{
+	LLMemType mt_ro(LLMemType::MTYPE_PIPELINE_RENDER_OBJECTS);
+	assertInitialized();
+	gGL.loadMatrix(gGLModelView);
+	gGLLastMatrix = NULL;
+	mSimplePool->pushBatches(type, mask, texture, batch_texture);
+	gGL.loadMatrix(gGLModelView);
+	gGLLastMatrix = NULL;		
+}
+
+void apply_cube_face_rotation(U32 face)
+{
+	switch (face)
+	{
+		case 0: 
+			gGL.rotatef(90.f, 0, 1, 0);
+			gGL.rotatef(180.f, 1, 0, 0);
+		break;
+		case 2: 
+			gGL.rotatef(-90.f, 1, 0, 0);
+		break;
+		case 4:
+			gGL.rotatef(180.f, 0, 1, 0);
+			gGL.rotatef(180.f, 0, 0, 1);
+		break;
+		case 1: 
+			gGL.rotatef(-90.f, 0, 1, 0);
+			gGL.rotatef(180.f, 1, 0, 0);
+		break;
+		case 3:
+			gGL.rotatef(90, 1, 0, 0);
+		break;
+		case 5: 
+			gGL.rotatef(180, 0, 0, 1);
+		break;
+	}
+}
+
+void validate_framebuffer_object()
+{                                                           
+	GLenum status;                                            
+	status = glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT); 
+	switch(status) 
+	{                                          
+		case GL_FRAMEBUFFER_COMPLETE:                       
+			//framebuffer OK, no error.
+			break;
+		case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
+			// frame buffer not OK: probably means unsupported depth buffer format
+			llerrs << "Framebuffer Incomplete Missing Attachment." << llendl;
+			break;
+		case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
+			// frame buffer not OK: probably means unsupported depth buffer format
+			llerrs << "Framebuffer Incomplete Attachment." << llendl;
+			break; 
+		case GL_FRAMEBUFFER_UNSUPPORTED:                    
+			/* choose different formats */                        
+			llerrs << "Framebuffer unsupported." << llendl;
+			break;                                                
+		default:                                                
+			llerrs << "Unknown framebuffer status." << llendl;
+			break;
+	}
+}
+
+void LLPipeline::bindScreenToTexture() 
+{
+	
+}
+
+static LLFastTimer::DeclareTimer FTM_RENDER_BLOOM("Bloom");
+
+void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield)
+{
+	LLMemType mt_ru(LLMemType::MTYPE_PIPELINE_RENDER_BLOOM);
+	if (!(gPipeline.canUseVertexShaders() &&
+		sRenderGlow))
+	{
+		return;
+	}
+
+	LLVertexBuffer::unbind();
+	LLGLState::checkStates();
+	LLGLState::checkTextureChannels();
+
+	assertInitialized();
+
+	if (gUseWireframe)
+	{
+		glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+	}
+
+	LLVector2 tc1(0,0);
+	LLVector2 tc2((F32) mScreen.getWidth()*2,
+				  (F32) mScreen.getHeight()*2);
+
+	LLFastTimer ftm(FTM_RENDER_BLOOM);
+	gGL.color4f(1,1,1,1);
+	LLGLDepthTest depth(GL_FALSE);
+	LLGLDisable blend(GL_BLEND);
+	LLGLDisable cull(GL_CULL_FACE);
+	
+	enableLightsFullbright(LLColor4(1,1,1,1));
+
+	gGL.matrixMode(LLRender::MM_PROJECTION);
+	gGL.pushMatrix();
+	gGL.loadIdentity();
+	gGL.matrixMode(LLRender::MM_MODELVIEW);
+	gGL.pushMatrix();
+	gGL.loadIdentity();
+
+	LLGLDisable test(GL_ALPHA_TEST);
+
+	gGL.setColorMask(true, true);
+	glClearColor(0,0,0,0);
+		
+	{
+		{
+			LLFastTimer ftm(FTM_RENDER_BLOOM_FBO);
+			mGlow[2].bindTarget();
+			mGlow[2].clear();
+		}
+		
+		gGlowExtractProgram.bind();
+		F32 minLum = llmax((F32) RenderGlowMinLuminance, 0.0f);
+		F32 maxAlpha = RenderGlowMaxExtractAlpha;		
+		F32 warmthAmount = RenderGlowWarmthAmount;	
+		LLVector3 lumWeights = RenderGlowLumWeights;
+		LLVector3 warmthWeights = RenderGlowWarmthWeights;
+
+
+		gGlowExtractProgram.uniform1f(LLShaderMgr::GLOW_MIN_LUMINANCE, minLum);
+		gGlowExtractProgram.uniform1f(LLShaderMgr::GLOW_MAX_EXTRACT_ALPHA, maxAlpha);
+		gGlowExtractProgram.uniform3f(LLShaderMgr::GLOW_LUM_WEIGHTS, lumWeights.mV[0], lumWeights.mV[1], lumWeights.mV[2]);
+		gGlowExtractProgram.uniform3f(LLShaderMgr::GLOW_WARMTH_WEIGHTS, warmthWeights.mV[0], warmthWeights.mV[1], warmthWeights.mV[2]);
+		gGlowExtractProgram.uniform1f(LLShaderMgr::GLOW_WARMTH_AMOUNT, warmthAmount);
+		LLGLEnable blend_on(GL_BLEND);
+		LLGLEnable test(GL_ALPHA_TEST);
+		
+		gGL.setSceneBlendType(LLRender::BT_ADD_WITH_ALPHA);
+		
+		mScreen.bindTexture(0, 0);
+		
+		gGL.color4f(1,1,1,1);
+		gPipeline.enableLightsFullbright(LLColor4(1,1,1,1));
+		gGL.begin(LLRender::TRIANGLE_STRIP);
+		gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
+		gGL.vertex2f(-1,-1);
+		
+		gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
+		gGL.vertex2f(-1,3);
+		
+		gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
+		gGL.vertex2f(3,-1);
+		
+		gGL.end();
+		
+		gGL.getTexUnit(0)->unbind(mScreen.getUsage());
+
+		mGlow[2].flush();
+	}
+
+	tc1.setVec(0,0);
+	tc2.setVec(2,2);
+
+	// power of two between 1 and 1024
+	U32 glowResPow = RenderGlowResolutionPow;
+	const U32 glow_res = llmax(1, 
+		llmin(1024, 1 << glowResPow));
+
+	S32 kernel = RenderGlowIterations*2;
+	F32 delta = RenderGlowWidth / glow_res;
+	// Use half the glow width if we have the res set to less than 9 so that it looks
+	// almost the same in either case.
+	if (glowResPow < 9)
+	{
+		delta *= 0.5f;
+	}
+	F32 strength = RenderGlowStrength;
+
+	gGlowProgram.bind();
+	gGlowProgram.uniform1f(LLShaderMgr::GLOW_STRENGTH, strength);
+
+	for (S32 i = 0; i < kernel; i++)
+	{
+		{
+			LLFastTimer ftm(FTM_RENDER_BLOOM_FBO);
+			mGlow[i%2].bindTarget();
+			mGlow[i%2].clear();
+		}
+			
+		if (i == 0)
+		{
+			gGL.getTexUnit(0)->bind(&mGlow[2]);
+		}
+		else
+		{
+			gGL.getTexUnit(0)->bind(&mGlow[(i-1)%2]);
+		}
+
+		if (i%2 == 0)
+		{
+			gGlowProgram.uniform2f(LLShaderMgr::GLOW_DELTA, delta, 0);
+		}
+		else
+		{
+			gGlowProgram.uniform2f(LLShaderMgr::GLOW_DELTA, 0, delta);
+		}
+
+		gGL.begin(LLRender::TRIANGLE_STRIP);
+		gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
+		gGL.vertex2f(-1,-1);
+		
+		gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
+		gGL.vertex2f(-1,3);
+		
+		gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
+		gGL.vertex2f(3,-1);
+		
+		gGL.end();
+		
+		mGlow[i%2].flush();
+	}
+
+	gGlowProgram.unbind();
+
+	if (LLRenderTarget::sUseFBO)
+	{
+		LLFastTimer ftm(FTM_RENDER_BLOOM_FBO);
+		glBindFramebuffer(GL_FRAMEBUFFER, 0);
+	}
+
+	gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft;
+	gGLViewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom;
+	gGLViewport[2] = gViewerWindow->getWorldViewRectRaw().getWidth();
+	gGLViewport[3] = gViewerWindow->getWorldViewRectRaw().getHeight();
+	glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
+
+	tc2.setVec((F32) mScreen.getWidth(),
+			(F32) mScreen.getHeight());
+
+	gGL.flush();
+	
+	LLVertexBuffer::unbind();
+
+	if (LLPipeline::sRenderDeferred)
+	{
+
+		bool dof_enabled = !LLViewerCamera::getInstance()->cameraUnderWater() &&
+							!LLToolMgr::getInstance()->inBuildMode() &&
+							RenderDepthOfField;
+
+
+		bool multisample = RenderFSAASamples > 1 && mFXAABuffer.isComplete();
+
+		gViewerWindow->setup3DViewport();
+				
+		if (dof_enabled)
+		{
+			LLGLSLShader* shader = &gDeferredPostProgram;
+			LLGLDisable blend(GL_BLEND);
+
+			//depth of field focal plane calculations
+			static F32 current_distance = 16.f;
+			static F32 start_distance = 16.f;
+			static F32 transition_time = 1.f;
+
+			LLVector3 focus_point;
+
+			LLViewerObject* obj = LLViewerMediaFocus::getInstance()->getFocusedObject();
+			if (obj && obj->mDrawable && obj->isSelected())
+			{ //focus on selected media object
+				S32 face_idx = LLViewerMediaFocus::getInstance()->getFocusedFace();
+				if (obj && obj->mDrawable)
+				{
+					LLFace* face = obj->mDrawable->getFace(face_idx);
+					if (face)
+					{
+						focus_point = face->getPositionAgent();
+					}
+				}
+			}
+		
+			if (focus_point.isExactlyZero())
+			{
+				if (LLViewerJoystick::getInstance()->getOverrideCamera())
+				{ //focus on point under cursor
+					focus_point = gDebugRaycastIntersection;
+				}
+				else if (gAgentCamera.cameraMouselook())
+				{ //focus on point under mouselook crosshairs
+					gViewerWindow->cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE,
+													NULL,
+													&focus_point);
+				}
+				else
+				{
+					LLViewerObject* obj = gAgentCamera.getFocusObject();
+					if (obj)
+					{ //focus on alt-zoom target
+						focus_point = LLVector3(gAgentCamera.getFocusGlobal()-gAgent.getRegion()->getOriginGlobal());
+					}
+					else
+					{ //focus on your avatar
+						focus_point = gAgent.getPositionAgent();
+					}
+				}
+			}
+
+			LLVector3 eye = LLViewerCamera::getInstance()->getOrigin();
+			F32 target_distance = 16.f;
+			if (!focus_point.isExactlyZero())
+			{
+				target_distance = LLViewerCamera::getInstance()->getAtAxis() * (focus_point-eye);
+			}
+
+			if (transition_time >= 1.f &&
+				fabsf(current_distance-target_distance)/current_distance > 0.01f)
+			{ //large shift happened, interpolate smoothly to new target distance
+				transition_time = 0.f;
+				start_distance = current_distance;
+			}
+			else if (transition_time < 1.f)
+			{ //currently in a transition, continue interpolating
+				transition_time += 1.f/CameraFocusTransitionTime*gFrameIntervalSeconds;
+				transition_time = llmin(transition_time, 1.f);
+
+				F32 t = cosf(transition_time*F_PI+F_PI)*0.5f+0.5f;
+				current_distance = start_distance + (target_distance-start_distance)*t;
+			}
+			else
+			{ //small or no change, just snap to target distance
+				current_distance = target_distance;
+			}
+
+			//convert to mm
+			F32 subject_distance = current_distance*1000.f;
+			F32 fnumber = CameraFNumber;
+			F32 default_focal_length = CameraFocalLength;
+
+			F32 fov = LLViewerCamera::getInstance()->getView();
+		
+			const F32 default_fov = CameraFieldOfView * F_PI/180.f;
+			//const F32 default_aspect_ratio = gSavedSettings.getF32("CameraAspectRatio");
+		
+			//F32 aspect_ratio = (F32) mScreen.getWidth()/(F32)mScreen.getHeight();
+		
+			F32 dv = 2.f*default_focal_length * tanf(default_fov/2.f);
+			//F32 dh = 2.f*default_focal_length * tanf(default_fov*default_aspect_ratio/2.f);
+
+			F32 focal_length = dv/(2*tanf(fov/2.f));
+		 
+			//F32 tan_pixel_angle = tanf(LLDrawable::sCurPixelAngle);
+	
+			// from wikipedia -- c = |s2-s1|/s2 * f^2/(N(S1-f))
+			// where	 N = fnumber
+			//			 s2 = dot distance
+			//			 s1 = subject distance
+			//			 f = focal length
+			//	
+
+			F32 blur_constant = focal_length*focal_length/(fnumber*(subject_distance-focal_length));
+			blur_constant /= 1000.f; //convert to meters for shader
+			F32 magnification = focal_length/(subject_distance-focal_length);
+
+			{ //build diffuse+bloom+CoF
+				mDeferredLight.bindTarget();
+				shader = &gDeferredCoFProgram;
+
+				bindDeferredShader(*shader);
+
+				S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mScreen.getUsage());
+				if (channel > -1)
+				{
+					mScreen.bindTexture(0, channel);
+				}
+
+				shader->uniform1f(LLShaderMgr::DOF_FOCAL_DISTANCE, -subject_distance/1000.f);
+				shader->uniform1f(LLShaderMgr::DOF_BLUR_CONSTANT, blur_constant);
+				shader->uniform1f(LLShaderMgr::DOF_TAN_PIXEL_ANGLE, tanf(1.f/LLDrawable::sCurPixelAngle));
+				shader->uniform1f(LLShaderMgr::DOF_MAGNIFICATION, magnification);
+				shader->uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF);
+				shader->uniform1f(LLShaderMgr::DOF_RES_SCALE, CameraDoFResScale);
+
+				gGL.begin(LLRender::TRIANGLE_STRIP);
+				gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
+				gGL.vertex2f(-1,-1);
+		
+				gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
+				gGL.vertex2f(-1,3);
+		
+				gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
+				gGL.vertex2f(3,-1);
+		
+				gGL.end();
+
+				unbindDeferredShader(*shader);
+				mDeferredLight.flush();
+			}
+
+			{ //perform DoF sampling at half-res (preserve alpha channel)
+				mScreen.bindTarget();
+				glViewport(0,0,(GLsizei) (mScreen.getWidth()*CameraDoFResScale), (GLsizei) (mScreen.getHeight()*CameraDoFResScale));
+				gGL.setColorMask(true, false);
+
+				shader = &gDeferredPostProgram;
+				bindDeferredShader(*shader);
+				S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mDeferredLight.getUsage());
+				if (channel > -1)
+				{
+					mDeferredLight.bindTexture(0, channel);
+				}
+
+				shader->uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF);
+				shader->uniform1f(LLShaderMgr::DOF_RES_SCALE, CameraDoFResScale);
+
+				gGL.begin(LLRender::TRIANGLE_STRIP);
+				gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
+				gGL.vertex2f(-1,-1);
+		
+				gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
+				gGL.vertex2f(-1,3);
+		
+				gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
+				gGL.vertex2f(3,-1);
+		
+				gGL.end();
+
+				unbindDeferredShader(*shader);
+				mScreen.flush();
+				gGL.setColorMask(true, true);
+			}
+	
+			{ //combine result based on alpha
+				if (multisample)
+				{
+					mDeferredLight.bindTarget();
+					glViewport(0, 0, mDeferredScreen.getWidth(), mDeferredScreen.getHeight());
+				}
+				else
+				{
+					gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft;
+					gGLViewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom;
+					gGLViewport[2] = gViewerWindow->getWorldViewRectRaw().getWidth();
+					gGLViewport[3] = gViewerWindow->getWorldViewRectRaw().getHeight();
+					glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
+				}
+
+				shader = &gDeferredDoFCombineProgram;
+				bindDeferredShader(*shader);
+				
+				S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mScreen.getUsage());
+				if (channel > -1)
+				{
+					mScreen.bindTexture(0, channel);
+					gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
+				}
+
+				shader->uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF);
+				shader->uniform1f(LLShaderMgr::DOF_RES_SCALE, CameraDoFResScale);
+
+				gGL.begin(LLRender::TRIANGLE_STRIP);
+				gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
+				gGL.vertex2f(-1,-1);
+		
+				gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
+				gGL.vertex2f(-1,3);
+		
+				gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
+				gGL.vertex2f(3,-1);
+		
+				gGL.end();
+
+				unbindDeferredShader(*shader);
+
+				if (multisample)
+				{
+					mDeferredLight.flush();
+				}
+			}
+		}
+		else
+		{
+			if (multisample)
+			{
+				mDeferredLight.bindTarget();
+			}
+			LLGLSLShader* shader = &gDeferredPostNoDoFProgram;
+			
+			bindDeferredShader(*shader);
+							
+			S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mScreen.getUsage());
+			if (channel > -1)
+			{
+				mScreen.bindTexture(0, channel);
+			}
+
+			gGL.begin(LLRender::TRIANGLE_STRIP);
+			gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
+			gGL.vertex2f(-1,-1);
+		
+			gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
+			gGL.vertex2f(-1,3);
+		
+			gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
+			gGL.vertex2f(3,-1);
+		
+			gGL.end();
+
+			unbindDeferredShader(*shader);
+
+			if (multisample)
+			{
+				mDeferredLight.flush();
+			}
+		}
+
+		if (multisample)
+		{
+			//bake out texture2D with RGBL for FXAA shader
+			mFXAABuffer.bindTarget();
+			
+			S32 width = mScreen.getWidth();
+			S32 height = mScreen.getHeight();
+			glViewport(0, 0, width, height);
+
+			LLGLSLShader* shader = &gGlowCombineFXAAProgram;
+
+			shader->bind();
+			shader->uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, width, height);
+
+			S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mDeferredLight.getUsage());
+			if (channel > -1)
+			{
+				mDeferredLight.bindTexture(0, channel);
+			}
+						
+			gGL.begin(LLRender::TRIANGLE_STRIP);
+			gGL.vertex2f(-1,-1);
+			gGL.vertex2f(-1,3);
+			gGL.vertex2f(3,-1);
+			gGL.end();
+
+			gGL.flush();
+
+			shader->disableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mDeferredLight.getUsage());
+			shader->unbind();
+			
+			mFXAABuffer.flush();
+
+			shader = &gFXAAProgram;
+			shader->bind();
+
+			channel = shader->enableTexture(LLShaderMgr::DIFFUSE_MAP, mFXAABuffer.getUsage());
+			if (channel > -1)
+			{
+				mFXAABuffer.bindTexture(0, channel);
+				gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
+			}
+						
+			gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft;
+			gGLViewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom;
+			gGLViewport[2] = gViewerWindow->getWorldViewRectRaw().getWidth();
+			gGLViewport[3] = gViewerWindow->getWorldViewRectRaw().getHeight();
+			glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
+
+			F32 scale_x = (F32) width/mFXAABuffer.getWidth();
+			F32 scale_y = (F32) height/mFXAABuffer.getHeight();
+			shader->uniform2f(LLShaderMgr::FXAA_TC_SCALE, scale_x, scale_y);
+			shader->uniform2f(LLShaderMgr::FXAA_RCP_SCREEN_RES, 1.f/width*scale_x, 1.f/height*scale_y);
+			shader->uniform4f(LLShaderMgr::FXAA_RCP_FRAME_OPT, -0.5f/width*scale_x, -0.5f/height*scale_y, 0.5f/width*scale_x, 0.5f/height*scale_y);
+			shader->uniform4f(LLShaderMgr::FXAA_RCP_FRAME_OPT2, -2.f/width*scale_x, -2.f/height*scale_y, 2.f/width*scale_x, 2.f/height*scale_y);
+			
+			gGL.begin(LLRender::TRIANGLE_STRIP);
+			gGL.vertex2f(-1,-1);
+			gGL.vertex2f(-1,3);
+			gGL.vertex2f(3,-1);
+			gGL.end();
+
+			gGL.flush();
+			shader->unbind();
+		}
+	}
+	else
+	{
+		U32 mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_TEXCOORD1;
+		LLPointer<LLVertexBuffer> buff = new LLVertexBuffer(mask, 0);
+		buff->allocateBuffer(3,0,TRUE);
+
+		LLStrider<LLVector3> v;
+		LLStrider<LLVector2> uv1;
+		LLStrider<LLVector2> uv2;
+
+		buff->getVertexStrider(v);
+		buff->getTexCoord0Strider(uv1);
+		buff->getTexCoord1Strider(uv2);
+		
+		uv1[0] = LLVector2(0, 0);
+		uv1[1] = LLVector2(0, 2);
+		uv1[2] = LLVector2(2, 0);
+		
+		uv2[0] = LLVector2(0, 0);
+		uv2[1] = LLVector2(0, tc2.mV[1]*2.f);
+		uv2[2] = LLVector2(tc2.mV[0]*2.f, 0);
+		
+		v[0] = LLVector3(-1,-1,0);
+		v[1] = LLVector3(-1,3,0);
+		v[2] = LLVector3(3,-1,0);
+				
+		buff->flush();
+
+		LLGLDisable blend(GL_BLEND);
+
+		if (LLGLSLShader::sNoFixedFunction)
+		{
+			gGlowCombineProgram.bind();
+		}
+		else
+		{
+			//tex unit 0
+			gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_COLOR);
+			//tex unit 1
+			gGL.getTexUnit(1)->setTextureColorBlend(LLTexUnit::TBO_ADD, LLTexUnit::TBS_TEX_COLOR, LLTexUnit::TBS_PREV_COLOR);
+		}
+		
+		gGL.getTexUnit(0)->bind(&mGlow[1]);
+		gGL.getTexUnit(1)->bind(&mScreen);
+		
+		LLGLEnable multisample(RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0);
+		
+		buff->setBuffer(mask);
+		buff->drawArrays(LLRender::TRIANGLE_STRIP, 0, 3);
+		
+		if (LLGLSLShader::sNoFixedFunction)
+		{
+			gGlowCombineProgram.unbind();
+		}
+		else
+		{
+			gGL.getTexUnit(1)->disable();
+			gGL.getTexUnit(1)->setTextureBlendType(LLTexUnit::TB_MULT);
+
+			gGL.getTexUnit(0)->activate();
+			gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
+		}
+		
+	}
+
+	gGL.setSceneBlendType(LLRender::BT_ALPHA);
+
+	if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PHYSICS_SHAPES))
+	{
+		if (LLGLSLShader::sNoFixedFunction)
+		{
+			gSplatTextureRectProgram.bind();
+		}
+
+		gGL.setColorMask(true, false);
+
+		LLVector2 tc1(0,0);
+		LLVector2 tc2((F32) gViewerWindow->getWorldViewWidthRaw()*2,
+				  (F32) gViewerWindow->getWorldViewHeightRaw()*2);
+
+		LLGLEnable blend(GL_BLEND);
+		gGL.color4f(1,1,1,0.75f);
+
+		gGL.getTexUnit(0)->bind(&mPhysicsDisplay);
+
+		gGL.begin(LLRender::TRIANGLES);
+		gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
+		gGL.vertex2f(-1,-1);
+		
+		gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
+		gGL.vertex2f(-1,3);
+		
+		gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
+		gGL.vertex2f(3,-1);
+		
+		gGL.end();
+		gGL.flush();
+
+		if (LLGLSLShader::sNoFixedFunction)
+		{
+			gSplatTextureRectProgram.unbind();
+		}
+	}
+
+	
+	if (LLRenderTarget::sUseFBO)
+	{ //copy depth buffer from mScreen to framebuffer
+		LLRenderTarget::copyContentsToFramebuffer(mScreen, 0, 0, mScreen.getWidth(), mScreen.getHeight(), 
+			0, 0, mScreen.getWidth(), mScreen.getHeight(), GL_DEPTH_BUFFER_BIT, GL_NEAREST);
+	}
+	
+
+	gGL.matrixMode(LLRender::MM_PROJECTION);
+	gGL.popMatrix();
+	gGL.matrixMode(LLRender::MM_MODELVIEW);
+	gGL.popMatrix();
+
+	LLVertexBuffer::unbind();
+
+	LLGLState::checkStates();
+	LLGLState::checkTextureChannels();
+
+}
+
+static LLFastTimer::DeclareTimer FTM_BIND_DEFERRED("Bind Deferred");
+
+void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, U32 noise_map)
+{
+	LLFastTimer t(FTM_BIND_DEFERRED);
+
+	if (noise_map == 0xFFFFFFFF)
+	{
+		noise_map = mNoiseMap;
+	}
+
+	shader.bind();
+	S32 channel = 0;
+	channel = shader.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mDeferredScreen.getUsage());
+	if (channel > -1)
+	{
+		mDeferredScreen.bindTexture(0,channel);
+		gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
+	}
+
+	channel = shader.enableTexture(LLShaderMgr::DEFERRED_SPECULAR, mDeferredScreen.getUsage());
+	if (channel > -1)
+	{
+		mDeferredScreen.bindTexture(1, channel);
+		gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
+	}
+
+	channel = shader.enableTexture(LLShaderMgr::DEFERRED_NORMAL, mDeferredScreen.getUsage());
+	if (channel > -1)
+	{
+		mDeferredScreen.bindTexture(2, channel);
+		gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
+	}
+
+	channel = shader.enableTexture(LLShaderMgr::DEFERRED_DEPTH, mDeferredDepth.getUsage());
+	if (channel > -1)
+	{
+		gGL.getTexUnit(channel)->bind(&mDeferredDepth, TRUE);
+		stop_glerror();
+		
+		//glTexParameteri(LLTexUnit::getInternalType(mDeferredDepth.getUsage()), GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE);		
+		//glTexParameteri(LLTexUnit::getInternalType(mDeferredDepth.getUsage()), GL_DEPTH_TEXTURE_MODE_ARB, GL_ALPHA);		
+
+		stop_glerror();
+
+		glh::matrix4f projection = glh_get_current_projection();
+		glh::matrix4f inv_proj = projection.inverse();
+		
+		shader.uniformMatrix4fv(LLShaderMgr::INVERSE_PROJECTION_MATRIX, 1, FALSE, inv_proj.m);
+		shader.uniform4f(LLShaderMgr::VIEWPORT, (F32) gGLViewport[0],
+									(F32) gGLViewport[1],
+									(F32) gGLViewport[2],
+									(F32) gGLViewport[3]);
+	}
+
+	channel = shader.enableTexture(LLShaderMgr::DEFERRED_NOISE);
+	if (channel > -1)
+	{
+		gGL.getTexUnit(channel)->bindManual(LLTexUnit::TT_TEXTURE, noise_map);
+		gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
+	}
+
+	channel = shader.enableTexture(LLShaderMgr::DEFERRED_LIGHTFUNC);
+	if (channel > -1)
+	{
+		gGL.getTexUnit(channel)->bindManual(LLTexUnit::TT_TEXTURE, mLightFunc);
+	}
+
+	stop_glerror();
+
+	channel = shader.enableTexture(LLShaderMgr::DEFERRED_LIGHT, mDeferredLight.getUsage());
+	if (channel > -1)
+	{
+		if (light_index > 0)
+		{
+			mScreen.bindTexture(0, channel);
+		}
+		else
+		{
+			mDeferredLight.bindTexture(0, channel);
+		}
+		gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
+	}
+
+	channel = shader.enableTexture(LLShaderMgr::DEFERRED_BLOOM);
+	if (channel > -1)
+	{
+		mGlow[1].bindTexture(0, channel);
+	}
+
+	stop_glerror();
+
+	for (U32 i = 0; i < 4; i++)
+	{
+		channel = shader.enableTexture(LLShaderMgr::DEFERRED_SHADOW0+i, LLTexUnit::TT_RECT_TEXTURE);
+		stop_glerror();
+		if (channel > -1)
+		{
+			stop_glerror();
+			gGL.getTexUnit(channel)->bind(&mShadow[i], TRUE);
+			gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
+			gGL.getTexUnit(channel)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
+			stop_glerror();
+			
+			glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);
+			glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
+			stop_glerror();
+		}
+	}
+
+	for (U32 i = 4; i < 6; i++)
+	{
+		channel = shader.enableTexture(LLShaderMgr::DEFERRED_SHADOW0+i);
+		stop_glerror();
+		if (channel > -1)
+		{
+			stop_glerror();
+			gGL.getTexUnit(channel)->bind(&mShadow[i], TRUE);
+			gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
+			gGL.getTexUnit(channel)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
+			stop_glerror();
+			
+			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);
+			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
+			stop_glerror();
+		}
+	}
+
+	stop_glerror();
+
+	F32 mat[16*6];
+	for (U32 i = 0; i < 16; i++)
+	{
+		mat[i] = mSunShadowMatrix[0].m[i];
+		mat[i+16] = mSunShadowMatrix[1].m[i];
+		mat[i+32] = mSunShadowMatrix[2].m[i];
+		mat[i+48] = mSunShadowMatrix[3].m[i];
+		mat[i+64] = mSunShadowMatrix[4].m[i];
+		mat[i+80] = mSunShadowMatrix[5].m[i];
+	}
+
+	shader.uniformMatrix4fv(LLShaderMgr::DEFERRED_SHADOW_MATRIX, 6, FALSE, mat);
+
+	stop_glerror();
+
+	channel = shader.enableTexture(LLShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP);
+	if (channel > -1)
+	{
+		LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL;
+		if (cube_map)
+		{
+			cube_map->enable(channel);
+			cube_map->bind();
+			F32* m = gGLModelView;
+						
+			F32 mat[] = { m[0], m[1], m[2],
+						  m[4], m[5], m[6],
+						  m[8], m[9], m[10] };
+		
+			shader.uniformMatrix3fv(LLShaderMgr::DEFERRED_ENV_MAT, 1, TRUE, mat);
+		}
+	}
+
+	shader.uniform4fv(LLShaderMgr::DEFERRED_SHADOW_CLIP, 1, mSunClipPlanes.mV);
+	shader.uniform1f(LLShaderMgr::DEFERRED_SUN_WASH, RenderDeferredSunWash);
+	shader.uniform1f(LLShaderMgr::DEFERRED_SHADOW_NOISE, RenderShadowNoise);
+	shader.uniform1f(LLShaderMgr::DEFERRED_BLUR_SIZE, RenderShadowBlurSize);
+
+	shader.uniform1f(LLShaderMgr::DEFERRED_SSAO_RADIUS, RenderSSAOScale);
+	shader.uniform1f(LLShaderMgr::DEFERRED_SSAO_MAX_RADIUS, RenderSSAOMaxScale);
+
+	F32 ssao_factor = RenderSSAOFactor;
+	shader.uniform1f(LLShaderMgr::DEFERRED_SSAO_FACTOR, ssao_factor);
+	shader.uniform1f(LLShaderMgr::DEFERRED_SSAO_FACTOR_INV, 1.0/ssao_factor);
+
+	LLVector3 ssao_effect = RenderSSAOEffect;
+	F32 matrix_diag = (ssao_effect[0] + 2.0*ssao_effect[1])/3.0;
+	F32 matrix_nondiag = (ssao_effect[0] - ssao_effect[1])/3.0;
+	// This matrix scales (proj of color onto <1/rt(3),1/rt(3),1/rt(3)>) by
+	// value factor, and scales remainder by saturation factor
+	F32 ssao_effect_mat[] = {	matrix_diag, matrix_nondiag, matrix_nondiag,
+								matrix_nondiag, matrix_diag, matrix_nondiag,
+								matrix_nondiag, matrix_nondiag, matrix_diag};
+	shader.uniformMatrix3fv(LLShaderMgr::DEFERRED_SSAO_EFFECT_MAT, 1, GL_FALSE, ssao_effect_mat);
+
+	F32 shadow_offset_error = 1.f + RenderShadowOffsetError * fabsf(LLViewerCamera::getInstance()->getOrigin().mV[2]);
+	F32 shadow_bias_error = 1.f + RenderShadowBiasError * fabsf(LLViewerCamera::getInstance()->getOrigin().mV[2]);
+
+	shader.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, mDeferredScreen.getWidth(), mDeferredScreen.getHeight());
+	shader.uniform1f(LLShaderMgr::DEFERRED_NEAR_CLIP, LLViewerCamera::getInstance()->getNear()*2.f);
+	shader.uniform1f (LLShaderMgr::DEFERRED_SHADOW_OFFSET, RenderShadowOffset*shadow_offset_error);
+	shader.uniform1f(LLShaderMgr::DEFERRED_SHADOW_BIAS, RenderShadowBias*shadow_bias_error);
+	shader.uniform1f(LLShaderMgr::DEFERRED_SPOT_SHADOW_OFFSET, RenderSpotShadowOffset);
+	shader.uniform1f(LLShaderMgr::DEFERRED_SPOT_SHADOW_BIAS, RenderSpotShadowBias);	
+
+	shader.uniform3fv(LLShaderMgr::DEFERRED_SUN_DIR, 1, mTransformedSunDir.mV);
+	shader.uniform2f(LLShaderMgr::DEFERRED_SHADOW_RES, mShadow[0].getWidth(), mShadow[0].getHeight());
+	shader.uniform2f(LLShaderMgr::DEFERRED_PROJ_SHADOW_RES, mShadow[4].getWidth(), mShadow[4].getHeight());
+	shader.uniform1f(LLShaderMgr::DEFERRED_DEPTH_CUTOFF, RenderEdgeDepthCutoff);
+	shader.uniform1f(LLShaderMgr::DEFERRED_NORM_CUTOFF, RenderEdgeNormCutoff);
+	
+
+	if (shader.getUniformLocation("norm_mat") >= 0)
+	{
+		glh::matrix4f norm_mat = glh_get_current_modelview().inverse().transpose();
+		shader.uniformMatrix4fv("norm_mat", 1, FALSE, norm_mat.m);
+	}
+}
+
+static LLFastTimer::DeclareTimer FTM_GI_TRACE("Trace");
+static LLFastTimer::DeclareTimer FTM_GI_GATHER("Gather");
+static LLFastTimer::DeclareTimer FTM_SUN_SHADOW("Shadow Map");
+static LLFastTimer::DeclareTimer FTM_SOFTEN_SHADOW("Shadow Soften");
+static LLFastTimer::DeclareTimer FTM_EDGE_DETECTION("Find Edges");
+static LLFastTimer::DeclareTimer FTM_LOCAL_LIGHTS("Local Lights");
+static LLFastTimer::DeclareTimer FTM_ATMOSPHERICS("Atmospherics");
+static LLFastTimer::DeclareTimer FTM_FULLSCREEN_LIGHTS("Fullscreen Lights");
+static LLFastTimer::DeclareTimer FTM_PROJECTORS("Projectors");
+static LLFastTimer::DeclareTimer FTM_POST("Post");
+
+
+void LLPipeline::renderDeferredLighting()
+{
+	if (!sCull)
+	{
+		return;
+	}
+
+	{
+		LLFastTimer ftm(FTM_RENDER_DEFERRED);
+
+		LLViewerCamera* camera = LLViewerCamera::getInstance();
+		{
+			LLGLDepthTest depth(GL_TRUE);
+			mDeferredDepth.copyContents(mDeferredScreen, 0, 0, mDeferredScreen.getWidth(), mDeferredScreen.getHeight(),
+							0, 0, mDeferredDepth.getWidth(), mDeferredDepth.getHeight(), GL_DEPTH_BUFFER_BIT, GL_NEAREST);	
+		}
+
+		LLGLEnable multisample(RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0);
+
+		if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD))
+		{
+			gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD);
+		}
+
+		//ati doesn't seem to love actually using the stencil buffer on FBO's
+		LLGLDisable stencil(GL_STENCIL_TEST);
+		//glStencilFunc(GL_EQUAL, 1, 0xFFFFFFFF);
+		//glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
+
+		gGL.setColorMask(true, true);
+		
+		//draw a cube around every light
+		LLVertexBuffer::unbind();
+
+		LLGLEnable cull(GL_CULL_FACE);
+		LLGLEnable blend(GL_BLEND);
+
+		glh::matrix4f mat = glh_copy_matrix(gGLModelView);
+
+		LLStrider<LLVector3> vert; 
+		mDeferredVB->getVertexStrider(vert);
+		LLStrider<LLVector2> tc0;
+		LLStrider<LLVector2> tc1;
+		mDeferredVB->getTexCoord0Strider(tc0);
+		mDeferredVB->getTexCoord1Strider(tc1);
+
+		vert[0].set(-1,1,0);
+		vert[1].set(-1,-3,0);
+		vert[2].set(3,1,0);
+		
+		{
+			setupHWLights(NULL); //to set mSunDir;
+			LLVector4 dir(mSunDir, 0.f);
+			glh::vec4f tc(dir.mV);
+			mat.mult_matrix_vec(tc);
+			mTransformedSunDir.set(tc.v);
+		}
+
+		gGL.pushMatrix();
+		gGL.loadIdentity();
+		gGL.matrixMode(LLRender::MM_PROJECTION);
+		gGL.pushMatrix();
+		gGL.loadIdentity();
+
+		if (RenderDeferredSSAO || RenderShadowDetail > 0)
+		{
+			mDeferredLight.bindTarget();
+			{ //paint shadow/SSAO light map (direct lighting lightmap)
+				LLFastTimer ftm(FTM_SUN_SHADOW);
+				bindDeferredShader(gDeferredSunProgram, 0);
+				mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
+				glClearColor(1,1,1,1);
+				mDeferredLight.clear(GL_COLOR_BUFFER_BIT);
+				glClearColor(0,0,0,0);
+
+				glh::matrix4f inv_trans = glh_get_current_modelview().inverse().transpose();
+
+				const U32 slice = 32;
+				F32 offset[slice*3];
+				for (U32 i = 0; i < 4; i++)
+				{
+					for (U32 j = 0; j < 8; j++)
+					{
+						glh::vec3f v;
+						v.set_value(sinf(6.284f/8*j), cosf(6.284f/8*j), -(F32) i);
+						v.normalize();
+						inv_trans.mult_matrix_vec(v);
+						v.normalize();
+						offset[(i*8+j)*3+0] = v.v[0];
+						offset[(i*8+j)*3+1] = v.v[2];
+						offset[(i*8+j)*3+2] = v.v[1];
+					}
+				}
+
+				gDeferredSunProgram.uniform3fv("offset", slice, offset);
+				gDeferredSunProgram.uniform2f("screenRes", mDeferredLight.getWidth(), mDeferredLight.getHeight());
+				
+				{
+					LLGLDisable blend(GL_BLEND);
+					LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS);
+					stop_glerror();
+					mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
+					stop_glerror();
+				}
+				
+				unbindDeferredShader(gDeferredSunProgram);
+			}
+			mDeferredLight.flush();
+		}
+		
+		if (RenderDeferredSSAO)
+		{ //soften direct lighting lightmap
+			LLFastTimer ftm(FTM_SOFTEN_SHADOW);
+			//blur lightmap
+			mScreen.bindTarget();
+			glClearColor(1,1,1,1);
+			mScreen.clear(GL_COLOR_BUFFER_BIT);
+			glClearColor(0,0,0,0);
+			
+			bindDeferredShader(gDeferredBlurLightProgram);
+			mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
+			LLVector3 go = RenderShadowGaussian;
+			const U32 kern_length = 4;
+			F32 blur_size = RenderShadowBlurSize;
+			F32 dist_factor = RenderShadowBlurDistFactor;
+
+			// sample symmetrically with the middle sample falling exactly on 0.0
+			F32 x = 0.f;
+
+			LLVector3 gauss[32]; // xweight, yweight, offset
+
+			for (U32 i = 0; i < kern_length; i++)
+			{
+				gauss[i].mV[0] = llgaussian(x, go.mV[0]);
+				gauss[i].mV[1] = llgaussian(x, go.mV[1]);
+				gauss[i].mV[2] = x;
+				x += 1.f;
+			}
+
+			gDeferredBlurLightProgram.uniform2f("delta", 1.f, 0.f);
+			gDeferredBlurLightProgram.uniform1f("dist_factor", dist_factor);
+			gDeferredBlurLightProgram.uniform3fv("kern", kern_length, gauss[0].mV);
+			gDeferredBlurLightProgram.uniform1f("kern_scale", blur_size * (kern_length/2.f - 0.5f));
+		
+			{
+				LLGLDisable blend(GL_BLEND);
+				LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS);
+				stop_glerror();
+				mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
+				stop_glerror();
+			}
+			
+			mScreen.flush();
+			unbindDeferredShader(gDeferredBlurLightProgram);
+
+			bindDeferredShader(gDeferredBlurLightProgram, 1);
+			mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
+			mDeferredLight.bindTarget();
+
+			gDeferredBlurLightProgram.uniform2f("delta", 0.f, 1.f);
+
+			{
+				LLGLDisable blend(GL_BLEND);
+				LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS);
+				stop_glerror();
+				mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
+				stop_glerror();
+			}
+			mDeferredLight.flush();
+			unbindDeferredShader(gDeferredBlurLightProgram);
+		}
+
+		stop_glerror();
+		gGL.popMatrix();
+		stop_glerror();
+		gGL.matrixMode(LLRender::MM_MODELVIEW);
+		stop_glerror();
+		gGL.popMatrix();
+		stop_glerror();
+
+		//copy depth and stencil from deferred screen
+		//mScreen.copyContents(mDeferredScreen, 0, 0, mDeferredScreen.getWidth(), mDeferredScreen.getHeight(),
+		//					0, 0, mScreen.getWidth(), mScreen.getHeight(), GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
+
+		mScreen.bindTarget();
+		// clear color buffer here - zeroing alpha (glow) is important or it will accumulate against sky
+		glClearColor(0,0,0,0);
+		mScreen.clear(GL_COLOR_BUFFER_BIT);
+		
+		if (RenderDeferredAtmospheric)
+		{ //apply sunlight contribution 
+			LLFastTimer ftm(FTM_ATMOSPHERICS);
+			bindDeferredShader(gDeferredSoftenProgram);	
+			{
+				LLGLDepthTest depth(GL_FALSE);
+				LLGLDisable blend(GL_BLEND);
+				LLGLDisable test(GL_ALPHA_TEST);
+
+				//full screen blit
+				gGL.pushMatrix();
+				gGL.loadIdentity();
+				gGL.matrixMode(LLRender::MM_PROJECTION);
+				gGL.pushMatrix();
+				gGL.loadIdentity();
+
+				mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
+				
+				mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
+
+				gGL.popMatrix();
+				gGL.matrixMode(LLRender::MM_MODELVIEW);
+				gGL.popMatrix();
+			}
+
+			unbindDeferredShader(gDeferredSoftenProgram);
+		}
+
+		{ //render non-deferred geometry (fullbright, alpha, etc)
+			LLGLDisable blend(GL_BLEND);
+			LLGLDisable stencil(GL_STENCIL_TEST);
+			gGL.setSceneBlendType(LLRender::BT_ALPHA);
+
+			gPipeline.pushRenderTypeMask();
+			
+			gPipeline.andRenderTypeMask(LLPipeline::RENDER_TYPE_SKY,
+										LLPipeline::RENDER_TYPE_CLOUDS,
+										LLPipeline::RENDER_TYPE_WL_SKY,
+										LLPipeline::END_RENDER_TYPES);
+								
+			
+			renderGeomPostDeferred(*LLViewerCamera::getInstance());
+			gPipeline.popRenderTypeMask();
+		}
+
+		BOOL render_local = RenderLocalLights;
+				
+		if (render_local)
+		{
+			gGL.setSceneBlendType(LLRender::BT_ADD);
+			std::list<LLVector4> fullscreen_lights;
+			LLDrawable::drawable_list_t spot_lights;
+			LLDrawable::drawable_list_t fullscreen_spot_lights;
+
+			for (U32 i = 0; i < 2; i++)
+			{
+				mTargetShadowSpotLight[i] = NULL;
+			}
+
+			std::list<LLVector4> light_colors;
+
+			LLVertexBuffer::unbind();
+			LLVector4a* v = (LLVector4a*) vert.get();
+
+			{
+				bindDeferredShader(gDeferredLightProgram);
+				mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
+
+				LLGLDepthTest depth(GL_TRUE, GL_FALSE);
+				for (LLDrawable::drawable_set_t::iterator iter = mLights.begin(); iter != mLights.end(); ++iter)
+				{
+					LLDrawable* drawablep = *iter;
+					
+					LLVOVolume* volume = drawablep->getVOVolume();
+					if (!volume)
+					{
+						continue;
+					}
+
+					if (volume->isAttachment())
+					{
+						if (!sRenderAttachedLights)
+						{
+							continue;
+						}
+					}
+
+
+					LLVector4a center;
+					center.load3(drawablep->getPositionAgent().mV);
+					const F32* c = center.getF32ptr();
+					F32 s = volume->getLightRadius()*1.5f;
+
+					LLColor3 col = volume->getLightColor();
+
+					if (col.magVecSquared() < 0.001f)
+					{
+						continue;
+					}
+
+					if (s <= 0.001f)
+					{
+						continue;
+					}
+
+					LLVector4a sa;
+					sa.splat(s);
+					if (camera->AABBInFrustumNoFarClip(center, sa) == 0)
+					{
+						continue;
+					}
+
+					sVisibleLightCount++;
+
+					glh::vec3f tc(c);
+					mat.mult_matrix_vec(tc);
+					
+					//vertex positions are encoded so the 3 bits of their vertex index 
+					//correspond to their axis facing, with bit position 3,2,1 matching
+					//axis facing x,y,z, bit set meaning positive facing, bit clear 
+					//meaning negative facing
+					mDeferredVB->getVertexStrider(vert);
+					v[0].set(c[0]-s,c[1]-s,c[2]-s);  // 0 - 0000 
+					v[1].set(c[0]-s,c[1]-s,c[2]+s);  // 1 - 0001
+					v[2].set(c[0]-s,c[1]+s,c[2]-s);  // 2 - 0010
+					v[3].set(c[0]-s,c[1]+s,c[2]+s);  // 3 - 0011
+																									   
+					v[4].set(c[0]+s,c[1]-s,c[2]-s); // 4 - 0100
+					v[5].set(c[0]+s,c[1]-s,c[2]+s); // 5 - 0101
+					v[6].set(c[0]+s,c[1]+s,c[2]-s); // 6 - 0110
+					v[7].set(c[0]+s,c[1]+s,c[2]+s); // 7 - 0111
+
+					if (camera->getOrigin().mV[0] > c[0] + s + 0.2f ||
+						camera->getOrigin().mV[0] < c[0] - s - 0.2f ||
+						camera->getOrigin().mV[1] > c[1] + s + 0.2f ||
+						camera->getOrigin().mV[1] < c[1] - s - 0.2f ||
+						camera->getOrigin().mV[2] > c[2] + s + 0.2f ||
+						camera->getOrigin().mV[2] < c[2] - s - 0.2f)
+					{ //draw box if camera is outside box
+						if (render_local)
+						{
+							if (volume->isLightSpotlight())
+							{
+								drawablep->getVOVolume()->updateSpotLightPriority();
+								spot_lights.push_back(drawablep);
+								continue;
+							}
+							
+							LLFastTimer ftm(FTM_LOCAL_LIGHTS);
+							//glTexCoord4f(tc.v[0], tc.v[1], tc.v[2], s*s);
+							gDeferredLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, tc.v);
+							gDeferredLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s*s);
+							gDeferredLightProgram.uniform3fv(LLShaderMgr::DIFFUSE_COLOR, 1, col.mV);
+							gDeferredLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, volume->getLightFalloff()*0.5f);
+							//gGL.diffuseColor4f(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff()*0.5f);
+							gGL.syncMatrices();
+							mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
+							glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8,
+								GL_UNSIGNED_SHORT, get_box_fan_indices_ptr(camera, center));
+							stop_glerror();
+						}
+					}
+					else
+					{	
+						if (volume->isLightSpotlight())
+						{
+							drawablep->getVOVolume()->updateSpotLightPriority();
+							fullscreen_spot_lights.push_back(drawablep);
+							continue;
+						}
+
+						fullscreen_lights.push_back(LLVector4(tc.v[0], tc.v[1], tc.v[2], s*s));
+						light_colors.push_back(LLVector4(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff()*0.5f));
+					}
+				}
+				unbindDeferredShader(gDeferredLightProgram);
+			}
+
+			if (!spot_lights.empty())
+			{
+				LLGLDepthTest depth(GL_TRUE, GL_FALSE);
+				bindDeferredShader(gDeferredSpotLightProgram);
+
+				mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
+
+				gDeferredSpotLightProgram.enableTexture(LLShaderMgr::DEFERRED_PROJECTION);
+
+				for (LLDrawable::drawable_list_t::iterator iter = spot_lights.begin(); iter != spot_lights.end(); ++iter)
+				{
+					LLFastTimer ftm(FTM_PROJECTORS);
+					LLDrawable* drawablep = *iter;
+
+					LLVOVolume* volume = drawablep->getVOVolume();
+
+					LLVector4a center;
+					center.load3(drawablep->getPositionAgent().mV);
+					const F32* c = center.getF32ptr();
+					F32 s = volume->getLightRadius()*1.5f;
+
+					sVisibleLightCount++;
+
+					glh::vec3f tc(c);
+					mat.mult_matrix_vec(tc);
+					
+					setupSpotLight(gDeferredSpotLightProgram, drawablep);
+					
+					LLColor3 col = volume->getLightColor();
+
+					//vertex positions are encoded so the 3 bits of their vertex index 
+					//correspond to their axis facing, with bit position 3,2,1 matching
+					//axis facing x,y,z, bit set meaning positive facing, bit clear 
+					//meaning negative facing
+					mDeferredVB->getVertexStrider(vert);
+					v[0].set(c[0]-s,c[1]-s,c[2]-s);  // 0 - 0000 
+					v[1].set(c[0]-s,c[1]-s,c[2]+s);  // 1 - 0001
+					v[2].set(c[0]-s,c[1]+s,c[2]-s);  // 2 - 0010
+					v[3].set(c[0]-s,c[1]+s,c[2]+s);  // 3 - 0011
+																									   
+					v[4].set(c[0]+s,c[1]-s,c[2]-s); // 4 - 0100
+					v[5].set(c[0]+s,c[1]-s,c[2]+s); // 5 - 0101
+					v[6].set(c[0]+s,c[1]+s,c[2]-s); // 6 - 0110
+					v[7].set(c[0]+s,c[1]+s,c[2]+s); // 7 - 0111
+					
+					gDeferredSpotLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, tc.v);
+					gDeferredSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s*s);
+					gDeferredSpotLightProgram.uniform3fv(LLShaderMgr::DIFFUSE_COLOR, 1, col.mV);
+					gDeferredSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, volume->getLightFalloff()*0.5f);
+					gGL.syncMatrices();
+					mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
+					glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8,
+							GL_UNSIGNED_SHORT, get_box_fan_indices_ptr(camera, center));
+				}
+				gDeferredSpotLightProgram.disableTexture(LLShaderMgr::DEFERRED_PROJECTION);
+				unbindDeferredShader(gDeferredSpotLightProgram);
+			}
+
+			//reset mDeferredVB to fullscreen triangle
+			mDeferredVB->getVertexStrider(vert);
+			vert[0].set(-1,1,0);
+			vert[1].set(-1,-3,0);
+			vert[2].set(3,1,0);
+
+			{
+				bindDeferredShader(gDeferredMultiLightProgram);
+			
+				mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
+
+				LLGLDepthTest depth(GL_FALSE);
+
+				//full screen blit
+				gGL.pushMatrix();
+				gGL.loadIdentity();
+				gGL.matrixMode(LLRender::MM_PROJECTION);
+				gGL.pushMatrix();
+				gGL.loadIdentity();
+
+				U32 count = 0;
+
+				const U32 max_count = 8;
+				LLVector4 light[max_count];
+				LLVector4 col[max_count];
+
+//				glVertexPointer(2, GL_FLOAT, 0, vert);
+
+				F32 far_z = 0.f;
+
+				while (!fullscreen_lights.empty())
+				{
+					LLFastTimer ftm(FTM_FULLSCREEN_LIGHTS);
+					light[count] = fullscreen_lights.front();
+					fullscreen_lights.pop_front();
+					col[count] = light_colors.front();
+					light_colors.pop_front();
+
+					far_z = llmin(light[count].mV[2]-sqrtf(light[count].mV[3]), far_z);
+
+					count++;
+					if (count == max_count || fullscreen_lights.empty())
+					{
+						gDeferredMultiLightProgram.uniform1i(LLShaderMgr::MULTI_LIGHT_COUNT, count);
+						gDeferredMultiLightProgram.uniform4fv(LLShaderMgr::MULTI_LIGHT, count, (GLfloat*) light);
+						gDeferredMultiLightProgram.uniform4fv(LLShaderMgr::MULTI_LIGHT_COL, count, (GLfloat*) col);
+						gDeferredMultiLightProgram.uniform1f(LLShaderMgr::MULTI_LIGHT_FAR_Z, far_z);
+						far_z = 0.f;
+						count = 0; 
+						mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
+					}
+				}
+				
+				unbindDeferredShader(gDeferredMultiLightProgram);
+
+				bindDeferredShader(gDeferredMultiSpotLightProgram);
+
+				gDeferredMultiSpotLightProgram.enableTexture(LLShaderMgr::DEFERRED_PROJECTION);
+
+				mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
+
+				for (LLDrawable::drawable_list_t::iterator iter = fullscreen_spot_lights.begin(); iter != fullscreen_spot_lights.end(); ++iter)
+				{
+					LLFastTimer ftm(FTM_PROJECTORS);
+					LLDrawable* drawablep = *iter;
+					
+					LLVOVolume* volume = drawablep->getVOVolume();
+
+					LLVector3 center = drawablep->getPositionAgent();
+					F32* c = center.mV;
+					F32 s = volume->getLightRadius()*1.5f;
+
+					sVisibleLightCount++;
+
+					glh::vec3f tc(c);
+					mat.mult_matrix_vec(tc);
+					
+					setupSpotLight(gDeferredMultiSpotLightProgram, drawablep);
+
+					LLColor3 col = volume->getLightColor();
+
+					gDeferredMultiSpotLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, tc.v);
+					gDeferredMultiSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s*s);
+					gDeferredMultiSpotLightProgram.uniform3fv(LLShaderMgr::DIFFUSE_COLOR, 1, col.mV);
+					gDeferredMultiSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, volume->getLightFalloff()*0.5f);
+					mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
+				}
+
+				gDeferredMultiSpotLightProgram.disableTexture(LLShaderMgr::DEFERRED_PROJECTION);
+				unbindDeferredShader(gDeferredMultiSpotLightProgram);
+
+				gGL.popMatrix();
+				gGL.matrixMode(LLRender::MM_MODELVIEW);
+				gGL.popMatrix();
+			}
+		}
+
+		gGL.setColorMask(true, true);
+	}
+
+	{ //render non-deferred geometry (alpha, fullbright, glow)
+		LLGLDisable blend(GL_BLEND);
+		LLGLDisable stencil(GL_STENCIL_TEST);
+
+		pushRenderTypeMask();
+		andRenderTypeMask(LLPipeline::RENDER_TYPE_ALPHA,
+						 LLPipeline::RENDER_TYPE_FULLBRIGHT,
+						 LLPipeline::RENDER_TYPE_VOLUME,
+						 LLPipeline::RENDER_TYPE_GLOW,
+						 LLPipeline::RENDER_TYPE_BUMP,
+						 LLPipeline::RENDER_TYPE_PASS_SIMPLE,
+						 LLPipeline::RENDER_TYPE_PASS_ALPHA,
+						 LLPipeline::RENDER_TYPE_PASS_ALPHA_MASK,
+						 LLPipeline::RENDER_TYPE_PASS_BUMP,
+						 LLPipeline::RENDER_TYPE_PASS_POST_BUMP,
+						 LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT,
+						 LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK,
+						 LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_SHINY,
+						 LLPipeline::RENDER_TYPE_PASS_GLOW,
+						 LLPipeline::RENDER_TYPE_PASS_GRASS,
+						 LLPipeline::RENDER_TYPE_PASS_SHINY,
+						 LLPipeline::RENDER_TYPE_PASS_INVISIBLE,
+						 LLPipeline::RENDER_TYPE_PASS_INVISI_SHINY,
+						 LLPipeline::RENDER_TYPE_AVATAR,
+						 END_RENDER_TYPES);
+		
+		renderGeomPostDeferred(*LLViewerCamera::getInstance());
+		popRenderTypeMask();
+	}
+
+	{
+		//render highlights, etc.
+		renderHighlights();
+		mHighlightFaces.clear();
+
+		renderDebug();
+
+		LLVertexBuffer::unbind();
+
+		if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
+		{
+			// Render debugging beacons.
+			gObjectList.renderObjectBeacons();
+			gObjectList.resetObjectBeacons();
+		}
+	}
+
+	mScreen.flush();
+						
+}
+
+void LLPipeline::setupSpotLight(LLGLSLShader& shader, LLDrawable* drawablep)
+{
+	//construct frustum
+	LLVOVolume* volume = drawablep->getVOVolume();
+	LLVector3 params = volume->getSpotLightParams();
+
+	F32 fov = params.mV[0];
+	F32 focus = params.mV[1];
+
+	LLVector3 pos = drawablep->getPositionAgent();
+	LLQuaternion quat = volume->getRenderRotation();
+	LLVector3 scale = volume->getScale();
+	
+	//get near clip plane
+	LLVector3 at_axis(0,0,-scale.mV[2]*0.5f);
+	at_axis *= quat;
+
+	LLVector3 np = pos+at_axis;
+	at_axis.normVec();
+
+	//get origin that has given fov for plane np, at_axis, and given scale
+	F32 dist = (scale.mV[1]*0.5f)/tanf(fov*0.5f);
+
+	LLVector3 origin = np - at_axis*dist;
+
+	//matrix from volume space to agent space
+	LLMatrix4 light_mat(quat, LLVector4(origin,1.f));
+
+	glh::matrix4f light_to_agent((F32*) light_mat.mMatrix);
+	glh::matrix4f light_to_screen = glh_get_current_modelview() * light_to_agent;
+
+	glh::matrix4f screen_to_light = light_to_screen.inverse();
+
+	F32 s = volume->getLightRadius()*1.5f;
+	F32 near_clip = dist;
+	F32 width = scale.mV[VX];
+	F32 height = scale.mV[VY];
+	F32 far_clip = s+dist-scale.mV[VZ];
+
+	F32 fovy = fov * RAD_TO_DEG;
+	F32 aspect = width/height;
+
+	glh::matrix4f trans(0.5f, 0.f, 0.f, 0.5f,
+				0.f, 0.5f, 0.f, 0.5f,
+				0.f, 0.f, 0.5f, 0.5f,
+				0.f, 0.f, 0.f, 1.f);
+
+	glh::vec3f p1(0, 0, -(near_clip+0.01f));
+	glh::vec3f p2(0, 0, -(near_clip+1.f));
+
+	glh::vec3f screen_origin(0, 0, 0);
+
+	light_to_screen.mult_matrix_vec(p1);
+	light_to_screen.mult_matrix_vec(p2);
+	light_to_screen.mult_matrix_vec(screen_origin);
+
+	glh::vec3f n = p2-p1;
+	n.normalize();
+	
+	F32 proj_range = far_clip - near_clip;
+	glh::matrix4f light_proj = gl_perspective(fovy, aspect, near_clip, far_clip);
+	screen_to_light = trans * light_proj * screen_to_light;
+	shader.uniformMatrix4fv(LLShaderMgr::PROJECTOR_MATRIX, 1, FALSE, screen_to_light.m);
+	shader.uniform1f(LLShaderMgr::PROJECTOR_NEAR, near_clip);
+	shader.uniform3fv(LLShaderMgr::PROJECTOR_P, 1, p1.v);
+	shader.uniform3fv(LLShaderMgr::PROJECTOR_N, 1, n.v);
+	shader.uniform3fv(LLShaderMgr::PROJECTOR_ORIGIN, 1, screen_origin.v);
+	shader.uniform1f(LLShaderMgr::PROJECTOR_RANGE, proj_range);
+	shader.uniform1f(LLShaderMgr::PROJECTOR_AMBIANCE, params.mV[2]);
+	S32 s_idx = -1;
+
+	for (U32 i = 0; i < 2; i++)
+	{
+		if (mShadowSpotLight[i] == drawablep)
+		{
+			s_idx = i;
+		}
+	}
+
+	shader.uniform1i(LLShaderMgr::PROJECTOR_SHADOW_INDEX, s_idx);
+
+	if (s_idx >= 0)
+	{
+		shader.uniform1f(LLShaderMgr::PROJECTOR_SHADOW_FADE, 1.f-mSpotLightFade[s_idx]);
+	}
+	else
+	{
+		shader.uniform1f(LLShaderMgr::PROJECTOR_SHADOW_FADE, 1.f);
+	}
+
+	{
+		LLDrawable* potential = drawablep;
+		//determine if this is a good light for casting shadows
+		F32 m_pri = volume->getSpotLightPriority();
+
+		for (U32 i = 0; i < 2; i++)
+		{
+			F32 pri = 0.f;
+
+			if (mTargetShadowSpotLight[i].notNull())
+			{
+				pri = mTargetShadowSpotLight[i]->getVOVolume()->getSpotLightPriority();			
+			}
+
+			if (m_pri > pri)
+			{
+				LLDrawable* temp = mTargetShadowSpotLight[i];
+				mTargetShadowSpotLight[i] = potential;
+				potential = temp;
+				m_pri = pri;
+			}
+		}
+	}
+
+	LLViewerTexture* img = volume->getLightTexture();
+
+	if (img == NULL)
+	{
+		img = LLViewerFetchedTexture::sWhiteImagep;
+	}
+
+	S32 channel = shader.enableTexture(LLShaderMgr::DEFERRED_PROJECTION);
+
+	if (channel > -1)
+	{
+		if (img)
+		{
+			gGL.getTexUnit(channel)->bind(img);
+
+			F32 lod_range = logf(img->getWidth())/logf(2.f);
+
+			shader.uniform1f(LLShaderMgr::PROJECTOR_FOCUS, focus);
+			shader.uniform1f(LLShaderMgr::PROJECTOR_LOD, lod_range);
+			shader.uniform1f(LLShaderMgr::PROJECTOR_AMBIENT_LOD, llclamp((proj_range-focus)/proj_range*lod_range, 0.f, 1.f));
+		}
+	}
+		
+}
+
+void LLPipeline::unbindDeferredShader(LLGLSLShader &shader)
+{
+	stop_glerror();
+	shader.disableTexture(LLShaderMgr::DEFERRED_NORMAL, mDeferredScreen.getUsage());
+	shader.disableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mDeferredScreen.getUsage());
+	shader.disableTexture(LLShaderMgr::DEFERRED_SPECULAR, mDeferredScreen.getUsage());
+	shader.disableTexture(LLShaderMgr::DEFERRED_DEPTH, mDeferredScreen.getUsage());
+	shader.disableTexture(LLShaderMgr::DEFERRED_LIGHT, mDeferredLight.getUsage());
+	shader.disableTexture(LLShaderMgr::DIFFUSE_MAP);
+	shader.disableTexture(LLShaderMgr::DEFERRED_BLOOM);
+
+	for (U32 i = 0; i < 4; i++)
+	{
+		if (shader.disableTexture(LLShaderMgr::DEFERRED_SHADOW0+i, LLTexUnit::TT_RECT_TEXTURE) > -1)
+		{
+			glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE);
+		}
+	}
+
+	for (U32 i = 4; i < 6; i++)
+	{
+		if (shader.disableTexture(LLShaderMgr::DEFERRED_SHADOW0+i) > -1)
+		{
+			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE);
+		}
+	}
+
+	shader.disableTexture(LLShaderMgr::DEFERRED_NOISE);
+	shader.disableTexture(LLShaderMgr::DEFERRED_LIGHTFUNC);
+
+	S32 channel = shader.disableTexture(LLShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP);
+	if (channel > -1)
+	{
+		LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL;
+		if (cube_map)
+		{
+			cube_map->disable();
+		}
+	}
+	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+	gGL.getTexUnit(0)->activate();
+	shader.unbind();
+}
+
+inline float sgn(float a)
+{
+    if (a > 0.0F) return (1.0F);
+    if (a < 0.0F) return (-1.0F);
+    return (0.0F);
+}
+
+void LLPipeline::generateWaterReflection(LLCamera& camera_in)
+{	
+	if (LLPipeline::sWaterReflections && assertInitialized() && LLDrawPoolWater::sNeedsReflectionUpdate)
+	{
+		BOOL skip_avatar_update = FALSE;
+		if (!isAgentAvatarValid() || gAgentCamera.getCameraAnimating() || gAgentCamera.getCameraMode() != CAMERA_MODE_MOUSELOOK || !LLVOAvatar::sVisibleInFirstPerson)
+		{
+			skip_avatar_update = TRUE;
+		}
+		
+		if (!skip_avatar_update)
+		{
+			gAgentAvatarp->updateAttachmentVisibility(CAMERA_MODE_THIRD_PERSON);
+		}
+		LLVertexBuffer::unbind();
+
+		LLGLState::checkStates();
+		LLGLState::checkTextureChannels();
+		LLGLState::checkClientArrays();
+
+		LLCamera camera = camera_in;
+		camera.setFar(camera.getFar()*0.87654321f);
+		LLPipeline::sReflectionRender = TRUE;
+		
+		gPipeline.pushRenderTypeMask();
+
+		glh::matrix4f projection = glh_get_current_projection();
+		glh::matrix4f mat;
+
+		stop_glerror();
+		LLPlane plane;
+
+		F32 height = gAgent.getRegion()->getWaterHeight(); 
+		F32 to_clip = fabsf(camera.getOrigin().mV[2]-height);
+		F32 pad = -to_clip*0.05f; //amount to "pad" clip plane by
+
+		//plane params
+		LLVector3 pnorm;
+		F32 pd;
+
+		S32 water_clip = 0;
+		if (!LLViewerCamera::getInstance()->cameraUnderWater())
+		{ //camera is above water, clip plane points up
+			pnorm.setVec(0,0,1);
+			pd = -height;
+			plane.setVec(pnorm, pd);
+			water_clip = -1;
+		}
+		else
+		{	//camera is below water, clip plane points down
+			pnorm = LLVector3(0,0,-1);
+			pd = height;
+			plane.setVec(pnorm, pd);
+			water_clip = 1;
+		}
+
+		if (!LLViewerCamera::getInstance()->cameraUnderWater())
+		{	//generate planar reflection map
+
+			//disable occlusion culling for reflection map for now
+			S32 occlusion = LLPipeline::sUseOcclusion;
+			LLPipeline::sUseOcclusion = 0;
+			gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+			glClearColor(0,0,0,0);
+			mWaterRef.bindTarget();
+			LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WATER0;
+			gGL.setColorMask(true, true);
+			mWaterRef.clear();
+			gGL.setColorMask(true, false);
+
+			mWaterRef.getViewport(gGLViewport);
+
+			stop_glerror();
+
+			gGL.pushMatrix();
+
+			mat.set_scale(glh::vec3f(1,1,-1));
+			mat.set_translate(glh::vec3f(0,0,height*2.f));
+
+			glh::matrix4f current = glh_get_current_modelview();
+
+			mat = current * mat;
+
+			glh_set_current_modelview(mat);
+			gGL.loadMatrix(mat.m);
+
+			LLViewerCamera::updateFrustumPlanes(camera, FALSE, TRUE);
+
+			glh::matrix4f inv_mat = mat.inverse();
+
+			glh::vec3f origin(0,0,0);
+			inv_mat.mult_matrix_vec(origin);
+
+			camera.setOrigin(origin.v);
+
+			glCullFace(GL_FRONT);
+
+			static LLCullResult ref_result;
+
+			if (LLDrawPoolWater::sNeedsReflectionUpdate)
+			{
+				//initial sky pass (no user clip plane)
+				{ //mask out everything but the sky
+					gPipeline.pushRenderTypeMask();
+					gPipeline.andRenderTypeMask(LLPipeline::RENDER_TYPE_SKY,
+						LLPipeline::RENDER_TYPE_WL_SKY,
+						LLPipeline::RENDER_TYPE_CLOUDS,
+						LLPipeline::END_RENDER_TYPES);
+
+					static LLCullResult result;
+					updateCull(camera, result);
+					stateSort(camera, result);
+
+					renderGeom(camera, TRUE);
+
+					gPipeline.popRenderTypeMask();
+				}
+
+				gPipeline.pushRenderTypeMask();
+
+				clearRenderTypeMask(LLPipeline::RENDER_TYPE_WATER,
+					LLPipeline::RENDER_TYPE_VOIDWATER,
+					LLPipeline::RENDER_TYPE_GROUND,
+					LLPipeline::RENDER_TYPE_SKY,
+					LLPipeline::RENDER_TYPE_CLOUDS,
+					LLPipeline::END_RENDER_TYPES);	
+
+				S32 detail = RenderReflectionDetail;
+				if (detail > 0)
+				{ //mask out selected geometry based on reflection detail
+					if (detail < 4)
+					{
+						clearRenderTypeMask(LLPipeline::RENDER_TYPE_PARTICLES, END_RENDER_TYPES);
+						if (detail < 3)
+						{
+							clearRenderTypeMask(LLPipeline::RENDER_TYPE_AVATAR, END_RENDER_TYPES);
+							if (detail < 2)
+							{
+								clearRenderTypeMask(LLPipeline::RENDER_TYPE_VOLUME, END_RENDER_TYPES);
+							}
+						}
+					}
+
+					LLGLUserClipPlane clip_plane(plane, mat, projection);
+					LLGLDisable cull(GL_CULL_FACE);
+					updateCull(camera, ref_result, -water_clip, &plane);
+					stateSort(camera, ref_result);
+				}	
+
+				if (LLDrawPoolWater::sNeedsDistortionUpdate)
+				{
+					if (RenderReflectionDetail > 0)
+					{
+						gPipeline.grabReferences(ref_result);
+						LLGLUserClipPlane clip_plane(plane, mat, projection);
+						renderGeom(camera);
+					}
+				}	
+
+				gPipeline.popRenderTypeMask();
+			}	
+			glCullFace(GL_BACK);
+			gGL.popMatrix();
+			mWaterRef.flush();
+			glh_set_current_modelview(current);
+			LLPipeline::sUseOcclusion = occlusion;
+		}
+
+		camera.setOrigin(camera_in.getOrigin());
+		//render distortion map
+		static BOOL last_update = TRUE;
+		if (last_update)
+		{
+			camera.setFar(camera_in.getFar());
+			clearRenderTypeMask(LLPipeline::RENDER_TYPE_WATER,
+								LLPipeline::RENDER_TYPE_VOIDWATER,
+								LLPipeline::RENDER_TYPE_GROUND,
+								END_RENDER_TYPES);	
+			stop_glerror();
+
+			LLPipeline::sUnderWaterRender = LLViewerCamera::getInstance()->cameraUnderWater() ? FALSE : TRUE;
+
+			if (LLPipeline::sUnderWaterRender)
+			{
+				clearRenderTypeMask(LLPipeline::RENDER_TYPE_GROUND,
+									LLPipeline::RENDER_TYPE_SKY,
+									LLPipeline::RENDER_TYPE_CLOUDS,
+									LLPipeline::RENDER_TYPE_WL_SKY,
+									END_RENDER_TYPES);		
+			}
+			LLViewerCamera::updateFrustumPlanes(camera);
+
+			gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+			LLColor4& col = LLDrawPoolWater::sWaterFogColor;
+			glClearColor(col.mV[0], col.mV[1], col.mV[2], 0.f);
+			mWaterDis.bindTarget();
+			LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WATER1;
+			mWaterDis.getViewport(gGLViewport);
+			
+			if (!LLPipeline::sUnderWaterRender || LLDrawPoolWater::sNeedsReflectionUpdate)
+			{
+				//clip out geometry on the same side of water as the camera
+				mat = glh_get_current_modelview();
+				LLPlane plane(-pnorm, -(pd+pad));
+
+				LLGLUserClipPlane clip_plane(plane, mat, projection);
+				static LLCullResult result;
+				updateCull(camera, result, water_clip, &plane);
+				stateSort(camera, result);
+
+				gGL.setColorMask(true, true);
+				mWaterDis.clear();
+				gGL.setColorMask(true, false);
+
+				renderGeom(camera);
+
+			}
+
+			LLPipeline::sUnderWaterRender = FALSE;
+			mWaterDis.flush();
+		}
+		last_update = LLDrawPoolWater::sNeedsReflectionUpdate && LLDrawPoolWater::sNeedsDistortionUpdate;
+
+		LLRenderTarget::unbindTarget();
+
+		LLPipeline::sReflectionRender = FALSE;
+
+		if (!LLRenderTarget::sUseFBO)
+		{
+			glClear(GL_DEPTH_BUFFER_BIT);
+		}
+		glClearColor(0.f, 0.f, 0.f, 0.f);
+		gViewerWindow->setup3DViewport();
+		gPipeline.popRenderTypeMask();
+		LLDrawPoolWater::sNeedsReflectionUpdate = FALSE;
+		LLDrawPoolWater::sNeedsDistortionUpdate = FALSE;
+		LLPlane npnorm(-pnorm, -pd);
+		LLViewerCamera::getInstance()->setUserClipPlane(npnorm);
+		
+		LLGLState::checkStates();
+
+		if (!skip_avatar_update)
+		{
+			gAgentAvatarp->updateAttachmentVisibility(gAgentCamera.getCameraMode());
+		}
+
+		LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
+	}
+}
+
+glh::matrix4f look(const LLVector3 pos, const LLVector3 dir, const LLVector3 up)
+{
+	glh::matrix4f ret;
+
+	LLVector3 dirN;
+	LLVector3 upN;
+	LLVector3 lftN;
+
+	lftN = dir % up;
+	lftN.normVec();
+	
+	upN = lftN % dir;
+	upN.normVec();
+	
+	dirN = dir;
+	dirN.normVec();
+
+	ret.m[ 0] = lftN[0];
+	ret.m[ 1] = upN[0];
+	ret.m[ 2] = -dirN[0];
+	ret.m[ 3] = 0.f;
+
+	ret.m[ 4] = lftN[1];
+	ret.m[ 5] = upN[1];
+	ret.m[ 6] = -dirN[1];
+	ret.m[ 7] = 0.f;
+
+	ret.m[ 8] = lftN[2];
+	ret.m[ 9] = upN[2];
+	ret.m[10] = -dirN[2];
+	ret.m[11] = 0.f;
+
+	ret.m[12] = -(lftN*pos);
+	ret.m[13] = -(upN*pos);
+	ret.m[14] = dirN*pos;
+	ret.m[15] = 1.f;
+
+	return ret;
+}
+
+glh::matrix4f scale_translate_to_fit(const LLVector3 min, const LLVector3 max)
+{
+	glh::matrix4f ret;
+	ret.m[ 0] = 2/(max[0]-min[0]);
+	ret.m[ 4] = 0;
+	ret.m[ 8] = 0;
+	ret.m[12] = -(max[0]+min[0])/(max[0]-min[0]);
+
+	ret.m[ 1] = 0;
+	ret.m[ 5] = 2/(max[1]-min[1]);
+	ret.m[ 9] = 0;
+	ret.m[13] = -(max[1]+min[1])/(max[1]-min[1]);
+
+	ret.m[ 2] = 0;
+	ret.m[ 6] = 0;
+	ret.m[10] = 2/(max[2]-min[2]);
+	ret.m[14] = -(max[2]+min[2])/(max[2]-min[2]);
+
+	ret.m[ 3] = 0;
+	ret.m[ 7] = 0;
+	ret.m[11] = 0;
+	ret.m[15] = 1;
+
+	return ret;
+}
+
+static LLFastTimer::DeclareTimer FTM_SHADOW_RENDER("Render Shadows");
+static LLFastTimer::DeclareTimer FTM_SHADOW_ALPHA("Alpha Shadow");
+static LLFastTimer::DeclareTimer FTM_SHADOW_SIMPLE("Simple Shadow");
+
+void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera& shadow_cam, LLCullResult &result, BOOL use_shader, BOOL use_occlusion)
+{
+	LLFastTimer t(FTM_SHADOW_RENDER);
+
+	//clip out geometry on the same side of water as the camera
+	S32 occlude = LLPipeline::sUseOcclusion;
+	if (!use_occlusion)
+	{
+		LLPipeline::sUseOcclusion = 0;
+	}
+	LLPipeline::sShadowRender = TRUE;
+	
+	U32 types[] = { 
+		LLRenderPass::PASS_SIMPLE, 
+		LLRenderPass::PASS_FULLBRIGHT, 
+		LLRenderPass::PASS_SHINY, 
+		LLRenderPass::PASS_BUMP, 
+		LLRenderPass::PASS_FULLBRIGHT_SHINY 
+	};
+
+	LLGLEnable cull(GL_CULL_FACE);
+
+	if (use_shader)
+	{
+		gDeferredShadowProgram.bind();
+	}
+
+	updateCull(shadow_cam, result);
+	stateSort(shadow_cam, result);
+	
+	//generate shadow map
+	gGL.matrixMode(LLRender::MM_PROJECTION);
+	gGL.pushMatrix();
+	gGL.loadMatrix(proj.m);
+	gGL.matrixMode(LLRender::MM_MODELVIEW);
+	gGL.pushMatrix();
+	gGL.loadMatrix(gGLModelView);
+
+	stop_glerror();
+	gGLLastMatrix = NULL;
+
+	{
+		//LLGLDepthTest depth(GL_TRUE);
+		//glClear(GL_DEPTH_BUFFER_BIT);
+	}
+
+	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+	
+	stop_glerror();
+	
+	//glCullFace(GL_FRONT);
+
+	LLVertexBuffer::unbind();
+
+	{
+		if (!use_shader)
+		{ //occlusion program is general purpose depth-only no-textures
+			gOcclusionProgram.bind();
+		}
+
+		gGL.diffuseColor4f(1,1,1,1);
+		gGL.setColorMask(false, false);
+	
+		LLFastTimer ftm(FTM_SHADOW_SIMPLE);
+		gGL.getTexUnit(0)->disable();
+		for (U32 i = 0; i < sizeof(types)/sizeof(U32); ++i)
+		{
+			renderObjects(types[i], LLVertexBuffer::MAP_VERTEX, FALSE);
+		}
+		gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
+		if (!use_shader)
+		{
+			gOcclusionProgram.unbind();
+		}
+	}
+	
+	if (use_shader)
+	{
+		gDeferredShadowProgram.unbind();
+		renderGeomShadow(shadow_cam);
+		gDeferredShadowProgram.bind();
+	}
+	else
+	{
+		renderGeomShadow(shadow_cam);
+	}
+
+	{
+		LLFastTimer ftm(FTM_SHADOW_ALPHA);
+		gDeferredShadowAlphaMaskProgram.bind();
+		gDeferredShadowAlphaMaskProgram.setMinimumAlpha(0.598f);
+		
+		U32 mask =	LLVertexBuffer::MAP_VERTEX | 
+					LLVertexBuffer::MAP_TEXCOORD0 | 
+					LLVertexBuffer::MAP_COLOR | 
+					LLVertexBuffer::MAP_TEXTURE_INDEX;
+
+		renderObjects(LLRenderPass::PASS_ALPHA_MASK, mask, TRUE, TRUE);
+		renderObjects(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, mask, TRUE, TRUE);
+		renderObjects(LLRenderPass::PASS_ALPHA, mask, TRUE, TRUE);
+		gDeferredTreeShadowProgram.bind();
+		gDeferredTreeShadowProgram.setMinimumAlpha(0.598f);
+		renderObjects(LLRenderPass::PASS_GRASS, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, TRUE);
+	}
+
+	//glCullFace(GL_BACK);
+
+	gDeferredShadowProgram.bind();
+	gGLLastMatrix = NULL;
+	gGL.loadMatrix(gGLModelView);
+	doOcclusion(shadow_cam);
+
+	if (use_shader)
+	{
+		gDeferredShadowProgram.unbind();
+	}
+	
+	gGL.setColorMask(true, true);
+			
+	gGL.matrixMode(LLRender::MM_PROJECTION);
+	gGL.popMatrix();
+	gGL.matrixMode(LLRender::MM_MODELVIEW);
+	gGL.popMatrix();
+	gGLLastMatrix = NULL;
+
+	LLPipeline::sUseOcclusion = occlude;
+	LLPipeline::sShadowRender = FALSE;
+}
+
+static LLFastTimer::DeclareTimer FTM_VISIBLE_CLOUD("Visible Cloud");
+BOOL LLPipeline::getVisiblePointCloud(LLCamera& camera, LLVector3& min, LLVector3& max, std::vector<LLVector3>& fp, LLVector3 light_dir)
+{
+	LLFastTimer t(FTM_VISIBLE_CLOUD);
+	//get point cloud of intersection of frust and min, max
+
+	if (getVisibleExtents(camera, min, max))
+	{
+		return FALSE;
+	}
+
+	//get set of planes on bounding box
+	LLPlane bp[] = { 
+		LLPlane(min, LLVector3(-1,0,0)),
+		LLPlane(min, LLVector3(0,-1,0)),
+		LLPlane(min, LLVector3(0,0,-1)),
+		LLPlane(max, LLVector3(1,0,0)),
+		LLPlane(max, LLVector3(0,1,0)),
+		LLPlane(max, LLVector3(0,0,1))};
+	
+	//potential points
+	std::vector<LLVector3> pp;
+
+	//add corners of AABB
+	pp.push_back(LLVector3(min.mV[0], min.mV[1], min.mV[2]));
+	pp.push_back(LLVector3(max.mV[0], min.mV[1], min.mV[2]));
+	pp.push_back(LLVector3(min.mV[0], max.mV[1], min.mV[2]));
+	pp.push_back(LLVector3(max.mV[0], max.mV[1], min.mV[2]));
+	pp.push_back(LLVector3(min.mV[0], min.mV[1], max.mV[2]));
+	pp.push_back(LLVector3(max.mV[0], min.mV[1], max.mV[2]));
+	pp.push_back(LLVector3(min.mV[0], max.mV[1], max.mV[2]));
+	pp.push_back(LLVector3(max.mV[0], max.mV[1], max.mV[2]));
+
+	//add corners of camera frustum
+	for (U32 i = 0; i < 8; i++)
+	{
+		pp.push_back(camera.mAgentFrustum[i]);
+	}
+
+
+	//bounding box line segments
+	U32 bs[] = 
+			{
+		0,1,
+		1,3,
+		3,2,
+		2,0,
+
+		4,5,
+		5,7,
+		7,6,
+		6,4,
+
+		0,4,
+		1,5,
+		3,7,
+		2,6
+	};
+
+	for (U32 i = 0; i < 12; i++)
+	{ //for each line segment in bounding box
+		for (U32 j = 0; j < 6; j++) 
+		{ //for each plane in camera frustum
+			const LLPlane& cp = camera.getAgentPlane(j);
+			const LLVector3& v1 = pp[bs[i*2+0]];
+			const LLVector3& v2 = pp[bs[i*2+1]];
+			LLVector3 n;
+			cp.getVector3(n);
+
+			LLVector3 line = v1-v2;
+
+			F32 d1 = line*n;
+			F32 d2 = -cp.dist(v2);
+
+			F32 t = d2/d1;
+
+			if (t > 0.f && t < 1.f)
+			{
+				LLVector3 intersect = v2+line*t;
+				pp.push_back(intersect);
+			}
+		}
+	}
+			
+	//camera frustum line segments
+	const U32 fs[] =
+	{
+		0,1,
+		1,2,
+		2,3,
+		3,0,
+
+		4,5,
+		5,6,
+		6,7,
+		7,4,
+	
+		0,4,
+		1,5,
+		2,6,
+		3,7	
+	};
+
+	LLVector3 center = (max+min)*0.5f;
+	LLVector3 size = (max-min)*0.5f;
+	
+	for (U32 i = 0; i < 12; i++)
+	{
+		for (U32 j = 0; j < 6; ++j)
+		{
+			const LLVector3& v1 = pp[fs[i*2+0]+8];
+			const LLVector3& v2 = pp[fs[i*2+1]+8];
+			const LLPlane& cp = bp[j];
+			LLVector3 n;
+			cp.getVector3(n);
+
+			LLVector3 line = v1-v2;
+
+			F32 d1 = line*n;
+			F32 d2 = -cp.dist(v2);
+
+			F32 t = d2/d1;
+
+			if (t > 0.f && t < 1.f)
+			{
+				LLVector3 intersect = v2+line*t;
+				pp.push_back(intersect);
+			}	
+		}
+	}
+
+	LLVector3 ext[] = { min-LLVector3(0.05f,0.05f,0.05f),
+		max+LLVector3(0.05f,0.05f,0.05f) };
+
+	for (U32 i = 0; i < pp.size(); ++i)
+	{
+		bool found = true;
+
+		const F32* p = pp[i].mV;
+			
+		for (U32 j = 0; j < 3; ++j)
+		{
+			if (p[j] < ext[0].mV[j] ||
+				p[j] > ext[1].mV[j])
+			{
+				found = false;
+				break;
+			}
+		}
+				
+		for (U32 j = 0; j < 6; ++j)
+		{
+			const LLPlane& cp = camera.getAgentPlane(j);
+			F32 dist = cp.dist(pp[i]);
+			if (dist > 0.05f) //point is above some plane, not contained
+					{
+				found = false;
+				break;
+						}
+					}
+
+					if (found)
+					{
+			fp.push_back(pp[i]);
+		}
+	}
+	
+	if (fp.empty())
+	{
+		return FALSE;
+	}
+	
+	return TRUE;
+}
+
+void LLPipeline::renderHighlight(const LLViewerObject* obj, F32 fade)
+{
+	if (obj && obj->getVolume())
+	{
+		for (LLViewerObject::child_list_t::const_iterator iter = obj->getChildren().begin(); iter != obj->getChildren().end(); ++iter)
+		{
+			renderHighlight(*iter, fade);
+		}
+
+		LLDrawable* drawable = obj->mDrawable;
+		if (drawable)
+		{
+			for (S32 i = 0; i < drawable->getNumFaces(); ++i)
+			{
+				LLFace* face = drawable->getFace(i);
+				if (face)
+				{
+					face->renderSelected(LLViewerTexture::sNullImagep, LLColor4(1,1,1,fade));
+				}
+			}
+		}
+	}
+}
+
+void LLPipeline::generateHighlight(LLCamera& camera)
+{
+	//render highlighted object as white into offscreen render target
+	if (mHighlightObject.notNull())
+	{
+		mHighlightSet.insert(HighlightItem(mHighlightObject));
+	}
+	
+	if (!mHighlightSet.empty())
+	{
+		F32 transition = gFrameIntervalSeconds/RenderHighlightFadeTime;
+
+		LLGLDisable test(GL_ALPHA_TEST);
+		LLGLDepthTest depth(GL_FALSE);
+		mHighlight.bindTarget();
+		disableLights();
+		gGL.setColorMask(true, true);
+		mHighlight.clear();
+
+		gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sWhiteImagep);
+		for (std::set<HighlightItem>::iterator iter = mHighlightSet.begin(); iter != mHighlightSet.end(); )
+		{
+			std::set<HighlightItem>::iterator cur_iter = iter++;
+
+			if (cur_iter->mItem.isNull())
+			{
+				mHighlightSet.erase(cur_iter);
+				continue;
+			}
+
+			if (cur_iter->mItem == mHighlightObject)
+			{
+				cur_iter->incrFade(transition); 
+			}
+			else
+			{
+				cur_iter->incrFade(-transition);
+				if (cur_iter->mFade <= 0.f)
+				{
+					mHighlightSet.erase(cur_iter);
+					continue;
+				}
+			}
+
+			renderHighlight(cur_iter->mItem->getVObj(), cur_iter->mFade);
+		}
+
+		mHighlight.flush();
+		gGL.setColorMask(true, false);
+		gViewerWindow->setup3DViewport();
+	}
+}
+
+
+void LLPipeline::generateSunShadow(LLCamera& camera)
+{
+	if (!sRenderDeferred || RenderShadowDetail <= 0)
+	{
+		return;
+	}
+
+	BOOL skip_avatar_update = FALSE;
+	if (!isAgentAvatarValid() || gAgentCamera.getCameraAnimating() || gAgentCamera.getCameraMode() != CAMERA_MODE_MOUSELOOK || !LLVOAvatar::sVisibleInFirstPerson)
+	{
+
+		skip_avatar_update = TRUE;
+	}
+
+	if (!skip_avatar_update)
+	{
+		gAgentAvatarp->updateAttachmentVisibility(CAMERA_MODE_THIRD_PERSON);
+	}
+
+	F64 last_modelview[16];
+	F64 last_projection[16];
+	for (U32 i = 0; i < 16; i++)
+	{ //store last_modelview of world camera
+		last_modelview[i] = gGLLastModelView[i];
+		last_projection[i] = gGLLastProjection[i];
+	}
+
+	pushRenderTypeMask();
+	andRenderTypeMask(LLPipeline::RENDER_TYPE_SIMPLE,
+					LLPipeline::RENDER_TYPE_ALPHA,
+					LLPipeline::RENDER_TYPE_GRASS,
+					LLPipeline::RENDER_TYPE_FULLBRIGHT,
+					LLPipeline::RENDER_TYPE_BUMP,
+					LLPipeline::RENDER_TYPE_VOLUME,
+					LLPipeline::RENDER_TYPE_AVATAR,
+					LLPipeline::RENDER_TYPE_TREE, 
+					LLPipeline::RENDER_TYPE_TERRAIN,
+					LLPipeline::RENDER_TYPE_WATER,
+					LLPipeline::RENDER_TYPE_VOIDWATER,
+					LLPipeline::RENDER_TYPE_PASS_ALPHA,
+					LLPipeline::RENDER_TYPE_PASS_ALPHA_MASK,
+					LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK,
+					LLPipeline::RENDER_TYPE_PASS_GRASS,
+					LLPipeline::RENDER_TYPE_PASS_SIMPLE,
+					LLPipeline::RENDER_TYPE_PASS_BUMP,
+					LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT,
+					LLPipeline::RENDER_TYPE_PASS_SHINY,
+					LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_SHINY,
+					END_RENDER_TYPES);
+
+	gGL.setColorMask(false, false);
+
+	//get sun view matrix
+	
+	//store current projection/modelview matrix
+	glh::matrix4f saved_proj = glh_get_current_projection();
+	glh::matrix4f saved_view = glh_get_current_modelview();
+	glh::matrix4f inv_view = saved_view.inverse();
+
+	glh::matrix4f view[6];
+	glh::matrix4f proj[6];
+	
+	//clip contains parallel split distances for 3 splits
+	LLVector3 clip = RenderShadowClipPlanes;
+
+	//F32 slope_threshold = gSavedSettings.getF32("RenderShadowSlopeThreshold");
+
+	//far clip on last split is minimum of camera view distance and 128
+	mSunClipPlanes = LLVector4(clip, clip.mV[2] * clip.mV[2]/clip.mV[1]);
+
+	clip = RenderShadowOrthoClipPlanes;
+	mSunOrthoClipPlanes = LLVector4(clip, clip.mV[2]*clip.mV[2]/clip.mV[1]);
+
+	//currently used for amount to extrude frusta corners for constructing shadow frusta
+	LLVector3 n = RenderShadowNearDist;
+	//F32 nearDist[] = { n.mV[0], n.mV[1], n.mV[2], n.mV[2] };
+
+	//put together a universal "near clip" plane for shadow frusta
+	LLPlane shadow_near_clip;
+	{
+		LLVector3 p = gAgent.getPositionAgent();
+		p += mSunDir * RenderFarClip*2.f;
+		shadow_near_clip.setVec(p, mSunDir);
+	}
+
+	LLVector3 lightDir = -mSunDir;
+	lightDir.normVec();
+
+	glh::vec3f light_dir(lightDir.mV);
+
+	//create light space camera matrix
+	
+	LLVector3 at = lightDir;
+
+	LLVector3 up = camera.getAtAxis();
+
+	if (fabsf(up*lightDir) > 0.75f)
+	{
+		up = camera.getUpAxis();
+	}
+
+	/*LLVector3 left = up%at;
+	up = at%left;*/
+
+	up.normVec();
+	at.normVec();
+	
+	
+	LLCamera main_camera = camera;
+	
+	F32 near_clip = 0.f;
+	{
+		//get visible point cloud
+		std::vector<LLVector3> fp;
+
+		main_camera.calcAgentFrustumPlanes(main_camera.mAgentFrustum);
+		
+		LLVector3 min,max;
+		getVisiblePointCloud(main_camera,min,max,fp);
+
+		if (fp.empty())
+		{
+			if (!hasRenderDebugMask(RENDER_DEBUG_SHADOW_FRUSTA))
+			{
+				mShadowCamera[0] = main_camera;
+				mShadowExtents[0][0] = min;
+				mShadowExtents[0][1] = max;
+
+				mShadowFrustPoints[0].clear();
+				mShadowFrustPoints[1].clear();
+				mShadowFrustPoints[2].clear();
+				mShadowFrustPoints[3].clear();
+			}
+			popRenderTypeMask();
+
+			if (!skip_avatar_update)
+			{
+				gAgentAvatarp->updateAttachmentVisibility(gAgentCamera.getCameraMode());
+			}
+
+			return;
+		}
+
+		//get good split distances for frustum
+		for (U32 i = 0; i < fp.size(); ++i)
+		{
+			glh::vec3f v(fp[i].mV);
+			saved_view.mult_matrix_vec(v);
+			fp[i].setVec(v.v);
+		}
+
+		min = fp[0];
+		max = fp[0];
+
+		//get camera space bounding box
+		for (U32 i = 1; i < fp.size(); ++i)
+		{
+			update_min_max(min, max, fp[i]);
+		}
+
+		near_clip = -max.mV[2];
+		F32 far_clip = -min.mV[2]*2.f;
+
+		//far_clip = llmin(far_clip, 128.f);
+		far_clip = llmin(far_clip, camera.getFar());
+
+		F32 range = far_clip-near_clip;
+
+		LLVector3 split_exp = RenderShadowSplitExponent;
+
+		F32 da = 1.f-llmax( fabsf(lightDir*up), fabsf(lightDir*camera.getLeftAxis()) );
+		
+		da = powf(da, split_exp.mV[2]);
+
+
+		F32 sxp = split_exp.mV[1] + (split_exp.mV[0]-split_exp.mV[1])*da;
+
+
+		for (U32 i = 0; i < 4; ++i)
+		{
+			F32 x = (F32)(i+1)/4.f;
+			x = powf(x, sxp);
+			mSunClipPlanes.mV[i] = near_clip+range*x;
+		}
+	}
+
+	// convenience array of 4 near clip plane distances
+	F32 dist[] = { near_clip, mSunClipPlanes.mV[0], mSunClipPlanes.mV[1], mSunClipPlanes.mV[2], mSunClipPlanes.mV[3] };
+	
+
+	if (mSunDiffuse == LLColor4::black)
+	{ //sun diffuse is totally black, shadows don't matter
+		LLGLDepthTest depth(GL_TRUE);
+
+		for (S32 j = 0; j < 4; j++)
+		{
+			mShadow[j].bindTarget();
+			mShadow[j].clear();
+			mShadow[j].flush();
+		}
+	}
+	else
+	{
+		for (S32 j = 0; j < 4; j++)
+		{
+			if (!hasRenderDebugMask(RENDER_DEBUG_SHADOW_FRUSTA))
+			{
+				mShadowFrustPoints[j].clear();
+			}
+
+			LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_SHADOW0+j;
+
+			//restore render matrices
+			glh_set_current_modelview(saved_view);
+			glh_set_current_projection(saved_proj);
+
+			LLVector3 eye = camera.getOrigin();
+
+			//camera used for shadow cull/render
+			LLCamera shadow_cam;
+		
+			//create world space camera frustum for this split
+			shadow_cam = camera;
+			shadow_cam.setFar(16.f);
+	
+			LLViewerCamera::updateFrustumPlanes(shadow_cam, FALSE, FALSE, TRUE);
+
+			LLVector3* frust = shadow_cam.mAgentFrustum;
+
+			LLVector3 pn = shadow_cam.getAtAxis();
+		
+			LLVector3 min, max;
+
+			//construct 8 corners of split frustum section
+			for (U32 i = 0; i < 4; i++)
+			{
+				LLVector3 delta = frust[i+4]-eye;
+				delta += (frust[i+4]-frust[(i+2)%4+4])*0.05f;
+				delta.normVec();
+				F32 dp = delta*pn;
+				frust[i] = eye + (delta*dist[j]*0.95f)/dp;
+				frust[i+4] = eye + (delta*dist[j+1]*1.05f)/dp;
+			}
+						
+			shadow_cam.calcAgentFrustumPlanes(frust);
+			shadow_cam.mFrustumCornerDist = 0.f;
+		
+			if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
+			{
+				mShadowCamera[j] = shadow_cam;
+			}
+
+			std::vector<LLVector3> fp;
+
+			if (!gPipeline.getVisiblePointCloud(shadow_cam, min, max, fp, lightDir))
+			{
+				//no possible shadow receivers
+				if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
+				{
+					mShadowExtents[j][0] = LLVector3();
+					mShadowExtents[j][1] = LLVector3();
+					mShadowCamera[j+4] = shadow_cam;
+				}
+
+				mShadow[j].bindTarget();
+				{
+					LLGLDepthTest depth(GL_TRUE);
+					mShadow[j].clear();
+				}
+				mShadow[j].flush();
+
+				mShadowError.mV[j] = 0.f;
+				mShadowFOV.mV[j] = 0.f;
+
+				continue;
+			}
+
+			if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
+			{
+				mShadowExtents[j][0] = min;
+				mShadowExtents[j][1] = max;
+				mShadowFrustPoints[j] = fp;
+			}
+				
+
+			//find a good origin for shadow projection
+			LLVector3 origin;
+
+			//get a temporary view projection
+			view[j] = look(camera.getOrigin(), lightDir, -up);
+
+			std::vector<LLVector3> wpf;
+
+			for (U32 i = 0; i < fp.size(); i++)
+			{
+				glh::vec3f p = glh::vec3f(fp[i].mV);
+				view[j].mult_matrix_vec(p);
+				wpf.push_back(LLVector3(p.v));
+			}
+
+			min = wpf[0];
+			max = wpf[0];
+
+			for (U32 i = 0; i < fp.size(); ++i)
+			{ //get AABB in camera space
+				update_min_max(min, max, wpf[i]);
+			}
+
+			// Construct a perspective transform with perspective along y-axis that contains
+			// points in wpf
+			//Known:
+			// - far clip plane
+			// - near clip plane
+			// - points in frustum
+			//Find:
+			// - origin
+
+			//get some "interesting" points of reference
+			LLVector3 center = (min+max)*0.5f;
+			LLVector3 size = (max-min)*0.5f;
+			LLVector3 near_center = center;
+			near_center.mV[1] += size.mV[1]*2.f;
+		
+		
+			//put all points in wpf in quadrant 0, reletive to center of min/max
+			//get the best fit line using least squares
+			F32 bfm = 0.f;
+			F32 bfb = 0.f;
+
+			for (U32 i = 0; i < wpf.size(); ++i)
+			{
+				wpf[i] -= center;
+				wpf[i].mV[0] = fabsf(wpf[i].mV[0]);
+				wpf[i].mV[2] = fabsf(wpf[i].mV[2]);
+			}
+
+			if (!wpf.empty())
+			{ 
+				F32 sx = 0.f;
+				F32 sx2 = 0.f;
+				F32 sy = 0.f;
+				F32 sxy = 0.f;
+			
+				for (U32 i = 0; i < wpf.size(); ++i)
+				{		
+					sx += wpf[i].mV[0];
+					sx2 += wpf[i].mV[0]*wpf[i].mV[0];
+					sy += wpf[i].mV[1];
+					sxy += wpf[i].mV[0]*wpf[i].mV[1]; 
+				}
+
+				bfm = (sy*sx-wpf.size()*sxy)/(sx*sx-wpf.size()*sx2);
+				bfb = (sx*sxy-sy*sx2)/(sx*sx-bfm*sx2);
+			}
+		
+			{
+				// best fit line is y=bfm*x+bfb
+		
+				//find point that is furthest to the right of line
+				F32 off_x = -1.f;
+				LLVector3 lp;
+
+				for (U32 i = 0; i < wpf.size(); ++i)
+				{
+					//y = bfm*x+bfb
+					//x = (y-bfb)/bfm
+					F32 lx = (wpf[i].mV[1]-bfb)/bfm;
+
+					lx = wpf[i].mV[0]-lx;
+				
+					if (off_x < lx)
+					{
+						off_x = lx;
+						lp = wpf[i];
+					}
+				}
+
+				//get line with slope bfm through lp
+				// bfb = y-bfm*x
+				bfb = lp.mV[1]-bfm*lp.mV[0];
+
+				//calculate error
+				mShadowError.mV[j] = 0.f;
+
+				for (U32 i = 0; i < wpf.size(); ++i)
+				{
+					F32 lx = (wpf[i].mV[1]-bfb)/bfm;
+					mShadowError.mV[j] += fabsf(wpf[i].mV[0]-lx);
+				}
+
+				mShadowError.mV[j] /= wpf.size();
+				mShadowError.mV[j] /= size.mV[0];
+
+				if (mShadowError.mV[j] > RenderShadowErrorCutoff)
+				{ //just use ortho projection
+					mShadowFOV.mV[j] = -1.f;
+					origin.clearVec();
+					proj[j] = gl_ortho(min.mV[0], max.mV[0],
+										min.mV[1], max.mV[1],
+										-max.mV[2], -min.mV[2]);
+				}
+				else
+				{
+					//origin is where line x = 0;
+					origin.setVec(0,bfb,0);
+
+					F32 fovz = 1.f;
+					F32 fovx = 1.f;
+				
+					LLVector3 zp;
+					LLVector3 xp;
+
+					for (U32 i = 0; i < wpf.size(); ++i)
+					{
+						LLVector3 atz = wpf[i]-origin;
+						atz.mV[0] = 0.f;
+						atz.normVec();
+						if (fovz > -atz.mV[1])
+						{
+							zp = wpf[i];
+							fovz = -atz.mV[1];
+						}
+					
+						LLVector3 atx = wpf[i]-origin;
+						atx.mV[2] = 0.f;
+						atx.normVec();
+						if (fovx > -atx.mV[1])
+						{
+							fovx = -atx.mV[1];
+							xp = wpf[i];
+						}
+					}
+
+					fovx = acos(fovx);
+					fovz = acos(fovz);
+
+					F32 cutoff = llmin((F32) RenderShadowFOVCutoff, 1.4f);
+				
+					mShadowFOV.mV[j] = fovx;
+				
+					if (fovx < cutoff && fovz > cutoff)
+					{
+						//x is a good fit, but z is too big, move away from zp enough so that fovz matches cutoff
+						F32 d = zp.mV[2]/tan(cutoff);
+						F32 ny = zp.mV[1] + fabsf(d);
+
+						origin.mV[1] = ny;
+
+						fovz = 1.f;
+						fovx = 1.f;
+
+						for (U32 i = 0; i < wpf.size(); ++i)
+						{
+							LLVector3 atz = wpf[i]-origin;
+							atz.mV[0] = 0.f;
+							atz.normVec();
+							fovz = llmin(fovz, -atz.mV[1]);
+
+							LLVector3 atx = wpf[i]-origin;
+							atx.mV[2] = 0.f;
+							atx.normVec();
+							fovx = llmin(fovx, -atx.mV[1]);
+						}
+
+						fovx = acos(fovx);
+						fovz = acos(fovz);
+
+						mShadowFOV.mV[j] = cutoff;
+					}
+
+				
+					origin += center;
+			
+					F32 ynear = -(max.mV[1]-origin.mV[1]);
+					F32 yfar = -(min.mV[1]-origin.mV[1]);
+				
+					if (ynear < 0.1f) //keep a sensible near clip plane
+					{
+						F32 diff = 0.1f-ynear;
+						origin.mV[1] += diff;
+						ynear += diff;
+						yfar += diff;
+					}
+								
+					if (fovx > cutoff)
+					{ //just use ortho projection
+						origin.clearVec();
+						mShadowError.mV[j] = -1.f;
+						proj[j] = gl_ortho(min.mV[0], max.mV[0],
+								min.mV[1], max.mV[1],
+								-max.mV[2], -min.mV[2]);
+					}
+					else
+					{
+						//get perspective projection
+						view[j] = view[j].inverse();
+
+						glh::vec3f origin_agent(origin.mV);
+					
+						//translate view to origin
+						view[j].mult_matrix_vec(origin_agent);
+
+						eye = LLVector3(origin_agent.v);
+
+						if (!hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
+						{
+							mShadowFrustOrigin[j] = eye;
+						}
+				
+						view[j] = look(LLVector3(origin_agent.v), lightDir, -up);
+
+						F32 fx = 1.f/tanf(fovx);
+						F32 fz = 1.f/tanf(fovz);
+
+						proj[j] = glh::matrix4f(-fx, 0, 0, 0,
+												0, (yfar+ynear)/(ynear-yfar), 0, (2.f*yfar*ynear)/(ynear-yfar),
+												0, 0, -fz, 0,
+												0, -1.f, 0, 0);
+					}
+				}
+			}
+
+			//shadow_cam.setFar(128.f);
+			shadow_cam.setOriginAndLookAt(eye, up, center);
+
+			shadow_cam.setOrigin(0,0,0);
+
+			glh_set_current_modelview(view[j]);
+			glh_set_current_projection(proj[j]);
+
+			LLViewerCamera::updateFrustumPlanes(shadow_cam, FALSE, FALSE, TRUE);
+
+			//shadow_cam.ignoreAgentFrustumPlane(LLCamera::AGENT_PLANE_NEAR);
+			shadow_cam.getAgentPlane(LLCamera::AGENT_PLANE_NEAR).set(shadow_near_clip);
+
+			//translate and scale to from [-1, 1] to [0, 1]
+			glh::matrix4f trans(0.5f, 0.f, 0.f, 0.5f,
+							0.f, 0.5f, 0.f, 0.5f,
+							0.f, 0.f, 0.5f, 0.5f,
+							0.f, 0.f, 0.f, 1.f);
+
+			glh_set_current_modelview(view[j]);
+			glh_set_current_projection(proj[j]);
+
+			for (U32 i = 0; i < 16; i++)
+			{
+				gGLLastModelView[i] = mShadowModelview[j].m[i];
+				gGLLastProjection[i] = mShadowProjection[j].m[i];
+			}
+
+			mShadowModelview[j] = view[j];
+			mShadowProjection[j] = proj[j];
+
+	
+			mSunShadowMatrix[j] = trans*proj[j]*view[j]*inv_view;
+		
+			stop_glerror();
+
+			mShadow[j].bindTarget();
+			mShadow[j].getViewport(gGLViewport);
+			mShadow[j].clear();
+		
+			{
+				static LLCullResult result[4];
+
+				//LLGLEnable enable(GL_DEPTH_CLAMP_NV);
+				renderShadow(view[j], proj[j], shadow_cam, result[j], TRUE);
+			}
+
+			mShadow[j].flush();
+ 
+			if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
+			{
+				LLViewerCamera::updateFrustumPlanes(shadow_cam, FALSE, FALSE, TRUE);
+				mShadowCamera[j+4] = shadow_cam;
+			}
+		}
+	}
+
+	
+	//hack to disable projector shadows 
+	bool gen_shadow = RenderShadowDetail > 1;
+
+	if (gen_shadow)
+	{
+		F32 fade_amt = gFrameIntervalSeconds * llmax(LLViewerCamera::getInstance()->getVelocityStat()->getCurrentPerSec(), 1.f);
+
+		//update shadow targets
+		for (U32 i = 0; i < 2; i++)
+		{ //for each current shadow
+			LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_SHADOW4+i;
+
+			if (mShadowSpotLight[i].notNull() && 
+				(mShadowSpotLight[i] == mTargetShadowSpotLight[0] ||
+				mShadowSpotLight[i] == mTargetShadowSpotLight[1]))
+			{ //keep this spotlight
+				mSpotLightFade[i] = llmin(mSpotLightFade[i]+fade_amt, 1.f);
+			}
+			else
+			{ //fade out this light
+				mSpotLightFade[i] = llmax(mSpotLightFade[i]-fade_amt, 0.f);
+				
+				if (mSpotLightFade[i] == 0.f || mShadowSpotLight[i].isNull())
+				{ //faded out, grab one of the pending spots (whichever one isn't already taken)
+					if (mTargetShadowSpotLight[0] != mShadowSpotLight[(i+1)%2])
+					{
+						mShadowSpotLight[i] = mTargetShadowSpotLight[0];
+					}
+					else
+					{
+						mShadowSpotLight[i] = mTargetShadowSpotLight[1];
+					}
+				}
+			}
+		}
+
+		for (S32 i = 0; i < 2; i++)
+		{
+			glh_set_current_modelview(saved_view);
+			glh_set_current_projection(saved_proj);
+
+			if (mShadowSpotLight[i].isNull())
+			{
+				continue;
+			}
+
+			LLVOVolume* volume = mShadowSpotLight[i]->getVOVolume();
+
+			if (!volume)
+			{
+				mShadowSpotLight[i] = NULL;
+				continue;
+			}
+
+			LLDrawable* drawable = mShadowSpotLight[i];
+
+			LLVector3 params = volume->getSpotLightParams();
+			F32 fov = params.mV[0];
+
+			//get agent->light space matrix (modelview)
+			LLVector3 center = drawable->getPositionAgent();
+			LLQuaternion quat = volume->getRenderRotation();
+
+			//get near clip plane
+			LLVector3 scale = volume->getScale();
+			LLVector3 at_axis(0,0,-scale.mV[2]*0.5f);
+			at_axis *= quat;
+
+			LLVector3 np = center+at_axis;
+			at_axis.normVec();
+
+			//get origin that has given fov for plane np, at_axis, and given scale
+			F32 dist = (scale.mV[1]*0.5f)/tanf(fov*0.5f);
+
+			LLVector3 origin = np - at_axis*dist;
+
+			LLMatrix4 mat(quat, LLVector4(origin, 1.f));
+
+			view[i+4] = glh::matrix4f((F32*) mat.mMatrix);
+
+			view[i+4] = view[i+4].inverse();
+
+			//get perspective matrix
+			F32 near_clip = dist+0.01f;
+			F32 width = scale.mV[VX];
+			F32 height = scale.mV[VY];
+			F32 far_clip = dist+volume->getLightRadius()*1.5f;
+
+			F32 fovy = fov * RAD_TO_DEG;
+			F32 aspect = width/height;
+			
+			proj[i+4] = gl_perspective(fovy, aspect, near_clip, far_clip);
+
+			//translate and scale to from [-1, 1] to [0, 1]
+			glh::matrix4f trans(0.5f, 0.f, 0.f, 0.5f,
+							0.f, 0.5f, 0.f, 0.5f,
+							0.f, 0.f, 0.5f, 0.5f,
+							0.f, 0.f, 0.f, 1.f);
+
+			glh_set_current_modelview(view[i+4]);
+			glh_set_current_projection(proj[i+4]);
+
+			mSunShadowMatrix[i+4] = trans*proj[i+4]*view[i+4]*inv_view;
+			
+			for (U32 j = 0; j < 16; j++)
+			{
+				gGLLastModelView[j] = mShadowModelview[i+4].m[j];
+				gGLLastProjection[j] = mShadowProjection[i+4].m[j];
+			}
+
+			mShadowModelview[i+4] = view[i+4];
+			mShadowProjection[i+4] = proj[i+4];
+
+			LLCamera shadow_cam = camera;
+			shadow_cam.setFar(far_clip);
+			shadow_cam.setOrigin(origin);
+
+			LLViewerCamera::updateFrustumPlanes(shadow_cam, FALSE, FALSE, TRUE);
+
+			stop_glerror();
+
+			mShadow[i+4].bindTarget();
+			mShadow[i+4].getViewport(gGLViewport);
+			mShadow[i+4].clear();
+
+			static LLCullResult result[2];
+
+			LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_SHADOW0+i+4;
+
+			renderShadow(view[i+4], proj[i+4], shadow_cam, result[i], FALSE, FALSE);
+
+			mShadow[i+4].flush();
+ 		}
+	}
+	else
+	{ //no spotlight shadows
+		mShadowSpotLight[0] = mShadowSpotLight[1] = NULL;
+	}
+
+
+	if (!CameraOffset)
+	{
+		glh_set_current_modelview(saved_view);
+		glh_set_current_projection(saved_proj);
+	}
+	else
+	{
+		glh_set_current_modelview(view[1]);
+		glh_set_current_projection(proj[1]);
+		gGL.loadMatrix(view[1].m);
+		gGL.matrixMode(LLRender::MM_PROJECTION);
+		gGL.loadMatrix(proj[1].m);
+		gGL.matrixMode(LLRender::MM_MODELVIEW);
+	}
+	gGL.setColorMask(true, false);
+
+	for (U32 i = 0; i < 16; i++)
+	{
+		gGLLastModelView[i] = last_modelview[i];
+		gGLLastProjection[i] = last_projection[i];
+	}
+
+	popRenderTypeMask();
+
+	if (!skip_avatar_update)
+	{
+		gAgentAvatarp->updateAttachmentVisibility(gAgentCamera.getCameraMode());
+	}
+}
+
+void LLPipeline::renderGroups(LLRenderPass* pass, U32 type, U32 mask, BOOL texture)
+{
+	for (LLCullResult::sg_list_t::iterator i = sCull->beginVisibleGroups(); i != sCull->endVisibleGroups(); ++i)
+	{
+		LLSpatialGroup* group = *i;
+		if (!group->isDead() &&
+			(!sUseOcclusion || !group->isOcclusionState(LLSpatialGroup::OCCLUDED)) &&
+			gPipeline.hasRenderType(group->mSpatialPartition->mDrawableType) &&
+			group->mDrawMap.find(type) != group->mDrawMap.end())
+		{
+			pass->renderGroup(group,type,mask,texture);
+		}
+	}
+}
+
+void LLPipeline::generateImpostor(LLVOAvatar* avatar)
+{
+	LLMemType mt_gi(LLMemType::MTYPE_PIPELINE_GENERATE_IMPOSTOR);
+	LLGLState::checkStates();
+	LLGLState::checkTextureChannels();
+	LLGLState::checkClientArrays();
+
+	static LLCullResult result;
+	result.clear();
+	grabReferences(result);
+	
+	if (!avatar || !avatar->mDrawable)
+	{
+		return;
+	}
+
+	assertInitialized();
+
+	BOOL muted = LLMuteList::getInstance()->isMuted(avatar->getID());
+
+	pushRenderTypeMask();
+	
+	if (muted)
+	{
+		andRenderTypeMask(LLPipeline::RENDER_TYPE_AVATAR, END_RENDER_TYPES);
+	}
+	else
+	{
+		andRenderTypeMask(LLPipeline::RENDER_TYPE_VOLUME,
+						LLPipeline::RENDER_TYPE_AVATAR,
+						LLPipeline::RENDER_TYPE_BUMP,
+						LLPipeline::RENDER_TYPE_GRASS,
+						LLPipeline::RENDER_TYPE_SIMPLE,
+						LLPipeline::RENDER_TYPE_FULLBRIGHT,
+						LLPipeline::RENDER_TYPE_ALPHA, 
+						LLPipeline::RENDER_TYPE_INVISIBLE,
+						LLPipeline::RENDER_TYPE_PASS_SIMPLE,
+						LLPipeline::RENDER_TYPE_PASS_ALPHA,
+						LLPipeline::RENDER_TYPE_PASS_ALPHA_MASK,
+						LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT,
+						LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK,
+						LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_SHINY,
+						LLPipeline::RENDER_TYPE_PASS_SHINY,
+						LLPipeline::RENDER_TYPE_PASS_INVISIBLE,
+						LLPipeline::RENDER_TYPE_PASS_INVISI_SHINY,
+						END_RENDER_TYPES);
+	}
+	
+	S32 occlusion = sUseOcclusion;
+	sUseOcclusion = 0;
+	sReflectionRender = sRenderDeferred ? FALSE : TRUE;
+	sShadowRender = TRUE;
+	sImpostorRender = TRUE;
+
+	LLViewerCamera* viewer_camera = LLViewerCamera::getInstance();
+	markVisible(avatar->mDrawable, *viewer_camera);
+	LLVOAvatar::sUseImpostors = FALSE;
+
+	LLVOAvatar::attachment_map_t::iterator iter;
+	for (iter = avatar->mAttachmentPoints.begin();
+		iter != avatar->mAttachmentPoints.end();
+		++iter)
+	{
+		LLViewerJointAttachment *attachment = iter->second;
+		for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
+			 attachment_iter != attachment->mAttachedObjects.end();
+			 ++attachment_iter)
+		{
+			if (LLViewerObject* attached_object = (*attachment_iter))
+			{
+				markVisible(attached_object->mDrawable->getSpatialBridge(), *viewer_camera);
+			}
+		}
+	}
+
+	stateSort(*LLViewerCamera::getInstance(), result);
+	
+	const LLVector4a* ext = avatar->mDrawable->getSpatialExtents();
+	LLVector3 pos(avatar->getRenderPosition()+avatar->getImpostorOffset());
+
+	LLCamera camera = *viewer_camera;
+
+	camera.lookAt(viewer_camera->getOrigin(), pos, viewer_camera->getUpAxis());
+	
+	LLVector2 tdim;
+
+
+	LLVector4a half_height;
+	half_height.setSub(ext[1], ext[0]);
+	half_height.mul(0.5f);
+
+	LLVector4a left;
+	left.load3(camera.getLeftAxis().mV);
+	left.mul(left);
+	left.normalize3fast();
+
+	LLVector4a up;
+	up.load3(camera.getUpAxis().mV);
+	up.mul(up);
+	up.normalize3fast();
+
+	tdim.mV[0] = fabsf(half_height.dot3(left).getF32());
+	tdim.mV[1] = fabsf(half_height.dot3(up).getF32());
+
+	gGL.matrixMode(LLRender::MM_PROJECTION);
+	gGL.pushMatrix();
+	
+	F32 distance = (pos-camera.getOrigin()).length();
+	F32 fov = atanf(tdim.mV[1]/distance)*2.f*RAD_TO_DEG;
+	F32 aspect = tdim.mV[0]/tdim.mV[1];
+	glh::matrix4f persp = gl_perspective(fov, aspect, 1.f, 256.f);
+	glh_set_current_projection(persp);
+	gGL.loadMatrix(persp.m);
+
+	gGL.matrixMode(LLRender::MM_MODELVIEW);
+	gGL.pushMatrix();
+	glh::matrix4f mat;
+	camera.getOpenGLTransform(mat.m);
+
+	mat = glh::matrix4f((GLfloat*) OGL_TO_CFR_ROTATION) * mat;
+
+	gGL.loadMatrix(mat.m);
+	glh_set_current_modelview(mat);
+
+	glClearColor(0.0f,0.0f,0.0f,0.0f);
+	gGL.setColorMask(true, true);
+	
+	// get the number of pixels per angle
+	F32 pa = gViewerWindow->getWindowHeightRaw() / (RAD_TO_DEG * viewer_camera->getView());
+
+	//get resolution based on angle width and height of impostor (double desired resolution to prevent aliasing)
+	U32 resY = llmin(nhpo2((U32) (fov*pa)), (U32) 512);
+	U32 resX = llmin(nhpo2((U32) (atanf(tdim.mV[0]/distance)*2.f*RAD_TO_DEG*pa)), (U32) 512);
+
+	if (!avatar->mImpostor.isComplete() || resX != avatar->mImpostor.getWidth() ||
+		resY != avatar->mImpostor.getHeight())
+	{
+		avatar->mImpostor.allocate(resX,resY,GL_RGBA,TRUE,FALSE);
+		
+		if (LLPipeline::sRenderDeferred)
+		{
+			addDeferredAttachments(avatar->mImpostor);
+		}
+		
+		gGL.getTexUnit(0)->bind(&avatar->mImpostor);
+		gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
+		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+	}
+
+	avatar->mImpostor.bindTarget();
+
+	if (LLPipeline::sRenderDeferred)
+	{
+		avatar->mImpostor.clear();
+		renderGeomDeferred(camera);
+		renderGeomPostDeferred(camera);
+	}
+	else
+	{
+		LLGLEnable scissor(GL_SCISSOR_TEST);
+		glScissor(0, 0, resX, resY);
+		avatar->mImpostor.clear();
+		renderGeom(camera);
+	}
+	
+	{ //create alpha mask based on depth buffer (grey out if muted)
+		if (LLPipeline::sRenderDeferred)
+		{
+			GLuint buff = GL_COLOR_ATTACHMENT0;
+			glDrawBuffersARB(1, &buff);
+		}
+
+		LLGLDisable blend(GL_BLEND);
+
+		if (muted)
+		{
+			gGL.setColorMask(true, true);
+		}
+		else
+		{
+			gGL.setColorMask(false, true);
+		}
+		
+		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+
+		LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_GREATER);
+
+		gGL.flush();
+
+		gGL.pushMatrix();
+		gGL.loadIdentity();
+		gGL.matrixMode(LLRender::MM_PROJECTION);
+		gGL.pushMatrix();
+		gGL.loadIdentity();
+
+		static const F32 clip_plane = 0.99999f;
+
+		if (LLGLSLShader::sNoFixedFunction)
+		{
+			gUIProgram.bind();
+		}
+
+		gGL.color4ub(64,64,64,255);
+		gGL.begin(LLRender::QUADS);
+		gGL.vertex3f(-1, -1, clip_plane);
+		gGL.vertex3f(1, -1, clip_plane);
+		gGL.vertex3f(1, 1, clip_plane);
+		gGL.vertex3f(-1, 1, clip_plane);
+		gGL.end();
+		gGL.flush();
+
+		if (LLGLSLShader::sNoFixedFunction)
+		{
+			gUIProgram.unbind();
+		}
+
+		gGL.popMatrix();
+		gGL.matrixMode(LLRender::MM_MODELVIEW);
+		gGL.popMatrix();
+	}
+
+	avatar->mImpostor.flush();
+
+	avatar->setImpostorDim(tdim);
+
+	LLVOAvatar::sUseImpostors = TRUE;
+	sUseOcclusion = occlusion;
+	sReflectionRender = FALSE;
+	sImpostorRender = FALSE;
+	sShadowRender = FALSE;
+	popRenderTypeMask();
+
+	gGL.matrixMode(LLRender::MM_PROJECTION);
+	gGL.popMatrix();
+	gGL.matrixMode(LLRender::MM_MODELVIEW);
+	gGL.popMatrix();
+
+	avatar->mNeedsImpostorUpdate = FALSE;
+	avatar->cacheImpostorValues();
+
+	LLVertexBuffer::unbind();
+	LLGLState::checkStates();
+	LLGLState::checkTextureChannels();
+	LLGLState::checkClientArrays();
+}
+
+BOOL LLPipeline::hasRenderBatches(const U32 type) const
+{
+	return sCull->getRenderMapSize(type) > 0;
+}
+
+LLCullResult::drawinfo_list_t::iterator LLPipeline::beginRenderMap(U32 type)
+{
+	return sCull->beginRenderMap(type);
+}
+
+LLCullResult::drawinfo_list_t::iterator LLPipeline::endRenderMap(U32 type)
+{
+	return sCull->endRenderMap(type);
+}
+
+LLCullResult::sg_list_t::iterator LLPipeline::beginAlphaGroups()
+{
+	return sCull->beginAlphaGroups();
+}
+
+LLCullResult::sg_list_t::iterator LLPipeline::endAlphaGroups()
+{
+	return sCull->endAlphaGroups();
+}
+
+BOOL LLPipeline::hasRenderType(const U32 type) const
+{
+    // STORM-365 : LLViewerJointAttachment::setAttachmentVisibility() is setting type to 0 to actually mean "do not render"
+    // We then need to test that value here and return FALSE to prevent attachment to render (in mouselook for instance)
+    // TODO: reintroduce RENDER_TYPE_NONE in LLRenderTypeMask and initialize its mRenderTypeEnabled[RENDER_TYPE_NONE] to FALSE explicitely
+	return (type == 0 ? FALSE : mRenderTypeEnabled[type]);
+}
+
+void LLPipeline::setRenderTypeMask(U32 type, ...)
+{
+	va_list args;
+
+	va_start(args, type);
+	while (type < END_RENDER_TYPES)
+	{
+		mRenderTypeEnabled[type] = TRUE;
+		type = va_arg(args, U32);
+	}
+	va_end(args);
+
+	if (type > END_RENDER_TYPES)
+	{
+		llerrs << "Invalid render type." << llendl;
+	}
+}
+
+BOOL LLPipeline::hasAnyRenderType(U32 type, ...) const
+{
+	va_list args;
+
+	va_start(args, type);
+	while (type < END_RENDER_TYPES)
+	{
+		if (mRenderTypeEnabled[type])
+		{
+			return TRUE;
+		}
+		type = va_arg(args, U32);
+	}
+	va_end(args);
+
+	if (type > END_RENDER_TYPES)
+	{
+		llerrs << "Invalid render type." << llendl;
+	}
+
+	return FALSE;
+}
+
+void LLPipeline::pushRenderTypeMask()
+{
+	std::string cur_mask;
+	cur_mask.assign((const char*) mRenderTypeEnabled, sizeof(mRenderTypeEnabled));
+	mRenderTypeEnableStack.push(cur_mask);
+}
+
+void LLPipeline::popRenderTypeMask()
+{
+	if (mRenderTypeEnableStack.empty())
+	{
+		llerrs << "Depleted render type stack." << llendl;
+	}
+
+	memcpy(mRenderTypeEnabled, mRenderTypeEnableStack.top().data(), sizeof(mRenderTypeEnabled));
+	mRenderTypeEnableStack.pop();
+}
+
+void LLPipeline::andRenderTypeMask(U32 type, ...)
+{
+	va_list args;
+
+	BOOL tmp[NUM_RENDER_TYPES];
+	for (U32 i = 0; i < NUM_RENDER_TYPES; ++i)
+	{
+		tmp[i] = FALSE;
+	}
+
+	va_start(args, type);
+	while (type < END_RENDER_TYPES)
+	{
+		if (mRenderTypeEnabled[type]) 
+		{
+			tmp[type] = TRUE;
+		}
+
+		type = va_arg(args, U32);
+	}
+	va_end(args);
+
+	if (type > END_RENDER_TYPES)
+	{
+		llerrs << "Invalid render type." << llendl;
+	}
+
+	for (U32 i = 0; i < LLPipeline::NUM_RENDER_TYPES; ++i)
+	{
+		mRenderTypeEnabled[i] = tmp[i];
+	}
+
+}
+
+void LLPipeline::clearRenderTypeMask(U32 type, ...)
+{
+	va_list args;
+
+	va_start(args, type);
+	while (type < END_RENDER_TYPES)
+	{
+		mRenderTypeEnabled[type] = FALSE;
+		
+		type = va_arg(args, U32);
+	}
+	va_end(args);
+
+	if (type > END_RENDER_TYPES)
+	{
+		llerrs << "Invalid render type." << llendl;
+	}
+}
+
+void LLPipeline::addDebugBlip(const LLVector3& position, const LLColor4& color)
+{
+	DebugBlip blip(position, color);
+	mDebugBlips.push_back(blip);
+}
+