diff options
| author | Nyx (Neal Orman) <nyx@lindenlab.com> | 2012-01-27 15:11:19 -0500 | 
|---|---|---|
| committer | Nyx (Neal Orman) <nyx@lindenlab.com> | 2012-01-27 15:11:19 -0500 | 
| commit | de468db614a26ba1d8706a3448cf840d938a8d5b (patch) | |
| tree | 09eca006a7ecd148cd80d4fb6216893b5f636a6b | |
| parent | f304b18a74c8d3ae92d2298845e1c9f4f248e11a (diff) | |
| parent | f19a77047d10eca2bff07891375b7859b9e68e99 (diff) | |
Automated merge with https://bitbucket.org/stinson_linden/viewer-development-havokai
| -rw-r--r-- | autobuild.xml | 8 | ||||
| -rw-r--r-- | indra/cmake/LLPhysicsExtensions.cmake | 20 | ||||
| -rw-r--r-- | indra/newview/llappviewer.cpp | 4 | ||||
| -rw-r--r-- | indra/newview/llfloaterpathfindingconsole.cpp | 1242 | ||||
| -rw-r--r-- | indra/newview/llfloaterpathfindingconsole.h | 302 | ||||
| -rw-r--r-- | indra/newview/llnavmeshstation.cpp | 2 | ||||
| -rw-r--r-- | indra/newview/llviewerdisplay.cpp | 3208 | ||||
| -rw-r--r-- | indra/newview/llviewerwindow.cpp | 10572 | ||||
| -rw-r--r-- | indra/newview/pipeline.cpp | 19612 | 
9 files changed, 17488 insertions, 17482 deletions
diff --git a/autobuild.xml b/autobuild.xml index 093a64e6f6..2ff33714b1 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -1110,9 +1110,9 @@              <key>archive</key>              <map>                <key>hash</key> -              <string>fdd82ea2322dcbd630c83d00edc9ada9</string> +              <string>e26b6d955394e079a151ad3b0d7d5c90</string>                <key>url</key> -              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/stinson_llpathinglibrary/rev/248448/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>01742f848b14256bfc5d5a4646a8425d</string> +              <string>0afb3d1e08c56c74db31ae3e78640abc</string>                <key>url</key> -              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/stinson_llpathinglibrary/rev/248448/arch/CYGWIN/installer/llphysicsextensions-0.1-windows-20120126.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 0ab57e48db..73d5dd59cf 100644 --- a/indra/cmake/LLPhysicsExtensions.cmake +++ b/indra/cmake/LLPhysicsExtensions.cmake @@ -1,22 +1,24 @@  # -*- 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) -if (INSTALL_PROPRIETARY AND NOT STANDALONE) -    set(LL_PHYSICS_LIB_NAME "llphysicsextensions") -else (INSTALL_PROPRIETARY AND NOT STANDALONE) -    set(LL_PHYSICS_LIB_NAME "llphysicsextensionsstub") -endif (INSTALL_PROPRIETARY AND NOT STANDALONE) - -find_library(LL_PHYSICS_DEBUG_LIB ${LL_PHYSICS_LIB_NAME} PATHS ${LLPHYSICS_DEBUG_LIBRARY_PATH}) -find_library(LL_PHYSICS_RELEASE_LIB ${LL_PHYSICS_LIB_NAME} 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 +      debug     ${LL_PHYSICS_DEBUG_LIB}      optimized ${LL_PHYSICS_RELEASE_LIB}  ) diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index a455d359bf..85e6cd3d3f 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 772f42860f..fce67c4171 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 c46fead91b..3ae5e25695 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 586ed4715d..87f7e92ddd 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 d2da940260..e8029293fc 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 4f34520924..7f2aefcc2b 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 61ec02c4e2..a929d7a6dd 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 ¢er, 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 ¢er, 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); +} +  | 
